@charset "utf-8";
/* =============================================================================
   VH VERSAILLES — « Consacre ton année scolaire à Dieu »
   Programme spécial rentrée 2026-2027 · 26–30 août 2026
   -----------------------------------------------------------------------------
   Feuille de styles du LOT SOCLE.
   Elle habille les 4 pages du site (index, je-donne-ma-vie, bienvenue, merci)
   à partir des classes et des attributs data-* décrits dans CONTRAT.md.

   SOMMAIRE
     01. Tokens de charte (variables :root)
     02. Réinitialisation et base
     03. Accessibilité (sr-only, skip-link, focus visible)
     04. Typographie (titres, eyebrow, lead, script)
     05. Mise en page (container, section, grid)
     06. Boutons
     07. Badges et pastilles
     08. Cartes
     09. Barre de progression + barre d'annonce (mode EN DIRECT)
     10. Menu (burger mobile)
     11. Hero : dégradé animé, rayons, bokeh, compte à rebours
     12. Plateformes de direct
     13. Timeline du programme
     14. Formulaires
     15. QR code, carte Maps, partage
     16. Révélation au scroll (.reveal)
     17. Divers (liens non configurés, pied de page, séparateurs)
     18. prefers-reduced-motion (neutralisation des animations)
     19. Impression
     20. Griffonnages scolaires (bandes doodle en fond de section)

   NOTE POLICES : aucune @import ici. Chaque page HTML porte ses <link>
   Google Fonts (Poppins + Kaushan Script) dans son <head> (cf. CONTRAT §2).
   ============================================================================= */


/* =============================================================================
   01. TOKENS DE CHARTE
   Les 8 couleurs ci-dessous sont imposées par le CONTRAT §2 : ne pas les
   renommer. Les variables « dérivées » (rayons, ombres, espacements…) sont
   libres mais servent partout : les modifier ici change tout le site.
   ============================================================================= */
:root {
  /* --- Couleurs imposées (CONTRAT §2) --- */
  --vh-vert:        #006C68;  /* vert profond, couleur dominante */
  --vh-vert-fonce:  #01423E;  /* fond des sections sombres */
  --vh-or:          #CFAE1F;  /* accents, filets, titres sur fond sombre */
  --vh-rouge:       #B12029;  /* CTA principal, badges */
  --vh-sable:       #FBF7E8;  /* fond clair chaud */
  /* Le CONTRAT donnait ici #F2F7F6, décrit comme « fond clair froid ». Mesuré,
     c'était un gris-menthe à 24 % de saturation (teinte 168°) alors que le
     sable est à 70 % (teinte 47°) : une section sur deux virait au gris
     d'hôpital et la page paraissait triste. Même clarté, même rôle, mais une
     teinte chaude (82°, 48 %) : l'alternance devient crème / crème vert
     tendre. Écart au CONTRAT §2 assumé et reporté dans CONTRAT.md. */
  --vh-clair:       #F6F9EE;  /* fond clair tempéré */
  --vh-encre:       #10201F;  /* texte courant sur fond clair */
  --vh-blanc:       #FFFFFF;

  /* --- Dérivés de couleur ---
     ATTENTION (règle non négociable du CONTRAT §2) : --vh-or ne sert JAMAIS
     de couleur de texte sur fond clair (contraste AA insuffisant). Sur fond
     clair il ne sert qu'aux filets, bordures, puces et surlignages.
     --vh-or-clair est une variante éclaircie réservée au TEXTE sur fond
     sombre (ratio ≥ 4.5:1 sur --vh-vert-fonce et sur le dégradé du hero). */
  --vh-or-clair:    #E6C93F;
  --vh-rouge-fonce: #8E1A21;
  --vh-vert-nuit:   #01312E;
  --vh-vert-medium: #04524E;
  --vh-encre-doux:  #3E5250;  /* texte secondaire sur fond clair (AA ≥ 4.5) */
  --vh-trait:       rgba(1, 66, 62, .14);   /* bordures discrètes fond clair */
  --vh-trait-or:    rgba(207, 174, 31, .45);/* filets dorés décoratifs */
  --vh-voile:       rgba(255, 255, 255, .10); /* surface vitrée sur fond sombre */
  --vh-voile-fort:  rgba(255, 255, 255, .18);

  /* --- Rôles de couleur contextuels ---
     Redéfinis plus bas par .hero, .section--sombre, .carte--sombre…
     Cela évite de répéter « couleur du texte » dans chaque composant. */
  --vh-texte:       var(--vh-encre);
  --vh-texte-doux:  var(--vh-encre-doux);
  --vh-accent:      var(--vh-vert);   /* eyebrow, script, puces */
  --vh-surface:     var(--vh-blanc);  /* fond des cartes */
  --vh-bordure:     var(--vh-trait);
  --vh-focus:       var(--vh-vert);   /* couleur du contour de focus */

  /* --- Dégradés --- */
  --vh-degrade-hero: linear-gradient(155deg,
                      var(--vh-vert-nuit) 0%,
                      var(--vh-vert-fonce) 30%,
                      #033F3B 55%,
                      var(--vh-vert-medium) 100%);
  --vh-degrade-sombre: linear-gradient(165deg,
                      var(--vh-vert-fonce) 0%,
                      #023E3A 55%,
                      var(--vh-vert-medium) 100%);
  --vh-degrade-or: linear-gradient(90deg,
                      rgba(207,174,31,0) 0%,
                      var(--vh-or) 22%,
                      var(--vh-or-clair) 50%,
                      var(--vh-or) 78%,
                      rgba(207,174,31,0) 100%);

  /* --- Rayons d'arrondi --- */
  --vh-rayon-xs: 8px;
  --vh-rayon:    14px;
  --vh-rayon-lg: 22px;
  --vh-rayon-xl: 30px;
  --vh-rayon-pill: 999px;

  /* --- Ombres --- */
  --vh-ombre-douce:      0 6px 18px rgba(1, 48, 45, .08);
  --vh-ombre-carte:      0 10px 30px rgba(1, 48, 45, .10),
                         0 2px 6px rgba(1, 48, 45, .06);
  --vh-ombre-carte-fort: 0 22px 48px rgba(1, 48, 45, .18),
                         0 4px 12px rgba(1, 48, 45, .10);
  --vh-ombre-sombre:     0 18px 44px rgba(0, 0, 0, .30);

  /* --- Espacements --- */
  --vh-esp-xs: .5rem;
  --vh-esp-sm: .875rem;
  --vh-esp-md: 1.25rem;
  --vh-esp-lg: 2rem;
  --vh-esp-xl: 3rem;
  --vh-gap:    clamp(1rem, 3vw, 1.75rem);
  --vh-section-y: clamp(3rem, 8vw, 6rem);

  /* --- Largeurs --- */
  --vh-conteneur: 1140px;
  --vh-conteneur-etroit: 720px;
  --vh-padding-lateral: clamp(1rem, 5vw, 2rem);

  /* --- Durées de transition --- */
  --vh-t-rapide: .18s;
  --vh-t:        .28s;
  --vh-t-lente:  .55s;
  --vh-easing:   cubic-bezier(.2, .7, .3, 1);

  /* --- Décalage pour les ancres (barre d'annonce collante) --- */
  --vh-offset-sticky: 5rem;

  /* Palette d'accent locale (surchargée par contexte) */
  color-scheme: light;
}


/* =============================================================================
   02. RÉINITIALISATION ET BASE
   ============================================================================= */
*,
*::before,
*::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: var(--vh-offset-sticky);
}

