# HABEOPURE — DOSSIER TECNICO DELLO STATO ATTUALE Versione fotografia: 2026-09-18 Sito pubblico: https://paga-sicuro.lovable.app Nessun dato reale di utenti in questo documento. ==================================================================== 1. PANORAMICA ==================================================================== COS'È Applicazione web (installabile come app sul telefono) per professionisti con entrate irregolari: calcola quanto del fatturato è davvero disponibile. Accesso con email o Google; i dati di ogni utente sono privati e protetti. Abbonamento: €15,99/mese o €159,90/anno (offerta FOUNDERS €11,99/mese o €119,90/anno per i primi 100 utenti), disdetta libera. SEZIONI PER L'UTENTE Reddito reale, entrate, spese, impegni, consuntivo mensile, vista mesi futuri, scenari, stipendio, cash flow, obiettivi, la mia situazione. FUNZIONALITÀ PRINCIPALI - Calcolo del Reddito reale e delle metriche derivate (Safe to Spend, Safe Salary, Maximum Theoretical Salary, runway, margine di sicurezza) su orizzonte 12 mesi. - Incassi con valuta estera (cambio BCE/Frankfurter con fallback e cambio manuale), scomposizione cachet / rimborso spese, provvigione agenzia con IVA opzionale, ritenuta d'acconto opzionale. - Impegni futuri datati con flag "potenzialmente deducibile". - Consuntivo mensile (dati reali) e confronto con la stima. - Vista mesi futuri, scenari, cash flow modificabile, obiettivi. - Free/Pro: un solo calcolo gratuito per account (enforcement server-side), metriche Pro offuscate finché l'entitlement non è attivo. STATO ATTUALE Applicazione funzionante end-to-end. Motore finanziario puro e testato. Pagamenti e email di benvenuto attivi nel flusso di acquisto. ==================================================================== 2. MOTORE FINANZIARIO — INPUT -> FORMULA -> OUTPUT ==================================================================== NORMALIZZAZIONE (projection.ts normalize) INPUT PlanInput -> FORMULA: safe() azzera NaN/Infinity, clamp0 azzera i negativi, probabilità limitata a 0-100, taxRate = min(100, max(0, taxPct))/100, deductibleMonthly limitato a businessMonthly, deductibleAmount degli impegni limitato all'importo, horizonMonths = max(1, round(input o 12)), righe con importo 0 scartate -> OUTPUT NormalizedPlan. BASELINE_CONFIDENCE = 1: nessuno sconto prudenziale nascosto. MESE DI COMPETENZA monthIndex = min(horizon-1, max(0, ceil(dueInDays/30) - 1)). Mese 1 = giorni 0-30. Le date oltre l'orizzonte confluiscono nell'ultimo mese. INCASSI PONDERATI (weightedIncomeByMonth) INPUT incomes + expectedMonthlyIncome -> FORMULA: per mese somma amount * probability/100; nei soli mesi senza alcuna fattura inserita aggiunge baselineMonthly * 1 -> OUTPUT array di 12 valori. nominalIncomeByMonth: identica senza ponderazione. SPESE POTENZIALMENTE DEDUCIBILI (deductibleByMonth) INPUT deductibleMonthly + impegni con deductible=true -> FORMULA: ogni mese parte da deductibleMonthly e somma, nel mese di scadenza, deductibleAmount (se indicato) altrimenti l'intero importo -> OUTPUT array mensile. PROIEZIONE 12 MESI (project(plan, salary, requiredBuffer)) Per ogni mese m: income = incassi ponderati(m) deductible = min(income, deducibili(m)) taxableBase = max(0, income - deductible) taxReserve = taxableBase * taxRate closing = opening + income - taxReserve - businessMonthly - obligations(m) - salary belowBuffer = closing < requiredBuffer - 0,005 opening(m+1) = closing(m) OUTPUT: 12 righe MonthProjection. Le spese PERSONALI non compaiono: sono finanziate dallo stipendio (nessun doppio conteggio). MARGINE DI SICUREZZA RICHIESTO (profiles.requiredBufferFor) INPUT profile, minBuffer, personalMonthly, businessMonthly -> FORMULA max(minBuffer * bufferMultiplier, (personal+business) * expenseMonths) con conservative 1,5/3 · balanced 1,2/2 · flexible 1,0/0 -> OUTPUT euro. NOTA: l'app autenticata passa sempre mode "flexible", quindi in pratica requiredBuffer = minBuffer risolto dalle impostazioni. SAFE SALARY (metrics + maxSustainableSalary) INPUT plan + requiredBuffer -> FORMULA: se minBalance(plan, 0) < buffer restituisce 0; altrimenti ricerca binaria su 60 iterazioni tra 0 e cash + incassi + baseline*12 + business*12 + 1000, criterio minBalance(plan, salary) >= buffer, dove minBalance = minimo dei closing della proiezione -> OUTPUT safeSalary (precisione interna sub-euro), safeSalaryRounded = max(0, round(safeSalary/50)*50). MAXIMUM THEORETICAL SALARY Stessa funzione con buffer = plan.minBuffer (senza moltiplicatore di profilo). Con profilo flexible coincide con il Safe Salary. SAFE TO SPEND INPUT cash, requiredBuffer, forecast 90 gg, businessMonthly, impegni <= 90 gg -> FORMULA max(0, cash - requiredBuffer - taxReserve90 - businessMonthly*3 - obligations90) -> OUTPUT euro una tantum. FORECAST 30/60/90 (forecastAt) monthsInWindow = max(1, min(horizon, ceil(days/30))); months = days/30. beforeSalary = cash + incassi(finestra) - accantonamento(finestra) - business*months - impegni scaduti entro days afterSalary = beforeSalary - salary*months. REDDITO REALE INPUT incassi ponderati, accantonamento, costi, impegni, margine -> FORMULA realIncome = max(0, expectedInflow - taxReserve - businessMonthly*activeMonths - obligationsTotal - max(0, requiredBuffer - cash)); realIncomeMonthly = realIncome / max(1, activeMonths); realIncomeRatio = realIncome / nominalInflow. activeMonths = numero di mesi con incasso ponderato > 0. RUNWAY (src/lib/engine/runway.ts — runwayFor) INPUT plan normalizzato, monthlyDraw, margine, orizzonte (12 di default, max 24) -> FORMULA: simula SOLO i mesi dell'orizzonte; conta i mesi con closing >= margine - 0,005; al primo mese sotto soglia aggiunge la frazione max(0, opening - margine)/(opening - closing) -> OUTPUT { months, beyondHorizon, breakMonth, minBalance, deficit, horizonMonths }. NON esiste più il cap artificiale 99 e non esiste più l'estrapolazione con avgBurn: se il piano non scende mai sotto il margine, months = horizonMonths e beyondHorizon = true (la UI mostra "12+ mesi"). Le quattro autonomie (metrics.runways): - current: nessun incasso futuro, nessun prelievo personale - currentPersonal: nessun incasso futuro, con prelievo personale - planned: incassi inseriti + baseline stimato, senza prelievo personale - operational: solo costi e impegni professionali - personal: prelievo = personal_draw_monthly, fallback spese personali (indipendente dal Safe Salary: nessuna circolarità) MODELLO FISCALE (src/lib/engine/tax) Solo combinazioni activity_type + tax_regime esplicitamente implementate e testate: professional+ordinary (aliquota dichiarata su incassi meno costi deducibili) e professional+forfettario (coefficiente di redditività, imposta sostitutiva, aliquota contributiva). Ogni altra combinazione, incluso "business", restituisce taxModelComplete = false con l'elenco dei parametri mancanti: nessuna stima fiscale inventata, accantonamento 0, ma cash flow, proiezione, autonomie e Safe Salary continuano a funzionare sui movimenti inseriti. ORIZZONTE E CALENDARIO Mesi di calendario reali (chiavi YYYY-MM). Le voci con data oltre l'orizzonte sono escluse dai calcoli ed elencate in "Oltre l'orizzonte" (metrics.beyondHorizon). Il baseline "incasso medio mensile atteso" viene usato solo nei mesi senza voci inserite, con coefficiente di prudenza 100% ed etichetta STIMA. Safe Salary resta definito sui prossimi 12 mesi anche con orizzonte 24. Arrotondamento conservativo verso il basso a €50 (floor50). STATO DEL PIANO green se bufferMargin >= 0 e Safe Salary >= spese personali; yellow se bufferCoverage >= 0,6 oppure Safe Salary > 0; altrimenti red. Etichette: "Margine di sicurezza coperto" / "Da tenere d'occhio" / "Sotto il margine di sicurezza". CASH FLOW (finance.ts projectCashFlow) INPUT EngineInput + stipendio scelto -> FORMULA nessuna: normalize() + engine.project(plan, salary, requiredBuffer). Il baseline (incasso medio atteso) entra SOLO nei mesi senza incassi inseriti, gli impegni e le quote deducibili sono quelli del motore -> OUTPUT le righe della proiezione (orizzonte 12 o 24 mesi) con etichetta di mese. VISTA MESI FUTURI (future.ts futureMonths) Per ogni mese m: openingCash = closing(m-1) della proiezione al Safe Salary; ricalcola computeMetrics con incassi e impegni traslati di 30*m giorni e filtrati (dueInDays > offset). OUTPUT realIncomeMonthly, safeSalary, safeToSpend, runway, requiredBuffer, bufferMargin, status per mese. Supporta incomeFactor (0, 1, 1,3). CONFIDENCE / PRUDENZA CONFIDENCE_LEVELS: confirmed 100, very_likely 85, likely 60, uncertain 30. Il motore pondera per probabilità, MA money-data.ts imposta probability: 100 su ogni incasso pianificato: nell'app autenticata la ponderazione è di fatto disattivata (scelta esplicita: "gli importi inseriti valgono al 100%"). ARROTONDAMENTI Safe Salary: multipli di 50 € per la visualizzazione (safeSalary resta esatto). Runway: nessun cap artificiale; mai oltre l'orizzonte osservato (12/24 mesi), con etichetta "12+ mesi"/"24+ mesi" quando il piano regge fino alla fine. Tolleranza di confronto sui saldi: 0,005 €. Nessun arrotondamento su reddito reale, accantonamento, Safe to Spend. EDGE CASES GESTITI NaN/Infinity azzerati; importi negativi azzerati; liquidità negativa ammessa in input (porta Safe Salary a 0); nessun incasso -> reddito reale 0 (nessuna media storica); incassi oltre l'orizzonte accorpati nell'ultimo mese; spese deducibili maggiori degli incassi -> imponibile 0, mai negativo; horizonMonths minimo 1; divisione per max(1, activeMonths); Safe to Spend e reddito reale mai negativi. ==================================================================== 3. REDDITO REALE ==================================================================== FORMULA EFFETTIVA (metrics.ts) realIncome = max(0, expectedInflow - taxReserve - businessMonthly*activeMonths - obligationsTotal - max(0, requiredBuffer - cash)) COMPONENTI - expectedInflow: incassi ponderati dei 12 mesi. In app = lordo in euro - ritenuta d'acconto, con probabilità 100%. Include l'incasso medio mensile atteso nei mesi senza fatture. - taxReserve: (incassi - spese potenzialmente deducibili) * percentuale dichiarata. - costi professionali: businessMonthly * mesi con incassi previsti (non 12 mesi fissi). - impegni futuri: totale degli impegni pianificati, che in app include anche le provvigioni agenzia (cash out). - riserva di sicurezza: solo la quota mancante, max(0, requiredBuffer - cash). - rimborsi spese: parte del lordo; non sono un guadagno ma entrano in cassa. Non vengono esclusi dal reddito reale, incidono solo come base di provvigione/ritenuta secondo gli interruttori dell'incasso. - IVA sulla provvigione: cash out sì, costo deducibile no (se IVA a credito). COSA RAPPRESENTA Una stima di pianificazione della liquidità che resta realmente disponibile nell'orizzonte di 12 mesi, dopo trattenute, accantonamento stimato, costi professionali, impegni e ricostruzione del margine di sicurezza. COSA NON RAPPRESENTA Non è il reddito fiscale, non è l'utile di bilancio, non calcola imposte effettive, non gestisce IVA a debito/liquidazioni, non tiene conto di acconti/saldi reali, non considera le spese personali (che sono coperte dallo stipendio). STIME vs DATI EFFETTIVI Dati inseriti dall'utente: liquidità, importi, date, percentuali, flag deducibilità. Stime del modello: accantonamento fiscale, imponibile, deducibilità, incasso medio dei mesi vuoti, cambio valuta del giorno, quota di margine da ricostruire. Dati effettivi separati: tabella monthly_actuals (consuntivo), con realIncomeActual = incasso reale - accantonamento reale - spese professionali reali. ==================================================================== 4. PROVVIGIONI E IVA — LOGICA REALMENTE IMPLEMENTATA ==================================================================== percentages.ts - reimbursementAmount = min(lordo, rimborso dichiarato) - cachetAmount = lordo - rimborso - commissionBase = commissionOnReimbursement ? lordo : cachet - effectiveCommissionPct(p, IVA) = IVA ? p * 1,22 : p - commissionAmount = base * effectiveCommissionPct / 100 (CASH OUT, IVA inclusa) - commissionNetAmount = base * p / 100 (COSTO PROFESSIONALE) - commissionVatAmount = commissionAmount - commissionNetAmount (IVA a credito) - commissionDeductibleAmount(row, vatIsCredit) = vatIsCredit ? netto : lordo - withholdingAmount = (withholdingOnReimbursement ? lordo : cachet) * ritenuta% / 100 - netIncomeAmount = max(0, lordo - commissionAmount - withholdingAmount) money-data.ts - L'incasso entra nella proiezione come incomeAfterWithholding = lordo - ritenuta. La provvigione NON viene sottratta dall'incasso. - La provvigione diventa un impegno (PlannedObligation) nel mese dell'incasso: amount = provvigione IVA inclusa (cash out reale) deductible = true deductibleAmount = provvigione netta se commission_vat_credit, altrimenti IVA inclusa - Impostazione settings.commission_vat_credit (default true) governa il comportamento; se false l'IVA rientra nel costo deducibile (caso forfettario/senza detrazione). SCENARIO ARTISTA/CANTANTE (verificato nel codice e nei test) Cachet 5.000 €, provvigione 10%, IVA 22%: cash out all'agenzia = 610 € costo professionale deducibile = 500 € IVA a credito = 110 €, tenuta separata imponibile stimato del mese = incassi - 500 € la liquidità del mese scende di 610 € Con ritenuta 20% sul cachet: in cassa entrano 4.000 €, poi escono 610 €. ==================================================================== 5. SAFE SALARY ==================================================================== FORMULA: massimo salary tale che min(closing di tutti i 12 mesi) >= requiredBuffer, trovato con ricerca binaria (60 iterazioni) su una funzione monotona decrescente. SIMULAZIONE: mese per mese, con incassi e impegni alle loro date, accantonamento calcolato mese per mese sull'imponibile del mese. Non è una divisione per 12. ORIZZONTE: 12 mesi (PLANNING_HORIZON_MONTHS, horizonMonths configurabile). MARGINE: requiredBuffer da profiles.requiredBufferFor; in app (mode flexible) è esattamente il margine impostato dall'utente in euro o in % degli incassi annui. SALDO MINIMO CONSENTITO: requiredBuffer. Se il margine è 0, il vincolo è saldo >= 0. ENTRATE FUTURE: incassi datati (lordo - ritenuta) + incasso medio nei mesi vuoti. SPESE PROFESSIONALI: businessMonthly ogni mese + impegni datati + provvigioni. SPESE PERSONALI: non entrano nella proiezione; sono finanziate dallo stipendio. Se safeSalaryRounded < personalMonthly viene alzato il flag salaryBelowPersonalExpenses e la UI mostra l'avviso. DIFFERENZA CON MAXIMUM THEORETICAL: stesso algoritmo con buffer = minBuffer puro (senza moltiplicatore di profilo). Con profilo flexible i due valori coincidono; con profilo prudente/equilibrato il massimo teorico è più alto. VERIFICA RICHIESTA — il Safe Salary può portare il saldo vicino a zero? SÌ, quando il margine di sicurezza impostato è 0. In quel caso il vincolo è closing >= 0 e per costruzione il mese più stretto arriva quasi esattamente a 0 (l'arrotondamento a 50 € verso il basso lascia solo un piccolo scarto positivo). Il calcolatore pubblico e lo scenario di esempio del dossier divulgativo usano minBuffer 0, quindi in quei contesti il saldo minimo tocca lo zero. Se l'utente imposta un margine (cifra o %), il saldo minimo resta sopra quel valore. ==================================================================== 6. RUNWAY ==================================================================== DEFINIZIONE COMUNE Numero di mesi, entro l'orizzonte, in cui la proiezione resta sopra il margine. Nessun cap artificiale, nessuna estrapolazione: se il piano non sfonda mai il margine il risultato è months = horizonMonths con beyondHorizon = true. RUNWAY ATTUALE (current) INPUT: liquidità di oggi, nessun incasso futuro, nessun prelievo personale. Risponde a "quanto durano i soldi che ho adesso". RUNWAY ATTUALE PERSONALE (currentPersonal) Come sopra, ma con il prelievo personale mensile. RUNWAY PIANIFICATO (planned) INPUT: incassi inseriti + baseline stimato nei mesi vuoti, senza prelievo personale. Nota: NON è garantito che current <= planned in ogni caso (per esempio quando gli incassi pianificati portano nuovi accantonamenti e impegni collegati); i test verificano i casi in cui la relazione deve valere e documentano le eccezioni. RUNWAY OPERATIVO (operational) Solo costi professionali e impegni, senza prelievi personali. RUNWAY PERSONALE (personal) Prelievo = personal_draw_monthly; se non impostato, spese personali mensili. Indipendente dal Safe Salary: nessuna circolarità tra le due metriche. Le spese personali NON vengono sottratte una seconda volta. ARROTONDAMENTO: nessuno nel motore; la UI mostra 1 decimale, oppure "N+ mesi" quando beyondHorizon è true. CASI LIMITE: primo mese già sotto margine -> 0. ALIAS DI COMPATIBILITÀ finance.ts espone ancora operationalRunway/personalRunway come numeri di mesi e runwayMonths = personalRunway, per le viste che non sono ancora state migrate. ==================================================================== 7. SAFE TO SPEND ==================================================================== FORMULA: max(0, cash - requiredBuffer - taxReserve90 - businessMonthly*3 - obligations90) PERIODO: 90 giorni (accantonamento del forecast a 90 gg, 3 mensilità di costi, impegni con dueInDays <= 90). RISERVE PROTETTE: margine di sicurezza + accantonamento fiscale stimato dei 90 gg. IMPEGNI FUTURI: solo quelli entro 90 giorni (incluse le provvigioni di quel periodo). SPESE PROFESSIONALI: 3 mesi. SPESE PERSONALI: non incluse (coperte dallo stipendio). DIFFERENZA CON SAFE SALARY: importo una tantum disponibile oggi, non un flusso mensile; guarda 90 giorni e non 12 mesi; non usa ricerca binaria. INVARIANTI TESTATE: mai negativo, mai superiore alla liquidità, monotono crescente rispetto alla liquidità. ==================================================================== 8. MARGINE DI SICUREZZA ==================================================================== DEFINIZIONE (UI e glossario): una somma che l'utente scegli di mantenere disponibile per mesi deboli, ritardi negli incassi o imprevisti. FORMULA: minBuffer risolto da percentages.resolveMinBuffer: - modalità "amount": cifra fissa in euro; - modalità "pct_income": % di annualExpectedIncomeBase = max(totale lordo delle fatture aperte, incasso medio mensile * 12). Poi requiredBufferFor(profile, minBuffer, personal, business); con mode "flexible" (sempre in app) requiredBuffer = minBuffer. UTILIZZO EFFETTIVO: soglia della proiezione, vincolo del Safe Salary e del Maximum Theoretical, sottrazione nel Safe to Spend, soglia dei due runway, quota di ricostruzione nel reddito reale (max(0, requiredBuffer - cash)), determinazione dello stato del piano. CONFIGURABILITÀ: /impostazioni, campo PercentAmountField (€ o %) con anteprima in euro; persistito in settings.min_buffer, min_buffer_pct, buffer_mode. MESSAGGI UI: card "Margine di sicurezza" in dashboard con "Minimo richiesto €Y" e "Margine disponibile ±€Z"; StatusPill con "Margine di sicurezza coperto" / "Da tenere d'occhio" / "Sotto il margine di sicurezza"; nessuna percentuale come informazione principale. ==================================================================== 9. "PERCHÉ QUESTO NUMERO?" ==================================================================== IMPLEMENTATO: sì, come
apribile. DOVE: /dashboard (chiuso di default) e /reddito-reale (aperto di default). METRICA COPERTA: Reddito reale. DATI MOSTRATI e ORIGINE: - Incassi previsti (lordo) -> metrics.grossTotal (money-data) - − Provvigione agenzia (costo professionale) -> metrics.commissionDeductibleTotal - − IVA sulla provvigione -> metrics.commissionVatTotal (etichetta diversa se IVA a credito) - − Ritenuta d'acconto -> metrics.withholdingTotal - = Arriva sul conto -> metrics.netToBankTotal - − Accantonamento fiscale stimato -> plan.realIncomeTax (engine) - − Costi professionali -> plan.realIncomeCosts (engine, mesi con incassi) - − Impegni futuri -> plan.realIncomeObligations (engine) - = Reddito realmente disponibile stimato -> plan.realIncome (engine) CORRISPONDENZA CON L'ENGINE: i valori sono tutti presi dall'engine o dall'adattatore, nessun ricalcolo locale. La lista non è però una somma algebrica esatta: le prime righe sono in "logica cassa" sul lordo (provvigione, IVA, ritenuta), mentre realIncomeTax/Costs/Obligations partono da expectedInflow (già netto di ritenuta) e contengono di nuovo la provvigione dentro gli impegni. Le voci sono corrette singolarmente, la lettura come sottrazione riga per riga non torna al centesimo. METRICHE ANCORA SENZA "Perché questo numero?": Safe to Spend, Safe Salary (ha però la pagina /stipendio con la catena esplicativa), Maximum Theoretical, runway operativo e personale, margine di sicurezza, Safe to Spend nel calcolatore. ==================================================================== 10. GLOSSARIO ==================================================================== 30 voci in src/lib/glossary.ts, tutte con titolo + spiegazione tecnica non semplificata: redditoReale, safeToSpend, safeSalary, maxTheoretical, margineSicurezza, margineSicurezzaPercentuale, runway, runwayOperativo, runwayPersonale, cashFlow, accantonamento, provvigione, iva, ivaCredito, ritenuta, importoLordo, importoNetto, probabilita, impegno, spesePersonali, speseProfessionali, deducibile, imponibile, incassoMedio, valuta, cambio, cambioManuale, cachet, rimborsoSpese, provvigioneRimborso. Linguaggio fiscale prudente: "accantonamento fiscale stimato", "imponibile stimato", "potenzialmente deducibile", con la nota "HABEOPURE fornisce stime di pianificazione e non sostituisce il commercialista". COMPONENTE: InfoTip (Popover shadcn, bottone ⓘ con aria-label "Cosa significa X"). Usato in StatCard (prop info), MoneyField, PercentAmountField, HierarchyStrip e nelle righe delle spiegazioni. Circa 39 punti di utilizzo nelle pagine. DOVE: dashboard, reddito-reale, stipendio, entrate, spese, impegni, impostazioni, calcolatore, componenti condivisi. TERMINI SENZA SPIEGAZIONE CONTESTUALE OVUNQUE - runway: la voce esiste nel glossario ma la dashboard mostra solo runwayOperativo e runwayPersonale (voce "runway" usata soprattutto dal dossier). - cashFlow, imponibile, probabilita, incassoMedio, valuta, spesePersonali, importoLordo: presenti nel glossario ma non richiamati con ⓘ in tutte le pagine in cui il termine appare (es. /cash-flow, tabelle di /futuro e /consuntivo). - Le righe della pagina /reddito-reale nel blocco "Perché questo numero?" non hanno ⓘ (a differenza della dashboard). ==================================================================== 11. UX/UI ==================================================================== GERARCHIA: HierarchyStrip mostra Reddito reale -> Safe to Spend -> Safe Salary -> Margine di sicurezza / Runway. Il numero eroe della dashboard è il reddito reale mensile, in verde, con spiegazione e disclaimer. METRICHE: griglia di StatCard 2 colonne su mobile, 3 su desktop: Safe to spend, Safe Salary, Cash disponibile, Accantonamento stimato, Provvigioni (deducibili), Runway operativo, Runway personale, Margine di sicurezza. Le card Pro sono sfocate con lucchetto per gli utenti Free. CTA: "Scopri il mio reddito reale" (landing), "Sblocca HABEOPURE" (UpgradeCard), "Come nasce lo stipendio", "Aggiorna i dati reali", "Vista mesi futuri", "Installa ora" (/installa). MESSAGGI: StatusPill con il linguaggio del margine; avviso quando il Safe Salary è sotto le spese personali; box "Perché la cifra ti sembra bassa" in /stipendio quando ci sono mesi vuoti senza incasso medio dichiarato; banner pagamento; nota cambio valuta non aggiornato (fxStale). EMPTY STATES: presenti per prossimi incassi, consuntivo del mese, confronto stima/consuntivo, elenchi di entrate/spese/impegni. ERROR STATES: gestione errori globale (error-capture, error-page) e stati di caricamento tramite state.loading; gli errori delle mutazioni Supabase non sono sempre mostrati con un messaggio dedicato per campo. MOBILE/RESPONSIVE: mobile-first, bottom bar con 5 voci principali, menu ☰ dall'alto con tutte le sezioni, account e installazione; tabelle in overflow-x con min-width. STATO COERENZA UI (dopo il polish pass) - Card "Margine di sicurezza": il valore principale è il margine minimo richiesto; liquidità disponibile e differenza sono informazioni secondarie. - /stipendio: la catena esplicativa legge gli output del motore, usa "Accantonamento fiscale stimato" e "mantenendo il margine di sicurezza"; la provvigione è contata una sola volta (già dentro gli impegni). - /cash-flow: nessuna formula propria, usa projectCashFlow -> engine.project con lo stesso margine del piano; l'incasso medio atteso compare solo nei mesi senza incassi inseriti ed è mostrato in colonna separata. - Dashboard: la card "Provvigioni (deducibili)" mostra la provvigione IVA inclusa (commissionTotal) mentre il blocco "Perché questo numero?" usa la quota deducibile (commissionDeductibleTotal). RICHIESTA DI AGGIORNAMENTO LIQUIDITÀ (funzione aggiunta dopo il polish pass) - Presentazione: foglio in alto sopra le altre sezioni, con azioni esplicite. - Trigger: salvataggio o modifica con data prevista in /entrate, /spese, /impegni; cambio stato di un'entrata a "incassata" (imposta anche actual_payment_date); pagamento di un impegno. Gli ultimi due chiamano cashPrompt.request(true), che ignora lo snooze. - Contenuto: "Vuoi aggiornare la tua liquidità?", liquidità registrata attuale, campo per il saldo reale del conto, azioni "Aggiorna liquidità" e "Non ora". - Persistenza: riusa settings.current_cash tramite useUpdateSettings (nessuna nuova tabella, nessuna migrazione, nessuna nuova formula). Mostra la data dell'ultimo aggiornamento. - Snooze: "Non ora" salva un timestamp in localStorage e sopprime la richiesta automatica per 2 ore; i trigger forzati restano sempre visibili. - Le date future NON modificano mai automaticamente la liquidità: solo la conferma esplicita dell'utente aggiorna il valore, e dashboard/metriche si ricalcolano con il normale flusso TanStack Query. ==================================================================== 12. DATI DEMO E VALORI HARDCODED ==================================================================== - /calcolatore DEFAULT_INPUT: cash 12.000, incassi 90 gg 15.000, spese personali 1.800, professionali 600, accantonamento 35%, minBuffer 0, profilo flexible. Sono valori iniziali del form pubblico: influenzano il primo risultato mostrato se l'utente non li modifica. - analysis-brief.ts EXAMPLE_SCENARIO: scenario totalmente inventato (cash 8.000, quattro incassi, incasso medio 2.500, spese 600/2.200, due impegni, 30%, minBuffer 0) usato dalla pagina /analisi e da /api/public/analisi.md. Non tocca i dati degli utenti. - /reddito-reale: due esempi numerici scritti a mano nel testo (60.000 € con agenzia al 10% + IVA e scenario con incassi in ritardo). Sono testo statico, non calcolati: possono divergere dalla logica se le formule cambiano. - Costanti: VAT_RATE 22, DEFAULT_WITHHOLDING_PCT 20, BASELINE_CONFIDENCE 1, nessun RUNWAY_CAP, arrotondamento 50 €, PLANNING_HORIZON_MONTHS 12, taxPct di default 30, CONFIDENCE_LEVELS 100/85/60/30, profili 1,5-3 / 1,2-2 / 1-0. - Nessun dato demo viene scritto nel database: i nuovi account partono da settings vuoti (tutti zero) e le pagine mostrano empty state.