/* ==========================================================================
   Mécaly — site vitrine
   Refonte alignée sur le design réel de l'app mobile (captures qa/captures/rn)
   - fond de page oklch(0.972 0.005 258.33) (#F4F6F9), léger halo lumineux en haut
   - grandes cartes blanches radius 24-28, ombres navy multicouches très douces
   - CTA principal = pilule NAVY pleine, texte blanc 700 terminé par un point
     orange (signature du logo « mécaly. », reprise des boutons de l'app :
     « Accepter. », « Voir la proposition. »). Contraste blanc/navy ≥ 12:1.
   - CTA secondaire = pilule outline navy sur blanc.
   - l'orange est l'ACCENT : kicker, liens texte, « Publier », PRIX (la loi de
     la marque : l'orange marque le prix), labels actifs, badges, points.
     L'orange marque = #F05000 : oklch(0.646 0.207 38.94) ; en petit corps sur
     blanc on passe par --brand-text (4.5:1).
   - cartes prestation : photo plein cadre + overlay navy + titre blanc 800 +
     pilule claire translucide « Publier → » texte orange
   - statuts : pastilles OUTLINE (vert Acceptée/Terminé), ambre plein En attente
   ========================================================================== */

/* ---------- Fonts (Poppins local, latin subset) ---------- */
@font-face{font-family:'Poppins';font-style:normal;font-weight:400;font-display:swap;src:url(../assets/fonts/poppins-400.woff2) format('woff2');}
@font-face{font-family:'Poppins';font-style:normal;font-weight:500;font-display:swap;src:url(../assets/fonts/poppins-500.woff2) format('woff2');}
@font-face{font-family:'Poppins';font-style:normal;font-weight:600;font-display:swap;src:url(../assets/fonts/poppins-600.woff2) format('woff2');}
@font-face{font-family:'Poppins';font-style:normal;font-weight:700;font-display:swap;src:url(../assets/fonts/poppins-700.woff2) format('woff2');}
@font-face{font-family:'Poppins';font-style:normal;font-weight:800;font-display:swap;src:url(../assets/fonts/poppins-800.woff2) format('woff2');}

/* ---------- Tokens (DESIGN.md app, exprimés en oklch — mêmes couleurs rendues) ---------- */
:root{
  --navy:oklch(0.242 0.061 259.51);             /* #0D1F3C */
  --brand:oklch(0.646 0.207 38.94);             /* #F05000 — l'orange marque, inchangé */
  --brand-press:oklch(0.598 0.191 39.19);       /* #D84800 */
  --brand-cta:oklch(0.588 0.207 38.94);         /* fond CTA : blanc 4.5:1 (AA texte < 19px) */
  --brand-cta-press:oklch(0.548 0.191 39.19);   /* CTA pressé/hover */
  --brand-text:oklch(0.57 0.207 38.94);         /* texte orange petit sur fond clair : 4.5:1 */
  --brand-text-strong:oklch(0.53 0.19 38.94);   /* idem sur surface légèrement teintée : 5.4:1 */
  --brand-tint:oklch(0.951 0.025 53.69);        /* #FDEBE0 */
  --brand-hero:oklch(0.705 0.195 40);           /* orange éclairci pour texte sur navy (~5.7:1, teinte conservée) */
  --bg:oklch(0.972 0.005 258.33);               /* #F4F6F9 */
  --surface:oklch(1 0 0);
  --hairline:oklch(0.93 0.007 260.73);          /* #E5E8ED */
  --muted:oklch(0.242 0.061 259.51 / .65);      /* AA sur fond clair en petit corps (4.8:1) */
  --success:oklch(0.627 0.17 149.21);           /* #16A34A */
  --success-text:oklch(0.513 0.17 149.21);      /* texte vert petit sur fond clair : 4.5:1 */
  --success-bg:oklch(0.955 0.018 161.12);       /* #E6F4EC */
  --warning:oklch(0.61 0.13 72.3);              /* #B27400 */
  --warning-bg:oklch(0.97 0.029 82.6);          /* #FFF4E0 */
  /* ombres multicouches : une petite serrée + une large diffuse */
  --shadow-card:0 1px 2px oklch(0.242 0.061 259.51 / .05), 0 10px 30px oklch(0.242 0.061 259.51 / .08);
  --shadow-soft:0 1px 2px oklch(0.242 0.061 259.51 / .04), 0 6px 18px oklch(0.242 0.061 259.51 / .06);
  --r-card:26px;
  --max:1240px;
  --gutter:clamp(20px,4vw,32px);
  --ease-out:cubic-bezier(.22,1,.36,1);         /* entrées : décélération exponentielle */
  --ease-in:cubic-bezier(.7,0,.84,0);           /* sorties */
  --ease-in-out:cubic-bezier(.65,0,.35,1);      /* bascules d'état */
  --ease-signature:var(--ease-out);             /* alias historique */
}

/* ---------- Base ---------- */
*,*::before,*::after{box-sizing:border-box;}
/* `clip`, pas `hidden` : `overflow-x:hidden` crée un CONTEXTE DE DÉFILEMENT, ce qui
   casse `position:sticky` sur tous les descendants (le header en dépend) et masque la
   cause d'un débordement au lieu de la corriger. `clip` coupe sans créer ce contexte. */
html{scroll-behavior:smooth;overflow-x:clip;}
html,body{margin:0;padding:0;background:var(--bg);}
/* PAS d'overflow-x sur body : combiné à celui de html, il faisait de body un
   conteneur de scroll → position:sticky du header ne collait plus (le clipping
   horizontal du viewport est déjà porté par html). */
body{
  font-family:'Poppins',system-ui,-apple-system,'Segoe UI',sans-serif;
  color:var(--navy);
  -webkit-font-smoothing:antialiased;
  -moz-osx-font-smoothing:grayscale;
  font-synthesis:none;
  line-height:1.5;
}
img{max-width:100%;}
a{color:inherit;}
.dot{color:var(--brand);}
section{scroll-margin-top:84px;}
/* Le lien de menu « Comment ca marche » vise #parcours : l'ancre vit sur le panneau
   du parcours, pas sur la section (qui porte deja id="prestations"). Meme marge que
   les sections pour ne pas passer sous le header colle. */
#parcours{scroll-margin-top:84px;}

h1,h2{text-wrap:balance;}
p{text-wrap:pretty;}

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

.wrap{max-width:var(--max);margin:0 auto;padding-left:var(--gutter);padding-right:var(--gutter);}

/* Icônes (sprite SVG inline) */
.ic{width:1em;height:1em;fill:currentColor;display:inline-block;vertical-align:-.125em;flex:none;}

/* ---------- Animations ---------- */
@keyframes mlFloat{0%,100%{transform:rotate(6deg) translateY(0);}50%{transform:rotate(5deg) translateY(-9px);}}
/* variante mobile : pas de rotation (la diagonale gonflait la boîte visuelle sur flux vertical) */
@keyframes mlFloatMobile{0%,100%{transform:translateY(0);}50%{transform:translateY(-6px);}}
@keyframes mlEnter{from{opacity:0;transform:translateX(50px);}to{opacity:1;transform:translateX(0);}}
@keyframes mlRise{from{opacity:0;transform:translateY(26px);}to{opacity:1;transform:translateY(0);}}
@keyframes mlMenu{from{opacity:0;transform:translateY(-10px);}to{opacity:1;transform:translateY(0);}}
/* Reduced-motion en TROIS PALIERS, et non en interrupteur.
   `prefers-reduced-motion` signale que le mouvement vestibulaire donne la nausée,
   pas que toute transition dérange. Tout couper est une sur-correction : un
   élément qui change d'état sans transition TÉLÉPORTE, ce qui désoriente aussi.
   L'ancienne règle `*{transition:none!important}` écrasait d'ailleurs le fondu
   voulu ligne ~465 pour les captures — même media query, mais `!important` bat
   la spécificité. */
@media (prefers-reduced-motion: reduce){
  /* ── Palier 1 — SUPPRIMÉ : ce qui déclenche le mal des transports.
        Translations de grande amplitude, rotations 3D, parallaxe, défilés
        continus. Toutes passent par `animation`, d'où la coupe globale. */
  *,*::before,*::after{animation:none !important;}
  html{scroll-behavior:auto;}

  /* Rien à forcer ici pour le titre : sous mouvement réduit, `main.js` ne
     découpe jamais le h1 en `.type-word` (retour anticipé sur `reduced`) — le
     texte reste le HTML d'origine, donc déjà visible sans qu'aucune règle n'ait
     à annuler un état masqué qui n'existe pas. */

  /* ── Palier 2 — ADOUCI : le mouvement devient un fondu court. On garde le FAIT
        de la transition (donc pas de téléportation) en retirant le déplacement.
        `transition-property:opacity` suffit : ce que la transition n'énumère plus
        s'applique instantanément, sans qu'on ait à écrire `transform:none`. */
  *,*::before,*::after{
    transition-property:opacity !important;
    transition-duration:.15s !important;
    transition-timing-function:linear !important;
  }

  /* ── Palier 3 — CONSERVÉ : anneaux de focus, indicateurs de chargement, retours
        d'état. Rien à écrire — ils ne portent ni `animation`, ni déplacement, et
        les deux règles ci-dessus les laissent intacts. Les supprimer retirerait
        une information sans protéger personne. */
}

/* ---------- Boutons ----------
   Pattern app (F2-annonces) : CTA principal = pilule NAVY pleine, texte blanc
   700, terminé par un point orange (« Accepter. », « Voir la proposition. »).
   Secondaire : outline navy sur blanc. Le point est collé au texte (gap:0). */
