/* Site public de VOKPIT (vokpit.pages.dev) : feuille unique des pages d'accueil / et /en et de la 404.
 *
 * Direction artistique « Plein phare » (docs/design/site-public.md) : un même tournage moto, en
 * plans réels, porte tout le récit. L'ouverture superpose cinq plans détourés d'une seule image
 * (ciel, logotype, montagnes, sol, motard) qui bougent chacun à leur profondeur ; deux séquences
 * d'images suivent le défilement ; deux boucles vidéo et une image fixe complètent. La marque
 * garde sa seule couleur vive, la ligne de signal menthe -> cyan.
 *
 * Sans script, ou sous prefers-reduced-motion, la page est entière et immobile : site.js pose la
 * classe .motion sur <html> seulement quand le mouvement est permis, et toutes les scènes
 * épinglées vivent sous cette classe. Les valeurs de repli de --p sont les états finaux.
 */

/* ---- Polices : Archivo variable (graisse 100-900, chasse 62-125 %), SIL OFL, servie par le site. */
@font-face {
  font-family: "Archivo";
  src: url("/fonts/archivo-roman.woff2") format("woff2");
  font-weight: 100 900;
  font-stretch: 62% 125%;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Archivo";
  src: url("/fonts/archivo-italic.woff2") format("woff2");
  font-weight: 100 900;
  font-stretch: 62% 125%;
  font-style: italic;
  font-display: swap;
}
/* Repli aux mêmes métriques verticales qu'Archivo (878 / 210 sur 1000) : l'échange de police ne
 * déplace pas les lignes. */
@font-face {
  font-family: "Archivo Repli";
  src: local("Arial"), local("Helvetica Neue"), local("Helvetica"), local("Liberation Sans"), local("Roboto");
  size-adjust: 104%;
  ascent-override: 84%;
  descent-override: 20%;
  line-gap-override: 0%;
}

/* ---- Jetons -------------------------------------------------------------------------------- */
:root {
  color-scheme: dark;

  /* Couleurs. Encre, acier et brume sont aussi celles de l'étalonnage des photos
   * (make_site_images.py). Contrastes relevés sur --ink : --text 17,9:1, --text-2 10,8:1,
   * --text-3 6,4:1, --mint 13,1:1, --amber 11:1, --sos 6,7:1. */
  --ink: #05070b;
  --ink-2: #0a0d13;
  --ink-3: #111620;
  --steel: #2a3645;
  --fog: #d9e2ea;
  --text: #eef2f6;
  --text-2: #b4bfcc;
  --text-3: #8592a2;
  --hair: rgb(238 242 246 / 0.12);
  --hair-2: rgb(238 242 246 / 0.24);
  --mint: #37e9c4;
  --cyan: #3de3ff;
  --signal: linear-gradient(90deg, var(--mint), var(--cyan));
  --on-signal: #05070b;
  --amber: #ffb020;
  --sos: #ff5a6a;
  --sos-ink: #140407;
  /* Section claire (brouillard) : encre sur brume, 14,5:1 et 9,3:1 ; ambre sombre 7,1:1. */
  --fog-text: #0b1018;
  --fog-text-2: #2c3644;
  --fog-amber: #7a4a00;

  /* Typographie */
  --font: "Archivo", "Archivo Repli", system-ui, -apple-system, "Segoe UI", sans-serif;
  --t-hero: clamp(2.6rem, 6.8vw - 0.1rem, 6.2rem);
  --t-display: clamp(2.25rem, 1.05rem + 5vw, 5.75rem);
  --t-quote: clamp(1.75rem, 1rem + 3vw, 3.75rem);
  --t-h3: clamp(1.25rem, 1.05rem + 0.8vw, 1.75rem);
  --t-lead: clamp(1.125rem, 1rem + 0.55vw, 1.5rem);
  --t-body: clamp(1rem, 0.96rem + 0.18vw, 1.125rem);
  --t-small: 0.9375rem;
  --t-label: 0.75rem;

  /* Espaces et largeurs */
  --gutter: clamp(1rem, 0.4rem + 3.4vw, 4.5rem);
  --wrap: 108rem;
  --measure: 36rem;
  --s-1: 0.25rem;
  --s-2: 0.5rem;
  --s-3: 0.75rem;
  --s-4: 1rem;
  --s-5: 1.5rem;
  --s-6: 2rem;
  --s-7: clamp(2.5rem, 2rem + 2vw, 4rem);
  --s-8: clamp(4rem, 3rem + 5vw, 8rem);
  --s-9: clamp(6rem, 4rem + 9vw, 14rem);
  --header-h: 4rem;

  /* Mouvement : survol, transition, révélation, cinéma */
  --ease-out: cubic-bezier(0.16, 0.84, 0.24, 1);
  --ease-io: cubic-bezier(0.65, 0, 0.35, 1);
  --dur-1: 160ms;
  --dur-2: 320ms;
  --dur-3: 700ms;
  --dur-4: 1400ms;

  --r-1: 6px;
  --r-2: 16px;
  --r-pill: 999px;
}

/* ---- Base ---------------------------------------------------------------------------------- */
*,
*::before,
*::after {
  box-sizing: border-box;
}
html {
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  scroll-padding-top: calc(var(--header-h) + 1rem);
}
body {
  margin: 0;
  background: var(--ink);
  color: var(--text);
  font-family: var(--font);
  font-size: var(--t-body);
  line-height: 1.6;
  font-stretch: 100%;
  font-kerning: normal;
  overflow-x: clip;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}
img,
svg,
picture {
  display: block;
  max-width: 100%;
}
img {
  height: auto;
}
a {
  color: inherit;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.2em;
}
a:hover {
  text-decoration-color: var(--cyan);
}
:focus-visible {
  outline: 2px solid var(--cyan);
  outline-offset: 3px;
  border-radius: 4px;
}
h1,
h2,
h3,
p,
ul,
ol,
dl,
dd,
figure,
blockquote {
  margin: 0;
}
ul,
ol {
  padding: 0;
  list-style: none;
}
strong {
  font-weight: 700;
}
q {
  quotes: "“" "”" "‘" "’";
}
:lang(fr) q {
  quotes: "«\00a0" "\00a0»" "“" "”";
}
::selection {
  background: var(--mint);
  color: var(--on-signal);
}

.wrap {
  width: 100%;
  max-width: var(--wrap);
  margin-inline: auto;
  padding-inline: var(--gutter);
}
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}
.skip {
  position: fixed;
  top: var(--s-3);
  left: var(--s-3);
  z-index: 100;
  padding: var(--s-3) var(--s-4);
  background: var(--text);
  color: var(--ink);
  font-weight: 700;
  border-radius: var(--r-1);
  transform: translateY(-200%);
  transition: transform var(--dur-2) var(--ease-out);
}
.skip:focus {
  transform: none;
}

/* ---- Typographie ----------------------------------------------------------------------------- */
.label {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  font-size: var(--t-label);
  font-weight: 600;
  font-stretch: 85%;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--text-2);
}
.label .km {
  font-variant-numeric: tabular-nums;
  color: var(--text);
}
.label .km::after {
  content: "";
  display: inline-block;
  width: 2.25rem;
  height: 1px;
  margin-left: var(--s-3);
  vertical-align: middle;
  background: var(--signal);
}
.display {
  font-size: var(--t-display);
  font-style: italic;
  font-weight: 850;
  font-stretch: 112%;
  line-height: 0.95;
  letter-spacing: -0.015em;
  text-wrap: balance;
}
.lead {
  font-size: var(--t-lead);
  line-height: 1.45;
  color: var(--text-2);
  max-width: var(--measure);
  text-wrap: pretty;
}
.prose {
  max-width: var(--measure);
  color: var(--text-2);
  text-wrap: pretty;
}
.prose p + p {
  margin-top: var(--s-4);
}
.prose strong {
  color: var(--text);
}
.note {
  font-size: var(--t-small);
  color: var(--text-3);
  max-width: var(--measure);
}
.quote {
  font-size: var(--t-quote);
  font-style: italic;
  font-weight: 750;
  font-stretch: 106%;
  line-height: 1.04;
  letter-spacing: -0.01em;
  text-wrap: balance;
}
.signal-text {
  background: var(--signal);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

/* ---- Boutons ------------------------------------------------------------------------------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--s-3);
  min-height: 3.5rem;
  padding: 0 var(--s-6);
  border-radius: var(--r-pill);
  font-weight: 700;
  font-stretch: 105%;
  font-size: 1rem;
  line-height: 1.2;
  text-decoration: none;
  cursor: pointer;
  transition:
    transform var(--dur-1) var(--ease-out),
    background-position var(--dur-3) var(--ease-out),
    border-color var(--dur-2) var(--ease-out),
    color var(--dur-2) var(--ease-out);
}
.btn svg {
  width: 1.25rem;
  height: 1.25rem;
  flex: none;
}
.btn--signal {
  color: var(--on-signal);
  background: linear-gradient(90deg, var(--mint), var(--cyan), var(--mint)) 0 0 / 200% 100%;
}
.btn--signal:hover {
  background-position: 100% 0;
}
.btn:active {
  transform: translateY(1px) scale(0.99);
}
/* Bouton secondaire au trait (mentions légales : ne plus compter ses visites). */
.btn--ghost {
  min-height: 2.75rem;
  margin: var(--s-1) var(--s-3) var(--s-1) 0;
  padding: 0 var(--s-5);
  border: 1px solid var(--hair-2);
  background: transparent;
  color: var(--text);
  font: inherit;
  font-weight: 650;
}
.btn--ghost:hover,
.btn--ghost:focus-visible {
  border-color: var(--mint);
}
.btn--ghost[aria-pressed="true"] {
  border-color: var(--mint);
  color: var(--mint);
}

/* ---- En-tête ------------------------------------------------------------------------------- */
.topbar {
  position: fixed;
  inset: 0 0 auto;
  z-index: 50;
  height: var(--header-h);
  transition:
    background-color var(--dur-2) var(--ease-out),
    box-shadow var(--dur-2) var(--ease-out);
}
/* Voile sous l'en-tête transparent : il descend plus bas que la barre, pour que les liens se
 * lisent même sur le ciel clair de la photo d'ouverture. */
.topbar::before {
  content: "";
  position: absolute;
  inset: 0 0 -4rem;
  z-index: -1;
  background: linear-gradient(rgb(5 7 11 / 0.82), rgb(5 7 11 / 0.45) 55%, rgb(5 7 11 / 0));
  pointer-events: none;
  transition: opacity var(--dur-2) var(--ease-out);
}
.topbar.is-solid::before {
  opacity: 0;
}
.topbar.is-solid {
  background: rgb(5 7 11 / 0.82);
  -webkit-backdrop-filter: blur(14px) saturate(1.2);
  backdrop-filter: blur(14px) saturate(1.2);
  box-shadow: 0 1px 0 var(--hair);
}
.topbar__in {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  height: 100%;
}
/* Le logotype garde ses proportions quelle que soit la largeur : un élément flexible peut rétrécir,
 * et la règle générale des images (max-width: 100 %) l'écrasait au téléphone (2026-10-14 : 93 px
 * de large pour 22 de haut à 390 px, au lieu de 110). */
.brand {
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  min-height: 44px;
  margin-right: auto;
}
/* Pictogramme « cockpit » et logotype : les fichiers de marque de l'application, vectorisés
 * (tools/pages/make_brand.py), jamais une police. */
.brand img {
  width: auto;
  max-width: none;
}
.brand__mark {
  height: 1.75rem;
}
.brand__word {
  height: 1.375rem;
}
/* Page d'un module : son nom DESSINÉ suit le logotype, à la même hauteur et à 0,35 fois cette
 * hauteur, comme dans l'application (ModeLockup : « VOKPIT MOTO » se lit d'un seul bloc). Il mène
 * au catalogue des modules de l'accueil. */
.brand--suite {
  margin-right: 0;
}
.suite {
  flex: none;
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  margin-right: auto;
  margin-left: calc(1.375rem * 0.35 - var(--s-2));
}
.suite img {
  width: auto;
  max-width: none;
  height: 1.375rem;
}
.topnav {
  display: none;
  gap: var(--s-5);
  font-size: var(--t-small);
  font-weight: 500;
}
.topnav a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  color: var(--text-2);
  text-decoration: none;
  transition: color var(--dur-1) var(--ease-out);
}
.topnav a:hover {
  color: var(--text);
}
/* Langue : les deux langues côte à côte, celle de la page marquée (un « EN » seul ne disait pas
 * s'il nommait la langue de la page ou l'autre). Dans l'en-tête sur grand écran ; au téléphone,
 * dans le menu, où l'en-tête n'a pas la place (2026-10-14). Changer de langue garde la partie lue
 * (site.js). */
