# PALETTES-SPEC — censimento delle 24 palette del Mac per il porting Windows

Questo documento è il censimento (slice **P3** del porting: replicare le palette
**identiche** su Windows) delle 24 palette registrate in `SVGEPaletteManager` nell'app
macOS. Non è codice: è la mappa di cosa esiste, dove sta nel sorgente Mac, che
scorciatoia ha, che dimensioni ha di default e quali controlli contiene. Ogni file:riga
è stato verificato con `grep -n`/`awk` sul repo Mac (sola lettura).

Alle 24 registrate si aggiungono **Brushes** e **Symbols** (§25 e §26), che sul Mac
esistono ma stanno FUORI dal registro: pannelli self-managed con store propri. Sono in
fondo al documento, nello stesso formato.

Fonti principali (base: `/Users/leo/svgeditor/SVGEditorMac/SVG Editor Mac/`):

- **Registro**: `GUI/SUI/Panel/SVGToolPanelSUIView.swift:1025` (`final class SVGEPaletteManager`);
  gli id delle palette alle righe **1034–1070**, la lista completa `all` (24 voci) alla riga **1071**.
- **Builder delle view**: `make_root(_:)` — stesso file, righe **1260–1287** (lo switch id → view SwiftUI).
- **Menu Window**: `Start/SVGEMenuBuilder.swift:2460` (`palette_menu_items()`), voci alle righe **2503–2621**.
- **Geometria/chrome condivisi**: factory `SVGEPaletteFactory.make` (SVGToolPanelSUIView.swift:315–336),
  normalizzazione dimensioni in `ensure_panel` (righe 1341–1545), header comune alto **23 pt**
  (`svge_palette_header_height`, riga 829).

## Meccanica comune (vale per tutte le palette)

- Ogni palette è un **NSPanel borderless flottante** (`styleMask [.borderless, .nonactivatingPanel]`,
  `level = .floating`, `hidesOnDeactivate = true`) creato a 64×320 e poi **content-sized** al primo
  layout: larghezza = fitting width del contenuto **+ 16 pt** di padding (`content_width_padding`,
  riga 1137; eccezione: Tools ha padding 0, riga 1426).
- Chrome custom, non titlebar di sistema: strip di drag alta 23 pt con titolo 10 pt, ✕ in alto a
  sinistra, menu opzioni **≡▾** in alto a destra (solo dove il contenuto lo dichiara con
  `.svge_palette_menu`), grip di resize in basso a destra solo per le palette ridimensionabili.
  Tools e Control sono **chromeless** (né titolo né menu ≡; riga 1128).
- Ridimensionabili **solo in altezza** (grip): Swatches, Scripts, Layers, Links (`resizable_palettes`,
  riga 1091; altezza minima 280, riga 1131). Ridimensionabile su **entrambi gli assi**: AI Script
  Console (`free_resizable_palettes`, riga 1116; min 360×240). Nessuna è width-resizable (riga 1103).
- Le palette laterali grandi (Swatches, Layers, Links, Scripts, Character, Paragraph) condividono
  **una sola larghezza** = la più stretta fra le aperte (`side_width_palettes`, riga 1143 + logica 1472–1497).
- La Control Palette è inchiodata a **900 pt** di larghezza (min == max, `control_fixed_width`,
  riga 1111): il contenuto in eccesso scorre in una ScrollView orizzontale.
- Frame persistiti in UserDefaults (`SVGEPalette.<id>`), visibilità in `SVGEPaletteVisible.<id>`;
  workspace di default con posti fissi per Tools/Swatches/Layers/Control (`workspace_defaults`,
  riga 2278). `hidden_palettes = [AI Script Console]` (riga 1079): esiste ma non è più offerta.

## Tabella riassuntiva

Traduzione scorciatoie: ⌘→Ctrl, ⌥→Alt, ⇧→Shift, F-key→F-key. ⚠ = caso ambiguo su Windows
(vedi note sotto la tabella). "—" = nessuna voce di menu / nessuna scorciatoia.
Le righe menu sono in `Start/SVGEMenuBuilder.swift`, le view in
`GUI/SUI/Panel/` (SVGTP = `SVGToolPanelSUIView.swift`).

| # | id (costante) | Titolo | Scorciatoia Mac | Scorciatoia Windows | Dimensioni di default | View (file:riga) |
|---|---|---|---|---|---|---|
| 1 | `tools` | Tools ("Toolbox" nel menu) | ⌘1 (menu:2503) | Ctrl+1 | content-sized, griglia fissa 67 pt di larghezza | SVGTP:2419 |
| 2 | `control` | Control Palette | ⌘2 (2504) | Ctrl+2 | **900 pt fissi** × altezza contenuto (minHeight 56) | SVGTP:3774 |
| 3 | `align` | Align | ⌥⌘A (2572) | Ctrl+Alt+A ⚠ | 114 pt × contenuto | SVGTP:8912 |
| 4 | `layers` | Layers | ⌘4 (2578) | Ctrl+4 | 240 pt × min 200 / ideal 300, h resizable | SVGTP:8218 |
| 5 | `character` | Character | ⌘T (2549) | Ctrl+T ⚠ | 300 pt × contenuto | SVGTP:8895 |
| 6 | `paragraph` | Paragraph | ⌥⌘T (2556) | Ctrl+Alt+T ⚠ | 250 pt × contenuto | SVGTP:11610 |
| 7 | `transparency` | Transparency | ⌘8 (2538) | Ctrl+8 | 240 pt × contenuto | SVGTP:9415 |
| 8 | `stroke` | Stroke | ⌘7 (2526) | Ctrl+7 | 240 pt × contenuto | SVGTP:9630 |
| 9 | `colors` | Colors | — (rimossa dal menu, commento a 2506) | — | 160 pt × contenuto | SVGTP:9047 |
| 10 | `info` | Info | ⌘9 (2573) | Ctrl+9 | 180 pt × contenuto | SVGTP:9112 |
| 11 | `swatches` | Swatches | F5 (2507) | F5 ⚠ | 250 pt × min 160 / ideal 280, h resizable | SVGESwatchesPalette.swift:1322 |
| 12 | `gradient` | Gradient | F6 (2508) | F6 | 248 pt × contenuto | SVGEColorPickerView.swift:1489 |
| 13 | `pattern` | Pattern | ⇧F6 (2509) | Shift+F6 | 236 pt × contenuto (scroll interno h 244) | SVGEColorPickerView.swift:3440 |
| 14 | `hatch` | Hatch | — (voce rimossa, SVGE-1746, commenti 2510-2521) | — | 236 pt × contenuto (scroll interno h 244) | SVGEHatchPalette.swift:110 |
| 15 | `ai` | AI Console | F7 (2598) | F7 | 480 pt × min 200 / ideal 320 | SVGEAIConsoleView.swift:2724 |
| 16 | `ai_scripts` | AI Script Console | — (nascosta, SK-1734) | — | min 440 / ideal 480 × min 220 / ideal 360, resizable 2 assi | SVGEAIScriptConsole.swift:590 |
| 17 | `scripts` | Scripts | voce senza chord (2597); ⌥⌘S su File ▸ Scripts ▸ Scripts Panel… (2113) | Ctrl+Alt+S ⚠ | minWidth 260 × min 240 / ideal 320, h resizable | SVGEScriptsPanel.swift:1120 |
| 18 | `links` | Links | F8 (2574) | F8 | 270 pt × min 180 / ideal 320, h resizable | SVGELinksPalette.swift:1092 |
| 19 | `navigator` | Navigator | ⇧F8 (2581) | Shift+F8 | 228 pt × contenuto (minimap fissa 208×156) | SVGENavigatorPalette.swift:212 |
| 20 | `pathfinder` | Pathfinder | ⌥⌘P (2588) | Ctrl+Alt+P ⚠ | 182 pt × contenuto | SVGEPathfinderPalette.swift:168 |
| 21 | `spray` | Spray | voce senza chord (2594) | — | 214 pt × contenuto | SVGESprayPalette.swift:319 |
| 22 | `debug` | Debug | — (voce rimossa, SVGE-1720) | — | 340 pt × min 160 / ideal 380 | SVGTP:9349 |
| 23 | `feedback` | Feedback | ⌥⌘F (2615) | Ctrl+Alt+F ⚠ | min 280 / ideal 310 × min 360 / ideal 440 | SVGEFeedbackPalette.swift:857 |
| 24 | `beta` | Beta Tools | — (voce rimossa, SVGE-1720) | — | 300 pt × contenuto | SVGEBetaToolsPalette.swift:138 |
| 25 | *(fuori registro)* | Brushes | ⌘5 (2523) | Ctrl+5 | 196 pt × contenuto (griglia h 158 fissa) | SVGEBrushesPalette.swift:1089 |
| 26 | *(fuori registro)* | Symbols | ⇧F7 (2525) | Shift+F7 | min 210×300 / ideal 242×420, resizable 2 assi | SVGESymbolsPalette.swift:746 |