.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:0;
  min-height:50px;padding:13px 26px;border-radius:999px;border:none;
  font-family:inherit;font-weight:700;font-size:15.5px;text-decoration:none;cursor:pointer;
  transition:transform .16s var(--ease-signature), box-shadow .16s ease, background-color .16s ease;
  white-space:nowrap;
}
.btn .dot{color:var(--brand);}
.btn-primary{background:var(--navy);color:#fff;box-shadow:0 2px 6px oklch(0.242 0.061 259.51 / .18), 0 12px 26px oklch(0.242 0.061 259.51 / .22);}
.btn-primary:hover{background:oklch(0.30 0.066 259.51);box-shadow:0 2px 6px oklch(0.242 0.061 259.51 / .2), 0 14px 30px oklch(0.242 0.061 259.51 / .28);transform:translateY(-2px);}
.btn-primary:active{transform:scale(.96);}
.btn-secondary{background:var(--surface);color:var(--navy);border:1.5px solid var(--navy);box-shadow:var(--shadow-soft);}
.btn-secondary:hover{box-shadow:0 2px 6px oklch(0.242 0.061 259.51 / .06), 0 10px 24px oklch(0.242 0.061 259.51 / .12);transform:translateY(-2px);}
.btn-secondary:active{transform:scale(.96);}
.btn-lg{min-height:58px;padding:16px 32px;font-size:19px;}

/* ---------- Header ---------- */
.site-header{
  position:sticky;top:0;z-index:60;
  background:oklch(1 0 0 / .86);
  backdrop-filter:blur(14px);-webkit-backdrop-filter:blur(14px);
  box-shadow:0 1px 0 oklch(0.242 0.061 259.51 / .06), 0 8px 24px oklch(0.242 0.061 259.51 / .05);
  transition:background-color .35s ease, box-shadow .35s ease;
}
.site-header .bar{height:76px;display:flex;align-items:center;gap:clamp(16px,3vw,36px);}
.site-header .logo{display:flex;align-items:center;text-decoration:none;padding:8px 0;}
.site-header .logo img{height:32px;width:auto;object-fit:contain;}
.site-header .logo-white{display:none;}
.nav-desktop{display:flex;gap:30px;margin-left:auto;font-size:14.5px;font-weight:600;}
/* La cible tactile est POSÉE, pas calculée : `padding:11px` donnait 43,99 px parce
   que la hauteur de ligne tombe sur une fraction. `min-height` supprime l'arithmétique
   et la question. La rangée est gouvernée par son `gap` : rien ne bouge à l'horizontale. */
.nav-desktop a{
  color:var(--navy);text-decoration:none;
  display:inline-flex;align-items:center;min-height:44px;
  transition:color .25s ease;
}
.nav-desktop a:hover{color:var(--brand-text);}
.header-cta{font-size:15px;min-height:46px;padding:11px 22px;}
.btn-compact{display:none;font-size:13.5px;padding:10px 18px;min-height:44px;margin-left:auto;}
.burger{
  display:none;align-items:center;justify-content:center;
  width:44px;height:44px;border-radius:12px;background:var(--bg);border:none;flex:none;cursor:pointer;color:var(--navy);
  transition:transform .12s ease, background-color .35s ease, color .35s ease;
}

/* ---------- Header sur le hero navy (avant scroll) ----------
   En haut de page le header vit SUR la surface navy : fond transparent,
   logo blanc, liens blancs, CTA inversé (pilule blanche, texte navy, point
   orange). La classe .is-on-hero est posée/retirée par main.js au scroll,
   la transition douce est portée par les règles ci-dessus. */
.site-header.is-on-hero{background:transparent;box-shadow:none;backdrop-filter:none;-webkit-backdrop-filter:none;}
/* dès qu'on a un peu scrollé mais qu'on est ENCORE sur le hero : bandeau
   navy translucide flouté, sinon le contenu du hero défile sous les liens */
.site-header.is-on-hero.is-scrolled{
  background:oklch(0.242 0.061 259.51 / .82);
  backdrop-filter:blur(14px);-webkit-backdrop-filter:blur(14px);
  box-shadow:0 1px 0 oklch(1 0 0 / .08);
}
.site-header.is-on-hero .logo-navy{display:none;}
.site-header.is-on-hero .logo-white{display:block;}
.site-header.is-on-hero .nav-desktop a{color:#fff;}
.site-header.is-on-hero .nav-desktop a:hover{color:var(--brand-hero);}
.site-header.is-on-hero .btn-primary{background:#fff;color:var(--navy);box-shadow:0 2px 6px oklch(0 0 0 / .18), 0 12px 26px oklch(0 0 0 / .24);}
.site-header.is-on-hero .btn-primary:hover{background:var(--bg);}
.site-header.is-on-hero .burger{background:oklch(1 0 0 / .14);color:#fff;}
/* menu mobile ouvert pendant qu'on est sur le hero : le panneau blanc a
   besoin d'un header opaque au-dessus, on repasse le bandeau en navy */
.site-header.is-on-hero:has(.nav-mobile.open){background:var(--navy);}
.burger:active{transform:scale(.96);}
.burger .ic{font-size:19px;}
.nav-mobile{
  display:none;flex-direction:column;background:var(--surface);
  padding:10px var(--gutter) 18px;
  box-shadow:0 12px 24px oklch(0.242 0.061 259.51 / .08);
  animation:mlMenu .22s ease both;
}
.nav-mobile.open{display:flex;}
.nav-mobile a{
  color:var(--navy);text-decoration:none;font-weight:600;font-size:15px;
  padding:14px 0;border-bottom:1px solid oklch(0.961 0.006 264.53);
}
.nav-mobile a:last-child{border-bottom:none;}

@media (max-width:899px){
  .nav-desktop,.header-cta{display:none;}
  .btn-compact{display:inline-flex;}
  .burger{display:flex;}
}

/* ---------- Hero : grande surface NAVY pleine largeur, quasi plein écran ----------
   Pattern des landings de référence (Doctolib/Qonto/Revolut) : la couleur de
   marque remplit TOUT le viewport, texte blanc géant dessus, le device déborde
   du cadre. Le header sticky vit sur cette surface (voir .is-on-hero).
   - marge négative = la surface passe sous le header (transparent en haut) ;
   - overflow:hidden = le téléphone est COUPÉ par le bord bas (profondeur) ;
   - coins bas arrondis : la section claire suivante vient s'y emboîter ;
   - texture micro-points + dégradé navy (clair haut-gauche → profond bas-droite)
     + halo orange diffus derrière le device (::after). */
.hero{
  position:relative;
  margin-top:-76px;padding-top:76px;      /* sous le header sticky (76px) */
  min-height:max(760px,min(92vh,1080px)); /* de quoi contenir le device en entier */
  display:flex;
  background:
    radial-gradient(circle at 1px 1px, oklch(1 0 0 / .045) 1.1px, transparent 1.6px) 0 0/23px 23px,
    radial-gradient(125% 125% at 10% -8%, oklch(0.335 0.075 257.6) 0%, var(--navy) 52%, oklch(0.205 0.052 259.51) 100%);
  border-radius:0 0 clamp(32px,4vw,52px) clamp(32px,4vw,52px);
  overflow:hidden;
}
.hero::before{
  content:"";position:absolute;inset:-20% -40%;z-index:0;pointer-events:none;
  background:linear-gradient(104deg, transparent 38%, oklch(1 0 0 / .07) 50%, transparent 62%);
  transform:translateX(-60%);
}
.js .hero::before{animation:sheen 1.9s cubic-bezier(.3,.1,.2,1) .35s both;}
@keyframes sheen{to{transform:translateX(60%);}}
.hero::after{
  content:"";position:absolute;right:4%;bottom:-10%;width:min(760px,56vw);aspect-ratio:1;
  border-radius:50%;pointer-events:none;z-index:0;
  /* PAS de filter:blur ici : Chromium promeut le blur en couche composée qui
     peut repasser AU-DESSUS du contenu après un reflow — le fondu est porté
     par le dégradé radial lui-même */
  background:radial-gradient(circle, oklch(0.646 0.207 38.94 / .34) 0%, oklch(0.646 0.207 38.94 / .13) 38%, transparent 66%);
}
/* z-index:1 explicite : le halo flouté (::after) ne doit JAMAIS passer
   au-dessus du contenu (quirk de compositing Chromium sur les gros blurs) */
.hero .wrap{position:relative;z-index:1;width:100%;display:flex;}
.hero-grid{
  flex:1;display:grid;grid-template-columns:minmax(0,1.16fr) minmax(0,.84fr);
  gap:clamp(24px,4vw,56px);align-items:center;
}
.hero-copy{padding:34px 0 72px;}
/* Entrée orchestrée du hero (une seule, au chargement). Sans JS ou en
   reduced-motion, tout est visible d'emblée : l'animation ne conditionne
   jamais la visibilité, elle ne fait que l'habiller. */
/* MACHINE À ÉCRIRE (18/08, revue le 15/08 — cf. le commentaire de main.js pour
   l'historique complet des deux pièges déjà tombés ici : `.type-line` sur toute
   la phrase, puis `width:0→100%` par MOT). Chaque MOT est un `inline-block` à
   largeur INTRINSÈQUE (jamais fixée) : le masque qui recule est un `clip-path`
   en `%` de SA PROPRE boîte, pas une largeur devinée à l'avance — un mot plus
   long, une police différente ou un `--chars` mal calculé ne peuvent plus
   reproduire le bug. `--chars`/`--start` sont posés par main.js (longueur du
   mot, décalage cumulé des mots/phrases précédentes). */
.spine__intro h1 .type-word{
  display:inline-block;max-width:100%;overflow:hidden;white-space:nowrap;
  vertical-align:bottom;
  /* `line-height:1.02` du h1 (cf. commentaire sur `.h1-lead` plus bas) rend
     CHAQUE mot trop court pour son propre jambage — mesuré : les deux "g" de
     "garages" tranchés net par ce `overflow:hidden`, avant même que la marge
     posée sur `.h1-lead` ait la moindre chance de jouer (elle protège le bloc
     entier, plus le decoupage par mot). Meme marge ici, au mot. */
  padding-bottom:.12em;
}
/* L'état masqué vit DANS le keyframe, pas en règle statique : si la feuille
   d'animation n'était pas appliquée alors que le JS a déjà posé `is-typing`,
   un clip à 100% figé laisserait le titre invisible sans recours. */
.js .spine__intro h1.is-typing .type-word{
  clip-path:inset(0 100% 0 0);
  animation:typeReveal calc(var(--chars,4) * 34ms) steps(var(--chars,4), end) forwards;
  animation-delay:var(--start,220ms);
}
@keyframes typeReveal{from{clip-path:inset(0 100% 0 0);} to{clip-path:inset(0 0 0 0);}}
/* le point orange de la marque tombe en dernier : c'est la ponctuation de
   l'entrée, pas une décoration de plus. `--dot-delay` est posé sur chaque
   phrase, pas sur le h1 : les deux points ne tombent donc pas ensemble. */
.js .spine__intro h1.is-typing .dot{display:inline-block;opacity:0;animation:dotDrop .5s var(--ease-out) forwards;animation-delay:var(--dot-delay,900ms);}
@keyframes dotDrop{
  0%{opacity:0;transform:translateY(-38%) scale(.5);}
  60%{opacity:1;transform:translateY(0) scale(1.18);}
  100%{opacity:1;transform:translateY(0) scale(1);}
}
/* Le curseur : un trait qui clignote juste après la dernière lettre tapée, posé
   par main.js à la fin de la dernière phrase, puis qui s'éteint — il ne doit pas
   rester planté sur la page une fois la phrase lue. `opacity:0` au repos : avant
   `--caret-start`, il est simplement invisible (pas d'`animation-fill-mode`
   nécessaire, c'est l'état normal de la règle qui s'applique). */
.type-caret{
  display:inline-block;width:.07em;height:.74em;margin-left:.06em;
  vertical-align:-.06em;background:oklch(0.705 0.195 40 / .95);
  opacity:0;
}
.js .spine__intro h1.is-typing .type-caret{
  animation:caretBlink .8s step-end 5, caretFade .35s ease forwards;
  animation-delay:var(--caret-start,0ms), calc(var(--caret-start,0ms) + 4000ms);
}
@keyframes caretBlink{0%,100%{opacity:1;} 50%{opacity:0;}}
@keyframes caretFade{to{opacity:0;}}

/* Stores — SEULE action du hero. Depuis le 15/08 ce sont les badges OFFICIELS d'Apple
   et de Google, plus les pastilles maison : des images entières (cadre, texte et logo
   compris). Il n'y a donc plus de fond, de rayon ni de padding à leur donner ici — ça
   dessinerait un second cadre autour du leur. La SEULE variable est la hauteur.
   Chacun garde son ratio propre (Apple 126,5×40, Google 239×70,9), d'où deux largeurs
   différentes à hauteur égale : c'est ce que prévoient les deux chartes, ne pas
   « égaliser » en étirant l'un des deux — déformer ces marques est interdit. */
/* Bloc magasins — 09/09, jour de la publication. Les badges sont redevenus des liens : la
   colonne garde la mention « Disponible sur », les règles d'atténuation et le lien
   « Prévenez-moi » ont été supprimés avec le balisage qui les portait.
   Les badges eux-mêmes ne changent pas d'un pixel : ce sont des marques déposées, on ne
   touche ni à leur colorimétrie ni à leur forme — le survol ne joue que sur l'opacité. */
.stores{display:flex;flex-direction:column;gap:12px;margin-top:38px;align-items:flex-start;scroll-margin-top:96px;}
.stores-badges{display:flex;gap:14px;flex-wrap:wrap;align-items:center;}
.stores-note{margin:0;font-weight:600;font-size:15px;color:oklch(1 0 0 / .78);}
.store-badge{display:flex;align-items:center;cursor:pointer;user-select:none;border-radius:6px;transition:opacity .18s ease;}
.store-badge:hover{opacity:.85;}
.store-badge img{height:48px;width:auto;display:block;}



/* ==========================================================================
   COLONNE VERTÉBRALE — hero statique (titre + 2 appareils) puis, en dessous,
   la route + les 3 étapes en pleine largeur. Avant le 15/08, le device restait
   collé (`sticky`) à côté des 3 étapes pendant tout le récit ; ce collage est
   ce qui cassait à son relâchement (cf. commentaire sur `#hero` dans le HTML).
   ========================================================================== */
.hero-wrap{position:relative;}
.spine{
  position:relative;
  background:
    radial-gradient(circle at 1px 1px, oklch(1 0 0 / .045) 1.1px, transparent 1.6px) 0 0/23px 23px,
    radial-gradient(120% 90% at 12% -6%, oklch(0.335 0.075 257.6) 0%, var(--navy) 48%, oklch(0.198 0.05 259.51) 100%);
  /* Coupure DROITE, sur toutes les largeurs (décision BOSS du 18/08 — d'abord posée sur
     mobile seul, étendue au desktop). Le bloc navy s'arrête net : c'est cette arête franche
     qui tranche les deux téléphones (cf. `overflow` juste en dessous), et un arrondi la
     rendrait molle exactement là où elle doit se voir. */
  border-radius:0;
  margin-top:-76px;padding-top:76px;
  /* `clip` GARDÉ — et c'est désormais un choix de DESSIN, plus une précaution technique
     (décision BOSS du 18/08). Depuis que le téléphone du hero vit DANS `.spine` (cf. le
     commentaire sur `.spine__device` dans index.html), c'est cette ligne qui le tranche net
     au bas du bloc navy : sur desktop, les deux appareils ne ressortent plus sur la section
     claire, ils s'arrêtent à la limite du navy. Le retirer les ferait déborder par-dessous.
     Sur mobile, l'appareil est entre le titre et les badges, donc entièrement à l'intérieur :
     cette ligne n'y change rien. */
  overflow:clip;
}
.spine__hero{display:flex;flex-direction:column;}
.spine__journey{position:relative;margin-top:clamp(12px,3vw,24px);}
.spine__intro{padding-block:clamp(28px,5vw,60px) clamp(20px,3vw,32px);}
/* Deux phrases, un seul h1. La première DOMINE : elle ne se lit plus comme
   l'amorce de la seconde, ce que faisait l'ancien kicker orange souligné. */
.spine__intro h1{
  margin:0;display:flex;flex-direction:column;gap:clamp(6px,.8vw,14px);
  color:#fff;font-weight:800;letter-spacing:-.045em;line-height:1.02;
}
/* `line-height:1.02` sur le h1 fait une line-box plus courte que la fonte : le
   jambage du « g » de « garages » sortait par le bas et se faisait trancher par le
   `overflow:clip` de la section. On ne remonte pas le line-height — c'est lui qui
   donne au titre sa compacité — on rend sa place au jambage. */
.h1-lead{
  display:block;
  /* `5.6vw` faisait ~72-80 px sur un 13" (1280-1440 px de large) : trop gros pour la
     largeur de `.spine__intro` (56 %), « Arrêtez d'appeler » cassait sur 3 lignes.
     `4.2vw` tient la même phrase sur 1-2 lignes à cette largeur, et rejoint le même
     plafond (84px) sur les écrans larges où la place ne manque pas. */
  font-size:clamp(40px,4.2vw,84px);
  padding-bottom:.09em;margin-bottom:-.05em;
}
.h1-follow{
  display:block;font-size:clamp(21px,2.6vw,38px);line-height:1.15;
  letter-spacing:-.03em;color:oklch(1 0 0 / .70);
}
/* Le fil vertical en pointillés qui prolongeait la route dans les sections claires
   a été retiré le 11/08 : il courait sur toute la hauteur de la page sans rejoindre
   quoi que ce soit et se lisait comme un artefact, pas comme un fil conducteur.
   La route redevient ce qu'elle est : un élément du hero, et rien d'autre. */
#confiance{position:relative;}

/* Le rail « séquestre » en quatre crans et la déclaration « Rien n'est versé au
   mécanicien… » ont été retirés le 11/08 sur demande du BOSS. L'argument reste dit
   au bon endroit — dans le Parcours (cf. plus bas, chapitre ③). */

/* ==========================================================================
   LE PARCOURS (15/08, soir) — port de `mecaly-app/src/ui/signature/Parcours.tsx`
   ==========================================================================
   Remplace la route + les 3 étapes statiques : UNE annonce, CINQ chapitres qui
   s'enchaînent en boucle (Créer → Proposée → Payer → Suivre → Terminée), pilotés
   par `js/parcours.js`. Les chapitres ② et ⑤ montrent la MÊME carte d'annonce —
   même photo, même titre — seul le badge change (ambre → vert) : c'est ce rappel
   qui fait lire une histoire suivie plutôt que cinq écrans sans rapport, comme
   dans l'app. Minutage identique : cycle de 15,5 s, mêmes bornes de chapitre. */
/* Le panneau qui porte le Parcours (15/08, tard) — sorti du hero, fusionné avec le
   carrousel de prestations : même vocabulaire que `.mecanos-panneau` (un panneau de
   l'autre ton posé dans une section claire), mais navy sur clair au lieu de clair sur
   navy — c'est l'inverse exact, et la page a déjà les deux sens. */
.pc-panel{
  background:var(--navy);
  border-radius:clamp(20px,2.4vw,30px);
  padding:clamp(26px,3.6vw,48px);
  margin-top:clamp(36px,5vw,56px);
  display:flex;flex-direction:column;align-items:center;
  /* Recadre net aux coins arrondis : une carte de chapitre un peu plus haute que la
     réserve de `.pc__stage` (mesuré le 15/08 tard, la carte d'annonce dépassait sous
     le panneau à certaines largeurs) se fait couper ici plutôt que déborder à l'écran. */
  overflow:hidden;
  box-shadow:0 30px 60px oklch(0.13 0.03 258 / .3), 0 8px 18px oklch(0.13 0.03 258 / .2);
}
/* Un vrai titre, pas une étiquette — même famille que le h1 du hero (gras, blanc,
   grande taille), demandé tel quel par le BOSS plutôt que la petite légende orange
   qu'il y avait avant. */
.pc-panel__title{
  color:#fff;font-weight:800;letter-spacing:-.03em;
  font-size:clamp(28px,4vw,42px);line-height:1.12;
  margin:0 0 clamp(20px,2.6vw,28px);text-align:center;
}
.pc{max-width:440px;width:100%;}
.pc__narration{position:relative;height:56px;}
/* ⚠️ PAS DE `display:flex` ICI — c'est ce qui détachait le point final (BOSS, 15/08 :
   « le point final est bugué, il est tout au bout »). En flex, le texte et le
   `<span class="dot">` sont DEUX items distincts : dès que la phrase se replie sur deux
   lignes, l'item texte prend toute la largeur et le point se retrouve projeté au bout de
   la ligne, séparé du dernier mot. Le point appartient à la phrase, il doit rester dans
   le flux du texte.
   Le centrage vertical qu'assurait `align-items:center` est repris par `top:50%` + une
   translation — et cette translation doit ABSORBER les 6 px de l'animation d'entrée,
   `transform` étant une propriété unique (même piège que les rotations du hero). */
.pc__line{
  position:absolute;left:0;right:0;top:50%;
  margin:0;font-size:clamp(17px,1.9vw,20px);font-weight:800;letter-spacing:-.015em;
  line-height:1.3;color:#fff;text-align:center;
  opacity:0;transform:translateY(calc(-50% + 6px));
  transition:opacity .35s var(--ease-out), transform .4s var(--ease-out);
}
.pc__line.is-active{opacity:1;transform:translateY(-50%);}
/* `margin-inline:auto` (BOSS, 15/08 : « la barre de progression, centre-la »). Elle était
   calée à gauche de son bloc, sous un titre et des phrases centrés — seule chose de la
   colonne à ne pas l'être. Les phrases passent en `text-align:center` par la même
   occasion : une barre centrée sous un texte aligné à gauche aurait juste déplacé le
   défaut d'un cran. */
.pc__rail{
  width:96px;height:2px;border-radius:99px;
  background:oklch(1 0 0 / .18);overflow:hidden;margin:10px auto 0;
}
.pc__rail-fill{
  width:100%;height:100%;background:#fff;
  transform-origin:left center;transform:scaleX(0);
}
@media (prefers-reduced-motion: no-preference){
  .pc__rail-fill{transition:transform .12s linear;}
}
.pc__stage{position:relative;height:clamp(268px,34vw,332px);margin-top:clamp(20px,2.6vw,28px);}
.pc-chapter{position:absolute;top:0;left:0;right:0;}

@keyframes pcSlideIn{from{opacity:0;transform:translateX(28px);}to{opacity:1;transform:translateX(0);}}
@keyframes pcSlideOut{from{opacity:1;transform:translateX(0);}to{opacity:0;transform:translateX(-28px);}}
.pc-chapter.is-entering{animation:pcSlideIn .42s var(--ease-out) both;}
.pc-chapter.is-leaving{animation:pcSlideOut .38s var(--ease-out) both;}
@keyframes pcPop{from{opacity:0;transform:scale(.82) translateY(5px);}to{opacity:1;transform:scale(1) translateY(0);}}
.pc-pop{opacity:0;animation:pcPop .38s var(--ease-out) both;animation-delay:calc(var(--i,0) * 260ms + 320ms);}
@media (prefers-reduced-motion: reduce){
  .pc-chapter.is-entering,.pc-chapter.is-leaving{animation:none;}
  .pc-pop{opacity:1;animation:none;}
}

/* Les deux formes de carte : SCHÉMATIQUE (`.pc-card`, chapitres ①③④) ou la VRAIE
   carte d'annonce (`.pc-annonce`, chapitres ②⑤) — même règle que dans l'app. */
.pc-card,.pc-annonce{
  background:var(--surface);border-radius:var(--r-card);overflow:hidden;
  box-shadow:0 18px 40px oklch(0.12 0.04 259 / .34);
}
.pc-card{padding:clamp(16px,1.8vw,20px);display:flex;flex-direction:column;gap:16px;}
.pc-row{display:flex;align-items:center;gap:12px;}
.pc-tile{width:56px;height:56px;border-radius:12px;overflow:hidden;flex:0 0 auto;}
.pc-tile img{width:100%;height:100%;object-fit:cover;display:block;}
.pc-facts{display:flex;flex-direction:column;gap:5px;flex:1;min-width:0;}
.pc-facts b{font-size:15.5px;font-weight:800;color:var(--navy);letter-spacing:-.01em;}
.pc-meta{display:flex;align-items:center;gap:5px;font-size:12.5px;font-weight:600;color:var(--muted);flex-wrap:wrap;}
.pc-meta .ic{width:13px;height:13px;fill:var(--navy);margin-right:1px;}
.pc-meta .ic:not(:first-child){margin-left:6px;}

.pc-slider{display:flex;flex-direction:column;gap:9px;}
.pc-slider-head{display:flex;align-items:center;justify-content:space-between;font-size:13px;font-weight:600;color:var(--muted);}
.pc-price{font-size:19px;font-weight:800;color:var(--brand-text-strong);letter-spacing:-.01em;}
.pc-track{position:relative;height:22px;}
.pc-track::before{
  content:'';position:absolute;left:0;right:0;top:50%;margin-top:-2px;
  height:4px;border-radius:99px;background:var(--hairline);
}
.pc-track-fill{
  position:absolute;left:0;top:50%;margin-top:-2px;width:100%;height:4px;
  border-radius:99px;background:var(--navy);transform-origin:left center;transform:scaleX(0);
}
.pc-thumb{
  position:absolute;left:0;top:50%;margin-top:-11px;width:22px;height:22px;border-radius:50%;
  background:var(--surface);border:2px solid var(--navy);box-shadow:0 2px 6px oklch(0 0 0 / .2);
}
@media (prefers-reduced-motion: no-preference){
  .pc-track-fill,.pc-thumb{transition:none;}
}
.pc-publish{
  display:flex;align-items:center;justify-content:center;gap:8px;
  background:var(--navy);color:#fff;border-radius:999px;padding:12px;
  font-size:14px;font-weight:700;
}
.pc-publish .ic{width:15px;height:15px;fill:#fff;}

/* La VRAIE carte — même disposition que `PrestaCard` en `caption="overlay"` dans
   l'app : titre + faits posés SUR la photo (voile bas), pas dans un bandeau blanc
   séparé (18/08 : « ce n'est pas vraiment celle de l'application » — c'est cette
   version-ci, pas la précédente, qui reprend le geste réel). Le badge de statut
   reste posé sur la photo, en haut. Ratio réduit (16/9, pas 16/10) : la carte tient
   plus sûrement dans la hauteur réservée du chapitre — cf. `.pc-panel{overflow}`. */
.pc-annonce-photo{position:relative;aspect-ratio:16 / 9;}
.pc-annonce-photo img{width:100%;height:100%;object-fit:cover;display:block;}
.pc-annonce-voile{
  position:absolute;inset:0;
  background:linear-gradient(180deg,
    oklch(0.242 0.061 259.51 / 0) 46%,
    oklch(0.242 0.061 259.51 / .58) 72%,
    oklch(0.242 0.061 259.51 / .74) 100%);
}
.pc-badge{
  position:absolute;top:10px;left:10px;z-index:1;font-size:11.5px;font-weight:700;
  padding:4px 8px;border-radius:5px;background:#fff;color:var(--navy);
}
.pc-badge--pending{background:var(--warning-bg);color:var(--warning);}
.pc-badge--success{background:var(--success-bg);color:var(--success-text);}
.pc-annonce-titre{
  position:absolute;left:0;right:0;bottom:0;z-index:1;
  padding:12px 16px;display:flex;flex-direction:column;gap:5px;
}
.pc-annonce-titre b{
  color:#fff;font-size:15px;font-weight:800;letter-spacing:-.01em;
  text-shadow:0 1px 6px oklch(0 0 0 / .3);
}
.pc-annonce-titre .pc-meta{color:oklch(1 0 0 / .82);}
.pc-annonce-titre .pc-meta .ic{fill:#fff;}
.pc-annonce-foot{
  display:flex;align-items:center;justify-content:space-between;gap:12px;
  padding:12px 16px 16px;
  font-size:13px;font-weight:600;color:var(--navy);
}
.pc-avatars{display:flex;align-items:center;}
.pc-avatar{
  width:30px;height:30px;border-radius:50%;flex:0 0 auto;
  display:flex;align-items:center;justify-content:center;
  background:var(--navy);color:#fff;font-size:11px;font-weight:800;
  border:2px solid var(--surface);margin-left:-10px;
}
.pc-avatar:first-child{margin-left:0;}
.pc-avatar--lg{width:44px;height:44px;font-size:14px;margin-left:0;}
.pc-stars-give{display:flex;align-items:center;gap:4px;}
.pc-stars-give .ic{width:16px;height:16px;fill:oklch(0.793 0.162 82.95);}

/* Chapitre ③ Payer */
.pc-stars{display:flex;align-items:center;gap:6px;font-size:13px;color:oklch(0.793 0.162 82.95);margin-top:2px;}
.pc-stars i{font-style:normal;font-size:12px;font-weight:600;color:var(--muted);}
.pc-secure{display:flex;align-items:center;justify-content:space-between;padding-top:14px;border-top:1px solid var(--hairline);}
.pc-secure span{display:flex;align-items:center;gap:6px;font-size:13px;font-weight:600;color:var(--muted);}
.pc-secure span .ic{width:14px;height:14px;fill:var(--success);}
.pc-check{width:20px;height:20px;fill:var(--success);}

/* Chapitre ④ Suivre */
.pc-track-head{display:flex;align-items:center;gap:8px;font-size:13px;font-weight:600;color:var(--muted);}
.pc-track-head .ic{width:14px;height:14px;fill:var(--navy);}
.pc-steps{display:flex;align-items:center;}
.pc-step{display:flex;flex-direction:column;align-items:center;gap:8px;flex:0 0 auto;}
.pc-step label{margin:0;font-size:12px;font-weight:700;color:var(--navy);white-space:nowrap;}
.pc-step label.pc-muted{color:var(--muted);font-weight:600;}
.pc-dot{width:12px;height:12px;border-radius:50%;background:var(--navy);flex:0 0 auto;}
.pc-dot--muted{background:var(--hairline);}
.pc-step-line{flex:1 1 auto;height:2px;background:var(--hairline);margin:0 6px 22px;}
/* Le mockup est un DÉCOR : il ne se clique pas, ne se sélectionne pas, ne se
   traîne pas. Rien ne l'en empêchait — d'où l'impression de « pouvoir cliquer
   dans le téléphone ». `aria-hidden` sur le bloc ne couvre que les lecteurs
   d'écran, pas la souris. */
/* ---------- Hero : la composition à deux appareils (refonte du 15/08 soir) ----------
   Référence donnée par le BOSS (Freetrade) : deux appareils COMPLETS, cote à cote,
   dans un hero STATIQUE — pas un premier plan qui domine un second à peine visible.
   Le device n'est plus `sticky` et ne suit plus le récit des 3 étapes.

   Sorti de `.spine` (cf. commentaire HTML sur `.hero-wrap`) pour pouvoir déborder
   PROPREMENT sous le hero, sans que `overflow:clip` ne le coupe : `position:absolute`
   dans `.hero-wrap`, ancré en haut à droite. Les deux `.phone` sont dimensionnés en
   HAUTEUR (le ratio de l'image fixe la largeur) : les agrandir ne change qu'un seul
   nombre par appareil, jamais leurs proportions. */
.spine__device{
  position:absolute;
  top:clamp(28px,5vw,68px);right:clamp(60px,10vw,140px);
  z-index:5;
  display:flex;align-items:flex-end;justify-content:flex-end;
  pointer-events:none;user-select:none;-webkit-user-select:none;
}
/* Entrée des deux appareils au chargement — ils sont au-dessus du pli, donc jouée
   au montage plutôt qu'au défilement (pas de `.reveal`/IntersectionObserver ici).
   ⚠️ OPACITÉ SEULE, jamais `transform` dans ce keyframe. Chaque appareil porte déjà SA
   rotation de repos en `transform` (-3° / 3°+14px en desktop, d'autres valeurs sous
   900 px) — un keyframe qui anime aussi `transform` fige sa DERNIÈRE valeur au sortir
   de l'animation (`animation-fill-mode:both`) et écraserait cette rotation, avec des
   valeurs qui devraient en plus changer par breakpoint. Un fondu n'a pas ce problème :
   il ne touche à rien que l'entrée ne doive pas changer. */
@keyframes phoneEnter{from{opacity:0;}to{opacity:1;}}
/* ── ENTRÉE PUIS FLOTTEMENT DES DEUX APPAREILS (BOSS, 15/08) ────────────────────────────
   `phoneEnter` n'était qu'un FONDU, et sa note expliquait pourquoi : les deux appareils
   portent des rotations DIFFÉRENTES (-3° et 3°), et `transform` étant une propriété unique,
   une animation qui ne poserait qu'une translation les redresserait tous les deux d'un coup.
   La réponse n'est pas de renoncer au mouvement, c'est d'écrire UN JEU DE KEYFRAMES PAR
   APPAREIL, chacun reprenant sa rotation à chaque étape. C'est un peu de répétition, et
   c'est le prix pour que l'entrée n'écrase pas la mise en place.

   Deux animations s'enchaînent sur le même élément, et l'ordre de déclaration compte : la
   dernière gagne quand les deux tournent. Le flottement démarre APRÈS la fin de l'entrée
   (délai > durée + délai de l'entrée) et n'a pas de `fill`, donc il n'impose rien tant qu'il
   n'a pas commencé — les deux ne se disputent jamais le même instant.

   ⚠️ Toute modification d'une rotation plus bas doit être répercutée ICI, dans les quatre
   keyframes. Sinon l'appareil se remet droit au premier tour d'animation. */
@keyframes phoneInBack{
  from{opacity:0;transform:rotate(-3deg) translateY(42px);}
  to  {opacity:1;transform:rotate(-3deg) translateY(0);}
}
@keyframes phoneFloatBack{
  0%,100%{transform:rotate(-3deg) translateY(0);}
  50%    {transform:rotate(-3deg) translateY(-13px);}
}
/* Le `--front` est posé 14 px plus bas au repos : sa valeur de repos n'est pas 0. */
@keyframes phoneInFront{
  from{opacity:0;transform:rotate(3deg) translateY(58px);}
  to  {opacity:1;transform:rotate(3deg) translateY(14px);}
}
@keyframes phoneFloatFront{
  0%,100%{transform:rotate(3deg) translateY(14px);}
  50%    {transform:rotate(3deg) translateY(0);}
}
@media (prefers-reduced-motion: no-preference){
  /* Décalage de 180 ms entre les deux entrées : ils se posent l'un après l'autre, ce qui
     donne la profondeur que deux arrivées simultanées écrasent. Et des durées de flottement
     PREMIÈRES l'une par rapport à l'autre (6,4 s / 5,6 s) pour qu'ils ne se resynchronisent
     jamais — deux appareils qui montent et descendent ensemble se lisent comme un seul bloc. */
  .spine__device .phone--back{
    animation:phoneInBack .8s var(--ease-out) .1s both,
              phoneFloatBack 6.4s ease-in-out 1.1s infinite;
  }
  .spine__device .phone--front{
    animation:phoneInFront .8s var(--ease-out) .28s both,
              phoneFloatFront 5.6s ease-in-out 1.3s infinite;
  }
}
/* ══ PLUS AUCUN `drop-shadow` SUR LES MOCKUPS — ET C'EST DÉFINITIF ═══════════════════════
   Le BOSS a signalé DEUX FOIS un rectangle gris derrière les appareils (photo d'écran le
   15/08 : « ça fait ça trop souvent, même sur desktop »).

   Premier correctif, insuffisant : déplacer le filtre du conteneur vers l'`<img>`, en
   pensant que seul le nœud PORTANT un transform était en cause. Il est revenu. La raison
   est plus large — `filter:drop-shadow()` doit lire le canal alpha de sa cible, or il suffit
   qu'un ANCÊTRE soit promu en couche composée pour que le filtre soit rastérisé à part et
   retombe sur la silhouette de la BOÎTE. Et ici les ancêtres sont promus en permanence :
   `anim.js` pose une parallaxe GSAP (transform inline) sur `.spine__device`,
   `.confiance-device` et `.mecanos-device`, et `.reveal` anime encore un transform.
   Déplacer le filtre d'un cran ne faisait donc que déplacer le problème.

   L'ombre est maintenant DESSINÉE : une ellipse floue au sol, en pseudo-élément. Ce n'est
   pas un filtre, ça ne lit aucun alpha, ça ne dépend d'aucune couche — donc ça ne peut pas
   dégénérer en rectangle, sur aucun moteur. On y perd l'ombre qui épouse exactement le
   contour de l'appareil ; on y gagne une ombre qui s'affiche toujours.

   ⚠️ NE PAS réintroduire de `drop-shadow` sur un mockup, même « juste pour le desktop ».
   C'est le bug qui est revenu deux fois. */
.spine__device .phone{
  position:relative;
  background:none;padding:0;border-radius:0;box-shadow:none;
}
.spine__device .phone img{display:block;height:100%;width:auto;}
/* L'ellipse est posée SOUS l'appareil (`z-index:-1` + parent sans fond), volontairement
   plus étroite que lui : une ombre aussi large que l'objet se lit comme un halo. */
.spine__device .phone::after{
  content:'';position:absolute;z-index:-1;
  left:8%;right:8%;bottom:-3%;height:6%;
  border-radius:50%;
  background:radial-gradient(closest-side, oklch(0 0 0 / .55), oklch(0 0 0 / 0));
  filter:blur(10px);
}
.spine__device .phone--back{
  height:clamp(340px, 43vw, 620px);
  transform:rotate(-3deg);
  margin-right:-11%;
  z-index:0;
}
.spine__device .phone--front{
  height:clamp(360px, 46vw, 660px);
  transform:rotate(3deg) translateY(14px);
  margin-left:-6%;
  z-index:1;
}
@media (max-width:899px){
  /* Sous 900 px, le device redevient statique — donc dans le flux, à l'endroit où il
     apparaît dans le HTML : APRÈS toute la section hero (titre + route + 3 étapes),
     puisqu'il vit maintenant hors de `.spine` (cf. `.hero-wrap`). Le débordement
     « propre » ne se pose qu'en desktop : sur un écran étroit, deux appareils qui
     chevauchent la jointure de section auraient produit l'inverse d'un rendu propre. */
  .spine__device{
    position:static;
    margin-top:clamp(28px,7vw,40px);
  }
  .spine__device .phone--back{height:clamp(176px,40vw,240px);}
  .spine__device .phone--front{height:clamp(192px,44vw,264px);}
}

@media (min-width:900px){
  /* Le device n'est plus un enfant de cette grille (il vit dans `.hero-wrap`, en
     `position:absolute`, cf. `.spine__device` plus bas) : `.spine__intro` réserve
     donc lui-même la place à droite, en max-width, plutôt que via une colonne. */
  /* 56 % chevauchait ENCORE le device à 1280 px (mesuré : colonne texte jusqu'à
     x=711, téléphones dès x=628) — le device est en `position:absolute`, calé sur
     la DROITE du wrap, sans lien avec la largeur de cette colonne : un pourcentage
     de la largeur totale ne peut pas deviner où il commence. 46 % laisse la marge
     mesurée nécessaire ; un retour à la ligne de plus vaut mieux qu'un titre qui
     passe derrière les appareils. */
  .spine__intro{max-width:46%;}
}

/* ---------- Device + démo en captures réelles ----------
   Le châssis suit les proportions du capteur : l'écran a EXACTEMENT le ratio
   des captures (660×1380 → 0,478), lisière de 3,4 % de la largeur et rayon de
   12 %, comme un téléphone du commerce. Rien n'est étiré, rien n'est deviné. */
.hero-phone .phone{
  /* plus aucun cadre dessiné ici : l'image EST le device (cadre iPhone 16 réel,
     généré par appshot, PNG à canal alpha). On ne fait que dimensionner. */
  width:clamp(264px, 21vw, 302px);background:none;padding:0;border-radius:0;box-shadow:none;
}
.hero-phone .phone-screen{
  position:relative;width:100%;aspect-ratio:700 / 1447;height:auto;
  background:none;border-radius:0;overflow:visible;display:block;
}



/* Chapitrage sous le device */
.demo-nav{
  position:absolute;left:0;right:0;bottom:10px;z-index:3;
  display:flex;flex-wrap:wrap;justify-content:center;gap:8px;
}
.demo-chip{
  border:1px solid oklch(1 0 0 / .26);border-radius:6px;
  background:oklch(1 0 0 / .06);color:oklch(1 0 0 / .82);
  font-family:inherit;font-size:12.5px;font-weight:600;letter-spacing:.01em;
  padding:8px 12px;min-height:36px;cursor:pointer;white-space:nowrap;
  transition:background-color .25s var(--ease-out), color .25s var(--ease-out), border-color .25s var(--ease-out);
}
.demo-chip:hover{background:oklch(1 0 0 / .14);color:#fff;}
.demo-chip.is-on{background:#fff;border-color:#fff;color:var(--navy);}
.demo-chip:focus-visible{outline:3px solid var(--brand-hero);outline-offset:2px;}

@media (prefers-reduced-motion: reduce){
  .tapdot{display:none;}
}

/* ---------- Hero : téléphone (ancienne réplique — conservé pour le device pro) ----------
   Contenu interne en px fixes → on ne touche pas à la width, seulement au
   scale. Ancré au BAS du hero et débordant de 100px sous le bord : le
   overflow:hidden du hero le coupe — débordement discret (~12 % du device),
   l'écran de la démo reste bien visible SANS que le haut du device ne
   percute le header sticky (scale 1.02, calé pour 90vh). Tilt mlFloat 6deg. */
.hero-phone{position:relative;align-self:stretch;}
.phone-enter{
  position:absolute;left:0;right:0;bottom:62px;z-index:2;
  display:flex;justify-content:center;
  animation:mlEnter .9s .2s var(--ease-out) both;
}
.phone-parallax{will-change:transform;}
/* Cas d'école du rectangle gris : `mlFloat` anime un transform, et le filtre était sur
   le MÊME nœud — donc recomposé à chaque frame, sur la boîte au lieu de l'alpha.
   Le conteneur flotte, l'image porte l'ombre (cf. la note détaillée sur `.spine__device`). */
.phone-float{animation:mlFloat 5.5s ease-in-out infinite;}
/* Ombre dessinée, pas filtrée (cf. la note sur `.spine__device .phone`) : ce bloc porte
   l'animation `mlFloat`, donc sa couche est composée en permanence. */
.phone-float{position:relative;}
.phone-float::after{
  content:'';position:absolute;z-index:-1;left:8%;right:8%;bottom:-3%;height:6%;
  border-radius:50%;
  background:radial-gradient(closest-side, oklch(0 0 0 / .5), oklch(0 0 0 / 0));
  filter:blur(10px);
}
@media (min-width:768px){
  .phone{transform:scale(.88);transform-origin:bottom center;}
}

/* ---------- Hero mobile : composé pour le téléphone, pas empilé ----------
   L'empilement « texte, puis device centré dessous » est la conversion
   paresseuse d'une maquette desktop : sur un écran de 390 px, le device
   centré fait une vignette timide au milieu de vide.
   Ici il déborde par la droite, plus grand que l'écran, incliné — on tient un
   téléphone dans la main, on ne regarde pas une photo de téléphone. Le
   chapitrage passe à gauche, sous le texte, là où le pouce arrive. */
@media (max-width:767px){
  .hero{min-height:0;padding-top:88px;overflow:hidden;}
  .hero-grid{grid-template-columns:1fr;gap:0;align-items:start;}
  .hero-copy{padding:0;position:relative;z-index:2;}
  .hero h1{font-size:clamp(34px,9vw,46px);}
  .stores{margin-top:24px;gap:10px;}
  .store-badge img{height:42px;}

  /* Le device déborde par la droite (il sort du cadre, il n'est pas posé au
     milieu), mais il reste ENTIER en hauteur : la démo est ce qu'on vient
     montrer, la tronquer serait absurde. */
  /* en flux : le conteneur prend la hauteur réelle du device, aucun calcul à
     tenir à jour quand la taille de l'écran change */
  .hero-phone{
    position:relative;align-self:auto;height:auto;
    margin:26px calc(var(--gutter) * -1) 0 0;
    overflow:visible;
  }
  .phone-enter{
    position:relative;inset:auto;right:-7%;
    justify-content:flex-end;animation-name:mlRise;
  }
  .hero-phone .phone{--scr-w:min(74vw,290px);transform:rotate(-4.5deg);transform-origin:top right;}
  .phone-float{animation:none;}          /* il est déjà incliné : pas de flottement en plus */

  /* chapitrage : sous le device, aligné à gauche comme le texte */
  .demo-nav{
    position:static;justify-content:flex-start;margin-top:22px;
    gap:6px;
  }
  .demo-chip{font-size:12px;padding:7px 10px;min-height:34px;}
  .hero::after{right:-30%;bottom:-4%;width:min(460px,120vw);}
}
@media (max-width:400px){
  .demo-chip{font-size:11.5px;padding:6px 9px;}
}
.phone{
  width:clamp(290px,30vw,370px);aspect-ratio:402/874;background:oklch(0.189 0.01 248.37);border-radius:52px;padding:10px;
  box-shadow:0 60px 90px oklch(0.242 0.061 259.51 / .32), 0 24px 40px oklch(0.242 0.061 259.51 / .2), inset 0 0 0 2px oklch(0.369 0.016 255.62);
}
/* radius concentrique : écran = 52 (téléphone) − 10 (padding) = 42 */
.phone-screen{
  background:oklch(0.966 0.006 255.48);
  background-image:radial-gradient(130% 46% at 50% -8%, oklch(1 0 0 / .95) 0%, oklch(1 0 0 / 0) 70%);
  border-radius:42px;overflow:hidden;position:relative;height:100%;display:flex;flex-direction:column;
}
.p-status{display:flex;align-items:center;justify-content:space-between;padding:10px 22px 2px;font-size:11px;font-weight:700;color:var(--navy);font-variant-numeric:tabular-nums;}
.p-island{position:absolute;left:50%;transform:translateX(-50%);top:9px;width:76px;height:21px;background:oklch(0.189 0.01 248.37);border-radius:100px;}
.p-status .sig{display:flex;gap:5px;align-items:center;font-size:10px;}
/* header : avatar + logo centré + cloche dans un rond blanc */
.p-appbar{display:flex;align-items:center;justify-content:space-between;padding:8px 16px 6px;}
.p-avatar-wrap{display:flex;align-items:center;gap:3px;flex:none;}
/* avatar rond NAVY à initiales, comme l'app */
.p-avatar{
  width:27px;height:27px;border-radius:100px;background:linear-gradient(140deg,oklch(0.328 0.071 257.6),var(--navy));
  color:#fff;font-size:10px;font-weight:800;display:flex;align-items:center;justify-content:center;flex:none;
  border:1.5px solid #fff;box-shadow:0 2px 6px oklch(0.242 0.061 259.51 / .14);
}
.p-appbar > img{height:17px;width:auto;object-fit:contain;}
.p-bell{
  width:29px;height:29px;border-radius:100px;background:var(--surface);flex:none;
  display:flex;align-items:center;justify-content:center;box-shadow:0 3px 10px oklch(0.242 0.061 259.51 / .10);
}
.p-bell .ic{color:var(--navy);font-size:12px;}
/* grande carte hero NAVY PLEINE « Bonjour Thomas » (app 13/07) */
.p-hero-pad{padding:8px 11px 4px;}
.p-card{
  background:var(--surface);border-radius:20px;
  box-shadow:0 2px 6px oklch(0.242 0.061 259.51 / .05), 0 10px 26px oklch(0.242 0.061 259.51 / .08);
}
.p-welcome{background:var(--navy);border-radius:22px;padding:17px 13px 15px;}
.p-hello{font-size:17px;font-weight:800;color:#fff;letter-spacing:-.01em;}
.p-hello .wave{font-family:"Apple Color Emoji","Segoe UI Emoji","Noto Color Emoji",sans-serif;font-weight:400;}
/* champ recherche = pilule BLANCHE dans la carte navy */
.p-search{
  display:flex;align-items:center;gap:7px;background:var(--surface);
  border-radius:100px;height:36px;padding:0 13px;margin-top:12px;
}
.p-search .ic{font-size:11px;color:oklch(0.55 0.02 262);}
.p-search span{font-size:9.5px;color:oklch(0.661 0.026 262.05);font-weight:500;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
/* 3 chips pilules BLANCHES, icônes NAVY */
.p-chips{display:flex;gap:7px;margin-top:11px;}
.p-chip{
  flex:1;display:flex;align-items:center;justify-content:center;gap:5px;
  background:var(--surface);
  border-radius:100px;padding:10px 4px;font-size:9.5px;font-weight:700;color:var(--navy);white-space:nowrap;
}
.p-chip .ic{color:var(--navy);font-size:12px;}
/* sections de l'écran */
.p-sec{margin-top:13px;}
.p-sec-head{display:flex;justify-content:space-between;align-items:center;padding:0 12px;margin-bottom:7px;}
.p-sec-head .t{font-size:13px;font-weight:800;color:var(--navy);white-space:nowrap;letter-spacing:-.01em;}
/* « Voir tout → » = pilule NAVY pleine texte blanc (app 13/07) */
.p-sec-head .more{
  background:var(--navy);color:#fff;border-radius:100px;padding:5px 11px;
  font-size:8.5px;font-weight:700;white-space:nowrap;flex:none;
}
/* cartes prestation : photo plein cadre + overlay navy + titre blanc 800 +
   pilule claire translucide « Publier → » texte orange.
   La 2e carte déborde de l'écran comme dans l'app. */
.p-presta-row{display:flex;gap:9px;overflow:hidden;padding:0 0 4px 12px;}
.p-presta{
  position:relative;flex:none;width:63%;aspect-ratio:120/152;border-radius:16px;overflow:hidden;
  background-color:var(--navy);background-size:cover;background-position:center;
  box-shadow:inset 0 0 0 1px oklch(0 0 0 / .1); /* liseré image */
}
.p-presta .meta{position:absolute;left:10px;right:10px;bottom:10px;}
.p-presta .n{font-size:11.5px;font-weight:800;color:#fff;line-height:1.22;letter-spacing:-.01em;}
.p-presta .pub{
  margin-top:8px;display:flex;align-items:center;justify-content:space-between;
  background:oklch(1 0 0 / .88);border-radius:100px;padding:6px 11px;
  font-size:9px;font-weight:700;color:var(--brand-text);
}
.p-presta .pub .ic{font-size:9px;color:var(--brand);}
/* annonce en cours : carte blanche, pastille statut OUTLINE verte,
   ligne pro + date/heure avec icônes (app 13/07) */
.p-annonces{padding:13px 11px 0;}
.p-annonces .p-sec-head{padding:0 1px;margin-bottom:8px;}
.p-annonce{border-radius:16px;padding:13px 12px;display:flex;align-items:center;gap:10px;}
/* radius concentrique : 16 (carte) − 12 (padding) ≈ 6 ; + liseré image */
.p-annonce img{width:48px;height:48px;border-radius:6px;object-fit:cover;flex:none;outline:1px solid oklch(0 0 0 / .1);outline-offset:-1px;}
.p-annonce .body{flex:1;min-width:0;display:flex;flex-direction:column;align-items:flex-start;gap:5px;}
.p-annonce .t{font-size:12px;font-weight:800;color:var(--navy);white-space:nowrap;}
.p-annonce .st{
  display:inline-flex;align-items:center;gap:3px;
  background:var(--surface);border:1px solid var(--success);color:var(--success-text);
  border-radius:100px;padding:3px 8px;font-size:8px;font-weight:700;white-space:nowrap;
}
.p-annonce .st .ic{font-size:8.5px;color:var(--success);}
.p-annonce .m{
  display:flex;align-items:center;gap:4px;font-size:8.5px;font-weight:600;
  color:var(--navy);opacity:.75;white-space:nowrap;font-variant-numeric:tabular-nums;
}
.p-annonce .m .ic{font-size:9px;}
.p-annonce .m .cal{margin-left:5px;}
.p-annonce .chev{margin-left:auto;font-size:11px;color:var(--navy);flex:none;}
/* bottom bar pleine largeur BLANCHE avec ENCOCHE COURBE autour du FAB orange
   dégradé rond centré : la barre épouse la courbe du FAB (masque radial),
   le FAB déborde au-dessus. Onglet actif = icône + label ORANGE sans pastille. */
.p-nav{position:absolute;left:0;right:0;bottom:0;z-index:3;}
/* drop-shadow (et non box-shadow) sur un WRAPPER de la barre masquée : le
   filtre voit la forme déjà découpée, donc hairline 1px + ombre douce épousent
   l'encoche courbe. Le FAB est un frère (hors du filtre) pour ne pas boucher
   la silhouette de l'encoche. */
.p-barwrap{
  filter:drop-shadow(0 -1px 0 oklch(0.242 0.061 259.51 / .15)) drop-shadow(0 -6px 14px oklch(0.242 0.061 259.51 / .14));
}
.p-nav .fab{
  position:absolute;top:-26px;left:50%;margin-left:-21px;z-index:2;
  width:42px;height:42px;border-radius:100px;
  background:linear-gradient(140deg,oklch(0.727 0.176 41.2),var(--brand) 62%,oklch(0.608 0.201 37.6));
  display:flex;align-items:center;justify-content:center;
  /* ombre neutre navy (portée sur la barre, dessine la courbe) + pointe orange */
  box-shadow:0 8px 16px oklch(0.242 0.061 259.51 / .22), 0 3px 8px oklch(0.646 0.207 38.94 / .22);
}
.p-nav .fab .ic{font-size:18px;color:#fff;}
/* encoche : cercle transparent r≈28 centré 5px au-dessus du bord haut de la
   barre (FAB r=21 + 7px de jour) — découpe au masque radial */
.p-bar{
  display:grid;grid-template-columns:1fr 1fr 64px 1fr 1fr;align-items:center;
  background:var(--surface);padding:10px 4px 17px;
  -webkit-mask:radial-gradient(circle at 50% -5px, transparent 27.5px, #000 28.5px);
  mask:radial-gradient(circle at 50% -5px, transparent 27.5px, #000 28.5px);
}
.p-bar .item{
  position:relative;display:flex;flex-direction:column;align-items:center;gap:3px;
  color:var(--navy);font-size:7.5px;font-weight:600;
}
.p-bar .item .ic{font-size:13px;}
.p-bar .item.on{color:var(--brand);font-weight:700;}
/* badge « 9+ » orange sur Messages, point orange sur Annonces */
.p-bar .item.has-badge::after{
  content:attr(data-badge);position:absolute;top:-6px;left:calc(50% + 3px);
  background:var(--brand);color:#fff;font-size:6.5px;font-weight:800;line-height:1;
  padding:2px 4px;border-radius:100px;border:1.5px solid var(--surface);
}
.p-bar .item.has-dot::after{
  content:"";position:absolute;top:-2px;left:calc(50% + 5px);
  width:5px;height:5px;border-radius:100px;background:var(--brand);
  border:1.5px solid var(--surface);
}
.p-home{position:absolute;left:0;right:0;bottom:0;z-index:4;padding-bottom:6px;display:flex;justify-content:center;}
.p-home span{width:110px;height:4px;border-radius:100px;background:var(--navy);opacity:.5;}
.phone-el{opacity:0;}

/* ---------- Démo scénarisée du téléphone ----------
   Écrans = calques absolus superposés entre la status bar et la bottom bar
   (toutes deux FIXES). Slides horizontaux type navigation native, uniquement
   transform/opacity. Le player JS (main.js) orchestre la timeline ; sans JS
   ou avec prefers-reduced-motion, seul l'accueil statique est visible. */
.no-anim{transition:none !important;}
.p-screens{position:relative;flex:1;min-height:0;}
.p-screen{
  position:absolute;inset:0;z-index:1;
  display:flex;flex-direction:column;
  background:oklch(0.966 0.006 255.48);
  transform:translateX(103%);
  transition:transform .38s var(--ease-out);
  will-change:transform;
}
.p-screen.s-home{background:transparent;}
.p-screen.is-active{transform:translateX(0);z-index:2;}
.p-screen.is-left{transform:translateX(-30%);}
.p-screen.is-fading{z-index:3;transform:translateX(0);opacity:0;transition:opacity .6s ease;}

/* header d'écran secondaire CLAIR (app réelle flow-01/04/06) : titre navy 800
   centré, chevron retour à gauche, hairline en bas, fond de l'écran */
.p-lightbar{
  display:flex;align-items:center;justify-content:space-between;gap:8px;flex:none;
  padding:9px 14px 8px;border-bottom:1px solid oklch(0.242 0.061 259.51 / .07);
}
.p-lightbar .back{display:flex;align-items:center;justify-content:center;width:22px;height:16px;flex:none;justify-content:flex-start;}
.p-lightbar .back .ic{font-size:11px;color:var(--navy);}
.p-lightbar .t{font-size:11.5px;font-weight:800;color:var(--navy);letter-spacing:-.01em;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
.p-lightbar .sp{width:22px;flex:none;}
/* « Aide » orange à droite (flow-06) */
.p-lightbar .aide{min-width:22px;flex:none;text-align:right;font-size:9px;font-weight:700;color:var(--brand-text);}

.p-pad{padding:10px 11px 92px;display:flex;flex-direction:column;gap:9px;flex:1;min-height:0;}

/* CTA pilule navy pleine largeur, point orange (pattern « Accepter. ») */
.p-cta{
  display:flex;align-items:center;justify-content:center;
  background:var(--navy);color:#fff;border-radius:100px;height:36px;flex:none;
  font-size:11px;font-weight:700;
  box-shadow:0 2px 5px oklch(0.242 0.061 259.51 / .16), 0 8px 18px oklch(0.242 0.061 259.51 / .2);
  transition:transform .16s var(--ease-out);
}
.p-cta.pressd{transform:scale(.95);}

/* flèche orange dans les CTA (« Continuer → », « Publier l'annonce → ») */
.p-cta .arr{color:var(--brand);}
/* overline de carte (EN QUOI ÇA CONSISTE, PRESTATION, RENDEZ-VOUS…) */
.ov{font-size:7px;font-weight:700;letter-spacing:.12em;text-transform:uppercase;color:var(--navy);}
/* avatar rond navy à initiales (partagé) */
.avatar{
  width:26px;height:26px;border-radius:100px;flex:none;
  background:linear-gradient(140deg,oklch(0.328 0.071 257.6),var(--navy));
  color:#fff;font-size:8.5px;font-weight:800;display:flex;align-items:center;justify-content:center;
}

/* ÉCRAN 2 — fiche prestation (réplique flow-04) */
.pad-presta{padding:9px 11px 78px;gap:7px;}
.pd-photo{
  position:relative;height:92px;border-radius:14px;flex:none;
  background-color:var(--navy);background-size:cover;background-position:center;
  box-shadow:inset 0 0 0 1px oklch(0 0 0 / .1);
}
.pd-badge{
  position:absolute;top:8px;left:8px;background:var(--surface);color:var(--navy);
  font-size:7.5px;font-weight:700;letter-spacing:.08em;border-radius:7px;padding:4px 8px;
  box-shadow:0 2px 6px oklch(0.242 0.061 259.51 / .14);
}
.pd-title{font-size:13px;font-weight:800;color:var(--navy);line-height:1.2;letter-spacing:-.015em;}
.pd-time{display:flex;align-items:center;gap:5px;font-size:9px;font-weight:600;color:var(--navy);margin-top:-3px;}
.pd-time .ic{font-size:10px;}
.pd-price{border-radius:16px;padding:10px 12px;display:flex;align-items:center;justify-content:space-between;gap:8px;}
.pd-price .l{font-size:10px;font-weight:800;color:var(--navy);white-space:nowrap;}
.pd-price .v{font-size:11px;font-weight:800;color:var(--brand);white-space:nowrap;font-variant-numeric:tabular-nums;}
.pd-info{border-radius:16px;padding:10px 12px;}
.pd-info p{margin:5px 0 0;font-size:8.5px;line-height:1.5;font-weight:500;color:var(--navy);opacity:.8;}
/* lignes à tirets ORANGE (« QUAND INTERVENIR ? ») */
.pd-info .li{display:flex;align-items:center;gap:7px;font-size:8.5px;font-weight:500;color:var(--navy);opacity:.85;margin-top:7px;}
.pd-info .li .dash{width:11px;height:2.5px;border-radius:2px;background:var(--brand);flex:none;}
.pd-cta{margin-top:auto;}

/* ÉCRAN 3 — formulaire Publier une annonce (réplique flow-01) */
.pad-form{padding:9px 11px 0;gap:8px;overflow:hidden;}
.p-form{border-radius:16px;padding:11px 12px;flex:none;}
/* pilule navy « prestation » avec icône grille + chevron */
.f-presta{margin-top:7px;display:flex;align-items:center;gap:7px;background:var(--navy);color:#fff;border-radius:100px;padding:8px 11px;}
.f-presta .ic{font-size:10px;flex:none;}
.f-presta .tx{flex:1;font-size:8.5px;font-weight:700;text-align:center;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
.f-presta .chev{font-size:8px;}
.f-div{height:1px;background:var(--hairline);margin:10px -2px 9px;flex:none;}
/* faux textarea (placeholder gris) */
.f-area{
  margin-top:7px;border:1.3px solid oklch(0.88 0.01 260);border-radius:11px;padding:8px 10px;
  font-size:8.5px;font-weight:500;color:oklch(0.661 0.026 262.05);line-height:1.45;min-height:34px;
}
.f-help{margin:7px 0 0;font-size:7.5px;line-height:1.55;font-weight:600;color:var(--muted);letter-spacing:.02em;}
.f-label{margin-top:8px;font-size:9.5px;font-weight:700;color:var(--navy);}
.f-label .req{color:var(--brand);}
/* dropdown outline (véhicule, adresse) */
.f-select{margin-top:6px;display:flex;align-items:center;gap:7px;border:1.3px solid oklch(0.88 0.01 260);border-radius:11px;padding:8px 10px;background:var(--surface);}
.f-select .ic{font-size:11px;color:var(--navy);}
.f-select .tx{flex:1;font-size:9px;font-weight:600;color:var(--navy);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
.f-select .tx.ph{color:oklch(0.661 0.026 262.05);font-weight:500;}
.f-select .chev{font-size:9px;color:var(--navy);}
/* tuiles PIÈCES / LIEU : icône en haut, libellé dessous ; active = navy pleine */
.f-tiles{display:flex;gap:8px;margin-top:7px;}
.f-tile{
  flex:1;min-width:0;display:flex;flex-direction:column;align-items:flex-start;gap:6px;
  border:1.3px solid oklch(0.88 0.01 260);border-radius:12px;padding:9px 9px;background:var(--surface);
  transition:transform .16s var(--ease-out), background-color .25s ease, border-color .25s ease;
}
.f-tile .ic{font-size:11px;color:var(--navy);}
.f-tile span{font-size:7.5px;font-weight:700;color:var(--navy);white-space:nowrap;}
.f-tile.on{background:var(--navy);border-color:var(--navy);}
.f-tile.on .ic,.f-tile.on span{color:#fff;}
.f-tile.pressd{transform:scale(.95);}
/* CTA collant en bas d'écran : grisé tant que le formulaire est incomplet */
.cta-sticky{
  position:absolute;left:11px;right:11px;bottom:76px;z-index:4;
  transition:background-color .35s ease, color .35s ease, transform .16s var(--ease-out);
}
.p-cta.is-off{background:oklch(0.9 0.008 260);color:oklch(0.6 0.02 262);box-shadow:none;}
.p-cta.is-off .arr{color:oklch(0.6 0.02 262);}

/* ÉCRAN 4 — propositions (réplique app-annonces) */
/* chips statut : En attente ambre pleine, Acceptées outline vert, Terminées outline navy */
.p-fchips{display:flex;gap:6px;padding:7px 11px 2px;flex:none;}
.fc{display:inline-flex;align-items:center;gap:4px;border-radius:100px;padding:5px 9px;font-size:8px;font-weight:700;white-space:nowrap;}
.fc .ic{font-size:9px;}
.fc-wait{background:var(--warning);color:#fff;}
.fc-ok{background:var(--surface);border:1.2px solid var(--success);color:var(--navy);}
.fc-ok .ic{color:var(--success);}
.fc-done{background:var(--surface);border:1.2px solid var(--navy);color:var(--navy);}
.pad-offres{padding:8px 11px 0;gap:9px;overflow:hidden;}
/* feuille blanche annonce > carte proposition > actions > pager */
.p-prop{
  background:var(--surface);border-radius:18px;padding:9px 10px 10px;flex:none;
  box-shadow:0 1px 3px oklch(0.242 0.061 259.51 / .04), 0 8px 20px oklch(0.242 0.061 259.51 / .06);
  opacity:0;transform:translateY(16px);
  transition:opacity .45s ease, transform .5s var(--ease-out);
}
.p-prop.in{opacity:1;transform:translateY(0);}
.ppc{border-radius:14px;padding:10px 11px;box-shadow:0 2px 6px oklch(0.242 0.061 259.51 / .06), 0 9px 22px oklch(0.242 0.061 259.51 / .1);}
.ppc .head{display:flex;align-items:center;gap:8px;}
.ppc .avatar{width:30px;height:30px;font-size:9.5px;}
.ppc .who{display:flex;flex-direction:column;gap:2px;min-width:0;}
.ppc .n{font-size:10.5px;font-weight:800;color:var(--navy);white-space:nowrap;}
.ppc .note{display:flex;align-items:center;gap:3px;font-size:8.5px;font-weight:700;color:var(--navy);font-variant-numeric:tabular-nums;}
.ppc .note .ic{font-size:9px;}
.ppc .cnt{color:var(--muted);font-weight:600;}
.ppc .ol{margin-top:8px;font-size:6.5px;font-weight:700;letter-spacing:.12em;text-transform:uppercase;color:var(--muted);}
/* prix orange géant (la loi de la marque) */
.ppc .price{font-size:21px;font-weight:800;color:var(--brand);line-height:1.1;letter-spacing:-.01em;font-variant-numeric:tabular-nums;}
/* encart navy 3 lignes CRÉNEAU / PIÈCES / LIEU */
.nrows{margin-top:7px;background:var(--navy);border-radius:10px;padding:0 10px;}
.nrows .row{display:flex;align-items:center;gap:6px;padding:7px 0;border-bottom:1px solid oklch(1 0 0 / .12);color:#fff;}
.nrows .row:last-child{border-bottom:none;}
.nrows .ic{font-size:9px;opacity:.9;}
.nrows .l{font-size:6.5px;font-weight:700;letter-spacing:.1em;text-transform:uppercase;opacity:.65;}
.nrows .v{font-size:8.5px;font-weight:700;white-space:nowrap;}
/* bulle commentaire du pro */
.ppc .msg{margin-top:7px;display:flex;align-items:center;gap:5px;font-size:8.5px;font-weight:600;color:var(--navy);}
.ppc .msg .ic{font-size:10px;}
.p-prop .acts{display:flex;gap:7px;margin-top:9px;padding:0 2px;}
.b-refuse{
  flex:1;display:flex;align-items:center;justify-content:center;
  background:var(--surface);border:1.2px solid oklch(0.577 0.215 27.32);color:oklch(0.53 0.2 27.32);
  border-radius:100px;height:27px;font-size:9px;font-weight:700;
}
.b-accept{
  flex:1.15;display:flex;align-items:center;justify-content:center;
  background:var(--navy);color:#fff;border-radius:100px;height:27px;
  font-size:9px;font-weight:700;
  transition:transform .16s var(--ease-out);
}
.b-accept.pressd{transform:scale(.94);}
.b-view{
  margin:7px 2px 0;display:flex;align-items:center;justify-content:center;
  height:27px;border-radius:100px;border:1.3px solid var(--navy);color:var(--navy);
  font-size:9px;font-weight:700;background:var(--surface);
}
/* pager : tiret orange actif + « 1 / 2 » */
.p-prop .pager{display:flex;justify-content:center;gap:4px;margin-top:8px;}
.p-prop .pager .dash{width:8px;height:3px;border-radius:2px;background:oklch(0.875 0.012 261.33);}
.p-prop .pager .dash.on{width:14px;background:var(--brand);}
.p-prop .pgn{text-align:center;font-size:7.5px;font-weight:600;color:var(--muted);margin-top:3px;font-variant-numeric:tabular-nums;}

/* ÉCRAN 5 — suivi (réplique flow-06) */
.pad-suivi{padding:8px 11px 0;gap:7px;overflow:hidden;}
/* bandeau vert « Proposition acceptée » */
.sv-banner{
  display:flex;align-items:center;gap:8px;background:var(--success-bg);border-radius:13px;padding:8px 10px;flex:none;
  opacity:0;transform:translateY(-8px);
  transition:opacity .4s ease, transform .45s var(--ease-out);
}
.sv-banner.in{opacity:1;transform:translateY(0);}
.sv-banner .ck{width:22px;height:22px;border-radius:100px;background:var(--success);display:flex;align-items:center;justify-content:center;flex:none;}
.sv-banner .ck .ic{font-size:11px;color:#fff;}
.sv-banner .tx{display:flex;flex-direction:column;gap:1px;min-width:0;}
.sv-banner .t{font-size:10px;font-weight:800;color:var(--success-text);}
.sv-banner .s{font-size:7.5px;font-weight:600;color:var(--success-text);opacity:.85;white-space:nowrap;}
.sv-title{border-radius:14px;padding:9px 12px;display:flex;flex-direction:column;gap:2px;flex:none;}
.sv-title .t{font-size:10px;font-weight:800;color:var(--navy);}
.sv-title .m{font-size:8px;font-weight:600;color:var(--muted);}
.sv-pro{border-radius:14px;padding:9px 12px;display:flex;align-items:center;gap:8px;flex:none;}
.sv-pro .avatar{width:28px;height:28px;font-size:9px;}
.sv-pro .who{flex:1;display:flex;flex-direction:column;gap:2px;min-width:0;}
.sv-pro .n{font-size:10px;font-weight:800;color:var(--navy);}
.sv-pro .note{display:flex;align-items:center;gap:3px;font-size:8px;font-weight:700;color:var(--navy);}
.sv-pro .note .ic{font-size:8.5px;}
.sv-pro .cnt{color:var(--muted);font-weight:600;white-space:nowrap;}
.sv-pro .chatbtn{
  width:24px;height:24px;border-radius:100px;border:1px solid var(--hairline);flex:none;
  display:flex;align-items:center;justify-content:center;box-shadow:var(--shadow-soft);
}
.sv-pro .chatbtn .ic{font-size:10px;color:var(--navy);}
.sv-rdv{border-radius:14px;padding:9px 12px;flex:none;}
.sv-rdv .row{display:flex;gap:7px;margin-top:6px;align-items:flex-start;}
.sv-rdv .row .ic{font-size:10px;color:var(--navy);margin-top:1px;}
.sv-rdv .tx{display:flex;flex-direction:column;gap:1px;}
.sv-rdv .v{font-size:9px;font-weight:700;color:var(--navy);font-variant-numeric:tabular-nums;}
.sv-rdv .m{font-size:7.5px;font-weight:500;color:var(--muted);}
.sv-statut{border-radius:14px;padding:9px 12px 10px;flex:none;}
.sv-statut .hint{display:flex;gap:6px;margin-top:6px;font-size:7.5px;line-height:1.45;font-weight:500;color:var(--muted);}
.sv-statut .hint .ic{font-size:9px;flex:none;margin-top:1px;color:var(--muted);}
/* timeline verticale : check vert → bouclier vert → 2 cercles vides */
.tl{margin-top:8px;}
.tl-it{position:relative;display:flex;gap:8px;padding-bottom:11px;}
.tl-it:last-child{padding-bottom:0;}
.tl-it::after{content:"";position:absolute;left:8px;top:19px;bottom:1px;width:2px;border-radius:2px;background:oklch(0.9 0.008 260);}
.tl-it:last-child::after{display:none;}
.tl-it.g::after{background:var(--success);}
.tdot{width:18px;height:18px;border-radius:100px;flex:none;display:flex;align-items:center;justify-content:center;position:relative;z-index:1;}
.tdot.ok{background:var(--success);}
.tdot.ok .ic{font-size:9px;color:#fff;}
.tdot.sh{background:var(--success-bg);box-shadow:inset 0 0 0 1.2px var(--success);}
.tdot.sh .ic{font-size:9px;color:var(--success);}
.tdot.empty{background:var(--surface);box-shadow:inset 0 0 0 1.5px oklch(0.875 0.012 261.33);}
.tl-it .tx{display:flex;flex-direction:column;gap:1px;min-width:0;padding-top:1px;}
.tl-it .t{font-size:9px;font-weight:800;color:var(--navy);}
.tl-it .m{font-size:7.5px;line-height:1.45;font-weight:500;color:var(--muted);}
/* pop springy des étapes remplies (déclenché par le player) */
#d-step-1 .tdot,#d-step-2 .tdot{transform:scale(0);transition:transform .45s var(--ease-out);}
#d-step-1 .tx,#d-step-2 .tx{opacity:0;transform:translateY(4px);transition:opacity .35s ease .1s, transform .35s ease .1s;}
#d-step-1::after,#d-step-2::after{transform:scaleY(0);transform-origin:top;transition:transform .4s ease .15s;}
#d-step-1.in .tdot,#d-step-2.in .tdot{transform:scale(1);}
#d-step-1.in .tx,#d-step-2.in .tx{opacity:1;transform:translateY(0);}
#d-step-1.in::after,#d-step-2.in::after{transform:scaleY(1);}
/* toast Conseil (glisse depuis le bas) */
.sv-toast{
  position:absolute;left:10px;right:10px;bottom:84px;z-index:5;
  display:flex;align-items:flex-start;gap:8px;
  background:var(--surface);border-radius:14px;padding:9px 10px;
  box-shadow:0 4px 10px oklch(0.242 0.061 259.51 / .12), 0 16px 36px oklch(0.242 0.061 259.51 / .22);
  opacity:0;transform:translateY(26px);
  transition:opacity .4s ease, transform .45s var(--ease-out);
}
.sv-toast.in{opacity:1;transform:translateY(0);}
.sv-toast img{width:30px;height:auto;flex:none;}
.sv-toast .tx{display:flex;flex-direction:column;gap:2px;min-width:0;}
.sv-toast .t{font-size:9px;font-weight:800;color:var(--navy);}
.sv-toast .m{font-size:7.5px;line-height:1.5;font-weight:500;color:var(--muted);}
.sv-toast .x{margin-left:auto;flex:none;padding:2px;}
.sv-toast .x .ic{font-size:8px;color:var(--navy);}

/* recherche : texte tapé caractère par caractère + curseur clignotant */
.p-search .val{color:var(--navy);font-weight:600;flex:none;}
.p-search .caret{flex:none;width:1.5px;height:13px;margin-left:1px;background:var(--navy);border-radius:1px;opacity:0;padding:0;}
.p-search.typing .ph{display:none;}
.p-search.typing .caret{animation:dCaret 1s steps(1) infinite;}
@keyframes dCaret{0%,60%{opacity:1;}61%,100%{opacity:0;}}



/* ---------- Prestations (pattern carte-photo-prix de l'app, format web) ----------
   padding-top généreux : la page respire entre le bord arrondi navy du hero
   et le titre (demande client). */
.svc-head h2{font-size:clamp(30px,3.9vw,44px);margin:0;}
.svc-grid{
  list-style:none;margin:28px 0 0;padding:0;
  display:grid;grid-template-columns:repeat(auto-fit,minmax(min(240px,100%),1fr));gap:20px;
}
.svc{
  position:relative;border-radius:var(--r-card);overflow:hidden;aspect-ratio:1/1;
  background:var(--navy);box-shadow:var(--shadow-card);
  transition:box-shadow .3s var(--ease-out);
}
/* la photo respire légèrement quand le pointeur passe : signal unique, aucune
   promesse de clic (la carte n'est pas un lien tant que l'app n'est pas publiée) */
.svc > img{transition:transform .6s var(--ease-out);}
@media (hover:hover) and (pointer:fine){
  .svc:hover > img{transform:scale(1.045);}
  .svc:hover{box-shadow:0 2px 6px oklch(0.242 0.061 259.51 / .08), 0 14px 34px oklch(0.242 0.061 259.51 / .14);}
}
.svc > img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;display:block;}
.svc-ol{
  position:absolute;inset:0;
  background:linear-gradient(180deg, oklch(0.242 0.061 259.51 / 0) 28%, oklch(0.242 0.061 259.51 / .62) 55%, oklch(0.242 0.061 259.51 / .95) 100%);
  box-shadow:inset 0 0 0 1px oklch(0 0 0 / .1); /* liseré image */
}
.svc-meta{position:absolute;left:20px;right:20px;bottom:18px;}
.svc-meta .n{font-size:clamp(18px,1.7vw,22px);font-weight:800;color:#fff;line-height:1.2;letter-spacing:-.015em;margin:0;}
/* prix discret et orange (la loi de la marque : l'orange marque le prix) —
   info marketing gardée au-dessus du bouton, l'app ne l'affiche plus */
.svc-meta .price{
  display:block;margin-top:12px;
  font-size:15px;font-weight:800;color:var(--brand-hero);
  font-variant-numeric:tabular-nums;
}
/* pilule claire translucide « Publier → » texte orange, pattern app 13/07 */
.svc-meta .publish{
  margin-top:9px;display:flex;align-items:center;justify-content:space-between;
  background:oklch(1 0 0 / .92);border-radius:100px;padding:11px 18px;
  font-size:14.5px;font-weight:700;color:var(--brand-text-strong);
  backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px);
}
.svc-meta .publish .ic{font-size:14px;color:var(--brand-text);}
.svc-note{margin:16px 0 0;max-width:70ch;font-size:12.5px;font-weight:500;color:var(--muted);}
/* ligne cas d'usage entre le nom et le prix : ton concret, 1 ligne, tronquée
   proprement si la carte est trop étroite (grille auto-fit) */
.svc-meta .usage{
  display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;overflow:hidden;
  margin-top:6px;font-size:12.5px;font-weight:500;line-height:1.4;
  color:oklch(1 0 0 / .82);
}

/* stagger des reveals : ~100ms par carte (desktop, grille) */
@media (min-width:900px){
  .svc-grid .svc:nth-child(2){transition-delay:.1s;}
  .svc-grid .svc:nth-child(3){transition-delay:.2s;}
  .svc-grid .svc:nth-child(4){transition-delay:.3s;}
}

/* < 900px : carrousel horizontal scroll-snap (pattern exact de l'app :
   cartes ~72vw, la suivante dépasse du bord droit pour inviter au swipe).
   Full-bleed via marges négatives DANS le scroller → aucun scroll
   horizontal de la page elle-même. Desktop ≥900px : grille inchangée. */
@media (max-width:899px){
  .svc-grid{
    display:flex;gap:14px;
    margin:24px calc(var(--gutter) * -1) 0;
    padding:4px var(--gutter) 18px;
    overflow-x:auto;overscroll-behavior-x:contain;
    scroll-snap-type:x mandatory;scroll-padding-left:var(--gutter);
    -webkit-overflow-scrolling:touch;
    scrollbar-width:none;
  }
  .svc-grid::-webkit-scrollbar{display:none;}
  .svc{flex:0 0 72vw;max-width:340px;scroll-snap-align:start;}
  /* les cartes hors écran à droite ne doivent pas rester invisibles (reveal) */
  .svc-grid > .svc.reveal{opacity:1;transform:none;transition:none;}
}

/* ---------- Sections communes ---------- */
.section-white{background:var(--surface);}
.rounded-top{border-radius:44px 44px 0 0;box-shadow:0 -20px 50px oklch(0.242 0.061 259.51 / .05);position:relative;}
.eyebrow{font-size:12px;font-weight:800;letter-spacing:.09em;color:var(--brand-text);text-transform:uppercase;}
h2{font-weight:800;letter-spacing:-.035em;line-height:1.1;margin:0;color:var(--navy);}
h2 .dot{display:inline-block;transition:transform .45s var(--ease-signature) .25s;}
.reveal:not(.in) h2 .dot{transform:scale(0);}
h2.reveal:not(.in) .dot{transform:scale(0);}

/* ---------- Parcours : comment ça marche + prestations ---------- */
#parcours .inner{padding-top:clamp(64px,9vw,104px);padding-bottom:clamp(48px,6vw,72px);}
#parcours .svc-head{margin-top:clamp(48px,7vw,80px);}
.h2-row{display:flex;align-items:flex-end;justify-content:flex-start;gap:clamp(20px,4vw,52px);}
.h2-row h2{font-size:clamp(32px,4.4vw,46px);}
.h2-row .tagline{display:block;margin-top:10px;font-size:16px;font-weight:700;color:var(--brand-text);}
/* Trois cartes identiques (icône + titre + texte) : c'est LA grille que les
   deux référentiels de design interdisent. Les étapes redeviennent une
   séquence — des colonnes séparées par un filet, numérotées, sans boîte. */
.steps{
  display:grid;grid-template-columns:repeat(auto-fit,minmax(min(230px,100%),1fr));
  gap:0;margin-top:clamp(32px,4vw,52px);
  border-top:1px solid var(--hairline);
}
.step{
  background:none;border-radius:0;padding:clamp(22px,2.4vw,30px) clamp(18px,2vw,26px) clamp(26px,3vw,34px) 0;
  display:flex;flex-direction:column;gap:12px;
  border-bottom:1px solid var(--hairline);
}
@media (min-width:760px){
  .step + .step{padding-left:clamp(22px,2.6vw,34px);border-left:1px solid var(--hairline);}
}
/* stagger des reveals : ~100ms par étape */
@media (min-width:900px){
  .steps .step:nth-child(2){transition-delay:.1s;}
  .steps .step:nth-child(3){transition-delay:.2s;}
}
.step-head{display:flex;align-items:baseline;gap:12px;}
.step-num{
  /* le chiffre n'a plus besoin d'une pastille : il porte lui-même */
  font-size:clamp(30px,3.4vw,40px);font-weight:800;line-height:1;
  color:var(--brand-text);letter-spacing:-.03em;font-variant-numeric:tabular-nums;
}
.step-head .ic{color:var(--brand-text);font-size:19px;align-self:center;}
.step .t{font-size:clamp(17px,1.5vw,19px);font-weight:800;letter-spacing:-.01em;}
.step .d{font-size:14px;font-weight:500;line-height:1.6;text-wrap:pretty;}

/* ---------- Mécaniciens (une seule section navy pleine) ---------- */
#mecanos{background:var(--navy);overflow:hidden;}
#mecanos .inner{
  /* la bande navy sépare déjà : elle n'a pas besoin d'autant d'air */
  padding-top:clamp(52px,6.5vw,76px);padding-bottom:clamp(52px,6.5vw,76px);
  /* minmax(0,1fr) et non 1fr : sinon la colonne prend la largeur mini de son
     contenu (les trois devices) et déborde du cadre sur petit écran */
  display:grid;grid-template-columns:minmax(0,1fr);
  gap:clamp(30px,5vw,64px);align-items:center;
}
/* Plus de deux colonnes ici depuis le 11/08 : la scène de droite n'est plus faite
   de trois devices figés mais d'une piste d'annonces qui défile, et une piste a
   besoin de la largeur entière. Le texte tient au-dessus, la bande court dessous. */
/* sur navy, l'orange marque pur passe AA (4.58:1) même en petit */
#mecanos .eyebrow{color:var(--brand);}
#mecanos h2{font-size:clamp(30px,3.8vw,44px);line-height:1.12;margin:14px 0 0;color:#fff;}
#mecanos .lead{font-size:16px;font-weight:500;line-height:1.7;margin:20px 0 0;color:#fff;max-width:460px;}
#mecanos .btn{margin-top:28px;}
/* sur fond navy, le CTA navy serait invisible : pilule inversée blanche,
   texte navy 700 + point orange — même signature « mécaly. » */
#mecanos .btn-primary{background:var(--surface);color:var(--navy);box-shadow:0 2px 6px oklch(0 0 0 / .2), 0 14px 30px oklch(0 0 0 / .3);}
#mecanos .btn-primary:hover{background:var(--bg);}
/* Le HAUT de la section : l'argumentaire à gauche, l'écran du pro à droite. La piste
   d'annonces vit maintenant DANS ce panneau, en fond (`.mecanos-bg`) : le téléphone
   montre l'OUTIL (sa zone, sa liste) devant, la piste montre le VOLUME de travail qui
   arrive derrière. */
.mecanos-haut{
  display:grid;grid-template-columns:minmax(0,1fr);
  gap:clamp(28px,4.5vw,56px);
  /* `start`, pas `center` : agrandi, le téléphone dépasse largement le bloc de texte —
     centrés sur sa hauteur, l'argumentaire ET son bouton « Rejoindre Mécaly » glissaient
     jusqu'à chevaucher la piste d'annonces en fond de panneau. Calé en haut, le texte
     reste sous le titre, où il doit être. */
  align-items:start;
}
/* La piste en fond : hors du flux de la grille (`position:absolute`), le panneau la
   recadre à ses coins arrondis (`overflow:hidden` sur `.mecanos-panneau`). Fondu sur
   les DEUX bords — plus seulement à droite — puisqu'elle est maintenant confinée dans
   une boîte et non plus à cheval sur le bord de l'écran. */
.mecanos-bg{
  position:absolute;inset:0;margin:0 !important;padding:0;
  z-index:0;display:flex;align-items:flex-end;
  /* Basse plutôt que centrée : centrée, la piste passait EN PLEIN sur « Développez
     votre activité avec Mécaly » — un fond ne doit jamais concurrencer le titre qu'il
     accompagne. Calée en bas, elle ne mord plus que sur la marge basse du panneau. */
  padding-bottom:clamp(10px,2vw,18px);
  pointer-events:none;
}
.mecanos-bg .annonces-piste{
  margin:0;padding:0;
  -webkit-mask-image:linear-gradient(90deg, transparent 0, #000 64px, #000 calc(100% - 64px), transparent 100%);
  mask-image:linear-gradient(90deg, transparent 0, #000 64px, #000 calc(100% - 64px), transparent 100%);
}
/* `margin-top` ajouté le 15/08 (BOSS : « descends un peu le téléphone de la partie
   mécanicien »). Il arrivait plus haut que le paragraphe qu'il accompagne ; décalé vers le
   bas, il s'aligne sur le corps du texte au lieu de le devancer. En `clamp` et non en
   pixels : la colonne de texte grandit avec la fenêtre, un décalage fixe se décrocherait à
   l'une des deux extrémités. */
.mecanos-device{justify-self:center;position:relative;z-index:1;}
.mecanos-haut > .reveal:not(.mecanos-bg){position:relative;z-index:1;margin-top:clamp(6px,1vw,14px);}
/* ⚠️ SPÉCIFICITÉ — le même piège que celui déjà documenté plus bas dans ce fichier, et il
   m'a eu : posé sur `.mecanos-device` seul (0,1,0), ce `margin-top` était écrasé par la
   règle juste au-dessus, `.mecanos-haut > .reveal:not(.mecanos-bg)` (0,3,0), qui matche AUSSI
   cet élément puisqu'il porte `.reveal`. Mesuré au navigateur : 12,8 px appliqués au lieu
   des 57,6 px demandés — silencieusement, sans rien dans la console.
   Le sélecteur ci-dessous pèse 0,3,0 lui aussi et vient après : il gagne.
   Descendre le téléphone est une demande du BOSS (15/08) — il arrivait plus haut que le
   paragraphe qu'il accompagne. En `clamp` et non en pixels, la colonne de texte à côté
   grandissant avec la fenêtre. */
.mecanos-haut > .mecanos-device.reveal{margin-top:clamp(20px,4.5vw,58px);}
/* Agrandi (15/08, tard) — la maquette d'origine le voulait plus discret que celui du
   hero, mais à cette taille il se perdait à côté de la piste d'annonces qui vient
   d'entrer dans le même panneau.
   Taille conservée (15/08, encore plus tard) : le problème n'était pas la taille du
   téléphone mais le fait qu'il imposait sa hauteur au panneau ENTIER (grille en
   colonnes, la ligne suit son item le plus haut) — corrigé plus bas en le sortant du
   flux de la grille à ≥900px (`.mecanos-panneau .mecanos-device`), pas ici. */
.mecanos-device .phone{width:clamp(300px,38vw,480px);}
/* pas de `.phone-screen` ici : le mockup EST l'image, cadre compris (même parti que
   le téléphone du fond dans le hero) — donc la règle de dimension lui va directement. */
.mecanos-device .phone--flat img{width:100%;height:auto;display:block;}
@media (min-width:900px){
  .mecanos-haut{grid-template-columns:minmax(0,1.08fr) minmax(0,.92fr);}
  .mecanos-device{justify-self:end;}
}
@media (min-width:1100px){
  .pro-device{position:absolute;left:0;top:50%;transform:translateY(-50%);}
}
@media (max-width:1099px){
  .pro-device{width:-moz-fit-content;width:fit-content;margin:30px auto 0;}
}
/* le mockup garde ses dimensions internes (contenu en px) : largeur fixe,
   et on neutralise les scale() que le hero applique globalement à .phone */

/* ----- Carte de zone : VRAIE carte de Marseille (tuiles CARTO locales) -----
   Image 880×880 centrée sur Marseille : le conteneur reste CARRÉ pour que les
   positions % (projection Mercator) tombent juste. Rayon 15 km = 37,92 % de
   la largeur → cercle de 75,84 % centré. */
.zone-map{
  position:relative;aspect-ratio:1/1;border-radius:var(--r-card);overflow:hidden;
  box-shadow:0 2px 6px oklch(0 0 0 / .2), 0 30px 70px oklch(0 0 0 / .32);
  outline:1px solid oklch(1 0 0 / .16);outline-offset:-1px;
}
.zm-map{position:absolute;inset:0;width:100%;height:100%;display:block;object-fit:cover;}
/* cercle de zone : mêmes réglages que le RadiusMap Leaflet de l'app
   (trait #F05000 2,5px, remplissage orange 10 %) */
.zm-circle{
  position:absolute;left:50%;top:50%;width:75.84%;aspect-ratio:1/1;
  transform:translate(-50%,-50%);border-radius:50%;
  border:2.5px solid var(--brand);background:oklch(0.646 0.207 38.94 / .10);
}
/* halo du cercle : invisible par défaut (reduced-motion/no-JS), il n'existe
   que par son animation. Margin % = relatif à la largeur → centrage exact. */
.zm-pulse{
  position:absolute;left:50%;top:50%;width:75.84%;aspect-ratio:1/1;
  margin:-37.92% 0 0 -37.92%;border-radius:50%;background:var(--brand);opacity:0;
}
/* pin central : la position du mécanicien, au centre exact de Marseille */
.zm-center{
  position:absolute;left:50%;top:50%;z-index:2;width:17px;height:17px;margin:-8.5px 0 0 -8.5px;
  border-radius:50%;background:var(--brand);border:3px solid #fff;
  box-shadow:0 3px 7px oklch(0.242 0.061 259.51 / .38);
}
/* pilule de zone = la puce « Zone » de l'app, navy pleine, posée sur le cercle */
.zm-zone-chip{
  position:absolute;transform:translate(-50%,-50%);z-index:2;
  display:inline-flex;align-items:center;gap:5px;white-space:nowrap;
  background:var(--navy);color:#fff;border-radius:100px;padding:7px 13px;
  font-size:11.5px;font-weight:700;
  box-shadow:0 2px 6px oklch(0 0 0 / .18), 0 10px 24px oklch(0.242 0.061 259.51 / .3);
}
.zm-zone-chip .ic{font-size:11px;color:#fff;}
/* marqueur annonce : étiquette blanche empilée (presta / km · prix orange) +
   pin navy, pointe du pin ancrée sur la position (translate(-50%,-100%)).
   Étiquette ÉTROITE (2 lignes) : les 4 lieux réels se serrent au NE de la
   carte, une étiquette large les ferait se chevaucher. --cdx : nudge
   horizontal optionnel par étiquette (désamorce un chevauchement précis). */
.zm-marker{
  position:absolute;transform:translate(-50%,-100%);z-index:2;
  display:flex;flex-direction:column;align-items:center;gap:2px;
}
.zm-chip{
  position:relative;
  display:flex;flex-direction:column;align-items:center;line-height:1.3;white-space:nowrap;
  background:var(--surface);border-radius:9px;padding:4px 9px 5px;
  box-shadow:0 1px 2px oklch(0 0 0 / .14), 0 8px 20px oklch(0.242 0.061 259.51 / .24);
  transform:translateX(var(--cdx,0px));
}
.zm-chip .n{font-size:10.5px;font-weight:700;color:var(--navy);}
.zm-chip small{font-size:8px;font-weight:600;color:var(--muted);font-variant-numeric:tabular-nums;}
.zm-chip small b{font-weight:800;color:var(--brand-text);}
.zm-pin{display:block;width:19px;height:24px;filter:drop-shadow(0 3px 4px oklch(0 0 0 / .28));}
.zm-pin path{transition:fill .35s ease;}
/* variante zm-side : étiquette à DROITE du pin (Allauch, coin dense) —
   le marqueur ne mesure que le pin, l'étiquette est posée en absolu */
.zm-marker.zm-side .zm-chip{position:absolute;left:calc(50% + 14px);bottom:6px;align-items:flex-start;}
/* état « offre envoyée » (la démo du téléphone répond sur la carte) :
   pin vert + coche verte qui pop sur l'étiquette */
.zm-chip .okdot{
  position:absolute;top:-6px;right:-6px;width:14px;height:14px;border-radius:50%;
  background:var(--success);border:2px solid #fff;
  display:flex;align-items:center;justify-content:center;
  transform:scale(0);transition:transform .45s var(--ease-out);
}
.zm-chip .okdot .ic{font-size:7px;color:#fff;}
#zm-allauch.sent .zm-pin path{fill:var(--success);}
#zm-allauch.sent .okdot{transform:scale(1);}
/* attribution des tuiles (obligatoire) : lisible mais effacée */
.zm-attrib{
  position:absolute;right:7px;bottom:5px;z-index:2;
  font-size:8.5px;font-weight:500;letter-spacing:.01em;
  color:oklch(0.242 0.061 259.51 / .55);background:oklch(1 0 0 / .62);
  padding:2px 6px;border-radius:6px;
}
/* petite carte (mobile) : étiquettes réduites pour laisser respirer le fond */
@media (max-width:560px){
  .zm-zone-chip{font-size:10.5px;padding:6px 11px;}
  .zm-chip{padding:3px 6px 4px;}
  .zm-chip .n{font-size:9px;}
  .zm-chip small{font-size:7px;}
  .zm-pin{width:16px;height:20px;}
  .zm-marker.zm-side .zm-chip{left:calc(50% + 11px);bottom:4px;}
  .zm-center{width:14px;height:14px;margin:-7px 0 0 -7px;border-width:2.5px;}
}
/* animations : cascade des pins (une fois, à l'entrée dans le viewport) +
   halo qui pulse sur le cercle (en pause hors viewport). Le JS pose .js-anim
   au chargement, .play/.in-view via IntersectionObserver ; sans JS ou en
   reduced-motion, tout est visible et statique. */
@media (prefers-reduced-motion: no-preference){
  .zone-map.js-anim .zm-marker,
  .zone-map.js-anim .zm-zone-chip{opacity:0;}
  .zone-map.js-anim.play .zm-zone-chip{animation:zmFade .5s ease .1s both;}
  .zone-map.js-anim.play .zm-marker{animation:zmPop .55s var(--ease-out) both;}
  .zone-map.js-anim.play .zm-marker:nth-of-type(2){animation-delay:.3s;}
  .zone-map.js-anim.play .zm-marker:nth-of-type(3){animation-delay:.45s;}
  .zone-map.js-anim.play .zm-marker:nth-of-type(4){animation-delay:.6s;}
  .zm-pulse{
    animation:zmPulse 3.4s cubic-bezier(.25,.55,.6,1) infinite;animation-play-state:paused;
  }
  .zone-map.in-view .zm-pulse{animation-play-state:running;}
}
@keyframes zmPop{
  from{opacity:0;transform:translate(-50%,-100%) translateY(10px) scale(.82);}
  to{opacity:1;transform:translate(-50%,-100%);}
}
@keyframes zmFade{from{opacity:0;}to{opacity:1;}}
/* pulse discret : sur une vraie carte claire, un halo plein à .25 noyait la
   ville sous un voile saumon — on part de .12 et on s'éteint plus tôt */
@keyframes zmPulse{
  0%{transform:scale(.1);opacity:.12;}
  70%{opacity:.04;}
  100%{transform:scale(1);opacity:0;}
}

/* ----- Écran pro du téléphone (compléments aux composants p-* du hero) -----
   Le device pro réutilise le système d'écrans du hero (.p-screens/.p-screen,
   slides natifs, doigt fantôme) : seul le tableau de bord (s-phome) est
   transparent, les écrans poussés gardent le fond gris clair. */
.p-screen.s-phome{background:transparent;}
/* chips du hero pro : 3 chips dont une large (ville + rayon + caret) → corps
   réduit pour tenir sur la largeur de la carte navy sans déborder */
#mecanos .p-chips{gap:6px;margin-top:9px;}
#mecanos .p-chip{font-size:8.5px;padding:9px 4px;gap:4px;}
#mecanos .p-chip .ic{font-size:11px;}
.pm-chip-zone{flex:1.4;}
.pm-chip-zone .pm-caret{font-size:7px;margin-left:-1px;}
.pm-chip-cal{flex:0 0 30px;}
#mecanos .p-welcome{padding:14px 13px 13px;}
#mecanos .p-search{margin-top:10px;height:34px;}
/* « Complétez votre profil · 75 % » : hairline, pastille brand-tint, barre orange */
.pm-completion{
  display:flex;align-items:center;gap:8px;margin-top:10px;padding-top:10px;
  border-top:1px solid oklch(1 0 0 / .18);
}
.pm-completion .pic{
  width:26px;height:26px;border-radius:9px;background:var(--brand-tint);flex:none;
  display:flex;align-items:center;justify-content:center;
}
.pm-completion .pic .ic{color:var(--brand);font-size:12px;}
.pm-completion .bd{flex:1;min-width:0;}
.pm-completion .line{display:flex;justify-content:space-between;align-items:baseline;font-size:10px;font-weight:700;color:#fff;}
.pm-completion .line .pct{font-variant-numeric:tabular-nums;}
.pm-completion .chev{color:#fff;font-size:10px;flex:none;}
.pm-progress{height:4px;border-radius:100px;background:oklch(1 0 0 / .22);margin-top:6px;overflow:hidden;}
.pm-progress span{display:block;height:100%;background:var(--brand);border-radius:100px;}
/* carrousel « Annonces autour de vous » : cartes blanches AnnonceCardBase,
   la 3e coupée par le bord d'écran comme dans l'app */
.pm-annonces{margin-top:9px;}
.pm-annonces .p-sec-head .t{font-size:12px;}
.pm-ann-row{display:flex;gap:8px;overflow:hidden;padding:2px 0 4px 12px;}
.pm-ann{flex:none;width:112px;border-radius:14px;overflow:hidden;}
.pm-ann .ph{position:relative;height:60px;background-color:var(--navy);background-size:cover;background-position:center;}
.pm-ann .city{
  position:absolute;top:6px;left:6px;max-width:calc(100% - 12px);
  display:inline-flex;align-items:center;gap:3px;white-space:nowrap;overflow:hidden;
  background:var(--navy);color:#fff;border-radius:100px;padding:3px 7px;
  font-size:7.5px;font-weight:700;
}
.pm-ann .city .ic{font-size:7px;color:#fff;flex:none;}
.pm-ann .av{
  position:absolute;bottom:5px;right:5px;width:20px;height:20px;border-radius:100px;
  background:linear-gradient(140deg,oklch(0.328 0.071 257.6),var(--navy));
  color:#fff;font-size:6.5px;font-weight:800;display:flex;align-items:center;justify-content:center;
  border:2px solid #fff;
}
.pm-ann .bd{padding:6px 8px 7px;display:flex;flex-direction:column;gap:2px;}
.pm-ann .bd .t{font-size:9.5px;font-weight:700;color:var(--navy);line-height:1.25;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
.pm-ann .pr{display:flex;align-items:baseline;gap:3px;font-size:11px;font-weight:800;color:var(--brand-text);font-variant-numeric:tabular-nums;}
.pm-ann .pr small{font-size:7px;font-weight:600;color:var(--muted);}
/* « Prochains rendez-vous » : état vide réel. La description évite le FAB
   central (padding latéral bas) pour ne pas passer sous lui. */
.pm-rdv{margin-top:9px;padding:0 11px;}
.pm-rdv .p-sec-head{padding:0 1px;margin-bottom:6px;}
.pm-empty{
  border-radius:16px;padding:9px 12px 10px;
  display:flex;flex-direction:column;align-items:center;gap:3px;text-align:center;
}
.pm-empty .ic{font-size:13px;color:var(--navy);}
.pm-empty .t{font-size:9.5px;font-weight:800;color:var(--navy);}
.pm-empty .d{font-size:7.5px;font-weight:500;color:var(--muted);line-height:1.4;}

/* ÉCRAN PRO 2 — détail de l'annonce (réplique pro/annonce/[id].tsx) */
/* padding bas 94 : le CTA pilule reste AU-DESSUS du FAB loupe de la bottom
   bar pro (dans l'app, l'ActionBar flotte au-dessus de la tab bar) */
.pad-pdetail{padding:8px 11px 94px;gap:7px;}
/* en-tête = extension horizontale de la photo (photo pleine hauteur à gauche) */
.pdd-head{display:flex;overflow:hidden;flex:none;}
.pdd-head .ph{flex:none;width:78px;background-color:var(--navy);background-size:cover;background-position:center;}
.pdd-head .bd{flex:1;min-width:0;padding:10px 11px;display:flex;flex-direction:column;justify-content:center;gap:4px;}
.pdd-head .t{font-size:11.5px;font-weight:800;color:var(--navy);line-height:1.2;letter-spacing:-.01em;}
.pdd-head .foot{display:flex;align-items:flex-end;justify-content:space-between;gap:8px;}
.pdd-head .m{font-size:7px;font-weight:600;color:var(--muted);}
.pdd-head .pr{display:flex;flex-direction:column;align-items:flex-end;line-height:1.15;font-size:15px;font-weight:800;color:var(--brand);font-variant-numeric:tabular-nums;}
.pdd-head .pr small{font-size:6.5px;font-weight:600;color:var(--muted);}
/* message du client : carte dédiée, citation entre guillemets */
.pdd-msg{padding:9px 11px 10px;flex:none;}
.ovrow{display:flex;align-items:center;gap:5px;}
.ovrow .ic{font-size:10px;color:var(--navy);}
.pdd-msg p{margin:5px 0 0;font-size:8.5px;line-height:1.5;font-weight:500;color:var(--navy);opacity:.85;}
/* client + véhicule fusionnés, séparés par un filet */
.pdd-client{padding:0 11px;flex:none;}
.pdd-client .row{display:flex;align-items:center;gap:8px;padding:9px 0;}
.pdd-client .row.veh{border-top:1px solid var(--hairline);}
.pdd-client .who{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px;}
.pdd-client .n{font-size:10px;font-weight:800;color:var(--navy);white-space:nowrap;}
.pdd-client .note{display:flex;align-items:center;gap:3px;font-size:8px;font-weight:700;color:var(--navy);font-variant-numeric:tabular-nums;}
.pdd-client .note .ic{font-size:8.5px;color:var(--brand);}
.pdd-client .cnt{color:var(--muted);font-weight:600;white-space:nowrap;}
.pdd-client .sub{font-size:7.5px;font-weight:600;color:var(--muted);}
.pdd-client .chev{margin-left:auto;font-size:10px;color:var(--muted);flex:none;}
.pdd-client .vthumb{
  width:26px;height:26px;border-radius:9px;background:var(--brand-tint);flex:none;
  display:flex;align-items:center;justify-content:center;
}
.pdd-client .vthumb .ic{font-size:12px;color:var(--brand);}
/* conditions : lignes icône + libellé/valeur (InfoRow) */
.pdd-cond{padding:2px 11px;flex:none;}
.pdd-cond .crow{display:flex;align-items:center;gap:8px;padding:7px 0;border-bottom:1px solid var(--hairline);}
.pdd-cond .crow:last-child{border-bottom:none;}
.pdd-cond .crow .ic{font-size:11px;color:var(--navy);flex:none;}
.pdd-cond .tx{display:flex;flex-direction:column;gap:1px;min-width:0;}
.pdd-cond .l{font-size:7px;font-weight:600;color:var(--muted);}
.pdd-cond .v{font-size:8.5px;font-weight:700;color:var(--navy);white-space:nowrap;font-variant-numeric:tabular-nums;}
.pdd-cta{margin-top:auto;}
/* même dégagement pour le CTA collant de l'écran d'offre pro */
#mecanos .cta-sticky{bottom:94px;}

/* ÉCRAN PRO 3 — faire une proposition (réplique F15-pro-offer) */
.pad-poffer{padding:8px 11px 0;gap:7px;overflow:hidden;}
.po-card{border-radius:16px;padding:9px 11px 10px;flex:none;}
/* stepper prix : − / valeur orange géante / + (le prix « se tape » au doigt) */
.po-stepper{display:flex;align-items:stretch;gap:1px;margin-top:7px;background:var(--bg);border-radius:11px;overflow:hidden;}
.po-stepper .stp{
  flex:none;width:30px;display:flex;align-items:center;justify-content:center;
  font-size:13px;font-weight:800;color:var(--navy);background:var(--surface);
  box-shadow:inset 0 0 0 1px var(--hairline);border-radius:11px;
}
.po-stepper .val{
  flex:1;min-width:0;display:flex;align-items:center;justify-content:center;gap:1px;
  padding:8px 4px;font-variant-numeric:tabular-nums;
}
.po-stepper .ph{font-size:15px;font-weight:800;color:oklch(0.78 0.02 262);}
.po-stepper.typing .ph,.po-stepper.filled .ph{display:none;}
.po-stepper .tx{font-size:15px;font-weight:800;color:var(--brand);letter-spacing:-.01em;}
.po-stepper .caret{flex:none;width:1.5px;height:14px;background:var(--navy);border-radius:1px;opacity:0;}
.po-stepper.typing .caret{animation:dCaret 1s steps(1) infinite;}
/* lignes pièces / lieu (toggle orange ON, comme F15) */
.po-row{display:flex;align-items:center;gap:8px;margin-top:7px;}
.po-row .ic{font-size:12px;color:var(--brand);flex:none;}
.po-row .tx{flex:1;min-width:0;display:flex;flex-direction:column;gap:1px;}
.po-row .n{font-size:8.5px;font-weight:700;color:var(--navy);white-space:nowrap;}
.po-row .m{font-size:7px;font-weight:500;color:var(--muted);}
.po-tgl{
  flex:none;width:26px;height:15px;border-radius:100px;background:oklch(0.87 0.012 261);
  position:relative;transition:background-color .25s ease;
}
.po-tgl span{
  position:absolute;top:2px;left:2px;width:11px;height:11px;border-radius:50%;
  background:#fff;box-shadow:0 1px 2px oklch(0 0 0 / .2);transition:transform .25s var(--ease-out);
}
.po-tgl.on{background:var(--brand);}
.po-tgl.on span{transform:translateX(11px);}
.po-card .f-div{margin:9px -1px 0;}
.po-card .f-div + .ov{margin-top:9px;display:block;}
/* pilule créneau : outline au repos → navy pleine quand choisie */
.po-slot{
  margin-top:7px;display:inline-flex;align-items:center;gap:6px;align-self:flex-start;
  border:1.3px solid var(--navy);border-radius:100px;padding:6px 11px;
  font-size:8.5px;font-weight:700;color:var(--navy);background:var(--surface);
  transition:background-color .3s ease, color .3s ease;font-variant-numeric:tabular-nums;
  white-space:nowrap;
}
.po-slot .ic{font-size:9px;color:var(--navy);transition:color .3s ease;}
.po-slot.on{background:var(--navy);color:#fff;}
.po-slot.on .ic{color:#fff;}
/* récap frais 7,5 % : masqué tant que le prix n'est pas saisi */
.po-recap{opacity:0;transform:translateY(10px);transition:opacity .4s ease, transform .45s var(--ease-out);}
.po-recap.in{opacity:1;transform:translateY(0);}
.po-recap .rrow,.psent-recap .rrow{
  display:flex;align-items:baseline;justify-content:space-between;gap:8px;
  padding:4px 0;font-variant-numeric:tabular-nums;
}
.po-recap .l,.psent-recap .l{font-size:8px;font-weight:600;color:var(--muted);}
.po-recap .v,.psent-recap .v{font-size:8.5px;font-weight:700;color:var(--navy);white-space:nowrap;}
.po-recap .rrow.tot,.psent-recap .rrow.tot{border-top:1px solid var(--hairline);margin-top:3px;padding-top:7px;}
.po-recap .tot .l,.psent-recap .tot .l{font-size:9px;font-weight:800;color:var(--navy);}
.po-recap .tot .v,.psent-recap .tot .v{font-size:13px;font-weight:800;color:var(--brand);}

/* ÉCRAN PRO 4 — confirmation « Proposition envoyée ! » (offer-sent.tsx),
   check vert dessiné au trait (dasharray) au lieu de la mascotte */
.psent-body{flex:1;min-height:0;display:flex;flex-direction:column;align-items:center;justify-content:center;padding:0 18px 70px;text-align:center;}
.psent-check{width:54px;height:54px;flex:none;}
.psent-check .c{stroke:var(--success);stroke-width:3;stroke-linecap:round;
  stroke-dasharray:158;stroke-dashoffset:158;transform:rotate(-90deg);transform-origin:center;}
.psent-check .k{stroke:var(--success);stroke-width:4;stroke-linecap:round;stroke-linejoin:round;
  stroke-dasharray:32;stroke-dashoffset:32;}
.psent-check.in .c{transition:stroke-dashoffset .55s var(--ease-out);stroke-dashoffset:0;}
.psent-check.in .k{transition:stroke-dashoffset .35s var(--ease-out) .45s;stroke-dashoffset:0;}
.psent-body .t{margin-top:12px;font-size:14px;font-weight:800;color:var(--navy);letter-spacing:-.015em;}
.psent-body .m{margin-top:6px;font-size:8.5px;font-weight:500;line-height:1.55;color:var(--muted);max-width:200px;}
.psent-recap{margin-top:14px;width:100%;padding:8px 12px 9px;text-align:left;}
.psent-recap .rrow .ic{font-size:10px;color:var(--navy);flex:none;margin-right:-2px;}
.psent-recap .rrow{align-items:center;}
.psent-recap .l{flex:1;}
/* entrée staggerée des éléments de confirmation (pilotée par le player) */
.psent-el{opacity:0;transform:translateY(10px);transition:opacity .4s ease, transform .45s var(--ease-out);}
.psent-el.in{opacity:1;transform:translateY(0);}

/* ---------- Confiance ---------- */
#confiance .inner{padding-top:clamp(68px,9.5vw,112px);padding-bottom:clamp(56px,7vw,84px);}
#confiance h2{font-size:clamp(28px,3.5vw,40px);max-width:18ch;}
/* Cinquième grille de cartes identiques de la page : elle saute. Les garanties
   deviennent une rangée de mentions séparées par des filets — même information,
   aucune boîte, et le regard glisse au lieu de compter des rectangles. */
.trust-grid{
  display:grid;grid-template-columns:repeat(auto-fit,minmax(min(168px,100%),1fr));
  gap:0;margin-top:clamp(36px,5vw,56px);text-align:left;
  border-top:1px solid var(--hairline);
}
.trust-card{
  background:none;border:0;box-shadow:none;border-radius:0;
  padding:22px clamp(14px,1.6vw,22px) 24px 0;
  display:flex;align-items:flex-start;gap:12px;text-align:left;
  border-bottom:1px solid var(--hairline);
}
@media (min-width:760px){
  .trust-card + .trust-card{padding-left:clamp(16px,1.8vw,24px);border-left:1px solid var(--hairline);}
}
/* stagger des reveals : ~80ms par carte */
@media (min-width:900px){
  .trust-grid .trust-card:nth-child(2){transition-delay:.08s;}
  .trust-grid .trust-card:nth-child(3){transition-delay:.16s;}
  .trust-grid .trust-card:nth-child(4){transition-delay:.24s;}
  .trust-grid .trust-card:nth-child(5){transition-delay:.32s;}
}
.trust-card .ic{color:var(--brand-text);font-size:19px;flex:none;margin-top:.15em;}
.trust-card span{font-size:13.5px;font-weight:700;line-height:1.35;}
@media (max-width:479px){
  .trust-grid{grid-template-columns:1fr 1fr;gap:0;}
  .trust-card:last-child{grid-column:1 / -1;}
}

/* ---------- Footer ---------- */
.site-footer{background:var(--navy);color:#fff;}
.site-footer .inner{padding-top:clamp(50px,7vw,70px);padding-bottom:44px;}
.footer-top{display:flex;align-items:center;gap:24px;flex-wrap:wrap;}
.footer-top img{height:30px;width:auto;object-fit:contain;}
.footer-top .tagline{font-size:15px;font-weight:600;}
.footer-top .btn{margin-left:auto;}
/* sur le footer navy, même pilule inversée que la section mécaniciens */
.site-footer .btn-primary{background:var(--surface);color:var(--navy);box-shadow:0 2px 6px oklch(0 0 0 / .2), 0 14px 30px oklch(0 0 0 / .3);}
.site-footer .btn-primary:hover{background:var(--bg);}
.footer-sep{height:1px;background:oklch(1 0 0 / .14);margin:34px 0 26px;}
.footer-links{display:flex;gap:8px 24px;flex-wrap:wrap;align-items:center;font-size:13.5px;font-weight:600;}
.footer-links a{color:#fff;text-decoration:none;padding:12px 0;transition:color .15s ease;}
.footer-links a:hover{color:oklch(0.781 0.139 47.2);}
.footer-links .copy{margin-left:auto;color:#fff;}
.footer-legal{margin-top:18px;font-size:12px;font-weight:500;color:oklch(1 0 0 / .65);line-height:1.6;max-width:60ch;}
@media (max-width:640px){
  .footer-top .btn{margin-left:0;}
  .footer-links .copy{margin-left:0;width:100%;}
}

/* ---------- Reveal on scroll ---------- */
.reveal{opacity:0;transform:translateY(28px);transition:opacity .5s ease, transform .7s var(--ease-out);}
.reveal.in{opacity:1;transform:translateY(0);}
/* cascade : dans une grille, les enfants ne doivent pas arriver tous en même
   temps — c'est le tic « tout fond en même temps ». 70 ms d'écart, 4 cartes
   maximum, soit 210 ms de traîne. */
@media (prefers-reduced-motion: reduce){
  .reveal,.phone-el,h2 .dot{opacity:1 !important;transform:none !important;}
}
.no-js .reveal,.no-js .phone-el{opacity:1;transform:none;}



/* ---------- Une arrivée par section, pas un fondu unique pour tout ----------
   Le tic à éviter, c'est l'uniformité : toutes les sections qui montent de
   28 px avec la même courbe. Chaque famille garde le même vocabulaire (opacité
   + translation) mais son propre tempo et sa propre direction. */

/* ⚠️ CE BLOC VISAIT DES COMPOSANTS QUI N'EXISTENT PLUS (12/08). Les cascades
   étaient écrites pour `.steps .step`, `.trust-grid .trust-card` et `.svc-grid
   .svc`, tous supprimés par les refontes successives — zéro occurrence dans
   `index.html`. Elles ne s'appliquaient donc à RIEN, et il ne restait que le
   fondu uniforme de `.reveal` : très exactement le tic que le commentaire
   ci-dessus dit vouloir éviter. Réécrit pour les composants réels.

   Le décalage se lit sur `--i`, posé par `nth-child` : aucun JS ne le calcule,
   donc rien à resynchroniser si l'ordre change dans le HTML. */

/* Le catalogue (12 catégories en grille) est remplacé par le carrousel
   `.annonces-*` (15/08, soir) : plus de reveal en cascade par rangée à tenir
   ici, l'entrée en vue déclenche juste `.annonces-scene.in` (fondu simple). */

/* Les listes à puces des deux sections claires : elles se DÉROULENT, une ligne
   après l'autre, serré (55 ms) — c'est une énumération, pas un empilement. */
.confiance-texte.in .confiance-points li{
  animation:ligneGlisse .45s var(--ease-out) both;
  animation-delay:calc(var(--i,0) * 55ms + 120ms);
}
.confiance-points li:nth-child(1){--i:0;}
.confiance-points li:nth-child(2){--i:1;}
.confiance-points li:nth-child(3){--i:2;}
.confiance-points li:nth-child(4){--i:3;}

/* Les appareils n'arrivent pas comme du texte : ils se POSENT — même montée,
   mais partie de plus bas et d'un poil plus petit, ce qui leur donne du poids. */
.confiance-device.reveal,
.mecanos-device.reveal{transform:translateY(36px) scale(.972);}
.confiance-device.reveal.in,
.mecanos-device.reveal.in{transform:none;transition:opacity .55s ease, transform .85s var(--ease-out);}

@keyframes ligneGlisse{
  from{opacity:0;transform:translateX(-10px);}
  to{opacity:1;transform:none;}
}

/* Un utilisateur « Réduire les animations » voit tout en place, immédiatement :
   ces animations sont `both`, donc leur état INITIAL masque le contenu — il
   faut les couper explicitement, pas seulement les raccourcir. */
@media (prefers-reduced-motion: reduce){
  .confiance-texte.in .confiance-points li{animation:none;}
  .confiance-device.reveal,
  .mecanos-device.reveal{transform:none !important;}
}


/* ---------- Prestation : la carte s'ouvre sur son détail ----------
   La carte est désormais une vraie commande (un <button> qui la recouvre) :
   plus de faux relief promettant un clic imaginaire. Le contenu du panneau
   vient du catalogue de l'app (durée, signes, fourchette 0,8×–1,8×). */
.svc-open{
  position:absolute;inset:0;z-index:3;
  border:0;padding:0;margin:0;background:transparent;
  cursor:pointer;-webkit-appearance:none;appearance:none;
  border-radius:var(--r-card);
}
.svc-open:focus-visible{outline:3px solid var(--brand-hero);outline-offset:-4px;}
.svc-meta{pointer-events:none;}
@media (hover:hover) and (pointer:fine){
  .svc:has(.svc-open:hover) > img,
  .svc:focus-within > img{transform:scale(1.045);}
  .svc:has(.svc-open:hover) .publish,
  .svc:focus-within .publish{background:#fff;}
  .svc:has(.svc-open:hover) .publish .ic{transform:translateX(3px);}
}
.svc-meta .publish{transition:background-color .25s var(--ease-out);}
.svc-meta .publish .ic{transition:transform .25s var(--ease-out);}

/* ---------- Panneau de détail ---------- */
.pdlg{
  border:0;padding:0;background:transparent;color:var(--navy);
  max-width:min(560px,calc(100% - 32px));width:100%;
  margin:auto;overflow:visible;
}
.pdlg::backdrop{background:oklch(0.242 0.061 259.51 / .55);}
.pdlg-in{
  position:relative;background:var(--surface);border-radius:20px;
  padding:clamp(22px,3.4vw,32px);
  box-shadow:0 8px 24px oklch(0.242 0.061 259.51 / .18), 0 32px 70px oklch(0.242 0.061 259.51 / .26);
}
.pdlg-close{
  position:absolute;top:12px;right:12px;width:44px;height:44px;
  display:grid;place-items:center;border:0;border-radius:50%;
  background:var(--bg);color:var(--navy);cursor:pointer;
  transition:background-color .2s var(--ease-out);
}
.pdlg-close:hover{background:var(--hairline);}
.pdlg-close .ic{font-size:15px;}
.pdlg-cat{
  font-size:12px;font-weight:800;letter-spacing:.09em;text-transform:uppercase;
  color:var(--brand-text);margin:0 44px 0 0;
}
.pdlg-title{font-size:clamp(22px,2.6vw,28px);font-weight:800;letter-spacing:-.02em;margin:6px 44px 0 0;line-height:1.15;}
.pdlg-usage{margin:10px 0 0;font-size:15px;font-weight:500;line-height:1.6;color:var(--muted);max-width:52ch;}
.pdlg-facts{
  display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px;margin-top:20px;
}
.pdlg-facts > div{
  background:var(--bg);border-radius:12px;padding:12px 14px;display:grid;gap:2px;
}
.pdlg-k{font-size:11.5px;font-weight:800;letter-spacing:.08em;text-transform:uppercase;color:var(--muted);margin:0;}
.pdlg-v{font-size:17px;font-weight:800;letter-spacing:-.01em;}
.pdlg-signs-k{margin:22px 0 0;}
.pdlg-signs{list-style:none;margin:10px 0 0;padding:0;display:grid;gap:1px;background:var(--hairline);border-radius:12px;overflow:hidden;}
.pdlg-signs li{
  background:var(--surface);padding:12px 14px;font-size:14.5px;font-weight:600;
  display:flex;align-items:center;gap:10px;
}
.pdlg-signs li::before{
  content:"";width:7px;height:7px;border-radius:50%;background:var(--brand);flex:none;
}
.pdlg-foot{margin:18px 0 0;font-size:12.5px;font-weight:500;line-height:1.55;color:var(--muted);}
@media (max-width:560px){
  /* en bas d'écran, comme une feuille : le pouce est en bas, pas au centre */
  .pdlg{max-width:100%;margin:auto auto 0;}
  .pdlg-in{border-radius:20px 20px 0 0;padding-bottom:calc(24px + env(safe-area-inset-bottom));}
  .pdlg-facts{grid-template-columns:minmax(0,1fr);}
}
.js .pdlg[open]{animation:pdlgIn .3s var(--ease-out) both;}
.js .pdlg[open]::backdrop{animation:pdlgFade .3s var(--ease-out) both;}
@keyframes pdlgIn{from{opacity:0;transform:translateY(14px) scale(.97);}to{opacity:1;transform:none;}}
@keyframes pdlgFade{from{opacity:0;}to{opacity:1;}}
@media (prefers-reduced-motion: reduce){
  .js .pdlg[open]{animation:pdlgFade .15s linear both;}
  .svc:has(.svc-open:hover) > img,.svc:focus-within > img{transform:none;}
}
@media (min-width:1100px){
  /* les appareils grandissent avec la colonne : le fondu de sortie suit */
}
@keyframes proDefile{
  from{transform:translateX(0);}
  to{transform:translateX(-50%);}   /* la liste est doublée : boucle sans couture */
}
/* `.phone` dessine encore un châssis (fond navy, rayon 52, padding, écran clair)
   hérité des maquettes en HTML. Les mockups sont maintenant des PNG où l'appareil
   EST dans l'image : sans cette remise à zéro, le rendu 3D se retrouvait posé dans
   un second téléphone dessiné. */
.phone--flat{
  width:100%;aspect-ratio:auto;background:none;padding:0;border-radius:0;box-shadow:none;
}
/* Ombre DESSINÉE, pas filtrée — mêmes raisons que sur `.spine__device .phone` (voir la note
   complète là-bas) : ces blocs reçoivent une parallaxe GSAP et un `.reveal`, donc leurs
   couches sont composées en permanence et tout `drop-shadow` y dégénère en rectangle. */
.phone--flat{position:relative;}
.phone--flat::after{
  content:'';position:absolute;z-index:-1;
  left:9%;right:9%;bottom:-2.5%;height:5.5%;
  border-radius:50%;
  background:radial-gradient(closest-side, oklch(0 0 0 / .5), oklch(0 0 0 / 0));
  filter:blur(9px);
}
.phone--flat .phone-screen{
  aspect-ratio:700 / 1423;height:auto;display:block;
  background:none;background-image:none;border-radius:0;overflow:visible;
}
.phone--flat .phone-screen img{width:100%;height:100%;object-fit:contain;display:block;}

/* ---------- Balancement lent des appareils ----------
   Amplitude VOLONTAIREMENT petite : ±5°. Le mockup est une image, donc la faire
   pivoter revient à traiter le téléphone comme un plan — faux en toute rigueur.
   Comparé image par image au vrai rendu 3D (yaw −12° et −2°), l'écart est
   invisible à cette amplitude. Au-delà, le châssis s'écrase d'un côté : c'est
   exactement ce qui rendait le device « bizarre » dans les versions précédentes.
   Une vraie rotation 3D coûterait 350 Ko d'images par appareil ; celle-ci ne
   coûte rien. */
@keyframes balancement{
  from{transform:rotateY(-5deg);}
  to{transform:rotateY(5deg);}
}
@media (prefers-reduced-motion: no-preference){
  /* Le téléphone du hero n'est dans aucun sélecteur ici : ses deux appareils sont
     statiques depuis le 15/08 (soir), posés une fois pour toutes à côté du titre. */
  /* décalés entre eux : trois appareils qui basculent à l'unisson font mécanique,
     pas vivant. Les retards sont négatifs — l'animation démarre déjà entamée. */
}
@media (prefers-reduced-motion: reduce){
  /* pas de défilement : la bande devient une rangée que l'on fait glisser */
}
/* « Avant de réserver » : même forme que le carnet — texte à gauche, UN écran à
   droite. Le carrousel de deux appareils qui s'y trouvait montrait deux fois le
   même argument dans deux mockups penchés ; il ne reste que la fiche du mécanicien,
   qui est ce que le visiteur veut voir avant de réserver. */
.confiance-grid{display:grid;grid-template-columns:minmax(0,1fr);gap:clamp(28px,4vw,56px);align-items:center;}
.confiance-texte h2{
  font-size:clamp(24px,2.9vw,38px);font-weight:800;letter-spacing:-.025em;
  line-height:1.18;margin:10px 0 0;max-width:22ch;color:var(--navy);
}
.confiance-texte .lead{margin:14px 0 clamp(20px,2.4vw,30px);}
.confiance-device{justify-self:center;}
.confiance-device .phone{width:clamp(210px,24vw,290px);}
@media (min-width:820px){
  .confiance-grid{grid-template-columns:minmax(0,1.05fr) minmax(0,.95fr);}
}

/* ---------- Pages légales ---------- */
.legal-main{max-width:820px;margin:0 auto;padding:clamp(32px,5vw,56px) var(--gutter) 80px;}
.legal-main h1{font-size:clamp(28px,4vw,40px);font-weight:800;letter-spacing:-.03em;line-height:1.15;color:var(--navy);margin:0;}
.legal-main .updated{font-size:13px;font-weight:500;color:var(--muted);margin-top:10px;}
.legal-note{
  margin-top:24px;background:var(--brand-tint);border:1px solid oklch(0.646 0.207 38.94 / .28);
  border-radius:10px;padding:14px 18px;font-size:13.5px;font-weight:500;line-height:1.6;color:var(--navy);
}
.legal-main h2{font-size:20px;margin:40px 0 0;}
/* Titre de PARTIE (« Conditions particulières aux mécaniciens professionnels »), distinct des
   titres d'articles, qui sont eux aussi des h2. La distinction n'est pas décorative : elle sépare
   ce qui engage tout le monde de ce qui n'engage que les mécaniciens professionnels. */
.legal-main h2.part{font-size:25px;font-weight:800;letter-spacing:-.02em;margin:72px 0 0;padding-top:8px;}
.legal-main h3{font-size:16px;font-weight:700;color:var(--navy);margin:28px 0 0;}
.legal-main p,.legal-main li{font-size:14.5px;font-weight:500;line-height:1.75;color:var(--navy);}
.legal-main p{margin:12px 0 0;max-width:70ch;}
.legal-main ul{margin:12px 0 0;padding-left:22px;}
.legal-main li{margin-top:6px;}
.legal-main a{color:var(--navy);font-weight:600;text-underline-offset:3px;text-decoration-thickness:from-font;}
.legal-main a:hover{color:var(--brand-text);}
.legal-main strong{font-weight:700;}
.legal-footer-space{height:20px;}


/* ══════════════════════════════════════════════════════════════════════════════════════════════
   MOBILE (≤ 899 px) — passe de finition du 27/07
   ══════════════════════════════════════════════════════════════════════════════════════════════
   Le desktop était jugé bon : RIEN ici ne s'applique au-dessus de 899 px, et ce bloc est le
   dernier de la feuille pour que l'ordre de cascade au-dessus reste inchangé.

   Ce qui était mesuré comme faible sur un viewport étroit :
   · le téléphone du hero démarrait sous la ligne de flottaison (y=464 pour 620 px de haut) et
     n'était qu'une vignette de 300 px de large ;
   · deux badges stores de 154 px côte à côte se partageaient la largeur — aucun n'avait le poids
     d'un CTA, et la cible tactile était courte ;
   · la seconde phrase du titre tombait à 21 px sur fond navy à 70 % d'opacité ;
   · les deux carrousels défilaient TOUT SEULS en 46 s, avec leurs diapositives dupliquées, sur un
     support où le doigt est le moyen naturel de parcourir ;
   · le message sur le paiement — la première question du visiteur — arrivait APRÈS le carrousel ;
   · le téléphone du carnet tombait à 210 px de large.
   ══════════════════════════════════════════════════════════════════════════════════════════════ */
@media (max-width:899px){

  /* ── Respiration générale ────────────────────────────────────────────────────────────────── */
  /* Le haut TOUJOURS plus grand que le bas : une section appartient a son titre. Avant, les
     respirations allaient de 56 a 119 px sans logique, et un vide de 119 px precedait le carnet. */
  #confiance .inner,
  #mecanos .inner{padding-top:clamp(64px,16vw,96px);padding-bottom:clamp(48px,12vw,72px);}

  /* ── HERO ────────────────────────────────────────────────────────────────────────────────── */
  .spine__intro{padding-block:clamp(20px,6vw,36px) clamp(26px,7vw,40px);}

  /* ÉCHELLE TYPOGRAPHIQUE — 4 marches franches (ratio ~1,4).
     Mesuré avant : `#confiance h2` 28,4 · `#mecanos h2` 28,4 · `.carnet-texte h2` 26,7 ·
     `.claim` 24,1 · `.spine__step h2` 24,1 · `.h1-follow` 22,4 — soit SIX rôles differents
     tenant dans 6 px. Un titre d'etape et un titre de section avaient la meme taille : rien ne
     disait lequel contenait l'autre, et la page se lisait a plat. */
  .h1-lead{font-size:clamp(38px,10.5vw,54px);line-height:1.02;}
  /* .h1-follow heritait `font-weight:800` du h1 : c'etait un SECOND titre, pas un sous-titre.
     Poids 600 et taille reduite lui rendent son rang. */
  .h1-follow{
    font-size:clamp(18px,4.6vw,21px);font-weight:600;line-height:1.3;
    letter-spacing:-.01em;color:oklch(1 0 0 / .74);
  }
  #confiance h2,#mecanos h2{font-size:clamp(26px,7.2vw,34px);line-height:1.14;max-width:100%;}
  #confiance .lead,#mecanos .lead{font-size:16.5px;line-height:1.6;}

  /* CTA : les badges s'empilent sur toute la largeur. Ils deviennent la cible principale du hero
     (60 px de haut, largeur pleine) au lieu de deux pastilles qui se disputaient la ligne.
     ⚠️ Volontairement PAS de bouton « Télécharger » supplémentaire : aucune fiche store n'existe
     encore, il ne pourrait mener nulle part. Un CTA qui ne fait rien est pire que pas de CTA. */
  /* Les badges maison s'empilaient ici en pleine largeur, le second traité en verre pour
     ne pas peser deux fois le même poids visuel. Rien de tout ça ne se transpose aux badges
     OFFICIELS (15/08) : les étirer sur toute la largeur les DÉFORMERAIT, et retoucher le
     fond de l'un des deux reviendrait à modifier une marque déposée — les deux chartes
     l'interdisent explicitement. Ils restent donc côte à côte, à leur taille propre, centrés,
     et passent à la ligne d'eux-mêmes si l'écran est trop étroit pour les deux. */
  .stores{flex-direction:row;justify-content:center;flex-wrap:wrap;gap:10px;margin-top:22px;}
  .store-badge img{height:44px;}

  /* Présence des deux téléphones : la paire déborde un peu à droite — elle a l'air posée
     sur la page au lieu d'y être encadrée. ⚠️ Cette règle ciblait `.spine__device .phone` (0,2,0),
     qui matche À LA FOIS `.phone--back` ET `.phone--front` : à spécificité égale avec les
     règles `.phone--back`/`.phone--front` plus haut dans ce fichier, being plus bas ici elle
     gagnait sur TOUT — width, margin, transform — et donnait aux deux appareils exactement
     la même valeur. Résultat mesuré : les deux phones parfaitement superposés, un seul
     visible. Remplacée par deux règles distinctes, une par appareil. */
  .spine__device{margin-inline:0;overflow:visible;margin-bottom:clamp(22px,5.5vw,32px);justify-content:flex-end;}
  .spine__device .phone--back{
    height:min(46vw,208px);
    transform:rotate(-9deg);
    margin-right:-8vw;
  }
  .spine__device .phone--front{
    height:min(50vw,228px);
    transform:rotate(4deg);
    margin-left:-4vw;
  }
  /* Le `rotate` ci-dessus et un `filter` sur le même nœud = rectangle gris : l'ombre
     descend donc sur l'image (cf. la note sur `.spine__device .phone`). */
  /* l'ombre au sol du bloc de base suffit ici — aucun drop-shadow, cf. sa note */

  /* Le doigt et son onde sont une mise en scène de démonstration : sur un écran tactile, un
     curseur qui appuie tout seul n'a plus de sens. L'enchaînement des écrans, lui, reste. */
  #hero-finger,#hero-ripple{display:none !important;}

  /* ── CARROUSELS : le doigt décide, pas une minuterie ─────────────────────────────────────── */
  /* Même mécanique que le repli `prefers-reduced-motion` déjà en place : la bande devient une
     rangée que l'on fait glisser, avec un arrêt franc sur chaque appareil. */
  /* `center` faisait tomber la diapo suivante n'importe ou et tranchait une legende en plein
     mot ; `start` + scroll-padding la laisse depasser franchement — c'est ce depassement qui
     dit « ca glisse », maintenant que le defilement automatique ne le dit plus. */
  /* A 232 px la seconde diapo etait visible a 68 % : trop pour se lire comme un debord, pas
     assez pour etre lisible — ca ne disait pas « faites glisser », ca disait « c'est casse », et
     la legende se faisait trancher en plein mot. A 82vw il ne reste qu'un liseret d'appareil, et
     l'ecran visible gagne 47 % : une capture de PREUVE doit d'abord etre lisible. */
  /* les copies ne servaient qu'à boucler sans couture : en glissé manuel elles deviennent des
     doublons que l'on rencontre vraiment */
  /* une seule animation par zone : le balancement permanent des appareils s'ajoutait au
     défilement et au reveal, ça faisait trois mouvements concurrents sur un petit écran */
  /* Mesure : le fond derriere les appareils sortait a rgb(202,203,206) contre rgb(244,246,249)
     pour la section — 42 points de luminance, une bande grise qui traverse toute la largeur et
     s'arrete net. L'ombre est calibree pour le navy, ou elle fait du volume ; sur fond clair deux
     ombres a 50 % de noir se cumulent en flaque. Allegee UNIQUEMENT sur la section claire. */

  /* ── CONFIANCE ───────────────────────────────────────────────────────────────────────────── */
  /* ⚠️ Cette colonne était ORDONNÉE EXPLICITEMENT (order 1, 2, 3, 4) pour trois blocs
     qui n'existent plus depuis le 11/08 — le carrousel, la déclaration sur l'argent et
     le rail du séquestre. Un `order` qui vise un sélecteur mort ne fait pas rien : les
     blocs restants héritaient de `order:0` et remontaient AVANT le titre, ce qui a mis
     l'écran du mécanicien tout en haut de la section. Plus d'ordre explicite : le flux
     du document suffit, texte puis écran. */
  #confiance .inner{display:flex;flex-direction:column;}
  #confiance .lead{margin-top:14px;}

  /* ── MÉCANICIENS ─────────────────────────────────────────────────────────────────────────── */
  #mecanos h2{font-size:clamp(25px,6.6vw,32px);}
  #mecanos .lead{margin-top:16px;}
  #mecanos .btn{width:100%;margin-top:26px;min-height:58px;}

  /* ⚠️ Aucune section ne doit pouvoir pousser la PAGE lateralement. Le carrousel sort
     volontairement de `.wrap` (marges negatives) pour toucher les bords ; combine au `.wrap`
     centre, cela creait une boucle — le debord decalait le wrap, ce qui aggravait le debord.
     Mesure : scrollWidth 534 pour un viewport de 500. `overflow-x:clip` coupe net SANS creer de
     contexte de defilement (contrairement a `hidden`), donc le glisse interne du carrousel et le
     `position:sticky` restent intacts. */
  #confiance,#mecanos,.site-footer{overflow-x:clip;}

  /* ── SURFACES : donner des reperes de scroll ─────────────────────────────────────────────── */
  /* Sur mobile le fond est le seul moyen de dire « je change de sujet » : il n'y a pas de largeur
     pour le signaler autrement. `#confiance` (dernière section claire avant le navy de
     « Pour les mécaniciens », depuis la suppression du carnet le 15/08) prend donc sa propre
     surface, avec le bord arrondi qui est déjà le vocabulaire du hero. */
  #confiance{
    background:var(--surface);
    border-radius:clamp(28px,7vw,40px) clamp(28px,7vw,40px) 0 0;
    box-shadow:0 -1px 0 var(--hairline);
  }
  /* `#mecanos` et le pied de page partageaient le MEME navy sans bordure : on ne voyait pas ou
     la section s'arretait, et le logo du footer semblait appartenir a l'argumentaire mecanicien. */
  /* Premier essai : bord arrondi sur `#mecanos` + navy « plus profond » sur le pied. Mesure —
     rgb(10,26,50) contre rgb(7,21,44), soit un contraste de 1,047:1 : IMPERCEPTIBLE, seule
     l'encoche portait la separation. Le vocabulaire s'inverse : c'est le pied qui prend le bord
     arrondi, et l'ecart de navy devient visible. */
  #mecanos{border-radius:0;}
  .site-footer{
    border-radius:clamp(28px,7vw,40px) clamp(28px,7vw,40px) 0 0;
    background:oklch(0.175 0.044 259.5);
    box-shadow:inset 0 1px 0 oklch(1 0 0 / .10);
  }
  .site-footer .inner{padding-top:clamp(40px,10vw,56px);}
  /* La rangee logo + bouton se tassait a gauche en laissant 135 px vides a droite (31 % de la
     largeur) : un bloc pense pour le desktop, pose tel quel sur mobile. */
  .site-footer .footer-top{display:flex;justify-content:space-between;align-items:center;gap:16px;}
  /* MESURÉ, pas estimé : la boîte de texte fait 20 px (13,5 px de corps), donc
     11 px de part et d'autre donnaient 42 px — deux px sous la cible. 12 px la
     posent exactement à 44. */
  .footer-links a{padding-block:12px;}

  /* `p{text-wrap:pretty}` est deja global, mais il n'evite que l'orphelin d'UN mot : sur des
     blocs de 2-3 lignes, quatre veuves subsistaient (« vous choisissez. », « et son prix. »,
     « votre prix. »). `balance` repartit les lignes a longueur egale — il plafonne a 6 lignes,
     seuil qu'aucun de ces blocs n'atteint. */
  #confiance .lead,#mecanos .lead{text-wrap:pretty;}

  /* ── Cibles tactiles du header ───────────────────────────────────────────────────────────── */
  /* 76 px de barre pour un logo de 32, une pilule et un burger : 9,7 % du premier ecran, paye
     sur 100 % du parcours. Et le burger (rayon 12) cotoyait la pilule (rayon 999) a 8 px
     d'ecart — deux vocabulaires de forme dans le meme geste. */
  .site-header .bar{height:64px;gap:10px;}
  .btn-compact{min-height:44px;padding-inline:18px;font-size:14.5px;}
  .burger{min-width:44px;min-height:44px;border-radius:999px;}
}

/* Le glissé manuel reste du mouvement : sous `reduced`, on retire jusqu'à l'accroche du snap. */
@media (max-width:899px) and (prefers-reduced-motion: reduce){
  .spine__device .phone{transform:none;}
}


/* ---------- Page 404 ----------
   Reprend le gabarit sobre des pages legales (`.legal-main`) : meme largeur, meme header, aucun
   composant neuf. Une page d'erreur doit rassurer et rediriger, pas se faire remarquer. */
.erreur-main{text-align:center;padding-bottom:clamp(64px,10vw,110px);}
.erreur-code{
  font-size:clamp(72px,16vw,132px);font-weight:800;line-height:1;letter-spacing:-.05em;
  color:var(--hairline);margin:clamp(8px,3vw,24px) 0 0;
}
.erreur-main h1{margin-top:clamp(4px,1.5vw,12px);}
.erreur-texte{
  font-size:17px;line-height:1.6;color:var(--muted);
  max-width:44ch;margin:16px auto 0;text-wrap:balance;
}
/* ⚠️ `.legal-main a{color:var(--navy)}` (gabarit des pages legales) ecrasait le blanc du
   `.btn-primary` : sur le bouton navy, il ne restait que le point orange sur fond navy, le
   libelle etait INVISIBLE. La regle du gabarit ne doit pas s'appliquer a un bouton. */
.erreur-main .btn-primary{color:#fff;}
.erreur-main .btn-primary:hover{color:#fff;}
.erreur-cta{margin-top:clamp(26px,4vw,36px);}
.erreur-liens{
  display:flex;flex-wrap:wrap;justify-content:center;gap:10px 22px;
  margin-top:clamp(34px,5vw,52px);padding-top:clamp(22px,3vw,30px);
  border-top:1px solid var(--hairline);
}
.erreur-liens a{
  font-size:14.5px;font-weight:600;color:var(--muted);text-decoration:none;
  padding-block:9px;
}
.erreur-liens a:hover{color:var(--brand-text);}
@media (max-width:899px){
  /* meme regle que le reste du mobile : une cible tactile ne descend pas sous 44 px */
  .erreur-liens{gap:4px 18px;}
  .erreur-liens a{padding-block:12px;}
  .erreur-cta{width:100%;min-height:58px;}
}


/* ==========================================================================
   CE QUE FAIT L'APP — la grille des prestations (11/08)
   ==========================================================================
   Ajoutée sous le hero. Le parcours était raconté, l'objet ne l'était pas :
   on savait comment ça marche, pas ce qu'on pouvait demander.

   Aucune icône. Douze pictogrammes choisis pour douze catégories mécaniques
   auraient tous fini par se ressembler (une clé, un disque, un rond) et
   n'auraient rien ajouté au libellé qu'ils accompagnent. La hiérarchie se
   joue au poids et à la couleur : le nom en navy, les exemples en gris.
   ========================================================================== */
/* ⚠️ `#prestations .inner{padding-top:…}` (visait le `.wrap.inner` qui portait CE
   titre, dans son ancienne position hors du panneau) est retiré ici : depuis que
   le carrousel vit DANS `.pc-panel` (18/08, plus tard), le seul `.wrap.inner`
   restant dans `#prestations` est celui du panneau lui-même — cette règle aurait
   empilé un second espace au-dessus, en plus du `margin-top` de `.pc-panel`. */
.presta-intro h2{
  /* `max-width:20ch` cassait « De la vidange au voyant qui s'allume sans prévenir »
     en 4-5 lignes hachées. Élargi : la même phrase tient en 2 lignes à la plupart
     des largeurs, comme le titre du hero. */
  font-size:clamp(24px,2.9vw,38px);font-weight:800;letter-spacing:-.025em;
  line-height:1.18;margin:10px 0 0;max-width:36ch;color:var(--navy);
}
.presta-intro .lead{margin:14px 0 0;max-width:62ch;}
/* Le titre et le carrousel vivent maintenant DANS `.pc-panel` (navy) : texte blanc,
   pleine largeur du panneau (le panneau centre ses enfants par défaut,
   `align-items:center`, qui les réduit sinon à leur largeur de contenu), et un
   espace dédié sous le Parcours — c'est la « place » que le panneau leur fait. */
.pc-panel .presta-intro{width:100%;margin-top:clamp(32px,4.5vw,52px);}
.pc-panel .presta-intro h2{color:#fff;max-width:none;}
.pc-panel .svc-scene{width:100%;}
/* Le panneau a déjà `overflow:hidden` (pour la carte de chapitre du Parcours) et
   son propre padding : le carrousel reste DEDANS plutôt que de déborder jusqu'au
   bord de l'écran comme sur une section pleine largeur — c'est ce que veut dire
   « l'intégrer » ici. Le fondu du bord (`mask-image`, juste en dessous) suffit à
   ne pas finir sur une carte tranchée net. */
.pc-panel .svc-piste{margin-right:0;}

/* Le carrousel « Les prestations » de l'app (15/08, soir) — port de `ServiceCard` /
   `ServiceGradient`, `mecaly-app/src/app/index.tsx:115-127`. Piste/défilement sur le
   même moteur que `.annonces-*` (cf. section pro plus bas), carte propre : photo
   pleine largeur, fondu bas, titre blanc — pas de badge de statut ni de prix, une
   catégorie n'est pas une annonce. */
.svc-scene{margin-top:clamp(28px,4vw,46px);}
.svc-piste{
  position:relative;overflow:hidden;
  margin-right:calc(var(--gutter) * -1);
  padding:6px 0 10px;
  -webkit-mask-image:linear-gradient(90deg, #000 0, #000 calc(100% - 96px), transparent 100%);
  mask-image:linear-gradient(90deg, #000 0, #000 calc(100% - 96px), transparent 100%);
}
.svc-track{
  list-style:none;margin:0;padding:0;
  display:flex;align-items:stretch;gap:clamp(12px,1.4vw,16px);
  width:max-content;
  animation:svcDefile 46s linear infinite;
}
.svc-piste:focus-within .svc-track{animation-play-state:paused;}
@keyframes svcDefile{
  from{transform:translateX(0);}
  to{transform:translateX(-50%);}   /* la liste est doublée en JS : boucle sans couture */
}
/* 236×288 dans l'app (`ServiceCard`) : ratio ~0,82, repris ici en `aspect-ratio` pour
   rester fluide plutôt qu'en dimensions figées. */
.svc-carte{
  position:relative;
  width:clamp(190px,17vw,236px);aspect-ratio:236/288;flex:0 0 auto;
  border-radius:16px;overflow:hidden;background:var(--navy);
}
.svc-photo{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;display:block;}
/* Le fondu : mêmes couleur, paliers et valeurs que `ServiceGradient` dans l'app —
   navy à alpha 0 en haut (pas transparent pur, qui délaverait sur iOS), plein aux
   deux tiers, tout le bas assez sombre pour porter un titre blanc en AA. */
.svc-voile{
  position:absolute;inset:0;
  background:linear-gradient(180deg,
    oklch(0.242 0.061 259.51 / 0) 52%,
    oklch(0.242 0.061 259.51 / .60) 68%,
    oklch(0.242 0.061 259.51 / .62) 100%);
}
.svc-texte{
  position:absolute;left:0;right:0;bottom:0;z-index:1;
  padding:16px;display:flex;flex-direction:column;gap:4px;
}
.svc-texte b{
  color:#fff;font-size:15px;font-weight:800;line-height:1.28;letter-spacing:-.01em;
  text-shadow:0 1px 6px oklch(0 0 0 / .35);
}
.svc-texte span{
  color:oklch(1 0 0 / .78);font-size:12px;font-weight:600;line-height:1.4;
}
@media (max-width:899px){
  .svc-piste{
    overflow-x:auto;overscroll-behavior-x:contain;
    scroll-snap-type:x mandatory;
    -webkit-mask-image:none;mask-image:none;
    scrollbar-width:none;
  }
  .svc-piste::-webkit-scrollbar{display:none;}
  .svc-track{animation:none;width:max-content;}
  .svc-carte{scroll-snap-align:start;width:min(46vw,206px);}
}
@media (prefers-reduced-motion: reduce){
  .svc-piste{overflow-x:auto;-webkit-mask-image:none;mask-image:none;scroll-snap-type:x proximity;}
  .svc-track{animation:none;}
  .svc-carte{scroll-snap-align:start;}
}

/* ==========================================================================
   POUR LES MÉCANICIENS — la piste d'annonces (11/08)
   ==========================================================================
   Remplace trois mockups de téléphone. Ce que le mécanicien veut voir n'est
   pas l'application : c'est le travail qui l'attend. Les cartes reprennent la
   disposition de `PrestaCard` en `caption="overlay"` — photo porteuse, badge
   de statut et budget en haut, titre et référence en bas, pied blanc avec la
   distance et le délai.

   La piste défile toute seule ET se fait glisser au doigt : `overflow-x:auto`
   + `scroll-snap` en dessous de 900 px, où l'animation s'arrête pour laisser
   la main au visiteur. Au-dessus, elle défile et s'arrête au survol comme au
   focus clavier.
   ========================================================================== */
.annonces-scene{margin-top:clamp(30px,4vw,48px);}
/* La piste déborde À DROITE seulement : les cartes partent de la marge du texte,
   comme tout le reste de la page, et la bande file hors de l'écran de l'autre
   côté. Un débordement des deux côtés coupait la première carte en deux sous le
   fondu gauche — la seule carte que l'œil lit vraiment. */
.annonces-piste{
  position:relative;overflow:hidden;
  margin-right:calc(var(--gutter) * -1);
  padding:6px 0 10px;
  -webkit-mask-image:linear-gradient(90deg, #000 0, #000 calc(100% - 96px), transparent 100%);
  mask-image:linear-gradient(90deg, #000 0, #000 calc(100% - 96px), transparent 100%);
}
.annonces-track{
  list-style:none;margin:0;padding:0;
  display:flex;align-items:stretch;gap:clamp(14px,1.6vw,20px);
  width:max-content;
  animation:annoncesDefile 54s linear infinite;
}
.annonces-piste:hover .annonces-track,
.annonces-piste:focus-within .annonces-track{animation-play-state:paused;}
@keyframes annoncesDefile{
  from{transform:translateX(0);}
  to{transform:translateX(-50%);}   /* la liste est doublée en JS : boucle sans couture */
}
.annonce-carte{
  width:clamp(244px,25vw,290px);flex:0 0 auto;
  background:var(--surface);border-radius:16px;overflow:hidden;
  box-shadow:var(--shadow-card);
  display:flex;flex-direction:column;
}
.annonce-photo{position:relative;aspect-ratio:16 / 10;overflow:hidden;}
.annonce-photo img{width:100%;height:100%;object-fit:cover;display:block;}
/* Le voile qui rend le titre lisible sur n'importe quelle photo. Il part du bas
   et meurt à mi-hauteur : un voile plein grisaillerait la photo entière. */
.annonce-photo::after{
  content:'';position:absolute;inset:0;
  background:linear-gradient(180deg, oklch(0.242 0.061 259.51 / .42) 0%, transparent 34%, transparent 44%, oklch(0.18 0.05 259 / .82) 100%);
}
.annonce-statut,.annonce-budget,.annonce-titre{position:absolute;z-index:1;}
.annonce-statut{
  top:10px;left:10px;
  background:var(--success-bg);color:var(--success-text);
  font-size:11.5px;font-weight:700;letter-spacing:.01em;
  padding:4px 8px;border-radius:5px;
}
.annonce-budget{
  top:10px;right:10px;
  background:oklch(1 0 0 / .94);color:var(--navy);
  font-size:14px;font-weight:800;letter-spacing:-.01em;
  padding:4px 9px;border-radius:5px;
  display:flex;align-items:baseline;gap:5px;
}
.annonce-budget i{font-style:normal;font-size:10px;font-weight:600;color:var(--muted);}
.annonce-titre{
  left:12px;right:12px;bottom:10px;
  color:#fff;font-size:14.5px;font-weight:700;line-height:1.28;
  letter-spacing:-.01em;
  display:flex;flex-direction:column;gap:3px;
}
.annonce-titre i{
  font-style:normal;font-size:11px;font-weight:600;
  color:oklch(1 0 0 / .62);letter-spacing:.02em;
}
.annonce-pied{
  display:flex;align-items:center;gap:16px;
  padding:11px 12px 12px;
}
.annonce-meta{
  display:inline-flex;align-items:center;gap:6px;
  font-size:12.5px;font-weight:600;color:var(--muted);
}
.annonce-meta .ic{width:13px;height:13px;fill:currentColor;flex:none;}

@media (max-width:899px){
  /* La bande cesse de défiler et devient une rangée que l'on fait glisser : sur
     un écran tactile, une animation qui tourne pendant qu'on essaie de swiper se
     bat contre le doigt. */
  .annonces-piste{
    overflow-x:auto;overscroll-behavior-x:contain;
    scroll-snap-type:x mandatory;
    -webkit-mask-image:none;mask-image:none;
    scrollbar-width:none;
  }
  .annonces-piste::-webkit-scrollbar{display:none;}
  .annonces-track{animation:none;width:max-content;}
  .annonce-carte{scroll-snap-align:start;width:min(76vw,300px);}
}
@media (prefers-reduced-motion: reduce){
  .annonces-piste{
    overflow-x:auto;-webkit-mask-image:none;mask-image:none;
    scroll-snap-type:x proximity;
  }
  .annonces-track{animation:none;}
  .annonce-carte{scroll-snap-align:start;}
}


/* ==========================================================================
   PASSE MOBILE — 11/08
   ==========================================================================
   « la version mobile est complètement merdique, faut la refaire » (BOSS).
   Ce qui a été constaté à 390 px, capture à l'appui, et corrigé ici :

   1. Les deux badges de store empilés pleine largeur mangeaient 132 px du
      meilleur pixel de la page pour dire deux fois « c'est une app ». Ils
      passent côte à côte, et perdent leur sur-titre « Disponible sur » qui
      n'apprend rien à personne sur un badge de store.
   2. Le téléphone occupait 74 vw et près de la moitié de la hauteur utile,
      penché de trois quarts : il écrasait le titre au lieu de l'illustrer.
   3. La route s'affichait comme un moignon orange de 30 px de large sous le
      téléphone, sans jamais rejoindre les étapes : sur une colonne unique, une
      route sinueuse n'a pas de place où serpenter. Elle est coupée net.
   ========================================================================== */
@media (max-width:899px){
  /* 1 — les badges tiennent sur une ligne. Depuis le 15/08 ce sont les badges OFFICIELS :
     des images entières. Plus de fond, de padding ni de rayon à leur donner — ça leur
     dessinait une seconde pastille blanche autour, vue à l'écran avant correction. */
  .stores{flex-direction:row;flex-wrap:wrap;justify-content:center;gap:10px;margin-top:22px;}
  .store-badge{flex:0 0 auto;}
  .store-badge img{height:44px;}

  /* 2 — l'appareil laisse la place au texte */
  .spine__device .phone{width:min(62vw,264px);}
  .spine__device{margin-bottom:clamp(16px,4vw,24px);}

  /* Confiance : même traitement que le carnet — texte, puis l'écran centré. */
  .confiance-device .phone{width:min(62vw,258px);}
  .confiance-device{margin-top:clamp(26px,7vw,38px);}
}

/* Les puces de « Avant de réserver ». Volontairement PAS `.carnet-points` : celle-ci
   devient une colonne à filet sous 900 px, un registre réservé au carnet pour que les
   deux sections claires ne jouent pas la même partition. */
.confiance-points{list-style:none;margin:0;padding:0;display:grid;gap:14px;}
.confiance-points li{
  padding-left:18px;position:relative;font-size:15px;line-height:1.6;color:var(--muted);
  max-width:52ch;
}
.confiance-points li::before{
  content:"";position:absolute;left:0;top:.62em;width:7px;height:7px;border-radius:50%;
  background:var(--brand);
}
.confiance-points b{color:var(--navy);font-weight:700;}

/* La colonne de texte des mécaniciens a perdu sa moitié de grille le 11/08 (la piste
   d'annonces prend toute la largeur en dessous) : sans borne, le h2 s'étalait sur une
   seule ligne de 1100 px et la lead sur 130 caractères. On borne la mesure, pas la
   grille — le titre retrouve ses deux lignes. */
#mecanos h2{max-width:16ch;}
#mecanos .lead{max-width:46ch;}

/* ═══════════════════════════════════════════════════════════════════════════════════════════
   HERO — PROFONDEUR, ARC ET ÉTOILES (inspiration BOSS, 15/08)
   « typiquement les téléphones, les étoiles des avis, le background qui fait pas 100 % uni,
   j'aime bien. » Trois ajouts ciblés, aucune refonte : la structure du hero ne bouge pas.
   ═══════════════════════════════════════════════════════════════════════════════════════════ */

/* LE FOND. `.spine` portait déjà une trame de points et un dégradé d'angle. Ce qui manquait,
   c'est une SOURCE : un halo chaud posé derrière les appareils, qui donne au navy une direction
   de lumière au lieu d'un aplat qui s'éteint uniformément. La trame de points reste la couche du
   dessus — c'est elle qui empêche le dégradé de faire du banding sur les grands écrans. */
.spine{
  background:
    radial-gradient(circle at 1px 1px, oklch(1 0 0 / .045) 1.1px, transparent 1.6px) 0 0/23px 23px,
    radial-gradient(58% 46% at 78% 18%, oklch(0.646 0.207 38.94 / .17) 0%, transparent 68%),
    radial-gradient(90% 65% at 88% 4%, oklch(0.42 0.06 258 / .55) 0%, transparent 60%),
    radial-gradient(120% 90% at 12% -6%, oklch(0.335 0.075 257.6) 0%, var(--navy) 48%, oklch(0.198 0.05 259.51) 100%);
}

/* PAS D'ARC ORANGE ICI — essayé le 15/08, retiré après capture.
   La maquette dont vient l'idée pose un arc orange derrière ses téléphones, sur un fond vide.
   Ce hero-ci n'a pas un fond vide : il porte DÉJÀ une courbe orange, la route (`#road`) qui
   relie les trois étapes du parcours et qui est le fil conducteur de toute la section. Deux
   courbes orange sur le même navy se disputent le regard sans que ni l'une ni l'autre ne
   gagne — c'est précisément le « deux récits concurrents à l'écran » qui avait fait retirer
   l'animation du téléphone le 12/08.
   Ce qui EST repris de la maquette, c'est la profondeur du fond : elle passe par la lumière
   (le halo ci-dessus), pas par un trait de plus. */

/* LES ÉTOILES. Or (`--star`, la même teinte que dans l'app) et non orange : l'orange du site a
   quatre rôles précis et « note » n'en fait pas partie — le confondre avec l'action affaiblit
   les deux. Taille volontairement discrète : c'est une preuve, pas un argument. */
.hero-note{
  display:flex;align-items:center;flex-wrap:wrap;gap:8px;
  margin:clamp(14px,2vw,20px) 0 0;
  color:oklch(1 0 0 / .72);font-size:clamp(13px,1.05vw,14.5px);line-height:1.45;
}
.hero-note__stars{display:inline-flex;gap:2px;flex:0 0 auto;}
.hero-note__stars .ic{width:15px;height:15px;fill:oklch(0.793 0.162 82.95);}

/* ⚠️ Le texte est dans UN span, pas posé nu dans le flex. Sans lui, chaque `<span class="dot">`
   devient un élément de flex à part entière et hérite du `gap:8px` : le point orange se
   détachait du mot qu'il termine (« notée . »), visible sur la capture du 15/08. Un `gap` ne
   sait pas distinguer un mot d'une ponctuation — c'est au balisage de le dire. */
.hero-note__txt{flex:1 1 auto;min-width:0;}

/* Badge de note (15/08, réf. BOSS). Étoiles + nombre, doré comme le reste des avis. */
.hero-rating{
  display:inline-flex;align-items:center;gap:10px;
  margin:clamp(16px,2.4vw,24px) 0 0;
}
.hero-rating__stars{display:inline-flex;gap:3px;flex:0 0 auto;}
.hero-rating__stars .ic{width:20px;height:20px;fill:oklch(0.793 0.162 82.95);}
.hero-rating__mid{display:flex;flex-direction:column;align-items:flex-start;gap:1px;}
.hero-rating__num{color:#fff;font-size:26px;font-weight:800;letter-spacing:-.01em;line-height:1;}
.hero-rating__cap{
  color:oklch(1 0 0 / .68);font-size:13px;font-weight:600;
  letter-spacing:.02em;white-space:nowrap;
}

/* ═══════════════════════════════════════════════════════════════════════════════════════════
   HERO — DEUX APPAREILS DE MÊME GABARIT (15/08, SOIR — annule le paragraphe qui précédait ici)
   Le paragraphe qui vivait à cet endroit expliquait pourquoi la taille égale avait été
   essayée puis rejetée le 15/08 (matin) : « ici l'appareil de devant est sticky et
   accompagne tout le récit, il domine forcément ». Ce soir-là, le BOSS a explicitement
   redemandé cette disposition en montrant une référence (Freetrade) et en autorisant à
   « faire de la place » — donc le device est sorti du sticky (cf. `#hero` dans le HTML,
   et `.spine__device`/`.phone--back`/`.phone--front` plus haut dans ce fichier), ce qui
   lève la raison même du rejet du matin. Les deux règles de dimensionnement définitives
   sont plus haut ; ce bloc ne fait plus que les béton­ner contre un futur conflit de
   spécificité — le même piège que celui documenté juste au-dessus (`.spine__device .phone--back`
   vs `.spine__device .phone`, à spécificité égale, l'ordre du fichier tranchait). */
.spine__device .phone{width:auto;}
.spine__device .phone img{height:100%;width:auto;display:block;}

/* ═══════════════════════════════════════════════════════════════════════════════════════════
   SECTION PRO — PANNEAU CLAIR, APPAREIL À GAUCHE (maquette du BOSS, 15/08)
   ═══════════════════════════════════════════════════════════════════════════════════════════ */
.mecanos-panneau{
  /* Blanc uni (15/08, tard) — la teinte chaude (`--brand-tint`) est retirée : elle
     entrait en concurrence avec la piste d'annonces, posée depuis en fond du panneau,
     dont les propres badges/photos portent déjà de la couleur. */
  background:var(--surface);
  border-radius:clamp(20px,2.4vw,30px);
  /* Boîte resserrée (18/08) : le téléphone, agrandi, dépasse maintenant volontairement
     du panneau — assumé, cf. `overflow:visible` juste en dessous — plutôt que de
     regonfler la boîte pour le contenir en entier. */
  padding:clamp(16px,2.2vw,28px);
  margin-bottom:clamp(30px,4vw,56px);
  position:relative;
  /* `visible`, pas `hidden` : la piste d'annonces en fond reste dans ses propres
     bornes (alignée en flex dans `.mecanos-bg`), donc rien ne s'échappe de son côté —
     seul le téléphone, plus grand que la boîte, est autorisé à en sortir. */
  overflow:visible;
  /* Le panneau est clair SUR du navy : sans ombre portée il flotte sans poids. Deux couches,
     l'une courte et dense pour l'assise, l'autre longue et diffuse pour la distance. */
  box-shadow:0 30px 60px oklch(0.13 0.03 258 / .45), 0 8px 18px oklch(0.13 0.03 258 / .3);
}
/* Le texte du panneau redevient navy : il est sur clair, alors que la section l'écrit en blanc. */
.mecanos-panneau h2{color:var(--navy);}
.mecanos-panneau .eyebrow{color:var(--brand-text-strong);}

/* L'appareil passe à GAUCHE. Il est premier dans le flux, donc rien à réordonner à une colonne :
   à deux colonnes, c'est la grille qui le pose à gauche et l'argumentaire à droite. */
@media (min-width:900px){
  .mecanos-panneau{grid-template-columns:minmax(0,.86fr) minmax(0,1.14fr);}
  /* Le téléphone garde sa taille (agrandi le 15/08) — mais en grille, la ligne
     suit son item le plus haut : lui laisser sa hauteur naturelle forçait tout
     le panneau blanc à l'imiter, avec un grand vide sous le bouton côté texte
     (la colonne de texte, elle, ne remplit que la moitié de cette hauteur).
     Sorti du flux (`position:absolute`, ancré au coin haut-gauche de la boîte
     de padding — même point de départ qu'en flux normal), il n'impose plus RIEN
     à la hauteur du panneau ; `overflow:visible` (cf. `.mecanos-panneau`) le
     laisse déborder sous le panneau si besoin, ce que le panneau assumait déjà. */
  /* ⚠️ `.mecanos-device` (3 classes de spécificité) — `.mecanos-haut > .reveal:not(.mecanos-bg)`,
     plus haut dans ce fichier, pose déjà `position:relative` avec 3 sélecteurs de classe. Un
     `.mecanos-panneau .mecanos-device` n'en a que 2 : il PERDAIT silencieusement (mesuré —
     `justify-self`/`top`/`left` s'appliquaient, `position` restait sur `relative`, seule cette
     PROPRIÉTÉ étant disputée par l'autre règle). `.reveal` ajouté ici pour égaler ses 3 classes
     et gagner par l'ordre du fichier (cette règle est plus bas).
     ⚠️ `top:0;left:0` mesuré flush au bord EXTÉRIEUR du panneau, padding ignoré (comme
     `.mecanos-bg` juste en dessous, dont c'est le comportement voulu — pas ici : le
     téléphone doit démarrer où le flux normal l'aurait posé). Décalé du padding du
     panneau, en dur, pour ne plus en dépendre.
     ⚠️ Ancré par `top` (18/08, encore) : le téléphone, plus haut que le panneau,
     débordait donc par le BAS — décision BOSS : le débordement doit se voir en
     HAUT, pas planer au-dessus du carrousel en bas. Ancré par `bottom` à la place
     (même décalage que `top` avant, mesuré depuis le bas de la boîte de padding) :
     le pied du téléphone se cale près du bas du panneau, sa tête dépasse par-dessus. */
  /* BAISSÉ (BOSS, 15/08 : « il dépasse trop »). Mesuré avant correction à 1280 px : 188 px
     au-dessus du panneau, pour un appareil de 948 px dans un panneau de 766 — il était plus
     GRAND que le bloc qui le porte.
     ⚠️ Le descendre seul ne suffit pas : ancré par le bas, son pied affleurait déjà le bord
     inférieur (−6 px), donc chaque pixel gagné en haut serait reparu en bas, par-dessus le
     carrousel d'annonces — exactement ce que l'ancrage par `bottom` voulait éviter. D'où les
     deux leviers ensemble : un cran de largeur en moins (la hauteur suit le ratio) et un
     ancrage plus bas. Le débordement par le haut reste voulu, il tombe à ~70 px. */
  .mecanos-panneau .mecanos-device.reveal{
    position:absolute;
    bottom:clamp(-30px,-2vw,-8px);left:clamp(16px,2.2vw,28px);
    justify-self:auto;
  }
  .mecanos-panneau .mecanos-device .phone{width:clamp(290px,35vw,450px);}
  /* Un élément en `position:absolute` sort de la grille (la spec l'exclut du
     placement automatique) : sans lui, le bloc de texte redevient le SEUL item
     et retombe en colonne 1 (gauche), pile sous le téléphone. On lui redonne
     sa colonne explicitement. */
  .mecanos-panneau .mecanos-device ~ .reveal{grid-column:2;}
  /* Le panneau suit maintenant la colonne de texte (plus courte) — il faut lui
     rendre un peu de hauteur pour que le bouton « Rejoindre Mécaly » ne vienne
     plus toucher la piste d'annonces en fond (`.mecanos-bg`, calée en bas).
     ⚠️ 190px de plafond ne suffisait pas : mesuré à 1100px de large, la carte
     d'annonce fait 213,6px (photo 16/10 + pied) + 18px de marge basse propres
     à `.mecanos-bg` = 231,6px déjà pris par la piste SEULE, sans compter une
     respiration avant le bouton — le bouton mordait dedans de ~56px. Élargi
     pour couvrir la carte la plus haute (jusqu'à ~223px à pleine largeur) plus
     une vraie marge. */
  .mecanos-panneau{padding-bottom:clamp(210px,27vw,300px);}
}

/* LES PUCES. Flèche orange dans une pastille pâle, comme la maquette. La flèche est le seul
   marqueur qui dise « ça avance » — une coche dirait « c'est fait », un point ne dirait rien. */
.mecanos-points{
  list-style:none;margin:clamp(16px,2vw,24px) 0 clamp(22px,2.6vw,30px);padding:0;
  display:grid;gap:clamp(10px,1.2vw,14px);
}
.mecanos-points li{
  display:grid;grid-template-columns:auto minmax(0,1fr);align-items:center;gap:12px;
  color:var(--navy);font-weight:600;font-size:clamp(15px,1.15vw,16.5px);line-height:1.35;
}
.mecanos-points .ic{
  width:26px;height:26px;padding:6px;box-sizing:border-box;
  border-radius:999px;background:var(--brand-tint);fill:var(--brand-text);
  /* Pastille ronde : c'est une géométrie, pas une capsule décorative — un cercle qui porte une
     flèche de 14 px ne peut pas être autre chose que rond. */
}

/* ⚠️ SPÉCIFICITÉ : ces trois règles portent `#mecanos` parce qu'elles doivent battre
   `#mecanos h2{color:#fff}` et `#mecanos .btn-primary{background:var(--surface)}` (l. 1357 et
   1362), qui ont un id. Sans lui, `.mecanos-panneau h2` (0,1,1) perd contre `#mecanos h2`
   (1,0,1) : le titre restait blanc sur crème et le bouton blanc sur crème — les deux illisibles,
   constaté à la capture.

   Ces règles-là ne sont PAS fautives : leur commentaire explique qu'« sur fond navy, le CTA navy
   serait invisible », et c'était vrai tant que toute la section était navy. Le panneau clair les
   invalide LOCALEMENT, pas globalement — d'où une levée limitée au panneau, et non leur
   suppression : la piste d'annonces qui suit est toujours sur navy et en a toujours besoin. */
#mecanos .mecanos-panneau h2{color:var(--navy);}
#mecanos .mecanos-panneau .eyebrow{color:var(--brand-text-strong);}
#mecanos .mecanos-panneau .btn-primary{
  /* Orange plein, comme la maquette : sur fond clair c'est l'orange qui porte l'action, la
     pilule blanche n'a plus de raison d'être (elle n'existait que pour survivre au navy). */
  background:var(--brand-cta);color:#fff;
  box-shadow:0 2px 6px oklch(0.42 0.15 39 / .3), 0 14px 30px oklch(0.42 0.15 39 / .28);
}
#mecanos .mecanos-panneau .btn-primary:hover{background:var(--brand-cta-press);}
/* Le point de signature devient blanc DANS ce bouton : ailleurs il est orange sur une pilule
   blanche ou navy, ici il serait orange sur orange — donc absent. La signature « mécaly. » ne
   vaut que si le point se voit ; un point invisible n'est pas une sobriété, c'est un oubli. */
#mecanos .mecanos-panneau .btn-primary .dot{color:#fff;}

/* ══════════════════════════════════════════════════════════════════════════════════════════
   PASSE MOBILE (18/08) — remise au propre du rendu sous 900 px
   ══════════════════════════════════════════════════════════════════════════════════════════
   Le site a été dessiné au desktop puis rétréci ; plusieurs blocs pensés pour de la largeur
   se retrouvaient superposés, tronqués ou perdus dans du vide. Ce bloc vient APRÈS tout le
   reste du fichier pour gagner à spécificité égale sans avoir à surenchérir en sélecteurs.

   Les quatre défauts MESURÉS sur un viewport de 390 px, avant correction :
   ① la piste d'annonces (`.mecanos-bg`, `position:absolute;inset:0`) passait PAR-DESSUS
     l'argumentaire du panneau mécanicien — « Vous fixez votre prix » et « Le paiement est
     bloqué » étaient illisibles, posés sur des photos ;
   ② les deux téléphones du hero, calés en `flex-end` avec des marges négatives, sortaient
     de 6 px à droite (scrollWidth 381 pour 375) et laissaient un vide à gauche ;
   ③ les carrousels étaient enfermés dans le padding de leur panneau (298 px de piste pour
     390 px d'écran) : cartes coupées en plein texte, aucune affordance de glissé ;
   ④ le sous-titre des cartes de prestation tombait à 12 px.

   Références : WCAG 2.2 SC 2.5.8 (cible 24 px minimum, 44 px recommandé — c'est 44 qui est
   visé ici), corps de texte ≥ 16 px, gouttière mobile 16-20 px, sections 48-64 px. */
@media (max-width:899px){

  /* ── ① LE PANNEAU MÉCANICIEN : la piste passe SOUS l'argumentaire ──────────────────────
     En desktop la piste est un DÉCOR de fond, derrière le téléphone et le texte — il y a la
     largeur pour que les trois cohabitent. Sur mobile il n'y en a pas : un fond derrière du
     texte n'est plus un fond, c'est du texte illisible. Elle redevient donc un bloc normal,
     en dernier — c'est la conversion standard d'un décor hors flux : on le remet dans le flux
     plutôt que de le laisser flotter par-dessus.
     `.mecanos-bg` est PREMIER dans le DOM (il doit l'être en desktop, pour passer derrière) :
     `order` le renvoie en fin de grille sans toucher au HTML. */
  .mecanos-bg{
    position:static;inset:auto;order:3;
    padding-bottom:0;
    /* !important : la règle desktop pose `margin:0 !important`.
       ⚠️ PAS de débord latéral ici, contrairement au carrousel du panneau « Comment ça
       marche » (③). Mesuré : ce panneau ne fait que 350 px sur un écran de 390, son padding
       n'en retient que 32 — un débord ne gagnerait presque rien, et il obligeait à clipper le
       panneau (`overflow:hidden`) pour garder les coins arrondis, ce qui tranchait 28 px de
       la piste par le bas. La piste reste dans le padding, et le panneau reste `visible`. */
    margin:clamp(20px,5vw,26px) 0 0 !important;
  }
  /* Ordre explicite, un sélecteur par rôle : `.mecanos-haut > .reveal:not(.mecanos-bg)`
     matche AUSSI `.mecanos-device` (qui porte `.reveal`), et l'emporterait sur un
     `.mecanos-device{order:1}` moins spécifique — les deux blocs se retrouveraient à égalité
     sur un ordre qui n'a alors plus rien d'explicite. */
  .mecanos-haut > .mecanos-device{order:1;}
  .mecanos-haut > .reveal:not(.mecanos-bg):not(.mecanos-device){order:2;}
  /* Le panneau n'a plus à réserver de place en bas pour une piste qui n'y est plus posée
     (le desktop y met jusqu'à 300 px pour la laisser passer derrière le texte). */
  .mecanos-panneau{padding-bottom:clamp(20px,5vw,28px);}

  /* ── ② HERO : les deux téléphones, entiers et centrés ──────────────────────────────────
     `justify-content:flex-end` + `margin-right:-8vw` poussait la paire hors de l'écran par la
     droite. Centrée et bornée en largeur, elle tient entière — un mockup coupé net par le bord
     ne se lit pas comme un débordement voulu, il se lit comme un bug. */
  .spine__device{justify-content:center;padding-inline:var(--gutter,20px);}
  .spine__device .phone--back{margin-right:-6vw;}
  .spine__device .phone--front{margin-left:-2vw;}
  /* La paire tombait 28 px SOUS le bloc navy, isolée au milieu du gris : ni dans le hero, ni
     dans la section suivante — elle se lisait comme un morceau oublié entre les deux. Remontée
     pour chevaucher le bord arrondi du hero, elle redevient ce qu'elle est : une image POSÉE
     sur le hero. Le chevauchement est le geste qui relie, le vide est celui qui sépare. */
  .spine__device{margin-top:calc(clamp(56px,15vw,78px) * -1);position:relative;z-index:2;}

  /* ── ③ CARROUSELS PLEINE LARGEUR ───────────────────────────────────────────────────────
     Un carrousel enfermé dans le padding de son panneau perd ce qui le rend lisible comme
     tel : le débord. On le laisse toucher les bords, et on rend le padding au CONTENU (via
     `scroll-padding-inline`) — la première carte reste alignée sur le texte au repos, mais la
     piste, elle, court d'un bord à l'autre.
     `scroll-padding` plutôt qu'un padding réel : il aligne les arrêts du snap sans décaler la
     boîte de défilement, donc la dernière carte ne se retrouve pas coincée avant le bord. */
  /* ⚠️ `width:auto` est un PIÈGE ici : `.pc-panel` est un flex column en `align-items:center`,
     donc un enfant en largeur automatique se dimensionne sur son CONTENU — et le contenu, c'est
     la piste en `width:max-content`, soit 3044 px. Mesuré : la scène partait à `left:-1327`,
     le carrousel n'avait plus de fenêtre de clipping du tout. La largeur doit rester DÉFINIE :
     100 % du panneau, plus les deux paddings qu'on annule pour aller chercher ses bords. */
  /* ⚠️ La valeur DOIT être celle de `.pc-panel{padding}` au caractère près — `clamp(26px,3.6vw,48px)`,
     et pas une approximation : mesuré avec un `clamp(16px,4vw,26px)` recopié de mémoire, le
     débord tombait 10 px court de chaque côté et la piste s'arrêtait AVANT le bord du panneau,
     ce qui ne se lit ni comme un débord ni comme un alignement. */
  .pc-panel .svc-scene{
    width:calc(100% + clamp(26px,3.6vw,48px) * 2);
    margin-inline:calc(clamp(26px,3.6vw,48px) * -1);   /* = padding de `.pc-panel`, annulé */
  }
  .pc-panel .svc-piste{
    margin-right:0;
    padding-inline:clamp(26px,3.6vw,48px);
    scroll-padding-inline:clamp(26px,3.6vw,48px);
  }
  /* La piste d'annonces du panneau mécanicien ne bleede PAS (cf. ①) : elle annule seulement
     la marge négative que le desktop lui donne pour aller chercher le bord de l'écran. */
  .mecanos-bg .annonces-piste{margin-right:0;}
  /* 46vw (≈180 px) écrasait le sous-titre sur trois lignes. 62vw laisse la carte respirer ET
     garde un tiers de la suivante à l'écran — c'est ce reste visible qui dit « ça glisse »,
     maintenant que plus rien ne défile tout seul. */
  .svc-carte{width:min(62vw,240px);}
  .annonce-carte{width:min(72vw,286px);}

  /* ── ④ TYPOGRAPHIE : plus rien sous 13 px ──────────────────────────────────────────────
     12 px sur un sous-titre de carte, c'est sous le plancher de lisibilité mobile. Les
     `eyebrow` restent à 12 px : ce sont des étiquettes en capitales espacées, un rôle où la
     petite taille est le signal — pas du texte à lire. */
  .svc-texte b{font-size:16px;}
  .svc-texte span{font-size:13px;line-height:1.45;}

  /* ── ⑤ ENCOCHES ────────────────────────────────────────────────────────────────────────
     `max()` et pas `env()` seul : sur un appareil SANS encoche, `env()` vaut `0px` et
     supprimerait la gouttière au lieu de l'augmenter. */
  .site-header .bar,
  .site-footer .inner{
    padding-left:max(var(--gutter,20px), env(safe-area-inset-left));
    padding-right:max(var(--gutter,20px), env(safe-area-inset-right));
  }
  .site-footer .inner{padding-bottom:max(clamp(28px,7vw,40px), env(safe-area-inset-bottom));}
}

/* ══════════════════════════════════════════════════════════════════════════════════════════
   PASSE MOBILE — 2e tour (18/08, retours BOSS sur écran)
   ══════════════════════════════════════════════════════════════════════════════════════════
   Le 1er tour avait DÉPLACÉ l'existant sans le redessiner : les deux téléphones du hero,
   réduits à 195 px de haut et posés dans la bande claire entre deux blocs navy, se lisaient
   comme un bout d'image oublié. Quatre décisions, toutes du BOSS. */
@media (max-width:899px){

  /* ── ⑥ HERO : UN SEUL téléphone, et qu'il compte ───────────────────────────────────────
     Deux appareils côte à côte, c'est une composition de LARGEUR : sur 390 px ils se
     réduisent mutuellement jusqu'à n'être plus lisibles ni l'un ni l'autre. Un seul, grand,
     droit et centré dit la même chose — c'est l'écran de publication d'annonce, le geste que
     le hero promet. L'appareil du fond (la carte) est masqué, pas rétréci.
     Hauteur (jamais largeur) : c'est elle qui est contrainte à l'écran, et le ratio de l'image
     fixe le reste — un appareil dimensionné en largeur devient trop haut sur un écran étroit. */
  .spine__device .phone--back{display:none;}
  .spine__device .phone--front{
    height:min(108vw,430px);
    width:auto;
    margin-left:0;margin-right:0;
    transform:none;                      /* droit : une seule pièce n'a pas à être penchée */
  }
  /* L'ombre descend sur l'IMAGE : ce nœud-ci porte un transform et, depuis le 15/08, une
     animation de flottement — un filtre au même endroit rend le rectangle gris que le BOSS
     a photographié (cf. la note complète sur `.spine__device .phone`). */
  /* idem : ombre au sol héritée, jamais de drop-shadow sur un mockup */
  /* Chevauchement franc mais court : assez pour que l'appareil APPARTIENNE au navy, pas assez
     pour couvrir la note ni les badges, qui vivent au bas du bloc. */
  .spine__device{
    margin-top:-56px;
    margin-bottom:clamp(24px,6vw,36px);
    padding-inline:0;
    /* ⚠️ `top`/`right` sont posés par la règle de base (desktop, `position:absolute`). Le
       mobile les neutralisait en repassant en `position:static` — mais le 1er tour a remis
       `position:relative` pour obtenir un `z-index`, ce qui les a RÉVEILLÉS : `right:60px`
       sur un élément relatif le DÉCALE de 60 px vers la gauche. Mesuré : `left:-60`, le
       téléphone tombait hors de l'axe et se faisait rogner. Ils sont annulés explicitement. */
    top:auto;right:auto;left:auto;bottom:auto;
  }

  /* ── ⑦ COUPURE DROITE SOUS LE HERO ─────────────────────────────────────────────────────
     Décision BOSS : le bloc navy se termine NET. Les coins arrondis du bas venaient du
     desktop, où le hero flotte au-dessus d'une page claire ; sur mobile il occupe toute la
     largeur, et un arrondi n'y arrondit rien — il ouvre juste deux triangles clairs. */
  .spine{border-radius:0;}

  /* ── ⑧ LE PIED DE PAGE NE FAIT PLUS UN SECOND NAVY ─────────────────────────────────────
     Le pied prenait un navy « plus profond » ET un bord arrondi, pour se distinguer de la
     section mécanicien. Résultat sur écran : deux navys qui se ressemblent trop pour se
     distinguer mais assez pour se voir, et l'arrondi qui laisse passer le fond clair aux
     deux coins — la « bande blanche » du retour BOSS. Le pied reprend donc EXACTEMENT le
     navy de la section qui le précède, et la jointure disparaît franchement.
     (Le commentaire du 1er essai, plus haut, mesurait 1,047:1 de contraste entre les deux
     navys et en concluait qu'il fallait ACCENTUER l'écart ; la conclusion inverse est
     retenue ici — un écart imperceptible ne se corrige pas, il s'assume.) */
  .site-footer{
    border-radius:0;
    background:var(--navy);
    box-shadow:none;
  }

  /* ── ⑨ LES BADGES DE STORE, OFFICIELS DEPUIS LE 15/08 ──────────────────────────────────
     Ce bloc dessinait les pastilles maison : fond blanc plein, ombre, padding, deux lignes
     de texte, et une neutralisation du `:nth-child(2)` en verre. Tout cela est CADUC — le
     badge est maintenant une image fournie par Apple et par Google, cadre et texte compris.
     Laisser ces règles enfermait chaque badge officiel dans une grosse pastille blanche
     (vu à l'écran le 15/08 avant correction).
     ⚠️ Ne pas rétablir un fond, un rayon ou une ombre autour : les deux chartes de marque
     interdisent d'encadrer, recolorer ou déformer leur badge. La seule variable est la
     hauteur, et les deux gardent chacun son ratio propre. */
  .stores{flex-direction:row;flex-wrap:wrap;justify-content:center;gap:12px;}
  .store-badge{flex:0 0 auto;}
  .store-badge img{height:46px;}
}

/* ══════════════════════════════════════════════════════════════════════════════════════════
   PASSE MOBILE — 3e tour : conformite a la grille "Mobile From Desktop"
   ══════════════════════════════════════════════════════════════════════════════════════════
   Audit mesure du rendu a 390 px contre la grille. Conformes sans rien toucher : gouttiere
   20 px / contenu 350 px · barre de nav 64 px · logo a gauche + CTA + burger a droite ·
   sections 64/48 px (contre 96-128 en desktop, dans le ratio -40/-50 % attendu) · hero empile
   titre → sous-titre → CTA → image · titre a 41 px sur 2 lignes · corps a 16 px · aucun
   debord horizontal (scrollWidth == clientWidth). Deux ecarts seulement, corriges ici. */
@media (max-width:899px){

  /* Rangees du menu a 56 px (mesurees a 52). Le contenu ne bouge pas, c'est la zone de tap
     qui s'aligne sur la valeur attendue. */
  .nav-mobile a{padding-block:17px;}

  /* « CGU » ne faisait que 30 px de large — sa hauteur etait deja a 44, mais une cible se
     mesure dans LES DEUX sens. Les trois autres liens du pied (102 a 133 px) passaient deja ;
     seul le libelle le plus court echouait, ce qui est exactement le cas ou l'on ne pense pas
     a regarder. Les 24 px qui separent les liens restent au-dessus du minimum de 8. */
  .footer-links a{min-width:44px;text-align:center;}
}

/* ══════════════════════════════════════════════════════════════════════════════════════════
   PASSE MOBILE — 4e tour (18/08, retours BOSS sur écran)
   ══════════════════════════════════════════════════════════════════════════════════════════ */
@media (max-width:899px){

  /* ── ⑩ LE TÉLÉPHONE DU HERO REMONTE ENTRE LE TITRE ET LES BADGES ───────────────────────
     Il vivait sous le bloc navy, à cheval sur la coupure : « aucun sens qu'il soit là ».
     Il est maintenant DANS `.spine__intro`, juste après le titre (déplacement HTML) — donc
     simplement en flux, sans chevauchement à régler ni bande à réserver. Toutes les astuces
     du tour précédent (marge négative, `z-index`, annulation de `top`/`right`) tombent. */
  .spine__device{
    position:static;
    margin:clamp(18px,5vw,26px) 0 clamp(20px,5vw,28px);
    justify-content:center;
    padding-inline:0;
  }
  /* AGRANDI (BOSS, 15/08) : de min(74vw,296px) à min(86vw,360px), soit ~+22 %. La borne
     précédente était calée pour que titre + appareil + les DEUX badges + la note tiennent
     dans le premier écran d'un 390×844. Deux choses ont changé depuis : la note d'app a été
     retirée, ce qui rend ~52 px, et le BOSS veut l'appareil plus présent. Les badges peuvent
     donc descendre un peu — ils restent la seule action de la page, et un visiteur qui a vu
     l'écran de l'app scrolle de lui-même.
     ⚠️ 86vw, pas 100 : au-delà, l'appareil touche les deux bords et se lit comme rogné. */
  .spine__device .phone--front{height:min(86vw,360px);}

  /* ── ET IL BOUGE (BOSS, 15/08) ──────────────────────────────────────────────────────────
     ⚠️ SANS ROTATION. `transform` est une propriété unique : un keyframes qui poserait
     `rotate(4deg) translateY(...)` — mon premier jet — écrase le `transform:none` que le
     bloc ⑧ impose sur mobile, et penche un appareil qui doit rester DROIT (« une seule
     pièce n'a pas à être penchée »). Vu à l'écran avant correction : le téléphone était
     incliné de 4°. Le corollaire vaut dans l'autre sens : si un jour ce breakpoint remet
     une rotation, elle devra être reprise DANS chaque étape des keyframes.
     Amplitude volontairement faible (10 px, 5,5 s) : le mockup est une image plate, un
     mouvement ample trahirait qu'aucune perspective ne l'accompagne. L'ombre vivant sur
     l'`<img>`, le conteneur peut bouger sans réveiller le bug de rectangle gris. */
  @media (prefers-reduced-motion: no-preference){
    @keyframes heroPhoneFloat{
      0%,100%{transform:translateY(0);}
      50%    {transform:translateY(-10px);}
    }
    .spine__device .phone--front{animation:heroPhoneFloat 5.5s ease-in-out .9s infinite;}
  }

  /* ── ⑪ « Comment ça marche » ET « Vous savez à qui » ÉTAIENT COLLÉS ────────────────────
     Le panneau navy finissait au ras de la section claire suivante : deux sujets différents
     sans respiration entre eux. Le blanc qui les sépare est ce qui dit qu'on change de sujet. */
  .pc-panel{margin-bottom:clamp(40px,10vw,56px);}

  /* ── ⑫ LE TÉLÉPHONE DE LA PARTIE MÉCANICIEN, PLUS PETIT (mobile SEULEMENT) ─────────────
     Il occupait 593 px de haut à lui seul, soit les deux tiers d'un écran, avant même
     l'argumentaire qu'il est censé accompagner. Le desktop garde sa taille. */
  .mecanos-device .phone{width:min(58vw,240px);}

  /* ── ⑬ LES CARROUSELS REDÉFILENT TOUT SEULS ────────────────────────────────────────────
     Ils avaient été figés sur mobile (« une animation qui tourne pendant qu'on swipe se bat
     contre le doigt ») — décision BOSS inverse : ils doivent bouger. Plutôt que de rendre
     l'ancienne animation `transform`, qui EMPÊCHE tout glissé, le défilement est piloté en
     `scrollLeft` par `js/main.js` : même mécanisme que le doigt, donc les deux cohabitent
     au lieu de se disputer — et le défilement se met en pause dès qu'on touche.
     Le `scroll-snap` est retiré ici : un snap `mandatory` ramènerait la piste sur la carte
     la plus proche à chaque image, ce qui bloque net un défilement continu. */
  .svc-piste,
  .mecanos-bg .annonces-piste{scroll-snap-type:none;}
  .svc-carte,
  .annonce-carte{scroll-snap-align:none;}
}

/* ══════════════════════════════════════════════════════════════════════════════════════════
   ARTICLE — `entretien-voiture-quand-faire-quoi.html`
   Une page de lecture, pas une page de vente : colonne etroite, typographie confortable, et
   un seul appel a l'action, a la fin. Le hero navy et le pied de page restent ceux du site.
   Volontairement SANS JS : rien a animer sur un texte qu'on vient lire.
   ══════════════════════════════════════════════════════════════════════════════════════════ */
.art-hero{
  background:
    radial-gradient(circle at 1px 1px, oklch(1 0 0 / .045) 1.1px, transparent 1.6px) 0 0/23px 23px,
    radial-gradient(120% 90% at 12% -6%, oklch(0.335 0.075 257.6) 0%, var(--navy) 48%, oklch(0.198 0.05 259.51) 100%);
  color:#fff;padding:clamp(100px,12vw,140px) 0 clamp(36px,5vw,56px);
}
.art-hero h1{
  margin:.3em 0 .4em;font-weight:800;letter-spacing:-.03em;line-height:1.08;
  font-size:clamp(30px,5vw,50px);max-width:18ch;
}
.art-hero .lead{color:oklch(1 0 0 / .8);font-size:clamp(16.5px,1.8vw,20px);line-height:1.6;max-width:56ch;}
.art-crumb{font-size:13.5px;color:oklch(1 0 0 / .55);letter-spacing:.01em;}
.art-crumb a{color:oklch(1 0 0 / .72);text-decoration:none;}
.art-crumb a:hover{color:#fff;text-decoration:underline;}
.art-meta{margin:clamp(18px,2.4vw,26px) 0 0;color:oklch(1 0 0 / .5);font-size:14px;}

/* La banniere chevauche la coupure du navy : c'est ce qui rattache l'image au titre au lieu
   de la poser au debut du texte comme une illustration decollee. */
.art-banniere{background:linear-gradient(to bottom, var(--navy) 0 52%, var(--bg) 52% 100%);}
.art-banniere img{
  width:100%;height:clamp(180px,26vw,340px);object-fit:cover;
  border-radius:20px;display:block;
  box-shadow:0 24px 48px oklch(0 0 0 / .22);
}

.art-prose{
  max-width:720px;padding-block:clamp(40px,5vw,64px);
  color:var(--navy);font-size:17px;line-height:1.75;
}
.art-prose p{margin:0 0 1.15em;opacity:.88;}
.art-prose h2{
  font-size:clamp(22px,2.8vw,30px);font-weight:800;letter-spacing:-.022em;line-height:1.2;
  margin:clamp(34px,4vw,48px) 0 .5em;opacity:1;
}
.art-prose h3{
  font-size:clamp(17.5px,2vw,20px);font-weight:800;letter-spacing:-.012em;
  margin:clamp(24px,2.8vw,32px) 0 .4em;
}
.art-prose em{font-style:italic;}
.art-liste{margin:0 0 1.15em;padding-left:1.2em;}
.art-liste li{margin-bottom:.55em;opacity:.88;}
.art-liste b{opacity:1;}

/* Tableau : `overflow-x` sur un conteneur, jamais sur la page — trois colonnes de chiffres
   ne rentrent pas sous 380 px, et c'est le tableau qui doit defiler, pas le texte autour. */
.art-table-wrap{overflow-x:auto;margin:0 0 1em;-webkit-overflow-scrolling:touch;}
.art-table{
  width:100%;border-collapse:collapse;font-size:15.5px;
  background:var(--surface);border:1px solid var(--hairline);border-radius:14px;overflow:hidden;
}
.art-table th, .art-table td{padding:12px 16px;text-align:left;border-bottom:1px solid var(--hairline);}
.art-table thead th{
  background:var(--bg);font-size:13px;text-transform:uppercase;letter-spacing:.06em;
  color:var(--muted);font-weight:700;white-space:nowrap;
}
.art-table tbody th{font-weight:700;color:var(--navy);}
.art-table tbody td{color:var(--navy);opacity:.8;white-space:nowrap;}
.art-table tbody tr:last-child th, .art-table tbody tr:last-child td{border-bottom:0;}

.art-note{
  border-left:3px solid var(--brand);padding-left:16px;
  font-size:15.5px;color:var(--muted);line-height:1.6;
}
.art-encadre{
  background:var(--brand-tint);border-radius:16px;
  padding:clamp(18px,2.4vw,26px);margin:clamp(28px,3.4vw,40px) 0;
}
.art-encadre p{margin:0;opacity:1;color:var(--navy);font-size:16px;line-height:1.65;}

.art-cta{background:var(--navy);color:#fff;text-align:center;padding-block:clamp(56px,7vw,88px);}
.art-cta h2{font-size:clamp(24px,3.2vw,34px);font-weight:800;letter-spacing:-.025em;margin:0 0 .4em;}
.art-cta p{color:oklch(1 0 0 / .72);margin:0 0 clamp(24px,3vw,32px);font-size:17px;max-width:52ch;margin-inline:auto;}

/* Le `<caption>` existe pour les lecteurs d'ecran — il decrit le tableau avant qu'on y entre.
   On le masque a l'oeil sans le retirer de l'arbre d'accessibilite (`display:none` l'en
   sortirait, et la table redeviendrait muette). */
.visually-hidden{
  position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;
  clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap;border:0;
}

/* Lien vers l'autre article, en fin de prose. Deux articles qui ne se citent pas sont deux
   culs-de-sac : le lecteur repart, et chacun reste seul face au moteur de recherche. */
.art-suite{
  margin-top:clamp(30px,3.6vw,44px);padding-top:clamp(18px,2vw,24px);
  border-top:1px solid var(--hairline);font-size:16px;color:var(--muted);
}
.art-suite a{color:var(--brand-text-strong);font-weight:700;text-decoration:none;}
.art-suite a:hover{text-decoration:underline;}

/* Liste des conseils (`conseils.html`) : la carte ENTIERE est cliquable — un lien qui ne
   couvre que le titre oblige a viser, et sur une liste on veut pouvoir taper n'importe ou. */
.cons-liste-section{background:var(--bg);padding-block:clamp(44px,6vw,72px);}
.cons-liste{
  list-style:none;margin:0;padding:0;
  display:grid;gap:clamp(16px,2vw,22px);grid-template-columns:repeat(auto-fill,minmax(300px,1fr));
}
.cons-carte{
  background:var(--surface);border:1px solid var(--hairline);border-radius:18px;overflow:hidden;
  transition:border-color .18s ease, transform .18s ease, box-shadow .18s ease;
}
.cons-carte a{display:block;text-decoration:none;color:inherit;height:100%;}
.cons-carte img{width:100%;height:168px;object-fit:cover;display:block;}
.cons-carte__corps{padding:clamp(16px,2vw,22px);}
.cons-carte__tag{
  display:inline-block;font-size:11.5px;font-weight:800;letter-spacing:.07em;text-transform:uppercase;
  color:var(--brand-text-strong);background:var(--brand-tint);border-radius:6px;padding:4px 9px;
}
.cons-carte h2{
  font-size:19px;font-weight:800;letter-spacing:-.015em;line-height:1.28;color:var(--navy);
  margin:12px 0 8px;
}
.cons-carte p{margin:0;color:var(--muted);font-size:15px;line-height:1.55;}
.cons-carte__lire{
  display:inline-block;margin-top:14px;color:var(--brand-text-strong);font-weight:700;font-size:14.5px;
}
.cons-carte:hover{
  border-color:oklch(0.646 0.207 38.94 / .45);
  transform:translateY(-2px);
  box-shadow:0 12px 28px oklch(0.242 0.061 259.51 / .1);
}
@media (prefers-reduced-motion: reduce){
  .cons-carte, .cons-carte:hover{transition:none;transform:none;}
}
