/* ============================================
   Chez L'Oncle Phil — V2 Spline
   Style système propre, mobile-first, épuré
   ============================================ */

:root {
    /* PALETTE "COUCHER DE SOLEIL" (28/09) : corail plus profond et plus
       saturé, brun-nuit chaud à la place du bleu-marine — reprend l'ambiance
       déjà annoncée dans le sous-titre du site ("du petit-déj au coucher de
       soleil"). Choisie parmi 3 options montrées et comparées en direct par
       le patron ; ni la mise en page ni les photos n'ont changé. */
    --phil-blue: #4a2b23;
    --phil-gold: #e8a23f;
    --phil-coral: #d9613f;
    /* Le corail seul mesure ~3,3:1 sur fond clair — insuffisant pour du texte
       de lecture (min. 4,5:1), mais dans la norme pour boutons/gros texte
       décoratif. Cette version plus sombre (~5:1) ne remplace PAS le corail
       des boutons/bordures, qui reste inchangé — elle ne sert qu'au TEXTE lu :
       prix, étiquettes, liens. */
    --phil-coral-texte: #b3431f;
    --phil-cream: #faf3e6;
    --phil-cream-2: #f2e0c4;
    --phil-white: #ffffff;
    --radius-xl: 40px;
    --radius-lg: 24px;
    --radius-md: 16px;
    --shadow-lift: 0 20px 40px -10px rgba(217, 97, 63, 0.18), 0 10px 20px -5px rgba(232, 162, 63, 0.08);
    --shadow-soft: 0 4px 20px rgba(74, 43, 35, 0.06);
    --easing: cubic-bezier(0.2, 0.8, 0.2, 1);
}

* { box-sizing: border-box; margin: 0; padding: 0; -webkit-tap-highlight-color: transparent; }
/* UN SEUL CONTENEUR DE DÉFILEMENT : la fenêtre. Corrigé le 02/10.
   `overflow-x: hidden` était posé sur html ET sur body. Seul celui de html se
   reporte sur la fenêtre ; celui de body faisait alors de body un conteneur
   défilant À PART ENTIÈRE, emboîté dans la page (mesuré : body défilait de 6 px
   tout seul, davantage pendant les animations de sections). Sur iPhone, le
   doigt s'accroche au conteneur le plus proche qui peut bouger : le geste
   déplaçait body de quelques pixels puis plus rien — la page « figée, qui
   repart au geste suivant », signalée sans cause apparente.
   `clip` coupe le débordement horizontal sans créer de conteneur défilant. Un
   Safari antérieur à 16 ignore la valeur : body reste alors `visible`, et c'est
   la règle de html qui retient le débordement — jamais deux conteneurs.
   `clip` sur LES DEUX AXES, pas seulement l'horizontal : les sections entrent
   en scène avec une translation, et le pied de page ainsi décalé dépassait du
   bas de 5 px tant qu'il n'était pas arrivé. La hauteur du document changeait
   donc en cours de défilement ; sur ordinateur, le défilement lissé (Lenis)
   visait alors un bas de page qui n'existait plus et ne s'arrêtait jamais. */
html { background: var(--phil-cream); overflow-x: hidden; }
body { background: var(--phil-cream); color: var(--phil-blue); font-family: 'Nunito', sans-serif; line-height: 1.6; overflow: clip; -webkit-font-smoothing: antialiased; }

h1, h2, h3, h4, .font-title { font-family: 'Fredoka', sans-serif; font-weight: 500; letter-spacing: -0.01em; line-height: 1.15; }
.handwritten { font-family: 'Pacifico', cursive; font-weight: 400; color: var(--phil-coral); }
img { max-width: 100%; height: auto; display: block; }
button { font-family: inherit; cursor: pointer; border: none; background: none; color: inherit; }
a { color: inherit; text-decoration: none; }
::selection { background: var(--phil-coral); color: white; }

.center { text-align: center; }
.center-block { text-align: center; }

/* === PROGRESS BAR === */
.scroll-progress {
    position: fixed; top: 0; left: 0; height: 3px; width: 0;
    background: linear-gradient(90deg, var(--phil-gold), var(--phil-coral));
    z-index: 1000; transition: width 0.05s linear;
}

/* === NAV === */
nav {
    position: fixed; top: 0; left: 0; right: 0; z-index: 100;
    padding: 0.75rem 1.5rem;
    display: flex; justify-content: space-between; align-items: center;
    background: rgba(251, 248, 241, 0.85);
    backdrop-filter: blur(14px) saturate(1.2);
    -webkit-backdrop-filter: blur(14px) saturate(1.2);
    border-bottom: 1px solid rgba(74, 43, 35, 0.05);
    transition: transform 0.4s var(--easing);
}
nav.hidden-nav { transform: translateY(-100%); }
/* Le pastille « P » et le nom en texte ont laissé la place au tampon lui-même.
   La hauteur, pas la largeur, est la mesure qui compte : le mot « L'ONCLE PHIL »
   déborde volontairement du cercle, donc l'image est plus large que haute et un
   dimensionnement par la largeur l'aurait rendue minuscule dans la barre. */
.nav-logo {
    display: flex; align-items: center;
    line-height: 0;                    /* évite l'espace fantôme sous une image en ligne */
}
.nav-logo img {
    height: 46px; width: auto; display: block;
}

.nav-links { display: flex; align-items: center; gap: 0.25rem; }
.nav-links a {
    font-family: 'Fredoka', sans-serif; font-size: 0.85rem;
    padding: 0.4rem 0.85rem; border-radius: 20px;
    transition: all 0.2s; opacity: 0.65;
}
.nav-links a:hover { opacity: 1; background: rgba(217, 97, 63, 0.08); }
.nav-links a.active { opacity: 1; color: var(--phil-coral-texte); }
.menu-btn { display: none; font-size: 1.4rem; padding: 0.4rem 0.6rem; }

/* === SECTIONS === */
section {
    padding: 6rem 1.5rem;
    position: relative;
    /* `svh` avant tout, `vh` en repli pour les navigateurs antérieurs à 2022.
       Sur iOS, `100vh` vaut la hauteur de la fenêtre SANS la barre d'URL : une
       section haute de 100vh dépasse donc l'écran réellement visible tant que
       cette barre est affichée, et son bas est coupé. `svh` — small viewport
       height — est par définition la hauteur la plus petite, barre comprise :
       la section tient toujours. */
    min-height: 100vh;
    min-height: 100svh;
    display: flex;
    align-items: center;
}
.section-inner { max-width: 1100px; margin: 0 auto; width: 100%; }
.section-label {
    display: inline-block;
    font-family: 'Fredoka', sans-serif; font-size: 0.75rem;
    text-transform: uppercase; letter-spacing: 3px;
    color: var(--phil-coral-texte); margin-bottom: 1rem; opacity: 0.85;
}
.section-label.center { display: block; text-align: center; }
h2 { font-size: clamp(2rem, 5vw, 3.3rem); margin-bottom: 1rem; }
.section-sub { font-size: 1.05rem; opacity: 0.65; margin-bottom: 2.5rem; max-width: 640px; }
.section-sub.center { margin-left: auto; margin-right: auto; text-align: center; }
/* Dans un bloc centré le sous-titre doit l'être aussi : sans ça son
   max-width de 640px le collait à gauche d'un conteneur de 1100px. */
.center-block .section-sub { margin-left: auto; margin-right: auto; }

/* ================================================================
   §1 HERO
================================================================ */
/* Le hero est la SEULE section sans z-index : il ne crée donc pas de contexte
   d'empilement, ce qui permet au CTA de passer AU-DESSUS de la gaufrette 3D
   (layer z-index 12). Les autres sections restent à 5, donc la gaufrette
   passe devant elles. */
