// Sassalbini · UI components

const { useState, useEffect, useRef, useMemo } = React;

const Icon = {
  Search: () => <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><circle cx="11" cy="11" r="7"/><path d="m20 20-3.5-3.5"/></svg>,
  Heart: ({filled}) => <svg width="16" height="16" viewBox="0 0 24 24" fill={filled ? "currentColor" : "none"} stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78L12 21.23l8.84-8.84a5.5 5.5 0 0 0 0-7.78z"/></svg>,
  Cart: () => <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><circle cx="9" cy="21" r="1"/><circle cx="20" cy="21" r="1"/><path d="M1 1h4l2.68 13.39a2 2 0 0 0 2 1.61h9.72a2 2 0 0 0 2-1.61L23 6H6"/></svg>,
  Close: () => <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>,
  Plus: () => <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>,
  Check: () => <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round"><polyline points="20 6 9 17 4 12"/></svg>,
  User: () => <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/></svg>,
  Arrow: () => <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><line x1="5" y1="12" x2="19" y2="12"/><polyline points="12 5 19 12 12 19"/></svg>,
  Phone: () => <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72c.13.96.37 1.9.7 2.81a2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45c.91.33 1.85.57 2.81.7A2 2 0 0 1 22 16.92z"/></svg>,
  Mail: () => <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z"/><polyline points="22,6 12,13 2,6"/></svg>,
  Pin: () => <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z"/><circle cx="12" cy="10" r="3"/></svg>,
  Menu: () => <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><line x1="3" y1="6" x2="21" y2="6"/><line x1="3" y1="12" x2="21" y2="12"/><line x1="3" y1="18" x2="21" y2="18"/></svg>,
};

function euro(n) { return "€ " + n.toFixed(2).replace(".", ","); }
function resolveAsset(path) { return (window.__ASSET_URIS && window.__ASSET_URIS[path]) || path; }
window.__hooks_loaded = true;

function Topbar({ cartCount, onOpenCart, onHero }) {
  const [menuOpen, setMenuOpen] = useState(false);
  const close = () => setMenuOpen(false);
  return (
    <div className={"topbar " + (onHero ? "over-hero" : "") + (menuOpen ? " menu-open" : "")}>
      <div className="topbar-inner">
        <a className="brand-mark" href="#" onClick={close}>
          <img className="brand-logo" src={resolveAsset("assets/logo.png")} alt="Dai Sassalbini · Formaggi e Salumi · da tre generazioni" />
        </a>
        <nav className="nav-links">
          <a href="#storia">Storia</a>
          <a href="#prodotti" className="active">Bottega</a>
          <a href="#mappa">Mercati &amp; Mappa</a>
          <a href="#contatti">Contatti</a>
        </nav>
        <div className="top-actions">
          <button className="icon-btn" aria-label="Account"><Icon.User /></button>
          <button className="icon-btn hide-on-mobile" aria-label="Preferiti"><Icon.Heart /></button>
          <button className="icon-btn" onClick={onOpenCart} aria-label="Carrello">
            <Icon.Cart />
            {cartCount > 0 && <span className="cart-count">{cartCount}</span>}
          </button>
          <button className="icon-btn nav-toggle" onClick={() => setMenuOpen(o => !o)} aria-label="Menu" aria-expanded={menuOpen}>
            {menuOpen ? <Icon.Close /> : <Icon.Menu />}
          </button>
        </div>
      </div>
      <nav className="mobile-menu" data-open={menuOpen}>
        <a href="#storia" onClick={close}>Storia</a>
        <a href="#prodotti" onClick={close}>Bottega</a>
        <a href="#mappa" onClick={close}>Mercati &amp; Mappa</a>
        <a href="#contatti" onClick={close}>Contatti</a>
      </nav>
    </div>
  );
}

