#!/usr/bin/env python3
"""
Genera dashboard.html — 100% self-contained, nessuna dipendenza esterna.
Utilizzo: python3 export_dashboard.py
"""
import glob, json, os
from pathlib import Path
import pandas as pd

BASE = Path(__file__).parent

def load_data():
    files = sorted(glob.glob(str(BASE / "vendite_*.csv")))
    if not files:
        raise RuntimeError("Nessun CSV trovato.")
    dfs = []
    for f in files:
        df = pd.read_csv(f, encoding="utf-8-sig")
        if "Struttura" not in df.columns:
            nome = Path(f).stem.replace("vendite_","").rsplit("_",1)[0]
            df.insert(0,"Struttura",nome)
        dfs.append(df)
    df = pd.concat(dfs, ignore_index=True)
    df["Data Vendita"] = pd.to_datetime(df["Data Vendita"], errors="coerce")
    df["Quantità"] = pd.to_numeric(df["Quantità"], errors="coerce").fillna(0)
    df["Prezzo"]   = pd.to_numeric(df["Prezzo"],   errors="coerce").fillna(0)
    df["Anno"]     = df["Data Vendita"].dt.year.astype("Int64")
    df["Mese"]     = df["Data Vendita"].dt.month
    df["Giorno"]   = df["Data Vendita"].dt.day
    df["NomeMese"] = df["Data Vendita"].dt.strftime("%b")
    return df.dropna(subset=["Struttura","Fotografo"])

def build_payload(df):
    """Formato compresso: indici invece di stringhe ripetute → file ~5x più piccolo."""
    anni      = sorted(df["Anno"].dropna().unique().astype(int).tolist(), reverse=True)
    strutture = sorted(df["Struttura"].unique().tolist())
    fotografi = sorted(df["Fotografo"].unique().tolist())
    formati   = sorted(df["Formato"].dropna().unique().tolist())
    # Camera: nome cartella/set — "" per righe senza cartella
    df["_cam"] = df["Camera"].fillna("").astype(str).str.strip() if "Camera" in df.columns else ""
    cameras   = sorted(df["_cam"].unique().tolist())

    si  = {s: i for i, s in enumerate(strutture)}
    fi  = {f: i for i, f in enumerate(fotografi)}
    fmi = {f: i for i, f in enumerate(formati)}
    ci  = {c: i for i, c in enumerate(cameras)}

    records = []
    for _, r in df.iterrows():
        try:
            records.append([
                si[r["Struttura"]],
                fi[r["Fotografo"]],
                fmi.get(str(r["Formato"]) if pd.notna(r["Formato"]) else "", 0),
                int(r["Anno"]),
                int(r["Mese"]),
                int(r["Giorno"]),
                round(float(r["Quantità"]), 2),
                round(float(r["Prezzo"]), 2),
                ci.get(str(r["_cam"]), 0),   # [8] indice camera/cartella
            ])
        except Exception:
            pass

    return {"anni": anni, "strutture": strutture, "fotografi": fotografi,
            "formati": formati, "cameras": cameras, "records": records}

DASH_USER = os.getenv("DASH_USER", "amedeo")
DASH_PASS = os.getenv("DASH_PASS", "CreativaPro2025!")

LOGIN_OVERLAY = """
<div id="loginOverlay" style="position:fixed;inset:0;background:#0c0e18;display:flex;
align-items:center;justify-content:center;z-index:99999;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif">
  <div style="background:#1f1e1c;border-radius:16px;padding:40px 32px 36px;width:90%;max-width:340px;border:1px solid #383530;box-shadow:0 24px 64px rgba(0,0,0,.65),0 2px 16px rgba(124,106,247,.08)">
    <div style="display:flex;align-items:center;gap:10px;margin-bottom:10px">
      <div style="width:38px;height:38px;border-radius:10px;background:linear-gradient(135deg,#cc5a2a,#e07a52);display:flex;align-items:center;justify-content:center;flex-shrink:0;box-shadow:0 4px 12px rgba(124,106,247,.35)">
        <svg width="20" height="18" viewBox="0 0 20 18" fill="none"><path d="M19 15a1.5 1.5 0 01-1.5 1.5h-15A1.5 1.5 0 011 15V6a1.5 1.5 0 011.5-1.5H5.5L7 3h6l1.5 2.5H17A1.5 1.5 0 0119 7v8z" stroke="white" stroke-width="1.5" stroke-linejoin="round"/><circle cx="10" cy="10.5" r="2.8" stroke="white" stroke-width="1.5"/></svg>
      </div>
      <div>
        <div style="color:#fff;font-size:1.05rem;font-weight:700;letter-spacing:-.2px;line-height:1.1">PM Dashboard</div>
        <div style="color:#4a4f6a;font-size:.72rem;margin-top:2px">Creativapro</div>
      </div>
    </div>
    <p style="color:#4a4f6a;font-size:.8rem;margin:0 0 24px">Inserisci le credenziali per accedere</p>
    <div id="loginErr" style="color:#f87171;font-size:.8rem;margin-bottom:10px;display:none;background:rgba(248,113,113,.1);border-radius:6px;padding:8px 10px">Credenziali errate, riprova.</div>
    <form id="loginForm" onsubmit="doLogin(event)" autocomplete="on">
      <label style="display:block;color:#555;font-size:.65rem;text-transform:uppercase;letter-spacing:.5px;margin-bottom:4px">Utente</label>
      <input id="loginUser" name="username" type="text" autocomplete="username"
        style="width:100%;background:#1a1917;border:1px solid #383530;border-radius:8px;padding:10px 12px;color:#e0e0e0;font-size:.9rem;margin-bottom:14px;outline:none;box-sizing:border-box;transition:border-color .15s"
        onfocus="this.style.borderColor='#cc5a2a'" onblur="this.style.borderColor='#383530'"/>
      <label style="display:block;color:#555;font-size:.65rem;text-transform:uppercase;letter-spacing:.5px;margin-bottom:4px">Password</label>
      <input id="loginPass" name="password" type="password" autocomplete="current-password"
        style="width:100%;background:#1a1917;border:1px solid #383530;border-radius:8px;padding:10px 12px;color:#e0e0e0;font-size:.9rem;margin-bottom:20px;outline:none;box-sizing:border-box;transition:border-color .15s"
        onfocus="this.style.borderColor='#cc5a2a'" onblur="this.style.borderColor='#383530'"/>
      <button type="submit" style="width:100%;background:linear-gradient(135deg,#cc5a2a,#e07a52);color:#fff;border:none;border-radius:8px;padding:12px;font-size:.95rem;font-weight:600;cursor:pointer;letter-spacing:.2px;box-shadow:0 4px 14px rgba(124,106,247,.4)">Accedi →</button>
    </form>
  </div>
</div>
<div id="logoutBtn" style="display:none;position:fixed;top:12px;right:14px;z-index:9999">
  <button onclick="doLogout()" style="background:#1f1e1c;color:#555;border:1px solid #383530;border-radius:20px;padding:6px 14px;font-size:.75rem;cursor:pointer;font-family:-apple-system,sans-serif">Esci</button>
</div>
<!-- Campanellino alert sicurezza -->
<div id="bellWrap" style="display:none;position:fixed;top:12px;right:80px;z-index:9999">
  <button id="bellBtn" onclick="toggleAlertPanel()" title="Alert di sicurezza"
    style="background:#1f1e1c;color:#f87171;border:1px solid #f87171;border-radius:20px;
           padding:6px 12px;font-size:.82rem;cursor:pointer;font-family:-apple-system,sans-serif;
           display:flex;align-items:center;gap:5px">
    🔔<span id="bellCount" style="background:#f87171;color:#fff;border-radius:10px;
        padding:1px 6px;font-size:.68rem;font-weight:700">0</span>
  </button>
</div>
<!-- Pannello alert slide-in da destra -->
<div id="alertPanel" style="display:none;position:fixed;top:0;right:0;width:380px;max-width:100vw;
     height:100vh;background:#1a1917;border-left:1px solid #383530;z-index:99998;
     overflow-y:auto;box-shadow:-8px 0 32px rgba(0,0,0,.65);font-family:-apple-system,sans-serif">
  <div style="padding:16px 20px;border-bottom:1px solid #383530;display:flex;
       justify-content:space-between;align-items:center;position:sticky;top:0;background:#1a1917;z-index:1">
    <div style="font-weight:700;color:#fff;font-size:.95rem">🔔 Alert di Sicurezza</div>
    <div style="display:flex;gap:6px;align-items:center;flex-wrap:wrap;justify-content:flex-end">
      <button onclick="segnaTestiLetti()"
        style="background:#2a2926;color:#888;border:1px solid #383530;border-radius:6px;
               padding:5px 10px;font-size:.72rem;cursor:pointer">✓ Tutti letti</button>
      <button onclick="esportaAlerts()"
        style="background:#2a2926;color:#cc5a2a;border:1px solid #383530;border-radius:6px;
               padding:5px 10px;font-size:.72rem;cursor:pointer">⬇ Esporta CSV</button>
      <button onclick="pulisciAlerts()"
        style="background:#2a2926;color:#f87171;border:1px solid #3a1a1a;border-radius:6px;
               padding:5px 10px;font-size:.72rem;cursor:pointer">🗑 Pulisci log</button>
      <button onclick="toggleAlertPanel()"
        style="background:none;border:none;color:#666;font-size:1.3rem;cursor:pointer;
               padding:2px 8px;line-height:1">✕</button>
    </div>
  </div>
  <div id="alertPanelBody" style="padding:12px 16px"></div>
</div>
<div id="alertBackdrop" onclick="toggleAlertPanel()"
     style="display:none;position:fixed;inset:0;z-index:99997;background:rgba(0,0,0,.45)"></div>
<script>
const _U="__USER__",_P="__PASS__";
function doLogin(e){
  e.preventDefault();
  const u=document.getElementById('loginUser').value;
  const p=document.getElementById('loginPass').value;
  if(u===_U && p===_P){
    sessionStorage.setItem('pm_auth','1');
    document.getElementById('loginOverlay').style.display='none';
    document.getElementById('logoutBtn').style.display='block';
    fetch('/log-access',{method:'POST',headers:{'Content-Type':'application/json'},
      body:JSON.stringify({username:u,nome:'Admin'})}).catch(()=>{});
    if(typeof checkPresenzeAlert==='function') checkPresenzeAlert();
    if(typeof aggiornaAlerts==='function') aggiornaAlerts();
    if(window.PasswordCredential){
      navigator.credentials.store(new PasswordCredential({id:u,password:p,name:'PM Dashboard'}));
    }
  } else {
    document.getElementById('loginErr').style.display='block';
  }
}
function doLogout(){
  sessionStorage.removeItem('pm_auth');
  location.reload();
}
if(sessionStorage.getItem('pm_auth')==='1'){
  document.getElementById('loginOverlay').style.display='none';
  document.getElementById('logoutBtn').style.display='block';
}
</script>
"""

LOGIN_OVERLAY_UTENTE = """
<div id="loginOverlay" style="position:fixed;inset:0;background:#0c0e18;display:flex;
align-items:center;justify-content:center;z-index:99999;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif">
  <div style="background:#1f1e1c;border-radius:16px;padding:40px 32px 36px;width:90%;max-width:340px;border:1px solid #383530;box-shadow:0 24px 64px rgba(0,0,0,.65),0 2px 16px rgba(124,106,247,.08)">
    <div style="display:flex;align-items:center;gap:10px;margin-bottom:10px">
      <div style="width:38px;height:38px;border-radius:10px;background:linear-gradient(135deg,#cc5a2a,#e07a52);display:flex;align-items:center;justify-content:center;flex-shrink:0;box-shadow:0 4px 12px rgba(124,106,247,.35)">
        <svg width="20" height="18" viewBox="0 0 20 18" fill="none"><path d="M19 15a1.5 1.5 0 01-1.5 1.5h-15A1.5 1.5 0 011 15V6a1.5 1.5 0 011.5-1.5H5.5L7 3h6l1.5 2.5H17A1.5 1.5 0 0119 7v8z" stroke="white" stroke-width="1.5" stroke-linejoin="round"/><circle cx="10" cy="10.5" r="2.8" stroke="white" stroke-width="1.5"/></svg>
      </div>
      <div>
        <div style="color:#fff;font-size:1.05rem;font-weight:700;letter-spacing:-.2px;line-height:1.1">PM Dashboard</div>
        <div style="color:#cc5a2a;font-size:.78rem;font-weight:500;margin-top:3px">Ciao, __NOME__!</div>
      </div>
    </div>
    <p style="color:#4a4f6a;font-size:.8rem;margin:0 0 24px">Inserisci la tua password per accedere</p>
    <div id="loginErr" style="color:#f87171;font-size:.8rem;margin-bottom:10px;display:none;background:rgba(248,113,113,.1);border-radius:6px;padding:8px 10px">Password errata, riprova.</div>
    <form id="loginForm" onsubmit="doLogin(event)" autocomplete="on">
      <label style="display:block;color:#555;font-size:.65rem;text-transform:uppercase;letter-spacing:.5px;margin-bottom:4px">Password</label>
      <input id="loginPass" name="password" type="password" autocomplete="current-password"
        style="width:100%;background:#1a1917;border:1px solid #383530;border-radius:8px;padding:10px 12px;
        color:#e0e0e0;font-size:.9rem;margin-bottom:20px;outline:none;box-sizing:border-box;transition:border-color .15s"
        onfocus="this.style.borderColor='#cc5a2a'" onblur="this.style.borderColor='#383530'"/>
      <button type="submit" style="width:100%;background:linear-gradient(135deg,#cc5a2a,#e07a52);color:#fff;border:none;border-radius:8px;
        padding:12px;font-size:.95rem;font-weight:600;cursor:pointer;letter-spacing:.2px;box-shadow:0 4px 14px rgba(124,106,247,.4)">Accedi →</button>
    </form>
  </div>
</div>
<div id="logoutBtn" style="display:none;position:fixed;top:12px;right:14px;z-index:9999">
  <button onclick="doLogout()" style="background:#1f1e1c;color:#555;border:1px solid #383530;
    border-radius:20px;padding:6px 14px;font-size:.75rem;cursor:pointer;font-family:-apple-system,sans-serif">Esci</button>
</div>
<script>
const _U="__USER__",_P="__PASS__",_NOME="__NOME__";
function doLogin(e){
  e.preventDefault();
  const p=document.getElementById('loginPass').value;
  if(p===_P){
    sessionStorage.setItem('pm_user_auth','1');
    document.getElementById('loginOverlay').style.display='none';
    document.getElementById('logoutBtn').style.display='block';
    fetch('/log-access',{method:'POST',headers:{'Content-Type':'application/json'},
      body:JSON.stringify({username:_U,nome:_NOME})}).catch(()=>{});
    if(typeof checkPresenzeAlert==='function') checkPresenzeAlert();
    if(typeof aggiornaAlertsU==='function') aggiornaAlertsU();
  } else {
    document.getElementById('loginErr').style.display='block';
  }
}
function doLogout(){
  sessionStorage.removeItem('pm_user_auth');
  location.reload();
}
if(sessionStorage.getItem('pm_user_auth')==='1'){
  document.getElementById('loginOverlay').style.display='none';
  document.getElementById('logoutBtn').style.display='block';
}
</script>
"""

def main():
    print("Caricamento dati...")
    df = load_data()
    payload = build_payload(df)
    print(f"  {len(payload['records'])} record · {payload['strutture']}")

    # Carica config stampanti, reset kit, costi e spese extra
    printers_file   = BASE / "printers.json"
    resets_file     = BASE / "kit_resets.json"
    costs_file      = BASE / "costs.json"
    expenses_file   = BASE / "expenses.json"
    presences_file  = BASE / "presences.json"
    users_file      = BASE / "users.json"
    access_log_file = BASE / "access_log.json"
    spectre_file    = BASE / "spectre_data.json"
    printers_data   = json.loads(printers_file.read_text(encoding="utf-8"))   if printers_file.exists()   else {"stampanti": []}
    resets_data     = json.loads(resets_file.read_text(encoding="utf-8"))     if resets_file.exists()     else {"resets": {}}
    costs_data      = json.loads(costs_file.read_text(encoding="utf-8"))      if costs_file.exists()      else {"fotografi": {}, "strutture": {}}
    expenses_data   = json.loads(expenses_file.read_text(encoding="utf-8"))   if expenses_file.exists()   else {"spese": []}
    presences_data  = json.loads(presences_file.read_text(encoding="utf-8"))  if presences_file.exists()  else {"presenze": []}
    users_data      = json.loads(users_file.read_text(encoding="utf-8"))      if users_file.exists()      else {"users": []}
    access_log_data = json.loads(access_log_file.read_text(encoding="utf-8")) if access_log_file.exists() else {"accessi": []}
    spectre_data    = json.loads(spectre_file.read_text(encoding="utf-8"))    if spectre_file.exists()    else {"postazioni": {}}

    # ── Dashboard admin (completa) ───────────────────────────────────────────
    overlay = LOGIN_OVERLAY.replace("__USER__", DASH_USER).replace("__PASS__", DASH_PASS)
    html = HTML.replace("__DATA__",       json.dumps(payload,          ensure_ascii=False))
    html = html.replace("__PRINTERS__",   json.dumps(printers_data,    ensure_ascii=False))
    html = html.replace("__RESETS__",     json.dumps(resets_data,       ensure_ascii=False))
    html = html.replace("__COSTS__",      json.dumps(costs_data,        ensure_ascii=False))
    html = html.replace("__EXPENSES__",   json.dumps(expenses_data,     ensure_ascii=False))
    html = html.replace("__PRESENCES__",  json.dumps(presences_data,    ensure_ascii=False))
    html = html.replace("__USERS__",      json.dumps(users_data,        ensure_ascii=False))
    html = html.replace("__ACCESS_LOG__", json.dumps(access_log_data,   ensure_ascii=False))
    html = html.replace("__SPECTRE__",    json.dumps(spectre_data,       ensure_ascii=False))
    html = html.replace("<body>", "<body>" + overlay, 1)
    out = BASE / "dashboard.html"
    out.write_text(html, encoding="utf-8")
    size_kb = out.stat().st_size // 1024
    print(f"✓ {out} ({size_kb} KB — nessuna dipendenza esterna)")

    # ── Dashboard per ogni utente (vista limitata) ───────────────────────────
    for user in users_data.get("users", []):
        uname    = user.get("username","")
        upass    = user.get("password","")
        unome    = user.get("nome", uname)
        strutture_utente = user.get("strutture", [])
        if not uname or not strutture_utente:
            continue
        # Filtra payload solo per le strutture dell'utente
        str_idx  = [payload["strutture"].index(s) for s in strutture_utente if s in payload["strutture"]]
        foto_nel_periodo = set()
        rec_filtrati = []
        for r in payload["records"]:
            if r[0] in str_idx:
                rec_filtrati.append(r)
                foto_nel_periodo.add(r[1])
        payload_u = {
            "anni":     payload["anni"],
            "strutture": [payload["strutture"][i] for i in str_idx],
            "fotografi": [payload["fotografi"][i] for i in sorted(foto_nel_periodo)],
            "formati":   payload["formati"],
            "records":   [[str_idx.index(r[0]), sorted(foto_nel_periodo).index(r[1]),
                           r[2], r[3], r[4], r[5], r[6], r[7]]
                          for r in rec_filtrati],
        }
        u_overlay = LOGIN_OVERLAY_UTENTE \
            .replace("__USER__", uname) \
            .replace("__PASS__", upass) \
            .replace("__NOME__", unome)
        default_perms = {"strutture":True,"fotografi":True,"obiettivi":True,
                         "consumabili":False,"contabilita":False,"presenze":True,
                         "input_presenze":True,"edit_spese":False,"alerts":False,"agenda":False}
        user_perms = {**default_perms, **user.get("perms", {})}
        html_u = HTML_UTENTE \
            .replace("__DATA__",      json.dumps(payload_u,      ensure_ascii=False)) \
            .replace("__PRESENCES__", json.dumps(presences_data, ensure_ascii=False)) \
            .replace("__EXPENSES__",  json.dumps(expenses_data,  ensure_ascii=False)) \
            .replace("__USERNAME__",  uname) \
            .replace("__MYPASS__",    upass) \
            .replace("__NOME__",      unome) \
            .replace("__PERMS__",     json.dumps(user_perms,     ensure_ascii=False))
        html_u = html_u.replace("<body>", "<body>" + u_overlay, 1)
        out_u = BASE / f"dashboard_{uname}.html"
        out_u.write_text(html_u, encoding="utf-8")
        print(f"✓ dashboard_{uname}.html ({out_u.stat().st_size//1024} KB)")