#hero { padding: 5rem 1.5rem 3rem; text-align: center; z-index: auto; }
.hero-inner { display: flex; flex-direction: column; align-items: center; gap: 1rem; }
.hero-badge {
    display: inline-flex; align-items: center; gap: 0.4rem;
    background: white; padding: 0.4rem 1rem; border-radius: 24px;
    font-size: 0.85rem; font-family: 'Fredoka', sans-serif;
    box-shadow: var(--shadow-soft);
}
.hero-badge .star { color: var(--phil-gold); }
/* Discrète à dessein : cette étiquette informe, elle ne doit pas rivaliser
   avec le badge d'avis juste au-dessus (la vraie accroche de confiance). */
.hero-badge-secondaire {
    background: transparent; box-shadow: none; padding: 0.15rem 0;
    font-size: 0.75rem; opacity: 0.55; margin-top: -0.5rem;
}
.hero-title { font-size: clamp(2.4rem, 6vw, 4.5rem); }
.hero-sub { font-size: 1.05rem; opacity: 0.8; max-width: 560px; }
.hero-sub-detail { font-size: 0.9rem; opacity: 0.65; }

/* Layer fixe où vit la gaufrette 3D.

   z-index 12 = DEVANT les panneaux de section (5), DERRIÈRE la barre de
   navigation (30), la barre de progression (40) et le panneau de détail (500).

   Elle passait auparavant DERRIÈRE les panneaux ; sa trajectoire se lit mieux
   au premier plan, elle traverse la page sans jamais être coupée.

   CONSÉQUENCE À CONNAÎTRE : tant qu'elle était derrière, le fond crème opaque du
   canvas Spline ne se voyait pas — les panneaux le recouvraient. Au premier plan
   il se poserait sur eux comme un disque clair. C'est ce qui impose le masque
   radial serré ci-dessous, et pourquoi son rayon n'est plus une marge de confort
   mais une valeur ajustée au plus près de la gaufrette rendue. */
.gaufrette-3d-layer {
    position: fixed;
    top: 50%; left: 50%;
    width: clamp(280px, 42vw, 520px);
    height: clamp(280px, 42vw, 520px);
    margin-left: calc(clamp(280px, 42vw, 520px) / -2);
    margin-top: calc(clamp(280px, 42vw, 520px) / -2);
    z-index: 12;
    opacity: 1;
    pointer-events: none;
    transform-origin: center center;
    will-change: transform, opacity;
}
.gaufrette-canvas {
    width: 100%; height: 100%;
    display: block;
    /* APPARITION EN FONDU. Le canvas reste invisible tant que le rendu n'est pas
       complet (module prêt ET texture décodée — voir `revelerGaufrette` dans
       script.js) : sans cela on verrait d'abord un disque sans son tampon. Il
       n'y a plus d'image d'attente derrière lui ; ce fondu est donc la seule
       entrée en scène de la gaufrette. */
    opacity: 0;
    transition: opacity 0.4s ease;
    /* Ombre portée calculée sur l'ALPHA réel du rendu : elle épouse la silhouette
       de la gaufrette et suit son inclinaison, là où une ombre dessinée en CSS
       resterait un ovale figé pendant que l'objet pivote. C'est ce qui la pose
       sur la page au lieu de la laisser flotter. */
    filter: drop-shadow(0 16px 22px rgba(150, 100, 50, 0.30));
    /* PLUS DE MASQUE. Le rendu Three.js est réellement transparent : il n'y a
       plus de fond opaque à découper. Le masque radial qui vivait ici a demandé
       quatre réglages successifs et deux campagnes de mesure — trop large il
       laissait un anneau crème sur les panneaux blancs, trop serré il tranchait
       le liseré doré et le « L' » du logo. Ce n'était pas un réglage difficile,
       c'était le symptôme d'un rendu opaque qu'on essayait de rattraper en aval.
       Le problème a disparu avec sa cause. */
}
/* Le badge "Built with Spline" est masqué par JS (MutationObserver sur le shadow DOM).
   Pas d'overlay CSS ici : le layer survole des sections de couleurs différentes,
   un rectangle crème collé au layer se verrait sur les sections blanches. */

.gaufrette-3d-layer.visible .gaufrette-canvas { opacity: 1; }

/* BULLE DE LA GAUFRETTE — façon bande dessinée. Le conteneur est déplacé à
   chaque image par le script (translate3d, pour suivre la gaufrette sans
   recalcul de mise en page) ; c'est le corps, à l'intérieur, qui porte
   l'animation d'apparition. Au-dessus de la gaufrette (12), sous la barre de
   navigation (30) et les panneaux (500).
   Le contour est un tracé SVG étiré à la taille du texte : `non-scaling-stroke`
   garde un trait de même épaisseur quelle que soit la longueur de la phrase.
   La queue est un second tracé, posé par-dessus le bord pour s'y fondre. */
.gaufrette-bulle {
    position: fixed; top: 0; left: 0;
    z-index: 13;
    pointer-events: none;
    will-change: transform;
}
.gaufrette-bulle-corps {
    position: relative; display: block;
    padding: 0.6rem 0.95rem 0.65rem;
    opacity: 0; transform: scale(0.75) rotate(-3deg);
    transform-origin: 0% 80%;
    transition: opacity 0.3s ease, transform 0.5s cubic-bezier(0.34, 1.4, 0.5, 1);
    /* Ombre douce et diffuse : la bulle se pose sur la page sans la marquer. */
    filter: drop-shadow(0 4px 10px rgba(74, 43, 35, 0.12));
}
.bulle-forme, .bulle-queue { position: absolute; overflow: visible; }
.bulle-forme { inset: 0; width: 100%; height: 100%; }
.bulle-queue { width: 22px; height: 18px; left: -16px; bottom: 18%; }
.bulle-forme path, .bulle-queue path {
    fill: var(--phil-white);
    /* Trait fin et teinté plutôt que noir franc : le dessin de BD reste, sans
       la dureté d'un contour sombre. */
    stroke: rgba(74, 43, 35, 0.3); stroke-width: 1.4;
    stroke-linejoin: round; stroke-linecap: round;
    vector-effect: non-scaling-stroke;
}
.bulle-texte {
    position: relative; display: block;
    font-family: 'Fredoka', sans-serif; font-weight: 500;
    font-size: 0.86rem; line-height: 1.25; letter-spacing: 0.01em;
    text-align: center; color: var(--phil-blue);
    text-wrap: balance;   /* lignes de longueur égale, pas de mot seul en bas */
}
.gaufrette-bulle.a-gauche .gaufrette-bulle-corps { transform-origin: 100% 80%; transform: scale(0.75) rotate(3deg); }
.gaufrette-bulle.a-gauche .bulle-queue { left: auto; right: -16px; transform: scaleX(-1); }
.gaufrette-bulle.parle .gaufrette-bulle-corps,
.gaufrette-bulle.a-gauche.parle .gaufrette-bulle-corps { opacity: 0.96; transform: scale(1) rotate(-1deg); }
@media (prefers-reduced-motion: reduce) {
    .gaufrette-bulle-corps { transform: none !important; transition: opacity 0.2s ease; }
}
/* La 3D n'a pas démarré (WebGL indisponible, contexte perdu) : on retire le
   canvas mort. Rien ne le remplace — le reste du site n'en dépend pas. */
.gaufrette-3d-layer.mode-2d .gaufrette-canvas { display: none; }

