/** * sales_help.js - Guida contestuale delle pagine statistiche vendite. * * Uso nelle pagine: *
Qui vedi gli ordini clienti del periodo scelto: quanti sono, quanto valgono, a che punto sono.
Gli ordini con la parola "listino" sono esclusi. I filtri restano memorizzati quando torni sulla pagina; la gomma 🧽 li azzera.
`, }, "page.years": { t: "Confronto anni: come si usa", b: `Qui confronti gli anni tra loro e vedi la situazione ad oggi.
Cliente, agente e area filtrano tutto, anche il fatturato.
`, }, "page.deliveries": { t: "Consegne: come si usa", b: `Qui vedi le righe d'ordine ancora da consegnare, cioè il lavoro da spedire.
Cosa fare: parti dalle scadute, poi guarda i prossimi giorni e le settimane più cariche del grafico.
`, }, "page.customer": { t: "Scheda cliente: come si usa", b: `Tutto su un cliente in una pagina. Cercalo per nome o codice, oppure clicca l'icona verde accanto a un cliente nelle altre pagine.
Utile prima di una telefonata o di una visita. I clienti visti di recente restano a portata di clic.
`, }, "page.summary": { t: "Sommario: come si legge", b: `Il riepilogo per la direzione: in un colpo d'occhio cosa va bene e cosa no.
Il sommario guarda sempre tutta l'azienda ad oggi: non ha filtri. Per approfondire usa le altre pagine.
`, }, /* ===================== SOMMARIO ===================== */ "sm.flow": { t: "Nuovi ordini", b: `Quanti ordini sono entrati (per data ordine) e quanto valgono, annullati esclusi:
▲ verde = più della volta prima · ▼ rosso = meno.
"Oggi" va letto a fine giornata: al mattino è normale che sia basso.
`, }, "sm.invYtd": { t: "Fatturato dell'anno", b: `Fatturato da gennaio a oggi rispetto allo stesso periodo dell'anno scorso.
🟢 almeno +3% · 🟡 tra −3% e +3% · 🔴 sotto −3%.
`, }, "sm.ordYtd": { t: "Ordinato dell'anno", b: `Ordini ricevuti da gennaio a oggi rispetto allo stesso periodo dell'anno scorso. È il fatturato dei prossimi mesi.
🟢 almeno +3% · 🟡 tra −3% e +3% · 🔴 sotto −3%.
`, }, "sm.forecast": { t: "Chiusura prevista", b: `Come chiuderà l'anno se si continua con lo stesso ritmo degli anni scorsi, confrontata con l'anno scorso intero.
🟢 almeno +3% · 🟡 tra −3% e +3% · 🔴 sotto −3%.
È una stima: diventa più affidabile man mano che l'anno avanza.
`, }, "sm.b2b": { t: "Book-to-bill", b: `Ordini entrati ÷ fatture emesse negli ultimi 90 giorni. Dice se il lavoro in arrivo tiene il passo con quello che consegniamo.
🟢 da 1,05 (il portafoglio cresce) · 🟡 tra 0,95 e 1,05 · 🔴 sotto 0,95 (lo stiamo consumando).
Il grafico mostra lo stesso valore mese per mese (su 3 mesi): la riga tratteggiata è 1.
`, }, "sm.cover": { t: "Lavoro in portafoglio", b: `Per quante settimane di lavoro basta quello che abbiamo da consegnare, al ritmo di fatturato degli ultimi 3 mesi.
🟢 almeno 8 settimane · 🟡 da 4 a 8 · 🔴 meno di 4.
`, }, "sm.late": { t: "Consegne in ritardo", b: `Quanta parte del portafoglio è già oltre la settimana ZIBO comunicata al cliente.
🟢 fino al 10% · 🟡 dal 10 al 25% · 🔴 oltre il 25%.
Cosa fare: apri Consegne e parti dalle righe scadute.
`, }, "sm.risk": { t: "Clienti a rischio", b: `Clienti abituali dormienti o probabilmente persi e quanto valevano in un anno, rispetto al giro d'affari totale.
🟢 fino al 3% · 🟡 dal 3 all'8% · 🔴 oltre l'8%.
Cosa fare: lista "Da richiamare subito" qui sotto, o quella completa in Confronto anni.
`, }, "sm.top5": { t: "Peso dei primi 5 clienti", b: `Quanto del fatturato degli ultimi 12 mesi viene dai 5 clienti più grandi. Più è alto, più dipendiamo da pochi nomi.
🟢 fino al 40% · 🟡 dal 40 al 60% · 🔴 oltre il 60%.
`, }, "sm.customers": { t: "Clienti attivi", b: `Clienti che hanno ordinato negli ultimi 12 mesi, confrontati con i 12 mesi prima. "Nuovi" = primo ordine nell'ultimo anno.
🟢 stabili o in crescita · 🟡 fino a −5% · 🔴 oltre −5%.
`, }, "sm.cn": { t: "Note di credito", b: `Note di credito degli ultimi 12 mesi in percentuale sul fatturato: misura resi, sconti e contestazioni.
🟢 fino all'1,5% · 🟡 dall'1,5 al 3% · 🔴 oltre il 3%.
`, }, "sm.up": { t: "Clienti che crescono", b: `I clienti che hanno aumentato di più (in euro) negli ultimi 12 mesi rispetto ai 12 precedenti. Da coltivare.
`, }, "sm.down": { t: "Clienti che calano", b: `I clienti che sono diminuiti di più (in euro) negli ultimi 12 mesi rispetto ai 12 precedenti.
Cosa fare: capire il motivo (concorrenza, prezzi, problemi di consegna) con una telefonata.
`, }, "sm.call": { t: "Da richiamare subito", b: `I clienti abituali più importanti che si sono fermati (dormienti o probabilmente persi), ordinati per valore.
`, }, /* ===================== ANDAMENTO ORDINI ===================== */ "st.orders": { t: "Ordini", b: `Numero di ordini del periodo e dei filtri scelti. Sotto: confronto con lo stesso periodo dell'anno prima.
Clic sul box: toglie il filtro di stato e mostra tutti gli ordini.
`, }, "st.value": { t: "Valore ordinato", b: `Somma dell'imponibile degli ordini del periodo (annullati esclusi), con il confronto con lo stesso periodo dell'anno prima.
`, }, "st.toship": { t: "Da evadere", b: `Valore degli ordini ancora aperti (non consegnati del tutto). In rosso la parte già in ritardo.
Cosa fare: se la quota in ritardo cresce, guarda la pagina Consegne.
`, }, "st.open": { t: "Aperti", b: `Ordini non ancora consegnati del tutto e non annullati. Clic per vederli.
`, }, "st.late": { t: "In ritardo", b: `Ordini con almeno una riga aperta oltre la data ZIBO (la settimana comunicata è finita).
Cosa fare: clic sul box per la lista, poi apri gli ordini per vedere quali righe mancano.
`, }, "st.done": { t: "Evasi", b: `Ordini completamente consegnati nel periodo scelto (per data ordine).
`, }, "st.toinvoice": { t: "Da fatturare", b: `Ordini consegnati ma non ancora fatturati.
Cosa fare: segnalali all'amministrazione se restano qui a lungo.
`, }, "st.customers": { t: "Clienti attivi", b: `Quanti clienti diversi hanno ordinato nel periodo. Sotto: in media dopo quanti giorni dall'ordine è prevista la consegna.
`, }, "st.monthly": { t: "Andamento mensile", b: `Ordini (o valore) mese per mese nel periodo scelto. Clic su un mese per filtrare solo quel mese.
`, }, "st.status": { t: "Ripartizione per stato", b: `Come si dividono gli ordini: aperti, evasi, bloccati, annullati. Clic su una fetta per filtrare.
`, }, "st.topcust": { t: "Top 10 clienti", b: `I 10 clienti più importanti del periodo (per numero ordini o valore). Le barre sono divise tra ordini aperti e altri (evasi/annullati).
Clic su un cliente per vedere solo i suoi ordini.
`, }, "st.due": { t: "Scadenze ordini aperti", b: `Gli ordini aperti divisi per quando vanno consegnati: già scaduti, questa settimana, la prossima, entro 30 giorni, oltre, senza data.
`, }, "st.items": { t: "Top 10 articoli", b: `Gli articoli più ordinati nel periodo, calcolati dalle righe d'ordine. Passa sopra una barra per quantità e valore.
`, }, "st.area": { t: "Per area", b: `Ordini (o valore) divisi per area commerciale.
`, }, "st.agent": { t: "Per agente", b: `Ordini (o valore) divisi per agente.
`, }, "st.list": { t: "Elenco ordini", b: `Tutti gli ordini dei filtri scelti. Clic su una riga per il dettaglio con le righe, le date e cosa resta da consegnare.
Una fotografia di oggi, che non cambia con gli anni scelti. Segue solo i filtri cliente, agente e area (così puoi vederla anche per un agente o un cliente).
`, }, "yr.backlog": { t: "Portafoglio da consegnare", b: `Valore di tutte le righe d'ordine ancora da consegnare.
Poche settimane = servono ordini nuovi. Tante settimane con molto in ritardo = c'è un problema di capacità o di consegne.
`, }, "yr.b2b": { t: "Book-to-bill", b: `Confronta il lavoro che entra (ordini) con quello che esce (fatture) negli ultimi 90 giorni.
È un segnale che arriva prima del calo di fatturato.
`, }, "yr.fcInv": { t: "Previsione fatturato", b: `Stima di come chiuderà l'anno. Si prende il fatturato ad oggi e lo si proietta con la stagionalità degli ultimi 3 anni (es. se negli anni scorsi a questa data eravamo al 78% dell'anno, oggi siamo probabilmente al 78%).
La forbice va dall'anno più favorevole a quello meno favorevole. Diventa più precisa man mano che l'anno avanza.
`, }, "yr.fcOrd": { t: "Previsione ordinato", b: `Come la previsione del fatturato, ma sugli ordini ricevuti: quanto ordinato porteremo a casa entro fine anno se si continua così.
`, }, "yr.b2bchart": { t: "Ordinato vs fatturato · 24 mesi", b: `Barre viola = ordini ricevuti nel mese · barre verdi = fatturato del mese.
La linea arancione è il book-to-bill su 3 mesi: sopra la riga tratteggiata dell'1 il portafoglio cresce, sotto si consuma.
Se la linea resta sotto 1 per diversi mesi, è il momento di spingere sugli ordini.
`, }, "yr.cards": { t: "Anni a confronto", b: `Una carta per ogni anno scelto: valore ordinato (numero grande), numero ordini, ordine medio, clienti, fatturato e variazione rispetto all'anno prima.
Con A pari data acceso ogni anno è contato fino a oggi: il confronto con l'anno in corso è corretto.
`, }, "yr.monthly": { t: "Ordinato per mese", b: `Una linea per anno, mese per mese: mostra la stagionalità e in quali mesi quest'anno va meglio o peggio.
`, }, "yr.cumul": { t: "Progressivo dell'anno", b: `Somma da gennaio a ogni mese. Se la linea dell'anno in corso è sopra quelle degli anni scorsi, siamo avanti; se è sotto, siamo indietro.
`, }, "yr.invMonthly": { t: "Fatturato per mese", b: `Fatturato vero per data della fattura: fatture + fatture d'acconto − note di credito (imponibile).
È sempre in €, anche se in alto è selezionato "N° ordini".
`, }, "yr.invCumul": { t: "Fatturato progressivo", b: `Fatturato sommato da gennaio, anno su anno: dice se stiamo fatturando più o meno degli anni scorsi alla stessa data.
`, }, "yr.invTable": { t: "Tabella dati fatturato", b: `Gli stessi numeri dei grafici in tabella: per mese (con progressivo e variazione) oppure l'elenco delle fatture e note di credito.
Pulsante Excel per scaricarli: il titolo del file riporta i filtri usati.
`, }, "yr.dormant": { t: "Clienti da richiamare", b: `Clienti che ordinavano con regolarità (almeno 4 volte negli ultimi 3 anni) e che ora tardano rispetto al loro solito.
Cosa fare: chiamare partendo dall'alto. Esporta in Excel per dividerli tra i commerciali.
`, }, "yr.custcmp": { t: "Clienti a confronto", b: `Ogni cliente con il suo valore (o numero ordini) negli anni scelti e la variazione tra gli ultimi due.
Clic su un cliente per filtrare la pagina; l'icona verde apre la sua scheda.
`, }, "yr.ytd": { t: "A pari data", b: `Acceso: ogni anno è contato solo fino al giorno di oggi (es. 1 gennaio – 15 ottobre). È il modo giusto per confrontare l'anno in corso con i precedenti.
Spento: anni interi (l'anno in corso sembrerà sempre più basso finché non finisce).
`, }, /* ===================== CONSEGNE ===================== */ "dl.horizon": { t: "Scadenza", b: `Filtra le righe per quando vanno consegnate: scadute (data ZIBO o data cliente), questa settimana, la prossima, entro 30 giorni, senza data.
`, }, "dl.total": { t: "Da consegnare", b: `Tutte le righe ancora da consegnare (con i filtri scelti) e il loro valore residuo (solo la parte non ancora consegnata).
`, }, "dl.lateZibo": { t: "Scadute (data ZIBO)", b: `Righe la cui settimana ZIBO è finita senza consegna: sono i ritardi veri verso il cliente.
Cosa fare: sono la priorità. Clic sul box per vederle tutte.
`, }, "dl.lateClient": { t: "Oltre data cliente", b: `Righe dove è superata la data desiderata dal cliente. Non sono necessariamente in ritardo per noi, ma il cliente potrebbe sollecitare.
`, }, "dl.next7": { t: "Prossimi 7 giorni", b: `Righe da consegnare da oggi ai prossimi 7 giorni. Clic per vederle.
`, }, "dl.nodate": { t: "Senza data", b: `Righe senza nessuna data di consegna in Mago.
Cosa fare: vanno completate in Mago, altrimenti non si possono pianificare.
`, }, "dl.weekly": { t: "Carico consegne per settimana", b: `Quanto c'è da consegnare settimana per settimana (per data ZIBO; se manca, data cliente). La prima barra rossa raccoglie tutto lo scaduto.
Serve a vedere le settimane troppo cariche. Clic su una barra per filtrare quella settimana.
`, }, "dl.lateCust": { t: "Clienti con più ritardo", b: `I clienti con più valore scaduto (data ZIBO superata). Clic per vedere solo le loro righe.
Utile per sapere chi avvisare per primo.
`, }, "dl.rows": { t: "Righe da consegnare", b: `Ogni riga: ordine, cliente, articolo, quantità ancora da consegnare, valore e date.
Pulsante Excel per scaricare l'elenco filtrato.
`, }, /* ===================== SCHEDA CLIENTE ===================== */ "sc.status": { t: "Stato del cliente", b: `Calcolato sul suo ritmo d'ordine degli ultimi 3 anni:
Fatturato del cliente da gennaio ad oggi, confrontato con lo stesso periodo dell'anno scorso. Sotto: l'anno scorso intero.
`, }, "sc.ord": { t: "Ordinato dell'anno", b: `Ordini ricevuti dal cliente da gennaio ad oggi, confrontati con lo stesso periodo dell'anno scorso.
Ordinato in calo e fatturato ancora alto = il fatturato calerà nei prossimi mesi.
`, }, "sc.open": { t: "Da consegnare", b: `Valore di quello che gli dobbiamo ancora consegnare e quante righe sono in ritardo (data ZIBO superata).
Prima di chiamarlo, guarda la scheda "Da consegnare" qui sotto.
`, }, "sc.cn": { t: "Note di credito", b: `Note di credito degli ultimi 12 mesi e quanto pesano sul fatturato. Diventa rosso dal 3%.
Una percentuale alta indica resi, contestazioni o problemi di qualità ricorrenti.
`, }, "sc.years": { t: "Ordinato e fatturato per anno", b: `Come è cresciuto (o calato) il cliente negli anni. L'anno in corso è ad oggi, quindi più basso finché l'anno non finisce.
`, }, "sc.months": { t: "Ultimi 24 mesi", b: `Ordini (viola) e fatture (verde) mese per mese: mostra se il cliente ordina con regolarità o a picchi, e se si sta fermando.
`, }, "sc.tables": { t: "Le tabelle", b: `Ogni tabella ha il suo pulsante Excel.
`, }, /* ===================== MATRICI ===================== */ "page.matrici": { t: "Matrici: come si legge", b: `A che prezzo vendiamo ogni matrice, nell'unità in cui la vendiamo: €/metro se a metri, €/kg se a chili. E quanta mescola consuma.
Le mescole sono una stima dall'ultima scheda di lavoro, senza scarto. Le righe a pezzi aspettano la conversione pezzi → metri.
`, }, "mx.types": { t: "Tipo", b: `Il tipo viene dalla lettera iniziale del campo Matrice/Misura di Mago:
Avvisi accanto alle matrici: non in anagrafica codice che non esiste in anagrafica · altra revisione revisione diversa da quella in anagrafica · abbinata a mano da "Ricorda corrispondenza".
Da sistemare raccoglie matrici non in anagrafica, altre revisioni e valori non riconosciuti.
`, }, "mx.k.value": { t: "Venduto con matrice", b: `Imponibile delle righe d'ordine del periodo che hanno il campo Matrice/Misura compilato, con il numero di matrici dell'anagrafica e di clienti.
`, }, "mx.k.qty": { t: "Venduto a metri / a chili", b: `Quantità venduta nel periodo e prezzo medio (imponibile ÷ quantità) su tutte le righe in quell'unità.
Clic sul box per vedere solo le matrici vendute in quell'unità.
`, }, "mx.k.mix": { t: "Mescola consumata", b: `Kg di mescola stimati per le righe vendute nel periodo.
Ancora da produrre: kg necessari per le righe ancora da consegnare (qualsiasi data). È la base per gli acquisti di mescola.
`, }, "mx.k.pz": { t: "Venduto a pezzi", b: `Righe vendute a pezzi (UM N.). Il prezzo al pezzo c'è, ma la mescola non si può stimare finché non c'è la conversione pezzi → metri.
`, }, "mx.k.cover": { t: "Copertura anagrafica", b: `Quanta parte del venduto è collegata a una matrice dell'anagrafica (verde), quanta è tubi, rettangoli, diametri e altri profili (viola), quanta resta da sistemare (arancio).
Cosa fare: clic sul box per la lista "Da sistemare" e completare l'anagrafica matrici o le corrispondenze.
`, }, "mx.k.margin": { t: "Margine sul grezzo", b: `Quanto resta del prezzo di vendita dopo il costo della sola mescola, sulle matrici dove il costo è completo.
Non comprende scarto, lavorazione, energia e trasporto: è il margine "lordo di mescola".
`, }, "mx.margin": { t: "Margine sul costo mescola", b: `Margine più basso: le matrici dove il prezzo copre meno il costo della mescola. Sono le prime da rivedere nei listini.
Più margine in euro: le matrici che portano più margine nel periodo (margine unitario × quantità).
🟢 da 60% · 🟡 da 40 a 60% · 🔴 sotto 40%.
Contano solo le matrici con costo completo. Clic su una matrice per il dettaglio con la linea del costo nel grafico.
`, }, /* ===================== PREVENTIVO ===================== */ "page.quote": { t: "Preventivo: come si usa", b: `I preventivi salvati restano in fondo alla pagina e si riaprono con un clic. Stampa per avere un foglio pulito.
`, }, "pv.cost": { t: "Costo", b: `Le correzioni valgono solo per questo preventivo e vengono salvate con lui.
`, }, "pv.scrap": { t: "Scarto %", b: `Percentuale di mescola persa in produzione (avvii, sfridi, scarti). Il costo della mescola viene aumentato di questa percentuale.
`, }, "pv.other": { t: "Altri costi", b: `Costi per metro o per kg da aggiungere alla mescola: lavorazioni esterne (biadesivo, giunzione, raspatura), imballo, trasporto, quota di lavorazione.
`, }, "pv.price": { t: "Prezzo suggerito", b: `Prezzo suggerito = costo totale × (1 + ricarico %). Es. costo 0,50 €/m con ricarico 100% → 1,00 €/m.
Il pulsante come mercato usa il ricarico che oggi si ottiene con il prezzo medio di vendita della matrice.
🟢 margine da 60% · 🟡 da 40 a 60% · 🔴 sotto 40% (margine = (prezzo − costo) ÷ prezzo).
`, }, "pv.offered": { t: "Prezzo proposto", b: `È il prezzo che finisce nel preventivo: parte dal suggerito e si può arrotondare a mano. Accanto, il margine che ne risulta.
`, }, "pv.refs": { t: "Confronto", b: `Mese per mese: costo della mescola (con i prezzi pagati in quel mese), prezzo medio di tutti i clienti e del cliente scelto. Le righe orizzontali sono il costo totale e il prezzo proposto.
Se la linea del costo sale e quella dei prezzi no, il margine si sta riducendo.
`, }, "mx.map": { t: "Mappa dei prezzi", b: `Ogni bolla è una matrice venduta nel periodo (le prime 150 per valore).
Le bolle in basso a destra sono matrici molto vendute a prezzo basso: le prime da guardare per un aumento.
`, }, "mx.moves": { t: "Prezzi in movimento", b: `Prezzo medio degli ultimi 12 mesi rispetto ai 12 mesi precedenti, per le matrici vendute in entrambi i periodi.
Serve a verificare che gli aumenti di listino siano stati applicati e a scoprire cali non voluti.
`, }, "mx.table": { t: "Classifica matrici", b: `La stessa matrice venduta a metri e a chili compare su due righe.
`, }, "mx.mix": { t: "Mescole consumate per mese", b: `Kg di mescola stimati dalle vendite, mese per mese.
Per ora senza scarto.
`, }, "mx.mixneed": { t: "Fabbisogno mescole", b: `Venduto: kg di mescola delle righe ordinate nel periodo.
Da produrre: kg che servono per le righe ancora da consegnare, qualsiasi sia la data dell'ordine.
Quando avremo il costo delle mescole, da qui si calcolerà anche il costo grezzo.
`, }, "mx.dprice": { t: "Prezzo nel tempo", b: `Ogni punto è una riga d'ordine: altezza = prezzo, colore = cliente (i primi 8 per valore, gli altri insieme).
La linea scura è il prezzo medio del mese. Punti sotto la linea = clienti che pagano meno della media.
La linea rossa tratteggiata è il costo della mescola mese per mese (prezzi pagati in quel mese): la distanza dalla linea dei prezzi è il margine.
Nella tabella Clienti, "Rispetto alla media" mostra di quanto ognuno paga più o meno, "Margine" quanto resta dopo la mescola.
`, }, }; /* ===================== STILE ===================== */ const CSS = ` .sh-btn{border:0;background:transparent;color:#94a3b8;padding:0 3px;margin-left:4px;font-size:.92em;line-height:1;cursor:pointer;vertical-align:baseline;text-transform:none;letter-spacing:0} .sh-btn:hover,.sh-btn.open{color:#198754} .sh-page{border:1px solid #d1fae5;background:#f0fdf4;color:#166534;border-radius:999px;padding:6px 14px;font-weight:700;font-size:.88rem;cursor:pointer;white-space:nowrap} .sh-page:hover{background:#dcfce7} .sh-pop{position:absolute;z-index:2000;width:340px;max-width:calc(100vw - 24px);background:#fff;border:1px solid #e2e8f0;border-radius:14px; box-shadow:0 18px 40px rgba(15,23,42,.18);padding:14px 16px 12px;font-size:.9rem;color:#1f2d3d;line-height:1.45;text-transform:none;letter-spacing:0;font-weight:400} .sh-pop.wide{width:460px} .sh-pop h6{font-weight:800;font-size:.98rem;margin:0 26px 8px 0;display:flex;align-items:center;gap:8px} .sh-pop h6 i{color:#198754} .sh-pop p{margin:0 0 8px} .sh-pop ul{margin:0 0 8px;padding-left:18px} .sh-pop li{margin-bottom:4px} .sh-pop .sh-note{background:#f0fdf4;border-left:3px solid #22c55e;padding:6px 10px;border-radius:6px;color:#14532d;margin:8px 0 0} .sh-pop .sh-x{position:absolute;right:8px;top:8px;border:0;background:transparent;color:#94a3b8;font-size:1.1rem;cursor:pointer;line-height:1;padding:4px} .sh-pop .sh-x:hover{color:#1f2d3d} .sh-chip{display:inline-block;font-size:.72rem;font-weight:800;border-radius:999px;padding:1px 8px;white-space:nowrap} .sh-red{background:#fee2e2;color:#991b1b}.sh-orange{background:#ffedd5;color:#9a3412}.sh-amber{background:#fef3c7;color:#b45309} .sh-yellow{background:#fef9c3;color:#854d0e}.sh-green{background:#dcfce7;color:#166534}.sh-grey{background:#e2e8f0;color:#334155}`; function injectCss() { if (document.getElementById("sales-help-css")) return; const st = document.createElement("style"); st.id = "sales-help-css"; st.textContent = CSS; document.head.appendChild(st); } /* ===================== POPOVER ===================== */ let pop = null, popBtn = null; function close() { if (pop) pop.remove(); if (popBtn) popBtn.classList.remove("open"); pop = null; popBtn = null; } function open(btn, key, wide) { const h = SALES_HELP[key]; if (!h) return; if (popBtn === btn) { close(); return; } close(); pop = document.createElement("div"); pop.className = "sh-pop" + (wide ? " wide" : ""); pop.setAttribute("role", "dialog"); pop.innerHTML = `