/* ============================================================
   SILLON — Chapitre 04 / ATLANTIQUE
   Système de design. Démonstration Niveau 1 pour Étage Zéro.

   Écrit à la main, sans framework ni compilation : le dépôt se
   publie tel quel sur Cloudflare Pages, et tout ce que décrit le
   brief — lignes topographiques animées, menu plein écran,
   curseur personnalisé, lightbox, filtres — se fait en natif.
   ============================================================ */

:root {
  /* --- Palette du brief ---------------------------------- */
  --encre:   #151715;   /* typographie principale */
  --craie:   #F1EEE5;   /* fond principal, respiration */
  --ocean:   #18363B;   /* navigation, fonds sombres, topographie */
  --algue:   #647566;   /* décoratif — voir la note ci-dessous */
  --sable:   #C7AD84;   /* cartes, repères, détails */
  --rouille: #C6623B;   /* accent vivant : filets, repères, focus */

  /* --- Trois variantes ajoutées, et pourquoi -------------
     La palette du brief est juste à l'œil mais ne tient pas le
     seuil de lisibilité de 4,5:1 sur trois usages qu'il prévoit
     lui-même. Plutôt que de changer ses couleurs, on ajoute une
     variante pour chaque usage fautif :

     · Algue sur craie plafonne à 4,23 — insuffisant pour du texte
       courant, alors que le brief lui donne les « états
       secondaires ». D'où --algue-texte, à 5,79.

     · Rouille est désignée couleur des boutons, mais AUCUN texte
       ne passe dessus : blanc 4,03, craie 3,47, encre 4,47. Le
       seuil est raté de trois centièmes dans le meilleur des cas.
       D'où --rouille-fond, à 5,08 avec du texte craie.

     · Rouille sur océan tombe à 3,20. D'où --rouille-clair, à
       4,90, pour les accents posés sur les fonds sombres.

     La Rouille du brief reste intacte partout où elle ne porte
     pas de texte : filets, repères, soulignements, tracés. */
  --algue-texte:   #525F54;   /* 5,79 sur craie */
  --rouille-fond:  #A04C29;   /* 5,08 avec texte craie dessus */
  --rouille-clair: #DE8B63;   /* 4,90 sur océan */

  /* Sable ne porte jamais de texte sur fond clair : 1,86 sur
     craie, il échoue même au seuil des grands titres. Sur océan
     il monte à 5,98 et devient le texte secondaire des sections
     sombres — les deux couleurs échangent leurs rôles selon le
     fond, exactement comme sur le site d'Étage Zéro. */

  /* --- Typographie --------------------------------------- */
  --display: "Bodoni Moda", "Didot", "Times New Roman", serif;
  --ui:      "Archivo", "Helvetica Neue", Arial, sans-serif;
  --mono:    "Space Mono", "SF Mono", Menlo, monospace;

  /* --- Échelle d'espacement, multiples de 4 -------------- */
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 20px;
  --space-5: 32px;
  --space-6: 48px;
  --space-7: 72px;
  --space-8: 104px;
  --space-9: 144px;
  --space-10: 200px;

  /* --- Mise en page -------------------------------------- */
  --container: 1360px;
  --texte-max: 68ch;
  --marge: 20px;

  /* Rayons très faibles ou nuls : le brief parle d'une identité
     éditoriale, pas d'une interface logicielle. */
  --radius: 0px;
  --radius-carte: 10px;

  /* --- Mouvement ----------------------------------------- */
  --ease-editorial: cubic-bezier(.22, .68, .28, 1);
  --t-hover:  170ms;   /* 120-220 ms au brief */
  --t-texte:  560ms;   /* 450-700 ms */
  --t-image:  720ms;   /* 500-900 ms */
  --t-page:   700ms;   /* 500-900 ms */
}

@media (min-width: 900px) {
  :root { --marge: 44px; }
}

/* ============================================================
   1 · Base
   ============================================================ */

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}

body {
  margin: 0;
  background: var(--craie);
  color: var(--encre);
  font-family: var(--ui);
  font-size: 16px;
  line-height: 1.62;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

@media (min-width: 900px) {
  body { font-size: 17px; }
}

img, video, svg { max-width: 100%; display: block; }
h1, h2, h3, h4, p, figure, blockquote, ul, ol { margin: 0; }
ul, ol { padding: 0; list-style: none; }

/* Le focus reste visible partout. Le brief l'exige nommément :
   « cohérent avec la DA, jamais supprimé sans alternative ». */
:focus-visible {
  outline: 2px solid var(--rouille);
  outline-offset: 3px;
}

/* ============================================================
   2 · Conteneurs et grille éditoriale
   ============================================================ */

.enveloppe {
  max-width: var(--container);
  margin: 0 auto;
  padding-left: var(--marge);
  padding-right: var(--marge);
}

.section { padding: var(--space-7) 0; }
@media (min-width: 900px) {
  .section { padding: var(--space-9) 0; }
}

.section--sombre {
  background: var(--ocean);
  color: var(--craie);
}
.section--sombre .dit { color: var(--sable); }

/* ============================================================
   3 · Typographie éditoriale
   ============================================================ */

.titre-geant,
.titre,
.sous-titre {
  font-family: var(--display);
  font-weight: 400;
  line-height: 1.02;
  letter-spacing: -0.015em;
}

/* Les tailles fluides évitent une cascade de points de rupture :
   le titre respire à toutes les largeurs sans réglage manuel. */
.titre-geant { font-size: clamp(52px, 13vw, 190px); }
.titre       { font-size: clamp(34px, 6.2vw, 82px); }
.sous-titre  { font-size: clamp(24px, 3.4vw, 40px); line-height: 1.12; }

.dit {
  color: var(--algue-texte);
  max-width: var(--texte-max);
}

.chapeau {
  font-size: clamp(18px, 2.1vw, 23px);
  line-height: 1.5;
  max-width: 54ch;
}

/* Micro-label : le système éditorial du brief — numéro de
   chapitre, coordonnées, mois, territoire. */
.label {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--algue-texte);
}
.section--sombre .label { color: var(--sable); }

.coord {
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: 0.1em;
}

/* ============================================================
   4 · Boutons
   ============================================================ */

.bouton {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  min-height: 52px;
  padding: 0 var(--space-5);
  font-family: var(--ui);
  font-size: 14px;
  font-weight: 500;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  text-decoration: none;
  border: 1px solid transparent;
  border-radius: var(--radius);
  cursor: pointer;
  transition: background var(--t-hover) var(--ease-editorial),
              color var(--t-hover) var(--ease-editorial),
              border-color var(--t-hover) var(--ease-editorial);
}

/* Fond rouille assombri : c'est la seule variante sur laquelle un
   texte atteint le seuil de lisibilité. */
.bouton--plein {
  background: var(--rouille-fond);
  color: var(--craie);
}
.bouton--plein:hover { background: #8E4423; }

.bouton--ligne {
  background: transparent;
  color: var(--encre);
  border-color: var(--encre);
}
.bouton--ligne:hover { background: var(--encre); color: var(--craie); }

.section--sombre .bouton--ligne { color: var(--craie); border-color: var(--craie); }
.section--sombre .bouton--ligne:hover { background: var(--craie); color: var(--ocean); }

/* ============================================================
   5 · Ligne topographique — motif identitaire
   ============================================================ */

/* Le brief en fait « le motif identitaire principal » : séparateur,
   loader, fond de menu, tracé au défilement. Un seul composant SVG,
   décliné par la classe. Le tracé s'anime par stroke-dashoffset,
   jamais par l'opacité — un bloc qui ne s'affiche pas vaut mieux
   qu'un bloc invisible dont on ignore qu'il est là. */
.topo {
  width: 100%;
  height: auto;
  fill: none;
  stroke: var(--rouille);
  stroke-width: 1.2;
  stroke-linecap: round;
}
.topo--pale { stroke: var(--sable); }
.section--sombre .topo { stroke: var(--rouille-clair); }

.separateur { padding: var(--space-6) 0 0; }

/* ============================================================
   6 · Accessibilité du mouvement
   ============================================================ */

/* Le brief demande « une alternative calme et complète ». On ne se
   contente donc pas d'accélérer les transitions à 0,01 ms : les
   effets qui n'ont plus de sens sans mouvement sont supprimés, et
   tout ce qui doit être lu reste en place. */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    transition-delay: 0s !important;
  }
}

