/* === Che Facemo — App + 3 views (real API) === */
/* eslint-disable */
const { useState, useEffect, useMemo, useRef, useCallback } = React;

const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "density": "comfy",
  "imageStyle": "gradient",
  "dark": false
}/*EDITMODE-END*/;

// ────────────────────────────────────────────────────────
//   MAP VIEW
// ────────────────────────────────────────────────────────
function MapView({ events, onOpen, onJumpToList, modalOpen }) {
  const [active, setActive] = useState(null);
  const W = 1200, H = 700;
  const futureEvents = useMemo(() => events.filter(e => e.date >= todayISO()), [events]);
  const counts    = countByProvince(futureEvents);
  const maxCount  = Math.max(...Object.values(counts), 1);

  const sideEvents = useMemo(() => {
    if (!active) return [];
    return futureEvents
      .filter(e => e.province === active)
      .sort((a, b) => a.date.localeCompare(b.date))
      .slice(0, 5);
  }, [active, futureEvents]);

  return (
    <div className={`mapview${modalOpen ? ' map-hidden' : ''}`}>
      <svg viewBox={`0 0 ${W} ${H}`} className="map-svg" preserveAspectRatio="xMidYMid meet">
        <g className="map-grid">
          {Array.from({ length: 12 }).map((_, i) => (
            <line key={`v${i}`} x1={(i+1)*(W/12)} y1="0" x2={(i+1)*(W/12)} y2={H} />
          ))}
          {Array.from({ length: 7 }).map((_, i) => (
            <line key={`h${i}`} x1="0" y1={(i+1)*(H/7)} x2={W} y2={(i+1)*(H/7)} />
          ))}
        </g>
        <MarcheCoast w={W} h={H} pad={60} />
        <path className="map-coast" d="M 1050,90 Q 1090,250 1070,420 Q 1030,560 920,610" />

        {Object.entries(PROVINCE_COORDS).map(([prov, [lat, lon]]) => {
          const { x, y } = projectLatLon(lat, lon, W, H, 60);
          const count    = counts[prov] || 0;
          const r        = count === 0 ? 10 : 18 + (count / maxCount) * 28;
          const isAct    = active === prov;
          return (
            <g key={prov} className={`marker-group${isAct ? ' act' : ''}`} onClick={() => setActive(prov)}>
              <circle cx={x} cy={y} r={r + 14} fill="var(--terracotta)" fillOpacity="0.08" />
              <circle cx={x} cy={y} r={r} className="marker-circle" />
              {count > 0 && <text x={x} y={y + 1} className="marker-count">{count}</text>}
              <text x={x} y={y + r + 22} className="marker-label">{prov}</text>
            </g>
          );
        })}

        <text x={W - 80} y={H/2} className="marker-label"
              style={{ fill:'var(--terracotta)', fontStyle:'italic', fontFamily:'var(--font-display)', fontSize:'28px', letterSpacing:0, textTransform:'none' }}>
          Adriatico
        </text>
      </svg>

      <div className="map-legend">
        <span>Eventi per provincia</span>
        <span style={{ display:'flex', alignItems:'center', gap:8 }}>
          <span className="swatch" style={{ width:10, height:10 }} /> pochi
        </span>
        <span style={{ display:'flex', alignItems:'center', gap:8 }}>
          <span className="swatch lg" /> molti
        </span>
      </div>

      {active && (
        <div className="map-side">
          <button className="close-x" onClick={() => setActive(null)} aria-label="Chiudi">×</button>
          <div className="eyebrow">Provincia</div>
          <h3>{active}</h3>
          <div className="label" style={{ color:'var(--terracotta)' }}>
            {counts[active]} eventi · prossimi 5
          </div>
          <div style={{ marginTop:6 }}>
            {sideEvents.length === 0 && <div className="cal-side empty">Nessun evento</div>}
            {sideEvents.map(e => {
              const cat = CATEGORIES[e.category] || CATEGORIES.musica;
              const d   = parseISO(e.date);
              return (
                <div key={e.id} className="mini-event" style={{ '--cat': cat.color }} onClick={() => onOpen(e)}>
                  <div>
                    <div className="mini-event-day">{d.getDate()}</div>
                    <div className="mini-event-mon">{monthLong(d).slice(0, 3)}</div>
                  </div>
                  <div>
                    <div className="mini-event-name">{e.event_name}</div>
                    <div className="mini-event-meta">{e.time || 'tutto il giorno'} · {e.venue}</div>
                  </div>
                </div>
              );
            })}
          </div>
          {sideEvents.length > 0 && (
            <button className="btn primary" style={{ marginTop:'auto', alignSelf:'flex-start' }}
                    onClick={() => onJumpToList(active)}>
              Vedi tutti <Icon.chev />
            </button>
          )}
        </div>
      )}

      {/* Mobile: bottom sheet — replaces side panel on small screens */}
      <div className={`map-sheet-back${active ? ' open' : ''}`} onClick={() => setActive(null)} />
      <div className={`map-bottom-sheet${active ? ' open' : ''}`}>
        <div className="map-bottom-sheet-handle" />
        <div className="map-bottom-sheet-head">
          <div>
            <div className="meta">{active ? `${counts[active] || 0} eventi · prossimi` : 'provincia'}</div>
            <h3>{active || '—'}</h3>
          </div>
          <button className="close-x" style={{ position:'static' }} onClick={() => setActive(null)} aria-label="Chiudi">×</button>
        </div>
        <div className="map-bottom-sheet-list">
          {sideEvents.length === 0 && active && (
            <div style={{ padding:'24px 0', textAlign:'center', fontFamily:'var(--font-mono)', fontSize:11,
                          letterSpacing:'0.14em', textTransform:'uppercase', color:'var(--fg-muted)' }}>
              Nessun evento
            </div>
          )}
          {sideEvents.map(e => {
            const cat = CATEGORIES[e.category] || CATEGORIES.musica;
            const d   = parseISO(e.date);
            return (
              <div key={e.id} className="mini-event" style={{ '--cat': cat.color }} onClick={() => onOpen(e)}>
                <div>
                  <div className="mini-event-day">{d.getDate()}</div>
                  <div className="mini-event-mon">{monthLong(d).slice(0, 3)}</div>
                </div>
                <div>
                  <div className="mini-event-name">{e.event_name}</div>
                  <div className="mini-event-meta">
                    <span style={{ color: cat.color }}>● {cat.label}</span> · {e.venue}
                  </div>
                </div>
              </div>
            );
          })}
          {sideEvents.length > 0 && (
            <button className="btn primary" style={{ marginTop:16 }}
                    onClick={() => { setActive(null); onJumpToList(active); }}>
              Vedi tutti <Icon.chev />
            </button>
          )}
        </div>
      </div>
    </div>
  );
}

