diff --git a/public/js/help.js b/public/js/help.js
index 97d3399..426c654 100644
--- a/public/js/help.js
+++ b/public/js/help.js
@@ -488,10 +488,50 @@ const HelpSystem = (function () {
{
heading: 'Sicurezza Account',
items: [
- 'Modifica la password del tuo account in qualsiasi momento.',
+ 'Modifica la password del tuo account in qualsiasi momento dal pulsante "Cambia password".',
'La piattaforma applica un timeout di sessione automatico dopo 30 minuti di inattivita\'. Un avviso con countdown appare 5 minuti prima del logout per permetterti di rimanere connesso.',
'Il logout automatico protegge le informazioni sensibili in caso di postazione incustodita.',
- 'Configura le impostazioni di notifica per scadenze e alert.'
+ 'La sezione Sessioni Attive elenca tutti i dispositivi attualmente loggati al tuo account (browser, sistema operativo, indirizzo IP, ultimo accesso). Puoi disconnettere un singolo dispositivo con "Disconnetti" oppure tutti tranne questo con "Disconnetti gli altri" — utile se sospetti accessi non autorizzati.'
+ ]
+ },
+ {
+ heading: 'Preferenze utente',
+ items: [
+ 'Nel tab Preferenze puoi personalizzare la tua esperienza individuale (non condivisa con altri membri dell\'organizzazione).',
+ 'Lingua: italiano, inglese, francese o tedesco — applicata a tutti i menu e messaggi.',
+ 'Tema: chiaro, scuro o automatico (segue le impostazioni del sistema operativo).',
+ 'Timezone: usata per visualizzare date e ore. Default Europe/Rome (CET/CEST). Cambia se lavori da un altro fuso.',
+ 'Notifiche email: ricevi via email gli avvisi per incidenti, scadenze e training.',
+ 'Notifiche in-app: mostra badge contatori nella sidebar per nuove notifiche.'
+ ]
+ },
+ {
+ heading: 'Password dimenticata',
+ items: [
+ 'Dalla pagina di login clicca su "Password dimenticata?" per richiedere un link di reset.',
+ 'Inserisci la tua email: se registrata riceverai un messaggio con un link valido 30 minuti.',
+ 'Il link è single-use: una volta cliccato e impostata la nuova password, non potra\' essere riusato.',
+ 'Per motivi di sicurezza, la pagina mostra sempre lo stesso messaggio sia che l\'email sia registrata sia che non lo sia (anti-enumeration).',
+ 'Dopo il reset, tutte le sessioni attive precedenti vengono disconnesse automaticamente.'
+ ]
+ },
+ {
+ heading: 'Cambio organizzazione (multi-tenant)',
+ items: [
+ 'Se sei membro di piu\' organizzazioni (es. consulente), nella sidebar appare un dropdown azienda in alto.',
+ 'Click sul dropdown per vedere tutte le organizzazioni a cui hai accesso e quale è quella attualmente attiva (✓).',
+ 'Selezionando un\'altra organizzazione il sistema emette un nuovo token con il contesto aggiornato e ricarica la pagina.',
+ 'Il cambio è registrato nell\'audit log come context_switch.'
+ ]
+ },
+ {
+ heading: 'Branding white-label (solo consulenti / super admin)',
+ items: [
+ 'Il tab Branding consente a uno studio di consulenza di personalizzare l\'interfaccia che vedranno i suoi clienti.',
+ 'Nome prodotto custom: sostituisce "NIS2 Agile" con il branding dello studio (es. "Studio Rossi NIS2 Suite").',
+ 'URL Logo: link assoluto al logo dello studio (es. https://www.tuosito.it/logo.svg). Verra\' mostrato nella sidebar e nelle pagine di login.',
+ 'Colori: il primario sostituisce il blu di default (intestazioni, pulsanti principali); il secondario sostituisce il ciano (badge, accenti).',
+ 'Le modifiche vengono applicate automaticamente a tutti gli utenti del firm al ricaricamento della pagina.'
]
}
],
diff --git a/public/js/i18n.js b/public/js/i18n.js
index bc39295..99ab212 100644
--- a/public/js/i18n.js
+++ b/public/js/i18n.js
@@ -175,6 +175,73 @@ const I18n = (function () {
'session.stay': { it: 'Rimani connesso', en: 'Stay connected' },
'session.logout_now': { it: 'Disconnetti', en: 'Log out' },
+ // ── Multi-device Sessions (Fase 2) ──────────────
+ 'sessions.title': { it: 'Sessioni Attive', en: 'Active Sessions' },
+ 'sessions.desc': { it: 'Dispositivi attualmente loggati al tuo account. Puoi disconnetterli singolarmente o tutti tranne questo.', en: 'Devices currently logged into your account. You can disconnect them individually or all but this one.' },
+ 'sessions.current_device': { it: 'Questo dispositivo', en: 'This device' },
+ 'sessions.revoke': { it: 'Disconnetti', en: 'Disconnect' },
+ 'sessions.revoke_all': { it: 'Disconnetti gli altri', en: 'Disconnect others' },
+ 'sessions.ip': { it: 'IP', en: 'IP' },
+ 'sessions.last_activity': { it: 'Ultimo accesso', en: 'Last activity' },
+ 'sessions.login': { it: 'Login', en: 'Login' },
+ 'sessions.empty': { it: 'Nessuna sessione attiva.', en: 'No active sessions.' },
+ 'sessions.confirm_revoke': { it: 'Disconnettere questo dispositivo?', en: 'Disconnect this device?' },
+ 'sessions.confirm_revoke_all': { it: 'Disconnettere tutti gli altri dispositivi?', en: 'Disconnect all other devices?' },
+
+ // ── Password Reset (Fase 3) ─────────────────────
+ 'pwreset.forgot_link': { it: 'Password dimenticata?', en: 'Forgot password?' },
+ 'pwreset.forgot_title': { it: 'Reimposta la tua password', en: 'Reset your password' },
+ 'pwreset.forgot_helper': { it: 'Inserisci l\'indirizzo email associato al tuo account. Ti invieremo un link valido 30 minuti.', en: 'Enter the email associated with your account. We will send you a link valid for 30 minutes.' },
+ 'pwreset.send_link': { it: 'Invia link', en: 'Send link' },
+ 'pwreset.set_new': { it: 'Imposta una nuova password', en: 'Set a new password' },
+ 'pwreset.new_password': { it: 'Nuova password', en: 'New password' },
+ 'pwreset.confirm': { it: 'Conferma password', en: 'Confirm password' },
+ 'pwreset.submit': { it: 'Imposta password', en: 'Set password' },
+ 'pwreset.back_login': { it: 'Torna al login', en: 'Back to login' },
+ 'pwreset.strength_weak': { it: 'Debole', en: 'Weak' },
+ 'pwreset.strength_medium': { it: 'Media', en: 'Medium' },
+ 'pwreset.strength_good': { it: 'Buona', en: 'Good' },
+ 'pwreset.strength_excellent':{ it: 'Ottima', en: 'Excellent' },
+
+ // ── Tenant switcher (Fase 3) ────────────────────
+ 'tenant.select': { it: 'Seleziona azienda', en: 'Select company' },
+ 'tenant.all': { it: '← Tutte le aziende', en: '← All companies' },
+
+ // ── Preferenze (Fase 4) ─────────────────────────
+ 'preferences.title': { it: 'Preferenze utente', en: 'User preferences' },
+ 'preferences.desc': { it: 'Personalizzazione interfaccia e notifiche.', en: 'Interface and notifications personalization.' },
+ 'preferences.language': { it: 'Lingua', en: 'Language' },
+ 'preferences.theme': { it: 'Tema', en: 'Theme' },
+ 'preferences.theme_auto': { it: 'Auto (segue sistema)', en: 'Auto (follows system)' },
+ 'preferences.theme_light': { it: 'Chiaro', en: 'Light' },
+ 'preferences.theme_dark': { it: 'Scuro', en: 'Dark' },
+ 'preferences.timezone': { it: 'Timezone', en: 'Timezone' },
+ 'preferences.notif_email': { it: 'Ricevi notifiche via email (incidenti, deadline, training)', en: 'Receive email notifications (incidents, deadlines, training)' },
+ 'preferences.notif_inapp': { it: 'Mostra notifiche in-app (badge sidebar)', en: 'Show in-app notifications (sidebar badges)' },
+ 'preferences.save': { it: 'Salva preferenze', en: 'Save preferences' },
+ 'preferences.saved': { it: '✓ Salvato', en: '✓ Saved' },
+
+ // ── Impersonate (Fase 4) ────────────────────────
+ 'impersonate.btn': { it: 'Impersonate', en: 'Impersonate' },
+ 'impersonate.tooltip': { it: 'Entra come questo utente per 1 ora', en: 'Enter as this user for 1 hour' },
+ 'impersonate.confirm': { it: 'Entrare come {email} per 1 ora?', en: 'Enter as {email} for 1 hour?' },
+ 'impersonate.banner': { it: 'Modalità Impersonate — stai usando l\'account di', en: 'Impersonate mode — you are using the account of' },
+ 'impersonate.exit': { it: 'Esci impersonate', en: 'Exit impersonate' },
+
+ // ── Branding white-label (Fase 5) ───────────────
+ 'branding.title': { it: 'Branding white-label', en: 'White-label branding' },
+ 'branding.desc': { it: 'Personalizza colori, logo e nome prodotto per il tuo studio. Visibile a tutti i tuoi clienti loggati.', en: 'Customize colors, logo and product name for your firm. Visible to all your logged-in clients.' },
+ 'branding.brand_name': { it: 'Nome prodotto custom (opzionale)', en: 'Custom product name (optional)' },
+ 'branding.logo_url': { it: 'URL Logo (opzionale)', en: 'Logo URL (optional)' },
+ 'branding.primary': { it: 'Colore primario', en: 'Primary color' },
+ 'branding.secondary': { it: 'Colore secondario', en: 'Secondary color' },
+ 'branding.save': { it: 'Salva branding', en: 'Save branding' },
+ 'branding.saved': { it: '✓ Salvato — ricarica per vedere', en: '✓ Saved — reload to see' },
+
+ // ── Settings tabs (Fase 4-5) ────────────────────
+ 'settings.preferences': { it: 'Preferenze', en: 'Preferences' },
+ 'settings.branding': { it: 'Branding', en: 'Branding' },
+
// ── Tempo relativo ─────────────────────────────
'time.now': { it: 'Adesso', en: 'Just now' },
'time.min_ago': { it: 'min fa', en: 'min ago' },
diff --git a/public/version.json b/public/version.json
index 71a3094..886b6b8 100644
--- a/public/version.json
+++ b/public/version.json
@@ -1 +1 @@
-{"version":"1.6.0","build":"20260529f","date":"2026-05-29T14:30:00+02:00","changelog":"UI Fasi 4+5: pulsante Impersonate in admin/users.html con banner persistente arancione, tab Preferenze in settings (lingua/tema/timezone/notifiche), tab Branding white-label per super_admin/consulenti (colori + logo + brand name). Vedi docs/GAP_TRPG_NIS2_ALIGNMENT.md"}
+{"version":"1.6.1","build":"20260529g","date":"2026-05-29T14:55:00+02:00","changelog":"Doc: aggiornati help.js (sezione Impostazioni con Sessioni/Preferenze/Branding/Reset/Tenant), i18n.js (chiavi IT/EN per Fasi 2-5), product knowledge AI AgileHub (card NIS2 id=914)"}