HTML = r"""<!DOCTYPE html>
<html lang="it">
<head>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width,initial-scale=1"/>
<title>PM Dashboard</title>
<style>
*{box-sizing:border-box;margin:0;padding:0}
body{font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;background:#1a1917;color:#e0e0e0;min-height:100vh}
.app{max-width:960px;margin:0 auto;padding:14px 14px 50px}

h2{font-size:.85rem;font-weight:600;color:#888;margin:18px 0 8px;text-transform:uppercase;letter-spacing:.6px}

.header{margin-bottom:10px}
.header h1{font-size:1.45rem;font-weight:700;color:#fff;display:flex;align-items:center;gap:8px}
.badge{display:inline-block;background:#242220;color:#666;font-size:.75rem;padding:4px 10px;border-radius:20px;margin-top:5px}

/* Filtri */
.filters{display:flex;flex-wrap:wrap;gap:10px;background:#242220;padding:12px 14px;border-radius:12px;margin:10px 0}
.fg{display:flex;flex-direction:column;gap:4px;flex:1;min-width:130px}
.fg label{font-size:.68rem;color:#666;text-transform:uppercase;letter-spacing:.5px}
select{background:#2a2926;color:#e0e0e0;border:1px solid #383530;border-radius:8px;
  padding:10px 10px;font-size:.92rem;width:100%;outline:none;-webkit-appearance:none;
  min-height:44px}

/* KPI */
.kpi{display:grid;grid-template-columns:1fr 1fr;gap:10px;margin:10px 0}
@media(min-width:540px){.kpi{grid-template-columns:repeat(4,1fr)}}
.kcard{background:#242220;border-radius:12px;padding:14px 16px;border-left:3px solid #cc5a2a;box-shadow:0 2px 10px rgba(0,0,0,.35)}
.kcard .lbl{font-size:.68rem;color:#555;text-transform:uppercase;letter-spacing:.4px}
.kcard .val{font-size:1.4rem;font-weight:700;color:#fff;margin-top:4px;line-height:1}
.kcard .sub{font-size:.7rem;color:#444;margin-top:4px}

/* Tabs */
.tabs{display:flex;flex-wrap:wrap;border-bottom:1px solid #1b1d2f;margin:16px 0 0;gap:2px 0}
.tab{padding:10px 14px;font-size:.85rem;font-weight:500;white-space:nowrap;cursor:pointer;
  color:#4a4f6a;background:none;border:none;border-bottom:2px solid transparent;transition:.2s;
  min-height:44px}
.tab:hover{color:#aaa}
.tab.on{color:#fff;border-bottom-color:#cc5a2a}
.fpreset{background:#2a2926;color:#888;border:1px solid #383530;border-radius:6px;padding:6px 10px;font-size:.78rem;cursor:pointer;white-space:nowrap;transition:.15s}
.fpreset:hover{color:#bbb;border-color:#3a3d50}

/* Mobile overrides */
@media(max-width:480px){
  .header h1{font-size:1.25rem}
  .fg{min-width:calc(50% - 5px)}
  select{font-size:.95rem;padding:11px 10px;min-height:46px}
  .kcard .val{font-size:1.25rem}
  .tab{padding:11px 14px;font-size:.85rem}
}
.pane{display:none;padding:12px 0}
.pane.on{display:block}

/* Landing Editor */
.led-section{background:#242220;border-radius:10px;margin-bottom:10px;overflow:hidden;border:1px solid #2a2926}
.led-head{padding:12px 16px;font-size:.88rem;font-weight:600;color:#c8b8ff;cursor:pointer;display:flex;justify-content:space-between;align-items:center;user-select:none;transition:.15s}
.led-head:hover{background:#1a1e30}
.led-body{padding:14px 16px;border-top:1px solid #2a2926;display:none}
.led-body.open{display:block}
.led-row{margin-bottom:10px}
.led-row label{display:block;font-size:.72rem;color:#888;margin-bottom:4px;text-transform:uppercase;letter-spacing:.4px}
.led-row input,.led-row textarea{width:100%;background:#1a1917;color:#e0e0e0;border:1px solid #383530;border-radius:6px;padding:7px 10px;font-size:.83rem;outline:none;resize:vertical;font-family:inherit}
.led-row input:focus,.led-row textarea:focus{border-color:#cc5a2a}
.led-lang-tabs{display:flex;gap:6px;margin-bottom:12px;flex-wrap:wrap}
.led-ltab{background:#2a2926;color:#888;border:1px solid #383530;border-radius:20px;padding:4px 12px;font-size:.75rem;cursor:pointer;transition:.15s}
.led-ltab.active{background:#cc5a2a;border-color:#cc5a2a;color:#fff}

/* Box generico */
.box{background:#242220;border-radius:10px;padding:14px;margin-bottom:12px;box-shadow:0 2px 8px rgba(0,0,0,.3)}

/* Grid 2 colonne */
.g2{display:grid;grid-template-columns:1fr;gap:12px}
@media(min-width:600px){.g2{grid-template-columns:1fr 1fr}}

/* SVG chart container */
.chart-wrap{width:100%;overflow:hidden}
svg.chart{width:100%;display:block}

/* Rank list */
.rlist{display:flex;flex-direction:column;gap:7px}
.ritem{background:#242220;border-radius:8px;padding:10px 12px}
.rrow{display:flex;justify-content:space-between;align-items:center;margin-bottom:5px}
.rname{font-size:.85rem;font-weight:600;color:#fff}
.rval{font-size:.85rem;font-weight:700;color:#cc5a2a}
.bar-bg{height:4px;background:#2a2926;border-radius:2px;overflow:hidden}
.bar-fg{height:4px;border-radius:2px}
.rsub{font-size:.65rem;color:#444;margin-top:4px}

/* Struttura cards */
.scards{display:grid;grid-template-columns:1fr;gap:10px}
@media(min-width:460px){.scards{grid-template-columns:repeat(auto-fit,minmax(190px,1fr))}}
.scard{background:#242220;border-radius:10px;padding:14px;border-top:3px solid #cc5a2a}
.sname{font-size:.95rem;font-weight:700;color:#fff;margin-bottom:10px}
.sgrid{display:grid;grid-template-columns:1fr 1fr;gap:6px}
.sstat{background:#2a2926;border-radius:6px;padding:8px}
.sstat .sl{font-size:.6rem;color:#444;text-transform:uppercase}
.sstat .sv{font-size:.88rem;font-weight:600;color:#e0e0e0;margin-top:2px}
.stop{font-size:.7rem;color:#666;margin-top:8px}

/* Obiettivi */
.gcards{display:grid;grid-template-columns:1fr;gap:10px}
@media(min-width:460px){.gcards{grid-template-columns:repeat(auto-fit,minmax(190px,1fr))}}
.gcard{background:#242220;border-radius:10px;padding:12px}
.grow{display:flex;justify-content:space-between;align-items:center;margin-bottom:5px}
.gname{font-size:.85rem;font-weight:600}
.gpct{font-size:.85rem;font-weight:700}
.gbar-bg{height:6px;background:#2a2926;border-radius:3px;overflow:hidden;margin:4px 0}
.gbar{height:6px;border-radius:3px;transition:width .4s}
.gfoot{display:flex;justify-content:space-between;font-size:.65rem;color:#444}
.gfoot input{background:transparent;border:none;border-bottom:1px solid #383530;
  color:#888;width:72px;text-align:right;font-size:.65rem;outline:none}
.green{color:#4ade80}.yellow{color:#facc15}.red{color:#f87171}

.footer{text-align:center;font-size:.65rem;color:#383530;margin-top:20px;padding-top:10px;border-top:1px solid #242220}
</style>
</head>
<body>
<!-- POPUP PRESENZE MANCANTI -->
<div id="presenzeModal" style="display:none;position:fixed;inset:0;background:rgba(0,0,0,.7);z-index:9999;align-items:center;justify-content:center">
  <div style="background:#161827;border:1.5px solid #f87171;border-radius:16px;padding:28px 28px 22px;max-width:420px;width:90%;box-shadow:0 8px 40px #000a">
    <div style="display:flex;align-items:center;gap:10px;margin-bottom:14px">
      <span style="font-size:1.6rem">⚠️</span>
      <span style="color:#f87171;font-size:1rem;font-weight:700">Presenze non inserite</span>
    </div>
    <p id="presenzeModalMsg" style="color:#ccc;font-size:.87rem;line-height:1.6;margin:0 0 20px"></p>
    <div style="display:flex;gap:10px">
      <button onclick="chiudiModalPresenze()" style="flex:1;background:#2a2926;color:#aaa;border:1px solid #383530;border-radius:8px;padding:11px;font-size:.88rem;cursor:pointer">Ricordamelo dopo</button>
      <button onclick="vaiAPresenze()" style="flex:1;background:#38bdf8;color:#1a1917;border:none;border-radius:8px;padding:11px;font-size:.88rem;font-weight:700;cursor:pointer">👥 Vai alle Presenze</button>
    </div>
  </div>
</div>
<div class="app">
  <div class="header">
    <h1 style="display:flex;align-items:center;gap:8px"><svg width="22" height="20" viewBox="0 0 22 20" fill="none" style="flex-shrink:0"><path d="M21 16a2 2 0 01-2 2H3a2 2 0 01-2-2V7a2 2 0 012-2h3.7L8 2.5h6l1.3 2.5H20a2 2 0 012 2v9z" stroke="#cc5a2a" stroke-width="1.6" stroke-linejoin="round"/><circle cx="11" cy="11" r="3" stroke="#cc5a2a" stroke-width="1.6"/></svg>PM Dashboard</h1>
    <div class="badge" id="badge">—</div>
  </div>

  <!-- RICERCA RAPIDA -->
  <div style="margin:0 0 10px;position:relative">
    <div style="display:flex;gap:8px;align-items:center;background:#242220;
      border-radius:12px;padding:10px 14px;border:1px solid #383530" id="searchWrap">
      <span style="font-size:1.1rem">🔍</span>
      <input type="text" id="searchQ" placeholder='Chiedi qualcosa… es. "quanto ha incassato Daniele questa settimana"'
        autocomplete="off"
        style="flex:1;background:none;border:none;outline:none;color:#e0e0e0;
        font-size:.88rem;min-width:0"
        oninput="searchLive(this.value)" onkeydown="if(event.key==='Enter')doSearch()"/>
      <button onclick="doSearch()" style="background:#cc5a2a;color:#fff;border:none;border-radius:8px;
        padding:7px 14px;font-size:.82rem;font-weight:600;cursor:pointer;white-space:nowrap;min-height:36px">
        Cerca
      </button>
      <button onclick="clearSearch()" title="Cancella"
        style="background:none;border:none;color:#444;font-size:1rem;cursor:pointer;padding:4px">✕</button>
    </div>
    <!-- Suggerimenti -->
    <div id="searchSuggest" style="display:none;position:absolute;top:100%;left:0;right:0;
      background:#242220;border:1px solid #383530;border-radius:10px;margin-top:4px;
      z-index:1000;max-height:200px;overflow-y:auto;box-shadow:0 8px 24px #00000066"></div>
    <!-- Risultato -->
    <div id="searchResult" style="display:none;margin-top:8px;background:#242220;
      border-radius:12px;padding:14px 16px;border-left:4px solid #cc5a2a"></div>
  </div>

  <div class="filters" style="flex-direction:column;gap:8px">
    <div style="display:flex;flex-wrap:wrap;gap:6px;align-items:center">
      <button class="fpreset" data-key="oggi"      onclick="setPreset('oggi')">Oggi</button>
      <button class="fpreset" data-key="ieri"      onclick="setPreset('ieri')">Ieri</button>
      <button class="fpreset" data-key="sett_cur"  onclick="setPreset('sett_cur')">Settimana corrente</button>
      <button class="fpreset" data-key="sett_prec" onclick="setPreset('sett_prec')">Ultima settimana</button>
      <button class="fpreset" data-key="mese_cur"  onclick="setPreset('mese_cur')">Mese corrente</button>
      <button class="fpreset" data-key="mese_prec" onclick="setPreset('mese_prec')">Ultimo mese</button>
      <button class="fpreset" data-key="3mesi"     onclick="setPreset('3mesi')">Ultimi 3 mesi</button>
      <button class="fpreset" data-key="anno_cur"  onclick="setPreset('anno_cur')">Anno corrente</button>
      <button class="fpreset" data-key="anno_prec" onclick="setPreset('anno_prec')">Ultimo anno</button>
      <button class="fpreset" data-key="tutto"     onclick="setPreset('tutto')">Tutto</button>
    </div>
    <div style="display:flex;flex-wrap:wrap;gap:8px;align-items:center">
      <div style="display:flex;align-items:center;gap:4px">
        <button onclick="navWeek(-1)" style="background:#2a2926;color:#aaa;border:1px solid #383530;border-radius:6px;padding:7px 10px;cursor:pointer;font-size:.9rem">&#9664;</button>
        <span id="weekLabel" style="font-size:.8rem;color:#aaa;padding:0 6px;white-space:nowrap;min-width:120px;text-align:center"></span>
        <button onclick="navWeek(1)" style="background:#2a2926;color:#aaa;border:1px solid #383530;border-radius:6px;padding:7px 10px;cursor:pointer;font-size:.9rem">&#9654;</button>
      </div>
      <div style="display:flex;align-items:center;gap:4px;flex-wrap:wrap">
        <input type="date" id="fDa" style="background:#2a2926;color:#e0e0e0;border:1px solid #383530;border-radius:8px;padding:7px 8px;font-size:.85rem;outline:none"/>
        <span style="color:#555">–</span>
        <input type="date" id="fA"  style="background:#2a2926;color:#e0e0e0;border:1px solid #383530;border-radius:8px;padding:7px 8px;font-size:.85rem;outline:none"/>
        <button onclick="applyCustomRange()" style="background:#cc5a2a;color:#fff;border:none;border-radius:8px;padding:7px 12px;font-size:.85rem;cursor:pointer">Applica</button>
      </div>
      <div class="fg" style="flex:1;min-width:140px"><label>🏖️ Struttura</label><select id="fStruttura"><option value="">Tutte</option></select></div>
      <div class="fg" style="flex:1;min-width:120px"><label>👤 Fotografo</label><select id="fFotografo"><option value="">Tutti</option></select></div>
    </div>
    <span id="filterInfo" style="font-size:.72rem;color:#555"></span>
  </div>

  <div class="kpi">
    <div class="kcard" style="border-color:#cc5a2a">
      <div class="lbl">💰 Incasso</div>
      <div class="val" id="kInc">—</div>
      <div class="sub" id="kTrans">—</div>
    </div>
    <div class="kcard" style="border-color:#e07a52">
      <div class="lbl">🖼️ Foto vendute</div>
      <div class="val" id="kQty">—</div>
      <div class="sub">unità totali</div>
    </div>
    <div class="kcard" style="border-color:#34d399">
      <div class="lbl">👤 Fotografi</div>
      <div class="val" id="kFoto">—</div>
      <div class="sub">attivi</div>
    </div>
    <div class="kcard" style="border-color:#f59e0b">
      <div class="lbl">🏖️ Strutture</div>
      <div class="val" id="kStr">—</div>
      <div class="sub">location</div>
    </div>
  </div>

  <div class="tabs">
    <button class="tab on" onclick="showTab(0)">🌐 Riepilogo</button>
    <button class="tab" onclick="showTab(1)">🏖️ Strutture</button>
    <button class="tab" onclick="showTab(2)">👤 Fotografi</button>
    <button class="tab" onclick="showTab(3)">🎯 Obiettivi</button>
    <button class="tab" onclick="showTab(4)">🖨️ Consumabili</button>
    <button class="tab" onclick="showTab(5)">💼 Contabilità</button>
    <button class="tab" onclick="showTab(6)">👥 Utenti</button>
    <button class="tab" onclick="showTab(7)">📷 Spectre</button>
  </div>

  <!-- TAB 0 -->
  <div class="pane on" id="pane0">
    <h2>💰 Incasso per struttura</h2>
    <div class="box chart-wrap" id="cStr"></div>
    <div class="g2">
      <div>
        <h2>📦 Formati top 8</h2>
        <div class="box chart-wrap" id="cFmt"></div>
      </div>
      <div>
        <h2>📈 Trend mensile</h2>
        <div class="box chart-wrap" id="cTrend"></div>
      </div>
    </div>
  </div>

  <!-- TAB 1 -->
  <div class="pane" id="pane1">
    <h2>🏖️ Dettaglio strutture</h2>
    <div class="scards" id="sCards"></div>
  </div>

  <!-- TAB 2 -->
  <div class="pane" id="pane2">
    <div class="g2">
      <div>
        <h2>🏆 Classifica incasso</h2>
        <div class="rlist" id="rankList"></div>
      </div>
      <div>
        <h2>📈 Top 5 trend mensile</h2>
        <div class="box chart-wrap" id="cFotoTrend"></div>
      </div>
    </div>
  </div>

  <!-- TAB 3 -->
  <div class="pane" id="pane3">
    <h2>🎯 Obiettivi <span style="font-size:.65rem;color:#444;font-weight:400">(modifica i target)</span></h2>
    <div class="gcards" id="goalCards"></div>
    <h2 style="margin-top:16px">📊 Incasso vs Target</h2>
    <div class="box chart-wrap" id="cGoal"></div>
  </div>

  <!-- TAB 4 — CONSUMABILI -->
  <div class="pane" id="pane4">

    <!-- KIT COUNTERS -->
    <h2>🖨️ Stato kit stampanti</h2>
    <div id="kitCards" style="display:flex;flex-direction:column;gap:10px;margin-bottom:16px"></div>

    <!-- RIEPILOGO STAMPE -->
    <div class="kpi" style="grid-template-columns:1fr 1fr">
      <div class="kcard" style="border-color:#38bdf8">
        <div class="lbl">🖨️ Stampe totali</div>
        <div class="val" id="cTotStampe">—</div>
        <div class="sub">unità nel periodo</div>
      </div>
      <div class="kcard" style="border-color:#e07a52">
        <div class="lbl">📦 Formati usati</div>
        <div class="val" id="cTotFormati">—</div>
        <div class="sub">tipologie diverse</div>
      </div>
    </div>

    <h2>🖨️ Stampe per formato</h2>
    <div class="box chart-wrap" id="cConsFmt"></div>

    <h2 style="margin-top:16px">📋 Dettaglio per formato</h2>
    <div class="box" id="consTable"></div>

    <h2 style="margin-top:16px">🏖️ Stampe per struttura</h2>
    <div class="box chart-wrap" id="cConsStr"></div>
  </div>

  <!-- TAB 5 — CONTABILITÀ -->
  <div class="pane" id="pane5">

    <!-- ALERTS -->
    <div id="contAlerts" style="margin-bottom:12px"></div>

    <!-- KPI P&L -->
    <div class="kpi" style="grid-template-columns:repeat(2,1fr)">
      <div class="kcard" style="border-color:#34d399">
        <div class="lbl">💰 Fatturato</div>
        <div class="val" id="plFatturato">—</div>
        <div class="sub">periodo selezionato</div>
      </div>
      <div class="kcard" style="border-color:#f87171">
        <div class="lbl">💸 Costi Totali</div>
        <div class="val" id="plCosti">—</div>
        <div class="sub">stipendi + canoni + extra</div>
      </div>
      <div class="kcard" style="border-color:#cc5a2a" id="plUtileCard">
        <div class="lbl">📈 Utile / Perdita</div>
        <div class="val" id="plUtile">—</div>
        <div class="sub" id="plMargine">—</div>
      </div>
      <div class="kcard" style="border-color:#f59e0b">
        <div class="lbl">🎯 Break-even giorno</div>
        <div class="val" id="plBreakeven">—</div>
        <div class="sub">da vendere ogni giorno</div>
      </div>
    </div>

    <!-- P&L PER STRUTTURA -->
    <h2 style="margin-top:16px">🏖️ P&L per struttura</h2>
    <div class="box" id="plStrTable"></div>

    <!-- PRESENZE & CONVERSIONE -->
    <h2 style="margin-top:16px">👥 Presenze & Conversione</h2>
    <div class="box" style="margin-bottom:4px">
      <div style="display:grid;grid-template-columns:1fr 1fr;gap:8px;margin-bottom:10px" id="presForm">
        <div>
          <label style="font-size:.65rem;color:#555;text-transform:uppercase;letter-spacing:.4px">Settimana (lunedì)</label>
          <input type="date" id="prLun" style="width:100%;background:#2a2926;border:1px solid #383530;
            border-radius:8px;padding:9px 10px;color:#e0e0e0;font-size:.88rem;outline:none;margin-top:3px;min-height:42px"
            onchange="aggiornaLabelSettimana()"/>
        </div>
        <div style="display:flex;align-items:flex-end">
          <div id="prSettimanaLabel" style="font-size:.78rem;color:#888;padding-bottom:10px"></div>
        </div>
        <div style="grid-column:1/-1">
          <label style="font-size:.65rem;color:#555;text-transform:uppercase;letter-spacing:.4px">Ospiti per struttura</label>
          <div id="prStruttureInputs" style="display:grid;grid-template-columns:1fr 1fr;gap:6px;margin-top:6px"></div>
        </div>
      </div>
      <button onclick="savePresenza()"
        style="width:100%;background:#38bdf8;color:#1a1917;border:none;border-radius:8px;
        padding:12px;font-size:.92rem;font-weight:700;cursor:pointer;min-height:46px">
        💾 Salva presenze settimana
      </button>
    </div>
    <div class="box" id="presenzeTable"></div>

    <!-- PERFORMANCE FOTOGRAFI -->
    <h2 style="margin-top:16px">👤 Performance fotografi</h2>
    <div class="box" id="plFotoTable"></div>

    <!-- SPESE EXTRA -->
    <h2 style="margin-top:16px">🧾 Spese extra</h2>
    <div class="box" style="margin-bottom:4px">
      <div style="display:grid;grid-template-columns:1fr 1fr;gap:8px;margin-bottom:10px" id="speseForm">
        <div>
          <label style="font-size:.65rem;color:#555;text-transform:uppercase;letter-spacing:.4px">Data</label>
          <input type="date" id="spData" style="width:100%;background:#2a2926;border:1px solid #383530;border-radius:8px;padding:9px 10px;color:#e0e0e0;font-size:.88rem;outline:none;margin-top:3px;min-height:42px"/>
        </div>
        <div>
          <label style="font-size:.65rem;color:#555;text-transform:uppercase;letter-spacing:.4px">Categoria</label>
          <select id="spCategoria" onchange="toggleCatCustom(this)"
            style="width:100%;background:#2a2926;border:1px solid #383530;border-radius:8px;padding:9px 10px;color:#e0e0e0;font-size:.88rem;outline:none;margin-top:3px;min-height:42px;-webkit-appearance:none">
            <option>Consumabili</option>
            <option>Trasporti</option>
            <option>Trasferte</option>
            <option>Attrezzatura</option>
            <option>Riparazioni</option>
            <option value="__stipendi__">💸 Stipendi fotografi</option>
            <option value="__bonus__">🏆 Bonus / Premio fotografo</option>
            <option value="__canone__">🏖️ Canone struttura</option>
            <option>Stipendi dipendenti</option>
            <option>Tasse e contributi</option>
            <option value="__custom__">✏️ Personalizzata...</option>
          </select>
          <input type="text" id="spCategoriaCustom" placeholder="Scrivi la categoria..."
            style="display:none;width:100%;background:#2a2926;border:1px solid #cc5a2a;
            border-radius:8px;padding:9px 10px;color:#e0e0e0;font-size:.88rem;outline:none;
            margin-top:6px;min-height:42px"/>
          <select id="spFotografo" style="display:none;width:100%;background:#2a2926;
            border:1px solid #facc15;border-radius:8px;padding:9px 10px;color:#e0e0e0;
            font-size:.88rem;outline:none;margin-top:6px;min-height:42px;-webkit-appearance:none">
            <option value="">— Seleziona fotografo —</option>
          </select>
        </div>
        <div>
          <label style="font-size:.65rem;color:#555;text-transform:uppercase;letter-spacing:.4px">Struttura (opzionale)</label>
          <select id="spStruttura" style="width:100%;background:#2a2926;border:1px solid #383530;border-radius:8px;padding:9px 10px;color:#e0e0e0;font-size:.88rem;outline:none;margin-top:3px;min-height:42px;-webkit-appearance:none">
            <option value="">Tutte / Generale</option>
          </select>
        </div>
        <div>
          <label style="font-size:.65rem;color:#555;text-transform:uppercase;letter-spacing:.4px">Importo (€)</label>
          <input type="number" id="spImporto" min="0" step="0.01" placeholder="0.00"
            style="width:100%;background:#2a2926;border:1px solid #383530;border-radius:8px;padding:9px 10px;color:#e0e0e0;font-size:.88rem;outline:none;margin-top:3px;min-height:42px"/>
        </div>
        <div style="grid-column:1/-1">
          <label style="font-size:.65rem;color:#555;text-transform:uppercase;letter-spacing:.4px">Descrizione</label>
          <input type="text" id="spDesc" placeholder="es. Carta DNP, benzina trasferta..."
            style="width:100%;background:#2a2926;border:1px solid #383530;border-radius:8px;padding:9px 10px;color:#e0e0e0;font-size:.88rem;outline:none;margin-top:3px;min-height:42px"/>
        </div>
      </div>
      <button onclick="addExpense()"
        style="width:100%;background:#34d399;color:#1a1917;border:none;border-radius:8px;
        padding:12px;font-size:.92rem;font-weight:700;cursor:pointer;min-height:46px">
        ➕ Aggiungi spesa
      </button>
    </div>
    <div class="box" id="speseList"></div>

    <!-- CONFIGURA COSTI -->
    <div style="margin-top:16px">
      <button onclick="toggleCostConfig()" id="btnCostConfig"
        style="background:#242220;color:#aaa;border:1px solid #383530;border-radius:8px;
        padding:10px 16px;font-size:.85rem;cursor:pointer;width:100%;text-align:left">
        ⚙️ Configura costi ▾
      </button>
      <div id="costConfigPanel" style="display:none;margin-top:10px">

        <h2>👤 Costi fotografi</h2>
        <div class="box" id="cfgFotoTable"></div>

        <h2 style="margin-top:14px">🏖️ Costi strutture (totale stagionale accordato)</h2>
        <div class="box" id="cfgStrTable"></div>

        <button onclick="saveCosts()"
          style="margin-top:14px;width:100%;background:#cc5a2a;color:#fff;border:none;
          border-radius:8px;padding:13px;font-size:.95rem;font-weight:600;cursor:pointer;min-height:46px">
          💾 Salva tutti i costi
        </button>
        <div id="saveMsg" style="text-align:center;font-size:.8rem;color:#34d399;margin-top:8px;display:none">
          ✅ Costi salvati! La dashboard si aggiorna entro 1 minuto.
        </div>
      </div>
    </div>

  </div>

  <!-- TAB 6 — UTENTI -->
  <div class="pane" id="pane6">
    <h2 style="margin-bottom:12px">👥 Gestione Utenti</h2>

    <!-- FORM NUOVO/MODIFICA UTENTE -->
    <div class="box" style="margin-bottom:12px">
      <div style="font-size:.75rem;color:#cc5a2a;font-weight:700;text-transform:uppercase;letter-spacing:.5px;margin-bottom:12px">
        ➕ Crea / Modifica utente
      </div>
      <div style="display:grid;grid-template-columns:1fr 1fr;gap:8px;margin-bottom:10px">
        <div>
          <label style="font-size:.65rem;color:#555;text-transform:uppercase;letter-spacing:.4px">Username (senza spazi)</label>
          <input type="text" id="uUsername" placeholder="es. marco_rossi"
            style="width:100%;background:#2a2926;border:1px solid #383530;border-radius:8px;padding:9px 10px;color:#e0e0e0;font-size:.88rem;outline:none;margin-top:3px;min-height:42px"/>
        </div>
        <div>
          <label style="font-size:.65rem;color:#555;text-transform:uppercase;letter-spacing:.4px">Nome visualizzato</label>
          <input type="text" id="uNome" placeholder="es. Marco Rossi"
            style="width:100%;background:#2a2926;border:1px solid #383530;border-radius:8px;padding:9px 10px;color:#e0e0e0;font-size:.88rem;outline:none;margin-top:3px;min-height:42px"/>
        </div>
        <div>
          <label style="font-size:.65rem;color:#555;text-transform:uppercase;letter-spacing:.4px">Password</label>
          <input type="text" id="uPassword" placeholder="password utente"
            style="width:100%;background:#2a2926;border:1px solid #383530;border-radius:8px;padding:9px 10px;color:#e0e0e0;font-size:.88rem;outline:none;margin-top:3px;min-height:42px"/>
        </div>
        <div>
          <label style="font-size:.65rem;color:#555;text-transform:uppercase;letter-spacing:.4px">Ruolo</label>
          <input type="text" id="uRuolo" placeholder="es. Capo Area, Socio..."
            style="width:100%;background:#2a2926;border:1px solid #383530;border-radius:8px;padding:9px 10px;color:#e0e0e0;font-size:.88rem;outline:none;margin-top:3px;min-height:42px"/>
        </div>
        <div style="grid-column:1/-1">
          <label style="font-size:.65rem;color:#555;text-transform:uppercase;letter-spacing:.4px">Strutture visibili (seleziona una o più)</label>
          <div id="uStruttureCheck" style="display:grid;grid-template-columns:repeat(2,1fr);gap:6px;margin-top:6px"></div>
        </div>
        <div style="grid-column:1/-1;margin-top:4px">
          <label style="font-size:.65rem;color:#555;text-transform:uppercase;letter-spacing:.4px;display:block;margin-bottom:6px">🔐 Permessi (sezioni visibili)</label>
          <div style="display:grid;grid-template-columns:repeat(2,1fr);gap:6px">
            <label style="display:flex;align-items:center;gap:8px;background:#2a2926;border-radius:8px;padding:8px 10px;cursor:pointer;border:1px solid #383530">
              <input type="checkbox" id="perm_strutture" style="accent-color:#cc5a2a;width:15px;height:15px" checked>
              <span style="font-size:.8rem;color:#ccc">🏖️ Strutture</span></label>
            <label style="display:flex;align-items:center;gap:8px;background:#2a2926;border-radius:8px;padding:8px 10px;cursor:pointer;border:1px solid #383530">
              <input type="checkbox" id="perm_fotografi" style="accent-color:#cc5a2a;width:15px;height:15px" checked>
              <span style="font-size:.8rem;color:#ccc">👤 Fotografi</span></label>
            <label style="display:flex;align-items:center;gap:8px;background:#2a2926;border-radius:8px;padding:8px 10px;cursor:pointer;border:1px solid #383530">
              <input type="checkbox" id="perm_obiettivi" style="accent-color:#cc5a2a;width:15px;height:15px" checked>
              <span style="font-size:.8rem;color:#ccc">🎯 Obiettivi</span></label>
            <label style="display:flex;align-items:center;gap:8px;background:#2a2926;border-radius:8px;padding:8px 10px;cursor:pointer;border:1px solid #383530">
              <input type="checkbox" id="perm_consumabili" style="accent-color:#cc5a2a;width:15px;height:15px">
              <span style="font-size:.8rem;color:#ccc">🖨️ Consumabili</span></label>
            <label style="display:flex;align-items:center;gap:8px;background:#2a2926;border-radius:8px;padding:8px 10px;cursor:pointer;border:1px solid #383530">
              <input type="checkbox" id="perm_contabilita" style="accent-color:#cc5a2a;width:15px;height:15px">
              <span style="font-size:.8rem;color:#ccc">💼 Contabilità</span></label>
            <label style="display:flex;align-items:center;gap:8px;background:#2a2926;border-radius:8px;padding:8px 10px;cursor:pointer;border:1px solid #383530">
              <input type="checkbox" id="perm_presenze" style="accent-color:#cc5a2a;width:15px;height:15px" checked>
              <span style="font-size:.8rem;color:#ccc">👥 Presenze</span></label>
            <label style="display:flex;align-items:center;gap:8px;background:#2a2926;border-radius:8px;padding:8px 10px;cursor:pointer;border:1px solid #38bdf844">
              <input type="checkbox" id="perm_input_presenze" style="accent-color:#38bdf8;width:15px;height:15px" checked>
              <span style="font-size:.8rem;color:#38bdf8">📝 Inserimento presenze</span></label>
            <label style="display:flex;align-items:center;gap:8px;background:#2a2926;border-radius:8px;padding:8px 10px;cursor:pointer;border:1px solid #f8717144">
              <input type="checkbox" id="perm_edit_spese" style="accent-color:#f87171;width:15px;height:15px">
              <span style="font-size:.8rem;color:#f87171">🧾 Agg./canc. spese</span></label>
            <label style="display:flex;align-items:center;gap:8px;background:#2a2926;border-radius:8px;padding:8px 10px;cursor:pointer;border:1px solid #f59e0b44">
              <input type="checkbox" id="perm_alerts" style="accent-color:#f59e0b;width:15px;height:15px">
              <span style="font-size:.8rem;color:#f59e0b">🔔 Ricevi alert Spectre</span></label>
            <label style="display:flex;align-items:center;gap:8px;background:#2a2926;border-radius:8px;padding:8px 10px;cursor:pointer;border:1px solid #34d39944">
              <input type="checkbox" id="perm_agenda" style="accent-color:#34d399;width:15px;height:15px">
              <span style="font-size:.8rem;color:#34d399">📅 Gestione agenda shooting</span></label>
          </div>
        </div>
      </div>
      <button onclick="saveUser()"
        style="width:100%;background:#cc5a2a;color:#fff;border:none;border-radius:8px;
        padding:12px;font-size:.92rem;font-weight:700;cursor:pointer;min-height:46px">
        💾 Salva utente
      </button>
    </div>

    <!-- LISTA UTENTI -->
    <div class="box" id="usersTable"></div>

    <!-- LOG ACCESSI -->
    <h2 style="margin-top:20px;margin-bottom:12px">🔍 Log accessi</h2>
    <div class="box" id="accessLogTable"></div>
  </div>

  <!-- TAB 7 — SPECTRE -->
  <div class="pane" id="pane7">
    <h2>🖥️ Stato Postazioni</h2>
    <div id="postazioniStato" style="margin-bottom:24px"></div>
    <h2>🔍 Controllo Schede SD (EXIF)</h2>
    <div id="exifContent" style="margin-bottom:24px"></div>
    <h2>📷 Sessioni Fotografiche (Spectre)</h2>
    <div id="spectreContent" style="margin-bottom:24px"></div>
    <h2>🌐 Landing Pages — Statistiche</h2>
    <div id="landingStatsContent"></div>

    <h2 style="margin-top:32px">✏️ Editor Landing Page</h2>
    <div id="landingEditorWrap" style="margin-top:12px">
      <div style="display:flex;align-items:center;gap:12px;margin-bottom:20px;flex-wrap:wrap">
        <label style="color:#aaa;font-size:.82rem">Struttura:</label>
        <select id="edStruttura" onchange="loadLandingConfig()"
          style="background:#2a2926;color:#e0e0e0;border:1px solid #383530;border-radius:6px;padding:6px 12px;font-size:.85rem">
          <option value="">— seleziona —</option>
        </select>
        <button onclick="loadLandingConfig()"
          style="background:#2a2926;color:#cc5a2a;border:1px solid #cc5a2a;border-radius:6px;padding:6px 14px;cursor:pointer;font-size:.82rem">🔄 Ricarica</button>
        <a id="edLandingLink" href="#" target="_blank"
          style="background:#2a2926;color:#cc5a2a;border:1px solid #383530;border-radius:6px;padding:6px 12px;font-size:.82rem;text-decoration:none;display:none">🔗 Apri landing</a>
      </div>

      <div id="landingEditorForm" style="display:none">
        <!-- Nome visualizzato -->
        <div class="led-section">
          <div class="led-head" onclick="toggleSection(this)">🏷️ Nome visualizzato <span>▼</span></div>
          <div class="led-body">
            <div class="led-row">
              <label>Nome struttura (nav/titolo)</label>
              <input type="text" id="led_display_name" placeholder="es. Marina Beach"/>
            </div>
          </div>
        </div>

        <!-- Prezzi -->
        <div class="led-section">
          <div class="led-head" onclick="toggleSection(this)">💶 Prezzi <span>▼</span></div>
          <div class="led-body">
            <div style="display:grid;grid-template-columns:1fr 1fr 1fr;gap:12px">
              <div class="led-row">
                <label>Pacchetto MINI (€)</label>
                <input type="text" id="led_p1" placeholder="20"/>
              </div>
              <div class="led-row">
                <label>Pacchetto FAMILY (€)</label>
                <input type="text" id="led_p2" placeholder="50"/>
              </div>
              <div class="led-row">
                <label>Pacchetto PREMIUM (€)</label>
                <input type="text" id="led_p3" placeholder="80"/>
              </div>
            </div>
          </div>
        </div>

        <!-- Gallery -->
        <div class="led-section">
          <div class="led-head" onclick="toggleSection(this)">🖼️ Galleria (URL immagini) <span>▼</span></div>
          <div class="led-body">
            <div style="display:grid;grid-template-columns:1fr 1fr;gap:10px">
              <div class="led-row"><label>Foto 1</label><input type="text" class="led-gal" data-idx="0" placeholder="https://..."/></div>
              <div class="led-row"><label>Foto 2</label><input type="text" class="led-gal" data-idx="1" placeholder="https://..."/></div>
              <div class="led-row"><label>Foto 3</label><input type="text" class="led-gal" data-idx="2" placeholder="https://..."/></div>
              <div class="led-row"><label>Foto 4</label><input type="text" class="led-gal" data-idx="3" placeholder="https://..."/></div>
              <div class="led-row"><label>Foto 5</label><input type="text" class="led-gal" data-idx="4" placeholder="https://..."/></div>
            </div>
          </div>
        </div>

        <!-- Testi per lingua -->
        <div class="led-section">
          <div class="led-head" onclick="toggleSection(this)">🌍 Testi — HERO <span>▼</span></div>
          <div class="led-body">
            <div class="led-lang-tabs">
              <button class="led-ltab active" onclick="switchLedLang(this,'hero')">🇮🇹 IT</button>
              <button class="led-ltab" onclick="switchLedLang(this,'hero')">🇬🇧 EN</button>
              <button class="led-ltab" onclick="switchLedLang(this,'hero')">🇫🇷 FR</button>
              <button class="led-ltab" onclick="switchLedLang(this,'hero')">🇩🇪 DE</button>
            </div>
            <div data-section="hero" data-lang="it" class="led-lang-panel">
              <div class="led-row"><label>Badge (es. 📍 Fotografia Professionale)</label><input type="text" class="led-txt" data-lang="it" data-key="badge"/></div>
              <div class="led-row"><label>Titolo hero (HTML ok, es. I tuoi ricordi&lt;br&gt;&lt;em&gt;immortalati&lt;/em&gt;)</label><textarea class="led-txt" data-lang="it" data-key="hero_h1" rows="2"></textarea></div>
              <div class="led-row"><label>Sottotitolo hero</label><textarea class="led-txt" data-lang="it" data-key="hero_p" rows="2"></textarea></div>
              <div class="led-row"><label>Testo footer</label><input type="text" class="led-txt" data-lang="it" data-key="footer_txt"/></div>
            </div>
            <div data-section="hero" data-lang="en" class="led-lang-panel" style="display:none">
              <div class="led-row"><label>Badge</label><input type="text" class="led-txt" data-lang="en" data-key="badge"/></div>
              <div class="led-row"><label>Titolo hero</label><textarea class="led-txt" data-lang="en" data-key="hero_h1" rows="2"></textarea></div>
              <div class="led-row"><label>Sottotitolo hero</label><textarea class="led-txt" data-lang="en" data-key="hero_p" rows="2"></textarea></div>
              <div class="led-row"><label>Testo footer</label><input type="text" class="led-txt" data-lang="en" data-key="footer_txt"/></div>
            </div>
            <div data-section="hero" data-lang="fr" class="led-lang-panel" style="display:none">
              <div class="led-row"><label>Badge</label><input type="text" class="led-txt" data-lang="fr" data-key="badge"/></div>
              <div class="led-row"><label>Titolo hero</label><textarea class="led-txt" data-lang="fr" data-key="hero_h1" rows="2"></textarea></div>
              <div class="led-row"><label>Sottotitolo hero</label><textarea class="led-txt" data-lang="fr" data-key="hero_p" rows="2"></textarea></div>
              <div class="led-row"><label>Testo footer</label><input type="text" class="led-txt" data-lang="fr" data-key="footer_txt"/></div>
            </div>
            <div data-section="hero" data-lang="de" class="led-lang-panel" style="display:none">
              <div class="led-row"><label>Badge</label><input type="text" class="led-txt" data-lang="de" data-key="badge"/></div>
              <div class="led-row"><label>Titolo hero</label><textarea class="led-txt" data-lang="de" data-key="hero_h1" rows="2"></textarea></div>
              <div class="led-row"><label>Sottotitolo hero</label><textarea class="led-txt" data-lang="de" data-key="hero_p" rows="2"></textarea></div>
              <div class="led-row"><label>Testo footer</label><input type="text" class="led-txt" data-lang="de" data-key="footer_txt"/></div>
            </div>
          </div>
        </div>

        <div class="led-section">
          <div class="led-head" onclick="toggleSection(this)">📋 Testi — SERVIZI <span>▼</span></div>
          <div class="led-body">
            <div class="led-lang-tabs">
              <button class="led-ltab active" onclick="switchLedLang(this,'svc')">🇮🇹 IT</button>
              <button class="led-ltab" onclick="switchLedLang(this,'svc')">🇬🇧 EN</button>
              <button class="led-ltab" onclick="switchLedLang(this,'svc')">🇫🇷 FR</button>
              <button class="led-ltab" onclick="switchLedLang(this,'svc')">🇩🇪 DE</button>
            </div>
            <div data-section="svc" data-lang="it" class="led-lang-panel">
              <div class="led-row"><label>Titolo sezione servizi</label><input type="text" class="led-txt" data-lang="it" data-key="svc_title"/></div>
              <div class="led-row"><label>Sottotitolo</label><textarea class="led-txt" data-lang="it" data-key="svc_sub" rows="2"></textarea></div>
              <div style="display:grid;grid-template-columns:1fr 1fr 1fr;gap:10px;margin-top:8px">
                <div><div style="color:#cc5a2a;font-size:.75rem;margin-bottom:6px">🏖️ Servizio 1</div>
                  <div class="led-row"><label>Nome</label><input type="text" class="led-txt" data-lang="it" data-key="s1_name"/></div>
                  <div class="led-row"><label>Descrizione</label><textarea class="led-txt" data-lang="it" data-key="s1_desc" rows="2"></textarea></div></div>
                <div><div style="color:#cc5a2a;font-size:.75rem;margin-bottom:6px">👨‍👩‍👧 Servizio 2</div>
                  <div class="led-row"><label>Nome</label><input type="text" class="led-txt" data-lang="it" data-key="s2_name"/></div>
                  <div class="led-row"><label>Descrizione</label><textarea class="led-txt" data-lang="it" data-key="s2_desc" rows="2"></textarea></div></div>
                <div><div style="color:#cc5a2a;font-size:.75rem;margin-bottom:6px">🌅 Servizio 3</div>
                  <div class="led-row"><label>Nome</label><input type="text" class="led-txt" data-lang="it" data-key="s3_name"/></div>
                  <div class="led-row"><label>Descrizione</label><textarea class="led-txt" data-lang="it" data-key="s3_desc" rows="2"></textarea></div></div>
              </div>
            </div>
            <div data-section="svc" data-lang="en" class="led-lang-panel" style="display:none">
              <div class="led-row"><label>Titolo sezione servizi</label><input type="text" class="led-txt" data-lang="en" data-key="svc_title"/></div>
              <div class="led-row"><label>Sottotitolo</label><textarea class="led-txt" data-lang="en" data-key="svc_sub" rows="2"></textarea></div>
              <div style="display:grid;grid-template-columns:1fr 1fr 1fr;gap:10px;margin-top:8px">
                <div><div style="color:#cc5a2a;font-size:.75rem;margin-bottom:6px">🏖️ Servizio 1</div>
                  <div class="led-row"><label>Nome</label><input type="text" class="led-txt" data-lang="en" data-key="s1_name"/></div>
                  <div class="led-row"><label>Descrizione</label><textarea class="led-txt" data-lang="en" data-key="s1_desc" rows="2"></textarea></div></div>
                <div><div style="color:#cc5a2a;font-size:.75rem;margin-bottom:6px">👨‍👩‍👧 Servizio 2</div>
                  <div class="led-row"><label>Nome</label><input type="text" class="led-txt" data-lang="en" data-key="s2_name"/></div>
                  <div class="led-row"><label>Descrizione</label><textarea class="led-txt" data-lang="en" data-key="s2_desc" rows="2"></textarea></div></div>
                <div><div style="color:#cc5a2a;font-size:.75rem;margin-bottom:6px">🌅 Servizio 3</div>
                  <div class="led-row"><label>Nome</label><input type="text" class="led-txt" data-lang="en" data-key="s3_name"/></div>
                  <div class="led-row"><label>Descrizione</label><textarea class="led-txt" data-lang="en" data-key="s3_desc" rows="2"></textarea></div></div>
              </div>
            </div>
            <div data-section="svc" data-lang="fr" class="led-lang-panel" style="display:none">
              <div class="led-row"><label>Titolo sezione servizi</label><input type="text" class="led-txt" data-lang="fr" data-key="svc_title"/></div>
              <div class="led-row"><label>Sottotitolo</label><textarea class="led-txt" data-lang="fr" data-key="svc_sub" rows="2"></textarea></div>
              <div style="display:grid;grid-template-columns:1fr 1fr 1fr;gap:10px;margin-top:8px">
                <div><div style="color:#cc5a2a;font-size:.75rem;margin-bottom:6px">🏖️ Servizio 1</div>
                  <div class="led-row"><label>Nome</label><input type="text" class="led-txt" data-lang="fr" data-key="s1_name"/></div>
                  <div class="led-row"><label>Descrizione</label><textarea class="led-txt" data-lang="fr" data-key="s1_desc" rows="2"></textarea></div></div>
                <div><div style="color:#cc5a2a;font-size:.75rem;margin-bottom:6px">👨‍👩‍👧 Servizio 2</div>
                  <div class="led-row"><label>Nome</label><input type="text" class="led-txt" data-lang="fr" data-key="s2_name"/></div>
                  <div class="led-row"><label>Descrizione</label><textarea class="led-txt" data-lang="fr" data-key="s2_desc" rows="2"></textarea></div></div>
                <div><div style="color:#cc5a2a;font-size:.75rem;margin-bottom:6px">🌅 Servizio 3</div>
                  <div class="led-row"><label>Nome</label><input type="text" class="led-txt" data-lang="fr" data-key="s3_name"/></div>
                  <div class="led-row"><label>Descrizione</label><textarea class="led-txt" data-lang="fr" data-key="s3_desc" rows="2"></textarea></div></div>
              </div>
            </div>
            <div data-section="svc" data-lang="de" class="led-lang-panel" style="display:none">
              <div class="led-row"><label>Titolo sezione servizi</label><input type="text" class="led-txt" data-lang="de" data-key="svc_title"/></div>
              <div class="led-row"><label>Sottotitolo</label><textarea class="led-txt" data-lang="de" data-key="svc_sub" rows="2"></textarea></div>
              <div style="display:grid;grid-template-columns:1fr 1fr 1fr;gap:10px;margin-top:8px">
                <div><div style="color:#cc5a2a;font-size:.75rem;margin-bottom:6px">🏖️ Servizio 1</div>
                  <div class="led-row"><label>Nome</label><input type="text" class="led-txt" data-lang="de" data-key="s1_name"/></div>
                  <div class="led-row"><label>Descrizione</label><textarea class="led-txt" data-lang="de" data-key="s1_desc" rows="2"></textarea></div></div>
                <div><div style="color:#cc5a2a;font-size:.75rem;margin-bottom:6px">👨‍👩‍👧 Servizio 2</div>
                  <div class="led-row"><label>Nome</label><input type="text" class="led-txt" data-lang="de" data-key="s2_name"/></div>
                  <div class="led-row"><label>Descrizione</label><textarea class="led-txt" data-lang="de" data-key="s2_desc" rows="2"></textarea></div></div>
                <div><div style="color:#cc5a2a;font-size:.75rem;margin-bottom:6px">🌅 Servizio 3</div>
                  <div class="led-row"><label>Nome</label><input type="text" class="led-txt" data-lang="de" data-key="s3_name"/></div>
                  <div class="led-row"><label>Descrizione</label><textarea class="led-txt" data-lang="de" data-key="s3_desc" rows="2"></textarea></div></div>
              </div>
            </div>
          </div>
        </div>

        <div class="led-section">
          <div class="led-head" onclick="toggleSection(this)">💰 Testi — PACCHETTI <span>▼</span></div>
          <div class="led-body">
            <div class="led-lang-tabs">
              <button class="led-ltab active" onclick="switchLedLang(this,'pkg')">🇮🇹 IT</button>
              <button class="led-ltab" onclick="switchLedLang(this,'pkg')">🇬🇧 EN</button>
              <button class="led-ltab" onclick="switchLedLang(this,'pkg')">🇫🇷 FR</button>
              <button class="led-ltab" onclick="switchLedLang(this,'pkg')">🇩🇪 DE</button>
            </div>
            <div data-section="pkg" data-lang="it" class="led-lang-panel">
              <div class="led-row"><label>Titolo sezione prezzi</label><input type="text" class="led-txt" data-lang="it" data-key="price_title"/></div>
              <div class="led-row"><label>Sottotitolo</label><textarea class="led-txt" data-lang="it" data-key="price_sub" rows="2"></textarea></div>
              <div style="display:grid;grid-template-columns:1fr 1fr 1fr;gap:10px;margin-top:8px">
                <div><div style="color:#f59e0b;font-size:.75rem;margin-bottom:6px">📦 MINI</div>
                  <div class="led-row"><label>Nome</label><input type="text" class="led-txt" data-lang="it" data-key="p1_name"/></div>
                  <div class="led-row"><label>Unità</label><input type="text" class="led-txt" data-lang="it" data-key="p1_unit"/></div>
                  <div class="led-row"><label>Feature 1</label><input type="text" class="led-txt" data-lang="it" data-key="p1_f1"/></div>
                  <div class="led-row"><label>Feature 2</label><input type="text" class="led-txt" data-lang="it" data-key="p1_f2"/></div>
                  <div class="led-row"><label>Feature 3</label><input type="text" class="led-txt" data-lang="it" data-key="p1_f3"/></div></div>
                <div><div style="color:#f59e0b;font-size:.75rem;margin-bottom:6px">📦 FAMILY</div>
                  <div class="led-row"><label>Nome</label><input type="text" class="led-txt" data-lang="it" data-key="p2_name"/></div>
                  <div class="led-row"><label>Unità</label><input type="text" class="led-txt" data-lang="it" data-key="p2_unit"/></div>
                  <div class="led-row"><label>Feature 1</label><input type="text" class="led-txt" data-lang="it" data-key="p2_f1"/></div>
                  <div class="led-row"><label>Feature 2</label><input type="text" class="led-txt" data-lang="it" data-key="p2_f2"/></div>
                  <div class="led-row"><label>Feature 3</label><input type="text" class="led-txt" data-lang="it" data-key="p2_f3"/></div>
                  <div class="led-row"><label>Feature 4</label><input type="text" class="led-txt" data-lang="it" data-key="p2_f4"/></div></div>
                <div><div style="color:#f59e0b;font-size:.75rem;margin-bottom:6px">📦 PREMIUM</div>
                  <div class="led-row"><label>Nome</label><input type="text" class="led-txt" data-lang="it" data-key="p3_name"/></div>
                  <div class="led-row"><label>Unità</label><input type="text" class="led-txt" data-lang="it" data-key="p3_unit"/></div>
                  <div class="led-row"><label>Feature 1</label><input type="text" class="led-txt" data-lang="it" data-key="p3_f1"/></div>
                  <div class="led-row"><label>Feature 2</label><input type="text" class="led-txt" data-lang="it" data-key="p3_f2"/></div>
                  <div class="led-row"><label>Feature 3</label><input type="text" class="led-txt" data-lang="it" data-key="p3_f3"/></div>
                  <div class="led-row"><label>Feature 4</label><input type="text" class="led-txt" data-lang="it" data-key="p3_f4"/></div></div>
              </div>
            </div>
            <div data-section="pkg" data-lang="en" class="led-lang-panel" style="display:none">
              <div class="led-row"><label>Titolo sezione prezzi</label><input type="text" class="led-txt" data-lang="en" data-key="price_title"/></div>
              <div class="led-row"><label>Sottotitolo</label><textarea class="led-txt" data-lang="en" data-key="price_sub" rows="2"></textarea></div>
              <div style="display:grid;grid-template-columns:1fr 1fr 1fr;gap:10px;margin-top:8px">
                <div><div style="color:#f59e0b;font-size:.75rem;margin-bottom:6px">📦 MINI</div>
                  <div class="led-row"><label>Nome</label><input type="text" class="led-txt" data-lang="en" data-key="p1_name"/></div>
                  <div class="led-row"><label>Unità</label><input type="text" class="led-txt" data-lang="en" data-key="p1_unit"/></div>
                  <div class="led-row"><label>Feature 1</label><input type="text" class="led-txt" data-lang="en" data-key="p1_f1"/></div>
                  <div class="led-row"><label>Feature 2</label><input type="text" class="led-txt" data-lang="en" data-key="p1_f2"/></div>
                  <div class="led-row"><label>Feature 3</label><input type="text" class="led-txt" data-lang="en" data-key="p1_f3"/></div></div>
                <div><div style="color:#f59e0b;font-size:.75rem;margin-bottom:6px">📦 FAMILY</div>
                  <div class="led-row"><label>Nome</label><input type="text" class="led-txt" data-lang="en" data-key="p2_name"/></div>
                  <div class="led-row"><label>Unità</label><input type="text" class="led-txt" data-lang="en" data-key="p2_unit"/></div>
                  <div class="led-row"><label>Feature 1</label><input type="text" class="led-txt" data-lang="en" data-key="p2_f1"/></div>
                  <div class="led-row"><label>Feature 2</label><input type="text" class="led-txt" data-lang="en" data-key="p2_f2"/></div>
                  <div class="led-row"><label>Feature 3</label><input type="text" class="led-txt" data-lang="en" data-key="p2_f3"/></div>
                  <div class="led-row"><label>Feature 4</label><input type="text" class="led-txt" data-lang="en" data-key="p2_f4"/></div></div>
                <div><div style="color:#f59e0b;font-size:.75rem;margin-bottom:6px">📦 PREMIUM</div>
                  <div class="led-row"><label>Nome</label><input type="text" class="led-txt" data-lang="en" data-key="p3_name"/></div>
                  <div class="led-row"><label>Unità</label><input type="text" class="led-txt" data-lang="en" data-key="p3_unit"/></div>
                  <div class="led-row"><label>Feature 1</label><input type="text" class="led-txt" data-lang="en" data-key="p3_f1"/></div>
                  <div class="led-row"><label>Feature 2</label><input type="text" class="led-txt" data-lang="en" data-key="p3_f2"/></div>
                  <div class="led-row"><label>Feature 3</label><input type="text" class="led-txt" data-lang="en" data-key="p3_f3"/></div>
                  <div class="led-row"><label>Feature 4</label><input type="text" class="led-txt" data-lang="en" data-key="p3_f4"/></div></div>
              </div>
            </div>
            <div data-section="pkg" data-lang="fr" class="led-lang-panel" style="display:none">
              <div class="led-row"><label>Titolo sezione prezzi</label><input type="text" class="led-txt" data-lang="fr" data-key="price_title"/></div>
              <div class="led-row"><label>Sottotitolo</label><textarea class="led-txt" data-lang="fr" data-key="price_sub" rows="2"></textarea></div>
              <div style="display:grid;grid-template-columns:1fr 1fr 1fr;gap:10px;margin-top:8px">
                <div><div style="color:#f59e0b;font-size:.75rem;margin-bottom:6px">📦 MINI</div>
                  <div class="led-row"><label>Nome</label><input type="text" class="led-txt" data-lang="fr" data-key="p1_name"/></div>
                  <div class="led-row"><label>Unità</label><input type="text" class="led-txt" data-lang="fr" data-key="p1_unit"/></div>
                  <div class="led-row"><label>Feature 1</label><input type="text" class="led-txt" data-lang="fr" data-key="p1_f1"/></div>
                  <div class="led-row"><label>Feature 2</label><input type="text" class="led-txt" data-lang="fr" data-key="p1_f2"/></div>
                  <div class="led-row"><label>Feature 3</label><input type="text" class="led-txt" data-lang="fr" data-key="p1_f3"/></div></div>
                <div><div style="color:#f59e0b;font-size:.75rem;margin-bottom:6px">📦 FAMILY</div>
                  <div class="led-row"><label>Nome</label><input type="text" class="led-txt" data-lang="fr" data-key="p2_name"/></div>
                  <div class="led-row"><label>Unità</label><input type="text" class="led-txt" data-lang="fr" data-key="p2_unit"/></div>
                  <div class="led-row"><label>Feature 1</label><input type="text" class="led-txt" data-lang="fr" data-key="p2_f1"/></div>
                  <div class="led-row"><label>Feature 2</label><input type="text" class="led-txt" data-lang="fr" data-key="p2_f2"/></div>
                  <div class="led-row"><label>Feature 3</label><input type="text" class="led-txt" data-lang="fr" data-key="p2_f3"/></div>
                  <div class="led-row"><label>Feature 4</label><input type="text" class="led-txt" data-lang="fr" data-key="p2_f4"/></div></div>
                <div><div style="color:#f59e0b;font-size:.75rem;margin-bottom:6px">📦 PREMIUM</div>
                  <div class="led-row"><label>Nome</label><input type="text" class="led-txt" data-lang="fr" data-key="p3_name"/></div>
                  <div class="led-row"><label>Unità</label><input type="text" class="led-txt" data-lang="fr" data-key="p3_unit"/></div>
                  <div class="led-row"><label>Feature 1</label><input type="text" class="led-txt" data-lang="fr" data-key="p3_f1"/></div>
                  <div class="led-row"><label>Feature 2</label><input type="text" class="led-txt" data-lang="fr" data-key="p3_f2"/></div>
                  <div class="led-row"><label>Feature 3</label><input type="text" class="led-txt" data-lang="fr" data-key="p3_f3"/></div>
                  <div class="led-row"><label>Feature 4</label><input type="text" class="led-txt" data-lang="fr" data-key="p3_f4"/></div></div>
              </div>
            </div>
            <div data-section="pkg" data-lang="de" class="led-lang-panel" style="display:none">
              <div class="led-row"><label>Titolo sezione prezzi</label><input type="text" class="led-txt" data-lang="de" data-key="price_title"/></div>
              <div class="led-row"><label>Sottotitolo</label><textarea class="led-txt" data-lang="de" data-key="price_sub" rows="2"></textarea></div>
              <div style="display:grid;grid-template-columns:1fr 1fr 1fr;gap:10px;margin-top:8px">
                <div><div style="color:#f59e0b;font-size:.75rem;margin-bottom:6px">📦 MINI</div>
                  <div class="led-row"><label>Nome</label><input type="text" class="led-txt" data-lang="de" data-key="p1_name"/></div>
                  <div class="led-row"><label>Unità</label><input type="text" class="led-txt" data-lang="de" data-key="p1_unit"/></div>
                  <div class="led-row"><label>Feature 1</label><input type="text" class="led-txt" data-lang="de" data-key="p1_f1"/></div>
                  <div class="led-row"><label>Feature 2</label><input type="text" class="led-txt" data-lang="de" data-key="p1_f2"/></div>
                  <div class="led-row"><label>Feature 3</label><input type="text" class="led-txt" data-lang="de" data-key="p1_f3"/></div></div>
                <div><div style="color:#f59e0b;font-size:.75rem;margin-bottom:6px">📦 FAMILY</div>
                  <div class="led-row"><label>Nome</label><input type="text" class="led-txt" data-lang="de" data-key="p2_name"/></div>
                  <div class="led-row"><label>Unità</label><input type="text" class="led-txt" data-lang="de" data-key="p2_unit"/></div>
                  <div class="led-row"><label>Feature 1</label><input type="text" class="led-txt" data-lang="de" data-key="p2_f1"/></div>
                  <div class="led-row"><label>Feature 2</label><input type="text" class="led-txt" data-lang="de" data-key="p2_f2"/></div>
                  <div class="led-row"><label>Feature 3</label><input type="text" class="led-txt" data-lang="de" data-key="p2_f3"/></div>
                  <div class="led-row"><label>Feature 4</label><input type="text" class="led-txt" data-lang="de" data-key="p2_f4"/></div></div>
                <div><div style="color:#f59e0b;font-size:.75rem;margin-bottom:6px">📦 PREMIUM</div>
                  <div class="led-row"><label>Nome</label><input type="text" class="led-txt" data-lang="de" data-key="p3_name"/></div>
                  <div class="led-row"><label>Unità</label><input type="text" class="led-txt" data-lang="de" data-key="p3_unit"/></div>
                  <div class="led-row"><label>Feature 1</label><input type="text" class="led-txt" data-lang="de" data-key="p3_f1"/></div>
                  <div class="led-row"><label>Feature 2</label><input type="text" class="led-txt" data-lang="de" data-key="p3_f2"/></div>
                  <div class="led-row"><label>Feature 3</label><input type="text" class="led-txt" data-lang="de" data-key="p3_f3"/></div>
                  <div class="led-row"><label>Feature 4</label><input type="text" class="led-txt" data-lang="de" data-key="p3_f4"/></div></div>
              </div>
            </div>
          </div>
        </div>

        <div class="led-section">
          <div class="led-head" onclick="toggleSection(this)">📣 Testi — CTA <span>▼</span></div>
          <div class="led-body">
            <div class="led-lang-tabs">
              <button class="led-ltab active" onclick="switchLedLang(this,'cta')">🇮🇹 IT</button>
              <button class="led-ltab" onclick="switchLedLang(this,'cta')">🇬🇧 EN</button>
              <button class="led-ltab" onclick="switchLedLang(this,'cta')">🇫🇷 FR</button>
              <button class="led-ltab" onclick="switchLedLang(this,'cta')">🇩🇪 DE</button>
            </div>
            <div data-section="cta" data-lang="it" class="led-lang-panel">
              <div class="led-row"><label>Titolo CTA</label><input type="text" class="led-txt" data-lang="it" data-key="cta_title"/></div>
              <div class="led-row"><label>Testo CTA</label><textarea class="led-txt" data-lang="it" data-key="cta_p" rows="2"></textarea></div>
              <div class="led-row"><label>Testo bottone WhatsApp</label><input type="text" class="led-txt" data-lang="it" data-key="cta_btn"/></div>
            </div>
            <div data-section="cta" data-lang="en" class="led-lang-panel" style="display:none">
              <div class="led-row"><label>Titolo CTA</label><input type="text" class="led-txt" data-lang="en" data-key="cta_title"/></div>
              <div class="led-row"><label>Testo CTA</label><textarea class="led-txt" data-lang="en" data-key="cta_p" rows="2"></textarea></div>
              <div class="led-row"><label>Testo bottone WhatsApp</label><input type="text" class="led-txt" data-lang="en" data-key="cta_btn"/></div>
            </div>
            <div data-section="cta" data-lang="fr" class="led-lang-panel" style="display:none">
              <div class="led-row"><label>Titolo CTA</label><input type="text" class="led-txt" data-lang="fr" data-key="cta_title"/></div>
              <div class="led-row"><label>Testo CTA</label><textarea class="led-txt" data-lang="fr" data-key="cta_p" rows="2"></textarea></div>
              <div class="led-row"><label>Testo bottone WhatsApp</label><input type="text" class="led-txt" data-lang="fr" data-key="cta_btn"/></div>
            </div>
            <div data-section="cta" data-lang="de" class="led-lang-panel" style="display:none">
              <div class="led-row"><label>Titolo CTA</label><input type="text" class="led-txt" data-lang="de" data-key="cta_title"/></div>
              <div class="led-row"><label>Testo CTA</label><textarea class="led-txt" data-lang="de" data-key="cta_p" rows="2"></textarea></div>
              <div class="led-row"><label>Testo bottone WhatsApp</label><input type="text" class="led-txt" data-lang="de" data-key="cta_btn"/></div>
            </div>
          </div>
        </div>

        <div style="margin-top:20px;display:flex;gap:12px;align-items:center;flex-wrap:wrap">
          <button onclick="saveLandingConfig()"
            style="background:linear-gradient(135deg,#cc5a2a,#e07a52);color:#fff;border:none;border-radius:8px;
                   padding:10px 28px;font-size:.9rem;font-weight:600;cursor:pointer">
            💾 Salva configurazione
          </button>
          <div id="ledSaveMsg" style="font-size:.82rem;color:#34d399;display:none">✅ Salvato!</div>
          <div id="ledSaveErr" style="font-size:.82rem;color:#f87171;display:none"></div>
        </div>
      </div>
    </div>
  </div>

  <div class="footer" id="footer"></div>
</div>

<script>
const _D         = __DATA__;
const PRINTERS   = __PRINTERS__;
const KIT_RESETS = __RESETS__;
let   COSTS      = __COSTS__;
let   EXPENSES   = __EXPENSES__;
let   PRESENCES  = __PRESENCES__;
let   USERS      = __USERS__;
let   ACCESS_LOG  = __ACCESS_LOG__;
let   SPECTRE     = __SPECTRE__;
// Decomprime il formato compatto in oggetti normali
const D = {
  anni: _D.anni,
  strutture: _D.strutture,
  fotografi: _D.fotografi,
  formati: _D.formati,
  cameras: _D.cameras||[],
  records: _D.records.map(r => ({
    Struttura: _D.strutture[r[0]],
    Fotografo: _D.fotografi[r[1]],
    Formato:   _D.formati[r[2]],
    Anno:      String(r[3]),
    Mese:      r[4],
    Giorno:    r[5],
    NomeMese:  ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'][r[4]-1],
    Quantità:  r[6],
    Prezzo:    r[7],
    Camera:    (_D.cameras||[])[r[8]]||'',
  }))
};
const C = ['#cc5a2a','#e07a52','#34d399','#f59e0b','#f87171','#38bdf8','#fb923c','#e879f9','#84cc16','#22d3ee'];
const MORD = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];
const MIT  = {Jan:'Gen',Feb:'Feb',Mar:'Mar',Apr:'Apr',May:'Mag',Jun:'Giu',
               Jul:'Lug',Aug:'Ago',Sep:'Set',Oct:'Ott',Nov:'Nov',Dec:'Dic'};
const targets = {};

// ── Formato numeri ──────────────────────────────────────────────────────────
const fmtE = n => '€ ' + Math.round(n).toLocaleString('it-IT');
const fmtN = n => Math.round(n).toLocaleString('it-IT');

// ── Filtri ──────────────────────────────────────────────────────────────────
const fStr  = document.getElementById('fStruttura');
const fFoto = document.getElementById('fFotografo');

const MESI_IT = ['','Gen','Feb','Mar','Apr','Mag','Giu','Lug','Ago','Set','Ott','Nov','Dic'];

D.strutture.forEach(s => { const o=document.createElement('option'); o.value=o.textContent=s; fStr.appendChild(o); });
D.fotografi.forEach(f => { targets[f]=15000; });

// ── Stato filtro data ────────────────────────────────────────────────────────
let _fromDate = null;
let _toDate   = null;
let _activePreset = '';

function isoDate(d) {
  return d.getFullYear()+'-'+String(d.getMonth()+1).padStart(2,'0')+'-'+String(d.getDate()).padStart(2,'0');
}
function getMonday(d) {
  const dt = new Date(d); dt.setHours(0,0,0,0);
  const day = dt.getDay();
  dt.setDate(dt.getDate() + (day===0 ? -6 : 1-day));
  return dt;
}
// Compatibilità con funzioni che usano anno/mese
function getFilterAnno() {
  return _fromDate ? String(_fromDate.getFullYear()) : String(new Date().getFullYear());
}
function getFilterMese() {
  if(!_fromDate || !_toDate) return '';
  if(_fromDate.getFullYear()===_toDate.getFullYear() && _fromDate.getMonth()===_toDate.getMonth())
    return String(_fromDate.getMonth()+1);
  return '';
}

function updateDateInputs() {
  const elDa = document.getElementById('fDa'), elA = document.getElementById('fA');
  if(elDa && _fromDate) elDa.value = isoDate(_fromDate);
  if(elA  && _toDate)   elA.value  = isoDate(_toDate);
}
function updateWeekLabel() {
  const el = document.getElementById('weekLabel');
  if(!el) return;
  if(!_fromDate || !_toDate) { el.textContent=''; return; }
  const df = _fromDate.toLocaleDateString('it-IT',{day:'numeric',month:'short',year:'numeric'});
  const dt = _toDate.toLocaleDateString('it-IT',{day:'numeric',month:'short',year:'numeric'});
  el.textContent = _fromDate.getTime()===_toDate.getTime() ? df : df+' – '+dt;
}
function updatePresetButtons() {
  document.querySelectorAll('.fpreset').forEach(btn => {
    const k = btn.getAttribute('data-key');
    const on = k === _activePreset;
    btn.style.background   = on ? '#cc5a2a' : '#2a2926';
    btn.style.color        = on ? '#fff'    : '#888';
    btn.style.borderColor  = on ? '#cc5a2a' : '#383530';
  });
}
function setPreset(key) {
  _activePreset = key;
  const today = new Date(); today.setHours(0,0,0,0);
  if(key==='oggi') {
    _fromDate = new Date(today); _toDate = new Date(today);
  } else if(key==='ieri') {
    const y = new Date(today); y.setDate(y.getDate()-1);
    _fromDate = y; _toDate = new Date(y);
  } else if(key==='sett_cur') {
    _fromDate = getMonday(today);
    _toDate = new Date(_fromDate); _toDate.setDate(_toDate.getDate()+6);
  } else if(key==='sett_prec') {
    _fromDate = getMonday(today); _fromDate.setDate(_fromDate.getDate()-7);
    _toDate = new Date(_fromDate); _toDate.setDate(_toDate.getDate()+6);
  } else if(key==='mese_cur') {
    _fromDate = new Date(today.getFullYear(), today.getMonth(), 1);
    _toDate   = new Date(today.getFullYear(), today.getMonth()+1, 0);
  } else if(key==='mese_prec') {
    _fromDate = new Date(today.getFullYear(), today.getMonth()-1, 1);
    _toDate   = new Date(today.getFullYear(), today.getMonth(), 0);
  } else if(key==='3mesi') {
    _toDate   = new Date(today);
    _fromDate = new Date(today); _fromDate.setMonth(_fromDate.getMonth()-3);
  } else if(key==='anno_cur') {
    _fromDate = new Date(today.getFullYear(), 0, 1);
    _toDate   = new Date(today.getFullYear(), 11, 31);
  } else if(key==='anno_prec') {
    _fromDate = new Date(today.getFullYear()-1, 0, 1);
    _toDate   = new Date(today.getFullYear()-1, 11, 31);
  } else if(key==='tutto') {
    _fromDate = new Date(2000, 0, 1);
    _toDate   = new Date(2099, 11, 31);
  }
  updateDateInputs(); updateWeekLabel(); updatePresetButtons(); updateFotografi(); render();
}
function navWeek(dir) {
  const base = (_fromDate && _activePreset.startsWith('sett')) ? new Date(_fromDate) : getMonday(new Date());
  base.setDate(base.getDate() + dir*7);
  _fromDate = base;
  _toDate = new Date(base); _toDate.setDate(_toDate.getDate()+6);
  _activePreset = '';
  updateDateInputs(); updateWeekLabel(); updatePresetButtons(); updateFotografi(); render();
}
function applyCustomRange() {
  const da = document.getElementById('fDa').value;
  const a  = document.getElementById('fA').value;
  if(da) _fromDate = new Date(da+'T00:00:00'); else _fromDate = new Date(2000,0,1);
  if(a)  _toDate   = new Date(a+'T00:00:00');  else _toDate   = new Date(2099,11,31);
  _activePreset = '';
  updateWeekLabel(); updatePresetButtons(); updateFotografi(); render();
}

// Aggiorna fotografi in base alla struttura selezionata
function updateFotografi() {
  const s = fStr.value;
  const foSet = [...new Set(D.records.filter(r => {
    if(!_fromDate || !_toDate) return !s || r.Struttura===s;
    const rd = new Date(r.Anno, r.Mese-1, r.Giorno);
    return rd >= _fromDate && rd <= _toDate && (!s || r.Struttura===s);
  }).map(r=>r.Fotografo))].sort();
  const cur = fFoto.value;
  fFoto.innerHTML = '<option value="">Tutti</option>';
  foSet.forEach(f => {
    const o=document.createElement('option');
    o.value=o.textContent=f;
    fFoto.appendChild(o);
    if(!targets[f]) targets[f]=15000;
  });
  if(foSet.includes(cur)) fFoto.value=cur;
}

function filtered() {
  const s=fStr.value, f=fFoto.value;
  let recs = D.records;
  if(_fromDate && _toDate) {
    recs = recs.filter(r => {
      const rd = new Date(r.Anno, r.Mese-1, r.Giorno);
      return rd >= _fromDate && rd <= _toDate;
    });
  }
  if(s) recs = recs.filter(r => r.Struttura===s);
  if(f) recs = recs.filter(r => r.Fotografo===f);
  return recs;
}
function grp(arr, key, val) {
  const m={};
  arr.forEach(r=>{ m[r[key]]=(m[r[key]]||0)+r[val]; });
  return m;
}

// ── SVG Charts ──────────────────────────────────────────────────────────────

function svgBar(container, labels, values, colors, fmt) {
  if (!labels.length) { container.innerHTML='<p style="color:#333;padding:20px;text-align:center">Nessun dato</p>'; return; }
  const W=340, barH=28, gap=8, padL=120, padR=82, padT=8, padB=8;
  const H = labels.length * (barH+gap) + padT + padB;
  const max = Math.max(...values) || 1;
  let html = `<svg class="chart" viewBox="0 0 ${W} ${H}" xmlns="http://www.w3.org/2000/svg">`;
  labels.forEach((lbl, i) => {
    const y = padT + i*(barH+gap);
    const bw = Math.max(4, (values[i]/max)*(W-padL-padR));
    const col = Array.isArray(colors) ? colors[i%colors.length] : colors;
    // Label colonna sinistra, allineata a destra
    const lblShort = lbl.length>16 ? lbl.slice(0,15)+'…' : lbl;
    html += `<text x="${padL-10}" y="${y+barH/2+4}" font-size="11" fill="#bbb" text-anchor="end">${lblShort}</text>`;
    // Barra
    html += `<rect x="${padL}" y="${y}" width="${bw}" height="${barH}" rx="5" fill="${col}" opacity=".9"/>`;
    // Valore a destra della barra
    html += `<text x="${padL+bw+8}" y="${y+barH/2+4}" font-size="11" fill="#888">${fmt ? fmt(values[i]) : fmtE(values[i])}</text>`;
  });
  html += '</svg>';
  container.innerHTML = html;
}

function svgDonut(container, labels, values, colors) {
  if (!labels.length) { container.innerHTML='<p style="color:#333;padding:20px;text-align:center">Nessun dato</p>'; return; }
  const S=180, cx=S/2, cy=S/2, R=65, r=38;
  const total = values.reduce((a,b)=>a+b,0) || 1;
  let html = `<svg class="chart" viewBox="0 0 ${S} ${S}" xmlns="http://www.w3.org/2000/svg">`;
  let angle = -Math.PI/2;
  values.forEach((v, i) => {
    const slice = (v/total)*Math.PI*2;
    const x1=cx+R*Math.cos(angle), y1=cy+R*Math.sin(angle);
    const x2=cx+R*Math.cos(angle+slice), y2=cy+R*Math.sin(angle+slice);
    const x3=cx+r*Math.cos(angle+slice), y3=cy+r*Math.sin(angle+slice);
    const x4=cx+r*Math.cos(angle), y4=cy+r*Math.sin(angle);
    const lg = slice>Math.PI?1:0;
    html += `<path d="M${x1},${y1} A${R},${R} 0 ${lg},1 ${x2},${y2} L${x3},${y3} A${r},${r} 0 ${lg},0 ${x4},${y4} Z"
      fill="${colors[i%colors.length]}" opacity=".9">
      <title>${labels[i]}: ${fmtN(v)}</title></path>`;
    angle += slice;
  });
  // Legend (max 8)
  const legLabels = labels.slice(0,8);
  legLabels.forEach((lbl, i) => {
    const ly = S*0.92 + Math.floor(i/2)*14 - (Math.ceil(legLabels.length/2)*7);
    const lx = (i%2===0) ? 4 : S/2+2;
    const short = lbl.length>14 ? lbl.slice(0,13)+'…' : lbl;
    html += `<rect x="${lx}" y="${ly}" width="8" height="8" rx="2" fill="${colors[i%colors.length]}"/>`;
    html += `<text x="${lx+11}" y="${ly+7}" font-size="9" fill="#777">${short}</text>`;
  });
  html += '</svg>';
  container.innerHTML = html;
}

function svgLine(container, labels, datasets) {
  if (!labels.length) { container.innerHTML='<p style="color:#333;padding:20px;text-align:center">Nessun dato</p>'; return; }
  const W=320, H=160, padL=52, padR=10, padT=10, padB=28;
  const iW=W-padL-padR, iH=H-padT-padB;
  const allVals = datasets.flatMap(d=>d.data);
  const maxV = Math.max(...allVals,1);
  const xStep = labels.length>1 ? iW/(labels.length-1) : iW;

  let html = `<svg class="chart" viewBox="0 0 ${W} ${H}" xmlns="http://www.w3.org/2000/svg">`;

  // Grid lines Y (4 lines)
  for(let g=0;g<=4;g++){
    const gy = padT + iH - (g/4)*iH;
    const gv = (g/4)*maxV;
    html += `<line x1="${padL}" y1="${gy}" x2="${W-padR}" y2="${gy}" stroke="#1e2130" stroke-width="1"/>`;
    html += `<text x="${padL-4}" y="${gy+4}" font-size="9" fill="#444" text-anchor="end">${fmtE(gv)}</text>`;
  }

  // X labels
  labels.forEach((lbl,i) => {
    const x = padL + i*xStep;
    html += `<text x="${x}" y="${H-6}" font-size="9" fill="#555" text-anchor="middle">${lbl}</text>`;
  });

  // Lines
  datasets.forEach((ds, di) => {
    const pts = ds.data.map((v,i) => `${padL+i*xStep},${padT+iH-(v/maxV)*iH}`);
    html += `<polyline points="${pts.join(' ')}" fill="none" stroke="${ds.color}" stroke-width="2" stroke-linejoin="round"/>`;
    ds.data.forEach((v,i) => {
      const px=padL+i*xStep, py=padT+iH-(v/maxV)*iH;
      html += `<circle cx="${px}" cy="${py}" r="3" fill="${ds.color}"><title>${ds.label}: ${fmtE(v)}</title></circle>`;
    });
  });

  // Legend
  datasets.slice(0,5).forEach((ds,i) => {
    html += `<rect x="${padL+i*58}" y="${H-padB+14}" width="8" height="3" rx="1" fill="${ds.color}"/>`;
    const short = ds.label.length>8 ? ds.label.slice(0,7)+'…' : ds.label;
    html += `<text x="${padL+i*58+11}" y="${H-padB+18}" font-size="8" fill="#666">${short}</text>`;
  });

  html += '</svg>';
  container.innerHTML = html;
}

// ── Render principale ───────────────────────────────────────────────────────
function render() {
  const rec = filtered();
  const incasso = rec.reduce((s,r)=>s+r.Prezzo,0);
  const qty     = rec.reduce((s,r)=>s+r.Quantità,0);
  const nFoto   = new Set(rec.map(r=>r.Fotografo)).size;
  const nStr    = new Set(rec.map(r=>r.Struttura)).size;

  document.getElementById('kInc').textContent   = fmtE(incasso);
  document.getElementById('kTrans').textContent = fmtN(rec.length)+' transazioni';
  document.getElementById('kQty').textContent   = fmtN(qty);
  document.getElementById('kFoto').textContent  = nFoto;
  document.getElementById('kStr').textContent   = nStr;
  document.getElementById('badge').textContent  = fmtN(rec.length)+' transazioni · '+(document.getElementById('weekLabel')||{textContent:''}).textContent;

  renderRiepilogo(rec);
  renderStrutture(rec);
  renderFotografi(rec);
  renderObiettivi(rec);
  renderConsumabili(rec);
  renderKitCounters();
  renderContabilita(rec);
  renderPresenze();
  renderSpectre();
}

function renderRiepilogo(rec) {
  // Bar strutture
  const sMap = grp(rec,'Struttura','Prezzo');
  const sK = Object.keys(sMap).sort((a,b)=>sMap[b]-sMap[a]);
  svgBar(document.getElementById('cStr'), sK, sK.map(k=>sMap[k]), C);

  // Donut formati
  const fMap = grp(rec,'Formato','Quantità');
  const fK = Object.keys(fMap).sort((a,b)=>fMap[b]-fMap[a]).slice(0,8);
  svgDonut(document.getElementById('cFmt'), fK, fK.map(k=>fMap[k]), C);

  // Line trend
  const strutture = [...new Set(rec.map(r=>r.Struttura))];
  const mData = {};
  rec.forEach(r => {
    if(!mData[r.NomeMese]) mData[r.NomeMese]={ord:MORD.indexOf(r.NomeMese)};
    mData[r.NomeMese][r.Struttura]=(mData[r.NomeMese][r.Struttura]||0)+r.Prezzo;
  });
  const ms = Object.entries(mData).sort((a,b)=>a[1].ord-b[1].ord);
  const labels = ms.map(([k])=>MIT[k]||k);
  const datasets = strutture.map((s,i)=>({label:s, color:C[i%C.length], data:ms.map(([,v])=>v[s]||0)}));
  svgLine(document.getElementById('cTrend'), labels, datasets);
}

function renderStrutture(rec) {
  const strutture = [...new Set(rec.map(r=>r.Struttura))].sort();
  document.getElementById('sCards').innerHTML = strutture.map((s,i) => {
    const sub = rec.filter(r=>r.Struttura===s);
    const inc = sub.reduce((a,r)=>a+r.Prezzo,0);
    const qty = sub.reduce((a,r)=>a+r.Quantità,0);
    const nF  = new Set(sub.map(r=>r.Fotografo)).size;
    const fmtG = grp(sub,'Formato','Quantità');
    const topFmt = Object.entries(fmtG).sort((a,b)=>b[1]-a[1])[0];
    const foG  = grp(sub,'Fotografo','Prezzo');
    const topFo = Object.entries(foG).sort((a,b)=>b[1]-a[1])[0];
    return `<div class="scard" style="border-color:${C[i%C.length]}">
      <div class="sname">🏖️ ${s}</div>
      <div class="sgrid">
        <div class="sstat"><div class="sl">💰 Incasso</div><div class="sv">${fmtE(inc)}</div></div>
        <div class="sstat"><div class="sl">🖼️ Vendute</div><div class="sv">${fmtN(qty)}</div></div>
        <div class="sstat"><div class="sl">👤 Fotografi</div><div class="sv">${nF}</div></div>
        <div class="sstat"><div class="sl">📦 Top formato</div><div class="sv">${topFmt?topFmt[0]:'-'}</div></div>
      </div>
      ${topFo?`<div class="stop">🏆 <strong style="color:#ccc">${topFo[0]}</strong> — ${fmtE(topFo[1])}</div>`:''}
    </div>`;
  }).join('');
}

function renderFotografi(rec) {
  const foMap = {};
  rec.forEach(r => {
    if(!foMap[r.Fotografo]) foMap[r.Fotografo]={inc:0,qty:0,n:0};
    foMap[r.Fotografo].inc+=r.Prezzo;
    foMap[r.Fotografo].qty+=r.Quantità;
    foMap[r.Fotografo].n++;
  });
  const sorted = Object.entries(foMap).sort((a,b)=>b[1].inc-a[1].inc);
  const maxInc = sorted[0]?.[1].inc||1;
  const medals = ['🥇','🥈','🥉'];

  document.getElementById('rankList').innerHTML = sorted.map(([f,v],i) => `
    <div class="ritem">
      <div class="rrow">
        <span class="rname">${medals[i]||'  '} ${f}</span>
        <span class="rval">${fmtE(v.inc)}</span>
      </div>
      <div class="bar-bg"><div class="bar-fg" style="width:${v.inc/maxInc*100}%;background:${C[i%C.length]}"></div></div>
      <div class="rsub">${fmtN(v.qty)} foto · ${v.n} vendite</div>
    </div>`).join('');

  // Top 5 trend
  const top5 = sorted.slice(0,5).map(([f])=>f);
  const mData = {};
  rec.forEach(r => {
    if(!mData[r.NomeMese]) mData[r.NomeMese]={ord:MORD.indexOf(r.NomeMese)};
    mData[r.NomeMese][r.Fotografo]=(mData[r.NomeMese][r.Fotografo]||0)+r.Prezzo;
  });
  const ms = Object.entries(mData).sort((a,b)=>a[1].ord-b[1].ord);
  const datasets = top5.map((f,i)=>({label:f, color:C[i%C.length], data:ms.map(([,v])=>v[f]||0)}));
  svgLine(document.getElementById('cFotoTrend'), ms.map(([k])=>MIT[k]||k), datasets);
}

function renderObiettivi(rec) {
  const foMap = grp(rec,'Fotografo','Prezzo');
  const sorted = Object.entries(foMap).sort((a,b)=>b[1]-a[1]);

  document.getElementById('goalCards').innerHTML = sorted.map(([f,inc],i) => {
    const t   = targets[f]||15000;
    const pct = Math.min(inc/t*100,100);
    const cls = pct>=100?'green':pct>=70?'yellow':'red';
    const col = pct>=100?'#4ade80':pct>=70?'#facc15':'#f87171';
    const tid = 'ti_'+i;
    return `<div class="gcard">
      <div class="grow">
        <span class="gname" style="color:${C[i%C.length]}">${f}</span>
        <span class="gpct ${cls}">${pct.toFixed(0)}%</span>
      </div>
      <div class="gbar-bg"><div class="gbar" style="width:${pct}%;background:${col}"></div></div>
      <div class="gfoot">
        <span>${fmtE(inc)}</span>
        <span>Target: <input type="number" id="${tid}" value="${t}" step="500"
          onchange="targets['${f}']=+this.value;renderObiettivi(filtered())"/></span>
      </div>
      ${pct<100?`<div style="font-size:.63rem;color:#444;margin-top:3px">Mancano ${fmtE(Math.max(t-inc,0))}</div>`:''}
    </div>`;
  }).join('');

  // Bar goal
  const labels = sorted.map(([f])=>f);
  const vals   = sorted.map(([,v])=>v);
  const tVals  = sorted.map(([f])=>targets[f]||15000);
  const maxV   = Math.max(...vals,...tVals,1);
  const W=340, barH=24, gap=8, padL=120, padR=82, padT=8, padB=8;
  const H = labels.length*(barH+gap)+padT+padB;
  let svg = `<svg class="chart" viewBox="0 0 ${W} ${H}" xmlns="http://www.w3.org/2000/svg">`;
  labels.forEach((lbl,i)=>{
    const y  = padT+i*(barH+gap);
    const w  = Math.max(4,(vals[i]/maxV)*(W-padL-padR));
    const wt = Math.max(4,(tVals[i]/maxV)*(W-padL-padR));
    // Label colonna sinistra
    const short = lbl.length>16?lbl.slice(0,15)+'…':lbl;
    svg += `<text x="${padL-10}" y="${y+barH/2+4}" font-size="11" fill="#bbb" text-anchor="end">${short}</text>`;
    // Barra incasso
    svg += `<rect x="${padL}" y="${y+barH*0.1}" width="${w}" height="${barH*0.8}" rx="4" fill="${C[i%C.length]}" opacity=".85"/>`;
    // Linea target
    svg += `<line x1="${padL+wt}" y1="${y}" x2="${padL+wt}" y2="${y+barH}" stroke="#f87171" stroke-width="2" stroke-dasharray="4,3"/>`;
    // Valore a destra
    svg += `<text x="${padL+w+8}" y="${y+barH/2+4}" font-size="11" fill="#888">${fmtE(vals[i])}</text>`;
  });
  svg += '</svg>';
  document.getElementById('cGoal').innerHTML = svg;
}

// ── Kit Counters ─────────────────────────────────────────────────────────────
function renderKitCounters() {
  const stampanti = PRINTERS.stampanti || [];
  const resets    = KIT_RESETS.resets  || {};
  const allRec    = D.records; // usa TUTTI i record, non i filtrati

  const cards = stampanti.map((s, i) => {
    const resetDateStr = resets[s.id] || null;
    const resetDate    = resetDateStr ? new Date(resetDateStr) : null;

    // Conta stampe di questo formato in questa struttura dalla data reset
    const used = allRec
      .filter(r => {
        if (r.Struttura !== s.struttura) return false;
        // confronto flessibile formato (es. "15x20" == "15X20")
        if (r.Formato?.toLowerCase().replace(/\s/g,'') !==
            s.formato?.toLowerCase().replace(/\s/g,'')) return false;
        if (!resetDate) return true;
        const d = new Date(r.Anno, r.Mese - 1, r.Giorno);
        return d >= resetDate;
      })
      .reduce((sum, r) => sum + r.Quantità, 0);

    const remaining = Math.max(0, s.kit_capacita - used);
    const pct       = Math.min(100, (used / s.kit_capacita) * 100);
    const alert     = remaining <= s.alert_soglia;
    const barColor  = alert ? '#f87171' : pct > 70 ? '#facc15' : '#34d399';

    const resetLabel = resetDate
      ? resetDate.toLocaleDateString('it-IT')
      : 'Kit non ancora resettato';

    return `
    <div style="background:#242220;border-radius:12px;padding:14px 16px;
      border-left:4px solid ${alert ? '#f87171' : C[i % C.length]}">
      ${alert ? `<div style="background:#f871711a;color:#f87171;font-size:.75rem;font-weight:600;
        border-radius:6px;padding:5px 10px;margin-bottom:10px;display:inline-block">
        ⚠️ KIT QUASI ESAURITO — rimangono solo ${Math.round(remaining)} stampe!</div>` : ''}
      <div style="display:flex;justify-content:space-between;align-items:flex-start;margin-bottom:10px">
        <div>
          <div style="font-size:.95rem;font-weight:700;color:#fff">${s.nome}</div>
          <div style="font-size:.75rem;color:#555;margin-top:2px">🏖️ ${s.struttura} · 📐 ${s.formato}</div>
        </div>
        <div style="text-align:right">
          <div style="font-size:1.2rem;font-weight:700;color:${alert?'#f87171':'#fff'}">${Math.round(remaining)}</div>
          <div style="font-size:.65rem;color:#444">stampe rimaste</div>
        </div>
      </div>
      <!-- Barra progresso -->
      <div style="background:#2a2926;border-radius:4px;height:8px;margin-bottom:8px;overflow:hidden">
        <div style="width:${pct}%;height:8px;border-radius:4px;background:${barColor};transition:width .4s"></div>
      </div>
      <div style="display:flex;justify-content:space-between;font-size:.68rem;color:#555;margin-bottom:10px">
        <span>Usate: <strong style="color:#ccc">${Math.round(used)}</strong> / ${s.kit_capacita}</span>
        <span>${pct.toFixed(0)}% consumato</span>
      </div>
      <div style="display:flex;justify-content:space-between;align-items:center;flex-wrap:wrap;gap:6px">
        <span style="font-size:.65rem;color:#333">📅 Ultimo reset: ${resetLabel}</span>
        <button onclick="resetKit('${s.id}','${s.nome}','${s.struttura}')"
          style="background:#cc5a2a;color:#fff;border:none;border-radius:8px;
          padding:8px 14px;font-size:.78rem;font-weight:600;cursor:pointer;min-height:36px">
          🔄 Nuovo kit montato
        </button>
      </div>
    </div>`;
  });

  document.getElementById('kitCards').innerHTML =
    cards.length ? cards.join('') :
    '<p style="color:#444;padding:16px;text-align:center">Nessuna stampante configurata in printers.json</p>';
}

function resetKit(printerId, nome, struttura) {
  const today = new Date().toISOString().split('T')[0];
  const ok = confirm(`Confermi il montaggio di un nuovo kit su ${nome} (${struttura})?\n\nIl contatore ripartirà da oggi (${today}).`);
  if (!ok) return;

  const url = `/reset-kit?printer_id=${encodeURIComponent(printerId)}&date=${today}&auth=${encodeURIComponent(_P)}`;
  fetch(url)
  .then(r => r.json())
  .then(data => {
    if (data.ok) {
      alert('✅ Kit resettato! Il contatore è ripartito da oggi.');
      KIT_RESETS.resets[printerId] = today;
      renderKitCounters();
    } else {
      alert('Errore: ' + (data.error || 'sconosciuto'));
    }
  })
  .catch(() => alert('Errore di connessione al server.'));
}

// ── Consumabili ─────────────────────────────────────────────────────────────
function renderConsumabili(rec) {
  // Stampe per formato (Quantità)
  const fmtMap = grp(rec,'Formato','Quantità');
  const fmtK = Object.keys(fmtMap).filter(k=>k&&k!=='undefined').sort((a,b)=>fmtMap[b]-fmtMap[a]);
  const totStampe = fmtK.reduce((s,k)=>s+fmtMap[k],0);
  const totFormati = fmtK.length;

  document.getElementById('cTotStampe').textContent = fmtN(totStampe);
  document.getElementById('cTotFormati').textContent = totFormati;

  // Grafico barre stampe per formato
  svgBar(document.getElementById('cConsFmt'), fmtK, fmtK.map(k=>fmtMap[k]), C, v=>fmtN(v)+' pz');

  // Tabella dettaglio
  const table = document.getElementById('consTable');
  if(!fmtK.length){ table.innerHTML='<p style="color:#333;padding:12px;text-align:center">Nessun dato</p>'; }
  else {
    let html = `<table style="width:100%;border-collapse:collapse;font-size:.82rem">
      <thead>
        <tr style="border-bottom:1px solid #2a2926">
          <th style="text-align:left;padding:7px 6px;color:#555;font-weight:600;text-transform:uppercase;font-size:.65rem;letter-spacing:.4px">Formato</th>
          <th style="text-align:right;padding:7px 6px;color:#555;font-weight:600;text-transform:uppercase;font-size:.65rem;letter-spacing:.4px">Stampe</th>
          <th style="text-align:right;padding:7px 6px;color:#555;font-weight:600;text-transform:uppercase;font-size:.65rem;letter-spacing:.4px">% totale</th>
          <th style="text-align:right;padding:7px 6px;color:#555;font-weight:600;text-transform:uppercase;font-size:.65rem;letter-spacing:.4px">Incasso</th>
        </tr>
      </thead><tbody>`;
    const incMap = grp(rec,'Formato','Prezzo');
    fmtK.forEach((f,i) => {
      const qty = fmtMap[f];
      const pct = totStampe ? (qty/totStampe*100).toFixed(1) : 0;
      const inc = incMap[f]||0;
      const col = C[i%C.length];
      html += `<tr style="border-bottom:1px solid #242220">
        <td style="padding:8px 6px;color:#e0e0e0;display:flex;align-items:center;gap:7px">
          <span style="display:inline-block;width:10px;height:10px;border-radius:3px;background:${col};flex-shrink:0"></span>${f}
        </td>
        <td style="padding:8px 6px;text-align:right;font-weight:700;color:#fff">${fmtN(qty)}</td>
        <td style="padding:8px 6px;text-align:right;color:#888">${pct}%</td>
        <td style="padding:8px 6px;text-align:right;color:#cc5a2a">${fmtE(inc)}</td>
      </tr>`;
    });
    html += `<tr style="border-top:2px solid #2a2926">
      <td style="padding:8px 6px;color:#888;font-weight:600">Totale</td>
      <td style="padding:8px 6px;text-align:right;font-weight:700;color:#fff">${fmtN(totStampe)}</td>
      <td style="padding:8px 6px;text-align:right;color:#888">100%</td>
      <td style="padding:8px 6px;text-align:right;color:#cc5a2a">${fmtE(rec.reduce((s,r)=>s+r.Prezzo,0))}</td>
    </tr></tbody></table>`;
    table.innerHTML = html;
  }

  // Barre stampe per struttura
  const strMap = grp(rec,'Struttura','Quantità');
  const strK = Object.keys(strMap).sort((a,b)=>strMap[b]-strMap[a]);
  svgBar(document.getElementById('cConsStr'), strK, strK.map(k=>strMap[k]), C, v=>fmtN(v)+' pz');
}

// ── Contabilità ──────────────────────────────────────────────────────────────

function cfgFoto(nome) {
  return Object.assign({paga_giornaliera:0, tasse_pct:50, bonus_soglia:0, bonus_pct:0},
    COSTS.fotografi?.[nome] || {});
}
function cfgStr(nome) {
  return Object.assign({canone_totale:0},
    COSTS.strutture?.[nome] || {});
}
// Calcola pagato alla struttura dai bonifici inseriti
function pagatoStr(nome) {
  const anno = getFilterAnno(), mese = getFilterMese();
  return (EXPENSES.spese||[])
    .filter(s => s.categoria==='Canone struttura' && s.struttura===nome &&
      (!anno || (s.data||'').startsWith(anno)) &&
      (!mese || parseInt((s.data||'').split('-')[1])===parseInt(mese)))
    .reduce((t,s)=>t+(parseFloat(s.importo)||0),0);
}

function calcFotoStats(rec, nome) {
  const cfg   = cfgFoto(nome);
  const sub   = rec.filter(r => r.Fotografo === nome);
  const giorni = new Set(sub.map(r => `${r.Anno}-${String(r.Mese).padStart(2,'0')}-${String(r.Giorno).padStart(2,'0')}`)).size;
  const fatturato = sub.reduce((s,r) => s+r.Prezzo, 0);
  const pagaBase  = giorni * cfg.paga_giornaliera;
  const tasse     = pagaBase * (cfg.tasse_pct / 100);
  const costoBase = pagaBase + tasse;
  const bonus     = fatturato > cfg.bonus_soglia && cfg.bonus_pct > 0
                    ? (fatturato - cfg.bonus_soglia) * (cfg.bonus_pct / 100) : 0;
  const costoTot  = costoBase + bonus;
  const utile     = fatturato - costoTot;
  return {nome, giorni, fatturato, pagaBase, tasse, costoBase, bonus, costoTot, utile};
}

function renderContabilita(rec) {
  const strutture = [...new Set(D.records.map(r=>r.Struttura))].sort();
  const fotografi = [...new Set(rec.map(r=>r.Fotografo))].sort();

  // ── KPI globali ──────────────────────────────────────────────────────────
  const fatTot = rec.reduce((s,r)=>s+r.Prezzo,0);
  let costiTot = 0;

  // costi fotografi — FIGURATIVI, non sottratti dalla cassa
  const fotoStats = fotografi.map(f => calcFotoStats(rec, f));
  // canoni strutture — FIGURATIVI, non sottratti dalla cassa (come i fotografi)
  // Solo i bonifici reali inseriti come "Canone struttura" entrano nel P&L

  // spese extra nel periodo (include bonifici reali: stipendi, canoni, ecc.)
  const totSpeseExtra = renderSpeseList(rec);
  costiTot += totSpeseExtra;

  const utile   = fatTot - costiTot;
  const margine = fatTot > 0 ? (utile/fatTot*100) : 0;

  // giorni operativi stimati (giorni distinti con almeno una vendita)
  const giorniOp = new Set(rec.map(r=>`${r.Anno}-${r.Mese}-${r.Giorno}`)).size || 1;
  const breakeven = giorniOp > 0 ? costiTot / giorniOp : 0;

  document.getElementById('plFatturato').textContent = fmtE(fatTot);
  document.getElementById('plCosti').textContent     = fmtE(costiTot);
  document.getElementById('plUtile').textContent     = fmtE(utile);
  document.getElementById('plMargine').textContent   = `margine ${margine.toFixed(1)}%`;
  document.getElementById('plBreakeven').textContent = fmtE(breakeven);
  const utileCard = document.getElementById('plUtileCard');
  utileCard.style.borderColor = utile >= 0 ? '#34d399' : '#f87171';
  document.getElementById('plUtile').style.color = utile >= 0 ? '#34d399' : '#f87171';

  // ── Alert ────────────────────────────────────────────────────────────────
  const alerts = [];
  if(utile < 0) alerts.push(`🔴 <strong>Attenzione: sei in perdita di ${fmtE(Math.abs(utile))}</strong> nel periodo selezionato`);
  fotoStats.forEach(f => {
    if(f.fatturato === 0 && f.giorni === 0) return;
    if(f.utile < 0) alerts.push(`🟠 <strong>${f.nome}</strong> non copre il suo costo — genera ${fmtE(f.fatturato)} ma costa ${fmtE(f.costoTot)}`);
    if(f.giorni > 0 && f.fatturato/f.giorni < breakeven*0.5)
      alerts.push(`🟡 <strong>${f.nome}</strong> produce poco: media ${fmtE(f.fatturato/f.giorni)}/giorno (break-even: ${fmtE(breakeven)})`);
  });
  document.getElementById('contAlerts').innerHTML = alerts.map(a =>
    `<div style="background:#242220;border-left:3px solid #f87171;border-radius:8px;
     padding:10px 14px;margin-bottom:8px;font-size:.82rem;color:#e0e0e0">${a}</div>`
  ).join('');

  // ── P&L per struttura ───────────────────────────────────────────────────
  const strList = [...new Set(rec.map(r=>r.Struttura))].sort();

  // Totali canoni strutture (figurativi)
  const totCanoneAccordato = strList.reduce((t,s)=>t+cfgStr(s).canone_totale,0);
  const totCanonePagato    = strList.reduce((t,s)=>t+pagatoStr(s),0);
  const totCanoneDaPagare  = Math.max(0, totCanoneAccordato - totCanonePagato);

  let strSummary = `
  <div style="display:grid;grid-template-columns:repeat(3,1fr);gap:8px;margin-bottom:14px">
    <div style="background:#2a2926;border-radius:8px;padding:10px 12px;border-left:3px solid #f59e0b">
      <div style="font-size:.62rem;color:#555;text-transform:uppercase;letter-spacing:.4px">🟡 Accordato (figurativo)</div>
      <div style="font-size:1.05rem;font-weight:700;color:#f59e0b;margin-top:3px">${fmtE(totCanoneAccordato)}</div>
    </div>
    <div style="background:#2a2926;border-radius:8px;padding:10px 12px;border-left:3px solid #34d399">
      <div style="font-size:.62rem;color:#555;text-transform:uppercase;letter-spacing:.4px">✅ Bonifici effettuati</div>
      <div style="font-size:1.05rem;font-weight:700;color:#34d399;margin-top:3px">${fmtE(totCanonePagato)}</div>
    </div>
    <div style="background:#2a2926;border-radius:8px;padding:10px 12px;border-left:3px solid #f87171">
      <div style="font-size:.62rem;color:#555;text-transform:uppercase;letter-spacing:.4px">⏳ Da bonificare ancora</div>
      <div style="font-size:1.05rem;font-weight:700;color:#f87171;margin-top:3px">${fmtE(totCanoneDaPagare)}</div>
    </div>
  </div>`;

  let tbl = `<div style="overflow-x:auto"><table style="width:100%;border-collapse:collapse;font-size:.8rem;min-width:580px">
    <thead><tr style="border-bottom:1px solid #2a2926">
      ${['Struttura','Fatturato','🟡 Accordato','✅ Pagato','⏳ Da pagare','📋 Spese extra','Utile cassa','Margine'].map(h=>
        `<th style="padding:8px 6px;color:#555;font-size:.65rem;text-transform:uppercase;
         letter-spacing:.4px;text-align:${h==='Struttura'?'left':'right'}">${h}</th>`).join('')}
    </tr></thead><tbody>`;
  strList.forEach((s,i) => {
    const subR      = rec.filter(r=>r.Struttura===s);
    const fat       = subR.reduce((a,r)=>a+r.Prezzo,0);
    const cStr      = cfgStr(s);
    const accordato = cStr.canone_totale;
    const pagato    = pagatoStr(s);
    const daPagare  = Math.max(0, accordato - pagato);
    // spese extra attribuite a questa struttura (escluso canone già contato)
    const anno = getFilterAnno(), mese = getFilterMese();
    const speseStr  = (EXPENSES.spese||[])
      .filter(sp => sp.struttura===s && sp.categoria!=='Canone struttura' &&
        (!anno || (sp.data||'').startsWith(anno)) &&
        (!mese || parseInt((sp.data||'').split('-')[1])===parseInt(mese)))
      .reduce((t,sp)=>t+(parseFloat(sp.importo)||0),0);
    // utile cassa = fatturato - canone pagato - spese extra attribuite
    const utileS    = fat - pagato - speseStr;
    const marg      = fat>0?(utileS/fat*100):0;
    const col       = utileS>=0?'#34d399':'#f87171';
    tbl += `<tr style="border-bottom:1px solid #242220">
      <td style="padding:8px 6px;color:#fff;font-weight:600">
        <span style="display:inline-block;width:8px;height:8px;border-radius:50%;
          background:${C[i%C.length]};margin-right:6px"></span>${s}</td>
      <td style="padding:8px 6px;text-align:right;color:#e0e0e0">${fmtE(fat)}</td>
      <td style="padding:8px 6px;text-align:right;color:#f59e0b">${fmtE(accordato)}</td>
      <td style="padding:8px 6px;text-align:right;color:#34d399">${fmtE(pagato)}</td>
      <td style="padding:8px 6px;text-align:right;color:#f87171">${fmtE(daPagare)}</td>
      <td style="padding:8px 6px;text-align:right;color:#aaa">${speseStr>0?'−&nbsp;'+fmtE(speseStr):'—'}</td>
      <td style="padding:8px 6px;text-align:right;font-weight:700;color:${col}">${fmtE(utileS)}</td>
      <td style="padding:8px 6px;text-align:right;color:${col}">${marg.toFixed(1)}%</td>
    </tr>`;
  });
  tbl += '</tbody></table></div>';
  document.getElementById('plStrTable').innerHTML = strSummary + tbl;

  // Calcola pagato per fotografo dai bonifici inseriti
  const anno = getFilterAnno(), mese = getFilterMese();
  function pagatoFoto(nome) {
    return (EXPENSES.spese||[])
      .filter(s => s.categoria==='Stipendi fotografi' && s.fotografo===nome &&
        (!anno || (s.data||'').startsWith(anno)) &&
        (!mese || parseInt((s.data||'').split('-')[1])===parseInt(mese)))
      .reduce((t,s)=>t+(parseFloat(s.importo)||0),0);
  }

  // ── Situazione stipendi ───────────────────────────────────────────────────
  const totMaturato = fotoStats.reduce((s,f)=>s+f.costoTot,0);
  const totPagato   = fotoStats.reduce((s,f)=>s+pagatoFoto(f.nome),0);
  const totDaPagare = Math.max(0, totMaturato - totPagato);

  let ftbl = `
  <div style="display:grid;grid-template-columns:repeat(3,1fr);gap:8px;margin-bottom:14px">
    <div style="background:#2a2926;border-radius:8px;padding:10px 12px;border-left:3px solid #e07a52">
      <div style="font-size:.62rem;color:#555;text-transform:uppercase;letter-spacing:.4px">💜 Maturato (figurativo)</div>
      <div style="font-size:1.05rem;font-weight:700;color:#e07a52;margin-top:3px">${fmtE(totMaturato)}</div>
    </div>
    <div style="background:#2a2926;border-radius:8px;padding:10px 12px;border-left:3px solid #34d399">
      <div style="font-size:.62rem;color:#555;text-transform:uppercase;letter-spacing:.4px">✅ Bonifici effettuati</div>
      <div style="font-size:1.05rem;font-weight:700;color:#34d399;margin-top:3px">${fmtE(totPagato)}</div>
    </div>
    <div style="background:#2a2926;border-radius:8px;padding:10px 12px;border-left:3px solid #f87171">
      <div style="font-size:.62rem;color:#555;text-transform:uppercase;letter-spacing:.4px">⏳ Da bonificare ancora</div>
      <div style="font-size:1.05rem;font-weight:700;color:#f87171;margin-top:3px">${fmtE(totDaPagare)}</div>
    </div>
  </div>
  <div style="overflow-x:auto"><table style="width:100%;border-collapse:collapse;font-size:.8rem;min-width:560px">
    <thead><tr style="border-bottom:1px solid #2a2926">
      ${['Fotografo','Giorni','Fatturato','💜 Maturato','Bonus','✅ Pagato','⏳ Da pagare','Produttività'].map(h=>
        `<th style="padding:8px 6px;color:#555;font-size:.65rem;text-transform:uppercase;
         letter-spacing:.4px;text-align:${h==='Fotografo'||h==='Produttività'?'left':'right'}">${h}</th>`
      ).join('')}
    </tr></thead><tbody>`;
  fotoStats.sort((a,b)=>b.fatturato-a.fatturato).forEach((f,i) => {
    const pagato   = pagatoFoto(f.nome);
    const daPagare = Math.max(0, f.costoTot - pagato);
    const prod     = f.costoTot > 0 ? (f.fatturato / f.costoTot) : 0;
    const prodCol  = prod >= 2 ? '#34d399' : prod >= 1 ? '#facc15' : '#f87171';
    const prodLbl  = prod >= 2 ? '🟢 Ottimo' : prod >= 1 ? '🟡 Ok' : '🔴 Sotto soglia';
    ftbl += `<tr style="border-bottom:1px solid #242220">
      <td style="padding:8px 6px;color:#fff;font-weight:600">${['🥇','🥈','🥉'][i]||'  '} ${f.nome}</td>
      <td style="padding:8px 6px;text-align:right;color:#aaa">${f.giorni}</td>
      <td style="padding:8px 6px;text-align:right;color:#e0e0e0">${fmtE(f.fatturato)}</td>
      <td style="padding:8px 6px;text-align:right;color:#e07a52">${fmtE(f.costoTot)}</td>
      <td style="padding:8px 6px;text-align:right;color:#f59e0b">${fmtE(f.bonus)}</td>
      <td style="padding:8px 6px;text-align:right;color:#34d399;font-weight:600">${fmtE(pagato)}</td>
      <td style="padding:8px 6px;text-align:right;color:${daPagare>0?'#f87171':'#34d399'};font-weight:700">${fmtE(daPagare)}</td>
      <td style="padding:8px 6px;color:${prodCol}">${prodLbl}</td>
    </tr>`;
  });
  ftbl += '</tbody></table></div>';
  document.getElementById('plFotoTable').innerHTML = ftbl;

  // ── Config panel fotografi ───────────────────────────────────────────────
  let cfgF = `<div style="overflow-x:auto"><table style="width:100%;border-collapse:collapse;font-size:.82rem;min-width:480px">
    <thead><tr style="border-bottom:1px solid #2a2926">
      ${['Fotografo','Paga/giorno (€)','Tasse %','Soglia bonus (€)','Bonus %'].map(h=>
        `<th style="padding:7px 6px;color:#555;font-size:.65rem;text-transform:uppercase;letter-spacing:.4px;text-align:left">${h}</th>`
      ).join('')}
    </tr></thead><tbody>`;
  [...new Set(D.records.map(r=>r.Fotografo))].sort().forEach(f => {
    const c = cfgFoto(f);
    cfgF += `<tr style="border-bottom:1px solid #242220">
      <td style="padding:7px 6px;color:#ccc;font-weight:600">${f}</td>
      <td style="padding:4px 6px"><input type="number" min="0" step="5" value="${c.paga_giornaliera}"
        data-foto="${f}" data-key="paga_giornaliera" onchange="updateCost(this)"
        style="background:#2a2926;border:1px solid #383530;border-radius:6px;padding:6px 8px;
        color:#e0e0e0;font-size:.82rem;width:90px;outline:none"></td>
      <td style="padding:4px 6px"><input type="number" min="0" max="100" step="1" value="${c.tasse_pct}"
        data-foto="${f}" data-key="tasse_pct" onchange="updateCost(this)"
        style="background:#2a2926;border:1px solid #383530;border-radius:6px;padding:6px 8px;
        color:#e0e0e0;font-size:.82rem;width:70px;outline:none"></td>
      <td style="padding:4px 6px"><input type="number" min="0" step="100" value="${c.bonus_soglia}"
        data-foto="${f}" data-key="bonus_soglia" onchange="updateCost(this)"
        style="background:#2a2926;border:1px solid #383530;border-radius:6px;padding:6px 8px;
        color:#e0e0e0;font-size:.82rem;width:90px;outline:none"></td>
      <td style="padding:4px 6px"><input type="number" min="0" max="100" step="1" value="${c.bonus_pct}"
        data-foto="${f}" data-key="bonus_pct" onchange="updateCost(this)"
        style="background:#2a2926;border:1px solid #383530;border-radius:6px;padding:6px 8px;
        color:#e0e0e0;font-size:.82rem;width:70px;outline:none"></td>
    </tr>`;
  });
  cfgF += '</tbody></table></div>';
  document.getElementById('cfgFotoTable').innerHTML = cfgF;

  // ── Config panel strutture ───────────────────────────────────────────────
  let cfgS = `<div style="overflow-x:auto"><table style="width:100%;border-collapse:collapse;font-size:.82rem">
    <thead><tr style="border-bottom:1px solid #2a2926">
      ${['Struttura','Totale accordato (€)'].map(h=>
        `<th style="padding:7px 6px;color:#555;font-size:.65rem;text-transform:uppercase;letter-spacing:.4px;text-align:left">${h}</th>`
      ).join('')}
    </tr></thead><tbody>`;
  strutture.forEach(s => {
    const c = cfgStr(s);
    cfgS += `<tr style="border-bottom:1px solid #242220">
      <td style="padding:7px 6px;color:#ccc;font-weight:600">${s}</td>
      <td style="padding:4px 6px"><input type="number" min="0" step="100" value="${c.canone_totale}"
        data-str="${s}" data-key="canone_totale" onchange="updateCostStr(this)"
        style="background:#2a2926;border:1px solid #383530;border-radius:6px;padding:6px 8px;
        color:#e0e0e0;font-size:.82rem;width:140px;outline:none"></td>
    </tr>`;
  });
  cfgS += '</tbody></table></div>';
  document.getElementById('cfgStrTable').innerHTML = cfgS;
}

function updateCost(el) {
  const f = el.dataset.foto, k = el.dataset.key;
  if(!COSTS.fotografi) COSTS.fotografi = {};
  if(!COSTS.fotografi[f]) COSTS.fotografi[f] = {paga_giornaliera:0,tasse_pct:50,bonus_soglia:0,bonus_pct:0};
  COSTS.fotografi[f][k] = parseFloat(el.value)||0;
  renderContabilita(filtered());
}
function updateCostStr(el) {
  const s = el.dataset.str, k = el.dataset.key;
  if(!COSTS.strutture) COSTS.strutture = {};
  if(!COSTS.strutture[s]) COSTS.strutture[s] = {canone_mensile:0,altri_costi_mensili:0};
  COSTS.strutture[s][k] = parseFloat(el.value)||0;
  renderContabilita(filtered());
}
// ── Spese Extra ──────────────────────────────────────────────────────────────
const CAT_COLORS = {
  'Consumabili':'#38bdf8','Trasporti':'#f59e0b','Trasferte':'#e07a52',
  'Attrezzatura':'#34d399','Riparazioni':'#f87171',
  'Stipendi fotografi':'#facc15','Bonus / Premio fotografo':'#fbbf24',
  'Stipendi dipendenti':'#e879f9',
  'Tasse e contributi':'#fb923c'
};
function catColor(cat){ return CAT_COLORS[cat]||'#cc5a2a'; }

function toggleCatCustom(sel) {
  const custom   = document.getElementById('spCategoriaCustom');
  const fotoSel  = document.getElementById('spFotografo');
  const strSel   = document.getElementById('spStruttura');
  const strLabel = strSel ? strSel.previousElementSibling : null;
  const needsFoto   = sel.value === '__stipendi__' || sel.value === '__bonus__';
  const needsCanone = sel.value === '__canone__';
  custom.style.display  = sel.value === '__custom__' ? 'block' : 'none';
  fotoSel.style.display = needsFoto ? 'block' : 'none';
  // Per "Canone struttura" la struttura è obbligatoria (evidenzia in giallo)
  if(strSel) strSel.style.borderColor = needsCanone ? '#f59e0b' : '#383530';
  if(strLabel) strLabel.textContent = needsCanone
    ? 'Struttura (obbligatoria)'
    : 'Struttura (opzionale)';
  if(sel.value === '__custom__') custom.focus();
  if(needsFoto) fotoSel.focus();
  if(needsCanone && strSel) strSel.focus();
}

function initSpeseForm() {
  // Popola dropdown strutture
  const sel = document.getElementById('spStruttura');
  if(sel && sel.options.length === 1) {
    D.strutture.forEach(s => {
      const o = document.createElement('option'); o.value=o.textContent=s; sel.appendChild(o);
    });
  }
  // Popola dropdown fotografi
  const fsel = document.getElementById('spFotografo');
  if(fsel && fsel.options.length === 1) {
    [...new Set(D.records.map(r=>r.Fotografo))].sort().forEach(f => {
      const o = document.createElement('option'); o.value=o.textContent=f; fsel.appendChild(o);
    });
  }
  // Data default = oggi
  const di = document.getElementById('spData');
  if(di && !di.value) di.value = new Date().toISOString().split('T')[0];
}

function renderSpeseList(filteredRec) {
  // Filtra spese per periodo selezionato (anno/mese/struttura)
  const anno  = getFilterAnno();
  const mese  = getFilterMese();
  const str   = document.getElementById('fStruttura').value;

  const spese = (EXPENSES.spese || []).filter(s => {
    if(!s.data) return true;
    const [sy,sm] = s.data.split('-');
    if(anno && sy !== anno) return false;
    if(mese && parseInt(sm) !== parseInt(mese)) return false;
    if(str  && s.struttura && s.struttura !== str) return false;
    return true;
  }).sort((a,b) => (b.data||'').localeCompare(a.data||''));

  const totSpese = spese.reduce((s,e)=>s+(parseFloat(e.importo)||0),0);

  if(!spese.length) {
    document.getElementById('speseList').innerHTML =
      `<p style="color:#444;padding:14px;text-align:center;font-size:.82rem">
       Nessuna spesa nel periodo. Aggiungila con il modulo sopra.</p>`;
    return totSpese;
  }

  // Raggruppa per categoria
  const perCat = {};
  spese.forEach(s => { perCat[s.categoria]=(perCat[s.categoria]||0)+(parseFloat(s.importo)||0); });

  let html = `<div style="display:flex;justify-content:space-between;align-items:center;
    margin-bottom:12px;padding-bottom:10px;border-bottom:1px solid #2a2926">
    <span style="font-size:.82rem;color:#888">${spese.length} spese nel periodo</span>
    <span style="font-size:1rem;font-weight:700;color:#f87171">− ${fmtE(totSpese)}</span>
  </div>`;

  // Mini riepilogo per categoria
  html += `<div style="display:flex;flex-wrap:wrap;gap:6px;margin-bottom:12px">`;
  Object.entries(perCat).sort((a,b)=>b[1]-a[1]).forEach(([cat,tot])=>{
    const col = catColor(cat);
    html += `<span style="background:${col}22;color:${col};border:1px solid ${col}44;
      border-radius:20px;padding:3px 10px;font-size:.72rem;font-weight:600">
      ${cat}: ${fmtE(tot)}</span>`;
  });
  html += `</div>`;

  // Lista spese
  spese.forEach(s => {
    const col = CAT_COLORS[s.categoria]||'#cc5a2a';
    const d   = s.data ? new Date(s.data+'T00:00:00').toLocaleDateString('it-IT') : '—';
    html += `<div style="display:flex;justify-content:space-between;align-items:flex-start;
      padding:9px 0;border-bottom:1px solid #242220;gap:8px">
      <div style="flex:1;min-width:0">
        <div style="display:flex;align-items:center;gap:6px;margin-bottom:2px;flex-wrap:wrap">
          <span style="background:${col}33;color:${col};border-radius:10px;
            padding:1px 8px;font-size:.68rem;font-weight:600;white-space:nowrap">${s.categoria}</span>
          ${s.fotografo?`<span style="font-size:.68rem;color:#aaa">👤 ${s.fotografo}</span>`:''}
          ${s.struttura?`<span style="font-size:.68rem;color:#555">🏖️ ${s.struttura}</span>`:''}
        </div>
        <div style="font-size:.82rem;color:#ccc;white-space:nowrap;overflow:hidden;
          text-overflow:ellipsis">${s.descrizione||'—'}</div>
        <div style="font-size:.68rem;color:#444;margin-top:1px">${d}</div>
      </div>
      <div style="display:flex;align-items:center;gap:8px;flex-shrink:0">
        <span style="font-weight:700;color:#f87171;font-size:.92rem">− ${fmtE(parseFloat(s.importo)||0)}</span>
        <button onclick="deleteExpense('${s.id}')"
          style="background:#2a2926;color:#555;border:1px solid #383530;border-radius:6px;
          padding:5px 8px;font-size:.75rem;cursor:pointer;min-height:32px">🗑</button>
      </div>
    </div>`;
  });

  document.getElementById('speseList').innerHTML = html;
  return totSpese;
}

function addExpense() {
  const data      = document.getElementById('spData').value;
  const selCat    = document.getElementById('spCategoria').value;
  const categoria = selCat === '__custom__'
    ? (document.getElementById('spCategoriaCustom').value.trim() || 'Personalizzata')
    : selCat === '__stipendi__' ? 'Stipendi fotografi'
    : selCat === '__bonus__'    ? 'Bonus / Premio fotografo'
    : selCat === '__canone__'   ? 'Canone struttura'
    : selCat;
  const needsFoto   = selCat === '__stipendi__' || selCat === '__bonus__';
  const needsCanone = selCat === '__canone__';
  const fotografo = needsFoto ? document.getElementById('spFotografo').value : '';
  if(needsFoto && !fotografo){ alert('Seleziona il fotografo'); return; }
  const struttura = document.getElementById('spStruttura').value;
  if(needsCanone && !struttura){ alert('Seleziona la struttura per il canone'); return; }
  const importo   = parseFloat(document.getElementById('spImporto').value)||0;
  const descrizione = document.getElementById('spDesc').value.trim();
  if(!importo){ alert('Inserisci un importo valido'); return; }
  const spesa = {
    id: Date.now().toString(36)+Math.random().toString(36).slice(2,6),
    data, categoria, fotografo, struttura, importo, descrizione
  };
  fetch('/add-expense',{
    method:'POST',
    headers:{'Content-Type':'application/json'},
    body:JSON.stringify({auth:_P, spesa})
  }).then(r=>r.json()).then(d=>{
    if(d.ok){
      EXPENSES.spese.push(spesa);
      document.getElementById('spImporto').value='';
      document.getElementById('spDesc').value='';
      renderContabilita(filtered());
    } else alert('Errore: '+(d.error||'sconosciuto'));
  }).catch(()=>alert('Errore connessione'));
}

function deleteExpense(id) {
  if(!confirm('Eliminare questa spesa?')) return;
  fetch('/delete-expense',{
    method:'POST',
    headers:{'Content-Type':'application/json'},
    body:JSON.stringify({auth:_P, id})
  }).then(r=>r.json()).then(d=>{
    if(d.ok){
      EXPENSES.spese = EXPENSES.spese.filter(s=>s.id!==id);
      renderContabilita(filtered());
    } else alert('Errore: '+(d.error||'sconosciuto'));
  }).catch(()=>alert('Errore connessione'));
}

function toggleCostConfig() {
  const p = document.getElementById('costConfigPanel');
  const b = document.getElementById('btnCostConfig');
  const open = p.style.display === 'none';
  p.style.display = open ? 'block' : 'none';
  b.textContent = open ? '⚙️ Configura costi ▴' : '⚙️ Configura costi ▾';
}
function saveCosts() {
  fetch('/save-costs', {
    method: 'POST',
    headers: {'Content-Type':'application/json'},
    body: JSON.stringify({auth: _P, costs: COSTS})
  })
  .then(r=>r.json())
  .then(d=>{
    const msg = document.getElementById('saveMsg');
    if(d.ok){ msg.style.display='block'; setTimeout(()=>msg.style.display='none',4000); }
    else alert('Errore salvataggio: '+(d.error||'sconosciuto'));
  })
  .catch(()=>alert('Errore connessione server'));
}

// ── Presenze & Conversione ───────────────────────────────────────────────────

function initPresForm() {
  const strutture = [...new Set(D.records.map(r=>r.Struttura))].sort();
  const cont = document.getElementById('prStruttureInputs');
  if(!cont) return;
  cont.innerHTML = strutture.map(s => `
    <div>
      <label style="font-size:.65rem;color:#888">${s}</label>
      <input type="number" id="pr_${s.replace(/\s/g,'_')}" min="0" step="1" placeholder="0"
        style="width:100%;background:#2a2926;border:1px solid #383530;border-radius:8px;
        padding:8px 10px;color:#e0e0e0;font-size:.88rem;outline:none;margin-top:3px;min-height:38px"/>
    </div>`).join('');
  // Imposta il lunedì di questa settimana come default
  const now = new Date();
  const dow = now.getDay()||7;
  const lun = new Date(now); lun.setDate(now.getDate()-(dow-1));
  document.getElementById('prLun').value = lun.toISOString().slice(0,10);
  aggiornaLabelSettimana();
}

function aggiornaLabelSettimana() {
  const v = document.getElementById('prLun').value;
  if(!v){ document.getElementById('prSettimanaLabel').textContent=''; return; }
  const lun = new Date(v+'T00:00:00');
  const dow = lun.getDay();
  // Forza al lunedì se l'utente sceglie un giorno diverso
  if(dow !== 1) {
    const offset = dow === 0 ? -6 : -(dow-1);
    lun.setDate(lun.getDate()+offset);
    document.getElementById('prLun').value = lun.toISOString().slice(0,10);
  }
  const dom = new Date(lun); dom.setDate(lun.getDate()+6);
  const fmt = d => d.toLocaleDateString('it-IT',{day:'2-digit',month:'short'});
  document.getElementById('prSettimanaLabel').textContent =
    `📅 ${fmt(lun)} – ${fmt(dom)}`;
}

function savePresenza() {
  const lunVal = document.getElementById('prLun').value;
  if(!lunVal){ alert('Seleziona la settimana'); return; }
  const lun = new Date(lunVal+'T00:00:00');
  const dom = new Date(lun); dom.setDate(lun.getDate()+6);
  const strutture = [...new Set(D.records.map(r=>r.Struttura))].sort();
  const strOspiti = {};
  strutture.forEach(s => {
    const v = parseInt(document.getElementById('pr_'+s.replace(/\s/g,'_')).value)||0;
    if(v>0) strOspiti[s] = v;
  });
  if(!Object.keys(strOspiti).length){ alert('Inserisci almeno una struttura con ospiti > 0'); return; }
  const presenza = {
    id: lunVal,
    lun: lunVal,
    dom: dom.toISOString().slice(0,10),
    strutture: strOspiti
  };
  fetch('/save-presence', {
    method:'POST', headers:{'Content-Type':'application/json'},
    body: JSON.stringify({auth: _P, presenza})
  }).then(r=>r.json()).then(d=>{
    if(d.ok){
      // aggiorna locale
      PRESENCES.presenze = PRESENCES.presenze.filter(p=>p.id!==presenza.id);
      PRESENCES.presenze.push(presenza);
      PRESENCES.presenze.sort((a,b)=>a.lun.localeCompare(b.lun));
      renderPresenze();
    } else alert('Errore: '+(d.error||'sconosciuto'));
  }).catch(()=>alert('Errore connessione'));
}

function deletePresenza(id) {
  if(!confirm('Eliminare questa settimana?')) return;
  fetch('/delete-presence', {
    method:'POST', headers:{'Content-Type':'application/json'},
    body: JSON.stringify({auth: _P, id})
  }).then(r=>r.json()).then(d=>{
    if(d.ok){
      PRESENCES.presenze = PRESENCES.presenze.filter(p=>p.id!==id);
      renderPresenze();
    } else alert('Errore: '+(d.error||'sconosciuto'));
  }).catch(()=>alert('Errore connessione'));
}

function renderPresenze() {
  const box = document.getElementById('presenzeTable');
  if(!box) return;
  const presenze = (PRESENCES.presenze||[]).slice().sort((a,b)=>b.lun.localeCompare(a.lun));
  if(!presenze.length){
    box.innerHTML = `<div style="color:#555;font-size:.82rem;text-align:center;padding:20px">
      Nessuna presenza inserita. Usa il modulo sopra per aggiungere la prima settimana.</div>`;
    return;
  }
  const strutture = [...new Set(D.records.map(r=>r.Struttura))].sort();
  let html = `<div style="overflow-x:auto"><table style="width:100%;border-collapse:collapse;font-size:.78rem;min-width:700px">
    <thead><tr style="border-bottom:1px solid #2a2926">
      <th style="padding:8px 6px;color:#555;font-size:.62rem;text-transform:uppercase;letter-spacing:.4px;text-align:left">Settimana</th>
      <th style="padding:8px 6px;color:#555;font-size:.62rem;text-transform:uppercase;letter-spacing:.4px;text-align:left">Struttura</th>
      <th style="padding:8px 6px;color:#555;font-size:.62rem;text-transform:uppercase;letter-spacing:.4px;text-align:right" title="Ospiti presenti in struttura">Ospiti</th>
      <th style="padding:8px 6px;color:#555;font-size:.62rem;text-transform:uppercase;letter-spacing:.4px;text-align:right" title="Famiglie fotografate (cartelle create)">Cartelle</th>
      <th style="padding:8px 6px;color:#555;font-size:.62rem;text-transform:uppercase;letter-spacing:.4px;text-align:right" title="Cartelle create / Ospiti">Coinvolg.%</th>
      <th style="padding:8px 6px;color:#555;font-size:.62rem;text-transform:uppercase;letter-spacing:.4px;text-align:right" title="Famiglie che hanno acquistato / Cartelle create">Convers.%</th>
      <th style="padding:8px 6px;color:#555;font-size:.62rem;text-transform:uppercase;letter-spacing:.4px;text-align:right" title="Incasso medio per cartella venduta">€/cartella</th>
      <th style="padding:8px 6px;width:30px"></th>
    </tr></thead><tbody>`;

  presenze.forEach(p => {
    const lun = new Date(p.lun+'T00:00:00');
    const dom = new Date(p.dom+'T00:00:00');
    const fmt = d => d.toLocaleDateString('it-IT',{day:'2-digit',month:'short'});
    const settLabel = `${fmt(lun)} – ${fmt(dom)}`;
    // Filtra record della settimana
    const recsSettimana = D.records.filter(r => {
      const dt = new Date(r.Anno, r.Mese-1, r.Giorno);
      return dt >= lun && dt <= dom;
    });
    const strutturePresenti = Object.keys(p.strutture);
    const rowspan = strutturePresenti.length;
    strutturePresenti.forEach((s, i) => {
      const ospiti = p.strutture[s] || 0;
      const recsStr = recsSettimana.filter(r=>r.Struttura===s);
      // Cartelle create = set unico di Camera non vuoti
      const cartelleSet = new Set(recsStr.map(r=>r.Camera).filter(c=>c));
      const cartelle = cartelleSet.size || 0;
      // Famiglie che hanno acquistato = Camera con almeno un Prezzo > 0
      const famiglieAcq = new Set(recsStr.filter(r=>r.Camera&&r.Prezzo>0).map(r=>r.Camera)).size;
      const fatturato = recsStr.reduce((t,r)=>t+r.Prezzo,0);
      // Tassi
      const coinv    = ospiti > 0 && cartelle > 0 ? (cartelle/ospiti*100) : 0;
      const conv     = cartelle > 0 ? (famiglieAcq/cartelle*100) : 0;
      const eurCart  = famiglieAcq > 0 ? (fatturato/famiglieAcq) : 0;
      const coinvCol = coinv >= 60 ? '#34d399' : coinv >= 30 ? '#facc15' : coinv > 0 ? '#f87171' : '#555';
      const convCol  = conv  >= 50 ? '#34d399' : conv  >= 25 ? '#facc15' : conv  > 0 ? '#f87171' : '#555';
      html += `<tr style="border-bottom:1px solid #242220">`;
      if(i === 0) {
        html += `<td rowspan="${rowspan}" style="padding:8px 6px;color:#aaa;vertical-align:top;white-space:nowrap">${settLabel}</td>`;
      }
      html += `
        <td style="padding:8px 6px;color:#e0e0e0">${s}</td>
        <td style="padding:8px 6px;text-align:right;color:#aaa">${fmtN(ospiti)}</td>
        <td style="padding:8px 6px;text-align:right;color:#e0e0e0">${fmtN(cartelle)}</td>
        <td style="padding:8px 6px;text-align:right;font-weight:600;color:${coinvCol}">${coinv>0?coinv.toFixed(1)+'%':'—'}</td>
        <td style="padding:8px 6px;text-align:right;font-weight:700;color:${convCol}">${conv>0?conv.toFixed(1)+'%':'—'}</td>
        <td style="padding:8px 6px;text-align:right;color:#38bdf8">${eurCart>0?fmtE(eurCart):'—'}</td>`;
      if(i === 0) {
        html += `<td rowspan="${rowspan}" style="padding:8px 6px;vertical-align:top;text-align:center">
          <button onclick="deletePresenza('${p.id}')"
            style="background:none;border:none;color:#444;cursor:pointer;font-size:.9rem"
            title="Elimina settimana">🗑️</button></td>`;
      }
      html += `</tr>`;
    });
  });
  html += '</tbody></table></div>';
  // Mini-legenda
  html += `<div style="margin-top:10px;font-size:.7rem;color:#555;display:flex;gap:16px;flex-wrap:wrap">
    <span>📐 <b style="color:#aaa">Coinvolg.%</b> = Cartelle create ÷ Ospiti × 100</span>
    <span>🎯 <b style="color:#aaa">Convers.%</b> = Famiglie che comprano ÷ Cartelle create × 100</span>
    <span>💰 <b style="color:#aaa">€/cartella</b> = Incasso ÷ Famiglie acquirenti</span>
  </div>`;
  box.innerHTML = html;
}

// ── Ricerca Rapida ───────────────────────────────────────────────────────────
const SUGGERIMENTI = [
  'quanto ha incassato [fotografo] questa settimana',
  'quanto ha incassato [fotografo] questo mese',
  'quanto ha incassato [fotografo] oggi',
  'quante foto ha venduto [fotografo] questa settimana',
  'chi ha venduto di più oggi',
  'chi ha venduto di più questa settimana',
  'chi ha venduto di più questo mese',
  'totale incasso [struttura] questo mese',
  'totale incasso [struttura] questa settimana',
  'quante stampe [struttura] questo mese',
  'miglior fotografo di agosto',
  'confronta fotografi questo mese',
];

const MESI_NOMI = {
  'gennaio':1,'febbraio':2,'marzo':3,'aprile':4,'maggio':5,'giugno':6,
  'luglio':7,'agosto':8,'settembre':9,'ottobre':10,'novembre':11,'dicembre':12
};

// ── Helper periodo ───────────────────────────────────────────────────────────
function _trovaMese(q) {
  for(const [nome, num] of Object.entries(MESI_NOMI)) if(q.includes(nome)) return {nome, num};
  return null;
}
function _ultimoGiorno(anno, mese) { return new Date(anno, mese, 0).getDate(); }
function _annoQ(q, fallback) { const m=q.match(/\b(20\d{2})\b/); return m ? parseInt(m[1]) : fallback; }
function _settimanaNum(q) {
  if(q.includes('ultim'))                                           return -1;
  if(q.includes('quart') || /\b4[°a]?\b/.test(q))                  return 4;
  if(q.includes('terz')  || /\b3[°a]?\b/.test(q))                  return 3;
  if(q.includes('second')|| /\b2[°a]?\b/.test(q))                  return 2;
  if(q.includes('prim')  || /\b1[°a]?\b/.test(q))                  return 1;
  return null;
}
// Restituisce array di settimane lun-dom [{da, a}] per il mese dato
// La "prima settimana" è quella che contiene il giorno 1 (può partire dal mese precedente)
function _settimaneMese(anno, mese) {
  const ultG = _ultimoGiorno(anno, mese);
  const d1 = new Date(anno, mese-1, 1);
  const dow1 = d1.getDay(); // 0=dom,1=lun,...,6=sab
  const offsetLun = dow1 === 0 ? -6 : -(dow1 - 1); // giorni al lunedì di quella settimana
  const settimane = [];
  let g = 1 + offsetLun; // primo lunedì (può essere <= 0 = appartiene al mese precedente)
  while(g <= ultG) {
    settimane.push({ da: Math.max(g, 1), a: Math.min(g + 6, ultG) });
    g += 7;
  }
  return settimane;
}

function parsePeriodo(q) {
  const now = new Date();
  const y = now.getFullYear(), m = now.getMonth()+1, d = now.getDate();

  if(q.includes('oggi'))
    return r => r.Anno==y && r.Mese==m && r.Giorno==d;

  if(q.includes('ieri')) {
    const ieri = new Date(now); ieri.setDate(d-1);
    return r => r.Anno==ieri.getFullYear() && r.Mese==ieri.getMonth()+1 && r.Giorno==ieri.getDate();
  }

  // Ferragosto = settimana del 15 agosto (lun-dom)
  if(q.includes('ferragosto')) {
    const fy = _annoQ(q, y);
    const fg = new Date(fy, 7, 15);
    const lunFg = new Date(fg); lunFg.setDate(fg.getDate() - ((fg.getDay()||7)-1));
    const domFg = new Date(lunFg); domFg.setDate(lunFg.getDate()+6);
    return r => { const dt=new Date(r.Anno,r.Mese-1,r.Giorno); return dt>=lunFg && dt<=domFg; };
  }

  // "ultimi N giorni"
  const ultGiorniM = q.match(/ultim[io]\s+(\d+)\s+giorn/);
  if(ultGiorniM) {
    const n = parseInt(ultGiorniM[1]);
    const da = new Date(now); da.setDate(d - n + 1); da.setHours(0,0,0,0);
    return r => { const dt=new Date(r.Anno,r.Mese-1,r.Giorno); return dt>=da && dt<=now; };
  }

  if(q.includes('questa settimana') || q.includes('settimana corrente')) {
    const lun = new Date(now); lun.setDate(d - ((now.getDay()||7)-1)); lun.setHours(0,0,0,0);
    return r => { const dt=new Date(r.Anno,r.Mese-1,r.Giorno); return dt>=lun && dt<=now; };
  }
  if(q.includes('settimana scorsa')) {
    const lun = new Date(now); lun.setDate(d - ((now.getDay()||7)-1) - 7);
    const dom = new Date(lun); dom.setDate(lun.getDate()+6);
    return r => { const dt=new Date(r.Anno,r.Mese-1,r.Giorno); return dt>=lun && dt<=dom; };
  }

  // "[prima/seconda/terza/quarta/ultima] settimana di [mese] [anno]" — settimane reali lun-dom
  if(q.includes('settimana')) {
    const mes = _trovaMese(q);
    const nSett = _settimanaNum(q);
    if(mes !== null && nSett !== null) {
      const fy = _annoQ(q, y);
      const setts = _settimaneMese(fy, mes.num);
      const s = nSett === -1 ? setts[setts.length-1] : setts[nSett-1];
      if(s) return r => r.Anno==fy && r.Mese==mes.num && r.Giorno>=s.da && r.Giorno<=s.a;
    }
  }

  // "weekend" / "fine settimana" di un mese
  if(q.includes('weekend') || q.includes('fine settimana')) {
    const mes = _trovaMese(q);
    const fy = _annoQ(q, y);
    const tm = mes ? mes.num : m;
    const ultG = _ultimoGiorno(fy, tm);
    const weekend = [];
    for(let g=1; g<=ultG; g++) {
      const dow = new Date(fy, tm-1, g).getDay();
      if(dow===6 || dow===0) weekend.push(g);
    }
    if(q.includes('ultim')) {
      const ultWe = weekend.slice(-2);
      return r => r.Anno==fy && r.Mese==tm && ultWe.includes(r.Giorno);
    }
    const primoWe = weekend.slice(0,2);
    return r => r.Anno==fy && r.Mese==tm && primoWe.includes(r.Giorno);
  }

  // "inizio mese" / "fine mese"
  if(q.includes('inizio') || q.includes('primi giorni')) {
    const mes = _trovaMese(q); const fy = _annoQ(q, y);
    const tm = mes ? mes.num : m;
    return r => r.Anno==fy && r.Mese==tm && r.Giorno<=10;
  }
  if(q.includes('fine mese') || q.includes('fine del mese') || q.includes('ultimi giorni')) {
    const mes = _trovaMese(q); const fy = _annoQ(q, y);
    const tm = mes ? mes.num : m;
    const ultG = _ultimoGiorno(fy, tm);
    return r => r.Anno==fy && r.Mese==tm && r.Giorno>=(ultG-9);
  }

  if(q.includes('questo mese') || q.includes('mese corrente'))
    return r => r.Anno==y && r.Mese==m;
  if(q.includes('mese scorso')) {
    const pm = m===1?12:m-1, py = m===1?y-1:y;
    return r => r.Anno==py && r.Mese==pm;
  }
  if(q.includes("quest'anno") || q.includes('questo anno'))
    return r => r.Anno==y;

  // Mese + anno specifici
  const mes = _trovaMese(q);
  if(mes) {
    const fy = _annoQ(q, null);
    if(fy) return r => r.Mese==mes.num && r.Anno==fy;
    return r => r.Mese==mes.num;
  }
  const fy2 = _annoQ(q, null);
  if(fy2) return r => r.Anno==fy2;
  return null;
}

function periodoLabel(q) {
  const now = new Date();
  const y = now.getFullYear();
  if(q.includes('oggi')) return 'oggi';
  if(q.includes('ieri')) return 'ieri';
  if(q.includes('ferragosto')) return `settimana Ferragosto ${_annoQ(q,y)}`;
  const ultGM = q.match(/ultim[io]\s+(\d+)\s+giorn/);
  if(ultGM) return `ultimi ${ultGM[1]} giorni`;
  if(q.includes('questa settimana')||q.includes('settimana corrente')) return 'questa settimana';
  if(q.includes('settimana scorsa')) return 'settimana scorsa';
  if(q.includes('settimana')) {
    const mes = _trovaMese(q); const nSett = _settimanaNum(q); const fy = _annoQ(q,y);
    if(mes && nSett !== null) {
      const lbl = nSett===-1 ? 'ultima' : ['prima','seconda','terza','quarta'][nSett-1]||`${nSett}ª`;
      return `${lbl} settimana di ${mes.nome} ${fy}`;
    }
  }
  if(q.includes('weekend')||q.includes('fine settimana')) {
    const mes = _trovaMese(q); const fy = _annoQ(q,y);
    const wlbl = q.includes('ultim') ? 'ultimo' : 'primo';
    return `${wlbl} weekend ${mes ? 'di '+mes.nome : ''} ${fy}`;
  }
  if(q.includes('inizio')||q.includes('primi giorni')) {
    const mes = _trovaMese(q); return `inizio ${mes ? mes.nome : 'mese'}`;
  }
  if(q.includes('fine mese')||q.includes('ultimi giorni')) {
    const mes = _trovaMese(q); return `fine ${mes ? mes.nome : 'mese'}`;
  }
  if(q.includes('questo mese')||q.includes('mese corrente'))
    return MESI_FULL[now.getMonth()]+' '+y;
  if(q.includes('mese scorso')) {
    const pm=now.getMonth()===0?11:now.getMonth()-1;
    return MESI_FULL[pm]+' '+(now.getMonth()===0?y-1:y);
  }
  const mes = _trovaMese(q);
  if(mes) { const fy=_annoQ(q,null); return mes.nome+(fy?' '+fy:''); }
  const fy=_annoQ(q,null); if(fy) return String(fy);
  return 'tutto il periodo';
}
const MESI_FULL=['Gennaio','Febbraio','Marzo','Aprile','Maggio','Giugno',
                 'Luglio','Agosto','Settembre','Ottobre','Novembre','Dicembre'];

function doSearch() {
  const q = document.getElementById('searchQ').value.toLowerCase().trim();
  document.getElementById('searchSuggest').style.display='none';
  if(!q){ clearSearch(); return; }

  const periodoFn  = parsePeriodo(q);
  const periodoLbl = periodoLabel(q);

  // Filtra per periodo
  let recs = periodoFn ? D.records.filter(periodoFn) : D.records;

  // Trova fotografo — prima match esatto, poi parziale (min 3 caratteri)
  const foto = D.fotografi.find(f => q.includes(f.toLowerCase()))
    || D.fotografi.find(f => {
        const words = q.split(/\s+/).filter(w=>w.length>=3);
        return words.some(w => f.toLowerCase().includes(w));
      });
  // Trova struttura — prima match esatto, poi parziale
  const str = D.strutture.find(s => q.includes(s.toLowerCase()))
    || D.strutture.find(s => {
        const words = q.split(/\s+/).filter(w=>w.length>=3);
        return words.some(w => s.toLowerCase().includes(w));
      });

  // Applica filtri
  if(foto) recs = recs.filter(r => r.Fotografo===foto);
  if(str)  recs = recs.filter(r => r.Struttura===str);

  const incasso = recs.reduce((s,r)=>s+r.Prezzo,0);
  const qty     = recs.reduce((s,r)=>s+r.Quantità,0);
  const giorni  = new Set(recs.map(r=>`${r.Anno}-${r.Mese}-${r.Giorno}`)).size;
  const nRec    = recs.length;

  let html = '';

  // ── CHI HA VENDUTO DI PIÙ ──────────────────────────────────────────────
  if(q.includes('chi ha venduto') || q.includes('migliore') || q.includes('miglior fotografo')) {
    const byFoto = {};
    recs.forEach(r=>{ byFoto[r.Fotografo]=(byFoto[r.Fotografo]||0)+r.Prezzo; });
    const sorted = Object.entries(byFoto).sort((a,b)=>b[1]-a[1]);
    if(!sorted.length){ html=`<span style="color:#555">Nessun dato per ${periodoLbl}</span>`; }
    else {
      html = `<div style="font-size:.82rem;color:#888;margin-bottom:8px">🏆 Classifica <strong style="color:#fff">${periodoLbl}</strong></div>`;
      sorted.slice(0,5).forEach(([f,v],i)=>{
        const med=['🥇','🥈','🥉'][i]||`${i+1}.`;
        html+=`<div style="display:flex;justify-content:space-between;padding:5px 0;
          border-bottom:1px solid #2a2926;font-size:.85rem">
          <span style="color:#ccc">${med} ${f}</span>
          <span style="color:#cc5a2a;font-weight:700">${fmtE(v)}</span></div>`;
      });
    }
  }
  // ── QUANTE FOTO / STAMPE ───────────────────────────────────────────────
  else if(q.includes('quante foto')||q.includes('quante stampe')||q.includes('stampe')) {
    const sogg = foto||str||'tutto';
    html = `<div style="font-size:.82rem;color:#888;margin-bottom:6px">
      🖼️ Stampe vendute — <strong style="color:#fff">${sogg}</strong> · ${periodoLbl}</div>
      <div style="font-size:1.6rem;font-weight:700;color:#38bdf8">${fmtN(qty)} pz</div>
      <div style="font-size:.75rem;color:#555;margin-top:4px">${nRec} transazioni · ${giorni} giorn${giorni===1?'o':'i'}</div>`;
    // Breakdown per formato
    if(!foto&&!str || str) {
      const fmtMap={};
      recs.forEach(r=>{fmtMap[r.Formato]=(fmtMap[r.Formato]||0)+r.Quantità;});
      const top=Object.entries(fmtMap).sort((a,b)=>b[1]-a[1]).slice(0,4);
      if(top.length>1){
        html+=`<div style="margin-top:8px;font-size:.75rem;color:#555">
          ${top.map(([f,v])=>`<span style="margin-right:10px">${f}: <strong style="color:#ccc">${fmtN(v)}</strong></span>`).join('')}
        </div>`;
      }
    }
  }
  // ── CONFRONTA FOTOGRAFI ────────────────────────────────────────────────
  else if(q.includes('confronta')||q.includes('paragona')) {
    const byFoto={};
    recs.forEach(r=>{byFoto[r.Fotografo]=(byFoto[r.Fotografo]||0)+r.Prezzo;});
    const sorted=Object.entries(byFoto).sort((a,b)=>b[1]-a[1]);
    const max=sorted[0]?.[1]||1;
    html=`<div style="font-size:.82rem;color:#888;margin-bottom:8px">📊 Confronto fotografi · <strong style="color:#fff">${periodoLbl}</strong></div>`;
    sorted.forEach(([f,v],i)=>{
      const pct=v/max*100;
      html+=`<div style="margin-bottom:6px">
        <div style="display:flex;justify-content:space-between;font-size:.8rem;margin-bottom:2px">
          <span style="color:#ccc">${f}</span><span style="color:#cc5a2a">${fmtE(v)}</span></div>
        <div style="background:#2a2926;border-radius:3px;height:6px">
          <div style="width:${pct}%;height:6px;border-radius:3px;background:${C[i%C.length]}"></div></div></div>`;
    });
  }
  // ── INCASSO GENERICO ───────────────────────────────────────────────────
  else {
    const sogg = foto ? `📸 ${foto}` : str ? `🏖️ ${str}` : '📊 Totale';
    const mediaGiorno = giorni>0 ? incasso/giorni : 0;
    html = `<div style="font-size:.82rem;color:#888;margin-bottom:6px">
      ${sogg} · <strong style="color:#fff">${periodoLbl}</strong></div>
      <div style="font-size:1.8rem;font-weight:700;color:#cc5a2a">${fmtE(incasso)}</div>
      <div style="display:flex;gap:16px;margin-top:8px;font-size:.75rem;color:#555;flex-wrap:wrap">
        <span>📦 ${fmtN(qty)} stampe</span>
        <span>🔄 ${nRec} transazioni</span>
        <span>📅 ${giorni} giorn${giorni===1?'o':'i'}</span>
        ${giorni>1?`<span>📈 media ${fmtE(mediaGiorno)}/giorno</span>`:''}
      </div>`;
    // Se fotografo: aggiungi confronto con periodo precedente se possibile
    if(foto && giorni>0) {
      const byStr={};
      recs.forEach(r=>{byStr[r.Struttura]=(byStr[r.Struttura]||0)+r.Prezzo;});
      const topStr=Object.entries(byStr).sort((a,b)=>b[1]-a[1])[0];
      if(topStr) html+=`<div style="margin-top:6px;font-size:.75rem;color:#555">
        🏆 Struttura top: <strong style="color:#ccc">${topStr[0]}</strong> ${fmtE(topStr[1])}</div>`;
    }
  }

  const res = document.getElementById('searchResult');
  res.innerHTML = html || `<span style="color:#555">Nessun risultato per "${q}"</span>`;
  res.style.display = 'block';
}

function searchLive(val) {
  const q = val.toLowerCase().trim();
  const sug = document.getElementById('searchSuggest');
  if(q.length < 2){ sug.style.display='none'; return; }

  // Genera suggerimenti personalizzati con nomi reali
  const examples = [];
  D.fotografi.slice(0,3).forEach(f => {
    examples.push(`quanto ha incassato ${f} questa settimana`);
    examples.push(`quanto ha incassato ${f} questo mese`);
    if(q.split(' ').some(w=>f.toLowerCase().startsWith(w)&&w.length>2))
      examples.unshift(`quanto ha incassato ${f} oggi`);
  });
  D.strutture.slice(0,3).forEach(s => {
    examples.push(`totale incasso ${s} questo mese`);
  });
  examples.push('chi ha venduto di più questa settimana');
  examples.push('chi ha venduto di più oggi');
  examples.push('confronta fotografi questo mese');

  // Trova nomi parziali nella query e sostituiscili con quelli completi nei suggerimenti
  const fotoMatch = D.fotografi.find(f=>q.split(/\s+/).some(w=>w.length>=2&&f.toLowerCase().includes(w)));
  const strMatch  = D.strutture.find(s=>q.split(/\s+/).some(w=>w.length>=2&&s.toLowerCase().includes(w)));

  const matches = examples
    .map(e => fotoMatch ? e.replace(/\[fotografo\]/gi, fotoMatch) : e)
    .map(e => strMatch  ? e.replace(/\[struttura\]/gi,  strMatch)  : e)
    .filter(e => {
      const words = q.split(/\s+/).filter(w=>w.length>1);
      return words.some(w => e.toLowerCase().includes(w));
    }).slice(0,5);

  if(!matches.length){ sug.style.display='none'; return; }
  sug.innerHTML = matches.map(m =>
    `<div onclick="document.getElementById('searchQ').value='${m}';doSearch()"
      style="padding:10px 14px;cursor:pointer;font-size:.82rem;color:#aaa;
      border-bottom:1px solid #242220"
      onmouseover="this.style.background='#2a2926'" onmouseout="this.style.background=''">${m}</div>`
  ).join('');
  sug.style.display='block';
}

function clearSearch() {
  document.getElementById('searchQ').value='';
  document.getElementById('searchResult').style.display='none';
  document.getElementById('searchSuggest').style.display='none';
}

// Chiudi suggerimenti cliccando fuori
document.addEventListener('click', e=>{
  if(!document.getElementById('searchWrap').contains(e.target))
    document.getElementById('searchSuggest').style.display='none';
});

// ── Tab switcher ────────────────────────────────────────────────────────────
function showTab(n) {
  document.querySelectorAll('.tab').forEach((t,i)=>t.classList.toggle('on',i===n));
  document.querySelectorAll('.pane').forEach((p,i)=>p.classList.toggle('on',i===n));
  if(n===7) { renderPostazioniStato(); renderExifControllo(); renderLandingStats(); }
}

// ── Gestione Utenti (admin) ──────────────────────────────────────────────────
function initUStruttureCheck() {
  const cont = document.getElementById('uStruttureCheck');
  if(!cont) return;
  cont.innerHTML = D.strutture.map(s => `
    <label style="display:flex;align-items:center;gap:8px;background:#2a2926;border-radius:8px;
      padding:9px 12px;cursor:pointer;border:1px solid #383530">
      <input type="checkbox" value="${s}"
        style="width:16px;height:16px;accent-color:#cc5a2a;cursor:pointer;flex-shrink:0">
      <span style="font-size:.82rem;color:#ccc">${s}</span>
    </label>`).join('');
}

function saveUser() {
  const username = document.getElementById('uUsername').value.trim().replace(/\s+/g,'_');
  const nome     = document.getElementById('uNome').value.trim();
  const password = document.getElementById('uPassword').value.trim();
  const ruolo    = document.getElementById('uRuolo').value.trim();
  if(!username){ alert('Inserisci uno username'); return; }
  if(!password){ alert('Inserisci una password'); return; }
  const strutture = [...document.querySelectorAll('#uStruttureCheck input:checked')].map(c=>c.value);
  if(!strutture.length){ alert('Seleziona almeno una struttura'); return; }
  const perms = {
    strutture:       document.getElementById('perm_strutture').checked,
    fotografi:       document.getElementById('perm_fotografi').checked,
    obiettivi:       document.getElementById('perm_obiettivi').checked,
    consumabili:     document.getElementById('perm_consumabili').checked,
    contabilita:     document.getElementById('perm_contabilita').checked,
    presenze:        document.getElementById('perm_presenze').checked,
    input_presenze:  document.getElementById('perm_input_presenze').checked,
    edit_spese:      document.getElementById('perm_edit_spese').checked,
    alerts:          document.getElementById('perm_alerts').checked,
    agenda:          document.getElementById('perm_agenda').checked,
  };
  const user = { username, nome: nome||username, password, ruolo, strutture, perms, can_input_presenze: perms.input_presenze };
  fetch('/save-user', {
    method:'POST', headers:{'Content-Type':'application/json'},
    body: JSON.stringify({auth:_P, user})
  }).then(r=>r.json()).then(d=>{
    if(d.ok){
      USERS.users = USERS.users.filter(u=>u.username!==username);
      USERS.users.push(user);
      renderUsers();
      document.getElementById('uUsername').value='';
      document.getElementById('uNome').value='';
      document.getElementById('uPassword').value='';
      document.getElementById('uRuolo').value='';
      document.querySelectorAll('#uStruttureCheck input').forEach(c=>c.checked=false);
      ['perm_strutture','perm_fotografi','perm_obiettivi','perm_consumabili','perm_contabilita',
       'perm_presenze','perm_input_presenze','perm_edit_spese','perm_alerts','perm_agenda'].forEach(id=>{
        const el=document.getElementById(id);
        if(el) el.checked=['perm_strutture','perm_fotografi','perm_obiettivi','perm_presenze','perm_input_presenze'].includes(id);
      });
      alert(`✅ Utente "${username}" salvato!\nLa sua dashboard sarà disponibile al link:\ndashboard_${username}.html`);
    } else alert('Errore: '+(d.error||'sconosciuto'));
  }).catch(()=>alert('Errore connessione server'));
}

function deleteUser(username) {
  if(!confirm(`Eliminare l'utente "${username}"?\nVerra eliminata anche la sua dashboard.`)) return;
  fetch('/delete-user', {
    method:'POST', headers:{'Content-Type':'application/json'},
    body: JSON.stringify({auth:_P, username})
  }).then(r=>r.json()).then(d=>{
    if(d.ok){
      USERS.users = USERS.users.filter(u=>u.username!==username);
      renderUsers();
    } else alert('Errore: '+(d.error||'sconosciuto'));
  }).catch(()=>alert('Errore connessione server'));
}

function renderUsers() {
  const box = document.getElementById('usersTable');
  if(!box) return;
  const users = USERS.users||[];
  if(!users.length){
    box.innerHTML = `<p style="color:#555;font-size:.82rem;text-align:center;padding:20px">
      Nessun utente creato. Usa il modulo sopra per aggiungere il primo utente.</p>`;
    return;
  }
  let html = `<table style="width:100%;border-collapse:collapse;font-size:.82rem">
    <thead><tr style="border-bottom:1px solid #2a2926">
      ${['Username','Nome','Ruolo','Strutture assegnate','Dashboard',''].map(h=>
        `<th style="padding:8px 6px;color:#555;font-size:.62rem;text-transform:uppercase;
          letter-spacing:.4px;text-align:left">${h}</th>`).join('')}
    </tr></thead><tbody>`;
  users.forEach((u,i) => {
    const col = ['#cc5a2a','#e07a52','#34d399','#f59e0b','#38bdf8'][i%5];
    html += `<tr style="border-bottom:1px solid #242220">
      <td style="padding:9px 6px">
        <span style="display:inline-flex;align-items:center;justify-content:center;
          width:28px;height:28px;border-radius:50%;background:${col}22;
          color:${col};font-size:.75rem;font-weight:700;margin-right:8px">
          ${(u.nome||u.username).charAt(0).toUpperCase()}</span>
        <strong style="color:#fff">@${u.username}</strong>
      </td>
      <td style="padding:9px 6px;color:#aaa">${u.nome||'—'}</td>
      <td style="padding:9px 6px;color:#666;font-size:.75rem">${u.ruolo||'—'}</td>
      <td style="padding:9px 6px">
        ${(u.strutture||[]).map(s=>`<span style="background:#cc5a2a22;color:#cc5a2a;
          border-radius:10px;padding:2px 8px;font-size:.7rem;margin:1px 2px;display:inline-block">${s}</span>`).join('')||'<span style="color:#444">—</span>'}
        <div style="margin-top:4px">
          ${[['strutture','🏖️'],['fotografi','👤'],['obiettivi','🎯'],['consumabili','🖨️'],
             ['contabilita','💼'],['presenze','👥'],['input_presenze','📝'],['edit_spese','🧾'],['alerts','🔔'],['agenda','📅']
            ].map(([k,emoji])=>(u.perms||{})[k]
              ?`<span style="font-size:.65rem;margin:1px 2px;display:inline-block" title="${k}">${emoji}</span>`
              :'').join('')}
        </div>
      </td>
      <td style="padding:9px 6px">
        <a href="dashboard_${u.username}.html" target="_blank"
          style="color:#38bdf8;font-size:.8rem;font-weight:600;text-decoration:none">🔗 Apri dashboard</a>
      </td>
      <td style="padding:9px 6px">
        <button onclick="deleteUser('${u.username}')"
          style="background:#f871711a;color:#f87171;border:1px solid #f8717133;border-radius:6px;
          padding:6px 10px;font-size:.75rem;cursor:pointer;min-height:32px">🗑 Elimina</button>
      </td>
    </tr>`;
  });
  html += '</tbody></table>';
  box.innerHTML = html;
}

function initUsersPanel() {
  initUStruttureCheck();
  renderUsers();
}

// ── Log Accessi ──────────────────────────────────────────────────────────────
function renderAccessLog(){
  const box=document.getElementById('accessLogTable');
  if(!box) return;
  const accessi=(ACCESS_LOG.accessi||[]).slice().reverse(); // più recenti prima
  if(!accessi.length){
    box.innerHTML='<div style="color:#555;font-size:.82rem;text-align:center;padding:20px">Nessun accesso registrato ancora.</div>';
    return;
  }
  // Raggruppa per utente: conta accessi e trova l'ultimo
  const byUser={};
  accessi.forEach(a=>{
    if(!byUser[a.username]) byUser[a.username]={nome:a.nome,count:0,ultimo:a.ts,ip:a.ip};
    byUser[a.username].count++;
    if(a.ts > byUser[a.username].ultimo) byUser[a.username].ultimo=a.ts;
  });
  let html=`<div style="margin-bottom:12px">
    <div style="font-size:.7rem;color:#555;text-transform:uppercase;letter-spacing:.4px;margin-bottom:8px">Riepilogo per utente</div>
    <div style="display:grid;grid-template-columns:repeat(auto-fill,minmax(180px,1fr));gap:8px">`;
  Object.entries(byUser).sort((a,b)=>b[1].ultimo.localeCompare(a[1].ultimo)).forEach(([u,v])=>{
    html+=`<div style="background:#2a2926;border-radius:10px;padding:12px;border:1px solid #383530">
      <div style="font-size:.82rem;font-weight:700;color:#e0e0e0;margin-bottom:4px">👤 ${v.nome}</div>
      <div style="font-size:.72rem;color:#cc5a2a;margin-bottom:2px">🔑 ${v.count} accesso${v.count!==1?'i':''}</div>
      <div style="font-size:.68rem;color:#555">Ultimo: ${v.ultimo.slice(0,16).replace('T',' ')}</div>
      <div style="font-size:.68rem;color:#444">IP: ${v.ip}</div>
    </div>`;
  });
  html+=`</div></div>`;
  // Tabella storica completa
  html+=`<div style="font-size:.7rem;color:#555;text-transform:uppercase;letter-spacing:.4px;margin-bottom:8px">Storico completo (ultimi ${Math.min(accessi.length,100)})</div>
  <div style="overflow-x:auto"><table style="width:100%;border-collapse:collapse;font-size:.76rem">
    <thead><tr style="border-bottom:1px solid #2a2926">
      ${['Utente','Nome','Data','Ora','IP'].map(h=>`<th style="padding:7px 8px;color:#555;font-size:.62rem;text-transform:uppercase;letter-spacing:.4px;text-align:left">${h}</th>`).join('')}
    </tr></thead><tbody>`;
  accessi.slice(0,100).forEach(a=>{
    const [data,ora]=(a.ts||'').split(' ');
    html+=`<tr style="border-bottom:1px solid #0d0f1e">
      <td style="padding:7px 8px;color:#cc5a2a;font-weight:600">${a.username}</td>
      <td style="padding:7px 8px;color:#e0e0e0">${a.nome}</td>
      <td style="padding:7px 8px;color:#aaa">${data||'—'}</td>
      <td style="padding:7px 8px;color:#aaa">${ora||'—'}</td>
      <td style="padding:7px 8px;color:#555;font-size:.7rem">${a.ip}</td>
    </tr>`;
  });
  html+=`</tbody></table></div>`;
  box.innerHTML=html;
}

function checkPresenzeAlert(){
  const modal=document.getElementById('presenzeModal');
  if(!modal) return;
  const today=new Date(); today.setHours(0,0,0,0);
  const dow=today.getDay()||7;
  const lun=new Date(today); lun.setDate(today.getDate()-(dow-1));
  const lunStr=lun.toISOString().slice(0,10);
  const entry=PRESENCES.presenze.find(p=>p.lun===lunStr);
  const tutteStrutture=D.strutture;
  const struttureMancanti=tutteStrutture.filter(s=>!entry||(entry.strutture||{})[s]===undefined||(entry.strutture||{})[s]===0);
  if(struttureMancanti.length>0){
    const dom=new Date(lun); dom.setDate(lun.getDate()+6);
    const fmt=d=>d.toLocaleDateString('it-IT',{day:'2-digit',month:'long'});
    document.getElementById('presenzeModalMsg').innerHTML=
      `<b>Settimana ${fmt(lun)} – ${fmt(dom)}</b><br>Le presenze non sono ancora state inserite per:<br><br>`+
      struttureMancanti.map(s=>`&nbsp;&nbsp;🏖️ <b>${s}</b>`).join('<br>')+
      `<br><br>Inserisci il numero di ospiti per calcolare correttamente il tasso di conversione.`;
    modal.style.display='flex';
  }
}
function chiudiModalPresenze(){
  document.getElementById('presenzeModal').style.display='none';
}
function vaiAPresenze(){
  chiudiModalPresenze();
  setTimeout(()=>{
    const el=document.getElementById('presForm');
    if(el) el.scrollIntoView({behavior:'smooth',block:'start'});
  },150);
}

// ── Spectre ──────────────────────────────────────────────────────────────────
// ── Stato postazioni (heartbeat + toggle Attiva/Pausa) ───────────────────────
function renderPostazioniStato() {
  if (sessionStorage.getItem('pm_auth') !== '1') return;
  const box = document.getElementById('postazioniStato');
  if (!box) return;
  box.innerHTML = '<div style="color:#555;font-size:.8rem">Caricamento stato postazioni...</div>';
  fetch('/postazioni-stato')
    .then(r => r.json())
    .then(data => {
      const postazioni = data.postazioni || {};
      const keys = Object.keys(postazioni);
      if (!keys.length) {
        box.innerHTML = '<div style="color:#555;font-size:.85rem">Nessuna postazione registrata.</div>';
        return;
      }
      const now = new Date();
      const ora = now.getHours();
      const orarioLavoro = ora >= 8 && ora < 22;

      let html = '<div style="overflow-x:auto"><table style="width:100%;border-collapse:collapse;font-size:.83rem">';
      html += `<thead><tr style="background:#12141f">
        <th style="padding:10px 12px;text-align:left;color:#666;font-weight:600">Struttura</th>
        <th style="padding:10px 12px;text-align:center;color:#666;font-weight:600">Stato</th>
        <th style="padding:10px 12px;text-align:center;color:#666;font-weight:600">Ctrl. Schede SD</th>
        <th style="padding:10px 12px;text-align:center;color:#666;font-weight:600">Ultimo sync</th>
        <th style="padding:10px 12px;text-align:center;color:#666;font-weight:600">Heartbeat</th>
        <th style="padding:10px 12px;text-align:center;color:#666;font-weight:600">Connessione</th>
      </tr></thead><tbody>`;

      keys.sort().forEach(nome => {
        const p      = postazioni[nome];
        const stato  = p.stato || 'attiva';
        const isPausa = stato === 'pausa';

        // Calcola offline
        let statoConn = '—';
        let connColor = '#555';
        if (p.ultimo_heartbeat) {
          const hb      = new Date(p.ultimo_heartbeat.replace(' ','T'));
          const diffMin = (now - hb) / 60000;
          const diffOre = diffMin / 60;
          if (isPausa) {
            statoConn = '⏸ In pausa'; connColor = '#4a4f6a';
          } else if (diffMin < 20) {
            statoConn = '🟢 Online'; connColor = '#4ade80';
          } else if (orarioLavoro && diffOre >= 3) {
            statoConn = '🔴 OFFLINE'; connColor = '#f87171';
          } else {
            statoConn = '🟡 Assente'; connColor = '#facc15';
          }
        } else if (isPausa) {
          statoConn = '⏸ In pausa'; connColor = '#4a4f6a';
        } else {
          statoConn = '⚫ Mai connessa'; connColor = '#555';
        }

        const syncLabel = p.ultimo_sync
          ? p.ultimo_sync.slice(0,16).replace('T',' ')
          : '—';
        const hbLabel = p.ultimo_heartbeat
          ? p.ultimo_heartbeat.slice(0,16)
          : '—';
        const rowBg = isPausa ? '#1a1917' : '#242220';

        const exifOn = p.exif_monitoring === true;
        html += `<tr style="background:${rowBg};border-bottom:1px solid #1b1d2f">
          <td style="padding:10px 12px;font-weight:600;color:${isPausa ? '#555' : '#e0e0e0'}">${nome}</td>
          <td style="padding:10px 12px;text-align:center">
            <button onclick="toggleStatoPostazione('${nome}','${isPausa ? 'attiva' : 'pausa'}')"
              style="background:${isPausa ? '#2a2926' : '#162a1e'};color:${isPausa ? '#cc5a2a' : '#4ade80'};
                     border:1px solid ${isPausa ? '#383530' : '#166534'};border-radius:6px;
                     padding:4px 12px;font-size:.75rem;cursor:pointer;white-space:nowrap">
              ${isPausa ? '▶ Attiva' : '⏸ Pausa'}
            </button>
          </td>
          <td style="padding:10px 12px;text-align:center">
            <button onclick="toggleExifMonitoring('${nome}',${!exifOn})"
              style="background:${exifOn ? '#162516' : '#2a2926'};color:${exifOn ? '#4ade80' : '#555'};
                     border:1px solid ${exifOn ? '#166534' : '#383530'};border-radius:6px;
                     padding:4px 12px;font-size:.75rem;cursor:pointer;white-space:nowrap">
              ${exifOn ? '🔍 Attivo' : '○ Disattivo'}
            </button>
          </td>
          <td style="padding:10px 12px;text-align:center;color:#666;font-size:.78rem">${syncLabel}</td>
          <td style="padding:10px 12px;text-align:center;color:#666;font-size:.78rem">${hbLabel}</td>
          <td style="padding:10px 12px;text-align:center;color:${connColor};font-weight:600;font-size:.82rem">${statoConn}</td>
        </tr>`;
      });

      html += '</tbody></table></div>';
      box.innerHTML = html;
    })
    .catch(() => {
      box.innerHTML = '<div style="color:#555;font-size:.85rem">Errore caricamento stato postazioni.</div>';
    });
}

function toggleStatoPostazione(nome, nuovoStato) {
  fetch('/set-postazione-stato', {
    method: 'POST',
    headers: {'Content-Type': 'application/json'},
    body: JSON.stringify({auth: _P, postazione: nome, stato: nuovoStato})
  }).then(() => renderPostazioniStato()).catch(() => {});
}

function toggleExifMonitoring(nome, abilitato) {
  fetch('/set-exif-monitoring', {
    method: 'POST',
    headers: {'Content-Type': 'application/json'},
    body: JSON.stringify({auth: _P, postazione: nome, abilitato: abilitato})
  }).then(() => renderPostazioniStato()).catch(() => {});
}

// Aggiorna stato postazioni ogni 5 minuti
setInterval(() => {
  if (document.getElementById('pane7') && document.getElementById('pane7').classList.contains('on')) {
    renderPostazioniStato();
    renderExifControllo();
  }
}, 300000);

// ── Controllo Schede SD / EXIF ────────────────────────────────────────────────
const SOGLIA_EXIF = 0.20; // 20% tolleranza

function renderExifControllo() {
  if (sessionStorage.getItem('pm_auth') !== '1') return;
  const box = document.getElementById('exifContent');
  if (!box) return;
  box.innerHTML = '<div style="color:#555;font-size:.8rem">Caricamento dati schede...</div>';
  fetch('/spectre-exif-data')
    .then(r => r.json())
    .then(data => {
      const strFiltro = fStr ? fStr.value : '';
      const sessioni = (data.sessioni || []).slice().reverse()
        .filter(s => !strFiltro || s.postazione === strFiltro)
        .slice(0, 50);
      if (!sessioni.length) {
        box.innerHTML = '<div style="color:#444;font-size:.82rem;padding:16px;background:#242220;border-radius:10px;text-align:center">' +
          'Nessuna scheda SD rilevata ancora. Il dato appare quando i fotografi inseriscono la scheda nel PC.</div>';
        return;
      }
      let html = `<div style="overflow-x:auto">
        <table style="width:100%;border-collapse:collapse;font-size:.80rem">
          <thead><tr style="border-bottom:1px solid #2a2926">
            ${['Data','Postazione','Fotocamera','Foto su scheda','Shutter count','Scatti nuovi','Stato'].map(h =>
              `<th style="padding:8px 6px;color:#555;font-size:.62rem;text-transform:uppercase;letter-spacing:.4px;text-align:left;white-space:nowrap">${h}</th>`
            ).join('')}
          </tr></thead><tbody>`;
      sessioni.forEach(s => {
        const delta    = s.shutter_delta;
        const foto     = s.foto_sulla_scheda || 0;
        const shutter  = s.shutter_count !== null && s.shutter_count !== undefined ? s.shutter_count.toLocaleString('it-IT') : '—';
        const deltaStr = delta !== null && delta !== undefined ? delta.toLocaleString('it-IT') : '—';
        // Logica sospetto: delta noto e delta > foto sulla scheda * (1 + soglia)
        let statoHtml = '<span style="color:#34d399;font-size:.75rem">✅ OK</span>';
        if (delta !== null && delta !== undefined && delta > foto * (1 + SOGLIA_EXIF)) {
          const eccesso = delta - foto;
          statoHtml = `<span style="color:#f87171;font-size:.75rem;font-weight:700">⚠️ SOSPETTO<br>
            <span style="font-weight:400">${eccesso} scatti non dichiarati</span></span>`;
        } else if (delta === null || delta === undefined) {
          statoHtml = '<span style="color:#555;font-size:.75rem">⏳ Prima sessione</span>';
        }
        const cam = [s.camera_make, s.camera_model].filter(Boolean).join(' ') || '—';
        const rowBg = (delta !== null && delta !== undefined && delta > foto * (1 + SOGLIA_EXIF))
          ? 'background:#1a0f0f' : 'background:#242220';
        html += `<tr style="${rowBg};border-bottom:1px solid #1a1917">
          <td style="padding:8px 6px;color:#aaa;white-space:nowrap">${s.timestamp ? s.timestamp.slice(0,16) : '—'}</td>
          <td style="padding:8px 6px;color:#fff">${s.postazione || '—'}</td>
          <td style="padding:8px 6px;color:#aaa">${cam}</td>
          <td style="padding:8px 6px;color:#cc5a2a;font-weight:700;text-align:center">${foto.toLocaleString('it-IT')}</td>
          <td style="padding:8px 6px;color:#38bdf8;text-align:center">${shutter}</td>
          <td style="padding:8px 6px;color:#f59e0b;font-weight:700;text-align:center">${deltaStr}</td>
          <td style="padding:8px 6px">${statoHtml}</td>
        </tr>`;
      });
      html += '</tbody></table></div>';
      html += `<div style="font-size:.68rem;color:#444;margin-top:8px;padding:0 4px">
        ⚠️ "Sospetto" = scatti registrati dalla fotocamera superiori del ${Math.round(SOGLIA_EXIF*100)}% rispetto alle foto sulla scheda.<br>
        "Prima sessione" = primo inserimento di questa fotocamera, nessun confronto disponibile.
      </div>`;
      box.innerHTML = html;
    })
    .catch(() => {
      box.innerHTML = '<div style="color:#f87171;font-size:.82rem;padding:12px">Errore caricamento dati EXIF</div>';
    });
}

function renderSpectre() {
  const box = document.getElementById('spectreContent');
  if (!box) return;
  const postazioni = SPECTRE && SPECTRE.postazioni ? SPECTRE.postazioni : {};
  const strFiltro = fStr ? fStr.value : '';
  const allKeys = Object.keys(postazioni);
  const keys = strFiltro ? allKeys.filter(p => p === strFiltro) : allKeys;
  if (!allKeys.length) {
    box.innerHTML = '<p style="color:#888;padding:20px">Nessun dato Spectre ricevuto. Esegui spectre_bridge2.bat su ogni postazione.</p>';
    return;
  }
  if (!keys.length) {
    box.innerHTML = '<p style="color:#888;padding:20px">Nessun dato Spectre per la struttura selezionata.</p>';
    return;
  }
  const oggi = new Date(); oggi.setHours(0,0,0,0);
  // Filtra per il periodo selezionato (stesso filtro della dashboard)
  const fDa = _fromDate ? new Date(_fromDate) : null;
  const fA  = _toDate   ? new Date(_toDate)   : null;
  if (fA) fA.setHours(23,59,59,999);
  let html = '';
  keys.forEach(postazione => {
    const d       = postazioni[postazione];
    const tutteCartelle = d.cartelle || [];
    // Applica filtro data su data_creazione
    const cart = tutteCartelle.filter(c => {
      if (!c.data_creazione || c.data_creazione === '0000-00-00') return false;
      const dc = new Date(c.data_creazione);
      if (fDa && dc < fDa) return false;
      if (fA  && dc > fA)  return false;
      return true;
    });
    const tot     = cart.length;
    const vend    = cart.filter(c => c.venduta).length;
    const nonV    = tot - vend;
    const conv    = tot > 0 ? (vend/tot*100).toFixed(1) : '0';
    const ts      = d.timestamp || '';
    // Cartelle non vendute con partenza entro 3 giorni = URGENTI
    const urgenti = cart.filter(c => {
      if (c.venduta) return false;
      if (!c.data_partenza || c.data_partenza === '0000-00-00') return false;
      const dp = new Date(c.data_partenza);
      const diff = (dp - oggi) / 86400000;
      return diff >= 0 && diff <= 3;
    });
    if (!cart.length) {
      html += `<div style="margin-bottom:20px">
        <h3 style="color:#cc5a2a;margin-bottom:6px">🏖️ ${postazione}</h3>
        <p style="color:#666;font-size:.85rem">Nessuna cartella nel periodo selezionato.</p>
      </div>`;
      return;
    }
    const periodoLabel = fDa && fA
      ? fDa.toLocaleDateString('it-IT',{day:'numeric',month:'short'}) + ' – ' + fA.toLocaleDateString('it-IT',{day:'numeric',month:'short',year:'numeric'})
      : 'Tutto il periodo';
    html += `<div style="margin-bottom:32px">
      <h3 style="color:#cc5a2a;margin-bottom:12px">🏖️ ${postazione}
        <span style="font-size:.75rem;color:#888;font-weight:400;margin-left:10px">${periodoLabel}</span>
        <span style="font-size:.7rem;color:#555;font-weight:400;margin-left:8px">Sync: ${ts}</span>
      </h3>`;
    // Alert urgenti
    if (urgenti.length) {
      html += `<div style="background:#2d1515;border:1.5px solid #f87171;border-radius:10px;padding:14px 18px;margin-bottom:16px">
        <div style="color:#f87171;font-weight:700;margin-bottom:8px">⚠️ ${urgenti.length} cartell${urgenti.length===1?'a':'e'} non vendut${urgenti.length===1?'a':'e'} con partenza imminente!</div>
        <div style="display:flex;flex-wrap:wrap;gap:8px">`;
      urgenti.forEach(c => {
        html += `<span style="background:#3d1a1a;border:1px solid #f87171;border-radius:6px;padding:4px 10px;font-size:.8rem;color:#fca5a5">${c.nome} — parte: ${c.data_partenza}</span>`;
      });
      html += `</div></div>`;
    }
    // Cards riepilogo
    html += `<div style="display:flex;gap:12px;flex-wrap:wrap;margin-bottom:16px">
      <div style="background:#1a1c2e;border-radius:10px;padding:14px 20px;min-width:120px;text-align:center">
        <div style="font-size:1.6rem;font-weight:700;color:#e0e0e0">${tot}</div>
        <div style="font-size:.75rem;color:#888">Cartelle create</div>
      </div>
      <div style="background:#1a1c2e;border-radius:10px;padding:14px 20px;min-width:120px;text-align:center">
        <div style="font-size:1.6rem;font-weight:700;color:#4ade80">${vend}</div>
        <div style="font-size:.75rem;color:#888">Vendute ✓</div>
      </div>
      <div style="background:#1a1c2e;border-radius:10px;padding:14px 20px;min-width:120px;text-align:center">
        <div style="font-size:1.6rem;font-weight:700;color:#f87171">${nonV}</div>
        <div style="font-size:.75rem;color:#888">Non vendute</div>
      </div>
      <div style="background:#1a1c2e;border-radius:10px;padding:14px 20px;min-width:120px;text-align:center">
        <div style="font-size:1.6rem;font-weight:700;color:#38bdf8">${conv}%</div>
        <div style="font-size:.75rem;color:#888">Conversione</div>
      </div>
    </div>
    <div style="overflow-x:auto">
    <table style="width:100%;border-collapse:collapse;font-size:.82rem">
      <thead><tr style="background:#12141f">
        <th style="padding:8px;text-align:left;color:#888">Famiglia / Cartella</th>
        <th style="padding:8px;text-align:center;color:#888">Data creazione</th>
        <th style="padding:8px;text-align:center;color:#888">Data partenza</th>
        <th style="padding:8px;text-align:right;color:#888">Foto</th>
        <th style="padding:8px;text-align:center;color:#888">Stato</th>
      </tr></thead>
      <tbody>`;
    // Ordina: non vendute prima, poi per data partenza
    const sorted = [...cart].sort((a,b) => {
      if (a.venduta !== b.venduta) return a.venduta ? 1 : -1;
      return (a.data_partenza||'').localeCompare(b.data_partenza||'');
    });
    sorted.forEach((c,i) => {
      const bg = i%2===0 ? '#1a1917' : '#12141f';
      const stato = c.venduta
        ? '<span style="color:#4ade80;font-weight:700">✓ Venduta</span>'
        : '<span style="color:#f87171;font-weight:700">✗ Non venduta</span>';
      // Evidenzia partenza imminente
      let rowStyle = `background:${bg}`;
      if (!c.venduta && c.data_partenza) {
        const dp = new Date(c.data_partenza); dp.setHours(0,0,0,0);
        const diff = (dp - oggi) / 86400000;
        if (diff >= 0 && diff <= 3) rowStyle = 'background:#2d1a0f';
      }
      html += `<tr style="${rowStyle}">
        <td style="padding:7px 8px;color:#e0e0e0;font-weight:500">${c.nome||''}</td>
        <td style="padding:7px 8px;text-align:center;color:#aaa">${c.data_creazione||''}</td>
        <td style="padding:7px 8px;text-align:center;color:#ccc">${c.data_partenza||'—'}</td>
        <td style="padding:7px 8px;text-align:right;color:#ccc">${c.n_foto||0}</td>
        <td style="padding:7px 8px;text-align:center">${stato}</td>
      </tr>`;
    });
    html += `</tbody></table></div></div>`;
  });
  box.innerHTML = html;
}

// ── Alert real-time — campanellino 🔔 (polling ogni 60 secondi) ─────────────
let _alertPanelOpen = false;

function aggiornaAlerts() {
  if (sessionStorage.getItem('pm_auth') !== '1') return;
  fetch('/spectre-alerts')
    .then(r => r.json())
    .then(data => {
      const tutti    = data.alerts || [];
      const nonLetti = tutti.filter(a => !a.letto);
      const bell  = document.getElementById('bellBtn');
      const count = document.getElementById('bellCount');
      const wrap  = document.getElementById('bellWrap');
      if (!bell || !wrap) return;
      if (tutti.length === 0) {
        wrap.style.display = 'none';
      } else if (nonLetti.length > 0) {
        // Alert non letti → campanellino rosso con badge
        wrap.style.display = 'block';
        bell.style.color = '#f87171';
        bell.style.borderColor = '#f87171';
        count.style.display = 'inline';
        count.textContent = nonLetti.length;
      } else {
        // Tutti letti ma esiste storico → campanellino grigio senza badge
        wrap.style.display = 'block';
        bell.style.color = '#555';
        bell.style.borderColor = '#383530';
        count.style.display = 'none';
      }
      if (_alertPanelOpen) renderAlertPanel(tutti);
    })
    .catch(() => {});
}

function renderAlertPanel(tutti) {
  const body = document.getElementById('alertPanelBody');
  if (!body) return;
  if (!tutti.length) {
    body.innerHTML = '<div style="color:#555;text-align:center;padding:40px 0;font-size:.88rem">Nessun alert ricevuto</div>';
    return;
  }
  // Più recente prima
  const reversed = [...tutti].reverse();
  let html = '';
  reversed.forEach((a, i) => {
    const realIdx   = tutti.length - 1 - i;
    const tipoLabel = a.tipo === 'jpeg_fuori_spectre' ? '📁 JPEG fuori Spectre' : (a.tipo || '?');
    const letto     = a.letto;
    html += `<div style="background:${letto ? '#1a1917' : '#1a0a0a'};border:1px solid ${letto ? '#1b1d2f' : '#7f1d1d'};
               border-radius:8px;padding:12px 14px;margin-bottom:8px;opacity:${letto ? '.55' : '1'}">
      <div style="display:flex;justify-content:space-between;align-items:flex-start;gap:10px">
        <div>
          <span style="color:${letto ? '#666' : '#f87171'};font-weight:600;font-size:.83rem">${tipoLabel}</span>
          <span style="color:#555;font-size:.72rem;margin-left:8px">${a.postazione || ''}</span>
        </div>
        ${letto
          ? '<span style="color:#2a4a2a;font-size:.7rem;white-space:nowrap;flex-shrink:0">✓ letto</span>'
          : `<button onclick="segnaLetto(${realIdx})"
               style="background:#7f1d1d;color:#fca5a5;border:none;border-radius:6px;
                      padding:4px 10px;cursor:pointer;font-size:.72rem;white-space:nowrap;flex-shrink:0">✓ Segna letto</button>`
        }
      </div>
      <div style="color:${letto ? '#3a3a4a' : '#ccc'};font-size:.78rem;margin-top:5px;word-break:break-all">${a.percorso || ''}</div>
      <div style="color:#3a3a4a;font-size:.7rem;margin-top:3px">${a.timestamp || ''}</div>
    </div>`;
  });
  body.innerHTML = html;
}

function toggleAlertPanel() {
  _alertPanelOpen = !_alertPanelOpen;
  const panel    = document.getElementById('alertPanel');
  const backdrop = document.getElementById('alertBackdrop');
  if (!panel || !backdrop) return;
  if (_alertPanelOpen) {
    panel.style.display = 'block';
    backdrop.style.display = 'block';
    fetch('/spectre-alerts').then(r => r.json())
      .then(d => renderAlertPanel(d.alerts || [])).catch(() => {});
  } else {
    panel.style.display = 'none';
    backdrop.style.display = 'none';
  }
}

function segnaLetto(idx) {
  fetch('/segna-alert-letto', {
    method: 'POST',
    headers: {'Content-Type': 'application/json'},
    body: JSON.stringify({auth: _P, idx: idx})
  }).then(() => {
    aggiornaAlerts();
    fetch('/spectre-alerts').then(r=>r.json()).then(d=>renderAlertPanel(d.alerts||[])).catch(()=>{});
  }).catch(() => {});
}

function segnaTestiLetti() {
  fetch('/segna-tutti-letti', {
    method: 'POST',
    headers: {'Content-Type': 'application/json'},
    body: JSON.stringify({auth: _P})
  }).then(() => {
    aggiornaAlerts();
    fetch('/spectre-alerts').then(r=>r.json()).then(d=>renderAlertPanel(d.alerts||[])).catch(()=>{});
  }).catch(() => {});
}

function pulisciAlerts() {
  if (!confirm('Eliminare tutto lo storico degli alert? Questa operazione non è reversibile.')) return;
  fetch('/pulisci-alerts', {
    method: 'POST',
    headers: {'Content-Type': 'application/json'},
    body: JSON.stringify({auth: _P})
  }).then(r => r.json()).then(d => {
    if (d.ok) {
      aggiornaAlerts();
      renderAlertPanel([]);
    }
  }).catch(() => {});
}

function esportaAlerts() {
  fetch('/spectre-alerts')
    .then(r => r.json())
    .then(data => {
      const alerts = data.alerts || [];
      if (!alerts.length) { alert('Nessun alert da esportare.'); return; }
      const righe = alerts.map(a =>
        `"${a.timestamp || ''}","${a.postazione || ''}","${a.tipo || ''}","${(a.percorso||'').replace(/"/g,"'")}","${a.letto ? 'Si' : 'No'}"`
      );
      const csv = 'Timestamp,Postazione,Tipo,Percorso,Letto\n' + righe.join('\n');
      const blob = new Blob([csv], {type: 'text/csv;charset=utf-8;'});
      const url  = URL.createObjectURL(blob);
      const link = document.createElement('a');
      link.href     = url;
      link.download = 'spectre_alerts_' + new Date().toISOString().slice(0,10) + '.csv';
      link.click();
      URL.revokeObjectURL(url);
    }).catch(() => {});
}

// Polling ogni 60 secondi
setInterval(aggiornaAlerts, 60000);

// ── Landing Pages Stats ──────────────────────────────────────────────────────
function renderLandingStats() {
  const el = document.getElementById('landingStatsContent');
  if (!el) return;
  el.innerHTML = '<div style="color:#555;font-size:.82rem;padding:8px 0">Caricamento...</div>';
  fetch('/landing-stats?auth='+encodeURIComponent(_P))
    .then(r => r.json())
    .then(data => {
      if (!data || !Object.keys(data).length) {
        el.innerHTML = '<div style="color:#555;font-size:.82rem;padding:8px 0">Nessun dato landing disponibile.</div>';
        return;
      }
      const strutture = Object.keys(data).sort();
      let html = '<div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:12px;margin-bottom:16px">';
      strutture.forEach(s => {
        const d = data[s];
        const visite   = (d.visits || []).length;
        const waClicks = (d.whatsapp_clicks || []).length;
        const conv     = visite > 0 ? Math.round(waClicks / visite * 100) : 0;
        const convColor = conv >= 20 ? '#34d399' : conv >= 10 ? '#f59e0b' : '#f87171';
        const landingUrl = '/landing?s=' + encodeURIComponent(s);
        html += `<div style="background:#242220;border-radius:10px;padding:14px;border-top:3px solid #cc5a2a">
          <div style="font-size:.95rem;font-weight:700;color:#fff;margin-bottom:10px;display:flex;justify-content:space-between;align-items:center">
            <span>🏖️ ${s}</span>
            <a href="${landingUrl}" target="_blank" style="color:#cc5a2a;font-size:.72rem;text-decoration:none;
               background:#2a2926;border:1px solid #383530;border-radius:6px;padding:3px 8px"
               title="Apri landing page">🔗 Apri</a>
          </div>
          <div style="display:grid;grid-template-columns:1fr 1fr 1fr;gap:6px">
            <div style="background:#2a2926;border-radius:6px;padding:8px;text-align:center">
              <div style="font-size:.6rem;color:#444;text-transform:uppercase;letter-spacing:.4px">Visite</div>
              <div style="font-size:1.1rem;font-weight:700;color:#e0e0e0;margin-top:2px">${visite}</div>
            </div>
            <div style="background:#2a2926;border-radius:6px;padding:8px;text-align:center">
              <div style="font-size:.6rem;color:#444;text-transform:uppercase;letter-spacing:.4px">WA Click</div>
              <div style="font-size:1.1rem;font-weight:700;color:#25d366;margin-top:2px">${waClicks}</div>
            </div>
            <div style="background:#2a2926;border-radius:6px;padding:8px;text-align:center">
              <div style="font-size:.6rem;color:#444;text-transform:uppercase;letter-spacing:.4px">Conversione</div>
              <div style="font-size:1.1rem;font-weight:700;color:${convColor};margin-top:2px">${conv}%</div>
            </div>
          </div>
          ${buildVisitChart(d.visits || [], d.whatsapp_clicks || [])}
          <div style="margin-top:8px;display:flex;gap:6px;align-items:center">
            <span style="font-size:.72rem;color:#555">Link:</span>
            <input type="text" value="${window.location.origin}${landingUrl}" readonly
              onclick="this.select()" style="flex:1;background:#2a2926;color:#cc5a2a;border:none;
              border-radius:4px;padding:4px 7px;font-size:.7rem;outline:none;cursor:text"/>
          </div>
        </div>`;
      });
      html += '</div>';
      el.innerHTML = html;
    }).catch(err => {
      el.innerHTML = '<div style="color:#f87171;font-size:.82rem;padding:8px 0">Errore caricamento stats landing.</div>';
    });
}

function buildVisitChart(visits, waClicks) {
  if (!visits.length && !waClicks.length) return '';
  // Raggruppa per giorno (ultimi 14 giorni)
  const today = new Date(); today.setHours(0,0,0,0);
  const days = [];
  for (let i = 13; i >= 0; i--) {
    const d = new Date(today); d.setDate(d.getDate() - i);
    days.push(d.toISOString().split('T')[0]);
  }
  const vMap = {}, wMap = {};
  visits.forEach(ts => { const d = ts.split('T')[0]; if(d in Object.fromEntries(days.map(x=>[x,0]))) vMap[d] = (vMap[d]||0)+1; });
  waClicks.forEach(ts => { const d = ts.split('T')[0]; if(d in Object.fromEntries(days.map(x=>[x,0]))) wMap[d] = (wMap[d]||0)+1; });
  const maxV = Math.max(...days.map(d=>(vMap[d]||0)), 1);
  const bars = days.map(d => {
    const v = vMap[d]||0, w = wMap[d]||0;
    const pV = Math.round(v/maxV*100), pW = Math.round(w/maxV*100);
    const dayShort = new Date(d+'T12:00:00').toLocaleDateString('it-IT',{day:'numeric',month:'numeric'});
    return `<div title="${dayShort}: ${v} visite, ${w} WA" style="flex:1;display:flex;flex-direction:column;align-items:center;gap:2px">
      <div style="width:100%;display:flex;flex-direction:column;justify-content:flex-end;height:28px;gap:1px">
        ${v ? `<div style="background:#cc5a2a;border-radius:2px 2px 0 0;height:${pV}%;min-height:2px"></div>` : ''}
        ${w ? `<div style="background:#25d366;border-radius:2px 2px 0 0;height:${pW}%;min-height:2px;margin-top:1px"></div>` : ''}
      </div>
    </div>`;
  }).join('');
  return `<div style="margin-top:10px">
    <div style="font-size:.6rem;color:#333;margin-bottom:4px;display:flex;justify-content:space-between">
      <span>Ultimi 14 giorni</span>
      <span><span style="color:#cc5a2a">▪</span> visite &nbsp;<span style="color:#25d366">▪</span> WA click</span>
    </div>
    <div style="display:flex;gap:1px;height:32px;align-items:flex-end">${bars}</div>
  </div>`;
}

// ── Landing Page Editor ───────────────────────────────────────────────────────
(function initLandingEditor(){
  const sel = document.getElementById('edStruttura');
  if (!sel) return;
  // Popola strutture dall'elenco utenti
  const strutture = new Set();
  (USERS.users || []).forEach(u => (u.strutture || []).forEach(s => strutture.add(s)));
  strutture.forEach(s => {
    const o = document.createElement('option'); o.value = s; o.textContent = s;
    sel.appendChild(o);
  });
  if (strutture.size === 1) { sel.value = [...strutture][0]; loadLandingConfig(); }
})();

function toggleSection(head){
  const body = head.nextElementSibling;
  body.classList.toggle('open');
  head.querySelector('span').textContent = body.classList.contains('open') ? '▲' : '▼';
}

function switchLedLang(btn, section){
  const parent = btn.closest('.led-body');
  parent.querySelectorAll('.led-ltab').forEach(b => b.classList.remove('active'));
  btn.classList.add('active');
  const lang = btn.textContent.slice(-2).toLowerCase();
  parent.querySelectorAll('.led-lang-panel').forEach(p => {
    p.style.display = (p.dataset.lang === lang && p.dataset.section === section) ? '' : 'none';
  });
}

function loadLandingConfig(){
  const struttura = document.getElementById('edStruttura').value;
  const form = document.getElementById('landingEditorForm');
  const link = document.getElementById('edLandingLink');
  if (!struttura) { form.style.display = 'none'; link.style.display = 'none'; return; }
  link.href = '/landing?s=' + encodeURIComponent(struttura);
  link.style.display = '';
  fetch('/get-landing-config?struttura=' + encodeURIComponent(struttura) + '&auth=' + encodeURIComponent(_P))
    .then(r => r.json())
    .then(cfg => {
      // Display name
      document.getElementById('led_display_name').value = cfg.display_name || '';
      // Prezzi
      const p = cfg.prezzi || {};
      document.getElementById('led_p1').value = p.p1 || '';
      document.getElementById('led_p2').value = p.p2 || '';
      document.getElementById('led_p3').value = p.p3 || '';
      // Gallery
      const gal = cfg.gallery || [];
      document.querySelectorAll('.led-gal').forEach(inp => {
        inp.value = gal[parseInt(inp.dataset.idx)] || '';
      });
      // Testi per lingua
      ['it','en','fr','de'].forEach(lang => {
        const t = cfg[lang] || {};
        document.querySelectorAll('.led-txt[data-lang="' + lang + '"]').forEach(inp => {
          inp.value = t[inp.dataset.key] || '';
        });
      });
      form.style.display = '';
    })
    .catch(() => { form.style.display = ''; });
}

function saveLandingConfig(){
  const struttura = document.getElementById('edStruttura').value;
  if (!struttura) return;
  const msg = document.getElementById('ledSaveMsg');
  const err = document.getElementById('ledSaveErr');
  msg.style.display = 'none'; err.style.display = 'none';
  // Raccoglie i dati
  const gallery = [];
  document.querySelectorAll('.led-gal').forEach(inp => { gallery[parseInt(inp.dataset.idx)] = inp.value.trim(); });
  const config = {
    display_name: document.getElementById('led_display_name').value.trim(),
    prezzi: {
      p1: document.getElementById('led_p1').value.trim(),
      p2: document.getElementById('led_p2').value.trim(),
      p3: document.getElementById('led_p3').value.trim()
    },
    gallery: gallery
  };
  // Raccoglie testi per ogni lingua
  ['it','en','fr','de'].forEach(lang => {
    config[lang] = {};
    document.querySelectorAll('.led-txt[data-lang="' + lang + '"]').forEach(inp => {
      if (inp.value.trim()) config[lang][inp.dataset.key] = inp.value.trim();
    });
  });
  fetch('/save-landing-config', {
    method: 'POST',
    headers: {'Content-Type': 'application/json'},
    body: JSON.stringify({ auth: _P, struttura, config })
  }).then(r => r.json()).then(d => {
    if (d.ok) { msg.style.display = ''; setTimeout(() => msg.style.display = 'none', 3000); }
    else { err.textContent = d.error || 'Errore sconosciuto'; err.style.display = ''; }
  }).catch(e => { err.textContent = 'Errore di rete'; err.style.display = ''; });
}

// ── Init ────────────────────────────────────────────────────────────────────
fStr.addEventListener('change', () => {
  updateFotografi(); render();
  // Se il tab Spectre è aperto, ricarica anche EXIF e stats landing
  if (document.getElementById('pane7') && document.getElementById('pane7').classList.contains('on')) {
    renderPostazioniStato(); renderExifControllo(); renderSpectre(); renderLandingStats();
  }
});
fFoto.addEventListener('change', render);

updateFotografi();
setPreset('anno_cur');
initSpeseForm();
initPresForm();
initUsersPanel();
renderAccessLog();
aggiornaAlerts();
// Mostra popup solo se già loggato (sessione attiva da reload/riapertura)
if(sessionStorage.getItem('pm_auth')==='1') checkPresenzeAlert();
if(sessionStorage.getItem('pm_auth')==='1') { renderPostazioniStato(); renderExifControllo(); renderLandingStats(); }
document.getElementById('footer').textContent =
  'Aggiornato: '+new Date().toLocaleDateString('it-IT')+' · PhotographerManager';
render();
</script>
</body>
</html>"""

