/* Sens de lecture — voir `tokens/design_tokens.css` pour le raisonnement complet.
 *
 * ⚠️ REDÉCLARÉ ICI À DESSEIN. `--dir` est défini dans les tokens, mais 12 des 25
 * layouts ne chargent PAS ce fichier — dont `landing_v9`, `landing_v10`,
 * `landing` et `public`, c'est-à-dire les pages publiques, celles où une visite
 * arabe arrive en premier. Sans cette redéclaration, `var(--dir, 1)` y prend son
 * repli et TOUTES les animations restent en LTR sur la vitrine.
 *
 * Deux lignes idempotentes valent mieux qu'une dépendance de chargement
 * invisible : si les deux fichiers sont présents, la valeur est la même.
 */
:root { --dir: 1; }
[dir="rtl"] { --dir: -1; }

/* =============================================================================
   FLOWAYZ — LANDING v10 (« le travail qui ne se facture pas, en moins »)
   =============================================================================
   Servi par `app/views/layouts/landing_v10.html.erb` UNIQUEMENT, et par les
   quatre pages de pôle qui partagent ce layout.

   Îlot visuel isolé, comme la v8 et la v9 : ni tokens de l'app, ni Tailwind.
   Ce fichier ne peut rien casser dans l'application, et réciproquement.

   ---------------------------------------------------------------------------
   CE QUI CHANGE PAR RAPPORT À LA v9, ET POURQUOI
   ---------------------------------------------------------------------------
   La v9 s'interdisait l'ombre, le dégradé et les angles au-delà de 4px. C'était
   un parti pris cohérent — une page de papier imprimé. La v10 garde ce SOL
   (papier, serif d'affichage, grandes respirations, filets d'un pixel) et y
   ramène la MATIÈRE de l'application : l'accent en HSL, le CTA à dégradé et
   reflet, les cartes à 20px, les élévations, le focus à double anneau.

   L'intention : une page qui se lit comme un magazine et se touche comme le
   produit. Quelqu'un qui s'inscrit ne doit pas avoir l'impression de changer de
   marque en passant la porte.

   ⚠️ Les valeurs de jetons ci-dessous sont RECOPIÉES de
   `tokens/design_tokens.css`, `themes/accents.css` et `flowayz_override.css`.
   Ce layout ne les charge pas — il ne PEUT pas : `tailwind.css` pèse 241 Ko à
   lui seul, soit trois fois le budget critique entier de la page. Si la charte
   de l'app change, répercuter ici à la main.

   ---------------------------------------------------------------------------
   CONTRAINTES FERMES — toute violation est un bug
   ---------------------------------------------------------------------------
     · L'ACCENT NE PARAÎT QUE CINQ FOIS : les 2 CTA, le filet des solutions en
       section 4, la colonne « après » en section 5, le panneau de la section 7.
       Sa rareté est ce qui fait le luxe ; sa profusion fait le SaaS générique.
     · JAMAIS `color: #fff` sur un fond accent — le contraste est porté par
       `--accent-contrast`, qui vaut du texte SOMBRE sur cet orange.
     · JAMAIS de `scale` au survol (directive Nelwep, redemandée trois fois) :
       halo, ombre et glissement d'un pixel. Le `scale` de PRESSION est admis,
       c'est un effet de bouton, pas un zoom de survol.
     · Deux familles de police, pas trois.
     · Aucune flèche dans les libellés de CTA — le test de longueur compte le
       texte lu, et un `&rarr;` y ajouterait six caractères.
     · Aucun `<table>` : les sections 4 et 5 sont des listes de définition. Plus
       juste sémantiquement, et la règle `tables` de `responsive:audit` (job CI
       bloquant) déclenche sur la seule présence de la balise.

   Breakpoints : 640 / 768 / 1024 uniquement (767.98 pour la borne haute
   mobile). `responsive:audit` n'autorise que douze largeurs — tout 480px ou
   900px fait échouer la CI.
   ============================================================================= */

/* ===== Polices auto-hébergées =================================================
   Identiques à la v9, et c'est délibéré : les deux woff2 pèsent 52,8 Ko et sont
   DÉJÀ préchargés en production. En changer coûterait le double sur le chemin
   critique, pour une page dont l'élément de plus grand rendu est du texte.

   Jamais de @import Google Fonts : supprimé du projet (commit 7377aa6a) pour la
   performance et la CSP. Les deux landings ne coexistent jamais sur une même
   page, il n'y a donc pas de doublon à l'exécution. */

@font-face {
  font-family: 'DM Serif Display';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("/assets/dm-serif-display-latin-e7359aff.woff2") format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
                 U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193,
                 U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'DM Serif Display';
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  src: url("/assets/dm-serif-display-italic-latin-12048ab2.woff2") format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
                 U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193,
                 U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Libre Franklin';
  font-style: normal;
  font-weight: 400 600;
  font-display: swap;
  src: url("/assets/libre-franklin-latin-799dc441.woff2") format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
                 U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193,
                 U+2212, U+2215, U+FEFF, U+FFFD;
}

/* ----- Latin étendu — polonais, lituanien, tchèque, hongrois… ----------------
   🔴 SANS CE BLOC, LA PAGE CHANGE DE POLICE EN PLEIN MOT. Les fichiers `-latin`
   ci-dessus sont les sous-ensembles « latin » de Google Fonts : 221 et 227
   glyphes, qui s'arrêtent à U+00FF. Or `ė` vit en U+0117, `į` en U+012F, `ū` en
   U+016B, `ł` en U+0142 — tous dans Latin Extended-A. Le navigateur ne trouvait
   pas le glyphe et retombait sur `Times New Roman`, au milieu du titre.
   Constaté sur `/lt` : « steigėte », « įmonės », « Pasiūlymas ».

   ⚠️ Élargir l'`unicode-range` des blocs ci-dessus n'aurait RIEN changé : les
   glyphes ne sont pas dans le fichier. Vérifié à la table `cmap`, pas déduit.

   ⚠️ CE N'EST PAS UN PROBLÈME DE CHOIX DE POLICE. Les ONZE woff2 du projet — SN
   Pro, Cantarell, Inter, Sen, Fraunces comprises — ont exactement le même trou.
   Changer de famille n'aurait rien réglé ; il fallait le sous-ensemble.

   L'`unicode-range` fait tout le travail de performance : un visiteur français,
   anglais, allemand ou espagnol ne télécharge JAMAIS ces fichiers, parce
   qu'aucun caractère de sa page n'y tombe. Seuls le polonais et le lituanien
   paient, et seulement 10 et 25 Ko. C'est pourquoi ils ne sont pas préchargés
   dans le layout : un `preload` les téléchargerait pour tout le monde.
   ---------------------------------------------------------------------------- */

@font-face {
  font-family: 'DM Serif Display';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("/assets/dm-serif-display-latinext-8bce86ed.woff2") format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7,
                 U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F,
                 U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113,
                 U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: 'Libre Franklin';
  font-style: normal;
  font-weight: 400 600;
  font-display: swap;
  src: url("/assets/libre-franklin-latinext-1251504a.woff2") format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7,
                 U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F,
                 U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113,
                 U+2C60-2C7F, U+A720-A7FF;
}

/* ===== Jetons ================================================================
   Palette « Bento » de l'application (`tokens/design_tokens.css`, refonte du
   2026-07-23), dont la règle fondatrice est : PLUS JAMAIS DE BLANC PUR EN FOND.
   Le fond est un off-white chaud, les cartes sont blanches — c'est ce décalage
   qui fait exister les cartes sans avoir besoin d'une ombre.
   ============================================================================= */

