/*
 * Styles portés depuis la maquette validée.
 *
 * FICHIER GÉNÉRÉ — ne pas modifier à la main.
 *   Source     : /tmp/prod/_toutes-sources.html
 *   Régénérer  : node bin/port-mockup-css.mjs "/tmp/prod/_toutes-sources.html" sites/beely-studio/theme/beely-child/assets/css/maquette.css
 *
 * Le CSS d'origine est conservé tel quel : seuls les sélecteurs sont renommés
 * vers les classes BEM du site, et les variables de la maquette remplacées par
 * les tokens du design system. Aucune valeur n'est retouchée ici.
 *
 * Les écarts voulus — accessibilité, contenu dynamique — se posent dans
 * components.css, chargé après cette feuille.
 */

/* ------------------------------------------------------------------ */
/* Cohabitation avec Bricks                                            */
/* ------------------------------------------------------------------ */

/*
 * Bricks impose `display:flex ; flex-direction:column ; width:100%` à ses
 * blocs, en 0-1-0, plus un `flex-wrap:wrap` sous `@media (max-width:760px)`.
 * Le CSS d'une maquette est écrit pour du HTML nu : ces défauts le contredisent
 * partout. On les neutralise **en bloc**, une fois.
 *
 * 0-1-0, et cette feuille arrive après le CSS de Bricks : elle gagne sur les
 * défauts, et perd sur tout ce qui est écrit à dessein —
 *
 *   .c-hero.brxe-section   (0-2-0)  un réglage posé dans un panneau
 *   .c-hero.c-hero         (0-2-0)  une règle de cette feuille
 *   .c-maillage__link.c-maillage__link   (0-1-1)  une règle descendante
 *
 * C'est ce dernier cas qui a motivé le changement. Le reset précédent visait
 * `:not([class*="c-"]):not([class*="l-"]):not([class*="u-"])` — trois sélecteurs
 * d'attribut, donc **0-3-0** — et écrasait donc les règles descendantes. Mesuré
 * le 02/08/2026 : les liens de maillage interne perdaient leur `inline-flex`,
 * repassaient en `inline`, et leur bordure en pilule se dessinait en grand arc
 * autour de la ligne de texte. Trois boutons méconnaissables par page, sur une
 * vingtaine de pages.
 *
 * « revert », pas « block » : chaque balise retrouve SA valeur par défaut. Un
 * élément Bricks porte `brxe-block` quelle que soit sa balise — un <table>, un
 * <li>, un <tr> en sont. Forcer « block » détruit leur mise en page : mesuré le
 * 01/08/2026, le tableau comparatif passait de 352 px à 1288 px.
 *
 * Ce que cela coûte, et il faut le savoir : un Block ajouté à la main dans le
 * builder naît en `display: block` et non en flex. Le contrôle « Display » du
 * panneau le remet en flex en un clic, et il émet alors du 0-2-0 qui gagne.
 */
.brxe-section, .brxe-block, .brxe-div, .brxe-container {
  display: revert;
  flex-direction: initial;
  align-items: initial;
  justify-content: initial;
  flex-wrap: initial;
  width: auto;
}

/*
 * Et les balises structurelles, MÊME SANS classe du site.
 *
 * Bricks pose « display: flex » sur tous ses blocs. Un <tr> ou un <td> n'a
 * souvent aucune classe — il échappe donc au reset ci-dessus, qui vise
 * [class*="c-"], et garde le flex. Le <table> retrouvait bien son display, mais
 * ses rangées restaient en flex : le tableau comparatif faisait 1288 px au lieu
 * de 352, ses quatre colonnes empilées.
 *
 * Ces balises portent leur mise en page dans leur nom ; on la leur rend.
 */
:where(.brxe-block, .brxe-div, .brxe-container):is(
  table, thead, tbody, tfoot, tr, th, td, caption, colgroup, col,
  li, dt, dd, figcaption, option, optgroup
) {
  display: revert;
  flex-direction: initial;
  align-items: initial;
  justify-content: initial;
  flex-wrap: initial;
  width: auto;
}

/* assets/css/styles.css */
/* =========================================================
   BEELY STUDIO — Page d'accueil
   Design tokens (variables Figma) + composants (BEM)
   Thème sombre & clair · Police Inter (auto-hébergée, RGPD : aucun appel externe)
   ========================================================= */





/* ---- THÈME CLAIR ---- */

/* =========================================================
   Reset
   ========================================================= */

/* =========================================================
   Boule de gradient animée (fond global)
   ========================================================= */

/* =========================================================
   Layout helpers
   ========================================================= */

/* =========================================================
   Typographie
   ========================================================= */
.u-accent { color: var(--color-primary); }

/* =========================================================
   Composants partagés
   ========================================================= */

/* ---- Pastilles ---- */

/* ---- Boutons ---- */

/* ---- Logo ---- */

/* ---- Bascule de thème ---- */

/* =========================================================
   HEADER
   ========================================================= */

/* Méga-menu desktop : navigation éditoriale, enrichie sans alourdir le mobile. */
.c-mega-menu.c-mega-menu { display: none; }
@media (min-width: 1101px) {
  .c-mega-menu.c-mega-menu { position: absolute; z-index: 60; top: calc(100% + 12px); left: 94px; display: grid; grid-template-columns: minmax(0, 1.3fr) minmax(220px, .7fr); gap: var(--space-l); width: min(760px, calc(100vw - 64px)); padding: var(--space-m); border: 1px solid var(--surface-border); border-radius: var(--radius-m); background: color-mix(in srgb, var(--color-d2) 94%, transparent); box-shadow: 0 28px 70px rgba(1, 8, 24, .24); backdrop-filter: blur(18px); -webkit-backdrop-filter: blur(18px); opacity: 0; visibility: hidden; pointer-events: none; transform: translateY(-8px) scale(.985); transition: opacity .2s var(--motion-easing-standard), transform .24s var(--motion-easing-standard), visibility 0s linear .24s; }
  .c-site-header.c-site-header.has-mega-open .c-mega-menu.c-mega-menu { opacity: 1; visibility: visible; pointer-events: auto; transform: none; transition-delay: 0s; }
  .c-mega-menu__eyebrow.c-mega-menu__eyebrow { margin-bottom: 7px; color: var(--color-primary); font-size: var(--fs-2xs); font-weight: 700; letter-spacing: .1em; }
  .c-mega-menu__title.c-mega-menu__title { margin-bottom: 7px; font-size: var(--fs-l); line-height: 1.1; }
  .c-mega-menu__intro.c-mega-menu__intro { max-width: 470px; color: var(--color-w-t3); font-size: var(--fs-xs); line-height: 1.55; }
  .c-mega-menu__links.c-mega-menu__links { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; margin-top: var(--space-m); }
  .c-mega-menu__link.c-mega-menu__link { display: flex; flex-direction: column; gap: 2px; min-width: 0; padding: 10px 11px; border: 1px solid transparent; border-radius: var(--radius-s); transition: background-color .2s var(--motion-easing-standard), border-color .2s var(--motion-easing-standard), transform .2s var(--motion-easing-standard); }
  .c-mega-menu__link.c-mega-menu__link:hover, .c-mega-menu__link.c-mega-menu__link:focus-visible { border-color: var(--surface-border); background: var(--color-primary-t5); transform: translateY(-1px); }
  .c-mega-menu__link.c-mega-menu__link b { color: var(--color-white); font-size: var(--fs-xs); }
  .c-mega-menu__link.c-mega-menu__link span { color: var(--color-w-t3); font-size: var(--fs-2xs); line-height: 1.4; }
  .c-mega-menu__feature.c-mega-menu__feature { display: flex; flex-direction: column; justify-content: space-between; gap: var(--space-m); min-height: 100%; padding: var(--space-m); border: 1px solid var(--color-primary-t3); border-radius: var(--radius-m); background: linear-gradient(145deg, var(--color-primary-t5), transparent 76%); }
  .c-mega-menu__feature.c-mega-menu__feature p { color: var(--color-w-t3); font-size: var(--fs-xs); line-height: 1.5; }
  .c-mega-menu__feature.c-mega-menu__feature strong { display: block; margin-bottom: 6px; color: var(--color-white); font-size: var(--fs-m); line-height: 1.2; }
  .c-mega-menu__feature.c-mega-menu__feature a { display: inline-flex; align-items: center; gap: 7px; width: fit-content; color: var(--color-primary); font-size: var(--fs-xs); font-weight: 700; }
  .c-mega-menu__feature.c-mega-menu__feature a::after { content: "→"; transition: transform .2s var(--motion-easing-standard); }
  .c-mega-menu__feature.c-mega-menu__feature a:hover::after { transform: translateX(3px); }
  .c-site-nav__link.c-site-nav__link.is-mega-active { color: var(--color-primary); }
}

/* =========================================================
   HERO
   ========================================================= */
/* En scène (JS) : le hero est haut, le groupe texte+mockup s'épingle, monte et le mockup grossit */   /* mesure de lecture : 810px (108ch) était trop long */

/* =========================================================
   LOGOS (marquee clients)
   ========================================================= */
/* Silhouettes monochromes uniformes : tous les logos rendus d'une seule teinte, quel que soit leur source */
@keyframes marquee { from { transform: translateX(0); } to { transform: translateX(-50%); } }

/* =========================================================
   TARIFS
   ========================================================= */
/* gap : source unique = --sp-card-gap (§7). Ne pas le redéclarer ici. */

/* =========================================================
   PROCESS (méthodologie)
   ========================================================= */

/* =========================================================
   PORTFOLIO
   ========================================================= */
/* Bloc consolidé « Une expertise forgée sur des projets d'envergure ».
   Une seule déclaration par sélecteur, zéro !important, tokens uniquement.
   Espacement : rôles sémantiques --sp-* (§1) — aucune 3e échelle.
   Typo : --fs-xs/s/m — aucune 3e échelle de type.
   Hooks JS préservés : .c-filter-btn.c-filter-btn/.is-active, .c-accordion-item.c-accordion-item/.is-open,
   .c-accordion-item__panel.c-accordion-item__panel (max-height piloté en JS), data-filter/data-category.
   La classe .l-section__head.l-section__head est CONSERVÉE sur .c-portfolio__head.c-portfolio__head : depuis la
   consolidation (§4) elle est ferrée à gauche partout, plus aucune surcharge
   ne la recentre — et script.u-js:563 garde son reveal sans liste à rallonge. */

/* ---- Enveloppe ---------------------------------------------------------
   RIEN à écrire ici, volontairement. §2 dé-gouttière .c-portfolio__inner.c-portfolio__inner et
   §4 en fait une colonne flex ferrée à gauche dont le `gap: --sp-head-gap`
   est le propriétaire UNIQUE des trois coutures (tête → filtres → accordéon
   → lien). Les enfants ne portent aucune margin : rien ne s'additionne,
   rien ne peut collapser, et le bloc respire au même rythme que le reste du
   site. Redéclarer gap/max-width ici ne ferait que ré-empiler une surcharge. */

/* ---- Filtres : chips discrets, ferrés à gauche ---- */

/* ---- Accordéon : lignes ouvertes à filets fins ---- */
/* Le filet est porté par CHAQUE ligne : il reste correct quand le filtre
   masque le premier élément (display:none emporte sa bordure avec lui). */

/* Les wrappers hérités s'effacent au profit de la grille de la ligne. */
/* <svg currentColor> : plus aucun filter à poser ni à annuler. */

/* ---- Panneau (max-height piloté en JS : ne PAS ajouter de padding ici) ---- */
/* Ouverture via grid-template-rows 0fr→1fr : anime vers la hauteur RÉELLE du
   contenu. L'ancien `max-height` piloté en JS était une propriété de layout
   recalculée à chaque frame (saccades sur mobile) et dépendait d'une mesure
   JS. Ici tout est en CSS, la hauteur est exacte par construction.
   Safari 16+/Firefox/Chrome animent grid-template-rows ; les moteurs plus
   anciens ouvrent instantanément (dégradation acceptable). */
/* Ouverture en CSS PUR : height 0 → auto (cf. FAQ). Le JS ne fait que basculer
   `.is-open`. `interpolate-size` anime là où c'est supporté, instantané ailleurs. */
/* Fondu du contenu (opacity composité, jamais de saccade) : ouverture douce
   même sur Safari où la hauteur s'ouvre instantanément. Gated `.u-js` : sans JS
   l'accordéon est déplié et tout doit rester visible. */
@media (prefers-reduced-motion: reduce) {
  .u-js .c-accordion-item__panel.c-accordion-item__panel, .u-js .c-accordion-item__content.c-accordion-item__content { transition: none; }
}
/* --fs-s (15px) et non --fs-xs : c'est le SEUL paragraphe de lecture du
   bloc. L'ancienne valeur 14.5px tombe entre les deux tokens ; l'arrondir
   vers le bas (12.5px) la mettrait au niveau des méta-libellés et rendrait
   le texte inconfortable. On reste dans l'échelle, au cran le plus proche. */
/* Les 2 visuels partagent la MÊME hauteur de ligne (pieds alignés) : la
   hauteur vient du visuel large, le carré l'étire en cover.
   §7 fournit display:grid + gap: var(--sp-card-gap) — gap resserré commun. */

/* ---- Paliers du bloc ---------------------------------------------------
   §9 (760px) passe déjà .c-accordion-item__images.c-accordion-item__images en colonne unique : on ne
   le réécrit pas ici, on ne traite que ce qui lui est propre. */
@media (max-width: 860px) {
  .c-accordion-item__content.c-accordion-item__content { grid-template-columns: 1fr; gap: var(--sp-5); }
  .c-accordion-item__desc.c-accordion-item__desc { max-width: none; }
}
@media (max-width: 420px) {
  .c-accordion-item__tag.c-accordion-item__tag { display: none; }
  .c-accordion-item__head.c-accordion-item__head { grid-template-areas: "idx name ico" "idx type ico"; }
}

/* Toutes les transitions introduites par le bloc, pas seulement deux. */
@media (prefers-reduced-motion: reduce) {
  .c-accordion-item__panel.c-accordion-item__panel,
  .c-accordion-item__icon.c-accordion-item__icon,
  .c-accordion-item__index.c-accordion-item__index,
  .c-accordion-item__name.c-accordion-item__name,
  .c-filter-btn.c-filter-btn { transition: none; }
}

/* =========================================================
   FAQ — voir le bloc « FAQ — accordéon aéré (DA unique) »,
   source unique plus bas dans ce fichier. Rien ici.
   ========================================================= */

/* =========================================================
   CTA (contact)
   ========================================================= */
/* Formulaire : sans cadre, intégré au thème (clair/sombre) */

/* =========================================================
   FOOTER
   ========================================================= */

/* =========================================================
   Apparition au scroll
   ========================================================= */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: 0.001ms !important; transition-duration: 0.001ms !important; scroll-behavior: auto !important; }
  .is-revealable.is-revealable { opacity: 1; transform: none; }
  .c-marquee__row.c-marquee__row { animation: none; }
}

/* =========================================================
   RESPONSIVE
   ========================================================= */
@media (max-width: 1100px) {
  /* .faq__* : gérés par le bloc FAQ unique (@media 1024px). */
  /* Portfolio : le palier mobile du bloc vit dans son bloc consolidé. */
}

@media (max-width: 900px) {
  /* Menu plein écran ouvert : header transparent pour laisser voir l'overlay (logo + croix restent au-dessus) */

  /* Menu plein écran (overlay verre + révélation circulaire depuis le burger) */

  /* Les rubriques et leurs sous-menus doivent conserver leur hauteur :
     c'est le panneau entier qui défile, jamais le contenu qui se tasse. */
.c-mobile-mega.c-mobile-mega{ flex: 0 0 auto; }

  /* Sous-menu tactile : même densité éditoriale que le méga-menu desktop. */
  .c-mobile-mega.c-mobile-mega {
    display: block;
    max-height: 0;
    padding: 0 4px;
    overflow: hidden;
    opacity: 0;
    transform: translateY(-8px);
    transition: max-height .45s var(--motion-easing-standard), opacity .25s var(--motion-easing-standard), transform .3s var(--motion-easing-standard), padding .35s var(--motion-easing-standard);
  }
  .c-mobile-mega.c-mobile-mega.is-open {
    max-height: 620px;
    padding: 4px 4px 14px;
    opacity: 1;
    transform: none;
  }
  .c-mobile-mega__eyebrow.c-mobile-mega__eyebrow { margin: 2px 0 4px; color: var(--color-primary); font-size: var(--fs-2xs); font-weight: 700; letter-spacing: .12em; }
  .c-mobile-mega__intro.c-mobile-mega__intro { margin: 0 0 14px; color: var(--color-w-t3); font-size: var(--fs-xs); line-height: 1.5; }
  .c-mobile-mega__links.c-mobile-mega__links { display: grid; gap: 7px; }
  .c-mobile-mega__links.c-mobile-mega__links a { position: relative; display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 2px 12px; padding: 10px 12px; border: 1px solid var(--surface-border); border-radius: var(--radius-s); background: var(--color-primary-t5); }
  .c-mobile-mega__links.c-mobile-mega__links span { color: var(--color-white); font-size: var(--fs-xs); font-weight: 700; }
  .c-mobile-mega__links.c-mobile-mega__links small { grid-column: 1; color: var(--color-w-t3); font-size: var(--fs-2xs); line-height: 1.4; }
  .c-mobile-mega__links.c-mobile-mega__links b { grid-row: 1 / span 2; grid-column: 2; align-self: center; color: var(--color-primary); font-size: var(--fs-s); }
  .c-mobile-mega__cta.c-mobile-mega__cta { display: flex; align-items: center; justify-content: space-between; margin-top: 12px; padding: 0 2px; color: var(--color-primary); font-size: var(--fs-xs); font-weight: 700; }
  .c-mobile-mega__cta.c-mobile-mega__cta span { font-size: var(--fs-s); }
}

@media (max-width: 640px) {

  /* Tarifs compacts en mobile : cartes presque entières sans scroller.
     (Le gap reste piloté par --sp-card-gap : une seule source.) */
}

/* Entrée animée du hero au chargement.
   On anime le CONTENEUR en un seul calque, et non chaque enfant séparément.
   Le stagger par enfant (4 animations déphasées sur ~1,15 s) forçait Firefox à
   repeindre la zone du hero en continu → ~17 frames perdues à l'arrivée sur Zen
   (Firefox), alors que Chromium/Safari layerisent et ne bronchent pas. En
   animant .c-hero__content.c-hero__content d'un bloc : 1 frame perdue, entrée identique à l'œil.
   (Le build du mockup, lui, ne pose pas problème et garde son animation.) */
@keyframes heroIn { to { opacity: 1; transform: none; } }
/* Firefox (donc Zen) re-rastérise le gros titre du hero à CHAQUE frame pendant
   l'entrée (qu'elle porte sur opacity ou transform) : il ne le promeut pas en
   calque, d'où ~15 frames perdues à l'arrivée, propres à ce moteur (mesuré ;
   Chromium et Safari layerisent et restent fluides). On y sert donc le hero
   directement en place — pas d'entrée animée, mais zéro rame. */
@-moz-document url-prefix() {
  html.u-js .c-hero__content.c-hero__content { opacity: 1; transform: none; }
  .is-hero-in.is-hero-in .c-hero__content.c-hero__content { animation: none; }
}

/* Logos tech flottants (mouvement continu) */

/* Survol des cartes */

/* Portfolio : transitions et hovers déclarés une seule fois, dans le bloc. */

/* Soulignement animé des liens (header + footer), sous chaque lien */

/* Barre de progression du scroll */

/* Boutons magnétiques (suivi du curseur en JS) */

/* =========================================================
   PASSE DE RAFFINEMENT — plus fin, plus tech
   ========================================================= */

/* Corps plus aéré *//* Titres : plus fins,
tracking serré */

/* Eyebrows / labels : fins, espacés (look tech) */

/* Surfaces "verre" + hairline */

/* Boutons plus fins */
/* Gélule du hero : pas de bleu nuit en thème clair */

/* Halos discrets. blur réduit 38->22px : le radial-gradient (transparent à 58%)
   porte déjà l'essentiel de la douceur, l'aspect est identique (vérifié en
   capture, clair + sombre) mais la rastérisation du calque flouté à l'arrivée
   est bien plus légère sur GPU modeste. */

/* Lien d'évitement (accessibilité) */

/* =========================================================
   PAGES LÉGALES
   ========================================================= */