.langs {
  display: none;
  align-items: center;
  gap: 2px;
  padding: 3px;
  border: 1px solid var(--hair-2);
  border-radius: var(--r-pill);
}
.langs > * {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 2.5rem;
  min-height: 2.25rem;
  border-radius: var(--r-pill);
  font-size: var(--t-label);
  font-weight: 700;
  letter-spacing: 0.12em;
  color: var(--text-2);
  text-decoration: none;
}
.langs a:hover,
.langs a:focus-visible {
  color: var(--text);
  background: rgb(255 255 255 / 0.06);
}
.langs [aria-current] {
  color: var(--ink);
  background: var(--text);
}
.toc__langs {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-3);
  margin-top: var(--s-2);
  padding: var(--s-3) var(--s-3) var(--s-1);
  border-top: 1px solid var(--hair);
  font-size: var(--t-small);
  color: var(--text-2);
}
.toc__langs .langs {
  display: inline-flex;
}
.topbar .btn {
  min-height: 2.75rem;
  padding: 0 var(--s-4);
  font-size: var(--t-small);
}
@media (min-width: 60rem) {
  .topbar__in {
    gap: var(--s-4);
  }
  .suite {
    margin-left: calc(1.375rem * 0.35 - var(--s-4));
  }
  .topnav {
    display: flex;
  }
  .topbar__in > .langs {
    display: inline-flex;
  }
  .toc__langs {
    display: none;
  }
  /* Pages secondaires : sur grand écran, leurs liens sont déjà dans l'en-tête. */
  .toc--pages {
    display: none;
  }
}
/* Téléphone : sur la page d'un module, logotype, nom du module et menu occupent la barre ;
 * « Télécharger » reste dans le sommaire et dans l'ouverture, à un geste (mesuré le 2026-10-14 :
 * à 390 px, le bouton sortait de l'écran de 5 px). */
@media (max-width: 26.5rem) {
  .topbar__in:has(.suite) > .btn {
    display: none;
  }
}
@media (max-width: 24rem) {
  .topbar .btn {
    padding: 0 var(--s-3);
  }
}
/* 320 px : le logotype seul, sans le pictogramme, pour que la barre tienne. */
@media (max-width: 22.5rem) {
  .brand__mark {
    display: none;
  }
}
/* Sommaire : un <details> (marche sans script) qui liste toutes les parties ; site.js le ferme
 * au choix d'une partie, à Échap ou à un clic ailleurs, et marque la partie à l'écran
 * (aria-current). Au téléphone, l'icône seule. */
.toc {
  position: relative;
}
.toc > summary {
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
  min-width: 44px;
  min-height: 44px;
  justify-content: center;
  padding: 0 var(--s-2);
  border-radius: var(--r-pill);
  font-size: var(--t-small);
  font-weight: 600;
  color: var(--text);
  cursor: pointer;
  list-style: none;
}
.toc > summary::-webkit-details-marker {
  display: none;
}
.toc > summary svg {
  width: 1.25rem;
  height: 1.25rem;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
}
.toc > summary span {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}
.toc[open] > summary {
  background: rgb(255 255 255 / 0.08);
}
.toc__panel {
  /* Ancré au bord droit de la fenêtre (l'en-tête fixe, qui le contient) : aligné sur le bouton,
   * il sortait de l'écran par la gauche au téléphone. */
  position: fixed;
  top: calc(var(--header-h) - 0.25rem);
  right: var(--gutter);
  width: min(19rem, calc(100vw - 2 * var(--gutter)));
  max-height: calc(100svh - var(--header-h) - 1.5rem);
  overflow: auto;
  padding: var(--s-2);
  border: 1px solid var(--hair-2);
  border-radius: var(--r-2);
  background: rgb(10 13 19 / 0.97);
  box-shadow: 0 24px 60px -20px rgb(0 0 0 / 0.9);
}
/* Une partie = son nom, rien d'autre (2026-10-14 : des numéros pour les chapitres et des points
 * pour le reste donnaient deux listes en une). La partie à l'écran porte un trait menthe. */
.toc__panel ol {
  margin: 0;
  padding: 0;
  list-style: none;
}
.toc__panel li a {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  min-height: 44px;
  padding: 0.65rem var(--s-3);
  border-radius: var(--r-1);
  color: var(--text-2);
  text-decoration: none;
}
.toc__panel li a::before {
  content: "";
  flex: none;
  width: 3px;
  height: 1.1em;
  border-radius: 2px;
  background: var(--hair-2);
}
.toc__panel li a:hover,
.toc__panel li a:focus-visible {
  background: rgb(255 255 255 / 0.06);
  color: var(--text);
}
.toc__panel li a[aria-current] {
  color: var(--text);
}
.toc__panel li a[aria-current]::before {
  background: var(--mint);
}
/* Groupe « Les modules » : fermé au départ, il s'ouvre au clic (un <details>, sans script) et, à la
 * souris, au survol (site.js). Ses entrées ont la taille et le trait des autres parties, en retrait
 * (2026-10-14 : le nom dessiné MOTO, plus grand et plus gras que le reste, détonnait). */
.toc__group > summary {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  min-height: 44px;
  padding: 0.65rem var(--s-3);
  border-radius: var(--r-1);
  color: var(--text-2);
  cursor: pointer;
  list-style: none;
}
.toc__group > summary::-webkit-details-marker {
  display: none;
}
.toc__group > summary::before {
  content: "";
  flex: none;
  width: 3px;
  height: 1.1em;
  border-radius: 2px;
  background: var(--hair-2);
}
.toc__group > summary:hover,
.toc__group > summary:focus-visible {
  background: rgb(255 255 255 / 0.06);
  color: var(--text);
}
.toc__group:not([open]):has(a[aria-current]) > summary {
  color: var(--text);
}
.toc__group:not([open]):has(a[aria-current]) > summary::before {
  background: var(--mint);
}
.toc__group > summary svg {
  flex: none;
  width: 1rem;
  height: 1rem;
  margin-left: auto;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
  transition: transform var(--dur-2) var(--ease-out);
}
.toc__group[open] > summary svg {
  transform: rotate(180deg);
}
.toc__sub {
  margin: 0;
  padding: 0 0 0 var(--s-5);
  list-style: none;
}
/* MOTO : son nom DESSINÉ, à la hauteur des capitales du texte du menu (0,686 em, celle d'Archivo,
 * relevée sur le fichier de police) et posé sur sa ligne de base, comme un mot : la même taille
 * que « Tous les modules » au-dessus. */
.toc__logo img {
  display: inline;
  width: auto;
  max-width: none;
  height: 0.686em;
  vertical-align: baseline;
}
@media (min-width: 60rem) {
  .toc > summary span {
    position: static;
    width: auto;
    height: auto;
    overflow: visible;
    clip-path: none;
  }
  .toc > summary {
    padding: 0 var(--s-3);
  }
}

/* ---- Documents : mentions légales, CGV, confidentialité, assistance, suppression de compte,
 * crédits, bêta (une page par langue, tools/pages/partials/README.md). Long texte en colonne de
 * lecture, mêmes encres, même police et mêmes titres que le reste du site. */
.doc {
  max-width: 46rem;
  margin: 0 auto;
  padding: calc(var(--header-h) + var(--s-8)) var(--gutter) var(--s-9);
  color: var(--text-2);
}
.doc > .label {
  margin-bottom: var(--s-4);
}
.doc h1 {
  margin-bottom: var(--s-4);
  font-size: clamp(2rem, 1.2rem + 3vw, 3.25rem);
  font-weight: 840;
  font-style: italic;
  font-stretch: 110%;
  line-height: 1.02;
  letter-spacing: -0.015em;
  color: var(--text);
  text-wrap: balance;
}
.doc h2 {
  margin: var(--s-8) 0 var(--s-3);
  font-size: clamp(1.25rem, 1.05rem + 0.7vw, 1.6rem);
  font-weight: 780;
  font-style: italic;
  font-stretch: 106%;
  line-height: 1.15;
  color: var(--text);
}
.doc h3 {
  margin: var(--s-6) 0 var(--s-2);
  font-size: 1.1rem;
  font-weight: 700;
  color: var(--text);
}
.doc p,
.doc ul,
.doc ol,
.doc .table-wrap {
  margin-bottom: var(--s-4);
}
.doc ul,
.doc ol {
  padding-left: 1.25rem;
}
.doc ul {
  list-style: disc;
}
.doc ol {
  list-style: decimal;
}
.doc li {
  margin-bottom: var(--s-2);
}
.doc li::marker {
  color: var(--text-3);
}
.doc strong {
  color: var(--text);
}
.doc a:not(.btn) {
  color: var(--mint);
  /* Une adresse longue (conditions de Gemma, article 10 des CGV) se coupe au lieu de déborder à
   * 320 px. */
  overflow-wrap: anywhere;
}
.doc .meta {
  margin-bottom: var(--s-6);
  font-size: var(--t-small);
  color: var(--text-3);
}
.doc .lead {
  color: var(--text-2);
}
.doc .notice,
.doc .summary,
.doc .box,
.doc .form,
.doc .legal-box {
  margin: var(--s-5) 0;
  padding: var(--s-4) var(--s-5);
  border: 1px solid var(--hair-2);
  border-radius: var(--r-2);
  background: var(--ink-2);
}
.doc .notice > :last-child,
.doc .summary > :last-child,
.doc .box > :last-child,
.doc .form > :last-child,
.doc .legal-box > :last-child {
  margin-bottom: 0;
}
/* L'encadré de garantie légale (article D. 211-4 du code de la consommation) doit se voir comme
 * un encadré ; le formulaire de rétractation, comme un formulaire. */
.doc .legal-box {
  border: 2px solid var(--text-3);
}
.doc .form {
  border-style: dashed;
}
/* Information que seul l'éditeur peut fournir et qui n'existe pas encore : visible comme telle,
 * jamais présentée comme une information réelle. */
.doc .todo {
  padding: 0 0.3em;
  border: 1px dashed #b88a12;
  border-radius: 4px;
  background: #3a2f0b;
  color: #ffd866;
  font-weight: 600;
}
.doc .table-wrap {
  overflow-x: auto;
}
.doc table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--t-small);
}
.doc th,
.doc td {
  padding: 0.55rem 0.7rem;
  border: 1px solid var(--hair-2);
  text-align: left;
  vertical-align: top;
}
.doc th {
  background: var(--ink-2);
  color: var(--text);
}
.doc code {
  padding: 0.05em 0.35em;
  border-radius: 4px;
  background: var(--ink-3);
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.88em;
  color: var(--text);
  overflow-wrap: anywhere;
}
.doc hr {
  margin: var(--s-8) 0;
  border: 0;
  border-top: 1px solid var(--hair);
}
.doc img {
  margin: var(--s-4) 0;
  border-radius: var(--r-1);
}
.doc [id] {
  scroll-margin-top: calc(var(--header-h) + var(--s-5));
}
.doc .doc-list {
  padding: 0;
  list-style: none;
  border-top: 1px solid var(--hair);
}
.doc .doc-list li {
  display: grid;
  grid-template-columns: minmax(7rem, 11rem) 1fr;
  gap: var(--s-4);
  margin: 0;
  padding: var(--s-4) 0;
  border-bottom: 1px solid var(--hair);
}
@media (max-width: 30rem) {
  .doc .doc-list li {
    grid-template-columns: 1fr;
    gap: var(--s-1);
  }
}
.doc .doc-cta {
  margin: var(--s-5) 0 var(--s-2);
}
.doc .install {
  margin-top: var(--s-7);
  padding: 0;
  list-style: none;
}

/* Pages secondaires (bêta, crédits, 404) : retour à l'accueil dans l'en-tête, à toutes les tailles. */
.backlinks {
  display: flex;
  gap: var(--s-2);
}
.backlinks a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: 0 var(--s-3);
  border-radius: var(--r-pill);
  font-size: var(--t-small);
  font-weight: 600;
  color: var(--text-2);
  text-decoration: none;
}
.backlinks a:hover,
.backlinks a:focus-visible {
  color: var(--text);
  background: rgb(255 255 255 / 0.06);
}

/* Revenir en haut : un lien vers l'ouverture, qui n'apparaît qu'une fois l'ouverture passée
 * (site.js, .is-shown) ; sans script, toujours là. */
