@pixerate/flair 0.0.0-stage → 0.1.0

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.
Files changed (53) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/LICENSE +21 -0
  3. package/README.md +254 -2
  4. package/dist/catalog/index.d.ts +74 -0
  5. package/dist/catalog/index.js +47 -0
  6. package/dist/catalog/index.js.map +1 -0
  7. package/dist/chunk-36DTNSHU.js +160 -0
  8. package/dist/chunk-36DTNSHU.js.map +1 -0
  9. package/dist/chunk-3FAUZOGL.js +331 -0
  10. package/dist/chunk-3FAUZOGL.js.map +1 -0
  11. package/dist/chunk-CFCLT2XL.js +1 -0
  12. package/dist/chunk-CFCLT2XL.js.map +1 -0
  13. package/dist/chunk-EHDJ3CPJ.js +327 -0
  14. package/dist/chunk-EHDJ3CPJ.js.map +1 -0
  15. package/dist/chunk-G5FNZDTA.js +536 -0
  16. package/dist/chunk-G5FNZDTA.js.map +1 -0
  17. package/dist/chunk-HKXOHRCD.js +763 -0
  18. package/dist/chunk-HKXOHRCD.js.map +1 -0
  19. package/dist/chunk-J55UBNAT.js +164 -0
  20. package/dist/chunk-J55UBNAT.js.map +1 -0
  21. package/dist/chunk-JWZCPMFG.js +2074 -0
  22. package/dist/chunk-JWZCPMFG.js.map +1 -0
  23. package/dist/chunk-MWVTQFV5.js +1894 -0
  24. package/dist/chunk-MWVTQFV5.js.map +1 -0
  25. package/dist/chunk-UQQNZSYL.js +594 -0
  26. package/dist/chunk-UQQNZSYL.js.map +1 -0
  27. package/dist/chunk-WMZQCUFJ.js +73 -0
  28. package/dist/chunk-WMZQCUFJ.js.map +1 -0
  29. package/dist/cli.d.ts +1 -0
  30. package/dist/cli.js +331 -0
  31. package/dist/cli.js.map +1 -0
  32. package/dist/clock-BhdXWH-n.d.ts +47 -0
  33. package/dist/controls-DdXMbovi.d.ts +97 -0
  34. package/dist/editor/index.d.ts +413 -0
  35. package/dist/editor/index.js +1009 -0
  36. package/dist/editor/index.js.map +1 -0
  37. package/dist/export-FEBPEEO7.js +22 -0
  38. package/dist/export-FEBPEEO7.js.map +1 -0
  39. package/dist/index.d.ts +1431 -0
  40. package/dist/index.js +1263 -0
  41. package/dist/index.js.map +1 -0
  42. package/dist/motion-D0TVv2CF.d.ts +148 -0
  43. package/dist/node.d.ts +24 -0
  44. package/dist/node.js +10 -0
  45. package/dist/node.js.map +1 -0
  46. package/dist/recorder-WJTWMEQN.js +10 -0
  47. package/dist/recorder-WJTWMEQN.js.map +1 -0
  48. package/dist/renderer-Oyynz-fs.d.ts +293 -0
  49. package/dist/types-CkKkavvB.d.ts +71 -0
  50. package/dist/vector/index.d.ts +83 -0
  51. package/dist/vector/index.js +39 -0
  52. package/dist/vector/index.js.map +1 -0
  53. package/package.json +96 -4
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/shader/renderer.ts","../src/shader/thumbnails.ts","../src/shader/frames.ts","../src/shader/gif.ts","../src/shader/standalone.ts","../src/shader/blend.ts","../src/time/noise.ts","../src/scene/effects.ts","../src/scene/check.ts","../src/scene/validate.ts","../src/scene/report.ts","../src/scene/behavior.ts","../src/scene/player.ts","../src/scene/standalone.ts"],"sourcesContent":["import { imageUrls, parseControls, type ControlDef, type ControlValue } from \"./controls.js\";\nimport {\n compileShader,\n createContext,\n drawFrame,\n resetGlCaches,\n type CompileError,\n type CompiledShader,\n} from \"./program.js\";\nimport { TextureCache, type ImageLoadError } from \"./textures.js\";\n\n/** Whether the latest source compiled, and if not, why. */\nexport interface CompileStatus {\n ok: boolean;\n errors: CompileError[];\n}\n\n/** What `onStats` reports: on play, pause, seek and restart, and twice a second while running. */\nexport interface RendererStats {\n /** `iTime`, in seconds. */\n time: number;\n /** Frames drawn per second over the last half second (0 while paused). */\n fps: number;\n playing: boolean;\n /** The drawing buffer's size in device pixels. */\n width: number;\n height: number;\n}\n\n/**\n * Runs one shader on a canvas: the editor's live preview. A source that does\n * not compile leaves the last working program on screen, so a typo never\n * blanks the preview; the errors are reported instead.\n *\n * The renderer owns its canvas (added to `host`, removed on dispose): a\n * canvas keeps its WebGL context for life, so reusing one after disposing\n * (a remount, hot reload) would get the released, lost context back.\n */\nexport class ShaderRenderer {\n readonly canvas: HTMLCanvasElement;\n private gl: WebGL2RenderingContext | null;\n private shader: CompiledShader | null = null;\n private textures: TextureCache | null = null;\n private controls: ControlDef[] = [];\n private values: Record<string, ControlValue> | undefined;\n private source = \"\";\n private raf = 0;\n private lastNow = 0;\n private frame = 0;\n private fpsFrames = 0;\n private fpsSince = 0;\n private resizeObserver: ResizeObserver;\n private mouse: [number, number, number, number] = [0, 0, 0, 0];\n private disposed = false;\n /** The latest source's status. */\n status: CompileStatus = { ok: true, errors: [] };\n /** `iTime`, in seconds. Use `seek` to change it. */\n time = 0;\n /** Playback speed: 1 is real time. */\n speed = 1;\n /** Device pixels per CSS pixel; lower renders faster. Use `setPixelRatio` to change it. */\n pixelRatio = Math.min(window.devicePixelRatio || 1, 2);\n playing = true;\n fps = 0;\n onStats?: (stats: RendererStats) => void;\n /** Called with `true` when the GL context is lost and `false` once it is restored and recompiled. */\n onContextLost?: (lost: boolean) => void;\n /** Called when an image control's URL cannot be loaded; the control shows black. */\n onImageError?: (error: ImageLoadError) => void;\n\n /** Creates a canvas in `host` (with `className`) and starts the animation loop. Size the canvas with CSS. */\n constructor(host: HTMLElement, className = \"\") {\n const canvas = document.createElement(\"canvas\");\n canvas.className = className;\n host.appendChild(canvas);\n this.canvas = canvas;\n this.gl = createContext(canvas, true);\n this.textures = this.gl && this.textureCache(this.gl);\n this.resizeObserver = new ResizeObserver(() => this.resize());\n this.resizeObserver.observe(canvas);\n canvas.addEventListener(\"webglcontextlost\", this.onLost);\n canvas.addEventListener(\"webglcontextrestored\", this.onRestored);\n canvas.addEventListener(\"pointerdown\", this.onPointerDown);\n canvas.addEventListener(\"pointermove\", this.onPointerMove);\n window.addEventListener(\"pointerup\", this.onPointerUp);\n this.resize();\n this.raf = requestAnimationFrame(this.tick);\n }\n\n /** False when the browser has no WebGL2. */\n get supported(): boolean {\n return this.gl !== null;\n }\n\n /** Compiles a new source; returns its status. Keeps the previous program when it fails. */\n setSource(source: string): CompileStatus {\n this.source = source;\n const controls = parseControls(source);\n if (!this.gl) {\n this.status = {\n ok: false,\n errors: [{ line: 0, message: \"WebGL2 is not available in this browser.\" }],\n };\n return this.status;\n }\n const result = compileShader(this.gl, source, controls);\n if (result.ok) {\n if (this.shader) this.gl.deleteProgram(this.shader.program);\n this.shader = result.shader;\n this.controls = controls;\n this.status = { ok: true, errors: [] };\n } else {\n this.status = { ok: false, errors: result.errors };\n }\n this.syncTextures();\n if (!this.playing) this.render();\n return this.status;\n }\n\n /**\n * Sets control values (see `controlValue`); a paused preview redraws.\n * Images load in the background and show once they arrive: await\n * `ready()` before a `capture` that needs them.\n */\n setValues(values: Record<string, ControlValue> | undefined) {\n this.values = values;\n this.syncTextures();\n if (!this.playing) this.render();\n }\n\n /**\n * Settles once the images the current controls show have loaded. Rejects\n * with an {@link ImageLoadError} when one cannot be (it shows black).\n */\n async ready(): Promise<void> {\n await this.textures?.ready(imageUrls(this.controls, this.values));\n }\n\n play() {\n this.playing = true;\n this.emit();\n }\n\n pause() {\n this.playing = false;\n this.emit();\n }\n\n /** Back to `iTime` 0 and frame 0. */\n restart() {\n this.time = 0;\n this.frame = 0;\n this.render();\n this.emit();\n }\n\n /** Jumps to `time` seconds (not below 0) and draws it. */\n seek(time: number) {\n this.time = Math.max(0, time);\n this.render();\n this.emit();\n }\n\n setPixelRatio(ratio: number) {\n this.pixelRatio = ratio;\n this.resize();\n }\n\n /**\n * Captures the current frame (optionally at another time) as a data URL\n * (JPEG unless `type` says PNG), at most `maxEdge` pixels on the long side\n * (default 1024). Playback time is left as it was. Null when nothing has\n * compiled yet.\n */\n capture(\n options: { time?: number; maxEdge?: number; type?: \"image/jpeg\" | \"image/png\" } = {},\n ): string | null {\n if (!this.gl || !this.shader) return null;\n const saved = this.time;\n if (options.time !== undefined) this.time = Math.max(0, options.time);\n this.render();\n const { width, height } = this.canvas;\n const scale = Math.min(1, (options.maxEdge ?? 1024) / Math.max(width, height));\n const out = document.createElement(\"canvas\");\n out.width = Math.max(1, Math.round(width * scale));\n out.height = Math.max(1, Math.round(height * scale));\n out.getContext(\"2d\")!.drawImage(this.canvas, 0, 0, out.width, out.height);\n this.time = saved;\n if (options.time !== undefined) this.render();\n return out.toDataURL(options.type ?? \"image/jpeg\", 0.85);\n }\n\n /** Stops the loop, releases the context and removes the canvas. The renderer cannot be used again. */\n dispose() {\n this.disposed = true;\n cancelAnimationFrame(this.raf);\n this.resizeObserver.disconnect();\n this.canvas.removeEventListener(\"webglcontextlost\", this.onLost);\n this.canvas.removeEventListener(\"webglcontextrestored\", this.onRestored);\n this.canvas.removeEventListener(\"pointerdown\", this.onPointerDown);\n this.canvas.removeEventListener(\"pointermove\", this.onPointerMove);\n window.removeEventListener(\"pointerup\", this.onPointerUp);\n if (this.gl && this.shader) this.gl.deleteProgram(this.shader.program);\n this.textures?.dispose();\n this.textures = null;\n // Free the context now rather than waiting for GC (browsers cap live contexts).\n this.gl?.getExtension(\"WEBGL_lose_context\")?.loseContext();\n this.gl = null;\n this.canvas.remove();\n }\n\n private resize() {\n // The layout size, not the bounding box: a rotated or scaled canvas keeps its own proportions.\n const w = Math.max(1, Math.round(this.canvas.clientWidth * this.pixelRatio));\n const h = Math.max(1, Math.round(this.canvas.clientHeight * this.pixelRatio));\n if (this.canvas.width !== w || this.canvas.height !== h) {\n this.canvas.width = w;\n this.canvas.height = h;\n this.render();\n }\n }\n\n private render(delta = 0) {\n if (!this.gl || !this.shader || this.gl.isContextLost()) return;\n drawFrame(\n this.gl,\n this.shader,\n this.controls,\n this.values,\n {\n width: this.canvas.width,\n height: this.canvas.height,\n time: this.time,\n delta,\n frame: this.frame,\n mouse: this.mouse,\n },\n this.textures ?? undefined,\n );\n }\n\n private textureCache(gl: WebGL2RenderingContext): TextureCache {\n return new TextureCache(gl, (_url, error) => {\n if (error) this.onImageError?.(error);\n else if (!this.playing) this.render();\n });\n }\n\n /** Starts loading the images now shown, and frees the ones no longer shown. */\n private syncTextures() {\n if (!this.textures) return;\n const urls = imageUrls(this.controls, this.values);\n this.textures.retain(urls);\n for (const url of urls) this.textures.request(url);\n }\n\n private tick = (now: number) => {\n if (this.disposed) return;\n this.raf = requestAnimationFrame(this.tick);\n const delta = this.lastNow ? Math.min((now - this.lastNow) / 1000, 0.1) : 0;\n this.lastNow = now;\n if (this.playing) {\n this.time += delta * this.speed;\n this.frame += 1;\n this.render(delta * this.speed);\n this.fpsFrames += 1;\n }\n if (now - this.fpsSince >= 500) {\n this.fps = this.playing\n ? Math.round((this.fpsFrames * 1000) / (now - this.fpsSince || 1))\n : 0;\n this.fpsFrames = 0;\n this.fpsSince = now;\n this.emit();\n }\n };\n\n private emit() {\n this.onStats?.({\n time: this.time,\n fps: this.fps,\n playing: this.playing,\n width: this.canvas.width,\n height: this.canvas.height,\n });\n }\n\n /** Pointer position in shader pixels (origin bottom-left, like gl_FragCoord). */\n private toPixels(e: PointerEvent): [number, number] {\n const rect = this.canvas.getBoundingClientRect();\n return [\n (e.clientX - rect.left) * (this.canvas.width / rect.width),\n (rect.bottom - e.clientY) * (this.canvas.height / rect.height),\n ];\n }\n\n private onPointerDown = (e: PointerEvent) => {\n const [x, y] = this.toPixels(e);\n this.mouse = [x, y, x, y];\n if (!this.playing) this.render();\n };\n\n private onPointerMove = (e: PointerEvent) => {\n if (this.mouse[2] <= 0 || e.buttons === 0) return;\n const [x, y] = this.toPixels(e);\n this.mouse = [x, y, this.mouse[2], this.mouse[3]];\n if (!this.playing) this.render();\n };\n\n private onPointerUp = () => {\n if (this.mouse[2] > 0)\n this.mouse = [this.mouse[0], this.mouse[1], -this.mouse[2], -Math.abs(this.mouse[3])];\n };\n\n private onLost = (e: Event) => {\n e.preventDefault();\n this.shader = null;\n this.textures?.dispose();\n this.textures = null;\n this.onContextLost?.(true);\n };\n\n private onRestored = () => {\n resetGlCaches();\n this.gl = createContext(this.canvas, true);\n this.textures = this.gl && this.textureCache(this.gl);\n this.setSource(this.source);\n this.onContextLost?.(false);\n };\n}\n","import { imageUrls, parseControls, type ControlDef, type ControlValue } from \"./controls.js\";\nimport {\n compileShader,\n createContext,\n drawFrame,\n resetGlCaches,\n type CompiledShader,\n} from \"./program.js\";\nimport { TextureCache } from \"./textures.js\";\n\n/** Controls a registered thumbnail. */\nexport interface ThumbnailHandle {\n /** Shows another source or other values. A new source is recompiled; new values only redraw. */\n update(source: string, values?: Record<string, ControlValue>): void;\n /** With reduced motion, a hovered thumbnail animates and the others hold a still frame. */\n setHovered(hovered: boolean): void;\n /** Stops drawing into the canvas and frees its program. */\n dispose(): void;\n}\n\nexport interface ThumbnailPoolOptions {\n /** Size of the shared render canvas (default 480 × 270). Thumbnails are drawn at most this large, then scaled. */\n renderWidth?: number;\n renderHeight?: number;\n /** Animation rate (default 30). */\n fps?: number;\n /** `iTime` of the still frame shown with reduced motion (default 2). */\n stillTime?: number;\n /** Hold still frames unless hovered (default: the `prefers-reduced-motion` media query). */\n reducedMotion?: boolean;\n}\n\ninterface Entry {\n canvas: HTMLCanvasElement;\n ctx: CanvasRenderingContext2D;\n source: string;\n values?: Record<string, ControlValue>;\n controls: ControlDef[];\n shader: CompiledShader | null;\n failed: boolean;\n dirty: boolean;\n visible: boolean;\n hovered: boolean;\n onStatus?: (ok: boolean) => void;\n}\n\n/**\n * Animated thumbnails from a single WebGL context. Browsers cap live WebGL\n * contexts (about 16), so a gallery cannot give every card its own: the pool\n * renders each visible thumbnail in turn on one hidden canvas and copies the\n * frame into the thumbnail's own 2D canvas, cropped to its aspect ratio like\n * `object-fit: cover`. Thumbnails off screen (by `IntersectionObserver`) cost\n * nothing, and programs compile once per source.\n *\n * Nothing is created until the first `register`.\n */\nexport class ThumbnailPool {\n private readonly renderWidth: number;\n private readonly renderHeight: number;\n private readonly interval: number;\n private readonly fps: number;\n private readonly stillTime: number;\n private readonly reducedMotion: boolean;\n private readonly entries = new Set<Entry>();\n private readonly byCanvas = new WeakMap<Element, Entry>();\n private observer: IntersectionObserver | null | undefined;\n private glCanvas: HTMLCanvasElement | null = null;\n private gl: WebGL2RenderingContext | null = null;\n private textures: TextureCache | null = null;\n private raf = 0;\n private last = 0;\n private start: number | null = null;\n\n constructor(options: ThumbnailPoolOptions = {}) {\n this.renderWidth = options.renderWidth ?? 480;\n this.renderHeight = options.renderHeight ?? 270;\n this.fps = options.fps ?? 30;\n this.interval = 1000 / this.fps;\n this.stillTime = options.stillTime ?? 2;\n this.reducedMotion =\n options.reducedMotion ??\n (typeof matchMedia !== \"undefined\" && matchMedia(\"(prefers-reduced-motion: reduce)\").matches);\n }\n\n /**\n * Starts drawing `source` into `canvas`, which should be sized with CSS; its\n * drawing buffer follows its CSS size and the device pixel ratio (up to 2).\n * `onStatus` hears whether the source compiled (and `false` without WebGL2).\n */\n register(\n canvas: HTMLCanvasElement,\n source: string,\n values?: Record<string, ControlValue>,\n onStatus?: (ok: boolean) => void,\n ): ThumbnailHandle {\n const observer = this.intersection();\n const entry: Entry = {\n canvas,\n ctx: canvas.getContext(\"2d\")!,\n source,\n values,\n controls: [],\n shader: null,\n failed: false,\n dirty: true,\n visible: observer === null,\n hovered: false,\n onStatus,\n };\n this.entries.add(entry);\n this.byCanvas.set(canvas, entry);\n observer?.observe(canvas);\n if (!this.context()) onStatus?.(false);\n this.schedule();\n return {\n update: (nextSource, nextValues) => {\n if (nextSource !== entry.source) {\n this.release(entry);\n entry.source = nextSource;\n entry.failed = false;\n }\n entry.values = nextValues;\n entry.dirty = true;\n this.retainTextures();\n this.schedule();\n },\n setHovered: (hovered) => {\n entry.hovered = hovered;\n entry.dirty = true;\n this.schedule();\n },\n dispose: () => {\n observer?.unobserve(canvas);\n this.entries.delete(entry);\n this.byCanvas.delete(canvas);\n this.release(entry);\n this.retainTextures();\n },\n };\n }\n\n /** The number of registered thumbnails. */\n get size(): number {\n return this.entries.size;\n }\n\n private intersection(): IntersectionObserver | null {\n if (this.observer !== undefined) return this.observer;\n this.observer =\n typeof IntersectionObserver === \"undefined\"\n ? null\n : new IntersectionObserver(\n (records) => {\n for (const r of records) {\n const entry = this.byCanvas.get(r.target);\n if (!entry) continue;\n entry.visible = r.isIntersecting;\n if (entry.visible) entry.dirty = true;\n }\n this.schedule();\n },\n { rootMargin: \"100px\" },\n );\n return this.observer;\n }\n\n private context(): WebGL2RenderingContext | null {\n if (this.gl && !this.gl.isContextLost()) return this.gl;\n const canvas = document.createElement(\"canvas\");\n canvas.width = this.renderWidth;\n canvas.height = this.renderHeight;\n canvas.addEventListener(\"webglcontextlost\", (e) => {\n e.preventDefault();\n for (const entry of this.entries) entry.shader = null;\n this.textures?.dispose();\n });\n canvas.addEventListener(\"webglcontextrestored\", () => {\n resetGlCaches();\n if (this.gl) this.textures = this.textureCache(this.gl);\n for (const entry of this.entries) entry.dirty = true;\n this.schedule();\n });\n resetGlCaches();\n this.glCanvas = canvas;\n this.gl = createContext(canvas);\n this.textures = this.gl && this.textureCache(this.gl);\n return this.gl;\n }\n\n private textureCache(gl: WebGL2RenderingContext): TextureCache {\n return new TextureCache(gl, (url) => {\n // A thumbnail showing the image redraws with it.\n for (const entry of this.entries) {\n if (imageUrls(entry.controls, entry.values).includes(url)) entry.dirty = true;\n }\n this.schedule();\n });\n }\n\n /** Frees the textures no thumbnail shows any more. */\n private retainTextures() {\n this.textures?.retain(\n [...this.entries].flatMap((entry) => imageUrls(entry.controls, entry.values)),\n );\n }\n\n private release(entry: Entry) {\n if (entry.shader) this.gl?.deleteProgram(entry.shader.program);\n entry.shader = null;\n }\n\n private compile(entry: Entry, gl: WebGL2RenderingContext) {\n entry.controls = parseControls(entry.source);\n const result = compileShader(gl, entry.source, entry.controls);\n entry.shader = result.ok ? result.shader : null;\n entry.failed = !result.ok;\n entry.onStatus?.(result.ok);\n }\n\n private renderEntry(entry: Entry, gl: WebGL2RenderingContext, time: number) {\n if (!entry.shader && !entry.failed) this.compile(entry, gl);\n if (!entry.shader) return;\n sizeCanvas(entry.canvas);\n // Fill the thumbnail the way `object-fit: cover` would, at its aspect ratio.\n const aspect = entry.canvas.width / entry.canvas.height;\n const w = Math.min(this.renderWidth, Math.round(this.renderHeight * aspect));\n const h = Math.min(this.renderHeight, Math.round(w / aspect));\n drawFrame(\n gl,\n entry.shader,\n entry.controls,\n entry.values,\n {\n width: w,\n height: h,\n time,\n delta: this.interval / 1000,\n frame: Math.floor(time * this.fps),\n mouse: [0, 0, 0, 0],\n },\n this.textures ?? undefined,\n );\n // The GL canvas's drawing buffer is valid until this task ends; copy it now.\n // WebGL draws from the bottom left, so the frame sits at the bottom of the canvas.\n entry.ctx.drawImage(\n this.glCanvas!,\n 0,\n this.renderHeight - h,\n w,\n h,\n 0,\n 0,\n entry.canvas.width,\n entry.canvas.height,\n );\n entry.dirty = false;\n }\n\n private schedule() {\n if (!this.raf && this.entries.size) this.raf = requestAnimationFrame(this.tick);\n }\n\n private tick = (now: number) => {\n this.raf = 0;\n const gl = this.context();\n if (!gl) return;\n this.start ??= now;\n const animate = now - this.last >= this.interval;\n const time = (now - this.start) / 1000;\n let keepGoing = false;\n for (const entry of this.entries) {\n if (!entry.visible) continue;\n const moving = !this.reducedMotion || entry.hovered;\n if (entry.dirty || (moving && animate)) {\n this.renderEntry(entry, gl, moving ? time : this.stillTime);\n }\n if (moving && entry.shader) keepGoing = true;\n }\n if (animate) this.last = now;\n if (keepGoing) this.schedule();\n };\n}\n\nfunction sizeCanvas(canvas: HTMLCanvasElement) {\n // The layout size, not the bounding box: a rotated or scaled canvas keeps its own proportions.\n const ratio = Math.min(window.devicePixelRatio || 1, 2);\n const w = Math.max(1, Math.round(canvas.clientWidth * ratio));\n const h = Math.max(1, Math.round(canvas.clientHeight * ratio));\n if (canvas.width !== w || canvas.height !== h) {\n canvas.width = w;\n canvas.height = h;\n }\n}\n\nlet shared: ThumbnailPool | null = null;\n\n/** The pool `registerThumbnail` uses, created on first use. */\nexport function sharedThumbnailPool(): ThumbnailPool {\n shared ??= new ThumbnailPool();\n return shared;\n}\n\n/** Registers a thumbnail with the shared pool. See {@link ThumbnailPool.register}. */\nexport function registerThumbnail(\n canvas: HTMLCanvasElement,\n source: string,\n values?: Record<string, ControlValue>,\n onStatus?: (ok: boolean) => void,\n): ThumbnailHandle {\n return sharedThumbnailPool().register(canvas, source, values, onStatus);\n}\n","import { imageUrls, parseControls, type ControlDef, type ControlValue } from \"./controls.js\";\nimport {\n compileShader,\n createContext,\n drawFrame,\n ShaderCompileError,\n type CompiledShader,\n} from \"./program.js\";\nimport { TextureCache } from \"./textures.js\";\n\nexport interface ShaderFramesOptions {\n source: string;\n values?: Record<string, ControlValue>;\n width: number;\n height: number;\n /** Draw on this canvas instead of a new, detached one. It is resized to `width` × `height`. */\n canvas?: HTMLCanvasElement;\n}\n\nexport interface RenderOptions {\n /** `iFrame` (default: the number of frames rendered so far). */\n frame?: number;\n /** `iTimeDelta` in seconds (default: the time since the previous `render`, else 0). */\n delta?: number;\n /** `iMouse` (default: all zero, as on a page nobody has touched). */\n mouse?: [number, number, number, number];\n}\n\n/**\n * Renders a shader at exact times you choose, off screen. There is no\n * animation loop and no clock: frame `n` of a recording at `fps` is\n * `render(start + n / fps)`, so the output is the same on any machine. It\n * suits recorders, video pipelines and anything else stepped by its own\n * clock. The constructor throws a {@link ShaderCompileError} when the source\n * does not compile.\n *\n * Image controls load in the background: `await frames.ready()` before the\n * first `render`, or the frames show black where the images go.\n */\nexport class ShaderFrames {\n readonly canvas: HTMLCanvasElement;\n readonly width: number;\n readonly height: number;\n readonly controls: ControlDef[];\n private gl: WebGL2RenderingContext | null;\n private shader: CompiledShader;\n private textures: TextureCache;\n private values: Record<string, ControlValue> | undefined;\n private rendered = 0;\n private lastTime: number | null = null;\n private pixels: Uint8Array;\n\n constructor(options: ShaderFramesOptions) {\n const { source, values, width, height } = options;\n this.width = Math.max(1, Math.round(width));\n this.height = Math.max(1, Math.round(height));\n this.canvas = options.canvas ?? document.createElement(\"canvas\");\n this.canvas.width = this.width;\n this.canvas.height = this.height;\n this.values = values;\n const gl = createContext(this.canvas, true);\n if (!gl) throw new Error(\"WebGL2 is not available in this browser.\");\n this.gl = gl;\n this.controls = parseControls(source);\n const compiled = compileShader(gl, source, this.controls);\n if (!compiled.ok) {\n this.dispose();\n throw new ShaderCompileError(compiled.errors);\n }\n this.shader = compiled.shader;\n this.textures = new TextureCache(gl);\n this.syncTextures();\n this.pixels = new Uint8Array(this.width * this.height * 4);\n }\n\n /** Changes control values for the frames that follow. */\n setValues(values: Record<string, ControlValue> | undefined) {\n this.values = values;\n this.syncTextures();\n }\n\n /**\n * Settles once every image the controls show has loaded. Rejects with an\n * {@link ImageLoadError} when one cannot be.\n */\n async ready(): Promise<void> {\n await this.textures.ready(imageUrls(this.controls, this.values));\n }\n\n /** Draws the frame at `time` seconds onto `canvas`. */\n render(time: number, options: RenderOptions = {}) {\n const gl = this.context();\n const delta = options.delta ?? (this.lastTime === null ? 0 : time - this.lastTime);\n drawFrame(\n gl,\n this.shader,\n this.controls,\n this.values,\n {\n width: this.width,\n height: this.height,\n time,\n delta,\n frame: options.frame ?? this.rendered,\n mouse: options.mouse ?? [0, 0, 0, 0],\n },\n this.textures,\n );\n this.rendered += 1;\n this.lastTime = time;\n }\n\n /**\n * The last rendered frame as RGBA bytes, rows top down (as in `ImageData`;\n * WebGL itself reads bottom up). Pass `out` to reuse a buffer of\n * `width * height * 4` bytes.\n */\n readPixels(out?: Uint8Array | Uint8ClampedArray): Uint8Array | Uint8ClampedArray {\n const gl = this.context();\n const { width, height } = this;\n const target = out ?? new Uint8Array(width * height * 4);\n if (target.length !== width * height * 4) {\n throw new RangeError(`readPixels needs a buffer of ${width * height * 4} bytes.`);\n }\n gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, this.pixels);\n const row = width * 4;\n for (let y = 0; y < height; y++) {\n target.set(this.pixels.subarray((height - 1 - y) * row, (height - y) * row), y * row);\n }\n return target;\n }\n\n /** Releases the GL context now rather than at garbage collection (browsers cap live contexts). */\n dispose() {\n if (!this.gl) return;\n if (this.shader) this.gl.deleteProgram(this.shader.program);\n this.textures?.dispose();\n this.gl.getExtension(\"WEBGL_lose_context\")?.loseContext();\n this.gl = null;\n }\n\n private syncTextures() {\n const urls = imageUrls(this.controls, this.values);\n this.textures.retain(urls);\n for (const url of urls) this.textures.request(url);\n }\n\n private context(): WebGL2RenderingContext {\n if (!this.gl) throw new Error(\"These frames have been disposed.\");\n if (this.gl.isContextLost()) throw new Error(\"The graphics context was lost.\");\n return this.gl;\n }\n}\n","// gifenc ships without types. The reference (not an import) brings them along when a host\n// type-checks these sources through the `workspace` condition.\n// eslint-disable-next-line @typescript-eslint/triple-slash-reference\n/// <reference path=\"./gifenc.d.ts\" />\nimport type { ControlValue } from \"./controls.js\";\nimport { ShaderFrames } from \"./frames.js\";\n\nexport interface GifOptions {\n source: string;\n values?: Record<string, ControlValue>;\n width: number;\n height: number;\n /** Frames per second. GIF delays are whole hundredths of a second, so 10, 20, 25 and 50 play back exactly. */\n fps: number;\n /** Seconds of animation to record. */\n duration: number;\n /** `iTime` of the first frame (default 0). */\n start?: number;\n /** Called after each frame with the frames done and the total. */\n onProgress?: (done: number, total: number) => void;\n /** Aborting rejects with an `AbortError` `DOMException`. */\n signal?: AbortSignal;\n}\n\n/** Lets the page repaint between frames so progress shows and Cancel works. */\nconst yieldToBrowser = () => new Promise<void>((resolve) => setTimeout(resolve, 0));\n\n/**\n * Records a shader as an animated GIF that loops forever. Frames are rendered\n * off screen at exact time steps (`start + i / fps`), so the result is smooth\n * whatever the page's frame rate, and nothing on screen is disturbed. Each\n * frame gets its own 256-colour palette. The encoder,\n * [gifenc](https://github.com/mattdesl/gifenc), is loaded on first use.\n *\n * Image controls are loaded before the first frame. Rejects with a\n * `ShaderCompileError` when the source does not compile, and an\n * `ImageLoadError` when an image cannot be loaded.\n */\nexport async function recordGif(options: GifOptions): Promise<Blob> {\n const { source, values, width, height, fps, duration, start = 0, onProgress, signal } = options;\n const { GIFEncoder, quantize, applyPalette } = await import(\"gifenc\");\n\n const frames = new ShaderFrames({ source, values, width, height });\n try {\n await frames.ready();\n const total = Math.max(1, Math.round(duration * fps));\n const delay = 1000 / fps;\n const rgba = new Uint8Array(frames.width * frames.height * 4);\n const gif = GIFEncoder();\n\n for (let i = 0; i < total; i++) {\n if (signal?.aborted) throw new DOMException(\"Cancelled\", \"AbortError\");\n frames.render(start + i / fps, { frame: i, delta: 1 / fps });\n frames.readPixels(rgba);\n const palette = quantize(rgba, 256);\n gif.writeFrame(applyPalette(rgba, palette), frames.width, frames.height, {\n palette,\n delay,\n ...(i === 0 ? { repeat: 0 } : {}),\n });\n onProgress?.(i + 1, total);\n if (i % 2 === 1) await yieldToBrowser();\n }\n\n gif.finish();\n return new Blob([gif.bytes()], { type: \"image/gif\" });\n } finally {\n frames.dispose();\n }\n}\n","import { controlValue, parseControls, type ControlValue } from \"./controls.js\";\nimport { VERTEX_SOURCE, wrapSource } from \"./program.js\";\nimport { SVG_EDGE } from \"./textures.js\";\n\nconst escapeHtml = (s: string) =>\n s.replace(/[&<>\"]/g, (c) => ({ \"&\": \"&amp;\", \"<\": \"&lt;\", \">\": \"&gt;\", '\"': \"&quot;\" })[c]!);\n\n/** JSON that is safe inside a `<script>`: a `</script>` or `<!--` in a shader comment cannot end it. */\nconst scriptJson = (value: unknown) => JSON.stringify(value).replace(/</g, \"\\\\u003c\");\n\nexport interface StandaloneOptions {\n /** The comment at the top of the script, saying where the page came from. */\n credit?: string;\n}\n\n/**\n * A self-contained HTML page that runs the shader full-window, with the\n * control values baked in. It has no dependencies and opens from disk. Like\n * the live preview, it feeds `iMouse` from pointer drags and caps the pixel\n * ratio at 2.\n *\n * Images are loaded by URL when the page opens: a `data:` URL travels with\n * the page, an `https:` one needs the network and CORS, and a `blob:` one\n * only lives as long as the page that made it. SVGs are sized to\n * {@link SVG_EDGE} pixels before they are decoded, as `loadImage` does.\n */\nexport function standaloneHtml(\n title: string,\n source: string,\n values?: Record<string, ControlValue>,\n options: StandaloneOptions = {},\n): string {\n const controls = parseControls(source).map((c) => ({\n name: c.name,\n type: c.type,\n value: controlValue(c, values),\n ...(c.texture ? { texture: c.texture } : {}),\n }));\n const credit = (options.credit ?? \"Exported with Flair.\").replace(/\\n/g, \" \");\n return `<!doctype html>\n<html lang=\"en\">\n<head>\n<meta charset=\"utf-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n<title>${escapeHtml(title)}</title>\n<style>html,body{margin:0;height:100%;background:#000}canvas{display:block;width:100%;height:100%}</style>\n</head>\n<body>\n<canvas id=\"c\"></canvas>\n<script>\n// ${credit.replace(/</g, \"\\\\u003c\")} Shadertoy-style fragment shader on WebGL2.\nconst VERTEX = ${scriptJson(VERTEX_SOURCE)};\nconst FRAGMENT = ${scriptJson(wrapSource(source))};\nconst CONTROLS = ${scriptJson(controls)};\nconst canvas = document.getElementById(\"c\");\nconst gl = canvas.getContext(\"webgl2\");\nif (!gl) document.body.textContent = \"WebGL2 is not available.\";\nfunction compile(type, src) {\n const s = gl.createShader(type);\n gl.shaderSource(s, src);\n gl.compileShader(s);\n if (!gl.getShaderParameter(s, gl.COMPILE_STATUS)) throw new Error(gl.getShaderInfoLog(s));\n return s;\n}\nconst program = gl.createProgram();\ngl.attachShader(program, compile(gl.VERTEX_SHADER, VERTEX));\ngl.attachShader(program, compile(gl.FRAGMENT_SHADER, FRAGMENT));\ngl.linkProgram(program);\ngl.useProgram(program);\nconst u = (n) => gl.getUniformLocation(program, n);\nlet unit = 0;\n// An SVG decodes at its own, often icon, size: give it ${SVG_EDGE} px on its long edge (and a\n// viewBox, so the drawing scales) to keep it sharp.\nasync function sizedSvg(url) {\n const doc = new DOMParser().parseFromString(await (await fetch(url)).text(), \"image/svg+xml\");\n const svg = doc.documentElement;\n const len = (n) => { const m = (svg.getAttribute(n) || \"\").trim().match(/^([\\\\d.]+)(px)?$/); return m && +m[1] > 0 ? +m[1] : 0; };\n const box = (svg.getAttribute(\"viewBox\") || \"\").trim().split(/[\\\\s,]+/).map(Number);\n const hasBox = box.length === 4 && box[2] > 0 && box[3] > 0;\n const w = len(\"width\") || (hasBox ? box[2] : 300), h = len(\"height\") || (hasBox ? box[3] : 150);\n const scale = ${SVG_EDGE} / Math.max(w, h);\n if (!hasBox) svg.setAttribute(\"viewBox\", \"0 0 \" + w + \" \" + h);\n svg.setAttribute(\"width\", Math.max(1, Math.round(w * scale)));\n svg.setAttribute(\"height\", Math.max(1, Math.round(h * scale)));\n return URL.createObjectURL(new Blob([new XMLSerializer().serializeToString(svg)], { type: \"image/svg+xml\" }));\n}\nfunction image(loc, url, texture) {\n const i = unit++, t = gl.createTexture();\n const bind = () => { gl.activeTexture(gl.TEXTURE0 + i); gl.bindTexture(gl.TEXTURE_2D, t); };\n const filter = { mipmap: gl.LINEAR_MIPMAP_LINEAR, linear: gl.LINEAR, nearest: gl.NEAREST }[texture.filter];\n const wrap = { repeat: gl.REPEAT, clamp: gl.CLAMP_TO_EDGE, mirror: gl.MIRRORED_REPEAT }[texture.wrap];\n bind();\n gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array([0, 0, 0, 255]));\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, filter);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, texture.filter === \"nearest\" ? gl.NEAREST : gl.LINEAR);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, wrap);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, wrap);\n gl.uniform1i(loc, i);\n if (!url) return;\n const img = new Image();\n if (!/^(data|blob):/i.test(url)) img.crossOrigin = \"anonymous\";\n img.onload = () => {\n bind();\n gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);\n gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, img);\n gl.generateMipmap(gl.TEXTURE_2D);\n };\n if (/^data:image\\\\/svg\\\\+xml[;,]/i.test(url) || /^(?!data:)[^?#]*\\\\.svg([?#]|$)/i.test(url)) {\n sizedSvg(url).then((src) => { img.src = src; }, () => {});\n } else img.src = url;\n}\nfor (const c of CONTROLS) {\n const loc = u(c.name);\n const v = c.value;\n if (c.type === \"float\") gl.uniform1f(loc, v);\n else if (c.type === \"int\" || c.type === \"bool\") gl.uniform1i(loc, Number(v));\n else if (c.type === \"sampler2D\") image(loc, v, c.texture);\n else gl[\"uniform\" + v.length + \"fv\"](loc, v);\n}\nlet mouse = [0, 0, 0, 0];\nconst px = (e) => { const r = canvas.getBoundingClientRect(); return [(e.clientX - r.left) * canvas.width / r.width, (r.bottom - e.clientY) * canvas.height / r.height]; };\ncanvas.addEventListener(\"pointerdown\", (e) => { const [x, y] = px(e); mouse = [x, y, x, y]; });\ncanvas.addEventListener(\"pointermove\", (e) => { if (e.buttons && mouse[2] > 0) { const [x, y] = px(e); mouse = [x, y, mouse[2], mouse[3]]; } });\naddEventListener(\"pointerup\", () => { if (mouse[2] > 0) mouse = [mouse[0], mouse[1], -mouse[2], -Math.abs(mouse[3])]; });\nlet start = performance.now(), last = start, frame = 0;\nfunction draw(now) {\n const dpr = Math.min(devicePixelRatio || 1, 2);\n const w = Math.round(canvas.clientWidth * dpr), h = Math.round(canvas.clientHeight * dpr);\n if (canvas.width !== w || canvas.height !== h) { canvas.width = w; canvas.height = h; }\n gl.viewport(0, 0, w, h);\n gl.uniform3f(u(\"iResolution\"), w, h, 1);\n gl.uniform1f(u(\"iTime\"), (now - start) / 1000);\n gl.uniform1f(u(\"iTimeDelta\"), (now - last) / 1000);\n gl.uniform1i(u(\"iFrame\"), frame++);\n gl.uniform4f(u(\"iMouse\"), mouse[0], mouse[1], mouse[2], mouse[3]);\n gl.drawArrays(gl.TRIANGLES, 0, 3);\n last = now;\n requestAnimationFrame(draw);\n}\nrequestAnimationFrame(draw);\n</script>\n</body>\n</html>\n`;\n}\n","/**\n * 38 Layer Blend Modes for Compositing and WebGL Shader Generation.\n * Mathematically matching Adobe After Effects & EffectCraft blending standards.\n */\n\nexport type BlendMode =\n | 'normal'\n | 'dissolve'\n | 'dancingDissolve'\n | 'darken'\n | 'multiply'\n | 'colorBurn'\n | 'classicColorBurn'\n | 'linearBurn'\n | 'darkerColor'\n | 'add'\n | 'lighten'\n | 'screen'\n | 'colorDodge'\n | 'classicColorDodge'\n | 'linearDodge'\n | 'lighterColor'\n | 'overlay'\n | 'softLight'\n | 'hardLight'\n | 'linearLight'\n | 'vividLight'\n | 'pinLight'\n | 'hardMix'\n | 'difference'\n | 'classicDifference'\n | 'exclusion'\n | 'subtract'\n | 'divide'\n | 'hue'\n | 'saturation'\n | 'color'\n | 'luminosity'\n | 'stencilAlpha'\n | 'stencilLuma'\n | 'silhouetteAlpha'\n | 'silhouetteLuma'\n | 'alphaAdd'\n | 'luminescentPremul';\n\nexport const ALL_BLEND_MODES: readonly BlendMode[] = [\n 'normal',\n 'dissolve',\n 'dancingDissolve',\n 'darken',\n 'multiply',\n 'colorBurn',\n 'classicColorBurn',\n 'linearBurn',\n 'darkerColor',\n 'add',\n 'lighten',\n 'screen',\n 'colorDodge',\n 'classicColorDodge',\n 'linearDodge',\n 'lighterColor',\n 'overlay',\n 'softLight',\n 'hardLight',\n 'linearLight',\n 'vividLight',\n 'pinLight',\n 'hardMix',\n 'difference',\n 'classicDifference',\n 'exclusion',\n 'subtract',\n 'divide',\n 'hue',\n 'saturation',\n 'color',\n 'luminosity',\n 'stencilAlpha',\n 'stencilLuma',\n 'silhouetteAlpha',\n 'silhouetteLuma',\n 'alphaAdd',\n 'luminescentPremul',\n];\n\nexport type ColorRgba = [number, number, number, number];\n\nfunction lum(r: number, g: number, b: number): number {\n return 0.3 * r + 0.59 * g + 0.11 * b;\n}\n\nfunction sat(r: number, g: number, b: number): number {\n return Math.max(r, g, b) - Math.min(r, g, b);\n}\n\nfunction clipColor(r: number, g: number, b: number): [number, number, number] {\n const l = lum(r, g, b);\n const n = Math.min(r, g, b);\n const x = Math.max(r, g, b);\n let cr = r;\n let cg = g;\n let cb = b;\n if (n < 0.0) {\n const denom = Math.max(1e-9, l - n);\n cr = l + ((cr - l) * l) / denom;\n cg = l + ((cg - l) * l) / denom;\n cb = l + ((cb - l) * l) / denom;\n }\n if (x > 1.0) {\n const denom = Math.max(1e-9, x - l);\n cr = l + ((cr - l) * (1.0 - l)) / denom;\n cg = l + ((cg - l) * (1.0 - l)) / denom;\n cb = l + ((cb - l) * (1.0 - l)) / denom;\n }\n return [cr, cg, cb];\n}\n\nfunction setLum(r: number, g: number, b: number, l: number): [number, number, number] {\n const d = l - lum(r, g, b);\n return clipColor(r + d, g + d, b + d);\n}\n\nfunction setSat(r: number, g: number, b: number, s: number): [number, number, number] {\n const mx = Math.max(r, g, b);\n const mn = Math.min(r, g, b);\n if (mx - mn <= 1e-9) return [0, 0, 0];\n const f = (v: number) => ((v - mn) * s) / (mx - mn);\n return [f(r), f(g), f(b)];\n}\n\nfunction burn(cb: number, cs: number): number {\n if (cb >= 1.0) return 1.0;\n if (cs <= 0.0) return 0.0;\n return 1.0 - Math.min(1.0, (1.0 - cb) / cs);\n}\n\nfunction dodge(cb: number, cs: number): number {\n if (cb <= 0.0) return 0.0;\n if (cs >= 1.0) return 1.0;\n return Math.min(1.0, cb / (1.0 - cs));\n}\n\nfunction hardLight(cb: number, cs: number): number {\n if (cs <= 0.5) {\n return cb * 2.0 * cs;\n }\n const s = 2.0 * cs - 1.0;\n return cb + s - cb * s;\n}\n\nfunction softLight(cb: number, cs: number): number {\n if (cs <= 0.5) {\n return cb - (1.0 - 2.0 * cs) * cb * (1.0 - cb);\n }\n const d = cb <= 0.25 ? ((16.0 * cb - 12.0) * cb + 4.0) * cb : Math.sqrt(Math.max(0.0, cb));\n return cb + (2.0 * cs - 1.0) * (d - cb);\n}\n\nfunction vividLight(cb: number, cs: number): number {\n return cs <= 0.5 ? burn(cb, 2.0 * cs) : dodge(cb, 2.0 * (cs - 0.5));\n}\n\nfunction separableBlend(mode: BlendMode, cb: number, cs: number): number {\n switch (mode) {\n case 'darken':\n return Math.min(cb, cs);\n case 'multiply':\n return cb * cs;\n case 'colorBurn':\n return burn(cb, cs);\n case 'classicColorBurn':\n return cs <= 0.0 ? 0.0 : 1.0 - (1.0 - cb) / cs;\n case 'linearBurn':\n return Math.max(0.0, cb + cs - 1.0);\n case 'add':\n case 'linearDodge':\n return cb + cs;\n case 'lighten':\n return Math.max(cb, cs);\n case 'screen':\n return cb + cs - cb * cs;\n case 'colorDodge':\n return dodge(cb, cs);\n case 'classicColorDodge':\n return cs >= 1.0 ? 1.0 : Math.min(1.0, cb / (1.0 - cs));\n case 'overlay':\n return hardLight(cs, cb);\n case 'softLight':\n return softLight(cb, cs);\n case 'hardLight':\n return hardLight(cb, cs);\n case 'linearLight':\n return Math.min(1.0, Math.max(0.0, cb + 2.0 * cs - 1.0));\n case 'vividLight':\n return vividLight(cb, cs);\n case 'pinLight':\n return cs <= 0.5 ? Math.min(cb, 2.0 * cs) : Math.max(cb, 2.0 * cs - 1.0);\n case 'hardMix':\n return cb + cs >= 1.0 ? 1.0 : 0.0;\n case 'difference':\n case 'classicDifference':\n return Math.abs(cb - cs);\n case 'exclusion':\n return cb + cs - 2.0 * cb * cs;\n case 'subtract':\n return Math.max(0.0, cb - cs);\n case 'divide':\n return cs <= 0.0 ? (cb > 0.0 ? 1.0 : 0.0) : cb / cs;\n default:\n return cs;\n }\n}\n\n/**\n * Evaluates CPU compositing of premultiplied RGBA source onto premultiplied RGBA destination.\n *\n * @param mode Blend mode to apply.\n * @param dst Destination premultiplied RGBA [r, g, b, a] in [0, 1].\n * @param src Source premultiplied RGBA [r, g, b, a] in [0, 1].\n * @param noise Per-pixel noise parameter in [0, 1] for Dissolve modes (default: 0).\n */\nexport function blendRgba(\n mode: BlendMode,\n dst: ColorRgba,\n src: ColorRgba,\n noise = 0,\n): ColorRgba {\n const sa = src[3];\n const da = dst[3];\n\n switch (mode) {\n case 'normal': {\n const k = 1.0 - sa;\n return [src[0] + dst[0] * k, src[1] + dst[1] * k, src[2] + dst[2] * k, sa + da * k];\n }\n case 'dissolve':\n case 'dancingDissolve': {\n if (sa <= 0.0 || noise >= sa) return [...dst];\n const inv = 1.0 / sa;\n return [src[0] * inv, src[1] * inv, src[2] * inv, 1.0];\n }\n case 'stencilAlpha':\n return [dst[0] * sa, dst[1] * sa, dst[2] * sa, dst[3] * sa];\n case 'silhouetteAlpha': {\n const k = 1.0 - sa;\n return [dst[0] * k, dst[1] * k, dst[2] * k, dst[3] * k];\n }\n case 'stencilLuma':\n case 'silhouetteLuma': {\n const l = lum(src[0], src[1], src[2]);\n const k = mode === 'stencilLuma' ? l : 1.0 - l;\n return [dst[0] * k, dst[1] * k, dst[2] * k, dst[3] * k];\n }\n case 'alphaAdd': {\n const k = 1.0 - sa;\n return [src[0] + dst[0] * k, src[1] + dst[1] * k, src[2] + dst[2] * k, Math.min(1.0, sa + da)];\n }\n case 'luminescentPremul': {\n const k = 1.0 - sa;\n return [src[0] + dst[0] * k, src[1] + dst[1] * k, src[2] + dst[2] * k, sa + da - sa * da];\n }\n }\n\n if (sa <= 0.0) return [...dst];\n if (da <= 0.0) return [...src];\n\n const cs: [number, number, number] = [src[0] / sa, src[1] / sa, src[2] / sa];\n const cb: [number, number, number] = [dst[0] / da, dst[1] / da, dst[2] / da];\n\n let b: [number, number, number];\n switch (mode) {\n case 'hue':\n b = setLum(...setSat(cs[0], cs[1], cs[2], sat(...cb)), lum(...cb));\n break;\n case 'saturation':\n b = setLum(...setSat(cb[0], cb[1], cb[2], sat(...cs)), lum(...cb));\n break;\n case 'color':\n b = setLum(cs[0], cs[1], cs[2], lum(...cb));\n break;\n case 'luminosity':\n b = setLum(cb[0], cb[1], cb[2], lum(...cs));\n break;\n case 'darkerColor':\n b = lum(...cs) < lum(...cb) ? cs : cb;\n break;\n case 'lighterColor':\n b = lum(...cs) > lum(...cb) ? cs : cb;\n break;\n default:\n b = [\n separableBlend(mode, cb[0], cs[0]),\n separableBlend(mode, cb[1], cs[1]),\n separableBlend(mode, cb[2], cs[2]),\n ];\n break;\n }\n\n const ao = sa + da - sa * da;\n return [\n (1.0 - da) * src[0] + (1.0 - sa) * dst[0] + sa * da * b[0],\n (1.0 - da) * src[1] + (1.0 - sa) * dst[1] + sa * da * b[1],\n (1.0 - da) * src[2] + (1.0 - sa) * dst[2] + sa * da * b[2],\n ao,\n ];\n}\n\n/**\n * Returns a self-contained GLSL shader function for blending two vec4 colors.\n * Useful for runtime GPU compositing across multiple shader layers or passes.\n */\nexport function getGlslBlendFunction(mode: BlendMode): string {\n switch (mode) {\n case 'multiply':\n return `vec4 blend(vec4 dst, vec4 src) {\n return vec4(src.rgb * dst.rgb * src.a + dst.rgb * (1.0 - src.a), src.a + dst.a * (1.0 - src.a));\n}`;\n case 'screen':\n return `vec4 blend(vec4 dst, vec4 src) {\n vec3 res = src.rgb + dst.rgb - src.rgb * dst.rgb;\n return vec4(mix(dst.rgb, res, src.a), src.a + dst.a * (1.0 - src.a));\n}`;\n case 'add':\n case 'linearDodge':\n return `vec4 blend(vec4 dst, vec4 src) {\n return vec4(min(vec3(1.0), dst.rgb + src.rgb * src.a), min(1.0, dst.a + src.a));\n}`;\n case 'overlay':\n return `vec4 blend(vec4 dst, vec4 src) {\n vec3 res = mix(2.0 * dst.rgb * src.rgb, 1.0 - 2.0 * (1.0 - dst.rgb) * (1.0 - src.rgb), step(vec3(0.5), dst.rgb));\n return vec4(mix(dst.rgb, res, src.a), src.a + dst.a * (1.0 - src.a));\n}`;\n case 'difference':\n return `vec4 blend(vec4 dst, vec4 src) {\n return vec4(mix(dst.rgb, abs(dst.rgb - src.rgb), src.a), src.a + dst.a * (1.0 - src.a));\n}`;\n case 'normal':\n default:\n return `vec4 blend(vec4 dst, vec4 src) {\n return src + dst * (1.0 - src.a);\n}`;\n }\n}\n","/**\n * Deterministic pseudo-random number generator, hash mixing, and C2-continuous smooth value noise.\n * Based on 64-bit SplitMix64 mixing and quintic Hermite interpolation.\n *\n * Produces deterministic, platform-independent outputs for wiggle, organic turbulence, and camera shake.\n */\n\n// BigInt constants for SplitMix64\nconst GOLDEN_GAMMA = 0x9e3779b97f4a7c15n;\nconst MULT1 = 0xbf58476d1ce4e5b9n;\nconst MULT2 = 0x94d049bb133111ebn;\nconst MASK64 = 0xffffffffffffffffn;\nconst BASE_MIX = 0x2545f4914f6cdd1dn;\nconst POW2_53 = 9007199254740992; // 2^53\n\n/**\n * SplitMix64 mixing finalizer: maps any 64-bit integer to a high-quality pseudorandom 64-bit integer.\n */\nexport function hash64(x: bigint): bigint {\n let v = (x + GOLDEN_GAMMA) & MASK64;\n v = ((v ^ (v >> 30n)) * MULT1) & MASK64;\n v = ((v ^ (v >> 27n)) * MULT2) & MASK64;\n return (v ^ (v >> 31n)) & MASK64;\n}\n\n/**\n * Combines multiple seed numbers/bigints into a single mixed 64-bit seed.\n */\nexport function mixSeeds(parts: (bigint | number)[]): bigint {\n let h = BASE_MIX;\n for (const p of parts) {\n const val = typeof p === 'bigint' ? p : BigInt(Math.floor(p));\n h = hash64(h ^ hash64(val & MASK64));\n }\n return h;\n}\n\n/**\n * Maps a 64-bit seed to a uniform float in [0, 1).\n */\nexport function unitFloat(seed: bigint | number): number {\n const s = typeof seed === 'bigint' ? seed : BigInt(Math.floor(seed));\n const hashed = hash64(s);\n const shifted = Number(hashed >> 11n);\n return shifted / POW2_53;\n}\n\n/**\n * Quintic Hermite interpolant fade function: 6t^5 - 15t^4 + 10t^3.\n * First and second derivatives are zero at t = 0 and t = 1, ensuring C2 continuity.\n */\nexport function quinticFade(t: number): number {\n return t * t * t * (t * (t * 6.0 - 15.0) + 10.0);\n}\n\n/**\n * Returns a deterministic pseudo-random lattice value in [-1, 1].\n */\nfunction lattice(seed: bigint, i: bigint): number {\n const mixed = seed ^ hash64(i & MASK64);\n return unitFloat(mixed) * 2.0 - 1.0;\n}\n\n/**\n * 1D C2-continuous smooth value noise in [-1, 1].\n * Guaranteed bounded by lattice values, smooth without sudden velocity spikes.\n */\nexport function noise1d(seed: bigint | number, x: number): number {\n if (!Number.isFinite(x)) return 0.0;\n const s = typeof seed === 'bigint' ? seed : BigInt(Math.floor(seed));\n const floorX = Math.floor(x);\n const u = quinticFade(x - floorX);\n const i = BigInt(Math.floor(floorX));\n const a = lattice(s, i);\n const b = lattice(s, i + 1n);\n return a + (b - a) * u;\n}\n\n/**\n * 3D C2-continuous smooth value noise in [-1, 1].\n */\nexport function noise3d(x: number, y: number, z: number, seed: bigint | number = 0): number {\n if (!Number.isFinite(x) || !Number.isFinite(y) || !Number.isFinite(z)) {\n return 0.0;\n }\n const s = typeof seed === 'bigint' ? seed : BigInt(Math.floor(seed));\n const fx = Math.floor(x);\n const fy = Math.floor(y);\n const fz = Math.floor(z);\n\n const u = quinticFade(x - fx);\n const v = quinticFade(y - fy);\n const w = quinticFade(z - fz);\n\n const ix = BigInt(fx);\n const iy = BigInt(fy);\n const iz = BigInt(fz);\n\n const g = (dx: bigint, dy: bigint, dz: bigint): number => {\n const combined = mixSeeds([s, ix + dx, iy + dy, iz + dz]);\n return unitFloat(combined) * 2.0 - 1.0;\n };\n\n const lerp = (a: number, b: number, t: number) => a + (b - a) * t;\n\n const x00 = lerp(g(0n, 0n, 0n), g(1n, 0n, 0n), u);\n const x10 = lerp(g(0n, 1n, 0n), g(1n, 1n, 0n), u);\n const x01 = lerp(g(0n, 0n, 1n), g(1n, 0n, 1n), u);\n const x11 = lerp(g(0n, 1n, 1n), g(1n, 1n, 1n), u);\n\n const y0 = lerp(x00, x10, v);\n const y1 = lerp(x01, x11, v);\n\n return lerp(y0, y1, w);\n}\n\n/**\n * Evaluates multi-octave fractal noise wiggle:\n * sum_{k=0}^{octaves-1} amp * (ampMult^k) * noise1d(freq * (2^k) * t)\n *\n * Matches the mathematical formulation of After Effects / EffectCraft wiggle().\n *\n * @param freq Oscillation frequency in Hz (cycles per second).\n * @param amp Maximum deviation amplitude.\n * @param octaves Number of noise detail octaves (default: 3).\n * @param ampMult Amplitude multiplier per octave (default: 0.5).\n * @param t Elapsed time in seconds.\n * @param seed Random seed (default: 42).\n * @param dimension Dimension index (0, 1, 2) to ensure decorrelated multi-axis wiggle.\n */\nexport function fractalWiggle(\n freq: number,\n amp: number,\n octaves = 3,\n ampMult = 0.5,\n t = 0,\n seed = 42,\n dimension = 0,\n): number {\n const oct = Math.max(1, Math.min(16, Math.floor(octaves)));\n let currentAmp = amp;\n let currentFreq = freq;\n let sum = 0.0;\n const baseSeed = BigInt(seed);\n\n for (let k = 0; k < oct; k++) {\n const s = mixSeeds([baseSeed, BigInt(dimension), BigInt(k)]);\n const phaseOffset = unitFloat(s) * 1000.0;\n sum += currentAmp * noise1d(s, currentFreq * t + phaseOffset);\n currentAmp *= ampMult;\n currentFreq *= 2.0;\n }\n\n return sum;\n}\n","import type { Rect } from './geometry.js';\n\nexport interface EffectBase {\n /** Unique identifier for the effect so it can be stopped or updated. */\n id: string;\n /** End the effect when this many subsequent shots begin. */\n shots?: number;\n /** Duration in milliseconds after which the effect stops automatically. */\n duration?: number;\n /** When to start: 'start' of shot or after commands are 'drawn'. Default: 'drawn'. */\n at?: 'start' | 'drawn';\n}\n\nexport interface GradientEffect extends EffectBase {\n type: 'gradient';\n colors: string[];\n rect?: Rect;\n ids?: string[];\n angle?: number;\n period?: number;\n opacity?: number;\n}\n\nexport interface FlowEffect extends EffectBase {\n type: 'flow';\n along: string;\n color?: string;\n dots?: number;\n period?: number;\n size?: number;\n direction?: 'forward' | 'back' | 'both';\n label?: string;\n}\n\nexport interface GlowEffect extends EffectBase {\n type: 'glow';\n ids: string[];\n color?: string;\n size?: number;\n pulse?: boolean;\n}\n\nexport interface SpotlightEffect extends EffectBase {\n type: 'spotlight';\n ids: string[];\n dim?: number;\n padding?: number;\n}\n\nexport interface ShimmerEffect extends EffectBase {\n type: 'shimmer';\n ids: string[];\n color?: string;\n period?: number;\n}\n\nexport interface RippleEffect extends EffectBase {\n type: 'ripple';\n ids: string[];\n color?: string;\n period?: number;\n size?: number;\n times?: number;\n}\n\nexport interface TimerEffect extends EffectBase {\n type: 'timer';\n ids: string[];\n time?: number;\n fill?: boolean;\n repeat?: boolean;\n color?: string;\n size?: number;\n}\n\nexport interface CounterEffect extends EffectBase {\n type: 'counter';\n to: number;\n from?: number;\n time?: number;\n text?: string;\n decimals?: number;\n near?: string;\n x?: number;\n y?: number;\n color?: string;\n size?: number;\n}\n\nexport interface HighlightEffect extends EffectBase {\n type: 'highlight';\n ids: string[];\n style?: 'marker' | 'underline';\n color?: string;\n}\n\nexport interface BlurEffect extends EffectBase {\n type: 'blur';\n ids: string[];\n amount?: number;\n padding?: number;\n}\n\nexport interface BurstEffect extends EffectBase {\n type: 'burst';\n ids: string[];\n color?: string;\n sparks?: number;\n size?: number;\n}\n\n/** Media layer effect driving a WebGL shader (or other media stream) under or over the scene. */\nexport interface MediaEffect extends EffectBase {\n type: 'media';\n /** ID in Scene.media. */\n media: string;\n rect?: Rect;\n ids?: string[];\n padding?: number;\n layer?: 'under' | 'over';\n opacity?: number;\n}\n\nexport type Effect =\n | GradientEffect\n | FlowEffect\n | GlowEffect\n | SpotlightEffect\n | ShimmerEffect\n | RippleEffect\n | TimerEffect\n | CounterEffect\n | HighlightEffect\n | BlurEffect\n | BurstEffect\n | MediaEffect;\n\nexport const EFFECT_TYPES = [\n 'gradient',\n 'flow',\n 'glow',\n 'spotlight',\n 'shimmer',\n 'ripple',\n 'timer',\n 'counter',\n 'highlight',\n 'blur',\n 'burst',\n 'media',\n] as const;\n\nexport const EFFECT_FADE_MS = 300;\n\nexport interface RunningEffect {\n effect: Effect;\n /** Timestamp when started (ms). */\n from: number;\n /** Timestamp when stopping/fading begins (ms). */\n until?: number;\n}\n\n/** Returns true if the effect has completely expired and finished fading out. */\nexport function effectGone(running: RunningEffect, now: number): boolean {\n if (running.until !== undefined) {\n return now >= running.until + EFFECT_FADE_MS;\n }\n if (running.effect.duration !== undefined) {\n return now >= running.from + running.effect.duration + EFFECT_FADE_MS;\n }\n return false;\n}\n\n/** Returns current opacity multiplier (0 to 1) accounting for fade in / fade out. */\nexport function effectOpacity(running: RunningEffect, now: number): number {\n if (now < running.from) return 0;\n // Fade in over first 150ms\n const inFade = Math.min(1, (now - running.from) / 150);\n\n if (running.until !== undefined) {\n const out = Math.max(0, 1 - (now - running.until) / EFFECT_FADE_MS);\n return inFade * out;\n }\n if (running.effect.duration !== undefined) {\n const remaining = running.from + running.effect.duration - now;\n if (remaining < 0) {\n const out = Math.max(0, 1 + remaining / EFFECT_FADE_MS);\n return inFade * out;\n }\n }\n return inFade;\n}\n","import { visibleRect, type View, type Stage } from './camera.js';\nimport { boundsOf, overlapArea, areaOf, type Rect, type SceneElement } from './geometry.js';\nimport { isElementCommand, type Shot } from './types.js';\n\nexport interface ShotCheck {\n /** Elements this shot drew or changed that the camera frame leaves out (\"outside\") or cuts (\"cut\"). */\n framing: { id: string; how: 'outside' | 'cut' }[];\n /** Elements this shot drew that overlap each other significantly. */\n overlaps: [string, string][];\n /** Smallest text size on screen in CSS px. */\n smallestText?: { id: string; text: string; px: number };\n /** Any text smaller than min readable threshold (e.g. 18px). */\n smallTexts?: { id: string; text: string; px: number }[];\n /** Elements clipped by the screen edges. */\n edges: string[];\n /** Elements covered by the title bar. */\n underTitle: string[];\n}\n\nexport const NO_CHECK: ShotCheck = { framing: [], overlaps: [], edges: [], underTitle: [] };\n\nexport const SMALL_TEXT_PX = 24;\n\nexport function titleBox(title: string, stage: Stage): Rect {\n const width = Math.min(stage.width, title.length * 20 + 64);\n return { x: (stage.width - width) / 2, y: 24, width, height: 60 };\n}\n\nexport function touchedIds(shot: Shot): string[] {\n const ids = new Set<string>();\n for (const cmd of shot.run ?? []) {\n if (isElementCommand(cmd)) {\n ids.add(cmd.element.id);\n } else if ('id' in cmd && typeof (cmd as any).id === 'string') {\n ids.add((cmd as any).id);\n }\n }\n return [...ids];\n}\n\nconst IN_FRAME = 0.95;\n\n/** Evaluates the elements on stage against the current camera view and shot settings. */\nexport function checkShot(\n shot: Shot,\n elements: readonly SceneElement[],\n view: View,\n stage: Stage,\n title?: string,\n): ShotCheck {\n const frameRect = visibleRect(view, stage);\n const touched = new Set(touchedIds(shot));\n const framing: { id: string; how: 'outside' | 'cut' }[] = [];\n const edges: string[] = [];\n const overlaps: [string, string][] = [];\n const activeElements = elements.filter((e) => !e.isDeleted && (e.opacity === undefined || e.opacity > 0));\n\n for (const el of activeElements) {\n const box = boundsOf(el);\n const overlap = overlapArea(box, frameRect);\n const boxArea = areaOf(box);\n\n if (touched.has(el.id)) {\n if (overlap === 0) {\n framing.push({ id: el.id, how: 'outside' });\n } else if (boxArea > 0 && overlap / boxArea < IN_FRAME) {\n framing.push({ id: el.id, how: 'cut' });\n }\n } else if (overlap > 0 && boxArea > 0 && overlap / boxArea < IN_FRAME) {\n edges.push(el.id);\n }\n }\n\n // Check overlaps among touched elements\n const touchedList = activeElements.filter((e) => touched.has(e.id));\n for (let i = 0; i < touchedList.length; i++) {\n for (let j = i + 1; j < touchedList.length; j++) {\n const a = touchedList[i]!;\n const b = touchedList[j]!;\n const aBox = boundsOf(a);\n const bBox = boundsOf(b);\n const ol = overlapArea(aBox, bBox);\n const minArea = Math.min(areaOf(aBox), areaOf(bBox));\n if (minArea > 0 && ol / minArea > 0.3) {\n overlaps.push([a.id, b.id]);\n }\n }\n }\n\n // Check text readability under current zoom\n const smallTexts: { id: string; text: string; px: number }[] = [];\n let smallestText: { id: string; text: string; px: number } | undefined;\n\n for (const el of activeElements) {\n if (el.text && el.fontSize) {\n const px = Math.round(el.fontSize * view.zoom);\n const item = { id: el.id, text: el.text, px };\n if (!smallestText || px < smallestText.px) {\n smallestText = item;\n }\n if (px < SMALL_TEXT_PX) {\n smallTexts.push(item);\n }\n }\n }\n\n // Check title obstruction\n const underTitle: string[] = [];\n if (title) {\n const tBox = titleBox(title, stage);\n // Convert tBox in screen space to scene space\n const sceneTBox: Rect = {\n x: tBox.x / view.zoom - view.scrollX,\n y: tBox.y / view.zoom - view.scrollY,\n width: tBox.width / view.zoom,\n height: tBox.height / view.zoom,\n };\n for (const el of activeElements) {\n if (overlapArea(boundsOf(el), sceneTBox) > 0) {\n underTitle.push(el.id);\n }\n }\n }\n\n return {\n framing,\n overlaps,\n smallestText,\n smallTexts: smallTexts.length ? smallTexts : undefined,\n edges,\n underTitle,\n };\n}\n","import type { Scene, Shot } from './types.js';\nimport { EFFECT_TYPES } from './effects.js';\n\nexport interface SceneIssue {\n /** 1-based shot index (0 indicates whole scene level). */\n shot: number;\n message: string;\n}\n\nconst LONG_CAPTION = 120;\nconst LONG_TITLE = 60;\nconst MAX_EFFECTS_PER_SHOT = 5;\n\n/** Validates a Scene before running or rendering it. */\nexport function validateScene(scene: Scene): SceneIssue[] {\n const issues: SceneIssue[] = [];\n const say = (shot: number, message: string) => issues.push({ shot, message });\n\n if (!scene.name || typeof scene.name !== 'string') {\n say(0, 'Scene needs a string name.');\n } else if (!/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(scene.name)) {\n say(0, `Scene name \"${scene.name}\" should be lowercase words and dashes.`);\n }\n\n if (!Array.isArray(scene.shots) || scene.shots.length === 0) {\n say(0, 'Scene needs at least one shot.');\n return issues;\n }\n\n const mediaKeys = new Set(Object.keys(scene.media ?? {}));\n const effectIds = new Set<string>();\n\n // Check media\n if (scene.media) {\n for (const [id, m] of Object.entries(scene.media)) {\n if (!m || typeof m !== 'object') {\n say(0, `Media \"${id}\" must be an object.`);\n } else if (!m.type) {\n say(0, `Media \"${id}\" needs a type.`);\n } else if (m.type === 'shader' && !m.source) {\n say(0, `Shader media \"${id}\" needs a source string.`);\n }\n }\n }\n\n for (const [idx, shot] of scene.shots.entries()) {\n const shotNum = idx + 1;\n\n // Check camera\n if (shot.camera) {\n if ('frame' in shot.camera) {\n if (!Array.isArray(shot.camera.frame) || shot.camera.frame.length === 0) {\n say(shotNum, 'Dynamic camera framing requires a non-empty frame array of element IDs.');\n }\n } else if (shot.camera.width <= 0 || shot.camera.height <= 0) {\n say(shotNum, 'Camera rectangle width and height must be positive.');\n }\n }\n\n // Check hold\n if (shot.hold !== undefined && shot.hold < 0) {\n say(shotNum, 'Shot hold cannot be negative.');\n }\n\n // Check text lengths\n if (shot.caption && shot.caption.length > LONG_CAPTION) {\n say(shotNum, `Caption is long (${shot.caption.length} chars); consider breaking into multiple shots.`);\n }\n if (shot.title && shot.title.length > LONG_TITLE) {\n say(shotNum, `Title is long (${shot.title.length} chars); titles should be concise headings.`);\n }\n\n // Check effects\n const effects = shot.effects ?? [];\n if (effects.length > MAX_EFFECTS_PER_SHOT) {\n say(shotNum, `Shot starts ${effects.length} effects at once; consider keeping effects focused.`);\n }\n\n for (const eff of effects) {\n if (!eff.id || typeof eff.id !== 'string') {\n say(shotNum, 'Every effect needs a unique string id.');\n continue;\n }\n if (effectIds.has(eff.id)) {\n say(shotNum, `Duplicate effect id \"${eff.id}\".`);\n }\n effectIds.add(eff.id);\n\n if (!EFFECT_TYPES.includes(eff.type as any)) {\n say(shotNum, `Unknown effect type \"${(eff as any).type}\".`);\n }\n\n if (eff.type === 'media') {\n if (!eff.media) {\n say(shotNum, `Media effect \"${eff.id}\" needs a media id.`);\n } else if (!mediaKeys.has(eff.media)) {\n say(shotNum, `Media effect \"${eff.id}\" references \"${eff.media}\" which is not defined in scene.media.`);\n }\n }\n\n if (eff.type === 'flow' && !eff.along) {\n say(shotNum, `Flow effect \"${eff.id}\" needs an \"along\" element id.`);\n }\n\n if (['glow', 'ripple', 'spotlight', 'shimmer', 'timer', 'blur', 'burst'].includes(eff.type)) {\n const withIds = eff as { ids?: string[] };\n if (!Array.isArray(withIds.ids) || withIds.ids.length === 0) {\n say(shotNum, `${eff.type} effect \"${eff.id}\" needs a non-empty ids array.`);\n }\n }\n }\n }\n\n return issues;\n}\n","import type { ShotCheck } from './check.js';\nimport type { Scene } from './types.js';\n\nexport interface ShotLog extends ShotCheck {\n index: number;\n start: number;\n drawn: number;\n end: number;\n caption?: string;\n title?: string;\n failed: string[];\n effects?: string[];\n}\n\nexport interface ReviewOptions {\n target?: [number, number];\n minTextPx?: number;\n}\n\nexport interface Review {\n totalMs: number;\n warnings: string[];\n notes: string[];\n markdown: string;\n}\n\n/** Formats a structured diagnostic report of scene playback. */\nexport function reviewScene(scene: Scene, logs: readonly ShotLog[], options: ReviewOptions = {}): Review {\n const warnings: string[] = [];\n const notes: string[] = [];\n const minTextPx = options.minTextPx ?? 18;\n const totalMs = logs.length > 0 ? logs[logs.length - 1]!.end : 0;\n const totalSec = (totalMs / 1000).toFixed(1);\n\n if (scene.target) {\n const [minS, maxS] = scene.target;\n const durS = totalMs / 1000;\n if (durS < minS) {\n warnings.push(`Scene is ${totalSec}s, shorter than target minimum (${minS}s).`);\n } else if (durS > maxS) {\n warnings.push(`Scene is ${totalSec}s, longer than target maximum (${maxS}s).`);\n }\n }\n\n for (const log of logs) {\n const shotPrefix = `Shot ${log.index}:`;\n\n if (log.failed.length > 0) {\n warnings.push(`${shotPrefix} ${log.failed.length} command(s) failed: ${log.failed.join(', ')}`);\n }\n\n for (const f of log.framing) {\n warnings.push(`${shotPrefix} element \"${f.id}\" is ${f.how} of the camera frame.`);\n }\n\n for (const [a, b] of log.overlaps) {\n notes.push(`${shotPrefix} elements \"${a}\" and \"${b}\" overlap significantly.`);\n }\n\n if (log.smallTexts) {\n for (const t of log.smallTexts) {\n if (t.px < minTextPx) {\n warnings.push(`${shotPrefix} text \"${t.text}\" is only ${t.px}px on screen (less than ${minTextPx}px minimum).`);\n }\n }\n }\n\n for (const id of log.underTitle) {\n warnings.push(`${shotPrefix} element \"${id}\" is partially covered by the title bar.`);\n }\n }\n\n // Generate markdown\n const lines: string[] = [\n `# Scene Preview Review: ${scene.title || scene.name}`,\n `**Total Duration:** ${totalSec}s (${logs.length} shots)`,\n '',\n ];\n\n if (warnings.length > 0) {\n lines.push('### ⚠️ Warnings to Address:');\n for (const w of warnings) lines.push(`- ${w}`);\n lines.push('');\n } else {\n lines.push('✅ No critical layout or framing warnings.');\n lines.push('');\n }\n\n if (notes.length > 0) {\n lines.push('### ℹ️ Layout Notes:');\n for (const n of notes) lines.push(`- ${n}`);\n lines.push('');\n }\n\n lines.push('### Shot Breakdown');\n lines.push('| Shot | Start | End | Duration | Title / Caption |');\n lines.push('|:---:|:---:|:---:|:---:|:---|');\n for (const log of logs) {\n const dur = ((log.end - log.start) / 1000).toFixed(1);\n const text = log.title || log.caption || '—';\n lines.push(`| ${log.index} | ${(log.start / 1000).toFixed(1)}s | ${(log.end / 1000).toFixed(1)}s | ${dur}s | ${text.slice(0, 40)} |`);\n }\n\n return {\n totalMs,\n warnings,\n notes,\n markdown: lines.join('\\n'),\n };\n}\n","import type { EasingCurve } from '../time/retiming.js';\n\nexport interface BehaviorBase {\n id?: string;\n /** Target element ID or media ID. */\n target: string;\n /** Property on element (e.g. 'x', 'y', 'scale', 'rotation', 'opacity') or uniform on media. */\n property: string;\n}\n\nexport interface OscillateBehavior extends BehaviorBase {\n type: 'oscillate';\n wave?: 'sine' | 'square' | 'triangle' | 'sawtooth';\n amplitude: number;\n /** Frequency in Hz (cycles per second). */\n frequency: number;\n /** Phase offset in radians (default 0). */\n phase?: number;\n /** Base center value. If undefined, treated as relative offset added to current base value. */\n center?: number;\n}\n\nexport interface RampBehavior extends BehaviorBase {\n type: 'ramp';\n from?: number;\n to: number;\n ease?: EasingCurve;\n}\n\nexport interface RateBehavior extends BehaviorBase {\n type: 'rate';\n /** Rate of change per second (e.g. degrees/sec or units/sec). */\n rate: number;\n}\n\nexport interface WriggleBehavior extends BehaviorBase {\n type: 'wriggle';\n /** Maximum amplitude of deviation. */\n amount: number;\n /** Speed / frequency of variation in Hz. */\n frequency: number;\n /** Number of noise octaves for organic complexity (default: 3). */\n octaves?: number;\n /** Deterministic random seed. */\n seed?: number;\n}\n\nexport interface OvershootBehavior extends BehaviorBase {\n type: 'overshoot';\n targetValue: number;\n startValue?: number;\n /** Oscillation frequency / cycles (default: 3). */\n cycles?: number;\n /** Damping factor (higher settles faster, default: 4.0). */\n damping?: number;\n}\n\nexport interface ThrowBehavior extends BehaviorBase {\n type: 'throw';\n /** Initial speed in units per second. */\n initialVelocity: number;\n /** Friction / deceleration factor (default: 2.0). */\n friction?: number;\n}\n\nexport type Behavior =\n | OscillateBehavior\n | RampBehavior\n | RateBehavior\n | WriggleBehavior\n | OvershootBehavior\n | ThrowBehavior;\n\nimport { fractalWiggle } from '../time/noise.js';\n\n/**\n * Computes smooth organic 1D multi-octave C2 noise wander matching AE wiggle.\n */\nfunction evaluateWriggle(\n t: number,\n freq: number,\n amount: number,\n octaves = 3,\n seed = 42,\n): number {\n return fractalWiggle(freq, amount, octaves, 0.5, t, seed, 0);\n}\n\n/**\n * Evaluates the new numeric value for a behavior at a given elapsed time.\n * @param behavior The behavior specification.\n * @param elapsedSec Elapsed time within the shot/behavior duration (in seconds).\n * @param durationSec Total duration of the shot/behavior (in seconds).\n * @param baseValue Initial or fallback value before behavior was applied.\n */\nexport function evaluateBehavior(\n behavior: Behavior,\n elapsedSec: number,\n durationSec: number,\n baseValue = 0,\n): number {\n const t = Math.max(0, elapsedSec);\n\n switch (behavior.type) {\n case 'oscillate': {\n const freq = behavior.frequency;\n const phase = behavior.phase ?? 0;\n const angle = 2 * Math.PI * freq * t + phase;\n let waveVal = 0;\n\n switch (behavior.wave) {\n case 'square':\n waveVal = Math.sin(angle) >= 0 ? 1 : -1;\n break;\n case 'triangle':\n waveVal = (2 / Math.PI) * Math.asin(Math.sin(angle));\n break;\n case 'sawtooth': {\n const norm = (angle / (2 * Math.PI)) % 1;\n waveVal = 2 * (norm < 0 ? norm + 1 : norm) - 1;\n break;\n }\n case 'sine':\n default:\n waveVal = Math.sin(angle);\n break;\n }\n\n const offset = waveVal * behavior.amplitude;\n return behavior.center !== undefined ? behavior.center + offset : baseValue + offset;\n }\n\n case 'ramp': {\n const from = behavior.from ?? baseValue;\n const to = behavior.to;\n const p = durationSec > 0 ? Math.min(1, Math.max(0, t / durationSec)) : 1;\n let eased = p;\n\n switch (behavior.ease) {\n case 'easeIn':\n eased = p * p;\n break;\n case 'easeOut':\n eased = p * (2 - p);\n break;\n case 'easeInOut':\n eased = p < 0.5 ? 2 * p * p : -1 + (4 - 2 * p) * p;\n break;\n case 'linear':\n default:\n eased = p;\n break;\n }\n\n return from + (to - from) * eased;\n }\n\n case 'rate': {\n return baseValue + behavior.rate * t;\n }\n\n case 'wriggle': {\n const wander = evaluateWriggle(\n t,\n behavior.frequency,\n behavior.amount,\n behavior.octaves ?? 3,\n behavior.seed ?? 42,\n );\n return baseValue + wander;\n }\n\n case 'overshoot': {\n const from = behavior.startValue ?? baseValue;\n const target = behavior.targetValue;\n const cycles = behavior.cycles ?? 3;\n const damping = behavior.damping ?? 4.0;\n\n if (durationSec <= 0) return target;\n const p = Math.min(1, t / durationSec);\n if (p >= 1) return target;\n\n // Damped harmonic oscillation: 1 - e^(-damping * p) * cos(cycles * pi * p)\n const envelope = Math.exp(-damping * p);\n const oscillation = Math.cos(cycles * Math.PI * p);\n const progress = 1 - envelope * oscillation;\n\n return from + (target - from) * progress;\n }\n\n case 'throw': {\n const v0 = behavior.initialVelocity;\n const k = Math.max(0.001, behavior.friction ?? 2.0);\n // Continuous displacement under linear drag: x(t) = (v0 / k) * (1 - e^(-k * t))\n const displacement = (v0 / k) * (1 - Math.exp(-k * t));\n return baseValue + displacement;\n }\n }\n}\n","import type { Clock } from '../time/clock.js';\nimport { ManualClock } from '../time/clock.js';\nimport {\n between,\n CAMERA_MS,\n DEFAULT_STAGE,\n easeInOutCubic,\n frame,\n calculateFramingRect,\n viewAt,\n type Stage,\n type View,\n} from './camera.js';\nimport { checkShot } from './check.js';\nimport { effectGone, type RunningEffect } from './effects.js';\nimport { evaluateBehavior } from './behavior.js';\nimport type { Rect, SceneElement } from './geometry.js';\nimport { reviewScene, type Review, type ShotLog } from './report.js';\nimport {\n isDeleteCommand,\n isElementCommand,\n isUpdateCommand,\n type Scene,\n type SceneCommand,\n type Shot,\n} from './types.js';\n\nexport interface SceneBoard {\n getView(): View;\n setView(view: View): void;\n elements(): readonly SceneElement[];\n runCommand(cmd: SceneCommand): void | Promise<void>;\n setTitle?(text: string, opacity: number): void;\n setCaption?(text: string): void;\n setEffects?(effects: readonly RunningEffect[]): void;\n setMediaTime?(mediaId: string, timeSeconds: number): void;\n}\n\n/** Pure in-memory board implementation suitable for headless simulation, testing, and SSR. */\nexport class MemorySceneBoard implements SceneBoard {\n private view: View;\n private elMap = new Map<string, SceneElement>();\n private currentTitle = '';\n private currentCaption = '';\n private runningEffects: readonly RunningEffect[] = [];\n\n constructor(stage: Stage = DEFAULT_STAGE) {\n this.view = viewAt(stage.width / 2, stage.height / 2, 1, stage);\n }\n\n getView(): View {\n return this.view;\n }\n\n setView(view: View): void {\n this.view = view;\n }\n\n elements(): readonly SceneElement[] {\n return Array.from(this.elMap.values());\n }\n\n runCommand(cmd: SceneCommand): void {\n if (isElementCommand(cmd)) {\n this.elMap.set(cmd.element.id, { ...cmd.element });\n } else if (isUpdateCommand(cmd)) {\n const existing = this.elMap.get(cmd.id);\n if (existing) {\n this.elMap.set(cmd.id, { ...existing, ...cmd.props });\n }\n } else if (isDeleteCommand(cmd)) {\n this.elMap.delete(cmd.id);\n } else if (cmd.type === 'clear') {\n this.elMap.clear();\n }\n }\n\n setTitle(text: string): void {\n this.currentTitle = text;\n }\n\n setCaption(text: string): void {\n this.currentCaption = text;\n }\n\n setEffects(effects: readonly RunningEffect[]): void {\n this.runningEffects = effects;\n }\n}\n\nexport interface PlayOptions {\n check?: boolean;\n afterShot?: (log: ShotLog) => void | Promise<void>;\n}\n\nexport interface PlayResult {\n ok: boolean;\n duration: number;\n shots: ShotLog[];\n}\n\n/**\n * Plays a scene's shots sequentially on `board` driven by `clock`.\n * When using a `ManualClock`, the execution is completely deterministic and stepped.\n */\nexport async function playScene(\n scene: Scene,\n board: SceneBoard,\n clock: Clock,\n options: PlayOptions = {},\n): Promise<PlayResult> {\n const stage: Stage = {\n width: scene.stage?.width ?? DEFAULT_STAGE.width,\n height: scene.stage?.height ?? DEFAULT_STAGE.height,\n caption: scene.stage?.caption ?? DEFAULT_STAGE.caption,\n };\n\n const shots: ShotLog[] = [];\n const begin = clock.now();\n let runningEffects: RunningEffect[] = [];\n const endsAt = new Map<RunningEffect, number>();\n\n const updateEffects = (next: RunningEffect[]) => {\n runningEffects = next.filter((r) => !effectGone(r, clock.now()));\n board.setEffects?.(runningEffects);\n };\n\n for (const [idx, shot] of scene.shots.entries()) {\n const shotStart = clock.now() - begin;\n const failedCmds: string[] = [];\n\n // Stop requested effects\n const stopIds = new Set(shot.stopEffects ?? []);\n if (stopIds.size > 0 || runningEffects.some((r) => endsAt.get(r) === idx)) {\n const now = clock.now();\n updateEffects(\n runningEffects.map((r) =>\n r.until === undefined && (stopIds.has(r.effect.id) || endsAt.get(r) === idx)\n ? { ...r, until: now }\n : r,\n ),\n );\n }\n\n // Camera move\n if (shot.camera) {\n let targetRect: Rect;\n if ('frame' in shot.camera) {\n const frameIds = new Set(shot.camera.frame);\n const targetElements = board.elements().filter((el) => frameIds.has(el.id));\n if (targetElements.length === 0 && shot.run) {\n for (const cmd of shot.run) {\n if (isElementCommand(cmd) && frameIds.has(cmd.element.id)) {\n targetElements.push(cmd.element);\n }\n }\n }\n targetRect = calculateFramingRect(targetElements, stage, {\n padding: shot.camera.padding,\n minWidth: shot.camera.minWidth,\n minHeight: shot.camera.minHeight,\n });\n } else {\n targetRect = shot.camera;\n }\n\n const targetView = frame(targetRect, stage);\n if (idx === 0) {\n board.setView(targetView);\n } else {\n const fromView = board.getView();\n const steps = 15;\n const stepMs = CAMERA_MS / steps;\n for (let s = 1; s <= steps; s++) {\n const t = easeInOutCubic(s / steps);\n board.setView(between(fromView, targetView, t, stage));\n await clock.sleep(stepMs);\n }\n }\n }\n\n // Set title and caption\n if (shot.title !== undefined) {\n board.setTitle?.(shot.title, 1);\n }\n if (shot.caption !== undefined) {\n board.setCaption?.(shot.caption);\n }\n\n // Start effects scheduled at 'start'\n const startEffects = (shot.effects ?? []).filter((e) => e.at === 'start');\n if (startEffects.length > 0) {\n const now = clock.now();\n const added = startEffects.map((effect): RunningEffect => ({ effect, from: now }));\n for (const r of added) if (r.effect.shots) endsAt.set(r, idx + r.effect.shots);\n updateEffects([...runningEffects, ...added]);\n }\n\n // Run commands\n for (const cmd of shot.run ?? []) {\n try {\n await board.runCommand(cmd);\n } catch (err: any) {\n failedCmds.push(err.message || String(err));\n }\n }\n\n // Start effects scheduled after 'drawn' (default)\n const drawnEffects = (shot.effects ?? []).filter((e) => e.at !== 'start');\n if (drawnEffects.length > 0) {\n const now = clock.now();\n const added = drawnEffects.map((effect): RunningEffect => ({ effect, from: now }));\n for (const r of added) if (r.effect.shots) endsAt.set(r, idx + r.effect.shots);\n updateEffects([...runningEffects, ...added]);\n }\n\n const drawnTime = clock.now() - begin;\n\n // Check shot layout & framing\n const check = options.check\n ? checkShot(shot, board.elements(), board.getView(), stage, shot.title)\n : { framing: [], overlaps: [], edges: [], underTitle: [] };\n\n // Hold dwell time and active behaviors\n const holdMs = shot.hold ?? 800;\n const behaviors = shot.behaviors ?? [];\n if (behaviors.length > 0) {\n const initialProps = new Map<string, number>();\n for (const b of behaviors) {\n const key = `${b.target}:${b.property}`;\n const el = board.elements().find((e) => e.id === b.target);\n if (el && typeof (el as any)[b.property] === 'number') {\n initialProps.set(key, (el as any)[b.property]);\n } else {\n initialProps.set(key, 0);\n }\n }\n\n const stepMs = 50;\n const steps = Math.max(1, Math.round(holdMs / stepMs));\n const actualStepMs = holdMs / steps;\n const durationSec = holdMs / 1000;\n\n for (let s = 1; s <= steps; s++) {\n await clock.sleep(actualStepMs);\n const elapsedSec = (s * actualStepMs) / 1000;\n for (const b of behaviors) {\n const baseVal = initialProps.get(`${b.target}:${b.property}`) ?? 0;\n const nextVal = evaluateBehavior(b, elapsedSec, durationSec, baseVal);\n board.runCommand({\n type: 'update',\n id: b.target,\n props: { [b.property]: nextVal },\n });\n }\n }\n } else {\n await clock.sleep(holdMs);\n }\n\n const shotEnd = clock.now() - begin;\n\n const log: ShotLog = {\n ...check,\n index: idx + 1,\n start: shotStart,\n drawn: drawnTime,\n end: shotEnd,\n caption: shot.caption,\n title: shot.title,\n failed: failedCmds,\n effects: runningEffects.map((r) => r.effect.id),\n };\n\n shots.push(log);\n if (options.afterShot) {\n await options.afterShot(log);\n }\n }\n\n const duration = clock.now() - begin;\n const ok = shots.every((s) => s.failed.length === 0 && s.framing.every((f) => f.how !== 'outside'));\n\n return { ok, duration, shots };\n}\n\n/**\n * Simulates a scene instantaneously using a ManualClock and MemorySceneBoard,\n * returning full timing details, layout checks, and diagnostic report.\n */\nexport async function simulateScene(\n scene: Scene,\n options: { minTextPx?: number } = {},\n): Promise<{ result: PlayResult; review: Review }> {\n const clock = new ManualClock();\n const board = new MemorySceneBoard();\n\n let done = false;\n let playError: any = null;\n const playPromise = playScene(scene, board, clock, { check: true })\n .then((res) => {\n done = true;\n return res;\n })\n .catch((err) => {\n done = true;\n playError = err;\n throw err;\n });\n\n // Advance manual clock until simulation finishes\n for (let i = 0; i < 5000 && !done; i++) {\n await clock.advance(50);\n }\n\n if (playError) throw playError;\n const result = await playPromise;\n const review = reviewScene(scene, result.shots, {\n target: scene.target,\n minTextPx: options.minTextPx,\n });\n\n return { result, review };\n}\n","import type { Scene } from './types.js';\n\n/**\n * Generates a self-contained, standalone HTML player for an animated scene.\n * Includes interactive playback controls, camera panning/zooming, title and caption rendering,\n * and embedded WebGL fragment shaders for bespoke motion graphics.\n */\nexport function standaloneSceneHtml(scene: Scene): string {\n const serializedScene = JSON.stringify(scene).replace(/</g, '\\\\u003c');\n const title = scene.title || scene.name;\n\n return `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"utf-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>${escapeHtml(title)} - Flair</title>\n <style>\n * { box-sizing: border-box; margin: 0; padding: 0; }\n body {\n background: #0f1117;\n color: #e2e8f0;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\n min-height: 100vh;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 16px;\n user-select: none;\n }\n .player-container {\n position: relative;\n width: 100%;\n max-width: 1200px;\n aspect-ratio: 16 / 9;\n background: #000;\n border-radius: 12px;\n overflow: hidden;\n box-shadow: 0 20px 50px rgba(0, 0, 0, 0.7), 0 0 0 1px rgba(255, 255, 255, 0.1);\n display: flex;\n flex-direction: column;\n }\n .viewport {\n position: relative;\n flex: 1;\n width: 100%;\n height: 100%;\n overflow: hidden;\n }\n canvas.layer {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n }\n .overlay-title {\n position: absolute;\n top: 24px;\n left: 50%;\n transform: translateX(-50%);\n background: rgba(15, 17, 23, 0.85);\n backdrop-filter: blur(8px);\n border: 1px solid rgba(255, 255, 255, 0.15);\n padding: 8px 24px;\n border-radius: 9999px;\n font-size: 1.15rem;\n font-weight: 600;\n letter-spacing: 0.02em;\n color: #fff;\n pointer-events: none;\n transition: opacity 0.3s ease;\n opacity: 0;\n }\n .overlay-caption {\n position: absolute;\n bottom: 64px;\n left: 50%;\n transform: translateX(-50%);\n background: rgba(15, 17, 23, 0.88);\n backdrop-filter: blur(8px);\n border: 1px solid rgba(255, 255, 255, 0.15);\n padding: 10px 20px;\n border-radius: 8px;\n font-size: 1.1rem;\n color: #f1f5f9;\n max-width: 80%;\n text-align: center;\n pointer-events: none;\n transition: opacity 0.3s ease;\n opacity: 0;\n }\n .controls-bar {\n position: absolute;\n bottom: 0;\n left: 0;\n right: 0;\n height: 52px;\n background: linear-gradient(to top, rgba(0, 0, 0, 0.9), transparent);\n display: flex;\n align-items: center;\n padding: 0 16px;\n gap: 12px;\n z-index: 10;\n }\n .btn {\n background: rgba(255, 255, 255, 0.15);\n border: none;\n color: #fff;\n padding: 6px 14px;\n border-radius: 6px;\n cursor: pointer;\n font-size: 0.9rem;\n font-weight: 500;\n transition: background 0.15s;\n }\n .btn:hover { background: rgba(255, 255, 255, 0.25); }\n .timeline {\n flex: 1;\n height: 6px;\n background: rgba(255, 255, 255, 0.2);\n border-radius: 3px;\n cursor: pointer;\n position: relative;\n }\n .timeline-progress {\n position: absolute;\n top: 0;\n left: 0;\n height: 100%;\n background: #3b82f6;\n border-radius: 3px;\n width: 0%;\n }\n .shot-badge {\n font-size: 0.85rem;\n color: #94a3b8;\n font-variant-numeric: tabular-nums;\n }\n </style>\n</head>\n<body>\n <div class=\"player-container\">\n <div class=\"viewport\" id=\"viewport\">\n <canvas id=\"shaderCanvas\" class=\"layer\"></canvas>\n <canvas id=\"sceneCanvas\" class=\"layer\"></canvas>\n <div id=\"titleEl\" class=\"overlay-title\"></div>\n <div id=\"captionEl\" class=\"overlay-caption\"></div>\n </div>\n <div class=\"controls-bar\">\n <button id=\"playBtn\" class=\"btn\">Play</button>\n <button id=\"prevBtn\" class=\"btn\">⏮</button>\n <button id=\"nextBtn\" class=\"btn\">⏭</button>\n <div id=\"timeline\" class=\"timeline\">\n <div id=\"progress\" class=\"timeline-progress\"></div>\n </div>\n <div id=\"shotBadge\" class=\"shot-badge\">Shot 1 / 1</div>\n </div>\n </div>\n\n <script>\n const scene = ${serializedScene};\n const sceneCanvas = document.getElementById('sceneCanvas');\n const shaderCanvas = document.getElementById('shaderCanvas');\n const ctx = sceneCanvas.getContext('2d');\n const titleEl = document.getElementById('titleEl');\n const captionEl = document.getElementById('captionEl');\n const playBtn = document.getElementById('playBtn');\n const prevBtn = document.getElementById('prevBtn');\n const nextBtn = document.getElementById('nextBtn');\n const progressEl = document.getElementById('progress');\n const shotBadge = document.getElementById('shotBadge');\n\n let currentShotIdx = 0;\n let isPlaying = false;\n let shotStartTime = 0;\n let gl = null;\n let shaderProgram = null;\n\n function resize() {\n const rect = sceneCanvas.parentElement.getBoundingClientRect();\n const dpr = window.devicePixelRatio || 1;\n sceneCanvas.width = rect.width * dpr;\n sceneCanvas.height = rect.height * dpr;\n shaderCanvas.width = rect.width * dpr;\n shaderCanvas.height = rect.height * dpr;\n }\n window.addEventListener('resize', resize);\n resize();\n\n // Setup WebGL if shader media is present\n const firstShaderKey = Object.keys(scene.media || {}).find(k => scene.media[k].type === 'shader');\n if (firstShaderKey && scene.media[firstShaderKey].source) {\n try {\n gl = shaderCanvas.getContext('webgl2');\n if (gl) {\n const vs = gl.createShader(gl.VERTEX_SHADER);\n gl.shaderSource(vs, '#version 300 es\\\\nin vec2 position; void main() { gl_Position = vec4(position, 0.0, 1.0); }');\n gl.compileShader(vs);\n\n const fs = gl.createShader(gl.FRAGMENT_SHADER);\n const fullFrag = '#version 300 es\\\\nprecision highp float;\\\\nout vec4 fragColor;\\\\nuniform vec2 u_resolution;\\\\nuniform float u_time;\\\\n' + scene.media[firstShaderKey].source + '\\\\nvoid main() { mainImage(fragColor, gl_FragCoord.xy); }';\n gl.shaderSource(fs, fullFrag);\n gl.compileShader(fs);\n\n shaderProgram = gl.createProgram();\n gl.attachShader(shaderProgram, vs);\n gl.attachShader(shaderProgram, fs);\n gl.linkProgram(shaderProgram);\n\n const quad = gl.createBuffer();\n gl.bindBuffer(gl.ARRAY_BUFFER, quad);\n gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([-1,-1, 3,-1, -1,3]), gl.STATIC_DRAW);\n const pos = gl.getAttribLocation(shaderProgram, 'position');\n gl.enableVertexAttribArray(pos);\n gl.vertexAttribPointer(pos, 2, gl.FLOAT, false, 0, 0);\n }\n } catch (e) {\n console.warn('Shader setup failed:', e);\n }\n }\n\n function renderShader(timeSeconds) {\n if (!gl || !shaderProgram) return;\n gl.viewport(0, 0, shaderCanvas.width, shaderCanvas.height);\n gl.useProgram(shaderProgram);\n const resLoc = gl.getUniformLocation(shaderProgram, 'u_resolution');\n const timeLoc = gl.getUniformLocation(shaderProgram, 'u_time');\n if (resLoc) gl.uniform2f(resLoc, shaderCanvas.width, shaderCanvas.height);\n if (timeLoc) gl.uniform1f(timeLoc, timeSeconds);\n gl.drawArrays(gl.TRIANGLES, 0, 3);\n }\n\n function updateShotUI() {\n const shot = scene.shots[currentShotIdx];\n if (!shot) return;\n\n shotBadge.textContent = 'Shot ' + (currentShotIdx + 1) + ' / ' + scene.shots.length;\n\n if (shot.title) {\n titleEl.textContent = shot.title;\n titleEl.style.opacity = '1';\n } else {\n titleEl.style.opacity = '0';\n }\n\n if (shot.caption) {\n captionEl.textContent = shot.caption;\n captionEl.style.opacity = '1';\n } else {\n captionEl.style.opacity = '0';\n }\n\n const pct = (currentShotIdx / scene.shots.length) * 100;\n progressEl.style.width = pct + '%';\n }\n\n function draw() {\n const now = performance.now() / 1000;\n renderShader(now);\n\n ctx.clearRect(0, 0, sceneCanvas.width, sceneCanvas.height);\n ctx.save();\n const shot = scene.shots[currentShotIdx];\n\n // Draw shot elements\n if (shot && shot.run) {\n for (const cmd of shot.run) {\n if (cmd.type === 'element' && cmd.element) {\n const el = cmd.element;\n ctx.fillStyle = el.backgroundColor || 'rgba(59, 130, 246, 0.4)';\n ctx.strokeStyle = el.strokeColor || '#3b82f6';\n ctx.lineWidth = 3;\n ctx.strokeRect(el.x, el.y, el.width, el.height);\n ctx.fillRect(el.x, el.y, el.width, el.height);\n\n if (el.text) {\n ctx.fillStyle = '#fff';\n ctx.font = '24px sans-serif';\n ctx.fillText(el.text, el.x + 16, el.y + 40);\n }\n }\n }\n }\n ctx.restore();\n\n if (isPlaying) {\n requestAnimationFrame(draw);\n }\n }\n\n playBtn.addEventListener('click', () => {\n isPlaying = !isPlaying;\n playBtn.textContent = isPlaying ? 'Pause' : 'Play';\n if (isPlaying) requestAnimationFrame(draw);\n });\n\n prevBtn.addEventListener('click', () => {\n if (currentShotIdx > 0) {\n currentShotIdx--;\n updateShotUI();\n draw();\n }\n });\n\n nextBtn.addEventListener('click', () => {\n if (currentShotIdx < scene.shots.length - 1) {\n currentShotIdx++;\n updateShotUI();\n draw();\n }\n });\n\n updateShotUI();\n draw();\n </script>\n</body>\n</html>`;\n}\n\nfunction escapeHtml(str: string): string {\n return str\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&#39;');\n}\n"],"mappings":"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","names":["escapeHtml"]}