# Gli asset UI del Mac, e cosa significano

Questa cartella non contiene arte nuova. Contiene **le stesse identiche immagini**
che l'app macOS disegna a schermo, copiate byte per byte dal repo Mac, più la mappa
che dice a chi appartengono e come vanno montate. È la conseguenza diretta del
`PORTING-PLAN.md` §4-bis: l'interfaccia Windows non è "ispirata" a quella Mac, è
**la stessa** — e un'icona ridisegnata a mano, per quanto simile, sarebbe già una
divergenza.

⛔ **Il repo macOS è di sola lettura.** Gli asset qui sotto sono stati COPIATI da
`/Users/leo/svgeditor` (commit di riferimento in `VENDOR.md`); nulla è stato scritto
lì. Quando il Mac ridisegna un'icona, si ricopia — non si ridisegna qui.

| | |
|---|---|
| Repo sorgente | `github.com/Bloophub/svgeditor` (checkout locale `~/svgeditor`) |
| Data dell'estrazione | 2026-08-30 |
| File copiati | **74** icone toolbox · **222** cursori (221 base + `rotate.png`) · **117** cursori 8× · 1 inventario CSV |

---

## 1. La toolbox

### 1.1 Geometria, letta dal codice

Tutti i numeri vengono da `SVGEditorMac/SVG Editor Mac/GUI/SUI/Panel/SVGToolPanelSUIView.swift`,
struct `SVGToolPanelContentSUIView` (riga 2480):

| Grandezza | Valore | Provenienza |
|---|---|---|
| Colonne | **2** (griglia fissa, mai adattiva) | `columns` — `GridItem(.fixed(cell))` ×2, riga 2500 |
| Lato della cella | **32 pt** | `private let cell: CGFloat = 32`, riga 2499 |
| Spaziatura fra colonne | **1 pt** | `GridItem(…, spacing: 1)`, riga 2501 |
| Spaziatura fra righe | **1 pt** | `LazyVGrid(columns:, spacing: 1)`, riga 2507 |
| Padding attorno alla griglia | **1 pt** per lato | `.padding(1)`, riga 2622 |
| **Larghezza totale della griglia** | **67 pt** = 32×2 + 1 + 2 | `grid_width`, riga 2504 |
| Righe | **12** (24 strumenti ÷ 2) | `get_mac_tool_list()` |
| Altezza della griglia | **397 pt** = 12×32 + 11×1 + 2 | derivata dai valori sopra |
| Glifo dell'icona | **16 × 16 pt**, `interpolation(.none)` | `tool_icon`, righe 2637-2645 |
| Glifo di ripiego (SF Symbol) | **15 × 15 pt**, `renderingMode(.template)` | `tool_icon`, righe 2649-2654 |
| Evidenziazione dello strumento attivo | `RoundedRectangle(cornerRadius: 4)` riempito con l'accent color al **25 %** di opacità | riga 2552-2554 |
| Marcatore di flyout | triangolo **5 × 5 pt** in basso a destra, padding 2 pt; accent color se il gruppo è attivo, altrimenti colore secondario | `SVGEFlyoutMarker`, righe 2706-2716; uso alle righe 2811-2814 (penna) e 2932-2935 (testo) |
| Soglia del long-press che apre il flyout | **0,35 s** | `LongPressGesture(minimumDuration: 0.35)`, righe 2821 e 2942 |

