/* ------------------------------------------------------------------ */
/* Rost — site vitrine.                                                */
/* Composition et mécaniques reprises de getdroppy.app, habillées aux  */
/* couleurs de l'application.                                          */
/* ------------------------------------------------------------------ */

/* Les polices, servies par le site lui-même (audit 7.12) : chargées chez
   Google, elles lui donnaient l'adresse de chaque visiteur. Inter et Inter
   Tight sont des polices VARIABLES (un fichier pour toutes les graisses),
   sous licence SIL Open Font License (`assets/fonts/OFL-*.txt`), découpées
   comme Google les sert : le latin, et le latin étendu que le français
   n'appelle presque jamais (il ne se télécharge que si un caractère le
   demande). Instrument Sans n'était jamais affichée : retirée. */
@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url("../fonts/inter-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url("../fonts/inter-latin-ext.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-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Inter Tight";
  font-style: normal;
  font-weight: 500 700;
  font-display: swap;
  src: url("../fonts/inter-tight-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Inter Tight";
  font-style: normal;
  font-weight: 500 700;
  font-display: swap;
  src: url("../fonts/inter-tight-latin-ext.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-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

:root {
  --bg: #13170C;
  --bg-deep: #0C0F07;
  --accent: #B7D98F;
  --accent-dim: #8FB368;
  --accent-text: #B7D98F;          /* le lime lisible : clair sur sombre, olive sur blanc */
  --accent-ring: rgba(183, 217, 143, 0.35);
  /* LE VERT PLEIN — règle de construction (4 octobre 2026) : il se choisit
     d'après ce qu'il y a DERRIÈRE lui, pas d'après le mode. Sur un fond
     sombre #B7D98F, sur un fond clair #A8CD74, texte #13170C. Aucun autre
     vert plein, aucun bouton en verre vert, dans le site comme dans
     l'application. Chaque dalle qui reste sombre en mode clair (barre, haut
     de page, carte de l'abonnement, pied de page) remet donc `--btn-fill` à
     #B7D98F avec ses autres jetons. `site/tools/check-buttons.mjs` mesure
     le fond derrière chaque vert et le vérifie. */
  --btn-fill: #B7D98F;
  --btn-on-fill: #13170C;
  --text: #ffffff;
  --text-2: rgba(255, 255, 255, 0.75);
  --text-3: rgba(255, 255, 255, 0.55);
  --card: rgba(255, 255, 255, 0.04);
  --card-strong: rgba(255, 255, 255, 0.07);
  --border: rgba(255, 255, 255, 0.08);
  --glass-bg: rgba(255, 255, 255, 0.06);
  --glass-border: rgba(255, 255, 255, 0.14);
  --glass-text: rgba(255, 255, 255, 0.85);
  --shadow-media: rgba(0, 0, 0, 0.45);
  /* Le PLAFOND dont la barre descend. Distinct du fond de la barre : la
     barre reste sombre en mode clair, le plafond non — sinon une bande
     noire barre le haut d'une page blanche. */
  --nav-ceiling: #0A0D06;
  /* La hauteur de bande de getdroppy.app, au pixel. */
  --nav-band-h: 10px;
  /* Les polices de getdroppy.app : Inter pour le courant,             */
  /* Inter Tight pour les titres.                                       */
  --font-ui: "Inter", ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
  --font-display: "Inter Tight", var(--font-ui);
  --ease-out: cubic-bezier(0.22, 1, 0.36, 1);
  --spring: cubic-bezier(0.34, 1.56, 0.64, 1);
  --dur-slow: 0.7s;
  --radius: 20px;
}

/* ------------------------------------------------------------------ */
/* Mode clair — juste le fond en blanc, l'identité reste. Les dalles   */
/* sombres (barre, wordscroll, preuve, pied de page) ne changent pas : */
/* c'est la composition de Droppy, du sombre posé sur du papier.       */
/* ------------------------------------------------------------------ */
:root[data-theme="light"] {
  --bg: #ffffff;
  --accent-text: #4F6B2E;          /* le #B7D98F foncé, même teinte, lisible sur blanc (29 septembre 2026) */
  --accent-ring: rgba(118, 150, 86, 0.40);
  --btn-fill: #A8CD74;             /* sur le papier : le vert plein des fonds clairs */
  --text: #16190e;
  --text-2: rgba(22, 25, 14, 0.75);
  /* Le gris des petits textes, foncé pour passer le seuil de lecture
     (4,5 pour 1 sur le blanc, audit 7.10 : à 55 % il était à 3,96, et sur
     le verre gris des règles moins encore). Aucun cadre ajouté :
     « mets juste un gris plus foncé mais n'encadre pas » (Matteo). */
  --text-3: rgba(22, 25, 14, 0.66);
  --card: rgba(20, 24, 12, 0.04);
  --card-strong: rgba(20, 24, 12, 0.07);
  --border: rgba(20, 24, 12, 0.10);
  --glass-bg: rgba(20, 24, 12, 0.05);
  --glass-border: rgba(20, 24, 12, 0.14);
  --glass-text: rgba(22, 25, 14, 0.85);
  --shadow-media: rgba(20, 24, 12, 0.18);
  /* La barre du haut, en clair, est une dalle d'olive sombre posée sur
     le papier — la composition de getdroppy.app, où la barre reste
     foncée sur la page claire, et la matière où le logo garde le mieux
     sa couleur d'origine. Essayés et écartés le 23 septembre 2026, à
     l'œil de Matteo : le gris des panneaux (trop pâle), un gris franc
     #929197 (froid), trois vert sauge de #737e62 à #626d51 (ternes). */
  --nav-ceiling: #1e2316;
}
:root[data-theme="light"] { color-scheme: light; }
/* Thème imposé : le choix d'apparence du pied de page est masqué, pas
   supprimé (29 septembre 2026, « si un jour je veux le remettre »). */
:root[data-theme-lock] .appearance { display: none; }
/* Le bas du pied de page, le vert de base : c'est aussi la couleur du
   dépassement du bas. */
:root { --foot-end: #222914; }
/* Le voile de la mise en valeur : une encre du fond, plus profonde que
   la page en sombre, olive foncé sur le papier. */
:root { --spot: rgba(4, 5, 2, 0.64); }
:root[data-theme="light"] { --spot: rgba(22, 25, 14, 0.52); }

/* Les dalles qui RESTENT sombres en mode clair reprennent les jetons
   du thème sombre — une seule liste, sinon chaque section diverge.
   Le pied de page en est sorti : il prend la couleur de la page, dans
   les deux thèmes (voir `.footer`). */
/* La barre, foncée dans les deux thèmes, reprend les jetons du thème
   sombre : texte clair, bouton lime. Son ombre s'allège sur le blanc,
   où celle du sombre faisait un halo sale. */
:root[data-theme="light"] .nav {
  --text: #ffffff;
  --text-2: rgba(255, 255, 255, 0.75);
  --accent-text: #B7D98F;
  --btn-fill: #B7D98F;
  --accent-ring: rgba(183, 217, 143, 0.35);
  color: var(--text);
  box-shadow: var(--nav-bg) 0 -8px 0 0, 0 12px 30px rgba(20, 24, 12, 0.16);
}

/* Les dégradés transparent → sombre des dalles sont invisibles sur fond
   sombre mais font des traînées grises sur blanc. En clair, la preuve et
   le wordscroll deviennent des sections claires : couleurs inversées. */

:root[data-theme="light"] .proof { background: none; }
:root[data-theme="light"] .wordscroll { background: none; }
/* Les mots éteints : gris très pâle sur blanc, au lieu du lime éteint. */
:root[data-theme="light"] .wordscroll.ws-ready .wordscroll__text,
:root[data-theme="light"] .wordscroll.ws-reduced-motion .wordscroll__text { color: rgba(22, 25, 14, 0.14); }
/* Le halo d'un mot : olive lisible, le lime clair disparaît sur blanc. */
:root[data-theme="light"] .wordscroll__text .w-glo {
  text-shadow: 0 0 10px rgba(118, 150, 86, 0.55), 0 0 26px rgba(118, 150, 86, 0.30);
}
/* Étincelles sombres sur papier. */
:root[data-theme="light"] .wordscroll__sparks span { background: rgba(22, 25, 14, 0.5); }
/* La lueur vert tendre du thème clair, sur le modèle de getdroppy.app :
   une lumière qui tombe du HAUT de l'écran, forte sous la barre et qui
   s'estompe vers le texte. Elle arrive quand la scène se fige, avec le
   texte qui s'écrit, et repart quand il cède la place à l'histoire.
   Essayées et retirées le 27 septembre 2026 : sept nappes attachées à des
   objets de toute la page, puis une tache au centre du texte. */
:root[data-theme="light"] .wordscroll__glow {
  background:
    radial-gradient(64% 48% at 50% 0%, rgba(170, 204, 130, 0.52), rgba(183, 217, 143, 0) 100%),
    radial-gradient(115% 82% at 50% 0%, rgba(183, 217, 143, 0.30), rgba(183, 217, 143, 0) 100%);
  opacity: calc(var(--ws-enter, 0) * var(--ws-copy, 1));
}

/* Sur papier blanc, les ombres portées s'allègent et le halo se calme. */
/* L'ombre se resserre DERRIÈRE le téléphone au lieu de s'étaler.
   Quarante pixels vers le bas et quatre-vingts de flou passent inaperçus
   sur du sombre ; sur du blanc, c'est une flaque grise, et les appareils
   inclinés la traînaient sur le côté — on lisait une ombre à droite, pas
   un objet posé. Resserrée, elle ne dit plus qu'une chose : il y a de
   l'épaisseur là-dessous.

   Le liseré, lui, redevient CLAIR — exactement celui du thème sombre,
   à la valeur près. Sombre sur un corps sombre, il ne se voyait pas, et
   les trois téléphones du hero se collaient en une seule masse ; clair,
   il suffit à découper celui de devant sur les deux autres.

   Essayé et retiré : une bande de six pixels à la couleur de la page
   autour du téléphone de devant. Elle découpait, mais elle en faisait
   un autocollant — le liseré du thème sombre est un cheveu, et c'est
   tout ce qu'il faut. */
:root[data-theme="light"] .phone {
  border-color: rgba(255, 255, 255, 0.14);
  box-shadow:
    0 2px 0 rgba(255, 255, 255, 0.08) inset,
    0 10px 26px rgba(20, 24, 12, 0.16),
    0 2px 6px rgba(20, 24, 12, 0.10);
}

* { margin: 0; padding: 0; box-sizing: border-box; }

html {
  /* Le dépassement en haut — le rebond du défilement — montre le fond
     de la TOILE, pas celui du corps. Sans cette ligne, on voit du blanc
     au-dessus de la bande dès qu'on tire la page vers le bas. */
  background: var(--nav-ceiling);
 scroll-behavior: smooth; }
/* Le rebond du BAS montre la même toile, et la toile n'a qu'une couleur.
   Tant que le pied de page était sombre, le hasard les accordait ; il a
   maintenant la couleur de la page, et tirer la page vers le haut
   aurait fait surgir une bande sombre sous lui. Le rebond ne se produit
   qu'aux deux bouts : la toile prend donc la couleur du bout dont on
   est le plus près (`site.js`, `initOverscroll`). */
html.is-low { background: var(--foot-end); }  /* le vert du pied de page */
/* Et la toile ne suffit pas : au changement de thème, le navigateur
   garde en mémoire la couleur du dépassement du haut et remontre
   l'ancien thème au-dessus de la barre. On peint donc AUSSI une nappe à
   la couleur de la barre juste au-dessus du haut de la page : hors de
   l'écran d'ordinaire, c'est elle que le rebond découvre, et comme elle
   fait partie de la page elle change avec le thème, sans mémoire. */
html::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: -100vh;
  height: 100vh;
  background: var(--nav-ceiling);
  pointer-events: none;
}
:root { color-scheme: dark; }

/* Interactions tactiles : pas de délai de double-tap, surbrillance maîtrisée. */
a, button, summary { touch-action: manipulation; -webkit-tap-highlight-color: transparent; }

/* Focus clavier visible sur le fond sombre — jamais retiré, seulement dessiné. */
:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: 4px;
}

body {
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-ui);
  font-size: 17px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  overflow-x: clip;
}

/* ------------------------------------------------------------------ */
/* Fond animé — trois nappes floues fixées derrière la page, qui       */
/* dérivent en sinus au rythme du défilement (voir site.js).           */
/* ------------------------------------------------------------------ */
.bg-motion {
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  overflow: hidden;
}
.bg-blob {
  position: absolute;
  border-radius: 50%;
  filter: blur(80px);
  will-change: transform;
}
.bg-blob--a { top: -12%; left: -10%; width: 55vw; height: 55vw; background: radial-gradient(closest-side, rgba(183, 217, 143, 0.10), transparent 70%); }
.bg-blob--b { top: 30%; right: -18%; width: 60vw; height: 60vw; background: radial-gradient(closest-side, rgba(94, 139, 126, 0.13), transparent 70%); }
.bg-blob--c { bottom: -20%; left: 12%; width: 50vw; height: 50vw; background: radial-gradient(closest-side, rgba(143, 179, 104, 0.07), transparent 70%); }
@media (prefers-reduced-motion: reduce) { .bg-motion { display: none; } }

/* Tout le contenu passe au-dessus des nappes. */
.nav, .hero, section, footer { position: relative; z-index: 1; }

/* Grain — la même recette que l'application : turbulence SVG à 3 %. */
body::after {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  opacity: 0.03;
  mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  background-size: 180px;
}

/* height: auto est indispensable dès que width/height sont posés en
   attributs (anti-CLS) : sans lui, la hauteur d'attribut s'applique
   telle quelle et les captures s'étirent. */
img { display: block; max-width: 100%; height: auto; }
a { color: inherit; text-decoration: none; }
h1, h2, h3, h4 { font-weight: 600; }

.container {
  width: min(1120px, calc(100% - 48px));
  margin: 0 auto;
}
.container--narrow { width: min(760px, calc(100% - 48px)); }

/* ------------------------------------------------------------------ */
/* Reveal au défilement — mécanique de site.js (getdroppy).            */
/* ------------------------------------------------------------------ */
/* Visible par DÉFAUT : un bloc ne se cache, pour entrer ensuite, que si un
   script tourne (`html.js`, posé dans le <head>). Sans script, le titre et
   les boutons restaient invisibles ; en 4G lente, ils le restaient jusqu'à
   l'arrivée de site.js. Le FILET : tant que site.js n'a pas posé `js-ready`,
   les blocs paraissent d'eux-mêmes au bout d'une seconde et demie. */
.js .reveal {
  opacity: 0;
  transform: translateY(24px);
  transition: opacity var(--dur-slow) var(--ease-out), transform var(--dur-slow) var(--ease-out);
  transition-delay: var(--reveal-delay, 0ms);
}
.js:not(.js-ready) .reveal { animation: reveal-failsafe 0.6s var(--ease-out) 1.5s forwards; }
@keyframes reveal-failsafe { to { opacity: 1; transform: none; } }
.js .reveal.is-visible { opacity: 1; transform: translateY(0); }
/* Une fois posé, on retire la boîte de transformation (leçon iOS de Droppy). */
.js .reveal.is-settled { transform: none; transition: none; }

@media (prefers-reduced-motion: reduce) {
  .js .reveal { transition-duration: 1ms; transform: none; }
  html { scroll-behavior: auto; }
}

/* Lu par les lecteurs d'écran, invisible à l'œil. */
.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* ------------------------------------------------------------------ */
/* Boutons — deux styles, comme l'application.                         */
/* Primaire : VERT PLEIN, `--btn-fill` (#B7D98F sur un fond sombre,   */
/* #A8CD74 sur un fond clair), texte #13170C. Secondaire : verre neutre.*/
/* Plus de verre vert (retiré le 4 octobre 2026).                      */
/* ------------------------------------------------------------------ */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 14px 24px;
  border-radius: 100px;
  font-weight: 600;
  font-size: 14px;
  line-height: 1.2;
  white-space: nowrap;
  position: relative;
  transition: background 0.18s ease, box-shadow 0.18s ease, transform 0.15s ease, filter 0.15s ease;
}
.btn:active { transform: scale(0.99); filter: brightness(0.92); }
/* Le survol garde LE MÊME vert, un peu plus lumineux : un deuxième vert
   pour le survol serait un troisième vert de bouton. */
.btn--primary {
  border: none;
  background: var(--btn-fill);
  color: var(--btn-on-fill);
  font-weight: 600;
}
.btn--primary:hover { filter: brightness(1.05); }
.btn--glass {
  background: var(--glass-bg);
  border: 1px solid var(--glass-border);
  color: var(--glass-text);
  -webkit-backdrop-filter: blur(12px);
  backdrop-filter: blur(12px);
}
.btn--glass:hover { background: var(--card-strong); }
/* Le bouton du programme pilote a la matière des bulles de questions :
   le voile de carte et son filet (demande de Matteo, 28 septembre 2026 ;
   un simple contour transparent l'avait précédé). */
.btn--clear {
  background: var(--card);
  border: 1px solid var(--border);
  color: var(--text);
}
.btn--clear:hover { background: var(--card-strong); }
/* Le bouton BLANC, celui de la carte verte de l'abonnement : les couleurs
   des deux cartes s'inversent (le vert passe au programme pilote). */