/* Réservé aux lecteurs d'écran. */
.hors-ecran {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* Lien d'évitement : premier arrêt au clavier sur chaque page. */
.evitement {
  position: absolute;
  left: var(--marge);
  top: -60px;
  z-index: 200;
  background: var(--ocean);
  color: var(--craie);
  padding: var(--space-3) var(--space-4);
  text-decoration: none;
  transition: top var(--t-hover) var(--ease-editorial);
}
.evitement:focus { top: var(--space-3); }

/* ============================================================
   7 · Loader — première entrée seulement
   ============================================================ */

/* Le loader se retire TOUT SEUL, en CSS. C'est un correctif important :
   la première version attendait un `setTimeout` pour disparaître, et si le
   script ne s'exécutait pas — bloqué, en erreur, ou dans une fenêtre dont
   les minuteries sont suspendues — le voile restait et la page entière
   devenait inaccessible. Un élément qui masque le contenu ne doit jamais
   dépendre de JavaScript pour s'effacer.

   L'animation part seule au chargement, et `forwards` la laisse à son état
   final. Le script ne sert plus qu'à sauter l'attente aux visites
   suivantes. */
.loader {
  position: fixed;
  inset: 0;
  z-index: 300;
  background: var(--ocean);
  color: var(--craie);
  display: grid;
  place-items: center;
  animation: loader-sortie 620ms var(--ease-editorial) 1400ms forwards;
}
@keyframes loader-sortie {
  to {
    transform: translateY(-101%);
    visibility: hidden;
    pointer-events: none;
  }
}
/* Retrait immédiat demandé par le script (visite déjà faite). */
.loader--parti {
  animation: none;
  transform: translateY(-101%);
  visibility: hidden;
  pointer-events: none;
}

.loader__in { text-align: center; padding: var(--space-4); }
.loader__mot {
  font-family: var(--display);
  font-size: clamp(44px, 9vw, 92px);
  letter-spacing: 0.04em;
  line-height: 1;
}
.loader__chap {
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--sable);
  margin-top: var(--space-3);
}
.loader__topo {
  width: min(380px, 70vw);
  margin: var(--space-5) auto 0;
  stroke: var(--rouille-clair);
  stroke-width: 1.4;
  fill: none;
}
.loader__topo path {
  stroke-dasharray: 620;
  stroke-dashoffset: 620;
  animation: tracer 1200ms var(--ease-editorial) forwards;
}
.loader__topo path:nth-child(2) { animation-delay: 160ms; }
@keyframes tracer { to { stroke-dashoffset: 0; } }

/* ============================================================
   8 · Bandeau de démonstration
   ============================================================ */

.bandeau {
  position: relative;
  z-index: 60;
  background: var(--encre);
  color: var(--craie);
  text-align: center;
  font-size: 12.5px;
  letter-spacing: 0.02em;
  padding: var(--space-2) var(--marge);
}
.bandeau a { color: var(--sable); }

/* ============================================================
   9 · En-tête
   ============================================================ */

.entete {
  position: sticky;
  top: 0;
  z-index: 50;
  background: transparent;
  transition: background var(--t-hover) var(--ease-editorial),
              border-color var(--t-hover) var(--ease-editorial);
  border-bottom: 1px solid transparent;
}
/* Transparente sur le hero, puis lisible dès qu'on descend — le brief
   demande « transparent sur hero, puis version compacte et lisible ». */
.entete--pose {
  background: var(--craie);
  border-bottom-color: rgba(21,23,21,.12);
}

.entete__in {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  max-width: var(--container);
  margin: 0 auto;
  padding: var(--space-3) var(--marge);
  transition: padding var(--t-hover) var(--ease-editorial);
}
.entete--pose .entete__in { padding-top: var(--space-2); padding-bottom: var(--space-2); }

.marque {
  font-family: var(--display);
  font-size: 24px;
  letter-spacing: 0.14em;
  text-decoration: none;
  color: var(--craie);
  margin-right: auto;
  min-height: 44px;
  display: inline-flex;
  align-items: center;
  transition: color var(--t-hover) var(--ease-editorial);
}
.entete--pose .marque { color: var(--encre); }

.nav { display: none; }
.entete__cta { display: none; }

@media (min-width: 1000px) {
  .nav {
    display: flex;
    gap: var(--space-5);
    margin-right: auto;
    margin-left: var(--space-6);
  }
  .nav a {
    color: var(--craie);
    text-decoration: none;
    font-size: 14px;
    letter-spacing: 0.05em;
    /* 44 px de haut, la règle du projet pour tout élément cliquable.
       Le filet reste collé au texte grâce au conteneur interne. */
    min-height: 44px;
    display: inline-flex;
    align-items: center;
    border-bottom: 1px solid transparent;
    transition: color var(--t-hover) var(--ease-editorial),
                border-color var(--t-hover) var(--ease-editorial);
  }
  .entete--pose .nav a { color: var(--encre); }
  .nav a:hover { border-bottom-color: currentColor; }
  .entete__cta { display: inline-flex; min-height: 44px; }
  .marque { margin-right: 0; }
}

/* Bouton du menu plein écran */
.burger {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  min-height: 44px;
  padding: 0 var(--space-2);
  background: none;
  border: 0;
  cursor: pointer;
  color: var(--craie);
  font-family: var(--ui);
  font-size: 12px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}
.entete--pose .burger { color: var(--encre); }
.burger__trait {
  display: block;
  width: 22px; height: 1px;
  background: currentColor;
  margin: 3px 0;
}
.burger__trait + .burger__trait { width: 14px; }
.burger__mot { margin-left: var(--space-1); }

@media (min-width: 1000px) { .burger { margin-left: var(--space-4); } }

/* ============================================================
   10 · Menu plein écran
   ============================================================ */

.menu {
  position: fixed;
  inset: 0;
  z-index: 90;
  background: var(--ocean);
  color: var(--craie);
  display: grid;
  align-content: center;
  padding: var(--space-8) var(--marge) var(--space-6);
  overflow-y: auto;
}
.menu[hidden] { display: none; }

.menu__fond { position: absolute; inset: 0; pointer-events: none; }
.menu__fond svg { width: 100%; height: 100%; }
.menu__lignes path {
  fill: none;
  stroke: var(--rouille-clair);
  stroke-width: 1;
  opacity: .5;
}

.menu__nav { position: relative; max-width: var(--container); margin: 0 auto; width: 100%; }
.menu__nav ul { display: grid; gap: var(--space-1); }
.menu__nav a {
  display: block;
  font-family: var(--display);
  font-size: clamp(34px, 8vw, 78px);
  line-height: 1.14;
  color: var(--craie);
  text-decoration: none;
  padding: var(--space-1) 0;
  transition: color var(--t-hover) var(--ease-editorial);
}
.menu__nav a::before {
  content: attr(data-i);
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: 0.1em;
  color: var(--sable);
  margin-right: var(--space-4);
  vertical-align: super;
}
.menu__nav a:hover { color: var(--rouille-clair); }