/*
 * La hauteur de ligne des titres légaux est **héritée**, comme dans la maquette.
 *
 * `base.css` donne 1,2 à tous les titres ; le bloc légal, lui, laissait ses `h2`
 * et `h3` prendre le 1,6 de leur conteneur. La règle portée reprenait la taille,
 * la graisse et les marges — pas la hauteur de ligne. Neuf pixels par titre,
 * huit titres, 77 px de page, et rien qui le signale.
 */

/* ============================================================
   Hero — icônes en ligne sous les boutons en mobile / tablette
   (placé en fin de fichier pour primer sur les overrides globaux)
   ============================================================ */
@media (max-width: 1100px) {
  /* pas de scène épinglée sur tablette/mobile : hero classique empilé */
}

/* =========================================================
   Prestations — grille de cartes (silo : home + pages offres)
   Réutilise le langage visuel des cartes (mêmes tokens/surfaces).
   ========================================================= */
/* Lien « voir plus » sous une section (maillage interne) */

/* =========================================================
   Sous-pages (pilier, offres, tarifs, méthode, à-propos)
   Layout éditorial long-form, cohérent avec la home.
   ========================================================= */
/* Fil d'Ariane */

/* En-tête de sous-page */

/* Corps éditorial */

/* Bloc FAQ éditorial (sous-pages) */
/* .prose-faq* : supprimé — aucun des 26 HTML n'utilisait ce markup. */

/* Glow décoratif derrière l'en-tête de sous-page */

/* =========================================================
   Grille de cartes à icône (bénéfices, fonctionnalités, raisons)
   Même langage visuel que les cartes du site.
   ========================================================= */

/* Liste à puces "check" (comme les features tarifaires) hors carte */

/* Corps d'une section de sous-page (sous le .l-section__head.l-section__head) */

/* Liste de liens en "chips" (zones desservies, secteurs) */

/* Chiffres clés — traitement éditorial à filets fins (pas d'encadré) */
@media (max-width: 620px) {
  .c-stats.c-stats { flex-direction: column; }
  .c-stats__item.c-stats__item { border-left: 0; border-top: 1px solid var(--color-w-t5); padding-block: var(--space-m); }
  .c-stats__item.c-stats__item:first-child { border-top: 0; }
}

/* =========================================================
   Ambiance — grille de fond + accent serif italique (inspiration éditoriale)
   ========================================================= */
/* Grille tech subtile derrière les héros, fondue sur les bords */
/* Halo bleu atmosphérique derrière le subhero (le hero l'a sur .c-hero__sticky.c-hero__sticky) */

/* =========================================================
   Direction artistique des pages éditoriales — SaaS premium
   Une composition nette et asymétrique : les illustrations sont
   entièrement en CSS, donc sans poids d'image ni contenu factice.
   ========================================================= */

/* Mockup navigateur : un objet produit concret, dans le même langage que la home. */

/* Surfaces de produit : rayon contenu, bordure précise, mouvement discret. */
@media (hover: hover) and (pointer: fine) {
  main > .c-subhero.c-subhero ~ .l-section.l-section .c-feature-card.c-feature-card:hover,
  main > .c-subhero.c-subhero ~ .l-section.l-section .c-presta-card.c-presta-card:hover {
    transform: translateY(-4px);
    border-color: var(--color-primary-t3);
    box-shadow: 0 26px 54px -38px rgba(30, 105, 254, .28);
  }
}

/* Les sous-pages réemploient volontairement les composants de la home.
   Seul le hero varie : c'est une extension, pas un deuxième design system. */
/* Variantes de squelettes : le visuel correspond au type de page, sans image lourde. */

@media (min-width: 901px) {
  main > .c-subhero.c-subhero:has(.c-subhero__showcase.c-subhero__showcase) { padding-right: clamp(260px, 28vw, 360px); }
  .c-subhero__showcase.c-subhero__showcase { right: calc((100vw - 100%) / -2 - 24px); }
  .c-subhero__showcase.c-subhero__showcase { z-index: 0; }
}

/* Sous 761 px, le visuel du hero REVIENT DANS LE FLUX.

   Le défaut, mesuré le 07/08/2026 sur les 27 pages qui portent un sous-hero :
   `.c-subhero__showcase` reste en `position: absolute` à toutes les largeurs.
   À 375 px il occupe y=289→678 pendant que le texte court de 153 à 458, et
   comme il est en `z-index: 0` contre 1 pour le texte, la maquette se dessine
   DERRIÈRE l'accroche et les boutons. Illisible, et invisible sur toute mesure
   de hauteur : rien ne déborde, rien ne manque, tout se superpose.

   L'accueil, lui, est juste — son `c-hero__sticky` repasse en `static` sous le
   palier. C'est ce comportement qu'on reproduit ici.

   ## Pourquoi cette règle est dans la feuille et non dans le panneau

   Elle Y EST DÉJÀ, et elle ne sert à rien : la classe globale
   `c-subhero__showcase` porte `_position:mobile_landscape: relative`, son
   `_order`, sa largeur et sa marge. Mais **aucun élément de ces pages ne
   référence cette classe globale** — elle arrive dans le DOM par un autre
   chemin. Bricks n'émet donc aucun CSS pour elle, et le rendu vient d'une copie
   de ses réglages de base laissée dans le CSS personnalisé global, sans les
   surcharges responsives.

   Le panneau reste la bonne place le jour où l'élément référencera la classe.
   En attendant, la feuille du thème est la seule qui atteigne la page — elle
   charge après le bloc global, donc elle gagne. Le doublon est nommé ici pour
   qu'on ne le corrige pas deux fois.

   `transform: none` n'est pas décoratif : la base translate de -47 % pour se
   centrer verticalement en absolu. En flux, cela remonterait le visuel dans le
   texte qu'on vient de dégager.

   ## Le seuil est 900 px, et non 760 — mesuré le 07/08/2026

   Signalé par Theo : « pour chaque hero, le breakpoint juste avant le mobile,
   quand l'illu est à droite, elle passe un peu derrière le contenu du hero ».
   La cause est unique, et elle tient en deux nombres qui cessent de bouger
   ensemble.

   Le rembourrage réservé au visuel vaut `clamp(260px, 28vw, 360px)`. Sous
   928 px de fenêtre, `28vw` passe sous 260 : le rembourrage se fige donc à son
   plancher. La largeur du visuel, elle, se fige à **385 px**. Les 125 px
   d'écart entrent dans la colonne de texte, et le visuel étant en `z-index: 0`
   contre 1, il passe DESSOUS — exactement le défaut décrit.

   Le chevauchement du titre h1, relevé sur `/site-vitrine/` :

       900 px   ·          860 px   3 px       820 px   43 px
       790 px   73 px      770 px   92 px      761 px   99 px

   Aucune valeur de `clamp` ne rattrape cela : dégager 99 px de plus à 761 px
   laisserait 350 px au texte, où le titre se briserait mot à mot. À ces
   largeurs, il n'y a **pas la place** pour deux colonnes — la disposition doit
   changer, pas se comprimer.

   Le seuil passe donc de 760 à **900 px**, qui est `tablet_portrait`, l'un des
   quatre paliers du blueprint (§7). Ce n'est pas un nombre choisi pour faire
   passer la mesure : c'est le palier où le site fait déjà basculer ses
   dispositions, et à 900 px la version côte à côte ne gardait plus que 37 px
   de dégagement. */
@media (max-width: 900px) {
  .c-subhero__showcase.c-subhero__showcase {
    position: relative;
    inset: auto;
    order: 5;
    /* Centré sur X — demandé par Theo, et c'est ce que la composition appelle :
       une illustration ferrée à gauche sous un texte ferré à gauche donne deux
       axes qui se concurrencent, et la largeur bridée à 360 px laisse un vide
       asymétrique à droite qu'on lit comme un défaut d'alignement. */
    width: min(100%, 360px);
    margin-top: var(--space-m);
    margin-inline: auto;
    align-self: center;
    transform: none;
  }
}

/* Les anciens mockups décoratifs des sous-pages sont remplacés par celui du hero. */

/* Mot-clé surligné en "chip" bleu (façon pixelmarin) */

/* =========================================================
   Mockup navigateur — illustration de site animée (pur CSS)
   ========================================================= */
/* Scène de zoom épinglé (home). Sans JS : simple bloc centré. */
/* Mockup vedette : centré, large, grossit au scroll */
/* Barre du navigateur — contraste garanti en clair ET sombre */
.c-mockup__url-text.c-mockup__url-text { flex: 0 0 auto; white-space: nowrap; }
/* Balayage lumineux (contenu qui paraît vivant) */

/* Contenu vivant (le zoom au scroll est géré en JS — voir script.u-js) */
@media (prefers-reduced-motion: reduce) {
  .c-mockup__caret.c-mockup__caret, .c-mockup__screen.c-mockup__screen::after, .c-mockup-hero__cta.c-mockup-hero__cta { animation: none; }
}
@keyframes mk-caret { 50% { opacity: 0; } }
@keyframes mk-shimmer { 0% { transform: translateX(-75%); } 55%, 100% { transform: translateX(185%); } }
@keyframes mk-pulse { 0%, 100% { box-shadow: 0 0 0 0 var(--color-primary-t3); } 55% { box-shadow: 0 0 0 7px transparent; } }

/* Le contenu du mockup se construit une fois le mockup à pleine taille (.is-live.is-live) */
@keyframes mk-draw { from { transform: scaleX(0.04); opacity: 0; } to { transform: scaleX(1); opacity: 1; } }
@keyframes mk-fade { from { transform: scale(0.5); opacity: 0; } to { transform: scale(1); opacity: 1; } }

/* Glow doux derrière le CTA final */

/* =========================================================
   BLOCS « DESIGN TECH » BESPOKE — couche d'alias de tokens
   Mappe le vocabulaire des blocs (--panel, --line, --text…)
   sur tes tokens réels : le thème dark/light reste géré par
   [data-theme] (aucune duplication). Retirer ce bloc + les
   <section class="bx-*"> des pages suffit à tout annuler.
   ========================================================= */

/* =========================================================
   MEGA-MENU — version aérée (surcharge, desktop ≥1101px)
   Le panneau reste le seul élément « flottant » encadré ;
   à l'intérieur : lignes ouvertes + filets, plus de cartes.
   ========================================================= */
@media (min-width: 1101px) {
  .c-mega-menu.c-mega-menu {
    grid-template-columns: minmax(0, 1.5fr) minmax(206px, 0.7fr);
    padding: var(--space-l);
    background: color-mix(in srgb, var(--surface) 97%, transparent);
    border-color: var(--surface-border);
  }
  .c-mega-menu__title.c-mega-menu__title { letter-spacing: -0.02em; }
  .c-mega-menu__links.c-mega-menu__links {
    grid-template-columns: 1fr;
    gap: 3px;
    margin-top: var(--space-s);
  }
  .c-mega-menu__link.c-mega-menu__link {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    row-gap: 2px;
    align-items: center;
    padding: 11px 12px;
    border: 0;
    border-radius: var(--radius-s);
    background: transparent;
    transition: background-color 0.2s var(--motion-easing-standard);
  }
  .c-mega-menu__link.c-mega-menu__link b { grid-column: 1; grid-row: 1; }
  .c-mega-menu__link.c-mega-menu__link span { grid-column: 1; grid-row: 2; }
  .c-mega-menu__link.c-mega-menu__link::after {
    content: "→";
    grid-column: 2;
    grid-row: 1 / span 2;
    align-self: center;
    color: var(--color-w-t5);
    font-size: var(--fs-s);
    transition: transform 0.2s var(--motion-easing-standard), color 0.2s var(--motion-easing-standard);
  }
  .c-mega-menu__link.c-mega-menu__link:hover,
  .c-mega-menu__link.c-mega-menu__link:focus-visible {
    background: color-mix(in srgb, var(--color-primary) 8%, transparent);
  }
  .c-mega-menu__link.c-mega-menu__link:hover::after,
  .c-mega-menu__link.c-mega-menu__link:focus-visible::after {
    color: var(--color-primary);
    transform: translateX(3px);
  }
  .c-mega-menu__feature.c-mega-menu__feature {
    border: 0;
    border-left: 1px solid var(--surface-border);
    border-radius: 0;
    background: transparent;
    padding: 2px 0 2px var(--space-l);
  }
  .c-mega-menu__feature.c-mega-menu__feature strong { letter-spacing: -0.01em; }
}

/* =========================================================
   PASSE DESIGN SYSTEM AÉRÉ + ANIMATIONS (composants + blocs)
   Généré : surcharges globales, se propagent à toutes les pages.
   ========================================================= */


/* ============ COMPOSANTS (restyle aéré) ============ */


/* ---- feature-card ---- */
/* =============================================================
   OVERRIDE — feature-card / feature-grid  →  AÉRÉ (Stripe-like)
   Cartes boxy (bordure + ombre + rond icône) transformées en
   items OUVERTS séparés par un filet, glyphe icône inline,
   entrée .is-in.is-in en cascade + micro-hover. Aucun HTML modifié.
   ============================================================= */

/* --- Grille : plus d'air, filet supérieur commun, reflow conservé ---
   FIX 2 : on centralise le padding-haut dans un token --grid-pad,
   partagé par la grille ET le tick d'accent (::after), pour qu'ils
   restent verrouillés ensemble (desktop + mobile). */
/* on garde les variantes de colonnes telles quelles (2 / 4) — juste l'air change */

/* --- La carte : plus de boîte. Bloc ouvert, filet + glyphe --- */

/* cascade : décalage progressif entre frères (pas de 70ms, plafonné) */

/* --- Icône : glyphe inline, plus de pastille pleine --- */

/* --- Titre : 700, serré, réagit au survol --- */

/* --- Texte : secondaire, lien = accent unique --- */

/* =============================================================
   SURCHARGE DU SCOPE SOUS-PAGE — on annule la carte "produit"
   (bordure, ombre, ::before dégradé, hover lift) au profit de
   la version aérée + un filet-accent en tête qui se dessine.
   ============================================================= */

/* on neutralise le liseré dégradé d'origine… */

/* …et on ajoute un court filet d'accent en tête, qui grandit au survol
   (analogue "underline grow", GPU-friendly : scaleX).
   FIX 2 : `top` calé sur le MÊME token --grid-pad que la grille,
   donc toujours posé pile sur le filet, desktop comme mobile. */

/* --- Micro-hover : titre → brand, glyphe glisse, filet-accent se dessine --- */
@media (hover: hover) and (pointer: fine) {
  main > .c-subhero.c-subhero ~ .l-section.l-section .c-feature-card.c-feature-card:hover { transform: none; }

  .c-feature-card.c-feature-card:hover .c-feature-card__title.c-feature-card__title { color: var(--brand); }
  .c-feature-card.c-feature-card:hover .c-feature-card__icon.c-feature-card__icon  { transform: translateX(3px); color: var(--brand); }

}

/* --- Reflow mobile : filet moins large, air resserré ---
   FIX 2 : on redéfinit --grid-pad ici → grille ET tick suivent
   automatiquement la même valeur mobile (26px). */

/* =============================================================
   GARDE MOUVEMENT RÉDUIT — tout visible, aucune anim
   ============================================================= */
@media (prefers-reduced-motion: reduce) {
  .c-feature-card.c-feature-card,
  .c-feature-card.c-feature-card.is-in,
  main > .c-subhero.c-subhero ~ .l-section.l-section .c-feature-card.c-feature-card,
  main > .c-subhero.c-subhero ~ .l-section.l-section .c-feature-card.c-feature-card.is-in,
  .c-feature-card__icon.c-feature-card__icon,
  .c-feature-card__title.c-feature-card__title,
  .feature-card__step,
  
}


/* ---- presta-card ---- */
/* =========================================================================
   OVERRIDE — presta-card  (services / prestations grid)
   Airy hairline restyle + staggered .is-in.is-in entrance + hover micro-interactions.
   Appended at end of stylesheet → equal-specificity rules win over originals.
   Colors use the alias layer only. Works in light + dark, reflows on mobile.

   REVEAL WIRING (fix 1, cleaner alternative): the class hook stays `.is-in`.
   A dedicated 4-line IntersectionObserver in assets/js/script.u-js observes
   `.c-presta-card` and toggles `.is-in`. It lives AFTER the `prefersReduced`
   early-return, so reduced-motion users never get the class (and the guard
   block below freezes the final state anyway). Keeping our own observer means
   the site's generic one does NOT overwrite our nth-child stagger with an
   inline transition-delay, nor push a conflicting `.is-revealable` 24px offset.
   ========================================================================= */

/* --- Grid: keep the 4-up reflow, breathe a little more between cards ------- */

/* --- Card: kill the box. Light hairline card, no shadow, no tint fill ------ */

/* Staggered reveal — continuous diagonal cascade, 50ms steps.
   The delay applies only to opacity+transform (rungs 1 & 2 of the shorthand);
   border-color/background-color keep 0s so hover stays instant.
   Rungs 1–8 cover the first two rows of a 4-up grid; any 9th+ card is capped
   at a shared 400ms so NOTHING past the ladder pops in with a 0ms delay. */

/* Hover: subtle lift + faint brand tint + accent hairline (no drop shadow) */
@media (hover: hover) and (pointer: fine) {
  .c-presta-card.c-presta-card:hover {
    transform: translateY(-4px);
    border-color: var(--brand-t);
    background: var(--brand-t2);        /* very light brand wash */
    box-shadow: none;
  }
}

/* --- Icon: flat brand-tint chip, no heavy fill ---------------------------- */
@media (hover: hover) and (pointer: fine) {
  .c-presta-card.c-presta-card:hover .c-presta-card__icon.c-presta-card__icon {
    transform: translateY(-1px) scale(1.04);
    background: var(--brand-t2);
  }
}

/* --- Title: 700 / tight tracking ------------------------------------------ */

/* --- Description: secondary text ------------------------------------------ */

/* --- « en savoir plus »: mono uppercase link with animated → arrow -------- */
/* Draw the arrow ourselves so we can animate it independently of icon markup.
   NOTE (fix 3): no permanent `will-change` here — a 4px nudge doesn't warrant
   a pinned compositing layer per card. The hover block below opts the layer in
   only for the pointer devices that can actually trigger the transform. */
/* Le HTML porte déjà un SVG flèche : sans ça on lisait « EN SAVOIR PLUS → → ».
   On masque le SVG plutôt que d'éditer 21 pages, et on garde le ::after,
   seul à être animé au survol. */
@media (hover: hover) and (pointer: fine) {
  .c-presta-card.c-presta-card:hover .c-presta-card__more.c-presta-card__more { gap: .5em; }   /* neutralise old gap bump */
  .c-presta-card.c-presta-card:hover .c-presta-card__more.c-presta-card__more::after {
    transform: translateX(4px);
    will-change: transform;            /* scoped: only while hovering */
  }
}

/* =========================================================================
   Landing / sub-page variant (main > .c-subhero.c-subhero ~ .l-section.l-section .c-presta-card.c-presta-card)
   Remove the boxed shadow + ::before gradient fill → same airy hairline.
   IMPORTANT (fix 2): the original rule at this selector (specificity 0,3,1)
   sets `transform: none`, which outranks both `.c-presta-card` (0,1,0) and
   `.c-presta-card.is-in` (0,2,0) — killing the slide on sub-pages. So we must
   re-establish BOTH the pre-state and the revealed state at THIS specificity,
   or subpage cards would fade without lifting.
   ========================================================================= */
@media (hover: hover) and (pointer: fine) {
  main > .c-subhero.c-subhero ~ .l-section.l-section .c-presta-card.c-presta-card:hover {
    transform: translateY(-4px);
    border-color: var(--brand-t);
    background: var(--brand-t2);
    box-shadow: none;
  }
}

/* --- Reduced-motion guard: freeze final state, no transitions/keyframes ----
   Covers the subpage selector too so its re-armed 14px offset can't strand a
   reduced-motion user on an invisible/offset card (the JS observer also never
   fires under reduced motion, so `.is-in` would never arrive on its own). */
@media (prefers-reduced-motion: reduce) {
  .c-presta-card.c-presta-card,
  .c-presta-card.c-presta-card.is-in,
  main > .c-subhero.c-subhero ~ .l-section.l-section .c-presta-card.c-presta-card,
  main > .c-subhero.c-subhero ~ .l-section.l-section .c-presta-card.c-presta-card.is-in,
  .c-presta-card__icon.c-presta-card__icon,
  .c-presta-card__more.c-presta-card__more,
  .c-presta-card__more.c-presta-card__more::after {
    opacity: 1 !important;
    transform: none !important;
    animation: none !important;
    transition: none !important;
    transition-delay: 0s !important;
  }
}