:root {
  /* --- Sol --------------------------------------------------------------- */
  --paper:      #EFECE7;   /* fond de page — off-white chaud, jamais #FFF */
  --paper-2:    #E7E3DC;   /* aplat « creux », sections alternées */
  --surface:    #FFFFFF;   /* cartes : le seul blanc pur de la page */
  --surface-2:  #F4F1EC;   /* survol de carte plate */

  /* --- Encre ------------------------------------------------------------- */
  --ink:        #191B20;   /* titres et texte principal */
  --ink-2:      #3B3F47;   /* secondaire */
  --ink-3:      #71767F;   /* méta, étiquettes, notes */

  --line:       rgba(23, 24, 29, 0.09);
  --line-faint: rgba(23, 24, 29, 0.05);
  --line-strong:rgba(23, 24, 29, 0.18);

  /* --- Accent -------------------------------------------------------------
     Système HSL de `themes/accents.css`. Tout est dérivé de trois nombres :
     changer `--accent-h` suffit à repeindre la page entière, exactement comme
     le sélecteur d'accent de l'application le fait pour un utilisateur.

     `--accent-contrast` vaut du texte SOMBRE : sur cet orange, du blanc tombe
     sous le seuil AA. C'est la raison d'être de la variable — et la raison pour
     laquelle `text-white` sur `bg-accent` est un bug dans tout le projet. */
  --accent-h: 16;
  --accent-s: 88%;
  --accent-l: 59%;

  --accent:         hsl(var(--accent-h), var(--accent-s), var(--accent-l));
  --accent-hover:   hsl(var(--accent-h), var(--accent-s), calc(var(--accent-l) - 8%));
  --accent-edge:    hsl(var(--accent-h), var(--accent-s), calc(var(--accent-l) - 16%));
  --accent-deep:    hsl(var(--accent-h), var(--accent-s), 26%);
  --accent-contrast: #1A202C;

  --accent-5:  hsla(var(--accent-h), var(--accent-s), var(--accent-l), 0.05);
  --accent-10: hsla(var(--accent-h), var(--accent-s), var(--accent-l), 0.10);
  --accent-20: hsla(var(--accent-h), var(--accent-s), var(--accent-l), 0.20);
  --accent-30: hsla(var(--accent-h), var(--accent-s), var(--accent-l), 0.30);

  /* Le dégradé du CTA : clair en haut, base au milieu, sombre en bas. C'est ce
     qui donne au bouton son volume sans une seule image. */
  --accent-gradient: linear-gradient(
    180deg,
    hsl(var(--accent-h), var(--accent-s), calc(var(--accent-l) + 7%)) 0%,
    var(--accent) 52%,
    hsl(var(--accent-h), var(--accent-s), calc(var(--accent-l) - 8%)) 100%);
  --accent-gradient-hover: linear-gradient(
    180deg,
    hsl(var(--accent-h), var(--accent-s), calc(var(--accent-l) + 9%)) 0%,
    var(--accent) 50%,
    hsl(var(--accent-h), var(--accent-s), calc(var(--accent-l) - 11%)) 100%);

  /* --- Élévations ---------------------------------------------------------
     Système `--elevation-*` de l'app, qui supersède les vieux `--shadow-*`.
     Deux couches : un contact net et proche, une diffusion large et douce. */
  --elevation-1: 0 1px 2px rgba(15, 23, 42, 0.04), 0 1px 3px rgba(15, 23, 42, 0.06);
  --elevation-2: 0 2px 4px rgba(15, 23, 42, 0.04), 0 4px 8px rgba(15, 23, 42, 0.08);
  --elevation-3: 0 4px 8px rgba(15, 23, 42, 0.05), 0 12px 24px rgba(15, 23, 42, 0.10);

  /* --- Mouvement ----------------------------------------------------------
     Courbes de `tokens/design_tokens.css`. Identiques à celles de l'app, pour
     que les deux surfaces aient le même geste. */
  --ease-premium: cubic-bezier(0.22, 1, 0.36, 1);
  --ease-spring:  cubic-bezier(0.34, 1.56, 0.64, 1);
  --ease-snappy:  cubic-bezier(0.19, 1, 0.22, 1);

  /* --- Formes ------------------------------------------------------------- */
  --r-btn:  12px;          /* `flowayz_override.css` : 12, pas 8 */
  --r-tile: 20px;          /* rayon des tuiles Bento */
  --r-sm:   8px;

  /* --- Typographie -------------------------------------------------------- */
  --font-display: 'DM Serif Display', 'Times New Roman', serif;
  --font-body:    'Libre Franklin', system-ui, sans-serif;

  /* --- Gabarit ------------------------------------------------------------
     Une ligne de 75 caractères se lit ; une ligne de 140 se perd. La copy de
     cette page est faite de phrases courtes qu'il faut lire l'une après
     l'autre, pas d'un pavé à survoler. */
  --maxw:       1120px;
  --maxw-prose: 62ch;
  --gutter:     32px;
}

/* ===== Thème sombre ==========================================================
   On inverse la LUMINOSITÉ sans perdre la CHALEUR. Les valeurs sont celles du
   bloc sombre de `design_tokens.css` : near-black chaud, jamais #000, et les
   cartes remontent d'un cran au lieu de descendre.

   L'accent s'ÉCLAIRCIT (59% → 72%) : c'est la règle du système d'accent de
   l'app. Une teinte calibrée pour un fond clair perd son contraste sur un fond
   sombre, et l'orange y devient boueux.

   ⚠️ TROIS sélecteurs, pas deux. Le script d'initialisation partagé pose
   `data-theme`, `data-mode` ET la classe `.dark` ; l'app cible les trois. Une
   page qui n'en couvrirait que deux resterait claire chez quelqu'un dont le
   choix a été posé par l'autre chemin.
   ============================================================================= */

html[data-theme="dark"],
html[data-mode="dark"],
html.dark {
  --paper:      #0B0C0F;
  --paper-2:    #101216;
  --surface:    #15181E;
  --surface-2:  #1C2027;

  --ink:        #F4F5F7;
  --ink-2:      #C9CFD8;
  --ink-3:      #8A909B;

  --line:        rgba(255, 255, 255, 0.07);
  --line-faint:  rgba(255, 255, 255, 0.04);
  --line-strong: rgba(255, 255, 255, 0.16);

  --accent-l: 72%;
  --accent-deep: hsl(var(--accent-h), var(--accent-s), 22%);

  --elevation-1: 0 1px 2px rgba(0, 0, 0, 0.25), 0 1px 3px rgba(0, 0, 0, 0.35);
  --elevation-2: 0 2px 4px rgba(0, 0, 0, 0.30), 0 4px 8px rgba(0, 0, 0, 0.40);
  --elevation-3: 0 4px 8px rgba(0, 0, 0, 0.35), 0 12px 24px rgba(0, 0, 0, 0.50);

  /* Le navigateur doit connaître le thème pour ses éléments natifs : barres de
     défilement, champs, sélection de texte. */
  color-scheme: dark;
}

/* ===== Base ================================================================== */

* { box-sizing: border-box; }

html {
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  scroll-behavior: smooth;
}

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: 17px;
  line-height: 1.6;
  font-weight: 400;
  /* Chiffres tabulaires, comme dans toute l'application : sans eux, les
     montants et les ordinaux dansent d'une ligne à l'autre. */
  font-variant-numeric: tabular-nums;
}

a { color: inherit; text-decoration: none; }

h1, h2, h3 {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 400;
  line-height: 1.06;
  letter-spacing: -0.01em;
}

p { margin: 0; }
img { max-width: 100%; display: block; }

::selection { background: var(--accent-20); }

/* Focus à double anneau — repris tel quel du système global de l'application
   (`components/bundle.css`). L'anneau intérieur est de la couleur du fond : il
   creuse un liseré qui détache l'anneau d'accent, quel que soit ce qu'il y a
   derrière. `:where()` maintient la spécificité à zéro, donc n'importe quelle
   règle plus loin peut le remplacer sans lutte de poids. */
:where(a, button, summary, [tabindex]):focus-visible {
  outline: none;
  box-shadow: 0 0 0 2px var(--paper),
              0 0 0 4px hsla(var(--accent-h), var(--accent-s), var(--accent-l), 0.55);
  border-radius: var(--r-sm);
}

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

.lv10-prose { max-width: var(--maxw-prose); }

/* Lien d'évitement — masqué jusqu'au focus clavier */
.lv10-skip {
  position: absolute;
  inset-inline-start: -9999px;
  top: 0;
  z-index: 100;
  padding: 12px 20px;
  background: var(--surface);
  color: var(--ink);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-sm);
}
.lv10-skip:focus { inset-inline-start: 16px; top: 16px; }