.to-top {
  position: fixed;
  right: var(--gutter);
  bottom: calc(var(--s-4) + env(safe-area-inset-bottom));
  z-index: 40;
  display: grid;
  place-items: center;
  width: 2.875rem;
  height: 2.875rem;
  border: 1px solid var(--hair-2);
  border-radius: 50%;
  background: rgb(10 13 19 / 0.85);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  color: var(--text);
  transition:
    opacity var(--dur-2) var(--ease-out),
    transform var(--dur-2) var(--ease-out),
    border-color var(--dur-1) var(--ease-out);
}
.to-top:hover {
  border-color: var(--cyan);
}
.to-top svg {
  width: 1.25rem;
  height: 1.25rem;
  fill: none;
  stroke: currentColor;
  stroke-width: 2.2;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.js .to-top:not(.is-shown) {
  opacity: 0;
  transform: translateY(0.75rem);
  pointer-events: none;
  visibility: hidden;
}
/* Une partie atteinte par le sommaire ne se cache pas sous l'en-tête fixe. */
section[id] {
  scroll-margin-top: calc(var(--header-h) + var(--s-6));
}
/* Une partie atteinte par un lien reçoit le focus (site.js) sans s'encadrer : le parcours au
 * clavier reprend depuis elle, le contour viendra du lien suivant. */
section[tabindex="-1"]:focus,
main[tabindex="-1"]:focus {
  outline: none;
}
/* Sauf l'ouverture et les scènes épinglées, qui portent elles-mêmes la marge de l'en-tête. */
#top,
.constat[id],
.reponse[id],
.anticipation[id] {
  scroll-margin-top: 0;
}


/* ---- Ouverture : cinq plans, une profondeur chacun ------------------------------------------- */
/* Les cinq plans partagent un même cadre aux proportions de l'image (16:9, ou 9:16 au téléphone),
 * agrandi de --S pour que les déplacements ne découvrent jamais un bord, et calé par --fx / --fy
 * (0 : bord gauche ou haut, 0,5 : centré). Chaque plan contient tout ce qui est SOUS son bord
 * haut (make_site_media.py) : un plan qui glisse ne découvre jamais de trou dans celui du dessous.
 * site.js écrit leurs transformations ; sans lui, la scène reste posée, entière. */
.hero {
  position: relative;
  height: 100vh;
  height: 100svh;
  background: var(--ink);
}
.motion .hero {
  height: 160vh;
  height: 160svh;
}
.hero__pin {
  position: sticky;
  top: 0;
  height: 100vh;
  height: 100svh;
  overflow: hidden;
  isolation: isolate;
}
.hero__stage {
  position: absolute;
  inset: 0;
  overflow: hidden;
  container-type: size;
  background: #0b2a4f;
}
/* Fondu d'entrée : avec un script, la scène reste au noir jusqu'à ce que ses plans soient tous
 * chargés (site.js pose .is-ready), puis entre d'un seul fondu. Si le script ne vient pas, elle
 * entre seule au bout de trois secondes. */
@media (scripting: enabled) {
  .hero__stage {
    opacity: 0;
    animation: stage-in 1.1s var(--ease-out) 3s forwards;
  }
}
.hero__stage.is-ready {
  opacity: 1;
  animation: none;
  transition: opacity 1.1s var(--ease-out);
}
@keyframes stage-in {
  to {
    opacity: 1;
  }
}
.hero__frame {
  --S: 1.08;
  --fx: 0.5;
  --fy: 0.4;
  --cover: max(100cqw, 100cqh * 16 / 9);
  position: absolute;
  width: calc(var(--cover) * var(--S));
  aspect-ratio: 16 / 9;
  left: calc((100cqw - var(--cover) * var(--S)) * var(--fx));
  top: calc((100cqh - var(--cover) * var(--S) * 9 / 16) * var(--fy));
}
.hero__layer {
  position: absolute;
  inset: 0;
  transform-origin: 50% 50%;
}
.hero__layer img {
  width: 100%;
  height: 100%;
}
.hero__ground,
.hero__rider {
  transform-origin: 50% 80%;
}
.motion .hero__layer {
  will-change: transform;
}
/* Le logotype de la marque, tracé une fois depuis brand_wordmark.png (docs/design/site-public.md) :
 * posé dans le ciel, derrière les montagnes et le motard, qui le recouvrent en partie. */
.hero__mark {
  inset: auto;
  left: 15%;
  top: 13.5%;
  width: 56%;
  color: #f4f8fb;
  opacity: 0.9;
}
.hero__mark svg {
  display: block;
  width: 100%;
  height: auto;
  fill: currentColor;
  overflow: visible;
  /* Brume : le bas des lettres, plus loin dans l'air, pâlit. */
  -webkit-mask-image: linear-gradient(180deg, #000 30%, rgb(0 0 0 / 0.55) 100%);
  mask-image: linear-gradient(180deg, #000 30%, rgb(0 0 0 / 0.55) 100%);
}
/* Voile : de quoi lire l'en-tête en haut, le texte en bas à gauche ; ::after fond la scène au noir
 * à la fin du défilement (--dark, écrit par site.js), d'où sort le chapitre suivant. */
.hero__veil {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background:
    linear-gradient(180deg, rgb(5 7 11 / 0.5) 0%, rgb(5 7 11 / 0) 14%),
    linear-gradient(0deg, rgb(5 7 11 / 0.92) 0%, rgb(5 7 11 / 0.55) 22%, rgb(5 7 11 / 0) 46%),
    linear-gradient(90deg, rgb(5 7 11 / 0.7) 0%, rgb(5 7 11 / 0.34) 28%, rgb(5 7 11 / 0) 46%);
}
.hero__veil::after {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--ink);
  opacity: var(--dark, 0);
}
.hero__copy {
  position: absolute;
  inset: auto 0 0;
  display: grid;
  justify-items: start;
  gap: var(--s-4);
  padding-bottom: clamp(2rem, 7vh, 5.5rem);
}
.hero__copy > * {
  max-width: min(42rem, 44vw);
}
.hero h1 {
  font-size: clamp(2.4rem, 3.1vw + 0.25rem, 4.75rem);
  font-style: italic;
  font-weight: 860;
  font-stretch: 110%;
  line-height: 0.94;
  letter-spacing: -0.02em;
  text-wrap: balance;
}
.hero h1 span {
  display: block;
  background: var(--signal);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
.hero__lead {
  font-size: var(--t-lead);
  line-height: 1.42;
  color: #dfe6ee;
  text-wrap: pretty;
}
.hero__copy .store-row {
  margin-top: var(--s-2);
}
.hero__meta {
  font-size: var(--t-small);
  color: var(--text-2);
}
.hero__meta span {
  white-space: nowrap;
}
.hero__cue {
  position: absolute;
  right: var(--gutter);
  bottom: clamp(2rem, 7vh, 5.5rem);
  display: none;
  align-items: center;
  gap: var(--s-3);
  font-size: var(--t-label);
  font-weight: 600;
  font-stretch: 85%;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--text-2);
}
.hero__cue span {
  position: relative;
  width: 1px;
  height: 3rem;
  overflow: hidden;
  background: var(--hair-2);
}
.hero__cue span::after {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--signal);
  transform: translateY(-100%);
}
.motion .hero__cue {
  display: flex;
}
/* Le texte s'efface au défilement, mais jamais un lien qui a le focus clavier. */
.motion .hero__copy:focus-within {
  opacity: 1 !important;
  transform: none !important;
  pointer-events: auto !important;
}

/* Grand écran en paysage : le motard est décalé à droite, le texte se pose à sa gauche. */
@media (min-aspect-ratio: 3/2) {
  .hero__frame {
    --S: 1.2;
    /* Calé presque à gauche, mais avec 3,5 % de marge : la souris déplace le sol jusqu'à 2,4 %
     * de la largeur, et un bord découvert montrerait le fond. */
    left: calc(var(--cover) * var(--S) * -0.035);
  }
}
/* Écrans très larges (21:9) : le cadre déborde surtout en hauteur ; on le cale vers le haut pour
 * garder le logotype, quitte à couper le bas des roues. */
@media (min-aspect-ratio: 2/1) {
  .hero__frame {
    --S: 1.1;
    --fy: 0.15;
  }
}
/* Entre les deux (tablettes, écrans carrés) : image paysage centrée, texte en bas sur toute la
 * largeur. */
@media (max-aspect-ratio: 3/2) {
  .hero__copy > * {
    max-width: 40rem;
  }
  .hero__veil {
    background:
      linear-gradient(180deg, rgb(5 7 11 / 0.5) 0%, rgb(5 7 11 / 0) 14%),
      linear-gradient(0deg, rgb(5 7 11 / 0.95) 0%, rgb(5 7 11 / 0.82) 30%, rgb(5 7 11 / 0) 62%);
  }
  .hero__cue {
    display: none !important;
  }
}
/* Téléphone : le cadre portrait 9:16, centré sur le motard. */
@media (max-aspect-ratio: 4/5) {
  /* Cadre agrandi et calé vers le bas : le ciel vide du haut sort de l'écran, le motard monte et
   * grandit, le logotype se pose juste derrière son casque. */
  .hero__frame {
    --S: 1.2;
    --fx: 0.5;
    --fy: 0.62;
    --cover: max(100cqw, 100cqh * 9 / 16);
    aspect-ratio: 9 / 16;
    top: calc((100cqh - var(--cover) * var(--S) * 16 / 9) * var(--fy));
  }
  .hero__mark {
    left: 17%;
    top: 25.5%;
    width: 66%;
  }
  .hero__copy {
    gap: var(--s-3);
    padding-bottom: calc(var(--s-6) + env(safe-area-inset-bottom));
  }
  .hero h1 {
    font-size: clamp(2.25rem, 10vw, 4rem);
  }
  .hero__lead {
    font-size: 1.0625rem;
  }
}
@media (max-aspect-ratio: 4/5) and (max-height: 700px) {
  .hero__meta {
    display: none;
  }
}

/* Entrée en scène, au chargement seulement. */
@media (prefers-reduced-motion: no-preference) {
  .hero__frame {
    animation: settle var(--dur-4) var(--ease-out) both;
  }
  .hero__copy > * {
    animation: fade var(--dur-3) var(--ease-out) both;
  }
  .hero__copy > :nth-child(2) {
    animation-delay: 120ms;
  }
  .hero__copy > :nth-child(3) {
    animation-delay: 240ms;
  }
  .hero__copy > :nth-child(n + 4) {
    animation-delay: 360ms;
  }
  .hero__cue span::after {
    animation: cue 2.2s var(--ease-io) infinite;
  }
}

/* ---- Chapitres ----------------------------------------------------------------------------- */
.chapter {
  position: relative;
  isolation: isolate;
  padding-block: var(--s-9);
}
/* Deux chapitres qui se suivent ne cumulent pas leurs marges : 411 px de vide entre la virée et le
 * tableau de bord à 1440 px (2026-10-14). La sécurité garde la sienne, dans son propre fond. */
.chapter + .chapter:not(.chapter--sos) {
  padding-top: 0;
}
.chapter__head {
  display: grid;
  gap: var(--s-5);
  margin-bottom: var(--s-8);
}
.chapter__head .lead {
  margin-top: var(--s-2);
}

/* Images paresseuses : chacune entre en fondu quand elle est à l'écran et chargée (site.js pose
 * .fade-img sur <html>, puis .is-shown sur l'image). Une opacité, pas un mouvement : le fondu
 * reste sous prefers-reduced-motion. Sans script, tout est visible. */
.fade-img main img[loading="lazy"] {
  opacity: 0;
  transition: opacity 0.9s var(--ease-out);
}
.fade-img main img[loading="lazy"].is-shown {
  opacity: 1;
}

/* Révélation à l'entrée dans l'écran : seulement quand site.js tourne (classe .js) et que le
 * mouvement est permis. Sans script, tout est visible. */
@media (prefers-reduced-motion: no-preference) {
  .js [data-reveal] {
    opacity: 0;
    transform: translate3d(0, 1.5rem, 0);
    transition:
      opacity var(--dur-3) var(--ease-out),
      transform var(--dur-3) var(--ease-out);
    transition-delay: var(--d, 0ms);
  }
  .js [data-reveal].is-in,
  .js [data-reveal]:focus-within {
    opacity: 1;
    transform: none;
  }
}


/* ---- 01 Le constat : une seconde sans regarder la route ----------------------------------------- */
/* Séquence « approche » : le motard arrive vers la caméra. Avec .motion, la vue se ferme en fente
 * (deux paupières, --lid écrit par site.js) pendant que le compteur avance jusqu'à 25 m sur sa
 * règle, puis se rouvre sur le motard tout proche. Sans .motion : l'image finale, les textes
 * dessous, le compteur à 25.
 * Enchaînée à l'ouverture (data-chain) : avec .motion, la section remonte d'un écran sur la fin de
 * l'ouverture, transparente, sans pointeur et en visibility: hidden (son cadre vide, poussé dans
 * le premier écran, compterait sinon comme un décalage de mise en page, CLS 0,16 mesuré), et
 * s'épingle par-dessus à l'instant où l'ouverture finit au noir ; site.js ne la rend visible
 * qu'alors, puis l'image sort du noir. */
.constat {
  position: relative;
  background: var(--ink);
}
.motion .constat {
  margin-top: -100vh;
  margin-top: -100svh;
  background: none;
  visibility: hidden;
}
.motion .constat > :not(.seq) {
  visibility: visible;
}
.motion .seq[data-chain] {
  background: none;
  pointer-events: none;
}
.motion .seq--blind {
  height: 230vh;
  height: 230svh;
}
.lids {
  display: none;
}
.motion .lids {
  position: absolute;
  inset: 0;
  display: block;
  pointer-events: none;
}
.lid {
  position: absolute;
  left: 0;
  right: 0;
  height: 43%;
  transform: scaleY(var(--lid, 0));
  background: linear-gradient(var(--dir), var(--ink) 80%, rgb(5 7 11 / 0.65) 93%, rgb(5 7 11 / 0));
}
.lid--top {
  top: 0;
  transform-origin: 50% 0;
  --dir: 180deg;
}
.lid--bottom {
  bottom: 0;
  transform-origin: 50% 100%;
  --dir: 0deg;
}
.beat--meter {
  display: grid;
  gap: var(--s-5);
}
.motion .beat--meter {
  top: calc(var(--header-h) + 3vh);
  display: flex;
  flex-direction: column;
  justify-content: space-between;
}
.meter {
  display: flex;
  align-items: baseline;
  gap: 0.06em;
  font-size: clamp(5rem, min(3rem + 16vw, 30vh), 17rem);
  font-weight: 880;
  font-style: italic;
  font-stretch: 112%;
  line-height: 0.8;
  letter-spacing: -0.035em;
  font-variant-numeric: tabular-nums;
}
.meter b {
  font-weight: inherit;
  min-width: 1.15em;
  text-align: right;
  background: linear-gradient(180deg, var(--text) 30%, #93a2b3);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
.meter small {
  font-size: 0.3em;
  font-weight: 700;
  font-stretch: 100%;
  letter-spacing: 0;
  color: var(--text-2);
}
/* Règle de 25 graduations, une par mètre, plus haute tous les 5 m ; la ligne de signal avance
 * avec le compteur (--m, 0 -> 1). */
.ruler {
  position: relative;
  width: min(100%, 40rem);
  height: 16px;
  margin-top: var(--s-5);
  background:
    repeating-linear-gradient(90deg, var(--hair-2) 0 2px, transparent 2px 20%) 0 0 / 100% 16px no-repeat,
    repeating-linear-gradient(90deg, var(--hair-2) 0 1px, transparent 1px 4%) 0 4px / 100% 8px no-repeat;
}
.ruler i {
  position: absolute;
  left: 0;
  top: 7px;
  width: calc(var(--m, 1) * 100%);
  height: 2px;
  background: var(--signal);
  box-shadow: 0 0 12px rgb(61 227 255 / 0.6);
}
.meter__caption {
  max-width: 24ch;
  font-size: clamp(1.4rem, 1rem + 1.7vw, 2.6rem);
  font-style: italic;
  font-weight: 720;
  font-stretch: 104%;
  line-height: 1.1;
  color: var(--text);
  text-wrap: balance;
}
.constat__after {
  display: grid;
  gap: var(--s-8);
  padding-block: var(--s-8) var(--s-9);
}
.frictions {
  display: grid;
  border-top: 1px solid var(--hair);
  counter-reset: friction;
}
.frictions li {
  display: flex;
  align-items: baseline;
  gap: var(--s-4);
  padding: var(--s-4) 0;
  border-bottom: 1px solid var(--hair);
  font-size: var(--t-h3);
  font-weight: 600;
  font-stretch: 104%;
  line-height: 1.25;
}
.frictions li::before {
  counter-increment: friction;
  content: counter(friction, decimal-leading-zero);
  font-size: var(--t-label);
  font-weight: 600;
  letter-spacing: 0.14em;
  color: var(--text-3);
  font-variant-numeric: tabular-nums;
}
.frictions li:last-child {
  color: var(--mint);
}
.rule {
  display: grid;
  gap: var(--s-5);
  max-width: 62rem;
  padding-left: var(--s-5);
  border-left: 2px solid var(--mint);
}
.rule cite {
  font-size: var(--t-small);
  font-style: normal;
  color: var(--text-3);
}
@media (min-width: 60rem) {
  .constat__after {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    column-gap: var(--s-8);
    align-items: start;
  }
}
/* Affiche et vidéo superposées : l'affiche (image paresseuse) tient la place, la vidéo se
 * révèle quand elle joue (.is-playing, posée par site.js). */
.film__poster,
.film__poster img,
[data-film] video {
  position: absolute;
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
[data-film] video {
  opacity: 0;
  transition: opacity var(--dur-3) var(--ease-out);
}
[data-film].is-playing video {
  opacity: 1;
}

/* Bouton pause des boucles vidéo (WCAG 2.2.2) : posé par site.js, qui seul lance la lecture. */
.film__toggle {
  position: absolute;
  right: var(--s-4);
  bottom: var(--s-4);
  z-index: 2;
  display: grid;
  place-items: center;
  width: 2.75rem;
  height: 2.75rem;
  padding: 0;
  border: 1px solid var(--hair-2);
  border-radius: 50%;
  background: rgb(5 7 11 / 0.55);
  color: var(--text);
  cursor: pointer;
  transition: border-color var(--dur-1) var(--ease-out);
}
.film__toggle:hover {
  border-color: var(--cyan);
}
.film__toggle svg {
  width: 1.1rem;
  height: 1.1rem;
  fill: none;
  stroke: currentColor;
  stroke-width: 2.2;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.film__toggle .i-play {
  display: none;
  fill: currentColor;
}
.film__toggle[data-state="paused"] .i-play {
  display: block;
}
.film__toggle[data-state="paused"] .i-pause {
  display: none;
}

/* ---- Séquences d'images pilotées par le défilement ------------------------------------------ */
/* Sans .motion : l'image finale (affiche) puis les textes, l'un sous l'autre. Avec .motion : la
 * scène s'épingle, site.js dessine dans le <canvas> l'image qui correspond au défilement (et à la
 * souris sur grand écran) et fait passer les textes un à un. */
.seq {
  position: relative;
  background: var(--ink);
}
.seq__media {
  position: relative;
  aspect-ratio: 16 / 9;
  overflow: hidden;
  background: var(--ink-2);
}
.seq__poster,
.seq__poster img,
.seq__canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}
.seq__poster img {
  object-fit: cover;
}
.seq__canvas {
  display: none;
}
.seq__beats {
  display: grid;
  gap: var(--s-6);
  padding-block: var(--s-7) var(--s-5);
}
.beat--small {
  display: grid;
  gap: var(--s-4);
  font-size: var(--t-quote);
  font-style: italic;
  font-weight: 780;
  font-stretch: 108%;
  line-height: 1.04;
  letter-spacing: -0.01em;
  text-wrap: balance;
  max-width: 22ch;
}
.beat--small .label {
  font-style: normal;
  font-size: var(--t-label);
  letter-spacing: 0.16em;
}
.beat--title,
.beat--intro {
  display: grid;
  gap: var(--s-5);
  max-width: 58rem;
}
.beat--intro .display,
.beat--title .display {
  font-size: clamp(2.25rem, 1rem + 4.2vw, 5.25rem);
}
.beat .lead {
  color: #d3dbe4;
}
.seq__bar {
  display: none;
}
@media (max-aspect-ratio: 4/5) {
  .seq__media {
    aspect-ratio: 9 / 16;
    max-height: 90svh;
  }
}

.motion .seq--reveal {
  height: 230vh;
  height: 230svh;
}
.motion .seq--road {
  height: 320vh;
  height: 320svh;
}
.motion .seq__pin {
  position: sticky;
  top: 0;
  height: 100vh;
  height: 100svh;
  overflow: hidden;
  isolation: isolate;
}
.motion .seq__media {
  position: absolute;
  inset: 0;
  z-index: -1;
  aspect-ratio: auto;
  max-height: none;
  opacity: 0;
}
/* Avec .motion, l'affiche (la dernière image) ne s'affiche que si aucune image de la séquence ne
 * vient (.is-static) : la première image dessinée entre en fondu (.is-live), sans saut depuis
 * une autre image. */
.motion .seq__poster {
  display: none;
}
.motion .seq.is-static .seq__poster {
  display: block;
}
.motion .seq__canvas {
  display: block;
  transform: scale(1.04);
  opacity: 0;
  transition: opacity 0.7s var(--ease-out);
}
.motion .seq.is-live .seq__canvas {
  opacity: 1;
}
.motion .seq__media::after {
  content: "";
  position: absolute;
  inset: 0;
  background:
    linear-gradient(180deg, rgb(5 7 11 / 0.55) 0%, rgb(5 7 11 / 0) 18%),
    linear-gradient(0deg, rgb(5 7 11 / 0.88) 0%, rgb(5 7 11 / 0.5) 26%, rgb(5 7 11 / 0) 52%),
    linear-gradient(90deg, rgb(5 7 11 / 0.55) 0%, rgb(5 7 11 / 0) 50%);
}
/* La route du chapitre 04 roule sous un ciel clair : voile plus dense à gauche et en bas. */
.motion .seq--road .seq__media::after {
  background:
    linear-gradient(180deg, rgb(5 7 11 / 0.55) 0%, rgb(5 7 11 / 0) 18%),
    linear-gradient(0deg, rgb(5 7 11 / 0.92) 0%, rgb(5 7 11 / 0.68) 34%, rgb(5 7 11 / 0) 64%),
    linear-gradient(90deg, rgb(5 7 11 / 0.78) 0%, rgb(5 7 11 / 0.4) 38%, rgb(5 7 11 / 0) 62%);
}
.seq .label,
.vision__text .label {
  color: var(--text);
}
.motion .seq__beats {
  position: absolute;
  inset: 0;
  z-index: 1;
  display: block;
  padding: 0;
}
/* Pendant qu'une séquence entre ou sort en glissant, son bord se fond dans l'encre (--et en haut,
 * --eb en bas, écrits par site.js, 0 une fois épinglée) : l'image arrive en fondu, sans bord net
 * et sans défilement noir avant elle. */
.motion .seq__pin::before,
.motion .seq__pin::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  height: 45%;
  pointer-events: none;
}
.motion .seq__pin::before {
  top: 0;
  background: linear-gradient(180deg, var(--ink), rgb(5 7 11 / 0));
  opacity: var(--et, 0);
}
.motion .seq__pin::after {
  bottom: 0;
  background: linear-gradient(0deg, var(--ink), rgb(5 7 11 / 0));
  opacity: var(--eb, 0);
}
.motion .beat {
  position: absolute;
  left: var(--gutter);
  right: var(--gutter);
  bottom: clamp(3.5rem, 11vh, 7rem);
  opacity: 0;
  pointer-events: none;
}
.motion .seq__bar {
  position: absolute;
  left: max(var(--gutter), calc((100% - var(--wrap)) / 2 + var(--gutter)));
  right: max(var(--gutter), calc((100% - var(--wrap)) / 2 + var(--gutter)));
  bottom: clamp(1.5rem, 4vh, 2.5rem);
  display: block;
  height: 2px;
  background: var(--hair);
}
.motion .seq__bar i {
  position: absolute;
  inset: 0;
  background: var(--signal);
  transform-origin: 0 50%;
  transform: scaleX(0);
  box-shadow: 0 0 12px rgb(61 227 255 / 0.5);
}
.reponse .voix__grid {
  padding-block: var(--s-9) var(--s-8);
}

/* ---- 04 L'anticipation : les annonces du casque -------------------------------------------- */
.alerts {
  display: grid;
  gap: var(--s-4);
}
.alert {
  display: grid;
  gap: var(--s-2);
  max-width: 34rem;
  padding: var(--s-5);
  border-left: 3px solid var(--amber);
  border-radius: 0 var(--r-2) var(--r-2) 0;
  background: rgb(5 7 11 / 0.72);
}
.alert__type {
  font-size: var(--t-label);
  font-weight: 700;
  font-stretch: 85%;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--amber);
}
.alert q {
  font-size: clamp(1.6rem, 1rem + 2.4vw, 3rem);
  font-style: italic;
  font-weight: 800;
  font-stretch: 106%;
  line-height: 1.05;
  letter-spacing: -0.01em;
}
.alert p {
  font-size: var(--t-small);
  color: var(--text-2);
}
.motion .alerts {
  position: static;
}
.motion .alert {
  right: auto;
  width: min(34rem, calc(100% - 2 * var(--gutter)));
}
/* Au téléphone, le cadre portrait met la route et ses chevrons en bas : les annonces montent
 * dans le ciel pour ne pas les couvrir. */
@media (max-aspect-ratio: 4/5) {
  .motion .alert {
    top: calc(var(--header-h) + 3vh);
    bottom: auto;
  }
}

/* ---- 02 Guidage : la voix devient le tracé ------------------------------------------------------ */
/* Carte dessinée pour le site (route en lacets, routes secondaires, courbes de niveau). Avec
 * .motion, la scène s'épingle : les lignes de la voix (onde de la phrase dite) convergent en un
 * tracé qui épouse la route, puis la flèche de navigation le parcourt (site.js). Sans .motion :
 * l'état final, tracé posé, flèche à l'arrivée, les trois phrases l'une sous l'autre. */
.route {
  position: relative;
  background: var(--ink);
}
.route__pin {
  display: grid;
  gap: var(--s-7);
  padding-block: var(--s-8);
}
.route__text {
  display: grid;
  gap: var(--s-6);
  align-content: center;
}
.route__beat {
  display: grid;
  gap: var(--s-4);
}
.route__say {
  font-size: clamp(1.5rem, 1rem + 1.8vw, 2.6rem);
  font-style: italic;
  font-weight: 720;
  font-stretch: 104%;
  line-height: 1.1;
  text-wrap: balance;
  max-width: 24ch;
}
.route__beat--shot {
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: end;
  column-gap: var(--s-5);
}
/* .route .route__shot : la règle .phone, plus bas, fixerait sinon sa largeur à min(100%, 22rem),
 * qui dans une colonne « auto » s'effondre. */
.route .route__shot {
  width: 7rem;
  padding: 0.3rem;
  border-radius: 1.2rem;
}
.route__shot .phone__screen {
  border-radius: 1.1rem;
}
/* Ce que dit le casque pendant que la flèche roule : les vraies annonces de l'application, en ambre
 * comme celles du chapitre 04. Avec .motion, l'annonce du moment passe en blanc (site.js, d'après
 * la position de la flèche), les autres restent en --text-3 : jamais d'opacité sur du texte. */
.route__calls {
  grid-column: 1 / -1;
  display: grid;
  margin-top: var(--s-4);
  border-top: 1px solid var(--hair);
}
.route__calls li {
  display: grid;
  gap: var(--s-1);
  padding: var(--s-3) 0 var(--s-3) var(--s-4);
  border-bottom: 1px solid var(--hair);
  border-left: 3px solid var(--amber);
  transition:
    color var(--dur-2) var(--ease-out),
    border-color var(--dur-2) var(--ease-out);
}
.route__call-type {
  font-size: var(--t-label);
  font-weight: 700;
  font-stretch: 85%;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--amber);
}
.route__calls q {
  font-size: clamp(1.05rem, 0.9rem + 0.5vw, 1.3rem);
  font-style: italic;
  font-weight: 720;
  line-height: 1.2;
}
.motion .route__calls li {
  border-left-color: var(--hair-2);
  color: var(--text-3);
}
.motion .route__calls li .route__call-type {
  color: var(--text-3);
}
.motion .route__calls li.is-on {
  border-left-color: var(--amber);
  color: var(--text);
}
.motion .route__calls li.is-on .route__call-type {
  color: var(--amber);
}
.route__ping {
  fill: none;
  stroke: var(--amber);
  stroke-width: 3;
  opacity: 0;
}
.route__map {
  position: relative;
  width: min(100%, 44rem);
  aspect-ratio: 1;
  margin: 0;
  overflow: hidden;
  border-radius: var(--r-2);
  background: #05080d;
  box-shadow:
    inset 0 0 0 1px var(--hair),
    0 40px 90px -40px rgb(0 0 0 / 0.9);
}
.route__map svg {
  display: block;
  width: 100%;
  height: 100%;
}
.map__contours path {
  fill: none;
  stroke: rgb(140 170 200 / 0.1);
  stroke-width: 1.5;
}
.map__side path {
  fill: none;
  stroke: #222d3b;
  stroke-width: 8;
  stroke-linecap: round;
}
.map__road-edge,
.map__road,
.map__lane,
.route__line,
.route__glow,
.route__ghost,
.route__done {
  fill: none;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.map__road-edge {
  stroke: #3a4859;
  stroke-width: 38;
}
.map__road {
  stroke: #141c26;
  stroke-width: 31;
}
.map__lane {
  stroke: rgb(238 242 246 / 0.22);
  stroke-width: 1.6;
  stroke-dasharray: 10 14;
}
.map__dest circle {
  fill: var(--ink);
  stroke: var(--mint);
  stroke-width: 5;
}
.map__dest text {
  fill: var(--text);
  font-family: var(--font);
  font-size: 30px;
  font-style: italic;
  font-weight: 720;
}
.route__line {
  stroke: url(#route-gradient);
  stroke-width: 9;
}
.route__glow {
  stroke: var(--cyan);
  stroke-width: 26;
  stroke-opacity: 0.16;
}
.route__ghost {
  stroke: var(--mint);
  stroke-width: 3;
  opacity: 0;
}
.route__done {
  stroke: rgb(5 7 11 / 0.55);
  stroke-width: 11;
  stroke-dasharray: 0 1;
}
.route__guide {
  fill: none;
  stroke: none;
}
.route__puck circle {
  fill: rgb(61 227 255 / 0.18);
  stroke: rgb(61 227 255 / 0.55);
  stroke-width: 2;
}
.route__puck path {
  fill: var(--text);
  stroke: var(--ink);
  stroke-width: 3;
  stroke-linejoin: round;
}
@media (min-width: 60rem) {
  .route__pin {
    grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.15fr);
    column-gap: var(--s-8);
    align-items: center;
  }
  .route__map {
    justify-self: end;
  }
}
.motion .route {
  height: 230vh;
  height: 230svh;
}
.motion .route__pin {
  position: sticky;
  top: 0;
  height: 100vh;
  height: 100svh;
  padding-block: calc(var(--header-h) + 3vh) 4vh;
}
.motion .route__text {
  position: relative;
  display: block;
  min-height: 20rem;
}
.motion .route__beat {
  position: absolute;
  inset: 50% 0 auto;
  translate: 0 -50%;
  opacity: 0;
  pointer-events: none;
}
.motion .route__map {
  width: auto;
  height: min(80vh, 52rem);
}
/* Au téléphone : la carte en haut, les phrases dessous. */
@media (max-aspect-ratio: 4/5) {
  .motion .route__pin {
    grid-template-rows: auto minmax(0, 1fr);
    align-content: start;
    gap: var(--s-5);
  }
  .motion .route__map {
    order: -1;
    justify-self: center;
    width: min(100%, 54vh);
    height: auto;
  }
  .motion .route__beat {
    inset: 0 0 auto;
    translate: none;
  }
  .route__shot {
    display: none;
  }
  .route__beat--shot {
    grid-template-columns: minmax(0, 1fr);
  }
  .motion .route__calls li:not(.is-on) {
    display: none;
  }
  .motion .route__calls:not(.has-on) li:first-child {
    display: grid;
  }
}

/* ---- 02 La réponse : quatre phrases, téléphone collant -------------------------------------- */
.phone {
  position: relative;
  width: min(100%, 22rem);
  aspect-ratio: 752 / 1582;
  padding: 0.6rem;
  border-radius: 2.75rem;
  background:
    linear-gradient(145deg, #232b37, #0b0f15 38%, #0b0f15 62%, #1a212c);
  box-shadow:
    inset 0 0 0 1px rgb(255 255 255 / 0.1),
    0 40px 80px -30px rgb(0 0 0 / 0.9),
    0 0 120px -40px rgb(61 227 255 / 0.35);
  box-sizing: content-box;
}
.phone__screen {
  position: relative;
  width: 100%;
  height: 100%;
  overflow: hidden;
  border-radius: 2.2rem;
  background: #071019;
}
.phone__screen picture,
.phone__screen img {
  width: 100%;
  height: 100%;
}
.phone__screen img {
  object-fit: cover;
}
.phone__screen > picture {
  position: absolute;
  inset: 0;
  transition:
    opacity var(--dur-3) var(--ease-out),
    transform var(--dur-3) var(--ease-out);
}
.phone__screen > picture[aria-hidden="true"] {
  opacity: 0;
  transform: scale(1.03);
}

.steps {
  display: grid;
  gap: var(--s-8);
}
.step {
  display: grid;
  gap: var(--s-5);
}
.step__tag {
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
  font-size: var(--t-label);
  font-weight: 600;
  font-stretch: 85%;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--mint);
}
.step__wave {
  width: 3.25rem;
  height: 1.25rem;
  color: var(--mint);
}
.step__wave path {
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
}
.step__shot {
  width: min(72vw, 18rem);
  margin-top: var(--s-3);
}
.step__shot .phone {
  width: 100%;
}
.voix__stage {
  display: none;
}

@media (min-width: 60rem) {
  .voix__grid {
    display: grid;
    grid-template-columns: minmax(0, 1.1fr) minmax(0, 0.9fr);
    column-gap: var(--s-8);
  }
  /* La dernière phrase ne garde pas d'écran vide sous elle : 508 px de noir la séparaient du
   * chapitre des boutons à 1440 px (2026-10-14). */
  .reponse .voix__grid {
    padding-bottom: 0;
  }
  .step:last-child {
    min-height: 0;
    padding-top: 18vh;
  }
  .steps {
    gap: 0;
  }
  .step {
    min-height: 72vh;
    align-content: center;
    transition: opacity var(--dur-3) var(--ease-out);
  }
  /* La phrase lue reste blanche, les autres passent en gris : jamais d'opacité, les contrastes
   * restent ceux de --text-3 (6,4:1). */
  .js .step .quote {
    transition: color var(--dur-3) var(--ease-out);
  }
  .js .step:not(.is-active) .quote {
    color: var(--text-3);
  }
  .step__shot {
    display: none;
  }
  .voix__stage {
    position: sticky;
    top: calc(var(--header-h) + 4vh);
    height: calc(100vh - var(--header-h) - 8vh);
    display: grid;
    place-items: center;
  }
  .voix__stage .phone {
    height: min(100%, 44rem);
    width: auto;
  }
}

/* Avec .motion, les trois phrases forment une scène épinglée (data-voix) : le téléphone reste fixe,
 * les phrases se relaient sur place selon la progression (data-in, data-out, site.js), et l'écran
 * du téléphone change avec elles. Avant le 2026-10-14, le téléphone collait puis repartait au
 * milieu de la dernière phrase, à des rythmes inégaux (retour du 2026-10-14 : « ça fait un peu n'importe quoi »). */
.motion .voix {
  height: 280vh;
  height: 280svh;
}
.motion .voix .voix__grid {
  position: sticky;
  top: 0;
  height: 100vh;
  height: 100svh;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  grid-template-rows: auto minmax(0, 1fr);
  align-content: start;
  gap: var(--s-5);
  padding-block: calc(var(--header-h) + 2vh) 3vh;
}
.motion .voix .steps {
  position: relative;
  display: block;
  height: 100%;
}
.motion .voix .step {
  position: absolute;
  inset: 0 0 auto;
  min-height: 0;
  padding: 0;
  opacity: 0;
  pointer-events: none;
  transition: none;
}
.motion .voix .step .quote {
  color: var(--text);
}
.motion .voix .step__shot {
  display: none;
}
.motion .voix .voix__stage {
  order: -1;
  position: relative;
  top: auto;
  display: grid;
  place-items: center;
  height: auto;
}
.motion .voix .voix__stage .phone {
  height: min(44vh, 44svh, 26rem);
  width: auto;
}
@media (max-height: 700px) {
  .motion .voix .voix__stage .phone {
    height: 36svh;
  }
}
@media (min-width: 60rem) {
  .motion .voix .voix__grid {
    grid-template-columns: minmax(0, 1.1fr) minmax(0, 0.9fr);
    grid-template-rows: minmax(0, 1fr);
    align-content: stretch;
    padding-block: calc(var(--header-h) + 4vh) 4vh;
  }
  .motion .voix .step {
    inset: 50% 0 auto;
    translate: 0 -50%;
  }
  .motion .voix .voix__stage {
    order: 0;
    height: 100%;
  }
  .motion .voix .voix__stage .phone {
    height: min(100%, 44rem);
  }
}

/* ---- 03 Les boutons de l'intercom ---------------------------------------------------------- */
.presses {
  display: grid;
  border-top: 1px solid var(--hair);
}
.press {
  display: grid;
  grid-template-columns: 5.5rem 1fr;
  align-items: center;
  gap: var(--s-4);
  padding: var(--s-4) 0;
  border-bottom: 1px solid var(--hair);
  color: var(--text-2);
}
.press__dots {
  display: flex;
  gap: 6px;
}
.press__dots i {
  width: 12px;
  height: 12px;
  border-radius: 50%;
  border: 1.5px solid var(--text-3);
}
.press__dots i.long {
  width: 44px;
  border-radius: 6px;
}
.press strong {
  display: block;
  color: var(--text);
  font-weight: 650;
}
.press--key {
  color: var(--text);
}
.press--key .press__dots i {
  border-color: var(--mint);
  background: var(--mint);
  box-shadow: 0 0 10px rgb(55 233 196 / 0.55);
}
@media (prefers-reduced-motion: no-preference) {
  .press--key.is-in .press__dots i {
    animation: tap 2.4s var(--ease-out) infinite;
  }
  .press--key.is-in .press__dots i:nth-child(2) {
    animation-delay: 160ms;
  }
  .press--key.is-in .press__dots i:nth-child(3) {
    animation-delay: 320ms;
  }
}
.intercom {
  display: grid;
  gap: var(--s-7);
}
@media (min-width: 60rem) {
  .intercom {
    grid-template-columns: minmax(0, 1.1fr) minmax(0, 0.9fr);
    column-gap: var(--s-8);
    align-items: end;
  }
  .intercom .chapter__head {
    margin-bottom: 0;
  }
}


/* ---- 05 La virée : la ligne posée sur une vraie route ------------------------------------- */
/* L'image entière à toute largeur, pour que la ligne de la virée se voie d'un bout à l'autre : au
 * téléphone, le cadre portrait d'avant (4:5) en coupait la moitié. */
.viree__media {
  position: relative;
  margin: 0;
}
.viree__canvas {
  position: relative;
  width: 100%;
  aspect-ratio: 16 / 9;
  overflow: hidden;
  border-radius: var(--r-2);
  background: var(--ink-2);
}
.viree__canvas picture,
.viree__canvas img,
.viree__canvas svg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}
.viree__canvas::after {
  content: "";
  position: absolute;
  inset: 0;
  background: url("/img/grain.webp") 0 0 / 128px 128px;
  opacity: 0.07;
  mix-blend-mode: overlay;
}
.viree__line {
  fill: none;
  stroke: url(#viree-gradient);
  stroke-width: 7;
  stroke-linecap: round;
  stroke-linejoin: round;
  stroke-dasharray: 1;
  stroke-dashoffset: calc(1 - var(--p, 1));
  filter: drop-shadow(0 0 10px rgb(61 227 255 / 0.65));
}
.viree__puck {
  fill: var(--text);
  opacity: var(--p, 1);
}
.readouts {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 13rem), 1fr));
  margin-top: var(--s-7);
  border-top: 1px solid var(--hair);
}
.readout {
  display: grid;
  gap: var(--s-2);
  align-content: start;
  padding: var(--s-5) var(--s-5) var(--s-5) 0;
  border-bottom: 1px solid var(--hair);
}
.readout dt {
  font-size: clamp(1.5rem, 1.1rem + 1.4vw, 2.25rem);
  font-weight: 820;
  font-style: italic;
  font-stretch: 108%;
  line-height: 1.05;
  font-variant-numeric: tabular-nums;
}
.readout dd {
  font-size: var(--t-small);
  color: var(--text-2);
}
.viree__note {
  margin-top: var(--s-6);
}
@media (min-width: 40rem) {
  .readout + .readout {
    padding-left: var(--s-5);
    border-left: 1px solid var(--hair);
  }
}
@media (min-width: 60rem) {
  .viree__intro {
    display: grid;
    grid-template-columns: minmax(0, 1.1fr) minmax(0, 0.9fr);
    column-gap: var(--s-8);
    align-items: end;
  }
}