**Note sui casi ambigui della traduzione ⌘→Ctrl:**

- **Ctrl+Alt+lettera** (Align, Paragraph, Pathfinder, Feedback, Scripts): su Windows Ctrl+Alt è
  sinonimo di **AltGr** — sui layout internazionali (italiano incluso) alcune combinazioni AltGr+lettera
  producono caratteri e verrebbero mangiate prima di arrivare all'app. Da testare per lettera; in caso
  di collisione la convenzione delle app Adobe su Windows è comunque Ctrl+Alt (Illustrator usa
  Shift+Ctrl+F9 per Pathfinder — scelta alternativa possibile).
- **Ctrl+T** (Character): su Windows è spesso "nuova scheda" nei browser, ma in un'app nativa è libera —
  è esattamente il chord di Character in Illustrator per Windows. OK ma segnalato.
- **F5** (Swatches): non riservata a livello di sistema, ma culturalmente "refresh"; Illustrator per
  Windows usa proprio F5 per Brushes e Shift+F5 per Graphic Styles, quindi F5 Swatches è accettabile.
- **F1** non è usata da nessuna palette (su Windows sarebbe Help): nessun conflitto.
- Nel menu Window del Mac compaiono anche **Brushes ⌘5** (riga 2523) e **Symbols ⇧F7** (riga 2525):
  NON sono nel registro delle 24 (hanno store/finestre proprie, `SVGEBrushesStore` /
  `SVGESymbolsStore`), ma **esistono e sono cablate** — sono censite qui sotto come **§25 e
  §26** (risposta a `QUESTIONS.md` §3). Le loro scorciatoie (Ctrl+5, Shift+F7) vanno
  riservate.

---

## 1. Tools (Toolbox)

- View: `SVGEToolsPaletteRoot` SVGTP:2419; griglia in `SVGToolPanelContentSUIView` SVGTP:2480.
  Menu: "Toolbox" ⌘1, SVGEMenuBuilder.swift:2503. Chromeless (né titolo né ≡).
- Dimensioni: nessun frame esplicito sul Root; la griglia è pinnata a `grid_width` = 2·32+1+2 =
  **67 pt** (SVGTP:2504, applicata a :2625). Il manager le dà padding orizzontale 0 (riga 1426).
- Controlli: griglia **2 colonne × 12 righe = 24 strumenti** (celle 32×32, spacing 1; lista da
  `svge_tool.get_mac_tool_list()`, Utility/SVGEEnumManager.swift:168): selection, direct_select,
  path, fhpath, spray, eraser, line, rect, ellipse, rounded_rect, polygon, star, text, text_pencil,
  eyedropper, scissor, measure, gradient, rotate, scale, reflect, shear, hand, zoom. Cinque slot
  speciali con flyout/long-press (penna :2783, text :2891, text_pencil :3110, brush-size per
  spray/eraser :3464, eyedropper :3635); il doppio click sugli altri apre i dialoghi
  Illustrator-style (Move, Rotate…, Scale…, ecc.). Sotto la griglia: Divider 56 pt e il proxy
  fill/stroke `SVGEFillStrokeView` (SVGTP:7668).

## 2. Control Palette

- View: `SVGEControlPaletteRoot` SVGTP:3774, corpo `SVGEControlPaletteView` SVGTP:3808 (body :4021).
  Menu: ⌘2, SVGEMenuBuilder.swift:2504. Chromeless; edge di default: top… ma il workspace la
  posiziona centrata in basso, 16 px sopra il bordo del contenuto della finestra documento (SVGTP:2311-2326).
- Dimensioni: larghezza **fissa 900 pt** (`control_fixed_width` riga 1111, pin a :1397 e :1543);
  `minHeight 56` (`textBarHeight`, applicato a :4066). Il contenuto oltre i 900 pt scorre in orizzontale.
- Controlli: barra context-sensitive. Con selezione normale (`selectionBar` :4139): proxy dei 9 punti
  di riferimento 34×34, campi X/Y/W/H (box 64 pt) con lucchetto aspect, Scala % (min 1) e Rotazione °
  (−360…360), bottoni "Rotate…"/"Reflect…", cluster align; poi swatch fill/stroke, weight
  (stepper-combo, max 500), opacity 0…100 %, Picker dash a 4 voci (Solid/Dashed/Dotted/Dash-dot),
  checkbox "Scale Strokes", toggle cap (butt/round/square) e join (miter/round/bevel). In editing
  testo (`textContextBar` :4467): colonne famiglia/stile font (120 pt), corpo, toggle B/I ecc.,
  tracking/leading, scala H/V, colore testo, allineamenti, rientri, spaziature. Tab order dei sei
  campi geometrici: X→Y→W→H→Scale→Rotate ciclico (:3798).

## 3. Align

- View: `SVGEAlignPaletteRoot` SVGTP:8912, corpo `SVGEAlignPaletteView` SVGTP:8927.
  Menu: ⌥⌘A, SVGEMenuBuilder.swift:2572.
- Dimensioni: larghezza fissa **114 pt** (3·30 + 2·4 + 16, frame a :8993), altezza content-sized.
- Controlli: header "Align" con toggle switch mini "**To Page**" (`@AppStorage("SVGEAlignToPage")`);
  griglia 3×2 = **6 celle** align (left/h-center/right/top/v-center/bottom, celle 30 pt); Divider;
  header "Distribute" con seconda griglia 3×2 = **6 celle**. Gating per arità: align abilitato con 2+
  oggetti (1+ se To Page), distribute con 3+ (:9002-9021). Nessun menu ≡.

## 4. Layers

- View: `SVGELayersPaletteRoot` SVGTP:8218, corpo `SVGELayersPaletteView` SVGTP:8333 (body :8695).
  Menu: ⌘4, SVGEMenuBuilder.swift:2578. Ridimensionabile in altezza; larghezza condivisa col gruppo laterale.
