` — uniform vertical rhythm, full-width.
-- **Page header:** always use `
` from `src/components/admin/PageHeader.tsx` — never hand-roll the title + action row.
-- **No width constraints on list pages:** do not add `max-w-*` or `mx-auto` to the page root. Width is controlled by the sidebar layout (`src/app/admin/layout.tsx`).
-- **Detail/form pages** (e.g. OfferEditorClient) may keep their own `max-w-4xl mx-auto` — this rule applies to list/overview pages only.
-- **Cards:** `rounded-lg border border-[#e5e7eb] bg-white p-4`; hover: `hover:shadow-[0_4px_12px_rgba(0,0,0,0.08)]`.
-- **Tables:** `bg-white rounded-xl border border-[#e5e7eb] overflow-hidden`; thead `bg-[#f9f9f9] border-b border-[#e5e7eb]`; row divider `border-b border-[#e5e7eb]`.
-
----
-
-## Interaction
-
-- Clickable elements: `cursor-pointer`
-- Colour transitions: `transition-colors duration-150`
-- Focus ring: `focus:outline-none focus-visible:ring-2 focus-visible:ring-[#1A463C]/30`
-- Minimum touch target on buttons: 44 × 44 px (use `py-2 px-4` minimum or `h-10`)
-- Primary CTA: `bg-[#1A463C] text-white hover:bg-[#163a31] transition-colors`
-- Secondary/ghost CTA: `border border-[#e5e7eb] text-[#1a1a1a] hover:bg-[#f9f9f9] transition-colors`
-- Destructive action: `text-[#dc2626] hover:bg-red-50 transition-colors`
-
----
-
-## Anti-patterns (do not do these)
-
-- **No emoji as UI icons** — use Lucide React icons instead.
-- **No mixed semantic tokens and hex** — pick hex throughout any given page/component.
-- **No per-page `max-w-*` on list pages** — layout width is the sidebar shell's responsibility.
-- **No hand-rolled page header divs** — always use `` to keep title size/weight/colour uniform.
-- **No inline `style={{}}` for colours that have a Tailwind class** — reserve `style` for dynamic values only (e.g. progress bar width percentages).
diff --git a/.planning/milestones/v2.1-ROADMAP.md b/.planning/milestones/v2.1-ROADMAP.md
new file mode 100644
index 0000000..ea29bb5
--- /dev/null
+++ b/.planning/milestones/v2.1-ROADMAP.md
@@ -0,0 +1,64 @@
+# Archivio milestone v2.1 — Offer Studio + CRM
+
+**Fasi previste:** 11–17 · **Consegnate:** 11, 12, 14 · **Aperta:** 2026-06-13 · **Chiusa per reset:** 2026-06-19
+
+> **Ricostruito a posteriori il 2026-08-08.** v2.1 è l'unica milestone rimasta senza
+> archivio: è stata interrotta da un reset di scope e nessuno l'ha chiusa
+> formalmente, così le sue fasi sono rimaste in `.planning/phases/` per due mesi.
+> Questo file è ricostruito da `MILESTONES.md`, dalla tabella Progress di
+> `ROADMAP.md` e dalle cartelle di fase archiviate in [v2.1-phases/](v2.1-phases/).
+> Non esiste un `v2.1-REQUIREMENTS.md`: i 23 requisiti originali sono stati
+> sovrascritti quando `REQUIREMENTS.md` è stato riscritto per v2.3.
+
+## Obiettivo originale
+
+Offer Studio (fasi 11–15) prima di Proposal AI (fasi 16–17): prima una UX dati
+pulita e veloce, poi il builder AI costruito sopra.
+
+## Esito per fase
+
+| Fase | Titolo | Plans | Esito |
+|---|---|---|---|
+| 11 | Catalog Database-View UX + consolidamento legacy | 4/4 | ✅ 2026-06-13 |
+| 12 | Offer Editor Tier A/B/C | 5/5 | ✅ 2026-06-18 |
+| 13 | Workspace — Servizi Attivi | — | ❄️ Congelata → ripresa in **v2.4** |
+| 14 | CRM Attio-style & Fix | 3/3 | ✅ 2026-06-14 |
+| 15 | Dashboard Revenue Stats | — | ❌ Abbandonata (bloccata su un mockup mai fornito) |
+| 16–17 | Proposal AI (impianto originale) | — | ♻️ Ri-scopate in v2.2 (fasi 21–22) |
+
+Documentazione di dettaglio (PLAN, SUMMARY, RESEARCH, VERIFICATION) in
+[v2.1-phases/](v2.1-phases/).
+
+## Cosa è stato consegnato
+
+- **Phase 11 — Catalog Database-View UX** (OFFER-07..10, OFFER-13): il catalogo
+ `services` come tabella a edit inline, tag multi-select, quick-add, ricerca
+ istantanea; consolidamento delle tabelle legacy.
+- **Phase 12 — Offer Editor Tier A/B/C** (OFFER-11, OFFER-15..18): editor offerte
+ con matrice checkbox servizi × tier, totale live, prezzo pubblico manuale, tag su
+ 4 dimensioni, promessa di trasformazione. 55 servizi reali caricati.
+- **Phase 14 — CRM Attio-style** (CRM-08..12): `/admin/leads` ridisegnata con edit
+ inline e tag multi-select; FollowUpWidget in italiano; LeadForm tipizzato;
+ SendQuoteModal ripulita dai rami irraggiungibili.
+
+## Il reset del 2026-06-19
+
+A metà milestone il piano è stato riscritto: la milestone **v2.2 "Sales Loop"**
+sostituisce le fasi residue. Decisioni bloccate in quel momento:
+
+1. L'URL del preventivo è `/preventivo/[slug]`, pubblico.
+2. Si tagliano Forecast, quote builder manuale e Phase 15; `/admin/analytics` viene
+ fusa nella Dashboard.
+3. Il portale post-vendita resta core e non si tocca (Phase 13 congelata).
+4. L'agente AI è "io scelgo l'offerta, l'AI personalizza" leggendo i transcript;
+ provider Claude.
+
+Phase 13 è poi tornata in vita come **milestone v2.4**, consegnata il 2026-08-01.
+
+## Debito lasciato aperto
+
+- Tabelle legacy `service_catalog` / `offer_services` / `offer_micro_services`
+ rimaste come deadweight.
+- `createService` / `serviceSchema` dead code in `src/app/admin/catalog/actions.ts`
+ (Phase 11 Plan 04, annotato in `deferred-items.md`).
+- `offer_micros` senza `created_at` — nessun "tier più vecchio" affidabile.
diff --git a/.planning/phases/11-catalog-database-view-ux-legacy-consolidation/11-01-PLAN.md b/.planning/milestones/v2.1-phases/11-catalog-database-view-ux-legacy-consolidation/11-01-PLAN.md
similarity index 100%
rename from .planning/phases/11-catalog-database-view-ux-legacy-consolidation/11-01-PLAN.md
rename to .planning/milestones/v2.1-phases/11-catalog-database-view-ux-legacy-consolidation/11-01-PLAN.md
diff --git a/.planning/phases/11-catalog-database-view-ux-legacy-consolidation/11-01-SUMMARY.md b/.planning/milestones/v2.1-phases/11-catalog-database-view-ux-legacy-consolidation/11-01-SUMMARY.md
similarity index 100%
rename from .planning/phases/11-catalog-database-view-ux-legacy-consolidation/11-01-SUMMARY.md
rename to .planning/milestones/v2.1-phases/11-catalog-database-view-ux-legacy-consolidation/11-01-SUMMARY.md
diff --git a/.planning/phases/11-catalog-database-view-ux-legacy-consolidation/11-02-PLAN.md b/.planning/milestones/v2.1-phases/11-catalog-database-view-ux-legacy-consolidation/11-02-PLAN.md
similarity index 100%
rename from .planning/phases/11-catalog-database-view-ux-legacy-consolidation/11-02-PLAN.md
rename to .planning/milestones/v2.1-phases/11-catalog-database-view-ux-legacy-consolidation/11-02-PLAN.md
diff --git a/.planning/phases/11-catalog-database-view-ux-legacy-consolidation/11-02-SUMMARY.md b/.planning/milestones/v2.1-phases/11-catalog-database-view-ux-legacy-consolidation/11-02-SUMMARY.md
similarity index 100%
rename from .planning/phases/11-catalog-database-view-ux-legacy-consolidation/11-02-SUMMARY.md
rename to .planning/milestones/v2.1-phases/11-catalog-database-view-ux-legacy-consolidation/11-02-SUMMARY.md
diff --git a/.planning/phases/11-catalog-database-view-ux-legacy-consolidation/11-03-PLAN.md b/.planning/milestones/v2.1-phases/11-catalog-database-view-ux-legacy-consolidation/11-03-PLAN.md
similarity index 100%
rename from .planning/phases/11-catalog-database-view-ux-legacy-consolidation/11-03-PLAN.md
rename to .planning/milestones/v2.1-phases/11-catalog-database-view-ux-legacy-consolidation/11-03-PLAN.md
diff --git a/.planning/phases/11-catalog-database-view-ux-legacy-consolidation/11-03-SUMMARY.md b/.planning/milestones/v2.1-phases/11-catalog-database-view-ux-legacy-consolidation/11-03-SUMMARY.md
similarity index 100%
rename from .planning/phases/11-catalog-database-view-ux-legacy-consolidation/11-03-SUMMARY.md
rename to .planning/milestones/v2.1-phases/11-catalog-database-view-ux-legacy-consolidation/11-03-SUMMARY.md
diff --git a/.planning/phases/11-catalog-database-view-ux-legacy-consolidation/11-04-PLAN.md b/.planning/milestones/v2.1-phases/11-catalog-database-view-ux-legacy-consolidation/11-04-PLAN.md
similarity index 100%
rename from .planning/phases/11-catalog-database-view-ux-legacy-consolidation/11-04-PLAN.md
rename to .planning/milestones/v2.1-phases/11-catalog-database-view-ux-legacy-consolidation/11-04-PLAN.md
diff --git a/.planning/phases/11-catalog-database-view-ux-legacy-consolidation/11-04-SUMMARY.md b/.planning/milestones/v2.1-phases/11-catalog-database-view-ux-legacy-consolidation/11-04-SUMMARY.md
similarity index 100%
rename from .planning/phases/11-catalog-database-view-ux-legacy-consolidation/11-04-SUMMARY.md
rename to .planning/milestones/v2.1-phases/11-catalog-database-view-ux-legacy-consolidation/11-04-SUMMARY.md
diff --git a/.planning/phases/11-catalog-database-view-ux-legacy-consolidation/11-CONTEXT.md b/.planning/milestones/v2.1-phases/11-catalog-database-view-ux-legacy-consolidation/11-CONTEXT.md
similarity index 100%
rename from .planning/phases/11-catalog-database-view-ux-legacy-consolidation/11-CONTEXT.md
rename to .planning/milestones/v2.1-phases/11-catalog-database-view-ux-legacy-consolidation/11-CONTEXT.md
diff --git a/.planning/phases/11-catalog-database-view-ux-legacy-consolidation/11-DISCUSSION-LOG.md b/.planning/milestones/v2.1-phases/11-catalog-database-view-ux-legacy-consolidation/11-DISCUSSION-LOG.md
similarity index 100%
rename from .planning/phases/11-catalog-database-view-ux-legacy-consolidation/11-DISCUSSION-LOG.md
rename to .planning/milestones/v2.1-phases/11-catalog-database-view-ux-legacy-consolidation/11-DISCUSSION-LOG.md
diff --git a/.planning/phases/11-catalog-database-view-ux-legacy-consolidation/11-PATTERNS.md b/.planning/milestones/v2.1-phases/11-catalog-database-view-ux-legacy-consolidation/11-PATTERNS.md
similarity index 100%
rename from .planning/phases/11-catalog-database-view-ux-legacy-consolidation/11-PATTERNS.md
rename to .planning/milestones/v2.1-phases/11-catalog-database-view-ux-legacy-consolidation/11-PATTERNS.md
diff --git a/.planning/phases/11-catalog-database-view-ux-legacy-consolidation/11-REVIEW.md b/.planning/milestones/v2.1-phases/11-catalog-database-view-ux-legacy-consolidation/11-REVIEW.md
similarity index 100%
rename from .planning/phases/11-catalog-database-view-ux-legacy-consolidation/11-REVIEW.md
rename to .planning/milestones/v2.1-phases/11-catalog-database-view-ux-legacy-consolidation/11-REVIEW.md
diff --git a/.planning/phases/11-catalog-database-view-ux-legacy-consolidation/11-VERIFICATION.md b/.planning/milestones/v2.1-phases/11-catalog-database-view-ux-legacy-consolidation/11-VERIFICATION.md
similarity index 100%
rename from .planning/phases/11-catalog-database-view-ux-legacy-consolidation/11-VERIFICATION.md
rename to .planning/milestones/v2.1-phases/11-catalog-database-view-ux-legacy-consolidation/11-VERIFICATION.md
diff --git a/.planning/phases/11-catalog-database-view-ux-legacy-consolidation/deferred-items.md b/.planning/milestones/v2.1-phases/11-catalog-database-view-ux-legacy-consolidation/deferred-items.md
similarity index 100%
rename from .planning/phases/11-catalog-database-view-ux-legacy-consolidation/deferred-items.md
rename to .planning/milestones/v2.1-phases/11-catalog-database-view-ux-legacy-consolidation/deferred-items.md
diff --git a/.planning/phases/12-offer-composition-drag-drop-csv-import/12-01-PLAN.md b/.planning/milestones/v2.1-phases/12-offer-composition-drag-drop-csv-import/12-01-PLAN.md
similarity index 100%
rename from .planning/phases/12-offer-composition-drag-drop-csv-import/12-01-PLAN.md
rename to .planning/milestones/v2.1-phases/12-offer-composition-drag-drop-csv-import/12-01-PLAN.md
diff --git a/.planning/phases/12-offer-composition-drag-drop-csv-import/12-01-SUMMARY.md b/.planning/milestones/v2.1-phases/12-offer-composition-drag-drop-csv-import/12-01-SUMMARY.md
similarity index 100%
rename from .planning/phases/12-offer-composition-drag-drop-csv-import/12-01-SUMMARY.md
rename to .planning/milestones/v2.1-phases/12-offer-composition-drag-drop-csv-import/12-01-SUMMARY.md
diff --git a/.planning/phases/12-offer-composition-drag-drop-csv-import/12-02-PLAN.md b/.planning/milestones/v2.1-phases/12-offer-composition-drag-drop-csv-import/12-02-PLAN.md
similarity index 100%
rename from .planning/phases/12-offer-composition-drag-drop-csv-import/12-02-PLAN.md
rename to .planning/milestones/v2.1-phases/12-offer-composition-drag-drop-csv-import/12-02-PLAN.md
diff --git a/.planning/phases/12-offer-composition-drag-drop-csv-import/12-02-SUMMARY.md b/.planning/milestones/v2.1-phases/12-offer-composition-drag-drop-csv-import/12-02-SUMMARY.md
similarity index 100%
rename from .planning/phases/12-offer-composition-drag-drop-csv-import/12-02-SUMMARY.md
rename to .planning/milestones/v2.1-phases/12-offer-composition-drag-drop-csv-import/12-02-SUMMARY.md
diff --git a/.planning/phases/12-offer-composition-drag-drop-csv-import/12-03-PLAN.md b/.planning/milestones/v2.1-phases/12-offer-composition-drag-drop-csv-import/12-03-PLAN.md
similarity index 100%
rename from .planning/phases/12-offer-composition-drag-drop-csv-import/12-03-PLAN.md
rename to .planning/milestones/v2.1-phases/12-offer-composition-drag-drop-csv-import/12-03-PLAN.md
diff --git a/.planning/phases/12-offer-composition-drag-drop-csv-import/12-03-SUMMARY.md b/.planning/milestones/v2.1-phases/12-offer-composition-drag-drop-csv-import/12-03-SUMMARY.md
similarity index 100%
rename from .planning/phases/12-offer-composition-drag-drop-csv-import/12-03-SUMMARY.md
rename to .planning/milestones/v2.1-phases/12-offer-composition-drag-drop-csv-import/12-03-SUMMARY.md
diff --git a/.planning/phases/12-offer-composition-drag-drop-csv-import/12-04-PLAN.md b/.planning/milestones/v2.1-phases/12-offer-composition-drag-drop-csv-import/12-04-PLAN.md
similarity index 100%
rename from .planning/phases/12-offer-composition-drag-drop-csv-import/12-04-PLAN.md
rename to .planning/milestones/v2.1-phases/12-offer-composition-drag-drop-csv-import/12-04-PLAN.md
diff --git a/.planning/phases/12-offer-composition-drag-drop-csv-import/12-04-SUMMARY.md b/.planning/milestones/v2.1-phases/12-offer-composition-drag-drop-csv-import/12-04-SUMMARY.md
similarity index 100%
rename from .planning/phases/12-offer-composition-drag-drop-csv-import/12-04-SUMMARY.md
rename to .planning/milestones/v2.1-phases/12-offer-composition-drag-drop-csv-import/12-04-SUMMARY.md
diff --git a/.planning/phases/12-offer-composition-drag-drop-csv-import/12-05-PLAN.md b/.planning/milestones/v2.1-phases/12-offer-composition-drag-drop-csv-import/12-05-PLAN.md
similarity index 100%
rename from .planning/phases/12-offer-composition-drag-drop-csv-import/12-05-PLAN.md
rename to .planning/milestones/v2.1-phases/12-offer-composition-drag-drop-csv-import/12-05-PLAN.md
diff --git a/.planning/phases/12-offer-composition-drag-drop-csv-import/12-05-SUMMARY.md b/.planning/milestones/v2.1-phases/12-offer-composition-drag-drop-csv-import/12-05-SUMMARY.md
similarity index 100%
rename from .planning/phases/12-offer-composition-drag-drop-csv-import/12-05-SUMMARY.md
rename to .planning/milestones/v2.1-phases/12-offer-composition-drag-drop-csv-import/12-05-SUMMARY.md
diff --git a/.planning/phases/12-offer-composition-drag-drop-csv-import/12-CONTEXT.md b/.planning/milestones/v2.1-phases/12-offer-composition-drag-drop-csv-import/12-CONTEXT.md
similarity index 100%
rename from .planning/phases/12-offer-composition-drag-drop-csv-import/12-CONTEXT.md
rename to .planning/milestones/v2.1-phases/12-offer-composition-drag-drop-csv-import/12-CONTEXT.md
diff --git a/.planning/phases/12-offer-composition-drag-drop-csv-import/12-RESEARCH.md b/.planning/milestones/v2.1-phases/12-offer-composition-drag-drop-csv-import/12-RESEARCH.md
similarity index 100%
rename from .planning/phases/12-offer-composition-drag-drop-csv-import/12-RESEARCH.md
rename to .planning/milestones/v2.1-phases/12-offer-composition-drag-drop-csv-import/12-RESEARCH.md
diff --git a/.planning/phases/12-offer-composition-drag-drop-csv-import/12-REVIEW.md b/.planning/milestones/v2.1-phases/12-offer-composition-drag-drop-csv-import/12-REVIEW.md
similarity index 100%
rename from .planning/phases/12-offer-composition-drag-drop-csv-import/12-REVIEW.md
rename to .planning/milestones/v2.1-phases/12-offer-composition-drag-drop-csv-import/12-REVIEW.md
diff --git a/.planning/phases/12-offer-composition-drag-drop-csv-import/12-UI-SPEC.md b/.planning/milestones/v2.1-phases/12-offer-composition-drag-drop-csv-import/12-UI-SPEC.md
similarity index 100%
rename from .planning/phases/12-offer-composition-drag-drop-csv-import/12-UI-SPEC.md
rename to .planning/milestones/v2.1-phases/12-offer-composition-drag-drop-csv-import/12-UI-SPEC.md
diff --git a/.planning/phases/12-offer-composition-drag-drop-csv-import/12-VERIFICATION.md b/.planning/milestones/v2.1-phases/12-offer-composition-drag-drop-csv-import/12-VERIFICATION.md
similarity index 100%
rename from .planning/phases/12-offer-composition-drag-drop-csv-import/12-VERIFICATION.md
rename to .planning/milestones/v2.1-phases/12-offer-composition-drag-drop-csv-import/12-VERIFICATION.md
diff --git a/.planning/phases/14-crm-attio-style-fix/14-01-PLAN.md b/.planning/milestones/v2.1-phases/14-crm-attio-style-fix/14-01-PLAN.md
similarity index 100%
rename from .planning/phases/14-crm-attio-style-fix/14-01-PLAN.md
rename to .planning/milestones/v2.1-phases/14-crm-attio-style-fix/14-01-PLAN.md
diff --git a/.planning/phases/14-crm-attio-style-fix/14-01-SUMMARY.md b/.planning/milestones/v2.1-phases/14-crm-attio-style-fix/14-01-SUMMARY.md
similarity index 100%
rename from .planning/phases/14-crm-attio-style-fix/14-01-SUMMARY.md
rename to .planning/milestones/v2.1-phases/14-crm-attio-style-fix/14-01-SUMMARY.md
diff --git a/.planning/phases/14-crm-attio-style-fix/14-02-PLAN.md b/.planning/milestones/v2.1-phases/14-crm-attio-style-fix/14-02-PLAN.md
similarity index 100%
rename from .planning/phases/14-crm-attio-style-fix/14-02-PLAN.md
rename to .planning/milestones/v2.1-phases/14-crm-attio-style-fix/14-02-PLAN.md
diff --git a/.planning/phases/14-crm-attio-style-fix/14-02-SUMMARY.md b/.planning/milestones/v2.1-phases/14-crm-attio-style-fix/14-02-SUMMARY.md
similarity index 100%
rename from .planning/phases/14-crm-attio-style-fix/14-02-SUMMARY.md
rename to .planning/milestones/v2.1-phases/14-crm-attio-style-fix/14-02-SUMMARY.md
diff --git a/.planning/phases/14-crm-attio-style-fix/14-03-PLAN.md b/.planning/milestones/v2.1-phases/14-crm-attio-style-fix/14-03-PLAN.md
similarity index 100%
rename from .planning/phases/14-crm-attio-style-fix/14-03-PLAN.md
rename to .planning/milestones/v2.1-phases/14-crm-attio-style-fix/14-03-PLAN.md
diff --git a/.planning/phases/14-crm-attio-style-fix/14-03-SUMMARY.md b/.planning/milestones/v2.1-phases/14-crm-attio-style-fix/14-03-SUMMARY.md
similarity index 100%
rename from .planning/phases/14-crm-attio-style-fix/14-03-SUMMARY.md
rename to .planning/milestones/v2.1-phases/14-crm-attio-style-fix/14-03-SUMMARY.md
diff --git a/.planning/phases/14-crm-attio-style-fix/14-PATTERNS.md b/.planning/milestones/v2.1-phases/14-crm-attio-style-fix/14-PATTERNS.md
similarity index 100%
rename from .planning/phases/14-crm-attio-style-fix/14-PATTERNS.md
rename to .planning/milestones/v2.1-phases/14-crm-attio-style-fix/14-PATTERNS.md
diff --git a/.planning/phases/14-crm-attio-style-fix/14-RESEARCH.md b/.planning/milestones/v2.1-phases/14-crm-attio-style-fix/14-RESEARCH.md
similarity index 100%
rename from .planning/phases/14-crm-attio-style-fix/14-RESEARCH.md
rename to .planning/milestones/v2.1-phases/14-crm-attio-style-fix/14-RESEARCH.md
diff --git a/.planning/phases/14-crm-attio-style-fix/14-REVIEW.md b/.planning/milestones/v2.1-phases/14-crm-attio-style-fix/14-REVIEW.md
similarity index 100%
rename from .planning/phases/14-crm-attio-style-fix/14-REVIEW.md
rename to .planning/milestones/v2.1-phases/14-crm-attio-style-fix/14-REVIEW.md
diff --git a/.planning/phases/14-crm-attio-style-fix/14-UI-SPEC.md b/.planning/milestones/v2.1-phases/14-crm-attio-style-fix/14-UI-SPEC.md
similarity index 100%
rename from .planning/phases/14-crm-attio-style-fix/14-UI-SPEC.md
rename to .planning/milestones/v2.1-phases/14-crm-attio-style-fix/14-UI-SPEC.md
diff --git a/.planning/phases/14-crm-attio-style-fix/14-VERIFICATION.md b/.planning/milestones/v2.1-phases/14-crm-attio-style-fix/14-VERIFICATION.md
similarity index 100%
rename from .planning/phases/14-crm-attio-style-fix/14-VERIFICATION.md
rename to .planning/milestones/v2.1-phases/14-crm-attio-style-fix/14-VERIFICATION.md
diff --git a/.planning/phases/14-crm-attio-style-fix/deferred-items.md b/.planning/milestones/v2.1-phases/14-crm-attio-style-fix/deferred-items.md
similarity index 100%
rename from .planning/phases/14-crm-attio-style-fix/deferred-items.md
rename to .planning/milestones/v2.1-phases/14-crm-attio-style-fix/deferred-items.md
diff --git a/.planning/phases/18-cleanup-consolidamento/18-01-PLAN.md b/.planning/milestones/v2.2-phases/18-cleanup-consolidamento/18-01-PLAN.md
similarity index 100%
rename from .planning/phases/18-cleanup-consolidamento/18-01-PLAN.md
rename to .planning/milestones/v2.2-phases/18-cleanup-consolidamento/18-01-PLAN.md
diff --git a/.planning/phases/18-cleanup-consolidamento/18-01-SUMMARY.md b/.planning/milestones/v2.2-phases/18-cleanup-consolidamento/18-01-SUMMARY.md
similarity index 100%
rename from .planning/phases/18-cleanup-consolidamento/18-01-SUMMARY.md
rename to .planning/milestones/v2.2-phases/18-cleanup-consolidamento/18-01-SUMMARY.md
diff --git a/.planning/phases/18-cleanup-consolidamento/18-02-PLAN.md b/.planning/milestones/v2.2-phases/18-cleanup-consolidamento/18-02-PLAN.md
similarity index 100%
rename from .planning/phases/18-cleanup-consolidamento/18-02-PLAN.md
rename to .planning/milestones/v2.2-phases/18-cleanup-consolidamento/18-02-PLAN.md
diff --git a/.planning/phases/18-cleanup-consolidamento/18-02-SUMMARY.md b/.planning/milestones/v2.2-phases/18-cleanup-consolidamento/18-02-SUMMARY.md
similarity index 100%
rename from .planning/phases/18-cleanup-consolidamento/18-02-SUMMARY.md
rename to .planning/milestones/v2.2-phases/18-cleanup-consolidamento/18-02-SUMMARY.md
diff --git a/.planning/phases/18-cleanup-consolidamento/18-03-PLAN.md b/.planning/milestones/v2.2-phases/18-cleanup-consolidamento/18-03-PLAN.md
similarity index 100%
rename from .planning/phases/18-cleanup-consolidamento/18-03-PLAN.md
rename to .planning/milestones/v2.2-phases/18-cleanup-consolidamento/18-03-PLAN.md
diff --git a/.planning/phases/18-cleanup-consolidamento/18-03-SUMMARY.md b/.planning/milestones/v2.2-phases/18-cleanup-consolidamento/18-03-SUMMARY.md
similarity index 100%
rename from .planning/phases/18-cleanup-consolidamento/18-03-SUMMARY.md
rename to .planning/milestones/v2.2-phases/18-cleanup-consolidamento/18-03-SUMMARY.md
diff --git a/.planning/phases/19-pipeline-crm-kanban/19-01-PLAN.md b/.planning/milestones/v2.2-phases/19-pipeline-crm-kanban/19-01-PLAN.md
similarity index 100%
rename from .planning/phases/19-pipeline-crm-kanban/19-01-PLAN.md
rename to .planning/milestones/v2.2-phases/19-pipeline-crm-kanban/19-01-PLAN.md
diff --git a/.planning/phases/19-pipeline-crm-kanban/19-01-SUMMARY.md b/.planning/milestones/v2.2-phases/19-pipeline-crm-kanban/19-01-SUMMARY.md
similarity index 100%
rename from .planning/phases/19-pipeline-crm-kanban/19-01-SUMMARY.md
rename to .planning/milestones/v2.2-phases/19-pipeline-crm-kanban/19-01-SUMMARY.md
diff --git a/.planning/phases/19-pipeline-crm-kanban/19-RESEARCH.md b/.planning/milestones/v2.2-phases/19-pipeline-crm-kanban/19-RESEARCH.md
similarity index 100%
rename from .planning/phases/19-pipeline-crm-kanban/19-RESEARCH.md
rename to .planning/milestones/v2.2-phases/19-pipeline-crm-kanban/19-RESEARCH.md
diff --git a/.planning/phases/19-pipeline-crm-kanban/19-VERIFICATION.md b/.planning/milestones/v2.2-phases/19-pipeline-crm-kanban/19-VERIFICATION.md
similarity index 100%
rename from .planning/phases/19-pipeline-crm-kanban/19-VERIFICATION.md
rename to .planning/milestones/v2.2-phases/19-pipeline-crm-kanban/19-VERIFICATION.md
diff --git a/.planning/phases/20-knowledge-base-cliente/20-01-PLAN.md b/.planning/milestones/v2.2-phases/20-knowledge-base-cliente/20-01-PLAN.md
similarity index 100%
rename from .planning/phases/20-knowledge-base-cliente/20-01-PLAN.md
rename to .planning/milestones/v2.2-phases/20-knowledge-base-cliente/20-01-PLAN.md
diff --git a/.planning/phases/20-knowledge-base-cliente/20-01-SUMMARY.md b/.planning/milestones/v2.2-phases/20-knowledge-base-cliente/20-01-SUMMARY.md
similarity index 100%
rename from .planning/phases/20-knowledge-base-cliente/20-01-SUMMARY.md
rename to .planning/milestones/v2.2-phases/20-knowledge-base-cliente/20-01-SUMMARY.md
diff --git a/.planning/phases/20-knowledge-base-cliente/20-02-PLAN.md b/.planning/milestones/v2.2-phases/20-knowledge-base-cliente/20-02-PLAN.md
similarity index 100%
rename from .planning/phases/20-knowledge-base-cliente/20-02-PLAN.md
rename to .planning/milestones/v2.2-phases/20-knowledge-base-cliente/20-02-PLAN.md
diff --git a/.planning/phases/20-knowledge-base-cliente/20-02-SUMMARY.md b/.planning/milestones/v2.2-phases/20-knowledge-base-cliente/20-02-SUMMARY.md
similarity index 100%
rename from .planning/phases/20-knowledge-base-cliente/20-02-SUMMARY.md
rename to .planning/milestones/v2.2-phases/20-knowledge-base-cliente/20-02-SUMMARY.md
diff --git a/.planning/phases/20-knowledge-base-cliente/20-03-PLAN.md b/.planning/milestones/v2.2-phases/20-knowledge-base-cliente/20-03-PLAN.md
similarity index 100%
rename from .planning/phases/20-knowledge-base-cliente/20-03-PLAN.md
rename to .planning/milestones/v2.2-phases/20-knowledge-base-cliente/20-03-PLAN.md
diff --git a/.planning/phases/20-knowledge-base-cliente/20-03-SUMMARY.md b/.planning/milestones/v2.2-phases/20-knowledge-base-cliente/20-03-SUMMARY.md
similarity index 100%
rename from .planning/phases/20-knowledge-base-cliente/20-03-SUMMARY.md
rename to .planning/milestones/v2.2-phases/20-knowledge-base-cliente/20-03-SUMMARY.md
diff --git a/.planning/phases/20-knowledge-base-cliente/20-CONTEXT.md b/.planning/milestones/v2.2-phases/20-knowledge-base-cliente/20-CONTEXT.md
similarity index 100%
rename from .planning/phases/20-knowledge-base-cliente/20-CONTEXT.md
rename to .planning/milestones/v2.2-phases/20-knowledge-base-cliente/20-CONTEXT.md
diff --git a/.planning/phases/20-knowledge-base-cliente/20-DISCUSSION-LOG.md b/.planning/milestones/v2.2-phases/20-knowledge-base-cliente/20-DISCUSSION-LOG.md
similarity index 100%
rename from .planning/phases/20-knowledge-base-cliente/20-DISCUSSION-LOG.md
rename to .planning/milestones/v2.2-phases/20-knowledge-base-cliente/20-DISCUSSION-LOG.md
diff --git a/.planning/phases/21-agente-ai-generazione-preventivo/21-01-SUMMARY.md b/.planning/milestones/v2.2-phases/21-agente-ai-generazione-preventivo/21-01-SUMMARY.md
similarity index 100%
rename from .planning/phases/21-agente-ai-generazione-preventivo/21-01-SUMMARY.md
rename to .planning/milestones/v2.2-phases/21-agente-ai-generazione-preventivo/21-01-SUMMARY.md
diff --git a/.planning/phases/21-agente-ai-generazione-preventivo/21-CONTEXT.md b/.planning/milestones/v2.2-phases/21-agente-ai-generazione-preventivo/21-CONTEXT.md
similarity index 100%
rename from .planning/phases/21-agente-ai-generazione-preventivo/21-CONTEXT.md
rename to .planning/milestones/v2.2-phases/21-agente-ai-generazione-preventivo/21-CONTEXT.md
diff --git a/.planning/phases/21-agente-ai-generazione-preventivo/21-DISCUSSION-LOG.md b/.planning/milestones/v2.2-phases/21-agente-ai-generazione-preventivo/21-DISCUSSION-LOG.md
similarity index 100%
rename from .planning/phases/21-agente-ai-generazione-preventivo/21-DISCUSSION-LOG.md
rename to .planning/milestones/v2.2-phases/21-agente-ai-generazione-preventivo/21-DISCUSSION-LOG.md
diff --git a/.planning/phases/21-agente-ai-generazione-preventivo/21-PLAN.md b/.planning/milestones/v2.2-phases/21-agente-ai-generazione-preventivo/21-PLAN.md
similarity index 100%
rename from .planning/phases/21-agente-ai-generazione-preventivo/21-PLAN.md
rename to .planning/milestones/v2.2-phases/21-agente-ai-generazione-preventivo/21-PLAN.md
diff --git a/.planning/phases/22-pagina-pubblica-preventivo/22-01-SUMMARY.md b/.planning/milestones/v2.2-phases/22-pagina-pubblica-preventivo/22-01-SUMMARY.md
similarity index 100%
rename from .planning/phases/22-pagina-pubblica-preventivo/22-01-SUMMARY.md
rename to .planning/milestones/v2.2-phases/22-pagina-pubblica-preventivo/22-01-SUMMARY.md
diff --git a/.planning/milestones/v2.3-REQUIREMENTS.md b/.planning/milestones/v2.3-REQUIREMENTS.md
new file mode 100644
index 0000000..0119316
--- /dev/null
+++ b/.planning/milestones/v2.3-REQUIREMENTS.md
@@ -0,0 +1,69 @@
+# Requirements: ClientHub v2.3 Email & Accesso
+
+**Defined:** 2026-06-21
+**Core Value:** Il cliente apre il link e vede esattamente a che punto è il suo progetto, cosa deve ancora succedere e cosa ha già approvato — senza dover scrivere email per chiedere aggiornamenti.
+
+## v2.3 Requirements
+
+### Email OTP Gate (AUTH-OTP-01)
+
+Portale cliente blindato da email OTP. Nuovo `client_emails` table (whitelist) + `otp_codes` table (codice, email, expires_at, consumed). Resend come provider email. Sessione **90 giorni** con cookie dopo verifica, revocabile dall'admin.
+
+- [x] **OTP-01**: Admin può aggiungere e rimuovere email dalla whitelist di ogni cliente nell'admin UI
+- [x] **OTP-02**: Cliente senza sessione OTP vede una schermata "inserisci email" invece della dashboard
+- [x] **OTP-03**: Sistema invia OTP via Resend solo se l'email inserita è nella whitelist di quel cliente
+- [x] **OTP-04**: Cliente inserisce il codice OTP ricevuto e ottiene sessione autenticata (cookie **90 giorni**)
+- [x] **OTP-05**: Codici OTP scadono dopo 15 minuti dall'invio
+- [x] **OTP-06**: Endpoint OTP è rate-limited per prevenire brute force
+- [x] **OTP-07**: Messaggi di errore OTP non rivelano se l'email è in whitelist o no (no enumeration)
+- [x] **OTP-08**: Admin può revocare in blocco tutte le sessioni attive di un cliente
+
+> **[2026-07-28] Modifiche alla spec del 2026-06-21**, decise in sessione:
+> - Sessione **90 giorni** invece di 30 (rientro più fluido), compensata da OTP-08.
+> - **SEND-01/SEND-02 spostati al backlog v2.4**: il preventivo si invia a mano, l'automazione non serve ora. Phase 23 si è ridotta alla sola infrastruttura Resend, che l'OTP usa comunque.
+> - **Il gate NON sta nel layout** ma in cima a ogni page sotto `/client/[token]/`. Nell'App Router il segmento `page` viene renderizzato in parallelo al layout: gattare nel layout nascondeva la dashboard a schermo ma lasciava fasi, task e pagamenti nel payload RSC dell'HTML (verificato: 46.907 byte con i dati → 17.594 dopo il fix). Helper: `src/lib/client-gate.ts`.
+
+## v2.4+ Backlog
+
+### Conversione Commerciale
+
+- **PROP-03**: Stripe Payment Link su deck pubblico `/preventivo/[slug]`
+- **PROP-04**: Auto-provisioning cliente/progetto/fasi al "Vinto" nel CRM
+- **SEND-01/SEND-02**: invio del link `/preventivo/[slug]` via email dall'admin UI — *rinviato da v2.3 il 2026-07-28, l'invio si fa a mano. L'infrastruttura Resend (`src/lib/mailer.ts`) è già pronta, manca solo l'azione e il pulsante.*
+
+### Post-Vendita
+
+- **Phase 13**: Gestione servizi attivi/ricorrenti post-vendita nel portale cliente (congelata da v2.1)
+
+## Out of Scope
+
+| Feature | Reason |
+|---------|--------|
+| Self-registration cliente | Solo whitelist admin-gestita — nessun accesso senza approvazione esplicita |
+| Magic link senza OTP | OTP è più sicuro e già deciso come design; magic link = scope creep |
+| Email marketing / newsletter | Non pertinente al portale |
+| Multi-admin | Ancora single admin per ora |
+
+## Traceability
+
+| Requirement | Phase | Status |
+|-------------|-------|--------|
+| OTP-01 | Phase 24 | ✅ Done (2026-07-28) |
+| OTP-02 | Phase 25 | ✅ Done (2026-07-28) |
+| OTP-03 | Phase 25 | ✅ Done (2026-07-28) |
+| OTP-04 | Phase 25 | ✅ Done (2026-07-28) |
+| OTP-05 | Phase 25 | ✅ Done (2026-07-28) |
+| OTP-06 | Phase 25 | ✅ Done (2026-07-28) |
+| OTP-07 | Phase 25 | ✅ Done (2026-07-28) |
+| OTP-08 | Phase 24 | ✅ Done (2026-07-28) |
+| SEND-01 | — | ⏭️ Rinviato a v2.4 |
+| SEND-02 | — | ⏭️ Rinviato a v2.4 |
+
+**Coverage:**
+- v2.3 requirements: 8 in scope (OTP-01…08) + 2 rinviati
+- Implementati: 8/8 ✓ — verificati con 9 test E2E in locale contro il DB di produzione
+- **Non ancora in produzione**: il codice è scritto e testato ma NON pushato. Vedi i blocchi in `STATE.md`.
+
+---
+*Requirements defined: 2026-06-21*
+*Last updated: 2026-07-28 — sessione 90gg, OTP-08 aggiunto, SEND-01/02 rinviati, OTP-01…08 implementati*
diff --git a/.planning/milestones/v2.3-ROADMAP.md b/.planning/milestones/v2.3-ROADMAP.md
new file mode 100644
index 0000000..aaa8ed0
--- /dev/null
+++ b/.planning/milestones/v2.3-ROADMAP.md
@@ -0,0 +1,99 @@
+# Archivio milestone v2.3 — Email & Accesso
+
+**Fasi:** 23–25 · **Aperta:** 2026-06-21 · **Shipped:** 2026-07-29 (commit `27da969`)
+**Requisiti:** [v2.3-REQUIREMENTS.md](v2.3-REQUIREMENTS.md)
+
+> **Nota di archivio.** v2.3 è stata eseguita **fuori dal ciclo GSD**: non sono mai
+> esistite cartelle `phases/23`, `24`, `25` con PLAN/SUMMARY. Questo file *è*
+> la documentazione della milestone — non cercare altrove.
+
+## Obiettivo
+
+Aggiungere uno strato email all'app: gate OTP per il portale cliente e invio del
+link preventivo dall'admin, con un'unica integrazione Resend condivisa.
+
+Il portale non doveva più essere apribile col solo link: chiunque avesse l'URL
+vedeva il progetto del cliente.
+
+## Fasi
+
+### Phase 23 — Resend Setup ✅ 2026-07-28
+
+**Goal:** infrastruttura email condivisa.
+**Requisiti:** SEND-01, SEND-02 (poi ridotti — vedi sotto).
+
+Consegnato: `resend@6.18.1`, `src/lib/mailer.ts` (Result tipizzato, mai un catch
+silenzioso), template OTP in italiano. `RESEND_API_KEY` e `RESEND_FROM` configurate
+su Coolify (production **e** preview).
+
+**Riduzione di scope del 2026-07-28:** SEND-01/SEND-02 (invio del preventivo via
+email dall'admin) spostati al backlog. Il preventivo si manda a mano; l'automazione
+non serviva subito. Phase 23 si è ridotta alla sola infrastruttura Resend, che il
+gate OTP usa comunque.
+
+### Phase 24 — Schema + Whitelist Admin ✅ 2026-07-28
+
+**Goal:** l'admin gestisce la whitelist email di ogni cliente; tabelle pronte per il gate.
+**Requisiti:** OTP-01. **Dipende da:** Phase 23.
+
+Migration `0015_otp_access.sql`, **additiva pura**, applicata a prod via SSH prima
+del codice dipendente: `client_emails` (whitelist, unique case-insensitive),
+`otp_codes` (hash del codice, mai il codice in chiaro), `clients.sessions_valid_from`
+(revoca in blocco). Conteggi pre/post identici sulle tabelle protette —
+clients 4 / projects 5 / payments 11 / phases 10.
+
+UI: sezione "Accessi al portale" in `/admin/clients/[id]` — aggiungi/rimuovi email,
+"Revoca sessioni attive". Server actions in `clients/[id]/actions.ts`.
+
+### Phase 25 — OTP Gate + Sessione ✅ 2026-07-29
+
+**Goal:** `/client/[token]/*` richiede verifica OTP prima di mostrare la dashboard.
+**Requisiti:** OTP-02..OTP-07. **Dipende da:** Phase 24.
+
+Consegnato: `src/lib/otp.ts` (codice 6 cifre CSPRNG, hash SHA-256 con
+`NEXTAUTH_SECRET`+clientId, TTL 15 minuti, monouso, max 5 tentativi),
+`src/lib/client-session.ts` (cookie HMAC per-cliente `ch_sess_`, httpOnly +
+secure + SameSite=lax, `path=/client`), `src/lib/client-gate.ts`, le route
+`/api/client/otp/request|verify`, il componente `OtpGate`.
+
+**Scostamento dalla spec del 21/06:** sessione **90 giorni** invece di 30 — rientro
+più fluido, compensato da OTP-08 (revoca in blocco lato admin).
+
+## Catena di dipendenze
+
+```
+Phase 23 (Resend SDK + env)
+ └── Phase 24 (schema additivo: client_emails + otp_codes)
+ └── Phase 25 (gate OTP + sessione cookie 90gg)
+```
+
+## Copertura requisiti
+
+| Requisito | Fase | Esito |
+|---|---|---|
+| SEND-01, SEND-02 | 23 | ⏭ Rinviati al backlog il 2026-07-28 |
+| OTP-01 | 24 | ✅ |
+| OTP-02 … OTP-07 | 25 | ✅ |
+| OTP-08 (revoca) | 24 | ✅ |
+
+## Verifica in produzione (2026-07-29, `hub.iamcavalli.net`)
+
+Gate mostrato senza cookie e **zero dati di progetto nell'HTML** (12.487 byte);
+email fuori e dentro whitelist danno risposta identica e solo la seconda genera un
+OTP; codice sbagliato rifiutato, corretto accettato; cookie `ch_sess_` con
+`Secure` + `HttpOnly` + `SameSite=lax` + `Max-Age=7776000`; rientro col cookie
+mostra la dashboard; la sessione di un cliente sull'URL di un altro mostra il gate.
+Nessun errore d'invio nei log del container. Dati di test rimossi, tabelle protette
+invariate.
+
+## Lezioni
+
+Le due lezioni operative di questa milestone (il gate non va nel layout App Router;
+ricreare il dominio su Resend rigenera la chiave DKIM) sono in `STATUS.md`,
+sezione "Lezioni operative" — è lì che si vanno a cercare.
+
+## Strascico alla chiusura
+
+La whitelist è stata seedata solo con `mario@test.it` (cliente di test). Tre clienti
+reali su quattro hanno whitelist vuota e finché lo è **il loro portale non è
+accessibile**. Voce aperta in `STATUS.md`.
diff --git a/.planning/phases/13-ciclo-vita-servizi-ricorrenti/13-SUMMARY.md b/.planning/phases/13-ciclo-vita-servizi-ricorrenti/13-SUMMARY.md
new file mode 100644
index 0000000..249c436
--- /dev/null
+++ b/.planning/phases/13-ciclo-vita-servizi-ricorrenti/13-SUMMARY.md
@@ -0,0 +1,55 @@
+# Phase 13 — Ciclo di vita dei servizi ricorrenti
+
+**Milestone:** v2.4 Post-vendita · **Stato:** ✅ in produzione, verificata end-to-end
+**Consegnata:** 2026-08-01 · **Commit:** `5177a37` · **Migration:** `0016_project_offer_lifecycle.sql`
+
+> **Ricostruito a posteriori il 2026-08-08** dal commit, dalla migration e da
+> `STATUS.md`. La fase è stata eseguita fuori dal ciclo GSD: non esiste un PLAN.
+> Phase 13 nasce congelata in v2.1 (giugno) e riaperta come milestone v2.4.
+
+## Il problema
+
+Un retainer, una volta assegnato, non si poteva fermare. `project_offers` aveva solo
+`start_date`, e il ramo retainer di `src/lib/forecast-queries.ts` sommava il canone a
+**ogni mese** dell'orizzonte da lì in poi, per sempre. Un cliente che disdiceva
+continuava a gonfiare il forecast a 12 mesi e a vedersi l'abbonamento attivo nel
+proprio portale.
+
+## Cosa è stato fatto
+
+**Schema** — migration `0016`, additiva pura, applicata a prod **prima** del push:
+`project_offers.status` (`attivo|sospeso|cessato`, CHECK `NOT VALID` per evitare un
+lock lungo) e `project_offers.end_date` (nullable, NULL = continuativo). Default
+`'attivo'` così ogni riga esistente conserva esattamente il comportamento precedente.
+Nessun DROP, nessun TRUNCATE. Idempotente.
+
+**Forecast** — i retainer si fermano a `end_date`; sospesi e cessati escono dal
+calcolo. `getOffersSoldBreakdown` **non** filtra per stato di proposito: è uno
+storico di vendita, ed escludere le cessate riscriverebbe il passato.
+`offersAcceptedTotal` esclude le cessate (default del piano pagamenti).
+
+**Admin** — comandi Sospendi / Riattiva / Cessa più data di fine nella tab Offerte,
+mostrati solo per i ricorrenti. `setProjectOfferLifecycle` valida con Zod e filtra
+**anche per `project_id`**, così un id arbitrario non può toccare un altro progetto.
+
+**Portale cliente** — "Attivo dal", "fino al", badge *In pausa*, "Canone mensile" al
+posto di "Prezzo finale". Le offerte cessate non arrivano mai al client.
+
+**Fix collaterale** — un retainer sospeso continuava a intestare i pagamenti "Totale
+Pagamento Mensile" e a sovrascriverne l'importo.
+
+## Decisioni
+
+- **Storico di vendita ≠ forecast.** Due letture diverse degli stessi dati: il
+ breakdown del venduto ignora lo stato, il forecast lo rispetta. Unificarle
+ avrebbe fatto sparire fatturato già incassato dai report.
+- **Default `'attivo'` invece di NULL.** Rende la migration a comportamento
+ invariato senza una backfill separata.
+- **Filtro per `project_id` nell'action**, non solo per id dell'offerta: difesa in
+ profondità contro un id manipolato.
+
+## Fuori scope, rimandato
+
+Tracciamento dei canoni mese per mese (agosto pagato / settembre no). Serve una
+tabella nuova: `payments` è protetta dai vincoli di Data Safety e la sua riscalatura
+è pensata per i piani una tantum. Voce di backlog in `REQUIREMENTS.md`.
diff --git a/.planning/phases/26-anteprima-admin-e-login/26-SUMMARY.md b/.planning/phases/26-anteprima-admin-e-login/26-SUMMARY.md
new file mode 100644
index 0000000..33dfc88
--- /dev/null
+++ b/.planning/phases/26-anteprima-admin-e-login/26-SUMMARY.md
@@ -0,0 +1,71 @@
+# Phase 26 — Anteprima admin del portale + toggle password sul login
+
+**Milestone:** v2.4 Post-vendita · **Stato:** ✅ in produzione (deploy Coolify 2026-08-08)
+**Commit:** `09a5b1f` (toggle password) · `187550f` (anteprima admin)
+
+> **Ricostruito a posteriori il 2026-08-08.** Lavoro non pianificato in roadmap,
+> nato da due attriti d'uso reali. 26 è il primo numero di fase libero.
+
+## 1. Toggle mostra/nascondi password — `09a5b1f`
+
+Il campo password del login admin non offriva modo di rileggere quanto digitato: un
+accesso fallito era indistinguibile da un errore di battitura.
+
+Toggle **inline**, non un nuovo primitivo in `ui/`: `type="password"` compare una
+sola volta in tutto il codebase, un'astrazione avrebbe avuto un solo consumatore.
+`type="button"` perché dentro un `