/* ---- 06 Le tableau de bord ----------------------------------------------------------------- */
.cockpit {
  display: grid;
  gap: var(--s-8);
}
.cockpit__phones {
  position: relative;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--s-4);
  align-items: start;
  max-width: 34rem;
}
.cockpit__phones .phone {
  width: 100%;
  padding: 0.45rem;
  border-radius: 2rem;
}
.cockpit__phones .phone__screen {
  border-radius: 1.6rem;
}
.cockpit__phones .phone:nth-child(1) {
  transform: translate3d(0, calc((var(--p, 0.5) - 0.5) * -6rem), 0);
}
.cockpit__phones .phone:nth-child(2) {
  margin-top: 4rem;
  transform: translate3d(0, calc((var(--p, 0.5) - 0.5) * 4rem), 0);
}
.specs {
  display: grid;
  border-top: 1px solid var(--hair);
}
.specs div {
  display: grid;
  gap: var(--s-1);
  padding: var(--s-4) 0;
  border-bottom: 1px solid var(--hair);
}
.specs dt {
  font-weight: 700;
  font-stretch: 105%;
}
.specs dd {
  color: var(--text-2);
}
@media (min-width: 60rem) {
  .cockpit {
    grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr);
    column-gap: var(--s-8);
    align-items: center;
  }
  .cockpit__phones {
    order: -1;
  }
  .cockpit .chapter__head {
    margin-bottom: var(--s-6);
  }
}