- Dimensioni: **240 pt × minHeight 200 / idealHeight 300 / maxHeight ∞** (:8759-8760).
- Controlli: lista scrollabile di righe layer con albero degli oggetti figli espandibile e chip di
  anteprima SVG 26×20 (`SVGELayerThumbView` :8241); footer con 4 bottoni 22×22: `+` nuovo layer,
  cestino, frecce su/giù (spostano oggetto selezionato o layer). Menu ≡ ricco (:8387): New Layer…,
  Duplicate, Delete, Options…, Make Clipping Mask, Locate Object, Merge Selected, Flatten Artwork,
  Reverse Order, Hide/Lock All, Show Previews, Palette Options… (sheet con dimensione riga
  small/medium/large, :8768); alcune voci presenti ma disabilitate (New Sublayer, Collect in New
  Layer, Release to Layers, Template, Outline All, Paste Remembers Layers).

## 5. Character

- View: `SVGECharacterPaletteRoot` SVGTP:8895, corpo `SVGECharacterPaletteView` SVGTP:10692 (body :10834).
  Menu: ⌘T, SVGEMenuBuilder.swift:2549 (duplicato inerte con Type ▸ Character, stesso selettore).
- Dimensioni: **300 pt** fissi (:10846), altezza content-sized; larghezza condivisa col gruppo laterale.
- Controlli: sette righe — famiglia font (picker 158 pt) + stile (popup 112 pt); corpo (6…288) +
  leading con hint "auto"; tracking (+ menu ▾ preset) + kerning (Auto/0); scala H/V % (1…10000);
  baseline shift in pt; riga di **8 toggle** di formato (Bold, Italic | Underline, Strikethrough |
  Superscript, Subscript | All Caps, Small Caps); sezione assi variabili solo per font variable
  (:11421). Disabilitata/al 50 % di opacità senza testo selezionato. Nessun menu ≡.

## 6. Paragraph

- View: `SVGEParagraphPaletteRoot` SVGTP:11610, corpo `SVGEParagraphPaletteView` SVGTP:11625.
  Menu: ⌥⌘T, SVGEMenuBuilder.swift:2556 (target esplicito `SVGEPaletteManager`, helper a :1176).
- Dimensioni: **250 pt** fissi (:11710), altezza content-sized.
- Controlli: riga di **7 bottoni di allineamento** (left, center, right, justify-left, justify-center,
  justify-right, justify-all — tabella :11661); campi Left/Right indent, First-line indent (anche
  negativo), Space before/after (box numerici 50 pt); checkbox "Hyphenate". Nessun menu ≡.

## 7. Transparency

- View: `SVGETransparencyPaletteRoot` SVGTP:9415, corpo `SVGETransparencyView` SVGTP:9430 (body :9496).
  Menu: ⌘8, SVGEMenuBuilder.swift:2538.
- Dimensioni: **240 pt** fissi (:9576), altezza content-sized.
- Controlli: riga "Blend" con Picker dei blend mode CSS (più voce "—" per stato misto); riga
  "Opacity" con **Slider 0…100** + box numerico (placeholder "—" su selezione mista) + "%";
  `Toggle("Knockout Group")` checkbox, disabilitato se la selezione non è un gruppo. Lo slider Blur
  è stato rimosso (SVGE-1751, commento :9556). Nessun menu ≡.

## 8. Stroke

- View: `SVGEStrokePaletteRoot` SVGTP:9630, corpo `SVGEStrokeSettingsView` SVGTP:10063 (body :10151).
  Menu: ⌘7, SVGEMenuBuilder.swift:2526.
- Dimensioni: **240 pt** fissi (:10349), altezza content-sized.
- Controlli: Weight (stepper-combo con preset, 0…500) + Cap (3 icon-toggle); Miter Limit (1…100) +
  Join (3 icon-toggle); Align stroke; `Toggle("Dashed Line")` con **6 campi** dash/gap alternati;
  `Toggle("Non-Scaling Stroke")`; sezione markers: picker Start/End (None/Arrow/Circle, 130 pt) e
  Scale marker (10…1000 %, step 10), disabilitata con entrambi i marker a None. Nessun menu ≡.

## 9. Colors

- View: `SVGEColorsPaletteRoot` SVGTP:9047, corpo `SVGEColorsPaletteView` SVGTP:9062.
  Menu: **nessuna voce** — rimossa dal menu Window ("color editing lives in Swatches", commento
  SVGEMenuBuilder.swift:2506); il selettore `x_toggle_colors_palette` esiste ancora
  (GUI/Doc/SVGEDocManager.swift:2332) ma non è raggiungibile dalla UI di produzione.
- Dimensioni: **160 pt** fissi (:9106), altezza content-sized.
- Controlli: Picker segmentato Fill/Stroke; `LazyVGrid` a **5 colonne fisse da 22 pt** con **25
  campioni** ("none" con diagonale rossa + 24 colori esadecimali fissi, :9068-9074); ogni cella
  applica `svg_set_paint` e mostra l'hex nel tooltip. Nessun menu ≡, nessun editor HSB/RGB.

## 10. Info

- View: `SVGEInfoPaletteRoot` SVGTP:9112, corpo `SVGEInfoPaletteView` SVGTP:9130.
  Menu: ⌘9, SVGEMenuBuilder.swift:2573.
- Dimensioni: **180 pt** fissi (:9189), altezza content-sized.
- Controlli: sola lettura, nessun bottone: due colonne X/Y e W/H (valori monospaced in box 56 pt,
  "—" senza selezione, unità documento da `SVGESetupUnits.from_pref`); riga "∠:" viva durante una
  rotazione; blocco Measure (D/∠ + W/H) quando il tool misura ha un risultato. Nessun menu ≡.

## 11. Swatches

- View: `SVGESwatchesPaletteRoot` GUI/SUI/Panel/SVGESwatchesPalette.swift:1322, corpo
  `SVGESwatchesPaletteView` :1357 (body :1586). Menu: F5, SVGEMenuBuilder.swift:2507.
  Ridimensionabile in altezza; larghezza condivisa col gruppo laterale.
- Dimensioni: **250 pt × minHeight 160 / idealHeight 280 / maxHeight ∞** (:1778-1779).
- Controlli: Picker segmentato Fill/Stroke; "Tint:" con picker a 11 step (100→0 %); campo Find
  opzionale; corpo a tre modalità — lista per nome, griglia campioni **16 pt** o **28 pt**
  (`LazyVGrid` adattiva, spacing 4, :2031); footer con `+` New Swatch, cestino Delete, matita
  Swatch Options…. Menu ≡ (:1716): New/Duplicate/New Tint/Delete/Options…, Select All Unused,
  Add All Unused Colors, Sort by Kind/Name/Hue, switch vista Name/Small/Large, Show Find Field
  ("Merge Swatches" presente ma sempre disabilitato).

## 12. Gradient

- View: `SVGEGradientPaletteRoot` GUI/SUI/Panel/SVGEColorPickerView.swift:1489, corpo
  `SVGEGradientPaletteView` :1650 (body :1719). Menu: F6, SVGEMenuBuilder.swift:2508.
