/* ═══════════ 00-polices ═══════════
   Bodoni Moda et Archivo, auto-hébergées (aucun appel à fonts.googleapis.com).
   Ce sont des polices VARIABLES : un seul fichier par famille et par
   sous-ensemble couvre toutes les graisses, d'où les plages font-weight.
   Pas de size-adjust : le calibrage exact demande une mesure réelle, et une
   valeur approximative provoquerait le décalage qu'elle est censée éviter.
   font-display: swap — le texte est lisible immédiatement, jamais masqué. */

@font-face {
  font-family: 'Bodoni Moda';
  font-style: normal;
  font-weight: 400 700;              /* variable : 400 → 700 */
  font-display: swap;
  src: url('/assets/fonts/bodoni-moda-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Bodoni Moda';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url('/assets/fonts/bodoni-moda-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
    U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020,
    U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url('/assets/fonts/archivo-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url('/assets/fonts/archivo-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
    U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020,
    U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* L'axe optique de Bodoni Moda suit la taille du texte automatiquement. */
.ml-habitacle { font-optical-sizing: auto; }


/* ═══ 01-socle ═══ */
/* HABITACLE — BLOC 01 : SOCLE. Scope .ml-habitacle, <div> dans le <main> : aucun
   sélecteur ne remonte au-dessus. Polices : bloc 00. */


/* ===== 1. VARIABLES — source unique, aucun hex ailleurs dans la feuille =====
   Paires mesurées : voir direction.json. Laiton sur papier = 2,0 : INTERDIT.
   Sous 3:1 (4A4E52, D6CFC1, 26231F) : décoratif, jamais une limite ni un état. */

.ml-habitacle {

  /* Matières — jamais en texte */
  --c-nuit:       #0E0D0C;
  --c-surface:    #1A1714; /* 1 matière, 2 rôles : carte sombre et encre sur clair */
  --c-encre-noir: #14120F;
  --c-noyer:      #3A2A1E;
  --c-joint:      #26231F;
  --c-papier:     #F4F0E8;
  --c-blanc:      #FFFFFF;

  /* Encres sur sombre ou noyer — interdites sur clair */
  --c-ivoire:       #F2EDE4;
  --c-gris-chaud:   #C9C1B4;
  --c-chrome-clair: #C9CDD2;
  --c-chrome-sourd: #8A9096;

  /* Encres sur clair — interdites sur sombre */
  --c-encre: #1A1714;
  --c-taupe: #4A423A;

  --c-laiton:       #C8A96A;
  --c-laiton-clair: #E0C489; /* survol, sur sombre */
  --c-laiton-fonce: #7A5A22;

  /* Filets porteurs, puis décoratifs */
  --c-filet-fonctionnel:       var(--c-chrome-sourd);
  --c-filet-clair-fonctionnel: var(--c-taupe);
  --c-filet-decor:       #4A4E52;
  --c-filet-clair-decor: #D6CFC1;

  --c-erreur-clair:  #8C1D18;
  --c-erreur-sombre: #F2B8B0;

  /* Moulure — le seul brillant du site, 1px */
  --moulure-sombre: linear-gradient(90deg,
      rgba(201,205,210,0) 0%, rgba(201,205,210,.55) 18%, rgba(201,205,210,1) 50%,
      rgba(201,205,210,.55) 82%, rgba(201,205,210,0) 100%);
  --moulure-claire: linear-gradient(90deg,
      rgba(122,90,34,0) 0%, rgba(122,90,34,.55) 18%, rgba(122,90,34,1) 50%,
      rgba(122,90,34,.55) 82%, rgba(122,90,34,0) 100%);

  /* Capitonnage — losanges CSS, fond de --c-surface */
  --capitonnage:
      repeating-linear-gradient(30deg,  rgba(242,237,228,.06) 0 1px, transparent 1px 28px),
      repeating-linear-gradient(-30deg, rgba(242,237,228,.06) 0 1px, transparent 1px 28px);

  --grain-cuir: none; /* tuile non livrée ; le jeton existe, pas de var fantôme */

  --ff-display: "Bodoni Moda", Georgia, "Times New Roman", serif;
  --ff-texte:   "Archivo", Arial, "Helvetica Neue", sans-serif;

  /* Typo fluide 360→1440px, part en rem : zoom 200 % opérant */
  --fs-display: clamp(2.25rem,   1.4167rem + 3.70vw, 4.75rem);   /* 36→76 */
  --fs-h2:      clamp(1.75rem,   1.4167rem + 1.48vw, 2.75rem);   /* 28→44 */
  --fs-h3:      clamp(1.25rem,   1.125rem  + 0.56vw, 1.625rem);  /* 20→26 */
  --fs-lead:    clamp(1.0625rem, 1rem      + 0.28vw, 1.25rem);   /* 17→20 */
  --fs-body:    clamp(1rem,      0.9792rem + 0.09vw, 1.0625rem); /* 16→17 */
  --fs-small:   clamp(0.875rem,  0.8542rem + 0.09vw, 0.9375rem); /* 14→15 */
  --fs-label:   clamp(0.75rem,   0.7292rem + 0.09vw, 0.8125rem); /* 12→13 */
  --fs-num:     var(--fs-display);

  --mesure-display: 18ch;
  --mesure-h2:      22ch;
  --mesure-h3:      30ch;
  --mesure-lead:    52ch;
  --mesure-body:    68ch;

  /* Espacement — échelle fermée */
  --sp-1:  4px;
  --sp-2:  8px;
  --sp-3:  12px;
  --sp-4:  16px;
  --sp-5:  24px;
  --sp-6:  32px;
  --sp-7:  48px;
  --sp-8:  64px;
  --sp-9:  96px;
  --sp-10: 128px;

  --pad-section: clamp(3.5rem,  2rem      + 6.67vw, 8rem);   /* 56→128 */
  --gouttiere:   clamp(1.25rem, 0.8333rem + 1.85vw, 2.5rem); /* 20→40 */
  --gap-grille:  clamp(1rem,    0.6667rem + 1.48vw, 2rem);   /* 16→32 */

  --w-container: 1280px;
  --w-large:     1440px;
  --w-form:      640px;
  --filet: 1px;
  --r-0:   0;
  --r-1:   2px;

  /* Règle d'or : tout bloc écrit ses durées en var(--dur-*), sinon le § 6 rate */
  --ease-sortie:   cubic-bezier(.16, 1, .3, 1);
  --ease-standard: cubic-bezier(.2, 0, 0, 1);
  --dur-1: 160ms;
  --dur-2: 260ms;
  --dur-3: 700ms;
  --dur-4: 1200ms;
  --dur-5: 2400ms;
  --dur-6: 9000ms;

  --decalage-ancre: 6rem;
  --touche-min:     48px;
}


/* ===== 2. RESET SCOPÉ ===== */

.ml-habitacle,
.ml-habitacle *,
.ml-habitacle *::before,
.ml-habitacle *::after { box-sizing: border-box; }

.ml-habitacle :where(h1, h2, h3, h4, h5, h6, p, figure, blockquote, dl, dd, ul, ol, fieldset) {
  margin: 0;
}
.ml-habitacle :where(ul, ol)  { padding-inline-start: var(--sp-5); }
.ml-habitacle :where(legend)  { padding: 0; }
.ml-habitacle :where(address) { font-style: normal; }
/* la feuille UA impose min-content */
.ml-habitacle :where(fieldset) { min-inline-size: 0; padding: 0; border: 0; }

.ml-habitacle :where(img, picture) { display: block; max-inline-size: 100%; block-size: auto; }
.ml-habitacle :where(svg)          { max-inline-size: 100%; block-size: auto; }
/* pas de block-size ici : video/iframe retomberaient à 150px de haut */
.ml-habitacle :where(video, iframe, object, embed, canvas) { display: block; max-inline-size: 100%; }

/* Un enfant de flex/grille doit rétrécir : sinon son min-content sort la page */
.ml-habitacle :where(
  a, address, article, aside, blockquote, button, dd, details, div, dl, dt, em,
  fieldset, figcaption, figure, footer, form, h1, h2, h3, h4, h5, h6, header, i,
  input, label, li, nav, ol, output, p, picture, section, select, small, span,
  strong, summary, textarea, time, ul
) { min-inline-size: 0; }

/* La racine est en overflow-x: clip : un débordement y est coupé, pas défilable */
.ml-habitacle :where(h1, h2, h3, h4, h5, h6, p, li, dd, dt, a, label, summary,
                     figcaption, blockquote, address) {
  overflow-wrap: break-word;
  hyphens: none;
}
/* `anywhere` : seule valeur qui réduit AUSSI le min-content d'un titre */
.ml-habitacle :where(h1, h2, h3) { overflow-wrap: anywhere; }


/* ===== 3. BASE ===== */

/* Défaut cuir nuit ; les .mh-s--* repeignent fond ET encre. clip, jamais hidden */
.ml-habitacle {
  overflow-x: clip;
  background-color: var(--c-nuit);
  color: var(--c-ivoire);
  font-family: var(--ff-texte);
  font-size: var(--fs-body);
  font-weight: 400;
  line-height: 1.65;
  font-optical-sizing: auto;
  text-align: start;
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  color-scheme: light;
  accent-color: var(--c-laiton-fonce);
}

/* Décalage porté par les cibles : une ancre n'arrive pas sous la barre fixe */
.ml-habitacle :where([id]) { scroll-margin-block-start: var(--decalage-ancre); }

@media (prefers-reduced-motion: no-preference) {
  .ml-habitacle { scroll-behavior: smooth; }
}

/* Bodoni interdite sous 28px : H1/H2 seulement, H3 en Archivo 600 */
.ml-habitacle :where(h1) {
  font-family: var(--ff-display);
  font-weight: 500;
  font-size: var(--fs-display);
  line-height: 1.04;
  letter-spacing: -0.015em;
  max-inline-size: var(--mesure-display);
  text-wrap: balance;
}
.ml-habitacle :where(h2) {
  font-family: var(--ff-display);
  font-weight: 500;
  font-size: var(--fs-h2);
  line-height: 1.12;
  letter-spacing: -0.010em;
  max-inline-size: var(--mesure-h2);
  text-wrap: balance;
}
.ml-habitacle :where(h3) {
  font-family: var(--ff-texte);
  font-weight: 600;
  font-size: var(--fs-h3);
  line-height: 1.25;
  max-inline-size: var(--mesure-h3);
  text-wrap: pretty;
}
.ml-habitacle :where(h4, h5, h6) {
  font-family: var(--ff-texte);
  font-weight: 600;
  font-size: var(--fs-body);
  line-height: 1.35;
}

.ml-habitacle :where(p)         { text-wrap: pretty; }
.ml-habitacle :where(small)     { font-size: var(--fs-small); line-height: 1.5; }
.ml-habitacle :where(strong, b) { font-weight: 600; }
.ml-habitacle :where(em)        { font-style: italic; }
/* Remixicon <i class="ri-…"> : la feuille UA l'obliquerait */
.ml-habitacle :where(i[class*="ri-"]) { font-style: normal; line-height: 1; }
.ml-habitacle :where(time, output)    { font-variant-numeric: tabular-nums lining-nums; }

/* `inherit` fait reprendre l'encre du fond : aucune paire bannie ne naît ici */
.ml-habitacle :where(a) { color: inherit; }

.ml-habitacle ::selection {
  background-color: var(--c-laiton);
  color: var(--c-encre-noir);
}

/* Paire des contrôles déclarée ici, jamais héritée : sinon un champ en section
   sombre sort à 1,2:1 — texte saisi présent et invisible. */
.ml-habitacle :where(input, select, textarea, button, output, progress, meter) {
  font: inherit;
  max-inline-size: 100%;
}
.ml-habitacle :where(input:not([type="checkbox"], [type="radio"]), select, textarea) {
  background-color: var(--c-blanc);
  color: var(--c-encre);
}
.ml-habitacle :where(input, textarea)::placeholder {
  color: var(--c-taupe);
  opacity: 1; /* Firefox en applique une qui dégrade le ratio */
}
/* Un <button> nu poserait une encre claire sur le gris de l'UA */
.ml-habitacle :where(button) {
  background-color: transparent;
  color: inherit;
  border: 0;
  cursor: pointer;
}
.ml-habitacle :where(textarea) { resize: vertical; }

.ml-habitacle :where(hr) {
  border: 0;
  block-size: var(--filet);
  background-color: var(--c-filet-decor);
  margin-block: var(--sp-6);
}


/* ===== 4. PRIMITIVES DE MISE EN PAGE ===== */

.ml-habitacle .mh-wrap {
  inline-size: 100%;
  max-inline-size: var(--w-container);
  margin-inline: auto;
  padding-inline: var(--gouttiere);
}

/* Grille 4 / 8 / 12 colonnes. minmax(0, 1fr), car 1fr = minmax(auto, 1fr).
   Sans portées déclarées, les enfants empilent au lieu de se tasser. */
.ml-habitacle .mh-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--gap-grille);
}
.ml-habitacle .mh-grid > * { grid-column: 1 / -1; }

@media (min-width: 640px) {
  .ml-habitacle .mh-grid { grid-template-columns: repeat(8, minmax(0, 1fr)); }
}
@media (min-width: 1024px) {
  .ml-habitacle .mh-grid { grid-template-columns: repeat(12, minmax(0, 1fr)); }
}

/* Seule règle de déport de la feuille, réservée au conteneur du champ leurre :
   aucun texte dedans ; ni opacité, ni visibilité, ni clip. */
.ml-habitacle .mh-sr-only,
.ml-habitacle .mh-devis__piege {
  position: absolute;
  inset-inline-start: -9999px;
  inline-size: 1px;
  block-size: 1px;
  overflow: hidden;
  pointer-events: none;
}


/* ===== 5. FOCUS — cuir 0→3px puis ivoire 3→5px : sur tout fond, l'un des deux
   anneaux dépasse 3:1. :is() à (0,3,0) bat un a:focus{outline:none} historique.
   Aucun rayon : il carrerait les boutons radio natifs. ===== */
.ml-habitacle :is(a, button, input, select, textarea, summary, details, label, area,
                  [tabindex], [contenteditable], audio[controls], video[controls],
                  iframe):focus-visible {
  outline: 2px solid var(--c-ivoire);
  outline-offset: 3px;
  box-shadow: 0 0 0 3px var(--c-encre-noir);
}


/* ===== 6. MOUVEMENT RÉDUIT — jetons neutralisés, puis filet à (0,3,0) pour
   toute durée en dur sur une classe. La mise en page ne bouge pas. ===== */
@media (prefers-reduced-motion: reduce) {

  .ml-habitacle {
    --dur-1: 1ms;
    --dur-2: 1ms;
    --dur-3: 1ms;
    --dur-4: 1ms;
    --dur-5: 1ms;
    --dur-6: 1ms;
    scroll-behavior: auto;
  }

  .ml-habitacle.ml-habitacle.ml-habitacle,
  .ml-habitacle.ml-habitacle.ml-habitacle *,
  .ml-habitacle.ml-habitacle.ml-habitacle *::before,
  .ml-habitacle.ml-habitacle.ml-habitacle *::after {
    animation-duration: 1ms;
    animation-delay: 0s;
    animation-iteration-count: 1;
    transition-duration: 1ms;
    transition-delay: 0s;
  }
}


/* ═══ 02-primitives ═══ */
/* BLOC 02 — PRIMITIVES · Habitacle (cuir, chrome, noyer, verre fumé)
   .ml-habitacle est posée sur un <div> du <main> : sélecteurs en (0,2,0),
   aucun ne remonte plus haut, partials du site hors périmètre. Aucune police
   ni PHP ici. Bague de focus : déclarée une seule fois, dans le socle.
   Mobile-first, aucune media query de largeur ; durées par --dur-1, que le
   socle remet à 1 ms en mouvement réduit. */


/* 02.1  CONTEXTES DE MATIÈRE — chaque modificateur PEINT sa matière (fond +
   encre) puis distribue les mêmes 9 jetons. Sans la peinture, une section sans
   bloc propre garde le fond de la racine tout en distribuant l'encre d'une
   autre : c'est ce qui rendait invisible, à 1,09:1, le titre de « Zones
   desservies ». Toutes les paires sont mesurées, aucune inventée. */

/* Cuir nuit #0E0D0C — défaut de la page ET du modificateur. */
.ml-habitacle,
.ml-habitacle .mh-s--cuir {
  --mh-txt: var(--c-ivoire);            /* 16,7:1 */
  --mh-txt-2: var(--c-gris-chaud);      /* 10,9:1 */
  --mh-eyebrow-txt: var(--c-chrome-clair); /* 12,2:1 */
  --mh-lien: var(--c-laiton);           /* 8,6:1 */
  --mh-btn2: var(--c-chrome-sourd);     /* 6,0:1 */
  --mh-moulure: var(--moulure-sombre);
  --mh-card-fond: var(--c-encre);       /* cuir surélevé #1A1714 */
  --mh-card-filet: var(--c-chrome-sourd); /* 5,5:1 — limite ≥ 3:1 */
  --mh-card-capiton: var(--capitonnage);
}

/* Papier ivoire #F4F0E8 — laiton clair et chromes interdits. */
.ml-habitacle .mh-s--papier {
  --mh-txt: var(--c-encre);             /* 15,7:1 */
  --mh-txt-2: var(--c-taupe);           /* 8,7:1 */
  --mh-eyebrow-txt: var(--c-laiton-fonce); /* 5,6:1 */
  --mh-lien: var(--c-laiton-fonce);     /* 5,6:1 */
  --mh-btn2: var(--c-taupe);            /* 8,7:1 */
  --mh-moulure: var(--moulure-claire);
  --mh-card-fond: transparent;          /* garde le papier */
  --mh-card-filet: var(--c-taupe);      /* 8,7:1 */
  --mh-card-capiton: none;              /* réservé au cuir */
}

/* Noyer #3A2A1E — seules trois couleurs y sont mesurées, pas une de plus. */
.ml-habitacle .mh-s--noyer {
  --mh-txt: var(--c-ivoire);            /* 11,8:1 */
  --mh-txt-2: var(--c-gris-chaud);      /* 7,7:1 */
  --mh-eyebrow-txt: var(--c-laiton);    /* 6,1:1 */
  --mh-lien: var(--c-laiton);           /* 6,1:1 */
  --mh-btn2: var(--c-laiton);           /* 6,1:1 */
  --mh-moulure: var(--moulure-sombre);
  --mh-card-fond: var(--c-encre);
  --mh-card-filet: var(--c-chrome-sourd); /* 5,5:1 */
  --mh-card-capiton: var(--capitonnage);
}

.ml-habitacle .mh-s--cuir   { background-color: var(--c-nuit);   color: var(--c-ivoire); }
.ml-habitacle .mh-s--papier { background-color: var(--c-papier); color: var(--c-encre);  }
.ml-habitacle .mh-s--noyer  { background-color: var(--c-noyer);  color: var(--c-ivoire); }


/* 02.2  EYEBROW */

.ml-habitacle .mh-eyebrow {
  display: block;
  margin: 0;
  font-family: var(--ff-texte);
  font-size: var(--fs-label);          /* plancher 12 px */
  font-weight: 600;
  line-height: 1.2;
  letter-spacing: 0.14em;              /* ls positif : capitales seulement */
  text-transform: uppercase;
  color: var(--mh-eyebrow-txt);
  overflow-wrap: break-word;
}

/* Le tiret : la moulure raccourcie, pseudo-élément vide. */
.ml-habitacle .mh-eyebrow::before {
  content: "";
  display: inline-block;
  inline-size: 32px;
  block-size: var(--filet);            /* 1 px, jamais 2 */
  margin-inline-end: var(--sp-3);      /* 12 px */
  vertical-align: 0.34em;
  background-image: var(--mh-moulure);
}

/* Tracé du tiret au chargement (hero) : décoratif, transform seul, une fois. */
@media (prefers-reduced-motion: no-preference) {
  .ml-habitacle .mh-eyebrow--trace::before {
    transform-origin: left center;
    animation: mh-trace var(--dur-3) var(--ease-sortie) both;
  }
}

@keyframes mh-trace { from { transform: scaleX(0); } }


/* 02.3  TITRE DE SECTION ET CHAPÔ */

.ml-habitacle .mh-h2 {
  margin: 0;
  max-inline-size: var(--mesure-h2);
  font-family: var(--ff-display);      /* Bodoni Moda — interdite sous 28 px, ok ici */
  font-size: var(--fs-h2);
  font-weight: 500;
  line-height: 1.12;
  letter-spacing: -0.010em;
  color: var(--mh-txt);
  text-wrap: balance;
  hyphens: none;                       /* césures FR auto : mauvaises */
  overflow-wrap: anywhere;             /* réduit AUSSI la taille min-content */
}

.ml-habitacle .mh-lead {
  margin: 0;
  max-inline-size: var(--mesure-lead);
  font-family: var(--ff-texte);
  font-size: var(--fs-lead);
  line-height: 1.55;
  color: var(--mh-txt-2);
  text-wrap: pretty;
  overflow-wrap: break-word;
}

.ml-habitacle .mh-eyebrow + .mh-h2 { margin-block-start: var(--sp-3); }  /* 12 px */
.ml-habitacle .mh-h2 + .mh-lead    { margin-block-start: var(--sp-4); }  /* 16 px */


/* 02.4  LA MOULURE — filet 1 px, jamais porteur de texte ; le reflet animé
   appartient au hero (bloc 03). */

.ml-habitacle .mh-moulure {
  margin: 0;
  border: 0;                           /* bordure UA du <hr> */
  inline-size: 100%;
  block-size: var(--filet);
  background-image: var(--mh-moulure);
}


/* 02.5  CARTE — limite portée par une bordure mesurée ≥ 3:1, jamais par un
   écart de fond. Zéro ombre. */

.ml-habitacle .mh-card {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);                    /* 12 px */
  min-inline-size: 0;                  /* enfant de grille : jamais de débordement */
  padding: var(--sp-5);                /* 24 px */
  border: var(--filet) solid var(--mh-card-filet);
  border-radius: var(--r-1);           /* 2 px partout */
  background-color: var(--mh-card-fond);
  background-image: var(--mh-card-capiton);
}

/* Arête haute : la moulure recouvre la bordure supérieure, bord à bord. */
.ml-habitacle .mh-card::before {
  content: "";
  position: absolute;
  inset-block-start: -1px;
  inset-inline: -1px;
  block-size: var(--filet);
  background-image: var(--mh-moulure);
  pointer-events: none;
}

.ml-habitacle .mh-card__titre {
  margin: 0;
  max-inline-size: var(--mesure-h3);
  font-family: var(--ff-texte);        /* Archivo : Bodoni interdite sous 28 px */
  font-size: var(--fs-h3);
  font-weight: 600;
  line-height: 1.25;
  color: var(--mh-txt);
  text-wrap: balance;
  overflow-wrap: anywhere;
}

.ml-habitacle .mh-card__texte {
  margin: 0;
  font-family: var(--ff-texte);
  font-size: var(--fs-body);
  line-height: 1.65;
  color: var(--mh-txt-2);
  text-wrap: pretty;
  overflow-wrap: break-word;
}


/* 02.6  BOUTONS — trois paires FIGÉES, jamais héritées : --or laiton plein
   (fond sombre ou noyer UNIQUEMENT), --encre encre pleine (fond clair, où le
   laiton tombe à 1,98:1), --chrome secondaire contextuel. La règle tient au
   NOM de la classe, pas à l'héritage. */

.ml-habitacle .mh-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;                     /* un libellé long revient à la ligne */
  gap: var(--sp-2);                    /* 8 px — écart avec l'icône */
  min-block-size: var(--touche-min);   /* 48 px */
  max-inline-size: 100%;
  padding-block: var(--sp-3);          /* 12 px */
  padding-inline: var(--sp-5);         /* 24 px */
  border: var(--filet) solid transparent;
  border-radius: var(--r-1);
  appearance: none;
  /* Fond et texte toujours déclarés : sans variante, un .mh-btn ne retombe
     jamais sur buttonface/buttontext (mesuré à 1,01:1 en mouture 1). */
  background-color: transparent;
  color: var(--mh-txt);
  font-family: var(--ff-texte);
  font-size: var(--fs-label);
  font-weight: 600;
  line-height: 1.2;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  text-align: center;
  text-decoration: none;
  overflow-wrap: break-word;
  cursor: pointer;
  transition: background-color var(--dur-1) var(--ease-standard),
              border-color var(--dur-1) var(--ease-standard),
              color var(--dur-1) var(--ease-standard);
}

.ml-habitacle .mh-btn--or {
  background-color: var(--c-laiton);
  border-color: var(--c-laiton);
  color: var(--c-encre-noir);          /* 8,3:1 */
}

.ml-habitacle .mh-btn--or:is(:hover, :focus-visible):not([aria-disabled="true"]) {
  background-color: var(--c-ivoire);
  border-color: var(--c-ivoire);
  color: var(--c-encre-noir);          /* 16,0:1 */
}

.ml-habitacle .mh-btn--encre {
  background-color: var(--c-encre);
  border-color: var(--c-encre);
  color: var(--c-papier);              /* 15,7:1 */
}

.ml-habitacle .mh-btn--encre:is(:hover, :focus-visible):not([aria-disabled="true"]) {
  background-color: var(--c-encre-noir);
  border-color: var(--c-encre-noir);
  color: var(--c-papier);              /* 16,5:1 */
}

.ml-habitacle .mh-btn--chrome {
  border-color: var(--mh-btn2);
  color: var(--mh-btn2);
}

.ml-habitacle .mh-btn--chrome:is(:hover, :focus-visible):not([aria-disabled="true"]) {
  border-color: var(--mh-txt);         /* 16,7 · 15,7 · 11,8:1 */
  color: var(--mh-txt);
}

/* Indisponible : aucune couleur délavée, contraste et focus préservés. */
.ml-habitacle .mh-btn[aria-disabled="true"] { cursor: not-allowed; }


