# NM OS™ — GUIDA STUDIO
> Come registrare le lezioni senza slide, con le pagine scena dello Studio Engine.
> Cartella: `03-Studio-Lezioni/` · Motore: `_engine/studio.css` · `_engine/studio.js` · `_engine/links.js` · Home: `index.html`

---

## 1. Cos'è lo Studio

Ogni modulo del corso è **una pagina HTML** (`M00-…html` … `M10-…html`, `MBR-Brand-e-Contenuti.html`, `MCO-Coach-Quotidiano.html`, `CS-Case-Study.html`) fatta di **scene a schermo intero** (1920×1080). Michele apre la pagina a schermo intero, la registra con OBS/ScreenFlow, e avanza con la freccia destra. Niente Keynote, niente PowerPoint: il testo è vero HTML con il Design System NM OS (dark, neon lime, Unbounded/Inter/JetBrains Mono).

Cosa fa il motore da solo:
- **Scene** con transizione (fade / slide / scale), HUD con modulo, lezione, progresso, contatore `scena 7/28 · step 2/5`.
- **Build step-by-step**: le voci di `.steps`, i nodi del `.flow`/`.tree`, le righe `.term-line`, i blocchi `.tl` della timeline e qualsiasi elemento con `class="build"` appaiono uno alla volta con `→`.
- **Prompt** con header, evidenziazione dei segnaposto `[tra parentesi quadre]` e bottone **Copia**.
- **Terminale** che digita i comandi da solo e mostra l'output.
- **Contatori** (`.stat-num[data-count]`) che salgono, **typewriter** sui titoli, **checklist** spuntabili con click o tasti 1-9.
- **Note del presentatore** (overlay `N` o finestra separata `?notes=1` sincronizzata).
- **Griglia** di tutte le scene (`G`), **timer** di registrazione (`T`), **schermo nero** (`B`), **chroma verde** (`C`).
- **Link ai tool** da un registro unico (`data-link="claude"` → URL affiliato da `00-CEO/links.json`).

---

## 2. Tasti rapidi (completi)

| Tasto | Cosa fa |
|---|---|
| `→` `Spazio` `PgDn` `Invio` | Avanti: prima rivela il prossimo step della scena, poi passa alla scena successiva |
| `←` `PgUp` `Backspace` | Indietro: nasconde l'ultimo step, poi torna alla scena precedente (con tutti gli step già rivelati) |
| `Home` / `End` | Prima / ultima scena |
| `1`-`9` | Spunta/despunta la voce n della checklist della scena corrente |
| `F` | Schermo intero (Fullscreen API) |
| `N` | Overlay note del presentatore in basso (sulla stessa finestra: **non** usarlo mentre registri) |
| `P` | Apre la **finestra note** (`?notes=1`, 1280×800) da spostare sul 2° monitor |
| `G` | Griglia di tutte le scene con anteprima: click per saltare |
| `T` | Avvia/pausa il **timer REC** (in basso a sinistra) · `⇧T` azzera e riparte |
| `B` | Schermo nero (pausa, cambio scena in post) |
| `C` | Chroma verde `#00FF00` (per PiP o inserti in post) |
| `H` | Nasconde/mostra l'HUD (wordmark, contatore, timer) |
| `R` | Ripete l'animazione della scena corrente (utile per rifare una ripresa) |
| `L` | **Tema chiaro / scuro** (chiaro predefinito). Anche col bottone sole/luna nell'HUD in basso a destra e nella finestra note. Scelta salvata in `localStorage` (`nmos-theme`) e sincronizzata fra finestra principale e finestra note |
| `?` | Aiuto tasti · `Esc` chiude tutti gli overlay |
| click | Click sul 12 % sinistro dello schermo = indietro, altrove = avanti (touch: swipe) |