body {
  margin: 0;
  min-height: 100%;
  background: var(--vh-blanc);
  color: var(--vh-texte);
  font-family: "Poppins", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  font-size: clamp(1rem, .96rem + .2vw, 1.0625rem);
  line-height: 1.65;
  font-weight: 400;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

h1, h2, h3, h4, h5, h6,
p, figure, blockquote, dl, dd { margin: 0 0 1em; }

h1, h2, h3, h4, h5, h6 {
  line-height: 1.15;
  font-weight: 800;
  letter-spacing: -.015em;
  text-wrap: balance;
}

ul, ol { margin: 0 0 1em; padding-left: 1.25em; }
li { margin-bottom: .35em; }

img, svg, video, iframe {
  max-width: 100%;
  display: block;
  height: auto;
}

a {
  color: var(--vh-vert);
  text-decoration-thickness: .08em;
  text-underline-offset: .18em;
  transition: color var(--vh-t) var(--vh-easing),
              opacity var(--vh-t) var(--vh-easing);
}
a:hover { color: var(--vh-vert-fonce); }

button, input, select, textarea { font: inherit; color: inherit; }

hr {
  border: 0;
  height: 2px;
  background: var(--vh-degrade-or);
  margin: var(--vh-esp-lg) 0;
  opacity: .8;
}

blockquote { padding-left: 1rem; border-left: 3px solid var(--vh-or); }

strong, b { font-weight: 700; }

::selection { background: rgba(0, 108, 104, .18); }

/* Cible d'ancre : évite que la barre collante masque le titre visé. */
[id] { scroll-margin-top: var(--vh-offset-sticky); }


/* =============================================================================
   03. ACCESSIBILITÉ
   ============================================================================= */

/* Masquage visuel qui reste lu par les lecteurs d'écran. */
.sr-only {
  position: absolute !important;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* Lien d'évitement : caché jusqu'à réception du focus clavier. */
.skip-link {
  position: absolute;
  top: -100px; left: 1rem;
  z-index: 200;
  padding: .8rem 1.25rem;
  background: var(--vh-rouge);
  color: var(--vh-blanc);
  font-weight: 700;
  border-radius: 0 0 var(--vh-rayon) var(--vh-rayon);
  text-decoration: none;
  box-shadow: var(--vh-ombre-carte-fort);
  transition: top var(--vh-t) var(--vh-easing);
}
.skip-link:focus,
.skip-link:focus-visible {
  top: 0;
  color: var(--vh-blanc);
}

/* Focus visible partout : contour net + halo pour rester lisible sur
   n'importe quel fond. La couleur s'adapte au contexte (--vh-focus). */
:focus { outline: none; }
:focus-visible {
  outline: 3px solid var(--vh-focus);
  outline-offset: 3px;
  border-radius: var(--vh-rayon-xs);
}
/* Sur fond sombre, l'or est parfaitement visible et autorisé. */
.hero,
.section--sombre,
.carte--sombre,
.carte--action,
body > header,
footer,
.pied,
[data-annonce] { --vh-focus: var(--vh-or-clair); }


/* =============================================================================
   04. TYPOGRAPHIE
   ============================================================================= */

/* Sur-titre court, majuscules, très lettré. */
.eyebrow {
  display: block;
  margin: 0 0 .6rem;
  font-size: .8125rem;
  font-weight: 700;
  letter-spacing: .2em;
  text-transform: uppercase;
  color: var(--vh-accent);
}

/* Échelles de titres, utilisables sur n'importe quelle balise. */
h1, .h1 {
  font-size: clamp(2rem, 1.15rem + 4.3vw, 3.75rem);
  font-weight: 800;
  line-height: 1.06;
  letter-spacing: -.025em;
  margin-bottom: .5em;
}
h2, .h2 {
  font-size: clamp(1.6rem, 1.1rem + 2.4vw, 2.6rem);
  font-weight: 800;
  line-height: 1.12;
  letter-spacing: -.02em;
  margin-bottom: .6em;
}
h3, .h3 {
  font-size: clamp(1.2rem, 1.05rem + .8vw, 1.5rem);
  font-weight: 700;
  line-height: 1.25;
  letter-spacing: -.01em;
  margin-bottom: .5em;
}

/* Chapô. */
.lead {
  font-size: clamp(1.0625rem, 1rem + .5vw, 1.3125rem);
  line-height: 1.6;
  font-weight: 400;
  color: var(--vh-texte-doux);
  max-width: 62ch;
}

/* Chiffre mis en avant dans un titre (« 3 jours de prière… »). Un chiffre
   frappe plus qu'un nombre écrit en toutes lettres : c'est le parti pris des
   affiches de jeûne et prière dont s'inspire cette page. L'or est ici sur
   fond vert profond, donc autorisé (cf. règle de contraste du contrat). */
.chiffre-cle {
  color: var(--vh-or);
  font-size: 1.5em;
  font-weight: 800;
  line-height: .8;
  letter-spacing: -.02em;
}

/* Dans un bloc centré, `text-align: center` centre le texte DANS le bloc,
   mais pas le bloc lui-même : avec max-width, .lead restait collé à gauche
   (32 px à gauche, 246 px à droite dans le hero). */
.texte-centre .lead,
[style*="text-align: center"] .lead,
#accueil .lead,
.hero .lead { margin-inline: auto; }
.hero .lead,
.section--sombre .lead,
.carte--sombre .lead,
.carte--action .lead { color: rgba(255, 255, 255, .88); }

/* Thème calligraphié. */
.script {
  font-family: "Kaushan Script", "Segoe Script", cursive;
  font-weight: 400;
  letter-spacing: 0;
  line-height: 1.3;
  color: var(--vh-accent);
  /* Kaushan a un dessin haut : on compense légèrement le rythme vertical. */
  padding-bottom: .08em;
}

/* Utilitaires de texte minimalistes. */
.texte-centre { text-align: center; }
.mesure { max-width: 62ch; }
.mesure-centre { max-width: 62ch; margin-inline: auto; }


/* =============================================================================
   05. MISE EN PAGE
   ============================================================================= */

.container {
  width: 100%;
  max-width: var(--vh-conteneur);
  margin-inline: auto;
  padding-inline: var(--vh-padding-lateral);
}
.container--etroit { max-width: var(--vh-conteneur-etroit); }

.section {
  position: relative;
  padding-block: var(--vh-section-y);
}

/* Variante sombre : dégradé vert, texte clair, filet doré haut et bas. */
.section--sombre {
  --vh-texte: var(--vh-blanc);
  --vh-texte-doux: rgba(255, 255, 255, .82);
  --vh-accent: var(--vh-or-clair);
  --vh-surface: var(--vh-voile);
  --vh-bordure: var(--vh-voile-fort);
  color: var(--vh-texte);
  background: var(--vh-degrade-sombre);
  border-top: 2px solid var(--vh-trait-or);
  border-bottom: 2px solid var(--vh-trait-or);
}
.section--sombre a:not(.btn) { color: var(--vh-or-clair); }
.section--sombre a:hover { color: var(--vh-blanc); }

.section--sable { background: var(--vh-sable); }
.section--clair { background: var(--vh-clair); }

/* Grilles : une colonne en mobile, puis élargissement progressif. */
.grid {
  display: grid;
  gap: var(--vh-gap);
  grid-template-columns: 1fr;
  align-items: stretch;
}
@media (min-width: 600px) {
  .grid--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .grid--4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (min-width: 800px) {
  .grid--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
@media (min-width: 1000px) {
  .grid--4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

/* Rangée d'actions (boutons côte à côte, empilés en mobile). */
.actions,
.boutons {
  display: flex;
  flex-wrap: wrap;
  gap: var(--vh-esp-sm);
  align-items: center;
}
@media (max-width: 479px) {
  .actions > .btn,
  .boutons > .btn { width: 100%; }
}


/* =============================================================================
   06. BOUTONS
   ============================================================================= */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .6em;
  min-height: 48px;               /* cible tactile confortable */
  padding: .85rem 1.6rem;
  border: 2px solid transparent;
  border-radius: var(--vh-rayon-pill);
  background: var(--vh-vert);
  color: var(--vh-blanc);
  font-size: 1rem;
  font-weight: 700;
  line-height: 1.2;
  letter-spacing: .01em;
  text-align: center;
  text-decoration: none;
  cursor: pointer;
  position: relative;
  box-shadow: var(--vh-ombre-douce);
  transition: transform var(--vh-t) var(--vh-easing),
              box-shadow var(--vh-t) var(--vh-easing),
              background-color var(--vh-t) var(--vh-easing),
              border-color var(--vh-t) var(--vh-easing),
              color var(--vh-t) var(--vh-easing);
}
.btn:hover {
  transform: translateY(-2px) scale(1.025);
  box-shadow: var(--vh-ombre-carte);
  color: var(--vh-blanc);
}
.btn:active { transform: translateY(0) scale(.98); }
.btn svg { width: 1.25em; height: 1.25em; fill: currentColor; flex: none; }

/* CTA principal. */
.btn--rouge { background: var(--vh-rouge); color: var(--vh-blanc); }
.btn--rouge:hover { background: var(--vh-rouge-fonce); }

/* Or : le texte est TOUJOURS encre foncée (l'or ne porte jamais de blanc). */
.btn--or { background: var(--vh-or); color: var(--vh-encre); }
.btn--or:hover { background: var(--vh-or-clair); color: var(--vh-encre); }

.btn--blanc { background: var(--vh-blanc); color: var(--vh-vert-fonce); }
.btn--blanc:hover { background: var(--vh-sable); color: var(--vh-vert-fonce); }

/* Bordure seule : hérite de la couleur du contexte. */
.btn--fantome {
  background: transparent;
  border-color: currentColor;
  color: var(--vh-vert);
  box-shadow: none;
}
.btn--fantome:hover {
  background: rgba(0, 108, 104, .08);
  color: var(--vh-vert-fonce);
  box-shadow: var(--vh-ombre-douce);
}
.hero .btn--fantome,
.section--sombre .btn--fantome,
.carte--sombre .btn--fantome,
.carte--action .btn--fantome { color: var(--vh-blanc); }
.hero .btn--fantome:hover,
.section--sombre .btn--fantome:hover,
.carte--sombre .btn--fantome:hover,
.carte--action .btn--fantome:hover {
  background: rgba(255, 255, 255, .14);
  color: var(--vh-blanc);
}

.btn--lg {
  min-height: 56px;
  padding: 1.05rem 2.1rem;
  font-size: clamp(1rem, .95rem + .3vw, 1.125rem);
}
.btn--bloc { width: 100%; display: flex; }

/* État désactivé et état de chargement (posé par app.js). */
.btn:disabled,
.btn[aria-disabled="true"] {
  opacity: .55;
  cursor: not-allowed;
  box-shadow: none;
}
.btn:disabled:hover,
.btn[aria-disabled="true"]:hover { transform: none; box-shadow: none; }

.btn[aria-busy="true"] {
  cursor: progress;
  color: transparent !important;
  pointer-events: none;
}
.btn[aria-busy="true"]::after {
  content: "";
  position: absolute;
  inset: 0;
  margin: auto;
  width: 1.25rem;
  height: 1.25rem;
  border: 3px solid rgba(255, 255, 255, .35);
  border-top-color: var(--vh-blanc);
  border-radius: 50%;
  animation: vh-rotation .7s linear infinite;
}
.btn--or[aria-busy="true"]::after,
.btn--blanc[aria-busy="true"]::after {
  border-color: rgba(16, 32, 31, .25);
  border-top-color: var(--vh-encre);
}
@keyframes vh-rotation { to { transform: rotate(360deg); } }


/* =============================================================================
   07. BADGES ET PASTILLES
   ============================================================================= */

.badge {
  display: inline-flex;
  align-items: center;
  gap: .4em;
  padding: .35rem .8rem;
  border-radius: var(--vh-rayon-pill);
  background: rgba(0, 108, 104, .10);
  border: 1px solid var(--vh-trait-or);   /* l'or en filet : autorisé */
  color: var(--vh-vert);                  /* texte vert : AA sur fond clair */
  font-size: .75rem;
  font-weight: 700;
  letter-spacing: .1em;
  text-transform: uppercase;
  line-height: 1.4;
}
.hero .badge,
.section--sombre .badge,
.carte--sombre .badge,
.carte--action .badge {
  background: rgba(255, 255, 255, .12);
  border-color: rgba(230, 201, 63, .6);
  color: var(--vh-or-clair);
}

/* Pastille rouge du thème. */
.pastille-theme {
  display: inline-flex;
  align-items: center;
  gap: .5em;
  padding: .45rem 1.1rem;
  border-radius: var(--vh-rayon-pill);
  background: var(--vh-rouge);
  color: var(--vh-blanc);
  font-size: clamp(.75rem, .7rem + .25vw, .875rem);
  font-weight: 800;
  letter-spacing: .16em;
  text-transform: uppercase;
  box-shadow: 0 6px 18px rgba(177, 32, 41, .35);
}


/* =============================================================================
   08. CARTES
   ============================================================================= */

.carte {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: .35rem;
  padding: clamp(1.25rem, 3.5vw, 2rem);
  background: var(--vh-blanc);
  border: 1px solid var(--vh-trait);
  border-radius: var(--vh-rayon-lg);
  box-shadow: var(--vh-ombre-carte);
  color: var(--vh-encre);
  transition: transform var(--vh-t) var(--vh-easing),
              box-shadow var(--vh-t) var(--vh-easing),
              border-color var(--vh-t) var(--vh-easing);
}
.carte:hover {
  transform: translateY(-6px);
  box-shadow: var(--vh-ombre-carte-fort);
  border-color: var(--vh-trait-or);
}
.carte > :last-child { margin-bottom: 0; }

/* Une carte entièrement cliquable ne doit pas perdre son focus visible. */
.carte:focus-within { border-color: var(--vh-trait-or); }

/* Variante sombre. */
.carte--sombre {
  --vh-texte: var(--vh-blanc);
  --vh-texte-doux: rgba(255, 255, 255, .82);
  --vh-accent: var(--vh-or-clair);
  background: var(--vh-degrade-sombre);
  border-color: rgba(207, 174, 31, .35);
  color: var(--vh-blanc);
  box-shadow: var(--vh-ombre-sombre);
}
.carte--sombre a { color: var(--vh-or-clair); }

/* Grande carte d'action verte (« Je donne ma vie », « Je suis nouveau »). */
.carte--action {
  --vh-texte: var(--vh-blanc);
  --vh-texte-doux: rgba(255, 255, 255, .85);
  --vh-accent: var(--vh-or-clair);
  align-items: flex-start;
  gap: .6rem;
  padding: clamp(1.5rem, 5vw, 2.75rem);
  background: var(--vh-degrade-hero);
  border: 1px solid rgba(207, 174, 31, .4);
  border-radius: var(--vh-rayon-xl);
  color: var(--vh-blanc);
  box-shadow: var(--vh-ombre-sombre);
  overflow: hidden;
  isolation: isolate;
}
/* Halo doré discret dans l'angle. */
.carte--action::before {
  content: "";
  position: absolute;
  z-index: -1;
  top: -40%; right: -20%;
  width: 70%; aspect-ratio: 1;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(207, 174, 31, .32), transparent 68%);
  pointer-events: none;
}
.carte--action:hover {
  transform: translateY(-6px);
  box-shadow: 0 26px 56px rgba(0, 0, 0, .38);
}
.carte--action a { color: var(--vh-or-clair); }
.carte--action .h2,
.carte--action .h3,
.carte--action h2,
.carte--action h3 { color: var(--vh-blanc); }
.carte--action .btn { margin-top: auto; }

/* Petit médaillon d'icône en tête de carte. */
.carte__icone {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 3rem; height: 3rem;
  margin-bottom: .75rem;
  border-radius: var(--vh-rayon);
  background: rgba(0, 108, 104, .10);
  color: var(--vh-vert);
  flex: none;
}
.carte--sombre .carte__icone,
.carte--action .carte__icone {
  background: rgba(255, 255, 255, .14);
  color: var(--vh-or-clair);
}
.carte__icone svg { width: 1.5rem; height: 1.5rem; fill: currentColor; }

/* -----------------------------------------------------------------------------
   Cartes « Pour qui ? » (élèves, parents, éducation…)
   Une carte blanche nue se lit mal en série de quatre : rien n'accroche l'œil
   et les quatre publics se confondent. On leur donne trois repères, tous
   discrets pour rester dans le ton de la page :
     • un médaillon d'icône (vert très pâle, symbole gris-vert) qui identifie
       le public avant même la lecture du titre ;
     • un filet vert→or en tête de carte, à demi tracé au repos, qui se
       complète au survol ;
     • un fond légèrement teinté de vert vers le bas.
   ----------------------------------------------------------------------------- */
.carte--public {
  overflow: hidden; /* pour que le filet de tête épouse l'arrondi */
  background:
    linear-gradient(180deg,
      rgba(0, 108, 104, 0) 55%,
      rgba(0, 108, 104, .055) 100%),
    var(--vh-blanc);
}
.carte--public::before {
  content: "";
  position: absolute;
  inset: 0 0 auto;
  height: 4px;
  background: linear-gradient(90deg, var(--accent, var(--vh-vert)) 0%, var(--vh-or) 100%);
  opacity: .4;
  transform: scaleX(.4);
  transform-origin: left center;
  transition: opacity var(--vh-t) var(--vh-easing),
              transform var(--vh-t) var(--vh-easing);
}
.carte--public:hover::before,
.carte--public:focus-within::before {
  opacity: 1;
  transform: scaleX(1);
}

/* « Professionnels de l'éducation » est plus long que la colonne : sans
   césure, le mot débordait de la carte. On réduit légèrement le titre et on
   autorise la coupure (l'attribut lang="fr" du document fournit le
   dictionnaire de césure). */
.carte--public .h3 {
  font-size: clamp(1.1rem, 1.02rem + .45vw, 1.3rem);
  hyphens: auto;
  overflow-wrap: break-word;
}

.carte__icone--public {
  width: 2.75rem; height: 2.75rem;
  margin-bottom: .85rem;
  border: 1px solid rgba(0, 108, 104, .16);
  border-color: color-mix(in srgb, var(--accent, var(--vh-vert)) 24%, transparent);
  background: rgba(0, 108, 104, .07);
  background: color-mix(in srgb, var(--accent, var(--vh-vert)) 9%, var(--vh-blanc));
  color: var(--vh-encre-doux); /* gris-vert : jamais l'or sur fond clair */
  transition: background var(--vh-t) var(--vh-easing),
              border-color var(--vh-t) var(--vh-easing),
              color var(--vh-t) var(--vh-easing),
              transform var(--vh-t) var(--vh-easing);
}
.carte__icone--public svg { width: 1.375rem; height: 1.375rem; }

.carte--public:hover .carte__icone--public,
.carte--public:focus-within .carte__icone--public {
  background: rgba(0, 108, 104, .14);
  background: color-mix(in srgb, var(--accent, var(--vh-vert)) 18%, var(--vh-blanc));
  border-color: rgba(0, 108, 104, .3);
  border-color: color-mix(in srgb, var(--accent, var(--vh-vert)) 40%, transparent);
  color: var(--vh-vert);
  transform: translateY(-2px) rotate(-4deg);
}

/* --- Une couleur par public ---
   Les quatre cartes étaient rigoureusement identiques : même filet vert-or,
   même pastille verte. Sur 13 000 px de page où le corps ne porte aucune
   couleur, cela pesait dans l'impression de tristesse. Chacune reçoit donc
   une teinte DE LA CHARTE — vert, or, rouge, vert profond — portée par le
   filet de tête et par la pastille de l'icône.
   Le glyphe, lui, garde --vh-encre-doux : sur fond clair l'or ne sert qu'aux
   filets, bordures et puces, jamais à un trait qui se lit (CONTRAT §2).
   Les déclarations rgba() qui précèdent chaque color-mix() sont le repli des
   navigateurs qui ne connaissent pas la fonction : ils retrouvent exactement
   l'aspect d'avant, en vert. */
.carte--public:nth-of-type(1) { --accent: var(--vh-vert); }
.carte--public:nth-of-type(2) { --accent: var(--vh-or); }
.carte--public:nth-of-type(3) { --accent: var(--vh-rouge); }
.carte--public:nth-of-type(4) { --accent: var(--vh-vert-fonce); }


/* =============================================================================
   09. BARRE DE PROGRESSION + BARRE D'ANNONCE
   ============================================================================= */

/* Fine barre de lecture en haut de page ; app.js pilote sa largeur. */
[data-progression-scroll] {
  position: fixed;
  top: 0; left: 0;
  z-index: 120;
  width: 0;
  height: 3px;
  background: var(--vh-degrade-or);
  background-color: var(--vh-or);
  box-shadow: 0 0 12px rgba(207, 174, 31, .6);
  transition: width .12s linear;
  pointer-events: none;
  will-change: width;
}

/* Barre d'annonce collante. */
[data-annonce] {
  --vh-texte: var(--vh-blanc);
  --vh-accent: var(--vh-or-clair);
  position: sticky;
  top: 0;
  z-index: 90;
  /* Vert de nuit hors direct, et non plus le quasi-noir #0B0F0E : celui-ci
     n'appartenait pas à la charte (15 % de saturation contre 97 % pour le
     vert de marque) et faisait, avec le pied de page, 1 133 px de deuil aux
     deux bouts du document. Le vert de nuit reste plus sombre que l'en-tête,
     et le filet doré du bas continue de les séparer. La bascule en rouge
     pendant le direct n'en est que plus franche. */
  background: var(--vh-vert-nuit);
  color: var(--vh-blanc);
  font-size: clamp(.8125rem, .78rem + .2vw, .9375rem);
  font-weight: 600;
  text-align: center;
  border-bottom: 1px solid rgba(207, 174, 31, .35);
  transition: background-color var(--vh-t) var(--vh-easing);
}
/* Le HTML peut poser soit un <a> qui enveloppe tout, soit un <p> + un <a>
   frères dans un .container : les deux cas sont couverts. */
[data-annonce] .container {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: .3rem .9rem;
  min-height: 44px;
  padding-block: .45rem;
}
[data-annonce] p { margin: 0; }
[data-annonce] a {
  display: inline-flex;
  align-items: center;
  gap: .4em;
  min-height: 32px;
  color: var(--vh-blanc);
  font-weight: 800;
  text-decoration: underline;
  text-decoration-color: rgba(255, 255, 255, .55);
  text-underline-offset: .22em;
}
[data-annonce] a:hover {
  color: var(--vh-or-clair);
  text-decoration-color: currentColor;
}
[data-annonce] > a:only-child {
  display: flex;
  justify-content: center;
  min-height: 44px;
  padding: .5rem var(--vh-padding-lateral);
  text-decoration: none;
}
[data-annonce-texte] { display: inline-block; }

/* Mode EN DIRECT : rouge pulsant (classe posée par app.js). */
[data-annonce].is-live {
  background: var(--vh-rouge);
  border-bottom-color: rgba(255, 255, 255, .35);
  animation: vh-pulsation 1.8s ease-in-out infinite;
}
[data-annonce].is-live a:hover { color: var(--vh-blanc); text-decoration: underline; }
[data-annonce].is-live [data-annonce-texte] { font-weight: 800; letter-spacing: .02em; }
@keyframes vh-pulsation {
  0%, 100% { background-color: var(--vh-rouge); box-shadow: 0 0 0 rgba(177, 32, 41, 0); }
  50%      { background-color: #C8262F; box-shadow: 0 6px 22px rgba(177, 32, 41, .55); }
}


/* =============================================================================
   10. EN-TÊTE DE SITE + MENU (burger mobile)
   Le lot index pose un <header> sans classe, contenant .container,
   [data-menu-bouton] et <nav data-menu>. Le header doit être `relative`
   pour que le panneau déroulant mobile (top:100%) se place correctement.
   ============================================================================= */

body > header {
  --vh-texte: var(--vh-blanc);
  --vh-accent: var(--vh-or-clair);
  --vh-bordure: rgba(255, 255, 255, .22);
  position: relative;
  z-index: 80;
  background: var(--vh-vert-fonce);
  color: var(--vh-blanc);
  border-bottom: 1px solid rgba(207, 174, 31, .3);
}
body > header a { color: var(--vh-blanc); text-decoration: none; }
body > header a:hover { color: var(--vh-or-clair); }
body > header > .container {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: .75rem 1.25rem;
  min-height: 60px;
  padding-block: .55rem;
}
body > header img,
body > header svg.logo { max-height: 44px; width: auto; }
body > header img.logo { max-height: none; }

[data-menu-bouton] {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .5rem;
  min-width: 48px;
  min-height: 48px;
  padding: .5rem .85rem;
  border: 1px solid var(--vh-bordure);
  border-radius: var(--vh-rayon);
  background: transparent;
  color: inherit;
  font-weight: 700;
  cursor: pointer;
  transition: background-color var(--vh-t) var(--vh-easing),
              transform var(--vh-t) var(--vh-easing);
}
[data-menu-bouton]:hover { background: rgba(0, 108, 104, .10); transform: scale(1.03); }
.hero [data-menu-bouton]:hover,
.section--sombre [data-menu-bouton]:hover { background: rgba(255, 255, 255, .14); }
[data-menu-bouton] svg { width: 1.4rem; height: 1.4rem; fill: currentColor; }

[data-menu] { display: flex; flex-wrap: wrap; gap: var(--vh-esp-md); align-items: center; }
[data-menu] ul {
  display: flex;
  flex-wrap: wrap;
  gap: var(--vh-esp-md);
  align-items: center;
  list-style: none;
  margin: 0; padding: 0;
}
[data-menu] li { margin: 0; }
[data-menu] a {
  display: inline-block;
  padding: .4rem 0;
  font-weight: 600;
  text-decoration: none;
  color: inherit;
  border-bottom: 2px solid transparent;
  transition: border-color var(--vh-t) var(--vh-easing),
              color var(--vh-t) var(--vh-easing);
}
[data-menu] a:hover { border-bottom-color: var(--vh-or); }

/* En dessous de 900px, le menu devient un panneau déroulant. */
@media (max-width: 899px) {
  [data-menu] {
    position: absolute;
    left: 0; right: 0;
    top: 100%;
    flex-direction: column;
    align-items: stretch;
    gap: .25rem;
    padding: 1rem var(--vh-padding-lateral) 1.25rem;
    background: var(--vh-vert-fonce);
    color: var(--vh-blanc);
    border-bottom: 2px solid var(--vh-or);
    box-shadow: var(--vh-ombre-sombre);
    transform: translateY(-8px);
    opacity: 0;
    visibility: hidden;
    transition: opacity var(--vh-t) var(--vh-easing),
                transform var(--vh-t) var(--vh-easing),
                visibility var(--vh-t) var(--vh-easing);
  }
  [data-menu] ul { flex-direction: column; align-items: stretch; gap: .25rem; }
  [data-menu] a { padding: .7rem .25rem; border-bottom: 1px solid rgba(255, 255, 255, .12); }
  [data-menu].is-ouvert {
    transform: translateY(0);
    opacity: 1;
    visibility: visible;
  }
  /* Repli sans JS : le menu reste dans le flux et lisible. */
  .no-js [data-menu] {
    position: static;
    transform: none;
    opacity: 1;
    visibility: visible;
    background: transparent;
    color: inherit;
    box-shadow: none;
    border-bottom: 0;
    padding-inline: 0;
  }
  .no-js [data-menu-bouton] { display: none; }
}
@media (min-width: 900px) {
  [data-menu-bouton] { display: none; }
}


/* =============================================================================
   11. HERO
   Dégradé animé + rayons de lumière + ~20 particules bokeh, 100 % en CSS
   (aucun canvas, aucun JS pour l'ambiance).
   ============================================================================= */

/* NOTE DE RACCORD — le lot index n'a pas de classe `.hero` au contrat : sa
   section d'accueil est `<section id="accueil" class="section section--sombre">`.
   Les deux écritures reçoivent donc exactement le même traitement.
   `.hero` reste disponible pour les pages dédiées. */
.hero,
#accueil.section--sombre {
  --vh-texte: var(--vh-blanc);
  --vh-texte-doux: rgba(255, 255, 255, .85);
  --vh-accent: var(--vh-or-clair);
  --vh-surface: var(--vh-voile);
  --vh-bordure: var(--vh-voile-fort);
  --vh-focus: var(--vh-or-clair);
  position: relative;
  isolation: isolate;
  overflow: hidden;
  display: flex;
  align-items: center;
  min-height: min(100svh, 860px);
  padding-block: clamp(3rem, 10vw, 6rem);
  color: var(--vh-blanc);
  background: var(--vh-degrade-hero);
  background-size: 220% 220%;
  background-position: 0% 0%;
  animation: vh-degrade 24s ease-in-out infinite alternate;
  border-top: 0;
  border-bottom: 3px solid var(--vh-or);
  text-align: center;
}
.hero > .container,
#accueil.section--sombre > .container { position: relative; z-index: 2; width: 100%; }
.hero a,
/* Idem : cette règle porte un ID, donc elle l'emportait sur .btn--or. */
#accueil.section--sombre a:not(.btn) { color: var(--vh-or-clair); }
/* Le compte à rebours du hero est le plus grand de la page. */
#accueil [data-countdown] { justify-content: center; margin-inline: auto; }

/* Hero court pour les pages dédiées (mobile-first : le formulaire doit
   rester atteignable sans long défilement). */
.hero--compact {
  min-height: 0;
  padding-block: clamp(2rem, 7vw, 3.5rem);
  text-align: left;
}

.hero__contenu {
  position: relative;
  z-index: 2;
  width: 100%;
  display: grid;
  gap: clamp(1rem, 3vw, 1.5rem);
  justify-items: center;
}
.hero--compact .hero__contenu { justify-items: start; }
.hero__contenu > * { margin-bottom: 0; }

/* --- Rayons de lumière (pseudo-élément 1) --- */
.hero::before,
#accueil.section--sombre::before {
  content: "";
  position: absolute;
  z-index: 0;
  inset: -25% -20% auto -20%;
  height: 150%;
  background:
    conic-gradient(from 188deg at 50% 0%,
      transparent 0deg,
      rgba(255, 255, 255, .10) 7deg,
      transparent 15deg,
      transparent 26deg,
      rgba(230, 201, 63, .14) 33deg,
      transparent 41deg,
      transparent 55deg,
      rgba(255, 255, 255, .07) 61deg,
      transparent 70deg,
      transparent 82deg,
      rgba(230, 201, 63, .10) 88deg,
      transparent 96deg),
    radial-gradient(60% 45% at 22% 8%, rgba(230, 201, 63, .18), transparent 70%),
    radial-gradient(70% 50% at 82% 92%, rgba(0, 108, 104, .40), transparent 72%);
  filter: blur(8px);
  opacity: .9;
  transform-origin: 50% 0%;
  animation: vh-rayons 20s ease-in-out infinite alternate;
  -webkit-mask-image: linear-gradient(180deg, #000 0%, rgba(0, 0, 0, .55) 55%, transparent 92%);
          mask-image: linear-gradient(180deg, #000 0%, rgba(0, 0, 0, .55) 55%, transparent 92%);
  pointer-events: none;
}

/* --- Bokeh : 20 particules obtenues avec 1 élément + 19 box-shadow --- */
.hero::after,
#accueil.section--sombre::after {
  content: "";
  position: absolute;
  z-index: 1;
  top: 0; left: 0;
  width: 9px; height: 9px;
  border-radius: 50%;
  background: rgba(255, 255, 255, .22);
  transform: translate(6vw, 14vh);
  filter: blur(2.5px);
  opacity: .85;
  pointer-events: none;
  box-shadow:
     10vw  48vh 0 1px rgba(255, 255, 255, .20),
     16vw  62vh 0 4px rgba(207, 174, 31, .18),
     24vw  28vh 0 0   rgba(255, 255, 255, .16),
     33vw  78vh 0 3px rgba(207, 174, 31, .14),
     41vw  12vh 0 2px rgba(255, 255, 255, .15),
     47vw  52vh 0 6px rgba(207, 174, 31, .10),
     55vw  22vh 0 1px rgba(255, 255, 255, .19),
     61vw  70vh 0 3px rgba(207, 174, 31, .15),
     68vw  38vh 0 0   rgba(255, 255, 255, .21),
     74vw  86vh 0 5px rgba(207, 174, 31, .11),
     81vw  18vh 0 2px rgba(255, 255, 255, .17),
     88vw  58vh 0 3px rgba(207, 174, 31, .13),
     93vw  32vh 0 1px rgba(255, 255, 255, .15),
     12vw  90vh 0 2px rgba(255, 255, 255, .12),
     29vw  92vh 0 4px rgba(207, 174, 31, .11),
     38vw  66vh 0 1px rgba(255, 255, 255, .16),
     52vw  88vh 0 2px rgba(207, 174, 31, .12),
     70vw   8vh 0 1px rgba(255, 255, 255, .13),
     85vw  74vh 0 4px rgba(207, 174, 31, .12);
  animation: vh-bokeh 26s ease-in-out infinite alternate;
}

@keyframes vh-degrade {
  0%   { background-position:   0%   0%; }
  50%  { background-position: 100%  55%; }
  100% { background-position:  25% 100%; }
}
@keyframes vh-rayons {
  0%   { transform: rotate(-3deg) scale(1);    opacity: .75; }
  50%  { transform: rotate(2deg)  scale(1.06); opacity: 1; }
  100% { transform: rotate(4deg)  scale(1.02); opacity: .8; }
}
@keyframes vh-bokeh {
  0%   { transform: translate(6vw, 14vh) scale(1);    opacity: .55; }
  50%  { transform: translate(4vw,  6vh) scale(1.12); opacity: .95; }
  100% { transform: translate(8vw, -2vh) scale(.95);  opacity: .6; }
}

/* Monogramme / logo dans le hero. */
.hero__logo {
  width: clamp(72px, 18vw, 116px);
  height: auto;
  margin-inline: auto;
  filter: drop-shadow(0 8px 20px rgba(0, 0, 0, .35));
}
.hero--compact .hero__logo { margin-inline: 0; }

/* --- Compte à rebours ---
   Piloté par [data-countdown] (conteneur) et [data-cd] (valeurs).
   Peut apparaître plusieurs fois : la taille s'adapte au contexte. */
[data-countdown] {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: stretch;
  gap: clamp(.4rem, 2vw, .9rem);
  margin: 0;
  padding: 0;
  list-style: none;
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
}
/* Chaque enfant direct est une cellule (jours / heures / minutes / secondes). */
[data-countdown] > * {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: .1rem;
  min-width: clamp(4rem, 17vw, 6.25rem);
  padding: .6rem .5rem .5rem;
  margin: 0;
  border-radius: var(--vh-rayon);
  background: rgba(255, 255, 255, .10);
  border: 1px solid rgba(255, 255, 255, .18);
  -webkit-backdrop-filter: blur(6px);
          backdrop-filter: blur(6px);
}
[data-countdown] [data-cd] {
  display: block;
  font-size: clamp(1.6rem, 1rem + 3.6vw, 3rem);
  font-weight: 800;
  line-height: 1;
  letter-spacing: -.02em;
  color: var(--vh-blanc);
}
/* Libellé sous le nombre (span, small, div… au choix du HTML). */
[data-countdown] > * > :not([data-cd]) {
  font-size: clamp(.625rem, .58rem + .2vw, .75rem);
  font-weight: 700;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--vh-or-clair);
  margin: 0;
}
/* Sur fond clair, les cellules se posent sur un fond vert lisible. */
.section--sable [data-countdown] > *,
.section--clair [data-countdown] > *,
#accueil [data-countdown] > * {
  background: var(--vh-vert-fonce);
  border-color: rgba(207, 174, 31, .5);
}
/* Sur la photographie du hero, une cellule vitrée BLANCHE éclaircirait le
   fond : les libellés dorés y tombaient à 2,54:1 sur les zones claires de
   l'image. Elle est donc un panneau vert de nuit translucide, qui assombrit —
   l'or y remonte à 5,5:1 et les chiffres blancs à 9:1, mesuré sur le pixel le
   plus clair de la photo. */
#accueil [data-countdown] > * {
  background: rgba(1, 49, 46, .55);
  border-color: rgba(207, 174, 31, .45);
}

/* Compte à rebours miniature dans la barre d'annonce. */
[data-annonce] [data-countdown] { display: inline-flex; gap: .35rem; }
[data-annonce] [data-countdown] > * {
  min-width: 0;
  padding: 0 .25rem;
  background: transparent;
  border: 0;
  flex-direction: row;
  gap: .1rem;
  -webkit-backdrop-filter: none;
          backdrop-filter: none;
}
[data-annonce] [data-countdown] [data-cd] { font-size: 1rem; font-weight: 800; }
[data-annonce] [data-countdown] > * > :not([data-cd]) {
  font-size: .8125rem;
  letter-spacing: 0;
  text-transform: none;
  color: rgba(255, 255, 255, .8);
}
/* Échéance dépassée (classe posée par app.js). */
[data-countdown].is-echu { opacity: .7; }


/* =============================================================================
   12. PLATEFORMES DE DIRECT (6 boutons)
   ============================================================================= */

/* Bandeau « c'est maintenant ».
   Masqué par défaut ; app.js pose .is-live sur [data-en-direct] pendant un
   créneau de CONFIG.creneauxDirect, exactement comme sur la barre du haut.
   Sans lui, la section du direct ne disait pas si la soirée avait commencé.
   Pas de pulsation : le rouge suffit (même parti pris que la barre). */