/* Réserve la place occupée visuellement par la gaufrette 3D (layer fixe).
   La hauteur est ÉCRITE PAR LE JS (--gauf-hero-h) à partir du diamètre réellement
   rendu : le layer est un clamp() de vw, le rail lui applique une échelle et le
   masque radial n'en garde que 84 %. Une valeur devinée en dur donnait 210px pour
   un disque de 253px — le bouton « Bienvenue » se retrouvait posé dessus. */
.hero-spacer {
    width: 100%;
    height: var(--gauf-hero-h, clamp(170px, 22vw, 210px));
}

.hero-cta {
    position: relative;
    z-index: 25;   /* au-dessus de la gaufrette (12), qui passe juste derrière */
    display: inline-flex; align-items: center; gap: 0.5rem;
    padding: 0.95rem 2.3rem;
    background: var(--phil-coral); color: white;
    border: none; cursor: pointer;
    border-radius: 40px;
    font-family: 'Fredoka', sans-serif; font-weight: 500; font-size: 1.05rem;
    box-shadow: 0 14px 32px -8px rgba(217, 97, 63, 0.7), 0 5px 12px -3px rgba(0,0,0,0.12);
    transition: transform 0.3s var(--easing), box-shadow 0.3s var(--easing);
    margin-top: 0.5rem;
}
.hero-cta:hover { transform: translateY(-4px); box-shadow: 0 20px 40px -10px rgba(217, 97, 63, 0.85); }
.hero-cta::before {
    content: ''; position: absolute; inset: -4px;
    border-radius: 40px;
    border: 2px solid rgba(217, 97, 63, 0.35);
    animation: pulse-ring 2.4s infinite;
    pointer-events: none;
}
.cta-arrow { display: inline-block; animation: bounce-arrow 1.8s ease-in-out infinite; }
@keyframes pulse-ring { 0% { opacity: 0.6; transform: scale(1); } 100% { opacity: 0; transform: scale(1.28); } }
@keyframes bounce-arrow { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(3px); } }

.hero-hint {
    position: relative;
    z-index: 25;
    margin-top: 1rem;
    font-size: 0.75rem; opacity: 0.5;
    letter-spacing: 2.5px; text-transform: uppercase;
    animation: hint-bounce 2.5s infinite;
}
@keyframes hint-bounce { 0%, 100% { transform: translateY(0); opacity: 0.4; } 50% { transform: translateY(5px); opacity: 0.85; } }

/* ================================================================
   GRAMMAIRE D'APPARITION — « émergence depuis le plan du panneau »
   ================================================================
   Un seul geste, décliné : le contenu ne surgit pas de nulle part en fondu, il
   pivote sur une charnière ancrée dans la surface du panneau et avance vers le
   lecteur. C'est le prolongement de la logique déjà en place — la gaufrette
   passe DERRIÈRE les panneaux —, appliquée cette fois au contenu.

   Trois conséquences de conception :

   1. La perspective vit sur le CONTENEUR, jamais sur l'élément animé. Une
      `perspective` posée sur l'élément lui-même donne une fuite par élément,
      chacun avec son propre point de vue : l'ensemble se lit comme un collage,
      pas comme un même espace. Sur le conteneur, tous les enfants partagent un
      point de fuite et la scène tient.

   2. L'état de départ est posé par la classe `.js-reveal`, ajoutée par le script
      lui-même. Sans JavaScript, aucun état caché n'est écrit et la page reste
      entièrement lisible — le contenu d'un restaurant ne doit jamais dépendre
      d'une animation pour s'afficher.

   3. Aucun `transition` ici : GSAP écrit `transform` image par image. Une
      transition CSS sur la même propriété se battrait avec lui et rendrait le
      mouvement mou (erreur déjà commise sur .photo). */

.section-inner,
.info-grid {
    perspective: 1400px;
    perspective-origin: 50% 45%;
}

.js-reveal [data-reveal] { will-change: transform, opacity; }

/* États de départ. Volontairement sobres : 20 à 26 degrés et 150 px de recul
   suffisent à faire lire la profondeur. Au-delà, le mouvement devient un tour de
   force qui attire l'attention sur lui-même au lieu de servir le contenu. */
.js-reveal [data-reveal="hinge-bottom"] {
    opacity: 0;
    transform: perspective(1400px) rotateX(-20deg) translate3d(0, 40px, -150px);
    transform-origin: 50% 100%;
}
.js-reveal [data-reveal="hinge-left"] {
    opacity: 0;
    transform: perspective(1400px) rotateY(24deg) translate3d(-38px, 0, -130px);
    transform-origin: 0% 50%;
}
.js-reveal [data-reveal="hinge-right"] {
    opacity: 0;
    transform: perspective(1400px) rotateY(-24deg) translate3d(38px, 0, -130px);
    transform-origin: 100% 50%;
}
/* Avancée pure, sans pivot : pour ce qui doit arriver de face. */
.js-reveal [data-reveal="depth"] {
    opacity: 0;
    transform: perspective(1400px) translate3d(0, 0, -260px) scale(0.94);
}
/* Le geste le plus discret, pour les lignes de texte. */
.js-reveal [data-reveal="lift"] {
    opacity: 0;
    transform: translate3d(0, 26px, 0);
}

/* Mouvement réduit : on n'anime rien et surtout on ne cache rien. */
@media (prefers-reduced-motion: reduce) {
    .js-reveal [data-reveal] { opacity: 1 !important; transform: none !important; }
}

/* ================================================================
   §2 UNIVERS
================================================================ */
#univers { background: var(--phil-white); }
.univers-texte-seul { max-width: 720px; }
.univers-text p { font-size: 1.05rem; opacity: 0.78; margin-bottom: 1rem; }
.btn-outline {
    display: inline-flex; align-items: center; gap: 0.5rem;
    margin-top: 1.5rem; padding: 0.9rem 1.75rem;
    border: 2px solid var(--phil-coral);
    border-radius: 40px; color: var(--phil-coral);
    font-family: 'Fredoka', sans-serif; font-weight: 500;
    transition: all 0.2s var(--easing);
}
.btn-outline:hover { background: var(--phil-coral); color: white; transform: translateY(-2px); }
/* ================================================================
   GALERIE DÉFILANTE §2
   ================================================================
   Remplace une grille 2x2 de hauteur figée qui ne pouvait tenir que trois
   photos — la quatrième recevait une hauteur de zéro et disparaissait.

   Principe repris du bandeau d'avis : une piste en flex, translatée de 0 à
   -50 %, contenu dupliqué à l'identique. Le décalage de moitié tombe donc
   exactement sur la jointure entre les deux copies, et la boucle ne se voit pas.

   Chaque photo garde SES PROPORTIONS : hauteur imposée, largeur libre. Un cadre
   de format fixe aurait recadré au hasard des sources — celles d'aujourd'hui
   sont en portrait 900x1613, une vignette carrée en aurait amputé la moitié. */
.galerie-wrapper {
    position: relative;
    overflow: hidden;
    margin-top: 3rem;
    padding: 0.5rem 0;
}
/* Fondus latéraux : les photos entrent et sortent du champ au lieu d'être
   tranchées net par le bord du panneau. */
.galerie-wrapper::before,
.galerie-wrapper::after {
    content: ''; position: absolute; top: 0; bottom: 0;
    width: clamp(40px, 8vw, 110px); z-index: 2; pointer-events: none;
}
.galerie-wrapper::before { left: 0;  background: linear-gradient(90deg, var(--phil-white), transparent); }
.galerie-wrapper::after  { right: 0; background: linear-gradient(-90deg, var(--phil-white), transparent); }

