/* ============================================================
   Ayyami, site vitrine.

   CONTRAT DE DIRECTION (mis à jour le 11/08/2026, verdict de Joumana)

   THÈSE : la mise en page suit le CANON ÉPROUVÉ des grands sites d'apps
   (Flo, Clue, Headspace, relevés en capture le 10 et 11/08) : héros en deux
   colonnes avec un téléphone ENTIER cadré, titres de section centrés,
   rangées image-texte en alternance, bande pleine largeur pour les données,
   rangée de trois règles, témoignages, FAQ, formulaire, offre. Aucune
   structure inventée : l'identité vit dans la matière, pas dans le plan.

   MONDE : celui de l'app, inchangé. Ciel de nuit #0B0A1A vers #2a2358, texte
   #E8E4F0, lilas #C8B4F0, or #E8C07D, menthe #7FD8B8, rose #D87DA8.
   Newsreader pour les titres, Lexend pour le texte (le corps de l'APP,
   vérifié dans src/App.jsx), Amiri pour l'arabe.
   Une seule unité d'ornement : le cran du cadran, en séparateur.

   HISTOIRE : elle comprend que l'app ne s'arrête pas à prédire ses règles,
   qu'elle l'accompagne aux moments exacts où elle doute, que la réponse
   vient avec sa source, et que ses données ne partent pas. Elle ouvre l'app.

   PREMIER ÉCRAN : à gauche la promesse et les deux actions, à droite l'écran
   d'accueil réel de l'app, ENTIER, dans un cadre de téléphone.

   SPECTACLE (verdict du 11/08 au soir : « vraiment tape-à-l'œil », visuels
   dynamiques, animations 3D, meilleure division) : l'idée défendue est LA
   LUNE. Une lune 3D en WebGL au centre de la page, le téléphone du héros qui
   suit le regard en perspective, les écrans qui se redressent en 3D en
   entrant, un grand numéral de jour par chapitre, les témoignages qui
   défilent. Trois lois tirées de la recherche sites primés : une seule idée
   défendue, une logique de scènes avec des respirations, la retenue
   technique (le lourd au héros et à la lune, le reste rapide et propre,
   fluide sur un téléphone moyen). L'offre fondatrice ne figure pas ici.

   INTERDITS HÉRITÉS DES VERDICTS : jamais un écran d'app en morceau recadré
   qui se dissout ; jamais une page pondérée à gauche avec du vide à droite ;
   jamais une capsule à filet ni un surtitre en capitales espacées ; chaque
   section s'équilibre sur la capture bureau avant livraison.
   ============================================================ */

/* ---------- Fontes servies depuis ce site : aucune requête tierce ---------- */
@font-face {
  font-family: "Newsreader";
  font-style: normal;
  font-weight: 300 600;
  font-display: swap;
  src: url("fonts/newsreader-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: "Newsreader";
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  src: url("fonts/newsreader-italic-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;
}
/* Lexend est la police de corps de l'APP (body de src/App.jsx) : le site parle
   la même langue. Public Sans, posée par erreur de mémoire, corrigée le 12/08. */
@font-face {
  font-family: "Lexend";
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url("fonts/lexend-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;
}
/* Amiri ne se charge que sur les pages qui portent de l'arabe : la plage
   unicode le garantit. */
@font-face {
  font-family: "Amiri";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("fonts/amiri-arabic.woff2") format("woff2");
  unicode-range: U+0600-06FF, U+0750-077F, U+0870-088E, U+0890-0891, U+0898-08E1,
    U+08E3-08FF, U+200C-200E, U+2010-2011, U+204F, U+2E41, U+FB50-FDFF, U+FE70-FE74,
    U+FE76-FEFC;
}

:root {
  --nuit-0: #0b0a1a;
  --nuit-1: #12102b;
  --nuit-2: #1e1a3a;
  --nuit-3: #251f45;

  --texte: #e8e4f0;
  /* Les seconds niveaux sont teintés depuis le fond, jamais gris neutres. */
  --texte-2: #b3adcf;
  --texte-3: #8b84a8;

  --lilas: #c8b4f0;
  --or: #e8c07d;
  --menthe: #7fd8b8;
  --rose: #e7b8e0;
  --sang: #d87da8;

  --titre: "Newsreader", Georgia, "Times New Roman", serif;
  --corps: "Lexend", system-ui, -apple-system, "Segoe UI", sans-serif;

  --marge: clamp(20px, 5vw, 64px);
  --large: 1180px;

  --sortie: cubic-bezier(0.16, 1, 0.3, 1);
}

* {
  box-sizing: border-box;
}

/* D'une page a l'autre (accueil vers lexique), le navigateur fond les deux
   vues au lieu de couper au blanc. Ignore par les navigateurs plus vieux. */
@view-transition {
  navigation: auto;
}

html {
  background: var(--nuit-0);
  scroll-behavior: smooth;
  -webkit-text-size-adjust: 100%;
}

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }
}

body {
  margin: 0;
  color: var(--texte);
  font: 400 17px/1.68 var(--corps);
  letter-spacing: 0.005em;
  /* Le ciel est peint en couleur pleine ET en dégradé fixe : sans la couleur
     pleine, le bas de page vire au blanc sur iOS Safari. */
  background-color: var(--nuit-0);
  background-image: radial-gradient(
    120% 62% at 50% -8%,
    #332a63 0%,
    #211c48 26%,
    #15122f 58%,
    #0b0a1a 100%
  );
  background-repeat: no-repeat;
  background-attachment: fixed;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;
}

::selection {
  background: rgba(200, 180, 240, 0.28);
}

a {
  color: var(--lilas);
  text-underline-offset: 3px;
  text-decoration-thickness: 1px;
}

/* height:auto est obligatoire : chaque img porte ses attributs width/height
   (pour réserver la place avant chargement), et sans lui la hauteur d'attribut
   s'applique telle quelle : tous les téléphones sortaient étirés (vu sur la
   capture du 11/08). */
img {
  max-width: 100%;
  height: auto;
  display: block;
}

:focus-visible {
  outline: 2px solid var(--or);
  outline-offset: 3px;
  border-radius: 4px;
}

.saut {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  background: var(--nuit-2);
  color: var(--texte);
  z-index: 40;
}
.saut:focus {
  width: auto;
  height: auto;
  clip-path: none;
  left: 0;
  top: 0;
  padding: 12px 18px;
  border-radius: 0 0 10px 0;
}

/* ---------- Le ciel vivant ----------
   Étoiles sur canvas (dessinées par le script de la page) et deux aurores qui
   dérivent. Le contenu vit au-dessus, le ciel reste derrière tout. Une seule
   scène continue, comme dans les vidéos du projet. */
#ciel {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: 0;
  pointer-events: none;
}

.aurore {
  position: fixed;
  z-index: 0;
  pointer-events: none;
  width: 68vmax;
  height: 68vmax;
  border-radius: 50%;
  opacity: 0.16;
}