function Hero({ cartCount, onOpenCart }) {
  const [scene, setScene] = useState(0);
  const scenes = [
    { img: resolveAsset("assets/hero1.jpg"), label: "Formaggi e salumi al banco", meta: "Dai Sassalbini · da tre generazioni" },
    { img: resolveAsset("assets/hero2.jpg"), label: "La squadra al banco", meta: "Lunigiana · ogni giorno un mercato" },
  ];
  useEffect(() => {
    const t = setInterval(() => setScene(s => (s + 1) % scenes.length), 5200);
    return () => clearInterval(t);
  }, []);
  return (
    <section className="hero-cine">
      <Topbar cartCount={cartCount} onOpenCart={onOpenCart} onHero={true} />
      <div className="hero-cine-stage">
        {scenes.map((s, i) => (
          <div key={i} className={"hero-scene " + (i === scene ? "active" : "")} aria-hidden={i !== scene}>
            <div className="hero-scene-img" style={{ backgroundImage: `url(${s.img})` }} />
          </div>
        ))}
        <div className="hero-grain" aria-hidden="true" />
        <div className="hero-gradient" aria-hidden="true" />
        <div className="hero-vignette" aria-hidden="true" />
      </div>

      <div className="hero-cine-content">
        <div className="hero-cine-copy">
          <div className="hero-cine-eyebrow">
            <span className="hero-cine-dot" />
            <span>Da tre generazioni · Lunigiana</span>
          </div>
          <h1 className="hero-cine-title">Il banco di formaggi e salumi<br/><em>della Lunigiana.</em></h1>
          <p className="hero-cine-lede">Tre generazioni di selezione: piccoli caseifici e produttori, nessun intermediario. Diciotto mercati a settimana — e ora la bottega online.</p>
          <div className="hero-cine-actions">
            <a href="#prodotti" className="hero-cta primary">Esplora la bottega <Icon.Arrow /></a>
            <a href="#mappa" className="hero-cta ghost">Dove trovarci</a>
          </div>
          <div className="hero-cine-meta">
            <span>58 anni al banco</span>
            <span className="sep" />
            <span>18 mercati a settimana</span>
            <span className="sep" />
            <span>nessun intermediario</span>
          </div>
        </div>

        <div className="hero-cine-ticks">
          {scenes.map((_, i) => (
            <button
              key={i}
              className={"hero-tick " + (i === scene ? "on" : "")}
              onClick={() => setScene(i)}
              aria-label={"Scena " + (i + 1)}
            >
              <span className="hero-tick-fill" />
            </button>
          ))}
        </div>
      </div>
    </section>
  );
}

function Storia() {
  const wrapRef = useRef(null);
  const [progress, setProgress] = useState(0);
  const [visible, setVisible] = useState({});
  const [activeYear, setActiveYear] = useState(STORY[0].year);
  const itemRefs = useRef([]);

  useEffect(() => {
    function onScroll() {
      const el = wrapRef.current;
      if (!el) return;
      const rect = el.getBoundingClientRect();
      const vh = window.innerHeight;
      // progress = 0 when top hits mid-viewport, 1 when bottom leaves mid
      const start = rect.top - vh * 0.5;
      const dist = rect.height;
      const p = Math.max(0, Math.min(1, -start / dist));
      setProgress(p);
    }
    window.addEventListener("scroll", onScroll, { passive: true });
    onScroll();
    return () => window.removeEventListener("scroll", onScroll);
  }, []);

  useEffect(() => {
    const io = new IntersectionObserver((entries) => {
      entries.forEach(e => {
        const idx = Number(e.target.dataset.idx);
        if (e.isIntersecting) {
          setVisible(v => ({ ...v, [idx]: true }));
          if (e.intersectionRatio > 0.5) setActiveYear(STORY[idx].year);
        }
      });
    }, { threshold: [0, 0.3, 0.5, 0.8], rootMargin: "-20% 0px -30% 0px" });
    itemRefs.current.forEach(r => { if (r) io.observe(r); });
    return () => io.disconnect();
  }, []);

  return (
    <section className="storyline" id="storia">
      <div className="storyline-head">
        <div className="eyebrow">Storia della famiglia · di generazione in generazione</div>
        <h2 className="section-title">
          Tre generazioni<br/><em>al banco.</em>
        </h2>
        <p className="storyline-lede">
          Dalla transumanza di Remo, tra Rosignano Marittimo e Sassalbo, ai furgoni che oggi attraversano i mercati toscani e liguri: una famiglia in cammino, che ha trasformato la fatica in valore e la tradizione in un'eredità viva. Scorri la timeline.
        </p>
        <div className="storyline-ticker">
          <span className="ticker-dot" />
          <span className="ticker-year">{activeYear}</span>
          <span className="ticker-label">capitolo in evidenza</span>
        </div>
      </div>

      <div className="storyline-wrap" ref={wrapRef}>
        <div className="storyline-rail">
          <div className="storyline-rail-fill" style={{ height: `${progress * 100}%` }} />
          {STORY.map((s, i) => (
            <div
              key={s.year}
              className={"storyline-node " + (visible[i] ? "in" : "")}
              style={{ top: `${(i / (STORY.length - 1)) * 100}%` }}
            >
              <span className="storyline-node-dot" />
              <span className="storyline-node-year">{s.year}</span>
            </div>
          ))}
        </div>

        <ol className="storyline-list">
          {STORY.map((s, i) => (
            <li
              key={s.year}
              ref={el => (itemRefs.current[i] = el)}
              data-idx={i}
              className={"storyline-item " + (i % 2 === 0 ? "left" : "right") + (visible[i] ? " in" : "") + (i === STORY.length - 1 ? " is-last" : "") + ((s.video || s.photo) ? " has-aside" : "") + (s.photo ? " has-photo" : "")}
            >
              <div className="storyline-card">
                <div className="storyline-year-big">{s.year}</div>
                <div className="storyline-divider" />
                {s.gen && <div className="storyline-gen">{s.gen}</div>}
                <h3 className="storyline-title">{s.title}</h3>
                <p className="storyline-body">{s.body}</p>
                <div className="storyline-corner" aria-hidden="true">
                  <svg viewBox="0 0 40 40" width="40" height="40" fill="none" stroke="currentColor" strokeWidth="1" strokeLinecap="round">
                    <path d="M2 2 L38 2 L38 38" />
                    <circle cx="2" cy="2" r="1.5" fill="currentColor" stroke="none" />
                  </svg>
                </div>
              </div>
              {s.video && (
                <div className="storyline-video-aside">
                  <video ref={el => { if (el) el.muted = true; }} src={resolveAsset(s.video)} autoPlay loop muted playsInline controls preload="metadata" />
                </div>
              )}
              {s.photo && (
                <div className="storyline-video-aside is-photo">
                  <img src={resolveAsset(s.photo)} alt={s.title} loading="lazy" />
                </div>
              )}
            </li>
          ))}
        </ol>
      </div>
    </section>
  );
}