.galerie {
    display: flex;
    width: max-content;
    /* --duree est écrite par le script d'après la largeur réellement mesurée,
       pour que la vitesse reste constante quel que soit le nombre de photos. */
    animation: galerie-defile var(--duree, 60s) linear infinite;
    will-change: transform;
}
@keyframes galerie-defile {
    from { transform: translate3d(0, 0, 0); }
    to   { transform: translate3d(-50%, 0, 0); }
}
/* On s'arrête quand quelqu'un regarde — au survol comme au doigt. */
.galerie-wrapper:hover .galerie,
.galerie-wrapper.en-pause .galerie { animation-play-state: paused; }

.galerie-piste { display: flex; gap: 1rem; padding-right: 1rem; }

.galerie-photo {
    flex: 0 0 auto;
    height: clamp(190px, 26vw, 300px);
    margin: 0;
    border-radius: var(--radius-lg);
    overflow: hidden;
    box-shadow: var(--shadow-soft);
    transition: box-shadow 0.4s var(--easing), filter 0.4s var(--easing);
}
.galerie-photo img {
    height: 100%; width: auto; display: block;
    /* La largeur suit la hauteur : aucune photo n'est recadrée. */
}
.galerie-photo:hover {
    box-shadow: 0 30px 56px -26px rgba(217, 97, 63, 0.45);
    filter: brightness(1.04);
}

/* Mouvement réduit : la bande s'immobilise et devient simplement parcourable
   au doigt. Le contenu reste accessible, seul le défilement automatique cesse. */
@media (prefers-reduced-motion: reduce) {
    .galerie { animation: none; }
    .galerie-wrapper { overflow-x: auto; }
    .galerie-photo:hover { filter: none; }
}

/* Respect du réglage système « réduire les animations ». On ne coupe pas le
   site : on neutralise les déplacements et on laisse les fondus, pour que rien
   ne devienne invisible. Le JS lit la même préférence et débranche les rails. */
@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
        scroll-behavior: auto !important;
    }
    .photo:hover { filter: none; }
}

/* ================================================================
   §3 CARTE — 3D Carousel orbital
================================================================ */
#carte { background: var(--phil-cream); overflow: visible; }

.menu-3d-scene {
    position: relative;
    /* `touch-action: pan-y` RETIRÉ le 27/09. Il devait réserver le vertical au
       navigateur et l'horizontal à l'anneau (voir l'ancien JS de glissement,
       supprimé le même jour). En usage réel, l'effet inverse se produisait :
       dès qu'un geste avait la moindre composante horizontale — courant sur un
       vrai doigt, même pour descendre la page — certains navigateurs
       refusaient tout défilement natif sur cette zone plutôt que de trancher
       pour le vertical, une décision prise avant même que le JavaScript ne
       voie le geste. Signalé comme « il faut scroller sur le côté ». Sans
       cette déclaration, la zone défile exactement comme le reste de la page,
       quel que soit l'angle du doigt. */
    height: clamp(440px, 55vh, 560px);
    margin: 3rem auto 1rem;
    max-width: 900px;
    perspective: 1600px;
    perspective-origin: center 45%;
    /* Rayon de l'anneau. Une seule déclaration, lue à la fois par le CSS des
       cartes ET par le script qui recule l'anneau : codé en dur aux deux endroits,
       il suffisait d'en corriger un pour désaligner la scène. Sur un écran étroit
       un rayon de 320px projetait la carte de devant hors du cadre — d'où les
       valeurs réduites plus bas. */
    --ring-r: 320px;
    --card-w: 260px;
}
.menu-3d-stage {
    position: absolute; inset: 0;
    transform-style: preserve-3d;
}
.menu-3d-ring {
    position: absolute; inset: 0;
    transform-style: preserve-3d;
    transform: translateZ(-320px) rotateY(0deg);
    transition: transform 0.9s cubic-bezier(0.16, 1, 0.3, 1);
    will-change: transform;
}
.menu-3d-card {
    position: absolute;
    top: 50%; left: 50%;
    width: var(--card-w, 260px); height: 340px;
    margin: -170px 0 0 calc(var(--card-w, 260px) / -2);
    transform-style: preserve-3d;
    /* DÉPLOIEMENT DE L'ANNEAU — `--deploy` va de 0 à 1 et est écrit sur le ring
       par le scroll ; les cartes en héritent. À 0 elles sont toutes confondues au
       centre, face au lecteur, comme un jeu de cartes serré ; à 1 elles occupent
       leurs positions sur le cercle. L'angle ET le rayon sont pilotés par la même
       variable, si bien que l'ouverture se lit comme un seul geste — l'éventail
       qui s'écarte — et non comme deux animations superposées.
       Une seule variable animée pour six cartes : rien à synchroniser. */
    transform: rotateY(calc(var(--angle) * var(--deploy, 1)))
               translateZ(calc(var(--ring-r, 320px) * var(--deploy, 1)));
    transition: filter 0.6s var(--easing);
}
.card-face {
    position: relative;
    width: 100%; height: 100%;
    background: white;
    border-radius: var(--radius-lg);
    box-shadow: 0 30px 60px -20px rgba(74, 43, 35, 0.25), 0 15px 30px -10px rgba(217, 97, 63, 0.15);
    padding: 2rem 1.5rem;
    display: flex; flex-direction: column;
    align-items: center; justify-content: center;
    text-align: center;
    border: 2px solid transparent;
    cursor: pointer;
    transition: all 0.4s var(--easing);
    backface-visibility: hidden;
}
.menu-3d-card.is-front .card-face {
    border-color: var(--phil-coral);
    transform: translateZ(30px) scale(1.05);
    box-shadow: 0 45px 80px -20px rgba(217, 97, 63, 0.4), 0 20px 40px -10px rgba(232, 162, 63, 0.2);
}
/* RÈGLE STRUCTURANTE — aucun `filter` ni `opacity` sur .menu-3d-card.
   Les deux forcent `transform-style: flat` sur l'élément : la chaîne
   preserve-3d se rompt, le `backface-visibility: hidden` de .card-face ne
   s'applique plus, et les cartes de l'arrière de l'anneau s'affichaient
   texte EN MIROIR. La mise en retrait se fait donc sur la face, qui est une
   feuille de l'arbre 3D et peut être aplatie sans dommage. */
.menu-3d-card:not(.is-front) .card-face {
    /* Le retrait suit le déploiement. Anneau replié, les cartes se recouvrent
       presque entièrement : à 0,62 leurs libellés se superposaient et devenaient
       illisibles si l'on s'arrêtait de défiler à mi-course. En les enfonçant à
       0,25 tant que l'éventail est fermé, le recouvrement se lit comme de l'ombre,
       et elles remontent à 0,62 une fois chacune à sa place. Même variable que la
       géométrie : impossible que les deux se désynchronisent. */
    opacity: calc(0.25 + 0.37 * var(--deploy, 1));
    box-shadow: 0 18px 40px -26px rgba(74, 43, 35, 0.4);
}
.menu-3d-card.is-back { pointer-events: none; }
.menu-3d-card.is-back .card-face { opacity: 0; }
.menu-3d-card .card-face:hover { transform: translateZ(40px) scale(1.02); }
.menu-3d-card.is-front .card-face:hover { transform: translateZ(50px) scale(1.08); }

.vignette-icon { font-size: 3rem; display: block; margin-bottom: 0.5rem; line-height: 1; }
.menu-3d-card h3 { font-size: 1.5rem; margin-bottom: 0.25rem; }
.vignette-sub { font-size: 0.85rem; opacity: 0.6; margin-bottom: 0.75rem; }
.vignette-price {
    font-family: 'Fredoka', sans-serif;
    font-weight: 600; color: var(--phil-coral-texte); font-size: 1.2rem;
}
.card-hint {
    margin-top: 1rem;
    font-size: 0.7rem; text-transform: uppercase; letter-spacing: 2px;
    color: var(--phil-coral-texte); opacity: 0;
    transition: opacity 0.3s;
}
.menu-3d-card.is-front .card-hint { opacity: 0.6; }