// ────────────────────────────────────────────────────────
//   MOBILE FOOTER (Edizione N. — visible only on mobile)
// ────────────────────────────────────────────────────────
function MobileFooter({ issueNum, today }) {
  return (
    <div className="mobile-footer">
      <div className="mobile-footer-row">
        <span>Edizione N. {issueNum}</span>
        <span>{weekdayShort(today)} {today.getDate()} {monthLong(today)} {today.getFullYear()}</span>
      </div>
      <hr />
      <div className="mobile-footer-row">
        <span>Aggiornato auto · ogni 6h</span>
        <span className="live">● live</span>
      </div>
      <div className="mobile-footer-sig">fatto nelle Marche · {today.getFullYear()}</div>
    </div>
  );
}

// ────────────────────────────────────────────────────────
//   LIST VIEW
// ────────────────────────────────────────────────────────
function ListView({ events, filters, setFilters, onOpen, onToast, loading, imageStyle, provinces, catKeys, issueNum, todayDate }) {
  const cats = catKeys;
  const cities  = useMemo(() => citiesForProvince(events, filters.province), [events, filters.province]);
  const weekend = thisWeekendRange();
  const week    = thisWeekRange();

  const filtered = useMemo(() => {
    const today = todayISO();
    return events.filter(e => {
      if (e.date < today)               return false;  // nascondi eventi passati dalla lista
      if (filters.province  && e.province  !== filters.province)  return false;
      if (filters.city      && e.city      !== filters.city)      return false;
      if (filters.category  && e.category  !== filters.category)  return false;
      if (filters.from      && e.date       < filters.from)       return false;
      if (filters.to        && e.date       > filters.to)         return false;
      return true;
    }).sort((a, b) => a.date.localeCompare(b.date));
  }, [events, filters]);

  const isWeekend = filters.from === weekend.from && filters.to === weekend.to;
  const isWeek    = filters.from === week.from    && filters.to === week.to;

  const toggleWeekend = () =>
    setFilters(f => isWeekend ? { ...f, from:'', to:'' } : { ...f, from:weekend.from, to:weekend.to });
  const toggleWeek = () =>
    setFilters(f => isWeek ? { ...f, from:'', to:'' } : { ...f, from:week.from, to:week.to });

  const hasFilters = filters.province || filters.city || filters.category || filters.from || filters.to;

  return (
    <div>
      <div className="filter-bar">
        <button className="pill pill-quick" aria-pressed={isWeekend} onClick={toggleWeekend}>
          ◐ Questo weekend
        </button>
        <button className="pill pill-quick" aria-pressed={isWeek} onClick={toggleWeek}>
          ☷ Questa settimana
        </button>
        <span className="filter-sep" />
        <select className="select-pill" value={filters.province}
                onChange={e => setFilters(f => ({ ...f, province:e.target.value, city:'' }))}>
          <option value="">Tutte le province</option>
          {provinces.map(p => <option key={p} value={p}>{p}</option>)}
        </select>
        {filters.province && cities.length > 1 && (
          <select className="select-pill" value={filters.city}
                  onChange={e => setFilters(f => ({ ...f, city:e.target.value }))}>
            <option value="">Tutte le città</option>
            {cities.map(c => <option key={c} value={c}>{c}</option>)}
          </select>
        )}
        <select className="select-pill" value={filters.category}
                onChange={e => setFilters(f => ({ ...f, category:e.target.value }))}>
          <option value="">Tutte le categorie</option>
          {cats.map(c => <option key={c} value={c}>{CATEGORIES[c].label}</option>)}
        </select>
        {hasFilters && (
          <button className="pill" style={{ borderStyle:'dashed' }}
                  onClick={() => setFilters({ province:'', city:'', category:'', from:'', to:'' })}>
            × reset
          </button>
        )}
        <span className="filter-count">
          {loading ? '…' : `${filtered.length}`} eventi
        </span>
      </div>

      {loading ? (
        <div className="list-grid">
          {Array.from({ length: 6 }).map((_, i) => <SkeletonCard key={i} />)}
        </div>
      ) : filtered.length === 0 ? (
        <div style={{ padding:60, textAlign:'center', border:'1px dashed var(--rule)',
                      fontFamily:'var(--font-mono)', fontSize:11, letterSpacing:'0.14em',
                      textTransform:'uppercase', color:'var(--fg-muted)' }}>
          Nessun evento con questi filtri
        </div>
      ) : (
        <div className="list-grid hero-mode">
          {filtered.map((e, i) => {
            const card = (
              <EventCard key={e.id} event={e} index={i} onOpen={onOpen}
                         onToast={onToast} imageStyle={imageStyle} />
            );
            if (i === 3) {
              return (
                <React.Fragment key={`frag-${e.id}`}>
                  <div className="flag">
                    <div className="lhs">in evidenza</div>
                    <div className="rhs">scorri ↓</div>
                  </div>
                  {card}
                </React.Fragment>
              );
            }
            return card;
          })}
        </div>
      )}

      <MobileFooter issueNum={issueNum} today={todayDate} />
    </div>
  );
}