function Filterbar({ cat, setCat, q, setQ, sort, setSort }) {
  return (
    <div className="filterbar">
      <div className="filter-group">
        <span className="filter-label">Latte</span>
        {CATEGORIES.map(c => (
          <button key={c.id} className="chip" data-active={cat === c.id} onClick={() => setCat(c.id)}>{c.label}</button>
        ))}
      </div>
      <div style={{flex: 1, minWidth: 12}} />
      <div className="filter-group" style={{position: "relative", flex: "1 1 260px"}}>
        <div style={{position: "absolute", left: 14, top: "50%", transform: "translateY(-50%)", color: "var(--muted)", zIndex: 1, pointerEvents: "none"}}><Icon.Search /></div>
        <input className="search-input" style={{paddingLeft: 36, width: "100%"}} placeholder="Cerca Parmigiano, Pecorino, Bufala…" value={q} onChange={e => setQ(e.target.value)} />
      </div>
      <select className="sort-select" value={sort} onChange={e => setSort(e.target.value)}>
        {SORT_OPTIONS.map(s => <option key={s.id} value={s.id}>{s.label}</option>)}
      </select>
    </div>
  );
}

function ProductCard({ p, onOpen, wished, toggleWish, inCart, onAdd }) {
  return (
    <article className="card" onClick={() => onOpen(p)}>
      <div className="card-media">
        <div className="card-badges">
          {p.badges.slice(0, 2).map((b, i) => <span key={i} className={"badge " + (b === "DOP" ? "badge-dop" : "")}>{b}</span>)}
        </div>
        <button className="card-wish" data-active={wished} onClick={e => { e.stopPropagation(); toggleWish(p.id); }} aria-label="Preferiti"><Icon.Heart filled={wished} /></button>
        <img src={resolveAsset(p.image)} alt={p.name} loading="lazy" />
      </div>
      <div className="card-body">
        <div className="card-origin">{p.origin}</div>
        <div className="card-name">{p.name}</div>
        <div className="card-meta">{p.meta}</div>
        <div className="card-footer">
          <div className="price">
            {p.salePrice ? (<><span className="price-main">{euro(p.salePrice)}</span><span className="price-sale">{euro(p.price)}</span></>) : <span className="price-main">{euro(p.price)}</span>}
            <span className="price-unit">/ {p.unit}</span>
          </div>
          <button className={"btn-add " + (inCart ? "added" : "")} onClick={e => { e.stopPropagation(); onAdd(p); }}>
            {inCart ? <><Icon.Check /> Nel carrello</> : <><Icon.Plus /> Aggiungi</>}
          </button>
        </div>
      </div>
    </article>
  );
}

