/* Landing « la grande tradition » v2 — chargée uniquement sur la landing.
   Le socle (fontes, tokens, grille, boutons, héro, escalier, FAQ) vit dans style.css. */

/* ————— Écriture à l'encre : les titres s'écrivent mot à mot ————— */
.mot { display: inline-block; }
[data-ecrit] .mot { opacity: 0; transform: translateY(0.22em) rotate(0.3deg); }
[data-ecrit].vu .mot { animation: encre 0.6s var(--ease) forwards; animation-delay: var(--d); }
@keyframes encre { to { opacity: 1; transform: none; } }
.hero h1[data-ecrit] { animation: none; }
.hero .sous { animation: lever 0.6s 0.15s var(--ease) both !important; }
.hero .zone-cta { animation: lever 0.6s 0.25s var(--ease) both !important; }
.hero .note-hero { animation: lever 0.6s 0.35s var(--ease) both !important; }

/* ————— T-0013 (lot 1) : le hero porte deux CTA — l'essai, et l'achat direct pour qui
   sait déjà ce qu'il veut. Même gabarit que .bouton (taille, padding, hérités via la
   classe .bouton) ; seule la couleur change, comme .bouton.secondaire dans style.css. ————— */
.bouton-secondaire { background: transparent; color: var(--action); box-shadow: inset 0 0 0 1px var(--action); }
/* Relecture Codex (NO-GO, objection 1) : sur le hero, --action tombe à 2,36-3,61:1 sur
   --nuit (selon l'occasion) et le survol de style.css (--action-doux en fond, texte
   inchangé) descend jusqu'à 1,06:1 — illisible. Dans le hero précisément, le bouton
   secondaire repasse en crème/nuit (≈14:1 dans les deux états), les seules couleurs déjà
   posées sur ce fond sombre (h1, sous-titre, note-hero). Spécificité (.hero .bouton-
   secondaire, deux classes) suffit à passer devant .bouton-secondaire seul, sans !important. */
.hero .bouton-secondaire { color: var(--creme); box-shadow: inset 0 0 0 1px var(--creme); }
@media (hover: hover) and (pointer: fine) {
  .hero .bouton-secondaire:hover { background: var(--creme); color: var(--nuit); }
}

/* ————— Duotone (statique, jamais animé). Les sources sont déjà en noir et blanc sauf retraite :
   grayscale(1) aligne les quatre photos sur le même traitement. Photo (::after) < teinte (::before) < texte.
   Les trois occasions ont désormais une photo en ouverture — plus de héro clair. ————— */
.hero-contenu { position: relative; z-index: 2; }
.hero.avec-photo::after, .bande-photo::after {
  content: ''; position: absolute; inset: 0; z-index: 0; filter: grayscale(1) contrast(1.12);
}
.hero.avec-photo::before, .bande-photo::before {
  content: ''; position: absolute; inset: 0; z-index: 1; mix-blend-mode: multiply; opacity: 0.38;
  background: linear-gradient(135deg, var(--nuit), var(--accent-doux));
}
.bande-photo .contenu { position: relative; z-index: 2; }

/* Bande muette : image seule, sans citation ni voile. Plus courte, elle sert de respiration. */
/* Chargement à l'approche : le fond n'est déclaré que sur `.chargee` (gabarit + HERO_CSS).
   Avant lui, la bande est une plage de nuit — cohérente avec le duotone, jamais un trou blanc. */
.bande-photo { background: var(--nuit); }
.bande-photo.muette { min-height: 44vh; padding: 0 !important; }
@media (max-width: 56rem) { .bande-photo.muette { min-height: 34vh; } }

/* ————— Vous êtes en bonne compagnie : trois exergues, trois colonnes explicites.
   main avait resserré l'auto-fit à minmax(13rem) pour en faire tenir trois dans 629 px ;
   la grille fait maintenant 52rem, une colonne fixe par exergue est plus sûre que le calcul. ————— */