.aurore-a {
  top: -28vmax;
  left: -18vmax;
  background: radial-gradient(circle at 50% 50%, #6f55c9 0%, transparent 62%);
}

.aurore-b {
  top: 4vmax;
  right: -26vmax;
  background: radial-gradient(circle at 50% 50%, #a8547e 0%, transparent 60%);
  opacity: 0.11;
}

@media (prefers-reduced-motion: no-preference) {
  html.js .aurore-a {
    animation: aurore-glisse 64s ease-in-out infinite alternate;
  }
  html.js .aurore-b {
    animation: aurore-glisse 88s ease-in-out infinite alternate-reverse;
  }
  @keyframes aurore-glisse {
    to {
      transform: translate3d(9vmax, 6vmax, 0) scale(1.12);
    }
  }
}

/* Tout le contenu passe au-dessus du ciel. */
header,
main,
footer {
  position: relative;
  z-index: 1;
}

/* ---------- Trame commune ---------- */
.bande {
  max-width: var(--large);
  margin: 0 auto;
  padding-left: var(--marge);
  padding-right: var(--marge);
}

/* Les titres et chapeaux se centrent, comme sur les grands sites. */
.centre {
  text-align: center;
}

.centre .titre-section,
.centre .chapeau-section {
  margin-left: auto;
  margin-right: auto;
}

/* ---------- Le cran : l'unique unité d'ornement du site ---------- */
.crans {
  display: block;
  width: min(320px, 62vw);
  height: 14px;
  margin: 0 auto;
  color: var(--lilas);
  opacity: 0.42;
}

/* ---------- En-tête ---------- */
/* Collant : le bouton « Ouvrir l'app » reste à portée de pouce pendant tout le
   défilement, et la lune de progression du menu devient enfin visible en cours
   de route (avant, elle défilait hors écran avec l'en-tête). Fond translucide
   flouté pour que le texte ne se mélange jamais à ce qui passe dessous.
   Le fond couvre TOUTE la largeur de l'écran : l'en-tête sort du gabarit
   .bande (sinon, sur un grand écran, le rectangle du fond s'arrête aux bords
   de la colonne de contenu et dessine deux coutures verticales). Le contenu,
   lui, reste aligné sur la colonne grâce au padding calculé. */
.entete {
  position: sticky;
  top: 0;
  z-index: 10;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  max-width: none;
  margin: 0;
  padding-left: max(var(--marge), calc((100% - var(--large)) / 2 + var(--marge)));
  padding-right: max(var(--marge), calc((100% - var(--large)) / 2 + var(--marge)));
  padding-top: 16px;
  padding-bottom: 16px;
  background: rgba(11, 10, 26, 0.72);
  -webkit-backdrop-filter: blur(12px);
  backdrop-filter: blur(12px);
}

.marque {
  display: inline-flex;
  align-items: center;
  gap: 11px;
  font-family: var(--titre);
  font-size: 21px;
  font-weight: 500;
  letter-spacing: -0.005em;
  color: var(--texte);
  text-decoration: none;
}

.marque svg {
  width: 21px;
  height: 21px;
  color: var(--lilas);
  flex: none;
}

.menu {
  display: flex;
  align-items: center;
  gap: 8px 26px;
  flex-wrap: wrap;
  justify-content: flex-end;
}

.menu a:not(.bouton) {
  font-size: 15px;
  color: var(--texte-2);
  text-decoration: none;
  transition: color 0.24s var(--sortie);
}

.menu a:not(.bouton):hover {
  color: var(--texte);
}

.menu-liens {
  display: flex;
  align-items: center;
  gap: 8px 26px;
  flex-wrap: wrap;
}

/* Le bouton du menu n'existe que sur petit écran, et seulement si le
   JavaScript répond : sans lui, les liens restent affichés. */
.menu-bouton {
  display: none;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  padding: 0;
  border: 1px solid rgba(200, 180, 240, 0.28);
  border-radius: 999px;
  background: transparent;
  color: var(--texte-2);
  font: inherit;
  cursor: pointer;
}

.menu-bouton svg {
  width: 20px;
  height: 20px;
}

@media (max-width: 620px) {
  .menu {
    gap: 10px;
    flex-wrap: nowrap;
  }

  html.js .menu-bouton {
    display: inline-flex;
  }

  /* Le panneau se pose sous l'en-tête, sur toute la largeur, et se referme
     dès qu'on choisit. Il sort du flux pour ne pas pousser la page. */
  html.js .menu-liens {
    position: absolute;
    top: 100%;
    right: var(--marge);
    left: var(--marge);
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    padding: 6px;
    border: 1px solid rgba(200, 180, 240, 0.16);
    border-radius: 16px;
    background: #16132f;
    -webkit-backdrop-filter: blur(14px);
    backdrop-filter: blur(14px);
    box-shadow: 0 18px 40px -18px rgba(0, 0, 0, 0.8);
    opacity: 0;
    visibility: hidden;
    transform: translateY(-8px);
    transition:
      opacity 0.22s var(--sortie),
      transform 0.22s var(--sortie),
      visibility 0.22s;
  }

  html.js .menu[data-ouvert="oui"] .menu-liens {
    opacity: 1;
    visibility: visible;
    transform: none;
  }

  html.js .menu-liens > a {
    padding: 13px 14px;
    border-radius: 11px;
    font-size: 16px;
  }

  html.js .menu-liens > a:active {
    background: rgba(200, 180, 240, 0.12);
  }
}

/* ---------- Boutons ---------- */
.bouton {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 14px 24px;
  border-radius: 999px;
  border: 1px solid transparent;
  font: 600 16px/1 var(--corps);
  letter-spacing: 0.005em;
  text-decoration: none;
  cursor: pointer;
  transition:
    transform 0.28s var(--sortie),
    box-shadow 0.28s var(--sortie),
    background-color 0.28s var(--sortie),
    border-color 0.28s var(--sortie);
}

.bouton-plein {
  background: var(--lilas);
  color: #1a1236;
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 0.28) inset,
    0 12px 26px -14px rgba(200, 180, 240, 0.9);
}
.bouton-plein:hover {
  background: #d7c7f6;
  transform: translateY(-1px);
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 0.32) inset,
    0 18px 34px -16px rgba(200, 180, 240, 0.95);
}
.bouton-plein:active {
  transform: translateY(0);
}

.bouton-fin {
  background: rgba(30, 26, 58, 0.55);
  border-color: rgba(200, 180, 240, 0.3);
  color: var(--texte);
}
.bouton-fin:hover {
  border-color: rgba(200, 180, 240, 0.6);
  background: rgba(37, 31, 69, 0.72);
  transform: translateY(-1px);
}

.bouton-petit {
  padding: 10px 18px;
  font-size: 15px;
  /* Sur 320px, « Ouvrir l'app » se coupait en deux lignes et l'en-tête
     grandissait d'autant (mesuré le 26/08 : 84px au lieu de 76). */
  white-space: nowrap;
}

/* Sous 380px, les trois éléments de l'en-tête (marque, menu, bouton) ne
   tiennent plus sur une ligne : mesuré à 320px, il manquait 15px. On resserre
   la marque et les écarts au lieu de laisser l'en-tête passer sur deux
   lignes. */
@media (max-width: 380px) {
  .bouton-petit {
    padding: 10px 14px;
    font-size: 14px;
  }

  .marque {
    gap: 8px;
    font-size: 17px;
  }

  .menu {
    gap: 8px;
  }
}

/* ---------- Le téléphone : un écran ENTIER dans un cadre ---------- */
.telephone {
  margin: 0;
  width: min(320px, 78vw);
  border-radius: 46px;
  padding: 11px;
  background: #060512;
  border: 1px solid rgba(200, 180, 240, 0.22);
  box-shadow:
    0 2px 0 rgba(255, 255, 255, 0.06) inset,
    0 34px 70px -30px rgba(0, 0, 0, 0.85);
}