.direct-live { display: none; }
.direct-live.is-live {
  display: flex;
  align-items: center;
  gap: .5rem;
  margin: 0 0 1rem;
  padding: .6rem .9rem;
  border: 1px solid rgba(177, 32, 41, .35);
  border-radius: var(--vh-rayon);
  background: rgba(177, 32, 41, .08);
  color: var(--vh-rouge);          /* 6,3:1 sur ce fond, et en gras */
  font-weight: 700;
}
.direct-live__point {
  width: .6rem;
  height: .6rem;
  flex: none;
  border-radius: 50%;
  background: var(--vh-rouge);
}

.plateformes {
  display: grid;
  /* Mobile : une plateforme par ligne, chacune pleinement lisible. */
  grid-template-columns: minmax(0, 1fr);
  gap: .75rem;
  margin: 0;
  padding: 0;
  list-style: none;
}
/* Le nombre de tuiles VISIBLES varie : un lien laissé vide dans CONFIG n'est
   pas affiché du tout (data-config-repli, js/app.js). Une grille figée à 6
   colonnes laissait alors un trou à droite. auto-fit ne crée que les colonnes
   utiles — plafonnées pour qu'une tuile isolée ne s'étire pas — et le groupe
   reste centré quel que soit le compte. */
/* Écrans moyens : trois colonnes, soit deux rangées pour cinq plateformes. */
@media (min-width: 620px) {
  .plateformes {
    grid-template-columns: repeat(3, minmax(0, 11rem));
    justify-content: center;
  }
}
/* Grands écrans : tout tient sur une seule ligne. auto-fit plutôt qu'un
   nombre figé, car une plateforme laissée vide dans CONFIG n'est pas
   affichée du tout : la rangée s'ajuste au compte réel. */
@media (min-width: 1024px) {
  .plateformes {
    grid-template-columns: repeat(auto-fit, minmax(8.5rem, 11rem));
    justify-content: center;
  }
}
.plateformes > li { margin: 0; }

.plateforme {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  /* Hauteur et respiration indexees sur la largeur de l'ecran : les tuiles
     restent compactes sur un telephone et prennent de l'ampleur sur grand
     ecran, sans jamais descendre sous la cible tactile de 84px. */
  gap: clamp(.4rem, .25rem + .4vw, .65rem);
  width: 100%;
  min-height: clamp(84px, 66px + 4.6vw, 124px);
  padding: clamp(.9rem, .6rem + .8vw, 1.4rem) .6rem;
  border: 1px solid var(--vh-trait);
  border-radius: var(--vh-rayon);
  background: var(--vh-blanc);
  color: var(--vh-vert-fonce);
  font-size: clamp(.8125rem, .77rem + .18vw, .9375rem);
  font-weight: 700;
  text-align: center;
  text-decoration: none;
  box-shadow: var(--vh-ombre-douce);
  transition: transform var(--vh-t) var(--vh-easing),
              box-shadow var(--vh-t) var(--vh-easing),
              border-color var(--vh-t) var(--vh-easing),
              background-color var(--vh-t) var(--vh-easing);
}
.plateforme:hover {
  transform: translateY(-4px);
  box-shadow: var(--vh-ombre-carte);
  border-color: var(--vh-or);
  color: var(--vh-vert-fonce);
}
.plateforme svg { width: 1.7rem; height: 1.7rem; fill: currentColor; flex: none; }

/* --- Tuile principale ---
   Des portes de même poids, c'est autant de décisions à prendre pour quelqu'un
   qui arrive à 20h29. Une seule est désignée — la diffusion principale — mais
   elle reste une tuile parmi les autres, dans la même rangée : c'est son
   liseré doré et sa ligne de détail qui la marquent, pas sa taille. Sortie de
   la grille, elle flottait au-dessus et pesait moins que le groupe. */
.plateforme--principale {
  border-width: 2px;
  border-color: var(--vh-trait-or);
}
.plateforme__texte { display: flex; flex-direction: column; gap: .1rem; }
.plateforme__nom { font-weight: 700; }
.plateforme__detail {
  font-size: .75rem;
  font-weight: 500;
  color: var(--vh-encre-doux);    /* 8,3:1 sur blanc */
}
/* Sur fond sombre (merci.html), le gris foncé disparaîtrait dans la tuile
   vitrée : on repasse au blanc adouci, comme les autres textes secondaires
   de ces contextes (5,8:1 sur la tuile). */
.hero .plateforme__detail,
.section--sombre .plateforme__detail,
.carte--sombre .plateforme__detail,
.carte--action .plateforme__detail { color: rgba(255, 255, 255, .82); }
/* La tuile marquée porte une ligne de plus : sans cela elle serait la seule
   haute de la rangée. Les cases de la grille s'étirent déjà à la plus haute ;
   il ne manquait qu'aux tuiles de remplir la leur — et aux rangées d'avoir
   toutes la même hauteur (sur mobile, la grille passe à deux rangées et la
   seconde était plus courte que la première). */
.plateformes { grid-auto-rows: 1fr; }
.plateformes .plateforme { height: 100%; }

/* Variante vitrée quand le bandeau est posé sur fond sombre. */
.hero .plateforme,
.section--sombre .plateforme,
.carte--sombre .plateforme,
.carte--action .plateforme {
  background: rgba(255, 255, 255, .10);
  border-color: rgba(255, 255, 255, .22);
  color: var(--vh-blanc);
  -webkit-backdrop-filter: blur(6px);
          backdrop-filter: blur(6px);
}
.hero .plateforme:hover,
.section--sombre .plateforme:hover,
.carte--sombre .plateforme:hover,
.carte--action .plateforme:hover {
  background: rgba(255, 255, 255, .18);
  border-color: var(--vh-or);
  color: var(--vh-blanc);
}


/* =============================================================================
   13. TIMELINE DU PROGRAMME
   Mobile : une colonne, fil à gauche. ≥ 900px : fil central, cartes alternées.
   ============================================================================= */

.timeline {
  position: relative;
  display: grid;
  gap: clamp(1rem, 3vw, 1.75rem);
  margin: 0;
  padding: .5rem 0 .5rem 2.75rem;
  list-style: none;
}
/* Le fil conducteur. */
.timeline::before {
  content: "";
  position: absolute;
  left: 1rem;
  top: .5rem;
  bottom: .5rem;
  width: 2px;
  margin-left: -1px;
  border-radius: 2px;
  background: linear-gradient(180deg,
              rgba(207, 174, 31, 0) 0%,
              var(--vh-or) 8%,
              var(--vh-or) 92%,
              rgba(207, 174, 31, 0) 100%);
}
.section--sombre .timeline::before {
  background: linear-gradient(180deg,
              rgba(230, 201, 63, 0) 0%,
              var(--vh-or-clair) 8%,
              var(--vh-or-clair) 92%,
              rgba(230, 201, 63, 0) 100%);
}

.timeline__item { position: relative; margin: 0; }

/* Le point sur le fil. */
.timeline__point {
  position: absolute;
  left: -2.75rem;
  top: .55rem;
  width: 2rem;
  height: 2rem;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: var(--vh-vert);
  border: 3px solid var(--vh-sable);
  box-shadow: 0 0 0 3px rgba(207, 174, 31, .45);
  color: var(--vh-blanc);
  font-size: .75rem;
  font-weight: 800;
  line-height: 1;
  z-index: 2;
  transition: transform var(--vh-t) var(--vh-easing),
              background-color var(--vh-t) var(--vh-easing);
}
.section--clair .timeline__point { border-color: var(--vh-clair); }
.section--sombre .timeline__point {
  background: var(--vh-or);
  border-color: var(--vh-vert-fonce);
  color: var(--vh-encre);
  box-shadow: 0 0 0 3px rgba(230, 201, 63, .30);
}
.timeline__item:hover .timeline__point { transform: scale(1.12); }
.timeline__point svg { width: 1rem; height: 1rem; fill: currentColor; }

/* La carte de l'étape. */
.timeline__carte {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: .35rem;
  padding: clamp(1.1rem, 3.5vw, 1.6rem);
  background: var(--vh-blanc);
  border: 1px solid var(--vh-trait);
  border-left: 4px solid var(--vh-or);
  border-radius: var(--vh-rayon);
  box-shadow: var(--vh-ombre-carte);
  transition: transform var(--vh-t) var(--vh-easing),
              box-shadow var(--vh-t) var(--vh-easing);
}
.timeline__carte:hover {
  transform: translateY(-4px);
  box-shadow: var(--vh-ombre-carte-fort);
}
.timeline__carte > :last-child { margin-bottom: 0; }
.section--sombre .timeline__carte {
  background: rgba(255, 255, 255, .07);
  border-color: rgba(255, 255, 255, .16);
  border-left-color: var(--vh-or);
  color: var(--vh-blanc);
  -webkit-backdrop-filter: blur(6px);
          backdrop-filter: blur(6px);
}

.timeline__date {
  display: block;
  font-size: .8125rem;
  font-weight: 800;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--vh-vert);
  margin: 0;
}
.section--sombre .timeline__date { color: var(--vh-or-clair); }

.timeline__horaire {
  display: inline-flex;
  align-items: center;
  gap: .35em;
  align-self: flex-start;
  padding: .25rem .7rem;
  border-radius: var(--vh-rayon-pill);
  background: rgba(207, 174, 31, .20);
  border: 1px solid var(--vh-trait-or);
  color: var(--vh-encre);   /* jamais de texte or sur fond clair */
  font-size: .8125rem;
  font-weight: 700;
  margin: 0;
}
.section--sombre .timeline__horaire {
  background: rgba(255, 255, 255, .14);
  color: var(--vh-blanc);
}

/* L'axe de prière du jour : c'est le titre de l'étape. */
/* L'axe DÉCRIT l'étape, il ne la titre pas : le <h3> s'en charge. En 800 et
   jusqu'à 1,31rem, il écrasait visuellement le titre qu'il suit. */
.timeline__axe {
  font-size: 1rem;
  font-weight: 400;
  line-height: 1.6;
  color: var(--vh-encre-doux);
  margin: .35rem 0 0;
}
.section--sombre .timeline__axe { color: rgba(255, 255, 255, .88); }

/* Le verset associé. */
.timeline__verset {
  position: relative;
  margin: .85rem 0 0;
  /* Le filet vient de la règle générique `blockquote` : on l'annule ici.
     Deux traits verticaux — celui de la carte et celui du verset — se
     concurrençaient. C'est le guillemet doré qui signale la citation. */
  border-left: 0;
  padding: .1rem 0 0 2.1rem;
  font-style: italic;
  font-size: .9375rem;
  line-height: 1.55;
  color: var(--vh-encre-doux);
}

/* ≥ 900px : fil central, cartes alternées de part et d'autre. */
@media (min-width: 900px) {
  .timeline { padding-left: 0; }
  .timeline::before { left: 50%; }
  .timeline__item { width: calc(50% - 2.5rem); }
  .timeline__item:nth-child(odd) { margin-right: auto; }
  .timeline__item:nth-child(even) { margin-left: auto; }
  .timeline__item:nth-child(odd) .timeline__point { left: auto; right: -3.5rem; }
  .timeline__item:nth-child(even) .timeline__point { left: -3.5rem; right: auto; }
  /* Petit trait de raccord entre la carte et le fil. */
  .timeline__item::after {
    content: "";
    position: absolute;
    top: 1.5rem;
    width: 1.5rem;
    height: 2px;
    background: var(--vh-trait-or);
  }
  .timeline__item:nth-child(odd)::after { right: -1.85rem; }
  .timeline__item:nth-child(even)::after { left: -1.85rem; }
}


/* =============================================================================
   14. FORMULAIRES
   ============================================================================= */

.form {
  display: grid;
  gap: clamp(.85rem, 2.5vw, 1.15rem);
  width: 100%;
}
@media (min-width: 720px) {
  .form--2col { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .form--2col .champ--large,
  .form--2col .champ--case,
  .form--2col .form-statut,
  .form--2col [data-conditionnel],
  .form--2col .form__actions { grid-column: 1 / -1; }
}

.champ {
  display: grid;
  gap: .35rem;
  min-width: 0;
}
.champ label {
  font-size: .9375rem;
  font-weight: 700;
  line-height: 1.4;
  color: var(--vh-texte);
}
/* Astérisque des champs obligatoires (si le HTML en pose un). */
.champ label .obligatoire,
.champ .obligatoire { color: var(--vh-rouge); font-weight: 800; }

.champ input,
.champ select,
.champ textarea {
  width: 100%;
  min-height: 48px;
  padding: .75rem .95rem;
  background: var(--vh-blanc);
  color: var(--vh-encre);
  border: 2px solid rgba(1, 66, 62, .20);
  border-radius: var(--vh-rayon);
  font-size: 1rem;   /* ≥16px : évite le zoom automatique sur iOS */
  line-height: 1.45;
  box-shadow: inset 0 1px 2px rgba(1, 48, 45, .05);
  transition: border-color var(--vh-t) var(--vh-easing),
              box-shadow var(--vh-t) var(--vh-easing),
              background-color var(--vh-t) var(--vh-easing);
  appearance: none;
  -webkit-appearance: none;
}
.champ textarea { min-height: 8rem; resize: vertical; }
.champ select {
  /* Chevron dessiné en CSS pur (pas de fichier image). */
  background-image:
    linear-gradient(45deg, transparent 50%, var(--vh-vert) 50%),
    linear-gradient(135deg, var(--vh-vert) 50%, transparent 50%);
  background-position:
    calc(100% - 1.15rem) calc(50% + 1px),
    calc(100% - .8rem) calc(50% + 1px);
  background-size: 6px 6px, 6px 6px;
  background-repeat: no-repeat;
  padding-right: 2.4rem;
}
.champ input::placeholder,
.champ textarea::placeholder { color: #7A8B89; opacity: 1; }

.champ input:hover,
.champ select:hover,
.champ textarea:hover { border-color: rgba(1, 66, 62, .35); }

.champ input:focus,
.champ select:focus,
.champ textarea:focus {
  outline: none;
  border-color: var(--vh-vert);
  box-shadow: 0 0 0 4px rgba(0, 108, 104, .18);
}
.champ input:focus-visible,
.champ select:focus-visible,
.champ textarea:focus-visible { outline: 3px solid var(--vh-focus); outline-offset: 2px; }

/* Champs sur fond sombre. */
.section--sombre .champ label,
.carte--sombre .champ label,
.carte--action .champ label { color: var(--vh-blanc); }

/* Case à cocher alignée avec son libellé. */
.champ--case {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: .7rem;
}
.champ--case input[type="checkbox"],
.champ--case input[type="radio"] {
  width: 1.35rem;
  height: 1.35rem;
  min-height: 0;
  flex: none;
  margin-top: .15rem;
  padding: 0;
  accent-color: var(--vh-vert);
  border-width: 2px;
  border-radius: 6px;
  box-shadow: none;
  appearance: auto;
  -webkit-appearance: auto;
  cursor: pointer;
}
.champ--case input[type="radio"] { border-radius: 50%; }
.champ--case > label,
.champ--case label {
  flex: 1 1 0;
  min-width: 12rem;
  font-size: .9375rem;
  font-weight: 500;
  line-height: 1.5;
  cursor: pointer;
}
.champ--case .msg-erreur { flex: 1 1 100%; }

/* État invalide. */
.champ--erreur input,
.champ--erreur select,
.champ--erreur textarea {
  border-color: var(--vh-rouge);
  background: #FFF6F6;
}
.champ--erreur input:focus,
.champ--erreur select:focus,
.champ--erreur textarea:focus {
  box-shadow: 0 0 0 4px rgba(177, 32, 41, .18);
}
.champ--erreur label { color: var(--vh-rouge); }
.section--sombre .champ--erreur label,
.carte--sombre .champ--erreur label { color: #FFC9CC; }

/* Message d'erreur sous le champ (masqué tant qu'il est vide). */
.msg-erreur {
  margin: 0;
  font-size: .875rem;
  font-weight: 600;
  line-height: 1.45;
  color: var(--vh-rouge);
  display: flex;
  align-items: flex-start;
  gap: .35em;
}
.msg-erreur:empty { display: none; }
.msg-erreur::before { content: "⚠"; font-size: .95em; line-height: 1.5; }
.section--sombre .msg-erreur,
.carte--sombre .msg-erreur,
.carte--action .msg-erreur { color: #FFC9CC; }

/* Zone de retour globale du formulaire (role="status"). */
.form-statut {
  margin: 0;
  padding: .85rem 1.1rem;
  border-radius: var(--vh-rayon);
  border: 1px solid var(--vh-trait);
  background: var(--vh-clair);
  color: var(--vh-encre);
  font-size: .9375rem;
  font-weight: 600;
  line-height: 1.5;
}
.form-statut:empty { display: none; }
.form-statut--erreur {
  background: #FFF1F1;
  border-color: rgba(177, 32, 41, .35);
  color: #7E141B;   /* rouge assombri : AA sur fond rosé */
}
.form-statut--succes {
  background: #EAF6F3;
  border-color: rgba(0, 108, 104, .35);
  color: #044C48;
}
.form-statut--info {
  background: var(--vh-sable);
  border-color: var(--vh-trait-or);
  color: var(--vh-encre);
}

/* --- .note ---
   Petit texte légal, mention RGPD, indice de champ.
   Gris FONCÉ volontairement (--vh-encre-doux = #3E5250, ratio ≈ 8.3:1 sur
   blanc et 7.7:1 sur sable) : le petit corps impose de garder AA large.
   Sur fond sombre, on passe à un gris très clair (ratio ≈ 8.8:1). */
.note,
.form__note,
.mention-rgpd {
  display: block;
  margin: 0;
  font-size: .8125rem;
  font-weight: 500;
  line-height: 1.55;
  color: var(--vh-encre-doux);
  letter-spacing: 0;
  text-transform: none;
}
.note + .note { margin-top: .35rem; }
.note a { color: var(--vh-vert); text-decoration: underline; }

/* Dans un champ : l'indice se glisse sous le label, avant le contrôle. */
.champ .note { margin: -.1rem 0 .1rem; }
/* Dans une case à cocher : le complément légal passe sous la ligne cochable. */
.champ--case .note { flex: 1 1 100%; margin: 0; }
.champ--case label .note,
.champ--case label > span.note { display: block; margin-top: .2rem; }

/* Variante sur fond sombre (carte d'action, section sombre, hero, pied). */
.section--sombre .note,
.section--sombre .form__note,
.section--sombre .mention-rgpd,
.carte--sombre .note,
.carte--action .note,
.hero .note,
footer .note,
.pied .note { color: #D9E5E3; }
.section--sombre .note a,
.carte--sombre .note a,
.carte--action .note a,
.hero .note a,
footer .note a,
.pied .note a { color: var(--vh-or-clair); }

/* Repli sans classe : un <p> ou un <span> nu posé dans un .champ (hors
   message d'erreur) ou en fin de .form est traité comme une note. */
.champ > p:not(.msg-erreur):not(.form-statut),
.champ > small,
.form > p:not(.msg-erreur):not(.form-statut):not(.lead),
.form > small {
  font-size: .8125rem;
  font-weight: 500;
  line-height: 1.55;
  color: var(--vh-encre-doux);
  margin: 0;
}
/* Un <span> nu dans un libellé de case porte en général le complément légal.
   On reste à .875rem (et non .8125rem) au cas où il contiendrait en réalité
   TOUT le texte de consentement : il doit rester confortable à lire. */
.champ--case label > span:not(.obligatoire):not(.sr-only):not(.badge) {
  display: block;
  margin-top: .2rem;
  font-size: .875rem;
  font-weight: 500;
  line-height: 1.5;
  color: var(--vh-encre-doux);
}
.section--sombre .champ > p:not(.msg-erreur),
.section--sombre .form > p:not(.msg-erreur):not(.form-statut),
.section--sombre .champ--case label > span:not(.obligatoire):not(.sr-only):not(.badge),
.carte--sombre .champ > p:not(.msg-erreur),
.carte--action .champ > p:not(.msg-erreur) { color: #D9E5E3; }

.form__actions { display: grid; gap: .75rem; }

/* Honeypot anti-spam : invisible à l'écran ET pour les lecteurs d'écran.
   (app.js pose en plus tabindex="-1" et aria-hidden="true".) */
.hp {
  position: absolute !important;
  left: -9999px !important;
  top: auto !important;
  width: 1px !important;
  height: 1px !important;
  overflow: hidden;
  opacity: 0;
  pointer-events: none;
}

/* Bloc de champs conditionnels : masqué tant que la case n'est pas cochée.
   Sans JS il reste visible (le formulaire doit rester utilisable). */
[data-conditionnel] { display: none; }
[data-conditionnel].est-visible { display: grid; gap: .85rem; }
.no-js [data-conditionnel] { display: grid; gap: .85rem; }
[data-conditionnel].est-visible {
  animation: vh-depliage var(--vh-t-lente) var(--vh-easing) both;
}
@keyframes vh-depliage {
  from { opacity: 0; transform: translateY(-6px); }
  to   { opacity: 1; transform: none; }
}


/* =============================================================================
   15. QR CODE, CARTE MAPS, PARTAGE
   ============================================================================= */

/* Conteneur du QR : app.js y insère un <canvas> (ou un message si le lien
   n'est pas encore configuré). */
[data-qr] {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: .6rem;
  padding: .85rem;
  background: var(--vh-blanc);
  border: 1px solid var(--vh-trait-or);
  border-radius: var(--vh-rayon);
  box-shadow: var(--vh-ombre-douce);
  max-width: 15rem;
  margin-inline: auto;
}
[data-qr] canvas {
  width: 100%;
  height: auto;
  border-radius: var(--vh-rayon-xs);
  image-rendering: pixelated;
  image-rendering: crisp-edges;
}
[data-qr] p {
  margin: 0;
  font-size: .8125rem;
  line-height: 1.45;
  text-align: center;
  color: var(--vh-encre-doux);
}
/* Message de repli quand la cible n'est pas configurée. */
[data-qr].est-vide {
  background: var(--vh-sable);
  border-style: dashed;
  min-height: 8rem;
  justify-content: center;
}

/* Carte Google Maps différée : l'iframe n'est injectée qu'au clic. */
[data-maps] {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: .75rem;
  align-items: center;
  justify-content: center;
  min-height: 14rem;
  padding: 1.25rem;
  border-radius: var(--vh-rayon-lg);
  border: 1px solid var(--vh-trait);
  background:
    linear-gradient(160deg, rgba(0, 108, 104, .10), rgba(207, 174, 31, .12)),
    var(--vh-clair);
  overflow: hidden;
  text-align: center;
}
[data-maps] iframe {
  width: 100%;
  min-height: clamp(14rem, 42vw, 22rem);
  border: 0;
  border-radius: var(--vh-rayon);
  display: block;
}
[data-maps].est-chargee { padding: 0; min-height: 0; border-color: var(--vh-trait-or); }
[data-maps] .maps__note {
  margin: 0;
  font-size: .8125rem;
  color: var(--vh-encre-doux);
  max-width: 34ch;
}

/* Boutons de partage. */
.partage { display: flex; flex-wrap: wrap; gap: .75rem; }
[data-copier-lien].est-copie {
  background: var(--vh-vert);
  color: var(--vh-blanc);
  border-color: var(--vh-vert);
}
/* Repli de partage : révélé par app.js quand navigator.share est absent. */
[data-partage-repli] { display: none; }
[data-partage-repli].est-visible { display: flex; flex-wrap: wrap; gap: .75rem; }
.no-js [data-partage-repli] { display: flex; flex-wrap: wrap; gap: .75rem; }


/* =============================================================================
   16. RÉVÉLATION AU SCROLL
   .reveal devient visible quand app.js ajoute .is-visible.
   Sans JS (html.no-js) ou en mouvement réduit, l'élément est visible d'emblée.
   ============================================================================= */

.reveal {
  opacity: 0;
  transform: translateY(24px);
  transition: opacity var(--vh-t-lente) var(--vh-easing),
              transform var(--vh-t-lente) var(--vh-easing);
  will-change: opacity, transform;
}
.reveal.is-visible {
  opacity: 1;
  transform: none;
  will-change: auto;
}
.no-js .reveal { opacity: 1; transform: none; }

/* Léger décalage en cascade entre éléments voisins. */
.grid > .reveal:nth-child(2),
.timeline > .reveal:nth-child(2) { transition-delay: .07s; }
.grid > .reveal:nth-child(3),
.timeline > .reveal:nth-child(3) { transition-delay: .14s; }
.grid > .reveal:nth-child(4),
.timeline > .reveal:nth-child(4) { transition-delay: .21s; }
.grid > .reveal:nth-child(5),
.timeline > .reveal:nth-child(5) { transition-delay: .28s; }
.grid > .reveal:nth-child(6),
.timeline > .reveal:nth-child(6) { transition-delay: .35s; }


/* =============================================================================
   17. DIVERS
   ============================================================================= */

/* Lien/bouton dont la valeur CONFIG n'est pas encore renseignée.
   app.js pose l'attribut data-config-manquant : on le neutralise
   visuellement sans jamais produire de lien mort.
   Attention : la règle est volontairement limitée aux <a> et <button>.
   Un simple texte (adresse, libellé) marqué data-config-manquant garde son
   contenu de repli écrit dans le HTML et son apparence normale. */
a[data-config-manquant],
button[data-config-manquant] {
  opacity: .5;
  cursor: not-allowed;
  filter: grayscale(.55);
  box-shadow: none !important;
  text-decoration: none;
}
a[data-config-manquant]:hover,
button[data-config-manquant]:hover {
  transform: none !important;
  box-shadow: none !important;
}
a[data-config-manquant]::after,
button[data-config-manquant]::after {
  content: " (bientôt)";
  font-size: .8em;
  font-weight: 600;
  opacity: .85;
}

/* Encadré (prière de repentance, encart de mise en avant). */
.encadre {
  padding: clamp(1.1rem, 4vw, 1.75rem);
  border-radius: var(--vh-rayon-lg);
  border: 1px solid var(--vh-trait-or);
  border-left: 5px solid var(--vh-or);
  background: var(--vh-sable);
  color: var(--vh-encre);
  box-shadow: var(--vh-ombre-douce);
}
.encadre > :last-child { margin-bottom: 0; }
.section--sombre .encadre {
  background: rgba(255, 255, 255, .08);
  color: var(--vh-blanc);
}

/* --- Citation biblique ---
   Employée sur fond clair ET sur fond sombre : la couleur du texte est
   héritée du contexte, seul le filet est doré (jamais de texte or sur clair). */
.verset {
  margin: 0 0 1em;
  padding: .25rem 0 .25rem 1rem;
  border-left: 3px solid var(--vh-or);
  font-style: italic;
  font-size: clamp(1rem, .96rem + .35vw, 1.125rem);
  line-height: 1.6;
  max-width: 52ch;
  color: inherit;
}
.section--sombre .verset,
.carte--sombre .verset,
.carte--action .verset,
.hero .verset { border-left-color: var(--vh-or-clair); }
/* Un verset qui SUIT une carte, au lieu de vivre dedans : `.verset` n'a pas
   de marge haute (elle vaut 0), la citation venait donc coller le bas de la
   carte sombre. La règle ne vise que la fratrie — sur merci.html le verset
   est À L'INTÉRIEUR de la carte et ne doit rien gagner. */
.carte + .verset { margin-top: var(--vh-gap); }
/* Variante centrée (hero, bandeau de verset directeur). */
.verset--centre {
  border-left: 0;
  padding: 0;
  text-align: center;
  margin-inline: auto;
}
.verset cite,
.verset .reference {
  display: block;
  margin-top: .5rem;
  font-style: normal;
  font-size: .8125rem;
  font-weight: 800;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--vh-accent);
}
.verset > p { margin: 0 0 .35em; }
.verset > p:last-of-type { margin-bottom: 0; }

/* Pied de page. */
footer,
.pied {
  /* Vert de nuit, comme la barre d'annonce en haut de page : les deux
     extrémités du document se répondent et encadrent le contenu — sans le
     quasi-noir qui les rendait funèbres. */
  background: var(--vh-vert-nuit);
  color: rgba(255, 255, 255, .88);
  border-top: 3px solid var(--vh-or);
  padding-block: clamp(2rem, 6vw, 3.25rem);
  font-size: .9375rem;
}
footer a,
.pied a { color: var(--vh-or-clair); }
footer a:hover,
.pied a:hover { color: var(--vh-blanc); }
footer :focus-visible,
.pied :focus-visible { outline-color: var(--vh-or-clair); }
footer ul,
.pied ul { list-style: none; padding: 0; }
footer svg,
.pied svg { fill: currentColor; }

/* Réseaux sociaux du pied de page (icônes SVG inline). */
.reseaux { display: flex; flex-wrap: wrap; gap: .6rem; align-items: center; }
.reseaux a {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px; height: 44px;
  border-radius: 50%;
  border: 1px solid rgba(255, 255, 255, .22);
  color: var(--vh-blanc);
  transition: background-color var(--vh-t) var(--vh-easing),
              transform var(--vh-t) var(--vh-easing),
              border-color var(--vh-t) var(--vh-easing);
}
.reseaux a:hover {
  background: rgba(255, 255, 255, .14);
  border-color: var(--vh-or);
  transform: translateY(-2px);
  color: var(--vh-blanc);
}
.reseaux svg { width: 1.25rem; height: 1.25rem; flex: none; }

/* Les pastilles rondes du pied de page ne peuvent pas accueillir la mention
   « (bientôt) » des liens non configurés : le texte écrase l'icône (SVG réduit
   à 0 de large dans le flex). L'information reste portée par le title, le
   grisé et aria-disabled. */
.reseaux a[data-config-manquant]::after { content: none; }

/* Séparateur doré décoratif. */
.filet-or {
  height: 3px;
  width: min(220px, 60%);
  margin: var(--vh-esp-md) auto;
  border-radius: 3px;
  background: var(--vh-degrade-or);
}


/* =============================================================================
   18. MOUVEMENT RÉDUIT
   Neutralise animations, transitions, dégradé animé, rayons, bokeh et reveal.
   ============================================================================= */

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    animation-delay: 0ms !important;
    transition-duration: .001ms !important;
    transition-delay: 0ms !important;
    scroll-behavior: auto !important;
  }
  html { scroll-behavior: auto !important; }

  /* Le contenu révélé au scroll doit être visible d'emblée. */
  .reveal {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
  }

  /* Ambiance du hero : on garde le décor, on supprime le mouvement.
     (Le bokeh et les rayons cessent de bouger, le dégradé se fige.) */
  .hero,
  #accueil.section--sombre {
    animation: none !important;
    background-position: 0% 0% !important;
  }
  .hero::before,
  #accueil.section--sombre::before {
    animation: none !important;
    transform: none !important;
  }
  .hero::after,
  #accueil.section--sombre::after {
    animation: none !important;
    transform: translate(6vw, 14vh) !important;
    opacity: .5 !important;
  }

  /* Barre d'annonce en direct : plus de pulsation, le rouge suffit. */
  [data-annonce].is-live { animation: none !important; background: var(--vh-rouge) !important; }

  /* Plus de translation ni de mise à l'échelle au survol. */
  .btn:hover,
  .btn:active,
  .carte:hover,
  .carte--action:hover,
  .timeline__carte:hover,
  .timeline__item:hover .timeline__point,
  .carte--public:hover .carte__icone--public,
  .carte--public:focus-within .carte__icone--public,
  .plateforme:hover,
  .reseaux a:hover,
  [data-menu-bouton]:hover { transform: none !important; }

  /* Le filet de tête s'allume sans se dérouler. */
  .carte--public::before { transform: none !important; }

  /* Le spinner de chargement est remplacé par un point fixe. */
  .btn[aria-busy="true"]::after {
    animation: none !important;
    border-top-color: transparent;
  }

  [data-progression-scroll] { transition: none !important; }
  [data-conditionnel].est-visible { animation: none !important; }
}


