# Cima Progetti - Sito Aziendale
Sito web moderno, performante e accessibile sviluppato con **Svelte 5 + Vite** per presentare servizi, metodologia e contatti aziendali. Completamente responsivo con supporto completo per telefoni e tablet.
## β¨ FunzionalitΓ principali
- π **Tema light/dark** con persistenza dual-storage (localStorage + cookie backup)
- π± **Design completamente responsivo** con breakpoint intelligenti
- β¬οΈ **Header smart** β trasparente all'inizio, sfondo blur opaco dopo scroll
- π **Menu hamburger** con animazione fluida di apertura/chiusura
- π¨ **Sistema di componenti riusabili** e theme-aware
- π **Routing client-side** con History API e fallback 404 per pagine non create
- π **Cookie consent** con personalizzazione categorie
- βΏ **AccessibilitΓ ** β focus-visible preservato, tap highlight rimosso su touch
- β‘ **Svelte 5 Runes** β reattivitΓ state-driven con $state(), $derived()
- π **Global error handling** β trap di SyntaxError visibile su dev server
## π οΈ Requisiti
- **Node.js** 18+ (consigliato LTS)
- **npm** 9+
## π Avvio rapido
```bash
npm install
npm run dev
```
Applicazione disponibile su `http://localhost:5173` (accesso locale) e `http://192.168.XX.XXX:5173` (rete locale).
## π Script disponibili
| Script | Descrizione |
|--------|-------------|
| `npm run dev` | Avvia il server di sviluppo con hot reload (esposto su 0.0.0.0:5173) |
| `npm run build` | Genera la build di produzione ottimizzata in `dist/` |
| `npm run preview` | Avvia preview della build (simula produzione in locale) |
## π Struttura del progetto
```
cimaprogetti/
βββ index.html # Template HTML entry point
βββ package.json # Dependencies e scripts
βββ vite.config.js # Configurazione Vite (SPA + host 0.0.0.0)
βββ svelte.config.js # Configurazione Svelte
β
βββ src/
β βββ main.js # Entry point con error trap globale
β βββ App.svelte # Root component con routing e layout
β β
β βββ components/
β β βββ Header/
β β β βββ Header.svelte # Navbar sticky con tema + scroll detection
β β β βββ Header.css # Stili header (blur backdrop, absolute menu)
β β β
β β βββ Button/
β β β βββ Button.svelte # Button/link riusabile (16 prop)
β β β βββ Button.css # Stili + focus-visible + no tap highlight
β β β
β β βββ CookiePopUp/
β β β βββ CookiePopUp.svelte # Cookie consent con toggle personalizzato
β β β βββ CookiePopUp.css # Dialog mobile + desktop
β β β βββ assets/ # SVG cookie icon
β β β
β β βββ Toggle/
β β β βββ Toggle.svelte # Switch accessibile
β β β βββ Toggle.css # Stili toggle (animated knob)
β β β
β β βββ ThemeToggle/
β β β βββ ThemeToggle.svelte
β β β βββ ThemeToggle.css
β β β
β β βββ Footer/
β β β βββ Footer.svelte
β β β βββ Footer.css
β β β
β β βββ Hero/, Services/ # Componenti home
β β
β βββ pages/
β β βββ index.svelte # Home page
β β βββ Contacts.svelte # Pagina contatti con team profiles
β β βββ 403.svelte, 404.svelte, 500.svelte, errore.svelte # Error pages
β β
β βββ lib/
β β βββ theme.js # Theme persistence (localStorage + cookie)
β β βββ navigation.js # Client-side routing utilities
β β βββ cookieConsent.js # Cookie storage & consent management
β β βββ errorRouting.js # Path normalization & aliases
β β
β βββ styles/
β βββ global.css # CSS variables, typography, resets
β βββ App.css # Layout principale
β βββ contacts.css # Pagina contatti (flex + absolute positioning)
β βββ error-pages.css # Pagine errore (clamp typography)
β
βββ public/
βββ images/
βββ background/ # Background patterns
βββ icons/ # Logo, UI icons
βββ contacts/ # Hero images (light/dark theme)
```
## π Configurazione Network
Il server Vite Γ¨ configurato per essere **accessibile dalla rete locale**:
```js
// vite.config.js
server: {
host: '0.0.0.0', // Ascolta su tutte le interfacce
port: 5173,
}
```
### Accesso dal telefono sulla stessa Wi-Fi
1. Avvia il dev server: `npm run dev`
2. Nel terminale vedrai l'indirizzo IP locale (es. `192.168.68.119`)
3. Dal telefono apri: `http://192.168.68.119:5173`
**Nota:** Per produzione, usa `npm run build && npm run preview` per servire la versione compilata su `http://192.168.68.119:4173` (compatibile con browser vecchi).
## πΊοΈ Routing
Il routing Γ¨ **client-side only** β nessuna pagina server. Gestito in `App.svelte` leggendo `window.location.pathname` e reagendo ai cambi di History API.
### Tabella rotte
| Route | Pagina | Comportamento |
|-------|--------|---------------|
| `/` | `index.svelte` | Home page (Hero + Services) |
| `/contatti` o `/contacts` | `Contacts.svelte` | Info contatti + team profiles |
| `/servizi`, `/metodo`, `/progetti`, `/chi-siamo` | `404.svelte` | Non create β mostra 404 ma mantiene URL |
| `/403`, `/404`, `/500`, `/errore` | Error pages | Pagine errore dedicate |
| Qualsiasi altra rotta | `404.svelte` | Fallback automatico |
### Meccanismo di routing
```js
// src/App.svelte
const getRoute = (path) => {
const normalized = resolvePathname(path) // Normalizza trailing slash
if (normalized === '/') return 'home'
if (normalized === '/contatti' || normalized === '/contacts') return 'contacts'
// ...
return '404' // Fallback
}
let currentRoute = $derived(getRoute(pathname))
```
### Come aggiungere una nuova pagina
1. **Crea il componente** in `src/pages/MyPage.svelte`
2. **Importa in App.svelte**:
```svelte
import MyPage from "./pages/MyPage.svelte"
```
3. **Aggiungi la route** in `getRoute()`:
```js
if (normalized === '/my-page') return 'mypage'
```
4. **Renderizza nel template**:
```svelte
{:else if currentRoute === 'mypage'}
```
## π¨ Sistema di Tema
### Tema Persistente Dual-Storage
Il tema viene salvato su **localStorage** (primario) e **cookie** (backup) simultaneamente. Questo assicura che il tema sopravviva anche se l'utente cancella parte dello storage del browser.
```js
// src/lib/theme.js
export const getSavedTheme = () => {
// Prova localStorage prima, poi cookie come fallback
return localStorage.getItem('theme') || getCookie('theme')
}
export const saveTheme = (theme) => {
localStorage.setItem('theme', theme)
setCookie('theme', theme) // Backup redundante
}
export const applyTheme = (theme) => {
document.documentElement.setAttribute('data-theme', theme)
}
```
### Variabili CSS Globali
Tutte le variabili tema sono in `src/styles/global.css`:
```css
:root {
--navbar-height: 140px;
--primary-color: #1343F0; /* Blu Cima */
--text-color: #111827; /* Grigio scuro */
--surface: #ffffff; /* Background carta */
--background: rgba(246, 249, 255, 0.5);
--background-opaque: #00000033;
--muted-color: #6b7280;
--lateral-margin: 12rem;
}
:root[data-theme='dark'] {
--primary-color: #4983F2; /* Blu chiaro */
--text-color: #e6eef8; /* Grigio molto chiaro */
--surface: #000;
--background: rgba(0, 0, 0, 0.8);
--background-opaque: rgba(255, 255, 255, 0.2);
}
/* Mobile breakpoint */
@media (max-width: 900px) {
:root {
--navbar-height: 110px;
--lateral-margin: 1.5rem;
}
}
```
### Come usare i colori tema
```svelte
Contenuto automaticamente theme-aware
```
## π§© Componenti Principali
### Header (Navbar Intelligente)
La navbar Γ¨ **sticky** e reagisce allo scroll con una transizione elegante:
- **Trasparente all'inizio** (`background-color: transparent`)
- **Sfondo blur dopo 100px di scroll** (`backdrop-filter: blur(8px)`)
- **Scompare al scroll verso il basso** (nascosto con `translateY(-100%)`)
- **Riappare al scroll verso l'alto** (velocitΓ rilevata)
```svelte
```
**Modifiche in Header.svelte:**
- Stato `hasBackground` che attiva a `scrollY > 100`
- Classe `with-bg` per applicare blur e shadow
- Mobile menu hamburger con animazione da basso
**CSS Features:**
- `backdrop-filter: blur(8px)` per effetto frosted glass
- `position: fixed` con `transition: transform 0.28s`
- Menu mobile `transform: translateY(100%)` β `translateY(0)` con cubic-bezier smoothing
### Button (Componente Riusabile)
Componente ultra-flessibile che renderizza come `` se ha `href`, altrimenti `