HTML_UTENTE = r"""<!DOCTYPE html>
<html lang="it">
<head>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width,initial-scale=1"/>
<title>PM Dashboard</title>
<style>
*{box-sizing:border-box;margin:0;padding:0}
body{font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;background:#1a1917;color:#e0e0e0;min-height:100vh}
.app{max-width:960px;margin:0 auto;padding:14px 14px 50px}
h2{font-size:.85rem;font-weight:600;color:#888;margin:18px 0 8px;text-transform:uppercase;letter-spacing:.6px}
.header{margin-bottom:10px}
.header h1{font-size:1.45rem;font-weight:700;color:#fff;display:flex;align-items:center;gap:8px}
.badge{display:inline-block;background:#242220;color:#666;font-size:.75rem;padding:4px 10px;border-radius:20px;margin-top:5px}
.filters{display:flex;flex-wrap:wrap;gap:10px;background:#242220;padding:12px 14px;border-radius:12px;margin:10px 0}
.fg{display:flex;flex-direction:column;gap:4px;flex:1;min-width:130px}
.fg label{font-size:.68rem;color:#666;text-transform:uppercase;letter-spacing:.5px}
select{background:#2a2926;color:#e0e0e0;border:1px solid #383530;border-radius:8px;padding:10px;font-size:.92rem;width:100%;outline:none;-webkit-appearance:none;min-height:44px}
.kpi{display:grid;grid-template-columns:1fr 1fr;gap:10px;margin:10px 0}
@media(min-width:540px){.kpi{grid-template-columns:repeat(4,1fr)}}
.kcard{background:#242220;border-radius:12px;padding:14px 16px;border-left:3px solid #cc5a2a;box-shadow:0 2px 10px rgba(0,0,0,.35)}
.kcard .lbl{font-size:.68rem;color:#555;text-transform:uppercase;letter-spacing:.4px}
.kcard .val{font-size:1.4rem;font-weight:700;color:#fff;margin-top:4px;line-height:1}
.kcard .sub{font-size:.7rem;color:#444;margin-top:4px}
.tabs{display:flex;flex-wrap:wrap;border-bottom:1px solid #1b1d2f;margin:16px 0 0;gap:2px 0}
.tab{padding:10px 14px;font-size:.85rem;font-weight:500;white-space:nowrap;cursor:pointer;color:#4a4f6a;background:none;border:none;border-bottom:2px solid transparent;transition:.2s;min-height:44px}
.tab:hover{color:#aaa}
.tab.on{color:#fff;border-bottom-color:#cc5a2a}
.fpreset{background:#2a2926;color:#888;border:1px solid #383530;border-radius:6px;padding:6px 10px;font-size:.78rem;cursor:pointer;white-space:nowrap;transition:.15s}
.fpreset:hover{color:#bbb;border-color:#3a3d50}
@media(max-width:480px){.header h1{font-size:1.25rem}.fg{min-width:calc(50% - 5px)}select{font-size:.95rem;padding:11px 10px;min-height:46px}.kcard .val{font-size:1.25rem}.tab{padding:10px 10px;font-size:.8rem}}
.pane{display:none;padding:12px 0}
.pane.on{display:block}
.box{background:#242220;border-radius:10px;padding:14px;margin-bottom:12px}
.g2{display:grid;grid-template-columns:1fr;gap:12px}
@media(min-width:600px){.g2{grid-template-columns:1fr 1fr}}
.chart-wrap{width:100%;overflow:hidden}
svg.chart{width:100%;display:block}
.rlist{display:flex;flex-direction:column;gap:7px}
.ritem{background:#242220;border-radius:8px;padding:10px 12px}
.rrow{display:flex;justify-content:space-between;align-items:center;margin-bottom:5px}
.rname{font-size:.85rem;font-weight:600;color:#fff}
.rval{font-size:.85rem;font-weight:700;color:#cc5a2a}
.bar-bg{height:4px;background:#2a2926;border-radius:2px;overflow:hidden}
.bar-fg{height:4px;border-radius:2px}
.rsub{font-size:.65rem;color:#444;margin-top:4px}
.scards{display:grid;grid-template-columns:1fr;gap:10px}
@media(min-width:460px){.scards{grid-template-columns:repeat(auto-fit,minmax(190px,1fr))}}
.scard{background:#242220;border-radius:10px;padding:14px;border-top:3px solid #cc5a2a}
.sname{font-size:.95rem;font-weight:700;color:#fff;margin-bottom:10px}
.sgrid{display:grid;grid-template-columns:1fr 1fr;gap:6px}
.sstat{background:#2a2926;border-radius:6px;padding:8px}
.sstat .sl{font-size:.6rem;color:#444;text-transform:uppercase}
.sstat .sv{font-size:.88rem;font-weight:600;color:#e0e0e0;margin-top:2px}
.stop{font-size:.7rem;color:#666;margin-top:8px}
.gcards{display:grid;grid-template-columns:1fr;gap:10px}
@media(min-width:460px){.gcards{grid-template-columns:repeat(auto-fit,minmax(190px,1fr))}}
.gcard{background:#242220;border-radius:10px;padding:12px}
.grow{display:flex;justify-content:space-between;align-items:center;margin-bottom:5px}
.gname{font-size:.85rem;font-weight:600}
.gpct{font-size:.85rem;font-weight:700}
.gbar-bg{height:6px;background:#2a2926;border-radius:3px;overflow:hidden;margin:4px 0}
.gbar{height:6px;border-radius:3px;transition:width .4s}
.gfoot{display:flex;justify-content:space-between;font-size:.65rem;color:#444}
.gfoot input{background:transparent;border:none;border-bottom:1px solid #383530;color:#888;width:72px;text-align:right;font-size:.65rem;outline:none}
.green{color:#4ade80}.yellow{color:#facc15}.red{color:#f87171}
.footer{text-align:center;font-size:.65rem;color:#383530;margin-top:20px;padding-top:10px;border-top:1px solid #242220}
</style>
</head>
<body>
<!-- Campanellino alert (visibile solo se PERMS.alerts) -->
<div id="bellWrap" style="display:none;position:fixed;top:12px;right:12px;z-index:9999">
  <button id="bellBtn" onclick="toggleAlertPanel()" title="Alert di sicurezza"
    style="background:#1f1e1c;color:#f87171;border:1px solid #f87171;border-radius:20px;
           padding:6px 12px;font-size:.82rem;cursor:pointer;font-family:-apple-system,sans-serif;
           display:flex;align-items:center;gap:5px">
    \U0001f514 <span id="bellCount" style="display:none;background:#f87171;color:#fff;border-radius:10px;
      padding:1px 6px;font-size:.72rem;font-weight:700"></span>
  </button>
</div>
<div id="alertPanel" style="display:none;position:fixed;top:0;right:0;width:340px;max-width:100vw;
     height:100vh;background:#1a1917;border-left:1px solid #383530;z-index:99998;
     overflow-y:auto;box-shadow:-8px 0 32px rgba(0,0,0,.65);font-family:-apple-system,sans-serif">
  <div style="padding:16px 16px 12px;border-bottom:1px solid #2a2926;display:flex;align-items:center;justify-content:space-between">
    <span style="color:#fff;font-weight:700;font-size:.95rem">\U0001f514 Alert Spectre</span>
    <div style="display:flex;gap:8px;align-items:center">
      <button onclick="segnaTestiLettiU()"
        style="background:#2a2926;color:#34d399;border:1px solid #383530;border-radius:6px;
               padding:5px 10px;font-size:.72rem;cursor:pointer">\u2713 Tutti letti</button>
      <button onclick="toggleAlertPanel()"
        style="background:none;border:none;color:#666;font-size:1.3rem;cursor:pointer;
               padding:2px 8px;line-height:1">\u2715</button>
    </div>
  </div>
  <div id="alertPanelBody" style="padding:12px 16px"></div>
</div>
<div id="alertBackdrop" onclick="toggleAlertPanel()"
     style="display:none;position:fixed;inset:0;z-index:99997;background:rgba(0,0,0,.45)"></div>
<!-- POPUP PRESENZE MANCANTI -->
<div id="presenzeModal" style="display:none;position:fixed;inset:0;background:rgba(0,0,0,.7);z-index:9999;align-items:center;justify-content:center">
  <div style="background:#161827;border:1.5px solid #f87171;border-radius:16px;padding:28px 28px 22px;max-width:420px;width:90%;box-shadow:0 8px 40px #000a">
    <div style="display:flex;align-items:center;gap:10px;margin-bottom:14px">
      <span style="font-size:1.6rem">⚠️</span>
      <span style="color:#f87171;font-size:1rem;font-weight:700">Presenze non inserite</span>
    </div>
    <p id="presenzeModalMsg" style="color:#ccc;font-size:.87rem;line-height:1.6;margin:0 0 20px"></p>
    <div style="display:flex;gap:10px">
      <button onclick="chiudiModalPresenze()" style="flex:1;background:#2a2926;color:#aaa;border:1px solid #383530;border-radius:8px;padding:11px;font-size:.88rem;cursor:pointer">Ricordamelo dopo</button>
      <button onclick="vaiAPresenze()" style="flex:1;background:#38bdf8;color:#1a1917;border:none;border-radius:8px;padding:11px;font-size:.88rem;font-weight:700;cursor:pointer">👥 Vai alle Presenze</button>
    </div>
  </div>
</div>
<div class="app">
  <div class="header">
    <h1 style="display:flex;align-items:center;gap:8px"><svg width="22" height="20" viewBox="0 0 22 20" fill="none" style="flex-shrink:0"><path d="M21 16a2 2 0 01-2 2H3a2 2 0 01-2-2V7a2 2 0 012-2h3.7L8 2.5h6l1.3 2.5H20a2 2 0 012 2v9z" stroke="#cc5a2a" stroke-width="1.6" stroke-linejoin="round"/><circle cx="11" cy="11" r="3" stroke="#cc5a2a" stroke-width="1.6"/></svg>PM Dashboard</h1>
    <div class="badge" id="badge">Vista: __NOME__</div>
  </div>

  <div class="filters" style="flex-direction:column;gap:8px">
    <div style="display:flex;flex-wrap:wrap;gap:6px;align-items:center">
      <button class="fpreset" data-key="oggi"      onclick="setPreset('oggi')">Oggi</button>
      <button class="fpreset" data-key="ieri"      onclick="setPreset('ieri')">Ieri</button>
      <button class="fpreset" data-key="sett_cur"  onclick="setPreset('sett_cur')">Settimana corrente</button>
      <button class="fpreset" data-key="sett_prec" onclick="setPreset('sett_prec')">Ultima settimana</button>
      <button class="fpreset" data-key="mese_cur"  onclick="setPreset('mese_cur')">Mese corrente</button>
      <button class="fpreset" data-key="mese_prec" onclick="setPreset('mese_prec')">Ultimo mese</button>
      <button class="fpreset" data-key="3mesi"     onclick="setPreset('3mesi')">Ultimi 3 mesi</button>
      <button class="fpreset" data-key="anno_cur"  onclick="setPreset('anno_cur')">Anno corrente</button>
      <button class="fpreset" data-key="anno_prec" onclick="setPreset('anno_prec')">Ultimo anno</button>
      <button class="fpreset" data-key="tutto"     onclick="setPreset('tutto')">Tutto</button>
    </div>
    <div style="display:flex;flex-wrap:wrap;gap:8px;align-items:center">
      <div style="display:flex;align-items:center;gap:4px">
        <button onclick="navWeek(-1)" style="background:#2a2926;color:#aaa;border:1px solid #383530;border-radius:6px;padding:7px 10px;cursor:pointer;font-size:.9rem">&#9664;</button>
        <span id="weekLabel" style="font-size:.8rem;color:#aaa;padding:0 6px;white-space:nowrap;min-width:120px;text-align:center"></span>
        <button onclick="navWeek(1)" style="background:#2a2926;color:#aaa;border:1px solid #383530;border-radius:6px;padding:7px 10px;cursor:pointer;font-size:.9rem">&#9654;</button>
      </div>
      <div style="display:flex;align-items:center;gap:4px;flex-wrap:wrap">
        <input type="date" id="fDa" style="background:#2a2926;color:#e0e0e0;border:1px solid #383530;border-radius:8px;padding:7px 8px;font-size:.85rem;outline:none"/>
        <span style="color:#555">–</span>
        <input type="date" id="fA"  style="background:#2a2926;color:#e0e0e0;border:1px solid #383530;border-radius:8px;padding:7px 8px;font-size:.85rem;outline:none"/>
        <button onclick="applyCustomRange()" style="background:#cc5a2a;color:#fff;border:none;border-radius:8px;padding:7px 12px;font-size:.85rem;cursor:pointer">Applica</button>
      </div>
      <div class="fg" style="flex:1;min-width:140px"><label>🏖️ Struttura</label><select id="fStruttura"><option value="">Tutte</option></select></div>
      <div class="fg" style="flex:1;min-width:120px"><label>👤 Fotografo</label><select id="fFotografo"><option value="">Tutti</option></select></div>
    </div>
  </div>

  <div class="kpi">
    <div class="kcard" style="border-color:#cc5a2a"><div class="lbl">💰 Incasso</div><div class="val" id="kInc">—</div><div class="sub" id="kTrans">—</div></div>
    <div class="kcard" style="border-color:#e07a52"><div class="lbl">🖼️ Foto vendute</div><div class="val" id="kQty">—</div><div class="sub">unità totali</div></div>
    <div class="kcard" style="border-color:#34d399"><div class="lbl">👤 Fotografi</div><div class="val" id="kFoto">—</div><div class="sub">attivi</div></div>
    <div class="kcard" style="border-color:#f59e0b"><div class="lbl">🏖️ Strutture</div><div class="val" id="kStr">—</div><div class="sub">location</div></div>
  </div>

  <div class="tabs" id="tabsBar">
    <button class="tab on"  data-tab="0">📊 Riepilogo</button>
    <button class="tab" data-perm="strutture"   data-tab="1">🏖️ Strutture</button>
    <button class="tab" data-perm="fotografi"   data-tab="2">👤 Fotografi</button>
    <button class="tab" data-perm="obiettivi"   data-tab="3">🎯 Obiettivi</button>
    <button class="tab" data-perm="consumabili" data-tab="4">🖨️ Consumabili</button>
    <button class="tab" data-perm="contabilita" data-tab="5">💼 Contabilità</button>
    <button class="tab" data-perm="presenze"    data-tab="6">👥 Presenze</button>
    <button class="tab" data-perm="agenda"      data-tab="7">📅 Agenda</button>
  </div>

  <!-- TAB 0 — RIEPILOGO -->
  <div class="pane on" id="pane0">
    <h2>💰 Incasso per struttura</h2>
    <div class="box chart-wrap" id="cStr"></div>
    <div class="g2">
      <div><h2>📈 Trend mensile</h2><div class="box chart-wrap" id="cTrend"></div></div>
      <div><h2>🏆 Top fotografi</h2><div class="rlist" id="rankList"></div></div>
    </div>
  </div>

  <!-- TAB 1 — STRUTTURE -->
  <div class="pane" id="pane1">
    <h2>🏖️ Dettaglio strutture</h2>
    <div class="scards" id="sCards"></div>
  </div>

  <!-- TAB 2 — FOTOGRAFI -->
  <div class="pane" id="pane2">
    <div class="g2">
      <div><h2>🏆 Classifica incasso</h2><div class="rlist" id="rankList2"></div></div>
      <div><h2>📈 Top 5 trend mensile</h2><div class="box chart-wrap" id="cFotoTrend"></div></div>
    </div>
    <h2 style="margin-top:14px">👤 Fotografi per struttura</h2>
    <div class="box" id="fotoPerStr"></div>
  </div>

  <!-- TAB 3 — OBIETTIVI -->
  <div class="pane" id="pane3">
    <h2>🎯 Obiettivi <span style="font-size:.65rem;color:#444;font-weight:400">(modifica i target)</span></h2>
    <div class="gcards" id="goalCards"></div>
    <h2 style="margin-top:16px">📊 Incasso vs Target</h2>
    <div class="box chart-wrap" id="cGoal"></div>
  </div>

  <!-- TAB 4 — CONSUMABILI -->
  <div class="pane" id="pane4">
    <div class="kpi" style="grid-template-columns:1fr 1fr">
      <div class="kcard" style="border-color:#38bdf8"><div class="lbl">🖨️ Stampe totali</div><div class="val" id="cTotStampe">—</div><div class="sub">unità nel periodo</div></div>
      <div class="kcard" style="border-color:#e07a52"><div class="lbl">📦 Formati usati</div><div class="val" id="cTotFormati">—</div><div class="sub">tipologie diverse</div></div>
    </div>
    <h2>🖨️ Stampe per formato</h2>
    <div class="box chart-wrap" id="cConsFmt"></div>
    <h2 style="margin-top:14px">🏖️ Stampe per struttura</h2>
    <div class="box chart-wrap" id="cConsStr"></div>
    <h2 style="margin-top:14px">📋 Dettaglio per formato</h2>
    <div class="box" id="consTable"></div>
  </div>

  <!-- TAB 5 — CONTABILITÀ -->
  <div class="pane" id="pane5">
    <div class="kpi" style="grid-template-columns:repeat(2,1fr)">
      <div class="kcard" style="border-color:#34d399"><div class="lbl">💰 Fatturato</div><div class="val" id="plFatturato">—</div><div class="sub">periodo selezionato</div></div>
      <div class="kcard" style="border-color:#f87171"><div class="lbl">💸 Spese inserite</div><div class="val" id="plSpese">—</div><div class="sub">nel periodo</div></div>
    </div>
    <h2 style="margin-top:14px">🏖️ Incasso per struttura</h2>
    <div class="box" id="plStrTable"></div>
    <h2 style="margin-top:14px">👤 Performance fotografi</h2>
    <div class="box" id="plFotoTable"></div>
    <h2 style="margin-top:14px">🧾 Spese</h2>
    <div id="speseFormU" style="display:none">
      <div class="box" style="margin-bottom:4px">
        <div style="display:grid;grid-template-columns:1fr 1fr;gap:8px;margin-bottom:10px">
          <div><label style="font-size:.65rem;color:#555;text-transform:uppercase;letter-spacing:.4px">Data</label>
            <input type="date" id="spData" style="width:100%;background:#2a2926;border:1px solid #383530;border-radius:8px;padding:9px 10px;color:#e0e0e0;font-size:.88rem;outline:none;margin-top:3px;min-height:42px"/></div>
          <div><label style="font-size:.65rem;color:#555;text-transform:uppercase;letter-spacing:.4px">Categoria</label>
            <input type="text" id="spCategoria" placeholder="es. Consumabili, Trasporti..."
              style="width:100%;background:#2a2926;border:1px solid #383530;border-radius:8px;padding:9px 10px;color:#e0e0e0;font-size:.88rem;outline:none;margin-top:3px;min-height:42px"/></div>
          <div><label style="font-size:.65rem;color:#555;text-transform:uppercase;letter-spacing:.4px">Importo (€)</label>
            <input type="number" id="spImporto" min="0" step="0.01" placeholder="0.00"
              style="width:100%;background:#2a2926;border:1px solid #383530;border-radius:8px;padding:9px 10px;color:#e0e0e0;font-size:.88rem;outline:none;margin-top:3px;min-height:42px"/></div>
          <div><label style="font-size:.65rem;color:#555;text-transform:uppercase;letter-spacing:.4px">Struttura</label>
            <select id="spStruttura" style="width:100%;background:#2a2926;border:1px solid #383530;border-radius:8px;padding:9px 10px;color:#e0e0e0;font-size:.88rem;outline:none;margin-top:3px;min-height:42px;-webkit-appearance:none">
              <option value="">Tutte / Generale</option></select></div>
          <div style="grid-column:1/-1"><label style="font-size:.65rem;color:#555;text-transform:uppercase;letter-spacing:.4px">Descrizione</label>
            <input type="text" id="spDesc" placeholder="es. Carta DNP, benzina..."
              style="width:100%;background:#2a2926;border:1px solid #383530;border-radius:8px;padding:9px 10px;color:#e0e0e0;font-size:.88rem;outline:none;margin-top:3px;min-height:42px"/></div>
        </div>
        <button onclick="addExpenseU()" style="width:100%;background:#34d399;color:#1a1917;border:none;border-radius:8px;padding:12px;font-size:.92rem;font-weight:700;cursor:pointer;min-height:46px">➕ Aggiungi spesa</button>
      </div>
    </div>
    <div class="box" id="speseList"></div>
  </div>

  <!-- TAB 6 — PRESENZE -->
  <div class="pane" id="pane6">
    <h2>👥 Inserisci presenze settimanali</h2>
    <div id="presenzeFormBox" class="box" style="margin-bottom:4px">
      <div style="display:grid;grid-template-columns:1fr 1fr;gap:8px;margin-bottom:10px">
        <div>
          <label style="font-size:.65rem;color:#555;text-transform:uppercase;letter-spacing:.4px">Settimana (lunedì)</label>
          <input type="date" id="prLun" style="width:100%;background:#2a2926;border:1px solid #383530;border-radius:8px;padding:9px 10px;color:#e0e0e0;font-size:.88rem;outline:none;margin-top:3px;min-height:42px" onchange="aggiornaLabelSettimana()"/>
        </div>
        <div style="display:flex;align-items:flex-end">
          <div id="prSettimanaLabel" style="font-size:.78rem;color:#888;padding-bottom:10px"></div>
        </div>
        <div style="grid-column:1/-1">
          <label style="font-size:.65rem;color:#555;text-transform:uppercase;letter-spacing:.4px">Ospiti per struttura</label>
          <div id="prStruttureInputs" style="display:grid;grid-template-columns:1fr 1fr;gap:6px;margin-top:6px"></div>
        </div>
      </div>
      <button onclick="savePresenza()" style="width:100%;background:#38bdf8;color:#1a1917;border:none;border-radius:8px;padding:12px;font-size:.92rem;font-weight:700;cursor:pointer;min-height:46px">💾 Salva presenze settimana</button>
    </div>
    <h2 style="margin-top:14px">📊 Storico presenze & conversione</h2>
    <div class="box" id="presenzeTable"></div>
  </div>

  <!-- TAB 7 — AGENDA SHOOTING -->
  <div class="pane" id="pane7">
    <h2>📅 Gestione Agenda Shooting</h2>
    <div class="box" id="agendaBox">
      <div id="agendaStrWrap" style="margin-bottom:14px;display:none">
        <label style="font-size:.65rem;color:#555;text-transform:uppercase;letter-spacing:.4px">🏖️ Struttura</label>
        <select id="agendaStr" onchange="loadAgendaStr(this.value)"
          style="width:100%;background:#2a2926;color:#e0e0e0;border:1px solid #383530;border-radius:8px;padding:10px;font-size:.92rem;outline:none;min-height:44px;-webkit-appearance:none;margin-top:4px"></select>
      </div>
      <div style="display:grid;grid-template-columns:1fr 1fr;gap:8px;margin-bottom:14px">
        <div>
          <label style="font-size:.65rem;color:#555;text-transform:uppercase;letter-spacing:.4px">📱 Numero WhatsApp</label>
          <input type="tel" id="agendaWA" placeholder="+393401234567"
            style="width:100%;background:#2a2926;border:1px solid #383530;border-radius:8px;padding:9px 10px;color:#e0e0e0;font-size:.88rem;outline:none;margin-top:4px;min-height:42px"/>
        </div>
        <div>
          <label style="font-size:.65rem;color:#555;text-transform:uppercase;letter-spacing:.4px">📝 Note per i clienti</label>
          <input type="text" id="agendaNote" placeholder="es. Shooting in spiaggia al tramonto"
            style="width:100%;background:#2a2926;border:1px solid #383530;border-radius:8px;padding:9px 10px;color:#e0e0e0;font-size:.88rem;outline:none;margin-top:4px;min-height:42px"/>
        </div>
      </div>
      <h2 style="margin-bottom:8px">➕ Aggiungi slot disponibile</h2>
      <div style="display:grid;grid-template-columns:1fr 1fr;gap:8px;margin-bottom:10px">
        <div>
          <label style="font-size:.65rem;color:#555;text-transform:uppercase;letter-spacing:.4px">📅 Data</label>
          <input type="date" id="slotData"
            style="width:100%;background:#2a2926;border:1px solid #383530;border-radius:8px;padding:9px 10px;color:#e0e0e0;font-size:.88rem;outline:none;margin-top:4px;min-height:42px"/>
        </div>
        <div>
          <label style="font-size:.65rem;color:#555;text-transform:uppercase;letter-spacing:.4px">🕐 Orario</label>
          <input type="time" id="slotOra"
            style="width:100%;background:#2a2926;border:1px solid #383530;border-radius:8px;padding:9px 10px;color:#e0e0e0;font-size:.88rem;outline:none;margin-top:4px;min-height:42px"/>
        </div>
        <div>
          <label style="font-size:.65rem;color:#555;text-transform:uppercase;letter-spacing:.4px">👤 Nome cliente (opzionale)</label>
          <input type="text" id="slotNome" placeholder="es. Mario Rossi"
            style="width:100%;background:#2a2926;border:1px solid #383530;border-radius:8px;padding:9px 10px;color:#e0e0e0;font-size:.88rem;outline:none;margin-top:4px;min-height:42px"/>
        </div>
        <div>
          <label style="font-size:.65rem;color:#555;text-transform:uppercase;letter-spacing:.4px">🛏️ Camera / Ombrellone (opzionale)</label>
          <input type="text" id="slotCamera" placeholder="es. 214 oppure Ombrellone 8"
            style="width:100%;background:#2a2926;border:1px solid #383530;border-radius:8px;padding:9px 10px;color:#e0e0e0;font-size:.88rem;outline:none;margin-top:4px;min-height:42px"/>
        </div>
      </div>
      <button onclick="addAgendaSlot()"
        style="background:#34d399;color:#1a1917;border:none;border-radius:8px;padding:10px 20px;font-size:.88rem;font-weight:700;cursor:pointer;margin-bottom:16px;min-height:42px">
        ➕ Aggiungi slot
      </button>
      <h2 style="margin-bottom:8px">📆 Slot configurati</h2>
      <div id="agendaSlotsList" style="margin-bottom:14px;display:flex;flex-direction:column;gap:6px"></div>
      <button onclick="saveAgenda(event)"
        style="width:100%;background:#cc5a2a;color:#fff;border:none;border-radius:8px;padding:12px;font-size:.92rem;font-weight:700;cursor:pointer;min-height:46px">
        💾 Salva agenda
      </button>
      <div id="agendaSaveMsg" style="margin-top:8px;font-size:.82rem;display:none;text-align:center;padding:6px;border-radius:6px"></div>
    </div>
  </div>

  <div class="footer" id="footer"></div>
</div>

<script>
const _D        = __DATA__;
let   PRESENCES = __PRESENCES__;
let   EXPENSES  = __EXPENSES__;
const PERMS     = __PERMS__;
const _USERNAME = "__USERNAME__";
const _MYPASS   = "__MYPASS__";

const C = ['#cc5a2a','#e07a52','#34d399','#f59e0b','#f87171','#38bdf8','#fb923c','#e879f9','#84cc16','#22d3ee'];
const MORD = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];
const MIT  = {Jan:'Gen',Feb:'Feb',Mar:'Mar',Apr:'Apr',May:'Mag',Jun:'Giu',Jul:'Lug',Aug:'Ago',Sep:'Set',Oct:'Ott',Nov:'Nov',Dec:'Dic'};
const targets = {};
const fmtE = n => '€ ' + Math.round(n).toLocaleString('it-IT');
const fmtN = n => Math.round(n).toLocaleString('it-IT');

const D = {
  anni: _D.anni, strutture: _D.strutture, fotografi: _D.fotografi, formati: _D.formati,
  cameras: _D.cameras||[],
  records: _D.records.map(r => ({
    Struttura: _D.strutture[r[0]], Fotografo: _D.fotografi[r[1]], Formato: _D.formati[r[2]],
    Anno: String(r[3]), Mese: r[4], Giorno: r[5], NomeMese: MORD[r[4]-1], Quantità: r[6], Prezzo: r[7],
    Camera: (_D.cameras||[])[r[8]]||'',
  }))
};
const MESI_IT = ['','Gen','Feb','Mar','Apr','Mag','Giu','Lug','Ago','Set','Ott','Nov','Dic'];

const fStr  = document.getElementById('fStruttura');
const fFoto = document.getElementById('fFotografo');

D.strutture.forEach(s => { const o=document.createElement('option'); o.value=o.textContent=s; fStr.appendChild(o); });
D.fotografi.forEach(f => { targets[f]=15000; });

// ── Stato filtro data ────────────────────────────────────────────────────────
let _fromDate = null;
let _toDate   = null;
let _activePreset = '';

function isoDate(d) {
  return d.getFullYear()+'-'+String(d.getMonth()+1).padStart(2,'0')+'-'+String(d.getDate()).padStart(2,'0');
}
function getMonday(d) {
  const dt = new Date(d); dt.setHours(0,0,0,0);
  const day = dt.getDay();
  dt.setDate(dt.getDate() + (day===0 ? -6 : 1-day));
  return dt;
}
function getFilterAnno() {
  return _fromDate ? String(_fromDate.getFullYear()) : String(new Date().getFullYear());
}
function getFilterMese() {
  if(!_fromDate || !_toDate) return '';
  if(_fromDate.getFullYear()===_toDate.getFullYear() && _fromDate.getMonth()===_toDate.getMonth())
    return String(_fromDate.getMonth()+1);
  return '';
}
function updateDateInputs() {
  const elDa = document.getElementById('fDa'), elA = document.getElementById('fA');
  if(elDa && _fromDate) elDa.value = isoDate(_fromDate);
  if(elA  && _toDate)   elA.value  = isoDate(_toDate);
}
function updateWeekLabel() {
  const el = document.getElementById('weekLabel');
  if(!el) return;
  if(!_fromDate || !_toDate) { el.textContent=''; return; }
  const df = _fromDate.toLocaleDateString('it-IT',{day:'numeric',month:'short',year:'numeric'});
  const dt = _toDate.toLocaleDateString('it-IT',{day:'numeric',month:'short',year:'numeric'});
  el.textContent = _fromDate.getTime()===_toDate.getTime() ? df : df+' – '+dt;
}
function updatePresetButtons() {
  document.querySelectorAll('.fpreset').forEach(btn => {
    const k = btn.getAttribute('data-key');
    const on = k === _activePreset;
    btn.style.background  = on ? '#cc5a2a' : '#2a2926';
    btn.style.color       = on ? '#fff'    : '#888';
    btn.style.borderColor = on ? '#cc5a2a' : '#383530';
  });
}
function setPreset(key) {
  _activePreset = key;
  const today = new Date(); today.setHours(0,0,0,0);
  if(key==='oggi') {
    _fromDate = new Date(today); _toDate = new Date(today);
  } else if(key==='ieri') {
    const y = new Date(today); y.setDate(y.getDate()-1);
    _fromDate = y; _toDate = new Date(y);
  } else if(key==='sett_cur') {
    _fromDate = getMonday(today);
    _toDate = new Date(_fromDate); _toDate.setDate(_toDate.getDate()+6);
  } else if(key==='sett_prec') {
    _fromDate = getMonday(today); _fromDate.setDate(_fromDate.getDate()-7);
    _toDate = new Date(_fromDate); _toDate.setDate(_toDate.getDate()+6);
  } else if(key==='mese_cur') {
    _fromDate = new Date(today.getFullYear(), today.getMonth(), 1);
    _toDate   = new Date(today.getFullYear(), today.getMonth()+1, 0);
  } else if(key==='mese_prec') {
    _fromDate = new Date(today.getFullYear(), today.getMonth()-1, 1);
    _toDate   = new Date(today.getFullYear(), today.getMonth(), 0);
  } else if(key==='3mesi') {
    _toDate   = new Date(today);
    _fromDate = new Date(today); _fromDate.setMonth(_fromDate.getMonth()-3);
  } else if(key==='anno_cur') {
    _fromDate = new Date(today.getFullYear(), 0, 1);
    _toDate   = new Date(today.getFullYear(), 11, 31);
  } else if(key==='anno_prec') {
    _fromDate = new Date(today.getFullYear()-1, 0, 1);
    _toDate   = new Date(today.getFullYear()-1, 11, 31);
  } else if(key==='tutto') {
    _fromDate = new Date(2000, 0, 1);
    _toDate   = new Date(2099, 11, 31);
  }
  updateDateInputs(); updateWeekLabel(); updatePresetButtons(); updateFotografi(); render();
}
function navWeek(dir) {
  const base = (_fromDate && _activePreset.startsWith('sett')) ? new Date(_fromDate) : getMonday(new Date());
  base.setDate(base.getDate() + dir*7);
  _fromDate = base;
  _toDate = new Date(base); _toDate.setDate(_toDate.getDate()+6);
  _activePreset = '';
  updateDateInputs(); updateWeekLabel(); updatePresetButtons(); updateFotografi(); render();
}
function applyCustomRange() {
  const da = document.getElementById('fDa').value;
  const a  = document.getElementById('fA').value;
  if(da) _fromDate = new Date(da+'T00:00:00'); else _fromDate = new Date(2000,0,1);
  if(a)  _toDate   = new Date(a+'T00:00:00');  else _toDate   = new Date(2099,11,31);
  _activePreset = '';
  updateWeekLabel(); updatePresetButtons(); updateFotografi(); render();
}
function updateFotografi() {
  const s=fStr.value;
  const foSet=[...new Set(D.records.filter(r=>{
    if(!_fromDate||!_toDate) return !s||r.Struttura===s;
    const rd=new Date(r.Anno,r.Mese-1,r.Giorno);
    return rd>=_fromDate&&rd<=_toDate&&(!s||r.Struttura===s);
  }).map(r=>r.Fotografo))].sort();
  const cur=fFoto.value;
  fFoto.innerHTML='<option value="">Tutti</option>';
  foSet.forEach(f=>{const o=document.createElement('option');o.value=o.textContent=f;fFoto.appendChild(o);if(!targets[f])targets[f]=15000;});
  if(foSet.includes(cur)) fFoto.value=cur;
}
function filtered() {
  const s=fStr.value,f=fFoto.value;
  let recs=D.records;
  if(_fromDate&&_toDate) recs=recs.filter(r=>{const rd=new Date(r.Anno,r.Mese-1,r.Giorno);return rd>=_fromDate&&rd<=_toDate;});
  if(s) recs=recs.filter(r=>r.Struttura===s);
  if(f) recs=recs.filter(r=>r.Fotografo===f);
  return recs;
}
function grp(arr,key,val){const m={};arr.forEach(r=>{m[r[key]]=(m[r[key]]||0)+r[val];});return m;}

// ── SVG Charts ───────────────────────────────────────────────────────────────
function svgBar(container,labels,values,colors,fmt){
  if(!labels.length){container.innerHTML='<p style="color:#333;padding:20px;text-align:center">Nessun dato</p>';return;}
  const W=340,barH=28,gap=8,padL=120,padR=82,padT=8,padB=8,H=labels.length*(barH+gap)+padT+padB,max=Math.max(...values)||1;
  let html=`<svg class="chart" viewBox="0 0 ${W} ${H}" xmlns="http://www.w3.org/2000/svg">`;
  labels.forEach((lbl,i)=>{
    const y=padT+i*(barH+gap),bw=Math.max(4,(values[i]/max)*(W-padL-padR)),col=Array.isArray(colors)?colors[i%colors.length]:colors,lblShort=lbl.length>16?lbl.slice(0,15)+'…':lbl;
    html+=`<text x="${padL-10}" y="${y+barH/2+4}" font-size="11" fill="#bbb" text-anchor="end">${lblShort}</text>`;
    html+=`<rect x="${padL}" y="${y}" width="${bw}" height="${barH}" rx="5" fill="${col}" opacity=".9"/>`;
    html+=`<text x="${padL+bw+8}" y="${y+barH/2+4}" font-size="11" fill="#888">${fmt?fmt(values[i]):fmtE(values[i])}</text>`;
  });
  html+='</svg>';container.innerHTML=html;
}
function svgLine(container,labels,datasets){
  if(!labels.length){container.innerHTML='<p style="color:#333;padding:20px;text-align:center">Nessun dato</p>';return;}
  const W=320,H=160,padL=52,padR=10,padT=10,padB=28,iW=W-padL-padR,iH=H-padT-padB;
  const allVals=datasets.flatMap(d=>d.data),maxV=Math.max(...allVals,1),xStep=labels.length>1?iW/(labels.length-1):iW;
  let html=`<svg class="chart" viewBox="0 0 ${W} ${H}" xmlns="http://www.w3.org/2000/svg">`;
  for(let g=0;g<=4;g++){const gy=padT+iH-(g/4)*iH;html+=`<line x1="${padL}" y1="${gy}" x2="${W-padR}" y2="${gy}" stroke="#1e2130" stroke-width="1"/><text x="${padL-4}" y="${gy+4}" font-size="9" fill="#444" text-anchor="end">${fmtE((g/4)*maxV)}</text>`;}
  labels.forEach((lbl,i)=>{html+=`<text x="${padL+i*xStep}" y="${H-6}" font-size="9" fill="#555" text-anchor="middle">${lbl}</text>`;});
  datasets.forEach(ds=>{
    const pts=ds.data.map((v,i)=>`${padL+i*xStep},${padT+iH-(v/maxV)*iH}`);
    html+=`<polyline points="${pts.join(' ')}" fill="none" stroke="${ds.color}" stroke-width="2" stroke-linejoin="round"/>`;
    ds.data.forEach((v,i)=>{const px=padL+i*xStep,py=padT+iH-(v/maxV)*iH;html+=`<circle cx="${px}" cy="${py}" r="3" fill="${ds.color}"><title>${ds.label}: ${fmtE(v)}</title></circle>`;});
  });
  datasets.slice(0,5).forEach((ds,i)=>{html+=`<rect x="${padL+i*58}" y="${H-padB+14}" width="8" height="3" rx="1" fill="${ds.color}"/><text x="${padL+i*58+11}" y="${H-padB+18}" font-size="8" fill="#666">${ds.label.length>8?ds.label.slice(0,7)+'…':ds.label}</text>`;});
  html+='</svg>';container.innerHTML=html;
}

// ── Permessi & Tab ────────────────────────────────────────────────────────────
const PERM_MAP = {strutture:1,fotografi:2,obiettivi:3,consumabili:4,contabilita:5,presenze:6};
function initTabs(){
  document.querySelectorAll('[data-perm]').forEach(btn=>{
    const p=btn.getAttribute('data-perm');
    if(!PERMS[p]){btn.style.display='none';}
  });
  if(!PERMS.input_presenze){
    const fb=document.getElementById('presenzeFormBox');
    if(fb) fb.style.display='none';
  }
  if(PERMS.edit_spese){
    const sf=document.getElementById('spesenzeFormU')||document.getElementById('speseFormU');
    if(sf) sf.style.display='block';
    // init strutture dropdown
    const sel=document.getElementById('spStruttura');
    if(sel&&sel.options.length===1) D.strutture.forEach(s=>{const o=document.createElement('option');o.value=o.textContent=s;sel.appendChild(o);});
    const di=document.getElementById('spData');
    if(di&&!di.value) di.value=new Date().toISOString().split('T')[0];
  }
}

function showTab(n){
  document.querySelectorAll('.tab').forEach(t=>t.classList.remove('on'));
  document.querySelectorAll('.pane').forEach(p=>p.classList.remove('on'));
  const btn=document.querySelector(`.tab[data-tab="${n}"]`);
  const pane=document.getElementById('pane'+n);
  if(btn) btn.classList.add('on');
  if(pane) pane.classList.add('on');
  if(n===7 && PERMS.agenda) { initAgenda(); }
}
document.querySelectorAll('.tab').forEach(btn=>{
  btn.addEventListener('click',()=>showTab(+btn.getAttribute('data-tab')));
});

// ── Render ────────────────────────────────────────────────────────────────────
function render(){
  const rec=filtered();
  const incasso=rec.reduce((s,r)=>s+r.Prezzo,0),qty=rec.reduce((s,r)=>s+r.Quantità,0);
  const nFoto=new Set(rec.map(r=>r.Fotografo)).size,nStr=new Set(rec.map(r=>r.Struttura)).size;
  document.getElementById('kInc').textContent=fmtE(incasso);
  document.getElementById('kTrans').textContent=fmtN(rec.length)+' transazioni';
  document.getElementById('kQty').textContent=fmtN(qty);
  document.getElementById('kFoto').textContent=nFoto;
  document.getElementById('kStr').textContent=nStr;
  document.getElementById('badge').textContent='Vista: __NOME__ · '+fmtN(rec.length)+' transazioni';
  renderRiepilogo(rec);
  renderStrutture(rec);
  renderFotografi(rec);
  renderObiettivi(rec);
  renderConsumabili(rec);
  renderContabilita(rec);
  renderPresenze();
}

function renderRiepilogo(rec){
  const sMap=grp(rec,'Struttura','Prezzo'),sK=Object.keys(sMap).sort((a,b)=>sMap[b]-sMap[a]);
  svgBar(document.getElementById('cStr'),sK,sK.map(k=>sMap[k]),C);
  const strutture=[...new Set(rec.map(r=>r.Struttura))],mData={};
  rec.forEach(r=>{if(!mData[r.NomeMese])mData[r.NomeMese]={ord:MORD.indexOf(r.NomeMese)};mData[r.NomeMese][r.Struttura]=(mData[r.NomeMese][r.Struttura]||0)+r.Prezzo;});
  const ms=Object.entries(mData).sort((a,b)=>a[1].ord-b[1].ord);
  svgLine(document.getElementById('cTrend'),ms.map(([k])=>MIT[k]||k),strutture.map((s,i)=>({label:s,color:C[i%C.length],data:ms.map(([,v])=>v[s]||0)})));
  const foMap={};rec.forEach(r=>{if(!foMap[r.Fotografo])foMap[r.Fotografo]={inc:0,qty:0,n:0};foMap[r.Fotografo].inc+=r.Prezzo;foMap[r.Fotografo].qty+=r.Quantità;foMap[r.Fotografo].n++;});
  const sorted=Object.entries(foMap).sort((a,b)=>b[1].inc-a[1].inc),maxInc=sorted[0]?.[1].inc||1,medals=['🥇','🥈','🥉'];
  document.getElementById('rankList').innerHTML=sorted.map(([f,v],i)=>`
    <div class="ritem"><div class="rrow"><span class="rname">${medals[i]||''} ${f}</span><span class="rval">${fmtE(v.inc)}</span></div>
    <div class="bar-bg"><div class="bar-fg" style="width:${v.inc/maxInc*100}%;background:${C[i%C.length]}"></div></div>
    <div class="rsub">${fmtN(v.qty)} foto · ${v.n} vendite</div></div>`).join('');
}

function renderStrutture(rec){
  document.getElementById('sCards').innerHTML=[...new Set(rec.map(r=>r.Struttura))].sort().map((s,i)=>{
    const sub=rec.filter(r=>r.Struttura===s),inc=sub.reduce((a,r)=>a+r.Prezzo,0),qty=sub.reduce((a,r)=>a+r.Quantità,0),nF=new Set(sub.map(r=>r.Fotografo)).size;
    const foG=grp(sub,'Fotografo','Prezzo'),topFo=Object.entries(foG).sort((a,b)=>b[1]-a[1])[0];
    const fmtG=grp(sub,'Formato','Quantità'),topFmt=Object.entries(fmtG).sort((a,b)=>b[1]-a[1])[0];
    return `<div class="scard" style="border-color:${C[i%C.length]}"><div class="sname">🏖️ ${s}</div>
      <div class="sgrid">
        <div class="sstat"><div class="sl">💰 Incasso</div><div class="sv">${fmtE(inc)}</div></div>
        <div class="sstat"><div class="sl">🖼️ Vendute</div><div class="sv">${fmtN(qty)}</div></div>
        <div class="sstat"><div class="sl">👤 Fotografi</div><div class="sv">${nF}</div></div>
        <div class="sstat"><div class="sl">📦 Top formato</div><div class="sv">${topFmt?topFmt[0]:'-'}</div></div>
      </div>${topFo?`<div class="stop">🏆 <strong style="color:#ccc">${topFo[0]}</strong> — ${fmtE(topFo[1])}</div>`:''}</div>`;
  }).join('');
}

function renderFotografi(rec){
  const foMap={};rec.forEach(r=>{if(!foMap[r.Fotografo])foMap[r.Fotografo]={inc:0,qty:0,n:0};foMap[r.Fotografo].inc+=r.Prezzo;foMap[r.Fotografo].qty+=r.Quantità;foMap[r.Fotografo].n++;});
  const sorted=Object.entries(foMap).sort((a,b)=>b[1].inc-a[1].inc),maxInc=sorted[0]?.[1].inc||1,medals=['🥇','🥈','🥉'];
  document.getElementById('rankList2').innerHTML=sorted.map(([f,v],i)=>`
    <div class="ritem"><div class="rrow"><span class="rname">${medals[i]||''} ${f}</span><span class="rval">${fmtE(v.inc)}</span></div>
    <div class="bar-bg"><div class="bar-fg" style="width:${v.inc/maxInc*100}%;background:${C[i%C.length]}"></div></div>
    <div class="rsub">${fmtN(v.qty)} foto · ${v.n} vendite</div></div>`).join('');
  const top5=sorted.slice(0,5).map(([f])=>f),mData={};
  rec.forEach(r=>{if(!mData[r.NomeMese])mData[r.NomeMese]={ord:MORD.indexOf(r.NomeMese)};mData[r.NomeMese][r.Fotografo]=(mData[r.NomeMese][r.Fotografo]||0)+r.Prezzo;});
  const ms=Object.entries(mData).sort((a,b)=>a[1].ord-b[1].ord);
  svgLine(document.getElementById('cFotoTrend'),ms.map(([k])=>MIT[k]||k),top5.map((f,i)=>({label:f,color:C[i%C.length],data:ms.map(([,v])=>v[f]||0)})));
  let fpHtml='<div style="overflow-x:auto"><table style="width:100%;border-collapse:collapse;font-size:.82rem"><thead><tr style="border-bottom:1px solid #2a2926">';
  fpHtml+=['Struttura','Fotografo','Incasso','Foto','Media/gg'].map(h=>`<th style="padding:8px 6px;color:#555;font-size:.65rem;text-transform:uppercase;letter-spacing:.4px;text-align:${h==='Struttura'||h==='Fotografo'?'left':'right'}">${h}</th>`).join('');
  fpHtml+='</tr></thead><tbody>';
  const rows=[];
  [...new Set(rec.map(r=>r.Struttura))].sort().forEach(s=>{
    [...new Set(rec.filter(r=>r.Struttura===s).map(r=>r.Fotografo))].sort().forEach(f=>{
      const sub=rec.filter(r=>r.Struttura===s&&r.Fotografo===f);
      const inc=sub.reduce((a,r)=>a+r.Prezzo,0),qty=sub.reduce((a,r)=>a+r.Quantità,0);
      const giorni=new Set(sub.map(r=>`${r.Anno}-${r.Mese}-${r.Giorno}`)).size;
      const t=targets[f]||15000,col=inc>=t?'#34d399':inc>=t*0.7?'#facc15':'#f87171';
      rows.push({s,f,inc,qty,giorni,col});
    });
  });
  rows.sort((a,b)=>b.inc-a.inc).forEach(({s,f,inc,qty,giorni,col})=>{
    fpHtml+=`<tr style="border-bottom:1px solid #242220"><td style="padding:8px 6px;color:#888">🏖️ ${s}</td><td style="padding:8px 6px;color:#fff;font-weight:600">👤 ${f}</td><td style="padding:8px 6px;text-align:right;color:${col};font-weight:700">${fmtE(inc)}</td><td style="padding:8px 6px;text-align:right;color:#aaa">${fmtN(qty)}</td><td style="padding:8px 6px;text-align:right;color:#38bdf8">${giorni>0?fmtE(inc/giorni):'—'}</td></tr>`;
  });
  fpHtml+='</tbody></table></div>';
  document.getElementById('fotoPerStr').innerHTML=fpHtml;
}

function renderObiettivi(rec){
  const foMap=grp(rec,'Fotografo','Prezzo'),sorted=Object.entries(foMap).sort((a,b)=>b[1]-a[1]);
  document.getElementById('goalCards').innerHTML=sorted.map(([f,inc],i)=>{
    const t=targets[f]||15000,pct=Math.min(inc/t*100,100),cls=pct>=100?'green':pct>=70?'yellow':'red',col=pct>=100?'#4ade80':pct>=70?'#facc15':'#f87171';
    return `<div class="gcard"><div class="grow"><span class="gname" style="color:${C[i%C.length]}">${f}</span><span class="gpct ${cls}">${pct.toFixed(0)}%</span></div>
      <div class="gbar-bg"><div class="gbar" style="width:${pct}%;background:${col}"></div></div>
      <div class="gfoot"><span>${fmtE(inc)}</span><span>Target: <input type="number" value="${t}" step="500" onchange="targets['${f}']=+this.value;renderObiettivi(filtered())"/></span></div>
      ${pct<100?`<div style="font-size:.63rem;color:#444;margin-top:3px">Mancano ${fmtE(Math.max(t-inc,0))}</div>`:''}</div>`;
  }).join('');
  const maxV=Math.max(...sorted.map(([,v])=>v),...sorted.map(([f])=>targets[f]||15000),1);
  const W=340,barH=24,gap=8,padL=120,padR=82,padT=8,padB=8,H=sorted.length*(barH+gap)+padT+padB;
  let svg=`<svg class="chart" viewBox="0 0 ${W} ${H}" xmlns="http://www.w3.org/2000/svg">`;
  sorted.forEach(([f,v],i)=>{
    const y=padT+i*(barH+gap),w=Math.max(4,(v/maxV)*(W-padL-padR)),wt=Math.max(4,((targets[f]||15000)/maxV)*(W-padL-padR)),short=f.length>16?f.slice(0,15)+'…':f;
    svg+=`<text x="${padL-10}" y="${y+barH/2+4}" font-size="11" fill="#bbb" text-anchor="end">${short}</text>`;
    svg+=`<rect x="${padL}" y="${y+barH*0.1}" width="${w}" height="${barH*0.8}" rx="4" fill="${C[i%C.length]}" opacity=".85"/>`;
    svg+=`<line x1="${padL+wt}" y1="${y}" x2="${padL+wt}" y2="${y+barH}" stroke="#f87171" stroke-width="2" stroke-dasharray="4,3"/>`;
    svg+=`<text x="${padL+w+8}" y="${y+barH/2+4}" font-size="11" fill="#888">${fmtE(v)}</text>`;
  });
  svg+='</svg>';
  document.getElementById('cGoal').innerHTML=svg;
}

function renderConsumabili(rec){
  const fmtMap=grp(rec,'Formato','Quantità'),fmtK=Object.keys(fmtMap).filter(k=>k&&k!=='undefined').sort((a,b)=>fmtMap[b]-fmtMap[a]);
  const totStampe=fmtK.reduce((s,k)=>s+fmtMap[k],0);
  document.getElementById('cTotStampe').textContent=fmtN(totStampe);
  document.getElementById('cTotFormati').textContent=fmtK.length;
  svgBar(document.getElementById('cConsFmt'),fmtK,fmtK.map(k=>fmtMap[k]),C,v=>fmtN(v)+' pz');
  const strMap=grp(rec,'Struttura','Quantità'),strK=Object.keys(strMap).sort((a,b)=>strMap[b]-strMap[a]);
  svgBar(document.getElementById('cConsStr'),strK,strK.map(k=>strMap[k]),C,v=>fmtN(v)+' pz');
  const incMap=grp(rec,'Formato','Prezzo');
  let html=`<div style="overflow-x:auto"><table style="width:100%;border-collapse:collapse;font-size:.82rem">
    <thead><tr style="border-bottom:1px solid #2a2926">${['Formato','Stampe','%','Incasso'].map(h=>`<th style="padding:7px 6px;color:#555;font-size:.65rem;text-transform:uppercase;letter-spacing:.4px;text-align:${h==='Formato'?'left':'right'}">${h}</th>`).join('')}</tr></thead><tbody>`;
  fmtK.forEach((f,i)=>{
    const qty=fmtMap[f],pct=totStampe?(qty/totStampe*100).toFixed(1):0,inc=incMap[f]||0;
    html+=`<tr style="border-bottom:1px solid #242220"><td style="padding:8px 6px;color:#e0e0e0;display:flex;align-items:center;gap:7px"><span style="display:inline-block;width:10px;height:10px;border-radius:3px;background:${C[i%C.length]};flex-shrink:0"></span>${f}</td><td style="padding:8px 6px;text-align:right;font-weight:700;color:#fff">${fmtN(qty)}</td><td style="padding:8px 6px;text-align:right;color:#888">${pct}%</td><td style="padding:8px 6px;text-align:right;color:#cc5a2a">${fmtE(inc)}</td></tr>`;
  });
  html+=`<tr style="border-top:2px solid #2a2926"><td style="padding:8px 6px;color:#888;font-weight:600">Totale</td><td style="padding:8px 6px;text-align:right;font-weight:700;color:#fff">${fmtN(totStampe)}</td><td style="padding:8px 6px;text-align:right;color:#888">100%</td><td style="padding:8px 6px;text-align:right;color:#cc5a2a">${fmtE(rec.reduce((s,r)=>s+r.Prezzo,0))}</td></tr></tbody></table></div>`;
  document.getElementById('consTable').innerHTML=html;
}

function renderContabilita(rec){
  const fatTot=rec.reduce((s,r)=>s+r.Prezzo,0);
  const anno=getFilterAnno(),mese=getFilterMese(),str=fStr.value;
  const spese=(EXPENSES.spese||[]).filter(s=>{
    if(!s.data) return true;
    const[sy,sm]=s.data.split('-');
    if(anno&&sy!==anno) return false;
    if(mese&&parseInt(sm)!==parseInt(mese)) return false;
    if(str&&s.struttura&&s.struttura!==str) return false;
    return true;
  });
  const totSpese=spese.reduce((s,e)=>s+(parseFloat(e.importo)||0),0);
  document.getElementById('plFatturato').textContent=fmtE(fatTot);
  document.getElementById('plSpese').textContent=fmtE(totSpese);

  // P&L per struttura (solo incasso)
  const strList=[...new Set(rec.map(r=>r.Struttura))].sort();
  let tbl=`<div style="overflow-x:auto"><table style="width:100%;border-collapse:collapse;font-size:.8rem"><thead><tr style="border-bottom:1px solid #2a2926">
    ${['Struttura','Fatturato','Transazioni','Foto'].map(h=>`<th style="padding:8px 6px;color:#555;font-size:.65rem;text-transform:uppercase;letter-spacing:.4px;text-align:${h==='Struttura'?'left':'right'}">${h}</th>`).join('')}
  </tr></thead><tbody>`;
  strList.forEach((s,i)=>{
    const sub=rec.filter(r=>r.Struttura===s),fat=sub.reduce((a,r)=>a+r.Prezzo,0),qty=sub.reduce((a,r)=>a+r.Quantità,0);
    tbl+=`<tr style="border-bottom:1px solid #242220"><td style="padding:8px 6px;color:#fff;font-weight:600"><span style="display:inline-block;width:8px;height:8px;border-radius:50%;background:${C[i%C.length]};margin-right:6px"></span>${s}</td><td style="padding:8px 6px;text-align:right;color:#cc5a2a;font-weight:700">${fmtE(fat)}</td><td style="padding:8px 6px;text-align:right;color:#aaa">${sub.length}</td><td style="padding:8px 6px;text-align:right;color:#aaa">${fmtN(qty)}</td></tr>`;
  });
  tbl+='</tbody></table></div>';
  document.getElementById('plStrTable').innerHTML=tbl;

  // Performance fotografi
  const foMap={};rec.forEach(r=>{if(!foMap[r.Fotografo])foMap[r.Fotografo]={inc:0,qty:0,giorni:new Set()};foMap[r.Fotografo].inc+=r.Prezzo;foMap[r.Fotografo].qty+=r.Quantità;foMap[r.Fotografo].giorni.add(`${r.Anno}-${r.Mese}-${r.Giorno}`);});
  let ftbl=`<div style="overflow-x:auto"><table style="width:100%;border-collapse:collapse;font-size:.8rem"><thead><tr style="border-bottom:1px solid #2a2926">
    ${['Fotografo','Incasso','Foto','Giorni','Media/gg','vs Target'].map(h=>`<th style="padding:8px 6px;color:#555;font-size:.65rem;text-transform:uppercase;letter-spacing:.4px;text-align:${h==='Fotografo'||h==='vs Target'?'left':'right'}">${h}</th>`).join('')}
  </tr></thead><tbody>`;
  Object.entries(foMap).sort((a,b)=>b[1].inc-a[1].inc).forEach(([f,v],i)=>{
    const t=targets[f]||15000,pct=t>0?v.inc/t*100:0,col=pct>=100?'#34d399':pct>=70?'#facc15':'#f87171',lbl=pct>=100?'🟢 Obiettivo':pct>=70?'🟡 In corso':'🔴 Sotto';
    ftbl+=`<tr style="border-bottom:1px solid #242220"><td style="padding:8px 6px;color:#fff;font-weight:600">${['🥇','🥈','🥉'][i]||''} ${f}</td><td style="padding:8px 6px;text-align:right;color:#cc5a2a;font-weight:700">${fmtE(v.inc)}</td><td style="padding:8px 6px;text-align:right;color:#aaa">${fmtN(v.qty)}</td><td style="padding:8px 6px;text-align:right;color:#aaa">${v.giorni.size}</td><td style="padding:8px 6px;text-align:right;color:#38bdf8">${v.giorni.size>0?fmtE(v.inc/v.giorni.size):'—'}</td><td style="padding:8px 6px;color:${col}">${lbl} (${pct.toFixed(0)}%)</td></tr>`;
  });
  ftbl+='</tbody></table></div>';
  document.getElementById('plFotoTable').innerHTML=ftbl;

  // Lista spese
  const box=document.getElementById('speseList');
  if(!box) return;
  if(!spese.length){box.innerHTML='<p style="color:#444;padding:14px;text-align:center;font-size:.82rem">Nessuna spesa nel periodo.</p>';return;}
  const perCat={};spese.forEach(s=>{perCat[s.categoria]=(perCat[s.categoria]||0)+(parseFloat(s.importo)||0);});
  let html=`<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:12px;padding-bottom:10px;border-bottom:1px solid #2a2926"><span style="font-size:.82rem;color:#888">${spese.length} spese</span><span style="font-size:1rem;font-weight:700;color:#f87171">− ${fmtE(totSpese)}</span></div>`;
  html+=`<div style="display:flex;flex-wrap:wrap;gap:6px;margin-bottom:12px">`;
  Object.entries(perCat).sort((a,b)=>b[1]-a[1]).forEach(([cat,tot])=>{html+=`<span style="background:#cc5a2a22;color:#cc5a2a;border:1px solid #cc5a2a44;border-radius:20px;padding:3px 10px;font-size:.72rem;font-weight:600">${cat}: ${fmtE(tot)}</span>`;});
  html+=`</div>`;
  spese.sort((a,b)=>(b.data||'').localeCompare(a.data||'')).forEach(s=>{
    const d=s.data?new Date(s.data+'T00:00:00').toLocaleDateString('it-IT'):'—';
    html+=`<div style="display:flex;justify-content:space-between;align-items:flex-start;padding:9px 0;border-bottom:1px solid #242220;gap:8px">
      <div style="flex:1;min-width:0"><div style="font-size:.75rem;color:#cc5a2a;margin-bottom:2px">${s.categoria}${s.struttura?' · 🏖️ '+s.struttura:''}</div>
      <div style="font-size:.82rem;color:#ccc">${s.descrizione||'—'}</div><div style="font-size:.68rem;color:#444;margin-top:1px">${d}</div></div>
      <div style="display:flex;align-items:center;gap:8px;flex-shrink:0">
        <span style="font-weight:700;color:#f87171;font-size:.92rem">− ${fmtE(parseFloat(s.importo)||0)}</span>
        ${PERMS.edit_spese?`<button onclick="deleteExpenseU('${s.id}')" style="background:#2a2926;color:#555;border:1px solid #383530;border-radius:6px;padding:5px 8px;font-size:.75rem;cursor:pointer;min-height:32px">🗑</button>`:''}
      </div></div>`;
  });
  box.innerHTML=html;
}

function addExpenseU(){
  const data=document.getElementById('spData').value;
  const categoria=document.getElementById('spCategoria').value.trim()||'Spesa';
  const importo=parseFloat(document.getElementById('spImporto').value)||0;
  const struttura=document.getElementById('spStruttura').value;
  const descrizione=document.getElementById('spDesc').value.trim();
  if(!importo){alert('Inserisci un importo valido');return;}
  const spesa={id:Date.now().toString(36)+Math.random().toString(36).slice(2,6),data,categoria,fotografo:'',struttura,importo,descrizione};
  fetch('/add-expense',{method:'POST',headers:{'Content-Type':'application/json'},
    body:JSON.stringify({auth:_P,spesa})
  }).then(r=>r.json()).then(d=>{
    if(d.ok){EXPENSES.spese.push(spesa);document.getElementById('spImporto').value='';document.getElementById('spDesc').value='';renderContabilita(filtered());}
    else alert('Errore: '+(d.error||'sconosciuto'));
  }).catch(()=>alert('Errore connessione'));
}
function deleteExpenseU(id){
  if(!confirm('Eliminare questa spesa?')) return;
  fetch('/delete-expense',{method:'POST',headers:{'Content-Type':'application/json'},
    body:JSON.stringify({auth:_P,id})
  }).then(r=>r.json()).then(d=>{
    if(d.ok){EXPENSES.spese=EXPENSES.spese.filter(s=>s.id!==id);renderContabilita(filtered());}
    else alert('Errore: '+(d.error||'sconosciuto'));
  }).catch(()=>alert('Errore connessione'));
}

// ── Presenze ──────────────────────────────────────────────────────────────────
function initPresForm(){
  const strutture=D.strutture.slice().sort();
  const cont=document.getElementById('prStruttureInputs');
  if(!cont) return;
  cont.innerHTML=strutture.map(s=>`<div><label style="font-size:.65rem;color:#888">${s}</label>
    <input type="number" id="pr_${s.replace(/\s/g,'_')}" min="0" step="1" placeholder="0"
      style="width:100%;background:#2a2926;border:1px solid #383530;border-radius:8px;padding:8px 10px;color:#e0e0e0;font-size:.88rem;outline:none;margin-top:3px;min-height:38px"/></div>`).join('');
  const now=new Date(),dow=now.getDay()||7,lun=new Date(now);
  lun.setDate(now.getDate()-(dow-1));
  document.getElementById('prLun').value=lun.toISOString().slice(0,10);
  aggiornaLabelSettimana();
}
function aggiornaLabelSettimana(){
  const v=document.getElementById('prLun').value;
  if(!v){document.getElementById('prSettimanaLabel').textContent='';return;}
  const lun=new Date(v+'T00:00:00'),dow=lun.getDay();
  if(dow!==1){const offset=dow===0?-6:-(dow-1);lun.setDate(lun.getDate()+offset);document.getElementById('prLun').value=lun.toISOString().slice(0,10);}
  const dom=new Date(lun);dom.setDate(lun.getDate()+6);
  const fmt=d=>d.toLocaleDateString('it-IT',{day:'2-digit',month:'short'});
  document.getElementById('prSettimanaLabel').textContent=`📅 ${fmt(lun)} – ${fmt(dom)}`;
}
function savePresenza(){
  const lunVal=document.getElementById('prLun').value;
  if(!lunVal){alert('Seleziona la settimana');return;}
  const lun=new Date(lunVal+'T00:00:00'),dom=new Date(lun);dom.setDate(lun.getDate()+6);
  const strutture=D.strutture.slice().sort(),strOspiti={};
  strutture.forEach(s=>{const v=parseInt(document.getElementById('pr_'+s.replace(/\s/g,'_')).value)||0;if(v>0)strOspiti[s]=v;});
  if(!Object.keys(strOspiti).length){alert('Inserisci almeno una struttura con ospiti > 0');return;}
  const presenza={id:lunVal,lun:lunVal,dom:dom.toISOString().slice(0,10),strutture:strOspiti};
  fetch('/save-presence-user',{method:'POST',headers:{'Content-Type':'application/json'},
    body:JSON.stringify({username:_U,password:_P,presenza})
  }).then(r=>r.json()).then(d=>{
    if(d.ok){PRESENCES.presenze=PRESENCES.presenze.filter(p=>p.id!==presenza.id);PRESENCES.presenze.push(presenza);PRESENCES.presenze.sort((a,b)=>a.lun.localeCompare(b.lun));renderPresenze();}
    else alert('Errore: '+(d.error||'sconosciuto'));
  }).catch(()=>alert('Errore connessione'));
}
function deletePresenza(id){
  if(!confirm('Eliminare questa settimana?')) return;
  fetch('/delete-presence-user',{method:'POST',headers:{'Content-Type':'application/json'},
    body:JSON.stringify({username:_U,password:_P,id})
  }).then(r=>r.json()).then(d=>{
    if(d.ok){PRESENCES.presenze=PRESENCES.presenze.filter(p=>p.id!==id);renderPresenze();}
    else alert('Errore: '+(d.error||'sconosciuto'));
  }).catch(()=>alert('Errore connessione'));
}
function renderPresenze(){
  const box=document.getElementById('presenzeTable');
  if(!box) return;
  const presenze=(PRESENCES.presenze||[]).slice().sort((a,b)=>b.lun.localeCompare(a.lun));
  if(!presenze.length){box.innerHTML='<div style="color:#555;font-size:.82rem;text-align:center;padding:20px">Nessuna presenza inserita ancora.</div>';return;}
  let html=`<div style="overflow-x:auto"><table style="width:100%;border-collapse:collapse;font-size:.78rem;min-width:620px"><thead><tr style="border-bottom:1px solid #2a2926">
    ${['Settimana','Struttura','Ospiti','Cartelle','Coinvolg.%','Convers.%','€/cartella',''].map(h=>`<th style="padding:8px 6px;color:#555;font-size:.62rem;text-transform:uppercase;letter-spacing:.4px;text-align:${h===''||h==='Ospiti'||h==='Cartelle'||h==='Coinvolg.%'||h==='Convers.%'||h==='€/cartella'?'right':'left'}">${h}</th>`).join('')}
  </tr></thead><tbody>`;
  presenze.forEach(p=>{
    const lun=new Date(p.lun+'T00:00:00'),dom=new Date(p.dom+'T00:00:00');
    const fmt=d=>d.toLocaleDateString('it-IT',{day:'2-digit',month:'short'});
    const settLabel=`${fmt(lun)} – ${fmt(dom)}`;
    const recsS=D.records.filter(r=>{const dt=new Date(r.Anno,r.Mese-1,r.Giorno);return dt>=lun&&dt<=dom;});
    const strP=Object.keys(p.strutture).filter(s=>D.strutture.includes(s));
    if(!strP.length) return;
    const rowspan=strP.length;
    strP.forEach((s,i)=>{
      const ospiti=p.strutture[s]||0,recsStr=recsS.filter(r=>r.Struttura===s);
      const cartelleSet=new Set(recsStr.map(r=>r.Camera).filter(c=>c));
      const cartelle=cartelleSet.size||0;
      const famiglieAcq=new Set(recsStr.filter(r=>r.Camera&&r.Prezzo>0).map(r=>r.Camera)).size;
      const fatturato=recsStr.reduce((t,r)=>t+r.Prezzo,0);
      const coinv=ospiti>0&&cartelle>0?(cartelle/ospiti*100):0;
      const conv=cartelle>0?(famiglieAcq/cartelle*100):0;
      const eurCart=famiglieAcq>0?(fatturato/famiglieAcq):0;
      const coinvCol=coinv>=60?'#34d399':coinv>=30?'#facc15':'#f87171';
      const convCol=conv>=50?'#34d399':conv>=25?'#facc15':'#f87171';
      html+=`<tr style="border-bottom:1px solid #242220">`;
      if(i===0) html+=`<td rowspan="${rowspan}" style="padding:8px 6px;color:#aaa;vertical-align:top;white-space:nowrap">${settLabel}</td>`;
      html+=`<td style="padding:8px 6px;color:#e0e0e0">${s}</td>`;
      html+=`<td style="padding:8px 6px;text-align:right;color:#aaa">${fmtN(ospiti)}</td>`;
      html+=`<td style="padding:8px 6px;text-align:right;color:#e0e0e0">${fmtN(cartelle)}</td>`;
      html+=`<td style="padding:8px 6px;text-align:right;font-weight:700;color:${coinvCol}">${ospiti>0?coinv.toFixed(1)+'%':'—'}</td>`;
      html+=`<td style="padding:8px 6px;text-align:right;font-weight:700;color:${convCol}">${cartelle>0?conv.toFixed(1)+'%':'—'}</td>`;
      html+=`<td style="padding:8px 6px;text-align:right;color:#38bdf8">${famiglieAcq>0?fmtE(eurCart):'—'}</td>`;
      if(i===0) html+=`<td rowspan="${rowspan}" style="padding:8px 6px;vertical-align:top;text-align:center">${PERMS.input_presenze?`<button onclick="deletePresenza('${p.id}')" style="background:none;border:none;color:#444;cursor:pointer;font-size:.9rem">🗑️</button>`:''}</td>`;
      html+=`</tr>`;
    });
  });
  html+='</tbody></table></div>';
  html+=`<div style="margin-top:10px;padding:10px 12px;background:#0d0f1e;border-radius:8px;font-size:.72rem;color:#666;line-height:1.7">
    <b style="color:#888">Legenda calcoli:</b><br>
    📁 <b>Cartelle</b> = famiglie fotografate (cartelle uniche nel periodo)<br>
    👥 <b>Coinvolgimento%</b> = Cartelle / Ospiti × 100 — quante famiglie sono state fotografate<br>
    ✅ <b>Conversione%</b> = Famiglie che hanno acquistato / Cartelle × 100<br>
    💶 <b>€/cartella</b> = Fatturato / Famiglie acquirenti
  </div>`;
  box.innerHTML=html;
}

function checkPresenzeAlert(){
  const modal=document.getElementById('presenzeModal');
  if(!modal || !PERMS.input_presenze) return;
  const today=new Date(); today.setHours(0,0,0,0);
  const dow=today.getDay()||7;
  const lun=new Date(today); lun.setDate(today.getDate()-(dow-1));
  const lunStr=lun.toISOString().slice(0,10);
  const entry=PRESENCES.presenze.find(p=>p.lun===lunStr);
  const mieStrutture=D.strutture;
  const hasDati=entry && mieStrutture.some(s=>(entry.strutture||{})[s]>0);
  if(!hasDati){
    const dom=new Date(lun); dom.setDate(lun.getDate()+6);
    const fmt=d=>d.toLocaleDateString('it-IT',{day:'2-digit',month:'long'});
    document.getElementById('presenzeModalMsg').innerHTML=
      `<b>Settimana ${fmt(lun)} – ${fmt(dom)}</b><br><br>`+
      mieStrutture.map(s=>`&nbsp;&nbsp;🏖️ <b>${s}</b>`).join('<br>')+
      `<br><br>Inserisci il numero di ospiti presenti in struttura per calcolare correttamente il tasso di conversione.`;
    modal.style.display='flex';
  }
}
function chiudiModalPresenze(){
  document.getElementById('presenzeModal').style.display='none';
}
function vaiAPresenze(){
  chiudiModalPresenze();
  // Apre il tab Presenze e scrolla al form
  const tabBtn=document.querySelector('.tab[data-tab="6"]');
  if(tabBtn) tabBtn.click();
  setTimeout(()=>{
    const el=document.getElementById('presenzeFormBox');
    if(el) el.scrollIntoView({behavior:'smooth',block:'start'});
  },150);
}

fStr.addEventListener('change',()=>{updateFotografi();render();});
fFoto.addEventListener('change',render);

updateFotografi();
setPreset('anno_cur');
initTabs();
initPresForm();
// Mostra popup solo se già loggato (sessione attiva da reload/riapertura)
if(sessionStorage.getItem('pm_user_auth')==='1') checkPresenzeAlert();
document.getElementById('footer').textContent='Aggiornato: '+new Date().toLocaleDateString('it-IT')+' · PhotographerManager';
render();

// ── Alert Spectre (sola lettura — senza export/clean) ────────────────────────
let _alertPanelOpen = false;
function aggiornaAlertsU() {
  if (!PERMS.alerts) return;
  if (sessionStorage.getItem('pm_user_auth') !== '1') return;
  fetch('/spectre-alerts')
    .then(r => r.json())
    .then(data => {
      const tutti    = data.alerts || [];
      const nonLetti = tutti.filter(a => !a.letto);
      const bell  = document.getElementById('bellBtn');
      const count = document.getElementById('bellCount');
      const wrap  = document.getElementById('bellWrap');
      if (!bell || !wrap) return;
      if (tutti.length === 0) {
        wrap.style.display = 'none';
      } else if (nonLetti.length > 0) {
        wrap.style.display = 'block';
        bell.style.color = '#f87171';
        bell.style.borderColor = '#f87171';
        count.textContent = nonLetti.length;
        count.style.display = 'inline';
      } else {
        wrap.style.display = 'block';
        bell.style.color = '#555';
        bell.style.borderColor = '#383530';
        count.style.display = 'none';
      }
      if (_alertPanelOpen) renderAlertPanelU(tutti);
    })
    .catch(() => {});
}
function renderAlertPanelU(tutti) {
  const body = document.getElementById('alertPanelBody');
  if (!body) return;
  if (!tutti.length) {
    body.innerHTML = '<div style="color:#555;text-align:center;padding:40px 0;font-size:.88rem">Nessun alert ricevuto</div>';
    return;
  }
  body.innerHTML = tutti.slice().reverse().map((a, i) => {
    const idx = tutti.length - 1 - i;
    return `<div style="background:${a.letto?'#242220':'#1a1030'};border-radius:8px;padding:10px 12px;margin-bottom:8px;
      border-left:3px solid ${a.letto?'#383530':'#f87171'}">
      <div style="font-size:.72rem;color:#555;margin-bottom:4px">${a.timestamp||''} · ${a.postazione||''}</div>
      <div style="font-size:.82rem;color:${a.letto?'#666':'#e0e0e0'}">${a.messaggio||''}</div>
      ${!a.letto?`<button onclick="segnaLettoU(${idx})"
        style="margin-top:6px;background:none;border:none;color:#cc5a2a;font-size:.72rem;cursor:pointer;padding:0">
        \u2713 Segna come letto</button>`:''}
    </div>`;
  }).join('');
}
function toggleAlertPanel() {
  _alertPanelOpen = !_alertPanelOpen;
  const panel    = document.getElementById('alertPanel');
  const backdrop = document.getElementById('alertBackdrop');
  if (_alertPanelOpen) {
    panel.style.display = 'block';
    backdrop.style.display = 'block';
    fetch('/spectre-alerts').then(r => r.json())
      .then(d => renderAlertPanelU(d.alerts || [])).catch(() => {});
  } else {
    panel.style.display = 'none';
    backdrop.style.display = 'none';
  }
}
function segnaLettoU(idx) {
  fetch('/segna-alert-letto', {
    method: 'POST', headers: {'Content-Type': 'application/json'},
    body: JSON.stringify({idx: idx})
  }).then(() => {
    aggiornaAlertsU();
    fetch('/spectre-alerts').then(r=>r.json()).then(d=>renderAlertPanelU(d.alerts||[])).catch(()=>{});
  }).catch(() => {});
}
function segnaTestiLettiU() {
  fetch('/segna-tutti-letti', {
    method: 'POST', headers: {'Content-Type': 'application/json'},
    body: JSON.stringify({})
  }).then(() => {
    aggiornaAlertsU();
    fetch('/spectre-alerts').then(r=>r.json()).then(d=>renderAlertPanelU(d.alerts||[])).catch(()=>{});
  }).catch(() => {});
}
if (PERMS.alerts) {
  aggiornaAlertsU();
  setInterval(aggiornaAlertsU, 60000);
}

// ── Agenda Shooting ────────────────────────────────────────────────────────────
let _agendaSlots = [];
let _agendaCurrentStr = '';
let _agendaInited = false;

function initAgenda() {
  const strs = D.strutture;
  if (!strs || !strs.length) return;
  const wrap = document.getElementById('agendaStrWrap');
  const sel  = document.getElementById('agendaStr');
  if (strs.length > 1) {
    sel.innerHTML = strs.map(s => `<option value="${s}">${s}</option>`).join('');
    wrap.style.display = 'block';
    if (!_agendaInited) loadAgendaStr(strs[0]);
  } else {
    if (wrap) wrap.style.display = 'none';
    if (!_agendaInited) loadAgendaStr(strs[0]);
  }
  _agendaInited = true;
  const slotData = document.getElementById('slotData');
  if (slotData && !slotData.value) slotData.value = new Date().toISOString().split('T')[0];
}

function loadAgendaStr(struttura) {
  _agendaCurrentStr = struttura;
  _agendaInited = true;
  fetch('/get-slots?s=' + encodeURIComponent(struttura))
    .then(r => r.json())
    .then(d => {
      document.getElementById('agendaWA').value   = d.whatsapp || '';
      document.getElementById('agendaNote').value = d.note     || '';
      _agendaSlots = d.slots || [];
      renderAgendaSlots();
    }).catch(() => {
      _agendaSlots = [];
      renderAgendaSlots();
    });
}

function renderAgendaSlots() {
  const el = document.getElementById('agendaSlotsList');
  if (!el) return;
  if (!_agendaSlots.length) {
    el.innerHTML = '<div style="color:#555;font-size:.82rem;padding:8px 0;text-align:center">Nessuno slot configurato. Aggiungi una data e un orario sopra.</div>';
    return;
  }
  const sorted = [..._agendaSlots].sort((a, b) => (a.data + a.ora) < (b.data + b.ora) ? -1 : 1);
  el.innerHTML = sorted.map((s) => {
    const origIdx = _agendaSlots.indexOf(s);
    const dateLabel = s.data ? new Date(s.data + 'T12:00:00').toLocaleDateString('it-IT', {weekday:'short',day:'numeric',month:'short'}) : s.data;
    const clienteInfo = [s.nome, s.camera ? 'cam. ' + s.camera : ''].filter(Boolean).join(' — ');
    const isBooked = s.prenotato || s.nome;
    return `<div style="background:#2a2926;border-radius:8px;padding:10px 12px;display:flex;justify-content:space-between;align-items:center;border:1px solid ${isBooked ? '#34d39944' : '#383530'}">
      <div style="display:flex;flex-direction:column;gap:4px">
        <div style="display:flex;align-items:center;gap:10px;flex-wrap:wrap">
          <span style="color:#fff;font-weight:600;font-size:.88rem">\u{1f4c5} ${dateLabel}</span>
          <span style="color:#cc5a2a;font-size:.88rem">\u{1f550} ${s.ora}</span>
          ${isBooked ? '<span style="background:#34d399;color:#1a1917;border-radius:4px;padding:2px 7px;font-size:.7rem;font-weight:700">PRENOTATO</span>' : '<span style="background:#383530;color:#555;border-radius:4px;padding:2px 7px;font-size:.7rem">libero</span>'}
        </div>
        ${clienteInfo ? `<div style="font-size:.78rem;color:#34d399">\u{1f464} ${clienteInfo}</div>` : ''}
      </div>
      <button onclick="removeAgendaSlot(${origIdx})"
        style="background:none;border:none;color:#f87171;font-size:1.1rem;cursor:pointer;padding:2px 6px;opacity:.7"
        title="Rimuovi slot">\u{1f5d1}\ufe0f</button>
    </div>`;
  }).join('');
}

function addAgendaSlot() {
  const data   = document.getElementById('slotData').value;
  const ora    = document.getElementById('slotOra').value;
  const nome   = document.getElementById('slotNome').value.trim();
  const camera = document.getElementById('slotCamera').value.trim();
  if (!data) { alert('Inserisci la data'); return; }
  if (!ora)  { alert('Inserisci l\'orario'); return; }
  if (_agendaSlots.some(s => s.data === data && s.ora === ora)) {
    alert('Slot gi\u00e0 presente per questa data e orario'); return;
  }
  _agendaSlots.push({ data, ora, nome, camera, prenotato: !!nome });
  document.getElementById('slotNome').value = '';
  document.getElementById('slotCamera').value = '';
  renderAgendaSlots();
}

function removeAgendaSlot(idx) {
  _agendaSlots.splice(idx, 1);
  renderAgendaSlots();
}

function saveAgenda(e) {
  const btn = e ? e.currentTarget || e.target : document.querySelector('#pane7 button[onclick*="saveAgenda"]');
  if (!_agendaCurrentStr) { alert('Seleziona una struttura'); return; }
  const wa   = document.getElementById('agendaWA').value.trim();
  const note = document.getElementById('agendaNote').value.trim();
  if (btn) { btn.disabled = true; btn.textContent = '\u23f3 Salvataggio...'; }
  fetch('/save-slots', {
    method: 'POST', headers: {'Content-Type': 'application/json'},
    body: JSON.stringify({ auth: _MYPASS, struttura: _agendaCurrentStr, whatsapp: wa, note, slots: _agendaSlots })
  }).then(r => r.json()).then(d => {
    if (btn) { btn.disabled = false; btn.textContent = '\ud83d\udcbe Salva agenda'; }
    const msg = document.getElementById('agendaSaveMsg');
    if (d.ok) {
      msg.textContent = '\u2705 Agenda salvata con successo!';
      msg.style.color = '#34d399'; msg.style.background = '#1a2e25';
    } else {
      msg.textContent = '\u274c Errore: ' + (d.error || 'Non autorizzato');
      msg.style.color = '#f87171'; msg.style.background = '#2e1a1a';
    }
    msg.style.display = 'block';
    setTimeout(() => { msg.style.display = 'none'; }, 3500);
  }).catch(() => {
    if (btn) { btn.disabled = false; btn.textContent = '\ud83d\udcbe Salva agenda'; }
    alert('Errore di connessione al server.');
  });
}
</script>
</body>
</html>"""

if __name__=="__main__":
    main()