/* Navigation buttons */
.menu-nav-btn {
    position: absolute;
    top: 50%; transform: translateY(-50%);
    width: 48px; height: 48px;
    border-radius: 50%;
    background: white;
    box-shadow: var(--shadow-soft);
    display: flex; align-items: center; justify-content: center;
    font-size: 1.4rem; color: var(--phil-coral);
    z-index: 10;
    transition: all 0.25s var(--easing);
    cursor: pointer;
}
.menu-nav-btn:hover { background: var(--phil-coral); color: white; transform: translateY(-50%) scale(1.1); }
.menu-nav-btn.prev { left: 1rem; }
.menu-nav-btn.next { right: 1rem; }

.menu-dots {
    position: absolute;
    bottom: -1.2rem; left: 50%;
    transform: translateX(-50%);
    display: flex; gap: 0;            /* l'écart vient du rembourrage des boutons */
    z-index: 10;
}
/* ZONE TACTILE. Le point mesurait 9px de côté : c'est ce que le doigt devait
   viser, alors que le minimum recommandé est 24px et qu'Apple préconise 44px.
   Sur les treize formats testés, c'était le seul défaut qui revenait partout.

   Le bouton fait donc 34x34 et reste transparent ; c'est un pseudo-élément qui
   dessine le point. La cible grandit sans que le repère visuel change de taille —
   neuf gros points auraient alourdi la scène. */
.menu-dot {
    width: 34px; height: 34px;
    padding: 0; border: 0; background: none;
    display: flex; align-items: center; justify-content: center;
    cursor: pointer;
}
.menu-dot::after {
    content: '';
    width: 9px; height: 9px; border-radius: 50%;
    background: rgba(74, 43, 35, 0.15);
    transition: width 0.3s var(--easing), background 0.3s var(--easing),
                border-radius 0.3s var(--easing);
}
.menu-dot.active::after { background: var(--phil-coral); width: 24px; border-radius: 6px; }
/* Le repère de focus doit rester visible pour la navigation au clavier. */
.menu-dot:focus-visible { outline: 2px solid var(--phil-coral); outline-offset: -4px; border-radius: 50%; }

.hint-tap {
    text-align: center; margin-top: 2rem;
    font-size: 0.85rem; opacity: 0.5;
}

/* Panel détail overlay */
.menu-detail-panel {
    position: fixed; inset: 0;
    z-index: 500;
    display: flex; align-items: center; justify-content: center;
    padding: 1.5rem;
    /* C'EST LE PANNEAU QUI RETIENT LA PAGE, plus un verrou posé sur html/body.
       Passer la racine en `overflow: hidden` à l'ouverture puis la rendre à la
       fermeture est un déclencheur connu sur Safari iOS : la page peut rester
       figée après coup. Ici, un doigt posé sur le panneau ne peut simplement
       pas faire défiler ce qu'il y a derrière ; rien n'est modifié sur la
       page, donc rien n'est à rétablir à la fermeture. La zone de lecture
       (`.menu-detail-scroll`) redonne le défilement vertical pour elle seule. */
    touch-action: none;
}
.menu-detail-panel[hidden] { display: none; }
.menu-detail-scrim {
    position: absolute; inset: 0;
    background: rgba(74, 43, 35, 0.55);
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
    animation: scrim-in 0.35s var(--easing);
}
@keyframes scrim-in { from { opacity: 0; } to { opacity: 1; } }
.menu-detail-box {
    position: relative;
    background: white;
    border-radius: var(--radius-xl);
    max-width: 640px; width: 100%;
    max-height: 82vh;
    /* La BOÎTE ne défile pas : elle cadre. C'est `.menu-detail-scroll` à
       l'intérieur qui défile, ce qui laisse le bouton de fermeture ancré au coin
       quoi qu'il arrive. `overflow: hidden` conserve les coins arrondis sur le
       contenu qui passe dessous. */
    display: flex; flex-direction: column;
    overflow: hidden;
    box-shadow: 0 40px 80px -20px rgba(0,0,0,0.4);
    /* Plus d'`animation` CSS ici. Le panneau ne « surgit » plus au centre : il
       naît de la vignette qu'on vient de toucher et grandit jusqu'à sa place
       (technique FLIP, voir openMenuDetail). Une keyframe CSS écrirait `transform`
       en même temps que GSAP et casserait cette continuité.
       C'est le geste qui porte le sens : l'utilisateur voit CE QU'IL A TOUCHÉ
       devenir le panneau, au lieu d'un dialogue anonyme apparaissant par-dessus. */
    will-change: transform;
}
/* Voile du haut, symétrique de celui du bas. Marge basse négative pour ne rien
   ajouter au flux — même précaution que pour l'autre, sinon il rallongerait la
   zone défilable et déclencherait un débordement fantôme. */
.menu-detail-fade-haut {
    position: sticky;
    top: 0;
    height: 2rem;
    margin: -2rem -2rem -2rem;
    background: linear-gradient(to top, rgba(255,255,255,0) 0%, rgba(255,255,255,0.80) 100%);
    pointer-events: none;
    opacity: 0;
    transition: opacity 0.3s var(--easing);
    z-index: 1;
}
/* Il n'a de sens qu'une fois qu'on a quitté le début. */
.menu-detail-scroll.est-defile .menu-detail-fade-haut { opacity: 1; }

/* Voile de bas de boîte. `sticky` plutôt que `fixed` ou `absolute` : il reste
   collé au bas de la ZONE VISIBLE du panneau pendant qu'on fait défiler, sans
   qu'on ait à recalculer sa position — un élément positionné par rapport à la
   boîte suivrait le contenu et disparaîtrait au premier défilement. */
.menu-detail-fade {
    position: sticky;
    /* `bottom: 0`, surtout pas une valeur négative. Avec `bottom: -2.5rem` le
       voile pouvait descendre sous le bas de la zone visible, ce qui ALLONGEAIT
       la zone défilable de 40 px : les menus courts devenaient scrollables pour
       rien, et le voile s'affichait en annonçant un contenu qui n'existait pas.
       La marge haute négative annule sa hauteur dans le flux, si bien qu'il ne
       contribue plus du tout au débordement — mesuré à 0 sur les menus courts. */
    bottom: 0;
    left: 0; right: 0;
    height: 2.25rem;
    margin: -2.25rem -2rem 0;        /* déborde sur le padding pour couvrir toute la largeur */
    /* N'atteint JAMAIS le blanc plein. À 3,5rem et opacité 1, le voile effaçait
       la dernière ligne visible : on lisait « Tartare bœuf, magret ou » à moitié
       gommé. Un indicateur de défilement doit suggérer la suite, pas supprimer du
       contenu. Court et jamais opaque, il adoucit la coupe au coin arrondi et
       s'arrête là. */
    background: linear-gradient(to bottom, rgba(255,255,255,0) 0%, rgba(255,255,255,0.80) 100%);
    pointer-events: none;
    opacity: 1;
    transition: opacity 0.3s var(--easing);
}
/* Arrivé en bas, ou rien à défiler : le voile s'efface. */
.menu-detail-scroll.est-en-bas .menu-detail-fade,
.menu-detail-scroll.sans-debordement .menu-detail-fade { opacity: 0; }