/* ---- 07 La sécurité ------------------------------------------------------------------------ */
.chapter--sos {
  background:
    radial-gradient(ellipse 70% 60% at 78% 40%, rgb(224 32 46 / 0.22), rgb(224 32 46 / 0) 70%),
    var(--sos-ink);
}
.chapter--sos .label .km::after {
  background: var(--sos);
}
.sos {
  display: grid;
  gap: var(--s-8);
}
.countdown {
  position: relative;
  display: grid;
  place-items: center;
  width: min(78vw, 22rem);
  aspect-ratio: 1;
}
.countdown svg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  transform: rotate(-90deg);
}
.countdown circle {
  fill: none;
  stroke-width: 3;
}
.countdown .track {
  stroke: rgb(255 133 145 / 0.18);
}
.countdown .sweep {
  stroke: var(--sos);
  stroke-linecap: round;
  stroke-dasharray: 1;
  stroke-dashoffset: calc(var(--p, 0) * 1);
}
.countdown__value {
  display: grid;
  justify-items: center;
  gap: var(--s-1);
  text-align: center;
}
.countdown__value b {
  font-size: clamp(3.5rem, 2rem + 6vw, 6rem);
  font-weight: 860;
  font-style: italic;
  font-stretch: 110%;
  line-height: 0.9;
  font-variant-numeric: tabular-nums;
}
.countdown__value span {
  font-size: var(--t-small);
  color: var(--text-2);
}
.sos__list {
  display: grid;
  border-top: 1px solid rgb(255 133 145 / 0.2);
}
.sos__list li {
  padding: var(--s-4) 0;
  border-bottom: 1px solid rgb(255 133 145 / 0.2);
  color: var(--text-2);
}
.sos__list strong {
  color: var(--text);
}
.urgence {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: var(--s-4);
  align-items: center;
  max-width: var(--measure);
  padding: var(--s-5);
  border: 1px solid rgb(255 133 145 / 0.45);
  border-radius: var(--r-2);
  background: rgb(255 90 106 / 0.06);
}
.urgence b {
  font-size: 2.25rem;
  font-weight: 860;
  font-stretch: 110%;
  font-style: italic;
  color: #ff8591;
  line-height: 1;
}
.urgence p {
  font-size: var(--t-small);
  color: var(--text);
}
@media (min-width: 60rem) {
  .sos {
    grid-template-columns: minmax(0, 1.15fr) minmax(0, 0.85fr);
    column-gap: var(--s-8);
    align-items: center;
  }
  .sos .chapter__head {
    margin-bottom: var(--s-6);
  }
  .sos__visual {
    display: grid;
    justify-items: center;
    gap: var(--s-6);
  }
}
.sos__visual {
  display: grid;
  gap: var(--s-6);
  justify-items: start;
}