/* 02.7  LIENS EN LIGNE — soulignement PERMANENT ; .mh-lien-nu est l'opt-out. */

.ml-habitacle :is(p, li, dd, dt, figcaption, blockquote, address, td, th, summary, .mh-lead, .mh-card__texte)
  a:not(.mh-btn, .mh-cible, .mh-lien-nu),
.ml-habitacle .mh-lien {
  color: var(--mh-lien);
  text-decoration-line: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
  overflow-wrap: break-word;
  transition: color var(--dur-1) var(--ease-standard),
              text-decoration-thickness var(--dur-1) var(--ease-standard);
}

.ml-habitacle :is(p, li, dd, dt, figcaption, blockquote, address, td, th, summary, .mh-lead, .mh-card__texte)
  a:not(.mh-btn, .mh-cible, .mh-lien-nu):is(:hover, :focus-visible),
.ml-habitacle .mh-lien:is(:hover, :focus-visible) {
  color: var(--mh-txt);
  text-decoration-thickness: 2px;
}


/* 02.8  ICÔNES — Remixicon (ri-*), jamais d'emoji : un glyphe bitmap ignore
   `color` et ne respecte aucune paire mesurée. */

.ml-habitacle :is([class^="ri-"], [class*=" ri-"]) {
  display: inline-block;
  flex: 0 0 auto;
  font-family: remixicon;              /* n'hérite jamais de --ff-texte : pas de tofu */
  font-style: normal;                  /* neutralise l'italique UA de <i> */
  font-weight: 400;
  font-size: 1.5em;
  line-height: 1;
  vertical-align: -0.375em;
}


/* 02.9  CIBLES TACTILES — aucun `color` ici : il écrasait celui de .mh-lien au
   repos et produisait un saut de couleur au survol. */

.ml-habitacle .mh-cible {
  display: inline-flex;
  align-items: center;
  flex-wrap: wrap;                     /* la flèche revient à la ligne, elle ne sort pas */
  gap: var(--sp-2);
  min-inline-size: var(--touche-min);  /* 48 px */
  min-block-size: var(--touche-min);
  max-inline-size: 100%;
  padding-block: var(--sp-2);
  overflow-wrap: break-word;
  transition: color var(--dur-1) var(--ease-standard);
}


/* 02.10  COULEURS FORCÉES — on rétablit la limite des boutons, transparente
   au repos ; le texte garde les couleurs système. */

@media (forced-colors: active) {
  .ml-habitacle .mh-btn { border-color: currentColor; }
}

/* ═══ 03-hero ═══ */
/* ===
   03 - HERO . "Vue depuis la banquette"                          cuir nuit
   Mobile : panneau de texte PUIS photo, empiles - aucun texte sur l'image.
   >= 1024px : un seul plan, photo en fond, aplat cuir opaque sous le texte.
   Rien n'est masque au repos ; les 3 animations ne portent que transform,
   sur des elements decoratifs vides (aria-hidden), toutes bornees.
   Ce bloc ne declare aucune variable : il consomme celles du bloc 01.
   === */

/* --- 03.1  La section
   svh et jamais vh : la barre d'URL mobile ferait sauter la hauteur au
   premier defilement. La section peint sa matiere ET son encre : aucune
   paire couleur/fond ne depend d'une classe que le gabarit peut oublier. */
.ml-habitacle .mh-hero {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  align-content: start;
  min-block-size: 640px;                       /* repli si svh inconnu */
  min-block-size: clamp(640px, 100svh, 860px);
  background-color: var(--c-nuit);
  color: var(--c-ivoire);                      /* 16,7:1 */
}

/* --- 03.2  Panneau de texte */
.ml-habitacle .mh-hero__panel {
  position: relative;
  z-index: 2;                                  /* devant la photo */
  padding-block: var(--sp-7) var(--sp-6);      /* 48 / 32 */
}

/* Grain de cuir : tuile de bruit 180x180 en data: URI. Le jeton --grain-cuir
   reste a livrer par le socle ; absent, la couche retombe sur `none`. */
.ml-habitacle .mh-hero__panel::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;                                  /* sous le texte, jamais devant */
  pointer-events: none;
  background-image: var(--grain-cuir, none);
  background-size: 180px 180px;
  opacity: .07;                                /* couche vide : aucun texte concerne */
}

/* .mh-hero__inner porte aussi .mh-wrap (conteneur 1280px + gouttiere). */
.ml-habitacle .mh-hero__inner {
  position: relative;
  z-index: 1;                                  /* au-dessus du grain */
}

/* --- 03.3  Eyebrow
   Le tiret de 32px est le ::before de .mh-eyebrow (bloc 02) : pas de
   display:flex ici, sinon le pseudo-element devient un item de flex et sa
   marge s'ajoute au gap - 24px au lieu des 12px du rythme. */
.ml-habitacle .mh-hero__eyebrow {
  margin: 0;
  color: var(--c-chrome-clair);                /* 12,2:1 */
}

/* --- 03.4  H1 et chapo
   Rythme : eyebrow > titre = 12px, titre > chapo = 16px, chapo > CTA = 32px. */
.ml-habitacle .mh-hero__titre {
  margin-block: var(--sp-3) 0;
  max-inline-size: var(--mesure-display);      /* 18ch */
  font-family: var(--ff-display);
  font-size: var(--fs-display);                /* 36 -> 76px */
  font-weight: 500;
  line-height: 1.04;
  letter-spacing: -.015em;
  color: var(--c-ivoire);                      /* 16,7:1 */
  text-wrap: balance;
  overflow-wrap: anywhere;                     /* seule valeur qui reduit min-content */
}

.ml-habitacle .mh-hero__chapo {
  margin-block: var(--sp-4) 0;
  max-inline-size: var(--mesure-lead);         /* 52ch */
  color: var(--c-gris-chaud);                  /* 10,9:1 */
  text-wrap: pretty;
}

/* --- 03.5  Duo de boutons - le dessin appartient au bloc 02, ici la seule
   disposition : align-items:stretch met les 2 CTA pleine largeur en mobile. */
.ml-habitacle .mh-hero__actions {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: var(--sp-3);                            /* 12px */
  margin-block-start: var(--sp-6);             /* 32px */
}

/* --- 03.6  Reassurance et indicateur
   Aucun chiffre, aucune promesse. L'icone double un libelle, jamais seule. */
.ml-habitacle .mh-hero__reassurance {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-3) var(--sp-5);                /* 12 / 24 */
  margin-block: var(--sp-6) 0;
  padding: 0;
  list-style: none;                            /* le <ul> porte role="list" */
}

.ml-habitacle .mh-hero__item {
  display: flex;
  align-items: center;
  gap: var(--sp-2);                            /* 8px */
  font-size: var(--fs-small);                  /* 14 -> 15px */
  line-height: 1.5;
  color: var(--c-gris-chaud);                  /* 10,9:1 */
}

/* Meme boite pour les deux vehicules d'icone Remixicon : <i class="ri-*">
   ou svg inline. Aucun emoji, ni ici ni dans le gabarit. */
.ml-habitacle :is(.mh-hero__ico, .mh-hero__defilement) {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  line-height: 1;
  color: var(--c-chrome-sourd);                /* 6,0:1 */
}

.ml-habitacle .mh-hero__ico {
  flex: 0 0 auto;
  inline-size: 20px;
  block-size: 20px;
  font-size: 20px;
}

/* Indicateur ri-arrow-down-line, aria-hidden. Animation 3/3, 4 passages. */
.ml-habitacle .mh-hero__defilement {
  inline-size: 24px;
  block-size: 24px;
  margin-block-start: var(--sp-6);             /* 32px */
  font-size: 24px;
  animation: mh-hero-defilement var(--dur-5, 2400ms)
             var(--ease-standard, cubic-bezier(.2, 0, 0, 1)) 4 both;
}

/* --- 03.7  La photo
   Mobile : bord a bord, SOUS le texte, jamais derriere lui. */
.ml-habitacle .mh-hero__media {
  position: relative;
  z-index: 0;
  display: block;
  inline-size: 100%;
  aspect-ratio: 4 / 5;
  max-block-size: 58svh;
  overflow: clip;                              /* jamais hidden : creerait un scroller */
  background-color: var(--c-nuit);             /* aplat d'attente : zero CLS */
}

.ml-habitacle .mh-hero__img {
  inline-size: 100%;
  block-size: 100%;
  object-fit: cover;
  object-position: 68% 50%;                    /* garde la banquette dans le cadre */
  animation: mh-hero-photo var(--dur-4, 1200ms)
             var(--ease-sortie, cubic-bezier(.16, 1, .3, 1)) 1 both;
}

/* Legende : sur un aplat cuir opaque, jamais sur la photo. Alignee sur la
   gouttiere du conteneur, sans unite de viewport. */
.ml-habitacle .mh-hero__legende {
  position: relative;
  z-index: 2;
  margin: 0;
  padding-block: var(--sp-3);
  padding-inline: max(var(--gouttiere),
    calc((100% - var(--w-container)) / 2 + var(--gouttiere)));
  background-color: var(--c-nuit);
  font-size: var(--fs-small);
  color: var(--c-gris-chaud);                  /* 10,9:1 */
}

/* --- 03.8  Moulure et reflet - signature du site : un filet de 1px, le seul
   element brillant de la page. */
.ml-habitacle .mh-hero__moulure {
  position: absolute;
  inset-inline: 0;
  inset-block-end: 0;
  z-index: 3;
  block-size: 1px;
  overflow: clip;                              /* borne le reflet */
  pointer-events: none;
  background-image: var(--moulure-sombre);
}

/* Le reflet herite du degrade de la moulure : aucun second degrade, aucune
   couleur nouvelle. Element vide, aria-hidden. Animation 2/3, bornee a
   3 passages - aucun mouvement automatique ne boucle (WCAG 2.2.2). */
.ml-habitacle .mh-hero__reflet {
  position: absolute;
  inset-block: 0;
  inset-inline-start: 0;
  inline-size: 40%;
  background-image: inherit;
  transform: translateX(-30%);
  animation: mh-hero-reflet var(--dur-6, 9000ms) ease-in-out 3 both;
}

/* --- 03.9  >= 1024px : un seul plan
   Rupture en px : en em, le hero basculerait a une largeur differente de
   celle ou la grille passe a 12 colonnes. */
@media (min-width: 1024px) {

  .ml-habitacle .mh-hero {
    grid-template-rows: minmax(0, 1fr) auto;   /* panneau, puis legende */
  }

  /* Verre fume : aplat cuir 100 % opaque sur toute la moitie gauche - donc
     sous la totalite de la colonne de texte - puis plumeau de 120px qui fond
     dans la photo. Il ne sert jamais de support de lisibilite : le texte
     s'arrete a 48px du premier pixel non opaque. */
  .ml-habitacle .mh-hero__panel {
    display: grid;
    align-content: center;
    padding-block: var(--sp-8);                /* 64px */
    background-image: linear-gradient(90deg,
      var(--c-nuit) 0%, var(--c-nuit) 50%, transparent calc(50% + 120px));
  }

  /* Le grain s'arrete net a la limite de l'aplat : la photo reste brute. */
  .ml-habitacle .mh-hero__panel::before { inset-inline-end: 50%; }

  .ml-habitacle .mh-hero__inner {
    display: grid;
    grid-template-columns: repeat(12, minmax(0, 1fr));
    column-gap: var(--gap-grille);
  }

  .ml-habitacle .mh-hero__contenu {
    grid-column: 1 / 7;                        /* 6 colonnes sur 12 */
    padding-inline-end: var(--sp-7);           /* 48px avant la limite de l'aplat */
  }

  .ml-habitacle .mh-hero__media {
    position: absolute;
    inset: 0;
    aspect-ratio: auto;
    max-block-size: none;
  }

  .ml-habitacle .mh-hero__img { object-position: 55% 50%; }

  .ml-habitacle .mh-hero__actions {
    flex-direction: row;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--sp-4);                          /* 16px */
  }

  .ml-habitacle .mh-hero__defilement { margin-block-start: var(--sp-7); }
}

/* --- 03.10  Ecran couche et court : on rend la hauteur au contenu. */
@media (orientation: landscape) and (max-height: 600px) {
  .ml-habitacle .mh-hero { min-block-size: 560px; }
}

/* Le plafond ne vaut que pour la photo en flux (< 1024px) : au-dela elle est
   en position absolue et remplit le cadre. */
@media (max-width: 1023.98px) and (orientation: landscape) and (max-height: 600px) {
  .ml-habitacle .mh-hero__media { max-block-size: 44svh; }
}

/* --- 03.11  Les trois animations */
@keyframes mh-hero-photo {
  from { transform: scale(1.06); }
  to   { transform: scale(1); }
}

@keyframes mh-hero-reflet {
  from { transform: translateX(-30%); }
  to   { transform: translateX(130%); }
}

@keyframes mh-hero-defilement {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(6px); }
}

/* Mouvement reduit : l'etat au repos est deja l'etat final (photo a l'echelle
   1, indicateur a 0). La mise en page ne change pas d'un pixel. */
@media (prefers-reduced-motion: reduce) {
  .ml-habitacle .mh-hero__img,
  .ml-habitacle .mh-hero__reflet,
  .ml-habitacle .mh-hero__defilement { animation: none; }
}


/* ═══ 04-occasions ═══ */
/* =========================================================================
   BLOC 04 — OCCASIONS  ·  « Les 5 occasions »
   Portee scopee : .ml-habitacle .mh-xxx (0,2,0). Rien au-dessus du div racine.
   Le socle fournit les jetons, .mh-wrap et la grille 4/8/12 ; les primitives
   fournissent .mh-eyebrow (et son tiret de 32 px), .mh-h2, .mh-lead, .mh-card
   (surface, capitonnage, bordure, moulure d'arete haute), .mh-card__titre,
   .mh-card__texte, .mh-lien, .mh-cible, les icones ri-* et la bague de focus.
   On ne pose ici que le rythme vertical, les portees de grille et deux etats.
   Fond et encre : poses par .mh-s--cuir, qui peint sa matiere
   (background-color + color) — le modificateur ne distribue plus seulement
   des jetons. Aucune couleur de texte n'est donc reecrite ici.
   ========================================================================= */

/* 04.1  LA SECTION — coupe franche, aucun filet de joint : le hero se ferme
   deja sur sa moulure chrome pleine largeur. */
.ml-habitacle .mh-occasions {
  padding-block: var(--pad-section); /* 56 -> 128 px */
}

/* 04.2  EN-TETE — le lockup (tiret, eyebrow, H2, chapo) vient des primitives.
   Il ne reste que le dernier intervalle du rythme : chapo -> contenu. */
.ml-habitacle .mh-occasions__entete {
  margin-block: 0 var(--sp-6); /* 32 px */
}

/* 04.3  LA GRILLE — le <ul> porte aussi .mh-grid : on reutilise les 4/8/12
   pistes du socle. Sur 12 pistes, une colonne du rythme a trois vaut 4 pistes,
   une colonne et demie en vaut 6. Mobile : une carte par rangee, c'est deja le
   defaut de .mh-grid > *. Seul l'ecart est repris (24 px puis 32 px). */
.ml-habitacle .mh-occasions__grille {
  gap: var(--sp-5); /* 24 px */
  margin: 0;
  padding: 0;
  list-style: none; /* le gabarit pose role="list" : sinon Safari retire le role */
}

/* 04.4  LA CARTE — tout le visuel vient de .mh-card. Ici : la colonne qui
   permet d'aligner les liens en pied, l'ancrage du lien etendu (§ 04.5) et la
   transition de bordure qui sert l'etat du § 04.6. Les durees passent par
   var(--dur-1) : le socle les ramene a 1 ms en mouvement reduit, ce bloc n'a
   donc aucune media query a redeclarer. */
.ml-habitacle .mh-occasions__item {
  position: relative;
  display: flex;
  flex-direction: column;
  transition: border-color var(--dur-1) var(--ease-standard);
}

/* Icone de tete, 24 px (taille et alignement poses par les regles ri-*) :
   chrome sourd a 5,30:1 sur la surface de carte, au-dessus des 3:1 exiges pour
   un element non textuel. Elle est toujours doublee du titre. */
.ml-habitacle .mh-occasions__ico {
  color: var(--c-chrome-sourd);
  transition: color var(--dur-1) var(--ease-standard);
}

/* 04.5  LE LIEN — couleur laiton, soulignement 1 px et cible de 48 px viennent
   de .mh-lien et .mh-cible (le bloc 02 ne pose plus `color: inherit` sur
   .mh-cible : la rustine locale qui vivait ici n'a plus lieu d'etre). Ne reste
   que l'alignement en pied, pour que les liens de cinq cartes de hauteurs
   differentes tombent sur la meme ligne. */
.ml-habitacle .mh-occasions__lien {
  margin-block-start: auto;
}

/* Carte entierement cliquable : le lien s'etend sur toute la surface.
   Pseudo-element vide (content: "" — jamais de texte genere), donc aucun
   second lien dans l'arbre d'accessibilite ni piege au clavier. Effet de bord
   utile : survoler la carte revient a survoler le lien. */
.ml-habitacle .mh-occasions__lien::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: var(--r-1); /* 2 px */
}

/* La fleche : 20 px, contre 24 px pour l'icone de tete. */
.ml-habitacle .mh-occasions__fleche {
  font-size: 1.25em;
}

/* 04.6  PORTEES DE GRILLE
   640-1023 px : 8 pistes, deux cartes par rangee (4+4).
   >= 1024 px  : 12 pistes, 4+4+4 en rangee 1, puis 6+6 — 1,5 colonne chacune.
   La regle « orpheline » donne la rangee entiere a la derniere carte quand
   leur nombre est impair ; elle est reprise a >= 1024 px, sinon
   `grid-column: 1 / -1` resterait actif et la 5e carte s'etalerait. */
@media (min-width: 640px) {
  .ml-habitacle .mh-occasions__item {
    grid-column: span 4;
  }

  .ml-habitacle .mh-occasions__item:last-child:nth-child(odd) {
    grid-column: 1 / -1;
  }
}

@media (min-width: 1024px) {
  .ml-habitacle .mh-occasions__grille {
    gap: var(--sp-6); /* 32 px */
  }

  .ml-habitacle .mh-occasions__item:nth-child(n + 4),
  .ml-habitacle .mh-occasions__item:last-child:nth-child(odd) {
    grid-column: span 6; /* 1,5 colonne */
  }
}

/* 04.7  ETATS DE LA CARTE — survol et focus clavier
   :focus-within fait reagir la carte quand son lien recoit le focus. La bague
   bicolore des primitives reste seule maitresse de l'indicateur : on ne touche
   qu'a la bordure et a la couleur de l'icone. Trois signaux simultanes, jamais
   la couleur seule : la limite se polit (#6A6F74 -> #C9CDD2, 10,71:1), l'icone
   passe au laiton (7,61:1) et le soulignement du lien double d'epaisseur —
   ce dernier produit par .mh-lien, puisque survoler la carte revient a
   survoler le lien etendu. Seules des couleurs changent : zero deplacement. */
.ml-habitacle .mh-occasions__item:is(:hover, :focus-within) {
  border-color: var(--c-chrome-clair);
}

.ml-habitacle .mh-occasions__item:is(:hover, :focus-within) .mh-occasions__ico {
  color: var(--c-laiton);
}


/* ═══ 05-flotte ═══ */
/* === BLOC 05 — LA FLOTTE (.mh-flotte) · papier ivoire =======================
   Aucune variable, aucun repli dans var(), aucun hexadécimal : une seule table
   de couleurs pour la feuille. Sur papier le laiton clair est interdit
   (1,98:1) : accents en laiton foncé (5,58:1), CTA en encre pleine
   (.mh-btn--encre, primitive non restylée ici).
   Aucun prix, aucun mouvement, aucun masquage.
   ========================================================================= */


/* 05.1 · Section — coupe franche avec le bloc sombre : aucune bordure, aucun
   dégradé de jonction. La matière est peinte par .mh-s--papier ; on la
   redouble ici, une paire couleur/fond ne devant pas dépendre d'une classe que
   le gabarit peut oublier. Mêmes valeurs : aucune divergence possible. */
.ml-habitacle .mh-flotte {
  padding-block: var(--pad-section);
  background-color: var(--c-papier);
  color: var(--c-encre);                 /* 15,70:1 */
}


/* 05.2 · Lockup — uniquement le rythme § 8.4 : eyebrow → titre 12px, titre →
   chapô 16px, chapô → contenu 32px. Les couleurs viennent des jetons de
   .mh-s--papier ; les recoloriser ici les figerait. */
.ml-habitacle .mh-flotte__lockup  { margin-block-end: var(--sp-6); }
.ml-habitacle .mh-flotte .mh-h2   { margin-block-start: var(--sp-3); }
.ml-habitacle .mh-flotte .mh-lead { margin-block-start: var(--sp-4); }


/* 05.3 · Grille — 1 colonne, 2 dès 640px, 3 dès 1024px. minmax(0, 1fr) et non
   1fr : une piste `1fr` a pour minimum le min-content de ses items, ce qui
   suffit à faire déborder la page sur un mot long. */
.ml-habitacle .mh-flotte__grille {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--sp-5);                      /* 24px entre fiches */
}


/* 05.4 · La fiche — pas .mh-card : cette primitive porte la surface cuir,
   illégale sur papier. Sa limite est une bordure fonctionnelle mesurée à
   3,94:1, jamais un écart de fond. Pas d'overflow : la bague de focus des
   cibles internes doit pouvoir déborder sans être rognée. */
.ml-habitacle .mh-flotte__fiche {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  align-content: start;
  min-inline-size: 0;                    /* item borné, comme la piste */
  border: var(--filet) solid var(--c-filet-clair-fonctionnel);
  border-radius: var(--r-1);             /* 2px, partout */
  background-color: var(--c-papier);
}

/* La moulure ferme l'arête haute : son dégradé vient du jeton de matière, on
   ne pose que la portée en grille (utile sur la fiche large). */
.ml-habitacle .mh-flotte .mh-moulure { grid-column: 1 / -1; }


/* 05.5 · Média — photo à fleur des bords intérieurs : le padding est porté par
   le corps, jamais par la fiche. Le 3:2 est tenu par le CSS ; width/height
   restent obligatoires dans le HTML (CLS = 0,000). Aucun rayon. */
.ml-habitacle .mh-flotte__media { margin: 0; }

.ml-habitacle .mh-flotte__photo {
  display: block;
  inline-size: 100%;
  block-size: auto;
  aspect-ratio: 3 / 2;
  object-fit: cover;
}

/* Légende § 12.3 : « Nos véhicules — [lieu], [mois année] » si le cliché est
   réel, sinon « Photographie d'illustration ». */
.ml-habitacle .mh-flotte__legende {
  padding-inline: var(--sp-5);           /* aligné sur le corps */
  padding-block-start: var(--sp-2);
  font-size: var(--fs-small);
  line-height: 1.5;
  color: var(--c-taupe);                 /* 8,67:1 */
}


/* 05.6 · Corps — ordre visuel = ordre du DOM : modèle → capacité →
   équipements → CTA. Aucun `order`, à aucune largeur. */
.ml-habitacle .mh-flotte__corps { padding: var(--sp-4) var(--sp-5) var(--sp-5); }

/* Nom du modèle : Archivo 600, pas de Didone — interdite sous 28px, et --fs-h3
   plafonne à 26px ; famille forcée pour ne pas dépendre d'un socle qui
   mettrait les h3 en display. `anywhere` et non `break-word` : seule cette
   valeur réduit AUSSI la taille min-content, donc la seule qui empêche un nom
   venu de la base d'élargir sa piste. */
.ml-habitacle .mh-flotte__modele {
  margin: 0;
  font-family: var(--ff-texte);
  font-size: var(--fs-h3);
  font-weight: 600;
  line-height: 1.25;
  color: var(--c-encre);                 /* 15,70:1 */
  text-wrap: pretty;
  overflow-wrap: anywhere;
}

/* Capacité passagers, chiffres tabulaires § 7.5. flex-wrap obligatoire : à
   320px, icône + libellé long ne doivent jamais élargir la fiche. */
.ml-habitacle .mh-flotte__capacite {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-2);
  margin: var(--sp-3) 0 0;
  font-weight: 500;
  color: var(--c-encre);                 /* 15,70:1 */
  font-variant-numeric: tabular-nums lining-nums;
}

.ml-habitacle .mh-flotte__nombre { font-weight: 600; }

/* Icône Remixicon : couvre <i class="ri-…"> (font-size) et <svg> (inline-size
   / block-size). font-style: normal neutralise l'italique qu'un :where(em, i)
   du socle appliquerait aux glyphes. L'icône n'est jamais seule porteuse
   d'information : elle accompagne « passagers ». */
.ml-habitacle .mh-flotte__ico {
  flex: 0 0 auto;
  inline-size: 24px;
  block-size: 24px;
  font-size: 24px;
  font-style: normal;
  line-height: 1;
  color: var(--c-laiton-fonce);          /* 5,58:1 */
}


/* 05.7 · Équipements, puces carrées de 4px. Le gabarit pose role="list" sur le
   <ul> : Safari retire le rôle dès que list-style vaut none. */
.ml-habitacle .mh-flotte__equip {
  display: grid;
  gap: var(--sp-2);
  margin: var(--sp-4) 0 0;
  padding: 0;
  list-style: none;
  color: var(--c-taupe);                 /* 8,67:1 */
}

.ml-habitacle .mh-flotte__equip > li {
  display: grid;
  grid-template-columns: 4px minmax(0, 1fr);
  column-gap: var(--sp-3);
  align-items: start;
}

/* Puce décorative : `content` est une chaîne VIDE, aucun caractère généré. Le
   décalage est un calage optique, pas un espacement : (1,65em − 4px) / 2
   centre la puce sur la première ligne. */
.ml-habitacle .mh-flotte__equip > li::before {
  content: "";
  inline-size: 4px;
  block-size: 4px;
  margin-block-start: calc((1.65em - 4px) / 2);
  background-color: var(--c-laiton-fonce);
}