/* Texte réservé aux lecteurs d'écran. Jamais `display: none` : cela le retire
   aussi de l'arbre d'accessibilité, ce qui est exactement l'inverse du but. */
.lv10-sr {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* ===== Boutons ===============================================================
   La signature de l'application, portée telle quelle depuis
   `flowayz_override.css:178` — qui a le DERNIER MOT dans l'app, et non le
   `.btn-primary` du bundle. Quatre couches y participent :

     1. le dégradé vertical, qui donne le volume ;
     2. la bordure `--accent-edge`, 16% plus sombre, qui pose l'arête ;
     3. la triple ombre — lèvre blanche intérieure, halo d'accent, ombre
        portée neutre ;
     4. le reflet qui balaie au survol.

   Cible tactile de 48px de haut au minimum (WCAG 2.5.5 en demande 44 ; on prend
   de la marge, la cible porte parfois des gants).
   ============================================================================= */

.lv10-btn {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 48px;
  padding: 14px 28px;
  white-space: nowrap;
  font-family: var(--font-body);
  font-size: 16px;
  font-weight: 600;
  letter-spacing: 0.01em;
  border: 1px solid transparent;
  border-radius: var(--r-btn);
  cursor: pointer;
  overflow: hidden;
  transition: box-shadow 0.22s var(--ease-premium),
              transform 0.22s var(--ease-premium),
              background 0.2s ease,
              border-color 0.2s ease,
              color 0.2s ease;
}

.lv10-btn--primary {
  background: var(--accent-gradient);
  color: var(--accent-contrast);
  border-color: var(--accent-edge);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.28),
              0 8px 22px -8px var(--accent),
              0 2px 6px -2px rgba(15, 23, 42, 0.18);
}

.lv10-btn--primary:hover {
  background: var(--accent-gradient-hover);
  /* Un pixel de lévitation, jamais un agrandissement. */
  transform: translateY(-1px);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.32),
              0 12px 30px -8px var(--accent),
              0 3px 10px -2px rgba(15, 23, 42, 0.22);
}

/* Pression : le bouton s'enfonce. L'ombre passe à l'intérieur — c'est ce qui
   fait la différence entre « cliqué » et « déplacé ». */
.lv10-btn--primary:active {
  transform: translateY(0);
  box-shadow: inset 0 2px 5px rgba(15, 23, 42, 0.20),
              0 4px 12px -6px var(--accent);
}

/* Le reflet. Le contenu du bouton doit passer AU-DESSUS, d'où le z-index sur
   les enfants directs — sans lui, le balayage blanchit le libellé au passage. */
.lv10-btn > * { position: relative; z-index: 1; }

.lv10-btn--primary::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background: linear-gradient(105deg,
              transparent 35%,
              rgba(255, 255, 255, 0.45) 50%,
              transparent 65%);
  transform: translateX(calc(var(--dir, 1) * -130%));
}

@media (prefers-reduced-motion: no-preference) {
  .lv10-btn--primary::before { transition: transform 0.75s var(--ease-premium); }
  .lv10-btn--primary:hover::before { transform: translateX(calc(var(--dir, 1) * 130%)); }
}

.lv10-btn--ghost {
  background: transparent;
  color: var(--ink);
  border-color: var(--line-strong);
}
.lv10-btn--ghost:hover {
  border-color: var(--accent);
  color: var(--accent);
  background: var(--accent-5);
}

/* ===== Cartes ================================================================
   Langage de `components/cards.css` : la hiérarchie vient des bordures et du
   fond, pas des ombres. Une carte au repos est PLATE ; elle ne se soulève qu'au
   survol, et seulement si elle est cliquable. */

.lv10-card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-tile);
  padding: 26px;
  transition: box-shadow 0.26s var(--ease-premium),
              border-color 0.26s var(--ease-premium),
              transform 0.26s var(--ease-premium);
}

/* La carte du socle : la seule élevée au repos de toute la page. Elle porte le
   filet d'accent qui dit « c'est là que tout commence ». */
.lv10-card--anchor {
  box-shadow: var(--elevation-2);
  border-color: var(--accent-20);
}

.lv10-card--link:hover {
  transform: translateY(-2px);
  border-color: var(--accent-30);
  box-shadow: var(--elevation-3), 0 0 20px var(--accent-10);
}

/* ===== Sections ============================================================== */

.lv10-section { border-top: 1px solid var(--line-faint); }
.lv10-pad     { padding: 80px 0; }
.lv10-sunk    { background: var(--paper-2); }

/* Le sur-titre de section — l'« eyebrow » de `premium_motion.css`. C'est le seul
   endroit où l'accent sert en typographie, et il est assez petit pour ne pas
   consommer le quota d'apparitions. */
.lv10-eyebrow {
  display: block;
  margin-bottom: 14px;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-3);
}

.lv10-h2 {
  font-size: clamp(30px, 5vw, 52px);
  line-height: 1.08;
  letter-spacing: -0.02em;
}

/* Filet qui pousse à l'apparition de la section — repris de `.premium-rule`. Un
   geste de trois-quarts de seconde qui ne coûte qu'une propriété animée. */
.lv10-rule {
  height: 1px;
  width: 0;
  margin-top: 22px;
  background: var(--accent);
  transition: width 0.9s var(--ease-premium);
}
.lv10-rule.is-visible { width: 72px; }

/* Suites de paragraphes : la copy est faite de phrases isolées, chacune sur sa
   ligne, séparées par du blanc. C'est le rythme du texte source. */
.lv10-lines {
  margin-top: 30px;
  display: grid;
  gap: 20px;
  max-width: var(--maxw-prose);
}

.lv10-lines p {
  font-size: clamp(17px, 2.1vw, 19px);
  color: var(--ink-2);
}
.lv10-lines p:last-child { color: var(--ink); }

/* ===== Révélation au défilement ==============================================
   Un seul mécanisme pour toute la page, piloté par l'IntersectionObserver du
   layout. Opacité et translation seules : ce sont les deux propriétés que le
   navigateur anime sans recalculer la mise en page.

   ⚠️ L'état initial est posé SOUS `@media (prefers-reduced-motion: no-preference)`
   et non l'inverse. Si la règle vivait par défaut, quelqu'un qui demande moins
   de mouvement — ou dont le JS ne s'exécute pas — verrait une page vide. Ici,
   sans préférence exprimée pour le mouvement, le contenu est simplement là. */
@media (prefers-reduced-motion: no-preference) {
  .lv10-reveal {
    opacity: 0;
    transform: translateY(12px);
    transition: opacity 0.5s var(--ease-premium),
                transform 0.5s var(--ease-premium);
  }
  .lv10-reveal.is-visible {
    opacity: 1;
    transform: none;
  }
}

/* ===== Barre de navigation ====================================================
   STATIQUE sous 768px, collante au-delà. La contrainte la plus dure du hero est
   que son bouton reste visible sans défiler sur un iPhone SE (375x667) : une
   barre collante de 74px y prélève 11% de la hauteur utile en permanence.
   ============================================================================= */

.lv10-nav {
  position: static;
  background: var(--paper);
  border-bottom: 1px solid var(--line-faint);
}

.lv10-nav__in {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  height: 64px;
}

.lv10-brand { display: inline-flex; align-items: center; min-height: 44px; }
.lv10-brand img { height: 32px; width: auto; }

/* `flowayz_logo_tag` rend DEUX images alternées par des classes Tailwind
   (`dark:hidden` / `hidden dark:block`). Tailwind n'est pas chargé ici : sans
   ces deux règles, les deux logos s'affichent CÔTE À CÔTE et font déborder
   toute la page. Le défaut a déjà été livré une fois (v9), invisible pour
   34 exemples de spec. */
.lv10-brand img[class*="dark:block"] { display: none; }
html[data-theme="dark"] .lv10-brand img[class*="dark:block"],
html[data-mode="dark"] .lv10-brand img[class*="dark:block"],
html.dark .lv10-brand img[class*="dark:block"] { display: block; }
html[data-theme="dark"] .lv10-brand img[class*="dark:hidden"],
html[data-mode="dark"] .lv10-brand img[class*="dark:hidden"],
html.dark .lv10-brand img[class*="dark:hidden"] { display: none; }