/* ---- Vision : un motard file dans le désert ---------------------------------------------------- */
.vision {
  position: relative;
  display: grid;
  align-content: end;
  min-height: 100vh;
  min-height: 100svh;
  overflow: hidden;
  isolation: isolate;
  background: var(--ink-2);
}
.vision__film {
  position: absolute;
  inset: 0;
  z-index: 0;
}
/* Retournée gauche-droite : le motard file à droite de l'écran, loin du texte posé à gauche. */
.vision__film video,
.vision__film .film__poster img {
  object-position: 66% 50%;
  transform: scaleX(-1);
}
.vision__film::after {
  content: "";
  position: absolute;
  inset: 0;
  background:
    linear-gradient(180deg, var(--ink) 0%, rgb(5 7 11 / 0.3) 22%, rgb(5 7 11 / 0) 40%),
    linear-gradient(0deg, rgb(5 7 11 / 0.95) 0%, rgb(5 7 11 / 0.78) 40%, rgb(5 7 11 / 0) 74%),
    linear-gradient(90deg, rgb(5 7 11 / 0.6) 0%, rgb(5 7 11 / 0) 55%);
}
.vision__film .film__toggle {
  top: calc(var(--header-h) + var(--s-4));
  bottom: auto;
  right: var(--gutter);
}
.vision__text {
  position: relative;
  z-index: 1;
  padding-block: var(--s-9) var(--s-8);
}
/* Au téléphone, la vidéo garde le haut de l'écran et le texte passe dessous. */
@media (max-aspect-ratio: 4/5) {
  .vision {
    display: block;
    min-height: 0;
  }
  .vision__film {
    position: relative;
    height: 62vh;
    height: 62svh;
  }
  .vision__film video,
  .vision__film .film__poster img {
    object-position: 50% 60%;
  }
  .vision__text {
    margin-top: -6rem;
    padding-top: 0;
  }
}
/* Liste des modules : le nom DESSINÉ de chaque module (fichiers de marque de l'application, jamais
 * une police ni un texte en dégradé), sous lequel une ligne dit s'il existe, comme les cartes
 * « Bientôt » de l'écran des modes de l'application (AppSuiteScreen). Tous à la même hauteur. */
.modlist {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--s-3);
  margin-block: var(--s-6);
}
.modlist__card {
  display: grid;
  justify-items: center;
  align-content: center;
  gap: var(--s-3);
  min-height: 8rem;
  padding: var(--s-5) var(--s-3);
  border: 1px solid var(--hair-2);
  border-radius: var(--r-2);
  background: rgb(10 13 19 / 0.72);
  text-decoration: none;
}
.modlist__card img {
  width: auto;
  max-width: none;
  height: clamp(1.4rem, 3.2vw, 2.4rem);
}
.modlist__card span {
  font-size: var(--t-small);
  font-weight: 600;
  color: var(--text-2);
}
/* Le module qu'on peut prendre : bordure au dégradé de marque, comme le bandeau du menu de
 * l'application (MenuModeBanner). */
.modlist .is-now .modlist__card {
  border: 1.5px solid transparent;
  background:
    linear-gradient(rgb(10 13 19 / 0.92), rgb(10 13 19 / 0.92)) padding-box,
    var(--signal) border-box;
}
.modlist .is-now .modlist__card span {
  color: var(--mint);
}
a.modlist__card:hover span,
a.modlist__card:focus-visible span {
  color: var(--text);
  text-decoration: underline;
  text-decoration-color: var(--mint);
}
@media (min-width: 48rem) {
  .modlist {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }
}

/* « VOKPIT MOTO » dessiné : deux fichiers de marque à la même hauteur, à 0,35 fois cette hauteur
 * l'un de l'autre (ModeLockup de l'application). */
.lockup {
  --lh: clamp(1.4rem, 0.9rem + 2.4vw, 2.8rem);
  display: flex;
  align-items: center;
  gap: calc(var(--lh) * 0.35);
}
.lockup img {
  width: auto;
  max-width: none;
  height: var(--lh);
}

/* ---- Accueil : le hub des modules (2026-10-14) --------------------------------------------------
 * VOKPIT est une base gratuite et des modules vendus, un par sport ; l'accueil présente la base et
 * le catalogue, chaque module a sa page (/moto). Mêmes encres, même police, mêmes composants que la
 * page MOTO. */

/* Ouverture : ciel, logotype et montagnes de la page MOTO, sans le motard ni le sol. La route que
 * porte encore le plan des montagnes disparaît sous l'encre ; le texte s'y pose. Plus courte que
 * celle de la page MOTO (20 % de fenêtre de course), et fondue à moitié seulement
 * (data-hero-soft). La base remonte PAR-DESSUS ses 20 derniers % (plus bas) : son titre entre
 * dès que le texte de l'ouverture s'efface. Mesuré le 2026-10-14 à 1440 x 900 : avec une
 * ouverture de 135 % et une base posée après, 440 px de défilement sans aucun texte. */
.motion .hero--hub {
  height: 120vh;
  height: 120svh;
}
.hero--hub .hero__stage {
  background: var(--ink);
}
.hero--hub .hero__veil {
  background:
    linear-gradient(180deg, rgb(5 7 11 / 0.5) 0%, rgb(5 7 11 / 0) 14%),
    linear-gradient(0deg, var(--ink) 0%, var(--ink) 34%, rgb(5 7 11 / 0.82) 46%, rgb(5 7 11 / 0) 64%),
    linear-gradient(90deg, rgb(5 7 11 / 0.55) 0%, rgb(5 7 11 / 0) 46%);
}
@media (min-aspect-ratio: 3/2) {
  .hero--hub .hero__frame {
    --S: 1.12;
    --fy: 0.3;
    left: calc((100cqw - var(--cover) * var(--S)) * 0.5);
  }
}
@media (max-aspect-ratio: 3/2) {
  .hero--hub .hero__veil {
    background:
      linear-gradient(180deg, rgb(5 7 11 / 0.5) 0%, rgb(5 7 11 / 0) 14%),
      linear-gradient(0deg, var(--ink) 0%, var(--ink) 42%, rgb(5 7 11 / 0.8) 54%, rgb(5 7 11 / 0) 70%);
  }
}

/* La base : son titre, l'écran SOS et ce qu'elle donne. Au téléphone, dans cet ordre ; sur grand
 * écran, le téléphone à gauche, CENTRÉ sur la hauteur du texte (les rangées 1fr du haut et du bas
 * absorbent l'écart, que le texte soit plus court ou plus long que le téléphone). Avec le
 * mouvement, elle remonte sur la fin de l'ouverture, là où son voile est déjà à l'encre. */