/* =============================================================================
   19. IMPRESSION
   ============================================================================= */

@media print {
  [data-annonce],
  [data-progression-scroll],
  [data-menu-bouton],
  .skip-link,
  [data-maps] { display: none !important; }
  .hero,
  .section--sombre,
  .carte--sombre,
  .carte--action {
    background: none !important;
    color: #000 !important;
    border-color: #999 !important;
  }
  .hero::before,
  .hero::after,
  #accueil.section--sombre::before,
  #accueil.section--sombre::after { display: none !important; }
  .reveal { opacity: 1 !important; transform: none !important; }
  body { font-size: 11pt; color: #000; }
  a[href^="http"]::after { content: " (" attr(href) ")"; font-size: 9pt; }
}

/* =========================================================================
   COULEURS DE MARQUE DES RÉSEAUX SOCIAUX
   -------------------------------------------------------------------------
   Deux contextes, deux traitements :

   • Bandeau « Regarder le direct » (fond clair) : l'icône porte la couleur
     de sa marque en permanence — c'est ce qui rend la plateforme
     identifiable d'un coup d'œil. Au survol, la couleur passe en fond et
     l'icône devient blanche.
   • Pastilles du pied de page (fond vert profond) : blanches au repos, car
     les bleus et rouges de marque sont illisibles sur du vert foncé. La
     couleur de marque n'apparaît qu'au survol, en fond.

   WhatsApp utilise #128C7E (vert foncé officiel) et non #25D366 : sur le
   fond clair, le vert vif ne donne que 1,83:1 alors que WCAG demande 3:1
   pour un élément non textuel. Le vert foncé atteint 3,82:1.

   DEUX JETONS PAR MARQUE, ET C'EST VOLONTAIRE :
   • --marque ....... l'icône au repos. Seuil 3:1 (élément non textuel) —
                      toutes les valeurs officielles le passent sur blanc.
   • --marque-fond .. le REMPLISSAGE au survol et au focus clavier. Là, le
                      libellé passe en blanc sur cette couleur : le seuil
                      devient 4,5:1 (texte de 13 px). Les couleurs officielles
                      n'y arrivent pas — YouTube 4,00:1, WhatsApp 4,14:1,
                      Facebook 4,23:1 — d'où une nuance assombrie réservée
                      au fond : 5,89 / 7,67 / 6,44:1. L'icône garde sa
                      couleur officielle, la reconnaissance est intacte.

   INSTAGRAM : LE DÉGRADÉ OFFICIEL EST CONSERVÉ TEL QUEL, par choix assumé.
   Le relevé, pour mémoire — dégradé reproduit au pixel près sur la tuile
   réelle (200 × 109), contraste du blanc mesuré sur chaque pixel :
     • sous le libellé ......... 1,42:1  (le texte tombe dans la bande
                                 jaune-orangé ; le seuil AA est de 4,5:1)
     • icône des pastilles ..... 1,87:1  (seuil de 3:1 pour un non-texte) —
                                 écart antérieur à cette page, pas introduit ici
   Déplacer le centre n'y change rien : la moitié chaude est trop claire pour
   du blanc où qu'elle tombe (testé à 30%/-20%, 25%/-45%, 50%/-60% → 2,72 /
   3,21 / 4,49 sous le libellé, et l'icône passe alors sous 3:1).
   Deux replis déjà chiffrés, si la question se rouvre un jour :
     • voile prune rgba(59,10,69,.55) par-dessus le dégradé → 4,97 / 5,84:1,
       les trois familles de couleur restent lisibles ;
     • magenta plein #A02771 (plus de dégradé) → 6,95:1.
   ========================================================================= */

.plateforme[data-config="direct.youtube"]   { --marque: #FF0000; --marque-fond: #CC0000; }
.plateforme[data-config="direct.facebook"]  { --marque: #1877F2; --marque-fond: #0A58CA; }
.plateforme[data-config="direct.tiktok"]    { --marque: #010101; --marque-fond: #010101; }
.plateforme[data-config="direct.instagram"] { --marque: #C13584; --marque-fond: #A02771; }
.plateforme[data-config="direct.whatsapp"]  { --marque: #128C7E; --marque-fond: #075E54; }
.plateforme[data-config="direct.zoom"]      { --marque: #0B5CFF; --marque-fond: #0B5CFF; }

.reseaux a[data-config="direct.youtube"]   { --marque: #FF0000; --marque-fond: #CC0000; }
.reseaux a[data-config="direct.facebook"]  { --marque: #1877F2; --marque-fond: #0A58CA; }
.reseaux a[data-config="direct.tiktok"]    { --marque: #010101; --marque-fond: #010101; }
.reseaux a[data-config="direct.instagram"] { --marque: #C13584; --marque-fond: #A02771; }
.reseaux a[data-config="direct.whatsapp"]  { --marque: #128C7E; --marque-fond: #075E54; }
.reseaux a[data-config="direct.zoom"]      { --marque: #0B5CFF; --marque-fond: #0B5CFF; }

/* Bandeau du direct : icône colorée au repos. */
.plateforme[data-config] svg { color: var(--marque, currentColor); }

/* Survol : la marque passe en fond, tout le contenu devient blanc.
   :not([data-config-manquant]) — un bouton non configuré ne doit pas
   s'allumer aux couleurs d'une plateforme injoignable. */
.plateforme[data-config]:not([data-config-manquant]):hover,
.plateforme[data-config]:not([data-config-manquant]):focus-visible {
  background: var(--marque-fond, var(--marque));
  border-color: var(--marque-fond, var(--marque));
  color: var(--vh-blanc);
}
.plateforme[data-config]:not([data-config-manquant]):hover svg,
.plateforme[data-config]:not([data-config-manquant]):focus-visible svg {
  color: var(--vh-blanc);
}
/* La ligne de détail de la tuile principale suit l'inversion. */
.plateforme[data-config]:not([data-config-manquant]):hover .plateforme__detail,
.plateforme[data-config]:not([data-config-manquant]):focus-visible .plateforme__detail {
  color: rgba(255, 255, 255, .92);
}

/* Pastilles du pied de page : blanches au repos, marque au survol. */
.reseaux a[data-config]:not([data-config-manquant]):hover,
.reseaux a[data-config]:not([data-config-manquant]):focus-visible {
  background: var(--marque-fond, var(--marque));
  border-color: var(--marque-fond, var(--marque));
  color: var(--vh-blanc);
}

/* Instagram est un dégradé, pas une couleur plate : on le restitue au survol.
   Dégradé officiel, tel quel — voir le relevé de contraste en tête de section
   pour ce que cela coûte et pour les deux replis déjà chiffrés. L'ordre
   compte : cette règle doit rester APRÈS celle qui pose var(--marque-fond). */
.plateforme[data-config="direct.instagram"]:not([data-config-manquant]):hover,
.plateforme[data-config="direct.instagram"]:not([data-config-manquant]):focus-visible,
.reseaux a[data-config="direct.instagram"]:not([data-config-manquant]):hover,
.reseaux a[data-config="direct.instagram"]:not([data-config-manquant]):focus-visible {
  background: radial-gradient(circle at 30% 107%,
    #FDF497 0%, #FDF497 5%, #FD5949 45%, #D6249F 60%, #285AEB 90%);
  border-color: #D6249F;
}

@media (prefers-reduced-motion: reduce) {
  .plateforme[data-config]:hover { transform: none; }
}

/* =========================================================================
   MARQUE DANS L'EN-TÊTE
   Le nom de l'église était en .sr-only : invisible à l'écran. Il devient
   visible à côté du monogramme, puisqu'il a été retiré du hero où il
   faisait doublon. Sur les petites largeurs, seul « Vases d'Honneur »
   reste : le nom complet mangerait la place du bouton de menu.
   ========================================================================= */
.marque {
  display: inline-flex;
  align-items: center;
  gap: .7rem;
  text-decoration: none;
  min-width: 0;
  flex: none;
}

/* Nom sur deux lignes, à la manière du logo officiel : la mention légère
   surmonte le nom de l'assemblée en capitales. Deux lignes plutôt qu'une
   seule longue : cela compacte la marque et laisse la place au menu de
   tenir sur la même ligne. */
.marque__nom {
  display: flex;
  flex-direction: column;
  justify-content: center;
  line-height: 1.08;
  color: var(--vh-blanc);
  min-width: 0;
}
.marque__ligne1 {
  font-size: 1rem;
  font-weight: 500;
  letter-spacing: .06em;
}
.marque__ligne2 {
  font-size: .875rem;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: .01em;
  white-space: nowrap;
}

/* Le monogramme est posé sur une pastille arrondie. Le fond est le vert
   #006C68 et non l'or : un monogramme blanc sur or ne donne que 2,16:1,
   il paraîtrait délavé, alors que sur ce vert il atteint 6,28:1. Le liseré
   or restitue l'accent de la charte sans coûter en lisibilité. */
.marque .logo {
  background: var(--vh-vert);
  border: 0;
  border-radius: 13px;
  /* Carré strict : dimensions égales + object-fit, sinon le ratio du
     monogramme (1172x1011) rendrait la pastille rectangulaire. */
  width: 46px;
  height: 46px;
  padding: 7px;
  box-sizing: border-box;
  object-fit: contain;
}
.marque:hover .logo { background: #00807B; }
.marque:hover .marque__nom { color: var(--vh-or-clair); }

/* Les pages secondaires n'ont pas de `header` : elles ouvrent directement sur
   la marque, posée au-dessus du titre. `.marque` étant un inline-flex sans
   marge, elle collerait le h1 — on lui rend l'espacement que portait le
   sur-titre qu'elle remplace (`.eyebrow`, margin-bottom .95rem). */
.marque--page { margin-bottom: .95rem; }

/* À partir de 900px le menu est en ligne : le header ne doit PAS revenir
   à la ligne, sinon la navigation se retrouve sous le logo. */
@media (min-width: 900px) {
  body > header > .container { flex-wrap: nowrap; }
  [data-menu] ul { flex-wrap: nowrap; gap: clamp(.75rem, 1.4vw, 1.5rem); }
  /* Sans ceci, « Le direct » se casse en « Le / direct » dès que la place
     manque : le menu doit rétrécir ses espaces, jamais ses mots. */
  [data-menu] a { white-space: nowrap; font-size: clamp(.875rem, .8rem + .25vw, .9375rem); }
}

/* Mobile : la marque doit laisser la place au bouton de menu sur la même
   ligne. Mesuré à 375px — sans cette réduction elle occupe 266px des 337px
   utiles, et le burger bascule sous elle (header à 122px de haut). */
@media (max-width: 560px) {
  .marque { gap: .5rem; }
  .marque__ligne1 { font-size: .8125rem; letter-spacing: .04em; }
  .marque__ligne2 { font-size: .875rem; }
  /* On reduit la pastille en gardant le carre : max-height seule
     l'aplatirait en 46x36. */
  .marque .logo { width: 40px; height: 40px; padding: 6px; border-radius: 11px; }
}
@media (max-width: 360px) {
  .marque__ligne2 { font-size: .8125rem; }
}

/* =========================================================================
   HIÉRARCHIE DES ACTIONS DE PARTAGE
   Quatre boutons de même poids se disputaient l'attention. Désormais :
   une seule action principale, et des solutions de repli discrètes qui
   n'apparaissent QUE si le partage natif du téléphone est indisponible
   (le conteneur [data-partage-repli] est révélé par app.js).
   ========================================================================= */
.btn--sm {
  padding: .5rem .95rem;
  font-size: .875rem;
  border-width: 1px;
  font-weight: 600;
}


/* Filet de sécurité : deux boutons posés côte à côte dans un paragraphe se
   touchaient, faute d'être dans un conteneur .actions. Cette marge vaut
   pour les boutons restés hors d'un conteneur flex ; dans .actions,
   .boutons ou [data-partage-repli], c'est le gap qui gère l'espacement. */
p > .btn { margin: .3rem .55rem .3rem 0; }
p > .btn:last-child { margin-right: 0; }
.actions > .btn,
.boutons > .btn,
[data-partage-repli] > .btn { margin: 0; }

/* Deux rangees d'actions qui se suivent doivent respirer entre elles. */
.actions + .actions { margin-top: .85rem; }


/* .actions est un conteneur flex : il n'hérite pas du text-align du parent.
   Dans le hero, centré, ses boutons se retrouvaient alignés à gauche. */
#accueil .actions,
.hero .actions,
.texte-centre .actions { justify-content: center; }

/* =========================================================================
   L'attribut hidden doit primer sur tout display d'auteur.
   Sans cette règle, .btn { display: inline-flex } l'emporte sur le
   [hidden] { display: none } du navigateur : le bouton de partage natif,
   que app.js masque quand navigator.share n'existe pas (cas de la plupart
   des navigateurs de bureau), restait affiché et sans effet au clic.
   ========================================================================= */
[hidden] { display: none !important; }

/* Respiration au-dessus d'une rangée d'actions : elle suit généralement une
   carte ou un paragraphe et se retrouvait collée à lui (0 px mesuré). */
.actions { margin-top: 1.25rem; }
.actions + .actions { margin-top: .85rem; }

/* =========================================================================
   PIED DE PAGE : marque identique à l'en-tête + monogramme en filigrane
   Le filigrane est décoratif : il est posé en ::after (donc jamais lu par
   un lecteur d'écran), sous le contenu, et sans capture de clic.
   ========================================================================= */
.pied { position: relative; overflow: hidden; }
.pied > .container { position: relative; z-index: 1; }

.pied::after {
  content: "";
  position: absolute;
  right: -1.5rem;
  bottom: -2.5rem;
  width: min(300px, 40%);
  aspect-ratio: 1172 / 1011;
  background: url("../assets/logo-vh-monogramme-blanc.png") no-repeat right bottom / contain;
  opacity: .07;
  pointer-events: none;
  z-index: 0;
}

/* La marque du pied de page reprend celle de l'en-tête, avec un peu d'air
   au-dessous puisqu'elle ouvre le bloc. */
.pied .marque { margin-bottom: 1rem; }
.pied .marque__nom { color: var(--vh-blanc); }

@media (max-width: 560px) {
  .pied::after { width: 55%; opacity: .06; }
}
@media (prefers-reduced-motion: no-preference) {
  .pied::after { transition: opacity var(--vh-t) var(--vh-easing); }
}

/* =========================================================================
   RÉCAPITULATIF DES HORAIRES
   Une liste à puces rendait ce bloc plat. Chaque ligne devient une rangée :
   pastille de date, intitulé, puis badge de lieu. La pastille est purement
   décorative (aria-hidden) — la date complète reste écrite dans le texte,
   donc rien n'est perdu pour un lecteur d'écran.
   ========================================================================= */
.horaires {
  list-style: none;
  margin: 0 0 1.1rem;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: .5rem;
}

.horaires__item {
  display: flex;
  align-items: center;
  gap: .8rem;
  flex-wrap: wrap;
  padding: .6rem .7rem;
  border-radius: var(--vh-rayon);
  background: rgba(0, 108, 104, .045);
  transition: background-color var(--vh-t) var(--vh-easing),
              transform var(--vh-t) var(--vh-easing);
}
.horaires__item:hover {
  background: rgba(0, 108, 104, .085);
  transform: translateX(2px);
}

/* Pastille de date : le chiffre porte, le jour abrégé accompagne. */
.horaires__date {
  flex: none;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  width: 46px;
  height: 46px;
  border-radius: 12px;
  background: var(--vh-vert);
  color: var(--vh-blanc);
  line-height: 1;
}
.horaires__date b { font-size: 1.15rem; font-weight: 800; }
.horaires__date i {
  font-style: normal;
  font-size: .625rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .05em;
  opacity: .9;
  margin-top: .12rem;
}

.horaires__corps {
  display: flex;
  flex-direction: column;
  gap: .1rem;
  min-width: 0;
  flex: 1 1 11rem;
}
.horaires__titre { font-weight: 700; line-height: 1.25; }
.horaires__meta { font-size: .8125rem; color: var(--vh-encre-doux); }

.horaires .badge { flex: none; }

/* Le culte du dimanche est le seul rendez-vous sur place : il se distingue. */
.horaires__item--phare {
  background: rgba(177, 32, 41, .075);
}
.horaires__item--phare:hover { background: rgba(177, 32, 41, .09); }
.horaires__item--phare .horaires__date { background: var(--vh-rouge); }
.badge--temple {
  background: rgba(177, 32, 41, .08);
  border-color: rgba(177, 32, 41, .35);
  color: var(--vh-rouge-fonce);
}

@media (max-width: 420px) {
  .horaires .badge { margin-left: calc(46px + .8rem); }
}
@media (prefers-reduced-motion: reduce) {
  .horaires__item:hover { transform: none; }
}

/* =========================================================================
   CARTE « LE LIEU »
   Elle enchaînait des paragraphes plats. Elle reprend maintenant le
   vocabulaire visuel des horaires — pastille de date, lignes à icône,
   encadré — pour que les deux cartes de la section se répondent.
   ========================================================================= */
.lieu__entete { margin-bottom: 1rem; }


.lieu__intitule { display: flex; flex-direction: column; gap: .15rem; min-width: 0; }
.lieu__intitule .h3 { margin: 0; }

.lieu__nom {
  font-size: 1.0625rem;
  font-weight: 700;
  margin-bottom: .6rem;
}

/* Lignes d'information à icône : adresse, horaire d'accueil. */
.lieu__ligne {
  display: flex;
  align-items: flex-start;
  gap: .55rem;
  margin-bottom: .5rem;
}
.lieu__icone {
  flex: none;
  width: 1.15rem;
  height: 1.15rem;
  margin-top: .12rem;
  color: var(--vh-vert);
}

/* L'appel aux franciliens est la vraie invitation de cette carte. */
.lieu__idf { margin: 1.1rem 0 .25rem; }
.lieu__idf p { margin-bottom: .5rem; }
.lieu__idf > :last-child { margin-bottom: 0; }

/* =========================================================================
   NOTE ÉPINGLÉE — le trombone remplace le filet latéral
   Le border-left de .encadre faisait bloc administratif. Un trombone
   accroché au bord haut évoque la note glissée dans un cahier, et parle
   au sujet de la page : la rentrée scolaire. Purement décoratif, donc
   aria-hidden et sans incidence sur la lecture.
   ========================================================================= */
.lieu__idf {
  position: relative;
  border-left-width: 1px;              /* on annule le filet de .encadre */
  border-left-color: var(--vh-trait-or);
  padding-top: 1.5rem;                 /* la place du trombone */
  margin-top: 1.6rem;                  /* il dépasse au-dessus de la carte */
}

.lieu__pin {
  position: absolute;
  top: -1.15rem;
  right: 1.5rem;
  width: 1.75rem;
  height: 2.9rem;
  /* Inclinaison : une punaise plantée à la main n'est jamais d'aplomb.
     Le volume, lui, vient des dégradés du SVG (dôme, fût, aiguille). */
  transform: rotate(19deg);
  transform-origin: 50% 20%;
  filter: drop-shadow(3px 5px 5px rgba(16, 32, 31, .34));
  pointer-events: none;
}

@media (max-width: 560px) {
  .lieu__pin { right: 1rem; width: 1.5rem; height: 2.5rem; }
}

/* =========================================================================
   TIMELINE DU PROGRAMME — reliefs
   ========================================================================= */

/* La pastille du fil porte le quantième : un repère chiffré le long du
   parcours, cohérent avec les pastilles du récapitulatif des horaires.
   Elle est aria-hidden, la date complète restant écrite dans la carte. */
.timeline__point {
  font-size: .8125rem;
  font-weight: 800;
  color: var(--vh-blanc);
  letter-spacing: -.01em;
}

/* Badge de lieu, posé juste après le titre de l'étape. */
.timeline__badge { align-self: flex-start; margin-top: .15rem; }

/* Guillemet ouvrant décoratif, à la place du filet latéral. */
.timeline__verset::before {
  content: "“";
  position: absolute;
  left: .1rem;
  top: -.35rem;
  font-family: Georgia, "Times New Roman", serif;
  font-size: 2.9rem;
  line-height: 1;
  color: var(--vh-or);
  opacity: .55;
}
.timeline__verset cite {
  display: block;
  margin-top: .3rem;
  font-style: normal;
  font-size: .8125rem;
  font-weight: 700;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--vh-vert);
}
.section--sombre .timeline__verset cite { color: var(--vh-or-clair); }

/* Le culte du dimanche est le seul rendez-vous sur place : il se distingue,
   comme dans le récapitulatif des horaires. */
.timeline__item:last-child .timeline__point { background: var(--vh-rouge); }
.timeline__item:last-child .timeline__carte { border-left-color: var(--vh-rouge); }

/* =========================================================================
   VIDÉO D'INVITATION DU PASTEUR
   Emplacement 16:9 réservé sous le hero. Rien n'est chargé avant le clic :
   c'est un bouton, pas un lecteur. Le ratio est posé en CSS pour qu'aucun
   saut de mise en page ne survienne à l'insertion de l'iframe.
   ========================================================================= */
.video {
  position: relative;
  aspect-ratio: 16 / 9;
  width: 100%;
  max-width: 46rem;
  margin: 1.5rem auto .9rem;
  border-radius: var(--vh-rayon-lg);
  overflow: hidden;
  background:
    radial-gradient(120% 120% at 30% 20%, rgba(207, 174, 31, .22), transparent 60%),
    linear-gradient(150deg, var(--vh-vert) 0%, var(--vh-vert-fonce) 100%);
  box-shadow: var(--vh-ombre-carte);
}
.video iframe { width: 100%; height: 100%; border: 0; display: block; }

.video__lecture {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: .85rem;
  width: 100%;
  border: 0;
  background: transparent;
  color: var(--vh-blanc);
  font-family: inherit;
  font-size: 1rem;
  font-weight: 700;
  cursor: pointer;
  transition: background-color var(--vh-t) var(--vh-easing);
}
.video__lecture:hover { background: rgba(0, 0, 0, .12); }
.video__lecture:disabled { cursor: not-allowed; opacity: .75; }

.video__icone {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 4.5rem;
  height: 4.5rem;
  border-radius: 50%;
  background: var(--vh-rouge);
  box-shadow: 0 8px 24px rgba(0, 0, 0, .3);
  transition: transform var(--vh-t) var(--vh-easing),
              background-color var(--vh-t) var(--vh-easing);
}
.video__icone svg { width: 1.9rem; height: 1.9rem; margin-left: .18rem; }
.video__lecture:hover .video__icone { transform: scale(1.07); background: #C8262F; }
.video__lecture:disabled .video__icone { background: rgba(255, 255, 255, .22); }

/* Tant que CONFIG.videoPasteur est vide : pas de faux lecteur, un ton sobre. */
.video.est-vide { background: linear-gradient(150deg, #2C4B48 0%, #1B302E 100%); }

@media (prefers-reduced-motion: reduce) {
  .video__lecture:hover .video__icone { transform: none; }
}

/* =========================================================================
   INFOS PRATIQUES — hauteur des cartes
   Par défaut la grille étire ses cartes à la hauteur de la plus haute :
   celle des horaires (541 px de contenu) était tirée à 924 px, laissant
   310 px de vide sous son dernier paragraphe. Chaque carte garde désormais
   sa hauteur propre.
   ========================================================================= */
#infos .grid { align-items: start; }

/* =========================================================================
   PARAGRAPHES COLLÉS À UN BLOC
   Le socle remet les marges des <p> à zéro et confie l'espacement aux
   classes. Un paragraphe nu posé juste après un bloc se retrouvait donc
   collé à lui : 0 px sous le compte à rebours et sous le bandeau des
   plateformes. Balayage de la page : ces deux cas étaient les seuls.
   ========================================================================= */
[data-countdown] + p,
.plateformes + p { margin-top: 1rem; }

/* Le hero porte une photographie de fond : son contenu doit rester au-dessus
   des voiles décoratifs du socle, et l'image ne doit pas déborder. */
#accueil { position: relative; overflow: hidden; }
#accueil > .container { position: relative; z-index: 2; }

/* =========================================================================
   BLOC DU THÈME — « ON TE TROUVERA DIX FOIS SUPÉRIEUR »
   -------------------------------------------------------------------------
   C'est la promesse qui donne son sens au programme, et elle passait en
   corps de sous-titre, coincée entre le titre et le chapô. Elle devient un
   bloc à part entière :
     • la phrase calligraphiée agrandie d'environ 25 % ;
     • « dix fois » — la mesure de la promesse — porté à une taille très
       supérieure au reste de la phrase, en or métallique ;
     • la référence biblique en pied.
   Le relief est mis sur les MOTS, pas sur un symbole : pas de « ×10 », la
   phrase du thème reste lisible telle qu'elle est écrite en Daniel 1:20.
   L'or comme couleur de texte est ici sur fond vert profond — le seul
   contexte où le CONTRAT §2 l'autorise.
   ========================================================================= */
.theme {
  display: grid;
  justify-items: center;
  gap: .1rem;
  margin-block: clamp(.75rem, 2.5vw, 1.5rem);
}
.theme > * { margin: 0; }
.theme .pastille-theme { margin-bottom: .5rem; }

/* La phrase du thème : environ un quart plus grande que l'ancienne .h2. */
.theme__phrase {
  font-size: clamp(1.75rem, 1.05rem + 3.2vw, 3.25rem);
  line-height: 1.18;
  max-width: 24ch;
}

/* « dix fois » : la mesure de la promesse.
   Même écriture calligraphiée que le reste de la phrase — c'est un accent
   d'échelle, pas un changement de voix — mais une taille très supérieure,
   un or métallique et un halo qui la décollent du dégradé du hero.
   `line-height` court : sans lui, les deux mots écarteraient les lignes
   voisines de la phrase. */
.theme__dix {
  display: inline-block;
  font-size: 1.6em;
  line-height: .82;
  white-space: nowrap;   /* « dix fois » ne se coupe jamais en deux lignes */
  color: var(--vh-or-clair);
  filter: drop-shadow(0 6px 20px rgba(207, 174, 31, .35));
}
/* Dégradé métallique sur les deux mots. Réservé aux navigateurs qui savent
   découper un fond sur du texte : ailleurs, l'or plein de `color` suffit. */
@supports ((-webkit-background-clip: text) or (background-clip: text)) {
  .theme__dix {
    background: linear-gradient(165deg,
      #FFF4BE 0%, var(--vh-or-clair) 36%, var(--vh-or) 64%, #C9A413 100%);
    -webkit-background-clip: text;
            background-clip: text;
    -webkit-text-fill-color: transparent;
  }
}
/* Sur fond clair, l'or ne peut pas porter le texte (CONTRAT §2) : les deux
   mots gardent alors la couleur du contexte, seule la taille les distingue. */
.section--sable .theme__dix,
.section--clair .theme__dix,
.bande-chiffres .theme__dix {
  color: inherit;
  filter: none;
  background: none;
  -webkit-text-fill-color: currentColor;
}

/* Référence du thème, juste sous la formule calligraphiée. */
.theme__ref {
  margin: .35rem 0 0;
  font-size: .8125rem;
  font-weight: 700;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--vh-or-clair);
}


/* =========================================================================
   PASSE DE RELIEF — ce qui donne du rythme à la page
   -------------------------------------------------------------------------
   Constat en relisant la page d'un bout à l'autre : le hero est riche
   (dégradé animé, rayons, bokeh, tour), puis TOUT ce qui suit retombe sur
   le même gabarit — sur-titre gris, titre noir, chapô, contenu, sur un
   aplat sable ou clair, neuf fois de suite. Rien n'accroche l'œil entre
   deux sections, et l'or de la charte n'apparaît quasiment plus une fois le
   hero passé.

   Quatre gestes, tous réutilisables, aucun nouveau composant lourd :
     1. le sur-titre devient une étiquette (pastille + point doré) ;
     2. un mot par titre peut être surligné à l'or ;
     3. les sections claires reçoivent une aura et un filet de séparation ;
     4. les boutons pleins gagnent un dégradé et un reflet au survol.

   Règle de contraste du CONTRAT §2 respectée partout : sur fond clair, l'or
   ne sert QUE de filet, de point ou de surlignage — jamais de couleur de
   texte.
   ========================================================================= */

/* --- 1. Sur-titre : de la ligne de texte à l'étiquette ------------------- */
.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: .55em;
  /* Dans une carte (flex en colonne), `align-items: stretch` étirait la
     pastille sur toute la largeur — 296 px pour le mot « Offrande ». Une
     largeur explicite désactive l'étirement dans TOUS les contextes
     (flex, grid, bloc) sans toucher au centrage du hero. */
  width: fit-content;
  max-width: 100%;
  margin-bottom: .95rem;
  padding: .34rem .9rem .34rem .72rem;
  border: 1px solid var(--vh-trait-or);
  border-radius: var(--vh-rayon-pill);
  background: rgba(0, 108, 104, .06);
  letter-spacing: .16em;
}
.eyebrow::before {
  content: "";
  flex: none;
  width: .4rem; height: .4rem;
  border-radius: 50%;
  background: var(--vh-or);
  box-shadow: 0 0 0 3px rgba(207, 174, 31, .22);
}
/* Sur fond sombre, l'étiquette se pose sur un voile blanc. */
.hero .eyebrow,
.section--sombre .eyebrow,
.carte--sombre .eyebrow,
.carte--action .eyebrow {
  background: rgba(255, 255, 255, .10);
  border-color: rgba(230, 201, 63, .45);
}
.hero .eyebrow::before,
.section--sombre .eyebrow::before,
.carte--sombre .eyebrow::before,
.carte--action .eyebrow::before {
  background: var(--vh-or-clair);
  box-shadow: 0 0 0 3px rgba(230, 201, 63, .22);
}

/* Variante sans pastille — placée APRÈS les surcharges de fond sombre, qui
   sont plus spécifiques qu'elle et repeindraient le voile blanc.
   Les pages secondaires ouvrent sur la signature de l'église
   (« Vases d'Honneur / Assemblée Conquête des Nations », une quarantaine de
   caractères) : en pastille, elle passait à deux lignes et prenait l'allure
   d'un bandeau. Elle garde donc la typographie du sur-titre, sans le cadre. */
.eyebrow--nu,
.hero .eyebrow--nu,
.section--sombre .eyebrow--nu,
.carte--sombre .eyebrow--nu,
.carte--action .eyebrow--nu {
  display: block;
  width: auto;
  padding: 0;
  border: 0;
  background: none;
}
.eyebrow--nu::before { content: none; }

/* --- 2. Mot-clé surligné à l'or -----------------------------------------
   Le dégradé est posé DERRIÈRE le texte (surlignage, pas couleur de texte) :
   la lettre reste encre foncée, le contraste ne bouge pas. */
.surligne {
  background-image: linear-gradient(180deg,
    transparent 56%,
    rgba(207, 174, 31, .42) 56%,
    rgba(207, 174, 31, .42) 93%,
    transparent 93%);
  background-repeat: no-repeat;
  padding-inline: .08em;
  -webkit-box-decoration-break: clone; /* le surlignage suit les retours à la ligne */
          box-decoration-break: clone;
}
.hero .surligne,
.section--sombre .surligne,
.carte--sombre .surligne,
.carte--action .surligne {
  background-image: linear-gradient(180deg,
    transparent 56%,
    rgba(230, 201, 63, .38) 56%,
    rgba(230, 201, 63, .38) 93%,
    transparent 93%);
}

/* --- 3. Sections claires : aura + filet de séparation --------------------
   Deux halos très faibles (vert en haut à gauche, or en bas à droite)
   suffisent à sortir les aplats de leur platitude ; un filet doré d'un
   pixel marque chaque changement de section. */
.section--sable,
.section--clair { isolation: isolate; }

.section--sable::before,
.section--clair::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background:
    radial-gradient(52% 42% at 6% -8%, rgba(0, 108, 104, .07), transparent 72%),
    radial-gradient(48% 40% at 104% 108%, rgba(207, 174, 31, .13), transparent 72%);
}
.section--sable > *,
.section--clair > * { position: relative; z-index: 1; }

.section--sable::after,
.section--clair::after {
  content: "";
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 1px;
  z-index: 1;
  background: var(--vh-degrade-or);
  opacity: .55;
  pointer-events: none;
}
/* Après une section sombre, le filet doublerait la bordure dorée : inutile. */
.section--sombre + .section--sable::after,
.section--sombre + .section--clair::after,
.bande-chiffres + .section--sable::after,
.bande-chiffres + .section--clair::after { content: none; }

/* --- 4. Boutons pleins : dégradé + reflet au survol ---------------------- */
/* `isolation` fait du bouton son propre contexte d'empilement : le reflet
   posé en z-index -1 passe alors AU-DESSUS du fond du bouton et EN DESSOUS
   de son libellé, sans avoir à envelopper le texte dans une balise. */
.btn:not(.btn--fantome) { overflow: hidden; isolation: isolate; }
.btn:not(.btn--fantome):not(.btn--blanc)::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: inherit;
  background: linear-gradient(100deg,
    transparent 38%,
    rgba(255, 255, 255, .28) 50%,
    transparent 62%);
  transform: translateX(-115%);
  transition: transform .6s var(--vh-easing);
  pointer-events: none;
}
.btn:not(.btn--fantome):not(.btn--blanc):hover::before { transform: translateX(115%); }

.btn--rouge {
  background-image: linear-gradient(140deg,
    #C8262F 0%, var(--vh-rouge) 46%, var(--vh-rouge-fonce) 100%);
}
.btn--rouge:hover {
  background-color: var(--vh-rouge-fonce);
  background-image: linear-gradient(140deg,
    var(--vh-rouge) 0%, var(--vh-rouge-fonce) 100%);
}
.btn--or {
  background-image: linear-gradient(140deg,
    #E6C93F 0%, var(--vh-or) 52%, #BC9C16 100%);
}
.btn--or:hover {
  background-color: var(--vh-or-clair);
  background-image: linear-gradient(140deg, #F0D65A 0%, var(--vh-or) 100%);
}

/* --- 5. Badge : un point avant le libellé -------------------------------- */
.badge::before {
  content: "";
  flex: none;
  width: .35rem; height: .35rem;
  border-radius: 50%;
  background: currentColor;
  opacity: .65;
}


/* =========================================================================
   BANDE DES CHIFFRES CLÉS
   -------------------------------------------------------------------------
   Juste après le hero sombre, une bande blanche nette : elle relance la
   lecture, résume l'engagement demandé (3 jours, 3 soirées, 1 culte,
   gratuit) et sert de respiration avant la vidéo d'invitation. Tous les
   chiffres sont repris tels quels du programme détaillé plus bas.
   ========================================================================= */
.bande-chiffres {
  padding-block: clamp(1.5rem, 4vw, 2.5rem);
  background: var(--vh-blanc);
  border-bottom: 1px solid var(--vh-trait);
}


.chiffres {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(1rem, 3vw, 1.5rem);
  margin: 0;
  padding: 0;
  list-style: none;
  text-align: center;
}
@media (min-width: 720px) {
  .chiffres { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

.chiffres__item {
  position: relative;
  margin: 0;
  padding-inline: .5rem;
}
/* Séparateurs internes : un filet vertical entre deux colonnes. */
.chiffres__item + .chiffres__item::before {
  content: "";
  position: absolute;
  left: 0; top: 12%; bottom: 12%;
  width: 1px;
  background: linear-gradient(180deg,
    transparent, var(--vh-trait-or) 30%, var(--vh-trait-or) 70%, transparent);
}
@media (max-width: 719px) {
  /* En deux colonnes, seul le filet du milieu a un sens. */
  .chiffres__item:nth-child(odd)::before { content: none; }
}

.chiffres__nombre {
  display: block;
  font-size: clamp(2.1rem, 1.5rem + 2.4vw, 3.1rem);
  font-weight: 800;
  line-height: 1;
  letter-spacing: -.03em;
  color: var(--vh-vert);
}
.chiffres__nombre sup {
  font-size: .45em;
  font-weight: 700;
  vertical-align: .55em;
  margin-left: .05em;
}
.chiffres__label {
  display: block;
  margin-top: .45rem;
  font-size: .8125rem;
  font-weight: 700;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--vh-encre-doux);
}
.chiffres__detail {
  display: block;
  margin-top: .15rem;
  font-size: .8125rem;
  font-weight: 400;
  letter-spacing: 0;
  text-transform: none;
  color: var(--vh-encre-doux);
  opacity: .85;
}


/* =========================================================================
   CITATION DU HERO
   -------------------------------------------------------------------------
   Le hero est centré, mais la citation héritait du filet vertical gauche des
   <blockquote> du socle : le trait doré se retrouvait plaqué au bord du
   conteneur, à plus de 250 px du texte qu'il était censé accompagner. On le
   remplace par un filet horizontal court, centré au-dessus de la citation.
   ========================================================================= */
#accueil blockquote,
.hero blockquote {
  position: relative;
  max-width: 46ch;
  margin-inline: auto;
  padding-left: 0;
  padding-top: 1.5rem;
  border-left: 0;
}
#accueil blockquote::before,
.hero blockquote::before {
  content: "";
  position: absolute;
  top: 0; left: 50%;
  width: 56px; height: 2px;
  margin-left: -28px;
  border-radius: 2px;
  background: var(--vh-degrade-or);
}


@media (prefers-reduced-motion: reduce) {
  /* Le reflet des boutons est purement décoratif : on le retire. */
  .btn::before { content: none !important; }
}

/* =========================================================================
   HERO — PHOTOGRAPHIE DE FOND
   L'image fournie par l'église est claire (ciel, visages) : sans voile, le
   texte blanc y serait illisible. Un voile NOIR est donc posé par-dessus.
   Il est plus dense EN HAUT, là où le ciel est le plus clair, et s'allège
   vers le bas pour que les visages restent visibles : à 84 % la bande
   basse ne conservait que 0,5 % de clarté moyenne, les visages y
   disparaissaient. À 56 % elle en garde 2,6 %, cinq fois plus, tout en
   laissant le texte blanc au-dessus du seuil. Le noir plutôt que le vert : il
   assombrit sans teinter, donc les couleurs de la photographie — médailles
   dorées, rubans tricolores — restent elles-mêmes. Le dégradé est
   déclaré AVANT l'image dans la même propriété : la première couche est
   celle du dessus.
   ========================================================================= */
/* Sélecteur aligné sur celui du socle (#accueil.section--sombre, spécificité
   1-1-0) : un simple #accueil (1-0-0) était écrasé et la photo n'apparaissait
   pas. L'animation vh-degrade, qui balade le fond de 220 %, est neutralisée :
   elle avait un sens pour un dégradé, aucun pour une photographie. */
/* =========================================================================
   LE PREMIER ÉCRAN — LA PHOTOGRAPHIE EN FOND, PLEIN CADRE
   -------------------------------------------------------------------------
   La photo occupe toute la section, le texte est posé dessus, centré.
   C'est le parti le plus simple, et c'est celui retenu.

   Ont été essayés et écartés : une bande photo en haut du hero (elle volait
   sa hauteur au contenu) ; la photo dans un cadre à droite (une vignette
   posée dans une boîte) ; un fond flouté surmonté du sujet net à droite
   (trop bricolé faute d'un vrai détourage).

   CE QUE COÛTE CE PARTI, mesuré : le ciel de la photographie contient des
   pixels blancs purs. Un texte clair posé dessus n'est lisible qu'à partir
   d'un voile assez dense, et c'est le plus petit texte qui commande. Les
   opacités ci-dessous sont le minimum relevé bloc par bloc, en projetant
   chaque boîte de texte sur les pixels réels de l'image — voir la section
   « THÈME » plus bas pour la référence du verset, qui est le cas limite.
   ========================================================================= */
#accueil.section--sombre {
  /* Opacités mesurées, ligne par ligne, en projetant chaque boîte de texte sur
     les pixels réels de la photographie :
       titre blanc ............... 0,495     guillemets ......... 0,63
       « 3 » doré ................ 0,665     « Daniel 1:20 » .... 0,60
       « dix fois » .............. 0,750  ← c'est lui qui commande
     La nuance la plus sombre du dégradé dont « dix fois » est peint (#CFAE1F)
     tombe sur un nuage blanc pur : c'est le cas limite de tout le hero.
     Le voile ne descend donc jamais sous 0,76. Toute retouche de ces valeurs
     impose de refaire la mesure. */
  background-image:
    linear-gradient(rgba(1, 49, 46, .80), rgba(1, 49, 46, .80)),
    url("../assets/hero.jpg");
  background-size: cover;
  /* 62 % et non 50 : le cadrage remonte les visages et les médailles dans
     la moitié basse, sous le bloc de textes plutôt que derrière lui. */
  background-position: center 62%;
  background-repeat: no-repeat;
  /* L'animation vh-degrade balade le fond de 220 % : elle a un sens pour un
     dégradé, aucun pour une photographie. */
  animation: none;
}

/* Version 800 px sur les petits écrans : 77 Ko au lieu de 227. */
@media (max-width: 820px) {
  #accueil.section--sombre {
    background-image:
      linear-gradient(rgba(1, 49, 46, .82), rgba(1, 49, 46, .82)),
      url("../assets/hero-mobile.jpg");
  }
}

/* « dix fois » est peint par un dégradé clippé sur le texte
   (background-clip: text) : le fond n'est peint QUE dans la boîte de
   padding, donc tout glyphe qui en déborde reste invisible.
   Mesuré : les glyphes de Kaushan Script occupent 92 px de haut pour une
   boîte de 68 px — la queue du « s » débordait de 24 px par le bas et
   n'était jamais colorée. Le padding agrandit la boîte peinte ; les marges
   négatives annulent le décalage qu'il provoquerait sur la mise en page. */
.theme__dix {
  padding: .18em .16em .34em .04em;
  margin: -.18em -.12em -.34em -.04em;
}

/* =========================================================================
   BANDEAU « COOKIES ET CONTENUS EXTÉRIEURS »
   -------------------------------------------------------------------------
   Construit par app.js et ajouté en fin de <body> : les quatre pages en
   héritent sans être modifiées. Barre fixe en bas de l'écran, sur le vert
   profond du site, filet doré en tête.

   Deux points de vigilance :
   • Les deux boutons ont exactement le même poids visuel (même taille, deux
     fonds pleins). Refuser doit être aussi facile qu'accepter, sinon le choix
     n'en est pas un.
   • La barre étant en position fixe, elle recouvrirait la fin du pied de page.
     app.js mesure sa hauteur réelle et la publie dans
     --vh-bandeau-consentement ; le <body> se réserve d'autant.
   ========================================================================= */

body { padding-bottom: var(--vh-bandeau-consentement, 0); }

.bandeau-consentement {
  --vh-texte: var(--vh-blanc);
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 130;              /* au-dessus de l'en-tête collant (90) */
  /* Même vert de nuit et même filet doré que la barre d'annonce en haut de
     page : les deux bandeaux système encadrent le site, le contenu vit
     entre eux. */
  background: var(--vh-vert-nuit);
  color: var(--vh-blanc);
  border-top: 1px solid rgba(207, 174, 31, .35);
  box-shadow: 0 -14px 38px rgba(0, 0, 0, .34);
  max-height: 82vh;
  overflow-y: auto;
}
.bandeau-consentement[hidden] { display: none; }

.bandeau-consentement__corps {
  display: flex;
  flex-wrap: wrap;
  gap: clamp(1rem, 3vw, 2rem);
  align-items: center;
  justify-content: space-between;
  padding-top: .95rem;
  padding-bottom: .95rem;
}

/* Le texte occupe la place restante ; c'est la colonne des boutons, à droite,
   qui borne sa largeur — d'où l'absence de max-width sur les paragraphes. */
.bandeau-consentement__texte { flex: 1 1 22rem; min-width: 0; }
.bandeau-consentement__texte p { margin: 0 0 .4rem; }
.bandeau-consentement__texte p:last-child { margin-bottom: 0; }
.bandeau-consentement__texte > p:not(.note):not(.bandeau-consentement__titre) {
  font-size: .875rem;
  line-height: 1.55;
}
.bandeau-consentement__texte strong { color: var(--vh-or-clair); }
.bandeau-consentement .note { color: #C9D6D4; font-size: .75rem; }

/* Repli « En savoir plus » : le détail complet est là, sans occuper la
   moitié d'un écran de téléphone tant qu'on ne le demande pas. */
.bandeau-consentement__details { margin-top: .35rem; }
.bandeau-consentement__details summary {
  display: inline-block;
  font-size: .75rem;
  font-weight: 600;
  color: var(--vh-or-clair);
  text-decoration: underline;
  cursor: pointer;
}
.bandeau-consentement__details summary:hover { color: var(--vh-blanc); }
.bandeau-consentement__details[open] summary { margin-bottom: .35rem; }

.bandeau-consentement__titre {
  font-size: 1rem;
  font-weight: 800;
  letter-spacing: -.01em;
  color: var(--vh-or-clair);
}
/* Le titre reçoit le focus quand le bandeau est rouvert depuis le pied de
   page : le contour doit rester visible, mais sans clignoter au clic. */
.bandeau-consentement__titre:focus { outline: none; }
.bandeau-consentement__titre:focus-visible {
  outline: 3px solid var(--vh-or-clair);
  outline-offset: 4px;
  border-radius: var(--vh-rayon-xs);
}

.bandeau-consentement__actions {
  display: flex;
  flex-wrap: wrap;
  gap: .6rem;
  align-items: center;
  flex: 0 0 auto;
}
.bandeau-consentement__actions .btn { flex: 0 0 auto; min-width: 8.5rem; }

.bandeau-consentement__lien {
  color: var(--vh-or-clair);
  font-weight: 600;
  text-decoration: underline;
  white-space: nowrap;
}
.bandeau-consentement__lien:hover { color: var(--vh-blanc); }
.bandeau-consentement :focus-visible { outline-color: var(--vh-or-clair); }

/* Petits écrans : le texte passe au-dessus, les deux boutons se partagent
   la largeur à parts égales. */
@media (max-width: 719px) {
  .bandeau-consentement__corps { padding-top: .85rem; padding-bottom: .85rem; }
  .bandeau-consentement__actions { width: 100%; }
  .bandeau-consentement__actions .btn { flex: 1 1 40%; min-width: 0; }
}

/* Arrivée en douceur, neutralisée plus bas si le mouvement est réduit. */
@media (prefers-reduced-motion: no-preference) {
  .bandeau-consentement { transform: translateY(100%); }
  .bandeau-consentement.est-visible {
    transform: translateY(0);
    transition: transform .32s var(--vh-easing, ease);
  }
}

/* -------------------------------------------------------------------------
   Bouton « lien » : rappel du pied de page et « Changer mon choix » posé
   dans un conteneur de contenu refusé. C'est un <button> (il agit sur la
   page, il ne navigue pas) qui doit se lire comme un lien.
   ------------------------------------------------------------------------- */
.lien-consentement {
  appearance: none;
  background: none;
  border: 0;
  padding: 0;
  font: inherit;
  font-weight: 600;
  color: inherit;
  text-decoration: underline;
  cursor: pointer;
}
.lien-consentement:hover { text-decoration: none; }

.pied__consentement {
  margin: .75rem 0 0;
  font-size: .8125rem;
}
.pied__consentement .lien-consentement { color: var(--vh-or-clair); }
.pied__consentement .lien-consentement:hover { color: var(--vh-blanc); }

/* Note posée à la place d'une carte ou d'une vidéo refusée. */
.consentement-refus {
  max-width: 42ch;
  color: var(--vh-encre-doux);
}
.consentement-refus .lien-consentement { color: var(--vh-vert); }
.section--sombre .consentement-refus .lien-consentement,
.carte--sombre .consentement-refus .lien-consentement { color: var(--vh-or-clair); }

@media (prefers-reduced-motion: reduce) {
  .bandeau-consentement { transform: none !important; transition: none !important; }
}

@media print {
  .bandeau-consentement,
  .pied__consentement { display: none !important; }
  body { padding-bottom: 0 !important; }
}

/* Kaushan Script ne possède pas les chevrons « » : le navigateur les rendait
   en doubles chevrons « << >> ». Les guillemets courbes sont donc sortis de
   la cursive et confiés à une police qui les dessine correctement. */
.theme__guillemet {
  font-family: Georgia, "Times New Roman", serif;
  font-style: normal;
  font-size: 1.15em;
  line-height: 0;
  vertical-align: -.14em;
  opacity: .85;
  margin: 0 .06em;
}

/* =========================================================================
   HERO — TENIR DANS LE PREMIER ÉCRAN
   Objectif : voir le compte à rebours ET les deux boutons sans faire
   défiler. Mesuré sur un écran de 752 px : avec le padding standard de
   96 px, les boutons tombaient 130 px sous la ligne de flottaison.
   Le padding suit donc la hauteur de la fenêtre plutôt qu'une valeur fixe.
   ========================================================================= */
#accueil.section--sombre {
  padding-block: clamp(1.5rem, 3.6vh, 3.5rem);
}
/* Écrans très bas (portables 13", fenêtres réduites) : on resserre encore
   les espaces internes du hero plutôt que de rogner les tailles de texte.
   (Le seuil était monté à 1000 px le temps d'un essai où une bande photo
   occupait le haut du hero ; les deux colonnes ne lui volant plus de
   hauteur, il revient à sa valeur d'origine.) */
@media (min-width: 900px) and (max-height: 820px) {
  #accueil .theme { margin-block: .35rem; }
  #accueil .actions { margin-top: .75rem; }
  /* On resserre les tailles plutôt que de retirer un élément du hero :
     mesuré, il manquait 57 px pour que les deux boutons passent au-dessus
     de la ligne de flottaison sur un écran de 752 px. */
  #accueil .h1 { font-size: clamp(2rem, 4.4vw, 3rem); }
  #accueil .theme__phrase { font-size: clamp(1.5rem, 3.2vw, 2.35rem); }
  #accueil .theme__dix { font-size: 1.45em; }
  #accueil .eyebrow { margin-bottom: .35rem; }
}

/* =========================================================================
   THÈME EN BLANC SUR LA PHOTOGRAPHIE
   L'or du thème se superposait aux médailles dorées de l'image : deux
   jaunes l'un sur l'autre, le texte s'y noyait. Il passe donc au vert
   menthe, qui garde la famille chromatique de la charte tout en se
   détachant de la photo — le vert #006C68 de la charte, lui, ne donne
   que 1,31:1 sur ce fond et serait illisible.
   Effet de bord bienvenu : sans background-clip, le glyphe n'est plus
   peint par un fond borné, donc la queue du « s » de « fois » ne peut
   plus être rognée — la cause racine disparaît.
   ========================================================================= */
/* Phrase en blanc, « dix fois » en or : la couleur dit ce que dit la
   phrase, la mesure est le cœur du thème. L'or reste possible parce qu'il
   ne porte plus que deux mots — c'était la phrase ENTIÈRE en doré qui se
   noyait dans les médailles de la photographie.
   Contrastes mesurés au pire pixel de chaque zone : blanc 8,21:1 sur la
   phrase, or clair 4,98:1 sur « dix fois » (l'or de charte #CFAE1F n'y
   donnerait que 3,79:1). */
#accueil .theme__phrase { color: var(--vh-blanc); }

#accueil .theme__dix {
  color: var(--vh-or-clair);
  background: none;
  -webkit-background-clip: border-box;
          background-clip: border-box;
  -webkit-text-fill-color: currentColor;
  /* Ombre portée sombre à la place du halo doré : elle décolle le texte
     des zones claires de la photographie. */
  filter: drop-shadow(0 3px 14px rgba(0, 0, 0, .55));
}

/* Les guillemets et la référence gardent l'or : petits, ils ponctuent sans
   entrer en concurrence avec les médailles. */
#accueil .theme__guillemet { color: var(--vh-or-clair); }

/* =========================================================================
   « Première soirée dans » : le badge clair de la section « L'invitation »
   Le hero utilisait la déclinaison sombre du sur-titre (texte doré, fond
   translucide). Sur la photographie, le badge clair ressort mieux et
   harmonise le hero avec le reste de la page. Fond opaque et non
   translucide : posé sur une image, un fond translucide laisse remonter
   les zones claires et fait varier le contraste du texte.
   ========================================================================= */
#accueil .eyebrow {
  background: var(--vh-sable);
  color: var(--vh-vert);
  border-color: var(--vh-or);
  box-shadow: 0 4px 14px rgba(0, 0, 0, .28);
}
#accueil .eyebrow::before { background: var(--vh-or); }

/* =========================================================================
   COMPTE À REBOURS VIVANT
   Un compteur qui ne change qu'un chiffre par seconde ne se voit pas
   vivre. Trois choses le rendent lisible comme un temps qui s'écoule :
   les chiffres saluent leur changement, la tuile des secondes bat une
   fois par seconde, et un filet doré souligne chaque tuile.
   Tout est neutralisé sous prefers-reduced-motion.
   ========================================================================= */

/* Chaque case de chiffre porte l'animation ; le conteneur reste stable. */
#accueil [data-cd] {
  display: inline-block;
  will-change: transform;
}

/* Le chiffre bascule brièvement quand il change. Discret sur les jours et
   les heures, qui changent rarement ; c'est surtout visible sur minutes
   et secondes, là où le temps se voit passer. */
@keyframes vh-cd-bascule {
  0%   { transform: translateY(-38%) scale(.92); opacity: .15; }
  55%  { transform: translateY(6%)   scale(1.04); opacity: 1; }
  100% { transform: translateY(0)    scale(1);    opacity: 1; }
}
#accueil [data-cd].vient-de-changer {
  animation: vh-cd-bascule .42s cubic-bezier(.22, 1, .36, 1);
}

/* La seconde bat : un pouls régulier qui dit que la page est en vie. */
@keyframes vh-cd-pouls {
  0%, 100% { box-shadow: 0 6px 18px rgba(0, 0, 0, .3); }
  50%      { box-shadow: 0 6px 22px rgba(230, 201, 63, .35); }
}
#accueil [data-cd="seconds"] { color: var(--vh-or-clair); }

/* Tuiles : filet doré supérieur, fond un peu plus dense, coin arrondi. */
#accueil [data-countdown] > div {
  position: relative;
  border-top: 2px solid var(--vh-or);
  box-shadow: 0 6px 18px rgba(0, 0, 0, .3);
  overflow: hidden;
}
#accueil [data-countdown] > div:last-child {
  animation: vh-cd-pouls 1s ease-in-out infinite;
}
/* Lueur qui traverse la tuile des secondes, très discrète. */
#accueil [data-countdown] > div:last-child::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(120deg, transparent 40%, rgba(230, 201, 63, .16) 50%, transparent 60%);
  transform: translateX(-100%);
  animation: vh-cd-lueur 3.2s ease-in-out infinite;
  pointer-events: none;
}
@keyframes vh-cd-lueur {
  0%, 70%  { transform: translateX(-100%); }
  100%     { transform: translateX(100%); }
}

@media (prefers-reduced-motion: reduce) {
  #accueil [data-cd].vient-de-changer,
  #accueil [data-countdown] > div:last-child,
  #accueil [data-countdown] > div:last-child::after { animation: none; }
}

/* Les titres des cartes « Pour qui ? » n'ont pas tous le même nombre de
   lignes : « Professionnels de l'éducation » en prend deux quand les autres
   n'en prennent qu'une, ce qui décalait le corps de texte d'une carte à
   l'autre. On réserve la hauteur de deux lignes pour toutes. */
@media (min-width: 700px) {
  #pour-qui .carte h3 { min-height: 2.5em; }
}

/* Le « 3 » du titre est posé sur la bande haute du hero, la plus claire de
   la photographie (ciel). Mesuré au pire pixel de cette zone : l'or de
   charte #CFAE1F n'y donne que 2,96:1, sous le seuil de 3:1 exigé pour du
   gros texte ; l'or clair atteint 3,89:1. */
#accueil .chiffre-cle {
  color: var(--vh-or-clair);
  text-shadow: 0 2px 12px rgba(0, 0, 0, .45);
}

/* « DANIEL 1:20 » fait 13 px : c'est du petit texte, soumis au seuil de
   4,5:1 et non aux 3:1 des gros caractères. En or clair il ne donnait que
   3,23:1 sur la bande médiane du hero — suffisant pour le thème qui le
   surmonte, insuffisant pour lui. Le blanc l'y porte à 5,30:1.
   L'accent doré reste porté par « dix fois » et les guillemets. */
#accueil .theme__ref {
  color: rgba(255, 255, 255, .92);
  text-shadow: 0 1px 8px rgba(0, 0, 0, .5);
}

/* =========================================================================
   CARTES D'ACTION — « Un pas de plus »
   C'est la section qui décide si quelqu'un franchit le pas : elle mérite
   d'être la plus engageante de la page.

   Défaut corrigé d'abord : la carte est un <a>, et `text-decoration`
   se propage à TOUS ses descendants sans qu'ils puissent l'annuler.
   Titres et paragraphes étaient donc soulignés, et le paragraphe héritait
   en plus de la couleur or des liens.
   ========================================================================= */
.carte--action {
  text-decoration: none;
  position: relative;
  overflow: hidden;
  isolation: isolate;
}
.carte--action h3,
.carte--action p,
.carte--action .btn { text-decoration: none; }
.carte--action p { color: rgba(255, 255, 255, .88); }
.carte--action h3 { color: var(--vh-blanc); }

/* Icône ronde en tête de carte. */
.action__icone {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 3.25rem;
  height: 3.25rem;
  margin-bottom: .9rem;
  border-radius: 50%;
  background: rgba(255, 255, 255, .14);
  border: 1px solid rgba(255, 255, 255, .22);
  color: var(--vh-or-clair);
  transition: transform var(--vh-t) var(--vh-easing),
              background-color var(--vh-t) var(--vh-easing);
}
.action__icone svg { width: 1.6rem; height: 1.6rem; }

/* Halo doré qui s'allume au survol, derrière le contenu. */
.carte--action::before {
  content: "";
  position: absolute;
  inset: -40% 55% 40% -40%;
  background: radial-gradient(circle, rgba(207, 174, 31, .38), transparent 68%);
  opacity: 0;
  z-index: -1;
  transition: opacity .45s var(--vh-easing), transform .45s var(--vh-easing);
}
.carte--action:hover::before,
.carte--action:focus-visible::before { opacity: 1; transform: translate(18%, 12%); }

.carte--action:hover .action__icone,
.carte--action:focus-visible .action__icone {
  transform: scale(1.08) rotate(-4deg);
  background: rgba(255, 255, 255, .22);
}

/* La flèche avance : elle dit qu'on va quelque part. */
.action__cta { gap: .55rem; }
.action__fleche {
  width: 1.05rem;
  height: 1.05rem;
  flex: none;
  transition: transform var(--vh-t) var(--vh-easing);
}
.carte--action:hover .action__fleche,
.carte--action:focus-visible .action__fleche { transform: translateX(5px); }

/* Le filet doré supérieur signale que la carte est cliquable en entier. */
.carte--action { border-top: 3px solid var(--vh-or); }

@media (prefers-reduced-motion: reduce) {
  .carte--action::before,
  .carte--action .action__icone,
  .carte--action .action__fleche { transition: none; }
  .carte--action:hover .action__icone { transform: none; }
  .carte--action:hover .action__fleche { transform: none; }
}

/* =========================================================================
   LE CULTE DU DIMANCHE PASSE DU ROUGE À L'OR
   Le rouge signale le DIRECT partout ailleurs sur la page : barre d'annonce
   en live, CTA principaux. L'employer pour le culte du dimanche — le seul
   rendez-vous SUR PLACE — disait exactement le contraire de ce qu'il est.
   L'or le distingue sans rien promettre de faux.

   Contraintes de contraste mesurées, l'or ne pardonnant pas :
   - sur une pastille or pleine, le texte doit être en encre (7,79:1) et
     surtout pas en blanc (2,16:1) ;
   - dans le badge, l'or comme texte donnerait 1,94:1 : c'est un brun doré
     qui le porte (6,58:1).
   ========================================================================= */

/* Récapitulatif des horaires */
.horaires__item--phare {
  background: rgba(207, 174, 31, .10);
}
.horaires__item--phare:hover { background: rgba(207, 174, 31, .17); }
.horaires__item--phare .horaires__date {
  background: var(--vh-or);
  color: var(--vh-encre);
}
.badge--temple {
  background: #FBF3D6;
  border-color: rgba(207, 174, 31, .55);
  color: #6B5310;
}

/* Timeline du programme */
.timeline__item:last-child .timeline__point {
  background: var(--vh-or);
  color: var(--vh-encre);
}
.timeline__item:last-child .timeline__carte {
  border-left-color: var(--vh-or);
}

/* Section « Inviter » : une seule rangée d'actions. Le bouton de partage
   natif n'existe que si le téléphone le propose ; quand il est masqué, sa
   rangée dédiée laissait 20 px de marge morte sur ordinateur. Réunis, les
   boutons s'alignent quel que soit le nombre réellement affiché. */
#inviter .actions {
  align-items: center;
  row-gap: .75rem;
}

/* L'icône suit la même progression que la tuile qui la contient. */
.plateforme svg {
  width: clamp(1.7rem, 1.35rem + .9vw, 2.4rem);
  height: clamp(1.7rem, 1.35rem + .9vw, 2.4rem);
}


/* =========================================================================
   HERO — LE STYLE DE L'AFFICHE (L'ARDOISE DE CLASSE, MAQUETTE « hero 5 »)
   -------------------------------------------------------------------------
   La maquette du commanditaire (_files/hero 5.png) tient en cinq gestes,
   et ce bloc les transpose un à un :

     1. le fond n'est pas un dégradé de marque, c'est un TABLEAU DE CLASSE :
        un carrousel de trois œuvres d'une seule pièce chacune (ardoise à
        gauche, photographie fondue à droite, assets/hero-diapo-*.jpg —
        enseignants, famille, étudiants), à TOUTES les largeurs — seul le
        cadrage change : bord gauche (ardoise surtout) sous 1240 px, bord
        droit (scène complète) au-delà ;
     2. les personnages de la photographie sont en NOIR ET BLANC (détourés
        dans le fichier même), le décor reste en couleur ;
     3. le titre est écrit À LA CRAIE — Fredericka the Great, qui porte sa
        propre texture de trait — sur deux lignes ;
     4. les deux lignes suivantes passent AU MARQUEUR, jaune puis rouge,
        et le DRAPEAU tricolore souligne le tout ;
     5. le thème se pose sur un POST-IT jaune punaisé, coin corné.

   CONTRASTES — le seuil est celui du CONTRAT §2. Mesures sur l'ardoise
   (#0B372F, la nuance médiane du fond) :
     craie #F4F7F2 .......... 12,8:1   (gros texte, seuil 3:1)
     marqueur or #F7E14A ..... 9,6:1   (gros texte)
     marqueur rouge #FF5A57 ... 3,5:1  (gros texte uniquement — c'est
        pourquoi cette teinte ne sert QUE sur la ligne la plus grande du
        titre, jamais sur du petit texte ; le rouge de charte #B12029 n'y
        donnerait que 1,6:1 et serait illisible)
   Sur le post-it (#FFE22E) :
     encre #10201F .......... 13,6:1
     rouge de charte #B12029 . 5,4:1   (le rouge de charte redevient
        possible ici : le fond est clair, et §2 n'interdit que l'OR)
   ========================================================================= */

.hero-affiche {
  --craie:          #F4F7F2;   /* blanc de craie : jamais du blanc pur */
  --ardoise:        #0B372F;
  --marqueur-or:    #F7E14A;
  --marqueur-rouge: #FF5A57;
  --note-haut:      #FFEE58;
  --note-bas:       #F5CE0B;
}

/* --- 1. L'ardoise : UN SEUL fond, l'œuvre elle-même -------------------- */
/* Ce sélecteur porte l'ID + deux classes : il l'emporte sur la règle
   « photographie plein cadre » plus haut, qui garde la main sur les pages
   n'ayant pas la classe `hero-affiche`.
   Chaque œuvre du carrousel contient TOUT le décor : ardoise texturée sur
   sa moitié gauche, photographie fondue à droite. Un seul fichier par
   œuvre sert donc tous les écrans — seul le CADRAGE change : ici, calé
   sur le bord gauche, on voit surtout l'ardoise ; au-delà de 1240 px, le
   cadrage passe à droite et la scène entière entre dans le champ (voir la
   requête média plus bas, qui explique aussi pourquoi 1240). La première
   œuvre est posée ici en fond statique : image de chargement et repli
   quand le carrousel est neutralisé ; la couleur de fond reste en filet
   de sécurité. */
#accueil.section--sombre.hero-affiche {
  background-color: var(--ardoise);
  background-image:
    /* Vignette : les bords du tableau prennent la lumière de biais. */
    radial-gradient(135% 105% at 50% 45%, transparent 52%, rgba(0, 0, 0, .34) 100%),
    url("../assets/hero-diapo-1.jpg");
  background-size: cover, cover;
  /* Calé en BAS : quand un écran très large force un recadrage vertical,
     c'est le haut d'ardoise vide qui sort du cadre — jamais les mains ni
     le bas des sujets. */
  background-position: center, left bottom;
  background-repeat: no-repeat;
  animation: none;
}

/* Les RAYONS de lumière du socle sont conservés (flou, animation, masque
   qui les éteint vers le bas viennent de la règle de base) mais REDIRIGÉS :
   leur origine passe du centre-haut au-dessus des PERSONNAGES (~72 % de la
   largeur — soit 66 % de ce pseudo-élément, qui déborde de 20 % de chaque
   côté), et les deux faisceaux tombent sur eux, plus jamais sur le texte.
   Ils remontent aussi d'un cran (z-index 1) pour passer au-dessus des
   calques du carrousel, au même niveau que le grain.
   Le ::after, lui, ne garde que le grain de craie ; le BOKEH est reporté
   sur .hero-diapos::after, les deux pseudo-éléments de la section étant
   pris. Aucun voile : l'ardoise des œuvres est assez sombre (~#0D2B24)
   pour porter tous les textes clairs du hero. */
#accueil.hero-affiche::before {
  z-index: 1;
  background:
    conic-gradient(from 158deg at 66% -4%,
      transparent 0deg,
      rgba(255, 255, 255, .10) 9deg,
      transparent 17deg,
      transparent 30deg,
      rgba(230, 201, 63, .13) 38deg,
      transparent 47deg),
    radial-gradient(48% 38% at 70% 5%, rgba(230, 201, 63, .15), transparent 70%);
  transform-origin: 66% 0%;
}
#accueil.hero-affiche::after {
  inset: 0;
  width: auto;
  height: auto;
  border-radius: 0;
  background-color: transparent;
  background-image:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='200' height='200'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='200' height='200' filter='url(%23g)' opacity='.16'/%3E%3C/svg%3E");
  background-size: 200px 200px;
  background-repeat: repeat;
  box-shadow: none;
  filter: none;
  opacity: 1;
  transform: none;
  animation: none;
}

/* (Le bandeau « L'Église de France en prière » et son drapeau ont été
   retirés à la demande du commanditaire : le drapeau vit désormais sous
   le titre, en trait séparateur — voir `.titre-affiche::after`.) */

/* --- 3. Le titre : la craie puis le marqueur -------------------------- */
.titre-affiche {
  display: grid;
  justify-items: center;
  gap: .05em;
  margin-bottom: clamp(.7rem, 1.8vw, 1.1rem);
  text-transform: uppercase;
  line-height: .95;
  letter-spacing: 0;
}

/* La craie : Fredericka the Great, au choix du commanditaire — son trait
   hachuré porte sa propre texture, aucun grain rapporté. Deux lignes
   explicites, comme sur la maquette : « 3 JOURS DE » très grande, « JEÛNE
   ET DE PRIÈRE » un cran dessous. Les tailles des lignes sont en `em` :
   tout réglage de la taille du parent (paliers d'écrans bas, très grands
   écrans) met les deux lignes à l'échelle d'un seul geste.
   ATTENTION échelle : Fredericka est LARGE — « JEÛNE ET DE PRIÈRE » fait
   ~11,3 px de large par px de corps (sonde navigateur). La colonne de
   titre faisant 33rem (528 px), le plafond du corps est à 2,85rem ;
   toute hausse impose de re-sonder la ligne la plus longue. */
.titre-affiche__craie {
  display: grid;
  justify-items: center;
  gap: .08em;
  font-family: "Fredericka the Great", "Poppins", system-ui, "Segoe UI", sans-serif;
  font-weight: 400;
  /* Plancher sondé à 375 px : à 1.8rem, « JEÛNE ET DE PRIÈRE » manquait
     la largeur de 6 px et cassait en deux. */
  font-size: clamp(1.55rem, .7rem + 4.3vw, 2.85rem);
  line-height: 1.02;
  letter-spacing: .01em;
  color: var(--craie);
  text-shadow: 0 6px 26px rgba(0, 0, 0, .5);
}
.titre-affiche__l1 { font-size: 1.5em; line-height: 1; }
.titre-affiche__l2 { font-size: 1em; }
/* Le « 3 » appartient au même trait de craie que « JOURS DE » : même
   taille, même ligne — c'est l'échelle de la ligne entière qui porte
   l'accent, comme sur la maquette. */
#accueil .titre-affiche .chiffre-cle {
  color: var(--craie);
  font-size: 1em;
  line-height: inherit;
  letter-spacing: inherit;
  text-shadow: none;
}

.titre-affiche__marqueur {
  position: relative;
  display: inline-block;
  /* Permanent Marker : le tracé au feutre de l'affiche, bords irréguliers
     compris. Police à graisse unique — demander 800 déclencherait un gras
     synthétique qui empâte le tracé. Elle penche déjà d'elle-même : le
     `skewX` reste léger, il ne fait qu'appuyer le geste. */
  font-family: "Permanent Marker", "Poppins", system-ui, sans-serif;
  font-weight: 400;
  line-height: 1.08;
  transform: skewX(-4deg) rotate(-1.1deg);
  text-shadow: 0 4px 16px rgba(0, 0, 0, .5);
}
.titre-affiche__marqueur--or {
  font-size: clamp(1.25rem, .75rem + 2.3vw, 2rem);
  letter-spacing: .01em;
  color: var(--marqueur-or);
}
.titre-affiche__marqueur--rouge {
  margin-top: .1em;
  font-size: clamp(1.6rem, .82rem + 3.2vw, 2.7rem);
  letter-spacing: .005em;
  color: var(--marqueur-rouge);
  transform: skewX(-4deg) rotate(-1.7deg);
}
/* Les trois petits traits d'éclat de part et d'autre de la ligne rouge.
   Ils viennent de l'AFFICHE OFFICIELLE (la maquette « hero 5 » n'en avait
   pas, ils avaient été retirés à ce titre puis rétablis par le
   commanditaire) : c'est le geste au marqueur qui fait « briller » le mot.
   Un seul fichier SVG, retourné pour le côté droit. Décor pur :
   `content: ""`, rien à annoncer aux lecteurs d'écran.
   Dimensionnés en `em` : ils suivent la taille du titre à tous les
   paliers, sans qu'aucune requête média ait à les reprendre. Et comme ce
   sont des enfants du marqueur, ils héritent de son `skewX`/`rotate` :
   les traits penchent avec la ligne. */
/* PALIER 1280 px — il n'est pas décoratif, il est mesuré. Notre ligne rouge
   dit « l'année scolaire à Dieu » là où l'affiche s'arrête à « L'ANNÉE
   SCOLAIRE » : deux mots de plus, et `white-space: nowrap` (posé plus bas
   pour l'empêcher de casser en deux) la fait remplir toute la colonne.
   Position du début du trait gauche, sondée sur la page :
     1000 px → -26 px   (hors écran)
     1200 px →  -4 px   (hors écran)
     1280 px →  36 px   (tient)
     1512 px →  86 px   (à l'aise)
   En dessous de 1280 px les traits seraient rognés par le bord de la
   fenêtre : mieux vaut ne pas les afficher que les afficher coupés. Pour
   les avoir à TOUTES les largeurs, il faudrait raccourcir la ligne rouge
   à « l'année scolaire » comme sur l'affiche. */
@media (min-width: 1280px) {
  .titre-affiche__marqueur--rouge::before,
  .titre-affiche__marqueur--rouge::after {
    content: "";
    position: absolute;
    top: 50%;
    width: .5em;
    height: .74em;
    background: url("../assets/traits-eclat.svg") center / contain no-repeat;
    pointer-events: none;
  }
  .titre-affiche__marqueur--rouge::before {
    right: 100%;
    margin-right: .16em;
    transform: translateY(-50%);
  }
  .titre-affiche__marqueur--rouge::after {
    left: 100%;
    margin-left: .16em;
    transform: translateY(-50%) scaleX(-1);
  }
}

/* Le trait sous le titre : le DRAPEAU tricolore, à la place du trait de
   craie — c'est lui qui porte désormais « l'Église de France » depuis que
   le bandeau du haut a été retiré. */
.titre-affiche::after {
  content: "";
  display: block;
  width: min(56%, 22rem);
  height: 3px;
  margin: clamp(.5rem, 1.3vw, .75rem) auto 0;
  border-radius: 1.5px;
  background: linear-gradient(90deg,
    #1B3FA0 0 33.34%, #FFFFFF 33.34% 66.67%, #C8102E 66.67% 100%);
  box-shadow: 0 2px 6px rgba(0, 0, 0, .4);
}

/* --- 5. Le thème sur un post-it punaisé ------------------------------- */
.theme--note {
  position: relative;
  width: min(100%, 33rem);
  margin-inline: auto;
  margin-block: clamp(.75rem, 1.9vw, 1.1rem);
  padding: clamp(1.25rem, 3.2vw, 1.5rem) clamp(1.15rem, 3.5vw, 1.9rem)
           clamp(.8rem, 2.1vw, 1.05rem);
  gap: .2rem;
  /* La feuille est un DESSIN (assets/postit-manuscrit.svg) et non plus un
     empilement de dégradés : bords gondolés et coin corné sont tracés à la
     main, dans la même famille que les griffonnages des sections. Elle
     s'étire à la boîte (`100% 100%`), le SVG étant fait pour ça.
     `clip-path` et `box-shadow` n'ont plus lieu d'être — la découpe du coin
     appartient au dessin — mais le drop-shadow reste : appliqué à
     l'élément, il épouse exactement la silhouette du tracé. */
  background: url("../assets/postit-manuscrit.svg") center / 100% 100% no-repeat;
  color: var(--vh-encre);
  transform: rotate(-1.6deg);
  filter: drop-shadow(0 14px 22px rgba(0, 0, 0, .34));
}
/* La punaise, dessinée elle aussi — fichier séparé pour qu'elle garde ses
   proportions pendant que la feuille s'étire avec le texte. */
.theme--note::before {
  content: "";
  position: absolute;
  z-index: 2;
  top: -20px;
  left: 50%;
  width: 30px;
  height: 40px;
  margin-left: -15px;
  background: url("../assets/punaise-manuscrite.svg") center / contain no-repeat;
}

/* Sur le post-it, l'or est interdit (fond clair, CONTRAT §2) et le blanc
   de la photographie n'a plus lieu d'être : tout repasse à l'encre, avec
   le rouge de charte pour la mesure et la référence — c'est exactement le
   partage de l'affiche. */
#accueil .theme--note .pastille-theme {
  padding: 0;
  background: none;
  box-shadow: none;
  margin-bottom: .45rem;
  /* « THÈME » en rouge, comme sur la maquette. 12 px : petit texte, seuil
     4,5:1 — le rouge de charte donne 5,4:1 sur le jaune du post-it. */
  color: var(--vh-rouge);
  font-size: .75rem;
  letter-spacing: .24em;
  text-indent: .24em;
}
#accueil .theme--note .theme__phrase {
  max-width: 19ch;
  font-size: clamp(1.25rem, .88rem + 1.75vw, 1.8rem);
  line-height: 1.16;
  /* Le vert profond de la maquette plutôt que l'encre : ~10:1 sur le
     jaune, et la note reste dans la famille chromatique de l'ardoise. */
  color: var(--vh-vert-fonce);
  text-shadow: none;
}
#accueil .theme--note .theme__dix {
  font-size: 1.4em;
  color: var(--vh-rouge);
  background: none;
  -webkit-text-fill-color: currentColor;
  filter: none;
}
/* Sur l'affiche, les guillemets sont du même trait plein que la phrase :
   l'`opacity` héritée du hero sombre les aurait fait tomber à 2,0:1. */
