/* ==========================================================================
   IMPRA — PASSE DE POLISH  (23 août 2026)
   Couche additive, chargée en dernier. Elle ne redéfinit aucun token de
   marque, aucune grille du système source, aucun composant de la baseline.

   Elle apporte quatre choses, et rien d'autre :
     1. un traitement typographique commun aux données clés,
     2. les états d'interaction des badges de store,
     3. le balayage du titre et le rail d'avis,
     4. la grille 12 colonnes de « Tout votre métier ».

   Langage de motion — volontairement pauvre : fondu, translation courte,
   progression, tracé, count-up, un seul balayage. Pas de rebond, pas de
   zoom, pas de rotation, pas de glow.
   ========================================================================== */

/* ==========================================================================
   1. KEY NUMBERS — le traitement commun des données IMPRA
   Une donnée importante se reconnaît à la graisse, au tracking resserré et
   au navy. Le bleu ne sert qu'au signe et à la progression.
   ========================================================================== */
.kn { display: flex; flex-direction: column; gap: 3px; }
.kn__v {
  font-family: var(--font-geometric);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  letter-spacing: -.022em;
  line-height: 1.04;
  color: var(--impra-navy);
  font-size: var(--kn-size, 30px);
  display: inline-flex; align-items: baseline; gap: .12em;
  white-space: nowrap;
}
.kn__v .sign,
.kn__v .kn__den { color: var(--impra-blue); }
.kn__v .kn__den { font-size: .52em; font-weight: 600; }
.kn__u { font-size: .5em; font-weight: 600; color: var(--impra-muted); letter-spacing: 0; }
.kn__k { font-size: var(--text-caption); line-height: 1.4; color: var(--impra-muted); max-width: 30ch; }
.kn__delta {
  display: inline-flex; align-items: center; gap: 4px;
  font-size: var(--text-caption); font-weight: var(--weight-semibold);
  color: var(--impra-success);
  opacity: 0; transform: translateY(4px);
  transition: opacity 420ms var(--ease-standard) 620ms, transform 420ms var(--ease-standard) 620ms;
}
.is-live .kn__delta { opacity: 1; transform: none; }
.kn--xl { --kn-size: clamp(30px, 3.2vw, 40px); }
.kn--lg { --kn-size: 30px; }
.kn--sm { --kn-size: 21px; }
.on-ink .kn__v, .band-ink .kn__v { color: var(--impra-surface); }
.on-ink .kn__k, .band-ink .kn__k { color: var(--color-lavender-mist); }
.on-ink .kn__u, .band-ink .kn__u { color: var(--color-lavender-mist); }
.on-ink .kn__v .sign, .band-ink .kn__v .sign,
.on-ink .kn__v .kn__den, .band-ink .kn__v .kn__den { color: #7FB0FF; }
.on-ink .kn__delta, .band-ink .kn__delta { color: #6EE7A8; }

/* ==========================================================================
   2. HERO — LA PREUVE SOCIALE
   Deux données signature séparées par une règle, pas deux lignes de texte
   secondaire. Elles pèsent sans devenir des cartes.
   ========================================================================== */
:root { --proof-star: #F0A50A; }   /* or de notation — hero et rail d'avis, nulle part ailleurs */

.proof-bar {
  display: flex; align-items: stretch; flex-wrap: wrap;
  gap: var(--space-24);
  padding-top: var(--space-24);
  border-top: var(--border-hairline);
}
.proof { display: flex; flex-direction: column; gap: 4px; }
.proof__v {
  font-family: var(--font-geometric);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  letter-spacing: -.024em;
  line-height: 1;
  font-size: clamp(26px, 2.4vw, 32px);
  color: var(--impra-navy);
  display: inline-flex; align-items: baseline;
}
.proof__v .sign { color: var(--impra-blue); }
.proof__v .proof__den { font-size: .5em; font-weight: 600; color: var(--impra-muted); margin-left: 1px; }
.proof__k { font-size: var(--text-caption); line-height: 1.35; color: var(--impra-muted); display: flex; align-items: center; gap: 7px; flex-wrap: wrap; }
.proof__rule { width: 1px; background: var(--impra-border); align-self: stretch; }
.stars { display: block; flex: 0 0 auto; height: 13px; width: auto; }
@media (max-width: 560px) {
  .proof-bar { gap: var(--space-16) var(--space-20); }
  .proof__rule { display: none; }
  .proof { flex: 1 1 100%; }
}

/* ==========================================================================
   3. BADGES DE STORE — ÉTATS D'INTERACTION
   Le fichier officiel n'est ni redessiné ni recoloré : tout l'effet vient du
   conteneur. L'ombre est une drop-shadow, pas une box-shadow — sans quoi la
   marge transparente du badge Google dessinerait un rectangle.
   ========================================================================== */
.store-badge {
  border-radius: 10px;
  /* Une ombre au repos : le badge est posé sur la page, pas collé dessus.
     C'est elle qui rend le soulèvement lisible — sans elle, le décalage de
     3 px passerait inaperçu. */
  filter: drop-shadow(0 2px 4px rgba(15,23,46,.10));
  /* Retour plus lent que l'aller : le badge se repose, il ne retombe pas. */
  transition: transform 280ms var(--ease-standard), filter 280ms var(--ease-standard);
  outline-offset: 4px;
  will-change: transform;
}
.store-badge--live { cursor: pointer; }

/* Le soulèvement s'applique aussi tant que la fiche n'existe pas : le badge
   doit répondre à la souris. Seule la navigation reste impossible. */
@media (hover: hover) and (pointer: fine) {
  .store-badge:hover {
    transform: translateY(-3px) scale(1.03);
    filter: drop-shadow(0 12px 22px rgba(15,23,46,.22));
    transition-duration: 200ms;
  }
}
.store-badge:active {
  transform: translateY(-1px) scale(1.01);
  filter: drop-shadow(0 4px 8px rgba(15,23,46,.18));
  transition-duration: 110ms;
}
/* Sur fond sombre une ombre portée ne se voit pas : c'est le déplacement seul
   qui porte l'effet, un peu plus franc pour compenser. */
.band-ink .store-badge,
.footer  .store-badge { filter: none; }
@media (hover: hover) and (pointer: fine) {
  .band-ink .store-badge:hover,
  .footer  .store-badge:hover { transform: translateY(-4px) scale(1.035); filter: none; }
}
.store-badge:focus-visible { outline: 2px solid var(--impra-blue); border-radius: 12px; }
.band-ink .store-badge:focus-visible,
.footer  .store-badge:focus-visible { outline-color: #7FB0FF; }
/* Tant que la fiche n'existe pas : rendu identique, aucune navigation possible */
.store-badge--pending { cursor: default; }
/* Zone tactile : 36 px d'encre + 8 px = 44 px, sans déplacer le badge */
@media (pointer: coarse) { .store-badge { padding: 4px; margin: -4px; } }
@media (prefers-reduced-motion: reduce) {
  .store-badge, .store-badge:hover, .store-badge:active { transition: none; transform: none; }
}

/* ==========================================================================
   4. BALAYAGE DU TITRE
   Le texte reste navy. Une bande bleue le traverse en 2,6 s, puis revient
   toutes les 9 s. Ce n'est pas un dégradé permanent.
   ========================================================================== */
@supports ((background-clip: text) or (-webkit-background-clip: text)) {
  /* Géométrie : l'image fait 300 % de la largeur du texte, la bande claire vit
     entre 44 % et 56 % de cette image. Aux deux positions extrêmes (0 % et
     100 %) la fenêtre visible ne montre que du navy — le texte est donc lisible
     au repos, animation jouée ou non. Une position hors bornes le rendrait
     invisible : c'est exactement le piège. */
  .hero__title .accent {
    background-image: linear-gradient(100deg,
      var(--impra-navy) 0%,   var(--impra-navy) 38%,
      #8CC0FB 44%,            #4D94F5 47.5%,
      var(--impra-blue) 50%,
      #4D94F5 52.5%,          #8CC0FB 56%,
      var(--impra-navy) 62%,  var(--impra-navy) 100%);
    background-size: 300% 100%;
    background-position: 0% 0;
    background-repeat: no-repeat;
    -webkit-background-clip: text; background-clip: text;
    color: transparent; -webkit-text-fill-color: transparent;
    animation: heroSweep 9s cubic-bezier(.33, 0, .2, 1) 1.6s infinite;
  }
  /* Le fond décroît de 100 % à 0 % : l'image glisse vers la droite, donc la
     bande traverse le texte de gauche à droite. */
  /* 2,6 s de passage sur un cycle de 9 s : la lumière traverse lentement, puis
     6,4 s de repos avant de revenir. Assez lent pour se regarder, assez espacé
     pour ne pas devenir un tic. */
  @keyframes heroSweep {
    0%           { background-position: 100% 0; }
    28.9%, 100%  { background-position: 0% 0; }
  }
}
@media (prefers-reduced-motion: reduce) {
  .hero__title .accent {
    background-image: none; animation: none;
    color: var(--impra-navy); -webkit-text-fill-color: var(--impra-navy);
  }
}

/* ==========================================================================
   5. RAIL D'AVIS — la preuve qui remplace la bande de chiffres redondante
   Boucle horizontale très lente, duplication transparente pour éviter le
   saut. Pause au survol. Liste statique en mouvement réduit.
   ========================================================================== */
.rail-head { display: flex; align-items: center; gap: var(--space-12); margin-bottom: var(--space-24); }
.rail-head__label {
  font-size: var(--text-caption); font-weight: var(--weight-semibold);
  letter-spacing: .1em; text-transform: uppercase; color: var(--impra-muted);
}
.rail-head__note { font-size: var(--text-caption); color: var(--impra-muted-soft); }
.rail {
  position: relative;
  /* Indispensable : le masque estompe mais ne coupe pas. Sans overflow, la
     piste dupliquée fait défiler toute la page latéralement. */
  overflow: hidden;
  -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 6%, #000 94%, transparent 100%);
          mask-image: linear-gradient(90deg, transparent 0, #000 6%, #000 94%, transparent 100%);
}
.rail__track {
  display: flex; width: max-content;
  /* Chaque carte prend la hauteur de son texte, et toutes se posent sur le
     même axe. Étirées, les brèves creusaient un grand vide entre la
     citation et la signature ; centrées, la bande respire et garde une
     ligne de lecture unique. */
  align-items: center;
  animation: railScroll 78s linear infinite;
  will-change: transform;
}
/* Pas de `gap` : il crée n-1 espaces et la translation de -50 % sautait d'un
   demi-gap à chaque tour. La marge de chaque wagon rend la boucle exacte.
   56 px = l'écart d'origine (40 px de marge UA des <figure> + 16 px de gap),
   repris à notre compte : plus aucune dépendance au style par défaut. */
.rail__track > * { margin: var(--space-16) var(--space-56) var(--space-16) 0; }
@keyframes railScroll { from { transform: translate3d(0,0,0); } to { transform: translate3d(-50%,0,0); } }
/* La boucle ne s'interrompt pas au survol : le mouvement fait partie de la
   bande, l'arrêter la ferait paraître cassée. Seul le mouvement réduit
   l'immobilise complètement. */

.review {
  flex: 0 0 auto; width: 316px;
  display: flex; flex-direction: column; gap: var(--space-12);
  padding: var(--space-24);
  border-radius: var(--radius-cards);
  background: var(--impra-surface);
  border: var(--border-hairline);
}
.review__stars { display: block; height: 12px; width: auto; align-self: flex-start; }
/* Les avis développés respirent plus large. Les hauteurs, elles, restent
   alignées : la variation donne du rythme, elle ne défait pas la ligne. */
.review--large { width: 372px; }

/* Connecteur entre deux avis — la grammaire de flux du système graphique :
   une trajectoire pointillée et une balise. Le halo respire lentement, décalé
   d'un connecteur à l'autre pour qu'ils ne pulsent jamais ensemble. */
.rail__link { flex: 0 0 40px; align-self: center; display: block; }
.rail__link svg { display: block; width: 40px; height: 24px; overflow: visible; }
.rail__halo { animation: railHalo 3.6s var(--ease-standard) var(--d, 0s) infinite; }
@keyframes railHalo {
  0%        { r: 4.6; opacity: .5; }
  70%, 100% { r: 11;  opacity: 0; }
}
.review__quote {
  margin: 0; font-size: var(--text-body-sm); line-height: 1.5; color: var(--impra-navy);
}
.review__who { display: flex; align-items: center; gap: 9px; margin-top: auto; }
.review__initials {
  width: 28px; height: 28px; flex: 0 0 28px; border-radius: 100px;
  display: grid; place-items: center;
  background: var(--impra-blue-soft); color: var(--impra-blue);
  font-size: 11px; font-weight: var(--weight-bold);
}
.review__name { font-size: var(--text-caption); color: var(--impra-muted); line-height: 1.35; }
.review__name b { color: var(--impra-navy); font-weight: var(--weight-semibold); display: block; }

@media (prefers-reduced-motion: reduce) {
  .rail { -webkit-mask-image: none; mask-image: none; overflow-x: auto; }
  .rail__track { animation: none; }
  .rail__track [data-clone] { display: none; }
  .rail__halo { animation: none; opacity: .45; }
}

/* ==========================================================================
   6. « TOUT VOTRE MÉTIER » — GRILLE 12 COLONNES
   7+5 · 4+4+4 · 6+6. Chaque carte a une composition, pas une icône posée
   au-dessus d'un titre.
   ========================================================================== */
.bento12 { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); gap: var(--element-gap); }
.b4 { grid-column: span 4; } .b5 { grid-column: span 5; }
.b6 { grid-column: span 6; } .b7 { grid-column: span 7; }

.dcard {
  position: relative; overflow: hidden;
  display: flex; flex-direction: column; gap: var(--space-12);
  padding: var(--space-32);
  min-height: 264px;
  border-radius: var(--radius-cards);
  border: var(--border-hairline);
  background: var(--impra-surface);
}
.dcard--tall { min-height: 300px; }
.dcard--ink {
  background: var(--color-ink-navy); border-color: var(--color-ink-navy);
  color: var(--color-paper-white);
}
.dcard--canvas { background: var(--color-warm-canvas); }
.dcard__num {
  font-size: 11px; font-weight: var(--weight-bold); letter-spacing: .14em;
  color: var(--impra-blue);
}
.dcard--ink .dcard__num { color: #7FB0FF; }
.dcard__title { font-family: var(--font-geometric); font-size: var(--text-subheading); line-height: var(--lh-subheading); color: inherit; margin: 0; }
.dcard__body { font-size: var(--text-body-sm); line-height: var(--lh-body-sm); color: var(--impra-muted); margin: 0; max-width: 46ch; }
.dcard--ink .dcard__body { color: var(--color-lavender-mist); }
.dcard__foot { margin-top: auto; padding-top: var(--space-16); }
/* Le texte doit rester au-dessus d'un média posé en fond */
.dcard > *:not(.dcard__media) { position: relative; z-index: 1; }

/* Le média participe à la composition : il se pose, il déborde, il n'est
   jamais centré au-dessus du titre. */
.dcard__media { position: absolute; z-index: 0; pointer-events: none; width: var(--mw, 150px); }
.dcard__media svg { display: block; width: 100%; height: auto; }
.dcard--m-tr .dcard__media { top: var(--space-20); right: var(--space-20); }
.dcard--m-br .dcard__media { bottom: calc(var(--space-16) * -1); right: var(--space-24); }
/* Un objet circulaire ne se coupe pas : la jauge reste entière dans la carte. */
.dcard--m-r  .dcard__media { top: 50%; right: var(--space-16); transform: translateY(-50%); }
/* Le texte cède exactement la largeur du média — sinon le titre passe dessous. */
.dcard--m-tr .dcard__title,
.dcard--m-tr .dcard__body { max-width: calc(100% - var(--mw, 150px) - 20px); }
.dcard--m-r  .dcard__body,
.dcard--m-r  .dcard__foot { max-width: calc(100% - var(--mw, 150px) - 16px); }
.dcard--m-br .dcard__body { max-width: 34ch; }
/* La réserve du pied se déclare carte par carte : un ratio global ferait soit
   chevaucher le média, soit replier une rangée de données qui tenait. */
.dcard__foot { max-width: var(--foot-max, none); }

/* ── Illustrations métier (cartes 02 et 04) ──────────────────────────────
   Elles occupent la colonne que `--mw` réserve déjà au texte, centrées
   entre le titre et le pied — ni collées au numéro, ni posées sur les
   étiquettes. Le PNG d'origine est détouré : rien à masquer, le fond de
   la carte passe au travers. */
/* Qualifié au même niveau que `.dcard--m-tr .dcard__media` (0-2-0) : sans
   cela cette règle (0-1-0) perd `top` et `right`, et l'illustration remonte
   se faire couper contre le bord haut de la carte. */
.dcard--m-tr .dcard__media--metier,
.dcard__media--metier {
  top: 50%;
  right: var(--space-24);
  transform: translateY(-50%);
}
.dcard__media--metier img { display: block; width: 100%; height: auto; }

/* Bandeau de statuts — l'ADN produit sans son interface */
.dcard .pill-row { position: relative; z-index: 1; }

/* Ligne de données à l'intérieur d'une carte */
.dgrid { display: flex; gap: var(--space-32); flex-wrap: wrap; }

@media (max-width: 1100px) {
  .dcard { padding: var(--space-24); min-height: 240px; }
  .dcard__media { width: calc(var(--mw, 150px) * .82); }
}
/* ── Tablette : 7+5 devient 12, les rangées de 3 deviennent 6+6 ── */
@media (max-width: 980px) {
  .b7, .b5 { grid-column: span 12; }
  .b4 { grid-column: span 6; }
  /* La troisième carte de la rangée prend toute la largeur : seule sur six
     colonnes, elle laisserait une demi-rangée vide. */
  .b4--last { grid-column: span 12; }
}
/* ── Mobile : une vraie séquence, Pilotage en synthèse finale ── */
@media (max-width: 720px) {
  .bento12 { grid-template-columns: minmax(0, 1fr); }
  .dcard__title, .dcard__body, .dcard__foot { max-width: none !important; }
  .b4, .b5, .b6, .b7, .b4:last-of-type { grid-column: span 1; }
  .dcard { min-height: 0; padding: var(--space-24); }
  /* Les trois variantes positionnées sont citées explicitement : sinon
     `.dcard--m-r .dcard__media` (0-2-0) l'emporte sur cette remise à plat
     (0-1-0) et le donut de Pilotage vient chevaucher sa légende. */
  .dcard__media,
  .dcard--m-r .dcard__media,
  .dcard--m-tr .dcard__media,
  .dcard--m-br .dcard__media {
    position: static; transform: none;
    width: min(100%, calc(var(--mw, 150px) * .86));
    margin-top: var(--space-12);
  }
  .dcard--m-r .dcard__body, .dcard--m-tr .dcard__body, .dcard--m-br .dcard__body { max-width: none; }
  .dcard[data-order] { order: var(--o); }
}

/* ==========================================================================
   7. MICRO-MOTION DES DONNÉES
   Brèves, déclenchées à l'apparition, une seule fois. Jamais un tableau de
   bord vivant en permanence.
   ========================================================================== */
.meter > i { transition: width 900ms var(--ease-standard) 120ms; }
.meter[data-fill] > i { width: 0; }
.is-live .meter[data-fill] > i { width: var(--fill); }

.spark path.line { stroke-dasharray: var(--len, 300); stroke-dashoffset: var(--len, 300); }
.is-live .spark path.line { transition: stroke-dashoffset 1100ms var(--ease-standard) 120ms; stroke-dashoffset: 0; }
.spark path.area { opacity: 0; transition: opacity 600ms var(--ease-standard) 700ms; }
.is-live .spark path.area { opacity: 1; }

.gauge-arc { stroke-dasharray: var(--arc) var(--rest); stroke-dashoffset: var(--arc); }
.is-live .gauge-arc { transition: stroke-dashoffset 1100ms var(--ease-standard) 180ms; stroke-dashoffset: 0; }

@media (prefers-reduced-motion: reduce) {
  .meter[data-fill] > i { width: var(--fill); transition: none; }
  .spark path.line { stroke-dasharray: none; stroke-dashoffset: 0; transition: none; }
  .spark path.area { opacity: 1; transition: none; }
  .gauge-arc { stroke-dashoffset: 0; transition: none; }
  .kn__delta { opacity: 1; transform: none; transition: none; }
}

/* ==========================================================================
   ASSISTANT — panneau rangeable
   La croix ne supprime plus le widget : elle le range vers la droite et laisse
   le lynx en bas de page. Deux états, une seule transition, aucun rebond.
   ========================================================================== */
.chat-panel__close {
  position: absolute; top: -10px; right: -10px;
  width: 24px; height: 24px; border-radius: var(--radius-buttons);
  border: var(--border-input); background: var(--surface-1);
  color: var(--impra-muted); cursor: pointer;
  display: grid; place-items: center; font-size: 13px; line-height: 1;
  transition: color 180ms var(--ease-standard), border-color 180ms var(--ease-standard);
}
.chat-panel__close:hover { color: var(--impra-navy); border-color: var(--impra-border-strong); }
.chat-panel__close:focus-visible { outline: 2px solid var(--impra-blue); outline-offset: 2px; }

/* Le panneau conserve son centrage : la translation de rangement s'ajoute au
   translateX(-50%) d'origine, elle ne le remplace pas. */
.chat-widget {
  transition: opacity 240ms var(--ease-standard),
              transform 240ms var(--ease-standard),
              visibility 0s;
}
body.chat-is-collapsed .chat-widget {
  opacity: 0;
  transform: translateX(calc(-50% + 56px)) scale(.97);
  pointer-events: none;
  visibility: hidden;
  transition-delay: 0s, 0s, 240ms;      /* on masque après la disparition */
}

.chat-launcher {
  position: fixed; z-index: 91;
  right: var(--space-24); bottom: var(--space-24);
  width: 56px; height: 56px; padding: 0;
  border-radius: var(--radius-buttons);
  border: var(--border-input);
  background: var(--surface-1);
  box-shadow: var(--shadow-widget);
  cursor: pointer;
  display: grid; place-items: center;
  opacity: 0; transform: scale(.86); pointer-events: none; visibility: hidden;
  transition: opacity 240ms var(--ease-standard),
              transform 240ms var(--ease-standard),
              box-shadow 200ms var(--ease-standard),
              visibility 0s linear 240ms;
}
body.chat-is-collapsed .chat-launcher {
  opacity: 1; transform: scale(1); pointer-events: auto; visibility: visible;
  transition-delay: 0s, 0s, 0s, 0s;
}
@media (hover: hover) and (pointer: fine) {
  body.chat-is-collapsed .chat-launcher:hover { transform: translateY(-2px) scale(1.03); }
}
.chat-launcher:active { transform: scale(.98); }
.chat-launcher:focus-visible { outline: 2px solid var(--impra-blue); outline-offset: 3px; }

/* Le lynx est réservé aux moments de marque (Explorer) : le lanceur porte
   un pictogramme neutre. */
.chat-launcher__face {
  width: 44px; height: 44px; border-radius: var(--radius-buttons);
  background-color: var(--impra-blue);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='none' stroke='white' stroke-width='1.9' stroke-linecap='round' stroke-linejoin='round' d='M21 11.6a7.8 7.8 0 0 1-8.4 7.7 9 9 0 0 1-3.2-.62L4 20l1.36-4.1A7.6 7.6 0 0 1 3.9 11.6 7.8 7.8 0 0 1 12.45 4 7.8 7.8 0 0 1 21 11.6z'/%3E%3C/svg%3E");
  background-size: 22px 22px;
  background-position: center;
  background-repeat: no-repeat;
}

/* Le panneau réduit n'occupe plus la même réserve en bas de page. */
body.chat-is-collapsed.page-bottom-pad { padding-bottom: 96px; }

@media (max-width: 700px) {
  .chat-launcher { right: var(--space-16); bottom: var(--space-16); }
}
@media (prefers-reduced-motion: reduce) {
  .chat-widget, .chat-launcher { transition: none; }
  body.chat-is-collapsed .chat-launcher:hover { transform: none; }
}

/* ==========================================================================
   8. NAVIGATION MOBILE                                    (Workleap × IMPRA)
   Benchmark Workleap : header sobre, un seul déclencheur de 48 px, panneau
   franc sous la barre. « Explorer IMPRA » reste dans le header — le menu
   porte la navigation et la connexion, jamais l'action principale.
   Couche IMPRA : la baseline Officevibe n'est pas touchée.
   ========================================================================== */
.nav__burger {
  display: none;
  width: 44px; height: 44px;
  margin-right: -6px;
  padding: 0;
  border: none; background: none; cursor: pointer;
  align-items: center; justify-content: center;
  border-radius: var(--radius-buttons);
}
.nav__burger-bars { display: block; width: 20px; }
.nav__burger-bars i {
  display: block; height: 2px; border-radius: 2px;
  background: var(--impra-navy);
  transition: transform 220ms var(--ease-standard), opacity 160ms var(--ease-standard);
}
.nav__burger-bars i + i { margin-top: 5px; }
.nav__burger[aria-expanded="true"] .nav__burger-bars i:first-child { transform: translateY(3.5px) rotate(45deg); }
.nav__burger[aria-expanded="true"] .nav__burger-bars i:last-child  { transform: translateY(-3.5px) rotate(-45deg); }
.nav__burger:focus-visible { outline: 2px solid var(--impra-blue); outline-offset: 2px; }

.nav-drawer {
  background: var(--surface-0);
  border-bottom: var(--border-hairline);
  box-shadow: 0 18px 28px rgba(15, 23, 46, .06);
}
.nav-drawer__inner { display: flex; flex-direction: column; padding-bottom: var(--space-12); }
.nav-drawer__link {
  display: flex; align-items: center;
  min-height: 52px;                     /* cible tactile large, benchmark Workleap */
  font-size: var(--text-body);
  font-weight: var(--weight-medium);
  color: var(--impra-navy);
  text-decoration: none;
  border-bottom: var(--border-hairline);
}
.nav-drawer__link:last-child { border-bottom: none; }
.nav-drawer__link--login { color: var(--impra-blue); }

@media (min-width: 901px) { .nav-drawer { display: none; } }
@media (max-width: 900px) {
  .nav__burger { display: inline-flex; }
  /* « Se connecter » vit dans le panneau : la barre garde logo + CTA + menu */
  .nav__actions .btn--ghost { display: none; }
  /* Le logo ne se laisse jamais écraser par le flex : sa taille est décidée
     plus bas, fluide — jamais par une pénurie de place. À 320 px il était
     compressé de 149 à 79 px. */
  .nav__wordmark { flex: 0 0 auto; }
}
@media (max-width: 620px) {
  /* Compaction construite à 320 px d'abord, puis vérifiée à 360/375/390 :
     logo, CTA et burger tiennent sans chevauchement ni écrasement, cibles
     tactiles intactes (44 px de hauteur). Trois clamp(), pas dix breakpoints. */
  .brand-logo img { height: clamp(19px, 2.17vw + 12.6px, 26px); }
  .nav__inner { gap: var(--space-12); }
  .nav__actions { gap: 6px; }
  .nav__actions .btn--primary {
    font-size: clamp(13px, .94vw + 10px, 14px);
    padding-inline: clamp(11px, 1.67vw + 5.7px, 16px);
  }
}
@media (max-width: 360px) {
  .nav .container { padding-inline: 18px; }
  .nav__inner { gap: var(--space-8); }
}

/* ==========================================================================
   9. RETOUR EN HAUT — mobile uniquement
   Discret, hors des zones de pouce des navigateurs, révélé après un
   défilement réel. Jamais présent au chargement.
   ========================================================================== */
.to-top {
  position: fixed; z-index: 80;
  right: var(--space-16);
  bottom: calc(var(--space-24) + env(safe-area-inset-bottom, 0px));
  width: 46px; height: 46px;
  padding: 0;
  display: none;                        /* activé par le media query mobile */
  place-items: center;
  border: var(--border-hairline);
  border-radius: var(--radius-buttons);
  background: var(--color-paper-white);
  color: var(--impra-muted);
  box-shadow: 0 6px 18px rgba(15, 23, 46, .12);
  cursor: pointer;
  opacity: 0; transform: translateY(8px); pointer-events: none;
  transition: opacity 240ms var(--ease-standard), transform 240ms var(--ease-standard);
}
.to-top.is-on { opacity: 1; transform: none; pointer-events: auto; }
.to-top:active { color: var(--impra-navy); }
.to-top:focus-visible { outline: 2px solid var(--impra-blue); outline-offset: 3px; }
@media (max-width: 900px) { .to-top:not([hidden]) { display: grid; } }
@media (prefers-reduced-motion: reduce) { .to-top { transition: none; } }

/* ==========================================================================
   10. HERO MOBILE — le visuel produit entre dans le premier écran
   Benchmark Workleap (390 × 844) : le visuel commence à 541 px, soit près de
   300 px lisibles sans défiler. Ici l'ordre du hero est conservé — seuls les
   espaces verticaux se resserrent, et la preuve passe sur une seule ligne.
   ========================================================================== */
@media (max-width: 900px) {
  .hero { padding-block: var(--space-16) var(--space-24); }
  /* Le rythme interne de la colonne : 24 → 16 px. Le H1, le sous-titre et les
     CTA gardent leur taille — seuls les intervalles se resserrent. */
  .hero .split--hero > .stack { gap: var(--space-16); }
  .hero .split--hero { gap: var(--space-16); }
  .hero .checklist--inline { margin-top: 0 !important; gap: var(--space-8) var(--space-20); }
  .hero-asset { margin-top: 0; }
}
@media (max-width: 620px) {
  /* Les deux preuves tiennent côte à côte : empilées, elles coûtaient 150 px
     du premier écran pour deux chiffres courts. */
  .hero .proof-bar { padding-top: var(--space-16); gap: var(--space-20); flex-wrap: nowrap; }
  .hero .proof { flex: 0 1 auto; }
  .hero .proof__rule { display: block; }
  .hero .proof__v { font-size: 26px; }
  /* La disponibilité mobile reste — label et badges sur une seule ligne. */
  .hero .hero__stores { margin-top: var(--space-8); }
  .hero .hero__stores .stores { flex-direction: row; align-items: center; gap: var(--space-12); }
  .hero .hero__stores .stores__label { flex: 1 1 100px; }
  .hero .hero__stores .stores__row { --store-ink: 30px; }
}

/* ==========================================================================
   11. CIBLES TACTILES                                    (WCAG 2.5.8, AA)
   Aucune géométrie visible n'est modifiée : la zone cliquable s'étend par
   un padding compensé d'une marge négative. Le rendu reste identique.
   ========================================================================== */

/* Le CTA du header restait à 33 px de haut sous 620 px : c'est l'action
   principale du site, elle doit rester confortable au pouce. */
@media (max-width: 620px) {
  .nav__actions .btn--primary { min-height: 44px; padding-block: 0; }
}

/* Liens de footer et liens fléchés : 18 à 22 px d'encre, désormais 44 px de
   zone tactile, sans desserrer la mise en page. */
@media (pointer: coarse) {
  .footer__col a,
  .footer__base a {
    padding-block: 13px;
    margin-block: -13px;
  }
  .link-arrow { padding-block: 11px; margin-block: -11px; }
}

/* ==========================================================================
   12. ACCESSIBILITÉ — CORRECTIFS LOCAUX
   Aucun changement visible : ces règles rétablissent un rendu identique
   après une correction sémantique du balisage.
   ========================================================================== */

/* Les intitulés de colonne du footer passent de <h4> à <h3> : un <h4> après
   un <h2> sautait un niveau de titre. Le style de la baseline visant
   `.footer__col h4`, on le reconduit à l'identique pour `h3`. */
.footer__col h3 {
  font-size: var(--text-caption);
  font-weight: var(--weight-bold);
  letter-spacing: var(--ls-eyebrow);
  text-transform: uppercase;
  color: var(--color-lavender-mist);
  margin: 0 0 var(--space-16);
}

/* Le header est collant : sans cette réserve, un élément atteint au clavier
   pouvait se retrouver caché sous la barre. */
:target, [id] { scroll-margin-top: 88px; }

/* Le bleu de marque porte 4,46:1 sur surface claire — juste sous le seuil AA
   de 4,5:1 pour du texte courant. Le token n'est pas touché : c'est une
   variante assombrie, dérivée de lui, réservée au TEXTE bleu. Les surfaces,
   les bordures et les icônes gardent le bleu de marque exact. */
:root { --impra-blue-text: color-mix(in srgb, var(--impra-blue) 86%, #000); }
.link-arrow,
.nav-drawer__link--login { color: var(--impra-blue-text); }

/* ==========================================================================
   13. HERO MOBILE — LE VISUEL REMONTE SOUS LES CTA
   Demande propriétaire : l'image se place juste après les deux boutons, avant
   les trois réassurances et la preuve chiffrée.

   `display: contents` sur la colonne de texte fait de ses enfants des items
   directs du hero : le visuel — qui en est le frère — peut alors s'intercaler
   entre eux par `order`. Le DOM n'est pas touché, le desktop non plus.
   ========================================================================== */
@media (max-width: 900px) {
  .hero .split--hero {
    display: flex;
    flex-direction: column;
    gap: var(--space-16);
  }
  .hero .split--hero > .stack { display: contents; }

  .hero .eyebrow            { order: 1; }
  .hero .hero__title        { order: 2; }
  .hero .lead               { order: 3; }
  .hero .row--wrap          { order: 4; }
  .hero .hero-asset         { order: 5; }
  .hero .checklist--inline  { order: 6; }
  .hero .proof-bar          { order: 7; }
  .hero .hero__stores       { order: 8; }

  /* Le visuel respire de part et d'autre sans rompre le rythme. */
  .hero .hero-asset { margin-block: var(--space-8); }
}

/* ==========================================================================
   14. HEADER — RÉPONSE BLEUE AU SURVOL
   Réservée au pointeur fin : sur tactile, un survol persistant serait un
   faux état. Le bleu de texte est la variante conforme AA.
   ========================================================================== */
@media (hover: hover) and (pointer: fine) {
  .nav__link,
  .nav__actions .btn--ghost {
    border-radius: var(--radius-buttons);
    transition: color var(--motion-base) var(--ease-standard),
                background-color var(--motion-base) var(--ease-standard);
  }
  .nav__link:hover,
  .nav__actions .btn--ghost:hover {
    color: var(--impra-blue-text);
    background: var(--impra-blue-soft);
  }
  /* Le CTA plein garde son bleu : il gagne l'élévation, pas une seconde teinte. */
  .nav__actions .btn--primary {
    transition: background-color var(--motion-base) var(--ease-standard),
                box-shadow 220ms var(--ease-standard),
                transform 220ms var(--ease-standard);
  }
  .nav__actions .btn--primary:hover {
    transform: translateY(-1px);
    box-shadow: 0 8px 20px color-mix(in srgb, var(--impra-blue) 38%, transparent);
  }
}
@media (prefers-reduced-motion: reduce) {
  .nav__actions .btn--primary:hover { transform: none; }
}

/* ==========================================================================
   15. « CE QUI VOUS RETIENT » — VERSION MOBILE
   Sur desktop, deux flèches manuscrites relient les trois cartes posées côte
   à côte. Empilées, elles pointent vers le vide : elles n'ont plus d'objet.
   Les cartes gardent leurs trois traitements — c'est la DA — mais se
   resserrent pour ne plus occuper trois écrans.
   ========================================================================== */
@media (max-width: 900px) {
  #objections .hand-arrow { display: none; }

  #objections .grid--3 { gap: var(--space-12); }
  #objections .step-card {
    padding: var(--space-24);
    transform: none !important;   /* aucune inclinaison une fois empilé */
  }
  /* Le numéro et le titre tiennent sur une seule ligne de lecture. */
  #objections .step-card > .row:first-child { gap: var(--space-12); }
  #objections .step-card__title {
    font-size: var(--text-body);
    line-height: 1.35;
    font-weight: var(--weight-semibold);
  }
  #objections .step-card__body { margin-top: var(--space-4); }
  /* La section respire moins largement : trois cartes, pas trois sections. */
  #objections .container { gap: var(--space-32) !important; }
}

/* ==========================================================================
   16. RÉASSURANCE EN LIGNE — bloc Démonstration
   Trois mentions courtes séparées par un point médian. Une seule ligne dès
   390 px : elles se lisent d'un coup d'œil au lieu d'occuper trois lignes.
   ========================================================================== */
.assur {
  display: flex; flex-wrap: wrap; align-items: center;
  gap: 0 var(--space-12);
  margin: 0; padding: 0; list-style: none;
  font-size: var(--text-body-sm);
  color: var(--color-lavender-mist);
}
.assur li { display: inline-flex; align-items: center; white-space: nowrap; }
.assur li + li::before {
  content: "·";
  margin-right: var(--space-12);
  color: rgba(255, 255, 255, .45);
}
/* Mobile : un seul composant, jamais un retour à la ligne accidentel.
   Une seule ligne exigerait ~10,5 px à 390 (294 px utiles pour 331 px de
   texte) : illisible. On assume donc un 2 + 1 volontaire sous 430 px —
   deux mentions centrées, la troisième centrée dessous, sans point médian
   orphelin en tête de ligne. Au-dessus, une ligne à 13 px tient. */
@media (max-width: 560px) {
  .assur { font-size: 13px; gap: 2px 10px; }
  .assur li + li::before { margin-right: 10px; }
}
@media (max-width: 430px) {
  .assur {
    justify-content: center; text-align: center;
    width: 100%;
    font-size: var(--text-caption); font-weight: var(--weight-medium);
    gap: 4px 8px;
  }
  .assur li + li::before { margin-right: 8px; }
  /* La troisième mention ouvre la seconde ligne : son séparateur disparaît. */
  .assur li:last-child::before { content: none; }
}

/* ==========================================================================
   16 ter. LES DEUX ILLUSTRATIONS DE COUVERTURE MÉTIER
   Carte 01 : le véhicule ET son dossier. Carte 03 : les frais, l'euro, la
   marge et sa courbe. Elles remplacent l'ancien véhicule seul et les blocs
   3D abstraits — un seul visuel par carte, jamais deux.

   Les deux fichiers sont détourés (canal alpha vérifié) : rien à masquer,
   le fond de la carte passe au travers, sombre ou clair.
   ========================================================================== */

/* ── Carte 01 · Véhicules et stock ──────────────────────────────────────
   Le nouveau visuel est presque carré (1139×950) là où l'ancien était très
   allongé. À largeur égale il monterait dans le texte : on le pose donc un
   peu plus étroit, calé sur le bord droit, sous les états. */
.dcard__media--v21ink.dcard__media--dossier { width: 252px; }
@media (max-width: 980px) { .dcard__media--v21ink.dcard__media--dossier { width: 214px; } }
/* Sur mobile le visuel revient dans le flux : sa hauteur coûte donc de la
   carte. Le nouveau dossier étant presque carré là où l'ancien véhicule
   était très allongé, on le resserre pour ne pas allonger la carte. */
@media (max-width: 720px) {
  .dcard--m-br .dcard__media--v21ink.dcard__media--dossier,
  .dcard__media--v21ink.dcard__media--dossier { width: 200px; }
}
@media (max-width: 380px) {
  .dcard--m-br .dcard__media--v21ink.dcard__media--dossier,
  .dcard__media--v21ink.dcard__media--dossier { width: 176px; }
}

/* ── Carte 03 · Frais et marge ──────────────────────────────────────────
   Même emprise que les blocs qu'il remplace (118 px) : la petite carte ne
   prend pas plus de poids que ses voisines. */
/* Le patron `m-br` fait déborder le média sous le bord de la carte : bon
   pour un bloc abstrait, mauvais pour une scène détaillée dont on
   couperait les pièces et la base. Celle-ci reste entière, à l'intérieur,
   et laisse respirer la ligne « marge prévue · investi ». */
.dcard--m-br .dcard__media--marge,
.dcard__media--marge {
  width: 106px;
  bottom: var(--space-12);
  right: var(--space-20);
}
.dcard__media--dossier img,
.dcard__media--marge img { display: block; width: 100%; height: auto; }

/* ==========================================================================
   16 · LA CARTE PHARE — 01 VÉHICULES ET STOCK
   La seule carte sombre du bento, et son point d'ancrage. Deux zones : le
   propos et les chiffres à gauche, le véhicule sur une signature de donnée
   à droite. Tout le travail consiste à desserrer — la carte disait déjà
   tout, elle le disait trop serré.
   ========================================================================== */
.dcard--phare {
  position: relative;
  overflow: hidden;
  display: block;                     /* le rythme vertical est posé au cas par cas */
  padding: var(--space-40);
  /* Un navy quasi noir, une lumière froide très basse derrière le véhicule.
     On éclaire le fond ; on n'allume pas une lampe. */
  background:
    radial-gradient(64% 78% at 78% 82%, rgba(77, 148, 245, .16) 0%, transparent 66%),
    linear-gradient(112deg, #060B1A 0%, #0A1228 58%, #0D1932 100%);
  border-color: rgba(127, 176, 255, .14);   /* presque imperceptible */
}

/* La trame de fond : la même que celle de la courbe, sur toute la carte,
   à la limite du visible. Elle donne une matière, pas une grille. */
.dcard--phare::before {
  content: "";
  position: absolute; inset: 0;
  background-image:
    linear-gradient(rgba(127, 176, 255, .045) 1px, transparent 1px),
    linear-gradient(90deg, rgba(127, 176, 255, .045) 1px, transparent 1px);
  background-size: 92px 92px;
  pointer-events: none;
}
/* Le contenu textuel est déjà reposé en relative par la règle générale des
   cartes ; inutile de la répéter ici. Ce sont les trois éléments flottants
   qui doivent s'en affranchir, et il leur faut 0-2-0 pour cela. */

/* Le numéro et son filet — la signature d'ouverture de la carte. */
.phare__num {
  display: inline-flex; align-items: center; gap: var(--space-12);
  font-size: 12px; font-weight: var(--weight-bold); letter-spacing: .14em;
  color: #7FB0FF;
}
.phare__num i { display: block; width: 46px; height: 1px; background: rgba(127, 176, 255, .34); }

/* Le titre en deux temps : ce qu'on maîtrise, puis ce qu'on pilote. La
   seconde ligne prend le bleu — c'est elle qui porte la promesse. */
/* ── La zone haute : le propos à gauche, le véhicule à droite ──────────
   La maquette de référence pose la bande KPI et le véhicule côte à côte.
   Notre carte fait 643 px là où elle en fait 790 : à cette largeur, trois
   chiffres et un véhicule ne tiennent pas sur la même ligne sans que l'un
   passe sur l'autre. Le véhicule occupe donc la droite du bloc éditorial,
   et la bande de chiffres prend toute la largeur en dessous. Personne ne
   marche sur personne. */
.phare__num, .phare__titre, .phare__corps, .statuts { max-width: 56%; }

.phare__titre {
  margin: var(--space-20) 0 0;
  /* Pas de borne en `ch` ici : à 34 px, 15ch valaient 359 px — plus large
     que la colonne — et la première ligne du titre passait sous le
     véhicule. La colonne commande, et le corps s'y ajuste. */
  font-size: clamp(23px, 2.15vw, 31px);
  line-height: 1.2;
  letter-spacing: -.02em;
  color: var(--color-paper-white);
}
.phare__titre em { font-style: normal; color: #4D94F5; }

.phare__corps {
  margin: var(--space-20) 0 0;
  color: rgba(198, 212, 238, .82);
}

/* ── Les statuts ─────────────────────────────────────────────────────── */
.statuts {
  display: flex; flex-wrap: wrap; gap: 8px;
  margin: var(--space-24) 0 0; padding: 0; list-style: none;
}
.statut {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 6px 12px 6px 10px;
  border-radius: 100px;
  border: 1px solid rgba(127, 176, 255, .16);
  background: rgba(127, 176, 255, .035);
  font-size: 12px; line-height: 1.3;
  color: rgba(206, 219, 240, .72);
  white-space: nowrap;
}
/* Un anneau, pas un point plein : l'état non courant se devine. */
.statut::before {
  content: ""; flex: 0 0 8px; width: 8px; height: 8px; border-radius: 50%;
  border: 1.5px solid rgba(127, 176, 255, .40);
}
.statut--actif {
  border-color: rgba(77, 148, 245, .55);
  background: rgba(77, 148, 245, .16);
  color: #DCE9FF;
}
.statut--actif::before { border-color: #4D94F5; background: #4D94F5; }

/* ── La bande de chiffres ──────────────────────────────────────────────
   Un seul cadre, trois colonnes, deux filets. L'encadré les rassemble :
   sans lui, trois chiffres posés sur le fond flottent. */
.phare__kpis {
  display: flex; align-items: stretch;
  margin-top: var(--space-32);
  border: 1px solid rgba(127, 176, 255, .16);
  border-radius: 14px;
  background: rgba(127, 176, 255, .035);
}
.phare__kpi {
  flex: 1 1 0; min-width: 0;
  display: flex; flex-direction: column; gap: 6px;
  padding: var(--space-20) var(--space-16);
}
.phare__kpi + .phare__kpi { border-left: 1px solid rgba(127, 176, 255, .14); }
.phare__kpi-ic { display: block; width: 19px; height: 19px; color: rgba(127, 176, 255, .72); }
.phare__kpi-ic svg {
  width: 100%; height: 100%; display: block;
  fill: none; stroke: currentColor; stroke-width: 1.6;
  stroke-linecap: round; stroke-linejoin: round;
}
.phare__kpi-v {
  margin-top: 2px;
  font-family: var(--font-geometric);
  font-weight: 700;
  font-size: clamp(20px, 1.7vw, 25px);
  line-height: 1.05;
  letter-spacing: -.026em;
  font-variant-numeric: tabular-nums;
  color: var(--color-paper-white);
  white-space: nowrap;
}
.phare__kpi-k { font-size: var(--text-caption); line-height: 1.3; color: rgba(190, 205, 232, .72); }

/* La visibilité ferme la carte — elle n'occupe pas une colonne de chiffre. */
.phare__insight {
  display: inline-flex; align-items: center; gap: 8px;
  margin: var(--space-20) 0 0;
  font-size: var(--text-caption);
  color: rgba(127, 176, 255, .88);
}

/* ── La signature de donnée ────────────────────────────────────────────
   Elle monte vers le coin haut droit, au-dessus du véhicule. Une courbe,
   quelques points, rien qui se lise comme un graphique. */
.dcard--phare .phare__data,
.phare__data {
  position: absolute;
  right: 0; top: 0;
  /* Calée sur la colonne du véhicule : plus large, la courbe traversait le
     paragraphe et le rendait sale. */
  width: 42%; height: 40%;
  z-index: 1;
  pointer-events: none;
}
.phare__trame { stroke: rgba(127, 176, 255, .07); stroke-width: 1; }
.phare__courbe { opacity: .85; }
.phare__points circle { fill: #4D94F5; }
.phare__point--fin { fill: #fff; stroke: #4D94F5; stroke-width: 2.4; }

.dcard--phare .phare__annot,
.phare__annot {
  position: absolute;
  right: var(--space-40); top: var(--space-20);
  z-index: 3;
  padding: 6px 12px;
  border-radius: 100px;
  border: 1px solid rgba(127, 176, 255, .24);
  background: rgba(8, 14, 32, .78);
  font-size: 11px; letter-spacing: .01em;
  color: #BFD6FF; white-space: nowrap;
}

/* ── Le véhicule ───────────────────────────────────────────────────────
   Il tient la moitié droite et se pose au bas de la carte. Le débord est
   choisi : la carte coupe dans l'ombre portée, jamais dans la carrosserie. */
.dcard--phare .phare__veh,
.phare__veh {
  position: absolute;
  right: calc(var(--space-24) * -1);
  /* Calé sur le bloc éditorial, jamais sur la bande de chiffres : il
     s'arrête au-dessus d'elle. */
  top: var(--space-48);
  width: 296px;
  z-index: 2;
  pointer-events: none;
}
.phare__veh img {
  display: block; width: 100%; height: auto;
  /* Une ombre de contact douce, dans le bleu du fond : le véhicule se pose
     sur la carte au lieu d'y être collé. */
  filter: drop-shadow(0 16px 24px rgba(2, 6, 20, .55))
          drop-shadow(0 40px 56px rgba(2, 6, 20, .38));
}

/* Les surcharges reprennent la qualification de la base : sans elle, une
   règle à une classe ne peut pas corriger une règle à deux, et le véhicule
   gardait ses 296 px à 1024 px — il passait alors sur le titre, le
   paragraphe ET les statuts. */
@media (max-width: 1100px) {
  .dcard--phare { padding: var(--space-32); }
  .phare__titre { font-size: clamp(23px, 2.6vw, 28px); }
  .phare__kpi { padding: var(--space-16) var(--space-12); }
  .phare__num, .phare__titre, .phare__corps, .statuts { max-width: 56%; }
  .dcard--phare .phare__veh {
    width: 232px;
    right: calc(var(--space-16) * -1);
    top: var(--space-40);
  }
  .dcard--phare .phare__annot { right: var(--space-24); font-size: 10px; padding: 5px 10px; }
  .dcard--phare .phare__data { width: 46%; }
}

/* ==========================================================================
   16 bis. PILOTAGE — LA CARTE 07 REPOSE SUR SON ILLUSTRATION
   Ni KPI, ni jauge, ni pourcentage : le parc entier d'un seul regard, un
   véhicule signalé. La carte dit ce qu'IMPRA donne à voir.

   L'image n'a pas de canal alpha — c'est une scène, pas un objet détouré.
   Elle occupe donc toute la largeur du bas de la carte et se fond dans le
   blanc par un dégradé : pas de rectangle rapporté, pas de bord franc.

   Elle reste DANS LE FLUX, poussée en bas par `margin-top: auto`, et
   déborde par des marges négatives. C'est ce qui garantit que la hauteur
   de la carte est toujours « texte + bandeau » : hors flux, elle grandissait
   avec la largeur et venait recouvrir le texte dès que la carte passait
   pleine largeur en tablette.
   ========================================================================== */
.dcard--parc { overflow: hidden; }

.dcard__parc {
  margin: auto calc(var(--space-32) * -1) calc(var(--space-32) * -1);
  padding-top: var(--space-24);
  line-height: 0;
  /* La lisière haute s'efface dans la carte : le dégradé estompe le bord,
     il ne délave pas les véhicules. */
  -webkit-mask-image: linear-gradient(180deg, transparent 0, #000 22%, #000 100%);
          mask-image: linear-gradient(180deg, transparent 0, #000 22%, #000 100%);
}
.dcard__parc img {
  display: block;
  width: 100%;
  height: 218px;
  /* `cover` recadre, il ne comprime jamais : le ratio de l'image est
     préservé à toutes les largeurs. Le cadrage privilégie le premier plan,
     là où le véhicule signalé se trouve. */
  object-fit: cover;
  object-position: center 62%;
}

/* Tablette : la carte passe pleine largeur (span 12). Sans plafond, le
   bandeau doublerait de hauteur — on le tient à une bande. */
@media (max-width: 1100px) {
  .dcard__parc { margin-inline: calc(var(--space-24) * -1); margin-bottom: calc(var(--space-24) * -1); }
  .dcard__parc img { height: 200px; }
}
/* Sous 720 px la carte passe à 20 px de padding : le débord doit suivre,
   sinon le bandeau dépasse de 4 px de chaque côté. */
@media (max-width: 720px) {
  .dcard__parc {
    padding-top: var(--space-16);
    margin-inline: calc(var(--space-20) * -1);
    margin-bottom: calc(var(--space-20) * -1);
  }
  .dcard__parc img { height: 152px; }
}
@media (max-width: 380px) {
  .dcard__parc img { height: 132px; }
}

/* ==========================================================================
   16 quater. LE CADRE DU CYCLE D'UNE AFFAIRE
   Six visuels, un seul cadre. Sa taille est fixée par le ratio des masters
   (1200 × 1500) : elle ne dépend d'aucune image, donc rien ne bouge quand
   on change d'étape — ni la hauteur, ni la largeur, ni la position.

   Le basculement est piloté par `data-beat` sur la figure, l'attribut que
   scene.impra.js posait déjà pour l'ancienne scène. Le pilote n'a pas été
   touché : c'est la même horloge, les mêmes boutons, la même reprise après
   un clic.
   ========================================================================== */
/* `.af-scene` porte un aspect-ratio de 5/6 hérité de l'ancienne scène, et
   un overflow: hidden. Qualifié en 0-2-0 pour l'emporter quel que soit
   l'ordre des feuilles : sans cela le cadre gardait 5/6, les vues en 4/5
   débordaient de 19 px et se faisaient couper EN BAS — précisément là où
   se trouve la barre de progression. */
.af-scene.af-viewer {
  margin: 0;
  aspect-ratio: 1200 / 1500;        /* le ratio des masters : le cadre, une fois pour toutes */
}

.af-vues { position: relative; width: 100%; height: 100%; }

.af-vue {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: contain;              /* jamais d'étirement */
  opacity: 0;
  /* Un souffle de 6 pour mille : perceptible comme un mouvement, jamais
     comme un zoom. La vue sortante ne recule pas — elle s'efface, sinon
     deux images se croisent en biais et l'œil accroche. */
  transform: scale(.994);
  transition: opacity 300ms var(--ease-standard), transform 300ms var(--ease-standard);
}

/* La vue de l'étape courante. Écrire les six paires vaut mieux qu'un
   sélecteur malin : on lit le mapping d'un coup d'œil. */
.af-viewer[data-beat="1"] .af-vue[data-vue="1"],
.af-viewer[data-beat="2"] .af-vue[data-vue="2"],
.af-viewer[data-beat="3"] .af-vue[data-vue="3"],
.af-viewer[data-beat="4"] .af-vue[data-vue="4"],
.af-viewer[data-beat="5"] .af-vue[data-vue="5"],
.af-viewer[data-beat="6"] .af-vue[data-vue="6"] {
  opacity: 1;
  transform: none;
}

@media (prefers-reduced-motion: reduce) {
  .af-vue { transition: none; transform: none; }
}

/* ── Mobile ────────────────────────────────────────────────────────────
   `#affaire .af-scene` bornait la scène à 300 px de haut — une mesure
   juste pour l'ancienne composition CSS, qui était paysage. Les visuels
   sont verticaux : dans un cadre paysage, la carte se retrouvait en
   boîte aux lettres, réduite au tiers de la largeur et illisible.
   Le cadre garde donc son ratio ici aussi. Qualifié avec l'ID pour
   l'emporter sur la règle d'origine (1-1-0).

   Ce n'est PAS la solution mobile définitive : les visuels dédiés
   restent à produire (voir impra/assets/cycle-affaire/mobile/). En
   attendant, mieux vaut une illustration lisible qu'une vignette. */
@media (max-width: 900px) {
  #affaire .af-scene.af-viewer {
    height: auto;
    max-height: none;
    min-height: 0;
    aspect-ratio: 1200 / 1500;
    /* Sans borne, le cadre atteignait 720 × 900 px en tablette : un visuel
       collant ne doit pas occuper l'écran entier. Il se cale au centre. */
    max-width: 360px;
    margin-inline: auto;
  }
}

/* ==========================================================================
   17. AVIS — BANDE CONTINUE, LE DOIGT PREND LA MAIN (mobile)
   Le desktop garde sa boucle CSS. Sous 900 px, même grammaire : les cartes
   défilent en continu, lentement, sans à-coups — et dès que le doigt se
   pose, la piste le suit physiquement (drag géré en JS, § AVIS de
   polish.impra.js). Au relâcher, la position est conservée et le défilement
   reprend de là, tout de suite.

   Les connecteurs disparaissent : cinq avis compacts, deux fois (la boucle
   a besoin du second jeu, marqué data-clone et muet pour les lecteurs
   d'écran).
   ========================================================================== */
@media (max-width: 900px) {
  .rail {
    overflow: hidden;
    -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 5%, #000 95%, transparent 100%);
            mask-image: linear-gradient(90deg, transparent 0, #000 5%, #000 95%, transparent 100%);
    touch-action: pan-y;          /* l'horizontal est à nous, la page garde le vertical */
    cursor: grab;
    outline-offset: 4px;
  }
  .rail:active { cursor: grabbing; }
  .rail:focus-visible { outline: 2px solid var(--impra-blue); border-radius: var(--radius-cards); }

  .rail__track {
    /* La boucle CSS sert de socle sans JavaScript ; le script la remplace
       par sa propre translation dès qu'il prend la main. Même vitesse que
       le desktop (~25 px/s), période plus courte. */
    animation-duration: 56s;
  }
  .rail__track > * { margin: 0 var(--space-12) 0 0; }
  .rail__link { display: none; }

  /* Carte compacte : moins haute, mieux proportionnée, lisible d'un regard. */
  /* Au doigt, un rail régulier se manipule mieux qu'un rail syncopé :
     la variation de largeur reste au desktop. */
  .review, .review--large {
    width: 264px;
    padding: var(--space-16) 18px;
    gap: var(--space-8);
    justify-content: flex-start;
  }
  .review__stars { height: 10px; }
  .review__quote {
    font-size: 14px; line-height: 1.5;
    color: var(--impra-navy);
    font-weight: var(--weight-medium);
  }
  .review__who {
    gap: 8px;
    margin-top: var(--space-4);
    padding-top: var(--space-8);
    border-top: var(--border-hairline);
  }
  .review__initials { width: 26px; height: 26px; flex-basis: 26px; font-size: 10px; }
  .review__name { line-height: 1.3; }

  #avis.section--tight { padding-block: var(--space-40); }
  #avis .section-head { margin-bottom: var(--space-24) !important; }
}
/* Mouvement réduit : pas de bande qui défile — une liste que l'on fait
   glisser soi-même. Le JS ne s'active pas, le jeu cloné disparaît. */
@media (prefers-reduced-motion: reduce) and (max-width: 900px) {
  .rail {
    overflow-x: auto; overflow-y: hidden;
    -webkit-overflow-scrolling: touch;
    -webkit-mask-image: none; mask-image: none;
    scrollbar-width: none;
    scroll-behavior: auto;
    touch-action: pan-x pan-y;
  }
  .rail::-webkit-scrollbar { display: none; }
  .rail__track { padding-inline: var(--page-gutter); }
}

/* ==========================================================================
   18. CYCLE D'UNE AFFAIRE — LE VÉHICULE RESTE À L'ÉCRAN (mobile)
   Le problème : le visuel en haut, les six étapes plusieurs écrans plus bas.
   L'utilisateur devait remonter pour voir à quoi correspondait une étape.

   Ici la scène devient collante sous le header pendant tout le parcours des
   étapes, et son état suit l'étape lue. Rien ne bouge tant qu'on ne défile
   pas : ce n'est pas un carrousel, c'est un repère.
   ========================================================================== */
@media (max-width: 900px) {
  #affaire .split--faq {
    display: block;                 /* la scène et la liste ne sont plus deux blocs empilés */
  }
  #affaire .af-scene {
    position: sticky;
    top: calc(64px + var(--space-8));   /* sous le header collant */
    z-index: 2;
    aspect-ratio: auto;
    height: 34vh;
    max-height: 300px;
    min-height: 210px;
    margin-bottom: var(--space-20);
    /* La scène reste lisible par-dessus les étapes qui défilent dessous. */
    box-shadow: 0 10px 24px rgba(15, 23, 46, .08);
  }
  /* À cette hauteur, les chips doivent rester lisibles sans écraser la voiture. */
  #affaire .af-chip { max-width: 62%; padding: 6px 10px 7px 12px; }
  #affaire .af-chip__k { font-size: 9.5px; letter-spacing: .06em; }
  #affaire .af-chip__v { font-size: 13px; }
  #affaire .af-glyph { width: 22%; }
  #affaire .af-meter { width: 52%; bottom: 11%; }
  #affaire .af-meter__k { font-size: 9.5px; }

  /* Les étapes défilent sous la scène. Chacune occupe assez de hauteur pour
     que le passage de l'une à l'autre se sente. */
  #affaire .steps { padding-left: var(--space-32); }
  #affaire .step { padding-block: var(--space-20); }
  #affaire .step__t { font-size: var(--text-body); }
  #affaire .step.is-active .step__t { color: var(--impra-blue-text); }
}
@media (max-width: 900px) and (max-height: 700px) {
  /* Petits écrans en hauteur : la scène cède du terrain aux étapes. */
  #affaire .af-scene { height: 30vh; min-height: 180px; }
}

/* Le bloc Démonstration portait sa marge intérieure en style en ligne, ce qui
   empêchait toute adaptation : 48 px de chaque côté ne laissaient que 246 px
   utiles à 390 px. Desktop inchangé, mobile desserré. */
#explorer .band-card { padding: var(--space-48); align-items: center; }
@media (max-width: 900px) { #explorer .band-card { padding: var(--space-32) var(--space-24); } }

/* ==========================================================================
   19. COCKPIT MÉTIER — LES PRIMITIVES
   Trois micro-composants, en HTML/CSS pur : aucun asset nouveau. Ils servent
   à rendre chaque domaine lisible en une seconde, pas à décorer.
   ========================================================================== */

/* ── LE FLUX — une séquence métier, pas une liste d'étiquettes ─────────────
   Remplace les faux rails à points qui ressemblaient à des contrôles de
   carrousel sans en être. Chaque étape est un mot déjà employé par la carte. */
.flow {
  display: flex; flex-wrap: wrap; align-items: center;
  gap: 8px 18px;
  margin: 0; padding: 0; list-style: none;
}
.flow li {
  position: relative;                       /* le connecteur vit dans l'intervalle */
  display: inline-flex; align-items: center;
  font-size: 10.5px; font-weight: var(--weight-semibold);
  letter-spacing: .015em;
  color: var(--impra-blue-text);
  background: var(--impra-blue-soft);
  border-radius: var(--radius-buttons);
  padding: 3px 9px;
  white-space: nowrap;
}
/* Le trait puis le chevron, posés DANS l'intervalle — jamais sur la pilule,
   sinon ils se peignent par-dessus son fond. */
.flow li:not(:last-child)::after,
.flow li:not(:last-child)::before {
  content: "";
  position: absolute; top: 50%;
  border-color: color-mix(in srgb, var(--impra-blue) 42%, transparent);
}
.flow li:not(:last-child)::after {
  left: calc(100% + 4px);
  width: 8px; height: 0;
  border-top: 1.5px solid;
  transform: translateY(-50%);
}
.flow li:not(:last-child)::before {
  left: calc(100% + 10px);
  width: 4.5px; height: 4.5px;
  border-top: 1.5px solid; border-right: 1.5px solid;
  transform: translateY(-50%) rotate(45deg);
}
.on-ink .flow li, .band-ink .flow li {
  color: var(--color-lavender-mist);
  background: rgba(255, 255, 255, .10);
}
/* Sous 560 px, une séquence de quatre étapes ne tient pas sur la largeur
   d'une carte : plutôt que de la couper — ce qui laisserait une flèche
   pointant vers le vide en fin de ligne — elle glisse d'un doigt. */
@media (max-width: 560px) {
  .flow {
    flex-wrap: nowrap;
    overflow-x: auto;
    gap: 0 16px;
    padding-bottom: 2px;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
  }
  .flow::-webkit-scrollbar { display: none; }
  .flow li { flex: 0 0 auto; }
}

/* ── LA PILE DE PIÈCES — carte Documents ─────────────────────────────────── */
.sheets { display: block; position: relative; width: 100%; aspect-ratio: 5 / 4; }
.sheets i {
  position: absolute; inset: 0;
  border-radius: 6px;
  background: var(--impra-surface);
  border: 1px solid var(--impra-border);
  box-shadow: 0 2px 8px rgba(15, 23, 46, .05);
}
.sheets i:nth-child(1) { transform: rotate(-8deg) translate(-9%, 5%); }
.sheets i:nth-child(2) { transform: rotate(-3deg) translate(-3%, 2%); }
.sheets i:nth-child(3) {
  transform: rotate(3deg) translate(6%, -2%);
  background:
    linear-gradient(var(--impra-border) 0 0) 14% 30% / 46% 3px no-repeat,
    linear-gradient(var(--impra-border) 0 0) 14% 48% / 62% 3px no-repeat,
    linear-gradient(color-mix(in srgb, var(--impra-blue) 60%, transparent) 0 0) 14% 68% / 28% 5px no-repeat,
    var(--impra-surface);
}

/* ── LE REGISTRE — carte Conformité ──────────────────────────────────────
   Même grammaire que la pile de pièces, à une différence près : la couverture
   du dessus est le livre de police, en navy. Les deux feuilles derrière sont
   les exports. Deux cartes voisines, un seul langage. */
.sheets--reg i:nth-child(3) {
  background: var(--impra-navy);
  border-color: var(--impra-navy);
  background-image:
    linear-gradient(rgba(255, 255, 255, .28) 0 0),
    linear-gradient(rgba(255, 255, 255, .18) 0 0),
    linear-gradient(#7FB0FF 0 0);
  background-repeat: no-repeat;
  background-position: 16% 32%, 16% 50%, 16% 70%;
  background-size: 44% 3px, 58% 3px, 26% 5px;
}
.dcard__media--reg { width: 126px; }

/* ==========================================================================
   20. COCKPIT MÉTIER — LA COMPOSITION MOBILE
   Sept panneaux empilés faisaient 3,4 écrans. Deux colonnes dès 560 px, des
   cartes resserrées, et les décorations qui coûtent de la hauteur sans rien
   dire s'effacent. Aucune information textuelle n'est retirée.
   ========================================================================== */
@media (max-width: 720px) {
  .bento12 { gap: var(--space-12); }
  .dcard { padding: var(--space-20); gap: var(--space-8); }
  .dcard__body { font-size: 13.5px; line-height: 1.5; }
  .dcard__foot { padding-top: var(--space-12); }
  /* Les objets décoratifs sans donnée cèdent la place — sauf les deux piles
     documentaires, qui disent en un coup d'œil de quoi parlent les cartes
     Documents et Conformité. Elles reviennent en coin, à taille réduite,
     et ne coûtent aucune hauteur : elles sont hors flux. */
  .dcard--canvas .dcard__media:not(.dcard__media--sheets):not(.dcard__media--reg):not(.dcard__media--marge) { display: none; }
  /* Qualifié au même niveau que `.dcard--m-br .dcard__media`, sinon la remise
     à plat mobile (0-2-0) l'emporte et le glyphe reprend la largeur de média
     d'une carte à photo — 220 px, par-dessus les étiquettes. */
  .dcard--m-br .dcard__media--sheets,
  .dcard--m-br .dcard__media--reg,
  .dcard__media--sheets,
  .dcard__media--reg {
    position: absolute;
    bottom: calc(var(--space-8) * -1);
    right: var(--space-12);
    width: 86px;
    margin-top: 0;
    opacity: .92;
  }
  .dcard--m-br .dcard__media--reg,
  .dcard__media--reg { width: 78px; }

  /* Les deux illustrations métier suivent la même règle que les piles
     documentaires : hors flux, en bas à droite, elles ne coûtent pas un
     pixel de hauteur. Qualifiées au même niveau que `.dcard--m-tr
     .dcard__media` (0-2-0), sinon la remise à plat mobile l'emporte et
     elles reprendraient la largeur de média du desktop, en plein flux. */
  /* L'illustration se loge contre le texte, jamais contre le pied : le rail
     d'étiquettes garde toute sa largeur et reste lisible d'un bout à
     l'autre. C'est le corps qui cède la place — une ligne de plus, une
     seule. La carte est en overflow: hidden, l'illustration reste donc
     entière, à l'intérieur. */
  .dcard--m-tr .dcard__media--metier,
  .dcard__media--metier {
    position: absolute;
    top: 76px;
    bottom: auto;
    right: var(--space-12);
    transform: none;
    margin-top: 0;
  }
  /* Carte 03 : le média des cartes claires s'efface sur mobile. Celui-ci
     revient — il porte le sens de la carte — au même régime que les
     autres illustrations métier : en coin, hors flux, et le corps du
     texte lui cède la place. */
  .dcard--canvas .dcard__media--marge,
  .dcard--m-br .dcard__media--marge,
  .dcard__media--marge {
    position: absolute;
    top: auto;
    bottom: var(--space-12);
    right: var(--space-12);
    width: 96px;
    margin-top: 0;
  }
  .dcard:has(.dcard__media--marge) .dcard__foot { padding-right: 108px; }

  .dcard--m-tr .dcard__media--achats,
  .dcard__media--achats { width: 96px; }
  .dcard--m-tr .dcard__media--flux,
  .dcard__media--flux   { width: 112px; }
  .dcard:has(.dcard__media--achats) .dcard__body { padding-right: 108px; }
  .dcard:has(.dcard__media--flux) .dcard__body { padding-right: 124px; }
}
/* Sous 380 px, la colonne de texte devient trop étroite : l'illustration
   se réduit d'un cran plutôt que de pousser le corps sur deux lignes de
   plus. Elle reste au-dessus du plancher de lisibilité. */
@media (max-width: 380px) {
  .dcard--canvas .dcard__media--marge,
  .dcard--m-br .dcard__media--marge,
  .dcard__media--marge { width: 82px; }
  .dcard:has(.dcard__media--marge) .dcard__foot { padding-right: 92px; }
  .dcard--m-tr .dcard__media--achats,
  .dcard__media--achats { width: 82px; }
  .dcard--m-tr .dcard__media--flux,
  .dcard__media--flux   { width: 96px; }
  .dcard:has(.dcard__media--achats) .dcard__body { padding-right: 92px; }
  .dcard:has(.dcard__media--flux) .dcard__body { padding-right: 106px; }
  /* Les étiquettes ne passent jamais sous la pile. */
  .dcard__media--sheets ~ .dcard__foot,
  .dcard__media--reg ~ .dcard__foot,
  .dcard:has(.dcard__media--sheets) .dcard__foot,
  .dcard:has(.dcard__media--reg) .dcard__foot { padding-right: 96px; }
}
@media (min-width: 561px) and (max-width: 720px) {
  /* Deux colonnes dès que la largeur le permet réellement. */
  .bento12 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .b7, .b5 { grid-column: span 2; }
  .b4 { grid-column: span 1; }
  .b6 { grid-column: span 2; }
}

/* ==========================================================================
   21. TARIFICATION — CE QUI DISTINGUE LES FORMULES
   Trois cartes qui affichaient le même « socle commun inclus » ne répondaient
   pas à la seule question qui compte : pourquoi payer plus. Chaque carte
   porte désormais son positionnement et ses quatre quotas.
   ========================================================================== */
.tier__for {
  margin: calc(var(--space-8) * -1) 0 0;
  font-size: var(--text-body-sm);
  line-height: var(--lh-body-sm);
  color: var(--impra-muted);
  min-height: 2.9em;                 /* les prix s'alignent d'une carte à l'autre */
}
.tier__list {
  list-style: none; margin: 0; padding: 0;
  display: flex; flex-direction: column; gap: var(--space-8);
  font-size: var(--text-body-sm);
  line-height: 1.4;
  color: var(--impra-muted);
}
.tier__list li {
  display: flex; align-items: baseline; gap: 7px;
  padding-block: 2px;
}
.tier__list li::before {
  content: "";
  flex: 0 0 5px; width: 5px; height: 5px;
  margin-top: .45em;
  border-radius: 50%;
  background: color-mix(in srgb, var(--impra-blue) 55%, transparent);
}
.tier__list b {
  color: var(--impra-navy);
  font-weight: var(--weight-bold);
  font-variant-numeric: tabular-nums;
}
.tier--accent .tier__list li::before { background: var(--impra-blue); }
.tier__compare { margin: 0; text-align: center; }
@media (max-width: 900px) {
  .tier__for { min-height: 0; }
  .tier__list { gap: 5px; }
  .tier__list li { padding-block: 0; }
  /* Les cartes portent maintenant quatre quotas : le rythme interne se
     resserre pour que la section reste parcourable au pouce. */
  .tier { gap: var(--space-12); padding: var(--space-24) var(--space-20); }
  .pricing { gap: var(--space-12); }
  #prix .container { gap: var(--space-32) !important; }
  #prix .card { padding: var(--space-24) !important; }
}
