/* LES POLICES SONT ICI, PLUS DANS UN @import.

   Un `@import` ne se découvre qu'APRÈS le téléchargement et l'analyse
   de cette feuille : le navigateur lance alors une seconde requête, et
   les polices arrivent bien après le premier rendu. Combiné à
   `font-display: swap`, le titre du héros s'affichait donc en police
   système puis basculait en Zodiak — un saut de 164 px de haut, très
   visible au rafraîchissement. C'est le scintillement signalé.

   Deux corrections : ces déclarations rejoignent la feuille principale
   (une requête en moins, et en cascade), et les trois fichiers du héros
   sont préchargés depuis le <head>. */
/* Polices servies depuis le site : aucun tiers, aucune requête sortante.
   Zodiak (serif à empattements taillés) et Switzer (grotesque neutre) —
   Indian Type Foundry, licence ITF Free Font, self-hosting autorisé.
   Le chemin est RELATIF : le site se relit sous un sous-chemin comme à
   la racine, et cette feuille est toujours chargée depuis la racine. */

@font-face {
  font-family: 'Zodiak';
  src: url('assets/polices/zodiak-300.woff2') format('woff2');
  font-weight: 300; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'Zodiak';
  src: url('assets/polices/zodiak-400.woff2') format('woff2');
  font-weight: 400; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'Zodiak';
  src: url('assets/polices/zodiak-400-italique.woff2') format('woff2');
  font-weight: 400; font-style: italic; font-display: swap;
}
@font-face {
  font-family: 'Switzer';
  src: url('assets/polices/switzer-400.woff2') format('woff2');
  font-weight: 400; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'Switzer';
  src: url('assets/polices/switzer-500.woff2') format('woff2');
  font-weight: 500; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'Switzer';
  src: url('assets/polices/switzer-600.woff2') format('woff2');
  font-weight: 600; font-style: normal; font-display: swap;
}


/* =====================================================================
   Aux Étangs de la Vieille Ferme — la feuille du site

   UNE SEULE feuille, pour les vingt-sept pages engendrées, ordonnée de
   la base vers le détail : palettes, rôles, socle, typographie, mise en
   page, composants.

   LA RÈGLE QUI TIENT TOUT. Les jetons nomment des RÔLES (--fond,
   --texte, --accent), jamais des pigments. Les --p-* n'alimentent QUE
   les rôles : aucune règle de cette feuille ne les emploie directement.
   Une couleur change alors sans qu'on relise rien — et c'est ce qui
   permettra au tableau de bord de piloter l'accent.
   ===================================================================== */

/* ─── Les palettes ───────────────────────────────────────────────────
   Un seul arrière-plan — l'ardoise — et quatorze accents. Le socle ne
   bouge jamais : seule la couleur d'accent change, ce qui rend la
   comparaison honnête.

   DEUX valeurs d'accent par palette, et c'est le point qui compte :

     --p-accent         CLAIR — il PORTE du texte sur l'arrière-plan
     --p-accent-bouton  SOUTENU — il REÇOIT du texte blanc
     --p-accent-photo   pour ce qui se pose SUR une photographie

   Une seule valeur imposerait du texte sombre sur un bouton clair.

   Les clartés ne sont pas choisies à l'œil : source/palette.py cherche,
   pour chaque teinte, celle qui atteint le contraste visé — 6,6 pour le
   texte d'accent, 7,4 pour le blanc sur le bouton. Et le chroma est
   calculé par rapport au maximum affichable à cette clarté, sans quoi
   un rouge éclairci vire au rose et un vert au pomme.
   ──────────────────────────────────────────────────────────────────── */
:root {
  --p-fond:    #0d1116;
  --p-fond-2:  #161c21;
  --p-surface: #1f262d;
  --p-texte:   #edf0f4;
  --p-texte-2: #a4aab1;
  --p-accent:        #d7807d;
  --p-accent-bouton: #9d2b3c;
  --p-accent-photo:  #e3a49f;
}

/* Bordeaux */
[data-accent="bordeaux"] {
  --p-accent:        #d7807d;
  --p-accent-bouton: #9d2b3c;
  --p-accent-photo:  #e3a49f;
}
/* Grenat */
[data-accent="grenat"] {
  --p-accent:        #d78270;
  --p-accent-bouton: #9e2c24;
  --p-accent-photo:  #e3a596;
}
/* Brique */
[data-accent="brique"] {
  --p-accent:        #d58461;
  --p-accent-bouton: #8d3e20;
  --p-accent-photo:  #e3a68c;
}
/* Terre cuite */
[data-accent="terre"] {
  --p-accent:        #c98b61;
  --p-accent-bouton: #804720;
  --p-accent-photo:  #e3a77f;
}
/* Cuivre */
[data-accent="cuivre"] {
  --p-accent:        #be8f60;
  --p-accent-bouton: #774c20;
  --p-accent-photo:  #e1a96e;
}
/* Ambre */
[data-accent="ambre"] {
  --p-accent:        #b29460;
  --p-accent-bouton: #6c5120;
  --p-accent-photo:  #d2af6e;
}
/* Laiton */
[data-accent="laiton"] {
  --p-accent:        #a99760;
  --p-accent-bouton: #655420;
  --p-accent-photo:  #c8b36e;
}
/* Olive */
[data-accent="olive"] {
  --p-accent:        #989d60;
  --p-accent-bouton: #56591f;
  --p-accent-photo:  #b4b96d;
}
/* Sauge */
[data-accent="sauge"] {
  --p-accent:        #64a769;
  --p-accent-bouton: #23622b;
  --p-accent-photo:  #74c67b;
}
/* Forêt */
[data-accent="forêt"] {
  --p-accent:        #66a590;
  --p-accent-bouton: #235f4f;
  --p-accent-photo:  #74c3a9;
}
/* Pétrole */
[data-accent="petrole"] {
  --p-accent:        #65a3a2;
  --p-accent-bouton: #235e5f;
  --p-accent-photo:  #75c1bf;
}
/* Bleu de nuit */
[data-accent="bleu"] {
  --p-accent:        #65a0bc;
  --p-accent-bouton: #235b76;
  --p-accent-photo:  #74bddf;
}
/* Aubergine */
[data-accent="aubergine"] {
  --p-accent:        #9d8fd3;
  --p-accent-bouton: #6a32bf;
  --p-accent-photo:  #b5aee1;
}
/* Prune */
[data-accent="prune"] {
  --p-accent:        #d177d5;
  --p-accent-bouton: #8d2b89;
  --p-accent-photo:  #dd9fe2;
}

/* Une couleur libre, pour le jour où le tableau de bord en proposera
   une : on donne la teinte, les trois valeurs se dérivent. Le navigateur
   qui ne connaît pas `oklch(from …)` garde l'accent choisi dans la
   liste — il ne casse rien. */
@supports (color: oklch(from red l c h)) {
  [data-accent="libre"] {
    --p-accent:        oklch(from var(--teinte-libre) .72 calc(c * .62) h);
    --p-accent-bouton: oklch(from var(--teinte-libre) .42 calc(c * .95) h);
    --p-accent-photo:  oklch(from var(--teinte-libre) .80 calc(c * .66) h);
  }
}

/* ─── LES RÔLES — c'est ce que les règles emploient ─────────────────── */
:root {
  --fond:          var(--p-fond);
  --fond-doux:     var(--p-fond-2);
  --fond-surface:  var(--p-surface);
  --texte:         var(--p-texte);
  --texte-doux:    var(--p-texte-2);
  --titre:         var(--p-texte);
  --accent:        var(--p-accent);
  --accent-bouton: var(--p-accent-bouton);
  --sur-accent:    #fff;
  --lisere:        color-mix(in srgb, var(--p-texte) 15%, transparent);

  /* --- la grille : douze colonnes, une gouttière constante ---------- */
  --colonnes:  12;
  --gouttiere: clamp(1rem, 2.2vw, 2.2rem);
  --large:     1480px;
  --moyen:     1040px;
  --etroit:     640px;

  /* --- typographie --------------------------------------------------
     Zodiak, serif à empattements taillés, pour le titrage ; Switzer,
     grotesque neutre, pour le reste. Le couple tient sur un axe de
     contraste, pas sur deux polices voisines. */
  --titrage:  "Zodiak", "Iowan Old Style", Georgia, "Times New Roman", serif;
  --courante: "Switzer", "Helvetica Neue", "Segoe UI", system-ui, sans-serif;

  --t-mention:  .84rem;
  --t-menu:     .95rem;
  --t-corps:    clamp(1rem, .97rem + .16vw, 1.0625rem);
  --t-chapo:    clamp(1.16rem, 1.06rem + .42vw, 1.36rem);
  --t-h4:       clamp(1.2rem, 1.12rem + .34vw, 1.44rem);
  --t-h3:       clamp(1.5rem, 1.32rem + .78vw, 1.95rem);
  --t-h2:       clamp(2.05rem, 1.6rem + 1.95vw, 3.2rem);
  --t-h1:       clamp(2.6rem, 1.8rem + 3.6vw, 5rem);
  --interligne: 1.7;

  /* --- rythme ------------------------------------------------------- */
  --e-1: .5rem;   --e-2: .875rem; --e-3: 1.5rem;  --e-4: 2.5rem;
  --e-5: clamp(2.5rem, 4.5vw, 4.5rem);
  --e-6: clamp(3.5rem, 6vw, 6.5rem);
  --marge-page: clamp(1.25rem, 5vw, 5rem);

  --rayon: 3px; --rayon-doux: 12px; --rayon-rond: 999px;

  /* Sorties exponentielles, jamais de rebond. */
  /* `--sortie` porte une DURÉE ET une courbe : elle s'écrit
     `transition: opacity var(--sortie)`, sans rien devant. Lui donner
     une durée — `opacity 300ms var(--courbe)` — fait des 380 ms un
     DÉLAI, et l'effet part avec quatre dixièmes de retard sans qu'aucune
     erreur ne le signale. Huit transitions du site en souffraient, dont
     le survol des boutons. Quand il faut une autre durée, c'est
     `--courbe` qu'on emploie. */
  --courbe:      cubic-bezier(.16, 1, .3, 1);
  --sortie:      380ms var(--courbe);
  --sortie-lent: 900ms var(--courbe);
  --sortie-court:180ms var(--courbe);

  /* --- empilement : une échelle NOMMÉE, jamais un 9999 -------------- */
  --z-fond: 0; --z-contenu: 1; --z-collant: 100; --z-entete: 200;
  --z-barre: 250; --z-voile: 300; --z-boite: 400; --z-alerte: 500; --z-bulle: 600;

  --haut-entete: 76px;   /* remesuré QUAND la classe change, pas
                            seulement au chargement */

  /* --- alias attendus par le module de réservation ------------------
     booking-widget.css est repris tel quel du parc et lit ces noms.
     --beige sert de #0d1116 de bouton avec du texte --ink dessus : elle
     doit rester claire par rapport à --ink, jamais l'accent. */
  /* LES ALIAS DU MODULE DE RÉSERVATION, définis par leur USAGE.

     Ces noms viennent de la charte de La Barbotte — un site CLAIR, où
     « ink » est une encre sombre et « cream » un fond crème. Ici le site
     est SOMBRE : traduits littéralement, ils donnaient un panneau gris
     clair (--ink-2) avec du texte sombre dessus (--cream), illisible et
     étranger à la page. On les mappe donc sur ce que le widget en FAIT,
     pas sur ce que leur nom raconte :

       --beige       le fond des boutons et des étapes franchies
       --beige-deep  ces mêmes fonds, au survol
       --ink         le texte POSÉ SUR --beige
       --ink-2       le fond du panneau
       --cream       le texte du panneau
       --ink-3       les filets et les bordures                        */
  --beige:      var(--p-accent-bouton);
  --beige-deep: color-mix(in srgb, var(--p-accent-bouton) 84%, black);
  --ink:        #ffffff;
  /* L'ARDOISE DU SITE, telle quelle. Je l'avais éclaircie en la mêlant
     à du blanc pour détacher le panneau du fond : cela a désaturé la
     teinte et donné un gris terne, étranger à la page. Un panneau se
     détache par son OMBRE et son filet, pas en changeant de couleur. */
  --ink-2:      var(--p-surface);
  --cream:      var(--p-texte);
  --ink-3:      color-mix(in srgb, var(--p-texte) 26%, transparent);
  --display: var(--titrage); --body: var(--courante);
  --fast: var(--sortie-court); --ease: cubic-bezier(.16, 1, .3, 1);
  --couleur-primaire: var(--accent); --couleur-secondaire: var(--titre);
  --couleur-fond: var(--fond); --couleur-texte: var(--texte);
}

/* Une section « douce » : le même fond, un cran plus clair. C'est ce qui
   donne le rythme — le site est entièrement sombre, il n'y a pas de
   bascule jour/nuit. */
.doux { background: var(--fond-doux); }

/* Ce qui est posé SUR une photographie impose ses couleurs : sans cela,
   un accent profond y peindrait le titre en sombre sur une image
   sombre. */
.sur-photo {
  --texte: #fff; --titre: #fff; --texte-doux: rgb(255 255 255 / .86);
  --accent: var(--p-accent-photo);
  --lisere: rgb(255 255 255 / .34);
  color: #fff;
}

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

