/* ==========================================================================
   pack.css — feuille unique du design pack LaitMeuh — v1.1 (22/08/2026)
   Remplace socle.css. Chargée APRÈS fonts.css et theme.css.
   Ne cible que les classes .cbl-* du contrat (§4.3 / §4.4 / §4.5 du brief),
   complétées des crochets listés §3 de la notice.
   Aucune couleur, fonte, espacement ou rayon en dur : tout passe par var(--…).
   v1.1 reprend les règles que le site maintenait à sa place (partie E du brief
   retour) : panneau du formulaire en frère de la carte, placeholder RGAA,
   panneau de consentement de la carte. La neutralisation à coups de !important
   des animations disparaît : pack.js honore désormais data-cbl-animations.
   ========================================================================== */

/* --------------------------------------------------------------------------
   0. Bases
   -------------------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }
/* Le bandeau de navigation des pages intérieures est collant : sans réserve de
   défilement, une ancre atterrirait dessous. */
html {
  -webkit-text-size-adjust: 100%;
  scroll-padding-top: calc(var(--layout-navbar-height) + var(--spacing-xs));
}

body {
  margin: 0;
  background: var(--color-surface);
  color: var(--color-text);
  font-family: var(--typography-body-font-family);
  font-size: var(--typography-body-font-size);
  line-height: var(--typography-body-line-height);
  text-wrap: pretty;
}

img { display: block; max-width: 100%; height: auto; }

a { color: var(--color-link); text-decoration-thickness: 1px; text-underline-offset: 3px; }
a:hover, a:focus-visible { color: var(--color-link-hover); }

:focus-visible {
  outline: 3px solid var(--color-focus);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}

.cbl-main { display: block; }

/* Gabarit de contenu — un seul jeu de règles partagé par tous les __inner. */
.cbl-topbar__inner,
.cbl-header__inner,
.cbl-nav,
.cbl-hero__inner,
.cbl-cards__inner,
.cbl-press__inner,
.cbl-prefooter__inner,
.cbl-footer__inner,
.cbl-flashes,
.cbl-richtext,
.cbl-form,
.cbl-tabs,
.cbl-cta {
  width: 100%;
  max-width: var(--layout-max);
  margin-inline: auto;
  padding-inline: var(--layout-gutter);
}

/* Ornement « filet — vache — filet » du site, en masque monochrome.
   La couleur suit le contexte : noir sur le bandeau jaune, jaune sur blanc. */
.cbl-richtext--band > h2::after,
.cbl-tabs__heading::after {
  content: "";
  display: block;
  width: 240px;
  height: 24px;
  margin: var(--spacing-sm) auto 0;
  background: url("../img/ornament-primary.png") center / contain no-repeat;
}
.cbl-richtext--on-primary > h2::after { background-image: url("../img/ornament-dark.png"); }

/* --------------------------------------------------------------------------
   1. Topbar (§4.5) — rendue sur toutes les pages sauf l'accueil (A11)
   -------------------------------------------------------------------------- */
.cbl-topbar {
  background: var(--color-topbar-bg);
  font-family: var(--typography-ui-font-family);
  font-size: var(--font-size-xs);
  letter-spacing: var(--typography-ui-letter-spacing);
}
/* Téléphone et e-mail à GAUCHE, comme sur le site (correctif A11), sur le même
   fond foncé que le pied de page et un peu plus serré que le reste du pack. */
.cbl-topbar__inner {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-start;
  gap: var(--spacing-md);
  padding-block: var(--spacing-2xs);
}
.cbl-topbar__phone,
.cbl-topbar__email {
  color: var(--color-topbar-text);
  text-decoration: none;
}
.cbl-topbar__phone:hover,
.cbl-topbar__email:hover { color: var(--color-primary); text-decoration: underline; }

/* --------------------------------------------------------------------------
   2. Header + navigation (§4.3 / §4.5)

   Deux en-têtes, pas un (B5). L'accueil garde la barre blanche unique, logo à
   gauche et navigation en ligne à droite ; elle est COLLANTE, ce que montre
   capture-popup-desktop.png. Les pages intérieures posent la marque sur une
   ligne blanche qui défile normalement, puis la navigation dans un bandeau
   jaune pleine largeur, lui collant : .cbl-header--stacked + .cbl-nav--bar,
   le bandeau étant un FRÈRE du header (son bloc collant a besoin du corps de
   page pour conteneur, pas d'un en-tête de 130 px).

   Aucune réserve d'espace à prévoir : `position: sticky` laisse l'élément dans
   le flux, le contenu ne saute donc pas au moment du décollement. Les deux
   variantes gardent la même hauteur avant et après — seule une ombre apparaît.
   -------------------------------------------------------------------------- */
.cbl-header {
  position: sticky;
  top: 0;
  z-index: 60;
  background: var(--color-header-bg);
  transition: box-shadow var(--motion-fast) var(--motion-ease);
}
.cbl-header--stuck { box-shadow: var(--shadow-sticky); }
/* Pages intérieures : la marque défile, c'est le bandeau jaune qui colle. */
.cbl-header--stacked { position: relative; box-shadow: none; }
.cbl-header__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--spacing-md);
  padding-block: var(--spacing-md);
}
.cbl-header__brand {
  display: inline-flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 6px;
  text-decoration: none;
  color: inherit;
}
.cbl-header__logo { height: 44px; width: auto; flex: 0 0 auto; }
.cbl-header__baseline {
  margin: 0;
  color: var(--color-neutral-500);
  font-size: var(--font-size-xs);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  line-height: 1.2;
}

.cbl-nav { padding-block: 0; padding-inline: 0; }
.cbl-nav ul {
  display: flex;
  flex-wrap: wrap;
  gap: var(--spacing-lg);
  list-style: none;
  margin: 0;
  padding: 0;
}
.cbl-nav a {
  display: block;
  padding-block: 6px;
  color: var(--color-nav-text);
  font-family: var(--typography-ui-font-family);
  font-weight: 500;
  font-size: 14px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  text-decoration: none;
}
.cbl-nav a:hover { color: var(--color-nav-text-active); }
.cbl-nav a[aria-current="page"] { color: var(--color-nav-text-active); }

/* La navigation principale vit dans la barre blanche du header, alignée à droite.
   Ciblée par sa position dans le header, et non par un modificateur : le contrat
   ne connaît que .cbl-nav, .cbl-nav--bar et .cbl-nav--footer. */
.cbl-header .cbl-nav { margin-left: auto; }

/* Bandeau jaune collant des pages intérieures (B5).
   La navigation EST le bandeau : pleine largeur, contenu calé à gauche sur la
   colonne de 1080 px, comme le montre capture-contacts-desktop.png. */