/* 05.8 · Actions — le bouton n'est pas restylé ici, on ne pose que son
   emplacement : en grille, il s'étire seul sur toute la largeur en mobile. */
.ml-habitacle .mh-flotte__actions { display: grid; margin-block-start: var(--sp-5); }

/* CTA de fin de section : rythme contenu → CTA = 48px. */
.ml-habitacle .mh-flotte__pied {
  display: grid;
  justify-items: start;
  margin-block-start: var(--sp-7);
}

/* Césure : aucune règle locale — le bloc 09 pose `break-word` sur la prose et
   `anywhere` sur les titres ; une règle de section ne ferait que les
   rétrograder. */


/* 05.9 · ≥ 640px — deux colonnes. Une dernière fiche isolée prend la rangée et
   passe à l'horizontale : média 40% à gauche, corps à droite. L'ordre du DOM
   ne change pas. */
@media (min-width: 640px) {
  .ml-habitacle .mh-flotte__grille { grid-template-columns: repeat(2, minmax(0, 1fr)); }

  .ml-habitacle .mh-flotte__fiche:nth-child(odd):last-child {
    grid-column: 1 / -1;
    grid-template-columns: 40% minmax(0, 1fr);
  }

  .ml-habitacle .mh-flotte__actions { justify-items: start; }
}


/* 05.10 · ≥ 1024px — trois colonnes : la rangée est pleine, la fiche isolée
   redevient verticale. Les deux déclarations de 640px sont annulées, sinon
   elle resterait pleine largeur. */
@media (min-width: 1024px) {
  .ml-habitacle .mh-flotte__grille {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: var(--sp-6);                    /* 32px */
  }

  .ml-habitacle .mh-flotte__fiche:nth-child(odd):last-child {
    grid-column: auto;
    grid-template-columns: minmax(0, 1fr);
  }
}


/* 05.11 · Couleurs forcées : les fonds d'auteur sont neutralisés — la fiche
   perdrait sa limite, la puce disparaîtrait. On repeint avec les couleurs
   système, seules honorées dans ce mode. Aucun forced-color-adjust. */
@media (forced-colors: active) {
  .ml-habitacle .mh-flotte__fiche { border: var(--filet) solid currentColor; }
  .ml-habitacle .mh-flotte__equip > li::before { background-color: CanvasText; }
}

/* ═══ 06-etapes-zones ═══ */
/* 06 — COMMENT ÇA MARCHE (cuir) + ZONES DESSERVIES (papier)
   Scope .ml-habitacle, mobile d'abord, une seule rupture : 1024px. Chaque
   section peint son FOND et son ENCRE, sans dépendre d'un modificateur que
   le gabarit peut oublier. Aucun jeton ni repli hexa : le socle fait foi. */

/* --- Les deux sections --- */

.ml-habitacle .mh-etapes,
.ml-habitacle .mh-zones {
  padding-block: var(--pad-section);
}

/* Coupe franche entre matières : aucun filet de jonction. */
.ml-habitacle .mh-etapes {
  background-color: var(--c-nuit);
  color: var(--c-ivoire); /* 16,7:1 */
}

.ml-habitacle .mh-zones {
  background-color: var(--c-papier);
  color: var(--c-encre); /* 15,7:1 */
}

/* --- Lockups : eyebrow → titre 12, titre → chapô 16, chapô → contenu 32 --- */

.ml-habitacle :is(.mh-etapes__lockup, .mh-zones__lockup) {
  margin-block-end: var(--sp-6);
}

.ml-habitacle :is(.mh-etapes, .mh-zones) .mh-eyebrow { margin-block-end: var(--sp-3); }
.ml-habitacle :is(.mh-etapes, .mh-zones) .mh-h2      { margin-block-end: var(--sp-4); }
.ml-habitacle :is(.mh-etapes, .mh-zones) .mh-lead    { margin-block-end: 0; }

/* Les six paires du lockup, déclarées et jamais héritées. */
.ml-habitacle .mh-etapes .mh-eyebrow { color: var(--c-chrome-clair); } /* 12,2:1 */
.ml-habitacle .mh-etapes .mh-h2      { color: var(--c-ivoire); }
.ml-habitacle .mh-etapes .mh-lead    { color: var(--c-gris-chaud); }   /* 10,9:1 */
.ml-habitacle .mh-zones  .mh-eyebrow { color: var(--c-laiton-fonce); } /* 5,6:1 — laiton clair interdit sur papier (1,98:1) */
.ml-habitacle .mh-zones  .mh-h2      { color: var(--c-encre); }
.ml-habitacle .mh-zones  .mh-lead    { color: var(--c-taupe); }        /* 8,7:1 */

/* --- La frise des 3 étapes : le rail EST la bordure de l'étape, donc
   continu de l'une à l'autre — l'écart de 24px est un padding, pas un gap. */

.ml-habitacle .mh-etapes__frise {
  position: relative; /* support du rail ≥1024px */
  margin: 0;
  padding: 0;
  list-style: none; /* → role="list" */
}

.ml-habitacle .mh-etape {
  position: relative;
  min-inline-size: 0;
  padding-inline-start: var(--sp-6); /* dégagement du rail */
  padding-block-end: var(--sp-5); /* 24px */
  border-inline-start: 1px solid var(--c-chrome-sourd); /* 6,0:1 */
}

.ml-habitacle .mh-etape:last-child { padding-block-end: 0; }

/* Pastille : carré de 12px, jamais un rond, vide → <span aria-hidden>. Le
   numéro est en line-height 1 : sa boîte vaut --fs-display, d'où le centrage
   sur sa demi-hauteur, sans valeur magique. */
.ml-habitacle .mh-etape__pastille {
  position: absolute;
  inline-size: var(--sp-3);
  block-size: var(--sp-3);
  inset-block-start: calc(var(--fs-display) / 2 - var(--sp-3) / 2);
  inset-inline-start: calc(-0.5px - var(--sp-3) / 2); /* centrée sur le filet */
  background-color: var(--c-laiton); /* 8,6:1 sur cuir */
  border-radius: var(--r-1);
}

.ml-habitacle .mh-etape__ligne {
  display: flex;
  flex-wrap: wrap; /* à 320px, rien ne déborde */
  align-items: baseline;
  column-gap: var(--sp-4);
  row-gap: 0;
}

/* Le numéro est du VRAI texte (« 01 »), jamais un compteur CSS. */
.ml-habitacle .mh-etape__num {
  flex: 0 0 auto;
  font-family: var(--ff-titre, var(--ff-display));
  font-weight: 400;
  font-size: var(--fs-display); /* 36 → 76px : plancher Bodoni tenu */
  line-height: 1;
  letter-spacing: -0.015em;
  font-variant-numeric: tabular-nums lining-nums;
  color: var(--c-laiton);
}

.ml-habitacle .mh-etape__titre {
  min-inline-size: 0;
  margin: 0;
  font-family: var(--ff-texte);
  font-weight: 600;
  font-size: var(--fs-h3);
  line-height: 1.25;
  color: var(--c-ivoire);
  text-wrap: balance;
  overflow-wrap: anywhere; /* réduit aussi la taille min-content */
}

.ml-habitacle .mh-etape__texte {
  margin-block: var(--sp-3) 0;
  max-inline-size: var(--mesure-body);
  color: var(--c-gris-chaud); /* 10,9:1 */
}

.ml-habitacle .mh-etapes__cta { margin-block-start: var(--sp-7); }

/* --- Zones desservies : listes rédigées à la main, aucun repli ni « voir
   plus », tout est dans le DOM. Sans page dédiée, la commune reste du texte. */

.ml-habitacle .mh-zones__bloc + .mh-zones__bloc {
  margin-block-start: var(--sp-7);
}

.ml-habitacle .mh-zones__sous-titre {
  margin: 0 0 var(--sp-4);
  font-family: var(--ff-texte);
  font-weight: 600;
  font-size: var(--fs-h3);
  line-height: 1.25;
  color: var(--c-encre);
  text-wrap: balance;
  overflow-wrap: anywhere;
}

/* 2 colonnes, 4 ≥1024px. Pistes bornées : un nom long n'élargit rien. */
.ml-habitacle .mh-zones__liste {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  column-gap: var(--sp-5);
  row-gap: var(--sp-2); /* 8px entre deux cibles */
  margin: 0;
  padding: 0;
  list-style: none; /* → role="list" */
}

.ml-habitacle .mh-zones__item {
  display: flex;
  align-items: center;
  min-inline-size: 0;
  min-block-size: 2.75rem; /* 44px : cible d'un lien de liste */
  color: var(--c-encre); /* une commune non liée reste lisible */
  overflow-wrap: anywhere; /* noms composés longs à 320px */
}

.ml-habitacle .mh-zones__liste--departements .mh-zones__item {
  font-weight: 600;
  font-variant-numeric: tabular-nums lining-nums; /* « Val-d'Oise (95) » */
}

/* Visé par l'élément, pas par une classe : le gabarit n'écrit pas
   .mh-zones__lien. (0,3,1) égale le lien de prose des primitives, que
   l'ordre de la feuille tranche ici. */
.ml-habitacle .mh-zones .mh-zones__item a {
  display: inline-flex;
  align-items: center;
  min-block-size: 2.75rem;
  color: var(--c-laiton-fonce); /* 5,6:1 sur papier */
  text-decoration-line: underline; /* permanent */
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
  transition: color var(--dur-1), text-decoration-thickness var(--dur-1);
}

/* Jamais la couleur seule : le trait passe à 2px. Pas de laiton plus
   soutenu sur papier — l'état actif est donc l'encre. */
.ml-habitacle .mh-zones .mh-zones__item a:is(:hover, :focus-visible) {
  color: var(--c-encre);
  text-decoration-thickness: 2px;
}

.ml-habitacle :is(.mh-zones__note, .mh-zones__legende) {
  margin-block: var(--sp-4) 0;
  max-inline-size: var(--mesure-body);
  font-size: var(--fs-small);
  line-height: 1.5;
  color: var(--c-taupe); /* 8,7:1 */
}

/* --- Carte statique : seul défilement horizontal du bloc ; sa bague de
   focus vient du socle (règle [tabindex]), rien à redéclarer. --- */

.ml-habitacle .mh-zones__carte { margin: var(--sp-7) 0 0; }
.ml-habitacle .mh-zones__legende { margin-block-start: var(--sp-3); }

.ml-habitacle .mh-zones__cadre {
  overflow-x: auto;
  overscroll-behavior-x: contain; /* le défilement ne gagne pas la page */
  max-inline-size: 100%;
  border: 1px solid var(--c-filet-clair-fonctionnel); /* 3,9:1 */
  border-radius: var(--r-1);
  background-color: var(--c-papier);
}

/* Image ou schéma SVG. 320px = seule largeur fixe autorisée : plancher de
   lisibilité que le cadre rend défilable, la page ne déborde pas. Le ratio
   vient des width/height du gabarit. */
.ml-habitacle .mh-zones__cadre > :is(img, svg) {
  display: block;
  inline-size: 100%;
  block-size: auto;
  min-inline-size: 320px;
}

/* --- ≥1024px --- */

@media (min-width: 1024px) {

  .ml-habitacle .mh-etapes__frise {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    column-gap: var(--sp-6);
  }

  /* Rail horizontal AU-DESSUS des étapes : il ne traverse aucun glyphe. */
  .ml-habitacle .mh-etapes__frise::before {
    content: "";
    position: absolute;
    inset-inline: 0;
    inset-block-start: calc(var(--sp-3) / 2);
    block-size: 1px;
    background-color: var(--c-chrome-sourd); /* 6,0:1 */
    pointer-events: none;
  }

  .ml-habitacle .mh-etape {
    padding-inline-start: 0;
    padding-block: var(--sp-6) 0; /* le contenu passe sous le rail */
    border-inline-start: 0;
  }

  .ml-habitacle .mh-etape__pastille {
    inset-block-start: 0; /* la pastille s'assoit sur le rail */
    inset-inline-start: 0;
  }

  .ml-habitacle .mh-etape__ligne { column-gap: var(--sp-5); }

  .ml-habitacle .mh-zones__liste {
    grid-template-columns: repeat(4, minmax(0, 1fr));
    column-gap: var(--sp-6);
  }
}


/* ═══ 07-faq-devis ═══ */
/* BLOC 07 — FAQ (cuir nuit) + DEVIS (noyer). Portee .ml-habitacle : aucun
   selecteur ne remonte au-dessus du <div>. Ni police, ni PHP, ni montant ; rien
   n'est replie ici (<details> ouverts), seul `transform` est anime, chaque
   section declare fond ET couleur. Pas de repli dans les var() : le socle est
   la source unique et ramene --dur-* a 1ms en mouvement reduit. */

.ml-habitacle :is(.mh-faq, .mh-devis) { padding-block: var(--pad-section); }

.ml-habitacle .mh-faq { background-color: var(--c-nuit); color: var(--c-ivoire); } /* 16,7:1 */
.ml-habitacle .mh-faq__inner { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--sp-5); }
.ml-habitacle .mh-faq__liste { margin: var(--sp-6) 0 0; padding: 0; list-style: none; }

@media (min-width: 1024px) {
  .ml-habitacle .mh-faq__inner {
    grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
    column-gap: var(--sp-7);
    align-items: start;
  }
  .ml-habitacle .mh-faq__liste { margin-block-start: 0; }
}

/* Filet entre 2 cibles = information : 6,0:1, pas le chrome mat. */
.ml-habitacle .mh-faq__ligne { border-block-start: 1px solid var(--c-chrome-sourd); }
.ml-habitacle .mh-faq__ligne:last-child { border-block-end: 1px solid var(--c-chrome-sourd); }

/* La mise en flex sort le <summary> de `list-item` : plus de triangle, rien masque. */
.ml-habitacle .mh-faq__q {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-4);
  min-block-size: 56px;
  padding-block: var(--sp-4);
  list-style: none;
  cursor: pointer;
  border-radius: var(--r-1);
}

/* `anywhere`, pas `break-word` : seul `anywhere` reduit la taille min-content. */
.ml-habitacle :is(.mh-faq__titre, .mh-devis__resume-titre, .mh-devis__legende) { overflow-wrap: anywhere; }
.ml-habitacle :is(.mh-faq__titre, .mh-devis__resume-titre) {
  margin: 0;
  font-family: var(--ff-texte);
  font-size: var(--fs-h3);
  font-weight: 600;
  line-height: 1.25;
  color: var(--c-ivoire); /* 16,7:1 sur cuir · 15,3:1 dans le resume */
}
.ml-habitacle .mh-faq__titre { text-wrap: balance; }

.ml-habitacle .mh-faq__chevron {
  flex: 0 0 auto;
  inline-size: 24px;
  block-size: 24px;
  font-size: 24px;
  line-height: 1;
  font-style: normal;
  color: var(--c-chrome-clair); /* 12,2:1 */
  transition: transform var(--dur-1) var(--ease-standard),
              color var(--dur-1) var(--ease-standard);
}

/* Ouvert : le « + » devient croix — l'etat est une FORME, pas une couleur. */
.ml-habitacle .mh-faq__item[open] .mh-faq__chevron { transform: rotate(45deg); }

.ml-habitacle .mh-faq__q:is(:hover, :focus-visible) .mh-faq__titre {
  text-decoration-line: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
}
.ml-habitacle .mh-faq__q:is(:hover, :focus-visible) .mh-faq__chevron { color: var(--c-laiton); } /* 8,6:1 */

.ml-habitacle .mh-faq__r { padding-block-end: var(--sp-5); }
.ml-habitacle .mh-faq__texte { margin: 0; color: var(--c-gris-chaud); text-wrap: pretty; } /* 10,9:1 */
.ml-habitacle .mh-faq__texte + .mh-faq__texte { margin-block-start: var(--sp-4); }

/* ══ (b) DEVIS — noyer ══ Trois encres seulement y sont mesurees : ivoire
   11,8:1, gris chaud 7,7:1, laiton 6,1:1 ; le chrome sourd n'y sert qu'en filet. */

.ml-habitacle .mh-devis { background-color: var(--c-noyer); color: var(--c-ivoire); border-block-start: 1px solid var(--c-joint); }

.ml-habitacle .mh-devis__mention {
  margin: var(--sp-4) 0 0;
  max-inline-size: 52ch;
  padding-inline-start: var(--sp-4);
  border-inline-start: 1px solid var(--c-chrome-sourd);
  color: var(--c-ivoire);
  text-wrap: pretty;
}

/* Texte serveur : ces rangees doivent revenir a la ligne. */
.ml-habitacle :is(.mh-devis__rappel, .mh-devis__erreur,
                  .mh-devis__resume-titre, .mh-devis__confirmation) { flex-wrap: wrap; }

.ml-habitacle .mh-devis__rappel { display: flex; align-items: center; gap: var(--sp-3); margin-block-start: var(--sp-5); }
.ml-habitacle .mh-devis__rappel-lien {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  min-block-size: var(--touche-min);
  font-weight: 600;
}

.ml-habitacle :is(.mh-devis__tel-num, .mh-tel__num) { font-variant-numeric: tabular-nums lining-nums; white-space: nowrap; }

.ml-habitacle .mh-devis__ico {
  flex: 0 0 auto;
  inline-size: 24px;
  block-size: 24px;
  font-size: 24px;
  line-height: 1;
  font-style: normal;
  color: var(--c-laiton);
}

/* .mh-devis__panneau prend ici son contrat : pas de panneau clair. */
.ml-habitacle :is(.mh-devis__form, .mh-devis__panneau) { margin-block-start: var(--sp-6); max-inline-size: 640px; }

/* <fieldset> : largeur mini min-content = debordement mobile n.1. */
.ml-habitacle .mh-devis__groupe { min-inline-size: 0; margin: 0; padding: 0; border: 0; }
.ml-habitacle .mh-devis__groupe + .mh-devis__groupe { margin-block-start: var(--sp-7); }
.ml-habitacle .mh-devis__legende { display: block; margin: 0 0 var(--sp-5); padding: 0; color: var(--c-laiton); }

.ml-habitacle .mh-devis__grille { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--sp-5); }
.ml-habitacle .mh-devis__bloc--large { grid-column: 1 / -1; }