html {
  /* Coupe le double-tap qui zoome ET les 300 ms d'attente avant chaque
     clic sur mobile. Le pincement, lui, reste possible. */
  touch-action: manipulation;
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--haut-entete) + 1.5rem);
  background: var(--fond);
}
body {
  margin: 0;
  background: var(--fond);
  color: var(--texte);
  font-family: var(--courante);
  font-size: var(--t-corps);
  line-height: var(--interligne);
  font-synthesis-weight: none;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  /* Filet de sécurité seulement : le vrai travail est de ne jamais
     produire de débordement, et de le MESURER sur douze formats. */
  overflow-x: clip;
}
img, picture, video, canvas, svg { display: block; max-width: 100%; }
img { height: auto; }
input, button, textarea, select { font: inherit; color: inherit; }
button { background: none; border: 0; padding: 0; cursor: pointer; }
ul, ol { margin: 0; padding: 0; list-style: none; }

/* =====================================================================
   TYPOGRAPHIE
   Chaque niveau a SA marge, exprimée dans sa propre taille (em) : elle
   suit alors la taille réelle du texte, y compris quand le clamp la
   réduit sur petit écran.
   ===================================================================== */
h1, h2, h3, h4 {
  font-family: var(--titrage);
  color: var(--titre);
  font-weight: 300;
  line-height: 1.07;
  letter-spacing: -.02em;
  margin: 0 0 .58em;
  /* La largeur se pose sur LE TITRE, en em : elle suit sa taille réelle.
     Posée sur le bloc qui le contient, un titre plus petit se retrouve
     étranglé sans raison. */
  text-wrap: balance;
}
h1 { font-size: var(--t-h1); max-width: 13em; line-height: 1.02; }
h2 { font-size: var(--t-h2); max-width: 15em; }
h3 { font-size: var(--t-h3); max-width: 19em; line-height: 1.16; font-weight: 400; margin-bottom: .5em; }
h4 { font-size: var(--t-h4); max-width: 24em; line-height: 1.3;  font-weight: 400; margin-bottom: .55em; }

/* L'emphase dans un titre se fait à l'ITALIQUE de la serif, et à
   l'accent. C'est la cadence de la maison — elle remplace le petit
   sur-titre en capitales espacées qu'on voit partout ailleurs. */
h1 em, h2 em, h3 em { font-style: italic; font-weight: 400; color: var(--accent); }

p { margin: 0 0 var(--e-3); max-width: 66ch; text-wrap: pretty; }
p:last-child { margin-bottom: 0; }
strong { font-weight: 600; }
a { color: inherit; }

.chapo {
  font-size: var(--t-chapo); line-height: 1.56;
  color: var(--texte-doux); max-width: 44ch; font-weight: 400;
  margin-bottom: 1.5em;
}
h1 + .chapo, h2 + .chapo { margin-top: -.15em; }
.mention { font-size: var(--t-mention); color: var(--texte-doux); }

/* `.apres` ne sert qu'à ESPACER. Elle ne touche pas au display, et
   c'est essentiel : la version qui posait `display: block` sur les div
   a mis les trois fiches de chambres en pleine largeur les unes sous
   les autres — la grille était écrasée par une classe d'espacement.
   Chaque composant garde son propre display ; `.apres` n'ajoute qu'une
   marge. */
.apres { margin-top: 2em; }

/* Le filet de la maison : il s'estompe à ses deux bouts, jamais un
   trait franc d'un bord à l'autre.

   `margin: 0` a été remplacé par `margin-inline: 0` : le raccourci
   écrasait le `margin-top` de `.apres`, posé plus haut dans la feuille.
   Le filet du pied se retrouvait à TROIS pixels du texte de la colonne
   la plus haute — mesuré — et paraissait le souligner. Un raccourci
   remet à zéro les quatre côtés, y compris ceux qu'on ne voulait pas
   toucher. */
.filet {
  border: 0; height: 1px; margin-inline: 0;
  background: linear-gradient(90deg, transparent, var(--lisere) 12%, var(--lisere) 88%, transparent);
}

/* =====================================================================
   MISE EN PAGE
   UNE SEULE enveloppe pour tout — en-tête, héros, sections, pied. C'est
   elle qui tient la colonne du site, et rien ne doit s'en échapper :
   l'en-tête à 72 px et le contenu à 172 px, c'est un écart qu'on voit
   au premier défilement.
   ===================================================================== */
.enveloppe {
  width: 100%; max-width: var(--large); margin-inline: auto;
  padding-inline: var(--marge-page);
}
.enveloppe--moyen  { max-width: var(--moyen); }
.enveloppe--etroit { max-width: var(--etroit); }

.section { padding-block: var(--e-6); position: relative; }
.section--serree { padding-block: var(--e-5); position: relative; }
.section__entete { margin-bottom: var(--e-5); max-width: 42rem; }
.section__entete > :last-child { margin-bottom: 0; }

/* Le bloc éditorial : image + texte partagent la MÊME ligne de départ,
   et l'image est la plus haute des deux. Le texte est borné à cinq
   colonnes ; au-delà, la ligne devient trop longue. */
.bloc { display: grid; gap: var(--e-4); grid-template-columns: 1fr; }
.bloc__media { margin: 0; }
.bloc__media img { width: 100%; height: auto; display: block; border-radius: var(--rayon-doux); }
.bloc__texte { align-self: start; }
.bloc__texte > :last-child { margin-bottom: 0; }
@media (min-width: 64rem) {
  .bloc {
    grid-template-columns: repeat(var(--colonnes), 1fr);
    gap: var(--gouttiere);
    /* `stretch` et non `start` : l'image prend la hauteur de la rangée.
       Mesuré sur le bloc du restaurant — l'image faisait 355 px et le
       texte 623 : elle avait l'air d'une vignette d'appoint posée à
       côté du texte, alors que c'est elle qui doit porter le bloc. Le
       TEXTE, lui, reste calé en haut (align-self sur .bloc__texte). */
    align-items: stretch;
  }
  .bloc__media { align-self: stretch; }
  .bloc__media img { height: 100%; object-fit: cover; }
  /* En grille, un élément qui arrive APRÈS dans le HTML et réclame des
     colonnes situées AVANT ne remonte pas de lui-même : il ouvre une
     rangée. Il faut lui dire sur quelle ligne il est. */
  .bloc > .bloc__media, .bloc > .bloc__texte, .bloc > .bloc__aside { grid-row: 1; }
  .bloc__media { grid-column: 1 / span 6; }
  .bloc__texte { grid-column: 8 / span 5; padding-top: .35rem; }
  .bloc--inverse .bloc__media { grid-column: 7 / span 6; }
  .bloc--inverse .bloc__texte { grid-column: 1 / span 5; }
  /* Une image PORTRAIT domine : cinq colonnes lui suffisent, et le
     texte en prend cinq aussi — sinon le bloc penche. */
  .bloc--portrait .bloc__media { grid-column: 1 / span 5; }
  .bloc--portrait .bloc__texte { grid-column: 7 / span 5; }
  .bloc--portrait.bloc--inverse .bloc__media { grid-column: 8 / span 5; }
  .bloc--portrait.bloc--inverse .bloc__texte { grid-column: 1 / span 5; }
  /* Deux colonnes de TEXTE : alignées en haut. `align-items: center` ne
     vaut que pour texte + image — entre deux textes, il décale les
     titres dès que les hauteurs diffèrent. */
  .bloc--texte .bloc__texte { grid-column: 1 / span 5; }
  .bloc--texte .bloc__aside { grid-column: 7 / span 6; }
}

/* Liste clé/valeur : une vraie grille à deux colonnes. Un min-width sur
   la clé ne suffit pas — chaque valeur démarrerait où finit sa clé. */
.paires { display: grid; gap: var(--e-2) var(--e-3); grid-template-columns: 1fr; margin: 0; }
.paires dt { color: var(--texte-doux); font-size: var(--t-mention); }
.paires dd { margin: 0; }
@media (min-width: 40rem) {
  .paires { grid-template-columns: minmax(8rem, 13rem) 1fr; }
  .paires dt { padding-top: .1em; }
}
.paires--serree { gap: .35rem var(--e-2); }
@media (min-width: 40rem) { .paires--serree { grid-template-columns: minmax(5.5rem, 7rem) 1fr; } }

/* Dans une colonne de pied, la place manque pour deux colonnes : le
   libellé se met AU-DESSUS de sa valeur, quelle que soit la largeur.
   Mesuré : « jeudi, vendredi & dimanche » tombait sur trois lignes,
   un mot par ligne. */
.pied .paires { grid-template-columns: 1fr; gap: 0; }
.pied .paires dt {
  font-size: .78rem; letter-spacing: .06em; text-transform: uppercase;
  color: var(--texte-doux); margin-top: var(--e-2);
}
.pied .paires dt:first-of-type { margin-top: 0; }
.pied .paires dd {
  color: var(--texte); margin-top: .15rem;
  /* Sans taille déclarée, une valeur d'horaire hérite du CORPS de texte
     (17 px) pendant que l'adresse et les liens voisins sont en
     « mention » (13,4 px) : les jours paraissaient deux crans plus gros
     que tout le reste du pied, sans raison. */
  font-size: var(--t-mention);
}
/* Tout le pied se lit à la même taille : le seul écart voulu est celui
   des titres de colonne. */
.pied { font-size: var(--t-mention); }
.pied .lien-icone { font-size: var(--t-mention); }

/* =====================================================================
   BOUTONS ET LIENS
   Jamais sur deux lignes : un bouton cassé perd sa forme de pilule et
   décentre son texte. C'est donc une contrainte de RÉDACTION autant que
   de style — les libellés restent courts.
   ===================================================================== */