.menu__pied {
  position: relative;
  margin-top: var(--space-6);
  color: var(--sable);
  max-width: var(--container);
  margin-left: auto;
  margin-right: auto;
  width: 100%;
}

/* ============================================================
   11 · Hero
   ============================================================ */

.hero {
  position: relative;
  min-height: 88svh;
  display: flex;
  align-items: flex-end;
  margin-top: -74px;      /* passe sous l'en-tête transparent */
  padding-top: 74px;
  overflow: hidden;
  background: var(--ocean);
}
.hero__media { position: absolute; inset: 0; }
.hero__media img {
  width: 100%; height: 100%;
  object-fit: cover;
  /* Le mouvement remplace la vidéo du brief : une échelle très lente,
     imperceptible image par image, qui donne vie au plan fixe sans peser
     un mégaoctet. */
  animation: respire 26s ease-in-out infinite alternate;
}
@keyframes respire { from { transform: scale(1); } to { transform: scale(1.07); } }

/* Voile de lisibilité : le brief l'exige — « texte toujours lisible sur
   photos ; overlays/gradients si nécessaire ». */
.hero::after {
  content: "";
  position: absolute; inset: 0;
  background:
    /* Voile dédié à la barre de navigation : la roche du haut de l'image est
       claire, et sans lui les liens en craie tombaient sous le seuil de
       lisibilité. Il s'arrête à 170 px pour ne pas assombrir la photo. */
    linear-gradient(to bottom, rgba(10,14,14,.80) 0, rgba(10,14,14,.46) 190px, rgba(10,14,14,0) 360px),
    linear-gradient(to top,
      rgba(10,14,14,.88) 0%, rgba(10,14,14,.64) 38%, rgba(10,14,14,.2) 74%, rgba(10,14,14,.1) 100%);
}

.hero__chap { color: var(--rouille-clair); margin-top: var(--space-3); }
.hero__dates { color: var(--craie); }
.bouton--clair { color: var(--craie); border-color: var(--craie); }
.bouton--clair:hover { background: var(--craie); color: var(--ocean); }

/* ============================================================
   12 · Manifeste
   ============================================================ */

.manifeste__mot { margin: var(--space-4) 0 var(--space-5); }
.manifeste__accent { color: var(--rouille-fond); }
.manifeste__dit { color: var(--algue-texte); }

/* Révélation par masque : le texte monte derrière une fenêtre qui le
   découpe. Uniquement du `transform` — sans le script, tout est déjà
   en place et lisible. */
.reveal { display: block; overflow: hidden; }
.reveal > span { display: block; }
.js-anim .reveal > span { transform: translateY(105%); }
.js-anim .vu .reveal > span,
.js-anim .reveal.vu > span {
  transform: translateY(0);
  transition: transform var(--t-texte) var(--ease-editorial);
}
.js-anim .reveal:nth-child(2) > span { transition-delay: 70ms; }
.js-anim .reveal:nth-child(3) > span { transition-delay: 150ms; }
.js-anim .reveal:nth-child(4) > span { transition-delay: 220ms; }

/* ============================================================
   13 · En-tête de section sur deux colonnes
   ============================================================ */

.entete-section { display: grid; gap: var(--space-4); }
.entete-section__dit { color: var(--algue-texte); }
@media (min-width: 900px) {
  .entete-section {
    grid-template-columns: 1.2fr .8fr;
    gap: var(--space-7);
    align-items: end;
  }
}

/* ============================================================
   14 · Aperçu de la carte
   ============================================================ */

.plats { display: grid; gap: var(--space-6); margin-top: var(--space-7); }
@media (min-width: 900px) {
  .plats { grid-template-columns: repeat(3, 1fr); gap: var(--space-5); }
  /* Décalage vertical : une grille parfaitement alignée ferait catalogue,
     le brief demande une composition éditoriale. */
  .plat:nth-child(2) { margin-top: var(--space-7); }
  .plat:nth-child(3) { margin-top: var(--space-4); }
}

.plat__media { overflow: hidden; background: var(--sable); }
.plat__media img {
  width: 100%;
  /* `height: auto` est indispensable : les attributs `width` et `height` du
     HTML — nécessaires pour réserver la place et éviter le décalage au
     chargement — comptent comme une hauteur explicite, et le navigateur
     ignore alors `aspect-ratio`. Sans cette ligne les images s'affichaient
     en 403 × 800 au lieu du 3:2 demandé. */
  height: auto;
  aspect-ratio: 3 / 2;
  object-fit: cover;
  transition: transform var(--t-image) var(--ease-editorial);
}
.plat:hover .plat__media img { transform: scale(1.04); }
.plat__txt { padding-top: var(--space-4); }
.plat__txt .sous-titre { margin: var(--space-2) 0; }
.plat__prix { color: var(--rouille-fond); }

.apercu__lien { margin-top: var(--space-7); }

/* ============================================================
   15 · Le lieu
   ============================================================ */

.lieu { background: var(--ocean); color: var(--craie); display: grid; }
/* Même raison que pour les plats : `height: auto` rend la main à
   `aspect-ratio`, que les attributs HTML neutralisaient. */
.lieu__media img { width: 100%; height: auto; aspect-ratio: 4 / 3; object-fit: cover; }
.lieu__txt {
  padding: var(--space-7) var(--marge);
  display: grid;
  align-content: center;
  gap: var(--space-4);
  max-width: 640px;
}
.lieu__txt .label { color: var(--sable); }
.lieu__txt .chapeau { color: var(--sable); }
.lieu__cuisine {
  font-family: var(--display);
  font-size: clamp(28px, 3.6vw, 44px);
  color: var(--rouille-clair);
  line-height: 1.1;
}
@media (min-width: 900px) {
  .lieu { grid-template-columns: 1fr 1fr; align-items: stretch; }
  /* En desktop la photo occupe toute la colonne : la hauteur vient de la
     grille, pas du rapport d'image. */
  .lieu__media { display: grid; }
  .lieu__media img { height: 100%; aspect-ratio: auto; min-height: 420px; }
  .lieu__txt { padding: var(--space-9) var(--space-7); }
}

/* ============================================================
   16 · Avis
   ============================================================ */

/* Un avis inventé se signale AVANT d'être lu, pas en petit dessous. */
.avertissement {
  display: inline-block;
  margin: var(--space-4) 0 var(--space-5);
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--rouille);
  color: var(--rouille-fond);
  font-size: 13px;
}
.avis__bloc { max-width: 24ch; }
.avis__bloc .sous-titre { max-width: 20ch; }
@media (min-width: 900px) {
  .avis__bloc { max-width: 34ch; }
  .avis__bloc .sous-titre { max-width: none; }
}
.avis__source { margin-top: var(--space-4); }

/* ============================================================
   17 · Appel final
   ============================================================ */

.final { background: var(--ocean); color: var(--craie); }
.final .label { color: var(--sable); }
.final .chapeau { color: var(--sable); margin-top: var(--space-4); }
.final__in { display: grid; gap: var(--space-3); }
.final__actions { display: flex; flex-wrap: wrap; gap: var(--space-3); margin-top: var(--space-5); }
.final__note { color: var(--sable); margin-top: var(--space-4); }

/* ============================================================
   18 · Pied de page
   ============================================================ */

.pied { background: var(--encre); color: var(--craie); padding: var(--space-7) 0 var(--space-8); }
.pied__mot {
  font-family: var(--display);
  font-size: clamp(26px, 4vw, 46px);
  line-height: 1.1;
  max-width: 18ch;
}
.pied__cols { display: grid; gap: var(--space-5); margin: var(--space-7) 0 var(--space-6); }
.pied .dit { color: var(--sable); margin-top: var(--space-2); }
.pied .label { color: var(--craie); }
.pied a { color: var(--sable); }
.pied__bas { color: var(--sable); border-top: 1px solid rgba(241,238,229,.16); padding-top: var(--space-4); }
@media (min-width: 900px) {
  .pied__cols { grid-template-columns: repeat(3, 1fr); gap: var(--space-6); }
}