Sotto la griglia, nello stesso pannello (`SVGEToolsPaletteRoot.tools_body`, riga 2444):
`VStack(spacing: 6)` → griglia → `Divider().frame(width: 56)` (riga 2451) → il proxy
riempimento/traccia `SVGEFillStrokeView` (riga 7668). **Non c'è la scritta col nome
dello strumento**: è stata rimossa (commento alle righe 2449-2450, richiesta #631).

La palette "Tools" è **senza titolo e senza menu ≡▾** (`chromeless_title_palettes`,
riga 1128) e il suo contenuto riceve **zero padding** in larghezza (riga 1426), così
la finestra aderisce esattamente ai 67 pt della griglia.

⚠️ **Invariante da non rompere.** La lista degli strumenti deve restare di lunghezza
**pari**: essendo letta come coppie di righe, un numero dispari lascia l'ultima cella
vuota — e una cella vuota è un buco che non espone alcun pulsante all'accessibilità
(`mac_tool_list_is_paired`, `SVGEEnumManager.swift:209`; asserzione a
`SVGToolPanelSUIView.swift:2490`). Gli strumenti si aggiungono **a coppie**.

### 1.2 L'ordine reale dei 24 slot

Fonte dell'ordine: `Utility/SVGEEnumManager.swift:168` (`get_mac_tool_list()`).
Fonte dei nomi file: `get_tool_custom_image_name()`, riga 330.
Fonte delle scorciatoie: `get_tool_shortcut()`, riga 511, incrociata con
`SkiaBridge/SVGESkiaView.mm:17396-17424` (gli alias del fork gestiti in `keyDown`)
e `Reference/gpu-window-keymap.md` §3d.

Le scorciatoie sono **lettere nude, senza modificatori**: la traduzione a Windows è
l'identità (nessun ⌘ da girare in Ctrl). L'unico caso da guardare è `\`.

| Riga | Col | Tool id (rawValue) | Nome | Icona (`toolbox/`) | Tasto Mac | Tasto Windows | Alias (fork, `keyDown`) |
|---:|---:|---|---|---|:---:|:---:|---|
| 1 | 1 | `select` | Selection | `ai_tool_selection.png` | `V` | `V` | `1` |
| 1 | 2 | `directselect` | Direct Selection | `ai_tool_direct_select.png` | `A` | `A` | — |
| 2 | 1 | `path` | Path (Pen) — **flyout** | `ai_tool_path.png` | `P` | `P` | `6` |
| 2 | 2 | `fhpath` | Free Hand (Pencil) | `ai_tool_fhpath.png` | — | — | `Y`, `Q`, `2` |
| 3 | 1 | `spray` | Spray | `ai_tool_spray.png` | `B` | `B` | — |
| 3 | 2 | `eraser` | Eraser | `ai_tool_eraser.png` | — | — | — |
| 4 | 1 | `line` | Line | `ai_tool_line.png` | `\` | `\` ⚠️ | `3` |
| 4 | 2 | `rect` | Rect | `ai_tool_rect.png` | `M` | `M` | `R`, `4` |
| 5 | 1 | `ellipse` | Ellipse | `ai_tool_ellipse.png` | `L` | `L` | `N`, `O`, `5` |
| 5 | 2 | `roundedrect` | Rounded Rect | `ai_tool_rounded_rect.png` | — | — | — |
| 6 | 1 | `polygon` | Polygon | `ai_tool_polygon.png` | `G` | `G` | — |
| 6 | 2 | `star` | Star | `ai_tool_star.png` | `S` | `S` | — |
| 7 | 1 | `text` | Text — **flyout** | `ai_tool_text.png` | `T` | `T` | `7` |
| 7 | 2 | `textpencil` | Text Pencil | **manca** → SF Symbol `signature` | — | — | — |
| 8 | 1 | `eyedropper` | Eyedropper | `ai_tool_eyedropper.png` | `I` | `I` | `E`, `9` |
| 8 | 2 | `scissor` | Scissors | `ai_tool_scissor.png` | `C` | `C` | — |
| 9 | 1 | `measure` | Measure | `ai_tool_measure.png` | — | — | — |
| 9 | 2 | `gradienttool` | Gradient | `ai_tool_gradient.png` | — | — | — |
| 10 | 1 | `xrotate` | Rotate | `ai_tool_rotate.png` | — | — | — |
| 10 | 2 | `xscale` | Scale | `ai_tool_scale.png` | — | — | — |
| 11 | 1 | `xreflect` | Reflect | `ai_tool_reflect.png` | — | — | — |
| 11 | 2 | `xshear` | Shear | `ai_tool_shear.png` | — | — | — |
| 12 | 1 | `xhand` | Hand | `ai_tool_hand.png` | `H` | `H` | — |
| 12 | 2 | `zoom` | Zoom | `ai_tool_zoom.png` | `Z` | `Z` | `8` |

⚠️ **Il tasto `\`** (Line). Sulle tastiere italiane e tedesche il backslash non ha un
tasto proprio: si ottiene con `AltGr`+`<` (IT) o `AltGr`+`ß` (DE). Un handler che
confronta il *virtual key code* (`VK_OEM_5`) prende il tasto sbagliato su quei layout.
Va confrontato il **carattere prodotto** (`WM_CHAR` = `\`), non il codice fisico —
esattamente come fa il Mac, che confronta `[ch isEqualToString:@"\\"]`
(`SVGESkiaView.mm:17405`).

⚠️ **Le cifre `1`–`9`** non sono l'ordine della toolbox di oggi: sono l'ordine storico
del fork (`select, fhpath, line, rect, ellipse, path, text, zoom, eyedropper`,
`SVGESkiaView.mm:17416-17424`). Vanno copiate così com'è, non ricalcolate.

⚠️ **Nessuna di queste lettere porta modificatori**, quindi nessuna collide con le
scorciatoie Ctrl+… di Windows. Vanno però **inibite mentre un campo di testo ha il
fuoco** (il Mac lo fa con la guardia `_textEdit` in `keyDown`, `SVGESkiaView.mm:17157`).

### 1.3 I flyout (long-press sullo slot)

Due slot su ventiquattro sono flyout. Il comportamento, identico per entrambi
(`SVGEPenToolSlot` riga 2783, `SVGETextToolSlot` riga 2891):

- **click breve** → attiva il sotto-strumento *rappresentato* (l'ultimo scelto);
- **long-press 0,35 s** → apre una striscia ORIZZONTALE di icone, celle da 32 pt con
  spacing 1 pt, padding 4 pt, ancorata al bordo **destro** dello slot
  (`arrowEdge: .trailing`);
- lo slot mostra sempre la faccia dell'ultimo sotto-strumento scelto, e quella scelta
  **sopravvive al riavvio** (`@AppStorage("SVGEPenSlotSubTool")` riga 2790 e
  `@AppStorage("SVGETextSlotSubTool")` riga 2895);
- la striscia si chiude sia con un click pulito su un'icona sia con un
  **press-drag-release** partito dallo slot (il Mac ha dovuto aggiungere
  `SVGEFlyoutDragCatcher`, riga 2727, perché il popover non riceve il rilascio di un
  drag già in corso: su Windows lo stesso problema si presenta con una finestra
  popup, e la soluzione è la stessa — catturare il mouse e decidere in base alla x
  del rilascio, `strip_step = cell + 1`, riga 2907).

**Flyout della penna** — 4 voci, in quest'ordine (riga 2794):

| # | Tool id | Nome | Icona |
|---:|---|---|---|
| 1 | `path` | Path | `ai_tool_path.png` |
| 2 | `addanchor` | Add Anchor | `ai_tool_add_anchor.png` |
| 3 | `delanchor` | Delete Anchor | `ai_tool_del_anchor.png` |
| 4 | `convertanchor` | Convert Anchor | `ai_tool_convert_anchor.png` |

**Flyout del testo** — 3 voci, in quest'ordine (riga 2901):

| # | Tool id | Nome | Icona |
|---:|---|---|---|
| 1 | `text` | Text | `ai_tool_text.png` |
| 2 | `textpath` | Type on Path | `ai_tool_text_path.png` |
| 3 | `textparagraph` | Area Type | `ai_tool_text_paragraph.png` |

`textparagraphskia` (Skia Paragraph) **non è nel flyout**: era la quarta voce ed è
stata tolta dalla produzione (SVGE-1720, commento alle righe 2897-2900). Il tool esiste ancora
nel codice. Non va replicata nella toolbox Windows.

### 1.4 Doppio click: ogni slot ne ha uno

Non è un dettaglio cosmetico — è il modo classico di Illustrator per aprire le opzioni
di uno strumento, ed è cablato slot per slot (`SVGToolPanelSUIView.swift:2565-2606`):

| Slot | Doppio click |
|---|---|
| `select`, `directselect` | dialogo **Move** |
| `xrotate`, `xscale`, `xshear`, `xreflect` | dialogo numerico della trasformazione, con Preview e pivot |
| `zoom` | zoom al **100 %** |
| `xhand` | **fit** nella finestra |
| `rect`, `ellipse`, `roundedrect`, `polygon`, `star` | dialogo numerico della forma, creata al centro dell'artboard |
| `fhpath` | mostra/nasconde la palette **Brushes** |
| `spray`, `eraser` | popover con il **diametro** del pennello (`SVGEBrushSizeToolSlot`, riga 2532) |
| `eyedropper` | popover **Eyedropper Options** (`SVGEEyedropperToolSlot`, riga 2540) |
| `textpencil` | opzioni del Text Pencil — frase, font, avanzamento (`SVGETextPencilToolSlot`, riga 2524) |

### 1.5 Cosa c'è in `toolbox/`, e cosa manca

74 file = 37 imageset × 2 varianti (`@1x` 16×16 px e `@2x` 32×32 px). Sono PNG di
**pixel-art nera su trasparente**, disegnati per essere mostrati **senza
interpolazione**: la variante `@2x` si usa a 200 % di DPI, la `@1x` a 100 %.
Ogni imageset del Mac dichiara `"template-rendering-intent": "original"` — cioè
**nessuna tinta**, i pixel vanno a schermo come sono.

⚠️ **Modo scuro.** Essendo arte nera senza variante scura, il Mac le **inverte**
(nero → bianco) quando il sistema è in Dark mode, e solo allora
(`SVGEDarkGlyph`, riga 2675). Windows deve fare lo stesso, non caricare un secondo set.

**Le due icone che il Mac non ha** (e che quindi non abbiamo copiato, perché non
esistono — non perché siano sfuggite):

| Slot riservato | Stato sul Mac | Cosa disegna oggi |
|---|---|---|
| `ai_tool_text_pencil` | **mai disegnata** (SVGE-1156) | SF Symbol **`signature`**, peso `.regular`, 15×15 pt, tinta `Color.primary` — `SVGEEnumManager.swift:257-258` |
| `ai_tool_text_paragraph_skia` | **mai disegnata** (SVGE-1314) | SF Symbol **`text.justify`**, stesse regole — `SVGEEnumManager.swift:253-254`. Irrilevante per la toolbox: il tool non è più nel flyout |

Un SF Symbol è un font di sistema Apple: **non è ridistribuibile e non esiste su
Windows**. Le due icone vanno **ridisegnate identiche** (`signature` = uno scarabocchio
di firma; `text.justify` = quattro righe di testo giustificate) in pixel-art nera
16×16 / 32×32, coerente con le altre 23. Finché non ci sono, lo slot Text Pencil resti
**visibile e disabilitato**, mai omesso — la lista deve restare pari (§1.1).

**Nove icone in più**, copiate ma **non usate da nessun codice del Mac** (verificato:
zero riferimenti fuori dal catalogo). Vengono dall'estrazione di Illustrator 7 e sono
qui perché servono agli strumenti che il piano prevede più avanti:

`ai_tool_blend` · `ai_tool_direct_group_select` · `ai_tool_fill_stroke` ·
`ai_tool_graph` · `ai_tool_group_select` · `ai_tool_lasso` · `ai_tool_mesh` ·
`ai_tool_no_color` · `ai_tool_paintbrush`

⚠️ In particolare `ai_tool_fill_stroke` e `ai_tool_no_color` **non** sono il proxy
riempimento/traccia sotto la griglia: quel widget è **disegnato in codice**, non da un
bitmap (`SVGEFillStrokeView`, riga 7668 — due cerchi da 26×26 pt sfalsati di ∓6 pt,
il riempimento pieno in alto a sinistra, la traccia come anello con centro trasparente
e bordo da 5 pt, la barretta rossa per "nessun colore", il "?" per selezione mista, la
"T" contornata mentre si edita testo). Va riscritto, non ricopiato.

---

## 2. I cursori

### 2.1 Cosa c'è nella cartella

| Cartella / file | Contenuto |
|---|---|
| `cursors/*.png` | **221 file**, copiati verbatim da `Method-Draw-master/drawmac/images/ai-cursors/` — tutti **16 × 16 px** |
| `cursors/rotate.png` | 24 × 24 px, da `Method-Draw-master/drawmac/images/rotate.png` — il cursore dell'anello di rotazione, hotspot 12,12 |
| `cursors/8x/*.png` | **117 file**, 128 × 128 px, da `~/svgeditor/extracted_icons/adobe-illustrator-7.0.1/png/cursors-8x/` — la stessa arte a risoluzione 8× |
| `cursors/inventory.csv` | copia integrale di `Reference/ai-cursors-inventory.csv` (222 righe di dati) |
| `cursors/native-cursor-map.csv` | **nuovo**: la matrice tool→cursore del canvas NATIVO, estratta da `SVGESkiaView.mm` |

I 221 PNG hanno due famiglie di nomi: **104** `ai_cursor_*` (gli slot semantici che il
codice nomina) e **117** `CURS_id_pNNNNN_*` (i nomi originali delle risorse `CURS` di
Illustrator 7.0.1, più due `crsr_*` a colori). Non sono duplicati l'uno dell'altro: gli
`ai_cursor_*` sono gli slot **cablati**, i `CURS_id_*` il magazzino da cui pescano.

### 2.2 Quale mappa usare

Ce ne sono **due**, e per Windows conta la seconda.

**`inventory.csv`** è il censimento completo dell'arte: 222 righe, una per file, con
`tool`, `contesto_stato`, `selettore_css`, `hotspot_x/y`, `wired` (69 sì, 153 no),
l'id `CURS` originale, la categoria e il ruolo canonico. Serve a sapere *cosa esiste* e
*a cosa somiglia*. Gli hotspot sono quelli della matrice CSS del build con WebView.

**`native-cursor-map.csv`** è quello da implementare: la matrice del canvas **senza
WebView** — cioè esattamente l'architettura di Windows — estratta da
`SkiaBridge/SVGESkiaView.mm` §17 (`desiredCursorAtView:flags:`, riga 5513). 61 righe:
per ogni `tool` × `stato` dà il **file**, l'**hotspot** e il cursore di sistema di
ripiego, con Mac e Windows affiancati e il `file:riga` di provenienza.

Il montaggio su Windows è diretto: `CreateIconIndirect` con `ICONINFO.fIcon = FALSE` e
`xHotspot`/`yHotspot` presi dalle colonne `hotspot_x`/`hotspot_y`. L'origine è
**l'angolo in alto a sinistra** in entrambi i sistemi, quindi gli hotspot si copiano
senza conversione. Un file mancante deve degradare al `fallback_win` della riga, mai
alla freccia di default silenziosamente.

### 2.3 Gli hotspot, per famiglia

Non sono arbitrari: seguono poche convenzioni per famiglia, tutte già nel CSV.

| Famiglia | Hotspot | Perché |
|---|:---:|---|
| Frecce di selezione (`select`, `directselect`, e le loro varianti ⇧/⌥), `edit_anchor` | **1, 1** | la punta della freccia |
| Penna e ancore (`path`, `pen_add`, `pen_delete`, `pen_close`) | **7, 0** | la punta del pennino, sul bordo superiore |
| Forme e trasformazioni (`line`, `rect`, `ellipse`, `polygon`, `star`, `rounded_rect`, `measure`, `zoom_in/out`, `rotate`, `scale`, `reflect`, `shear`) | **6, 6** | il centro del mirino |
| Testo (`text`, `text_option`, `text_horizontal_on_path`, `text_horizontal_in_rect`, `text_shift_in_path`) | **7, 11** | la base della barra dell'I-beam |
| Contagocce (`eyedropper`, `eyedropper_full`) | **0, 15** | la punta della pipetta, angolo in basso a sinistra |
| Matita (`pencil`) | **0, 14** / gomma **0, 13** | la punta |
| Mano (`hand`, `fist`) | **8, 9** | il centro del palmo |
| Anello di rotazione (`rotate.png`, 24×24) | **12, 12** | il centro |

### 2.4 I tre cursori che non sono un file

Vanno **disegnati a runtime**, come fa il Mac:

1. **Anello del pennello** (Spray, Eraser) — un cerchio il cui diametro è la larghezza
   REALE del pennello allo zoom corrente, così il puntatore mostra quanto coprirà il
   tratto. Ricetta esatta (`svge_brush_ring_cursor`, `SVGESkiaView.mm:1697`): bitmap
   quadrato di lato `ceil(d)+4`, anello bianco al 92 % di opacità con tratto 2,5,
   sopra un anello nero all'85 % con tratto 1,0, hotspot al centro. Si mette in cache
   per diametro intero (un mousemove non deve ricostruire un bitmap). Diametro
   sotto-pixel o oltre 124 pt → si ripiega sul mirino, **mai su un anello troncato**.
2. **Doppia freccia di duplicazione** (⌥-drag che lascia una copia) — sul Mac cerca
   prima `ai_cursor_select_duplicate.png` (**non esiste**, è un gancio di sostituzione
   senza modifiche al codice), poi `ai_cursor_arrow_copy.png` (**c'è**, hotspot 1,1),
   e solo come ultima spiaggia disegna due frecce sovrapposte
   (`svge_duplicate_drag_cursor`, riga 1732). Su Windows: usare
   `ai_cursor_arrow_copy.png`.
3. **Cursori di ridimensionamento diagonali** — il Mac deve pescarli da un'API privata
   (`_windowResizeNorthWestSouthEastCursor`, riga 1668) perché AppKit non li espone.
   Windows li ha pubblici: `IDC_SIZENWSE` e `IDC_SIZENESW`. Qui il porting è più
   semplice dell'originale.

⚠️ **Deviazione già dichiarata sul Mac, da mantenere**: i cursori delle maniglie di
resize **non ruotano** con l'oggetto (la gabbia nativa è allineata agli assi), a
differenza del fork JS (`svge_resize_grip_cursor`, riga 1683). Windows si comporta come
il Mac nativo.

### 2.5 Cosa manca

| File | Situazione |
|---|---|
| `ai_cursor_select_duplicate.png` | **non esiste sul Mac.** È volutamente un gancio: se un giorno Leo fornisce l'icona finale, basta metterla nella cartella e vince da sola. Fino ad allora il cursore di duplicazione è `ai_cursor_arrow_copy.png` |
| `ai_cursor_shapelib.png` | **riga 49 dell'inventario senza file corrispondente.** È lo slot della "shape library" di Method Draw, uno strumento che **non è nella toolbox** (`get_mac_tool_list` non lo contiene): la riga è un residuo del censimento. Nessuna azione |

Nessun altro dei 221 file citati dal codice manca: verificato uno per uno contro la
matrice nativa.

### 2.6 Alta risoluzione

I cursori base sono 16×16 px, pensati per il 100 % di DPI. A 150 % / 200 % Windows
scala i cursori di sistema ma **non** quelli custom, che vanno forniti già alla
dimensione giusta. La cartella `8x/` contiene la stessa arte a 128×128 px: da lì si
ricavano per riduzione a numeri interi le taglie 32 (200 %) e 48 (300 %), che è una
scalatura **esatta** (128 = 4×32 = 8×16) e quindi conserva la pixel-art senza
sfocarla. Gli hotspot vanno moltiplicati per lo stesso fattore.

⚠️ I nomi in `8x/` seguono lo schema `CURS_id_pNNNNN_*_8x.png`: non c'è una copia 8×
per gli slot `ai_cursor_*`. La corrispondenza `ai_cursor_*` → `CURS_id_*` sta nelle
colonne `curs_id` / `curs_name` di `inventory.csv` — è quella la chiave di join.

---

## 3. Le palette: nessun asset, solo SF Symbols

Le icone della toolbox sono file (§1). Quelle dentro le **palette** no: il Mac le
prende dagli **SF Symbols**, cioè da un font di sistema Apple che **non è
ridistribuibile e su Windows non esiste**. Non c'è quindi niente da copiare in
questa cartella — vanno **ridisegnate identiche**, alla stessa taglia e con lo
stesso peso, come già deciso per `signature` e `text.justify` (§1.5). Qui si
tiene il conto di quali sono, palette per palette: così la prossima slice sa che
cosa deve disegnare, e nessuno va a cercare un PNG che non esiste.

### 3.1 Layers (P3/5, `win/ui_layers_palette.cpp`)

| SF Symbol | Dove | Taglia / peso | Riga del Mac |
|---|---|---|---|
| `eye.fill` | occhio di un layer visibile | 10 pt, `.primary` | SVGToolPanelSUIView.swift:8474 |
| `eye.slash` | occhio di un layer nascosto | 10 pt, `.secondary` al 50 % | :8474 + :8478 (SVGE-1104) |
| `lock.fill` | lucchetto chiuso | 9 pt, `.primary` | :8484 |
| `lock.open` | lucchetto aperto | 9 pt, `.secondary` | :8484 |
| `chevron.right` | apertura dell'albero oggetti | 8 pt **bold**, ruotato di 90° da aperto | :8494 |
| `plus` | footer, nuovo layer | glifo in cella 22×22 | :8721 |
| `trash` | footer, elimina | glifo in cella 22×22 | :8726 |
| `arrow.up` | footer, alza | glifo in cella 22×22 | :8738 |
| `arrow.down` | footer, abbassa | glifo in cella 22×22 | :8744 |

Non sono SF Symbols — e infatti sono disegnati in codice anche sul Mac — il
**chip di anteprima** 26×20 (`SVGELayerThumbView`, :8241), il **pallino** e il
**quadratino** del colore del layer (:8447 e :8506) e il **cerchio bersaglio**
`SVGETargetCircleView` (:8285).

### 3.2 Swatches (P3/6, `win/ui_swatches_palette.cpp`)

Le righe sono di `GUI/SUI/Panel/SVGESwatchesPalette.swift`.

| SF Symbol | Dove | Taglia / peso | Riga del Mac |
|---|---|---|---|
| `plus` | footer, nuovo campione | taglia del corpo (13 pt), cella 22×22 | :1700 |
| `trash` | footer, elimina | taglia del corpo, cella 22×22 | :1703 |
| `pencil` | footer, Swatch Options… (grigia, nota 1 dell'header) | taglia del corpo, cella 22×22 | :1708 |
| `magnifyingglass` | riga Find, a sinistra del campo | 10 pt, `.secondary` | :1627 |
| `xmark.circle.fill` | riga Find, bottone "Clear" | 10 pt, `.secondary` | :1635 |

Non sono SF Symbols — sono percorsi vettoriali disegnati a mano anche sul Mac,
e qui hanno le stesse coordinate:

| Disegno | Geometria | Riga del Mac |
|---|---|---|
| chip del campione | rettangolo raggio 2, bordo `primary` 35 % spesso 0,5 | :2254, :2326-2328 |
| diagonale di `[None]` | da (1, s−1) a (s−1, 1), **rossa** spessa 1,5 | :2303-2308 |
| triangolino della tinta | angolo basso-destra, lato `s × 0,4`, bianco pieno + ipotenusa `primary` 45 % spessa 0,5 | :2310-2324 |
| rombo CMYK | quattro triangoli che si toccano al centro: #00AEEF, #EC008C, #FFF200, nero; quadrato 11 col bordo `primary` 40 % | :2344-2349 |
| strisce RGB | tre bande uguali #FF0000, #00A651, #0000FF | :2353-2357 |
| icona `[None]` | quadrato bianco + diagonale rossa spessa 1,2 | :2360-2367 |

Il **segmentato Fill/Stroke** (:1589) e il **menu a tendina del Tint** (:1600)
sono controlli di sistema su macOS: qui sono ridisegnati in Skia (rettangoli
raggio 5, il segmento attivo in accent, le due frecce del picker), perché un
`NSSegmentedControl` non esiste su Windows e un controllo nativo Win32 non
sarebbe mai identico (PORTING-PLAN §4-bis).

### 3.3 Stroke (P3/7, `win/ui_stroke_palette.cpp`)

Le righe sono di `GUI/SUI/Panel/SVGToolPanelSUIView.swift`.

| SF Symbol | Dove | Taglia / peso | Riga del Mac |
|---|---|---|---|
| `arrowtriangle.up.fill` | ▲ della colonnina dello stepper (Weight, Miter Limit, Scale) | 5 pt | :9861 |
| `arrowtriangle.down.fill` | ▼ della stessa colonnina | 5 pt | :9861 |
| `arrowtriangle.down.fill` | ▾ del menu dei preset di Weight | 6 pt | :9814 |

Non sono SF Symbols — sono percorsi vettoriali disegnati a mano anche sul Mac,
e qui hanno le stesse coordinate, numero per numero:

| Disegno | Geometria | Riga del Mac |
|---|---|---|
| icona del **cap** | traccia spessa 8 `secondary` da x = −2 a x = 0,55·w, y = h/2, col cap richiesto; ancora verticale `primary` spessa 1 da y = 1 a y = h−1; il tutto ritagliato alla cella 20 × 16 | :9971-9990 |
| icona del **join** | angolo `(7, h+6) → (7, 7) → (w+6, 7)` spesso 7 `secondary`, join richiesto, miterLimit 10, ritagliato alla cella | :9996-10009 |
| icona dell'**align** | banda spessa 4 `secondary` al 55 % su un quadrato con inset `edge ± band/2` (inside/outside) o `edge` (center), `edge` = 4; sopra, il bordo dell'oggetto `primary` spesso 1 con inset 4 | :10016-10041 |
| cella dell'**icon-toggle** | 20 × 16, raggio 3, fondo accent al 30 % se attiva, bordo accent o `separatorColor` spesso 1 | :9954-9959 |
| **stepper-combo** | alto 20, raggio 3, fondo `textBackgroundColor`, bordo `separatorColor`; colonnina 12 divisa a metà, divisore 1, campo largo `fieldWidth` con padding 4, ▾ largo 14 | :9758-9837 |
| campo **dash** | 28 × (10 pt + 2 + 2 di padding), raggio 3, testo 10 pt monospazio centrato | :10048-10060 |

Il **checkbox** (`.toggleStyle(.checkbox)`) e il **Picker** dei marker sono
controlli di sistema su macOS: qui sono ridisegnati in Skia (quadratino 12 con la
spunta bianca; rettangolo raggio 5 con la coppia di triangolini a destra), per la
stessa ragione del segmentato di Swatches. Il Picker apre comunque un vero menu a
tendina di Windows, come il ▾ dei preset.

### 3.4 Align (P3/8, `win/ui_align_palette.cpp`)

Le righe sono di `GUI/SUI/Panel/SVGToolPanelSUIView.swift`.

Le **dodici** icone della palette sono SF Symbols, tutte alla stessa taglia
(15 pt, `.font(.system(size: iconSize))`, :9038) e tutte `.primary` da accese,
`.secondary` da spente:

| SF Symbol | Cella | Riga del Mac |
|---|---|---|
| `align.horizontal.left.fill` | Align Left | :8973 |
| `align.horizontal.center.fill` | Align Horizontal Center | :8974 |
| `align.horizontal.right.fill` | Align Right | :8975 |
| `align.vertical.top.fill` | Align Top | :8977 |
| `align.vertical.center.fill` | Align Vertical Center | :8978 |
| `align.vertical.bottom.fill` | Align Bottom | :8979 |
| `distribute.horizontal.left` | Distribute Left Edges | :8984 |
| `distribute.horizontal.center` | Distribute Horizontal Centers | :8985 |
| `distribute.horizontal.right` | Distribute Right Edges | :8986 |
| `distribute.vertical.top` | Distribute Top Edges | :8988 |
| `distribute.vertical.center` | Distribute Vertical Centers | :8989 |
| `distribute.vertical.bottom` | Distribute Bottom Edges | :8990 |

Come per Layers, Swatches e Stroke sono **ridisegnate in Skia**, alla stessa
taglia e con la stessa GRAMMATICA del simbolo Apple — non col suo tracciato, che
non si può copiare:

| Famiglia | Ricetta del ridisegno (cornice 15 × 15) |
|---|---|
| `align.*` | la **guida** su cui si allinea (retta 1 pt `.primary`: verticale a x = 0,5 / 7,5 / 14,5 per left/center/right, orizzontale alle stesse y per top/center/bottom) più **due barre** spesse 3,5 e lunghe 12 e 7,5, appoggiate alla guida nelle corsie a 3 e a 8,5 |
| `distribute.*` | **tre barre** spesse 3,5 e lunghe 10 / 14 / 10 nelle stesse posizioni (bordo "min" a 0,5 / 5,75 / 11) più un **segno di riferimento** (retta 1 pt `.primary` per tutta la cornice) sul bordo distribuito — sinistro, centro o destro; fra le tre varianti di un asse cambia il segno, non le barre |

Non è un SF Symbol il **Toggle** `.switch` `.mini` di "To Page" (:8967): è un
controllo di sistema, qui ridisegnato in Skia (capsula 26 × 15, pomo tondo
bianco, fondo accent da acceso) per la ragione di PORTING-PLAN §4-bis.

### 3.5 Pathfinder (P3/8, `win/ui_pathfinder_palette.cpp`)

Le righe sono di `GUI/SUI/Panel/SVGEPathfinderPalette.swift`.

**Qui non c'è nessun SF Symbol**, e lo dice il Mac stesso (:94-96): *«Drawn, not
SF-Symbol'd: the boolean result IS the icon […] and no symbol set carries the
nine of them»*. Le nove icone sono percorsi disegnati a mano anche sul Mac, e qui
hanno le **stesse coordinate, numero per numero**:

| Disegno | Geometria | Riga del Mac |
|---|---|---|
| cornice dell'icona | 22 × 18 | :102 |
| quadrato di dietro (`back`) | `(0,5, 4,5, 13, 13)` | :103 |
| quadrato davanti (`front`) | `(8,5, 0,5, 13, 13)` | :104 |
| tratto sottile | spessore 1 | :129 |
| tratteggio del Crop | spessore 1, dash `[2, 2]` | :130 |
| `ghost` | il colore pieno al **30 %** | :120 |
| `line` | `.primary` al **75 %** da acceso, `.secondary` da spento | :121 |
| Unite | `fill(union)` | :133 |
| Minus Front | `A` ritagliato in negativo su `B`, poi il contorno di `B` | :135-136 |
| Minus Back | `B` ritagliato in negativo su `A`, poi il contorno di `A` | :138-139 |
| Intersect | `B` ritagliato dentro `A`, poi i due contorni | :141-143 |
| Exclude | `fill(union)` **even-odd**, poi i due contorni | :146-148 |
| Divide | le tre facce (due `ghost`, l'intersezione piena), poi i due contorni | :150-154 |
| Trim | `A` in negativo su `B` in `ghost`, poi `B` pieno | :156-157 |
| Merge | `union` in `ghost`, l'intersezione piena, poi il contorno dell'`union` | :159-161 |
| Crop | `A` ritagliato dentro `B` pieno, contorno di `A`, contorno **tratteggiato** di `B` | :163-165 |
| cella | 30 × 30, angoli 4, fondo `controlBackgroundColor`, bordo `separatorColor` 1, opacità 50 % da spenta | :299-308 |

⛔ **Le nove celle sono disegnate ma SPENTE**: il pathfinder byte-fedele
(Martinez-Rueda di `pathbool.js`, `Reference/native-flip-design.md` §DECISIONI DI
LEO punto 2) non è nel motore, e `pathops_bool.*` è la via che quella decisione
esclude. È la stessa disciplina delle nove voci di Object ▸ Pathfinder ▸ nella
barra dei menu: presenti e grigie, mai omesse (PORTING-PLAN §4-bis).

### 3.6 Transparency (P3/8, `win/ui_transparency_palette.cpp`)

Nessun SF Symbol: la palette è fatta di tre soli controlli, e sono tutti e tre
controlli **di sistema** macOS, quindi tutti e tre ridisegnati in Skia
(PORTING-PLAN §4-bis).

| Disegno | Geometria | Riga del Mac |
|---|---|---|
| `Picker` dei blend mode | rettangolo raggio 5 alto 20, la coppia di triangolini a destra; apre un vero menu a tendina di Windows | :9499-9509 |
| `Slider` 0…100 | traccia alta 4 con angoli tondi (la parte a sinistra del pomo in accent), pomo tondo r = 7 col bordo | :9523 |
| `SVGENumberBox` | rettangolo raggio 3 alto 20, campo 48 + 5 di padding per lato = **58**, testo 11 pt monospazio | :6073, :6160, :6186 |
| checkbox "Knockout Group" | quadratino 12 raggio 3 con la spunta bianca, come quello di Stroke | :9563-9567 |

---

## 4. Provenienza, riga per riga

Ogni percorso è relativo a `/Users/leo/svgeditor` (repo Mac, sola lettura).

| Cosa | Da dove |
|---|---|
| Ordine dei 24 slot, id, nomi, scorciatoie | `SVGEditorMac/SVG Editor Mac/Utility/SVGEEnumManager.swift:168` (`get_mac_tool_list`), `:330` (`get_tool_custom_image_name`), `:511` (`get_tool_shortcut`), `:215` (`get_tool_sf_image_name`) |
| Geometria della griglia, flyout, doppi click | `SVGEditorMac/SVG Editor Mac/GUI/SUI/Panel/SVGToolPanelSUIView.swift:2480-2700` (griglia), `:2783` (flyout penna), `:2891` (flyout testo), `:7668` (proxy fill/stroke) |
| Palette Tools senza titolo, larghezza senza padding | `SVGEditorMac/SVG Editor Mac/GUI/SUI/Panel/SVGToolPanelSUIView.swift:1128`, `:1426` |
| Icone della toolbox | `SVGEditorMac/SVG Editor Mac/Assets.xcassets/ai_tool_*.imageset/` (PNG `@1x` + `@2x`) |
| Cursori | `SVGEditorMac/SVG Editor Mac/Method-Draw-master/drawmac/images/ai-cursors/` |
| Cursore dell'anello di rotazione | `SVGEditorMac/SVG Editor Mac/Method-Draw-master/drawmac/images/rotate.png` |
| Cursori 8× | `extracted_icons/adobe-illustrator-7.0.1/png/cursors-8x/` |
| Inventario dei cursori | `Reference/ai-cursors-inventory.csv` |
| Matrice cursori del canvas nativo | `SVGEditorMac/SVG Editor Mac/SkiaBridge/SVGESkiaView.mm:1637-1800` (costruttori) e `:5513-5717` (`desiredCursorAtView:flags:`) |
| Matrice cursori del canvas WebView (storica, per confronto) | `SVGEditorMac/SVG Editor Mac/GUI/Editor/SVGEEditorWebView.swift:772-911` (`SVGECursorFactory`, `toolCursorStyleCSS` a `:783`, 94 regole) |
| Alias dei tasti-tool e cifre 1–9 | `SVGEditorMac/SVG Editor Mac/SkiaBridge/SVGESkiaView.mm:17396-17424`; `Reference/gpu-window-keymap.md` §3d |
| Palette Layers: view, righe, footer, menu ≡▾ | `SVGEditorMac/SVG Editor Mac/GUI/SUI/Panel/SVGToolPanelSUIView.swift:8218-8790` (view), `:6472`/`:6525` (modello e VM), `:8789` (Layer Options) |
| Palette Swatches: view, chip, icone, menu ≡▾, operazioni | `SVGEditorMac/SVG Editor Mac/GUI/SUI/Panel/SVGESwatchesPalette.swift:1586-1820` (body), `:141` (modello `SVGESwatch`), `:283` (VM), `:402` (libreria di default), `:2254`/`:2336` (chip e icona di modello), `:2628`/`:2954` (i due dialoghi non portati) |
| Palette Stroke: view, controlli, icone, unita' del peso | `SVGEditorMac/SVG Editor Mac/GUI/SUI/Panel/SVGToolPanelSUIView.swift:9630` (root), `:10063-10460` (corpo + sincronizzazione con la selezione), `:9700`/`:9758` (`SVGEStepperComboField`), `:9662` (`SVGEStrokeWeightUnits`, la scala dei preset), `:9947`-`:10060` (i toggle, le tre icone, il campo dash) |

## 5. L'icona dell'applicazione

`svgeditor.ico` è l'**AppIcon del Mac** (`SVGEditorMac/SVG Editor Mac/Assets.xcassets/AppIcon.appiconset/` — il set che `ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon` dichiara nel progetto Xcode; l'`AppIcon 1.appiconset` accanto è il set iOS legacy e non si usa), impacchettata in `.ico` senza ridisegnare un pixel:

| Voce .ico | Sorgente |
|---|---|
| 16, 32, 64, 128 (DIB BGRA) | `icon_16x16.png`, `icon_32x32.png`, `icon_32x32@2x.png`, `icon_128x128.png` — byte decodificati, colori intatti |
| 256 (PNG incapsulato) | `icon_256x256.png` |
| 48 (DIB BGRA) | **derivata** da `icon_512x512.png` con bicubico: è l'unica taglia che macOS non ha, e Windows la usa (Explorer «icone medie») |

Montata da `win/svgeditor.rc` (risorsa `1`: è l'icona dell'exe per Explorer, taskbar e Alt-Tab) e da `wc.hIcon` in `win/main.cpp` per la classe della finestra.

**Le tile del Microsoft Store** (aggiunta 02/09/2026): `win/store/app-icon-1024.png` è `icon_512x512@2x.png` dello stesso set, copiato **byte per byte** (1024 × 1024, RGBA). È la sorgente più grande che esiste, e `scripts/package-win.ps1` ne ricava **tutte** le taglie del pacchetto MSIX (Square44/71/150/310, Wide310x150, StoreLogo alle scale 100-400 e le `targetsize` 16-256) con un ridimensionamento bicubico **verso il basso**, mai verso l'alto: la Square310x310 a scala 400 è 1240 px e dal PNG 256 dell'`.ico` uscirebbe sfocata. Sta in `win/store/` e non in `win/assets/` di proposito: `win/assets/` viene copiata intera accanto all'exe, e questo file non è dell'app.

I documenti fratelli in questa cartella: `PALETTES-SPEC.md` (le 24 palette) e
`MENUS-SPEC.md` (l'albero completo dei menu e tutte le scorciatoie).

## §5 — Shape library dei Symbols (aggiunta 01/09/2026, oracolo)

`win/assets/shapelib/*.json` — 12 file, 272 glifi, copiati VERBATIM da
`SVGEditorMac/SVG Editor Mac/Method-Draw-master/drawmac/shapelib/` (repo Mac,
main). `social.json` escluso DI PROPOSITO, come fa il Mac (PALETTES-SPEC §26).
Servono al tab Library della palette Symbols.

## §6 — Il documento di esempio: `sample/fox.svg` (aggiunta 01/09/2026)

`win/assets/sample/fox.svg` — **1 file, 20.284 byte**, copiato **byte per byte** da
`C:\dev\svgeditor-oracle\fox.svg` (l'oracolo di sola lettura). Non è arte nuova e non
è un file generato: è un documento **612 × 792 pt, modo colore `rgb`**, disegnato e
**salvato da questa stessa applicazione** (porta `data-svge-color-mode` e la libreria
di campioni in `se:swatches`, cioè l'intestazione che scrive il nostro serializzatore).
Verifica: `md5 = e96659901f87c3af4cb51a02584006fa` da tutt'e due le parti.

**A cosa serve.** Sul Mac `Utility/SVGEURLUtility.swift:52-58` copia al primo avvio la
cartella `resourcex/sample` del bundle dentro i Documenti dell'utente, e **mai
sovrascrive** (`if !FileManager.default.fileExists(atPath: sh.path)`, riga 55). Su
Windows lo fa `install_sample_documents()` (`win/main.cpp`), che enumera
`assets\sample\*` e chiama `CopyFileW(..., TRUE)` — il `TRUE` è il «fail if exists»,
cioè lo stesso «mai sovrascrivere» in una chiamata sola e senza corsa fra il test e la
copia. La cartella di destinazione è quella vera dell'utente:
`SHGetKnownFolderPath(FOLDERID_Documents)`, non `%USERPROFILE%\Documents` costruita a
mano (che su questa VM sarebbe sbagliata: Documenti è rimappata su `C:\Mac\Home\Documents`).

⚠️ **Divergenza DECISA da Leo, non un'omissione.** Il bundle macOS spedisce **tre**
campioni (`resourcex/sample/sample.svg`, `sample1.svg`, `sample2.svg`). Qui ce n'è
**uno solo, `fox.svg`, e li SOSTITUISCE tutti e tre**. È una scelta di Leo sul
contenuto, non una limitazione del guscio: `install_sample_documents()` copia
l'*intera* cartella, quindi rimettere i tre file del Mac è questione di copiarli in
`win/assets/sample/`, senza toccare una riga di codice.

⛔ **Il corpus di `tests/` non c'entra e non si tocca.** Quei file sono gli input degli
oracoli di `ctest` (parità byte-a-byte con il Mac): un documento di esempio è una cosa
che l'utente apre, un corpus è una cosa che un test confronta. Confonderli
significherebbe che un giorno qualcuno "aggiusta" un sample e rompe una parità.

## §7 — Gli asset della splash: `splash/` (aggiunta 01/09/2026)

`win/assets/splash/` — **9 file**, copiati verbatim dalla radice del target macOS
(`SVGEditorMac/SVG Editor Mac/`):

| File | Sorgente | Che cos'è |
|---|---|---|
| `SplashArtwork.png` | `SVG Editor Mac/SplashArtwork.png` (36.227 byte, md5 `53af7629e56a3c8b64f8a8e8556db49c`) | il ritaglio piatto ~3,9:1 dell'arte «Midnight Sun» — la fascia della **pagina 0** |
| `SplashSlideVector.svg` | idem | slide 1 — Full Vector Editor |
| `SplashSlideFormats.svg` | idem | slide 2 — PDF / EPS / AI Support |
| `SplashSlideAI.svg` | idem | slide 3 — AI Generator |
| `SplashSlideMCP.svg` | idem | slide 4 — MCP Server |
| `SplashSlideCMYK.svg` | idem | slide 5 — CMYK Support |
| `SplashSlideScripts.svg` | idem | slide 6 — Scripts |
| `SplashSlideType.svg` | idem | slide 7 — Advanced Typography |
| `SplashSlideAIScript.svg` | idem | slide 8 — AI Scripting |

Gli otto SVG sono documenti veri, tutti `viewBox="0 0 420 108"`, autorati sulla
**palette campionata dall'arte delle montagne** (cielo `#7538DE → #C95CAC`, cresta
`#3B2E6E`/`#241B4D`, sole `#F5A710 → #FBC432`, neve `#FFFFFF` —
`SVGESplashWindow.swift:38-41`). **Non sono immagini**: li rasterizza il NOSTRO
renderer a ogni avvio, `palette_raster_svg` (la pipeline del canvas) a **2×** della
fascia 420 × 108 pt, che è il `dpi: 144` del Mac (`renderArtwork`, :319-329). Se una
rasterizzazione fallisce la fascia dipinge comunque il cielo, mai un buco bianco
(:49-50).

Il montaggio è in `win/ui_splash.{h,cpp}`; i testi delle otto slide sono **verbatim**
dalla tabella `SVGESplashWindow.slides` (:125-161) e la versione viene da
`win/version.h`, la stessa intestazione che compila la `VERSIONINFO` del `.rc`.

### `SVGE_NO_SPLASH=1` — la variabile dei GATE, dichiarata

La splash si apre **a ogni avvio**, come sul Mac, e non ha nessun «don't show again».
Per i 16 gate di `scripts/` questo è rumore: galleggia sopra la finestra del documento
(quindi finisce negli **screenshot** dei gate a input vero) e intercetta la «prima
interazione». `SVGE_NO_SPLASH=1` la spegne, e i 16 gate la impostano in testa, subito
dopo `$ErrorActionPreference` (i processi figli la ereditano).

⚠️ **Non è una preferenza dell'utente e sul Mac non esiste**: nessuna voce di menu la
tocca, non sta in `palettes.ini`, non è documentata nell'interfaccia. È una variabile
d'ambiente per l'automazione, e questa riga è la sua unica dichiarazione.

La stessa variabile spegne **anche il flusso d'avvio dell'updater** (`win/updater.h`):
la domanda «Check for updates automatically?» che l'app fa al secondo avvio (il
`SUUpdatePermissionPrompt` di Sparkle) e il controllo silenzioso ogni 24 h. Sono, come
la splash, superfici che si aprono **da sole** all'avvio, e un gate non deve trovarsi
davanti una domanda modale. La voce Help ▸ Check for Updates… resta viva.

## §8 — Il catalogo dei tool MCP: `SVGEMCPTools.json` (aggiunta 02/09/2026)

`win/assets/SVGEMCPTools.json` — **1 file, 132.570 byte**, copiato **byte per byte** da
`C:\dev\svgeditor-oracle\SVGEditorMac\SVG Editor Mac\SVGEMCPTools.json` (la risorsa del bundle
macOS). Verifica: `md5 = 856733b1632cbfff69bb41a8519e3f97` da tutt'e due le parti.
(Il file ha gli a capo LF del Mac e così sta nel repo; su un checkout con `core.autocrlf=true`
la copia di lavoro può uscire CRLF, come già i JSON di `shapelib/` — il lettore non se ne
accorge, e il confronto byte per byte va fatto sul blob del repo.)

**Che cos'è.** Il catalogo dei **48 tool** che il server MCP dentro l'app espone
(`svgeditor.exe --mcp-stdio`, svgfeedback SVGE-1880): per ogni tool `name`, `description`,
`input_schema` (JSON Schema degli argomenti) e — per 46 di essi — `body`, il corpo ES5 che
viene incapsulato nell'envelope e **eseguito con `run_jsx` nell'app viva**. I due tool senza
corpo sono `svg_guide` (`kind: "guide"`, testo statico per topic) e `svg_run_js`
(`kind: "raw_js"`, il codice arriva dall'argomento). È un file **GENERATO** dai sorgenti
dell'helper Node `mcp/src/tools/*.ts` del repo Mac (la sorgente di verità dei tool:
`mcp/README.md`, sezione «Catalogo dei tool»); il consumatore Mac è
`MCP/SVGEMCPToolCatalog.swift`, quello Windows `win/mcp_seam.cpp` (`ToolCatalog`).

**Non si riscrive un tool a mano.** Quando il Mac rigenera il JSON, si ricopia — così i due
server espongono la stessa superficie, con lo stesso testo e lo stesso schema, e mandano
all'app lo stesso sorgente. Il gate `mcp_seam_test` conta le 48 voci e i due generi speciali.

**Dove sta a runtime.** Accanto all'eseguibile in `assets\` (il CMake copia tutta
`win/assets/` con `copy_directory`), cercato da `svgemcp::catalog_path()` con lo stesso
ordine di `svgeui::assets_dir()`: `%SVGE_ASSETS_DIR%`, poi `assets\` accanto all'exe, poi
risalendo verso `winssets`. Se manca, il server risponde comunque (con zero tool) e lo
dice su stderr, come il Mac (`SVGEMCPStdioServer.swift:62-64`).

### `SVGE_MCP_BRIDGE_DIR` — la variabile dei GATE, dichiarata

La casella di posta fra il processo `--mcp-stdio` e l'istanza grafica è
`%LOCALAPPDATA%\SVGEData\SVGEMCPBridge\` (`win/mcp_bridge.h`). `SVGE_MCP_BRIDGE_DIR=<cartella>`
la sposta, per provare il ponte senza toccare la casella vera dell'utente. Come
`SVGE_NO_SPLASH`, non è una preferenza e sul Mac non esiste.