.lv10-nav__cta {
  display: flex;
  align-items: center;
  gap: 12px;
}

.lv10-nav__login {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: 0 6px;
  font-size: 15px;
  color: var(--ink-2);
}
.lv10-nav__login:hover { color: var(--ink); }

/* Bascule de thème — même gabarit que la commande de langue, pour que les deux
   se lisent comme une paire. */
.lv10-theme {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 44px;
  min-height: 44px;
  padding: 0;
  background: none;
  border: 0;
  border-radius: var(--r-sm);
  color: var(--ink-2);
  cursor: pointer;
  transition: color 0.18s var(--ease-snappy), background-color 0.18s var(--ease-snappy);
}
.lv10-theme:hover { color: var(--ink); background: var(--line-faint); }
.lv10-theme svg { width: 19px; height: 19px; }

.lv10-theme__moon { display: none; }
html[data-theme="dark"] .lv10-theme__sun,
html[data-mode="dark"] .lv10-theme__sun,
html.dark .lv10-theme__sun { display: none; }
html[data-theme="dark"] .lv10-theme__moon,
html[data-mode="dark"] .lv10-theme__moon,
html.dark .lv10-theme__moon { display: block; }

/* ===== Hero ==================================================================
   Asymétrique au-delà de 1024px : le texte à gauche, l'objet « devis » à droite.
   Sous ce seuil l'objet passe dessous — à 375px il ferait 40% de la hauteur
   utile et repousserait le bouton hors de l'écran, ce qui est exactement la
   contrainte de recette que la v9 avait posée.
   ============================================================================= */

/* --- Le fond de rivière ------------------------------------------------------
   Reprise de la v8 et de la v9 : c'est un actif de la marque, pas une image
   d'illustration — la rivière image le « flow », et elle répond au van.

   🔴 LA v9 LA SERT EN 381 Ko, EN JPEG, À TOUS LES ÉCRANS, et le gate de poids
   ne la compte pas : elle est déclarée en `background-image` dans la feuille,
   pas en balise. Personne ne l'a donc jamais vue passer. Ici, trois largeurs en
   AVIF avec repli WebP — un téléphone reçoit 33 Ko au lieu de 381.

   ⚠️ Le `../` du chemin est indispensable : Propshaft résout par rapport au
   chemin LOGIQUE de la feuille (`pages/landing_v10.css`), donc sans lui il
   cherche `pages/landing/v10/...` et sert un 404 SILENCIEUX.

   `image-set()` choisit le format ; les media queries choisissent la largeur.
   Le préfixe `-webkit-` couvre les Safari antérieurs à 17.

   LE VOILE EST DE LA COULEUR DU PAPIER, jamais un aplat neutre. C'est ce qui
   rend l'ensemble gratuit en maintenance : en thème clair il éclaircit la photo
   jusqu'au ton du reste de la page et l'encre sombre reste lisible ; en thème
   sombre il l'assombrit et l'encre, qui a basculé au crème, l'est tout autant.
   Aucune règle de couleur de texte n'a besoin d'exister pour ce hero. */
.lv10-hero {
  padding: 64px 0 72px;
  position: relative;
  isolation: isolate;               /* le voile ne peut pas déborder du hero */
  background-image: -webkit-image-set(
      url("/assets/landing/v10/riviere-768-8839b68c.avif") type("image/avif"),
      url("/assets/landing/v10/riviere-768-33529ab5.webp") type("image/webp"));
  background-image: image-set(
      url("/assets/landing/v10/riviere-768-8839b68c.avif") type("image/avif"),
      url("/assets/landing/v10/riviere-768-33529ab5.webp") type("image/webp"));
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
}

.lv10-hero::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  /* 0,86 en clair : la photo doit rester une TEXTURE sous le titre, pas une
     image qui lui dispute l'attention. Le hero porte un objet devis à droite,
     et deux points d'intérêt concurrents en feraient un hero illisible. */
  background: rgba(239, 236, 231, 0.86);
}

html[data-theme="dark"] .lv10-hero::before,
html[data-mode="dark"] .lv10-hero::before,
html.dark .lv10-hero::before {
  /* Plus transparent en sombre : la photo est déjà sombre, elle n'a pas besoin
     d'être écrasée, et c'est le thème où elle se donne vraiment à voir. */
  background: rgba(11, 12, 15, 0.74);
}

.lv10-hero__grid { display: grid; gap: 48px; }

/* ⚠️ `min-width: 0` N'EST PAS UNE PRÉCAUTION DÉCORATIVE. Un enfant de grille
   vaut `min-width: auto` par défaut, c'est-à-dire « jamais plus étroit que mon
   contenu ». L'objet devis contient une phrase en `white-space: nowrap` : sans
   cette ligne, la colonne impose sa largeur, et c'est TOUTE LA PAGE qui déborde
   horizontalement, pas seulement le hero.
   Mesuré à 320px avant correction : 17px de débordement, et douze éléments du
   hero s'étendant de 20 à 337 au lieu de 20 à 300. */
.lv10-hero__grid > * { min-width: 0; }

/* La signature du van, en anglais quelle que soit la langue de la page. C'est du
   lettrage cité, pas de la copy. */
.lv10-hero__signature {
  margin-bottom: 22px;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-3);
}

.lv10-hero h1 {
  font-size: clamp(38px, 6.4vw, 68px);
  line-height: 1.04;
  letter-spacing: -0.025em;
  /* Sur le hub, la colonne de la grille borne déjà le titre. Sur les pages de
     pôle il n'y a pas de seconde colonne : sans cette borne il court sur les
     1 056 px du gabarit, et une ligne de titre aussi longue cesse de se lire
     d'un seul regard. La valeur est en `em`, donc elle suit la taille de police
     et vaut aussi bien pour les langues aux mots longs. */
  max-width: 13.5em;
}

/* Une ligne par phrase — `display: block` sur des `span`, jamais de `<br>` : le
   titre reste UNE phrase continue pour un lecteur d'écran et pour l'indexation,
   et la mise en page ne s'écrit pas dans le fichier de copy. */
.lv10-hero__line { display: block; }

.lv10-hero__sub {
  margin-top: 26px;
  max-width: 30em;
  font-size: clamp(18px, 2.6vw, 22px);
  line-height: 1.5;
  color: var(--ink-2);
}

.lv10-hero__actions { margin-top: 34px; }

.lv10-hero__note {
  margin-top: 14px;
  font-size: 14px;
  color: var(--ink-3);
}

/* Les quatre temps du métier. Ce sont les MÊMES quatre mots que les sections de
   la barre latérale de l'application : quelqu'un qui s'inscrit après avoir lu
   ceci retrouve la structure annoncée dès son premier écran. Si les libellés de
   la sidebar changent, ceux-ci doivent suivre. */
.lv10-poles { margin-top: 44px; }

.lv10-poles__list {
  margin: 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: 6px 0;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-3);
}

/* Les séparateurs sont posés par le CSS, jamais dans le texte — sinon ils
   seraient lus à voix haute entre chaque mot. */
.lv10-poles__item + .lv10-poles__item::before {
  content: "·";
  margin: 0 12px;
  color: var(--line-strong);
}

.lv10-poles__note {
  margin-top: 12px;
  font-size: 14px;
  color: var(--ink-3);
}

/* ===== L'objet « devis » =====================================================
   La preuve visuelle du hero, dessinée en CSS. Zéro image, zéro requête, et
   surtout : AUCUN TEXTE FIGÉ. Les libellés viennent du gabarit, donc l'objet
   fonctionne dans les six langues sans qu'on retouche un pixel.

   C'est la raison pour laquelle il remplace une capture d'écran : une capture
   d'interface française est fausse sur /de, elle pèse ~35 Ko, et elle vieillit à
   chaque retouche du produit.
   ============================================================================= */

.lv10-quote {
  position: relative;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-tile);
  box-shadow: var(--elevation-3);
  padding: 22px;
  max-width: 460px;
}