/* ============================================================
   19 · Barre de conversion mobile
   ============================================================ */

.barre-mobile {
  position: fixed;
  left: 0; right: 0; bottom: 0;
  z-index: 45;
  display: grid;
  grid-template-columns: 1fr 1fr 1.2fr;
  background: var(--craie);
  border-top: 1px solid rgba(21,23,21,.14);
}
.barre-mobile a {
  min-height: 56px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  text-decoration: none;
  color: var(--encre);
  font-size: 13px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
.barre-mobile__cta { background: var(--rouille-fond); color: var(--craie); }
/* La barre mange l'espace du bas : on le rend au pied de page. */
body { padding-bottom: 56px; }

@media (min-width: 1000px) {
  .barre-mobile { display: none; }
  body { padding-bottom: 0; }
}

/* ============================================================
   20 · Curseur personnalisé — desktop à pointeur fin uniquement
   ============================================================ */

.curseur { display: none; }

/* `pointer: fine` exclut le tactile, et le script vérifie en plus le
   mouvement réduit. Le brief l'impose : « pas de custom cursor sur mobile ». */
@media (pointer: fine) and (min-width: 1000px) {
  .js-curseur .curseur {
    display: grid;
    place-items: center;
    position: fixed;
    top: 0; left: 0;
    z-index: 400;   /* au-dessus de la visionneuse (250) et du loader (300) : masqué derrière, le curseur laissait le visiteur sans repère puisque le curseur natif est caché */
    pointer-events: none;
    mix-blend-mode: difference;
    /* Tant que la souris n'a pas bougé, le curseur serait un point noir
       collé dans l'angle supérieur gauche. On ne le montre qu'au premier
       mouvement — c'est le seul endroit du site où l'on masque par
       `visibility`, parce qu'il s'agit d'un ornement et non d'un contenu. */
    visibility: hidden;
    transition: transform 90ms linear;
  }
  .js-curseur .curseur--pret { visibility: visible; }
  .js-curseur .curseur__point {
    width: 9px; height: 9px;
    border-radius: 50%;
    background: var(--craie);
    transition: transform 200ms var(--ease-editorial);
  }
  .js-curseur .curseur__mot {
    position: absolute;
    font-family: var(--mono);
    font-size: 10px;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--craie);
    opacity: 0;
  }
  /* Sur une cible, le point devient un disque qui porte le mot. */
  .js-curseur .curseur--actif .curseur__point { transform: scale(6.4); }
  .js-curseur .curseur--actif .curseur__mot { opacity: 1; }
  .js-curseur, .js-curseur a, .js-curseur button { cursor: none; }
}

/* ============================================================
   21 · Apparition des blocs au défilement
   ============================================================ */

/* Même règle que sur la démonstration artisan, apprise à la dure : on
   n'anime jamais l'opacité d'un bloc de contenu. Au pire un bloc reste
   posé 18 px plus bas, ce qui ne se voit pas — alors qu'une opacité
   bloquée laisse une section entièrement blanche. */
.js-anim .appar { transform: translateY(18px); }
.js-anim .appar.vu {
  transform: none;
  transition: transform var(--t-image) var(--ease-editorial);
}

@media (prefers-reduced-motion: reduce) {
  .js-anim .appar,
  .js-anim .reveal > span { transform: none; }
  .hero__media img { animation: none; }
  .plat:hover .plat__media img { transform: none; }
  .loader { display: none; }
}

/* ============================================================
   22 · Page Le Concept
   ============================================================ */

.page-hero { padding-top: var(--space-7); }
.page-hero__titre { margin: var(--space-4) 0 var(--space-5); }
.page-hero__dit { color: var(--algue-texte); }

/* --- Les trois phases --- */
.phases__liste { display: grid; gap: var(--space-6); }
.phases__num { color: var(--rouille-fond); }
.phases__liste h3 { margin: var(--space-2) 0 var(--space-3); }
@media (min-width: 900px) {
  .phases__liste { grid-template-columns: repeat(3, 1fr); gap: var(--space-6); }
  .phases__liste li { padding-top: var(--space-4); border-top: 1px solid rgba(21,23,21,.16); }
}

/* --- Produit → Geste → Assiette ---------------------------
   L'image tient en haut de l'écran pendant que le texte défile.
   Sur mobile la colonne collante n'a pas de sens : tout repasse en pile,
   et chaque étape reste lisible sans aucune interaction. */

.parcours { background: var(--ocean); color: var(--craie); padding: var(--space-7) 0; }
.parcours .label { color: var(--sable); }
.parcours .dit { color: var(--sable); }

.parcours__in { display: grid; gap: var(--space-6); }

.parcours__cadre {
  position: relative;
  margin: 0;
  aspect-ratio: 3 / 2;
  overflow: hidden;
  background: #0F2226;
}
.parcours__img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
/* Les images se succèdent par fondu. C'est le SEUL endroit du site où
   l'on anime une opacité, et c'est admis ici : il ne s'agit pas d'un bloc
   de contenu mais de trois variantes de la même illustration. Chacune
   porte son propre texte alternatif, et sans JavaScript la première
   reste affichée — rien ne disparaît. */
.js-anim .parcours__img { opacity: 0; transition: opacity 520ms var(--ease-editorial); }
.js-anim .parcours__img.est-actif { opacity: 1; }

.etape { padding: var(--space-5) 0; border-top: 1px solid rgba(241,238,229,.18); }
.etape:first-of-type { border-top: 0; }
.etape__num { color: var(--rouille-clair); }
.etape h3 { margin: var(--space-2) 0 var(--space-3); }

@media (min-width: 900px) {
  .parcours { padding: var(--space-9) 0; }
  .parcours__in { grid-template-columns: 1fr 1fr; gap: var(--space-7); align-items: start; }
  .parcours__media { position: sticky; top: 96px; }
  .etape { padding: var(--space-8) 0; }
  .etape:first-of-type { padding-top: 0; }
}

/* --- Carte du territoire --- */
.carte { display: grid; gap: var(--space-6); margin-top: var(--space-7); }
@media (min-width: 900px) {
  .carte { grid-template-columns: .8fr 1.2fr; gap: var(--space-7); align-items: start; }
}

.carte__dessin { position: relative; max-width: 300px; margin: 0 auto; width: 100%; }
@media (min-width: 900px) {
  /* Le dessin occupe sa colonne : à 180 px il flottait dans le vide. */
  .carte__dessin { max-width: 420px; margin: 0; }
}
.carte__svg { width: 100%; height: auto; }
.carte__trait { fill: none; stroke: var(--encre); stroke-width: 1.4; stroke-linejoin: round; }
.carte__houle { fill: none; stroke: var(--sable); stroke-width: 1.1; }

/* Chaque point est un vrai bouton : 44 px de zone tactile, atteignable au
   clavier, avec un état visible quand il est choisi. */
.carte__point {
  position: absolute;
  left: var(--x); top: var(--y);
  width: 44px; height: 44px;
  margin: -22px 0 0 -22px;
  padding: 0;
  background: none;
  border: 0;
  cursor: pointer;
  display: grid;
  place-items: center;
}
.carte__point::before {
  content: "";
  width: 11px; height: 11px;
  border-radius: 50%;
  background: var(--craie);
  border: 1.5px solid var(--encre);
  transition: background var(--t-hover) var(--ease-editorial),
              transform var(--t-hover) var(--ease-editorial);
}
.carte__point:hover::before { transform: scale(1.25); }
.carte__point[aria-pressed="true"]::before {
  background: var(--rouille-fond);
  border-color: var(--rouille-fond);
  transform: scale(1.35);
}