@media (min-width: 640px) {
  .ml-habitacle :is(.mh-devis__form, .mh-devis__panneau) { max-inline-size: 880px; }
  .ml-habitacle .mh-devis__grille { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .ml-habitacle .mh-devis__envoyer { inline-size: auto; }
}

.ml-habitacle .mh-devis__label { display: block; margin-block-end: var(--sp-2); color: var(--c-ivoire); }
.ml-habitacle :is(.mh-devis__label, .mh-devis__legende) {
  font-size: var(--fs-label);
  font-weight: 600;
  line-height: 1.2;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

.ml-habitacle .mh-devis__requis {
  margin-inline-start: var(--sp-2);
  font-weight: 400;
  letter-spacing: 0.08em;
  text-transform: none;
  color: var(--c-gris-chaud);
}

.ml-habitacle .mh-devis__aide { margin: var(--sp-2) 0 0; color: var(--c-gris-chaud); }

.ml-habitacle :is(.mh-faq__texte, .mh-devis__mention, .mh-devis__rappel-lien,
                  .mh-devis__resume-liste, .mh-devis__confirmation) { font-size: var(--fs-body); line-height: 1.65; }
.ml-habitacle :is(.mh-devis__aide, .mh-devis__note,
                  .mh-devis__case-label, .mh-devis__erreur) { font-size: var(--fs-small); line-height: 1.5; }
.ml-habitacle :is(.mh-faq__texte, .mh-devis__aide, .mh-devis__note,
                  .mh-devis__erreur) { max-inline-size: var(--mesure-body); }

/* Paire fond/texte TOUJOURS declaree : sans fond, 1,17:1. Ici 15,3:1. */
.ml-habitacle .mh-devis__champ {
  display: block;
  inline-size: 100%;
  min-inline-size: 0;
  min-block-size: 52px;
  padding: var(--sp-3) var(--sp-4);
  background-color: var(--c-encre);
  color: var(--c-ivoire);
  border: 1px solid var(--c-chrome-sourd);
  border-radius: var(--r-1);
  font-family: var(--ff-texte);
  font-size: var(--fs-body); /* >= 16px : pas de zoom iOS */
  line-height: 1.5;
  color-scheme: dark;
  transition: border-color var(--dur-1) var(--ease-standard);
}

.ml-habitacle .mh-devis__champ::placeholder { color: var(--c-gris-chaud); opacity: 1; } /* 10,0:1 */
.ml-habitacle .mh-devis__champ--zone { resize: vertical; }

/* Focus : filet a 11,2:1 + la bague du socle. 1px : aucun decalage. */
.ml-habitacle .mh-devis__champ:focus-visible,
.ml-habitacle .mh-devis__champ[aria-invalid="true"]:focus-visible { border-color: var(--c-chrome-clair); }

/* Erreur = 3 signaux : filet 2px, message, icone. 10,4:1. */
.ml-habitacle .mh-devis__champ[aria-invalid="true"] { border-width: 2px; border-color: var(--c-erreur-sombre); }
.ml-habitacle .mh-devis__erreur {
  display: flex;
  align-items: flex-start;
  gap: var(--sp-2);
  margin: var(--sp-2) 0 0;
  font-weight: 600;
  color: var(--c-erreur-sombre);
}
.ml-habitacle .mh-devis__erreur .mh-devis__ico { inline-size: 20px; block-size: 20px; font-size: 20px; color: var(--c-erreur-sombre); }

/* Resume (role="alert") : fond a 1,30:1, c'est le filet 8,0:1 qui borne. */
.ml-habitacle .mh-devis__resume {
  margin-block-end: var(--sp-6);
  padding: var(--sp-5);
  background-color: var(--c-encre);
  color: var(--c-ivoire);
  border: 1px solid var(--c-erreur-sombre);
  border-radius: var(--r-1);
}
.ml-habitacle .mh-devis__resume-titre { display: flex; align-items: center; gap: var(--sp-2); }
.ml-habitacle .mh-devis__resume-liste { margin: var(--sp-3) 0 0; padding-inline-start: var(--sp-5); color: var(--c-gris-chaud); } /* 10,0:1 */
.ml-habitacle .mh-devis__resume-lien { display: inline-block; min-block-size: 44px; padding-block: var(--sp-2); }

.ml-habitacle .mh-devis__confirmation {
  display: flex;
  align-items: flex-start;
  gap: var(--sp-3);
  margin-block-end: var(--sp-6);
  padding: var(--sp-5);
  border: 1px solid var(--c-chrome-sourd);
  border-radius: var(--r-1);
  color: var(--c-ivoire);
}

.ml-habitacle .mh-devis__consentement { display: flex; align-items: flex-start; gap: var(--sp-3); }

/* 24px = minimum WCAG 2.2 (2.5.8) ; cible de repli = le libelle, 48px. */
.ml-habitacle .mh-devis__case {
  flex: 0 0 auto;
  inline-size: 24px;
  block-size: 24px;
  margin-block-start: var(--sp-2);
  accent-color: var(--c-laiton);
  color-scheme: dark;
}
.ml-habitacle .mh-devis__case-label {
  min-block-size: var(--touche-min);
  padding-block: var(--sp-2);
  color: var(--c-gris-chaud);
  cursor: pointer;
}

/* Jamais de lien signale par la couleur seule ; bloc 02 ignore <label>. */
.ml-habitacle :is(.mh-devis__lien, .mh-devis__rappel-lien, .mh-devis__resume-lien) {
  text-decoration-line: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
}
.ml-habitacle :is(.mh-devis__lien, .mh-devis__rappel-lien,
                  .mh-devis__resume-lien):is(:hover, :focus-visible) { text-decoration-thickness: 2px; }
/* RECETTE 02/08 : ce lien mesurait 15px de haut (cible tactile ratee) alors
   qu'il est seul dans son <p>. Meme traitement que .mh-devis__resume-lien. */
.ml-habitacle .mh-devis__lien {
  color: var(--c-laiton);
  display: inline-flex;
  align-items: center;
  min-block-size: 44px;
}
.ml-habitacle .mh-devis__lien:is(:hover, :focus-visible) { color: var(--c-ivoire); }

/* Dans de la prose : la regle de liens du bloc 02 pese (0,3,1) et les passerait
   en laiton — l'alerte du resume disparaitrait. D'ou (0,4,0) puis (0,5,0). */
.ml-habitacle .mh-devis .mh-devis__rappel .mh-devis__rappel-lien { color: var(--c-ivoire); } /* 11,8:1 */
.ml-habitacle .mh-devis .mh-devis__resume .mh-devis__resume-lien { color: var(--c-erreur-sombre); } /* 10,4:1 */
.ml-habitacle .mh-devis .mh-devis__resume .mh-devis__resume-lien:is(:hover, :focus-visible) { color: var(--c-ivoire); } /* 15,3:1 */

/* Turnstile : hauteur reservee (CLS nul) et 3 niveaux bornes — le tiers pose un <div> a 300px. */
.ml-habitacle .mh-devis__turnstile { min-block-size: 65px; min-inline-size: 0; max-inline-size: 100%; }
.ml-habitacle .mh-devis__turnstile > *,
.ml-habitacle .mh-devis__turnstile iframe { max-inline-size: 100%; }

/* Piege a robots — UNIQUE deport hors ecran de la feuille. CONTRAT : conteneur
   sans texte/label/placeholder, input tabindex="-1" + aria-label, PAS d'aria-hidden. */
.ml-habitacle .mh-devis__piege {
  position: absolute;
  inset-inline-start: -9999px;
  inline-size: 1px;
  block-size: 1px;
  overflow: hidden;
  pointer-events: none;
}

.ml-habitacle .mh-devis__envoyer { margin-block-start: var(--sp-7); inline-size: 100%; }
.ml-habitacle .mh-devis__note { margin: var(--sp-4) 0 0; color: var(--c-gris-chaud); text-wrap: pretty; }


/* ═══ 09-responsive-print ═══ */
/* BLOC 09 - RESPONSIVE, PREFERENCES, IMPRESSION, GARDE-FOU. Dernier bloc, donc
   zero !important. .ml-habitacle est un <div> du <main> ; header et footer du
   site sont hors perimetre. .mh-eyebrow, .mh-lead, .mh-h2 et .mh-card__* sont
   des p, h2 et h3 : les selecteurs d'element les couvrent deja. */

/* == 9.1 ZERO DEBORDEMENT == */

/* clip et jamais hidden : hidden creerait un conteneur de defilement. */
.ml-habitacle {
  max-inline-size: 100%;
  overflow-x: clip;
}

.ml-habitacle :where(img, picture, svg, canvas) {
  max-inline-size: 100%;
  block-size: auto;
}
.ml-habitacle :where(video, iframe, object, embed) { max-inline-size: 100%; }

/* A 320 px la largeur utile vaut 280 px ; fieldset reste en min-content. */
.ml-habitacle :where(input, select, textarea, button, output, progress, meter) {
  max-inline-size: 100%;
}
.ml-habitacle :where(input:not([type="checkbox"], [type="radio"]), select, textarea) {
  inline-size: 100%;
}
.ml-habitacle :where(fieldset) { min-inline-size: 0; }
.ml-habitacle :where(textarea) { resize: vertical; }

/* min-width:auto fait exploser la piste d'un item flex/grid. Liste elargie a
   a, span, i, em, strong, small, figcaption, legend, output, h5, h6. */
.ml-habitacle :where(
  a, abbr, address, article, aside, blockquote, button, cite, div, dl, dd, dt,
  em, fieldset, figcaption, figure, footer, form, h1, h2, h3, h4, h5, h6,
  header, i, input, label, legend, li, main, nav, ol, output, p, picture, pre,
  section, select, small, span, strong, table, textarea, time, ul
) { min-inline-size: 0; }

/* Ancre portee par la cible : pas de scroll-padding sur <html>. 64 + 8 px. */
.ml-habitacle :where([id]) { scroll-margin-block-start: 4.5rem; }

/* == 9.2 CESURE == */
.ml-habitacle :where(
  h1, h2, h3, h4, h5, h6, p, li, dd, dt, figcaption, caption, blockquote,
  label, legend, td, th, address, a, span, small, time
) {
  overflow-wrap: break-word;
  hyphens: none;
}

/* anywhere : seule valeur qui reduit AUSSI la taille min-content. */
.ml-habitacle :where(h1, h2, h3) { overflow-wrap: anywhere; }

/* == 9.3 RUPTURE == */
@media (min-width: 1024px) {
  .ml-habitacle :where([id]) { scroll-margin-block-start: 5rem; }
}

/* == 9.4 ENCOCHES == */
.ml-habitacle .mh-wrap {
  padding-inline-start: max(var(--gouttiere), env(safe-area-inset-left, 0px));
  padding-inline-end: max(var(--gouttiere), env(safe-area-inset-right, 0px));
}

@media (orientation: landscape) and (max-height: 600px) {
  .ml-habitacle :where(.mh-hero__media) { max-block-size: 44svh; }
}

/* == 9.5 MOUVEMENT REDUIT == */
@media (prefers-reduced-motion: reduce) {
  .ml-habitacle.ml-habitacle {
    --dur-1: 1ms; --dur-2: 1ms; --dur-3: 1ms;
    --dur-4: 1ms; --dur-5: 1ms; --dur-6: 1ms;
  }
  .ml-habitacle.ml-habitacle *,
  .ml-habitacle.ml-habitacle *::before,
  .ml-habitacle.ml-habitacle *::after {
    animation-duration: 1ms;
    animation-delay: 0ms;
    animation-iteration-count: 1;
    transition-duration: 1ms;
    transition-delay: 0ms;
    scroll-behavior: auto;
  }
}

/* == 9.6 CONTRASTE RENFORCE == aucun hex nouveau. Moulure : chrome clair
   12,2:1 cuir, 8,6:1 noyer ; laiton fonce 5,6:1 papier. Limites : chrome
   sourd 6,0:1 cuir, encre 15,7:1 papier. */
@media (prefers-contrast: more) {
  .ml-habitacle :is(.mh-s--cuir, .mh-s--noyer, .mh-hero) .mh-moulure {
    background-image: none;
    background-color: var(--c-chrome-clair);
  }
  .ml-habitacle .mh-s--papier .mh-moulure {
    background-image: none;
    background-color: var(--c-laiton-fonce);
  }
  .ml-habitacle :is(.mh-s--cuir, .mh-hero) :is(.mh-card, .mh-flotte__fiche) {
    border-color: var(--c-chrome-sourd);
  }
  .ml-habitacle .mh-s--noyer :is(.mh-card, .mh-devis__panneau) {
    border-color: var(--c-chrome-clair);
  }
  .ml-habitacle .mh-s--papier :is(.mh-card, .mh-flotte__fiche) {
    border-color: var(--c-encre);
  }
  .ml-habitacle :is(.mh-card, .mh-flotte__fiche, .mh-hero__panel) {
    background-image: none;
  }
  .ml-habitacle :is(p, li, dd, dt, figcaption) a {
    text-decoration-thickness: 2px;
  }
  .ml-habitacle :is(a, button, input, select, textarea, [tabindex]):focus-visible {
    outline-width: 3px;
  }
}

/* == 9.7 COULEURS FORCEES == moulure en bordure (seule propriete qui accepte
   currentColor) ; bouton sur 3 etats, :hover pesant (0,2,1). */
.ml-habitacle { color-scheme: dark; }

@media (forced-colors: active) {
  .ml-habitacle :is(.mh-moulure, hr) {
    background-image: none;
    background-color: transparent;
    block-size: 0;
    border-block-start: 1px solid currentColor;
  }
  .ml-habitacle :is(.mh-card, .mh-flotte__fiche, .mh-devis__panneau) {
    border: 1px solid currentColor;
  }
  .ml-habitacle .mh-btn,
  .ml-habitacle .mh-btn:hover,
  .ml-habitacle .mh-btn:focus-visible {
    border: 1px solid currentColor;
  }
  .ml-habitacle :is(a, button, input, select, textarea, [tabindex]):focus-visible {
    outline-width: 3px;
  }
  .ml-habitacle :where(input, select, textarea) {
    border: 1px solid currentColor;
  }
}

/* == 9.8 IMPRESSION == rien n'est masque, aucun hex nouveau. */
@page { margin: 12mm; }

@media print {

  .ml-habitacle {
    background-color: var(--c-blanc);
    background-image: none;
    color: var(--c-encre);
    color-scheme: light;
  }

  /* __resume et __confirmation inclus : sinon encre sur encre, 1,00:1. */
  .ml-habitacle :is(.mh-s--cuir, .mh-s--papier, .mh-s--noyer, .mh-hero,
                    .mh-hero__panel, .mh-flotte, .mh-flotte__fiche, .mh-etape,
                    .mh-devis, .mh-card, .mh-devis__panneau, .mh-devis__resume,
                    .mh-devis__confirmation) {
    background: none;
    border-color: var(--c-taupe);
  }

  /* (0,3,0) grace a .mh-devis__ico : egale la regle du devis, gagne par
     l'ordre. i couvre les Remixicon : sinon chevron FAQ a 1,60:1. */
  .ml-habitacle.ml-habitacle :is(h1, h2, h3, h4, h5, h6, p, li, dd, dt, i,
    figcaption, caption, label, legend, blockquote, address, time, small,
    strong, em, span, a, td, th, .mh-devis__ico) {
    color: var(--c-encre);
    background-color: transparent;
  }

  /* Champs (0,2,1) > .mh-devis__champ (0,2,0) : sinon 1,17:1. */
  .ml-habitacle.ml-habitacle :is(input, select, textarea, option) {
    background: none;
    border: 1px solid var(--c-taupe);
    color: var(--c-encre);
    -webkit-text-fill-color: var(--c-encre);
  }
  .ml-habitacle.ml-habitacle :is(input, textarea)::placeholder {
    color: var(--c-taupe);
    opacity: 1;
  }

  .ml-habitacle .mh-moulure {
    background: none;
    block-size: 0;
    border-block-start: 1px solid var(--c-taupe);
  }

  .ml-habitacle .mh-btn {
    background: none;
    color: var(--c-encre);
    border: 1px solid var(--c-encre);
  }

  .ml-habitacle :is(p, li, dd) a {
    text-decoration-line: underline;
    text-decoration-thickness: 1px;
  }
  .ml-habitacle a[href^="http"]::after,
  .ml-habitacle a[href^="mailto:"]::after {
    content: " (" attr(href) ")";
    font-size: 0.85em;
    overflow-wrap: anywhere;
  }

  .ml-habitacle :is(h1, h2, h3, .mh-eyebrow) { break-after: avoid-page; }
  .ml-habitacle :is(.mh-card, .mh-flotte__fiche, .mh-etape, .mh-faq__ligne,
                    figure, tr) { break-inside: avoid; }
  .ml-habitacle :is(p, li) { orphans: 3; widows: 3; }
  .ml-habitacle .mh-devis { break-before: page; }

  .ml-habitacle :is(.mh-hero__media img, .mh-flotte__photo) {
    max-block-size: 80mm;
    object-fit: contain;
  }
}

/* == 9.9 GARDE-FOU FINAL == (0,4,0) par doublement de la racine. Ni display
   ni color. Classes reelles du gabarit. Exclu : le piege et :empty. */
.ml-habitacle.ml-habitacle :is(
  h1, h2, h3, h4, h5, h6, p, li, dd, dt, figcaption, caption, label, legend,
  blockquote, address, time, small, strong, em, span, a, td, th, option,
  .mh-card, .mh-hero, .mh-hero__panel, .mh-occasions, .mh-flotte,
  .mh-flotte__fiche, .mh-etapes, .mh-etape, .mh-zones, .mh-faq, .mh-faq__ligne,
  .mh-devis, .mh-devis__panneau, .mh-wrap, .mh-grid
):not(.mh-devis__piege, .mh-devis__piege *, .mh-hp, .mh-hp *, .mh-moulure, :empty) {
  opacity: 1;
  visibility: visible;
  clip-path: none;
  text-indent: 0;
  max-block-size: none;
  -webkit-text-fill-color: currentColor;
}


/* ═══ correctifs de recette ═══ */
/* [neutralisé le 20260731 — texte de compte rendu collé dans la feuille : en CSS ce prélude avalait la règle suivante] Fichier écrit : `C:\Users\HP\AppData\Local\Temp\claude\C--\78552721-554f-407e-b883-8dcc0d2b3bdd\scratchpad\11-recette.css` — à concaténer après le bloc 09. Total assemblé : **79 654 o = 77,8 Ko** (budget 80 Ko tenu). */


/* ═══════════════════════════════════════════════════════════════════════════
   HABITACLE — BLOC 11 : CORRECTIFS DE RECETTE
   Se concatène en DERNIÈRE position, après le bloc 09. Une règle = un constat.
   Aucune déclaration prioritaire, aucun hex nouveau, aucune géométrie neuve :
   chaque règle gagne par sa position finale, à spécificité égale ou supérieure,
   indiquée en commentaire.
   ═══════════════════════════════════════════════════════════════════════════ */

/* 11.1  BLOQUANT texte-masqué — le fond du panneau hero n'est pas décoratif.
   Le § 9.6 pose `background-image: none` sur .mh-hero__panel. Or à partir de
   1024px ce fond EST l'aplat cuir 100 % opaque posé sous toute la colonne de
   texte (§ 03.9). Supprimé, le H1 ivoire #F2EDE4, l'eyebrow #C9CDD2 et le
   chapô #C9C1B4 tombent directement sur la photo extérieure (ciel, reflets
   chromés) : contraste non mesurable, aucune des 16 paires ne s'applique plus,
   et cela dans le mode que l'utilisateur active pour mieux voir. On rétablit
   l'aplat du § 03.9 à l'identique. (0,2,0), source postérieure. */
@media (prefers-contrast: more) and (min-width: 1024px) {
  .ml-habitacle .mh-hero__panel {
    background-image: linear-gradient(90deg,
      var(--c-nuit) 0%, var(--c-nuit) 50%, transparent calc(50% + 120px));
  }
}

/* 11.2  Même constat, la VRAIE cible du § 9.6 : le grain de cuir, qui vit sur
   le pseudo-élément et ne porte, lui, aucune information. (0,2,1). */
@media (prefers-contrast: more) {
  .ml-habitacle .mh-hero__panel::before { background-image: none; }
}

/* 11.3  BLOQUANT contraste — l'encre d'impression doit gagner sur les liens.
   La règle d'encre du § 9.8 pèse (0,3,0) : elle perd contre la prose du § 02.7
   (0,3,1) et contre les liens du devis (0,4,0) puis (0,5,0) à l'état actif.
   Sur papier blanc : laiton #C8A96A = 2,25:1, #F2B8B0 = 1,71:1, et le souligné
   du téléphone reste en #F2EDE4 = 1,17:1. (0,4,1) et (0,5,1) battent les trois. */
@media print {
  .ml-habitacle.ml-habitacle.ml-habitacle.ml-habitacle a,
  .ml-habitacle.ml-habitacle.ml-habitacle.ml-habitacle a:is(:hover, :focus-visible, :visited) {
    color: var(--c-encre);                    /* 17,85:1 sur blanc */
    -webkit-text-fill-color: var(--c-encre);
    text-decoration-color: currentColor;
  }
}

/* 11.4  BLOQUANT cohérence — la FAQ est écrite pour un lockup que le gabarit
   ne livre pas. .mh-faq__inner passe en 5fr/7fr à 1024px avec QUATRE enfants
   directs (eyebrow, H2, chapô, liste) et aucune portée de grille : le
   placement automatique met le H2 à droite de son propre eyebrow et remonte
   l'accordéon à hauteur du chapô. Placement explicite, (0,2,0). */
@media (min-width: 1024px) {
  .ml-habitacle .mh-faq__inner > :not(.mh-faq__liste) { grid-column: 1; }
  .ml-habitacle .mh-faq__liste { grid-column: 2; grid-row: 1; }
}

/* 11.5  Même constat, second effet, à toutes les largeurs : en grille les
   marges de fratrie du bloc 02 ne fusionnent pas et le row-gap de 24px s'y
   ajoute — eyebrow→H2 = 36px au lieu de 12, H2→chapô = 40 au lieu de 16,
   chapô→liste = 56 au lieu de 32. Le rythme du § 8.4 vient des marges. */
.ml-habitacle .mh-faq__inner { row-gap: 0; }

/* 11.6  BLOQUANT cohérence — zéro pixel entre la frise des 3 étapes et le
   paragraphe de liaison. Ce <p class="mh-lead"> a pour frère précédent un
   </ol> : la règle .mh-h2 + .mh-lead du bloc 02 ne l'atteint pas, le reset
   met p { margin: 0 }, .mh-etapes__frise déclare margin: 0 et
   .mh-etape:last-child padding-block-end: 0. 48px = le rythme contenu → CTA
   déjà appliqué par .mh-etapes__cta juste en dessous. (0,3,0). */
.ml-habitacle .mh-etapes__frise + .mh-lead { margin-block-start: var(--sp-7); }


/* [neutralisé le 20260731 — texte de compte rendu collé dans la feuille : en CSS ce prélude avalait la règle suivante] --- */

/* [neutralisé le 20260731 — texte de compte rendu collé dans la feuille : en CSS ce prélude avalait la règle suivante] ## */

/* ═══════════ 99-bouclier ═══════════
   Le site charge encore ses feuilles historiques (l'en-tête et le pied en ont
   besoin). Certaines posent des règles !important sur des sélecteurs d'éléments
   nus (h2, section, a, body, input…) : en CSS, !important l'emporte sur la
   spécificité, donc une règle propre mais sans !important perd, aussi précise
   soit-elle. C'est ce mécanisme qui a fait échouer les tentatives précédentes.

   Ce bloc re-affirme, et RIEN DE PLUS, les propriétés réellement menacées,
   mesurées sur les 9 feuilles historiques (analyse hors @media print).
   Règle de sûreté : jamais de !important sur display, visibility, opacity,
   position, height, max-height, clip-path — aucune de ces règles ne peut donc
   masquer du texte, même par accident. */

/* — Couleur et fond. Menacés par tk-a11y (body{color:#000}) et les feuilles
     de rustines. Les modificateurs de matière doivent gagner. — */
.ml-habitacle                { background-color: var(--c-nuit) !important; color: var(--c-ivoire) !important; }
.ml-habitacle .mh-s--cuir    { background-color: var(--c-nuit) !important;   color: var(--c-ivoire) !important; }
.ml-habitacle .mh-s--papier  { background-color: var(--c-papier) !important; color: var(--c-encre) !important; }
.ml-habitacle .mh-s--noyer   { background-color: var(--c-noyer) !important;  color: var(--c-ivoire) !important; }

/* Le texte hérite de sa section : on neutralise les 45 règles qui forcent une
   couleur sombre sur p, li, td, span, article p, ul li… */
.ml-habitacle :is(p, li, dd, dt, td, th, span, figcaption, blockquote, address, summary, label, small) {
  color: inherit !important;
}
.ml-habitacle :is(h1, h2, h3, h4, h5, h6) { color: inherit !important; }

/* Les encres secondaires restent secondaires, section par section. */
.ml-habitacle .mh-s--cuir   :is(.mh-lead, .mh-card__texte, .mh-legende) { color: var(--c-gris-chaud) !important; }
.ml-habitacle .mh-s--noyer  :is(.mh-lead, .mh-card__texte, .mh-legende) { color: var(--c-gris-chaud) !important; }
.ml-habitacle .mh-s--papier :is(.mh-lead, .mh-card__texte, .mh-legende) { color: var(--c-taupe) !important; }

/* — Typographie. Menacée par « .section-title, h2 { font-size: 1.5rem } » et
     « body { font-size: max(1rem,16px) } ». — */
.ml-habitacle              { font-family: var(--ff-texte) !important; font-size: var(--fs-body) !important; }
.ml-habitacle :is(h1)      { font-family: var(--ff-display) !important; font-size: var(--fs-display) !important; line-height: 1.04 !important; }
.ml-habitacle :is(h2)      { font-family: var(--ff-display) !important; font-size: var(--fs-h2) !important;      line-height: 1.12 !important; }
.ml-habitacle :is(h3)      { font-family: var(--ff-texte) !important;   font-size: var(--fs-h3) !important;      line-height: 1.25 !important; }
.ml-habitacle .mh-lead     { font-size: var(--fs-lead) !important; }
.ml-habitacle .mh-eyebrow  { font-size: var(--fs-label) !important; }
/* « h1, h2 { white-space: normal } » du site : c'est aussi ce qu'on veut, mais
   on le réaffirme pour que text-wrap: balance ne soit pas neutralisé. */
.ml-habitacle :is(h1, h2, h3) { white-space: normal !important; }

/* — Espacement des sections. Menacé par « section { padding: 40px 0 } »,
     « section:first-of-type { margin-top: 0; padding-top: 0 } » et la règle
     mobile « section { padding-top: 2.5rem } ». — */
.ml-habitacle > section {
  padding-block: var(--pad-section) !important;
  margin-block: 0 !important;
}
/* Le hero gère sa propre hauteur : il ne prend pas le rembourrage de section. */
.ml-habitacle > .mh-hero { padding-block: 0 !important; }

/* — Liens. « a { text-decoration: underline } » du site s'appliquerait aux
     boutons, qui deviendraient soulignés. — */
.ml-habitacle :is(.mh-btn, .mh-btn--or, .mh-btn--chrome, .mh-btn--encre) { text-decoration: none !important; }

/* — Focus. « *:focus-visible { outline } » du site remplacerait la bague
     bicolore. On la réaffirme : elle reste visible dans les deux cas, donc
     aucune régression d'accessibilité si l'une ou l'autre gagne. — */
.ml-habitacle :is(a, button, summary, input, select, textarea, [tabindex]):focus-visible {
  outline: 2px solid var(--c-ivoire) !important;
  outline-offset: 2px !important;
  box-shadow: 0 0 0 4px var(--c-encre-noir) !important;
}
.ml-habitacle .mh-s--papier :is(a, button, summary, input, select, textarea, [tabindex]):focus-visible {
  outline-color: var(--c-encre) !important;
  box-shadow: 0 0 0 4px var(--c-papier) !important;
}

/* — Champs de formulaire. « input, select, textarea { border-width: 2px;
     border-color: #000 } » poserait un liseré noir sur le bloc noyer. — */
.ml-habitacle :is(input, select, textarea) {
  border-width: 1px !important;
  border-color: var(--c-chrome-sourd) !important;
  background-color: var(--c-surface) !important;
  color: var(--c-ivoire) !important;
  font-family: var(--ff-texte) !important;
}
.ml-habitacle :is(input, select, textarea):focus-visible {
  border-color: var(--c-chrome-clair) !important;
}
/* Le texte d'aide des champs doit rester lisible sur le fond des champs. */
.ml-habitacle ::placeholder { color: var(--c-chrome-sourd) !important; opacity: 1; }

/* — Rayon. Le site impose des coins arrondis à plusieurs endroits ; la
     direction tient à 2px partout (« une portière n'a pas de coins à 16px »). — */
.ml-habitacle :is(.mh-btn, .mh-card, .mh-flotte__fiche, input, select, textarea, img, picture) {
  border-radius: var(--r-1) !important;
}

/* — Dernier garde-fou : aucun contenu textuel de la refonte ne peut être
     invisible, quelle que soit la feuille qui passe par là. — */
.ml-habitacle :is(h1, h2, h3, h4, h5, h6, p, li, dd, dt, td, th, summary, label, figcaption, blockquote, address) {
  opacity: 1;
  visibility: visible;
}


/* ═══════════ 10-coquille ═══════════
   COQUILLE HABITACLE — barre de navigation, panneau mobile, fil d'Ariane,
   pied de page, barre d'accès mobile, bouton flottant, bandeau cookies.
   -----------------------------------------------------------------------------
   POURQUOI UN AUTRE SCOPE QUE .ml-habitacle
   .ml-habitacle est posée sur un <div> DANS le <main> : elle ne peut pas
   atteindre l'en-tête ni le pied, qui vivent en dehors. La coquille porte donc
   sa propre classe racine, .mh-shell, présente sur chaque élément qu'elle
   émet ; le <body> des pages converties porte .mh-page.

   JETONS
   Les variables sont déclarées sur .ml-habitacle, pas sur :root : elles ne
   descendent donc pas jusqu'à la coquille. Le bloc « 10.1 » ci-dessous en est
   le MIROIR — mêmes noms, mêmes valeurs, aucune couleur nouvelle, aucune paire
   de contraste non mesurée. Si une valeur change dans le bloc 01, elle doit
   changer ici : c'est la seule duplication de la feuille, et elle est
   volontaire (un fichier appendé ne peut pas modifier un bloc antérieur).

   TEXTE MASQUÉ
   Aucun. Pas un opacity:0, pas un visibility:hidden, pas un height:0, pas un
   clip-path sur du contenu. Les seuls display:none portent sur des COMMANDES
   (le burger au-delà de 1200px, la croix de fermeture sans JavaScript, les
   éléments d'interface fixes à l'impression) ou sur l'état fermé du panneau de
   menu — qui est un menu, dont tous les liens sont déjà dans la barre.
   Les animations ne touchent que transform.
   ═══════════════════════════════════════════════════════════════════════════ */


/* ═══ 10.1  JETONS DE LA COQUILLE — miroir du bloc 01 ═══ */

.mh-page,
.mh-shell {
  --c-nuit:       #0E0D0C;
  --c-surface:    #1A1714;
  --c-encre-noir: #14120F;
  --c-noyer:      #3A2A1E;
  --c-joint:      #26231F;
  --c-papier:     #F4F0E8;

  --c-ivoire:       #F2EDE4;   /* 16,7:1 sur nuit */
  --c-gris-chaud:   #C9C1B4;   /* 10,9:1 sur nuit */
  --c-chrome-clair: #C9CDD2;   /* 12,2:1 sur nuit */
  --c-chrome-sourd: #8A9096;   /*  6,0:1 sur nuit */

  --c-laiton:       #C8A96A;   /*  8,6:1 sur nuit */
  --c-laiton-clair: #E0C489;
  --c-laiton-fonce: #7A5A22;

  --c-filet-decor: #4A4E52;    /* décoratif : jamais une limite, jamais du texte */

  --moulure-sombre: linear-gradient(90deg,
      rgba(201,205,210,0) 0%, rgba(201,205,210,.55) 18%, rgba(201,205,210,1) 50%,
      rgba(201,205,210,.55) 82%, rgba(201,205,210,0) 100%);

  --ff-display: "Bodoni Moda", Georgia, "Times New Roman", serif;
  --ff-texte:   "Archivo", Arial, "Helvetica Neue", sans-serif;

  --fs-h3:    clamp(1.25rem,   1.125rem  + 0.56vw, 1.625rem);
  --fs-body:  clamp(1rem,      0.9792rem + 0.09vw, 1.0625rem);
  --fs-small: clamp(0.875rem,  0.8542rem + 0.09vw, 0.9375rem);
  --fs-label: clamp(0.75rem,   0.7292rem + 0.09vw, 0.8125rem);

  --sp-1:  4px;
  --sp-2:  8px;
  --sp-3:  12px;
  --sp-4:  16px;
  --sp-5:  24px;
  --sp-6:  32px;
  --sp-7:  48px;
  --sp-8:  64px;

  --gouttiere:  clamp(1.25rem, 0.8333rem + 1.85vw, 2.5rem);
  --gap-grille: clamp(1rem,    0.6667rem + 1.48vw, 2rem);

  --w-container: 1280px;
  --filet: 1px;
  --r-1:   2px;

  --ease-standard: cubic-bezier(.2, 0, 0, 1);
  --ease-sortie:   cubic-bezier(.16, 1, .3, 1);
  --dur-1: 160ms;
  --dur-2: 260ms;

  --touche-min: 48px;

  /* Propres à la coquille */
  --mh-barre-h:  64px;   /* hauteur de la barre d'accès mobile */
  --mh-entete-h: 64px;   /* hauteur de la barre de navigation */
}


/* ═══ 10.2  PAGE ═══ */

/* Le fond de page passe en cuir : sans lui, un interstice blanc apparaîtrait
   entre le <main> et le pied dès qu'une marge se glisse quelque part. */
body.mh-page {
  background-color: var(--c-nuit);
}

/* Verrou de défilement posé sur <html> pendant que le panneau de menu est
   ouvert. Retiré à la fermeture par le même script. */
html.mh-verrou { overflow: hidden; }


/* ═══ 10.3  SOCLE DE LA COQUILLE ═══ */

.mh-shell,
.mh-shell *,
.mh-shell *::before,
.mh-shell *::after { box-sizing: border-box; }

.mh-shell {
  font-family: var(--ff-texte);
  font-size: var(--fs-body);
  line-height: 1.65;
  color: var(--c-ivoire);
  text-align: start;
}

.mh-shell :where(p, ul, ol, li, h1, h2, h3, h4, figure) { margin: 0; }
.mh-shell :where(ul, ol) { padding: 0; list-style: none; }
.mh-shell :where(img)    { display: block; max-inline-size: 100%; block-size: auto; }
.mh-shell :where(a)      { color: inherit; text-decoration: none; }
.mh-shell :where(button)  {
  appearance: none;
  margin: 0;
  border: 0;
  background: none;
  color: inherit;
  font: inherit;
  cursor: pointer;
}
/* Un enfant de flex ou de grille doit pouvoir rétrécir sous son min-content,
   sinon un libellé long pousse la page en défilement horizontal. */
.mh-shell :where(a, div, li, nav, p, section, span, ul) { min-inline-size: 0; }
.mh-shell :where(p, li, a, span, strong) { overflow-wrap: break-word; }

/* Icônes Remixicon. Jamais d'emoji : un glyphe bitmap ignore `color`. */
.mh-shell :is([class^="ri-"], [class*=" ri-"]) {
  display: inline-block;
  flex: 0 0 auto;
  font-family: remixicon;
  font-style: normal;
  font-weight: 400;
  font-size: 1.25em;
  line-height: 1;
  vertical-align: -0.2em;
}

/* Conteneur : même gabarit que celui du contenu, pour que la barre, le pied et
   les sections soient alignés au pixel. */
.mh-shell .mh-wrap {
  inline-size: 100%;
  max-inline-size: var(--w-container);
  margin-inline: auto;
  padding-inline: var(--gouttiere);
}

/* La moulure : filet 1 px, seul brillant de la coquille comme du contenu. */
.mh-shell .mh-menu__moulure,
.mh-shell .mh-pied__moulure {
  display: block;
  inline-size: 100%;
  block-size: var(--filet);
  background-image: var(--moulure-sombre);
}

/* Bague de focus : identique à celle du contenu, visible sur cuir. */
.mh-shell :is(a, button, [tabindex]):focus-visible {
  outline: 2px solid var(--c-ivoire);
  outline-offset: 2px;
  box-shadow: 0 0 0 4px var(--c-encre-noir);
  border-radius: var(--r-1);
}


/* ═══ 10.4  LIEN D'ÉVITEMENT ═══ */

/* Hors focus il est sorti du cadre par translation — c'est une COMMANDE de
   navigation au clavier, pas du contenu, et elle reste dans le DOM, lisible
   par les technologies d'assistance et atteignable à la première tabulation. */
.mh-shell.mh-evitement {
  position: fixed;
  inset-block-start: 0;
  inset-inline-start: var(--sp-4);
  z-index: 1100;
  display: inline-block;
  padding: var(--sp-3) var(--sp-5);
  border: var(--filet) solid var(--c-laiton);
  border-radius: var(--r-1);
  background-color: var(--c-encre-noir);
  color: var(--c-ivoire);
  font-size: var(--fs-small);
  font-weight: 600;
  transform: translateY(-140%);
  transition: transform var(--dur-1) var(--ease-standard);
}
.mh-shell.mh-evitement:focus-visible,
.mh-shell.mh-evitement:focus { transform: translateY(var(--sp-2)); }


/* ═══ 10.5  BARRE DE NAVIGATION ═══ */

.mh-shell.mh-entete {
  position: sticky;
  inset-block-start: 0;
  z-index: 900;
  border: 0;
  background-color: var(--c-nuit);
  box-shadow: none;
}

/* La moulure chrome 1 px, en bas de la barre. Décorative : aucun texte, aucune
   information ne repose dessus. */
.mh-shell.mh-entete::after {
  content: "";
  position: absolute;
  inset-inline: 0;
  inset-block-end: 0;
  block-size: var(--filet);
  background-image: var(--moulure-sombre);
  pointer-events: none;
}

.mh-shell .mh-entete__inner {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  min-block-size: var(--mh-entete-h);
  padding-block: var(--sp-2);
}

.mh-shell .mh-entete__logo {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  /* RECETTE 02/08 : l'ancre epousait l'image (32px) et ratait la cible de 44px.
     L'image garde sa taille ; seule la zone cliquable grandit. */
  min-block-size: var(--touche-min);
}
.mh-shell .mh-entete__img {
  inline-size: auto;
  block-size: 32px;
  border-radius: var(--r-1);
}

/* Navigation : cachée à la barre sous 1200 px, où elle est servie par le
   panneau. Les liens y sont intégralement repris — rien n'est perdu. */
.mh-shell .mh-nav { display: none; }

.mh-shell .mh-nav__liste {
  display: flex;
  flex-wrap: nowrap;
  align-items: center;
  gap: var(--sp-1);
}

.mh-shell .mh-nav__lien {
  display: inline-flex;
  align-items: center;
  min-block-size: var(--touche-min);
  padding-inline: var(--sp-2);
  color: var(--c-gris-chaud);            /* 10,9:1 */
  font-size: var(--fs-label);
  font-weight: 500;
  letter-spacing: 0.02em;
  white-space: nowrap;
  transition: color var(--dur-1) var(--ease-standard);
}
.mh-shell .mh-nav__lien:is(:hover, :focus-visible) {
  color: var(--c-ivoire);                /* 16,7:1 */
  text-decoration-line: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 6px;
}
/* Page courante : soulignée en permanence — jamais signalée par la couleur
   seule. */
.mh-shell .mh-nav__lien--actif {
  color: var(--c-ivoire);
  text-decoration-line: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 6px;
  text-decoration-color: var(--c-laiton);
}

.mh-shell .mh-entete__actions {
  margin-inline-start: auto;
  display: flex;
  align-items: center;
  gap: var(--sp-2);
}

/* Téléphone : le numéro est ÉCRIT, à toutes les largeurs. */
.mh-shell .mh-tel {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  min-block-size: var(--touche-min);
  padding-inline: var(--sp-2);
  color: var(--c-chrome-clair);          /* 12,2:1 */
  font-size: var(--fs-label);
  font-weight: 600;
  letter-spacing: 0.04em;
  white-space: nowrap;
  transition: color var(--dur-1) var(--ease-standard);
}
.mh-shell .mh-tel:is(:hover, :focus-visible) { color: var(--c-ivoire); }
.mh-shell .mh-tel__ico { color: var(--c-laiton); }

/* Appel à l'action : laiton plein, encre noire dessus (8,3:1). Aucun prix,
   aucun montant — la demande de devis EST l'action. */
.mh-shell .mh-cta {
  display: none;
  align-items: center;
  justify-content: center;
  min-block-size: var(--touche-min);
  padding-inline: var(--sp-5);
  border: var(--filet) solid var(--c-laiton);
  border-radius: var(--r-1);
  background-color: var(--c-laiton);
  color: var(--c-encre-noir);
  font-size: var(--fs-label);
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  white-space: nowrap;
  transition: background-color var(--dur-1) var(--ease-standard),
              border-color var(--dur-1) var(--ease-standard);
}
.mh-shell .mh-cta:is(:hover, :focus-visible) {
  background-color: var(--c-ivoire);
  border-color: var(--c-ivoire);
  color: var(--c-encre-noir);            /* 16,0:1 */
}

.mh-shell .mh-lang {
  display: none;
  align-items: center;
  justify-content: center;
  min-inline-size: 44px;
  min-block-size: var(--touche-min);
  padding-inline: var(--sp-2);
  border: var(--filet) solid var(--c-chrome-sourd);
  border-radius: var(--r-1);
  color: var(--c-chrome-clair);
  font-size: var(--fs-label);
  font-weight: 600;
  letter-spacing: 0.08em;
  transition: border-color var(--dur-1) var(--ease-standard),
              color var(--dur-1) var(--ease-standard);
}
.mh-shell .mh-lang:is(:hover, :focus-visible) {
  border-color: var(--c-ivoire);
  color: var(--c-ivoire);
}

/* Burger : trois filets chrome. Commande, pas contenu. */
.mh-shell .mh-burger {
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 5px;
  inline-size: var(--touche-min);
  block-size: var(--touche-min);
  border: var(--filet) solid var(--c-filet-decor);
  border-radius: var(--r-1);
  background-color: transparent;
  transition: border-color var(--dur-1) var(--ease-standard);
}
.mh-shell .mh-burger:is(:hover, :focus-visible) { border-color: var(--c-chrome-clair); }
.mh-shell .mh-burger__trait {
  display: block;
  inline-size: 20px;
  block-size: var(--filet);
  background-color: var(--c-chrome-clair);
}


/* ═══ 10.6  PANNEAU DE MENU (mobile et tablette) ═══
   État fermé = attribut `hidden`. C'est l'état d'un MENU, pas du texte
   dissimulé : les mêmes liens sont dans la barre au-delà de 1200 px, et sans
   JavaScript le <noscript> du gabarit rend ce panneau statique et déroulé.
   Aucune règle ici ne masque un texte au repos. */

.mh-shell.mh-menu {
  position: fixed;
  inset: 0;
  z-index: 1000;
  display: flex;
  flex-direction: column;
  overflow-y: auto;
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
  background-color: var(--c-nuit);
}
/* Sans cette ligne, `display:flex` ci-dessus battrait la règle UA de [hidden]
   et le panneau serait ouvert en permanence. */
.mh-shell.mh-menu[hidden] { display: none; }

.mh-shell .mh-menu__panneau {
  inline-size: 100%;
  max-inline-size: var(--w-container);
  margin-inline: auto;
  padding: var(--sp-4) var(--gouttiere) var(--sp-8);
}

.mh-shell .mh-menu__entete {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-4);
  min-block-size: var(--mh-entete-h);
}
.mh-shell .mh-menu__titre {
  color: var(--c-chrome-clair);
  font-size: var(--fs-label);
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}
.mh-shell .mh-menu__fermer {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  inline-size: var(--touche-min);
  block-size: var(--touche-min);
  border: var(--filet) solid var(--c-filet-decor);
  border-radius: var(--r-1);
  color: var(--c-chrome-clair);
  transition: border-color var(--dur-1) var(--ease-standard),
              color var(--dur-1) var(--ease-standard);
}
.mh-shell .mh-menu__fermer:is(:hover, :focus-visible) {
  border-color: var(--c-ivoire);
  color: var(--c-ivoire);
}

.mh-shell .mh-menu__liste { margin-block-start: var(--sp-4); }

.mh-shell .mh-menu__lien {
  display: flex;
  align-items: center;
  min-block-size: 56px;
  padding-block: var(--sp-3);
  border-block-end: var(--filet) solid var(--c-joint);
  color: var(--c-ivoire);                /* 16,7:1 */
  font-size: var(--fs-h3);
  font-weight: 500;
  transition: color var(--dur-1) var(--ease-standard);
}
.mh-shell .mh-menu__lien:is(:hover, :focus-visible) { color: var(--c-laiton); }
.mh-shell .mh-menu__lien--actif {
  color: var(--c-laiton);                /* 8,6:1 */
  text-decoration-line: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 6px;
}

.mh-shell .mh-menu__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-3);
  margin-block-start: var(--sp-6);
}
.mh-shell .mh-menu__cta {
  display: inline-flex;
  flex: 1 1 100%;
}
.mh-shell .mh-menu__tel {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  min-block-size: var(--touche-min);
  padding-inline: var(--sp-4);
  border: var(--filet) solid var(--c-chrome-sourd);
  border-radius: var(--r-1);
  color: var(--c-chrome-clair);
  font-size: var(--fs-small);
  font-weight: 600;
  white-space: nowrap;
}
.mh-shell .mh-menu__tel:is(:hover, :focus-visible) {
  border-color: var(--c-ivoire);
  color: var(--c-ivoire);
}
.mh-shell .mh-menu__lang {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-inline-size: var(--touche-min);
  min-block-size: var(--touche-min);
  padding-inline: var(--sp-3);
  border: var(--filet) solid var(--c-chrome-sourd);
  border-radius: var(--r-1);
  color: var(--c-chrome-clair);
  font-size: var(--fs-label);
  font-weight: 600;
  letter-spacing: 0.08em;
}
.mh-shell .mh-menu__lang:is(:hover, :focus-visible) {
  border-color: var(--c-ivoire);
  color: var(--c-ivoire);
}