.btn--white {
  background: #ffffff;
  color: #16190e;
  border: 0;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.20);
}
.btn--white:hover { background: #eef1e6; }

/* ------------------------------------------------------------------ */
/* Barre de navigation suspendue — la forme exacte du bandeau Droppy : */
/* une barre OPAQUE accrochée au bord haut, coins bas arrondis, et     */
/* deux congés concaves qui la raccordent au plafond de chaque côté.   */
/* Le fond doit être opaque : les congés sont dessinés en dégradés     */
/* radiaux de la même couleur, un verre flouté ne se raccorderait pas. */
/* ------------------------------------------------------------------ */
/* La bande de plafond : pleine largeur, la même matière que la barre —
   c'est d'elle que la barre descend, et que les congés se raccordent. */
.nav-band {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  /* Assez HAUTE pour que rien de la page ne paraisse à côté de la barre :
     à quatorze pixels, le halo lime du héros débordait de chaque côté du
     pavé et faisait une tache verte en haut à gauche. La barre descend
     ensuite sous la bande, et ce sont ses coins arrondis et ses congés qui
     la détachent — la matière est la même. */
  height: var(--nav-band-h);
  background: var(--nav-ceiling);
  z-index: 49;
}

.nav {
  /* Une seule matière pour la bande et la barre : deux valeurs
     différentes se voyaient au raccord des congés, qui sont dessinés
     avec la couleur de la BANDE. */
  --nav-bg: var(--nav-ceiling);
  --nav-fillet: 24px;
  position: fixed;
  top: 0;
  left: 50%;
  transform: translateX(-50%);
  z-index: 50;
  display: flex;
  align-items: center;
  gap: 22px;
  /* Centré sur la barre VISIBLE, qui part du haut de l'écran : les
     huit pixels de la bande comptent au-dessus du contenu. À 15 / 12 le
     logo et les mots tombaient cinq pixels trop bas (Matteo, 23 sept.).
     Et SERRÉE comme celle de getdroppy.app : le bouton touche presque
     les bords, la même marge en haut, en bas et à droite (onze pixels,
     bande comprise). */
  padding: 3px 11px 11px 20px;
  background: var(--nav-bg);
  /* La forme de getdroppy.app, relevée au pixel sur leur page : la barre
     descend de HUIT pixels sous le haut, et l'ombre pleine `0 -8px 0`
     remonte sa matière jusqu'au bord — c'est ce qui la soude à la bande
     sans qu'aucun raccord ne se voie. */
  top: 8px;
  border-radius: 0 0 24px 24px;
  box-shadow: var(--nav-bg) 0 -8px 0 0, 0 18px 40px rgba(0, 0, 0, 0.28);
}
/* Les congés : un carré de chaque côté, évidé par un cercle centré sur
   son coin bas extérieur — la matière restante épouse le bord haut. */
.nav::before,
.nav::after {
  content: "";
  position: absolute;
  top: -8px;                 /* ils partent du haut de l'écran */
  width: var(--nav-fillet);
  height: calc(var(--nav-fillet) + 8px);
}
.nav::before {
  left: calc(1px - var(--nav-fillet));
  background: radial-gradient(var(--nav-fillet) at 0 100%, transparent calc(var(--nav-fillet) - 1px), var(--nav-bg) var(--nav-fillet));
}
.nav::after {
  right: calc(1px - var(--nav-fillet));
  background: radial-gradient(var(--nav-fillet) at 100% 100%, transparent calc(var(--nav-fillet) - 1px), var(--nav-bg) var(--nav-fillet));
}
.nav__brand { display: flex; align-items: center; flex-shrink: 0; }
/* max-width: none — le « max-width: 100% » global se résout en boucle dans
   un conteneur flex dimensionné par son contenu, et rétrécissait la marque. */
.nav__wordmark { height: 32px; width: auto; max-width: none; }
.nav__links { display: flex; gap: 22px; }
.nav__links a {
  font-size: 14px;
  font-weight: 500;
  white-space: nowrap;  /* « Foire aux questions » coupait la barre en deux lignes */
  color: var(--text-2);
  transition: color 0.2s var(--ease-out);
}
.nav__links a:hover { color: var(--text); }
/* « Se connecter » : séparé des liens de la page par un filet, et en
   blanc — ce n'est pas une partie du site, c'est la porte de l'application. */
.nav__links .nav__login { position: relative; margin-left: 12px; color: var(--text); }
.nav__links .nav__login::before {
  content: "";
  position: absolute;
  left: -18px;
  top: 50%;
  width: 1px;
  height: 14px;
  margin-top: -7px;
  background: rgba(255, 255, 255, 0.22);
}
.nav__cta { padding: 11px 20px; font-size: 14px; }

/* La barre COMPACTE du haut de l'accueil (29 septembre 2026) : le logo
   et le bouton d'accès sont déjà sur l'écran de départ, la barre ne
   montre que les liens (au téléphone, que le bouton de menu). Quand
   « Conçu par un pharmacien » passe sous elle, elle s'élargit et les
   deux reviennent : la largeur s'ouvre, puis ils apparaissent en fondu,
   un léger zoom depuis leur bord intérieur. Au retour, ils se
   COMPRIMENT d'abord vers l'intérieur, encore visibles, et ne
   s'effacent qu'à la fin (demande de Matteo : pas de disparition sèche).
   Les plafonds collent à leur largeur réelle (logo ~57 px, bouton
   ~176 px) : trop larges, la barre finissait de s'ouvrir au premier
   tiers de la transition et le reste ne bougeait plus. */
.nav {
  --nav-ease: cubic-bezier(0.65, 0, 0.35, 1);
  transition: padding 0.44s var(--nav-ease), width 0.44s var(--nav-ease);
}
.nav__brand,
.nav__cta {
  overflow: hidden;
  transition:
    max-width 0.44s var(--nav-ease),
    margin 0.44s var(--nav-ease),
    padding 0.44s var(--nav-ease),
    opacity 0.3s var(--ease-out) 0.2s,
    transform 0.36s var(--ease-out) 0.17s,
    visibility 0s;
}
.nav__brand { max-width: 62px; transform-origin: right center; }
.nav__cta { max-width: 184px; transform-origin: left center; white-space: nowrap; }
.nav.is-compact .nav__brand,
.nav.is-compact .nav__cta {
  max-width: 0;
  opacity: 0;
  transform: scale(0.35, 0.8);
  pointer-events: none;
  /* Caché aussi pour la tabulation et les lecteurs d'écran, une fois
     le repli fini. */
  visibility: hidden;
  transition:
    max-width 0.42s var(--nav-ease),
    margin 0.42s var(--nav-ease),
    padding 0.42s var(--nav-ease),
    transform 0.38s var(--nav-ease),
    opacity 0.16s var(--ease-out) 0.25s,
    visibility 0s 0.42s;
}
@media (min-width: 861px) {
  .nav.is-compact { padding-right: 20px; }
  /* L'écart de 22 px que la barre met entre ses éléments se referme avec eux. */
  .nav.is-compact .nav__brand { margin-right: -22px; }
  .nav.is-compact .nav__cta { margin-left: -22px; padding-left: 0; padding-right: 0; }
}
@media (prefers-reduced-motion: reduce) {
  .nav, .nav__brand, .nav__cta { transition: none !important; }
}



.nav__burger { display: none; }

/* Sur téléphone, la forme de getdroppy.app : la barre ne prend PAS toute
   la largeur, ses congés la raccordent à la bande du haut comme sur
   ordinateur ; le logo, un bouton de menu, le bouton d'accès. Le menu
   ouvert ALLONGE la barre vers le bas, les liens les uns sous les
   autres, et le bouton devient une croix. */
@media (max-width: 860px) {
  .nav { gap: 12px; width: calc(100% - 48px); flex-wrap: wrap; border-radius: 0 0 22px 22px; }
  /* Le bouton de menu étant au centre exact, le bouton d'accès se
     resserre pour ne pas passer dessous, et la barre gagne un peu de
     largeur. */
  /* Symétrie : le logo, plus grand, est à la même distance du bord
     gauche que le bouton d'accès du bord droit (Matteo, 29 septembre). */
  .nav { width: min(calc(100% - 44px), 400px); padding: 1px 9px 7px 11px; }
  .nav__wordmark { height: 40px; }
  .nav__brand { max-width: 74px; transform-origin: right center; }
  .nav__cta { margin-left: auto; padding: 9px 11px; font-size: 12px; }
  .nav__cta { max-width: 140px; }
  /* Trente pixels de haut, c'est trop peu pour un doigt (audit 7.10) :
     une bordure TRANSPARENTE de sept pixels en haut et en bas porte la zone
     de toucher à 44, le fond s'arrêtant à la bordure — le dessin ne
     change pas, et les marges négatives rendent sa place à la barre. */
  .nav__cta {
    border-top: 7px solid transparent;
    border-bottom: 7px solid transparent;
    background-clip: padding-box;
    margin-top: -7px;
    margin-bottom: -7px;
  }
  /* Compacte : juste le bouton de menu, au milieu. Le menu ouvert la
     rend à sa largeur, logo et bouton d'accès restant cachés. */
  .nav.is-compact:not(.is-open) { width: 62px; }
  /* Le menu ouvert depuis la barre compacte reste ÉTROIT : juste la
     largeur des liens, centrés sous la croix — pas une fenêtre qui
     prend tout l'écran (Matteo). */
  .nav.is-compact.is-open { width: 214px; }
  .nav__links { align-items: center; text-align: center; }
  /* Barre ouverte (logo et bouton) : le menu ne l'allonge plus sur toute
     sa largeur, il PEND sous le bouton de menu, aussi étroit que la
     barre compacte ouverte, de la même matière. */
  .nav:not(.is-compact) .nav__links {
    position: absolute;
    top: 100%;
    left: calc(50% - 107px);
    width: 214px;
    background: var(--nav-bg);
    border-radius: 0 0 22px 22px;
    box-shadow: 0 12px 30px rgba(20, 24, 12, 0.16);
    /* Se déroule par une découpe qui descend, et non par la hauteur :
       `overflow: hidden` rognerait les congés qui le raccordent à la
       barre. La découpe déborde sur les côtés pour les laisser voir. */
    max-height: none;
    overflow: visible;
    clip-path: inset(0 -30px 100% -30px round 0 0 22px 22px);
    transition: clip-path 0.38s var(--ease-out), opacity 0.22s var(--ease-out) 0.16s, visibility 0s 0.4s;
  }
  .nav.is-open:not(.is-compact) .nav__links {
    clip-path: inset(0 -30px -60px -30px round 0 0 22px 22px);
    transition: clip-path 0.42s var(--ease-out), opacity 0.2s var(--ease-out), visibility 0s;
  }
  /* Les congés : l'angle entre la barre et le menu qui pend est arrondi
     vers l'intérieur, comme le raccord de la barre à la bande du haut. */
  .nav:not(.is-compact) .nav__links::before,
  .nav:not(.is-compact) .nav__links::after {
    content: "";
    position: absolute;
    top: 0;
    width: 18px;
    height: 18px;
  }
  .nav:not(.is-compact) .nav__links::before {
    left: -17px;
    background: radial-gradient(18px at 0 100%, transparent 17px, var(--nav-bg) 18px);
  }
  .nav:not(.is-compact) .nav__links::after {
    right: -17px;
    background: radial-gradient(18px at 100% 100%, transparent 17px, var(--nav-bg) 18px);
  }
  .nav.is-compact .nav__cta { padding-left: 0; padding-right: 0; max-width: 0; }
  .nav__burger {
    /* Au CENTRE de la barre, qu'elle soit compacte, ouverte ou allongée
       par le menu : posé sur la première rangée, hors du flux. */
    position: absolute;
    top: 1px;
    left: calc(50% - 20px);
    display: inline-flex;
    flex-shrink: 0;
    width: 40px;
    height: 40px;
    border: 0;
    padding: 0;
    background: none;
    color: var(--text);
    cursor: pointer;
  }
  .nav__burger span {
    position: absolute;
    left: 10px;
    right: 10px;
    height: 2px;
    border-radius: 2px;
    background: currentColor;
    transition: transform 0.32s var(--ease-out), opacity 0.2s var(--ease-out);
  }
  .nav__burger span:nth-child(1) { top: 13px; }
  .nav__burger span:nth-child(2) { top: 19px; }
  .nav__burger span:nth-child(3) { top: 25px; }
  .nav.is-open .nav__burger span:nth-child(1) { transform: translateY(6px) rotate(45deg); }
  .nav.is-open .nav__burger span:nth-child(2) { opacity: 0; }
  .nav.is-open .nav__burger span:nth-child(3) { transform: translateY(-6px) rotate(-45deg); }
  .nav__links {
    order: 5;
    flex-basis: 100%;
    flex-direction: column;
    gap: 0;
    max-height: 0;
    overflow: hidden;
    opacity: 0;
    visibility: hidden;
    transition: max-height 0.42s var(--ease-out), opacity 0.25s var(--ease-out), visibility 0s 0.42s;
  }
  .nav.is-open .nav__links {
    max-height: 420px;  /* six liens depuis « Tarifs » : 337 pixels, 340 ne laissait rien */
    opacity: 1;
    visibility: visible;
    transition: max-height 0.42s var(--ease-out), opacity 0.3s var(--ease-out) 0.06s, visibility 0s;
  }
  .nav__links a { font-size: 17px; padding: 13px 16px; }
  .nav__links .nav__login { margin-left: 0; }
  .nav__links .nav__login::before { left: 30%; right: 30%; top: 0; width: auto; height: 1px; margin-top: 0; }
  .nav__links a:first-child { margin-top: 8px; }
  .nav__links a:last-child { margin-bottom: 10px; }
}
@media (max-width: 400px) {
  .nav__cta { padding: 8px 9px; font-size: 11.5px; max-width: 136px; }
}
/* Sur les petits écrans, la barre reprend de la largeur : le bouton
   d'accès passerait sous le bouton de menu, centré. */
@media (max-width: 380px) {
  .nav:not(.is-compact) { width: calc(100% - 20px); }
}

/* ------------------------------------------------------------------ */
/* Téléphone — cadre dessiné en CSS autour des captures réelles.       */
/* ------------------------------------------------------------------ */
.phone {
  position: relative;
  width: min(280px, 72vw);
  padding: 10px;
  border-radius: 50px;
  background: linear-gradient(180deg, #262b1c, #14170d);
  border: 1px solid rgba(255, 255, 255, 0.14);
  /* L'ombre se tient DERRIÈRE l'appareil, elle ne s'étale pas sous lui.
     Quarante pixels vers le bas et quatre-vingts de flou faisaient une
     flaque sombre large comme la scène, qui s'écrasait sur le fond bien
     au-delà des téléphones. Resserrée, elle ne dit plus qu'une chose :
     il y a de l'épaisseur là-dessous. Mêmes distances qu'en thème
     clair, avec l'encre du fond sombre. */
  box-shadow:
    0 2px 0 rgba(255, 255, 255, 0.08) inset,
    0 10px 26px rgba(0, 0, 0, 0.50),
    0 2px 6px rgba(0, 0, 0, 0.38);
}
.phone img { border-radius: 40px; }
/* L'encoche dynamique a été retirée des visuels : elle recouvrait le haut
   des captures pour ne rien dire de plus qu'un cadre de téléphone déjà
   reconnaissable. La règle reste vide pour mémoire. */

/* ------------------------------------------------------------------ */
/* Hero — composition de Droppy : colonne centrée, média en dessous.   */
/* ------------------------------------------------------------------ */
.hero {
  position: relative;
  padding: 150px 24px 40px;
  overflow: clip;
}
/* Halo lime — la couche du fond A1 de l'application. */
.hero::before {
  content: "";
  position: absolute;
  top: -18vh;
  left: -16vw;
  width: 62vw;
  height: 46vh;
  pointer-events: none;
  background: radial-gradient(ellipse 80% 95% at 38% 20%, rgba(183, 217, 143, 0.30), rgba(183, 217, 143, 0.10) 40%, transparent 72%);
  filter: blur(2px);
  /* Le halo s'ALLUME sous la barre. Sa partie la plus claire tombait
     dans les soixante premiers pixels de la page : une tache verte
     apparaissait à gauche de la barre, là où getdroppy.app ne montre
     qu'une matière unie. Le masque est mesuré depuis le haut de
     l'ÉLÉMENT, qui commence 18vh au-dessus de la page — d'où les deux
     `calc` : transparent jusqu'au haut de la page, plein à 96 px. Le
     halo n'a pas bougé d'un pixel, il n'entre simplement plus dans la
     barre. */
  -webkit-mask-image: linear-gradient(to bottom, transparent calc(18vh + 2px), #000 calc(18vh + 96px));
  mask-image: linear-gradient(to bottom, transparent calc(18vh + 2px), #000 calc(18vh + 96px));
}

/* Le bureau en fond du haut de page, à la manière de l'illustration de
   getdroppy.app : derrière tout le reste, très atténué, et effacé vers
   le bas par un masque — c'est la couleur de la page qui apparaît
   dessous, donc le blanc en clair et le vert foncé en sombre, sans
   dégradé à tenir d'accord avec le thème. En sombre, plus discret :
   ses clairs olive allumeraient la page. Réglé à l'œil de Matteo, qui
   la voulait plus visible que le premier essai. */
.hero__backdrop {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 112vh;
  z-index: -1;
  pointer-events: none;
  background: url("../img/hero-bureau.webp") center 30% / cover no-repeat;
  opacity: 0.7;
  -webkit-mask-image: linear-gradient(to bottom, #000 0%, #000 50%, transparent 100%);
  mask-image: linear-gradient(to bottom, #000 0%, #000 50%, transparent 100%);
}
/* Au téléphone, une version plus légère (1000 pixels de large au lieu de
   1600) : à 42 % d'opacité derrière le texte, la différence ne se voit pas. */
@media (max-width: 860px) { .hero__backdrop { background-image: url("../img/hero-bureau-tel.webp"); } }
:root:not([data-theme="light"]) .hero__backdrop { opacity: 0.42; }
/* En clair aussi, le haut de page prend l'image du thème sombre (demande
   de Matteo, 29 septembre 2026) : le bureau à 33 % sur le vert foncé,
   écritures blanches. Le haut de page porte le vert du sombre sur tout
   le premier écran, puis se fond dans le blanc de la page derrière les
   téléphones ; `isolation` pour que la photo (z-index −1) passe
   par-dessus ce fond et non dessous. */
:root[data-theme="light"] .hero {
  isolation: isolate;
  /* Le vert s'éclaircit en passant par des verts, jamais par le gris :
     un fondu direct du vert foncé au blanc traverse un gris sale (vu par
     Matteo). Long (76 → 168vh, le bas du premier écran s'éclaircit déjà),
     en courbe douce, les couleurs interpolées en OKLab entre des olives
     de plus en plus pâles : aucun palier. Il finit TRANSPARENT et non
     blanc : les taches de fond de la page (`.bg-blob`) passent dessous,
     et un fond blanc les coupait net au bas du haut de page. */
  background: linear-gradient(to bottom,
    #13170C 0,
    #13170c calc(76.0vh + var(--hero-fade-shift, 0vh)),
    #15190d calc(81.1vh + var(--hero-fade-shift, 0vh)),
    #1a1f12 calc(86.2vh + var(--hero-fade-shift, 0vh)),
    #232919 calc(91.3vh + var(--hero-fade-shift, 0vh)),
    #2f3622 calc(96.4vh + var(--hero-fade-shift, 0vh)),
    #3e462e calc(101.6vh + var(--hero-fade-shift, 0vh)),
    #505a3d calc(106.7vh + var(--hero-fade-shift, 0vh)),
    #6c7757 calc(111.8vh + var(--hero-fade-shift, 0vh)),
    #8c9674 calc(116.9vh + var(--hero-fade-shift, 0vh)),
    #adb793 calc(122.0vh + var(--hero-fade-shift, 0vh)),
    #c1caab calc(127.1vh + var(--hero-fade-shift, 0vh)),
    #d5dcc4 calc(132.2vh + var(--hero-fade-shift, 0vh)),
    #e9eedb calc(137.3vh + var(--hero-fade-shift, 0vh)),
    rgba(240, 244, 230, 0.62) calc(142.4vh + var(--hero-fade-shift, 0vh)),
    rgba(245, 247, 238, 0.36) calc(147.6vh + var(--hero-fade-shift, 0vh)),
    rgba(249, 251, 245, 0.17) calc(152.7vh + var(--hero-fade-shift, 0vh)),
    rgba(252, 253, 250, 0.06) calc(157.8vh + var(--hero-fade-shift, 0vh)),
    rgba(254, 254, 254, 0.015) calc(162.9vh + var(--hero-fade-shift, 0vh)),
    rgba(255, 255, 255, 0) calc(168.0vh + var(--hero-fade-shift, 0vh)));
}
:root[data-theme="light"] .hero__backdrop { opacity: 0.42; }  /* 33 → 37 → 42 %, plus clair par petits crans (30 septembre 2026) */
:root[data-theme="light"] .hero__inner {
  --text: #ffffff;
  --text-2: rgba(255, 255, 255, 0.75);
  --text-3: rgba(255, 255, 255, 0.55);
  --accent-text: #B7D98F;
  --btn-fill: #B7D98F;
  --glass-bg: rgba(255, 255, 255, 0.06);
  --glass-border: rgba(255, 255, 255, 0.14);
  --glass-text: rgba(255, 255, 255, 0.85);
  --card: rgba(255, 255, 255, 0.04);
  --card-strong: rgba(255, 255, 255, 0.07);
  --border: rgba(255, 255, 255, 0.08);
  color: var(--text);
}

/* Champ réactif : halos flous qui dérivent au défilement et suivent la souris. */
.hero__field { position: absolute; inset: 0; pointer-events: none; }
.orb {
  position: absolute;
  border-radius: 50%;
  filter: blur(60px);
  will-change: transform;
}
.orb--a { top: 8%; right: -6%; width: 380px; height: 380px; background: radial-gradient(closest-side, rgba(183, 217, 143, 0.14), transparent 70%); }
.orb--b { top: 46%; left: -8%; width: 460px; height: 460px; background: radial-gradient(closest-side, rgba(94, 139, 126, 0.18), transparent 70%); }
.orb--c { bottom: -4%; right: 22%; width: 300px; height: 300px; background: radial-gradient(closest-side, rgba(183, 217, 143, 0.10), transparent 70%); }

/* Le premier écran n'a que le bureau et le texte, posé EN BAS de l'écran ;
   les téléphones n'arrivent qu'au défilement (demande de Matteo,
   28 septembre 2026). */
.hero__inner {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-end;
  text-align: center;
  max-width: 1180px;
  margin-inline: auto;
  min-height: calc(100vh - 150px);
  min-height: calc(100svh - 150px);
  /* Le texte remonte sur la photo : « Conçu par un pharmacien » restait
     dans le fondu clair du bas de l'écran. Les téléphones ne bougent pas
     (la hauteur totale est la même). */
  padding-bottom: 9vh;
}
/* Sur la carte BLANCHE du programme pilote, le bouton prend le fond de la
   carte de l'abonnement, texte blanc : les deux cartes sont l'inverse l'une
   de l'autre — la verte porte un bouton blanc, la blanche un bouton vert
   foncé (Matteo, 30 septembre 2026). Ce n'est pas un vert plein mais le
   fond de l'application, sans voile vert depuis le 4 octobre 2026. */
:root[data-theme="light"] .access-card--pilot .btn--primary {
  /* Le dégradé du bandeau de l'officine de l'application (sa lueur verte
     dans un coin) : vert clair à gauche, vert foncé à droite (Matteo,
     7 octobre 2026). Le bout droit s'arrête sur le vert foncé de la carte de
     l'abonnement voisine (#1e2414, relevé au pixel), pas plus sombre. Les
     nuages qui dérivaient dedans sont retirés : ils le marbraient. */
  background:
    radial-gradient(180px 90px at 14% 30%, rgba(183, 217, 143, 0.16), transparent 70%),
    linear-gradient(90deg, #3a4230 0%, #2a3120 50%, #1e2414 100%);
  color: #ffffff;
}
:root[data-theme="light"] .access-card--pilot .btn--clouds > .card-clouds { display: none; }
:root[data-theme="light"] .access-card--pilot .btn--primary:hover { filter: brightness(1.25); }
/* Le logo occupe l'espace libre au-dessus du titre, centré dedans. Lime
   clair sur le sombre ; en clair, presque noir comme le titre — l'olive
   se perdait dans la photo. */
.hero__logo {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 90px;
}
.hero__logo img { height: clamp(110px, 23vh, 240px); width: auto; }
/* Remonté : il se pose dans le haut de l'espace libre, pas au milieu. */
.hero__logo { align-items: flex-start; padding-top: 0; margin-top: clamp(-80px, -7vh, -24px); }
.hero__title {
  font-family: var(--font-display);
  font-weight: 700;
  /* En très grand, comme le titre de getdroppy.app : deux lignes qui
     occupent la largeur. */
  font-size: clamp(2.1rem, 4.4vw, 3.8rem);
  letter-spacing: -0.045em;
  line-height: 1.02;
  text-wrap: balance;
  margin-bottom: 26px;
}
/* Deux lignes à l'ordinateur, coupées après « la tête » ; au téléphone
   le titre se range de lui-même. */
@media (max-width: 860px) { .hero__br { display: none; } }
.hero__subtitle {
  font-size: clamp(1.05rem, 1.7vw, 1.3rem);
  /* Sur la photo du bureau, il prend la couleur du titre : gris, il se
     perdait dedans. Un halo à la couleur de la page autour des lettres a
     été essayé et retiré (« le reflet blanc derrière les lettres »). */
  color: var(--text);
  line-height: 1.6;
  max-width: 640px;
  margin-bottom: 32px;
  text-wrap: balance;
}
.hero__actions {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  flex-wrap: wrap;
}
/* La signature, CENTRÉE entre les boutons et le bas du premier écran :
   sa boîte occupe tout l'espace sous les boutons, le texte en son milieu. */
.hero__note {
  height: clamp(96px, 17vh, 170px);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 15px;
  font-weight: 500;
  font-style: italic;
  color: var(--text-2);
}

/* Trois téléphones en éventail sous le texte, comme le média du hero Droppy. */
.hero__art {
  position: relative;
  display: flex;
  justify-content: center;
  align-items: flex-start;
  margin-top: 64px;
  will-change: transform;
}
/* À l'ordinateur, les trois téléphones descendent dans le blanc du
   fondu, sous le vert (Matteo, 29 septembre) : ils commençaient dans les
   olives du milieu. */
@media (min-width: 861px) { .hero__art { margin-top: calc(64px + 24vh); } }
.hero__art .phone--center { position: relative; z-index: 2; }
.hero__art .phone--left,
.hero__art .phone--right { position: relative; z-index: 1; margin-top: 48px; }
/* L'ÉVENTAIL, demandé par Matteo : en haut de page, les deux téléphones
   de côté sont rangés sous celui du milieu et les trois sont un peu plus
   bas ; en défilant, ils s'ouvrent jusqu'à leur place d'aujourd'hui —
   c'est la position finale, et celle qu'on garde sans JavaScript.

   `--fan` va de 0 (rangés) à 1 (ouverts) ; site.js le pose sur le
   groupe (`initHeroFan`). Pas de `transform` sur le groupe lui-même :
   la souris s'en sert déjà pour le faire flotter, et l'un écraserait
   l'autre. Chaque téléphone lit la variable pour son propre compte. */
.hero__art { --fan: 1; --fan-drop: 110px; --fan-tuck: 120px; }
.hero__art .phone--center { transform: translateY(calc((1 - var(--fan)) * var(--fan-drop))); }
.hero__art .phone--left {
  transform: translateY(calc((1 - var(--fan)) * var(--fan-drop)))
             rotate(calc(-2.5deg - 4.5deg * var(--fan)))
             translateX(calc(34px + (1 - var(--fan)) * var(--fan-tuck)));
}
.hero__art .phone--right {
  transform: translateY(calc((1 - var(--fan)) * var(--fan-drop)))
             rotate(calc(2.5deg + 4.5deg * var(--fan)))
             translateX(calc(-34px - (1 - var(--fan)) * var(--fan-tuck)));
}

/* Sur téléphone, les trois restent (ils étaient masqués, et le premier
   écran n'en montrait qu'un) : celui du milieu un peu plus petit, les
   deux autres EN RETRAIT derrière lui, plus petits encore, à moitié
   coupés par les bords de l'écran. Le même éventail qu'à l'ordinateur :
   rangés sous celui du milieu en haut de page, ils s'écartent au
   défilement (`--fan`, `initHeroFan`). */
@media (max-width: 860px) {
  .hero { padding-top: 120px; }
  .hero__inner { min-height: calc(100vh - 120px); min-height: calc(100svh - 120px); }
  /* Au téléphone, le logo descend un peu et le titre grandit. Pour que
     tout tienne au-dessus du fondu, le logo et la boîte de la signature
     se resserrent (le premier écran débordait). */
  .hero__inner { padding-bottom: 5vh; }
  /* Et le fondu du clair commence un peu plus bas qu'à l'ordinateur. */
  .hero { --hero-fade-shift: 7vh; }
  .hero__logo { margin-top: 2vh; }
  .hero__logo img { height: clamp(96px, 18vh, 170px); }
  .hero__title { font-size: clamp(2.45rem, 10vw, 2.9rem); }
  .hero__note { height: 88px; }
  .hero__art { --fan-drop: 70px; --m-spread: 36vw; }
  .hero__art .phone--center { width: min(250px, 62vw); }
  .hero__art .phone--left,
  .hero__art .phone--right {
    position: absolute;
    top: 0;
    left: 50%;
    width: min(210px, 52vw);
    margin-top: 40px;
    margin-left: calc(-0.5 * min(210px, 52vw));
    border-radius: 42px;
  }
  .hero__art .phone--left {
    transform: translateY(calc((1 - var(--fan)) * var(--fan-drop)))
               translateX(calc(-1 * var(--m-spread) * var(--fan)))
               rotate(calc(-2.5deg - 4.5deg * var(--fan)));
  }
  .hero__art .phone--right {
    transform: translateY(calc((1 - var(--fan)) * var(--fan-drop)))
               translateX(calc(var(--m-spread) * var(--fan)))
               rotate(calc(2.5deg + 4.5deg * var(--fan)));
  }
}

/* ------------------------------------------------------------------ */
/* Wordscroll — portage du wordscroll.css de getdroppy.app.            */
/* ------------------------------------------------------------------ */
.wordscroll {
  position: relative;
  overflow-x: clip;
  background: linear-gradient(180deg, rgba(12, 15, 7, 0) 0%, var(--bg-deep) 12%, var(--bg-deep) 88%, rgba(12, 15, 7, 0) 100%);
}
.wordscroll__stage {
  position: static;
  min-height: 100vh;
  min-height: 100dvh;
  overflow: visible;
  --ws-enter: 1;
  --ws-glow: 0.6;
  --ws-copy: 1;
  --ws-demo: 1;
  --ws-bloom: 0;
  display: flex;
  flex-direction: column;
  gap: 48px;
  padding: 96px 0;
}
.wordscroll.ws-ready { height: 917vh; }  /* 1012vh avant que l'étape 2 ne cesse de défiler */
.wordscroll.ws-ready .wordscroll__stage {
  position: sticky;
  top: 0;
  height: 100vh;
  height: 100dvh;
  min-height: 0;
  overflow: hidden;
  --ws-enter: 0;
  --ws-glow: 0;
  --ws-copy: 1;
  --ws-demo: 0;
  --ws-bloom: 0;
  display: block;
  padding: 0;
}
.wordscroll__glow {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: radial-gradient(46% 36% at 50% 8%, rgba(183, 217, 143, 0.12), rgba(183, 217, 143, 0) 70%);
  opacity: var(--ws-enter, 0);
}
.wordscroll__bloom {
  position: absolute;
  left: 50%;
  top: 52%;
  width: 140vmax;
  height: 140vmax;
  transform: translate(-50%, -50%) scale(calc(0.62 + 0.38 * var(--ws-bloom, 0)));
  border-radius: 50%;
  pointer-events: none;
  background: radial-gradient(closest-side, rgba(183, 217, 143, 0.08), rgba(183, 217, 143, 0) 62%);
  opacity: var(--ws-bloom, 0);
}
.wordscroll__copy {
  position: static;
  padding: 0 24px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: clamp(24px, 3.4vh, 36px);
}
.wordscroll.ws-ready .wordscroll__copy {
  position: absolute;
  inset: 0;
  opacity: var(--ws-copy);
  transform: scale(calc(0.96 + 0.04 * var(--ws-copy)));
}
.wordscroll__demo {
  position: static;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: clamp(16px, 4vw, 48px);
}
.wordscroll.ws-ready .wordscroll__demo {
  position: absolute;
  inset: 0;
  opacity: var(--ws-demo);
  transform: scale(calc(0.955 + 0.045 * var(--ws-demo)));
  pointer-events: none;
}
.wordscroll.ws-ready .wordscroll__stage.ws-demo-active .wordscroll__demo { pointer-events: auto; }
.phone--demo { width: min(320px, 40vh); }

.wordscroll__text {
  position: relative;
  z-index: 1;
  margin: 0;
  max-width: 22ch;
  text-align: center;
  font-family: var(--font-display);
  font-weight: 700;
  letter-spacing: -0.02em;
  font-size: clamp(30px, 4.7vw, 58px);
  line-height: 1.16;
  color: var(--text);
}
.wordscroll.ws-ready .wordscroll__text { color: rgba(183, 217, 143, 0.14); }
.wordscroll__text .w { position: relative; display: inline-block; white-space: pre; }
.wordscroll__text .w-lit { position: absolute; inset: 0; color: var(--text); opacity: 0; }
.wordscroll__text .w-glo {
  position: absolute;
  inset: 0;
  color: transparent;
  opacity: 0;
  pointer-events: none;
  text-shadow: 0 0 10px rgba(183, 217, 143, 0.75), 0 0 26px rgba(183, 217, 143, 0.45);
}

/* Étincelles — le twinkle de Droppy, en blanc chaud. */
.wordscroll__sparks { position: absolute; inset: 0 0 55% 0; pointer-events: none; }
.wordscroll__sparks span {
  position: absolute;
  width: 2px;
  height: 2px;
  border-radius: 50%;
  background: #fff;
  opacity: 0;
  animation: ws-twinkle 4.5s ease-in-out infinite;
}
.wordscroll__sparks span:nth-child(1) { top: 12%; left: 22%; animation-delay: 0.1s; }
.wordscroll__sparks span:nth-child(2) { top: 28%; left: 68%; width: 3px; height: 3px; animation-delay: 0.6s; }
.wordscroll__sparks span:nth-child(3) { top: 8%; left: 52%; animation-delay: 1.1s; }
.wordscroll__sparks span:nth-child(4) { top: 34%; left: 40%; animation-delay: 1.6s; }
.wordscroll__sparks span:nth-child(5) { top: 18%; left: 78%; width: 3px; height: 3px; animation-delay: 2.1s; }
.wordscroll__sparks span:nth-child(6) { top: 40%; left: 16%; animation-delay: 2.6s; }
.wordscroll__sparks span:nth-child(7) { top: 6%; left: 34%; animation-delay: 3.1s; }
.wordscroll__sparks span:nth-child(8) { top: 24%; left: 88%; animation-delay: 3.6s; }
.wordscroll__sparks span:nth-child(9) { top: 44%; left: 60%; width: 3px; height: 3px; animation-delay: 4s; }
.wordscroll__sparks span:nth-child(10) { top: 15%; left: 8%; animation-delay: 0.9s; }
@keyframes ws-twinkle {
  0%, 100% { opacity: 0; transform: scale(0.8); }
  50% { opacity: 0.5; transform: scale(1.15); }
}

/* Sans JavaScript ou en mouvement réduit : tout est lisible, rien n'épingle. */
.wordscroll.ws-reduced-motion { height: auto; }
.wordscroll.ws-reduced-motion .wordscroll__stage {
  position: static;
  height: auto;
  min-height: 0;
  --ws-enter: 1;
  --ws-copy: 1;
  --ws-demo: 1;
  --ws-glow: 0.6;
  display: flex;
  flex-direction: column;
  gap: 48px;
  padding: 96px 0;
  overflow: visible;
}
.wordscroll.ws-reduced-motion .wordscroll__copy,
.wordscroll.ws-reduced-motion .wordscroll__demo { position: static; transform: none; }
.wordscroll.ws-reduced-motion .w-lit { opacity: 1 !important; }
@media (prefers-reduced-motion: reduce) {
  .wordscroll__sparks span { animation: none; opacity: 0; }
}

@media (max-width: 720px) {
  .wordscroll.ws-ready { height: 792vh; }
}

/* ------------------------------------------------------------------ */
/* L'histoire de la création — le téléphone reste épinglé, ses écrans  */
/* se succèdent au fil du défilement, les légendes vivent sur les      */
/* côtés. Tout est piloté par site.js sur la même mécanique que les    */
/* mots : opacité et translation posées image par image.               */
/* ------------------------------------------------------------------ */
.story {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
}
/* Le changement d'écran est une ROTATION du téléphone : il pivote sur
   lui-même (site.js pilote le rotateY), l'écran bascule à l'instant où
   le téléphone est de profil — invisible — et le tour s'achève sur le
   nouvel écran. Un seul écran est visible à la fois, jamais deux. */
/* Perspective serrée : plus elle est courte, plus la profondeur se voit
   quand le téléphone tourne — le bord proche grossit, le bord loin fuit. */
.story { perspective: 900px; }
.phone--demo { will-change: transform; transform-style: preserve-3d; }
/* L'ÉPAISSEUR du téléphone : une vraie tranche 3D fermée tout autour —
   deux côtés, haut, bas, et quatre coins faits de petites bandes qui
   suivent l'arrondi. site.js éclaire chaque bande selon l'angle. */
.phone--demo { --edge: 12px; --r: 50px; }
.phone__depth--back {
  position: absolute; inset: 0; border-radius: var(--r);
  background: linear-gradient(180deg, #232819, #141810);
  border: 1px solid rgba(255, 255, 255, 0.10);
  transform: translateZ(calc(-1 * var(--edge))) rotateY(180deg);
}
.phone__edge, .phone__arc { position: absolute; }
.phone__edge--l, .phone__edge--r { top: var(--r); bottom: var(--r); width: var(--edge); }
.phone__edge--l { left: 0; transform-origin: left center; transform: rotateY(90deg);
  background: linear-gradient(90deg, #2c3322, #59624a 45%, #1d2215); }
.phone__edge--r { right: 0; transform-origin: right center; transform: rotateY(-90deg);
  background: linear-gradient(90deg, #1d2215, #59624a 55%, #2c3322); }
.phone__edge--t, .phone__edge--b { left: var(--r); right: var(--r); height: var(--edge); }
.phone__edge--t { top: 0; transform-origin: center top; transform: rotateX(-90deg);
  background: linear-gradient(180deg, #2c3322, #434b36 45%, #1d2215); }
.phone__edge--b { bottom: 0; transform-origin: center bottom; transform: rotateX(90deg);
  background: linear-gradient(0deg, #2c3322, #434b36 45%, #1d2215); }
.phone__arcs { position: absolute; inset: 0; transform-style: preserve-3d; pointer-events: none; }
.phone__arc { width: var(--edge); height: 10px; margin-top: -5px; transform-origin: left center;
  background: linear-gradient(90deg, #2c3322, #59624a 45%, #1d2215); }
/* La face avant reste devant ses tranches. */
.phone--demo .story__screens { transform: translateZ(1px); }

/* La vidéo occupe le cadre du téléphone exactement comme une capture. */
.phone__video {
  display: block;
  width: 100%;
  height: auto;
  border-radius: inherit;
  background: var(--bg);
}
.story__screens {
  position: relative;
  overflow: hidden;
  border-radius: 40px;
}
.story__screens img { border-radius: 0; }
/* Les écrans s'empilent dans le téléphone, et seul celui de l'étape en
   cours est visible — seulement quand le défilement les pilote
   (`ws-ready`). Sinon, ils se lisent tous, voir plus bas. */
.wordscroll.ws-ready .story__screens > img:not(:first-child) {
  position: absolute;
  inset: 0;
  opacity: 0;
}

.story__caption {
  position: absolute;
  top: 50%;
  /* --story-shift : la légende entre par le bas et sort par le haut,
     posé par site.js au rythme du défilement. */
  transform: translateY(calc(-50% + var(--story-shift, 0px)));
  width: min(300px, 26vw);
  will-change: transform, opacity;
}
.wordscroll.ws-ready .story__caption { opacity: 0; }
.story__caption--left { right: calc(50% + 230px); text-align: right; }
.story__caption--right { left: calc(50% + 230px); text-align: left; }
.story__step { font-size: 14px; font-weight: 600; color: var(--accent-text); margin-bottom: 8px; }
.story__caption h3 {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(22px, 2.2vw, 30px);
  letter-spacing: -0.02em;
  line-height: 1.1;
  margin-bottom: 10px;
}
.story__caption p:not(.story__step) { font-size: 15px; color: var(--text-3); line-height: 1.55; }

/* Au téléphone, les étapes 1 à 4 prennent la mise en page de la
   génération (Matteo, 29 septembre) : le téléphone remplit la place
   entre la barre et la légende, à la même hauteur que celui de la
   génération, la légende posée en bas de l'écran. */
@media (max-width: 900px) {
  .wordscroll.ws-ready .wordscroll__demo { padding: 58px 0 178px; }
  /* La perspective passe à la scène : sur `.story`, elle en faisait le
     repère des légendes, collées au téléphone. */
  .wordscroll.ws-ready .wordscroll__demo { perspective: 900px; }
  .wordscroll.ws-ready .story { position: static; perspective: none; }
  .wordscroll.ws-ready .story__caption { bottom: 5vh; }
  .wordscroll__text { font-size: clamp(34px, 9vw, 46px); }
}
@media (max-width: 900px) {
  .phone--demo { width: min(81vw, calc((100vh - 236px) * 0.437)); width: min(81vw, calc((100dvh - 236px) * 0.437)); }
  .story__screens { border-radius: 30px; }
  .story__caption {
    top: auto;
    bottom: max(-16vh, -120px);
    left: 50%;
    right: auto;
    transform: translateX(-50%) translateY(var(--story-shift, 0px));
    width: min(340px, 86vw);
    text-align: center;
  }
  .story__caption--left { right: auto; text-align: center; }
  .story__caption--right { left: 50%; text-align: center; }
}

/* Mouvement réduit, sans JavaScript, ou avant qu'il arrive : rien
   n'épingle, les quatre étapes se lisent, chaque légende au-dessus de SON
   écran. Les écrans restaient transparents en mouvement réduit (une
   colonne vide sur près de trois hauteurs d'écran, audit 7.4). Le
   téléphone unique s'efface (`display: contents`) pour que légendes et
   écrans se rangent en grille ; chaque écran porte alors son propre cadre.
   Côte à côte à l'ordinateur, deux par deux sur une tablette, l'un sous
   l'autre au téléphone. */
.wordscroll:not(.ws-ready) .story {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  justify-items: center;
  align-items: start;
  gap: 18px 28px;
  perspective: none;
  max-width: 1160px;
  margin: 0 auto;
  padding: 0 24px;
}
.wordscroll:not(.ws-ready) .phone--demo,
.wordscroll:not(.ws-ready) .story__screens { display: contents; }
.wordscroll:not(.ws-ready) .phone__depth,
.wordscroll:not(.ws-ready) .phone__edge,
.wordscroll:not(.ws-ready) .phone__arcs { display: none; }
.wordscroll:not(.ws-ready) .story__caption {
  position: static;
  transform: none;
  opacity: 1;
  width: auto;
  max-width: 420px;
  text-align: center;
  align-self: end;
}
.wordscroll:not(.ws-ready) [data-story-screen] {
  position: static;
  opacity: 1;
  width: min(260px, 72vw);
  padding: 9px;
  border-radius: 44px;
  background: linear-gradient(180deg, #262b1c, #14170d);
  border: 1px solid rgba(255, 255, 255, 0.14);
  box-shadow: 0 2px 0 rgba(255, 255, 255, 0.08) inset, 0 10px 26px rgba(20, 24, 12, 0.18);
  margin-bottom: 30px;
}
/* Une colonne : légende, écran, légende, écran… */
.wordscroll:not(.ws-ready) [data-story-caption="0"] { order: 0; }
.wordscroll:not(.ws-ready) [data-story-screen="0"] { order: 1; }
.wordscroll:not(.ws-ready) [data-story-caption="1"] { order: 2; }
.wordscroll:not(.ws-ready) [data-story-screen="1"] { order: 3; }
.wordscroll:not(.ws-ready) [data-story-caption="2"] { order: 4; }
.wordscroll:not(.ws-ready) [data-story-screen="2"] { order: 5; }
.wordscroll:not(.ws-ready) [data-story-caption="3"] { order: 6; }
.wordscroll:not(.ws-ready) [data-story-screen="3"] { order: 7; }
/* Deux par deux. */
@media (min-width: 640px) {
  .wordscroll:not(.ws-ready) .story { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .wordscroll:not(.ws-ready) [data-story-caption="0"] { grid-area: 1 / 1; }
  .wordscroll:not(.ws-ready) [data-story-caption="1"] { grid-area: 1 / 2; }
  .wordscroll:not(.ws-ready) [data-story-screen="0"] { grid-area: 2 / 1; }
  .wordscroll:not(.ws-ready) [data-story-screen="1"] { grid-area: 2 / 2; }
  .wordscroll:not(.ws-ready) [data-story-caption="2"] { grid-area: 3 / 1; }
  .wordscroll:not(.ws-ready) [data-story-caption="3"] { grid-area: 3 / 2; }
  .wordscroll:not(.ws-ready) [data-story-screen="2"] { grid-area: 4 / 1; }
  .wordscroll:not(.ws-ready) [data-story-screen="3"] { grid-area: 4 / 2; }
}
/* Les quatre côte à côte. */
@media (min-width: 1100px) {
  .wordscroll:not(.ws-ready) .story { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .wordscroll:not(.ws-ready) [data-story-caption="2"] { grid-area: 1 / 3; }
  .wordscroll:not(.ws-ready) [data-story-caption="3"] { grid-area: 1 / 4; }
  .wordscroll:not(.ws-ready) [data-story-screen="2"] { grid-area: 2 / 3; }
  .wordscroll:not(.ws-ready) [data-story-screen="3"] { grid-area: 2 / 4; }
  .wordscroll:not(.ws-ready) [data-story-screen] { width: min(240px, 100%); }
}

/* ------------------------------------------------------------------ */
/* Sections — échelle typographique de Droppy.                         */
/* ------------------------------------------------------------------ */
.section-title {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(2.1rem, 5vw, 3rem);
  line-height: 1.06;
  letter-spacing: -0.03em;
  text-align: center;
  text-wrap: balance;
  margin-bottom: 18px;
}
.section-sub {
  color: var(--text-3);
  font-size: clamp(1.05rem, 2.4vw, 1.25rem);
  text-align: center;
  max-width: 60ch;
  margin: 0 auto 56px;
}

/* ------------------------------------------------------------------ */
/* Les deux bandeaux d'écrans — des cartes qu'on fait glisser.         */
/*                                                                    */
/* Anatomie reprise de « Just some of the highlights » chez            */
/* getdroppy.app : le titre et sa phrase DANS la carte, en haut, et    */
/* l'écran plein cadre en dessous, jusqu'aux bords. La carte se lit    */
/* alors seule — un texte posé sous un rail ne dit pas de quelle carte */
/* il parle dès qu'on en voit deux.                                    */
/*                                                                    */
/* Le rail sort de la colonne et va jusqu'au bord : une carte coupée   */
/* par le bord droit est ce qui dit qu'il y en a d'autres.             */
/* ------------------------------------------------------------------ */
.shelf { padding: 110px 0 40px; }
.shelf .section-title { margin-bottom: 14px; }

/* La largeur d'une carte se DÉDUIT de son écran : la hauteur d'image est
   posée une fois, et la largeur est celle que le rapport de forme du
   montage réclame. C'est ce qui permet de ne rien rogner. */
/* 700 pixels de haut, sauf sur un écran trop bas pour montrer le titre
   ET les écrans en entier sous la barre du haut pendant la mise en
   valeur : on y réserve la barre (80), le titre et ses marges (142) et
   un peu d'air. Au-dessus de 960 pixels de haut, rien ne change. */
.band { --hcard-h: clamp(480px, calc(100vh - 260px), 700px); position: relative; margin-top: 54px; }

/* La MISE EN VALEUR, reprise de la première vidéo de getdroppy.app :
   quand un bandeau arrive au centre de l'écran, il s'y COLLE pendant un
   défilement supplémentaire, et le reste de la page s'assombrit derrière
   lui. Il faut défiler plus que d'ordinaire pour en sortir — c'est le
   but : on s'arrête sur les écrans.

   La mécanique, relevée chez eux : une piste plus haute que le bandeau
   (ici, son pseudo-élément ajoute la hauteur de la tenue), le bandeau
   collant dedans, et un voile plein écran dont l'opacité suit la
   distance du bandeau au centre. site.js calcule où coller le bandeau
   pour que ses écrans tombent au milieu, et pose `has-lock` : sans
   JavaScript, ou en mouvement réduit, les bandeaux défilent normalement. */
.band-lock { position: relative; }
/* La TENUE : 85 % d'une hauteur d'écran de défilement pendant laquelle
   la vidéo reste en grand. À 50 %, on en sortait trop facilement
   (Matteo, 27 septembre 2026). */
.shelf.has-lock .band-lock::after { content: ""; display: block; height: var(--band-hold, 85vh); }
.shelf.has-lock .band-lock > .band { position: sticky; top: var(--band-top, 0px); z-index: 1; }
.spot {
  position: fixed;
  inset: 0;
  z-index: 2;
  background: var(--spot);
  opacity: 0;
  pointer-events: none;
}
/* Le bandeau mis en valeur passe AU-DESSUS du voile ; l'autre reste
   dessous, assombri avec le reste. */
.shelf.has-lock .band-lock > .band.is-spot { z-index: 3; }
/* Pendant la mise en valeur, la section passe devant les sections
   voisines — sans quoi celles qui la suivent dans la page peindraient
   par-dessus le voile et resteraient claires. Toujours sous la barre du
   haut (50), qu'on puisse encore s'en servir. */
.shelf.is-spotlit { z-index: 40; }
/* La carte du milieu GROSSIT à l'approche, jusqu'à occuper la hauteur
   entre la barre du haut et le bas de l'écran (site.js). L'espace entre
   les cartes ne change pas : grossie, elle passe un peu par-dessus ses
   deux voisines. Le rail rogne ce qui sort de sa boîte, d'où la place
   ajoutée en haut et en bas, reprise par une marge négative. */
.shelf.has-lock .rail__track {
  padding-top: calc(54px + var(--zoom-room, 0px));
  padding-bottom: calc(116px + var(--zoom-room, 0px));
  margin-top: calc(-1 * var(--zoom-room, 0px));
  margin-bottom: calc(-1 * var(--zoom-room, 0px));
}
.shelf.has-lock .hcard { position: relative; transform-origin: center; }
.band--films { --hcard-w: calc(var(--hcard-h) * 720 / 1280); }
.band__head {
  max-width: 1240px;
  margin: 0 auto 18px;
  padding: 0 24px;
  text-align: center;
}
/* Le rôle, en un mot et en grand : c'est un intertitre, pas une
   étiquette. */
.band__title {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(26px, 3.4vw, 40px);
  letter-spacing: -0.03em;
  color: var(--text);
}
/* Ce que le bandeau montre, en une phrase (demande de Matteo, 27
   septembre 2026). La liste des écrans qui la suivait, cliquable, a été
   retirée le même jour : « le texte fait l'affaire ». */
.band__lede {
  max-width: 700px;
  margin: 10px auto 0;
  font-size: 15px;
  line-height: 1.55;
  color: var(--text-2);
}

.rail__track {
  display: flex;
  gap: 22px;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  /* La carte en cours se cale au CENTRE, et les gouttières valent une
     demi-fenêtre : c'est ce qui permet à la PREMIÈRE comme à la DERNIÈRE
     d'y venir. Sans cet air devant et derrière, le défilement s'arrête
     au bout du contenu et les dernières cartes ne passent jamais au
     milieu — donc leur vidéo ne joue jamais. */
  /* De l'air autour des cartes, et ce n'est pas du confort : leur ombre
     descend à cent pixels, et un conteneur qui défile ROGNE ce qui
     dépasse. Le bord du rognage traçait un trait gris net en travers de
     toute la page — la « ligne de séparation ». Avec la place, l'ombre
     s'éteint d'elle-même. */
  padding: 54px calc(50vw - var(--hcard-w) / 2) 116px;
  scrollbar-width: none;
  -ms-overflow-style: none;
  overscroll-behavior-x: contain;
}
.rail__track::-webkit-scrollbar { display: none; }

.hcard {
  flex: 0 0 auto;
  width: var(--hcard-w);
  scroll-snap-align: center;
  border-radius: 30px;
  overflow: hidden;
  background: var(--card);
  border: 1px solid var(--border);
  box-shadow: 0 30px 70px var(--shadow-media);
  /* Aucune carte n'est mise en retrait, comme chez getdroppy.app : un
     voile sur les autres a été essayé et retiré le jour même. Nos
     captures n'ont pas toutes la même clarté — l'accueil est plus
     lumineux qu'une fenêtre posée sur un fond flou —, donc le voile
     désignait la mauvaise carte aussi souvent que la bonne. */
}
/* L'écran est montré ENTIER, sans rien par-dessus : le titre et la
   phrase qui vivaient en haut de la carte mangeaient un tiers de l'image
   et coupaient l'écran en bas. Chaque bandeau porte déjà son nom, et les
   montages écrivent le leur. */
.hcard__media {
  position: relative;
  aspect-ratio: 1170 / 2532;
  background: var(--bg);
}
.hcard__media--video { aspect-ratio: 720 / 1280; }
/* La carte à vidéo a la hauteur du bandeau, et l'écran la REMPLIT. Sa
   hauteur venait du rapport de forme, calculé sur la largeur moins les
   deux filets de bordure : il manquait un pixel et demi en bas, où le
   fond blanc de la carte passait en trait — invisible à taille normale,
   net une fois la carte grossie. */
.band--films .hcard { height: var(--hcard-h); }
.band--films .hcard__media--video { aspect-ratio: auto; height: 100%; }
/* Et la vidéo déborde d'un pixel tout autour, rognée par l'arrondi de la
   carte : grossie, une carte composée par le navigateur arrondit ses
   bords au demi-pixel, et le fond clair du cadre passait dessous en
   liseré. */
.band--films .hcard__media video,
.band--films .hcard__media img {
  inset: -1px;
  width: calc(100% + 2px);
  height: calc(100% + 2px);
}
/* L'écran est posé en ABSOLU dans son cadre, et c'est ce qui fait tenir
   le rapport de forme : une image ou une vidéo en `height: 100%` dans
   une boîte dont la hauteur vient d'un `aspect-ratio` forme une boucle,
   et le navigateur retombe alors sur les proportions du fichier — la
   vidéo s'affichait deux fois trop grande, son titre coupé aux deux
   bouts. Sorti du flux, il ne dicte plus rien. */
.hcard__media img,
.hcard__media video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: top;
  display: block;
}


/* Le bandeau SEUL, en paysage : une carte au format de sa vidéo (16/9),
   aussi large que le permet la hauteur du bandeau, sans toucher les
   bords de l'écran. Le reste — voile, grossissement, lecture — est
   celui des deux bandeaux d'écrans. */
.band--solo { --hcard-w: min(calc(var(--hcard-h) * 16 / 9), calc(100vw - 200px), 1100px); }
.band--solo .hcard { height: calc(var(--hcard-w) * 9 / 16); }
.band--solo .hcard__media--video { aspect-ratio: auto; height: 100%; background: #fff; }
.band--solo .hcard__media video,
.band--solo .hcard__media img {
  inset: -1px;
  width: calc(100% + 2px);
  height: calc(100% + 2px);
  object-position: center;
}

.rail__arrow {
  position: absolute;
  top: calc(50% + 20px);
  z-index: 3;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  display: none;
  align-items: center;
  justify-content: center;
  color: var(--text);
  background: var(--glass-bg);
  border: 1px solid var(--glass-border);
  backdrop-filter: blur(18px);
  -webkit-backdrop-filter: blur(18px);
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.35);
  transition: transform 0.2s var(--ease-out), opacity 0.2s var(--ease-out);
}
.rail__arrow svg { width: 20px; height: 20px; }
.rail__arrow--prev { left: max(16px, calc(50vw - 690px)); }
.rail__arrow--next { right: max(16px, calc(50vw - 690px)); }
.rail__arrow[disabled] { opacity: 0; pointer-events: none; }
@media (hover: hover) and (min-width: 1000px) {
  .rail__arrow { display: flex; }
  .rail__arrow:hover { transform: scale(1.06); }
  .rail__track { cursor: grab; }
  .rail.is-dragging .rail__track { cursor: grabbing; scroll-snap-type: none; }
}

@media (max-width: 900px) {
  .band { margin-top: 40px; }
  .band { --hcard-h: min(560px, 74vh); }
  /* Sur un téléphone, la carte ne dépasse jamais la largeur de l'écran. */
  .band--films { --hcard-w: min(calc(var(--hcard-h) * 720 / 1280), 82vw); }
  /* Sur téléphone, le badge a sa version DEBOUT (`badge-mobile.mp4`,
     720 × 1280, posée par site.js) : en paysage, la vidéo tenait sur
     deux cents pixels de haut et ne se lisait pas. La carte prend donc
     la forme de celles des deux interfaces. */
  .band--solo { --hcard-w: min(calc(var(--hcard-h) * 720 / 1280), 82vw); }
  .band--solo .hcard { height: calc(var(--hcard-w) * 1280 / 720); }
  .rail__track { gap: 16px; }
}

/* ------------------------------------------------------------------ */
/* La génération, scrubbée : la scène est épinglée, le téléphone joue  */
/* la séquence du curseur puis tourne sur les écrans de la revue.      */
/* ------------------------------------------------------------------ */
/* 560 et non plus 480 : le passage du curseur au mois compte double
   (`SLOW_SHARE`, site.js). */
/* 520vh, dont 40vh pour l'entrée du téléphone et 60vh de tenue sur le
   planning généré avant « Publier ». La section REMONTE de 72vh
   sous la fin des vidéos de l'équipe : il restait trois quarts d'écran
   de page blanche entre le voile qui se lève et le téléphone qui
   apparaît (« ça met trop de temps à être visible », 28 septembre 2026).
   La scène ne prend aucun clic, pour laisser les cartes qui partent
   répondre sous elle. */
.scrub { position: relative; height: 520vh; margin-top: -72vh; }
.scrub.is-ready .scrub__stage { pointer-events: none; }
.scrub__stage {
  position: sticky;
  top: 0;
  height: 100vh;
  height: 100dvh;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}
/* Le téléphone n'est PAS centré : il se tient d'un côté, le texte de
   l'autre, et les deux échangent leur place d'un moment à l'autre.
   Il ne tourne plus sur lui-même — le montage enchaîne les écrans tout
   seul —, donc la perspective ne sert plus.

   Le « téléphone » est ici le cadre de l'animation : elle dessine son
   propre appareil, ombre comprise, dans une scène de 1018 × 1884. On
   garde donc exactement ce rapport, sans quoi l'animation se recadre
   elle-même et l'appareil rétrécit au milieu du vide. */
.scrub__anim {
  position: relative;
  width: min(370px, 47vh);
  aspect-ratio: 1018 / 1884;
  /* L'ENTRÉE : une fois la scène figée, le téléphone apparaît en fondu
     en grandissant un peu depuis son centre, avec sa légende — la
     transition de l'étape 1 (site.js, `--enter-s`). Couché et éteint,
     puis montant du bas : retirés tous les deux. */
  transform: translateX(var(--phone-x, 0px)) translateY(var(--center-y, 0px))
             scale(var(--enter-s, 1));
  transform-origin: 50% 50%;
  will-change: transform, opacity;
}
/* Le halo, centré sur le téléphone : il culmine quand le téléphone se
   pose, puis s'éteint pendant qu'on lit la légende. */
.scrub__halo {
  position: absolute;
  left: 50%; top: 50%;
  width: 1100px; height: 1100px; margin: -550px 0 0 -550px;
  border-radius: 50%;
  pointer-events: none;
  background: radial-gradient(closest-side, var(--scrub-halo), rgba(183, 217, 143, 0) 68%);
  opacity: var(--enter-glow, 0);
  transform: translateX(var(--phone-x, 0px)) scale(var(--enter-halo, 1));
}
:root { --scrub-halo: rgba(183, 217, 143, 0.13); }
:root[data-theme="light"] { --scrub-halo: rgba(143, 179, 104, 0.16); }
.scrub__anim iframe {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
  background: transparent;
  /* Sans cette ligne, le cadre est un rectangle BLANC.
     Le site déclare `color-scheme: dark` (ou `light`) sur sa racine ; la
     page du cadre, elle, n'en déclare aucun. Quand les deux diffèrent,
     Chrome refuse la transparence et peint le fond de la page encadrée en
     blanc pour garantir le contraste. `normal` retire la déclaration du
     cadre : les deux redeviennent d'accord, et le halo du site se voit
     derrière l'ombre du téléphone. */
  color-scheme: normal;
  /* Le cadre dessinait un RECTANGLE plus gris que la page autour du
     téléphone. Ce n'est pas un fond : c'est l'ombre portée de l'appareil,
     large de cent cinquante pixels, que la scène de l'animation coupe à
     ses propres bords — le cadre ne fait que montrer la coupe. On ne peut
     pas la retirer de l'animation, alors on ÉTEINT ses bords : un masque
     rend les six pour cent extérieurs transparents, soit exactement la
     marge qui entoure l'appareil. L'ombre s'efface où elle était tranchée,
     et l'appareil n'est pas entamé. */
  -webkit-mask-image:
    linear-gradient(to right, transparent 0, #000 6%, #000 94%, transparent 100%),
    linear-gradient(to bottom, transparent 0, #000 6%, #000 94%, transparent 100%);
  -webkit-mask-composite: source-in;
  mask-image:
    linear-gradient(to right, transparent 0, #000 6%, #000 94%, transparent 100%),
    linear-gradient(to bottom, transparent 0, #000 6%, #000 94%, transparent 100%);
  mask-composite: intersect;
  /* Le cadre ne prend jamais le doigt ni la molette : le geste appartient
     à la page, c'est lui qui fait avancer le montage. */
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.35s ease;
}
.scrub__anim.is-live iframe { opacity: 1; }
.scrub__still {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
  /* Le même fondu des bords que le cadre : l'ombre de l'image d'attente
     est coupée aux mêmes bords, et dessinait le même rectangle. */
  -webkit-mask-image:
    linear-gradient(to right, transparent 0, #000 6%, #000 94%, transparent 100%),
    linear-gradient(to bottom, transparent 0, #000 6%, #000 94%, transparent 100%);
  -webkit-mask-composite: source-in;
  mask-image:
    linear-gradient(to right, transparent 0, #000 6%, #000 94%, transparent 100%),
    linear-gradient(to bottom, transparent 0, #000 6%, #000 94%, transparent 100%);
  mask-composite: intersect;
  transition: opacity 0.35s ease;
}
.scrub__anim.is-live .scrub__still { opacity: 0; }
.scrub__copy {
  position: absolute;
  top: calc(50% + var(--center-y, 0px));
  width: min(360px, 30vw);
  opacity: 0;
  transform: translateY(calc(-50% + var(--story-shift, 0px)));
  will-change: transform, opacity;
}
.scrub__copy--left { right: calc(50% + 40px); text-align: right; }
.scrub__copy--right { left: calc(50% + 40px); text-align: left; }
.scrub__copy h3 {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(22px, 2.2vw, 30px);
  letter-spacing: -0.02em;
  line-height: 1.1;
  margin-bottom: 10px;
}
.scrub__copy p:not(.story__step) { font-size: 15px; color: var(--text-3); line-height: 1.55; }
.scrub .story__screens > img,
.scrub .story__screens > canvas { position: absolute; inset: 0; opacity: 0; width: 100%; height: 100%; object-fit: cover; display: block; }
.scrub .story__screens > img[data-scrub-screen="0"] { position: relative; opacity: 1; }
/* La toile prend la place de l'image une fois les vues décodées : elle
   est alors DEVANT, et l'image dessous ne sert plus que de gabarit de
   hauteur. */
.scrub .story__screens > canvas[data-scrub-canvas] { opacity: 1; z-index: 1; }

@media (max-width: 900px) {
  .scrub { height: 475vh; }
  /* La légende vit SOUS le téléphone, dans la scène : on remonte donc le
     téléphone d'autant, sinon elle sort de l'écran. */
  /* Le téléphone occupe TOUTE la place entre la barre et la légende
     (Matteo, 29 septembre) : la scène est bornée en haut par la barre et
     en bas par la légende, et l'appareil prend la hauteur qui reste. */
  .scrub__stage { padding-top: 58px; padding-bottom: 178px; }
  .scrub .scrub__anim { width: min(92vw, calc((100vh - 236px) * 0.5403)); width: min(92vw, calc((100dvh - 236px) * 0.5403)); }
  /* Sur téléphone, le décalage horizontal n'a pas la place d'exister ;
     l'entrée, elle, reste. */
  .scrub__stage .scrub__anim {
    transform: scale(var(--enter-s, 1));
  }
  .scrub__copy,
  .scrub__copy--left,
  .scrub__copy--right {
    top: auto;
    bottom: 5vh;
    left: 50%;
    right: auto;
    width: min(340px, 86vw);
    text-align: center;
    transform: translate(-50%, var(--story-shift, 0px));
  }
}

/* Sans JavaScript ou en mouvement réduit : rien n'épingle, on lit les
   trois moments l'un sous l'autre. */
.scrub:not(.is-ready) { height: auto; margin-top: 0; }
.scrub:not(.is-ready) .scrub__stage {
  position: static;
  height: auto;
  flex-direction: column;
  gap: 28px;
  padding: 80px 24px;
}
.scrub:not(.is-ready) .scrub__copy {
  position: static;
  transform: none;
  opacity: 1;
  width: min(420px, 90vw);
  text-align: center;
}
.scrub:not(.is-ready) .story__screens > img { position: static; opacity: 1; margin-bottom: 20px; }
.scrub:not(.is-ready) .phone__depth,
.scrub:not(.is-ready) .scrub__halo { display: none; }

/* Fonctionnalités — rangées alternées */
.features { padding: 76px 0 24px; }
.features .section-title { margin-bottom: 44px; }
.feature {
  display: grid;
  grid-template-columns: 1fr 1fr;
  align-items: center;
  gap: clamp(28px, 4vw, 64px);
  padding: 26px 0;
}
.feature--flip .feature__copy { order: 2; }
.feature--flip .feature__art { order: 1; }
.feature__copy h3 {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(1.35rem, 2vw, 1.7rem);
  letter-spacing: -0.02em;
  margin-bottom: 14px;
}
.feature__copy p { color: var(--text-2); font-size: 16px; max-width: 46ch; }
.feature__copy p + p { margin-top: 14px; }
.feature__art { display: flex; justify-content: center; }

@media (max-width: 860px) {
  .feature { grid-template-columns: 1fr; padding: 24px 0; }
  .feature--flip .feature__copy { order: 1; }
  .feature--flip .feature__art { order: 2; }
  .feature__copy { text-align: center; }
  .feature__copy p { margin-inline: auto; }
}

/* ------------------------------------------------------------------ */
/* Sur ordinateur aussi (8.4, 11 octobre 2026) : le titre et quatre    */
/* points à gauche, un portable et une tablette à droite. Les écrans   */
/* sont de vraies captures du jeu de démonstration                     */
/* (tools/desktop-shots.mjs), les appareils sont dessinés en CSS, de   */
/* la matière des téléphones du haut de page.                          */
/*                                                                    */
/* L'ENTRÉE est suivie au défilement (site.js, `initDesk`), à la façon */
/* des pages d'Apple : le portable monte et s'ouvre — l'écran pivote   */
/* sur sa charnière —, s'allume, un reflet passe dessus, puis la       */
/* tablette vient se poser devant. Chaque étape lit une variable posée */
/* par le script ; sans lui (ou en mouvement réduit), les variables    */
/* gardent leur valeur de repos et tout est posé d'emblée.            */
/* ------------------------------------------------------------------ */
/* `clip` et non `hidden` : le halo ne fait pas glisser la page de côté,
   et rien ne devient une boîte à défilement. */
.desk { padding: 130px 0 110px; overflow-x: clip; }
.desk__grid {
  display: grid;
  grid-template-columns: minmax(0, 0.78fr) minmax(0, 1.22fr);
  grid-template-areas: "head stage" "points stage";
  column-gap: clamp(40px, 5vw, 76px);
  row-gap: 30px;
}
.desk__head { grid-area: head; align-self: end; }
.desk__stage { grid-area: stage; align-self: center; }
.desk__points { grid-area: points; align-self: start; }
.desk__kicker { font-size: 14px; font-weight: 600; color: var(--accent-text); margin-bottom: 10px; }
.desk__title {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(2.1rem, 4.4vw, 3rem);
  line-height: 1.06;
  letter-spacing: -0.03em;
  text-wrap: balance;
}
.desk__lede { margin-top: 16px; font-size: 16.5px; line-height: 1.6; color: var(--text-2); max-width: 44ch; }
.desk__points { list-style: none; display: grid; gap: 20px; }
.desk__point { display: flex; align-items: flex-start; gap: 16px; }
.desk__ico {
  width: 42px;
  height: 42px;
  border-radius: 13px;
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--accent-text);
  background: color-mix(in srgb, #8FB368 16%, transparent);
  border: 1px solid color-mix(in srgb, #8FB368 34%, transparent);
}
.desk__ico svg { width: 21px; height: 21px; }
.desk__point h3 { font-size: 16px; font-weight: 600; letter-spacing: -0.01em; line-height: 1.3; margin: 2px 0 4px; }
.desk__point p { font-size: 14.5px; line-height: 1.55; color: var(--text-3); text-wrap: pretty; }

/* La scène : le portable dans le flux, la tablette posée devant lui, en
   bas à gauche, qui déborde un peu vers le texte. Le bas de la scène
   laisse la place à ce qu'elle dépasse sous le portable. */
.desk__stage {
  position: relative;
  isolation: isolate;
  padding: 0 0 8% 4%;
  /* Le portable SORT de la colonne vers la droite, jusqu'à 40 px du bord
     de l'écran : dans sa seule colonne, il était plus petit que le texte
     d'à côté. Sur un écran étroit, la marge négative tombe à zéro. */
  margin-right: min(0px, calc(600px - 50vw));
  /* Les valeurs de REPOS : sans script, tout est posé. */
  --lift: 0px;
  --lid: 0deg;
  --off: 0;
  --glare: -70%;
  --glare-o: 0;
  --tx: 0px;
  --ty: 0px;
  --tr: 0deg;
  --t-o: 1;
  --glow: 1;
  --par-l: 0px;
  --par-t: 0px;
}
/* Le halo de la génération, derrière les appareils. */
.desk__glow {
  position: absolute;
  z-index: -1;
  left: 54%;
  top: 46%;
  width: 125%;
  aspect-ratio: 1.5;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  background: radial-gradient(closest-side, var(--scrub-halo), rgba(183, 217, 143, 0) 70%);
  opacity: var(--glow);
  pointer-events: none;
}
.laptop {
  position: relative;
  margin: 0;
  /* La perspective est celle d'un regard posé un peu AU-DESSUS du
     portable : l'écran qui se ferme vers nous se lit en raccourci. */
  perspective: 1800px;
  perspective-origin: 50% -20%;
  transform: translate3d(0, calc(var(--lift) + var(--par-l)), 0);
}
/* L'ombre que le portable pose sur la table. */
.laptop::after {
  content: "";
  position: absolute;
  z-index: -1;
  left: 3%;
  right: 3%;
  bottom: -18px;
  height: 30px;
  border-radius: 50%;
  background: radial-gradient(closest-side, rgba(20, 24, 12, 0.30), rgba(20, 24, 12, 0));
  pointer-events: none;
}
.laptop__lid {
  position: relative;
  width: 86%;
  margin: 0 auto;
  transform-origin: 50% 100%;
  transform: rotateX(var(--lid));
  transform-style: preserve-3d;
}
.laptop__face {
  position: relative;
  padding: 1.6% 1.6% 2.3%;
  border-radius: clamp(10px, 1.5vw, 18px) clamp(10px, 1.5vw, 18px) 4px 4px;
  background: linear-gradient(180deg, #1d2116, #0d0f09);
  border: 1px solid rgba(255, 255, 255, 0.12);
  box-shadow:
    0 2px 0 rgba(255, 255, 255, 0.07) inset,
    0 26px 50px rgba(20, 24, 12, 0.16),
    0 4px 12px rgba(20, 24, 12, 0.10);
  -webkit-backface-visibility: hidden;
  backface-visibility: hidden;
}
/* Le dos de l'écran, l'aluminium, qu'on aperçoit portable fermé. */
.laptop__back {
  position: absolute;
  inset: 0;
  border-radius: clamp(10px, 1.5vw, 18px) clamp(10px, 1.5vw, 18px) 4px 4px;
  background: linear-gradient(180deg, #474d3c, #2a2e22);
  transform: rotateY(180deg);
  -webkit-backface-visibility: hidden;
  backface-visibility: hidden;
}
.laptop__cam {
  position: absolute;
  top: 0;
  left: 50%;
  width: 5px;
  height: 5px;
  /* Une marge en pourcentage se lit sur la LARGEUR : la caméra reste au
     milieu du bandeau du haut, quelle que soit la taille. */
  margin: calc(0.8% - 2.5px) 0 0 -2.5px;
  border-radius: 50%;
  background: #2b3123;
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.06);
}
.laptop__screen {
  position: relative;
  aspect-ratio: 1560 / 975;
  overflow: hidden;
  border-radius: clamp(4px, 0.6vw, 8px) clamp(4px, 0.6vw, 8px) 2px 2px;
  background: #13170C;
}
.laptop__screen img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
/* L'écran ÉTEINT : un noir posé sur la capture, qui s'efface. */
.laptop__off { position: absolute; inset: 0; background: #050604; opacity: var(--off); pointer-events: none; }
/* Le reflet qui passe sur l'écran quand il s'allume. */
.laptop__glare {
  position: absolute;
  top: -10%;
  bottom: -10%;
  left: -30%;
  width: 60%;
  background: linear-gradient(100deg, rgba(255, 255, 255, 0) 30%, rgba(255, 255, 255, 0.14) 50%, rgba(255, 255, 255, 0) 70%);
  transform: translate3d(var(--glare), 0, 0);
  opacity: var(--glare-o);
  pointer-events: none;
}
/* Le socle : une plaque plus large que l'écran, l'encoche au milieu de
   son bord, éclairée sur son arête haute. */
.laptop__base {
  position: relative;
  height: 0;
  padding-bottom: 2.5%;
  margin-top: -1px;
  border-radius: 2px 2px 40% 40% / 2px 2px 100% 100%;
  background: linear-gradient(180deg, #5a6050 0%, #353a2c 38%, #1b1e15 100%);
  box-shadow: 0 1px 0 rgba(255, 255, 255, 0.22) inset;
}
.laptop__base::before {
  content: "";
  position: absolute;
  top: 0;
  left: 50%;
  width: 14%;
  height: 40%;
  transform: translateX(-50%);
  border-radius: 0 0 10px 10px / 0 0 100% 100%;
  background: linear-gradient(180deg, #23271b, #3c4233);
}
.tablet {
  position: absolute;
  z-index: 2;
  left: -4%;
  bottom: 0;
  width: 27%;
  margin: 0;
  padding: clamp(5px, 0.75vw, 10px);
  border-radius: clamp(16px, 2.1vw, 26px);
  background: linear-gradient(180deg, #262b1c, #14170d);
  border: 1px solid rgba(255, 255, 255, 0.14);
  box-shadow:
    0 2px 0 rgba(255, 255, 255, 0.08) inset,
    0 28px 54px rgba(20, 24, 12, 0.30),
    0 6px 16px rgba(20, 24, 12, 0.16);
  transform: translate3d(var(--tx), calc(var(--ty) + var(--par-t)), 0) rotate(var(--tr));
  transform-origin: 50% 100%;
  opacity: var(--t-o);
}
.tablet__screen {
  position: relative;
  aspect-ratio: 540 / 773;
  overflow: hidden;
  border-radius: calc(clamp(16px, 2.1vw, 26px) - clamp(5px, 0.75vw, 10px));
  background: #13170C;
}
.tablet__screen img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
/* Pendant l'entrée seulement : le navigateur prépare les calques. */
.desk.is-moving .laptop,
.desk.is-moving .laptop__lid,
.desk.is-moving .tablet { will-change: transform; }

@media (max-width: 960px) {
  .desk { padding: 100px 0 90px; }
  .desk__grid { display: flex; flex-direction: column; gap: 34px; }
  .desk__head { text-align: center; }
  .desk__lede { margin-inline: auto; }
  .desk__stage { padding: 0 0 9% 3%; width: min(100%, 640px); margin: 0 auto; }
  .tablet { left: -3%; width: 29%; }
  .desk__points { width: min(100%, 560px); margin: 0 auto; }
}

/* Conformité — grille de règles */
.rules { padding: 120px 0; }
/* Deux familles, chacune son titre et sa rangée (audit 7.6). */
.rules__group + .rules__group { margin-top: 44px; }
.rules__head { text-align: center; max-width: 640px; margin: 0 auto; }
.rules__title {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(22px, 2.4vw, 28px);
  letter-spacing: -0.02em;
  line-height: 1.15;
}
.rules__lede { margin-top: 8px; font-size: 15px; line-height: 1.55; color: var(--text-2); text-wrap: balance; }
.rules__head + .rules__grid { margin-top: 26px; }
/* Sans JavaScript : une grille ordinaire. */
.rules__grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 14px;
}
@media (max-width: 1000px) { .rules__grid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 560px) { .rules__grid { grid-template-columns: 1fr; } }

/* Avec JavaScript : trois rangées qui dérivent, sens alternés, fondu sur
   les bords — la grille des Droplets de getdroppy.app, portée au verre
   sombre de Rost. Chaque rangée porte DEUX jeux identiques et l'animation
   parcourt exactement un jeu : le jeu porte l'espace final en padding,
   donc la boucle n'a pas de couture. */
.rules__rows {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  /* L'écart entre rangées et l'air en haut et en bas laissent passer la
     lueur et l'ombre des panneaux : le défilé masque ce qui dépasse, et
     sans cette place les panneaux étaient COUPÉS net en haut et en bas. */
  gap: 30px;
  padding: 26px 0 40px;
  overflow: hidden;
  /* Le défilé sort de la colonne et va d'un bord à l'autre de l'écran :
     une règle coupée par le bord est ce qui dit qu'il en passe d'autres.
     Le fondu reste, mais serré — à 8 % il mangeait une carte entière de
     chaque côté. */
  width: 100vw;
  margin-left: calc(50% - 50vw);
  -webkit-mask-image: linear-gradient(90deg, transparent 0%, #000 3%, #000 97%, transparent 100%);
  mask-image: linear-gradient(90deg, transparent 0%, #000 3%, #000 97%, transparent 100%);
}
.rules__row {
  display: flex;
  width: max-content;
  animation: rules-drift var(--row-dur, 84s) linear infinite;
  animation-delay: var(--row-phase, 0s);
}
.rules__row--reverse { animation-direction: reverse; }
.rules__rows:hover .rules__row { animation-play-state: paused; }
/* Une rangée hors écran continue de coûter une composition par image. */
.rules__row.is-offstage { animation-play-state: paused !important; }
@keyframes rules-drift { to { transform: translateX(-50%); } }
.rules__set { display: flex; gap: 14px; padding-right: 14px; }

/* Les panneaux de la Conformité passent au VERRE, comme les cartes de
   l'application : une matière translucide qui laisse passer le fond,
   une arête haute éclairée, une assise sombre. Ils défilent au-dessus du
   halo, et c'est précisément ce qui rend le verre lisible — il prend la
   couleur de ce qui passe dessous.

   Pas de `saturate()` dans le flou : sur un fond lime il vire au vert.
   Leçon déjà payée dans l'application. */
.rule {
  position: relative;
  width: 300px;
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 14px 16px;
  border-radius: var(--radius);
  background: var(--glass-bg);
  border: 1px solid var(--glass-border);
  /* Quatorze pixels et non vingt : mesuré sur la bande qui défile, le
     flou coûte un quart du temps d'image, et il se lit pareil. */
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.14),
    inset 0 -1px 0 rgba(0, 0, 0, 0.18),
    0 12px 28px rgba(0, 0, 0, 0.22);
  text-align: left;
  transition: background 0.2s var(--ease-out), border-color 0.2s var(--ease-out);
}
/* Le reflet du haut : une bande claire qui s'éteint au tiers, comme sur
   une arête de verre éclairée par le dessus. */
.rule::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.10), rgba(255, 255, 255, 0) 38%);
}
.rule:hover { background: var(--card); border-color: var(--accent-ring); }
/* Le même verre en thème CLAIR, et il demande plus de travail : sur du
   blanc, une plaque translucide blanche ne se voit pas. Ce qui la fait
   exister, c'est l'ARÊTE — un filet clair en haut, un filet sombre en
   bas — et une ombre portée basse. Le fond descend à 38 % pour que le
   halo de la page passe au travers. */
/* Le même verre en thème CLAIR, et il demande plus de travail : sur du
   blanc, une plaque translucide blanche ne se voit pas. Ce qui la fait
   exister, c'est la LUEUR DU POURTOUR — une bande claire et floue tout
   le long du bord, plus vive en haut et en bas —, une arête nette d'un
   pixel, et une ombre portée basse. Le centre reste le plus transparent :
   c'est ce qui donne l'épaisseur. */
:root[data-theme="light"] .rule {
  /* Un fond GRIS-blanc et non blanc pur : c'est le gris qui donne au
     verre son épaisseur — une plaque parfaitement blanche sur du blanc
     n'est plus une plaque, c'est un trou. Le dégradé descend vers le
     gris, la lueur du pourtour reste blanche. */
  background: linear-gradient(170deg, rgba(255, 255, 255, 0.58), rgba(226, 229, 222, 0.62));
  border-color: rgba(255, 255, 255, 0.60);
  box-shadow:
    inset 0 0 0 1px rgba(255, 255, 255, 0.85),
    inset 0 12px 24px -12px rgba(255, 255, 255, 1),
    inset 0 -12px 24px -12px rgba(255, 255, 255, 1),
    inset 16px 0 26px -16px rgba(255, 255, 255, 0.95),
    inset -16px 0 26px -16px rgba(255, 255, 255, 0.95),
    0 16px 34px rgba(20, 24, 12, 0.10),
    0 2px 6px rgba(20, 24, 12, 0.04);
}
:root[data-theme="light"] .rule::before {
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.55), rgba(255, 255, 255, 0) 46%);
}
.rule__icon {
  width: 52px;
  height: 52px;
  border-radius: 14px;
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--tint, var(--accent));
  background: color-mix(in srgb, var(--tint, #8FB368) 16%, transparent);
  border: 1px solid color-mix(in srgb, var(--tint, #8FB368) 34%, transparent);
}
.rule__icon svg { width: 25px; height: 25px; }
.rule__copy { flex: 1; min-width: 0; }
.rule__name {
  font-size: 15px;
  font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--text);
  margin-bottom: 3px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.rule__body {
  font-size: 12.5px;
  color: var(--text-3);
  line-height: 1.4;
  /* Deux lignes au plus : le texte est écrit pour tenir, ceci est le filet. */
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

@media (prefers-reduced-motion: reduce) {
  .rules__rows { -webkit-mask-image: none; mask-image: none; }
  .rules__row { animation: none; width: auto; justify-content: center; }
  .rules__set { flex-wrap: wrap; justify-content: center; padding-right: 0; }
  .rules__set[aria-hidden] { display: none; }
}

/* Preuve */
.proof {
  padding: 120px 0;
  background: linear-gradient(180deg, rgba(12, 15, 7, 0) 0%, var(--bg-deep) 18%, var(--bg-deep) 82%, rgba(12, 15, 7, 0) 100%);
}
.proof__stats {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 16px;
  max-width: 900px;
  margin: 0 auto;
}
/* Les chiffres se déroulent au défilement (`initCounters`, site.js). */
.stat {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 30px 26px;
  text-align: center;
}
.stat__value {
  display: block;
  font-weight: 600;
  font-size: clamp(34px, 3.6vw, 48px);
  letter-spacing: -0.03em;
  line-height: 1;
  color: var(--accent-text);
  margin-bottom: 12px;
  /* Des chiffres de même largeur : sans ça, le nombre tremble en
     défilant, chaque chiffre ayant sa chasse. */
  font-variant-numeric: tabular-nums;
}
.stat__label { font-size: 14px; color: var(--text-2); line-height: 1.5; display: block; }
.proof__note {
  text-align: center;
  margin-top: 28px;
  font-size: 13px;
  color: var(--text-3);
}
@media (max-width: 720px) { .proof__stats { grid-template-columns: 1fr; } }

/* ------------------------------------------------------------------ */
/* Vos fichiers, dans les deux sens (8.5, 11 octobre 2026) : quatre    */
/* cartes. La carte blanche du comptable et la carte sombre de la      */
/* reprise reprennent les deux cartes de l'accès (le blanc du pilote,  */
/* le vert de l'abonnement et ses nuages) ; l'impression et l'agenda   */
/* sont blanches. Chaque carte porte une petite scène dessinée en      */
/* HTML, qui JOUE en entrant dans l'écran (site.js, `initFiles`, pose  */
/* `is-armed` sur la section puis `is-in` sur la carte). Sans script   */
/* ou en mouvement réduit, `is-armed` n'est jamais posé : tout est là. */
/* ------------------------------------------------------------------ */
.files { padding: 110px 0 50px; }
.files__grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 20px;
  max-width: 1060px;
  margin: 0 auto;
}
.fcard {
  position: relative;
  display: flex;
  flex-direction: column;
  border-radius: 26px;
  background: var(--card-strong);
  border: 1px solid var(--border);
  overflow: hidden;
  isolation: isolate;
}
:root[data-theme="light"] .fcard--light {
  background: #ffffff;
  box-shadow: 0 30px 70px rgba(20, 24, 12, 0.12), 0 8px 22px rgba(20, 24, 12, 0.06);
}
/* La carte sombre : celle de l'abonnement, jetons du sombre compris. */
.fcard--dark {
  --text: #ffffff;
  --text-2: rgba(255, 255, 255, 0.75);
  --text-3: rgba(255, 255, 255, 0.55);
  --accent-text: #B7D98F;
  --btn-fill: #B7D98F;
  --accent-ring: rgba(183, 217, 143, 0.35);
  --border: rgba(255, 255, 255, 0.08);
  background: linear-gradient(180deg, rgba(183, 217, 143, 0.10), rgba(183, 217, 143, 0.03)), #13170C;
  border-color: rgba(183, 217, 143, 0.35);
  color: var(--text);
  box-shadow: 0 30px 70px rgba(20, 24, 12, 0.22), 0 8px 22px rgba(20, 24, 12, 0.10);
}
.fcard--dark > :not(.card-clouds) { position: relative; z-index: 1; }
.fcard__copy { display: flex; flex-direction: column; flex: 1; padding: 26px 32px 32px; }
.fcard__tag { font-size: 13px; color: var(--text-3); margin-bottom: 8px; }
.fcard h3 {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 23px;
  letter-spacing: -0.02em;
  line-height: 1.15;
  margin-bottom: 10px;
}
.fcard__copy > p:not(.fcard__tag) { font-size: 15px; line-height: 1.55; color: var(--text-2); }
.fcard__list { list-style: none; display: grid; gap: 10px; margin-top: 16px; }
.fcard__list li { position: relative; padding-left: 20px; font-size: 14.5px; line-height: 1.5; color: var(--text-2); text-wrap: pretty; }
.fcard__list li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 8px;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--accent-dim);
}

/* La scène d'une carte : un papier vert très pâle, posé dans la carte. */
.fcard__art {
  position: relative;
  display: grid;
  align-content: center;
  margin: 12px 12px 0;
  height: 280px;
  border-radius: 18px;
  overflow: hidden;
  background:
    radial-gradient(90% 70% at 50% 0%, rgba(183, 217, 143, 0.30), rgba(183, 217, 143, 0) 70%),
    linear-gradient(180deg, #f3f5ee, #e9ede1);
}

/* Le fichier du comptable, ouvert dans un tableur. Plus large que la
   carte au téléphone : la fenêtre sort alors par la droite, comme une
   feuille de calcul trop grande pour l'écran. */
.csv {
  width: 470px;
  margin-left: max(14px, calc((100% - 470px) / 2));
  border-radius: 12px;
  overflow: hidden;
  background: #ffffff;
  color: #16190e;
  border: 1px solid rgba(20, 24, 12, 0.08);
  box-shadow: 0 18px 40px rgba(20, 24, 12, 0.14), 0 2px 6px rgba(20, 24, 12, 0.08);
}
.csv__bar {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 9px 12px;
  background: #f6f7f3;
  border-bottom: 1px solid rgba(20, 24, 12, 0.08);
}
.csv__dots { display: flex; gap: 5px; }
.csv__dots i { width: 8px; height: 8px; border-radius: 50%; background: rgba(20, 24, 12, 0.14); }
.csv__name { display: inline-flex; align-items: center; gap: 6px; font-size: 11.5px; font-weight: 600; color: rgba(22, 25, 14, 0.78); }
.csv__name svg { width: 14px; height: 14px; }
.csv__table { width: 100%; border-collapse: collapse; table-layout: fixed; font-size: 10.5px; }
.csv__table th,
.csv__table td {
  padding: 5px 7px;
  border-right: 1px solid rgba(20, 24, 12, 0.08);
  border-bottom: 1px solid rgba(20, 24, 12, 0.08);
  text-align: right;
  font-variant-numeric: tabular-nums;
}
.csv__table th:first-child,
.csv__table td:first-child { width: 24%; text-align: left; }
.csv__table th {
  padding: 5px 6px;
  font-size: 9px;
  font-weight: 600;
  line-height: 1.25;
  text-align: left;
  vertical-align: bottom;
  background: #fafbf7;
  color: rgba(22, 25, 14, 0.80);
}
.csv__table td:first-child { font-weight: 600; }
/* La cellule choisie, comme dans un tableur : un cadre vert. */
.csv__hi { position: relative; }
.csv__hi::after {
  content: "";
  position: absolute;
  inset: -1px;
  border: 2px solid #8FB368;
  border-radius: 2px;
  background: rgba(168, 205, 116, 0.14);
  pointer-events: none;
}
.csv__rules { padding: 7px 10px 0; font-size: 9px; line-height: 1.4; color: rgba(22, 25, 14, 0.55); }
.csv__rules:last-child { padding-bottom: 10px; }

/* Le planning tenu dans un tableur, qui passe dans Rost, et la semaine
   type qui en sort. La scène est une vitre sombre dans la carte verte. */
.fcard__art--dark {
  align-content: start;
  gap: 18px;
  padding: 22px 22px 0;
  background: rgba(255, 255, 255, 0.04);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.08);
}
.imp { display: flex; align-items: center; }
.imp__file {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 9px 13px;
  border-radius: 12px;
  background: rgba(255, 255, 255, 0.08);
  border: 1px solid rgba(255, 255, 255, 0.14);
  font-size: 13px;
  font-weight: 600;
  color: rgba(255, 255, 255, 0.85);
  white-space: nowrap;
}
.imp__file svg { width: 18px; height: 18px; color: rgba(255, 255, 255, 0.7); }
.imp__line {
  position: relative;
  flex: 1;
  height: 2px;
  margin: 0 12px;
  background: repeating-linear-gradient(90deg, rgba(255, 255, 255, 0.28) 0 6px, rgba(255, 255, 255, 0) 6px 12px);
}
.imp__line i {
  position: absolute;
  top: 50%;
  left: 0;
  width: 8px;
  height: 8px;
  margin: -4px 0 0 -4px;
  border-radius: 50%;
  background: #B7D98F;
  animation: imp-travel 2.6s cubic-bezier(0.45, 0, 0.25, 1) infinite;
}
@keyframes imp-travel {
  0% { left: 0; opacity: 0; }
  14% { opacity: 1; }
  78% { left: 100%; opacity: 1; }
  100% { left: 100%; opacity: 0; }
}
.imp__rost {
  width: 46px;
  height: 46px;
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 14px;
  background: rgba(183, 217, 143, 0.10);
  border: 1px solid rgba(183, 217, 143, 0.32);
}
.imp__rost img { width: 24px; height: 24px; }
.fsteps { list-style: none; display: grid; gap: 14px; margin: 20px 0 28px; }
.fsteps li { position: relative; display: flex; align-items: flex-start; gap: 14px; }
.fsteps__n {
  flex: 0 0 auto;
  width: 28px;
  height: 28px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  font-family: var(--font-display);
  font-size: 14px;
  font-weight: 600;
  color: var(--accent-text);
  background: rgba(183, 217, 143, 0.14);
  border: 1px solid var(--accent-ring);
}
/* Le fil qui relie les étapes. */
.fsteps li:not(:last-child)::after {
  content: "";
  position: absolute;
  left: 13.5px;
  top: 31px;
  bottom: -13px;
  width: 1px;
  background: rgba(183, 217, 143, 0.35);
  transform-origin: 50% 0;
}
.fsteps p { padding-top: 3px; font-size: 15px; line-height: 1.5; color: var(--text-2); }
.fcard--dark .btn { align-self: flex-start; margin-top: auto; }

/* La feuille qui sort de l'imprimante : celle de l'application
   (PrintWeek.tsx), en petit — jours en lignes, une colonne par
   personne, le matin en haut et l'après-midi en bas de la case, la
   journée continue sur la diagonale, « Repos » hachuré, « Congé »
   quadrillé, les titres grisés. */
.fcard__art--print { height: 318px; align-content: start; }
.prt { position: relative; height: 318px; }
.prt__slot {
  position: absolute;
  z-index: 2;
  top: 18px;
  left: 4%;
  right: 4%;
  height: 14px;
  border-radius: 8px;
  background: linear-gradient(180deg, #2f3427, #14170d);
  box-shadow: 0 6px 14px rgba(20, 24, 12, 0.20);
}
.prt__slot::after {
  content: "";
  position: absolute;
  left: 4%;
  right: 4%;
  bottom: 3px;
  height: 2px;
  border-radius: 1px;
  background: #050604;
}
/* La sortie rogne la feuille au ras de la fente : elle en sort. */
.prt__out { position: absolute; z-index: 1; top: 29px; left: 4%; right: 4%; bottom: 0; overflow: hidden; padding: 0 4% 20px; }
.prt__sheet {
  padding: 12px 12px 7px;
  background: #ffffff;
  color: #16190e;
  border: 1px solid rgba(20, 24, 12, 0.06);
  box-shadow: 0 10px 24px rgba(20, 24, 12, 0.14);
}
.prt__head { display: flex; align-items: flex-end; justify-content: space-between; gap: 10px; margin-bottom: 8px; }
.prt__head b { display: block; font-size: 10px; font-weight: 700; letter-spacing: -0.01em; line-height: 1.2; }
.prt__head small { display: block; font-size: 6.5px; line-height: 1.3; color: #6b6e64; }
.prt__wk { text-align: right; }
.prt__table { width: 100%; border-collapse: collapse; table-layout: fixed; }
.prt__table th,
.prt__table td { border: 1px solid rgba(22, 25, 14, 0.78); }
.prt__table thead th { padding: 3px 0; font-size: 7.5px; font-weight: 600; text-align: center; background: #f0f0ec; }
.prt__table thead .prt__corner { border: 0; background: none; }
.prt__table tbody th {
  width: 21%;
  padding: 3px 6px;
  font-size: 7.5px;
  font-weight: 600;
  line-height: 1.2;
  text-align: left;
  background: #f0f0ec;
}
.prt__table tbody th small { display: block; font-size: 6px; font-weight: 400; color: #6b6e64; }
.prt__table td { position: relative; height: 33px; padding: 0; font-size: 7px; font-weight: 600; white-space: nowrap; }
.prt__am { position: absolute; left: 9%; top: 17%; }
.prt__pm { position: absolute; right: 9%; bottom: 17%; }
.prt__cont > span { position: absolute; }
.prt__cont > span:first-child { left: 13%; top: 13%; }
.prt__cont > span:last-child { right: 13%; bottom: 13%; }
/* Le trait de la diagonale reste au milieu, à distance des deux heures :
   au téléphone, les cases sont étroites. */
.prt__cont i {
  position: absolute;
  left: 38%;
  right: 38%;
  top: 50%;
  height: 1px;
  background: #16190e;
  transform: rotate(24deg);
}
.prt__rest { background: repeating-linear-gradient(135deg, rgba(22, 25, 14, 0.28) 0 0.75px, rgba(22, 25, 14, 0) 0.75px 4.5px); }
.prt__leave {
  background:
    repeating-linear-gradient(135deg, rgba(22, 25, 14, 0.26) 0 0.75px, rgba(22, 25, 14, 0) 0.75px 4.5px),
    repeating-linear-gradient(45deg, rgba(22, 25, 14, 0.26) 0 0.75px, rgba(22, 25, 14, 0) 0.75px 4.5px);
}
.prt__rest em,
.prt__leave em {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  padding: 1px 3px;
  font-size: 6.5px;
  font-style: normal;
  font-weight: 500;
  color: #6b6e64;
  background: #ffffff;
}
.prt__foot { margin-top: 5px; text-align: right; font-size: 6px; color: #6b6e64; }
.prt__foot b { color: #16190e; font-weight: 600; }

/* L'agenda du téléphone : la semaine de services, et celui qui change
   après une nouvelle publication. */
.fcard__art--agenda { justify-items: center; height: 318px; }
.agd {
  width: min(84%, 340px);
  padding: 14px 16px 6px;
  border-radius: 20px;
  background: #ffffff;
  color: #16190e;
  border: 1px solid rgba(20, 24, 12, 0.06);
  box-shadow: 0 18px 40px rgba(20, 24, 12, 0.14), 0 2px 6px rgba(20, 24, 12, 0.08);
}
.agd__head { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 6px; }
.agd__head b { font-family: var(--font-display); font-size: 16px; font-weight: 600; letter-spacing: -0.02em; }
.agd__sync {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 3px 9px 3px 7px;
  border-radius: 100px;
  font-size: 10.5px;
  font-weight: 600;
  color: #4F6B2E;
  background: rgba(168, 205, 116, 0.24);
}
.agd__sync svg { width: 12px; height: 12px; }
.agd__list { list-style: none; }
.agd__list li { display: flex; align-items: center; gap: 12px; padding: 4px 0; border-top: 1px solid rgba(20, 24, 12, 0.07); }
.agd__day { display: flex; flex-direction: column; align-items: center; width: 32px; flex-shrink: 0; font-size: 9.5px; line-height: 1.15; color: #6b6e64; }
.agd__day b { font-size: 14px; font-weight: 600; color: #16190e; }
.agd__ev {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 4px 10px 4px 12px;
  border-radius: 9px;
  font-size: 11.5px;
  font-weight: 600;
  background: rgba(168, 205, 116, 0.20);
}
.agd__t { display: grid; justify-items: end; font-size: 10px; line-height: 1.2; font-variant-numeric: tabular-nums; }
.agd__t small { font-size: 10px; font-weight: 500; color: #6b6e64; }
.agd__old, .agd__new { grid-area: 1 / 1; }
.agd__t small { grid-area: 2 / 1; }
.agd__old { opacity: 0; }

/* La semaine type, du lundi au vendredi. */
.tpl { padding: 12px 12px 10px; border-radius: 14px; background: rgba(0, 0, 0, 0.22); }
.tpl__title { margin: 0 0 8px 2px; font-size: 11.5px; font-weight: 600; color: rgba(255, 255, 255, 0.70); }
.tpl__table { width: 100%; border-collapse: separate; border-spacing: 4px; table-layout: fixed; margin: -4px; width: calc(100% + 8px); }
.tpl__table thead th { font-size: 9.5px; font-weight: 600; text-align: center; color: rgba(255, 255, 255, 0.55); }
.tpl__table tbody th { width: 15%; font-size: 11px; font-weight: 600; text-align: left; color: rgba(255, 255, 255, 0.85); }
/* L'équipe importée (11 octobre 2026) : la fonction prend la place qu'il lui faut. */
.tpl--team .tpl__table thead th:first-child { width: 17%; }
.tpl--team .tpl__table thead th:nth-child(2) { width: 37%; }
.tpl__table td {
  height: 34px;
  padding: 0 2px;
  border-radius: 8px;
  text-align: center;
  font-size: 9.5px;
  font-weight: 600;
  line-height: 1.15;
  color: rgba(255, 255, 255, 0.90);
  background: rgba(183, 217, 143, 0.17);
}
.tpl__table td.tpl__off {
  color: rgba(255, 255, 255, 0.45);
  font-weight: 500;
  background: repeating-linear-gradient(135deg, rgba(255, 255, 255, 0.08) 0 1px, rgba(255, 255, 255, 0) 1px 5px);
}

@media (max-width: 860px) {
  .files__grid { grid-template-columns: 1fr; max-width: 560px; }
  .fcard__copy { padding: 24px 24px 28px; }
  .fcard__art--dark { padding: 18px 14px 0; }
}
/* Au téléphone, la feuille garde trois personnes : à quatre, la
   diagonale d'une journée continue passait sur ses heures. */
@media (max-width: 520px) {
  .prt__table tr > :nth-child(5) { display: none; }
}

/* -------- L'entrée des scènes (seulement `is-armed`, posé par le script) -------- */
.files.is-armed .csv__table tbody tr,
.files.is-armed .csv__rules,
.files.is-armed .csv__hi::after,
.files.is-armed .fsteps li,
.files.is-armed .fsteps li::after,
.files.is-armed .prt__sheet,
.files.is-armed .prt__table tbody tr,
.files.is-armed .prt__foot,
.files.is-armed .agd,
.files.is-armed .agd__list li,
.files.is-armed .agd__sync,
.files.is-armed .agd__old,
.files.is-armed .agd__new,
.files.is-armed .imp__file,
.files.is-armed .imp__rost,
.files.is-armed .tpl__table td span,
.files.is-armed .tpl__table td {
  transition: opacity 0.5s var(--ease-out), transform 0.6s var(--ease-out);
}
/* Le tableur : les lignes se remplissent l'une après l'autre, puis la
   cellule des heures supplémentaires est choisie, puis les règles. */
.files.is-armed .fcard:not(.is-in) .csv__table tbody tr { opacity: 0; transform: translateX(-8px); }
.files.is-armed .csv__table tbody tr { transition-delay: calc(0.3s + var(--i) * 0.14s); }
.files.is-armed .fcard:not(.is-in) .csv__hi::after { opacity: 0; transform: scale(1.25); }
.files.is-armed .csv__hi::after { transition-delay: 1.1s; transition-timing-function: var(--spring); }
.files.is-armed .fcard:not(.is-in) .csv__rules { opacity: 0; }
.files.is-armed .csv__rules { transition-delay: 1.3s; }
/* La reprise : le fichier, puis Rost, puis les étapes et leur fil. */
.files.is-armed .fcard:not(.is-in) .imp__file { opacity: 0; transform: translateX(-14px); }
.files.is-armed .fcard:not(.is-in) .imp__rost { opacity: 0; transform: scale(0.7); }
.files.is-armed .imp__rost { transition-delay: 0.25s; transition-timing-function: var(--spring); }
.files.is-armed .fcard:not(.is-in) .imp__line i { opacity: 0; animation-play-state: paused; }
.files.is-armed .fcard:not(.is-now) .imp__line i { animation-play-state: paused; }
.files.is-armed .fcard:not(.is-in) .tpl__table td { background-color: rgba(183, 217, 143, 0.04); }
.files.is-armed .fcard:not(.is-in) .tpl__table td.tpl__off { opacity: 0.3; }
.files.is-armed .fcard:not(.is-in) .tpl__table td span { opacity: 0; transform: translateY(5px); }
.files.is-armed .tpl__table td,
.files.is-armed .tpl__table td span { transition-delay: calc(0.9s + var(--i) * 0.09s); }
.files.is-armed .tpl__table td { transition-property: background-color, opacity; }
.files.is-armed .fcard:not(.is-in) .fsteps li { opacity: 0; transform: translateY(10px); }
.files.is-armed .fsteps li { transition-delay: calc(0.35s + var(--i) * 0.28s); }
.files.is-armed .fcard:not(.is-in) .fsteps li::after { transform: scaleY(0); }
.files.is-armed .fsteps li::after { transition: transform 0.4s var(--ease-out); transition-delay: calc(0.6s + var(--i) * 0.28s); }
/* L'impression : la feuille sort de la fente, puis les jours s'impriment. */
.files.is-armed .fcard:not(.is-in) .prt__sheet { transform: translateY(-104%); }
.files.is-armed .prt__sheet { transition: transform 1.25s cubic-bezier(0.3, 0.7, 0.2, 1) 0.15s; }
.files.is-armed .fcard:not(.is-in) .prt__table tbody tr,
.files.is-armed .fcard:not(.is-in) .prt__foot { opacity: 0; }
.files.is-armed .prt__table tbody tr { transition-delay: calc(0.95s + var(--i) * 0.11s); }
.files.is-armed .prt__foot { transition-delay: 1.7s; }
/* L'agenda : les services arrivent, puis une publication change jeudi. */
.files.is-armed .fcard:not(.is-in) .agd { opacity: 0; transform: translateY(16px) scale(0.98); }
.files.is-armed .fcard:not(.is-in) .agd__list li { opacity: 0; transform: translateY(8px); }
.files.is-armed .agd__list li { transition-delay: calc(0.3s + var(--i) * 0.12s); }
.files.is-armed .fcard:not(.is-in) .agd__sync { opacity: 0; transform: scale(0.85); }
.files.is-armed .agd__sync { transition-delay: 1.75s; transition-timing-function: var(--spring); }
.files.is-armed .fcard.is-in .agd__sync svg { animation: agd-spin 0.9s var(--ease-out) 1.75s 1 both; }
@keyframes agd-spin { from { transform: rotate(-180deg); } to { transform: rotate(180deg); } }
.files.is-armed .fcard:not(.is-in) .agd__old { opacity: 1; }
.files.is-armed .fcard:not(.is-in) .agd__new { opacity: 0; transform: translateY(6px); }
.files.is-armed .agd__old { transition-delay: 1.9s; }
.files.is-armed .fcard.is-in .agd__old { opacity: 0; transform: translateY(-6px); }
.files.is-armed .agd__new { transition-delay: 1.95s; }
.files.is-armed .fcard.is-in .agd__changed .agd__ev { animation: agd-flash 1.2s ease 1.9s 1 both; }
@keyframes agd-flash {
  0%, 100% { background: rgba(168, 205, 116, 0.20); }
  30% { background: rgba(168, 205, 116, 0.55); }
}
@media (prefers-reduced-motion: reduce) {
  .imp__line i { animation: none; left: 50%; }
}

/* Installation */
.install { padding: 120px 0; }
/* Les trois étapes d'un côté, la démonstration de l'autre : on lit le
   geste et on le voit dans le même regard. */
.install__row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 300px;
  gap: 56px;
  align-items: center;
  max-width: 1000px;
  margin: 0 auto;
}
.install__steps {
  list-style: none;
  display: grid;
  gap: 16px;
}
/* Le cadre prend la SILHOUETTE du téléphone filmé, et rien d'autre : la
   vidéo le montre posé sur un fond noir, et ce rectangle noir se voyait
   autour (Matteo). Le téléphone y occupe 41–647 × 41–1238 sur 688 ×
   1280, coins de 82 : mesuré image par image, il ne bouge pas. On
   agrandit donc la vidéo d'autant et on ne garde que ce rectangle
   arrondi. */
.install__demo {
  position: relative;
  margin: 0;
  aspect-ratio: 607 / 1198;
  border-radius: 13.51% / 6.845%;
  overflow: hidden;
  background: #0b0e09;
  box-shadow: 0 30px 70px var(--shadow-media);
}
.install__demo video {
  position: absolute;
  left: -6.755%;
  top: -3.422%;
  width: 113.344%;
  height: 106.845%;
  object-fit: cover;
  display: block;
}
@media (max-width: 900px) {
  .install__row { grid-template-columns: 1fr; gap: 34px; justify-items: center; }
  /* La taille du téléphone de la génération. */
  .install__demo { width: min(81vw, calc((100vh - 236px) * 0.4748)); width: min(81vw, calc((100dvh - 236px) * 0.4748)); }
}
.step {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 28px 24px;
}
.step__num {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  border-radius: 50%;
  background: rgba(183, 217, 143, 0.14);
  border: 1px solid var(--accent-ring);
  color: var(--accent-text);
  font-weight: 600;
  font-size: 15px;
  margin-bottom: 16px;
}
.step h4 { font-size: 16px; letter-spacing: -0.01em; margin-bottom: 6px; }
.step p { font-size: 14px; color: var(--text-3); }

/* Accès */
/* La section d'accès occupe tout l'écran : le titre et les deux cartes
   centrés dans sa hauteur (demande de Matteo, 28 septembre 2026). */
.access {
  min-height: 100vh;
  min-height: 100svh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: 90px 0 60px;
}
.access .access-card { padding: 48px 36px; }
/* Les cartes s'allongent jusqu'à remplir l'écran, sous le titre. */
@media (min-width: 721px) {
  .access .access-card { min-height: calc(100svh - 330px); }
}
.access .access-card h3 { margin-bottom: 18px; }
.access .access-card ul { margin-bottom: 36px; }
.access .access-card li { margin-bottom: 14px; }
.access__cards {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 20px;
  max-width: 860px;
  margin: 40px auto 0;
}
.access-card {
  background: var(--card-strong);
  border: 1px solid var(--border);
  border-radius: 24px;
  padding: 34px 30px;
  display: flex;
  flex-direction: column;
  box-shadow: 0 24px 60px rgba(0, 0, 0, 0.30);
}
.access-card--pilot {
  background: linear-gradient(180deg, rgba(183, 217, 143, 0.10), rgba(183, 217, 143, 0.03));
  border-color: var(--accent-ring);
}
:root[data-theme="light"] .access-card {
  background: #ffffff;
  box-shadow: 0 24px 60px rgba(20, 24, 12, 0.12);
}
/* En clair, les rôles s'inversent : la carte du programme pilote est
   NEUTRE, blanche comme le papier, et c'est celle de l'abonnement qui
   porte le vert — exactement la carte verte du thème sombre, texte clair
   compris (demande de Matteo, 28 septembre 2026). Un premier essai
   mettait le pilote en olive fondu dans le blanc : retiré. */
:root[data-theme="light"] .access-card--pilot {
  background: #ffffff;
  border-color: var(--border);
  /* Une ombre plus franche : blanche sur le blanc, la carte s'y perdait. */
  box-shadow: 0 30px 70px rgba(20, 24, 12, 0.22), 0 8px 22px rgba(20, 24, 12, 0.10);
}
:root[data-theme="light"] .access-card:not(.access-card--pilot) {
  --text: #ffffff;
  --text-2: rgba(255, 255, 255, 0.75);
  --text-3: rgba(255, 255, 255, 0.55);
  --accent-text: #B7D98F;
  --btn-fill: #B7D98F;
  --accent-ring: rgba(183, 217, 143, 0.35);
  --border: rgba(255, 255, 255, 0.08);
  --card-strong: rgba(255, 255, 255, 0.07);
  --glass-bg: rgba(255, 255, 255, 0.06);
  --glass-border: rgba(255, 255, 255, 0.14);
  --glass-text: rgba(255, 255, 255, 0.85);
  background: linear-gradient(180deg, rgba(183, 217, 143, 0.10), rgba(183, 217, 143, 0.03)), #13170C;
  border-color: rgba(183, 217, 143, 0.35);
  color: var(--text);
}
.access-card__tag { font-size: 13px; color: var(--text-3); margin-bottom: 10px; }
.access-card h3 {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 23px;
  letter-spacing: -0.02em;
  margin-bottom: 14px;
}
/* Le prix est le sujet de la carte : il se lit en premier. */
.access-card__price { display: flex; align-items: baseline; gap: 10px; margin-bottom: 24px; flex-wrap: wrap; }
.access-card__amount {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(34px, 3.4vw, 42px);
  letter-spacing: -0.03em;
  line-height: 1;
  color: var(--text);
}
.access-card__per { font-size: 15px; font-weight: 500; color: var(--accent-text); }
.access-card ul { list-style: none; margin-bottom: 28px; flex: 1; }
.access-card li {
  position: relative;
  padding-left: 22px;
  font-size: 15px;
  color: var(--text-2);
  margin-bottom: 10px;
}
.access-card li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 9px;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--accent-dim);
}
/* Au téléphone, le PILOTE d'abord (audit 7.5) : « Demander un accès »
   descend ici, et la carte qu'il cherche était la seconde, hors de l'écran
   sous celle de l'abonnement. */
@media (max-width: 720px) {
  .access__cards { grid-template-columns: 1fr; }
  .access__cards .access-card--pilot { order: -1; }
}

/* L'adresse sous les boutons d'e-mail (audit 7.5) : un `mailto:` n'ouvre
   rien chez qui lit ses e-mails dans le navigateur. Le bouton de copie
   n'existe qu'avec JavaScript. */
.mail-copy {
  align-self: center;
  margin-top: 14px;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  gap: 2px 5px;
  font-size: 13px;
  color: var(--text-3);
  text-align: center;
}
/* L'adresse et son bouton ne se séparent pas : c'est « Ou écrivez à » qui
   passe à la ligne au besoin. */
.mail-copy__pair { display: inline-flex; align-items: center; gap: 8px; white-space: nowrap; }
.mail-copy__address { color: var(--text-2); font-weight: 500; user-select: all; -webkit-user-select: all; }
/* L'adresse est un LIEN : un clic ouvre la messagerie (Matteo, 11 octobre
   2026, à la place de l'icône « copier »). Vert, appuyé, jamais souligné. */
a.mail-copy__address { color: var(--accent-text); font-weight: 600; text-decoration: none; user-select: auto; -webkit-user-select: auto; transition: opacity 0.16s ease; }
a.mail-copy__address:hover { opacity: 0.75; }
a.mail-copy__address:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; border-radius: 4px; }
/* « Copier » est une ICÔNE (audit 7.5, 11 octobre 2026) : deux feuillets
   au trait, qui deviennent une coche un instant après la copie. Le dessin
   est un rond de 30 px (`::before`), la zone de toucher le bouton entier,
   44 × 44 ; ses marges négatives la reprennent, la ligne ne grandit pas. */
.mail-copy__btn {
  position: relative;
  flex: 0 0 auto;
  width: 44px;
  height: 44px;
  margin: -12px -7px -12px -5px;
  padding: 0;
  border: 0;
  background: none;
  color: var(--text-2);
  cursor: pointer;
  transition: color 0.2s var(--ease-out);
}
.mail-copy__btn::before {
  content: "";
  position: absolute;
  inset: 7px;
  border-radius: 50%;
  background: var(--card);
  box-shadow: inset 0 0 0 1px var(--border);
  transition: background 0.2s var(--ease-out), transform 0.2s var(--ease-out);
}
.mail-copy__btn:hover { color: var(--text); }
.mail-copy__btn:hover::before { background: var(--card-strong); }
.mail-copy__btn:active::before { transform: scale(0.92); }
.mail-copy__btn:focus-visible { outline: none; }
.mail-copy__btn:focus-visible::before { outline: 2px solid var(--accent); outline-offset: 2px; }
.mail-copy__ico {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 16px;
  height: 16px;
  margin: -8px 0 0 -8px;
  transition: opacity 0.22s var(--ease-out), transform 0.32s var(--spring);
}
.mail-copy__ico--done { opacity: 0; transform: scale(0.5); }
.mail-copy__btn.is-done { color: var(--accent-text); }
.mail-copy__btn.is-done .mail-copy__ico--copy { opacity: 0; transform: scale(0.5); }
.mail-copy__btn.is-done .mail-copy__ico--done { opacity: 1; transform: scale(1); }
@media (prefers-reduced-motion: reduce) { .mail-copy__ico { transition: none; } }
html:not(.js) .mail-copy__btn { display: none; }
/* La carte du pilote est BLANCHE en clair : le voile de carte y est gris. */
:root[data-theme="light"] .access-card--pilot .mail-copy__btn::before { background-color: rgba(20, 24, 12, 0.05); }
:root[data-theme="light"] .access-card--pilot .mail-copy__btn:hover::before { background-color: rgba(20, 24, 12, 0.09); }

/* Le bouton lecture (audit 7.4) : un rond discret au milieu de la vidéo,
   en mouvement réduit, ou quand la lecture automatique est refusée
   (l'iPhone en économie d'énergie). Il s'efface pendant la lecture. */
.vplay { display: none; }
/* Sous le milieu : les affiches portent le titre du montage en leur centre. */
.has-play > .vplay {
  position: absolute;
  left: 50%;
  top: 66%;
  z-index: 2;
  width: 54px;
  height: 54px;
  margin: -27px 0 0 -27px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  border: 1px solid rgba(255, 255, 255, 0.22);
  background: rgba(19, 23, 12, 0.55);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  color: #ffffff;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.25);
  cursor: pointer;
  transition: opacity 0.25s var(--ease-out), transform 0.2s var(--ease-out);
}
/* Le triangle CENTRÉ À L'ŒIL (audit 7.4, 11 octobre 2026). Centré sur sa
   boîte, un triangle qui pointe à droite paraît décalé à gauche : sa masse
   est du côté de sa base. Centré sur sa masse (son centre de gravité), il
   paraît décalé à droite, sa pointe file. L'œil le place entre les deux :
   la boîte du triangle 1,4 px à droite du centre du rond, sa masse 0,4 px à
   gauche (tracé dans site.js, `playButton`). Avant, une marge de 3 px
   s'ajoutait à un tracé déjà décalé : la boîte tombait 3,5 px à droite. */
.has-play > .vplay svg { width: 24px; height: 24px; }
.has-play > .vplay:hover { transform: scale(1.06); }
.has-play.is-playing > .vplay { opacity: 0; pointer-events: none; }

/* Questions — accordéon */
.faq { padding: 60px 0 120px; }
.faq .section-title { margin-bottom: 48px; }
.faq__item {
  border-bottom: 1px solid var(--border);
}
.faq__item summary {
  list-style: none;
  cursor: pointer;
  padding: 22px 40px 22px 4px;
  font-weight: 600;
  font-size: 16px;
  letter-spacing: -0.01em;
  position: relative;
  transition: color 0.2s var(--ease-out);
}
.faq__item summary::-webkit-details-marker { display: none; }
.faq__item summary::after {
  content: "+";
  position: absolute;
  right: 8px;
  top: 50%;
  transform: translateY(-50%);
  font-size: 22px;
  font-weight: 400;
  color: var(--text-3);
  transition: transform 0.3s var(--ease-out);
}
.faq__item[open] summary::after { transform: translateY(-50%) rotate(45deg); color: var(--accent-text); }
.faq__item summary:hover { color: var(--accent-text); }
.faq__body { overflow: hidden; }
.faq__body p {
  padding: 0 4px 24px;
  color: var(--text-2);
  font-size: 15px;
  max-width: 68ch;
}

/* Questions — des BULLES DE SMS qui flottent dans l'espace (demande de
   Matteo). Toucher une bulle la fait GROSSIR sur place et passer devant
   un voile qui assombrit la page ; la réponse arrive dessous comme un
   message reçu : trois points, puis la bulle. La liste ci-dessus reste la
   source des questions et le repli sans JavaScript ou en mouvement réduit
   (site.js, `initFaqChat`). */
.faq.has-chat .faq__list { display: none; }
.faq.has-chat .container--narrow { width: min(1100px, calc(100% - 48px)); }
.faq.is-talking { position: relative; z-index: 45; }
.qs { position: relative; height: 740px; margin-top: -8px; }
/* La matière est celle des panneaux de l'installation (« Ouvrez
   getrost.fr ») : le voile de carte et son filet, rien d'autre — Matteo,
   deux essais plus colorés écartés. */
.bub {
  position: relative;
  display: inline-block;
  padding: 12px 17px 13px;
  border-radius: 22px;
  font-size: 15px;
  line-height: 1.45;
  letter-spacing: -0.005em;
  text-align: left;
  color: var(--text);
  background: var(--card);
  border: 1px solid var(--border);
}
.bub--q { font-weight: 600; border-bottom-right-radius: 6px; }
.bub--a { color: var(--text-2); border-bottom-left-radius: 6px; }
/* Devant le voile, la bulle et sa réponse deviennent OPAQUES : un voile
   de carte sur un fond assombri serait sombre et laisserait voir les
   bulles de derrière. */
.qw.is-picked .bub {
  background: linear-gradient(var(--card-strong), var(--card-strong)), var(--bg);
  box-shadow: 0 18px 44px rgba(0, 0, 0, 0.35);
}
:root[data-theme="light"] .qw.is-picked .bub { box-shadow: 0 16px 40px rgba(20, 24, 12, 0.16); }

/* Chaque bulle vit dans un porteur qui flotte (`--x`, `--y`, et une
   PROFONDEUR `--z` qui la rend un peu plus pâle au fond — jamais floue).
   site.js le fait dériver et suivre la souris. */
.qw {
  position: absolute;
  left: var(--x);
  top: var(--y);
  width: max-content;
  max-width: min(310px, 74vw);
  transform: translate(-50%, -50%);
  opacity: 0;
  transition: opacity 0.6s var(--ease-out);
}
.qs.is-in .qw { opacity: var(--o, 1); }
.qs.is-open .qw.is-picked { opacity: 1; z-index: 3; }
.qb {
  display: block;
  border: 0;
  padding: 0;
  background: none;
  font: inherit;
  cursor: pointer;
  transition: transform 0.4s var(--spring);
  -webkit-tap-highlight-color: transparent;
}
@media (hover: hover) { .qs:not(.is-open) .qb:hover { transform: scale(1.04); } }
.qw.is-picked .qb { transform: scale(1.14); transform-origin: right center; }
/* La bulle ouverte GLISSE jusqu'au milieu (site.js), et en revient. */
.qw.is-picked, .qw.is-returning { transition: opacity 0.6s var(--ease-out), transform 0.6s cubic-bezier(0.22, 1, 0.36, 1); }
.qb:focus-visible { outline: none; }
.qb:focus-visible .bub { outline: 2px solid var(--accent-ring); outline-offset: 3px; }

/* Le voile : tout le reste s'assombrit, comme pendant la mise en valeur
   des vidéos. */
.qs__veil {
  position: fixed;
  inset: 0;
  z-index: 2;
  background: var(--spot);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.4s var(--ease-out);
}
.qs.is-open .qs__veil { opacity: 1; pointer-events: auto; }

/* La conversation, au milieu : la question à droite, la réponse dessous
   à gauche, comme dans une messagerie. site.js calcule sa place. */
.qs__answer {
  position: absolute;
  top: var(--qa-top, 100%);
  left: var(--qa-left, 0px);
  width: var(--qa-w, 460px);
  display: flex;
  justify-content: flex-start;
}
.qs__close {
  position: absolute;
  right: -14px;
  top: -16px;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--text);
  background: linear-gradient(var(--card-strong), var(--card-strong)), var(--bg);
  border: 1px solid var(--border);
  cursor: pointer;
  z-index: 1;
  opacity: 0;
  transform: scale(0.6);
  transition: opacity 0.25s var(--ease-out) 0.15s, transform 0.3s var(--spring) 0.15s;
}
.qs__close svg { width: 14px; height: 14px; }
.qw.is-picked .qs__close { opacity: 1; transform: none; }
/* Les trois points de « Rost écrit… ». */
.bub--typing { padding: 15px 17px; display: inline-flex; gap: 5px; }
.bub--typing i {
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--text); opacity: 0.35;
  animation: qs-dot 1s infinite ease-in-out;
}
.bub--typing i:nth-child(2) { animation-delay: 0.15s; }
.bub--typing i:nth-child(3) { animation-delay: 0.3s; }
@keyframes qs-dot { 0%, 60%, 100% { transform: translateY(0); opacity: 0.35; } 30% { transform: translateY(-4px); opacity: 0.9; } }
.qs__hint {
  text-align: center;
  font-size: 14px;
  color: var(--text-3);
  margin-top: -18px;
  margin-bottom: 8px;
}

/* Appel final */
.final { padding: 140px 0 160px; text-align: center; position: relative; }
.final::before {
  content: "";
  position: absolute;
  left: 50%;
  bottom: -10vh;
  transform: translateX(-50%);
  width: 80vw;
  height: 50vh;
  pointer-events: none;
  background: radial-gradient(ellipse 60% 70% at 50% 100%, rgba(183, 217, 143, 0.12), transparent 70%);
}
.final__title {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(2.1rem, 5vw, 3rem);
  line-height: 1.06;
  letter-spacing: -0.03em;
  text-wrap: balance;
  margin-bottom: 36px;
}
.final__actions { display: flex; justify-content: center; gap: 14px; position: relative; }

/* ------------------------------------------------------------------ */
/* Pied de page — composition de getdroppy.app : une colonne qui parle */
/* à gauche, les liens en colonnes centrées à droite.                  */
/* ------------------------------------------------------------------ */
/* LE PIED DE PAGE À LA DROPPY (28 septembre 2026) : chez eux, des
   nuages descendent du haut sur un bleu profond, et le pied de page s'y
   écrit en clair. Ici, un bureau vu de haut sur un vert olive
   (`footer-objets.webp`, détourés) : les objets bordent le haut, le vert porte le
   texte. Le haut de l'image se fond dans la couleur de la page, blanc
   ou vert foncé ; le texte prend les jetons du thème sombre dans les
   deux thèmes. Il avait la couleur de la page depuis le 22 septembre.
   L'image COUVRE le pied de page (quelques pixels rognés sur les côtés
   à l'ordinateur) : posée à sa largeur, elle s'arrêtait avant le bas et
   laissait une bande plus sombre. */
.footer {
  position: relative;
  --text: #ffffff;
  --text-2: rgba(255, 255, 255, 0.78);
  --text-3: rgba(255, 255, 255, 0.62);
  --accent-text: #B7D98F;
  --btn-fill: #B7D98F;
  --accent-ring: rgba(183, 217, 143, 0.35);
  --card: rgba(255, 255, 255, 0.08);
  --border: rgba(255, 255, 255, 0.14);
  color: var(--text);
  /* Le texte remonte dans le bas de l'image, sous les objets, comme chez
     Droppy où il commence dans les derniers nuages : pas d'espace perdu. */
  padding-top: max(250px, 36vw);
}
/* L'image du pied de page (quatrième version, fournie par Matteo le 28
   septembre 2026) est déjà détourée : son haut est TRANSPARENT, le bord
   des objets fait la limite avec la page — comme les nuages de Droppy.
   Son bas se FOND dans le vert qui la prolonge sous le texte : le vert
   uni commence sous son dernier creux transparent (38 % de sa hauteur)
   et l'image s'efface sur son dernier quart par-dessus — la jonction
   se voyait (demande de Matteo). */
.footer { --foot-img-h: 55.9vw; background: none; }
/* En clair, derrière le haut transparent de l'image, un vert TRÈS pâle
   monte du blanc : il commence sous la dernière bulle des questions (le
   bas de leur section) et descend jusque sous les objets (demande de
   Matteo, 28 septembre 2026). En sombre, la page a déjà ce vert. */
:root[data-theme="light"] .faq,
:root[data-theme="light"] .legal-page main {
  background: linear-gradient(to bottom, transparent calc(100% - 120px), #eef3e1 100%);
}
:root[data-theme="light"] .footer {
  background: linear-gradient(to bottom, #eef3e1 0, #bccb97 calc(var(--foot-img-h) * 0.42));
}
.footer::before,
.footer::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  pointer-events: none;
}
.footer::before {
  top: calc(var(--foot-img-h) * 0.4);
  bottom: 0;
  background: #222914;
}
/* L'image n'est demandée qu'à l'approche du pied de page (`is-near`,
   site.js) : elle partait avec la page, tout en bas (audit 7.8). */
.footer::after {
  top: 0;
  height: var(--foot-img-h);
  background: center top / 100% auto no-repeat;
  -webkit-mask-image: linear-gradient(to bottom, #000 72%, transparent 100%);
  mask-image: linear-gradient(to bottom, #000 72%, transparent 100%);
}
.footer.is-near::after,
html:not(.js) .footer::after { background-image: url("../img/footer-objets.webp"); }
@media (max-width: 860px) {
  .footer { --foot-img-h: calc(max(100vw, 760px) * 0.559); }
  .footer::after { background-size: max(100%, 760px) auto; }
}
.footer .appearance__thumb { background: rgba(255, 255, 255, 0.16); box-shadow: 0 2px 8px rgba(0, 0, 0, 0.28); }
.footer > .container { position: relative; z-index: 1; width: min(1400px, calc(100% - 64px)); }
.footer__grid {
  display: grid;
  grid-template-columns: minmax(0, 1.2fr) minmax(0, 2.4fr);
  gap: clamp(40px, 6vw, 110px);
  padding: 60px 0 64px;
}
.footer__brand { margin-bottom: 22px; }
/* La colonne qui parle, centrée sur elle-même comme chez Droppy. */
@media (min-width: 861px) {
  .footer__about { display: flex; flex-direction: column; align-items: center; text-align: center; }
  .footer__line, .footer__text { margin-left: auto; margin-right: auto; }
}
/* Le logo signe le pied de page : à 30 pixels il se perdait à côté de
   la phrase en dessous, plus grande que lui. */
.footer__brand img { height: 76px; width: auto; }
.footer__line {
  font-family: var(--font-display);
  font-size: clamp(1.25rem, 2vw, 1.6rem);
  font-weight: 600;
  letter-spacing: -0.02em;
  line-height: 1.2;
  color: var(--text);
  margin-bottom: 14px;
  max-width: 20ch;
}
.footer__text {
  font-size: 14.5px;
  line-height: 1.55;
  color: var(--text-3);
  max-width: 38ch;
  margin-bottom: 26px;
}
.footer__cta { margin-bottom: 30px; }
.footer__copy { font-size: 13px; color: var(--text-3); }
/* La signature, comme le « Built with … by » de getdroppy.app. */
.footer__maker { margin-top: 8px; font-size: 13px; color: var(--text-2); }
/* L'apparence : un rail à la matière des bulles de questions, et une
   pastille ronde qui glisse sous le choix pris — le soleil plein à
   rayons pointus, la lune, et le demi-cercle d'« Auto » (celui
   d'Apple). */
.appearance {
  --opt: 34px;
  position: relative;
  display: inline-flex;
  margin-top: 18px;
  padding: 3px;
  border-radius: 100px;
  background: var(--card);
  border: 1px solid var(--border);
}
.appearance__thumb {
  position: absolute;
  top: 3px;
  left: 3px;
  width: var(--opt);
  height: var(--opt);
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.16);
  border: 1px solid rgba(255, 255, 255, 0.10);
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.28);
  transform: translateX(calc(var(--pick, 2) * var(--opt)));
  transition: transform 0.36s var(--ease-out);
}
.appearance__opt {
  position: relative;
  z-index: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--opt);
  height: var(--opt);
  border: 0;
  padding: 0;
  background: none;
  border-radius: 50%;
  color: var(--text-3);
  cursor: pointer;
  transition: color 0.2s var(--ease-out);
}
.appearance__opt svg { width: 17px; height: 17px; }
.appearance__opt:hover { color: var(--text-2); }
.appearance__opt[aria-checked="true"] { color: var(--text); }

.footer__cols {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 24px;
  padding-top: 6px;
}
.footer__col { display: flex; flex-direction: column; gap: 13px; text-align: center; }
.footer__col-title {
  font-size: 15px;
  font-weight: 600;
  color: var(--text);
  margin-bottom: 3px;
}
.footer__col a { font-size: 14.5px; color: var(--text-3); transition: color 0.2s var(--ease-out); }
.footer__col a:hover { color: var(--text); }

@media (max-width: 860px) {
  .footer__grid { grid-template-columns: 1fr; gap: 48px; padding: 64px 0 56px; }
  .footer__cols { gap: 18px; }
  .footer__col { text-align: left; }
}
@media (max-width: 520px) {
  .footer__cols { grid-template-columns: 1fr 1fr; gap: 32px 18px; }
}

/* Les ancres s'arrêtent sous la barre suspendue. */
section, header { scroll-margin-top: 90px; }

/* ------------------------------------------------------------------ */
/* Pages légales — la composition de getdroppy.app : une image en      */
/* tête, une étiquette, le titre et la date, puis une colonne étroite  */
/* aux sections numérotées (28 septembre 2026). L'image est le bureau  */
/* du haut de l'accueil, fondu vers le bas dans la couleur de la page. */
/* ------------------------------------------------------------------ */
.legal-hero {
  position: relative;
  z-index: 1;
  min-height: min(68vh, 640px);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 150px 24px 90px;
  overflow: clip;
  text-align: center;
}
.legal-hero__backdrop { height: 100%; }
/* Une page qui a SA photo (fournie par Matteo) : un vert profond qui se
   perd dans une brume blanche. Elle garde sa largeur (560 px au moins :
   sur téléphone, les feuillages des bords restent en partie visibles) et se pose
   EN BAS du premier écran, son blanc sur le bord bas ; au-dessus, son
   vert (#2b3118, uni sur toute la largeur) prolonge l'écran jusqu'en
   haut. Le texte posé dessus garde les jetons clairs. */
.legal-hero--full {
  --legal-img-h: calc(max(100vw, 560px) * 0.4668);
  min-height: 100svh;
  /* Plus de marge en bas qu'en haut : le titre monte au-dessus du milieu. */
  padding: 70px 24px 26vh;
  --text: #ffffff;
  background: linear-gradient(to bottom,
    #2b3118 0, #2b3118 calc(100% - var(--legal-img-h) * 0.55),
    transparent calc(100% - var(--legal-img-h) * 0.55));
}
.legal-hero__photo {
  position: absolute;
  /* Descendue de près d'un cinquième de sa hauteur : le bord de l'écran
     tombe juste où son blanc devient uni. Ce blanc a été porté au blanc
     pur de la page dans le fichier : aucun fondu n'est posé dessus. */
  inset: auto 0 calc(var(--legal-img-h) * -0.19) 0;
  height: var(--legal-img-h);
  z-index: -1;
  pointer-events: none;
  background: center bottom / max(100%, 560px) auto no-repeat;
  /* Son haut se fond dans le vert uni qui prolonge l'écran. */
  -webkit-mask-image: linear-gradient(to bottom, transparent 0, #000 14%);
  mask-image: linear-gradient(to bottom, transparent 0, #000 14%);
}
/* En sombre, la brume se dissout plus tôt dans le vert de la page : son
   blanc ferait une bande claire au bas de l'écran. */
:root:not([data-theme="light"]) .legal-hero__photo {
  -webkit-mask-image: linear-gradient(to bottom, transparent 0, #000 14%, #000 38%, transparent 74%);
  mask-image: linear-gradient(to bottom, transparent 0, #000 14%, #000 38%, transparent 74%);
}
.legal-hero__inner { position: relative; max-width: 820px; }
.legal-hero__title {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(2.3rem, 5vw, 3.6rem);
  letter-spacing: -0.04em;
  line-height: 1.05;
  color: var(--text);
  text-wrap: balance;
}
.legal-hero__lede {
  margin-top: 16px;
  font-size: clamp(1rem, 1.5vw, 1.15rem);
  color: var(--text);
  text-wrap: balance;
}
.legal-doc {
  position: relative;
  z-index: 1;
  max-width: 720px;
  margin: 0 auto;
  padding: 24px 24px 130px;
  font-size: 16px;
  line-height: 1.7;
  color: var(--text-2);
}
/* Sous une photo plein écran, le texte prend du recul sur le bord des objets. */
.legal-hero--full + .legal-doc { padding-top: clamp(64px, 9vw, 110px); }
.legal-doc h2 {
  font-family: var(--font-display);
  font-size: 20px;
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--text);
  margin: 44px 0 12px;
}
.legal-doc h2:first-child { margin-top: 0; }
.legal-doc p + p { margin-top: 12px; }
.legal-doc ul { list-style: none; margin: 4px 0 0; }
.legal-doc li { position: relative; padding-left: 22px; margin-bottom: 10px; }
.legal-doc li::before {
  content: "";
  position: absolute;
  left: 2px;
  top: 11px;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--accent-dim);
}
/* En vert, sans soulignement : aucun lien du site n'est souligné (Matteo). */
.legal-doc a { color: var(--accent-text); font-weight: 500; }
/* La date de la version, au pied du texte, en discret (28 octobre 2026). */
.legal-doc .legal-updated { margin-top: 40px; font-size: 14px; color: var(--text-3); }
/* La page d'erreur (`app/global-not-found.tsx`) : la tête des
   pages légales, puis deux chemins pour repartir. */
.notfound { text-align: center; }
.notfound__actions { display: flex; justify-content: center; flex-wrap: wrap; gap: 12px; margin-top: 30px; }
/* Sur le vert sombre de la tête : le vert plein des fonds sombres, et le
   verre clair (règle du vert plein). */
.legal-hero .notfound__actions {
  --btn-fill: #B7D98F;
  --glass-bg: rgba(255, 255, 255, 0.06);
  --glass-border: rgba(255, 255, 255, 0.14);
  --glass-text: rgba(255, 255, 255, 0.85);
  --card-strong: rgba(255, 255, 255, 0.10);
}

/* Ce que seul l'éditeur sait : surligné tant que ce n'est pas rempli. */
.legal-todo {
  background: rgba(255, 184, 0, 0.22);
  color: var(--text);
  border-radius: 5px;
  padding: 1px 6px;
  font-weight: 600;
}

/* ------------------------------------------------------------------ */
/* La page de l'abonnement (29 septembre 2026) — la tête des pages     */
/* légales, puis le temps gagné, les offres, ce qui est compris,       */
/* comment ça se passe et les questions sur le prix. Ses sections      */
/* sont dans components/abonnement/ (Next, 25 octobre 2026).           */
/* ------------------------------------------------------------------ */
/* Le petit lien sous le bouton des cartes d'accès de l'accueil. */
.access-card__more {
  align-self: center;
  margin-top: 16px;
  font-size: 13.5px;
  font-weight: 500;
  color: var(--text-3);
  transition: color 0.2s var(--ease-out);
}
.access-card__more:hover { color: var(--text); }

/* Les liens du texte : en vert, sans soulignement (demande de Matteo). */
.price-page main a:not(.btn) { color: var(--accent-text); font-weight: 500; }

/* Les panneaux blancs de la page : la carte blanche du pilote. */
.gain__card,
.plan-group,
.included__item {
  background: var(--card-strong);
  border: 1px solid var(--border);
  border-radius: 24px;
}
:root[data-theme="light"] .gain__card,
:root[data-theme="light"] .plan-group {
  background: #ffffff;
  box-shadow: 0 30px 70px rgba(20, 24, 12, 0.14), 0 8px 22px rgba(20, 24, 12, 0.06);
}
:root[data-theme="light"] .included__item {
  background: #ffffff;
  box-shadow: 0 18px 44px rgba(20, 24, 12, 0.08);
}

/* Le temps gagné. */
.gain { padding: clamp(70px, 9vw, 110px) 0 50px; }
.gain .section-sub { margin-bottom: 40px; font-size: clamp(0.95rem, 1.6vw, 1.05rem); }
.gain__card { max-width: 900px; margin: 0 auto; padding: 38px 40px 34px; }
.gain__control { display: flex; flex-direction: column; align-items: center; gap: 6px; text-align: center; }
.gain__label { font-size: 15px; font-weight: 500; color: var(--text-3); }
.gain__count {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 56px;
  letter-spacing: -0.03em;
  line-height: 1;
  color: var(--text);
  font-variant-numeric: tabular-nums;
}
.gain__range {
  --p: 25%;
  -webkit-appearance: none;
  appearance: none;
  display: block;
  width: 100%;
  height: 8px;
  margin: 0;
  border-radius: 100px;
  /* « Le vert de la barre » (#1e2316, celui de la barre du haut et de la
     carte de l'abonnement), éclairé vers l'olive de ses nuages (#45502d).
     Le vert forêt des boutons de l'application a été essayé et retiré. */
  background:
    linear-gradient(90deg, #1e2316, #45502d) 0 0 / var(--p) 100% no-repeat,
    var(--card-strong);
  cursor: pointer;
}
/* La barre fait 8 px, mais on la saisit sur une bande de 40 autour
   d'elle ; le geste appartient au curseur : la page ne défile pas en le
   tirant. */
.gain__track { padding: 16px 0; margin: 6px 0 18px; cursor: pointer; touch-action: none; }
.gain__range.is-grabbing, .gain__track.is-grabbing { cursor: grabbing; }
.gain__range:focus-visible { outline: 2px solid var(--accent-ring); outline-offset: 6px; }
.gain__range::-webkit-slider-thumb {
  -webkit-appearance: none;
  transition: transform 0.18s var(--ease-out);
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: #ffffff;
  border: 1px solid rgba(20, 24, 12, 0.12);
  box-shadow: 0 4px 12px rgba(20, 24, 12, 0.22);
}
.gain__range.is-grabbing::-webkit-slider-thumb { transform: scale(1.12); }
.gain__range.is-grabbing::-moz-range-thumb { transform: scale(1.12); }
.gain__range::-moz-range-thumb {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: #ffffff;
  border: 1px solid rgba(20, 24, 12, 0.12);
  box-shadow: 0 4px 12px rgba(20, 24, 12, 0.22);
}
.gain__figures {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 20px;
  padding-bottom: 28px;
  border-bottom: 1px solid var(--border);
  text-align: center;
}
.gain__value {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(28px, 3.4vw, 40px);
  letter-spacing: -0.03em;
  line-height: 1.05;
  color: var(--text);
  font-variant-numeric: tabular-nums;
}
.gain__caption { margin-top: 8px; font-size: 14px; line-height: 1.45; color: var(--text-3); }
.gain__result {
  margin-top: 26px;
  text-align: center;
  font-family: var(--font-display);
  font-size: clamp(19px, 2.2vw, 24px);
  font-weight: 500;
  letter-spacing: -0.015em;
  color: var(--text);
}
.gain__result strong { font-weight: 700; color: var(--accent-text); }
.gain__note {
  max-width: 74ch;
  margin: 20px auto 0;
  text-align: center;
  font-size: 13px;
  line-height: 1.6;
  color: var(--text-3);
}
@media (max-width: 640px) {
  .gain__card { padding: 28px 22px 26px; }
  .gain__figures { grid-template-columns: 1fr; gap: 18px; text-align: center; }
}

/* Les offres. */
.plans { padding: 70px 0 60px; }
.plans .section-sub { margin-bottom: 44px; }
.plans__cards {
  display: grid;
  grid-template-columns: 1.15fr 1fr;
  gap: 20px;
  max-width: 980px;
  margin: 0 auto;
}
.plans .access-card { padding: 44px 36px; }
.plans .access-card h3 { margin-bottom: 18px; }
.plans .access-card ul { margin-bottom: 34px; }
.plans .access-card li { margin-bottom: 12px; }
.plans .access-card__price { margin-bottom: 8px; }
.plan__detail { font-size: 14px; color: var(--text-3); margin-bottom: 24px; min-height: 2.9em; }
.plan__head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px 16px;
  flex-wrap: wrap;
  margin-bottom: 22px;
}
.plans .plan__head h3 { margin-bottom: 0; }
.plan__billing { display: flex; align-items: center; }
/* La remise, accrochée au coin haut droit d'« Annuel ». */
.plan__save {
  position: absolute;
  top: -11px;
  right: -9px;
  font-size: 10.5px;
  font-weight: 700;
  line-height: 1;
  padding: 4px 6px;
  border-radius: 100px;
  color: var(--accent-text);
  /* Un lime léger rendu opaque : la pastille chevauche le bord du rail. */
  background: #3a4526;
  white-space: nowrap;
  pointer-events: none;
}
/* À l'annuel, au-dessus du prix : douze mois barrés, et le gain. Sa place
   est gardée au mensuel : l'afficher ne pousse pas la carte. */
.plan__was {
  display: flex;
  align-items: baseline;
  gap: 10px;
  margin-bottom: 8px;
  font-size: 15px;
  visibility: hidden;
}
.plan__was.is-on { visibility: visible; }
.plan__was s { color: var(--text-3); text-decoration-thickness: 1.5px; font-variant-numeric: tabular-nums; }
.plan__was span { color: var(--accent-text); font-weight: 600; letter-spacing: -0.01em; }
.plan__count { display: flex; flex-direction: column; align-items: flex-start; gap: 10px; margin-bottom: 26px; }
.plan__count-label { font-size: 14px; font-weight: 600; color: var(--text-2); }
.plan .access-card__amount { font-variant-numeric: tabular-nums; }

/* Un sélecteur à pastille, la matière de celui de l'apparence du pied de
   page : un rail, et une pastille qui glisse sous le choix pris. Sa
   place est mesurée sur le bouton choisi (site.js, initPricing). */
.seg {
  position: relative;
  display: inline-flex;
  padding: 3px;
  border-radius: 100px;
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid rgba(255, 255, 255, 0.08);
}
/* La pastille est du verre : un voile clair, une arête haute éclairée,
   une assise sombre, et le flou de ce qui est dessous (sans saturate(),
   qui teinte en vert). */
.seg__thumb {
  position: absolute;
  top: 3px;
  bottom: 3px;
  left: 0;
  width: 0;
  border-radius: 100px;
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.24), rgba(255, 255, 255, 0.08));
  border: 1px solid rgba(255, 255, 255, 0.20);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.35),
    inset 0 -1px 0 rgba(0, 0, 0, 0.18),
    0 4px 14px rgba(0, 0, 0, 0.30);
  -webkit-backdrop-filter: blur(12px);
  backdrop-filter: blur(12px);
  transform: translateX(var(--x, 3px));
  transition: transform 0.36s var(--ease-out), width 0.36s var(--ease-out);
}
.seg.is-still .seg__thumb { transition: none; }
.seg__opt {
  position: relative;
  z-index: 1;
  display: inline-flex;
  align-items: center;
  height: 34px;
  padding: 0 16px;
  border: 0;
  background: none;
  border-radius: 100px;
  font: inherit;
  font-size: 14px;
  font-weight: 600;
  color: rgba(255, 255, 255, 0.62);
  cursor: pointer;
  white-space: nowrap;
  transition: color 0.2s var(--ease-out);
}
.seg__opt:hover { color: #ffffff; }
.seg__opt[aria-checked="true"],
.seg__opt[aria-checked="true"]:hover { color: #ffffff; }
.seg__opt:focus-visible { outline: 2px solid var(--accent-ring); outline-offset: 1px; }
.seg--round .seg__opt { width: 38px; padding: 0; justify-content: center; font-variant-numeric: tabular-nums; }

/* L'offre groupement, en bandeau sous les deux cartes. */
.plan-group {
  max-width: 980px;
  margin: 20px auto 0;
  padding: 32px 36px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 32px;
}
.plan-group h3 {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 23px;
  letter-spacing: -0.02em;
  margin-bottom: 10px;
}
/* « Ou écrivez à » garde la taille et la couleur de celui des cartes
   (Matteo, 12 octobre 2026 : « trop gros, de la même taille que celui du
   dessus »). */
.plan-group p:not(.access-card__tag):not(.mail-copy) { font-size: 15px; color: var(--text-2); max-width: 58ch; }
.plan-group .btn { flex-shrink: 0; }
.plan-group__cta { display: flex; flex-direction: column; align-items: center; flex-shrink: 0; }
@media (max-width: 720px) {
  .plans__cards { grid-template-columns: 1fr; }
  .plans .access-card { padding: 36px 24px; }
  .plan-group { flex-direction: column; align-items: stretch; padding: 30px 24px; gap: 22px; }
}

/* Tout est compris. */
.included { padding: 80px 0; }
.included .section-sub { margin-bottom: 44px; }
.included__grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 20px;
  max-width: 1040px;
  margin: 0 auto;
}
.included__item { padding: 28px 26px 18px; }
.included__item h3 {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 19px;
  letter-spacing: -0.015em;
  margin-bottom: 14px;
}
.included__item ul { list-style: none; }
.included__item li {
  margin-bottom: 10px;
  font-size: 14.5px;
  line-height: 1.5;
  color: var(--text-2);
}
@media (max-width: 960px) { .included__grid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 620px) { .included__grid { grid-template-columns: 1fr; } }

/* Comment ça se passe : quatre étapes numérotées. */
.howto { padding: 60px 0; }
.howto .section-title { margin-bottom: 40px; }
.howto__steps { list-style: none; counter-reset: step; }
.howto__step {
  counter-increment: step;
  position: relative;
  padding: 22px 0 22px 62px;
  border-bottom: 1px solid var(--border);
}
.howto__step:last-child { border-bottom: 0; }
.howto__step::before {
  content: counter(step);
  position: absolute;
  left: 0;
  top: 20px;
  width: 38px;
  height: 38px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 16px;
  color: var(--accent-text);
  background: rgba(143, 179, 104, 0.16);
}
.howto__step h3 {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 18px;
  letter-spacing: -0.01em;
  margin-bottom: 6px;
}
.howto__step p { font-size: 15px; line-height: 1.6; color: var(--text-2); }

/* Les questions sur le prix : les bulles de l'accueil, dans un espace
   moins haut (six questions au lieu de douze). */
.price-faq { padding: 60px 0 140px; }
.qs.qs--short { height: 460px; }

/* Un lien dans la réponse d'une bulle de questions : en vert, sans
   soulignement, comme les liens du texte de l'abonnement. */
.qs__answer a { color: var(--accent-text); font-weight: 500; }

/* Des petits nuages verts dans la carte de l'abonnement (29 septembre
   2026) : les nappes floues qui flottaient derrière la page en sombre,
   en petit, qui dérivent lentement chacune à son rythme. La carte les
   rogne ; son contenu passe devant. */
.access-card:has(> .card-clouds) { position: relative; isolation: isolate; overflow: hidden; }
.access-card > :not(.card-clouds) { position: relative; z-index: 1; }
.card-clouds { position: absolute; inset: 0; z-index: 0; pointer-events: none; }
.card-clouds i {
  position: absolute;
  aspect-ratio: 1;
  border-radius: 50%;
  /* Une seule couleur pour tous, en grandes nappes (pas de points
     localisés) : le lime léger, qui se lit OLIVE sur le vert de la carte
     (#45502d au plus fort) — le vert choisi par Matteo sur la première
     version ; le vert forêt des boutons a été essayé et retiré. */
  background: radial-gradient(closest-side, rgba(183, 217, 143, 0.26), rgba(183, 217, 143, 0.10) 55%, transparent 78%);
  filter: blur(40px);
  will-change: transform;
  animation: card-cloud var(--dur, 22s) ease-in-out var(--delay, 0s) infinite alternate;
}
.card-clouds i:nth-child(1) { --dur: 22s; top: -30%; left: -35%; width: 110%; --dx: 60px; --dy: 40px; }
.card-clouds i:nth-child(2) { --dur: 27s; --delay: -8s; top: 25%; right: -45%; width: 105%; --dx: -70px; --dy: 50px; }
.card-clouds i:nth-child(3) { --dur: 31s; --delay: -15s; bottom: -40%; left: -20%; width: 115%; --dx: 60px; --dy: -50px; }
@keyframes card-cloud {
  from { transform: translate3d(0, 0, 0) scale(1); }
  to { transform: translate3d(var(--dx), var(--dy), 0) scale(1.14); }
}
@media (prefers-reduced-motion: reduce) { .card-clouds i { animation: none; } }

/* Le bouton de la carte du pilote porte AUSSI les nuages de la carte de
   l'abonnement (Matteo, 1er octobre 2026 : « je ne vois pas l'effet de la
   card abonnement dans le bouton gratuit ») : les mêmes trois nappes,
   la même couleur et les mêmes rythmes, à l'échelle du bouton — plus
   petites et moins floues, centrées sur sa hauteur. Le texte passe devant. */
.btn--clouds { position: relative; isolation: isolate; overflow: hidden; }
.btn--clouds > .btn__label { position: relative; z-index: 1; }
.btn--clouds > .card-clouds i { filter: blur(12px); top: 50%; }
.btn--clouds > .card-clouds i:nth-child(1) { left: -12%; width: 56%; margin-top: -28%; --dx: 46px; --dy: 8px; }
.btn--clouds > .card-clouds i:nth-child(2) { right: -18%; left: auto; width: 52%; margin-top: -26%; --dx: -54px; --dy: -8px; }
.btn--clouds > .card-clouds i:nth-child(3) { left: 30%; bottom: auto; width: 48%; margin-top: -24%; --dx: 40px; --dy: 6px; }

/* ============================================================
   Le survol des boutons d'action, repris de getdroppy.app (bouton
   « Purchase », 5 octobre 2026) : le mot se dissout dans un flou et un
   symbole apparaît à sa place — une clé pour « Demander un accès », une
   flèche vers le bas pour « Voir comment ça marche », qui descend à la
   suite de la page, une cloche pour « Être prévenu ». Le mot reste dans le flux : le bouton ne change pas de
   taille. Au doigt, rien ne change (pas de survol), et sans animations le
   mot reste.
   ============================================================ */
.btn-morph { position: relative; --morph-dur: 340ms; --morph-ease: cubic-bezier(0.22, 1, 0.36, 1); --morph-blur: 14px; }
.btn-morph__face {
  display: inline-flex; align-items: center; justify-content: center; gap: inherit;
  transition: opacity var(--morph-dur) linear, filter var(--morph-dur) var(--morph-ease);
}
.btn-morph__face--rest { opacity: 1; filter: blur(0); }
.btn-morph__face--hover { position: absolute; inset: 0; opacity: 0; filter: blur(var(--morph-blur)); pointer-events: none; }
.btn-morph__mark { width: 22px; height: 22px; flex: 0 0 auto; }
.nav__cta.btn-morph, .footer__cta.btn-morph { --morph-blur: 10px; }
.nav__cta.btn-morph .btn-morph__mark { width: 18px; height: 18px; }
@media (hover: hover) and (pointer: fine) {
  .btn-morph:hover .btn-morph__face--rest { opacity: 0; filter: blur(var(--morph-blur)); }
  .btn-morph:hover .btn-morph__face--hover { opacity: 1; filter: blur(0); }
}
@media (prefers-reduced-motion: reduce) {
  .btn-morph__face { transition: none; }
  .btn-morph__face--hover { display: none; }
  .btn-morph:hover .btn-morph__face--rest { opacity: 1; filter: none; }
}
