diff --git a/CHANGELOG.md b/CHANGELOG.md
index d4281dc..3841c4b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -12,6 +12,15 @@ per Windows (portatile e installabile), Mac e Android, e va online su [GitHub Pa
- **Clear** (licenza source-available, non permissiva) si può spegnere dal Centro AI.
- **Nota onesta**: i modelli veri non sono stati scaricati né eseguiti; prove con motori finti (`test/unit/funzioni-ai.test.mjs`, `test/unit/motore_ai_server*.py`).
+## [1.8.5] — 2026-10-30 · Revisione finale: tutto in ordine
+
+- **Montaggio più pulito**: barra del contenitore con le sole voci principali, lettere dei tasti leggibili (la S non sembra più un 5), Esc chiude il menu del tasto destro, velocità scritte ×0,25 / ×0,5.
+- **Mixer e Strumenti** stanno nella colonna senza tagli; la colonna destra si allarga sugli schermi grandi.
+- **Modifica clip**: tessere degli effetti più piccole (sei per riga), niente doppioni, etichette intere.
+- **Finale** senza titoli ripetuti; **LIVE** con REGISTRA unico pulsante oro; **Montage** con tutti i 28 stili a schermo.
+- **Guida, Novità, Cerca, Centro AI e finestre di sicurezza** rifinite; testi lunghi con i puntini e il testo intero al passaggio.
+- **README nuovo** come pagina prodotto, con i download in alto.
+
## [1.8.2] — 2026-10-30 · Meno scritte, tutto leggibile e a schermo
- **Scritte leggibili**: il carattere a 7 segmenti resta solo sui numeri (timecode); pesi, VRAM e dati usano un carattere mono pulito.
diff --git a/README.md b/README.md
index 112ea0e..8c8710b 100644
--- a/README.md
+++ b/README.md
@@ -1,209 +1,128 @@
-
-
+ DaProd Editor Video
+ Un editor video per Windows e Mac, in stile banco di montaggio.
+ Lo tieni sul tuo PC. Niente account, niente abbonamento.
-# DaProd · Editor Video 🎬
+
+
+
+
+
+
-[](https://cammo22.github.io/DaProdVideo/app/)
+
-[](https://cammo22.github.io/DaProdVideo/)
-[](https://github.com/cammo22/DaProdEditorVideo/releases/latest)
-[](CHANGELOG.md)
-[](https://tauri.app/)
-[](LICENSE)
-[](https://discord.gg/Njs52aacwq)
+Scarica
-Il **banco di montaggio DaProd**: vecchio stile, moderno dentro. Un monitor grande, il **contenitore** come un
-esplora risorse (le tue **cartelle**, e transizioni ed effetti con le **anteprime fatte coi fotogrammi del tuo
-montaggio**), la **pulsantiera** con i tasti grandi, i **livelli a barra**, gli **FX a blocchetti sopra le clip**
-(effetti e transizioni, coi loro suoni), la titolatrice, le **dissolvenze con la forma** (analogica, morbida, a S), i
-**proxy su richiesta da Attività** per andare lisci anche coi file pesanti, la **pagina Finale** per colore, **sottotitoli
-scritti dall'AI** (Nemotron di NVIDIA o Whisper, sul tuo computer), **voce AI**, **velocità delle clip** (Alt+E) col movimento fluido e logo su tutto il montaggio, **più timeline** nello stesso
-progetto, la pagina **LIVE** per registrare lo schermo **con la webcam a bolla** (3-2-1, pausa, segni, telecomando),
-il **pacchetto .daprod** con dentro tutti i file e la **EDL**. Cursore sul punto, premi **1** e tagli, premi **2**
-ed elimini. Arriva su **Windows, poi Linux e Mac** e, in versione prova, **nel browser**.
+
+
+
+
+
-
+Dalla pagina delle release scegli il file della tua versione:
+DaProd-Video-<versione>-setup.exe (installer Windows) · DaProd-Video-<versione>-portatile.exe (Windows senza installazione) · DaProd-Video-<versione>.dmg (Mac).
-| La pagina Finale: i sottotitoli scritti dall'AI, col menu a destra | Il contenitore a cartelle: la transizione provata sui tuoi fotogrammi |
-| --- | --- |
-|  |  |
+Windows può dire «Windows ha protetto il PC»: premi Ulteriori informazioni → Esegui comunque. Il Mac, la prima volta: tasto destro → Apri. I file non sono firmati a pagamento.
-| Il cubo 3D | Transizioni e proprietà |
-| --- | --- |
-|  |  |
+
-| Più timeline e i sottotitoli nella riga SOTT | LIVE: lo schermo in stile presentazione, con la webcam a bolla |
-| --- | --- |
-|  |  |
-
-## ▶ Come si monta
-
-> **Non sai dove sta una cosa?** Premi **`Ctrl+K`** (o 🔍 **Cerca** in alto) e scrivi quello che vuoi fare: *rallenta*,
-> *sottotitoli*, *togli lo sfondo*, *dissolvenza*, *titolo neon*… e la fai da lì, col suo tasto accanto. **`F1`** apre
-> **Come si fa**: una guida corta per ogni lavoro, col pulsante **Fallo adesso** che ti porta proprio al punto giusto.
-> Tutte le funzioni AI (sottotitoli, traduzione, voce, sfondo, tracking, montaggio automatico, colore) stanno insieme nel
-> **Centro AI** (pulsante ✨ **AI** in alto o menu **AI**), con **Controlla l'AI** che prova sul tuo computer se tutto è a posto.
-
-0. In alto c'è la **barra bianca** con le cose rapide: Progetti, Salva, Importa, Annulla/Ripeti, il nome del progetto e Cerca. Sotto, la testata coi menu, le pagine ed Esporta.
- All'apertura trovi la **pagina iniziale**: i progetti recenti (con la miniatura), Nuovo, Apri e DaProdMontage. Torni quando vuoi dal tasto **Progetti** in alto.
-1. **Importa** i video (pulsante *Importa*, `Ctrl+I`, o trascinali nel contenitore). Il primo video decide il formato del progetto. Nel contenitore a sinistra c'è l'albero: **Video, Musica, Immagini** e **le tue cartelle** (*Nuova cartella*, trascina i file dentro); importando da una cartella il file entra lì, da Musica la finestra mostra solo gli audio.
-2. Nel **contenitore** passa il mouse su un video: scorre avanti e indietro col puntatore. **Trascinalo** nella timeline, o premi **+** per metterlo al cursore (e il cursore va alla fine: +, +, + e hai la scaletta). Se lì è occupato va su una traccia libera: **niente viene coperto**.
-3. Vuoi scegliere il pezzo? **Doppio clic**: si apre nel monitor come **sorgente**. Segna **attacco** (`I`) e **stacco** (`O`) e premi **`,`** (inserisci) o **`.`** (sovrascrivi). **Tab** torna al montaggio.
-4. Cursore dove vuoi (la **rotella** va di un fotogramma alla volta, col suono) e **`1`**: taglio. Il pezzo più corto è già scelto: **`2`** e via, e si passa alla clip dopo. **`Q`** / **`W`** tolgono lo scarto a sinistra / a destra del cursore.
-5. **Accendi le tracce** (clic sul nome) e il taglio tocca solo quelle. **`S`** separa l'audio dal video, o unisce più clip in un gruppo.
-6. **Effetti e transizioni sono blocchetti sopra le clip**: una striscia sottile in basso sulla traccia video, niente corsia a parte. Trascina un **effetto** (lampo, scossa, zoom colpo, glitch, dal nero, zoom lento, camera a mano, bande cinema, e le **luci** e le **distorsioni**: bagliore, riflesso d'obiettivo, neon, onda, bolla, vortice, caleidoscopio…) sopra una clip: **si sistema da solo** all'inizio, alla fine o centrato sul taglio fra due clip (lontano dai bordi resta dove lo lasci), e vale per la sua traccia e per quelle sotto. Trascina una **transizione** (dissolvenza, passaggio al nero, spinta, zoom, mosaico, **cubo 3D**, girata, onda, lampo, glitch, tendine SMPTE con stella e cuore, frusta, rotazione, lama di luce, tenda, polvere…) vicino a un taglio: si centra da sola, e **più è lunga più è lenta**. Poi **allungali dai bordi**. Due o più sullo stesso punto **si sommano e si fondono**. Molti hanno già il **loro suono** (whoosh, colpo, zap, glitch, salita…), spento di partenza: l'**altoparlante sul blocco** lo accende con un clic, il **tasto destro sull'altoparlante** apre i suoni e **passandoci sopra li senti**. **Clic su un blocco o su una clip** e il pannello di destra mostra le sue impostazioni (📌 lo tiene sempre in vista). I blocchetti **seguono la clip** su cui stanno. Le clip non cambiano mai durata. Anche gli **effetti della clip** (Vivace, Caldo, Cinema, Pellicola, Vignetta…) si sommano fra loro.
-7. Il **volume** è la linea gialla sulle clip audio: trascinala, doppio clic per un punto, tasto destro → *Abbassa qui*. I **quadratini in alto** agli angoli di ogni clip sono le dissolvenze: tirali verso l'interno; poi **trascina la linea della dissolvenza su o giù** per la forma (analogica che parte piano piano, morbida, veloce; tasto destro sul quadratino → anche **a S** e le durate pronte; doppio clic la raddrizza). **Fade in, fade out, incrocio, eco, ovattato** si trascinano dal contenitore sulle clip audio. Il tasto **fx** in fondo alla clip accende gli effetti al volo.
-8. **`F9`** apre la pagina **Finale**, col suo menu a destra: **colore** (automatico su tutto, look, ritocchi, prima/dopo), **audio** finale col limitatore, **sottotitoli** (**scritti dall'AI**: Nemotron 3.5 di NVIDIA (nell'app, su scheda NVIDIA, Mac o CPU) o Whisper ascoltano la presa diretta, e dall'italiano Whisper li scrive anche direttamente in inglese; o i tempi dai dialoghi da riempire a mano; importa ed esporta .srt e .vtt), **logo** sempre in vista, **apertura** e chiusura (clip, titoli, dal nero e al nero), **lingue e AI** (compresa la **voce AI**: i sottotitoli letti da una voce di NVIDIA) ed **esporta** (MP4, MOV, WebM, WAV, EDL, .srt, .vtt).
-9. I **sottotitoli** stanno nella riga **SOTT**, fra le tracce video e quelle audio: **trascinali**, tira i bordi per i tempi, **doppio clic** (o **F2**) per scrivere o correggere il testo (Invio conferma, Maiusc+Invio va a capo, Ctrl+Invio divide la riga dove sta il cursore, Tab passa alla riga dopo), tasto destro per **unire** (appaiono insieme) o **dividere**. Nel Finale ogni riga ha i tasti ⇤ ⇥ − + per sistemare i tempi al volo. I sottotitoli «scritti nel video» escono bruciati nel filmato esportato.
-10. **Più timeline**: le schede sopra la timeline, il **+** ne fa una nuova o una copia; doppio clic per rinominarla.
-11. **`F10`** apre la pagina **LIVE**: **REGISTRA** (`R`, col 3-2-1), **PAUSA** (`Spazio`), **SEGNA** (`M`), **FERMA** (`F`). Col microfono (VU e scelta del microfono), l'audio del computer e la **webcam**, che si registra a parte e va sulla traccia sopra come **bolla** nell'angolo che scegli; lo **stile presentazione** mette lo schermo con angoli tondi e ombra su uno sfondo sfumato. Con **più finestre al volo** aggiungi altre finestre mentre registri (**N**) e passi dall'una all'altra (**1-9**, **L** cambia la disposizione). Il **TELECOMANDO** è una finestrella quasi quadrata, sempre sopra le altre, con l'**anteprima** di quello che registri, PAUSA grande, SEGNA, cambio finestra e FERMA. Tutto finisce nella cartella *Registrazioni* e in fondo alla timeline, legato insieme.
-12. **`V`** stringe la timeline: **proprietà, mixer e VU scendono fino in fondo** a destra (di nuovo `V` per tornare larga). La **barra a destra** della timeline scorre su e giù fra le tracce.
-13. **`P`** fa un'**istantanea** del fotogramma nel contenitore, da allungare quanto vuoi (**`Shift+P`**: fermo immagine al cursore).
-14. **Sull'immagine del monitor**: clic su quello che vedi e lo scegli; trascina per spostarlo, tira un angolo per ingrandirlo, il pallino in alto lo gira. tira un lato per stirare (Maiusc sugli angoli, Ctrl dal centro, **✂** per ritagliare) e Ctrl+clic sceglie quella sotto. **↝ Movimento** gli dà una posizione d'inizio e una di fine e tutte le **tappe** che vuoi (**+**, o fermo fra due tappe muovi) e ci passa dentro piano piano; **🎯** segue un oggetto (tracking) e titoli, immagini ed effetti lo inseguono; nelle proprietà ci sono i movimenti pronti (entra da sinistra, sale dal basso, si avvicina…). Gli effetti come **bolla**, **vortice** e **zoom** hanno un mirino: mettilo dove vuoi, anche in movimento. Più **transizioni sullo stesso taglio si sommano**.
-15. **File → Salva il pacchetto .daprod**: il progetto **con dentro tutti i suoi file** (uno zip vero, i file restano identici). Lo apri su un altro computer e ritrovi tutto. Il **.dpv** invece è il progetto leggero: tiene il montaggio, i file restano dove sono.
-16. **`F8`** apre **DaProdMontage**, la quarta pagina: butta dentro **foto e video alla rinfusa** (anche solo foto), scegli **cosa festeggi** (28 stili: matrimonio, battesimo, comunione, cresima, laurea, compleanno, Natale, viaggio, reel verticale…), quanto deve durare e, se vuoi, il brano. **✨ CREA IL MONTAGGIO** e il programma ordina le foto (per data di scatto), le tiene il tempo giusto, le muove, mette transizioni, titoli e quello che cade sopra, appoggia i tagli ai battiti. Lo vedi **in anteprima nel monitor in alto**: se non ti piace **🎲 Rigenera** (ogni volta cambia, anche con le stesse scelte), se ti piace **✅ Importa nella timeline** e lo ritocchi.
-17. **Togliere lo sfondo**: sulla clip, **Proprietà → Sfondo** (o il tasto **SFONDO** sul monitor). **Colore** (green screen con fino a 3 colori, contagocce, via il riflesso), **Luce** o **AI** (soggetto, persona, oggetti coi clic). **Generatori → Animazioni**: 49 animazioni personalizzabili (sottopancia, testi, grafici, social, fondi, cerimonie).
-18. **La barra delle attività** (in basso a destra) mostra sempre cosa fa il programma dietro le quinte — riaprire i file, forme d'onda, colore, copie leggere, conversioni, sottotitoli e voce con l'AI — con la percentuale e il tempo che manca. **Un clic** apre il pannello con tutte le righe (passati, mancano, in coda, finite da poco): **✕** ferma una riga, **⏸ Pausa** ferma i lavori in coda. I lavori pesanti vanno uno alla volta e aspettano mentre il montaggio suona; riaprendo un progetto con tante clip si riaprono prima i file che stanno in timeline, e le misure già fatte (forme d'onda, colore, locandine) si ricordano.
-19. A **schermo pieno** le tracce crescono da sole; **`Ctrl+Shift`+rotella** le alza e le abbassa. Nell'app **`Ctrl +`** e **`Ctrl −`** ingrandiscono tutta l'interfaccia.
-
-### 🎛 La pulsantiera
-
-| Tasto | Cosa fa | Tasto | Cosa fa |
-| --- | --- | --- | --- |
-| **1** | taglia al cursore (le tracce accese, o tutte) e sceglie il pezzo più corto | **5** | dissolvenza incrociata sul taglio più vicino |
-| **2** | elimina la clip scelta (con la sua audio) e passa alla dopo | **6** | tendina sul taglio |
-| **3** | elimina e chiude il buco (ripple) | **7** | passaggio al nero |
-| **S** (o **4**) | separa un gruppo / unisce più clip in un gruppo | **8** | dissolvenza in apertura e chiusura |
-| **Q** | via lo scarto a sinistra del cursore | **W** | via lo scarto a destra del cursore |
-
-| Tasto | Cosa fa | Tasto | Cosa fa |
-| --- | --- | --- | --- |
-| `Spazio` | play / stop | `J` `K` `L` | shuttle indietro, fermo, avanti (ripeti: ×2 ×4 ×8 ×16) |
-| `←` `→` rotella | un fotogramma, col suono (`Shift+←→`: un secondo) | `↑` `↓` | taglio precedente / successivo |
-| `I` `O` | attacco e stacco (sul monitor) | `Alt+X` | toglie attacco e stacco (anche la ✕ sul monitor) |
-| `,` `.` | inserisci / sovrascrivi dalla sorgente (`[` `]` su tastiera USA) | `E` `Invio` | EDIT nel modo attivo |
-| `Z` `X` | solleva / estrai fra attacco e stacco | `Shift+R` | rivedi l'ultimo montaggio con il preroll |
-| `Tab` | monitor: sorgente ↔ montaggio | `F` | abbina fotogramma (la sorgente nel monitor) |
-| `Ins` | modo libero / inserisci | `R` `N` `B` | ripple, calamita, linea della **trasparenza** sui video |
-| `Shift+Q` | attacco e stacco sulla clip sotto il cursore | `Ctrl+Shift`+rotella | tracce più alte / più basse |
-| `F9` | pagina Montaggio ↔ pagina **Finale** | `F10` | pagina **LIVE** (registra lo schermo) |
-| `V` | timeline stretta ↔ larga (proprietà e VU fino in fondo) | `Alt+Shift`+trascina | sposta la clip **e tutto quello dopo**, su tutte le tracce (come EDIUS) |
-| `M` | marcatore | `T` | titolo al cursore · `G` zone di sicurezza |
-| `P` | **istantanea** del fotogramma nel contenitore | `Shift+P` | **fermo immagine** di 2 s al cursore |
-| `Ctrl+Z` `Ctrl+Y` | annulla / ripeti (200 passi) | `Ctrl+C` `X` `V` | copia, taglia, incolla le clip |
-| tastierino `0-9` | scrive il timecode (`1000` = 10 s, `+25`) | `F1` | tutti i tasti |
-
-Con il mouse: **trascina** per spostare (anche di traccia: si ferma contro le vicine, non copre niente), i
-**bordi** per il trim, **Shift** sul taglio per il roll, **Alt** per lo slip, **Ctrl** per il trim ripple,
-**Alt+Shift** per spostare la clip e tutto quello che viene dopo, su tutte le tracce, insieme.
-**Rotella** = un fotogramma per scatto col suono, **Ctrl+rotella** = zoom, **Shift+rotella** = scorri,
-**Alt+rotella** = su e giù fra le tracce. **Tasto destro** sulla clip: elimina lo scarto a sinistra/destra di
-quel punto, transizioni all'inizio e alla fine, effetti a tempo, *Abbassa qui*; sul **blocchetto FX**: durata,
-centra sul taglio, cambia, **suono** (quale, acceso/spento, volume), colore, "ripeti subito dopo"; sull'**altoparlante** del
-blocchetto: i suoni, da sentire passandoci sopra; sulla **riga SOTT**: unisci, dividi, inizia e finisci al cursore. I menu
-stanno sempre dentro lo schermo. La **barra in fondo è un navigatore**: trascina la
-finestra gialla per scorrere, tira i suoi bordi per lo zoom. Ogni bordo fra i pannelli si trascina
-(doppio clic lo chiude). **Doppio clic sull'immagine**: schermo intero con la timeline in piccolo e i VU.
-Sul telefono: tocco = cursore, **tieni premuto** e trascina per spostare, **due dita** per lo zoom.
-
-## 📥 App: Windows, poi Linux e Mac
-
-I file delle [release](https://github.com/cammo22/DaProdEditorVideo/releases/latest):
-
-| | File | Come si usa |
-| --- | --- | --- |
-| 🪟 Windows | `DaProd-Video-X.Y.Z-portatile.exe` | niente installazione: doppio clic e parte. Se SmartScreen avvisa: *Ulteriori informazioni → Esegui comunque* |
-| 💿 Windows | `DaProd-Video-X.Y.Z-setup.exe` | installa con il collegamento nel menu Start (senza permessi di amministratore) |
-| 🍎 Mac | `DaProd-Video-X.Y.Z.dmg` | trascina in Applicazioni; la prima volta *tasto destro → Apri* (su Sequoia: *Impostazioni → Privacy e sicurezza → Apri comunque*) |
-
-Le app sono fatte con **Tauri 2**: l'interfaccia gira nel motore web del sistema (WebView2 su Windows, WebKit
-su Mac) e i file li legge e li scrive **Rust**. Pesano pochi MB, leggono ore di girato a
-pezzi senza caricarle in memoria, scrivono l'export mentre esce e **riprendono il montaggio da dove eri**.
-Requisiti: Windows 10/11, macOS 14 o più nuovo con Safari aggiornato (per l'audio serve WebKit 26).
-
-**È tutto automatico** (`.github/workflows/app.yml`): quando su `main` arriva una versione nuova (il campo
-`version` di `package.json`), GitHub Actions fa le prove, compila le app desktop e pubblica da sola la release
-`vX.Y.Z` con le note prese dal CHANGELOG. Per una versione nuova basta alzare `version`, scrivere la voce nel
-CHANGELOG e unire.
-
-**Aggiornarsi è un clic**: nell'app c'è il tasto **Aggiornamenti** in alto (si accende da solo quando esce una
-versione nuova). Fa vedere le novità, scarica il file giusto (setup, portatile o DMG) e lo apre. Alla prima
-apertura dopo l'aggiornamento compaiono le **novità** della versione (sempre anche da *Aiuto → Novità*).
-
-## 🌐 La versione prova su GitHub Pages
-
-[`cammo22.github.io/DaProdVideo`](https://cammo22.github.io/DaProdVideo/) è la home; il banco è in
-[`/app/`](https://cammo22.github.io/DaProdVideo/app/). È **completo** (montaggio, effetti, export), con
-il **montaggio dimostrativo** generato al volo per provarlo senza file. I limiti sono quelli del browser:
-
-- serve **Chrome, Edge, Brave, Opera** (anche su Android) o **Safari 26**: il motore è WebCodecs;
-- i file restano nel browser: riaprendo, Chrome ed Edge chiedono di ridare il permesso (*File → Ricollega media*), gli altri di sceglierli di nuovo;
-- l'export senza "Salva con nome" (Firefox, Safari) passa dalla memoria: per montaggi lunghi meglio l'app.
-
-Ogni merge su `main` ricompila la home e il banco e li mette sul ramo `gh-pages` (`.github/workflows/pages.yml`).
-Se il sito non si accende da solo, una volta sola: *Settings → Pages → Deploy from a branch → `gh-pages` / (root)*.
-
-## 🛠 Come è fatto
-
-| Pezzo | Con cosa |
+Cosa fa
+
+- 🎬 **Montaggio a tracce**: tagli, spostamenti, dissolvenze, velocità. Il tasto **1** taglia, il tasto **2** elimina.
+- 🎛️ **Proprietà a schede**: Quadro, Colore, Audio e AI, sempre nello stesso posto.
+- 🔊 **Finale**: volume in LUFS, controllo prima dell'uscita, preset per YouTube, Reel/TikTok, Instagram e master.
+- 📡 **LIVE**: registri schermo, webcam e microfono. Scene in diretta (tasti 1–6), telecomando a parte.
+- 🪄 **Montage**: scegli i file e lo stile, il programma monta da solo. Ritocchi veloci, e lo stesso seme dà lo stesso montaggio.
+- 🎨 **Colore**: LUT `.cube`, ruote lift/gamma/gain, curve RGB.
+- 🔑 **Keyframe e maschere**: posizione, zoom, opacità, colore, volume ed effetti. Maschere a rettangolo, ellisse e Bézier.
+- 🔤 **Titoli animati**: 24 animazioni pronte. Monitor ed esportazione sono identici.
+- 🧠 **AI locali** (vedi sotto): sfondo, rumore, voce, sottotitoli.
+- 💾 **Non perdi il lavoro**: autosalvataggio, «Recupera il lavoro» dopo un crash, file `.dap` con i media dentro.
+
+
+
+Requisiti
+
+- **Windows 10 o 11**, oppure **macOS 14** o più nuovo.
+- **Minimo**: un PC Windows o Mac normale. Il montaggio va anche senza scheda video.
+- **Per l'AI pesante** (rumore, sfondo, separazione voce): una scheda **NVIDIA RTX** con **8 GB** di memoria video è consigliata. Senza scheda video l'AI gira lo stesso, ma più lenta.
+- Spazio libero sul disco: i modelli AI pesano da pochi MB a qualche GB. Li scarichi solo se li vuoi.
+
+
+
+Primi passi
+
+1. Apri il programma e crea un progetto nuovo (File → Nuovo).
+2. Trascina i video nel **Contenitore** a sinistra, poi sulla timeline.
+3. Taglia con **1**, togli le parti brutte con **2**, sposta le clip con il mouse.
+4. Vai al **Finale**, scegli il preset e fai partire l'esportazione.
+
+
+
+Tasti principali
+
+| Tasto | Cosa fa |
| --- | --- |
-| Lettura e scrittura dei media | [Mediabunny](https://mediabunny.dev) (MP4, MOV, MKV, WebM, MPEG-TS/AVCHD, MP3, WAV, FLAC, OGG) su **WebCodecs**, decodifica e codifica hardware; AC-3 delle videocamere con il decoder WASM; **proxy automatici** (960 px, un fotogramma chiave ogni mezzo secondo) fatti dietro le quinte e conservati nel disco privato (OPFS) |
-| Mixer video | **WebGL2**: un buffer per strato, trasformazioni (con **angoli tondi e ombra morbida**, calcolati con la distanza da un rettangolo arrotondato), proc amp, chiave, look, tendine SMPTE, effetti digitali e dissolvenze negli shader; il passaggio degli **effetti a tempo** dopo ogni traccia che ne ha (valgono per lei e per quelle sotto); colore automatico misurato su ogni ripresa, un passaggio finale per il colore di tutto il montaggio, e sopra a tutto logo e sottotitoli |
-| Audio | **Web Audio**: volume e incroci come inviluppi, filtri per la voce, limitatore finale, audio a colpetti quando vai di fotogramma in fotogramma, VU dalla scheda audio, mixaggio dell'export a pezzi con `OfflineAudioContext` |
-| Registrazione (LIVE) | `getDisplayMedia` per lo schermo, `getUserMedia` per microfono e webcam, microfono e audio del computer mescolati con Web Audio, **MediaRecorder** a pezzi (ogni pausa chiude un pezzo, schermo e webcam allo stesso taglio); alla fine Mediabunny cuce i pezzi in un file solo, senza ricodificare, con durata e ricerca giuste e l'app lo salva in *Video → DaProd Video*. Il telecomando è una finestra **Document Picture-in-Picture** (nel browser) o la finestra dell'app fatta piccola e sempre in primo piano |
-| Pacchetto .daprod | uno **zip** scritto a mano (nomi UTF-8, **zip64** oltre i 4 GB), coi file "stored": nell'app Rust copia i byte e calcola il CRC a pezzi da 64 MB; all'apertura i media si leggono **direttamente da dentro lo zip** (inizio e lunghezza di ogni file), senza scompattare |
-| Timeline | una sola **tela 2D** ridisegnata solo quando serve; miniature a potenze di due (zoomando si riusano) e forma d'onda a 100 picchi al secondo |
-| Modello | fotogrammi interi sulla timeline (come le centraline a nastro), più timeline (sequenze) nello stesso progetto, annulla a fotografie del progetto |
-| Togliere lo sfondo | chiave a colori nel piano del colore (YUV) dello shader; ritaglio AI con [transformers.js](https://github.com/huggingface/transformers.js) in un Worker: **BEN2** e **BiRefNet** (MIT), **MODNet** (Apache-2.0), **SAM 2.1 Tiny** / SlimSAM (Apache-2.0); le maschere si mescolano nel tempo e stanno in una cache sul computer |
-| Animazioni | funzioni pure del tempo disegnate su **Canvas 2D** (`src/render/anim/`), ispirate al catalogo di [HyperFrames](https://github.com/heygen-com/hyperframes) (Apache-2.0); caratteri **@fontsource** (OFL) |
-| DaProdMontage | `src/core/montage.ts` (piano: ordine, doppioni, tempo esatto, battiti, Ken Burns) + 28 stili in `montagePreset.ts`; data EXIF, qualità e ritmo del brano calcolati sul posto, senza AI |
-| AI (sottotitoli, traduzione, voce, sfondo) | **Nemotron 3.5** di NVIDIA con [NeMo-Speech.cpp](https://github.com/NVIDIA/NeMo-Speech.cpp) 0.2.0 (programma a parte che l'app scarica da sola: CUDA, Metal o CPU, e se la scheda non ce la fa riprova sul processore; modelli GGUF che scarica lui) oppure **Whisper** (tiny, base o small), **Hy-MT2** (Apache-2.0, nel motore AI locale opzionale) per tradurre e i modelli per lo sfondo con [transformers.js](https://huggingface.co/docs/transformers.js) in un worker. **La libreria e ONNX Runtime viaggiano dentro l'app** (`public/ai/`, li prepara `scripts/ai-locale.mjs` prima della build, con il controllo dell'impronta): da Internet arrivano solo i modelli, da Hugging Face, **una volta sola**. Su WebGPU se c'è e funziona davvero, se no WASM; ogni modello prova più pesi (q8, fp16, fp32) prima di arrendersi, e gli errori si spiegano in italiano (`src/media/erroriAI.ts`). L'audio della presa diretta si prende a 16 kHz, si taglia nei silenzi a pezzi di un minuto e **non esce mai dal computer** |
-| App | **Tauri 2 / Rust**: `src-tauri/src/lib.rs` legge i media a pezzi, scrive l'export in streaming (anche `content://` su Android), salva progetti e autosalvataggio; `aggiorna.rs` scarica e apre la versione nuova |
-
-```bash
-npm install
-npm run dev # il banco in http://localhost:5173/app/
-npm run build # dist/: home + banco (quello che va su Pages e dentro le app)
-npm run tauri dev # l'app desktop in sviluppo (serve Rust)
-npm run tauri build # l'app desktop di rilascio
-```
-
-### 🙏 Crediti e licenze
-
-- **Animazioni**: il catalogo si ispira a [HyperFrames](https://github.com/heygen-com/hyperframes) di HeyGen (Apache-2.0); i disegni sono riscritti da zero per il nostro motore, nessun codice è copiato. I caratteri vengono da [Fontsource](https://fontsource.org) (SIL Open Font License).
-- **AI nell'app (1.3.0)**: [transformers.js](https://github.com/huggingface/transformers.js) 4.3.1 (Apache-2.0) e [ONNX Runtime Web](https://github.com/microsoft/onnxruntime) (MIT) sono copiati dentro l'app con le loro licenze (`ai/LICENSE-*.txt`).
-- **Togliere lo sfondo**: i modelli non stanno nell'app, si scaricano al primo uso da Hugging Face e restano sul computer: [BEN2](https://huggingface.co/PramaLLC/BEN2) e [BiRefNet](https://github.com/ZhengPeng7/BiRefNet) (MIT), [MODNet](https://github.com/ZHKKKe/MODNet) (Apache-2.0), [SAM 2.1 Tiny ONNX](https://huggingface.co/CardAnvilModels/sam2.1-hiera-tiny-ONNX) e [SlimSAM](https://github.com/czg1225/SlimSAM) (Apache-2.0), tutti via [transformers.js](https://github.com/huggingface/transformers.js) (Apache-2.0). Per la chiave a colori e il ritaglio ho letto come li fa [OpenReel](https://github.com/Augani/openreel-video) per confrontare le idee; il codice è nostro.
-
-### ✅ Controlli automatici
-
-```bash
-npm run build
-npx playwright install chromium
-node test/prove.mjs # oltre 300 prove (più `node test/prove-nuove.mjs [sfondo|animazioni|montage|aiuto]` da sole): timecode, 1 taglia (e sceglie il pezzo corto), 2 elimina (e passa alla
- # dopo), S separa/unisce, Q e W, tracce accese, rotella, niente viene coperto, volume
- # trascinato, FX sulle clip (si attaccano ai bordi, seguono la clip, suoni accesi/spenti
- # e nel mixaggio), Alt+Shift, maniglie delle dissolvenze, navigatore, pagina Finale
- # (sottotitoli AI, logo, apertura), effetti che si sommano, menu dentro lo schermo,
- # riga SOTT (sposta, unisci, dividi), più timeline, LIVE con pausa, novità, istantanea, tre punti dalla sorgente,
- # play col clic, countdown fino a 1, forme delle dissolvenze, cartelle, anteprime coi fotogrammi veri, riquadro
- # sui sottotitoli, pacchetto .daprod salvato e riaperto, LIVE con webcam, 3-2-1, segni e stile presentazione,
- # play dal mezzo di una ripresa col GOP lungo e proxy, EDL, export WebM riletto
-node test/foto.mjs # foto del banco (computer, Finale, contenitore, timeline, LIVE, telefono) in test/.out/
-```
-
-### 📁 Dove sta cosa
-
-- `src/core/` il modello: tipi, timecode (anche drop-frame), operazioni di montaggio, annulla, gli FX a blocchetti (`blocchi.ts`) e il catalogo dei loro suoni (`suoni.ts`), gli effetti della clip che si sommano (`effettiClip.ts`), le timeline (`sequenze.ts`), i sottotitoli, i titoli e countdown pronti (`generatori.ts`), le cornici (bolla, presentazione: `cornici.ts`).
-- `src/pacchetto.ts` il pacchetto .daprod (zip e zip64, scrittura e lettura).
-- `src/media/` Mediabunny: contenitore, fotogrammi (flusso e ricerca), proxy automatici, banco audio.
-- `src/render/` il piano di ogni fotogramma e il mixer WebGL2 (effetti a tempo, colore automatico e colore finale, logo e sottotitoli), titolatrice e countdown, le anteprime del contenitore coi fotogrammi del cursore (`provino.ts`).
-- `src/ui/` timeline, monitor, pulsantiera, contenitore, proprietà, pagina Finale, pagina LIVE (`live.ts`), pagina DaProdMontage (`montage.ts`), togliere lo sfondo (`sfondo.ts`), mixer e VU, strumenti, finestre.
-- Per ritrovare le cose: `src/ui/cerca.ts` (Ctrl+K) con quello che si trova in `fontiCerca.ts`, `src/ui/guida.ts` (F1, Come si fa), `src/ui/centroAI.ts` (Centro AI) e, sotto, `src/media/libreriaAI.ts` (la libreria AI dentro l'app e i ripieghi), `erroriAI.ts` (gli errori spiegati), `diagnosiAI.ts` (Controlla l'AI).
-- `src/azioni.ts` tutti i comandi con i loro tasti · `src/effetti.ts` gli effetti al volo · `src/export/` export ed EDL · `src/demo.ts` il montaggio dimostrativo.
-- `src-tauri/` l'app Rust, con `gen/android` per l'APK · `test/` le prove.
-
-## Limiti
-
-Il mosaico non garantisce anonimizzazione irreversibile: controlla tutta la clip e il tracking. La 1.5.7 non applica la censura dei progetti nuovi: non usare il downgrade per consegnare immagini protette.
+| **1** | Taglia (sulle tracce accese, o sulla clip sotto il cursore) |
+| **2** | Elimina lo scarto |
+| **S** | Separa / unisci |
+| **Q / W** | Togli lo scarto |
+| **Rotella** | Avanti o indietro di un fotogramma, con il suono |
+| **Ctrl + rotella** | Zoom della timeline |
+| **Alt + E** | Velocità della clip |
+| **Ctrl + D** | Duplica |
+| **Ctrl + K** | Cerca in tutto il programma |
+| **F1** | Guida |
+| **F8** | Montage |
+| **F10** | LIVE |
+
+Tutti i comandi sono in `src/azioni.ts`. **Ctrl + K** li trova anche per nome.
+
+
+
+AI: cosa è pronto e cosa è opzionale
+
+**Pronto nel programma** (si scarica il modello la prima volta, poi gira nel programma):
+
+- **Togli lo sfondo**: SAM 3 con clic sull'oggetto, o persona.
+- **Segui un oggetto**: tracking che sposta testo, immagini ed effetti.
+- **Togli i rumori**: MossFormer2 o DeepFilterNet3.
+- **Voce e base**: separa voce e musica (Demucs).
+- **Sottotitoli automatici**: Whisper, da 40 MB fino a 564 MB.
+- **Montaggio automatico** e **colore automatico**: nessun modello, sono regole del programma.
+
+**Opzionale** (si accende solo se lo chiedi, dal Centro AI):
+
+- Trova i tagli automatici, voce pulita, voce e musica con Kim Vocal 2.
+- Sottotitoli con Nemotron o con parole e tempi (Qwen3-ASR), traduzione dei sottotitoli (Hy-MT2).
+- Voce AI e voce realistica (Qwen3-TTS).
+- Voce da podcast (Clear): licenza source-available, si può spegnere.
+
+**Sperimentale**: rallentatore fluido (RIFE).
+
+Ogni risultato è materiale che puoi modificare. L'originale resta, e **Ctrl + Z** annulla.
+
+
+
+Privacy
+
+Tutto resta sul tuo PC. I video, l'audio e i progetti non vanno su internet. I modelli AI si scaricano una volta e poi girano in locale. I tuoi file non escono dal PC. Unico contatto esterno: il download dei modelli AI e, se usi Clear, un conteggio d'uso anonimo del suo SDK.
+
+
+
+Licenze di terze parti
+
+Il programma usa componenti di terzi, ognuno con la sua licenza. L'elenco completo e i testi sono in [TERZE-PARTI.md](TERZE-PARTI.md).
+
+
+
+
+ Novità ·
+ Software di terzi ·
+ Negozio DaProd ·
+ Discord
+
+
+Un'app DaProd Produzioni, fatta con cura e in italiano.
diff --git a/package-lock.json b/package-lock.json
index b1a2ff4..488fd22 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "daprod-video",
- "version": "1.8.2",
+ "version": "1.8.5",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "daprod-video",
- "version": "1.8.2",
+ "version": "1.8.5",
"license": "MIT",
"dependencies": {
"@desert-ant-labs/clear": "3.6.0",
diff --git a/package.json b/package.json
index 17f0acc..522bc6f 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
"name": "daprod-video",
"productName": "DaProd Video",
- "version": "1.8.2",
+ "version": "1.8.5",
"description": "DaProd Video: il montaggio video vecchio stile, moderno dentro. Timeline, due monitor, pulsantiera e VU a lancetta.",
"author": "DaProd",
"license": "MIT",
diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock
index f51eb6f..f08051b 100644
--- a/src-tauri/Cargo.lock
+++ b/src-tauri/Cargo.lock
@@ -615,7 +615,7 @@ checksum = "914a755b7c2d4af2bdcff7ce1739e2db9a1b81a9b07123d8015786ae03c0980d"
[[package]]
name = "daprod-video"
-version = "1.8.2"
+version = "1.8.5"
dependencies = [
"getrandom 0.3.4",
"libc",
diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml
index 29904f6..30bfb46 100644
--- a/src-tauri/Cargo.toml
+++ b/src-tauri/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "daprod-video"
-version = "1.8.2"
+version = "1.8.5"
description = "DaProd Video: il montaggio vecchio stile, moderno dentro"
authors = ["DaProd"]
license = "MIT"
diff --git a/src/main.ts b/src/main.ts
index 3cbc7a7..5da0423 100644
--- a/src/main.ts
+++ b/src/main.ts
@@ -35,6 +35,7 @@ import { attivaSuggerimenti } from './ui/suggerimento';
// il sistema «Banco» sulle altre schermate: va DOPO tutti gli altri stili (anche quelli che arrivano con ui/app)
import './stile/schermate.css';
import './stile/montage.css';
+import './stile/montaggioRev.css';
import { h } from './ui/dom';
import { isTauri } from './platform';
import { preparaRiserva } from './media/riserva';
diff --git a/src/stile/finale.css b/src/stile/finale.css
index 465a2e7..a507efc 100644
--- a/src/stile/finale.css
+++ b/src/stile/finale.css
@@ -128,6 +128,7 @@ html #app[data-pagina='finale']:not(.stretto) {
.fin-schede-nav button { min-height: var(--riga, clamp(34px, 3.15vh, 36px)); font: 600 15px/1.3 var(--ui); }
.fin-schede-nav button[aria-pressed='true'] { border-color: var(--cia, #35e8ff); color: var(--cia, #35e8ff); }
.fin-schede-corpo { min-width: 0; min-height: 0; }
+.finale .fin-doppio { display: none; }
.fin-schede-corpo > [hidden] { display: none !important; }
.finale :is(button, summary, input, select, textarea):focus-visible { outline: 2px solid var(--cia); outline-offset: 2px; }
.fin-misure { gap: 8px; padding: 8px 12px; }
diff --git a/src/stile/live.css b/src/stile/live.css
index 245175a..cae1016 100644
--- a/src/stile/live.css
+++ b/src/stile/live.css
@@ -36,6 +36,10 @@
border: 1px solid var(--bordo-forte); background: var(--metallo-chiaro); color: var(--testo);
font: 700 17px var(--ui); letter-spacing: 1px; box-shadow: none;
}
+/* l'unico oro della pagina è REGISTRA (fermo); «Esporta» della testata diventa di metallo */
+#app .live:not(.in-onda):not(.in-pausa) .live-btn.reg:not(:disabled) { background: var(--oro); color: #14110a; border-color: rgba(255, 213, 74, 0.5); box-shadow: 0 0 0 1px rgba(255, 213, 74, 0.35), 0 6px 18px rgba(255, 171, 0, 0.22); }
+#app .live:not(.in-onda):not(.in-pausa) .live-btn.reg:not(:disabled) .live-punto { background: var(--rosso); }
+#app[data-pagina='live'] .testata .btn.primario { background: linear-gradient(180deg, #2c2b34, #1d1c23); color: var(--testo); border-color: var(--bordo-forte); box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.07); }
#app .live .live-btn.reg .live-punto { width: 14px; height: 14px; border-radius: 50%; flex: none; background: #4d4650; box-shadow: none; transition: background 0.15s, border-radius 0.15s; }
#app .live.in-onda .live-btn.reg { border-color: var(--rosso); background: rgba(255, 77, 109, 0.15); }
#app .live.in-onda .live-btn.reg .live-punto { border-radius: 2px; background: var(--rosso); box-shadow: 0 0 12px var(--rosso); animation: live-pulsa 1s ease-in-out infinite; }
diff --git a/src/stile/montage.css b/src/stile/montage.css
index f2f1227..5850536 100644
--- a/src/stile/montage.css
+++ b/src/stile/montage.css
@@ -87,15 +87,17 @@
/* ——— 2 · gli stili ——— */
.montage .mt-filtri { flex: none; }
-.montage .mt-feste { flex: 1; min-height: 0; overflow: auto; display: grid; grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); grid-auto-rows: minmax(196px, 1fr); gap: 14px; align-content: start; padding: 2px; }
-.montage .mt-festa { position: relative; display: flex; flex-direction: column; justify-content: flex-end; gap: 2px; min-height: 196px; padding: 0 0 12px; overflow: hidden; text-align: left; border: 2px solid transparent; border-radius: 8px; color: var(--testo); cursor: pointer; }
-.montage .mt-festa canvas { position: absolute; left: 0; top: 0; width: 100%; height: calc(100% - 96px); object-fit: cover; }
+.montage .mt-feste { flex: 1; min-height: 0; overflow: auto; display: grid; grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); grid-auto-rows: minmax(150px, 1fr); gap: 12px; align-content: stretch; padding: 2px; }
+.montage .mt-festa { position: relative; display: flex; flex-direction: column; justify-content: flex-end; gap: 2px; min-height: 150px; padding: 0 0 10px; overflow: hidden; text-align: left; border: 2px solid transparent; border-radius: 8px; color: var(--testo); cursor: pointer; }
+.montage .mt-festa canvas { position: absolute; left: 0; top: 0; width: 100%; height: calc(100% - 84px); object-fit: cover; }
.montage .mt-velo { position: absolute; left: 0; right: 0; bottom: 84px; height: 40px; background: linear-gradient(180deg, rgba(11, 10, 15, 0), rgba(11, 10, 15, 0.78)); pointer-events: none; }
.montage .mt-festa b, .montage .mt-festa small, .montage .mt-festa em { position: relative; font-style: normal; padding: 0 14px; }
-.montage .mt-festa b { font: 700 22px/1.15 var(--ui); }
-.montage .mt-festa small { font: 500 14px/1.3 var(--ui); color: #cfcadb; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
+.montage .mt-festa b { font: 700 20px/1.15 var(--ui); }
+.montage .mt-festa small { font: 500 14px/1.3 var(--ui); color: #cfcadb; display: -webkit-box; -webkit-line-clamp: 1; -webkit-box-orient: vertical; overflow: hidden; }
+/* ritmo e musica stanno nel suggerimento e al passo 3: sulla scheda sono una scritta in più */
+.montage .mt-festa em { display: none; }
.montage .mt-festa em { font: 600 12.5px var(--ui); color: var(--etichetta); letter-spacing: 0.5px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
-.montage .mt-festa::after { content: ''; position: absolute; left: 0; right: 0; bottom: 0; height: 96px; background: rgba(11, 10, 15, 0.82); z-index: 0; }
+.montage .mt-festa::after { content: ''; position: absolute; left: 0; right: 0; bottom: 0; height: 84px; background: rgba(11, 10, 15, 0.82); z-index: 0; }
.montage .mt-festa b, .montage .mt-festa small, .montage .mt-festa em { z-index: 1; }
.montage .mt-festa:hover { border-color: var(--bordo-forte); }
.montage .mt-festa.scelta { border-color: var(--cia); box-shadow: 0 0 0 1px var(--cia); }
diff --git a/src/stile/montaggioRev.css b/src/stile/montaggioRev.css
new file mode 100644
index 0000000..996cef9
--- /dev/null
+++ b/src/stile/montaggioRev.css
@@ -0,0 +1,55 @@
+/* Revisione 1.8.5 — Montaggio, colonna destra, Modifica clip, Cerca, Centro AI, finestre.
+ Solo correzioni di ordine (cose tagliate, schiacciate, duplicate): le regole grandi stanno nei file «Banco».
+ Va DOPO tutti gli altri stili. */
+
+/* ——— la colonna destra cresce con lo schermo (a 2560 era sempre stretta e il resto restava vuoto) ——— */
+@media (min-width: 1800px) { :root { --lato: clamp(300px, 15.6vw, 420px); } }
+
+/* ——— contenitore stretto (barretta di icone): solo le voci principali, senza il solco di puntini delle sottovoci ——— */
+@container (max-width: 430px) {
+ .bin-cat.sotto { display: none; }
+ .bin-albero-titolo { display: block; font-size: 0; height: 1px; padding: 0; margin: 6px 6px; background: var(--bordo); }
+}
+
+/* ——— Mixer: le strisce dividono la colonna (cinque non stavano e «ASCOLTO» usciva dal bordo) ——— */
+.strisce { gap: 4px; }
+.striscia { flex: 1 1 0; width: auto; min-width: 0; }
+.striscia-nome, .striscia-tipo { max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
+.striscia.master .striscia-nome { font-size: 9px; letter-spacing: 0; }
+
+/* ——— Strumenti: forma d'onda e vettorscopio stanno tutti e due nella colonna, senza scorrere ——— */
+.lato-corpo:has(> .scopi) { overflow: hidden; }
+.scopi { display: flex; flex-direction: column; height: 100%; min-height: 0; box-sizing: border-box; gap: 6px; }
+.scopi figure { margin: 0; display: flex; flex-direction: column; min-height: 0; }
+.scopi figure:first-of-type { flex: 0 0 34%; }
+.scopi figure:nth-of-type(2) { flex: 1 1 0; }
+.scopi canvas, .scopi figure:nth-child(2) canvas { flex: 1 1 0; min-height: 0; width: 100%; height: 100%; object-fit: contain; margin: 0; }
+.scopi figcaption { flex: none; padding-top: 2px; }
+.scopi .nota { flex: none; margin: 0; font-size: 12px; line-height: 1.3; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }
+
+/* ——— Cerca (Ctrl+K): le righe non escono dal riquadro, il testo lungo ha i puntini ——— */
+.cerca-voce { grid-template-columns: 118px minmax(0, 1fr) auto; }
+.cerca-testo { min-width: 0; }
+.cerca-testo b { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
+.cerca-cat { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
+
+/* ——— Tasti della centralina: i tasti restano piccoli (si allungavano quanto la riga della spiegazione) ——— */
+.tasto-riga { align-items: start; }
+.tasto-riga .tasti { align-self: start; align-items: flex-start; }
+.tasto-riga kbd { align-self: flex-start; height: auto; line-height: 1.5; }
+
+/* ——— Centro AI: titoli e frasi lunghe con i puntini, niente tagli a metà parola ——— */
+.centro-ai .sch-funzione p { min-width: 0; }
+
+/* ——— Modifica clip ——— */
+.editor-clip .tessere { grid-template-columns: repeat(auto-fill, minmax(132px, 1fr)); gap: 8px; }
+.editor-clip .ec-campi { min-width: 0; }
+.scopi figure:first-of-type canvas { object-fit: fill; }
+
+/* ——— pulsantiera: la «S» nel carattere a spaziatura fissa sembrava un 5 (SEPARA e MIX avevano lo stesso numero): le lettere vanno nel carattere normale ——— */
+.tasto-num .tasto-numero.lettera { font: 800 12px var(--ui); }
+.menu-contesto .voce .tasto.lettera, .voce .tasto.lettera { font: 700 13px var(--ui); }
+
+/* Modifica clip: la sezione principale non ha più il filo giallo (vecchio stile) che toccava i campi */
+.editor-clip .isp-gruppo.principale { box-shadow: none; border: 0; }
+.editor-clip .isp-riga { grid-template-columns: minmax(96px, 150px) minmax(0, 1fr) auto; }
diff --git a/src/stile/schermate.css b/src/stile/schermate.css
index d3ea9f4..e5e1dc5 100644
--- a/src/stile/schermate.css
+++ b/src/stile/schermate.css
@@ -300,3 +300,10 @@ body.pip-live { background: var(--fondo, #0b0a0f); }
.home .hm-quando { font-family: var(--mono) !important; font-size: 12px !important; }
.home .hm-targa .hm-seg { font-family: var(--mono); }
.dialogo.centro-ai { width: min(1120px, calc(100vw - 48px)); max-height: calc(100dvh - 80px); }
+
+/* guida: l'icona dell'argomento sta staccata dal titolo e l'elenco usa l'altezza che c'è */
+.dialogo.guida .guida-corpo h3 { display: flex; gap: 10px; align-items: center; }
+.dialogo.guida .guida-elenco { max-height: 70vh; }
+
+/* novità: il titolo della versione è testo, non oro (l'oro è dell'azione) */
+.novita-titolo { color: var(--testo, #ebe7f4); font-size: 18px; }
diff --git a/src/stile/solido.css b/src/stile/solido.css
index a069653..23ad4ee 100644
--- a/src/stile/solido.css
+++ b/src/stile/solido.css
@@ -19,6 +19,7 @@
/* comandi alti almeno 44 px */
.btn.sol-alto { min-height: 44px; padding: 0 18px; border-radius: 6px; font-size: 14px; font-weight: 700; }
+.dialogo.solido .btn.sol-alto { font: 700 15px var(--ui); } /* tutti i tasti del piede della stessa misura */
.btn.sol-leggero { color: var(--testo2); }
.btn.sol-leggero:hover { color: var(--testo); }
.btn.sol-alto:disabled { opacity: 0.45; cursor: default; }
diff --git a/src/ui/centroAI.ts b/src/ui/centroAI.ts
index 10a4ef8..38686a6 100644
--- a/src/ui/centroAI.ts
+++ b/src/ui/centroAI.ts
@@ -389,9 +389,10 @@ function schedeRegistro(chiudi: () => void, controlla: () => void): HTMLElement
precedente.disabled = indice === 0; successiva.disabled = indice === pagine - 1; pagina.textContent = `${indice + 1} / ${pagine}`;
griglia.replaceChildren(...lista.slice(indice * 12, indice * 12 + 12).map((f) => {
const guida = FUNZIONI_AI.find((x) => x.id === f.id);
- const nome = f.nome.replace(/ \(.*$/, '').slice(0, 24);
+ const nome = f.nome.replace(/ \(.*$/, '');
const manca = guida?.manca();
- const descrizione = manca ? '⚠ ' + manca.slice(0, 52) : f.descrizione.split(/[.;(]/)[0].slice(0, 55);
+ // niente tagli a mano: se non sta in una riga ci pensa il CSS (puntini), e il testo intero è nel suggerimento
+ const descrizione = manca ? '⚠ ' + manca : f.descrizione.split(/\.\s|[;(]/)[0].replace(/\.$/, '');
const peso = !f.peso || /nessun modello/i.test(f.peso) ? 'Integrata' : f.id === 'rumore' ? 'da 9 MB' : f.id === 'sottotitoli' ? 'da 40 MB' : (f.peso.match(/[\d,.]+(?:–[\d,.]+)?\s*(?:MB|GB)/i)?.[0] ?? 'Peso da verificare');
const info = h('button', { class: 'btn-mini ai-info', 'aria-label': `Informazioni su ${f.nome}`, title: 'Dettagli e requisiti', on: { click: () => {
const d = dialogo(f.nome); d.corpo.append(h('p', null, f.descrizione), h('p', { class: 'sch-pesovram' }, pesoEVram(f).riga)); if (guida) d.corpo.append(h('p', null, guida.come.join(' · ')));
diff --git a/src/ui/contenitore.ts b/src/ui/contenitore.ts
index 6d7ee3a..87a1ffb 100644
--- a/src/ui/contenitore.ts
+++ b/src/ui/contenitore.ts
@@ -41,7 +41,7 @@ const TIPI: Ramo[] = [
const LIBRERIA: Ramo[] = [
{ id: 'transizioni', nome: 'Transizioni', icona: 'transizione', figli: [['tr:dissolvenze', 'Dissolvenze'], ['tr:movimento', 'Movimento'], ['tr:3d', '3D e forme'], ['tr:luce', 'Luce'], ['tr:stile', 'Stile'], ['tr:tendine', 'Tendine SMPTE']] },
{ id: 'titoli', nome: 'Titoli', icona: 'titolo', figli: [['tit:titoli', 'Titoli'], ...GRUPPI_HTML.map((g): [string, string] => ['tit:html-' + g.id, 'Animati · ' + g.nome]), ['tit:sott', 'Sottotitoli'], ['tit:tv', 'TV e social'], ['tit:conto', 'Countdown'], ['tit:sala', 'Macchine della sala']] },
- { id: 'animazioni', nome: 'Animazioni', icona: 'effetti', figli: GRUPPI_LIBRERIA.map((g): [string, string] => ['an:' + g.id, g.nome]) },
+ { id: 'animazioni', nome: 'Animazioni', icona: 'elastico', figli: GRUPPI_LIBRERIA.map((g): [string, string] => ['an:' + g.id, g.nome]) },
{ id: 'effetti', nome: 'Effetti', icona: 'effetti', figli: [['fx:rapidi', 'Rapidi'], ['fx:lunghi', 'Lunghi'], ['fx:luci', 'Luci'], ['fx:distorsioni', 'Distorsioni'], ['fx:colore', 'Colore'], ['fx:particelle', 'Particelle'], ['fx:clip', 'Stile della clip'], ['fx:audio', 'Audio']] },
];
@@ -247,7 +247,7 @@ export class Contenitore {
const voce = (id: string, nome: string, ic: string, livello: number, extra: { figli?: boolean; n?: number } = {}) => {
const chiuso = this.chiusi.has(id);
const el = h('button', {
- class: 'bin-cat' + (id === this.nodo ? ' attiva' : '') + (extra.figli ? ' con-figli' : '') + (chiuso ? ' chiuso' : ''), 'data-c': id, title: nome,
+ class: 'bin-cat' + (id === this.nodo ? ' attiva' : '') + (extra.figli ? ' con-figli' : '') + (chiuso ? ' chiuso' : '') + (livello > 0 ? ' sotto' : ''), 'data-c': id, title: nome,
style: `--livello:${livello}`,
on: {
click: (e: MouseEvent) => {
diff --git a/src/ui/dom.ts b/src/ui/dom.ts
index 7ed1317..6bc3579 100644
--- a/src/ui/dom.ts
+++ b/src/ui/dom.ts
@@ -233,8 +233,16 @@ export function menuContesto(x: number, y: number, voci: VoceMenu[]) {
dentroLoSchermo(m, x, y);
menuAperto = m;
setTimeout(() => {
- const via = (e: Event) => { if (!m.contains(e.target as Node)) { chiudiMenu(); document.removeEventListener('pointerdown', via, true); } };
+ const via = (e: Event) => { if (!m.contains(e.target as Node)) { chiudiMenu(); document.removeEventListener('pointerdown', via, true); document.removeEventListener('keydown', esc, true); } };
+ // Esc chiude il menu (e basta: non deve anche togliere la scelta alla clip)
+ const esc = (e: KeyboardEvent) => {
+ if (!m.isConnected) { document.removeEventListener('keydown', esc, true); document.removeEventListener('pointerdown', via, true); return; }
+ if (e.key !== 'Escape') return;
+ e.stopPropagation(); e.preventDefault(); chiudiMenu();
+ document.removeEventListener('keydown', esc, true); document.removeEventListener('pointerdown', via, true);
+ };
document.addEventListener('pointerdown', via, true);
+ document.addEventListener('keydown', esc, true);
});
}
@@ -245,7 +253,7 @@ export function costruisciMenu(voci: VoceMenu[]): HTMLElement {
const riga = h('button', {
class: 'voce' + (v.disattiva ? ' spenta' : '') + (v.sotto ? ' ha-sotto' : ''), role: 'menuitem', disabled: !!v.disattiva,
on: { click: (e: Event) => { if (v.sotto) { e.stopPropagation(); return; } chiudiMenu(); v.fn?.(); } },
- }, h('span', { class: 'spunta' }, v.spunta ? '●' : ''), h('span', { class: 'nome' }, v.nome ?? ''), h('span', { class: 'tasto' }, v.tasto ?? (v.sotto ? '▸' : '')));
+ }, h('span', { class: 'spunta' }, v.spunta ? '●' : ''), h('span', { class: 'nome' }, v.nome ?? ''), h('span', { class: 'tasto' + (/^[A-Za-z]$/.test(v.tasto ?? '') ? ' lettera' : '') }, v.tasto ?? (v.sotto ? '▸' : '')));
if (v.sotto) {
const sub = costruisciMenu(v.sotto);
sub.classList.add('sotto');
diff --git a/src/ui/finaleSchede.ts b/src/ui/finaleSchede.ts
index ad7fc05..f441a9d 100644
--- a/src/ui/finaleSchede.ts
+++ b/src/ui/finaleSchede.ts
@@ -12,6 +12,12 @@ export function schedeFinale(pannelli: HTMLElement[], nomi?: string[], iniziale
pannelli.forEach((p, i) => nav.append(h('button', {
type: 'button', class: 'btn-mini', on: { click: () => scegli(i) },
}, nomi?.[i] ?? p.querySelector('h4, legend')?.textContent ?? `Sezione ${i + 1}`)));
+ // il titolo del pannello che ripete la scheda appena premuta è scritta in più: si nasconde
+ pannelli.forEach((p, i) => {
+ const t = p.querySelector(':scope > h4');
+ const scheda = nav.children[i]?.textContent?.trim().toLowerCase();
+ if (t && scheda && t.textContent?.trim().toLowerCase() === scheda) t.classList.add('fin-doppio');
+ });
scegli(iniziale);
return h('div', { class: 'fin-schede' }, nav, corpo);
}
diff --git a/src/ui/ispettore.ts b/src/ui/ispettore.ts
index d00b7d3..0b9343b 100644
--- a/src/ui/ispettore.ts
+++ b/src/ui/ispettore.ts
@@ -1295,8 +1295,8 @@ export class Ispettore {
scelte.append(h('button', { class: 'pp-mini-btn', 'data-gruppo': g.dataset.g, on: { click: () => apri(g) } }, g.querySelector('summary')?.childNodes[0]?.textContent ?? 'Controlli'));
contenuto.append(g);
}
- const avanzate = h('button', { class: 'pp-mini-btn', on: { click: () => mostra('avanzate') } }, '⚙ Avanzate');
- area.replaceChildren(h('div', { class: 'ec-titolo' }, h('h2', null, cat[2]), ...(id !== 'avanzate' && disponibili.some(([k]) => k === 'avanzate') ? [avanzate] : [])), ...(gruppi.length > 1 ? [scelte] : []), contenuto);
+ // «Avanzate» sta già nella colonna a sinistra: niente secondo pulsante uguale in alto
+ area.replaceChildren(h('div', { class: 'ec-titolo' }, h('h2', null, cat[2])), ...(gruppi.length > 1 ? [scelte] : []), contenuto);
apri(gruppi.find((g) => g.dataset.g === this.editorGruppo) ?? gruppi[0]);
};
for (const [id, ico, nome] of disponibili) nav.append(h('button', { type: 'button', 'data-sezione': id, on: { click: () => mostra(id) } }, h('span', { 'aria-hidden': 'true' }, ico), nome));
diff --git a/src/ui/mixer.ts b/src/ui/mixer.ts
index 3a95cff..bb6dd5d 100644
--- a/src/ui/mixer.ts
+++ b/src/ui/mixer.ts
@@ -146,7 +146,7 @@ export class Mixer {
const mf = h('input', { type: 'range', class: 'fader-v', min: 0, max: 150, step: 1, value: String(Math.round(banco.volumeMaster * 100)), orient: 'vertical' }) as HTMLInputElement;
const mv = h('span', { class: 'striscia-val' }, Math.round(banco.volumeMaster * 100) + '%');
mf.addEventListener('input', () => { banco.volumeMaster = Number(mf.value) / 100; mv.textContent = mf.value + '%'; banco.aggiornaTracce(store.doc); });
- strisce.push(h('div', { class: 'striscia master' }, h('b', { class: 'striscia-nome' }, 'ASCOLTO'), h('span', { class: 'striscia-tipo' }, 'CUFFIA'), h('div', { class: 'striscia-fader' }, mf), mv, h('div', { class: 'striscia-btn' })));
+ strisce.push(h('div', { class: 'striscia master' }, h('b', { class: 'striscia-nome' }, 'CUFFIA'), h('span', { class: 'striscia-tipo' }, 'ASCOLTO'), h('div', { class: 'striscia-fader' }, mf), mv, h('div', { class: 'striscia-btn' })));
this.el.replaceChildren(h('p', { class: 'nota' }, 'Doppio clic su un fader = torna a zero. I livelli video sono la trasparenza di tutta la traccia.'), h('div', { class: 'strisce' }, strisce));
}
diff --git a/src/ui/pulsantiera.ts b/src/ui/pulsantiera.ts
index 273e75e..a4ce257 100644
--- a/src/ui/pulsantiera.ts
+++ b/src/ui/pulsantiera.ts
@@ -11,7 +11,7 @@ export class Pulsantiera {
constructor(tl: Timeline) {
const tasto = (num: string, ic: string, nome: string, az: string, title: string, cls = '') =>
- h('button', { class: 'tasto-num ' + cls, title, on: { click: () => esegui(az) } }, h('span', { class: 'tasto-numero' }, num), icona(ic, 16), h('span', { class: 'nome' }, nome));
+ h('button', { class: 'tasto-num ' + cls, title, on: { click: () => esegui(az) } }, h('span', { class: 'tasto-numero' + (/\d/.test(num) ? '' : ' lettera') }, num), icona(ic, 16), h('span', { class: 'nome' }, nome));
const modo = (nome: string, az: string, on: () => boolean, title: string, ic?: string) => {
const el = h('button', { class: 'tasto-modo', title, on: { click: () => esegui(az) } }, h('span', { class: 'led' }), ic ? icona(ic, 14) : null, h('span', null, nome));
this.spie.push({ el, on });
diff --git a/src/ui/velocita.ts b/src/ui/velocita.ts
index 82fc975..254cdb0 100644
--- a/src/ui/velocita.ts
+++ b/src/ui/velocita.ts
@@ -74,7 +74,7 @@ export function finestraVelocita(ids?: Iterable) {
};
const preset = [0.1, 0.25, 0.5, 0.75, 1, 1.5, 2, 4, 8];
const bottoni = h('div', { class: 'vel-preset' }, preset.map((x) => h('button', { class: 'btn', title: `Velocità ${x * 100}%`, on: { click: () => { v = x; aggiorna(); } } },
- x === 1 ? '1×' : x < 1 ? '÷' + Math.round(1 / x * 100) / 100 : '×' + x)));
+ '×' + String(x).replace('.', ','))));
num.addEventListener('input', () => { const x = Number(num.value) / 100; if (x > 0) { v = x; aggiorna(); } });
cursore.addEventListener('input', () => { v = daCursore(Number(cursore.value)); aggiorna(); });
fluido.addEventListener('change', () => { fluidoTocco = true; });