/* ═══ 10.7  FIL D'ARIANE ═══ */

.mh-shell.mh-fil {
  background-color: var(--c-nuit);
  border-block-end: var(--filet) solid var(--c-joint);
}
.mh-shell .mh-fil__inner { padding-block: var(--sp-3); }
.mh-shell .mh-fil__liste {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-1) var(--sp-2);
  font-size: var(--fs-small);
}
.mh-shell .mh-fil__item {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
}
.mh-shell .mh-fil__lien {
  color: var(--c-laiton);                /* 8,6:1 */
  text-decoration-line: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
}
.mh-shell .mh-fil__lien:is(:hover, :focus-visible) { color: var(--c-ivoire); }
.mh-shell .mh-fil__sep    { color: var(--c-chrome-sourd); }
.mh-shell .mh-fil__actuel { color: var(--c-gris-chaud); }  /* 10,9:1 */


/* ═══ 10.8  PIED DE PAGE ═══ */

.mh-shell.mh-pied {
  position: relative;
  background-color: var(--c-nuit);
  color: var(--c-ivoire);
}
.mh-shell .mh-pied__moulure { position: absolute; inset-block-start: 0; inset-inline: 0; }

.mh-shell .mh-pied__inner {
  padding-block: var(--sp-8) var(--sp-6);
}

.mh-shell .mh-pied__marque {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--sp-4);
  padding-block-end: var(--sp-6);
  border-block-end: var(--filet) solid var(--c-joint);
}
/* RECETTE 02/08 : meme correction de cible tactile que le logo d'entete. */
.mh-shell .mh-pied__logo {
  display: inline-flex;
  align-items: center;
  min-block-size: var(--touche-min);
}
.mh-shell .mh-pied__logo img { inline-size: auto; block-size: 38px; }
.mh-shell .mh-pied__texte {
  max-inline-size: 52ch;
  color: var(--c-gris-chaud);            /* 10,9:1 */
  font-size: var(--fs-small);
  line-height: 1.6;
}
.mh-shell .mh-pied__reseaux {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2);
}
.mh-shell .mh-pied__reseau {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  inline-size: var(--touche-min);
  block-size: var(--touche-min);
  border: var(--filet) solid var(--c-filet-decor);
  border-radius: var(--r-1);
  color: var(--c-chrome-clair);          /* 12,2:1 */
  transition: border-color var(--dur-1) var(--ease-standard),
              color var(--dur-1) var(--ease-standard);
}
.mh-shell .mh-pied__reseau:is(:hover, :focus-visible) {
  border-color: var(--c-laiton);
  color: var(--c-laiton);
}

/* Une colonne en mobile, trois à partir de 900 px : c'est le gabarit demandé. */
.mh-shell .mh-pied__grille {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--gap-grille);
  padding-block: var(--sp-6);
}
.mh-shell .mh-pied__col { min-inline-size: 0; }

.mh-shell .mh-pied__titre {
  margin-block-end: var(--sp-4);
  color: var(--c-ivoire);
  font-family: var(--ff-texte);          /* Bodoni interdite sous 28 px */
  font-size: var(--fs-h3);
  font-weight: 600;
  line-height: 1.25;
  letter-spacing: 0;
}

.mh-shell .mh-pied__liste {
  display: flex;
  flex-direction: column;
  gap: var(--sp-1);
}
.mh-shell .mh-pied__lien {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  /* RECETTE 02/08 : 40px echouait la cible tactile de 44px du standard maison.
     Ramene sur le jeton --touche-min, deja utilise par tout le reste. */
  min-block-size: var(--touche-min);
  color: var(--c-gris-chaud);            /* 10,9:1 */
  font-size: var(--fs-small);
  transition: color var(--dur-1) var(--ease-standard);
}
.mh-shell .mh-pied__lien:is(:hover, :focus-visible) {
  color: var(--c-ivoire);
  text-decoration-line: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 4px;
}
.mh-shell .mh-pied__lien--fort {
  color: var(--c-ivoire);
  font-size: var(--fs-body);
  font-weight: 600;
}
.mh-shell .mh-pied__lien i { color: var(--c-laiton); }

.mh-shell .mh-pied__contact { gap: var(--sp-4); }
.mh-shell .mh-pied__label {
  display: block;
  color: var(--c-chrome-sourd);          /* 6,0:1 */
  font-size: var(--fs-label);
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}
.mh-shell .mh-pied__valeur {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  min-block-size: 40px;
  color: var(--c-gris-chaud);
  font-size: var(--fs-small);
}
.mh-shell .mh-pied__valeur i { color: var(--c-laiton); }

.mh-shell .mh-pied__wa {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);
  min-block-size: var(--touche-min);
  margin-block-start: var(--sp-4);
  padding-inline: var(--sp-5);
  border: var(--filet) solid var(--c-chrome-sourd);
  border-radius: var(--r-1);
  color: var(--c-chrome-clair);          /* 12,2:1 */
  font-size: var(--fs-label);
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  transition: border-color var(--dur-1) var(--ease-standard),
              color var(--dur-1) var(--ease-standard);
}
.mh-shell .mh-pied__wa:is(:hover, :focus-visible) {
  border-color: var(--c-ivoire);
  color: var(--c-ivoire);
}

/* Partenaires : mêmes liens qu'auparavant, simplement rhabillés. */
.mh-shell .mh-pied__partenaires {
  padding-block: var(--sp-4);
  border-block-start: var(--filet) solid var(--c-joint);
  color: var(--c-gris-chaud);
  font-size: var(--fs-small);
  line-height: 2;
}
.mh-shell .mh-pied__partenaires-titre {
  margin-inline-end: var(--sp-2);
  color: var(--c-chrome-sourd);
  font-size: var(--fs-label);
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}
.mh-shell .mh-pied__partenaire {
  color: var(--c-gris-chaud);
  text-decoration-line: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
}
.mh-shell .mh-pied__partenaire:is(:hover, :focus-visible) { color: var(--c-ivoire); }
.mh-shell .mh-pied__puce {
  margin-inline: var(--sp-2);
  color: var(--c-filet-decor);
}

.mh-shell .mh-pied__bas {
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
  padding-block: var(--sp-5);
  border-block-start: var(--filet) solid var(--c-joint);
}
.mh-shell .mh-pied__copy {
  color: var(--c-gris-chaud);
  font-size: var(--fs-small);
}
.mh-shell .mh-pied__legal {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2) var(--sp-5);
}

/* Mention légale VTC : texte de loi, il doit rester parfaitement lisible. */
.mh-shell .mh-pied__vtc {
  padding-block: var(--sp-5);
  border-block-start: var(--filet) solid var(--c-joint);
  color: var(--c-gris-chaud);            /* 10,9:1 */
  font-size: var(--fs-small);
  line-height: 1.7;
}
.mh-shell .mh-pied__vtc p { max-inline-size: 100ch; }
.mh-shell .mh-pied__vtc strong { color: var(--c-ivoire); font-weight: 600; }
.mh-shell .mh-pied__vtc-titre {
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
/* Lien dans un paragraphe : souligné en permanence, comme dans le contenu. */
.mh-shell .mh-pied__vtc a {
  color: var(--c-laiton);
  text-decoration-line: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
}
.mh-shell .mh-pied__vtc a:is(:hover, :focus-visible) { color: var(--c-ivoire); }

.mh-shell .mh-pied__partenaires--bas { padding-block-end: 0; }


/* ═══ 10.9  BARRE D'ACCÈS MOBILE ═══
   Cinq destinations, les mêmes qu'auparavant. Chaque icône est doublée d'un
   libellé écrit : rien ne repose sur le pictogramme seul. */

.mh-shell.mh-barre {
  position: fixed;
  inset-inline: 0;
  inset-block-end: 0;
  z-index: 920;
  display: flex;
  align-items: stretch;
  min-block-size: var(--mh-barre-h);
  padding-block-end: env(safe-area-inset-bottom, 0px);
  border-block-start: var(--filet) solid var(--c-joint);
  background-color: var(--c-encre-noir);
}
.mh-shell .mh-barre__lien {
  flex: 1 1 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  min-inline-size: 0;
  padding: var(--sp-2) var(--sp-1);
  color: var(--c-gris-chaud);            /* 10,9:1 sur encre noire */
  text-align: center;
  transition: color var(--dur-1) var(--ease-standard);
}
.mh-shell .mh-barre__lien:is(:hover, :focus-visible) { color: var(--c-ivoire); }
.mh-shell .mh-barre__ico { font-size: 1.375rem; }
.mh-shell .mh-barre__txt {
  font-size: var(--fs-label);
  font-weight: 500;
  line-height: 1.2;
}
.mh-shell .mh-barre__lien--actif {
  color: var(--c-laiton);                /* 8,6:1 */
  box-shadow: inset 0 2px 0 0 var(--c-laiton);
}
.mh-shell .mh-barre__lien--cta {
  color: var(--c-encre-noir);
  background-color: var(--c-laiton);     /* 8,3:1 */
}
.mh-shell .mh-barre__lien--cta:is(:hover, :focus-visible) {
  background-color: var(--c-ivoire);
  color: var(--c-encre-noir);
}
.mh-shell .mh-barre__lien--cta.mh-barre__lien--actif {
  color: var(--c-encre-noir);
  box-shadow: inset 0 2px 0 0 var(--c-encre-noir);
}

/* Au-delà de 768 px la barre disparaît : c'est un élément d'interface mobile,
   ses cinq destinations sont toutes présentes ailleurs dans la page (barre de
   navigation, panneau, pied). */
@media (min-width: 768px) {
  .mh-shell.mh-barre { display: none; }
}
/* En dessous, le pied réserve la place de la barre pour que sa dernière ligne
   ne passe jamais dessous. */
@media (max-width: 767.98px) {
  .mh-shell .mh-pied__inner {
    padding-block-end: calc(var(--mh-barre-h) + var(--sp-6) + env(safe-area-inset-bottom, 0px));
  }
}


/* ═══ 10.10  BOUTON FLOTTANT WHATSAPP ═══ */

.mh-shell.mh-flottant {
  position: fixed;
  inset-inline-end: var(--sp-4);
  inset-block-end: calc(var(--mh-barre-h) + var(--sp-4) + env(safe-area-inset-bottom, 0px));
  z-index: 930;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  inline-size: 52px;
  block-size: 52px;
  border: var(--filet) solid var(--c-laiton);
  border-radius: var(--r-1);
  background-color: var(--c-encre-noir);
  color: var(--c-laiton);                /* 8,6:1 */
  transition: background-color var(--dur-1) var(--ease-standard),
              color var(--dur-1) var(--ease-standard);
}
.mh-shell.mh-flottant i { font-size: 1.5rem; }
.mh-shell.mh-flottant:is(:hover, :focus-visible) {
  background-color: var(--c-laiton);
  color: var(--c-encre-noir);            /* 8,3:1 */
}
@media (min-width: 768px) {
  .mh-shell.mh-flottant {
    inset-block-end: var(--sp-5);
    inset-inline-end: var(--sp-5);
  }
}


/* ═══ 10.11  BANDEAU COOKIES ═══
   Commande, pas contenu. Le script commun du pied lui rend `display:block` :
   la mise en page est donc portée par l'enfant, jamais par la boîte elle-même. */

.mh-shell.mh-cookies {
  position: fixed;
  inset-inline: var(--sp-3);
  inset-block-end: calc(var(--mh-barre-h) + var(--sp-8) + env(safe-area-inset-bottom, 0px));
  z-index: 1010;
  max-inline-size: 640px;
  margin-inline: auto;
  padding: var(--sp-4);
  border: var(--filet) solid var(--c-chrome-sourd);
  border-radius: var(--r-1);
  background-color: var(--c-surface);
}
.mh-shell .mh-cookies__inner {
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
}
.mh-shell .mh-cookies__texte {
  color: var(--c-gris-chaud);
  font-size: var(--fs-small);
  line-height: 1.6;
}
.mh-shell .mh-cookies__lien {
  color: var(--c-laiton);
  text-decoration-line: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
}
.mh-shell .mh-cookies__lien:is(:hover, :focus-visible) { color: var(--c-ivoire); }
.mh-shell .mh-cookies__ok {
  align-self: flex-start;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-block-size: var(--touche-min);
  padding-inline: var(--sp-5);
  border: var(--filet) solid var(--c-laiton);
  border-radius: var(--r-1);
  background-color: var(--c-laiton);
  color: var(--c-encre-noir);            /* 8,3:1 */
  font-size: var(--fs-label);
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}
.mh-shell .mh-cookies__ok:is(:hover, :focus-visible) {
  background-color: var(--c-ivoire);
  border-color: var(--c-ivoire);
}
@media (min-width: 768px) {
  .mh-shell.mh-cookies { inset-block-end: var(--sp-5); }
  .mh-shell .mh-cookies__inner { flex-direction: row; align-items: center; gap: var(--sp-5); }
  .mh-shell .mh-cookies__texte { flex: 1 1 auto; }
  .mh-shell .mh-cookies__ok { align-self: auto; flex: 0 0 auto; }
}


/* ═══ 10.12  BASCULE VERS LA BARRE COMPLÈTE (≥ 1200 px) ═══
   Un seul point de rupture : au-dessus, les sept liens, le devis et la langue
   tiennent dans la barre sans jamais la faire déborder ; en dessous, ils sont
   servis par le panneau. Aucun texte n'est perdu d'un côté ni de l'autre. */

@media (min-width: 1200px) {
  .mh-shell { --mh-entete-h: 72px; }
  .mh-shell .mh-nav    { display: block; margin-inline-start: auto; }
  .mh-shell .mh-cta    { display: inline-flex; }
  .mh-shell .mh-lang   { display: inline-flex; }
  .mh-shell .mh-burger { display: none; }
  .mh-shell.mh-menu    { display: none; }
  .mh-shell .mh-entete__actions { margin-inline-start: 0; gap: var(--sp-3); }
  .mh-shell .mh-entete__img     { block-size: 36px; }
}

@media (min-width: 900px) {
  .mh-shell .mh-pied__grille { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--sp-7); }
  .mh-shell .mh-pied__marque { flex-direction: row; align-items: center; gap: var(--sp-6); }
  .mh-shell .mh-pied__texte  { flex: 1 1 auto; }
  .mh-shell .mh-pied__bas    { flex-direction: row; align-items: center; justify-content: space-between; }
}


