gpucanvas 0.3.1 → 0.4.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/README.md +130 -10
- package/dist/{chunk-RBXGH44N.js → chunk-DPCICAYZ.js} +702 -11
- package/dist/chunk-DPCICAYZ.js.map +1 -0
- package/dist/{editor-BSRqjhN8.d.ts → editor-CuH4tLHg.d.ts} +13 -3
- package/dist/index.d.ts +165 -3
- package/dist/index.js +17 -1
- package/dist/react.d.ts +1 -1
- package/dist/react.js +1 -1
- package/package.json +5 -3
- package/dist/chunk-RBXGH44N.js.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/camera.ts","../src/effects.ts","../src/elements.ts","../src/node-style.ts","../src/types.ts","../src/dom-backend.ts","../src/atlas.ts","../src/composite-shader.ts","../src/gpu-renderer.ts","../src/page.ts","../src/gpu-backend.ts","../src/layers.ts","../src/overlay.ts","../src/snap.ts","../src/editor.ts","../src/index.ts"],"sourcesContent":["export interface Camera {\n /** World coordinate shown at the viewport's top-left corner. */\n x: number;\n y: number;\n zoom: number;\n}\n\nexport interface Rect {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\nexport interface Point {\n x: number;\n y: number;\n}\n\n/** A point in surface pixels (from the surface's top left) as world units. */\nexport const screenToWorld = (camera: Camera, point: Point): Point => ({\n x: camera.x + point.x / camera.zoom,\n y: camera.y + point.y / camera.zoom,\n});\n\n/** A world point as surface pixels. */\nexport const worldToScreen = (camera: Camera, point: Point): Point => ({\n x: (point.x - camera.x) * camera.zoom,\n y: (point.y - camera.y) * camera.zoom,\n});\n\nexport const MIN_ZOOM = 0.02;\nexport const MAX_ZOOM = 16;\n\nconst clampZoom = (zoom: number) => Math.min(MAX_ZOOM, Math.max(MIN_ZOOM, zoom));\n\n/** Zooms by `factor` while keeping the world point under (screenX, screenY) fixed. */\nexport function zoomAt(camera: Camera, screenX: number, screenY: number, factor: number): Camera {\n const zoom = clampZoom(camera.zoom * factor);\n const worldX = camera.x + screenX / camera.zoom;\n const worldY = camera.y + screenY / camera.zoom;\n return { x: worldX - screenX / zoom, y: worldY - screenY / zoom, zoom };\n}\n\nexport function visibleWorldRect(\n camera: Camera,\n viewportWidth: number,\n viewportHeight: number,\n): Rect {\n return {\n x: camera.x,\n y: camera.y,\n width: viewportWidth / camera.zoom,\n height: viewportHeight / camera.zoom,\n };\n}\n\nexport const containsPoint = (rect: Rect, point: Point) =>\n point.x >= rect.x &&\n point.x < rect.x + rect.width &&\n point.y >= rect.y &&\n point.y < rect.y + rect.height;\n\nexport const intersects = (a: Rect, b: Rect) =>\n a.x < b.x + b.width && b.x < a.x + a.width && a.y < b.y + b.height && b.y < a.y + a.height;\n\n/** Fits `bounds` into the viewport with `padding` CSS pixels on each side. */\nexport function fitCamera(\n bounds: Rect,\n viewportWidth: number,\n viewportHeight: number,\n padding = 40,\n): Camera {\n const zoom = clampZoom(\n Math.min(\n (viewportWidth - padding * 2) / Math.max(1, bounds.width),\n (viewportHeight - padding * 2) / Math.max(1, bounds.height),\n ),\n );\n return {\n x: bounds.x + bounds.width / 2 - viewportWidth / 2 / zoom,\n y: bounds.y + bounds.height / 2 - viewportHeight / 2 / zoom,\n zoom,\n };\n}\n\n/**\n * Wheel and drag input: trackpad scroll pans, pinch or ctrl/cmd + wheel zooms, dragging empty\n * space pans. Calls `onChange` with the next camera; the caller owns the camera value.\n */\nexport function bindCameraInput(\n element: HTMLElement,\n getCamera: () => Camera,\n onChange: (camera: Camera) => void,\n): () => void {\n const onWheel = (event: WheelEvent) => {\n event.preventDefault();\n const bounds = element.getBoundingClientRect();\n const camera = getCamera();\n if (event.ctrlKey || event.metaKey) {\n const factor = Math.exp(-event.deltaY * (event.deltaMode === 1 ? 0.05 : 0.01));\n onChange(zoomAt(camera, event.clientX - bounds.left, event.clientY - bounds.top, factor));\n } else {\n onChange({\n ...camera,\n x: camera.x + event.deltaX / camera.zoom,\n y: camera.y + event.deltaY / camera.zoom,\n });\n }\n };\n\n let drag: { pointerId: number; x: number; y: number } | null = null;\n const onPointerDown = (event: PointerEvent) => {\n // Only drags that start on the canvas background pan; nodes keep their own pointer events.\n // Shift-drags are left to the app, for a selection box.\n if ((event.button !== 0 && event.button !== 1) || event.shiftKey) return;\n if (\n event.target !== element &&\n !(event.target as Element).hasAttribute?.('data-gpucanvas-surface')\n )\n return;\n drag = { pointerId: event.pointerId, x: event.clientX, y: event.clientY };\n element.setPointerCapture(event.pointerId);\n };\n const onPointerMove = (event: PointerEvent) => {\n if (!drag || event.pointerId !== drag.pointerId) return;\n const camera = getCamera();\n onChange({\n ...camera,\n x: camera.x - (event.clientX - drag.x) / camera.zoom,\n y: camera.y - (event.clientY - drag.y) / camera.zoom,\n });\n drag.x = event.clientX;\n drag.y = event.clientY;\n };\n const onPointerUp = (event: PointerEvent) => {\n if (drag?.pointerId === event.pointerId) drag = null;\n };\n\n element.addEventListener('wheel', onWheel, { passive: false });\n element.addEventListener('pointerdown', onPointerDown);\n element.addEventListener('pointermove', onPointerMove);\n element.addEventListener('pointerup', onPointerUp);\n element.addEventListener('pointercancel', onPointerUp);\n return () => {\n element.removeEventListener('wheel', onWheel);\n element.removeEventListener('pointerdown', onPointerDown);\n element.removeEventListener('pointermove', onPointerMove);\n element.removeEventListener('pointerup', onPointerUp);\n element.removeEventListener('pointercancel', onPointerUp);\n };\n}\n","/**\n * Shader effects on live nodes. An effect is a WGSL function the GPU runs for every pixel of a\n * node's snapshot, so the component stays live DOM while it ripples, glows or dissolves.\n *\n * The function is `fn effect(input: EffectInput) -> vec4f`, returning a premultiplied color:\n *\n * ```wgsl\n * struct EffectInput {\n * uv: vec2f, // 0 to 1 across the node; outside that range in its padding\n * size: vec2f, // the node's size in CSS pixels\n * time: f32, // seconds since the canvas started\n * zoom: f32, // the camera's zoom\n * params: vec4f, // the node's parameters, from setEffect\n * pointer: vec2f, // the pointer, in the node's uv; far away when it is off the canvas\n * press: vec2f, // where the last press landed, in the node's uv\n * sincePress: f32, // seconds since that press\n * }\n * fn source(uv: vec2f) -> vec4f // the node's own pixels, transparent outside 0 to 1\n * fn hash(p: vec2f) -> f32 // a pseudo-random value from 0 to 1\n * fn noise(p: vec2f) -> f32 // smooth value noise from 0 to 1\n * ```\n */\nexport interface Effect {\n readonly name: string;\n readonly wgsl: string;\n /** Runs every frame while a node wearing it is in view, for effects that use `time`. */\n readonly animated: boolean;\n /** Parameters a node gets when `setEffect` leaves them out, up to four. */\n readonly params: readonly number[];\n /** How far past its node the effect draws, in CSS pixels: a glow's reach, a blur's spread. */\n readonly pad: number | ((params: readonly number[]) => number);\n /**\n * The same look as a CSS `filter`, for the DOM backend. Effects without one show their node\n * unchanged there.\n */\n readonly css?: (params: readonly number[], time: number) => string;\n /** Seconds an animated CSS look takes to repeat. Default 4. */\n readonly period?: number;\n}\n\nexport interface EffectDefinition {\n name: string;\n wgsl: string;\n animated?: boolean;\n params?: readonly number[];\n pad?: Effect['pad'];\n css?: Effect['css'];\n period?: number;\n}\n\nexport const defineEffect = (definition: EffectDefinition): Effect =>\n Object.freeze({\n animated: false,\n params: [],\n pad: 0,\n ...definition,\n });\n\n/** Four parameters: the ones given, then the effect's defaults, then zero. */\nexport const effectParams = (effect: Effect, params?: ArrayLike<number>): number[] =>\n [0, 1, 2, 3].map((i) => params?.[i] ?? effect.params[i] ?? 0);\n\nexport const effectPad = (effect: Effect, params: readonly number[]) =>\n typeof effect.pad === 'function' ? effect.pad(params) : effect.pad;\n\n/** CSS's hue-rotate matrix, so the GPU and DOM looks match. */\nconst HUE_ROTATE = /* wgsl */ `\nfn hueRotate(color: vec3f, degrees: f32) -> vec3f {\n let c = cos(radians(degrees));\n let s = sin(radians(degrees));\n let m = mat3x3f(\n vec3f(0.213 + 0.787 * c - 0.213 * s, 0.213 - 0.213 * c + 0.143 * s, 0.213 - 0.213 * c - 0.787 * s),\n vec3f(0.715 - 0.715 * c - 0.715 * s, 0.715 + 0.285 * c + 0.140 * s, 0.715 - 0.715 * c + 0.715 * s),\n vec3f(0.072 - 0.072 * c + 0.928 * s, 0.072 - 0.072 * c - 0.283 * s, 0.072 + 0.928 * c + 0.072 * s),\n );\n return m * color;\n}\n`;\n\n/** Cycles hues. Parameters: degrees per second (default 90). */\nexport const hue = defineEffect({\n name: 'hue',\n animated: true,\n params: [90],\n wgsl: /* wgsl */ `${HUE_ROTATE}\nfn effect(input: EffectInput) -> vec4f {\n let color = source(input.uv);\n return vec4f(clamp(hueRotate(color.rgb, input.time * input.params.x), vec3f(0.0), vec3f(color.a)), color.a);\n}`,\n css: ([speed], time) => `hue-rotate(${((time * speed) % 360).toFixed(1)}deg)`,\n});\n\n/** Gray. Parameters: amount, 0 to 1 (default 1). */\nexport const grayscale = defineEffect({\n name: 'grayscale',\n params: [1],\n wgsl: /* wgsl */ `\nfn effect(input: EffectInput) -> vec4f {\n let color = source(input.uv);\n let gray = dot(color.rgb, vec3f(0.2126, 0.7152, 0.0722));\n return vec4f(mix(color.rgb, vec3f(gray), input.params.x), color.a);\n}`,\n css: ([amount]) => `grayscale(${amount})`,\n});\n\n/** Blur over 32 taps on a disk. Parameters: radius in CSS pixels (default 6). */\nexport const blur = defineEffect({\n name: 'blur',\n params: [6],\n pad: ([radius]) => radius,\n wgsl: /* wgsl */ `\nfn effect(input: EffectInput) -> vec4f {\n let radius = input.params.x / input.size;\n var color = vec4f(0.0);\n var weight = 0.0;\n // A Vogel spiral: even coverage of the disk with few taps.\n for (var i = 0u; i < 32u; i++) {\n let r = sqrt((f32(i) + 0.5) / 32.0);\n let a = f32(i) * 2.39996;\n let w = exp(-2.0 * r * r);\n color += source(input.uv + vec2f(cos(a), sin(a)) * r * radius) * w;\n weight += w;\n }\n return color / weight;\n}`,\n css: ([radius]) => `blur(${radius / 2}px)`,\n});\n\n/**\n * A breathing glow around the node's shape. Parameters: red, green, blue (0 to 1) and reach in\n * CSS pixels (default a blue 24 px).\n */\nexport const glow = defineEffect({\n name: 'glow',\n animated: true,\n params: [0.31, 0.55, 1, 24],\n pad: (params) => params[3],\n period: Math.PI,\n wgsl: /* wgsl */ `\nfn effect(input: EffectInput) -> vec4f {\n let color = source(input.uv);\n let reach = input.params.w * (0.65 + 0.35 * sin(input.time * 2.0));\n // How much of the shape lies within reach, sampled on two rings.\n var cover = 0.0;\n for (var i = 0u; i < 24u; i++) {\n let a = f32(i) * 0.2618;\n let r = select(0.5, 1.0, i % 2u == 0u);\n cover += source(input.uv + vec2f(cos(a), sin(a)) * r * reach / input.size).a;\n }\n let alpha = smoothstep(0.0, 1.0, cover / 24.0) * 0.9;\n return color + vec4f(input.params.rgb * alpha, alpha) * (1.0 - color.a);\n}`,\n css: ([r, g, b, reach], time) => {\n const radius = reach * (0.65 + 0.35 * Math.sin(time * 2));\n const rgb = [r, g, b].map((v) => Math.round(v * 255)).join(' ');\n return `drop-shadow(0 0 ${(radius / 2).toFixed(1)}px rgb(${rgb} / 0.9))`;\n },\n});\n\n/** Rings spreading from the center. Parameters: amplitude and wavelength in CSS pixels (6, 90). */\nexport const ripple = defineEffect({\n name: 'ripple',\n animated: true,\n params: [6, 90],\n pad: ([amplitude]) => amplitude,\n wgsl: /* wgsl */ `\nfn effect(input: EffectInput) -> vec4f {\n let p = (input.uv - 0.5) * input.size;\n let d = length(p);\n let wave = sin(d / input.params.y * 6.2832 - input.time * 4.0);\n let push = select(vec2f(0.0), p / d, d > 0.001) * wave * input.params.x;\n let color = source(input.uv + push / input.size);\n return vec4f(color.rgb * (1.0 + 0.06 * wave), color.a);\n}`,\n});\n\n/** Big pixels. Parameters: block size in CSS pixels (default 8). */\nexport const pixelate = defineEffect({\n name: 'pixelate',\n params: [8],\n wgsl: /* wgsl */ `\nfn effect(input: EffectInput) -> vec4f {\n let block = max(input.params.x, 1.0);\n let cell = (floor(input.uv * input.size / block) + 0.5) * block;\n return source(cell / input.size);\n}`,\n});\n\n/**\n * Burns away along noise with a glowing edge, for a node leaving or arriving. Parameters:\n * progress, 0 (whole) to 1 (gone).\n */\nexport const dissolve = defineEffect({\n name: 'dissolve',\n params: [0.5],\n wgsl: /* wgsl */ `\nfn effect(input: EffectInput) -> vec4f {\n let color = source(input.uv);\n let p = input.uv * input.size / 24.0;\n let n = noise(p) * 0.65 + noise(p * 2.7) * 0.35;\n let edge = n - (input.params.x * 1.2 - 0.1);\n let keep = smoothstep(0.0, 0.02, edge);\n let burn = (1.0 - smoothstep(0.0, 0.08, edge)) * keep;\n return color * keep + vec4f(1.0, 0.45, 0.1, 1.0) * burn * color.a;\n}`,\n css: ([progress]) => `opacity(${1 - progress})`,\n});\n\n/**\n * A glass lens that follows the pointer, magnifying what is under it with a colored rim.\n * Parameters: radius in CSS pixels and magnification (default 110, 1.8).\n */\nexport const glass = defineEffect({\n name: 'glass',\n animated: true,\n params: [110, 1.8],\n wgsl: /* wgsl */ `\nfn effect(input: EffectInput) -> vec4f {\n let d = (input.uv - input.pointer) * input.size;\n let radius = input.params.x;\n let t = length(d) / radius;\n if (t >= 1.0) {\n let shadow = (1.0 - smoothstep(1.0, 1.12, t)) * 0.18;\n let under = source(input.uv);\n return vec4f(under.rgb * (1.0 - shadow), under.a);\n }\n // A dome: strongest at the center, flattening to no change at the rim.\n let scale = mix(1.0 / input.params.y, 1.0, t * t * t);\n let bent = input.pointer + d * scale / input.size;\n let fringe = d / radius * (t * t * 6.0) / input.size;\n let middle = source(bent);\n var color = vec4f(source(bent + fringe).r, middle.g, source(bent - fringe).b, middle.a);\n // A bright rim and a highlight up and to the left.\n let rim = smoothstep(0.86, 0.97, t) * (1.0 - smoothstep(0.985, 1.0, t));\n let shine = pow(max(0.0, 1.0 - length(d / radius - vec2f(-0.38, -0.42)) / 0.42), 2.0);\n // Light catches the upper left of the rim, and the lower right falls into shade.\n let side = dot(normalize(d + vec2f(0.0001)), vec2f(-0.7071, -0.7071));\n let light = rim * (0.25 + 0.35 * side) + shine * 0.3;\n let shade = rim * max(0.0, -side) * 0.25;\n color = vec4f(color.rgb * (1.0 - shade), color.a);\n color = color + vec4f(light, light, light, light) * (1.0 - color.a * 0.4);\n return min(color, vec4f(1.0));\n}`,\n});\n\n/**\n * A ring of light that bends the node as it spreads from each press. Parameters: speed in CSS\n * pixels per second, ring width and push (default 900, 60, 18).\n */\nexport const shockwave = defineEffect({\n name: 'shockwave',\n animated: true,\n params: [900, 60, 18],\n wgsl: /* wgsl */ `\nfn effect(input: EffectInput) -> vec4f {\n let fade = exp(-input.sincePress * 1.6);\n if (fade < 0.01) {\n return source(input.uv);\n }\n let d = (input.uv - input.press) * input.size;\n let dist = length(d);\n let x = (dist - input.sincePress * input.params.x) / input.params.y;\n let ring = exp(-x * x);\n let push = select(vec2f(0.0), d / dist, dist > 0.001) * sin(x * 2.5) * ring * input.params.z * fade;\n let offset = push / input.size;\n let middle = source(input.uv - offset);\n let color = vec4f(source(input.uv - offset * 1.4).r, middle.g, source(input.uv - offset * 0.6).b, middle.a);\n return color + vec4f(0.45, 0.65, 1.0, 1.0) * ring * fade * 0.25 * middle.a;\n}`,\n});\n\n/** Broadcast glitches: torn rows, split color channels and corrupted blocks, in bursts. */\nexport const glitch = defineEffect({\n name: 'glitch',\n animated: true,\n wgsl: /* wgsl */ `\nfn effect(input: EffectInput) -> vec4f {\n // Every node glitches on its own schedule.\n let own = hash(input.size);\n let tick = floor(input.time * 12.0 + own * 50.0);\n let burst = step(0.82, hash(vec2f(floor(tick / 3.0), own)));\n if (burst == 0.0) {\n return source(input.uv);\n }\n let row = floor(input.uv.y * mix(12.0, 40.0, hash(vec2f(tick, 1.0))));\n let tear = step(0.6, hash(vec2f(row, tick))) * (hash(vec2f(row, tick + 7.0)) - 0.5) * 0.06;\n let uv = vec2f(input.uv.x + tear, input.uv.y);\n let split = vec2f(0.012 * hash(vec2f(tick, 3.0)), 0.0);\n let middle = source(uv);\n var color = vec4f(source(uv + split).r, middle.g, source(uv - split).b, middle.a);\n // A few blocks show pixels from elsewhere, with their channels swapped.\n let block = floor(input.uv * vec2f(14.0, 8.0));\n if (hash(block + vec2f(tick)) > 0.975) {\n let moved = source(fract(input.uv + vec2f(hash(block), hash(block + 9.0)) * 0.3));\n color = vec4f(moved.brg, moved.a);\n }\n return color;\n}`,\n});\n\n/** Worn tape: a wavering picture, color bleeding sideways, a rolling band, noise and grain. */\nexport const vhs = defineEffect({\n name: 'vhs',\n animated: true,\n wgsl: /* wgsl */ `\nfn effect(input: EffectInput) -> vec4f {\n let y = input.uv.y;\n let t = input.time;\n var wave = sin(y * 38.0 + t * 3.0) * 0.0012 + sin(y * 6.0 - t * 1.3) * 0.002;\n // Head-switching noise along the bottom.\n let bottom = smoothstep(0.93, 1.0, y);\n wave += bottom * (hash(vec2f(floor(y * 180.0), floor(t * 30.0))) - 0.5) * 0.04;\n let uv = vec2f(input.uv.x + wave, y);\n let bleed = vec2f(3.0 / input.size.x, 0.0);\n let middle = source(uv);\n var color = vec4f(source(uv + bleed).r, middle.g, source(uv - bleed * 1.5).b, middle.a);\n // Softer, warmer and a little washed out.\n let gray = dot(color.rgb, vec3f(0.299, 0.587, 0.114));\n color = vec4f(mix(vec3f(gray), color.rgb, 0.8) * vec3f(1.04, 1.0, 0.92), color.a);\n let band = smoothstep(0.08, 0.0, abs(fract(y * 0.6 - t * 0.12) - 0.5));\n let lines = 0.94 + 0.06 * sin(y * input.size.y * 3.1416);\n let grain = (hash(input.uv * input.size + vec2f(t * 97.0, t * 61.0)) - 0.5) * 0.12;\n return vec4f(clamp(color.rgb * lines + (band * 0.08 + grain) * color.a, vec3f(0.0), vec3f(color.a)), color.a);\n}`,\n});\n\n/**\n * Ice over the node, clear where the pointer is. Parameters: the clear radius in CSS pixels\n * (default 140).\n */\nexport const frost = defineEffect({\n name: 'frost',\n animated: true,\n params: [140],\n wgsl: /* wgsl */ `\nfn effect(input: EffectInput) -> vec4f {\n let p = input.uv * input.size;\n let dist = length((input.uv - input.pointer) * input.size);\n let edge = noise(p / 40.0) * 50.0;\n let ice = smoothstep(input.params.x * 0.55, input.params.x * 1.2, dist + edge);\n if (ice <= 0.0) {\n return source(input.uv);\n }\n // Frosted glass: the node seen blurred and bent through uneven ice.\n let thick = noise(p / 90.0) * 0.6 + noise(p / 23.0) * 0.4;\n let bend = (vec2f(noise(p / 14.0), noise(p / 14.0 + 31.0)) - 0.5) * 6.0 * ice;\n var color = vec4f(0.0);\n for (var i = 0u; i < 8u; i++) {\n let a = f32(i) * 0.7854 + 0.4;\n let r = select(3.0, 6.0, i % 2u == 0u) * ice;\n color += source((p + bend + vec2f(cos(a), sin(a)) * r) / input.size);\n }\n color /= 8.0;\n let white = vec4f(0.9, 0.95, 1.0, 1.0) * color.a;\n // Feathery crystals and a few glints.\n let crystals = smoothstep(0.7, 0.95, noise(p / 12.0 + noise(p / 40.0) * 2.0)) * 0.1;\n let glint = step(0.997, hash(floor(p / 1.5))) * 0.8;\n let frosted = mix(color, white, (0.3 + thick * 0.25) * ice);\n return min(frosted + vec4f((crystals + glint) * ice) * color.a, vec4f(color.a));\n}`,\n});\n\n/**\n * A lens that redraws what is under the pointer in big dithered pixels and a few colors.\n * Parameters: radius and pixel size in CSS pixels (default 130, 4).\n */\nexport const dither = defineEffect({\n name: 'dither',\n animated: true,\n params: [130, 4],\n wgsl: /* wgsl */ `\nfn effect(input: EffectInput) -> vec4f {\n let p = input.uv * input.size;\n let dist = length((input.uv - input.pointer) * input.size);\n let radius = input.params.x;\n if (dist > radius + 1.5) {\n return source(input.uv);\n }\n let block = max(input.params.y, 1.0);\n let cell = floor(p / block);\n let base = source((cell + 0.5) * block / input.size);\n var bayer = array<f32, 16>(0.0, 8.0, 2.0, 10.0, 12.0, 4.0, 14.0, 6.0, 3.0, 11.0, 1.0, 9.0, 15.0, 7.0, 13.0, 5.0);\n let index = u32(cell.x) % 4u + (u32(cell.y) % 4u) * 4u;\n let threshold = (bayer[index] + 0.5) / 16.0 - 0.5;\n // Two levels per channel: eight colors, mixed by the pattern.\n let straight = base.rgb / max(base.a, 0.0001);\n let levels = floor(clamp(straight + threshold * 0.6, vec3f(0.0), vec3f(1.0)) + 0.5);\n let dithered = vec4f(levels * base.a, base.a);\n let ring = 1.0 - smoothstep(0.0, 1.5, abs(dist - radius));\n return mix(dithered, vec4f(0.1, 0.1, 0.12, 1.0), ring * 0.8);\n}`,\n});\n\nexport const EFFECTS = {\n glass,\n shockwave,\n glitch,\n vhs,\n frost,\n dither,\n glow,\n hue,\n ripple,\n blur,\n pixelate,\n dissolve,\n grayscale,\n} as const;\n","import type { Point, Rect } from './camera';\n\n/*\n * Elements inside nodes. A node's layout stays current even while its page is parked, so an\n * element's box relative to its node, scaled by the node's world size, is its place in the world.\n * The scale also cancels whatever transform the backend puts on the node.\n */\n\n/** Where `element`, inside the node `node` placed at `nodeRect`, sits in world units. */\nexport function rectInNode(node: HTMLElement, nodeRect: Rect, element: Element): Rect {\n if (element === node) return { ...nodeRect };\n const outer = node.getBoundingClientRect();\n const inner = element.getBoundingClientRect();\n const scale = outer.width > 0 ? nodeRect.width / outer.width : 1;\n return {\n x: nodeRect.x + (inner.left - outer.left) * scale,\n y: nodeRect.y + (inner.top - outer.top) * scale,\n width: inner.width * scale,\n height: inner.height * scale,\n };\n}\n\n/**\n * The deepest element of `node` under the world point `point`. It descends through the children\n * whose boxes hold the point, the last one first, since later siblings paint on top.\n */\nexport function elementInNode(node: HTMLElement, nodeRect: Rect, point: Point): Element {\n const outer = node.getBoundingClientRect();\n const scale = nodeRect.width > 0 ? outer.width / nodeRect.width : 1;\n const x = outer.left + (point.x - nodeRect.x) * scale;\n const y = outer.top + (point.y - nodeRect.y) * scale;\n let hit: Element = node;\n descend: for (;;) {\n for (let child = hit.lastElementChild; child; child = child.previousElementSibling) {\n const box = child.getBoundingClientRect();\n if (\n box.width > 0 &&\n box.height > 0 &&\n x >= box.left &&\n x < box.right &&\n y >= box.top &&\n y < box.bottom\n ) {\n hit = child;\n continue descend;\n }\n }\n return hit;\n }\n}\n\n/** The node that holds `element`: the element itself or its nearest ancestor in `nodes`. */\nexport function nodeOfElement<T>(nodes: Map<HTMLElement, T>, element: Element): HTMLElement | null {\n for (let at: Element | null = element; at; at = at.parentElement) {\n if (nodes.has(at as HTMLElement)) return at as HTMLElement;\n }\n return null;\n}\n","import type { Rect } from './camera';\n\n/** Sizes a node's element; containment keeps one node's changes from relaying out the others. */\nexport function applyNodeSize(element: HTMLElement, rect: Rect) {\n element.style.width = `${rect.width}px`;\n element.style.height = `${rect.height}px`;\n}\n\nexport function applyNodeBase(element: HTMLElement) {\n element.style.boxSizing = 'border-box';\n element.style.contain = 'strict';\n element.style.overflow = 'hidden';\n}\n\nexport function boundsOf(rects: Iterable<Rect>): Rect | null {\n let minX = Infinity,\n minY = Infinity,\n maxX = -Infinity,\n maxY = -Infinity;\n for (const rect of rects) {\n minX = Math.min(minX, rect.x);\n minY = Math.min(minY, rect.y);\n maxX = Math.max(maxX, rect.x + rect.width);\n maxY = Math.max(maxY, rect.y + rect.height);\n }\n return minX === Infinity ? null : { x: minX, y: minY, width: maxX - minX, height: maxY - minY };\n}\n","import type { Camera, Point, Rect } from './camera';\nimport type { Effect } from './effects';\n\nexport type GpuCanvasMode = 'gpu' | 'dom';\n\nexport interface GpuCanvasOptions {\n /** `auto` uses the GPU path when WebGPU and HTML-in-Canvas are available, otherwise DOM. */\n mode?: 'auto' | GpuCanvasMode;\n /** Canvas background, any CSS color. */\n background?: string;\n /** Outline of selected elements, any CSS color. Default `#4f8cff`. */\n selectionColor?: string;\n /** Outline of the hovered element, any CSS color. Default: the selection color. */\n hoverColor?: string;\n camera?: Camera;\n /** Side of each atlas layer in texels. Default 4096, capped by the device. */\n atlasSize?: number;\n /** Atlas layers; each 4096 layer costs 64 MB of GPU memory. One holds thumbnails. Default 5. */\n atlasLayers?: number;\n /** Most snapshot pixels rasterized per frame; the rest wait for later frames. Default 24M. */\n rasterPixelBudget?: number;\n /** Most raster calls per frame; one call covers a whole page or one node. Default 12. */\n maxRastersPerFrame?: number;\n /** Main-thread milliseconds a frame may spend issuing rasters. Default 6. */\n rasterTimeBudgetMs?: number;\n /** Side of a page, the unit nodes are batched into for rasterizing, in CSS pixels. Default 2048. */\n pageSize?: number;\n onCameraChange?: (camera: Camera) => void;\n}\n\nexport interface GpuCanvasStats {\n mode: GpuCanvasMode;\n nodes: number;\n visible: number;\n /** Visible nodes still waiting for a snapshot at the current zoom. */\n pending: number;\n /** Nodes that got fresh pixels in the last frame. */\n rasterizedLastFrame: number;\n /** Raster calls in the last frame (gpu only). */\n rasterCallsLastFrame?: number;\n /** Main-thread milliseconds the last frame spent issuing rasters. */\n rasterMs: number;\n /** Pages nodes are batched into, and how many are drawable right now (gpu only). */\n pages?: number;\n drawablePages?: number;\n atlasLayersUsed: number;\n /** Main-thread milliseconds the last composite took. */\n frameMs: number;\n /** Frames composited since creation (gpu only). An idle canvas draws none. */\n frames?: number;\n /** Times a visible node that had pixels showed a placeholder instead: visible flicker. */\n lostPixels?: number;\n /** Times a sharp zoomed-in node fell back to its blurrier whole snapshot. */\n lostDetail?: number;\n /** Share of the thumbnail layer in use, 0 to 1 (gpu only). */\n thumbnailFill?: number;\n /** Visible nodes showing only their thumbnail while a sharper snapshot is drawn (gpu only). */\n onThumbnail?: number;\n /** Visible nodes the last frame planned to rasterize: missing, dirty, blurry, oversampled. */\n needs?: number[];\n}\n\nexport interface GpuCanvas {\n readonly mode: GpuCanvasMode;\n /** The element that receives camera input; the host's only child. */\n readonly surface: HTMLElement;\n /** Places `element` on the canvas at `rect` (world units). The element keeps its own DOM and events. */\n addNode(element: HTMLElement, rect: Rect): void;\n updateNode(element: HTMLElement, rect: Rect): void;\n removeNode(element: HTMLElement): void;\n /** Where `element` sits on the canvas, in world units, or null when it is not a node. */\n getNodeRect(element: HTMLElement): Rect | null;\n /** Nodes that overlap `rect` (world units), such as the ones under a selection box. */\n getNodesIn(rect: Rect): HTMLElement[];\n /** The node that holds `element`: the element itself when it is a node, or null. */\n getNodeOf(element: Element): HTMLElement | null;\n /** Where any element on the canvas sits, a node or anything inside one, in world units. */\n getElementRect(element: Element): Rect | null;\n /** The deepest element under the world point `point`, in the topmost node there. */\n getElementAt(point: Point): Element | null;\n /**\n * Outlines these elements as selected, replacing the previous selection. They can be nodes or\n * anything inside them, and the outlines follow their layout. Pass `[]` to clear.\n */\n setSelection(elements: Iterable<Element>): void;\n /** Outlines one element more lightly, such as the one under the pointer. Pass null to clear. */\n setHover(element: Element | null): void;\n /**\n * Draws a node through a shader effect, such as \\`ripple\\` or one from \\`defineEffect\\`, with up to\n * four parameters (the effect's defaults otherwise). Pass null to remove it. The DOM backend\n * shows effects that have a CSS look as a \\`filter\\` and ignores the rest.\n */\n setEffect(node: HTMLElement, effect: Effect | null, params?: ArrayLike<number>): void;\n getCamera(): Camera;\n setCamera(camera: Camera): void;\n /** A point in surface pixels as world units, under the current camera. */\n screenToWorld(point: Point): Point;\n /** A world point as surface pixels, under the current camera. */\n worldToScreen(point: Point): Point;\n /**\n * Redraws every node. Call it after a change the nodes' own DOM does not show, such as a theme\n * class on `<html>` or a web font finishing loading.\n */\n invalidate(): void;\n /** Changes the canvas background, any CSS color. */\n setBackground(color: string): void;\n /** Fits all nodes in view. */\n fit(padding?: number): void;\n getStats(): GpuCanvasStats;\n destroy(): void;\n}\n\nexport const DEFAULT_CAMERA: Camera = { x: 0, y: 0, zoom: 1 };\nexport const DEFAULT_SELECTION_COLOR = '#4f8cff';\n/** Width of the selection outline, in CSS pixels at any zoom. */\nexport const SELECTION_WIDTH = 2;\n/** Width of the hover outline, in CSS pixels at any zoom. */\nexport const HOVER_WIDTH = 1;\n","import {\n bindCameraInput,\n containsPoint,\n fitCamera,\n intersects,\n screenToWorld,\n visibleWorldRect,\n worldToScreen,\n type Camera,\n type Rect,\n} from './camera';\nimport { effectParams, type Effect } from './effects';\nimport { elementInNode, nodeOfElement, rectInNode } from './elements';\nimport { applyNodeBase, applyNodeSize, boundsOf } from './node-style';\nimport {\n DEFAULT_CAMERA,\n DEFAULT_SELECTION_COLOR,\n HOVER_WIDTH,\n SELECTION_WIDTH,\n type GpuCanvas,\n type GpuCanvasOptions,\n} from './types';\n\n/**\n * The fallback, and the way most infinite canvases work today: every node is absolutely\n * positioned inside one world element that the camera moves with a CSS transform.\n */\nexport function createDomCanvas(host: HTMLElement, options: GpuCanvasOptions): GpuCanvas {\n const surface = document.createElement('div');\n surface.dataset.gpucanvasSurface = '';\n Object.assign(surface.style, {\n position: 'relative',\n width: '100%',\n height: '100%',\n overflow: 'hidden',\n touchAction: 'none',\n background: options.background ?? 'transparent',\n });\n const world = document.createElement('div');\n world.dataset.gpucanvasSurface = '';\n Object.assign(world.style, {\n position: 'absolute',\n left: '0',\n top: '0',\n transformOrigin: '0 0',\n willChange: 'transform',\n });\n // Outlines of elements inside nodes, above every node.\n const overlay = document.createElement('div');\n Object.assign(overlay.style, { position: 'absolute', left: '0', top: '0', zIndex: '1' });\n world.append(overlay);\n surface.append(world);\n host.append(surface);\n\n const nodes = new Map<HTMLElement, Rect>();\n // Outlines live inside the zoomed world, so their width divides the zoom back out.\n const ring = (color: string, width: number) =>\n `calc(${width}px / var(--gpucanvas-zoom)) solid ${color}`;\n const selectionColor = options.selectionColor ?? DEFAULT_SELECTION_COLOR;\n const selectionRing = ring(selectionColor, SELECTION_WIDTH);\n const hoverRing = ring(options.hoverColor ?? selectionColor, HOVER_WIDTH);\n let selection = new Set<Element>();\n let hovered: Element | null = null;\n /** Nodes wearing an outline, and boxes standing in for the outlines of elements inside nodes. */\n let outlinedNodes = new Set<HTMLElement>();\n const boxes = new Map<Element, HTMLElement>();\n const elementRect = (element: Element): Rect | null => {\n const node = element.isConnected ? nodeOfElement(nodes, element) : null;\n return node ? rectInNode(node, nodes.get(node)!, element) : null;\n };\n // Boxes follow their elements' layout every frame while there are any.\n let boxFrame = 0;\n const placeBoxes = () => {\n boxFrame = boxes.size ? requestAnimationFrame(placeBoxes) : 0;\n for (const [element, box] of boxes) {\n const rect = elementRect(element);\n box.style.display = rect ? 'block' : 'none';\n if (rect) {\n box.style.transform = `translate(${rect.x}px, ${rect.y}px)`;\n box.style.width = `${rect.width}px`;\n box.style.height = `${rect.height}px`;\n }\n }\n };\n const drawOutlines = () => {\n const wanted = new Map<Element, string>();\n for (const element of selection) wanted.set(element, selectionRing);\n if (hovered && !wanted.has(hovered)) wanted.set(hovered, hoverRing);\n const nextNodes = new Set<HTMLElement>();\n for (const [element, outline] of wanted) {\n if (!nodes.has(element as HTMLElement)) continue;\n (element as HTMLElement).style.outline = outline;\n nextNodes.add(element as HTMLElement);\n }\n for (const node of outlinedNodes) if (!nextNodes.has(node)) node.style.outline = '';\n outlinedNodes = nextNodes;\n for (const [element, box] of boxes) {\n if (wanted.has(element)) continue;\n box.remove();\n boxes.delete(element);\n }\n for (const [element, outline] of wanted) {\n if (nodes.has(element as HTMLElement)) continue;\n let box = boxes.get(element);\n if (!box) {\n box = document.createElement('div');\n Object.assign(box.style, {\n position: 'absolute',\n left: '0',\n top: '0',\n pointerEvents: 'none',\n });\n overlay.append(box);\n boxes.set(element, box);\n }\n box.style.outline = outline;\n }\n if (boxes.size && !boxFrame) placeBoxes();\n };\n /** Animated CSS looks, run by the browser as filter animations. */\n const animations = new Map<HTMLElement, Animation>();\n const KEYFRAMES = 24;\n const clearEffect = (element: HTMLElement) => {\n animations.get(element)?.cancel();\n animations.delete(element);\n element.style.filter = '';\n };\n const applyEffect = (element: HTMLElement, effect: Effect | null, params?: ArrayLike<number>) => {\n clearEffect(element);\n if (!effect?.css) return;\n const values = effectParams(effect, params);\n if (!effect.animated) {\n element.style.filter = effect.css(values, 0);\n return;\n }\n const period = effect.period ?? 4;\n const keyframes = Array.from({ length: KEYFRAMES + 1 }, (_, i) => ({\n filter: effect.css!(values, (i / KEYFRAMES) * period),\n }));\n animations.set(\n element,\n element.animate(keyframes, { duration: period * 1000, iterations: Infinity }),\n );\n };\n let camera = options.camera ?? DEFAULT_CAMERA;\n let frameMs = 0;\n\n const apply = () => {\n const start = performance.now();\n world.style.transform = `scale(${camera.zoom}) translate(${-camera.x}px, ${-camera.y}px)`;\n world.style.setProperty('--gpucanvas-zoom', String(camera.zoom));\n frameMs = performance.now() - start;\n };\n const setCamera = (next: Camera) => {\n camera = next;\n apply();\n options.onCameraChange?.(camera);\n };\n const unbindInput = bindCameraInput(surface, () => camera, setCamera);\n apply();\n\n return {\n mode: 'dom',\n surface,\n addNode(element, rect) {\n applyNodeBase(element);\n element.style.position = 'absolute';\n nodes.set(element, rect);\n this.updateNode(element, rect);\n world.append(element);\n },\n updateNode(element, rect) {\n nodes.set(element, rect);\n element.style.left = `${rect.x}px`;\n element.style.top = `${rect.y}px`;\n applyNodeSize(element, rect);\n },\n removeNode(element) {\n clearEffect(element);\n nodes.delete(element);\n outlinedNodes.delete(element);\n element.style.outline = '';\n element.remove();\n },\n getNodeRect: (element) => nodes.get(element) ?? null,\n getNodesIn(rect) {\n return [...nodes].filter(([, node]) => intersects(node, rect)).map(([element]) => element);\n },\n getNodeOf: (element) => nodeOfElement(nodes, element),\n getElementRect: elementRect,\n getElementAt(point) {\n // The last node added draws on top.\n let top: HTMLElement | null = null;\n for (const [element, rect] of nodes) if (containsPoint(rect, point)) top = element;\n return top ? elementInNode(top, nodes.get(top)!, point) : null;\n },\n setSelection(elements) {\n selection = new Set(elements);\n drawOutlines();\n },\n setHover(element) {\n if (element === hovered) return;\n hovered = element;\n drawOutlines();\n },\n setEffect(element, effect, params) {\n if (nodes.has(element)) applyEffect(element, effect, params);\n },\n getCamera: () => camera,\n setCamera,\n screenToWorld: (point) => screenToWorld(camera, point),\n worldToScreen: (point) => worldToScreen(camera, point),\n // The browser repaints DOM nodes itself.\n invalidate() {},\n setBackground(color) {\n surface.style.background = color;\n },\n fit(padding) {\n const bounds = boundsOf(nodes.values());\n if (bounds) setCamera(fitCamera(bounds, surface.clientWidth, surface.clientHeight, padding));\n },\n getStats() {\n const view = visibleWorldRect(camera, surface.clientWidth, surface.clientHeight);\n let visible = 0;\n for (const rect of nodes.values()) if (intersects(rect, view)) visible++;\n return {\n mode: 'dom',\n nodes: nodes.size,\n visible,\n pending: 0,\n rasterizedLastFrame: 0,\n rasterMs: 0,\n atlasLayersUsed: 0,\n frameMs,\n };\n },\n destroy() {\n cancelAnimationFrame(boxFrame);\n unbindInput();\n surface.remove();\n },\n };\n}\n","/** A rectangle in one layer of the atlas texture array, in texels. */\nexport interface AtlasSlot {\n layer: number;\n x: number;\n y: number;\n width: number;\n height: number;\n /** Bumped when the layer is evicted; a slot is valid while it matches the layer's generation. */\n generation: number;\n}\n\ninterface Shelf {\n y: number;\n height: number;\n x: number;\n}\n\ninterface Layer {\n shelves: Shelf[];\n nextY: number;\n generation: number;\n /** Frame number of the last allocation in, or draw from, this layer; the stalest is evicted. */\n lastUsed: number;\n /** Frame number of the last allocation; a layer filled this frame is never evicted. */\n lastAllocated: number;\n}\n\nconst PADDING = 1;\n\n/**\n * Shelf packer over the layers of one texture array. Nothing is freed individually: when every\n * layer is full, the least recently used layer is recycled. Its slots that are still on screen\n * (`keep`) are first copied into a spare layer on the GPU, so they never flash; the rest become\n * invalid and are rasterized again the next time they are visible. The recycled layer becomes\n * the new spare.\n *\n * Layer 0 is pinned: it holds small thumbnails that are never recycled (`allocatePinned`), so\n * every node keeps some pixels however much the other layers churn.\n */\nexport class Atlas {\n readonly texture: GPUTexture;\n readonly view: GPUTextureView;\n readonly size: number;\n /** Slots to rescue when their layer is recycled, most important first. */\n keep: () => Iterable<AtlasSlot | null> = () => [];\n private layers: Layer[];\n private spare: number;\n private frame = 0;\n\n constructor(\n private readonly device: GPUDevice,\n size: number,\n layerCount: number,\n ) {\n this.size = size;\n this.texture = device.createTexture({\n label: 'gpucanvas atlas',\n size: [size, size, layerCount],\n format: 'rgba8unorm',\n usage:\n GPUTextureUsage.TEXTURE_BINDING |\n GPUTextureUsage.COPY_SRC |\n GPUTextureUsage.COPY_DST |\n GPUTextureUsage.RENDER_ATTACHMENT,\n });\n this.view = this.texture.createView({ dimension: '2d-array' });\n this.layers = Array.from({ length: layerCount }, () => ({\n shelves: [],\n nextY: 0,\n generation: 0,\n lastUsed: -1,\n lastAllocated: -1,\n }));\n this.spare = layerCount - 1;\n }\n\n /** The layer `allocatePinned` fills; it is never recycled. */\n readonly pinned = 0;\n\n get layerCount() {\n return this.layers.length;\n }\n\n get usedLayers() {\n return this.layers.filter((layer, index) => index !== this.spare && layer.nextY > 0).length;\n }\n\n /** How much of the pinned layer is taken, 0 to 1. */\n get pinnedFill() {\n return this.layers[this.pinned].nextY / this.size;\n }\n\n nextFrame() {\n this.frame++;\n }\n\n /** Marks a layer as drawn from this frame, so eviction prefers others. */\n touch(layer: number) {\n this.layers[layer].lastUsed = this.frame;\n }\n\n isValid(slot: AtlasSlot | null): slot is AtlasSlot {\n return slot !== null && this.layers[slot.layer].generation === slot.generation;\n }\n\n allocate(width: number, height: number): AtlasSlot | null {\n const w = Math.ceil(width) + PADDING;\n const h = Math.ceil(height) + PADDING;\n if (w > this.size || h > this.size) return null;\n for (let index = 0; index < this.layers.length; index++) {\n if (index === this.spare || index === this.pinned) continue;\n const slot = this.allocateIn(index, w, h);\n if (slot) return slot;\n }\n // Never recycle a layer filled this frame: its slots are about to be drawn.\n let stalest = -1;\n for (let index = 0; index < this.layers.length; index++) {\n const layer = this.layers[index];\n if (index === this.spare || index === this.pinned || layer.lastAllocated === this.frame)\n continue;\n if (stalest < 0 || layer.lastUsed < this.layers[stalest].lastUsed) stalest = index;\n }\n if (stalest < 0) return null;\n const target = this.recycle(stalest);\n return this.allocateIn(target, w, h);\n }\n\n /** Space in the pinned layer, or null once it is full. */\n allocatePinned(width: number, height: number): AtlasSlot | null {\n return this.allocateIn(this.pinned, Math.ceil(width) + PADDING, Math.ceil(height) + PADDING);\n }\n\n isPinned(slot: AtlasSlot | null) {\n return slot !== null && slot.layer === this.pinned;\n }\n\n /** Moves the kept slots of `index` into the spare layer, wipes `index`, and swaps the two. */\n private recycle(index: number) {\n const target = this.spare;\n const from = this.layers[index];\n this.evict(target);\n const encoder = this.device.createCommandEncoder({ label: 'gpucanvas atlas rescue' });\n let copies = 0;\n const seen = new Set<AtlasSlot>();\n for (const slot of this.keep()) {\n if (!slot || seen.has(slot) || slot.layer !== index || slot.generation !== from.generation) {\n continue;\n }\n seen.add(slot);\n // Slots cut from a whole page start at fractional texels; copy whole texels around them.\n const x0 = Math.floor(slot.x);\n const y0 = Math.floor(slot.y);\n const x1 = Math.min(this.size, Math.ceil(slot.x + slot.width));\n const y1 = Math.min(this.size, Math.ceil(slot.y + slot.height));\n const moved = this.allocateIn(target, x1 - x0 + PADDING, y1 - y0 + PADDING);\n if (!moved) break;\n encoder.copyTextureToTexture(\n { texture: this.texture, origin: { x: x0, y: y0, z: index } },\n { texture: this.texture, origin: { x: moved.x, y: moved.y, z: target } },\n [x1 - x0, y1 - y0, 1],\n );\n copies++;\n slot.layer = target;\n slot.x = moved.x + (slot.x - x0);\n slot.y = moved.y + (slot.y - y0);\n slot.generation = moved.generation;\n }\n if (copies > 0) this.device.queue.submit([encoder.finish()]);\n this.evict(index);\n this.spare = index;\n return target;\n }\n\n private allocateIn(index: number, w: number, h: number): AtlasSlot | null {\n const layer = this.layers[index];\n let shelf = layer.shelves.find(\n (candidate) =>\n candidate.height >= h && candidate.height <= h * 1.5 && candidate.x + w <= this.size,\n );\n if (!shelf) {\n if (layer.nextY + h > this.size) return null;\n shelf = { y: layer.nextY, height: h, x: 0 };\n layer.shelves.push(shelf);\n layer.nextY += h;\n }\n const slot = {\n layer: index,\n x: shelf.x,\n y: shelf.y,\n width: w - PADDING,\n height: h - PADDING,\n generation: layer.generation,\n };\n shelf.x += w;\n layer.lastUsed = this.frame;\n layer.lastAllocated = this.frame;\n return slot;\n }\n\n private evict(index: number) {\n const layer = this.layers[index];\n layer.shelves = [];\n layer.nextY = 0;\n layer.generation++;\n }\n\n destroy() {\n this.texture.destroy();\n }\n}\n","/**\n * One instanced quad per visible node: its atlas snapshot, or a placeholder until one exists.\n * Outlines (selection, hover) are quads on top, each a ring just outside an element's edge with\n * its own color and width.\n *\n * Snapshots are kept when zooming out, so a quad often covers fewer pixels than its texels.\n * Plain bilinear filtering would then skip texels and shimmer while the camera moves, so the\n * fragment shader takes up to 4 x 4 samples spread over the pixel's footprint (a box filter),\n * clamped to the node's own atlas rectangle so neighbors never bleed in.\n */\nconst prelude = /* wgsl */ `\nstruct View {\n size: vec2f, // canvas size in CSS pixels\n origin: vec2f, // camera position, world units\n zoom: f32,\n dpr: f32,\n atlasSize: f32,\n time: f32, // seconds since the canvas started\n placeholder: vec4f, // premultiplied color for nodes without a snapshot\n pointer: vec4f, // pointer and last press in world units; far away when there is none\n pressTime: f32, // seconds since the last press\n}\n\n@group(0) @binding(0) var<uniform> view: View;\n@group(0) @binding(1) var atlas: texture_2d_array<f32>;\n@group(0) @binding(2) var atlasSampler: sampler;\n\nstruct Instance {\n @location(0) rect: vec4f, // world x, y, width, height\n @location(1) uv: vec4f, // atlas texels x0, y0, x1, y1; for a ring, its premultiplied color\n @location(2) info: vec4f, // layer, kind (0 snapshot, 1 placeholder, 2 ring), ring width or effect pad\n @location(3) params: vec4f, // an effect's parameters\n}\n\nstruct Varyings {\n @builtin(position) position: vec4f,\n @location(0) texel: vec2f,\n @location(1) @interpolate(flat) bounds: vec4f,\n @location(2) @interpolate(flat) info: vec2f,\n @location(3) @interpolate(flat) color: vec4f,\n @location(4) uv: vec2f, // 0 to 1 across the node, past that in an effect's padding\n @location(5) @interpolate(flat) size: vec2f,\n @location(6) @interpolate(flat) params: vec4f,\n @location(7) @interpolate(flat) corner: vec2f, // the node's top left in world units\n}\n\n@vertex\nfn vs(@builtin(vertex_index) vertex: u32, instance: Instance) -> Varyings {\n let corner = vec2f(f32(vertex & 1u), f32(vertex >> 1u));\n // A ring's quad reaches past its element by the ring's width, an effect's by its padding.\n let ring = instance.info.y > 1.5;\n let grow = select(instance.info.z, instance.info.z / view.zoom, ring);\n let start = instance.rect.xy - grow;\n let end = instance.rect.xy + instance.rect.zw + grow;\n // Snap edges to device pixels so a snapshot drawn at its raster scale stays crisp.\n let scale = view.zoom * view.dpr;\n let topLeft = round((start - view.origin) * scale) / view.dpr;\n let bottomRight = round((end - view.origin) * scale) / view.dpr;\n let point = mix(topLeft, bottomRight, corner);\n var out: Varyings;\n out.position = vec4f(point.x / view.size.x * 2.0 - 1.0, 1.0 - point.y / view.size.y * 2.0, 0.0, 1.0);\n if (ring) {\n // World units from the element's top left, and the element's own edges.\n out.texel = mix(vec2f(-grow), instance.rect.zw + grow, corner);\n out.bounds = vec4f(0.0, 0.0, instance.rect.zw);\n out.color = instance.uv;\n } else {\n let pad = grow * (instance.uv.zw - instance.uv.xy) / instance.rect.zw;\n out.texel = mix(instance.uv.xy - pad, instance.uv.zw + pad, corner);\n out.color = instance.uv;\n // Half a texel inside the node's rectangle: the outermost sample center that cannot blend\n // with whatever sits next to it in the atlas.\n out.bounds = vec4f(instance.uv.xy + 0.5, instance.uv.zw - 0.5);\n }\n out.info = instance.info.xy;\n out.uv = mix(-grow / instance.rect.zw, 1.0 + grow / instance.rect.zw, corner);\n out.size = instance.rect.zw;\n out.corner = instance.rect.xy;\n out.params = instance.params;\n return out;\n}\n`;\n\nexport const compositeShader = /* wgsl */ `${prelude}\n@fragment\nfn fs(in: Varyings) -> @location(0) vec4f {\n // Derivatives first: WGSL only allows them in uniform control flow.\n let dx = dpdx(in.texel);\n let dy = dpdy(in.texel);\n if (in.info.y > 1.5) {\n // The ring covers what lies outside the element; the element itself shows through.\n let outside = max(in.bounds.xy - in.texel, in.texel - in.bounds.zw);\n return select(vec4f(0.0), in.color, max(outside.x, outside.y) > 0.0);\n }\n if (in.info.y > 0.5) {\n return view.placeholder;\n }\n let layer = i32(in.info.x);\n // Texels covered by this pixel along each screen axis.\n let footprint = vec2f(length(vec2f(dx.x, dy.x)), length(vec2f(dx.y, dy.y)));\n let taps = vec2u(clamp(ceil(footprint), vec2f(1.0), vec2f(4.0)));\n var color = vec4f(0.0);\n for (var j = 0u; j < taps.y; j++) {\n for (var i = 0u; i < taps.x; i++) {\n let offset = (vec2f(f32(i), f32(j)) + 0.5) / vec2f(taps) - 0.5;\n let texel = clamp(in.texel + offset * footprint, in.bounds.xy, in.bounds.zw);\n color += textureSampleLevel(atlas, atlasSampler, texel / view.atlasSize, layer, 0.0);\n }\n }\n return color / f32(taps.x * taps.y);\n}\n`;\n\n/**\n * A node wearing an effect: the effect's WGSL, given its node's pixels through \\`source\\`. Effects\n * read the whole snapshot, never sharper tiles, so they can sample anywhere in the node.\n */\nexport const effectShader = (wgsl: string) => /* wgsl */ `${prelude}\nstruct EffectInput {\n uv: vec2f,\n size: vec2f,\n time: f32,\n zoom: f32,\n params: vec4f,\n pointer: vec2f,\n press: vec2f,\n sincePress: f32,\n}\n\nvar<private> sourceRect: vec4f;\nvar<private> sourceLayer: i32;\n\nfn source(uv: vec2f) -> vec4f {\n if (any(uv < vec2f(0.0)) || any(uv > vec2f(1.0))) {\n return vec4f(0.0);\n }\n let texel = clamp(mix(sourceRect.xy, sourceRect.zw, uv), sourceRect.xy + 0.5, sourceRect.zw - 0.5);\n return textureSampleLevel(atlas, atlasSampler, texel / view.atlasSize, sourceLayer, 0.0);\n}\n\nfn hash(p: vec2f) -> f32 {\n return fract(sin(dot(p, vec2f(127.1, 311.7))) * 43758.5453);\n}\n\nfn noise(p: vec2f) -> f32 {\n let i = floor(p);\n let f = fract(p);\n let u = f * f * (3.0 - 2.0 * f);\n return mix(\n mix(hash(i), hash(i + vec2f(1.0, 0.0)), u.x),\n mix(hash(i + vec2f(0.0, 1.0)), hash(i + vec2f(1.0, 1.0)), u.x),\n u.y,\n );\n}\n\n${wgsl}\n\n@fragment\nfn fs(in: Varyings) -> @location(0) vec4f {\n sourceRect = in.color;\n sourceLayer = i32(in.info.x);\n let pointer = (view.pointer.xy - in.corner) / in.size;\n let press = (view.pointer.zw - in.corner) / in.size;\n return effect(\n EffectInput(in.uv, in.size, view.time, view.zoom, in.params, pointer, press, view.pressTime),\n );\n}\n`;\n","import type { Atlas } from './atlas';\nimport type { Camera, Point } from './camera';\nimport { compositeShader, effectShader } from './composite-shader';\nimport type { Effect } from './effects';\n\nexport const FLOATS_PER_INSTANCE = 16;\n\n/** Consecutive instances drawn with one effect's pipeline, or the plain one (`effect` null). */\nexport interface Run {\n effect: Effect | null;\n start: number;\n count: number;\n}\n\n/**\n * Draws every visible node with instanced draw calls: one for the whole frame, or one per run of\n * nodes sharing an effect, in paint order. The caller fills `instances` with FLOATS_PER_INSTANCE\n * floats per quad: world rect, atlas texel rect (a ring's color), then layer, kind (0 snapshot,\n * 1 placeholder, 2 ring) and ring width or effect padding, then an effect's parameters.\n */\nexport class CompositeRenderer {\n instances = new Float32Array(FLOATS_PER_INSTANCE * 4096);\n private instanceBuffer: GPUBuffer;\n private readonly uniforms: GPUBuffer;\n private readonly uniformData = new Float32Array(20);\n private readonly pipeline: GPURenderPipeline;\n private readonly bindGroup: GPUBindGroup;\n private readonly bindGroupLayout: GPUBindGroupLayout;\n private readonly sampler: GPUSampler;\n /** Effect pipelines, null while one compiles. Compiling never blocks a frame. */\n private readonly effects = new Map<Effect, GPURenderPipeline | null>();\n /** Called when an effect pipeline is ready, so the caller can draw it. */\n onEffectReady: () => void = () => {};\n\n constructor(\n private readonly device: GPUDevice,\n private readonly context: GPUCanvasContext,\n format: GPUTextureFormat,\n private readonly atlas: Atlas,\n public background: [number, number, number, number],\n public placeholder: [number, number, number, number],\n ) {\n this.bindGroupLayout = device.createBindGroupLayout({\n entries: [\n { binding: 0, visibility: GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT, buffer: {} },\n {\n binding: 1,\n visibility: GPUShaderStage.FRAGMENT,\n texture: { viewDimension: '2d-array' },\n },\n { binding: 2, visibility: GPUShaderStage.FRAGMENT, sampler: {} },\n ],\n });\n this.sampler = device.createSampler({ magFilter: 'linear', minFilter: 'linear' });\n this.pipeline = device.createRenderPipeline(\n this.pipelineDescriptor('gpucanvas composite', compositeShader, format),\n );\n this.format = format;\n this.uniforms = device.createBuffer({\n size: this.uniformData.byteLength,\n usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST,\n });\n this.bindGroup = device.createBindGroup({\n layout: this.bindGroupLayout,\n entries: [\n { binding: 0, resource: { buffer: this.uniforms } },\n { binding: 1, resource: atlas.view },\n { binding: 2, resource: this.sampler },\n ],\n });\n this.instanceBuffer = this.createInstanceBuffer();\n }\n\n private readonly format: GPUTextureFormat;\n\n private pipelineDescriptor(\n label: string,\n code: string,\n format: GPUTextureFormat,\n ): GPURenderPipelineDescriptor {\n const module = this.device.createShaderModule({ label, code });\n return {\n label,\n layout: this.device.createPipelineLayout({ bindGroupLayouts: [this.bindGroupLayout] }),\n vertex: {\n module,\n entryPoint: 'vs',\n buffers: [\n {\n arrayStride: FLOATS_PER_INSTANCE * 4,\n stepMode: 'instance',\n attributes: [\n { shaderLocation: 0, offset: 0, format: 'float32x4' },\n { shaderLocation: 1, offset: 16, format: 'float32x4' },\n { shaderLocation: 2, offset: 32, format: 'float32x4' },\n { shaderLocation: 3, offset: 48, format: 'float32x4' },\n ],\n },\n ],\n },\n fragment: {\n module,\n entryPoint: 'fs',\n targets: [\n {\n format,\n // Snapshots are requested premultiplied.\n blend: {\n color: { srcFactor: 'one', dstFactor: 'one-minus-src-alpha' },\n alpha: { srcFactor: 'one', dstFactor: 'one-minus-src-alpha' },\n },\n },\n ],\n },\n primitive: { topology: 'triangle-strip' },\n };\n }\n\n /** Whether `effect` can draw this frame. The first ask starts compiling it. */\n hasEffect(effect: Effect): boolean {\n if (this.effects.has(effect)) return this.effects.get(effect) !== null;\n this.effects.set(effect, null);\n this.device\n .createRenderPipelineAsync(\n this.pipelineDescriptor(\n `gpucanvas effect ${effect.name}`,\n effectShader(effect.wgsl),\n this.format,\n ),\n )\n .then((pipeline) => {\n this.effects.set(effect, pipeline);\n this.onEffectReady();\n })\n .catch((error) => console.error(`[gpucanvas] effect \"${effect.name}\" failed`, error));\n return false;\n }\n\n /** Grows the CPU and GPU instance storage to hold at least `count` instances. */\n reserve(count: number) {\n const floats = count * FLOATS_PER_INSTANCE;\n if (this.instances.length >= floats) return;\n this.instances = new Float32Array(Math.max(floats, this.instances.length * 2));\n this.instanceBuffer.destroy();\n this.instanceBuffer = this.createInstanceBuffer();\n }\n\n draw(\n camera: Camera,\n cssWidth: number,\n cssHeight: number,\n dpr: number,\n count: number,\n runs: readonly Run[],\n /** Seconds since start, pointer and press in world units, seconds since the press. */\n effects: { time: number; pointer: Point; press: Point; sincePress: number },\n ) {\n const { device } = this;\n this.uniformData.set([\n cssWidth,\n cssHeight,\n camera.x,\n camera.y,\n camera.zoom,\n dpr,\n this.atlas.size,\n effects.time,\n ...this.placeholder,\n effects.pointer.x,\n effects.pointer.y,\n effects.press.x,\n effects.press.y,\n effects.sincePress,\n ]);\n device.queue.writeBuffer(this.uniforms, 0, this.uniformData);\n if (count > 0) {\n device.queue.writeBuffer(\n this.instanceBuffer,\n 0,\n this.instances,\n 0,\n count * FLOATS_PER_INSTANCE,\n );\n }\n const [r, g, b] = this.background;\n const encoder = device.createCommandEncoder();\n const pass = encoder.beginRenderPass({\n colorAttachments: [\n {\n view: this.context.getCurrentTexture().createView(),\n clearValue: { r, g, b, a: 1 },\n loadOp: 'clear',\n storeOp: 'store',\n },\n ],\n });\n if (count > 0) {\n pass.setBindGroup(0, this.bindGroup);\n pass.setVertexBuffer(0, this.instanceBuffer);\n let current: GPURenderPipeline | null = null;\n for (const run of runs.length ? runs : [{ effect: null, start: 0, count }]) {\n const pipeline = (run.effect && this.effects.get(run.effect)) || this.pipeline;\n if (pipeline !== current) pass.setPipeline((current = pipeline));\n pass.draw(4, run.count, 0, run.start);\n }\n }\n pass.end();\n device.queue.submit([encoder.finish()]);\n }\n\n destroy() {\n this.instanceBuffer.destroy();\n this.uniforms.destroy();\n }\n\n private createInstanceBuffer() {\n return this.device.createBuffer({\n label: 'gpucanvas instances',\n size: this.instances.byteLength,\n usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST,\n });\n }\n}\n","/**\n * A page is one `drawable` container holding many nodes, laid out side by side in CSS pixels.\n * The browser records a page as one snapshot, so a single `drawElementImageToTexture` call can\n * rasterize every node on it, and a source rectangle crops out one node when only it changed.\n * Each call costs roughly a quarter millisecond on top of its pixels, so batching nodes into\n * pages is what makes a 10,000-node overview fill in a second instead of a minute.\n */\n\n/** Space between nodes on a page, so filtering at a node's edge never reads its neighbor. */\nconst GAP = 4;\n\ninterface Shelf {\n y: number;\n height: number;\n x: number;\n}\n\nexport interface PageSlot {\n page: Page;\n x: number;\n y: number;\n}\n\nexport class Page {\n readonly element: HTMLDivElement;\n readonly width: number;\n readonly height: number;\n /** Nodes currently placed on this page. */\n count = 0;\n /** Has the `drawable` attribute and is rendered; parked pages use `content-visibility: hidden`. */\n drawable = false;\n /** Frame in which the page became drawable. Its snapshot exists from that frame's paint on. */\n promotedFrame = -1;\n /** Kept drawable for the live (hit-testable) or focused node. */\n pinned = false;\n /** Registered for hit testing with `updateElementGeometry`. */\n registered = false;\n private shelves: Shelf[] = [];\n private nextY = 0;\n\n constructor(width: number, height: number) {\n this.width = width;\n this.height = height;\n this.element = document.createElement('div');\n this.element.dataset.gpucanvasPage = '';\n Object.assign(this.element.style, {\n position: 'relative',\n width: `${width}px`,\n height: `${height}px`,\n // Pages share the canvas origin: each one pulls the next back up by its own height.\n marginBottom: `${-height}px`,\n contain: 'strict',\n overflow: 'hidden',\n // Parked pages keep their layout but skip style, layout updates and paint. Unlike\n // `display: none`, their nodes keep their size, so components that measure themselves\n // (charts with a ResizeObserver) don't re-render empty every time a page parks.\n contentVisibility: 'hidden',\n });\n }\n\n /** Reserves a spot for a `width` x `height` node, or returns null when the page is full. */\n place(width: number, height: number): PageSlot | null {\n const w = Math.ceil(width) + GAP;\n const h = Math.ceil(height) + GAP;\n if (w > this.width + GAP || h > this.height + GAP) return null;\n let shelf = this.shelves.find(\n (candidate) =>\n candidate.height >= h &&\n candidate.height <= h * 1.25 &&\n candidate.x + w <= this.width + GAP,\n );\n if (!shelf) {\n if (this.nextY + h > this.height + GAP) return null;\n shelf = { y: this.nextY, height: h, x: 0 };\n this.shelves.push(shelf);\n this.nextY += h;\n }\n const slot = { page: this, x: shelf.x, y: shelf.y };\n shelf.x += w;\n this.count++;\n return slot;\n }\n\n release() {\n this.count--;\n }\n\n setDrawable(drawable: boolean, frame: number) {\n if (this.drawable === drawable) return;\n this.drawable = drawable;\n this.registered = false;\n if (drawable) {\n this.promotedFrame = frame;\n this.element.style.contentVisibility = '';\n this.element.setAttribute('drawable', '');\n } else {\n this.element.removeAttribute('drawable');\n this.element.style.contentVisibility = 'hidden';\n this.element.style.transform = '';\n }\n }\n}\n","import { Atlas, type AtlasSlot } from './atlas';\nimport {\n bindCameraInput,\n containsPoint,\n fitCamera,\n intersects,\n screenToWorld,\n visibleWorldRect,\n worldToScreen,\n type Camera,\n type Point,\n type Rect,\n} from './camera';\nimport { elementInNode, nodeOfElement, rectInNode } from './elements';\nimport { effectPad, effectParams, type Effect } from './effects';\nimport { CompositeRenderer, FLOATS_PER_INSTANCE, type Run } from './gpu-renderer';\nimport { boundsOf } from './node-style';\nimport { Page } from './page';\nimport {\n DEFAULT_CAMERA,\n DEFAULT_SELECTION_COLOR,\n HOVER_WIDTH,\n SELECTION_WIDTH,\n type GpuCanvas,\n type GpuCanvasOptions,\n} from './types';\n\ninterface Node {\n element: HTMLElement;\n rect: Rect;\n page: Page;\n /** The node's position on its page, CSS pixels. */\n pageX: number;\n pageY: number;\n slot: AtlasSlot | null;\n /** Texels per CSS pixel the slot was rasterized at. */\n slotScale: number;\n /**\n * A THUMBNAIL_SCALE snapshot in the atlas's pinned layer. It is never evicted, so zoomed out\n * the node needs nothing else, and closer in it stands in while a sharper snapshot is drawn.\n */\n thumb: AtlasSlot | null;\n /** The node changed since its thumbnail was drawn. */\n thumbStale: boolean;\n /** When the thumbnail was last drawn, from performance.now(). */\n thumbAt: number;\n /** What the last composite showed for this node: 0 nothing, 1 placeholder, 2 snapshot, 3 sharp. */\n shown: number;\n shownFrame: number;\n /** Content changed since the slot was rasterized. */\n dirty: boolean;\n /**\n * Zoomed in past MAX_RASTER_SCALE the whole snapshot is only a backdrop: the part in view is\n * drawn sharp as tiles, filled center first within the frame budget. While content animates,\n * one half-resolution preview of the view stands in, since redrawing every tile each frame\n * would cost too much.\n */\n tiles: Tile[];\n preview: AtlasSlot | null;\n previewRect: Rect | null;\n previewScale: number;\n /** Scratch: this frame's preview rect and scale, when one is needed. */\n previewTarget: Rect | null;\n previewTargetScale: number;\n /** Last time the node's content changed, from performance.now(). */\n changedAt: number;\n /** Last time a change of the node's content reached the atlas. */\n refreshedAt: number;\n /**\n * The whole snapshot predates a change that only the preview and tiles show so far. It is\n * redrawn once the node is no longer zoomed in that far.\n */\n wholeStale: boolean;\n /** Alone on its page, so zoomed-in snapshots rasterize only this node. */\n solo: boolean;\n /** Scratch values for the current frame's plan. */\n targetScale: number;\n priority: number;\n}\n\n/** A sharp piece of a zoomed-in node, `rect` in world units. */\ninterface Tile {\n slot: AtlasSlot;\n rect: Rect;\n scale: number;\n column: number;\n row: number;\n /** Shows content from before the node's last change; stays until a fresh tile replaces it. */\n stale: boolean;\n}\n\ninterface TileJob {\n node: Node;\n rect: Rect;\n scale: number;\n column: number;\n row: number;\n priority: number;\n}\n\ninterface PagePlan {\n page: Page;\n /** Nodes that need a whole snapshot. */\n nodes: Node[];\n /** Nodes that need a preview, then tiles; both after any whole snapshot. */\n previews: Node[];\n tiles: TileJob[];\n priority: number;\n}\n\nconst MIN_RASTER_SCALE = 1 / 64;\n/**\n * Whole-node snapshots stop here (100% zoom on a 2x display); closer in, tiles of the visible\n * part take over. A snapshot costs about 12 ns per pixel on the main thread, so one large card\n * at 4x would already stall a frame.\n */\nconst MAX_RASTER_SCALE = 2;\nconst MAX_DETAIL_SCALE = 64;\n/** Side of a tile in device pixels: about 3 ms to draw, so two fit the frame budget. */\nconst TILE_PIXELS = 512;\n/**\n * Content that changed this recently counts as animating: zoomed in, it is drawn as one\n * half-resolution preview of the view, then as sharp tiles once it rests. The full screen at 8x\n * zoom is about ten million pixels, too many to redraw every frame.\n */\nconst CONTENT_SETTLE_MS = 150;\n\n/**\n * Live content (spinners, clocks, video) changes every frame. A node that small on screen shows\n * no difference between 60 redraws a second and a few, so below SMALL_NODE_PX it refreshes at\n * most every SMALL_REFRESH_MS. Thousands of tiny spinners then cost what a few large ones do.\n */\nconst SMALL_NODE_PX = 200;\nconst SMALL_REFRESH_MS = 250;\nconst right = (rect: Rect) => rect.x + rect.width;\nconst bottom = (rect: Rect) => rect.y + rect.height;\n/** How long the camera must rest before blurry snapshots are upgraded. */\nconst SETTLE_MS = 120;\n/** Events that use a node, and how long after one its transitions are followed frame by frame. */\nconst USE_EVENTS = ['click', 'input', 'change', 'keydown'] as const;\nconst USED_MS = 1000;\n/** A node that stops being live stays rasterizable this long, so hover-out transitions finish. */\nconst LINGER_MS = 300;\n/** Kept snapshots may be this many times sharper than needed before they are redrawn smaller. */\nconst MAX_OVERSAMPLING = 4;\nconst DEFAULT_PAGE_SIZE = 2048;\n/**\n * Thumbnails: a 1440 px wide screen is 90 texels across, as sharp as it gets on a 2x display at\n * the 3% zoom of a 5,000 node overview. Five thousand of them fit the pinned layer.\n */\nconst THUMBNAIL_SCALE = 1 / 16;\n/** Live content redraws its thumbnail at most this often; nobody reads a spinner at 3% zoom. */\nconst THUMBNAIL_REFRESH_MS = 1000;\n/**\n * Pages made drawable per frame. Chrome paints every drawable page in its rendering update,\n * outside our own timing, and a page of two dozen rich cards can take tens of milliseconds, so\n * the count adapts to how long frames actually take: halved after a slow frame, grown by one\n * after a fast one.\n */\nconst MAX_PROMOTIONS_PER_FRAME = 8;\nconst SLOW_FRAME_MS = 22;\nconst FAST_FRAME_MS = 12;\n\n/** Need classes, most urgent first. */\nconst MISSING = 0;\nconst DIRTY = 1;\nconst BLURRY = 2;\nconst OVERSAMPLED = 3;\n\nexport function supportsGpuCanvas(): boolean {\n return (\n typeof navigator !== 'undefined' &&\n 'gpu' in navigator &&\n typeof HTMLCanvasElement !== 'undefined' &&\n 'requestPaint' in HTMLCanvasElement.prototype &&\n 'getElementTransform' in HTMLCanvasElement.prototype &&\n typeof GPUQueue !== 'undefined' &&\n 'drawElementImageToTexture' in GPUQueue.prototype\n );\n}\n\n/**\n * Snapshots are rasterized at power-of-two scales so zooming reuses them; a snapshot up to 10%\n * too small is accepted before paying for the next scale.\n */\nfunction rasterScaleFor(deviceScale: number) {\n const scale = 2 ** Math.ceil(Math.log2(deviceScale) - 0.14);\n return Math.min(MAX_DETAIL_SCALE, Math.max(MIN_RASTER_SCALE, scale));\n}\n\nconst intersection = (a: Rect, b: Rect): Rect | null => {\n const x = Math.max(a.x, b.x);\n const y = Math.max(a.y, b.y);\n const right = Math.min(a.x + a.width, b.x + b.width);\n const bottom = Math.min(a.y + a.height, b.y + b.height);\n return right > x && bottom > y ? { x, y, width: right - x, height: bottom - y } : null;\n};\n\nconst contains = (outer: Rect, inner: Rect) =>\n inner.x >= outer.x &&\n inner.y >= outer.y &&\n inner.x + inner.width <= outer.x + outer.width &&\n inner.y + inner.height <= outer.y + outer.height;\n\nfunction cssColorToRgba(color: string): [number, number, number, number] {\n const context = document.createElement('canvas').getContext('2d')!;\n context.fillStyle = color;\n context.fillRect(0, 0, 1, 1);\n const [r, g, b, a] = context.getImageData(0, 0, 1, 1).data;\n return [r / 255, g / 255, b / 255, a / 255];\n}\n\nconst premultiplied = ([r, g, b, a]: [number, number, number, number]) =>\n [r * a, g * a, b * a, a] as [number, number, number, number];\n\nconst distanceToCenter = (rect: Rect, view: Rect) =>\n Math.hypot(\n rect.x + rect.width / 2 - (view.x + view.width / 2),\n rect.y + rect.height / 2 - (view.y + view.height / 2),\n );\n\n/**\n * The GPU backend.\n *\n * Nodes are live DOM, grouped into pages inside `<canvas content=\"drawable\">`. A page that has\n * nodes waiting for pixels is made drawable, rasterized into a texture-array atlas in the next\n * paint event (whole, or one node at a time when only a few changed), then parked with\n * `content-visibility: hidden` so it costs the browser nothing per frame. Compositing runs from\n * requestAnimationFrame and draws every visible node in one instanced call, so panning and\n * zooming never touch the DOM.\n *\n * Hit testing (Chrome 157): only drawables registered with `updateElementGeometry` are hit\n * tested, at their CSS position. Only the page under the pointer is registered, and its CSS\n * transform puts the node under the pointer exactly where the GPU drew it.\n */\nexport async function createGpuCanvas(\n host: HTMLElement,\n options: GpuCanvasOptions,\n): Promise<GpuCanvas> {\n const adapter = await navigator.gpu.requestAdapter({ powerPreference: 'high-performance' });\n if (!adapter) throw new Error('gpucanvas: no WebGPU adapter');\n const device = await adapter.requestDevice();\n\n const surface = document.createElement('div');\n surface.dataset.gpucanvasSurface = '';\n Object.assign(surface.style, {\n position: 'relative',\n width: '100%',\n height: '100%',\n overflow: 'hidden',\n touchAction: 'none',\n });\n const canvas = document.createElement('canvas');\n canvas.setAttribute('content', 'drawable');\n canvas.dataset.gpucanvasSurface = '';\n Object.assign(canvas.style, { display: 'block', width: '100%', height: '100%' });\n surface.append(canvas);\n host.append(surface);\n\n const context = canvas.getContext('webgpu')!;\n const format = navigator.gpu.getPreferredCanvasFormat();\n context.configure({ device, format, alphaMode: 'opaque' });\n\n const atlasSize = Math.min(options.atlasSize ?? 4096, device.limits.maxTextureDimension2D);\n const atlas = new Atlas(\n device,\n atlasSize,\n Math.min(options.atlasLayers ?? 5, device.limits.maxTextureArrayLayers),\n );\n const pageSize = Math.min(options.pageSize ?? DEFAULT_PAGE_SIZE, atlasSize);\n const maxRasterCalls = options.maxRastersPerFrame ?? 12;\n const rasterTimeBudgetMs = options.rasterTimeBudgetMs ?? 6;\n const rasterPixelBudget = options.rasterPixelBudget ?? 24_000_000;\n // Nodes still waiting for pixels draw as a block slightly off the background.\n const colorsFor = (css: string) => {\n const background = cssColorToRgba(css);\n const shade = background[0] + background[1] + background[2] > 1.5 ? 0.92 : 1.25;\n const placeholder = background.map((channel) =>\n Math.min(1, channel * shade + (shade > 1 ? 0.02 : 0)),\n );\n placeholder[3] = 1;\n return [background, placeholder] as [typeof background, typeof background];\n };\n const renderer = new CompositeRenderer(\n device,\n context,\n format,\n atlas,\n ...colorsFor(options.background ?? '#f4f4f5'),\n );\n const selectionColor = premultiplied(\n cssColorToRgba(options.selectionColor ?? DEFAULT_SELECTION_COLOR),\n );\n const hoverColor = options.hoverColor\n ? premultiplied(cssColorToRgba(options.hoverColor))\n : selectionColor;\n\n const nodes = new Map<HTMLElement, Node>();\n /** Effects nodes wear, with their parameters and how far past the node they draw. */\n const effects = new Map<HTMLElement, { effect: Effect; params: number[]; pad: number }>();\n const startedAt = performance.now();\n /** Where effects see the pointer when there is none. */\n const FAR_AWAY: Point = { x: -1e7, y: -1e7 };\n renderer.onEffectReady = () => schedule();\n const runs: Run[] = [];\n /** An effect in view animates, or is still compiling: draw again next frame. */\n let effectsMoving = false;\n let selection = new Set<Element>();\n let hovered: Element | null = null;\n /** World rects of outlined elements inside nodes, measured once until their layout changes. */\n const ringRects = new Map<Element, Rect>();\n const ringRect = (element: Element): Rect | null => {\n const own = nodes.get(element as HTMLElement);\n if (own) return own.rect;\n const at = element.isConnected ? nodeOfElement(nodes, element) : null;\n if (!at) return null;\n const node = nodes.get(at)!;\n let rect = ringRects.get(element);\n if (!rect) ringRects.set(element, (rect = rectInNode(at, node.rect, element)));\n return rect;\n };\n const pages = new Map<Page, Set<Node>>();\n // What is on screen survives a full atlas: whole snapshots first, then sharp tiles.\n atlas.keep = function* () {\n const onScreen = (tile: Tile) => intersects(tile.rect, frameView);\n for (const node of visible) yield node.slot;\n for (const node of visible) {\n for (const tile of node.tiles) {\n if (tile.scale === detailScale && !tile.stale && onScreen(tile)) yield tile.slot;\n }\n }\n for (const node of visible) {\n yield node.preview;\n for (const tile of node.tiles) if (onScreen(tile)) yield tile.slot;\n }\n };\n const pageByElement = new Map<Element, Page>();\n let openPage: Page | null = null;\n\n let camera = options.camera ?? DEFAULT_CAMERA;\n let lastCameraChange = -Infinity;\n let frameNumber = 0;\n let promotionsPerFrame = 2;\n let lastFrameAt = 0;\n let rafId = 0;\n let destroyed = false;\n /** The node under the pointer: the only one that receives pointer events. */\n let live: Node | null = null;\n let livePositioned = false;\n let lingering: Node | null = null;\n let lingerTimer = 0;\n let focused: Node | null = null;\n let pointer: { x: number; y: number } | null = null;\n let settleTimer = 0;\n const stats = {\n visible: 0,\n pending: 0,\n rasterizedLastFrame: 0,\n rasterCallsLastFrame: 0,\n rasterMs: 0,\n frameMs: 0,\n frames: 0,\n lostPixels: 0,\n lostDetail: 0,\n onThumbnail: 0,\n /** Last plan's nodes per need class: missing, dirty, blurry, oversampled. */\n needs: [0, 0, 0, 0],\n };\n const visible: Node[] = [];\n const plans = new Map<Page, PagePlan>();\n\n const schedule = () => {\n if (rafId || destroyed) return;\n rafId = requestAnimationFrame(() => {\n rafId = 0;\n frameNumber++;\n frame(false);\n });\n };\n\n const resizeObserver = new ResizeObserver(([entry]) => {\n const size = entry.devicePixelContentBoxSize?.[0];\n canvas.width = Math.max(\n 1,\n size ? size.inlineSize : Math.round(entry.contentRect.width * devicePixelRatio),\n );\n canvas.height = Math.max(\n 1,\n size ? size.blockSize : Math.round(entry.contentRect.height * devicePixelRatio),\n );\n schedule();\n });\n resizeObserver.observe(canvas, { box: 'device-pixel-content-box' });\n\n /** Readable nodes in view with CSS transitions running, and when the last one ends. */\n const transitioning = new Map<Node, number>();\n const isPinned = (page: Page) =>\n live?.page === page ||\n lingering?.page === page ||\n focused?.page === page ||\n [...transitioning.keys()].some((node) => node.page === page);\n\n /** This frame's texels per CSS pixel for tiles, and the world rect in view. */\n let detailScale = 1;\n let frameView: Rect = { x: 0, y: 0, width: 0, height: 0 };\n let contentTimer = 0;\n const scheduleAfterContentSettles = () => {\n clearTimeout(contentTimer);\n contentTimer = window.setTimeout(schedule, CONTENT_SETTLE_MS + 10);\n };\n let refreshTimer = 0;\n let refreshAt = Infinity;\n /** How long a changed node waits before it is redrawn: only small ones wait. */\n const refreshWait = (node: Node, now: number) =>\n Math.max(node.rect.width, node.rect.height) * camera.zoom < SMALL_NODE_PX\n ? node.refreshedAt + SMALL_REFRESH_MS - now\n : 0;\n const refreshLater = (wait: number) => {\n const at = performance.now() + wait;\n if (at >= refreshAt) return;\n clearTimeout(refreshTimer);\n refreshAt = at;\n refreshTimer = window.setTimeout(() => {\n refreshAt = Infinity;\n schedule();\n }, wait);\n };\n /** Builds this frame's raster plan: which visible nodes need pixels, grouped by page. */\n const planFrame = (view: Rect, desiredScale: number, deviceScale: number, moving: boolean) => {\n const now = performance.now();\n // Tiles are redrawn whenever the zoom settles anyway, so they use the exact device scale:\n // one tile texel per screen pixel.\n detailScale = Math.min(deviceScale, MAX_DETAIL_SCALE);\n frameView = view;\n visible.length = 0;\n plans.clear();\n stats.needs = [0, 0, 0, 0];\n for (const node of nodes.values()) {\n if (!intersects(node.rect, view)) continue;\n visible.push(node);\n const scale = Math.min(\n desiredScale,\n MAX_RASTER_SCALE,\n (atlasSize - 1) / node.rect.width,\n (atlasSize - 1) / node.rect.height,\n );\n if (node.dirty) node.changedAt = now;\n // Zoomed out this far the thumbnail is all the detail there is to see.\n const thumbnailEnough = scale <= THUMBNAIL_SCALE;\n if (thumbnailEnough && freshThumb(node) && !node.dirty && !node.wholeStale) {\n node.slot = node.thumb;\n node.slotScale = THUMBNAIL_SCALE;\n }\n const animating = now - node.changedAt < CONTENT_SETTLE_MS;\n const deep = desiredScale > scale;\n if (deep && !node.solo) lift(node);\n const jobs = deep ? planDetail(node, view, animating, moving) : [];\n if (!deep) {\n node.preview = null;\n node.tiles.length = 0;\n }\n const valid = atlas.isValid(node.slot);\n let need = -1;\n // A node with a thumbnail has something on screen, so empty ones go first.\n if (!valid) need = atlas.isValid(node.thumb) ? DIRTY : MISSING;\n // Zoomed in, the whole snapshot is a backdrop under the preview and tiles; a change can\n // wait for it until the node is seen at a smaller zoom.\n else if (deep) need = node.slotScale < scale / (moving ? 4 : 2) ? BLURRY : -1;\n else if (node.dirty || node.wholeStale) {\n const wait = refreshWait(node, now);\n if (wait > 0) refreshLater(wait);\n else need = DIRTY;\n }\n // In motion only snapshots under half the needed scale are redrawn, nearest the middle\n // first within the frame's budget, so a flight never shows thumbnails blown up.\n else if (node.slotScale < (moving ? scale / 2 : scale)) need = BLURRY;\n else if (!moving && node.slotScale > scale * MAX_OVERSAMPLING) need = OVERSAMPLED;\n if (need >= 0) stats.needs[need]++;\n if (need < 0 && !node.previewTarget && jobs.length === 0) continue;\n // Snapshots this small are thumbnails, and those have one fixed scale.\n node.targetScale = thumbnailEnough ? THUMBNAIL_SCALE : scale;\n node.priority = (need < 0 ? BLURRY : need) * 1e12 + distanceToCenter(node.rect, view);\n let plan = plans.get(node.page);\n if (!plan) {\n plan = { page: node.page, nodes: [], previews: [], tiles: [], priority: node.priority };\n plans.set(node.page, plan);\n }\n plan.priority = Math.min(plan.priority, node.priority);\n if (need >= 0) plan.nodes.push(node);\n if (node.previewTarget) plan.previews.push(node);\n plan.tiles.push(...jobs);\n }\n for (const plan of plans.values()) plan.tiles.sort((a, b) => a.priority - b.priority);\n };\n\n /**\n * Plans a zoomed-in node: a preview while its content animates, otherwise the tiles in view\n * it is missing at this frame's scale.\n */\n const planDetail = (node: Node, view: Rect, animating: boolean, moving: boolean) => {\n const shown = intersection(node.rect, view)!;\n node.previewTarget = null;\n node.tiles = node.tiles.filter((tile) => atlas.isValid(tile.slot));\n // Old tiles stay on screen under the preview until fresh ones replace them.\n if (node.dirty) for (const tile of node.tiles) tile.stale = true;\n if (!atlas.isValid(node.preview)) node.preview = null;\n if (animating) {\n const scale = detailScale / 2;\n const stale =\n !node.preview ||\n node.dirty ||\n node.previewScale !== scale ||\n !contains(node.previewRect!, shown);\n if (stale) {\n node.previewTarget = fitPreview(shown, scale);\n node.previewTargetScale = scale;\n }\n scheduleAfterContentSettles();\n return [];\n }\n // Panning at a steady zoom keeps filling tiles; while the zoom changes it waits to settle.\n const current = node.tiles.filter((tile) => tile.scale === detailScale && !tile.stale);\n if (moving && current.length === 0) return [];\n const size = Math.max(1, Math.floor(TILE_PIXELS / detailScale));\n const jobs: TileJob[] = [];\n const first = (edge: number, origin: number) => Math.floor((edge - origin) / size);\n for (\n let row = first(shown.y, node.rect.y);\n row <= first(bottom(shown) - 1e-6, node.rect.y);\n row++\n ) {\n for (\n let column = first(shown.x, node.rect.x);\n column <= first(right(shown) - 1e-6, node.rect.x);\n column++\n ) {\n if (current.some((tile) => tile.column === column && tile.row === row)) continue;\n const rect = intersection(node.rect, {\n x: node.rect.x + column * size,\n y: node.rect.y + row * size,\n width: size,\n height: size,\n })!;\n jobs.push({\n node,\n rect,\n scale: detailScale,\n column,\n row,\n priority: distanceToCenter(rect, view),\n });\n }\n }\n // Once the view is tiled at this scale, older tiles and the preview are hidden anyway.\n if (jobs.length === 0) {\n node.tiles = current;\n node.preview = null;\n }\n return jobs;\n };\n\n /** The world rect a preview covers: `shown`, shrunk around its center to fit one layer. */\n const fitPreview = (shown: Rect, scale: number): Rect => {\n const limit = (atlasSize - 2) / scale;\n const fit = (start: number, size: number) =>\n size <= limit ? [start, size] : [start + (size - limit) / 2, limit];\n const [x, width] = fit(shown.x, shown.width);\n const [y, height] = fit(shown.y, shown.height);\n return { x, y, width, height };\n };\n\n /** Draws one snapshot region into the atlas. Returns false when it could not. */\n const drawSnapshot = (\n page: Page,\n source: { x: number; y: number; width: number; height: number } | null,\n slot: AtlasSlot,\n ) => {\n try {\n device.queue.drawElementImageToTexture(\n source\n ? {\n source: page.element,\n sourceX: source.x,\n sourceY: source.y,\n sourceWidth: source.width,\n sourceHeight: source.height,\n }\n : { source: page.element },\n {\n texture: atlas.texture,\n origin: { x: slot.x, y: slot.y, z: slot.layer },\n size: { width: slot.width, height: slot.height },\n premultipliedAlpha: true,\n },\n );\n return true;\n } catch {\n // Not recorded yet; the next paint event retries.\n return false;\n }\n };\n\n /**\n * Atlas space for a `width` x `height` snapshot. A redraw at the same size overwrites the slot\n * it replaces, so redraws (a hover, a click, an animation) never fill the atlas. Thumbnails go\n * to the pinned layer while it has room.\n */\n const slotFor = (previous: AtlasSlot | null, width: number, height: number, thumbnail = false) =>\n atlas.isValid(previous) &&\n atlas.isPinned(previous) === thumbnail &&\n previous.width === width &&\n previous.height === height &&\n Number.isInteger(previous.x) &&\n Number.isInteger(previous.y)\n ? previous\n : ((thumbnail ? atlas.allocatePinned(width, height) : null) ?? atlas.allocate(width, height));\n const freshThumb = (node: Node) => atlas.isValid(node.thumb) && !node.thumbStale;\n /** Records a snapshot that reached the atlas; at thumbnail scale it is the node's thumbnail. */\n const drawn = (node: Node, slot: AtlasSlot, scale: number, now: number) => {\n node.slot = slot;\n node.slotScale = scale;\n if (scale === THUMBNAIL_SCALE) {\n node.thumb = slot;\n node.thumbStale = false;\n node.thumbAt = now;\n } else if (node.dirty) node.thumbStale = true;\n if (node.dirty) {\n // A preview from before the change would cover the fresh snapshot.\n node.preview = null;\n node.refreshedAt = now;\n }\n node.dirty = false;\n node.wholeStale = false;\n };\n /** Whole page slots per page, reused when the page is drawn again at the same size. */\n const pageSlots = new Map<Page, AtlasSlot>();\n\n /**\n * Rasterizes planned pages in priority order within the frame's budget. A page where many\n * nodes need pixels is drawn whole in one call; otherwise each node is cropped out.\n */\n const rasterize = (start: number) => {\n let calls = 0;\n let pixels = 0;\n let rasterized = 0;\n let pending = 0;\n const overBudget = () =>\n calls > 0 &&\n (calls >= maxRasterCalls ||\n pixels >= rasterPixelBudget ||\n performance.now() - start >= rasterTimeBudgetMs);\n const ordered = [...plans.values()].sort((a, b) => a.priority - b.priority);\n for (const plan of ordered) {\n const { page } = plan;\n // A page promoted this frame may still hold the snapshot from before it was parked.\n if (!page.drawable || page.promotedFrame >= frameNumber || overBudget()) {\n pending += plan.nodes.length + plan.previews.length + plan.tiles.length;\n continue;\n }\n const scale = plan.nodes.reduce((max, node) => Math.max(max, node.targetScale), 0);\n const members = pages.get(page)!;\n const neededArea = plan.nodes.reduce((sum, n) => sum + n.rect.width * n.rect.height, 0);\n // A whole page also redraws members nobody is looking at, so it is worth it only while\n // the page is small in the atlas: at most a quarter of a layer.\n const wholeFits = page.width * scale <= atlasSize / 2 && page.height * scale <= atlasSize / 2;\n const whole =\n wholeFits && (plan.nodes.length >= 6 || neededArea >= 0.25 * page.width * page.height);\n const wholeSlot = whole\n ? slotFor(\n pageSlots.get(page) ?? null,\n Math.ceil(page.width * scale),\n Math.ceil(page.height * scale),\n scale === THUMBNAIL_SCALE,\n )\n : null;\n if (wholeSlot) pageSlots.set(page, wholeSlot);\n if (wholeSlot && !drawSnapshot(page, null, wholeSlot)) {\n pending += plan.nodes.length + plan.previews.length + plan.tiles.length;\n continue;\n }\n\n if (wholeSlot) {\n const slot = wholeSlot;\n calls++;\n pixels += slot.width * slot.height;\n for (const node of members) {\n const part = {\n layer: slot.layer,\n generation: slot.generation,\n x: slot.x + node.pageX * scale,\n y: slot.y + node.pageY * scale,\n width: node.rect.width * scale,\n height: node.rect.height * scale,\n };\n drawn(node, part, scale, start);\n }\n rasterized += members.size;\n } else {\n for (const node of plan.nodes) {\n if (overBudget()) {\n pending++;\n continue;\n }\n const thumbnail = node.targetScale === THUMBNAIL_SCALE;\n const slot = slotFor(\n thumbnail ? node.thumb : node.slot,\n Math.max(1, Math.round(node.rect.width * node.targetScale)),\n Math.max(1, Math.round(node.rect.height * node.targetScale)),\n thumbnail,\n );\n const region = {\n x: node.pageX,\n y: node.pageY,\n width: node.rect.width,\n height: node.rect.height,\n };\n if (!slot || !drawSnapshot(page, region, slot)) {\n pending++;\n continue;\n }\n calls++;\n pixels += slot.width * slot.height;\n drawn(node, slot, node.targetScale, start);\n rasterized++;\n }\n }\n /** Crops `rect` (world units) of `node` out of its page into the atlas at `scale`. */\n // The first snapshot at a scale in a frame pays to rasterize the page at that scale;\n // further crops at the same scale are nearly free, so they skip the budget.\n const warm = new Set<number>();\n const drawRegion = (node: Node, rect: Rect, scale: number, previous: AtlasSlot | null) => {\n if (!warm.has(scale) && overBudget()) return null;\n const slot = slotFor(\n previous,\n Math.max(1, Math.round(rect.width * scale)),\n Math.max(1, Math.round(rect.height * scale)),\n );\n const region = {\n x: node.pageX + rect.x - node.rect.x,\n y: node.pageY + rect.y - node.rect.y,\n width: rect.width,\n height: rect.height,\n };\n if (!slot || !drawSnapshot(page, region, slot)) return null;\n calls++;\n warm.add(scale);\n pixels += slot.width * slot.height;\n // The node's whole snapshot now lags behind what the preview and tiles show.\n if (node.dirty) {\n node.dirty = false;\n node.wholeStale = true;\n node.thumbStale = true;\n node.refreshedAt = start;\n }\n return slot;\n };\n for (const node of plan.previews) {\n const slot = drawRegion(node, node.previewTarget!, node.previewTargetScale, node.preview);\n if (!slot) {\n pending++;\n continue;\n }\n node.preview = slot;\n node.previewRect = node.previewTarget;\n node.previewScale = node.previewTargetScale;\n node.previewTarget = null;\n }\n let tilesLeft = 0;\n for (const job of plan.tiles) {\n // A change since planning makes the job's content stale; the next plan redoes it.\n const { node, column, row, scale } = job;\n const old = node.tiles.findIndex(\n (tile) =>\n tile.stale && tile.scale === scale && tile.column === column && tile.row === row,\n );\n const previous = old >= 0 ? node.tiles[old].slot : null;\n const slot = node.dirty ? null : drawRegion(node, job.rect, scale, previous);\n if (!slot) {\n tilesLeft++;\n continue;\n }\n if (old >= 0) node.tiles.splice(old, 1);\n node.tiles.push({ slot, rect: job.rect, scale, column, row, stale: false });\n }\n pending += tilesLeft;\n // While the page is drawable, its nodes' thumbnails are nearly free: one small raster of\n // the page, then a crop per node.\n for (const node of members) {\n if (freshThumb(node) || node.dirty) continue;\n if (atlas.isValid(node.thumb) && start - node.thumbAt < THUMBNAIL_REFRESH_MS) continue;\n const slot = slotFor(\n node.thumb,\n Math.max(1, Math.round(node.rect.width * THUMBNAIL_SCALE)),\n Math.max(1, Math.round(node.rect.height * THUMBNAIL_SCALE)),\n true,\n );\n const region = {\n x: node.pageX,\n y: node.pageY,\n width: node.rect.width,\n height: node.rect.height,\n };\n if (!slot || !drawSnapshot(page, region, slot)) continue;\n calls++;\n node.thumb = slot;\n node.thumbStale = false;\n node.thumbAt = start;\n }\n const done =\n plan.nodes.every((node) => !node.dirty && atlas.isValid(node.slot)) &&\n plan.previews.every((node) => node.previewTarget === null) &&\n tilesLeft === 0;\n if (done && !isPinned(page)) page.setDrawable(false, frameNumber);\n }\n stats.rasterizedLastFrame = rasterized;\n stats.rasterCallsLastFrame = calls;\n return pending;\n };\n\n const composite = () => {\n let instances = visible.length;\n for (const node of visible) instances += node.tiles.length + (node.preview ? 1 : 0);\n instances += selection.size + 1;\n renderer.reserve(instances);\n const data = renderer.instances;\n let count = 0;\n runs.length = 0;\n effectsMoving = false;\n let runEffect: Effect | null = null;\n const startRun = (effect: Effect | null) => {\n if (runs.length && runEffect === effect) return;\n runEffect = effect;\n runs.push({ effect, start: count, count: 0 });\n };\n const push = (rect: Rect, slot: AtlasSlot | null) => {\n startRun(null);\n runs[runs.length - 1].count++;\n const offset = count++ * FLOATS_PER_INSTANCE;\n data[offset] = rect.x;\n data[offset + 1] = rect.y;\n data[offset + 2] = rect.width;\n data[offset + 3] = rect.height;\n if (slot) {\n atlas.touch(slot.layer);\n data[offset + 4] = slot.x;\n data[offset + 5] = slot.y;\n data[offset + 6] = slot.x + slot.width;\n data[offset + 7] = slot.y + slot.height;\n data[offset + 8] = slot.layer;\n data[offset + 9] = 0;\n } else {\n data[offset + 9] = 1;\n }\n data[offset + 10] = 0;\n };\n /** A node drawn by its effect: the whole snapshot, padded, with its parameters. */\n const pushEffect = (\n node: Node,\n slot: AtlasSlot,\n worn: { effect: Effect; params: number[]; pad: number },\n ) => {\n startRun(worn.effect);\n runs[runs.length - 1].count++;\n const offset = count++ * FLOATS_PER_INSTANCE;\n const { rect } = node;\n data[offset] = rect.x;\n data[offset + 1] = rect.y;\n data[offset + 2] = rect.width;\n data[offset + 3] = rect.height;\n atlas.touch(slot.layer);\n data[offset + 4] = slot.x;\n data[offset + 5] = slot.y;\n data[offset + 6] = slot.x + slot.width;\n data[offset + 7] = slot.y + slot.height;\n data[offset + 8] = slot.layer;\n data[offset + 9] = 0;\n data[offset + 10] = worn.pad;\n data.set(worn.params, offset + 12);\n };\n const pushRing = (element: Element, color: number[], width: number) => {\n const rect = ringRect(element);\n if (!rect || !intersects(rect, frameView)) return;\n startRun(null);\n runs[runs.length - 1].count++;\n const offset = count++ * FLOATS_PER_INSTANCE;\n data[offset] = rect.x;\n data[offset + 1] = rect.y;\n data[offset + 2] = rect.width;\n data[offset + 3] = rect.height;\n data.set(color, offset + 4);\n data[offset + 9] = 2;\n data[offset + 10] = width;\n };\n let onThumbnail = 0;\n for (const node of visible) {\n // Until its snapshot is drawn, a node shows its thumbnail.\n const base = atlas.isValid(node.slot)\n ? node.slot\n : atlas.isValid(node.thumb)\n ? node.thumb\n : null;\n if (base && base !== node.slot) onThumbnail++;\n const hasSlot = base !== null;\n const sharp = node.tiles.length > 0 || (node.preview !== null && atlas.isValid(node.preview));\n const shown = sharp ? 3 : hasSlot ? 2 : 1;\n // Flicker accounting: pixels a node showed last frame and lost this one. A node coming\n // into view is pop-in, not flicker.\n const before = node.shownFrame === stats.frames - 1 ? node.shown : 0;\n if (before >= 2 && shown === 1) stats.lostPixels++;\n if (before === 3 && shown === 2) stats.lostDetail++;\n node.shown = shown;\n node.shownFrame = stats.frames;\n const worn = effects.size ? effects.get(node.element) : undefined;\n if (worn) {\n if (worn.effect.animated) effectsMoving = true;\n if (base && renderer.hasEffect(worn.effect)) {\n pushEffect(node, base, worn);\n continue;\n }\n effectsMoving = true;\n }\n push(node.rect, base);\n // Back to front: stale tiles and tiles from an earlier zoom, the preview of a change,\n // then this zoom's fresh tiles.\n const current = (tile: Tile) => tile.scale === detailScale && !tile.stale;\n for (const tile of node.tiles)\n if (!current(tile) && atlas.isValid(tile.slot)) push(tile.rect, tile.slot);\n if (node.preview && atlas.isValid(node.preview)) push(node.previewRect!, node.preview);\n for (const tile of node.tiles)\n if (current(tile) && atlas.isValid(tile.slot)) push(tile.rect, tile.slot);\n }\n stats.onThumbnail = onThumbnail;\n // Outlines last, so no neighbor covers them, and hover over the selection.\n for (const element of selection) pushRing(element, selectionColor, SELECTION_WIDTH);\n if (hovered && !selection.has(hovered)) pushRing(hovered, hoverColor, HOVER_WIDTH);\n const cssWidth = canvas.clientWidth;\n const dpr = canvas.width / Math.max(1, cssWidth);\n const now = performance.now();\n renderer.draw(camera, cssWidth, canvas.clientHeight, dpr, count, runs, {\n time: (now - startedAt) / 1000,\n pointer: pointer ? screenToWorld(camera, pointer) : FAR_AWAY,\n press,\n sincePress: Math.min((now - pressedAt) / 1000, 1e4),\n });\n };\n\n /**\n * One frame. From requestAnimationFrame (`inPaint` false) it plans, promotes the pages that\n * need pixels, and either composites straight away or asks for a paint event. In the paint\n * event snapshots are current, so rasterizing happens there, followed by the composite.\n */\n const frame = (inPaint: boolean) => {\n if (destroyed) return;\n const start = performance.now();\n atlas.nextFrame();\n const cssWidth = canvas.clientWidth;\n const dpr = canvas.width / Math.max(1, cssWidth);\n const view = visibleWorldRect(camera, cssWidth, canvas.clientHeight);\n const moving = start - lastCameraChange < SETTLE_MS;\n planFrame(view, rasterScaleFor(camera.zoom * dpr), camera.zoom * dpr, moving);\n\n if (!inPaint && plans.size > 0) {\n // Only consecutive frames say how long a frame takes.\n const interval = start - lastFrameAt;\n if (interval < 100) {\n if (interval > SLOW_FRAME_MS) promotionsPerFrame = Math.max(1, promotionsPerFrame >> 1);\n else if (interval < FAST_FRAME_MS)\n promotionsPerFrame = Math.min(MAX_PROMOTIONS_PER_FRAME, promotionsPerFrame + 1);\n }\n lastFrameAt = start;\n let promoted = 0;\n for (const plan of [...plans.values()].sort((a, b) => a.priority - b.priority)) {\n if (plan.page.drawable) continue;\n if (promoted++ >= promotionsPerFrame) break;\n plan.page.setDrawable(true, frameNumber);\n }\n // The paint event follows in this same rendering update and finishes the frame.\n awaitingPaint = true;\n canvas.requestPaint();\n return;\n }\n\n let pending = 0;\n stats.rasterizedLastFrame = 0;\n stats.rasterCallsLastFrame = 0;\n if (inPaint && plans.size > 0) pending = rasterize(start);\n // A page promoted for a camera that has moved on has nothing left to draw: park it, or\n // Chrome keeps painting it every frame.\n for (const page of pages.keys()) {\n if (page.drawable && !plans.has(page) && page.promotedFrame < frameNumber && !isPinned(page))\n page.setDrawable(false, frameNumber);\n }\n stats.rasterMs = performance.now() - start;\n composite();\n stats.frames++;\n positionLivePage();\n stats.visible = visible.length;\n stats.pending = pending;\n stats.frameMs = performance.now() - start;\n if (pending > 0 || effectsMoving) schedule();\n };\n\n /** A frame asked for this paint event; others come from content animating on its own. */\n let awaitingPaint = false;\n canvas.onpaint = (event) => {\n // CSS-only changes (hover, focus rings, transitions) on pinned pages reach us only here.\n let changed = false;\n for (const element of event.changedElements) {\n const page = pageByElement.get(element);\n if (!page) continue;\n for (const node of [live, lingering, focused, ...transitioning.keys()]) {\n if (node?.page === page) {\n node.dirty = true;\n changed = true;\n }\n }\n }\n if (changed) ringRects.clear();\n if (!awaitingPaint && !changed) return;\n awaitingPaint = false;\n frame(true);\n };\n\n const viewNow = () => visibleWorldRect(camera, canvas.clientWidth, canvas.clientHeight);\n\n /** The node an element belongs to: its ancestor whose parent is a page. */\n const nodeOf = (target: globalThis.Node): Node | undefined => {\n let element = target instanceof HTMLElement ? target : target.parentElement;\n while (element?.parentElement && !pageByElement.has(element.parentElement)) {\n element = element.parentElement;\n }\n return element ? nodes.get(element) : undefined;\n };\n\n // Content changes on any node, drawable or parked. Style that gpucanvas writes on page and\n // node elements is ignored.\n const mutations = new MutationObserver((records) => {\n // Outlined elements may have moved inside their nodes.\n ringRects.clear();\n let changed = false;\n for (const record of records) {\n const target = record.target as HTMLElement;\n if (\n record.type === 'attributes' &&\n (nodes.has(target) || pageByElement.has(target) || target === canvas)\n ) {\n continue;\n }\n const node = nodeOf(record.target);\n if (node && !node.dirty) {\n node.dirty = true;\n // Off screen it waits until it scrolls into view.\n if (!changed) changed = intersects(node.rect, viewNow());\n }\n }\n if (changed) schedule();\n });\n mutations.observe(canvas, {\n subtree: true,\n childList: true,\n characterData: true,\n attributes: true,\n });\n\n /** Releases a page from hit testing once nothing pins it; it parks after its next raster. */\n const unpin = (page: Page) => {\n if (isPinned(page)) return;\n if (page.registered) canvas.clearElementGeometry(page.element);\n page.registered = false;\n page.element.style.transform = '';\n schedule();\n };\n\n /**\n * Puts the live page's hit area under the live node. The draw matrix maps the page's\n * default-size snapshot (CSS px x dpr) to canvas pixels. A page promoted this frame has no\n * paint record yet, so it is positioned on the next frame.\n */\n const positionLivePage = () => {\n if (!live || livePositioned) return;\n const dpr = canvas.width / Math.max(1, canvas.clientWidth);\n const { zoom } = camera;\n const drawn = new DOMMatrix([\n zoom,\n 0,\n 0,\n zoom,\n ((live.rect.x - camera.x) * zoom - live.pageX * zoom) * dpr,\n ((live.rect.y - camera.y) * zoom - live.pageY * zoom) * dpr,\n ]);\n try {\n live.page.element.style.transform = canvas\n .getElementTransform(live.page.element, drawn)\n .toString();\n live.element.style.pointerEvents = 'auto';\n livePositioned = true;\n } catch {\n schedule();\n }\n };\n\n /** Moves the hit-test target to `node`: its page is registered and positioned under it. */\n const setLive = (node: Node | null) => {\n if (node === live) return;\n const previous = live;\n live = node;\n if (previous) {\n previous.element.style.pointerEvents = 'none';\n clearTimeout(lingerTimer);\n const earlier = lingering;\n lingering = previous;\n if (earlier && earlier !== previous) {\n earlier.dirty = true;\n unpin(earlier.page);\n }\n lingerTimer = window.setTimeout(() => {\n const last = lingering;\n if (!last) return;\n lingering = null;\n last.dirty = true;\n unpin(last.page);\n }, LINGER_MS);\n unpin(previous.page);\n }\n if (!node) return;\n const { page } = node;\n page.setDrawable(true, frameNumber);\n if (!page.registered) {\n canvas.updateElementGeometry(page.element, {});\n page.registered = true;\n }\n livePositioned = false;\n positionLivePage();\n schedule();\n };\n\n /** Makes the topmost node under the last pointer position live. */\n const pickLive = () => {\n if (!pointer) return setLive(null);\n const point = screenToWorld(camera, pointer);\n let hit: Node | null = null;\n for (const node of nodes.values()) if (containsPoint(node.rect, point)) hit = node;\n setLive(hit);\n };\n\n const onPointerMove = (event: PointerEvent) => {\n const bounds = canvas.getBoundingClientRect();\n pointer = { x: event.clientX - bounds.left, y: event.clientY - bounds.top };\n // A press in progress belongs to the live node (text selection, sliders) or to a pan.\n if (event.buttons === 0) pickLive();\n };\n const onPointerLeave = () => {\n pointer = null;\n setLive(null);\n };\n /** Where the last press landed, in world units, and when: effects such as shockwaves use it. */\n let press: Point = FAR_AWAY;\n let pressedAt = -Infinity;\n const onPointerDown = (event: PointerEvent) => {\n const bounds = canvas.getBoundingClientRect();\n press = screenToWorld(camera, {\n x: event.clientX - bounds.left,\n y: event.clientY - bounds.top,\n });\n pressedAt = performance.now();\n if (effects.size) schedule();\n };\n const onFocusIn = (event: FocusEvent) => {\n const node = nodeOf(event.target as HTMLElement) ?? null;\n if (node === focused) return;\n const previous = focused;\n focused = node;\n if (previous) {\n previous.dirty = true;\n unpin(previous.page);\n }\n if (node) {\n node.page.setDrawable(true, frameNumber);\n node.dirty = true;\n schedule();\n }\n };\n const onFocusOut = (event: FocusEvent) => {\n if (event.relatedTarget && canvas.contains(event.relatedTarget as globalThis.Node)) return;\n const previous = focused;\n focused = null;\n if (previous) {\n previous.dirty = true;\n unpin(previous.page);\n }\n };\n // An image that finishes loading changes pixels without changing the DOM.\n const onResourceLoad = (event: Event) => {\n const node = nodeOf(event.target as HTMLElement);\n if (!node) return;\n node.dirty = true;\n schedule();\n };\n canvas.addEventListener('load', onResourceLoad, true);\n // Snapshots taken before a web font arrived show the fallback font.\n const onFontsLoaded = () => {\n for (const node of nodes.values()) node.dirty = true;\n schedule();\n };\n document.fonts.addEventListener('loadingdone', onFontsLoaded);\n surface.addEventListener('pointermove', onPointerMove);\n surface.addEventListener('pointerleave', onPointerLeave);\n surface.addEventListener('pointerdown', onPointerDown, true);\n canvas.addEventListener('focusin', onFocusIn);\n canvas.addEventListener('focusout', onFocusOut);\n // A transition paints without touching the DOM, so a click (from a person or from script)\n // would leave a half-finished frame. A readable node in view that was just used keeps its page\n // pinned and redrawn on every paint until its transitions are over. Content that animates on\n // its own, like a looping indicator, keeps the cheaper refresh on mutations: pinning it would\n // repaint its whole page every frame. A deadline ends the pin, transitions in parked pages\n // never fire transitionend.\n const usedAt = new WeakMap<Node, number>();\n const onUse = (event: Event) => {\n const node = nodeOf(event.target as HTMLElement);\n if (node) usedAt.set(node, performance.now());\n };\n const transitionMs = (element: Element) => {\n const style = getComputedStyle(element);\n const seconds = (list: string) => list.split(',').map((value) => parseFloat(value) || 0);\n const durations = seconds(style.transitionDuration);\n const delays = seconds(style.transitionDelay);\n const longest = Math.max(...durations.map((d, i) => d + (delays[i % delays.length] ?? 0)));\n return Math.min(1000, longest * 1000);\n };\n const onTransitionRun = (event: Event) => {\n const node = nodeOf(event.target as HTMLElement);\n const now = performance.now();\n if (!node || now - (usedAt.get(node) ?? -Infinity) > USED_MS) return;\n if (!intersects(node.rect, viewNow())) return;\n if (Math.max(node.rect.width, node.rect.height) * camera.zoom < SMALL_NODE_PX) return;\n const ms = transitionMs(event.target as Element) + 32;\n const end = now + ms;\n if ((transitioning.get(node) ?? 0) >= end) return;\n transitioning.set(node, end);\n node.dirty = true;\n schedule();\n setTimeout(() => {\n if (transitioning.get(node) !== end) return;\n transitioning.delete(node);\n node.dirty = true;\n unpin(node.page);\n schedule();\n }, ms);\n };\n for (const type of USE_EVENTS) canvas.addEventListener(type, onUse, true);\n canvas.addEventListener('transitionrun', onTransitionRun);\n\n const setCamera = (next: Camera) => {\n camera = next;\n lastCameraChange = performance.now();\n // A moving canvas has no hover; the node under a still pointer becomes live once it rests.\n setLive(null);\n clearTimeout(settleTimer);\n settleTimer = window.setTimeout(() => {\n pickLive();\n schedule();\n }, SETTLE_MS);\n schedule();\n options.onCameraChange?.(camera);\n };\n const unbindInput = bindCameraInput(surface, () => camera, setCamera);\n\n const placeNode = (element: HTMLElement, rect: Rect) => {\n let slot = openPage?.place(rect.width, rect.height) ?? null;\n if (!slot) {\n const page = new Page(\n Math.max(pageSize, Math.ceil(rect.width)),\n Math.max(pageSize, Math.ceil(rect.height)),\n );\n pages.set(page, new Set());\n pageByElement.set(page.element, page);\n canvas.append(page.element);\n // Oversized nodes get a page of their own and leave the open page as it was.\n if (page.width === pageSize && page.height === pageSize) openPage = page;\n slot = page.place(rect.width, rect.height)!;\n }\n Object.assign(element.style, {\n position: 'absolute',\n left: `${slot.x}px`,\n top: `${slot.y}px`,\n width: `${rect.width}px`,\n height: `${rect.height}px`,\n });\n slot.page.element.append(element);\n return slot;\n };\n\n const releaseNode = (node: Node) => {\n const members = pages.get(node.page)!;\n members.delete(node);\n node.page.release();\n if (members.size === 0 && node.page !== openPage) {\n pages.delete(node.page);\n pageByElement.delete(node.page.element);\n node.page.element.remove();\n }\n };\n\n /**\n * Moves a node onto a page of its own. Chrome rasterizes a snapshot's whole source element at\n * the requested scale before cropping, so zoomed in, a crop from a shared page pays for every\n * node on it: about 100 ms at 16x for two dozen app screens, under 10 ms for one.\n * `moveBefore` keeps focus, running transitions and other DOM state across the move.\n */\n const lift = (node: Node) => {\n const previous = node.page;\n const wasLive = live === node;\n if (wasLive) setLive(null);\n const page = new Page(Math.ceil(node.rect.width), Math.ceil(node.rect.height));\n pages.set(page, new Set());\n pageByElement.set(page.element, page);\n canvas.append(page.element);\n page.place(node.rect.width, node.rect.height);\n const target = page.element as HTMLElement & {\n moveBefore?: (child: globalThis.Node, before: globalThis.Node | null) => void;\n };\n if (target.moveBefore) target.moveBefore(node.element, null);\n else target.append(node.element);\n node.element.style.left = '0px';\n node.element.style.top = '0px';\n releaseNode(node);\n node.page = page;\n node.pageX = 0;\n node.pageY = 0;\n node.solo = true;\n pages.get(page)!.add(node);\n // The whole snapshot is still valid: the node's pixels did not change, only its page.\n if (pages.has(previous) && !isPinned(previous)) {\n unpin(previous);\n previous.setDrawable(false, frameNumber);\n }\n if (wasLive) pickLive();\n };\n\n const attach = (node: Node) => {\n const slot = placeNode(node.element, node.rect);\n node.page = slot.page;\n node.pageX = slot.x;\n node.pageY = slot.y;\n node.slot = null;\n node.thumb = null;\n node.solo = false;\n node.dirty = true;\n pages.get(slot.page)!.add(node);\n };\n\n return {\n mode: 'gpu',\n surface,\n addNode(element, rect) {\n Object.assign(element.style, {\n boxSizing: 'border-box',\n contain: 'strict',\n overflow: 'hidden',\n pointerEvents: 'none',\n });\n const node = {\n element,\n rect,\n slotScale: 0,\n thumb: null,\n thumbStale: false,\n thumbAt: -Infinity,\n shown: 0,\n shownFrame: -1,\n targetScale: 0,\n tiles: [] as Tile[],\n preview: null,\n previewRect: null,\n previewScale: 0,\n previewTarget: null,\n previewTargetScale: 0,\n changedAt: -Infinity,\n refreshedAt: -Infinity,\n wholeStale: false,\n solo: false,\n priority: 0,\n } as Node;\n attach(node);\n nodes.set(element, node);\n schedule();\n },\n updateNode(element, rect) {\n const node = nodes.get(element);\n if (!node) return;\n const resized = node.rect.width !== rect.width || node.rect.height !== rect.height;\n node.rect = rect;\n ringRects.clear();\n if (resized) {\n if (live === node) setLive(null);\n releaseNode(node);\n attach(node);\n }\n schedule();\n },\n removeNode(element) {\n const node = nodes.get(element);\n if (!node) return;\n if (live === node) setLive(null);\n if (lingering === node) lingering = null;\n if (focused === node) focused = null;\n transitioning.delete(node);\n effects.delete(element);\n selection.delete(element);\n nodes.delete(element);\n releaseNode(node);\n element.remove();\n schedule();\n },\n getNodeRect: (element) => {\n const node = nodes.get(element);\n return node ? { ...node.rect } : null;\n },\n getNodesIn(rect) {\n const hits: HTMLElement[] = [];\n for (const node of nodes.values()) if (intersects(node.rect, rect)) hits.push(node.element);\n return hits;\n },\n getNodeOf: (element) => nodeOfElement(nodes, element),\n getElementRect(element) {\n const rect = ringRect(element);\n return rect ? { ...rect } : null;\n },\n getElementAt(point) {\n // The last node added draws on top.\n let top: Node | null = null;\n for (const node of nodes.values()) if (containsPoint(node.rect, point)) top = node;\n return top ? elementInNode(top.element, top.rect, point) : null;\n },\n setSelection(elements) {\n selection = new Set(elements);\n ringRects.clear();\n schedule();\n },\n setHover(element) {\n if (element === hovered) return;\n hovered = element;\n ringRects.clear();\n schedule();\n },\n setEffect(element, effect, params) {\n if (!nodes.has(element)) return;\n if (effect) {\n const values = effectParams(effect, params);\n effects.set(element, { effect, params: values, pad: effectPad(effect, values) });\n } else effects.delete(element);\n schedule();\n },\n screenToWorld: (point) => screenToWorld(camera, point),\n worldToScreen: (point) => worldToScreen(camera, point),\n getCamera: () => camera,\n setCamera,\n invalidate: onFontsLoaded,\n setBackground(color) {\n [renderer.background, renderer.placeholder] = colorsFor(color);\n schedule();\n },\n fit(padding) {\n const bounds = boundsOf([...nodes.values()].map((node) => node.rect));\n if (bounds) setCamera(fitCamera(bounds, canvas.clientWidth, canvas.clientHeight, padding));\n },\n getStats: () => ({\n mode: 'gpu',\n nodes: nodes.size,\n visible: stats.visible,\n pending: stats.pending,\n rasterizedLastFrame: stats.rasterizedLastFrame,\n rasterCallsLastFrame: stats.rasterCallsLastFrame,\n rasterMs: stats.rasterMs,\n pages: pages.size,\n drawablePages: [...pages.keys()].filter((page) => page.drawable).length,\n atlasLayersUsed: atlas.usedLayers,\n frameMs: stats.frameMs,\n frames: stats.frames,\n lostPixels: stats.lostPixels,\n lostDetail: stats.lostDetail,\n thumbnailFill: atlas.pinnedFill,\n onThumbnail: stats.onThumbnail,\n needs: stats.needs,\n }),\n destroy() {\n destroyed = true;\n cancelAnimationFrame(rafId);\n clearTimeout(settleTimer);\n clearTimeout(lingerTimer);\n clearTimeout(contentTimer);\n mutations.disconnect();\n document.fonts.removeEventListener('loadingdone', onFontsLoaded);\n canvas.removeEventListener('load', onResourceLoad, true);\n surface.removeEventListener('pointermove', onPointerMove);\n surface.removeEventListener('pointerleave', onPointerLeave);\n surface.removeEventListener('pointerdown', onPointerDown, true);\n canvas.removeEventListener('focusin', onFocusIn);\n canvas.removeEventListener('focusout', onFocusOut);\n canvas.removeEventListener('transitionrun', onTransitionRun);\n for (const type of USE_EVENTS) canvas.removeEventListener(type, onUse, true);\n unbindInput();\n resizeObserver.disconnect();\n canvas.onpaint = null;\n surface.remove();\n renderer.destroy();\n atlas.destroy();\n device.destroy();\n },\n };\n}\n","import { intersects, type Point, type Rect } from './camera';\nimport type { GpuCanvas } from './types';\n\n/**\n * A layer is what one click selects: one element, or several that act as one, such as a React\n * component that renders a fragment. Its first element is its identity.\n */\nexport type Layer = Element[];\n\n/**\n * What a click can select, from the element under the pointer. `'node'`: whole nodes only.\n * `'element'`: every element down to the one under the pointer. A function returns the layers\n * inside the node that hold `element`, outermost first; the node itself always comes before them.\n */\nexport type EditorPick =\n 'node' | 'element' | ((element: Element, canvas: GpuCanvas) => Array<Element | Element[]>);\n\nexport const sameLayer = (a: Layer | null | undefined, b: Layer | null | undefined) =>\n !!a && !!b && a[0] === b[0];\n\nexport const layerIn = (layer: Layer, list: readonly Layer[]) =>\n list.some((other) => sameLayer(layer, other));\n\n/** The union of a layer's elements in world units, or null when none is on the canvas. */\nexport function layerRect(canvas: GpuCanvas, layer: Layer): Rect | null {\n let union: Rect | null = null;\n for (const element of layer) {\n const rect = canvas.getElementRect(element);\n if (rect) union = union ? unionRect(union, rect) : rect;\n }\n return union;\n}\n\nexport function unionRect(a: Rect, b: Rect): Rect {\n const x = Math.min(a.x, b.x);\n const y = Math.min(a.y, b.y);\n return {\n x,\n y,\n width: Math.max(a.x + a.width, b.x + b.width) - x,\n height: Math.max(a.y + a.height, b.y + b.height) - y,\n };\n}\n\nconst sameRect = (a: Rect | null, b: Rect | null) =>\n !!a &&\n !!b &&\n Math.abs(a.x - b.x) < 0.5 &&\n Math.abs(a.y - b.y) < 0.5 &&\n Math.abs(a.width - b.width) < 0.5 &&\n Math.abs(a.height - b.height) < 0.5;\n\n/** Every depth a click can reach through the elements and pick of one canvas. */\nexport function createLayers(canvas: GpuCanvas, pick: EditorPick) {\n /** The layers holding `element`, outermost first, starting with its node. */\n const chainOf = (element: Element): Layer[] => {\n const node = canvas.getNodeOf(element);\n if (!node) return [];\n let inner: Layer[];\n if (pick === 'node') inner = [];\n else if (pick === 'element') {\n inner = [];\n for (let at: Element | null = element; at && at !== node; at = at.parentElement) {\n inner.unshift([at]);\n }\n } else {\n inner = pick(element, canvas)\n .map((layer) => [layer].flat())\n .filter((layer) => layer.length > 0 && layer[0] !== node);\n }\n // A wrapper the size of the layer around it is a click that seems to do nothing: skip it.\n const chain: Layer[] = [[node]];\n let previous = canvas.getNodeRect(node);\n for (const layer of inner) {\n const rect = layerRect(canvas, layer);\n if (sameRect(rect, previous)) continue;\n chain.push(layer);\n previous = rect;\n }\n return chain;\n };\n\n const chainAt = (world: Point): Layer[] => {\n const element = canvas.getElementAt(world);\n return element ? chainOf(element) : [];\n };\n\n /** The layers one level inside `parent`, in document order. */\n const childrenOf = (parent: Layer): Layer[] => {\n if (pick === 'node') return [];\n const children: Layer[] = [];\n if (pick === 'element') {\n // Element children, looking through wrappers the size of their parent.\n const visit = (element: Element, outer: Rect | null) => {\n for (const child of element.children) {\n const rect = canvas.getElementRect(child);\n if (!rect || rect.width <= 0 || rect.height <= 0) continue;\n if (sameRect(rect, outer)) visit(child, outer);\n else children.push([child]);\n }\n };\n for (const root of parent) visit(root, layerRect(canvas, parent));\n return children;\n }\n // Any other pick: the next layer on the chain of every element inside, skipping what an\n // earlier child already holds.\n for (const root of parent) {\n for (const element of root.querySelectorAll('*')) {\n if (children.some((child) => child.some((held) => held.contains(element)))) continue;\n const chain = chainOf(element);\n const index = chain.findIndex((layer) => sameLayer(layer, parent));\n const child = index >= 0 ? chain[index + 1] : undefined;\n if (child && !layerIn(child, children)) children.push(child);\n }\n }\n return children;\n };\n\n /** Layers at the top level (nodes) or inside `scope` that overlap a world rect. */\n const layersIn = (scope: Layer | null, rect: Rect): Layer[] =>\n scope\n ? childrenOf(scope).filter((layer) => {\n const box = layerRect(canvas, layer);\n return !!box && intersects(box, rect);\n })\n : canvas.getNodesIn(rect).map((node) => [node]);\n\n return { chainOf, chainAt, childrenOf, layersIn };\n}\n\nexport type Layers = ReturnType<typeof createLayers>;\n","import type { Rect } from './camera';\nimport type { Guide } from './snap';\n\n/** Resize handles, by the edges they move. */\nexport const HANDLES = ['nw', 'n', 'ne', 'e', 'se', 's', 'sw', 'w'] as const;\nexport type Handle = (typeof HANDLES)[number];\n\nconst HANDLE_PX = 8;\nconst CURSORS: Record<Handle, string> = {\n nw: 'nwse-resize',\n se: 'nwse-resize',\n ne: 'nesw-resize',\n sw: 'nesw-resize',\n n: 'ns-resize',\n s: 'ns-resize',\n e: 'ew-resize',\n w: 'ew-resize',\n};\n\n/** What the overlay shows this frame, in surface pixels. */\nexport interface OverlayState {\n hover: { rect: Rect; name: string | null } | null;\n /** `size` is in world units: what the selection measures, at any zoom. */\n selection: { rect: Rect; size: Rect; name: string | null; count: number } | null;\n /** A frame around a selection of several layers. */\n bounds: boolean;\n handles: boolean;\n guides: Rect[];\n}\n\nconst pill = (color: string) => ({\n position: 'absolute',\n font: '500 11px/16px system-ui, sans-serif',\n padding: '0 5px',\n borderRadius: '3px',\n color: '#fff',\n background: color,\n whiteSpace: 'nowrap',\n pointerEvents: 'none',\n});\n\n/**\n * The editor's chrome above the canvas: names and sizes, a frame and handles around the\n * selection, and snapping guides. Outlines themselves are drawn by the canvas.\n */\nexport function createOverlay(surface: HTMLElement, color: string, hoverColor: string) {\n const root = document.createElement('div');\n Object.assign(root.style, {\n position: 'absolute',\n inset: '0',\n overflow: 'hidden',\n pointerEvents: 'none',\n zIndex: '2',\n });\n const make = (style: Record<string, string>) => {\n const element = document.createElement('div');\n Object.assign(element.style, { left: '0', top: '0' }, style, { display: 'none' });\n root.append(element);\n return element;\n };\n const hoverName = make(pill(hoverColor));\n const name = make(pill(color));\n const size = make(pill(color));\n const bounds = make({ position: 'absolute', border: `1px solid ${color}` });\n const handles = HANDLES.map((handle) => {\n const element = make({\n position: 'absolute',\n width: `${HANDLE_PX}px`,\n height: `${HANDLE_PX}px`,\n boxSizing: 'border-box',\n background: '#fff',\n border: `1px solid ${color}`,\n pointerEvents: 'auto',\n cursor: CURSORS[handle],\n });\n element.dataset.gpucanvasHandle = handle;\n return element;\n });\n const guides: HTMLElement[] = [];\n surface.append(root);\n\n const show = (element: HTMLElement, visible: boolean) => {\n element.style.display = visible ? 'block' : 'none';\n };\n const place = (element: HTMLElement, x: number, y: number) => {\n element.style.transform = `translate(${Math.round(x)}px, ${Math.round(y)}px)`;\n };\n const text = (element: HTMLElement, value: string) => {\n if (element.textContent !== value) element.textContent = value;\n };\n\n return {\n render(state: OverlayState) {\n const { hover, selection } = state;\n show(hoverName, !!hover?.name);\n if (hover?.name) {\n text(hoverName, hover.name);\n place(hoverName, hover.rect.x - 1, hover.rect.y - 19);\n }\n show(name, !!selection?.name);\n show(size, !!selection);\n show(bounds, !!selection && state.bounds);\n for (const handle of handles) show(handle, !!selection && state.handles);\n if (selection) {\n const { rect } = selection;\n if (selection.name) {\n text(name, selection.name);\n place(name, rect.x - 1, rect.y - 19);\n }\n const { width, height } = selection.size;\n const label = `${Math.round(width)} × ${Math.round(height)}`;\n text(size, selection.count > 1 ? `${selection.count} layers · ${label}` : label);\n // Centered under the selection; its width is known once it has text.\n place(size, rect.x + rect.width / 2 - size.offsetWidth / 2, rect.y + rect.height + 6);\n if (state.bounds) {\n place(bounds, rect.x, rect.y);\n bounds.style.width = `${rect.width}px`;\n bounds.style.height = `${rect.height}px`;\n }\n if (state.handles) {\n HANDLES.forEach((handle, i) => {\n const fx = handle.includes('w') ? 0 : handle.includes('e') ? 1 : 0.5;\n const fy = handle.includes('n') ? 0 : handle.includes('s') ? 1 : 0.5;\n place(\n handles[i],\n rect.x + rect.width * fx - HANDLE_PX / 2,\n rect.y + rect.height * fy - HANDLE_PX / 2,\n );\n });\n }\n }\n // Guides are lines in surface pixels: rects one pixel thick.\n while (guides.length < state.guides.length) {\n guides.push(make({ position: 'absolute', background: '#f43f5e' }));\n }\n guides.forEach((line, i) => {\n const guide = state.guides[i];\n show(line, !!guide);\n if (!guide) return;\n place(line, guide.x, guide.y);\n line.style.width = `${Math.max(1, guide.width)}px`;\n line.style.height = `${Math.max(1, guide.height)}px`;\n });\n },\n remove() {\n root.remove();\n },\n };\n}\n\n/** A world guide as a one-pixel rect in surface pixels. */\nexport const guideRect = (\n guide: Guide,\n toScreen: (x: number, y: number) => { x: number; y: number },\n): Rect => {\n const a = toScreen(guide.x1, guide.y1);\n const b = toScreen(guide.x2, guide.y2);\n return {\n x: Math.min(a.x, b.x),\n y: Math.min(a.y, b.y),\n width: Math.abs(b.x - a.x),\n height: Math.abs(b.y - a.y),\n };\n};\n","import type { Rect } from './camera';\n\n/** A line drawn while something snaps, in world units. */\nexport interface Guide {\n x1: number;\n y1: number;\n x2: number;\n y2: number;\n}\n\n/** Fractions of a rect's width or height that snap: its start, middle and end. */\nexport const ALL_ANCHORS = [0, 0.5, 1];\n\nconst anchorsX = (rect: Rect) => ALL_ANCHORS.map((f) => rect.x + rect.width * f);\nconst anchorsY = (rect: Rect) => ALL_ANCHORS.map((f) => rect.y + rect.height * f);\n\n/** The smallest shift within `threshold` that lines one of `moving` up with one of `lines`. */\nfunction nearest(moving: number[], lines: number[], threshold: number): number {\n let best = Infinity;\n for (const from of moving) {\n for (const to of lines) {\n const delta = to - from;\n if (Math.abs(delta) <= threshold && Math.abs(delta) < Math.abs(best)) best = delta;\n }\n }\n return best === Infinity ? 0 : best;\n}\n\n/**\n * How far to shift `rect` so the anchors listed in `edges` (fractions of its width and height)\n * line up with the start, middle or end of a target, and the guides that show it.\n */\nexport function snapRect(\n rect: Rect,\n targets: readonly Rect[],\n threshold: number,\n edges: { x: number[]; y: number[] } = { x: ALL_ANCHORS, y: ALL_ANCHORS },\n): { dx: number; dy: number; guides: Guide[] } {\n const xs = targets.flatMap(anchorsX);\n const ys = targets.flatMap(anchorsY);\n const dx = nearest(\n edges.x.map((f) => rect.x + rect.width * f),\n xs,\n threshold,\n );\n const dy = nearest(\n edges.y.map((f) => rect.y + rect.height * f),\n ys,\n threshold,\n );\n const moved = { ...rect, x: rect.x + dx, y: rect.y + dy };\n return { dx, dy, guides: guidesFor(moved, targets, edges) };\n}\n\n/** One line per aligned position, spanning the moved rect and every target on it. */\nfunction guidesFor(rect: Rect, targets: readonly Rect[], edges: { x: number[]; y: number[] }) {\n const guides: Guide[] = [];\n const close = (a: number, b: number) => Math.abs(a - b) < 0.01;\n for (const f of edges.x) {\n const x = rect.x + rect.width * f;\n const hits = targets.filter((target) => anchorsX(target).some((at) => close(at, x)));\n if (!hits.length) continue;\n const top = Math.min(rect.y, ...hits.map((t) => t.y));\n const bottom = Math.max(rect.y + rect.height, ...hits.map((t) => t.y + t.height));\n guides.push({ x1: x, y1: top, x2: x, y2: bottom });\n }\n for (const f of edges.y) {\n const y = rect.y + rect.height * f;\n const hits = targets.filter((target) => anchorsY(target).some((at) => close(at, y)));\n if (!hits.length) continue;\n const left = Math.min(rect.x, ...hits.map((t) => t.x));\n const right = Math.max(rect.x + rect.width, ...hits.map((t) => t.x + t.width));\n guides.push({ x1: left, y1: y, x2: right, y2: y });\n }\n return guides;\n}\n","import { screenToWorld, visibleWorldRect, type Point, type Rect } from './camera';\nimport {\n createLayers,\n layerIn,\n layerRect,\n sameLayer,\n unionRect,\n type EditorPick,\n type Layer,\n} from './layers';\nimport { createOverlay, guideRect, type Handle } from './overlay';\nimport { snapRect, type Guide } from './snap';\nimport { DEFAULT_SELECTION_COLOR, type GpuCanvas } from './types';\n\nexport interface TransformEvent {\n phase: 'start' | 'move' | 'end' | 'cancel';\n kind: 'move' | 'resize';\n /** What is being moved or resized. */\n layers: Layer[];\n /** Each layer's rect when the gesture started, world units. */\n from: Rect[];\n /** Where each layer should be now. On `cancel` it equals `from`. */\n to: Rect[];\n}\n\nexport interface EditorOptions {\n /** What a click can select, and how deep a double-click goes. Default `'node'`. */\n pick?: EditorPick;\n /**\n * `'shift-click'` (default): clicks still reach the components. Shift-click selects,\n * shift-cmd-click (shift-ctrl-click) adds or removes, shift-drag draws a selection box.\n * `'click'`: an edit mode. Every click selects, shift-click adds or removes, drags move, and\n * shift-drag on the background draws a selection box.\n * Either way, a double-click goes one layer deeper, and a drag on the open area of the layer\n * you are inside draws a box over its children.\n */\n trigger?: 'shift-click' | 'click';\n /** Outlines what a click would select. With `'shift-click'`, only while shift is held. Default true. */\n hover?: boolean;\n /** Shift-drag draws a box that selects the layers it touches. Default true. */\n marquee?: boolean;\n /** Names and sizes next to the selection and the hovered layer. Default true. */\n labels?: boolean;\n /** A layer's name for its label. Default: the element's tag inside nodes, nothing for nodes. */\n label?: (layer: Layer) => string | null;\n /** Moves and resizes snap to the edges and centers of their neighbors. Default true. */\n snap?: boolean;\n /** Called with the new selection after every change. */\n onChange?: (selected: Layer[]) => void;\n /**\n * Called through every move and resize. The editor never moves anything itself: apply `to`\n * (`updateNode`, state, styles) to make it real. Handles and drag-to-move need this and the\n * `'click'` trigger.\n */\n onTransform?: (event: TransformEvent) => void;\n /** Labels, frame and handles. Default `#4f8cff`. */\n color?: string;\n}\n\nexport interface Editor {\n get(): Layer[];\n /** Selects these layers at the top level. */\n set(layers: Iterable<Element | Element[]>): void;\n clear(): void;\n /** Removes the listeners, the chrome and the outlines. */\n destroy(): void;\n}\n\ntype MarqueeCanvas = Pick<GpuCanvas, 'surface' | 'getCamera' | 'getNodesIn' | 'setSelection'>;\n\n/**\n * A selection box over the canvas, in surface pixels. What it overlaps is selected as it grows,\n * by default every node, so the outlines sweep across the canvas with it.\n */\nexport function createMarquee(\n canvas: MarqueeCanvas,\n color = DEFAULT_SELECTION_COLOR,\n select: (world: Rect) => Element[] = (world) => canvas.getNodesIn(world),\n) {\n const box = document.createElement('div');\n Object.assign(box.style, {\n position: 'absolute',\n display: 'none',\n pointerEvents: 'none',\n border: `1px solid ${color}`,\n background: `color-mix(in srgb, ${color} 12%, transparent)`,\n zIndex: '1',\n });\n canvas.surface.append(box);\n return {\n /** Spans the box from `a` to `b` (surface pixels) and selects what it covers. */\n update(a: Point, b: Point): Element[] {\n const x = Math.min(a.x, b.x);\n const y = Math.min(a.y, b.y);\n const width = Math.abs(b.x - a.x);\n const height = Math.abs(b.y - a.y);\n Object.assign(box.style, {\n display: 'block',\n left: `${x}px`,\n top: `${y}px`,\n width: `${width}px`,\n height: `${height}px`,\n });\n const camera = canvas.getCamera();\n const hits = select({\n ...screenToWorld(camera, { x, y }),\n width: width / camera.zoom,\n height: height / camera.zoom,\n });\n canvas.setSelection(hits);\n return hits;\n },\n hide() {\n box.style.display = 'none';\n },\n remove() {\n box.remove();\n },\n };\n}\n\n/** How far a press may move and still count as a click, in CSS pixels. */\nconst CLICK_SLOP = 4;\n/** How close an edge has to come to snap, in CSS pixels. */\nconst SNAP_PX = 6;\n/** Above this many layers the selection shows one size, not each name. */\nconst MAX_NAMED = 1;\n\nconst isEditable = (element: Element | null) =>\n !!element &&\n (element instanceof HTMLInputElement ||\n element instanceof HTMLTextAreaElement ||\n element instanceof HTMLSelectElement ||\n (element as HTMLElement).isContentEditable);\n\ntype Gesture =\n /** `inside`: the press is on the open area of the scope itself, where a drag draws a box. */\n | { kind: 'press'; start: Point; additive: boolean; target: Target; inside: boolean }\n | { kind: 'marquee'; start: Point }\n | {\n kind: 'move' | 'resize';\n start: Point;\n handle: Handle | null;\n layers: Layer[];\n from: Rect[];\n bounds: Rect;\n to: Rect[];\n targets: Rect[];\n guides: Guide[];\n };\n\n/** A layer a click lands on, and the layers it sits inside, outermost first. */\ninterface Target {\n layer: Layer;\n scopes: Layer[];\n}\n\n/**\n * A canvas editor's selection: click, double-click to go deeper, hover, box selection,\n * keyboard navigation, labels, and moving and resizing with snapping. The canvas draws the\n * outlines; the editor draws the rest above it.\n */\nexport function bindEditor(canvas: GpuCanvas, options: EditorOptions = {}): Editor {\n const {\n pick = 'node',\n trigger = 'shift-click',\n hover = true,\n marquee = true,\n labels = true,\n snap = true,\n color = DEFAULT_SELECTION_COLOR,\n onChange,\n onTransform,\n } = options;\n const label =\n options.label ??\n ((layer: Layer) => (canvas.getNodeOf(layer[0]) === layer[0] ? null : layer[0].localName));\n const { surface } = canvas;\n const layers = createLayers(canvas, pick);\n const transforms = !!onTransform && trigger === 'click';\n const overlay = createOverlay(surface, color, color);\n let marqueeLayers: Layer[] = [];\n const box = marquee\n ? createMarquee(canvas, color, (world) => {\n marqueeLayers = layers.layersIn(scopes.at(-1) ?? null, world);\n return marqueeLayers.flat();\n })\n : null;\n\n let selection: Layer[] = [];\n /** The layers the selection sits inside, outermost first. Clicks stay at its depth. */\n let scopes: Layer[] = [];\n let hovered: Layer | null = null;\n let gesture: Gesture | null = null;\n let pointer: Point | null = null;\n let shift = false;\n let swallowClick = false;\n\n const commit = (next: Layer[], nextScopes: Layer[] = scopes) => {\n selection = next.filter((layer, i) => next.findIndex((other) => sameLayer(layer, other)) === i);\n scopes = selection.length ? nextScopes : [];\n canvas.setSelection(selection.flat());\n onChange?.(selection);\n draw();\n };\n const setHovered = (layer: Layer | null) => {\n if (sameLayer(layer, hovered) || layer === hovered) return;\n hovered = layer;\n canvas.setHover(layer?.[0] ?? null);\n draw();\n };\n const at = (event: MouseEvent): Point => {\n const bounds = surface.getBoundingClientRect();\n return { x: event.clientX - bounds.left, y: event.clientY - bounds.top };\n };\n const chainAt = (point: Point) => layers.chainAt(canvas.screenToWorld(point));\n /** What a click lands on: inside the deepest scope on the chain, one level down from it. */\n const targetIn = (chain: Layer[]): Target | null => {\n if (!chain.length) return null;\n for (let i = scopes.length - 1; i >= 0; i--) {\n const k = chain.findIndex((layer) => sameLayer(layer, scopes[i]));\n if (k < 0) continue;\n return k + 1 < chain.length\n ? { layer: chain[k + 1], scopes: chain.slice(0, k + 1) }\n : { layer: chain[k], scopes: chain.slice(0, k) };\n }\n return { layer: chain[0], scopes: [] };\n };\n const selecting = (withShift: boolean) => trigger === 'click' || withShift;\n const updateHover = () => {\n const show = hover && pointer && !gesture && selecting(shift);\n setHovered(show ? (targetIn(chainAt(pointer!))?.layer ?? null) : null);\n };\n\n // ----- chrome ---------------------------------------------------------------------------\n\n let frame = 0;\n /** Redraws the chrome every frame while there is any, so it follows the camera and layout. */\n const draw = () => {\n if (!frame) frame = requestAnimationFrame(render);\n };\n const toScreen = (rect: Rect): Rect => {\n const { x, y } = canvas.worldToScreen(rect);\n const zoom = canvas.getCamera().zoom;\n return { x, y, width: rect.width * zoom, height: rect.height * zoom };\n };\n const unionOf = (rects: (Rect | null)[]) =>\n rects.reduce<Rect | null>(\n (union, rect) => (!rect ? union : union ? unionRect(union, rect) : rect),\n null,\n );\n const render = () => {\n frame = 0;\n const transforming = gesture?.kind === 'move' || gesture?.kind === 'resize' ? gesture : null;\n const world = transforming\n ? unionOf(transforming.to)\n : selection.length\n ? unionOf(selection.map((layer) => layerRect(canvas, layer)))\n : null;\n const hoverRect = hovered && !layerIn(hovered, selection) ? layerRect(canvas, hovered) : null;\n overlay.render({\n hover: labels && hoverRect ? { rect: toScreen(hoverRect), name: label(hovered!) } : null,\n selection:\n labels && world\n ? {\n rect: toScreen(world),\n size: world,\n name: selection.length <= MAX_NAMED ? label(selection[0]) : null,\n count: selection.length,\n }\n : null,\n bounds: selection.length > 1 || !!transforming,\n handles: transforms && selection.length > 0 && gesture?.kind !== 'marquee',\n guides: transforming\n ? transforming.guides.map((guide) =>\n guideRect(guide, (x, y) => canvas.worldToScreen({ x, y })),\n )\n : [],\n });\n if (selection.length || hovered || gesture) draw();\n };\n\n // ----- moving and resizing ----------------------------------------------------------------\n\n const emit = (phase: TransformEvent['phase']) => {\n if (gesture?.kind !== 'move' && gesture?.kind !== 'resize') return;\n onTransform?.({\n phase,\n kind: gesture.kind,\n layers: gesture.layers,\n from: gesture.from,\n to: phase === 'cancel' ? gesture.from : gesture.to,\n });\n };\n /** Neighbors to snap to: the other layers in the same scope, and the scope itself. */\n const snapTargets = (moving: Layer[]): Rect[] => {\n if (!snap) return [];\n const scope = scopes.at(-1);\n if (!scope) {\n const view = visibleWorldRect(canvas.getCamera(), surface.clientWidth, surface.clientHeight);\n return canvas\n .getNodesIn(view)\n .filter((node) => !moving.some((layer) => layer[0] === node))\n .map((node) => canvas.getNodeRect(node)!);\n }\n const rects = layers\n .childrenOf(scope)\n .filter((layer) => !layerIn(layer, moving))\n .map((layer) => layerRect(canvas, layer));\n return [layerRect(canvas, scope), ...rects].filter((rect): rect is Rect => !!rect);\n };\n const beginTransform = (start: Point, handle: Handle | null) => {\n const from = selection.map((layer) => layerRect(canvas, layer));\n if (from.some((rect) => !rect)) return;\n const rects = from as Rect[];\n gesture = {\n kind: handle ? 'resize' : 'move',\n start,\n handle,\n layers: selection,\n from: rects,\n bounds: unionOf(rects)!,\n to: rects,\n targets: snapTargets(selection),\n guides: [],\n };\n setHovered(null);\n emit('start');\n };\n const updateTransform = (point: Point, keepRatio: boolean) => {\n if (gesture?.kind !== 'move' && gesture?.kind !== 'resize') return;\n const zoom = canvas.getCamera().zoom;\n let dx = (point.x - gesture.start.x) / zoom;\n let dy = (point.y - gesture.start.y) / zoom;\n const { bounds, handle } = gesture;\n const threshold = SNAP_PX / zoom;\n let next: Rect;\n if (!handle) {\n // Shift keeps a move on its main axis.\n if (keepRatio) Math.abs(dx) > Math.abs(dy) ? (dy = 0) : (dx = 0);\n next = { ...bounds, x: bounds.x + dx, y: bounds.y + dy };\n const snapped = snapRect(next, gesture.targets, threshold);\n next = { ...next, x: next.x + snapped.dx, y: next.y + snapped.dy };\n gesture.guides = snapped.guides;\n } else {\n let left = bounds.x;\n let top = bounds.y;\n let right = bounds.x + bounds.width;\n let bottom = bounds.y + bounds.height;\n if (handle.includes('w')) left = Math.min(left + dx, right - 1);\n if (handle.includes('e')) right = Math.max(right + dx, left + 1);\n if (handle.includes('n')) top = Math.min(top + dy, bottom - 1);\n if (handle.includes('s')) bottom = Math.max(bottom + dy, top + 1);\n next = { x: left, y: top, width: right - left, height: bottom - top };\n const corner = handle.length === 2;\n if (keepRatio && corner) {\n // Shift on a corner keeps the proportions, anchored at the opposite corner.\n const scale = Math.max(next.width / bounds.width, next.height / bounds.height);\n const width = bounds.width * scale;\n const height = bounds.height * scale;\n next = {\n x: handle.includes('w') ? right - width : left,\n y: handle.includes('n') ? bottom - height : top,\n width,\n height,\n };\n gesture.guides = [];\n } else {\n const edges = {\n x: handle.includes('w') ? [0] : handle.includes('e') ? [1] : [],\n y: handle.includes('n') ? [0] : handle.includes('s') ? [1] : [],\n };\n const snapped = snapRect(next, gesture.targets, threshold, edges);\n if (edges.x[0] === 0)\n next = { ...next, x: next.x + snapped.dx, width: next.width - snapped.dx };\n if (edges.x[0] === 1) next = { ...next, width: next.width + snapped.dx };\n if (edges.y[0] === 0)\n next = { ...next, y: next.y + snapped.dy, height: next.height - snapped.dy };\n if (edges.y[0] === 1) next = { ...next, height: next.height + snapped.dy };\n gesture.guides = snapped.guides;\n }\n }\n // Every layer keeps its place inside the group.\n const sx = next.width / bounds.width;\n const sy = next.height / bounds.height;\n gesture.to = gesture.from.map((rect) => ({\n x: next.x + (rect.x - bounds.x) * sx,\n y: next.y + (rect.y - bounds.y) * sy,\n width: rect.width * sx,\n height: rect.height * sy,\n }));\n emit('move');\n draw();\n };\n\n // ----- input ------------------------------------------------------------------------------\n\n const onPointerDown = (event: PointerEvent) => {\n shift = event.shiftKey;\n swallowClick = false;\n if (event.button !== 0) return;\n const point = at(event);\n const take = () => {\n // Nothing under the pointer sees this press, nor the click it ends in.\n event.stopPropagation();\n swallowClick = true;\n surface.setPointerCapture(event.pointerId);\n };\n const handle = (event.target as Element).closest?.<HTMLElement>('[data-gpucanvas-handle]');\n if (handle && transforms) {\n take();\n return beginTransform(point, handle.dataset.gpucanvasHandle as Handle);\n }\n const target = targetIn(chainAt(point));\n if (!target) {\n if (event.shiftKey && box) {\n take();\n gesture = { kind: 'marquee', start: point };\n return;\n }\n // A plain press on the background clears, and still pans the camera.\n if (selection.length) commit([], []);\n return;\n }\n if (!selecting(event.shiftKey)) return;\n take();\n // Adding and removing is shift-click in the edit mode, and shift with cmd or ctrl where a\n // shift-click is what selects.\n const additive =\n trigger === 'click' ? event.shiftKey : event.shiftKey && (event.metaKey || event.ctrlKey);\n const inside = !!box && sameLayer(target.layer, scopes.at(-1));\n // A press selects at once, so the drag that follows moves it.\n if (!additive && !inside && !layerIn(target.layer, selection)) {\n commit([target.layer], target.scopes);\n }\n gesture = { kind: 'press', start: point, additive, target, inside };\n setHovered(null);\n };\n const onPointerMove = (event: PointerEvent) => {\n shift = event.shiftKey;\n pointer = at(event);\n if (!gesture) return updateHover();\n if (gesture.kind === 'press') {\n if (Math.hypot(pointer.x - gesture.start.x, pointer.y - gesture.start.y) <= CLICK_SLOP)\n return;\n // Dragging moves in the edit mode, and draws a selection box otherwise.\n if (gesture.inside || (trigger !== 'click' && box)) {\n gesture = { kind: 'marquee', start: gesture.start };\n } else if (trigger === 'click' && transforms) beginTransform(gesture.start, null);\n else return;\n }\n if (gesture?.kind === 'marquee') {\n box!.update(gesture.start, pointer);\n selection = marqueeLayers;\n onChange?.(selection);\n draw();\n } else updateTransform(pointer, event.shiftKey);\n };\n const onPointerUp = () => {\n const done = gesture;\n gesture = null;\n if (!done) return;\n if (done.kind === 'marquee') {\n box!.hide();\n commit(marqueeLayers);\n } else if (done.kind === 'press') {\n const { layer, scopes: inside } = done.target;\n if (!done.additive) commit([layer], inside);\n else if (layerIn(layer, selection))\n commit(selection.filter((other) => !sameLayer(other, layer)));\n else commit([...selection, layer], inside);\n } else {\n gesture = done;\n emit('end');\n gesture = null;\n }\n updateHover();\n draw();\n };\n const onDoubleClick = (event: MouseEvent) => {\n if (!selecting(event.shiftKey)) return;\n event.preventDefault();\n event.stopPropagation();\n // One level deeper than the selection, under the pointer.\n const chain = chainAt(at(event));\n let depth = -1;\n chain.forEach((layer, i) => {\n if (layerIn(layer, selection)) depth = i;\n });\n if (depth >= 0 && chain[depth + 1]) commit([chain[depth + 1]], chain.slice(0, depth + 1));\n };\n const onPointerLeave = () => {\n pointer = null;\n setHovered(null);\n };\n // A press the editor takes would otherwise focus, or select text in, the component under it.\n const onMouseDown = (event: MouseEvent) => {\n if (!swallowClick) return;\n event.preventDefault();\n event.stopPropagation();\n };\n const onClick = (event: MouseEvent) => {\n if (!swallowClick) return;\n swallowClick = false;\n event.preventDefault();\n event.stopPropagation();\n };\n const up = () => {\n const parent = scopes.at(-1);\n if (parent) commit([parent], scopes.slice(0, -1));\n };\n const onKey = (event: KeyboardEvent) => {\n if (event.key === 'Shift') {\n shift = event.type === 'keydown';\n return updateHover();\n }\n if (event.type !== 'keydown' || isEditable(document.activeElement)) return;\n if (event.key === 'Escape') {\n if (gesture?.kind === 'move' || gesture?.kind === 'resize') {\n emit('cancel');\n gesture = null;\n } else if (scopes.length) up();\n else if (selection.length) commit([], []);\n return;\n }\n if (!selection.length) return;\n if (event.key === 'Enter') {\n event.preventDefault();\n if (event.shiftKey) return up();\n const first = layers.childrenOf(selection[0])[0];\n if (first) commit([first], [...scopes, selection[0]]);\n } else if (event.key === 'Tab') {\n event.preventDefault();\n const scope = scopes.at(-1);\n const siblings = scope\n ? layers.childrenOf(scope)\n : canvas.getNodesIn({ x: -1e9, y: -1e9, width: 2e9, height: 2e9 }).map((node) => [node]);\n const index = siblings.findIndex((layer) => sameLayer(layer, selection[0]));\n const step = event.shiftKey ? -1 : 1;\n const next = siblings[(index + step + siblings.length) % siblings.length];\n if (next) commit([next]);\n }\n };\n\n surface.addEventListener('pointerdown', onPointerDown, true);\n surface.addEventListener('mousedown', onMouseDown, true);\n surface.addEventListener('click', onClick, true);\n surface.addEventListener('dblclick', onDoubleClick, true);\n surface.addEventListener('pointermove', onPointerMove);\n surface.addEventListener('pointerup', onPointerUp);\n surface.addEventListener('pointercancel', onPointerUp);\n surface.addEventListener('pointerleave', onPointerLeave);\n window.addEventListener('keydown', onKey);\n window.addEventListener('keyup', onKey);\n return {\n get: () => selection,\n set: (next) =>\n commit(\n [...next].map((layer) => [layer].flat()),\n [],\n ),\n clear: () => commit([], []),\n destroy() {\n surface.removeEventListener('pointerdown', onPointerDown, true);\n surface.removeEventListener('mousedown', onMouseDown, true);\n surface.removeEventListener('click', onClick, true);\n surface.removeEventListener('dblclick', onDoubleClick, true);\n surface.removeEventListener('pointermove', onPointerMove);\n surface.removeEventListener('pointerup', onPointerUp);\n surface.removeEventListener('pointercancel', onPointerUp);\n surface.removeEventListener('pointerleave', onPointerLeave);\n window.removeEventListener('keydown', onKey);\n window.removeEventListener('keyup', onKey);\n cancelAnimationFrame(frame);\n box?.remove();\n overlay.remove();\n canvas.setHover(null);\n canvas.setSelection([]);\n },\n };\n}\n","import { createDomCanvas } from './dom-backend';\nimport { createGpuCanvas as createGpuBackend, supportsGpuCanvas } from './gpu-backend';\nimport type { GpuCanvas, GpuCanvasOptions } from './types';\n\nexport type { Camera, Point, Rect } from './camera';\nexport { fitCamera, screenToWorld, worldToScreen, zoomAt } from './camera';\nexport type { Editor, EditorOptions, TransformEvent } from './editor';\nexport { bindEditor } from './editor';\nexport type { EditorPick, Layer } from './layers';\nexport type { Effect, EffectDefinition } from './effects';\nexport { defineEffect, EFFECTS as effects } from './effects';\nexport type { GpuCanvas, GpuCanvasMode, GpuCanvasOptions, GpuCanvasStats } from './types';\nexport { supportsGpuCanvas };\n\n/**\n * Creates an infinite canvas inside `host`. Uses WebGPU + HTML-in-Canvas when the browser has\n * both (Chrome 157+), and plain DOM transforms everywhere else; the API is the same.\n */\nexport async function createGpuCanvas(\n host: HTMLElement,\n options: GpuCanvasOptions = {},\n): Promise<GpuCanvas> {\n const mode = options.mode ?? 'auto';\n if (mode === 'dom' || (mode === 'auto' && !supportsGpuCanvas())) {\n return createDomCanvas(host, options);\n }\n try {\n return await createGpuBackend(host, options);\n } catch (error) {\n if (mode === 'gpu') throw error;\n return createDomCanvas(host, options);\n }\n}\n"],"mappings":";AAoBO,IAAM,gBAAgB,CAAC,QAAgB,WAAyB;AAAA,EACrE,GAAG,OAAO,IAAI,MAAM,IAAI,OAAO;AAAA,EAC/B,GAAG,OAAO,IAAI,MAAM,IAAI,OAAO;AACjC;AAGO,IAAM,gBAAgB,CAAC,QAAgB,WAAyB;AAAA,EACrE,IAAI,MAAM,IAAI,OAAO,KAAK,OAAO;AAAA,EACjC,IAAI,MAAM,IAAI,OAAO,KAAK,OAAO;AACnC;AAEO,IAAM,WAAW;AACjB,IAAM,WAAW;AAExB,IAAM,YAAY,CAAC,SAAiB,KAAK,IAAI,UAAU,KAAK,IAAI,UAAU,IAAI,CAAC;AAGxE,SAAS,OAAO,QAAgB,SAAiB,SAAiB,QAAwB;AAC/F,QAAM,OAAO,UAAU,OAAO,OAAO,MAAM;AAC3C,QAAM,SAAS,OAAO,IAAI,UAAU,OAAO;AAC3C,QAAM,SAAS,OAAO,IAAI,UAAU,OAAO;AAC3C,SAAO,EAAE,GAAG,SAAS,UAAU,MAAM,GAAG,SAAS,UAAU,MAAM,KAAK;AACxE;AAEO,SAAS,iBACd,QACA,eACA,gBACM;AACN,SAAO;AAAA,IACL,GAAG,OAAO;AAAA,IACV,GAAG,OAAO;AAAA,IACV,OAAO,gBAAgB,OAAO;AAAA,IAC9B,QAAQ,iBAAiB,OAAO;AAAA,EAClC;AACF;AAEO,IAAM,gBAAgB,CAAC,MAAY,UACxC,MAAM,KAAK,KAAK,KAChB,MAAM,IAAI,KAAK,IAAI,KAAK,SACxB,MAAM,KAAK,KAAK,KAChB,MAAM,IAAI,KAAK,IAAI,KAAK;AAEnB,IAAM,aAAa,CAAC,GAAS,MAClC,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,IAAI,EAAE;AAG/E,SAAS,UACd,QACA,eACA,gBACA,UAAU,IACF;AACR,QAAM,OAAO;AAAA,IACX,KAAK;AAAA,OACF,gBAAgB,UAAU,KAAK,KAAK,IAAI,GAAG,OAAO,KAAK;AAAA,OACvD,iBAAiB,UAAU,KAAK,KAAK,IAAI,GAAG,OAAO,MAAM;AAAA,IAC5D;AAAA,EACF;AACA,SAAO;AAAA,IACL,GAAG,OAAO,IAAI,OAAO,QAAQ,IAAI,gBAAgB,IAAI;AAAA,IACrD,GAAG,OAAO,IAAI,OAAO,SAAS,IAAI,iBAAiB,IAAI;AAAA,IACvD;AAAA,EACF;AACF;AAMO,SAAS,gBACd,SACA,WACA,UACY;AACZ,QAAM,UAAU,CAAC,UAAsB;AACrC,UAAM,eAAe;AACrB,UAAM,SAAS,QAAQ,sBAAsB;AAC7C,UAAM,SAAS,UAAU;AACzB,QAAI,MAAM,WAAW,MAAM,SAAS;AAClC,YAAM,SAAS,KAAK,IAAI,CAAC,MAAM,UAAU,MAAM,cAAc,IAAI,OAAO,KAAK;AAC7E,eAAS,OAAO,QAAQ,MAAM,UAAU,OAAO,MAAM,MAAM,UAAU,OAAO,KAAK,MAAM,CAAC;AAAA,IAC1F,OAAO;AACL,eAAS;AAAA,QACP,GAAG;AAAA,QACH,GAAG,OAAO,IAAI,MAAM,SAAS,OAAO;AAAA,QACpC,GAAG,OAAO,IAAI,MAAM,SAAS,OAAO;AAAA,MACtC,CAAC;AAAA,IACH;AAAA,EACF;AAEA,MAAI,OAA2D;AAC/D,QAAM,gBAAgB,CAAC,UAAwB;AAG7C,QAAK,MAAM,WAAW,KAAK,MAAM,WAAW,KAAM,MAAM,SAAU;AAClE,QACE,MAAM,WAAW,WACjB,CAAE,MAAM,OAAmB,eAAe,wBAAwB;AAElE;AACF,WAAO,EAAE,WAAW,MAAM,WAAW,GAAG,MAAM,SAAS,GAAG,MAAM,QAAQ;AACxE,YAAQ,kBAAkB,MAAM,SAAS;AAAA,EAC3C;AACA,QAAM,gBAAgB,CAAC,UAAwB;AAC7C,QAAI,CAAC,QAAQ,MAAM,cAAc,KAAK,UAAW;AACjD,UAAM,SAAS,UAAU;AACzB,aAAS;AAAA,MACP,GAAG;AAAA,MACH,GAAG,OAAO,KAAK,MAAM,UAAU,KAAK,KAAK,OAAO;AAAA,MAChD,GAAG,OAAO,KAAK,MAAM,UAAU,KAAK,KAAK,OAAO;AAAA,IAClD,CAAC;AACD,SAAK,IAAI,MAAM;AACf,SAAK,IAAI,MAAM;AAAA,EACjB;AACA,QAAM,cAAc,CAAC,UAAwB;AAC3C,QAAI,MAAM,cAAc,MAAM,UAAW,QAAO;AAAA,EAClD;AAEA,UAAQ,iBAAiB,SAAS,SAAS,EAAE,SAAS,MAAM,CAAC;AAC7D,UAAQ,iBAAiB,eAAe,aAAa;AACrD,UAAQ,iBAAiB,eAAe,aAAa;AACrD,UAAQ,iBAAiB,aAAa,WAAW;AACjD,UAAQ,iBAAiB,iBAAiB,WAAW;AACrD,SAAO,MAAM;AACX,YAAQ,oBAAoB,SAAS,OAAO;AAC5C,YAAQ,oBAAoB,eAAe,aAAa;AACxD,YAAQ,oBAAoB,eAAe,aAAa;AACxD,YAAQ,oBAAoB,aAAa,WAAW;AACpD,YAAQ,oBAAoB,iBAAiB,WAAW;AAAA,EAC1D;AACF;;;ACrGO,IAAM,eAAe,CAAC,eAC3B,OAAO,OAAO;AAAA,EACZ,UAAU;AAAA,EACV,QAAQ,CAAC;AAAA,EACT,KAAK;AAAA,EACL,GAAG;AACL,CAAC;AAGI,IAAM,eAAe,CAAC,QAAgB,WAC3C,CAAC,GAAG,GAAG,GAAG,CAAC,EAAE,IAAI,CAAC,MAAM,SAAS,CAAC,KAAK,OAAO,OAAO,CAAC,KAAK,CAAC;AAEvD,IAAM,YAAY,CAAC,QAAgB,WACxC,OAAO,OAAO,QAAQ,aAAa,OAAO,IAAI,MAAM,IAAI,OAAO;AAGjE,IAAM;AAAA;AAAA,EAAwB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAcvB,IAAM,MAAM,aAAa;AAAA,EAC9B,MAAM;AAAA,EACN,UAAU;AAAA,EACV,QAAQ,CAAC,EAAE;AAAA,EACX;AAAA;AAAA,IAAiB,GAAG,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAK9B,KAAK,CAAC,CAAC,KAAK,GAAG,SAAS,eAAgB,OAAO,QAAS,KAAK,QAAQ,CAAC,CAAC;AACzE,CAAC;AAGM,IAAM,YAAY,aAAa;AAAA,EACpC,MAAM;AAAA,EACN,QAAQ,CAAC,CAAC;AAAA,EACV;AAAA;AAAA,IAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMjB,KAAK,CAAC,CAAC,MAAM,MAAM,aAAa,MAAM;AACxC,CAAC;AAGM,IAAM,OAAO,aAAa;AAAA,EAC/B,MAAM;AAAA,EACN,QAAQ,CAAC,CAAC;AAAA,EACV,KAAK,CAAC,CAAC,MAAM,MAAM;AAAA,EACnB;AAAA;AAAA,IAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAejB,KAAK,CAAC,CAAC,MAAM,MAAM,QAAQ,SAAS,CAAC;AACvC,CAAC;AAMM,IAAM,OAAO,aAAa;AAAA,EAC/B,MAAM;AAAA,EACN,UAAU;AAAA,EACV,QAAQ,CAAC,MAAM,MAAM,GAAG,EAAE;AAAA,EAC1B,KAAK,CAAC,WAAW,OAAO,CAAC;AAAA,EACzB,QAAQ,KAAK;AAAA,EACb;AAAA;AAAA,IAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcjB,KAAK,CAAC,CAAC,GAAG,GAAG,GAAG,KAAK,GAAG,SAAS;AAC/B,UAAM,SAAS,SAAS,OAAO,OAAO,KAAK,IAAI,OAAO,CAAC;AACvD,UAAM,MAAM,CAAC,GAAG,GAAG,CAAC,EAAE,IAAI,CAAC,MAAM,KAAK,MAAM,IAAI,GAAG,CAAC,EAAE,KAAK,GAAG;AAC9D,WAAO,oBAAoB,SAAS,GAAG,QAAQ,CAAC,CAAC,UAAU,GAAG;AAAA,EAChE;AACF,CAAC;AAGM,IAAM,SAAS,aAAa;AAAA,EACjC,MAAM;AAAA,EACN,UAAU;AAAA,EACV,QAAQ,CAAC,GAAG,EAAE;AAAA,EACd,KAAK,CAAC,CAAC,SAAS,MAAM;AAAA,EACtB;AAAA;AAAA,IAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AASnB,CAAC;AAGM,IAAM,WAAW,aAAa;AAAA,EACnC,MAAM;AAAA,EACN,QAAQ,CAAC,CAAC;AAAA,EACV;AAAA;AAAA,IAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAMnB,CAAC;AAMM,IAAM,WAAW,aAAa;AAAA,EACnC,MAAM;AAAA,EACN,QAAQ,CAAC,GAAG;AAAA,EACZ;AAAA;AAAA,IAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUjB,KAAK,CAAC,CAAC,QAAQ,MAAM,WAAW,IAAI,QAAQ;AAC9C,CAAC;AAMM,IAAM,QAAQ,aAAa;AAAA,EAChC,MAAM;AAAA,EACN,UAAU;AAAA,EACV,QAAQ,CAAC,KAAK,GAAG;AAAA,EACjB;AAAA;AAAA,IAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA2BnB,CAAC;AAMM,IAAM,YAAY,aAAa;AAAA,EACpC,MAAM;AAAA,EACN,UAAU;AAAA,EACV,QAAQ,CAAC,KAAK,IAAI,EAAE;AAAA,EACpB;AAAA;AAAA,IAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAgBnB,CAAC;AAGM,IAAM,SAAS,aAAa;AAAA,EACjC,MAAM;AAAA,EACN,UAAU;AAAA,EACV;AAAA;AAAA,IAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAuBnB,CAAC;AAGM,IAAM,MAAM,aAAa;AAAA,EAC9B,MAAM;AAAA,EACN,UAAU;AAAA,EACV;AAAA;AAAA,IAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAoBnB,CAAC;AAMM,IAAM,QAAQ,aAAa;AAAA,EAChC,MAAM;AAAA,EACN,UAAU;AAAA,EACV,QAAQ,CAAC,GAAG;AAAA,EACZ;AAAA;AAAA,IAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA0BnB,CAAC;AAMM,IAAM,SAAS,aAAa;AAAA,EACjC,MAAM;AAAA,EACN,UAAU;AAAA,EACV,QAAQ,CAAC,KAAK,CAAC;AAAA,EACf;AAAA;AAAA,IAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAqBnB,CAAC;AAEM,IAAM,UAAU;AAAA,EACrB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;;;AC9YO,SAAS,WAAW,MAAmB,UAAgB,SAAwB;AACpF,MAAI,YAAY,KAAM,QAAO,EAAE,GAAG,SAAS;AAC3C,QAAM,QAAQ,KAAK,sBAAsB;AACzC,QAAM,QAAQ,QAAQ,sBAAsB;AAC5C,QAAM,QAAQ,MAAM,QAAQ,IAAI,SAAS,QAAQ,MAAM,QAAQ;AAC/D,SAAO;AAAA,IACL,GAAG,SAAS,KAAK,MAAM,OAAO,MAAM,QAAQ;AAAA,IAC5C,GAAG,SAAS,KAAK,MAAM,MAAM,MAAM,OAAO;AAAA,IAC1C,OAAO,MAAM,QAAQ;AAAA,IACrB,QAAQ,MAAM,SAAS;AAAA,EACzB;AACF;AAMO,SAAS,cAAc,MAAmB,UAAgB,OAAuB;AACtF,QAAM,QAAQ,KAAK,sBAAsB;AACzC,QAAM,QAAQ,SAAS,QAAQ,IAAI,MAAM,QAAQ,SAAS,QAAQ;AAClE,QAAM,IAAI,MAAM,QAAQ,MAAM,IAAI,SAAS,KAAK;AAChD,QAAM,IAAI,MAAM,OAAO,MAAM,IAAI,SAAS,KAAK;AAC/C,MAAI,MAAe;AACnB,UAAS,YAAS;AAChB,aAAS,QAAQ,IAAI,kBAAkB,OAAO,QAAQ,MAAM,wBAAwB;AAClF,YAAM,MAAM,MAAM,sBAAsB;AACxC,UACE,IAAI,QAAQ,KACZ,IAAI,SAAS,KACb,KAAK,IAAI,QACT,IAAI,IAAI,SACR,KAAK,IAAI,OACT,IAAI,IAAI,QACR;AACA,cAAM;AACN,iBAAS;AAAA,MACX;AAAA,IACF;AACA,WAAO;AAAA,EACT;AACF;AAGO,SAAS,cAAiB,OAA4B,SAAsC;AACjG,WAAS,KAAqB,SAAS,IAAI,KAAK,GAAG,eAAe;AAChE,QAAI,MAAM,IAAI,EAAiB,EAAG,QAAO;AAAA,EAC3C;AACA,SAAO;AACT;;;ACtDO,SAAS,cAAc,SAAsB,MAAY;AAC9D,UAAQ,MAAM,QAAQ,GAAG,KAAK,KAAK;AACnC,UAAQ,MAAM,SAAS,GAAG,KAAK,MAAM;AACvC;AAEO,SAAS,cAAc,SAAsB;AAClD,UAAQ,MAAM,YAAY;AAC1B,UAAQ,MAAM,UAAU;AACxB,UAAQ,MAAM,WAAW;AAC3B;AAEO,SAAS,SAAS,OAAoC;AAC3D,MAAI,OAAO,UACT,OAAO,UACP,OAAO,WACP,OAAO;AACT,aAAW,QAAQ,OAAO;AACxB,WAAO,KAAK,IAAI,MAAM,KAAK,CAAC;AAC5B,WAAO,KAAK,IAAI,MAAM,KAAK,CAAC;AAC5B,WAAO,KAAK,IAAI,MAAM,KAAK,IAAI,KAAK,KAAK;AACzC,WAAO,KAAK,IAAI,MAAM,KAAK,IAAI,KAAK,MAAM;AAAA,EAC5C;AACA,SAAO,SAAS,WAAW,OAAO,EAAE,GAAG,MAAM,GAAG,MAAM,OAAO,OAAO,MAAM,QAAQ,OAAO,KAAK;AAChG;;;ACsFO,IAAM,iBAAyB,EAAE,GAAG,GAAG,GAAG,GAAG,MAAM,EAAE;AACrD,IAAM,0BAA0B;AAEhC,IAAM,kBAAkB;AAExB,IAAM,cAAc;;;AC1FpB,SAAS,gBAAgB,MAAmB,SAAsC;AACvF,QAAM,UAAU,SAAS,cAAc,KAAK;AAC5C,UAAQ,QAAQ,mBAAmB;AACnC,SAAO,OAAO,QAAQ,OAAO;AAAA,IAC3B,UAAU;AAAA,IACV,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,UAAU;AAAA,IACV,aAAa;AAAA,IACb,YAAY,QAAQ,cAAc;AAAA,EACpC,CAAC;AACD,QAAM,QAAQ,SAAS,cAAc,KAAK;AAC1C,QAAM,QAAQ,mBAAmB;AACjC,SAAO,OAAO,MAAM,OAAO;AAAA,IACzB,UAAU;AAAA,IACV,MAAM;AAAA,IACN,KAAK;AAAA,IACL,iBAAiB;AAAA,IACjB,YAAY;AAAA,EACd,CAAC;AAED,QAAM,UAAU,SAAS,cAAc,KAAK;AAC5C,SAAO,OAAO,QAAQ,OAAO,EAAE,UAAU,YAAY,MAAM,KAAK,KAAK,KAAK,QAAQ,IAAI,CAAC;AACvF,QAAM,OAAO,OAAO;AACpB,UAAQ,OAAO,KAAK;AACpB,OAAK,OAAO,OAAO;AAEnB,QAAM,QAAQ,oBAAI,IAAuB;AAEzC,QAAM,OAAO,CAAC,OAAe,UAC3B,QAAQ,KAAK,qCAAqC,KAAK;AACzD,QAAM,iBAAiB,QAAQ,kBAAkB;AACjD,QAAM,gBAAgB,KAAK,gBAAgB,eAAe;AAC1D,QAAM,YAAY,KAAK,QAAQ,cAAc,gBAAgB,WAAW;AACxE,MAAI,YAAY,oBAAI,IAAa;AACjC,MAAI,UAA0B;AAE9B,MAAI,gBAAgB,oBAAI,IAAiB;AACzC,QAAM,QAAQ,oBAAI,IAA0B;AAC5C,QAAM,cAAc,CAAC,YAAkC;AACrD,UAAM,OAAO,QAAQ,cAAc,cAAc,OAAO,OAAO,IAAI;AACnE,WAAO,OAAO,WAAW,MAAM,MAAM,IAAI,IAAI,GAAI,OAAO,IAAI;AAAA,EAC9D;AAEA,MAAI,WAAW;AACf,QAAM,aAAa,MAAM;AACvB,eAAW,MAAM,OAAO,sBAAsB,UAAU,IAAI;AAC5D,eAAW,CAAC,SAAS,GAAG,KAAK,OAAO;AAClC,YAAM,OAAO,YAAY,OAAO;AAChC,UAAI,MAAM,UAAU,OAAO,UAAU;AACrC,UAAI,MAAM;AACR,YAAI,MAAM,YAAY,aAAa,KAAK,CAAC,OAAO,KAAK,CAAC;AACtD,YAAI,MAAM,QAAQ,GAAG,KAAK,KAAK;AAC/B,YAAI,MAAM,SAAS,GAAG,KAAK,MAAM;AAAA,MACnC;AAAA,IACF;AAAA,EACF;AACA,QAAM,eAAe,MAAM;AACzB,UAAM,SAAS,oBAAI,IAAqB;AACxC,eAAW,WAAW,UAAW,QAAO,IAAI,SAAS,aAAa;AAClE,QAAI,WAAW,CAAC,OAAO,IAAI,OAAO,EAAG,QAAO,IAAI,SAAS,SAAS;AAClE,UAAM,YAAY,oBAAI,IAAiB;AACvC,eAAW,CAAC,SAAS,OAAO,KAAK,QAAQ;AACvC,UAAI,CAAC,MAAM,IAAI,OAAsB,EAAG;AACxC,MAAC,QAAwB,MAAM,UAAU;AACzC,gBAAU,IAAI,OAAsB;AAAA,IACtC;AACA,eAAW,QAAQ,cAAe,KAAI,CAAC,UAAU,IAAI,IAAI,EAAG,MAAK,MAAM,UAAU;AACjF,oBAAgB;AAChB,eAAW,CAAC,SAAS,GAAG,KAAK,OAAO;AAClC,UAAI,OAAO,IAAI,OAAO,EAAG;AACzB,UAAI,OAAO;AACX,YAAM,OAAO,OAAO;AAAA,IACtB;AACA,eAAW,CAAC,SAAS,OAAO,KAAK,QAAQ;AACvC,UAAI,MAAM,IAAI,OAAsB,EAAG;AACvC,UAAI,MAAM,MAAM,IAAI,OAAO;AAC3B,UAAI,CAAC,KAAK;AACR,cAAM,SAAS,cAAc,KAAK;AAClC,eAAO,OAAO,IAAI,OAAO;AAAA,UACvB,UAAU;AAAA,UACV,MAAM;AAAA,UACN,KAAK;AAAA,UACL,eAAe;AAAA,QACjB,CAAC;AACD,gBAAQ,OAAO,GAAG;AAClB,cAAM,IAAI,SAAS,GAAG;AAAA,MACxB;AACA,UAAI,MAAM,UAAU;AAAA,IACtB;AACA,QAAI,MAAM,QAAQ,CAAC,SAAU,YAAW;AAAA,EAC1C;AAEA,QAAM,aAAa,oBAAI,IAA4B;AACnD,QAAM,YAAY;AAClB,QAAM,cAAc,CAAC,YAAyB;AAC5C,eAAW,IAAI,OAAO,GAAG,OAAO;AAChC,eAAW,OAAO,OAAO;AACzB,YAAQ,MAAM,SAAS;AAAA,EACzB;AACA,QAAM,cAAc,CAAC,SAAsB,QAAuB,WAA+B;AAC/F,gBAAY,OAAO;AACnB,QAAI,CAAC,QAAQ,IAAK;AAClB,UAAM,SAAS,aAAa,QAAQ,MAAM;AAC1C,QAAI,CAAC,OAAO,UAAU;AACpB,cAAQ,MAAM,SAAS,OAAO,IAAI,QAAQ,CAAC;AAC3C;AAAA,IACF;AACA,UAAM,SAAS,OAAO,UAAU;AAChC,UAAM,YAAY,MAAM,KAAK,EAAE,QAAQ,YAAY,EAAE,GAAG,CAAC,GAAG,OAAO;AAAA,MACjE,QAAQ,OAAO,IAAK,QAAS,IAAI,YAAa,MAAM;AAAA,IACtD,EAAE;AACF,eAAW;AAAA,MACT;AAAA,MACA,QAAQ,QAAQ,WAAW,EAAE,UAAU,SAAS,KAAM,YAAY,SAAS,CAAC;AAAA,IAC9E;AAAA,EACF;AACA,MAAI,SAAS,QAAQ,UAAU;AAC/B,MAAI,UAAU;AAEd,QAAM,QAAQ,MAAM;AAClB,UAAM,QAAQ,YAAY,IAAI;AAC9B,UAAM,MAAM,YAAY,SAAS,OAAO,IAAI,eAAe,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC;AACpF,UAAM,MAAM,YAAY,oBAAoB,OAAO,OAAO,IAAI,CAAC;AAC/D,cAAU,YAAY,IAAI,IAAI;AAAA,EAChC;AACA,QAAM,YAAY,CAAC,SAAiB;AAClC,aAAS;AACT,UAAM;AACN,YAAQ,iBAAiB,MAAM;AAAA,EACjC;AACA,QAAM,cAAc,gBAAgB,SAAS,MAAM,QAAQ,SAAS;AACpE,QAAM;AAEN,SAAO;AAAA,IACL,MAAM;AAAA,IACN;AAAA,IACA,QAAQ,SAAS,MAAM;AACrB,oBAAc,OAAO;AACrB,cAAQ,MAAM,WAAW;AACzB,YAAM,IAAI,SAAS,IAAI;AACvB,WAAK,WAAW,SAAS,IAAI;AAC7B,YAAM,OAAO,OAAO;AAAA,IACtB;AAAA,IACA,WAAW,SAAS,MAAM;AACxB,YAAM,IAAI,SAAS,IAAI;AACvB,cAAQ,MAAM,OAAO,GAAG,KAAK,CAAC;AAC9B,cAAQ,MAAM,MAAM,GAAG,KAAK,CAAC;AAC7B,oBAAc,SAAS,IAAI;AAAA,IAC7B;AAAA,IACA,WAAW,SAAS;AAClB,kBAAY,OAAO;AACnB,YAAM,OAAO,OAAO;AACpB,oBAAc,OAAO,OAAO;AAC5B,cAAQ,MAAM,UAAU;AACxB,cAAQ,OAAO;AAAA,IACjB;AAAA,IACA,aAAa,CAAC,YAAY,MAAM,IAAI,OAAO,KAAK;AAAA,IAChD,WAAW,MAAM;AACf,aAAO,CAAC,GAAG,KAAK,EAAE,OAAO,CAAC,CAAC,EAAE,IAAI,MAAM,WAAW,MAAM,IAAI,CAAC,EAAE,IAAI,CAAC,CAAC,OAAO,MAAM,OAAO;AAAA,IAC3F;AAAA,IACA,WAAW,CAAC,YAAY,cAAc,OAAO,OAAO;AAAA,IACpD,gBAAgB;AAAA,IAChB,aAAa,OAAO;AAElB,UAAI,MAA0B;AAC9B,iBAAW,CAAC,SAAS,IAAI,KAAK,MAAO,KAAI,cAAc,MAAM,KAAK,EAAG,OAAM;AAC3E,aAAO,MAAM,cAAc,KAAK,MAAM,IAAI,GAAG,GAAI,KAAK,IAAI;AAAA,IAC5D;AAAA,IACA,aAAa,UAAU;AACrB,kBAAY,IAAI,IAAI,QAAQ;AAC5B,mBAAa;AAAA,IACf;AAAA,IACA,SAAS,SAAS;AAChB,UAAI,YAAY,QAAS;AACzB,gBAAU;AACV,mBAAa;AAAA,IACf;AAAA,IACA,UAAU,SAAS,QAAQ,QAAQ;AACjC,UAAI,MAAM,IAAI,OAAO,EAAG,aAAY,SAAS,QAAQ,MAAM;AAAA,IAC7D;AAAA,IACA,WAAW,MAAM;AAAA,IACjB;AAAA,IACA,eAAe,CAAC,UAAU,cAAc,QAAQ,KAAK;AAAA,IACrD,eAAe,CAAC,UAAU,cAAc,QAAQ,KAAK;AAAA;AAAA,IAErD,aAAa;AAAA,IAAC;AAAA,IACd,cAAc,OAAO;AACnB,cAAQ,MAAM,aAAa;AAAA,IAC7B;AAAA,IACA,IAAI,SAAS;AACX,YAAM,SAAS,SAAS,MAAM,OAAO,CAAC;AACtC,UAAI,OAAQ,WAAU,UAAU,QAAQ,QAAQ,aAAa,QAAQ,cAAc,OAAO,CAAC;AAAA,IAC7F;AAAA,IACA,WAAW;AACT,YAAM,OAAO,iBAAiB,QAAQ,QAAQ,aAAa,QAAQ,YAAY;AAC/E,UAAI,UAAU;AACd,iBAAW,QAAQ,MAAM,OAAO,EAAG,KAAI,WAAW,MAAM,IAAI,EAAG;AAC/D,aAAO;AAAA,QACL,MAAM;AAAA,QACN,OAAO,MAAM;AAAA,QACb;AAAA,QACA,SAAS;AAAA,QACT,qBAAqB;AAAA,QACrB,UAAU;AAAA,QACV,iBAAiB;AAAA,QACjB;AAAA,MACF;AAAA,IACF;AAAA,IACA,UAAU;AACR,2BAAqB,QAAQ;AAC7B,kBAAY;AACZ,cAAQ,OAAO;AAAA,IACjB;AAAA,EACF;AACF;;;ACvNA,IAAM,UAAU;AAYT,IAAM,QAAN,MAAY;AAAA,EAUjB,YACmB,QACjB,MACA,YACA;AAHiB;AAIjB,SAAK,OAAO;AACZ,SAAK,UAAU,OAAO,cAAc;AAAA,MAClC,OAAO;AAAA,MACP,MAAM,CAAC,MAAM,MAAM,UAAU;AAAA,MAC7B,QAAQ;AAAA,MACR,OACE,gBAAgB,kBAChB,gBAAgB,WAChB,gBAAgB,WAChB,gBAAgB;AAAA,IACpB,CAAC;AACD,SAAK,OAAO,KAAK,QAAQ,WAAW,EAAE,WAAW,WAAW,CAAC;AAC7D,SAAK,SAAS,MAAM,KAAK,EAAE,QAAQ,WAAW,GAAG,OAAO;AAAA,MACtD,SAAS,CAAC;AAAA,MACV,OAAO;AAAA,MACP,YAAY;AAAA,MACZ,UAAU;AAAA,MACV,eAAe;AAAA,IACjB,EAAE;AACF,SAAK,QAAQ,aAAa;AAAA,EAC5B;AAAA,EAxBmB;AAAA,EAVV;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAET,OAAyC,MAAM,CAAC;AAAA,EACxC;AAAA,EACA;AAAA,EACA,QAAQ;AAAA;AAAA,EA8BP,SAAS;AAAA,EAElB,IAAI,aAAa;AACf,WAAO,KAAK,OAAO;AAAA,EACrB;AAAA,EAEA,IAAI,aAAa;AACf,WAAO,KAAK,OAAO,OAAO,CAAC,OAAO,UAAU,UAAU,KAAK,SAAS,MAAM,QAAQ,CAAC,EAAE;AAAA,EACvF;AAAA;AAAA,EAGA,IAAI,aAAa;AACf,WAAO,KAAK,OAAO,KAAK,MAAM,EAAE,QAAQ,KAAK;AAAA,EAC/C;AAAA,EAEA,YAAY;AACV,SAAK;AAAA,EACP;AAAA;AAAA,EAGA,MAAM,OAAe;AACnB,SAAK,OAAO,KAAK,EAAE,WAAW,KAAK;AAAA,EACrC;AAAA,EAEA,QAAQ,MAA2C;AACjD,WAAO,SAAS,QAAQ,KAAK,OAAO,KAAK,KAAK,EAAE,eAAe,KAAK;AAAA,EACtE;AAAA,EAEA,SAAS,OAAe,QAAkC;AACxD,UAAM,IAAI,KAAK,KAAK,KAAK,IAAI;AAC7B,UAAM,IAAI,KAAK,KAAK,MAAM,IAAI;AAC9B,QAAI,IAAI,KAAK,QAAQ,IAAI,KAAK,KAAM,QAAO;AAC3C,aAAS,QAAQ,GAAG,QAAQ,KAAK,OAAO,QAAQ,SAAS;AACvD,UAAI,UAAU,KAAK,SAAS,UAAU,KAAK,OAAQ;AACnD,YAAM,OAAO,KAAK,WAAW,OAAO,GAAG,CAAC;AACxC,UAAI,KAAM,QAAO;AAAA,IACnB;AAEA,QAAI,UAAU;AACd,aAAS,QAAQ,GAAG,QAAQ,KAAK,OAAO,QAAQ,SAAS;AACvD,YAAM,QAAQ,KAAK,OAAO,KAAK;AAC/B,UAAI,UAAU,KAAK,SAAS,UAAU,KAAK,UAAU,MAAM,kBAAkB,KAAK;AAChF;AACF,UAAI,UAAU,KAAK,MAAM,WAAW,KAAK,OAAO,OAAO,EAAE,SAAU,WAAU;AAAA,IAC/E;AACA,QAAI,UAAU,EAAG,QAAO;AACxB,UAAM,SAAS,KAAK,QAAQ,OAAO;AACnC,WAAO,KAAK,WAAW,QAAQ,GAAG,CAAC;AAAA,EACrC;AAAA;AAAA,EAGA,eAAe,OAAe,QAAkC;AAC9D,WAAO,KAAK,WAAW,KAAK,QAAQ,KAAK,KAAK,KAAK,IAAI,SAAS,KAAK,KAAK,MAAM,IAAI,OAAO;AAAA,EAC7F;AAAA,EAEA,SAAS,MAAwB;AAC/B,WAAO,SAAS,QAAQ,KAAK,UAAU,KAAK;AAAA,EAC9C;AAAA;AAAA,EAGQ,QAAQ,OAAe;AAC7B,UAAM,SAAS,KAAK;AACpB,UAAM,OAAO,KAAK,OAAO,KAAK;AAC9B,SAAK,MAAM,MAAM;AACjB,UAAM,UAAU,KAAK,OAAO,qBAAqB,EAAE,OAAO,yBAAyB,CAAC;AACpF,QAAI,SAAS;AACb,UAAM,OAAO,oBAAI,IAAe;AAChC,eAAW,QAAQ,KAAK,KAAK,GAAG;AAC9B,UAAI,CAAC,QAAQ,KAAK,IAAI,IAAI,KAAK,KAAK,UAAU,SAAS,KAAK,eAAe,KAAK,YAAY;AAC1F;AAAA,MACF;AACA,WAAK,IAAI,IAAI;AAEb,YAAM,KAAK,KAAK,MAAM,KAAK,CAAC;AAC5B,YAAM,KAAK,KAAK,MAAM,KAAK,CAAC;AAC5B,YAAM,KAAK,KAAK,IAAI,KAAK,MAAM,KAAK,KAAK,KAAK,IAAI,KAAK,KAAK,CAAC;AAC7D,YAAM,KAAK,KAAK,IAAI,KAAK,MAAM,KAAK,KAAK,KAAK,IAAI,KAAK,MAAM,CAAC;AAC9D,YAAM,QAAQ,KAAK,WAAW,QAAQ,KAAK,KAAK,SAAS,KAAK,KAAK,OAAO;AAC1E,UAAI,CAAC,MAAO;AACZ,cAAQ;AAAA,QACN,EAAE,SAAS,KAAK,SAAS,QAAQ,EAAE,GAAG,IAAI,GAAG,IAAI,GAAG,MAAM,EAAE;AAAA,QAC5D,EAAE,SAAS,KAAK,SAAS,QAAQ,EAAE,GAAG,MAAM,GAAG,GAAG,MAAM,GAAG,GAAG,OAAO,EAAE;AAAA,QACvE,CAAC,KAAK,IAAI,KAAK,IAAI,CAAC;AAAA,MACtB;AACA;AACA,WAAK,QAAQ;AACb,WAAK,IAAI,MAAM,KAAK,KAAK,IAAI;AAC7B,WAAK,IAAI,MAAM,KAAK,KAAK,IAAI;AAC7B,WAAK,aAAa,MAAM;AAAA,IAC1B;AACA,QAAI,SAAS,EAAG,MAAK,OAAO,MAAM,OAAO,CAAC,QAAQ,OAAO,CAAC,CAAC;AAC3D,SAAK,MAAM,KAAK;AAChB,SAAK,QAAQ;AACb,WAAO;AAAA,EACT;AAAA,EAEQ,WAAW,OAAe,GAAW,GAA6B;AACxE,UAAM,QAAQ,KAAK,OAAO,KAAK;AAC/B,QAAI,QAAQ,MAAM,QAAQ;AAAA,MACxB,CAAC,cACC,UAAU,UAAU,KAAK,UAAU,UAAU,IAAI,OAAO,UAAU,IAAI,KAAK,KAAK;AAAA,IACpF;AACA,QAAI,CAAC,OAAO;AACV,UAAI,MAAM,QAAQ,IAAI,KAAK,KAAM,QAAO;AACxC,cAAQ,EAAE,GAAG,MAAM,OAAO,QAAQ,GAAG,GAAG,EAAE;AAC1C,YAAM,QAAQ,KAAK,KAAK;AACxB,YAAM,SAAS;AAAA,IACjB;AACA,UAAM,OAAO;AAAA,MACX,OAAO;AAAA,MACP,GAAG,MAAM;AAAA,MACT,GAAG,MAAM;AAAA,MACT,OAAO,IAAI;AAAA,MACX,QAAQ,IAAI;AAAA,MACZ,YAAY,MAAM;AAAA,IACpB;AACA,UAAM,KAAK;AACX,UAAM,WAAW,KAAK;AACtB,UAAM,gBAAgB,KAAK;AAC3B,WAAO;AAAA,EACT;AAAA,EAEQ,MAAM,OAAe;AAC3B,UAAM,QAAQ,KAAK,OAAO,KAAK;AAC/B,UAAM,UAAU,CAAC;AACjB,UAAM,QAAQ;AACd,UAAM;AAAA,EACR;AAAA,EAEA,UAAU;AACR,SAAK,QAAQ,QAAQ;AAAA,EACvB;AACF;;;ACvMA,IAAM;AAAA;AAAA,EAAqB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAyEpB,IAAM;AAAA;AAAA,EAA6B,GAAG,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAkC7C,IAAM,eAAe,CAAC;AAAA;AAAA,EAA4B,GAAG,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAsCjE,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACtJC,IAAM,sBAAsB;AAe5B,IAAM,oBAAN,MAAwB;AAAA,EAc7B,YACmB,QACA,SACjB,QACiB,OACV,YACA,aACP;AANiB;AACA;AAEA;AACV;AACA;AAEP,SAAK,kBAAkB,OAAO,sBAAsB;AAAA,MAClD,SAAS;AAAA,QACP,EAAE,SAAS,GAAG,YAAY,eAAe,SAAS,eAAe,UAAU,QAAQ,CAAC,EAAE;AAAA,QACtF;AAAA,UACE,SAAS;AAAA,UACT,YAAY,eAAe;AAAA,UAC3B,SAAS,EAAE,eAAe,WAAW;AAAA,QACvC;AAAA,QACA,EAAE,SAAS,GAAG,YAAY,eAAe,UAAU,SAAS,CAAC,EAAE;AAAA,MACjE;AAAA,IACF,CAAC;AACD,SAAK,UAAU,OAAO,cAAc,EAAE,WAAW,UAAU,WAAW,SAAS,CAAC;AAChF,SAAK,WAAW,OAAO;AAAA,MACrB,KAAK,mBAAmB,uBAAuB,iBAAiB,MAAM;AAAA,IACxE;AACA,SAAK,SAAS;AACd,SAAK,WAAW,OAAO,aAAa;AAAA,MAClC,MAAM,KAAK,YAAY;AAAA,MACvB,OAAO,eAAe,UAAU,eAAe;AAAA,IACjD,CAAC;AACD,SAAK,YAAY,OAAO,gBAAgB;AAAA,MACtC,QAAQ,KAAK;AAAA,MACb,SAAS;AAAA,QACP,EAAE,SAAS,GAAG,UAAU,EAAE,QAAQ,KAAK,SAAS,EAAE;AAAA,QAClD,EAAE,SAAS,GAAG,UAAU,MAAM,KAAK;AAAA,QACnC,EAAE,SAAS,GAAG,UAAU,KAAK,QAAQ;AAAA,MACvC;AAAA,IACF,CAAC;AACD,SAAK,iBAAiB,KAAK,qBAAqB;AAAA,EAClD;AAAA,EApCmB;AAAA,EACA;AAAA,EAEA;AAAA,EACV;AAAA,EACA;AAAA,EAnBT,YAAY,IAAI,aAAa,sBAAsB,IAAI;AAAA,EAC/C;AAAA,EACS;AAAA,EACA,cAAc,IAAI,aAAa,EAAE;AAAA,EACjC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAEA,UAAU,oBAAI,IAAsC;AAAA;AAAA,EAErE,gBAA4B,MAAM;AAAA,EAAC;AAAA,EAyClB;AAAA,EAET,mBACN,OACA,MACA,QAC6B;AAC7B,UAAM,SAAS,KAAK,OAAO,mBAAmB,EAAE,OAAO,KAAK,CAAC;AAC7D,WAAO;AAAA,MACL;AAAA,MACA,QAAQ,KAAK,OAAO,qBAAqB,EAAE,kBAAkB,CAAC,KAAK,eAAe,EAAE,CAAC;AAAA,MACrF,QAAQ;AAAA,QACN;AAAA,QACA,YAAY;AAAA,QACZ,SAAS;AAAA,UACP;AAAA,YACE,aAAa,sBAAsB;AAAA,YACnC,UAAU;AAAA,YACV,YAAY;AAAA,cACV,EAAE,gBAAgB,GAAG,QAAQ,GAAG,QAAQ,YAAY;AAAA,cACpD,EAAE,gBAAgB,GAAG,QAAQ,IAAI,QAAQ,YAAY;AAAA,cACrD,EAAE,gBAAgB,GAAG,QAAQ,IAAI,QAAQ,YAAY;AAAA,cACrD,EAAE,gBAAgB,GAAG,QAAQ,IAAI,QAAQ,YAAY;AAAA,YACvD;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,MACA,UAAU;AAAA,QACR;AAAA,QACA,YAAY;AAAA,QACZ,SAAS;AAAA,UACP;AAAA,YACE;AAAA;AAAA,YAEA,OAAO;AAAA,cACL,OAAO,EAAE,WAAW,OAAO,WAAW,sBAAsB;AAAA,cAC5D,OAAO,EAAE,WAAW,OAAO,WAAW,sBAAsB;AAAA,YAC9D;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,MACA,WAAW,EAAE,UAAU,iBAAiB;AAAA,IAC1C;AAAA,EACF;AAAA;AAAA,EAGA,UAAU,QAAyB;AACjC,QAAI,KAAK,QAAQ,IAAI,MAAM,EAAG,QAAO,KAAK,QAAQ,IAAI,MAAM,MAAM;AAClE,SAAK,QAAQ,IAAI,QAAQ,IAAI;AAC7B,SAAK,OACF;AAAA,MACC,KAAK;AAAA,QACH,oBAAoB,OAAO,IAAI;AAAA,QAC/B,aAAa,OAAO,IAAI;AAAA,QACxB,KAAK;AAAA,MACP;AAAA,IACF,EACC,KAAK,CAAC,aAAa;AAClB,WAAK,QAAQ,IAAI,QAAQ,QAAQ;AACjC,WAAK,cAAc;AAAA,IACrB,CAAC,EACA,MAAM,CAAC,UAAU,QAAQ,MAAM,uBAAuB,OAAO,IAAI,YAAY,KAAK,CAAC;AACtF,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,QAAQ,OAAe;AACrB,UAAM,SAAS,QAAQ;AACvB,QAAI,KAAK,UAAU,UAAU,OAAQ;AACrC,SAAK,YAAY,IAAI,aAAa,KAAK,IAAI,QAAQ,KAAK,UAAU,SAAS,CAAC,CAAC;AAC7E,SAAK,eAAe,QAAQ;AAC5B,SAAK,iBAAiB,KAAK,qBAAqB;AAAA,EAClD;AAAA,EAEA,KACE,QACA,UACA,WACA,KACA,OACA,MAEA,SACA;AACA,UAAM,EAAE,OAAO,IAAI;AACnB,SAAK,YAAY,IAAI;AAAA,MACnB;AAAA,MACA;AAAA,MACA,OAAO;AAAA,MACP,OAAO;AAAA,MACP,OAAO;AAAA,MACP;AAAA,MACA,KAAK,MAAM;AAAA,MACX,QAAQ;AAAA,MACR,GAAG,KAAK;AAAA,MACR,QAAQ,QAAQ;AAAA,MAChB,QAAQ,QAAQ;AAAA,MAChB,QAAQ,MAAM;AAAA,MACd,QAAQ,MAAM;AAAA,MACd,QAAQ;AAAA,IACV,CAAC;AACD,WAAO,MAAM,YAAY,KAAK,UAAU,GAAG,KAAK,WAAW;AAC3D,QAAI,QAAQ,GAAG;AACb,aAAO,MAAM;AAAA,QACX,KAAK;AAAA,QACL;AAAA,QACA,KAAK;AAAA,QACL;AAAA,QACA,QAAQ;AAAA,MACV;AAAA,IACF;AACA,UAAM,CAAC,GAAG,GAAG,CAAC,IAAI,KAAK;AACvB,UAAM,UAAU,OAAO,qBAAqB;AAC5C,UAAM,OAAO,QAAQ,gBAAgB;AAAA,MACnC,kBAAkB;AAAA,QAChB;AAAA,UACE,MAAM,KAAK,QAAQ,kBAAkB,EAAE,WAAW;AAAA,UAClD,YAAY,EAAE,GAAG,GAAG,GAAG,GAAG,EAAE;AAAA,UAC5B,QAAQ;AAAA,UACR,SAAS;AAAA,QACX;AAAA,MACF;AAAA,IACF,CAAC;AACD,QAAI,QAAQ,GAAG;AACb,WAAK,aAAa,GAAG,KAAK,SAAS;AACnC,WAAK,gBAAgB,GAAG,KAAK,cAAc;AAC3C,UAAI,UAAoC;AACxC,iBAAW,OAAO,KAAK,SAAS,OAAO,CAAC,EAAE,QAAQ,MAAM,OAAO,GAAG,MAAM,CAAC,GAAG;AAC1E,cAAM,WAAY,IAAI,UAAU,KAAK,QAAQ,IAAI,IAAI,MAAM,KAAM,KAAK;AACtE,YAAI,aAAa,QAAS,MAAK,YAAa,UAAU,QAAS;AAC/D,aAAK,KAAK,GAAG,IAAI,OAAO,GAAG,IAAI,KAAK;AAAA,MACtC;AAAA,IACF;AACA,SAAK,IAAI;AACT,WAAO,MAAM,OAAO,CAAC,QAAQ,OAAO,CAAC,CAAC;AAAA,EACxC;AAAA,EAEA,UAAU;AACR,SAAK,eAAe,QAAQ;AAC5B,SAAK,SAAS,QAAQ;AAAA,EACxB;AAAA,EAEQ,uBAAuB;AAC7B,WAAO,KAAK,OAAO,aAAa;AAAA,MAC9B,OAAO;AAAA,MACP,MAAM,KAAK,UAAU;AAAA,MACrB,OAAO,eAAe,SAAS,eAAe;AAAA,IAChD,CAAC;AAAA,EACH;AACF;;;ACrNA,IAAM,MAAM;AAcL,IAAM,OAAN,MAAW;AAAA,EACP;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAET,QAAQ;AAAA;AAAA,EAER,WAAW;AAAA;AAAA,EAEX,gBAAgB;AAAA;AAAA,EAEhB,SAAS;AAAA;AAAA,EAET,aAAa;AAAA,EACL,UAAmB,CAAC;AAAA,EACpB,QAAQ;AAAA,EAEhB,YAAY,OAAe,QAAgB;AACzC,SAAK,QAAQ;AACb,SAAK,SAAS;AACd,SAAK,UAAU,SAAS,cAAc,KAAK;AAC3C,SAAK,QAAQ,QAAQ,gBAAgB;AACrC,WAAO,OAAO,KAAK,QAAQ,OAAO;AAAA,MAChC,UAAU;AAAA,MACV,OAAO,GAAG,KAAK;AAAA,MACf,QAAQ,GAAG,MAAM;AAAA;AAAA,MAEjB,cAAc,GAAG,CAAC,MAAM;AAAA,MACxB,SAAS;AAAA,MACT,UAAU;AAAA;AAAA;AAAA;AAAA,MAIV,mBAAmB;AAAA,IACrB,CAAC;AAAA,EACH;AAAA;AAAA,EAGA,MAAM,OAAe,QAAiC;AACpD,UAAM,IAAI,KAAK,KAAK,KAAK,IAAI;AAC7B,UAAM,IAAI,KAAK,KAAK,MAAM,IAAI;AAC9B,QAAI,IAAI,KAAK,QAAQ,OAAO,IAAI,KAAK,SAAS,IAAK,QAAO;AAC1D,QAAI,QAAQ,KAAK,QAAQ;AAAA,MACvB,CAAC,cACC,UAAU,UAAU,KACpB,UAAU,UAAU,IAAI,QACxB,UAAU,IAAI,KAAK,KAAK,QAAQ;AAAA,IACpC;AACA,QAAI,CAAC,OAAO;AACV,UAAI,KAAK,QAAQ,IAAI,KAAK,SAAS,IAAK,QAAO;AAC/C,cAAQ,EAAE,GAAG,KAAK,OAAO,QAAQ,GAAG,GAAG,EAAE;AACzC,WAAK,QAAQ,KAAK,KAAK;AACvB,WAAK,SAAS;AAAA,IAChB;AACA,UAAM,OAAO,EAAE,MAAM,MAAM,GAAG,MAAM,GAAG,GAAG,MAAM,EAAE;AAClD,UAAM,KAAK;AACX,SAAK;AACL,WAAO;AAAA,EACT;AAAA,EAEA,UAAU;AACR,SAAK;AAAA,EACP;AAAA,EAEA,YAAY,UAAmB,OAAe;AAC5C,QAAI,KAAK,aAAa,SAAU;AAChC,SAAK,WAAW;AAChB,SAAK,aAAa;AAClB,QAAI,UAAU;AACZ,WAAK,gBAAgB;AACrB,WAAK,QAAQ,MAAM,oBAAoB;AACvC,WAAK,QAAQ,aAAa,YAAY,EAAE;AAAA,IAC1C,OAAO;AACL,WAAK,QAAQ,gBAAgB,UAAU;AACvC,WAAK,QAAQ,MAAM,oBAAoB;AACvC,WAAK,QAAQ,MAAM,YAAY;AAAA,IACjC;AAAA,EACF;AACF;;;ACSA,IAAM,mBAAmB,IAAI;AAM7B,IAAM,mBAAmB;AACzB,IAAM,mBAAmB;AAEzB,IAAM,cAAc;AAMpB,IAAM,oBAAoB;AAO1B,IAAM,gBAAgB;AACtB,IAAM,mBAAmB;AACzB,IAAM,QAAQ,CAAC,SAAe,KAAK,IAAI,KAAK;AAC5C,IAAM,SAAS,CAAC,SAAe,KAAK,IAAI,KAAK;AAE7C,IAAM,YAAY;AAElB,IAAM,aAAa,CAAC,SAAS,SAAS,UAAU,SAAS;AACzD,IAAM,UAAU;AAEhB,IAAM,YAAY;AAElB,IAAM,mBAAmB;AACzB,IAAM,oBAAoB;AAK1B,IAAM,kBAAkB,IAAI;AAE5B,IAAM,uBAAuB;AAO7B,IAAM,2BAA2B;AACjC,IAAM,gBAAgB;AACtB,IAAM,gBAAgB;AAGtB,IAAM,UAAU;AAChB,IAAM,QAAQ;AACd,IAAM,SAAS;AACf,IAAM,cAAc;AAEb,SAAS,oBAA6B;AAC3C,SACE,OAAO,cAAc,eACrB,SAAS,aACT,OAAO,sBAAsB,eAC7B,kBAAkB,kBAAkB,aACpC,yBAAyB,kBAAkB,aAC3C,OAAO,aAAa,eACpB,+BAA+B,SAAS;AAE5C;AAMA,SAAS,eAAe,aAAqB;AAC3C,QAAM,QAAQ,KAAK,KAAK,KAAK,KAAK,KAAK,WAAW,IAAI,IAAI;AAC1D,SAAO,KAAK,IAAI,kBAAkB,KAAK,IAAI,kBAAkB,KAAK,CAAC;AACrE;AAEA,IAAM,eAAe,CAAC,GAAS,MAAyB;AACtD,QAAM,IAAI,KAAK,IAAI,EAAE,GAAG,EAAE,CAAC;AAC3B,QAAM,IAAI,KAAK,IAAI,EAAE,GAAG,EAAE,CAAC;AAC3B,QAAMA,SAAQ,KAAK,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK;AACnD,QAAMC,UAAS,KAAK,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM;AACtD,SAAOD,SAAQ,KAAKC,UAAS,IAAI,EAAE,GAAG,GAAG,OAAOD,SAAQ,GAAG,QAAQC,UAAS,EAAE,IAAI;AACpF;AAEA,IAAM,WAAW,CAAC,OAAa,UAC7B,MAAM,KAAK,MAAM,KACjB,MAAM,KAAK,MAAM,KACjB,MAAM,IAAI,MAAM,SAAS,MAAM,IAAI,MAAM,SACzC,MAAM,IAAI,MAAM,UAAU,MAAM,IAAI,MAAM;AAE5C,SAAS,eAAe,OAAiD;AACvE,QAAM,UAAU,SAAS,cAAc,QAAQ,EAAE,WAAW,IAAI;AAChE,UAAQ,YAAY;AACpB,UAAQ,SAAS,GAAG,GAAG,GAAG,CAAC;AAC3B,QAAM,CAAC,GAAG,GAAG,GAAG,CAAC,IAAI,QAAQ,aAAa,GAAG,GAAG,GAAG,CAAC,EAAE;AACtD,SAAO,CAAC,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,GAAG;AAC5C;AAEA,IAAM,gBAAgB,CAAC,CAAC,GAAG,GAAG,GAAG,CAAC,MAChC,CAAC,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,CAAC;AAEzB,IAAM,mBAAmB,CAAC,MAAY,SACpC,KAAK;AAAA,EACH,KAAK,IAAI,KAAK,QAAQ,KAAK,KAAK,IAAI,KAAK,QAAQ;AAAA,EACjD,KAAK,IAAI,KAAK,SAAS,KAAK,KAAK,IAAI,KAAK,SAAS;AACrD;AAgBF,eAAsB,gBACpB,MACA,SACoB;AACpB,QAAM,UAAU,MAAM,UAAU,IAAI,eAAe,EAAE,iBAAiB,mBAAmB,CAAC;AAC1F,MAAI,CAAC,QAAS,OAAM,IAAI,MAAM,8BAA8B;AAC5D,QAAM,SAAS,MAAM,QAAQ,cAAc;AAE3C,QAAM,UAAU,SAAS,cAAc,KAAK;AAC5C,UAAQ,QAAQ,mBAAmB;AACnC,SAAO,OAAO,QAAQ,OAAO;AAAA,IAC3B,UAAU;AAAA,IACV,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,UAAU;AAAA,IACV,aAAa;AAAA,EACf,CAAC;AACD,QAAM,SAAS,SAAS,cAAc,QAAQ;AAC9C,SAAO,aAAa,WAAW,UAAU;AACzC,SAAO,QAAQ,mBAAmB;AAClC,SAAO,OAAO,OAAO,OAAO,EAAE,SAAS,SAAS,OAAO,QAAQ,QAAQ,OAAO,CAAC;AAC/E,UAAQ,OAAO,MAAM;AACrB,OAAK,OAAO,OAAO;AAEnB,QAAM,UAAU,OAAO,WAAW,QAAQ;AAC1C,QAAM,SAAS,UAAU,IAAI,yBAAyB;AACtD,UAAQ,UAAU,EAAE,QAAQ,QAAQ,WAAW,SAAS,CAAC;AAEzD,QAAM,YAAY,KAAK,IAAI,QAAQ,aAAa,MAAM,OAAO,OAAO,qBAAqB;AACzF,QAAM,QAAQ,IAAI;AAAA,IAChB;AAAA,IACA;AAAA,IACA,KAAK,IAAI,QAAQ,eAAe,GAAG,OAAO,OAAO,qBAAqB;AAAA,EACxE;AACA,QAAM,WAAW,KAAK,IAAI,QAAQ,YAAY,mBAAmB,SAAS;AAC1E,QAAM,iBAAiB,QAAQ,sBAAsB;AACrD,QAAM,qBAAqB,QAAQ,sBAAsB;AACzD,QAAM,oBAAoB,QAAQ,qBAAqB;AAEvD,QAAM,YAAY,CAAC,QAAgB;AACjC,UAAM,aAAa,eAAe,GAAG;AACrC,UAAM,QAAQ,WAAW,CAAC,IAAI,WAAW,CAAC,IAAI,WAAW,CAAC,IAAI,MAAM,OAAO;AAC3E,UAAM,cAAc,WAAW;AAAA,MAAI,CAAC,YAClC,KAAK,IAAI,GAAG,UAAU,SAAS,QAAQ,IAAI,OAAO,EAAE;AAAA,IACtD;AACA,gBAAY,CAAC,IAAI;AACjB,WAAO,CAAC,YAAY,WAAW;AAAA,EACjC;AACA,QAAM,WAAW,IAAI;AAAA,IACnB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAG,UAAU,QAAQ,cAAc,SAAS;AAAA,EAC9C;AACA,QAAM,iBAAiB;AAAA,IACrB,eAAe,QAAQ,kBAAkB,uBAAuB;AAAA,EAClE;AACA,QAAM,aAAa,QAAQ,aACvB,cAAc,eAAe,QAAQ,UAAU,CAAC,IAChD;AAEJ,QAAM,QAAQ,oBAAI,IAAuB;AAEzC,QAAM,UAAU,oBAAI,IAAoE;AACxF,QAAM,YAAY,YAAY,IAAI;AAElC,QAAM,WAAkB,EAAE,GAAG,MAAM,GAAG,KAAK;AAC3C,WAAS,gBAAgB,MAAM,SAAS;AACxC,QAAM,OAAc,CAAC;AAErB,MAAI,gBAAgB;AACpB,MAAI,YAAY,oBAAI,IAAa;AACjC,MAAI,UAA0B;AAE9B,QAAM,YAAY,oBAAI,IAAmB;AACzC,QAAM,WAAW,CAAC,YAAkC;AAClD,UAAM,MAAM,MAAM,IAAI,OAAsB;AAC5C,QAAI,IAAK,QAAO,IAAI;AACpB,UAAM,KAAK,QAAQ,cAAc,cAAc,OAAO,OAAO,IAAI;AACjE,QAAI,CAAC,GAAI,QAAO;AAChB,UAAM,OAAO,MAAM,IAAI,EAAE;AACzB,QAAI,OAAO,UAAU,IAAI,OAAO;AAChC,QAAI,CAAC,KAAM,WAAU,IAAI,SAAU,OAAO,WAAW,IAAI,KAAK,MAAM,OAAO,CAAE;AAC7E,WAAO;AAAA,EACT;AACA,QAAM,QAAQ,oBAAI,IAAqB;AAEvC,QAAM,OAAO,aAAa;AACxB,UAAM,WAAW,CAAC,SAAe,WAAW,KAAK,MAAM,SAAS;AAChE,eAAW,QAAQ,QAAS,OAAM,KAAK;AACvC,eAAW,QAAQ,SAAS;AAC1B,iBAAW,QAAQ,KAAK,OAAO;AAC7B,YAAI,KAAK,UAAU,eAAe,CAAC,KAAK,SAAS,SAAS,IAAI,EAAG,OAAM,KAAK;AAAA,MAC9E;AAAA,IACF;AACA,eAAW,QAAQ,SAAS;AAC1B,YAAM,KAAK;AACX,iBAAW,QAAQ,KAAK,MAAO,KAAI,SAAS,IAAI,EAAG,OAAM,KAAK;AAAA,IAChE;AAAA,EACF;AACA,QAAM,gBAAgB,oBAAI,IAAmB;AAC7C,MAAI,WAAwB;AAE5B,MAAI,SAAS,QAAQ,UAAU;AAC/B,MAAI,mBAAmB;AACvB,MAAI,cAAc;AAClB,MAAI,qBAAqB;AACzB,MAAI,cAAc;AAClB,MAAI,QAAQ;AACZ,MAAI,YAAY;AAEhB,MAAI,OAAoB;AACxB,MAAI,iBAAiB;AACrB,MAAI,YAAyB;AAC7B,MAAI,cAAc;AAClB,MAAI,UAAuB;AAC3B,MAAI,UAA2C;AAC/C,MAAI,cAAc;AAClB,QAAM,QAAQ;AAAA,IACZ,SAAS;AAAA,IACT,SAAS;AAAA,IACT,qBAAqB;AAAA,IACrB,sBAAsB;AAAA,IACtB,UAAU;AAAA,IACV,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,YAAY;AAAA,IACZ,YAAY;AAAA,IACZ,aAAa;AAAA;AAAA,IAEb,OAAO,CAAC,GAAG,GAAG,GAAG,CAAC;AAAA,EACpB;AACA,QAAM,UAAkB,CAAC;AACzB,QAAM,QAAQ,oBAAI,IAAoB;AAEtC,QAAM,WAAW,MAAM;AACrB,QAAI,SAAS,UAAW;AACxB,YAAQ,sBAAsB,MAAM;AAClC,cAAQ;AACR;AACA,YAAM,KAAK;AAAA,IACb,CAAC;AAAA,EACH;AAEA,QAAM,iBAAiB,IAAI,eAAe,CAAC,CAAC,KAAK,MAAM;AACrD,UAAM,OAAO,MAAM,4BAA4B,CAAC;AAChD,WAAO,QAAQ,KAAK;AAAA,MAClB;AAAA,MACA,OAAO,KAAK,aAAa,KAAK,MAAM,MAAM,YAAY,QAAQ,gBAAgB;AAAA,IAChF;AACA,WAAO,SAAS,KAAK;AAAA,MACnB;AAAA,MACA,OAAO,KAAK,YAAY,KAAK,MAAM,MAAM,YAAY,SAAS,gBAAgB;AAAA,IAChF;AACA,aAAS;AAAA,EACX,CAAC;AACD,iBAAe,QAAQ,QAAQ,EAAE,KAAK,2BAA2B,CAAC;AAGlE,QAAM,gBAAgB,oBAAI,IAAkB;AAC5C,QAAM,WAAW,CAAC,SAChB,MAAM,SAAS,QACf,WAAW,SAAS,QACpB,SAAS,SAAS,QAClB,CAAC,GAAG,cAAc,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,KAAK,SAAS,IAAI;AAG7D,MAAI,cAAc;AAClB,MAAI,YAAkB,EAAE,GAAG,GAAG,GAAG,GAAG,OAAO,GAAG,QAAQ,EAAE;AACxD,MAAI,eAAe;AACnB,QAAM,8BAA8B,MAAM;AACxC,iBAAa,YAAY;AACzB,mBAAe,OAAO,WAAW,UAAU,oBAAoB,EAAE;AAAA,EACnE;AACA,MAAI,eAAe;AACnB,MAAI,YAAY;AAEhB,QAAM,cAAc,CAAC,MAAY,QAC/B,KAAK,IAAI,KAAK,KAAK,OAAO,KAAK,KAAK,MAAM,IAAI,OAAO,OAAO,gBACxD,KAAK,cAAc,mBAAmB,MACtC;AACN,QAAM,eAAe,CAAC,SAAiB;AACrC,UAAM,KAAK,YAAY,IAAI,IAAI;AAC/B,QAAI,MAAM,UAAW;AACrB,iBAAa,YAAY;AACzB,gBAAY;AACZ,mBAAe,OAAO,WAAW,MAAM;AACrC,kBAAY;AACZ,eAAS;AAAA,IACX,GAAG,IAAI;AAAA,EACT;AAEA,QAAM,YAAY,CAAC,MAAY,cAAsB,aAAqB,WAAoB;AAC5F,UAAM,MAAM,YAAY,IAAI;AAG5B,kBAAc,KAAK,IAAI,aAAa,gBAAgB;AACpD,gBAAY;AACZ,YAAQ,SAAS;AACjB,UAAM,MAAM;AACZ,UAAM,QAAQ,CAAC,GAAG,GAAG,GAAG,CAAC;AACzB,eAAW,QAAQ,MAAM,OAAO,GAAG;AACjC,UAAI,CAAC,WAAW,KAAK,MAAM,IAAI,EAAG;AAClC,cAAQ,KAAK,IAAI;AACjB,YAAM,QAAQ,KAAK;AAAA,QACjB;AAAA,QACA;AAAA,SACC,YAAY,KAAK,KAAK,KAAK;AAAA,SAC3B,YAAY,KAAK,KAAK,KAAK;AAAA,MAC9B;AACA,UAAI,KAAK,MAAO,MAAK,YAAY;AAEjC,YAAM,kBAAkB,SAAS;AACjC,UAAI,mBAAmB,WAAW,IAAI,KAAK,CAAC,KAAK,SAAS,CAAC,KAAK,YAAY;AAC1E,aAAK,OAAO,KAAK;AACjB,aAAK,YAAY;AAAA,MACnB;AACA,YAAM,YAAY,MAAM,KAAK,YAAY;AACzC,YAAM,OAAO,eAAe;AAC5B,UAAI,QAAQ,CAAC,KAAK,KAAM,MAAK,IAAI;AACjC,YAAM,OAAO,OAAO,WAAW,MAAM,MAAM,WAAW,MAAM,IAAI,CAAC;AACjE,UAAI,CAAC,MAAM;AACT,aAAK,UAAU;AACf,aAAK,MAAM,SAAS;AAAA,MACtB;AACA,YAAM,QAAQ,MAAM,QAAQ,KAAK,IAAI;AACrC,UAAI,OAAO;AAEX,UAAI,CAAC,MAAO,QAAO,MAAM,QAAQ,KAAK,KAAK,IAAI,QAAQ;AAAA,eAG9C,KAAM,QAAO,KAAK,YAAY,SAAS,SAAS,IAAI,KAAK,SAAS;AAAA,eAClE,KAAK,SAAS,KAAK,YAAY;AACtC,cAAM,OAAO,YAAY,MAAM,GAAG;AAClC,YAAI,OAAO,EAAG,cAAa,IAAI;AAAA,YAC1B,QAAO;AAAA,MACd,WAGS,KAAK,aAAa,SAAS,QAAQ,IAAI,OAAQ,QAAO;AAAA,eACtD,CAAC,UAAU,KAAK,YAAY,QAAQ,iBAAkB,QAAO;AACtE,UAAI,QAAQ,EAAG,OAAM,MAAM,IAAI;AAC/B,UAAI,OAAO,KAAK,CAAC,KAAK,iBAAiB,KAAK,WAAW,EAAG;AAE1D,WAAK,cAAc,kBAAkB,kBAAkB;AACvD,WAAK,YAAY,OAAO,IAAI,SAAS,QAAQ,OAAO,iBAAiB,KAAK,MAAM,IAAI;AACpF,UAAI,OAAO,MAAM,IAAI,KAAK,IAAI;AAC9B,UAAI,CAAC,MAAM;AACT,eAAO,EAAE,MAAM,KAAK,MAAM,OAAO,CAAC,GAAG,UAAU,CAAC,GAAG,OAAO,CAAC,GAAG,UAAU,KAAK,SAAS;AACtF,cAAM,IAAI,KAAK,MAAM,IAAI;AAAA,MAC3B;AACA,WAAK,WAAW,KAAK,IAAI,KAAK,UAAU,KAAK,QAAQ;AACrD,UAAI,QAAQ,EAAG,MAAK,MAAM,KAAK,IAAI;AACnC,UAAI,KAAK,cAAe,MAAK,SAAS,KAAK,IAAI;AAC/C,WAAK,MAAM,KAAK,GAAG,IAAI;AAAA,IACzB;AACA,eAAW,QAAQ,MAAM,OAAO,EAAG,MAAK,MAAM,KAAK,CAAC,GAAG,MAAM,EAAE,WAAW,EAAE,QAAQ;AAAA,EACtF;AAMA,QAAM,aAAa,CAAC,MAAY,MAAY,WAAoB,WAAoB;AAClF,UAAM,QAAQ,aAAa,KAAK,MAAM,IAAI;AAC1C,SAAK,gBAAgB;AACrB,SAAK,QAAQ,KAAK,MAAM,OAAO,CAAC,SAAS,MAAM,QAAQ,KAAK,IAAI,CAAC;AAEjE,QAAI,KAAK,MAAO,YAAW,QAAQ,KAAK,MAAO,MAAK,QAAQ;AAC5D,QAAI,CAAC,MAAM,QAAQ,KAAK,OAAO,EAAG,MAAK,UAAU;AACjD,QAAI,WAAW;AACb,YAAM,QAAQ,cAAc;AAC5B,YAAM,QACJ,CAAC,KAAK,WACN,KAAK,SACL,KAAK,iBAAiB,SACtB,CAAC,SAAS,KAAK,aAAc,KAAK;AACpC,UAAI,OAAO;AACT,aAAK,gBAAgB,WAAW,OAAO,KAAK;AAC5C,aAAK,qBAAqB;AAAA,MAC5B;AACA,kCAA4B;AAC5B,aAAO,CAAC;AAAA,IACV;AAEA,UAAM,UAAU,KAAK,MAAM,OAAO,CAAC,SAAS,KAAK,UAAU,eAAe,CAAC,KAAK,KAAK;AACrF,QAAI,UAAU,QAAQ,WAAW,EAAG,QAAO,CAAC;AAC5C,UAAM,OAAO,KAAK,IAAI,GAAG,KAAK,MAAM,cAAc,WAAW,CAAC;AAC9D,UAAM,OAAkB,CAAC;AACzB,UAAM,QAAQ,CAAC,MAAc,WAAmB,KAAK,OAAO,OAAO,UAAU,IAAI;AACjF,aACM,MAAM,MAAM,MAAM,GAAG,KAAK,KAAK,CAAC,GACpC,OAAO,MAAM,OAAO,KAAK,IAAI,MAAM,KAAK,KAAK,CAAC,GAC9C,OACA;AACA,eACM,SAAS,MAAM,MAAM,GAAG,KAAK,KAAK,CAAC,GACvC,UAAU,MAAM,MAAM,KAAK,IAAI,MAAM,KAAK,KAAK,CAAC,GAChD,UACA;AACA,YAAI,QAAQ,KAAK,CAAC,SAAS,KAAK,WAAW,UAAU,KAAK,QAAQ,GAAG,EAAG;AACxE,cAAM,OAAO,aAAa,KAAK,MAAM;AAAA,UACnC,GAAG,KAAK,KAAK,IAAI,SAAS;AAAA,UAC1B,GAAG,KAAK,KAAK,IAAI,MAAM;AAAA,UACvB,OAAO;AAAA,UACP,QAAQ;AAAA,QACV,CAAC;AACD,aAAK,KAAK;AAAA,UACR;AAAA,UACA;AAAA,UACA,OAAO;AAAA,UACP;AAAA,UACA;AAAA,UACA,UAAU,iBAAiB,MAAM,IAAI;AAAA,QACvC,CAAC;AAAA,MACH;AAAA,IACF;AAEA,QAAI,KAAK,WAAW,GAAG;AACrB,WAAK,QAAQ;AACb,WAAK,UAAU;AAAA,IACjB;AACA,WAAO;AAAA,EACT;AAGA,QAAM,aAAa,CAAC,OAAa,UAAwB;AACvD,UAAM,SAAS,YAAY,KAAK;AAChC,UAAM,MAAM,CAAC,OAAe,SAC1B,QAAQ,QAAQ,CAAC,OAAO,IAAI,IAAI,CAAC,SAAS,OAAO,SAAS,GAAG,KAAK;AACpE,UAAM,CAAC,GAAG,KAAK,IAAI,IAAI,MAAM,GAAG,MAAM,KAAK;AAC3C,UAAM,CAAC,GAAG,MAAM,IAAI,IAAI,MAAM,GAAG,MAAM,MAAM;AAC7C,WAAO,EAAE,GAAG,GAAG,OAAO,OAAO;AAAA,EAC/B;AAGA,QAAM,eAAe,CACnB,MACA,QACA,SACG;AACH,QAAI;AACF,aAAO,MAAM;AAAA,QACX,SACI;AAAA,UACE,QAAQ,KAAK;AAAA,UACb,SAAS,OAAO;AAAA,UAChB,SAAS,OAAO;AAAA,UAChB,aAAa,OAAO;AAAA,UACpB,cAAc,OAAO;AAAA,QACvB,IACA,EAAE,QAAQ,KAAK,QAAQ;AAAA,QAC3B;AAAA,UACE,SAAS,MAAM;AAAA,UACf,QAAQ,EAAE,GAAG,KAAK,GAAG,GAAG,KAAK,GAAG,GAAG,KAAK,MAAM;AAAA,UAC9C,MAAM,EAAE,OAAO,KAAK,OAAO,QAAQ,KAAK,OAAO;AAAA,UAC/C,oBAAoB;AAAA,QACtB;AAAA,MACF;AACA,aAAO;AAAA,IACT,QAAQ;AAEN,aAAO;AAAA,IACT;AAAA,EACF;AAOA,QAAM,UAAU,CAAC,UAA4B,OAAe,QAAgB,YAAY,UACtF,MAAM,QAAQ,QAAQ,KACtB,MAAM,SAAS,QAAQ,MAAM,aAC7B,SAAS,UAAU,SACnB,SAAS,WAAW,UACpB,OAAO,UAAU,SAAS,CAAC,KAC3B,OAAO,UAAU,SAAS,CAAC,IACvB,YACE,YAAY,MAAM,eAAe,OAAO,MAAM,IAAI,SAAS,MAAM,SAAS,OAAO,MAAM;AAC/F,QAAM,aAAa,CAAC,SAAe,MAAM,QAAQ,KAAK,KAAK,KAAK,CAAC,KAAK;AAEtE,QAAM,QAAQ,CAAC,MAAY,MAAiB,OAAe,QAAgB;AACzE,SAAK,OAAO;AACZ,SAAK,YAAY;AACjB,QAAI,UAAU,iBAAiB;AAC7B,WAAK,QAAQ;AACb,WAAK,aAAa;AAClB,WAAK,UAAU;AAAA,IACjB,WAAW,KAAK,MAAO,MAAK,aAAa;AACzC,QAAI,KAAK,OAAO;AAEd,WAAK,UAAU;AACf,WAAK,cAAc;AAAA,IACrB;AACA,SAAK,QAAQ;AACb,SAAK,aAAa;AAAA,EACpB;AAEA,QAAM,YAAY,oBAAI,IAAqB;AAM3C,QAAM,YAAY,CAAC,UAAkB;AACnC,QAAI,QAAQ;AACZ,QAAI,SAAS;AACb,QAAI,aAAa;AACjB,QAAI,UAAU;AACd,UAAM,aAAa,MACjB,QAAQ,MACP,SAAS,kBACR,UAAU,qBACV,YAAY,IAAI,IAAI,SAAS;AACjC,UAAM,UAAU,CAAC,GAAG,MAAM,OAAO,CAAC,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,WAAW,EAAE,QAAQ;AAC1E,eAAW,QAAQ,SAAS;AAC1B,YAAM,EAAE,KAAK,IAAI;AAEjB,UAAI,CAAC,KAAK,YAAY,KAAK,iBAAiB,eAAe,WAAW,GAAG;AACvE,mBAAW,KAAK,MAAM,SAAS,KAAK,SAAS,SAAS,KAAK,MAAM;AACjE;AAAA,MACF;AACA,YAAM,QAAQ,KAAK,MAAM,OAAO,CAAC,KAAK,SAAS,KAAK,IAAI,KAAK,KAAK,WAAW,GAAG,CAAC;AACjF,YAAM,UAAU,MAAM,IAAI,IAAI;AAC9B,YAAM,aAAa,KAAK,MAAM,OAAO,CAAC,KAAK,MAAM,MAAM,EAAE,KAAK,QAAQ,EAAE,KAAK,QAAQ,CAAC;AAGtF,YAAM,YAAY,KAAK,QAAQ,SAAS,YAAY,KAAK,KAAK,SAAS,SAAS,YAAY;AAC5F,YAAM,QACJ,cAAc,KAAK,MAAM,UAAU,KAAK,cAAc,OAAO,KAAK,QAAQ,KAAK;AACjF,YAAM,YAAY,QACd;AAAA,QACE,UAAU,IAAI,IAAI,KAAK;AAAA,QACvB,KAAK,KAAK,KAAK,QAAQ,KAAK;AAAA,QAC5B,KAAK,KAAK,KAAK,SAAS,KAAK;AAAA,QAC7B,UAAU;AAAA,MACZ,IACA;AACJ,UAAI,UAAW,WAAU,IAAI,MAAM,SAAS;AAC5C,UAAI,aAAa,CAAC,aAAa,MAAM,MAAM,SAAS,GAAG;AACrD,mBAAW,KAAK,MAAM,SAAS,KAAK,SAAS,SAAS,KAAK,MAAM;AACjE;AAAA,MACF;AAEA,UAAI,WAAW;AACb,cAAM,OAAO;AACb;AACA,kBAAU,KAAK,QAAQ,KAAK;AAC5B,mBAAW,QAAQ,SAAS;AAC1B,gBAAM,OAAO;AAAA,YACX,OAAO,KAAK;AAAA,YACZ,YAAY,KAAK;AAAA,YACjB,GAAG,KAAK,IAAI,KAAK,QAAQ;AAAA,YACzB,GAAG,KAAK,IAAI,KAAK,QAAQ;AAAA,YACzB,OAAO,KAAK,KAAK,QAAQ;AAAA,YACzB,QAAQ,KAAK,KAAK,SAAS;AAAA,UAC7B;AACA,gBAAM,MAAM,MAAM,OAAO,KAAK;AAAA,QAChC;AACA,sBAAc,QAAQ;AAAA,MACxB,OAAO;AACL,mBAAW,QAAQ,KAAK,OAAO;AAC7B,cAAI,WAAW,GAAG;AAChB;AACA;AAAA,UACF;AACA,gBAAM,YAAY,KAAK,gBAAgB;AACvC,gBAAM,OAAO;AAAA,YACX,YAAY,KAAK,QAAQ,KAAK;AAAA,YAC9B,KAAK,IAAI,GAAG,KAAK,MAAM,KAAK,KAAK,QAAQ,KAAK,WAAW,CAAC;AAAA,YAC1D,KAAK,IAAI,GAAG,KAAK,MAAM,KAAK,KAAK,SAAS,KAAK,WAAW,CAAC;AAAA,YAC3D;AAAA,UACF;AACA,gBAAM,SAAS;AAAA,YACb,GAAG,KAAK;AAAA,YACR,GAAG,KAAK;AAAA,YACR,OAAO,KAAK,KAAK;AAAA,YACjB,QAAQ,KAAK,KAAK;AAAA,UACpB;AACA,cAAI,CAAC,QAAQ,CAAC,aAAa,MAAM,QAAQ,IAAI,GAAG;AAC9C;AACA;AAAA,UACF;AACA;AACA,oBAAU,KAAK,QAAQ,KAAK;AAC5B,gBAAM,MAAM,MAAM,KAAK,aAAa,KAAK;AACzC;AAAA,QACF;AAAA,MACF;AAIA,YAAM,OAAO,oBAAI,IAAY;AAC7B,YAAM,aAAa,CAAC,MAAY,MAAYC,QAAe,aAA+B;AACxF,YAAI,CAAC,KAAK,IAAIA,MAAK,KAAK,WAAW,EAAG,QAAO;AAC7C,cAAM,OAAO;AAAA,UACX;AAAA,UACA,KAAK,IAAI,GAAG,KAAK,MAAM,KAAK,QAAQA,MAAK,CAAC;AAAA,UAC1C,KAAK,IAAI,GAAG,KAAK,MAAM,KAAK,SAASA,MAAK,CAAC;AAAA,QAC7C;AACA,cAAM,SAAS;AAAA,UACb,GAAG,KAAK,QAAQ,KAAK,IAAI,KAAK,KAAK;AAAA,UACnC,GAAG,KAAK,QAAQ,KAAK,IAAI,KAAK,KAAK;AAAA,UACnC,OAAO,KAAK;AAAA,UACZ,QAAQ,KAAK;AAAA,QACf;AACA,YAAI,CAAC,QAAQ,CAAC,aAAa,MAAM,QAAQ,IAAI,EAAG,QAAO;AACvD;AACA,aAAK,IAAIA,MAAK;AACd,kBAAU,KAAK,QAAQ,KAAK;AAE5B,YAAI,KAAK,OAAO;AACd,eAAK,QAAQ;AACb,eAAK,aAAa;AAClB,eAAK,aAAa;AAClB,eAAK,cAAc;AAAA,QACrB;AACA,eAAO;AAAA,MACT;AACA,iBAAW,QAAQ,KAAK,UAAU;AAChC,cAAM,OAAO,WAAW,MAAM,KAAK,eAAgB,KAAK,oBAAoB,KAAK,OAAO;AACxF,YAAI,CAAC,MAAM;AACT;AACA;AAAA,QACF;AACA,aAAK,UAAU;AACf,aAAK,cAAc,KAAK;AACxB,aAAK,eAAe,KAAK;AACzB,aAAK,gBAAgB;AAAA,MACvB;AACA,UAAI,YAAY;AAChB,iBAAW,OAAO,KAAK,OAAO;AAE5B,cAAM,EAAE,MAAM,QAAQ,KAAK,OAAAA,OAAM,IAAI;AACrC,cAAM,MAAM,KAAK,MAAM;AAAA,UACrB,CAAC,SACC,KAAK,SAAS,KAAK,UAAUA,UAAS,KAAK,WAAW,UAAU,KAAK,QAAQ;AAAA,QACjF;AACA,cAAM,WAAW,OAAO,IAAI,KAAK,MAAM,GAAG,EAAE,OAAO;AACnD,cAAM,OAAO,KAAK,QAAQ,OAAO,WAAW,MAAM,IAAI,MAAMA,QAAO,QAAQ;AAC3E,YAAI,CAAC,MAAM;AACT;AACA;AAAA,QACF;AACA,YAAI,OAAO,EAAG,MAAK,MAAM,OAAO,KAAK,CAAC;AACtC,aAAK,MAAM,KAAK,EAAE,MAAM,MAAM,IAAI,MAAM,OAAAA,QAAO,QAAQ,KAAK,OAAO,MAAM,CAAC;AAAA,MAC5E;AACA,iBAAW;AAGX,iBAAW,QAAQ,SAAS;AAC1B,YAAI,WAAW,IAAI,KAAK,KAAK,MAAO;AACpC,YAAI,MAAM,QAAQ,KAAK,KAAK,KAAK,QAAQ,KAAK,UAAU,qBAAsB;AAC9E,cAAM,OAAO;AAAA,UACX,KAAK;AAAA,UACL,KAAK,IAAI,GAAG,KAAK,MAAM,KAAK,KAAK,QAAQ,eAAe,CAAC;AAAA,UACzD,KAAK,IAAI,GAAG,KAAK,MAAM,KAAK,KAAK,SAAS,eAAe,CAAC;AAAA,UAC1D;AAAA,QACF;AACA,cAAM,SAAS;AAAA,UACb,GAAG,KAAK;AAAA,UACR,GAAG,KAAK;AAAA,UACR,OAAO,KAAK,KAAK;AAAA,UACjB,QAAQ,KAAK,KAAK;AAAA,QACpB;AACA,YAAI,CAAC,QAAQ,CAAC,aAAa,MAAM,QAAQ,IAAI,EAAG;AAChD;AACA,aAAK,QAAQ;AACb,aAAK,aAAa;AAClB,aAAK,UAAU;AAAA,MACjB;AACA,YAAM,OACJ,KAAK,MAAM,MAAM,CAAC,SAAS,CAAC,KAAK,SAAS,MAAM,QAAQ,KAAK,IAAI,CAAC,KAClE,KAAK,SAAS,MAAM,CAAC,SAAS,KAAK,kBAAkB,IAAI,KACzD,cAAc;AAChB,UAAI,QAAQ,CAAC,SAAS,IAAI,EAAG,MAAK,YAAY,OAAO,WAAW;AAAA,IAClE;AACA,UAAM,sBAAsB;AAC5B,UAAM,uBAAuB;AAC7B,WAAO;AAAA,EACT;AAEA,QAAM,YAAY,MAAM;AACtB,QAAI,YAAY,QAAQ;AACxB,eAAW,QAAQ,QAAS,cAAa,KAAK,MAAM,UAAU,KAAK,UAAU,IAAI;AACjF,iBAAa,UAAU,OAAO;AAC9B,aAAS,QAAQ,SAAS;AAC1B,UAAM,OAAO,SAAS;AACtB,QAAI,QAAQ;AACZ,SAAK,SAAS;AACd,oBAAgB;AAChB,QAAI,YAA2B;AAC/B,UAAM,WAAW,CAAC,WAA0B;AAC1C,UAAI,KAAK,UAAU,cAAc,OAAQ;AACzC,kBAAY;AACZ,WAAK,KAAK,EAAE,QAAQ,OAAO,OAAO,OAAO,EAAE,CAAC;AAAA,IAC9C;AACA,UAAM,OAAO,CAAC,MAAY,SAA2B;AACnD,eAAS,IAAI;AACb,WAAK,KAAK,SAAS,CAAC,EAAE;AACtB,YAAM,SAAS,UAAU;AACzB,WAAK,MAAM,IAAI,KAAK;AACpB,WAAK,SAAS,CAAC,IAAI,KAAK;AACxB,WAAK,SAAS,CAAC,IAAI,KAAK;AACxB,WAAK,SAAS,CAAC,IAAI,KAAK;AACxB,UAAI,MAAM;AACR,cAAM,MAAM,KAAK,KAAK;AACtB,aAAK,SAAS,CAAC,IAAI,KAAK;AACxB,aAAK,SAAS,CAAC,IAAI,KAAK;AACxB,aAAK,SAAS,CAAC,IAAI,KAAK,IAAI,KAAK;AACjC,aAAK,SAAS,CAAC,IAAI,KAAK,IAAI,KAAK;AACjC,aAAK,SAAS,CAAC,IAAI,KAAK;AACxB,aAAK,SAAS,CAAC,IAAI;AAAA,MACrB,OAAO;AACL,aAAK,SAAS,CAAC,IAAI;AAAA,MACrB;AACA,WAAK,SAAS,EAAE,IAAI;AAAA,IACtB;AAEA,UAAM,aAAa,CACjB,MACA,MACA,SACG;AACH,eAAS,KAAK,MAAM;AACpB,WAAK,KAAK,SAAS,CAAC,EAAE;AACtB,YAAM,SAAS,UAAU;AACzB,YAAM,EAAE,KAAK,IAAI;AACjB,WAAK,MAAM,IAAI,KAAK;AACpB,WAAK,SAAS,CAAC,IAAI,KAAK;AACxB,WAAK,SAAS,CAAC,IAAI,KAAK;AACxB,WAAK,SAAS,CAAC,IAAI,KAAK;AACxB,YAAM,MAAM,KAAK,KAAK;AACtB,WAAK,SAAS,CAAC,IAAI,KAAK;AACxB,WAAK,SAAS,CAAC,IAAI,KAAK;AACxB,WAAK,SAAS,CAAC,IAAI,KAAK,IAAI,KAAK;AACjC,WAAK,SAAS,CAAC,IAAI,KAAK,IAAI,KAAK;AACjC,WAAK,SAAS,CAAC,IAAI,KAAK;AACxB,WAAK,SAAS,CAAC,IAAI;AACnB,WAAK,SAAS,EAAE,IAAI,KAAK;AACzB,WAAK,IAAI,KAAK,QAAQ,SAAS,EAAE;AAAA,IACnC;AACA,UAAM,WAAW,CAAC,SAAkB,OAAiB,UAAkB;AACrE,YAAM,OAAO,SAAS,OAAO;AAC7B,UAAI,CAAC,QAAQ,CAAC,WAAW,MAAM,SAAS,EAAG;AAC3C,eAAS,IAAI;AACb,WAAK,KAAK,SAAS,CAAC,EAAE;AACtB,YAAM,SAAS,UAAU;AACzB,WAAK,MAAM,IAAI,KAAK;AACpB,WAAK,SAAS,CAAC,IAAI,KAAK;AACxB,WAAK,SAAS,CAAC,IAAI,KAAK;AACxB,WAAK,SAAS,CAAC,IAAI,KAAK;AACxB,WAAK,IAAI,OAAO,SAAS,CAAC;AAC1B,WAAK,SAAS,CAAC,IAAI;AACnB,WAAK,SAAS,EAAE,IAAI;AAAA,IACtB;AACA,QAAI,cAAc;AAClB,eAAW,QAAQ,SAAS;AAE1B,YAAM,OAAO,MAAM,QAAQ,KAAK,IAAI,IAChC,KAAK,OACL,MAAM,QAAQ,KAAK,KAAK,IACtB,KAAK,QACL;AACN,UAAI,QAAQ,SAAS,KAAK,KAAM;AAChC,YAAM,UAAU,SAAS;AACzB,YAAM,QAAQ,KAAK,MAAM,SAAS,KAAM,KAAK,YAAY,QAAQ,MAAM,QAAQ,KAAK,OAAO;AAC3F,YAAM,QAAQ,QAAQ,IAAI,UAAU,IAAI;AAGxC,YAAM,SAAS,KAAK,eAAe,MAAM,SAAS,IAAI,KAAK,QAAQ;AACnE,UAAI,UAAU,KAAK,UAAU,EAAG,OAAM;AACtC,UAAI,WAAW,KAAK,UAAU,EAAG,OAAM;AACvC,WAAK,QAAQ;AACb,WAAK,aAAa,MAAM;AACxB,YAAM,OAAO,QAAQ,OAAO,QAAQ,IAAI,KAAK,OAAO,IAAI;AACxD,UAAI,MAAM;AACR,YAAI,KAAK,OAAO,SAAU,iBAAgB;AAC1C,YAAI,QAAQ,SAAS,UAAU,KAAK,MAAM,GAAG;AAC3C,qBAAW,MAAM,MAAM,IAAI;AAC3B;AAAA,QACF;AACA,wBAAgB;AAAA,MAClB;AACA,WAAK,KAAK,MAAM,IAAI;AAGpB,YAAM,UAAU,CAAC,SAAe,KAAK,UAAU,eAAe,CAAC,KAAK;AACpE,iBAAW,QAAQ,KAAK;AACtB,YAAI,CAAC,QAAQ,IAAI,KAAK,MAAM,QAAQ,KAAK,IAAI,EAAG,MAAK,KAAK,MAAM,KAAK,IAAI;AAC3E,UAAI,KAAK,WAAW,MAAM,QAAQ,KAAK,OAAO,EAAG,MAAK,KAAK,aAAc,KAAK,OAAO;AACrF,iBAAW,QAAQ,KAAK;AACtB,YAAI,QAAQ,IAAI,KAAK,MAAM,QAAQ,KAAK,IAAI,EAAG,MAAK,KAAK,MAAM,KAAK,IAAI;AAAA,IAC5E;AACA,UAAM,cAAc;AAEpB,eAAW,WAAW,UAAW,UAAS,SAAS,gBAAgB,eAAe;AAClF,QAAI,WAAW,CAAC,UAAU,IAAI,OAAO,EAAG,UAAS,SAAS,YAAY,WAAW;AACjF,UAAM,WAAW,OAAO;AACxB,UAAM,MAAM,OAAO,QAAQ,KAAK,IAAI,GAAG,QAAQ;AAC/C,UAAM,MAAM,YAAY,IAAI;AAC5B,aAAS,KAAK,QAAQ,UAAU,OAAO,cAAc,KAAK,OAAO,MAAM;AAAA,MACrE,OAAO,MAAM,aAAa;AAAA,MAC1B,SAAS,UAAU,cAAc,QAAQ,OAAO,IAAI;AAAA,MACpD;AAAA,MACA,YAAY,KAAK,KAAK,MAAM,aAAa,KAAM,GAAG;AAAA,IACpD,CAAC;AAAA,EACH;AAOA,QAAM,QAAQ,CAAC,YAAqB;AAClC,QAAI,UAAW;AACf,UAAM,QAAQ,YAAY,IAAI;AAC9B,UAAM,UAAU;AAChB,UAAM,WAAW,OAAO;AACxB,UAAM,MAAM,OAAO,QAAQ,KAAK,IAAI,GAAG,QAAQ;AAC/C,UAAM,OAAO,iBAAiB,QAAQ,UAAU,OAAO,YAAY;AACnE,UAAM,SAAS,QAAQ,mBAAmB;AAC1C,cAAU,MAAM,eAAe,OAAO,OAAO,GAAG,GAAG,OAAO,OAAO,KAAK,MAAM;AAE5E,QAAI,CAAC,WAAW,MAAM,OAAO,GAAG;AAE9B,YAAM,WAAW,QAAQ;AACzB,UAAI,WAAW,KAAK;AAClB,YAAI,WAAW,cAAe,sBAAqB,KAAK,IAAI,GAAG,sBAAsB,CAAC;AAAA,iBAC7E,WAAW;AAClB,+BAAqB,KAAK,IAAI,0BAA0B,qBAAqB,CAAC;AAAA,MAClF;AACA,oBAAc;AACd,UAAI,WAAW;AACf,iBAAW,QAAQ,CAAC,GAAG,MAAM,OAAO,CAAC,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,WAAW,EAAE,QAAQ,GAAG;AAC9E,YAAI,KAAK,KAAK,SAAU;AACxB,YAAI,cAAc,mBAAoB;AACtC,aAAK,KAAK,YAAY,MAAM,WAAW;AAAA,MACzC;AAEA,sBAAgB;AAChB,aAAO,aAAa;AACpB;AAAA,IACF;AAEA,QAAI,UAAU;AACd,UAAM,sBAAsB;AAC5B,UAAM,uBAAuB;AAC7B,QAAI,WAAW,MAAM,OAAO,EAAG,WAAU,UAAU,KAAK;AAGxD,eAAW,QAAQ,MAAM,KAAK,GAAG;AAC/B,UAAI,KAAK,YAAY,CAAC,MAAM,IAAI,IAAI,KAAK,KAAK,gBAAgB,eAAe,CAAC,SAAS,IAAI;AACzF,aAAK,YAAY,OAAO,WAAW;AAAA,IACvC;AACA,UAAM,WAAW,YAAY,IAAI,IAAI;AACrC,cAAU;AACV,UAAM;AACN,qBAAiB;AACjB,UAAM,UAAU,QAAQ;AACxB,UAAM,UAAU;AAChB,UAAM,UAAU,YAAY,IAAI,IAAI;AACpC,QAAI,UAAU,KAAK,cAAe,UAAS;AAAA,EAC7C;AAGA,MAAI,gBAAgB;AACpB,SAAO,UAAU,CAAC,UAAU;AAE1B,QAAI,UAAU;AACd,eAAW,WAAW,MAAM,iBAAiB;AAC3C,YAAM,OAAO,cAAc,IAAI,OAAO;AACtC,UAAI,CAAC,KAAM;AACX,iBAAW,QAAQ,CAAC,MAAM,WAAW,SAAS,GAAG,cAAc,KAAK,CAAC,GAAG;AACtE,YAAI,MAAM,SAAS,MAAM;AACvB,eAAK,QAAQ;AACb,oBAAU;AAAA,QACZ;AAAA,MACF;AAAA,IACF;AACA,QAAI,QAAS,WAAU,MAAM;AAC7B,QAAI,CAAC,iBAAiB,CAAC,QAAS;AAChC,oBAAgB;AAChB,UAAM,IAAI;AAAA,EACZ;AAEA,QAAM,UAAU,MAAM,iBAAiB,QAAQ,OAAO,aAAa,OAAO,YAAY;AAGtF,QAAM,SAAS,CAAC,WAA8C;AAC5D,QAAI,UAAU,kBAAkB,cAAc,SAAS,OAAO;AAC9D,WAAO,SAAS,iBAAiB,CAAC,cAAc,IAAI,QAAQ,aAAa,GAAG;AAC1E,gBAAU,QAAQ;AAAA,IACpB;AACA,WAAO,UAAU,MAAM,IAAI,OAAO,IAAI;AAAA,EACxC;AAIA,QAAM,YAAY,IAAI,iBAAiB,CAAC,YAAY;AAElD,cAAU,MAAM;AAChB,QAAI,UAAU;AACd,eAAW,UAAU,SAAS;AAC5B,YAAM,SAAS,OAAO;AACtB,UACE,OAAO,SAAS,iBACf,MAAM,IAAI,MAAM,KAAK,cAAc,IAAI,MAAM,KAAK,WAAW,SAC9D;AACA;AAAA,MACF;AACA,YAAM,OAAO,OAAO,OAAO,MAAM;AACjC,UAAI,QAAQ,CAAC,KAAK,OAAO;AACvB,aAAK,QAAQ;AAEb,YAAI,CAAC,QAAS,WAAU,WAAW,KAAK,MAAM,QAAQ,CAAC;AAAA,MACzD;AAAA,IACF;AACA,QAAI,QAAS,UAAS;AAAA,EACxB,CAAC;AACD,YAAU,QAAQ,QAAQ;AAAA,IACxB,SAAS;AAAA,IACT,WAAW;AAAA,IACX,eAAe;AAAA,IACf,YAAY;AAAA,EACd,CAAC;AAGD,QAAM,QAAQ,CAAC,SAAe;AAC5B,QAAI,SAAS,IAAI,EAAG;AACpB,QAAI,KAAK,WAAY,QAAO,qBAAqB,KAAK,OAAO;AAC7D,SAAK,aAAa;AAClB,SAAK,QAAQ,MAAM,YAAY;AAC/B,aAAS;AAAA,EACX;AAOA,QAAM,mBAAmB,MAAM;AAC7B,QAAI,CAAC,QAAQ,eAAgB;AAC7B,UAAM,MAAM,OAAO,QAAQ,KAAK,IAAI,GAAG,OAAO,WAAW;AACzD,UAAM,EAAE,KAAK,IAAI;AACjB,UAAMC,SAAQ,IAAI,UAAU;AAAA,MAC1B;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,QACE,KAAK,KAAK,IAAI,OAAO,KAAK,OAAO,KAAK,QAAQ,QAAQ;AAAA,QACtD,KAAK,KAAK,IAAI,OAAO,KAAK,OAAO,KAAK,QAAQ,QAAQ;AAAA,IAC1D,CAAC;AACD,QAAI;AACF,WAAK,KAAK,QAAQ,MAAM,YAAY,OACjC,oBAAoB,KAAK,KAAK,SAASA,MAAK,EAC5C,SAAS;AACZ,WAAK,QAAQ,MAAM,gBAAgB;AACnC,uBAAiB;AAAA,IACnB,QAAQ;AACN,eAAS;AAAA,IACX;AAAA,EACF;AAGA,QAAM,UAAU,CAAC,SAAsB;AACrC,QAAI,SAAS,KAAM;AACnB,UAAM,WAAW;AACjB,WAAO;AACP,QAAI,UAAU;AACZ,eAAS,QAAQ,MAAM,gBAAgB;AACvC,mBAAa,WAAW;AACxB,YAAM,UAAU;AAChB,kBAAY;AACZ,UAAI,WAAW,YAAY,UAAU;AACnC,gBAAQ,QAAQ;AAChB,cAAM,QAAQ,IAAI;AAAA,MACpB;AACA,oBAAc,OAAO,WAAW,MAAM;AACpC,cAAM,OAAO;AACb,YAAI,CAAC,KAAM;AACX,oBAAY;AACZ,aAAK,QAAQ;AACb,cAAM,KAAK,IAAI;AAAA,MACjB,GAAG,SAAS;AACZ,YAAM,SAAS,IAAI;AAAA,IACrB;AACA,QAAI,CAAC,KAAM;AACX,UAAM,EAAE,KAAK,IAAI;AACjB,SAAK,YAAY,MAAM,WAAW;AAClC,QAAI,CAAC,KAAK,YAAY;AACpB,aAAO,sBAAsB,KAAK,SAAS,CAAC,CAAC;AAC7C,WAAK,aAAa;AAAA,IACpB;AACA,qBAAiB;AACjB,qBAAiB;AACjB,aAAS;AAAA,EACX;AAGA,QAAM,WAAW,MAAM;AACrB,QAAI,CAAC,QAAS,QAAO,QAAQ,IAAI;AACjC,UAAM,QAAQ,cAAc,QAAQ,OAAO;AAC3C,QAAI,MAAmB;AACvB,eAAW,QAAQ,MAAM,OAAO,EAAG,KAAI,cAAc,KAAK,MAAM,KAAK,EAAG,OAAM;AAC9E,YAAQ,GAAG;AAAA,EACb;AAEA,QAAM,gBAAgB,CAAC,UAAwB;AAC7C,UAAM,SAAS,OAAO,sBAAsB;AAC5C,cAAU,EAAE,GAAG,MAAM,UAAU,OAAO,MAAM,GAAG,MAAM,UAAU,OAAO,IAAI;AAE1E,QAAI,MAAM,YAAY,EAAG,UAAS;AAAA,EACpC;AACA,QAAM,iBAAiB,MAAM;AAC3B,cAAU;AACV,YAAQ,IAAI;AAAA,EACd;AAEA,MAAI,QAAe;AACnB,MAAI,YAAY;AAChB,QAAM,gBAAgB,CAAC,UAAwB;AAC7C,UAAM,SAAS,OAAO,sBAAsB;AAC5C,YAAQ,cAAc,QAAQ;AAAA,MAC5B,GAAG,MAAM,UAAU,OAAO;AAAA,MAC1B,GAAG,MAAM,UAAU,OAAO;AAAA,IAC5B,CAAC;AACD,gBAAY,YAAY,IAAI;AAC5B,QAAI,QAAQ,KAAM,UAAS;AAAA,EAC7B;AACA,QAAM,YAAY,CAAC,UAAsB;AACvC,UAAM,OAAO,OAAO,MAAM,MAAqB,KAAK;AACpD,QAAI,SAAS,QAAS;AACtB,UAAM,WAAW;AACjB,cAAU;AACV,QAAI,UAAU;AACZ,eAAS,QAAQ;AACjB,YAAM,SAAS,IAAI;AAAA,IACrB;AACA,QAAI,MAAM;AACR,WAAK,KAAK,YAAY,MAAM,WAAW;AACvC,WAAK,QAAQ;AACb,eAAS;AAAA,IACX;AAAA,EACF;AACA,QAAM,aAAa,CAAC,UAAsB;AACxC,QAAI,MAAM,iBAAiB,OAAO,SAAS,MAAM,aAAgC,EAAG;AACpF,UAAM,WAAW;AACjB,cAAU;AACV,QAAI,UAAU;AACZ,eAAS,QAAQ;AACjB,YAAM,SAAS,IAAI;AAAA,IACrB;AAAA,EACF;AAEA,QAAM,iBAAiB,CAAC,UAAiB;AACvC,UAAM,OAAO,OAAO,MAAM,MAAqB;AAC/C,QAAI,CAAC,KAAM;AACX,SAAK,QAAQ;AACb,aAAS;AAAA,EACX;AACA,SAAO,iBAAiB,QAAQ,gBAAgB,IAAI;AAEpD,QAAM,gBAAgB,MAAM;AAC1B,eAAW,QAAQ,MAAM,OAAO,EAAG,MAAK,QAAQ;AAChD,aAAS;AAAA,EACX;AACA,WAAS,MAAM,iBAAiB,eAAe,aAAa;AAC5D,UAAQ,iBAAiB,eAAe,aAAa;AACrD,UAAQ,iBAAiB,gBAAgB,cAAc;AACvD,UAAQ,iBAAiB,eAAe,eAAe,IAAI;AAC3D,SAAO,iBAAiB,WAAW,SAAS;AAC5C,SAAO,iBAAiB,YAAY,UAAU;AAO9C,QAAM,SAAS,oBAAI,QAAsB;AACzC,QAAM,QAAQ,CAAC,UAAiB;AAC9B,UAAM,OAAO,OAAO,MAAM,MAAqB;AAC/C,QAAI,KAAM,QAAO,IAAI,MAAM,YAAY,IAAI,CAAC;AAAA,EAC9C;AACA,QAAM,eAAe,CAAC,YAAqB;AACzC,UAAM,QAAQ,iBAAiB,OAAO;AACtC,UAAM,UAAU,CAAC,SAAiB,KAAK,MAAM,GAAG,EAAE,IAAI,CAAC,UAAU,WAAW,KAAK,KAAK,CAAC;AACvF,UAAM,YAAY,QAAQ,MAAM,kBAAkB;AAClD,UAAM,SAAS,QAAQ,MAAM,eAAe;AAC5C,UAAM,UAAU,KAAK,IAAI,GAAG,UAAU,IAAI,CAAC,GAAG,MAAM,KAAK,OAAO,IAAI,OAAO,MAAM,KAAK,EAAE,CAAC;AACzF,WAAO,KAAK,IAAI,KAAM,UAAU,GAAI;AAAA,EACtC;AACA,QAAM,kBAAkB,CAAC,UAAiB;AACxC,UAAM,OAAO,OAAO,MAAM,MAAqB;AAC/C,UAAM,MAAM,YAAY,IAAI;AAC5B,QAAI,CAAC,QAAQ,OAAO,OAAO,IAAI,IAAI,KAAK,aAAa,QAAS;AAC9D,QAAI,CAAC,WAAW,KAAK,MAAM,QAAQ,CAAC,EAAG;AACvC,QAAI,KAAK,IAAI,KAAK,KAAK,OAAO,KAAK,KAAK,MAAM,IAAI,OAAO,OAAO,cAAe;AAC/E,UAAM,KAAK,aAAa,MAAM,MAAiB,IAAI;AACnD,UAAM,MAAM,MAAM;AAClB,SAAK,cAAc,IAAI,IAAI,KAAK,MAAM,IAAK;AAC3C,kBAAc,IAAI,MAAM,GAAG;AAC3B,SAAK,QAAQ;AACb,aAAS;AACT,eAAW,MAAM;AACf,UAAI,cAAc,IAAI,IAAI,MAAM,IAAK;AACrC,oBAAc,OAAO,IAAI;AACzB,WAAK,QAAQ;AACb,YAAM,KAAK,IAAI;AACf,eAAS;AAAA,IACX,GAAG,EAAE;AAAA,EACP;AACA,aAAW,QAAQ,WAAY,QAAO,iBAAiB,MAAM,OAAO,IAAI;AACxE,SAAO,iBAAiB,iBAAiB,eAAe;AAExD,QAAM,YAAY,CAAC,SAAiB;AAClC,aAAS;AACT,uBAAmB,YAAY,IAAI;AAEnC,YAAQ,IAAI;AACZ,iBAAa,WAAW;AACxB,kBAAc,OAAO,WAAW,MAAM;AACpC,eAAS;AACT,eAAS;AAAA,IACX,GAAG,SAAS;AACZ,aAAS;AACT,YAAQ,iBAAiB,MAAM;AAAA,EACjC;AACA,QAAM,cAAc,gBAAgB,SAAS,MAAM,QAAQ,SAAS;AAEpE,QAAM,YAAY,CAAC,SAAsB,SAAe;AACtD,QAAI,OAAO,UAAU,MAAM,KAAK,OAAO,KAAK,MAAM,KAAK;AACvD,QAAI,CAAC,MAAM;AACT,YAAM,OAAO,IAAI;AAAA,QACf,KAAK,IAAI,UAAU,KAAK,KAAK,KAAK,KAAK,CAAC;AAAA,QACxC,KAAK,IAAI,UAAU,KAAK,KAAK,KAAK,MAAM,CAAC;AAAA,MAC3C;AACA,YAAM,IAAI,MAAM,oBAAI,IAAI,CAAC;AACzB,oBAAc,IAAI,KAAK,SAAS,IAAI;AACpC,aAAO,OAAO,KAAK,OAAO;AAE1B,UAAI,KAAK,UAAU,YAAY,KAAK,WAAW,SAAU,YAAW;AACpE,aAAO,KAAK,MAAM,KAAK,OAAO,KAAK,MAAM;AAAA,IAC3C;AACA,WAAO,OAAO,QAAQ,OAAO;AAAA,MAC3B,UAAU;AAAA,MACV,MAAM,GAAG,KAAK,CAAC;AAAA,MACf,KAAK,GAAG,KAAK,CAAC;AAAA,MACd,OAAO,GAAG,KAAK,KAAK;AAAA,MACpB,QAAQ,GAAG,KAAK,MAAM;AAAA,IACxB,CAAC;AACD,SAAK,KAAK,QAAQ,OAAO,OAAO;AAChC,WAAO;AAAA,EACT;AAEA,QAAM,cAAc,CAAC,SAAe;AAClC,UAAM,UAAU,MAAM,IAAI,KAAK,IAAI;AACnC,YAAQ,OAAO,IAAI;AACnB,SAAK,KAAK,QAAQ;AAClB,QAAI,QAAQ,SAAS,KAAK,KAAK,SAAS,UAAU;AAChD,YAAM,OAAO,KAAK,IAAI;AACtB,oBAAc,OAAO,KAAK,KAAK,OAAO;AACtC,WAAK,KAAK,QAAQ,OAAO;AAAA,IAC3B;AAAA,EACF;AAQA,QAAM,OAAO,CAAC,SAAe;AAC3B,UAAM,WAAW,KAAK;AACtB,UAAM,UAAU,SAAS;AACzB,QAAI,QAAS,SAAQ,IAAI;AACzB,UAAM,OAAO,IAAI,KAAK,KAAK,KAAK,KAAK,KAAK,KAAK,GAAG,KAAK,KAAK,KAAK,KAAK,MAAM,CAAC;AAC7E,UAAM,IAAI,MAAM,oBAAI,IAAI,CAAC;AACzB,kBAAc,IAAI,KAAK,SAAS,IAAI;AACpC,WAAO,OAAO,KAAK,OAAO;AAC1B,SAAK,MAAM,KAAK,KAAK,OAAO,KAAK,KAAK,MAAM;AAC5C,UAAM,SAAS,KAAK;AAGpB,QAAI,OAAO,WAAY,QAAO,WAAW,KAAK,SAAS,IAAI;AAAA,QACtD,QAAO,OAAO,KAAK,OAAO;AAC/B,SAAK,QAAQ,MAAM,OAAO;AAC1B,SAAK,QAAQ,MAAM,MAAM;AACzB,gBAAY,IAAI;AAChB,SAAK,OAAO;AACZ,SAAK,QAAQ;AACb,SAAK,QAAQ;AACb,SAAK,OAAO;AACZ,UAAM,IAAI,IAAI,EAAG,IAAI,IAAI;AAEzB,QAAI,MAAM,IAAI,QAAQ,KAAK,CAAC,SAAS,QAAQ,GAAG;AAC9C,YAAM,QAAQ;AACd,eAAS,YAAY,OAAO,WAAW;AAAA,IACzC;AACA,QAAI,QAAS,UAAS;AAAA,EACxB;AAEA,QAAM,SAAS,CAAC,SAAe;AAC7B,UAAM,OAAO,UAAU,KAAK,SAAS,KAAK,IAAI;AAC9C,SAAK,OAAO,KAAK;AACjB,SAAK,QAAQ,KAAK;AAClB,SAAK,QAAQ,KAAK;AAClB,SAAK,OAAO;AACZ,SAAK,QAAQ;AACb,SAAK,OAAO;AACZ,SAAK,QAAQ;AACb,UAAM,IAAI,KAAK,IAAI,EAAG,IAAI,IAAI;AAAA,EAChC;AAEA,SAAO;AAAA,IACL,MAAM;AAAA,IACN;AAAA,IACA,QAAQ,SAAS,MAAM;AACrB,aAAO,OAAO,QAAQ,OAAO;AAAA,QAC3B,WAAW;AAAA,QACX,SAAS;AAAA,QACT,UAAU;AAAA,QACV,eAAe;AAAA,MACjB,CAAC;AACD,YAAM,OAAO;AAAA,QACX;AAAA,QACA;AAAA,QACA,WAAW;AAAA,QACX,OAAO;AAAA,QACP,YAAY;AAAA,QACZ,SAAS;AAAA,QACT,OAAO;AAAA,QACP,YAAY;AAAA,QACZ,aAAa;AAAA,QACb,OAAO,CAAC;AAAA,QACR,SAAS;AAAA,QACT,aAAa;AAAA,QACb,cAAc;AAAA,QACd,eAAe;AAAA,QACf,oBAAoB;AAAA,QACpB,WAAW;AAAA,QACX,aAAa;AAAA,QACb,YAAY;AAAA,QACZ,MAAM;AAAA,QACN,UAAU;AAAA,MACZ;AACA,aAAO,IAAI;AACX,YAAM,IAAI,SAAS,IAAI;AACvB,eAAS;AAAA,IACX;AAAA,IACA,WAAW,SAAS,MAAM;AACxB,YAAM,OAAO,MAAM,IAAI,OAAO;AAC9B,UAAI,CAAC,KAAM;AACX,YAAM,UAAU,KAAK,KAAK,UAAU,KAAK,SAAS,KAAK,KAAK,WAAW,KAAK;AAC5E,WAAK,OAAO;AACZ,gBAAU,MAAM;AAChB,UAAI,SAAS;AACX,YAAI,SAAS,KAAM,SAAQ,IAAI;AAC/B,oBAAY,IAAI;AAChB,eAAO,IAAI;AAAA,MACb;AACA,eAAS;AAAA,IACX;AAAA,IACA,WAAW,SAAS;AAClB,YAAM,OAAO,MAAM,IAAI,OAAO;AAC9B,UAAI,CAAC,KAAM;AACX,UAAI,SAAS,KAAM,SAAQ,IAAI;AAC/B,UAAI,cAAc,KAAM,aAAY;AACpC,UAAI,YAAY,KAAM,WAAU;AAChC,oBAAc,OAAO,IAAI;AACzB,cAAQ,OAAO,OAAO;AACtB,gBAAU,OAAO,OAAO;AACxB,YAAM,OAAO,OAAO;AACpB,kBAAY,IAAI;AAChB,cAAQ,OAAO;AACf,eAAS;AAAA,IACX;AAAA,IACA,aAAa,CAAC,YAAY;AACxB,YAAM,OAAO,MAAM,IAAI,OAAO;AAC9B,aAAO,OAAO,EAAE,GAAG,KAAK,KAAK,IAAI;AAAA,IACnC;AAAA,IACA,WAAW,MAAM;AACf,YAAM,OAAsB,CAAC;AAC7B,iBAAW,QAAQ,MAAM,OAAO,EAAG,KAAI,WAAW,KAAK,MAAM,IAAI,EAAG,MAAK,KAAK,KAAK,OAAO;AAC1F,aAAO;AAAA,IACT;AAAA,IACA,WAAW,CAAC,YAAY,cAAc,OAAO,OAAO;AAAA,IACpD,eAAe,SAAS;AACtB,YAAM,OAAO,SAAS,OAAO;AAC7B,aAAO,OAAO,EAAE,GAAG,KAAK,IAAI;AAAA,IAC9B;AAAA,IACA,aAAa,OAAO;AAElB,UAAI,MAAmB;AACvB,iBAAW,QAAQ,MAAM,OAAO,EAAG,KAAI,cAAc,KAAK,MAAM,KAAK,EAAG,OAAM;AAC9E,aAAO,MAAM,cAAc,IAAI,SAAS,IAAI,MAAM,KAAK,IAAI;AAAA,IAC7D;AAAA,IACA,aAAa,UAAU;AACrB,kBAAY,IAAI,IAAI,QAAQ;AAC5B,gBAAU,MAAM;AAChB,eAAS;AAAA,IACX;AAAA,IACA,SAAS,SAAS;AAChB,UAAI,YAAY,QAAS;AACzB,gBAAU;AACV,gBAAU,MAAM;AAChB,eAAS;AAAA,IACX;AAAA,IACA,UAAU,SAAS,QAAQ,QAAQ;AACjC,UAAI,CAAC,MAAM,IAAI,OAAO,EAAG;AACzB,UAAI,QAAQ;AACV,cAAM,SAAS,aAAa,QAAQ,MAAM;AAC1C,gBAAQ,IAAI,SAAS,EAAE,QAAQ,QAAQ,QAAQ,KAAK,UAAU,QAAQ,MAAM,EAAE,CAAC;AAAA,MACjF,MAAO,SAAQ,OAAO,OAAO;AAC7B,eAAS;AAAA,IACX;AAAA,IACA,eAAe,CAAC,UAAU,cAAc,QAAQ,KAAK;AAAA,IACrD,eAAe,CAAC,UAAU,cAAc,QAAQ,KAAK;AAAA,IACrD,WAAW,MAAM;AAAA,IACjB;AAAA,IACA,YAAY;AAAA,IACZ,cAAc,OAAO;AACnB,OAAC,SAAS,YAAY,SAAS,WAAW,IAAI,UAAU,KAAK;AAC7D,eAAS;AAAA,IACX;AAAA,IACA,IAAI,SAAS;AACX,YAAM,SAAS,SAAS,CAAC,GAAG,MAAM,OAAO,CAAC,EAAE,IAAI,CAAC,SAAS,KAAK,IAAI,CAAC;AACpE,UAAI,OAAQ,WAAU,UAAU,QAAQ,OAAO,aAAa,OAAO,cAAc,OAAO,CAAC;AAAA,IAC3F;AAAA,IACA,UAAU,OAAO;AAAA,MACf,MAAM;AAAA,MACN,OAAO,MAAM;AAAA,MACb,SAAS,MAAM;AAAA,MACf,SAAS,MAAM;AAAA,MACf,qBAAqB,MAAM;AAAA,MAC3B,sBAAsB,MAAM;AAAA,MAC5B,UAAU,MAAM;AAAA,MAChB,OAAO,MAAM;AAAA,MACb,eAAe,CAAC,GAAG,MAAM,KAAK,CAAC,EAAE,OAAO,CAAC,SAAS,KAAK,QAAQ,EAAE;AAAA,MACjE,iBAAiB,MAAM;AAAA,MACvB,SAAS,MAAM;AAAA,MACf,QAAQ,MAAM;AAAA,MACd,YAAY,MAAM;AAAA,MAClB,YAAY,MAAM;AAAA,MAClB,eAAe,MAAM;AAAA,MACrB,aAAa,MAAM;AAAA,MACnB,OAAO,MAAM;AAAA,IACf;AAAA,IACA,UAAU;AACR,kBAAY;AACZ,2BAAqB,KAAK;AAC1B,mBAAa,WAAW;AACxB,mBAAa,WAAW;AACxB,mBAAa,YAAY;AACzB,gBAAU,WAAW;AACrB,eAAS,MAAM,oBAAoB,eAAe,aAAa;AAC/D,aAAO,oBAAoB,QAAQ,gBAAgB,IAAI;AACvD,cAAQ,oBAAoB,eAAe,aAAa;AACxD,cAAQ,oBAAoB,gBAAgB,cAAc;AAC1D,cAAQ,oBAAoB,eAAe,eAAe,IAAI;AAC9D,aAAO,oBAAoB,WAAW,SAAS;AAC/C,aAAO,oBAAoB,YAAY,UAAU;AACjD,aAAO,oBAAoB,iBAAiB,eAAe;AAC3D,iBAAW,QAAQ,WAAY,QAAO,oBAAoB,MAAM,OAAO,IAAI;AAC3E,kBAAY;AACZ,qBAAe,WAAW;AAC1B,aAAO,UAAU;AACjB,cAAQ,OAAO;AACf,eAAS,QAAQ;AACjB,YAAM,QAAQ;AACd,aAAO,QAAQ;AAAA,IACjB;AAAA,EACF;AACF;;;ACr9CO,IAAM,YAAY,CAAC,GAA6B,MACrD,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,CAAC,MAAM,EAAE,CAAC;AAErB,IAAM,UAAU,CAAC,OAAc,SACpC,KAAK,KAAK,CAAC,UAAU,UAAU,OAAO,KAAK,CAAC;AAGvC,SAAS,UAAU,QAAmB,OAA2B;AACtE,MAAI,QAAqB;AACzB,aAAW,WAAW,OAAO;AAC3B,UAAM,OAAO,OAAO,eAAe,OAAO;AAC1C,QAAI,KAAM,SAAQ,QAAQ,UAAU,OAAO,IAAI,IAAI;AAAA,EACrD;AACA,SAAO;AACT;AAEO,SAAS,UAAU,GAAS,GAAe;AAChD,QAAM,IAAI,KAAK,IAAI,EAAE,GAAG,EAAE,CAAC;AAC3B,QAAM,IAAI,KAAK,IAAI,EAAE,GAAG,EAAE,CAAC;AAC3B,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,OAAO,KAAK,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,IAAI;AAAA,IAChD,QAAQ,KAAK,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,IAAI;AAAA,EACrD;AACF;AAEA,IAAM,WAAW,CAAC,GAAgB,MAChC,CAAC,CAAC,KACF,CAAC,CAAC,KACF,KAAK,IAAI,EAAE,IAAI,EAAE,CAAC,IAAI,OACtB,KAAK,IAAI,EAAE,IAAI,EAAE,CAAC,IAAI,OACtB,KAAK,IAAI,EAAE,QAAQ,EAAE,KAAK,IAAI,OAC9B,KAAK,IAAI,EAAE,SAAS,EAAE,MAAM,IAAI;AAG3B,SAAS,aAAa,QAAmB,MAAkB;AAEhE,QAAM,UAAU,CAAC,YAA8B;AAC7C,UAAM,OAAO,OAAO,UAAU,OAAO;AACrC,QAAI,CAAC,KAAM,QAAO,CAAC;AACnB,QAAI;AACJ,QAAI,SAAS,OAAQ,SAAQ,CAAC;AAAA,aACrB,SAAS,WAAW;AAC3B,cAAQ,CAAC;AACT,eAAS,KAAqB,SAAS,MAAM,OAAO,MAAM,KAAK,GAAG,eAAe;AAC/E,cAAM,QAAQ,CAAC,EAAE,CAAC;AAAA,MACpB;AAAA,IACF,OAAO;AACL,cAAQ,KAAK,SAAS,MAAM,EACzB,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,KAAK,CAAC,EAC7B,OAAO,CAAC,UAAU,MAAM,SAAS,KAAK,MAAM,CAAC,MAAM,IAAI;AAAA,IAC5D;AAEA,UAAM,QAAiB,CAAC,CAAC,IAAI,CAAC;AAC9B,QAAI,WAAW,OAAO,YAAY,IAAI;AACtC,eAAW,SAAS,OAAO;AACzB,YAAM,OAAO,UAAU,QAAQ,KAAK;AACpC,UAAI,SAAS,MAAM,QAAQ,EAAG;AAC9B,YAAM,KAAK,KAAK;AAChB,iBAAW;AAAA,IACb;AACA,WAAO;AAAA,EACT;AAEA,QAAM,UAAU,CAAC,UAA0B;AACzC,UAAM,UAAU,OAAO,aAAa,KAAK;AACzC,WAAO,UAAU,QAAQ,OAAO,IAAI,CAAC;AAAA,EACvC;AAGA,QAAM,aAAa,CAAC,WAA2B;AAC7C,QAAI,SAAS,OAAQ,QAAO,CAAC;AAC7B,UAAM,WAAoB,CAAC;AAC3B,QAAI,SAAS,WAAW;AAEtB,YAAM,QAAQ,CAAC,SAAkB,UAAuB;AACtD,mBAAW,SAAS,QAAQ,UAAU;AACpC,gBAAM,OAAO,OAAO,eAAe,KAAK;AACxC,cAAI,CAAC,QAAQ,KAAK,SAAS,KAAK,KAAK,UAAU,EAAG;AAClD,cAAI,SAAS,MAAM,KAAK,EAAG,OAAM,OAAO,KAAK;AAAA,cACxC,UAAS,KAAK,CAAC,KAAK,CAAC;AAAA,QAC5B;AAAA,MACF;AACA,iBAAW,QAAQ,OAAQ,OAAM,MAAM,UAAU,QAAQ,MAAM,CAAC;AAChE,aAAO;AAAA,IACT;AAGA,eAAW,QAAQ,QAAQ;AACzB,iBAAW,WAAW,KAAK,iBAAiB,GAAG,GAAG;AAChD,YAAI,SAAS,KAAK,CAACC,WAAUA,OAAM,KAAK,CAAC,SAAS,KAAK,SAAS,OAAO,CAAC,CAAC,EAAG;AAC5E,cAAM,QAAQ,QAAQ,OAAO;AAC7B,cAAM,QAAQ,MAAM,UAAU,CAAC,UAAU,UAAU,OAAO,MAAM,CAAC;AACjE,cAAM,QAAQ,SAAS,IAAI,MAAM,QAAQ,CAAC,IAAI;AAC9C,YAAI,SAAS,CAAC,QAAQ,OAAO,QAAQ,EAAG,UAAS,KAAK,KAAK;AAAA,MAC7D;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAGA,QAAM,WAAW,CAAC,OAAqB,SACrC,QACI,WAAW,KAAK,EAAE,OAAO,CAAC,UAAU;AAClC,UAAM,MAAM,UAAU,QAAQ,KAAK;AACnC,WAAO,CAAC,CAAC,OAAO,WAAW,KAAK,IAAI;AAAA,EACtC,CAAC,IACD,OAAO,WAAW,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;AAElD,SAAO,EAAE,SAAS,SAAS,YAAY,SAAS;AAClD;;;AC5HO,IAAM,UAAU,CAAC,MAAM,KAAK,MAAM,KAAK,MAAM,KAAK,MAAM,GAAG;AAGlE,IAAM,YAAY;AAClB,IAAM,UAAkC;AAAA,EACtC,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,GAAG;AAAA,EACH,GAAG;AAAA,EACH,GAAG;AAAA,EACH,GAAG;AACL;AAaA,IAAM,OAAO,CAAC,WAAmB;AAAA,EAC/B,UAAU;AAAA,EACV,MAAM;AAAA,EACN,SAAS;AAAA,EACT,cAAc;AAAA,EACd,OAAO;AAAA,EACP,YAAY;AAAA,EACZ,YAAY;AAAA,EACZ,eAAe;AACjB;AAMO,SAAS,cAAc,SAAsB,OAAe,YAAoB;AACrF,QAAM,OAAO,SAAS,cAAc,KAAK;AACzC,SAAO,OAAO,KAAK,OAAO;AAAA,IACxB,UAAU;AAAA,IACV,OAAO;AAAA,IACP,UAAU;AAAA,IACV,eAAe;AAAA,IACf,QAAQ;AAAA,EACV,CAAC;AACD,QAAM,OAAO,CAAC,UAAkC;AAC9C,UAAM,UAAU,SAAS,cAAc,KAAK;AAC5C,WAAO,OAAO,QAAQ,OAAO,EAAE,MAAM,KAAK,KAAK,IAAI,GAAG,OAAO,EAAE,SAAS,OAAO,CAAC;AAChF,SAAK,OAAO,OAAO;AACnB,WAAO;AAAA,EACT;AACA,QAAM,YAAY,KAAK,KAAK,UAAU,CAAC;AACvC,QAAM,OAAO,KAAK,KAAK,KAAK,CAAC;AAC7B,QAAM,OAAO,KAAK,KAAK,KAAK,CAAC;AAC7B,QAAM,SAAS,KAAK,EAAE,UAAU,YAAY,QAAQ,aAAa,KAAK,GAAG,CAAC;AAC1E,QAAM,UAAU,QAAQ,IAAI,CAAC,WAAW;AACtC,UAAM,UAAU,KAAK;AAAA,MACnB,UAAU;AAAA,MACV,OAAO,GAAG,SAAS;AAAA,MACnB,QAAQ,GAAG,SAAS;AAAA,MACpB,WAAW;AAAA,MACX,YAAY;AAAA,MACZ,QAAQ,aAAa,KAAK;AAAA,MAC1B,eAAe;AAAA,MACf,QAAQ,QAAQ,MAAM;AAAA,IACxB,CAAC;AACD,YAAQ,QAAQ,kBAAkB;AAClC,WAAO;AAAA,EACT,CAAC;AACD,QAAM,SAAwB,CAAC;AAC/B,UAAQ,OAAO,IAAI;AAEnB,QAAM,OAAO,CAAC,SAAsB,YAAqB;AACvD,YAAQ,MAAM,UAAU,UAAU,UAAU;AAAA,EAC9C;AACA,QAAM,QAAQ,CAAC,SAAsB,GAAW,MAAc;AAC5D,YAAQ,MAAM,YAAY,aAAa,KAAK,MAAM,CAAC,CAAC,OAAO,KAAK,MAAM,CAAC,CAAC;AAAA,EAC1E;AACA,QAAM,OAAO,CAAC,SAAsB,UAAkB;AACpD,QAAI,QAAQ,gBAAgB,MAAO,SAAQ,cAAc;AAAA,EAC3D;AAEA,SAAO;AAAA,IACL,OAAO,OAAqB;AAC1B,YAAM,EAAE,OAAO,UAAU,IAAI;AAC7B,WAAK,WAAW,CAAC,CAAC,OAAO,IAAI;AAC7B,UAAI,OAAO,MAAM;AACf,aAAK,WAAW,MAAM,IAAI;AAC1B,cAAM,WAAW,MAAM,KAAK,IAAI,GAAG,MAAM,KAAK,IAAI,EAAE;AAAA,MACtD;AACA,WAAK,MAAM,CAAC,CAAC,WAAW,IAAI;AAC5B,WAAK,MAAM,CAAC,CAAC,SAAS;AACtB,WAAK,QAAQ,CAAC,CAAC,aAAa,MAAM,MAAM;AACxC,iBAAW,UAAU,QAAS,MAAK,QAAQ,CAAC,CAAC,aAAa,MAAM,OAAO;AACvE,UAAI,WAAW;AACb,cAAM,EAAE,KAAK,IAAI;AACjB,YAAI,UAAU,MAAM;AAClB,eAAK,MAAM,UAAU,IAAI;AACzB,gBAAM,MAAM,KAAK,IAAI,GAAG,KAAK,IAAI,EAAE;AAAA,QACrC;AACA,cAAM,EAAE,OAAO,OAAO,IAAI,UAAU;AACpC,cAAM,QAAQ,GAAG,KAAK,MAAM,KAAK,CAAC,SAAM,KAAK,MAAM,MAAM,CAAC;AAC1D,aAAK,MAAM,UAAU,QAAQ,IAAI,GAAG,UAAU,KAAK,gBAAa,KAAK,KAAK,KAAK;AAE/E,cAAM,MAAM,KAAK,IAAI,KAAK,QAAQ,IAAI,KAAK,cAAc,GAAG,KAAK,IAAI,KAAK,SAAS,CAAC;AACpF,YAAI,MAAM,QAAQ;AAChB,gBAAM,QAAQ,KAAK,GAAG,KAAK,CAAC;AAC5B,iBAAO,MAAM,QAAQ,GAAG,KAAK,KAAK;AAClC,iBAAO,MAAM,SAAS,GAAG,KAAK,MAAM;AAAA,QACtC;AACA,YAAI,MAAM,SAAS;AACjB,kBAAQ,QAAQ,CAAC,QAAQ,MAAM;AAC7B,kBAAM,KAAK,OAAO,SAAS,GAAG,IAAI,IAAI,OAAO,SAAS,GAAG,IAAI,IAAI;AACjE,kBAAM,KAAK,OAAO,SAAS,GAAG,IAAI,IAAI,OAAO,SAAS,GAAG,IAAI,IAAI;AACjE;AAAA,cACE,QAAQ,CAAC;AAAA,cACT,KAAK,IAAI,KAAK,QAAQ,KAAK,YAAY;AAAA,cACvC,KAAK,IAAI,KAAK,SAAS,KAAK,YAAY;AAAA,YAC1C;AAAA,UACF,CAAC;AAAA,QACH;AAAA,MACF;AAEA,aAAO,OAAO,SAAS,MAAM,OAAO,QAAQ;AAC1C,eAAO,KAAK,KAAK,EAAE,UAAU,YAAY,YAAY,UAAU,CAAC,CAAC;AAAA,MACnE;AACA,aAAO,QAAQ,CAAC,MAAM,MAAM;AAC1B,cAAM,QAAQ,MAAM,OAAO,CAAC;AAC5B,aAAK,MAAM,CAAC,CAAC,KAAK;AAClB,YAAI,CAAC,MAAO;AACZ,cAAM,MAAM,MAAM,GAAG,MAAM,CAAC;AAC5B,aAAK,MAAM,QAAQ,GAAG,KAAK,IAAI,GAAG,MAAM,KAAK,CAAC;AAC9C,aAAK,MAAM,SAAS,GAAG,KAAK,IAAI,GAAG,MAAM,MAAM,CAAC;AAAA,MAClD,CAAC;AAAA,IACH;AAAA,IACA,SAAS;AACP,WAAK,OAAO;AAAA,IACd;AAAA,EACF;AACF;AAGO,IAAM,YAAY,CACvB,OACA,aACS;AACT,QAAM,IAAI,SAAS,MAAM,IAAI,MAAM,EAAE;AACrC,QAAM,IAAI,SAAS,MAAM,IAAI,MAAM,EAAE;AACrC,SAAO;AAAA,IACL,GAAG,KAAK,IAAI,EAAE,GAAG,EAAE,CAAC;AAAA,IACpB,GAAG,KAAK,IAAI,EAAE,GAAG,EAAE,CAAC;AAAA,IACpB,OAAO,KAAK,IAAI,EAAE,IAAI,EAAE,CAAC;AAAA,IACzB,QAAQ,KAAK,IAAI,EAAE,IAAI,EAAE,CAAC;AAAA,EAC5B;AACF;;;ACxJO,IAAM,cAAc,CAAC,GAAG,KAAK,CAAC;AAErC,IAAM,WAAW,CAAC,SAAe,YAAY,IAAI,CAAC,MAAM,KAAK,IAAI,KAAK,QAAQ,CAAC;AAC/E,IAAM,WAAW,CAAC,SAAe,YAAY,IAAI,CAAC,MAAM,KAAK,IAAI,KAAK,SAAS,CAAC;AAGhF,SAAS,QAAQ,QAAkB,OAAiB,WAA2B;AAC7E,MAAI,OAAO;AACX,aAAW,QAAQ,QAAQ;AACzB,eAAW,MAAM,OAAO;AACtB,YAAM,QAAQ,KAAK;AACnB,UAAI,KAAK,IAAI,KAAK,KAAK,aAAa,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,IAAI,EAAG,QAAO;AAAA,IAC/E;AAAA,EACF;AACA,SAAO,SAAS,WAAW,IAAI;AACjC;AAMO,SAAS,SACd,MACA,SACA,WACA,QAAsC,EAAE,GAAG,aAAa,GAAG,YAAY,GAC1B;AAC7C,QAAM,KAAK,QAAQ,QAAQ,QAAQ;AACnC,QAAM,KAAK,QAAQ,QAAQ,QAAQ;AACnC,QAAM,KAAK;AAAA,IACT,MAAM,EAAE,IAAI,CAAC,MAAM,KAAK,IAAI,KAAK,QAAQ,CAAC;AAAA,IAC1C;AAAA,IACA;AAAA,EACF;AACA,QAAM,KAAK;AAAA,IACT,MAAM,EAAE,IAAI,CAAC,MAAM,KAAK,IAAI,KAAK,SAAS,CAAC;AAAA,IAC3C;AAAA,IACA;AAAA,EACF;AACA,QAAM,QAAQ,EAAE,GAAG,MAAM,GAAG,KAAK,IAAI,IAAI,GAAG,KAAK,IAAI,GAAG;AACxD,SAAO,EAAE,IAAI,IAAI,QAAQ,UAAU,OAAO,SAAS,KAAK,EAAE;AAC5D;AAGA,SAAS,UAAU,MAAY,SAA0B,OAAqC;AAC5F,QAAM,SAAkB,CAAC;AACzB,QAAM,QAAQ,CAAC,GAAW,MAAc,KAAK,IAAI,IAAI,CAAC,IAAI;AAC1D,aAAW,KAAK,MAAM,GAAG;AACvB,UAAM,IAAI,KAAK,IAAI,KAAK,QAAQ;AAChC,UAAM,OAAO,QAAQ,OAAO,CAAC,WAAW,SAAS,MAAM,EAAE,KAAK,CAAC,OAAO,MAAM,IAAI,CAAC,CAAC,CAAC;AACnF,QAAI,CAAC,KAAK,OAAQ;AAClB,UAAM,MAAM,KAAK,IAAI,KAAK,GAAG,GAAG,KAAK,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;AACpD,UAAMC,UAAS,KAAK,IAAI,KAAK,IAAI,KAAK,QAAQ,GAAG,KAAK,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC;AAChF,WAAO,KAAK,EAAE,IAAI,GAAG,IAAI,KAAK,IAAI,GAAG,IAAIA,QAAO,CAAC;AAAA,EACnD;AACA,aAAW,KAAK,MAAM,GAAG;AACvB,UAAM,IAAI,KAAK,IAAI,KAAK,SAAS;AACjC,UAAM,OAAO,QAAQ,OAAO,CAAC,WAAW,SAAS,MAAM,EAAE,KAAK,CAAC,OAAO,MAAM,IAAI,CAAC,CAAC,CAAC;AACnF,QAAI,CAAC,KAAK,OAAQ;AAClB,UAAM,OAAO,KAAK,IAAI,KAAK,GAAG,GAAG,KAAK,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;AACrD,UAAMC,SAAQ,KAAK,IAAI,KAAK,IAAI,KAAK,OAAO,GAAG,KAAK,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,KAAK,CAAC;AAC7E,WAAO,KAAK,EAAE,IAAI,MAAM,IAAI,GAAG,IAAIA,QAAO,IAAI,EAAE,CAAC;AAAA,EACnD;AACA,SAAO;AACT;;;ACDO,SAAS,cACd,QACA,QAAQ,yBACR,SAAqC,CAAC,UAAU,OAAO,WAAW,KAAK,GACvE;AACA,QAAM,MAAM,SAAS,cAAc,KAAK;AACxC,SAAO,OAAO,IAAI,OAAO;AAAA,IACvB,UAAU;AAAA,IACV,SAAS;AAAA,IACT,eAAe;AAAA,IACf,QAAQ,aAAa,KAAK;AAAA,IAC1B,YAAY,sBAAsB,KAAK;AAAA,IACvC,QAAQ;AAAA,EACV,CAAC;AACD,SAAO,QAAQ,OAAO,GAAG;AACzB,SAAO;AAAA;AAAA,IAEL,OAAO,GAAU,GAAqB;AACpC,YAAM,IAAI,KAAK,IAAI,EAAE,GAAG,EAAE,CAAC;AAC3B,YAAM,IAAI,KAAK,IAAI,EAAE,GAAG,EAAE,CAAC;AAC3B,YAAM,QAAQ,KAAK,IAAI,EAAE,IAAI,EAAE,CAAC;AAChC,YAAM,SAAS,KAAK,IAAI,EAAE,IAAI,EAAE,CAAC;AACjC,aAAO,OAAO,IAAI,OAAO;AAAA,QACvB,SAAS;AAAA,QACT,MAAM,GAAG,CAAC;AAAA,QACV,KAAK,GAAG,CAAC;AAAA,QACT,OAAO,GAAG,KAAK;AAAA,QACf,QAAQ,GAAG,MAAM;AAAA,MACnB,CAAC;AACD,YAAM,SAAS,OAAO,UAAU;AAChC,YAAM,OAAO,OAAO;AAAA,QAClB,GAAG,cAAc,QAAQ,EAAE,GAAG,EAAE,CAAC;AAAA,QACjC,OAAO,QAAQ,OAAO;AAAA,QACtB,QAAQ,SAAS,OAAO;AAAA,MAC1B,CAAC;AACD,aAAO,aAAa,IAAI;AACxB,aAAO;AAAA,IACT;AAAA,IACA,OAAO;AACL,UAAI,MAAM,UAAU;AAAA,IACtB;AAAA,IACA,SAAS;AACP,UAAI,OAAO;AAAA,IACb;AAAA,EACF;AACF;AAGA,IAAM,aAAa;AAEnB,IAAM,UAAU;AAEhB,IAAM,YAAY;AAElB,IAAM,aAAa,CAAC,YAClB,CAAC,CAAC,YACD,mBAAmB,oBAClB,mBAAmB,uBACnB,mBAAmB,qBAClB,QAAwB;AA6BtB,SAAS,WAAW,QAAmB,UAAyB,CAAC,GAAW;AACjF,QAAM;AAAA,IACJ,OAAO;AAAA,IACP,UAAU;AAAA,IACV,QAAQ;AAAA,IACR,UAAU;AAAA,IACV,SAAS;AAAA,IACT,OAAO;AAAA,IACP,QAAQ;AAAA,IACR;AAAA,IACA;AAAA,EACF,IAAI;AACJ,QAAM,QACJ,QAAQ,UACP,CAAC,UAAkB,OAAO,UAAU,MAAM,CAAC,CAAC,MAAM,MAAM,CAAC,IAAI,OAAO,MAAM,CAAC,EAAE;AAChF,QAAM,EAAE,QAAQ,IAAI;AACpB,QAAM,SAAS,aAAa,QAAQ,IAAI;AACxC,QAAM,aAAa,CAAC,CAAC,eAAe,YAAY;AAChD,QAAM,UAAU,cAAc,SAAS,OAAO,KAAK;AACnD,MAAI,gBAAyB,CAAC;AAC9B,QAAM,MAAM,UACR,cAAc,QAAQ,OAAO,CAAC,UAAU;AACtC,oBAAgB,OAAO,SAAS,OAAO,GAAG,EAAE,KAAK,MAAM,KAAK;AAC5D,WAAO,cAAc,KAAK;AAAA,EAC5B,CAAC,IACD;AAEJ,MAAI,YAAqB,CAAC;AAE1B,MAAI,SAAkB,CAAC;AACvB,MAAI,UAAwB;AAC5B,MAAI,UAA0B;AAC9B,MAAI,UAAwB;AAC5B,MAAI,QAAQ;AACZ,MAAI,eAAe;AAEnB,QAAM,SAAS,CAAC,MAAe,aAAsB,WAAW;AAC9D,gBAAY,KAAK,OAAO,CAAC,OAAO,MAAM,KAAK,UAAU,CAAC,UAAU,UAAU,OAAO,KAAK,CAAC,MAAM,CAAC;AAC9F,aAAS,UAAU,SAAS,aAAa,CAAC;AAC1C,WAAO,aAAa,UAAU,KAAK,CAAC;AACpC,eAAW,SAAS;AACpB,SAAK;AAAA,EACP;AACA,QAAM,aAAa,CAAC,UAAwB;AAC1C,QAAI,UAAU,OAAO,OAAO,KAAK,UAAU,QAAS;AACpD,cAAU;AACV,WAAO,SAAS,QAAQ,CAAC,KAAK,IAAI;AAClC,SAAK;AAAA,EACP;AACA,QAAM,KAAK,CAAC,UAA6B;AACvC,UAAM,SAAS,QAAQ,sBAAsB;AAC7C,WAAO,EAAE,GAAG,MAAM,UAAU,OAAO,MAAM,GAAG,MAAM,UAAU,OAAO,IAAI;AAAA,EACzE;AACA,QAAM,UAAU,CAAC,UAAiB,OAAO,QAAQ,OAAO,cAAc,KAAK,CAAC;AAE5E,QAAM,WAAW,CAAC,UAAkC;AAClD,QAAI,CAAC,MAAM,OAAQ,QAAO;AAC1B,aAAS,IAAI,OAAO,SAAS,GAAG,KAAK,GAAG,KAAK;AAC3C,YAAM,IAAI,MAAM,UAAU,CAAC,UAAU,UAAU,OAAO,OAAO,CAAC,CAAC,CAAC;AAChE,UAAI,IAAI,EAAG;AACX,aAAO,IAAI,IAAI,MAAM,SACjB,EAAE,OAAO,MAAM,IAAI,CAAC,GAAG,QAAQ,MAAM,MAAM,GAAG,IAAI,CAAC,EAAE,IACrD,EAAE,OAAO,MAAM,CAAC,GAAG,QAAQ,MAAM,MAAM,GAAG,CAAC,EAAE;AAAA,IACnD;AACA,WAAO,EAAE,OAAO,MAAM,CAAC,GAAG,QAAQ,CAAC,EAAE;AAAA,EACvC;AACA,QAAM,YAAY,CAAC,cAAuB,YAAY,WAAW;AACjE,QAAM,cAAc,MAAM;AACxB,UAAM,OAAO,SAAS,WAAW,CAAC,WAAW,UAAU,KAAK;AAC5D,eAAW,OAAQ,SAAS,QAAQ,OAAQ,CAAC,GAAG,SAAS,OAAQ,IAAI;AAAA,EACvE;AAIA,MAAI,QAAQ;AAEZ,QAAM,OAAO,MAAM;AACjB,QAAI,CAAC,MAAO,SAAQ,sBAAsB,MAAM;AAAA,EAClD;AACA,QAAM,WAAW,CAAC,SAAqB;AACrC,UAAM,EAAE,GAAG,EAAE,IAAI,OAAO,cAAc,IAAI;AAC1C,UAAM,OAAO,OAAO,UAAU,EAAE;AAChC,WAAO,EAAE,GAAG,GAAG,OAAO,KAAK,QAAQ,MAAM,QAAQ,KAAK,SAAS,KAAK;AAAA,EACtE;AACA,QAAM,UAAU,CAAC,UACf,MAAM;AAAA,IACJ,CAAC,OAAO,SAAU,CAAC,OAAO,QAAQ,QAAQ,UAAU,OAAO,IAAI,IAAI;AAAA,IACnE;AAAA,EACF;AACF,QAAM,SAAS,MAAM;AACnB,YAAQ;AACR,UAAM,eAAe,SAAS,SAAS,UAAU,SAAS,SAAS,WAAW,UAAU;AACxF,UAAM,QAAQ,eACV,QAAQ,aAAa,EAAE,IACvB,UAAU,SACR,QAAQ,UAAU,IAAI,CAAC,UAAU,UAAU,QAAQ,KAAK,CAAC,CAAC,IAC1D;AACN,UAAM,YAAY,WAAW,CAAC,QAAQ,SAAS,SAAS,IAAI,UAAU,QAAQ,OAAO,IAAI;AACzF,YAAQ,OAAO;AAAA,MACb,OAAO,UAAU,YAAY,EAAE,MAAM,SAAS,SAAS,GAAG,MAAM,MAAM,OAAQ,EAAE,IAAI;AAAA,MACpF,WACE,UAAU,QACN;AAAA,QACE,MAAM,SAAS,KAAK;AAAA,QACpB,MAAM;AAAA,QACN,MAAM,UAAU,UAAU,YAAY,MAAM,UAAU,CAAC,CAAC,IAAI;AAAA,QAC5D,OAAO,UAAU;AAAA,MACnB,IACA;AAAA,MACN,QAAQ,UAAU,SAAS,KAAK,CAAC,CAAC;AAAA,MAClC,SAAS,cAAc,UAAU,SAAS,KAAK,SAAS,SAAS;AAAA,MACjE,QAAQ,eACJ,aAAa,OAAO;AAAA,QAAI,CAAC,UACvB,UAAU,OAAO,CAAC,GAAG,MAAM,OAAO,cAAc,EAAE,GAAG,EAAE,CAAC,CAAC;AAAA,MAC3D,IACA,CAAC;AAAA,IACP,CAAC;AACD,QAAI,UAAU,UAAU,WAAW,QAAS,MAAK;AAAA,EACnD;AAIA,QAAM,OAAO,CAAC,UAAmC;AAC/C,QAAI,SAAS,SAAS,UAAU,SAAS,SAAS,SAAU;AAC5D,kBAAc;AAAA,MACZ;AAAA,MACA,MAAM,QAAQ;AAAA,MACd,QAAQ,QAAQ;AAAA,MAChB,MAAM,QAAQ;AAAA,MACd,IAAI,UAAU,WAAW,QAAQ,OAAO,QAAQ;AAAA,IAClD,CAAC;AAAA,EACH;AAEA,QAAM,cAAc,CAAC,WAA4B;AAC/C,QAAI,CAAC,KAAM,QAAO,CAAC;AACnB,UAAM,QAAQ,OAAO,GAAG,EAAE;AAC1B,QAAI,CAAC,OAAO;AACV,YAAM,OAAO,iBAAiB,OAAO,UAAU,GAAG,QAAQ,aAAa,QAAQ,YAAY;AAC3F,aAAO,OACJ,WAAW,IAAI,EACf,OAAO,CAAC,SAAS,CAAC,OAAO,KAAK,CAAC,UAAU,MAAM,CAAC,MAAM,IAAI,CAAC,EAC3D,IAAI,CAAC,SAAS,OAAO,YAAY,IAAI,CAAE;AAAA,IAC5C;AACA,UAAM,QAAQ,OACX,WAAW,KAAK,EAChB,OAAO,CAAC,UAAU,CAAC,QAAQ,OAAO,MAAM,CAAC,EACzC,IAAI,CAAC,UAAU,UAAU,QAAQ,KAAK,CAAC;AAC1C,WAAO,CAAC,UAAU,QAAQ,KAAK,GAAG,GAAG,KAAK,EAAE,OAAO,CAAC,SAAuB,CAAC,CAAC,IAAI;AAAA,EACnF;AACA,QAAM,iBAAiB,CAAC,OAAc,WAA0B;AAC9D,UAAM,OAAO,UAAU,IAAI,CAAC,UAAU,UAAU,QAAQ,KAAK,CAAC;AAC9D,QAAI,KAAK,KAAK,CAAC,SAAS,CAAC,IAAI,EAAG;AAChC,UAAM,QAAQ;AACd,cAAU;AAAA,MACR,MAAM,SAAS,WAAW;AAAA,MAC1B;AAAA,MACA;AAAA,MACA,QAAQ;AAAA,MACR,MAAM;AAAA,MACN,QAAQ,QAAQ,KAAK;AAAA,MACrB,IAAI;AAAA,MACJ,SAAS,YAAY,SAAS;AAAA,MAC9B,QAAQ,CAAC;AAAA,IACX;AACA,eAAW,IAAI;AACf,SAAK,OAAO;AAAA,EACd;AACA,QAAM,kBAAkB,CAAC,OAAc,cAAuB;AAC5D,QAAI,SAAS,SAAS,UAAU,SAAS,SAAS,SAAU;AAC5D,UAAM,OAAO,OAAO,UAAU,EAAE;AAChC,QAAI,MAAM,MAAM,IAAI,QAAQ,MAAM,KAAK;AACvC,QAAI,MAAM,MAAM,IAAI,QAAQ,MAAM,KAAK;AACvC,UAAM,EAAE,QAAQ,OAAO,IAAI;AAC3B,UAAM,YAAY,UAAU;AAC5B,QAAI;AACJ,QAAI,CAAC,QAAQ;AAEX,UAAI,UAAW,MAAK,IAAI,EAAE,IAAI,KAAK,IAAI,EAAE,IAAK,KAAK,IAAM,KAAK;AAC9D,aAAO,EAAE,GAAG,QAAQ,GAAG,OAAO,IAAI,IAAI,GAAG,OAAO,IAAI,GAAG;AACvD,YAAM,UAAU,SAAS,MAAM,QAAQ,SAAS,SAAS;AACzD,aAAO,EAAE,GAAG,MAAM,GAAG,KAAK,IAAI,QAAQ,IAAI,GAAG,KAAK,IAAI,QAAQ,GAAG;AACjE,cAAQ,SAAS,QAAQ;AAAA,IAC3B,OAAO;AACL,UAAI,OAAO,OAAO;AAClB,UAAI,MAAM,OAAO;AACjB,UAAIC,SAAQ,OAAO,IAAI,OAAO;AAC9B,UAAIC,UAAS,OAAO,IAAI,OAAO;AAC/B,UAAI,OAAO,SAAS,GAAG,EAAG,QAAO,KAAK,IAAI,OAAO,IAAID,SAAQ,CAAC;AAC9D,UAAI,OAAO,SAAS,GAAG,EAAG,CAAAA,SAAQ,KAAK,IAAIA,SAAQ,IAAI,OAAO,CAAC;AAC/D,UAAI,OAAO,SAAS,GAAG,EAAG,OAAM,KAAK,IAAI,MAAM,IAAIC,UAAS,CAAC;AAC7D,UAAI,OAAO,SAAS,GAAG,EAAG,CAAAA,UAAS,KAAK,IAAIA,UAAS,IAAI,MAAM,CAAC;AAChE,aAAO,EAAE,GAAG,MAAM,GAAG,KAAK,OAAOD,SAAQ,MAAM,QAAQC,UAAS,IAAI;AACpE,YAAM,SAAS,OAAO,WAAW;AACjC,UAAI,aAAa,QAAQ;AAEvB,cAAM,QAAQ,KAAK,IAAI,KAAK,QAAQ,OAAO,OAAO,KAAK,SAAS,OAAO,MAAM;AAC7E,cAAM,QAAQ,OAAO,QAAQ;AAC7B,cAAM,SAAS,OAAO,SAAS;AAC/B,eAAO;AAAA,UACL,GAAG,OAAO,SAAS,GAAG,IAAID,SAAQ,QAAQ;AAAA,UAC1C,GAAG,OAAO,SAAS,GAAG,IAAIC,UAAS,SAAS;AAAA,UAC5C;AAAA,UACA;AAAA,QACF;AACA,gBAAQ,SAAS,CAAC;AAAA,MACpB,OAAO;AACL,cAAM,QAAQ;AAAA,UACZ,GAAG,OAAO,SAAS,GAAG,IAAI,CAAC,CAAC,IAAI,OAAO,SAAS,GAAG,IAAI,CAAC,CAAC,IAAI,CAAC;AAAA,UAC9D,GAAG,OAAO,SAAS,GAAG,IAAI,CAAC,CAAC,IAAI,OAAO,SAAS,GAAG,IAAI,CAAC,CAAC,IAAI,CAAC;AAAA,QAChE;AACA,cAAM,UAAU,SAAS,MAAM,QAAQ,SAAS,WAAW,KAAK;AAChE,YAAI,MAAM,EAAE,CAAC,MAAM;AACjB,iBAAO,EAAE,GAAG,MAAM,GAAG,KAAK,IAAI,QAAQ,IAAI,OAAO,KAAK,QAAQ,QAAQ,GAAG;AAC3E,YAAI,MAAM,EAAE,CAAC,MAAM,EAAG,QAAO,EAAE,GAAG,MAAM,OAAO,KAAK,QAAQ,QAAQ,GAAG;AACvE,YAAI,MAAM,EAAE,CAAC,MAAM;AACjB,iBAAO,EAAE,GAAG,MAAM,GAAG,KAAK,IAAI,QAAQ,IAAI,QAAQ,KAAK,SAAS,QAAQ,GAAG;AAC7E,YAAI,MAAM,EAAE,CAAC,MAAM,EAAG,QAAO,EAAE,GAAG,MAAM,QAAQ,KAAK,SAAS,QAAQ,GAAG;AACzE,gBAAQ,SAAS,QAAQ;AAAA,MAC3B;AAAA,IACF;AAEA,UAAM,KAAK,KAAK,QAAQ,OAAO;AAC/B,UAAM,KAAK,KAAK,SAAS,OAAO;AAChC,YAAQ,KAAK,QAAQ,KAAK,IAAI,CAAC,UAAU;AAAA,MACvC,GAAG,KAAK,KAAK,KAAK,IAAI,OAAO,KAAK;AAAA,MAClC,GAAG,KAAK,KAAK,KAAK,IAAI,OAAO,KAAK;AAAA,MAClC,OAAO,KAAK,QAAQ;AAAA,MACpB,QAAQ,KAAK,SAAS;AAAA,IACxB,EAAE;AACF,SAAK,MAAM;AACX,SAAK;AAAA,EACP;AAIA,QAAM,gBAAgB,CAAC,UAAwB;AAC7C,YAAQ,MAAM;AACd,mBAAe;AACf,QAAI,MAAM,WAAW,EAAG;AACxB,UAAM,QAAQ,GAAG,KAAK;AACtB,UAAM,OAAO,MAAM;AAEjB,YAAM,gBAAgB;AACtB,qBAAe;AACf,cAAQ,kBAAkB,MAAM,SAAS;AAAA,IAC3C;AACA,UAAM,SAAU,MAAM,OAAmB,UAAuB,yBAAyB;AACzF,QAAI,UAAU,YAAY;AACxB,WAAK;AACL,aAAO,eAAe,OAAO,OAAO,QAAQ,eAAyB;AAAA,IACvE;AACA,UAAM,SAAS,SAAS,QAAQ,KAAK,CAAC;AACtC,QAAI,CAAC,QAAQ;AACX,UAAI,MAAM,YAAY,KAAK;AACzB,aAAK;AACL,kBAAU,EAAE,MAAM,WAAW,OAAO,MAAM;AAC1C;AAAA,MACF;AAEA,UAAI,UAAU,OAAQ,QAAO,CAAC,GAAG,CAAC,CAAC;AACnC;AAAA,IACF;AACA,QAAI,CAAC,UAAU,MAAM,QAAQ,EAAG;AAChC,SAAK;AAGL,UAAM,WACJ,YAAY,UAAU,MAAM,WAAW,MAAM,aAAa,MAAM,WAAW,MAAM;AACnF,UAAM,SAAS,CAAC,CAAC,OAAO,UAAU,OAAO,OAAO,OAAO,GAAG,EAAE,CAAC;AAE7D,QAAI,CAAC,YAAY,CAAC,UAAU,CAAC,QAAQ,OAAO,OAAO,SAAS,GAAG;AAC7D,aAAO,CAAC,OAAO,KAAK,GAAG,OAAO,MAAM;AAAA,IACtC;AACA,cAAU,EAAE,MAAM,SAAS,OAAO,OAAO,UAAU,QAAQ,OAAO;AAClE,eAAW,IAAI;AAAA,EACjB;AACA,QAAM,gBAAgB,CAAC,UAAwB;AAC7C,YAAQ,MAAM;AACd,cAAU,GAAG,KAAK;AAClB,QAAI,CAAC,QAAS,QAAO,YAAY;AACjC,QAAI,QAAQ,SAAS,SAAS;AAC5B,UAAI,KAAK,MAAM,QAAQ,IAAI,QAAQ,MAAM,GAAG,QAAQ,IAAI,QAAQ,MAAM,CAAC,KAAK;AAC1E;AAEF,UAAI,QAAQ,UAAW,YAAY,WAAW,KAAM;AAClD,kBAAU,EAAE,MAAM,WAAW,OAAO,QAAQ,MAAM;AAAA,MACpD,WAAW,YAAY,WAAW,WAAY,gBAAe,QAAQ,OAAO,IAAI;AAAA,UAC3E;AAAA,IACP;AACA,QAAI,SAAS,SAAS,WAAW;AAC/B,UAAK,OAAO,QAAQ,OAAO,OAAO;AAClC,kBAAY;AACZ,iBAAW,SAAS;AACpB,WAAK;AAAA,IACP,MAAO,iBAAgB,SAAS,MAAM,QAAQ;AAAA,EAChD;AACA,QAAM,cAAc,MAAM;AACxB,UAAM,OAAO;AACb,cAAU;AACV,QAAI,CAAC,KAAM;AACX,QAAI,KAAK,SAAS,WAAW;AAC3B,UAAK,KAAK;AACV,aAAO,aAAa;AAAA,IACtB,WAAW,KAAK,SAAS,SAAS;AAChC,YAAM,EAAE,OAAO,QAAQ,OAAO,IAAI,KAAK;AACvC,UAAI,CAAC,KAAK,SAAU,QAAO,CAAC,KAAK,GAAG,MAAM;AAAA,eACjC,QAAQ,OAAO,SAAS;AAC/B,eAAO,UAAU,OAAO,CAAC,UAAU,CAAC,UAAU,OAAO,KAAK,CAAC,CAAC;AAAA,UACzD,QAAO,CAAC,GAAG,WAAW,KAAK,GAAG,MAAM;AAAA,IAC3C,OAAO;AACL,gBAAU;AACV,WAAK,KAAK;AACV,gBAAU;AAAA,IACZ;AACA,gBAAY;AACZ,SAAK;AAAA,EACP;AACA,QAAM,gBAAgB,CAAC,UAAsB;AAC3C,QAAI,CAAC,UAAU,MAAM,QAAQ,EAAG;AAChC,UAAM,eAAe;AACrB,UAAM,gBAAgB;AAEtB,UAAM,QAAQ,QAAQ,GAAG,KAAK,CAAC;AAC/B,QAAI,QAAQ;AACZ,UAAM,QAAQ,CAAC,OAAO,MAAM;AAC1B,UAAI,QAAQ,OAAO,SAAS,EAAG,SAAQ;AAAA,IACzC,CAAC;AACD,QAAI,SAAS,KAAK,MAAM,QAAQ,CAAC,EAAG,QAAO,CAAC,MAAM,QAAQ,CAAC,CAAC,GAAG,MAAM,MAAM,GAAG,QAAQ,CAAC,CAAC;AAAA,EAC1F;AACA,QAAM,iBAAiB,MAAM;AAC3B,cAAU;AACV,eAAW,IAAI;AAAA,EACjB;AAEA,QAAM,cAAc,CAAC,UAAsB;AACzC,QAAI,CAAC,aAAc;AACnB,UAAM,eAAe;AACrB,UAAM,gBAAgB;AAAA,EACxB;AACA,QAAM,UAAU,CAAC,UAAsB;AACrC,QAAI,CAAC,aAAc;AACnB,mBAAe;AACf,UAAM,eAAe;AACrB,UAAM,gBAAgB;AAAA,EACxB;AACA,QAAM,KAAK,MAAM;AACf,UAAM,SAAS,OAAO,GAAG,EAAE;AAC3B,QAAI,OAAQ,QAAO,CAAC,MAAM,GAAG,OAAO,MAAM,GAAG,EAAE,CAAC;AAAA,EAClD;AACA,QAAM,QAAQ,CAAC,UAAyB;AACtC,QAAI,MAAM,QAAQ,SAAS;AACzB,cAAQ,MAAM,SAAS;AACvB,aAAO,YAAY;AAAA,IACrB;AACA,QAAI,MAAM,SAAS,aAAa,WAAW,SAAS,aAAa,EAAG;AACpE,QAAI,MAAM,QAAQ,UAAU;AAC1B,UAAI,SAAS,SAAS,UAAU,SAAS,SAAS,UAAU;AAC1D,aAAK,QAAQ;AACb,kBAAU;AAAA,MACZ,WAAW,OAAO,OAAQ,IAAG;AAAA,eACpB,UAAU,OAAQ,QAAO,CAAC,GAAG,CAAC,CAAC;AACxC;AAAA,IACF;AACA,QAAI,CAAC,UAAU,OAAQ;AACvB,QAAI,MAAM,QAAQ,SAAS;AACzB,YAAM,eAAe;AACrB,UAAI,MAAM,SAAU,QAAO,GAAG;AAC9B,YAAM,QAAQ,OAAO,WAAW,UAAU,CAAC,CAAC,EAAE,CAAC;AAC/C,UAAI,MAAO,QAAO,CAAC,KAAK,GAAG,CAAC,GAAG,QAAQ,UAAU,CAAC,CAAC,CAAC;AAAA,IACtD,WAAW,MAAM,QAAQ,OAAO;AAC9B,YAAM,eAAe;AACrB,YAAM,QAAQ,OAAO,GAAG,EAAE;AAC1B,YAAM,WAAW,QACb,OAAO,WAAW,KAAK,IACvB,OAAO,WAAW,EAAE,GAAG,MAAM,GAAG,MAAM,OAAO,KAAK,QAAQ,IAAI,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;AACzF,YAAM,QAAQ,SAAS,UAAU,CAAC,UAAU,UAAU,OAAO,UAAU,CAAC,CAAC,CAAC;AAC1E,YAAM,OAAO,MAAM,WAAW,KAAK;AACnC,YAAM,OAAO,UAAU,QAAQ,OAAO,SAAS,UAAU,SAAS,MAAM;AACxE,UAAI,KAAM,QAAO,CAAC,IAAI,CAAC;AAAA,IACzB;AAAA,EACF;AAEA,UAAQ,iBAAiB,eAAe,eAAe,IAAI;AAC3D,UAAQ,iBAAiB,aAAa,aAAa,IAAI;AACvD,UAAQ,iBAAiB,SAAS,SAAS,IAAI;AAC/C,UAAQ,iBAAiB,YAAY,eAAe,IAAI;AACxD,UAAQ,iBAAiB,eAAe,aAAa;AACrD,UAAQ,iBAAiB,aAAa,WAAW;AACjD,UAAQ,iBAAiB,iBAAiB,WAAW;AACrD,UAAQ,iBAAiB,gBAAgB,cAAc;AACvD,SAAO,iBAAiB,WAAW,KAAK;AACxC,SAAO,iBAAiB,SAAS,KAAK;AACtC,SAAO;AAAA,IACL,KAAK,MAAM;AAAA,IACX,KAAK,CAAC,SACJ;AAAA,MACE,CAAC,GAAG,IAAI,EAAE,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,KAAK,CAAC;AAAA,MACvC,CAAC;AAAA,IACH;AAAA,IACF,OAAO,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC;AAAA,IAC1B,UAAU;AACR,cAAQ,oBAAoB,eAAe,eAAe,IAAI;AAC9D,cAAQ,oBAAoB,aAAa,aAAa,IAAI;AAC1D,cAAQ,oBAAoB,SAAS,SAAS,IAAI;AAClD,cAAQ,oBAAoB,YAAY,eAAe,IAAI;AAC3D,cAAQ,oBAAoB,eAAe,aAAa;AACxD,cAAQ,oBAAoB,aAAa,WAAW;AACpD,cAAQ,oBAAoB,iBAAiB,WAAW;AACxD,cAAQ,oBAAoB,gBAAgB,cAAc;AAC1D,aAAO,oBAAoB,WAAW,KAAK;AAC3C,aAAO,oBAAoB,SAAS,KAAK;AACzC,2BAAqB,KAAK;AAC1B,WAAK,OAAO;AACZ,cAAQ,OAAO;AACf,aAAO,SAAS,IAAI;AACpB,aAAO,aAAa,CAAC,CAAC;AAAA,IACxB;AAAA,EACF;AACF;;;ACljBA,eAAsBC,iBACpB,MACA,UAA4B,CAAC,GACT;AACpB,QAAM,OAAO,QAAQ,QAAQ;AAC7B,MAAI,SAAS,SAAU,SAAS,UAAU,CAAC,kBAAkB,GAAI;AAC/D,WAAO,gBAAgB,MAAM,OAAO;AAAA,EACtC;AACA,MAAI;AACF,WAAO,MAAM,gBAAiB,MAAM,OAAO;AAAA,EAC7C,SAAS,OAAO;AACd,QAAI,SAAS,MAAO,OAAM;AAC1B,WAAO,gBAAgB,MAAM,OAAO;AAAA,EACtC;AACF;","names":["right","bottom","scale","drawn","child","bottom","right","right","bottom","createGpuCanvas"]}
|