// ────────────────────────────────────────────────────────
//   CALENDAR VIEW
// ────────────────────────────────────────────────────────
function CalendarView({ events, onOpen, onToast, provinces }) {
  const today = parseISO(todayISO());
  const [cursor,    setCursor]    = useState({ y: today.getFullYear(), m: today.getMonth() });
  const [selected,  setSelected]  = useState(todayISO());
  const [province,  setProvince]  = useState('');
  const [city,      setCity]      = useState('');
  const [rangeFrom, setRangeFrom] = useState('');
  const [rangeTo,   setRangeTo]   = useState('');

  const cities = useMemo(() => citiesForProvince(events, province), [events, province]);

  const filtered = useMemo(
    () => events.filter(e => {
      if (province && e.province !== province) return false;
      if (city     && e.city     !== city)     return false;
      return true;
    }),
    [events, province, city]
  );

  useEffect(() => { setCity(''); }, [province]);

  const rangeActive = Boolean(rangeFrom || rangeTo);

  const grid = useMemo(() => {
    const first    = new Date(cursor.y, cursor.m, 1);
    const startDay = first.getDay() === 0 ? 6 : first.getDay() - 1;
    const start    = new Date(first); start.setDate(first.getDate() - startDay);
    const days     = [];
    for (let i = 0; i < 42; i++) {
      const d = new Date(start); d.setDate(start.getDate() + i);
      days.push(d);
    }
    return days;
  }, [cursor]);

  const eventsByDay = useMemo(() => {
    const map = {};
    filtered.forEach(e => { (map[e.date] = map[e.date] || []).push(e); });
    return map;
  }, [filtered]);

  const sideEvents = useMemo(() => {
    if (rangeActive) {
      const from = rangeFrom || '0000-00-00';
      const to   = rangeTo   || '9999-12-31';
      return filtered
        .filter(e => e.date >= from && e.date <= to)
        .sort((a, b) => a.date.localeCompare(b.date) || (a.time || '').localeCompare(b.time || ''));
    }
    return (eventsByDay[selected] || []).sort((a, b) => (a.time || '').localeCompare(b.time || ''));
  }, [rangeActive, rangeFrom, rangeTo, filtered, eventsByDay, selected]);

  const sideEventsByDay = useMemo(() => {
    if (!rangeActive) return null;
    const out = {};
    sideEvents.forEach(e => { (out[e.date] = out[e.date] || []).push(e); });
    return out;
  }, [rangeActive, sideEvents]);

  const monthEvents = useMemo(() => {
    const monthStr = `${cursor.y}-${String(cursor.m + 1).padStart(2, '0')}`;
    return filtered.filter(e => e.date.startsWith(monthStr)).sort((a, b) => a.date.localeCompare(b.date));
  }, [filtered, cursor]);

  const exportICS = () => {
    const list  = rangeActive ? sideEvents : monthEvents;
    const label = rangeActive
      ? `${rangeFrom || 'inizio'}_${rangeTo || 'fine'}`
      : `${monthLong(new Date(cursor.y, cursor.m, 1))}-${cursor.y}`;
    if (!list.length) { onToast('Nessun evento da esportare'); return; }
    downloadICS(list, `che-facemo-${label}${province ? '-' + province.toLowerCase() : ''}.ics`);
    onToast(`Calendario .ics scaricato (${list.length} eventi)`);
  };

  const cursorDate = new Date(cursor.y, cursor.m, 1);

  const isInRange = (iso) => {
    if (!rangeActive) return false;
    const from = rangeFrom || '0000-00-00';
    const to   = rangeTo   || '9999-12-31';
    return iso >= from && iso <= to;
  };

  return (
    <div className="cal-wrap">
      <div>
        <div className="cal-head">
          <h2>
            <span className="serif-i">{monthLong(cursorDate)}</span>{' '}
            <span className="num" style={{ color:'var(--fg-soft)' }}>{cursor.y}</span>
          </h2>
          <div className="cal-nav">
            <button className="ico-btn" onClick={() => setCursor(c => {
              const d = new Date(c.y, c.m - 1, 1);
              return { y: d.getFullYear(), m: d.getMonth() };
            })}><Icon.chev style={{ transform:'rotate(180deg)' }} /></button>
            <button className="ico-btn" onClick={() => {
              setCursor({ y: today.getFullYear(), m: today.getMonth() });
              setSelected(todayISO());
            }}>oggi</button>
            <button className="ico-btn" onClick={() => setCursor(c => {
              const d = new Date(c.y, c.m + 1, 1);
              return { y: d.getFullYear(), m: d.getMonth() };
            })}><Icon.chev /></button>
          </div>
        </div>

        <div className="filter-bar" style={{ marginBottom:14, paddingTop:0, borderBottom:0, gap:8 }}>
          <select className="select-pill" value={province}
                  onChange={e => setProvince(e.target.value)}>
            <option value="">Tutte le province</option>
            {provinces.map(p => <option key={p} value={p}>{p}</option>)}
          </select>
          {province && cities.length > 1 && (
            <select className="select-pill" value={city}
                    onChange={e => setCity(e.target.value)}>
              <option value="">Tutte le città</option>
              {cities.map(c => <option key={c} value={c}>{c}</option>)}
            </select>
          )}
          <span className="filter-sep" />
          <DateRangePill from={rangeFrom} to={rangeTo} setFrom={setRangeFrom} setTo={setRangeTo} />
          {(province || city || rangeActive) && (
            <button className="pill" style={{ borderStyle:'dashed' }}
                    onClick={() => { setProvince(''); setCity(''); setRangeFrom(''); setRangeTo(''); }}>
              × reset
            </button>
          )}
          <button className="pill pill-quick" onClick={exportICS} style={{ marginLeft:'auto' }}>
            <Icon.cal /> Esporta {rangeActive ? 'intervallo' : monthLong(cursorDate)} (.ics)
          </button>
        </div>

        <div className="cal-grid">
          {['lun','mar','mer','gio','ven','sab','dom'].map(d => (
            <div className="cal-hd" key={d}>{d}</div>
          ))}
          {grid.map((d, i) => {
            const iso     = fmtISO(d);
            const inMonth = d.getMonth() === cursor.m;
            const isToday = iso === todayISO();
            const isSel   = !rangeActive && iso === selected;
            const inRange = isInRange(iso);
            const evs     = eventsByDay[iso] || [];
            return (
              <div key={i}
                   className={`cal-cell${inMonth ? '' : ' out'}${isToday ? ' today' : ''}${isSel ? ' act' : ''}${inRange ? ' in-range' : ''}`}
                   onClick={() => setSelected(iso)}>
                <div className="cal-day-n">{d.getDate()}</div>
                {evs.length > 0 && (
                  <div className="cal-dots">
                    {evs.slice(0, 6).map((e, j) => {
                      const cat = CATEGORIES[e.category] || CATEGORIES.musica;
                      return <span key={j} className="cal-dot" style={{ '--cat': cat.color }} title={e.event_name} />;
                    })}
                  </div>
                )}
              </div>
            );
          })}
        </div>
      </div>

      <div className="cal-side">
        <div className="eyebrow">
          {rangeActive
            ? `Intervallo${rangeFrom ? ` · dal ${formatDateShort(rangeFrom)}` : ''}${rangeTo ? ` · al ${formatDateShort(rangeTo)}` : ''}`
            : 'Giorno selezionato'}
        </div>
        <h3>
          {rangeActive
            ? <span className="serif-i">{sideEvents.length} eventi</span>
            : <span className="serif-i">{formatDateLong(selected)}</span>}
        </h3>

        {sideEvents.length === 0 ? (
          <div className="empty">
            Nessun evento {rangeActive ? 'in questo intervallo' : 'questo giorno'}
            {province && ` in ${city || province}`}
          </div>
        ) : rangeActive ? (
          Object.entries(sideEventsByDay).map(([day, evs]) => (
            <div key={day} style={{ marginTop:8 }}>
              <div className="eyebrow" style={{ marginBottom:4, color:'var(--terracotta)' }}>
                {formatDateLong(day)}
              </div>
              {evs.map(e => <SideRow key={e.id} event={e} onOpen={onOpen} onToast={onToast} />)}
            </div>
          ))
        ) : (
          sideEvents.map(e => <SideRow key={e.id} event={e} onOpen={onOpen} onToast={onToast} />)
        )}
      </div>
    </div>
  );
}

