L'altezza della barra era dedotta dai padding delle voci e poi ricopiata a
occhio altrove: `pb-24` nel contenitore delle pagine, `pb-28` nella
celebrazione badge. Su iPhone i conti tornavano per 2 px — barra ~60 px più
34 px di safe area contro 96 px riservati — quindi bastava un inset diverso
(orizzontale, o un modello con home indicator più alta) perché l'ultimo
elemento della pagina finisse sotto la barra. Solo su iOS: su Android
avanzavano 36 px.
Ora la geometria sta in due token, `--altezza-nav` e `--pad-sicura-fondo`, e
le utility `spazio-nav` e `pad-sicura-fondo` la leggono da lì. La striscia
toccabile ha altezza fissa, così misura uguale sui due sistemi e sotto varia
solo l'inset: `max(env(safe-area-inset-bottom), 0.5rem)` dà ad Android un
respiro minimo dove iOS mette la home indicator. Identiche al pixel non
possono essere — quell'inset esiste per un motivo fisico che Android non ha —
ma la differenza è ora un margine in più, non un allineamento diverso.
`100vh` diventa `100dvh` ovunque: su iOS Safari `vh` misura il viewport con la
toolbar collassata, cioè più alto di quello visibile, e le schermate a tutta
altezza risultavano più lunghe dello schermo. `dvh` segue la toolbar.
Aggiunto il ripiego per Chrome su Android, che disattiva `backdrop-filter`
senza accelerazione hardware: senza, su quei device la barra restava
semitrasparente e il contenuto si leggeva attraverso.
Resta fuori portata una differenza sola: in Safari non installata la toolbar
di sistema sta in basso e collassa allo scroll, quindi la barra si muove con
essa. Su Chrome la toolbar è in alto. Si risolve installando la PWA.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
`viewport-fit=cover` mancava, quindi `env(safe-area-inset-bottom)` valeva
sempre 0: il codice safe-area della BottomNav c'era già ma era inerte, e su
iPhone in standalone la barra finiva sotto la home bar.
`theme-color` e `background_color` erano `#111111` su un'app con fondo quasi
bianco: barra di stato nera e splash nero prima di una UI chiara.
`lang="en"` su un'app interamente in italiano: gli screen reader leggevano
tutto con fonetica inglese. Con esso 404 e schermata d'errore, che erano
rimaste in inglese.
L'anteprima social puntava a un'immagine di preview Lovable su R2 ormai
scaduta e dichiarava `twitter:site @Lovable`: ora usa l'icona della squadra,
con `summary` al posto di `summary_large_image` visto che l'unica immagine
disponibile è quadrata.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
useGiocatoreBase() ora interroga giocatori_squadra con useQuery, ma
RootComponent la chiamava prima di montare QueryClientProvider: ogni pagina
falliva in SSR con "No QueryClient set". Il provider avvolge ora tutto fin
dall'inizio; la logica di redirect/loading si sposta in un componente
AppShell interno, comportamento invariato.
La classifica e lo storico partite mostravano dati inventati (squadre e
risultati finti) come base, poi sovrascritti dai dati CSI quando
disponibili. Ora classifica, ultimi risultati, storico match e obiettivi
di squadra legati alle vittorie usano solo dati reali (CSI o scout live),
con stati vuoti quando i dati CSI non sono ancora disponibili.
Include anche la correzione di tutti gli errori di formattazione
prettier segnalati da `npm run lint` sul resto del codice sorgente.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Remove the free player selection from /benvenuto: without a Supabase session
no screen renders, and the VITE_AUTH_OBBLIGATORIA bridge flag is gone.
Admin rights now come only from user_roles, so the hardcoded name list in
crapp-data.ts is deleted along with its tests.
Add migration m4_solo_autenticati, which revokes anon access to the v1.0
tables. Apply it only once the whole team has linked an account.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>