/* La phrase qu'on saisit, en haut. Un champ, pas un titre. */
.lv10-quote__prompt {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 13px 15px;
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--r-btn);
  color: var(--ink-2);
  /* La phrase est en `nowrap` — l'effet de frappe l'exige. Elle doit donc
     RÉTRÉCIR au lieu de pousser, sinon elle fixe un plancher de largeur à toute
     la page. À 320px, 11,5px suffisent à la contenir dans les 206px
     disponibles ; au-delà de 425px la borne haute reprend la main. */
  font-size: clamp(11.5px, 3.6vw, 14.5px);
}

.lv10-quote__typed {
  display: inline-block;
  overflow: hidden;
  white-space: nowrap;
  vertical-align: bottom;
}

/* Le curseur clignotant, en accent. Un pseudo-élément : rien à ajouter dans le
   gabarit, et il disparaît avec l'animation quand le mouvement est refusé. */
.lv10-quote__caret {
  display: inline-block;
  width: 2px;
  height: 1.05em;
  background: var(--accent);
  vertical-align: text-bottom;
}

.lv10-quote__doc { margin-top: 18px; }

.lv10-quote__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  padding-bottom: 12px;
  border-bottom: 1px solid var(--line);
}

.lv10-quote__title {
  font-family: var(--font-display);
  font-size: 19px;
  color: var(--ink);
}

.lv10-quote__ref {
  font-size: 12px;
  letter-spacing: 0.08em;
  color: var(--ink-3);
}

.lv10-quote__rows { margin-top: 4px; }

.lv10-quote__row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 11px 0;
  border-bottom: 1px solid var(--line-faint);
  font-size: 14px;
  color: var(--ink-2);
}

/* Les barres grises qui figurent le texte des lignes. Une largeur par rang, pour
   que le bloc ait l'irrégularité d'un vrai devis plutôt que l'alignement d'un
   tableau de démonstration. */
.lv10-quote__bar {
  height: 9px;
  border-radius: 999px;
  background: var(--line);
  flex: 0 1 auto;
}
.lv10-quote__row:nth-child(1) .lv10-quote__bar { width: 58%; }
.lv10-quote__row:nth-child(2) .lv10-quote__bar { width: 72%; }
.lv10-quote__row:nth-child(3) .lv10-quote__bar { width: 46%; }
.lv10-quote__row:nth-child(4) .lv10-quote__bar { width: 64%; }

.lv10-quote__amount {
  flex: 0 0 auto;
  height: 9px;
  width: 42px;
  border-radius: 999px;
  background: var(--line-strong);
  opacity: 0.55;
}

.lv10-quote__total {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  margin-top: 14px;
  padding-top: 14px;
  border-top: 1px solid var(--line-strong);
  font-size: 14px;
  font-weight: 600;
  color: var(--ink);
}

.lv10-quote__total-value {
  height: 11px;
  width: 68px;
  border-radius: 999px;
  background: var(--accent);
}

/* --- L'animation ------------------------------------------------------------
   Une seule exécution, jamais de boucle : le hero est vu dès l'arrivée, une
   boucle ne servirait qu'à distraire et à consommer de la batterie.

   Sous `prefers-reduced-motion: reduce`, rien de tout ceci ne s'applique — la
   phrase est simplement écrite et les lignes simplement présentes. */
/* ⚠️ LA DURÉE TOTALE EST UNE CONTRAINTE, PAS UN RÉGLAGE D'AMBIANCE.

   Une première version étalait la séquence sur 3,9 s. Conséquence mesurée à la
   capture : pendant près de quatre secondes, l'objet est une CARTE VIDE. C'est
   ce que voient une capture d'écran, un aperçu social, un visiteur qui arrive et
   défile aussitôt — et c'est la seule preuve visuelle du hero.

   La séquence tient donc en 2,3 s au total, et l'ordre reste lisible : on écrit
   la phrase, PUIS le devis s'écrit. Ne pas rallonger sans re-capturer. */
@media (prefers-reduced-motion: no-preference) {
  .lv10-quote__typed {
    width: 0;
    animation: lv10-type 1.15s steps(36, end) 0.15s forwards;
  }

  .lv10-quote__caret {
    animation: lv10-blink 1s steps(2, start) infinite;
  }

  .lv10-quote__row,
  .lv10-quote__total {
    opacity: 0;
    animation: lv10-row-in 0.4s var(--ease-premium) forwards;
  }

  /* La cascade démarre juste après la frappe (0,15 + 1,15 = 1,3 s). */
  .lv10-quote__row:nth-child(1) { animation-delay: 1.35s; }
  .lv10-quote__row:nth-child(2) { animation-delay: 1.47s; }
  .lv10-quote__row:nth-child(3) { animation-delay: 1.59s; }
  .lv10-quote__row:nth-child(4) { animation-delay: 1.71s; }
  .lv10-quote__total            { animation-delay: 1.90s; }
}

@keyframes lv10-type {
  from { width: 0; }
  to   { width: 100%; }
}

@keyframes lv10-blink {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0; }
}

@keyframes lv10-row-in {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: none; }
}

/* ===== 1 · La scène ==========================================================
   La seule photographie de la moitié haute. Pleine largeur, sombre, avec la
   copy posée dessus.

   Le voile est INDISPENSABLE et n'est pas décoratif : sans lui, le contraste du
   texte dépend de ce que contient la photo à cet endroit, ce qui n'est pas
   vérifiable. Avec lui, il est garanti par construction.
   ============================================================================= */

.lv10-scene {
  position: relative;
  isolation: isolate;
  background: #0B0C0F;
  overflow: hidden;
}

.lv10-scene__media {
  position: absolute;
  inset: 0;
  z-index: -2;
}

.lv10-scene__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* Le point d'intérêt de la photo de nuit est en haut à droite (l'écran) ;
     centrer recadrerait sur le bureau vide. */
  object-position: 60% 40%;
}

/* Les opacités ne sont pas choisies à l'œil : elles sont calculées pour que le
   texte tienne le contraste sur le PIRE point de la photo — la lampe, proche du
   blanc pur. À 0,90 sur la gauche où vit le texte, un pixel à 255 retombe à 35 :
   le crème (#F4F5F7) y est à plus de 12:1, très au-delà du seuil AA. La droite
   s'allège à 0,42 pour que la scène reste une scène et pas un aplat. */
.lv10-scene::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(100deg,
              rgba(11, 12, 15, 0.90) 0%,
              rgba(11, 12, 15, 0.74) 52%,
              rgba(11, 12, 15, 0.42) 100%);
}

.lv10-scene__inner { padding: 96px 0; }

.lv10-scene h2 {
  max-width: 15em;
  font-size: clamp(28px, 5vw, 48px);
  color: #F4F5F7;
}

.lv10-scene .lv10-lines { max-width: 34em; }
.lv10-scene .lv10-lines p { color: rgba(244, 245, 247, 0.74); }
.lv10-scene .lv10-lines p:last-child { color: #F4F5F7; }
.lv10-scene .lv10-eyebrow { color: rgba(244, 245, 247, 0.55); }

/* ===== 2 · Le principe =======================================================
   Quatre temps en frise verticale. Le filet qui les relie est posé sur la LISTE
   et non sur chaque élément, sans quoi il redémarrerait à chaque puce. */

.lv10-steps {
  position: relative;
  margin: 40px 0 0;
  padding: 0 0 0 42px;
  list-style: none;
  display: grid;
  gap: 30px;
  max-width: var(--maxw-prose);
}

.lv10-steps::before {
  content: "";
  position: absolute;
  inset-inline-start: 12px;
  top: 8px;
  bottom: 8px;
  width: 1px;
  background: var(--line);
}

.lv10-step { position: relative; }

/* L'ordinal, dans une pastille posée sur le filet. Le fond OPAQUE est ce qui
   coupe le trait proprement à chaque étape. */
.lv10-step__n {
  position: absolute;
  inset-inline-start: -42px;
  top: 1px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 25px;
  height: 25px;
  border-radius: 999px;
  background: var(--paper);
  border: 1px solid var(--line-strong);
  font-size: 12px;
  font-weight: 700;
  color: var(--ink-3);
}

.lv10-step p {
  font-size: clamp(17px, 2.1vw, 19px);
  color: var(--ink);
  line-height: 1.5;
}

.lv10-step__after {
  margin-top: 34px;
  max-width: var(--maxw-prose);
  color: var(--ink-2);
}

/* ===== 3 · Les quatre pôles ================================================== */

.lv10-poles-grid {
  margin-top: 40px;
  display: grid;
  gap: 20px;
}

.lv10-pole__label {
  display: block;
  margin-bottom: 10px;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-3);
}

