@font-face{font-family:"Jost";font-style:normal;font-weight:100 900;font-display:swap;src:url("/assets/polices/jost-latin-ext.woff2") format("woff2-variations");unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}
@font-face{font-family:"Jost";font-style:normal;font-weight:100 900;font-display:swap;src:url("/assets/polices/jost-latin.woff2") format("woff2-variations");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}
/* ==========================================================================
   FEUILLE DE STYLE — engendrée à partir des jetons.

   Aucune valeur littérale de couleur, de taille ou d'espacement n'apparaît
   ici : uniquement des `var(--…)` dont chaque nom a été vérifié à la
   compilation. Une `var()` inexistante est ignorée en silence par le
   navigateur — c'est ainsi qu'une règle `color: var(--gris)` (le vrai jeton
   s'appelant `--c-gris`) est restée morte sur l'ancien site sans qu'aucun
   outil ne la signale.

   Organisation en couches (`@layer`) : la cascade est déclarée explicitement
   plutôt que subie. Une règle de composant l'emporte sur le socle sans
   dépendre de l'ordre d'écriture ni de la spécificité des sélecteurs — ce
   qui supprime la course au `!important`.
   ========================================================================== */

@layer socle, agencement, composants, ornements;

@layer socle {
/* ==========================================================================
   SOCLE — émis en tête de chaque page, avant toute règle de composant.

   Chaque déclaration ici corrige un défaut MESURÉ sur un moteur réel.
   Aucune n'est décorative. La justification est donnée en regard, parce
   qu'une ligne de reset sans justification devient un culte : on la recopie
   pendant dix ans après que le bug a été corrigé.

   Socle de compatibilité visé : Safari 16+, Chrome 120+, Firefox 128+.
   Justification : sur mobile aux États-Unis, WebKit est MAJORITAIRE (58,4 %
   du trafic, juillet 2026) — parce que tout navigateur sur iOS, « Chrome »
   compris, est WebKit ; aucun moteur alternatif n'a été livré sur iOS malgré
   l'ouverture du DMA en mars 2024. Safari est donc le facteur limitant, et
   c'est lui qui commande nos choix — pas Chrome.
   Source : StatCounter, export CSV brut, juillet 2026.
   ========================================================================== */

:root{
  --c-blanc: #ffffff;
  --c-creme: #f4f2ee;
  --c-encre: #1c1c1c;
  --c-gris: #6e6e6e;
  --c-gris-clair: #d8d6d2;
  --c-gris-sombre: #a9a9a9;
  --c-gris-sur-creme: #6e6e6e;
  --c-ligne: rgba(17,17,17,.16);
  --c-noir: #111111;
  --t-espacement-kicker: 0.22em;
  --t-graisse-texte: 300;
  --t-graisse-titres: 400;
  --t-interligne-texte: 1.65;
  --t-interligne-titres: 1.24;
  --t-police-texte: "Jost","Helvetica Neue",Arial,sans-serif;
  --t-police-titres: "Futura","Jost","Century Gothic",sans-serif;
  --s-kicker: .75rem;
  --s-texte: clamp(.95rem,.35vw + .88rem,1.0625rem);
  --s-titre-m: clamp(1.5rem, 1.1rem + 1.6vw, 4.5rem);
  --s-titre-xl: clamp(2.1rem, 2.2rem + 3.4vw, 9rem);
  --s-titre-xxl: clamp(2.9rem, 4rem + 5.9vw, 16rem);
  --e-hauteur-nav: 72px;
  --e-hauteur-nav-desktop: 102px;
  --e-logo-desktop: 49px;
  --e-logo-mobile: 33px;
  --e-marge-page: clamp(1.25rem,4.5vw,4.5rem);
  --e-rythme-section: clamp(3rem,7vw,6rem);
  --f-rayon-bouton: 999px;
  --f-transition: cubic-bezier(.22,.61,.36,1);
}

*, *::before, *::after { box-sizing: border-box; }

html {
  /* iOS gonfle automatiquement le texte de certains blocs au changement
     d'orientation (« text inflation »), produisant des tailles incohérentes.
     `100%` neutralise le gonflement SANS bloquer le zoom de l'utilisateur —
     `none` le bloquerait dans certains contextes, ce qui serait un échec
     WCAG 1.4.4.

     Portée réelle, à ne pas surestimer : Firefox n'implémente PAS cette
     propriété, sous aucun préfixe. Elle corrige WebKit et Blink, pas Gecko.
     Elle figure dans la quasi-totalité des resets diffusés, présentée comme
     une harmonisation entre navigateurs — ce qu'elle n'est pas. */
  -webkit-text-size-adjust: 100%;

  /* Déclarer le schéma de couleurs est ce qui dissuade un navigateur de
     réécrire lui-même les couleurs de la page. Samsung Internet — 4,5 % du
     mobile européen — propose un mode sombre qui INVERSE algorithmiquement
     les couleurs d'un site clair : teintes de marque altérées, contrastes
     détruits, textes illisibles sur les photos.
     `only light` et non `light` : le mot-clé `only` est ce qui signale que
     le site N'A PAS de thème sombre et refuse la conversion automatique.
     Avec `light` seul, Samsung applique quand même son algorithme.
     Le mécanisme reste imparfait — l'utilisateur peut forcer l'inversion
     dans les réglages, et les anciennes versions ignorent l'indication.
     Le design doit donc survivre à une inversion : aucune information
     portée par la seule couleur, logo sur fond transparent. */
  color-scheme: only light;

  /* Le navigateur peint son propre fond derrière la page. Sans couleur
     explicite ici, iOS 26 laisse apparaître des bandes blanches autour des
     barres translucides. */
  background-color: var(--c-creme);
}

/* La barre de défilement classique de Windows occupe ~15 px et RÉTRÉCIT le
   viewport : une page qui devient défilante après chargement décale tout son
   contenu horizontalement. macOS utilise des barres en surimpression — le
   défaut est donc invisible sur le Mac de celui qui développe.
   `stable` réserve la gouttière dès le départ.

   Sous `@supports` parce que la propriété est « Newly available » (déc. 2024)
   et non « Widely available » : sans support, on retrouve simplement le
   comportement actuel. Aucun risque. */
@supports (scrollbar-gutter: stable) {
  html { scrollbar-gutter: stable; }
}

/* Le défilement animé est agréable, et il est aussi un déclencheur reconnu
   de troubles vestibulaires. Il n'est donc activé QUE si l'utilisateur n'a
   pas demandé l'inverse au niveau du système. WCAG 2.3.3. */
@media (prefers-reduced-motion: no-preference) {
  html { scroll-behavior: smooth; }
}

body {
  margin: 0;
  background: var(--c-creme);
  color: var(--c-noir);
  font-family: var(--t-police-texte);
  font-weight: var(--t-graisse-texte);
  font-size: var(--s-texte);
  line-height: var(--t-interligne-texte);

  /* macOS a supprimé l'anticrénelage sous-pixel en 2018 (Mojave). L'objection
     classique contre `antialiased` — « il casse le rendu sous-pixel » — est
     donc caduque. Aujourd'hui il rétablit une graisse cohérente avec
     Windows et Linux. Aucun effet ailleurs que sur macOS. */
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;

  /* `clip` et NON `hidden`.
     `overflow-x: hidden` sur body crée un conteneur de défilement : tout
     `position: sticky` de la page s'y rattache au lieu de se rattacher à la
     page, et cesse de coller — d'abord sur Safari. `clip` coupe le
     débordement sans créer ce conteneur.
     L'ancien site portait `overflow-x: hidden` sur body. */
  overflow-x: clip;
}

/* Images et médias — trois règles, trois défauts distincts.
   `display:block` supprime l'espace fantôme sous l'image (héritage de
   l'alignement sur la ligne de base du texte).
   `max-width:100%` + `height:auto` empêchent le débordement tout en
   préservant le rapport d'aspect. */
img, svg, video, canvas { display: block; max-width: 100%; height: auto; }

/* Safari et Edge appliquent la taille minimale intrinsèque aux SVG en ligne,
   contrairement à Chrome et Firefox : un logo dans une grille explose la
   mise en page — sur Safari uniquement, donc invisible en développement.
   `min-width: 0` rétablit la réduction. */
.grille > *, .rangee > * { min-width: 0; }

a { color: inherit; text-decoration: none; }

/* iOS zoome la page au focus sur un champ dont le texte fait moins de 16px.
   La page se décale, et l'utilisateur reste zoomé après la sortie du champ.
   Ce comportement est volontaire chez Apple et ne sera pas corrigé : la
   seule parade est de ne jamais descendre sous 16px.

   Portée sous-estimée, et c'est un enjeu commercial direct : la règle vaut
   aussi dans les navigateurs intégrés d'Instagram, Facebook et LinkedIn,
   qui sont des WKWebView sur iOS. Un formulaire à 14px fait donc zoomer
   TOUT visiteur arrivant par les réseaux sociaux — au moment précis où il
   remplit le champ. Le seuil est calculé après transformation : un
   `transform: scale()` ne le contourne pas. */
input, select, textarea, button {
  font-family: inherit;
  font-size: max(16px, 1rem);
  color: inherit;
}

/* Cible tactile : 48 px.
   Quatre normes donnent quatre chiffres — WCAG 2.5.8 exige 24 px (niveau AA,
   contraignant), WCAG 2.5.5 recommande 44 px (AAA), Apple 44 pt, Material
   48 dp. Retenir 48 les satisfait toutes d'un seul nombre, ce qui supprime
   l'arbitrage plutôt que de le trancher au cas par cas.
   Les liens à l'intérieur d'un paragraphe sont exemptés par le critère
   lui-même (exception « Inline ») et ne sont donc pas visés ici. */
.btn, button, input, select, textarea, .nav__liens a {
  min-height: 48px;
  /* Supprime le délai de double-tap sans désactiver le zoom à deux doigts.
     `touch-action: none` le désactiverait — échec WCAG 1.4.4. */
  touch-action: manipulation;
}

/* Une ancre qui vise une section la place sous la barre fixe, donc hors de
   vue. La marge de défilement réserve la hauteur de la barre. */
[id] { scroll-margin-top: calc(var(--e-hauteur-nav) + 12px); }

/* Le contour de focus est la seule indication visuelle pour qui navigue au
   clavier. `:focus-visible` ne l'affiche PAS au clic à la souris, ce qui
   supprime la raison qu'ont les designers de le retirer — et donc la faute
   d'accessibilité qui suit (WCAG 2.4.7). */
:focus-visible {
  outline: 2px solid currentColor;
  outline-offset: 3px;
}

/* Texte réservé aux technologies d'assistance.
   `clip-path` et non `left: -9999px` : un élément déplacé hors écran est
   toujours une cible de défilement, et provoque un saut horizontal quand il
   reçoit le focus. */
.sr {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* Le lien d'évitement. Premier élément focalisable de la page : il permet
   de sauter la navigation, qui est identique sur les treize pages.
   WCAG 2.4.1, niveau A. */
.evitement {
  position: absolute;
  top: 0; left: 0;
  z-index: 200;
  padding: .75rem 1.25rem;
  background: var(--c-noir);
  color: var(--c-creme);
  transform: translateY(-120%);
}
.evitement:focus { transform: none; }

/* Coupure de sécurité globale. Tout ce qui bouge s'arrête si l'utilisateur
   a exprimé cette préférence au niveau du système. Une seule règle couvre
   toutes les animations du site, présentes et futures — c'est ce qui la
   rend fiable : on ne peut pas oublier d'y penser en ajoutant un composant. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
}

}

@layer agencement {

  /* Le contenu ne dépasse jamais la marge de page. Une seule règle porte
     cette contrainte, plutôt qu'un `padding` répété sur chaque section. */
  .sec, .hero__in, .pied {
    padding-inline: var(--e-marge-page);
  }

  .sec { padding-block: var(--e-rythme-section); }

  /* Grilles fluides. `auto-fit` + `minmax` produit le passage à une colonne
     SANS media query : la grille se réorganise selon la place disponible,
     pas selon une largeur d'écran devinée. C'est aussi ce qui la rend juste
     dans un conteneur étroit — une colonne latérale, un aperçu — là où une
     media query, qui interroge la fenêtre, se tromperait. */
  .grille { display: grid; gap: clamp(1.5rem, 3vw, 2.4rem); }
  .grille--2 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 20rem), 1fr)); }
  .grille--3 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 17rem), 1fr)); }
  .grille--4 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 13rem), 1fr)); }

  /* `min(100%, …)` est indispensable : sans lui, `minmax(20rem, 1fr)` force
     20rem même quand le conteneur est plus étroit, et la grille déborde
     horizontalement sur les petits écrans. */

  /* ---------- Socle du responsive ----------
     Un enfant de grille ou de boite flexible ne peut pas, par defaut,
     devenir plus etroit que son mot le plus long (`min-width:auto`). Ce mot
     impose alors une piste plus large que le conteneur, et la page deborde
     lateralement.

     Le defaut est invisible en francais et se declare a la traduction : il
     suffit d'un compose allemand. Mesure sur ce site avant correction :
     91 conteneurs sur 97 y etaient exposes, et le titre « Pour celles qui
     ne se reconnaissent plus » debordait de 17 px a 414 px de large — la
     resolution la plus frequente de Suisse.

     `min-width:0` retire cette taille minimale : l'enfant redevient libre
     de retrecir, et le mot trop long se coupe au lieu de pousser la page.
     https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_grid_layout/Grid_layout_and_overflow */
  :where(.pile, .rangee, .shead, .grille, main, section, article, header,
         footer, nav, div, ul, ol, dl) > * { min-width: 0; }

  /* Un mot plus long que sa colonne se coupe plutot que de deborder.
     `anywhere` et non `break-word` : seul le premier reduit reellement la
     largeur minimale intrinseque du bloc, donc empeche la piste de grille
     de deborder.

     MAIS il ne s'applique PAS aux titres. Applique aux titres, il coupait
     l'allemand en plein mot : « SCHENK / EN SIE », « MOMEN / T. ». Un
     titre coupe n'importe ou est pire que le probleme qu'on corrige.

     Les titres recoivent a la place :
       · `text-wrap: balance` — repartit les lignes harmonieusement
       · `hyphens: auto`      — coupe aux SYLLABES, selon le dictionnaire
                                de la langue declaree par <html lang>
     La cesure syllabique est correcte typographiquement ; la cesure
     arbitraire ne l'est jamais. */
  :where(p, li, dd, dt, figcaption) { overflow-wrap: anywhere; }

  :where(h1, h2, h3, h4, .titre) {
    hyphens: auto;
    /* Repli pour les moteurs sans dictionnaire de cesure : le mot deborde
       de sa boite mais ne casse plus la mise en page, car `min-width:0`
       plus haut a deja libere la piste de grille. */
    overflow-wrap: break-word;
  }

  /* `text-wrap: balance` n'est interoperable que depuis mai 2024. Sous
     @supports, les moteurs qui l'ignorent gardent une mise en ligne
     ordinaire — parfaitement lisible. */
  @supports (text-wrap: balance) {
    :where(h1, h2, h3, h4, .titre) { text-wrap: balance; }
  }

  .pile { display: grid; gap: clamp(2.4rem, 5vw, 4rem); }
  .rangee { display: flex; flex-wrap: wrap; gap: 1rem; align-items: center; }

  /* En-tête de section : deux colonnes sur grand écran, titre à gauche,
     chapô à droite. */
  .shead { display: grid; gap: 1.1rem; margin-bottom: clamp(1.6rem, 3.5vw, 2.6rem); }
  .shead__top {
    display: flex; justify-content: space-between; align-items: baseline;
    gap: 1rem; border-bottom: 1px solid var(--c-ligne); padding-bottom: .85rem;
  }
  @media (min-width: 64em) {
    .shead { grid-template-columns: 1fr 1fr; align-items: end; }
    .shead__top { grid-column: 1 / -1; }
  }
}