.chapter.base {
  z-index: 2;
  padding-top: var(--s-8);
}
.motion .chapter.base {
  margin-top: -20vh;
  margin-top: -20svh;
  padding-top: var(--s-6);
  background: linear-gradient(180deg, rgb(5 7 11 / 0) 0, var(--ink) 20vh);
  background: linear-gradient(180deg, rgb(5 7 11 / 0) 0, var(--ink) 20svh);
}
.base__in {
  display: grid;
  gap: var(--s-6);
}
.base__head {
  margin-bottom: 0;
}
.base__phone {
  justify-self: center;
  width: min(72vw, 20rem);
  margin-block: var(--s-4);
}
.base__phone .phone {
  width: 100%;
}
@media (min-width: 60rem) {
  .base__in {
    grid-template-columns: minmax(0, 0.8fr) minmax(0, 1.2fr);
    grid-template-rows: 1fr auto auto 1fr;
    grid-template-areas:
      "phone ."
      "phone head"
      "phone specs"
      "phone .";
    column-gap: var(--s-8);
    row-gap: 0;
  }
  .base__head {
    grid-area: head;
    margin-bottom: var(--s-6);
  }
  .base__phone {
    grid-area: phone;
    align-self: center;
    margin-block: 0;
  }
  .base__specs {
    grid-area: specs;
  }
}
/* Grand écran : la liste en deux colonnes, pour que le texte ait à peu près la hauteur du téléphone. */
@media (min-width: 75rem) {
  .base__specs {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    column-gap: var(--s-6);
    border-top: 0;
  }
  .base__specs div {
    align-content: start;
  }
  .base__specs div:nth-child(-n + 2) {
    border-top: 1px solid var(--hair);
  }
}

/* L'écran SOS mis en scène comme le chapitre Sécurité de la page MOTO : halo rouge, anneau du compte
 * à rebours autour du bouton (son centre est à 50 % et 24,4 % de la capture, son halo gris fait 54 %
 * de sa largeur), deux ondes qui en partent, et la puce « 2:00 pour annuler » qui flotte au bord.
 * site.js (data-scene) écrit --p au défilement : l'anneau se vide, la puce décompte, le téléphone
 * pivote à peine. Sans script ni mouvement : anneau plein, 2:00, téléphone de face, ondes absentes. */
.sosphone {
  position: relative;
  isolation: isolate;
}
.sosphone::before {
  content: "";
  position: absolute;
  z-index: -1;
  inset: 2% -12% 30%;
  background: radial-gradient(closest-side, rgb(255 60 80 / 0.3), rgb(255 60 80 / 0));
  pointer-events: none;
}
.sosphone .phone {
  box-shadow:
    inset 0 0 0 1px rgb(255 255 255 / 0.1),
    0 40px 80px -30px rgb(0 0 0 / 0.9),
    0 0 120px -30px rgb(255 90 106 / 0.5);
}
.motion .sosphone__device {
  transform: perspective(1400px) rotateY(calc((var(--p, 0.5) - 0.5) * -16deg))
    rotateX(calc((var(--p, 0.5) - 0.5) * 6deg));
  will-change: transform;
}
.sosphone__ring,
.sosphone__pulse {
  position: absolute;
  left: 50%;
  top: 24.4%;
  aspect-ratio: 1;
  pointer-events: none;
}
.sosphone__ring {
  width: 62%;
  transform: translate(-50%, -50%) rotate(-90deg);
}
.sosphone__ring circle {
  fill: none;
  stroke-width: 2.5;
}
.sosphone__ring .track {
  stroke: rgb(255 133 145 / 0.2);
}
.sosphone__ring .sweep {
  stroke: var(--sos);
  stroke-linecap: round;
  stroke-dasharray: 1;
  stroke-dashoffset: calc(var(--p, 0) * 1);
}
.sosphone__ring .sweep--glow {
  stroke-width: 8;
  opacity: 0.25;
}
.sosphone__pulse {
  width: 51%;
  transform: translate(-50%, -50%);
}
.sosphone__pulse i {
  position: absolute;
  inset: 0;
  border: 2px solid rgb(255 90 106 / 0.7);
  border-radius: 50%;
  opacity: 0;
}
@media (prefers-reduced-motion: no-preference) {
  .sosphone__pulse i {
    animation: sos-pulse 2.4s var(--ease-out) infinite;
  }
  .sosphone__pulse i + i {
    animation-delay: 1.2s;
  }
}
@keyframes sos-pulse {
  from {
    opacity: 0.8;
    transform: scale(1);
  }
  to {
    opacity: 0;
    transform: scale(1.5);
  }
}
.sosphone__chip {
  position: absolute;
  right: -9%;
  top: 27%;
  justify-items: start;
  gap: 0.15rem;
  padding: 0.6rem 0.95rem 0.7rem;
  border: 1px solid rgb(255 133 145 / 0.45);
  border-radius: var(--r-2);
  background: rgb(28 6 10 / 0.92);
  box-shadow:
    0 18px 40px -16px rgb(0 0 0 / 0.9),
    0 0 40px -12px rgb(255 90 106 / 0.6);
  text-align: left;
}
.motion .sosphone__chip {
  transform: translate3d(0, calc((var(--p, 0.5) - 0.5) * -3rem), 0);
}
.sosphone__chip b {
  font-size: clamp(1.5rem, 1.1rem + 1.2vw, 2rem);
  color: var(--text);
}
.sosphone__chip span {
  font-size: var(--t-label);
  letter-spacing: 0.08em;
  color: #ff9aa4;
}

/* Les modules : leurs noms en grand (celui qu'on peut prendre en plein, les autres au trait), puis
 * la carte du module MOTO. */
.modules .modlist {
  margin-top: 0;
}
/* Ce que débloque n'importe quel module, avant la carte du module MOTO (partage du 2026-10-14 :
 * la base gratuite, des fonctions communes à tout module payant, celles d'un seul module). */
.common {
  display: grid;
  gap: var(--s-4);
  margin-bottom: var(--s-6);
}
.common ul {
  display: grid;
  gap: var(--s-2) var(--s-6);
}
.common li {
  display: flex;
  align-items: baseline;
  gap: var(--s-3);
  color: var(--text-2);
}
.common li::before {
  content: "";
  flex: none;
  width: 0.55rem;
  height: 0.55rem;
  border-radius: 50%;
  background: var(--mint);
  transform: translateY(-0.1em);
}
@media (min-width: 48rem) {
  .common ul {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}
.modcard {
  display: grid;
  overflow: hidden;
  border: 1px solid var(--hair-2);
  border-radius: var(--r-2);
  background: var(--ink-2);
}
.modcard__photo {
  position: relative;
  aspect-ratio: 4 / 3;
  overflow: hidden;
}
/* La photo est portrait : posée en absolu, elle couvre la place que la carte lui donne, sans en
 * imposer la hauteur. */
.modcard__photo img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 45%;
}
.modcard__photo::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(0deg, var(--ink-2) 0%, rgb(5 7 11 / 0) 45%);
}
.modcard__body {
  display: grid;
  gap: var(--s-4);
  justify-items: start;
  padding: var(--s-6) var(--s-5) var(--s-6);
}
.modcard__title {
  margin-block: var(--s-1);
}
.modcard__text {
  max-width: var(--measure);
  color: var(--text-2);
  text-wrap: pretty;
}
.modcard__price {
  font-size: var(--t-small);
  color: var(--text-2);
}
.modcard__price b {
  font-size: 1.5rem;
  font-style: italic;
  font-weight: 860;
  font-stretch: 110%;
  color: var(--text);
}
.modules__note {
  margin-top: var(--s-5);
}
.chapter.modules {
  padding-bottom: var(--s-8);
}
@media (min-width: 48rem) {
  .modcard {
    grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr);
    align-items: stretch;
  }
  .modcard__photo {
    aspect-ratio: auto;
    min-height: 24rem;
  }
  .modcard__photo::after {
    background: linear-gradient(270deg, var(--ink-2) 0%, rgb(5 7 11 / 0) 40%);
  }
  .modcard__body {
    align-content: center;
    padding: var(--s-7);
  }
}

/* ---- Appel final : le motard arrive, phare allumé --------------------------------------------- */
.finale {
  position: relative;
  display: grid;
  align-content: end;
  min-height: 100vh;
  min-height: 100svh;
  overflow: hidden;
  isolation: isolate;
}
.finale__photo {
  position: absolute;
  inset: 0;
  z-index: -2;
  background: var(--ink-2);
}
.finale__photo picture,
.finale__photo img {
  width: 100%;
  height: 100%;
}
.finale__photo img {
  object-fit: cover;
  object-position: 44% 50%;
  transform: scale(calc(1.12 - var(--p, 1) * 0.12));
}
.finale::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background:
    linear-gradient(180deg, var(--ink) 0%, rgb(5 7 11 / 0) 26%),
    linear-gradient(0deg, rgb(5 7 11 / 0.94) 0%, rgb(5 7 11 / 0.6) 34%, rgb(5 7 11 / 0) 62%);
}
.finale__in {
  padding-block: var(--s-9) var(--s-8);
}
.finale .display {
  font-size: var(--t-hero);
  max-width: 14ch;
}
.finale .store-row {
  margin-top: var(--s-6);
}
.finale .note {
  margin-top: var(--s-4);
  color: var(--text-2);
}

/* ---- Fiche pratique : tarif, installation, questions, achat --------------------------------- */
.practical {
  background: var(--ink-2);
  border-top: 1px solid var(--hair);
}
.practical .chapter {
  padding-block: var(--s-8);
}
.practical .chapter + .chapter {
  border-top: 1px solid var(--hair);
}
.practical h2,
.simple-page h1 {
  font-size: clamp(1.75rem, 1.2rem + 2.4vw, 3rem);
  font-weight: 820;
  font-style: italic;
  font-stretch: 110%;
  line-height: 1;
  letter-spacing: -0.01em;
}
.split {
  display: grid;
  gap: var(--s-6);
}
.practical .chapter__head {
  align-content: start;
  margin-bottom: 0;
}
@media (min-width: 60rem) {
  .split {
    grid-template-columns: minmax(0, 0.8fr) minmax(0, 1.2fr);
    column-gap: var(--s-8);
  }
}
.plans {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--t-small);
}
.plans th,
.plans td {
  padding: var(--s-4) var(--s-3);
  border-bottom: 1px solid var(--hair);
  text-align: left;
  vertical-align: top;
}
.plans thead th {
  font-size: var(--t-label);
  font-weight: 700;
  font-stretch: 85%;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text-2);
}
.plans thead th {
  white-space: nowrap;
}
/* Les en-têtes des offres au-dessus de leurs pastilles, centrées comme elles. */
.plans thead th:not(:first-child) {
  text-align: center;
}
/* Le nom du module en tête de colonne : le nom DESSINÉ de l'application. */
.plans__logo {
  width: auto;
  max-width: none;
  height: 0.9rem;
  vertical-align: middle;
}
.plans thead th.moto,
.plans thead th.module {
  color: var(--mint);
}
.plans tbody th {
  font-weight: 500;
  color: var(--text);
}
/* Accueil : l'exemple sous « Les fonctions de son sport » (pour MOTO, son nom dessiné). */
.plans__eg {
  display: block;
  margin-top: var(--s-1);
  font-weight: 400;
  color: var(--text-2);
}
.plans__eg .plans__logo {
  display: inline-block;
  height: 0.7rem;
  vertical-align: baseline;
}
.plans td {
  text-align: center;
  width: 6.5rem;
  color: var(--text-2);
}
/* Téléphone : les en-têtes passent à la ligne et les colonnes des offres se resserrent, la place va
 * au nom des fonctions (à 390 px, « With a module » d'un seul tenant lui laissait 150 px ; à
 * 320 px, le tableau dépassait de 32 px). */
@media (max-width: 40rem) {
  .plans thead th {
    white-space: normal;
  }
  .plans td {
    width: 4.75rem;
  }
}
@media (max-width: 24rem) {
  .plans th,
  .plans td {
    padding-inline: var(--s-2);
  }
}
.plans td.yes::before {
  content: "";
  display: inline-block;
  width: 0.7rem;
  height: 0.7rem;
  border-radius: 50%;
  background: var(--mint);
}
.plans td.no::before {
  content: "";
  display: inline-block;
  width: 0.7rem;
  height: 1px;
  vertical-align: middle;
  background: var(--text-3);
}
.plans tfoot td,
.plans tfoot th {
  border-bottom: 0;
  padding-top: var(--s-5);
}
.price {
  display: grid;
  gap: var(--s-2);
}
.price b {
  font-size: clamp(2.5rem, 1.6rem + 3vw, 4rem);
  font-weight: 860;
  font-stretch: 110%;
  font-style: italic;
  line-height: 1;
}
.price span {
  color: var(--text-2);
  font-size: var(--t-small);
}

/* Les deux seuls appels : Google Play et l'App Store. Texte seul, sans logo des magasins (leurs
 * badges officiels ne s'emploient que pour une application publiée). Tant qu'une fiche n'est pas
 * publiée, build-site.sh change le lien en <span class="store-btn is-soon"> marqué « Bientôt » :
 * un appel visible, jamais un lien mort. */