.carte__fiches { position: relative; }
.fiche img {
  width: 100%; height: auto;
  aspect-ratio: 3 / 2;
  object-fit: cover;
  margin-bottom: var(--space-4);
}
.fiche h3 { margin: var(--space-2) 0 var(--space-3); }
.fiche + .fiche { margin-top: var(--space-6); padding-top: var(--space-6); border-top: 1px solid var(--ez-trait, rgba(21,23,21,.16)); }

/* Avec JavaScript, une seule fiche à la fois. Sans lui, les trois restent
   empilées et lisibles — c'est la version qui fait foi. */
.js-anim .carte__fiches .fiche { display: none; }
.js-anim .carte__fiches .fiche.est-actif { display: block; }
.js-anim .fiche + .fiche { margin-top: 0; padding-top: 0; border-top: 0; }

.territoire__note { margin-top: var(--space-6); }

/* --- Archives des chapitres --- */
.chapitres { display: grid; gap: var(--space-5); margin-top: var(--space-7); }
@media (min-width: 900px) { .chapitres { grid-template-columns: repeat(4, 1fr); } }

.chapitre {
  padding-top: var(--space-4);
  border-top: 1px solid rgba(21,23,21,.16);
  color: var(--algue-texte);
}
.chapitre h3 { color: var(--algue-texte); margin: var(--space-2) 0; }
.chapitre__num { color: var(--algue-texte); }

/* Le chapitre en cours est le seul en pleine encre : les précédents ont
   eu lieu, ils ne sont plus au menu. */
.chapitre--actif { border-top-color: var(--rouille-fond); color: var(--encre); }
.chapitre--actif h3, .chapitre--actif .chapitre__num { color: var(--encre); }
.chapitre--actif .dit { color: var(--algue-texte); }
.chapitre__etat {
  display: inline-block;
  margin-top: var(--space-3);
  padding: var(--space-1) var(--space-3);
  background: var(--rouille-fond);
  color: var(--craie);
  font-size: 11px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}

@media (prefers-reduced-motion: reduce) {
  .js-anim .parcours__img { transition: none; }
  .carte__point:hover::before { transform: none; }
}

/* ============================================================
   23 · Correction d'espacement autour des séparateurs
   ============================================================ */

/* Un séparateur CLÔT sa section. Trois bourrages se cumulaient :
   celui du bas du séparateur (48), celui du bas de la section (144)
   et celui du haut de la section suivante (144) — soit 336 px de vide
   mesurés entre la vague et le texte suivant. On supprime les deux
   premiers : la vague se rattache au bloc qu'elle termine, et l'écart
   avec la suite redevient l'espacement normal entre deux sections. */
.manifeste, .page-hero { padding-bottom: 0; }

/* La section qui SUIT un séparateur repartait sur 144 px de respiration,
   alors que le trait vient déjà de marquer la coupure. Mesuré depuis la
   vague visible, cela faisait 185 px de vide. On repasse à 48 px. */
.manifeste + .section,
.page-hero + .section { padding-top: var(--space-6); }

/* ============================================================
   24 · Page La Carte
   ============================================================ */

/* --- Navigation interne ---
   Ce sont de vraies ancres : elles fonctionnent sans JavaScript. Le
   repérage de la section en cours est le seul apport du script. */
.ancres {
  position: sticky;
  top: 0;
  z-index: 40;
  background: var(--craie);
  border-bottom: 1px solid rgba(21,23,21,.12);
}
.ancres__in { display: flex; gap: var(--space-5); overflow-x: auto; }
.ancres a {
  flex: none;
  min-height: 52px;
  display: inline-flex;
  align-items: center;
  color: var(--algue-texte);
  text-decoration: none;
  font-size: 13px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  border-bottom: 2px solid transparent;
  transition: color var(--t-hover) var(--ease-editorial),
              border-color var(--t-hover) var(--ease-editorial);
}
.ancres a:hover { color: var(--encre); }
.ancres a.actif { color: var(--encre); border-bottom-color: var(--rouille-fond); }

/* --- La liste des mets --- */
.carte-plats__in { display: grid; gap: var(--space-6); }

.famille + .famille { margin-top: var(--space-7); }
.famille__nom {
  padding-bottom: var(--space-3);
  border-bottom: 1px solid rgba(21,23,21,.16);
}

.mets {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-4);
  padding: var(--space-4) 0;
  border-bottom: 1px solid rgba(21,23,21,.08);
}
.mets__nom {
  font-family: var(--display);
  font-size: clamp(20px, 2.4vw, 27px);
  line-height: 1.2;
}
.mets__prix { color: var(--rouille-fond); flex: none; }

.carte-plats__note { margin-top: var(--space-6); font-size: 15px; }

/* --- Panneau d'illustration, desktop uniquement --------------
   Le brief autorise une photo au survol « avec contraste préservé ».
   Elle n'ajoute aucune information : le nom et le prix sont dans la
   liste. D'où `aria-hidden` et des `alt` vides — un lecteur d'écran
   n'a rien à y gagner, et sur mobile le panneau disparaît pour que la
   carte reste un texte qu'on lit. */
.carte-plats__vue { display: none; }

@media (min-width: 1000px) {
  .carte-plats__in { grid-template-columns: 1.1fr .9fr; gap: var(--space-7); align-items: start; }
  .carte-plats__vue { display: block; position: sticky; top: 132px; }
  .vue__cadre {
    position: relative;
    aspect-ratio: 3 / 2;
    overflow: hidden;
    background: var(--sable);
  }
  .vue__img {
    position: absolute; inset: 0;
    width: 100%; height: 100%;
    object-fit: cover;
    opacity: 0;
    transition: opacity 420ms var(--ease-editorial);
  }
  .vue__img.est-actif { opacity: 1; }

  /* Le met survolé se décale : on voit lequel commande l'image. */
  .mets { transition: padding-left var(--t-hover) var(--ease-editorial); }
  .mets:hover, .mets.est-actif { padding-left: var(--space-3); }
  .mets.est-actif .mets__nom { color: var(--rouille-fond); }
}

/* --- Menu dégustation --- */
.degustation { background: var(--ocean); color: var(--craie); }
.degustation .label { color: var(--sable); }
.degustation .dit { color: var(--sable); }
.degustation__in { display: grid; gap: var(--space-4); max-width: 720px; }

.degustation__prix {
  display: flex;
  align-items: baseline;
  gap: var(--space-3);
  flex-wrap: wrap;
  margin-top: var(--space-3);
}
.degustation__chiffre {
  font-family: var(--display);
  font-size: clamp(46px, 7vw, 86px);
  line-height: 1;
  color: var(--rouille-clair);
}

.accords { display: grid; gap: var(--space-2); margin: var(--space-4) 0; }
.accords li {
  display: flex;
  justify-content: space-between;
  gap: var(--space-4);
  padding: var(--space-3) 0;
  border-bottom: 1px solid rgba(241,238,229,.18);
  color: var(--sable);
}
.accords .coord { color: var(--craie); }

.degustation__duree { font-size: 15px; }

/* --- Boissons --- */
.boissons__cols { display: grid; gap: var(--space-6); margin-top: var(--space-7); }
.boissons__cols .famille + .famille { margin-top: 0; }
.boissons .mets { padding: var(--space-3) 0; }
.boissons .mets__nom { font-size: clamp(17px, 1.7vw, 20px); }
@media (min-width: 900px) {
  .boissons__cols { grid-template-columns: repeat(3, 1fr); gap: var(--space-6); }
}

@media (prefers-reduced-motion: reduce) {
  .vue__img { transition: none; }
  .mets:hover, .mets.est-actif { padding-left: 0; }
}