@layer composants {

  /* ---------- Typographie ---------- */
  .titre {
    font-family: var(--t-police-titres);
    font-weight: var(--t-graisse-titres);
    text-transform: uppercase;
    letter-spacing: -.015em;
    line-height: var(--t-interligne-titres);
    margin: 0;
    /* Le titre est saisi avec des retours à la ligne voulus par la
       rédaction. `pre-line` les respecte sans exiger de `<br>`, qui n'a
       aucune valeur sémantique et n'est pas annoncé par un lecteur d'écran. */
    white-space: pre-line;
  }
  /* Une capitale accentuée (Ç, É, À) descend sous la ligne quand l'interligne
     est très serré, et se lit alors comme une apostrophe de la ligne suivante. */
  .titre--accent { line-height: var(--t-interligne-titres); }

  .t-xxl { font-size: var(--s-titre-xxl); }
  .t-xl  { font-size: var(--s-titre-xl); }
  .t-md  { font-size: var(--s-titre-m); }
  .t-sm  { font-size: var(--s-texte); }

  .etiq {
    font-family: var(--t-police-titres);
    text-transform: uppercase;
    letter-spacing: var(--t-espacement-kicker);
    font-size: var(--s-kicker);
    font-weight: 400;
    color: var(--c-gris-sur-creme);
    margin: 0;
  }

  .chapo {
    font-size: clamp(1rem, .5vw + .95rem, 1.25rem);
    line-height: 1.55;
    max-width: 34ch;
    font-weight: 300;
    margin: 0;
  }

  /* La mesure de ligne. Entre 45 et 75 caractères : au-delà, l'œil perd la
     ligne suivante en revenant à la marge. `ch` suit la police, donc la
     contrainte reste juste quand la typographie change. */
  p { max-width: 68ch; }

  .txt-second { color: var(--c-gris-sur-creme); }
  .mention { font-size: .75rem; color: var(--c-gris-sur-creme); }

  /* ---------- Boutons ---------- */
  .btn {
    display: inline-flex; align-items: center; justify-content: center;
    gap: .7em;
    font-family: var(--t-police-titres);
    text-transform: uppercase;
    letter-spacing: .13em;
    font-size: var(--s-kicker);
    padding: 1.05em 2.1em;
    border: 1px solid currentColor;
    border-radius: var(--f-rayon-bouton);
    background: none; cursor: pointer;
    position: relative; overflow: hidden;
    transition: color .45s var(--f-transition);
    white-space: nowrap;
  }
  .btn > span { position: relative; z-index: 1; }
  .btn::before {
    content: ""; position: absolute; inset: 0;
    background: currentColor;
    transform: translateY(101%);
    transition: transform .5s var(--f-transition);
  }

  /* Le survol n'existe que pour un pointeur PRÉCIS. Sur tactile, un `:hover`
     non conditionné reste appliqué après le tap — le bouton demeure allumé
     jusqu'à ce qu'on touche ailleurs.
     `any-hover` serait le mauvais test : un portable tactile équipé d'une
     souris y répond « oui » et le défaut revient. */
  @media (hover: hover) and (pointer: fine) {
    .btn:hover::before { transform: none; }
    .btn--clair:hover  { color: var(--c-noir); }
    .btn--sombre:hover { color: var(--c-creme); }
    .btn--plein:hover  { color: var(--c-noir); }
  }
  /* L'état tactile réel, toujours présent, hors media query. */
  .btn:active { transform: translateY(1px); }

  .btn--clair  { color: var(--c-blanc); }
  .btn--sombre { color: var(--c-noir); }
  .btn--plein  {
    background: var(--c-noir); color: var(--c-creme);
    border-color: var(--c-noir);
  }
  .btn--plein::before { background: var(--c-creme); }

  /* ---------- Hero ---------- */
  .hero {
    position: relative;
    display: flex; align-items: flex-end;
    background: var(--c-noir);
    /* `svh` : la hauteur quand la barre du navigateur est DÉPLOYÉE.
       `vh` vaudrait la hauteur barre masquée — le contenu déborderait au
       chargement. `dvh` suivrait la barre en temps réel et provoquerait un
       recalcul de mise en page à chaque défilement.
       La ligne `vh` précède comme repli pour les moteurs anciens. */
    /* Sur un ecran BAS — telephone en paysage — reclamer toute la hauteur
       produit une bande illisible surmontee d'un menu fixe qui mange deja
       17 % de l'ecran. 99,78 % des telephones en paysage sont sous 480 px
       de haut. On borne donc la demande a une hauteur praticable. */
    min-height: 26rem;
    overflow: hidden;
  }
  @media (min-height: 30em) {
    .hero { min-height: 100vh; min-height: 100svh; }
  }
  .hero__img { position: absolute; inset: 0; }
  .hero__img img { width: 100%; height: 100%; object-fit: cover; object-position: center 28%; }
  .hero__img::after {
    content: ""; position: absolute; inset: 0;
    background: linear-gradient(180deg,
      rgb(0 0 0 / .55) 0%, rgb(0 0 0 / .12) 38%, rgb(0 0 0 / .72) 100%);
  }
  .hero__in {
    position: relative; z-index: 2; width: 100%;
    /* Le menu est `fixed` : il ne pousse rien. Sans reserve en haut, la
       ligne de reperes du hero passe DESSOUS et le logo recouvre le texte.
       Mesure avant correction, en paysage 852x393 : le logo chevauchait
       « Kaina Experience » sur 59x18 px. Invisible a la mesure de
       debordement, visible seulement en comparant les boites deux a deux. */
    padding-block: calc(var(--e-hauteur-nav) + 1rem) clamp(2.2rem, 5vw, 4rem);
    color: var(--c-blanc);
  }
  .hero__meta {
    display: flex; justify-content: space-between; align-items: baseline;
    gap: 1rem;
    border-bottom: 1px solid rgb(255 255 255 / .28);
    padding-bottom: .9rem;
    margin-bottom: clamp(1.4rem, 3.5vw, 2.4rem);
  }
  .hero__meta .etiq { color: rgb(255 255 255 / .82); }
  .hero .titre { color: var(--c-blanc); }
  .hero h1 span { display: block; overflow: hidden; }
  .hero h1 span i {
    display: block; font-style: normal;
    transform: translateY(102%);
    animation: monter .95s var(--f-transition) forwards;
  }
  .hero h1 span:nth-child(2) i { animation-delay: .10s; }
  .hero h1 span:nth-child(3) i { animation-delay: .20s; }
  @keyframes monter { to { transform: none; } }

  .hero__bas {
    display: flex; flex-wrap: wrap; gap: 1.5rem;
    justify-content: space-between; align-items: flex-end;
    margin-top: clamp(1.4rem, 3.5vw, 2.2rem);
  }
  .hero__bas p { margin: 0; color: rgb(255 255 255 / .9); max-width: 32ch; }

  /* ---------- Fonds de section ---------- */
  /* Le fond emporte SES couleurs de texte. Choisir « sombre » ne peut pas
     laisser un texte gris illisible : le couple est indissociable, et son
     contraste est calculé à la compilation. */
  .sec--sombre { background: var(--c-noir); color: var(--c-creme); }
  .sec--sombre .etiq { color: var(--c-gris-sombre); }
  .sec--sombre .chapo { color: var(--c-gris-clair); }
  .sec--blanc { background: var(--c-blanc); }

  /* ---------- Étapes ---------- */
  .etape { display: grid; gap: 1.4rem; align-items: start; }
  .etape__fig {
    position: relative; overflow: hidden;
    background: var(--c-gris-clair); margin: 0;
    /* Un conteneur arrondi + `overflow:hidden` ne découpe PAS un enfant
       animé en `transform` sur WebKit : les coins de l'image dépassent en
       carré. `isolation` force un contexte d'empilement et rétablit le
       découpage. Bug WebKit 98538, ouvert depuis 2012. */
    isolation: isolate;
  }
  .etape__fig img {
    width: 100%; aspect-ratio: 4 / 5; object-fit: cover;
    transition: transform 1.1s var(--f-transition);
  }
  @media (hover: hover) and (pointer: fine) {
    .etape:hover .etape__fig img { transform: scale(1.035); }
  }
  .etape__n {
    position: absolute; top: 1rem; left: 1rem; z-index: 2;
    color: var(--c-blanc);
    font-family: var(--t-police-titres);
    font-size: var(--s-kicker); letter-spacing: .2em;
    text-shadow: 0 1px 12px rgb(0 0 0 / .5);
  }
  .etape__b > * + * { margin-top: .55rem; }
  .etape__b p { color: var(--c-gris-sur-creme); max-width: 46ch; }

  @media (min-width: 48em) {
    .etape { grid-template-columns: 1fr 1fr; gap: clamp(1.8rem, 4vw, 3.5rem); }
  }
  @media (min-width: 64em) {
    .etape { gap: clamp(2.5rem, 5vw, 5rem); align-items: center; }
  }
  /* Aucun `order` n'alterne l'image d'un côté puis de l'autre : un ordre
     visuel qui contredit l'ordre du DOM casse la navigation au clavier —
     le focus saute de droite à gauche sans logique apparente (WCAG 1.3.2).
     L'alternance, si elle est voulue, doit venir d'un ordre réellement
     différent dans le contenu, pas d'une inversion visuelle. */

  /* ---------- Listes ---------- */
  .l-puces { list-style: none; margin: 0; padding: 0; display: grid; gap: .5rem; }
  .l-puces li { display: grid; grid-template-columns: auto 1fr; gap: .6rem; }
  .l-puces li::before {
    content: ""; width: 5px; height: 5px; border-radius: 50%;
    background: currentColor; margin-top: .62em;
  }

  .l-filets {
    list-style: none; margin: 0; padding: 0;
    border-top: 1px solid var(--c-ligne);
    counter-reset: filet;
  }
  .l-filets li {
    counter-increment: filet;
    padding-block: clamp(.95rem, 2.2vw, 1.5rem);
    border-bottom: 1px solid var(--c-ligne);
    display: grid; grid-template-columns: auto 1fr; gap: 1.1rem;
    align-items: baseline;
  }
  /* Le numéro est engendré par CSS, donc absent du texte : un lecteur
     d'écran ne l'annonce pas, ce qui est correct — l'ordre est déjà porté
     par la liste elle-même. */
  .l-filets li::before {
    content: counter(filet, decimal-leading-zero);
    font-family: var(--t-police-titres);
    font-size: var(--s-kicker); letter-spacing: .16em;
    color: var(--c-gris-sur-creme);
  }
  .sec--sombre .l-filets { border-color: rgb(255 255 255 / .18); }
  .sec--sombre .l-filets li { border-color: rgb(255 255 255 / .18); }
  .sec--sombre .l-filets li::before { color: var(--c-gris-sombre); }
  /* Le titre et la description de la puce sont sur la MÊME ligne, séparés
     par une espace — comme dans le modèle d'origine. Les empiler double la
     hauteur de la liste : mesuré à 291 px par puce contre 77 px attendus,
     soit 1300 px de trop sur la section. L'écart ne se voit pas sur une
     capture partielle ; il se voit en comparant les hauteurs calculées. */
  .l-filets b { font-weight: inherit; }
  .l-filets b::after { content: " "; }
  .li__d { color: var(--c-gris-sur-creme); }
  .sec--sombre .li__d { color: var(--c-gris-clair); }
  @media (min-width: 48em) {
    .l-filets li { grid-template-columns: 5rem 1fr; }
  }

  .l-nue { list-style: none; margin: 0; padding: 0; }

  /* ---------- Cartes ---------- */
  .carte {
    display: flex; flex-direction: column;
    background: var(--c-blanc);
    border: 1px solid var(--c-ligne);
  }
  .carte__fig { overflow: hidden; background: var(--c-gris-clair); margin: 0; isolation: isolate; }
  .carte__fig img {
    width: 100%; aspect-ratio: 4 / 5; object-fit: cover;
    object-position: center 30%;
    transition: transform 1.1s var(--f-transition);
  }
  @media (hover: hover) and (pointer: fine) {
    .carte:hover .carte__fig img { transform: scale(1.04); }
  }
  .carte__b {
    padding: clamp(1.3rem, 2.6vw, 1.9rem);
    display: flex; flex-direction: column; flex: 1; gap: .9rem;
  }
  .carte__t { display: flex; justify-content: space-between; align-items: baseline; gap: 1rem; }
  .carte__t .titre { margin: 0; }
  .carte__prix {
    font-family: var(--t-police-titres);
    font-size: 1.0625rem; white-space: nowrap;
  }
  .carte__d { margin: 0; color: var(--c-gris-sur-creme); font-size: .9375rem; }
  .carte__ul {
    list-style: none; margin: 0; padding: .95rem 0 0;
    display: grid; gap: .5rem;
    border-top: 1px solid var(--c-ligne);
  }
  .carte__ul li {
    display: grid; grid-template-columns: auto 1fr; gap: .6rem;
    font-size: .875rem; line-height: 1.5;
  }
  .carte__ul li::before {
    content: ""; width: 5px; height: 5px; border-radius: 50%;
    background: var(--c-noir); margin-top: .55em;
  }
  .carte .btn { margin-top: auto; align-self: flex-start; }
  .marque {
    font-family: var(--t-police-titres);
    font-size: var(--z-kicker); letter-spacing: .18em; text-transform: uppercase;
    background: var(--c-noir); color: var(--c-creme);
    padding: .42em .8em; align-self: flex-start;
  }

  /* Le titre de carte est le lien. Le soulignement animé indique
     l'interactivité autrement que par la seule couleur — un daltonien ne
     distingue pas un titre cliquable d'un titre ordinaire si la couleur est
     le seul indice (WCAG 1.4.1). */
  .carte__t .titre a { position: relative; display: inline-block; }
  .carte__t .titre a::after {
    content: ""; position: absolute; left: 0; right: 0; bottom: .06em;
    height: 1px; background: currentColor;
    transform: scaleX(0); transform-origin: left;
    transition: transform .45s var(--f-transition);
  }
  @media (hover: hover) and (pointer: fine) {
    .carte__t .titre a:hover::after { transform: scaleX(1); }
  }

  /* ---------- Tableau de prix ---------- */
  /* Une vraie table : la relation entre l'intitulé et son prix est portée
     par le balisage. Les `<div>` en flex qui l'imitent perdent cette
     relation, et un lecteur d'écran annonce alors des montants sans dire
     de quoi il s'agit (WCAG 1.3.1). */
  .tarifs { width: 100%; border-collapse: collapse; border-top: 1px solid var(--c-ligne); }
  .tarifs th, .tarifs td {
    text-align: left; font-weight: inherit;
    padding-block: clamp(.85rem, 2vw, 1.2rem);
    border-bottom: 1px solid var(--c-ligne);
    vertical-align: baseline;
  }
  .tarifs th { max-width: 44ch; }
  .tarifs td {
    font-family: var(--t-police-titres);
    text-align: right; white-space: nowrap;
    /* Les chiffres s'alignent verticalement colonne par colonne : les prix
       d'une liste se comparent alors d'un coup d'œil. */
    font-variant-numeric: tabular-nums;
  }

  /* ---------- Dépliants ---------- */
  .dep__grille { border-top: 1px solid var(--c-ligne); }
  .dep { border-bottom: 1px solid var(--c-ligne); }
  .dep__q {
    display: flex; justify-content: space-between; align-items: center;
    gap: 1.2rem; cursor: pointer;
    padding-block: clamp(1rem, 2.4vw, 1.45rem);
    font-family: var(--t-police-titres);
    text-transform: uppercase; letter-spacing: .04em;
    font-size: clamp(.9375rem, 1.5vw, 1.125rem);
    list-style: none;
  }
  /* Le marqueur natif est remplacé par un signe dessiné ; il faut le retirer
     dans les deux syntaxes, la propriétaire restant nécessaire sur WebKit. */
  .dep__q::-webkit-details-marker { display: none; }
  .dep__i { position: relative; width: 13px; height: 13px; flex: none; }
  .dep__i::before, .dep__i::after {
    content: ""; position: absolute; background: currentColor;
    transition: transform .4s var(--f-transition);
  }
  .dep__i::before { inset: 6px 0 auto 0; height: 1.5px; }
  .dep__i::after  { inset: 0 6px 0 auto; width: 1.5px; }
  .dep[open] .dep__i::after { transform: scaleY(0); }
  .dep__r { color: var(--c-gris-sur-creme); max-width: 62ch; }
  .dep__r p { margin: 0 0 1.2rem; }

  /* ---------- Bandeau défilant ---------- */
  .defilant {
    background: var(--c-noir); color: var(--c-creme);
    padding-block: .95rem;
    overflow: hidden; white-space: nowrap;
  }
  .defilant__t { display: inline-flex; gap: 2.5rem; animation: glisser 34s linear infinite; }
  .defilant__t span {
    font-family: var(--t-police-titres);
    text-transform: uppercase; letter-spacing: .2em;
    font-size: var(--s-kicker);
  }
  @keyframes glisser { to { transform: translateX(-50%); } }

  /* ---------- Figures ---------- */
  .fig--large { margin: clamp(2.4rem, 5vw, 3.5rem) 0 0; overflow: hidden; isolation: isolate; }
  .fig--large img { width: 100%; aspect-ratio: 3 / 2; object-fit: cover; }

  /* ---------- Citations ---------- */
  .cit { margin: 0; padding-left: 1.2rem; border-left: 2px solid var(--c-ligne); }
  .cit cite { display: block; font-style: normal; font-size: .875rem; color: var(--c-gris-sur-creme); margin-top: .6rem; }
  .cite__r { color: var(--c-gris-sur-creme); }
}


  /* ---------- Navigation ---------- */
  .nav {
    position: fixed; inset: 0 0 auto 0; z-index: 100;
    height: var(--e-hauteur-nav);
    display: flex; align-items: center; justify-content: space-between;
    padding-inline: var(--e-marge-page);
    /* `difference` rend le logo lisible sur toute image de hero, claire ou
       sombre, sans avoir à choisir une variante par page.

       MAIS il est porté par les ENFANTS de la barre, jamais par la barre
       elle-même. Raison : `mix-blend-mode` cree un CONTEXTE D'EMPILEMENT.
       Appliqué à `.nav`, il enfermait le menu de langue dans ce contexte —
       son `z-index: 20` ne valait plus que DANS la barre, et le hero
       (`z-index: 2` au niveau du document) se dessinait par-dessus.

       Le symptôme était trompeur : le trait du hero traversait le panneau.
       On corrige d'abord la composition (le panneau ne fond plus), et le
       panneau restait quand même dessous — parce que le vrai problème
       était l'empilement, créé par ce même fondu.

       En descendant le fondu d'un niveau, la barre ne crée plus de
       contexte : le panneau retrouve le contexte du document, où son
       `z-index` compte face au hero. */
    transition: background .4s var(--f-transition);
  }
  .nav > :where(.nav__logo, .nav__liens, .burger) {
    mix-blend-mode: difference;
  }
  .nav.opaque > :where(.nav__logo, .nav__liens, .burger) {
    mix-blend-mode: normal;
  }
  .nav.opaque {
    background: var(--c-creme);
    border-bottom: 1px solid var(--c-ligne);
  }
  .nav__logo { display: flex; align-items: center; height: 100%; }
  .nav__logo img { height: var(--e-logo-mobile); width: auto; filter: invert(1); }
  .nav.opaque .nav__logo img { filter: none; }

  .nav__liens { display: none; gap: clamp(1.2rem, 2.4vw, 2.6rem); align-items: center; }
  .nav__liens a {
    font-family: var(--t-police-titres); text-transform: uppercase;
    letter-spacing: .13em; font-size: var(--s-kicker);
    color: var(--c-blanc);
    display: inline-flex; align-items: center;
    position: relative;
  }
  .nav.opaque .nav__liens a { color: var(--c-noir); }
  .nav__liens a::after {
    content: ""; position: absolute; left: 0; right: 0; bottom: .8rem; height: 1px;
    background: currentColor; transform: scaleX(0); transform-origin: left;
    transition: transform .45s var(--f-transition);
  }
  @media (hover: hover) and (pointer: fine) {
    .nav__liens a:hover::after { transform: scaleX(1); }
  }

  .burger {
    display: flex; flex-direction: column; justify-content: center; gap: 5px;
    width: 48px; background: none; border: 0; cursor: pointer;
    padding: 0; margin-right: -6px; align-items: flex-end;
  }
  .burger span {
    display: block; height: 1.5px; width: 22px; background: var(--c-blanc);
    transition: transform .4s var(--f-transition), width .4s var(--f-transition);
  }
  .nav.opaque .burger span { background: var(--c-noir); }
  .burger span:nth-child(2) { width: 16px; }
  body.menu-ouvert .burger span:nth-child(1) { transform: translateY(3.25px) rotate(45deg); }
  body.menu-ouvert .burger span:nth-child(2) { width: 22px; transform: translateY(-3.25px) rotate(-45deg); }

  .menu {
    position: fixed; inset: 0; z-index: 99;
    background: var(--c-creme);
    display: flex; flex-direction: column; justify-content: center;
    padding: var(--e-hauteur-nav) var(--e-marge-page) var(--e-marge-page);
    /* `clip-path` plutôt que `display:none` : l'animation d'ouverture est
       possible, et le contenu reste dans l'arbre d'accessibilité. */
    clip-path: inset(0 0 100% 0);
    transition: clip-path .7s var(--f-transition);
    pointer-events: none;
  }
  body.menu-ouvert .menu { clip-path: inset(0 0 0 0); pointer-events: auto; }
  .menu a {
    font-family: var(--t-police-titres); text-transform: uppercase;
    font-size: clamp(2rem, 9vw, 4rem); line-height: var(--t-interligne-titres);
    padding-block: .22em; border-bottom: 1px solid var(--c-ligne);
  }
  .menu__pied { margin-top: auto; padding-top: 2rem;
    color: var(--c-gris-sur-creme); font-size: .8125rem; }

  /* ---------- Fil d'Ariane ---------- */
  .fil { padding: 1.1rem var(--e-marge-page); border-bottom: 1px solid var(--c-ligne);
    margin-top: var(--e-hauteur-nav); }
  .fil ol { list-style: none; display: flex; flex-wrap: wrap; gap: .55rem;
    margin: 0; padding: 0;
    font-family: var(--t-police-titres); text-transform: uppercase;
    letter-spacing: .16em; font-size: var(--z-kicker); color: var(--c-gris-sur-creme); }
  .fil li + li::before { content: "/"; margin-right: .55rem; color: var(--c-gris-clair); }
  .fil [aria-current] { color: var(--c-noir); }

  /* ---------- Déroulé horaire ---------- */
  .deroule { margin: 0; border-top: 1px solid var(--c-ligne); }
  .deroule__l {
    display: grid; gap: .3rem;
    padding-block: clamp(1.1rem, 2.4vw, 1.6rem);
    border-bottom: 1px solid var(--c-ligne);
  }
  .deroule dt {
    font-family: var(--t-police-titres); font-size: var(--s-kicker);
    letter-spacing: .18em; text-transform: uppercase;
    color: var(--c-gris-sur-creme);
  }
  .deroule dd { margin: 0; }
  .deroule__t { font-family: var(--t-police-titres); font-size: var(--s-titre-m);
    text-transform: uppercase; line-height: var(--t-interligne-titres); margin: 0 0 .4rem; }
  .deroule dd p { margin: 0; color: var(--c-gris-sur-creme); max-width: 52ch; }
  @media (min-width: 48em) {
    .deroule__l { grid-template-columns: 7.5rem 1fr; gap: 1.5rem; align-items: baseline; }
  }

  /* ---------- Prix ---------- */
  .prix { display: flex; flex-wrap: wrap; align-items: baseline; gap: .8rem 1.4rem;
    padding-block: 1.2rem; border-block: 1px solid var(--c-ligne);
    margin-bottom: 1.4rem; }
  .prix__m { margin: 0; font-family: var(--t-police-titres);
    font-size: clamp(1.6rem, 3.4vw, 2.4rem); font-weight: 400; }
  .prix__m strong { font-weight: inherit; }
  .prix__d { color: var(--c-gris-sur-creme); font-size: .875rem;
    font-family: var(--t-police-texte); }

  /* ---------- Exergue ---------- */
  .exergue {
    margin: 0; padding: clamp(2.5rem, 6vw, 4.5rem) var(--e-marge-page);
    background: var(--c-noir); color: var(--c-creme);
    font-family: var(--t-police-titres); text-transform: uppercase;
    font-size: clamp(1.3rem, 3.4vw, 2.4rem); line-height: var(--t-interligne-titres);
    text-align: center;
  }
  .exergue p { margin: 0 auto; max-width: 24ch; }
  .exergue cite { display: block; margin-top: 1.2rem; font-style: normal;
    font-size: var(--s-kicker); letter-spacing: .18em; color: var(--c-gris-sombre); }

  /* ---------- Moments ---------- */
  .moment { display: grid; gap: 1.4rem; align-items: center; }
  .moment__fig { margin: 0; overflow: hidden; background: var(--c-gris-clair);
    isolation: isolate; }
  .moment__fig img { width: 100%; aspect-ratio: 4 / 5; object-fit: cover; }
  .moment__b > * + * { margin-top: .6rem; }
  .moment .cit { border-left: 2px solid var(--c-ligne); padding-left: 1.1rem;
    font-style: italic; }
  @media (min-width: 48em) {
    .moment { grid-template-columns: 1fr 1fr; gap: clamp(1.8rem, 4vw, 3.5rem); }
  }

  /* ---------- Colonnes inclus / non inclus ---------- */
  .colonne ul { list-style: none; margin: .9rem 0 0; padding: 0;
    border-top: 1px solid var(--c-ligne); }
  .colonne li { padding-block: .85rem; border-bottom: 1px solid var(--c-ligne);
    display: grid; grid-template-columns: auto 1fr; gap: .75rem;
    align-items: baseline; font-size: .9375rem; }
  .colonne li::before { content: ""; width: 5px; height: 5px; border-radius: 50%;
    background: var(--c-noir); margin-top: .55em; }
  /* La liste « non inclus » se distingue par la couleur ET par la puce
     évidée : la couleur seule ne suffit pas (WCAG 1.4.1). */
  .l-exclue li { color: var(--c-gris-sur-creme); }
  .l-exclue li::before { background: none; box-shadow: inset 0 0 0 1px var(--c-gris-clair); }

  /* ---------- Annuaire ---------- */
  .recherche { display: grid; gap: .5rem; margin-bottom: 1.2rem; max-width: 34rem; }
  .recherche label { font-family: var(--t-police-titres); text-transform: uppercase;
    letter-spacing: var(--t-espacement-kicker); font-size: var(--s-kicker);
    color: var(--c-gris-sur-creme); }
  .recherche input { border: 1px solid var(--c-ligne); background: var(--c-blanc);
    padding: .8em 1em; border-radius: 0; }
  #compte { margin: 0; font-size: .8125rem; color: var(--c-gris-sur-creme); }

  .filtres { display: flex; flex-wrap: wrap; gap: .5rem; margin-bottom: 1.6rem; }
  .filtres button {
    font-family: var(--t-police-titres); text-transform: uppercase;
    letter-spacing: .12em; font-size: var(--s-kicker);
    padding: .7em 1.2em; border: 1px solid var(--c-ligne);
    border-radius: var(--f-rayon-bouton); background: none; cursor: pointer;
  }
  /* L'état actif se lit par le fond ET par `aria-pressed` : visuel et
     programmatique portent la même information. */
  .filtres button[aria-pressed="true"] {
    background: var(--c-noir); color: var(--c-creme); border-color: var(--c-noir);
  }

  .fiches { display: grid; gap: clamp(1rem, 2vw, 1.4rem); }
  .fiche { display: grid; grid-template-columns: auto 1fr; gap: 1.1rem;
    padding: clamp(1.1rem, 2.2vw, 1.5rem);
    border: 1px solid var(--c-ligne); background: var(--c-blanc); }
  .fiche[hidden] { display: none; }
  .fiche__logo { margin: 0; width: 48px; height: 48px; flex: none;
    display: grid; place-items: center;
    border: 1px solid var(--c-ligne); }
  .fiche__m { font-family: var(--t-police-titres); font-size: .8125rem;
    letter-spacing: .06em; }
  .fiche__b > * + * { margin-top: .5rem; }
  .fiche__b .titre { font-size: var(--s-texte); }
  .fiche__meta { display: flex; flex-wrap: wrap; gap: .4rem .9rem; margin: 0;
    font-family: var(--t-police-titres); text-transform: uppercase;
    letter-spacing: .12em; font-size: var(--z-kicker); color: var(--c-gris-sur-creme); }
  .fiche__b p { font-size: .9375rem; margin: 0; }
  .fiche__angle { color: var(--c-gris-sur-creme); }
  .fiche__etat { color: var(--c-gris-sur-creme); font-size: .8125rem; }
  .fiche__lien a { text-decoration: underline; text-underline-offset: .2em; }
  @media (min-width: 64em) { .fiches { grid-template-columns: repeat(2, 1fr); } }

  /* ---------- Appel à l'action ---------- */
  .appel { background: var(--c-noir); color: var(--c-creme); text-align: center; }
  .appel .etiq { color: var(--c-gris-sombre); }
  .appel .titre { margin: 1rem auto clamp(1.4rem, 3vw, 2rem); max-width: 16ch; }
  .appel .chapo { margin-inline: auto; max-width: 46ch; color: var(--c-gris-clair); }
  .appel__f { display: flex; gap: .6rem; max-width: 520px;
    margin: clamp(1.8rem, 4vw, 2.6rem) auto 0; flex-wrap: wrap;
    justify-content: center; }
  .champ { flex: 1 1 240px; display: grid; gap: .4rem; text-align: left; min-width: 0; }
  .champ label { font-family: var(--t-police-titres); text-transform: uppercase;
    letter-spacing: var(--t-espacement-kicker); font-size: var(--s-kicker);
    color: var(--c-gris-sombre); }
  .champ input { background: none; border: 0;
    border-bottom: 1px solid rgb(255 255 255 / .4);
    color: var(--c-creme); padding: .7em .2em; min-width: 0; }
  .champ input::placeholder { color: rgb(255 255 255 / .45); }
  .champ input:focus-visible { outline: none; border-bottom-color: var(--c-creme); }
  .appel .mention { margin-top: 1.5rem; color: var(--c-gris-sombre); }

  /* ---------- Pied de page ---------- */
  .pied { background: var(--c-noir); color: var(--c-creme);
    padding: clamp(2.5rem, 5vw, 4rem) var(--e-marge-page) 2rem;
    border-top: 1px solid rgb(255 255 255 / .16); }
  .pied__haut { display: grid; gap: 2rem; padding-bottom: 2.5rem; }
  .pied__ident img { height: 34px; width: auto; }
  .pied__ident p { margin: 1.1rem 0 0; max-width: 32ch;
    color: var(--c-gris-sombre); font-size: .875rem; }
  .pied__t { font-family: var(--t-police-titres); text-transform: uppercase;
    letter-spacing: .18em; font-size: var(--z-kicker); font-weight: 400;
    color: var(--c-gris-sombre); margin: 0 0 .9rem; }
  /* `min-height:24px` et non une simple marge : WCAG 2.2 (2.5.8) exige
     24x24 px de CIBLE, pas d'espacement. Mesure avant correction : 23 px —
     l'echec d'un seul pixel, invisible a l'oeil et certain a la mesure.
     Le remplissage vertical agrandit la cible ET separe les liens, ce que
     la marge seule ne faisait pas. */
  .pied__col a { display: flex; align-items: center; min-height: 24px;
    color: rgb(255 255 255 / .82);
    font-size: .875rem; padding-block: .25rem; margin-bottom: .35rem; }
  @media (hover: hover) and (pointer: fine) {
    .pied__col a:hover { color: var(--c-blanc); }
  }
  .pied__bas { border-top: 1px solid rgb(255 255 255 / .16); padding-top: 1.5rem;
    display: flex; flex-wrap: wrap; gap: .8rem; justify-content: space-between;
    color: var(--c-gris-sombre); font-size: .75rem; }
  @media (min-width: 48em) { .pied__haut { grid-template-columns: 1.4fr 1fr 1fr 1fr; } }

  /* ---------- Page 404 ---------- */
  .sec--404 { min-height: 20rem;
    display: flex; flex-direction: column; justify-content: center;
    padding-block: calc(var(--e-hauteur-nav) + 3rem) 5rem; }
  .sec--404 .l-puces { margin-top: 1.6rem; }

  /* ---------- Ecran BAS : telephone en paysage ----------
     La hauteur est ici la ressource rare, pas la largeur. Un menu fixe de
     72 px sur 414 px de haut consomme 17 % de l'ecran en permanence.
     On interroge la HAUTEUR et non l'orientation : « orientation:landscape »
     est vrai aussi bien pour un telephone a 852x393 que pour un ecran de
     bureau a 2560x1440, et le clavier logiciel le declenche a tort en
     portrait.
     https://developer.mozilla.org/en-US/docs/Web/CSS/@media/orientation */
  @media (max-height: 30em) {
    :root { --e-hauteur-nav: 3rem; }
    .hero__in { padding-bottom: 1.2rem; }
  }

  /* ---------- Grand écran ---------- */
  @media (min-width: 64em) {
    :root { --e-hauteur-nav: var(--e-hauteur-nav-desktop); }
    .nav__logo img { height: var(--e-logo-desktop); }
    .nav__liens { display: flex; }
    .burger { display: none; }
  }


  /* ---------- Sélecteur de langue ---------- */
  /* `<details>` natif : ouverture, fermeture à Échap et navigation au
     clavier sont fournies par le navigateur. Un menu en JavaScript devrait
     réimplémenter les trois — et en oublierait au moins un. */
  .langues{position:relative;flex:none}
  .langues summary{
    display:flex;align-items:center;gap:.45rem;
    min-height:48px;padding:0 .6rem;cursor:pointer;list-style:none;
    font-family:var(--t-police-titres);text-transform:uppercase;
    letter-spacing:.1em;font-size:var(--s-kicker);
    color:var(--c-blanc);
  }
  .nav.opaque .langues summary{color:var(--c-noir)}
  .langues summary::-webkit-details-marker{display:none}
  .langues summary::after{
    content:"";width:.42em;height:.42em;border:1px solid currentColor;
    border-width:0 1px 1px 0;transform:translateY(-2px) rotate(45deg);
    transition:transform .25s var(--f-transition);
  }
  .langues[open] summary::after{transform:translateY(1px) rotate(-135deg)}
  /* ------------------------------------------------------------------
     REGLE DE SOCLE : tout panneau surgissant s'extrait de ses ancetres.

     Le probleme, constate en desktop : le menu de langue s'ouvre a
     l'interieur de `.nav`, qui porte `mix-blend-mode: difference` pour
     rendre le logo lisible sur n'importe quelle image de hero. Or un
     element fondu impose son mode a TOUTE sa descendance : le fond du
     menu se combinait avec le trait horizontal du hero, qui le traversait
     de part en part.

     Aucun `z-index` ne corrige cela. Ce n'est pas un probleme
     d'EMPILEMENT mais de COMPOSITION : le fondu s'applique avant que
     l'empilement n'entre en jeu.

     Deux proprietes suffisent, et elles vont par paire :
       · `mix-blend-mode: normal`  annule le fondu herite de l'ancetre
       · `isolation: isolate`      cree un contexte de composition propre,
                                   de sorte que les enfants du panneau ne
                                   refondent pas a leur tour

     La regle est deliberement portee par `:where()` : sa specificite est
     nulle, donc n'importe quelle regle de composant peut encore ajuster
     l'apparence du panneau sans avoir a lutter contre ce socle.

     La liste des selecteurs est le CONTRAT : tout panneau surgissant d'un
     site construit avec ce CMS porte `.surgissant`, `[role=menu]`, ou
     appartient au selecteur de langue. Le defaut devient alors
     inexprimable, quel que soit le fondu applique a la barre.
     ------------------------------------------------------------------ */
  :where(.langues ul, [role="menu"], .surgissant) {
    mix-blend-mode: normal;
    isolation: isolate;
  }

  .langues ul{
    position:absolute;top:100%;inset-inline-end:0;z-index:20;
    list-style:none;margin:.3rem 0 0;padding:.3rem;min-width:11rem;
    background:var(--c-creme);border:1px solid var(--c-ligne);
  }
  .langues li{margin:0}
  .langues ul a{
    display:flex;align-items:center;gap:.55rem;
    min-height:44px;padding:0 .7rem;color:var(--c-noir);
    font-family:var(--t-police-texte);font-size:.875rem;
    text-transform:none;letter-spacing:0;
  }
  @media (hover:hover) and (pointer:fine){
    .langues ul a:hover{background:var(--c-gris-clair)}
  }
  /* La langue courante se distingue par le fond ET par le gras : la couleur
     seule ne suffit pas (WCAG 1.4.1). */
  .langues ul a[aria-current]{background:var(--c-noir);color:var(--c-creme);font-weight:600}

  /* En-tête : masqué sur petit écran, où le sélecteur du pied prend le
     relais. Deux sélecteurs simultanés sur mobile encombreraient une barre
     déjà étroite. */
  .langues--entete{display:none}
  @media (min-width:64em){.langues--entete{display:block}}

  .langues--pied summary{color:var(--c-gris-sombre)}
  /* Le menu du pied s'ouvre VERS LE HAUT (il est en bas de page) et reste
     ancre a DROITE. Un ancrage a gauche le poussait hors de l'ecran : le
     resumé se trouve a x=279 sur un viewport de 414 px, et une liste de
     176 px depassait alors de 41 px. Le defaut etait invisible menu ferme.
     `max-width` garantit qu'aucune langue au nom long ne le fera deborder. */
  .langues--pied ul{bottom:100%;top:auto}
  .langues ul{max-width:calc(100vw - 2.5rem)}

@layer ornements {
  /* L'apparition au défilement. `opacity:0` par défaut est un pari : si le
     script ne s'exécute pas, le contenu reste invisible. On l'affiche donc
     par défaut, et le script AJOUTE l'état masqué avant d'animer — sans JS,
     la page est simplement moins animée, jamais vide.
     C'est l'inverse de l'ancien site, où six cartes restaient à `opacity:0`
     tant que le défilement ne les avait pas atteintes. */
  .anim { transition: opacity .85s var(--f-transition), transform .85s var(--f-transition); }
  .js .anim { opacity: 0; transform: translateY(22px); }
  .js .anim.vu { opacity: 1; transform: none; }
}