.menu-detail-scroll {
    flex: 1 1 auto;
    min-height: 0;                   /* sans ça un enfant flex refuse de rétrécir */
    overflow-y: auto;
    /* Empêche le défilement de se propager à la page quand on atteint le haut ou
       le bas. Sans ça, continuer à faire défiler emmène la page derrière le
       panneau, et on perd la carte qu'on était en train de lire. */
    overscroll-behavior: contain;
    -webkit-overflow-scrolling: touch;
    touch-action: pan-y;
    scrollbar-width: thin;
    /* Le padding BAS est porté par le contenu, pas par le conteneur défilant.
       Raison : les décalages d'un élément `sticky` se mesurent depuis la boîte de
       CONTENU du scrollport. Avec `padding-bottom` ici, `bottom: 0` plaçait le
       voile 40px au-dessus du bord visible — il estompait l'avant-dernière ligne
       en laissant la dernière nette, soit l'inverse de ce qu'un indicateur de
       défilement doit montrer. Déplacé sur le contenu, le bord bas du scrollport
       coïncide avec le bord visible et le voile se pose au bon endroit. */
    padding: 2.5rem 2rem 0;
}
.menu-detail-content { padding-bottom: 2.5rem; }

.menu-detail-close {
    position: absolute; top: 1rem; right: 1rem;
    z-index: 2;                      /* au-dessus du contenu qui défile dessous */
    width: 40px; height: 40px; border-radius: 50%;
    background: var(--phil-cream);
    display: flex; align-items: center; justify-content: center;
    font-size: 1.5rem; color: var(--phil-blue);
    transition: 0.2s;
}
.menu-detail-close:hover { background: var(--phil-coral); color: white; }
.detail-header { text-align: center; margin-bottom: 1.5rem; }
.detail-header .icon-big { font-size: 3rem; display: block; margin-bottom: 0.5rem; }
.detail-header h3 { font-size: 2rem; margin-bottom: 0.25rem; }
.detail-header .sub { font-size: 0.95rem; opacity: 0.6; margin-bottom: 0.5rem; }
/* Note de catégorie (ex. Sucré) : sous le sous-titre, au-dessus du prix. Largeur
   bornée pour qu'une phrase longue se lise en lignes courtes et centrées plutôt
   qu'en une barre sur toute la largeur du panneau. */
.detail-header .note {
    max-width: 34rem; margin: 0.35rem auto 0.9rem;
    font-size: 0.92rem; line-height: 1.5; font-style: italic;
    color: var(--phil-blue); opacity: 0.85;
}
.detail-header .price { font-family: 'Fredoka', sans-serif; font-weight: 600; color: var(--phil-coral-texte); font-size: 1.3rem; }
.detail-group { margin-top: 1.5rem; }
.detail-group h4 {
    font-size: 0.85rem; text-transform: uppercase; letter-spacing: 2px;
    color: var(--phil-coral-texte); margin-bottom: 0.75rem;
}
.detail-group ul { list-style: none; }
.detail-group li {
    display: flex; justify-content: space-between;
    padding: 0.6rem 0; border-bottom: 1px dashed rgba(74, 43, 35, 0.1);
    font-size: 0.95rem; gap: 1rem;
}
.detail-group li { align-items: baseline; }
.item-nom { display: flex; flex-direction: column; gap: 0.2rem; }
.item-desc {
    font-size: 0.8rem; line-height: 1.45;
    color: rgba(74, 43, 35, 0.55);
    font-weight: 400;
}
.detail-group li .item-prix {
    font-weight: 600; color: var(--phil-coral-texte); white-space: nowrap;
}
.detail-disclaimer {
    margin-top: 1.5rem; padding: 0.75rem 1rem;
    background: rgba(217, 97, 63, 0.08);
    border-radius: var(--radius-md);
    font-size: 0.85rem; color: var(--phil-coral-texte);
    font-style: italic; text-align: center;
}

/* ================================================================
   TRANSITIONS ENTRE SECTIONS (overlay coral qui flash)
================================================================ */
.section-transition-overlay {
    position: fixed; top: 0; left: 0;
    width: 100%; height: 100%;
    background: linear-gradient(135deg, var(--phil-coral), var(--phil-gold));
    z-index: 90;
    pointer-events: none;
    transform: translateY(-100%);
    will-change: transform;
}

/* Hover 3D subtil sur cards (via JS mouse-tilt) */
.info-card { transform-style: preserve-3d; will-change: transform; transition: transform 0.4s var(--easing); }

/* Survol : ombre et luminosité UNIQUEMENT. Aucun `transform` — la grammaire
   d'apparition en écrit un sur ces mêmes cartes, et les deux se battraient. */
.info-card { transition: box-shadow 0.4s var(--easing), filter 0.4s var(--easing); }
.info-card:hover {
    box-shadow: 0 32px 60px -28px rgba(217, 97, 63, 0.45);
    filter: brightness(1.02);
}
@media (prefers-reduced-motion: reduce) { .info-card:hover { filter: none; } }

.review-card { transform-style: preserve-3d; will-change: transform; transition: transform 0.4s var(--easing); }

/* ================================================================
   §5 AVIS
================================================================ */
#avis { background: var(--phil-white); overflow: hidden; }
.review-badge {
    display: inline-flex; align-items: center; gap: 0.75rem;
    margin: 1rem auto 2.5rem;
    padding: 1rem 2rem;
    background: var(--phil-cream); border-radius: 40px;
}
.big-note {
    font-family: 'Fredoka', sans-serif; font-weight: 600;
    font-size: 2rem; color: var(--phil-coral-texte);
}
/* Note en étoiles avec demi-étoile exacte. La couche dorée est superposée à la
   couche grise et rognée à `--part` de sa largeur, ce qui permet d'afficher
   n'importe quelle note au dixième près sans caractère spécial ni image. */
.review-badge .stars { position: relative; display: inline-block; letter-spacing: 2px; }
.review-badge .stars-vides   { color: rgba(74, 43, 35, 0.20); }
.review-badge .stars-pleines {
    position: absolute; inset: 0;
    color: var(--phil-gold);
    width: var(--part, 100%);
    overflow: hidden;
    white-space: nowrap;
}
.review-count { opacity: 0.6; font-size: 0.9rem; }

.reviews-marquee-wrapper {
    position: relative; overflow: hidden;
    padding: 1rem 0; margin: 2rem 0;
}
.reviews-marquee-wrapper::before,
.reviews-marquee-wrapper::after {
    content: ''; position: absolute; top: 0; bottom: 0;
    width: 100px; z-index: 2; pointer-events: none;
}
.reviews-marquee-wrapper::before { left: 0; background: linear-gradient(90deg, var(--phil-white), transparent); }
.reviews-marquee-wrapper::after { right: 0; background: linear-gradient(-90deg, var(--phil-white), transparent); }
.reviews-marquee {
    display: flex; gap: 1.5rem;
    animation: scroll-reviews 60s linear infinite;
    width: max-content;
}
.reviews-marquee:hover,
.reviews-marquee-wrapper.en-pause .reviews-marquee { animation-play-state: paused; }
@keyframes scroll-reviews { from { transform: translateX(0); } to { transform: translateX(-50%); } }

.review-card {
    flex-shrink: 0; width: 320px;
    background: var(--phil-cream); border-radius: var(--radius-lg);
    padding: 1.5rem; text-align: left;
    box-shadow: var(--shadow-soft);
}
.review-head {
    display: flex; justify-content: space-between;
    margin-bottom: 0.5rem;
}
.review-head .author { font-family: 'Fredoka', sans-serif; font-weight: 500; }
.review-head .stars-sm { color: var(--phil-gold); font-size: 0.85rem; letter-spacing: 1px; }
.review-card p { font-size: 0.92rem; opacity: 0.8; font-style: italic; line-height: 1.5; }