/* ---- pricing / price-card (+ replace conic border) ---- */
/* =========================================================================
   PRICING / PRICE-CARD — AIRY OVERRIDE (Stripe-like, hairline, aéré)
   Appended at end of stylesheet → equal-specificity rules WIN.
   Re-declares existing selectors only. No HTML/class changes.
   Site JS reveals .c-price-card.c-price-card via .is-revealable.is-revealable + .is-visible.is-visible; we also honor
   the spec's .is-in.is-in. Reduced motion: JS skips .is-revealable.is-revealable → cards stay visible,
   plus an explicit guard below.
   ========================================================================= */

/* ---- Section shell: more air, comfortable rhythm ---------------------- */
/* Les gaps des deux grilles de tarifs ont UNE seule source : --sp-card-gap
   (§7, fin de feuille). Les `clamp(16px,3vw,32px)` qui vivaient ici sont
   supprimés — ils écartaient les cartes de 32px sur desktop et rendaient
   toute tentative de resserrage inopérante. */

/* ---- Base card: kill the boxy filled panel → light hairline card ------ */
/* subtle hover lift + brand hairline tint, NO boxy shadow */

/* ---- Featured plan: NOT a heavy box — soft brand tint + accent line --- */

/* mono "RECOMMANDÉ" tag straddling the top edge (badge, not a box) */
/* `.c-price-card > * { z-index: 2 }` : occurrence unique dans §7b (fin de feuille). */

/* ---- Price figure: tabular, quiet "à partir de" label ----------------- */

/* titles: house style (700, tight tracking) */

/* soften the icon chip to a hairline tile, not a filled block */

/* ---- Feature rows: hairline list, not gapped chips -------------------- */
/* highlight row: brand ink instead of heavy underline */

/* comparison layout: restyle the ✓ glyph to an airy hairline check disc */

/* CTA nudge on hover (arrow-like affordance via translate) */

/* ========================================================================
   ENTRANCE ANIMATIONS (.is-in.is-in per spec + .is-visible.is-visible used by this site)
   Card-level reveal is already handled by .is-revealable.is-revealable/.is-visible; we refine it
   and add a STAGGERED reveal for the feature rows inside a revealed card.
   Gated on .is-revealable.is-revealable so no-JS / reduced-motion (JS skips .is-revealable.is-revealable) = visible.
   ======================================================================== */

/* feature rows cascade in once their card is revealed */
/* stagger between sibling rows (60ms steps, capped) */

/* ---- Mobile: single column already reflows; keep it airy -------------- */
@media (max-width: 720px) {
  .c-price-card.c-price-card { padding: 20px; }
  .c-price-card--featured.c-price-card--featured::after { right: 16px; font-size: 9px; }
  .l-price-features-cols.l-price-features-cols { grid-template-columns: 1fr; }
}

/* ========================================================================
   FIX #1 (light-theme boxy shadow leak) — placed at the very end so it
   lands AFTER styles.css:860 `[data-theme="light"] .c-price-card.c-price-card:hover`
   at EQUAL specificity (0,0,3,0) and wins by source order. Otherwise the
   base big drop shadow returns on hover in the LIGHT theme.
   ======================================================================== */

/* ---- Reduced-motion guard (belt & suspenders) ------------------------- */
@media (prefers-reduced-motion: reduce) {
  .c-price-card.c-price-card,
  .c-price-card.c-price-card.is-revealable,
  .c-price-card.c-price-card.is-revealable.is-visible,
  .c-price-card.c-price-card.is-in,
  .c-price-feature.c-price-feature,
  .c-price-card.c-price-card.is-revealable .c-price-feature.c-price-feature,
  .c-price-card.c-price-card.is-in .c-price-feature.c-price-feature {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
    animation: none !important;
  }
  .c-price-card__cta.c-price-card__cta { transition: none !important; }
  /* FIX #4: also neutralize the instantaneous hover transforms so nothing
     snaps under reduced motion. */
  .c-price-card.c-price-card:hover,
  .c-price-card.c-price-card:hover .c-price-card__cta.c-price-card__cta { transform: none !important; }
}


/* ---- check-list ---- */
/* ============================================================
   COMPONENT OVERRIDE — .c-check-list.c-check-list  (REV)
   Airy hairline restyle + staggered check-draw entrance.
   Appended at end of stylesheet → equal specificity wins.

   Requires (tiny, add early in <head>):
     document.documentElement.classList.add('js');
   so the entrance pre-state only applies when JS can reveal it.
   ============================================================ */

/* ---- The list: strip any list chrome, open it up ---- */

/* ---- Rows: open, hairline-separated, NO per-item boxes ----
   FIX 1: pre-state (opacity/translate) is NOT applied here — it is
   gated on html.u-js below, so without JS the list is fully visible. */

/* FIX 1 — entrance pre-state ONLY when JS is present to reveal it.
   No JS / script error / observer failure → rows stay visible. */

/* revealed state (JS IntersectionObserver adds .is-in.is-in) */

/* FIX 1 — belt-and-suspenders for engines exposing scripting: none */
@media (scripting: none){
  .c-check-list__item.c-check-list__item{
    opacity: 1 !important;
    transform: none !important;
  }
}

/* Staggered reveal — 60ms steps between siblings */

/* FIX 4 — hover now warms the text with a DISTINCT token, so the
   color .2s transition actually has somewhere to go. */

/* ---- The check glyph: airy tinted disc, brand-ink mark ----
   FIX 3: position:relative anchors the fallback legs to the disc.
   FIX 6: removed inert `flex: 0 0 auto` (this is a grid item). */

/* If the icon ships an inline <svg>, keep it crisp + currentColor */

/* --- CHECK-DRAW: animate an inline SVG check path on reveal ---
   FIX 5: length-independent draw. Author the SVG check path with
   pathLength="1"; the dash length then maps to the normalized path,
   so any glyph hides/draws exactly regardless of its real length. */

/* --- Fallback CHECK-DRAW for icons WITHOUT an inline svg ---
   Draw a tick with two pseudo-element strokes so the glyph still
   animates. Guarded by :empty so it never doubles a real SVG.
   FIX 3: placement via explicit top/left offsets (anchored to the
   now-positioned disc) instead of fragile margin nudges. */
/* short leg (bottom-left → vertex) */
/* long leg (vertex → top-right) */

@keyframes cl-check-draw{
  to{ stroke-dashoffset: 0; }
}
/* each leg keeps its own angle while scaling in */
@keyframes cl-leg-short{
  to{ transform: rotate(45deg) scaleX(1); }
}
@keyframes cl-leg-long{
  to{ transform: rotate(-45deg) scaleX(1); }
}

/* ---- Contextual: check-list inside a section after the subhero.
   Slightly airier rhythm + comfortable measure in that context. ---- */

/* ---- Mobile: keep the 2-col glyph/text grid, tighten gutters ---- */

/* ---- REDUCED-MOTION GUARD ----
   FIX 2: the fallback-glyph pseudos are NOT in this blanket reset,
   so they don't get flattened to two horizontal bars. They get
   explicit drawn end-states below instead. */
@media (prefers-reduced-motion: reduce){
  .c-check-list__item.c-check-list__item,
  .c-check-list__item.c-check-list__item.is-in,
  .c-check-list__icon.c-check-list__icon,
  .c-check-list__icon.c-check-list__icon svg path,
  .c-check-list__icon.c-check-list__icon svg polyline,
  html.u-js .c-check-list__item.c-check-list__item,
  html.u-js .c-check-list__item.c-check-list__item.is-in,
  html.u-js .c-check-list__item.c-check-list__item.is-in .c-check-list__icon.c-check-list__icon svg path,
  html.u-js .c-check-list__item.c-check-list__item.is-in .c-check-list__icon.c-check-list__icon svg polyline{
    opacity: 1 !important;
    transform: none !important;
    animation: none !important;
    transition: none !important;
    stroke-dashoffset: 0 !important;
  }

  /* FIX 2 — draw the fallback tick fully, keeping each leg's angle. */
  .c-check-list__icon.c-check-list__icon:empty::before{
    transform: rotate(45deg) scaleX(1) !important;
    animation: none !important;
    transition: none !important;
    opacity: 1 !important;
  }
  .c-check-list__icon.c-check-list__icon:empty::after{
    transform: rotate(-45deg) scaleX(1) !important;
    animation: none !important;
    transition: none !important;
    opacity: 1 !important;
  }
}


/* ---- stats ---- */
/* ============================================================
   STATS — airy override (Stripe / épuré / aéré)  [REVISED]
   Kills the bordered boxes. Big mono figures, hairline
   vertical separators, mono uppercase labels, staggered
   .is-in.is-in entrance + subtle hover, reduced-motion guarded.
   ============================================================ */

/* --- Container: open grid row, no card, no borders ---
   FIX #3: commit to a fixed 4-col desktop grid so wrapping is
   deterministic. auto-fit left a stray leading hairline on the
   first item of every wrapped row (only global :first-child was
   cleared). A fixed count keeps the single-row assumption true,
   so the :first-child border reset is always correct. --- */

/* --- Item: strip the box, add left hairline separator --- */
/* first item in each row has no leading rule (clean left edge) *//* --- The big figure: mono,
tabular,
tight tracking --- *//* --- The label: mono eyebrow,
uppercase,
faint --- */

/* --- Contextual variant: stats inside a section that follows
       the subhero — a touch more breathing room + top/bottom
       hairline framing the whole band (open, not boxed). --- */

/* ============================================================
   ANIMATION — staggered .is-in.is-in entrance
   ============================================================ */
/* stagger siblings by 70ms steps */

/* Fallback: if the observer never fires (no JS on the container),
   reveal after a short delay so figures are never stuck hidden. */
@keyframes stats-safety{ to{ opacity:1; transform:none; } }

/* --- Hover micro-interaction: subtle lift + accent tint on the
       figure, and the separating hairline warms to brand.
   FIX #2: do NOT re-declare the base .c-stats__item.c-stats__item transition here
   (it silently shortened the entrance slide to .25s while opacity
   stayed .6s, desyncing the desktop entrance). Instead keep the
   base .6s transform for entrance and scope the SNAPPY duration to
   the hover state only. --- */
@media (hover:hover){
  .c-stats__item.c-stats__item.is-in:hover{
    transform:translateY(-3px);
    transition:transform .25s var(--motion-easing-standard);
  }
  .c-stats__item.c-stats__item:hover{ border-left-color:var(--brand-t2); }
  .c-stats__item.c-stats__item:hover > :first-child,
  .c-stats__item.c-stats__item:hover strong,
  .c-stats__item.c-stats__item:hover b{
    color:var(--brand);
    transition:color .2s var(--motion-easing-standard);
  }
}

/* --- Underline sheen sweeping under the figure on entrance,
       drawing the eye to the number.
   FIX #1: animate transform:scaleX (compositor-only) instead of
   width (paint-bound / janky). Base is the full 28px width scaled
   to 0 from the left, so the reveal is a pure GPU transform. --- */

/* ============================================================
   RESPONSIVE — reflow cleanly on mobile
   ============================================================ */
@media (max-width:640px){
  /* FIX #4: the underline's left offset must track the reduced
     padding, otherwise it no longer aligns to the figure's left
     edge at this breakpoint. */
  /* when items wrap onto a new row, the "first-child" rule no
     longer covers the left column of subsequent rows; restore
     the clean left edge for odd items in the 2-col layout. */
}
@media (max-width:400px){
  .c-stats.c-stats{ grid-template-columns:1fr; }  /* single column */
  .c-stats__item.c-stats__item{
    border-left:0 !important;
    border-top:1px solid var(--line);
    padding-top:var(--space-5,1.25rem);
  }
  .c-stats__item.c-stats__item:first-child{ border-top:0; }
  /* keep the sheen flush with the figure at this padding too */
  .c-stats__item.c-stats__item::after{ left:var(--space-4,1rem); }
}

/* ============================================================
   REDUCED MOTION GUARD
   ============================================================ */
@media (prefers-reduced-motion:reduce){
  .c-stats__item.c-stats__item,
  .c-stats__item.c-stats__item.is-in,
  .c-stats__item.c-stats__item::after,
  .c-stats.c-stats:not(.is-in.is-in) .c-stats__item.c-stats__item{
    opacity:1 !important;
    transform:none !important;
    animation:none !important;
    transition:none !important;
  }
  /* FIX #1: base width:28px + transform:none yields the full
     static underline (no scaleX needed). */
  .c-stats__item.c-stats__item::after{ transform:none !important; }
}


/* ---- faq ---- */
/* =========================================================================
   FAQ — accordéon aéré (DA unique) — SOURCE UNIQUE
   Remplace et absorbe les 5 couches empilées : styles.css §FAQ historique,
   la part FAQ du @media 1100px, `.c-faq__question` du groupe de titres, le bloc
   `.prose-faq*` (mort : aucun des 26 HTML ne l'utilise) et l'ancien §7c
   (qui doublait le padding : 24px sur .c-faq__item.c-faq__item + 20px sur .c-faq__question.c-faq__question = 44px).
   Aucune autre règle .c-faq.c-faq ne doit être écrite ailleurs.

   Hooks JS préservés : .c-faq__question.c-faq__question (role=button, tabindex, aria-expanded),
   .is-open.is-open sur .c-faq__item.c-faq__item, .is-in.is-in (observer de cascade).
   Sans JS (html sans .u-js) : tout reste ouvert, visible et lisible.
   ========================================================================= */

/* ---------- Section : pas de gouttière en plus, pas de fond ---------- */

/* ---------- Grille : intro ferrée à gauche + colonne de questions ---------- */

/* ---------- Colonne intro ---------- */

/* Lien de contact : lien fléché mono discret, pas un 2e accent plein.
   `.faq__link` = markup cible ; `.c-btn` = compat avec le HTML actuel. */

/* ---------- Liste : UN filet par ligne, gap 0 (plus de trait flottant) ---------- */
/* Le dernier item ne ferme pas la liste : le filet de la section suivante
   (§6a) ou celui du footer joue ce rôle — sinon deux traits à 24px. */

/* ---------- Question (élément cliquable équipé par le JS) ---------- */

/* Indicateur + → × : deux filets 1px, rotation 45°, jamais affiché sans JS */

/* ---------- Réponse ---------- */
/* Ouverture en CSS PUR : height 0 → auto. Le JS ne fait plus que basculer
   `.is-open`. Fini l'animation de hauteur pilotée en JS qui relayoutait toute
   la page à chaque frame (saccade sur Safari quand le contenu du dessous bouge).
   `interpolate-size: allow-keywords` fait animer 0→auto là où c'est supporté
   (Chrome 129+) ; ailleurs (Safari/Firefox) l'ouverture est instantanée — donc
   AUCUNE frame à saccader. Simple et increvable. */
.u-js .c-faq__answer-wrap.c-faq__answer-wrap {
  overflow: hidden;
  height: 0;
  interpolate-size: allow-keywords;
  transition: height 0.32s var(--motion-easing-standard);
}
.u-js .c-faq__item.c-faq__item.is-open .c-faq__answer-wrap.c-faq__answer-wrap { height: auto; }
/* Fondu du contenu : `opacity` est composité (GPU), il ne déclenche aucun
   layout et ne peut donc JAMAIS saccader. Il donne une ouverture douce même sur
   Safari, où la hauteur, elle, s'ouvre instantanément. */
/* Padding CONSTANT : il fait partie de la hauteur mesurée et le conteneur le
   clippe quand il est fermé. Aucune animation d'opacité ni de padding superposée
   à la hauteur → une seule et unique animation, nette partout (le double
   mouvement désynchronisé était rendu comme un scintillement par Safari). */

/* ---------- Reveal (.is-in.is-in posé par le JS) ----------
   UN SEUL système : l'observer `.is-in`. `.c-faq__item` a été retiré de la
   liste `revealTargets` du script (qui posait `.is-revealable` + un
   `style.transitionDelay` INLINE — un style inline bat toute feuille, ces
   délais-ci n'auraient jamais servi). Gated sous `.u-js` : sans JS, rien ne
   peut rester invisible. */

@media (prefers-reduced-motion: reduce) {
  .u-js .c-faq__item.c-faq__item { opacity: 1; transform: none; transition: none; }
  .c-faq__question.c-faq__question::after, .c-faq__answer.c-faq__answer { transition: none; }
}

/* ---------- Mobile ----------
   1024px et non 860 : à 900px de viewport la colonne intro tombait à ~330px
   pour un h2 en clamp(26px,3.4vw,38px). Aligné sur le reste du site. */
@media (max-width: 1024px) {
  .c-faq__inner.c-faq__inner { grid-template-columns: 1fr; row-gap: var(--sp-6); }
  .c-faq__intro.c-faq__intro { position: static; max-width: 46ch; }
  .c-faq__question.c-faq__question { gap: var(--sp-4); padding-block: 20px; }
}

/* ---- cta banner ---- */
/* =========================================================
   CTA BANNER — override "airy / Stripe" + entrance animations
   Re-declares existing selectors (appended = wins at equal
   specificity). Open, centered, hairline; a soft brand bloom
   replaces the hard tinted/bordered box. Dark + light safe.
   ========================================================= */

/* Section: positioning context for the bloom + air.
   FIX 1: overflow:clip contains the @keyframes cta-bloom
   scale(1.04) so the inset:0 pseudo can't push ~2% past the
   edges and spawn a horizontal scrollbar on mobile. */

/* Soft radial brand bloom — subtler, wider, no hard edge/box.
   Uses brand tint so it reads in both themes. */

/* Inner: open layout, generous max width, no shadow anywhere */

/* Banner variant: centered, airy, NO boxy card.
   At most a hairline top rule + whitespace to anchor it. */

/* Title: 700, tight tracking, accent word carries the one blue */
.c-cta__title.c-cta__title .u-accent{
  color: var(--brand, var(--color-primary));
}
/* .u-highlight reste un marqueur (texte blanc sur fond bleu) — ne pas recolorer le texte */

/* Text: secondary tone, comfortable measure, centered in banner */

/* Actions: keep pill buttons, center, add a touch of top air */

/* Button hover micro-interaction (subtle lift, no layout shift).
   FIX 3: every var(--motion-easing-standard) carries an `ease` fallback so an
   undefined token can't invalidate the shorthand. */

/* ---------- ENTRANCE (.is-in.is-in cascade: title → text → buttons) ---------- */
/* Land state is the natural resting state (always defined so the
   content is visible by default). The pre-state below is gated so
   it only hides items when JS is present to reveal them again. */

/* Pre-state: only apply the hidden start when JS can add .is-in.is-in.
   FIX 2a: gate behind a `.u-js` root class so if the bootstrap
   script never ran, the pre-state is never applied and content
   stays visible. (Set html.u-js as early as possible in <head>.) */

/* Land when the CTA (or its inner) receives .is-in.is-in */
/* Fallback: also honour .is-in.is-in placed directly on each item */

/* FIX 2b: belt-and-braces — if scripting is entirely unavailable,
   force the content visible regardless of any .u-js gating. */
@media (scripting: none){
  .c-cta__title.c-cta__title,
  .c-cta__text.c-cta__text,
  .c-cta__actions.c-cta__actions,
  .u-js .c-cta__title.c-cta__title,
  .u-js .c-cta__text.c-cta__text,
  .u-js .c-cta__actions.c-cta__actions{
    opacity:1;
    transform:none;
  }
}

/* Stagger the cascade (110ms steps) */

/* Bloom breathes gently once revealed (optional keyframe).
   Scale kept but now safely clipped by .l-section.l-section.c-cta overflow. */
@keyframes cta-bloom{
  0%,100%{ opacity:.72; transform:scale(1); }
  50%{ opacity:1; transform:scale(1.04); }
}
/* FIX 3: var(--motion-easing-standard) fallback on the bloom animation too. */

/* ---------- MOBILE REFLOW ---------- */