.cbl-nav--bar {
  position: sticky;
  top: 0;
  z-index: 60;
  max-width: none;
  background: var(--color-nav-bg);
  padding-inline: max(var(--layout-gutter), (100% - var(--layout-max)) / 2);
  transition: box-shadow var(--motion-fast) var(--motion-ease);
}
.cbl-nav--bar.cbl-nav--stuck { box-shadow: var(--shadow-sticky); }
.cbl-nav--bar ul {
  align-items: center;
  justify-content: flex-start;
  gap: var(--spacing-md);
  /* Les items portent une respiration horizontale pour que la pastille de l'item
     courant ait de la place ; le retrait rend au premier libellé son alignement
     sur la colonne de contenu. */
  margin-inline-start: -14px;
  min-height: var(--layout-navbar-height);
}
/* Sur #fec321, l'ocre de l'item courant tombe à 3,05:1 : sur le bandeau, l'état
   courant n'est jamais porté par la couleur du texte. Il l'est par une PASTILLE
   INVERSÉE — fond --color-text, libellé --color-primary (8,9:1) — le même idiome
   que la pastille de l'année active des onglets. Ni filet, ni soulignement :
   sur une bande de couleur, un trait sombre se lit comme une bordure de boîte. */
.cbl-nav--bar a {
  color: var(--color-text);
  padding: 8px 14px;
  border-radius: var(--radius-sm);
}
.cbl-nav--bar a:hover {
  background: var(--color-primary-deep);
  color: var(--color-text);
}
.cbl-nav--bar a[aria-current="page"] {
  background: var(--color-text);
  color: var(--color-primary);
}
.cbl-nav--bar a[aria-current="page"]:hover {
  background: var(--color-text);
  color: var(--color-primary);
}

/* Bouton burger — injecté par le JS du pack, masqué au-dessus de 640px. */
.cbl-nav__toggle {
  display: none;
  align-items: center;
  gap: 10px;
  margin: 0;
  padding: 12px 0;
  border: 0;
  background: none;
  color: var(--color-text);
  font-family: var(--typography-ui-font-family);
  font-size: var(--font-size-xs);
  letter-spacing: var(--typography-ui-letter-spacing);
  text-transform: uppercase;
  cursor: pointer;
}
.cbl-nav__toggle svg { display: block; }

.cbl-nav--footer { padding-inline: 0; }
.cbl-nav--footer ul { gap: var(--spacing-md); justify-content: center; }
.cbl-nav--footer a {
  padding-block: 0;
  color: var(--color-footer-text);
  font-size: var(--font-size-xs);
}
.cbl-nav--footer a:hover { color: var(--color-primary); }

/* --------------------------------------------------------------------------
   3. Flashs (§4.3)
   -------------------------------------------------------------------------- */
.cbl-flashes { padding-block: var(--spacing-sm) 0; }
.cbl-flash {
  margin-block: var(--spacing-xs);
  padding: 14px var(--spacing-sm);
  border-left: 4px solid currentColor;
  background: var(--color-surface-alt);
  font-size: var(--font-size-sm);
}
.cbl-flash--success { color: var(--color-success); }
.cbl-flash--error   { color: var(--color-error); }
.cbl-flash--info    { color: var(--color-info); }

/* --------------------------------------------------------------------------
   4. Hero — bandeau de titre (§4.3 / §4.5)
   -------------------------------------------------------------------------- */
.cbl-hero {
  position: relative;
  display: flex;
  align-items: center;
  isolation: isolate;
  min-height: var(--layout-hero-height);
  background: var(--color-neutral-900) center / cover no-repeat;
  color: var(--color-text-invert);
  overflow: hidden;
}
.cbl-hero__image {
  position: absolute;
  inset: 0;
  z-index: -2;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.cbl-hero::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: var(--color-hero-veil);
}
.cbl-hero__inner { padding-block: var(--spacing-lg); }
.cbl-hero__text { text-align: center; }
.cbl-hero__title {
  margin: 0;
  font-family: var(--typography-ui-font-family);
  font-weight: 400;
  font-size: 44px;
  line-height: 1.1;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  text-shadow: 0 2px 12px rgba(24, 21, 22, 0.5);
}
.cbl-hero__subtitle {
  margin: var(--spacing-xs) 0 0;
  font-size: var(--font-size-lg);
}
.cbl-hero--compact { min-height: 220px; }
.cbl-hero--compact .cbl-hero__title { font-size: var(--font-size-2xl); }

/* Fil d'ariane (§4.5) */
.cbl-breadcrumb { margin-top: 6px; }
.cbl-breadcrumb ol {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 10px;
  margin: 0;
  padding: 0;
  list-style: none;
  font-size: 17px;
  text-shadow: 0 2px 12px rgba(24, 21, 22, 0.5);
}
.cbl-breadcrumb li + li::before { content: "/"; margin-right: 10px; opacity: 0.75; }
.cbl-breadcrumb a { color: var(--color-text-invert); text-decoration: none; }
.cbl-breadcrumb a:hover { color: var(--color-primary); text-decoration: underline; }
.cbl-breadcrumb [aria-current="page"] { opacity: 0.92; }

/* --------------------------------------------------------------------------
   5. Texte riche (§4.3)
   -------------------------------------------------------------------------- */
.cbl-richtext { padding-block: var(--spacing-xl); }
.cbl-richtext > :first-child { margin-top: 0; }
.cbl-richtext > :last-child { margin-bottom: 0; }

.cbl-richtext h2,
.cbl-richtext h3,
.cbl-richtext h4 {
  font-family: var(--typography-heading-font-family);
  font-weight: var(--typography-heading-font-weight);
  line-height: var(--typography-heading-line-height);
  color: var(--color-text);
}
.cbl-richtext h2 { margin-block: var(--spacing-lg) var(--spacing-md); font-size: var(--font-size-3xl); }
.cbl-richtext h3 { margin-block: var(--spacing-lg) var(--spacing-sm); font-size: var(--font-size-xl); }
.cbl-richtext h4 { margin-block: var(--spacing-md) var(--spacing-xs); font-size: 21px; }
.cbl-richtext p { margin-block: 0 var(--spacing-md); }
.cbl-richtext ul,
.cbl-richtext ol { margin-block: 0 var(--spacing-md); padding-left: 1.4em; }
.cbl-richtext li { margin-bottom: var(--spacing-xs); }
.cbl-richtext blockquote {
  margin-block: var(--spacing-md);
  padding-left: var(--spacing-md);
  border-left: 3px solid var(--color-primary);
  font-style: italic;
}
.cbl-richtext strong { font-weight: 700; }
.cbl-richtext a { color: var(--color-text); text-decoration: underline; }
.cbl-richtext a:hover { color: var(--color-primary-deep); }
.cbl-richtext .cbl-btn { text-decoration: none; }

.cbl-richtext--narrow { max-width: 900px; }

/* Parution de presse : rythme et filet de séparation (page « On parle de nous »). */
.cbl-richtext--parution {
  max-width: 900px;
  padding-block: var(--spacing-lg) 0;
  border-top: 1px solid var(--color-border-soft);
}
.cbl-richtext--parution > p { margin-bottom: 0; font-size: var(--font-size-lg); }
.cbl-richtext--parution strong { white-space: nowrap; }

/* Section titrée et centrée (« Bienvenue à notre ferme ! », « Nos produits »…) */
.cbl-richtext--band { text-align: center; }
.cbl-richtext--band > h2 { margin-top: 0; margin-bottom: var(--spacing-md); }
.cbl-richtext--band > p { max-width: 820px; margin-inline: auto; font-size: var(--font-size-lg); }