.exergues { display: grid; grid-template-columns: repeat(3, 1fr); gap: 0 2.4rem; margin-top: 3rem; }
.exergue { position: relative; padding: 3.4rem 0 1.8rem; }
.exergue::before {
  content: ''; position: absolute; top: 3rem; left: 0; right: 0; height: 1px; background: var(--ligne);
  transform: scaleX(0); transform-origin: left center; transition: transform 0.9s var(--ease);
}
.compagnie.vu .exergue::before { transform: scaleX(1); }
.exergue > p { position: relative; z-index: 1; opacity: 0; transform: translateY(16px); transition: opacity 0.9s var(--ease), transform 0.9s var(--ease); }
.compagnie.vu .exergue > p { opacity: 1; transform: none; }
.exergue:nth-child(2)::before, .exergue:nth-child(2) > p { transition-delay: 0.18s; }
.exergue:nth-child(3)::before, .exergue:nth-child(3) > p { transition-delay: 0.36s; }
.exergue .lieu { text-transform: uppercase; letter-spacing: 0.2em; font-size: 0.68rem; color: var(--texte-doux); margin-bottom: 0.7rem; }
.exergue .morale { margin-top: 0.7rem; font-style: italic; color: var(--texte-doux); font-size: 0.94rem; }
.exergue .an {
  /* main avait remonté le millésime fantôme pour qu'il cesse de chevaucher ; il devient ici
     un vrai libellé daté, dans le flux, au-dessus du filet — plus rien ne peut se superposer. */
  position: absolute; top: 0; left: 0; z-index: 0; pointer-events: none; font-style: italic; font-weight: 600;
  font-size: 2.6rem; line-height: 1; color: var(--accent); opacity: 0; transition: opacity 0.9s 0.4s var(--ease);
}
.compagnie.vu .exergue .an { opacity: 0.55; }
@media (max-width: 56rem) { .exergues { grid-template-columns: 1fr; gap: 0; } }

/* ————— La feuille de brouillon : ratures, corrections, marges ————— */
.feuille {
  position: relative; margin: 3rem 0 0; background: #fff; max-width: 40rem;
  padding: 3rem 2.8rem 2.4rem; box-shadow: 0 1px 2px rgba(12,15,22,0.07), 0 16px 48px rgba(12,15,22,0.1);
  font-size: 1.14rem; line-height: 2;
}
.feuille::before { content: ''; position: absolute; top: 0; bottom: 0; left: 2rem; width: 1px; background: color-mix(in srgb, var(--filet) 30%, transparent); }
.feuille p + p { margin-top: 1.1rem; }
.rature { position: relative; color: var(--texte-doux); }
.rature::after {
  content: ''; position: absolute; left: -1%; right: -1%; top: 52%; height: 2px; background: var(--filet);
  border-radius: 2px; transform: scaleX(0); transform-origin: left center; transition: transform 0.9s var(--ease);
}
.feuille.vu .rature::after { transform: scaleX(1) rotate(-1.2deg); }
.correction { font-style: italic; color: var(--accent); opacity: 0; transition: opacity 0.8s 0.55s var(--ease); }
.feuille.vu .correction { opacity: 1; }
.marge {
  position: absolute; right: -11.5rem; width: 10rem; font-style: italic; color: var(--texte-doux);
  font-size: 0.9rem; line-height: 1.45; transform: rotate(-1.8deg); opacity: 0; transition: opacity 0.9s 0.8s var(--ease);
}
.marge::before { content: '↳ '; color: var(--accent); }
.feuille.vu .marge { opacity: 1; }
.didascalie { font-variant: small-caps; letter-spacing: 0.12em; color: var(--texte-doux); font-style: normal; }
.feuille footer { margin-top: 1.8rem; font-size: 0.85rem; color: var(--texte-doux); font-style: italic; line-height: 1.5; }
@media (max-width: 68rem) {
  .marge { position: static; display: block; width: auto; margin: 0.2rem 0 0.6rem; transform: rotate(-0.8deg); }
  .feuille { padding: 2.2rem 1.5rem 1.9rem; font-size: 1.05rem; }
  .feuille::before { left: 0.9rem; }
}

/* ————— Parlons franchement : 2 colonnes, et un bloc impair final qui prend toute la largeur
   (retraite en a 5 — l'ancienne grille rigide laissait une cellule vide). ————— */
.difference { display: grid; grid-template-columns: repeat(2, 1fr); gap: 2rem 2.4rem; margin-top: 2.6rem; }
.difference > div { border-top: 2px solid var(--accent); padding: 1.6rem 0 0; }
.difference > div:last-child:nth-child(odd) { grid-column: 1 / -1; }
.difference h3 { font-size: 1.14rem; font-weight: 600; margin-bottom: 0.5rem; }
.difference p { color: var(--texte-doux); font-size: 1rem; max-width: 34em; }
@media (max-width: 56rem) { .difference { grid-template-columns: 1fr; } }