.bouton {
  display: inline-flex; align-items: center; justify-content: center; gap: .6em;
  padding: .95em 1.9em;
  border: 0; border-radius: var(--rayon-rond);
  background: var(--accent-bouton);
  color: var(--sur-accent);
  font-family: var(--courante); font-size: var(--t-menu); font-weight: 500;
  letter-spacing: .005em; line-height: 1.2;
  white-space: nowrap; text-decoration: none; cursor: pointer;
  transition: background 260ms var(--courbe), transform 160ms var(--courbe);
}
.bouton:hover  { background: color-mix(in srgb, var(--accent-bouton) 84%, #fff); transform: translateY(-1px); }
.bouton:active { transform: translateY(0); }
.bouton svg { flex: none; width: 1.05em; height: 1.05em; }

/* Le second : une surface translucide, SANS trait. Une bordure grise de
   1 px est la forme la plus datée qui soit, et elle ne tient pas sur une
   photo — le trait disparaît sur les zones claires. */
.bouton--second {
  background: color-mix(in srgb, var(--texte) 11%, transparent);
  color: var(--texte);
}
.bouton--second:hover { background: color-mix(in srgb, var(--texte) 20%, transparent); color: var(--texte); }
/* Sur une photo : verre dépoli. C'est le seul endroit du site où le flou
   est employé, et il y est fonctionnel — il rend le libellé lisible quel
   que soit le pixel qui passe dessous. */
.sur-photo .bouton--second {
  background: rgb(255 255 255 / .14);
  backdrop-filter: blur(14px) saturate(1.2);
  color: #fff;
}
.sur-photo .bouton--second:hover { background: rgb(255 255 255 / .26); }

.boutons { display: flex; flex-wrap: wrap; gap: var(--e-2); align-items: center; }
/* Sous 420 px, un bouton prend toute la largeur plutôt que de tronquer. */
@media (max-width: 26.25rem) {
  .boutons, .boutons.apres { display: grid; gap: var(--e-2); }
  .boutons > .bouton { width: 100%; }
  .boutons .lien-trait { width: 100%; justify-content: flex-start; }
}

/* Un lien qui mêle une icône et du texte. Sans inline-flex, la
   réinitialisation svg{display:block} envoie l'icône seule sur sa
   ligne, au-dessus du texte. */
.lien-icone {
  display: inline-flex; align-items: center; gap: .55em;
  text-decoration: none; color: var(--accent); font-weight: 500;
}
.lien-icone svg { flex: none; width: 1.05em; height: 1.05em; }
.lien-icone:hover { text-decoration: underline; text-underline-offset: .28em; }

/* Le lien-trait : le trait s'allonge au survol. */
.lien-trait {
  display: inline-flex; align-items: center; gap: .6em;
  text-decoration: none; color: var(--accent);
  font-size: var(--t-menu); font-weight: 500;
}
.lien-trait::after {
  content: ""; flex: none; width: 1.5em; height: 1px;
  background: currentColor; transition: width var(--sortie);
}
.lien-trait:hover::after { width: 2.4em; }

/* =====================================================================
   L'EN-TÊTE
   ===================================================================== */
.entete {
  position: fixed; inset: 0 0 auto 0; z-index: var(--z-entete);
  padding-block: var(--e-2);
  /* Tant qu'il flotte sur la photo du héros, il impose ses couleurs —
     jetons compris, sinon le bouton reste peint en sombre sur la photo
     et devient invisible. */
  color: #fff;
  --texte: #fff; --accent: var(--p-accent-photo);
  --accent-bouton: color-mix(in srgb, var(--p-accent-bouton) 88%, #000);
  --lisere: rgb(255 255 255 / .3);
  transition: background 420ms var(--courbe), color 420ms var(--courbe),
              padding 420ms var(--courbe);
}
.entete__enveloppe { display: flex; align-items: center; gap: var(--e-3); }
/* Le fond ne se pose QU'UNE FOIS défilé : posé d'emblée, il forme une
   barre flottant sur rien. Et il est presque opaque — des photos passent
   dessous, à 88 % les libellés deviennent illisibles. */
.entete.pose {
  background: color-mix(in srgb, var(--p-fond) 97%, transparent);
  backdrop-filter: blur(14px);
  color: var(--p-texte);
  --texte: var(--p-texte); --accent: var(--p-accent);
  --accent-bouton: var(--p-accent-bouton); --sur-accent: #fff;
  --lisere: color-mix(in srgb, var(--p-texte) 16%, transparent);
  border-bottom: 1px solid var(--lisere);
  padding-block: calc(var(--e-2) * .66);
}
.entete__marque { display: block; flex: none; }
.entete__marque img { width: clamp(112px, 12vw, 152px); height: auto; }
.entete__nav { display: none; margin-left: auto; gap: clamp(1rem, 1.8vw, 1.9rem); }
@media (min-width: 64rem) { .entete__nav { margin-right: auto; } }
/* ENFANTS DIRECTS seulement. Écrite `.entete__nav a`, cette règle
   attrapait tout lien du panneau déroulant — et sa spécificité (0,1,1)
   battait `.sous-menu__vue` (0,1,0) : les trois aperçus, posés en
   `absolute`, retombaient en `relative`, s'empilaient dans le flux et
   le survol ne montrait plus rien. Le trait animé n'a de sens que sur
   les entrées de premier niveau ; à l'intérieur du panneau, c'est le
   fond de l'entrée survolée qui marque la position. */
.entete__nav > a,
.entete__nav > .sous-menu > a {
  text-decoration: none; font-size: var(--t-menu); color: inherit;
  position: relative; padding-block: .35em; white-space: nowrap;
}
.entete__nav > a::after,
.entete__nav > .sous-menu > a::after {
  content: ""; position: absolute; left: 0; right: 100%; bottom: .1em; height: 1px;
  background: currentColor; transition: right var(--sortie);
}
.entete__nav > a[aria-current]::after,
.entete__nav > .sous-menu > a[aria-current]::after { right: 0; }
@media (hover: hover) {
  .entete__nav > a:hover::after,
  .entete__nav > .sous-menu:hover > a::after { right: 0; }
}
.entete__actions { display: flex; gap: .6rem; align-items: center; }

/* Le sélecteur de langue : trois codes, pas un menu déroulant. À trois
   langues, un menu demande un geste de plus pour cacher deux mots. */
.langues {
  display: none; align-items: center; gap: .1rem;
  margin-left: auto; padding-right: .9rem;
  font-size: var(--t-mention); letter-spacing: .04em;
}
.langues a, .langues__actuelle {
  padding: .3rem .42rem; border-radius: calc(var(--rayon-doux) - 3px);
  text-decoration: none; color: var(--texte-doux);
  transition: color var(--sortie-court), background var(--sortie-court);
}
/* Le trait de la langue courante : un `box-shadow: inset` épousait le
   rayon du bouton et se dessinait en arc de cercle. Un vrai filet, posé
   en `::after`, reste droit. */
.langues__actuelle { color: var(--texte); background: none; position: relative; }
.langues__actuelle::after {
  content: ""; position: absolute; left: .42rem; right: .42rem; bottom: .12rem;
  height: 1px; background: currentColor;
}
@media (hover: hover) { .langues a:hover { color: var(--accent); } }
/* Sur la photo du héros, l'en-tête est clair : le sélecteur suit. */
.sur-photo .langues a, .entete .langues a { color: rgb(255 255 255 / .72); }
.entete .langues__actuelle { color: #fff; }
.entete .langues__actuelle::after { background: rgb(255 255 255 / .6); }
@media (min-width: 64rem) { .langues { display: flex; } }

/* Dans le menu plein écran, les mêmes trois codes, en ligne. Le pied
   est une GRILLE : sans `flex-direction: row` explicite et sans
   `justify-self`, les trois codes s'empilaient en colonne et poussaient
   le pied par-dessus la liste des pages. */
.voile-menu .langues {
  display: flex; flex-direction: row; justify-content: flex-start;
  justify-self: start; margin: 0; padding: 0; gap: .25rem;
  font-size: .95rem;
}
.voile-menu .langues a, .voile-menu .langues__actuelle {
  padding: .4rem .65rem; color: var(--texte-doux);
}
.voile-menu .langues__actuelle { color: var(--texte); }
@media (min-width: 64rem) { .entete__nav { display: flex; } }
@media (max-width: 63.99rem) { .entete__actions { display: none; } }

/* --- le bouton du menu ----------------------------------------------
   Deux traits FINS et courts, pas trois barres épaisses : le hamburger
   à trois barres grasses fait daté, et il est plus large qu'il n'a
   besoin. Au survol, le trait du haut s'allonge ; à l'ouverture, les
   deux se croisent. */
.menu-bouton {
  margin-left: auto;
  display: inline-flex; align-items: center; gap: .7em;
  color: inherit; font-size: var(--t-menu); font-weight: 500;
  padding: .55em .1em;
}
.menu-bouton__traits {
  position: relative; flex: none;
  width: 1.5rem; height: .65rem;
}
.menu-bouton__traits::before,
.menu-bouton__traits::after {
  content: ""; position: absolute; left: 0; height: 1.5px;
  background: currentColor; border-radius: 2px;
  transition: width var(--sortie), transform var(--sortie), top var(--sortie);
}
.menu-bouton__traits::before { top: 0; width: 100%; }
.menu-bouton__traits::after  { top: .5rem; width: 62%; }
.menu-bouton:hover .menu-bouton__traits::after { width: 100%; }
.menu-bouton[aria-expanded="true"] .menu-bouton__traits::before { top: .25rem; transform: rotate(45deg); }
.menu-bouton[aria-expanded="true"] .menu-bouton__traits::after  { top: .25rem; width: 100%; transform: rotate(-45deg); }
@media (min-width: 64rem) { .menu-bouton { display: none; } }

/* =====================================================================
   LE HÉROS

   PLEIN ÉCRAN, en `svh` et non `vh` : sur mobile, `vh` compte la barre
   d'adresse qui se rétracte, et le bas du héros passe sous le pli tant
   qu'on n'a pas fait défiler.

   ANCRÉ EN BAS. La règle générale veut qu'un héros soit ancré en haut,
   pour que le titre tombe à la même hauteur d'une page à l'autre. Sur un
   héros plein écran porté par l'image, elle produit l'inverse de ce
   qu'on cherche : le texte se tasse dans le tiers supérieur et laisse
   cinq cents pixels de vide dessous. Ancré en bas, ce qui devient
   constant d'une page à l'autre c'est la position de l'ACTION — le
   repère utile. Les pages intérieures utilisent `.heros--court`, dont la
   hauteur est fixe : le titre y retombe au même endroit.
   ===================================================================== */
.heros {
  position: relative; isolation: isolate;
  display: flex; flex-direction: column; justify-content: flex-end;
  min-height: 100svh;
  padding-top: calc(var(--haut-entete) + 2rem);
  padding-bottom: var(--e-4);
  overflow: hidden;
}
.heros--court { min-height: min(68svh, 40rem); }

/* --- le fond : quatre images en fondu lent -------------------------
   Pas un carrousel. Aucune flèche, aucune pastille : le visiteur n'a
   rien à piloter. Six secondes par image, deux de fondu — assez pour
   voir, trop lent pour distraire. Le TITRE ne change pas (sinon on ne
   peut pas le lire) ; seule la légende suit. */
.heros__fond { position: absolute; inset: 0; z-index: -1; }
.heros__vue {
  position: absolute; inset: 0;
  opacity: 0;
  transition: opacity 2s ease-in-out;
}
.heros__vue[data-vue-active] { opacity: 1; }
/* La première vue porte `data-vue-active` dès le HTML : sans script,
   elle reste donc affichée toute seule. Une règle `:first-child` en
   plus aurait la même spécificité que `[data-vue-active]` et, venant
   après, garderait la première vue visible SOUS toutes les autres —
   les quatre images se superposaient. */
.heros__vue img { width: 100%; height: 100%; object-fit: cover; }
@media (prefers-reduced-motion: no-preference) {
  .heros__vue[data-vue-active] img { animation: respire 22s ease-in-out both; }
}
@keyframes respire { from { transform: scale(1.005); } to { transform: scale(1.055); } }

/* Deux couches de voile : une verticale, pour que le bas porte le texte
   et que le ciel reste lisible en haut ; une horizontale côté gauche, là
   où le texte se pose. Sans elles, le contraste du titre tombait à 2,0
   sur le ciel clair — mesuré. */
.heros__fond::after {
  content: ""; position: absolute; inset: 0;
  /* UN HALO, PAS UNE BANDE. Un dégradé horizontal noircit toute la
     colonne gauche sur TOUTE la hauteur — or le texte n'occupe qu'un
     bloc au milieu. On voyait donc une bande sombre là où il n'y a rien
     à protéger, en haut comme en bas. Le halo elliptique suit le bloc
     de texte : le reste de la gauche retrouve la photo.

     Restent deux bandes horizontales, et elles ont chacune leur raison :
     celle du haut porte le logo et la navigation, celle du bas porte la
     ligne des horaires et de l'adresse. */
  background:
    radial-gradient(112% 82% at 20% 58%,
      rgb(6 8 11 / .84) 0%, rgb(6 8 11 / .62) 32%,
      rgb(6 8 11 / .2) 62%, rgb(6 8 11 / 0) 84%),
    linear-gradient(to bottom, rgb(6 8 11 / .5) 0%, rgb(6 8 11 / .1) 22%,
                    rgb(6 8 11 / .2) 62%, rgb(6 8 11 / .88) 100%);
}

.heros__corps { position: relative; }
.heros h1 { max-width: 11em; }
.heros .chapo { max-width: 42ch; margin-bottom: var(--e-4); }

/* La légende suit l'image et nomme ce qu'on voit : c'est ce qui donne un
   sens au défilement des vues, à la place des pastilles d'un carrousel. */
.heros__legende {
  display: inline-flex; align-items: center; gap: .85em;
  font-size: clamp(.95rem, .9rem + .2vw, 1.1rem);
  letter-spacing: .01em;
  color: rgb(255 255 255 / .88);
  margin: 0 0 var(--e-3);
  min-height: 1.5em;   /* réservée : sinon le titre monte et descend
                          d'une vue à l'autre */
}
.heros__legende::before {
  content: ""; width: 2.2em; height: 1px; background: currentColor; opacity: .75;
}

/* --- les informations, DANS le héros -------------------------------
   Ce qu'on cherche en premier sur le site d'un restaurant : quand c'est
   ouvert, où c'est, comment appeler. Dans le héros, elles sont lues
   sans un seul défilement — et elles sont posées sur la GRILLE, pas
   flottantes quelque part à droite. */
/* Un numéro de téléphone se lit comme une donnée, pas comme un lien de
   texte. Le trait du navigateur l'alourdissait partout où il apparaît —
   et sur la photo du héros, il sautait aux yeux avant le numéro. Il
   reste cliquable : c'est la couleur qui le signale au survol. */
a[href^="tel:"] { text-decoration: none; }
@media (hover: hover) {
  .heros__infos a[href^="tel:"]:hover { color: var(--accent); }
}

.heros__infos {
  margin-top: var(--e-5);
  padding-top: var(--e-4);
  border-top: 1px solid rgb(255 255 255 / .26);
  display: grid; gap: var(--e-3) var(--gouttiere);
  grid-template-columns: 1fr;
  font-size: clamp(.95rem, .9rem + .2vw, 1.0625rem);
  line-height: 1.5;
}
.heros__infos p { margin: 0; max-width: none; color: rgb(255 255 255 / .88); }
.heros__infos b {
  display: block; margin-bottom: .2em;
  font-weight: 600; color: #fff;
  font-size: .92em; letter-spacing: .04em;
}
.heros__infos a { color: #fff; }
/* Des colonnes ÉGALES cassaient « jeudi, vendredi, samedi & dimanche »
   sur deux lignes pendant que la colonne voisine gardait du vide.
   Chacune prend la largeur de son contenu, et l'espace restant se
   répartit entre elles. */
@media (min-width: 46rem) {
  .heros__infos {
    grid-template-columns: repeat(4, max-content);
    justify-content: space-between;
    gap: var(--e-3) clamp(1.5rem, 4vw, 4rem);
  }
}
/* Sous 46 rem, on ne garde que l'essentiel : quatre blocs empilés
   pousseraient le titre hors de l'écran. */
@media (max-width: 45.99rem) {
  .heros__infos { grid-template-columns: 1fr 1fr; }
  .heros__infos > :nth-child(n+3) { display: none; }
}

/* Le héros est le seul bloc qui doit tenir sur un téléphone en paysage :
   on y resserre plutôt que de pousser le titre dehors. */
@media (max-height: 34rem) {
  .heros { min-height: 0; padding-top: calc(var(--haut-entete) + 1.5rem); }
  .heros__infos { display: none; }
}
/* La barre d'action occupe le bas de l'écran : le héros lui réserve sa
   place, sinon le second bouton passe dessous. */
@media (max-width: 63.99rem) {
  .heros { padding-bottom: calc(var(--e-3) + 4.6rem + env(safe-area-inset-bottom)); }
}

/* =====================================================================
   LES BANDEAUX
   ===================================================================== */

/* --- l'annonce, dans le héros --------------------------------------
   Pour l'actualité qui a un enjeu : un menu de Saint-Valentin, une
   fermeture, des places limitées. Une ligne fine, refermable, dont le
   choix est retenu dans localStorage (aucun cookie). C'est précisément
   ce qui manquait à leur site : leur menu de février est resté sept
   mois en page d'accueil. */
.annonce {
  position: absolute; inset: var(--haut-entete) 0 auto 0; z-index: var(--z-contenu);
  background: color-mix(in srgb, var(--p-accent-bouton) 92%, #000);
  color: #fff;
}
.annonce__corps {
  display: flex; align-items: center; gap: var(--e-2);
  padding-block: .6rem; font-size: var(--t-mention);
}
.annonce__corps p { margin: 0; max-width: none; }
.annonce a { color: #fff; text-underline-offset: .25em; }
.annonce__fermer {
  margin-left: auto; flex: none;
  display: inline-flex; align-items: center; justify-content: center;
  width: 1.9rem; height: 1.9rem; border-radius: 50%; color: #fff;
  transition: background var(--sortie-court);
}
.annonce__fermer:hover { background: rgb(255 255 255 / .18); }
.annonce__fermer svg { width: .95rem; height: .95rem; }
.annonce[hidden] { display: none; }

/* --- « table ou chambre » -------------------------------------------
   La seule décision que le visiteur a à prendre, posée une fois, au
   milieu de la page. */
.choix {
  display: grid; gap: var(--gouttiere);
  grid-template-columns: 1fr;
}
@media (min-width: 46rem) { .choix { grid-template-columns: 1fr 1fr; } }
.choix__volet {
  position: relative; isolation: isolate; overflow: hidden;
  border-radius: var(--rayon-doux);
  min-height: clamp(16rem, 26vw, 21rem);
  display: flex; flex-direction: column; justify-content: flex-end;
  padding: var(--e-4);
  text-decoration: none;
}
.choix__volet img { position: absolute; inset: 0; z-index: -1; width: 100%; height: 100%; object-fit: cover;
                    transition: transform 1s var(--courbe); }
.choix__volet::after {
  content: ""; position: absolute; inset: 0; z-index: -1;
  background: linear-gradient(to top, rgb(6 8 11 / .9), rgb(6 8 11 / .32) 62%, rgb(6 8 11 / .45));
}
@media (hover: hover) { .choix__volet:hover img { transform: scale(1.04); } }
.choix__volet h3 { color: #fff; margin-bottom: .35em; }
.choix__volet p { color: rgb(255 255 255 / .84); font-size: var(--t-mention); margin-bottom: var(--e-3); }
.choix__volet .bouton { align-self: flex-start; }

/* --- la lettre mensuelle -------------------------------------------- */
.lettre { display: grid; gap: var(--e-4); grid-template-columns: 1fr; align-items: center; }
@media (min-width: 52rem) { .lettre { grid-template-columns: 1fr 1fr; } }
.lettre form { display: flex; flex-wrap: wrap; gap: var(--e-2); }
.lettre input[type="email"] { flex: 1 1 14rem; }

/* =====================================================================
   LES CHAMPS — un seul habillage, pour le formulaire comme pour la
   lettre mensuelle.
   ===================================================================== */
.champ { display: grid; gap: .45rem; }
.champ > span { font-size: var(--t-mention); color: var(--texte-doux); }
input[type="text"], input[type="email"], input[type="tel"], input[type="date"],
input[type="time"], textarea, select {
  width: 100%;
  padding: .85em 1em;
  background: var(--fond-surface);
  border: 1px solid var(--lisere);
  border-radius: var(--rayon-doux);
  color: var(--texte);
  transition: border-color var(--sortie-court), background var(--sortie-court);
}
input:hover, textarea:hover, select:hover { border-color: color-mix(in srgb, var(--texte) 28%, transparent); }
input:focus-visible, textarea:focus-visible, select:focus-visible {
  outline: 2px solid var(--accent); outline-offset: 2px; border-color: transparent;
}
textarea { min-height: 9rem; resize: vertical; }
::placeholder { color: color-mix(in srgb, var(--texte) 42%, transparent); opacity: 1; }
.champs { display: grid; gap: var(--e-3); grid-template-columns: 1fr; }
@media (min-width: 40rem) { .champs--deux { grid-template-columns: 1fr 1fr; } }
.champ--large { grid-column: 1 / -1; }

/* Le champ piège : il doit s'appeler `website` — c'est le nom
   qu'inspecte worker-api/handlers/sendEmail.js. Le renommer désarme le
   filtre à robots sans que rien ne le signale. */
.piege {
  position: absolute !important; left: -9999px !important;
  width: 1px !important; height: 1px !important; overflow: hidden !important;
}

/* =====================================================================
   LA TABLE DES PRIX
   ===================================================================== */
.tarifs { display: grid; }
.tarifs__ligne {
  display: grid; grid-template-columns: 1fr auto; gap: var(--e-3);
  align-items: baseline; padding-block: .95rem;
  border-top: 1px solid var(--lisere);
}
.tarifs__ligne:last-child { border-bottom: 1px solid var(--lisere); }
.tarifs__nom  { font-family: var(--titrage); font-size: var(--t-h4); font-weight: 400; }
.tarifs__prix { font-family: var(--titrage); font-size: var(--t-h4); white-space: nowrap;
                font-variant-numeric: lining-nums; }
.tarifs__detail { grid-column: 1 / -1; color: var(--texte-doux); font-size: var(--t-mention); margin: 0; }

/* =====================================================================
   LA GALERIE — un pavage qui remplit EXACTEMENT ses rangées

       ┌───────────┬───────────┐   1 : 3 colonnes × 2 rangées
       │           │     2     │   2, 3 : 3 × 1
       │     1     ├───────────┤   4, 5, 6 : 2 × 1
       │           │     3     │
       ├───────┬───┴───┬───────┤   six colonnes, trois rangées,
       │   4   │   5   │   6   │   dix-huit cases, six images,
       └───────┴───────┴───────┘   aucune case orpheline

   Le piège : un `aspect-ratio` posé sur CHAQUE case impose sa hauteur et
   défait le `grid-row: span 2` — les cases se chevauchaient, 135 % de
   remplissage mesurés. La hauteur se donne à la RANGÉE.
   ===================================================================== */
.galerie {
  display: grid; gap: var(--e-1);
  grid-template-columns: repeat(2, 1fr);
  grid-auto-rows: clamp(8rem, 20vw, 13.5rem);
}
.galerie figure { margin: 0; overflow: hidden; border-radius: var(--rayon); }
.galerie img { width: 100%; height: 100%; object-fit: cover; }
.galerie > :nth-child(1) { grid-column: span 2; grid-row: span 2; }
@media (min-width: 48rem) {
  /* La composition de base vise SIX photos : une grande sur deux
     rangées, deux demi-largeurs à côté, trois tiers dessous. */
  .galerie { grid-template-columns: repeat(6, 1fr); }
  .galerie > :nth-child(1) { grid-column: span 3; grid-row: span 2; }
  .galerie > :nth-child(2), .galerie > :nth-child(3) { grid-column: span 3; }
  .galerie > :nth-child(4), .galerie > :nth-child(5),
  .galerie > :nth-child(6) { grid-column: span 2; }

  /* À QUATRE : deux rangées de deux, chaque case sur DEUX rangées de
     grille. Deux essais ont échoué avant celui-ci, et pour la même
     raison — la hauteur de rangée est plafonnée à 13,5 rem : une case
     pleine largeur y devient un bandeau de 6 pour 1, et une photo
     verticale n'en montre qu'une tranche. À 3 sur 6 colonnes et deux
     rangées, on retombe sur du 3:2. */
  .galerie[data-nombre="4"] > * { grid-column: span 3; grid-row: span 2; }
  .galerie[data-nombre="5"] > :nth-child(4),
  .galerie[data-nombre="5"] > :nth-child(5) { grid-column: span 3; }
  /* À TROIS, la composition de base tombe juste : rien à corriger. */
}

/* --- LE BANDEAU D'ANNONCE --------------------------------------------
   Posé AU-DESSUS de l'en-tête, qu'il pousse vers le bas. Sa hauteur est
   mesurée par le script et rangée dans `--haut-annonce` : tout ce qui
   se cale sous l'en-tête s'en sert. La deviner, c'est poser la
   navigation de travers dès qu'un message tient sur deux lignes. */
:root { --haut-annonce: 0px; }
.annonce {
  position: fixed; inset: 0 0 auto; z-index: calc(var(--z-entete) + 1);
  background: var(--p-accent-bouton); color: #fff;
  font-size: var(--t-mention);
}
.annonce[hidden] { display: none; }
.annonce__corps {
  display: flex; align-items: center; justify-content: center;
  gap: .6rem; padding-block: .6rem; text-align: center;
}
.annonce__corps p { margin: 0; }
.annonce__picto { display: block; width: 1.1em; height: 1.1em; flex: none; }
.annonce__picto svg { width: 100%; height: 100%; display: block; }
.annonce__lien { color: #fff; text-underline-offset: .25em; white-space: nowrap; }
.annonce__lien[hidden] { display: none; }

/* L'en-tête descend d'autant, et tout ce qui se cale dessous suit. */
.entete { top: var(--haut-annonce); }
body.a-annonce .heros--court,
body.a-annonce .heros { scroll-margin-top: calc(var(--haut-entete) + var(--haut-annonce)); }
body.a-annonce .sommaire { top: calc(var(--haut-entete) + var(--haut-annonce)); }

/* Le titre des pages sans héros — conditions, 404. */
/* SANS HÉROS, RIEN NE COMPENSE L'EN-TÊTE. Sur les pages avec héros,
   c'est lui qui porte le décalage sous la navigation fixe ; ici, il n'y
   a pas de héros — et le titre passait littéralement DERRIÈRE la barre,
   le premier mot à moitié caché. Le décalage se pose donc ici. */
.titre-simple {
  margin-top: 0; margin-bottom: 0;
  padding-top: calc(var(--haut-entete) + clamp(2.4rem, 4.4vw, 3.6rem));
}
/* Même chose pour une page dont le corps écrit son propre <h1> — la
   404. On pousse le MAIN, puisque le titre n'est pas à nous. */
main.sans-heros > section:first-child {
  padding-top: calc(var(--haut-entete) + clamp(2.4rem, 4.4vw, 3.6rem));
}
/* …sauf si c'est notre propre titre qui ouvre la page : il porte déjà
   le décalage, l'ajouter deux fois creuserait un trou. */
main.sans-heros > .enveloppe:first-child + section { padding-top: var(--e-4); }

/* --- CE QUE LE MODULE NE PEUT PAS DEVINER -----------------------------
   Le widget est écrit pour un site CLAIR. Trois réglages ne se font pas
   par ses alias, et se posent donc ici — dans NOTRE feuille, jamais dans
   la sienne, qui appartient au modèle et se réinstalle. */

/* 1. Le panneau garde l'ardoise : il se détache par une ombre portée et
      un filet, ce qui le pose SUR la page sans le décolorer. */
.bw-overlay .bw-panel, .bw-panel {
  box-shadow: 0 2px 10px rgb(0 0 0 / .4), 0 30px 80px -20px rgb(0 0 0 / .8);
  border-color: color-mix(in srgb, var(--p-texte) 16%, transparent);
}

/* 2. UN JETON, DEUX MÉTIERS — et c'est là tout le problème.

      `--beige` porte le bordeaux profond : il est fait pour RECEVOIR du
      blanc, en fond de bouton. Le widget s'en sert aussi comme couleur
      de TEXTE et de TRAIT. Sur le site clair d'origine, les deux usages
      passent ; sur l'ardoise, le texte devient illisible — mesuré à
      2,07 pour 1 là où il en faut 4,5.

      Relevé exhaustif dans la feuille du module : vingt-deux endroits,
      dont sept où l'accent est du texte ou un trait. On les reprend
      tous ici, avec l'accent CLAIR de la charte — celui qui, lui, est
      calculé pour porter du texte sur fond sombre.

      Sélecteurs doublés (`.bw-panel …`) : la feuille du widget est
      chargée APRÈS la nôtre, une spécificité égale ne suffirait pas. */
.bw-panel .bw-note a, .bw-panel .bw-empty a, .bw-panel .bw-mot a,
.bw-panel .bw-intro a, .bw-panel .bw-error a,
.bw-panel .bw-toggle,
.bw-panel .bw-select__option[aria-selected="true"],
.bw-panel .bw-ferme b,
.bw-panel .bw-done .bw-ref { color: var(--p-accent); }

/* Le récapitulatif — les trois valeurs qu'on relit avant de confirmer :
   en BLANC. Ce sont les informations, pas des liens ; elles doivent se
   lire d'un coup d'œil, pas se signaler comme cliquables. */
.bw-panel .bw-recap-val { color: var(--p-texte); }

/* Les traits : la coche de confirmation, les pictogrammes. */
.bw-panel .bw-done .bw-check svg,
.bw-panel .bw-ferme svg { stroke: var(--p-accent); }
.bw-panel .bw-done .bw-check { border-color: var(--p-accent); }

/* La puce de l'option choisie dans une liste déroulante. */
.bw-panel .bw-select__option[aria-selected="true"]::before {
  background: var(--p-accent); border-color: var(--p-accent);
}

/* 3. Les cases non choisies : un fond légèrement plus clair que le
      panneau, pour qu'on les voie comme des boutons avant de les
      survoler. */
.bw-opt:not(.is-active), .bw-day:not(.is-active) {
  background: color-mix(in srgb, var(--p-texte) 6%, transparent);
}

/* QUAND LE PANNEAU DE RÉSERVATION EST OUVERT, l'en-tête s'efface.

   Il est en `position: fixed` avec un z-index de 200, le voile du
   panneau monte à 490 : l'en-tête passe donc DESSOUS, mais le voile est
   translucide et on continue de lire « Chambres » et « Réserver » par
   transparence, juste au-dessus d'un formulaire qui fait déjà ce qu'ils
   proposent. Le widget verrouille le défilement en posant
   `overflow: hidden` sur <html> : on s'accroche à ce signal, qu'il pose
   toujours, plutôt qu'à une classe qui pourrait changer de nom. */
html[style*="overflow: hidden"] .entete,
html[style*="overflow:hidden"] .entete {
  opacity: 0; pointer-events: none;
  transition: opacity 220ms var(--courbe);
}
.entete { transition: opacity 220ms var(--courbe); }

/* --- LES ACTUALITÉS ---------------------------------------------------
   Des cartes basses : l'image, la période, le titre, une phrase. La
   période AVANT le titre — c'est la première chose qu'on cherche dans
   une annonce, et la dernière qu'on trouve quand elle est en bas. */
.actus {
  display: grid; gap: var(--gouttiere);
  grid-template-columns: 1fr;
}
@media (min-width: 52rem) { .actus { grid-template-columns: repeat(3, 1fr); } }
.actu { margin: 0; }
.actu__lien {
  display: block; height: 100%; text-decoration: none; color: inherit;
}
.actu__media {
  overflow: hidden; border-radius: var(--rayon);
  aspect-ratio: 3 / 2; margin-bottom: 1.1rem;
}
.actu__media img { width: 100%; height: 100%; object-fit: cover; display: block; }
.actu__quand {
  margin: 0 0 .25em; color: var(--accent);
  font-size: var(--t-mention); letter-spacing: .02em;
}
.actu h3 { margin: 0 0 .4em; }
.actu p:last-child { margin: 0; color: var(--texte-doux); }
@media (hover: hover) {
  .actu__media img { transition: transform 900ms var(--courbe); }
  .actu__lien:hover .actu__media img { transform: scale(1.04); }
  .actu__lien:hover h3 { color: var(--accent); }
  .actu h3 { transition: color var(--sortie-court); }
}

/* =====================================================================
   LES FICHES — chambres, salles, offres
   La photo est visible d'emblée : la révéler au survol prive du doigt
   l'information principale, et une chambre se vend d'abord par sa photo.
   ===================================================================== */
.fiches { display: grid; gap: var(--gouttiere); grid-template-columns: 1fr; }
@media (min-width: 52rem) { .fiches { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 52rem) { .fiches--deux { grid-template-columns: repeat(2, 1fr); } }
.fiche {
  display: flex; flex-direction: column;
  text-decoration: none; color: inherit;
  background: var(--fond-surface);
  border: 1px solid var(--lisere);
  border-radius: var(--rayon-doux);
  overflow: hidden;
  transition: border-color var(--sortie), transform var(--sortie);
}
@media (hover: hover) {
  .fiche:hover { border-color: color-mix(in srgb, var(--accent) 45%, transparent); transform: translateY(-2px); }
}
.fiche__media { position: relative; overflow: hidden; aspect-ratio: 4 / 5; }
.fiche__media img { width: 100%; height: 100%; object-fit: cover; transition: transform 1s var(--courbe); }
@media (hover: hover) { .fiche:hover .fiche__media img { transform: scale(1.03); } }
/* Une légende POSÉE SUR une image ne peut pas compter sur un dégradé :
   sur une chambre claire, le texte blanc disparaît. Badge presque
   opaque, qui tient sur n'importe quel fond. */
.badge {
  position: absolute; left: .7rem; top: .7rem;
  padding: .3em .65em; border-radius: var(--rayon-rond);
  background: rgb(6 8 11 / .62); backdrop-filter: blur(8px);
  color: #fff; font-size: var(--t-mention); font-weight: 500;
  font-variant-numeric: lining-nums; white-space: nowrap;
}
.fiche__corps { display: flex; flex-direction: column; flex: 1; padding: var(--e-3); }
.fiche__nom { font-family: var(--titrage); font-weight: 300; margin: 0 0 .35em; max-width: none;
              font-size: var(--t-h3); line-height: 1.1; }
.fiche__detail { color: var(--texte-doux); font-size: var(--t-mention); margin: 0; }
/* Le dernier bloc se colle en bas : trois fiches aux textes inégaux
   alignent quand même leurs liens. */
.fiche__pied { margin-top: auto; padding-top: var(--e-3); }

/* =====================================================================
   LE PLEIN CADRE
   ===================================================================== */
.plein {
  position: relative; isolation: isolate;
  min-height: min(78svh, 42rem);
  display: flex; align-items: flex-end;
  padding-block: var(--e-5); overflow: hidden;
}
.plein__fond { position: absolute; inset: 0; z-index: -1; }
.plein__fond img { width: 100%; height: 100%; object-fit: cover; }
.plein__fond::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(to top, rgb(6 8 11 / .88), rgb(6 8 11 / .26) 58%, rgb(6 8 11 / .46));
}
.plein__corps h2 { max-width: 13em; }
.plein__corps .chapo { max-width: 46ch; }

/* =====================================================================
   LES LIGNES — la région, les liens d'une liste
   ===================================================================== */
.lignes { border-top: 1px solid var(--lisere); }
.lignes > a {
  display: grid; gap: .2rem var(--e-3); grid-template-columns: 1fr auto;
  align-items: baseline; padding-block: 1.15rem;
  border-bottom: 1px solid var(--lisere);
  text-decoration: none; color: inherit;
  transition: padding-left var(--sortie), color var(--sortie);
}
@media (hover: hover) { .lignes > a:hover { padding-left: .6rem; color: var(--accent); } }
.lignes__nom  { font-family: var(--titrage); font-size: var(--t-h4); font-weight: 400; }
.lignes__quoi { color: var(--texte-doux); font-size: var(--t-mention); grid-column: 1 / -1; max-width: 52ch; }
.lignes__note { font-size: var(--t-mention); color: var(--texte-doux); }

/* =====================================================================
   LE FILM — une façade, jamais un lecteur chargé d'emblée
   ===================================================================== */
.film { position: relative; overflow: hidden; border-radius: var(--rayon-doux); background: #000; }
.film__cadre { position: relative; aspect-ratio: 16 / 9; }
.film__cadre img, .film__cadre video { width: 100%; height: 100%; object-fit: cover; }
.film__lecture {
  position: absolute; inset: 0;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: var(--e-2);
  color: #fff;
  background: linear-gradient(to top, rgb(6 8 11 / .5), rgb(6 8 11 / .1));
  transition: background var(--sortie);
}
.film__lecture:hover { background: linear-gradient(to top, rgb(6 8 11 / .6), rgb(6 8 11 / .2)); }
.film__rond {
  display: inline-flex; align-items: center; justify-content: center;
  width: clamp(3.6rem, 7vw, 5rem); aspect-ratio: 1; border-radius: 50%;
  border: 1px solid rgb(255 255 255 / .7); background: rgb(255 255 255 / .12);
  backdrop-filter: blur(6px);
  transition: transform var(--sortie), background var(--sortie);
}
.film__lecture:hover .film__rond { transform: scale(1.06); background: rgb(255 255 255 / .24); }
.film__rond svg { width: 38%; height: 38%; margin-left: 8%; }
.film__duree { font-size: var(--t-mention); letter-spacing: .04em; }

/* =====================================================================
   LA VISIONNEUSE

   LE POINT DÉLICAT : une zone d'affichage IDENTIQUE pour tous les
   clichés. Trois pièges s'enchaînent, et il faut les trois corrections
   ensemble :

   1. `max-width`/`max-height` seuls laissent chaque image à sa taille
      native : un portrait déborde et chasse la légende, une vignette
      flotte au milieu du noir ;
   2. `object-fit: contain` uniformise — mais tant que l'image reste DANS
      LE FLUX, c'est elle qui dicte la hauteur du cadre ;
   3. l'arrondi porte alors sur la zone et non sur le cliché.

   D'où : l'image est hors du flux, elle garde son format, elle est
   bornée par le cadre, et l'arrondi porte sur ses vrais bords.
   Vérifié photo par photo : la zone et la légende ne bougent pas.
   ===================================================================== */
.vis { width: 100vw; max-width: none; height: 100dvh; background: transparent; }
.vis__corps {
  position: relative; display: grid; grid-template-rows: 1fr auto; height: 100%;
  padding: clamp(2.6rem, 5vw, 3.4rem) clamp(.7rem, 4vw, 4rem) 0;
}
.vis__cadre { position: relative; grid-row: 1; min-height: 0; }
.vis__cadre img {
  position: absolute; inset: 0; margin: auto;
  width: auto; height: auto; max-width: 100%; max-height: 100%;
  border-radius: var(--rayon-doux);
}
/* Le pied a une hauteur FIXE. Avec une min-height, une légende de trois
   lignes raboterait la zone du cliché, et la zone changerait donc d'une
   photo à l'autre — ce que tout le reste cherche à éviter. */
.vis__pied {
  grid-row: 2; height: 5.2rem;
  /* TROIS colonnes, dont une vide à gauche. En `space-between`, la
     légende se calait à gauche et se décentrait un peu plus à chaque
     compteur plus long. Ici la colonne vide fait contrepoids : la
     légende est centrée sur la FENÊTRE, pas sur l'espace qui reste. */
  display: grid; grid-template-columns: 1fr minmax(0, auto) 1fr;
  align-items: center; gap: var(--e-3);
  color: rgb(255 255 255 / .8); font-size: var(--t-mention);
}
.vis__legende {
  grid-column: 2; margin: 0; max-width: 62ch; text-align: center;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.vis__compteur { grid-column: 3; justify-self: end; margin: 0; font-variant-numeric: tabular-nums; opacity: .8; }
.vis__fermer, .vis__nav {
  position: absolute; z-index: 2;
  display: inline-flex; align-items: center; justify-content: center;
  width: 2.9rem; height: 2.9rem; border-radius: 50%;
  background: rgb(255 255 255 / .1); color: #fff; backdrop-filter: blur(6px);
  transition: background var(--sortie-court);
}
.vis__fermer:hover, .vis__nav:hover { background: rgb(255 255 255 / .22); }
.vis__fermer { top: clamp(.6rem, 2vw, 1.2rem); right: clamp(.6rem, 2vw, 1.2rem); }
.vis__nav { top: 50%; transform: translateY(-50%); }
.vis__nav--prec { left: clamp(.3rem, 1.5vw, 1.2rem); }
.vis__nav--suiv { right: clamp(.3rem, 1.5vw, 1.2rem); }
.vis__nav svg, .vis__fermer svg { width: 1.3rem; height: 1.3rem; }
.vis__nav[hidden] { display: none; }
/* La vignette : un vrai bouton, donc atteignable au clavier. */
.vignette { display: block; width: 100%; height: 100%; padding: 0; border: 0; background: none; cursor: zoom-in; }
.vignette img { width: 100%; height: 100%; object-fit: cover; }

/* =====================================================================
   LE MENU PLEIN ÉCRAN

   Il tient sur UNE hauteur d'écran, sans défilement : une liste qu'il
   faut faire défiler cache ses dernières entrées, et personne ne devine
   qu'il y en a. Onze entrées y entrent — huit pages et les trois
   chambres — parce que les sections n'y figurent plus : le sommaire à
   pastilles les donne déjà, sur la page où elles servent.

   Le pied du menu porte l'action et le téléphone : c'est ce qu'on vient
   chercher quand on ouvre un menu sur un site de restaurant.
   ===================================================================== */
.voile-menu { width: 100vw; max-width: none; height: 100dvh; }
.voile-menu__corps {
  height: 100%; background: var(--fond); color: var(--texte);
  display: flex; flex-direction: column;
  padding: var(--e-2) var(--marge-page) calc(var(--e-3) + env(safe-area-inset-bottom));
}
.voile-menu__haut {
  display: flex; align-items: center; justify-content: space-between;
  padding-block: var(--e-1); flex: none;
}

.voile-menu nav {
  flex: 1 1 auto; min-height: 0;
  display: flex; flex-direction: column; justify-content: center;
  gap: clamp(.1rem, 1vh, .5rem);
  padding-block: var(--e-3);
}
.voile-menu__page {
  font-family: var(--titrage); font-weight: 300;
  /* La taille suit la HAUTEUR de l'écran, pas sa largeur : c'est la
     hauteur qui manque quand onze entrées doivent tenir. */
  font-size: clamp(1.35rem, 3.1vh, 2rem);
  line-height: 1.15;
  text-decoration: none; color: var(--titre);
  padding-block: .1em;
}
/* Les chambres, en rang serré sous leur parent : trois libellés courts
   sur une ligne plutôt que trois lignes de plus. */
.voile-menu__enfants {
  display: flex; flex-wrap: wrap; gap: .3rem .45rem;
  padding: .15rem 0 .35rem;
}
.voile-menu__enfants a {
  font-family: var(--courante); font-size: .82rem;
  text-decoration: none; color: var(--texte-doux);
  padding: .3rem .7rem;
  border: 1px solid var(--lisere); border-radius: var(--rayon-rond);
}
@media (hover: hover) {
  .voile-menu__page:hover { color: var(--accent); }
  .voile-menu__enfants a:hover { color: var(--texte); border-color: color-mix(in srgb, var(--texte) 30%, transparent); }
}

.voile-menu__pied {
  flex: none; display: grid; gap: var(--e-2);
  padding-top: var(--e-3); border-top: 1px solid var(--lisere);
}
.voile-menu__pied .boutons { display: grid; grid-template-columns: 1fr 1fr; gap: var(--e-2); }
.voile-menu__pied .bouton { width: 100%; }

/* Sur un écran vraiment court — un téléphone en paysage —, la liste
   défile plutôt que de déborder. */
@media (max-height: 30rem) {
  .voile-menu nav { justify-content: flex-start; overflow-y: auto; }
}

/* =====================================================================
   LA BARRE D'ACTION MOBILE
   Fond OPAQUE, séparateurs en border-left : avec un `gap` sur un
   conteneur semi-transparent, la page défile dans les interstices.
   Hauteur commune et libellés d'UN SEUL MOT — les trois colonnes
   s'alignent quelle que soit la langue.
   ===================================================================== */
.barre-appel {
  position: fixed; inset: auto 0 0 0; z-index: var(--z-barre);
  display: flex; background: var(--p-fond);
  border-top: 1px solid var(--lisere);
  padding-bottom: env(safe-area-inset-bottom);
}
.barre-appel > * {
  flex: 1 1 0;
  display: inline-flex; flex-direction: column; align-items: center; justify-content: center;
  gap: .25em; min-height: 4.1rem; padding: .55rem .3rem;
  font-size: .78rem; font-weight: 500; white-space: nowrap;
  text-decoration: none; color: var(--p-texte);
}
.barre-appel > * + * { border-left: 1px solid var(--lisere); }
.barre-appel svg { width: 1.2em; height: 1.2em; flex: none; }
.barre-appel .callbar-main { color: #fff; background: var(--p-accent-bouton); }
.barre-appel small { display: block; font-size: .78em; font-weight: 400; opacity: .82; }
@media (min-width: 64rem) { .barre-appel { display: none; } }

/* =====================================================================
   LE PIED
   ===================================================================== */
.pied { padding-block: var(--e-5) var(--e-4); border-top: 1px solid var(--lisere); }
.pied__haut { display: grid; gap: var(--e-5) var(--gouttiere); grid-template-columns: 1fr; }
@media (min-width: 46rem) { .pied__haut { grid-template-columns: 1fr 1fr; } }
@media (min-width: 64rem) { .pied__haut { grid-template-columns: 1.6fr 1fr 1fr 1fr; } }
.pied__logo { width: 168px; height: auto; }
/* Un titre de colonne doit se voir COMME un titre : l'accent et un peu
   de graisse suffisent — sans cela les quatre colonnes se lisent comme
   un seul bloc de texte gris. */
.pied h4 {
  margin-bottom: var(--e-3);
  font-family: var(--courante); font-size: var(--t-mention); font-weight: 600;
  letter-spacing: .08em; text-transform: uppercase; color: var(--accent);
}
.pied p { margin-bottom: var(--e-2); }
.pied .paires dt { color: var(--texte-doux); }
.pied .paires dd { color: var(--texte); }
/* Neuf liens dans une seule colonne la rendaient deux fois plus haute
   que ses voisines, et elle passait sous le filet de séparation. */
.pied__liens { display: grid; gap: .6rem; }
@media (min-width: 64rem) {
  .pied__liens { grid-template-columns: 1fr 1fr; gap: .6rem var(--e-3); }
}
.pied__liens a { text-decoration: none; color: var(--texte-doux); font-size: var(--t-mention); white-space: nowrap; }
.pied__liens a:hover { color: var(--accent); }
.pied .filet { margin-top: var(--e-4); }
.pied__bas {
  display: flex; flex-wrap: wrap; gap: var(--e-2);
  align-items: center; justify-content: space-between;
  font-size: var(--t-mention); color: var(--texte-doux);
}
.pied__bas a { color: var(--texte-doux); }
.pied__bas a:hover { color: var(--accent); }
.pied__reseaux { display: flex; gap: var(--e-2); margin: 0; }
.pied__reseaux .lien-icone svg { width: 1.3em; height: 1.3em; }
@media (max-width: 63.99rem) { .pied { padding-bottom: calc(var(--e-4) + 5rem); } }

/* =====================================================================
   ACCESSIBILITÉ
   ===================================================================== */
:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
  outline: 2px solid var(--accent); outline-offset: 3px; border-radius: var(--rayon);
}
.saut-contenu {
  position: absolute; left: var(--e-2); top: -6rem; z-index: var(--z-alerte);
  padding: .8em 1.3em; background: var(--p-texte); color: var(--p-fond);
  border-radius: var(--rayon-rond); text-decoration: none; font-weight: 500;
  transition: top var(--sortie);
}
.saut-contenu:focus { top: var(--e-2); }
.invisible {
  position: absolute !important; width: 1px !important; height: 1px !important;
  padding: 0 !important; margin: -1px !important; overflow: hidden !important;
  clip-path: inset(50%) !important; white-space: nowrap !important; border: 0 !important;
}

/* =====================================================================
   MOUVEMENT

   LE CONTENU EST VISIBLE, POINT. L'apparition n'est qu'un enrichissement
   posé par-dessus, et elle ne passe par aucun script.

   `animation-fill-mode: none` et une plage qui démarre à `entry 0%` :
   hors de sa plage, une animation en `none` n'applique RIEN, donc
   l'élément est à son état normal. Avec le `both` du réflexe, il
   resterait figé à opacité zéro — mesuré, deux fois, une section entière
   sortie vide.
   ===================================================================== */
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    .apparait {
      animation: monte linear none;
      animation-timeline: view(); animation-range: entry 0% cover 24%;
    }
    /* Dans une liste, l'entrée se décale d'un enfant à l'autre. Le
       décalage appartient à LA LISTE : il ne se pose pas sur toutes les
       sections — la vague uniforme est le vrai défaut, pas le mouvement. */
    .apparait-suite > * {
      animation: monte linear none;
      animation-timeline: view(); animation-range: entry 0% cover 22%;
    }
    .apparait-suite > :nth-child(2)   { animation-range: entry 0% cover 27%; }
    .apparait-suite > :nth-child(3)   { animation-range: entry 0% cover 32%; }
    .apparait-suite > :nth-child(n+4) { animation-range: entry 0% cover 37%; }
  }
}
@keyframes monte { from { opacity: 0; transform: translateY(20px); } to { opacity: 1; transform: none; } }

/* --- L'ENTRÉE DU HÉROS -----------------------------------------------
   Le héros n'avait aucune animation : il apparaissait d'un bloc, et
   cette apparition brutale se lit comme un scintillement — d'autant que
   la mesure montre 371 ms d'attente avant le premier rendu, image déjà
   chargée en 11 ms.

   Une animation de PAGE, pas de défilement : `view()` ne conviendrait
   pas ici, l'élément est déjà dans la vue au chargement. Elle part donc
   au premier rendu et se joue toujours, sans script ni condition.

   `both` est sûr dans ce cas précis — contrairement aux animations de
   défilement, où il fige le contenu à opacité zéro hors de sa plage :
   celle-ci n'a pas de plage, elle démarre et se termine. */
@media (prefers-reduced-motion: no-preference) {
  .heros__legende,
  .heros__corps h1,
  .heros__corps .chapo,
  .heros__corps .boutons,
  .heros__infos {
    animation: entree 1100ms cubic-bezier(.16, 1, .3, 1) both;
  }
  /* En cascade : la légende, le titre, le chapô, les boutons, la ligne
     d'horaires. Le décalage reste court — un héros qui se construit
     pendant une seconde et demie fait attendre pour rien. */
  .heros__legende          { animation-delay:  60ms; }
  .heros__corps h1         { animation-delay: 140ms; }
  .heros__corps .chapo     { animation-delay: 280ms; }
  .heros__corps .boutons   { animation-delay: 400ms; }
  .heros__infos            { animation-delay: 520ms; }

  /* Le FOND accompagne, plus lentement et sans déplacement : une image
     qui monte en même temps que le texte donne le mal de mer. */
  .heros__fond { animation: fondu 1400ms ease-out both; }
}
@keyframes entree { from { opacity: 0; transform: translateY(22px); } }
@keyframes fondu  { from { opacity: 0; } }

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

/* =====================================================================
   LES BOÎTES — le piège majeur
   Un <dialog> fermé est masqué par la feuille du navigateur. TOUTE règle
   display posée sans condition l'écrase, et laisse une boîte vide,
   infermable, par-dessus la page. Le contrôle de revue le vérifie.
   ===================================================================== */
dialog:not([open]) { display: none; }
dialog { border: 0; padding: 0; background: transparent; max-width: 100vw; max-height: 100dvh; color: var(--texte); }
dialog::backdrop { background: rgb(6 8 11 / .9); backdrop-filter: blur(8px); }

/* La signature de l'agence : discrète, mais cliquable. Elle prend la
   couleur d'accent au survol, comme tous les liens du pied. */
.pied__signature { margin: 0; color: var(--texte-doux); }
.pied__signature a { color: var(--texte-doux); text-underline-offset: .25em; }
.pied__signature a:hover { color: var(--accent); }

/* =====================================================================
   LES PAGES INTÉRIEURES
   ===================================================================== */

/* =====================================================================
   LE HÉROS COURT des pages intérieures

   MESURÉ, et corrigé : une hauteur fixe de 480 px donnait un cadre au
   format 3:1 alors que les images sont en 21:9 (2,33:1). `object-fit:
   cover` rognait donc 22 % de la photo, en haut et en bas — et c'est
   justement là que se trouve ce qui situe une pièce : le plafond, le
   sol, l'horizon.

   Le cadre prend donc le format DE L'IMAGE, borné par un plancher (pour
   que le titre tienne sur un téléphone, où un 21:9 ne ferait que
   167 px) et par un plafond (pour qu'un grand écran ne transforme pas
   la bande en second plein écran). */
.heros--court {
  /* PAS d'`aspect-ratio` ici. Combiné à un `max-height`, il déduit la
     LARGEUR de la hauteur au lieu de l'inverse : le héros s'est
     retrouvé à 1 269 px de large sur un écran de 1 440, et ne prenait
     plus toute la largeur.

     La hauteur se calcule donc en `vw` — 42,85 vw, soit le 9/21 du
     format des images — bornée par un plancher (pour que le titre
     tienne sur un téléphone) et un plafond (pour qu'un grand écran ne
     transforme pas la bande en second plein écran). */
  /* `min-height` et non `height` : une hauteur FERME découpe le bloc
     sans regarder ce qu'il contient. Mesuré à 390 px — le titre passait
     SOUS l'en-tête, jusqu'à 95 px de recouvrement sur « La région »,
     parce que le contenu était poussé en bas d'un cadre trop court. Le
     bloc garde donc sa hauteur de référence, mais il grandit quand le
     texte le demande. */
  min-height: clamp(23rem, 42.85vw, 38rem);
  height: auto;
  /* L'AIR SOUS L'EN-TÊTE, garanti. Avec 1,5 rem, l'écart mesuré entre
     le bas de l'en-tête et le haut du titre tombait à 28 px sur
     téléphone et tablette — sur les pages dont le titre prend deux ou
     trois lignes, le bloc paraissait poussé contre la navigation. Il
     varie forcément avec la longueur du titre ; ce qu'on fixe ici,
     c'est le MINIMUM. */
  padding-top: calc(var(--haut-entete) + clamp(2.6rem, 4.4vw, 3.4rem));
  padding-bottom: var(--e-4);
}
/* Un titre de héros court se pose sur deux lignes au plus dans la
   plupart des langues ; passé trois, il mange la photo. On serre donc
   son plafond de taille — sans toucher au héros de l'accueil, qui
   dispose de toute la hauteur de l'écran. */
.heros--court h1 { font-size: clamp(2.1rem, 5.2vw, 4.2rem); }

/* Le fondu vers la section suivante. Sans lui, la photographie s'arrête
   net sur un trait horizontal, et la coupure se voit d'autant plus que
   le bas de l'image est clair. Le dégradé descend vers la couleur de
   fond de la page — il vient donc mourir exactement dans la section qui
   suit, quelle qu'elle soit. */
.heros--court::after {
  content: "";
  position: absolute; inset: auto 0 0 0;
  height: clamp(5rem, 14vh, 9rem);
  background: linear-gradient(to bottom, transparent, var(--p-fond) 92%);
  pointer-events: none;
  z-index: -1;
}
/* Le corps passe au-dessus du fondu : sans cela le dégradé, posé plus
   tard dans l'ordre d'empilement, voilerait le texte. */
.heros--court .heros__corps { position: relative; z-index: 1; }
.heros--court h1 { max-width: 14em; }

/* Le voile d'un héros COURT n'est pas celui d'un plein écran. Sur un
   plein écran, le texte est en bas et l'image respire au-dessus ; ici
   le texte occupe presque toute la hauteur, et le voile du plein écran
   rendait la photo quasi noire — luminosité mesurée à 0,29 avant voile,
   et 0,82 d'opacité par-dessus.

   On allège des deux côtés, et on vérifie que le titre garde son
   contraste : le contrôle de revue le mesure sur les quatorze pages. */
.heros--court .heros__fond::after {
  /* Même principe que l'accueil : un halo sur le bloc de texte, et non
     une bande sur toute la colonne. Il est placé un peu plus haut ici,
     le héros court étant deux fois moins haut. */
  background:
    radial-gradient(104% 88% at 18% 62%,
      rgb(6 8 11 / .84) 0%, rgb(6 8 11 / .63) 34%,
      rgb(6 8 11 / .18) 64%, rgb(6 8 11 / 0) 86%),
    linear-gradient(to bottom,
      rgb(6 8 11 / .36) 0%, rgb(6 8 11 / .06) 26%,
      rgb(6 8 11 / .08) 62%, rgb(6 8 11 / .4) 100%);
}
/* Une ombre portée SOUS le titre, et sous lui seul. C'est ce qui permet
   de garder la photographie lisible à droite sans noircir toute la
   bande : mesuré, le voile seul faisait tomber le contraste à 2,53 sur
   la chambre Deluxe, dont l'image est très claire. L'ombre agit là où
   le texte se pose, pixel par pixel, et nulle part ailleurs. */
.heros--court h1,
.heros--court .chapo {
  /* Trois rayons, pas un : le halo serré tient les lettres sur un
     reflet clair, le large les détache du fond. C'est ce qui permet de
     ne PAS noircir la photo pour gagner du contraste. */
  text-shadow: 0 1px 28px rgb(6 8 11 / .82),
               0 0 9px  rgb(6 8 11 / .58),
               0 1px 3px rgb(6 8 11 / .5);
}

/* --- la carte des mets ---------------------------------------------- */
.cartes { display: grid; gap: var(--e-5) var(--gouttiere); grid-template-columns: 1fr; }
@media (min-width: 64rem) { .cartes { grid-template-columns: 1fr 1fr; } }
.carte-section h3 { margin-bottom: var(--e-2); color: var(--accent); }

/* --- le menu du mois : une suite de services, sans prix par ligne ---- */
.menu-mois { display: grid; gap: 0; }
.menu-mois__ligne { padding-block: .8rem; border-top: 1px solid var(--lisere); }
.menu-mois__ligne:last-child { border-bottom: 1px solid var(--lisere); }
.menu-mois__nom { display: block; font-family: var(--titrage); font-size: var(--t-h4); font-weight: 400; }
.menu-mois__detail { display: block; color: var(--texte-doux); font-size: var(--t-mention); margin-top: .15rem; }

/* --- une liste de mets sans prix ------------------------------------ */
.mets { display: grid; gap: var(--e-4) var(--gouttiere); grid-template-columns: 1fr; }
@media (min-width: 48rem) { .mets { grid-template-columns: 1fr 1fr; } }
.mets__bloc h3 { margin-bottom: .2em; color: var(--accent); }
.mets__bloc .mention { margin-bottom: var(--e-2); }
/* --- LE PLAT SIGNATURE ------------------------------------------------
   Un cadre, un filet d'accent, et le prix détaché en bas. Le tout tient
   dans une colonne de lecture : c'est ce qui le distingue du corps de
   la carte sans crier. */
.signature {
  max-width: 34rem; margin-inline: auto; padding: var(--e-4) var(--e-3);
  border: 1px solid var(--lisere); border-radius: var(--rayon-doux);
  background: color-mix(in srgb, var(--p-texte) 3%, transparent);
  text-align: center;
}
.signature__mention {
  margin: 0 0 .9em; color: var(--texte-doux); font-size: var(--t-mention);
}
.signature h2 { margin: 0 0 .7em; }
.signature__met { margin: 0 auto; max-width: 30rem; }
.signature__prix {
  margin: 1.1em 0 0; padding-top: .9em;
  border-top: 1px solid var(--lisere);
  color: var(--accent); font-size: 1.35rem; font-variant-numeric: tabular-nums;
}

.mets__liste { display: grid; gap: .9rem; }
/* Un met porte un NOM, un PRIX et un DÉTAIL. Le prix se cale à droite
   sur une grille à deux colonnes, le détail passe dessous en pleine
   largeur : c'est la lecture d'une carte, pas d'une liste à puces. */
.mets__liste li:has(.mets__nom) {
  display: grid; grid-template-columns: 1fr auto;
  column-gap: .9rem; align-items: baseline; padding-left: 0;
}
.mets__liste li:has(.mets__nom)::before { content: none; }
.mets__nom { font-weight: 500; }
.mets__prix {
  color: var(--accent); font-variant-numeric: tabular-nums; white-space: nowrap;
}
.mets__detail {
  grid-column: 1 / -1; margin-top: .15em;
  color: var(--texte-doux); font-size: var(--t-mention);
}
.mets__liste li { padding-left: 1.1em; position: relative; }
.mets__liste li::before {
  content: ""; position: absolute; left: 0; top: .72em;
  width: .35em; height: 1px; background: var(--accent);
}

/* --- une liste de points -------------------------------------------- */
.points { display: grid; gap: .65rem; }
.points li { padding-left: 1.4em; position: relative; }
.points li::before {
  content: ""; position: absolute; left: 0; top: .68em;
  width: .7em; height: 1px; background: var(--accent);
}

/* Des équipements avec leur PICTO : une grille à deux colonnes, l'icône
   calée sur la première ligne du texte — pas centrée verticalement, ce
   qui la ferait flotter au milieu d'un intitulé sur deux lignes. */
.points--pictos { list-style: none; padding-left: 0; display: grid; gap: .85rem; }
.points--pictos li {
  display: grid; grid-template-columns: 1.6rem 1fr;
  gap: .8rem; align-items: start; padding-left: 0;
}
.points--pictos li::before { content: none; }
.points__picto {
  display: block; width: 1.6rem; height: 1.6rem; color: var(--accent);
  /* aligne l'icône sur la hauteur de capitale du texte */
  margin-top: .05em;
}
.points__picto svg { width: 100%; height: 100%; display: block; }


/* --- le déroulé d'une journée --------------------------------------- */
.etapes { display: grid; gap: 0; counter-reset: etape; }
.etapes li {
  display: grid; gap: .2rem var(--e-3); grid-template-columns: 1fr;
  padding-block: .95rem; border-top: 1px solid var(--lisere);
}
.etapes li:last-child { border-bottom: 1px solid var(--lisere); }
@media (min-width: 40rem) { .etapes li { grid-template-columns: 6rem 1fr; } }
.etapes__heure { font-family: var(--titrage); font-size: var(--t-h4); color: var(--accent); font-variant-numeric: lining-nums; }
.etapes__quoi { color: var(--texte-doux); }

/* --- le formulaire --------------------------------------------------- */
.formulaire { max-width: 46rem; }
.champ > span em { font-style: normal; color: var(--accent); }
.formulaire [data-contact-message]:empty { display: none; }
.formulaire [data-contact-message] { margin-top: var(--e-2); }

/* --- le plan, en façade ---------------------------------------------- */
.plan {
  background: var(--fond-surface); border: 1px solid var(--lisere);
  border-radius: var(--rayon-doux); padding: var(--e-4);
}
.plan__adresse { margin-bottom: var(--e-3); }
.plan__adresse strong { font-family: var(--titrage); font-size: var(--t-h4); font-weight: 400; }
.plan .mention { margin-top: var(--e-2); }

/* --- le rappel de fin de page ---------------------------------------- */
.rappel {
  display: grid; gap: var(--e-3); align-items: center;
  grid-template-columns: 1fr;
}
@media (min-width: 52rem) { .rappel { grid-template-columns: 1fr auto; gap: var(--e-4); } }
.rappel h2 { margin: 0; max-width: 16em; }

/* =====================================================================
   LE SOUS-MENU — un panneau à vignettes

   Leur méga-menu montrait trois grandes images côte à côte, et c'était
   la bonne idée : sur un site de restaurant et d'hôtel, une photo dit
   en un dixième de seconde ce qu'un libellé met une phrase à expliquer.

   Ce qu'il faisait mal, et qu'on ne reprend pas : chaque entrée y était
   DÉDOUBLÉE — un lien pour l'image, un autre pour le texte — soit
   trente-six liens pour neuf pages, et autant d'entrées vides annoncées
   par un lecteur d'écran. Ici, un seul lien porte l'image et le mot.

   Le parent reste un LIEN vers sa propre page ; le chevron d'à côté est
   un bouton séparé qui ne fait qu'ouvrir le panneau.
   ===================================================================== */
.sous-menu { position: relative; display: inline-flex; align-items: center; gap: .15em;
             white-space: nowrap; flex: none; }
.sous-menu__bouton {
  display: inline-flex; align-items: center; justify-content: center;
  width: 1.4em; height: 1.4em; color: inherit; opacity: .7;
  transition: opacity var(--sortie-court), transform var(--sortie);
}
.sous-menu__bouton svg { width: .85em; height: .85em; }
.sous-menu:hover .sous-menu__bouton { opacity: 1; }
.sous-menu__bouton[aria-expanded="true"] { opacity: 1; transform: rotate(180deg); }

.sous-menu__liste {
  display: grid; gap: .1rem; align-content: start;
  min-width: 11.5rem;
}
.sous-menu__panneau {
  position: absolute; top: 100%; left: 50%; z-index: var(--z-entete);
  display: grid; grid-template-columns: auto 20rem; gap: var(--e-3);
  max-width: calc(100vw - 2 * var(--marge-page));
  margin-top: .7rem; padding: var(--e-2);
  transform: translateX(-50%) translateY(-.35rem);
  background: var(--p-fond);
  border: 1px solid color-mix(in srgb, var(--p-texte) 14%, transparent);
  border-radius: var(--rayon-doux);
  box-shadow: 0 2px 8px rgb(0 0 0 / .34), 0 24px 60px -22px rgb(0 0 0 / .7);
  opacity: 0; visibility: hidden;
  transition: opacity var(--sortie), transform var(--sortie), visibility var(--sortie);
}
.sous-menu:hover .sous-menu__panneau,
.sous-menu:focus-within .sous-menu__panneau,
.sous-menu[data-ouvert] .sous-menu__panneau {
  opacity: 1; visibility: visible; transform: translateX(-50%);
}
/* Une fermeture EXPLICITE — Échap, ou un clic dehors — l'emporte sur
   `:focus-within`, qui garderait sinon le panneau ouvert tant que le
   bouton a le focus : on appuierait sur Échap et rien ne se passerait. */
.sous-menu[data-ferme] .sous-menu__panneau {
  opacity: 0; visibility: hidden; transform: translateX(-50%) translateY(-.35rem);
}

.sous-menu__liste a {
  position: relative;
  padding: .62rem .9rem; border-radius: calc(var(--rayon-doux) - 2px);
  font-size: var(--t-menu); text-decoration: none; color: var(--p-texte);
  white-space: nowrap;
  transition: background var(--sortie-court), color var(--sortie-court);
}
.sous-menu__liste a:hover,
.sous-menu__liste a[aria-current] { background: color-mix(in srgb, var(--p-texte) 8%, transparent); color: var(--p-accent); }

/* --- LA MOSAÏQUE : plusieurs photos, montrées ensemble ----------------
   Cinq cases de tailles inégales. La première est la dominante — deux
   colonnes sur deux rangées — les quatre autres l'entourent. Aucune
   n'est cachée, il n'y a rien à faire défiler.

   `aspect-ratio` sur chaque case plutôt qu'une hauteur de rangée : la
   grille garde sa forme quelle que soit la largeur, et aucune image ne
   se déforme. */
/* `.bloc--multiple` NE REDÉFINIT PAS la grille : `.bloc` en pose une de
   douze colonnes, et deux colonnes posées par-dessus étaient tout
   simplement ignorées — la mosaïque retombait à sa largeur minimale,
   207 px au lieu de 600. On se place DANS la grille existante, comme le
   font déjà .bloc__media et .bloc__texte. */
/* PLEINE LARGEUR. Côte à côte avec le texte, les cinq photos tombaient
   à 152 px sur un écran de 1440 et à 106 px sur un 1024 — mesuré. Une
   section qui dit « cinq terrasses » ne peut pas les montrer en
   timbres-poste. Le texte prend donc une colonne de lecture au-dessus,
   et les photos toute la largeur en dessous : elles doublent de taille. */
@media (min-width: 64rem) {
  .bloc--multiple > .bloc__texte { grid-column: 1 / span 7; grid-row: 1; }
  .bloc--multiple > .mosaique { grid-column: 1 / -1; grid-row: 2; }
}
.mosaique {
  display: grid; gap: .5rem;
  grid-template-columns: repeat(4, 1fr);
}
.mosaique__vue { margin: 0; overflow: hidden; border-radius: var(--rayon-doux); }
.mosaique__vue img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* La visionneuse insère un <button> AUTOUR de l'image : sans cette
   règle il se dimensionne sur son contenu et l'image déborde de sa
   case. Le bouton doit devenir la case. */
.mosaique__vue .vignette {
  display: block; width: 100%; height: 100%; padding: 0;
  border: 0; background: none; cursor: pointer;
}
/* la dominante */
.mosaique__vue--1 { grid-column: span 4; aspect-ratio: 3 / 2; }
/* les quatre satellites, deux par rangée */
.mosaique__vue--2, .mosaique__vue--3,
.mosaique__vue--4, .mosaique__vue--5 { grid-column: span 2; aspect-ratio: 3 / 2; }

@media (min-width: 46rem) {
  /* Au-delà du téléphone, la dominante prend la hauteur de deux
     satellites : c'est ce qui casse la régularité de planche contact. */
  .mosaique { grid-template-rows: repeat(2, auto); }
  .mosaique__vue--1 { grid-column: span 2; grid-row: span 2; aspect-ratio: 1 / 1; }
  .mosaique__vue--2, .mosaique__vue--3,
  .mosaique__vue--4, .mosaique__vue--5 { grid-column: span 1; aspect-ratio: 1 / 1; }

  /* TROIS photos : la composition à cinq laisserait deux cases vides.
     La dominante prend la moitié, les deux autres s'empilent à côté. */
  .mosaique[data-nombre="3"] .mosaique__vue--1 { grid-column: span 2; grid-row: span 2; }
  .mosaique[data-nombre="3"] .mosaique__vue--2,
  .mosaique[data-nombre="3"] .mosaique__vue--3 { grid-column: span 2; grid-row: span 1; aspect-ratio: 2 / 1; }

  /* DEUX photos. La grille passe à CINQ colonnes rien que pour ce cas :
     sur quatre, la seconde n'en recevait qu'une et se retrouvait en
     bande verticale de 318 px de large sur 647 de haut — une photo
     d'assiette y était réduite à un fragment. Trois cinquièmes / deux
     cinquièmes donnent deux cadres respirables et des hauteurs voisines. */
  .mosaique[data-nombre="2"] { grid-template-columns: repeat(5, 1fr); grid-template-rows: auto; }
  .mosaique[data-nombre="2"] .mosaique__vue--1 { grid-column: 1 / span 3; grid-row: 1; aspect-ratio: 3 / 2; }
  .mosaique[data-nombre="2"] .mosaique__vue--2 { grid-column: 4 / span 2; grid-row: 1; aspect-ratio: 1 / 1; }

  /* QUATRE photos. Colonnes ET rangées ÉCRITES, pas laissées au
     placement automatique : avec `span` seul, la dominante se casait où
     il restait de la place — elle s'est retrouvée à droite, la moitié
     de la grille à l'envers. */
  .mosaique[data-nombre="4"] .mosaique__vue--1 { grid-column: 1 / span 2; grid-row: 1 / span 2; }
  .mosaique[data-nombre="4"] .mosaique__vue--2 { grid-column: 3 / span 2; grid-row: 1; aspect-ratio: 2 / 1; }
  .mosaique[data-nombre="4"] .mosaique__vue--3 { grid-column: 3; grid-row: 2; }
  .mosaique[data-nombre="4"] .mosaique__vue--4 { grid-column: 4; grid-row: 2; }
}
@media (hover: hover) {
  .mosaique__vue img { transition: transform 900ms var(--courbe); }
  .mosaique__vue:hover img { transform: scale(1.04); }
}

/* --- l'aperçu : UNE image, qui suit le libellé survolé --------------
   Trois vignettes alignées, c'est le méga-menu que tout le monde fait —
   et c'est celui de leur site actuel. Ici, une seule image, deux fois
   plus grande, qui change selon ce qu'on survole.

   Tout se joue en CSS : les images sont superposées et `:has()` révèle
   celle dont le libellé est survolé ou porte le focus. Sans script, la
   première reste affichée — le panneau ne dépend de rien. */
.sous-menu__apercu { position: relative; aspect-ratio: 4 / 3; overflow: hidden;
                     border-radius: calc(var(--rayon-doux) - 3px); }
.sous-menu__vue {
  position: absolute; inset: 0;
  display: block; opacity: 0; text-decoration: none;
  /* L'état de repos est celui vers lequel l'image SORTANTE s'en va :
     elle recule d'un cheveu et se dissipe. `--decalage` porte le sens
     du geste (voir `data-sens` plus bas) — l'entrante et la sortante
     glissent alors en sens contraire, ce qui donne au changement le
     mouvement d'un feuillet qu'on tourne plutôt qu'un simple fondu. */
  transform: scale(1.045) translateY(var(--decalage, 8px));
  will-change: opacity, transform;
  /* UNE IMAGE À OPACITÉ ZÉRO RESTE CLIQUABLE. Les trois aperçus sont
     superposés : sans cette ligne, le clic tomberait toujours sur le
     dernier empilé, quelle que soit l'image affichée — et mènerait à la
     mauvaise section sans que rien ne le laisse deviner. */
  pointer-events: none;
  /* Sortie plus VIVE que l'entrée : les deux images se croisent au lieu
     de se superposer à mi-course, où l'on verrait deux photos à moitié
     transparentes l'une sur l'autre. */
  transition: opacity 300ms var(--courbe), transform 420ms var(--courbe);
}
/* Au repos — panneau qui vient de s'ouvrir, ou navigateur sans script —
   la première image est posée, sans animation à jouer. */
.sous-menu__panneau:not([data-vue-active]) .sous-menu__vue[data-vue-defaut] {
  opacity: 1; transform: none;
}

.sous-menu__vue img { width: 100%; height: 100%; object-fit: cover; }
@media (hover: hover) {
  .sous-menu__vue:hover img { transform: scale(1.02); }
  .sous-menu__vue img { transition: transform 700ms var(--courbe); }
}

/* Le rang retenu par le script décide de la vue affichée — et de la
   seule qui reçoit les clics. Trois rangs suffisent : aucun sous-menu
   n'a plus de trois entrées illustrées. */
.sous-menu__panneau[data-vue-active="0"] .sous-menu__vue:nth-child(1),
.sous-menu__panneau[data-vue-active="1"] .sous-menu__vue:nth-child(2),
.sous-menu__panneau[data-vue-active="2"] .sous-menu__vue:nth-child(3) {
  opacity: 1; pointer-events: auto;
  transform: none;
  /* Le zoom se résorbe bien après que l'image est pleinement visible :
     c'est ce décalage entre les deux durées qui donne l'impression que
     la photo se POSE, au lieu d'apparaître. */
  transition: opacity 460ms var(--courbe),
              transform 1100ms cubic-bezier(.16, 1, .3, 1);
}
/* Dès qu'un rang est retenu, la vue par défaut s'efface — sans quoi
   deux images resteraient superposées. */
.sous-menu__panneau[data-vue-active] .sous-menu__vue[data-vue-defaut] {
  opacity: 0; pointer-events: none;
}
.sous-menu__panneau[data-vue-active="0"] .sous-menu__vue[data-vue-defaut] {
  opacity: 1; pointer-events: auto; transform: none;
}

/* LE SENS DU GESTE. En descendant dans la liste, l'image entrante monte
   et la sortante descend ; en remontant, l'inverse. Rien ne le dit
   explicitement, mais l'œil le lit — c'est ce qui distingue un
   changement d'image d'un vrai mouvement. */
.sous-menu__panneau[data-sens="bas"]  { --decalage:  10px; }
.sous-menu__panneau[data-sens="haut"] { --decalage: -10px; }

@media (prefers-reduced-motion: reduce) {
  .sous-menu__vue,
  .sous-menu__panneau[data-vue-active="0"] .sous-menu__vue:nth-child(1),
  .sous-menu__panneau[data-vue-active="1"] .sous-menu__vue:nth-child(2),
  .sous-menu__panneau[data-vue-active="2"] .sous-menu__vue:nth-child(3) {
    transform: none;
    transition: opacity 180ms linear;
  }
}
/* Tant qu'aucun rang n'est retenu — au repos, ou sans script du tout —
   c'est la première vue qui s'affiche, et elle seule est cliquable. */
.sous-menu__panneau:not([data-vue-active]) .sous-menu__vue[data-vue-defaut] {
  pointer-events: auto;
}

/* Plus de `:has()` ici : le rang est porté par un attribut, que tout
   navigateur sait lire. Sans script, la première image reste affichée
   et cliquable — le panneau perd le changement au survol, rien d'autre. */

/* Le parent signale qu'une de ses sections est active — sans quoi
   l'entrée « Le restaurant » ne se distingue plus une fois qu'on a
   commencé à lire la page. */
.sous-menu:has(a[aria-current="true"]) > a { color: var(--accent); }

/* Dans le menu plein écran, les enfants sont en retrait sous leur
   parent — pas dans un accordéon : trois entrées de plus ne justifient
   pas un pli de plus à ouvrir. */
.voile-menu__enfant {
  font-size: clamp(1.1rem, 4.5vw, 1.45rem) !important;
  padding-left: 1.2em;
  color: var(--texte-doux) !important;
  border-bottom: 0 !important;
}
.voile-menu nav a + .voile-menu__enfant { padding-top: .35em; }

/* =====================================================================
   LE SOMMAIRE d'une page longue — EN MOBILE SEULEMENT

   Sur grand écran, le sous-menu de la barre de navigation mène déjà aux
   mêmes sections : afficher les deux, c'est proposer deux fois la même
   chose à trente centimètres d'écart. Le sommaire ne sert donc qu'en
   dessous de 64 rem, là où la navigation se replie dans le menu plein
   écran et où plus rien n'indique ce que la page contient.

   Il se colle sous l'en-tête au défilement — et son fond ne se pose
   QU'UNE FOIS collé : posé d'emblée, il forme une pastille grise
   flottant sur rien.

   `top` se règle sur --haut-entete, que le script remesure QUAND la
   classe de l'en-tête change : une mesure prise une seule fois vaudrait
   l'état déployé, et le sommaire se figerait dix-sept pixels trop bas.
   ===================================================================== */
.sommaire { display: none; }
@media (max-width: 63.99rem) {
.sommaire {
  display: block;
  position: sticky; top: var(--haut-entete); z-index: var(--z-collant);
  border-bottom: 1px solid transparent;
  transition: background var(--sortie), border-color var(--sortie);
}
.sommaire.collee {
  /* OPAQUE, pas à 97 % : une barre collante a du contenu qui défile
     dessous, et trois pour cent de transparence suffisent à le laisser
     voir — des images passent derrière les libellés et le tout devient
     illisible. Le flou n'y change rien, il ne fait que brouiller ce
     qu'on aperçoit. */
  background: var(--p-fond);
  border-bottom-color: var(--lisere);
}
.sommaire__liste {
  display: flex; gap: .45rem;
  padding-block: .7rem;
  /* Les ancres DÉFILENT horizontalement plutôt que d'empiler deux
     rangées collantes qui mangeraient l'écran. */
  overflow-x: auto; flex-wrap: nowrap;
  scrollbar-width: none;
  /* Le défilement s'arrête sur une pastille, jamais au milieu. */
  scroll-snap-type: x proximity;
  /* Une marge de départ et d'arrivée : la première et la dernière
     pastille ne se collent pas au bord de l'écran. */
  scroll-padding-inline: var(--marge-page);
}
.sommaire__liste::-webkit-scrollbar { display: none; }

/* DES PASTILLES, pas du texte nu. Posée sur un fond sombre, une rangée
   de mots gris ne se lit pas comme une barre de navigation : rien ne
   dit qu'on peut cliquer, ni qu'il y en a d'autres plus loin. Un fond,
   un contour et un rayon suffisent à le dire sans un mot. */
.sommaire__liste a {
  position: relative; white-space: nowrap; flex: none;
  scroll-snap-align: start;
  padding: .45rem .85rem;
  border-radius: var(--rayon-rond);
  border: 1px solid var(--lisere);
  background: color-mix(in srgb, var(--p-texte) 5%, transparent);
  text-decoration: none; color: var(--texte-doux);
  font-size: var(--t-menu);
  transition: background var(--sortie-court), color var(--sortie-court),
              border-color var(--sortie-court);
}
.sommaire__liste a[aria-current] {
  background: var(--accent-bouton); border-color: transparent; color: #fff;
}
@media (hover: hover) {
  .sommaire__liste a:hover { border-color: color-mix(in srgb, var(--p-texte) 28%, transparent); color: var(--texte); }
  .sommaire__liste a[aria-current]:hover { color: #fff; }
}

/* Un voile au bord droit : il dit qu'il y a la suite. Sans lui, une
   pastille coupée net ressemble à un défaut d'affichage.

   Pas de `position: relative` ici : `sticky` positionne déjà, et le
   redéclarer l'écrase — la barre cessait de coller et défilait avec la
   page, sans que rien d'autre ne change à l'œil. */
.sommaire::after {
  content: ""; position: absolute; inset: 0 0 0 auto; width: 2.6rem;
  background: linear-gradient(to right, transparent, var(--p-fond) 78%);
  pointer-events: none;
}
.sommaire.aubout::after { opacity: 0; transition: opacity var(--sortie); }
@media (hover: hover) { .sommaire__liste a:hover::after { right: 0; } }
}