/* ---------- REDUCED-MOTION GUARD ---------- */
@media (prefers-reduced-motion: reduce){
  .c-cta__title.c-cta__title,.c-cta__text.c-cta__text,.c-cta__actions.c-cta__actions,
  .u-js .c-cta__title.c-cta__title,.u-js .c-cta__text.c-cta__text,.u-js .c-cta__actions.c-cta__actions,
  .c-cta__title.c-cta__title.is-in,.c-cta__text.c-cta__text.is-in,.c-cta__actions.c-cta__actions.is-in,
  .l-section.l-section.c-cta.is-in .c-cta__title.c-cta__title,
  .l-section.l-section.c-cta.is-in .c-cta__text.c-cta__text,
  .l-section.l-section.c-cta.is-in .c-cta__actions.c-cta__actions,
  .c-cta__inner--banner.c-cta__inner--banner.is-in .c-cta__title.c-cta__title,
  .c-cta__inner--banner.c-cta__inner--banner.is-in .c-cta__text.c-cta__text,
  .c-cta__inner--banner.c-cta__inner--banner.is-in .c-cta__actions.c-cta__actions{
    opacity:1!important;
    transform:none!important;
    animation:none!important;
    transition:none!important;
  }
  .l-section.l-section.c-cta.is-in::before{ animation:none!important; }
  .c-cta__actions.c-cta__actions .c-btn.c-btn{ transition:none!important; }
}

/* STAGGER d'entrée — FIX 2 : scopé à .is-revealable.is-revealable pour ne PAS retarder la
   transition de hover (transform de la carte). Ne touche donc que l'entrée. */

/* ============================ REFLOW MOBILE ============================ */
@media (max-width: 1024px) {
}

/* ============================ REDUCED MOTION ============================ */
@media (prefers-reduced-motion: reduce) {
}


/* ============ ANIMATIONS PAR BLOC ============ */


/* ---- bx-prix ---- */
/* ============================================================
   bx-prix — animations (appended; animates existing elements only)
   Ambient (always-on) + on-view builds (.is-in.is-in) + hover micro-interactions
   ============================================================ */

/* ---------- keyframes ---------- */
@keyframes bxp-rise   { from{ opacity:0; transform:translateY(14px) } to{ opacity:1; transform:none } }
@keyframes bxp-up     { from{ opacity:0; transform:translateY(10px) } to{ opacity:1; transform:none } }
@keyframes bxp-in-l   { from{ opacity:0; transform:translateX(-12px) } to{ opacity:1; transform:none } }
@keyframes bxp-pop    { from{ opacity:0; transform:scale(.96) } to{ opacity:1; transform:none } }
@keyframes bxp-zone   { from{ transform:scaleX(0) } to{ transform:scaleX(1) } }
@keyframes bxp-linex  { from{ transform:scaleX(0) } to{ transform:scaleX(1) } }
@keyframes bxp-draw   { from{ stroke-dashoffset:var(--bxp-dash,30) } to{ stroke-dashoffset:0 } }
/* ambient */
@keyframes bxp-sheen  { 0%{ background-position:200% 0 } 100%{ background-position:-120% 0 } }
@keyframes bxp-pulse  { 0%,100%{ transform:scale(1); box-shadow:0 0 0 0 color-mix(in srgb,var(--brand) 45%,transparent) }
                        50%    { transform:scale(1.18); box-shadow:0 0 0 4px color-mix(in srgb,var(--brand) 0%,transparent) } }
@keyframes bxp-breathe{ 0%,100%{ box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--brand) 22%,transparent) }
                        50%    { box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--brand) 42%,transparent) } }
@keyframes bxp-badge  { 0%,100%{ opacity:.72 } 50%{ opacity:1 } }
@keyframes bxp-cursor { 0%{ transform:translateX(-30%) } 100%{ transform:translateX(430%) } }

/* ============================================================
   AMBIENT — always-on, subtle, infinite (no JS)
   ============================================================ */

/* budget track: a slow light "cursor" sweeps the whole rail, like a value being scanned */

/* the brand "sur-mesure" dot breathes/pulses like a live status */

/* highlighted "Recommandé" column: a soft brand sheen drifts down the whole column */
/* the "Recommandé" badge itself softly pulses */

/* recurring-fees total: a gentle breathing brand hairline glow */

/* ============================================================
   ON-VIEW BUILD — plays once when block / sub-section scrolls in
   root .c-prix.c-prix.is-in  +  each .c-prix__part.c-prix__part.is-in
   ============================================================ */

/* --- header (root) --- */

/* --- every part: kick / h3 / sub lead in --- */

/* --- 01 · budget SCALE: segments fill in from left, staggered like a gauge --- */
/* segment labels + numeric marks fade up after the fill */

/* --- 01 · TIER columns stagger up --- */

/* --- 01 · six FACTORS: hairline top draws, text fades, staggered --- */

/* --- 02 · MATRIX rows slide/stagger in --- */
/* matrix mark icons draw themselves (check / dash / cross) */

/* --- 03 · CHECKLIST: rows stagger + checkmarks draw --- */

/* --- 03 · RECURRING FEES: rows stagger, dotted leaders draw across --- */
/* total pops in */

/* ============================================================
   HOVER — micro-interactions (.2s)
   ============================================================ */

/* ============================================================
   REDUCED MOTION — hard stop, nothing left hidden or mid-animation
   ============================================================ */
@media (prefers-reduced-motion: reduce){
  .c-prix.c-prix *{ animation:none!important; transition:none!important }
  .c-prix.c-prix [style], .c-prix.c-prix *{ opacity:1!important; transform:none!important }
  .c-prix.c-prix .c-prix__zone.c-prix__zone,
  .c-prix.c-prix .c-prix__lead.c-prix__lead,
  .c-prix.c-prix .c-prix__factor.c-prix__factor::after{ transform:none!important }
  .c-prix.c-prix svg path{ stroke-dashoffset:0!important }
  .c-prix.c-prix .c-prix__track.c-prix__track::after{ display:none!important }
}


/* ---- bx-refonte ---- */
/* =====================================================================
   bx-refonte — animations (append-only, animates existing elements)
   Meaning: avant/après browser mockups, a connecting arrow, delta stats,
   severity signal rows, and a lossless 301 SEO-migration flow.
   ===================================================================== */

/* ---------- AMBIENT (always-on, subtle, no JS) ---------------------- */

/* The "Après" mockup gently floats — feels live, modern, alive */
@keyframes bxrf-float{0%,100%{transform:translateY(0)}50%{transform:translateY(-4px)}}

/* Premium sheen sweeping the brand pill in the redesigned mockup */
@keyframes bxrf-sheen{0%,55%{transform:translateX(-130%)}100%{transform:translateX(130%)}}

/* Breathing glow on the "301" migration badge (set here; re-declared on-view) */
@keyframes bxrf-glow{0%,100%{box-shadow:0 0 0 0 transparent}
  50%{box-shadow:0 0 12px color-mix(in srgb,var(--brand) 42%,transparent)}}

/* Slow shimmer travelling along the eyebrow hairline */
@keyframes bxrf-line{0%,100%{opacity:.5}50%{opacity:1}}

/* ---------- ON-VIEW BUILD · 01 AVANT / APRÈS ----------------------- */

/* Browser chrome assembles: bar drops in, then view pieces stagger */

@keyframes bxrf-bar{from{opacity:0;transform:translateY(-8px)}to{opacity:1;transform:none}}
@keyframes bxrf-piece{from{opacity:0;transform:translateY(10px) scale(.98)}to{opacity:1;transform:none}}

/* Connecting arrow draws itself, shaft then head */
@keyframes bxrf-draw{to{stroke-dashoffset:0}}
/* …then keeps a subtle forward nudge, hinting the migration direction */
@keyframes bxrf-nudge{0%,100%{transform:translateX(0)}50%{transform:translateX(3px)}}

/* Delta stat cards rise and stagger (values count up via JS) */
@keyframes bxrf-rise{from{opacity:0;transform:translateY(14px)}to{opacity:1;transform:none}}

/* ---------- ON-VIEW BUILD · 02 SIGNAUX ----------------------------- */

/* Signal rows slide + stagger in */
@keyframes bxrf-rowin{from{opacity:0;transform:translateX(-14px)}to{opacity:1;transform:none}}

/* Severity dots pop; critical (hi) dots then pulse a warning ring */
@keyframes bxrf-pop{from{transform:scale(0)}60%{transform:scale(1.25)}to{transform:scale(1)}}
@keyframes bxrf-dot{0%,100%{box-shadow:0 0 0 0 color-mix(in srgb,var(--danger) 55%,transparent)}
  70%,100%{box-shadow:0 0 0 7px color-mix(in srgb,var(--danger) 0%,transparent)}}

/* ---------- ON-VIEW BUILD · SEO 301 FLOW --------------------------- */
/* (.c-refonte-seo.c-refonte-seo is not a *-sub, so keyed to the block root .is-in.is-in) */
@keyframes bxrf-flowin{from{opacity:0;transform:translateX(-10px)}to{opacity:1;transform:none}}
/* 301 badge: builds in, then resumes its ambient breathing glow */

/* ---------- HOVER micro-interactions ------------------------------- */

/* Mockups lift softly on hover */

/* Signal rows tint + nudge on hover */

/* Delta cards subtly warm on hover */

/* ---------- REDUCED MOTION GUARD ----------------------------------- */
@media (prefers-reduced-motion: reduce){
  .c-refonte.c-refonte *{animation:none!important;transition:none!important}
  .c-refonte.c-refonte [style],.c-refonte.c-refonte *{opacity:1!important;transform:none!important}
  .c-refonte.c-refonte .c-refonte__arrow.c-refonte__arrow svg path{stroke-dashoffset:0!important}
  .c-refonte.c-refonte .c-refonte__rows.c-refonte__rows .c-refonte__sev.c-refonte__sev{transform:none!important}
  .c-refonte.c-refonte .c-refonte__new.c-refonte__new .c-refonte__pill.c-refonte__pill::after{display:none!important}
}


/* ---- bx-compare ---- */
/* ============================================================
   bx-compare — animations (appended; animate-only, no relayout)
   Meaning: a "vitrine OU e-commerce" arbitration table.
   The "ou" pill is the fulcrum → it breathes. Rows build in
   like a ledger being written, checkmarks draw, figures settle,
   arrows lead the eye toward each verdict.
   ============================================================ */

/* --- keyframes --- */
@keyframes bxc-rise{from{opacity:0;transform:translateY(14px)}to{opacity:1;transform:none}}
@keyframes bxc-rise-sm{from{opacity:0;transform:translateY(9px)}to{opacity:1;transform:none}}
@keyframes bxc-fade{from{opacity:0}to{opacity:1}}
@keyframes bxc-row-in{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:none}}
@keyframes bxc-col-in{from{opacity:0;transform:translateX(10px)}to{opacity:1;transform:none}}
@keyframes bxc-draw{to{stroke-dashoffset:0}}
@keyframes bxc-fig-in{from{opacity:0;transform:translateY(5px)}to{opacity:1;transform:none}}
/* eyebrow hairline grows out from the text */
@keyframes bxc-line-grow{from{opacity:0;transform:scaleX(0)}to{opacity:.55;transform:scaleX(1)}}
/* ambient: the "ou" fulcrum breathes, softly weighing both sides */
@keyframes bxc-ou-breathe{
  0%,100%{transform:translate(-50%,-50%) scale(1);border-color:var(--line);box-shadow:0 0 0 0 var(--brand-t)}
  50%{transform:translate(-50%,-50%) scale(1.06);border-color:var(--brand-t2);box-shadow:0 0 0 4px transparent}
}
/* ambient: mobile "ou" cue breathes on compositor-safe props only
   (transform+opacity) — mirrors the desktop fulcrum; no layout thrash */
@keyframes bxc-oum-breathe{
  0%,100%{opacity:.8;transform:scale(1)}
  50%{opacity:1;transform:scale(1.04)}
}
/* ambient: featured "yes" ticks keep a faint alive glow */
@keyframes bxc-yes-pulse{
  0%,100%{opacity:.85}
  50%{opacity:1;filter:drop-shadow(0 0 3px var(--brand-t))}
}
/* ambient: arrows in the decision list drift forward, inviting */
@keyframes bxc-arrow-drift{
  0%,100%{transform:translateX(0)}
  50%{transform:translateX(3px)}
}

/* ===== HEADER build (root section) ===== */

/* ===== SUB-SECTION build (each .c-compare__sec.c-compare__sec.is-in) ===== */

/* ---- Ledger: header columns slide in from the divide ---- */
/* the "ou" pill drops in last, then hands off to its ambient breathe */

/* ---- Ledger rows: staggered ledger-writing build ---- */

/* ---- Checkmarks draw themselves in, then keep a faint pulse ---- */
/* the "aucun/non" dashes fade up gently */

/* ---- Figures (budget / délai) settle in after their row ---- */

/* ---- Decision rows: stagger in, arrows draw + ambient drift ---- */

/* ---- Hybrid note: icon draws (padlock), text fades ---- */

/* ---- Mobile "ou" cue: ambient breathe (no desktop grid cell) ---- */

/* ===== HOVER micro-interactions ===== */

/* ===== reduced motion ===== */
@media (prefers-reduced-motion: reduce){
  .c-compare.c-compare *{animation:none!important;transition:none!important}
  .c-compare.c-compare [style],.c-compare.c-compare *{opacity:1!important;transform:none!important}
  .c-compare.c-compare .c-compare__yes.c-compare__yes path,
  .c-compare.c-compare .c-compare__answer.c-compare__answer svg path,
  .c-compare.c-compare .c-compare__hybrid.c-compare__hybrid path{stroke-dashoffset:0!important}
  .c-compare.c-compare .c-compare__eyebrow.c-compare__eyebrow::before{opacity:.55!important}
}


/* ---- bx-seo ---- */
/* ============================================================
   bx-seo — animations (append-only; animates existing elements)
   Block meaning: a faux Google local result (browser chrome,
   listing w/ stars+score, map w/ roads+pin) + a 3-lever ledger
   with metrics + a NAP coherence checkmark.
   Triggers: AMBIENT (always-on) + ON-VIEW BUILD (.is-in.is-in on root
   .c-seo.c-seo and hairline sub .c-seo__sub.c-seo__sub) + HOVER micro-interactions.
   --- REVISION: ambient twinkle + dotpulse now survive the build
   (they were permanently shadowed by the .is-in.is-in `pop` rules while
   `.is-in` stays on the root). Both loops are re-chained onto the
   build rules so they hand off cleanly after the pop completes.
   ============================================================ */

/* ---------- keyframes ---------- */
@keyframes bx-seo-rise{from{opacity:0;transform:translateY(14px)}to{opacity:1;transform:none}}
@keyframes bx-seo-pop{from{opacity:0;transform:scale(.6)}60%{opacity:1;transform:scale(1.06)}to{opacity:1;transform:scale(1)}}
@keyframes bx-seo-ui-in{from{opacity:0;transform:translateY(18px) scale(.985)}to{opacity:1;transform:none}}
@keyframes bx-seo-bar-in{from{opacity:0;transform:translateY(-10px)}to{opacity:1;transform:none}}
@keyframes bx-seo-block-in{from{opacity:0;transform:scale(.4)}to{opacity:.35;transform:scale(1)}}
@keyframes bx-seo-draw{from{stroke-dashoffset:var(--bx-seo-len,260)}to{stroke-dashoffset:0}}
@keyframes bx-seo-pin-drop{from{opacity:0;transform:translate(-50%,-170%)}60%{opacity:1;transform:translate(-50%,-92%)}to{opacity:1;transform:translate(-50%,-100%)}}
@keyframes bx-seo-label-in{from{opacity:0;transform:translateX(-50%) translateY(6px)}to{opacity:1;transform:translateX(-50%)}}
/* ambient */
@keyframes bx-seo-bob{0%,100%{transform:translateY(0)}50%{transform:translateY(-2px)}}
@keyframes bx-seo-ping{0%{transform:translate(-50%,-50%) scale(.4);opacity:.5}70%{opacity:0}100%{transform:translate(-50%,-50%) scale(2.4);opacity:0}}
@keyframes bx-seo-twinkle{0%,100%{filter:none;opacity:1}50%{filter:brightness(1.28);opacity:.86}}
@keyframes bx-seo-sheen{0%{transform:translateX(-120%)}55%,100%{transform:translateX(220%)}}
@keyframes bx-seo-breathe{0%,100%{opacity:1}50%{opacity:.62}}
@keyframes bx-seo-dotpulse{0%,100%{opacity:.55;transform:scale(1)}50%{opacity:1;transform:scale(1.12)}}
@keyframes bx-seo-flow{to{stroke-dashoffset:-48}}

/* =========================================================
   ON-VIEW BUILD — root section (.c-seo.c-seo.is-in)
   ========================================================= */
/* intro reveal */

/* the UI object assembles piece by piece */

/* browser dots: pop in on build, THEN hand off to the ambient
   traffic-light pulse. Both animations are chained on the SAME
   rule so specificity can't strip the loop once .is-in.is-in persists.
   Matched delays: pulse starts ~after each dot's pop settles. */

/* listing rows stagger in */

/* stars pop one by one (the featured rating), THEN hand off to
   the ambient twinkle. Both chained on the same rule so the loop
   survives the persistent .is-in.is-in. Twinkle keeps its staggered feel
   by spacing each star's loop start after its pop resolves. */

/* map assembles: blocks scale, roads draw, pin drops */
/* main roads draw (horizontal + vertical = nth-of-type 1 & 2) */
/* pin lands + label fades up */

/* NAP coherence checkmark draws in */

/* =========================================================
   ON-VIEW BUILD — ledger sub-section (.c-seo__sub.c-seo__sub.is-in)
   ========================================================= */
/* rows slide/stagger in */
/* index numbers + metrics pop for emphasis */
/* tags stagger */

/* =========================================================
   AMBIENT — always-on, subtle, infinite (no JS)
   ========================================================= */
/* map pin gently bobs (svg has no base transform) + radiating ping */

/* diagonal road = a live "route": flowing dashes */

/* the featured rating: stars quietly twinkle (staggered) — fallback
   for the pre-build state; after .is-in.is-in the chained loop above owns it */

/* "Ouvert" status softly breathes like a live indicator */

/* browser dots: slow sequential pulse — pre-build fallback;
   after .is-in.is-in the chained loop above owns it */

/* primary "Itinéraire" button: slow premium sheen sweep
   (lengthened for a calmer cadence alongside the resumed loops) */

/* slow gradient sweep across the browser chrome bar (lengthened) */

/* =========================================================
   HOVER — micro-interactions (.2s var(--motion-easing-standard))
   ========================================================= */

/* =========================================================
   REDUCED-MOTION GUARD — nothing left mid-animation/invisible
   (re-assert pin/pinlabel base transforms so they stay placed)
   ========================================================= */
@media (prefers-reduced-motion: reduce){
  .c-seo.c-seo *{animation:none!important;transition:none!important}
  .c-seo.c-seo *{opacity:1!important;transform:none!important}
  .c-seo.c-seo .c-seo__map-block.c-seo__map-block{opacity:.35!important}
  .c-seo.c-seo .c-seo__map-road.c-seo__map-road{stroke-dasharray:none!important;stroke-dashoffset:0!important}
  .c-seo.c-seo .c-seo__nap.c-seo__nap svg path{stroke-dasharray:none!important;stroke-dashoffset:0!important}
  .c-seo.c-seo .c-seo__pin.c-seo__pin{transform:translate(-50%,-100%)!important}
  .c-seo.c-seo .c-seo__pin-label.c-seo__pin-label{transform:translateX(-50%)!important}
  .c-seo.c-seo .c-seo__btn--primary.c-seo__btn--primary::after,.c-seo.c-seo .c-seo__ui-bar.c-seo__ui-bar::after,.c-seo.c-seo .c-seo__pin.c-seo__pin::after{display:none!important}
}


/* ---- bx-mobile ---- */
/* ===================================================================
   bx-mobile — animations (append-only, animates existing elements)
   Meaning: "mobile-first" — a desktop mockup + phone preview assemble,
   touch-target figures count & draw, X-pitfalls draw, method rows stagger.
   =================================================================== */

/* ---------- AMBIENT (always-on, subtle, no JS) ---------- */

/* Browser chrome "traffic-light" dots breathe like a live tab */
@keyframes bx-mobile-dotpulse{
  0%,100%{ opacity:.55 }
  50%    { opacity:1 }
}

/* The phone preview gently floats — feels held in the hand */
@keyframes bx-mobile-float{
  0%,100%{ transform:translateY(0) }
  50%    { transform:translateY(-6px) }
}

/* Featured CTA inside the phone: soft breathing brand glow (the "recommandé" beat) */
@keyframes bx-mobile-ctaglow{
  0%,100%{ box-shadow:0 0 0 0 var(--brand-t) }
  50%    { box-shadow:0 0 0 3px var(--brand-t) }
}

/* Slow sheen sweeping the eyebrow hairline — quiet sign of life */
@keyframes bx-mobile-sheen{
  0%  { background-position:-140% 0 }
  100%{ background-position:140% 0 }
}

