/* ============================================================
   LunaCycle, 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 ---------- */
.entete {
  position: relative;
  z-index: 10;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding-top: 22px;
  padding-bottom: 22px;
}

.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);
}

/* Sur petit écran, les liens de texte disparaissent : ils sont repris dans le
   pied de page, et l'action principale garde la place. */
@media (max-width: 620px) {
  .menu > a:not(.bouton) {
    display: none;
  }
}

/* ---------- 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;
}

/* ---------- 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);
}

.telephone img {
  width: 100%;
  border-radius: 36px;
}

/* ---------- 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;
}

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. */
#traversee {
  overflow-x: clip;
}

.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 h3 {
  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;
  justify-items: center;
}

.beat {
  margin: 0;
  color: var(--texte-2);
  max-width: 54ch;
}

.beat-1,
.beat-3 {
  font-size: clamp(1.15rem, 2.2vw, 1.5rem);
  line-height: 1.5;
}

.beat-2 {
  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. */
@media (prefers-reduced-motion: no-preference) {
  @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;
    }

    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 {
  width: 100%;
  max-width: 920px;
  margin: 0 auto;
  min-width: 640px;
  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.1em;
  text-transform: uppercase;
  color: var(--texte-3);
  border-bottom-color: rgba(200, 180, 240, 0.24);
  white-space: nowrap;
}

.tableau tbody th {
  font-weight: 400;
  color: var(--texte);
  width: 42%;
}

.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: attr(data-jour) / "";
  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. */
.rangee::after {
  content: "";
  position: absolute;
  z-index: 0;
  inset: 6% -12% 6% 30%;
  background: radial-gradient(
    58% 58% at 68% 50%,
    color-mix(in srgb, var(--de, #c8b4f0) 11%, transparent),
    transparent 74%
  );
  pointer-events: none;
}

.rangee.inverse::after {
  inset: 6% 30% 6% -12%;
  background: radial-gradient(
    58% 58% at 32% 50%,
    color-mix(in srgb, var(--de, #c8b4f0) 11%, transparent),
    transparent 74%
  );
}

.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;
  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;
}