- Dimensioni: **248 pt** fissi (:1876), altezza content-sized.
- Controlli: Picker Fill/Stroke; selettore tipo a griglia 3 colonne con **5 tipi** (Linear, Radial,
  Sweep, Conical, Mesh); rampa `SVGEGradientRamp` (doppio click aggiunge stop, drag sposta, drag
  fuori elimina, doppio click su stop apre il color picker) + editor dello stop + sezione preset;
  Slider "Angle" 0…360° (linear/sweep/conical); per conical tre righe slider+campo: Inner 0…200,
  Outer 1…200, Focus 0…100 %; Picker "Spread" Pad/Reflect/Repeat; bottone **Apply**. Per mesh:
  preview + editor dedicato. Menu ≡ (:1951) con una sola voce: "Add a Preset" (disabilitata su mesh).

## 13. Pattern

- View: `SVGEPatternPaletteRoot` GUI/SUI/Panel/SVGEColorPickerView.swift:3440, corpo
  `SVGEPatternPaletteView` :3456 (body :3482). Menu: ⇧F6, SVGEMenuBuilder.swift:2509.
- Dimensioni: **236 pt** fissi (:3640); ScrollView interna fissa a **244 pt** di altezza (:3521).
- Controlli: Picker Fill/Stroke; nella ScrollView: griglia pattern utente (da Edit ▸ Define
  Pattern…), libreria `SVGEPatternFillsGrid` (49 tile in gruppi, `LazyVGrid` 4 colonne, celle
  fisse 46, thumbnail 46×34) e sezione "Classic" con i **7 preset procedurali** (dots, stripes h/v/d,
  checker, grid, crosshatch). Sotto: chip colore 22×18 + "Size" (campo 1…400 px) + **Apply**;
  checkbox "Background" con secondo chip; checkbox "Scale pattern with object"; preview 44 pt;
  sezione "Image Pattern" con "Choose Image…", miniatura 34×26, campo Tile 1…2000 px e secondo
  Apply. Nessun menu ≡.

## 14. Hatch

- View: `SVGEHatchPaletteRoot` GUI/SUI/Panel/SVGEHatchPalette.swift:110, corpo
  `SVGEHatchPaletteView` :123. Menu: **voce rimossa** (SVGE-1746, commento
  SVGEMenuBuilder.swift:2510-2521; il chord ⇧F5 è caduto con la voce); il selettore
  `x_toggle_hatch_palette` resta (SVGTP:1240 circa) ma la palette non è raggiungibile dalla UI.
- Dimensioni: **236 pt** fissi (:278); ScrollView delle figure fissa a **244 pt** (:171).
- Controlli: gemella del Pattern ma applica le figure come **tile vettoriali reali** (hatch fill)
  invece che come `<pattern>`: stessa libreria 49 preset + 7 "Classic" (griglie 4 colonne, celle 46);
  chip colore + "Size" 6…400 px + Apply; checkbox Background con secondo chip; preview 44 pt; riga
  finale con hint "Click a figure to hatch the selection." e bottone **Remove**. Nessun menu ≡.

## 15. AI Console

- View: `SVGEAIConsoleRoot` GUI/SUI/Panel/SVGEAIConsoleView.swift:2724, corpo `SVGEAIConsoleView`
  :2734 (body :2765). Menu: F7, SVGEMenuBuilder.swift:2598.
- Dimensioni: **480 pt × minHeight 200 / idealHeight 320 / maxHeight ∞** (:2773-2774).
- Controlli: transcript scrollabile con busy-row (ProgressView + contatore secondi + bottone
  **Stop**); riga "Speed" con slider AppKit a tacche (solo engine nativo, una tacca per livello
  esposto dal server); riga thumbnails allegati (chip 40×40 con ✕ e contatore n/max); input bar con
  📎 allega immagine, menu prompt (`text.badge.plus`: Default, Built-in, Your prompts, Manage
  prompts…), TextField monospace multiriga (1…6 righe) e bottone **Send** borderedProminent.
  Drop di immagini sull'intera palette. Nessun menu ≡.

## 16. AI Script Console (nascosta)

- View: `SVGEAIScriptConsoleRoot` GUI/SUI/Panel/SVGEAIScriptConsole.swift:590, corpo
  `SVGEAIScriptConsoleView` :595. Menu: **nessuno** — SK-1734 ha rimosso ogni entry point; è anche
  in `hidden_palettes` (SVGTP:1079), quindi non viene mai ripristinata. Nel porting va decisa:
  replicarla nascosta o ometterla.
- Dimensioni: **minWidth 440 / idealWidth 480 × minHeight 220 / idealHeight 360**, unica palette
  ridimensionabile su entrambi gli assi (:616-617; `free_resizable_palettes` SVGTP:1116).
- Controlli: transcript monospace 11 con prefissi `>`/`◆`/`✗` e colori per ruolo (righe lunghe in
  sotto-scroll maxHeight 260); `scriptBar` con nome `<file>.jsx` e bottoni **Save to Scripts** /
  **Copy**; input bar con TextField "Describe the script to write…", cestino (clear session) e Send.

## 17. Scripts

- View: `SVGEScriptsPaletteRoot` GUI/SUI/Panel/SVGEScriptsPanel.swift:1120, corpo
  `SVGEScriptsPanelView` :1125. Menu: voce Window senza chord (SVGEMenuBuilder.swift:2597);
  il chord **⌥⌘S** vive su File ▸ Scripts ▸ Scripts Panel… (:2113, stesso selettore).
  Ridimensionabile in altezza; larghezza condivisa col gruppo laterale.
- Dimensioni: **minWidth 260 × minHeight 240 / idealHeight 320 / maxHeight ∞** (:1240-1241).
- Controlli: bottone Reload; `List` a due sezioni "Demo" (script builtin) e "Imported", doppio click
  apre lo Script Console; barra con **Run** (shortcut Return), matita rename, cestino (solo
  imported), cartella "Reveal Scripts folder"; pannello output monospace (min 60 / max 120 pt) se
  c'è output. Menu ≡ (:1245): New Script, Add Script…, Edit Script…, Rename Script…, Show in Finder.

## 18. Links

- View: `SVGELinksPaletteRoot` GUI/SUI/Panel/SVGELinksPalette.swift:1092, corpo
  `SVGELinksPaletteView` :1118. Menu: F8, SVGEMenuBuilder.swift:2574. Ridimensionabile in altezza;
  larghezza condivisa col gruppo laterale.
- Dimensioni: **270 pt × minHeight 180 / idealHeight 320 / maxHeight ∞** (:1167-1168).
- Controlli: lista righe link con thumbnail 26×26, nome, stato ("Missing" / dimensioni), badge e
  warning; tap seleziona, doppio tap "go to". Barra inferiore: contatore "N Links · N missing" e 4
  bottoni icona — Relink…, Go To Link, Update All Links, Edit Original. Menu ≡ (:1170): Update All
  Links, Extract All Embedded…, e sull'item selezionato Go To Link, Relink…, Update Link, Embed
  Link, Extract…, Edit Original, Reveal in Finder.

## 19. Navigator

- View: `SVGENavigatorPaletteRoot` GUI/SUI/Panel/SVGENavigatorPalette.swift:212, corpo
  `SVGENavigatorPaletteView` :241. Menu: ⇧F8, SVGEMenuBuilder.swift:2581.
- Dimensioni: **228 pt** fissi (boxWidth 208 + 20, :305); minimap fissa **208×156** (:388),
  altezza complessiva content-sized.
