[FEAT] UI V3 — flotta: chrome top-nav + design system su 32 pagine app

Migrazione UI dal V2 (Bootstrap Italia, sidebar) al V3 (top-nav mega-menu
navy/oro, Inter+Lucide self-host) fedele ai mockup docs/mockup Ui/.
- 32 pagine app convertite (incl. admin/*): head Inter+v3.css, chrome
  topnav-v3, contenuti in card V3, dati REALI preservati (id/data-* intatti),
  i18n/help/FAB reali invariati, nessun CDN esterno.
- v3.css: aggiunti widget condivisi (modal/toast/form/btn-variant/spinner/
  progress/tag/badge) + utility (.btn base, .text-muted, .sr-only) + alias
  variabili V2->token V3, così modali/form/toast di common.js funzionano
  ovunque senza style.css.
- maintenance.html: finestra estesa a ~12:15.
- docs/UI_V3_FLEET_BRIEF.md: ricetta operativa della flotta.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
DevEnv nis2-agile
2026-06-27 15:57:35 +02:00
co-authored by Claude Opus 4.8
parent b0fc190704
commit a4150b5389
37 changed files with 4655 additions and 4922 deletions
+173 -159
View File
@@ -3,49 +3,54 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
<title>Modello Organizzativo SGSI (ISO 27001) - NIS2 Agile</title>
<!-- Bootstrap Italia v2.18.1 self-hostato (regola: MAI CDN). Caricato PRIMA di style.css
cosi' style.css (design system esistente) resta autorevole per i widget renderizzati
via JS (wizard/SoA/tabelle) -> parita' funzionale assoluta. BI veste la chrome. -->
<link rel="stylesheet" href="/vendor/bootstrap-italia/dist/css/bootstrap-italia.min.css">
<link rel="stylesheet" href="/css/style.css?v=20260618">
<title>Modello Organizzativo SGSI (ISO 27001) · NIS2 Agile</title>
<!-- UI V3: Inter self-host + design system v3.css. Self-host only, nessun CDN esterno. -->
<link rel="stylesheet" href="/vendor/inter/inter.css?v=20260627">
<link rel="stylesheet" href="/css/v3.css?v=20260627">
<style>
.isms-intro { background:#eff6ff; border-left:4px solid var(--primary,#2563eb); padding:14px 18px; border-radius:8px; margin-bottom:20px; font-size:.92rem; line-height:1.6; }
.isms-steps { display:flex; flex-wrap:wrap; gap:6px; margin-bottom:20px; }
.isms-step { flex:1 1 140px; min-width:120px; padding:10px 12px; border:1.5px solid var(--gray-200,#e5e7eb); border-radius:10px; background:#fff; cursor:pointer; font-size:.82rem; text-align:center; }
.isms-step.active { border-color:var(--primary,#2563eb); background:#eff6ff; font-weight:700; }
.isms-step.done { border-color:#16a34a; }
.isms-step .num { display:inline-block; width:22px; height:22px; line-height:22px; border-radius:50%; background:var(--gray-100,#f3f4f6); font-weight:700; margin-bottom:4px; }
.isms-step.done .num { background:#16a34a; color:#fff; }
/* Stili specifici della pagina SGSI non coperti da v3.css (nessun CDN). */
.text-muted { color: var(--muted); }
.sr-only { position:absolute; width:1px; height:1px; overflow:hidden; clip:rect(0 0 0 0); }
/* Base .btn usata dai bottoni generati via JS (es. "btn btn-sm btn-outline") */
.btn { display:inline-flex; align-items:center; justify-content:center; gap:7px; font:inherit; font-weight:600; font-size:12.5px; border-radius:8px; padding:8px 13px; border:1px solid transparent; cursor:pointer; line-height:1.4; text-decoration:none; }
.btn .icon, .btn .ic { width:15px; height:15px; }
.isms-intro { background:#EAF1FA; border-left:4px solid var(--c-blue); padding:14px 18px; border-radius:10px; margin-bottom:18px; font-size:.92rem; line-height:1.6; color:var(--ink); }
.isms-steps { display:flex; flex-wrap:wrap; gap:8px; margin-bottom:20px; }
.isms-step { flex:1 1 140px; min-width:120px; padding:11px 12px; border:1.5px solid var(--line); border-radius:11px; background:#fff; cursor:pointer; font-size:.82rem; text-align:center; transition:border-color .12s,background .12s; }
.isms-step:hover { border-color:#9FBEDD; }
.isms-step.active { border-color:var(--c-blue); background:#EAF1FA; font-weight:700; }
.isms-step.done { border-color:var(--c-green); }
.isms-step .num { display:inline-block; width:22px; height:22px; line-height:22px; border-radius:50%; background:#EEF2F7; font-weight:700; margin-bottom:4px; }
.isms-step.done .num { background:var(--c-green); color:#fff; }
.isms-panel { display:none; }
.isms-panel.active { display:block; }
.isms-disclaimer { font-size:.8rem; color:#92400e; background:#fffbeb; border:1px solid #fde68a; border-radius:8px; padding:10px 12px; margin:12px 0; }
.raci-row { display:flex; gap:8px; align-items:center; flex-wrap:wrap; padding:8px 0; border-bottom:1px solid var(--gray-100,#f3f4f6); }
.raci-row input, .raci-row select { padding:6px 8px; border:1px solid var(--gray-200,#e5e7eb); border-radius:6px; font-size:.85rem; }
.soa-std { border:1px solid var(--gray-200,#e5e7eb); border-radius:10px; margin-bottom:14px; overflow:hidden; }
.soa-std-head { background:var(--gray-50,#f9fafb); padding:12px 16px; cursor:pointer; display:flex; justify-content:space-between; align-items:center; }
.isms-panel h3 { margin:0 0 12px; font-size:17px; font-weight:800; }
.isms-panel h4 { margin:16px 0 8px; font-size:14px; font-weight:700; }
.isms-disclaimer { font-size:.8rem; color:#92400e; background:#FBF1E2; border:1px solid #fde68a; border-radius:8px; padding:10px 12px; margin:12px 0; }
.raci-row { display:flex; gap:8px; align-items:center; flex-wrap:wrap; padding:8px 0; border-bottom:1px solid var(--line); }
.raci-row input, .raci-row select { padding:8px 10px; border:1px solid var(--line); border-radius:8px; font:inherit; font-size:.85rem; color:var(--ink); }
.soa-std { border:1px solid var(--line); border-radius:11px; margin-bottom:14px; overflow:hidden; }
.soa-std-head { background:#F5F8FC; padding:12px 16px; cursor:pointer; display:flex; justify-content:space-between; align-items:center; }
.soa-std-body { padding:6px 14px 14px; display:none; }
.soa-std.open .soa-std-body { display:block; }
.soa-theme { font-size:.78rem; font-weight:700; text-transform:uppercase; color:var(--gray-500,#6b7280); margin:14px 0 6px; letter-spacing:.04em; }
.soa-ctrl { padding:12px 0; border-top:1px solid var(--gray-100,#f3f4f6); }
.soa-theme { font-size:.78rem; font-weight:700; text-transform:uppercase; color:var(--muted); margin:14px 0 6px; letter-spacing:.04em; }
.soa-ctrl { padding:12px 0; border-top:1px solid var(--line); }
.soa-ctrl-head { display:flex; gap:10px; align-items:flex-start; justify-content:space-between; flex-wrap:wrap; }
.soa-code { display:inline-block; background:#eef2ff; color:#3730a3; font-weight:700; font-size:.72rem; padding:2px 8px; border-radius:6px; margin-right:6px; }
.soa-derived { background:#ecfdf5; color:#065f46; font-size:.68rem; padding:1px 6px; border-radius:5px; }
.soa-code { display:inline-block; background:#E7F0FB; color:#1F5FA8; font-weight:700; font-size:.72rem; padding:2px 8px; border-radius:6px; margin-right:6px; }
.soa-derived { background:#E6F4EC; color:#1E7A4E; font-size:.68rem; padding:1px 6px; border-radius:5px; }
.soa-opts { display:flex; flex-wrap:wrap; gap:6px; margin-top:8px; }
.soa-opt { min-height:34px; padding:5px 10px; border:1.5px solid var(--gray-200,#e5e7eb); border-radius:18px; background:#fff; cursor:pointer; font-size:.8rem; font-weight:600; }
.soa-opt.sel-implemented,.soa-opt.sel-verified { background:#16a34a; color:#fff; border-color:#16a34a; }
.soa-opt.sel-in_progress { background:#f59e0b; color:#fff; border-color:#f59e0b; }
.soa-opt { min-height:34px; padding:5px 10px; border:1.5px solid var(--line); border-radius:18px; background:#fff; cursor:pointer; font:inherit; font-size:.8rem; font-weight:600; color:var(--ink); }
.soa-opt.sel-implemented,.soa-opt.sel-verified { background:var(--c-green); color:#fff; border-color:var(--c-green); }
.soa-opt.sel-in_progress { background:var(--c-amber); color:#fff; border-color:var(--c-amber); }
.soa-opt.sel-not_started { background:#9ca3af; color:#fff; border-color:#9ca3af; }
.soa-justif { width:100%; margin-top:8px; padding:8px; border:1px solid var(--gray-200,#e5e7eb); border-radius:6px; font-size:.84rem; min-height:46px; }
.soa-justif { width:100%; margin-top:8px; padding:8px; border:1px solid var(--line); border-radius:8px; font:inherit; font-size:.84rem; min-height:46px; color:var(--ink); }
.isms-field { margin-bottom:14px; }
.isms-field label { display:block; font-weight:600; font-size:.88rem; margin-bottom:4px; }
.isms-field textarea, .isms-field input { width:100%; padding:9px; border:1px solid var(--gray-200,#e5e7eb); border-radius:8px; font-size:.9rem; }
.isms-field textarea, .isms-field input { width:100%; padding:9px; border:1px solid var(--line); border-radius:8px; font:inherit; font-size:.9rem; color:var(--ink); }
.isms-flags label { display:block; padding:8px 0; font-size:.9rem; }
.ck-item { display:flex; justify-content:space-between; padding:8px 0; border-bottom:1px solid var(--gray-100,#f3f4f6); font-size:.9rem; }
.ck-yes { color:#16a34a; font-weight:700; } .ck-no { color:#9ca3af; }
.savehint { font-size:.78rem; color:var(--gray-400,#9ca3af); min-height:16px; }
/* Allinea l'icona sprite BI nel bottone Esporta col testo */
.content-header-actions .btn .icon { vertical-align:text-bottom; margin-right:4px; }
.ck-item { display:flex; justify-content:space-between; padding:8px 0; border-bottom:1px solid var(--line); font-size:.9rem; }
.ck-yes { color:var(--c-green); font-weight:700; } .ck-no { color:#9ca3af; }
.savehint { font-size:.78rem; color:var(--muted); min-height:16px; }
</style>
<!-- PWA:start -->
<link rel="manifest" href="/manifest.webmanifest">
@@ -62,142 +67,151 @@
<!-- PWA:end -->
</head>
<body>
<div class="app-layout">
<aside class="sidebar" id="sidebar"></aside>
<main class="main-content">
<header class="content-header">
<h2 data-i18n="isms.title">Modello Organizzativo SGSI (ISO 27001)</h2>
<div class="content-header-actions">
<span class="savehint" id="isms-savehint" role="status" aria-live="polite"></span>
<button class="btn btn-outline btn-sm" id="nis2-isms-btn-export" onclick="ismsExportView()" data-i18n="isms.export">
<svg class="icon icon-sm" aria-hidden="true"><use href="/vendor/bootstrap-italia/dist/svg/sprites.svg#it-file"></use></svg>
<span>Esporta SGSI</span>
</button>
</div>
</header>
<!-- Chrome V3 (appbar + mega-menu) iniettata da topnav-v3.js in questo host -->
<div id="topnav"></div>
<div class="content-body">
<div class="isms-intro" id="nis2-isms-intro">
<strong data-i18n="isms.intro.title">Costruisci il tuo Sistema di Gestione della Sicurezza delle Informazioni.</strong>
<span data-i18n="isms.intro.body">Procedura guidata ISO/IEC 27001:2022 (clausole 4-10 + Statement of Applicability). Lo Statement of Applicability viene pre-popolato dalle tue risposte alla Gap Analysis NIS2. Attiva le estensioni cloud ISO 27017/27018 dove pertinenti.</span>
</div>
<div class="isms-disclaimer" id="nis2-isms-disclaimer" data-i18n="isms.disclaimer">Strumento di supporto e pre-audit: non costituisce una certificazione ISO 27001 né un parere professionale vincolante. Gli obblighi normativi in Italia derivano da NIS2 / D.Lgs. 138/2024 / Determinazioni ACN; ISO 27001/27017/27018 sono best practice.</div>
<main class="wrap">
<nav class="crumb" aria-label="breadcrumb">
<i data-lucide="home" class="ic"></i><a href="dashboard.html">Home</a>
<i data-lucide="chevron-right" class="ic"></i><span>SGSI (ISO 27001)</span>
</nav>
<div class="page-head">
<div>
<h1 data-i18n="isms.title">Modello Organizzativo SGSI (ISO 27001)</h1>
<p class="sub">Procedura guidata ISO/IEC 27001:2022 — clausole 4–10 + Statement of Applicability</p>
</div>
<div class="content-header-actions" style="display:flex; align-items:center; gap:12px; flex-wrap:wrap;">
<span class="savehint" id="isms-savehint" role="status" aria-live="polite"></span>
<button class="btn-ghost" id="nis2-isms-btn-export" onclick="ismsExportView()" data-i18n="isms.export">
<i data-lucide="file-text" class="ic"></i>
<span>Esporta SGSI</span>
</button>
</div>
</div>
<div class="isms-steps" id="isms-steps"></div>
<section class="card card-pad">
<div class="isms-intro" id="nis2-isms-intro">
<strong data-i18n="isms.intro.title">Costruisci il tuo Sistema di Gestione della Sicurezza delle Informazioni.</strong>
<span data-i18n="isms.intro.body">Procedura guidata ISO/IEC 27001:2022 (clausole 4-10 + Statement of Applicability). Lo Statement of Applicability viene pre-popolato dalle tue risposte alla Gap Analysis NIS2. Attiva le estensioni cloud ISO 27017/27018 dove pertinenti.</span>
</div>
<div class="isms-disclaimer" id="nis2-isms-disclaimer" data-i18n="isms.disclaimer">Strumento di supporto e pre-audit: non costituisce una certificazione ISO 27001 né un parere professionale vincolante. Gli obblighi normativi in Italia derivano da NIS2 / D.Lgs. 138/2024 / Determinazioni ACN; ISO 27001/27017/27018 sono best practice.</div>
<!-- STEP 1 - Contesto & Ambito (cl.4) -->
<div class="isms-panel" id="panel-0">
<div class="card"><div class="card-body">
<h3 data-i18n="isms.s1.title">1. Contesto e Ambito (cl. 4)</h3>
<div class="isms-field"><label for="f-scope" data-i18n="isms.s1.scope">Ambito del SGSI (scope statement)</label><textarea id="f-scope" rows="3" placeholder="Es. Tutti i sistemi e processi a supporto dei servizi ICT erogati dalla sede di..."></textarea></div>
<div class="isms-field"><label for="f-ctx-int" data-i18n="isms.s1.ctx_int">Contesto interno</label><textarea id="f-ctx-int" rows="2"></textarea></div>
<div class="isms-field"><label for="f-ctx-ext" data-i18n="isms.s1.ctx_ext">Contesto esterno</label><textarea id="f-ctx-ext" rows="2"></textarea></div>
<div class="isms-field"><label for="f-parties" data-i18n="isms.s1.parties">Parti interessate (una per riga)</label><textarea id="f-parties" rows="3" placeholder="Clienti&#10;Autorità (ACN/CSIRT)&#10;Fornitori ICT"></textarea></div>
<div class="isms-field"><label for="f-boundaries" data-i18n="isms.s1.boundaries">Confini del SGSI</label><textarea id="f-boundaries" rows="2"></textarea></div>
<div class="isms-field"><label for="f-exclusions" data-i18n="isms.s1.exclusions">Esclusioni motivate</label><textarea id="f-exclusions" rows="2"></textarea></div>
<div class="isms-flags">
<strong data-i18n="isms.s1.cloud">Estensioni cloud (attivano i controlli condizionali nel SoA)</strong>
<label><input type="checkbox" id="f-uses-cloud"> <span data-i18n="isms.s1.uses_cloud">Usiamo servizi cloud pubblici (Microsoft 365, AWS, Google...) → ISO 27017</span></label>
<label><input type="checkbox" id="f-cloud-provider"> <span data-i18n="isms.s1.cloud_provider">Siamo fornitori di servizi cloud → ISO 27017 (lato provider)</span></label>
<label><input type="checkbox" id="f-pii-cloud"> <span data-i18n="isms.s1.pii_cloud">Trattiamo dati personali (PII) in cloud pubblico come responsabili → ISO 27018</span></label>
</div>
<button class="btn btn-primary" id="nis2-isms-btn-save-step1" onclick="saveStep1()" data-i18n="isms.save_next">Salva e continua</button>
</div></div>
</div>
<div class="isms-steps" id="isms-steps"></div>
<!-- STEP 2 - Leadership (cl.5) -->
<div class="isms-panel" id="panel-1">
<div class="card"><div class="card-body">
<h3 data-i18n="isms.s2.title">2. Leadership: ruoli e responsabilità (cl. 5)</h3>
<p class="text-muted" data-i18n="isms.s2.hint">Definisci i ruoli del SGSI con la matrice RACI (Responsible, Accountable, Consulted, Informed).</p>
<div id="roles-list"></div>
<div class="raci-row" style="border-top:2px solid var(--gray-200,#e5e7eb); margin-top:10px;">
<input id="r-name" placeholder="Ruolo (es. CISO)" aria-label="Ruolo" style="flex:1 1 160px;">
<input id="r-resp" placeholder="Responsabilità" aria-label="Responsabilità" style="flex:2 1 220px;">
<select id="r-raci" aria-label="RACI"><option value="">RACI</option><option>R</option><option>A</option><option>C</option><option>I</option></select>
<button class="btn btn-sm btn-primary" id="nis2-isms-btn-add-role" onclick="addRole()" data-i18n="isms.s2.add">Aggiungi ruolo</button>
</div>
<button class="btn btn-outline" id="nis2-isms-btn-next-step2" style="margin-top:14px;" onclick="goStep(2)" data-i18n="isms.next">Continua</button>
</div></div>
</div>
<!-- STEP 3 - Risk (cl.6) -->
<div class="isms-panel" id="panel-2">
<div class="card"><div class="card-body">
<h3 data-i18n="isms.s3.title">3. Risk: metodologia e obiettivi (cl. 6)</h3>
<div class="isms-field"><label for="f-method" data-i18n="isms.s3.method">Metodologia di risk assessment</label><textarea id="f-method" rows="3" placeholder="Es. ISO 27005 / NIST SP 800-30; scala probabilità×impatto 5×5 (già usata nel modulo Rischi)."></textarea></div>
<div class="isms-field"><label for="f-objectives" data-i18n="isms.s3.objectives">Obiettivi del SGSI (uno per riga)</label><textarea id="f-objectives" rows="3"></textarea></div>
<p class="text-muted" data-i18n="isms.s3.link">Il registro dei rischi vive nel modulo <a href="risks.html">Rischi</a>: questo passo ne dichiara la metodologia.</p>
<button class="btn btn-primary" id="nis2-isms-btn-save-step3" onclick="saveStep3()" data-i18n="isms.save_next">Salva e continua</button>
</div></div>
</div>
<!-- STEP 4 - SoA -->
<div class="isms-panel" id="panel-3">
<div class="card"><div class="card-body">
<h3 data-i18n="isms.s4.title">4. Statement of Applicability</h3>
<p class="text-muted" data-i18n="isms.s4.hint">I controlli sono pre-popolati dalle risposte NIS2 dove esiste corrispondenza (badge "da NIS2"). Conferma applicabilità, stato e motivazione per ciascuno.</p>
<div style="margin:10px 0;">
<button class="btn btn-sm btn-outline" id="nis2-isms-btn-derive-soa" onclick="deriveSoa()" data-i18n="isms.s4.derive">Ri-deriva dal NIS2</button>
<span id="soa-stats" class="text-muted" style="margin-left:12px; font-size:.85rem;"></span>
</div>
<div id="soa-groups"></div>
<button class="btn btn-outline" id="nis2-isms-btn-next-step4" style="margin-top:14px;" onclick="goStep(4)" data-i18n="isms.next">Continua</button>
</div></div>
</div>
<!-- STEP 5 - Documented information (cl.7-8) -->
<div class="isms-panel" id="panel-4">
<div class="card"><div class="card-body">
<h3 data-i18n="isms.s5.title">5. Documented Information (cl. 7-8)</h3>
<div class="raci-row" style="border:none;">
<label for="d-type" class="sr-only" style="position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);">Tipo di documento</label>
<select id="d-type" style="flex:1 1 200px;" aria-label="Tipo di documento">
<option value="policy_sgsi">Policy SGSI</option>
<option value="dichiarazione_applicabilita">Dichiarazione di Applicabilità</option>
<option value="politica_controllo_accessi">Politica controllo accessi</option>
<option value="procedura_incident">Procedura gestione incidenti</option>
<option value="procedura_continuita">Procedura continuità operativa</option>
<option value="politica_fornitori">Politica sicurezza fornitori</option>
</select>
<button class="btn btn-sm btn-primary" onclick="aiGenDoc()" id="btn-aigen" data-i18n="isms.s5.aigen">Genera bozza con AI</button>
</div>
<div class="savehint" id="aigen-hint" role="status" aria-live="polite"></div>
<div id="docs-list" style="margin-top:14px;"></div>
<button class="btn btn-outline" id="nis2-isms-btn-next-step5" style="margin-top:14px;" onclick="goStep(5)" data-i18n="isms.next">Continua</button>
</div></div>
</div>
<!-- STEP 6 - Monitoring & Readiness (cl.9-10) -->
<div class="isms-panel" id="panel-5">
<div class="card"><div class="card-body">
<h3 data-i18n="isms.s6.title">6. Monitoraggio e Miglioramento (cl. 9-10)</h3>
<p class="text-muted" data-i18n="isms.s6.hint">Gli audit interni e le non conformità si gestiscono nei moduli esistenti: <a href="reports.html">Audit & Report</a> e NCR/CAPA.</p>
<h4 data-i18n="isms.s6.readiness">Completamento del SGSI</h4>
<div style="text-align:center; margin:14px 0;">
<div style="font-size:2.6rem; font-weight:800;" id="readiness-pct">0%</div>
</div>
<div id="readiness-checklist"></div>
</div></div>
<!-- STEP 1 - Contesto & Ambito (cl.4) -->
<div class="isms-panel" id="panel-0">
<div class="card card-pad">
<h3 data-i18n="isms.s1.title">1. Contesto e Ambito (cl. 4)</h3>
<div class="isms-field"><label for="f-scope" data-i18n="isms.s1.scope">Ambito del SGSI (scope statement)</label><textarea id="f-scope" rows="3" placeholder="Es. Tutti i sistemi e processi a supporto dei servizi ICT erogati dalla sede di..."></textarea></div>
<div class="isms-field"><label for="f-ctx-int" data-i18n="isms.s1.ctx_int">Contesto interno</label><textarea id="f-ctx-int" rows="2"></textarea></div>
<div class="isms-field"><label for="f-ctx-ext" data-i18n="isms.s1.ctx_ext">Contesto esterno</label><textarea id="f-ctx-ext" rows="2"></textarea></div>
<div class="isms-field"><label for="f-parties" data-i18n="isms.s1.parties">Parti interessate (una per riga)</label><textarea id="f-parties" rows="3" placeholder="Clienti&#10;Autorità (ACN/CSIRT)&#10;Fornitori ICT"></textarea></div>
<div class="isms-field"><label for="f-boundaries" data-i18n="isms.s1.boundaries">Confini del SGSI</label><textarea id="f-boundaries" rows="2"></textarea></div>
<div class="isms-field"><label for="f-exclusions" data-i18n="isms.s1.exclusions">Esclusioni motivate</label><textarea id="f-exclusions" rows="2"></textarea></div>
<div class="isms-flags">
<strong data-i18n="isms.s1.cloud">Estensioni cloud (attivano i controlli condizionali nel SoA)</strong>
<label><input type="checkbox" id="f-uses-cloud"> <span data-i18n="isms.s1.uses_cloud">Usiamo servizi cloud pubblici (Microsoft 365, AWS, Google...) → ISO 27017</span></label>
<label><input type="checkbox" id="f-cloud-provider"> <span data-i18n="isms.s1.cloud_provider">Siamo fornitori di servizi cloud → ISO 27017 (lato provider)</span></label>
<label><input type="checkbox" id="f-pii-cloud"> <span data-i18n="isms.s1.pii_cloud">Trattiamo dati personali (PII) in cloud pubblico come responsabili → ISO 27018</span></label>
</div>
<button class="btn-primary" id="nis2-isms-btn-save-step1" onclick="saveStep1()" data-i18n="isms.save_next">Salva e continua</button>
</div>
</div>
</main>
</div>
<!-- STEP 2 - Leadership (cl.5) -->
<div class="isms-panel" id="panel-1">
<div class="card card-pad">
<h3 data-i18n="isms.s2.title">2. Leadership: ruoli e responsabilità (cl. 5)</h3>
<p class="text-muted" data-i18n="isms.s2.hint">Definisci i ruoli del SGSI con la matrice RACI (Responsible, Accountable, Consulted, Informed).</p>
<div id="roles-list"></div>
<div class="raci-row" style="border-top:2px solid var(--line); margin-top:10px;">
<input id="r-name" placeholder="Ruolo (es. CISO)" aria-label="Ruolo" style="flex:1 1 160px;">
<input id="r-resp" placeholder="Responsabilità" aria-label="Responsabilità" style="flex:2 1 220px;">
<select id="r-raci" aria-label="RACI"><option value="">RACI</option><option>R</option><option>A</option><option>C</option><option>I</option></select>
<button class="btn-primary btn-sm" id="nis2-isms-btn-add-role" onclick="addRole()" data-i18n="isms.s2.add">Aggiungi ruolo</button>
</div>
<button class="btn-ghost" id="nis2-isms-btn-next-step2" style="margin-top:14px;" onclick="goStep(2)" data-i18n="isms.next">Continua</button>
</div>
</div>
<!-- STEP 3 - Risk (cl.6) -->
<div class="isms-panel" id="panel-2">
<div class="card card-pad">
<h3 data-i18n="isms.s3.title">3. Risk: metodologia e obiettivi (cl. 6)</h3>
<div class="isms-field"><label for="f-method" data-i18n="isms.s3.method">Metodologia di risk assessment</label><textarea id="f-method" rows="3" placeholder="Es. ISO 27005 / NIST SP 800-30; scala probabilità×impatto 5×5 (già usata nel modulo Rischi)."></textarea></div>
<div class="isms-field"><label for="f-objectives" data-i18n="isms.s3.objectives">Obiettivi del SGSI (uno per riga)</label><textarea id="f-objectives" rows="3"></textarea></div>
<p class="text-muted" data-i18n="isms.s3.link">Il registro dei rischi vive nel modulo <a href="risks.html">Rischi</a>: questo passo ne dichiara la metodologia.</p>
<button class="btn-primary" id="nis2-isms-btn-save-step3" onclick="saveStep3()" data-i18n="isms.save_next">Salva e continua</button>
</div>
</div>
<!-- STEP 4 - SoA -->
<div class="isms-panel" id="panel-3">
<div class="card card-pad">
<h3 data-i18n="isms.s4.title">4. Statement of Applicability</h3>
<p class="text-muted" data-i18n="isms.s4.hint">I controlli sono pre-popolati dalle risposte NIS2 dove esiste corrispondenza (badge "da NIS2"). Conferma applicabilità, stato e motivazione per ciascuno.</p>
<div style="margin:10px 0;">
<button class="btn-ghost btn-sm" id="nis2-isms-btn-derive-soa" onclick="deriveSoa()" data-i18n="isms.s4.derive">Ri-deriva dal NIS2</button>
<span id="soa-stats" class="text-muted" style="margin-left:12px; font-size:.85rem;"></span>
</div>
<div id="soa-groups"></div>
<button class="btn-ghost" id="nis2-isms-btn-next-step4" style="margin-top:14px;" onclick="goStep(4)" data-i18n="isms.next">Continua</button>
</div>
</div>
<!-- STEP 5 - Documented information (cl.7-8) -->
<div class="isms-panel" id="panel-4">
<div class="card card-pad">
<h3 data-i18n="isms.s5.title">5. Documented Information (cl. 7-8)</h3>
<div class="raci-row" style="border:none;">
<label for="d-type" class="sr-only">Tipo di documento</label>
<select id="d-type" style="flex:1 1 200px;" aria-label="Tipo di documento">
<option value="policy_sgsi">Policy SGSI</option>
<option value="dichiarazione_applicabilita">Dichiarazione di Applicabilità</option>
<option value="politica_controllo_accessi">Politica controllo accessi</option>
<option value="procedura_incident">Procedura gestione incidenti</option>
<option value="procedura_continuita">Procedura continuità operativa</option>
<option value="politica_fornitori">Politica sicurezza fornitori</option>
</select>
<button class="btn-primary btn-sm" onclick="aiGenDoc()" id="btn-aigen" data-i18n="isms.s5.aigen">Genera bozza con AI</button>
</div>
<div class="savehint" id="aigen-hint" role="status" aria-live="polite"></div>
<div id="docs-list" style="margin-top:14px;"></div>
<button class="btn-ghost" id="nis2-isms-btn-next-step5" style="margin-top:14px;" onclick="goStep(5)" data-i18n="isms.next">Continua</button>
</div>
</div>
<!-- STEP 6 - Monitoring & Readiness (cl.9-10) -->
<div class="isms-panel" id="panel-5">
<div class="card card-pad">
<h3 data-i18n="isms.s6.title">6. Monitoraggio e Miglioramento (cl. 9-10)</h3>
<p class="text-muted" data-i18n="isms.s6.hint">Gli audit interni e le non conformità si gestiscono nei moduli esistenti: <a href="reports.html">Audit & Report</a> e NCR/CAPA.</p>
<h4 data-i18n="isms.s6.readiness">Completamento del SGSI</h4>
<div style="text-align:center; margin:14px 0;">
<div style="font-size:2.6rem; font-weight:800; color:var(--c-blue);" id="readiness-pct">0%</div>
</div>
<div id="readiness-checklist"></div>
</div>
</div>
</section>
</main>
<!-- Scripts V3: api.js → common.js (helper+FAB reali) → Lucide self-host →
topnav-v3.js (chrome, ridefinisce loadSidebar) → i18n → help → isms.js.
isms.js si auto-inizializza su DOMContentLoaded (checkAuth/I18n/loadSidebar/Help/render). -->
<script src="/js/api.js?v=20260625d"></script>
<script src="/js/common.js?v=20260624g"></script>
<!-- Bootstrap Italia bundle (componenti) + override sidebar BI (common-bi.js).
common-bi.js va DOPO common.js: ridefinisce solo loadSidebar() con markup BI,
riusando tutti gli helper di common.js (zero backend). -->
<script src="/vendor/bootstrap-italia/dist/js/bootstrap-italia.bundle.min.js"></script>
<script>
if (window.bootstrap && bootstrap.loadFonts) {
bootstrap.loadFonts('/vendor/bootstrap-italia/dist/fonts');
}
</script>
<script src="/js/common-bi.js?v=20260625d"></script>
<script src="/js/common.js?v=20260627v3"></script>
<script src="/vendor/lucide/lucide.min.js"></script>
<script src="/js/topnav-v3.js?v=20260627"></script>
<script src="/js/i18n.js?v=20260631"></script>
<script src="/js/help.js?v=20260625d"></script>
<script src="/js/isms.js?v=20260620b"></script>
<script src="/js/isms.js?v=20260627v3"></script>
<script>
// Icone Lucide della chrome + crumb/page-head statici. L'init dati e il wiring
// (renderSteps/loadModel/goStep) restano in isms.js (suo DOMContentLoaded).
document.addEventListener('DOMContentLoaded', function(){
if (window.lucide && lucide.createIcons) { try { lucide.createIcons(); } catch (e) {} }
});
</script>
</body>
</html>