.store-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-3);
}
.store-btn {
  display: inline-grid;
  grid-template-columns: auto auto;
  align-items: center;
  column-gap: var(--s-4);
  min-height: 3.75rem;
  padding: var(--s-2) var(--s-6) var(--s-2) var(--s-5);
  border: 1px solid var(--hair-2);
  border-radius: var(--r-2);
  background: rgb(5 7 11 / 0.55);
  color: var(--text);
  text-decoration: none;
  line-height: 1.1;
  transition:
    border-color var(--dur-2) var(--ease-out),
    transform var(--dur-1) var(--ease-out);
}
.store-btn__k {
  grid-column: 1;
  font-size: 0.75rem;
  letter-spacing: 0.04em;
  color: var(--text-2);
}
.store-btn__n {
  grid-column: 1;
  font-size: 1.25rem;
  font-weight: 760;
  font-stretch: 105%;
}
.store-btn__soon {
  display: none;
}
a.store-btn {
  border-color: transparent;
  background: linear-gradient(90deg, var(--mint), var(--cyan));
  color: var(--on-signal);
}
a.store-btn .store-btn__k {
  color: var(--on-signal);
}
a.store-btn:hover {
  transform: translateY(-1px);
}
a.store-btn:active {
  transform: translateY(1px);
}
.store-btn.is-soon .store-btn__soon {
  display: block;
  grid-column: 2;
  grid-row: 1 / 3;
  padding: 0.3rem 0.6rem;
  border: 1px solid var(--hair-2);
  border-radius: var(--r-pill);
  font-size: var(--t-label);
  font-weight: 650;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--mint);
}
/* Téléphones compatibles, sous les deux appels de la section Télécharger. */
.stores {
  display: grid;
  margin-top: var(--s-7);
  border-top: 1px solid var(--hair);
}
.stores li {
  display: grid;
  grid-template-columns: minmax(7rem, 10rem) 1fr;
  gap: var(--s-4);
  padding: var(--s-4) 0;
  border-bottom: 1px solid var(--hair);
  color: var(--text-2);
}
.stores strong {
  color: var(--text);
}
.chapter__head .store-row {
  margin-top: var(--s-2);
}
/* Pages simples (beta.html, credits.html) ; les trois gestes de l'installation de l'APK. */
.simple-page {
  padding-top: var(--header-h);
}
.simple-page .chapter__head .btn {
  margin-top: var(--s-2);
}
.install {
  display: grid;
  gap: var(--s-5);
  counter-reset: step;
}
.install li {
  display: grid;
  grid-template-columns: 3.5rem 1fr;
  gap: var(--s-4);
  padding-bottom: var(--s-5);
  border-bottom: 1px solid var(--hair);
  color: var(--text-2);
}
.install li::before {
  counter-increment: step;
  content: counter(step, decimal-leading-zero);
  font-size: 2rem;
  font-weight: 860;
  font-style: italic;
  font-stretch: 110%;
  line-height: 1;
  color: var(--text);
  font-variant-numeric: tabular-nums;
}
.install strong,
.install em {
  color: var(--text);
}

.faq {
  border-top: 1px solid var(--hair);
}
.faq details {
  border-bottom: 1px solid var(--hair);
}
.faq summary {
  position: relative;
  display: flex;
  align-items: center;
  min-height: 3.75rem;
  padding: var(--s-3) 3rem var(--s-3) 0;
  font-weight: 650;
  font-size: 1.0625rem;
  cursor: pointer;
  list-style: none;
}
.faq summary::-webkit-details-marker {
  display: none;
}
.faq summary::after {
  content: "";
  position: absolute;
  right: 0.75rem;
  top: 50%;
  width: 0.75rem;
  height: 0.75rem;
  border-right: 1.5px solid var(--text-2);
  border-bottom: 1.5px solid var(--text-2);
  transform: translateY(-70%) rotate(45deg);
  transition: transform var(--dur-2) var(--ease-out);
}
.faq details[open] summary::after {
  transform: translateY(-30%) rotate(-135deg);
}
.faq details p {
  padding: 0 0 var(--s-5);
  max-width: var(--measure);
  color: var(--text-2);
}

.purchase {
  display: grid;
  gap: var(--s-3);
  max-width: 48rem;
}
.purchase li {
  position: relative;
  padding-left: var(--s-5);
  color: var(--text-2);
}
.purchase li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.72em;
  width: 0.6rem;
  height: 1px;
  background: var(--mint);
}
.purchase strong,
.purchase em {
  color: var(--text);
}
.purchase a,
.prose a,
.note a,
.contact a,
.lead a,
.faq a {
  color: var(--text);
  text-decoration-color: var(--mint);
}


/* ---- Pied de page ------------------------------------------------------------------------------ */
.contact {
  display: grid;
  gap: var(--s-3);
  max-width: var(--measure);
  color: var(--text-2);
}
.site-footer {
  padding-block: var(--s-7) var(--s-6);
  border-top: 1px solid var(--hair);
  font-size: var(--t-small);
  color: var(--text-3);
}
/* Le verrouillage de la marque (pictogramme au-dessus du logotype), tel que dessiné dans le
 * fichier de marque de l'application (BrandLockup). */
.site-footer__brand {
  display: inline-flex;
  margin-bottom: var(--s-5);
}
.site-footer__brand img {
  width: auto;
  height: 4.5rem;
}
.site-footer__features {
  margin-bottom: var(--s-2);
}
.site-footer__features a {
  font-weight: 600;
}
.site-footer nav ul {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2) var(--s-5);
}
.site-footer nav a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  color: var(--text-2);
  text-decoration: none;
}
.site-footer nav a:hover {
  color: var(--text);
  text-decoration: underline;
  text-decoration-color: var(--mint);
}

/* ---- Pages par fonction (2026-10-14) ---------------------------------------------------------
 * Une page par recherche que tapent les motards (tools/pages/fonctions/, docs/referencement.md) :
 * fil d'Ariane, ouverture (titre, chapeau, magasins, écran ou photo), texte en colonne de lecture,
 * questions, liens vers les autres fonctions. Mêmes encres, même police, mêmes composants. */
.feature {
  padding-top: calc(var(--header-h) + var(--s-5));
  padding-bottom: var(--s-8);
  color: var(--text-2);
}
.crumbs ol {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-1) var(--s-2);
  margin: 0;
  padding: 0;
  list-style: none;
  font-size: var(--t-small);
  color: var(--text-3);
}
.crumbs li + li::before {
  content: "›";
  margin-right: var(--s-2);
  color: var(--text-3);
}
.crumbs a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  color: var(--text-2);
  text-decoration: none;
}
.crumbs a:hover,
.crumbs a:focus-visible {
  color: var(--text);
  text-decoration: underline;
  text-decoration-color: var(--mint);
}
.crumbs [aria-current] {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  color: var(--text-2);
}
.feature__hero {
  display: grid;
  gap: var(--s-7);
  align-items: center;
  padding-block: var(--s-5) var(--s-8);
}
.feature__copy {
  display: grid;
  gap: var(--s-4);
  justify-items: start;
}
.feature__copy h1 {
  font-size: clamp(2.2rem, 1.3rem + 3.4vw, 4.25rem);
  font-weight: 860;
  font-style: italic;
  font-stretch: 110%;
  line-height: 0.96;
  letter-spacing: -0.02em;
  color: var(--text);
  text-wrap: balance;
}
.feature__copy .lead {
  max-width: var(--measure);
  font-size: var(--t-lead);
  color: var(--text-2);
}
.feature__note {
  max-width: var(--measure);
  font-size: var(--t-small);
  color: var(--text-3);
}
.feature__shot {
  justify-self: center;
  width: min(64vw, 18rem);
  margin: 0;
}
.feature__shot .phone {
  width: 100%;
}
.feature__shot--wide {
  width: 100%;
}
.feature__shot--wide img {
  width: 100%;
  height: auto;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  border-radius: var(--r-2);
  box-shadow: 0 40px 80px -30px rgb(0 0 0 / 0.9);
}
@media (min-width: 60rem) {
  .feature__hero {
    grid-template-columns: minmax(0, 1.25fr) minmax(0, 0.75fr);
    column-gap: var(--s-8);
  }
  .feature__shot--wide {
    justify-self: stretch;
  }
}
/* Le texte : la colonne de lecture et les titres des documents. */
.feature__body {
  max-width: 46rem;
  margin: 0 auto;
  padding-inline: var(--gutter);
}
.feature__body section + section {
  margin-top: var(--s-7);
}
.feature__body h2 {
  margin-bottom: var(--s-3);
  font-size: clamp(1.35rem, 1.1rem + 0.9vw, 1.85rem);
  font-weight: 780;
  font-style: italic;
  font-stretch: 106%;
  line-height: 1.12;
  color: var(--text);
  scroll-margin-top: calc(var(--header-h) + var(--s-5));
}
.feature__body p,
.feature__body ul,
.feature__body ol,
.feature__body .table-wrap {
  margin-bottom: var(--s-4);
}
.feature__body ul,
.feature__body ol {
  padding-left: 1.25rem;
}
.feature__body ul {
  list-style: disc;
}
.feature__body ol {
  list-style: decimal;
}
.feature__body li {
  margin-bottom: var(--s-2);
}
.feature__body li::marker {
  color: var(--text-3);
}
.feature__body strong {
  color: var(--text);
}
.feature__body a {
  color: var(--mint);
}
.feature__body .table-wrap {
  overflow-x: auto;
}
.feature__body table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--t-small);
}
.feature__body th,
.feature__body td {
  padding: 0.55rem 0.7rem;
  border-bottom: 1px solid var(--hair);
  text-align: left;
  vertical-align: top;
}
.feature__body th {
  color: var(--text);
  font-weight: 650;
}
.feature__body .faq summary {
  color: var(--text);
}
/* Les autres fonctions : une carte par page, le nom en clair et une ligne. */
.feature__more {
  padding-top: var(--s-8);
}
.feature__more h2 {
  margin-bottom: var(--s-5);
  font-size: clamp(1.35rem, 1.1rem + 0.9vw, 1.85rem);
  font-weight: 780;
  font-style: italic;
  font-stretch: 106%;
  color: var(--text);
}
.feature__more ul,
.detail-links {
  display: grid;
  gap: var(--s-3);
  margin: 0;
  padding: 0;
  list-style: none;
}
@media (min-width: 40rem) {
  .feature__more ul {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}
@media (min-width: 72rem) {
  .feature__more ul {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }
}
.feature__more a,
.detail-links a {
  display: grid;
  gap: var(--s-1);
  height: 100%;
  padding: var(--s-4) var(--s-5);
  border: 1px solid var(--hair-2);
  border-radius: var(--r-2);
  background: var(--ink-2);
  color: var(--text-2);
  text-decoration: none;
  transition: border-color var(--dur-2) var(--ease-out), background var(--dur-2) var(--ease-out);
}
.feature__more a:hover,
.feature__more a:focus-visible,
.detail-links a:hover,
.detail-links a:focus-visible {
  border-color: var(--mint);
  background: rgb(55 233 196 / 0.06);
}
.feature__more strong,
.detail-links strong {
  font-size: 1.0625rem;
  font-weight: 700;
  color: var(--text);
}
.feature__more span:not(.label),
.detail-links span {
  font-size: var(--t-small);
}
@media (min-width: 40rem) {
  .detail-links {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}
/* Page MOTO et accueil : les liens vers les pages par fonction. */
.specs__more {
  display: inline-block;
  margin-top: var(--s-1);
  color: var(--mint);
}

/* ---- Page introuvable ---------------------------------------------------------------------- */
.lost {
  display: grid;
  align-content: center;
  gap: var(--s-6);
  min-height: 100vh;
  min-height: 100svh;
  padding-block: calc(var(--header-h) + var(--s-6)) var(--s-7);
}
.lost .display {
  font-size: var(--t-hero);
}
.lost__links {
  display: grid;
  gap: var(--s-6);
}
.lost__links ul {
  display: grid;
  gap: var(--s-1);
}
.lost__links a {
  display: inline-flex;
  min-height: 44px;
  align-items: center;
  color: var(--text);
  text-decoration-color: var(--mint);
}
@media (min-width: 40rem) {
  .lost__links {
    grid-template-columns: 1fr 1fr;
  }
}


/* ---- Images-clés --------------------------------------------------------------------------- */
@keyframes settle {
  from {
    opacity: 0;
    scale: 1.08;
  }
  to {
    opacity: 1;
    scale: 1;
  }
}
@keyframes fade {
  from {
    opacity: 0;
    transform: translate3d(0, 0.75rem, 0);
  }
  to {
    opacity: 1;
    transform: none;
  }
}
@keyframes cue {
  0% {
    transform: translateY(-100%);
  }
  60%,
  100% {
    transform: translateY(100%);
  }
}
@keyframes tap {
  0%,
  100% {
    transform: scale(1);
    opacity: 1;
  }
  12% {
    transform: scale(0.7);
    opacity: 0.6;
  }
  24% {
    transform: scale(1);
    opacity: 1;
  }
}

/* ---- Mouvement réduit : aucune animation, aucun défilement doux, états finaux -------------- */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 1ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 1ms !important;
    scroll-behavior: auto !important;
  }
}
/* Les fondus d'images restent : une opacité n'est pas un mouvement (WCAG 2.3.3), et aucune image
 * n'apparaît d'un coup. Les écrans du téléphone y perdent leur léger zoom, pas leur fondu. */
@media (prefers-reduced-motion: reduce) {
  .hero__stage.is-ready,
  .fade-img main img[loading="lazy"],
  [data-film] video {
    transition-duration: 0.9s !important;
  }
  .phone__screen > picture {
    transition: opacity 0.7s var(--ease-out) !important;
  }
}
@media (prefers-reduced-motion: no-preference) {
  html:focus-within {
    scroll-behavior: smooth;
  }
}