function ProductModal({ p, onClose, onAdd }) {
  const [qty, setQty] = useState(1);
  useEffect(() => {
    const onKey = e => { if (e.key === "Escape") onClose(); };
    document.addEventListener("keydown", onKey);
    document.body.style.overflow = "hidden";
    return () => { document.removeEventListener("keydown", onKey); document.body.style.overflow = ""; };
  }, []);
  if (!p) return null;
  return (
    <div className="modal-veil" onClick={onClose}>
      <div className="modal" onClick={e => e.stopPropagation()}>
        <button className="modal-close" onClick={onClose}><Icon.Close /></button>
        <div className="modal-grid">
          <div className="modal-media"><img src={resolveAsset(p.image)} alt={p.name} /></div>
          <div className="modal-body">
            <div className="eyebrow">{p.origin}</div>
            <h2>{p.name}</h2>
            <div className="modal-badges">{p.badges.map((b, i) => <span key={i} className={"badge " + (b === "DOP" ? "badge-dop" : "")}>{b}</span>)}</div>
            <p className="modal-desc">{p.meta}</p>
            <div className="modal-specs">
              <div className="spec"><div className="spec-label">Stagionatura</div><div className="spec-value">{p.aging}</div></div>
              <div className="spec"><div className="spec-label">Latte</div><div className="spec-value">{p.milk}</div></div>
              <div className="spec"><div className="spec-label">Formato</div><div className="spec-value" style={{fontSize: 14}}>{p.format}</div></div>
              <div className="spec"><div className="spec-label">Consegna</div><div className="spec-value" style={{fontSize: 14}}>Refrigerata · 24-48h</div></div>
            </div>
            <div className="modal-price-row">
              <div className="price">
                {p.salePrice ? (<><span className="price-main">{euro(p.salePrice)}</span><span className="price-sale">{euro(p.price)}</span></>) : <span className="price-main">{euro(p.price)}</span>}
                <span className="price-unit">/ {p.unit}</span>
              </div>
              <div className="qty">
                <button onClick={() => setQty(q => Math.max(1, q - 1))}>−</button>
                <span>{qty}</span>
                <button onClick={() => setQty(q => q + 1)}>+</button>
              </div>
            </div>
            <div className="modal-actions">
              <button className="btn-primary" onClick={() => { onAdd(p, qty); onClose(); }}><Icon.Cart /> Aggiungi al carrello</button>
              <button className="btn-ghost">Dettagli</button>
            </div>
          </div>
        </div>
      </div>
    </div>
  );
}

function CartPanel({ items, onClose, onQty, onRemove }) {
  useEffect(() => {
    document.body.style.overflow = "hidden";
    return () => { document.body.style.overflow = ""; };
  }, []);
  const rows = items.map(it => ({ ...it, product: PRODUCTS.find(p => p.id === it.id) })).filter(r => r.product);
  const subtotal = rows.reduce((s, r) => s + (r.product.salePrice ?? r.product.price) * r.qty, 0);
  const shipping = subtotal > 80 ? 0 : (rows.length ? 9.90 : 0);
  const total = subtotal + shipping;
  return (
    <>
      <div className="cart-veil" onClick={onClose} />
      <aside className="cart-panel">
        <div className="cart-header"><h3>Il tuo carrello</h3><button className="icon-btn" onClick={onClose}><Icon.Close /></button></div>
        <div className="cart-body">
          {rows.length === 0 ? (
            <div className="cart-empty"><div className="big">Il banco ti aspetta.</div><div>Scegli una forma dalla bottega e torna qui.</div></div>
          ) : rows.map(r => (
            <div className="cart-item" key={r.id}>
              <img src={resolveAsset(r.product.image)} alt="" />
              <div className="cart-item-info">
                <div className="name">{r.product.name}</div>
                <div className="meta">{r.product.origin}</div>
                <div className="qty-inline">
                  <button onClick={() => onQty(r.id, r.qty - 1)}>−</button>
                  <span className="font-mono" style={{fontSize: 12}}>{r.qty}</span>
                  <button onClick={() => onQty(r.id, r.qty + 1)}>+</button>
                  <button onClick={() => onRemove(r.id)} style={{marginLeft: 8, fontSize: 11, border: "none", background: "transparent", color: "var(--muted)", cursor: "pointer"}}>rimuovi</button>
                </div>
              </div>
              <div className="cart-item-price">{euro((r.product.salePrice ?? r.product.price) * r.qty)}</div>
            </div>
          ))}
        </div>
        {rows.length > 0 && (
          <div className="cart-footer">
            <div className="cart-row"><span>Subtotale</span><span>{euro(subtotal)}</span></div>
            <div className="cart-row"><span>Spedizione refrigerata</span><span>{shipping === 0 ? "Omaggio" : euro(shipping)}</span></div>
            <div className="cart-row total"><span>Totale</span><span className="val">{euro(total)}</span></div>
            <button className="checkout-btn">Procedi al checkout <Icon.Arrow /></button>
          </div>
        )}
      </aside>
    </>
  );
}