/* Fond jaune à éclaboussure de lait */
.cbl-richtext--on-primary {
  max-width: none;
  padding-block: var(--spacing-xl) var(--spacing-2xl);
  padding-inline: var(--layout-gutter);
  background: var(--color-primary-band) url("../img/yellow_bg.jpg") center / cover no-repeat;
}
.cbl-richtext--on-primary > * { max-width: var(--layout-max); margin-inline: auto; }

/* Fond photo (« Lait frais BIO ») */
.cbl-richtext--on-photo {
  position: relative;
  isolation: isolate;
  max-width: none;
  padding-block: var(--spacing-2xl);
  padding-inline: var(--layout-gutter);
  background: var(--color-neutral-900) url("../img/bg_fresh.jpg") center / cover no-repeat;
  color: var(--color-text-invert);
}
.cbl-richtext--on-photo::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: var(--color-band-veil);
}
.cbl-richtext--on-photo > * { max-width: var(--layout-max); margin-inline: auto; }
.cbl-richtext--on-photo h2 { color: var(--color-primary); }
.cbl-richtext--on-photo > h2::after { margin-inline: 0; }
.cbl-richtext--on-photo h3 { color: var(--color-text-invert); font-size: var(--font-size-xl); }
.cbl-richtext--on-photo a { color: var(--color-text-invert); }
.cbl-richtext--on-photo a:hover { color: var(--color-primary); }
.cbl-richtext--on-photo .cbl-btn--primary { color: var(--color-text); }
.cbl-richtext--on-photo .cbl-btn--primary:hover { color: var(--color-text); }

/* Photo d'accompagnement d'une section (extension richtext — voir notice §3). */
.cbl-richtext--with-media {
  position: relative;
  min-height: 460px;
  text-align: left;
}
.cbl-richtext--with-media > * { max-width: none; margin-inline: 0; width: min(100%, 48%); }
.cbl-richtext--on-photo.cbl-richtext--with-media,
.cbl-richtext--on-primary.cbl-richtext--with-media {
  padding-inline: max(var(--layout-gutter), (100% - var(--layout-max)) / 2);
}
.cbl-richtext__media {
  position: absolute;
  top: 50%;
  right: max(var(--layout-gutter), (100% - var(--layout-max)) / 2);
  width: 340px;
  height: 340px;
  margin: 0;
  border: 6px solid var(--color-text-invert);
  border-radius: var(--radius-pill);
  object-fit: cover;
  transform: translateY(-50%);
}
/* La photo est centrée par translateY(-50%) : son entrée doit composer avec ce
   décalage, sinon elle retombe une demi-hauteur trop bas en fin d'animation. */
.cbl-richtext__media.cbl-reveal { transform: translateY(calc(-50% + 40px)); }
.cbl-richtext__media.cbl-reveal--in { transform: translateY(-50%); }

/* --------------------------------------------------------------------------
   6. Image (§4.3 + extension lien §4.4)
   -------------------------------------------------------------------------- */
.cbl-image {
  max-width: var(--layout-max);
  margin: var(--spacing-lg) auto;
  padding-inline: var(--layout-gutter);
}
.cbl-image img { margin-inline: auto; }
.cbl-image figcaption {
  margin-top: var(--spacing-xs);
  color: var(--color-text-muted);
  font-size: var(--font-size-sm);
  text-align: center;
}
.cbl-image--full { max-width: none; margin-block: 0; padding-inline: 0; }
.cbl-image--full img { width: 100%; }
.cbl-image--narrow { max-width: 900px; margin-block: var(--spacing-md) var(--spacing-2xl); }

.cbl-image__link {
  display: block;
  transition: opacity var(--motion-fast) var(--motion-ease);
}
.cbl-image__link:hover { opacity: 0.88; }
.cbl-image__link:focus-visible { outline-offset: 4px; }

/* Pastille du logo posée à cheval sur la bande jaune. */
.cbl-image--pastille {
  position: relative;
  z-index: 1;
  margin-block: -100px var(--spacing-lg);
}
.cbl-image--pastille img {
  width: 200px;
  filter: drop-shadow(var(--shadow-pastille));
}

/* Photo ronde bordée de blanc (bouteille de lait, section « Lait frais BIO »). */
.cbl-image--round img {
  width: 340px;
  height: 340px;
  border: 6px solid var(--color-text-invert);
  border-radius: var(--radius-pill);
  object-fit: cover;
}

/* --------------------------------------------------------------------------
   7. Boutons (§4.3)
   -------------------------------------------------------------------------- */
.cbl-btn {
  display: inline-block;
  padding: 17px 34px;
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--color-text);
  font-family: var(--typography-ui-font-family);
  font-weight: 500;
  font-size: var(--font-size-xs);
  letter-spacing: 0.12em;
  line-height: 1;
  text-transform: uppercase;
  text-decoration: none;
  cursor: pointer;
  transition: background-color var(--motion-fast) var(--motion-ease),
              color var(--motion-fast) var(--motion-ease);
}
.cbl-btn--primary { background: var(--color-primary); color: var(--color-text); }
.cbl-btn--primary:hover { background: var(--color-primary-deep); color: var(--color-text); }

.cbl-cta { padding-block: var(--spacing-xl); text-align: center; }
.cbl-cta__button { min-width: 200px; }

/* --------------------------------------------------------------------------
   7 bis. Retour en haut de page (B3)
   Carré jaune fixe en bas à droite, posé par pack.js — le socle n'a rien à
   rendre, comme pour le burger de navigation. Il forme un seul dispositif avec
   le bandeau collant : il apparaît au même moment, passé le même seuil.
   Particulièrement utile sur « On parle de nous », qui fait près de 8 000 px.
   -------------------------------------------------------------------------- */
.cbl-totop {
  position: fixed;
  right: var(--spacing-md);
  bottom: var(--spacing-md);
  z-index: 90;
  display: grid;
  place-items: center;
  width: var(--layout-totop-size);
  height: var(--layout-totop-size);
  padding: 0;
  border: 0;
  border-radius: 0;
  background: var(--color-primary);
  color: var(--color-text);
  cursor: pointer;
  opacity: 0;
  visibility: hidden;
  transform: translateY(10px);
  transition: opacity var(--motion-fast) var(--motion-ease),
              transform var(--motion-fast) var(--motion-ease),
              background-color var(--motion-fast) var(--motion-ease),
              visibility 0s linear var(--motion-fast);
}
.cbl-totop--in {
  opacity: 1;
  visibility: visible;
  transform: none;
  transition-delay: 0s;
}
.cbl-totop:hover { background: var(--color-primary-deep); }
.cbl-totop svg { display: block; }

/* --------------------------------------------------------------------------
   8. Cartes (§4.4)
   -------------------------------------------------------------------------- */
