function Menu({ menu, addToCart, openCart, cartCount, initCat, onInitCatDone }) {
  const [activeCat, setActiveCat] = React.useState(CATEGORIES[0].id);
  const [query, setQuery] = React.useState("");
  const sectionRefs = React.useRef({});
  const tabsRef    = React.useRef(null);
  const tabRefs    = React.useRef({});
  const isClicking = React.useRef(false);

  const filtered = React.useMemo(() => {
    const q = query.trim().toLowerCase();
    if (!q) return menu;
    return menu.filter(m => m.name.toLowerCase().includes(q) || m.desc.toLowerCase().includes(q));
  }, [menu, query]);

  const byCat = React.useMemo(() => {
    const groups = {};
    CATEGORIES.forEach(c => groups[c.id] = []);
    filtered.forEach(m => { if (groups[m.cat]) groups[m.cat].push(m); });
    return groups;
  }, [filtered]);

  // Scroll active tab into view in the tab bar
  const scrollTabIntoView = (id) => {
    const bar = tabsRef.current;
    const tab = tabRefs.current[id];
    if (!bar || !tab) return;
    const barLeft = bar.scrollLeft;
    const barRight = barLeft + bar.clientWidth;
    const tabLeft = tab.offsetLeft;
    const tabRight = tabLeft + tab.offsetWidth;
    if (tabLeft < barLeft + 8) bar.scrollTo({ left: tabLeft - 8, behavior: "smooth" });
    else if (tabRight > barRight - 8) bar.scrollTo({ left: tabRight - bar.clientWidth + 8, behavior: "smooth" });
  };

  // Scroll to initial category when coming from home page
  React.useEffect(() => {
    if (!initCat) return;
    const tryScroll = () => {
      const el = sectionRefs.current[initCat];
      if (el) {
        const top = el.getBoundingClientRect().top + window.scrollY - 140;
        window.scrollTo({ top, behavior: "smooth" });
        setActiveCat(initCat);
        onInitCatDone();
      } else {
        setTimeout(tryScroll, 80);
      }
    };
    setTimeout(tryScroll, 100);
  }, [initCat]);

  // IntersectionObserver — met à jour l'onglet actif pendant le scroll
  React.useEffect(() => {
    if (query) return; // en mode recherche, pas d'observer
    const observer = new IntersectionObserver((entries) => {
      if (isClicking.current) return;
      entries.forEach(entry => {
        if (entry.isIntersecting) {
          const id = entry.target.dataset.cat;
          if (id) { setActiveCat(id); scrollTabIntoView(id); }
        }
      });
    }, { rootMargin: "-30% 0px -60% 0px", threshold: 0 });

    Object.entries(sectionRefs.current).forEach(([, el]) => { if (el) observer.observe(el); });
    return () => observer.disconnect();
  }, [filtered, query]);

  const scrollTo = (id) => {
    isClicking.current = true;
    setActiveCat(id);
    scrollTabIntoView(id);
    const el = sectionRefs.current[id];
    if (el) {
      const top = el.getBoundingClientRect().top + window.scrollY - 120;
      window.scrollTo({ top, behavior: "smooth" });
    }
    setTimeout(() => { isClicking.current = false; }, 800);
  };

  return (
    <main>
      <section style={{ padding: "60px 0 30px" }}>
        <div className="container">
          <div className="label" style={{ color: "var(--accent)" }}>La carte</div>
          <h1>Notre menu</h1>
        </div>
      </section>

      {/* Sticky tabs + search */}
      <div style={{ position: "sticky", top: 80, zIndex: 30, background: "rgba(255,255,255,.95)", backdropFilter: "blur(10px)", borderBottom: "1px solid var(--line)", padding: "14px 0" }}>
        <div className="container menu-tabs-row" style={{ display: "flex", gap: 16, alignItems: "center", flexWrap: "wrap" }}>
          <div ref={tabsRef} className="menu-tabs-bar" style={{ display: "flex", gap: 6, overflowX: "auto", flex: 1, minWidth: 0, WebkitOverflowScrolling: "touch", scrollbarWidth: "none", msOverflowStyle: "none" }}>
            {CATEGORIES.map(c => (
              <button key={c.id} ref={el => tabRefs.current[c.id] = el} onClick={() => scrollTo(c.id)} style={{
                padding: "8px 14px", borderRadius: 999, fontSize: 13, fontWeight: 500,
                whiteSpace: "nowrap", flex: "none",
                background: activeCat === c.id ? "var(--ink)" : "var(--cream)",
                color: activeCat === c.id ? "#fff" : "var(--ink-2)",
                transition: "background .15s, color .15s",
              }}>
                {c.label}
                <span className="num" style={{ marginLeft: 6, opacity: .55, fontSize: 11 }}>
                  {byCat[c.id]?.length || 0}
                </span>
              </button>
            ))}
          </div>
          <div className="menu-search" style={{ position: "relative", width: 240 }}>
            <input className="input" placeholder="Rechercher un plat…" value={query}
                   onChange={e => setQuery(e.target.value)}
                   style={{ paddingLeft: 36 }} />
            <span style={{ position: "absolute", left: 12, top: "50%", transform: "translateY(-50%)", color: "var(--muted)" }}>
              <Icon.Search />
            </span>
          </div>
        </div>
      </div>

      {/* Sections */}
      <section style={{ padding: "40px 0 80px" }}>
        <div className="container">
          {CATEGORIES.map(c => {
            const items = byCat[c.id] || [];
            if (!items.length) return null;
            return (
              <div key={c.id} ref={el => sectionRefs.current[c.id] = el} data-cat={c.id} style={{ marginBottom: 56 }}>
                <div className="row" style={{ marginBottom: 20, gap: 16 }}>
                  <h2>{c.label}</h2>
                  <div style={{ flex: 1, height: 1, background: "var(--line)" }} />
                  <span className="muted small num">{items.length} plat{items.length > 1 ? "s" : ""}</span>
                </div>
                <div className="menu-grid">
                  {items.map(item => (
                    <MenuRow key={item.id} item={item} onAdd={() => addToCart(item)} />
                  ))}
                </div>
              </div>
            );
          })}
          {filtered.length === 0 && (
            <div style={{ textAlign: "center", padding: "60px 20px", color: "var(--muted)" }}>
              <p>Aucun plat ne correspond à votre recherche.</p>
            </div>
          )}
        </div>
      </section>

      {/* Sticky bottom cart bar */}
      {cartCount > 0 && (
        <div style={{
          position: "fixed", bottom: 20, left: "50%", transform: "translateX(-50%)",
          background: "var(--ink)", color: "#fff", borderRadius: 999,
          padding: "10px 16px 10px 22px", display: "flex", alignItems: "center", gap: 14,
          boxShadow: "var(--shadow-lg)", zIndex: 40, cursor: "pointer"
        }} onClick={openCart}>
          <Icon.Bag /> <span className="num">{cartCount} article{cartCount > 1 ? "s" : ""}</span>
          <span className="btn btn-accent btn-sm" style={{ padding: "6px 12px" }}>
            Voir le panier <Icon.ArrowRight />
          </span>
        </div>
      )}
    </main>
  );
}

