/* ============================================================================
   Oltanis — feuille commune à toutes les pages.
   S'appuie strictement sur les tokens de colors_and_type.css.
   Charte : trois tons (blanc / encre / cobalt), Bricolage condensé display,
   Geist texte, Geist Mono étiquettes. Pas d'ombre (sauf header au scroll,
   demandé au brief), angles vifs, esthétique tableau / filets hairline.

   Issue du découpage de landing.css, qui pesait 105 Ko et partait sur les
   vingt-sept pages alors que 82 à 92 % n'y servait à rien hors de l'accueil.
   Ce qui ne sert QUE à l'accueil vit désormais dans home.css, chargé par
   index.php seulement, après ce fichier.

   Le partage a été établi en testant chaque sélecteur contre le DOM réel des
   vingt-sept pages, pseudo-classes d'interaction et classes d'état retirées
   pour qu'une règle d'état suive l'élément qu'elle habille. Une règle vue
   nulle part reste ici, par prudence.

   ATTENTION À LA CASCADE. home.css étant chargé APRÈS ce fichier, une règle
   déplacée passe derrière toutes celles d'ici : à spécificité égale, le
   vainqueur change. Vingt-huit règles propres à l'accueil sont donc restées
   ici pour cette seule raison — leur déplacement modifiait un interlettrage
   (.trustband-item) ou une taille de police (.module-cat). Avant de déplacer
   une règle d'un fichier à l'autre, vérifier qu'aucune règle postérieure ne
   vise le même sélecteur avec la même propriété.
   ========================================================================== */
* { box-sizing: border-box; }
html { scroll-behavior: smooth; }
body { margin: 0; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; }}
a { color: inherit; }

/* Lien d'évitement — accessibilité clavier (visible uniquement au focus) */
.skip-link { position: absolute; left: 12px; top: -64px; z-index: 200; background: var(--encre); color: var(--blanc); font-family: var(--font-sans); font-weight: 500; font-size: 14px; padding: 10px 16px; border-radius: var(--radius-ui); text-decoration: none; transition: top var(--dur-ui) var(--ease); }
.skip-link:focus { top: 12px; }

/* --------------------------------------------------------------------------
   Bandeau d'état, au-dessus du header et sur toutes les pages.

   Le site marque bien chaque brique non ouverte — « prochainement » sur
   l'offre commerçant, GPAO « en cours de développement », facturation
   électronique « pas encore ouverte à la souscription ». Mais rien ne disait à
   qui arrive directement sur /tarifs ou sur une page solutions que l'ENTREPRISE
   elle-même n'est pas ouverte : la grille de prix, les 40 modules et le bouton
   « Demander une démo » laissaient croire à un service qu'on peut souscrire.

   Permanent et non refermable, par choix : une bannière qu'on ferme ne se
   revoit plus, et ce sont justement les visites de retour, celles où l'on va
   sur les tarifs, qu'il faut informer. Il est en HTML statique, donc lisible
   sans JavaScript.
   -------------------------------------------------------------------------- */