/* ————— T-0013 (lot 1) : ligne factuelle sous le nom du palier, avant l'accroche —
   aucune taille déclarée : elle hérite exactement celle de .rang-accroche (style.css),
   seule la graisse la distingue. ————— */
.rang-livrable { font-weight: 600; margin-bottom: 0.25rem; }
/* Re-jugement Codex n°3 (Chrome headless réel, 1440 px, hommage) : prix, bouton et
   garantie tombaient SOUS le texte du palier — .rang-texte, sans base flex, imposait sa
   largeur max-content (la ligne `livrable`) et poussait .rang-achat hors de la ligne ;
   l'essai précédent (`flex-wrap` + `max-width` sur .rang-achat) cassait en prime les
   boutons sur deux lignes. Ici : .rang-texte absorbe l'espace restant et wrappe son
   propre texte ; .rang-achat (flex-shrink:0, style.css:137) garde sa largeur intrinsèque,
   bornée par la garantie (22em) plutôt que par le bouton. Bornées au-dessus de 640 px
   (capture réelle 375 px, re-jugement Codex) : sous ce seuil, style.css:217-221 empile
   `.rang` en colonne et passe `.rang-achat` en grille — `flex: 1 1 0` y deviendrait une
   base de HAUTEUR nulle et `margin-inline-start: auto` décale la garantie vers la droite ;
   ces deux règles n'ont de sens qu'en disposition ligne. Syntaxe de plage (re-jugement
   Codex n°4) : `width > 640px` est le complément EXACT de `max-width: 640px` (style.css:217)
   — `min-width: 641px` laissait un trou fractionnaire entre 640 et 641px (zoom navigateur). */
@media (width > 640px) {
  .rang-texte { flex: 1 1 0; min-width: 0; }
  .rang-remboursement { max-width: 22em; margin-inline-start: auto; }
}

/* ————— Exemples génériques par palier ————— */
.rang details { border: none; padding: 0; margin-top: 0.45rem; max-width: none; }
.rang summary { font-size: 0.85rem; color: var(--action); font-weight: 400; cursor: pointer; }
.rang details p { font-style: italic; font-size: 0.93rem; color: var(--texte-doux); padding: 0.55rem 0 0.2rem; max-width: 38em; }
/* Le palier vedette montre son exemple ouvert (P5, T-0010) : même typo que .rang
   summary/details p, sans le repli — la meilleure preuve de la page reste visible. */
.exemple-ouvert { margin-top: 0.45rem; }
.exemple-titre { font-size: 0.85rem; color: var(--action); font-weight: 400; margin-bottom: 0.2rem; }
.exemple-ouvert p:last-child { font-style: italic; font-size: 0.93rem; color: var(--texte-doux); max-width: 38em; }

/* ————— P1 (T-0010) : interstitiel de confiance avant Stripe. Un seul dialog par page,
   même monde visuel nuit/crème que le hero. Mobile 390px d'abord : largeur en vw plafonnée. ————— */
.dialog-palier {
  /* Pas de `position` ici (relecture, objection #2) : la feuille UA centre `dialog:modal`
     via `position: fixed` — un `position: relative` d'auteur écrase ce centrage et
     ancrait le dialog en haut-gauche (0,0). `.dialog-fermer` en `absolute` reste
     correctement positionné : `<dialog>` est déjà lui-même positionné par l'UA.
     `margin: auto` restauré explicitement : le reset global `* { margin: 0 }`
     (style.css:20) écrase sinon le `margin: auto` de l'UA qui fait tout le centrage
     (mesuré au CDP sans ce filet : dialog collé en (0,0), aucun centrage). */
  border: none; border-radius: 14px; padding: 0; margin: auto;
  width: min(92vw, 30rem); max-width: 30rem; background: var(--nuit); color: var(--creme);
  box-shadow: 0 30px 80px rgba(12,15,22,0.45);
}
.dialog-palier::backdrop { background: rgba(12,15,22,0.62); }
.dialog-corps { padding: 2.2rem 1.6rem 1.8rem; display: grid; gap: 0.9rem; }
.dialog-fermer {
  position: absolute; top: 0.7rem; right: 0.7rem; width: 2rem; height: 2rem;
  background: transparent; border: none; color: rgba(243,234,217,0.72); font-size: 1.1rem; cursor: pointer;
}
.dialog-fermer:hover { color: var(--creme); }
.dialog-nom { font-size: 1.25rem; font-weight: 600; padding-right: 1.6rem; }
.dialog-prix { font-size: 1.6rem; font-weight: 600; color: var(--accent-doux); margin-top: -0.4rem; }
.dialog-inclus { list-style: none; display: grid; gap: 0.5rem; margin: 0.2rem 0; padding: 0; }
.dialog-inclus li { padding-left: 1.2rem; position: relative; font-size: 0.95rem; color: rgba(243,234,217,0.88); }
.dialog-inclus li::before { content: '—'; position: absolute; left: 0; color: var(--accent-doux); }
.dialog-etape, .dialog-remboursement, .dialog-retour { font-size: 0.85rem; color: rgba(243,234,217,0.72); margin: 0; }
/* Plein dès P1, indépendamment du traitement global de .bouton-achat (P3) : le bouton
   final du dialog doit être le geste le plus fort de la page, avant même la refonte des
   boutons de l'escalier. */