function MenuRow({ item, onAdd }) {
  const hasImage = !!item.image;
  return (
    <div style={{
      display: "flex", gap: 14, padding: 14,
      background: "#fff", border: "1px solid var(--line)", borderRadius: 14,
      transition: "border-color .15s, transform .12s",
    }}
      onMouseEnter={e => e.currentTarget.style.borderColor = "var(--ink)"}
      onMouseLeave={e => e.currentTarget.style.borderColor = "var(--line)"}>
      {hasImage && (
        <img src={item.image} alt={item.name} style={{ width: 84, height: 84, flex: "none", borderRadius: 10, objectFit: "cover" }} />
      )}
      <div style={{ flex: 1, minWidth: 0, display: "flex", flexDirection: "column", justifyContent: "space-between", gap: 6 }}>
        <div>
          <div className="between" style={{ alignItems: "flex-start", gap: 10 }}>
            <div style={{ fontWeight: 500, lineHeight: 1.25, fontFamily: "Instrument Serif, serif", fontSize: 18 }}>
              {item.name}
            </div>
            <div className="num nowrap" style={{ fontWeight: 600 }}>
              {item.price.toFixed(2).replace(".", ",")} €
            </div>
          </div>
          <div className="small muted" style={{
            marginTop: 4,
            overflow: "hidden", display: "-webkit-box",
            WebkitLineClamp: 2, WebkitBoxOrient: "vertical",
          }}>{item.desc}</div>
        </div>
        <div className="between" style={{ marginTop: 4 }}>
          <div className="row" style={{ gap: 6, flexWrap: "wrap" }}>
            {(item.tags || []).map(t => (
              <span key={t} className={
                t === "signature" ? "chip new" :
                t === "épicé" ? "chip warn" :
                (t === "végétarien" || t === "sans alcool" || t === "sans gluten") ? "chip ok" : "chip"
              } style={{ fontSize: 10, padding: "3px 8px" }}>
                {t === "végétarien" && <Icon.Leaf />}
                {t === "signature" && <Icon.Sparkle />}
                {t}
              </span>
            ))}
          </div>
          <button className="btn btn-primary btn-sm" onClick={onAdd} style={{ padding: "6px 12px" }}>
            <Icon.Plus /> Ajouter
          </button>
        </div>
      </div>
    </div>
  );
}

window.Menu = Menu;