/* La barre d'ancres se cale SOUS l'en-tête, qui mesure 69 px et colle déjà
   en haut. À top:0 les deux se superposaient. */
.ancres { top: 69px; }
@media (min-width: 1000px) { .carte-plats__vue { top: 150px; } }

/* ============================================================
   25 · Avis — une citation à la fois
   ============================================================ */

/* Le brief demande « une citation majeure à la fois ». Sans JavaScript,
   les trois restent empilées et lisibles : c'est la version qui fait foi,
   le défilement n'est qu'un confort. */
.avis__bloc + .avis__bloc { margin-top: var(--space-6); padding-top: var(--space-6); border-top: 1px solid rgba(21,23,21,.14); }

.js-anim .avis__bloc { display: none; }
.js-anim .avis__bloc.est-actif { display: block; }
.js-anim .avis__bloc + .avis__bloc { margin-top: 0; padding-top: 0; border-top: 0; }

.avis__nav { display: none; gap: var(--space-2); margin-top: var(--space-6); }
.js-anim .avis__nav { display: flex; }

/* Vrais boutons : 44 px de zone tactile, atteignables au clavier. */
.avis__point {
  width: 44px; height: 44px;
  padding: 0;
  background: none;
  border: 0;
  cursor: pointer;
  display: grid;
  place-items: center;
}
.avis__point::before {
  content: "";
  width: 9px; height: 9px;
  border-radius: 50%;
  border: 1px solid var(--algue-texte);
  transition: background var(--t-hover) var(--ease-editorial),
              border-color var(--t-hover) var(--ease-editorial);
}
.avis__point:hover::before { border-color: var(--encre); }
.avis__point.est-actif::before { background: var(--rouille-fond); border-color: var(--rouille-fond); }

/* ============================================================
   26 · Page Le Restaurant
   ============================================================ */

.matieres { display: grid; gap: var(--space-6); margin-top: var(--space-7); }
@media (min-width: 1000px) {
  .matieres { grid-template-columns: 1.15fr .85fr; gap: var(--space-7); align-items: start; }
  .matieres__photo { position: sticky; top: 100px; }
}

.matieres__photo { position: relative; }
.matieres__photo img { width: 100%; height: auto; aspect-ratio: 1 / 1; object-fit: cover; }

/* Repères posés sur la photo. Vrais boutons : 44 px, clavier, tactile. */
.matieres__point {
  position: absolute;
  left: var(--x); top: var(--y);
  width: 44px; height: 44px;
  margin: -22px 0 0 -22px;
  padding: 0;
  background: none;
  border: 0;
  cursor: pointer;
  display: grid;
  place-items: center;
}
.matieres__point::before {
  content: "";
  width: 13px; height: 13px;
  border-radius: 50%;
  background: rgba(241,238,229,.9);
  border: 1.5px solid var(--encre);
  transition: background var(--t-hover) var(--ease-editorial),
              transform var(--t-hover) var(--ease-editorial);
}
.matieres__point:hover::before { transform: scale(1.2); }
.matieres__point[aria-pressed="true"]::before {
  background: var(--rouille-fond);
  border-color: var(--rouille-fond);
  transform: scale(1.35);
}

/* Sans JavaScript, les quatre matières restent empilées et lisibles.
   Les repères ne font que raccourcir le parcours. */
.matiere + .matiere { margin-top: var(--space-5); padding-top: var(--space-5); border-top: 1px solid rgba(21,23,21,.14); }
.matiere h3 { margin: var(--space-2) 0 var(--space-3); }

.js-anim .matieres__liste .matiere { display: none; }
.js-anim .matieres__liste .matiere.est-actif { display: block; }
.js-anim .matiere + .matiere { margin-top: 0; padding-top: 0; border-top: 0; }

/* --- Informations pratiques --- */
.pratique__cols { display: grid; gap: var(--space-6); margin-top: var(--space-7); }
@media (min-width: 900px) { .pratique__cols { grid-template-columns: repeat(3, 1fr); gap: var(--space-6); } }

.pratique__bloc { padding-top: var(--space-4); border-top: 1px solid rgba(21,23,21,.16); }
.pratique__bloc > * + * { margin-top: var(--space-3); }
.pratique__fort {
  font-family: var(--display);
  font-size: clamp(21px, 2.4vw, 27px);
  line-height: 1.2;
}
.pratique__contact a { color: var(--encre); }

.horaires { display: grid; gap: var(--space-2); }
.horaires > div {
  display: flex;
  justify-content: space-between;
  gap: var(--space-4);
  padding: var(--space-2) 0;
  border-bottom: 1px solid rgba(21,23,21,.08);
}
.horaires dt { color: var(--algue-texte); font-size: 15px; }
.horaires dd { margin: 0; font-family: var(--mono); font-size: 13px; text-align: right; }
.horaires__ferme { color: var(--rouille-fond); }

.pratique__capacite {
  display: flex;
  align-items: baseline;
  gap: var(--space-3);
  flex-wrap: wrap;
  margin-top: var(--space-8);
  padding-top: var(--space-5);
  border-top: 1px solid rgba(21,23,21,.16);
}
.pratique__chiffre {
  font-family: var(--display);
  font-size: clamp(56px, 9vw, 120px);
  line-height: 1;
  color: var(--rouille-fond);
}

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

/* Un repère posé sur une photo doit se voir quelle que soit la photo.
   Le repère actif, en rouille, devenait invisible sur le bloc de cuisine
   en acier patiné — même teinte. Un anneau clair et une ombre nette le
   détachent de tout fond, sans ajouter d'ombre portée décorative. */
.matieres__point::before {
  box-shadow: 0 0 0 2px rgba(241,238,229,.85);
}
.matieres__point[aria-pressed="true"]::before {
  box-shadow: 0 0 0 3px rgba(241,238,229,.95);
}

/* ============================================================
   27 · Page Galerie
   ============================================================ */

/* --- Filtres ---
   Masqués sans JavaScript : filtrer est un confort, et un bouton qui ne
   fait rien vaut moins que pas de bouton du tout. Les dix-neuf images
   restent alors toutes affichées. */
.filtres { display: none; flex-wrap: wrap; gap: var(--space-2); margin-top: var(--space-5); }
.js-anim .filtres { display: flex; }

.filtre {
  min-height: 44px;
  padding: 0 var(--space-4);
  background: none;
  border: 1px solid rgba(21,23,21,.22);
  border-radius: var(--radius);
  cursor: pointer;
  font-family: var(--ui);
  font-size: 13px;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--algue-texte);
  transition: color var(--t-hover) var(--ease-editorial),
              background var(--t-hover) var(--ease-editorial),
              border-color var(--t-hover) var(--ease-editorial);
}
.filtre:hover { color: var(--encre); border-color: var(--encre); }
.filtre.est-actif {
  background: var(--encre);
  border-color: var(--encre);
  color: var(--craie);
}
.filtres__compte { display: none; margin-top: var(--space-4); }
.js-anim .filtres__compte { display: block; }

/* --- La grille éditoriale ---
   Le brief interdit la grille 3×3 : les formats alternent, certaines
   images occupent deux colonnes, d'autres sont hautes. Sur mobile tout
   repasse en une colonne, où l'alternance n'aurait aucun sens. */
.gal { display: grid; gap: var(--space-4); margin-top: var(--space-6); }

