/* NEKTAR — Hero v2 : nav drawer + OpenTable */ const { useState, useEffect, useRef, useCallback } = React; const TWEAK_DEFAULTS = { "layout": "centered", "overlay": "marked", "brand": "horizontal", "lang": "fr" }; const OVERLAYS = { subtle: "linear-gradient(180deg, rgba(13,27,62,0.20) 0%, rgba(13,27,62,0.05) 35%, rgba(13,27,62,0.45) 100%)", marked: "linear-gradient(180deg, rgba(13,27,62,0.45) 0%, rgba(13,27,62,0.25) 35%, rgba(13,27,62,0.70) 100%)", bottom: "linear-gradient(180deg, transparent 0%, transparent 50%, rgba(13,27,62,0.80) 100%)", }; // Photo Nektar — LG1_9471 (dossier "Photos Nektar JB", public) const HERO_IMG = "https://drive.google.com/thumbnail?id=14d1wDed1NNt-wLhXeyXfo-qxqr8xXlM2&sz=w2400"; /* 1 clic — déclenche le bouton OT dans le DOM (iframe=false) */ function openResa() { const btn = document.querySelector( '#ot-reservation-widget button, #ot-reservation-widget a, [id*="ot-widget-container"] button, [id*="ot-widget-container"] a' ); if (btn) btn.click(); } /* ------------------------------------------------------- Hooks ------------------------------------------------------- */ function useScrolled(threshold = 12) { const [scrolled, set] = useState(false); useEffect(() => { const fn = () => set(window.scrollY > threshold); fn(); window.addEventListener("scroll", fn, { passive: true }); return () => window.removeEventListener("scroll", fn); }, [threshold]); return scrolled; } function useLockScroll(active) { useEffect(() => { if (active) document.body.classList.add("modal-open"); else document.body.classList.remove("modal-open"); return () => document.body.classList.remove("modal-open"); }, [active]); } function useEscKey(handler, active) { useEffect(() => { if (!active) return; const fn = (e) => { if (e.key === "Escape") handler(); }; document.addEventListener("keydown", fn); return () => document.removeEventListener("keydown", fn); }, [handler, active]); } /* ------------------------------------------------------- Floating Réserver — apparaît quand le CTA hero quitte le viewport ------------------------------------------------------- */ function FloatingResa({ copy }) { const [visible, setVisible] = useState(false); useEffect(() => { const cta = document.querySelector('.hero__cta'); if (!cta) return; const obs = new IntersectionObserver( ([entry]) => setVisible(!entry.isIntersecting), { threshold: 0 } ); obs.observe(cta); return () => obs.disconnect(); }, []); return ( ); } /* ------------------------------------------------------- Nav Drawer ------------------------------------------------------- */ function NavDrawer({ isOpen, onClose, copy, lang, setLang }) { useLockScroll(isOpen); useEscKey(onClose, isOpen); return (
); } /* ------------------------------------------------------- 2. RESERVATION MODAL ------------------------------------------------------- */ /* ------------------------------------------------------- Nav ------------------------------------------------------- */ function Nav({ t, copy, lang, setLang, scrolled, onOpenDrawer }) { return ( ); } /* ------------------------------------------------------- Hero ------------------------------------------------------- */ function HeroTitle({ copy }) { return (

{copy.hero.word}
{copy.hero.post}

); } function Hero({ t, copy }) { const imgRef = useRef(null); const [loaded, setLoaded] = useState(false); useEffect(() => { const img = imgRef.current; if (img && img.complete && img.naturalWidth > 0) setLoaded(true); }, []); return (
setLoaded(true)} loading="eager" decoding="async" />
{copy.hero.eyebrow}
{ e.preventDefault(); openResa(); }}> {copy.hero.cta}  →
{copy.hero.addrLine}
{copy.hero.hoursLine}
{t.lang === "fr" ? "Découvrir" : "Discover"}
); } function Teaser({ copy }) { return (
{copy.next.eyebrow}

{copy.next.teaser}

); } /* ------------------------------------------------------- App ------------------------------------------------------- */ function App() { const [t, setTweak] = useTweaks(TWEAK_DEFAULTS); const scrolled = useScrolled(); const copy = window.NEKTAR_COPY[t.lang] || window.NEKTAR_COPY.fr; const [navOpen, setNavOpen] = useState(false); const openNav = useCallback(() => setNavOpen(true), []); const closeNav = useCallback(() => setNavOpen(false), []); useEffect(() => { document.documentElement.lang = t.lang; }, [t.lang]); return ( {copy.a11y.skip}