import React, { useMemo } from 'react';
import { SeasonalOverlayProps } from '../types';
import {
animCosmosDrift,
animNebulaA,
animNebulaB,
animGalaxySpin,
animTwinkle,
animStarPulse,
animParallaxNear,
animParallaxFar,
animComet,
} from './DeepSpace.css';
/**
* Deep Space overlay — a cosmic, awe-inspiring ambient mode. Layered oklch
* radial gradients build a deep violet void seeded with drifting magenta/cyan
* nebula clouds and a faint distant galaxy spiral. A parallax starfield sits at
* two depths (a dense field of tiny twinkling stars plus a handful of brighter
* hero stars), and slow comet streaks cross the sky occasionally.
*
* Palette (oklch): deep cosmic violet oklch(0.2 0.12 300), nebula magenta
* oklch(0.55 0.2 330), cyan oklch(0.75 0.13 200), starlight white
* oklch(0.98 0.02 280).
*
* RENDERING CONTRACT: the parent supplies a fixed inset:0 overflow:hidden
* pointer-events:none container at the right z-index. We only return
* absolutely-positioned aria-hidden children at low opacity — no z-index,
* position:fixed, or pointer-events here — kept well below opaque so chat text
* stays WCAG-AA legible.
*
* REDUCED MOTION: when `reduced`, render a static but gorgeous scene (a still
* nebula, a static starfield, a frozen galaxy and one frozen comet streak) with
* no `animation` at all. The settings preview always passes reduced=true.
*/
const STAR_TINTS = [
'oklch(0.98 0.02 280)', // starlight white
'oklch(0.9 0.07 230)', // cool cyan-white
'oklch(0.88 0.08 330)', // faint magenta-white
] as const;
const HERO_TINTS = [
'oklch(0.92 0.06 200)', // cyan starlight
'oklch(0.9 0.09 330)', // magenta starlight
'oklch(0.98 0.02 280)', // pure starlight
] as const;
type Star = {
top: number;
left: number;
size: number;
color: string;
duration: number;
delay: number;
staticOpacity: number;
};
type HeroStar = Star;
type Comet = {
top: number;
left: number;
length: number;
angle: number;
color: string;
duration: number;
delay: number;
};
// Deterministic pseudo-random so the memoized scene is stable across renders.
const rand = (seed: number) => {
const x = Math.sin(seed * 12.9898 + 78.233) * 43758.5453;
return x - Math.floor(x);
};
// A four-point gleam (sparkle) as an inline SVG data-URI — CSP-safe, no assets.
const gleamUri = (color: string) =>
`url("data:image/svg+xml,${encodeURIComponent(
``,
)}")`;
function makeStars(count: number, seedBase: number): Star[] {
return Array.from({ length: count }, (_, i) => {
const s = seedBase + i;
return {
top: rand(s + 1) * 100,
left: rand(s + 101) * 100,
size: 1 + Math.floor(rand(s + 201) * 2), // 1–2px tiny stars
color: STAR_TINTS[i % STAR_TINTS.length],
duration: 2.6 + rand(s + 301) * 3.4,
delay: rand(s + 401) * 5,
staticOpacity: 0.4 + rand(s + 501) * 0.55,
};
});
}
export function DeepSpaceOverlay({ reduced }: SeasonalOverlayProps) {
// Two parallax depths. Far = dense + faint, Near = sparser + slightly larger.
const farStars = useMemo(() => makeStars(40, 1000), []);
const nearStars = useMemo(() => makeStars(22, 2000), []);
const heroStars = useMemo(
() =>
Array.from({ length: 6 }, (_, i) => {
const s = 3000 + i;
return {
top: 6 + rand(s + 1) * 78,
left: 6 + rand(s + 101) * 88,
size: 9 + Math.floor(rand(s + 201) * 9), // 9–17px gleams
color: HERO_TINTS[i % HERO_TINTS.length],
duration: 4 + rand(s + 301) * 4,
delay: rand(s + 401) * 5,
staticOpacity: 0.85,
};
}),
[],
);
const comets = useMemo(
() =>
Array.from({ length: 3 }, (_, i) => {
const s = 4000 + i;
return {
top: 8 + rand(s + 1) * 44,
left: -10 + rand(s + 101) * 30,
length: 120 + Math.floor(rand(s + 201) * 120),
angle: 18 + rand(s + 301) * 16, // gentle downward diagonal
color: i % 2 === 0 ? 'oklch(0.92 0.06 200)' : 'oklch(0.9 0.09 330)',
duration: 7 + rand(s + 401) * 5,
delay: 2 + i * 6 + rand(s + 501) * 4,
};
}),
[],
);
return (
<>
{/* Deep cosmic void — layered oklch radial gradients for depth. A barely
perceptible drift gives the whole field life without distraction. */}
{/* Drifting nebula clouds — blurred radial gradients in magenta + cyan. */}
{/* A third, central violet wash to bind the two color clouds together. */}
{/* Faint distant galaxy spiral — an inline conic-ish swirl from layered
radial gradients, blurred and very slowly rotating. */}
{/* Far parallax starfield — dense, faint, tiny twinkling stars. */}
{farStars.map((s, i) => (
))}
{/* Near parallax starfield — sparser, brighter, drifts a touch faster. */}
{nearStars.map((s, i) => (
))}
{/* Hero stars — a few bright four-point gleams that pulse slowly. */}
{heroStars.map((s, i) => (
))}
{/* Comet / warp streaks. In reduced mode, freeze a single streak mid-flight
so the static thumbnail reads as a living cosmos. */}
{(reduced ? comets.slice(0, 1) : comets).map((c, i) => (