- Controlli: minimap del documento (thumbnail + pagina bianca + **rettangolo rosso** dell'area
  visibile, pan via drag layer nativo); riga zoom: bottone − (×0.75), **slider logaritmico
  6 %…1600 %** (mini), bottone + (×1.25), campo percentuale 52 pt. Placeholder "No open document."
  senza documento. Nessun menu ≡.

## 20. Pathfinder

- View: `SVGEPathfinderPaletteRoot` GUI/SUI/Panel/SVGEPathfinderPalette.swift:168, corpo
  `SVGEPathfinderPaletteView` :182. Menu: ⌥⌘P, SVGEMenuBuilder.swift:2588.
- Dimensioni: **182 pt** fissi (5·30 + 4·4 + 16, :216), altezza content-sized.
- Controlli: header "Shape Modes" con **5 bottoni** (Unite, Minus Front, Minus Back, Intersect,
  Exclude); header "Pathfinders" con **4 bottoni** (Divide, Trim, Merge, Crop); celle 30×30 con
  icone disegnate ad hoc, abilitazione secondo il numero/tipo di operandi e tooltip che spiega il
  perché di una cella grigia; riga di hint dinamica in fondo. Nessun menu ≡.

## 21. Spray

- View: `SVGESprayPaletteRoot` GUI/SUI/Panel/SVGESprayPalette.swift:319, corpo `SVGESprayPaletteView`
  :324. Menu: voce Window senza chord (SVGEMenuBuilder.swift:2594; il commento spiega che ogni
  ⌥⌘lettera vicina è già occupata).
- Dimensioni: **214 pt** fissi (:357), altezza content-sized (cresce col DisclosureGroup).
- Controlli: preview dello spray; slider **Size** 2…400, **Density** 1…100, **Dot Size** 0.25…24
  (label 62 pt, valore 38 pt); DisclosureGroup "Spray Options" con picker Shape / Rotate / Origin /
  Direction, slider Spread 5…360, Edge Fade 0…1, Opacity 0.05…1, Size Var 0…12, Opacity Var 0…1 e
  riga Seed con "Randomize"; in fondo bottone **Reset**. Nessun menu ≡.

## 22. Debug (nascosta)

- View: `SVGEDebugPaletteView` SVGTP:9349 (non esiste un Root separato: la view osserva direttamente
  `SVGEDebugLog.shared`). Menu: **voce rimossa** dal Window di produzione (SVGE-1720, commento
  SVGEMenuBuilder.swift:2607-2610); il selettore `x_toggle_debug_palette` resta per uso interno.
- Dimensioni: **340 pt × minHeight 160 / idealHeight 380 / maxHeight ∞** (:9405-9406).
- Controlli: header con toggle "solo errori" (`exclamationmark.triangle` + contatore, rosso quando
  attivo), contatore righe totali, cestino (clear); log monospace 10 pt (verde per le righe normali,
  rosso semibold per gli errori), testo selezionabile, autoscroll a fondo. Nessun menu ≡.

## 23. Feedback

- View: `SVGEFeedbackPaletteRoot` GUI/SUI/Panel/SVGEFeedbackPalette.swift:857 (il Root È la view: i
  controlli sono computed property dello stesso struct). Menu: ⌥⌘F, SVGEMenuBuilder.swift:2615
  (target esplicito, helper :1216); si apre anche dal 💬 in basso a sinistra della pagina editor.
  Edge di default: left, ma parcheggiata a destra della Toolbox (SVGTP:2326-2345).
- Dimensioni: **minWidth 280 / idealWidth 310 × minHeight 360 / idealHeight 440** (:875) —
  elastica su entrambi gli assi, nessuna misura fissa.
- Controlli: banner introduttivo dismissibile con link al forum; cronologia chat a bolle con, sui
  messaggi falliti, "Retry" / "Send text only" / rimetti-nel-composer; riga thumbnails in attesa;
  composer con text view fissa 56 pt (placeholder "Describe a bug or idea… (Enter to send)"),
  bottoni 📎 "Attach images…" e "Paste image (⌘V)", ProgressView di coda e **Send** borderedProminent
  (⌘Return). Drop di file/immagini sull'intera palette. Nessun menu ≡.

## 24. Beta Tools (nascosta)

- View: `SVGEBetaToolsPaletteRoot` GUI/SUI/Panel/SVGEBetaToolsPalette.swift:138 (il Root è la view).
  Menu: **voce rimossa** (SVGE-1720, commento SVGEMenuBuilder.swift:2616-2619); selettore
  `x_toggle_beta_tools_palette` mantenuto per uso interno.
- Dimensioni: **300 pt** fissi (:164), altezza content-sized.
- Controlli: intro "Experimental tools, off by default…"; catalogo (`SVGEBetaToolsCatalog.all`,
  :61-83) con **2 voci**: "Skia Paragraph (area text)" (solo heading informativo, senza toggle) e
  "Hatch Fill" (checkbox; se ON compare il pannello `SVGEHatchFillControls`); riga finale
  "Relaunch the app to apply your change." + bottone "Relaunch Now" quando serve. Nessun menu ≡.

---

# Le due palette FUORI dal registro (Brushes e Symbols)

Risposta a `QUESTIONS.md` §3. **Sì: entrambe esistono sul Mac di produzione**, sono
vive e cablate (non stub), ma non sono nel registro `SVGEPaletteManager.all`
(SVGTP:1071) — sono **self-managed**: ogni store possiede il proprio
`SVGEPalettePanel`, la propria copia della chrome ✕/ridges e le proprie chiavi
UserDefaults. Da qui la loro assenza dal censimento delle 24. Le sezioni 25 e 26
sono nello stesso formato delle precedenti.

Meccanica comune a tutte e due (dove differiscono dal registro):

- Il pannello è creato da `SVGEPaletteFactory.make(title:content:resizable:)` come per
  le altre, ma da `ensure_panel()` dello STORE (Brushes:838, Symbols:499), non dal manager.
  Niente `content_width_padding`, niente larghezza condivisa del gruppo laterale: la
  larghezza è quella che il body dichiara.
- La chrome è una **copia locale** della strip condivisa (strip alta 10 pt con la ✕ a
  sinistra + `SVGEPaletteHeaderDragArea`, Divider, poi il consueto
  `SVGEPaletteTitleBody` col titolo e il menu **≡▾**): `SVGEBrushesChrome`
  SVGEBrushesPalette.swift:1051 (strip :1018), `SVGESymbolsChrome`
  SVGESymbolsPalette.swift:698 (strip :667). Serve perché la ✕ condivisa chiama
  `SVGEPaletteManager.hide_palette`, che conosce solo i pannelli del manager.
- Posizione di default: `SVGEPaletteFactory.position(edge: .right)` rispetto alla main
  window, poi `SVGEPaletteGeometry.clamp` (SVGE-749) al primo layout.
- Entrambe si **auto-annunciano** al manager con
  `register_self_managed_palette(nome, panel:show:hide:)` (Brushes:864, Symbols:551) —
  altrimenti il TAB (nascondi/mostra tutte le palette), che itera il registro, le
  salterebbe. Su Windows il TAB deve conoscerle allo stesso modo.
- Le voci di menu le raggiungono con **target esplicito** sullo store
  (`brushes_item` SVGEMenuBuilder.swift:1190, `symbols_item` :1203), come Paragraph e
  Feedback: nessun nuovo selettore sulla responder chain.