function Mercati() {
  const today = new Date().getDay(); // 0=Dom, 1=Lun ...
  const todayIdx = today === 0 ? 6 : today - 1;
  const todayMarket = MARKETS[todayIdx];
  const todayCities = todayMarket.stops.map(s => s.city);
  return (
    <section className="mercati" id="mercati">
      <div className="section-intro">
        <div>
          <div className="eyebrow">Mercati · da lunedì a sabato</div>
          <h2 className="section-title">Dove trovarci<br/><em>questa settimana.</em></h2>
        </div>
        <p>Il banco è itinerante: ogni settimana i furgoni attraversano la Toscana e la Liguria, dalla Versilia alle Cinque Terre. Arriviamo la mattina presto, chiudiamo quando finisce la forma.</p>
      </div>

      <div className="mercati-hero" style={{marginTop: 26}}>
        <div style={{display: "flex", alignItems: "center", gap: 12, flexWrap: "wrap"}}>
          <span className="today-pill"><span className="dot" /> {todayMarket.closed ? "Oggi chiuso" : "In piazza oggi"}</span>
          <span style={{fontFamily: "Geist Mono, monospace", fontSize: 11, letterSpacing: "0.18em", textTransform: "uppercase", color: "var(--muted)"}}>{new Date().toLocaleDateString("it-IT", { weekday: "long", day: "numeric", month: "long" })}</span>
        </div>
        <h3 className="today-title">
          {todayMarket.closed ? (<>Il banco <em>riposa.</em><br/>Ci vediamo domani.</>) : (<>Oggi siamo a<br/><em>{todayCities.join(" · ")}</em></>)}
        </h3>
        {!todayMarket.closed && (
          <div className="today-meta">
            <div><Icon.Pin /> <strong>{todayCities.length} {todayCities.length === 1 ? "mercato" : "mercati"} oggi</strong></div>
            <div>Solo contanti, POS contactless e bancomat.</div>
          </div>
        )}
        <div className="week-grid">
          {MARKETS.map((m, i) => (
            <div key={m.day} className={"day-card " + (i === todayIdx ? "today" : "") + (m.closed ? " closed" : "")}>
              <div className="day-short">{m.dayShort}</div>
              <div className="day-city">{m.closed ? "Riposo" : m.stops.map(s => s.city).join(" · ")}</div>
              <div className="day-hours">{m.closed ? "A presto" : m.stops.length + (m.stops.length === 1 ? " mercato" : " mercati")}</div>
            </div>
          ))}
        </div>
      </div>
    </section>
  );
}

const TRUCK_SVG = `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M10 17h4V5H2v12h3"/><path d="M20 17h2v-3.34a4 4 0 0 0-1.17-2.83L19 9h-5v8h1"/><circle cx="7.5" cy="17.5" r="2.5"/><circle cx="17.5" cy="17.5" r="2.5"/></svg>`;

function makePinIcon(gold) {
  return window.L.divIcon({
    className: "",
    html: `<div class="map-pin ${gold ? "today" : ""}">${TRUCK_SVG}</div>`,
    iconSize: [gold ? 40 : 34, gold ? 40 : 34],
    iconAnchor: [gold ? 20 : 17, gold ? 46 : 40],
  });
}