.lv10-pole__title {
  font-family: var(--font-display);
  font-size: clamp(21px, 3vw, 27px);
  line-height: 1.15;
  color: var(--ink);
}

.lv10-pole__body {
  margin-top: 12px;
  color: var(--ink-2);
  line-height: 1.55;
}

.lv10-pole__more {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  margin-top: 12px;
  font-size: 14.5px;
  font-weight: 600;
  color: var(--accent);
}
.lv10-pole__more:hover { text-decoration: underline; text-underline-offset: 3px; }

.lv10-pole__object { margin-bottom: 18px; }

.lv10-poles-note {
  margin-top: 30px;
  max-width: var(--maxw-prose);
  color: var(--ink-2);
}

/* ===== Objets produit dessinés ===============================================
   Quatre petites vignettes en SVG, une par pôle. Volontairement schématiques :
   elles disent « un document », « un montant relancé », « un créneau », « une
   page partagée » — pas « voici l'écran exact ». Une promesse de forme, pas de
   pixel. */

.lv10-object {
  width: 100%;
  height: auto;
  max-width: 168px;
}

.lv10-object__paper { fill: var(--surface-2); stroke: var(--line-strong); }
.lv10-object__bar   { fill: var(--line-strong); opacity: 0.4; }
.lv10-object__mark  { fill: var(--accent); }
.lv10-object__line  { stroke: var(--line-strong); opacity: 0.55; }

/* ===== 4 · Les trente paires =================================================
   Le cœur de la page.

   La colonne des DOULEURS doit se lire seule et d'une traite : beaucoup ne
   liront que les `dt`, et enchaînés, ils racontent déjà leur semaine. D'où le
   traitement — la douleur en corps supérieur et en encre pleine, la réponse en
   secondaire, marquée d'un filet d'accent.

   L'inverse (mettre la réponse en avant) transformerait la section en liste de
   fonctionnalités, ce qui est exactement ce que cette copy refuse d'être.
   ============================================================================= */

.lv10-pairs {
  margin: 34px 0 0;
  display: grid;
  gap: 26px;
}

/* ⚠️ Une marge sur `.lv10-pairs__group + .lv10-pairs__group` NE FONCTIONNE PAS
   ici, et le défaut était visible en capture : chaque groupe vit dans son PROPRE
   `.lv10-wrap` (la respiration doit pouvoir sortir en pleine largeur entre
   deux), donc les groupes ne sont jamais frères. Le sélecteur adjacent ne
   trouvait rien et les titres de groupe venaient se coller à la dernière paire
   du groupe précédent.

   La marge est donc portée par le groupe lui-même. Le premier en hérite aussi,
   ce qui tombe bien : il en a besoin sous le titre de section. */
.lv10-pairs__group { margin-top: 64px; }

.lv10-pairs__heading {
  display: flex;
  align-items: center;
  gap: 16px;
  font-size: 12.5px;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-3);
}

/* Le filet qui prolonge l'étiquette de groupe jusqu'au bord. `flex: 1` plutôt
   qu'une largeur : il s'adapte à la longueur du mot, qui varie beaucoup d'une
   langue à l'autre (« Rendez-vous » contre « Terminvereinbarung »). */
.lv10-pairs__heading::after {
  content: "";
  flex: 1 1 auto;
  height: 1px;
  background: var(--line);
}

.lv10-pair {
  padding-bottom: 24px;
  border-bottom: 1px solid var(--line-faint);
}

.lv10-pair:last-child { padding-bottom: 0; border-bottom: 0; }

.lv10-pair dt {
  font-size: clamp(17px, 2.2vw, 19px);
  font-weight: 600;
  color: var(--ink);
  line-height: 1.45;
}

.lv10-pair dd {
  margin: 10px 0 0;
  padding-inline-start: 16px;
  border-inline-start: 2px solid var(--accent);
  color: var(--ink-2);
  line-height: 1.55;
}

/* ===== La respiration ========================================================
   Une phrase seule, centrée, pleine largeur, sur l'encre. Elle coupe la liste
   en deux — c'est sa seule fonction. En serif et en grand : elle doit se lire
   comme une conclusion, pas comme une trente-et-unième paire. */

.lv10-breath {
  margin: 64px 0;
  padding: 72px 0;
  background: var(--ink);
}

.lv10-breath p {
  margin: 0 auto;
  max-width: 20em;
  text-align: center;
  font-family: var(--font-display);
  font-size: clamp(26px, 4.6vw, 44px);
  line-height: 1.12;
  letter-spacing: -0.015em;
  color: var(--paper);
}

/* ===== 5 · Avant, après ======================================================
   Les en-têtes de colonne sont masqués sous 768px : les deux colonnes y sont
   empilées, un en-tête flottant au-dessus d'une pile ne désignerait rien. La
   lecture reste assurée par les préfixes `lv10-sr` de chaque paire. */

.lv10-vs__heads { display: none; }

.lv10-vs__head {
  font-size: 12.5px;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.lv10-vs__head--after { color: var(--accent); }

.lv10-vs__list {
  margin: 30px 0 0;
  display: grid;
  gap: 22px;
}

.lv10-vs__row {
  padding-bottom: 20px;
  border-bottom: 1px solid var(--line-faint);
}
.lv10-vs__row:last-child { padding-bottom: 0; border-bottom: 0; }

/* L'état actuel est en retrait — c'est ce qu'on quitte. La réponse est en encre
   pleine : c'est là que va le regard. */
.lv10-vs__row dt { color: var(--ink-3); }

.lv10-vs__row dd {
  margin: 6px 0 0;
  color: var(--ink);
  font-weight: 500;
}

.lv10-vs__closing {
  margin-top: 38px;
  max-width: var(--maxw-prose);
  font-size: clamp(17px, 2.1vw, 19px);
  color: var(--ink-2);
}

/* ===== 6 · Les questions =====================================================
   `<details>` natifs. Zéro JavaScript, accessible par construction, et
   fonctionnels avant même que la page ait fini de charger. */

.lv10-faq {
  margin-top: 38px;
  max-width: var(--maxw-prose);
  border-top: 1px solid var(--line-faint);
}

.lv10-faq__item { border-bottom: 1px solid var(--line-faint); }

.lv10-faq__q {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  min-height: 44px;
  padding: 20px 0;
  cursor: pointer;
  list-style: none;
  font-size: clamp(17px, 2.2vw, 19px);
  font-weight: 600;
  color: var(--ink);
  line-height: 1.45;
  transition: color 0.18s var(--ease-snappy);
}

/* Le marqueur natif est retiré des DEUX façons : `list-style` couvre Firefox,
   le pseudo-élément WebKit couvre Safari. Sans les deux, un triangle système
   s'ajoute à côté du signe. */
.lv10-faq__q::-webkit-details-marker { display: none; }
.lv10-faq__q:hover { color: var(--accent); }

/* Le signe + qui devient −. Deux traits en pseudo-éléments plutôt qu'une icône :
   rien à charger, et la rotation se lit mieux qu'un basculement d'image. */
.lv10-faq__sign {
  position: relative;
  flex: 0 0 auto;
  width: 18px;
  height: 18px;
}
.lv10-faq__sign::before,
.lv10-faq__sign::after {
  content: "";
  position: absolute;
  inset-inline-start: 0;
  top: 50%;
  width: 100%;
  height: 1.5px;
  background: var(--ink-3);
  transition: transform 0.28s var(--ease-premium);
}
.lv10-faq__sign::after { transform: rotate(90deg); }
.lv10-faq__item[open] .lv10-faq__sign::after { transform: rotate(0deg); }
.lv10-faq__item[open] .lv10-faq__q { color: var(--accent); }

.lv10-faq__a {
  padding: 0 0 22px;
  max-width: 46em;
  color: var(--ink-2);
  line-height: 1.6;
}

/* ===== Liens de texte ========================================================
   Soulignés. Un lien identifié par la seule couleur est invisible pour qui ne
   distingue pas l'orange du brun, et illisible en plein soleil. */

.lv10-link {
  color: var(--accent);
  text-decoration: underline;
  text-underline-offset: 3px;
  font-weight: 600;
}
.lv10-link:hover { color: var(--accent-hover); }

/* ===== 7 · Ce que contient un compte gratuit ================================= */

.lv10-free {
  margin-top: 36px;
  padding: 40px 32px;
  background: var(--accent-5);
  border: 1px solid var(--accent-20);
  border-radius: var(--r-tile);
  text-align: center;
}

.lv10-free__contains {
  margin: 0 auto;
  max-width: 26em;
  font-size: clamp(18px, 2.4vw, 23px);
  line-height: 1.5;
  color: var(--ink);
}

.lv10-free__note {
  margin-top: 18px;
  color: var(--ink-2);
}

.lv10-free__pricing {
  margin-top: 26px;
  font-size: 15px;
  color: var(--ink-3);
}

/* ===== 8 · La fin ============================================================
   Seconde et dernière photographie. Même construction que la section 1 : voile
   garanti, texte par-dessus, et le CTA qui ferme la page. */

.lv10-end {
  position: relative;
  isolation: isolate;
  background: #0B0C0F;
  overflow: hidden;
}

.lv10-end__media { position: absolute; inset: 0; z-index: -2; }

.lv10-end__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* Cadrage volontairement différent de celui du hero (centre) : le même lieu,
     vu plus bas et plus large. C'est ce décalage qui fait lire les deux images
     comme un aller-retour, et non comme un fichier réemployé par paresse. */
  object-position: 50% 78%;
}