// ── SideRow ───────────────────────────────────────────────────────────────────
function SideRow({ event: e, onOpen, onToast }) {
  const cat = CATEGORIES[e.category] || CATEGORIES.musica;
  return (
    <div className="row" style={{ '--cat': cat.color }}>
      <div className="row-time">{e.time || 'all day'}</div>
      <div>
        <div className="row-name" onClick={() => onOpen(e)} style={{ cursor:'pointer' }}>
          {e.event_name}
        </div>
        <div className="row-loc">
          <span style={{ color: cat.color }}>● {cat.label}</span> · {e.venue}, {e.city}
        </div>
        <div className="row-actions">
          <GCalBtn event={e} label="GCal" small />
          <ShareBtn event={e} small onToast={onToast} />
          <IGBtn event={e} small />
        </div>
      </div>
    </div>
  );
}

// ── DateRangePill ─────────────────────────────────────────────────────────────
function DateRangePill({ from, to, setFrom, setTo }) {
  const active = !!(from || to);
  return (
    <span>
      <span className={`pill pill-quick daterange-lbl${active ? ' on' : ''}`} aria-pressed={active}>
        <span style={{ opacity:.7 }}>dal</span>
        <input type="date" className="daterange-inp" value={from} max={to || undefined}
               onChange={e => setFrom(e.target.value)} />
        <span style={{ opacity:.7 }}>al</span>
        <input type="date" className="daterange-inp" value={to} min={from || undefined}
               onChange={e => setTo(e.target.value)} />
      </span>
    </span>
  );
}

