# Longevity — l'interfaccia: piano di implementazione > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. **Goal:** dare una faccia al fascicolo del cliente — il questionario che si compila in pagina e il referto che il cliente legge, col radar a sette assi. **Architecture:** pagine Astro dentro il sito esistente, sotto `/longevity/`, con un layout dedicato e un foglio di stile prefissato. Il contenuto statico è Astro; React solo dove serve interattività vera — il questionario a blocchi e il radar. I dati arrivano dal motore già costruito, mai da query scritte nelle pagine. **Tech Stack:** Astro, React, recharts (già in casa), better-sqlite3, vitest. Nessuna dipendenza nuova. **Spec:** `docs/specs/2026-08-21-longevity-design.md` **Piani precedenti, già eseguiti:** `2026-08-21-longevity-strato-dati.md` e `2026-08-22-longevity-motore.md`. Lo strato dati e il motore esistono, sono testati, e nessuna pagina li usa ancora. ## Global Constraints - Branch **`feat/longevity`**. `main` non si tocca, non si deploya, non si pusha senza che Adriano lo chieda. - **Nessuna dipendenza npm nuova.** - Test in `tests/longevity/`, eseguiti con `npm test`. Codice e commenti in italiano. - ⚠️ **La suite parte con un rosso che non è nostro:** `tests/modifiche-agosto.test.ts` (test del sito disallineato su `main`, fuori perimetro). L'atteso è **1 fallito pre-esistente**, il resto verde. Non ripararlo. - ⚠️ **`npx tsc --noEmit` deve restare pulito.** In questo lavoro il tipo è il meccanismo di sicurezza: un typecheck rosso è un cancello che nessuno guarda più. - **Nessun dato reale di persone** nelle fixture. ## Le due regole di prodotto che l'interfaccia non può violare **1. Un punteggio insufficiente non si mostra come numero.** Il motore restituisce un tipo che nel ramo insufficiente **non ha il campo `valore`**: la pagina non ha da dove prenderlo. Ma la barriera finisce lì — la tabella dei punteggi è letta da una funzione tipata (`leggiScore`), e **le pagine devono usare quella**, mai una query propria. Una `SELECT valore FROM score` scritta in una pagina riapre il buco. **2. Il colore non giudica il corpo.** Niente semaforo verde/giallo/rosso sui punteggi: il servizio è premium ma **non clinico**, e un rosso su «Composizione Corporea» detto a una persona è un giudizio, non un'informazione. I punteggi si esprimono con l'**intensità** del colore d'accento del sito. L'unico colore di segnale — il mattone `#b05a4e` già presente nel foglio di Stress Index — è riservato ai **valori fuori range**, che segnalano un problema **della misura**, non della persona. ## Il gesto che questa interfaccia deve avere Il radar mostra **quello che sappiamo** come area piena, e dove la misura non basta lascia un **perimetro tratteggiato** con, sotto, cosa manca per completarlo. Non un buco, non un errore: un invito. Regge tre cose insieme — la regola di prodotto («tratteggiato, mai un numero pieno fasullo»), la leva commerciale che il cliente voleva per il livello avanzato, e una posizione onesta: *non ti diciamo un numero che non sappiamo*. ⚠️ **Con i dati di oggi sei assi su sette saranno tratteggiati**, perché nel registro c'è solo il questionario e i test fisici arrivano col piano degli import. È atteso: chi guarda la prima dashboard non deve scambiarlo per un guasto. ## Struttura dei file | File | Responsabilità | |---|---| | `src/layouts/Longevity.astro` | layout della piattaforma: intestazione, niente header pubblico | | `src/styles/longevity.css` | stile prefissato `.lg`, globale (deve raggiungere le isole React) | | `src/pages/longevity/questionario.astro` | la pagina del questionario | | `src/components/longevity/Questionario.tsx` | isola React: quattro blocchi, validazione, invio | | `src/pages/api/longevity/questionario.ts` | endpoint che salva una compilazione | | `src/pages/longevity/io.astro` | il referto del cliente | | `src/components/longevity/Radar.tsx` | isola React: il radar a sette assi col tratteggio | | `src/components/longevity/MacroScore.astro` | le tre carte dei macro-score | | `src/lib/longevity/vista.ts` | ciò che serve alle pagine, letto dal motore | --- ### Task 1: Il guscio — layout, stile, e una rotta che risponde **Files:** - Create: `src/layouts/Longevity.astro`, `src/styles/longevity.css`, `src/pages/longevity/index.astro` - Test: `tests/longevity/pagine.test.ts` **Interfaces:** - Consumes: `isProtectedPath`, `canAccessAdminPath` da `src/lib/auth.ts` - Produces: il layout `Longevity.astro` con `title` e `crumbs`, e le classi `.lg-*` **Il modello da seguire:** `src/layouts/StressIndex.astro` e `src/styles/stress-index.css`. Leggili prima di scrivere. Il foglio di stile va **globale e prefissato**, non in `