#accueil .theme--note .theme__guillemet { color: var(--vh-vert-fonce); opacity: 1; }
/* « Daniel 1:20 » en vert profond : sur la maquette, le rouge est réservé
   à « THÈME » et à la mesure « dix fois ». */
#accueil .theme--note .theme__ref {
  margin-top: .5rem;
  color: var(--vh-vert-fonce);
  text-shadow: none;
}

/* --- Écran large : le post-it quitte la colonne, épinglé à droite ------ */
/* L'affiche empile tout — une landing n'y est pas tenue. Au-delà de 980 px,
   le bloc qui fait agir (titre, compte à rebours, boutons) s'aligne à
   gauche, et le post-it est épinglé à droite comme une note au coin du
   tableau. En dessous, l'empilement centré de l'affiche reste le bon parti. */
@media (min-width: 980px) {
  /* Même en cadrage gauche, la photo entre partiellement dans le champ
     dès que l'écran s'élargit. Ce plafond de hauteur (66 % de la largeur)
     règle l'échelle de l'image pour que le visage de la mère soit soit
     ENTIER à l'écran (et à droite du post-it), soit hors champ — jamais
     tranché par le bord. Vérifié par calcul de 980 à 1239 px. */
  #accueil.section--sombre.hero-affiche {
    min-height: min(calc(100svh - 7rem), 66vw, 860px);
  }
  .hero-affiche .hero-texte {
    display: grid;
    /* Trois colonnes : le bloc de texte, le post-it, et une colonne VIDE
       qui réserve le flanc droit à la photographie de l'œuvre. Mesuré sur
       la maquette : la note fait ~16 % de la largeur (270 px sur 1672) et
       s'arrête aux 2/3 de l'image — le visage de la mère commence à ~72 %.
       La note est donc bornée à 16,5rem et le vide de droite encaisse tout
       le reste ; sans cette 3e colonne, la note collait au bord droit du
       conteneur et couvrait le visage. */
    grid-template-columns: minmax(0, 33rem) minmax(14rem, 15.5rem) 1fr;
    column-gap: clamp(2rem, 3vw, 3rem);
    align-items: center;
    /* Le bloc de texte est CENTRÉ dans sa colonne (comparé à l'écran avec
       le fer à gauche) : la colonne étant étroite, l'axe symétrique —
       titre, drapeau, badge, compteur, boutons sur un même centre —
       retrouve l'esprit de l'affiche d'origine. */
    justify-items: center;
    text-align: center;
  }
  .hero-affiche .hero-texte > * { grid-column: 1; }
  /* Cinq éléments dans la colonne de gauche : le post-it, placé deuxième
     dans le document, occupe leurs cinq rangées dans la colonne du milieu —
     aligné en HAUT, à hauteur du titre, compact comme sur la maquette. */
  .hero-affiche .hero-texte .theme--note {
    grid-column: 2;
    grid-row: 1 / span 5;
    align-self: start;
    justify-self: stretch;
    width: 100%;
    max-width: none;
    margin-block: 0;
    padding: 1.5rem 1.1rem 1rem;
    /* Penché dans l'autre sens qu'en colonne : la note est punaisée de
       biais, elle ne fait plus partie de l'empilement. */
    transform: rotate(2.2deg);
  }
  .hero-affiche .hero-texte .titre-affiche {
    margin-bottom: clamp(1.1rem, 2.4vh, 1.6rem);
  }
  /* La ligne rouge est plus longue que la colonne du titre : centrée, elle
     DÉBORDE symétriquement sous le post-it (aligné en haut, il ne descend
     jamais jusqu'à elle), comme le marqueur déborde du bloc sur la
     maquette. Sans nowrap, elle casserait en deux dans la colonne de 33rem. */
  .hero-affiche .hero-texte .titre-affiche__marqueur--rouge { white-space: nowrap; }
  .hero-affiche .hero-texte .titre-affiche::after { width: min(100%, 25rem); }
  /* Rythme vertical de la colonne de gauche, sur un pas régulier : badge,
     compteur, date et boutons forment un seul groupe — celui qui fait
     agir — et le titre s'en détache d'un pas plus grand. */
  .hero-affiche .hero-texte .eyebrow { margin-bottom: .7rem; }
  #accueil.hero-affiche [data-countdown] + p { margin-top: .8rem; margin-bottom: 0; }
  #accueil.hero-affiche .actions { margin-top: 1.1rem; }

  /* Le texte du post-it suit sa largeur de maquette : compact. */
  #accueil .theme--note .theme__phrase {
    font-size: clamp(1.15rem, .9rem + .55vw, 1.4rem);
  }
  #accueil .theme--note .theme__ref { font-size: .8125rem; margin-top: .35rem; }
  #accueil .theme--note .pastille-theme { margin-bottom: .3rem; }
}