@media (min-width: 700px) {
  .gal { grid-template-columns: repeat(2, 1fr); gap: var(--space-5); }
}
@media (min-width: 1100px) {
  /* Six colonnes, et un cycle de sept vignettes qui remplit exactement
     chaque rangée : 4+2, puis 2+4, puis 2+2+2. Les largeurs alternent
     donc sans jamais laisser de trou.

     La version precedente melangeait des elements sur deux rangees avec
     des largeurs variables : le placement automatique ne trouvait plus
     ou les poser et laissait des vides au milieu de la grille. */
  .gal {
    grid-template-columns: repeat(6, 1fr);
    grid-auto-rows: 290px;
    gap: var(--space-5);
  }
  .gal__item { grid-column: span 2; }
  .gal__item:nth-child(7n+1),
  .gal__item:nth-child(7n+4) { grid-column: span 4; }

  /* La derniere vignette occupe la largeur restante : sans elle, la
     grille se terminait sur une image seule et quatre colonnes vides. */
  .gal__item:last-child { grid-column: span 6; }

  /* Chaque image remplit sa case : c est ce qui garantit des rangees
     d une seule hauteur, donc aucun decalage. */
  .gal__ouvrir { height: 100%; }
  .gal__ouvrir img,
  .gal__item--haut .gal__ouvrir img {
    height: 100%;
    aspect-ratio: auto;
  }
}

.gal__item { margin: 0; }
.gal__ouvrir {
  display: block;
  width: 100%;
  padding: 0;
  border: 0;
  background: var(--sable);
  cursor: pointer;
  overflow: hidden;
}
.gal__ouvrir img {
  width: 100%;
  height: auto;
  aspect-ratio: 3 / 2;
  object-fit: cover;
  transition: transform var(--t-image) var(--ease-editorial);
}
.gal__item--haut .gal__ouvrir img { aspect-ratio: 3 / 4; }
.gal__ouvrir:hover img { transform: scale(1.03); }
/* Plus de légende sous les vignettes : le brief la place dans la
   visionneuse, pas dans la grille. Dix-neuf libellés sous dix-neuf
   images faisaient un catalogue, pas une galerie. Le titre vit
   maintenant dans un attribut data-titre, que la visionneuse lit. */

/* --- Visionneuse --- */
.loupe {
  position: fixed;
  inset: 0;
  z-index: 250;
  background: rgba(11,17,18,.97);
  color: var(--craie);
  display: grid;
  grid-template-columns: 64px 1fr 64px;
  grid-template-rows: auto 1fr;
  align-items: center;
  padding: var(--space-3);
}
.loupe[hidden] { display: none; }

.loupe__barre {
  grid-column: 1 / -1;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  padding: 0 var(--space-2) var(--space-3);
}
.loupe__compte { color: var(--sable); }
.loupe__fermer {
  min-height: 44px;
  padding: 0 var(--space-4);
  background: none;
  border: 1px solid rgba(241,238,229,.4);
  color: var(--craie);
  cursor: pointer;
  font-family: var(--ui);
  font-size: 12px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}
.loupe__fermer:hover { background: var(--craie); color: var(--ocean); }

.loupe__nav {
  width: 56px; height: 56px;
  background: none;
  border: 0;
  cursor: pointer;
  color: var(--craie);
  display: grid;
  place-items: center;
}
.loupe__nav svg { width: 26px; height: 26px; fill: none; stroke: currentColor; stroke-width: 1.5; }
.loupe__nav:hover { color: var(--rouille-clair); }

.loupe__cadre {
  margin: 0;
  min-width: 0;
  display: grid;
  gap: var(--space-3);
  justify-items: center;
  align-content: center;
}
.loupe__cadre img {
  max-width: 100%;
  max-height: 74svh;
  width: auto; height: auto;
  object-fit: contain;
}
.loupe__leg { color: var(--sable); text-align: center; }

@media (max-width: 699px) {
  /* Sur mobile les flèches passent sous l'image : à 44 px de côté elles
     mangeaient un tiers de la largeur utile. */
  .loupe { grid-template-columns: 1fr; grid-template-rows: auto 1fr auto; }
  .loupe__cadre { grid-row: 2; }
  .loupe__nav--prec { grid-row: 3; justify-self: start; }
  .loupe__nav--suiv { grid-row: 3; justify-self: end; }
}

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

/* ============================================================
   28 · Page Réserver
   ============================================================ */

.avertissement--large { max-width: 62ch; margin-top: var(--space-5); }

/* --- Parcours en trois étapes --- */
.parcours-resa { display: grid; gap: var(--space-6); margin-top: var(--space-7); }
@media (min-width: 1000px) {
  .parcours-resa { grid-template-columns: repeat(3, 1fr); gap: var(--space-6); align-items: start; }
}

.etape-resa {
  margin: 0;
  padding: var(--space-5) 0 0;
  border: 0;
  border-top: 1px solid rgba(21,23,21,.16);
}
.etape-resa legend {
  padding: 0;
  font-family: var(--display);
  font-size: clamp(21px, 2.3vw, 27px);
  line-height: 1.2;
  display: flex;
  align-items: baseline;
  gap: var(--space-3);
}
.etape-resa__num { color: var(--rouille-fond); }
.etape-resa > * + * { margin-top: var(--space-4); }
.etape-resa__note { font-size: 14px; }

/* Les choix sont de vrais boutons radio : le clavier et les lecteurs
   d'écran les comprennent nativement. Seule l'apparence change. */
.choix { display: flex; flex-wrap: wrap; gap: var(--space-2); }
.choix__op { position: relative; }
.choix__op input {
  position: absolute;
  opacity: 0;
  width: 100%; height: 100%;
  margin: 0;
  cursor: pointer;
}
.choix__op span {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 52px;
  min-height: 48px;
  padding: 0 var(--space-3);
  border: 1px solid rgba(21,23,21,.24);
  font-family: var(--mono);
  font-size: 13px;
  color: var(--algue-texte);
  transition: background var(--t-hover) var(--ease-editorial),
              color var(--t-hover) var(--ease-editorial),
              border-color var(--t-hover) var(--ease-editorial);
}
.choix__op input:hover + span { border-color: var(--encre); color: var(--encre); }
.choix__op input:checked + span {
  background: var(--encre);
  border-color: var(--encre);
  color: var(--craie);
}
/* Le focus clavier doit se voir : la case elle-même est transparente. */
.choix__op input:focus-visible + span {
  outline: 2px solid var(--rouille);
  outline-offset: 2px;
}
.choix--service span, .choix--creneaux span { font-family: var(--ui); letter-spacing: 0.04em; }

/* --- Récapitulatif --- */
.recap { display: grid; gap: var(--space-3); }
.recap__ligne {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-4);
  padding-bottom: var(--space-2);
  border-bottom: 1px solid rgba(21,23,21,.1);
}
.recap strong { font-family: var(--display); font-size: 20px; font-weight: 400; }

/* --- Formulaire de contact --- */
.contact { background: var(--ocean); color: var(--craie); }
.contact .label { color: var(--sable); }
.contact .chapeau, .contact .dit { color: var(--sable); }
.contact a { color: var(--craie); }

.contact__in { display: grid; gap: var(--space-6); }
@media (min-width: 1000px) {
  .contact__in { grid-template-columns: .85fr 1.15fr; gap: var(--space-8); align-items: start; }
}
.contact__intro > * + * { margin-top: var(--space-4); }
.contact__coord { font-size: 15px; }

.form { display: grid; gap: var(--space-4); }
.ch { display: grid; gap: var(--space-2); }
.ch label { font-size: 14px; letter-spacing: 0.03em; }
.contact .ch label { color: var(--craie); }

.ch input, .ch select, .ch textarea {
  width: 100%;
  min-height: 50px;
  padding: var(--space-3) 0;
  background: transparent;
  border: 0;
  border-bottom: 1px solid rgba(241,238,229,.34);
  color: var(--craie);
  font-family: var(--ui);
  font-size: 16px;
  border-radius: 0;
}
.ch textarea { min-height: 120px; resize: vertical; }
.ch input:focus, .ch select:focus, .ch textarea:focus {
  outline: none;
  border-bottom-color: var(--rouille-clair);
}
.ch select option { color: var(--encre); }

