import type { ComponentPropsWithoutRef, ElementType, ReactNode } from 'react' import { cn } from '../../lib/cn' /** How far the light bleeds. `soft` stays behind text; `bold` is a hero. */ export type AuroraIntensity = 'soft' | 'medium' | 'bold' const INTENSITY: Record = { soft: { opacity: 0.4, blur: 70, scale: 0.85 }, medium: { opacity: 0.62, blur: 58, scale: 1 }, bold: { opacity: 0.85, blur: 46, scale: 1.2 }, } /** The three drifting blobs. Each has its own path, so they never sync up. */ const BLOBS = [ { animation: 'aurora-a', duration: 17, top: '-25%', left: '-15%', size: '70%' }, { animation: 'aurora-b', duration: 23, top: '-10%', left: '35%', size: '80%' }, { animation: 'aurora-c', duration: 29, top: '20%', left: '5%', size: '65%' }, ] export interface AuroraSurfaceOwnProps { /** Content laid over the aurora. */ children?: ReactNode /** Three colours, one per blob. Defaults to the accent family. */ colors?: [string, string, string] intensity?: AuroraIntensity /** Overlay a fine grain so the gradient never bands on wide screens. */ grain?: boolean /** Freeze the blobs where they are. */ paused?: boolean /** Merged last, so it wins. */ className?: string /** Classes for the content layer above the light. */ contentClassName?: string } type AuroraSurfaceProps = AuroraSurfaceOwnProps & { /** Element to render. */ as?: E } & Omit, keyof AuroraSurfaceOwnProps | 'as'> /** * A container lit from behind by three slowly drifting colour fields. * * The effect is three blurred radial gradients on their own transform loops at * co-prime durations, so the composite never visibly repeats. Only `transform` * animates — the blur is set once and never recalculated — which is what keeps * a full-bleed hero at 60fps where an animated `filter` would not. * * The light sits in an `aria-hidden` layer under the content and the whole * thing clips itself, so it can be dropped behind real UI without changing any * of the contrast or focus behaviour above it. */ export function AuroraSurface({ as, children, colors = ['var(--color-accent)', '#7fd4ff', 'var(--color-accent-soft)'], intensity = 'medium', grain = false, paused = false, className, contentClassName, ...rest }: AuroraSurfaceProps) { const Component = (as ?? 'div') as ElementType const { opacity, blur, scale } = INTENSITY[intensity] return (