/** * Hero background SPEC — the pure, React-free core of the hero-background resolver. * * This module is importable on a backend / server runtime (the cascade) with ZERO * React in its dependency graph: it holds only the TYPES, the legal-space rules, * the named-preset menu, and the layer-descriptor logic. The React renderer that * turns a descriptor into JSX lives in ./hero-background.tsx and imports from here. * * - The TYPES make every illegal background unrepresentable (Beams never combines, * a Spotlight only pairs with a `top` grid, Ambient never mixes with Visual, * a combined Glow has no position — it inherits the grid's). * - `heroBackgroundLayers(spec)` resolves a spec to the ordered, named layer * descriptors (`{ name, props }`) — pure data, no components. * - `HERO_BACKGROUNDS` is the named-preset menu (legal-by-construction shortcuts). * - `allLegalHeroBackgrounds()` enumerates the FULL legal space (every legal * shape, including the Pattern+Ambient and Spotlight+top-grid COMBINATIONS) so a * consumer can draw a varied background per site without re-implementing the rules. */ type GridStyle = 'dashed' | 'diagonal' | 'sparse' | 'crosshatch' | 'perspective'; interface GridPositions { dashed: 'top' | 'center' | 'bottom'; diagonal: 'top' | 'center'; sparse: 'top' | 'center'; crosshatch: 'top' | 'center'; perspective: 'top' | 'bottom'; } type PatternBackground = { [S in GridStyle]: { style: S; position: GridPositions[S]; animate?: boolean; animationDelay?: number; }; }[GridStyle]; /** A grid pinned to the top — the only patterns a Spotlight may pair with (R2). */ type TopGridPattern = { style: GridStyle; position: 'top'; animate?: boolean; animationDelay?: number; }; type GlowColor = 'primary' | 'accent' | 'muted'; type GlowPosition = 'top' | 'center' | 'bottom'; /** Ambient alone — a glow picks its own position. */ type AmbientBackground = { kind: 'glow'; position?: GlowPosition; color?: GlowColor; animate?: boolean; } | { kind: 'gradientBlur'; }; /** Ambient combined with a pattern — a glow has NO position; it inherits the grid's (R1/R5). */ type AmbientCombine = { kind: 'glow'; color?: GlowColor; animate?: boolean; } | { kind: 'gradientBlur'; }; type SpotlightColor = 'primary' | 'accent' | 'muted' | 'foreground'; type SpotlightPosition = 'top-left' | 'top-right'; type BeamsPosition = 'center' | 'top'; interface PatternSection { pattern: PatternBackground; ambient?: AmbientCombine; } interface AmbientSection { ambient: AmbientBackground; } interface SpotlightSection { visual: { kind: 'spotlight'; position?: SpotlightPosition; color?: SpotlightColor; animate?: boolean; }; pattern?: TopGridPattern; } interface BeamsSection { visual: { kind: 'beams'; position?: BeamsPosition; }; } type SectionBackground = PatternSection | AmbientSection | SpotlightSection | BeamsSection; interface PageBackground { noise?: { fixed?: boolean; }; } type ComponentName = 'GridDashedTop' | 'GridDashedCenter' | 'GridDashedBottom' | 'GridDiagonalTop' | 'GridDiagonalCenter' | 'GridSparseTop' | 'GridSparseCenter' | 'GridCrosshatchTop' | 'GridCrosshatchCenter' | 'GridPerspectiveTop' | 'GridPerspectiveBottom' | 'GlowTop' | 'GlowCenter' | 'GlowBottom' | 'GradientBlur' | 'SpotlightTopLeft' | 'SpotlightTopRight' | 'Beams' | 'BeamsTop'; type HeroBackgroundLayer = { name: ComponentName; props: Record; }; /** * The ordered layer descriptors for a spec — exported so the rules are unit-testable * without scraping the DOM. Render order (R5): the grid Pattern is the base layer * (painted first / behind); the accent (Ambient wash or Spotlight) is painted last * (in front). Beams always renders alone (R3). */ declare function heroBackgroundLayers(bg: SectionBackground): HeroBackgroundLayer[]; declare const HERO_BACKGROUNDS: { 'dashed-top': { pattern: { style: "dashed"; position: "top"; }; }; 'perspective-bottom': { pattern: { style: "perspective"; position: "bottom"; }; }; 'crosshatch-top': { pattern: { style: "crosshatch"; position: "top"; }; }; 'dashed-top + blur': { pattern: { style: "dashed"; position: "top"; }; ambient: { kind: "gradientBlur"; }; }; 'dashed-top + glow': { pattern: { style: "dashed"; position: "top"; }; ambient: { kind: "glow"; }; }; 'sparse-top + blur': { pattern: { style: "sparse"; position: "top"; }; ambient: { kind: "gradientBlur"; }; }; 'spotlight-top-left + dashed-top': { visual: { kind: "spotlight"; position: "top-left"; }; pattern: { style: "dashed"; position: "top"; }; }; 'spotlight-top-right + crosshatch-top': { visual: { kind: "spotlight"; position: "top-right"; }; pattern: { style: "crosshatch"; position: "top"; }; }; 'gradient-blur': { ambient: { kind: "gradientBlur"; }; }; 'glow-top': { ambient: { kind: "glow"; position: "top"; }; }; 'spotlight-top-left': { visual: { kind: "spotlight"; position: "top-left"; }; }; 'beams-center': { visual: { kind: "beams"; }; }; 'beams-top': { visual: { kind: "beams"; position: "top"; }; }; }; type HeroBackgroundPreset = keyof typeof HERO_BACKGROUNDS; /** * Every legal `SectionBackground`, generated from the rules (not hand-listed) in a * STABLE order — so a seeded draw maps the same seed to the same background. Covers * all six legal shapes, INCLUDING the Pattern+Ambient and Spotlight+top-grid * combinations (so a draw yields layered backgrounds, not just single components). */ declare function allLegalHeroBackgrounds(): SectionBackground[]; export { type AmbientBackground, type AmbientCombine, type AmbientSection, type BeamsPosition, type BeamsSection, type ComponentName, type GlowColor, type GlowPosition, type GridPositions, type GridStyle, HERO_BACKGROUNDS, type HeroBackgroundLayer, type HeroBackgroundPreset, type PageBackground, type PatternBackground, type PatternSection, type SectionBackground, type SpotlightColor, type SpotlightPosition, type SpotlightSection, type TopGridPattern, allLegalHeroBackgrounds, heroBackgroundLayers };