/* Voile vertical, et non horizontal : le texte occupe ici toute la largeur.
   0,66 au point le plus clair — le ciel près du soleil, quasi blanc — ramène un
   pixel à 255 vers 92, où le crème tient environ 6:1. Le descendre à 0,58
   ferait passer le corps de texte tout juste sous le seuil AA : c'est la marge
   qui a fixé la valeur, pas le goût. */
.lv10-end::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(180deg,
              rgba(11, 12, 15, 0.82) 0%,
              rgba(11, 12, 15, 0.66) 52%,
              rgba(11, 12, 15, 0.88) 100%);
}

.lv10-end__inner { padding: 104px 0; }

.lv10-end h2 {
  max-width: 14em;
  font-size: clamp(30px, 5.4vw, 54px);
  color: #F4F5F7;
}

.lv10-end .lv10-lines p { color: rgba(244, 245, 247, 0.74); }
.lv10-end .lv10-lines p:last-child { color: #F4F5F7; }
.lv10-end .lv10-eyebrow { color: rgba(244, 245, 247, 0.55); }

.lv10-end__actions { margin-top: 40px; }

.lv10-end__note {
  margin-top: 14px;
  font-size: 14px;
  color: rgba(244, 245, 247, 0.6);
}

/* ===== Pied de page ==========================================================
   Deux rangées : les quatre pôles d'abord — ils servent autant le visiteur que
   le maillage interne — puis les liens de service. */

.lv10-footer {
  border-top: 1px solid var(--line);
  padding: 44px 0 52px;
}

.lv10-footer__poles,
.lv10-footer__links {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 24px;
}

/* Cible tactile de 44px (WCAG 2.5.5) : ces liens font 20px de haut en texte et
   sont côte à côte — sans hauteur minimale, un doigt en attrape deux. */
.lv10-footer__poles a,
.lv10-footer__links a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  font-size: 15px;
}

.lv10-footer__poles a { color: var(--ink); font-weight: 600; }
.lv10-footer__poles a:hover { color: var(--accent); }

.lv10-footer__links { margin-top: 4px; }
.lv10-footer__links a { color: var(--ink-2); font-size: 14.5px; }
.lv10-footer__links a:hover { color: var(--ink); }

.lv10-footer__signature {
  margin-top: 14px;
  font-size: 14px;
  color: var(--ink-3);
}

/* ===== Une capture d'écran ===================================================
   Traitée comme une PIÈCE, pas comme une illustration : un cadre net, une ombre
   qui la décolle du papier, et une légende qui dit ce qu'on regarde.

   ⚠️ `max-width` à 700px alors que la source fait 768 : elle est donc toujours
   servie légèrement RÉDUITE, jamais agrandie. Une capture d'interface
   suréchantillonnée est immédiatement reconnaissable — le texte y bave — et
   c'est le genre de détail qui décrédibilise une page entière. Le jour où une
   capture de meilleure définition arrive, cette borne peut monter.

   `aspect-ratio` posé sur l'image : la place est réservée avant l'arrivée du
   fichier, donc aucun décalage de mise en page. */
.lv10-shot {
  margin: 44px 0 0;
  max-width: 700px;
}

.lv10-shot__media {
  display: block;
  border-radius: var(--r-tile);
  overflow: hidden;
  border: 1px solid var(--line);
  box-shadow: var(--elevation-3);
  background: var(--surface);
}

.lv10-shot__media img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 768 / 252;
}

.lv10-shot__caption {
  margin-top: 14px;
  font-size: 14.5px;
  line-height: 1.55;
  color: var(--ink-3);
}

/* ===== Pages de pôle =========================================================
   Elles partagent tout le vocabulaire ci-dessus. Ne s'ajoutent ici que le
   fil d'Ariane et le retour vers le hub. */

.lv10-crumb {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  font-size: 14px;
  color: var(--ink-3);
}
.lv10-crumb:hover { color: var(--accent); }

.lv10-back {
  margin-top: 48px;
  padding-top: 32px;
  border-top: 1px solid var(--line-faint);
}

/* =============================================================================
   Responsive — mobile-first. Seuls 640/768/1024/1280/1536 sont autorisés
   (responsive:audit), 767.98 pour la borne haute mobile.
   ============================================================================= */

@media (min-width: 768px) {
  .lv10-nav {
    position: sticky;
    top: 0;
    z-index: 20;
  }
  .lv10-nav__in { height: 74px; }
  .lv10-brand img { height: 38px; }

  .lv10-hero { padding: 88px 0 100px; }
  .lv10-pad  { padding: 112px 0; }

  /* La largeur de la source suit celle de l'écran : inutile d'envoyer 1920 px
     à une tablette, et visiblement mou d'étirer 768 px sur un grand écran. */
  .lv10-hero {
    background-image: -webkit-image-set(
        url("/assets/landing/v10/riviere-1280-34b12a03.avif") type("image/avif"),
        url("/assets/landing/v10/riviere-1280-515cd938.webp") type("image/webp"));
    background-image: image-set(
        url("/assets/landing/v10/riviere-1280-34b12a03.avif") type("image/avif"),
        url("/assets/landing/v10/riviere-1280-515cd938.webp") type("image/webp"));
  }

  .lv10-scene__inner { padding: 136px 0; }
  .lv10-end__inner   { padding: 148px 0; }

  .lv10-free { padding: 56px 48px; }

  /* Les pôles passent en deux colonnes. Trois seraient trop étroites pour que
     les vignettes se lisent — c'est à 1024px qu'elles s'alignent. */
  .lv10-poles-grid { grid-template-columns: repeat(2, 1fr); gap: 24px; }

  /* Les paires passent en deux colonnes : la douleur à gauche, la réponse à
     droite. Sous 768px elles s'empilent — la réponse suit sa douleur, ce qui
     reste l'ordre de lecture juste. */
  .lv10-pair {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 36px;
    align-items: baseline;
  }
  .lv10-pair dd { margin-top: 0; }

  /* Le comparatif passe en deux colonnes, et ses en-têtes apparaissent : ils ne
     désignent quelque chose que lorsque les colonnes existent réellement. */
  .lv10-vs__heads {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 36px;
    margin-top: 38px;
  }

  .lv10-vs__row {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 36px;
    align-items: baseline;
  }
  .lv10-vs__row dd { margin-top: 0; }
}