/* ═══ 10.13  MOUVEMENT RÉDUIT, COULEURS FORCÉES, IMPRESSION ═══ */

@media (prefers-reduced-motion: reduce) {
  .mh-shell,
  .mh-shell * {
    transition-duration: 1ms !important;
    animation-duration: 1ms !important;
    animation-iteration-count: 1 !important;
  }
}

@media (forced-colors: active) {
  .mh-shell :is(.mh-cta, .mh-lang, .mh-burger, .mh-menu__fermer, .mh-pied__reseau,
                .mh-pied__wa, .mh-cookies__ok, .mh-flottant) {
    border-color: currentColor;
  }
}

@media print {
  /* Seuls des éléments d'interface disparaissent ; aucun texte de contenu. */
  .mh-shell.mh-barre,
  .mh-shell.mh-flottant,
  .mh-shell.mh-cookies,
  .mh-shell.mh-evitement,
  .mh-shell .mh-burger { display: none !important; }
  .mh-shell.mh-entete  { position: static; }
  .mh-shell.mh-entete,
  .mh-shell.mh-pied,
  .mh-shell.mh-fil { background-color: transparent; color: #000; }
  .mh-shell :is(.mh-nav__lien, .mh-tel, .mh-pied__lien, .mh-pied__texte,
                .mh-pied__titre, .mh-pied__copy, .mh-pied__vtc,
                .mh-fil__lien, .mh-fil__actuel) { color: #000; }
}


/* ═══ 10.14  BOUCLIER DE LA COQUILLE ═══
   Même principe que le bloc 99 : les feuilles historiques ne sont plus
   chargées sur les pages Habitacle, mais le CSS critique en ligne du <head>,
   lui, reste émis. Il pose « header { position:sticky; background:#fff;
   border-bottom:1px solid #eee } », « nav { display:flex; padding:.5rem 1rem } »,
   « nav a { color:#1a1a1a; padding:.5rem } », « a:hover { color:#8b6914;
   text-decoration:underline } » et « h1..h6 { color:#1a1a2e } ». Aucune de ces
   règles n'est en !important : les sélecteurs de classe ci-dessus les battent
   déjà par spécificité. On réaffirme malgré tout les quatre propriétés qui
   feraient basculer la coquille en clair si une feuille future les forçait.
   JAMAIS sur display, visibility, opacity, position ou height : aucune règle
   de ce bloc ne peut masquer un texte. */

/* — Matières. « header { background:#fff } » et « section { background:#f5f5f5 } »
     repeindraient la coquille en clair, texte ivoire sur blanc. — */
.mh-shell.mh-entete,
.mh-shell.mh-pied,
.mh-shell.mh-fil,
.mh-shell.mh-menu    { background-color: var(--c-nuit) !important; }
.mh-shell.mh-barre   { background-color: var(--c-encre-noir) !important; }
.mh-shell.mh-cookies { background-color: var(--c-surface) !important; }

/* — Encres. Réaffirmées UNE CLASSE À LA FOIS, jamais par un `inherit` global :
     un bloc unique écraserait les couleurs voulues des libellés, des
     séparateurs et des icônes. Toutes ces classes portent du texte sans état
     de survol : aucun !important ne peut donc figer une interaction. — */
.mh-shell .mh-pied__titre  { color: var(--c-ivoire) !important; }        /* menacé par h1..h6 { color:#1a1a2e } */
.mh-shell .mh-menu__titre  { color: var(--c-chrome-clair) !important; }
.mh-shell .mh-pied__texte,
.mh-shell .mh-pied__copy,
.mh-shell .mh-pied__vtc,
.mh-shell .mh-pied__partenaires,
.mh-shell .mh-cookies__texte { color: var(--c-gris-chaud) !important; }  /* menacés par body p { color } */
.mh-shell .mh-pied__label,
.mh-shell .mh-fil__sep     { color: var(--c-chrome-sourd) !important; }
.mh-shell .mh-fil__actuel  { color: var(--c-gris-chaud) !important; }

/* — Polices. « body, p, h2 { font-family } » ramènerait la coquille aux polices
     historiques, non chargées ici : le rendu tomberait sur une pile système. — */
.mh-shell,
.mh-shell :is(.mh-nav__lien, .mh-menu__lien, .mh-pied__lien, .mh-fil__lien,
              .mh-tel, .mh-cta, .mh-lang, .mh-pied__titre, .mh-pied__partenaire,
              .mh-barre__txt, .mh-cookies__ok) {
  font-family: var(--ff-texte) !important;
}

/* — Boutons. « a { text-decoration: underline } » soulignerait les commandes
     pleines ; le soulignement est réservé aux liens de texte. — */
.mh-shell :is(.mh-cta, .mh-lang, .mh-burger, .mh-menu__fermer, .mh-menu__tel,
              .mh-menu__lang, .mh-pied__reseau, .mh-pied__wa, .mh-barre__lien,
              .mh-cookies__ok, .mh-flottant, .mh-evitement, .mh-tel) {
  text-decoration: none !important;
}

/* — Rayon. Le site impose des coins arrondis ; la direction tient à 2 px. — */
.mh-shell :is(.mh-cta, .mh-lang, .mh-burger, .mh-menu__fermer, .mh-menu__tel,
              .mh-menu__lang, .mh-pied__reseau, .mh-pied__wa, .mh-cookies__ok,
              .mh-flottant, .mh-evitement, img) {
  border-radius: var(--r-1) !important;
}

/* — Dernier garde-fou : aucun texte de la coquille ne peut devenir invisible,
     quelle que soit la feuille qui passerait par là. — */
.mh-shell :is(h1, h2, h3, h4, p, li, span, strong, address, a, button) {
  opacity: 1;
  visibility: visible;
}


/* ═══ 10.15  BOUCLIER DES ENCRES DE LIENS ═══════════════════════════════════
   MENACE MESURÉE, relevée sur la page rendue et non supposée : le CSS en ligne
   du <head> — émis sur toutes les pages, y compris les pages converties —
   contient

       html body nav a, html body header a { color: #fff !important; }

   Un sélecteur d'éléments nus, en !important : il bat n'importe quelle règle
   propre, quelle que soit sa spécificité. Sans le bloc ci-dessous, TOUS les
   liens de la barre, du fil d'Ariane, de la barre d'accès mobile et des
   mentions légales passaient en blanc pur — dont le bouton « Réserver », qui
   affichait alors du blanc sur laiton, mesuré à 1,9:1. C'est exactement le
   mécanisme qui a fait échouer les refontes précédentes.

   La parade : réaffirmer l'encre, en !important, sur chaque classe de lien de
   la coquille — au repos ET au survol, sans quoi le !important du repos
   figerait l'état de survol. Uniquement `color` : jamais display, visibility,
   opacity, position ni height. Aucune règle de ce bloc ne peut masquer un
   texte ; toutes les valeurs sortent des paires déjà mesurées.
   L'ordre compte : base d'abord, variantes et survols ensuite. ══════════ */

/* — Barre de navigation — */
.mh-shell .mh-nav__lien   { color: var(--c-gris-chaud) !important; }   /* 10,9:1 */
.mh-shell .mh-tel         { color: var(--c-chrome-clair) !important; } /* 12,2:1 */
.mh-shell .mh-lang        { color: var(--c-chrome-clair) !important; } /* 12,2:1 */
.mh-shell .mh-cta         { color: var(--c-encre-noir) !important; }   /*  8,3:1 sur laiton */
.mh-shell .mh-tel__ico    { color: var(--c-laiton) !important; }
.mh-shell .mh-nav__lien:is(:hover, :focus-visible),
.mh-shell .mh-nav__lien--actif,
.mh-shell .mh-tel:is(:hover, :focus-visible),
.mh-shell .mh-lang:is(:hover, :focus-visible) { color: var(--c-ivoire) !important; }  /* 16,7:1 */
.mh-shell .mh-cta:is(:hover, :focus-visible)  { color: var(--c-encre-noir) !important; } /* 16,0:1 sur ivoire */

/* — Panneau de menu — */
.mh-shell .mh-menu__lien  { color: var(--c-ivoire) !important; }
.mh-shell .mh-menu__tel,
.mh-shell .mh-menu__lang  { color: var(--c-chrome-clair) !important; }
.mh-shell .mh-menu__fermer { color: var(--c-chrome-clair) !important; }
.mh-shell .mh-menu__lien:is(:hover, :focus-visible),
.mh-shell .mh-menu__lien--actif { color: var(--c-laiton) !important; } /* 8,6:1 */
.mh-shell .mh-menu__tel:is(:hover, :focus-visible),
.mh-shell .mh-menu__lang:is(:hover, :focus-visible),
.mh-shell .mh-menu__fermer:is(:hover, :focus-visible) { color: var(--c-ivoire) !important; }

/* — Fil d'Ariane (un <nav> : directement visé par la règle blanche) — */
.mh-shell .mh-fil__lien   { color: var(--c-laiton) !important; }       /* 8,6:1 */
.mh-shell .mh-fil__lien:is(:hover, :focus-visible) { color: var(--c-ivoire) !important; }

/* — Pied de page (les mentions légales sont un <nav>) — */
.mh-shell .mh-pied__lien       { color: var(--c-gris-chaud) !important; }
.mh-shell .mh-pied__lien--fort { color: var(--c-ivoire) !important; }
.mh-shell .mh-pied__lien i     { color: var(--c-laiton) !important; }
.mh-shell .mh-pied__valeur i   { color: var(--c-laiton) !important; }
.mh-shell .mh-pied__reseau     { color: var(--c-chrome-clair) !important; }
.mh-shell .mh-pied__wa         { color: var(--c-chrome-clair) !important; }
.mh-shell .mh-pied__partenaire { color: var(--c-gris-chaud) !important; }
.mh-shell .mh-pied__puce       { color: var(--c-filet-decor) !important; }
.mh-shell .mh-pied__vtc a      { color: var(--c-laiton) !important; }
.mh-shell .mh-pied__vtc strong { color: var(--c-ivoire) !important; }
.mh-shell .mh-pied__lien:is(:hover, :focus-visible),
.mh-shell .mh-pied__wa:is(:hover, :focus-visible),
.mh-shell .mh-pied__partenaire:is(:hover, :focus-visible),
.mh-shell .mh-pied__vtc a:is(:hover, :focus-visible) { color: var(--c-ivoire) !important; }
.mh-shell .mh-pied__reseau:is(:hover, :focus-visible) { color: var(--c-laiton) !important; }

/* — Barre d'accès mobile (un <nav>) et bouton flottant — */
.mh-shell .mh-barre__lien       { color: var(--c-gris-chaud) !important; }
.mh-shell .mh-barre__lien--actif { color: var(--c-laiton) !important; }
.mh-shell .mh-barre__lien--cta,
.mh-shell .mh-barre__lien--cta.mh-barre__lien--actif { color: var(--c-encre-noir) !important; }
.mh-shell .mh-barre__lien:is(:hover, :focus-visible) { color: var(--c-ivoire) !important; }
.mh-shell .mh-barre__lien--cta:is(:hover, :focus-visible) { color: var(--c-encre-noir) !important; }
.mh-shell.mh-flottant { color: var(--c-laiton) !important; }
.mh-shell.mh-flottant:is(:hover, :focus-visible) { color: var(--c-encre-noir) !important; }

/* — Bandeau cookies et lien d'évitement — */
.mh-shell .mh-cookies__lien { color: var(--c-laiton) !important; }
.mh-shell .mh-cookies__ok   { color: var(--c-encre-noir) !important; }
.mh-shell .mh-cookies__lien:is(:hover, :focus-visible) { color: var(--c-ivoire) !important; }
.mh-shell.mh-evitement      { color: var(--c-ivoire) !important; }


/* ═══ 10.16  IMPRESSION — dernier mot ═══
   Repris ici, après le bouclier, et en !important : sans cela les encres
   claires ci-dessus s'imprimeraient sur du papier blanc. On ne masque que des
   commandes ; tout le texte du pied et de la barre reste imprimé, en noir. */

@media print {
  .mh-shell.mh-entete,
  .mh-shell.mh-pied,
  .mh-shell.mh-fil,
  .mh-shell.mh-menu    { background-color: transparent !important; }
  .mh-shell :is(.mh-nav__lien, .mh-nav__lien--actif, .mh-tel, .mh-tel__ico,
                .mh-lang, .mh-pied__lien, .mh-pied__lien--fort, .mh-pied__texte,
                .mh-pied__titre, .mh-pied__copy, .mh-pied__vtc, .mh-pied__vtc a,
                .mh-pied__vtc strong, .mh-pied__partenaire, .mh-pied__partenaires,
                .mh-pied__valeur, .mh-pied__label, .mh-fil__lien, .mh-fil__actuel,
                .mh-fil__sep, .mh-menu__lien) { color: #000 !important; }
  .mh-shell .mh-pied__lien i,
  .mh-shell .mh-pied__valeur i { color: #000 !important; }
}


/* ═══════════ 11-chrome-liquide ═══════════
   LA NAPPE DE MÉTAL EN FUSION — hero de l'accueil, et lui seul.
   -----------------------------------------------------------------------------
   CE QUE CE BLOC POSE : une couche décorative entre la photo et le panneau de
   texte, sa découpe, et son repli. Rien d'autre. Il ne touche à aucun texte,
   à aucune couleur d'encre, à aucune dimension de contenu.

   EMPILEMENT DU HERO (inchangé, seule la valeur 1 est nouvelle) :
       0  .mh-hero__media    la photo
       1  .mh-chrome         la nappe            ← ce bloc
       2  .mh-hero__panel    le texte
       3  .mh-hero__moulure  le filet de 1 px, qui reste le plus net de tous

   SÛRETÉ, point par point :
   · Le <canvas> est vide, aria-hidden et en pointer-events:none — il n'est ni
     lisible, ni cliquable, ni atteignable au clavier. Ce n'est pas du contenu.
   · Aucune règle de ce bloc ne pose opacity, visibility, display ni height sur
     un élément porteur de texte. Le seul opacity écrit ici vit sur un
     pseudo-élément décoratif, et il vaut 1 AU REPOS : il ne descend à 0 que
     lorsque la 3D a effectivement pris la main.
   · Sans JavaScript, sans WebGL ou en mouvement réduit, le canvas ne reçoit
     jamais de contexte de rendu : il ne peint rien, reste transparent, et le
     hero est exactement celui d'aujourd'hui — photo, dégradé cuir, filet.
   · La couche est hors flux (position: absolute) et ses dimensions viennent de
     ses décalages : elle ne peut décaler aucune mise en page (CLS = 0).
   · Deux découpes indépendantes garantissent que la nappe n'approche jamais la
     colonne de texte : le masque CSS ci-dessous, ET l'aplat cuir du panneau,
     qui est de toute façon au-dessus d'elle.
   Aucune couleur nouvelle : chrome clair #C9CDD2, chrome sourd #8A9096 et
   laiton #C8A96A viennent tous des jetons du bloc 01. */


/* --- 11.1  La couche ------------------------------------------------------
   `overflow: clip` et non `hidden` : hidden créerait un conteneur défilable.
   `contain` borne la mise en page et la peinture au cadre — le reste de la
   page ne repeint jamais à cause de la nappe. */
.ml-habitacle .mh-chrome {
  position: absolute;
  inset: 0;
  z-index: 1;
  overflow: clip;
  pointer-events: none;
  contain: layout paint;
}

/* --- 11.2  La toile
   Dimensions posées en pourcentage du cadre, jamais en unités de viewport : la
   barre d'URL mobile ne peut pas la faire respirer. Le fondu d'entrée est fait
   DANS le nuanceur (uniforme uOpacite), pas ici : la feuille ne contient donc
   aucune règle capable de masquer quoi que ce soit. */
.ml-habitacle .mh-chrome__toile {
  display: block;
  inline-size: 100%;
  block-size: 100%;
  border: 0;
}

/* --- 11.3  Le repli — l'état par défaut, celui qu'on voit sans JavaScript
   Un halo de chrome et une pointe de laiton, immobiles, posés du côté de la
   photo. Le hero garde sa matière quand la 3D ne tourne pas. Ce
   pseudo-élément est vide et décoratif : il ne porte aucun caractère. */
.ml-habitacle .mh-chrome::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background-image:
    radial-gradient(115% 68% at 78% 32%,
      rgba(201, 205, 210, .11) 0%, rgba(201, 205, 210, 0) 62%),
    radial-gradient(85% 52% at 62% 80%,
      rgba(200, 169, 106, .07) 0%, rgba(200, 169, 106, 0) 70%);
  transition: opacity var(--dur-3, 700ms)
              var(--ease-sortie, cubic-bezier(.16, 1, .3, 1));
}

/* La classe n'est posée par le module qu'une fois la première image rendue :
   les deux matières se croisent, aucun clignotement. */
.ml-habitacle .mh-chrome--actif::before { opacity: 0; }

/* --- 11.4  Découpe ≥ 1024 px — un seul plan
   Le panneau de texte occupe la moitié gauche sur un aplat cuir opaque. La
   nappe est masquée bien avant cette limite : même si le masque du nuanceur
   échouait, aucun reflet ne peut remonter sous une lettre. */
@media (min-width: 1024px) {
  .ml-habitacle .mh-chrome {
    -webkit-mask-image: linear-gradient(90deg,
      transparent 0%, transparent 44%, #000 64%, #000 100%);
            mask-image: linear-gradient(90deg,
      transparent 0%, transparent 44%, #000 64%, #000 100%);
  }
}

/* --- 11.5  Découpe < 1024 px — deux plans empilés
   Le texte est en haut, la photo dessous. La nappe ne vit que dans le bas du
   cadre, sur la photo, et s'éteint avant le filet de bas de section. */
@media (max-width: 1023.98px) {
  .ml-habitacle .mh-chrome {
    -webkit-mask-image: linear-gradient(180deg,
      transparent 0%, transparent 34%, #000 58%, #000 90%, transparent 100%);
            mask-image: linear-gradient(180deg,
      transparent 0%, transparent 34%, #000 58%, #000 90%, transparent 100%);
  }

  /* Le panneau reçoit en propre l'aplat cuir qu'il empruntait jusqu'ici à la
     section. Rigoureusement la même couleur : zéro changement visuel, mais le
     texte devient opposable — aucun reflet ne peut passer derrière lui. */
  .ml-habitacle .mh-hero__panel { background-color: var(--c-nuit); }
}

/* --- 11.6  Mouvement réduit
   Le module ne monte rien du tout dans ce cas : la couche reste au repli, et
   ce repli ne bouge pas. On coupe aussi sa transition, par principe. */
@media (prefers-reduced-motion: reduce) {
  .ml-habitacle .mh-chrome::before { transition: none; }
}

/* --- 11.7  Couleurs forcées et impression
   En couleurs forcées, un dégradé décoratif n'a plus de sens et brouillerait
   la lecture ; à l'impression, il gaspillerait de l'encre. On retire la
   couche : elle ne contient aucun texte, rien n'est perdu. */
@media (forced-colors: active) {
  .ml-habitacle .mh-chrome { display: none; }
}

@media print {
  .ml-habitacle .mh-chrome { display: none; }
}

/* --- 11.8  Défilement Lenis
   Feuille exigée par Lenis. Bornée à html/body : aucune autre règle du site
   n'est concernée, et les classes ne sont posées que lorsque le module a
   réellement démarré le défilement (grand écran, pointeur fin, mouvement non
   réduit). Sans JavaScript, aucune de ces classes n'existe. */
html.lenis,
html.lenis body            { block-size: auto; }
.lenis.lenis-smooth        { scroll-behavior: auto !important; }
.lenis.lenis-smooth [data-lenis-prevent] { overscroll-behavior: contain; }
.lenis.lenis-stopped       { overflow: clip; }
.lenis.lenis-smooth iframe { pointer-events: none; }


/* ═══════════ 12-prestation ═══════════
   Trois primitives utilisées par le gabarit de page prestation (/{slug}) et par
   lui seul. Elles se placent en DERNIÈRE position : à spécificité égale, la
   source la plus tardive tranche. Aucune ne pose display, visibility, opacity,
   position ni height — aucune ne peut donc masquer un texte.
   La couleur du texte n'est jamais déclarée ici : le bouclier impose déjà
   `color: inherit !important` sur p, li et les titres, et l'encre vient du
   modificateur de matière de la section. La déclarer serait perdre, ou pire,
   gagner avec une paire non mesurée. */

/* 12.1  PROSE ÉDITORIALE — le contenu rédactionnel venu de la base, une fois
   passé au filtre d'affichage du gabarit. Rythme vertical uniquement. */
.ml-habitacle .mh-prose {
  max-inline-size: var(--mesure-body);
  margin-block-start: var(--sp-6);
  font-size: var(--fs-body);
  line-height: 1.7;
}
.ml-habitacle .mh-prose > * + *      { margin-block-start: var(--sp-4); }
.ml-habitacle .mh-prose > h3         { margin-block-start: var(--sp-7); }
.ml-habitacle .mh-prose > :first-child { margin-block-start: 0; }
.ml-habitacle .mh-prose :is(ul, ol)  { padding-inline-start: var(--sp-5); }
.ml-habitacle .mh-prose li + li      { margin-block-start: var(--sp-2); }
.ml-habitacle .mh-prose li::marker   { color: var(--mh-lien); }

/* 12.2  CE QUE COMPREND LA PRESTATION — liste de cases cochées. Pistes bornées
   par minmax(0, …) : un libellé long n'élargit jamais la grille. */
.ml-habitacle .mh-inclus {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 260px), 1fr));
  column-gap: var(--sp-5);
  row-gap: var(--sp-2);
  margin: var(--sp-6) 0 0;
  padding: 0;
  list-style: none;
}
.ml-habitacle .mh-inclus__item {
  display: flex;
  align-items: flex-start;
  gap: var(--sp-2);
  min-inline-size: 0;
  min-block-size: 2.75rem;
  overflow-wrap: anywhere;
}
.ml-habitacle .mh-inclus__ico { color: var(--mh-lien); font-size: 1.25em; }

/* 12.3  GALERIE — toutes les images sont dans le flux et visibles. L'ancien
   carrousel gardait deux vues sur trois en display:none. */
.ml-habitacle .mh-galerie {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 260px), 1fr));
  gap: var(--gap-grille);
  margin-block-start: var(--sp-5);
}
.ml-habitacle .mh-galerie__fig { margin: 0; min-inline-size: 0; }
.ml-habitacle .mh-galerie__img {
  inline-size: 100%;
  aspect-ratio: 3 / 2;
  object-fit: cover;
  border: var(--filet) solid var(--mh-card-filet);
  border-radius: var(--r-1);
}


/* ═══════════ 12-prestations ═══════════
   PAGE PRESTATIONS (/services) — sommaire des familles et fiches illustrées.

   Ce bloc ne crée AUCUNE couleur : il ne consomme que les jetons de matière
   posés par .mh-s--cuir / --papier / --noyer (bloc 02.1), pour qu'une même
   fiche reste mesurée sur les trois fonds. Un seul !important, au § 12.9, et
   sur une COULEUR uniquement. Aucune règle sur display, visibility, opacity,
   position, height, max-height ni clip-path : rien ici ne peut masquer un
   texte, même par accident.

   Position : DERNIÈRE du fichier. À spécificité égale (0,2,0) il gagne donc
   sur « .mh-grid > * » (portées de grille) et sur le rembourrage de .mh-card,
   qui sont les deux seules primitives qu'il redéclare.
   ═══════════════════════════════════════════════════════════════════════════ */

/* 12.1 · HERO DE PAGE — le hero d'accueil vise 100svh ; sur un catalogue, le
   premier titre de famille doit rester atteignable sans un défilement complet.
   On abaisse le PLANCHER, jamais un plafond : le contenu pousse la boîte. */
.ml-habitacle .mh-hero--page { min-block-size: clamp(420px, 62svh, 620px); }


/* 12.2 · SOMMAIRE — six raccourcis vers les ancres de famille. Le conteneur
   est un <div role="navigation"> et JAMAIS un <nav> : une règle en ligne du
   site pose « html body nav a { color:#fff !important } », qui rendrait ces
   liens blancs — donc illisibles sur le papier ivoire. Les liens portent
   .mh-cible : cible de 48 px, et sortie du traitement de prose du § 02.7, qui
   pèse (0,2,2) et gagnerait sinon sur la couleur posée ici. */
.ml-habitacle .mh-sommaire__liste {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-3);                      /* 12 px */
  margin: var(--sp-6) 0 0;               /* 32 px : chapô → contenu */
  padding: 0;
  list-style: none;                      /* le gabarit pose role="list" */
}