- Entrambe si nascondono da sole mentre è aperto un pannello Open/Save (osservano
  `NSSavePanel` didBecomeKey / willClose) e si riagganciano al documento che diventa
  main (`NSWindow.didBecomeMainNotification`): Brushes ri-spinge il brush attivo nella
  nuova webview, Symbols ricarica la lista dal nuovo documento.

## 25. Brushes

- View: `SVGEBrushesPaletteView` GUI/SUI/Panel/SVGEBrushesPalette.swift:1089 (body :1097);
  store/pannello `SVGEBrushesStore` :240 (`ensure_panel` :838). Menu: **⌘5**,
  SVGEMenuBuilder.swift:2523 (→ Ctrl+5); Edit ▸ **Define Brush from Selection**, senza
  chord, :636 (abilitata solo con selezione, `validateMenuItem` :831).
- Dimensioni: **196 pt** fissi (:1143 — il literal è `4·40 + 3·6 + 16 + 2`, scritto a mano
  per non far esplodere il type-checker), altezza content-sized; **non ridimensionabile**
  (`resizable: false`, :842). La griglia dei brush vive in una ScrollView alta **158 pt
  fissi** (:1107).
- Controlli:
  - **Griglia** `LazyVGrid` 4 colonne `.fixed(40)`, spacing 6, padding 8 (:1100-1106).
    Celle **40×40**, corner radius 4, bordo 0.5 pt che diventa un anello accentColor di
    2 pt sulla cella attiva. Prima cella = **None** (`circle.slash`, :1363); poi una cella
    per brush (:1378) con la thumbnail dell'artwork e context menu "Delete Brush" (solo
    brush utente).
  - **Parametri del brush attivo** (compaiono solo se c'è un brush attivo): slider
    **Size** 0.2…4 (read-out `1.0×`) e **Spacing** 0…60 (read-out `Auto` sotto 0.5).
    Riga = label 44 pt + slider + valore 34 pt (`slider_row` :1199). Il rilascio dello
    slider COMMITTA (vedi undo sotto), il trascinamento no.
  - **DisclosureGroup "Scatter Options"** (:1236), chiuso di default e aperto da solo per
    un brush che già usa lo scatter (`has_scatter`). Contiene, in quest'ordine: picker
    **Spread** (Fixed / Count / Fit / Scale / Fit Random / Scale Random); slider **Count**
    1…200 (solo Spread=Count); **Fit Adj** −80…200 % (solo fit/scale/*-rand); picker
    **Artwork** (All Together / Random / In Order — solo con più di un artwork);
    **Fade In** e **Fade Out** 0…1; checkbox **Follow Path**; picker **Rotate** (Off /
    Rotate / Vibrate) con **Step** −180…180° o **± Angle** 0…180°; **Anchor X** e
    **Anchor Y** 0…100 %; **Scatter** 0…60; **Size Var** 0…100 %; **Opacity Var**
    0…100 %; intestazione "Velocity" e **Size Vel / Opacity Vel / Spacing Vel** 0…100 %;
    riga **Seed** (numero + bottone "Randomize"); bottone **Reset Scatter**.
    I picker sono `.menu` `.mini`, i label 10 pt. Ogni controllo scrive subito la
    definizione e committa (picker/toggle/Randomize) o committa al rilascio (slider).
  - **Footer**: nome del brush attivo, o "No brush (plain pencil)" (:1176); a destra il
    bottone **+** = *New Brush* (:1128), che con una selezione fa Define Brush portandosi
    dietro TUTTI i parametri mostrati, e senza selezione duplica il brush attivo coi suoi
    parametri come brush utente ("… copy", "… copy 2").
  - **Menu ≡▾** (:1151): *Apply Brush to Selection*, *Remove Brush from Selection*, —,
    *New Brush from Current Settings*, *Define Brush from Selection*, —,
    *Delete "&lt;nome&gt;"* (solo se il brush attivo è un brush utente).
  - **Cinque alert di rifiuto** con testo esatto da riportare: "This selection cannot take
    a brush" (:605), "Nothing to save as a brush" (:496), "Select something to apply the
    brush to" (:758), "No brush is active" (:769), "This selection cannot become a
    brush" / "Select something to define a brush from" (:806). Regola SVGE-1307: un
    comando di questa palette non fallisce mai in silenzio.
  - **Semantica del click** (:550): con selezione ⇒ rende attivo il brush **e lo applica**;
    senza selezione ⇒ arma/disarma il pennello. Il click su None con selezione **toglie**
    il brush. Il gate è `has_editable_selection()` (verità del master), MAI l'eco
    `selected_panel` (SVGE-1425). Scegliere un brush **non cambia lo strumento attivo**
    (SVGE-1457).
- Operazioni ed etichette di undo (core condiviso, **già presente in questo repo**):
  - stamp lungo un path ⇒ `svgscene::brush_stamp`, Transaction **"Brush Stroke"**
    (core/scene/brush_ops.h:526 e :544); `removeSpine` toglie il path sorgente NELLA
    STESSA transazione, quindi applicare un brush a un tracciato già disegnato è **un
    solo ⌘Z**.
  - cella None / *Remove Brush from Selection* ⇒ `brush_unstamp`, **"Remove Brush"**
    (brush_ops.h:572, :588): il gruppo di stamp esce e torna il `<path>` spina, con lo
    stesso id.
  - rilascio di uno slider con strokes selezionati ⇒ re-stamp dei SOLI strokes che usano
    quel brush (`commit_params` :684) — di nuovo "Brush Stroke", uno step per gesto.
  - Object ▸ Expand su uno stroke ⇒ `brush_expand` (brush_ops.h:650).
  - un redraw della spina riusa lo stesso stamp con label **"Redraw"**
    (`label` parametro, brush_ops.h:537).
  - *Define Brush* **non tocca il documento**: cattura markup + defs e scrive solo nello
    store ⇒ nessuno step di undo.
- Store / persistenza — **UserDefaults, non il documento**:
  - `SVGEUserBrushes` — `Data`, JSON array di `SVGEBrushDef`: i brush definiti
    dall'utente (chiave :244, lettura :376, scrittura :385).
  - `SVGEBrushPresetTweaksV2` — `Data`, JSON dict `id → SVGEBrushDef`: le modifiche fatte
    ai preset built-in, **senza l'artwork** (che viene sempre dal codice, così un futuro
    aggiornamento dei preset raggiunge l'utente) — :246, :364.
  - `SVGEBrushPresetTweaks` — formato legacy `[spacing, scale]` per preset, ancora LETTO
    per non perdere i tweak di un'installazione vecchia (:245, :353); vince la v2.
  - `SVGEPaletteVisible.Brushes` (Bool) e `SVGEPalette.Brushes`
    (String, `NSStringFromRect`) — visibilità e frame (:247-248).
  - I **6 preset** (Dot, Square, Star, Scatter Dots, Calligraphic, Scatter) sono
    **compilati nel sorgente** (:255-286), non un asset: il markup va riportato verbatim,
    è l'unico modo in cui la pagina può conoscerli.
  - Nel **DOCUMENTO** finisce solo lo stroke stampato: un
    `<g class="svge-brush-stroke">` con `data-svge-brush-spine` / `data-svge-brush-id` /
    `data-svge-brush-def` (`BrushMeta`, brush_ops.h:501-514) — è ciò che rende lo stroke
    ri-stampabile e reversibile anche senza la palette e su un'altra macchina.
  - La libreria è anche iniettata nella pagina come `window.__svge_brush_library`
    (base64 JSON, `push_library` :712 / `library_b64` :722): canale **solo webview**, letto
    dall'MCP `svg_list_brushes` e dal `doc.brushes` dei .jsx. Il pennello nativo NON lo
    usa (legge il brush attivo dal master).
  - Modello serializzato: `SVGEBrushDef` :40, con **decoder scritto a mano** (:124) perché
    ogni campo scatter/velocity è OPZIONALE sul filo — una libreria salvata da una build
    precedente deve continuare a decodificare. Stessa regola su Windows.
- Dipendenze dal motore: **`core/scene/brush_ops.{h,cpp}` esiste già qui**, completo di
  `BrushDef` con scatter e velocity (brush_ops.h:278-340), `brush_stamp` /
  `brush_stamp_build` / `brush_unstamp` / `brush_expand`, `brush_stamp_placements`,
  `brush_artworks`, `brush_markup_defs` (:436, la cattura dei defs referenziati) e
  `brush_meta_read`. **Quello che manca è tutto lato applicazione**: la palette, lo store
  persistente, la cattura "Define Brush" dalla selezione (sul Mac
  `masterDefineBrushJSON`, SVGESkiaEngine.swift:4444) e la misura del bbox dell'artwork
  (`BrushBBox` è fornito dal chiamante).
- Parti che richiederanno slice dedicate:
  1. **Thumbnail del brush**: il Mac passa markup + defs al decoder SVG di `NSImage`
     (:910). Su Windows serve rasterizzare markup+defs con Skia in una cella 40×40 —
     è la stessa esigenza delle thumbnail di Symbols e Swatches.
  2. **Recupero dei defs da documento vivo** (SVGE-1316, `resolved_defs` :951): un brush
     salvato prima della cattura dei defs si "ripara" leggendo il documento aperto e
     ADOTTA il risultato. Comportamento da replicare per compatibilità delle librerie.
  3. **Velocity dynamics**: dipende dal profilo di velocità del gesto freehand
     (`BrushVelocity`), quindi è agganciata alla slice del pencil, non a questa.
  4. **Il canale `window.__svge_brush_library`**: ha senso solo se e quando Windows
     espone lo stesso surface MCP/.jsx.

## 26. Symbols

- View: `SVGESymbolsPaletteView` GUI/SUI/Panel/SVGESymbolsPalette.swift:746 (body :765);
  store/pannello `SVGESymbolsStore` :125 (`ensure_panel` :499). Menu: **⇧F7**,
  SVGEMenuBuilder.swift:2525 (→ Shift+F7; F7 da solo è AI Console, SVGE-1590).
  `x_new_symbol` :489 è il target di "New Symbol", abilitato solo con selezione (:493).
- Dimensioni: **ridimensionabile su ENTRAMBI gli assi** (SVGE-789) — min **210×300**,
  ideal **242×420** (= 5 colonne: `5·40 + 4·6 + 16 + 2`), max 4000×4000 (:756-759,
  applicati al pannello :508-517). È l'unica palette dopo l'AI Script Console con questa
  libertà; grip in basso a destra (:737). Il frame è persistito ad **ogni move e ogni
  resize** (osservatori :536-546), non solo alla chiusura.
- Controlli:
  - **Picker segmentato Library / Document** in cima (:769), pieno-larghezza.
  - **Tab Library** (:826): popup **sezione** ("All Symbols" + una voce per sezione),
    campo **Search** con lente e ✕ (filtro su nome e chiave), poi UNA ScrollView con
    `LazyVGrid` `.adaptive(min:40, max:40)` spacing 6 e **header di sezione pinnati**
    (mostrati solo in modalità All, :889). Celle **40×40** con la glifo come template
    tinta col colore label (:921). Footer: "N symbols in 12 sections" oppure "N of N
    symbols" oppure "No matching symbols" (:900). Click = piazza; context menu
    "Place on Canvas".
  - **Tab Document** (:951): stessa griglia coi simboli del documento (chip **quadrati**
    40×40, mai cerchi — richiesta esplicita; anello accentColor 2 pt sul chip
    selezionato, :1021); placeholder "Drag artwork here or click New Symbol" quando è
    vuoto; **drop area** su tutta la ScrollView che definisce un simbolo dalla selezione
    corrente (un drag ORIGINATO dentro la webview non arriva ad AppKit come pasteboard
    tipato: il drop usa la selezione, non un payload). Footer: "N symbols" + bottone
    **+**. Un click sul chip **piazza un'istanza** e lo rende il simbolo selezionato
    della palette.
  - **Menu ≡▾** (:801): *New Symbol from Selection*, —, *Duplicate "X"*,
    *Symbol Options…*, *Delete "X"* (i tre disabilitati senza un chip selezionato,
    e nominano il chip), —, *Break Link to Symbol* (disabilitato senza selezione
    sul canvas).
  - **Context menu del chip** (:1058): Place Instance, —, Duplicate Symbol,
    Symbol Options…, —, Delete Symbol. Il right-click seleziona prima il chip, così
    palette e menu non discordano mai.
  - **Dialog "Symbol Options"** (`SVGESymbolOptionsPanel.runModal` :1080, view :1096):
    **finestra modale centrata**, non sheet (la palette è flottante e non ha una finestra
    documento propria), passata da `SVGEModalGuard`; campo "Name:" (label 50 pt allineata
    a destra, TextField 200 pt), riga "N instances in this document", Cancel/OK, minWidth
    300 (:1134). Illustrator ha altri campi (export type, punto di registrazione, 9-slice):
    NON sono mostrati perché non hanno backend qui.
  - **Alert di conferma** su Delete quando `uses > 0` (:408): "Delete the symbol "X"?" +
    "N instances … will be deleted with it. You can undo this with Edit ▸ Undo".
    Un simbolo inutilizzato viene cancellato senza dialogo.
  - **Alert** "No symbol instance is selected" quando Break Link non tocca nulla (:452).
- Operazioni ed etichette di undo — `core/scene/compound_ops.h`, **già presente qui**:
  - *New Symbol from Selection* ⇒ `symbol_create` — **"Create Symbol"**
    (compound_ops.h:104-111): la selezione diventa un `<symbol id viewBox overflow>` in
    `<defs>` con un `<title>`, e sul canvas resta un `<use>` che la sostituisce.
  - **Place** (click sul chip) ⇒ un `<use href="#id">` al centro dell'artboard —
    **"Place Symbol"**. ⚠ Non esiste ancora una funzione di core dedicata: sul Mac è una
    insert etichettata (SVGESkiaEngine.swift:2090-2114, `masterPasteSVG(label: "Place
    Symbol")`, dove l'href **non** viene ri-id-ato). Su Windows va scritta.
  - *Delete* ⇒ `symbol_delete` — **"Delete Symbol"** (compound_ops.h:113): il `<symbol>`
    **e ogni `<use>` che lo referenzia**, in un solo step.
  - *Duplicate* ⇒ `symbol_duplicate` — **"Duplicate Symbol"** (:119-126): copia
    indipendente della definizione, subito dopo l'originale in `<defs>`, senza istanze.
  - *Symbol Options* (rename) ⇒ `symbol_rename` — label **"Symbol Options"** (:128-133);
    un nome invariato **non** produce uno step di undo.
  - *Break Link to Symbol* ⇒ `symbol_break_link` — **"Break Link to Symbol"**
    (:135-153), **uno step per l'intera selezione**: ogni `<use>` selezionato diventa un
    `<g>` che ne eredita identità e paint, con la matrice del viewport ripiegata nel
    `transform`; la definizione resta in `<defs>`.
- Store / persistenza — **il DOCUMENTO, non UserDefaults**:
  - Un simbolo È un `<symbol>` in `<defs>` (viewBox = bbox della selezione, `<title>` =
    nome) e ogni istanza È un `<use href="#id">`: si salvano e si ricaricano con l'SVG,
    senza alcun archivio a fianco. La palette **ricostruisce** la lista dal documento
    (`reload()` :237) ad ogni evento `{symbols_changed:1}` (dispatch webview
    SVGEEditorJS.swift:2011, hook nativo SVGESkiaEngine.swift:4778) e quando una finestra
    diventa main.
  - `SVGESymbolDef` (:88) = id + name (dal `<title>`) + `previewSvg` (un SVG standalone
    per la thumbnail) + **`uses`** (quante istanze), prodotto parsando i `<symbol>`
    (SVGESkiaEngine.swift:4918-4944). `uses` serve alla conferma di Delete e alla riga
    del dialog Options.
  - In UserDefaults finiscono **solo tre cose**: `SVGESymbols.LibrarySection` (la sezione
    scelta nel tab Library, :158-160), `SVGEPaletteVisible.Symbols` e
    `SVGEPalette.Symbols` (:183-184). Nessuna libreria utente persistita.
  - La **selezione di palette** (`selected_id`, :127) e il gate di Break Link
    (`can_break_link`, :146) sono stato volatile: il secondo è spinto dal doc manager ad
    ogni cambio di selezione (SVGEDocManager.swift:775) e calcolato dal MASTER, non
    dall'eco `selected_panel`.
- La **libreria built-in è un ASSET, e in questo repo non c'è ancora**:
  `drawmac/shapelib/*.json` — 12 file letti dal bundle (`load_library` :285), **272
  glifi**: Basic 24, Arrows 35, Symbols 32, Objects 25, Nature 28, User Interface 50,
  Weather & Time 16, Music 18, Flowchart 18, Dialog baloons 11, Cards & Chess 10, Math 5.
  `social.json` esiste nel bundle ma è **deliberatamente escluso** dall'elenco
  (`section_order` :258, richiesta esplicita dell'utente). Sono ~370 KB di JSON
  `{key: "path data"}` da vendorizzare sotto `win/assets/` (o accanto).
- Dipendenze dal motore: `compound_ops` ha già **tutti e cinque** i symbol_*; il renderer
  ha già il `<use>` di un `<symbol>` con la **matrice di viewport implicita** e il clip
  (core/scene/render.cpp:3291-3298), e `scene_queries.cpp:289` include un simbolo piazzato
  nel bbox della selezione. Manca: l'enumerazione dei `<symbol>` del documento con conteggio
  degli `<use>` (l'equivalente di js_list_symbols), la generazione del `previewSvg`, la
  "Place Symbol", e l'allocazione degli id (`svge_next_symbol_id`).
- Parti che richiederanno slice dedicate:
  1. **La conversione "positiva"** dei glifi badge: `SVGEShapePath.positive`
     (GUI/SUI/Shapes/SVGShapeLib.swift:90) toglie il disco decorativo che racchiude il
     glifo, ed è applicata **alla sola categoria "symbol"** (32 path su 272) — applicarla
     a tutta la libreria mangia artwork reale (donut, gear, lenti…). È ~60 righe di
     scanner di subpath da portare: non esiste nel core C++.
  2. **Thumbnail**: `previewSvg` è decodificato da `NSImage`; su Windows serve il
     rasterizzatore Skia (come per Brushes), con memoizzazione per id — il Mac tiene una
     cache di al più 272 immagini 40 pt per lancio.
  3. **EDIT SYMBOL è un residuo dichiarato anche sul Mac** (nota a
     SVGESymbolsPalette.swift:1138): non è un dialogo ma una **modalità di isolamento**
     del canvas (mostrare il contenuto del `<symbol>` da solo, instradarci le modifiche,
     smorzare il resto, breadcrumb di uscita) — la stessa macchina che servirebbe
     all'isolamento dei gruppi, che non esiste ancora da nessuna delle due parti. Non va
     stimata in questa slice.
  4. **Il drop di artwork sulla palette** funziona solo come "definisci dalla selezione":
     un drag originato dentro il canvas non arriva tipato. Su Windows la limitazione
     potrebbe non esserci — è una scelta da fare, non una parità da replicare alla lettera.

---

## Lacune

1. **Palette senza dimensioni esplicite nel codice**: Tools (content-sized: la larghezza discende
   dalla griglia 67 pt, l'altezza dal contenuto — il "67 pt tight" è citato solo nei commenti
   SVGTP:1127 e :1420); per tutte le altre la larghezza dichiarata nel body va letta insieme alla
   normalizzazione del manager (+16 pt di `content_width_padding` e larghezza condivisa del gruppo
   laterale), quindi la larghezza **finestra** effettiva può differire di 16 pt dalla larghezza
   **contenuto** riportata in tabella.
2. **Cinque palette esistono ma non hanno entry point nella UI di produzione**: Colors (voce menu
   rimossa), Hatch (SVGE-1746), Debug e Beta Tools (SVGE-1720), AI Script Console (SK-1734, anche in
   `hidden_palettes`). Nel porting va deciso se replicarle (fedeltà completa al registro) o ometterle
   (fedeltà alla UI spedita).
3. ~~Brushes e Symbols non sono censite qui.~~ **Colmata**: sono ora **§25 e §26**. Restano fuori
   dal registro delle 24 (`SVGEPaletteManager.all`, SVGTP:1071) perché sono self-managed —
   quindi vanno portate con il **loro** ciclo show/hide/persist, non con quello del manager, e
   devono comunque annunciarsi al TAB (`register_self_managed_palette`). Il loro debito residuo è
   di ASSET e non di spec: i 12 file `drawmac/shapelib/*.json` (272 glifi) del tab Library di
   Symbols non sono ancora in questo repo, e i 6 preset di Brushes sono compilati nel sorgente
   Swift, da ritrascrivere verbatim.
4. **Scorciatoie Windows non deterministiche**: i cinque chord Ctrl+Alt+lettera (A, T, P, F, S)
   collidono potenzialmente con AltGr sui layout internazionali; da verificare su tastiera italiana
   prima di fissarli. Ctrl+T e F5 segnalati ma considerati accettabili (parità con Illustrator Windows).
5. **Dettagli non estratti**: il contenuto di `SVGEHatchFillControls` (gli slider del pannello Beta
   Tools ▸ Hatch Fill) non è stato letto; i sotto-menu dei flyout penna e testo della Toolbox sono
   descritti voce per voce in `MANIFEST.md` §1.3 (e i doppi click di ogni slot in §1.4), mentre i
   popover di brush-size / eyedropper / text-pencil restano da specificare campo per campo; le colonne del `textContextBar` della Control Palette sono elencate ma non specificate campo
   per campo. Sono approfondimenti da fare quando si implementa la singola palette.
6. Le posizioni di default del workspace (Tools 16×16 dall'origine dei righelli, Swatches in alto a
   destra, Layers sotto Swatches, Control centrata 16 px dal fondo — SVGTP:2290-2326) sono censite
   nella sezione "Meccanica comune" ma andranno tradotte in coordinate Windows (origine top-left,
   DPI scaling) in fase di implementazione.