.cbl-cards { padding-block: var(--spacing-lg) var(--spacing-2xl); }
.cbl-cards__inner {
  display: grid;
  gap: var(--spacing-lg) var(--spacing-md);
}
.cbl-cards--cols-2 .cbl-cards__inner { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.cbl-cards--cols-3 .cbl-cards__inner { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.cbl-cards--cols-4 .cbl-cards__inner { grid-template-columns: repeat(4, minmax(0, 1fr)); }

.cbl-cards__item {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
}
.cbl-cards__media {
  width: 100%;
  aspect-ratio: 16 / 10;
  object-fit: cover;
}
.cbl-cards__title {
  margin: var(--spacing-md) 0 0;
  font-family: var(--typography-heading-font-family);
  font-weight: var(--typography-heading-font-weight);
  font-size: var(--font-size-xl);
  line-height: var(--typography-heading-line-height);
  color: var(--color-text);
}
.cbl-cards__text {
  margin: var(--spacing-sm) 0 0;
  color: var(--color-text-muted);
  font-size: var(--font-size-md);
}
.cbl-cards__link {
  margin-top: var(--spacing-sm);
  color: var(--color-text);
  font-family: var(--typography-ui-font-family);
  font-size: var(--font-size-xs);
  letter-spacing: var(--typography-ui-letter-spacing);
  text-transform: uppercase;
  text-decoration: none;
  border-bottom: 2px solid var(--color-primary);
  padding-bottom: 2px;
}
.cbl-cards__link:hover { color: var(--color-primary-deep); border-bottom-color: var(--color-primary-deep); }

/* Médias ronds (grille « Nos produits »). */
.cbl-cards--round .cbl-cards__media {
  width: 190px;
  height: 190px;
  aspect-ratio: auto;
  border-radius: var(--radius-pill);
}
.cbl-cards--round { padding-bottom: var(--spacing-3xl); }

/* Cartes encadrées sans média (coordonnées de la page Contacts). */
.cbl-cards--framed .cbl-cards__item {
  justify-content: center;
  min-height: 200px;
  padding: var(--spacing-lg) var(--spacing-md);
  border: 1px solid var(--color-border);
}
.cbl-cards--framed .cbl-cards__title { margin-top: 0; }
/* Le site affiche ces liens en ocre ; décision du client du 18/08 confirmée :
   on garde le texte foncé (partie D du brief retour). */
.cbl-cards--framed .cbl-cards__text a { color: var(--color-text); }

/* --------------------------------------------------------------------------
   9. Slider (§4.4)
   -------------------------------------------------------------------------- */
.cbl-slider { position: relative; background: var(--color-neutral-900); }
.cbl-slider__track {
  display: block;
  margin: 0;
  padding: 0;
  list-style: none;
}
.cbl-slider__slide {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  isolation: isolate;
  min-height: var(--layout-slider-height);
  padding: var(--spacing-xl) var(--layout-gutter);
  overflow: hidden;
}
.cbl-slider__media {
  position: absolute;
  inset: 0;
  z-index: -2;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
/* Voile de la photo. Sa valeur bascule pendant la rotation du cube : la face qui
   s'éloigne s'assombrit, ce qui donne le volume (B4). */
.cbl-slider__slide::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background-color: var(--color-hero-veil);
  transition: background-color var(--motion-slide) var(--motion-ease-inout);
}
.cbl-slider__slide--dim::after { background-color: var(--color-cube-veil); }
.cbl-slider__content {
  width: 100%;
  max-width: var(--layout-max);
  color: var(--color-text-invert);
  text-align: center;
}
.cbl-slider__title,
.cbl-slider__titre-suite {
  margin: 0;
  font-family: var(--typography-heading-font-family);
  font-weight: var(--typography-heading-font-weight);
  font-size: var(--font-size-4xl);
  line-height: 1.05;
  color: var(--color-text-invert);
  text-shadow: 0 3px 18px rgba(24, 21, 22, 0.55);
}
.cbl-slider__subtitle {
  margin: var(--spacing-sm) 0 0;
  font-family: var(--typography-ui-font-family);
  font-weight: 300;
  font-size: var(--font-size-2xl);
  letter-spacing: 0.02em;
  text-transform: uppercase;
  text-shadow: 0 2px 14px rgba(24, 21, 22, 0.55);
}
.cbl-slider__cta { margin-top: var(--spacing-lg); padding-block: 21px; }

/* Entrée du contenu — trois comportements distincts, comme sur le site (B4) :
   le titre entre LETTRE À LETTRE en glissant, le sous-titre monte d'un bloc, le
   bouton arrive avec un léger dépassement. Le découpage en lettres est fait par
   pack.js (un <span> par caractère, dans un mot insuécable, le titre complet
   porté par aria-label) : sans JS, et en mouvement réduit, aucun découpage — le
   titre reste lisible d'un bloc. Piloté par --active, posée par le JS. */
@keyframes cbl-slide-in {
  from { opacity: 0; transform: translateY(34px); }
  to   { opacity: 1; transform: translateY(0); }
}
@keyframes cbl-slide-in-cta {
  from { opacity: 0; transform: translateY(22px) scale(0.9); }
  to   { opacity: 1; transform: translateY(0) scale(1); }
}
@keyframes cbl-slide-media {
  from { transform: scale(1.12); }
  to   { transform: scale(1); }
}
@keyframes cbl-char-in {
  from { opacity: 0; transform: translate3d(-0.42em, 0.12em, 0); }
  to   { opacity: 1; transform: none; }
}
.cbl-slider--ready .cbl-slider__slide .cbl-slider__title,
.cbl-slider--ready .cbl-slider__slide .cbl-slider__titre-suite,
.cbl-slider--ready .cbl-slider__slide .cbl-slider__subtitle,
.cbl-slider--ready .cbl-slider__slide .cbl-slider__cta { opacity: 0; }

/* Titre découpé : ce sont les lettres qui portent l'entrée, plus le titre.
   Même spécificité que la règle de masquage ci-dessus, posée après elle. */
.cbl-slider--ready .cbl-slider__slide .cbl-slider__title--split { opacity: 1; }
.cbl-slider__word { display: inline-block; white-space: nowrap; }
.cbl-slider__char { display: inline-block; }
.cbl-slider--ready .cbl-slider__char { opacity: 0; }

.cbl-slider__slide--active .cbl-slider__title:not(.cbl-slider__title--split),
.cbl-slider__slide--active .cbl-slider__titre-suite:not(.cbl-slider__title--split) {
  animation: cbl-slide-in 1000ms var(--motion-ease) 320ms both;
}
.cbl-slider__slide--active .cbl-slider__char {
  animation: cbl-char-in 620ms var(--motion-ease) both;
  animation-delay: calc(320ms + var(--cbl-char-index, 0) * 34ms);
}
.cbl-slider__slide--active .cbl-slider__subtitle {
  animation: cbl-slide-in 900ms var(--motion-ease) 880ms both;
}
.cbl-slider__slide--active .cbl-slider__cta {
  animation: cbl-slide-in-cta 760ms var(--motion-ease-back) 1280ms both;
}
.cbl-slider__slide--active .cbl-slider__media {
  animation: cbl-slide-media 13000ms var(--motion-ease) both;
}

/* Sans JS : les diapositives restent empilées et lisibles, contrôles masqués. */
.cbl-slider__controls { display: none; }

/* Avec JS : ROTATION DE CUBE (B4). La piste est le cube, la diapositive une face.
   La piste porte translateZ(-L/2), ce qui ramène la face avant dans le plan de
   l'écran ; les faces sont posées en rotateY(k·90deg) translateZ(L/2). Tourner la
   piste de -90deg amène donc la face droite exactement où était la face avant :
   ni saut d'échelle, ni changement de plan. Flèche suivante = -90deg, précédente
   = +90deg, le sens suit la direction demandée.
   L vient du DOM (largeur mesurée) : pack.js écrit les transformations des deux
   seules faces en jeu en style inline. C'est le seul endroit du pack où une
   valeur en pixels a un sens — elle n'est pas un choix graphique. */
.cbl-slider--ready {
  overflow: hidden;
  perspective: 1600px;
  perspective-origin: 50% 45%;
}
.cbl-slider--ready .cbl-slider__track {
  position: relative;
  height: var(--layout-slider-height);
  transform-style: preserve-3d;
  transition: transform var(--motion-slide) var(--motion-ease-inout);
}
.cbl-slider--ready .cbl-slider__slide {
  position: absolute;
  inset: 0;
  min-height: 0;
  visibility: hidden;
  backface-visibility: hidden;
}
/* Deux faces montées à la fois, jamais plus : la sortante et l'entrante. */
.cbl-slider--ready .cbl-slider__slide--face { visibility: visible; }
.cbl-slider--ready .cbl-slider__controls { display: block; }

.cbl-slider__prev,
.cbl-slider__next {
  position: absolute;
  top: 50%;
  z-index: 2;
  display: grid;
  place-items: center;
  width: 46px;
  height: 46px;
  margin-top: -23px;
  padding: 0;
  border: 0;
  border-radius: var(--radius-pill);
  background: rgba(255, 255, 255, 0.18);
  color: var(--color-text-invert);
  cursor: pointer;
  transition: background-color var(--motion-fast) var(--motion-ease);
}
.cbl-slider__prev:hover,
.cbl-slider__next:hover { background: var(--color-primary); color: var(--color-text); }
.cbl-slider__prev { left: var(--spacing-md); }
.cbl-slider__next { right: var(--spacing-md); }

.cbl-slider__dots {
  position: absolute;
  left: 0;
  right: 0;
  bottom: var(--spacing-md);
  z-index: 2;
  display: flex;
  justify-content: center;
  gap: 10px;
}
.cbl-slider__dots button {
  width: 12px;
  height: 12px;
  padding: 0;
  border: 2px solid var(--color-text-invert);
  border-radius: var(--radius-pill);
  background: transparent;
  cursor: pointer;
}
.cbl-slider__dots button[aria-selected="true"] { background: var(--color-text-invert); }

/* --------------------------------------------------------------------------
   10. Onglets (§4.4)
   -------------------------------------------------------------------------- */
.cbl-tabs {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  padding-block: var(--spacing-xl);
}
.cbl-tabs__heading {
  grid-column: 1 / -1;
  margin: 0 0 var(--spacing-xl);
  font-family: var(--typography-heading-font-family);
  font-weight: var(--typography-heading-font-weight);
  font-size: var(--font-size-3xl);
  line-height: var(--typography-heading-line-height);
  text-align: center;
}
/* Photo d'accompagnement (extension du BlocType tabs — voir notice §3).
   height:0 + min-height:100% : la photo ne pousse pas les rangées de la grille,
   elle se contente de remplir la hauteur que la colonne de droite a fixée. */
.cbl-tabs__media {
  grid-column: 1;
  grid-row: 2 / span 30;
  width: 100%;
  height: 0;
  min-height: 100%;
  object-fit: contain;
  object-position: center;
  background: var(--color-accent);
}
.cbl-tabs__nav {
  grid-column: 2;
  grid-row: 2;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--spacing-xs);
  padding: var(--spacing-lg) var(--spacing-lg) 0;
  background: var(--color-accent);
}
/* Découvrabilité du clavier (B7). Le patron WAI-ARIA est juste, mais rien à
   l'écran ne dit que les flèches servent à quelque chose : un visiteur tabule
   depuis « 1989 », atterrit sur le bouton du panneau et conclut que les années
   ne sont pas navigables. L'aide — lue en permanence par les lecteurs d'écran via
   aria-describedby — devient donc visible quand un onglet prend le focus.
   :has(:focus-visible) et non :focus-within : un clic souris ne doit rien
   déclencher, l'aide ne s'adresse qu'à qui navigue au clavier. L'onglet focalisé
   porte déjà son propre anneau ; un second liseré autour de la liste entière se
   lirait comme une bordure de boîte et non comme un état. */
.cbl-tabs__hint {
  grid-column: 2;
  grid-row: 3;
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}
.cbl-tabs__nav:has(:focus-visible) + .cbl-tabs__hint {
  position: static;
  width: auto;
  height: auto;
  margin: 0;
  padding: var(--spacing-sm) var(--spacing-lg) 0;
  overflow: visible;
  clip-path: none;
  white-space: normal;
  background: var(--color-accent);
  color: var(--color-text);
  font-family: var(--typography-ui-font-family);
  font-size: var(--font-size-xs);
  letter-spacing: var(--typography-ui-letter-spacing);
  text-align: center;
}
.cbl-tabs__tab {
  padding: 7px 18px;
  border: 0;
  border-radius: var(--radius-pill);
  background: transparent;
  color: var(--color-text-muted);
  font-family: var(--typography-ui-font-family);
  font-size: var(--font-size-xs);
  letter-spacing: var(--typography-ui-letter-spacing);
  cursor: pointer;
  transition: background-color var(--motion-fast) var(--motion-ease),
              color var(--motion-fast) var(--motion-ease);
}
.cbl-tabs__tab:hover { color: var(--color-text); }
.cbl-tabs__tab[aria-selected="true"] { background: var(--color-primary); color: var(--color-text); }

.cbl-tabs__panel {
  grid-column: 2;
  padding: var(--spacing-md) var(--spacing-lg) var(--spacing-lg);
  background: var(--color-accent);
  text-align: center;
}
/* Avec JS : tous les panneaux occupent la MÊME cellule de grille. La hauteur du
   bloc est donc celle du panneau le plus long et ne bouge plus d'une année à
   l'autre ; les panneaux inactifs restent en place, simplement invisibles
   (visibility:hidden les retire aussi du clavier et de l'arbre d'accessibilité).
   Sans JS, la règle ne s'applique pas : les panneaux se suivent en chronologie. */
.cbl-tabs--ready .cbl-tabs__panel { grid-row: 4; }
.cbl-tabs--ready .cbl-tabs__panel[hidden] { display: block; visibility: hidden; }
.cbl-tabs__title {
  margin: var(--spacing-md) 0 var(--spacing-sm);
  font-family: var(--typography-heading-font-family);
  font-weight: var(--typography-heading-font-weight);
  font-size: var(--font-size-xl);
  line-height: var(--typography-heading-line-height);
}
.cbl-tabs__body p { margin: 0 0 var(--spacing-md); }
.cbl-tabs__body > :last-child { margin-bottom: 0; }
.cbl-tabs__body .cbl-btn { margin-top: var(--spacing-md); }

/* --------------------------------------------------------------------------
   11. Popup événementielle (§4.4)
   -------------------------------------------------------------------------- */
.cbl-popup[hidden] { display: none; }
.cbl-popup {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: grid;
  place-items: center;
  padding: var(--spacing-md);
}
.cbl-popup__overlay {
  position: absolute;
  inset: 0;
  background: rgba(24, 21, 22, 0.62);
}
.cbl-popup__window {
  position: relative;
  max-width: 620px;
  max-height: calc(100vh - 2 * var(--spacing-md));
  overflow: auto;
  background: var(--color-surface);
  box-shadow: var(--shadow-raised);
}
.cbl-popup__close {
  position: absolute;
  top: 12px;
  right: 12px;
  width: 42px;
  height: 42px;
  padding: 0;
  border: 0;
  border-radius: var(--radius-pill);
  background: var(--color-primary);
  color: var(--color-text);
  font-family: var(--typography-ui-font-family);
  font-size: 24px;
  line-height: 1;
  cursor: pointer;
}
.cbl-popup__close:hover { background: var(--color-primary-deep); }
.cbl-popup__media { width: 100%; }

/* --------------------------------------------------------------------------
   12. Formulaire (§4.3)
   -------------------------------------------------------------------------- */
.cbl-form {
  padding-block: var(--spacing-xl);
}
.cbl-form--narrow { max-width: 700px; }
.cbl-form__intro { margin: 0 0 var(--spacing-lg); }
.cbl-form__field { margin-bottom: var(--spacing-md); }
.cbl-form__field label {
  display: block;
  margin-bottom: 6px;
  font-family: var(--typography-ui-font-family);
  font-size: var(--font-size-xs);
  letter-spacing: var(--typography-ui-letter-spacing);
  text-transform: uppercase;
  color: var(--color-text);
}
.cbl-form__field input,
.cbl-form__field textarea {
  width: 100%;
  padding: 14px var(--spacing-sm);
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  background: var(--color-primary-soft);
  color: var(--color-text);
  font-family: inherit;
  font-size: var(--font-size-md);
  line-height: 1.5;
}
.cbl-form__field textarea { min-height: 170px; resize: vertical; }
.cbl-form__field input::placeholder,
.cbl-form__field textarea::placeholder { color: var(--color-text); opacity: 0.62; }

.cbl-form__req { margin-left: 3px; color: var(--color-text); }
.cbl-form__error {
  display: block;
  margin-top: 6px;
  color: var(--color-error);
  font-size: var(--font-size-sm);
}
.cbl-form__field--error input,
.cbl-form__field--error textarea { border-color: var(--color-error); border-width: 2px; }

.cbl-form__check {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  margin-bottom: var(--spacing-md);
  font-size: var(--font-size-sm);
}
.cbl-form__check input { flex: 0 0 auto; width: 20px; height: 20px; margin: 4px 0 0; accent-color: var(--color-text); }
.cbl-form__check label { font-family: var(--typography-body-font-family); text-transform: none; letter-spacing: 0; }

.cbl-hp {
  position: absolute !important;
  left: -9999px !important;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

/* Formulaire posé sur le panneau jaune (page Contacts). */
.cbl-form--on-primary {
  max-width: none;
  padding-inline: var(--layout-gutter);
  background: var(--color-primary);
}
.cbl-form--on-primary > * { max-width: 700px; margin-inline: auto; }
.cbl-form__title {
  margin-block: 0 var(--spacing-md);
  margin-inline: auto;
  font-family: var(--typography-heading-font-family);
  font-weight: var(--typography-heading-font-weight);
  font-size: var(--font-size-3xl);
  line-height: var(--typography-heading-line-height);
  color: var(--color-text);
}
.cbl-form--on-primary .cbl-form__field input,
.cbl-form--on-primary .cbl-form__field textarea { background: var(--color-primary-soft); }

/* Panneau Contacts : restitution du formulaire d'origine — pas de libellé au-dessus
   des champs, l'intitulé est porté par le placeholder, sur des champs sans bordure.
   Les <label> restent dans le DOM (liés par for) pour les lecteurs d'écran : ils
   sont masqués visuellement, jamais display:none.
   GARDE HOSTILE AUX ERREURS (A1) : le masquage ne peut atteindre ni un
   <label class="cbl-form__check">, ni le libellé d'une case imbriquée par erreur
   dans un champ. Le coût d'un :not() est nul, celui d'un formulaire muet est
   total — une case required réduite à 1×1 px rend l'envoi impossible sans que
   rien ne l'explique à l'écran. */
.cbl-form--on-primary .cbl-form__field > label:not(.cbl-form__check) {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
}
.cbl-form--on-primary .cbl-form__field .cbl-form__check,
.cbl-form--on-primary .cbl-form__field .cbl-form__check label {
  position: static;
  width: auto;
  height: auto;
  margin: 0;
  overflow: visible;
  clip: auto;
  clip-path: none;
  white-space: normal;
}
.cbl-form--on-primary .cbl-form__field input,
.cbl-form--on-primary .cbl-form__field textarea {
  border: 0;
  border-radius: 0;
  padding: 18px var(--spacing-sm);
  color: var(--color-text);
}
/* Remède RGAA appliqué (A7) : le placeholder blanc était à 1,47:1 sur
   --color-primary-soft, sous le seuil AA. En --color-text il monte à 11,1:1,
   sans aucun impact de mise en page. */
.cbl-form--on-primary .cbl-form__field input::placeholder,
.cbl-form--on-primary .cbl-form__field textarea::placeholder {
  color: var(--color-text);
  opacity: 1;
}
.cbl-form--on-primary .cbl-form__field textarea { min-height: 210px; }
.cbl-form--on-primary .cbl-form__check { margin-top: var(--spacing-md); }
.cbl-form--on-primary form { display: flex; flex-direction: column; }
.cbl-form--on-primary .cbl-btn--primary { align-self: flex-end; }
.cbl-form--on-primary .cbl-btn--primary {
  background: transparent;
  border-color: var(--color-neutral-0);
}
.cbl-form--on-primary .cbl-btn--primary:hover { background: var(--color-text); color: var(--color-primary); }

/* --------------------------------------------------------------------------
   12 bis. Carte (page Contacts) — trois modes du BlocType map
   `iframe` · `statique` (image cliquable) · `consentement` (substitut + clic).

   Le socle Cobelay ne sait pas imbriquer les blocs, et ce n'est pas une lacune
   passagère : le CHEMIN PRINCIPAL est donc le formulaire rendu en FRÈRE de la
   carte et remonté par marge négative (B2). .cbl-map__panel reste en réserve
   pour le jour où l'imbrication existera. Règle générale du pack : tout effet de
   superposition doit pouvoir s'exprimer entre blocs frères.
   -------------------------------------------------------------------------- */
.cbl-map {
  position: relative;
  display: flex;
  justify-content: flex-end;
  min-height: var(--layout-map-height);
  padding-inline: max(var(--layout-gutter), (100% - var(--layout-max)) / 2);
  background: var(--color-surface-alt);
}
/* Un seul crochet pour les trois modes : iframe interactive ou image substitut.
   object-fit évite qu'une image de tuiles ne se déforme (A8). */
.cbl-map__frame {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
  object-fit: cover;
}
/* Mode `statique` : toute la carte est cliquable et ouvre le service externe. */
.cbl-map__link {
  position: absolute;
  inset: 0;
  display: block;
}
.cbl-map__link:focus-visible { outline-offset: -6px; }

/* Mode `consentement` (A8) : l'image statique sert de substitut, l'iframe ne se
   charge qu'après un clic explicite — zéro requête tierce avant le clic, donc
   pas de bandeau de consentement à ajouter et les mentions légales du site
   restent vraies. Le bouton est un lien : la mécanique tient sans JS.
   Posé en bas à GAUCHE de la carte — la droite est occupée par le panneau jaune.
   Motif appelé à resservir : tout contenu tiers déposant des cookies a son
   substitut dans le pack. */
.cbl-map__consent {
  position: absolute;
  left: max(var(--layout-gutter), (100% - var(--layout-max)) / 2);
  bottom: var(--spacing-lg);
  z-index: 1;
  max-width: 420px;
  padding: var(--spacing-md);
  background: var(--color-surface);
  border: 1px solid var(--color-border-soft);
  box-shadow: var(--shadow-raised);
}
.cbl-map__consent-text {
  margin: 0 0 var(--spacing-sm);
  color: var(--color-text);
  font-size: var(--font-size-sm);
  line-height: 1.6;
}

/* Réserve : panneau enfant, pour le jour où l'imbrication de blocs arrivera. */
.cbl-map__panel {
  position: relative;
  width: 560px;
  max-width: 100%;
  background: var(--color-primary);
}
.cbl-map__panel .cbl-form { padding-block: var(--spacing-lg); }
.cbl-map__panel .cbl-form > * { max-width: none; }

/* Chemin principal : le bloc form_embed SUIT le bloc map et se remonte de la
   hauteur de la carte. Même rendu que le panneau enfant, sans imbrication. */
.cbl-map + .cbl-form--on-primary {
  position: relative;
  z-index: 2;
  width: 560px;
  max-width: 100%;
  margin-top: calc(-1 * var(--layout-map-height));
  margin-inline: auto max(var(--layout-gutter), (100% - var(--layout-max)) / 2);
  padding-block: var(--spacing-lg);
}
.cbl-map + .cbl-form--on-primary > * { max-width: none; }

/* --------------------------------------------------------------------------
   12 ter. Entrées au défilement
   Les classes sont posées par pack.js, jamais par le HTML du socle : sans JS,
   aucune règle ne s'applique et tout le contenu reste visible. Le JS ne pose
   rien non plus si prefers-reduced-motion est demandé, ni si la page est
   déclarée sans entrée (body[data-cbl-animations="off"], B1) : le pack fournit
   le vocabulaire du mouvement, son application par page appartient au site.
   -------------------------------------------------------------------------- */
.cbl-reveal {
  opacity: 0;
  transform: translateY(40px);
  transition: opacity var(--motion-reveal) var(--motion-ease), transform var(--motion-reveal) var(--motion-ease);
}
.cbl-reveal--in { opacity: 1; transform: none; }

/* Entrée ample : bandeau jaune d'accueil et pastille sous le bandeau. Course plus
   longue et plus lente, poussée par pack.js qui pose aussi le décalage.
   L'état de départ est écrit ici, sous .cbl-js, pour qu'il s'applique dès le
   premier affichage : sinon le texte se peint à sa place puis saute quand le
   script pose les classes. Sans JS, .cbl-js n'existe pas et rien n'est masqué.
   Le marqueur de page est testé ICI aussi : c'est ce qui rend inutile la
   neutralisation à coups de !important que le site maintenait (partie E). */
@media (prefers-reduced-motion: no-preference) {
  .cbl-js body:not([data-cbl-animations="off"]) .cbl-richtext--on-primary > h2:not(.cbl-reveal--in),
  .cbl-js body:not([data-cbl-animations="off"]) .cbl-richtext--on-primary > p:not(.cbl-reveal--in) {
    opacity: 0;
    transform: translateY(96px);
  }
  .cbl-js body:not([data-cbl-animations="off"]) .cbl-image--pastille:not(.cbl-reveal--in) {
    opacity: 0;
    transform: translateY(96px) scale(.94);
  }
}
.cbl-reveal--ample {
  transform: translateY(96px);
  transition-duration: 1250ms;
}
.cbl-image--pastille.cbl-reveal--ample { transform: translateY(96px) scale(.94); }
.cbl-reveal--ample.cbl-reveal--in { transform: none; }

/* Entrée du duo texte + photo ronde (bloc --with-media), relevée image par image
   sur la capture vidéo du site : la colonne de texte glisse d'un seul tenant
   depuis la gauche — une centaine de pixels, sans aucun déplacement vertical —
   et la photo ronde grandit de 0,72 à 1 SUR SON PROPRE CENTRE, qui ne bouge pas.
   Le texte part le premier, la photo le suit à 120 ms.
   Les enfants du texte partagent le même délai : décalés par rang, le bloc se
   disloquerait au lieu de se déplacer. */
.cbl-reveal--from-left {
  transform: translateX(-100px);
  transition-duration: 700ms;
}
.cbl-reveal--from-left.cbl-reveal--in { transform: none; }
.cbl-richtext__media.cbl-reveal--zoom {
  transform: translateY(-50%) scale(.72);
  transition-duration: 700ms;
}
.cbl-richtext__media.cbl-reveal--zoom.cbl-reveal--in { transform: translateY(-50%) scale(1); }

/* --------------------------------------------------------------------------
   13. Pré-footer et footer (§4.3 / §4.5)
   -------------------------------------------------------------------------- */
.cbl-prefooter { background: var(--color-prefooter-bg); color: var(--color-prefooter-text); padding-block: 70px 46px; }
.cbl-prefooter__inner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--spacing-md) var(--spacing-lg);
  padding-bottom: 60px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.12);
}
.cbl-prefooter__title {
  margin: 0;
  font-family: var(--typography-heading-font-family);
  font-weight: var(--typography-heading-font-weight);
  font-size: var(--font-size-3xl);
  line-height: var(--typography-heading-line-height);
  color: var(--color-prefooter-text);
}
.cbl-prefooter__text { margin: 0; flex: 1 1 240px; font-size: var(--font-size-md); }
.cbl-prefooter__cta {
  display: inline-block;
  margin-left: auto;
  padding: 17px 34px;
  border: 1px solid var(--color-text-invert);
  color: var(--color-text-invert);
  font-family: var(--typography-ui-font-family);
  font-weight: 500;
  font-size: var(--font-size-xs);
  letter-spacing: 0.12em;
  line-height: 1;
  text-transform: uppercase;
  text-decoration: none;
  transition: background-color var(--motion-fast) var(--motion-ease),
              color var(--motion-fast) var(--motion-ease);
}
.cbl-prefooter__cta:hover { background: var(--color-primary); border-color: var(--color-primary); color: var(--color-text); }
/* Garde (A4) : .cbl-prefooter__cta porte déjà le bouton complet. Un partial qui
   y ajoute cbl-btn--primary repeindrait le fond en jaune sous du texte blanc
   (2,0:1). Le modificateur est neutralisé ici plutôt que débattu. */