.dialog-liens { margin-top: 0.4rem; }
/* Objection #1 (bloquant) : un `display` d'auteur passe TOUJOURS devant l'attribut
   `hidden` (feuille UA, priorité la plus basse) — les 3 liens de paiement étaient donc
   tous visibles et cliquables en même temps, même libellé générique, quel que soit le
   palier ouvert. La visibilité réelle vient désormais de la classe `.actif`, posée par
   le JS sur le seul lien du palier ouvert ; `hidden` reste en filet si le CSS ne charge pas. */
.dialog-liens .bouton-achat { display: none; width: 100%; text-align: center; background: var(--action); color: #fff; box-shadow: none; }
.dialog-liens .bouton-achat.actif { display: block; }
.dialog-annuler {
  justify-self: center; margin-top: 0.2rem; border: none; background: none; cursor: pointer;
  font: inherit; color: rgba(243,234,217,0.72);
}
.dialog-annuler:hover { color: var(--creme); }

/* ————— Panthéon : plaques de musée ————— */
.plaques { display: grid; grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr)); gap: 1.6rem; margin-top: 2.8rem; }
.plaque { border-top: 2px solid var(--accent-doux); padding: 1.4rem 0 0; }
.plaque .lieu { text-transform: uppercase; letter-spacing: 0.18em; font-size: 0.66rem; color: var(--accent-doux); margin-bottom: 0.8rem; }
.plaque p { font-size: 0.97rem; line-height: 1.55; color: rgba(243,234,217,0.85); }
.pantheon .morale { margin-top: 2.8rem; font-style: italic; font-size: 1.35rem; color: var(--accent-doux); max-width: 24em; }

/* ————— L'invitation : carte sur papier, PAS une seconde bande d'encre.
   Le manifeste et l'invitation utilisaient exactement le même composant. ————— */
.invitation { text-align: left; }
.carte-invitation {
  max-width: var(--large); border-top: 3px double var(--filet); border-bottom: 3px double var(--filet);
  padding: 3.2rem 0; display: grid; gap: 1.2rem; justify-items: start;
}
.carte-invitation h2 { font-size: clamp(1.9rem, 4vw, 2.9rem); margin: 0; max-width: 14em; }
.carte-invitation p { color: var(--texte-doux); max-width: 32em; font-size: 1.08rem; }
.carte-invitation .bouton { margin-top: 0.8rem; }

/* ————— CTA flottant : masqué par défaut, apparaît hors du héro (.visible),
   masqué dans #ebauche et #versions (.masque) ; après une ébauche rendue il
   change de mission — libellé et cible posés par le gabarit vers les prix. ————— */
.cta-flottant {
  position: fixed; bottom: 1.2rem; right: 1.2rem; z-index: 40;
  opacity: 0; pointer-events: none; transform: translateY(8px);
  transition: opacity 0.6s var(--ease), transform 0.6s var(--ease);
}
.cta-flottant.visible:not(.masque) { opacity: 1; pointer-events: auto; transform: none; }
.cta-flottant .bouton { box-shadow: 0 10px 30px rgba(12,15,22,0.35); }
@media (max-width: 640px) { .cta-flottant { display: none; } }
.masque { opacity: 0; pointer-events: none; }