URL:
- `pagina.html#s=12` riprende dalla scena 12 (l'hash si aggiorna da solo mentre avanzi: puoi copiarlo per riprendere una registrazione).
- `pagina.html?notes=1` apre la **vista presentatore**.
- `pagina.html?theme=dark` (o `?theme=light`) forza il tema e lo salva come preferenza. Senza parametro: ultima scelta salvata, altrimenti **chiaro**. Terminali e prompt restano scuri in entrambi i temi (voluto). Schermo nero `B` e chroma `C` non cambiano.

API console (per debug): `Studio.goto(5)`, `Studio.next()`, `Studio.prev()`, `Studio.index`, `Studio.total`, `Studio.toggleGrid()`, `Studio.timerToggle()`, `Studio.openNotesWindow()`, `Studio.toggleTheme()`, `Studio.setTheme('dark'|'light')`, `Studio.theme`.

---

## 3. Setup di registrazione

### 3.1 Servire la cartella (consigliato)
Le pagine funzionano anche aprendo il file (`file://`), ma via **http** funzionano meglio: registro link letto da `00-CEO/links.json`, `?notes=1` sincronizzato via BroadcastChannel, conteggi scene nella Home.

```bash
cd "03-Studio-Lezioni"
python3 -m http.server 4320
# poi apri http://localhost:4320/index.html
```

### 3.2 Finestra 1920×1080
Le scene usano `vw`/`vh` e `clamp()`: si adattano, ma la scala tipografica è pensata per **1920×1080**. Due strade:
- **Schermo intero** su un monitor Full HD: premi `F`.
- **Finestra fissa** (se il monitor è 4K/5K o vuoi registrare una regione): apri Chrome, DevTools → `⌘⇧M` (device toolbar) → dimensione personalizzata `1920×1080`, zoom 100 %; oppure in OBS cattura la finestra e imposta il canvas a 1920×1080.

Consigli: Chrome o Edge (Chromium), zoom 100 % (`⌘0`), nascondi la barra dei preferiti, usa un **profilo Chrome "Studio"** senza estensioni, disattiva le notifiche macOS (Focus → Non disturbare).

### 3.3 OBS Studio
1. Scena "Studio": fonte **Cattura finestra** → la finestra Chrome della lezione (oppure **Cattura schermo** del monitor 1).
2. Impostazioni → Video: base 1920×1080, output 1920×1080, 30 fps (60 se vuoi le animazioni più fluide).
3. Output: registrazione `mkv` o `mov`, encoder Apple VT H.264 (o ProRes se hai spazio), bitrate 20-30 Mbps.
4. Audio: microfono su traccia 1, audio desktop **disattivato** (le pagine non hanno audio).
5. Facoltativo: scena "Demo" con **Cattura finestra** del browser dei tool (Claude, Railway…) e scena "Camera" per l'intro. Passa da una scena all'altra con gli hotkey OBS (evita `F`, `N`, `G`, `T`, `B`, `C`, `H`, `P`, `R` che sono già usati dallo Studio).
6. Il **timer REC** dello Studio (`T`) è indipendente da OBS: usalo per tenere i minuti della scaletta.

### 3.4 ScreenFlow / Descript
- ScreenFlow: registra **Schermo** (monitor 1) + microfono; nelle preferenze disattiva "mostra click del mouse" (il click avanza la scena e il cerchietto si vede).
- Descript: nuovo progetto → **Registra schermo** → seleziona la finestra Chrome. Descript trascrive: le note del presentatore (`.say`) sono già frasi pronte da dire.

### 3.5 Secondo monitor: vista presentatore (`?notes=1`)
1. Apri la lezione nella finestra principale (monitor 1, quella registrata).
2. Premi `P`: si apre la stessa pagina con `?notes=1` in una nuova finestra. Spostala sul monitor 2 (o su iPad con lo stesso browser via `http://<ip-del-mac>:4320/…?notes=1`, stessa rete: in quel caso la sincronizzazione usa `localStorage` e serve la stessa origine, quindi apri anche la principale dall'IP).
3. La vista note mostra: **scena corrente** (numero, step, titolo, anteprima), **cosa dire** (le `<aside class="notes">` della scena), **prossima scena**, **timer** e **orologio**.
4. Le frecce, `Spazio`, `Home`/`End`, `T` e `B` premuti nella finestra note **comandano la finestra principale** (BroadcastChannel + fallback `localStorage`).
5. Non usare `N` nella finestra registrata: le note compaiono a schermo.

Come funziona la sincronizzazione (per chi vuole estenderla): la pagina principale trasmette `{type:'state', index, frag, title, next, notes, timer}` sul canale `nmos-studio-<modulo>` e lo salva in `localStorage['nmos-studio-state-<modulo>']`; la vista note trasmette comandi `{type:'cmd', cmd:'next'|'prev'|'home'|'end'|'timer'|'black'}`.

---

## 4. Creare una nuova lezione dal template

1. **Duplica** `TEMPLATE-LEZIONE.html` → `M0X-Nome-Modulo.html` (stessa cartella, così `_engine/` resta relativo).
2. Imposta `<title>` e il `<main>`:
   ```html
   <main class="studio" data-module="M0X" data-phase="costruisci" data-title="Nome modulo">
   ```
   `data-phase`: `setup` · `valida` (cyan) · `costruisci` (lime) · `vendi` (orange) · `duplica` (violet) · `trasversale` (violet, etichetta CASE STUDY). Cambia il colore neon di tutta la pagina.
3. Ogni `<section class="scene …">` è una scena. Ordine nel file = ordine in registrazione. Attributi:
   - `data-lesson="M0X.L03"` e `data-lesson-title="…"` → mostrati nell'HUD e nella vista note.
   - `data-transition="slide|scale"` (default fade) · `class="center"` centra tutto · `class="top"` allinea in alto.
   - `data-title="…"` forza il titolo in griglia (altrimenti prende `.h1/.h2/.h3/.quote`).
4. In ogni scena metti `<aside class="notes">…</aside>` = note del presentatore. Usa `<span class="say">…</span>` per le frasi da dire testualmente e `<b>` per le parole chiave.
5. Aggiungi `class="build"` a qualsiasi elemento che deve apparire con `→`. Sono già "build" automatici: `.steps > li`, `.flow .node/.link`, `.tree .node/.vlink/.hbar`, `.terminal .term-line`, `.timeline .tl`. Per disattivare l'auto-build su un blocco: `data-build="none"` sul contenitore.
6. Struttura consigliata per modulo (≈ 22-30 scene): hero → mappa (steps) → per ogni lezione: title (slide) + 2-4 scene di contenuto (steps / diagram / prompt / terminal / demo / checklist / compliance) → compare eco vs completo → result.
7. Skin (facoltativa): `MBR` e `MCO` hanno nel `<head>`, dopo lo script del tema, anche lo script anti-flash della skin del portale (`nmos-skin` in `localStorage`, `?skin=gaming|essenziale`, gaming predefinita → attributo `data-skin` su `<html>`). Il motore non ha regole di skin: le due pagine le usano solo per i propri componenti locali (angoli tagliati), sempre con le variabili del tema.
8. Regole di scrittura: italiano, frasi corte, verbi. Mai "guadagna", "facile", "garantito", "sicuro" (fuori dalle colonne "Non dire"). Segnaposto nei prompt tra `[parentesi quadre]`. Numeri solo di **tempo, costo, volume**, mai di guadagno; ogni numero d'esempio con la riga `.stat-src` che lo dichiara.

### 4.1 Componenti (riferimento rapido)

| Componente | Markup minimo | Note |
|---|---|---|
| Titolo modulo | `.scene.scene-title.center.hero` + `.eyebrow` + `.h1[data-typewriter="40"]` + `.lead` + `.row > .pill` | Typewriter aggiunge il cursore da solo |
| Titolo lezione | `.scene.scene-title[data-transition="slide"]` + `.kicker > .num` + `.h1 + .cursor` + `.lead` | |
| Steps | `ol.steps > li` (+ `<small>`) · varianti `.compact`, `.two`, `.icons` (`data-icon`) | Ogni `li` è uno step |
| Cards | `.cards.c2/.c3/.c4 > .card` (+ `.card-k`, `.card-t`, `p`) · colori `.violet .red .cyan .orange` · `.glowing` | Non build (entrano con la scena); aggiungi `.build` se serve |
| Diagramma | `.flow > .node / .link` alternati · `.flow[data-dir="col"]` verticale · `.node.end` finale · colori `.violet .orange .cyan .red` · `.link.loop` | `.tree > .level > .node`, `.vlink`, `.hbar` per alberi |
| Prompt | `.prompt[data-label="…"] > pre` · `.small` compatto · `.build` per farlo apparire con `→` | Le `[parentesi]` diventano `.ph` lime; `<span class="pc">` per commenti |
| Checklist | `ul.checklist > li` · `.two`, `.compact` · `data-auto` si spunta da sola (scena risultato) | Tasti 1-9 |
| Compare | `table.compare` con `th.eco` / `th.pro`, `td.eco` / `td.pro`, `.cost`, `<small>` | Anche per tabelle generiche (th senza classe) |
| Demo | `.scene-demo.center` + `.demo-cta > .rec` + `.demo-steps > span` + `.tool-list > a.tool[data-link="…"]` + `p.disclosure[data-link-disclosure]` | Vedi 4.2 |
| Terminale | `.terminal[data-title] > .term-line[data-cmd] > .term-out` · `data-ps="❯"` · `.comment` · `data-speed` | Output: `.ok .warn .err .k .s .dim` |
| Stat | `.stats > .stat > .stat-num[data-count][data-prefix][data-suffix][data-duration]` + `.stat-lab` + `.stat-src` | Decimali dal valore (`4.4`) |
| Timeline | `.timeline > .tl[data-n="Giorno 1"] > b + p` | Ogni `.tl` è uno step |
| Quote | `.scene-quote.center > p.quote + .quote-by` | |
| Compliance | `.banner[data-level="warn|danger|ok"] > .b-icon + div(.b-k, .b-t, p, ul)` · `.no-yes > .col.no / .col.yes` | `.no-yes.build` per rivelarlo con `→` |
| Result | `.scene-result > .result-grid > div(.h2 + ul.checklist.compact[data-auto]) + .result-badge(.rb-num, .rb-lab)` | |
| Mock browser / phone | `.browser > .browser-bar(i,i,i,.url) + .browser-body` · `.apps > div > .phone > .screen(.app-h, .app-sub, .app-opt, .app-btn, .app-row, .app-num, .app-bar, .app-note)` + `.app-label` | |
| Layout | `.two-col` (`.equal`), `.stack`, `.row`, `.spacer`, `.max-70/.max-60/.max-50` | |

### 4.2 Link ai tool (`data-link`)
Nessun URL scritto a mano. Il registro è `00-CEO/links.json` (copia locale `_engine/links.json`, fallback embed `_engine/links.fallback.js` per `file://`).

```html
<a class="tool" data-link="railway"><span class="tool-n">03</span><span><span class="tool-name" data-fill="name"></span><span class="tool-what">deploy dal repo</span></span></a>
<span data-link-name="claude"></span>          <!-- nome del tool -->
<span data-link-plan="claude:eco"></span>      <!-- piano economico; "claude:pro" = completo -->
<p class="disclosure" data-link-disclosure></p><!-- nota affiliazione obbligatoria -->
```
Chiavi disponibili: `claude claude_code chatgpt github railway resend lovable higgsfield canva stripe shopify descript heygen capcut meta_ads google_ads google_trends ahrefs semrush similarweb twilio brevo notion airtable hubspot zoom skool ionos namecheap cloudflare elevenlabs nm_os_community nm_os_checkout bunny` (`ionos` = registrar consigliato per dominio + email professionale; `namecheap` resta nel registro solo come alternativa). Una chiave mancante mette `.link-missing` sull'elemento e un `title` con l'errore. Per aggiungere un tool: modifica `00-CEO/links.json` (e la copia `_engine/links.json`), non le pagine.

### 4.3 Aggiungere la pagina alla Home
In `index.html` duplica una `<a class="card">` nella griglia: `data-phase`, `data-file`, `data-scenes` (conteggio statico), `data-lessons`, titolo e descrizione. Via http la Home rilegge il numero di scene dalla pagina.

---

## 5. Esportare PNG delle scene (thumbnail, anteprime nel portale)

### 5.1 A mano (Chrome)
1. Apri la scena (`#s=N`), premi `H` per nascondere l'HUD e `End`/`→` finché tutti gli step sono visibili (o apri dalla griglia `G`: le scene aperte dalla griglia sono già "tutte rivelate").
2. DevTools → `⌘⇧P` → **Capture screenshot** (viewport) oppure **Capture full size screenshot**. Con il device toolbar a 1920×1080 il PNG è esattamente Full HD.

### 5.2 In serie (Playwright, opzionale)
```bash
npm i -D playwright && npx playwright install chromium
```
```js
// export-scenes.mjs — esporta tutte le scene di una pagina in PNG 1920x1080 (tutti gli step rivelati)
import { chromium } from 'playwright';
const [,, file='M10-Duplica.html', out='thumbs'] = process.argv;
const browser = await chromium.launch(); const page = await browser.newPage({ viewport:{ width:1920, height:1080 } });
await page.goto(`http://localhost:4320/${file}`); await page.waitForTimeout(1500);
const total = await page.evaluate(() => Studio.total);
await page.keyboard.press('h');                                   // HUD off
for (let i = 1; i <= total; i++) {
  await page.evaluate(n => Studio.goto(n), i);                    // vai alla scena i (step nascosti)
  const steps = await page.evaluate(n => Studio.scenes[n-1]._frags.length, i);
  for (let k = 0; k < steps; k++) await page.evaluate(() => Studio.next()); // rivela ogni step senza cambiare scena
  await page.waitForTimeout(1200);                                // animazioni, contatori, terminale
  await page.screenshot({ path: `${out}/${file.replace('.html','')}-${String(i).padStart(2,'0')}.png` });
}
await browser.close();
```
```
Esegui con `node export-scenes.mjs M10-Duplica.html thumbs` (cartella `thumbs/` creata prima, server http attivo). `Studio.next()` rivela gli step uno alla volta e passa alla scena dopo solo quando sono finiti: per questo il ciclo si ferma a `_frags.length`.

Suggerimento per il portale: la thumbnail della lezione è la **scena title** (hero o kicker) senza HUD; la copertina del modulo è la scena 1.

---

## 6. Checklist pre-registrazione

- [ ] `python3 -m http.server 4320` attivo e pagina aperta da `http://localhost:4320/…`
- [ ] Chrome profilo "Studio", zoom 100 %, nessuna estensione, notifiche macOS disattivate
- [ ] `F` schermo intero (o finestra 1920×1080) · canvas OBS 1920×1080 · fonte corretta selezionata
- [ ] `?notes=1` aperto sul 2° monitor (`P`) e sincronizzato: premi `→` lì e la principale avanza
- [ ] I bottoni della scena demo aprono i tool (registro caricato: il nome compare, non è vuoto). Se compare `.link-missing`, controlla la chiave in `links.json`
- [ ] Prompt: bottone **Copia** funziona (via http è `navigator.clipboard`; via `file://` usa il fallback)
- [ ] `G`: scorri la griglia, controlla che nessuna scena sia tagliata (testo troppo lungo → riduci o `.compact`)
- [ ] `Home`, poi `T` quando parte la registrazione · `H` se non vuoi l'HUD nel video
- [ ] Microfono su traccia separata · audio desktop spento
- [ ] Ultima scena = result: le voci si spuntano da sole (`data-auto`), lascia 4-5 secondi
- [ ] A fine ripresa: `⇧T` azzera il timer, `#s=1` per la prossima lezione

Ritmo consigliato: 1 scena ≈ 40-90 secondi; scena prompt ≈ 2 minuti (leggi, commenta i 3 blocchi, Copia); scena demo = switch alla scena OBS "Demo" e torna allo Studio per la checklist.

---

## 7. Troubleshooting

| Problema | Causa probabile | Rimedio |
|---|---|---|
| Nomi dei tool vuoti nella scena demo | Registro non caricato (`file://` senza fallback, o `links.json` non trovato) | Servi via http; verifica che esista `../../00-CEO/links.json` rispetto a `_engine/` o la copia `_engine/links.json`; console: `NMOS_LINKS` |
| La finestra note non si aggiorna | Origine diversa (es. principale su `localhost`, note su `127.0.0.1`), o browser diverso | Apri entrambe dallo **stesso** host e browser; la sync usa BroadcastChannel e `localStorage` della stessa origine |
| `→` non avanza | Focus in un input/textarea, o overlay aperto (griglia/help) | `Esc`, poi click sulla scena |
| Le note compaiono nel video | Hai premuto `N` nella finestra registrata | `N` di nuovo o `Esc`; usa `P` per la finestra separata |
| Font "sbagliati" (system-ui) | Google Fonts bloccato / offline | Serve connessione la prima volta; poi la cache basta. In alternativa scarica i font e cambia l'`@import` in `studio.css` |
| Testo tagliato in basso | Scena troppo piena | Usa `.steps.compact`, `.prompt.small`, `.checklist.two`, oppure dividi in due scene |
| Contatore `stat-num` mostra decimali strani | `data-count="4,4"` con la virgola | Usa il punto: `data-count="4.4"` (la virgola la mette il formato it-IT) |
| La griglia `G` mostra anteprime vuote | Le anteprime si costruiscono al primo `G` e alla resize | Premi `G` due volte; dopo un resize si ricostruisce |
| Copia prompt non funziona | `navigator.clipboard` richiede https/localhost | Su `file://` scatta il fallback `execCommand`; se fallisce, seleziona il testo a mano |
| Il click avanza per sbaglio durante la demo | Click sulla pagina studio invece che sul browser dei tool | In OBS passa alla scena "Demo"; oppure premi `B` (nero) mentre lavori sull'altro schermo |
| Scena `#s=` non riparte dall'inizio degli step | Da hash si arriva senza step rivelati (per costruire dal vivo) | È voluto; per vederla completa apri dalla griglia `G` |
| Timer non visibile | Non ancora avviato | `T` la prima volta lo mostra e lo avvia |

---

## 8. File della cartella

| File | Cosa |
|---|---|
| `index.html` | Studio Home: griglia di tutte le pagine, badge fase, conteggio scene, tasti, link a questa guida |
| `M00-Sistema-Operativo.html` … `M10-Duplica.html` | Una pagina per modulo (M02 e M08 in produzione da un altro team) |
| `MBR-Brand-e-Contenuti.html` | Sessione S15 «Chi sei online»: BR.L01-BR.L06, 30 scene, prompt P171-P181 |
| `MCO-Coach-Quotidiano.html` | Sessione S18 «Il tuo assistente quotidiano»: CO.L01-CO.L06, 30 scene, prompt P182-P193 |
| `CS-Case-Study.html` | Case Study AromaVita + FitMeal end-to-end, 4 fasi |
| `TEMPLATE-LEZIONE.html` | Template con tutti i tipi di scena e le istruzioni nei commenti |
| `_engine/studio.css` | Design System (tema chiaro predefinito su `:root`, scuro sotto `:root[data-theme="dark"]`) + componenti + HUD + overlay + vista note |
| `_engine/studio.js` | Motore: navigazione, build, prompt, terminale, contatori, griglia, timer, sync note, tema chiaro/scuro (tasto `L`) |
| `_engine/links.js` · `links.json` · `links.fallback.js` | Registro link tool (affiliazione) |
| `GUIDA-STUDIO.md` | Questa guida |

Regole di compliance (valgono anche per lo Studio): mai promesse di guadagno, mai claim medici, disclaimer standard nella scena finale di ogni modulo e vicino a ogni numero d'esempio, disclosure affiliazione in ogni scena demo (`data-link-disclosure`).