.cbl-prefooter__cta.cbl-btn--primary {
  background: transparent;
  border-color: var(--color-text-invert);
  color: var(--color-text-invert);
}
.cbl-prefooter__cta.cbl-btn--primary:hover {
  background: var(--color-primary);
  border-color: var(--color-primary);
  color: var(--color-text);
}

.cbl-footer { background: var(--color-footer-bg); color: var(--color-footer-text); }
.cbl-footer__inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--spacing-xs);
  padding-block: 40px;
}
.cbl-footer__copy { margin: 0; font-size: 14px; text-align: center; }
.cbl-footer a { color: var(--color-footer-text); }
.cbl-footer a:hover { color: var(--color-primary); }

/* --------------------------------------------------------------------------
   14. Responsive — mobile first appliqué en retrait (~1024 px puis ~640 px)
   -------------------------------------------------------------------------- */
@media (max-width: 1024px) {
  :root { --font-size-4xl: 58px; --font-size-3xl: 36px; --layout-slider-height: 520px; }
  .cbl-cards--cols-4 .cbl-cards__inner { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  /* Les rangées sont posées EXPLICITEMENT (B6) : dans une grille, un élément
     placé est traité avant les éléments automatiques. Laisser la photo en
     `grid-row: auto` au milieu de rangées numérotées la renvoyait en rangée 4,
     donc plus de 1 000 px sous le texte, alors qu'elle est deuxième dans le DOM.
     L'ordre visuel suit maintenant l'ordre du DOM : titre, photo, années, panneau. */
  .cbl-tabs { grid-template-columns: minmax(0, 1fr); }
  .cbl-tabs__heading { grid-row: 1; }
  .cbl-tabs__media {
    grid-column: 1;
    grid-row: 2;
    height: auto;
    min-height: 0;
    max-height: 320px;
  }
  .cbl-tabs__nav { grid-column: 1; grid-row: 3; background: var(--color-accent); }
  .cbl-tabs__hint { grid-column: 1; grid-row: 4; }
  /* Les panneaux ne sont PAS placés hors de --ready : sans JS, ils doivent
     s'enchaîner en chronologie (rangées 5, 6, 7…) et non se superposer. Les
     rangées 1 à 4 étant toutes occupées par des éléments placés, le placement
     automatique ne peut plus les renvoyer avant la photo — le piège de B6. */
  .cbl-tabs__panel { grid-column: 1; background: var(--color-accent); }
  .cbl-tabs--ready .cbl-tabs__panel { grid-row: 5; }
  .cbl-richtext--with-media { min-height: 0; text-align: center; }
  .cbl-richtext--with-media > * { width: 100%; margin-inline: auto; }
  .cbl-richtext--with-media > h2::after { margin-inline: auto; }
  .cbl-richtext__media {
    position: static;
    width: 260px;
    height: 260px;
    margin: var(--spacing-lg) auto 0;
    transform: none;
  }
  .cbl-richtext__media.cbl-reveal { transform: translateY(40px); }
  .cbl-richtext__media.cbl-reveal--in { transform: none; }
  /* La photo n'est plus centrée par translateY : l'agrandissement se suffit. */
  .cbl-richtext__media.cbl-reveal--zoom { transform: scale(.72); }
  .cbl-richtext__media.cbl-reveal--zoom.cbl-reveal--in { transform: none; }
  .cbl-reveal--from-left { transform: translateX(-48px); }
  .cbl-image--round img { width: 260px; height: 260px; }
  .cbl-map { min-height: 0; display: block; padding-inline: 0; }
  .cbl-map__frame { position: static; height: 300px; }
  .cbl-map__link { position: static; }
  .cbl-map__panel { position: static; left: auto; right: auto; margin-left: 0; width: 100%; }
  .cbl-map__consent { position: static; max-width: none; margin: var(--spacing-md) var(--layout-gutter); }
  .cbl-map + .cbl-form--on-primary {
    width: 100%;
    margin-top: 0;
    margin-inline: 0;
  }
}

@media (max-width: 640px) {
  :root {
    --font-size-4xl: 38px;
    --font-size-3xl: 28px;
    --font-size-2xl: 20px;
    --font-size-xl: 22px;
    --font-size-lg: 17px;
    --spacing-xl: 48px;
    --spacing-2xl: 64px;
    --layout-slider-height: 420px;
    --layout-hero-height: 190px;
  }
  .cbl-topbar__inner { justify-content: center; gap: var(--spacing-sm); }
  .cbl-header__inner { padding-block: var(--spacing-sm); }
  .cbl-header__logo { height: 46px; }

  .cbl-nav__toggle { display: inline-flex; }
  .cbl-header .cbl-nav { margin-left: auto; }
  /* Le bandeau collant garde sa hauteur quand la liste passe en tiroir : le
     burger doit rester utilisable dedans (B5). */
  .cbl-nav--bar { display: flex; align-items: center; min-height: var(--layout-navbar-height); }
  .cbl-nav--bar .cbl-nav__toggle { margin-left: auto; }
  .cbl-nav--bar ul { margin-inline-start: 0; }
  .cbl-nav--bar a { border-radius: 0; }
  .cbl-nav ul {
    position: absolute;
    left: 0;
    right: 0;
    top: 100%;
    z-index: 60;
    flex-direction: column;
    gap: 0;
    padding-inline: var(--layout-gutter);
    background: var(--color-header-bg);
    box-shadow: var(--shadow-raised);
  }
  .cbl-nav a { padding-block: 14px; border-top: 1px solid rgba(35, 31, 32, 0.14); }
  /* Repliée dès que le JS a pris la main ; dépliée sinon. */
  .cbl-nav--collapsed ul { display: none; }
  .cbl-nav--open ul { display: flex; }

  .cbl-hero__title { font-size: var(--font-size-2xl); }
  .cbl-cards--cols-3 .cbl-cards__inner,
  .cbl-cards--cols-4 .cbl-cards__inner,
  .cbl-cards--cols-2 .cbl-cards__inner { grid-template-columns: minmax(0, 1fr); }
  .cbl-slider__prev, .cbl-slider__next { display: none; }
  .cbl-image--pastille { margin-block: -70px var(--spacing-md); }
  .cbl-richtext--on-primary { padding-block: var(--spacing-xl) 84px; }
  .cbl-image--pastille img { width: 140px; }
  .cbl-image--round img { width: 200px; height: 200px; }
  .cbl-prefooter { padding-block: var(--spacing-lg) var(--spacing-md); }
  .cbl-prefooter__inner { flex-direction: column; align-items: flex-start; padding-bottom: var(--spacing-lg); }
  .cbl-prefooter__cta { margin-left: 0; }
  .cbl-btn { padding: 15px 26px; }
  .cbl-totop { right: var(--spacing-sm); bottom: var(--spacing-sm); }
}

/* --------------------------------------------------------------------------
   15. Mouvement réduit et impression
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
  /* Pas de rotation, pas d'entrée lettre à lettre : pack.js n'écrit alors aucune
     transformation 3D et ne découpe pas le titre — le changement est direct. */
  .cbl-slider--ready { perspective: none; }
  .cbl-slider--ready .cbl-slider__track { transition: none; transform: none; }
}

@media print {
  .cbl-slider__controls,
  .cbl-nav__toggle,
  .cbl-totop,
  .cbl-popup { display: none !important; }
  .cbl-header, .cbl-nav--bar { position: static; box-shadow: none; }
  .cbl-slider--ready { perspective: none; }
  .cbl-slider--ready .cbl-slider__track { display: block; height: auto; transform: none !important; }
  .cbl-slider--ready .cbl-slider__slide { position: static; visibility: visible; transform: none !important; }
  body { color: #000; background: #fff; }
}
