@autumnsgrove/gossamer 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../src/renderer.ts","../src/patterns.ts","../src/characters.ts","../src/animation.ts","../src/utils/canvas.ts","../src/utils/image.ts","../src/utils/performance.ts","../src/index.ts"],"sourcesContent":["/**\n * Gossamer Core Renderer\n *\n * Canvas-based ASCII rendering engine. Converts image data to ASCII characters\n * by mapping brightness values to a character set.\n */\n\n// Define locally to avoid circular dependency with index.ts\nconst DEFAULT_CHARACTERS = ' .:-=+*#%@';\n\nfunction calculateBrightness(r: number, g: number, b: number): number {\n return 0.21 * r + 0.72 * g + 0.07 * b;\n}\n\n/**\n * Configuration for the Gossamer renderer\n */\nexport interface RenderConfig {\n /** Canvas element to render to */\n canvas: HTMLCanvasElement;\n /** Character set ordered from light to dark */\n characters: string;\n /** Width of each character cell in pixels */\n cellWidth: number;\n /** Height of each character cell in pixels */\n cellHeight: number;\n /** Color for rendering characters */\n color: string;\n /** Background color (empty string for transparent) */\n backgroundColor: string;\n /** Font family */\n fontFamily: string;\n /** Custom brightness calculation function */\n brightnessFunction: (r: number, g: number, b: number) => number;\n}\n\n/**\n * Default render configuration\n */\nconst DEFAULT_RENDER_CONFIG: Omit<RenderConfig, 'canvas'> = {\n characters: DEFAULT_CHARACTERS,\n cellWidth: 8,\n cellHeight: 12,\n color: '#ffffff',\n backgroundColor: '',\n fontFamily: 'monospace',\n brightnessFunction: calculateBrightness,\n};\n\n/**\n * Core ASCII renderer class\n *\n * Handles all canvas rendering operations for ASCII effects.\n * Supports both static rendering and animation loops.\n */\nexport class GossamerRenderer {\n private ctx: CanvasRenderingContext2D;\n private config: RenderConfig;\n private animationId: number | null = null;\n private lastFrameTime: number = 0;\n private isRunning: boolean = false;\n\n constructor(canvas: HTMLCanvasElement, config: Partial<Omit<RenderConfig, 'canvas'>> = {}) {\n const context = canvas.getContext('2d');\n if (!context) {\n throw new Error('Failed to get 2D rendering context');\n }\n\n this.ctx = context;\n this.config = {\n canvas,\n ...DEFAULT_RENDER_CONFIG,\n ...config,\n };\n\n this.setupCanvas();\n }\n\n /**\n * Set up the canvas with optimal rendering settings\n */\n private setupCanvas(): void {\n const { fontFamily, cellHeight } = this.config;\n\n // Set font for consistent character sizing\n this.ctx.font = `${cellHeight}px ${fontFamily}`;\n this.ctx.textBaseline = 'top';\n\n // Enable image smoothing for better quality\n this.ctx.imageSmoothingEnabled = true;\n this.ctx.imageSmoothingQuality = 'high';\n }\n\n /**\n * Update the renderer configuration\n */\n updateConfig(config: Partial<Omit<RenderConfig, 'canvas'>>): void {\n this.config = { ...this.config, ...config };\n this.setupCanvas();\n }\n\n /**\n * Resize the canvas to match new dimensions\n */\n resize(width: number, height: number): void {\n const { canvas } = this.config;\n canvas.width = width;\n canvas.height = height;\n this.setupCanvas();\n }\n\n /**\n * Get the current canvas dimensions\n */\n getDimensions(): { width: number; height: number } {\n return {\n width: this.config.canvas.width,\n height: this.config.canvas.height,\n };\n }\n\n /**\n * Calculate the number of cells that fit in the canvas\n */\n getCellCount(): { cols: number; rows: number } {\n const { width, height } = this.getDimensions();\n const { cellWidth, cellHeight } = this.config;\n\n return {\n cols: Math.ceil(width / cellWidth),\n rows: Math.ceil(height / cellHeight),\n };\n }\n\n /**\n * Clear the canvas\n */\n clear(): void {\n const { canvas, backgroundColor } = this.config;\n\n if (backgroundColor) {\n this.ctx.fillStyle = backgroundColor;\n this.ctx.fillRect(0, 0, canvas.width, canvas.height);\n } else {\n this.ctx.clearRect(0, 0, canvas.width, canvas.height);\n }\n }\n\n /**\n * Render a single frame from image data\n */\n renderFrame(imageData: ImageData): void {\n const { canvas, characters, cellWidth, cellHeight, color, brightnessFunction } = this.config;\n const { width, data } = imageData;\n\n this.clear();\n this.ctx.fillStyle = color;\n\n for (let y = 0; y < canvas.height; y += cellHeight) {\n for (let x = 0; x < canvas.width; x += cellWidth) {\n const brightness = this.getCellBrightness(data, x, y, width, cellWidth, cellHeight, brightnessFunction);\n const charIndex = Math.floor((brightness / 255) * (characters.length - 1));\n const char = characters[Math.min(charIndex, characters.length - 1)];\n\n if (char !== ' ') {\n this.ctx.fillText(char, x, y);\n }\n }\n }\n }\n\n /**\n * Render ASCII from a brightness grid (for pattern-based rendering)\n */\n renderFromBrightnessGrid(grid: number[][]): void {\n const { characters, cellWidth, cellHeight, color } = this.config;\n\n this.clear();\n this.ctx.fillStyle = color;\n\n for (let row = 0; row < grid.length; row++) {\n for (let col = 0; col < grid[row].length; col++) {\n const brightness = grid[row][col];\n const charIndex = Math.floor((brightness / 255) * (characters.length - 1));\n const char = characters[Math.min(charIndex, characters.length - 1)];\n\n if (char !== ' ') {\n this.ctx.fillText(char, col * cellWidth, row * cellHeight);\n }\n }\n }\n }\n\n /**\n * Render ASCII with per-cell colors (for colored image rendering)\n */\n renderWithColors(data: Array<{ char: string; color: string; x: number; y: number }>): void {\n this.clear();\n\n for (const { char, color, x, y } of data) {\n if (char !== ' ') {\n this.ctx.fillStyle = color;\n this.ctx.fillText(char, x, y);\n }\n }\n }\n\n /**\n * Calculate average brightness for a cell region\n */\n private getCellBrightness(\n data: Uint8ClampedArray,\n startX: number,\n startY: number,\n imageWidth: number,\n cellWidth: number,\n cellHeight: number,\n brightnessFunction: (r: number, g: number, b: number) => number\n ): number {\n let total = 0;\n let count = 0;\n\n for (let cy = 0; cy < cellHeight; cy++) {\n for (let cx = 0; cx < cellWidth; cx++) {\n const px = ((startY + cy) * imageWidth + (startX + cx)) * 4;\n if (px >= 0 && px + 2 < data.length) {\n total += brightnessFunction(data[px], data[px + 1], data[px + 2]);\n count++;\n }\n }\n }\n\n return count > 0 ? total / count : 0;\n }\n\n /**\n * Start an animation loop with FPS limiting\n */\n startAnimation(\n updateFn: (time: number, deltaTime: number) => ImageData | number[][],\n fps: number = 30\n ): void {\n if (this.isRunning) {\n this.stopAnimation();\n }\n\n this.isRunning = true;\n const frameInterval = 1000 / fps;\n this.lastFrameTime = performance.now();\n\n const animate = (currentTime: number): void => {\n if (!this.isRunning) return;\n\n const deltaTime = currentTime - this.lastFrameTime;\n\n if (deltaTime >= frameInterval) {\n const result = updateFn(currentTime, deltaTime);\n\n if (result instanceof ImageData) {\n this.renderFrame(result);\n } else {\n this.renderFromBrightnessGrid(result);\n }\n\n this.lastFrameTime = currentTime - (deltaTime % frameInterval);\n }\n\n this.animationId = requestAnimationFrame(animate);\n };\n\n this.animationId = requestAnimationFrame(animate);\n }\n\n /**\n * Stop the animation loop\n */\n stopAnimation(): void {\n this.isRunning = false;\n if (this.animationId !== null) {\n cancelAnimationFrame(this.animationId);\n this.animationId = null;\n }\n }\n\n /**\n * Check if animation is currently running\n */\n isAnimating(): boolean {\n return this.isRunning;\n }\n\n /**\n * Pause animation (can be resumed)\n */\n pause(): void {\n this.isRunning = false;\n if (this.animationId !== null) {\n cancelAnimationFrame(this.animationId);\n this.animationId = null;\n }\n }\n\n /**\n * Clean up and destroy the renderer\n */\n destroy(): void {\n this.stopAnimation();\n }\n}\n","/**\n * Gossamer Pattern Generators\n *\n * Provides noise and pattern generation functions for ambient ASCII effects.\n * Includes Perlin noise, wave patterns, and static noise.\n */\n\n/**\n * Configuration for pattern generation\n */\nexport interface PatternConfig {\n /** Pattern scale - higher values create finer detail */\n frequency: number;\n /** Pattern intensity multiplier */\n amplitude: number;\n /** Animation speed multiplier */\n speed: number;\n}\n\n/**\n * Default pattern configuration\n */\nexport const DEFAULT_PATTERN_CONFIG: PatternConfig = {\n frequency: 0.05,\n amplitude: 1.0,\n speed: 0.5,\n};\n\n// Permutation table for Perlin noise\nconst PERMUTATION = new Uint8Array(512);\nconst P = new Uint8Array([\n 151, 160, 137, 91, 90, 15, 131, 13, 201, 95, 96, 53, 194, 233, 7, 225, 140, 36, 103, 30, 69, 142,\n 8, 99, 37, 240, 21, 10, 23, 190, 6, 148, 247, 120, 234, 75, 0, 26, 197, 62, 94, 252, 219, 203,\n 117, 35, 11, 32, 57, 177, 33, 88, 237, 149, 56, 87, 174, 20, 125, 136, 171, 168, 68, 175, 74, 165,\n 71, 134, 139, 48, 27, 166, 77, 146, 158, 231, 83, 111, 229, 122, 60, 211, 133, 230, 220, 105, 92,\n 41, 55, 46, 245, 40, 244, 102, 143, 54, 65, 25, 63, 161, 1, 216, 80, 73, 209, 76, 132, 187, 208,\n 89, 18, 169, 200, 196, 135, 130, 116, 188, 159, 86, 164, 100, 109, 198, 173, 186, 3, 64, 52, 217,\n 226, 250, 124, 123, 5, 202, 38, 147, 118, 126, 255, 82, 85, 212, 207, 206, 59, 227, 47, 16, 58,\n 17, 182, 189, 28, 42, 223, 183, 170, 213, 119, 248, 152, 2, 44, 154, 163, 70, 221, 153, 101, 155,\n 167, 43, 172, 9, 129, 22, 39, 253, 19, 98, 108, 110, 79, 113, 224, 232, 178, 185, 112, 104, 218,\n 246, 97, 228, 251, 34, 242, 193, 238, 210, 144, 12, 191, 179, 162, 241, 81, 51, 145, 235, 249,\n 14, 239, 107, 49, 192, 214, 31, 181, 199, 106, 157, 184, 84, 204, 176, 115, 121, 50, 45, 127, 4,\n 150, 254, 138, 236, 205, 93, 222, 114, 67, 29, 24, 72, 243, 141, 128, 195, 78, 66, 215, 61, 156,\n 180,\n]);\n\n// Initialize permutation table\nfor (let i = 0; i < 256; i++) {\n PERMUTATION[i] = P[i];\n PERMUTATION[i + 256] = P[i];\n}\n\n/**\n * Fade function for smooth interpolation (6t^5 - 15t^4 + 10t^3)\n */\nfunction fade(t: number): number {\n return t * t * t * (t * (t * 6 - 15) + 10);\n}\n\n/**\n * Linear interpolation\n */\nfunction lerp(a: number, b: number, t: number): number {\n return a + t * (b - a);\n}\n\n/**\n * Gradient function for Perlin noise\n */\nfunction grad(hash: number, x: number, y: number): number {\n const h = hash & 3;\n const u = h < 2 ? x : y;\n const v = h < 2 ? y : x;\n return ((h & 1) === 0 ? u : -u) + ((h & 2) === 0 ? v : -v);\n}\n\n/**\n * 2D Perlin noise function\n *\n * @param x - X coordinate\n * @param y - Y coordinate\n * @returns Noise value between -1 and 1\n */\nexport function perlinNoise2D(x: number, y: number): number {\n // Find unit square containing point\n const xi = Math.floor(x) & 255;\n const yi = Math.floor(y) & 255;\n\n // Find relative position in square\n const xf = x - Math.floor(x);\n const yf = y - Math.floor(y);\n\n // Fade curves\n const u = fade(xf);\n const v = fade(yf);\n\n // Hash coordinates of square corners\n const aa = PERMUTATION[PERMUTATION[xi] + yi];\n const ab = PERMUTATION[PERMUTATION[xi] + yi + 1];\n const ba = PERMUTATION[PERMUTATION[xi + 1] + yi];\n const bb = PERMUTATION[PERMUTATION[xi + 1] + yi + 1];\n\n // Blend results from 4 corners\n const x1 = lerp(grad(aa, xf, yf), grad(ba, xf - 1, yf), u);\n const x2 = lerp(grad(ab, xf, yf - 1), grad(bb, xf - 1, yf - 1), u);\n\n return lerp(x1, x2, v);\n}\n\n/**\n * Fractal Brownian Motion (fBm) using Perlin noise\n * Creates more organic-looking noise by layering multiple octaves\n *\n * @param x - X coordinate\n * @param y - Y coordinate\n * @param octaves - Number of noise layers (default: 4)\n * @param persistence - Amplitude decay per octave (default: 0.5)\n * @returns Noise value between -1 and 1\n */\nexport function fbmNoise(x: number, y: number, octaves: number = 4, persistence: number = 0.5): number {\n let total = 0;\n let frequency = 1;\n let amplitude = 1;\n let maxValue = 0;\n\n for (let i = 0; i < octaves; i++) {\n total += perlinNoise2D(x * frequency, y * frequency) * amplitude;\n maxValue += amplitude;\n amplitude *= persistence;\n frequency *= 2;\n }\n\n return total / maxValue;\n}\n\n/**\n * Wave pattern generator\n *\n * @param x - X coordinate\n * @param y - Y coordinate\n * @param time - Time value for animation\n * @param config - Pattern configuration\n * @returns Value between -1 and 1\n */\nexport function wavePattern(\n x: number,\n y: number,\n time: number,\n config: PatternConfig = DEFAULT_PATTERN_CONFIG\n): number {\n const { frequency, amplitude, speed } = config;\n const wave1 = Math.sin(x * frequency + time * speed);\n const wave2 = Math.cos(y * frequency + time * speed * 0.7);\n const wave3 = Math.sin((x + y) * frequency * 0.5 + time * speed * 0.5);\n\n return ((wave1 + wave2 + wave3) / 3) * amplitude;\n}\n\n/**\n * Ripple pattern (concentric waves from center)\n *\n * @param x - X coordinate\n * @param y - Y coordinate\n * @param centerX - Ripple center X\n * @param centerY - Ripple center Y\n * @param time - Time value for animation\n * @param config - Pattern configuration\n * @returns Value between -1 and 1\n */\nexport function ripplePattern(\n x: number,\n y: number,\n centerX: number,\n centerY: number,\n time: number,\n config: PatternConfig = DEFAULT_PATTERN_CONFIG\n): number {\n const { frequency, amplitude, speed } = config;\n const dx = x - centerX;\n const dy = y - centerY;\n const distance = Math.sqrt(dx * dx + dy * dy);\n\n return Math.sin(distance * frequency - time * speed) * amplitude;\n}\n\n/**\n * Static noise generator (random values)\n *\n * @param seed - Optional seed for reproducible noise\n * @returns Value between 0 and 1\n */\nexport function staticNoise(seed?: number): number {\n if (seed !== undefined) {\n // Simple seeded random using sine\n const x = Math.sin(seed * 12.9898) * 43758.5453;\n return x - Math.floor(x);\n }\n return Math.random();\n}\n\n/**\n * Seeded 2D noise for reproducible patterns\n *\n * @param x - X coordinate\n * @param y - Y coordinate\n * @param seed - Seed value\n * @returns Value between 0 and 1\n */\nexport function seededNoise2D(x: number, y: number, seed: number = 0): number {\n const n = Math.sin(x * 12.9898 + y * 78.233 + seed) * 43758.5453;\n return n - Math.floor(n);\n}\n\n/**\n * Generate a brightness grid for pattern rendering\n *\n * @param cols - Number of columns\n * @param rows - Number of rows\n * @param pattern - Pattern type\n * @param time - Current time in seconds\n * @param config - Pattern configuration\n * @returns 2D array of brightness values (0-255)\n */\nexport function generateBrightnessGrid(\n cols: number,\n rows: number,\n pattern: 'perlin' | 'waves' | 'static' | 'ripple' | 'fbm',\n time: number = 0,\n config: PatternConfig = DEFAULT_PATTERN_CONFIG\n): number[][] {\n const grid: number[][] = [];\n const { frequency, amplitude, speed } = config;\n\n for (let row = 0; row < rows; row++) {\n grid[row] = [];\n for (let col = 0; col < cols; col++) {\n let value: number;\n\n switch (pattern) {\n case 'perlin':\n value = perlinNoise2D(\n col * frequency + time * speed * 0.1,\n row * frequency + time * speed * 0.05\n );\n break;\n\n case 'fbm':\n value = fbmNoise(\n col * frequency + time * speed * 0.1,\n row * frequency + time * speed * 0.05,\n 4,\n 0.5\n );\n break;\n\n case 'waves':\n value = wavePattern(col, row, time, config);\n break;\n\n case 'ripple':\n value = ripplePattern(col, row, cols / 2, rows / 2, time, config);\n break;\n\n case 'static':\n default:\n // For static, use time as seed for animated static\n value = seededNoise2D(col, row, Math.floor(time * speed * 10)) * 2 - 1;\n break;\n }\n\n // Normalize from [-1, 1] to [0, 255] with amplitude\n const normalized = (value + 1) * 0.5 * amplitude;\n const brightness = Math.max(0, Math.min(255, Math.floor(normalized * 255)));\n grid[row][col] = brightness;\n }\n }\n\n return grid;\n}\n\n/**\n * Generate ImageData from a brightness grid\n *\n * @param grid - 2D array of brightness values\n * @param cellWidth - Width of each cell\n * @param cellHeight - Height of each cell\n * @returns ImageData object\n */\nexport function gridToImageData(grid: number[][], cellWidth: number, cellHeight: number): ImageData {\n const rows = grid.length;\n const cols = grid[0]?.length || 0;\n const width = cols * cellWidth;\n const height = rows * cellHeight;\n const data = new Uint8ClampedArray(width * height * 4);\n\n for (let row = 0; row < rows; row++) {\n for (let col = 0; col < cols; col++) {\n const brightness = grid[row][col];\n\n // Fill cell region with brightness value\n for (let cy = 0; cy < cellHeight; cy++) {\n for (let cx = 0; cx < cellWidth; cx++) {\n const px = ((row * cellHeight + cy) * width + (col * cellWidth + cx)) * 4;\n data[px] = brightness; // R\n data[px + 1] = brightness; // G\n data[px + 2] = brightness; // B\n data[px + 3] = 255; // A\n }\n }\n }\n }\n\n return new ImageData(data, width, height);\n}\n\nexport type PatternType = 'perlin' | 'waves' | 'static' | 'ripple' | 'fbm';\n","/**\n * Gossamer Character Sets\n *\n * Predefined character sets for ASCII rendering, ordered from light to dark.\n * Character density determines which character represents each brightness level.\n */\n\n/**\n * Character set configuration\n */\nexport interface CharacterSet {\n /** Unique identifier for the character set */\n name: string;\n /** Description of the set's aesthetic */\n description: string;\n /** Characters ordered from lightest (space) to darkest */\n characters: string;\n /** Recommended use cases */\n bestFor: string[];\n}\n\n/**\n * Standard character sets for ASCII rendering\n */\nexport const CHARACTER_SETS: Record<string, CharacterSet> = {\n standard: {\n name: 'Standard',\n description: 'Classic ASCII art character set',\n characters: ' .:-=+*#%@',\n bestFor: ['general', 'images', 'patterns'],\n },\n\n dense: {\n name: 'Dense',\n description: 'High detail character set with many gradations',\n characters: \" .'`^\\\",:;Il!i><~+_-?][}{1)(|\\\\/tfjrxnuvczXYUJCLQ0OZmwqpdbkhao*#MW&8%B@$\",\n bestFor: ['detailed images', 'portraits', 'high contrast'],\n },\n\n minimal: {\n name: 'Minimal',\n description: 'Clean and simple with few characters',\n characters: ' .:*#',\n bestFor: ['backgrounds', 'subtle effects', 'clean aesthetic'],\n },\n\n grove: {\n name: 'Grove',\n description: 'Organic, soft characters inspired by nature',\n characters: ' ·∙•◦○◉●',\n bestFor: ['organic patterns', 'soft backgrounds', 'nature themes'],\n },\n\n dots: {\n name: 'Dots',\n description: 'Braille-like dot patterns',\n characters: ' ⋅∘∙●',\n bestFor: ['stipple effects', 'pointillism', 'dotted textures'],\n },\n\n blocks: {\n name: 'Blocks',\n description: 'Block-based characters for sharp edges',\n characters: ' ░▒▓█',\n bestFor: ['retro effects', 'pixel art', 'bold patterns'],\n },\n\n lines: {\n name: 'Lines',\n description: 'Line-based characters for directional effects',\n characters: ' -─═╌│┃',\n bestFor: ['rain effects', 'streaks', 'motion blur'],\n },\n\n stars: {\n name: 'Stars',\n description: 'Star and sparkle characters',\n characters: ' ·✧✦✫✬✯★',\n bestFor: ['sparkle effects', 'night sky', 'magical themes'],\n },\n\n nature: {\n name: 'Nature',\n description: 'Nature-themed decorative characters',\n characters: ' .~≈∿⌇☘',\n bestFor: ['decorative', 'themed effects', 'organic patterns'],\n },\n\n weather: {\n name: 'Weather',\n description: 'Weather-related symbols',\n characters: ' ·.:*❄❅❆',\n bestFor: ['snow effects', 'weather simulations', 'seasonal themes'],\n },\n\n binary: {\n name: 'Binary',\n description: 'Digital-style binary characters',\n characters: ' 01',\n bestFor: ['digital effects', 'matrix style', 'tech themes'],\n },\n\n math: {\n name: 'Math',\n description: 'Mathematical symbols',\n characters: ' +-×÷=≠≈∞',\n bestFor: ['abstract patterns', 'tech themes', 'decorative'],\n },\n};\n\n/**\n * Get a character set by name\n */\nexport function getCharacterSet(name: string): CharacterSet | undefined {\n return CHARACTER_SETS[name];\n}\n\n/**\n * Get just the characters string from a named set\n */\nexport function getCharacters(name: string): string {\n return CHARACTER_SETS[name]?.characters || CHARACTER_SETS.standard.characters;\n}\n\n/**\n * List all available character set names\n */\nexport function getCharacterSetNames(): string[] {\n return Object.keys(CHARACTER_SETS);\n}\n\n/**\n * Create a custom character set\n */\nexport function createCharacterSet(\n name: string,\n characters: string,\n description: string = '',\n bestFor: string[] = []\n): CharacterSet {\n return {\n name,\n description,\n characters,\n bestFor,\n };\n}\n\n/**\n * Validate that a character string is suitable for ASCII rendering\n * (should start with space and have at least 2 characters)\n */\nexport function validateCharacterSet(characters: string): boolean {\n if (characters.length < 2) return false;\n if (characters[0] !== ' ') return false;\n return true;\n}\n\n/**\n * Reverse a character set (for inverted brightness mapping)\n */\nexport function invertCharacters(characters: string): string {\n return characters.split('').reverse().join('');\n}\n","/**\n * Gossamer Animation Utilities\n *\n * FPS limiting, animation loop management, and timing utilities.\n */\n\n/**\n * Animation state for tracking loop execution\n */\nexport interface AnimationState {\n /** Whether animation is currently running */\n isRunning: boolean;\n /** Current animation frame ID */\n frameId: number | null;\n /** Timestamp of last frame */\n lastFrameTime: number;\n /** Frame interval in ms (derived from FPS) */\n frameInterval: number;\n /** Total elapsed time in ms */\n elapsedTime: number;\n /** Current frame count */\n frameCount: number;\n}\n\n/**\n * Options for creating an animation loop\n */\nexport interface AnimationOptions {\n /** Target frames per second (default: 30) */\n fps?: number;\n /** Callback when animation starts */\n onStart?: () => void;\n /** Callback when animation stops */\n onStop?: () => void;\n /** Callback for each frame - return false to stop */\n onFrame: (time: number, deltaTime: number, frameCount: number) => boolean | void;\n}\n\n/**\n * Create a managed animation loop with FPS limiting\n */\nexport function createAnimationLoop(options: AnimationOptions): {\n start: () => void;\n stop: () => void;\n pause: () => void;\n resume: () => void;\n getState: () => AnimationState;\n} {\n const { fps = 30, onStart, onStop, onFrame } = options;\n\n const state: AnimationState = {\n isRunning: false,\n frameId: null,\n lastFrameTime: 0,\n frameInterval: 1000 / fps,\n elapsedTime: 0,\n frameCount: 0,\n };\n\n let pausedTime = 0;\n let isPaused = false;\n\n function animate(currentTime: number): void {\n if (!state.isRunning || isPaused) return;\n\n const deltaTime = currentTime - state.lastFrameTime;\n\n if (deltaTime >= state.frameInterval) {\n state.elapsedTime += deltaTime;\n state.frameCount++;\n\n const continueAnimation = onFrame(currentTime, deltaTime, state.frameCount);\n\n if (continueAnimation === false) {\n stop();\n return;\n }\n\n // Adjust for frame timing drift\n state.lastFrameTime = currentTime - (deltaTime % state.frameInterval);\n }\n\n state.frameId = requestAnimationFrame(animate);\n }\n\n function start(): void {\n if (state.isRunning) return;\n\n state.isRunning = true;\n state.lastFrameTime = performance.now();\n state.elapsedTime = 0;\n state.frameCount = 0;\n isPaused = false;\n\n onStart?.();\n state.frameId = requestAnimationFrame(animate);\n }\n\n function stop(): void {\n state.isRunning = false;\n isPaused = false;\n\n if (state.frameId !== null) {\n cancelAnimationFrame(state.frameId);\n state.frameId = null;\n }\n\n onStop?.();\n }\n\n function pause(): void {\n if (!state.isRunning || isPaused) return;\n\n isPaused = true;\n pausedTime = performance.now();\n\n if (state.frameId !== null) {\n cancelAnimationFrame(state.frameId);\n state.frameId = null;\n }\n }\n\n function resume(): void {\n if (!state.isRunning || !isPaused) return;\n\n isPaused = false;\n // Adjust lastFrameTime to account for paused duration\n state.lastFrameTime += performance.now() - pausedTime;\n state.frameId = requestAnimationFrame(animate);\n }\n\n function getState(): AnimationState {\n return { ...state };\n }\n\n return { start, stop, pause, resume, getState };\n}\n\n/**\n * Simple throttle function for limiting function execution\n */\nexport function throttle<T extends (...args: unknown[]) => unknown>(\n fn: T,\n limit: number\n): (...args: Parameters<T>) => void {\n let lastCall = 0;\n let timeout: ReturnType<typeof setTimeout> | null = null;\n\n return (...args: Parameters<T>): void => {\n const now = Date.now();\n\n if (now - lastCall >= limit) {\n lastCall = now;\n fn(...args);\n } else if (!timeout) {\n timeout = setTimeout(() => {\n lastCall = Date.now();\n timeout = null;\n fn(...args);\n }, limit - (now - lastCall));\n }\n };\n}\n\n/**\n * Debounce function for delaying execution until activity stops\n */\nexport function debounce<T extends (...args: unknown[]) => unknown>(\n fn: T,\n delay: number\n): (...args: Parameters<T>) => void {\n let timeout: ReturnType<typeof setTimeout> | null = null;\n\n return (...args: Parameters<T>): void => {\n if (timeout) {\n clearTimeout(timeout);\n }\n\n timeout = setTimeout(() => {\n timeout = null;\n fn(...args);\n }, delay);\n };\n}\n\n/**\n * Calculate actual FPS from frame times\n */\nexport function calculateFPS(frameTimes: number[], sampleSize: number = 60): number {\n if (frameTimes.length < 2) return 0;\n\n const samples = frameTimes.slice(-sampleSize);\n const totalTime = samples[samples.length - 1] - samples[0];\n const frameCount = samples.length - 1;\n\n if (totalTime <= 0) return 0;\n\n return (frameCount / totalTime) * 1000;\n}\n\n/**\n * Easing functions for smooth animations\n */\nexport const easings = {\n /** Linear - no easing */\n linear: (t: number): number => t,\n\n /** Ease in - slow start */\n easeIn: (t: number): number => t * t,\n\n /** Ease out - slow end */\n easeOut: (t: number): number => t * (2 - t),\n\n /** Ease in/out - slow start and end */\n easeInOut: (t: number): number => (t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t),\n\n /** Sine ease in */\n sineIn: (t: number): number => 1 - Math.cos((t * Math.PI) / 2),\n\n /** Sine ease out */\n sineOut: (t: number): number => Math.sin((t * Math.PI) / 2),\n\n /** Sine ease in/out */\n sineInOut: (t: number): number => -(Math.cos(Math.PI * t) - 1) / 2,\n\n /** Bounce at end */\n bounceOut: (t: number): number => {\n const n1 = 7.5625;\n const d1 = 2.75;\n\n if (t < 1 / d1) {\n return n1 * t * t;\n } else if (t < 2 / d1) {\n return n1 * (t -= 1.5 / d1) * t + 0.75;\n } else if (t < 2.5 / d1) {\n return n1 * (t -= 2.25 / d1) * t + 0.9375;\n } else {\n return n1 * (t -= 2.625 / d1) * t + 0.984375;\n }\n },\n};\n\nexport type EasingFunction = (t: number) => number;\n","/**\n * Canvas Utilities\n *\n * Helper functions for canvas creation, setup, and manipulation.\n */\n\n/**\n * Options for canvas creation\n */\nexport interface CanvasOptions {\n /** Canvas width in pixels */\n width?: number;\n /** Canvas height in pixels */\n height?: number;\n /** Whether to use high DPI scaling */\n highDPI?: boolean;\n /** CSS class to add to canvas */\n className?: string;\n /** Inline styles to apply */\n style?: Partial<CSSStyleDeclaration>;\n}\n\n/**\n * Create a canvas element with optimal settings\n */\nexport function createCanvas(options: CanvasOptions = {}): HTMLCanvasElement {\n const { width = 300, height = 150, highDPI = true, className, style } = options;\n\n const canvas = document.createElement('canvas');\n\n if (highDPI) {\n const dpr = window.devicePixelRatio || 1;\n canvas.width = width * dpr;\n canvas.height = height * dpr;\n canvas.style.width = `${width}px`;\n canvas.style.height = `${height}px`;\n\n const ctx = canvas.getContext('2d');\n if (ctx) {\n ctx.scale(dpr, dpr);\n }\n } else {\n canvas.width = width;\n canvas.height = height;\n }\n\n if (className) {\n canvas.className = className;\n }\n\n if (style) {\n Object.assign(canvas.style, style);\n }\n\n return canvas;\n}\n\n/**\n * Get the device pixel ratio\n */\nexport function getDevicePixelRatio(): number {\n return typeof window !== 'undefined' ? window.devicePixelRatio || 1 : 1;\n}\n\n/**\n * Resize canvas to match container dimensions\n */\nexport function resizeCanvasToContainer(\n canvas: HTMLCanvasElement,\n container: HTMLElement,\n highDPI: boolean = true\n): { width: number; height: number } {\n const rect = container.getBoundingClientRect();\n const dpr = highDPI ? getDevicePixelRatio() : 1;\n\n const width = rect.width;\n const height = rect.height;\n\n canvas.width = width * dpr;\n canvas.height = height * dpr;\n canvas.style.width = `${width}px`;\n canvas.style.height = `${height}px`;\n\n if (highDPI) {\n const ctx = canvas.getContext('2d');\n if (ctx) {\n ctx.scale(dpr, dpr);\n }\n }\n\n return { width, height };\n}\n\n/**\n * Create an offscreen canvas for buffer rendering\n */\nexport function createOffscreenCanvas(width: number, height: number): HTMLCanvasElement | OffscreenCanvas {\n if (typeof OffscreenCanvas !== 'undefined') {\n return new OffscreenCanvas(width, height);\n }\n\n // Fallback for environments without OffscreenCanvas\n const canvas = document.createElement('canvas');\n canvas.width = width;\n canvas.height = height;\n return canvas;\n}\n\n/**\n * Clear a canvas\n */\nexport function clearCanvas(\n ctx: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D,\n width: number,\n height: number,\n backgroundColor?: string\n): void {\n if (backgroundColor) {\n ctx.fillStyle = backgroundColor;\n ctx.fillRect(0, 0, width, height);\n } else {\n ctx.clearRect(0, 0, width, height);\n }\n}\n\n/**\n * Get image data from a canvas region\n */\nexport function getImageData(\n ctx: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D,\n x: number = 0,\n y: number = 0,\n width?: number,\n height?: number\n): ImageData {\n const canvas = ctx.canvas;\n const w = width ?? canvas.width;\n const h = height ?? canvas.height;\n\n return ctx.getImageData(x, y, w, h);\n}\n\n/**\n * Set optimal rendering context settings\n */\nexport function optimizeContext(ctx: CanvasRenderingContext2D): void {\n // Disable image smoothing for crisp ASCII rendering\n ctx.imageSmoothingEnabled = false;\n\n // Use source-over for standard compositing\n ctx.globalCompositeOperation = 'source-over';\n}\n\n/**\n * Set text rendering options for ASCII display\n */\nexport function setupTextRendering(\n ctx: CanvasRenderingContext2D,\n fontSize: number,\n fontFamily: string = 'monospace',\n color: string = '#ffffff'\n): void {\n ctx.font = `${fontSize}px ${fontFamily}`;\n ctx.textBaseline = 'top';\n ctx.textAlign = 'left';\n ctx.fillStyle = color;\n}\n\n/**\n * Measure text width for a given font configuration\n */\nexport function measureTextWidth(\n ctx: CanvasRenderingContext2D,\n text: string,\n fontSize: number,\n fontFamily: string = 'monospace'\n): number {\n const originalFont = ctx.font;\n ctx.font = `${fontSize}px ${fontFamily}`;\n const metrics = ctx.measureText(text);\n ctx.font = originalFont;\n return metrics.width;\n}\n\n/**\n * Calculate optimal cell size for a given canvas and desired columns\n */\nexport function calculateCellSize(\n canvasWidth: number,\n canvasHeight: number,\n targetCols: number\n): { cellWidth: number; cellHeight: number; cols: number; rows: number } {\n const cellWidth = Math.floor(canvasWidth / targetCols);\n // Use a typical monospace aspect ratio of ~0.6\n const cellHeight = Math.floor(cellWidth * 1.5);\n const cols = Math.floor(canvasWidth / cellWidth);\n const rows = Math.floor(canvasHeight / cellHeight);\n\n return { cellWidth, cellHeight, cols, rows };\n}\n\n/**\n * Apply a CSS blend mode to canvas compositing\n */\nexport function setBlendMode(\n ctx: CanvasRenderingContext2D,\n mode: 'normal' | 'multiply' | 'screen' | 'overlay' | 'darken' | 'lighten' | 'color-dodge' | 'color-burn' | 'soft-light' | 'hard-light' | 'difference' | 'exclusion'\n): void {\n ctx.globalCompositeOperation = mode === 'normal' ? 'source-over' : mode;\n}\n","/**\n * Image Utilities\n *\n * Image loading, processing, and pixel manipulation for ASCII conversion.\n */\n\n/**\n * Image loading options\n */\nexport interface ImageLoadOptions {\n /** Cross-origin setting for external images */\n crossOrigin?: 'anonymous' | 'use-credentials' | '';\n /** Maximum width to scale image to */\n maxWidth?: number;\n /** Maximum height to scale image to */\n maxHeight?: number;\n /** Whether to preserve aspect ratio when scaling */\n preserveAspectRatio?: boolean;\n}\n\n/**\n * Load an image from a URL\n */\nexport function loadImage(src: string, options: ImageLoadOptions = {}): Promise<HTMLImageElement> {\n return new Promise((resolve, reject) => {\n const img = new Image();\n\n if (options.crossOrigin !== undefined) {\n img.crossOrigin = options.crossOrigin;\n }\n\n img.onload = () => resolve(img);\n img.onerror = () => reject(new Error(`Failed to load image: ${src}`));\n\n img.src = src;\n });\n}\n\n/**\n * Load and scale an image to fit within bounds\n */\nexport async function loadAndScaleImage(\n src: string,\n maxWidth: number,\n maxHeight: number,\n options: ImageLoadOptions = {}\n): Promise<{ image: HTMLImageElement; width: number; height: number }> {\n const img = await loadImage(src, options);\n\n let width = img.naturalWidth;\n let height = img.naturalHeight;\n\n // Scale down if needed\n if (width > maxWidth || height > maxHeight) {\n const widthRatio = maxWidth / width;\n const heightRatio = maxHeight / height;\n const scale = Math.min(widthRatio, heightRatio);\n\n width = Math.floor(width * scale);\n height = Math.floor(height * scale);\n }\n\n return { image: img, width, height };\n}\n\n/**\n * Draw an image to a canvas and get its pixel data\n */\nexport function imageToPixelData(\n image: HTMLImageElement | HTMLCanvasElement | ImageBitmap,\n width?: number,\n height?: number\n): ImageData {\n const w = width ?? (image instanceof HTMLImageElement ? image.naturalWidth : image.width);\n const h = height ?? (image instanceof HTMLImageElement ? image.naturalHeight : image.height);\n\n const canvas = document.createElement('canvas');\n canvas.width = w;\n canvas.height = h;\n\n const ctx = canvas.getContext('2d');\n if (!ctx) {\n throw new Error('Failed to get 2D context');\n }\n\n ctx.drawImage(image, 0, 0, w, h);\n return ctx.getImageData(0, 0, w, h);\n}\n\n/**\n * Extract brightness values from image data\n */\nexport function extractBrightness(\n imageData: ImageData,\n brightnessFunction: (r: number, g: number, b: number) => number = (r, g, b) => 0.21 * r + 0.72 * g + 0.07 * b\n): number[] {\n const { data, width, height } = imageData;\n const brightness: number[] = new Array(width * height);\n\n for (let i = 0; i < data.length; i += 4) {\n brightness[i / 4] = brightnessFunction(data[i], data[i + 1], data[i + 2]);\n }\n\n return brightness;\n}\n\n/**\n * Sample image data at cell-based intervals\n */\nexport function sampleImageCells(\n imageData: ImageData,\n cellWidth: number,\n cellHeight: number,\n brightnessFunction: (r: number, g: number, b: number) => number = (r, g, b) => 0.21 * r + 0.72 * g + 0.07 * b\n): { brightness: number; color: string }[][] {\n const { data, width, height } = imageData;\n const cols = Math.ceil(width / cellWidth);\n const rows = Math.ceil(height / cellHeight);\n\n const result: { brightness: number; color: string }[][] = [];\n\n for (let row = 0; row < rows; row++) {\n result[row] = [];\n\n for (let col = 0; col < cols; col++) {\n const cellData = sampleCell(data, width, col * cellWidth, row * cellHeight, cellWidth, cellHeight);\n const brightness = brightnessFunction(cellData.r, cellData.g, cellData.b);\n\n result[row][col] = {\n brightness,\n color: `rgb(${Math.round(cellData.r)}, ${Math.round(cellData.g)}, ${Math.round(cellData.b)})`,\n };\n }\n }\n\n return result;\n}\n\n/**\n * Sample average color from a cell region\n */\nfunction sampleCell(\n data: Uint8ClampedArray,\n imageWidth: number,\n startX: number,\n startY: number,\n cellWidth: number,\n cellHeight: number\n): { r: number; g: number; b: number; a: number } {\n let totalR = 0;\n let totalG = 0;\n let totalB = 0;\n let totalA = 0;\n let count = 0;\n\n for (let y = startY; y < startY + cellHeight; y++) {\n for (let x = startX; x < startX + cellWidth; x++) {\n const px = (y * imageWidth + x) * 4;\n\n if (px >= 0 && px + 3 < data.length) {\n totalR += data[px];\n totalG += data[px + 1];\n totalB += data[px + 2];\n totalA += data[px + 3];\n count++;\n }\n }\n }\n\n if (count === 0) {\n return { r: 0, g: 0, b: 0, a: 0 };\n }\n\n return {\n r: totalR / count,\n g: totalG / count,\n b: totalB / count,\n a: totalA / count,\n };\n}\n\n/**\n * Convert RGB to hex color string\n */\nexport function rgbToHex(r: number, g: number, b: number): string {\n const toHex = (n: number) =>\n Math.max(0, Math.min(255, Math.round(n)))\n .toString(16)\n .padStart(2, '0');\n return `#${toHex(r)}${toHex(g)}${toHex(b)}`;\n}\n\n/**\n * Convert hex color to RGB\n */\nexport function hexToRgb(hex: string): { r: number; g: number; b: number } | null {\n const result = /^#?([a-f\\d]{2})([a-f\\d]{2})([a-f\\d]{2})$/i.exec(hex);\n return result\n ? {\n r: parseInt(result[1], 16),\n g: parseInt(result[2], 16),\n b: parseInt(result[3], 16),\n }\n : null;\n}\n\n/**\n * Adjust image brightness\n */\nexport function adjustBrightness(imageData: ImageData, amount: number): ImageData {\n const { data, width, height } = imageData;\n const adjusted = new Uint8ClampedArray(data.length);\n\n for (let i = 0; i < data.length; i += 4) {\n adjusted[i] = Math.min(255, Math.max(0, data[i] + amount));\n adjusted[i + 1] = Math.min(255, Math.max(0, data[i + 1] + amount));\n adjusted[i + 2] = Math.min(255, Math.max(0, data[i + 2] + amount));\n adjusted[i + 3] = data[i + 3];\n }\n\n return new ImageData(adjusted, width, height);\n}\n\n/**\n * Adjust image contrast\n */\nexport function adjustContrast(imageData: ImageData, amount: number): ImageData {\n const { data, width, height } = imageData;\n const adjusted = new Uint8ClampedArray(data.length);\n const factor = (259 * (amount + 255)) / (255 * (259 - amount));\n\n for (let i = 0; i < data.length; i += 4) {\n adjusted[i] = Math.min(255, Math.max(0, factor * (data[i] - 128) + 128));\n adjusted[i + 1] = Math.min(255, Math.max(0, factor * (data[i + 1] - 128) + 128));\n adjusted[i + 2] = Math.min(255, Math.max(0, factor * (data[i + 2] - 128) + 128));\n adjusted[i + 3] = data[i + 3];\n }\n\n return new ImageData(adjusted, width, height);\n}\n\n/**\n * Invert image colors\n */\nexport function invertColors(imageData: ImageData): ImageData {\n const { data, width, height } = imageData;\n const inverted = new Uint8ClampedArray(data.length);\n\n for (let i = 0; i < data.length; i += 4) {\n inverted[i] = 255 - data[i];\n inverted[i + 1] = 255 - data[i + 1];\n inverted[i + 2] = 255 - data[i + 2];\n inverted[i + 3] = data[i + 3];\n }\n\n return new ImageData(inverted, width, height);\n}\n\n/**\n * Convert image to grayscale\n */\nexport function toGrayscale(imageData: ImageData): ImageData {\n const { data, width, height } = imageData;\n const grayscale = new Uint8ClampedArray(data.length);\n\n for (let i = 0; i < data.length; i += 4) {\n const gray = 0.21 * data[i] + 0.72 * data[i + 1] + 0.07 * data[i + 2];\n grayscale[i] = gray;\n grayscale[i + 1] = gray;\n grayscale[i + 2] = gray;\n grayscale[i + 3] = data[i + 3];\n }\n\n return new ImageData(grayscale, width, height);\n}\n","/**\n * Performance Utilities\n *\n * Visibility detection, resource management, and optimization helpers.\n */\n\n/**\n * Visibility observer callback type\n */\nexport type VisibilityCallback = (isVisible: boolean, entry: IntersectionObserverEntry) => void;\n\n/**\n * Create an IntersectionObserver for visibility-based animation control\n *\n * @param element - Element to observe\n * @param callback - Called when visibility changes\n * @param threshold - Visibility threshold (0-1, default: 0.1)\n * @returns Cleanup function to disconnect observer\n */\nexport function createVisibilityObserver(\n element: Element,\n callback: VisibilityCallback,\n threshold: number = 0.1\n): () => void {\n const observer = new IntersectionObserver(\n (entries) => {\n for (const entry of entries) {\n callback(entry.isIntersecting, entry);\n }\n },\n { threshold }\n );\n\n observer.observe(element);\n\n return () => {\n observer.disconnect();\n };\n}\n\n/**\n * Create a ResizeObserver for responsive canvas sizing\n *\n * @param element - Element to observe\n * @param callback - Called on resize with new dimensions\n * @param debounceMs - Debounce delay in ms (default: 100)\n * @returns Cleanup function to disconnect observer\n */\nexport function createResizeObserver(\n element: Element,\n callback: (width: number, height: number, entry: ResizeObserverEntry) => void,\n debounceMs: number = 100\n): () => void {\n let timeout: ReturnType<typeof setTimeout> | null = null;\n\n const observer = new ResizeObserver((entries) => {\n if (timeout) {\n clearTimeout(timeout);\n }\n\n timeout = setTimeout(() => {\n const entry = entries[0];\n if (entry) {\n const { width, height } = entry.contentRect;\n callback(width, height, entry);\n }\n }, debounceMs);\n });\n\n observer.observe(element);\n\n return () => {\n if (timeout) {\n clearTimeout(timeout);\n }\n observer.disconnect();\n };\n}\n\n/**\n * Check if the user prefers reduced motion\n */\nexport function prefersReducedMotion(): boolean {\n if (typeof window === 'undefined') return false;\n return window.matchMedia('(prefers-reduced-motion: reduce)').matches;\n}\n\n/**\n * Create a listener for reduced motion preference changes\n *\n * @param callback - Called when preference changes\n * @returns Cleanup function to remove listener\n */\nexport function onReducedMotionChange(callback: (prefersReduced: boolean) => void): () => void {\n if (typeof window === 'undefined') {\n return () => {};\n }\n\n const mediaQuery = window.matchMedia('(prefers-reduced-motion: reduce)');\n\n const handler = (event: MediaQueryListEvent) => {\n callback(event.matches);\n };\n\n mediaQuery.addEventListener('change', handler);\n\n // Call immediately with current value\n callback(mediaQuery.matches);\n\n return () => {\n mediaQuery.removeEventListener('change', handler);\n };\n}\n\n/**\n * Check if the browser is in a low-power mode or has reduced capabilities\n */\nexport function isLowPowerMode(): boolean {\n // Check for battery API (if available)\n if (typeof navigator !== 'undefined' && 'getBattery' in navigator) {\n // Battery API is async, so this is a simplified check\n // Real implementation would need to be async\n return false;\n }\n\n // Fallback: check for hardware concurrency\n if (typeof navigator !== 'undefined' && navigator.hardwareConcurrency) {\n return navigator.hardwareConcurrency <= 2;\n }\n\n return false;\n}\n\n/**\n * Get recommended FPS based on device capabilities\n */\nexport function getRecommendedFPS(): number {\n if (prefersReducedMotion()) {\n return 0; // No animation\n }\n\n if (isLowPowerMode()) {\n return 15; // Low power mode\n }\n\n // Default for capable devices\n return 30;\n}\n\n/**\n * Performance monitoring for debugging\n */\nexport interface PerformanceMetrics {\n fps: number;\n frameTime: number;\n droppedFrames: number;\n}\n\n/**\n * Create a simple FPS counter\n */\nexport function createFPSCounter(): {\n tick: () => void;\n getFPS: () => number;\n getMetrics: () => PerformanceMetrics;\n reset: () => void;\n} {\n const frameTimes: number[] = [];\n const maxSamples = 60;\n let droppedFrames = 0;\n let lastFrameTime = performance.now();\n\n function tick(): void {\n const now = performance.now();\n const delta = now - lastFrameTime;\n lastFrameTime = now;\n\n frameTimes.push(now);\n\n if (frameTimes.length > maxSamples) {\n frameTimes.shift();\n }\n\n // Count dropped frames (assuming 60fps target, frames taking >20ms are \"dropped\")\n if (delta > 20) {\n droppedFrames += Math.floor(delta / 16.67) - 1;\n }\n }\n\n function getFPS(): number {\n if (frameTimes.length < 2) return 0;\n\n const oldest = frameTimes[0];\n const newest = frameTimes[frameTimes.length - 1];\n const elapsed = newest - oldest;\n\n if (elapsed === 0) return 0;\n\n return ((frameTimes.length - 1) / elapsed) * 1000;\n }\n\n function getMetrics(): PerformanceMetrics {\n const fps = getFPS();\n const frameTime = fps > 0 ? 1000 / fps : 0;\n\n return {\n fps: Math.round(fps * 10) / 10,\n frameTime: Math.round(frameTime * 100) / 100,\n droppedFrames,\n };\n }\n\n function reset(): void {\n frameTimes.length = 0;\n droppedFrames = 0;\n lastFrameTime = performance.now();\n }\n\n return { tick, getFPS, getMetrics, reset };\n}\n\n/**\n * Request idle callback with fallback\n */\nexport function requestIdleCallback(\n callback: () => void,\n options?: { timeout?: number }\n): number {\n // Use globalThis for cross-environment compatibility\n const global = globalThis as typeof globalThis & {\n requestIdleCallback?: typeof window.requestIdleCallback;\n setTimeout: typeof setTimeout;\n };\n\n if (typeof global.requestIdleCallback === 'function') {\n return global.requestIdleCallback(callback, options);\n }\n\n // Fallback using setTimeout\n return global.setTimeout(callback, options?.timeout ?? 1) as unknown as number;\n}\n\n/**\n * Cancel idle callback with fallback\n */\nexport function cancelIdleCallback(id: number): void {\n // Use globalThis for cross-environment compatibility\n const global = globalThis as typeof globalThis & {\n cancelIdleCallback?: typeof window.cancelIdleCallback;\n clearTimeout: typeof clearTimeout;\n };\n\n if (typeof global.cancelIdleCallback === 'function') {\n global.cancelIdleCallback(id);\n } else {\n global.clearTimeout(id);\n }\n}\n\n/**\n * Check if we're running in a browser environment\n */\nexport function isBrowser(): boolean {\n return typeof window !== 'undefined' && typeof document !== 'undefined';\n}\n\n/**\n * Check if Canvas is supported\n */\nexport function isCanvasSupported(): boolean {\n if (!isBrowser()) return false;\n\n const canvas = document.createElement('canvas');\n return !!(canvas.getContext && canvas.getContext('2d'));\n}\n\n/**\n * Check if OffscreenCanvas is supported\n */\nexport function isOffscreenCanvasSupported(): boolean {\n return typeof OffscreenCanvas !== 'undefined';\n}\n","/**\n * Gossamer - ASCII Visual Effects Library\n *\n * Threads of light. Delicate textures woven through your space.\n *\n * @packageDocumentation\n */\n\n// =============================================================================\n// Core Types\n// =============================================================================\n\n/**\n * Core configuration for ASCII rendering\n */\nexport interface GossamerConfig {\n /** Character set for ASCII rendering (light to dark) */\n characters?: string;\n /** Cell width in pixels */\n cellWidth?: number;\n /** Cell height in pixels */\n cellHeight?: number;\n /** Foreground color */\n color?: string;\n /** Background color (transparent if not set) */\n backgroundColor?: string;\n /** Font family for ASCII characters */\n fontFamily?: string;\n /** Enable animation loop */\n animate?: boolean;\n /** Target FPS for animation */\n fps?: number;\n}\n\n/**\n * Preset configuration for effects\n */\nexport interface PresetConfig {\n /** Preset display name */\n name: string;\n /** Preset description */\n description: string;\n /** Character set */\n characters: string;\n /** Pattern type */\n pattern: 'perlin' | 'waves' | 'static' | 'ripple' | 'fbm';\n /** Pattern frequency */\n frequency: number;\n /** Pattern amplitude */\n amplitude: number;\n /** Animation speed */\n speed: number;\n /** Default opacity */\n opacity: number;\n}\n\n// =============================================================================\n// Constants\n// =============================================================================\n\n/**\n * Default character set ordered from light to dark\n */\nexport const DEFAULT_CHARACTERS = ' .:-=+*#%@';\n\n/**\n * Default configuration values\n */\nexport const DEFAULT_CONFIG: Required<GossamerConfig> = {\n characters: DEFAULT_CHARACTERS,\n cellWidth: 8,\n cellHeight: 12,\n color: '#ffffff',\n backgroundColor: '',\n fontFamily: 'monospace',\n animate: false,\n fps: 30,\n};\n\n// =============================================================================\n// Core Functions\n// =============================================================================\n\n/**\n * Calculate brightness from RGB values using luminance formula\n * Uses the standard luminance coefficients: 0.21 R + 0.72 G + 0.07 B\n */\nexport function calculateBrightness(r: number, g: number, b: number): number {\n return 0.21 * r + 0.72 * g + 0.07 * b;\n}\n\n/**\n * Map a brightness value (0-255) to an ASCII character\n */\nexport function brightnessToChar(\n brightness: number,\n characters: string = DEFAULT_CHARACTERS\n): string {\n const index = Math.floor((brightness / 255) * (characters.length - 1));\n return characters[Math.min(index, characters.length - 1)];\n}\n\n// =============================================================================\n// Module Exports\n// =============================================================================\n\n// Renderer\nexport { GossamerRenderer } from './renderer';\nexport type { RenderConfig } from './renderer';\n\n// Patterns\nexport {\n perlinNoise2D,\n fbmNoise,\n wavePattern,\n ripplePattern,\n staticNoise,\n seededNoise2D,\n generateBrightnessGrid,\n gridToImageData,\n DEFAULT_PATTERN_CONFIG,\n} from './patterns';\nexport type { PatternConfig, PatternType } from './patterns';\n\n// Characters\nexport {\n CHARACTER_SETS,\n getCharacterSet,\n getCharacters,\n getCharacterSetNames,\n createCharacterSet,\n validateCharacterSet,\n invertCharacters,\n} from './characters';\nexport type { CharacterSet } from './characters';\n\n// Animation\nexport {\n createAnimationLoop,\n throttle,\n debounce,\n calculateFPS,\n easings,\n} from './animation';\nexport type { AnimationState, AnimationOptions, EasingFunction } from './animation';\n\n// Canvas Utilities\nexport {\n createCanvas,\n getDevicePixelRatio,\n resizeCanvasToContainer,\n createOffscreenCanvas,\n clearCanvas,\n getImageData,\n optimizeContext,\n setupTextRendering,\n measureTextWidth,\n calculateCellSize,\n setBlendMode,\n} from './utils/canvas';\nexport type { CanvasOptions } from './utils/canvas';\n\n// Image Utilities\nexport {\n loadImage,\n loadAndScaleImage,\n imageToPixelData,\n extractBrightness,\n sampleImageCells,\n rgbToHex,\n hexToRgb,\n adjustBrightness,\n adjustContrast,\n invertColors,\n toGrayscale,\n} from './utils/image';\nexport type { ImageLoadOptions } from './utils/image';\n\n// Performance Utilities\nexport {\n createVisibilityObserver,\n createResizeObserver,\n prefersReducedMotion,\n onReducedMotionChange,\n isLowPowerMode,\n getRecommendedFPS,\n createFPSCounter,\n requestIdleCallback,\n cancelIdleCallback,\n isBrowser,\n isCanvasSupported,\n isOffscreenCanvasSupported,\n} from './utils/performance';\nexport type { VisibilityCallback, PerformanceMetrics } from './utils/performance';\n\n// =============================================================================\n// Version\n// =============================================================================\n\n/**\n * Gossamer version\n */\nexport const VERSION = '0.1.0';\n"],"names":["DEFAULT_CHARACTERS","calculateBrightness"],"mappings":"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EAAI;AAAA,EAAK;AAAA,EAAK;AAAA,EAAI;AAAA,EAAI;AAAA,EAAK;AAAA,EAAI;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAI;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAI;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAC9F;AAAA,EAAI;AAAA,EAAI;AAAA,EAAI;AAAA,EAAK;AAAA,EAAI;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAI;AAAA,EAAI;AAAA,EAAI;AAAA,EAAI;AAAA,EAAK;AAAA,EAAG;AAAA,EAAK;AAAA,EAAI;AAAA,EAAI;AAAA,EAAK;AAAA,EAAI;AAAA,EAAK;AAAA,EAAK;AAAA,EAC5F;AAAA,EAAI;AAAA,EAAI;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAI;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAG;AAAA,EAAI;AAAA,EAAI;AAAA,EAC7F;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAG;AAAA,EAAK;AAAA,EAAI;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAI;AAAA,EAAI;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAI;AAAA,EAAK;AAAA,EAAI;AAAA,EAAI;AAAA,EAC5F;AAAA,EAAI;AAAA,EAAK;AAAA,EAAK;AAAA,EAAI;AAAA,EAAI;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAG;AAAA,EAAI;AAAA,EAAK;AAAA,EAAK;AAAA,EAAI;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAC7F;AAAA,EAAK;AAAA,EAAI;AAAA,EAAK;AAAA,EAAG;AAAA,EAAK;AAAA,EAAI;AAAA,EAAI;AAAA,EAAK;AAAA,EAAI;AAAA,EAAI;AAAA,EAAK;AAAA,EAAK;AAAA,EAAI;AAAA,EAAK;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"}
1
+ {"version":3,"file":"index.js","sources":["../src/renderer.ts","../src/patterns.ts","../src/characters.ts","../src/colors.ts","../src/animation.ts","../src/utils/canvas.ts","../src/utils/image.ts","../src/utils/performance.ts","../src/index.ts"],"sourcesContent":["/**\n * Gossamer Core Renderer\n *\n * Canvas-based ASCII rendering engine. Converts image data to ASCII characters\n * by mapping brightness values to a character set.\n */\n\n// Define locally to avoid circular dependency with index.ts\nconst DEFAULT_CHARACTERS = ' .:-=+*#%@';\n\nfunction calculateBrightness(r: number, g: number, b: number): number {\n return 0.21 * r + 0.72 * g + 0.07 * b;\n}\n\n/**\n * Configuration for the Gossamer renderer\n */\nexport interface RenderConfig {\n /** Canvas element to render to */\n canvas: HTMLCanvasElement;\n /** Character set ordered from light to dark */\n characters: string;\n /** Width of each character cell in pixels */\n cellWidth: number;\n /** Height of each character cell in pixels */\n cellHeight: number;\n /** Color for rendering characters */\n color: string;\n /** Background color (empty string for transparent) */\n backgroundColor: string;\n /** Font family */\n fontFamily: string;\n /** Custom brightness calculation function */\n brightnessFunction: (r: number, g: number, b: number) => number;\n}\n\n/**\n * Default render configuration\n */\nconst DEFAULT_RENDER_CONFIG: Omit<RenderConfig, 'canvas'> = {\n characters: DEFAULT_CHARACTERS,\n cellWidth: 8,\n cellHeight: 12,\n color: '#ffffff',\n backgroundColor: '',\n fontFamily: 'monospace',\n brightnessFunction: calculateBrightness,\n};\n\n/**\n * Core ASCII renderer class\n *\n * Handles all canvas rendering operations for ASCII effects.\n * Supports both static rendering and animation loops.\n */\nexport class GossamerRenderer {\n private ctx: CanvasRenderingContext2D;\n private config: RenderConfig;\n private animationId: number | null = null;\n private lastFrameTime: number = 0;\n private isRunning: boolean = false;\n\n // Performance: Character texture atlas\n private charAtlas: OffscreenCanvas | HTMLCanvasElement | null = null;\n private atlasCharacters: string = '';\n\n constructor(canvas: HTMLCanvasElement, config: Partial<Omit<RenderConfig, 'canvas'>> = {}) {\n const context = canvas.getContext('2d');\n if (!context) {\n throw new Error('Failed to get 2D rendering context');\n }\n\n this.ctx = context;\n this.config = {\n canvas,\n ...DEFAULT_RENDER_CONFIG,\n ...config,\n };\n\n this.setupCanvas();\n this.buildCharacterAtlas();\n }\n\n /**\n * Build character texture atlas for fast rendering\n * Pre-renders all characters to an offscreen canvas, then uses drawImage\n * instead of fillText for 5-10x faster rendering\n */\n private buildCharacterAtlas(): void {\n const { characters, cellWidth, cellHeight, color, fontFamily } = this.config;\n\n // Skip if atlas already built with same characters\n if (this.atlasCharacters === characters && this.charAtlas) {\n return;\n }\n\n // Create offscreen canvas (use OffscreenCanvas if available for better perf)\n const atlasWidth = characters.length * cellWidth;\n const atlasHeight = cellHeight;\n\n if (typeof OffscreenCanvas !== 'undefined') {\n this.charAtlas = new OffscreenCanvas(atlasWidth, atlasHeight);\n } else {\n this.charAtlas = document.createElement('canvas');\n this.charAtlas.width = atlasWidth;\n this.charAtlas.height = atlasHeight;\n }\n\n const ctx = this.charAtlas.getContext('2d');\n if (!ctx) {\n this.charAtlas = null;\n return;\n }\n\n\n // Clear with transparent background\n ctx.clearRect(0, 0, atlasWidth, atlasHeight);\n\n // Render each character\n ctx.fillStyle = color;\n ctx.font = `${cellHeight}px ${fontFamily}`;\n ctx.textBaseline = 'top';\n\n for (let i = 0; i < characters.length; i++) {\n const char = characters[i];\n if (char !== ' ') {\n ctx.fillText(char, i * cellWidth, 0);\n }\n }\n\n this.atlasCharacters = characters;\n }\n\n /**\n * Set up the canvas with optimal rendering settings\n */\n private setupCanvas(): void {\n const { fontFamily, cellHeight } = this.config;\n\n // Set font for consistent character sizing\n this.ctx.font = `${cellHeight}px ${fontFamily}`;\n this.ctx.textBaseline = 'top';\n\n // Enable image smoothing for better quality\n this.ctx.imageSmoothingEnabled = true;\n this.ctx.imageSmoothingQuality = 'high';\n }\n\n /**\n * Update the renderer configuration\n */\n updateConfig(config: Partial<Omit<RenderConfig, 'canvas'>>): void {\n const needsAtlasRebuild =\n config.characters !== undefined ||\n config.color !== undefined ||\n config.cellWidth !== undefined ||\n config.cellHeight !== undefined ||\n config.fontFamily !== undefined;\n\n this.config = { ...this.config, ...config };\n this.setupCanvas();\n\n if (needsAtlasRebuild) {\n this.atlasCharacters = ''; // Force rebuild\n this.buildCharacterAtlas();\n }\n }\n\n /**\n * Resize the canvas to match new dimensions\n */\n resize(width: number, height: number): void {\n const { canvas } = this.config;\n canvas.width = width;\n canvas.height = height;\n this.setupCanvas();\n }\n\n /**\n * Get the current canvas dimensions\n */\n getDimensions(): { width: number; height: number } {\n return {\n width: this.config.canvas.width,\n height: this.config.canvas.height,\n };\n }\n\n /**\n * Calculate the number of cells that fit in the canvas\n */\n getCellCount(): { cols: number; rows: number } {\n const { width, height } = this.getDimensions();\n const { cellWidth, cellHeight } = this.config;\n\n return {\n cols: Math.ceil(width / cellWidth),\n rows: Math.ceil(height / cellHeight),\n };\n }\n\n /**\n * Clear the canvas\n */\n clear(): void {\n const { canvas, backgroundColor } = this.config;\n\n if (backgroundColor) {\n this.ctx.fillStyle = backgroundColor;\n this.ctx.fillRect(0, 0, canvas.width, canvas.height);\n } else {\n this.ctx.clearRect(0, 0, canvas.width, canvas.height);\n }\n }\n\n /**\n * Render a single frame from image data\n */\n renderFrame(imageData: ImageData): void {\n const { canvas, characters, cellWidth, cellHeight, color, brightnessFunction } = this.config;\n const { width, data } = imageData;\n\n this.clear();\n this.ctx.fillStyle = color;\n\n for (let y = 0; y < canvas.height; y += cellHeight) {\n for (let x = 0; x < canvas.width; x += cellWidth) {\n const brightness = this.getCellBrightness(data, x, y, width, cellWidth, cellHeight, brightnessFunction);\n const charIndex = Math.floor((brightness / 255) * (characters.length - 1));\n const char = characters[Math.min(charIndex, characters.length - 1)];\n\n if (char !== ' ') {\n this.ctx.fillText(char, x, y);\n }\n }\n }\n }\n\n /**\n * Render ASCII from a brightness grid (for pattern-based rendering)\n */\n renderFromBrightnessGrid(grid: number[][]): void {\n const { characters, cellWidth, cellHeight, color } = this.config;\n\n this.clear();\n this.ctx.fillStyle = color;\n\n for (let row = 0; row < grid.length; row++) {\n for (let col = 0; col < grid[row].length; col++) {\n const brightness = grid[row][col];\n const charIndex = Math.floor((brightness / 255) * (characters.length - 1));\n const char = characters[Math.min(charIndex, characters.length - 1)];\n\n if (char !== ' ') {\n this.ctx.fillText(char, col * cellWidth, row * cellHeight);\n }\n }\n }\n }\n\n /**\n * Render ASCII with per-cell colors (for colored image rendering)\n */\n renderWithColors(data: Array<{ char: string; color: string; x: number; y: number }>): void {\n this.clear();\n\n for (const { char, color, x, y } of data) {\n if (char !== ' ') {\n this.ctx.fillStyle = color;\n this.ctx.fillText(char, x, y);\n }\n }\n }\n\n /**\n * PERFORMANCE: Render from BrightnessBuffer using texture atlas\n *\n * Uses pre-rendered character sprites instead of fillText calls.\n * 5-10x faster than renderFromBrightnessGrid for large canvases.\n *\n * @param buffer - BrightnessBuffer from fillBrightnessBuffer\n */\n renderFromBuffer(buffer: { data: Uint8Array; cols: number; rows: number }): void {\n const { characters, cellWidth, cellHeight } = this.config;\n\n this.clear();\n\n // Fall back to fillText if atlas not available\n if (!this.charAtlas) {\n this.ctx.fillStyle = this.config.color;\n const charLen = characters.length - 1;\n let idx = 0;\n for (let row = 0; row < buffer.rows; row++) {\n for (let col = 0; col < buffer.cols; col++) {\n const brightness = buffer.data[idx++];\n const charIndex = (brightness / 255 * charLen) | 0;\n const char = characters[Math.min(charIndex, charLen)];\n if (char !== ' ') {\n this.ctx.fillText(char, col * cellWidth, row * cellHeight);\n }\n }\n }\n return;\n }\n\n // Use atlas for fast rendering via drawImage\n const charLen = characters.length - 1;\n let idx = 0;\n\n for (let row = 0; row < buffer.rows; row++) {\n const y = row * cellHeight;\n for (let col = 0; col < buffer.cols; col++) {\n const brightness = buffer.data[idx++];\n const charIndex = (brightness / 255 * charLen) | 0;\n\n // Skip space characters (index 0 in most charsets)\n if (charIndex === 0 && characters[0] === ' ') {\n continue;\n }\n\n // Draw from atlas: source is the character's position in the atlas\n this.ctx.drawImage(\n this.charAtlas,\n charIndex * cellWidth, 0, cellWidth, cellHeight, // source\n col * cellWidth, y, cellWidth, cellHeight // destination\n );\n }\n }\n }\n\n /**\n * PERFORMANCE: Render brightness grid using atlas (legacy grid format)\n *\n * @param grid - 2D array of brightness values\n */\n renderGridFast(grid: number[][]): void {\n const { characters, cellWidth, cellHeight } = this.config;\n\n this.clear();\n\n if (!this.charAtlas) {\n // Fallback to standard method\n this.renderFromBrightnessGrid(grid);\n return;\n }\n\n const charLen = characters.length - 1;\n\n for (let row = 0; row < grid.length; row++) {\n const y = row * cellHeight;\n const rowData = grid[row];\n for (let col = 0; col < rowData.length; col++) {\n const brightness = rowData[col];\n const charIndex = (brightness / 255 * charLen) | 0;\n\n if (charIndex === 0 && characters[0] === ' ') {\n continue;\n }\n\n this.ctx.drawImage(\n this.charAtlas,\n charIndex * cellWidth, 0, cellWidth, cellHeight,\n col * cellWidth, y, cellWidth, cellHeight\n );\n }\n }\n }\n\n /**\n * Calculate average brightness for a cell region\n */\n private getCellBrightness(\n data: Uint8ClampedArray,\n startX: number,\n startY: number,\n imageWidth: number,\n cellWidth: number,\n cellHeight: number,\n brightnessFunction: (r: number, g: number, b: number) => number\n ): number {\n let total = 0;\n let count = 0;\n\n for (let cy = 0; cy < cellHeight; cy++) {\n for (let cx = 0; cx < cellWidth; cx++) {\n const px = ((startY + cy) * imageWidth + (startX + cx)) * 4;\n if (px >= 0 && px + 2 < data.length) {\n total += brightnessFunction(data[px], data[px + 1], data[px + 2]);\n count++;\n }\n }\n }\n\n return count > 0 ? total / count : 0;\n }\n\n /**\n * Start an animation loop with FPS limiting\n */\n startAnimation(\n updateFn: (time: number, deltaTime: number) => ImageData | number[][],\n fps: number = 30\n ): void {\n if (this.isRunning) {\n this.stopAnimation();\n }\n\n this.isRunning = true;\n const frameInterval = 1000 / fps;\n this.lastFrameTime = performance.now();\n\n const animate = (currentTime: number): void => {\n if (!this.isRunning) return;\n\n const deltaTime = currentTime - this.lastFrameTime;\n\n if (deltaTime >= frameInterval) {\n const result = updateFn(currentTime, deltaTime);\n\n if (result instanceof ImageData) {\n this.renderFrame(result);\n } else {\n this.renderFromBrightnessGrid(result);\n }\n\n this.lastFrameTime = currentTime - (deltaTime % frameInterval);\n }\n\n this.animationId = requestAnimationFrame(animate);\n };\n\n this.animationId = requestAnimationFrame(animate);\n }\n\n /**\n * Stop the animation loop\n */\n stopAnimation(): void {\n this.isRunning = false;\n if (this.animationId !== null) {\n cancelAnimationFrame(this.animationId);\n this.animationId = null;\n }\n }\n\n /**\n * Check if animation is currently running\n */\n isAnimating(): boolean {\n return this.isRunning;\n }\n\n /**\n * Pause animation (can be resumed)\n */\n pause(): void {\n this.isRunning = false;\n if (this.animationId !== null) {\n cancelAnimationFrame(this.animationId);\n this.animationId = null;\n }\n }\n\n /**\n * Clean up and destroy the renderer\n */\n destroy(): void {\n this.stopAnimation();\n }\n}\n","/**\n * Gossamer Pattern Generators\n *\n * Provides noise and pattern generation functions for ambient ASCII effects.\n * Includes Perlin noise, wave patterns, and static noise.\n */\n\n/**\n * Configuration for pattern generation\n */\nexport interface PatternConfig {\n /** Pattern scale - higher values create finer detail */\n frequency: number;\n /** Pattern intensity multiplier */\n amplitude: number;\n /** Animation speed multiplier */\n speed: number;\n}\n\n/**\n * Default pattern configuration\n */\nexport const DEFAULT_PATTERN_CONFIG: PatternConfig = {\n frequency: 0.05,\n amplitude: 1.0,\n speed: 0.5,\n};\n\n// Permutation table for Perlin noise\nconst PERMUTATION = new Uint8Array(512);\nconst P = new Uint8Array([\n 151, 160, 137, 91, 90, 15, 131, 13, 201, 95, 96, 53, 194, 233, 7, 225, 140, 36, 103, 30, 69, 142,\n 8, 99, 37, 240, 21, 10, 23, 190, 6, 148, 247, 120, 234, 75, 0, 26, 197, 62, 94, 252, 219, 203,\n 117, 35, 11, 32, 57, 177, 33, 88, 237, 149, 56, 87, 174, 20, 125, 136, 171, 168, 68, 175, 74, 165,\n 71, 134, 139, 48, 27, 166, 77, 146, 158, 231, 83, 111, 229, 122, 60, 211, 133, 230, 220, 105, 92,\n 41, 55, 46, 245, 40, 244, 102, 143, 54, 65, 25, 63, 161, 1, 216, 80, 73, 209, 76, 132, 187, 208,\n 89, 18, 169, 200, 196, 135, 130, 116, 188, 159, 86, 164, 100, 109, 198, 173, 186, 3, 64, 52, 217,\n 226, 250, 124, 123, 5, 202, 38, 147, 118, 126, 255, 82, 85, 212, 207, 206, 59, 227, 47, 16, 58,\n 17, 182, 189, 28, 42, 223, 183, 170, 213, 119, 248, 152, 2, 44, 154, 163, 70, 221, 153, 101, 155,\n 167, 43, 172, 9, 129, 22, 39, 253, 19, 98, 108, 110, 79, 113, 224, 232, 178, 185, 112, 104, 218,\n 246, 97, 228, 251, 34, 242, 193, 238, 210, 144, 12, 191, 179, 162, 241, 81, 51, 145, 235, 249,\n 14, 239, 107, 49, 192, 214, 31, 181, 199, 106, 157, 184, 84, 204, 176, 115, 121, 50, 45, 127, 4,\n 150, 254, 138, 236, 205, 93, 222, 114, 67, 29, 24, 72, 243, 141, 128, 195, 78, 66, 215, 61, 156,\n 180,\n]);\n\n// Initialize permutation table\nfor (let i = 0; i < 256; i++) {\n PERMUTATION[i] = P[i];\n PERMUTATION[i + 256] = P[i];\n}\n\n/**\n * Fade function for smooth interpolation (6t^5 - 15t^4 + 10t^3)\n */\nfunction fade(t: number): number {\n return t * t * t * (t * (t * 6 - 15) + 10);\n}\n\n/**\n * Linear interpolation\n */\nfunction lerp(a: number, b: number, t: number): number {\n return a + t * (b - a);\n}\n\n/**\n * Gradient function for Perlin noise\n */\nfunction grad(hash: number, x: number, y: number): number {\n const h = hash & 3;\n const u = h < 2 ? x : y;\n const v = h < 2 ? y : x;\n return ((h & 1) === 0 ? u : -u) + ((h & 2) === 0 ? v : -v);\n}\n\n/**\n * 2D Perlin noise function\n *\n * @param x - X coordinate\n * @param y - Y coordinate\n * @returns Noise value between -1 and 1\n */\nexport function perlinNoise2D(x: number, y: number): number {\n // Find unit square containing point\n const xi = Math.floor(x) & 255;\n const yi = Math.floor(y) & 255;\n\n // Find relative position in square\n const xf = x - Math.floor(x);\n const yf = y - Math.floor(y);\n\n // Fade curves\n const u = fade(xf);\n const v = fade(yf);\n\n // Hash coordinates of square corners\n const aa = PERMUTATION[PERMUTATION[xi] + yi];\n const ab = PERMUTATION[PERMUTATION[xi] + yi + 1];\n const ba = PERMUTATION[PERMUTATION[xi + 1] + yi];\n const bb = PERMUTATION[PERMUTATION[xi + 1] + yi + 1];\n\n // Blend results from 4 corners\n const x1 = lerp(grad(aa, xf, yf), grad(ba, xf - 1, yf), u);\n const x2 = lerp(grad(ab, xf, yf - 1), grad(bb, xf - 1, yf - 1), u);\n\n return lerp(x1, x2, v);\n}\n\n/**\n * Fractal Brownian Motion (fBm) using Perlin noise\n * Creates more organic-looking noise by layering multiple octaves\n *\n * @param x - X coordinate\n * @param y - Y coordinate\n * @param octaves - Number of noise layers (default: 4)\n * @param persistence - Amplitude decay per octave (default: 0.5)\n * @returns Noise value between -1 and 1\n */\nexport function fbmNoise(x: number, y: number, octaves: number = 4, persistence: number = 0.5): number {\n let total = 0;\n let frequency = 1;\n let amplitude = 1;\n let maxValue = 0;\n\n for (let i = 0; i < octaves; i++) {\n total += perlinNoise2D(x * frequency, y * frequency) * amplitude;\n maxValue += amplitude;\n amplitude *= persistence;\n frequency *= 2;\n }\n\n return total / maxValue;\n}\n\n/**\n * Wave pattern generator\n *\n * @param x - X coordinate\n * @param y - Y coordinate\n * @param time - Time value for animation\n * @param config - Pattern configuration\n * @returns Value between -1 and 1\n */\nexport function wavePattern(\n x: number,\n y: number,\n time: number,\n config: PatternConfig = DEFAULT_PATTERN_CONFIG\n): number {\n const { frequency, amplitude, speed } = config;\n const wave1 = Math.sin(x * frequency + time * speed);\n const wave2 = Math.cos(y * frequency + time * speed * 0.7);\n const wave3 = Math.sin((x + y) * frequency * 0.5 + time * speed * 0.5);\n\n return ((wave1 + wave2 + wave3) / 3) * amplitude;\n}\n\n/**\n * Ripple pattern (concentric waves from center)\n *\n * @param x - X coordinate\n * @param y - Y coordinate\n * @param centerX - Ripple center X\n * @param centerY - Ripple center Y\n * @param time - Time value for animation\n * @param config - Pattern configuration\n * @returns Value between -1 and 1\n */\nexport function ripplePattern(\n x: number,\n y: number,\n centerX: number,\n centerY: number,\n time: number,\n config: PatternConfig = DEFAULT_PATTERN_CONFIG\n): number {\n const { frequency, amplitude, speed } = config;\n const dx = x - centerX;\n const dy = y - centerY;\n const distance = Math.sqrt(dx * dx + dy * dy);\n\n return Math.sin(distance * frequency - time * speed) * amplitude;\n}\n\n/**\n * Static noise generator (random values)\n *\n * @param seed - Optional seed for reproducible noise\n * @returns Value between 0 and 1\n */\nexport function staticNoise(seed?: number): number {\n if (seed !== undefined) {\n // Simple seeded random using sine\n const x = Math.sin(seed * 12.9898) * 43758.5453;\n return x - Math.floor(x);\n }\n return Math.random();\n}\n\n/**\n * Seeded 2D noise for reproducible patterns\n *\n * @param x - X coordinate\n * @param y - Y coordinate\n * @param seed - Seed value\n * @returns Value between 0 and 1\n */\nexport function seededNoise2D(x: number, y: number, seed: number = 0): number {\n const n = Math.sin(x * 12.9898 + y * 78.233 + seed) * 43758.5453;\n return n - Math.floor(n);\n}\n\n/**\n * Clouds pattern - soft, billowy fbm with gentle movement\n * The signature Gossamer effect!\n *\n * @param x - X coordinate\n * @param y - Y coordinate\n * @param time - Time value for animation\n * @param config - Pattern configuration\n * @returns Value between -1 and 1\n */\nexport function cloudsPattern(\n x: number,\n y: number,\n time: number,\n config: PatternConfig = DEFAULT_PATTERN_CONFIG\n): number {\n const { frequency, amplitude, speed } = config;\n\n // Slow, drifting movement\n const drift = time * speed * 0.02;\n const nx = x * frequency * 0.5 + drift;\n const ny = y * frequency * 0.5 + drift * 0.7;\n\n // Layer multiple octaves with high persistence for soft, puffy look\n const base = fbmNoise(nx, ny, 5, 0.6);\n\n // Add subtle secondary drift layer\n const detail = fbmNoise(nx * 2 + drift * 0.5, ny * 2 - drift * 0.3, 3, 0.5) * 0.3;\n\n // Combine and bias toward lighter values (more sky, less dense cloud)\n const combined = base + detail;\n return Math.tanh(combined * 1.5) * amplitude;\n}\n\n/**\n * Plasma pattern - classic demoscene effect\n * Combines sine waves at different frequencies and phases\n *\n * @param x - X coordinate\n * @param y - Y coordinate\n * @param time - Time value for animation\n * @param config - Pattern configuration\n * @returns Value between -1 and 1\n */\nexport function plasmaPattern(\n x: number,\n y: number,\n time: number,\n config: PatternConfig = DEFAULT_PATTERN_CONFIG\n): number {\n const { frequency, amplitude, speed } = config;\n const t = time * speed;\n\n // Classic plasma: sum of sines at different scales and rotations\n const v1 = Math.sin(x * frequency + t);\n const v2 = Math.sin(y * frequency + t * 0.7);\n const v3 = Math.sin((x + y) * frequency * 0.5 + t * 0.5);\n const v4 = Math.sin(Math.sqrt(x * x + y * y) * frequency * 0.3 + t * 0.8);\n\n // Add some swirl\n const cx = x - 40;\n const cy = y - 20;\n const v5 = Math.sin(Math.atan2(cy, cx) * 3 + t * 0.4);\n\n return ((v1 + v2 + v3 + v4 + v5) / 5) * amplitude;\n}\n\n/**\n * Vortex pattern - swirling spiral around center\n *\n * @param x - X coordinate\n * @param y - Y coordinate\n * @param centerX - Vortex center X\n * @param centerY - Vortex center Y\n * @param time - Time value for animation\n * @param config - Pattern configuration\n * @returns Value between -1 and 1\n */\nexport function vortexPattern(\n x: number,\n y: number,\n centerX: number,\n centerY: number,\n time: number,\n config: PatternConfig = DEFAULT_PATTERN_CONFIG\n): number {\n const { frequency, amplitude, speed } = config;\n\n const dx = x - centerX;\n const dy = y - centerY;\n const distance = Math.sqrt(dx * dx + dy * dy);\n const angle = Math.atan2(dy, dx);\n\n // Spiral: angle + distance creates the swirl\n const spiral = angle + distance * frequency * 0.1 - time * speed;\n\n // Add some turbulence based on distance\n const turbulence = perlinNoise2D(distance * 0.1, time * speed * 0.5) * 0.3;\n\n return (Math.sin(spiral * 3) + turbulence) * amplitude;\n}\n\n/**\n * Matrix pattern - falling columns like digital rain\n *\n * @param x - X coordinate (column)\n * @param y - Y coordinate (row)\n * @param time - Time value for animation\n * @param config - Pattern configuration\n * @returns Value between -1 and 1\n */\nexport function matrixPattern(\n x: number,\n y: number,\n time: number,\n config: PatternConfig = DEFAULT_PATTERN_CONFIG\n): number {\n const { frequency, amplitude, speed } = config;\n\n // Each column has its own speed and phase based on x position\n const columnSeed = seededNoise2D(x, 0, 42);\n const columnSpeed = 0.5 + columnSeed * 1.5;\n const columnPhase = columnSeed * 100;\n\n // Calculate falling position\n const fallPosition = (y * frequency + time * speed * columnSpeed + columnPhase) % 20;\n\n // Create \"head\" of the rain drop (brightest) with trailing fade\n const headBrightness = fallPosition < 1 ? 1 : 0;\n const trailLength = 8;\n const trailBrightness =\n fallPosition < trailLength ? Math.pow(1 - fallPosition / trailLength, 2) : 0;\n\n // Add some randomness for flickering effect\n const flicker = seededNoise2D(x, Math.floor(time * 10), y) * 0.2;\n\n const value = Math.max(headBrightness, trailBrightness) + flicker;\n return (value * 2 - 1) * amplitude;\n}\n\n/**\n * Gradient pattern - smooth animated gradients\n *\n * @param x - X coordinate\n * @param y - Y coordinate\n * @param cols - Total columns (for normalization)\n * @param rows - Total rows (for normalization)\n * @param time - Time value for animation\n * @param config - Pattern configuration\n * @returns Value between -1 and 1\n */\nexport function gradientPattern(\n x: number,\n y: number,\n cols: number,\n rows: number,\n time: number,\n config: PatternConfig = DEFAULT_PATTERN_CONFIG\n): number {\n const { frequency, amplitude, speed } = config;\n\n // Normalize coordinates to 0-1\n const nx = x / cols;\n const ny = y / rows;\n\n // Animated angle for gradient direction\n const angle = time * speed * 0.2;\n const cos = Math.cos(angle);\n const sin = Math.sin(angle);\n\n // Rotate the gradient\n const rotated = nx * cos + ny * sin;\n\n // Add some wave distortion\n const distortion = Math.sin(ny * Math.PI * 2 * frequency + time * speed) * 0.1;\n\n const value = (rotated + distortion) * 2 - 1;\n return Math.sin(value * Math.PI) * amplitude;\n}\n\n/**\n * Diamond pattern - interference creating diamond shapes\n *\n * @param x - X coordinate\n * @param y - Y coordinate\n * @param time - Time value for animation\n * @param config - Pattern configuration\n * @returns Value between -1 and 1\n */\nexport function diamondPattern(\n x: number,\n y: number,\n time: number,\n config: PatternConfig = DEFAULT_PATTERN_CONFIG\n): number {\n const { frequency, amplitude, speed } = config;\n const t = time * speed;\n\n // Diamond pattern using absolute value (Manhattan distance creates diamonds)\n const wave1 = Math.sin((Math.abs(x - 40) + Math.abs(y - 20)) * frequency + t);\n const wave2 = Math.sin((Math.abs(x - 40) - Math.abs(y - 20)) * frequency * 0.7 - t * 0.8);\n\n // Add some rotation over time\n const angle = t * 0.1;\n const rx = x * Math.cos(angle) - y * Math.sin(angle);\n const ry = x * Math.sin(angle) + y * Math.cos(angle);\n const wave3 = Math.sin((Math.abs(rx) + Math.abs(ry)) * frequency * 0.5 + t * 0.5);\n\n return ((wave1 + wave2 + wave3) / 3) * amplitude;\n}\n\n/**\n * Fractal pattern - animated Mandelbrot/Julia set\n *\n * @param x - X coordinate\n * @param y - Y coordinate\n * @param cols - Total columns (for centering)\n * @param rows - Total rows (for centering)\n * @param time - Time value for animation\n * @param config - Pattern configuration\n * @returns Value between -1 and 1\n */\nexport function fractalPattern(\n x: number,\n y: number,\n cols: number,\n rows: number,\n time: number,\n config: PatternConfig = DEFAULT_PATTERN_CONFIG\n): number {\n const { frequency, amplitude, speed } = config;\n\n // Map to complex plane, centered and scaled\n const scale = 3.5 * frequency;\n const zx = ((x / cols) * scale - scale / 2) + Math.sin(time * speed * 0.1) * 0.2;\n const zy = ((y / rows) * scale - scale / 2) + Math.cos(time * speed * 0.1) * 0.2;\n\n // Julia set with animated c parameter\n const cx = -0.7 + Math.sin(time * speed * 0.05) * 0.1;\n const cy = 0.27 + Math.cos(time * speed * 0.07) * 0.1;\n\n let zrx = zx;\n let zry = zy;\n const maxIter = 20;\n let iter = 0;\n\n // Iterate z = z² + c\n while (zrx * zrx + zry * zry < 4 && iter < maxIter) {\n const tmp = zrx * zrx - zry * zry + cx;\n zry = 2 * zrx * zry + cy;\n zrx = tmp;\n iter++;\n }\n\n // Smooth coloring\n if (iter === maxIter) {\n return -1 * amplitude; // Inside the set\n }\n\n // Normalize iteration count to [-1, 1]\n const smooth = iter - Math.log2(Math.log2(zrx * zrx + zry * zry));\n return ((smooth / maxIter) * 2 - 1) * amplitude;\n}\n\n/**\n * Generate a brightness grid for pattern rendering\n *\n * @param cols - Number of columns\n * @param rows - Number of rows\n * @param pattern - Pattern type\n * @param time - Current time in seconds\n * @param config - Pattern configuration\n * @returns 2D array of brightness values (0-255)\n */\nexport function generateBrightnessGrid(\n cols: number,\n rows: number,\n pattern: PatternType,\n time: number = 0,\n config: PatternConfig = DEFAULT_PATTERN_CONFIG\n): number[][] {\n const grid: number[][] = [];\n const { frequency, amplitude, speed } = config;\n\n for (let row = 0; row < rows; row++) {\n grid[row] = [];\n for (let col = 0; col < cols; col++) {\n let value: number;\n\n switch (pattern) {\n case 'perlin':\n value = perlinNoise2D(\n col * frequency + time * speed * 0.1,\n row * frequency + time * speed * 0.05\n );\n break;\n\n case 'fbm':\n value = fbmNoise(\n col * frequency + time * speed * 0.1,\n row * frequency + time * speed * 0.05,\n 4,\n 0.5\n );\n break;\n\n case 'waves':\n value = wavePattern(col, row, time, config);\n break;\n\n case 'ripple':\n value = ripplePattern(col, row, cols / 2, rows / 2, time, config);\n break;\n\n case 'static':\n // For static, use time as seed for animated static\n value = seededNoise2D(col, row, Math.floor(time * speed * 10)) * 2 - 1;\n break;\n\n case 'clouds':\n value = cloudsPattern(col, row, time, config);\n break;\n\n case 'plasma':\n value = plasmaPattern(col, row, time, config);\n break;\n\n case 'vortex':\n value = vortexPattern(col, row, cols / 2, rows / 2, time, config);\n break;\n\n case 'matrix':\n value = matrixPattern(col, row, time, config);\n break;\n\n case 'gradient':\n value = gradientPattern(col, row, cols, rows, time, config);\n break;\n\n case 'diamond':\n value = diamondPattern(col, row, time, config);\n break;\n\n case 'fractal':\n value = fractalPattern(col, row, cols, rows, time, config);\n break;\n\n default:\n value = seededNoise2D(col, row, Math.floor(time * speed * 10)) * 2 - 1;\n break;\n }\n\n // Normalize from [-1, 1] to [0, 255] with amplitude\n const normalized = (value + 1) * 0.5 * amplitude;\n const brightness = Math.max(0, Math.min(255, Math.floor(normalized * 255)));\n grid[row][col] = brightness;\n }\n }\n\n return grid;\n}\n\n/**\n * Generate ImageData from a brightness grid\n *\n * @param grid - 2D array of brightness values\n * @param cellWidth - Width of each cell\n * @param cellHeight - Height of each cell\n * @returns ImageData object\n */\nexport function gridToImageData(grid: number[][], cellWidth: number, cellHeight: number): ImageData {\n const rows = grid.length;\n const cols = grid[0]?.length || 0;\n const width = cols * cellWidth;\n const height = rows * cellHeight;\n const data = new Uint8ClampedArray(width * height * 4);\n\n for (let row = 0; row < rows; row++) {\n for (let col = 0; col < cols; col++) {\n const brightness = grid[row][col];\n\n // Fill cell region with brightness value\n for (let cy = 0; cy < cellHeight; cy++) {\n for (let cx = 0; cx < cellWidth; cx++) {\n const px = ((row * cellHeight + cy) * width + (col * cellWidth + cx)) * 4;\n data[px] = brightness; // R\n data[px + 1] = brightness; // G\n data[px + 2] = brightness; // B\n data[px + 3] = 255; // A\n }\n }\n }\n }\n\n return new ImageData(data, width, height);\n}\n\nexport type PatternType =\n | 'perlin'\n | 'waves'\n | 'static'\n | 'ripple'\n | 'fbm'\n | 'clouds'\n | 'plasma'\n | 'vortex'\n | 'matrix'\n | 'gradient'\n | 'diamond'\n | 'fractal';\n\n// ============================================================================\n// PERFORMANCE-OPTIMIZED API\n// ============================================================================\n\n/**\n * Reusable brightness buffer using flat Uint8Array\n * ~30% faster than number[][] due to contiguous memory and no GC pressure\n */\nexport interface BrightnessBuffer {\n /** Flat array of brightness values (0-255), row-major order */\n data: Uint8Array;\n /** Number of columns */\n cols: number;\n /** Number of rows */\n rows: number;\n}\n\n/**\n * Create a reusable brightness buffer\n * Call once at init, then reuse with fillBrightnessBuffer\n *\n * @param cols - Number of columns\n * @param rows - Number of rows\n * @returns Reusable buffer object\n */\nexport function createBrightnessBuffer(cols: number, rows: number): BrightnessBuffer {\n return {\n data: new Uint8Array(cols * rows),\n cols,\n rows,\n };\n}\n\n/**\n * Fill an existing brightness buffer with pattern data (zero allocation)\n * Use this in animation loops for best performance\n *\n * @param buffer - Pre-allocated buffer from createBrightnessBuffer\n * @param pattern - Pattern type to generate\n * @param time - Current time in seconds\n * @param config - Pattern configuration\n */\nexport function fillBrightnessBuffer(\n buffer: BrightnessBuffer,\n pattern: PatternType,\n time: number = 0,\n config: PatternConfig = DEFAULT_PATTERN_CONFIG\n): void {\n const { data, cols, rows } = buffer;\n const { frequency, amplitude, speed } = config;\n\n let idx = 0;\n for (let row = 0; row < rows; row++) {\n for (let col = 0; col < cols; col++) {\n let value: number;\n\n switch (pattern) {\n case 'perlin':\n value = perlinNoise2D(\n col * frequency + time * speed * 0.1,\n row * frequency + time * speed * 0.05\n );\n break;\n\n case 'fbm':\n value = fbmNoise(\n col * frequency + time * speed * 0.1,\n row * frequency + time * speed * 0.05,\n 4,\n 0.5\n );\n break;\n\n case 'waves':\n value = wavePattern(col, row, time, config);\n break;\n\n case 'ripple':\n value = ripplePattern(col, row, cols / 2, rows / 2, time, config);\n break;\n\n case 'static':\n value = seededNoise2D(col, row, Math.floor(time * speed * 10)) * 2 - 1;\n break;\n\n case 'clouds':\n value = cloudsPattern(col, row, time, config);\n break;\n\n case 'plasma':\n value = plasmaPattern(col, row, time, config);\n break;\n\n case 'vortex':\n value = vortexPattern(col, row, cols / 2, rows / 2, time, config);\n break;\n\n case 'matrix':\n value = matrixPattern(col, row, time, config);\n break;\n\n case 'gradient':\n value = gradientPattern(col, row, cols, rows, time, config);\n break;\n\n case 'diamond':\n value = diamondPattern(col, row, time, config);\n break;\n\n case 'fractal':\n value = fractalPattern(col, row, cols, rows, time, config);\n break;\n\n default:\n value = seededNoise2D(col, row, Math.floor(time * speed * 10)) * 2 - 1;\n break;\n }\n\n // Normalize from [-1, 1] to [0, 255] with amplitude\n // Using bitwise OR for fast floor: (x | 0) is faster than Math.floor(x)\n const normalized = (value + 1) * 0.5 * amplitude;\n data[idx++] = normalized * 255 | 0;\n }\n }\n}\n\n/**\n * Get brightness value from buffer at (col, row)\n * @param buffer - Brightness buffer\n * @param col - Column index\n * @param row - Row index\n * @returns Brightness value 0-255\n */\nexport function getBufferValue(buffer: BrightnessBuffer, col: number, row: number): number {\n return buffer.data[row * buffer.cols + col];\n}\n","/**\n * Gossamer Character Sets\n *\n * Predefined character sets for ASCII rendering, ordered from light to dark.\n * Character density determines which character represents each brightness level.\n */\n\n/**\n * Character set configuration\n */\nexport interface CharacterSet {\n /** Unique identifier for the character set */\n name: string;\n /** Description of the set's aesthetic */\n description: string;\n /** Characters ordered from lightest (space) to darkest */\n characters: string;\n /** Recommended use cases */\n bestFor: string[];\n}\n\n/**\n * Standard character sets for ASCII rendering\n */\nexport const CHARACTER_SETS: Record<string, CharacterSet> = {\n standard: {\n name: 'Standard',\n description: 'Classic ASCII art character set',\n characters: ' .:-=+*#%@',\n bestFor: ['general', 'images', 'patterns'],\n },\n\n dense: {\n name: 'Dense',\n description: 'High detail character set with many gradations',\n characters: \" .'`^\\\",:;Il!i><~+_-?][}{1)(|\\\\/tfjrxnuvczXYUJCLQ0OZmwqpdbkhao*#MW&8%B@$\",\n bestFor: ['detailed images', 'portraits', 'high contrast'],\n },\n\n minimal: {\n name: 'Minimal',\n description: 'Clean and simple with few characters',\n characters: ' .:*#',\n bestFor: ['backgrounds', 'subtle effects', 'clean aesthetic'],\n },\n\n grove: {\n name: 'Grove',\n description: 'Organic, soft characters inspired by nature',\n characters: ' ·∙•◦○◉●',\n bestFor: ['organic patterns', 'soft backgrounds', 'nature themes'],\n },\n\n dots: {\n name: 'Dots',\n description: 'Braille-like dot patterns',\n characters: ' ⋅∘∙●',\n bestFor: ['stipple effects', 'pointillism', 'dotted textures'],\n },\n\n blocks: {\n name: 'Blocks',\n description: 'Block-based characters for sharp edges',\n characters: ' ░▒▓█',\n bestFor: ['retro effects', 'pixel art', 'bold patterns'],\n },\n\n lines: {\n name: 'Lines',\n description: 'Line-based characters for directional effects',\n characters: ' -─═╌│┃',\n bestFor: ['rain effects', 'streaks', 'motion blur'],\n },\n\n stars: {\n name: 'Stars',\n description: 'Star and sparkle characters',\n characters: ' ·✧✦✫✬✯★',\n bestFor: ['sparkle effects', 'night sky', 'magical themes'],\n },\n\n nature: {\n name: 'Nature',\n description: 'Nature-themed decorative characters',\n characters: ' .~≈∿⌇☘',\n bestFor: ['decorative', 'themed effects', 'organic patterns'],\n },\n\n weather: {\n name: 'Weather',\n description: 'Weather-related symbols',\n characters: ' ·.:*❄❅❆',\n bestFor: ['snow effects', 'weather simulations', 'seasonal themes'],\n },\n\n binary: {\n name: 'Binary',\n description: 'Digital-style binary characters',\n characters: ' 01',\n bestFor: ['digital effects', 'matrix style', 'tech themes'],\n },\n\n math: {\n name: 'Math',\n description: 'Mathematical symbols',\n characters: ' +-×÷=≠≈∞',\n bestFor: ['abstract patterns', 'tech themes', 'decorative'],\n },\n\n // ==========================================================================\n // GLASS-OPTIMIZED CHARACTER SETS\n // Designed for subtle overlays on Glass components\n // More characters = more visible gradations\n // ==========================================================================\n\n 'glass-dots': {\n name: 'Glass Dots',\n description: 'Soft dot gradations for glass overlays',\n characters: ' ·∘∙○•●',\n bestFor: ['glass overlays', 'subtle backgrounds', 'mist effects'],\n },\n\n 'glass-mist': {\n name: 'Glass Mist',\n description: 'Ethereal mist effect for glass',\n characters: ' .·∙•◦○◉●',\n bestFor: ['glass overlays', 'fog effects', 'ambient backgrounds'],\n },\n\n 'glass-dust': {\n name: 'Glass Dust',\n description: 'Floating dust particles',\n characters: ' ˙·∘°•◦○',\n bestFor: ['glass overlays', 'particle effects', 'light scatter'],\n },\n\n 'glass-soft': {\n name: 'Glass Soft',\n description: 'Soft block gradations for glass',\n characters: ' ·░▒▓',\n bestFor: ['glass overlays', 'soft gradients', 'frosted effect'],\n },\n\n 'glass-sparkle': {\n name: 'Glass Sparkle',\n description: 'Subtle sparkles for glass',\n characters: ' ·.✧✦✫★',\n bestFor: ['glass overlays', 'highlight effects', 'magical themes'],\n },\n\n 'glass-wave': {\n name: 'Glass Wave',\n description: 'Flowing wave patterns for glass',\n characters: ' .~∼≈≋',\n bestFor: ['glass overlays', 'water effects', 'flowing motion'],\n },\n\n 'glass-organic': {\n name: 'Glass Organic',\n description: 'Natural, organic feel for glass',\n characters: ' .·:;∘○◦•●',\n bestFor: ['glass overlays', 'nature themes', 'grove aesthetic'],\n },\n};\n\n/**\n * Get a character set by name\n */\nexport function getCharacterSet(name: string): CharacterSet | undefined {\n return CHARACTER_SETS[name];\n}\n\n/**\n * Get just the characters string from a named set\n */\nexport function getCharacters(name: string): string {\n return CHARACTER_SETS[name]?.characters || CHARACTER_SETS.standard.characters;\n}\n\n/**\n * List all available character set names\n */\nexport function getCharacterSetNames(): string[] {\n return Object.keys(CHARACTER_SETS);\n}\n\n/**\n * Create a custom character set\n */\nexport function createCharacterSet(\n name: string,\n characters: string,\n description: string = '',\n bestFor: string[] = []\n): CharacterSet {\n return {\n name,\n description,\n characters,\n bestFor,\n };\n}\n\n/**\n * Validate that a character string is suitable for ASCII rendering\n * (should start with space and have at least 2 characters)\n */\nexport function validateCharacterSet(characters: string): boolean {\n if (characters.length < 2) return false;\n if (characters[0] !== ' ') return false;\n return true;\n}\n\n/**\n * Reverse a character set (for inverted brightness mapping)\n */\nexport function invertCharacters(characters: string): string {\n return characters.split('').reverse().join('');\n}\n","/**\n * Gossamer Color Palettes\n *\n * Grove-themed color palettes for ASCII effects.\n * Designed to complement Glass UI components.\n */\n\n/**\n * Color definition with metadata\n */\nexport interface ColorDef {\n /** Hex color value */\n hex: string;\n /** Human-readable name */\n name: string;\n /** Recommended opacity for glass overlays (0-1) */\n glassOpacity?: number;\n}\n\n/**\n * Grove Green palette - Primary brand colors\n */\nexport const GROVE_GREEN = {\n 50: { hex: '#f0fdf4', name: 'Grove Green 50', glassOpacity: 0.3 },\n 100: { hex: '#dcfce7', name: 'Grove Green 100', glassOpacity: 0.25 },\n 200: { hex: '#bbf7d0', name: 'Grove Green 200', glassOpacity: 0.2 },\n 300: { hex: '#86efac', name: 'Grove Green 300', glassOpacity: 0.18 },\n 400: { hex: '#4ade80', name: 'Grove Green 400', glassOpacity: 0.15 },\n 500: { hex: '#22c55e', name: 'Grove Green 500', glassOpacity: 0.12 },\n 600: { hex: '#16a34a', name: 'Grove Green 600', glassOpacity: 0.1 },\n 700: { hex: '#15803d', name: 'Grove Green 700', glassOpacity: 0.1 },\n 800: { hex: '#166534', name: 'Grove Green 800', glassOpacity: 0.08 },\n 900: { hex: '#14532d', name: 'Grove Green 900', glassOpacity: 0.08 },\n} as const;\n\n/**\n * Cream palette - Light/warm backgrounds\n */\nexport const CREAM = {\n 50: { hex: '#fefdfb', name: 'Cream 50', glassOpacity: 0.4 },\n 100: { hex: '#fdfcf8', name: 'Cream 100', glassOpacity: 0.35 },\n 200: { hex: '#faf8f3', name: 'Cream 200', glassOpacity: 0.3 },\n 300: { hex: '#f5f2ea', name: 'Cream 300', glassOpacity: 0.25 },\n 400: { hex: '#ede9de', name: 'Cream 400', glassOpacity: 0.2 },\n 500: { hex: '#e2ddd0', name: 'Cream 500', glassOpacity: 0.18 },\n 600: { hex: '#d4cec0', name: 'Cream 600', glassOpacity: 0.15 },\n 700: { hex: '#c4bdb0', name: 'Cream 700', glassOpacity: 0.12 },\n 800: { hex: '#b0a99c', name: 'Cream 800', glassOpacity: 0.1 },\n 900: { hex: '#9a9387', name: 'Cream 900', glassOpacity: 0.08 },\n} as const;\n\n/**\n * Bark palette - Dark/earth tones\n */\nexport const BARK = {\n 50: { hex: '#faf7f5', name: 'Bark 50', glassOpacity: 0.3 },\n 100: { hex: '#f0ebe6', name: 'Bark 100', glassOpacity: 0.25 },\n 200: { hex: '#e0d5cc', name: 'Bark 200', glassOpacity: 0.2 },\n 300: { hex: '#ccb59c', name: 'Bark 300', glassOpacity: 0.18 },\n 400: { hex: '#b89a7a', name: 'Bark 400', glassOpacity: 0.15 },\n 500: { hex: '#a57c5a', name: 'Bark 500', glassOpacity: 0.12 },\n 600: { hex: '#8a6344', name: 'Bark 600', glassOpacity: 0.1 },\n 700: { hex: '#6f4d39', name: 'Bark 700', glassOpacity: 0.1 },\n 800: { hex: '#553a2a', name: 'Bark 800', glassOpacity: 0.08 },\n 900: { hex: '#3d2914', name: 'Bark 900', glassOpacity: 0.06 },\n} as const;\n\n/**\n * Status colors\n */\nexport const STATUS = {\n success: { hex: '#22c55e', name: 'Success', glassOpacity: 0.12 },\n warning: { hex: '#f59e0b', name: 'Warning', glassOpacity: 0.12 },\n error: { hex: '#dc2626', name: 'Error', glassOpacity: 0.1 },\n info: { hex: '#0ea5e9', name: 'Info', glassOpacity: 0.12 },\n} as const;\n\n/**\n * Combined Grove color schemes for easy access\n */\nexport const GROVE_COLORS = {\n // Greens\n grove: GROVE_GREEN[500].hex,\n 'grove-light': GROVE_GREEN[300].hex,\n 'grove-dark': GROVE_GREEN[700].hex,\n 'grove-muted': GROVE_GREEN[400].hex,\n\n // Creams\n cream: CREAM[50].hex,\n 'cream-warm': CREAM[200].hex,\n 'cream-deep': CREAM[500].hex,\n\n // Barks\n bark: BARK[900].hex,\n 'bark-light': BARK[500].hex,\n 'bark-medium': BARK[700].hex,\n\n // Utility\n white: '#ffffff',\n black: '#000000',\n transparent: 'transparent',\n} as const;\n\n/**\n * Glass-optimized color schemes\n * Pre-configured for use with Glass components\n */\nexport const GLASS_SCHEMES = {\n // Light mode schemes (on light backgrounds)\n 'grove-mist': {\n color: GROVE_GREEN[500].hex,\n background: 'transparent',\n opacity: 0.12,\n description: 'Subtle green mist for light glass',\n },\n 'cream-haze': {\n color: CREAM[600].hex,\n background: 'transparent',\n opacity: 0.15,\n description: 'Warm cream haze for cozy glass',\n },\n 'bark-shadow': {\n color: BARK[700].hex,\n background: 'transparent',\n opacity: 0.08,\n description: 'Soft earth shadow for depth',\n },\n\n // Dark mode schemes (on dark backgrounds)\n 'grove-glow': {\n color: GROVE_GREEN[400].hex,\n background: '#1a1915',\n opacity: 0.15,\n description: 'Glowing green for dark glass',\n },\n 'cream-dust': {\n color: CREAM[300].hex,\n background: '#1a1915',\n opacity: 0.1,\n description: 'Dusty cream particles in dark',\n },\n 'moonlight': {\n color: '#e2e8f0',\n background: '#1a1915',\n opacity: 0.08,\n description: 'Cool moonlight glow',\n },\n\n // Accent schemes\n 'spring-fresh': {\n color: GROVE_GREEN[300].hex,\n background: 'transparent',\n opacity: 0.18,\n description: 'Fresh spring green overlay',\n },\n 'autumn-warm': {\n color: '#d97706',\n background: 'transparent',\n opacity: 0.1,\n description: 'Warm autumn amber tones',\n },\n 'winter-frost': {\n color: '#93c5fd',\n background: 'transparent',\n opacity: 0.12,\n description: 'Cool frost blue overlay',\n },\n} as const;\n\nexport type GroveColorName = keyof typeof GROVE_COLORS;\nexport type GlassSchemeName = keyof typeof GLASS_SCHEMES;\n\n/**\n * Get a Grove color by name\n */\nexport function getGroveColor(name: GroveColorName | string): string {\n if (name in GROVE_COLORS) {\n return GROVE_COLORS[name as GroveColorName];\n }\n // If it's already a hex color, return it\n if (name.startsWith('#')) {\n return name;\n }\n // Default to grove green\n return GROVE_COLORS.grove;\n}\n\n/**\n * Get a glass scheme by name\n */\nexport function getGlassScheme(name: GlassSchemeName | string): {\n color: string;\n background: string;\n opacity: number;\n} {\n if (name in GLASS_SCHEMES) {\n const scheme = GLASS_SCHEMES[name as GlassSchemeName];\n return {\n color: scheme.color,\n background: scheme.background,\n opacity: scheme.opacity,\n };\n }\n // Default to grove-mist\n return {\n color: GLASS_SCHEMES['grove-mist'].color,\n background: GLASS_SCHEMES['grove-mist'].background,\n opacity: GLASS_SCHEMES['grove-mist'].opacity,\n };\n}\n\n/**\n * List all Grove color names\n */\nexport function getGroveColorNames(): string[] {\n return Object.keys(GROVE_COLORS);\n}\n\n/**\n * List all glass scheme names\n */\nexport function getGlassSchemeNames(): string[] {\n return Object.keys(GLASS_SCHEMES);\n}\n\n/**\n * Apply opacity to a hex color, returning rgba string\n */\nexport function hexToRgba(hex: string, opacity: number): string {\n const r = parseInt(hex.slice(1, 3), 16);\n const g = parseInt(hex.slice(3, 5), 16);\n const b = parseInt(hex.slice(5, 7), 16);\n return `rgba(${r}, ${g}, ${b}, ${opacity})`;\n}\n","/**\n * Gossamer Animation Utilities\n *\n * FPS limiting, animation loop management, and timing utilities.\n */\n\n/**\n * Animation state for tracking loop execution\n */\nexport interface AnimationState {\n /** Whether animation is currently running */\n isRunning: boolean;\n /** Current animation frame ID */\n frameId: number | null;\n /** Timestamp of last frame */\n lastFrameTime: number;\n /** Frame interval in ms (derived from FPS) */\n frameInterval: number;\n /** Total elapsed time in ms */\n elapsedTime: number;\n /** Current frame count */\n frameCount: number;\n}\n\n/**\n * Options for creating an animation loop\n */\nexport interface AnimationOptions {\n /** Target frames per second (default: 30) */\n fps?: number;\n /** Callback when animation starts */\n onStart?: () => void;\n /** Callback when animation stops */\n onStop?: () => void;\n /** Callback for each frame - return false to stop */\n onFrame: (time: number, deltaTime: number, frameCount: number) => boolean | void;\n}\n\n/**\n * Create a managed animation loop with FPS limiting\n */\nexport function createAnimationLoop(options: AnimationOptions): {\n start: () => void;\n stop: () => void;\n pause: () => void;\n resume: () => void;\n getState: () => AnimationState;\n} {\n const { fps = 30, onStart, onStop, onFrame } = options;\n\n const state: AnimationState = {\n isRunning: false,\n frameId: null,\n lastFrameTime: 0,\n frameInterval: 1000 / fps,\n elapsedTime: 0,\n frameCount: 0,\n };\n\n let pausedTime = 0;\n let isPaused = false;\n\n function animate(currentTime: number): void {\n if (!state.isRunning || isPaused) return;\n\n const deltaTime = currentTime - state.lastFrameTime;\n\n if (deltaTime >= state.frameInterval) {\n state.elapsedTime += deltaTime;\n state.frameCount++;\n\n const continueAnimation = onFrame(currentTime, deltaTime, state.frameCount);\n\n if (continueAnimation === false) {\n stop();\n return;\n }\n\n // Adjust for frame timing drift\n state.lastFrameTime = currentTime - (deltaTime % state.frameInterval);\n }\n\n state.frameId = requestAnimationFrame(animate);\n }\n\n function start(): void {\n if (state.isRunning) return;\n\n state.isRunning = true;\n state.lastFrameTime = performance.now();\n state.elapsedTime = 0;\n state.frameCount = 0;\n isPaused = false;\n\n onStart?.();\n state.frameId = requestAnimationFrame(animate);\n }\n\n function stop(): void {\n state.isRunning = false;\n isPaused = false;\n\n if (state.frameId !== null) {\n cancelAnimationFrame(state.frameId);\n state.frameId = null;\n }\n\n onStop?.();\n }\n\n function pause(): void {\n if (!state.isRunning || isPaused) return;\n\n isPaused = true;\n pausedTime = performance.now();\n\n if (state.frameId !== null) {\n cancelAnimationFrame(state.frameId);\n state.frameId = null;\n }\n }\n\n function resume(): void {\n if (!state.isRunning || !isPaused) return;\n\n isPaused = false;\n // Adjust lastFrameTime to account for paused duration\n state.lastFrameTime += performance.now() - pausedTime;\n state.frameId = requestAnimationFrame(animate);\n }\n\n function getState(): AnimationState {\n return { ...state };\n }\n\n return { start, stop, pause, resume, getState };\n}\n\n/**\n * Simple throttle function for limiting function execution\n */\nexport function throttle<T extends (...args: unknown[]) => unknown>(\n fn: T,\n limit: number\n): (...args: Parameters<T>) => void {\n let lastCall = 0;\n let timeout: ReturnType<typeof setTimeout> | null = null;\n\n return (...args: Parameters<T>): void => {\n const now = Date.now();\n\n if (now - lastCall >= limit) {\n lastCall = now;\n fn(...args);\n } else if (!timeout) {\n timeout = setTimeout(() => {\n lastCall = Date.now();\n timeout = null;\n fn(...args);\n }, limit - (now - lastCall));\n }\n };\n}\n\n/**\n * Debounce function for delaying execution until activity stops\n */\nexport function debounce<T extends (...args: unknown[]) => unknown>(\n fn: T,\n delay: number\n): (...args: Parameters<T>) => void {\n let timeout: ReturnType<typeof setTimeout> | null = null;\n\n return (...args: Parameters<T>): void => {\n if (timeout) {\n clearTimeout(timeout);\n }\n\n timeout = setTimeout(() => {\n timeout = null;\n fn(...args);\n }, delay);\n };\n}\n\n/**\n * Calculate actual FPS from frame times\n */\nexport function calculateFPS(frameTimes: number[], sampleSize: number = 60): number {\n if (frameTimes.length < 2) return 0;\n\n const samples = frameTimes.slice(-sampleSize);\n const totalTime = samples[samples.length - 1] - samples[0];\n const frameCount = samples.length - 1;\n\n if (totalTime <= 0) return 0;\n\n return (frameCount / totalTime) * 1000;\n}\n\n/**\n * Easing functions for smooth animations\n */\nexport const easings = {\n /** Linear - no easing */\n linear: (t: number): number => t,\n\n /** Ease in - slow start */\n easeIn: (t: number): number => t * t,\n\n /** Ease out - slow end */\n easeOut: (t: number): number => t * (2 - t),\n\n /** Ease in/out - slow start and end */\n easeInOut: (t: number): number => (t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t),\n\n /** Sine ease in */\n sineIn: (t: number): number => 1 - Math.cos((t * Math.PI) / 2),\n\n /** Sine ease out */\n sineOut: (t: number): number => Math.sin((t * Math.PI) / 2),\n\n /** Sine ease in/out */\n sineInOut: (t: number): number => -(Math.cos(Math.PI * t) - 1) / 2,\n\n /** Bounce at end */\n bounceOut: (t: number): number => {\n const n1 = 7.5625;\n const d1 = 2.75;\n\n if (t < 1 / d1) {\n return n1 * t * t;\n } else if (t < 2 / d1) {\n return n1 * (t -= 1.5 / d1) * t + 0.75;\n } else if (t < 2.5 / d1) {\n return n1 * (t -= 2.25 / d1) * t + 0.9375;\n } else {\n return n1 * (t -= 2.625 / d1) * t + 0.984375;\n }\n },\n};\n\nexport type EasingFunction = (t: number) => number;\n","/**\n * Canvas Utilities\n *\n * Helper functions for canvas creation, setup, and manipulation.\n */\n\n/**\n * Options for canvas creation\n */\nexport interface CanvasOptions {\n /** Canvas width in pixels */\n width?: number;\n /** Canvas height in pixels */\n height?: number;\n /** Whether to use high DPI scaling */\n highDPI?: boolean;\n /** CSS class to add to canvas */\n className?: string;\n /** Inline styles to apply */\n style?: Partial<CSSStyleDeclaration>;\n}\n\n/**\n * Create a canvas element with optimal settings\n */\nexport function createCanvas(options: CanvasOptions = {}): HTMLCanvasElement {\n const { width = 300, height = 150, highDPI = true, className, style } = options;\n\n const canvas = document.createElement('canvas');\n\n if (highDPI) {\n const dpr = window.devicePixelRatio || 1;\n canvas.width = width * dpr;\n canvas.height = height * dpr;\n canvas.style.width = `${width}px`;\n canvas.style.height = `${height}px`;\n\n const ctx = canvas.getContext('2d');\n if (ctx) {\n ctx.scale(dpr, dpr);\n }\n } else {\n canvas.width = width;\n canvas.height = height;\n }\n\n if (className) {\n canvas.className = className;\n }\n\n if (style) {\n Object.assign(canvas.style, style);\n }\n\n return canvas;\n}\n\n/**\n * Get the device pixel ratio\n */\nexport function getDevicePixelRatio(): number {\n return typeof window !== 'undefined' ? window.devicePixelRatio || 1 : 1;\n}\n\n/**\n * Resize canvas to match container dimensions\n */\nexport function resizeCanvasToContainer(\n canvas: HTMLCanvasElement,\n container: HTMLElement,\n highDPI: boolean = true\n): { width: number; height: number } {\n const rect = container.getBoundingClientRect();\n const dpr = highDPI ? getDevicePixelRatio() : 1;\n\n const width = rect.width;\n const height = rect.height;\n\n canvas.width = width * dpr;\n canvas.height = height * dpr;\n canvas.style.width = `${width}px`;\n canvas.style.height = `${height}px`;\n\n if (highDPI) {\n const ctx = canvas.getContext('2d');\n if (ctx) {\n ctx.scale(dpr, dpr);\n }\n }\n\n return { width, height };\n}\n\n/**\n * Create an offscreen canvas for buffer rendering\n */\nexport function createOffscreenCanvas(width: number, height: number): HTMLCanvasElement | OffscreenCanvas {\n if (typeof OffscreenCanvas !== 'undefined') {\n return new OffscreenCanvas(width, height);\n }\n\n // Fallback for environments without OffscreenCanvas\n const canvas = document.createElement('canvas');\n canvas.width = width;\n canvas.height = height;\n return canvas;\n}\n\n/**\n * Clear a canvas\n */\nexport function clearCanvas(\n ctx: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D,\n width: number,\n height: number,\n backgroundColor?: string\n): void {\n if (backgroundColor) {\n ctx.fillStyle = backgroundColor;\n ctx.fillRect(0, 0, width, height);\n } else {\n ctx.clearRect(0, 0, width, height);\n }\n}\n\n/**\n * Get image data from a canvas region\n */\nexport function getImageData(\n ctx: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D,\n x: number = 0,\n y: number = 0,\n width?: number,\n height?: number\n): ImageData {\n const canvas = ctx.canvas;\n const w = width ?? canvas.width;\n const h = height ?? canvas.height;\n\n return ctx.getImageData(x, y, w, h);\n}\n\n/**\n * Set optimal rendering context settings\n */\nexport function optimizeContext(ctx: CanvasRenderingContext2D): void {\n // Disable image smoothing for crisp ASCII rendering\n ctx.imageSmoothingEnabled = false;\n\n // Use source-over for standard compositing\n ctx.globalCompositeOperation = 'source-over';\n}\n\n/**\n * Set text rendering options for ASCII display\n */\nexport function setupTextRendering(\n ctx: CanvasRenderingContext2D,\n fontSize: number,\n fontFamily: string = 'monospace',\n color: string = '#ffffff'\n): void {\n ctx.font = `${fontSize}px ${fontFamily}`;\n ctx.textBaseline = 'top';\n ctx.textAlign = 'left';\n ctx.fillStyle = color;\n}\n\n/**\n * Measure text width for a given font configuration\n */\nexport function measureTextWidth(\n ctx: CanvasRenderingContext2D,\n text: string,\n fontSize: number,\n fontFamily: string = 'monospace'\n): number {\n const originalFont = ctx.font;\n ctx.font = `${fontSize}px ${fontFamily}`;\n const metrics = ctx.measureText(text);\n ctx.font = originalFont;\n return metrics.width;\n}\n\n/**\n * Calculate optimal cell size for a given canvas and desired columns\n */\nexport function calculateCellSize(\n canvasWidth: number,\n canvasHeight: number,\n targetCols: number\n): { cellWidth: number; cellHeight: number; cols: number; rows: number } {\n const cellWidth = Math.floor(canvasWidth / targetCols);\n // Use a typical monospace aspect ratio of ~0.6\n const cellHeight = Math.floor(cellWidth * 1.5);\n const cols = Math.floor(canvasWidth / cellWidth);\n const rows = Math.floor(canvasHeight / cellHeight);\n\n return { cellWidth, cellHeight, cols, rows };\n}\n\n/**\n * Apply a CSS blend mode to canvas compositing\n */\nexport function setBlendMode(\n ctx: CanvasRenderingContext2D,\n mode: 'normal' | 'multiply' | 'screen' | 'overlay' | 'darken' | 'lighten' | 'color-dodge' | 'color-burn' | 'soft-light' | 'hard-light' | 'difference' | 'exclusion'\n): void {\n ctx.globalCompositeOperation = mode === 'normal' ? 'source-over' : mode;\n}\n","/**\n * Image Utilities\n *\n * Image loading, processing, and pixel manipulation for ASCII conversion.\n */\n\n/**\n * Image loading options\n */\nexport interface ImageLoadOptions {\n /** Cross-origin setting for external images */\n crossOrigin?: 'anonymous' | 'use-credentials' | '';\n /** Maximum width to scale image to */\n maxWidth?: number;\n /** Maximum height to scale image to */\n maxHeight?: number;\n /** Whether to preserve aspect ratio when scaling */\n preserveAspectRatio?: boolean;\n}\n\n/**\n * Load an image from a URL\n */\nexport function loadImage(src: string, options: ImageLoadOptions = {}): Promise<HTMLImageElement> {\n return new Promise((resolve, reject) => {\n const img = new Image();\n\n if (options.crossOrigin !== undefined) {\n img.crossOrigin = options.crossOrigin;\n }\n\n img.onload = () => resolve(img);\n img.onerror = () => reject(new Error(`Failed to load image: ${src}`));\n\n img.src = src;\n });\n}\n\n/**\n * Load and scale an image to fit within bounds\n */\nexport async function loadAndScaleImage(\n src: string,\n maxWidth: number,\n maxHeight: number,\n options: ImageLoadOptions = {}\n): Promise<{ image: HTMLImageElement; width: number; height: number }> {\n const img = await loadImage(src, options);\n\n let width = img.naturalWidth;\n let height = img.naturalHeight;\n\n // Scale down if needed\n if (width > maxWidth || height > maxHeight) {\n const widthRatio = maxWidth / width;\n const heightRatio = maxHeight / height;\n const scale = Math.min(widthRatio, heightRatio);\n\n width = Math.floor(width * scale);\n height = Math.floor(height * scale);\n }\n\n return { image: img, width, height };\n}\n\n/**\n * Draw an image to a canvas and get its pixel data\n */\nexport function imageToPixelData(\n image: HTMLImageElement | HTMLCanvasElement | ImageBitmap,\n width?: number,\n height?: number\n): ImageData {\n const w = width ?? (image instanceof HTMLImageElement ? image.naturalWidth : image.width);\n const h = height ?? (image instanceof HTMLImageElement ? image.naturalHeight : image.height);\n\n const canvas = document.createElement('canvas');\n canvas.width = w;\n canvas.height = h;\n\n const ctx = canvas.getContext('2d');\n if (!ctx) {\n throw new Error('Failed to get 2D context');\n }\n\n ctx.drawImage(image, 0, 0, w, h);\n return ctx.getImageData(0, 0, w, h);\n}\n\n/**\n * Extract brightness values from image data\n */\nexport function extractBrightness(\n imageData: ImageData,\n brightnessFunction: (r: number, g: number, b: number) => number = (r, g, b) => 0.21 * r + 0.72 * g + 0.07 * b\n): number[] {\n const { data, width, height } = imageData;\n const brightness: number[] = new Array(width * height);\n\n for (let i = 0; i < data.length; i += 4) {\n brightness[i / 4] = brightnessFunction(data[i], data[i + 1], data[i + 2]);\n }\n\n return brightness;\n}\n\n/**\n * Sample image data at cell-based intervals\n */\nexport function sampleImageCells(\n imageData: ImageData,\n cellWidth: number,\n cellHeight: number,\n brightnessFunction: (r: number, g: number, b: number) => number = (r, g, b) => 0.21 * r + 0.72 * g + 0.07 * b\n): { brightness: number; color: string }[][] {\n const { data, width, height } = imageData;\n const cols = Math.ceil(width / cellWidth);\n const rows = Math.ceil(height / cellHeight);\n\n const result: { brightness: number; color: string }[][] = [];\n\n for (let row = 0; row < rows; row++) {\n result[row] = [];\n\n for (let col = 0; col < cols; col++) {\n const cellData = sampleCell(data, width, col * cellWidth, row * cellHeight, cellWidth, cellHeight);\n const brightness = brightnessFunction(cellData.r, cellData.g, cellData.b);\n\n result[row][col] = {\n brightness,\n color: `rgb(${Math.round(cellData.r)}, ${Math.round(cellData.g)}, ${Math.round(cellData.b)})`,\n };\n }\n }\n\n return result;\n}\n\n/**\n * Sample average color from a cell region\n */\nfunction sampleCell(\n data: Uint8ClampedArray,\n imageWidth: number,\n startX: number,\n startY: number,\n cellWidth: number,\n cellHeight: number\n): { r: number; g: number; b: number; a: number } {\n let totalR = 0;\n let totalG = 0;\n let totalB = 0;\n let totalA = 0;\n let count = 0;\n\n for (let y = startY; y < startY + cellHeight; y++) {\n for (let x = startX; x < startX + cellWidth; x++) {\n const px = (y * imageWidth + x) * 4;\n\n if (px >= 0 && px + 3 < data.length) {\n totalR += data[px];\n totalG += data[px + 1];\n totalB += data[px + 2];\n totalA += data[px + 3];\n count++;\n }\n }\n }\n\n if (count === 0) {\n return { r: 0, g: 0, b: 0, a: 0 };\n }\n\n return {\n r: totalR / count,\n g: totalG / count,\n b: totalB / count,\n a: totalA / count,\n };\n}\n\n/**\n * Convert RGB to hex color string\n */\nexport function rgbToHex(r: number, g: number, b: number): string {\n const toHex = (n: number) =>\n Math.max(0, Math.min(255, Math.round(n)))\n .toString(16)\n .padStart(2, '0');\n return `#${toHex(r)}${toHex(g)}${toHex(b)}`;\n}\n\n/**\n * Convert hex color to RGB\n */\nexport function hexToRgb(hex: string): { r: number; g: number; b: number } | null {\n const result = /^#?([a-f\\d]{2})([a-f\\d]{2})([a-f\\d]{2})$/i.exec(hex);\n return result\n ? {\n r: parseInt(result[1], 16),\n g: parseInt(result[2], 16),\n b: parseInt(result[3], 16),\n }\n : null;\n}\n\n/**\n * Adjust image brightness\n */\nexport function adjustBrightness(imageData: ImageData, amount: number): ImageData {\n const { data, width, height } = imageData;\n const adjusted = new Uint8ClampedArray(data.length);\n\n for (let i = 0; i < data.length; i += 4) {\n adjusted[i] = Math.min(255, Math.max(0, data[i] + amount));\n adjusted[i + 1] = Math.min(255, Math.max(0, data[i + 1] + amount));\n adjusted[i + 2] = Math.min(255, Math.max(0, data[i + 2] + amount));\n adjusted[i + 3] = data[i + 3];\n }\n\n return new ImageData(adjusted, width, height);\n}\n\n/**\n * Adjust image contrast\n */\nexport function adjustContrast(imageData: ImageData, amount: number): ImageData {\n const { data, width, height } = imageData;\n const adjusted = new Uint8ClampedArray(data.length);\n const factor = (259 * (amount + 255)) / (255 * (259 - amount));\n\n for (let i = 0; i < data.length; i += 4) {\n adjusted[i] = Math.min(255, Math.max(0, factor * (data[i] - 128) + 128));\n adjusted[i + 1] = Math.min(255, Math.max(0, factor * (data[i + 1] - 128) + 128));\n adjusted[i + 2] = Math.min(255, Math.max(0, factor * (data[i + 2] - 128) + 128));\n adjusted[i + 3] = data[i + 3];\n }\n\n return new ImageData(adjusted, width, height);\n}\n\n/**\n * Invert image colors\n */\nexport function invertColors(imageData: ImageData): ImageData {\n const { data, width, height } = imageData;\n const inverted = new Uint8ClampedArray(data.length);\n\n for (let i = 0; i < data.length; i += 4) {\n inverted[i] = 255 - data[i];\n inverted[i + 1] = 255 - data[i + 1];\n inverted[i + 2] = 255 - data[i + 2];\n inverted[i + 3] = data[i + 3];\n }\n\n return new ImageData(inverted, width, height);\n}\n\n/**\n * Convert image to grayscale\n */\nexport function toGrayscale(imageData: ImageData): ImageData {\n const { data, width, height } = imageData;\n const grayscale = new Uint8ClampedArray(data.length);\n\n for (let i = 0; i < data.length; i += 4) {\n const gray = 0.21 * data[i] + 0.72 * data[i + 1] + 0.07 * data[i + 2];\n grayscale[i] = gray;\n grayscale[i + 1] = gray;\n grayscale[i + 2] = gray;\n grayscale[i + 3] = data[i + 3];\n }\n\n return new ImageData(grayscale, width, height);\n}\n","/**\n * Performance Utilities\n *\n * Visibility detection, resource management, and optimization helpers.\n */\n\n/**\n * Visibility observer callback type\n */\nexport type VisibilityCallback = (isVisible: boolean, entry: IntersectionObserverEntry) => void;\n\n/**\n * Create an IntersectionObserver for visibility-based animation control\n *\n * @param element - Element to observe\n * @param callback - Called when visibility changes\n * @param threshold - Visibility threshold (0-1, default: 0.1)\n * @returns Cleanup function to disconnect observer\n */\nexport function createVisibilityObserver(\n element: Element,\n callback: VisibilityCallback,\n threshold: number = 0.1\n): () => void {\n const observer = new IntersectionObserver(\n (entries) => {\n for (const entry of entries) {\n callback(entry.isIntersecting, entry);\n }\n },\n { threshold }\n );\n\n observer.observe(element);\n\n return () => {\n observer.disconnect();\n };\n}\n\n/**\n * Create a ResizeObserver for responsive canvas sizing\n *\n * @param element - Element to observe\n * @param callback - Called on resize with new dimensions\n * @param debounceMs - Debounce delay in ms (default: 100)\n * @returns Cleanup function to disconnect observer\n */\nexport function createResizeObserver(\n element: Element,\n callback: (width: number, height: number, entry: ResizeObserverEntry) => void,\n debounceMs: number = 100\n): () => void {\n let timeout: ReturnType<typeof setTimeout> | null = null;\n\n const observer = new ResizeObserver((entries) => {\n if (timeout) {\n clearTimeout(timeout);\n }\n\n timeout = setTimeout(() => {\n const entry = entries[0];\n if (entry) {\n const { width, height } = entry.contentRect;\n callback(width, height, entry);\n }\n }, debounceMs);\n });\n\n observer.observe(element);\n\n return () => {\n if (timeout) {\n clearTimeout(timeout);\n }\n observer.disconnect();\n };\n}\n\n/**\n * Check if the user prefers reduced motion\n */\nexport function prefersReducedMotion(): boolean {\n if (typeof window === 'undefined') return false;\n return window.matchMedia('(prefers-reduced-motion: reduce)').matches;\n}\n\n/**\n * Create a listener for reduced motion preference changes\n *\n * @param callback - Called when preference changes\n * @returns Cleanup function to remove listener\n */\nexport function onReducedMotionChange(callback: (prefersReduced: boolean) => void): () => void {\n if (typeof window === 'undefined') {\n return () => {};\n }\n\n const mediaQuery = window.matchMedia('(prefers-reduced-motion: reduce)');\n\n const handler = (event: MediaQueryListEvent) => {\n callback(event.matches);\n };\n\n mediaQuery.addEventListener('change', handler);\n\n // Call immediately with current value\n callback(mediaQuery.matches);\n\n return () => {\n mediaQuery.removeEventListener('change', handler);\n };\n}\n\n/**\n * Check if the browser is in a low-power mode or has reduced capabilities\n */\nexport function isLowPowerMode(): boolean {\n // Check for battery API (if available)\n if (typeof navigator !== 'undefined' && 'getBattery' in navigator) {\n // Battery API is async, so this is a simplified check\n // Real implementation would need to be async\n return false;\n }\n\n // Fallback: check for hardware concurrency\n if (typeof navigator !== 'undefined' && navigator.hardwareConcurrency) {\n return navigator.hardwareConcurrency <= 2;\n }\n\n return false;\n}\n\n/**\n * Get recommended FPS based on device capabilities\n */\nexport function getRecommendedFPS(): number {\n if (prefersReducedMotion()) {\n return 0; // No animation\n }\n\n if (isLowPowerMode()) {\n return 15; // Low power mode\n }\n\n // Default for capable devices\n return 30;\n}\n\n/**\n * Performance monitoring for debugging\n */\nexport interface PerformanceMetrics {\n fps: number;\n frameTime: number;\n droppedFrames: number;\n}\n\n/**\n * Create a simple FPS counter\n */\nexport function createFPSCounter(): {\n tick: () => void;\n getFPS: () => number;\n getMetrics: () => PerformanceMetrics;\n reset: () => void;\n} {\n const frameTimes: number[] = [];\n const maxSamples = 60;\n let droppedFrames = 0;\n let lastFrameTime = performance.now();\n\n function tick(): void {\n const now = performance.now();\n const delta = now - lastFrameTime;\n lastFrameTime = now;\n\n frameTimes.push(now);\n\n if (frameTimes.length > maxSamples) {\n frameTimes.shift();\n }\n\n // Count dropped frames (assuming 60fps target, frames taking >20ms are \"dropped\")\n if (delta > 20) {\n droppedFrames += Math.floor(delta / 16.67) - 1;\n }\n }\n\n function getFPS(): number {\n if (frameTimes.length < 2) return 0;\n\n const oldest = frameTimes[0];\n const newest = frameTimes[frameTimes.length - 1];\n const elapsed = newest - oldest;\n\n if (elapsed === 0) return 0;\n\n return ((frameTimes.length - 1) / elapsed) * 1000;\n }\n\n function getMetrics(): PerformanceMetrics {\n const fps = getFPS();\n const frameTime = fps > 0 ? 1000 / fps : 0;\n\n return {\n fps: Math.round(fps * 10) / 10,\n frameTime: Math.round(frameTime * 100) / 100,\n droppedFrames,\n };\n }\n\n function reset(): void {\n frameTimes.length = 0;\n droppedFrames = 0;\n lastFrameTime = performance.now();\n }\n\n return { tick, getFPS, getMetrics, reset };\n}\n\n/**\n * Request idle callback with fallback\n */\nexport function requestIdleCallback(\n callback: () => void,\n options?: { timeout?: number }\n): number {\n // Use globalThis for cross-environment compatibility\n const global = globalThis as typeof globalThis & {\n requestIdleCallback?: typeof window.requestIdleCallback;\n setTimeout: typeof setTimeout;\n };\n\n if (typeof global.requestIdleCallback === 'function') {\n return global.requestIdleCallback(callback, options);\n }\n\n // Fallback using setTimeout\n return global.setTimeout(callback, options?.timeout ?? 1) as unknown as number;\n}\n\n/**\n * Cancel idle callback with fallback\n */\nexport function cancelIdleCallback(id: number): void {\n // Use globalThis for cross-environment compatibility\n const global = globalThis as typeof globalThis & {\n cancelIdleCallback?: typeof window.cancelIdleCallback;\n clearTimeout: typeof clearTimeout;\n };\n\n if (typeof global.cancelIdleCallback === 'function') {\n global.cancelIdleCallback(id);\n } else {\n global.clearTimeout(id);\n }\n}\n\n/**\n * Check if we're running in a browser environment\n */\nexport function isBrowser(): boolean {\n return typeof window !== 'undefined' && typeof document !== 'undefined';\n}\n\n/**\n * Check if Canvas is supported\n */\nexport function isCanvasSupported(): boolean {\n if (!isBrowser()) return false;\n\n const canvas = document.createElement('canvas');\n return !!(canvas.getContext && canvas.getContext('2d'));\n}\n\n/**\n * Check if OffscreenCanvas is supported\n */\nexport function isOffscreenCanvasSupported(): boolean {\n return typeof OffscreenCanvas !== 'undefined';\n}\n","/**\n * Gossamer - ASCII Visual Effects Library\n *\n * Threads of light. Delicate textures woven through your space.\n *\n * @packageDocumentation\n */\n\n// =============================================================================\n// Core Types\n// =============================================================================\n\n/**\n * Core configuration for ASCII rendering\n */\nexport interface GossamerConfig {\n /** Character set for ASCII rendering (light to dark) */\n characters?: string;\n /** Cell width in pixels */\n cellWidth?: number;\n /** Cell height in pixels */\n cellHeight?: number;\n /** Foreground color */\n color?: string;\n /** Background color (transparent if not set) */\n backgroundColor?: string;\n /** Font family for ASCII characters */\n fontFamily?: string;\n /** Enable animation loop */\n animate?: boolean;\n /** Target FPS for animation */\n fps?: number;\n}\n\n/**\n * Preset configuration for effects\n */\nexport interface PresetConfig {\n /** Preset display name */\n name: string;\n /** Preset description */\n description: string;\n /** Character set */\n characters: string;\n /** Pattern type */\n pattern: 'perlin' | 'waves' | 'static' | 'ripple' | 'fbm' | 'clouds' | 'plasma' | 'vortex' | 'matrix' | 'gradient' | 'diamond' | 'fractal';\n /** Pattern frequency */\n frequency: number;\n /** Pattern amplitude */\n amplitude: number;\n /** Animation speed */\n speed: number;\n /** Default opacity */\n opacity: number;\n}\n\n// =============================================================================\n// Constants\n// =============================================================================\n\n/**\n * Default character set ordered from light to dark\n */\nexport const DEFAULT_CHARACTERS = ' .:-=+*#%@';\n\n/**\n * Default configuration values\n */\nexport const DEFAULT_CONFIG: Required<GossamerConfig> = {\n characters: DEFAULT_CHARACTERS,\n cellWidth: 8,\n cellHeight: 12,\n color: '#ffffff',\n backgroundColor: '',\n fontFamily: 'monospace',\n animate: false,\n fps: 30,\n};\n\n// =============================================================================\n// Core Functions\n// =============================================================================\n\n/**\n * Calculate brightness from RGB values using luminance formula\n * Uses the standard luminance coefficients: 0.21 R + 0.72 G + 0.07 B\n */\nexport function calculateBrightness(r: number, g: number, b: number): number {\n return 0.21 * r + 0.72 * g + 0.07 * b;\n}\n\n/**\n * Map a brightness value (0-255) to an ASCII character\n */\nexport function brightnessToChar(\n brightness: number,\n characters: string = DEFAULT_CHARACTERS\n): string {\n const index = Math.floor((brightness / 255) * (characters.length - 1));\n return characters[Math.min(index, characters.length - 1)];\n}\n\n// =============================================================================\n// Module Exports\n// =============================================================================\n\n// Renderer\nexport { GossamerRenderer } from './renderer';\nexport type { RenderConfig } from './renderer';\n\n// Patterns\nexport {\n // Core noise functions\n perlinNoise2D,\n fbmNoise,\n staticNoise,\n seededNoise2D,\n // Pattern generators\n wavePattern,\n ripplePattern,\n cloudsPattern,\n plasmaPattern,\n vortexPattern,\n matrixPattern,\n gradientPattern,\n diamondPattern,\n fractalPattern,\n // Grid generation (legacy API)\n generateBrightnessGrid,\n gridToImageData,\n // Performance-optimized API\n createBrightnessBuffer,\n fillBrightnessBuffer,\n getBufferValue,\n // Config\n DEFAULT_PATTERN_CONFIG,\n} from './patterns';\nexport type { PatternConfig, PatternType, BrightnessBuffer } from './patterns';\n\n// Characters\nexport {\n CHARACTER_SETS,\n getCharacterSet,\n getCharacters,\n getCharacterSetNames,\n createCharacterSet,\n validateCharacterSet,\n invertCharacters,\n} from './characters';\nexport type { CharacterSet } from './characters';\n\n// Colors (Grove palette)\nexport {\n GROVE_GREEN,\n CREAM,\n BARK,\n STATUS,\n GROVE_COLORS,\n GLASS_SCHEMES,\n getGroveColor,\n getGlassScheme,\n getGroveColorNames,\n getGlassSchemeNames,\n hexToRgba,\n} from './colors';\nexport type { ColorDef, GroveColorName, GlassSchemeName } from './colors';\n\n// Animation\nexport {\n createAnimationLoop,\n throttle,\n debounce,\n calculateFPS,\n easings,\n} from './animation';\nexport type { AnimationState, AnimationOptions, EasingFunction } from './animation';\n\n// Canvas Utilities\nexport {\n createCanvas,\n getDevicePixelRatio,\n resizeCanvasToContainer,\n createOffscreenCanvas,\n clearCanvas,\n getImageData,\n optimizeContext,\n setupTextRendering,\n measureTextWidth,\n calculateCellSize,\n setBlendMode,\n} from './utils/canvas';\nexport type { CanvasOptions } from './utils/canvas';\n\n// Image Utilities\nexport {\n loadImage,\n loadAndScaleImage,\n imageToPixelData,\n extractBrightness,\n sampleImageCells,\n rgbToHex,\n hexToRgb,\n adjustBrightness,\n adjustContrast,\n invertColors,\n toGrayscale,\n} from './utils/image';\nexport type { ImageLoadOptions } from './utils/image';\n\n// Performance Utilities\nexport {\n createVisibilityObserver,\n createResizeObserver,\n prefersReducedMotion,\n onReducedMotionChange,\n isLowPowerMode,\n getRecommendedFPS,\n createFPSCounter,\n requestIdleCallback,\n cancelIdleCallback,\n isBrowser,\n isCanvasSupported,\n isOffscreenCanvasSupported,\n} from './utils/performance';\nexport type { VisibilityCallback, PerformanceMetrics } from './utils/performance';\n\n// =============================================================================\n// Version\n// =============================================================================\n\n/**\n * Gossamer version\n */\nexport const VERSION = '0.1.0';\n"],"names":["DEFAULT_CHARACTERS","calculateBrightness","charLen","idx"],"mappings":"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EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAI;AAAA,EAAK;AAAA,EAAI;AAAA,EAC9F;AAAA,EAAI;AAAA,EAAK;AAAA,EAAK;AAAA,EAAI;AAAA,EAAI;AAAA,EAAK;AAAA,EAAI;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAI;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAI;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAC9F;AAAA,EAAI;AAAA,EAAI;AAAA,EAAI;AAAA,EAAK;AAAA,EAAI;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAI;AAAA,EAAI;AAAA,EAAI;AAAA,EAAI;AAAA,EAAK;AAAA,EAAG;AAAA,EAAK;AAAA,EAAI;AAAA,EAAI;AAAA,EAAK;AAAA,EAAI;AAAA,EAAK;AAAA,EAAK;AAAA,EAC5F;AAAA,EAAI;AAAA,EAAI;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAI;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAG;AAAA,EAAI;AAAA,EAAI;AAAA,EAC7F;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAG;AAAA,EAAK;AAAA,EAAI;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAI;AAAA,EAAI;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAI;AAAA,EAAK;AAAA,EAAI;AAAA,EAAI;AAAA,EAC5F;AAAA,EAAI;AAAA,EAAK;AAAA,EAAK;AAAA,EAAI;AAAA,EAAI;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAG;AAAA,EAAI;AAAA,EAAK;AAAA,EAAK;AAAA,EAAI;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAC7F;AAAA,EAAK;AAAA,EAAI;AAAA,EAAK;AAAA,EAAG;AAAA,EAAK;AAAA,EAAI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"}