diff --git a/app/src/components/auth/AuthBackground.tsx b/app/src/components/auth/AuthBackground.tsx
index 86c6d31..5a6617f 100644
--- a/app/src/components/auth/AuthBackground.tsx
+++ b/app/src/components/auth/AuthBackground.tsx
@@ -1,4 +1,4 @@
-import { BACKGROUND_IMAGES } from '../../lib/backgrounds';
+import { BACKGROUND_SCENES } from '../../lib/backgrounds';
import { useBackgroundCrossfade } from '../../hooks/useBackgroundCrossfade';
export function AuthBackground() {
@@ -6,15 +6,43 @@ export function AuthBackground() {
return (
- {BACKGROUND_IMAGES.map((bg, i) => (
+ {BACKGROUND_SCENES.map((scene, i) => (
+ key={scene.id}
+ className="absolute inset-0 transition-opacity duration-[2400ms] ease-in-out"
+ style={{ opacity: i === activeIndex ? 1 : 0 }}
+ >
+ {scene.blobs.map((blob, bi) => (
+
+ ))}
+
))}
-
-
+
+ {/* Grain léger : casse l'effet "dégradé plat", donne une texture
+ plus organique - technique courante sur les fonds génératifs. */}
+
+
+ {/* Scrim en deux passes : un voile uniforme (garantit le contraste du
+ texte quelle que soit la position des taches de couleur) plus un
+ dégradé directionnel plus marqué côté texte. */}
+
+
);
}
diff --git a/app/src/hooks/useBackgroundCrossfade.ts b/app/src/hooks/useBackgroundCrossfade.ts
index 8d16b6f..ba17ca6 100644
--- a/app/src/hooks/useBackgroundCrossfade.ts
+++ b/app/src/hooks/useBackgroundCrossfade.ts
@@ -1,14 +1,15 @@
import { useEffect, useState } from 'react';
-import { BACKGROUND_IMAGES } from '../lib/backgrounds';
+import { BACKGROUND_SCENES } from '../lib/backgrounds';
-const INTERVAL_MS = 5400;
+const INTERVAL_MS = 8000;
export function useBackgroundCrossfade(): number {
const [index, setIndex] = useState(0);
useEffect(() => {
+ if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) return;
const id = window.setInterval(() => {
- setIndex((i) => (i + 1) % BACKGROUND_IMAGES.length);
+ setIndex((i) => (i + 1) % BACKGROUND_SCENES.length);
}, INTERVAL_MS);
return () => window.clearInterval(id);
}, []);
diff --git a/app/src/index.css b/app/src/index.css
index 3f9cdbd..2effa0e 100644
--- a/app/src/index.css
+++ b/app/src/index.css
@@ -93,6 +93,26 @@ input::placeholder {
animation: tc-pulse 2.4s ease-in-out infinite;
}
+@keyframes tc-drift {
+ 0%,
+ 100% {
+ transform: translate(0, 0) scale(1);
+ }
+ 50% {
+ transform: translate(3%, -4%) scale(1.06);
+ }
+}
+
+.tc-drift {
+ animation: tc-drift 22s ease-in-out infinite;
+}
+
+@media (prefers-reduced-motion: reduce) {
+ .tc-drift {
+ animation: none;
+ }
+}
+
.upload-progress-stripes {
background-image: linear-gradient(
115deg,
diff --git a/app/src/lib/backgrounds.ts b/app/src/lib/backgrounds.ts
index 501e37b..8d2ff6e 100644
--- a/app/src/lib/backgrounds.ts
+++ b/app/src/lib/backgrounds.ts
@@ -1,10 +1,49 @@
/**
- * Auth-screen background layers. Replace each entry with
- * `url('/assets/bg-1.jpg') center/cover no-repeat` for real photography —
- * the crossfade logic in useBackgroundCrossfade doesn't change.
+ * Scènes du diaporama de fond de l'écran de connexion : de l'art génératif
+ * (pas de photo tierce, pour rester libre de droits) - deux à trois taches
+ * de couleur douces, floutées, qui dérivent lentement (voir `.tc-drift`
+ * dans index.css) et s'enchaînent en fondu. Palette "zen" volontairement
+ * sourde : jamais de couleur saturée à pleine opacité.
*/
-export const BACKGROUND_IMAGES: string[] = [
- 'radial-gradient(120% 95% at 22% 12%, #2b3340 0%, #121620 55%, #070910 100%)',
- 'radial-gradient(120% 95% at 78% 18%, #2f2b3f 0%, #16131f 55%, #08070d 100%)',
- 'radial-gradient(130% 100% at 45% 85%, #1f3340 0%, #0f161c 55%, #070a0d 100%)',
+export interface BackgroundBlob {
+ color: string;
+ top: string;
+ left: string;
+ size: string;
+}
+
+export interface BackgroundScene {
+ id: string;
+ blobs: BackgroundBlob[];
+}
+
+export const BACKGROUND_SCENES: BackgroundScene[] = [
+ {
+ id: 'aube',
+ blobs: [
+ { color: 'rgba(123,148,255,0.42)', top: '-12%', left: '58%', size: '56vw' },
+ { color: 'rgba(255,168,140,0.24)', top: '52%', left: '2%', size: '44vw' },
+ ],
+ },
+ {
+ id: 'nuit',
+ blobs: [
+ { color: 'rgba(91,102,255,0.38)', top: '-16%', left: '72%', size: '60vw' },
+ { color: 'rgba(124,92,255,0.3)', top: '58%', left: '12%', size: '50vw' },
+ ],
+ },
+ {
+ id: 'foret',
+ blobs: [
+ { color: 'rgba(94,214,170,0.22)', top: '8%', left: '76%', size: '48vw' },
+ { color: 'rgba(53,124,132,0.38)', top: '62%', left: '6%', size: '54vw' },
+ ],
+ },
+ {
+ id: 'braise',
+ blobs: [
+ { color: 'rgba(255,186,128,0.26)', top: '-6%', left: '18%', size: '50vw' },
+ { color: 'rgba(179,111,255,0.3)', top: '54%', left: '68%', size: '54vw' },
+ ],
+ },
];