Gli Opening Bundles scadono il 04/09 alle 23:59:59 e dopo di loro non c'era
nessuna edizione: dal 5 il sito avrebbe mostrato "Nessuna promozione in corso"
mentre le promo erano vive. Adriano ha consegnato le sei creative il 03/09.
Edizione `settembre-2026` (5 -> 19 settembre, chiude il giorno
dell'inaugurazione): tornano i pacchetti da 5 incontri, con in piu' il
Check-up avanzato, che e' una valutazione singola e per questo dice
"1 valutazione" invece di "5 incontri". Prezzi 250/150/130/80/70.
Due cose che la struttura non prevedeva:
- **Nessun prezzo barrato.** Le creative danno il solo prezzo promo, e i
listini pieni di agosto (300/220/140/100) sono numeri che nessuno ha
riconfermato - riportarli accanto ai nuovi sarebbe stato inventarli.
`price-old` diventa opzionale nella CardSpec (`priceOld`) invece di essere
un tag vuoto: cosi' la spec dichiara che quella card non ne ha, e il test
lo pretende solo dove c'e'. Agosto e i bundle sono marcati `priceOld: true`,
quindi restano sotto controllo come prima.
- **Cinque card non stanno in una griglia da due o da tre** senza lasciare un
buco in fondo. `.cards-5` va a sei colonne con span due, cosi' le ultime due
si spostano al centro; a due card per riga sotto i 1000px, a una sotto i 700.
Testi ripresi dall'edizione di agosto, gia' approvata dal cliente, cambiando
solo cio' che le date rendevano falso: la FAQ delle class diceva "gli orari
saranno pubblicati entro Settembre" e adesso e' settembre, quindi rimanda al
calendario che esiste. La FAQ 7 sul Check-up e' nuova e va fatta leggere a
Nicola prima della pubblicazione.
186 test verdi, `astro check` invariato (i 3 errori della pagina promo sono
preesistenti e non toccati).
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FPKFABRT3y26dFNMquF3CS
Coda della modifica precedente, e senza questa quella era una regressione sul
telefono. A colonne uguali la piu' stretta deve contenere la parola piu'
lunga; in layout automatico il browser allargava da solo le colonne piene e
stringeva quelle vuote, quindi il problema non si vedeva.
Il conto, misurato sul Montserrat 400 che il sito serve davvero (non
stimato): REFORMER a .7rem con letter-spacing .1em e' 75,4 px, mentre la
colonna a 720px ne offriva 72,7 di spazio utile — 2,7 in meno. La parola
sarebbe uscita dalla cella proprio dove il minimo si vede, cioe' sul
telefono, che quella tabella la fa scorrere in orizzontale apposta.
A 780px la colonna da' 81,3 px, ~6 di margine. In stampa il conto era gia'
buono (corpo .62rem e padding ridotto: 66,8 px in 77,9).
Il conto e' scritto nel CSS accanto alla regola: chi tocca padding, corpo o
spaziatura deve rifarlo.
185 test verdi.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Chiesto da Adriano. La tabella era in layout automatico, quindi il browser
dimensionava ogni colonna sul contenuto: il sabato, che porta la nota «solo
il 12 settembre», veniva largo quasi il doppio, e i giorni senza class si
stringevano. Una griglia oraria con le colonne di misure diverse si legge
male proprio dove serve — nell'incrocio fra un giorno e un'ora.
`table-layout: fixed` piu' una larghezza sulla sola colonna delle ore
(64px): tutto il resto viene diviso in parti uguali fra le sette dei giorni.
E' lo stesso criterio che il PDF applica da sempre — la' le colonne sono
`(larghezzaUtile - larghezzaOra) / GIORNI.length` — quindi adesso le due
versioni dello stesso foglio si somigliano invece di divergere.
La colonna delle ore resta piu' stretta dei giorni, come nel PDF: ci sta
dentro «12.15» e nient'altro.
185 test verdi.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Chiesto da Adriano l'01/09. Tolte le tre celle del venerdi' dal calendario
'settembre-1-18': MOBILITY alle 8.30, REFORMER alle 9.15 e alle 10.00.
Erano tutte di mattina, quindi in quel periodo il venerdi' resta una colonna
completamente vuota. Resta VUOTA e non barrata: togliere le class non vuol
dire che la sala sia chiusa, e nessuno l'ha detto — il dato distingue le due
cose apposta (`chiusi`), e sceglierne una che non ci e' stata comunicata
sarebbe inventare un'informazione.
⚠️ L'edit e' confinato al primo calendario. Le tre righe del venerdi' sono
IDENTICHE, carattere per carattere, in 'settembre-21-in-poi' — dove il
venerdi' deve restare — quindi una sostituzione sul file intero ne avrebbe
prese sei invece di tre. Verificato dopo: dal 21 settembre il venerdi' ha
ancora PILATES 7.45, MOBILITY 8.30, REFORMER 9.15 e 10.00.
Aggiunto un commento nel dato, perche' confrontando le due griglie il buco
sembra una trascrizione monca e il prossimo che passa lo "corregge".
185 test verdi.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Caporali «» attorno alla frase — sono le virgolette italiane, e su un corsivo
di quel corpo reggono meglio delle doppie curve.
Corpo da clamp(1.05rem, 2.4vw, 1.3rem) a clamp(1.35rem, 3.4vw, 1.9rem): ~+45%
sia sul minimo che sul massimo, quindi cresce anche su mobile. Interlinea da
1.8 a 1.5, altrimenti a quel corpo le due righe galleggiavano.
Il <br /> che spezza la frase in due versi resta dov'era.
Tre ritocchi chiesti dal cliente: il "Primo piano" sotto "Prova i nostri
servizi" spariva il messaggio piu' che aiutare, il download della locandina
sta meglio a fine lettura che nell'apertura, e il titolo del programma va
a capo dopo "Come si svolge".
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
La pagina dell'inaugurazione del 19 settembre: il programma completo della
giornata, gli slot di prova del mattino e del pomeriggio, la festa serale.
Il blocco del titolo è il ritaglio della locandina vera, non una sua
riproduzione: i caratteri originali non li abbiamo, e ricostruirli a occhio
è già stato provato senza riuscirci. Il resto della pagina usa la tipografia
del sito e i colori campionati dalla locandina, così volantino e schermo si
riconoscono come la stessa cosa.
La locandina scaricabile è ricalcata in vettoriale dallo stesso JPEG — tre
colori piatti, quindi ogni forma diventa un tracciato — e monta il QR code
definitivo verso questa pagina, un filo più piccolo dell'originale per
lasciargli attorno il margine muto che lo standard richiede.
I testi non passano più dal pannello contenuti: la pagina è in codice.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Chiesto da Adriano il 19/08: era 0,82rem sotto un titolo che arriva a 2,6rem, e
sembrava una didascalia. Ora cresce con la finestra come il titolo, restando un
gradino sotto.
Chiesto da Adriano il 19/08. Sono due tag e non un testo con un a capo dentro:
la data si cambia da sola se l'evento si sposta, e un ritorno a capo dentro un
valore di testo non sopravvive all'editor del pannello.
Il titolo vive anche nel database: in produzione va aggiornato
eventi.inaugurazione.title a "Inaugurazione", altrimenti resta la riga unica.
Il tag nuovo (.date) non e' in tabella e viene dal seed.
La foto di Eva in pagina non veniva dal repo ma da un file caricato dal
pannello il 12/07 (tag team.eva.image-about): lo scatto giusto, ritagliato piu'
largo, ma con il logo ancora nell'angolo. Il file del repo era l'altro ritaglio,
piu' stretto, e non lo vedeva nessuno.
Ora team-eva-dark.jpg E' quella foto, col logo rimosso: maschera dei pixel del
logo allargata di 4 px per prendere i bordi sfumati, ricostruzione biharmonic
(scikit-image) e grana del tessuto ripresa dalla stoffa 80 px piu' in alto —
una toppa liscia si sarebbe notata.
Cosi' tutte le foto stanno in un posto solo e passano dall'ottimizzazione della
build (54 KB webp invece di 177 KB jpeg servito com'e'). In produzione va
svuotato il tag team.eva.image-about, altrimenti continua a vincere il file
caricato. Originale col logo su
wasabi://.../foto-team/team-eva-dark-ORIGINALE-col-logo.jpeg; il file su
uploads/ resta dov'e'.
Il ritaglio e' 864x1240 (0.697) invece di 1547x1920 (0.806): le card ritagliano
a 3:4, quindi qui si perde qualcosa sopra e sotto invece che ai lati. Verificato
sulla card renderizzata.
Adriano ha tolto un piccolo logo dall'angolo in basso a destra delle sette foto
scure della pagina About: alessandro, alice, donata, eleonora, eva, giulia,
nicola. Originali in wasabi://.../Sito_Web/foto-team-originali-20260819.zip.
Stesso formato di prima (JPEG 1547x1920, RGB): l'unica differenza e' un riquadro
di ~80x80 px nell'angolo, verificato confrontando le immagini. I file pesano il
doppio perche' risalvati a qualita' piu' alta, ma in pagina non cambia nulla: la
build li ricomprime in webp attorno agli 85 KB.
Nota: la foto di Eva in pagina NON e' questa, e' un ritaglio piu' largo dello
stesso scatto caricato dal pannello il 12/07 (tag team.eva.image-about), che il
logo ce l'ha ancora.
Segnalato da Adriano il 19/08. Il valore vive anche nel database dei contenuti,
dove viene letto per primo: il seed da solo non avrebbe cambiato la pagina, e
l'aggiornamento del tag about.hero.title va fatto in produzione.
Segnalato da Adriano il 19/08: "Check-up Avanzato" era appiccicato alla foto
sopra e si leggeva come una didascalia invece che come l'inizio di una parte
nuova.
Lo stacco e' un padding e non un margine: sopra c'e' gia' il margine
dell'immagine, e due margini verticali adiacenti collassano fra loro — con
margin-top lo spazio sarebbe rimasto quello di prima.
Chiesta da Adriano il 19/08. Restava in coda alle FAQ e ripeteva, in versione
piu' povera, cio' che la sezione Check-up Avanzato racconta per esteso.
In pagina resta una sola domanda. I due tag del pannello
(service.profilazione.faq.2.q e .a) non sono piu' letti da nessuno.
Il documento MODIFICHE_PER_SITO.pdf porta cinque cose.
1. "Small Group" si chiama "Personalized Training Group". Il nome vive anche
nel database dei contenuti, dove `resolveContent` legge prima della copia
nel codice: `scripts/testi-17-agosto.mjs` aggiorna le 19 righe rimaste,
una volta sola, correggendo anche gli articoli ("Lo Small Group" -> "Il
Personalized Training Group"). Lo slug della scheda resta `small-group`:
cambiarlo romperebbe i link gia' girati su WhatsApp.
2. Dalla pagina Servizi le card instradano dove serve. "One to One" apre la
vista Training con One to One, Personalized Training Group e Rehab;
"Class" quella con Holistic e Reformer. Le viste sono `/training/<vista>`;
una vista inventata e' 404, non l'elenco intero, altrimenti un indirizzo
rotto continuerebbe a sembrare buono.
3. La Performance Class non si eroga piu': la scheda che la spiegava
risponde 404, la card "Class" resta in griglia. Con la scheda e' caduta la
tabella prezzi, che era solo sua.
4. Il Check-up racconta Base e Avanzato: trafiletto nuovo nella card e
sezione "Check-up Avanzato" nella scheda, con la Wellness Tower e i cinque
punti. Il calendario delle class si apre ora anche dalla card Class in
griglia e dalla scheda Reformer, oltre che da Holistic.
5. "Promo ed eventi" diventa una pagina di scelta: le promozioni restano su
/promo-eventi/promo, l'inaugurazione del 19 settembre sta su
/promo-eventi/eventi. Il testo dice che il programma della giornata manca
ancora, ed e' editabile dal pannello.
Corretti due link del footer che portavano a schede inesistenti
(`/services/personal-training` non e' mai stato uno slug).
181 test verdi (157 + 24 nuovi), build ok, `astro check` invariato.
Il popup mostrava solo l'orario del momento: chi guarda ad agosto vuole sapere
com'e' settembre per intero, e una griglia sola gli fa credere che valga per
sempre. Ora ci sono tutti quelli non ancora scaduti, ognuno con la sua etichetta
- In vigore, oppure la data da cui parte - e quelli passati spariscono da soli.
Il bottone scarica /calendario/tutti.pdf: un orario per pagina, con le giornate
fuori griglia ripetute su ognuna, perche' un foglio stampato da solo deve bastare
a se stesso. Gli id singoli restano validi per mandarne uno solo.
calendarioDaMostrare (uno) diventa calendariDaMostrare (tutti): una funzione
sola, non due che dicono cose simili - e' lo stesso difetto dei due link della
pagina servizi, che erano due espressioni per lo stesso indirizzo e sono
divergute.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Quei due giorni non stanno in nessuna delle due griglie perche' non hanno class:
il 19 c'e' la presentazione della nuova apertura, il 20 si sta chiusi. Scritto
come avviso con la sua finestra, il vuoto smette di sembrare una trascrizione
incompleta e diventa un'informazione.
Gli avvisi compaiono in cima al popup e in fondo al PDF - e' il file che gira su
WhatsApp, e chi lo riceve non ha la pagina davanti. Spariscono da soli quando
sono passati: un avviso scaduto dice che il centro e' chiuso in un giorno gia'
trascorso, e chi legge non sa piu' se valga per quest'anno o per il prossimo.
Lo spazio riservato in fondo alla pagina cresce con gli avvisi, altrimenti la
griglia si allunga fino a spingerli su una seconda pagina.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Le due celle coperte dal riquadro di Excel nel foglio dal 21 settembre: Adriano
conferma che non c'e' nulla. Il dato non cambia, cambia il commento - quel vuoto
adesso e' una risposta, non una lettura mancata.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
"Scarica in PDF" non apre piu' la stampa del browser: e' un link a
/calendario/<id>.pdf che restituisce un documento disegnato dal dato con PDFKit,
con Content-Disposition attachment. Serve perche' il calendario si gira su
WhatsApp, ed e' cosi' che questo centro parla coi clienti: chi lo riceve non ha
il sito aperto davanti.
Niente browser headless: Chromium in un container da 2 vCPU costa centinaia di
megabyte e un processo per richiesta, per una griglia di sette colonne.
Le linee della griglia si tracciano in una passata a parte, dopo i riempimenti:
disegnandole riga per riga, il riempimento della riga seguente copriva quella
appena fatta e due lezioni uguali in fasce consecutive si leggevano come un
blocco unico lungo il doppio.
Quattro test: intestazione %PDF- e coda %%EOF (un documento non chiuso arriva
monco e il browser mostra una pagina bianca invece di un errore), una pagina
sola, nomi di file distinti. Un id sconosciuto e' 404, non un PDF vuoto.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Le due griglie fornite dal cliente (1-18 settembre, dal 21 in poi) sono
trascritte come dato e ridisegnate nello stile del sito: si leggono da telefono,
si stampano in PDF e per correggere una cella non serve rifare uno screenshot.
Quale griglia compare lo decide la data, come per le edizioni della promo: quella
in vigore, oppure - se nessuna lo e' ancora - la prossima, dichiarando da quando
entra. Serve perche' il link esiste da subito e ad agosto un "nessun calendario"
non direbbe niente a chi vuole gli orari di settembre.
Il popup e' un <dialog> nativo: fondale, Esc e trappola del focus senza
librerie. "Scarica in PDF" stampa la sola griglia, gia' impaginata in orizzontale
dal CSS di stampa. Le discipline hanno una barra colorata a sinistra oltre al
fondo, cosi' restano distinguibili anche quando il browser stampa senza sfondi.
Quattordici test sul dato: confini al secondo in ora italiana, fasce orarie
uniche e in ordine, nessuna lezione in un giorno di chiusura, e il buco vero fra
il 19 e il 20 settembre resta dichiarato invece che nascosto.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Erano due espressioni diverse per lo stesso link e sono divergute: su One to One e
Performance Class la foto apriva la scheda del servizio mentre il testo mandava a
/training, quindi la destinazione dipendeva da dove capitava il dito. Adesso
l'indirizzo lo calcola una funzione sola, usata da entrambi. Verificato sulla
pagina renderizzata: sei card, zero link discordanti.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Senza login (o con una data illeggibile) il parametro veniva ignorato e la pagina
rispondeva con l'edizione corrente: due date diverse davano lo stesso risultato,
e si legge come una funzione rotta invece che come un accesso mancante. Ora una
barra rossa dichiara il motivo e come rimediare.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
La pagina non mostra piu' una promozione sola scritta nel codice: sceglie
l'edizione la cui finestra contiene l'istante della richiesta. Il 20 agosto alle
00:00 la promo agosto lascia il posto agli Opening Bundles senza deploy, e dopo
il 4 settembre la pagina dichiara che non c'e' nessuna promozione invece di
lasciare online prezzi scaduti.
Le edizioni sono dato (data/promo-edizioni.ts): finestra, quante card, quali
campi ha ciascuna. I testi restano tag modificabili dal pannello, col prefisso
dell'edizione. I bundle aggiungono domanda, descrizione e riquadro del periodo
di utilizzo, presi dal volantino del cliente.
Le date portano l'offset esplicito: il server gira in UTC e senza offset lo
scambio avverrebbe due ore prima di quanto scritto sul sito. La pagina esce con
Cache-Control: no-store, perche' una copia in cache la congelerebbe all'edizione
vecchia.
Dieci test: le finestre non si sovrappongono e non lasciano buchi, il countdown
scade quando finisce l'edizione, e ogni tag richiesto esiste nel seed - un tag
mancante non romperebbe la pagina, lascerebbe una card senza prezzo.
Anteprima con ?anteprima=<data>, solo per chi e' loggato.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
MethodSteps passa a una sola colonna con step in orizzontale, PartnersStrip
riduce loghi e spaziature, TrainingCards ridimensiona testi e padding.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Nuovo tag promo.faq.0 (q/a) numerato 0 per evitare di rinumerare le FAQ
esistenti: il seed è INSERT OR IGNORE e non riscriverebbe i tag già
presenti nei DB, causando disallineamento tra domanda e risposta.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
I filtri non dicevano dove ci fosse materiale: si sceglieva una categoria
per scoprirla vuota. Ora ognuna porta il proprio conteggio, cestino e
bozze esclusi, e il numero si aggiorna insieme ai filtri quando si cambia
tematica senza ricaricare.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Ogni clic su una categoria ricaricava l'intera pagina, header e hero
compresi, con lo sfarfallio che ne consegue. Ora si scarica la stessa
pagina e si sostituiscono soltanto la griglia e i filtri, con una breve
dissolvenza; l'indirizzo resta corretto e avanti/indietro funzionano.
I link restano link veri: senza JavaScript, o se la risposta non ha la
forma attesa, la navigazione avviene come prima.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Eliminare un articolo non lasciava nulla di recuperabile: ora la riga
finisce nel cestino (colonna deleted_at, aggiunta anche ai database già
esistenti) e sparisce da sito e pannello, ma resta ripristinabile dalla
nuova pagina /admin/cestino, dove sta anche la cancellazione definitiva.
L'API la accetta solo su articoli già cestinati, così il contenuto non si
perde per un clic distratto.
Ogni lettura pubblica — elenco, recenti, archivio per mese, pagina del
singolo articolo — filtra il cestino, e chi non gestisce vede nel cestino
soltanto i propri articoli.
Le azioni di riga diventano icone (matita e cestino) come nell'elenco
utenti, con etichetta accessibile che nomina l'articolo.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Le due azioni di riga diventano icone (chiave e cestino) con etichetta
accessibile: pesavano quanto il contenuto della tabella. Il ruolo smette
di essere il menu a tendina di sistema e prende la forma di una pillola
colorata per livello, restando un <select> che salva al cambio.
La chiave apre un pannello dove la password si può scrivere a mano oppure
far generare: l'endpoint accetta ora una password scelta, con lo stesso
minimo di otto caratteri della creazione, e continua a restituirla in
chiaro una volta sola perché nel database ne resta solo l'hash. Il valore
si copia con un pulsante invece che dal prompt del browser.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
L'elenco aveva il modulo di creazione appiccicato sopra la tabella: ora
c'è il pulsante "+ Nuovo utente" che porta a /admin/users/new, dove il
modulo ha spazio per etichette vere e per spiegare cosa comporta ogni
ruolo. A creazione avvenuta si torna all'elenco.
Nel menu la voce "Sito" diventa "Vai a sito", più esplicita sul fatto che
porta fuori dal pannello.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Il menu in alto si riduce alle voci che servono davvero — Articoli,
Contenuti, Utenti, Sito, Esci — con la voce corrente evidenziata; ognuna
resta visibile solo a chi ha il ruolo per aprirla, e in pagina di login la
barra mostra il solo marchio. "Nuovo" esce dal menu perché il pulsante per
creare un articolo è già in cima all'elenco Articoli.
Il pannello smette di essere un foglio di stile a sé: adotta i font e la
palette del sito, come Campus e Stress Index, con tabelle, pulsanti, campi
e pillole di stato riportati allo stesso linguaggio.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Le due sezioni erano ferme al prototipo locale, più povero della
piattaforma vera. Analytics ha ora l'intervallo di date, i KPI con la
nota sotto il valore, la distribuzione dello score a quattro serie per
fascia, le classifiche per recupero medio col numero di misurazioni e il
confronto segmenti con selettore di dimensione. Sport diventa Dashboard,
Sessioni con filtri atleta/periodo/sport e schede atleta con carico e
tendenza.
I numeri non sono più costanti scritte a mano: si calcolano dai dati nel
periodo scelto. La logica sta in lib/stress-index/analytics.ts e sport.ts,
coperta da test — che hanno subito trovato uno slittamento delle settimane
dovuto alle date costruite in ora locale invece che in UTC.
Le sessioni hanno ora ora di inizio, HR max, RPE e durata al secondo, che
il prototipo non prevedeva.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Il ruolo `campus` diventa `piattaforme` e non apre più solo la sezione
Biohacking: copre tutte le aree riservate, con migrazione guardata sugli
utenti esistenti. Nell'header la vecchia voce Biohacking lascia il posto a
un menu Piattaforme con i due link, visibile solo a chi ha il ruolo, e
/piattaforme diventa la pagina di atterraggio.
Stress Index è portata dentro il sito: le nove viste dell'area
professionisti diventano pagine Astro sotto /piattaforme/stress-index,
con lo stile del sito al posto del design system del prototipo. React
resta solo dove serve davvero — grafici recharts e scheda cliente — il
resto è Astro con un filo di JS. I dati sono ancora quelli dimostrativi,
raccolti in lib/stress-index/data.ts.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Prezzi aggiornati (One to One 200, Small Group 125, Reformer 115,
Holistic 75) con migrazione guardata sul vecchio valore, così le righe
già ritoccate dal pannello non vengono sovrascritte. I barrati restano
invariati. Nota di validità con la finestra 1-19 agosto e countdown alla
scadenza sopra le card: la deadline è un tag editabile, il blocco si
nasconde da solo quando la promo è finita.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Campo opzionale Service.heroTitle: l'hero (H1) di /services/one-to-one
mostra "PERSONAL TRAINING" mentre H2/card restano "One to One" (tag
condiviso service.one-to-one.title invariato). Nessuna migrazione DB.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Contatti: rate-limit per IP reale (X-Forwarded-For) invece dell'IP del
proxy Traefik, condiviso da tutti; controllo spostato dopo la validazione
così bot/honeypot non consumano la quota. Honeypot rinominato da "website"
a "hp_field" per non farlo riempire dall'autofill del browser (falsi 400).
- Servizi: "Performance Class" -> "Class" (titolo/card/H1/footer); migrazione
DB invertita e guardata.
- One to One: migrazione titolo prod "Personal training" -> "One to One".
- Footer: orario sabato 8-17 (non 8-19), seed + migrazione guardata.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Il riquadro training "performance-class" è stato rimosso dal seed nel commit
9966ec3, ma i suoi 5 tag restavano nei DB esistenti come orfani non
renderizzati (uno con un edit errato dell'editor, "Holistic Class"). Aggiunge
una DELETE idempotente per l'intero gruppo; il seed non li reinserisce
(trainings.ts non ha più questo id). Verificata su copia del DB prod: 5 -> 0
orfani, riquadri validi e 39 edit reali del pannello intatti.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Nei DB esistenti (prod + dev) service.performance-class.title era rimasto
"Class", mostrando "CLASS" come H1 della pagina /services/performance-class
e nelle card di /services e home. Il seed è INSERT OR IGNORE e non lo
aggiornava; una nuova installazione era invece corretta.
Aggiunge una migrazione guardata dal vecchio valore (idempotente, non tocca
le modifiche del pannello) che allinea a "Performance Class". Verificata su
copia del DB di produzione: titolo corretto, 40 edit del pannello intatti.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Il commit 1522d97 ha spostato la freccia "→" dei bottoni promo nel CSS
(::after) e il maiuscolo in text-transform, cambiando il seed in minuscolo
senza freccia. Ma il seed è INSERT OR IGNORE: sui DB esistenti (produzione)
le righe restavano a "LE NOSTRE PROPOSTE →" / "ACQUISTA →", e il ::after
avrebbe prodotto una doppia freccia.
Aggiunge una migrazione guardata dal vecchio valore (idempotente, non tocca
le righe modificate dal pannello) che le allinea al seed corrente. Verificata
su copia del DB di produzione: frecce corrette e 40 edit del pannello intatti.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Rimossa la colonna "invia messaggio" (nome, cognome, telefono, mail,
messaggio) e l'import ContactForm inutilizzato.
- Griglia a 3 colonne con contenuto centrato, logo incluso.
- Training e Servizi allineati alla riga "Promuoviamo il movimento...".
- Altezza del footer ridotta (padding compattato).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>