/* --- Très grands écrans : tout monte d'un cran ------------------------- */
/* Au-delà de 1440 px, les plafonds des clamp() sont atteints depuis
   longtemps : le hero flottait, petit, au centre d'une ardoise immense.
   Le conteneur s'élargit à 1280 px et chaque échelle monte d'environ 15 %.
   Les deux lignes de craie étant en `em` du parent, une seule taille les
   pilote : à 4rem, « 3 JOURS DE » fait ~99 px et « JEÛNE ET DE PRIÈRE »
   64 px — la colonne de gauche (720 px avec la note à 26rem) les tient. */
@media (min-width: 1440px) {
  #accueil.section--sombre.hero-affiche { min-height: min(100svh, 960px); }
  #accueil.hero-affiche > .container { max-width: 1280px; }
  .hero-affiche .hero-texte {
    /* La note passe de 16 à 18rem (grand écran seulement) : le vide de
       droite appartient toujours à la photo. La borne n'est pas un goût,
       elle est MESURÉE — voir le bloc de la note plus bas. */
    grid-template-columns: minmax(0, 38rem) minmax(17rem, 18rem) 1fr;
    column-gap: 4rem;
  }
  /* Fredericka à 3.25rem : « JEÛNE ET DE PRIÈRE » ≈ 588 px (sonde),
     tenu par la colonne de 38rem (608 px). */
  #accueil .titre-affiche__craie { font-size: 3.25rem; }
  #accueil .titre-affiche__marqueur--or { font-size: 2.3rem; }
  #accueil .titre-affiche__marqueur--rouge { font-size: 3rem; }
  .hero-affiche .hero-texte .titre-affiche { margin-bottom: 1.9rem; }
  .hero-affiche .hero-texte .titre-affiche::after { width: min(100%, 28rem); height: 4px; }
  .hero-affiche .hero-texte .eyebrow { margin-bottom: .9rem; }
  #accueil [data-countdown] { gap: 1rem; }
  #accueil [data-countdown] > * { min-width: 7.25rem; padding: .75rem .6rem .6rem; }
  #accueil [data-countdown] [data-cd] { font-size: 3.4rem; }
  #accueil.hero-affiche .actions { margin-top: 1.5rem; }
  /* LA NOTE AGRANDIE SUR GRAND ÉCRAN — et pourquoi elle ne peut pas l'être
     davantage. Le fond est le carrousel d'œuvres, sujets ancrés en bas à
     droite : le bord BAS de la note ne doit pas descendre sur les têtes.
     Marge mesurée (sonde canvas sur les fichiers d'œuvres) entre le bas de
     la note et le sujet le plus haut situé SOUS elle, à 1512 × 900 ; un
     négatif veut dire que la note mord sur le sujet :

       réglage            larg.  bas    œuvre 1   œuvre 4
       16rem / 1,55rem     262   274      -12       +12     (avant)
       18rem / 1,75rem     294   271      +47        -3
       18rem / 1,75rem     294   263      +55        +5     (RETENU)
       19rem / 1,80rem     310   271       .         -1     (trop large)

     Deux enseignements. 1) ÉLARGIR COÛTE : la note couvre alors des
     colonnes d'image où les sujets montent plus haut — c'est l'œuvre 4 qui
     décroche la première, d'où la borne à 18rem. 2) Le `margin-top` négatif
     est la clé : il remonte la note d'autant qu'elle a grandi, si bien que
     son bord bas MONTE (274 → 263) au lieu de descendre. Sans lui, tout le
     gain de taille irait sur les têtes.
     Résultat : +12 % de largeur, +13 % de texte, et le pire cas passe de
     -12 (la note mordait) à +5 (elle ne mord plus sur aucune œuvre). */
  .hero-affiche .hero-texte .theme--note {
    padding: 1.45rem 1.35rem .95rem;
    margin-top: -1rem;
  }
  /* `max-width` levé : bornée à 19ch, la phrase n'aurait pas profité de la
     colonne élargie et se serait cassée en une ligne de plus. */
  #accueil .theme--note .theme__phrase { font-size: 1.75rem; max-width: none; }
  #accueil .theme--note .theme__ref { font-size: .95rem; margin-top: .45rem; }
}

