Vrai mode sombre via prefers-color-scheme (palette repensée, pas une
inversion — fond brun quasi-noir pour rester dans la famille chaude de la
marque, contrastes vérifiés WCAG AA). Répond aux deux demandes de Kévin en
une implémentation : mode sombre réel + rendu moins agressif en usage
réel (soirée en intérieur tamisé). Appliqué à la page upload, la galerie
admin et le générateur QR ; le carton imprimable reste volontairement en
clair uniquement (pas de mode sombre pertinent pour un PDF imprimé).
Finition : easing dédié aux transitions d'état (séparé du rebond ludique
existant), halo de couleur en fond de page, hover desktop enrichi,
focus ring teinté, entrées en fondu au chargement, modale de bienvenue
peaufinée.
Brainstorm documenté (voir rapport de tâche) : palette/typo confirmées
plutôt qu'étendues avec une 4e couleur ou une police supplémentaire, pour
rester fidèle à l'identité perso de Kévin plutôt que de la diluer.
Demande Kévin : mot de bienvenue personnalisé (nom de l'événement) +
mention légale RGPD, affiché une fois par événement (localStorage) au
lieu d'un bloc toujours visible dans le formulaire. Texte légal conservé
à l'identique (docs/rgpd.md), seule la présentation change. Reste
consultable à tout moment via un lien "Infos sur tes données" sous le
formulaire, qui rouvre la même modale.
Retour direct de Kévin après la 1ère passe (trop sage) : palette poussée
en saturation (corail vif en primaire, prune + doré en accents), formes
plus rondes (boutons pilule, rayons 20px), micro-animations avec du peps
(easing overshoot, coche qui se dessine + confettis CSS purs à l'envoi,
spinner animé). Police d'accent Fraunces ajoutée pour les titres (2
fichiers .woff2 auto-hébergés, ~44 Ko, SIL OFL, jamais de CDN).
Ton de voix retravaillé : micro-copies plus souriantes, nouvel état
"limite de photos atteinte" traité chaleureusement (pas comme une erreur).
Cohérence maintenue sur galerie admin, carton imprimable, et générateur
QR (sync légère, priorité basse). Testé en conditions réelles sur
photobooth.assistantaikev.eu.
Nouvelle colonne max_photos_per_guest (NULL = illimité). Appliquée via un
guest_id anonyme persisté en localStorage — pas une identité vérifiée,
contournable en changeant d'appareil, mais fait respecter côté serveur
(source de vérité) et bloque l'UI proactivement côté client. Ancienne
signature de insert_public_photo (sans guest_id) supprimée pour empêcher
tout contournement.
Testé en conditions réelles sur kevin-lecou-hub (2 photos acceptées,
3e refusée avec max_photos_per_guest=2).
nginx réécrit /admin/<slug> et /e/<slug> vers le vrai index.html (try_files),
mais l'URL affichée au navigateur reste /admin/<slug> — les chemins relatifs
(style.css, config.js, gallery.js/upload.js) se résolvaient donc contre cette
URL "virtuelle" au lieu du vrai dossier, tombaient sur le fallback nginx et
recevaient du HTML au lieu du CSS/JS attendu. La galerie admin restait
bloquée sur "Chargement..." avec un style complètement cassé. Passage en
chemins absolus (/e/..., /admin/gallery/...) partout.
Signalé par Kévin après test réel sur /admin/demo-kevin.
Au passage : durcit la protection anti-double-soumission du formulaire
upload (garde-fou supplémentaire au niveau de l'event listener) et
remet à zéro photo/nom/message immédiatement après un envoi réussi.
nginx:alpine ne connaît pas l'extension .mjs par défaut et la servait en
application/octet-stream — le navigateur refusait d'exécuter les modules
ES (browser-image-compression.mjs, qrcode-generator.mjs), ce qui plantait
silencieusement TOUT le JS qui les importe : page upload invité bloquée
sur "Chargement...", générateur QR et carton imprimable cassés depuis
leur déploiement. Aucune erreur visible sans ouvrir la console navigateur.
Découvert suite à un vrai test d'upload de Kévin depuis son téléphone.
Palette affinée autour de l'accent brun/terracotta déjà en prod (continuité,
pas de rupture) : tokens de couleur/rayon/ombre partagés entre la page
upload et la galerie admin. Emoji remplacés par des icônes SVG inline
(rendu cohérent multi-OS). Bloc de marque discret en en-tête des deux
écrans invité/admin.
Nouveau : carton imprimable A5 (src/admin/print-template/) qui génère le
QR en direct via le module qrcode.js existant, prêt pour l'export PDF
navigateur.
Pas de police custom : stack système conservée pour rester sobre
(zéro poids réseau supplémentaire).
Deux boutons séparés (deux inputs file) plutôt qu'un seul avec
capture=environment qui masquait l'option galerie — retour de Kévin
après test réel. État de sélection centralisé dans state.selectedFile.
Container nginx dédié, rattaché au réseau Docker de n8n pour réutiliser
Traefik/Let's Encrypt déjà en place. Config versionnée dans deploy/.
APP_BASE_URL configurée sur les Edge Functions pour le CORS. Testé en
conditions réelles : upload invité + galerie admin fonctionnels depuis
le domaine public.
Schéma dédié `photobooth` (jamais exposé via PostgREST, accès exclusivement
via fonctions SECURITY DEFINER dans public) avec RLS, policies Storage sur
bucket privé event-photos, Edge Functions admin-gallery et expire-events,
et job pg_cron d'expiration J+7. Le tout déployé et testé en conditions
réelles sur le projet Supabase kevin-lecou-hub avant relecture sécurité
(faille d'abus sur insert_public_photo corrigée en cours de route).
Côté front : page upload invité (compression + HEIC + RGPD), galerie admin
avec export ZIP, générateur de QR code autonome. Workflow n8n de purge
Storage J+7 fourni (à activer manuellement côté n8n).