@media (min-width: 1024px) {
  .lv10-hero {
    background-image: -webkit-image-set(
        url("/assets/landing/v10/riviere-1920-76d15658.avif") type("image/avif"),
        url("/assets/landing/v10/riviere-1920-89c47c97.webp") type("image/webp"));
    background-image: image-set(
        url("/assets/landing/v10/riviere-1920-76d15658.avif") type("image/avif"),
        url("/assets/landing/v10/riviere-1920-89c47c97.webp") type("image/webp"));
  }

  /* Le hero devient asymétrique. 1,15fr et non 1fr : la colonne de texte doit
     rester dominante — c'est le titre qui vend, l'objet ne fait que prouver. */
  .lv10-hero__grid {
    grid-template-columns: 1.15fr 1fr;
    gap: 64px;
    align-items: center;
  }

  .lv10-poles-grid { grid-template-columns: repeat(4, 1fr); }

  /* Le socle occupe la largeur entière au-dessus des trois autres : c'est ce
     qui dit « une base, puis trois domaines » sans l'écrire. */
  .lv10-poles-grid--anchored { grid-template-columns: repeat(3, 1fr); }
  .lv10-poles-grid--anchored .lv10-card--anchor { grid-column: 1 / -1; }
}

/* Sous 768px : gouttières resserrées. La barre reste complète (logo + langue +
   thème + Connexion + bouton), tous en `nowrap` — sans ces réductions elle
   impose une largeur minimale supérieure à l'écran et fait déborder TOUTE la
   page horizontalement, pas seulement la nav. Constaté en v8 à 375px. */
@media (max-width: 767.98px) {
  .lv10-wrap { padding: 0 20px; }
  .lv10-nav__cta { gap: 6px; }
  .lv10-nav__cta .lv10-btn {
    padding: 11px 15px;
    font-size: 14px;
    min-height: 44px;
  }
  .lv10-free { padding: 32px 22px; }
  .lv10-breath { margin: 48px 0; padding: 56px 0; }
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  /* `transition-duration` seul ne couvre PAS les `@keyframes` : le sélecteur de
     langue en emploie pour l'entrée de son panneau, et il continuerait de
     s'animer chez quelqu'un qui demande explicitement moins de mouvement. */
  * {
    transition-duration: 0.01ms !important;
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
  }
}

/* =============================================================================
   Sélecteur de langue — un globe, un drapeau, six langues.

   Repris de `pages/landing_v9.css` où il a été mis au point, avec ses courbes
   d'origine (celles de `base/dopamine.css`, le système d'animation de l'app) :
   le composant doit se comporter comme le reste du produit, pas comme une page
   à part.

   ⚠️ Uniquement `transform` et `opacity` : ce sont les deux seules propriétés
   que le navigateur anime sans recalculer la mise en page. Animer `height` sur
   un menu qui s'ouvre coûterait des images perdues sur la page qui absorbe tout
   le trafic payant.

   ⚠️ Aucun `scale` au SURVOL des lignes (directive Nelwep) : le retour passe par
   le fond, la couleur et un léger glissement. Le `scale(0.96)` de la PRESSION
   sur le globe est un effet de bouton — celui-là est admis.
   ============================================================================= */

.lv10-lang {
  position: relative;
  display: inline-block;
  --lv10-stagger: 45ms;
}

.lv10-lang__current {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 5px;
  min-width: 44px;
  min-height: 44px;
  padding: 0 6px;
  border-radius: var(--r-sm);
  cursor: pointer;
  list-style: none;
  color: var(--ink-2);
  transition: color 0.18s var(--ease-snappy),
              background-color 0.18s var(--ease-snappy),
              transform 0.12s var(--ease-snappy);
}

.lv10-lang__current::-webkit-details-marker { display: none; }
.lv10-lang__current:hover { color: var(--ink); background: var(--line-faint); }
.lv10-lang__current:active { transform: scale(0.96); }

/* Le globe pivote d'un quart de tour à l'ouverture. Le geste dit « on change de
   langue » sans un mot, et il se termine avant que la première ligne du menu
   n'arrive — l'œil suit une chose à la fois. */
.lv10-lang__globe {
  width: 19px;
  height: 19px;
  transition: transform 0.42s var(--ease-spring);
}
.lv10-lang[open] .lv10-lang__globe { transform: rotate(90deg); }

/* Le cadre du drapeau est indispensable, pas décoratif : la bande blanche du
   drapeau polonais et le papier de la barre sont proches en thème clair, sans
   lui le drapeau perd son contour haut. */
.lv10-lang__chip {
  display: block;
  width: 20px;
  height: 14px;
  overflow: hidden;
  border: 1px solid var(--line-strong);
  border-radius: 3px;
}

.lv10-lang__chip svg,
.lv10-lang__flag svg {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Ancré à DROITE : le sélecteur vit au bord droit de la barre, un menu aligné à
   gauche sortirait de l'écran en mobile.

   ⚠️ `min-width` est à 148px et pas plus, et ce n'est pas un réglage esthétique.
   Ancré à droite, le bord GAUCHE du menu vaut « bord droit du sélecteur moins
   la largeur ». À 320px, 168px faisaient sortir le menu de 8px par la gauche et
   coupaient un drapeau. Le débordement était invisible au défilement de la page
   (le menu est en position absolue, donc `scrollWidth` ne bouge pas) : il ne se
   voit qu'en mesurant le menu OUVERT. */
.lv10-lang__menu {
  position: absolute;
  top: calc(100% + 6px);
  inset-inline-end: 0;
  z-index: 30;
  min-width: 148px;
  max-width: calc(100vw - 16px);
  margin: 0;
  padding: 5px;
  list-style: none;
  background: var(--surface);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-btn);
  box-shadow: var(--elevation-3);
  transform-origin: top right;
  animation: lv10-lang-in 0.28s var(--ease-spring) both;
}

@keyframes lv10-lang-in {
  from { opacity: 0; transform: translateY(-6px) scale(0.95); }
  to   { opacity: 1; transform: translateY(0) scale(1); }
}

/* Chaque ligne arrive derrière la précédente. `--i` vient du gabarit : un rang
   posé sur l'élément évite une règle `nth-child` par position, et le décalage
   suit tout seul si une septième langue arrive. */
.lv10-lang__menu li {
  animation: lv10-lang-item-in 0.3s var(--ease-snappy) both;
  animation-delay: calc(60ms + var(--i) * var(--lv10-stagger));
}

@keyframes lv10-lang-item-in {
  from { opacity: 0; transform: translateX(calc(var(--dir, 1) * 6px)); }
  to   { opacity: 1; transform: translateX(0); }
}

/* Le fond de survol glisse depuis la gauche via un pseudo-élément : c'est le
   geste des éléments de navigation de l'application, et il ne touche ni à la
   largeur ni à la hauteur, donc aucun recalcul de mise en page. */
.lv10-lang__opt {
  position: relative;
  isolation: isolate;
  display: flex;
  align-items: center;
  gap: 10px;
  min-height: 44px;
  padding: 0 10px;
  border-radius: var(--r-sm);
  font-family: var(--font-body);
  font-size: 14px;
  font-weight: 500;
  color: var(--ink-2);
  transition: color 0.18s var(--ease-snappy), transform 0.18s var(--ease-snappy);
}

.lv10-lang__opt::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: inherit;
  background: var(--accent-10);
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform 0.24s var(--ease-snappy);
}

.lv10-lang__opt:hover {
  color: var(--ink);
  /* Glissement, pas agrandissement : la ligne ne change pas de taille. */
  transform: translateX(calc(var(--dir, 1) * 2px));
}
.lv10-lang__opt:hover::before { transform: scaleX(1); }

/* Taille fixe : les six SVG ont des rapports différents (2:3 pour l'anglais,
   3:2 pour le français), sans quoi la liste ondulerait. */
.lv10-lang__flag {
  display: block;
  flex: 0 0 auto;
  width: 20px;
  height: 14px;
  overflow: hidden;
  border: 1px solid var(--line-strong);
  border-radius: 3px;
}

.lv10-lang__name { flex: 1 1 auto; }

/* La langue active est marquée par la couleur, la graisse ET une coche : la
   couleur seule ne se distingue pas en plein soleil, ni pour qui ne perçoit pas
   le contraste. */
.lv10-lang__opt.is-active { color: var(--ink); font-weight: 600; }
.lv10-lang__tick { flex: 0 0 auto; width: 15px; height: 15px; color: var(--accent); }