.btn-google {
    display: inline-flex; align-items: center; gap: 0.6rem;
    margin-top: 2rem; padding: 1rem 2rem;
    background: white; border: 2px solid var(--phil-coral);
    border-radius: 40px; color: var(--phil-coral);
    font-family: 'Fredoka', sans-serif; font-weight: 500;
    transition: all 0.25s var(--easing);
    box-shadow: var(--shadow-soft);
}
.btn-google:hover { background: var(--phil-coral); color: white; transform: translateY(-3px); }
.btn-google:hover svg path { fill: white; }

/* ================================================================
   §6 INFOS
================================================================ */
#infos { background: var(--phil-cream); }
.info-grid {
    display: grid; grid-template-columns: repeat(3, 1fr);
    gap: 1.5rem; margin-top: 3rem;
}
.info-card {
    background: white; padding: 2rem 1.5rem;
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-soft); text-align: center;
    transition: transform 0.3s var(--easing);
    display: flex; flex-direction: column; align-items: center;
}
.info-card:hover { transform: translateY(-4px); }
.info-icon {
    width: 52px; height: 52px;
    background: linear-gradient(135deg, var(--phil-gold), var(--phil-coral));
    border-radius: 50%;
    display: flex; align-items: center; justify-content: center;
    color: white; font-size: 1.3rem;
    margin-bottom: 1rem;
    box-shadow: 0 6px 15px -5px rgba(217, 97, 63, 0.4);
}
.info-card h3 { margin-bottom: 0.75rem; font-size: 1.15rem; }
.info-card p { font-size: 0.95rem; opacity: 0.85; }
/* ZONES TACTILES DE §6. Ce sont les gestes les plus utiles du site — appeler,
   trouver le chemin — et c'étaient les plus petits : 25px de haut pour le
   numéro, 19px pour l'itinéraire, là où 32 est le minimum recommandé. Le
   rembourrage les agrandit sans changer leur poids visuel. */
.info-tel {
    display: inline-flex; align-items: center; justify-content: center;
    margin-top: 0.5rem;
    padding: 0.5rem 1rem; min-height: 44px;
    border-radius: 40px;
    background: rgba(217, 97, 63, 0.09);
    font-weight: 700; font-size: 1.15rem;
    color: var(--phil-coral-texte);
    transition: background 0.25s var(--easing);
}
.info-tel:hover { background: rgba(217, 97, 63, 0.18); }
.info-link {
    display: inline-flex; align-items: center;
    margin-top: 0.35rem;
    padding: 0.55rem 0.75rem; min-height: 40px;
    font-size: 0.85rem; opacity: 0.6;
}
.info-link span { border-bottom: 1px dotted currentColor; }
.info-link:hover { color: var(--phil-coral); opacity: 1; }

.hours-block { margin-top: 0.5rem; text-align: center; }
.hours-row-head {
    font-family: 'Fredoka', sans-serif;
    color: var(--phil-coral-texte); font-weight: 600;
    font-size: 0.85rem; text-transform: uppercase; letter-spacing: 1.5px;
    margin-bottom: 0.15rem;
}
.hours-row { font-size: 0.95rem; }
.hours-row-sub { font-size: 0.8rem; opacity: 0.6; margin-top: 0.15rem; }
.disclaimer-box {
    margin-top: 1rem; padding: 0.6rem 1rem;
    background: rgba(217, 97, 63, 0.08);
    border-radius: var(--radius-md);
    font-size: 0.8rem; color: var(--phil-coral-texte);
    font-family: 'Fredoka', sans-serif; font-weight: 500;
    letter-spacing: 0.5px;
}

.social-links { display: flex; justify-content: center; gap: 1rem; margin-top: 0.5rem; }
.social-links a {
    width: 42px; height: 42px;
    display: flex; align-items: center; justify-content: center;
    background: var(--phil-cream); border-radius: 50%;
    color: var(--phil-blue); transition: all 0.25s var(--easing);
}
.social-links a:hover { background: var(--phil-coral); color: white; transform: translateY(-3px); }
.social-handle { margin-top: 0.75rem; font-size: 0.85rem; opacity: 0.6; }

/* ================================================================
   §7 FOOTER
================================================================ */
footer { background: var(--phil-blue); color: var(--phil-cream); padding: 4rem 1.5rem 2rem; min-height: auto; }
footer { display: block; }
.footer-inner {
    max-width: 800px; margin: 0 auto;
    text-align: center;
}
.footer-logo { font-family: 'Fredoka', sans-serif; font-size: 1.4rem; font-weight: 600; margin-bottom: 0.5rem; }
.footer-tag { opacity: 0.65; font-size: 0.9rem; margin-bottom: 1.5rem; }
.footer-links {
    display: flex; justify-content: center; align-items: center;
    gap: 0.25rem; margin-bottom: 1.5rem;
    flex-wrap: wrap;
    font-size: 0.9rem;
}
/* Le rembourrage remplace l'écart : les liens s'éloignent autant qu'avant à
   l'œil, mais leur zone touchable atteint 40px de haut au lieu de 22. */
.footer-links a {
    display: inline-flex; align-items: center;
    padding: 0.55rem 0.6rem; min-height: 40px;
    opacity: 0.8; transition: 0.2s;
}
.footer-links a:hover { color: var(--phil-coral); opacity: 1; }
.footer-links .dot { opacity: 0.4; }
.footer-copy { opacity: 0.45; font-size: 0.8rem; }

/* ================================================================
   ÉCHELLE Z-INDEX — une seule source de vérité
   ----------------------------------------------------------------
     5  panneaux de section & footer
    12  gaufrette 3D — elle circule DEVANT les panneaux depuis qu'elle traverse
        toute la page ; c'est ce qui impose au hero de ne pas créer de contexte
        d'empilement, sans quoi le bouton « Bienvenue » passerait dessous
    25  bouton « Bienvenue » du hero (au-dessus de la gaufrette)
    30  nav
    40  barre de progression
   500  panneau de détail de la carte
   600  fenêtre de choix de la langue (elle doit couvrir le panneau)

   Cette échelle était FAUSSE : elle annonçait 1 pour la gaufrette et 100 pour le
   panneau de détail, valeurs d'une version antérieure. Un commentaire d'ordre
   d'empilement qui ment est pire que pas de commentaire — on s'y fie pour placer
   un nouvel élément, et il passe derrière ce qu'il devait couvrir.
================================================================ */
section, footer { position: relative; z-index: 5; }
nav { z-index: 30 !important; }
.scroll-progress { z-index: 40 !important; }

/* ================================================================
   SECTIONS EN PANNEAUX
   ----------------------------------------------------------------
   La gaufrette ne disparaît plus jamais : elle circule en continu
   derrière la page. Pour qu'on la voie passer, il faut que les
   panneaux ne recouvrent pas tout — d'où les gouttières latérales
   et les respirations verticales, par lesquelles elle réapparaît.
   Le fond crème du body est le « décor » dans lequel elle voyage.
================================================================ */
section:not(#hero) {
    width: calc(100% - 12rem);
    max-width: 1200px;
    margin: 0 auto 4rem;
    border-radius: 42px;
    box-shadow: 0 30px 70px -40px rgba(74, 43, 35, 0.28);
}
footer {
    width: calc(100% - 12rem);
    max-width: 1200px;
    margin: 0 auto;
    border-radius: 42px 42px 0 0;
}
/* Le hero reste plein cadre et transparent : la gaufrette s'y montre entière */
#hero { background: transparent; }
.hero-inner { position: relative; z-index: 2; }

@media (max-width: 900px) {
    section:not(#hero), footer {
        width: calc(100% - 1.5rem);
        border-radius: 28px;
        /* Écart ramené à une valeur normale. Il avait été porté à 210px pour donner
           de la place au rail vertical des écrans étroits ; ce rail n'existe plus,
           et ces respirations démesurées ne faisaient qu'allonger la page. */
        margin-bottom: 3rem;
    }
    footer { margin-bottom: 0; }
}