/* Pendant le chargement differe, le cadre restait un rectangle noir et vide
   (vu en capture le 31/08). Un lavis de la nuit de l'app occupe la place :
   l'ecran arrive par-dessus, rien ne saute. */
.telephone img {
  width: 100%;
  border-radius: 36px;
  background: linear-gradient(170deg, #241f47 0%, #171432 46%, #0e0c22 100%);
}

/* ---------- Héros ---------- */
.ouverture {
  padding-top: clamp(24px, 4vw, 48px);
  padding-bottom: clamp(36px, 5vw, 64px);
}

.ouverture-grille {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: clamp(32px, 5vw, 56px);
  align-items: center;
  justify-items: center;
}

.ouverture-texte {
  text-align: center;
  max-width: 560px;
}

@media (min-width: 880px) {
  .ouverture-grille {
    grid-template-columns: minmax(0, 1.08fr) minmax(0, 0.92fr);
    justify-items: stretch;
  }
  .ouverture-texte {
    text-align: left;
    max-width: none;
  }
  .ouverture-tel {
    display: flex;
    justify-content: center;
  }
}

h1 {
  font-family: var(--titre);
  font-weight: 500;
  font-size: clamp(2.7rem, 6.2vw, 5.2rem);
  line-height: 1.02;
  letter-spacing: -0.035em;
  margin: 0 0 24px;
  text-wrap: balance;
}

.ouverture h1 {
  font-size: clamp(2.7rem, 6.2vw, 5.2rem);
  line-height: 1.02;
}

.surtitre {
  color: var(--lilas);
  font-size: 0.9rem;
  line-height: 1.55;
  margin: 0 0 18px;
}

h1 .attenue {
  color: var(--texte-2);
}

.promesse {
  font-size: clamp(1.06rem, 1.6vw, 1.2rem);
  line-height: 1.62;
  color: var(--texte-2);
  max-width: 44ch;
  margin: 0 0 30px;
}

.ouverture-texte.centre .promesse,
.ouverture-texte:not(.centre) .promesse {
  margin-left: auto;
  margin-right: auto;
}

@media (min-width: 880px) {
  .ouverture-texte .promesse {
    margin-left: 0;
    margin-right: 0;
  }
}

.ouverture-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 14px 18px;
}

@media (min-width: 880px) {
  .ouverture-actions {
    justify-content: flex-start;
  }
}

.sous-action {
  font-size: 14.5px;
  color: var(--texte-3);
  margin: 14px 0 0;
}

/* ---------- Sections courantes ---------- */
.section {
  padding-top: clamp(56px, 7vw, 96px);
  padding-bottom: clamp(16px, 2.5vw, 32px);
}

.titre-section {
  font-family: var(--titre);
  font-weight: 500;
  font-size: clamp(1.95rem, 3.8vw, 2.9rem);
  line-height: 1.12;
  letter-spacing: -0.022em;
  margin: 0 0 14px;
  max-width: 24ch;
  text-wrap: balance;
}

.chapeau-section {
  color: var(--texte-2);
  max-width: 54ch;
  margin: 0 0 8px;
}

/* ---------- La traversée : rangées en alternance ---------- */
/* Les lavis et les grands numéraux débordent volontairement de leur rangée :
   la section les recadre, sinon la page défile sur le côté au téléphone.
   MAIS la section s'étend sur toute la largeur de l'écran (contenu aligné
   par le padding calculé) : sinon, sur un grand écran, le recadrage coupe
   les dégradés aux bords de la colonne et dessine des coutures verticales,
   le même défaut que l'en-tête. */
#traversee {
  overflow-x: clip;
  max-width: none;
  margin: 0;
  padding-left: max(var(--marge), calc((100% - var(--large)) / 2 + var(--marge)));
  padding-right: max(var(--marge), calc((100% - var(--large)) / 2 + var(--marge)));
}

.rangee {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: clamp(26px, 4vw, 40px);
  align-items: center;
  justify-items: center;
  padding-top: clamp(40px, 5.5vw, 72px);
}

.rangee-texte {
  max-width: 520px;
}

.rangee-tel {
  width: min(258px, 72vw);
}

/* La fenêtre : un recadrage FRANC sur la partie de l'écran qui compte (les
   volets qui vivent en bas d'écran), bordée, jamais un fondu qui se dissout.
   Plus large qu'un téléphone : le volet devient lisible. */
.fenetre {
  margin: 0;
  width: min(430px, 88vw);
  border-radius: 22px;
  overflow: hidden;
  border: 1px solid rgba(200, 180, 240, 0.24);
  box-shadow: 0 30px 60px -28px rgba(0, 0, 0, 0.8);
}

.fenetre img {
  width: 100%;
  display: block;
}

@media (min-width: 880px) {
  .rangee {
    grid-template-columns: minmax(0, 1.1fr) minmax(0, 0.9fr);
    gap: clamp(40px, 6vw, 96px);
    justify-items: stretch;
  }
  .rangee-texte {
    justify-self: start;
  }
  .rangee-tel {
    justify-self: center;
  }
  /* L'alternance : une rangée sur deux, le téléphone passe à gauche. */
  .rangee.inverse .rangee-texte {
    order: 2;
    justify-self: end;
  }
  .rangee.inverse .rangee-tel {
    order: 1;
  }
}

/* Le jour : une ligne de texte colorée, rien de plus. La capsule à filet et
   capitales espacées est le marqueur d'interface générée n°1 de la recherche
   du 06/08 : bannie. */