/* ————— Fondu formulaire → attente → résultat (zone essai uniquement) ————— */
#zone-essai, #attente-essai, #resultat-essai {
  transition: opacity 300ms var(--ease), transform 300ms var(--ease), display 300ms allow-discrete;
}
#zone-essai.cache, #attente-essai.cache, #resultat-essai.cache { opacity: 0; transform: translateY(8px); }
/* Le résultat arrive avec cérémonie : plus lentement que l'attente qu'il remplace (audit 30/08). */
#resultat-essai { transition-duration: 600ms; }
@starting-style {
  #zone-essai:not(.cache), #attente-essai:not(.cache), #resultat-essai:not(.cache) { opacity: 0; transform: translateY(8px); }
}
.revelable { opacity: 0; transform: translateY(18px); transition: opacity 0.9s var(--ease), transform 0.9s var(--ease); }
.revelable.vu { opacity: 1; transform: none; }

@media (prefers-reduced-motion: reduce) {
  [data-ecrit] .mot { animation: none !important; opacity: 1 !important; transform: none !important; }
  .hero .sous, .hero .zone-cta, .hero .note-hero { animation: none !important; }
  .compagnie .exergue > p, .compagnie .exergue::before { opacity: 1 !important; transform: none !important; transition: none !important; }
  .compagnie .exergue .an { opacity: 0.55 !important; transition: none !important; }
  .feuille .rature::after { transform: scaleX(1) rotate(-1.2deg) !important; transition: none !important; }
  .feuille .correction, .feuille .marge { opacity: 1 !important; transition: none !important; }
  .revelable { opacity: 1 !important; transform: none !important; transition: none !important; }
  .cta-flottant, #zone-essai, #attente-essai, #resultat-essai { transition: none !important; }
}

/* ————— T-0007 : essai en premier — verrous et signaux ————— */
.compteur-anecdote { font-size: 0.85rem; color: var(--texte-doux); margin-top: 0.4rem; }
/* Message du bouton sous le seuil (LOT 7) : discret et NEUTRE, distinct de .erreur
   (--filet) — ce n'est pas une erreur, juste une invitation à continuer.
   aria-live="polite" (gabarit) : la région reste TOUJOURS exposée — ni display:none
   ni visibility:hidden, sur elle ni sur :empty, à aucun moment (un premier `:empty {
   display:none }` retirait quand même la région de l'arbre d'accessibilité, NO-GO
   Codex re-jugement 2). Vide, elle ne doit occuper AUCUNE place visuelle : hauteur et
   marge réduites à zéro, jamais son exposition. */
.aide-seuil { font-size: 0.87rem; color: var(--texte-doux); margin-top: 0.5rem; }
/* Vide, l'aide sort du flux (la grille du formulaire espace TOUS ses enfants, gap
   1.3rem — elle laissait un trou sous le bouton). Motif de masquage accessible :
   `display: none` retirerait la region aria-live de l'arbre et son apparition
   deja remplie ne serait plus annoncee (relecture Codex). */
.aide-seuil:empty { position: absolute; width: 1px; height: 1px; margin: 0; padding: 0;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
/* T-0009 « le premier mot » : la micro-démo de transformation — un repère permanent,
   jamais une barre. Texte statique (aucune affordance de champ), jamais le traitement
   .extrait (réservé au vrai résultat). Compact : 3 lignes max en mobile. */
.exemple-champ {
  border-left: 2px dotted var(--accent-doux); padding: 0.15rem 0 0.15rem 0.9rem;
  margin: 0.1rem 0 0.55rem; font-size: 0.88rem; font-style: italic;
  color: var(--texte-doux); max-width: 34em;
}
.exemple-champ em { color: var(--encre); }
.exemple-tag {
  font-style: normal; font-variant: small-caps; letter-spacing: 0.08em;
  font-size: 0.78rem; color: var(--action);
}
@media (max-width: 640px) {
  .exemple-champ { display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }
}
#attente-essai .points span { display: inline-block; animation: pointsPulse 1.2s var(--ease) infinite; }
#attente-essai .points span:nth-child(2) { animation-delay: 0.2s; }
#attente-essai .points span:nth-child(3) { animation-delay: 0.4s; }
@keyframes pointsPulse { 0%, 60%, 100% { opacity: 0.25; } 30% { opacity: 1; } }
@media (prefers-reduced-motion: reduce) { #attente-essai .points span { animation: none; opacity: 1; } }

/* Escalier ferme : la mention se lit avant les prix, jamais apres. */
.attente-escalier {
  margin: -0.8rem 0 2rem; padding: 0.9rem 1.2rem; font-size: 0.98rem;
  color: var(--texte-doux); border-left: 3px solid var(--accent); background: var(--creme);
}