/* -------------------------------------------------------------------------
   ÉCRANS BAS — TENIR LE COMPTE À REBOURS ET LES DEUX BOUTONS AU-DESSUS DE
   LA LIGNE DE FLOTTAISON
   Le hero visait déjà cet objectif (voir « HERO — TENIR DANS LE PREMIER
   ÉCRAN » plus haut), mais ses règles ne portent plus : elles resserrent
   `.h1` et `.theme__phrase`, or le titre est devenu trois blocs empilés et
   la phrase du thème vit maintenant dans le post-it.

   Un seul palier ne suffisait plus. Mesuré, bas du dernier bouton par
   rapport à la ligne de flottaison (négatif = au-dessus) :
     écran 1280 × 752 — état antérieur −40 px | un palier +62 | deux +2
     écran 1280 × 860 — état antérieur +18 px | un palier +48 | deux +25
   Ces mesures valent pour l'EMPILEMENT, donc pour la bande 900 → 979 px de
   large : au-delà, le post-it passe à droite du bloc de texte (voir la mise
   en page d'écran large plus haut) et rend à la colonne les ~180 px de
   hauteur du post-it — les paliers n'y ont plus lieu d'être, ils sont donc
   bornés en largeur pour ne pas rogner l'échelle d'affiche du titre.
   ------------------------------------------------------------------------- */