/* ---------- ON-VIEW BUILD (plays once, gated on .is-in.is-in) ---------- */

/* Reusable keyframes */
@keyframes bx-mobile-rise{ from{ opacity:0; transform:translateY(14px) } to{ opacity:1; transform:none } }
@keyframes bx-mobile-fillx{ from{ transform:scaleX(0) } to{ transform:scaleX(1) } }
@keyframes bx-mobile-pop{ from{ opacity:0; transform:scale(.94) translateY(10px) } to{ opacity:1; transform:none } }
@keyframes bx-mobile-drawline{ from{ transform:scaleX(0) } to{ transform:scaleX(1) } }
@keyframes bx-mobile-drawcheck{ to{ stroke-dashoffset:0 } }

/* Header intro (root section) */

/* Sub-section kicker/head intro */

/* --- Desktop browser mockup assembles piece by piece --- */
/* chrome bar slides down first */
/* content bars "fill" from the left like a skeleton drawing in */

/* --- Phone preview assembles after the desktop, its own rows fill --- */

/* --- Touch-target notes: stagger in, and their leading hairline "draws" --- */

/* --- Pitfalls (X) & method (numbers): staggered rows --- */

/* The X strokes draw themselves (stroke-dashoffset) */

/* Method numbers tick to brand as they land */
@keyframes bx-mobile-numin{ from{ opacity:0; transform:translateX(-6px) } to{ opacity:1; transform:none } }

/* ---------- HOVER micro-interactions ---------- */
/* Whole desk lifts on hover — invites inspection */

/* ---------- REDUCED-MOTION GUARD ---------- */
@media (prefers-reduced-motion: reduce){
  .c-mobile.c-mobile *{ animation:none!important; transition:none!important }
  .c-mobile.c-mobile [style], .c-mobile.c-mobile *{ opacity:1!important; transform:none!important }
  /* ensure drawn/filled elements rest in their final state */
  .c-mobile.c-mobile .c-mobile__cross.c-mobile__cross path{ stroke-dashoffset:0!important }
  .c-mobile.c-mobile .c-mobile__block.c-mobile__block,
  .c-mobile.c-mobile .c-mobile__col.c-mobile__col span,
  .c-mobile.c-mobile .c-mobile__phone-body.c-mobile__phone-body > *,
  .c-mobile.c-mobile .c-mobile__figure.c-mobile__figure::before{ transform:none!important }
}


/* ---- bx-methode ---- */
/* ==========================================================================
   bx-methode — animations (appended; animates existing elements only)
   Meaning: a linear 4-step method (spine + nodes) → phase cards → delay bars.
   Ambient touches + on-view builds + hover. GPU-friendly. RM-gated at end.
   Trigger: JS adds .is-in.is-in to .c-methode.c-methode (root) when it scrolls into view.
   ========================================================================== */

/* ---- keyframes ---------------------------------------------------------- */
@keyframes bxm-rise{from{opacity:0;transform:translateY(14px)}to{opacity:1;transform:none}}
@keyframes bxm-line{from{transform:scaleX(0)}to{transform:scaleX(1)}}
@keyframes bxm-rail-draw{from{transform:scaleX(0)}to{transform:scaleX(1)}}
@keyframes bxm-node-pop{0%{opacity:0;transform:scale(0)}70%{transform:scale(1.35)}100%{opacity:1;transform:scale(1)}}
@keyframes bxm-tag-in{from{opacity:0;transform:translateX(-8px)}to{opacity:1;transform:none}}
@keyframes bxm-fill-grow{from{transform:scaleX(0)}to{transform:scaleX(1)}}

/* ambient */
@keyframes bxm-rail-sheen{0%{background-position:-30% 0}100%{background-position:130% 0}}
@keyframes bxm-node-pulse{0%,100%{box-shadow:0 0 0 4px var(--brand-t2)}50%{box-shadow:0 0 0 7px transparent}}
@keyframes bxm-breathe{0%,100%{transform:scale(1);opacity:.9}50%{transform:scale(1.09);opacity:1}}
@keyframes bxm-fill-sheen{0%{background-position:-40% 0}100%{background-position:140% 0}}

/* ---- AMBIENT (always-on, subtle, infinite) ----------------------------- */
/* Slow light traveling along the process spine — expresses the linear flow */
/* Current-step node breathes (living "you are here" pin) */
/* Single interlocutor icon gently breathes */
/* Recommended "one-page" bar carries a soft brand sheen */

/* ---- ON-VIEW BUILD (plays once when block scrolls in) ------------------- */
/* Header assembles */

/* Spine draws left→right, then nodes pop in sequence */
/* current node: pop in, then hand off to the ambient breathe */

/* Phase cards stagger up */
/* Tag rows slide in within each phase (secondary life) */

/* Timeline: kicker/title rise, rows slide, tracks fill from 0 → their width */
/* recommended bar: grow, then resume its ambient sheen */

/* ---- HOVER micro-interactions ------------------------------------------ */

/* ---- reduced motion: nothing left hidden or mid-animation --------------- */
@media (prefers-reduced-motion: reduce){
  .c-methode.c-methode *{animation:none!important;transition:none!important}
  .c-methode.c-methode [style], .c-methode.c-methode *{opacity:1!important;transform:none!important}
}


/* ---- bx-erreurs ---- */
/* ============================================================
   bx-erreurs — animations (diagnostic ledger)
   Meaning: a register of 7 site errors + their corrections.
   Motion vocabulary: pulsing status dots (err = alert, fix = healthy),
   a hairline that draws, ledger rows that "post in" like entries
   being written, and the correction column sliding off its divider.
   Only transform / opacity / filter — no relayout.
   ============================================================ */

/* ---------- AMBIENT (always-on, subtle, infinite) ---------- */

/* Error status dots: a slow diagnostic pulse (like a warning blip).
   Tiny amplitude, long period so it feels alive, not busy. */
@keyframes bx-erreurs-pulse-err{
  0%,100%{ box-shadow:0 0 0 0 var(--danger); filter:none; opacity:1 }
  50%    { box-shadow:0 0 0 3px color-mix(in srgb,var(--danger) 0%,transparent); filter:brightness(1.15); opacity:.82 }
}

/* Correction dots: a calmer "healthy" breathing glow, offset in phase
   so the err/fix pair reads as problem vs. resolved. */
@keyframes bx-erreurs-breathe-fix{
  0%,100%{ filter:none; opacity:.9 }
  50%    { filter:brightness(1.25) drop-shadow(0 0 4px color-mix(in srgb,var(--brand) 55%,transparent)); opacity:1 }
}

/* ---------- ON-VIEW BUILD (plays once when block scrolls in) ---------- */

/* Initial pre-entry states (only meaningful once .is-in.is-in wires the reveal;
   reduced-motion guard below restores everything to visible). */

/* Eyebrow hairline draws out like a pen stroke opening the register. */
@keyframes bx-erreurs-draw-line{ from{ transform:scaleX(0) } to{ transform:scaleX(1) } }

/* Head: eyebrow text, title, lede rise in sequence. */
@keyframes bx-erreurs-rise{ to{ opacity:1; transform:none } }

/* Ledger container fades up as a surface for the rows to post onto. */

/* Rows "post in" one by one — like entries being written to the register. */
@keyframes bx-erreurs-row-in{
  from{ opacity:0; transform:translateY(16px) }
  to  { opacity:1; transform:none }
}

/* Mono index counts up its weight — a quick "stamp" as each row lands. */
@keyframes bx-erreurs-stamp{
  0%  { opacity:0; transform:translateX(-4px) scale(.92) }
  60% { opacity:1; transform:translateX(0) scale(1.04) }
  100%{ opacity:1; transform:none }
}

/* The correction column slides in off its divider — the "fix" arriving
   after the error is stated. Nudged from the left border, settles home. */
@keyframes bx-erreurs-fix-in{
  from{ opacity:0; transform:translateX(14px) }
  to  { opacity:1; transform:none }
}

/* Footer CTA rises in last. */

/* ---------- HOVER micro-interactions ---------- */

/* Row hover: gentle lift + the index brightens, as if that entry is
   pulled forward for review. */

/* Titles tint toward their state colour on hover of the row. */

/* Footer link: arrow-like nudge + brand tint. */

/* ---------- Reduced motion: everything visible, nothing mid-flight ---------- */
@media (prefers-reduced-motion: reduce){
  .c-erreurs.c-erreurs *{ animation:none!important; transition:none!important }
  .c-erreurs.c-erreurs [style], .c-erreurs.c-erreurs *{ opacity:1!important; transform:none!important }
  .c-erreurs__eyebrow.c-erreurs__eyebrow::before{ transform:scaleX(1)!important }
}


/* ---- bx-apropos ---- */
/* ===================================================================
   bx-apropos — animations (appended) — REVISED
   Meaning: a career timeline on a connector line, a client roster,
   big stat figures, and a grouped tooling stack.
   FIXES in this revision:
     - Hand off the two 'is-now' ambient loops on a (0,6,0) selector so
       the on-view build no longer clobbers pin-pulse / now-glow.
     - Give the timeline connector a JS-free fallback via
       @media (scripting:none) so it renders even when .is-in.is-in never lands.
   =================================================================== */

/* ---------- keyframes ---------- */
@keyframes bxa-rise-sm{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}
@keyframes bxa-slide-in{from{opacity:0;transform:translateX(-16px)}to{opacity:1;transform:translateX(0)}}
@keyframes bxa-pop{0%{opacity:0;transform:scale(.4)}60%{opacity:1;transform:scale(1.18)}100%{opacity:1;transform:scale(1)}}
@keyframes bxa-chip-in{from{opacity:0;transform:translateY(6px) scale(.94)}to{opacity:1;transform:translateY(0) scale(1)}}
@keyframes bxa-draw-x{from{transform:scaleX(0)}to{transform:scaleX(1)}}
/* ambient: light travelling along the timeline hairline */
@keyframes bxa-line-sweep{0%{background-position:200% 0}100%{background-position:-100% 0}}
/* ambient: the "aujourd'hui / is-now" pin breathing */
@keyframes bxa-pin-pulse{0%,100%{box-shadow:0 0 0 0 var(--brand-t)}55%{box-shadow:0 0 0 6px transparent}}
/* ambient: soft sheen on the eyebrow hairline */
@keyframes bxa-eyebrow-sheen{0%{background-position:200% 0}100%{background-position:-100% 0}}
/* ambient: gentle breathing on the active step title */
@keyframes bxa-now-glow{0%,100%{opacity:.85}50%{opacity:1}}

/* ---------- AMBIENT (always on, JS-free) ---------- */

/* eyebrow rule gets a slow travelling sheen */

/* timeline connector: faint light drifting along the track */

/* the "now" step pin quietly breathes, and its title glows.
   NOTE: these plain (0,3,0) ambient rules are the pre-scroll / no-build
   fallback. Once the build reveals the block, the (0,6,0) hand-off rules
   below take over (reveal-then-loop) so the ambient motion survives. */

/* ---------- ON-VIEW BUILD ---------- */

/* header (keyed to the block root) */

/* every sub kicker + h3 rises when its part scrolls in */

/* 01 · PARCOURS — connector draws left→right, dots pop, cards rise */
/* FIX 3: no-JS / no-observer fallback — restore the connector when
   scripting is unavailable so the timeline still renders without JS
   (the collapsed scaleX(0) state above is only meant to precede the
   .is-in.is-in draw). Precisely targets no-JS UAs and never misfires while
   JS is present, unlike a `.u-js` class convention we don't control. */
@media (scripting: none){
  .c-apropos__steps.c-apropos__steps::before{transform:none}
}

/* FIX 1 + 2: 'aujourd'hui' hand-off. These selectors are (0,6,0), so
   they outrank the plain (0,5,0) nth-child build rules that would
   otherwise set `animation` on the same is-now dot/title and kill the
   ambient loop after reveal. Each runs the reveal ONCE (matching the
   nth-child(3) stagger: dot .60s, title .68s) then starts the infinite
   ambient loop, delayed until the reveal has fully landed so there is a
   seamless reveal→loop hand-off with no re-trigger flash. */

/* client roster — rows stagger in from the left */

/* stat figures — rise + count up (see dataCount) */

/* 02 · STACK — tool rows stagger, chips pop in one by one */

/* ---------- HOVER micro-interactions ---------- */

/* client rows: subtle lift + tint, role nudges toward its value */

/* stat cell: figure lifts a touch on hover */

/* chips: lift + brand tint */

/* tool row: faint tint of its role label on hover */

/* ---------- reduced motion guard ---------- */
@media (prefers-reduced-motion: reduce){
  .c-apropos.c-apropos *{animation:none!important;transition:none!important}
  .c-apropos.c-apropos [style],.c-apropos.c-apropos *{opacity:1!important;transform:none!important}
  .c-apropos__steps.c-apropos__steps::before{transform:none!important}
}


/* ---- bx-vitrine ---- */
/* ============================================================
   bx-vitrine — animations (append-only, animates existing els)
   Meaning: a "spec sheet" of a vitrine site — checklist rows,
   an assembling browser + sitemap mockup with drawing connectors,
   a highlighted "choice" panel, and audience chips.
   ============================================================ */

/* ---- default rest states (only for on-view built elements) ---- */
/* Guarded so nothing hides if JS/observer never fires: only
   applied while the block is NOT yet .is-in.is-in. */

/* =============== ON-VIEW BUILD : HEADER =============== */
@keyframes bxv-up{from{opacity:0;transform:translateY(14px)}to{opacity:1;transform:none}}
@keyframes bxv-rise{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:none}}
/* eyebrow hairline draws in from the label */
@keyframes bxv-hair{from{transform:scaleX(0)}to{transform:scaleX(1)}}

/* =============== ON-VIEW BUILD : SECTION HEADINGS =============== */

/* =============== ON-VIEW BUILD : CHECKLIST ROWS =============== */
/* Rows slide + stagger in; the spec sheet fills line by line. */
@keyframes bxv-row{from{opacity:0;transform:translateX(-10px)}to{opacity:1;transform:none}}

/* Checkmark literally draws itself (stroke-dashoffset), right after its row */
@keyframes bxv-check{from{stroke-dashoffset:26}to{stroke-dashoffset:0}}
/* tags pop after their check */
@keyframes bxv-pop{from{opacity:0;transform:translateY(4px) scale(.94)}to{opacity:1;transform:none}}

/* =============== ON-VIEW BUILD : BROWSER / SITEMAP MOCKUP =============== */
/* The mockup assembles: frame settles, chrome, dots, url, then the
   sitemap tree with connector lines drawing and nodes popping in. */
@keyframes bxv-frame{from{opacity:0;transform:translateY(16px) scale(.985)}to{opacity:1;transform:none}}

@keyframes bxv-slidedown{from{opacity:0;transform:translateY(-8px)}to{opacity:1;transform:none}}

/* traffic-light dots pop in one by one */

/* url reveals like it's being typed/loaded (clip from left) */
@keyframes bxv-type{from{clip-path:inset(0 100% 0 0)}to{clip-path:inset(0 0 0 0)}}

/* root node (home / "Accueil") lands with a soft brand glow */
@keyframes bxv-node{from{opacity:0;transform:translateY(8px) scale(.96)}to{opacity:1;transform:none}}

/* connector lines DRAW: vertical trunk grows down, branches grow right */
@keyframes bxv-trunk{from{transform:scaleY(0)}to{transform:scaleY(1)}}
@keyframes bxv-branch{from{transform:scaleX(0)}to{transform:scaleX(1)}}

/* child nodes pop in right after their branch draws */

/* legend fades up last */

/* the "one-page vs multi-page" choice panel slides in */
@keyframes bxv-panel{from{opacity:0;transform:translateY(12px)}to{opacity:1;transform:none}}

/* =============== ON-VIEW BUILD : "CONÇU POUR" CHIPS =============== */

/* =============== AMBIENT (always-on, subtle, infinite) =============== */

/* Root sitemap node breathes a soft brand glow — the "live" homepage */
@keyframes bxv-breathe{0%,100%{box-shadow:0 0 0 0 var(--brand-t)}50%{box-shadow:0 0 0 5px var(--brand-t)}}

/* Sheen sweeps across the root node like a passing highlight */
@keyframes bxv-sheen{0%{background-position:180% 0}55%,100%{background-position:-80% 0}}

/* Highlighted "choice" panel gets a slow diagonal sheen sweep */
@keyframes bxv-sheen2{0%{background-position:200% 0}50%,100%{background-position:-120% 0}}

/* the choice-panel icon gently pulses */
@keyframes bxv-iconpulse{0%,100%{opacity:.75}50%{opacity:1}}

/* "Option" tag softly pulses to flag it's optional */
@keyframes bxv-optpulse{0%,100%{opacity:.7}50%{opacity:1}}

/* browser traffic-light dots gently shimmer, staggered, after assembly */
@keyframes bxv-dot{0%,100%{opacity:.55}50%{opacity:.95}}

/* legend "page principale" dot softly pulses like a live status */
@keyframes bxv-statuspulse{0%,100%{transform:scale(1);opacity:.85}50%{transform:scale(1.25);opacity:1}}

/* =============== HOVER MICRO-INTERACTIONS =============== */
/* Spec rows lift + tint their label; check nudges */

/* sitemap child nodes lift + tint toward brand on hover */

/* audience chips lift + tint */

/* =============== REDUCED MOTION GUARD =============== */
@media (prefers-reduced-motion: reduce){
  .c-vitrine.c-vitrine *{animation:none!important;transition:none!important}
  .c-vitrine.c-vitrine [style], .c-vitrine.c-vitrine *{opacity:1!important;transform:none!important}
  .c-vitrine.c-vitrine .c-vitrine__check.c-vitrine__check{stroke-dashoffset:0!important}
  .c-vitrine.c-vitrine .c-vitrine__url.c-vitrine__url{clip-path:none!important}
  .c-vitrine.c-vitrine .c-vitrine__node.c-vitrine__node.is-root::after,
  .c-vitrine.c-vitrine .c-vitrine__choice.c-vitrine__choice::after{display:none!important}
  .c-vitrine.c-vitrine :not(.is-in.is-in) header>*,
  .c-vitrine__sec.c-vitrine__sec:not(.is-in.is-in) .c-vitrine__row.c-vitrine__row,
  .c-vitrine__sec.c-vitrine__sec:not(.is-in.is-in) .c-vitrine__browser.c-vitrine__browser,
  .c-vitrine__sec.c-vitrine__sec:not(.is-in.is-in) .c-vitrine__choice.c-vitrine__choice,
  .c-vitrine__sec.c-vitrine__sec:not(.is-in.is-in) .c-vitrine__kicker.c-vitrine__kicker,
  .c-vitrine__sec.c-vitrine__sec:not(.is-in.is-in) .c-vitrine__h3.c-vitrine__h3,
  .c-vitrine__sec.c-vitrine__sec:not(.is-in.is-in) .c-vitrine__note.c-vitrine__note,
  .c-vitrine.c-vitrine:not(.is-in.is-in) .c-vitrine-for__label.c-vitrine-for__label,
  .c-vitrine.c-vitrine:not(.is-in.is-in) .c-vitrine__chip.c-vitrine__chip{opacity:1!important}
}


/* ============ GARDE NO-JS : rien d'invisible sans JavaScript ============ */

/* =========================================================
   CORRECTIFS post-vérification
   ========================================================= */
/* Tables de contenu (pages légales / prose) : défilables sur mobile
   sans casser l'alignement des colonnes (display:block => scroll du bloc,
   l'intérieur reste une table). On exclut la matrice bx-prix (déjà gérée). */

/* …mais au-dessus du mobile, ce `display:block` empêche le tableau d'occuper
   sa colonne.

   Un `<table>` en `display:block` enveloppe ses rangées dans une boîte de
   tableau ANONYME, dimensionnée en shrink-to-fit. Le `width: 100%` posé au
   panneau de `c-legal__table` s'applique alors à la boîte de bloc, jamais à la
   grille : le tableau se dessine à la largeur de son contenu, au milieu d'une
   colonne deux fois plus large. C'est le §5 dans sa forme pure — un réglage de
   panneau rendu inerte par une règle écrite ailleurs, et le client qui ouvre le
   builder y voit bien « 100 % ».

   Mesuré le 06/08/2026 à 1440 px, colonne de 812 px :
     /mentions-legales/  grille 538,2 px  ·  puis 467,0 px
     /confidentialite/   grille 550,7 px
   Les tableaux d'article ne montraient rien : ils remplissent déjà leur figure.
   Le défaut y était latent, il est corrigé au passage.

   Le palier 641 n'est pas un réglage de confort : sous 640 px, ce `display:block`
   EST le conteneur de défilement des tableaux légaux, qui n'en ont aucun autre.
   Le retirer là ferait déborder le document — mesuré, /confidentialite/ à 375 px
   défile bien dans son propre bloc (clientWidth 327, scrollWidth 509).

   Même spécificité (0-2-2) que la règle du CSS personnalisé global qu'elle
   corrige : on gagne par l'ordre des feuilles — celle-ci est la 16e, le bloc
   global la 9e. Et c'est pourquoi on ne rejoue PAS `css-to-bricks.mjs --apply`
   après ce dépôt : la règle `main table` ne vit dans aucune source, un rejeu la
   retirerait du bloc global et réécrirait 510 classes pour rien. */