// ────────────────────────────────────────────────────────
//   APP SHELL
// ────────────────────────────────────────────────────────
function App() {
  const [tw, setTw]         = useTweaks(TWEAK_DEFAULTS);
  const [tab, setTab]       = useState('lista');
  const [filters, setFilters] = useState({ province:'', city:'', category:'', from:'', to:'' });
  const [allEvents, setAllEvents] = useState([]);
  const [provinces, setProvinces] = useState([...Object.keys(PROVINCE_COORDS)].sort());
  const [catKeys, setCatKeys]   = useState(() =>
    Object.keys(CATEGORIES).sort((a, b) =>
      CATEGORIES[a].label.localeCompare(CATEGORIES[b].label, 'it')
    )
  );
  const [openEvent, setOpenEvent] = useState(null);
  const [toast, setToast]   = useState('');
  const [loading, setLoading] = useState(true);

  // Load events: last month + all future, up to 500
  useEffect(() => {
    const past = new Date();
    past.setMonth(past.getMonth() - 1);
    const from = fmtISO(past);
    fetch(`/api/events?from=${from}&limit=500&include_past=1`)
      .then(r => r.json())
      .then(data => {
        setAllEvents((data.events || []).map(normalizeEvent));
        setLoading(false);
      })
      .catch(() => setLoading(false));
  }, []);

  // Load province list from API (sorted)
  useEffect(() => {
    fetch('/api/provinces')
      .then(r => r.json())
      .then(tree => {
        const flat = Object.values(tree).flat().sort();
        if (flat.length) setProvinces(flat);
      })
      .catch(() => {});
  }, []);

  // Load categories from API, poll every 30s for bot changes
  useEffect(() => {
    const fetchCats = () =>
      fetch('/api/categories').then(r => r.json()).then(cats => {
        // Sync window.CATEGORIES in-place BEFORE updating state so the option
        // labels (CATEGORIES[key].label) are always readable on re-render
        Object.keys(window.CATEGORIES).forEach(k => delete window.CATEGORIES[k]);
        Object.assign(window.CATEGORIES, cats);
        // Sort by displayed label, not by internal key
        const sorted = Object.keys(cats).sort((a, b) =>
          cats[a].label.localeCompare(cats[b].label, 'it')
        );
        setCatKeys(sorted);
      }).catch(() => {});
    fetchCats();
    const id = setInterval(fetchCats, 30000);
    return () => clearInterval(id);
  }, []);

  // Theme / density on root element
  useEffect(() => {
    document.documentElement.dataset.theme   = tw.dark    ? 'dark'  : 'light';
    document.documentElement.dataset.density = tw.density;
  }, [tw.dark, tw.density]);

  const showToast = useCallback((msg) => {
    setToast(msg);
    clearTimeout(showToast._t);
    showToast._t = setTimeout(() => setToast(''), 2100);
  }, []);

  const jumpToList = (prov) => {
    setFilters(f => ({ ...f, province: prov, city: '' }));
    setTab('lista');
  };

  const today    = parseISO(todayISO());
  const issueNum = Math.floor((new Date() - new Date('2026-01-01')) / (7 * 86400000)) + 1;

  return (
    <div className="app">
      <header className="masthead">
        <div className="masthead-top">
          <div className="masthead-top-l">
            <span className="label">Edizione N. {issueNum}</span>
            <span className="label">{weekdayShort(today)} {today.getDate()} {monthLong(today)} {today.getFullYear()}</span>
          </div>
          <div className="masthead-top-r">
            <span className="label">Aggiornato auto · ogni 6h</span>
            <span className="label" style={{ color:'var(--terracotta)' }}>● live</span>
          </div>
        </div>
        <div className="masthead-main">
          <div className="brand">
            <h1><span className="che">CHE</span> <em>Facemo</em></h1>
            <div className="brand-sub">eventi · Marche · dal vivo</div>
          </div>
          <nav className="tabs" role="tablist">
            {['lista','mappa','calendario'].map(name => (
              <button key={name} className="tab" role="tab"
                      aria-current={tab === name}
                      onClick={() => setTab(name)}>
                {name}
              </button>
            ))}
          </nav>
        </div>
      </header>

      <main className="main">
        {tab === 'lista' && (
          <ListView
            events={allEvents}
            filters={filters}
            setFilters={setFilters}
            onOpen={setOpenEvent}
            onToast={showToast}
            loading={loading}
            imageStyle={tw.imageStyle}
            provinces={provinces}
            catKeys={catKeys}
            issueNum={issueNum}
            todayDate={today}
          />
        )}
        {tab === 'mappa' && (
          <MapView
            events={allEvents}
            onOpen={setOpenEvent}
            onJumpToList={jumpToList}
            modalOpen={openEvent !== null}
          />
        )}
        {tab === 'calendario' && (
          <CalendarView
            events={allEvents}
            onOpen={setOpenEvent}
            onToast={showToast}
            provinces={provinces}
          />
        )}
      </main>

      <footer>
        <span>Dati da Instagram · aggiornato automaticamente</span>
        <span>
          Che Facemo © {today.getFullYear()} · fatto nelle Marche
          {' · '}
          <a href="/policy.html" target="_blank" rel="noopener" style={{ color:'inherit', opacity:.7 }}>Contenuti &amp; Uso</a>
        </span>
      </footer>

      {openEvent && (
        <Modal
          event={openEvent}
          onClose={() => setOpenEvent(null)}
          onToast={showToast}
          imageStyle={tw.imageStyle}
        />
      )}

      <Toast msg={toast} />

      <TweaksPanel title="Tweaks">
        <TweakSection label="Layout">
          <TweakRadio
            label="Densità"
            value={tw.density}
            onChange={v => setTw('density', v)}
            options={[
              { value:'compact',  label:'Compatta' },
              { value:'comfy',    label:'Comoda'   },
              { value:'spacious', label:'Ariosa'   },
            ]}
          />
          <TweakRadio
            label="Stile immagine"
            value={tw.imageStyle}
            onChange={v => setTw('imageStyle', v)}
            options={[
              { value:'gradient', label:'Gradiente' },
              { value:'striped',  label:'A righe'   },
              { value:'solid',    label:'Pieno'      },
            ]}
          />
        </TweakSection>
        <TweakSection label="Tema">
          <TweakToggle
            label="Modalità scura"
            value={tw.dark}
            onChange={v => setTw('dark', v)}
          />
        </TweakSection>
      </TweaksPanel>
    </div>
  );
}

ReactDOM.createRoot(document.getElementById('root')).render(<App />);