.prelaunch { background: var(--ink-2, #14141d); border-bottom: 1px solid var(--blanc-20); }
.prelaunch p { margin: 0; padding-top: 10px; padding-bottom: 10px; font-size: 13px; line-height: 1.45; color: var(--blanc-80); }
.prelaunch b { font-weight: 600; color: var(--blanc); }
.prelaunch a { color: var(--accent-display); text-underline-offset: 2px; white-space: nowrap; }
.prelaunch a:hover { color: var(--blanc); }
@media (max-width: 559px) {
  .prelaunch p { font-size: 12.5px; padding-top: 9px; padding-bottom: 9px; }
}

.page { width: 100%; max-width: var(--max-page); margin: 0 auto; padding-left: 24px; padding-right: 24px; }
@media (min-width: 768px) { .page { padding-left: 48px; padding-right: 48px; }}
@media (min-width: 1100px) { .page { padding-left: 64px; padding-right: 64px; }}
.w-full { width: 100%; }

/* ---- Fil d'Ariane — composant de site ------------------------------------
   Vivait dans pages.css, que alto.html ne charge pas : le fil y sortait brut,
   en Geist 17 px souligné, au lieu du mono capitales de la charte. Il remonte
   ici, où toutes les pages qui l'emploient le voient. Valeurs du thème sombre
   directement, sans repasser par --encre-NN écrit pour un fond blanc. */
.crumb { border-bottom: 1px solid var(--hairline); }
.crumb .page { display: flex; align-items: center; gap: 10px; padding-top: 16px; padding-bottom: 16px;
  font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--blanc-60); flex-wrap: wrap; }
.crumb a { color: var(--blanc-60); text-decoration: none; transition: color var(--dur-fast) var(--ease); }
.crumb a:hover { color: var(--accent-texte); text-decoration: underline; text-underline-offset: 3px; }
.crumb .sep { color: var(--blanc-60); }        /* .3 tombait à 2,57:1 : barre invisible */
.crumb .here { color: var(--blanc); }

/* ---- Liens dans le texte courant -----------------------------------------
   `a { color: inherit }` laisse chaque lien de paragraphe prendre la couleur de
   son conteneur : selon la page, le même lien sortait en #9db4ff souligné, en
   blanc 82 % souligné, ou en blanc pur — indiscernable d'un mot en gras. Vingt
   et un liens portaient un style en ligne pour rattraper le coup, et pas tous
   la même valeur. On pose la règle une fois. */
.seo-lead a, .featrow-b a, .featrow-list a,
.assure-b a, .olto-cta-note a, .price-model a, .probleme-cta-note a,
.ms-grid p a, .choice-steps li p a {
  color: var(--accent-texte);
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-thickness: 1px;
}
/* Lien d'action d'un en-tête de section (« Toutes les solutions → ») : même
   accent, mais sans soulignement — c'est une action, pas une note de lecture. */
/* « Toutes les solutions → », « Tout le blog → » : une action à part entière,
   posée seule dans l'en-tête de section — pas un lien au fil du texte, donc pas
   couverte par l'exception des liens en ligne. En display:inline sans marge
   interne, sa zone tactile faisait 14 px de haut. Rendue cliquable sur toute sa
   hauteur, avec un retrait négatif pour ne pas déplacer la mise en page. */
.section-pag a { color: var(--accent-texte); text-decoration: none;
  display: inline-block; padding: 8px 4px; margin: -8px -4px; }
.section-pag a:hover { text-decoration: underline; text-underline-offset: 3px; }
/* Alto garde ses liens rouges : univers scopé, accent volontairement distinct. */
.alto-uni .seo-lead a, .alto-uni a.alto-link { color: var(--rouge-vif); }

/* ---- Tableaux larges : indiquer qu'ils défilent --------------------------
   Le comparatif (min-width 680 px) et la grille tarifaire (760 px) sont posés
   dans un conteneur overflow-x:auto, mais rien ne le signalait : en 375 px, le
   comparatif laissait 52 % de sa largeur hors écran — dont toute la colonne
   Oltanis, c'est-à-dire l'argument de la page. Ombres de défilement en CSS pur
   (deux calques `local` qui masquent, deux calques `scroll` qui portent
   l'ombre) : elles n'apparaissent que du côté où il reste à défiler.
   Les deux composants vivaient chacun dans le <style> de sa page, avec des
   réglages différents ; ils partagent désormais le même comportement. */
.cmp-wrap, .pt-wrap {
  background-color: var(--ink-2);
  background-image:
    linear-gradient(to right, var(--ink-2), rgba(20,20,29,0)),
    linear-gradient(to left,  var(--ink-2), rgba(20,20,29,0)),
    linear-gradient(to right, rgba(0,0,0,0.5), rgba(0,0,0,0)),
    linear-gradient(to left,  rgba(0,0,0,0.5), rgba(0,0,0,0));
  background-position: 0 0, 100% 0, 0 0, 100% 0;
  background-repeat: no-repeat;
  background-size: 26px 100%, 26px 100%, 18px 100%, 18px 100%;
  background-attachment: local, local, scroll, scroll;
}

/* ---- Reconstructed wordmark ---- */
.wm { font-family: var(--font-display); font-weight: 800; letter-spacing: -0.045em; text-transform: uppercase; display: inline-flex; align-items: baseline; user-select: none; line-height: 0.95; }
.wm .accent-i { font-style: italic; color: var(--cobalt); }

/* ---- Mono kicker helper ---- */
.kick { font-family: var(--font-mono); font-weight: 400; text-transform: uppercase; letter-spacing: 0.14em; color: var(--encre-60); }
.section-encre .kick, .footer .kick { color: var(--blanc-60); }

/* ===========================================================================
   Buttons
   ========================================================================== */
.btn { position: relative; display: inline-flex; align-items: center; justify-content: center; gap: 10px; border-radius: var(--radius-ui); font-family: var(--font-sans); font-weight: 500; line-height: 1; border: 1px solid transparent; cursor: pointer; white-space: nowrap; text-decoration: none; transition: background var(--dur-ui) var(--ease), color var(--dur-ui) var(--ease), border-color var(--dur-ui) var(--ease), box-shadow var(--dur-ui) var(--ease), transform var(--dur-ui) var(--ease-spring); }
.btn:active { transform: translateY(1px) scale(0.99); }
@media (prefers-reduced-motion: no-preference) { .btn .arrow { transition: transform 220ms var(--ease-spring); }}
.btn:hover .arrow { transform: translateX(4px); }
.btn:focus-visible { outline: var(--focus-ring); outline-offset: var(--focus-offset); }
.btn:focus-visible .arrow { transform: translateX(4px); }
.btn-md { height: 42px; padding: 0 20px; font-size: 14px; }
.btn-lg { height: 52px; padding: 0 30px; font-size: 16px; }
.btn-primary { background: var(--grad-cobalt); color: var(--blanc); box-shadow: 0 4px 14px -6px rgba(24,70,220,0.5); }
.btn-primary:hover { box-shadow: var(--shadow-cobalt); transform: translateY(-2px); }
.btn-ghost { background: transparent; color: var(--encre); border-color: var(--encre); }
.btn-ghost:hover { background: var(--encre); color: var(--blanc); transform: translateY(-2px); box-shadow: var(--shadow-md); }
.btn-reverse { background: var(--blanc); color: var(--encre); }
.btn-reverse:hover { background: var(--cobalt); color: var(--blanc); transform: translateY(-2px); box-shadow: var(--shadow-cobalt); }
.btn-ghost-light { background: transparent; color: var(--blanc); border-color: var(--blanc-20); }
.btn-ghost-light:hover { background: var(--blanc); color: var(--encre); transform: translateY(-2px); }

/* ===========================================================================
   Header — sticky, shrinks + subtle shadow on scroll
   ========================================================================== */
.header { position: sticky; top: 0; z-index: 60; background: rgba(255,255,255,0.72); backdrop-filter: blur(16px) saturate(140%); -webkit-backdrop-filter: blur(16px) saturate(140%); border-bottom: 1px solid var(--hairline); transition: box-shadow var(--dur-ui) var(--ease), background var(--dur-ui) var(--ease); }
.header.is-scrolled { box-shadow: var(--shadow-md); background: rgba(255,255,255,0.85); }
/* Barre de progression de lecture (injectée par landing.js, présente sur toutes les pages) */
.scroll-progress { position: fixed; top: 0; left: 0; height: 3px; width: 100%; z-index: 80; background: var(--grad-cobalt); transform: scaleX(0); transform-origin: 0 50%; transition: transform 80ms linear; will-change: transform; pointer-events: none; }
@media (prefers-reduced-motion: reduce) { .scroll-progress { display: none; }}
.header-bar { display: flex; align-items: center; justify-content: space-between; gap: 24px; height: 76px; transition: height var(--dur-ui) var(--ease); }
.header.is-scrolled .header-bar { height: 62px; }
.header-brand { display: inline-flex; align-items: center; gap: 0; font-size: 22px; }
.nav { display: none; align-items: center; gap: 30px; }
.nav a { font-size: 14px; color: var(--encre-85); text-decoration: none; position: relative; padding: 4px 0; transition: color var(--dur-fast) var(--ease); white-space: nowrap; }
/* Soulignement en transform (compositor) : entre par la gauche, sort par la droite */
.nav a::after { content: ""; position: absolute; left: 0; right: 0; bottom: -2px; height: 2px; background: var(--cobalt); transform: scaleX(0); transform-origin: 100% 50%; }
@media (prefers-reduced-motion: no-preference) { .nav a::after { transition: transform var(--dur-ui) var(--ease); }}
.nav a:hover { color: var(--encre); }
.nav a:hover::after, .nav a:focus-visible::after { transform: scaleX(1); transform-origin: 0 50%; }
.header-cta { display: none; }
.burger { display: inline-flex; height: 42px; width: 42px; align-items: center; justify-content: center; border: 1px solid var(--encre); background: transparent; border-radius: var(--radius-ui); font-family: var(--font-mono); font-size: 17px; cursor: pointer; color: var(--encre); }
/* Bascule desktop : placée APRÈS les bases pour que la cascade s'applique.
   Le seuil est passé de 940 à 1120 px en ajoutant « Notes de mise à jour » au
   menu. Mesuré : à 940 px, l'accueil ne laissait que 76 px de marge pour un
   libellé qui en demande 180 — le menu passait sur deux lignes dans une barre
   haute de 76 px, et l'accueil gagnait une barre de défilement horizontale.
   Aucun huitième élément ne tient à 940 px, même court : « Nouveautés » aurait
   encore débordé de 29 px. Entre 1120 et 1320 px, l'espacement est resserré pour
   garder de l'air. En dessous, c'est le menu au burger — qui porte le même lien. */
@media (min-width: 1120px) { .nav { display: flex; } .header-cta { display: inline-flex; } .burger { display: none; }}
@media (min-width: 1120px) and (max-width: 1320px) { .nav { gap: 22px; }}
.nav-mobile { display: none; flex-direction: column; gap: 4px; padding-top: 12px; padding-bottom: 24px; border-top: 1px solid var(--hairline); }
.nav-mobile.is-open { display: flex; }
.nav-mobile a { font-size: 17px; padding: 12px 4px; text-decoration: none; border-bottom: 1px solid var(--hairline); }
.nav-mobile .btn { margin-top: 16px; }

/* ===========================================================================
   Sections
   ========================================================================== */
.section { padding-top: clamp(60px, 9vw, 112px); padding-bottom: clamp(60px, 9vw, 112px); background: var(--blanc); color: var(--encre); }
/* Respiration renforcée réservée aux sections d'ouverture et de clôture.
   Ces règles d'ID ont été écrites pour la page d'accueil. Un sélecteur d'ID
   (1,0,0) écrase .section-tight (0,1,0) : sur les pages internes, la section
   FAQ passait donc de 56 px à 144 px, seule à rompre la cadence de la page.
   On les scope à l'accueil, seule page à porter .home-doc. */
@media (min-width: 1200px) {
  .section-cobalt,
  .home-doc #probleme,
  .home-doc #faq { padding-top: 144px; padding-bottom: 144px; }}
.section-cobalt { background: var(--cobalt); color: var(--blanc); }
.section-tight { padding-top: clamp(44px, 5vw, 56px); padding-bottom: clamp(44px, 5vw, 56px); }
.section-head { display: flex; align-items: flex-end; justify-content: space-between; gap: 24px; border-bottom: 1px solid var(--hairline); padding-bottom: 18px; margin-bottom: 56px; }
@media (min-width: 1200px) { .section-head { margin-bottom: 68px; }}
.section-head-left { max-width: 60ch; }
.section-title { margin: 16px 0 0; font-family: var(--font-display); font-weight: 800; letter-spacing: -0.045em; font-size: clamp(34px, 5vw, 60px); line-height: 1.0; }
.section-intro { margin: 24px 0 0; max-width: 60ch; font-size: clamp(16px, 2vw, 19px); line-height: 1.55; color: var(--encre-80); }
.section-pag { font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.14em; color: var(--encre-60); white-space: nowrap; }
@keyframes floaty { 0%,100% { transform: translateY(0); } 50% { transform: translateY(-10px); } }
@keyframes pulse { 0%,100% { opacity: 1; } 50% { opacity: 0.35; } }
.targets-lab { font-family: var(--font-mono); letter-spacing: 0.14em; text-transform: uppercase; color: var(--encre-60); padding-right: 28px; }
.trustband-lab { font-family: var(--font-mono); letter-spacing: 0.14em; text-transform: uppercase; color: var(--encre-60); }
.trustband-item { display: inline-flex; align-items: center; gap: 9px; font-family: var(--font-mono); letter-spacing: 0.06em; text-transform: uppercase; color: var(--encre-80); }

.module-card { position: relative; background: var(--blanc); padding: 24px; min-height: 196px; display: flex; flex-direction: column; justify-content: space-between; cursor: default; transition: background var(--dur-ui) var(--ease), transform var(--dur-ui) var(--ease), box-shadow var(--dur-ui) var(--ease); }
.module-card:hover { transform: translateY(-4px); box-shadow: var(--shadow-md); z-index: 1; }
.module-cat { font-family: var(--font-mono); font-size: 9px; letter-spacing: 0.12em; text-transform: uppercase; color: var(--accent-texte); }
.assure { position: relative; overflow: hidden; background: var(--blanc); border: 1px solid var(--hairline); padding: 28px 26px; display: flex; flex-direction: column; gap: 12px; min-height: 210px; transition: transform var(--dur-ui) var(--ease), box-shadow var(--dur-ui) var(--ease), border-color var(--dur-ui) var(--ease); }
.assure::before { content: ""; position: absolute; top: 0; left: 0; width: 100%; height: 2px; background: var(--cobalt); transform: scaleX(0); transform-origin: left; transition: transform var(--dur-ui) var(--ease); }
.assure:hover { transform: translateY(-4px); box-shadow: var(--shadow-md); border-color: rgba(157,180,255,.55); z-index: 1; }
.assure:hover::before { transform: scaleX(1); }
.assure-k { font-family: var(--font-mono); letter-spacing: 0.12em; text-transform: uppercase; color: var(--accent-texte); }
.pcol { position: relative; display: flex; flex-direction: column; border: 1px solid var(--hairline); background: var(--blanc); padding: 32px 28px; transition: border-color var(--dur-ui) var(--ease), transform var(--dur-ui) var(--ease), box-shadow var(--dur-ui) var(--ease); }
.pcol:hover { border-color: rgba(157,180,255,.55); transform: translateY(-6px); box-shadow: var(--shadow-lg); z-index: 1; }
.pcol-dark { background: var(--grad-ink); color: var(--blanc); border-color: var(--encre); }
.pcol-dark:hover { border-color: var(--cobalt); box-shadow: var(--shadow-cobalt); }
.pcol-top { display: flex; align-items: center; justify-content: space-between; }
.pcol-name { font-family: var(--font-mono); letter-spacing: 0.14em; text-transform: uppercase; color: var(--encre-60); }
.pcol-dark .pcol-name { color: var(--blanc-70); }
.pcol-reco { font-family: var(--font-mono); letter-spacing: 0.12em; text-transform: uppercase; color: var(--accent-texte); }
.pcol-price { margin-top: 26px; }
.pcol-amount { display: inline-flex; align-items: flex-start; white-space: nowrap; font-family: var(--font-display); font-weight: 800; letter-spacing: -0.04em; font-size: clamp(42px, 4vw, 54px); line-height: 1; }
.pcol-unit { display: block; margin-top: 10px; font-family: var(--font-mono); letter-spacing: 0.08em; text-transform: uppercase; color: var(--encre-60); }
.pcol-dark .pcol-unit { color: var(--blanc-60); }
.pcol-bill { margin-top: 8px; font-family: var(--font-mono); letter-spacing: 0.08em; text-transform: uppercase; color: var(--encre-60); min-height: 14px; }
.pcol-dark .pcol-bill { color: var(--blanc-60); }
.pcol-feat { list-style: none; margin: 26px 0 0; padding: 0; flex: 1; display: flex; flex-direction: column; gap: 12px; font-size: 14px; }
.pcol-feat li { display: flex; gap: 12px; align-items: baseline; }
.pcol-feat li .tick { flex: none; margin-top: 7px; width: 16px; height: 1px; background: var(--encre-50); }
.pcol-dark .pcol-feat li .tick { background: var(--blanc-60); }
.pcol-feat li span:last-child { color: var(--encre-85); }
.pcol-dark .pcol-feat li span:last-child { color: var(--blanc-90); }
/* ---- Phase 4 : tarifs — les tirets se cochent, le prix pop, la carte IA respire */
@media (prefers-reduced-motion: no-preference) {
  .pcol-feat li .tick { transform: scaleX(0); transform-origin: left center; transition: transform 300ms var(--ease-out); }
  .pcol-feat li:nth-child(1) .tick { transition-delay: 200ms; }
  .pcol-feat li:nth-child(2) .tick { transition-delay: 262ms; }
  .pcol-feat li:nth-child(3) .tick { transition-delay: 324ms; }
  .pcol-feat li:nth-child(4) .tick { transition-delay: 386ms; }
  .pcol-feat li:nth-child(5) .tick { transition-delay: 448ms; }
  .pcol-amount { transform-origin: left center; }
  @keyframes pcolPricePop { from { transform: translateY(7px) scale(0.94); } to { transform: none; } }
  @keyframes pcolBreathe { 0%, 100% { opacity: 0.55; } 50% { opacity: 1; } }}
/* ---------------------------------------------------------------------------
   Option en supplément — carte pleine largeur, sous la grille des packs.
   Elle ne rejoint PAS la grille : ce n'est pas un cinquième pack qu'on
   choisirait à la place d'un autre, mais une option qui s'ajoute à celui qu'on a.

   Trois zones et pas une de plus : le discours à gauche, le prix à droite dans
   un rail qui lui appartient, les réserves en une seule ligne en dessous. Une
   facture dessinée occupe le fond du rail — décorative, jamais lue.
   ========================================================================== */
.addon { position: relative; overflow: hidden; isolation: isolate;
         border: 1px solid var(--hairline); background: var(--ink-2);
         padding: 34px 32px; margin-top: 16px;
         display: grid; grid-template-columns: 1fr; gap: 24px 44px; }
@media (min-width: 900px) { .addon { grid-template-columns: 1fr 268px; padding: 38px 36px; }}

/* La facture de fond. Elle se lit ENTIÈRE, dans l'angle bas-droit resté vide,
   et jamais sous une ligne de texte : à moitié rognée elle ne ressemblait plus à
   rien, et ses filets traversaient le prix. Le texte qui la borde est plafonné
   en largeur pour qu'aucune ligne ne vienne la recouvrir. */
.addon-illu { position: absolute; right: 30px; bottom: 16px; width: 126px; height: auto;
              z-index: 0; pointer-events: none; opacity: .07;
              fill: none; stroke: var(--blanc); stroke-width: 5; stroke-linecap: round; stroke-linejoin: round; }
.addon-illu rect { fill: var(--blanc); stroke: none; }
@media (max-width: 899px) { .addon-illu { display: none; }}
.addon-corps, .addon-prix, .addon-fine { position: relative; z-index: 1; }

/* ---- Le discours ---- */
.addon-badge { display: inline-block; font-family: var(--font-mono); font-size: 10px; letter-spacing: .12em;
               text-transform: uppercase; color: var(--accent-texte); border: 1px solid rgba(60,99,242,.45);
               padding: 4px 10px; }
.addon-t { margin: 14px 0 0; font-family: var(--font-display); font-weight: 800; letter-spacing: -.035em;
           font-size: clamp(26px, 3.2vw, 34px); line-height: 1.08; color: var(--blanc); }
.addon-d { margin: 12px 0 0; max-width: 54ch; font-size: 16px; line-height: 1.55; color: var(--encre-80); }
.addon-feat { list-style: none; margin: 24px 0 0; padding: 0; display: grid; grid-template-columns: 1fr;
              gap: 11px 30px; font-size: 15px; line-height: 1.45; color: var(--encre-85); }
@media (min-width: 640px) { .addon-feat { grid-template-columns: 1fr 1fr; }}
/* Le marqueur est peint ici, et non repris de .pcol-feat : là-bas le tiret naît
   à scaleX(0) et n'est déplié que par l'animation de la grille des packs. Hors
   de cette grille il restait invisible, et la liste flottait sans repère. */
.addon-feat li { position: relative; padding-left: 26px; }
.addon-feat li::before { content: ""; position: absolute; left: 0; top: .62em; width: 15px; height: 1px;
                         background: var(--accent-texte); }

/* ---- Le rail du prix ---- */
.addon-prix { align-self: start; }
@media (min-width: 900px) { .addon-prix { border-left: 1px solid var(--hairline); padding-left: 36px; }}
@media (max-width: 899px) { .addon-prix { border-top: 1px solid var(--hairline); padding-top: 24px; }}
.addon-montant { display: flex; align-items: baseline; flex-wrap: wrap; gap: 0 8px; }
.addon-n { font-family: var(--font-display); font-weight: 800; letter-spacing: -.05em;
           font-size: clamp(52px, 6vw, 66px); line-height: .92; color: var(--blanc); }
.addon-cur { font-family: var(--font-display); font-weight: 800; font-size: 24px; color: var(--blanc); }
.addon-unite { font-family: var(--font-mono); font-size: 11px; letter-spacing: .08em; text-transform: uppercase;
               color: var(--encre-60); flex-basis: 100%; margin-top: 6px; }
.addon-cle { margin: 14px 0 0; font-size: 14px; line-height: 1.4; font-weight: 500; color: var(--accent-texte); }
.addon-quota { margin: 20px 0 0; display: grid; gap: 12px; border-top: 1px solid var(--hairline); padding-top: 18px; }
.addon-quota dt { font-family: var(--font-mono); font-size: 10px; letter-spacing: .1em; text-transform: uppercase;
                  color: var(--encre-60); }
.addon-quota dd { margin: 3px 0 0; font-size: 15px; line-height: 1.35; color: var(--blanc); }

/* ---- Les réserves, une seule fois ---- */
.addon-fine { grid-column: 1 / -1; margin: 0; padding-top: 20px; border-top: 1px solid var(--hairline);
              font-size: 13px; line-height: 1.6; color: var(--encre-60); }
/* Le texte s'arrête avant la facture ; le filet, lui, va jusqu'au bord. */
@media (min-width: 900px) { .addon-fine { padding-right: 230px; }}
.addon-fine strong { color: var(--encre-85); }
.addon-fine a { color: var(--accent-texte); }

.pcol .btn { margin-top: 30px; }
.pcol-foot { margin-top: 18px; font-family: var(--font-mono); letter-spacing: 0.1em; text-transform: uppercase; color: var(--encre-60); }
.pcol-dark .pcol-foot { color: var(--blanc-60); }
.probleme-cta-note { font-family: var(--font-mono); letter-spacing: 0.08em; text-transform: uppercase; color: var(--blanc-60); }

/* ===========================================================================
   FAQ
   ========================================================================== */
.faq { list-style: none; margin: 0; padding: 0; border-top: 1px solid var(--hairline); max-width: 820px; }
.faq-item { border-bottom: 1px solid var(--hairline); }
.faq-q { display: flex; width: 100%; align-items: center; justify-content: space-between; gap: 24px; padding: 22px 0; background: none; border: none; text-align: left; cursor: pointer; color: inherit; transition: color var(--dur-ui) var(--ease); font-family: inherit; }
.faq-q:hover { color: var(--accent-texte); }
.faq-qt { font-size: clamp(17px, 2vw, 20px); font-weight: 500; }
.faq-plus { font-family: var(--font-mono); font-size: 20px; line-height: 1; flex: none; transition: transform var(--dur-ui) var(--ease), color var(--dur-ui) var(--ease); }
.faq-item.is-open .faq-plus { transform: rotate(45deg); color: var(--accent-texte); }
.faq-panel { display: grid; grid-template-rows: 0fr; }
.faq-item.is-open .faq-panel { grid-template-rows: 1fr; }
.faq-panel > div { min-height: 0; overflow: hidden; visibility: hidden; }
.faq-item.is-open .faq-panel > div { visibility: visible; }
@media (prefers-reduced-motion: no-preference) {
  .faq-panel { transition: grid-template-rows 320ms var(--ease); }
  /* La réponse reste visible pendant le repli, puis sort de l'arbre. */
  .faq-panel > div { transition: visibility 0s linear 320ms; }
  .faq-item.is-open .faq-panel > div { transition: visibility 0s; }
  /* Le texte de réponse suit le panneau : fondu + légère montée, même tempo */
  .faq-a { opacity: 0; transform: translateY(-4px); transition: opacity 260ms var(--ease-out) 60ms, transform 260ms var(--ease-out) 60ms; }
  .faq-item.is-open .faq-a { opacity: 1; transform: none; }}
.faq-a { margin: 0; padding: 0 52px 26px 0; font-size: 16px; line-height: 1.6; color: var(--encre-80); }

/* ===========================================================================
   Final CTA
   ========================================================================== */
.cta-inner { display: flex; flex-direction: column; gap: 40px; }
@media (min-width: 820px) { .cta-inner { flex-direction: row; align-items: flex-end; justify-content: space-between; }}
.cta-title { margin: 0; font-family: var(--font-display); font-weight: 800; letter-spacing: -0.045em; font-size: clamp(44px, 7vw, 84px); line-height: 0.94; max-width: 14ch; }
.cta-lead { margin: 24px 0 0; max-width: 42ch; font-size: clamp(17px, 2vw, 19px); line-height: 1.55; color: var(--blanc-90); }
.cta-actions { display: flex; flex-wrap: wrap; gap: 12px; }

/* ===========================================================================
   Footer
   ========================================================================== */
.footer { background: var(--encre); color: var(--blanc); }
.footer .page { padding-top: 72px; padding-bottom: 48px; }
@media (min-width: 768px) { .footer .page { padding-top: 96px; }}
.footer-grid { display: grid; grid-template-columns: 1fr; gap: 40px 32px; }
@media (min-width: 560px) { .footer-grid { grid-template-columns: 1fr 1fr; } .footer-brand { grid-column: 1 / -1; }}
@media (min-width: 900px) { .footer-grid { grid-template-columns: 2fr 1fr 1fr 1fr; } .footer-grid--5 { grid-template-columns: 1.7fr 1fr 1fr 1fr 1fr; } .footer-brand { grid-column: auto; }}
.footer-brand .wm { font-size: 40px; color: var(--blanc); }
.footer-brand .wm .accent-i { color: var(--accent-display); }
.footer-tag { margin: 22px 0 0; max-width: 34ch; font-size: 15px; line-height: 1.55; color: var(--blanc-80); }
.footer-coords { margin-top: 28px; display: flex; flex-direction: column; gap: 5px; font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.06em; color: var(--blanc-70); }
.footer-coords p { margin: 0; }
.footer-col-t { font-family: var(--font-mono); letter-spacing: 0.14em; text-transform: uppercase; color: var(--blanc-60); }
.footer-col ul { list-style: none; margin: 18px 0 0; padding: 0; display: flex; flex-direction: column; gap: 12px; }
.footer-col a { font-size: 14px; color: var(--blanc-90); text-decoration: none; position: relative; transition: color var(--dur-fast) var(--ease); }
/* #6e8cff (cobalt clair, déjà utilisé par le hub des flux) : le cobalt plein
   est sous 3:1 sur le footer noir — insuffisant pour un indicateur d'état. */
.footer-col a::after { content: ""; position: absolute; left: 0; right: 0; bottom: -3px; height: 1px; background: #6e8cff; transform: scaleX(0); transform-origin: 100% 50%; }
@media (prefers-reduced-motion: no-preference) and (hover: hover) and (pointer: fine) { .footer-col a::after { transition: transform var(--dur-ui) var(--ease); }}
.footer-col a:hover { color: var(--accent-texte); }
.footer-col a:hover::after, .footer-col a:focus-visible::after { transform: scaleX(1); transform-origin: 0 50%; }
.footer-base { margin-top: 64px; border-top: 1px solid var(--blanc-15); padding-top: 24px; display: flex; flex-direction: column; gap: 14px; }
@media (min-width: 760px) { .footer-base { flex-direction: row; align-items: center; justify-content: space-between; }}
.footer-base .l { font-family: var(--font-mono); letter-spacing: 0.1em; text-transform: uppercase; color: var(--blanc-60); }
.footer-social { display: flex; gap: 18px; }
.footer-social a { font-family: var(--font-mono); letter-spacing: 0.1em; text-transform: uppercase; color: var(--blanc-70); text-decoration: none; position: relative; transition: color var(--dur-fast) var(--ease); }
.footer-social a::after { content: ""; position: absolute; left: 0; right: 0; bottom: -3px; height: 1px; background: #6e8cff; transform: scaleX(0); transform-origin: 100% 50%; }
@media (prefers-reduced-motion: no-preference) and (hover: hover) and (pointer: fine) { .footer-social a::after { transition: transform var(--dur-ui) var(--ease); }}
.footer-social a:hover { color: var(--accent-texte); }
.footer-social a:hover::after, .footer-social a:focus-visible::after { transform: scaleX(1); transform-origin: 0 50%; }

/* ===========================================================================
   Scroll reveal (sober: fade + 8px translate)
   ========================================================================== */
@media (prefers-reduced-motion: no-preference) {
  [data-reveal]:not([data-stagger]) { opacity: 0; transform: translateY(10px); transition: opacity var(--dur-reveal) var(--ease), transform var(--dur-reveal) var(--ease); }
  [data-reveal]:not([data-stagger]).is-revealed { opacity: 1; transform: translateY(0); }
  /* staggered groups: the children animate individually */
  [data-stagger] > * { opacity: 0; transform: translateY(12px); transition: opacity var(--dur-reveal) var(--ease), transform var(--dur-reveal) var(--ease); }
  [data-stagger] > *.is-revealed { opacity: 1; transform: translateY(0); }}

/* Toast for fake CTA actions */
.toast { position: fixed; left: 50%; bottom: 28px; transform: translate(-50%, 20px); z-index: 200; background: var(--encre); color: var(--blanc); border: 1px solid var(--encre); border-left: 3px solid var(--cobalt); padding: 14px 20px; font-size: 14px; opacity: 0; pointer-events: none; transition: opacity var(--dur-ui) var(--ease), transform var(--dur-ui) var(--ease); max-width: calc(100vw - 32px); }
.toast.is-show { opacity: 1; transform: translate(-50%, 0); }

/* ===========================================================================
   Offre de lancement + essai (section Tarifs)
   ========================================================================== */
.price-trial { font-family: var(--font-mono); letter-spacing: 0.1em; text-transform: uppercase; color: var(--encre-60); }
.price-model { margin: -12px 0 30px; max-width: 72ch; font-size: 14px; line-height: 1.55; color: var(--encre-70); }
.price-model strong { color: var(--encre-85); }
.olto-status { font-family: var(--font-mono); letter-spacing: 0.1em; text-transform: uppercase; color: var(--blanc-60); display: flex; align-items: center; gap: 6px; margin-top: 3px; }
/* Chat joué en direct (assets/olto-chat.js) : messages révélés 1 par 1, bulle
   « en train d'écrire » avant chaque réponse d'Olto. */
@media (prefers-reduced-motion: no-preference) {
  .olto-typing { align-self: flex-start; display: inline-flex; gap: 5px; align-items: center;
    background: rgba(60,99,242,0.18); border: 1px solid rgba(60,99,242,0.42); border-radius: 14px; border-bottom-left-radius: 4px; padding: 13px 15px; animation: oltoMsgIn 220ms var(--ease-out) both; }
  .olto-typing span { width: 7px; height: 7px; border-radius: 50%; background: var(--blanc-70); animation: oltoTypeDot 1.2s ease-in-out infinite; }
  .olto-typing span:nth-child(2) { animation-delay: .18s; }
  .olto-typing span:nth-child(3) { animation-delay: .36s; }
  @keyframes oltoMsgIn { from { opacity: 0; transform: translateY(9px); } to { opacity: 1; transform: none; } }
  @keyframes oltoTypeDot { 0%, 60%, 100% { opacity: .3; transform: translateY(0); } 30% { opacity: 1; transform: translateY(-3px); } }}
.demo-form input, .demo-form textarea { width: 100%; font-family: var(--font-sans); font-size: 15px; color: var(--blanc); background: transparent; border: 1px solid var(--blanc-40); border-radius: var(--radius-ui); padding: 12px 14px; }
.demo-reassure { margin: 4px 0 0; font-family: var(--font-mono); letter-spacing: 0.08em; text-transform: uppercase; color: var(--blanc-60); }
.demo-status.ok { color: var(--blanc); border-left: 3px solid var(--cobalt); padding-left: 10px; }
.demo-status.err { color: var(--blanc); border-left: 3px solid var(--blanc-60); padding-left: 10px; }
.spot-k { font-family: var(--font-mono); letter-spacing: 0.14em; text-transform: uppercase; color: var(--blanc-60); }

/* ===========================================================================
   Affinages responsive (tablette + smartphone)
   ========================================================================== */
html { scroll-padding-top: 84px; }      /* ancres non masquées par le header sticky */
body { overflow-wrap: break-word; }     /* pas de débordement (emails, mots longs) */

/* En-tête de section empilé : la pagination n'écrase plus le titre */
@media (max-width: 640px) {
  .section-head { flex-direction: column; align-items: flex-start; gap: 10px; margin-bottom: 40px; }
  .faq-a { padding-right: 0; }
  .faq-q { gap: 16px; }}

/* Respiration verticale réduite sur petits téléphones */
@media (max-width: 520px) {
  .pcol { padding: 28px 24px; }
  .benef, .assure, .module-card { padding: 24px; }}

/* ===========================================================================
   Motion & finitions modernes (v2) — tout désactivé sous reduced-motion
   ========================================================================== */

/* Spotlight cobalt : halo suivant le curseur sur les cartes (premium, discret) */
@media (prefers-reduced-motion: no-preference) and (hover: hover) {
  .pcol, .benef, .module-card, .relcard, .assure { position: relative; }
  .pcol::after, .benef::after, .module-card::after, .relcard::after, .assure::after {
    content: ""; position: absolute; inset: 0; z-index: 0; pointer-events: none; opacity: 0;
    background: radial-gradient(220px circle at var(--mx, 50%) var(--my, 50%), rgba(24,70,220,0.10), transparent 60%);
    transition: opacity var(--dur-ui) var(--ease);
  }
  .pcol-dark::after { background: radial-gradient(240px circle at var(--mx, 50%) var(--my, 50%), rgba(60,99,242,0.22), transparent 62%); }
  .pcol:hover::after, .benef:hover::after, .module-card:hover::after, .relcard:hover::after, .assure:hover::after { opacity: 1; }
  .pcol > *, .benef > *, .module-card > *, .relcard > *, .assure > * { position: relative; z-index: 1; }}

/* Compteurs accentués : petit "pop" + flash cobalt à la fin du count-up */
@media (prefers-reduced-motion: no-preference) {
  [data-count].is-counted { animation: countPop 520ms var(--ease-spring); }
  @keyframes countPop { 0% { color: var(--cobalt); transform: scale(1.10); } 60% { color: var(--cobalt); } 100% { transform: scale(1); } }}
@media (prefers-reduced-motion: no-preference) {
  @keyframes heroShimmer { from { background-position: 120% 0; } to { background-position: -40% 0; } }}

/* Dashboard du hero : les lignes "streamées" une à une (effet Live) */
@media (prefers-reduced-motion: no-preference) {
  @keyframes dashRowIn { from { opacity: 0; transform: translateX(-10px); } to { opacity: 1; transform: none; } }}

/* Menu mobile : entrée échelonnée des liens à l'ouverture */
@media (prefers-reduced-motion: no-preference) {
  .nav-mobile.is-open > * { animation: navItemIn 320ms var(--ease-out) both; }
  .nav-mobile.is-open > *:nth-child(1) { animation-delay: 30ms; }
  .nav-mobile.is-open > *:nth-child(2) { animation-delay: 70ms; }
  .nav-mobile.is-open > *:nth-child(3) { animation-delay: 110ms; }
  .nav-mobile.is-open > *:nth-child(4) { animation-delay: 150ms; }
  .nav-mobile.is-open > *:nth-child(5) { animation-delay: 190ms; }
  .nav-mobile.is-open > *:nth-child(6) { animation-delay: 230ms; }
  @keyframes navItemIn { from { opacity: 0; transform: translateY(-8px); } to { opacity: 1; transform: none; } }}
@media (prefers-reduced-motion: no-preference) {
  @keyframes wordUp { from { transform: translateY(115%); } to { transform: translateY(0); } }}

/* Halo "aurora" du hero : dérive lente et respiration */
@media (prefers-reduced-motion: no-preference) {
  @keyframes auroraDrift { from { transform: translate3d(0,0,0) scale(1); } to { transform: translate3d(-5%,4%,0) scale(1.16); } }}
@media (prefers-reduced-motion: no-preference) {
  @keyframes sparkDraw { to { stroke-dashoffset: 0; } }
  @keyframes sparkArea { to { opacity: 1; } }}

/* ===========================================================================
   Finitions motion (v3) — accents de section, CTA final, icônes modules
   ========================================================================== */

/* Trait cobalt qui se trace sous le titre de section (scroll-driven, fallback statique) */
.section-head { position: relative; }
.section-head::after { content: ""; position: absolute; left: 0; bottom: -1px; height: 2px; width: 64px; background: var(--cobalt); transform-origin: left center; }
@media (prefers-reduced-motion: no-preference) {
  @supports (animation-timeline: view()) {
    .section-head::after { transform: scaleX(0); animation: sectionLine linear both; animation-timeline: view(); animation-range: entry 5% cover 22%; }
    @keyframes sectionLine { to { transform: scaleX(1); } }
  }}

/* CTA final (section cobalt) — halo clair qui dérive doucement */
.section-cobalt { position: relative; overflow: hidden; }
.section-cobalt > * { position: relative; z-index: 1; }
.section-cobalt::before { content: ""; position: absolute; inset: 0; z-index: 0; pointer-events: none;
  background: radial-gradient(48% 60% at 18% 22%, rgba(255,255,255,0.18), transparent 62%); }
@media (prefers-reduced-motion: no-preference) {
  .section-cobalt::before { animation: ctaGlow 13s ease-in-out infinite alternate; }
  @keyframes ctaGlow { from { transform: translate(0,0) scale(1); } to { transform: translate(46%,22%) scale(1.25); } }}
.bento-cell { position: relative; overflow: hidden; display: flex; flex-direction: column; justify-content: flex-start;
  background: var(--blanc); border: 1px solid var(--hairline); padding: 28px;
  transition: transform var(--dur-ui) var(--ease), box-shadow var(--dur-ui) var(--ease), border-color var(--dur-ui) var(--ease); }
.bento-cell:hover { transform: translateY(-4px); box-shadow: var(--shadow-lg); z-index: 1; border-color: var(--encre); }
.bento-cell.is-dark { background: var(--grad-ink); border-color: var(--encre); color: var(--blanc); }
.bento-cell.is-dark:hover { border-color: var(--cobalt); box-shadow: var(--shadow-cobalt); }

/* Spotlight curseur aussi sur les cellules bento */
@media (prefers-reduced-motion: no-preference) and (hover: hover) {
  .bento-cell::after { content: ""; position: absolute; inset: 0; z-index: 0; pointer-events: none; opacity: 0;
    background: radial-gradient(220px circle at var(--mx, 50%) var(--my, 50%), rgba(24,70,220,0.10), transparent 60%);
    transition: opacity var(--dur-ui) var(--ease); }
  .bento-cell.is-dark::after { background: radial-gradient(240px circle at var(--mx,50%) var(--my,50%), rgba(60,99,242,0.22), transparent 62%); }}
.section-dot-l { position: absolute; right: 22px; top: 50%; transform: translateY(-50%); white-space: nowrap; font-family: var(--font-mono); letter-spacing: 0.1em; text-transform: uppercase; color: var(--encre); background: var(--blanc); border: 1px solid var(--hairline); box-shadow: var(--shadow-sm); padding: 5px 9px; border-radius: var(--radius-ui); opacity: 0; pointer-events: none; transition: opacity var(--dur-ui) var(--ease); }   /* aurora plus présent sur fond sombre */

/* FAQ premium en 2 colonnes (desktop) */
@media (min-width: 860px) {
  .faq { display: grid; grid-template-columns: 1fr 1fr; column-gap: 56px; max-width: none; border-top: none; align-items: start; }
  .faq-item { border-top: 1px solid var(--hairline); border-bottom: none; }}

/* Micro-interaction : pop du message de statut (succès / erreur) sur les formulaires */
@media (prefers-reduced-motion: no-preference) {
  .demo-status.ok, .demo-status.err { animation: statusIn 360ms var(--ease-out); }
  @keyframes statusIn { from { opacity: 0; transform: translateY(5px); } to { opacity: 1; transform: none; } }}
.demo-status.ok { display: flex; align-items: center; gap: 8px; }
.demo-status.ok::before { content: ""; flex: none; width: 16px; height: 16px; border-radius: 999px; background: var(--cobalt);
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M13 4.5 6.5 11 3 7.5' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center/12px no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M13 4.5 6.5 11 3 7.5' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center/12px no-repeat; }

/* ===========================================================================
   THÈME SOMBRE GLOBAL — bascule clair → sombre (tokens texte/filets en clair
   + surfaces blanches assombries). Le dashboard reste blanc (il ressort).
   ========================================================================== */
:root { --ink-0:#08080c; --ink-1:#0e0e16; --ink-2:#14141d; --ink-3:#1b1b25; }
body.oltanis {
  --hairline: rgba(255,255,255,0.12);
  --muted: #9aa1ad;
  --encre-85: rgba(255,255,255,0.92);
  --encre-80: rgba(255,255,255,0.82);
  --encre-70: rgba(255,255,255,0.70);
  --encre-60: rgba(255,255,255,0.56);
  /* 0.44 donnait 4,33:1 sur #08080c et 4,31:1 sur #1b1b25 — sous le seuil de
     4,5:1, alors que cet échelon porte des étiquettes de 10-11 px (index des
     lignes de bénéfices, dates des cartes, mentions de prix). 0.48 → 4,9:1
     partout. Corriger le barreau plutôt que chaque sélecteur qui s'en sert. */
  --encre-50: rgba(255,255,255,0.48);
  background: var(--ink-0); color: var(--blanc);
}
/* Sections (alternance de deux noirs) */
.section { background: var(--ink-0); }
/* Header : glass sombre */
.header { background: rgba(10,10,14,0.72); border-bottom-color: var(--hairline); }
.header.is-scrolled { background: rgba(10,10,14,0.88); }
.burger { border-color: var(--blanc-20); color: var(--blanc); }
.nav a:hover { color: var(--blanc); }
/* Boutons : ghost devient clair sur sombre */
.btn-ghost { color: var(--blanc); border-color: var(--blanc-20); }
.btn-ghost:hover { background: var(--blanc); color: var(--encre); }
/* Cartes claires → surfaces sombres */
.module-card, .pcol, .assure, .bento-cell, .cell, .quiz-card { background: var(--ink-2); }
.benef:hover, .module-card:hover { background: var(--ink-3); }
/* Cartes "dark" d'accent : encore plus sombres + filet cobalt pour ressortir */
.pcol-dark, .bento-cell.is-dark { background: #050509; border-color: rgba(24,70,220,0.55); }
.section-title, .bento-t, .module-name, .assure-t, .featrow-h, .faq-qt { color: var(--blanc); }
@keyframes fmFlow    { to { stroke-dashoffset: -160; } }
@keyframes fmWave    { 0% { opacity: 0.5; transform: scale(1); } 100% { opacity: 0; transform: scale(2.6); } }
@keyframes fmBreathe { 0%, 100% { opacity: 0.72; } 50% { opacity: 1; } }

/* Correctifs dark (audit) : texte de section en clair par défaut + cellules compteur sombres
   + restauration du texte sombre dans le dashboard blanc (îlot clair). */
.section { color: var(--blanc); }


/* ==========================================================================
   FINITION SOMBRE — correctifs de thème (phase 1)
   Le calque décoratif et les ombres avaient été écrits pour la version CLAIRE
   de la landing ; la bascule sombre ne les avait jamais repris.
   ========================================================================== */

/* 1. Le bloc CTA final avait perdu son fond cobalt : `.section` (bloc sombre)
      écrasait `.section-cobalt` à spécificité égale, en arrivant après. */
body.oltanis .section-cobalt { background: var(--cobalt); }
body.oltanis .section-cobalt .section-title,
body.oltanis .section-cobalt .cta-title { color: var(--blanc); }

/* 2. Ombres : rgba(10,10,10,…) est invisible sur #08080c. On repasse sur du
      noir franc, plus large, pour que l'élévation au survol existe vraiment. */
body.oltanis {
  --shadow-sm: 0 2px 8px -2px rgba(0,0,0,0.55);
  --shadow-md: 0 14px 30px -12px rgba(0,0,0,0.70), 0 4px 10px -6px rgba(0,0,0,0.50);
  --shadow-lg: 0 34px 70px -24px rgba(0,0,0,0.80);
}

/* 4. Anneau de focus : le cobalt plein tombe à 2,6:1 sur fond sombre. */
body.oltanis { --focus-ring: 2px solid var(--accent-texte); }

/* 4-bis. L'ACCENT lui-même n'avait jamais suivi la bascule sombre.
   --cobalt #1846DC est calibré pour du texte sur blanc ; sur #08080c il donne
   2,81:1, sous le seuil de 3:1 exigé même pour du très grand texte. Or c'est la
   signature du site : le I italique de la marque (47 occurrences), le mot
   accentué de chaque H1, les numéros, le + des FAQ.
   Deux tokens, un par rôle (voir colors_and_type.css) :
     --accent-display #5B7CFF  reste franchement cobalt aux grandes tailles
     --accent-texte   #9DB4FF  reste lisible à 10-11 px
   ATTENTION : ne concerne QUE le texte posé sur les fonds sombres. Le tableau
   de bord du héros est un îlot blanc — le badge .r-tag.ok y garde le cobalt
   plein, qui y vaut 6,3:1. Les fonds, bordures et dégradés cobalt sont eux
   aussi inchangés : seul le texte était en cause. */
body.oltanis .accent-i          { color: var(--accent-display); }
body.oltanis .section-cobalt .btn-ghost-light { background: rgba(255,255,255,.10); }

/* ==========================================================================
   LONGUEUR — cartes modules en format horizontal compact sur petit écran.
   En une colonne, 46 cartes verticales représentaient 9 349 px : la section
   Modules pesait à elle seule un tiers de la page au doigt. Le contenu est
   identique (aucune carte retirée, aucun texte masqué), seule la disposition
   change : icône à gauche, texte à droite.
   ========================================================================== */
@media (max-width: 559px) {
  .module-cat { font-size: 9px; line-height: 1.2; }}
@media (min-width: 1100px) {
  .mm-hub-l { margin-top: 6px; font-family: var(--font-mono); font-size: 10px; letter-spacing: .12em;
              text-transform: uppercase; color: var(--accent-texte); text-align: center; line-height: 1.4; }}

@media (min-width: 1100px) and (prefers-reduced-motion: no-preference) {
  @keyframes mmSeve {
    0%       { background-position: 0 -90px; opacity: 0; }
    12%      { opacity: 1; }
    88%      { opacity: 1; }
    100%     { background-position: 0 100%; opacity: 0; }
  }
  @keyframes mmMoyeu { 0%, 100% { opacity: .38; } 8% { opacity: .85; } 40% { opacity: .5; } }
  @keyframes mmRameau {
    from { transform: translateX(0); opacity: 1; }
    to   { transform: translateX(66px); opacity: 0; }
  }}
.mm-count { font-family: var(--font-mono); letter-spacing: .1em; text-transform: uppercase;
            color: var(--blanc-60); flex: none; white-space: nowrap; }
@keyframes mmOpen { from { opacity: 0; transform: translateY(-8px); } to { opacity: 1; transform: none; } }

/* ==========================================================================
   MOBILE — confort tactile
   ========================================================================== */
/* Verrou de défilement quand le menu est ouvert (posé par landing.js). */
html.menu-open, html.menu-open body { overflow: hidden; }

@media (max-width: 900px) {
  /* Cibles tactiles : les liens de pied de page mesuraient 16 à 21 px de haut.
     On élargit la zone de contact sans changer la densité visuelle. */
  .footer-col a, .footer-social a, .footer-base a {
    display: inline-flex; align-items: center; min-height: 44px;
  }
  .footer-col li { display: flex; }
  .footer-social { gap: 4px 20px; }
  /* Un lien d'une seule lettre (« X ») ne faisait que 7 px de large. */
  .footer-social a { min-width: 44px; justify-content: center; }
  .header-brand { min-height: 44px; display: inline-flex; align-items: center; }

  /* Champs de formulaire : sous 16 px, iOS zoome automatiquement au focus et
     l'utilisateur se retrouve avec une page décalée. */
  .demo-form input, .demo-form select, .demo-form textarea,
  input[type="text"], input[type="email"], input[type="tel"], select, textarea {
    font-size: 16px;
  }}

/* Survol « collé » au doigt : sur écran tactile, un tap laisse l'état hover
   actif jusqu'au tap suivant. On neutralise les survols décoratifs là où le
   pointeur n'est pas fin. */
@media (hover: none) {
  .module-card:hover, .benef:hover, .assure:hover, .pcol:hover, .relcard:hover,
  .mm-node:hover, .bento-cell:hover {
    transform: none; box-shadow: none;
  }}

/* ==========================================================================
   TYPOGRAPHIE — mise au propre (phase 4)
   ========================================================================== */

/* 1. Mesure de ligne. Un paragraphe de prose devient pénible à lire au-delà
      de ~75 caractères : l'œil perd la ligne suivante. Trois blocs sortaient
      de la fourchette, dont un à 134 caractères par ligne sur 1 312 px. */
/* Valeurs calibrées sur la mesure réelle (nombre de caractères par ligne
   rendue) et non sur l'unité ch, qui vaut la largeur du « 0 » — plus large
   que la moyenne des lettres, d'où une surestimation d'environ 30 %. */
.price-model { max-width: 500px; }
.faq-a { max-width: 570px; }
body.oltanis .addon { border-color: var(--blanc-20); }
body.oltanis .addon-badge { border-color: rgba(157,180,255,.4); }

/* 3. Échelle des étiquettes capitales. Le même rôle — sur-titre, catégorie,
      mention — était rendu avec 12 spécifications différentes (5 tailles de
      9 à 14 px, 4 valeurs d'approche). On ramène à deux crans :
        · 11 px / 0.14em  → sur-titres de section et étiquettes principales
        · 10 px / 0.12em  → mentions secondaires
      Seules la taille et l'approche sont normalisées ; couleurs et positions
      restent celles de chaque composant. */
.kick, .trustband-lab, .trustband-item, .targets-lab, .spot-k,
.pcol-name, .pcol-unit, .alto-teaser-k, .mm-count, .probleme-cta-note {
  font-size: 11px; letter-spacing: .14em;
}
.lab, .module-cat, .assure-k, .pcol-reco, .pcol-bill, .pcol-foot,
.footer-col-t, .olto-status, .price-trial, .demo-reassure,
.mm-hub-l, .section-dot-l, .footer-base .l, .footer-social a {
  font-size: 10px; letter-spacing: .12em;
}

/* ==========================================================================
   RÉDUCTION DES ANIMATIONS — filet global
   Les blocs @media (prefers-reduced-motion: no-preference) du fichier couvrent
   les @keyframes, mais pas les transitions déclarées hors de ces blocs : cartes
   qui se soulèvent, boutons qui montent, icônes qui pivotent. Un utilisateur
   ayant demandé la réduction les voyait toutes. Les délais sont conservés :
   le repli des panneaux de FAQ en dépend.
   ========================================================================== */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }}

/* ==========================================================================
   ACTUALITÉS — bande d'accueil et page dédiée
   Le contenu vient de data/actus.json, rendu CÔTÉ SERVEUR par _actus.php :
   le HTML part complet, lisible sans JavaScript comme le reste du site.
   Mêmes primitives que les autres cartes du site (filet --hairline, surface
   --ink-2, élévation au survol) : aucune nouvelle grammaire visuelle.
   ========================================================================== */
.actu-liste { display: grid; grid-template-columns: 1fr; gap: 16px; }
@media (min-width: 760px)  { .actu-liste { grid-template-columns: 1fr 1fr; }}
@media (min-width: 1200px) { .actu-liste { grid-template-columns: repeat(3, 1fr); }}

.actu { display: flex; flex-direction: column; gap: 12px;
        background: var(--ink-2); border: 1px solid var(--hairline);
        padding: 24px 22px; }
.actu-meta { display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap; }
.actu-tag { font-family: var(--font-mono); font-size: 10px; letter-spacing: .12em;
            text-transform: uppercase; color: var(--accent-texte); }
.actu-date { font-family: var(--font-mono); font-size: 10px; letter-spacing: .08em;
             text-transform: uppercase; color: var(--blanc-60); }
.actu-t { margin: 0; font-family: var(--font-display); font-weight: 800;
          letter-spacing: -.03em; font-size: 22px; line-height: 1.1; color: var(--blanc); }
.actu-b { margin: 0; font-size: 15px; line-height: 1.55; color: var(--blanc-80); }
/* Le lien est repoussé en pied de carte pour que les cartes d'une même rangée
   l'alignent, quelle que soit la longueur du texte. */
.actu-lien { margin-top: auto; padding-top: 4px; font-size: 14px; font-weight: 500;
             color: var(--accent-texte); text-decoration: none;
             display: inline-flex; align-items: center; gap: 8px; }
.actu-lien:hover { text-decoration: underline; text-underline-offset: 3px; }

/* Une actualité épinglée occupe toute la largeur : c'est celle qu'on veut voir
   en arrivant. La classe est posée par _actus.php, pas déduite en CSS — le
   dépôt n'utilise :has() nulle part et ce n'est pas la peine de commencer ici.
   Réservé à la PAGE dédiée : sur la bande d'accueil, une carte pleine largeur
   suivie de deux autres laisse une case vide dans la grille à trois colonnes —
   le même défaut que celui corrigé sur le hub Solutions. */
@media (min-width: 760px) {
  .actu-liste--page > .actu-une { grid-column: 1 / -1; }
  .actu-liste--page > .actu-une .actu-t { font-size: 28px; }
  .actu-liste--page > .actu-une .actu-b { max-width: 68ch; }}

@media (prefers-reduced-motion: no-preference) {
  .actu { transition: transform var(--dur-ui) var(--ease),
                      border-color var(--dur-ui) var(--ease),
                      box-shadow var(--dur-ui) var(--ease); }
  .actu:hover { transform: translateY(-3px); border-color: rgba(60,99,242,.55);
                box-shadow: 0 18px 40px -28px rgba(24,70,220,.6); }
  .actu-lien .arrow { transition: transform 220ms var(--ease-spring); display: inline-block; }
  .actu:hover .actu-lien .arrow { transform: translateX(4px); }}