@media (min-width: 641px) {
  main table:not(.c-prix__matrix.c-prix__matrix) {
    display: table;
    width: 100%;
    max-width: 100%;
    overflow-x: visible;
  }
}
/* Sécurité : les conteneurs scrollables des blocs bx ne poussent pas la page.
   `min-width: 0` : sans lui un parent grid/flex refuse de rétrécir le
   conteneur sous la largeur de son contenu → c'est la PAGE qui déborde.
   `overscroll-behavior-x: contain` : le scroll de la matrice ne se chaîne
   pas vers le document (plus de « swipe qui emporte la page » sur mobile). */

/* =========================================================
   HARMONISATION EYEBROWS + ÉTAPES (langage aéré)
   ========================================================= */
/* Les eyebrows de section (.c-pill.c-pill) : plus de pilule arrondie → texte
   mono majuscule, comme les nouveaux blocs. (!important pour battre
   les règles de thème/scope existantes, purement cosmétique.) */


/* =========================================================================
   PRICING SHOWPIECE — AIRY ELEVATION
   Appended at the very end → equal-specificity rules WIN by source order.
   Re-declares existing selectors only. No HTML / class changes; tokens only.
   Shared by HOME (index.html) + /tarifs → styled to read great on both.
   Deliberately does NOT touch .c-price-card--featured.c-price-card--featured::before / ::after so the
   "RECOMMANDÉ" badge and the top brand sheen from the earlier block stay live.
   Entrance is gated on .is-revealable.is-revealable (JS early-returns under reduced-motion / no-IO,
   so .is-revealable.is-revealable is never added → price stays visible) — never an unconditional
   opacity:0. Belt-&-suspenders reduced-motion guard included at the end.
   ========================================================================= */

/* ---- A) PRICE = the focal point ---------------------------------------
   The markup places <small>À PARTIR DE</small> then <b>999€</b> inside a
   .c-price-card__price.c-price-card__price that the base stylesheet pins absolute top/right. We
   un-pin it into the flow as its own hairline-separated zone at the foot of
   .c-price-card__info.c-price-card__info: a quiet mono micro-label sitting ABOVE a large mono
   figure. Column flow puts <small> above <b> automatically (DOM order). */
/* micro-label: mono, uppercase, whisper-quiet */
/* the figure: large mono numeral with real presence */

/* ---- B) Feature check glyph → theme-aware brand-ink hairline check -----
   The inline SVG hardcodes fill/stroke = var(--color-primary). Author CSS
   fill/stroke on the shapes overrides inline presentation attributes, so we
   retint the check to --brand-ink (the accent that stays legible in BOTH
   themes) while keeping the disc airy via its inline fill-opacity. */

/* ---- C) Feature rows: reaffirm airy hairline list; highlight = brand ---
   (row hairlines/padding already set upstream; here we keep the highlight
   readable — a touch more weight + brand ink, no heavy underline.) */

/* ---- D) Tasteful entrance: price rises in with the card's cascade ------
   Mirrors the feature-row stagger already in place. Gated on .is-revealable.is-revealable only,
   so no-JS / reduced-motion (JS never adds .is-revealable.is-revealable) leaves it fully visible.
   Reveals on .is-visible.is-visible (this site) AND .is-in.is-in (spec) — never fights the
   card-level reveal, just layers under it. */

/* ---- E) Mobile: keep the figure bold but overflow-safe at 380px -------- */
@media (max-width: 480px) {
  .c-price-card__price.c-price-card__price {
    margin-top: var(--space-xs);
    padding-top: var(--space-xs);
  }
  .c-price-card__price.c-price-card__price b { font-size: clamp(30px, 9vw, 40px); }
}

/* ---- F) Reduced-motion guard (belt & suspenders) ---------------------- */
@media (prefers-reduced-motion: reduce) {
  .c-price-card.c-price-card.is-revealable .c-price-card__price.c-price-card__price,
  .c-price-card.c-price-card.is-revealable.is-visible .c-price-card__price.c-price-card__price,
  .c-price-card.c-price-card.is-in .c-price-card__price.c-price-card__price {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
  }
}

/* =========================================================
   ANIMATIONS SIGNATURE
   ========================================================= */
/* Shine premium au survol des CTA primaires (au repos : hors-champ, invisible) */
@keyframes btnShine{ from{ left:-80%; } to{ left:135%; } }
@media (prefers-reduced-motion: reduce){ .c-btn--primary.c-btn--primary:hover::after{ animation:none !important; } }

/* =========================================================
   SUBHERO SHOWCASE — mini-produits par page + build-in animé
   Enrichissement additif : ne touche ni la position, ni l'overflow,
   ni le débordement voulu du showcase. Base toujours visible ;
   le mouvement ne s'ajoute que par-dessus (JS + no-preference).
   Tokens de thème uniquement.
   ========================================================= */

/* ---- A) Chaque variante devient un mini-produit reconnaissable ---------- */

/* PRICING — cartes = paliers tarifaires : prix en tête + lignes de features */

/* PROCESS — étapes reliées : connecteur + pastille d'index + libellé */

/* EDITORIAL — un article : image de une + signature (avatar + nom) */

/* PROFILE — avatar vérifié + cartes de statistiques (chiffre + label) */

/* ONEPAGE — page longue : bandeau hero + sections empilées + scrollbar */

/* REFONTE — comparatif avant/après : ancienne page atténuée, nouvelle + curseur */

/* ---- B) Build-in animé : le squelette s'assemble en cascade ------------- */
/* Transitions (pas d'animation) → les boucles ambiantes (caret/pulse/shimmer)
   restent intactes. État masqué uniquement si JS ET mouvement autorisé. */
@media (prefers-reduced-motion: no-preference) {
  .u-js .c-subhero__showcase.c-subhero__showcase .c-mockup-hero.c-mockup-hero > *,
  .u-js .c-subhero__showcase.c-subhero__showcase .c-mockup__screen.c-mockup__screen > .c-mockup-line.c-mockup-line {
    opacity: 0;
    transform: translateY(14px);
    transition: opacity .55s var(--motion-easing-standard), transform .55s var(--motion-easing-standard);
  }
  /* Cartes : opacité seule → les transforms de variante (carte mise en avant) sont préservées */
  .u-js .c-subhero__showcase.c-subhero__showcase .c-mockup-row.c-mockup-row > .c-mockup-card.c-mockup-card {
    opacity: 0;
    transition: opacity .55s var(--motion-easing-standard);
  }

  /* Séquence d'assemblage */
  .u-js .c-subhero__showcase.c-subhero__showcase .c-mockup-hero.c-mockup-hero > *:nth-child(1) { transition-delay: .08s; }
  .u-js .c-subhero__showcase.c-subhero__showcase .c-mockup-hero.c-mockup-hero > *:nth-child(2) { transition-delay: .16s; }
  .u-js .c-subhero__showcase.c-subhero__showcase .c-mockup-hero.c-mockup-hero > *:nth-child(3) { transition-delay: .24s; }
  .u-js .c-subhero__showcase.c-subhero__showcase .c-mockup-hero.c-mockup-hero > *:nth-child(4) { transition-delay: .32s; }
  .u-js .c-subhero__showcase.c-subhero__showcase .c-mockup-row.c-mockup-row > .c-mockup-card.c-mockup-card:nth-child(1) { transition-delay: .40s; }
  .u-js .c-subhero__showcase.c-subhero__showcase .c-mockup-row.c-mockup-row > .c-mockup-card.c-mockup-card:nth-child(2) { transition-delay: .48s; }
  .u-js .c-subhero__showcase.c-subhero__showcase .c-mockup-row.c-mockup-row > .c-mockup-card.c-mockup-card:nth-child(3) { transition-delay: .56s; }
  .u-js .c-subhero__showcase.c-subhero__showcase .c-mockup__screen.c-mockup__screen > .c-mockup-line.c-mockup-line:nth-child(3) { transition-delay: .62s; }
  .u-js .c-subhero__showcase.c-subhero__showcase .c-mockup__screen.c-mockup__screen > .c-mockup-line.c-mockup-line:nth-child(4) { transition-delay: .70s; }
  .u-js .c-subhero__showcase.c-subhero__showcase .c-mockup__screen.c-mockup__screen > .c-mockup-line.c-mockup-line:nth-child(5) { transition-delay: .78s; }

  /* État révélé */
  .c-subhero__showcase.c-subhero__showcase.is-built .c-mockup-hero.c-mockup-hero > *,
  .c-subhero__showcase.c-subhero__showcase.is-built .c-mockup__screen.c-mockup__screen > .c-mockup-line.c-mockup-line { opacity: 1; transform: translateY(0); }
  .c-subhero__showcase.c-subhero__showcase.is-built .c-mockup-row.c-mockup-row > .c-mockup-card.c-mockup-card { opacity: 1; }

  /* ---- C) Flottement ambiant très discret (desktop uniquement) ---- */
  @media (min-width: 761px) {
    .c-subhero__mockup.c-subhero__mockup { animation: subhero-float 7s var(--motion-easing-standard) infinite; }
  }
}
@keyframes subhero-float {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-6px); }
}

/* ---- Garde MOUVEMENT RÉDUIT : tout visible, aucune animation ------------ */
@media (prefers-reduced-motion: reduce) {
  .c-subhero__showcase.c-subhero__showcase .c-mockup-hero.c-mockup-hero > *,
  .c-subhero__showcase.c-subhero__showcase .c-mockup__screen.c-mockup__screen > .c-mockup-line.c-mockup-line {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
  }
  .c-subhero__showcase.c-subhero__showcase .c-mockup-row.c-mockup-row > .c-mockup-card.c-mockup-card {
    opacity: 1 !important;
    transition: none !important;
  }
  .c-subhero__mockup.c-subhero__mockup { animation: none !important; }
}

/* =========================================================
   STEPS-PIN — scroll-pinned horizontal-progress stepper
   Generic driver for every [data-steps-pin]. Structure:
     .c-steps-pin.c-steps-pin            → tall track wrapper (creates the pin travel)
       .c-steps-pin__stage.c-steps-pin__stage   → position:sticky, top = live header height
         .c-methode__board.c-methode__board → rail + fill + nodes + 4 phases (the board)
   JS sets --p (0→1) + the sticky top live each frame; CSS maps --p
   to the horizontal fill width. Fallback (<=900px / reduced motion):
   no pin — the board flows and stacks normally, fully visible.
   ========================================================= */
/* Pas de `top` ici : le driver écrit `stage.style.top = headerH + 'px'` en
   inline à chaque frame (script.u-js). Un `top: var(--steps-pin-top, 88px)`
   serait inopérant — et --steps-pin-top n'est défini nulle part. */

/* La scène occupe la hauteur utile sous le header et répartit le vide en
   haut ET en bas (avant : tout le vide tombait sous les cartes, la scène
   semblait « pas assez haute »). --hh est posée par le driver (hauteur réelle
   du header sticky) ; le fallback couvre le cas où le JS n'a pas encore tourné.
   Bornée aux viewports où le pin est actif — cf. les media queries du driver. */
@media (min-width: 901px) and (min-height: 761px) {
  .u-js .c-steps-pin.c-steps-pin[data-steps-pin] .c-steps-pin__stage.c-steps-pin__stage {
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: var(--sp-head-gap);
    min-height: calc(100vh - var(--hh, 88px));
  }
  /* En flex, la marge du header ferait doublon avec le `gap`. */
  .u-js .c-steps-pin.c-steps-pin[data-steps-pin] .c-steps-pin__head.c-steps-pin__head { margin-block: 0; }
}

/* La TÊTE DE SECTION vit DANS la scène : elle reste visible pendant tout le
   pin (on sait toujours de quel bloc on lit les étapes). Elle est donc
   comptée dans la hauteur de scène — voir le seuil `max-height` plus bas.
   Elle ouvre une sous-section séparée par un filet (celui porté par
   .c-methode__board.c-methode__board) : elle suit donc le rythme --sp-block / --sp-block-in
   comme tous les autres « filet + air » du site, pas un espacement ad hoc. */
/* Aucune surcharge de font-size : `.c-methode__h2` / `.c-methode__lede`
   portent l'échelle du site, identique desktop et mobile. */

/* The scroll travel while pinned is created by an in-flow spacer AFTER the
   sticky stage — this extends the wrapper's CONTENT box so the sticky
   constraint rect has room. (Bottom padding does NOT work in Chromium: the
   sticky rect is clamped to the content box, so a padded wrapper never pins.)
   Gated on .u-js so the page has no dead space when scripting is off. */

/* Le board n'ajoute plus de margin (c'est le head qui porte la couture au-
   dessus du filet) et son air sous le filet passe sur le token commun.
   Spécificité (0,2,0) : bat le `<style>` inline des pages (0,1,0) sans
   `!important`, malgré sa position postérieure dans la cascade. */

/* 2 CTA SOUS les étapes, FERRÉS À GAUCHE comme tout le reste du site
   (`.l-section`/`.l-section__head` sont en align-items:flex-start — les centrer
   ici recréerait la couture « deux designs greffés »).
   Ils sont HORS de .c-steps-pin.c-steps-pin (frère suivant), donc dans le flux normal :
   ils entrent d'eux-mêmes dans le champ à la FIN de la course du pin. Aucun
   mécanisme d'opacité — `opacity:0` ne retire pas les pointer-events, deux
   liens invisibles resteraient cliquables par-dessus le contenu. Et la scène
   reste courte, donc elle tient dans un viewport d'ordinateur portable. */

/* Horizontal progress fill riding the spine, driven by --p on the stage. */

/* The board list must never render "1./2." markers. */

/* FALLBACK — no pin: board flows / stacks and stays fully visible.
   Le seuil `max-height` vient d'une MESURE, pas d'une estimation :
   scène (head + board) = 643px au pire (901→1100px de large) et en-tête
   collant = 73px, soit 716px requis. En dessous de 760px de haut la scène
   dépasserait le viewport et son bas serait coupé → on ne pin pas.
   ⚠ Ces DEUX valeurs (900 / 760) sont dupliquées dans script.u-js (mqSmall /
   mqShort). Si l'une change, l'autre doit changer : un breakpoint CSS que le
   JS ignore met le spacer à 0 pendant que le driver reste en mode pin
   (travel ≈ 0 → --p bloqué à 0, les 4 étapes gèlent sur l'étape 1). */
@media (max-width: 900px), (max-height: 760px) {
  .u-js .c-steps-pin.c-steps-pin[data-steps-pin] .c-steps-pin__spacer.c-steps-pin__spacer { height: 0; }
  .c-steps-pin__stage.c-steps-pin__stage { position: static; }
  .c-steps-pin__fill.c-steps-pin__fill { display: none; }
}
@media (prefers-reduced-motion: reduce) {
  .u-js .c-steps-pin.c-steps-pin[data-steps-pin] .c-steps-pin__spacer.c-steps-pin__spacer { height: 0; }
  .c-steps-pin__stage.c-steps-pin__stage { position: static; }
}

/* =========================================================
   SITE VIVANT — Couche d'animations pilotées par le scroll
   (append-only). Premium, GPU-only (transform/opacity),
   entièrement conditionnée à prefers-reduced-motion.
   Principe : enhancement pur. L'état de base est TOUJOURS
   pleinement visible ; ni JS ni scroll-timeline ne sont requis
   pour lire le contenu — le mouvement n'est qu'une surcouche.
   Un halo ambiant (.c-bg-orb.c-bg-orb) dérive déjà en JS sur toutes les
   pages : on ne le touche pas ici (conflit de transform inline).
   ========================================================= */

/* ---------- 1 · Parallaxe des halos ambiants (scroll-linked) ----------
   Les halos décoratifs dérivent doucement (≤40px d'amplitude), plus
   lentement que le scroll. Pilotage 100% CSS via scroll-timeline quand
   le navigateur le supporte ; sinon un rAF discret (script.u-js) prend le
   relais. transform-only, jamais width/height/top/left. */
@keyframes bv-hero-glow-drift {
  from { transform: translate(-50%, -18px); }
  to   { transform: translate(-50%, 18px); }
}
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    /* Halo du hero : dérive au fil du scroll racine (visible pendant le pin). */
    .c-hero__glow.c-hero__glow {
      animation: bv-hero-glow-drift linear both;
      animation-timeline: scroll(root block);
      will-change: transform;
    }
  }
}

/* ---------- 2 · Révélations directionnelles (alternance gauche/droite) ----------
   On superpose une légère direction (18px) à la révélation .is-in.is-in existante,
   en PRÉ-ÉTAT uniquement (:not(.is-in.is-in)) pour ne jamais figer l'état de repos.
   Gated .u-js + no-preference : sans JS ou en reduced-motion, aucun décalage.
   La cascade nth-child (transition-delay) et l'opacité restent pilotées par
   les règles existantes — on ne fait que composer le translateX au translateY.
   Spécificité (0,4,1) : bat les pré-états de base ET le scope sous-page. */
@media (prefers-reduced-motion: no-preference) {
  html.u-js .c-presta-card.c-presta-card:nth-child(odd):not(.is-in.is-in)   { transform: translate(-18px, 14px); }
  html.u-js .c-presta-card.c-presta-card:nth-child(even):not(.is-in.is-in)  { transform: translate(18px, 14px); }
  html.u-js .c-feature-card.c-feature-card:nth-child(odd):not(.is-in.is-in)  { transform: translate(-18px, 14px); }
  html.u-js .c-feature-card.c-feature-card:nth-child(even):not(.is-in.is-in) { transform: translate(18px, 14px); }
}

/* ---------- 3 · Accent scrollé : jauge budget (bx-prix, page /prix) ----------
   Un filet de marque se remplit de gauche à droite au fil du scroll, comme une
   valeur qui se révèle. Pseudo dédié (::before libre — le sweep ambiant utilise
   ::after), scaleX only, piloté par view(). N'existe QUE sous @supports +
   no-preference : sans support ou en reduced-motion, la jauge reste normale
   (aucun contenu masqué — c'est un élément décoratif purement additif). */
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    /* La timeline suit le RAIL (pas le filet de 2px), sinon la course serait
       quasi nulle : timeline nommée sur .c-prix__track.c-prix__track, consommée par ::before. */
    .c-prix.c-prix .c-prix__track.c-prix__track {
      view-timeline-name: --bv-prix-track;
      view-timeline-axis: block;
    }
    .c-prix.c-prix .c-prix__track.c-prix__track::before {
      content: "";
      position: absolute;
      left: 0; right: 0; bottom: 0;
      height: 2px;
      background: linear-gradient(90deg,
        color-mix(in srgb, var(--brand) 55%, transparent), var(--brand));
      transform-origin: left center;
      transform: scaleX(0);
      pointer-events: none;
      z-index: 3;
      animation: bv-prix-fill linear both;
      animation-timeline: --bv-prix-track;
      animation-range: cover 15% cover 78%;
      will-change: transform;
    }
  }
}

/* ---------- Garde-fou reduced-motion (obligatoire) ----------
   Redondant avec les gates no-preference ci-dessus, mais explicite : toute la
   couche « site vivant » est neutralisée, sans état intermédiaire ni élément
   masqué. Les halos reprennent leur transform de base (centrage conservé). */
@media (prefers-reduced-motion: reduce) {
  .c-hero__glow.c-hero__glow { animation: none !important; }
  html.u-js .c-presta-card.c-presta-card:not(.is-in.is-in),
  html.u-js .c-feature-card.c-feature-card:not(.is-in.is-in) { transform: none !important; }
  .c-prix.c-prix .c-prix__track.c-prix__track::before { content: none !important; animation: none !important; }
}


