[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
+122
View File
@@ -263,3 +263,125 @@ a.stat:hover{box-shadow:0 8px 20px rgba(16,40,80,.13);transform:translateY(-1px)
.ctrl-btn{min-width:44px;min-height:44px}
.fab{width:52px;height:52px}
}
/* ═══════════════════════════════════════════════════════════════════════════
* V3 — WIDGET CONDIVISI (compat) — modali/toast/form/bottoni/spinner/progress.
* Generati da common.js (showModal/showNotification) e dal markup di varie
* pagine: vivevano in style.css (rimosso dalle pagine V3). Qui sono ri-portati
* UNA volta sola e ritematizzati sui colori V3. NON ridefinisce .btn-primary /
* .btn-ghost / .badge-t (già in v3.css sopra): nessun conflitto.
* ═════════════════════════════════════════════════════════════════════════ */
:root{
/* alias V2→V3 usati dai widget sottostanti */
--primary:#1F5FA8; --primary-dark:#16487f; --primary-light:#3b7bc4; --primary-bg:#eaf1f9;
--secondary:#1E8A5A; --secondary-light:#27a06b; --secondary-bg:#e3f3ea;
--warning:#D98324; --warning-light:#e89a45; --warning-bg:#fbeede;
--danger:#C62828; --danger-light:#e05656; --danger-bg:#fbe5e5;
--info:#1F5FA8; --info-bg:#eaf1f9;
--gray-50:#f8fafc; --gray-100:#f1f5f9; --gray-200:#e2e8f0; --gray-300:#cbd5e1;
--gray-400:#94a3b8; --gray-500:#64748b; --gray-600:#475569; --gray-700:#334155;
--gray-800:#1e293b; --gray-900:#0f172a;
--card-bg:var(--card); --border-radius:10px; --border-radius-lg:var(--radius); --border-radius-sm:6px;
--transition:250ms ease; --transition-fast:150ms ease;
}
/* Bottoni (varianti non presenti in v3.css; self-sufficient, non toccano primary/ghost) */
.btn-secondary,.btn-success,.btn-danger,.btn-warning,.btn-outline{
display:inline-flex;align-items:center;justify-content:center;gap:8px;padding:10px 18px;
font-size:.875rem;font-weight:600;font-family:inherit;border:1px solid transparent;
border-radius:var(--radius);cursor:pointer;text-decoration:none;line-height:1.4;white-space:nowrap;
transition:background .15s ease,border-color .15s ease,color .15s ease}
.btn-secondary{background:var(--gray-100);color:var(--gray-700);border-color:var(--gray-300)}
.btn-secondary:hover:not(:disabled){background:var(--gray-200);border-color:var(--gray-400)}
.btn-success{background:var(--secondary);color:#fff;border-color:var(--secondary)}
.btn-success:hover:not(:disabled){background:var(--secondary-light)}
.btn-danger{background:var(--danger);color:#fff;border-color:var(--danger)}
.btn-danger:hover:not(:disabled){background:var(--danger-light)}
.btn-warning{background:var(--warning);color:#1a1a1a;border-color:var(--warning)}
.btn-outline{background:transparent;color:var(--navy-nav);border-color:var(--navy-nav)}
.btn-outline:hover:not(:disabled){background:var(--navy-nav);color:#fff}
.btn-secondary:disabled,.btn-success:disabled,.btn-danger:disabled,.btn-warning:disabled,.btn-outline:disabled{opacity:.5;cursor:not-allowed}
.btn-sm{padding:6px 14px;font-size:.8rem}
.btn-lg{padding:14px 28px;font-size:1rem}
.btn-icon{padding:8px;width:36px;height:36px}
.btn-group{display:flex;gap:8px}
/* Form */
.form-group{margin-bottom:20px}
.form-label{display:block;font-size:.8125rem;font-weight:600;color:var(--gray-700);margin-bottom:6px}
.form-label .required{color:var(--danger);margin-left:2px}
.form-group .form-label{position:static;line-height:1.4;padding:0;width:auto;max-width:none;z-index:auto;background-color:transparent;cursor:default}
.form-input,.form-select,.form-textarea{width:100%;padding:10px 14px;font-size:.875rem;font-family:inherit;color:var(--ink);background:var(--card);border:1px solid var(--line);border-radius:var(--border-radius);transition:border-color var(--transition-fast),box-shadow var(--transition-fast);outline:none}
.form-input:focus,.form-select:focus,.form-textarea:focus{border-color:var(--navy-nav);box-shadow:0 0 0 3px rgba(31,95,168,.15)}
.form-input::placeholder,.form-textarea::placeholder{color:var(--gray-400)}
.form-input.error,.form-select.error,.form-textarea.error{border-color:var(--danger);box-shadow:0 0 0 3px rgba(198,40,40,.12)}
.form-textarea{resize:vertical;min-height:100px}
.form-select{appearance:none;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='%2364748b' viewBox='0 0 16 16'%3E%3Cpath d='M8 11L3 6h10l-5 5z'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:right 12px center;padding-right:36px}
.form-help{font-size:.75rem;color:var(--gray-500);margin-top:6px}
/* Badge generici (style.css legacy) — coesistono con .badge-t di v3.css */
.badge{display:inline-flex;align-items:center;gap:4px;padding:3px 10px;font-size:.7rem;font-weight:600;border-radius:100px;text-transform:uppercase;letter-spacing:.03em;white-space:nowrap}
.badge-primary{background:var(--primary-bg);color:var(--primary)}
.badge-success{background:var(--secondary-bg);color:#15803d}
.badge-warning{background:var(--warning-bg);color:#a16207}
.badge-danger{background:var(--danger-bg);color:var(--danger)}
.badge-info{background:var(--info-bg);color:var(--primary)}
.badge-neutral{background:var(--gray-100);color:var(--gray-600)}
.badge-lg{padding:6px 16px;font-size:.8rem}
.tag{display:inline-flex;align-items:center;gap:4px;padding:4px 10px;font-size:.75rem;font-weight:500;background:var(--gray-100);color:var(--gray-600);border-radius:var(--border-radius-sm);border:1px solid var(--gray-200)}
/* Progress */
.progress{width:100%;height:8px;background:var(--gray-200);border-radius:100px;overflow:hidden}
.progress-bar{height:100%;border-radius:100px;transition:width .8s ease;background:var(--navy-nav)}
.progress-bar.success{background:var(--secondary)}
.progress-bar.warning{background:var(--warning)}
.progress-bar.danger{background:var(--danger)}
.progress-lg{height:12px}
.progress-label{display:flex;justify-content:space-between;margin-bottom:6px;font-size:.8rem}
.progress-label span:first-child{font-weight:600;color:var(--gray-700)}
.progress-label span:last-child{color:var(--gray-500)}
/* Modal (showModal di common.js) */
.modal-overlay{position:fixed;inset:0;width:100%;height:100%;background:rgba(15,23,42,.6);backdrop-filter:blur(4px);z-index:1000;display:flex;align-items:center;justify-content:center;opacity:0;visibility:hidden;transition:all var(--transition)}
.modal-overlay.active{opacity:1;visibility:visible}
.modal{background:var(--card);border-radius:var(--border-radius-lg);box-shadow:0 20px 60px rgba(0,0,0,.2);width:90%;max-width:560px;max-height:85vh;overflow-y:auto;transform:translateY(20px) scale(.95);transition:transform var(--transition)}
.modal-overlay.active .modal{transform:translateY(0) scale(1)}
.modal-overlay .modal{display:block;position:relative;inset:auto;margin:0;z-index:auto;pointer-events:auto}
.modal-header{padding:20px 24px;border-bottom:1px solid var(--line);display:flex;align-items:center;justify-content:space-between}
.modal-header h3{font-size:1.125rem;font-weight:700;color:var(--ink)}
.modal-close{background:none;border:none;color:var(--gray-400);cursor:pointer;padding:4px;border-radius:var(--border-radius-sm);transition:color var(--transition-fast);line-height:1;font-size:1.4rem}
.modal-close:hover{color:var(--gray-700)}
.modal-body{padding:24px}
.modal-footer{padding:16px 24px;border-top:1px solid var(--line);display:flex;justify-content:flex-end;gap:8px}
/* Notifiche / toast (showNotification di common.js) */
.notification-container{position:fixed;top:20px;right:20px;z-index:2000;display:flex;flex-direction:column;gap:8px;pointer-events:none}
.notification{background:var(--card);border-radius:var(--border-radius);box-shadow:0 8px 24px rgba(0,0,0,.15);padding:14px 20px;display:flex;align-items:center;gap:12px;min-width:320px;max-width:480px;pointer-events:auto;animation:slideIn .3s ease;border-left:4px solid var(--gray-400)}
.notification.success{border-left-color:var(--secondary)}
.notification.error{border-left-color:var(--danger)}
.notification.warning{border-left-color:var(--warning)}
.notification.info{border-left-color:var(--primary)}
.notification-icon{width:20px;height:20px;flex-shrink:0}
.notification.success .notification-icon{color:var(--secondary)}
.notification.error .notification-icon{color:var(--danger)}
.notification.warning .notification-icon{color:var(--warning)}
.notification.info .notification-icon{color:var(--primary)}
.notification-message{flex:1;font-size:.875rem;color:var(--gray-700);font-weight:500}
.notification-close{background:none;border:none;color:var(--gray-400);cursor:pointer;padding:2px;font-size:1.1rem;line-height:1}
.notification.fade-out{animation:slideOut .3s ease forwards}
@keyframes slideIn{from{transform:translateX(100%);opacity:0}to{transform:translateX(0);opacity:1}}
@keyframes slideOut{from{transform:translateX(0);opacity:1}to{transform:translateX(100%);opacity:0}}
/* Spinner */
.spinner{width:24px;height:24px;border:3px solid var(--gray-200);border-top-color:var(--navy-nav);border-radius:50%;animation:spin .7s linear infinite;margin:0 auto}
.spinner-lg{width:40px;height:40px;border-width:4px}
@keyframes spin{to{transform:rotate(360deg)}}
/* Utility generiche (ex Bootstrap Italia/style.css) usate da markup di varie pagine.
* .btn base SENZA padding → non altera il padding di .btn-primary/.btn-ghost (v3) ; i
* variant (sm/secondary/outline/...) restano self-sufficient. */
.btn{display:inline-flex;align-items:center;justify-content:center;gap:8px;font-family:inherit;font-weight:600;border:1px solid transparent;border-radius:var(--radius);cursor:pointer;text-decoration:none;line-height:1.4;white-space:nowrap;transition:background .15s ease,border-color .15s ease,color .15s ease}
.btn:disabled{opacity:.5;cursor:not-allowed}
.text-muted{color:var(--muted)}
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}
:root{ --success:var(--c-green); --error:var(--c-red); }