/* Le champ « date » du parcours est sur fond clair, pas sombre. */
.etape-resa .ch input {
  border-bottom-color: rgba(21,23,21,.28);
  color: var(--encre);
}
.etape-resa .ch label { color: var(--encre); }
.etape-resa .ch input:focus { border-bottom-color: var(--rouille-fond); }

/* Champ fautif : le filet passe à 2 px en plus de la couleur — la teinte
   seule ne suffit pas à qui distingue mal les couleurs. */
.ch [aria-invalid="true"] { border-bottom: 2px solid var(--rouille-clair); }
.erreur {
  margin-top: var(--space-2);
  font-size: 13px;
  color: var(--rouille-clair);
  line-height: 1.45;
}

.form__confidentialite { font-size: 14px; max-width: 52ch; }
.form__recu {
  padding: var(--space-5);
  border: 1px solid var(--rouille-clair);
  color: var(--craie);
  font-family: var(--display);
  font-size: clamp(20px, 2.4vw, 27px);
  line-height: 1.3;
}
.form__recu[hidden] { display: none; }

/* ============================================================
   29 · Corrections relevées à l'audit des six pages
   ============================================================ */

/* Le sélecteur `.barre-mobile a` (une classe + un type) l'emportait sur
   `.barre-mobile__cta` (une classe) : le texte du bouton restait en encre
   sur le fond rouille, à 3,06. On remonte la spécificité. */
.barre-mobile a.barre-mobile__cta { color: var(--craie); }

/* Sur fond océan, `--algue-texte` tombe à 1,92 : il est calibré pour le
   fond craie. Le texte secondaire des sections sombres prend le sable,
   comme partout ailleurs sur le site. */
.lieu__txt .dit,
.parcours .dit,
.degustation .dit { color: var(--sable); }

/* ============================================================
   30 · Hero recomposé — le langage de la carte marine
   ============================================================ */

/* La première version empilait label, titre, dates et boutons en bas à
   gauche : exactement la composition du site du menuisier, qui utilise la
   même photo plein écran. Deux démonstrations qui se ressemblent ne
   démontrent rien.

   Ici les informations sont posées aux quatre coins, comme les mentions
   d'une carte marine, et le titre traverse toute la largeur. Même photo,
   même contenu, composition sans rapport. */

.hero__grille {
  position: relative;
  z-index: 2;
  width: 100%;
  color: var(--craie);
  display: grid;
  gap: var(--space-5);
  padding-top: var(--space-6);
  padding-bottom: var(--space-6);
}

.hero__ancre { margin: 0; }
.hero__ancre--hg, .hero__ancre--hd { color: var(--sable); }

.hero__centre { display: grid; gap: var(--space-3); }
.hero__chap { color: var(--rouille-clair); }

/* Le titre occupe toute la largeur disponible. `clamp` sur la vue plutôt
   qu'une taille fixe : il touche les deux bords à toutes les largeurs. */
.hero__titre {
  font-family: var(--display);
  font-weight: 400;
  font-size: clamp(46px, 15.5vw, 260px);
  line-height: .92;
  letter-spacing: -0.02em;
  margin: 0;
}

/* Le trait topographique a ete retire du hero. Une seule courbe, presque
   plate sur 1800 px, ne se lisait pas comme une courbe de niveau mais
   comme un soulignement mal cale — le motif garde ses trois emplois
   ailleurs, ou il a la place de se deployer. */
.hero__dates { color: var(--craie); }

@media (min-width: 900px) {
  /* Trois rangées : les mentions en haut, le titre au milieu, les actions
     en bas — chacune tirée vers les bords opposés. */
  .hero__grille {
    grid-template-columns: 1fr auto;
    grid-template-rows: auto 1fr auto;
    align-content: space-between;
    min-height: 74svh;
    gap: var(--space-6) var(--space-5);
    padding-top: var(--space-7);
    padding-bottom: var(--space-7);
  }
  .hero__ancre--hg { grid-column: 1; grid-row: 1; }
  .hero__ancre--hd { grid-column: 2; grid-row: 1; text-align: right; }
  .hero__centre    { grid-column: 1 / -1; grid-row: 2; align-content: center; }
  .hero__ancre--bg { grid-column: 1; grid-row: 3; }
  .hero__ancre--bd { grid-column: 2; grid-row: 3; text-align: right; }

  /* Les dates passent à droite, sous le trait : la ligne du bas se lit
     alors d'un bord à l'autre, comme une échelle de carte. */
  .hero__dates { text-align: right; }
}

/* Le hero ne se cale plus en bas : la composition occupe toute la hauteur. */
.hero { align-items: stretch; }
.hero__grille { align-self: stretch; }

/* Les deux mentions des coins hauts tombaient sur la roche claire, hors de
   portée du voile : en sable elles étaient illisibles. Elles passent en
   craie, et le voile du haut descend plus bas pour les couvrir. */
.hero__ancre--hg, .hero__ancre--hd { color: var(--craie); }

@media (max-width: 899px) {
  /* En mobile la composition redevient une pile : on resserre, sinon les
     six éléments s'étalent sur toute la hauteur de l'écran. */
  .hero__grille { gap: var(--space-4); padding-top: var(--space-5); padding-bottom: var(--space-5); }
  .hero__centre { gap: var(--space-2); }
  .hero__ancre--bg, .hero__ancre--bd { margin-top: 0; }
  .hero__ancre--bd { margin-top: calc(var(--space-2) * -1); }
}

/* ============================================================
   31 · Icône du menu et avis côte à côte
   ============================================================ */

/* Les deux traits étaient enfants directs du bouton, qui est en `flex`
   horizontal : ils se plaçaient donc côte à côte et se lisaient comme
   deux tirets de ponctuation. Ils sont maintenant empilés dans leur
   propre conteneur. */
.burger__icone {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 5px;
}
.burger__trait { display: block; width: 20px; height: 1.5px; background: currentColor; margin: 0; }
.burger__trait + .burger__trait { width: 13px; }

/* --- Les trois avis, côte à côte ---
   Le brief demandait « une citation majeure à la fois ». Les afficher
   ensemble supprime le défilement, mais aussi toute dépendance au script :
   il n'y a plus rien à faire fonctionner pour que les trois se lisent. */
.avis__nav { display: none !important; }

.js-anim .avis__bloc { display: block; }
.avis__bloc { max-width: none; }
.avis__bloc .sous-titre { max-width: none; font-size: clamp(19px, 1.9vw, 23px); line-height: 1.35; }

.avis__grille { display: grid; gap: var(--space-6); margin-top: var(--space-5); }
@media (min-width: 900px) {
  .avis__grille { grid-template-columns: repeat(3, 1fr); gap: var(--space-6); }
}
.avis__grille .avis__bloc {
  margin: 0;
  padding-top: var(--space-4);
  border-top: 1px solid rgba(21,23,21,.18);
}
.js-anim .avis__grille .avis__bloc + .avis__bloc { margin-top: 0; padding-top: var(--space-4); border-top: 1px solid rgba(21,23,21,.18); }

/* --- Surfaces de clic ------------------------------------------------------
   Relevé le 3 septembre 2026 par le contrôle automatique : trois liens
   faisaient 16 à 19 px de haut, là où la règle en demande 44. Le padding
   agrandit la cible, la marge négative la reprend pour que rien ne bouge
   à l'œil. Sur le téléphone d'un restaurant, ce n'est pas un détail. */
.pratique__contact a,
.contact__coord a,
.pied__bas a,
.bandeau-zone .bandeau a {
  display: inline-block;
  padding: 13px 4px;
  margin: -13px 0;
  vertical-align: middle;
}