function Mappa() {
  const today = new Date().getDay();
  const todayIdx = today === 0 ? 6 : today - 1;
  const [selected, setSelected] = useState(MARKETS[todayIdx].closed ? 0 : todayIdx);
  const mapRef = useRef(null);
  const leafletMap = useRef(null);
  const markersRef = useRef([]);

  useEffect(() => {
    if (!window.L || leafletMap.current) return;
    const map = window.L.map(mapRef.current, { zoomControl: false, scrollWheelZoom: false, fadeAnimation: false });
    window.L.control.zoom({ position: "topright" }).addTo(map);
    window.L.tileLayer("https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}{r}.png", {
      attribution: '&copy; OpenStreetMap contributors &copy; CARTO',
      subdomains: "abcd", maxZoom: 19,
    }).addTo(map);
    const allCoords = [];
    MARKETS.forEach((m, i) => {
      if (m.closed) return;
      markersRef.current[i] = [];
      m.stops.forEach(s => {
        allCoords.push(s.coords);
        const marker = window.L.marker(s.coords, { icon: makePinIcon(false) }).addTo(map);
        marker.bindPopup(`<strong>${s.city}</strong><br/><span style="font-family:Geist Mono,monospace;font-size:11px;opacity:0.7">${m.day}</span>`);
        marker.on("click", () => setSelected(i));
        markersRef.current[i].push(marker);
      });
    });
    map.fitBounds(allCoords, { padding: [40, 40] });
    leafletMap.current = map;
    // Ensure tiles render when section scrolls into view (offscreen init → size=0 bug)
    const io = new IntersectionObserver((entries) => {
      entries.forEach(e => { if (e.isIntersecting) { map.invalidateSize(); } });
    }, { threshold: 0.1 });
    io.observe(mapRef.current);
    // And force a resize once fonts/layout settle
    setTimeout(() => map.invalidateSize(), 300);
    return () => io.disconnect();
  }, []);

  useEffect(() => {
    if (!leafletMap.current) return;
    // Tutti i pin del giorno selezionato diventano oro, gli altri tornano normali
    MARKETS.forEach((m, i) => {
      (markersRef.current[i] || []).forEach(marker => marker.setIcon(makePinIcon(i === selected)));
    });
    const m = MARKETS[selected];
    if (m.closed || !m.stops.length) return;
    leafletMap.current.flyToBounds(m.stops.map(s => s.coords), { padding: [60, 60], maxZoom: 12, duration: 0.8 });
  }, [selected]);

  return (
    <section className="mappa" id="mappa">
      <div className="section-intro">
        <div>
          <div className="eyebrow">Mappa interattiva</div>
          <h2 className="section-title">Dalla Versilia<br/><em>alle Cinque Terre.</em></h2>
        </div>
        <p>Clicca su un giorno: la mappa inquadra le sue piazze e i camioncini diventano oro.</p>
      </div>
      <div className="mappa-wrap" style={{marginTop: 26}}>
        <div className="mappa-side">
          <div className="eyebrow">Toscana &amp; Liguria · piazza per piazza</div>
          <h3>Il giro settimanale</h3>
          <div className="mappa-list">
            {MARKETS.map((m, i) => (
              <button key={m.day} className={"mappa-item" + (i === selected ? " active" : "")} onClick={() => setSelected(i)} disabled={m.closed}>
                <div className="pill">{m.dayShort}</div>
                <div>
                  <div className="place">{m.closed ? "Riposo" : m.stops.map(s => s.city).join(" · ")}</div>
                  <div className="sub">{m.closed ? "A presto" : m.stops.length + (m.stops.length === 1 ? " mercato" : " mercati")}</div>
                </div>
              </button>
            ))}
          </div>
        </div>
        <div className="mappa-map">
          <div id="leaflet-map" ref={mapRef} />
        </div>
      </div>
    </section>
  );
}

function Testimonianze() {
  return (
    <section className="testi" id="recensioni">
      <div className="section-intro">
        <div>
          <div className="eyebrow">Recensioni · la voce dei clienti</div>
          <h2 className="section-title">Quattro generazioni<br/><em>al nostro banco.</em></h2>
        </div>
        <p>Non solo cheese tasting. Famiglie, chef, enotecari, ragazzi che venivano con i nonni e ora portano i figli.</p>
      </div>
      <div className="testi-grid">
        {TESTIMONIALS.map((t, i) => (
          <article key={i} className="testi-card">
            <p className="testi-quote">{t.content}</p>
            <div className="testi-foot">
              <div className="testi-avatar">{t.avatar ? <img src={t.avatar} alt={t.name} loading="lazy" /> : t.name.charAt(0)}</div>
              <div className="testi-meta">
                <div className="n">{t.name}</div>
                <div className="r">{t.role} {t.city}</div>
              </div>
              <div className="stars">★★★★★</div>
            </div>
          </article>
        ))}
      </div>
    </section>
  );
}