/* ================================================================
   MOBILE
================================================================ */
@media (max-width: 900px) {
    section { padding: 4rem 1rem; }
    #hero { padding: 6rem 1rem 3rem; }

    .nav-links { display: none; }
    .nav-links.open {
        display: flex; flex-direction: column;
        position: absolute; top: 100%; right: 1rem;
        background: white; padding: 1rem;
        border-radius: var(--radius-md); box-shadow: var(--shadow-lift);
        min-width: 180px;
    }
    .menu-btn { display: block; }


    .menu-grid { grid-template-columns: 1fr; gap: 1rem; }
    .menu-vignette.expanded { grid-column: span 1; }

    .info-grid { grid-template-columns: 1fr; }

    .review-card { width: 280px; }
    /* Le logo est un peu réduit sur téléphone, la barre y étant plus étroite. */
    .nav-logo img { height: 38px; }
}

@media (max-width: 900px) {
    /* Anneau resserré : à 320px de rayon la carte de devant sortait de l'écran
       sur un téléphone. On réduit rayon ET largeur de carte ensemble, sinon les
       cartes voisines se recouvrent au lieu de s'écarter. */
    .menu-3d-scene { --ring-r: 220px; --card-w: 210px; perspective: 1100px; }
}
@media (max-width: 480px) {
    .hero-title { font-size: 2.3rem; }
    .hero-stage { width: 88vw; height: 88vw; }
    .menu-3d-scene { --ring-r: 178px; --card-w: 178px; perspective: 900px; }
}

/* ================================================================
   CHOIX DE LA LANGUE
================================================================ */
.nav-langue {
    display: flex; align-items: center; gap: 0.4rem;
    padding: 0.45rem 0.8rem;
    border: 1px solid rgba(74, 43, 35, 0.14);
    border-radius: 40px;
    background: rgba(255, 255, 255, 0.6);
    font-family: 'Fredoka', sans-serif; font-size: 0.8rem; font-weight: 500;
    color: var(--phil-blue);
    cursor: pointer;
    transition: all 0.25s var(--easing);
    /* 40px de haut : au-dessus du minimum tactile, comme les points du carrousel. */
    min-height: 40px;
}
.nav-langue:hover { border-color: var(--phil-coral); color: var(--phil-coral); }
.nav-langue-drapeau { font-size: 1rem; line-height: 1; }

.langue-panneau {
    position: fixed; inset: 0; z-index: 600;
    display: flex; align-items: center; justify-content: center;
    padding: 1.5rem;
}
.langue-panneau[hidden] { display: none; }
.langue-voile {
    position: absolute; inset: 0;
    background: rgba(74, 43, 35, 0.55);
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
    animation: scrim-in 0.35s var(--easing);
}
.langue-boite {
    position: relative;
    background: white;
    border-radius: var(--radius-xl);
    padding: 2.5rem 2rem;
    max-width: 460px; width: 100%;
    box-shadow: 0 40px 80px -20px rgba(0, 0, 0, 0.4);
    text-align: center;
    animation: langue-entree 0.45s var(--easing);
}
@keyframes langue-entree {
    from { opacity: 0; transform: translateY(18px) scale(0.96); }
    to   { opacity: 1; transform: none; }
}
.langue-titre { font-size: 1.5rem; margin-bottom: 0.5rem; }
.langue-sous { font-size: 0.9rem; opacity: 0.6; margin-bottom: 1.75rem; }

.langue-liste { display: grid; grid-template-columns: 1fr 1fr; gap: 0.75rem; }
.langue-choix {
    display: flex; align-items: center; gap: 0.7rem;
    padding: 0.9rem 1rem;
    border: 2px solid rgba(74, 43, 35, 0.1);
    border-radius: var(--radius-md);
    background: var(--phil-cream);
    font-family: 'Fredoka', sans-serif; font-size: 0.95rem; font-weight: 500;
    color: var(--phil-blue);
    cursor: pointer;
    transition: all 0.2s var(--easing);
    min-height: 52px;
}
.langue-choix:hover { border-color: var(--phil-coral); transform: translateY(-2px); }
.langue-choix.suggeree { border-color: var(--phil-coral); background: rgba(217, 97, 63, 0.08); }
.langue-choix .drapeau { font-size: 1.35rem; line-height: 1; }
.langue-choix:focus-visible { outline: 2px solid var(--phil-coral); outline-offset: 2px; }

.langue-passer {
    margin-top: 1.5rem;
    padding: 0.6rem 1rem;
    background: none; border: 0;
    font-family: 'Fredoka', sans-serif; font-size: 0.85rem;
    color: var(--phil-blue); opacity: 0.55;
    cursor: pointer; text-decoration: underline;
    transition: opacity 0.2s var(--easing);
    min-height: 40px;
}
.langue-passer:hover { opacity: 0.9; }

/* Note sur les allergènes, affichée dans la carte hors français. Elle n'existe
   pas en français : les noms de plats y sont déjà dans la langue du lecteur. */
.carte-note-langue {
    margin-top: 1.25rem; padding: 0.7rem 1rem;
    background: rgba(217, 97, 63, 0.08);
    border-radius: var(--radius-md);
    font-size: 0.8rem; color: var(--phil-coral-texte);
    text-align: center; line-height: 1.45;
}

@media (max-width: 480px) {
    .langue-liste { grid-template-columns: 1fr; }
    .nav-langue-code { display: none; }
    .nav-langue { padding: 0.45rem 0.6rem; }
}
@media (prefers-reduced-motion: reduce) {
    .langue-boite { animation: none; }
    .langue-choix:hover { transform: none; }
}

/* ============================================================================
   ALLÈGEMENTS POUR LES ÉCRANS TACTILES
   ============================================================================
   Trois effets qui ne coûtent rien sur un Mac et beaucoup sur un téléphone.
   Le trafic vient d'Instagram, donc du téléphone : c'est là qu'il faut choisir.

   1. L'OMBRE PORTÉE DE LA GAUFRETTE — PLUS COUPÉE D'OFFICE depuis le 03/10,
      voir `.allegee` juste en dessous. Raison d'origine : `drop-shadow` sur un canvas WebGL oblige
      le compositeur à refabriquer une copie floutée du canvas À CHAQUE IMAGE,
      puisque le contenu change à chaque image. C'est la dépense la plus lourde
      de la page pendant un défilement. La gaufrette garde sa silhouette et son
      relief, qui viennent de l'éclairage 3D, pas de cette ombre.

   2. LES FLOUS D'ARRIÈRE-PLAN. `backdrop-filter` sur la barre de navigation est
      recalculé pendant tout le défilement, puisque ce qui passe dessous change
      en permanence. On garde le même fond, simplement opaque : à l'œil la
      différence est mince, au toucher elle ne l'est pas.

   Ciblage par `pointer: coarse` — le doigt — plutôt que par la largeur : une
   tablette ou un téléphone en paysage a besoin du même allègement.
   ========================================================================== */
/* L'ombre portée de la gaufrette n'est plus coupée d'office sur téléphone
   (03/10) : elle ne l'est que si le garde-fou de fluidité (script.js) mesure
   que l'appareil n'arrive plus à suivre. */
.gaufrette-3d-layer.allegee .gaufrette-canvas { filter: none; }

@media (pointer: coarse), (max-width: 900px) {

    #navbar {
        background: rgba(251, 248, 241, 0.97);
        backdrop-filter: none;
        -webkit-backdrop-filter: none;
    }
    .menu-detail-scrim, .langue-voile {
        backdrop-filter: none;
        -webkit-backdrop-filter: none;
    }
}