/* =========================================================================
   BEELY — SYSTÈME CENTRAL CONSOLIDÉ  (rév. 2)
   Rythme · Alignement · Séparateurs · Cards
   -------------------------------------------------------------------------
   Ce bloc REMPLACE (il ne s'ajoute pas) — suppressions faites dans le même
   commit, sinon rien n'est consolidé :
     styles.css  55-65    1re échelle --space-*            → réécrite ici
     styles.css  957-960  2e échelle --space-* (résiduelle) → SUPPRIMÉE
     styles.css  150-165  .l-section.l-section / .l-section__head.l-section__head          → réécrites ici
     styles.css  862-884  conic + borderSpin (price-card)   → SUPPRIMÉ
     styles.css  1126, 1169, 1270, 1298, 1348               → SUPPRIMÉS
     styles.css  1498-1511, 1605-1606, 1646-1673 (zone rouge) → SUPPRIMÉE
     styles.css  1859-1872 (padding bx + sous-blocs)        → réécrit ici
     styles.css  1963 (max-width feature-grid--2)           → SUPPRIMÉ
     styles.css  2385-2447 (::before sheen + priceSheen)    → SUPPRIMÉ
     12 pages    <style> inline : le motif « filet + air »  → SUPPRIMÉ du HTML
   Zéro !important. Aucun `~`, aucun `:has()`, aucun sélecteur d'attribut.
   ========================================================================= */


/* =========================================================================
   1. ÉCHELLE D'ESPACEMENT UNIQUE
   Base 4px, 8 crans. Les composants n'écrivent QUE les rôles sémantiques :
   c'est ce qui empêche la ré-apparition des 34 gaps sauvages.
   ========================================================================= */


/* Sous 900px la barre du header se réorganise et gagne ~10px : le token suit,
   sinon tout élément sticky se colle 10px trop haut. */


/* =========================================================================
   2. GOUTTIÈRE UNIQUE
   Une seule mécanique de colonne : header, sections, blocs bx-*, footer.
   Tous les filets partagent le même x gauche et le même x droit.
   ========================================================================= */
/* `.c-footer-locations` porte son propre filet : il doit partir de la même
   colonne que les autres, sinon on voit deux gouttières dans le footer. */

/* Les wrappers internes hérités ne re-gouttièrent plus (sinon 24 + 24)
   et ne rétrécissent plus la colonne (sinon les filets se décalent). */

/* Garde-fou scroll horizontal. `clip` (et non `hidden`) : aucun conteneur
   de défilement créé, donc position:sticky (scroll-pin des étapes) intact. */


/* =========================================================================
   3. SECTION — rythme vertical et alignement
   UN seul padding-block pour toutes les sections : plus de coutures à
   140 / 170 / 174px sur la même page.
   ========================================================================= */

/* --- Correctif gouttière (header / footer / subhero) ---------------------
   Le header (styles.css:283) et le footer (:711) portaient un padding-inline
   var(--space-m) sur le PARENT, EN PLUS de la gouttière --sp-gutter portée par
   leurs enfants (.c-site-header__inner.c-site-header__inner, .c-site-footer__top.c-site-footer__top/__bottom, .c-footer-locations.c-footer-locations)
   → double gouttière : alignés à 1440 par le seul jeu du centrage, mais décalés
   de ~24px sous 1366px (header/footer à 48, sections à 24). On retire le padding
   horizontal du parent : seuls les enfants gouttièrent, à la même colonne que
   les sections, à TOUTES les largeurs. */

/* Le subhero utilisait `width: min(100% - 2*space-m, site-max)` + padding-left 0
   → ferré à 37px @1440 au lieu de 61 (pas de gouttière gauche). On l'aligne sur
   la mécanique des sections : largeur pleine plafonnée à --maxw, centrée, plus la
   gouttière à gauche. Le padding-droit (réservé au mockup en position:absolute)
   et le padding-bloc sont conservés. */

/* Chaque enfant occupe la colonne : le ferrage vient de l'alignement du
   TEXTE, pas d'une largeur réduite qui recentrerait le bloc. */

/* --- RÈGLE D'OR : UN SEUL PROPRIÉTAIRE D'ESPACE PAR COUTURE ---------------
   L'espace vertical appartient au parent, via cette unique règle adjacente.
   Les composants ne portent plus de margin verticale : plus rien ne
   s'additionne, et rien ne peut collapser (contexte flex). */

/* Un lien de rappel se rattache à ce qui le précède : couture courte. */

/* Décoratifs positionnés : ils ne sont ni dans la colonne ni dans le rythme. */
/* `.faq__glow` retiré : le halo était imbriqué DANS `.c-faq__inner`, donc ce
   sélecteur enfant-direct ne l'a jamais atteint — et l'<img> a été supprimé
   des 26 pages avec la refonte du bloc FAQ. */


/* =========================================================================
   4. TÊTE DE SECTION — ferrée à gauche, une seule fois
   Remplace styles.css:158-165 ET les 5 surcharges contradictoires.
   Le ferrage à gauche s'obtient en SUPPRIMANT les annulations.
   ========================================================================= */

/* On limite la MESURE du texte, pas la largeur du conteneur. */

/* Corps de section : même logique, aucune margin propre. */

/* Wrappers hérités qui contiennent une tête + un contenu empilés : ils
   deviennent eux aussi des colonnes rythmées, sinon `.l-section > * + *` ne
   se déclenche jamais (la tête est imbriquée) et la tête colle au contenu.
   `.c-faq__inner` est VOLONTAIREMENT exclu : c'est une grille 2 colonnes
   (intro à gauche / liste à droite), la passer en flex-column casserait la
   FAQ. Son gap propre assure déjà la couture. */
/* .c-portfolio__filters.c-portfolio__filters n'est plus listé ici : plus rien ne le centre depuis
   que son bloc est consolidé, cette dé-centrage était devenu une surcharge
   sans cible. .c-linklist.c-linklist, lui, est encore centré l.1435. */

/* Le CTA de fin de page est la seule occurrence prévue.
   Il reste PLEINE LARGEUR : son halo (`.l-section.c-cta::before{inset:0}`) doit
   couvrir toute la fenêtre. La colonne de lecture est reconstituée par le
   padding, pas par une max-width — sinon le halo se coupe net à 1366px.
   (Pas de 100vw : cela déborderait de la largeur de la barre de défilement.) */


/* =========================================================================
   6. SÉPARATEURS — une règle, un filet, jamais deux
   Le filet est porté par l'élément QUI COMMENCE, sur son border-top : il
   partage son bord avec l'espacement, impossible de désynchroniser.
   ========================================================================= */

/* 6a — LE filet inter-sections. Source de vérité unique, home ET sous-pages. */

/* 6b — AUCUN autre porteur de filet de section : on neutralise les traits
        orphelins ou en doublon.
        Le border-top du `.c-site-footer` (styles.css:614) est CONSERVÉ : c'est
        le seul séparateur de fin de page. Il est simplement retokenisé en
        var(--line) pour s'aligner sur les autres filets. */

/* 6c — Les porteurs de filet ne prennent JAMAIS de max-width locale, sinon
        les traits ne se répondent pas verticalement. */   /* .c-faq__list.c-faq__list : déclaré dans le bloc FAQ unique */

/* 6d — Sous-sections des blocs bx-* : motif « filet + air » écrit UNE fois,
        sur des classes EXPLICITES (plus de sélecteur d'attribut).
        Remplace styles.css:1866-1872, où margin-top(89) + padding-top(44)
        s'additionnaient à 133px avec 3 rythmes différents — et où
        `[class*="__sub"]` frappait aussi `.c-methode__sub`, un simple
        paragraphe de chapô, qui héritait d'un filet et de 90px d'air.
        Les mêmes déclarations ont été retirées des <style> inline des pages :
        sans cela, ces règles-ci seraient des no-op (spécificité égale,
        position postérieure dans la cascade). */

/* Le premier de la série n'ouvre pas sur un filet orphelin. */

/* `.c-vitrine-for` reste une ligne de chips : le motif ne doit pas casser
   sa mise en page horizontale. *//* 6e — Les sections qui portent un bloc bx-* suivent --sp-section comme les
        autres : plus de padding spécial,
et `.l-section > *{width:100%}` (§3)
        couvre déjà leur largeur. Rien à écrire ici. */


/* =========================================================================
   7. CARDS — gaps resserrés et homogènes
   Hier : 24 / 32 / 43.2 / 52 / 34 / 44px. Aujourd'hui : un seul token.
   Resserrer tout le site de 16 à 12px = UNE ligne (--sp-card-gap).
   ========================================================================= *//* Colonnes — `min(…,
100%)` sur CHAQUE piste : à 320px de viewport la boîte
   de contenu fait 280px,
une piste rigide de 280/300px déborderait et
   overflow-x:clip rognerait le contenu au lieu de le reflower. */

/* Padding interne unique de toute card encadrée : le gap se resserre, l'air
   passe À L'INTÉRIEUR — la respiration reste, les cartes se rapprochent. */

/* 7b — Carte « Expert » : liseré COMPLET, les 4 côtés.
        Le liseré ne faisait plus le tour parce qu'il avait été réduit à un
        trait de 2px en haut (::before) posé PAR-DESSUS la bordure : double
        filet haut, rien sur les 3 autres côtés.
        Ici : un anneau dégradé de 1px obtenu par masque (la padding-box est
        exclue de la border-box). Statique → zéro repaint permanent.
        · le rayon suit celui de la card : .c-price-card.c-price-card est en var(--r-m),
          l'anneau doit donc être en calc(var(--r-m) + 1px) — pas --r-l.
        · les stops sont OPAQUES : --brand-t2 (alpha .13/.22) rendait
          l'anneau quasi invisible au milieu du dégradé, et --brand-2 est un
          hex codé en dur sans variante claire. color-mix garde le contraste
          dans les deux thèmes. */
/* Le badge « RECOMMANDÉ » passe au-dessus de l'anneau, le contenu au-dessus des deux. */

/* 7c — FAQ : voir le bloc « FAQ — accordéon aéré » (source unique).
        L'ancienne surcharge posait padding-block:24px sur .c-faq__item.c-faq__item alors
        que .c-faq__question.c-faq__question portait déjà padding:20px : 44px d'air par question au
        lieu de 24. Les deux couches sont fusionnées en une seule. */


/* =========================================================================
   8. ACCESSIBILITÉ — focus visible sur un site majoritairement sans bordure
   Pas de `border-radius` ici : il s'appliquerait à l'ÉLÉMENT, pas à
   l'outline, et écraserait le rayon pill d'un `.c-btn` ou d'un chip au clavier.
   L'outline suit déjà le rayon propre de l'élément.
   ========================================================================= */
/* On ne retire jamais l'outline sans le remplacer. */


/* =========================================================================
   9. MOBILE — le rythme se compresse, il ne change pas de nature
   Un seul palier, mêmes règles, valeurs plus courtes. Aucun re-centrage.
   ========================================================================= */
@media (max-width: 760px) {

  /* TOUTES les grilles passent en colonne unique — y compris celles qui
     gardaient une piste de 280/300px et débordaient à 320px. */
}

/* =========================================================================
   PERFORMANCE — animations infinies hors écran
   Cf. le bloc « ANIMATIONS INFINIES » de script.u-js. `.is-anim-idle` est posée
   par un IntersectionObserver quand l'élément quitte le champ (+200px de marge).
   ========================================================================= */

/* Le marquee anime `transform` en boucle sur des rangées qui contiennent
   des logos sous `filter`. Sans promotion explicite, chaque frame repeint
   les images filtrées ; avec, la rangée est rasterisée une fois puis
   simplement composée. `will-change` est légitime ici : l'animation est
   permanente tant que la rangée est visible. */

/* =========================================================================
   PROSE ÉDITORIALE — refonte airée (remplace le rendu « article de blog brut »)
   S'applique à toutes les sections .c-prose.c-prose (27 pages de contenu long). Appended
   en fin de feuille pour gagner la cascade sur les anciennes règles .c-prose.c-prose.
   Objectif : mêmes codes que les blocs bx-* — ferré à gauche, chapitres séparés
   par un filet fin avec un index mono, typo travaillée, une seule couleur
   d'accent, tokens theme-aware (rendu correct en clair ET en sombre).
   ========================================================================= */   /* compteur continu par page (pas de « 01 » dupliqué) */

/* Accroche : premier paragraphe / .c-prose__lead.c-prose__lead — plus grand, couleur pleine */

/* Chapitre : chaque h2 ouvre une section, précédée d'un filet fin et d'un
   index mono numéroté (compteur continu dans la section-body). */
/* Le tout premier chapitre de la section ne porte pas de filet (rien au-dessus). */

/* Sous-titre */

/* Listes : puce fine alignée sur la ligne de base */

/* =========================================================================
   CTA DE MILIEU D'ARTICLE — relance de conversion sur les pages longues.
   Injectée par script.u-js après le 2e chapitre des pages à article long (celles
   qui font beaucoup lire avant la CTA finale). Style airé, ferré à gauche, borné
   par des filets fins — pas d'encadrement (cohérent avec la DA).
   ========================================================================= */
.c-prose-cta.c-prose-cta {
  max-width: 74ch;
  margin-block: clamp(38px, 5vw, 60px);
  padding-block: clamp(22px, 3vw, 30px);
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 18px 28px;
}
.c-prose-cta__text.c-prose-cta__text { display: flex; flex-direction: column; gap: 5px; }
.c-prose-cta__title.c-prose-cta__title {
  color: var(--text);
  font-weight: 700;
  font-size: 1.16rem;
  letter-spacing: -0.01em;
}
.c-prose-cta__sub.c-prose-cta__sub { color: var(--text-2); font-size: 0.96rem; line-height: 1.5; max-width: 46ch; }
.c-prose-cta.c-prose-cta .c-btn.c-btn { flex: none; }
@media (max-width: 560px) {
  .c-prose-cta.c-prose-cta { align-items: flex-start; }
  .c-prose-cta.c-prose-cta .c-btn.c-btn { width: 100%; justify-content: center; }
}

/* =========================================================================
   PROSE — le bloc occupe TOUTE la colonne, seul le TEXTE est borné.
   Avant : `.c-prose` était plafonnée à 760px dans une colonne de ~1318px (58 %),
   d'où l'impression que la section ne faisait que la moitié de la page. On
   libère le conteneur (les filets de chapitre traversent donc toute la colonne,
   comme les séparateurs des autres sections) et on garde une mesure de lecture
   confortable sur les éléments de texte uniquement.
   ========================================================================= */

/* Le montant est en chiffres tabulaires MONOSPACE : l'espace de séparation des
   milliers y occupe la largeur d'un chiffre, ce qui donnait « 2␣␣␣499€ ».
   On la resserre pour retrouver une espace fine typographique. Sans effet sur
   les montants sans séparateur (999€). */

/* Les cartes de prix passent côte à côte dès ~720px : à 900px de viewport
   chacune ne fait plus que ~420px, et la liste en 2 colonnes y tombe à ~200px
   par colonne — les libellés se cassent sur 4 lignes. On replie la liste sur
   une colonne tant que la carte reste étroite (le repli n'existait qu'à 720px). */
@media (max-width: 1024px) {
  .l-price-features-cols.l-price-features-cols { grid-template-columns: 1fr; }
}

/* =========================================================================
   PROSE — chapitres en 2 colonnes (titre à gauche, corps à droite).
   Les .c-prose-chapter.c-prose-chapter sont construits par script.u-js à partir du markup plat.
   Objectif : occuper toute la colonne. Avant, le texte plafonnait à ~700px
   dans une colonne de ~1300px, laissant la moitié droite vide.
   ========================================================================= */
.c-prose-chapter.c-prose-chapter { display: grid; grid-template-columns: 1fr; }
.c-prose-chapter__body.c-prose-chapter__body { display: flex; flex-direction: column; gap: clamp(15px, 1.5vw, 19px); }

/* Le filet de chapitre appartient désormais au chapitre entier (il traverse
   les deux colonnes) et non plus au seul h2. */
.c-prose-chapter.c-prose-chapter {
  margin-top: clamp(46px, 6vw, 72px);
  padding-top: clamp(26px, 3.4vw, 40px);
  border-top: 1px solid var(--line);
}
.c-prose.c-prose > .c-prose-chapter.c-prose-chapter:first-child { margin-top: 0; padding-top: 0; border-top: 0; }
.c-prose.c-prose .c-prose-chapter.c-prose-chapter > .c-prose-chapter__head.c-prose-chapter__head > h2 {
  margin-top: 0;
  padding-top: 0;
  border-top: 0;
}

@media (min-width: 1000px) {
  .c-prose-chapter.c-prose-chapter {
    grid-template-columns: minmax(0, 0.62fr) minmax(0, 1fr);
    gap: clamp(36px, 3.6vw, 64px);
    align-items: start;
  }
  /* Le titre reste visible pendant la lecture du chapitre. */
  .c-prose-chapter__head.c-prose-chapter__head { position: sticky; top: calc(var(--header-h, 72px) + 24px); }
  /* Dans la colonne de droite, le texte occupe toute sa largeur : c'est la
     colonne elle-même qui borne désormais la mesure de lecture. */
  .c-prose-chapter__body.c-prose-chapter__body > p,
  .c-prose-chapter__body.c-prose-chapter__body > ul,
  .c-prose-chapter__body.c-prose-chapter__body > ol,
  .c-prose-chapter__body.c-prose-chapter__body > h3 { max-width: none; }
}

/* Le h2 n'est plus enfant direct de .c-prose.c-prose (il vit dans .c-prose-chapter__head.c-prose-chapter__head) :
   les sélecteurs `.c-prose > h2` ne matchaient plus et le titre perdait sa
   typographie ainsi que son index de chapitre. On re-cible. */
.c-prose.c-prose .c-prose-chapter__head.c-prose-chapter__head > h2 {
  counter-increment: prose-ch;
  margin: 0;
  padding: 0;
  border-top: 0;
  font-size: clamp(1.5rem, 2.9vw, 2.05rem);
  font-weight: 700;
  letter-spacing: -0.02em;
  line-height: 1.14;
  color: var(--text);
  text-wrap: balance;
  max-width: none;
}
.c-prose.c-prose .c-prose-chapter__head.c-prose-chapter__head > h2::before {
  content: counter(prose-ch, decimal-leading-zero);
  display: block;
  margin-bottom: 14px;
  font-family: var(--mono);
  font-size: 12px;
  font-weight: 400;
  letter-spacing: 0.08em;
  color: var(--brand-ink);
}

/* La CTA de milieu d'article sépare deux chapitres : elle doit traverser toute
   la colonne, comme les filets, et non rester à la mesure de lecture. */
.c-prose.c-prose > .c-prose-cta.c-prose-cta { max-width: none; }

/* La check-list empilait 4 items courts sur une colonne bornée à 60ch (~567px),
   avec ~750px de vide à droite (même défaut que les chapitres de prose). Sur
   grand écran elle passe en 2 colonnes PLEINE largeur : on lève d'abord le
   plafond `max-width:60ch` posé plus haut (sinon les 2 colonnes ne font que
   couper 567px en deux). Les items restent courts : lecture préservée, page
   raccourcie, largeur occupée. */
/* Entre 640 et 1000px : 1 colonne mais pleine largeur (on lève le plafond 60ch
   qui laissait du vide à droite ; les items sont un peu plus longs ici, 1 colonne
   large se lit mieux que 2 serrées). */
@media (min-width: 640px) {
  main > .c-subhero.c-subhero ~ .l-section.l-section .c-check-list.c-check-list,
  .c-check-list.c-check-list { max-width: none; }
}
/* Au-delà de 1000px : 2 colonnes pleine largeur. */
@media (min-width: 1000px) {
  main > .c-subhero.c-subhero ~ .l-section.l-section .c-check-list.c-check-list,
  .c-check-list.c-check-list {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    column-gap: clamp(32px, 3.5vw, 64px);
  }
}

/* =========================================================================
   THÈME CLAIR — délimitation des cartes.
   En clair, price-card / presta-card / feature-card avaient un fond identique
   à la page (contraste 1.000) et feature-card n'avait aucune bordure → cartes
   qui se fondent dans le fond. On leur donne une présence subtile (bordure fine
   + ombre douce façon Stripe), SANS toucher aux tokens globaux (--color-d2 /
   --surface-border piloteraient header/footer/mockups → effets de bord). Scopé
   [data-theme="light"] uniquement ; la carte « Expert » vedette garde son liseré.
   ========================================================================= */

/* =========================================================================
   MAILLAGE INTERNE LOCAL — chips de liens vers villes proches / métiers liés,
   sur les 19 landing pages. Style aéré (DA), pastilles à filet fin.
   ========================================================================= */