.jour-pill {
  margin: 0 0 12px;
  color: var(--de, #c8b4f0);
  font-family: var(--corps);
  font-size: 14.5px;
  font-weight: 600;
}

.rangee h2 {
  font-family: var(--titre);
  font-weight: 500;
  font-size: clamp(1.5rem, 2.8vw, 2.1rem);
  line-height: 1.14;
  letter-spacing: -0.02em;
  margin: 0 0 14px;
  text-wrap: balance;
}

.rangee p {
  margin: 0 0 14px;
  color: var(--texte-2);
  max-width: 52ch;
}

.rangee p strong {
  color: var(--texte);
  font-weight: 600;
}

/* Ses mots à elle, pas les nôtres. */
.sa-phrase {
  font-family: var(--titre);
  font-style: italic;
  font-weight: 400;
  font-size: clamp(1.15rem, 2vw, 1.4rem);
  line-height: 1.42;
  color: var(--texte);
  margin: 0 0 6px;
  max-width: 30ch;
}

.sa-source {
  font-size: 13.5px;
  color: var(--texte-3);
  margin: 0 0 18px;
  max-width: 44ch;
}

/* ---------- La scène de la lune : épinglée, le défilement est la timeline ----------
   Repli sans timeline de défilement : une bande simple, tout empilé, lisible. */
.scene-lune {
  margin-top: clamp(64px, 8vw, 110px);
  border-top: 1px solid rgba(200, 180, 240, 0.14);
  border-bottom: 1px solid rgba(200, 180, 240, 0.14);
  background: linear-gradient(
    to bottom,
    rgba(30, 26, 58, 0),
    rgba(30, 26, 58, 0.5) 12%,
    rgba(30, 26, 58, 0.5) 88%,
    rgba(30, 26, 58, 0)
  );
}

.scene-colle {
  display: grid;
  place-items: center;
  gap: 26px;
  padding: clamp(44px, 6vw, 76px) 0;
  text-align: center;
}

.beats {
  display: grid;
  gap: 20px;
  justify-items: center;
}

.beat {
  margin: 0;
  color: var(--texte-2);
  max-width: 54ch;
}

.beat-2,
.beat-3 {
  font-size: clamp(1.15rem, 2.2vw, 1.5rem);
  line-height: 1.5;
}

.beat-1 {
  max-width: 26ch;
  font-family: var(--titre);
  font-weight: 500;
  font-size: clamp(2.2rem, 5vw, 3.8rem);
  line-height: 1.08;
  letter-spacing: -0.03em;
  color: var(--texte);
  margin: 10px 0;
}

/* La lune : le seul visuel qui n'est pas un écran, et c'est celui de l'app. */
.lune-bloc {
  display: flex;
  justify-content: center;
}

.lune {
  position: relative;
  width: clamp(170px, 26vw, 300px);
  aspect-ratio: 1;
  border-radius: 50%;
  background: radial-gradient(circle at 38% 34%, #fff, #e7ddff 52%, #b9a7ec 100%);
  box-shadow: 0 0 90px -12px rgba(200, 180, 240, 0.65);
}

/* La version épinglée, là où le navigateur sait scruber. Grand écran
   seulement : au téléphone, 240vh de course pour une lune et trois phrases
   font deux écrans et demi presque vides (mesuré le 20/08 sur la pleine page
   mobile). Sur téléphone, la bande simple au-dessus s'applique : lune et
   messages empilés, tout visible, rien à scruber. */
@media (prefers-reduced-motion: no-preference) and (min-width: 880px) {
  @supports (animation-timeline: view()) {
    html.js .scene-lune {
      height: 240vh;
      view-timeline: --scene-lune block;
    }

    html.js .scene-colle {
      position: sticky;
      top: 0;
      height: 100vh;
      padding: 0;
      grid-template-areas: "centre";
      overflow: hidden;
    }

    html.js .scene-colle > * {
      grid-area: centre;
    }

    /* La lune grossit sur toute la course. */
    html.js .scene-colle .lune-bloc {
      animation: lune-grossit linear both;
      animation-timeline: --scene-lune;
      animation-range: cover 5% cover 85%;
    }
    @keyframes lune-grossit {
      from {
        transform: scale(0.5);
      }
      to {
        transform: scale(1.18);
      }
    }

    /* Les messages se succèdent, chacun sur sa fenêtre de course, devant la
       lune, avec une ombre portée pour rester lisibles au croisement. */
    html.js .beats {
      z-index: 1;
      position: relative;
    }

    /* Le texte passait DEVANT la lune pleine lumiere : blanc sur blanc,
       illisible (verdict du 31/08, mesure au pixel a l'appui). Un voile sombre
       se pose entre la lune et les mots, assez large pour couvrir les trois
       messages, assez doux pour ne jamais se voir comme une forme. */
    html.js .beats::before {
      content: "";
      position: absolute;
      z-index: -1;
      left: 50%;
      top: 50%;
      width: min(180vw, 1500px);
      height: min(90vh, 700px);
      transform: translate(-50%, -50%);
      background: radial-gradient(
        closest-side at 50% 50%,
        rgba(9, 8, 20, 0.62),
        rgba(9, 8, 20, 0.46) 45%,
        rgba(9, 8, 20, 0.22) 72%,
        transparent 100%
      );
      pointer-events: none;
    }

    html.js .beat {
      grid-area: 1 / 1;
      opacity: 0;
      text-shadow: 0 2px 26px rgba(11, 10, 26, 0.9);
      animation: beat-passe linear both;
      animation-timeline: --scene-lune;
    }

    html.js .beat-1 {
      animation-range: cover 6% cover 34%;
    }
    html.js .beat-2 {
      animation-range: cover 28% cover 60%;
    }
    html.js .beat-3 {
      animation-range: cover 54% cover 82%;
    }
    @keyframes beat-passe {
      0% {
        opacity: 0;
        transform: translateY(46px);
      }
      22% {
        opacity: 1;
        transform: none;
      }
      78% {
        opacity: 1;
        transform: none;
      }
      100% {
        opacity: 0;
        transform: translateY(-42px);
      }
    }

    /* Le bouton arrive en dernier et reste. */
    html.js .beat-4 {
      animation-name: beat-final;
      animation-range: cover 80% cover 96%;
    }
    @keyframes beat-final {
      from {
        opacity: 0;
        transform: translateY(40px);
      }
      to {
        opacity: 1;
        transform: none;
      }
    }
  }
}

/* ---------- Les trois règles de confiance ---------- */
.trois {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 30px;
  margin-top: 34px;
}

@media (min-width: 820px) {
  .trois {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 38px;
  }
}

.regle {
  padding-top: 20px;
  border-top: 1px solid rgba(200, 180, 240, 0.2);
}

.regle h3 {
  font-family: var(--titre);
  font-weight: 500;
  font-size: 1.28rem;
  line-height: 1.24;
  letter-spacing: -0.014em;
  margin: 0 0 10px;
  color: var(--texte);
}

.regle p {
  margin: 0;
  color: var(--texte-2);
  font-size: 16px;
}

.note-deen {
  margin: 40px auto 0;
  padding-top: 22px;
  border-top: 1px solid rgba(200, 180, 240, 0.14);
  font-family: var(--titre);
  font-style: italic;
  font-size: 1.15rem;
  line-height: 1.5;
  color: var(--texte-2);
  max-width: 46ch;
}

/* ---------- Ouvert / en option ---------- */
.deux-colonnes {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: clamp(34px, 5vw, 56px);
  max-width: 920px;
  margin: 34px auto 0;
}

@media (min-width: 820px) {
  .deux-colonnes {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

.colonne h3 {
  font-family: var(--titre);
  font-size: 1.3rem;
  font-weight: 500;
  letter-spacing: -0.012em;
  margin: 0 0 20px;
  padding-bottom: 14px;
  border-bottom: 1px solid rgba(200, 180, 240, 0.18);
}

.colonne.ouvert h3 {
  color: var(--menthe);
  border-bottom-color: rgba(127, 216, 184, 0.28);
}
.colonne.option h3 {
  color: var(--or);
  border-bottom-color: rgba(232, 192, 125, 0.28);
}

.liste {
  list-style: none;
  margin: 0;
  padding: 0;
}

.liste li {
  position: relative;
  padding-left: 26px;
  margin-bottom: 14px;
  color: var(--texte);
  font-size: 16.5px;
}

.liste li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 11px;
  width: 12px;
  height: 2px;
  border-radius: 2px;
  background: var(--menthe);
}

.colonne.option .liste li::before {
  background: var(--or);
}

.prix-ligne {
  margin: 24px 0 0;
  font-size: 15px;
  color: var(--texte-2);
}

.prix-ligne b {
  color: var(--texte);
  font-weight: 600;
}

/* ---------- Le tableau de comparaison ---------- */
.tableau-enveloppe {
  overflow-x: auto;
  margin: 34px calc(var(--marge) * -1) 0;
  padding: 0 var(--marge);
}

.tableau {
  table-layout: fixed;
  width: 100%;
  max-width: 920px;
  margin: 0 auto;
  min-width: 580px;
  border-collapse: collapse;
  font-size: 15.5px;
}

.tableau th,
.tableau td {
  text-align: left;
  padding: 15px 16px;
  border-bottom: 1px solid rgba(200, 180, 240, 0.12);
  vertical-align: top;
}

.tableau thead th {
  font-family: var(--corps);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0;
  text-transform: none;
  color: var(--texte-2);
  border-bottom-color: rgba(200, 180, 240, 0.24);
  white-space: nowrap;
}

.tableau tbody th {
  font-weight: 400;
  color: var(--texte);
  width: 26%;
}

.tableau td {
  color: var(--texte-2);
}

/* La colonne qui nous concerne est tenue par une teinte de fond continue. */
.tableau .nous {
  background: rgba(200, 180, 240, 0.07);
  color: var(--texte);
}

.tableau thead .nous {
  color: var(--lilas);
  background: rgba(200, 180, 240, 0.1);
}

/* Le mot est écrit : la couleur ne porte jamais l'information toute seule. */
.tableau .oui {
  color: var(--menthe);
}
.tableau .nous.oui {
  color: var(--menthe);
  font-weight: 600;
}
.tableau .non {
  color: var(--texte-3);
}

.note-tableau {
  margin: 20px auto 0;
  font-size: 13.5px;
  color: var(--texte-3);
  max-width: 68ch;
}

.visuellement-cache {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* ---------- Les testeuses ---------- */
.citations {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 0 clamp(34px, 5vw, 64px);
  max-width: 980px;
  margin: 10px auto 0;
}

@media (min-width: 820px) {
  .citations {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

.voix {
  margin: 0;
  padding: 26px 0;
  border-top: 1px solid rgba(200, 180, 240, 0.13);
  display: grid;
  gap: 8px;
  align-content: start;
}

.voix .etoiles {
  margin: 0 0 10px;
  color: var(--or);
  line-height: 0;
}

.voix blockquote {
  margin: 0;
  font-family: var(--titre);
  font-size: clamp(1.12rem, 1.9vw, 1.38rem);
  line-height: 1.44;
  letter-spacing: -0.008em;
  color: var(--texte);
}

.voix figcaption {
  font-size: 13px;
  letter-spacing: 0.02em;
  color: var(--texte-3);
}

/* ---------- Les questions ---------- */
.questions {
  max-width: 760px;
  margin: 10px auto 0;
}

.questions details {
  border-top: 1px solid rgba(200, 180, 240, 0.13);
}

.questions details:last-child {
  border-bottom: 1px solid rgba(200, 180, 240, 0.13);
}

.questions summary {
  list-style: none;
  cursor: pointer;
  display: flex;
  align-items: baseline;
  gap: 16px;
  padding: 20px 0;
  font-family: var(--titre);
  font-weight: 500;
  font-size: clamp(1.1rem, 2vw, 1.32rem);
  line-height: 1.32;
  letter-spacing: -0.012em;
  color: var(--texte);
}

.questions summary::-webkit-details-marker {
  display: none;
}

/* La croix tourne pour devenir un plus quand la question se referme. */
.questions summary::after {
  content: "";
  margin-left: auto;
  flex: none;
  width: 13px;
  height: 13px;
  align-self: center;
  background:
    linear-gradient(var(--lilas), var(--lilas)) center / 100% 1.5px no-repeat,
    linear-gradient(var(--lilas), var(--lilas)) center / 1.5px 100% no-repeat;
  transition: transform 0.35s var(--sortie);
}

.questions details[open] summary::after {
  transform: rotate(45deg);
}

.questions summary:hover {
  color: var(--lilas);
}

.questions details p {
  margin: 0 0 24px;
  max-width: 62ch;
  color: var(--texte-2);
}

/* ---------- Où l'ouvrir ---------- */
/* Le panneau des accès : l'œuvre de nuit (générée le 12/08 via son Gemini,
   site/img/ciel-nuit.webp) porte la scène des trois portes. Le voile garantit
   le contraste, plus dense derrière les portes. */
.portes-panneau {
  position: relative;
  overflow: hidden;
  border-radius: 32px;
  border: 1px solid rgba(200, 180, 240, 0.24);
  background:
    linear-gradient(
      to bottom,
      rgba(13, 11, 30, 0.5),
      rgba(13, 11, 30, 0.6) 46%,
      rgba(11, 10, 26, 0.82)
    ),
    url("img/ciel-nuit.webp") center / cover no-repeat,
    linear-gradient(to bottom, #1b1738, #12102b);
  padding: clamp(36px, 5vw, 64px) clamp(18px, 4vw, 56px) clamp(30px, 4vw, 52px);
}

.portes {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 12px;
  max-width: 980px;
  margin: 30px auto 0;
}

@media (min-width: 760px) {
  .portes {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}

.porte {
  display: flex;
  align-items: center;
  gap: 15px;
  padding: 16px 20px;
  border-radius: 16px;
  border: 1px solid rgba(200, 180, 240, 0.3);
  background: rgba(22, 19, 46, 0.82);
  color: var(--texte);
  text-decoration: none;
  transition:
    border-color 0.28s var(--sortie),
    background-color 0.28s var(--sortie),
    transform 0.28s var(--sortie);
}

.porte:hover {
  border-color: rgba(200, 180, 240, 0.55);
  background: rgba(37, 31, 69, 0.7);
  transform: translateY(-1px);
}

.porte svg {
  flex: none;
  width: 25px;
  height: 25px;
  color: var(--texte-2);
}

.porte .l1 {
  display: block;
  font-size: 11.5px;
  letter-spacing: 0.06em;
  color: var(--texte-3);
}

.porte .l2 {
  display: block;
  font-size: 16.5px;
  font-weight: 600;
  margin-top: 2px;
}

.porte.bientot {
  pointer-events: none;
  border-style: dashed;
  border-color: rgba(200, 180, 240, 0.2);
  background: rgba(30, 26, 58, 0.28);
}

.porte.bientot .l1,
.porte.bientot .l2,
.porte.bientot svg {
  color: var(--texte-3);
}

.porte .attente {
  margin-left: auto;
  font-family: var(--titre);
  font-style: italic;
  font-size: 15px;
  color: var(--or);
  white-space: nowrap;
}

.porte:not(.bientot) .attente {
  display: none;
}

/* ---------- Rester prévenue ---------- */
.formulaire {
  max-width: 460px;
  margin: 26px auto 0;
  text-align: center;
}

.champ {
  display: grid;
  gap: 8px;
  margin-bottom: 14px;
  text-align: left;
}

.champ label {
  font-size: 14px;
  font-weight: 600;
  color: var(--texte-2);
}

.champ input {
  width: 100%;
  padding: 14px 18px;
  border-radius: 14px;
  border: 1px solid rgba(200, 180, 240, 0.28);
  background: rgba(18, 16, 43, 0.7);
  color: var(--texte);
  font: 400 16.5px/1.4 var(--corps);
  transition:
    border-color 0.24s var(--sortie),
    background-color 0.24s var(--sortie);
}

.champ input::placeholder {
  color: var(--texte-3);
}

.champ input:hover {
  border-color: rgba(200, 180, 240, 0.45);
}

.champ input:focus {
  outline: none;
  border-color: var(--lilas);
  background: rgba(30, 26, 58, 0.85);
}

.champ input:focus-visible {
  outline: 2px solid var(--or);
  outline-offset: 2px;
}

.formulaire .bouton {
  width: 100%;
}

.mention {
  margin: 16px 0 0;
  font-size: 13.5px;
  line-height: 1.55;
  color: var(--texte-3);
}

.reponse {
  margin: 16px 0 0;
  font-size: 15.5px;
  color: var(--menthe);
}

/* Le champ que seuls les robots remplissent. Caché par découpe et pas poussé
   hors écran, sinon la page se met à défiler sur le côté. */
.pot-de-miel {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* ---------- Pied de page ---------- */
.pied {
  margin-top: clamp(48px, 6vw, 80px);
  padding-block: 34px 54px;
  border-top: 1px solid rgba(200, 180, 240, 0.13);
  display: flex;
  flex-wrap: wrap;
  gap: 14px 28px;
  align-items: center;
  justify-content: space-between;
  font-size: 14.5px;
  color: var(--texte-3);
}

.pied nav {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 22px;
}

/* Le rembourrage agrandit la zone tactile à 44 px sans bouger la mise en
   page : la marge négative rend la place que le rembourrage prend. */
.pied a {
  color: var(--texte-2);
  text-decoration: none;
  display: inline-block;
  padding: 12px 6px;
  margin: -12px -6px;
}

.pied a:hover {
  color: var(--texte);
  text-decoration: underline;
}

/* ---------- La scène 3D ----------
   Le lourd vit à deux endroits : le héros et la lune. Le reste de la page
   reste rapide et propre, c'est la retenue des sites primés. */

/* Le titre se révèle ligne par ligne, par masque, entrées ease-out. */
h1 .ligne {
  display: block;
  overflow: hidden;
}

h1 .ligne > span {
  display: block;
}

@media (prefers-reduced-motion: no-preference) {
  html.js .ouverture-texte h1 .ligne > span {
    transform: translateY(108%);
    transition: transform 0.9s var(--sortie);
  }
  html.js .ouverture-texte.vu h1 .ligne:nth-child(1) > span {
    transition-delay: 0.05s;
  }
  html.js .ouverture-texte.vu h1 .ligne:nth-child(2) > span {
    transition-delay: 0.16s;
  }
  html.js .ouverture-texte.vu h1 .ligne > span {
    transform: none;
  }
}

/* Le téléphone du héros vit en perspective et suit le regard : la cible du
   ressort est posée par le script dans --ry et --rx. */
.ouverture-tel {
  perspective: 1300px;
}

.ouverture-tel .telephone {
  transform: rotateY(var(--ry, -10deg)) rotateX(var(--rx, 3deg));
  will-change: transform;
}

/* Les écrans des chapitres arrivent tournés et se redressent en entrant. */
.rangee {
  perspective: 1300px;
}

@media (prefers-reduced-motion: no-preference) {
  /* Repli (navigateurs sans timeline de défilement) : bascule à l'entrée. */
  html.js .rangee .telephone,
  html.js .rangee .fenetre {
    transform: rotateY(-16deg);
    transition: transform 1.15s var(--sortie);
  }
  html.js .rangee.inverse .telephone,
  html.js .rangee.inverse .fenetre {
    transform: rotateY(16deg);
  }
  html.js .rangee.vu .telephone,
  html.js .rangee.vu .fenetre {
    transform: none;
  }

  /* Là où le navigateur sait lier une animation au défilement, TOUT progresse
     avec le doigt : le défilement est la timeline, pas un déclencheur.
     Verdict du 12/08 : des animations interactives qui progressent quand on
     défile. */
  @supports (animation-timeline: view()) {
    html.js .rangee .telephone,
    html.js .rangee .fenetre {
      transition: none;
      transform: none;
      animation: redresse linear both;
      animation-timeline: view();
      animation-range: entry 0% cover 46%;
    }
    html.js .rangee.inverse .telephone,
    html.js .rangee.inverse .fenetre {
      animation-name: redresse-inverse;
    }
    @keyframes redresse {
      from {
        transform: perspective(1100px) rotateY(-22deg) translateY(28px) scale(0.95);
      }
      to {
        transform: none;
      }
    }
    @keyframes redresse-inverse {
      from {
        transform: perspective(1100px) rotateY(22deg) translateY(28px) scale(0.95);
      }
      to {
        transform: none;
      }
    }

    /* Le bloc de texte du chapitre glisse à contre-rythme de l'écran : deux
       vitesses, la scène prend de la profondeur. */
    html.js .rangee-texte {
      animation: texte-glisse linear both;
      animation-timeline: view();
      animation-range: cover 0% cover 100%;
    }
    @keyframes texte-glisse {
      from {
        transform: translateY(22px);
      }
      to {
        transform: translateY(-16px);
      }
    }

    /* Les grands numéraux dérivent moins vite que le contenu : la profondeur
       naît de l'écart des vitesses, comme la parallaxe des vidéos. */
    html.js .rangee::before {
      animation: numeral-derive linear both;
      animation-timeline: view();
      animation-range: cover 0% cover 100%;
    }
    @keyframes numeral-derive {
      from {
        transform: translateY(96px);
        opacity: 0;
      }
      30% {
        opacity: 0.12;
      }
      to {
        transform: translateY(-84px);
        opacity: 0.12;
      }
    }

    /* Le lavis du chapitre s'allume au rythme de l'entrée. */
    html.js .rangee::after {
      animation: lavis-pose linear both;
      animation-timeline: view();
      animation-range: entry 0% cover 38%;
    }
    @keyframes lavis-pose {
      from {
        opacity: 0;
      }
      to {
        opacity: 1;
      }
    }

    /* Les lignes du tableau se posent une à une en montant dans l'écran. */
    html.js .tableau tbody tr {
      animation: ligne-pose linear both;
      animation-timeline: view();
      animation-range: entry 0% entry 90%;
    }
    @keyframes ligne-pose {
      from {
        opacity: 0;
        transform: translateY(14px);
      }
      to {
        opacity: 1;
        transform: none;
      }
    }
  }

  /* Le téléphone du héros répond au départ : quand on quitte le haut de la
     page, il s'incline et recule, scrubbé sur les 600 premiers pixels. Posé
     sur l'enveloppe : l'inclinaison au pointeur vit sur le cadre, dedans. */
  @supports (animation-timeline: scroll()) {
    html.js .ouverture-tel {
      animation: heros-depart linear both;
      animation-timeline: scroll();
      animation-range: 0px 620px;
    }
    @keyframes heros-depart {
      to {
        transform: translateY(72px) scale(0.9) rotate(2.2deg);
      }
    }

    /* Le texte du héros part plus vite que le téléphone : parallaxe de départ. */
    html.js .ouverture-texte {
      animation: heros-texte linear both;
      animation-timeline: scroll();
      animation-range: 0px 520px;
    }
    @keyframes heros-texte {
      to {
        transform: translateY(-46px);
        opacity: 0.25;
      }
    }
  }
}

/* Le grand numéral du chapitre : la division se lit de loin. Il vit derrière
   le téléphone, dans la couleur du moment, et reste muet pour les lecteurs
   d'écran (texte alternatif vide). */
.rangee {
  position: relative;
}

.rangee::before {
  content: none;
  position: absolute;
  z-index: 0;
  top: 0.08em;
  right: 4%;
  font-family: var(--titre);
  font-weight: 500;
  font-size: clamp(6.5rem, 13vw, 11rem);
  line-height: 1;
  letter-spacing: -0.04em;
  color: var(--de, #c8b4f0);
  opacity: 0.12;
  pointer-events: none;
}

.rangee.inverse::before {
  right: auto;
  left: 4%;
}

@media (max-width: 879px) {
  .rangee::before {
    top: 4px;
    right: 0;
    font-size: clamp(4.5rem, 20vw, 6.5rem);
  }
  .rangee.inverse::before {
    right: 0;
    left: auto;
  }
}

/* Le lavis du chapitre : une teinte à peine posée derrière la scène, qui
   change avec le moment du cycle, comme les lavis colorés des vidéos.
   Diffusion élargie le 18/08 (son retour sur grand écran) : le halo s'étale
   plus loin et s'éteint plus progressivement, pour qu'aucun bord ne se
   devine, quelle que soit la largeur de l'écran. */
/* closest-side : l'ellipse se dimensionne sur le bord le plus proche de sa
   boîte, donc le fondu atteint le transparent AVANT tout bord, sur toute
   taille d'écran. Un rayon en %, lui, peut dépasser la boîte : elle tranche
   alors l'ellipse encore teintée et dessine une ligne droite, la « hitbox »
   que Joumana voyait (contrôle : amplifier les niveaux d'une capture). */
.rangee::after {
  content: "";
  position: absolute;
  z-index: 0;
  inset: -45% -85% -45% -25%;
  background: radial-gradient(
    closest-side at 62% 50%,
    color-mix(in srgb, var(--de, #c8b4f0) 10%, transparent),
    color-mix(in srgb, var(--de, #c8b4f0) 5%, transparent) 48%,
    color-mix(in srgb, var(--de, #c8b4f0) 2%, transparent) 72%,
    transparent 94%
  );
  pointer-events: none;
}

.rangee.inverse::after {
  inset: -45% -25% -45% -85%;
  background: radial-gradient(
    closest-side at 38% 50%,
    color-mix(in srgb, var(--de, #c8b4f0) 10%, transparent),
    color-mix(in srgb, var(--de, #c8b4f0) 5%, transparent) 48%,
    color-mix(in srgb, var(--de, #c8b4f0) 2%, transparent) 72%,
    transparent 94%
  );
}

.rangee > * {
  position: relative;
  z-index: 1;
}

/* La lune 3D : le canvas remplit le disque, le dégradé reste dessous en
   repli quand WebGL manque. */
.lune canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border-radius: 50%;
}

/* ---------- Les avis : une rangée qui se parcourt à la main ----------
   Molette, doigt, ou cliquer-glisser : la main de la lectrice, pas un défilé
   imposé (verdict du 12/08 : « on peut pas scroller les avis ? »). */
.avis-defile {
  display: grid;
  grid-auto-flow: column;
  gap: clamp(28px, 4vw, 56px);
  overflow-x: auto;
  scroll-snap-type: x proximity;
  /* Sans scroll-padding, l'aimantation colle la première carte au bord de
     l'écran et mange le padding : la carte démarrait rognée (mesuré le 20/08,
     scrollLeft 20 au repos sur téléphone). */
  scroll-padding-inline: var(--marge);
  padding-bottom: 14px;
  margin: 10px calc(var(--marge) * -1) 0;
  padding-left: var(--marge);
  padding-right: var(--marge);
  -webkit-mask-image: linear-gradient(to right, transparent, #000 6%, #000 94%, transparent);
  mask-image: linear-gradient(to right, transparent, #000 6%, #000 94%, transparent);
  scrollbar-width: thin;
  scrollbar-color: rgba(200, 180, 240, 0.35) transparent;
  cursor: grab;
}

.avis-defile.en-main {
  cursor: grabbing;
  scroll-snap-type: none;
  user-select: none;
}

.avis-defile::-webkit-scrollbar {
  height: 6px;
}

.avis-defile::-webkit-scrollbar-thumb {
  background: rgba(200, 180, 240, 0.3);
  border-radius: 3px;
}

.avis-defile .voix {
  width: min(460px, 78vw);
  scroll-snap-align: start;
  border-top: 1px solid rgba(200, 180, 240, 0.13);
}

/* ---------- Les respirations ----------
   La dérive lente des cadres a été retirée le 12/08 : posée sur l'image
   intérieure, elle faisait glisser l'écran DANS le téléphone immobile
   (verdict : « certains éléments flottent bizarrement »). Le mouvement des
   cadres appartient au défilement, et à lui seul. */
@media (prefers-reduced-motion: no-preference) {
  /* La lune respire : son halo grandit à peine, en opacité seulement. */
  html.js .lune::after {
    content: "";
    position: absolute;
    inset: -34%;
    border-radius: 50%;
    background: radial-gradient(circle, rgba(200, 180, 240, 0.32) 0%, transparent 66%);
    animation: lune-respire 6.5s ease-in-out infinite alternate;
  }
  @keyframes lune-respire {
    from {
      opacity: 0.55;
    }
    to {
      opacity: 1;
    }
  }

  /* La réponse d'une question se déploie au lieu d'apparaître d'un bloc. */
  .questions details[open] p {
    animation: devoile 0.5s var(--sortie);
  }
  @keyframes devoile {
    from {
      opacity: 0;
      transform: translateY(6px);
    }
  }
}

.lune {
  position: relative;
}

/* ---------- Entrée des blocs : une seule famille de mouvement ---------- */
html.js .entre {
  opacity: 0;
  transform: translateY(14px);
  filter: blur(4px);
  transition:
    opacity 0.85s var(--sortie),
    transform 0.85s var(--sortie),
    filter 0.85s var(--sortie);
}

html.js .entre.vu {
  opacity: 1;
  transform: none;
  filter: none;
}

@media (prefers-reduced-motion: reduce) {
  html.js .entre,
  html.js .entre.vu {
    opacity: 1;
    transform: none;
    filter: none;
    transition: none;
  }
  .bouton:hover,
  .porte:hover {
    transform: none;
  }
}

/* ---------- Pages de texte (confidentialité, contact, suppression) ---------- */
.texte {
  max-width: 760px;
  padding-top: clamp(30px, 5vw, 56px);
  padding-bottom: 80px;
}

.texte h1 {
  font-size: clamp(2rem, 5vw, 2.9rem);
  margin-bottom: 8px;
}

.texte .maj {
  color: var(--texte-3);
  font-size: 14px;
  margin: 0 0 40px;
}

.texte h2 {
  font-family: var(--titre);
  font-weight: 500;
  font-size: 1.4rem;
  letter-spacing: -0.012em;
  color: var(--lilas);
  margin: 40px 0 12px;
}

.texte p,
.texte li {
  color: var(--texte-2);
  max-width: 66ch;
}

.texte strong {
  color: var(--texte);
  font-weight: 600;
}

.texte ul {
  padding-left: 20px;
}

.texte li {
  margin-bottom: 10px;
}

.encadre {
  border-left: 1px solid var(--menthe);
  padding: 4px 0 4px 22px;
  margin: 26px 0;
}

.encadre p {
  margin: 0;
  color: var(--texte);
}

/* ---------- Le lexique ---------- */
.groupe {
  margin-top: 54px;
}

.groupe > h2 {
  font-family: var(--titre);
  font-size: 1.5rem;
  font-weight: 500;
  letter-spacing: -0.014em;
  color: var(--lilas);
  margin: 0 0 4px;
  padding-bottom: 14px;
  border-bottom: 1px solid rgba(200, 180, 240, 0.16);
}

.mot {
  padding: 22px 0;
  border-bottom: 1px solid rgba(200, 180, 240, 0.1);
}

.mot h3 {
  display: flex;
  align-items: baseline;
  gap: 14px;
  flex-wrap: wrap;
  font-family: var(--titre);
  font-weight: 500;
  font-size: 1.35rem;
  letter-spacing: -0.012em;
  color: var(--texte);
  margin: 0 0 8px;
}

/* L'arabe a besoin d'air et d'une taille à lui. */
.mot .ar {
  font-family: "Amiri", "Traditional Arabic", serif;
  font-size: 1.2rem;
  line-height: 1.9;
  color: var(--lilas);
  font-weight: 400;
}

.mot p {
  margin: 0;
}

.mot .source {
  margin-top: 8px;
  font-size: 13.5px;
  color: var(--menthe);
  letter-spacing: 0.02em;
}

/* Verdict du 19/08/2026 (« trop de texte, pas adapté sur iPhone ou iPad ») :
   sur petit écran, la typo des rangées se resserre pour que chaque bloc de
   texte reste plus court que le visuel qu'il accompagne. */
@media (max-width: 640px) {
  .rangee { padding-top: 34px; }
  .rangee h2 { font-size: 1.6rem; }
  .sa-phrase { font-size: 1.08rem; }
  .promesse { line-height: 1.55; }
}

/* Verdict du 20/08/2026 (« toujours cata sur iPhone ») : au pouce, on defile
   plus vite que les 0,85 s de fondu d'entree, donc on regarde toujours des
   zones encore vides. Au telephone, aucune choregraphie d'entree : le contenu
   est la, immediatement. Le bureau garde ses entrees. */
@media (max-width: 879px) {
  html.js .ouverture-texte,
  html.js .ouverture-tel,
  html.js .rangee-texte,
  html.js .rangee .telephone {
    animation: none;
  }
  html.js .entre {
    opacity: 1;
    transform: none;
    filter: none;
    transition: none;
  }
  html.js .rangee .telephone,
  html.js .rangee .fenetre {
    transform: none !important;
    transition: none;
  }
  html.js .ouverture-texte h1 .ligne > span {
    transform: none;
    transition: none;
  }
}

/* ---------- Retour en haut ----------
   La page d'accueil fait environ 11 000 px au telephone : sans ce bouton, on
   remonte au pouce pendant plusieurs secondes. Il n'apparait qu'une fois la
   premiere hauteur d'ecran passee, et il ne concurrence jamais l'action
   principale : discret, en bas a droite, sous l'en-tete collant. */
.haut {
  position: fixed;
  right: clamp(16px, 4vw, 34px);
  bottom: clamp(16px, 4vw, 34px);
  z-index: 9;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 46px;
  height: 46px;
  border: 1px solid rgba(200, 180, 240, 0.26);
  border-radius: 999px;
  background: rgba(18, 16, 43, 0.92);
  -webkit-backdrop-filter: blur(12px);
  backdrop-filter: blur(12px);
  color: var(--texte-2);
  cursor: pointer;
  opacity: 0;
  visibility: hidden;
  transform: translateY(10px);
  transition:
    opacity 0.3s var(--sortie),
    transform 0.3s var(--sortie),
    visibility 0.3s,
    color 0.24s var(--sortie);
}

.haut svg {
  width: 20px;
  height: 20px;
}

.haut[data-vu="oui"] {
  opacity: 1;
  visibility: visible;
  transform: none;
}

.haut:hover {
  color: var(--texte);
}

/* ---------- Impression ----------
   Les pages qu'on imprime vraiment : confidentialite, suppression de compte,
   contact. Un examinateur d'Apple ou de Google en garde une copie, et une
   lectrice peut vouloir la sienne. Sur papier, le ciel de nuit devient du noir
   d'encre : on repasse en noir sur blanc, on retire le decor, et chaque lien
   ecrit son adresse. */
@media print {
  #ciel,
  .aurore,
  .haut,
  .menu-bouton,
  .entete .bouton,
  .scene-lune {
    display: none !important;
  }

  html,
  body,
  .entete,
  .pied {
    background: #fff !important;
    color: #000 !important;
    -webkit-backdrop-filter: none !important;
    backdrop-filter: none !important;
  }

  .entete {
    position: static !important;
    border-bottom: 1px solid #ccc;
  }

  .marque {
    color: #000 !important;
  }

  .bande {
    max-width: none;
    padding: 0;
  }

  h1,
  h2,
  h3,
  .titre-section,
  strong {
    color: #000 !important;
  }

  p,
  li,
  .maj,
  .chapeau-section {
    color: #1a1a1a !important;
  }

  a {
    color: #000 !important;
    text-decoration: underline;
  }

  /* Un lien imprime ne mene nulle part si son adresse n'est pas ecrite. */
  main a[href^="http"]::after,
  main a[href^="mailto"]::after {
    content: " (" attr(href) ")";
    font-size: 0.85em;
    word-break: break-all;
  }

  .encadre {
    border: 1px solid #999;
    background: none;
  }

  h1,
  h2 {
    page-break-after: avoid;
  }
}

/* Le bouton « copier l'adresse » de la page contact. Cache par defaut : le
   script le montre seulement si le navigateur sait copier. */
.copier {
  display: inline-flex;
  align-items: center;
  margin-left: 10px;
  padding: 7px 13px;
  border: 1px solid rgba(200, 180, 240, 0.26);
  border-radius: 999px;
  background: transparent;
  color: var(--texte-2);
  font: inherit;
  font-size: 14px;
  cursor: pointer;
  transition: color 0.24s var(--sortie), border-color 0.24s var(--sortie);
}

.copier:hover {
  color: var(--texte);
  border-color: rgba(200, 180, 240, 0.5);
}

/* Liens de lecture et signature de la nouvelle rédaction. */
.liens-guides {
  display: flex;
  justify-content: center;
  flex-wrap: wrap;
  gap: 10px 24px;
  margin: 22px 0 0;
}
.liens-guides a { padding: 10px 0; }
.pied .signature { display: inline-block; margin-top: 8px; font-size: 0.85rem; color: var(--texte-2); }

/* Comparatif court : les mêmes lignes pour chaque appli, avec sources à ouvrir. */
.tableau thead th:first-child { width: 26%; }
.tableau th, .tableau td { padding: 16px 12px; }
.sources-comparatif { max-width: 920px; margin: 8px auto 0; color: var(--texte-2); font-size: 14px; }
.sources-comparatif summary { width: fit-content; padding: 14px 0; cursor: pointer; color: var(--lilas); }
.sources-comparatif p { max-width: 74ch; }
.sources-comparatif ul { padding-left: 20px; }
.sources-comparatif li { margin-bottom: 12px; }
.sources-comparatif a { display: inline-block; padding: 10px 0; }
#comparaison .note-tableau { max-width: 920px; color: var(--texte-2); }
.aide-comparatif { display: none; }
@media (max-width: 640px) {
  .aide-comparatif { display: block; margin: 20px 0 0; color: var(--texte-2); font-size: 13px; }
  .tableau-enveloppe { margin-top: 10px; }
  .tableau { font-size: 14px; }
  .tableau thead th:first-child, .tableau tbody th {
    position: sticky;
    left: 0;
    z-index: 1;
    background: #15122c;
    box-shadow: 8px 0 12px -12px #000;
  }
}
