diff --git a/frontend/src/app/globals.css b/frontend/src/app/globals.css index eaf6a7a..547da3c 100644 --- a/frontend/src/app/globals.css +++ b/frontend/src/app/globals.css @@ -193,8 +193,17 @@ html.lenis body { @keyframes abrbanShimmer { to { background-position: 200% center; } } +/* Gentle horizontal sway for the auth-screen clouds (see AuthSky). */ +@keyframes abrbanCloudDrift { + from { transform: translateX(calc(var(--drift, 6vw) * -1)); } + to { transform: translateX(var(--drift, 6vw)); } +} .abrban-float { animation: abrbanFloat 6s ease-in-out infinite; } .abrban-scroll-hint { animation: abrbanScrollHint 1.8s ease-in-out infinite; } +.abrban-cloud-drift { + animation: abrbanCloudDrift var(--drift-dur, 40s) ease-in-out infinite alternate; + animation-delay: var(--drift-delay, 0s); +} .abrban-shimmer { background: linear-gradient(100deg, #93c5fd 0%, #ffffff 25%, #2563eb 50%, #ffffff 75%, #93c5fd 100%); background-size: 200% auto; @@ -223,7 +232,8 @@ html.lenis body { @media (prefers-reduced-motion: reduce) { .abrban-float, .abrban-scroll-hint, - .abrban-shimmer { + .abrban-shimmer, + .abrban-cloud-drift { animation: none; } } diff --git a/frontend/src/components/auth/AuthShell.tsx b/frontend/src/components/auth/AuthShell.tsx index 2c9e409..8f16a34 100644 --- a/frontend/src/components/auth/AuthShell.tsx +++ b/frontend/src/components/auth/AuthShell.tsx @@ -5,11 +5,12 @@ import { Link } from '@/i18n/Link'; import { useT } from '@/i18n/I18nProvider'; import { LanguageSwitcher } from '@/i18n/LanguageSwitcher'; import { Logo } from '@/components/landing/Logo'; +import { AuthSky } from './AuthSky'; -// Auth shell that carries the Abrban brand into a calmer, more premium key: a -// deep blue gradient, a faint infrastructure grid, soft brand-blue glows and a -// vignette — no fluffy clouds — with the form inside the same frosted dark-glass -// panel used across the landing. Direction is inherited from the root layout. +// Auth shell that carries the Abrban brand straight from the landing: the same +// bright, cloud-filled sky (see AuthSky) sits behind the form, which lives in the +// same frosted dark-glass panel — so login/register read as one world with the +// public landing. Direction is inherited from the root layout. export function AuthShell({ title, subtitle, @@ -27,21 +28,9 @@ export function AuthShell({ }) { const t = useT(); return ( -
- {/* Background atmosphere */} -
- {/* Deep brand gradient */} -
- {/* Fine infrastructure grid, faded toward the edges */} -
- {/* Soft brand-blue glows */} -
-
- {/* Crisp hairline along the very top */} -
- {/* Vignette to focus the centre */} -
-
+
+ {/* Bright cloud-filled sky backdrop, shared with the landing */} + {/* Header */}
diff --git a/frontend/src/components/auth/AuthSky.tsx b/frontend/src/components/auth/AuthSky.tsx new file mode 100644 index 0000000..7478e41 --- /dev/null +++ b/frontend/src/components/auth/AuthSky.tsx @@ -0,0 +1,97 @@ +'use client'; + +import type { CSSProperties } from 'react'; + +// A calm, lightweight echo of the landing's cinematic sky — the same pale-blue +// gradient (weather stop 0) and the very same vendored cloud puff (/cloud.png), +// but as cheap drifting CSS sprites instead of the full WebGL scene. It keeps the +// auth screens visually tied to the landing ("ابر" floating behind the form) +// without pulling three.js onto the login/register routes. + +// Each cloud is a small cluster of overlapping puffs so the silhouette reads as a +// soft fluffy cloud rather than a single blob. Offsets are relative to the +// cluster's own box (percent of its width). +const PUFFS = [ + { l: '0%', t: '32%', w: '52%' }, + { l: '20%', t: '6%', w: '62%' }, + { l: '46%', t: '24%', w: '56%' }, + { l: '28%', t: '40%', w: '66%' }, +]; + +type CloudSpec = { + // Anchor: provide either left/right and either top/bottom. + left?: string; + right?: string; + top?: string; + bottom?: string; + width: string; // cluster width + opacity: number; + blur: number; // px + drift: string; // horizontal sway amplitude + dur: string; // drift duration + delay: string; // negative to desync +}; + +const CLOUDS: CloudSpec[] = [ + { top: '6%', left: '-8%', width: '30rem', opacity: 0.92, blur: 1, drift: '7vw', dur: '34s', delay: '0s' }, + { top: '18%', right: '-10%', width: '36rem', opacity: 0.8, blur: 2, drift: '6vw', dur: '42s', delay: '-7s' }, + { top: '50%', left: '2%', width: '24rem', opacity: 0.5, blur: 3, drift: '5vw', dur: '38s', delay: '-14s' }, + { top: '62%', right: '0%', width: '30rem', opacity: 0.58, blur: 3, drift: '8vw', dur: '46s', delay: '-4s' }, + { bottom: '-6%', left: '18%', width: '38rem', opacity: 0.72, blur: 4, drift: '5vw', dur: '52s', delay: '-22s' }, +]; + +function Cloud({ spec }: { spec: CloudSpec }) { + const driftVars = { + '--drift': spec.drift, + '--drift-dur': spec.dur, + '--drift-delay': spec.delay, + } as CSSProperties; + + return ( +
+
+
+ {PUFFS.map((p, i) => ( + + ))} +
+
+
+ ); +} + +export function AuthSky() { + return ( +
+ {/* Bright sky gradient — landing weather stop 0 (calm, bright overcast). */} +
+ {/* Soft warm sun glow, high and centred, like the landing's hidden sun. */} +
+ {/* Drifting clouds. */} + {CLOUDS.map((spec, i) => ( + + ))} + {/* Low fog haze so the bottom melts into the sky like the landing. */} +
+ {/* Crisp hairline along the very top. */} +
+ {/* Vignette to focus the centre — matches LandingPage. */} +
+
+ ); +}