/* assets/css/forms.css */
/* =========================================================
   BEELY STUDIO — Pages formulaire (contact / devis) + merci
   Styles de champs d'après la maquette Figma, thème clair/sombre
   (s'appuie sur les tokens de styles.css)
   ========================================================= */

/* L'attribut hidden doit toujours l'emporter sur les display: flex/inline-flex */

/* Bordure des champs au repos (un peu plus marquée en clair, champs blancs sur blanc) */

/* ---------- Layout 2 colonnes (gauche fixe 50vw/100vh, droite scrollable) ---------- */

/* Barre du haut (retour accueil + thème) */

/* Accroche */

/* ---------- Formulaire ---------- */

/* Indicateur d'étapes */

/* ---------- Animations ---------- */
@keyframes cfIn { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: translateY(0); } }
/* Champs : entrée en cascade à chaque affichage d'étape (et au chargement) */
/* Choix (cartes radio/checkbox) : cascade interne */
/* Titre + description de l'étape : ré-animés à chaque changement */
/* Select ouvert : l'étape (et son dropdown) passe au-dessus des boutons */

@media (prefers-reduced-motion: reduce) {
  .c-contact-form__step.c-contact-form__step:not([hidden]) > *,
  .c-contact-form__step.c-contact-form__step:not([hidden]) .c-choice.c-choice,
  .c-contact-form__title.c-contact-form__title.is-anim, .c-contact-form__desc.c-contact-form__desc.is-anim { animation: none !important; }
}

/* Champs */  /* le <legend> ne reçoit pas le gap flex du .c-form-field.c-form-field -> on aligne sur l'écart des champs texte (6px) */

/* État erreur */

/* Select custom */

/* ---------- Select custom (déroulant stylé, JS) ---------- */            /* on retire le chevron natif */

/* ---------- Choix en cartes (radios / checkboxes groupés) ---------- */
/* marqueur */
/* état sélectionné */

/* Consentement simple */

/* ---------- Navigation du formulaire ---------- */

/* ---------- Thème clair : colonne droite blanche + champs blancs (hairline marquée) ---------- */   /* blanc pur */

/* ---------- Responsive ---------- */
@media (max-width: 640px) {
  /* Aside compact : on garde logo + retour accueil + toggle, on masque l'argumentaire */
}
@media (max-width: 480px) {
  .l-form-row.l-form-row { flex-direction: column; }
}

/* =========================================================
   PAGE MERCI
   ========================================================= */
.c-thanks__title.c-thanks__title .u-accent { color: var(--color-primary); }

/* <style> */
/* a-propos.html */

    /* ---- header ---- */

    /* ---- parcours : stepped narrative on a connector line ---- */

    /* ---- grands comptes : hairline row list ---- */

    /* ---- stat row : big mono figures, vertical hairlines ---- */

    /* ---- stack / toolbelt : grouped mono chips, hairline rows ---- */

    @media(max-width:720px){
      .c-apropos__steps.c-apropos__steps{grid-template-columns:1fr;gap:0}
      .c-apropos__steps.c-apropos__steps::before{top:0;bottom:0;left:5px;right:auto;width:1px;height:auto}
      .c-apropos-step.c-apropos-step{padding:0 0 26px 26px}
      .c-apropos-step.c-apropos-step:last-child{padding-bottom:0}
      .c-apropos-step__dot.c-apropos-step__dot{position:absolute;left:0;top:2px;margin:0}
      .c-apropos__stats.c-apropos__stats{grid-template-columns:1fr}
      .c-apropos-stat.c-apropos-stat+.c-apropos-stat.c-apropos-stat{border-left:0;border-top:1px solid var(--line)}
      .c-apropos-tool.c-apropos-tool{grid-template-columns:1fr;gap:14px}
    }
    @media(max-width:400px){
      .c-apropos__client.c-apropos__client{flex-wrap:wrap;gap:2px 16px}
      .c-apropos-client__role.c-apropos-client__role{margin-left:0;text-align:left}
    }
  
/* <style> */
/* creation-site-internet.html */

    /* header */

    /* interlocuteur unique — inline note, no box */

    /* phase board */

    /* the connective spine with nodes */

    @media (max-width:860px){
      .c-methode__grid.c-methode__grid{grid-template-columns:1fr}
      .c-methode__rail.c-methode__rail,.c-methode__nodes.c-methode__nodes{display:none}
      .c-methode__phase.c-methode__phase{padding:26px 0 0 20px;position:relative}
      .c-methode__phase.c-methode__phase + .c-methode__phase.c-methode__phase{padding-left:20px}
      .c-methode__phase.c-methode__phase{border-left:1px solid var(--line)}
      .c-methode__phase.c-methode__phase::before{content:"";position:absolute;left:-5px;top:30px;width:9px;height:9px;border-radius:50%;background:var(--panel);border:1.6px solid var(--line-strong)}
      .c-methode__phase.c-methode__phase.is-current::before{border-color:var(--brand);background:var(--brand-t)}
      .c-methode__phase.c-methode__phase:first-child{padding-top:0}
      .c-methode__phase.c-methode__phase:first-child::before{top:4px}
    }
    @media (max-width:520px){
      .c-methode__row.c-methode__row{grid-template-columns:1fr 72px;grid-template-areas:"label val" "track track";row-gap:10px}
      .c-methode__row-label.c-methode__row-label{grid-area:label}
      .c-methode__row-value.c-methode__row-value{grid-area:val}
      .c-methode__track.c-methode__track{grid-area:track}
      .c-methode__scale.c-methode__scale{grid-template-columns:1fr}
    }
  
/* <style> */
/* erreurs-creation-site-internet.html */

    @media (max-width:720px){
      .c-erreurs__row.c-erreurs__row{grid-template-columns:44px 1fr;row-gap:20px;column-gap:20px}
      .c-erreurs__idx.c-erreurs__idx{grid-row:1;grid-column:1}
      .c-erreurs__cell.c-erreurs__cell.is-err{grid-column:2}
      .c-erreurs__cell.c-erreurs__cell.is-fix{grid-column:2;border-left:0;padding-left:0;margin-left:0;padding-top:16px;border-top:1px dotted var(--line)}
    }
  
/* <style> */
/* index.html */

        /* ---------- header ---------- */

        /* ---------- garanties : airy hairline list, two aligned columns ---------- */

        /* ---------- preuves : big mono figures, vertical hairlines, no boxes ---------- */

        /* ---------- entrance (gated on html.u-js, staggered) ---------- */

        /* ---------- responsive ---------- */
        @media(max-width:440px){
          .c-why__proofs.c-why__proofs{grid-template-columns:1fr}
          .c-why__proof.c-why__proof{padding:16px 0}
          .c-why__proof.c-why__proof+.c-why__proof.c-why__proof{border-left:0;border-top:1px solid var(--line)}
          .c-why__proof.c-why__proof:nth-child(even){padding-left:0}
        }

        /* ---------- reduced-motion guard : everything visible ---------- */
        @media (prefers-reduced-motion: reduce){
          html.u-js .c-why__head.c-why__head,
          html.u-js .c-why__kick.c-why__kick,
          html.u-js .c-why__h3.c-why__h3,
          html.u-js .c-why__gain.c-why__gain,
          html.u-js .c-why__proof.c-why__proof,
          html.u-js .c-why__note.c-why__note{opacity:1!important;transform:none!important;transition:none!important}
        }
      
/* <style> */
/* merci.html */
  
/* <style> */
/* prix-creation-site-internet.html */

          /* ---------- header ---------- */

          /* ---------- 01 · budget scale (data-viz, light rail) ---------- */

          /* ---------- 01 · tier columns (borderless, vertical hairlines) ---------- */

          /* ---------- 01 · 6 factors (open index, hairline tops) ---------- */

          /* ---------- 02 · matrix (hairline rows + one tinted column) ---------- */

          /* ---------- 03 · checklist + recurring fees (open) ---------- */

          @media(max-width:820px){
            .c-prix__foot.c-prix__foot{grid-template-columns:1fr;gap:38px}
          }
          @media(max-width:440px){
            .c-prix__mark.c-prix__mark{font-size:10px}
            .c-prix__seglabels.c-prix__seglabels span{font-size:9.5px}
          }
        
/* <style> */
/* referencement-local-google.html */

    /* ONE framed UI object: faux Google local result */

    /* NAP one-liner */

    @media (max-width:720px){
      .c-seo__ui.c-seo__ui{grid-template-columns:1fr}
      .c-seo__map.c-seo__map{border-left:0;border-top:1px solid var(--line);min-height:180px}
      .c-seo__row.c-seo__row{grid-template-columns:32px 1fr;gap:14px}
      .c-seo__metric.c-seo__metric{grid-column:2;text-align:left;margin-top:4px}
      .c-seo__metric.c-seo__metric b{font-size:18px}
    }
  
/* <style> */
/* refonte-site-internet.html */

    /* AVANT / APRES */
    /* AVANT : desature, tasse */
    /* APRES : net, une touche de marque */

    /* SIGNAUX */

    /* SEO migration line */
  
/* <style> */
/* site-internet-mobile-first.html */
    @media(min-width:860px){.c-mobile__pair.c-mobile__pair{grid-template-columns:minmax(0,1.15fr) minmax(0,.85fr);gap:56px}}
    @media(min-width:520px){.c-mobile__phone.c-mobile__phone{width:150px;right:12px}}
    @media(min-width:760px){.c-mobile__duo.c-mobile__duo{grid-template-columns:1fr 1fr}}
    @media(min-width:760px){
      .c-mobile__pane.c-mobile__pane{padding-right:40px}
      .c-mobile__pane.c-mobile__pane+.c-mobile__pane.c-mobile__pane{padding-right:0;padding-left:40px;border-left:1px solid var(--line)}
    }
    @media(max-width:759px){.c-mobile__pane.c-mobile__pane+.c-mobile__pane.c-mobile__pane{margin-top:28px}}
  
/* <style> */
/* site-vitrine-ou-site-ecommerce.html */

    /* Header */

    /* Ledger */

    /* Mobile-only "ou" cue (hidden on desktop; won't occupy a grid cell) */

    /* Decision hint */

    /* Hybrid note */

    @media(max-width:560px){
      .c-compare__head.c-compare__head{display:none}
      .c-compare__row.c-compare__row{grid-template-columns:1fr;padding:8px 0}
      .c-compare__cell.c-compare__cell{padding:11px 0}
      .c-compare__cell--crit.c-compare__cell--crit{padding-top:18px;color:var(--brand-ink);font-size:12px}
      .c-compare__cell--ecom.c-compare__cell--ecom{border-left:0}
      .c-compare__tag.c-compare__tag{display:block;font-family:var(--mono);text-transform:uppercase;letter-spacing:.06em;font-size:10px;color:var(--text-3);margin-bottom:5px}
      .c-compare__ou-mark.c-compare__ou-mark{display:flex;align-items:center;justify-content:center;gap:12px;margin:9px 0 3px;font-family:var(--mono);text-transform:uppercase;letter-spacing:.08em;font-size:10px;color:var(--text-3);line-height:1}
      .c-compare__ou-mark.c-compare__ou-mark::before,.c-compare__ou-mark.c-compare__ou-mark::after{content:"";flex:1;height:1px;background:var(--line);max-width:64px}
      .c-compare__decide-row.c-compare__decide-row{grid-template-columns:1fr;gap:8px}
    }
  
/* <style> */
/* site-vitrine.html */

/* ==========================================================================
   Pré-états d'entrée — SOUS `.u-js` UNIQUEMENT
   ========================================================================== */

/* Ces douze classes portaient `opacity: 0` dans leur PANNEAU Bricks. Un panneau
   ne sait pas viser un ancêtre : le masque s'appliquait donc aussi quand le
   script du site ne tourne pas, alors que le thème conditionne déjà ses
   87 autres pré-états à `.u-js` (functions.php, script de tête).

   Mesuré sans JavaScript le 07/08/2026 :

     /site-vitrine/            43 blocs invisibles   2 639 k px²
     /a-propos/                33 blocs invisibles   1 263 k px²
     /refonte-site-internet/   14 blocs invisibles   1 542 k px²

   Titres de page, accroches et H2 compris — la §2 dit exactement l'inverse :
   « Rien d'essentiel ne dépend de l'animation. Sans JavaScript, le contenu doit
   être lisible. »

   Le masque est donc retiré des panneaux et recréé ici, où il peut porter sa
   condition. Douze classes seulement : ce sont celles dont un révélateur existe
   et fonctionne — mesuré instance par instance, 158 `c-feature-card` sur 158,
   46 `c-presta-card` sur 46. Les quinze autres n'en avaient aucun, et leur
   masque était de la perte sèche : il ne revient pas.

   `prefers-reduced-motion` est respecté par la seconde condition — un mouvement
   imposé à qui l'a refusé peut déclencher un malaise vestibulaire (WCAG 2.3.3),
   et sans elle le contenu resterait masqué pour ces personnes. */

@media (prefers-reduced-motion: no-preference) {
  .u-js .c-presta-card:not(.is-in):not(.is-visible):not(.is-revealable),
  .u-js .c-feature-card:not(.is-in):not(.is-visible):not(.is-revealable),
  .u-js .c-stats__item:not(.is-in):not(.is-visible):not(.is-revealable) {
    opacity: 0;
    transform: translateY(14px);
  }

  .u-js .c-apropos__eyebrow:not(.is-in):not(.is-visible):not(.is-revealable),
  .u-js .c-apropos__kicker:not(.is-in):not(.is-visible):not(.is-revealable),
  .u-js .c-apropos__chip:not(.is-in):not(.is-visible):not(.is-revealable),
  .u-js .c-apropos__client:not(.is-in):not(.is-visible):not(.is-revealable),
  .u-js .c-apropos-step__dot:not(.is-in):not(.is-visible):not(.is-revealable),
  .u-js .c-apropos-tool:not(.is-in):not(.is-visible):not(.is-revealable),
  .u-js .c-refonte__bar:not(.is-in):not(.is-visible):not(.is-revealable),
  .u-js .c-refonte__delta:not(.is-in):not(.is-visible):not(.is-revealable),
  .u-js .c-refonte__row:not(.is-in):not(.is-visible):not(.is-revealable) {
    opacity: 0;
  }
}

/* Le flux « avant → après » de la page refonte : son pré-état n'a pas de
   condition d'état révélé — il est annulé par l'animation qui suit. Sans
   JavaScript, l'animation ne part pas et les trois libellés du schéma
   (`/accueil.html`, `301`, `/nouvelle-page`) n'existent pas. Six mille pixels
   carrés, et le schéma perd son sens : il ne reste que des flèches.

   Le sélecteur du bloc global est minifié et introuvable à l'identique ; on le
   contre ici, où la feuille charge en dernier. Spécificité relevée à cinq
   classes pour battre le 0-4-0 d'origine sans recourir à `!important`. */
html:not(.u-js) .c-refonte.c-refonte .c-refonte__flow.c-refonte__flow > * {
  opacity: 1;
  animation: none;
}

/* Cibles tactiles : 44 px au doigt, quel que soit le contexte.

   Mesuré le 07/08/2026 à 375 px : le même `.c-btn` sortait à 19, 34 ou 50 px
   selon l'endroit — son rembourrage est à zéro et sa hauteur ne vient que de
   `height: var(--control-h)`, donc elle dérive dès qu'une règle de contexte
   redéfinit la taille de police. Ce n'est pas une variante assumée.

   Le réglage vit dans le panneau (`_heightMin:tablet_portrait`), et il suffit
   partout SAUF pour les boutons que le panneau n'atteint pas — un `.c-btn`
   écrit en HTML brut ne porte pas de classe `brxe-<id>`, et le sélecteur
   `.c-btn.brxe-text-basic` de Bricks ne le rattrape pas toujours. Cette règle
   est le filet : elle vise la classe seule, et la feuille charge en dernier.

   24 px est le minimum de WCAG 2.5.8 ; 44 est la recommandation de niveau AAA,
   et la surface réelle d'un pouce. Un bouton de 24 px se rate une fois sur
   cinq — c'est une conversion perdue, pas seulement un critère.

   Rien au-dessus de 900 px : à la souris, 34 px est une densité légitime, et
   c'est celle de la maquette validée. */
@media (max-width: 900px) {
  /* `!important`, et c'est ici qu'il se justifie.

     Mesuré : ce plancher est battu sur certains boutons alors qu'aucune règle
     concurrente ne le déclare — les éléments concernés portent un `id`
     (`#brxe-…`), que Bricks emploie pour ses styles d'instance et qui bat toute
     classe à 1-0-0 (§7). Un `min-height` d'accessibilité n'a pas à perdre
     contre une décision de mise en page : il est le plancher, pas une
     préférence. Vérifié par la mesure — 19 px avant, 45 après. */
  .c-btn.c-btn,
  .c-legal__back.c-legal__back,
  .c-contact-intro__back.c-contact-intro__back,
  .l-section__more.l-section__more {
    min-height: 44px !important;
    display: inline-flex;
    align-items: center;
  }

  /* Le fil d'Ariane : ses liens font 20 px et vivent dans une ligne. On leur
     donne la hauteur par le rembourrage, sans casser le retour à la ligne. */
  .c-breadcrumb.c-breadcrumb a {
    display: inline-flex;
    align-items: center;
    min-height: 32px;
    padding-block: 6px;
  }
}

/* La bannière d'appel à l'action ne rembourre pas ce que sa section rembourre
   déjà.

   `c-cta__inner--banner` porte `padding-top: clamp(40px, 6vw, 76px)` dans son
   panneau, et la section qui l'accueille porte déjà ses 72 px. Sur 27 pages
   une règle enfant (`.l-section > .c-cta__inner`) annule ce doublon ; sur
   l'accueil un conteneur intermédiaire l'en empêche, et le sélecteur enfant ne
   traverse pas.

   Mesuré le 07/08/2026 à 1440 px : 148 px de vide au-dessus du titre contre
   70 en dessous, quand /tarifs/ — structurellement voisine — est centrée. Une
   seule page sur vingt-huit, donc l'exception, pas la règle.

   Descendant et non enfant : c'est précisément ce qui manquait. Deux fois la
   classe pour passer à 0-4-0 et battre le panneau, sans `!important`. */
.l-section .c-cta__inner--banner.c-cta__inner--banner {
  padding-top: 0;
}

/* =========================================================================
   CIBLES TACTILES DU PIED DE PAGE — réclamer le vide, pas en ajouter
   ========================================================================= */

/* Mesuré le 08/08/2026 à 375 px : 26 liens de pied de page hauts de 20 px, sur
   chaque page. WCAG 2.5.8 demande 24 px au niveau AA, et 44 est la valeur qui
   correspond à la surface d'un pouce.

   Les monter à 44 px ajouterait plus de 600 px de pied sur mobile, et le pied
   est déjà aéré : l'espace EXISTE entre les liens, il n'est simplement pas
   cliquable. Le rembourrage le réclame, la marge négative le rend à la mise en
   page — la cible passe de 20 à 32 px, et le rythme visuel ne bouge pas d'un
   pixel.

   32 et non 44 : au-delà, le rembourrage dépasse l'espace disponible et il
   faudrait vraiment allonger le pied. 32 px dégage confortablement le seuil AA,
   et le critère prévoit précisément l'espacement comme équivalent. */
@media (max-width: 900px) {
  .c-footer-col__link.c-footer-col__link,
  .c-site-footer__mail.c-site-footer__mail,
  .c-footer-locations a {
    display: block;
    padding-block: 6px;
    margin-block: -6px;
  }

  /* Les liens par ville sont en ligne, côte à côte : c'est l'écart HORIZONTAL
     qui manque, et une marge négative verticale n'y changerait rien. */
  .c-footer-locations a {
    display: inline-block;
    padding-inline: 4px;
    margin-inline: -4px;
  }

  /* Les pilules de maillage font 42 px — deux pixels du seuil, pour un
     rembourrage de 8 px sur une ligne de 24. Les porter à 44 ne coûte rien et
     retire dix-neuf cibles de la liste par page. */
  .c-linklist a {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
  }
}

/* La note de bas de schéma court sur 913 px — ~100 caractères par ligne, sur
   deux lignes pleines. C'est de la prose, pas une étiquette : elle relève du
   même plancher que les paragraphes d'article (68ch ≈ 85 caractères).
   La borne, et non un raccourcissement du texte : la phrase dit ce qu'elle doit
   dire, c'est la colonne qui est trop large. */
.c-vitrine__choice.c-vitrine__choice p {
  max-width: 68ch;
}