/* En deux colonnes, un seul réglage suffit aux fenêtres basses. Réduire le
   padding de la section ne changeait RIEN : son min-height de 100svh la
   fait déborder sous la fenêtre (la barre d'annonce et l'en-tête, ~112 px,
   la poussent vers le bas) et le centrage flex fige la position du contenu.
   C'est donc le min-height qui rend ces 112 px. Mesuré à 1280 × 752 : les
   boutons passent de +5 px sous la ligne de flottaison à −27 au-dessus. */
@media (min-width: 980px) and (max-height: 800px) {
  #accueil.section--sombre.hero-affiche {
    min-height: min(calc(100svh - 7rem), 860px);
    padding-block: 1rem;
  }
}

/* Palier 1 — portables et fenêtres réduites, tant que tout est empilé. */
@media (min-width: 900px) and (max-width: 979px) and (max-height: 900px) {
  #accueil .titre-affiche { margin-bottom: .85rem; }
  #accueil .titre-affiche__craie           { font-size: clamp(1.95rem, 4.2vw, 3.25rem); }
  #accueil .titre-affiche__marqueur--or    { font-size: clamp(1.2rem, 2.5vw, 1.85rem); }
  #accueil .titre-affiche__marqueur--rouge { font-size: clamp(1.5rem, 3.2vw, 2.45rem); }
  #accueil .theme--note {
    margin-block: .85rem;
    padding-block: 1.25rem .9rem;
  }
  #accueil .theme--note .theme__phrase { font-size: clamp(1.2rem, 2.2vw, 1.65rem); }
}

/* Palier 2 — fenêtres vraiment basses. Le trait tricolore disparaît : c'est
   le seul élément du hero dont la suppression ne retire aucune information. */
@media (min-width: 900px) and (max-width: 979px) and (max-height: 800px) {
  #accueil.section--sombre.hero-affiche { padding-block: clamp(.9rem, 2.2vh, 2rem); }
  #accueil .titre-affiche { margin-bottom: .4rem; }
  #accueil .titre-affiche__craie           { font-size: clamp(1.8rem, 3vw, 2.15rem); }
  #accueil .titre-affiche__marqueur--or    { font-size: clamp(1.1rem, 1.8vw, 1.3rem); }
  #accueil .titre-affiche__marqueur--rouge { font-size: clamp(1.4rem, 2.3vw, 1.75rem); }
  #accueil .titre-affiche::after { display: none; }
  #accueil .theme--note {
    margin-block: .1rem;
    padding-block: .9rem .6rem;
  }
  #accueil .theme--note .theme__phrase { font-size: clamp(1.1rem, 1.9vw, 1.3rem); }
}

/* =========================================================================
   HERO — L'ŒUVRE « hero 5 » EN FOND, ET LES FINITIONS DE LA MAQUETTE
   -------------------------------------------------------------------------
   Le fond est déjà l'œuvre (voir « 1. L'ardoise » plus haut) : à partir de
   1240 px, seul le CADRAGE change — il passe du bord gauche (ardoise
   seule) au bord droit, et la scène photographiée entre dans le champ.
   POURQUOI 1240 : sous cette largeur, le calcul (note bornée à 15,5rem,
   colonne titre à 33rem) fait passer le bord droit du post-it sur le
   visage de la mère, quel que soit l'arbitrage colonne/hauteur — c'est la
   géométrie de l'œuvre qui fixe le seuil, pas une préférence. ========= */
@media (min-width: 1240px) {
  #accueil.section--sombre.hero-affiche {
    /* La scène tend vers le 16:9 de l'œuvre : sur un écran plus carré, un
       hero de pleine hauteur recadrerait l'image et ramènerait le visage
       de la mère sous le post-it (mesuré à 1280 × 860 : visage à x 916,
       note jusqu'à x 1166). En bornant la hauteur à 56 % de la largeur, le
       recadrage reste doux et les proportions de la maquette tiennent.
       Le premier terme rend à la fenêtre la place de la barre d'annonce et
       de l'en-tête (~7rem) : sans lui, le centrage flex repousse les
       boutons sous la ligne de flottaison des fenêtres basses. */
    min-height: min(calc(100svh - 7rem), 56vw, 920px);
    background-position: center, right bottom;
  }
}

/* --- Le carrousel d'ambiance ------------------------------------------- */
/* Les trois œuvres du commanditaire en fondu croisé, dans son ordre :
   enseignants, famille, étudiants. Pur CSS : chaque calque s'allume 1 s,
   reste plein 8 s, s'éteint 1 s — décalés de 8 s, cycle de 24 s.
   L'ordre du document règle les recouvrements : un calque qui s'allume
   passe DEVANT le précédent (frère suivant peint au-dessus), et au
   bouclage le calque 1 se rallume DERRIÈRE le calque 3 avant que celui-ci
   ne s'éteigne — le fond n'est jamais nu. Sous le tout, la section garde
   l'œuvre 1 en fond statique : c'est l'image de secours (chargement,
   prefers-reduced-motion) et elle rend le premier allumage invisible.
   Les fichiers viennent FINIS du commanditaire (halo doré compris) :
   simple conversion PNG → JPEG, aucune retouche ni recomposition ici. */
.hero-diapos {
  position: absolute;
  inset: 0;
  z-index: 0;
}
.hero-diapos > div {
  position: absolute;
  inset: 0;
  background-size: cover;
  /* Ancrage BAS, comme le fond statique de la section : le bas des œuvres
     (mains, sacs) reste toujours dans le cadre. */
  background-position: left bottom;
  background-repeat: no-repeat;
  opacity: 0;
  animation: vh-diapo 24s linear infinite;
}
.hero-diapos > div:nth-child(1) { background-image: url("../assets/hero-diapo-1.jpg"); }
.hero-diapos > div:nth-child(2) { background-image: url("../assets/hero-diapo-2.jpg"); animation-delay: 8s; }
.hero-diapos > div:nth-child(3) { background-image: url("../assets/hero-diapo-3.jpg"); animation-delay: 16s; }
@keyframes vh-diapo {
  0%     { opacity: 0; }
  4.17%  { opacity: 1; }
  37.5%  { opacity: 1; }
  41.67% { opacity: 0; }
  100%   { opacity: 0; }
}

/* --- La légende de chaque œuvre ---------------------------------------- */
/* « Pour les professionnels de l'éducation / les parents / les élèves et
   étudiants » — posée DANS le calque qu'elle commente : elle hérite de son
   fondu, l'apparition et la disparition sont synchrones sans la moindre
   animation supplémentaire. Marqueur jaune penché, comme la ligne « pour
   consacrer » du titre : même famille de gestes. En haut à droite, sur
   l'ardoise, au-dessus des personnages — l'emplacement qu'occupait le
   verset, le seul toujours vide sur les trois œuvres. Cachée sous 980 px :
   en cadrage gauche les personnages sortent du champ, la légende n'aurait
   personne à présenter. */
.hero-diapos__legende { display: none; }
@media (min-width: 980px) {
  .hero-diapos__legende {
    display: block;
    position: absolute;
    top: clamp(1.5rem, 3.8vh, 2.75rem);
    right: clamp(1.5rem, 3.5vw, 3.5rem);
    max-width: 19rem;
    font-family: "Permanent Marker", "Poppins", system-ui, sans-serif;
    font-size: clamp(1.15rem, .85rem + .75vw, 1.65rem);
    line-height: 1.2;
    text-align: right;
    color: var(--marqueur-or, #F7E14A);
    transform: rotate(-2deg);
    text-shadow: 0 3px 14px rgba(0, 0, 0, .6);
  }
}

/* Les BULLES de lumière (bokeh) du socle, reportées sur le conteneur du
   carrousel : son ::after, dernier peint de ce contexte d'empilement,
   monte au-dessus des calques. Mêmes valeurs et même animation
   (vh-bokeh, déclarée au socle) que le hero d'origine. */
.hero-diapos::after {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: rgba(255, 255, 255, .22);
  transform: translate(6vw, 14vh);
  filter: blur(2.5px);
  opacity: .85;
  pointer-events: none;
  box-shadow:
     10vw  48vh 0 1px rgba(255, 255, 255, .20),
     16vw  62vh 0 4px rgba(207, 174, 31, .18),
     24vw  28vh 0 0   rgba(255, 255, 255, .16),
     33vw  78vh 0 3px rgba(207, 174, 31, .14),
     41vw  12vh 0 2px rgba(255, 255, 255, .15),
     47vw  52vh 0 6px rgba(207, 174, 31, .10),
     55vw  22vh 0 1px rgba(255, 255, 255, .19),
     61vw  70vh 0 3px rgba(207, 174, 31, .15),
     68vw  38vh 0 0   rgba(255, 255, 255, .21),
     74vw  86vh 0 5px rgba(207, 174, 31, .11),
     81vw  18vh 0 2px rgba(255, 255, 255, .17),
     88vw  58vh 0 3px rgba(207, 174, 31, .13),
     93vw  32vh 0 1px rgba(255, 255, 255, .15),
     12vw  90vh 0 2px rgba(255, 255, 255, .12),
     29vw  92vh 0 4px rgba(207, 174, 31, .11),
     38vw  66vh 0 1px rgba(255, 255, 255, .16),
     52vw  88vh 0 2px rgba(207, 174, 31, .12),
     70vw   8vh 0 1px rgba(255, 255, 255, .13),
     85vw  74vh 0 4px rgba(207, 174, 31, .12);
  animation: vh-bokeh 26s ease-in-out infinite alternate;
}
/* Le cadrage des calques suit celui de la section : bord gauche (ardoise
   surtout) sous 1240 px, bord droit (scène complète) au-delà — toujours
   calé en bas. Placé APRÈS la règle de base : même spécificité, c'est
   l'ordre qui tranche. */
@media (min-width: 1240px) {
  .hero-diapos > div { background-position: right bottom; }
}

/* Mouvement neutralisé : les calques restent éteints (l'œuvre 1 statique
   de la section porte seule le décor) et les bulles s'immobilisent — le
   socle fait de même pour les rayons. */
@media (prefers-reduced-motion: reduce) {
  .hero-diapos > div,
  .hero-diapos::after { animation: none; }
}

/* --- Post-it réduit dans l'empilement mobile --------------------------- */
/* Pleine largeur, la note pesait autant que le titre ; réduite d'un cran
   (largeur, corps, marges internes), elle redevient une note épinglée au
   milieu de la pile — et rend ~35 px de hauteur au premier écran. */
@media (max-width: 979px) {
  .theme--note {
    width: min(92%, 21rem);
    padding: 1.1rem 1rem .8rem;
  }
  #accueil .theme--note .pastille-theme { font-size: .7rem; margin-bottom: .3rem; }
  #accueil .theme--note .theme__phrase {
    font-size: clamp(1.1rem, .85rem + 1.3vw, 1.5rem);
  }
  #accueil .theme--note .theme__ref { font-size: .8125rem; margin-top: .35rem; }
}

/* (Le verset d'appui Proverbes 16:3 a été retiré à la demande du
   commanditaire.) */

/* --- Badge « Première soirée dans » : sombre, cerclé d'or -------------- */
/* La maquette pose un badge sombre bordé d'or, horloge dorée en tête —
   et non le badge sable des sections claires. Craie sur fond vert nuit
   translucide : ≥ 12:1 sur l'ardoise. */
#accueil .eyebrow {
  gap: .5em;
  background: rgba(1, 49, 46, .55);
  color: var(--craie, #F4F7F2);
  border: 1.5px solid var(--vh-or);
  box-shadow: 0 4px 14px rgba(0, 0, 0, .35);
}
#accueil .eyebrow::before { display: none; }
#accueil .eyebrow svg { flex: none; color: var(--vh-or-clair); }

/* --- Tuiles du compte à rebours : cerclées d'or, libellés dorés -------- */
#accueil [data-countdown] > div {
  background: rgba(1, 49, 46, .48);
  border: 1px solid rgba(207, 174, 31, .55);
  border-top: 2px solid var(--vh-or);
}
#accueil [data-countdown] > * > :not([data-cd]) { color: var(--vh-or-clair); }

/* --- La date, précédée de son calendrier ------------------------------- */
#accueil .hero-date {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: .5em;
}
#accueil .hero-date svg { flex: none; color: var(--vh-or-clair); }

/* --- Flèches cerclées des boutons, comme sur la maquette --------------- */
.btn-fleche {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.55em;
  height: 1.55em;
  margin-left: .5em;
  margin-right: -.4em;
  border-radius: 50%;
  background: var(--vh-blanc);
  flex: none;
  vertical-align: middle;
}
.btn--rouge .btn-fleche { color: var(--vh-rouge); }
/* Sur le bouton or, l'or comme couleur de flèche échouerait sur le cercle
   blanc (CONTRAT §2) : c'est le brun doré du badge temple qui trace. */
.btn--or .btn-fleche { color: #6B5310; }

/* L'ardoise ne bouge pas : rien à neutraliser ici, mais la règle existe
   pour que toute animation ajoutée plus tard au hero y soit soumise. */
@media (prefers-reduced-motion: reduce) {
  #accueil.hero-affiche,
  #accueil.hero-affiche::before,
  #accueil.hero-affiche::after { animation: none; }
}


/* =============================================================================
   20. GRIFFONNAGES SCOLAIRES
   Deux bandes de fournitures dessinées au trait (assets/doodle-bande.svg),
   répétées horizontalement en haut et en bas de la section — l'esprit des
   cadres « doodle rentrée », aux couleurs de la charte. Le décalage
   horizontal différent de la bande basse casse l'effet de symétrie. Le
   supplément de padding maintient le contenu hors des bandes : les
   griffonnages encadrent, ils ne passent jamais sous le texte.
   Décor pur : rien à annoncer aux lecteurs d'écran, rien à imprimer (la
   section 19 retire déjà les fonds à l'impression).
   ============================================================================= */
.section--griffonnee {
  background-image: url("../assets/doodle-bande.svg"), url("../assets/doodle-bande.svg");
  background-repeat: repeat-x;
  background-position: left -60px top 10px, left 210px bottom 10px;
  background-size: auto clamp(72px, 10vw, 108px);
  padding-block: calc(var(--vh-section-y) + clamp(3rem, 7vw, 4.25rem));
}

/* Grands motifs isolés — un objet par section, posé dans le vide à droite
   du titre (les titres sont calés à gauche, le chapô est limité à 62ch).
   Sous 64rem le texte occupe toute la largeur : le motif disparaît plutôt
   que de passer sous les mots. */
@media (min-width: 64rem) {
  .section--motif-agenda,
  .section--motif-carte,
  .section--motif-telephone,
  .section--motif-enveloppe,
  .section--motif-globe,
  .section--motif-stylo {
    background-repeat: no-repeat;
    background-position: top 3.5rem right clamp(1.5rem, 5vw, 5rem);
    background-size: auto clamp(200px, 24vw, 340px);
  }
  /* L'agenda et la carte sont des objets compacts : à taille égale ils
     paraissent plus petits que le téléphone ou le globe. On les agrandit. */
  .section--motif-agenda,
  .section--motif-carte { background-size: auto clamp(240px, 28vw, 400px); }
  .section--motif-agenda    { background-image: url("../assets/doodle-agenda.svg"); }
  .section--motif-carte     { background-image: url("../assets/doodle-carte.svg"); }
  .section--motif-telephone { background-image: url("../assets/doodle-telephone.svg"); }
  .section--motif-enveloppe { background-image: url("../assets/doodle-enveloppe.svg"); }
  .section--motif-globe     { background-image: url("../assets/doodle-globe.svg"); }
  .section--motif-stylo     { background-image: url("../assets/doodle-stylo.svg"); }
}

/* Griffonnages de la timeline du programme : un petit objet en face de
   chaque carte, du côté que l'alternance des cartes laisse vide. Ils ne
   s'affichent qu'avec le fil central (>= 900px, même seuil que la
   timeline en deux colonnes) ; en une colonne il n'y a pas de vide. */
.timeline__gribouillis { display: none; }
@media (min-width: 900px) {
  .timeline__gribouillis {
    display: block;
    position: absolute;
    width: clamp(76px, 8vw, 116px);
    height: auto;
    color: var(--vh-vert-fonce);
    /* .6 : assez présent pour que le duotone se lise (corps blancs,
       accents or), assez doux pour rester un décor. */
    opacity: .6;
    pointer-events: none;
  }
  .timeline__item:nth-child(odd)  .timeline__gribouillis { left: calc(100% + 6.5rem); }
  .timeline__item:nth-child(even) .timeline__gribouillis { right: calc(100% + 6.5rem); }
  /* Tailles et inclinaisons variées : l'irrégularité fait le charme. */
  .timeline__item:nth-child(1) .timeline__gribouillis { top: 22%; transform: rotate(-9deg); }
  .timeline__item:nth-child(2) .timeline__gribouillis { top: 12%; transform: rotate(7deg); width: clamp(96px, 10vw, 140px); }
  .timeline__item:nth-child(3) .timeline__gribouillis { top: 30%; transform: rotate(-7deg); width: clamp(64px, 7vw, 96px); }
  .timeline__item:nth-child(4) .timeline__gribouillis { top: 14%; transform: rotate(8deg); width: clamp(60px, 6.5vw, 88px); }
  .timeline__item:nth-child(5) .timeline__gribouillis { top: 24%; transform: rotate(-6deg); width: clamp(56px, 6.5vw, 82px); }
}