.ml-habitacle .mh-sommaire__lien {
  display: inline-flex;
  align-items: center;
  flex-wrap: wrap;                       /* à 320 px le compte revient à la ligne */
  gap: var(--sp-2) var(--sp-3);
  min-block-size: var(--touche-min);     /* 48 px */
  max-inline-size: 100%;
  padding-block: var(--sp-2);
  padding-inline: var(--sp-4);
  border: var(--filet) solid var(--mh-card-filet);
  border-radius: var(--r-1);             /* 2 px, partout */
  color: var(--mh-txt);
  text-decoration: none;
  transition: border-color var(--dur-1) var(--ease-standard),
              color var(--dur-1) var(--ease-standard);
}

/* Trois signaux au survol et au focus, jamais la couleur seule : la limite se
   colore, l'encre passe au laiton de la matière, l'icône suit. */
.ml-habitacle .mh-sommaire__lien:is(:hover, :focus-visible) {
  border-color: var(--mh-lien);
  color: var(--mh-lien);
}

.ml-habitacle .mh-sommaire__ico {
  font-size: 1.25em;
  color: var(--mh-lien);
}

/* Le compte est celui des fiches réellement rendues plus bas : il est calculé
   à l'affichage, jamais saisi à la main. */
.ml-habitacle .mh-sommaire__nb {
  color: var(--mh-txt-2);
  font-size: var(--fs-small);
  font-variant-numeric: tabular-nums lining-nums;
}


/* 12.3 · EN-TÊTE DE FAMILLE — le lockup (tiret, eyebrow, H2, chapô) vient des
   primitives. N'est ajoutée que l'icône de famille, toujours doublée du titre
   écrit juste dessous, et le dernier intervalle du rythme : en-tête → grille. */
.ml-habitacle .mh-presta__entete { margin-block: 0 var(--sp-6); }

.ml-habitacle .mh-presta__ico {
  display: block;                        /* l'icône occupe sa ligne, au-dessus du H2 */
  margin-block-end: var(--sp-3);
  font-size: 2em;
  line-height: 1;
  color: var(--mh-lien);
}


/* 12.4 · LA GRILLE — le <ul> porte aussi .mh-grid : 4 / 8 / 12 pistes du
   socle. `span 4` vaut donc 1 fiche par rangée en mobile (défaut de
   .mh-grid > *), 2 dès 640 px, 3 dès 1024 px. Aucune règle « orpheline » : sur
   un catalogue, une dernière fiche étalée sur la rangée entière déséquilibre. */
.ml-habitacle .mh-presta__grille {
  gap: var(--sp-5);                      /* 24 px */
  margin: 0;
  padding: 0;
  list-style: none;
}

@media (min-width: 640px) {
  .ml-habitacle .mh-presta__item { grid-column: span 4; }
}

@media (min-width: 1024px) {
  .ml-habitacle .mh-presta__grille { gap: var(--sp-6); } /* 32 px */
}


/* 12.5 · LA FICHE — .mh-card fournit la surface, la limite mesurée ≥ 3:1 et la
   moulure d'arête haute (son ::before). Ici la photo vient à fleur des bords
   intérieurs : le rembourrage quitte la carte pour le corps. */
.ml-habitacle .mh-presta__item {
  padding: 0;
  gap: 0;
  transition: border-color var(--dur-1) var(--ease-standard);
}

/* `clip` et jamais `hidden` : hidden créerait un conteneur défilable. Seule la
   photo est bornée — la bague de focus du lien vit dans le corps, jamais ici. */
.ml-habitacle .mh-presta__media {
  margin: 0;
  overflow: clip;
}

/* Le 3:2 est tenu par le CSS ; width/height restent posés dans le HTML.
   L'aplat d'attente évite le trou blanc pendant le chargement différé. */
.ml-habitacle .mh-presta__photo {
  display: block;
  inline-size: 100%;
  block-size: auto;
  aspect-ratio: 3 / 2;
  object-fit: cover;
  background-color: var(--c-joint);
  transition: transform var(--dur-2) var(--ease-sortie);
}

/* Ordre visuel = ordre du DOM : titre → texte → lien. Aucun `order`. */
.ml-habitacle .mh-presta__corps {
  display: flex;
  flex: 1 1 auto;
  flex-direction: column;
  gap: var(--sp-3);                      /* 12 px */
  padding: var(--sp-5);                  /* 24 px */
}


/* 12.6 · LE LIEN — .mh-lien pose la couleur et le soulignement, .mh-cible la
   cible de 48 px. Ne restent que l'alignement en pied — pour que les liens de
   fiches de hauteurs différentes tombent sur la même ligne — et l'extension du
   clic à toute la fiche. Le pseudo-élément est VIDE (content: "") : aucun
   second lien dans l'arbre d'accessibilité, aucun piège au clavier. */
.ml-habitacle .mh-presta__lien { margin-block-start: auto; }

.ml-habitacle .mh-presta__lien::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: var(--r-1);
}

.ml-habitacle .mh-presta__fleche { font-size: 1.25em; }


/* 12.7 · ÉTATS — survol et focus clavier. :focus-within fait réagir la fiche
   quand son lien reçoit le focus. La bague bicolore des primitives reste seule
   maîtresse de l'indicateur. Trois signaux simultanés : la limite passe au
   laiton de la matière, le soulignement du lien double d'épaisseur (produit
   par .mh-lien, puisque survoler la fiche revient à survoler le lien étendu),
   et la photo avance très légèrement — un `transform`, rien d'autre : aucune
   réserve de place ne change, aucun texte ne se déplace. */
.ml-habitacle .mh-presta__item:is(:hover, :focus-within) {
  border-color: var(--mh-lien);
}

.ml-habitacle .mh-presta__item:is(:hover, :focus-within) .mh-presta__photo {
  transform: scale(1.03);
}


/* 12.8 · APPEL FINAL — même lockup que les autres sections ; seuls les boutons
   se mettent en ligne dès qu'il y a la place. Trois actions, aucune n'est un
   prix : le devis EST l'action. */
.ml-habitacle .mh-appel__actions {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: var(--sp-3);
  margin-block-start: var(--sp-6);
}

@media (min-width: 640px) {
  .ml-habitacle .mh-appel__actions {
    flex-direction: row;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--sp-4);
  }
}

.ml-habitacle .mh-appel__mention {
  margin-block-start: var(--sp-4);
  max-inline-size: var(--mesure-lead);
  color: var(--mh-txt-2);
  font-size: var(--fs-small);
}


/* 12.9 · Le compte du sommaire doit rester une encre SECONDAIRE. Le bouclier
   du § 99 pose « .ml-habitacle :is(…, span, …) { color: inherit !important } »
   pour neutraliser les 45 règles historiques qui forcent une couleur sombre
   sur les span : à !important égal, seule une spécificité supérieure repasse
   devant. (0,2,0) contre (0,1,1). C'est une COULEUR et rien d'autre — aucune
   propriété capable de masquer un texte n'est touchée, et la paire reste
   mesurée sur les trois matières (8,67:1 sur papier, 10,88:1 sur cuir). */
.ml-habitacle .mh-sommaire__nb { color: var(--mh-txt-2) !important; }



/* ═══════════ 13-ville ═══════════
   PAGE VILLE (/ville/{slug}) — complément, et rien de plus.

   La primitive `.mh-prose` existe déjà (bloc « 12-prestation ») : rythme
   vertical générique, listes, puces. Elle n'est PAS redéclarée ici — deux
   définitions du même rythme finiraient par diverger. Ce bloc n'ajoute que ce
   qu'elle ne couvre pas encore, parce que le fragment rédigé pour une commune
   contient, lui, des titres de rang 2 et des listes de définitions :

     — la respiration avant un <h2> (une page ville reçoit plusieurs sections
       rédigées, là où une fiche prestation n'en reçoit qu'une) ;
     — le couple <dt>/<dd> des questions-réponses écrites en base ;
     — une rangée de boutons hors hero, propre à ce gabarit.

   Aucun hex nouveau, aucun jeton nouveau, aucun !important. Aucune
   déclaration ne touche display, visibility, opacity, position, height,
   max-height ni clip-path : rien ici ne peut masquer un texte.
   Position : DERNIÈRE du fichier — à spécificité égale, la source la plus
   tardive tranche.
   ═══════════════════════════════════════════════════════════════════════════ */


/* ═══ 13.1  PROSE — compléments ═══ */

/* Un <h2> ouvre une nouvelle section rédigée : il respire plus qu'un <h3>.
   (0,1,2) — bat `.mh-prose > * + *` (0,1,1). Le premier enfant garde sa marge
   nulle : `.mh-prose > :first-child` pèse (0,2,0) et reste maître. */
.ml-habitacle .mh-prose > * + h2 { margin-block-start: var(--sp-8); }   /* 64px */
.ml-habitacle .mh-prose > * + :is(h4, h5, h6) { margin-block-start: var(--sp-6); }

/* Questions / réponses livrées en <dl> : le terme porte le poids, la réponse
   porte le filet. #D6CFC1 est un filet DÉCORATIF — il ne délimite aucune zone
   cliquable et ne porte aucune information. */
.ml-habitacle .mh-prose dt {
  margin-block-start: var(--sp-5);
  font-weight: 600;
}
.ml-habitacle .mh-prose dt:first-child { margin-block-start: 0; }
.ml-habitacle .mh-prose dd {
  margin-block-start: var(--sp-2);
  margin-inline-start: 0;
  padding-inline-start: var(--sp-4);
  border-inline-start: var(--filet) solid var(--c-filet-clair-decor);
}
.ml-habitacle .mh-s--cuir .mh-prose dd,
.ml-habitacle .mh-s--noyer .mh-prose dd {
  border-inline-start-color: var(--c-filet-decor);
}
.ml-habitacle .mh-prose blockquote {
  padding-inline-start: var(--sp-4);
  border-inline-start: var(--filet) solid var(--c-filet-clair-decor);
}


/* ═══ 13.2  LOCKUP ET RANGÉE D'ACTIONS ═══
   Mobile : une colonne, boutons pleine largeur — la cible de 48px vient du
   bloc 02. Dès 640px : en ligne, avec retour à la ligne. */

.ml-habitacle .mh-ville__lockup { margin-block-end: var(--sp-6); }

.ml-habitacle .mh-ville__actions {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: var(--sp-3);                    /* 12px */
  margin-block-start: var(--sp-6);     /* 32px */
}

@media (min-width: 640px) {
  .ml-habitacle .mh-ville__actions {
    flex-direction: row;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--sp-4);                  /* 16px */
  }
}

/* Le paragraphe de liaison qui suit la rangée d'actions. */
.ml-habitacle .mh-ville__actions + .mh-lead { margin-block-start: var(--sp-7); }


/* ═══ 13.3  SIX CARTES DE PRESTATION — rangée finale pleine ═══
   Le bloc 04.6 est écrit pour CINQ occasions : à partir de 1024px il donne une
   demi-colonne aux cartes 4 et 5, ce qui produit 3 + 2. Une page ville en
   reçoit six : la sixième resterait seule, en demi-largeur, sur sa propre
   rangée. Les trois sélecteurs ci-dessous ne se déclenchent QUE si la liste en
   compte exactement six (4e depuis le début ET 3e depuis la fin), ce qui rend
   la rangée de 3 + 3. Une liste de cinq — l'accueil — n'est pas touchée.
   (0,3,0) : postérieur et plus spécifique que 04.6 (0,2,0). */
@media (min-width: 1024px) {
  .ml-habitacle .mh-occasions__item:nth-child(4):nth-last-child(3),
  .ml-habitacle .mh-occasions__item:nth-child(5):nth-last-child(2),
  .ml-habitacle .mh-occasions__item:nth-child(6):nth-last-child(1) {
    grid-column: span 4;
  }
}


/* ═══════════ 14-journal ═══════════
   LE JOURNAL — la liste (/blog/) et le gabarit d'article (/blog/{slug}, les
   routes /en/… et les slugs racine hérités).

   Ce bloc ne crée AUCUNE couleur : il ne consomme que les jetons de matière
   posés par .mh-s--cuir / --papier / --noyer (bloc 02.1). Aucune règle sur
   display, visibility, opacity, position, height, max-height ni clip-path :
   rien ici ne peut masquer un texte, même par accident. Les seules règles
   `overflow` portent sur des conteneurs de média ou de tableau, jamais sur du
   texte, et emploient `clip` ou `auto` — jamais `hidden` sur un bloc de prose.

   Position : après le bloc 13, donc dernier du fichier. Il ne redéclare que
   les portées de grille et le rembourrage de .mh-card.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ═══ 14.1  BANDEAU DE FAITS — date de publication, temps de lecture ═══
   Deux faits vérifiables, jamais une note ni un compte d'avis. L'icône ne porte
   jamais seule l'information : elle double un libellé écrit. */

.ml-habitacle .mh-journal__meta {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-3) var(--sp-5);
  margin: var(--sp-6) 0 0;
  padding: 0;
  list-style: none;
  color: var(--mh-txt-2);
  font-size: var(--fs-small);
}

.ml-habitacle .mh-journal__meta-item {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
}

.ml-habitacle .mh-journal__meta-ico {
  font-size: 1.15em;
  color: var(--mh-lien);
}


/* ═══ 14.2  PROSE — compléments propres au corpus du journal ═══
   La primitive `.mh-prose` (bloc 12.1) fournit le rythme et la mesure. Ici :
   les trois formes que la base contient en plus d'un texte de prestation —
   un tableau, un dépliant de FAQ, un titre de niveau 2. */

.ml-habitacle .mh-journal__prose > * + h2 { margin-block-start: var(--sp-8); }
.ml-habitacle .mh-journal__prose h2 {
  font-family: var(--ff-texte);
  font-size: var(--fs-h3);
  font-weight: 600;
  line-height: 1.25;
  color: var(--mh-txt);
}
.ml-habitacle .mh-journal__prose h3 {
  font-family: var(--ff-texte);
  font-size: var(--fs-lead);
  font-weight: 600;
  line-height: 1.25;
  color: var(--mh-txt);
}

/* Le tableau déborde en largeur sur un téléphone : c'est LUI qui défile, jamais
   la page. `auto` et non `hidden` : rien n'est coupé, tout reste atteignable. */
.ml-habitacle .mh-prose__tableau {
  overflow-x: auto;
  margin-block-start: var(--sp-5);
  -webkit-overflow-scrolling: touch;
}
.ml-habitacle .mh-prose__tableau table {
  inline-size: 100%;
  border-collapse: collapse;
  font-size: var(--fs-small);
}
.ml-habitacle .mh-prose__tableau :is(th, td) {
  padding: var(--sp-2) var(--sp-3);
  border: var(--filet) solid var(--mh-card-filet);
  text-align: start;
  vertical-align: top;
}
.ml-habitacle .mh-prose__tableau th { font-weight: 600; color: var(--mh-txt); }

/* Dépliant de FAQ. Le gabarit pose TOUJOURS l'attribut `open` : la réponse est
   à l'écran au premier rendu, sans JavaScript. Aucune règle ici ne la masque —
   le visiteur peut refermer, la page ne le fait jamais pour lui. */
.ml-habitacle .mh-prose__depli {
  margin-block-start: var(--sp-4);
  padding: var(--sp-4);
  border: var(--filet) solid var(--mh-card-filet);
  border-radius: var(--r-1);
}
.ml-habitacle .mh-prose__depli > summary {
  cursor: pointer;
  color: var(--mh-txt);
  font-weight: 600;
  list-style: none;
}
.ml-habitacle .mh-prose__depli > summary::-webkit-details-marker { display: none; }
.ml-habitacle .mh-prose__depli > summary::before {
  content: "";
  display: inline-block;
  inline-size: 1.5rem;
  block-size: var(--filet);
  margin-inline-end: var(--sp-3);
  vertical-align: middle;
  background-color: var(--mh-lien);
}
.ml-habitacle .mh-prose__depli > :not(summary) { margin-block-start: var(--sp-3); }


/* ═══ 14.3  RAPPELS DE FIN D'ARTICLE — services, partage ═══
   Deux rangées de liens qui EXISTAIENT déjà dans l'ancien gabarit ; seul
   l'habillage change. Les jetons de cible (48 px) et de couleur viennent de
   .mh-sommaire__lien, réemployé tel quel. */

.ml-habitacle :is(.mh-journal__services, .mh-journal__partage) {
  max-inline-size: var(--mesure-body);
  margin-block-start: var(--sp-8);
}

.ml-habitacle :is(.mh-journal__services-titre, .mh-journal__partage-titre) {
  margin-block-start: var(--sp-5);
  font-family: var(--ff-texte);
  font-size: var(--fs-lead);
  font-weight: 600;
  line-height: 1.25;
  color: var(--mh-txt);
}

.ml-habitacle :is(.mh-journal__services-liste, .mh-journal__partage-liste) {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-3);
  margin: var(--sp-5) 0 0;
  padding: 0;
  list-style: none;
}


/* ═══ 14.4  FICHES D'ARTICLE — « à lire ensuite » et liste du journal ═══
   Le <ul> porte aussi .mh-grid : 4 / 8 / 12 pistes du socle. `span 4` vaut
   1 fiche par rangée en mobile, 2 dès 640 px, 3 dès 1024 px.
   UN SEUL lien par fiche : l'ancien gabarit en posait deux ou trois vers la
   même destination — la photo, le titre, puis « Lire la suite ». */

.ml-habitacle .mh-journal__grille {
  gap: var(--sp-5);
  margin: var(--sp-7) 0 0;
  padding: 0;
  list-style: none;
}

@media (min-width: 640px)  { .ml-habitacle .mh-journal__item { grid-column: span 4; } }
@media (min-width: 1024px) { .ml-habitacle .mh-journal__grille { gap: var(--sp-6); } }

.ml-habitacle .mh-journal__item {
  padding: 0;
  gap: 0;
  transition: border-color var(--dur-1) var(--ease-standard);
}

.ml-habitacle .mh-journal__lien {
  display: grid;
  grid-template-rows: auto 1fr auto;
  block-size: 100%;
  color: var(--mh-txt);
  text-decoration: none;
}

/* `clip` et jamais `hidden` : hidden créerait un conteneur défilable. */
.ml-habitacle .mh-journal__media {
  display: block;
  overflow: clip;
  aspect-ratio: 3 / 2;
}

.ml-habitacle .mh-journal__photo {
  inline-size: 100%;
  block-size: 100%;
  object-fit: cover;
  transition: transform var(--dur-2) var(--ease-standard);
}

.ml-habitacle .mh-journal__titre {
  display: block;
  padding: var(--sp-5) var(--sp-5) var(--sp-3);
  font-family: var(--ff-texte);
  font-size: var(--fs-h3);
  font-weight: 600;
  line-height: 1.3;
}

.ml-habitacle .mh-journal__date {
  display: block;
  padding-inline: var(--sp-5);
  color: var(--mh-txt-2);
  font-size: var(--fs-small);
}

.ml-habitacle .mh-journal__fleche {
  padding: var(--sp-3) var(--sp-5) var(--sp-5);
  color: var(--mh-lien);
  font-size: 1.25em;
}

/* Trois signaux au survol et au focus, jamais la couleur seule. */
.ml-habitacle .mh-journal__item:is(:hover, :focus-within) { border-color: var(--mh-lien); }
.ml-habitacle .mh-journal__lien:is(:hover, :focus-visible) .mh-journal__titre { color: var(--mh-lien); }
.ml-habitacle .mh-journal__item:hover .mh-journal__photo { transform: scale(1.03); }

@media (prefers-reduced-motion: reduce) {
  .ml-habitacle .mh-journal__photo { transition: none; }
  .ml-habitacle .mh-journal__item:hover .mh-journal__photo { transform: none; }
}


/* ═══ 14.5  LA LISTE — deux colonnes dès 1024 px ═══
   La colonne de gauche porte les douze fiches de la page courante ; celle de
   droite, les repères déjà présents dans l'ancienne barre latérale. */

.ml-habitacle .mh-journal__layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--sp-8);
}

@media (min-width: 1024px) {
  .ml-habitacle .mh-journal__layout {
    grid-template-columns: minmax(0, 1fr) minmax(0, 22rem);
    gap: var(--sp-7);
    align-items: start;
  }
}

.ml-habitacle .mh-journal__liste {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--sp-5);
  margin: 0;
  padding: 0;
  list-style: none;
}

@media (min-width: 640px) {
  .ml-habitacle .mh-journal__liste { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}


/* ═══ 14.6  REPÈRES LATÉRAUX — recherche, rubriques, publications, mots-clés ═══
   Volume BORNÉ : la page servait 379 liens, dont 251 rubriques. Les listes sont
   coupées à l'affichage, jamais dans la base ; toutes les URL restent servies et
   listées aux sitemaps. */

.ml-habitacle .mh-journal__aside {
  display: flex;
  flex-direction: column;
  gap: var(--sp-6);
}

.ml-habitacle .mh-journal__bloc {
  padding-block-start: var(--sp-5);
  border-block-start: var(--filet) solid var(--mh-card-filet);
}
.ml-habitacle .mh-journal__bloc:first-child {
  padding-block-start: 0;
  border-block-start: 0;
}

.ml-habitacle .mh-journal__bloc-titre {
  margin: 0 0 var(--sp-4);
  font-family: var(--ff-texte);
  font-size: var(--fs-lead);
  font-weight: 600;
  line-height: 1.25;
  color: var(--mh-txt);
}

.ml-habitacle .mh-journal__bloc-liste {
  display: flex;
  flex-direction: column;
  gap: var(--sp-1);
  margin: 0;
  padding: 0;
  list-style: none;
}

.ml-habitacle .mh-journal__bloc-lien {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  min-block-size: var(--touche-min);
  padding-block: var(--sp-2);
  color: var(--mh-txt);
  text-decoration: none;
  border-block-end: var(--filet) solid var(--mh-card-filet);
}
.ml-habitacle .mh-journal__bloc-lien:is(:hover, :focus-visible) { color: var(--mh-lien); }

.ml-habitacle .mh-journal__bloc-compte {
  color: var(--mh-txt-2);
  font-size: var(--fs-small);
  font-variant-numeric: tabular-nums lining-nums;
}

.ml-habitacle .mh-journal__mots {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2);
  margin: 0;
  padding: 0;
  list-style: none;
}

.ml-habitacle .mh-journal__mot {
  display: inline-flex;
  align-items: center;
  min-block-size: var(--touche-min);
  padding-block: var(--sp-2);
  padding-inline: var(--sp-4);
  border: var(--filet) solid var(--mh-card-filet);
  border-radius: var(--r-1);
  color: var(--mh-txt);
  font-size: var(--fs-small);
  text-decoration: none;
}
.ml-habitacle .mh-journal__mot:is(:hover, :focus-visible) {
  border-color: var(--mh-lien);
  color: var(--mh-lien);
}


/* ═══ 14.7  PAGINATION ═══
   Les URL sont celles de l'ancienne barre : « ?page=N », inchangées. */

.ml-habitacle .mh-journal__pages {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: var(--sp-3);
  margin-block-start: var(--sp-8);
  padding-block-start: var(--sp-6);
  border-block-start: var(--filet) solid var(--mh-card-filet);
}

.ml-habitacle .mh-journal__page {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  min-block-size: var(--touche-min);
  min-inline-size: var(--touche-min);
  justify-content: center;
  padding-inline: var(--sp-4);
  border: var(--filet) solid var(--mh-card-filet);
  border-radius: var(--r-1);
  color: var(--mh-txt);
  text-decoration: none;
  font-variant-numeric: tabular-nums lining-nums;
}
.ml-habitacle .mh-journal__page:is(:hover, :focus-visible) {
  border-color: var(--mh-lien);
  color: var(--mh-lien);
}
.ml-habitacle .mh-journal__page--actuelle {
  border-color: var(--mh-lien);
  color: var(--mh-lien);
  font-weight: 600;
}


/* ═══════════ 12-wow ═══════════
   « LA MOULURE COURT » — le filet chromé devient le fil qui coud les matières.
   Se concatène en DERNIÈRE position : chaque règle gagne par sa place dans la
   cascade, jamais par un !important, jamais par un sélecteur plus lourd que le
   bloc qu'elle complète.

   ┌─ CE BLOC N'ÉCRIT NULLE PART, SUR AUCUN SÉLECTEUR ────────────────────────┐
   │  opacity: 0   ·   visibility: hidden   ·   display: none                 │
   │  height: 0    ·   max-height: 0        ·   clip-path                     │
   │  text-indent négatif · font-size: 0 · -webkit-text-fill-color: transparent│
   └──────────────────────────────────────────────────────────────────────────┘
   Pas « pas sur du texte » : PAS DU TOUT. Le domaine est pénalisé par Google et
   du texte masqué y serait lu comme du cloaking ; c'est le piège qui a fait
   rater trois refontes de cette page. Une règle qui n'existe pas ne peut pas
   être appliquée au mauvais élément par un futur remaniement. Le seul geste de
   ce bloc, sur la matière comme sur le contenu, est `transform`.

   AUTRES INTERDITS TENUS : aucun hex nouveau (les jetons du bloc 01, plus du
   noir pur en canal alpha pour les masques et les ombres — qui n'est pas une
   encre) ; aucune animation de `width`, `height`, `top` ou `left` ; aucune URL
   changée ; aucune règle existante retirée ; les 16 paires de contraste
   mesurées sortent d'ici intactes.

   LES DEUX VOIES
     VOIE A — la matière : couches VIDES, `aria-hidden`, `pointer-events: none`,
     zéro caractère de texte. Elles se contentent d'un `scale`.
     VOIE B — le contenu : `transform` seul. L'état « avant » est 16 px plus
     bas, pas invisible. 16 px et pas 24 : 24 px est le défaut générique qui
     signe une page produite à la chaîne.

   LE VERROU
   Tout ce qui décale quoi que ce soit est enfermé sous `.ml-habitacle.mh-anime`.
   Cette classe n'est posée que par l'amorceur en ligne du gabarit, en JavaScript,
   et elle est RETIRÉE si le module ne répond pas. Sans JavaScript elle n'existe
   pas : aucune règle de décalage ne s'applique, la page est servie exactement à
   sa position finale. Le test « JavaScript coupé » est donc vrai par
   construction, et non par vigilance.

   MOUVEMENT RÉDUIT
   Le § 6 du socle écrase déjà tous les `--dur-*` à 1 ms. Chaque durée ci-dessous
   est écrite en `var(--dur-*)` : la conformité est automatique, sans une seule
   media query supplémentaire. Le § 12.9 et le module ajoutent deux ceintures.
   ═══════════════════════════════════════════════════════════════════════════ */