function Contatti() {
  return (
    <section className="cta" id="contatti">
      <div className="cta-text">
        <div className="cta-eyebrow">Contatti · scrivi a Marco</div>
        <h3>Ordina al telefono,<br/><em>come al banco.</em></h3>
        <p>Chiama o scrivi: Marco ti consiglia le stagionature, organizza consegne nella zona, prepara taglieri su misura per eventi e ristoranti.</p>
      </div>
      <div className="cta-card">
        <a href="tel:+390187000000" className="cta-contact">
          <span className="cta-contact-ico"><Icon.Phone /></span>
          <span className="cta-contact-txt">
            <span className="cta-contact-label">Telefono · WhatsApp</span>
            <span className="cta-contact-value">+39 0187 000 000</span>
          </span>
          <span className="cta-contact-arrow"><Icon.Arrow /></span>
        </a>
        <a href="mailto:info@sassalbini.it" className="cta-contact">
          <span className="cta-contact-ico"><Icon.Mail /></span>
          <span className="cta-contact-txt">
            <span className="cta-contact-label">Email</span>
            <span className="cta-contact-value">info@sassalbini.it</span>
          </span>
          <span className="cta-contact-arrow"><Icon.Arrow /></span>
        </a>
        <div className="cta-hours"><span className="dot" /> Lun–Sab · 14:00–19:00</div>
      </div>
    </section>
  );
}

function Footer() {
  return (
    <footer className="footer shell" style={{maxWidth: 1440}}>
      <div className="footer-brand">
        <div className="font-display">Sassalbini</div>
        <p style={{marginTop: 10, maxWidth: 340}}>Formaggi e salumi al banco da tre generazioni. Castelnuovo Magra, Lunigiana. Diciotto mercati settimanali, una bottega online.</p>
        <p style={{marginTop: 16, fontSize: 11, opacity: 0.7, fontFamily: "Geist Mono, monospace", letterSpacing: "0.1em"}}>P.IVA IT 00000000000 · © 2026 Sassalbini</p>
      </div>
      <div>
        <h5>Bottega</h5>
        <a href="#prodotti">Formaggi</a>
        <a href="#prodotti">Tutte le stagionature</a>
        <a href="#mappa">Mercati &amp; Mappa</a>
      </div>
      <div>
        <h5>Contatti</h5>
        <a href="tel:+390187000000">+39 0187 000 000</a>
        <a href="mailto:info@sassalbini.it">info@sassalbini.it</a>
        <a href="#">Castelnuovo Magra (SP)</a>
        <a href="https://www.facebook.com/daisassalbini" target="_blank" rel="noopener">Facebook</a>
      </div>
    </footer>
  );
}

function Tweaks({ theme, setTheme }) {
  return (
    <div className="tweaks">
      <h4>Tweaks</h4>
      <div className="tweak-row">
        <div className="tweak-label">Direzione visiva</div>
        <div className="tweak-seg" style={{gridTemplateColumns: "repeat(2, 1fr)"}}>
          <button data-active={theme === "editorial"} onClick={() => setTheme("editorial")}>Editoriale</button>
          <button data-active={theme === "chiaro"} onClick={() => setTheme("chiaro")}>Chiaro</button>
        </div>
      </div>
      <div className="tweak-row">
        <div className="tweak-label" style={{lineHeight: 1.6}}>
          <strong style={{color: "var(--fg)"}}>Editoriale</strong> — crema &amp; bordeaux, rivista.<br/>
          <strong style={{color: "var(--fg)"}}>Chiaro</strong> — bianco puro, minimale.
        </div>
      </div>
    </div>
  );
}

function Toast({ msg }) {
  if (!msg) return null;
  return <div className="toast"><Icon.Check /> {msg.text}</div>;
}

function FloatingCart({ count, onOpen }) {
  return (
    <button className="cart-fab" onClick={onOpen} aria-label="Apri il carrello">
      <Icon.Cart />
      {count > 0 && <span className="cart-fab-count">{count}</span>}
    </button>
  );
}

Object.assign(window, { Topbar, Hero, Storia, Filterbar, ProductCard, ProductModal, CartPanel, Mercati, Mappa, Testimonianze, Contatti, Footer, Tweaks, Toast, FloatingCart, euro });
