/* ============================================================
   Hanken Grotesk — police variable (une seule famille, 100→900).
   Auto-hébergée : aucun appel à un CDN de polices (RGPD/CNIL).
   ============================================================ */
@font-face {
  font-family: 'Hanken Grotesk';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("fonts/font-290037c6-1cb4-4656-a97c-9e00ca87e279.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: 'Hanken Grotesk';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("fonts/font-207c71bf-9453-434b-adc2-56131f2fe8f6.woff2") format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* ============================================================
   JETONS
   Registre : plaque émaillée. Vert profond en aplat, lettrage
   clair, arêtes nettes, filets fins. Le vert porte la marque
   (stratégie « committed »), il n'est pas un simple accent.
   ============================================================ */
:root {
  /* Verts — l'émail */
  --vert-900: oklch(0.26 0.050 168);
  --vert-800: oklch(0.36 0.075 167);
  --vert-700: oklch(0.44 0.088 166);
  --vert-600: oklch(0.52 0.098 165);
  --vert-300: oklch(0.80 0.115 162);

  /* Encre — le bleu nuit de la marque */
  --encre:      oklch(0.25 0.028 245);
  --encre-doux: oklch(0.44 0.022 245);
  --encre-tres-doux: oklch(0.55 0.018 245);

  /* Fonds clairs : blanc cassé teinté VERS le vert de la marque,
     jamais vers le crème/sable. */
  --papier:  oklch(0.985 0.004 165);
  --surface: oklch(0.955 0.006 165);
  --craie:      oklch(0.97 0.010 160);
  --craie-doux: oklch(0.88 0.022 165);

  /* Filets */
  --trait:       color-mix(in oklch, var(--encre) 14%, transparent);
  --trait-fort:  color-mix(in oklch, var(--encre) 30%, transparent);
  --trait-clair: color-mix(in oklch, var(--craie) 22%, transparent);

  /* Statuts */
  --statut-attente: oklch(0.52 0.03 250);
  --statut-cours:   oklch(0.52 0.13 250);
  --statut-fini:    var(--vert-600);

  /* Rayon : la plaque est nette. Presque pas d'arrondi. */
  --r: 3px;

  /* Rythme */
  --page: 1120px;
  --gouttiere: clamp(20px, 5vw, 40px);
  --section: clamp(60px, 7vw, 104px);
  /* Hauteur de nav figée : le héros s'en déduit (100svh - nav) pour que
     nav + héros fassent exactement un écran. */
  --nav-h: 68px;

  /* Profondeur (échelle sémantique, jamais de 9999) */
  --z-sticky: 100;
  --z-nav: 200;
  --z-modale: 300;

  /* Courbe : sortie exponentielle, sans rebond */
  --sortie: cubic-bezier(0.22, 1, 0.36, 1);
}

/* ============================================================
   BASE
   ============================================================ */
*, *::before, *::after { box-sizing: border-box; }
html { scroll-behavior: smooth; }

/* Défilement libre. On garde seulement scroll-margin-top pour que les
   ancres du menu ne fassent pas passer les titres sous la nav collante. */
.emaille--ecran,
main > section { scroll-margin-top: var(--nav-h); }

/* Tarifs : l'ancre vise le TITRE, pas le haut de la section. Le titre est
   sous le padding-haut de la section (var(--section)) ; on retranche donc
   ce padding pour que la section remonte et cale « Un prix clair, sans
   surprise. » juste sous la nav (+16px de respiration). */
#tarifs { scroll-margin-top: calc(var(--nav-h) - var(--section) + 16px); }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
}

body {
  margin: 0;
  background: var(--papier);
  color: var(--encre);
  font-family: 'Hanken Grotesk', system-ui, sans-serif;
  font-size: 17px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

h1, h2, h3 { margin: 0; text-wrap: balance; }
p { margin: 0; text-wrap: pretty; }
a { color: inherit; text-decoration: none; }
svg { display: block; }

:focus-visible {
  outline: 2px solid var(--vert-600);
  outline-offset: 3px;
  border-radius: 2px;
}
.emaille :focus-visible { outline-color: var(--vert-300); }

.saut-contenu {
  position: absolute; left: -9999px;
  background: var(--encre); color: var(--craie);
  padding: 12px 18px; border-radius: var(--r);
}
.saut-contenu:focus { left: 16px; top: 16px; z-index: var(--z-nav); }

/* ============================================================
   TYPOGRAPHIE
   Une seule famille. Le contraste vient de la graisse (400→800)
   et de l'échelle (ratio ≥ 1.25), pas d'un second caractère.
   Chiffres tabulaires partout où il y a des nombres : ça remplace
   le monospace sans en avoir le costume.
   ============================================================ */
.titre-geant {
  font-weight: 800;
  font-size: clamp(2.5rem, 6.2vw, 4.6rem);  /* max 73.6px, plafond 96px respecté */
  line-height: 1.02;
  letter-spacing: -0.032em;                  /* plancher -0.04em respecté */
}
.titre {
  font-weight: 700;
  font-size: clamp(1.9rem, 3.6vw, 2.75rem);
  line-height: 1.1;
  letter-spacing: -0.022em;
}
.titre-petit {
  font-weight: 700;
  font-size: clamp(1.4rem, 2.2vw, 1.65rem);
  line-height: 1.2;
  letter-spacing: -0.015em;
}
.titre-mini {
  margin: 0;
  font-weight: 700;
  font-size: 1.06rem;
  line-height: 1.25;
  letter-spacing: -0.01em;
}
.chapo {
  font-size: clamp(1.06rem, 1.5vw, 1.2rem);
  line-height: 1.6;
  color: var(--encre-doux);
  max-width: 62ch;
}
.chapo-clair { color: var(--craie-doux); }
.lede { color: var(--encre-doux); max-width: 68ch; }
.nb { font-variant-numeric: tabular-nums; }

/* ============================================================
   MISE EN PAGE
   ============================================================ */
.page { max-width: var(--page); margin: 0 auto; padding-inline: var(--gouttiere); }
.section { padding-block: var(--section); }
.section--serre { padding-block: calc(var(--section) * 0.62); }

/* Bloc d'appui : une sous-partie DANS un pilier. Un filet fin et un
   écart serré, au lieu des 256px + titre de rang égal qui donnaient
   à une fonctionnalité secondaire le même poids qu'un pilier. */
.appui {
  margin-top: clamp(38px, 4.6vw, 62px);
  padding-top: clamp(30px, 3.6vw, 46px);
  border-top: 1px solid var(--trait);
}

/* Filet de tête de section : le « rythme » vient de là,
   pas d'un chapeau majuscule tracké au-dessus de chaque titre. */
.filet {
  border: 0; height: 1px; margin: 0 0 clamp(28px, 4vw, 48px);
  background: var(--trait);
}
.emaille .filet, .nuit .filet { background: var(--trait-clair); }

.duo {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: clamp(32px, 5vw, 64px);
}
.duo--bas { align-items: end; }
/* Ce panneau est premier dans le DOM (donc à gauche du texte sur grand
   écran). En colonne unique il faut le pousser APRÈS le texte — sinon une
   ancre dépose le lecteur sur une capture, titre de section hors écran. */
@media (max-width: 700px) { .duo__avant { order: 1; } }

/* ============================================================
   BOUTONS
   ============================================================ */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  font: inherit; font-weight: 600; font-size: 1rem;
  padding: 13px 24px;
  border: 1px solid transparent;
  border-radius: var(--r);
  cursor: pointer;
  transition: background-color .18s var(--sortie), color .18s var(--sortie),
              border-color .18s var(--sortie), transform .18s var(--sortie);
}
.btn:active { transform: translateY(1px); }

.btn--plein { background: var(--vert-600); color: var(--papier); }
.btn--plein:hover { background: var(--vert-700); }

.btn--craie { background: var(--craie); color: var(--vert-900); }
.btn--craie:hover { background: #fff; }

.btn--ligne { border-color: var(--trait-fort); color: var(--encre); }
.btn--ligne:hover { border-color: var(--encre); background: var(--surface); }

.emaille .btn--ligne { border-color: var(--trait-clair); color: var(--craie); }
.emaille .btn--ligne:hover { border-color: var(--craie); background: color-mix(in oklch, var(--craie) 10%, transparent); }

/* « Ouverture prochaine » / « Prévenez-moi » : bouton vert plein, bien visible
   sur tous les fonds (héros clair, émail sombre, carte nuit). Texte vert foncé
   pour le contraste — la même pastille partout, sans surcharge par fond. */
.bientot {
  display: inline-flex; align-items: center; gap: 10px;
  font: inherit; font-weight: 600;
  padding: 13px 22px;
  border: 1px solid transparent;
  border-radius: var(--r);
  background: #8cdcb5;
  color: var(--vert-900);
  cursor: pointer;
  transition: background-color .18s var(--sortie), transform .18s var(--sortie);
}
.bientot:hover { background: color-mix(in srgb, #8cdcb5 88%, #14503b); }
.bientot:active { transform: translateY(1px); }
/* Cloche « on vous préviendra » : remplace l'ancienne pastille — un seul
   marqueur, et qui dit l'action plutôt qu'un simple état. */
.bientot__cloche { align-self: center; flex: none; color: var(--vert-900); }
/* Libellé en deux temps : l'action, puis la note d'essai dessous — un
   vrai CTA lisible à toute largeur, sans repli désordonné dans les cartes. */
.bientot__txt { display: flex; flex-direction: column; align-items: flex-start; gap: 2px; line-height: 1.25; text-align: left; }
.offre .bientot__txt { align-items: center; text-align: center; }
.bientot small { font-weight: 400; font-size: .8em; color: var(--vert-800); }

/* ============================================================
   MODALE LISTE D'ATTENTE — « Prévenez-moi à l'ouverture »
   ============================================================ */
.modale {
  position: fixed; inset: 0; z-index: var(--z-modale);
  display: none; align-items: center; justify-content: center;
  padding: 20px;
  background: color-mix(in oklch, var(--vert-900) 60%, transparent);
  -webkit-backdrop-filter: blur(2px); backdrop-filter: blur(2px);
}
.modale[aria-hidden="false"] { display: flex; }
.modale__panneau {
  position: relative;
  width: 100%; max-width: 440px;
  background: var(--papier);
  border: 1px solid var(--trait);
  border-top: 3px solid var(--vert-600);
  border-radius: var(--r);
  padding: 34px 30px 28px;
  box-shadow: 0 24px 60px -20px color-mix(in oklch, var(--vert-900) 55%, transparent);
}
.modale__fermer {
  position: absolute; top: 12px; right: 12px;
  width: 34px; height: 34px;
  display: inline-flex; align-items: center; justify-content: center;
  border: none; background: transparent; border-radius: var(--r);
  font: inherit; font-size: 1.5rem; line-height: 1; color: var(--encre-doux);
  cursor: pointer;
  transition: background-color .15s var(--sortie), color .15s var(--sortie);
}
.modale__fermer:hover { background: var(--surface); color: var(--encre); }
.modale__titre { font-size: 1.4rem; font-weight: 800; letter-spacing: -0.02em; color: var(--encre); max-width: 20ch; }
.modale__texte { margin-top: 10px; color: var(--encre-doux); font-size: .95rem; line-height: 1.5; }
.modale__form { margin-top: 22px; display: flex; flex-direction: column; gap: 12px; }
.modale__label { font-size: .85rem; font-weight: 600; color: var(--encre); }
.modale__input {
  font: inherit; width: 100%;
  padding: 12px 14px;
  border: 1px solid var(--trait-fort); border-radius: var(--r);
  background: #fff; color: var(--encre);
  transition: border-color .15s var(--sortie), box-shadow .15s var(--sortie);
}
.modale__input:focus {
  outline: none; border-color: var(--vert-600);
  box-shadow: 0 0 0 3px color-mix(in oklch, var(--vert-600) 18%, transparent);
}
.modale__textarea { min-height: 104px; resize: vertical; line-height: 1.5; }
.modale__opt { font-weight: 400; color: var(--encre-tres-doux); }
.modale__form .btn { width: 100%; margin-top: 2px; }
.modale__mention { font-size: .78rem; color: var(--encre-tres-doux); line-height: 1.45; }
.modale__erreur { font-size: .85rem; color: oklch(0.55 0.17 25); min-height: 1.15em; margin: -4px 0 0; }
.modale__succes { text-align: center; padding: 6px 0 4px; }
.modale__succes-pastille {
  width: 46px; height: 46px; margin: 0 auto 14px;
  display: flex; align-items: center; justify-content: center;
  border-radius: 50%; background: color-mix(in oklch, var(--vert-600) 16%, transparent);
}
/* Honeypot : hors écran mais laissé dans le flux pour les bots. */
.modale__pot { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }
@media (prefers-reduced-motion: no-preference) {
  .modale[aria-hidden="false"] .modale__panneau { animation: modale-entree .28s var(--sortie); }
}
@keyframes modale-entree { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }

/* ============================================================
   L'ÉMAIL : le vert porte 40 % de la page.
   ============================================================ */
.emaille {
  background: var(--vert-800);
  color: var(--craie);
}

/* Le héros tient exactement le premier écran. Sans ça, la hauteur du vert
   est dictée par celle du contenu et la coupure tombe à un endroit
   arbitraire, différent sur chaque écran : c'est ce qui « fait bizarre ».
   svh (et non vh) pour que la barre d'adresse mobile ne déborde pas. */
.emaille--ecran {
  min-height: calc(100vh - var(--nav-h));
  min-height: calc(100svh - var(--nav-h));
  display: flex;
  flex-direction: column;
}

/* Héros clair : blanc cassé teinté vers le vert de la marque (--papier),
   texte encre. Le vert n'ouvre plus la page en aplat — il l'encadre
   (nav en haut, appel final + bande nuit plus bas). Sur ce fond clair, la
   capture produit n'a plus le contraste de l'émail : on lui donne un filet
   plus marqué et une ombre plus portante pour qu'elle reste « la fenêtre ». */
.heros-clair {
  background: var(--papier);
  color: var(--encre);
}
.heros-clair .heros__mention { color: var(--encre-tres-doux); }
.heros-clair .panneau {
  border-color: var(--trait-fort);
  box-shadow: 0 1px 2px color-mix(in oklch, var(--encre) 5%, transparent),
              0 30px 60px -30px color-mix(in oklch, var(--vert-900) 42%, transparent);
}

/* ------- Barre de navigation ------- */
.nav {
  position: sticky; top: 0; z-index: var(--z-nav);
  /* Vert foncé du pied de page : la nav et le footer encadrent la page
     avec la même valeur, l'émail du héros reste plus clair entre les deux. */
  background: var(--vert-900);
  border-bottom: 1px solid var(--trait-clair);
}
/* Une fois le héros dépassé, la nav se détache par une ombre portée :
   petit signal d'état au défilement, sans changer la mise en page. */
.nav--pose { box-shadow: 0 10px 26px -18px color-mix(in oklch, var(--vert-900) 80%, transparent); }
@media (prefers-reduced-motion: no-preference) {
  .nav { transition: box-shadow .3s var(--sortie); }
}
.nav__in {
  max-width: var(--page); margin: 0 auto;
  /* -1px : la bordure de la nav compte dans les 68px du jeton. */
  min-height: calc(var(--nav-h) - 1px);
  padding-inline: var(--gouttiere);
  display: flex; align-items: center; gap: 32px;
}
.marque { display: flex; align-items: center; gap: 11px; font-weight: 700; font-size: 1.3rem; letter-spacing: -0.02em; }
/* Blanc pur, pas la craie légèrement verte du reste de l'émail. */
.nav .marque { color: #fff; }
.nav__liens { display: flex; gap: 26px; margin-left: auto; font-size: .95rem; }
.nav__liens a { color: var(--craie-doux); transition: color .15s var(--sortie); }
.nav__liens a:hover { color: var(--craie); }
.nav__actions { display: flex; align-items: center; gap: 14px; }
.nav__actions .connexion { font-weight: 600; font-size: .95rem; color: var(--craie); }
.nav__actions .connexion:hover { text-decoration: underline; text-underline-offset: 4px; }
.nav__bientot {
  display: inline-flex; align-items: center; gap: 6px;
  font: inherit; font-size: .85rem; font-weight: 600; color: var(--vert-900);
  background: var(--vert-300);
  border: none;
  padding: 7px 13px; border-radius: var(--r);
  cursor: pointer;
  transition: background-color .15s var(--sortie), transform .15s var(--sortie);
}
.nav__bientot svg { flex: none; }
.nav__bientot:hover { background: color-mix(in oklch, var(--vert-300) 84%, #fff); }
.nav__bientot:active { transform: translateY(1px); }
@media (max-width: 900px) { .nav__liens { display: none; } }
@media (max-width: 560px) { .nav__actions .connexion { display: none; } }

/* ------- Héros ------- */
/* Titre pleine largeur AU-DESSUS de la grille (hors de la colonne étroite) :
   il respire sur 2-3 lignes larges au lieu de se casser en 6 à côté du mock.
   text-wrap: balance répartit les lignes proprement. */
.heros__texte { max-width: 24ch; text-wrap: balance; margin-bottom: clamp(28px, 3.5vw, 44px); }
.heros .chapo { margin-top: 0; }
.heros__cta { display: flex; flex-wrap: wrap; gap: 14px; margin-top: 34px; }
.heros__mention { margin-top: 20px; font-size: .92rem; color: var(--craie-doux); }

.heros__grille {
  display: grid;
  grid-template-columns: minmax(0, 0.86fr) minmax(0, 1.14fr);
  gap: clamp(32px, 5vw, 56px);
  align-items: center;
}
@media (max-width: 940px) {
  .heros__grille { grid-template-columns: 1fr; }
  .heros__texte { max-width: 100%; }
}

/* Le héros occupe la hauteur restante sous la nav, contenu centré.
   Le panneau reste entièrement DANS le vert : la fenêtre éclairée est
   dans le mur, elle n'en sort pas. Un débord par marge négative se
   battrait avec le plein écran (quand le contenu est court, l'espace
   libre l'avale) et la coupure redeviendrait imprévisible. */
.heros {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding-block: clamp(32px, 4vw, 56px);
}

/* ============================================================
   PANNEAU PRODUIT (les captures — l'imagerie de la page)
   ============================================================ */
.panneau {
  /* Le panneau s'adapte à SA largeur, pas à celle de l'écran : le même
     composant sert en colonne étroite (héros) et en pleine largeur.
     Sans ça, les colonnes fixes saturent l'espace et « objet », qui est
     la colonne utile, se fait écraser à zéro. */
  container-type: inline-size;
  background: #fff;
  /* Encre imposée : dans le héros, le panneau est enfant de .emaille et
     héritait la craie (blanc cassé) — donc du blanc sur blanc, illisible. */
  color: var(--encre);
  border: 1px solid var(--trait);
  border-radius: var(--r);
  overflow: hidden;
  box-shadow: 0 1px 1px color-mix(in oklch, var(--encre) 4%, transparent),
              0 26px 50px -28px color-mix(in oklch, var(--vert-900) 55%, transparent);
}
.panneau__barre {
  display: flex; align-items: center; gap: 12px;
  padding: 9px 14px;
  background: var(--surface);
  border-bottom: 1px solid var(--trait);
}
.panneau__url {
  font-size: .78rem; color: var(--encre-tres-doux);
  background: #fff; border: 1px solid var(--trait);
  border-radius: 2px; padding: 4px 12px;
}
/* Pas de hauteur plancher : le panneau prend la hauteur de son contenu.
   Les 400px imposés gonflaient des captures qui n'en demandaient que 300. */
.panneau__corps { display: flex; }
.panneau--plat .panneau__corps { display: block; min-height: 0; }

/* Rail latéral de l'app */
.rail { width: 196px; flex: 0 0 auto; background: var(--encre); padding: 16px 12px; }
.rail__marque { display: flex; align-items: center; gap: 8px; padding: 4px 6px 16px; font-weight: 700; font-size: .95rem; color: var(--craie); }
.rail__item { display: flex; align-items: center; gap: 10px; padding: 8px 10px; border-radius: 2px; font-size: .84rem; color: color-mix(in oklch, var(--craie) 62%, transparent); }
.rail__item .puce { width: 14px; height: 14px; border-radius: 2px; background: color-mix(in oklch, var(--craie) 22%, transparent); flex: 0 0 auto; }
.rail__item--actif { background: color-mix(in oklch, var(--vert-600) 30%, transparent); color: var(--craie); font-weight: 600; }
.rail__item--actif .puce { background: var(--vert-300); }
.rail__item .compte { margin-left: auto; font-size: .78rem; color: var(--vert-300); font-variant-numeric: tabular-nums; }

.vue { flex: 1 1 0%; display: flex; flex-direction: column; background: #fff; min-width: 0; }
.vue__tete {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 15px 18px; border-bottom: 1px solid var(--trait);
}
.vue__titre { font-weight: 700; font-size: 1.05rem; letter-spacing: -0.01em; }
.vue__outils { display: flex; align-items: center; gap: 9px; }
.jeton {
  font-size: .78rem; color: var(--encre-tres-doux);
  border: 1px solid var(--trait); border-radius: 2px; padding: 5px 11px;
}
.jeton--vert { background: var(--vert-600); color: #fff; border-color: transparent; font-weight: 600; }

/* Lignes de tickets */
.ligne {
  display: flex; align-items: center; gap: 14px;
  padding: 12px 18px;
  border-bottom: 1px solid color-mix(in oklch, var(--encre) 7%, transparent);
  font-size: .88rem;
}
.ligne:last-child { border-bottom: 0; }
.ligne .ref { width: 66px; flex: 0 0 auto; color: var(--encre-tres-doux); font-variant-numeric: tabular-nums; font-weight: 500; }
.ligne .objet { flex: 1 1 0%; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ligne .client, .ligne .provenance { width: 128px; flex: 0 0 auto; color: var(--encre-tres-doux); font-size: .82rem; }
.ligne .qui {
  width: 26px; height: 26px; flex: 0 0 auto; border-radius: 50%;
  display: grid; place-items: center;
  font-size: .66rem; font-weight: 700;
  background: var(--encre); color: var(--craie);
}
.ligne .qui--vert { background: var(--vert-600); color: #fff; }

/* Dégressif par largeur de panneau. « objet » n'est jamais sacrifié :
   c'est la seule colonne qui dit de quoi parle le ticket. */
@container (max-width: 760px) { .ligne .client, .ligne .provenance { display: none; } }
@container (max-width: 560px) { .rail { display: none; } }
@container (max-width: 400px) { .ligne .ref { display: none; } }

.etat {
  width: 82px; flex: 0 0 auto; text-align: center;
  font-size: .72rem; font-weight: 700; letter-spacing: .01em;
  padding: 4px 0; border-radius: 2px;
}
.etat--attente { color: var(--statut-attente); background: color-mix(in oklch, var(--statut-attente) 12%, transparent); }
.etat--cours   { color: var(--statut-cours);   background: color-mix(in oklch, var(--statut-cours) 12%, transparent); }
.etat--fini    { color: var(--vert-700);       background: color-mix(in oklch, var(--vert-600) 14%, transparent); }

/* ============================================================
   LA TRIADE — trois colonnes séparées par des filets.
   Pas de cartes, pas de tuiles d'icônes arrondies.
   ============================================================ */
.triade {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  border-top: 1px solid var(--trait);
}
.triade__col {
  padding: clamp(28px, 3.4vw, 40px) clamp(20px, 2.6vw, 34px);
  border-bottom: 1px solid var(--trait);
  border-right: 1px solid var(--trait);
}
.triade__col:last-child { border-right: 0; }
.triade__col h3 { margin-bottom: 10px; }
.triade__col p { color: var(--encre-doux); font-size: .97rem; }
.triade__num {
  display: block; width: 26px; height: 2px;
  background: var(--vert-600); margin-bottom: 18px;
  transition: width .25s var(--sortie);
}
@media (max-width: 800px) { .triade__col { border-right: 0; } }

/* Colonnes-liens : uniquement la première triade (la seconde, les
   périmètres commerciaux, reste du texte simple). */
a.triade__col { display: block; color: inherit; transition: background-color .2s var(--sortie); }
a.triade__col:hover { background: var(--surface); }
a.triade__col:hover .triade__num { width: 44px; }

.triade__aller {
  display: inline-flex; align-items: center; gap: 7px;
  margin-top: 18px;
  font-size: .92rem; font-weight: 600;
  color: var(--vert-700);
}
.triade__aller svg { transition: transform .25s var(--sortie); }
a.triade__col:hover .triade__aller svg { transform: translateX(4px); }
/* Même signe posé sur un lien isolé (fin de section, renvoi vers une page
   dédiée) : là c'est le lien lui-même qui porte le survol, pas la colonne. */
a.triade__aller:hover svg { transform: translateX(4px); }
a.triade__aller:hover { text-decoration: underline; text-underline-offset: 4px; }
.emaille a.triade__aller { color: var(--vert-300); }
@media (prefers-reduced-motion: reduce) {
  .triade__num, .triade__aller svg { transition: none; }
}

/* ============================================================
   ACHEMINEMENT EMAIL
   Les adresses font ~48 caractères : elles doivent pouvoir se casser
   n'importe où, sinon elles débordent du panneau en colonne étroite.
   ============================================================ */
.adresse {
  font-weight: 600;
  color: var(--encre);
  overflow-wrap: anywhere;
  font-variant-numeric: tabular-nums;
}
.route {
  display: flex; flex-direction: column; gap: 9px;
  border: 1px solid var(--trait);
  border-radius: var(--r);
  padding: 12px 14px;
}
.route__adresse {
  font-size: .84rem;
  line-height: 1.4;
  color: var(--encre-tres-doux);
  overflow-wrap: anywhere;
}
.route__adresse strong { color: var(--encre); font-weight: 700; }
.route__vers {
  display: inline-flex; align-items: center; gap: 8px;
  color: var(--vert-600);
}
/* .etat a une largeur fixe de 82px pour les tableaux de tickets ;
   ici l'étiquette porte un nom d'équipe, elle doit s'adapter. */
.route .etat { width: auto; padding: 4px 10px; }

/* ============================================================
   LISTES À COCHES
   ============================================================ */
.coches { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 11px; }
.coches li { display: flex; align-items: flex-start; gap: 11px; font-size: .97rem; }
.coches svg { flex: 0 0 auto; margin-top: 3px; }

/* ============================================================
   INVENTAIRE (« et tout le reste ») — liste réglée, pas 6 cartes.
   ============================================================ */
.inventaire {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: 0 clamp(32px, 5vw, 64px);
  border-top: 1px solid var(--trait);
}
.inventaire__item {
  padding: 22px 0;
  border-bottom: 1px solid var(--trait);
  display: grid; grid-template-columns: auto 1fr; gap: 4px 14px;
}
.inventaire__item dt { font-weight: 700; grid-column: 2; }
.inventaire__item dd { margin: 0; grid-column: 2; color: var(--encre-doux); font-size: .95rem; }
.inventaire__item::before {
  content: ""; grid-row: 1 / span 2; grid-column: 1;
  width: 3px; border-radius: 2px; background: var(--vert-600);
  align-self: stretch;
}

/* ============================================================
   BANDE NUIT — le second monde de couleur (bleu encre)
   ============================================================ */
.nuit { background: var(--encre); color: var(--craie); }
.nuit .lede, .nuit .chapo { color: var(--craie-doux); }
.nuit .coches li { color: var(--craie); }

/* ============================================================
   TARIFS
   ============================================================ */
.bascule {
  display: inline-flex; align-items: center; gap: 3px;
  border: 1px solid var(--trait); border-radius: var(--r); padding: 3px;
  background: #fff;
}
.bascule button {
  font: inherit; font-weight: 600; font-size: .9rem;
  padding: 8px 18px; border: 0; border-radius: 2px;
  background: transparent; color: var(--encre-doux);
  cursor: pointer;
  display: inline-flex; align-items: center; gap: 7px;
  transition: background-color .18s var(--sortie), color .18s var(--sortie);
}
.bascule button[aria-selected="true"] { background: var(--vert-600); color: #fff; }
.bascule .gain {
  font-size: .72rem; font-weight: 700; padding: 2px 7px; border-radius: 2px;
  background: color-mix(in oklch, var(--vert-600) 14%, transparent); color: var(--vert-700);
  font-variant-numeric: tabular-nums;
}
.bascule button[aria-selected="true"] .gain { background: color-mix(in oklch, #fff 24%, transparent); color: #fff; }

.offres {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: 0; max-width: 860px; margin: 0 auto;
  border: 1px solid var(--trait-fort); border-radius: var(--r);
  overflow: hidden;
}
.offre { padding: clamp(24px, 2.6vw, 30px); display: flex; flex-direction: column; background: #fff; }
.offre + .offre { border-left: 1px solid var(--trait-fort); }
@media (max-width: 700px) { .offre + .offre { border-left: 0; border-top: 1px solid var(--trait-fort); } }
.offre--nuit { background: var(--encre); color: var(--craie); }
.offre__nom { font-weight: 700; font-size: .95rem; }
.offre--nuit .offre__nom { color: var(--vert-300); }
.offre__prix { display: flex; align-items: baseline; gap: 8px; margin-top: 10px; }
.offre__montant { font-weight: 800; font-size: 2.8rem; line-height: 1; letter-spacing: -0.03em; font-variant-numeric: tabular-nums; }
.offre__unite { font-size: .9rem; color: var(--encre-tres-doux); }
.offre--nuit .offre__unite { color: var(--craie-doux); }
.offre__note { margin-top: 7px; font-size: .85rem; color: var(--encre-tres-doux); }
.offre--nuit .offre__note { color: var(--craie-doux); }
.offre__filet { height: 1px; background: var(--trait); margin: 16px 0; }
.offre--nuit .offre__filet { background: var(--trait-clair); }
.offre .coches { flex: 1 1 auto; gap: 9px; }
.offre .bientot, .offre .btn { margin-top: 20px; justify-content: center; }
.offre__gratuit {
  font-size: .78rem; font-weight: 700; color: var(--vert-900);
  background: var(--vert-300); padding: 3px 9px; border-radius: 2px;
}

/* ============================================================
   FAQ
   ============================================================ */
.faq { border-top: 1px solid var(--trait); }
.faq details { border-bottom: 1px solid var(--trait); }
.faq summary {
  list-style: none; cursor: pointer;
  display: flex; align-items: center; justify-content: space-between; gap: 20px;
  /* 4px à droite : le chevron pivoté à 45° déborde de sa boîte de layout
     et gonflerait la zone de défilement du bloc. */
  padding: 20px 4px 20px 0;
  font-weight: 700; font-size: 1.05rem;
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after {
  content: ""; flex: 0 0 auto;
  width: 11px; height: 11px;
  border-right: 2px solid var(--vert-600); border-bottom: 2px solid var(--vert-600);
  transform: rotate(45deg) translateY(-2px);
  transition: transform .22s var(--sortie);
}
.faq details[open] summary::after { transform: rotate(-135deg) translateY(-2px); }
.faq .reponse { padding: 0 0 22px; color: var(--encre-doux); max-width: 68ch; }

/* ============================================================
   PIED DE PAGE
   ============================================================ */
.pied { background: var(--vert-900); color: var(--craie-doux); }
.pied__grille {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr));
  gap: 40px;
  padding-block: clamp(48px, 6vw, 64px) 36px;
}
.pied__marque { min-width: 190px; }
.pied__marque p { margin-top: 14px; font-size: .88rem; color: color-mix(in oklch, var(--craie) 62%, transparent); max-width: 26ch; }
.pied h2 { font-size: .82rem; font-weight: 700; letter-spacing: .02em; color: var(--vert-300); margin-bottom: 14px; }
.pied ul { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 10px; font-size: .92rem; }
.pied ul a { color: var(--craie-doux); }
.pied ul a:hover { color: var(--craie); text-decoration: underline; text-underline-offset: 3px; }
.pied__bas {
  border-top: 1px solid var(--trait-clair);
  padding-block: 18px;
  display: flex; justify-content: space-between; flex-wrap: wrap; gap: 10px;
  font-size: .84rem; color: color-mix(in oklch, var(--craie) 55%, transparent);
}

/* ============================================================
   MOUVEMENT
   Le défaut est VISIBLE : l'état masqué n'est posé que si JS
   tourne (html.js) et si l'utilisateur ne réclame pas moins de
   mouvement. Sans JS, ou en rendu headless, tout s'affiche.
   ============================================================ */
/* Filet de sécurité absolu : force l'affichage sans dépendre d'une
   transition. Une transition ne progresse pas dans un rendu non peint
   (onglet en arrière-plan, headless) ; poser « .vu » n'y suffirait donc
   pas et la section partirait blanche. Ici l'opacité saute à 1. */
.montre-tout .leve,
.montre-tout .heros__mock,
.montre-tout .heros__mock .ligne,
.montre-tout .stagger > *,
.montre-tout .seq :is(h2,h3,h4,p,ul,.panneau) {
  opacity: 1 !important;
  transform: none !important;
  transition: none !important;
}
.montre-tout .jauge { transform: scaleX(var(--fin, 0)) !important; transition: none !important; }

/* Jauge de progression (avancement projet) : remplissage par scaleX (GPU,
   sans reflow) depuis la gauche. Au repos elle vaut --fin ; quand JS tourne,
   elle part de 0 et se remplit à l'entrée dans le champ. --fin est un ratio
   (0.62), pas un pourcentage. */
.jauge {
  width: 100%; height: 100%; background: var(--vert-600); border-radius: inherit;
  transform: scaleX(var(--fin, 0)); transform-origin: left;
}

@media (prefers-reduced-motion: no-preference) {
  .js .leve { opacity: 0; transform: translateY(16px); }
  .js .leve.vu {
    opacity: 1; transform: none;
    transition: opacity .7s var(--sortie), transform .7s var(--sortie);
  }
  .js .heros__mock { opacity: 0; transform: translateY(26px); }
  .js .heros__mock.vu {
    opacity: 1; transform: none;
    transition: opacity .9s var(--sortie) .1s, transform .9s var(--sortie) .1s;
  }
  /* Le seul décalage en cascade de la page : les tickets qui
     tombent un par un. Il montre le produit en train de travailler. */
  .js .heros__mock .ligne { opacity: 0; transform: translateY(8px); }
  .js .heros__mock.vu .ligne {
    opacity: 1; transform: none;
    transition: opacity .5s var(--sortie), transform .5s var(--sortie);
    transition-delay: calc(.45s + var(--i) * .08s);
  }

  /* Décalage intra-liste : les enfants d'un groupe .stagger entrent l'un
     après l'autre quand le groupe passe le seuil. C'est du décalage de
     fratrie (colonnes, items d'inventaire, offres), pas un fondu de section
     de plus — chaque liste s'assemble au lieu d'apparaître d'un bloc. */
  .js .stagger > * { opacity: 0; transform: translateY(12px); }
  .js .stagger.vu > * {
    opacity: 1; transform: none;
    transition: opacity .55s var(--sortie), transform .55s var(--sortie);
    transition-delay: calc(var(--i, 0) * .06s);
  }

  /* Révélation « Apple » en deux temps : dans un groupe .seq, le titre
     (h2/h3/h4) monte en fondu, puis le corps (paragraphes, listes, panneau)
     suit avec un léger décalage. Le conteneur .seq ne bouge pas — il ne fait
     que déclencher. L'intérieur d'un panneau est exclu du corps (:not) pour
     ne pas se fondre deux fois (le panneau se fond déjà comme un tout). */
  .js .seq :is(h2, h3, h4),
  .js .seq :is(p, ul, .panneau):not(.panneau *) {
    opacity: 0; transform: translateY(24px);
  }
  .js .seq.vu :is(h2, h3, h4) {
    opacity: 1; transform: none;
    transition: opacity .8s var(--sortie), transform .8s var(--sortie);
  }
  .js .seq.vu :is(p, ul, .panneau):not(.panneau *) {
    opacity: 1; transform: none;
    transition: opacity .8s var(--sortie) .13s, transform .8s var(--sortie) .13s;
  }

  /* La jauge se remplit à l'entrée : elle montre l'avancement se faire.
     Dissimulation instantanée (comme .leve), transition au seul remplissage. */
  .js .jauge { transform: scaleX(0); }
  .js .jauge.vu { transform: scaleX(var(--fin, 0)); transition: transform 1.1s var(--sortie) .1s; }
}