/* ═══ 12.1  JETONS DU BLOC — ombres et grain, rien d'autre ═══ */

.ml-habitacle {

  /* Ombres douces multi-couches — deux plans, jamais un box-shadow brut. C'est
     du cuir nuit #0E0D0C en alpha, pas une teinte nouvelle. Elles n'existent
     qu'au survol et ne portent jamais une limite ni un état : sur cette page
     les limites sont des filets de 1 px mesurés, et rien d'autre. */
  --ombre-proche: 0 1px 2px rgba(14, 13, 12, .30), 0 1px 1px rgba(14, 13, 12, .22);
  --ombre-levee:  0 8px 24px rgba(14, 13, 12, .34), 0 2px 6px rgba(14, 13, 12, .26);

  /* Grain de cuir. Le bloc 01 déclare `--grain-cuir: none` avec ce commentaire :
     « tuile non livrée ; le jeton existe, pas de var fantôme ». On la livre, en
     ligne, sans une requête de plus. Elle est consommée par
     `.mh-hero__panel::before` — couche vide, `pointer-events: none`, opacité .07
     posée par le bloc 03 : elle ne peut toucher aucun texte. La règle 11.2 la
     coupe déjà en contraste renforcé. */
  --grain-cuir:
    url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20width='180'%20height='180'%3E%3Cfilter%20id='g'%3E%3CfeTurbulence%20type='fractalNoise'%20baseFrequency='0.82'%20numOctaves='3'%20stitchTiles='stitch'/%3E%3C/filter%3E%3Crect%20width='180'%20height='180'%20filter='url(%23g)'/%3E%3C/svg%3E");
}


/* ═══ 12.2  LES SIX SECTIONS — support des couches, sans un pixel de décalage ═══
   `position: relative` : indispensable, les couches sont hors flux.
   `overflow: clip` et JAMAIS `hidden` : `hidden` créerait un conteneur de
   défilement, donc une barre fantôme et un piège au clavier.
   Le contenu passe explicitement au-dessus : sans cette seconde règle, une
   couche positionnée peindrait PAR-DESSUS le texte — l'ordre de peinture place
   les descendants positionnés après les blocs en flux. C'est le seul vrai
   danger de cette technique, et il se règle ici, une fois. */

.ml-habitacle :is(.mh-occasions, .mh-flotte, .mh-etapes, .mh-zones, .mh-faq, .mh-devis) {
  position: relative;
  overflow: clip;
}

.ml-habitacle :is(.mh-occasions, .mh-flotte, .mh-etapes, .mh-zones, .mh-faq, .mh-devis) > .mh-wrap {
  position: relative;
  z-index: 1;
}


/* ═══ 12.3  LA JONCTION — le geste, six fois ═══
   Le hero porte déjà la sienne (bloc 03.8) : c'est la première. Les cinq autres
   se posent à chaque changement de matière — cuir → papier, papier → cuir,
   cuir → papier, papier → cuir, cuir → noyer. Le même geste, six fois, jamais
   un geste différent : c'est ce qui fait « maison » plutôt que « bibliothèque
   d'effets ».
   `var(--mh-moulure)` est lu sur la SECTION : sur papier ivoire la jonction
   bascule donc d'elle-même sur le laiton foncé #7A5A22 (5,6:1), jamais sur le
   chrome clair, qui y tomberait à 1,5:1. Aucune couleur n'est écrite ici. */

.ml-habitacle .mh-jonction {
  position: absolute;
  inset-block-start: 0;
  inset-inline: 0;
  z-index: 2;                       /* au-dessus de la matière ET du contenu */
  block-size: var(--filet);         /* 1 px, jamais 2 */
  overflow: clip;                   /* borne la lueur */
  pointer-events: none;
  background-image: var(--mh-moulure);
}

/* La lueur hérite du dégradé de la jonction : aucun second dégradé, aucune
   couleur nouvelle. Élément vide, `aria-hidden`, au repos hors cadre. */
.ml-habitacle .mh-jonction__reflet {
  position: absolute;
  inset-block: 0;
  inset-inline-start: 0;
  inline-size: 40%;
  background-image: inherit;
  transform: translateX(-30%);
}

/* Le tracé : depuis le centre vers les deux bords. */
.ml-habitacle.mh-anime .mh-jonction {
  transform: scaleX(0);
  transform-origin: 50% 50%;
  transition: transform var(--dur-3) var(--ease-sortie);
}

.ml-habitacle.mh-anime .mh-jonction.in { transform: none; }

/* Puis la lueur, UNE fois, après le tracé. Le keyframe est celui du hero,
   `mh-hero-reflet`, repris à l'identique — aucun nouveau, pour que le geste
   soit littéralement le même. Un seul passage : rien ne boucle sur cette page
   (WCAG 2.2.2), et l'observateur se déconnecte juste après. */
.ml-habitacle.mh-anime .mh-jonction.in .mh-jonction__reflet {
  animation: mh-hero-reflet var(--dur-4) var(--ease-standard) 1 both;
  animation-delay: var(--dur-3);
}


/* ═══ 12.4  LA MATIÈRE — cuir capitonné, noyer veiné ═══
   Couches strictement décoratives : vides, `aria-hidden`, `pointer-events:
   none`. Elles n'utilisent malgré tout que `transform` — voir l'encadré en
   tête de bloc.
   Hauteur plafonnée et fondu bas : le capitonnage se concentre en haut de
   section puis s'éteint. Décision de dessin ET plafond mémoire — une nappe
   pleine hauteur promue en couche composite coûte ~9,6 Mo de texture par
   section en DPR 2,6 ; quatre sections cuir sortiraient à ~38 Mo, que Chrome
   peut décider de dé-promouvoir en pleine animation. C'est exactement le
   saccadement qu'on cherchait à éviter. */

.ml-habitacle .mh-matiere {
  position: absolute;
  inset-block-start: -1px;
  inset-inline: -1px;
  z-index: 0;
  block-size: min(100%, 720px);
  overflow: clip;
  pointer-events: none;
  /* Masque : du noir pur en canal alpha, pas une encre de la palette. */
  -webkit-mask-image: linear-gradient(to bottom, black 0%, black 58%, transparent 100%);
          mask-image: linear-gradient(to bottom, black 0%, black 58%, transparent 100%);
}

/* La nappe intérieure : c'est elle que GSAP fait dériver sur desktop. Deux
   éléments imbriqués parce que deux pilotes différents ne doivent jamais
   écrire dans la même propriété `transform` — le CSS tient le tassement, le
   JavaScript tient la dérive. La marge verticale de 4 % absorbe les ±1,6 % de
   dérive sans jamais découvrir un bord. */
.ml-habitacle .mh-matiere__nappe {
  position: absolute;
  inset-block: -4%;
  inset-inline: 0;
  display: block;
  background-image: var(--capitonnage);
}

/* Le veinage du noyer — la section de conversion, donc le seul dessin sur
   mesure de la page. SVG en ligne, sans un caractère. La couleur des tracés
   est posée ICI et non dans le gabarit : les trois modes de repli du § 12.9
   n'ont alors qu'une seule ligne à neutraliser.
   Surtout PAS de `stroke-dashoffset` : ce n'est pas un `transform`, ça repeint
   le SVG à chaque trame. */
.ml-habitacle .mh-matiere__veinage {
  position: absolute;
  inset-block: -4%;
  inset-inline: 0;
  display: block;
  inline-size: 100%;
  block-size: 108%;
}

.ml-habitacle .mh-matiere__veinage path {
  fill: none;
  stroke: rgba(242, 237, 228, .05);   /* ivoire du bloc 01, en alpha */
  stroke-width: 1;
  vector-effect: non-scaling-stroke;
}

/* Entrée : le losange se resserre, le cuir se boutonne. 700 ms, une fois.
   Le fond est rasterisé UNE fois puis simplement transformé — on n'anime
   jamais `background-size`, qui repeindrait à chaque trame. */
.ml-habitacle.mh-anime .mh-matiere {
  transform: scale(1.08);
  transition: transform var(--dur-3) var(--ease-sortie);
}

.ml-habitacle.mh-anime .mh-matiere.in { transform: none; }

/* Le noyer prend son veinage : même geste, amplitude plus courte. */
.ml-habitacle.mh-anime .mh-matiere--noyer { transform: scale(1.04) translateY(8px); }
.ml-habitacle.mh-anime .mh-matiere--noyer.in { transform: none; }

/* Sous 768 px : on coupe le SCALE et on garde la texture. Le mobile garde la
   matière, il perd un tassement de 700 ms qu'il n'aurait pas vu — et la nappe
   n'est jamais promue en couche composite sur les machines qui le paient. */
@media (max-width: 767.98px) {
  .ml-habitacle.mh-anime :is(.mh-matiere, .mh-matiere--noyer),
  .ml-habitacle.mh-anime :is(.mh-matiere, .mh-matiere--noyer).in {
    transform: none;
    transition: none;
  }
  .ml-habitacle .mh-matiere { block-size: min(100%, 560px); }
}

/* `will-change` n'est JAMAIS laissé en dur dans la feuille : le module le pose
   sur l'élément le temps du geste et le retire au `transitionend`. La seule
   exception est la dérive continue, qui n'existe que quand GSAP a réellement
   pris la main — la classe est posée par le module et retirée s'il se démonte. */
.ml-habitacle.mh-derive .mh-matiere__nappe,
.ml-habitacle.mh-derive .mh-matiere__veinage { will-change: transform; }


/* ═══ 12.5  VOIE B — LE CONTENU ═══
   La règle opposable du concept, en quatre lignes. Aucune opacité, ni ici ni
   ailleurs : le texte est à pleine opacité dans le HTML servi, à pleine
   opacité sans JavaScript, à pleine opacité pendant l'animation. Ce qui bouge,
   c'est sa position — de 16 px, une fois.
   L'échelonnement est posé par le module en style en ligne (60 ms de pas,
   plafond 240 ms) : sans JavaScript il n'y a ni décalage ni retard. */

.ml-habitacle.mh-anime [data-mh-reveal] {
  transform: translateY(16px);
  transition: transform var(--dur-2) var(--ease-sortie);
}

.ml-habitacle.mh-anime [data-mh-reveal].in { transform: none; }


/* ═══ 12.6  MICRO-INTERACTIONS — tout élément cliquable ═══
   On ne touche AUCUNE couleur déjà mesurée : les trois paires de boutons du
   bloc 02.6 et les encres de liens du bloc 10.15 sortent d'ici inchangées. Ce
   qui s'ajoute est du mouvement, et une ombre qui n'existe qu'au survol.
   La bague de focus reste celle du § 5 du socle — cuir 0→3 px puis ivoire
   3→5 px, la seule paire qui dépasse 3:1 sur les trois matières. Aucune règle
   ci-dessous ne la recouvre : `box-shadow` au survol, `outline` au focus. */

.ml-habitacle .mh-btn {
  transition: background-color var(--dur-1) var(--ease-standard),
              border-color     var(--dur-1) var(--ease-standard),
              color            var(--dur-1) var(--ease-standard),
              transform        var(--dur-1) var(--ease-sortie),
              box-shadow       var(--dur-2) var(--ease-sortie);
}

.ml-habitacle .mh-btn:is(:hover, :focus-visible):not([aria-disabled="true"]) {
  transform: translateY(-1px);
  box-shadow: var(--ombre-levee);
}

.ml-habitacle .mh-btn:active:not([aria-disabled="true"]) {
  transform: translateY(0) scale(.985);
  box-shadow: var(--ombre-proche);
}

/* Les cartes d'occasion. La limite reste portée par la bordure mesurée : au
   survol elle passe à l'encre de lien de la section — 8,6:1 sur cuir. Le
   `:focus-within` fait vivre la carte quand on arrive au clavier sur le lien
   qui la recouvre : sans lui, un visiteur au clavier ne verrait jamais l'état
   que le visiteur à la souris voit. */
.ml-habitacle .mh-card {
  transition: transform    var(--dur-2) var(--ease-sortie),
              border-color var(--dur-1) var(--ease-standard),
              box-shadow   var(--dur-2) var(--ease-sortie);
}

.ml-habitacle .mh-occasions__item:is(:hover, :focus-within) {
  transform: translateY(-2px);
  border-color: var(--mh-lien);
  box-shadow: var(--ombre-levee);
}

/* La flèche avance de 4 px — le seul mouvement qui dit « ça continue ». */
.ml-habitacle .mh-occasions__fleche {
  transition: transform var(--dur-1) var(--ease-sortie);
}
.ml-habitacle .mh-occasions__item:is(:hover, :focus-within) .mh-occasions__fleche {
  transform: translateX(4px);
}

/* Les fiches de la flotte vivent sur papier ivoire : pas d'ombre portée sur du
   papier, ce serait un faux relief. Le filet se resserre, c'est tout. */
.ml-habitacle .mh-flotte__fiche {
  transition: border-color var(--dur-1) var(--ease-standard);
}
.ml-habitacle .mh-flotte__fiche:is(:hover, :focus-within) {
  border-color: var(--mh-lien);       /* laiton foncé 5,6:1 sur papier */
}

/* Liens de prose : le souligné s'épaissit et s'écarte. Aucune couleur ne
   change — les encres de lien sont mesurées section par section. */
.ml-habitacle .mh-lien {
  transition: color                     var(--dur-1) var(--ease-standard),
              text-decoration-thickness var(--dur-1) var(--ease-standard),
              text-underline-offset     var(--dur-1) var(--ease-standard);
}
.ml-habitacle .mh-lien:is(:hover, :focus-visible) {
  text-decoration-thickness: 2px;
  text-underline-offset: 4px;
}

/* Sélection de texte : laiton et encre noire, une paire déjà mesurée à 8,3:1
   par le bouton --or. */
.ml-habitacle ::selection {
  background-color: var(--c-laiton);
  color: var(--c-encre-noir);
}


/* ═══ 12.7  ÉTAT « ENVOI » DU FORMULAIRE ═══
   Le succès et l'erreur sont rendus par le serveur : ils survivent à un
   JavaScript coupé, et ils ne sont pas de mon ressort. Il manquait le seul
   état qui n'existe que dans le navigateur. Le nœud `.mh-devis__etat` est CRÉÉ
   à la soumission : au repos il n'est pas dans le document — rien n'est masqué,
   il n'y a rien à masquer. C'est la même discipline que le reste du bloc. */

.ml-habitacle .mh-devis__etat {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  margin: var(--sp-4) 0 0;
  font-size: var(--fs-small);
  color: var(--c-gris-chaud);         /* 7,7:1 sur noyer */
}

.ml-habitacle .mh-devis__form--envoi .mh-devis__envoyer { cursor: progress; }

/* Le rouet : décoratif et `aria-hidden`. L'information est portée par le texte
   de la zone `role="status"`, jamais par l'icône seule. Borné à 20 tours — la
   page a navigué bien avant, et rien ne tourne indéfiniment sur ce site. En
   mouvement réduit, le § 6 du socle le fige et le texte suffit. */
.ml-habitacle .mh-btn__rouet {
  display: inline-flex;
  inline-size: 1em;
  block-size: 1em;
  font-size: 1.15em;
  line-height: 1;
  animation: mh-rouet var(--dur-4) linear 20 both;
}

@keyframes mh-rouet { to { transform: rotate(360deg); } }

/* Résumé d'erreurs et confirmation : un filet de 3 px côté départ, pour que le
   bloc se repère sans compter sur la seule couleur (critère 1.4.1). Les
   bordures d'origine restent, on ne fait qu'en épaissir un côté. */
.ml-habitacle .mh-devis__resume {
  border-inline-start-width: 3px;
  box-shadow: var(--ombre-proche);
}

.ml-habitacle .mh-devis__confirmation {
  border-inline-start-width: 3px;
  border-inline-start-color: var(--c-laiton);   /* 6,1:1 sur noyer */
  box-shadow: var(--ombre-proche);
}


/* ═══ 12.8  ÉTAT VIDE — la flotte sans véhicule en base ═══
   Un écran vide n'est pas une panne, c'est une invitation à agir : on nomme ce
   qui manque et on donne la sortie. Aucun chiffre, aucune promesse, aucun
   véhicule inventé. */

.ml-habitacle .mh-etat-vide {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--sp-4);
  margin-block-start: var(--sp-6);
  padding: var(--sp-6);
  border: var(--filet) solid var(--mh-card-filet);
  border-radius: var(--r-1);
}

.ml-habitacle .mh-etat-vide__ico {
  inline-size: 28px;
  block-size: 28px;
  font-size: 28px;
  line-height: 1;
  color: var(--mh-btn2);
}

.ml-habitacle .mh-etat-vide__texte {
  margin: 0;
  max-inline-size: var(--mesure-lead);
  color: var(--mh-txt-2);
  text-wrap: pretty;
}


/* ═══ 12.9  REPLIS — les quatre modes où tout ceci doit s'effacer proprement ═══
   Aucune de ces règles n'utilise `display`, `visibility` ni `opacity` : on
   éteint un dégradé, un fond ou un tracé, jamais un élément. */

/* Mouvement réduit. Le § 6 met déjà toutes les durées à 1 ms ; on remet en plus
   chaque état « avant » à sa position finale, pour qu'aucun contenu ne reste
   décalé de 16 px si le module n'a pas pu retirer `.mh-anime`. */
@media (prefers-reduced-motion: reduce) {

  .ml-habitacle.mh-anime [data-mh-reveal],
  .ml-habitacle.mh-anime [data-mh-reveal].in,
  .ml-habitacle.mh-anime .mh-jonction,
  .ml-habitacle.mh-anime .mh-jonction.in,
  .ml-habitacle.mh-anime .mh-matiere,
  .ml-habitacle.mh-anime .mh-matiere.in,
  .ml-habitacle.mh-anime .mh-matiere--noyer,
  .ml-habitacle.mh-anime .mh-matiere--noyer.in {
    transform: none;
    transition: none;
  }

  .ml-habitacle .mh-jonction__reflet,
  .ml-habitacle.mh-anime .mh-jonction.in .mh-jonction__reflet,
  .ml-habitacle .mh-btn__rouet { animation: none; }

  .ml-habitacle .mh-btn:is(:hover, :focus-visible):not([aria-disabled="true"]),
  .ml-habitacle .mh-btn:active:not([aria-disabled="true"]),
  .ml-habitacle .mh-occasions__item:is(:hover, :focus-within),
  .ml-habitacle .mh-occasions__item:is(:hover, :focus-within) .mh-occasions__fleche {
    transform: none;
  }
}

/* Couleurs forcées. Un dégradé n'y est pas peint : la jonction disparaîtrait
   sans laisser de trace. On la rend en BORDURE — seule propriété que ce mode
   conserve — et on retire les ombres, qui n'y veulent plus rien dire. La lueur
   hérite du dégradé éteint : elle s'efface d'elle-même. */
@media (forced-colors: active) {

  .ml-habitacle .mh-jonction {
    background-image: none;
    border-block-start: 1px solid CanvasText;
  }

  .ml-habitacle .mh-matiere__nappe { background-image: none; }
  .ml-habitacle .mh-matiere__veinage path { stroke: none; }

  .ml-habitacle .mh-btn:is(:hover, :focus-visible),
  .ml-habitacle .mh-occasions__item:is(:hover, :focus-within),
  .ml-habitacle .mh-devis__resume,
  .ml-habitacle .mh-devis__confirmation { box-shadow: none; }
}

/* Contraste renforcé : le grain de cuir est déjà coupé par la règle 11.2 sur le
   pseudo-élément. On coupe en plus le capitonnage et le veinage, qui ajoutent
   du bruit sous un texte que l'utilisateur cherche justement à mieux lire. */
@media (prefers-contrast: more) {
  .ml-habitacle .mh-matiere__nappe { background-image: none; }
  .ml-habitacle .mh-matiere__veinage path { stroke: none; }
}

/* Impression : rien de tout ceci n'existe sur papier. */
@media print {

  .ml-habitacle .mh-matiere__nappe { background-image: none; }
  .ml-habitacle .mh-matiere__veinage path { stroke: none; }
  .ml-habitacle .mh-btn__rouet { animation: none; }

  .ml-habitacle .mh-jonction {
    background-image: none;
    border-block-start: 1px solid var(--c-encre);
  }

  .ml-habitacle.mh-anime [data-mh-reveal],
  .ml-habitacle.mh-anime [data-mh-reveal].in { transform: none; }

  .ml-habitacle :is(.mh-btn, .mh-card, .mh-devis__resume, .mh-devis__confirmation) {
    box-shadow: none;
  }
}


/* ═══════════ 12.10 — RECETTE ═══════════
   DEUX HÉRITAGES QUI CONTREDISENT LA REFONTE. Ajouté en dernière position,
   comme le bloc 12-wow : chaque règle gagne par sa place dans la cascade,
   jamais par un !important. Aucune couleur nouvelle, aucun masquage, aucune
   URL touchée, rien de retiré. Ces deux règles ne sortent jamais des pages
   Habitacle : cette feuille n'est émise que là (partials/header.php).

   ── 12.10.a  L'EN-TÊTE EST « sticky », PAS « fixed » ──────────────────────
   `style-moderne.css` pose `main { margin-top: 70px }` : la compensation d'un
   en-tête FIXE, hors flux, qui n'existe plus. `.mh-shell.mh-entete` est
   `position: sticky` et occupe déjà ses 72 px DANS le flux. Les deux se
   cumulaient — 72 + 70 = 142 px avant le hero — dont 70 px de bande vide entre
   le filet chromé de la barre et l'arête haute du hero.
   Effet de bord mesuré, plus grave que la bande : le hero vise
   `clamp(640px, 100svh, 860px)` pour tenir dans l'écran ; poussé de 142 px, son
   arête basse — donc sa moulure, la signature de la page — tombait sous la
   ligne de flottaison dès 900 px de haut.

   ── 12.10.b  LE DÉFILEMENT DOUX DOIT S'ARRÊTER EN MOUVEMENT RÉDUIT ────────
   Le § 6 écrit `scroll-behavior: auto` sur `.ml-habitacle`. C'est un <div> :
   il ne défile pas, la valeur n'y produit rien. L'élément qui défile est
   `html`, et il garde le `scroll-behavior: smooth` de `style-moderne.css`.
   Mesuré : lien d'évitement, sommaire et ancres de FAQ défilaient encore en
   animation pour quelqu'un qui a demandé qu'on arrête de bouger. On coupe à la
   racine, là où la propriété est lue. */

body.mh-page main { margin-block-start: 0; }

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


/* ═══ 13-captcha ═══
   Verification anti-robot maison. C'est du TEXTE, donc lisible par un lecteur
   d'ecran et associe a son champ — contrairement a une image de captcha. */
.ml-habitacle .mh-captcha,
.mh-shell .mh-captcha {
  margin-block: var(--sp-5, 24px);
  padding: var(--sp-4, 16px);
  border: 1px solid var(--c-chrome-sourd, #8A9096);
  border-radius: var(--r-1, 2px);
  background-color: var(--c-surface, #1A1714);
}
.mh-captcha__label {
  display: block;
  font-family: var(--ff-texte, Archivo, sans-serif);
  font-size: var(--fs-label, .8125rem);
  font-weight: 600;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--c-chrome-clair, #C9CDD2);
  margin-block-end: var(--sp-2, 8px);
}
.mh-captcha__question {
  font-family: var(--ff-display, "Bodoni Moda", Georgia, serif);
  font-size: 1.5rem;
  line-height: 1.3;
  color: var(--c-ivoire, #F2EDE4);
  margin-block: 0 var(--sp-3, 12px);
}
.mh-captcha__champ {
  inline-size: 100%;
  max-inline-size: 240px;
  min-block-size: 48px;
  padding: var(--sp-3, 12px);
  border: 1px solid var(--c-chrome-sourd, #8A9096);
  border-radius: var(--r-1, 2px);
  background-color: var(--c-nuit, #0E0D0C);
  color: var(--c-ivoire, #F2EDE4);
  font-family: var(--ff-texte, Archivo, sans-serif);
  font-size: 1rem;
}
.mh-captcha__champ:focus-visible {
  outline: 2px solid var(--c-ivoire, #F2EDE4);
  outline-offset: 2px;
  border-color: var(--c-chrome-clair, #C9CDD2);
}
.mh-captcha__aide {
  margin-block: var(--sp-2, 8px) 0;
  font-size: var(--fs-small, .875rem);
  color: var(--c-gris-chaud, #C9C1B4);
}
/* Sur fond papier, l'encre s'inverse : le chrome clair y serait illisible. */
.mh-s--papier .mh-captcha { background-color: #FFFFFF; border-color: var(--c-taupe, #4A423A); }
.mh-s--papier .mh-captcha__label { color: var(--c-taupe, #4A423A); }
.mh-s--papier .mh-captcha__question,
.mh-s--papier .mh-captcha__champ { color: var(--c-encre, #1A1714); }
.mh-s--papier .mh-captcha__champ { background-color: #FFFFFF; }
.mh-s--papier .mh-captcha__aide { color: var(--c-taupe, #4A423A); }