open-plant 1.2.6 → 1.2.8
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 +7 -0
- package/dist/index.cjs +7 -7
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +1233 -1203
- package/dist/index.js.map +1 -1
- package/dist/types/react/draw-layer.d.ts +12 -1
- package/dist/types/react/draw-layer.d.ts.map +1 -1
- package/dist/types/react/wsi-viewer-canvas.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../src/core/gl-utils.ts","../src/core/ortho-camera.ts","../src/core/m1-tile-renderer.ts","../src/wsi/brush-stroke.ts","../src/wsi/constants.ts","../src/wsi/utils.ts","../src/react/draw-layer.tsx","../src/wsi/image-info.ts","../src/react/overview-map.tsx","../src/react/tile-viewer-canvas.tsx","../src/wsi/point-clip.ts","../src/wsi/webgpu.ts","../src/wsi/point-clip-hybrid.ts","../src/wsi/point-clip-worker-client.ts","../src/wsi/roi-term-stats.ts","../src/wsi/tile-scheduler.ts","../src/wsi/wsi-tile-renderer.ts","../src/react/wsi-viewer-canvas.tsx"],"sourcesContent":["function compileShader(gl: WebGL2RenderingContext, type: number, source: string): WebGLShader {\n const shader = gl.createShader(type);\n if (!shader) {\n throw new Error(\"Failed to create shader.\");\n }\n\n gl.shaderSource(shader, source);\n gl.compileShader(shader);\n\n const ok = gl.getShaderParameter(shader, gl.COMPILE_STATUS);\n if (!ok) {\n const log = gl.getShaderInfoLog(shader) ?? \"unknown shader error\";\n gl.deleteShader(shader);\n throw new Error(log);\n }\n\n return shader;\n}\n\nexport function createProgram(gl: WebGL2RenderingContext, vertexSource: string, fragmentSource: string): WebGLProgram {\n const vertexShader = compileShader(gl, gl.VERTEX_SHADER, vertexSource);\n const fragmentShader = compileShader(gl, gl.FRAGMENT_SHADER, fragmentSource);\n\n const program = gl.createProgram();\n if (!program) {\n gl.deleteShader(vertexShader);\n gl.deleteShader(fragmentShader);\n throw new Error(\"Failed to create program.\");\n }\n\n gl.attachShader(program, vertexShader);\n gl.attachShader(program, fragmentShader);\n gl.linkProgram(program);\n\n gl.deleteShader(vertexShader);\n gl.deleteShader(fragmentShader);\n\n const ok = gl.getProgramParameter(program, gl.LINK_STATUS);\n if (!ok) {\n const log = gl.getProgramInfoLog(program) ?? \"unknown link error\";\n gl.deleteProgram(program);\n throw new Error(log);\n }\n\n return program;\n}\n\nexport function requireUniformLocation(\n gl: WebGL2RenderingContext,\n program: WebGLProgram,\n uniformName: string,\n): WebGLUniformLocation {\n const location = gl.getUniformLocation(program, uniformName);\n if (!location) {\n throw new Error(`Failed to get uniform location: ${uniformName}`);\n }\n return location;\n}\n\nexport function requireWebGL2(canvas: HTMLCanvasElement): WebGL2RenderingContext {\n const context = canvas.getContext(\"webgl2\", {\n alpha: false,\n antialias: false,\n depth: false,\n stencil: false,\n preserveDrawingBuffer: false,\n powerPreference: \"high-performance\",\n });\n\n if (!context) {\n throw new Error(\"WebGL2 is not available.\");\n }\n\n return context;\n}\n","export interface ViewState {\n offsetX: number;\n offsetY: number;\n zoom: number;\n}\n\nexport class OrthoCamera {\n private viewportWidth = 1;\n private viewportHeight = 1;\n\n private viewState: ViewState = {\n offsetX: 0,\n offsetY: 0,\n zoom: 1,\n };\n\n setViewport(width: number, height: number): void {\n this.viewportWidth = Math.max(1, width);\n this.viewportHeight = Math.max(1, height);\n }\n\n getViewportSize(): { width: number; height: number } {\n return {\n width: this.viewportWidth,\n height: this.viewportHeight,\n };\n }\n\n setViewState(next: Partial<ViewState>): void {\n if (next.offsetX !== undefined) {\n this.viewState.offsetX = next.offsetX;\n }\n\n if (next.offsetY !== undefined) {\n this.viewState.offsetY = next.offsetY;\n }\n\n if (next.zoom !== undefined) {\n this.viewState.zoom = Math.max(0.0001, next.zoom);\n }\n }\n\n getViewState(): ViewState {\n return { ...this.viewState };\n }\n\n getMatrix(): Float32Array {\n const viewWidth = this.viewportWidth / this.viewState.zoom;\n const viewHeight = this.viewportHeight / this.viewState.zoom;\n\n const sx = 2 / viewWidth;\n const sy = -2 / viewHeight;\n const tx = -1 - this.viewState.offsetX * sx;\n const ty = 1 - this.viewState.offsetY * sy;\n\n return new Float32Array([\n sx,\n 0,\n 0,\n 0,\n sy,\n 0,\n tx,\n ty,\n 1,\n ]);\n }\n}\n","import {\n\tcreateProgram,\n\trequireUniformLocation,\n\trequireWebGL2,\n} from \"./gl-utils\";\nimport { OrthoCamera, type ViewState } from \"./ortho-camera\";\nimport type { Bounds, TileDefinition } from \"./types\";\n\ninterface LoadedTile {\n\tid: string;\n\tbounds: Bounds;\n\ttexture: WebGLTexture;\n}\n\nexport interface M1TileRendererOptions {\n\tcanvas: HTMLCanvasElement;\n\timageWidth: number;\n\timageHeight: number;\n\tclearColor?: [number, number, number, number];\n\tinitialViewState?: Partial<ViewState>;\n}\n\nconst VERTEX_SHADER = `#version 300 es\nprecision highp float;\n\nin vec2 aUnit;\nin vec2 aUv;\n\nuniform mat3 uCamera;\nuniform vec4 uBounds;\n\nout vec2 vUv;\n\nvoid main() {\n vec2 world = vec2(\n mix(uBounds.x, uBounds.z, aUnit.x),\n mix(uBounds.y, uBounds.w, aUnit.y)\n );\n vec3 clip = uCamera * vec3(world, 1.0);\n gl_Position = vec4(clip.xy, 0.0, 1.0);\n vUv = aUv;\n}\n`;\n\nconst FRAGMENT_SHADER = `#version 300 es\nprecision highp float;\n\nin vec2 vUv;\nuniform sampler2D uTexture;\n\nout vec4 outColor;\n\nvoid main() {\n outColor = texture(uTexture, vUv);\n}\n`;\n\nexport class M1TileRenderer {\n\tprivate readonly canvas: HTMLCanvasElement;\n\tprivate readonly gl: WebGL2RenderingContext;\n\tprivate readonly camera = new OrthoCamera();\n\tprivate readonly imageWidth: number;\n\tprivate readonly imageHeight: number;\n\tprivate readonly clearColor: [number, number, number, number];\n\tprivate readonly program: WebGLProgram;\n\tprivate readonly vao: WebGLVertexArrayObject;\n\tprivate readonly quadBuffer: WebGLBuffer;\n\tprivate readonly uCameraLocation: WebGLUniformLocation;\n\tprivate readonly uBoundsLocation: WebGLUniformLocation;\n\tprivate readonly uTextureLocation: WebGLUniformLocation;\n\tprivate readonly resizeObserver: ResizeObserver;\n\n\tprivate tiles: LoadedTile[] = [];\n\tprivate frameId: number | null = null;\n\tprivate loadVersion = 0;\n\tprivate destroyed = false;\n\tprivate fitted = false;\n\tprivate controlledViewState = false;\n\n\tconstructor(options: M1TileRendererOptions) {\n\t\tthis.canvas = options.canvas;\n\t\tthis.imageWidth = Math.max(1, options.imageWidth);\n\t\tthis.imageHeight = Math.max(1, options.imageHeight);\n\t\tthis.clearColor = options.clearColor ?? [0.03, 0.05, 0.08, 1];\n\n\t\tthis.gl = requireWebGL2(this.canvas);\n\t\tthis.program = createProgram(this.gl, VERTEX_SHADER, FRAGMENT_SHADER);\n\n\t\tconst vao = this.gl.createVertexArray();\n\t\tconst quadBuffer = this.gl.createBuffer();\n\t\tif (!vao || !quadBuffer) {\n\t\t\tthrow new Error(\"Failed to create WebGL buffers.\");\n\t\t}\n\n\t\tthis.vao = vao;\n\t\tthis.quadBuffer = quadBuffer;\n\n\t\tthis.gl.bindVertexArray(this.vao);\n\t\tthis.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.quadBuffer);\n\n\t\tconst quadVertices = new Float32Array([\n\t\t\t0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1,\n\t\t]);\n\n\t\tthis.gl.bufferData(this.gl.ARRAY_BUFFER, quadVertices, this.gl.STATIC_DRAW);\n\n\t\tconst unitLocation = this.gl.getAttribLocation(this.program, \"aUnit\");\n\t\tconst uvLocation = this.gl.getAttribLocation(this.program, \"aUv\");\n\t\tif (unitLocation < 0 || uvLocation < 0) {\n\t\t\tthrow new Error(\"Failed to get attribute locations.\");\n\t\t}\n\n\t\tconst stride = 4 * Float32Array.BYTES_PER_ELEMENT;\n\t\tthis.gl.enableVertexAttribArray(unitLocation);\n\t\tthis.gl.vertexAttribPointer(\n\t\t\tunitLocation,\n\t\t\t2,\n\t\t\tthis.gl.FLOAT,\n\t\t\tfalse,\n\t\t\tstride,\n\t\t\t0,\n\t\t);\n\t\tthis.gl.enableVertexAttribArray(uvLocation);\n\t\tthis.gl.vertexAttribPointer(\n\t\t\tuvLocation,\n\t\t\t2,\n\t\t\tthis.gl.FLOAT,\n\t\t\tfalse,\n\t\t\tstride,\n\t\t\t2 * Float32Array.BYTES_PER_ELEMENT,\n\t\t);\n\n\t\tthis.gl.bindVertexArray(null);\n\t\tthis.gl.bindBuffer(this.gl.ARRAY_BUFFER, null);\n\n\t\tthis.uCameraLocation = requireUniformLocation(\n\t\t\tthis.gl,\n\t\t\tthis.program,\n\t\t\t\"uCamera\",\n\t\t);\n\t\tthis.uBoundsLocation = requireUniformLocation(\n\t\t\tthis.gl,\n\t\t\tthis.program,\n\t\t\t\"uBounds\",\n\t\t);\n\t\tthis.uTextureLocation = requireUniformLocation(\n\t\t\tthis.gl,\n\t\t\tthis.program,\n\t\t\t\"uTexture\",\n\t\t);\n\n\t\tif (options.initialViewState) {\n\t\t\tthis.controlledViewState = true;\n\t\t\tthis.camera.setViewState(options.initialViewState);\n\t\t}\n\n\t\tthis.resizeObserver = new ResizeObserver(() => {\n\t\t\tthis.resize();\n\t\t});\n\n\t\tthis.resizeObserver.observe(this.canvas);\n\t\tthis.resize();\n\t}\n\n\tasync setTiles(tiles: TileDefinition[]): Promise<void> {\n\t\tif (this.destroyed) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst version = ++this.loadVersion;\n\n\t\tconst loaded = await Promise.all(\n\t\t\ttiles.map(async (tile) => {\n\t\t\t\tconst loadedTile = await this.loadTile(tile, version);\n\t\t\t\treturn loadedTile;\n\t\t\t}),\n\t\t);\n\n\t\tif (this.destroyed || version !== this.loadVersion) {\n\t\t\tfor (const tile of loaded) {\n\t\t\t\tif (tile) {\n\t\t\t\t\tthis.gl.deleteTexture(tile.texture);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tthis.disposeTiles(this.tiles);\n\t\tthis.tiles = loaded.filter((tile): tile is LoadedTile => tile !== null);\n\t\tthis.requestRender();\n\t}\n\n\tsetViewState(viewState: Partial<ViewState>): void {\n\t\tthis.controlledViewState = true;\n\t\tthis.camera.setViewState(viewState);\n\t\tthis.requestRender();\n\t}\n\n\tgetViewState(): ViewState {\n\t\treturn this.camera.getViewState();\n\t}\n\n\tdestroy(): void {\n\t\tif (this.destroyed) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.destroyed = true;\n\t\tthis.loadVersion += 1;\n\n\t\tif (this.frameId !== null) {\n\t\t\tcancelAnimationFrame(this.frameId);\n\t\t\tthis.frameId = null;\n\t\t}\n\n\t\tthis.resizeObserver.disconnect();\n\t\tthis.disposeTiles(this.tiles);\n\t\tthis.tiles = [];\n\n\t\tthis.gl.deleteBuffer(this.quadBuffer);\n\t\tthis.gl.deleteVertexArray(this.vao);\n\t\tthis.gl.deleteProgram(this.program);\n\t}\n\n\tprivate async loadTile(\n\t\ttile: TileDefinition,\n\t\tversion: number,\n\t): Promise<LoadedTile | null> {\n\t\ttry {\n\t\t\tconst response = await fetch(tile.url);\n\t\t\tif (!response.ok) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Tile fetch failed: ${response.status} ${response.statusText}`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst blob = await response.blob();\n\t\t\tconst bitmap = await createImageBitmap(blob);\n\n\t\t\tif (this.destroyed || version !== this.loadVersion) {\n\t\t\t\tbitmap.close();\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tconst texture = this.gl.createTexture();\n\t\t\tif (!texture) {\n\t\t\t\tbitmap.close();\n\t\t\t\tthrow new Error(\"Failed to create tile texture.\");\n\t\t\t}\n\n\t\t\tthis.gl.bindTexture(this.gl.TEXTURE_2D, texture);\n\t\t\tthis.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL, 1);\n\t\t\tthis.gl.texParameteri(\n\t\t\t\tthis.gl.TEXTURE_2D,\n\t\t\t\tthis.gl.TEXTURE_WRAP_S,\n\t\t\t\tthis.gl.CLAMP_TO_EDGE,\n\t\t\t);\n\t\t\tthis.gl.texParameteri(\n\t\t\t\tthis.gl.TEXTURE_2D,\n\t\t\t\tthis.gl.TEXTURE_WRAP_T,\n\t\t\t\tthis.gl.CLAMP_TO_EDGE,\n\t\t\t);\n\t\t\tthis.gl.texParameteri(\n\t\t\t\tthis.gl.TEXTURE_2D,\n\t\t\t\tthis.gl.TEXTURE_MIN_FILTER,\n\t\t\t\tthis.gl.LINEAR,\n\t\t\t);\n\t\t\tthis.gl.texParameteri(\n\t\t\t\tthis.gl.TEXTURE_2D,\n\t\t\t\tthis.gl.TEXTURE_MAG_FILTER,\n\t\t\t\tthis.gl.LINEAR,\n\t\t\t);\n\t\t\tthis.gl.texImage2D(\n\t\t\t\tthis.gl.TEXTURE_2D,\n\t\t\t\t0,\n\t\t\t\tthis.gl.RGBA,\n\t\t\t\tthis.gl.RGBA,\n\t\t\t\tthis.gl.UNSIGNED_BYTE,\n\t\t\t\tbitmap,\n\t\t\t);\n\t\t\tthis.gl.bindTexture(this.gl.TEXTURE_2D, null);\n\t\t\tbitmap.close();\n\n\t\t\treturn {\n\t\t\t\tid: tile.id,\n\t\t\t\tbounds: tile.bounds,\n\t\t\t\ttexture,\n\t\t\t};\n\t\t} catch (error) {\n\t\t\tconsole.error(`[M1TileRenderer] tile load failed: ${tile.id}`, error);\n\t\t\treturn null;\n\t\t}\n\t}\n\n\tprivate resize(): void {\n\t\tif (this.destroyed) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst rect = this.canvas.getBoundingClientRect();\n\t\tconst cssWidth = Math.max(1, rect.width || this.canvas.clientWidth || 1);\n\t\tconst cssHeight = Math.max(1, rect.height || this.canvas.clientHeight || 1);\n\t\tconst dpr = Math.max(1, window.devicePixelRatio || 1);\n\n\t\tconst targetWidth = Math.max(1, Math.round(cssWidth * dpr));\n\t\tconst targetHeight = Math.max(1, Math.round(cssHeight * dpr));\n\n\t\tif (\n\t\t\tthis.canvas.width !== targetWidth ||\n\t\t\tthis.canvas.height !== targetHeight\n\t\t) {\n\t\t\tthis.canvas.width = targetWidth;\n\t\t\tthis.canvas.height = targetHeight;\n\t\t}\n\n\t\tthis.camera.setViewport(cssWidth, cssHeight);\n\t\tthis.gl.viewport(0, 0, this.canvas.width, this.canvas.height);\n\n\t\tif (!this.fitted && !this.controlledViewState) {\n\t\t\tthis.fitToImage();\n\t\t\tthis.fitted = true;\n\t\t}\n\n\t\tthis.requestRender();\n\t}\n\n\tprivate fitToImage(): void {\n\t\tconst viewport = this.camera.getViewportSize();\n\n\t\tconst zoom = Math.min(\n\t\t\tviewport.width / this.imageWidth,\n\t\t\tviewport.height / this.imageHeight,\n\t\t);\n\t\tconst safeZoom = Number.isFinite(zoom) && zoom > 0 ? zoom : 1;\n\n\t\tconst visibleWorldWidth = viewport.width / safeZoom;\n\t\tconst visibleWorldHeight = viewport.height / safeZoom;\n\n\t\tconst offsetX = (this.imageWidth - visibleWorldWidth) * 0.5;\n\t\tconst offsetY = (this.imageHeight - visibleWorldHeight) * 0.5;\n\n\t\tthis.camera.setViewState({\n\t\t\tzoom: safeZoom,\n\t\t\toffsetX,\n\t\t\toffsetY,\n\t\t});\n\t}\n\n\tprivate requestRender(): void {\n\t\tif (this.frameId !== null || this.destroyed) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.frameId = requestAnimationFrame(() => {\n\t\t\tthis.frameId = null;\n\t\t\tthis.render();\n\t\t});\n\t}\n\n\tprivate render(): void {\n\t\tif (this.destroyed) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.gl.clearColor(\n\t\t\tthis.clearColor[0],\n\t\t\tthis.clearColor[1],\n\t\t\tthis.clearColor[2],\n\t\t\tthis.clearColor[3],\n\t\t);\n\t\tthis.gl.clear(this.gl.COLOR_BUFFER_BIT);\n\n\t\tthis.gl.useProgram(this.program);\n\t\tthis.gl.bindVertexArray(this.vao);\n\t\tthis.gl.uniformMatrix3fv(\n\t\t\tthis.uCameraLocation,\n\t\t\tfalse,\n\t\t\tthis.camera.getMatrix(),\n\t\t);\n\t\tthis.gl.uniform1i(this.uTextureLocation, 0);\n\n\t\tfor (const tile of this.tiles) {\n\t\t\tthis.gl.activeTexture(this.gl.TEXTURE0);\n\t\t\tthis.gl.bindTexture(this.gl.TEXTURE_2D, tile.texture);\n\t\t\tthis.gl.uniform4f(\n\t\t\t\tthis.uBoundsLocation,\n\t\t\t\ttile.bounds[0],\n\t\t\t\ttile.bounds[1],\n\t\t\t\ttile.bounds[2],\n\t\t\t\ttile.bounds[3],\n\t\t\t);\n\t\t\tthis.gl.drawArrays(this.gl.TRIANGLE_STRIP, 0, 4);\n\t\t}\n\n\t\tthis.gl.bindTexture(this.gl.TEXTURE_2D, null);\n\t\tthis.gl.bindVertexArray(null);\n\t}\n\n\tprivate disposeTiles(tiles: LoadedTile[]): void {\n\t\tfor (const tile of tiles) {\n\t\t\tthis.gl.deleteTexture(tile.texture);\n\t\t}\n\t}\n}\n","export type BrushStrokeCoordinate = [number, number];\nexport type BrushStrokeBounds = [number, number, number, number];\n\nexport interface BrushStrokePolygonOptions {\n\tradius: number;\n\tclipBounds?: BrushStrokeBounds;\n\tminRasterStep?: number;\n\tmaxRasterPixels?: number;\n\tmaxRasterSize?: number;\n\tsimplifyTolerance?: number;\n\tcircleSides?: number;\n}\n\ninterface RasterConfig {\n\tminX: number;\n\tminY: number;\n\tstep: number;\n\tpadding: number;\n\twidth: number;\n\theight: number;\n}\n\ninterface BoundaryEdge {\n\tstart: number;\n\tend: number;\n\tdir: 0 | 1 | 2 | 3;\n}\n\nconst DEFAULT_MIN_RASTER_STEP = 0.1;\nconst DEFAULT_MAX_RASTER_PIXELS = 4_000_000;\nconst DEFAULT_MAX_RASTER_SIZE = 4096;\nconst DEFAULT_CIRCLE_SIDES = 64;\nconst MIN_RADIUS = 1e-6;\nconst ALPHA_THRESHOLD = 24;\n\nfunction clamp(value: number, min: number, max: number): number {\n\treturn Math.max(min, Math.min(max, value));\n}\n\nfunction closeRing(\n\tcoordinates: BrushStrokeCoordinate[],\n): BrushStrokeCoordinate[] {\n\tif (!Array.isArray(coordinates) || coordinates.length < 3) return [];\n\tconst out = coordinates.map(([x, y]) => [x, y] as BrushStrokeCoordinate);\n\tconst first = out[0];\n\tconst last = out[out.length - 1];\n\tif (!first || !last) return [];\n\tif (first[0] !== last[0] || first[1] !== last[1]) {\n\t\tout.push([first[0], first[1]]);\n\t}\n\treturn out;\n}\n\nfunction sanitizePath(\n\tpoints: BrushStrokeCoordinate[],\n): BrushStrokeCoordinate[] {\n\tif (!Array.isArray(points) || points.length === 0) return [];\n\tconst out: BrushStrokeCoordinate[] = [];\n\tfor (const point of points) {\n\t\tif (!Array.isArray(point) || point.length < 2) continue;\n\t\tconst x = Number(point[0]);\n\t\tconst y = Number(point[1]);\n\t\tif (!Number.isFinite(x) || !Number.isFinite(y)) continue;\n\t\tconst prev = out[out.length - 1];\n\t\tif (prev && Math.abs(prev[0] - x) < 1e-9 && Math.abs(prev[1] - y) < 1e-9) {\n\t\t\tcontinue;\n\t\t}\n\t\tout.push([x, y]);\n\t}\n\treturn out;\n}\n\nfunction createCirclePolygon(\n\tcenter: BrushStrokeCoordinate,\n\tradius: number,\n\tsides: number,\n): BrushStrokeCoordinate[] {\n\tif (radius <= MIN_RADIUS || sides < 8) return [];\n\tconst ring: BrushStrokeCoordinate[] = [];\n\tfor (let i = 0; i <= sides; i += 1) {\n\t\tconst t = (i / sides) * Math.PI * 2;\n\t\tring.push([\n\t\t\tcenter[0] + Math.cos(t) * radius,\n\t\t\tcenter[1] + Math.sin(t) * radius,\n\t\t]);\n\t}\n\treturn closeRing(ring);\n}\n\nfunction createBoundsFallback(\n\tpoints: BrushStrokeCoordinate[],\n\tradius: number,\n): BrushStrokeCoordinate[] {\n\tif (!points.length) return [];\n\tlet minX = Infinity;\n\tlet minY = Infinity;\n\tlet maxX = -Infinity;\n\tlet maxY = -Infinity;\n\tfor (const [x, y] of points) {\n\t\tif (x < minX) minX = x;\n\t\tif (x > maxX) maxX = x;\n\t\tif (y < minY) minY = y;\n\t\tif (y > maxY) maxY = y;\n\t}\n\tif (!Number.isFinite(minX) || !Number.isFinite(minY)) return [];\n\tconst pad = Math.max(radius, 1);\n\treturn closeRing([\n\t\t[minX - pad, minY - pad],\n\t\t[maxX + pad, minY - pad],\n\t\t[maxX + pad, maxY + pad],\n\t\t[minX - pad, maxY + pad],\n\t]);\n}\n\nfunction computeExpandedBounds(\n\tpoints: BrushStrokeCoordinate[],\n\tradius: number,\n): BrushStrokeBounds {\n\tlet minX = Infinity;\n\tlet minY = Infinity;\n\tlet maxX = -Infinity;\n\tlet maxY = -Infinity;\n\tfor (const [x, y] of points) {\n\t\tif (x < minX) minX = x;\n\t\tif (x > maxX) maxX = x;\n\t\tif (y < minY) minY = y;\n\t\tif (y > maxY) maxY = y;\n\t}\n\tconst pad = Math.max(radius, 1);\n\treturn [minX - pad, minY - pad, maxX + pad, maxY + pad];\n}\n\nfunction resolveRasterConfig(\n\tbounds: BrushStrokeBounds,\n\tradius: number,\n\toptions: BrushStrokePolygonOptions,\n): RasterConfig {\n\tconst minRasterStep = Math.max(\n\t\tDEFAULT_MIN_RASTER_STEP,\n\t\tNumber(options.minRasterStep) || 0,\n\t);\n\tconst maxRasterPixels = Math.max(\n\t\t32_768,\n\t\tMath.floor(options.maxRasterPixels || DEFAULT_MAX_RASTER_PIXELS),\n\t);\n\tconst maxRasterSize = Math.max(\n\t\t256,\n\t\tMath.floor(options.maxRasterSize || DEFAULT_MAX_RASTER_SIZE),\n\t);\n\n\tconst widthWorld = Math.max(1e-3, bounds[2] - bounds[0]);\n\tconst heightWorld = Math.max(1e-3, bounds[3] - bounds[1]);\n\tlet step = Math.max(minRasterStep, Number.EPSILON);\n\tlet padding = 3;\n\tlet width = Math.ceil(widthWorld / step) + padding * 2 + 1;\n\tlet height = Math.ceil(heightWorld / step) + padding * 2 + 1;\n\n\twhile (\n\t\twidth > maxRasterSize ||\n\t\theight > maxRasterSize ||\n\t\twidth * height > maxRasterPixels\n\t) {\n\t\tstep *= 1.15;\n\t\twidth = Math.ceil(widthWorld / step) + padding * 2 + 1;\n\t\theight = Math.ceil(heightWorld / step) + padding * 2 + 1;\n\t\tif (step > Math.max(widthWorld, heightWorld)) {\n\t\t\tbreak;\n\t\t}\n\t}\n\n\twidth = Math.max(8, width);\n\theight = Math.max(8, height);\n\n\treturn {\n\t\tminX: bounds[0],\n\t\tminY: bounds[1],\n\t\tstep,\n\t\tpadding,\n\t\twidth,\n\t\theight,\n\t};\n}\n\ntype AnyCanvas2DContext =\n\t| CanvasRenderingContext2D\n\t| OffscreenCanvasRenderingContext2D;\n\nfunction createRasterContext(\n\twidth: number,\n\theight: number,\n): AnyCanvas2DContext | null {\n\tif (typeof OffscreenCanvas !== \"undefined\") {\n\t\tconst canvas = new OffscreenCanvas(width, height);\n\t\tconst context = canvas.getContext(\"2d\", { willReadFrequently: true });\n\t\tif (context) return context;\n\t}\n\tif (typeof document !== \"undefined\") {\n\t\tconst canvas = document.createElement(\"canvas\");\n\t\tcanvas.width = width;\n\t\tcanvas.height = height;\n\t\treturn canvas.getContext(\"2d\", { willReadFrequently: true });\n\t}\n\treturn null;\n}\n\nfunction worldToRaster(\n\tpoint: BrushStrokeCoordinate,\n\tconfig: RasterConfig,\n): BrushStrokeCoordinate {\n\treturn [\n\t\t(point[0] - config.minX) / config.step + config.padding,\n\t\t(point[1] - config.minY) / config.step + config.padding,\n\t];\n}\n\nfunction rasterizeStrokeMask(\n\tpath: BrushStrokeCoordinate[],\n\tradius: number,\n\tconfig: RasterConfig,\n): Uint8Array {\n\tconst context = createRasterContext(config.width, config.height);\n\tif (!context) return new Uint8Array(0);\n\n\tcontext.clearRect(0, 0, config.width, config.height);\n\tcontext.fillStyle = \"#ffffff\";\n\tcontext.strokeStyle = \"#ffffff\";\n\tcontext.lineCap = \"round\";\n\tcontext.lineJoin = \"round\";\n\tcontext.lineWidth = (radius * 2) / config.step;\n\n\tconst points = path.map(point => worldToRaster(point, config));\n\tif (points.length <= 1) {\n\t\tconst p = points[0];\n\t\tif (!p) return new Uint8Array(0);\n\t\tcontext.beginPath();\n\t\tcontext.arc(p[0], p[1], radius / config.step, 0, Math.PI * 2);\n\t\tcontext.fill();\n\t} else {\n\t\tcontext.beginPath();\n\t\tcontext.moveTo(points[0][0], points[0][1]);\n\t\tfor (let i = 1; i < points.length; i += 1) {\n\t\t\tcontext.lineTo(points[i][0], points[i][1]);\n\t\t}\n\t\tcontext.stroke();\n\t}\n\n\tconst image = context.getImageData(0, 0, config.width, config.height);\n\tconst out = new Uint8Array(config.width * config.height);\n\tfor (let i = 0; i < out.length; i += 1) {\n\t\tout[i] = image.data[i * 4 + 3] >= ALPHA_THRESHOLD ? 1 : 0;\n\t}\n\treturn out;\n}\n\nfunction buildBoundaryEdges(mask: Uint8Array, width: number, height: number): BoundaryEdge[] {\n\tconst edges: BoundaryEdge[] = [];\n\tconst stride = width + 1;\n\tconst vertex = (x: number, y: number): number => y * stride + x;\n\tconst at = (x: number, y: number): boolean =>\n\t\tx >= 0 && y >= 0 && x < width && y < height && mask[y * width + x] > 0;\n\n\tfor (let y = 0; y < height; y += 1) {\n\t\tfor (let x = 0; x < width; x += 1) {\n\t\t\tif (!at(x, y)) continue;\n\t\t\tif (!at(x, y - 1)) {\n\t\t\t\tedges.push({\n\t\t\t\t\tstart: vertex(x, y),\n\t\t\t\t\tend: vertex(x + 1, y),\n\t\t\t\t\tdir: 0,\n\t\t\t\t});\n\t\t\t}\n\t\t\tif (!at(x + 1, y)) {\n\t\t\t\tedges.push({\n\t\t\t\t\tstart: vertex(x + 1, y),\n\t\t\t\t\tend: vertex(x + 1, y + 1),\n\t\t\t\t\tdir: 1,\n\t\t\t\t});\n\t\t\t}\n\t\t\tif (!at(x, y + 1)) {\n\t\t\t\tedges.push({\n\t\t\t\t\tstart: vertex(x + 1, y + 1),\n\t\t\t\t\tend: vertex(x, y + 1),\n\t\t\t\t\tdir: 2,\n\t\t\t\t});\n\t\t\t}\n\t\t\tif (!at(x - 1, y)) {\n\t\t\t\tedges.push({\n\t\t\t\t\tstart: vertex(x, y + 1),\n\t\t\t\t\tend: vertex(x, y),\n\t\t\t\t\tdir: 3,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\treturn edges;\n}\n\nfunction turnPriority(fromDir: number, toDir: number): number {\n\tconst delta = (toDir - fromDir + 4) % 4;\n\tif (delta === 1) return 0; // right\n\tif (delta === 0) return 1; // straight\n\tif (delta === 3) return 2; // left\n\treturn 3; // reverse\n}\n\nfunction traceLoops(edges: BoundaryEdge[]): number[][] {\n\tif (!edges.length) return [];\n\n\tconst outgoing = new Map<number, number[]>();\n\tfor (let i = 0; i < edges.length; i += 1) {\n\t\tconst entry = outgoing.get(edges[i].start);\n\t\tif (entry) {\n\t\t\tentry.push(i);\n\t\t} else {\n\t\t\toutgoing.set(edges[i].start, [i]);\n\t\t}\n\t}\n\n\tconst used = new Uint8Array(edges.length);\n\tconst loops: number[][] = [];\n\n\tfor (let i = 0; i < edges.length; i += 1) {\n\t\tif (used[i]) continue;\n\n\t\tconst first = edges[i];\n\t\tconst startVertex = first.start;\n\t\tlet currentVertex = first.end;\n\t\tlet currentDir = first.dir;\n\t\tconst loop: number[] = [first.start, first.end];\n\t\tused[i] = 1;\n\n\t\tlet guard = 0;\n\t\tconst guardLimit = edges.length * 3;\n\t\twhile (currentVertex !== startVertex && guard < guardLimit) {\n\t\t\tconst candidates = outgoing.get(currentVertex);\n\t\t\tif (!candidates || candidates.length === 0) break;\n\n\t\t\tlet bestIndex = -1;\n\t\t\tlet bestPriority = Infinity;\n\t\t\tfor (const edgeIndex of candidates) {\n\t\t\t\tif (used[edgeIndex]) continue;\n\t\t\t\tconst candidate = edges[edgeIndex];\n\t\t\t\tconst priority = turnPriority(currentDir, candidate.dir);\n\t\t\t\tif (priority < bestPriority) {\n\t\t\t\t\tbestPriority = priority;\n\t\t\t\t\tbestIndex = edgeIndex;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (bestIndex < 0) break;\n\t\t\tused[bestIndex] = 1;\n\t\t\tconst next = edges[bestIndex];\n\t\t\tcurrentVertex = next.end;\n\t\t\tcurrentDir = next.dir;\n\t\t\tloop.push(currentVertex);\n\t\t\tguard += 1;\n\t\t}\n\n\t\tif (\n\t\t\tloop.length >= 4 &&\n\t\t\tloop[0] === loop[loop.length - 1]\n\t\t) {\n\t\t\tloops.push(loop);\n\t\t}\n\t}\n\n\treturn loops;\n}\n\nfunction toWorldRing(\n\tvertexLoop: number[],\n\twidth: number,\n\tconfig: RasterConfig,\n): BrushStrokeCoordinate[] {\n\tconst stride = width + 1;\n\tconst ring: BrushStrokeCoordinate[] = [];\n\tfor (const id of vertexLoop) {\n\t\tconst x = id % stride;\n\t\tconst y = Math.floor(id / stride);\n\t\tring.push([\n\t\t\tconfig.minX + (x - config.padding) * config.step,\n\t\t\tconfig.minY + (y - config.padding) * config.step,\n\t\t]);\n\t}\n\treturn closeRing(ring);\n}\n\nfunction polygonSignedArea(ring: BrushStrokeCoordinate[]): number {\n\tif (ring.length < 4) return 0;\n\tlet sum = 0;\n\tfor (let i = 0; i < ring.length - 1; i += 1) {\n\t\tconst a = ring[i];\n\t\tconst b = ring[i + 1];\n\t\tsum += a[0] * b[1] - b[0] * a[1];\n\t}\n\treturn sum * 0.5;\n}\n\nfunction removeCollinearVertices(\n\tring: BrushStrokeCoordinate[],\n\tepsilon = 1e-9,\n): BrushStrokeCoordinate[] {\n\tconst closed = closeRing(ring);\n\tif (closed.length < 5) return closed;\n\tconst out: BrushStrokeCoordinate[] = [closed[0]];\n\tfor (let i = 1; i < closed.length - 1; i += 1) {\n\t\tconst prev = out[out.length - 1];\n\t\tconst curr = closed[i];\n\t\tconst next = closed[i + 1];\n\t\tconst cross =\n\t\t\t(curr[0] - prev[0]) * (next[1] - curr[1]) -\n\t\t\t(curr[1] - prev[1]) * (next[0] - curr[0]);\n\t\tif (Math.abs(cross) <= epsilon) continue;\n\t\tout.push(curr);\n\t}\n\tout.push(out[0]);\n\treturn closeRing(out);\n}\n\nfunction pointLineDistanceSquared(\n\tp: BrushStrokeCoordinate,\n\ta: BrushStrokeCoordinate,\n\tb: BrushStrokeCoordinate,\n): number {\n\tconst abx = b[0] - a[0];\n\tconst aby = b[1] - a[1];\n\tconst len2 = abx * abx + aby * aby;\n\tif (len2 <= 1e-12) {\n\t\tconst dx = p[0] - a[0];\n\t\tconst dy = p[1] - a[1];\n\t\treturn dx * dx + dy * dy;\n\t}\n\tconst t = clamp(\n\t\t((p[0] - a[0]) * abx + (p[1] - a[1]) * aby) / len2,\n\t\t0,\n\t\t1,\n\t);\n\tconst x = a[0] + abx * t;\n\tconst y = a[1] + aby * t;\n\tconst dx = p[0] - x;\n\tconst dy = p[1] - y;\n\treturn dx * dx + dy * dy;\n}\n\nfunction simplifyRdp(\n\tpoints: BrushStrokeCoordinate[],\n\ttolerance: number,\n): BrushStrokeCoordinate[] {\n\tif (points.length <= 2 || tolerance <= 0) return points.slice();\n\n\tconst keep = new Uint8Array(points.length);\n\tkeep[0] = 1;\n\tkeep[points.length - 1] = 1;\n\tconst tolerance2 = tolerance * tolerance;\n\tconst stack: Array<[number, number]> = [[0, points.length - 1]];\n\n\twhile (stack.length > 0) {\n\t\tconst next = stack.pop();\n\t\tif (!next) break;\n\t\tconst [start, end] = next;\n\t\tif (end - start <= 1) continue;\n\n\t\tlet maxDist2 = 0;\n\t\tlet split = -1;\n\t\tfor (let i = start + 1; i < end; i += 1) {\n\t\t\tconst dist2 = pointLineDistanceSquared(points[i], points[start], points[end]);\n\t\t\tif (dist2 > maxDist2) {\n\t\t\t\tmaxDist2 = dist2;\n\t\t\t\tsplit = i;\n\t\t\t}\n\t\t}\n\n\t\tif (split >= 0 && maxDist2 > tolerance2) {\n\t\t\tkeep[split] = 1;\n\t\t\tstack.push([start, split], [split, end]);\n\t\t}\n\t}\n\n\tconst out: BrushStrokeCoordinate[] = [];\n\tfor (let i = 0; i < points.length; i += 1) {\n\t\tif (keep[i]) out.push(points[i]);\n\t}\n\treturn out;\n}\n\nfunction simplifyClosedRing(\n\tring: BrushStrokeCoordinate[],\n\ttolerance: number,\n): BrushStrokeCoordinate[] {\n\tconst closed = closeRing(ring);\n\tif (closed.length < 5 || tolerance <= 0) return closed;\n\tconst open = closed.slice(0, -1);\n\tconst simplified = simplifyRdp(open, tolerance);\n\tif (simplified.length < 3) return closed;\n\treturn closeRing(simplified);\n}\n\nfunction clampRingToBounds(\n\tring: BrushStrokeCoordinate[],\n\tbounds: BrushStrokeBounds | undefined,\n): BrushStrokeCoordinate[] {\n\tif (!bounds) return ring;\n\treturn closeRing(\n\t\tring.map(([x, y]) => [\n\t\t\tclamp(x, bounds[0], bounds[2]),\n\t\t\tclamp(y, bounds[1], bounds[3]),\n\t\t] as BrushStrokeCoordinate),\n\t);\n}\n\nexport function buildBrushStrokePolygon(\n\tpath: BrushStrokeCoordinate[],\n\toptions: BrushStrokePolygonOptions,\n): BrushStrokeCoordinate[] {\n\tconst points = sanitizePath(path);\n\tconst radius = Math.max(MIN_RADIUS, Number(options.radius) || 0);\n\tif (points.length === 0 || !Number.isFinite(radius)) return [];\n\n\tconst circleSides = Math.max(12, Math.floor(options.circleSides || DEFAULT_CIRCLE_SIDES));\n\tif (points.length === 1) {\n\t\treturn clampRingToBounds(\n\t\t\tcreateCirclePolygon(points[0], radius, circleSides),\n\t\t\toptions.clipBounds,\n\t\t);\n\t}\n\n\tconst bounds = computeExpandedBounds(points, radius);\n\tconst raster = resolveRasterConfig(bounds, radius, options);\n\tconst mask = rasterizeStrokeMask(points, radius, raster);\n\tif (!mask.length) {\n\t\treturn clampRingToBounds(createBoundsFallback(points, radius), options.clipBounds);\n\t}\n\n\tconst edges = buildBoundaryEdges(mask, raster.width, raster.height);\n\tconst loops = traceLoops(edges);\n\tif (!loops.length) {\n\t\treturn clampRingToBounds(createBoundsFallback(points, radius), options.clipBounds);\n\t}\n\n\tlet bestRing: BrushStrokeCoordinate[] = [];\n\tlet bestArea = 0;\n\tfor (const loop of loops) {\n\t\tconst ring = toWorldRing(loop, raster.width, raster);\n\t\tconst area = Math.abs(polygonSignedArea(ring));\n\t\tif (area <= bestArea) continue;\n\t\tbestArea = area;\n\t\tbestRing = ring;\n\t}\n\n\tif (!bestRing.length) {\n\t\treturn clampRingToBounds(createBoundsFallback(points, radius), options.clipBounds);\n\t}\n\n\tconst tolerance =\n\t\ttypeof options.simplifyTolerance === \"number\" && Number.isFinite(options.simplifyTolerance)\n\t\t\t? Math.max(0, options.simplifyTolerance)\n\t\t\t: raster.step * 0.2;\n\tconst simplified = simplifyClosedRing(\n\t\tremoveCollinearVertices(bestRing, raster.step * 1e-3),\n\t\ttolerance,\n\t);\n\treturn clampRingToBounds(simplified, options.clipBounds);\n}\n","export const DEFAULT_POINT_COLOR: [number, number, number, number] = [\n\t160, 160, 160, 255,\n];\n","import { DEFAULT_POINT_COLOR } from \"./constants\";\nimport type { TermPalette, WsiViewState } from \"./types\";\n\nexport function clamp(value: number, min: number, max: number): number {\n\treturn Math.max(min, Math.min(max, value));\n}\n\nexport function calcScaleResolution(\n\timageMpp: number,\n\timageZoom: number,\n\tcurrentZoom: number,\n): number {\n\tconst mpp = Number(imageMpp);\n\tconst z0 = Number(imageZoom);\n\tconst z1 = Number(currentZoom);\n\tif (!Number.isFinite(mpp) || mpp <= 0) return 1;\n\tif (!Number.isFinite(z0) || !Number.isFinite(z1)) return mpp;\n\treturn Math.pow(2, z0 - z1) * mpp;\n}\n\nexport function calcScaleLength(\n\timageMpp: number,\n\timageZoom: number,\n\tcurrentZoom: number,\n): string {\n\tconst resolution = calcScaleResolution(imageMpp, imageZoom, currentZoom);\n\tlet length = 100 * resolution;\n\tif (Number(imageMpp)) {\n\t\tlet unit = \"μm\";\n\t\tif (length > 1000) {\n\t\t\tlength /= 1000;\n\t\t\tunit = \"mm\";\n\t\t}\n\t\treturn `${length.toPrecision(3)} ${unit}`;\n\t}\n\treturn `${Math.round(length * 1000) / 1000} pixels`;\n}\n\nexport function isSameViewState(\n\ta: Partial<WsiViewState> | null | undefined,\n\tb: Partial<WsiViewState> | null | undefined,\n): boolean {\n\tif (!a && !b) return true;\n\tif (!a || !b) return false;\n\treturn (\n\t\tMath.abs((a.zoom ?? 0) - (b.zoom ?? 0)) < 1e-6 &&\n\t\tMath.abs((a.offsetX ?? 0) - (b.offsetX ?? 0)) < 1e-6 &&\n\t\tMath.abs((a.offsetY ?? 0) - (b.offsetY ?? 0)) < 1e-6 &&\n\t\tMath.abs((a.rotationDeg ?? 0) - (b.rotationDeg ?? 0)) < 1e-6\n\t);\n}\n\nexport function toBearerToken(value: string | null | undefined): string {\n\tconst trimmed = String(value ?? \"\").trim();\n\tif (!trimmed) return \"\";\n\tif (/^bearer\\s+/i.test(trimmed)) {\n\t\tconst token = trimmed.replace(/^bearer\\s+/i, \"\").trim();\n\t\treturn token ? `Bearer ${token}` : \"\";\n\t}\n\treturn `Bearer ${trimmed}`;\n}\n\nexport function hexToRgba(\n\thex: string | null | undefined,\n): [number, number, number, number] {\n\tconst value = String(hex ?? \"\").trim();\n\tconst match = value.match(/^#?([0-9a-fA-F]{6})$/);\n\tif (!match) return [...DEFAULT_POINT_COLOR];\n\n\tconst n = Number.parseInt(match[1], 16);\n\treturn [(n >> 16) & 255, (n >> 8) & 255, n & 255, 255];\n}\n\nexport function buildTermPalette(\n\tterms:\n\t\t| Array<{ termId?: string | null; termColor?: string | null }>\n\t\t| null\n\t\t| undefined,\n): TermPalette {\n\tconst palette: Array<[number, number, number, number]> = [\n\t\t[...DEFAULT_POINT_COLOR],\n\t];\n\tconst termToPaletteIndex = new Map<string, number>();\n\n\tfor (const term of terms ?? []) {\n\t\tconst termId = String(term?.termId ?? \"\");\n\t\tif (!termId || termToPaletteIndex.has(termId)) continue;\n\n\t\ttermToPaletteIndex.set(termId, palette.length);\n\t\tpalette.push(hexToRgba(term?.termColor));\n\t}\n\n\tconst colors = new Uint8Array(palette.length * 4);\n\tfor (let i = 0; i < palette.length; i += 1) {\n\t\tcolors[i * 4] = palette[i][0];\n\t\tcolors[i * 4 + 1] = palette[i][1];\n\t\tcolors[i * 4 + 2] = palette[i][2];\n\t\tcolors[i * 4 + 3] = palette[i][3];\n\t}\n\n\treturn { colors, termToPaletteIndex };\n}\n\nexport function createProgram(\n\tgl: WebGL2RenderingContext,\n\tvertexSource: string,\n\tfragmentSource: string,\n): WebGLProgram {\n\tconst vs = gl.createShader(gl.VERTEX_SHADER);\n\tconst fs = gl.createShader(gl.FRAGMENT_SHADER);\n\tif (!vs || !fs) {\n\t\tthrow new Error(\"Shader allocation failed\");\n\t}\n\n\tgl.shaderSource(vs, vertexSource);\n\tgl.compileShader(vs);\n\tif (!gl.getShaderParameter(vs, gl.COMPILE_STATUS)) {\n\t\tthrow new Error(gl.getShaderInfoLog(vs) || \"vertex compile failed\");\n\t}\n\n\tgl.shaderSource(fs, fragmentSource);\n\tgl.compileShader(fs);\n\tif (!gl.getShaderParameter(fs, gl.COMPILE_STATUS)) {\n\t\tthrow new Error(gl.getShaderInfoLog(fs) || \"fragment compile failed\");\n\t}\n\n\tconst program = gl.createProgram();\n\tif (!program) {\n\t\tthrow new Error(\"Program allocation failed\");\n\t}\n\n\tgl.attachShader(program, vs);\n\tgl.attachShader(program, fs);\n\tgl.linkProgram(program);\n\n\tgl.deleteShader(vs);\n\tgl.deleteShader(fs);\n\n\tif (!gl.getProgramParameter(program, gl.LINK_STATUS)) {\n\t\tthrow new Error(gl.getProgramInfoLog(program) || \"program link failed\");\n\t}\n\n\treturn program;\n}\n","import { type CSSProperties, type MutableRefObject, type PointerEvent as ReactPointerEvent, type RefObject, useCallback, useEffect, useMemo, useRef } from \"react\";\nimport { buildBrushStrokePolygon } from \"../wsi/brush-stroke\";\nimport { calcScaleResolution } from \"../wsi/utils\";\n\nexport type StampDrawTool = \"stamp-rectangle\" | \"stamp-circle\" | \"stamp-rectangle-4096px\" | \"stamp-rectangle-2mm2\" | \"stamp-circle-2mm2\" | \"stamp-circle-hpf-0.2mm2\";\n\nexport type DrawTool = \"cursor\" | \"freehand\" | \"rectangle\" | \"circular\" | \"brush\" | StampDrawTool;\n\nexport type DrawCoordinate = [number, number];\n\nexport type DrawBounds = [number, number, number, number];\n\nexport type DrawIntent = \"roi\" | \"patch\" | \"brush\";\n\nexport interface DrawResult {\n tool: Exclude<DrawTool, \"cursor\">;\n intent: DrawIntent;\n coordinates: DrawCoordinate[];\n bbox: DrawBounds;\n areaPx: number;\n}\n\nexport type PatchDrawResult = DrawResult & {\n tool: \"stamp-rectangle-4096px\";\n intent: \"patch\";\n};\n\nexport interface DrawRegion {\n id?: string | number;\n coordinates: DrawCoordinate[];\n label?: string;\n}\n\nexport interface RegionStyleContext {\n region: DrawRegion;\n regionId: string | number;\n regionIndex: number;\n state: \"default\" | \"hover\" | \"active\";\n}\n\nexport type RegionStrokeStyleResolver = (context: RegionStyleContext) => Partial<RegionStrokeStyle> | null | undefined;\n\nexport type DrawOverlayCoordinates = DrawCoordinate[] | DrawCoordinate[][] | DrawCoordinate[][][];\n\nexport interface DrawOverlayShape {\n id?: string | number;\n coordinates: DrawOverlayCoordinates;\n closed?: boolean;\n fill?: boolean;\n stroke?: Partial<RegionStrokeStyle>;\n strokeStyle?: Partial<RegionStrokeStyle>;\n invertedFill?: DrawOverlayInvertedFillStyle;\n visible?: boolean;\n}\n\nexport interface DrawOverlayInvertedFillStyle {\n fillColor: string;\n}\n\nexport interface RegionStrokeStyle {\n color: string;\n width: number;\n lineDash: number[];\n lineJoin: CanvasLineJoin;\n lineCap: CanvasLineCap;\n shadowColor: string;\n shadowBlur: number;\n shadowOffsetX: number;\n shadowOffsetY: number;\n}\n\nexport interface RegionLabelStyle {\n fontFamily: string;\n fontSize: number;\n fontWeight: string | number;\n textColor: string;\n backgroundColor: string;\n borderColor: string;\n borderWidth: number;\n paddingX: number;\n paddingY: number;\n offsetY: number;\n borderRadius: number;\n}\n\nexport interface DrawProjector {\n screenToWorld(clientX: number, clientY: number): DrawCoordinate | number[];\n worldToScreen(worldX: number, worldY: number): DrawCoordinate | number[];\n getViewState?: () => { zoom: number; rotationDeg?: number };\n zoomBy?: (factor: number, screenX: number, screenY: number) => void;\n}\n\nexport interface StampOptions {\n rectangleAreaMm2?: number;\n circleAreaMm2?: number;\n rectanglePixelSize?: number;\n}\n\nexport interface BrushOptions {\n radius: number;\n fillColor?: string;\n fillOpacity?: number;\n cursorColor?: string;\n cursorActiveColor?: string;\n cursorLineWidth?: number;\n cursorLineDash?: number[];\n}\n\nexport interface DrawLayerProps {\n tool: DrawTool;\n imageWidth: number;\n imageHeight: number;\n imageMpp?: number;\n imageZoom?: number;\n stampOptions?: StampOptions;\n brushOptions?: BrushOptions;\n projectorRef: RefObject<DrawProjector | null>;\n onDrawComplete?: (result: DrawResult) => void;\n onPatchComplete?: (result: PatchDrawResult) => void;\n enabled?: boolean;\n viewStateSignal?: unknown;\n persistedRegions?: DrawRegion[];\n patchRegions?: DrawRegion[];\n persistedPolygons?: DrawCoordinate[][];\n regionStrokeStyle?: Partial<RegionStrokeStyle>;\n regionStrokeHoverStyle?: Partial<RegionStrokeStyle>;\n regionStrokeActiveStyle?: Partial<RegionStrokeStyle>;\n patchStrokeStyle?: Partial<RegionStrokeStyle>;\n resolveRegionStrokeStyle?: RegionStrokeStyleResolver;\n overlayShapes?: DrawOverlayShape[];\n hoveredRegionId?: string | number | null;\n activeRegionId?: string | number | null;\n regionLabelStyle?: Partial<RegionLabelStyle>;\n invalidateRef?: MutableRefObject<(() => void) | null>;\n className?: string;\n style?: CSSProperties;\n}\n\ninterface DrawSession {\n isDrawing: boolean;\n pointerId: number | null;\n start: DrawCoordinate | null;\n current: DrawCoordinate | null;\n cursor: DrawCoordinate | null;\n points: DrawCoordinate[];\n stampCenter: DrawCoordinate | null;\n}\n\ninterface ResolvedBrushOptions {\n radius: number;\n fillColor: string;\n fillOpacity: number;\n cursorColor: string;\n cursorActiveColor: string;\n cursorLineWidth: number;\n cursorLineDash: number[];\n}\n\nconst DRAW_FILL = \"rgba(255, 77, 79, 0.16)\";\nconst FREEHAND_MIN_POINTS = 3;\nconst FREEHAND_SCREEN_STEP = 2;\nconst CIRCLE_SIDES = 96;\nconst MIN_AREA_PX = 1;\nconst EMPTY_REGIONS: DrawRegion[] = [];\nconst EMPTY_DASH: number[] = [];\nconst MICRONS_PER_MM = 1000;\nconst DEFAULT_STAMP_RECTANGLE_AREA_MM2 = 2;\nconst DEFAULT_STAMP_CIRCLE_AREA_MM2 = 2;\nconst DEFAULT_STAMP_RECTANGLE_PIXEL_SIZE = 4096;\nconst LEGACY_HPF_CIRCLE_AREA_MM2 = 0.2;\nconst WHEEL_ZOOM_IN_FACTOR = 1.12;\nconst WHEEL_ZOOM_OUT_FACTOR = 0.89;\nconst DEFAULT_BRUSH_RADIUS = 32;\nconst DEFAULT_BRUSH_FILL_COLOR = \"#000000\";\nconst DEFAULT_BRUSH_FILL_OPACITY = 0.1;\nconst DEFAULT_BRUSH_CURSOR_COLOR = \"#FFCF00\";\nconst DEFAULT_BRUSH_CURSOR_ACTIVE_COLOR = \"#FF0000\";\nconst DEFAULT_BRUSH_CURSOR_LINE_WIDTH = 1.5;\nconst DEFAULT_BRUSH_CURSOR_DASH = [2, 2];\nconst BRUSH_SCREEN_STEP = 1.5;\n\nconst DEFAULT_REGION_STROKE_STYLE: RegionStrokeStyle = {\n color: \"#ff4d4f\",\n width: 2,\n lineDash: EMPTY_DASH,\n lineJoin: \"round\",\n lineCap: \"round\",\n shadowColor: \"rgba(0, 0, 0, 0)\",\n shadowBlur: 0,\n shadowOffsetX: 0,\n shadowOffsetY: 0,\n};\n\nconst DEFAULT_PATCH_STROKE_STYLE: RegionStrokeStyle = {\n color: \"#4cc9f0\",\n width: 2,\n lineDash: [10, 8],\n lineJoin: \"round\",\n lineCap: \"round\",\n shadowColor: \"rgba(0, 0, 0, 0)\",\n shadowBlur: 0,\n shadowOffsetX: 0,\n shadowOffsetY: 0,\n};\n\nconst DEFAULT_REGION_LABEL_STYLE: RegionLabelStyle = {\n fontFamily: \"ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace\",\n fontSize: 12,\n fontWeight: 500,\n textColor: \"#ffffff\",\n backgroundColor: \"rgba(8, 14, 22, 0.88)\",\n borderColor: \"rgba(255, 77, 79, 0.85)\",\n borderWidth: 1,\n paddingX: 6,\n paddingY: 4,\n offsetY: 10,\n borderRadius: 3,\n};\n\nfunction clamp(value: number, min: number, max: number): number {\n return Math.max(min, Math.min(max, value));\n}\n\nfunction isStampTool(tool: DrawTool): tool is StampDrawTool {\n return (\n tool === \"stamp-rectangle\" || tool === \"stamp-circle\" || tool === \"stamp-rectangle-4096px\" || tool === \"stamp-rectangle-2mm2\" || tool === \"stamp-circle-2mm2\" || tool === \"stamp-circle-hpf-0.2mm2\"\n );\n}\n\nfunction clampPositiveOrFallback(value: number | undefined, fallback: number): number {\n if (typeof value !== \"number\" || !Number.isFinite(value) || value <= 0) {\n return fallback;\n }\n return value;\n}\n\nfunction resolveStampOptions(options: StampOptions | undefined): Required<StampOptions> {\n return {\n rectangleAreaMm2: clampPositiveOrFallback(options?.rectangleAreaMm2, DEFAULT_STAMP_RECTANGLE_AREA_MM2),\n circleAreaMm2: clampPositiveOrFallback(options?.circleAreaMm2, DEFAULT_STAMP_CIRCLE_AREA_MM2),\n rectanglePixelSize: clampPositiveOrFallback(options?.rectanglePixelSize, DEFAULT_STAMP_RECTANGLE_PIXEL_SIZE),\n };\n}\n\nfunction clampUnitOpacity(value: number | undefined, fallback: number): number {\n if (typeof value !== \"number\" || !Number.isFinite(value)) return fallback;\n return clamp(value, 0, 1);\n}\n\nfunction sanitizeBrushLineDash(value: number[] | undefined): number[] {\n if (!Array.isArray(value)) return DEFAULT_BRUSH_CURSOR_DASH;\n const out = value.filter(item => Number.isFinite(item) && item >= 0);\n return out.length > 0 ? out : DEFAULT_BRUSH_CURSOR_DASH;\n}\n\nfunction resolveBrushOptions(options: BrushOptions | undefined): ResolvedBrushOptions {\n const radius = clampPositiveOrFallback(options?.radius, DEFAULT_BRUSH_RADIUS);\n const cursorLineWidth = clampPositiveOrFallback(options?.cursorLineWidth, DEFAULT_BRUSH_CURSOR_LINE_WIDTH);\n return {\n radius,\n fillColor: options?.fillColor || DEFAULT_BRUSH_FILL_COLOR,\n fillOpacity: clampUnitOpacity(options?.fillOpacity, DEFAULT_BRUSH_FILL_OPACITY),\n cursorColor: options?.cursorColor || DEFAULT_BRUSH_CURSOR_COLOR,\n cursorActiveColor: options?.cursorActiveColor || DEFAULT_BRUSH_CURSOR_ACTIVE_COLOR,\n cursorLineWidth,\n cursorLineDash: sanitizeBrushLineDash(options?.cursorLineDash),\n };\n}\n\nfunction mm2ToUm2(areaMm2: number): number {\n return areaMm2 * MICRONS_PER_MM * MICRONS_PER_MM;\n}\n\nfunction createSquareFromCenter(center: DrawCoordinate | null, halfLength: number): DrawCoordinate[] {\n if (!center || !Number.isFinite(halfLength) || halfLength <= 0) return [];\n return closeRing([\n [center[0] - halfLength, center[1] - halfLength],\n [center[0] + halfLength, center[1] - halfLength],\n [center[0] + halfLength, center[1] + halfLength],\n [center[0] - halfLength, center[1] + halfLength],\n ]);\n}\n\nfunction createCircleFromCenter(center: DrawCoordinate | null, radius: number, sides = CIRCLE_SIDES): DrawCoordinate[] {\n if (!center || !Number.isFinite(radius) || radius <= 0) return [];\n\n const coords: DrawCoordinate[] = [];\n for (let i = 0; i <= sides; i += 1) {\n const t = (i / sides) * Math.PI * 2;\n coords.push([center[0] + Math.cos(t) * radius, center[1] + Math.sin(t) * radius]);\n }\n\n return closeRing(coords);\n}\n\nexport function closeRing(coords: DrawCoordinate[]): DrawCoordinate[] {\n if (!Array.isArray(coords) || coords.length < 3) return [];\n\n const out = coords.map(([x, y]) => [x, y] as DrawCoordinate);\n const first = out[0];\n const last = out[out.length - 1];\n if (!first || !last) return [];\n\n if (first[0] !== last[0] || first[1] !== last[1]) {\n out.push([first[0], first[1]]);\n }\n\n return out;\n}\n\nexport function createRectangle(start: DrawCoordinate | null, end: DrawCoordinate | null): DrawCoordinate[] {\n if (!start || !end) return [];\n\n return closeRing([\n [start[0], start[1]],\n [end[0], start[1]],\n [end[0], end[1]],\n [start[0], end[1]],\n ]);\n}\n\nexport function createCircle(start: DrawCoordinate | null, end: DrawCoordinate | null, sides = CIRCLE_SIDES): DrawCoordinate[] {\n if (!start || !end) return [];\n\n const centerX = (start[0] + end[0]) * 0.5;\n const centerY = (start[1] + end[1]) * 0.5;\n const radius = Math.hypot(end[0] - start[0], end[1] - start[1]) * 0.5;\n if (radius < 1) return [];\n\n const coords: DrawCoordinate[] = [];\n for (let i = 0; i <= sides; i += 1) {\n const t = (i / sides) * Math.PI * 2;\n coords.push([centerX + Math.cos(t) * radius, centerY + Math.sin(t) * radius]);\n }\n\n return closeRing(coords);\n}\n\nfunction polygonArea(coords: DrawCoordinate[]): number {\n if (!Array.isArray(coords) || coords.length < 4) return 0;\n\n let sum = 0;\n for (let i = 0; i < coords.length - 1; i += 1) {\n const a = coords[i];\n const b = coords[i + 1];\n sum += a[0] * b[1] - b[0] * a[1];\n }\n\n return Math.abs(sum * 0.5);\n}\n\nfunction computeBounds(coords: DrawCoordinate[]): DrawBounds {\n if (!Array.isArray(coords) || coords.length === 0) return [0, 0, 0, 0];\n\n let minX = Infinity;\n let minY = Infinity;\n let maxX = -Infinity;\n let maxY = -Infinity;\n\n for (const [x, y] of coords) {\n if (x < minX) minX = x;\n if (x > maxX) maxX = x;\n if (y < minY) minY = y;\n if (y > maxY) maxY = y;\n }\n\n return [minX, minY, maxX, maxY];\n}\n\nfunction isValidPolygon(coords: DrawCoordinate[]): boolean {\n return Array.isArray(coords) && coords.length >= 4 && polygonArea(coords) > MIN_AREA_PX;\n}\n\nfunction tracePath(ctx: CanvasRenderingContext2D, points: DrawCoordinate[], close = false): void {\n if (points.length === 0) return;\n\n ctx.moveTo(points[0][0], points[0][1]);\n for (let i = 1; i < points.length; i += 1) {\n ctx.lineTo(points[i][0], points[i][1]);\n }\n\n if (close) {\n ctx.closePath();\n }\n}\n\nfunction drawPath(ctx: CanvasRenderingContext2D, points: DrawCoordinate[], strokeStyle: RegionStrokeStyle, close = false, fill = false): void {\n if (points.length === 0) return;\n\n ctx.beginPath();\n tracePath(ctx, points, close);\n if (fill && close) {\n ctx.fillStyle = DRAW_FILL;\n ctx.fill();\n }\n\n ctx.strokeStyle = strokeStyle.color;\n ctx.lineWidth = strokeStyle.width;\n ctx.lineJoin = strokeStyle.lineJoin;\n ctx.lineCap = strokeStyle.lineCap;\n ctx.shadowColor = strokeStyle.shadowColor;\n ctx.shadowBlur = strokeStyle.shadowBlur;\n ctx.shadowOffsetX = strokeStyle.shadowOffsetX;\n ctx.shadowOffsetY = strokeStyle.shadowOffsetY;\n ctx.setLineDash(strokeStyle.lineDash);\n ctx.stroke();\n ctx.setLineDash(EMPTY_DASH);\n ctx.shadowColor = \"rgba(0, 0, 0, 0)\";\n ctx.shadowBlur = 0;\n ctx.shadowOffsetX = 0;\n ctx.shadowOffsetY = 0;\n}\n\nfunction resolveStrokeStyle(style: Partial<RegionStrokeStyle> | undefined): RegionStrokeStyle {\n const dash = Array.isArray(style?.lineDash) ? style.lineDash.filter(value => Number.isFinite(value) && value >= 0) : EMPTY_DASH;\n const width = typeof style?.width === \"number\" && Number.isFinite(style.width) ? Math.max(0, style.width) : DEFAULT_REGION_STROKE_STYLE.width;\n const shadowBlur = typeof style?.shadowBlur === \"number\" && Number.isFinite(style.shadowBlur) ? Math.max(0, style.shadowBlur) : DEFAULT_REGION_STROKE_STYLE.shadowBlur;\n const shadowOffsetX = typeof style?.shadowOffsetX === \"number\" && Number.isFinite(style.shadowOffsetX) ? style.shadowOffsetX : DEFAULT_REGION_STROKE_STYLE.shadowOffsetX;\n const shadowOffsetY = typeof style?.shadowOffsetY === \"number\" && Number.isFinite(style.shadowOffsetY) ? style.shadowOffsetY : DEFAULT_REGION_STROKE_STYLE.shadowOffsetY;\n return {\n color: style?.color || DEFAULT_REGION_STROKE_STYLE.color,\n width,\n lineDash: dash.length ? dash : EMPTY_DASH,\n lineJoin: style?.lineJoin || DEFAULT_REGION_STROKE_STYLE.lineJoin,\n lineCap: style?.lineCap || DEFAULT_REGION_STROKE_STYLE.lineCap,\n shadowColor: style?.shadowColor || DEFAULT_REGION_STROKE_STYLE.shadowColor,\n shadowBlur,\n shadowOffsetX,\n shadowOffsetY,\n };\n}\n\nfunction mergeStrokeStyle(base: RegionStrokeStyle, override: Partial<RegionStrokeStyle> | undefined): RegionStrokeStyle {\n if (!override) return base;\n return resolveStrokeStyle({\n color: override.color ?? base.color,\n width: override.width ?? base.width,\n lineDash: override.lineDash ?? base.lineDash,\n lineJoin: override.lineJoin ?? base.lineJoin,\n lineCap: override.lineCap ?? base.lineCap,\n shadowColor: override.shadowColor ?? base.shadowColor,\n shadowBlur: override.shadowBlur ?? base.shadowBlur,\n shadowOffsetX: override.shadowOffsetX ?? base.shadowOffsetX,\n shadowOffsetY: override.shadowOffsetY ?? base.shadowOffsetY,\n });\n}\n\nfunction isSameRegionId(a: string | number | null | undefined, b: string | number | null | undefined): boolean {\n if (a === null || a === undefined || b === null || b === undefined) {\n return false;\n }\n return String(a) === String(b);\n}\n\nfunction isNestedRingCoordinates(coordinates: DrawOverlayCoordinates): boolean {\n const first = coordinates[0];\n return Array.isArray(first) && Array.isArray(first[0]);\n}\n\nfunction isFiniteNumber(value: unknown): value is number {\n return typeof value === \"number\" && Number.isFinite(value);\n}\n\nfunction isCoordinatePair(value: unknown): value is [number, number] {\n return Array.isArray(value) && value.length >= 2 && isFiniteNumber(value[0]) && isFiniteNumber(value[1]);\n}\n\nfunction isCoordinateRing(value: unknown): value is DrawCoordinate[] {\n return Array.isArray(value) && value.length >= 2 && value.every(point => isCoordinatePair(point));\n}\n\nfunction collectOverlayRings(value: unknown, out: DrawCoordinate[][]): void {\n if (!Array.isArray(value) || value.length === 0) return;\n if (isCoordinateRing(value)) {\n out.push(value.map(([x, y]) => [x, y] as DrawCoordinate));\n return;\n }\n for (const item of value) {\n collectOverlayRings(item, out);\n }\n}\n\nfunction normalizeOverlayRings(coordinates: DrawOverlayCoordinates, close: boolean): DrawCoordinate[][] {\n const sourceRings: DrawCoordinate[][] = [];\n collectOverlayRings(coordinates, sourceRings);\n const out: DrawCoordinate[][] = [];\n for (const ring of sourceRings) {\n if (ring.length < 2) continue;\n const normalized = close ? closeRing(ring) : ring;\n if (normalized.length >= (close ? 4 : 2)) {\n out.push(normalized);\n }\n }\n return out;\n}\n\nfunction drawInvertedFillMask(ctx: CanvasRenderingContext2D, outerRing: DrawCoordinate[], holeRings: DrawCoordinate[][], fillColor: string): void {\n if (outerRing.length < 4 || holeRings.length === 0) return;\n ctx.save();\n ctx.beginPath();\n tracePath(ctx, outerRing, true);\n for (const ring of holeRings) {\n if (ring.length < 4) continue;\n tracePath(ctx, ring, true);\n }\n ctx.fillStyle = fillColor;\n ctx.fill(\"evenodd\");\n ctx.restore();\n}\n\nfunction resolveLabelStyle(style: Partial<RegionLabelStyle> | undefined): RegionLabelStyle {\n const px = typeof style?.paddingX === \"number\" && Number.isFinite(style.paddingX) ? Math.max(0, style.paddingX) : DEFAULT_REGION_LABEL_STYLE.paddingX;\n const py = typeof style?.paddingY === \"number\" && Number.isFinite(style.paddingY) ? Math.max(0, style.paddingY) : DEFAULT_REGION_LABEL_STYLE.paddingY;\n const fs = typeof style?.fontSize === \"number\" && Number.isFinite(style.fontSize) ? Math.max(8, style.fontSize) : DEFAULT_REGION_LABEL_STYLE.fontSize;\n const bw = typeof style?.borderWidth === \"number\" && Number.isFinite(style.borderWidth) ? Math.max(0, style.borderWidth) : DEFAULT_REGION_LABEL_STYLE.borderWidth;\n const oy = typeof style?.offsetY === \"number\" && Number.isFinite(style.offsetY) ? style.offsetY : DEFAULT_REGION_LABEL_STYLE.offsetY;\n const br = typeof style?.borderRadius === \"number\" && Number.isFinite(style.borderRadius) ? Math.max(0, style.borderRadius) : DEFAULT_REGION_LABEL_STYLE.borderRadius;\n return {\n fontFamily: style?.fontFamily || DEFAULT_REGION_LABEL_STYLE.fontFamily,\n fontSize: fs,\n fontWeight: style?.fontWeight || DEFAULT_REGION_LABEL_STYLE.fontWeight,\n textColor: style?.textColor || DEFAULT_REGION_LABEL_STYLE.textColor,\n backgroundColor: style?.backgroundColor || DEFAULT_REGION_LABEL_STYLE.backgroundColor,\n borderColor: style?.borderColor || DEFAULT_REGION_LABEL_STYLE.borderColor,\n borderWidth: bw,\n paddingX: px,\n paddingY: py,\n offsetY: oy,\n borderRadius: br,\n };\n}\n\nfunction drawRoundedRect(ctx: CanvasRenderingContext2D, x: number, y: number, width: number, height: number, radius: number): void {\n const r = Math.max(0, Math.min(radius, width * 0.5, height * 0.5));\n ctx.beginPath();\n ctx.moveTo(x + r, y);\n ctx.lineTo(x + width - r, y);\n ctx.quadraticCurveTo(x + width, y, x + width, y + r);\n ctx.lineTo(x + width, y + height - r);\n ctx.quadraticCurveTo(x + width, y + height, x + width - r, y + height);\n ctx.lineTo(x + r, y + height);\n ctx.quadraticCurveTo(x, y + height, x, y + height - r);\n ctx.lineTo(x, y + r);\n ctx.quadraticCurveTo(x, y, x + r, y);\n ctx.closePath();\n}\n\nfunction getTopAnchor(coords: DrawCoordinate[]): DrawCoordinate | null {\n if (!coords.length) return null;\n\n let minY = Infinity;\n for (const point of coords) {\n if (point[1] < minY) minY = point[1];\n }\n if (!Number.isFinite(minY)) return null;\n\n let minX = Infinity;\n let maxX = -Infinity;\n for (const point of coords) {\n if (Math.abs(point[1] - minY) > 0.5) continue;\n if (point[0] < minX) minX = point[0];\n if (point[0] > maxX) maxX = point[0];\n }\n\n if (!Number.isFinite(minX) || !Number.isFinite(maxX)) return null;\n return [(minX + maxX) * 0.5, minY];\n}\n\nfunction drawRegionLabel(ctx: CanvasRenderingContext2D, text: string, anchor: DrawCoordinate, canvasWidth: number, canvasHeight: number, labelStyle: RegionLabelStyle): void {\n const label = text.trim();\n if (!label) return;\n\n ctx.save();\n ctx.font = `${labelStyle.fontWeight} ${labelStyle.fontSize}px ${labelStyle.fontFamily}`;\n ctx.textAlign = \"center\";\n ctx.textBaseline = \"middle\";\n\n const textWidth = ctx.measureText(label).width;\n const boxWidth = textWidth + labelStyle.paddingX * 2;\n const boxHeight = labelStyle.fontSize + labelStyle.paddingY * 2;\n\n const x = clamp(anchor[0], boxWidth * 0.5 + 1, canvasWidth - boxWidth * 0.5 - 1);\n const y = clamp(anchor[1] - labelStyle.offsetY, boxHeight * 0.5 + 1, canvasHeight - boxHeight * 0.5 - 1);\n const left = x - boxWidth * 0.5;\n const top = y - boxHeight * 0.5;\n\n ctx.fillStyle = labelStyle.backgroundColor;\n ctx.strokeStyle = labelStyle.borderColor;\n ctx.lineWidth = labelStyle.borderWidth;\n drawRoundedRect(ctx, left, top, boxWidth, boxHeight, labelStyle.borderRadius);\n ctx.fill();\n if (labelStyle.borderWidth > 0) {\n ctx.stroke();\n }\n\n ctx.fillStyle = labelStyle.textColor;\n ctx.fillText(label, x, y + 0.5);\n ctx.restore();\n}\n\nfunction clampWorld(coord: DrawCoordinate, imageWidth: number, imageHeight: number): DrawCoordinate {\n return [clamp(coord[0], 0, imageWidth), clamp(coord[1], 0, imageHeight)];\n}\n\nfunction toCoord(value: DrawCoordinate | number[]): DrawCoordinate | null {\n if (!Array.isArray(value) || value.length < 2) return null;\n const x = Number(value[0]);\n const y = Number(value[1]);\n if (!Number.isFinite(x) || !Number.isFinite(y)) return null;\n return [x, y];\n}\n\nexport function DrawLayer({\n tool,\n imageWidth,\n imageHeight,\n imageMpp,\n imageZoom,\n stampOptions,\n brushOptions,\n projectorRef,\n onDrawComplete,\n onPatchComplete,\n enabled,\n viewStateSignal,\n persistedRegions,\n patchRegions,\n persistedPolygons,\n regionStrokeStyle,\n regionStrokeHoverStyle,\n regionStrokeActiveStyle,\n patchStrokeStyle,\n resolveRegionStrokeStyle,\n overlayShapes,\n hoveredRegionId = null,\n activeRegionId = null,\n regionLabelStyle,\n invalidateRef,\n className,\n style,\n}: DrawLayerProps): React.ReactElement {\n const canvasRef = useRef<HTMLCanvasElement | null>(null);\n const drawPendingRef = useRef(false);\n const overlayDebugSnapshotRef = useRef<Map<string, string>>(new Map());\n const lastToolRef = useRef<DrawTool>(tool);\n const sessionRef = useRef<DrawSession>({\n isDrawing: false,\n pointerId: null,\n start: null,\n current: null,\n cursor: null,\n points: [],\n stampCenter: null,\n });\n\n const active = enabled ?? tool !== \"cursor\";\n const mergedPersistedRegions = useMemo<DrawRegion[]>(() => {\n if (persistedRegions && persistedRegions.length > 0) {\n return persistedRegions;\n }\n if (!persistedPolygons || persistedPolygons.length === 0) {\n return EMPTY_REGIONS;\n }\n return persistedPolygons.map((coordinates, index) => ({\n id: index,\n coordinates,\n }));\n }, [persistedRegions, persistedPolygons]);\n const mergedPatchRegions = useMemo<DrawRegion[]>(() => patchRegions ?? EMPTY_REGIONS, [patchRegions]);\n\n const resolvedStrokeStyle = useMemo(() => resolveStrokeStyle(regionStrokeStyle), [regionStrokeStyle]);\n const resolvedHoverStrokeStyle = useMemo(() => mergeStrokeStyle(resolvedStrokeStyle, regionStrokeHoverStyle), [resolvedStrokeStyle, regionStrokeHoverStyle]);\n const resolvedActiveStrokeStyle = useMemo(() => mergeStrokeStyle(resolvedStrokeStyle, regionStrokeActiveStyle), [resolvedStrokeStyle, regionStrokeActiveStyle]);\n const resolvedPatchStrokeStyle = useMemo(() => mergeStrokeStyle(DEFAULT_PATCH_STROKE_STYLE, patchStrokeStyle), [patchStrokeStyle]);\n\n const resolvedLabelStyle = useMemo(() => resolveLabelStyle(regionLabelStyle), [regionLabelStyle]);\n const resolvedStampOptions = useMemo(() => resolveStampOptions(stampOptions), [stampOptions]);\n const resolvedBrushOptions = useMemo(() => resolveBrushOptions(brushOptions), [brushOptions]);\n\n const mergedStyle = useMemo<CSSProperties>(\n () => ({\n position: \"absolute\",\n inset: 0,\n zIndex: 2,\n width: \"100%\",\n height: \"100%\",\n display: \"block\",\n touchAction: \"none\",\n pointerEvents: active ? \"auto\" : \"none\",\n cursor: active ? (tool === \"brush\" ? \"none\" : \"crosshair\") : \"default\",\n ...style,\n }),\n [active, tool, style]\n );\n\n const resizeCanvas = useCallback(() => {\n const canvas = canvasRef.current;\n if (!canvas) return;\n\n const rect = canvas.getBoundingClientRect();\n const dpr = Math.max(1, window.devicePixelRatio || 1);\n const w = Math.max(1, Math.round(rect.width * dpr));\n const h = Math.max(1, Math.round(rect.height * dpr));\n\n if (canvas.width !== w || canvas.height !== h) {\n canvas.width = w;\n canvas.height = h;\n }\n }, []);\n\n const worldToScreenPoints = useCallback(\n (points: DrawCoordinate[]): DrawCoordinate[] => {\n const projector = projectorRef.current;\n if (!projector || points.length === 0) return [];\n\n const out = new Array<DrawCoordinate>(points.length);\n for (let i = 0; i < points.length; i += 1) {\n const coord = toCoord(projector.worldToScreen(points[i][0], points[i][1]));\n if (!coord) return [];\n out[i] = coord;\n }\n return out;\n },\n [projectorRef]\n );\n\n const worldRadiusToScreenPixels = useCallback(\n (center: DrawCoordinate, worldRadius: number): number => {\n if (!Number.isFinite(worldRadius) || worldRadius <= 0) return 0;\n const projector = projectorRef.current;\n if (!projector) return 0;\n const a = toCoord(projector.worldToScreen(center[0], center[1]));\n const b = toCoord(projector.worldToScreen(center[0] + worldRadius, center[1]));\n if (!a || !b) return 0;\n return Math.hypot(b[0] - a[0], b[1] - a[1]);\n },\n [projectorRef]\n );\n\n const micronsToWorldPixels = useCallback(\n (lengthUm: number): number => {\n if (!Number.isFinite(lengthUm) || lengthUm <= 0) return 0;\n\n // If mpp is missing, fall back to 1um/px assumption.\n const mppValue = typeof imageMpp === \"number\" && Number.isFinite(imageMpp) && imageMpp > 0 ? imageMpp : 1;\n const imageZoomValue = typeof imageZoom === \"number\" && Number.isFinite(imageZoom) ? imageZoom : 0;\n const viewZoomRaw = projectorRef.current?.getViewState?.().zoom;\n const viewZoom = typeof viewZoomRaw === \"number\" && Number.isFinite(viewZoomRaw) && viewZoomRaw > 0 ? viewZoomRaw : 1;\n const continuousZoom = imageZoomValue + Math.log2(viewZoom);\n const umPerScreenPixel = Math.max(1e-9, calcScaleResolution(mppValue, imageZoomValue, continuousZoom));\n const screenPixels = lengthUm / umPerScreenPixel;\n return screenPixels / viewZoom;\n },\n [imageMpp, imageZoom, projectorRef]\n );\n\n const buildStampCoords = useCallback(\n (stampTool: StampDrawTool, center: DrawCoordinate | null): DrawCoordinate[] => {\n if (!center) return [];\n\n let areaMm2 = 0;\n if (stampTool === \"stamp-rectangle-4096px\") {\n const halfLength = resolvedStampOptions.rectanglePixelSize * 0.5;\n const fixed = createSquareFromCenter(center, halfLength);\n return fixed.map(point => clampWorld(point, imageWidth, imageHeight));\n }\n\n if (stampTool === \"stamp-rectangle\" || stampTool === \"stamp-rectangle-2mm2\") {\n areaMm2 = stampTool === \"stamp-rectangle-2mm2\" ? DEFAULT_STAMP_RECTANGLE_AREA_MM2 : resolvedStampOptions.rectangleAreaMm2;\n } else if (stampTool === \"stamp-circle\" || stampTool === \"stamp-circle-2mm2\" || stampTool === \"stamp-circle-hpf-0.2mm2\") {\n areaMm2 = stampTool === \"stamp-circle-hpf-0.2mm2\" ? LEGACY_HPF_CIRCLE_AREA_MM2 : stampTool === \"stamp-circle-2mm2\" ? DEFAULT_STAMP_CIRCLE_AREA_MM2 : resolvedStampOptions.circleAreaMm2;\n }\n if (!Number.isFinite(areaMm2) || areaMm2 <= 0) return [];\n\n const areaUm2 = mm2ToUm2(areaMm2);\n let coords: DrawCoordinate[] = [];\n if (stampTool === \"stamp-rectangle\" || stampTool === \"stamp-rectangle-2mm2\") {\n const halfLength = micronsToWorldPixels(Math.sqrt(areaUm2) * 0.5);\n coords = createSquareFromCenter(center, halfLength);\n } else if (stampTool === \"stamp-circle\" || stampTool === \"stamp-circle-2mm2\" || stampTool === \"stamp-circle-hpf-0.2mm2\") {\n const radius = micronsToWorldPixels(Math.sqrt(areaUm2 / Math.PI));\n coords = createCircleFromCenter(center, radius);\n }\n\n if (!coords.length) return [];\n return coords.map(point => clampWorld(point, imageWidth, imageHeight));\n },\n [micronsToWorldPixels, imageWidth, imageHeight, resolvedStampOptions]\n );\n\n const buildPreviewCoords = useCallback((): DrawCoordinate[] => {\n const session = sessionRef.current;\n if (isStampTool(tool)) {\n return buildStampCoords(tool, session.stampCenter);\n }\n if (tool === \"brush\") {\n return [];\n }\n if (!session.isDrawing) return [];\n\n if (tool === \"freehand\") {\n return session.points;\n }\n if (tool === \"rectangle\") {\n return createRectangle(session.start, session.current);\n }\n if (tool === \"circular\") {\n return createCircle(session.start, session.current);\n }\n\n return [];\n }, [tool, buildStampCoords]);\n\n const drawBrushStrokePreview = useCallback(\n (ctx: CanvasRenderingContext2D): void => {\n const session = sessionRef.current;\n if (!session.isDrawing || session.points.length === 0) return;\n\n const screenPoints = worldToScreenPoints(session.points);\n if (screenPoints.length === 0) return;\n const anchor = session.points[session.points.length - 1] ?? session.points[0];\n const radiusPx = worldRadiusToScreenPixels(anchor, resolvedBrushOptions.radius);\n if (!Number.isFinite(radiusPx) || radiusPx <= 0) return;\n\n ctx.save();\n ctx.globalAlpha = resolvedBrushOptions.fillOpacity;\n ctx.fillStyle = resolvedBrushOptions.fillColor;\n ctx.strokeStyle = resolvedBrushOptions.fillColor;\n ctx.lineCap = \"round\";\n ctx.lineJoin = \"round\";\n ctx.lineWidth = radiusPx * 2;\n if (screenPoints.length === 1) {\n ctx.beginPath();\n ctx.arc(screenPoints[0][0], screenPoints[0][1], radiusPx, 0, Math.PI * 2);\n ctx.fill();\n } else {\n ctx.beginPath();\n ctx.moveTo(screenPoints[0][0], screenPoints[0][1]);\n for (let i = 1; i < screenPoints.length; i += 1) {\n ctx.lineTo(screenPoints[i][0], screenPoints[i][1]);\n }\n ctx.stroke();\n }\n ctx.restore();\n },\n [worldToScreenPoints, worldRadiusToScreenPixels, resolvedBrushOptions]\n );\n\n const drawBrushCursor = useCallback(\n (ctx: CanvasRenderingContext2D): void => {\n const session = sessionRef.current;\n const cursor = session.cursor;\n if (!cursor) return;\n const screen = toCoord(projectorRef.current?.worldToScreen(cursor[0], cursor[1]) ?? []);\n if (!screen) return;\n const radiusPx = worldRadiusToScreenPixels(cursor, resolvedBrushOptions.radius);\n if (!Number.isFinite(radiusPx) || radiusPx <= 0) return;\n\n ctx.save();\n ctx.beginPath();\n ctx.arc(screen[0], screen[1], radiusPx, 0, Math.PI * 2);\n ctx.strokeStyle = session.isDrawing ? resolvedBrushOptions.cursorActiveColor : resolvedBrushOptions.cursorColor;\n ctx.lineWidth = resolvedBrushOptions.cursorLineWidth;\n ctx.setLineDash(resolvedBrushOptions.cursorLineDash);\n ctx.stroke();\n ctx.setLineDash(EMPTY_DASH);\n ctx.restore();\n },\n [projectorRef, worldRadiusToScreenPixels, resolvedBrushOptions]\n );\n\n const drawOverlay = useCallback(() => {\n resizeCanvas();\n\n const canvas = canvasRef.current;\n if (!canvas) return;\n\n const ctx = canvas.getContext(\"2d\");\n if (!ctx) return;\n\n const dpr = Math.max(1, window.devicePixelRatio || 1);\n const canvasWidth = canvas.width / dpr;\n const canvasHeight = canvas.height / dpr;\n ctx.setTransform(1, 0, 0, 1, 0, 0);\n ctx.clearRect(0, 0, canvas.width, canvas.height);\n ctx.setTransform(dpr, 0, 0, dpr, 0, 0);\n\n // Persisted ROI outlines always remain visible.\n if (mergedPersistedRegions.length > 0) {\n for (let i = 0; i < mergedPersistedRegions.length; i += 1) {\n const region = mergedPersistedRegions[i];\n const ring = region?.coordinates;\n if (!ring || ring.length < 3) continue;\n const closed = closeRing(ring);\n const screen = worldToScreenPoints(closed);\n if (screen.length >= 4) {\n const regionKey = region.id ?? i;\n const state: RegionStyleContext[\"state\"] = isSameRegionId(activeRegionId, regionKey) ? \"active\" : isSameRegionId(hoveredRegionId, regionKey) ? \"hover\" : \"default\";\n let strokeStyle = state === \"active\" ? resolvedActiveStrokeStyle : state === \"hover\" ? resolvedHoverStrokeStyle : resolvedStrokeStyle;\n\n if (resolveRegionStrokeStyle) {\n const resolved = resolveRegionStrokeStyle({\n region,\n regionId: regionKey,\n regionIndex: i,\n state,\n });\n strokeStyle = mergeStrokeStyle(strokeStyle, resolved || undefined);\n }\n drawPath(ctx, screen, strokeStyle, true, false);\n }\n }\n }\n\n if (mergedPatchRegions.length > 0) {\n for (let i = 0; i < mergedPatchRegions.length; i += 1) {\n const region = mergedPatchRegions[i];\n const ring = region?.coordinates;\n if (!ring || ring.length < 3) continue;\n const closed = closeRing(ring);\n const screen = worldToScreenPoints(closed);\n if (screen.length < 4) continue;\n drawPath(ctx, screen, resolvedPatchStrokeStyle, true, false);\n }\n }\n\n if (Array.isArray(overlayShapes) && overlayShapes.length > 0) {\n const debugOverlay = Boolean((globalThis as { __OPEN_PLANT_DEBUG_OVERLAY__?: boolean }).__OPEN_PLANT_DEBUG_OVERLAY__);\n const imageOuterRing = worldToScreenPoints(\n closeRing([\n [0, 0],\n [imageWidth, 0],\n [imageWidth, imageHeight],\n [0, imageHeight],\n ])\n );\n for (let i = 0; i < overlayShapes.length; i += 1) {\n const shape = overlayShapes[i];\n if (!shape?.coordinates?.length || shape.visible === false) continue;\n\n const closed = shape.closed ?? isNestedRingCoordinates(shape.coordinates);\n const renderRings = normalizeOverlayRings(shape.coordinates, closed);\n\n if (shape.invertedFill?.fillColor) {\n const holeRings: DrawCoordinate[][] = [];\n const closedRings = normalizeOverlayRings(shape.coordinates, true);\n for (const ring of closedRings) {\n const screen = worldToScreenPoints(ring);\n if (screen.length >= 4) {\n holeRings.push(screen);\n }\n }\n if (debugOverlay) {\n const debugKey = String(shape.id ?? i);\n const debugSignature = `${imageOuterRing.length}|${closedRings.length}|${holeRings.length}|${shape.invertedFill.fillColor}`;\n if (overlayDebugSnapshotRef.current.get(debugKey) !== debugSignature) {\n overlayDebugSnapshotRef.current.set(debugKey, debugSignature);\n console.debug(\"[open-plant] invertedFill\", {\n id: shape.id ?? i,\n outerRingPoints: imageOuterRing.length,\n sourceRingCount: closedRings.length,\n holeRingCount: holeRings.length,\n fillColor: shape.invertedFill.fillColor,\n });\n }\n }\n drawInvertedFillMask(ctx, imageOuterRing, holeRings, shape.invertedFill.fillColor);\n }\n\n if (renderRings.length === 0) continue;\n const strokeStyle = mergeStrokeStyle(resolvedStrokeStyle, shape.stroke ?? shape.strokeStyle);\n for (const ring of renderRings) {\n const screen = worldToScreenPoints(ring);\n if (screen.length < 2) continue;\n drawPath(ctx, screen, strokeStyle, closed, shape.fill ?? false);\n }\n }\n }\n\n if (active) {\n if (tool === \"brush\") {\n drawBrushStrokePreview(ctx);\n drawBrushCursor(ctx);\n } else {\n const preview = buildPreviewCoords();\n if (preview.length > 0) {\n if (tool === \"freehand\") {\n const line = worldToScreenPoints(preview);\n if (line.length >= 2) {\n drawPath(ctx, line, resolvedStrokeStyle, false, false);\n }\n if (line.length >= 3) {\n drawPath(ctx, worldToScreenPoints(closeRing(preview)), resolvedStrokeStyle, true, true);\n }\n } else {\n const polygon = worldToScreenPoints(preview);\n if (polygon.length >= 4) {\n drawPath(ctx, polygon, resolvedStrokeStyle, true, true);\n }\n }\n }\n }\n }\n\n // Draw labels last so they stay visually on top.\n if (mergedPersistedRegions.length > 0) {\n for (const region of mergedPersistedRegions) {\n if (!region.label) continue;\n const ring = region?.coordinates;\n if (!ring || ring.length < 3) continue;\n const closed = closeRing(ring);\n const anchorWorld = getTopAnchor(closed);\n if (!anchorWorld) continue;\n const anchorScreen = toCoord(projectorRef.current?.worldToScreen(anchorWorld[0], anchorWorld[1]) ?? []);\n if (!anchorScreen) continue;\n drawRegionLabel(ctx, region.label, anchorScreen, canvasWidth, canvasHeight, resolvedLabelStyle);\n }\n }\n }, [\n active,\n tool,\n buildPreviewCoords,\n drawBrushStrokePreview,\n drawBrushCursor,\n resizeCanvas,\n worldToScreenPoints,\n imageWidth,\n imageHeight,\n projectorRef,\n mergedPersistedRegions,\n overlayShapes,\n hoveredRegionId,\n activeRegionId,\n resolvedStrokeStyle,\n resolvedHoverStrokeStyle,\n resolvedActiveStrokeStyle,\n mergedPatchRegions,\n resolvedPatchStrokeStyle,\n resolveRegionStrokeStyle,\n resolvedLabelStyle,\n ]);\n\n const requestDraw = useCallback(() => {\n if (drawPendingRef.current) return;\n drawPendingRef.current = true;\n requestAnimationFrame(() => {\n drawPendingRef.current = false;\n drawOverlay();\n });\n }, [drawOverlay]);\n\n const resetSession = useCallback((preserveCursor = false) => {\n const session = sessionRef.current;\n const canvas = canvasRef.current;\n\n if (canvas && session.pointerId !== null && canvas.hasPointerCapture(session.pointerId)) {\n try {\n canvas.releasePointerCapture(session.pointerId);\n } catch {\n // noop\n }\n }\n\n session.isDrawing = false;\n session.pointerId = null;\n session.start = null;\n session.current = null;\n session.points = [];\n session.stampCenter = null;\n if (!preserveCursor) {\n session.cursor = null;\n }\n }, []);\n\n const toWorld = useCallback(\n (event: ReactPointerEvent<HTMLCanvasElement>): DrawCoordinate | null => {\n const projector = projectorRef.current;\n if (!projector || imageWidth <= 0 || imageHeight <= 0) return null;\n\n const raw = toCoord(projector.screenToWorld(event.clientX, event.clientY));\n if (!raw) return null;\n return clampWorld(raw, imageWidth, imageHeight);\n },\n [projectorRef, imageWidth, imageHeight]\n );\n\n const finishSession = useCallback(() => {\n const session = sessionRef.current;\n if (!session.isDrawing) {\n resetSession(true);\n requestDraw();\n return;\n }\n\n let coordinates: DrawCoordinate[] = [];\n if (tool === \"freehand\") {\n if (session.points.length >= FREEHAND_MIN_POINTS) {\n coordinates = closeRing(session.points);\n }\n } else if (tool === \"rectangle\") {\n coordinates = createRectangle(session.start, session.current);\n } else if (tool === \"circular\") {\n coordinates = createCircle(session.start, session.current);\n } else if (tool === \"brush\") {\n const zoom = Math.max(1e-6, projectorRef.current?.getViewState?.().zoom ?? 1);\n const minRasterStep = 0.75 / zoom;\n coordinates = buildBrushStrokePolygon(session.points, {\n radius: resolvedBrushOptions.radius,\n clipBounds: [0, 0, imageWidth, imageHeight],\n minRasterStep,\n simplifyTolerance: minRasterStep * 0.4,\n }) as DrawCoordinate[];\n }\n\n if ((tool === \"freehand\" || tool === \"rectangle\" || tool === \"circular\" || tool === \"brush\") && isValidPolygon(coordinates) && onDrawComplete) {\n const intent: DrawIntent = tool === \"brush\" ? \"brush\" : \"roi\";\n onDrawComplete({\n tool,\n intent,\n coordinates,\n bbox: computeBounds(coordinates),\n areaPx: polygonArea(coordinates),\n });\n }\n\n resetSession(true);\n requestDraw();\n }, [tool, onDrawComplete, resetSession, requestDraw, resolvedBrushOptions.radius, imageWidth, imageHeight]);\n\n const handleStampAt = useCallback(\n (stampTool: StampDrawTool, center: DrawCoordinate): void => {\n const coordinates = buildStampCoords(stampTool, center);\n if (!isValidPolygon(coordinates)) return;\n const intent: DrawIntent = stampTool === \"stamp-rectangle-4096px\" ? \"patch\" : \"roi\";\n const result: DrawResult = {\n tool: stampTool,\n intent,\n coordinates,\n bbox: computeBounds(coordinates),\n areaPx: polygonArea(coordinates),\n };\n onDrawComplete?.(result);\n if (intent === \"patch\" && onPatchComplete) {\n onPatchComplete(result as PatchDrawResult);\n }\n },\n [buildStampCoords, onDrawComplete, onPatchComplete]\n );\n\n const appendBrushPoint = useCallback(\n (session: DrawSession, world: DrawCoordinate): void => {\n const projector = projectorRef.current;\n const zoom = Math.max(1e-6, projector?.getViewState?.().zoom ?? 1);\n const minWorldStep = BRUSH_SCREEN_STEP / zoom;\n const minWorldStep2 = minWorldStep * minWorldStep;\n const prev = session.points[session.points.length - 1];\n if (!prev) {\n session.points.push(world);\n session.current = world;\n return;\n }\n const dx = world[0] - prev[0];\n const dy = world[1] - prev[1];\n if (dx * dx + dy * dy >= minWorldStep2) {\n session.points.push(world);\n } else {\n session.points[session.points.length - 1] = world;\n }\n session.current = world;\n },\n [projectorRef]\n );\n\n const handlePointerDown = useCallback(\n (event: ReactPointerEvent<HTMLCanvasElement>) => {\n if (!active) return;\n if (tool === \"cursor\") return;\n if (event.button !== 0) return;\n\n const world = toWorld(event);\n if (!world) return;\n\n event.preventDefault();\n event.stopPropagation();\n\n if (isStampTool(tool)) {\n const session = sessionRef.current;\n session.stampCenter = world;\n handleStampAt(tool, world);\n requestDraw();\n return;\n }\n\n const canvas = canvasRef.current;\n if (canvas) {\n canvas.setPointerCapture(event.pointerId);\n }\n\n const session = sessionRef.current;\n session.isDrawing = true;\n session.pointerId = event.pointerId;\n session.start = world;\n session.current = world;\n session.cursor = world;\n session.points = tool === \"freehand\" || tool === \"brush\" ? [world] : [];\n requestDraw();\n },\n [active, tool, toWorld, handleStampAt, requestDraw]\n );\n\n const handlePointerMove = useCallback(\n (event: ReactPointerEvent<HTMLCanvasElement>) => {\n if (!active) return;\n if (tool === \"cursor\") return;\n\n const world = toWorld(event);\n if (!world) return;\n\n if (isStampTool(tool)) {\n const session = sessionRef.current;\n session.stampCenter = world;\n event.preventDefault();\n event.stopPropagation();\n requestDraw();\n return;\n }\n\n const session = sessionRef.current;\n if (tool === \"brush\") {\n session.cursor = world;\n if (!session.isDrawing || session.pointerId !== event.pointerId) {\n requestDraw();\n return;\n }\n event.preventDefault();\n event.stopPropagation();\n appendBrushPoint(session, world);\n requestDraw();\n return;\n }\n\n if (!session.isDrawing || session.pointerId !== event.pointerId) {\n return;\n }\n event.preventDefault();\n event.stopPropagation();\n\n if (tool === \"freehand\") {\n const projector = projectorRef.current;\n const zoom = Math.max(1e-6, projector?.getViewState?.().zoom ?? 1);\n const minWorldStep = FREEHAND_SCREEN_STEP / zoom;\n const minWorldStep2 = minWorldStep * minWorldStep;\n const prev = session.points[session.points.length - 1];\n\n if (!prev) {\n session.points.push(world);\n } else {\n const dx = world[0] - prev[0];\n const dy = world[1] - prev[1];\n if (dx * dx + dy * dy >= minWorldStep2) {\n session.points.push(world);\n }\n }\n } else {\n session.current = world;\n }\n\n requestDraw();\n },\n [active, tool, toWorld, requestDraw, projectorRef, appendBrushPoint]\n );\n\n const handlePointerUp = useCallback(\n (event: ReactPointerEvent<HTMLCanvasElement>) => {\n const session = sessionRef.current;\n if (!session.isDrawing || session.pointerId !== event.pointerId) return;\n\n event.preventDefault();\n event.stopPropagation();\n const world = toWorld(event);\n if (world) {\n session.cursor = world;\n if (tool === \"brush\") {\n appendBrushPoint(session, world);\n } else {\n session.current = world;\n }\n }\n const canvas = canvasRef.current;\n if (canvas && canvas.hasPointerCapture(event.pointerId)) {\n try {\n canvas.releasePointerCapture(event.pointerId);\n } catch {\n // noop\n }\n }\n\n finishSession();\n },\n [finishSession, toWorld, tool, appendBrushPoint]\n );\n\n const handlePointerLeave = useCallback(() => {\n const session = sessionRef.current;\n let changed = false;\n if (tool === \"brush\" && !session.isDrawing && session.cursor) {\n session.cursor = null;\n changed = true;\n }\n if (isStampTool(tool) && session.stampCenter) {\n session.stampCenter = null;\n changed = true;\n }\n if (changed) {\n requestDraw();\n }\n }, [tool, requestDraw]);\n\n useEffect(() => {\n resizeCanvas();\n requestDraw();\n\n const canvas = canvasRef.current;\n if (!canvas) return undefined;\n\n const observer = new ResizeObserver(() => {\n resizeCanvas();\n requestDraw();\n });\n observer.observe(canvas);\n\n return () => {\n observer.disconnect();\n };\n }, [resizeCanvas, requestDraw]);\n\n useEffect(() => {\n if (!active) {\n resetSession();\n }\n requestDraw();\n }, [active, requestDraw, resetSession]);\n\n useEffect(() => {\n if (lastToolRef.current === tool) {\n return;\n }\n lastToolRef.current = tool;\n resetSession();\n requestDraw();\n }, [tool, resetSession, requestDraw]);\n\n useEffect(() => {\n requestDraw();\n }, [viewStateSignal, mergedPersistedRegions, overlayShapes, requestDraw]);\n\n useEffect(() => {\n if (!invalidateRef) return undefined;\n invalidateRef.current = requestDraw;\n return () => {\n if (invalidateRef.current === requestDraw) {\n invalidateRef.current = null;\n }\n };\n }, [invalidateRef, requestDraw]);\n\n useEffect(() => {\n if (!active) return undefined;\n\n const onKeyDown = (event: KeyboardEvent): void => {\n if (event.key !== \"Escape\") return;\n resetSession();\n requestDraw();\n };\n\n window.addEventListener(\"keydown\", onKeyDown);\n return () => {\n window.removeEventListener(\"keydown\", onKeyDown);\n };\n }, [active, resetSession, requestDraw]);\n\n return (\n <canvas\n ref={canvasRef}\n className={className}\n style={mergedStyle}\n onPointerDown={handlePointerDown}\n onPointerMove={handlePointerMove}\n onPointerUp={handlePointerUp}\n onPointerCancel={handlePointerUp}\n onPointerLeave={handlePointerLeave}\n onContextMenu={event => {\n if (active) event.preventDefault();\n }}\n onWheel={event => {\n if (!active) return;\n const canvas = canvasRef.current;\n const projector = projectorRef.current;\n if (!canvas || typeof projector?.zoomBy !== \"function\") return;\n event.preventDefault();\n event.stopPropagation();\n const rect = canvas.getBoundingClientRect();\n const screenX = event.clientX - rect.left;\n const screenY = event.clientY - rect.top;\n projector.zoomBy(event.deltaY < 0 ? WHEEL_ZOOM_IN_FACTOR : WHEEL_ZOOM_OUT_FACTOR, screenX, screenY);\n requestDraw();\n }}\n />\n );\n}\n","import type { WsiImageSource, WsiTerm } from \"./types\";\n\nfunction trimTrailingSlash(value: string): string {\n return String(value ?? \"\").replace(/\\/+$/, \"\");\n}\n\nfunction ensureLeadingSlash(value: string): string {\n const raw = String(value ?? \"\");\n return raw.startsWith(\"/\") ? raw : `/${raw}`;\n}\n\nfunction joinImsTileRoot(tileBaseUrl: string): string {\n const base = trimTrailingSlash(tileBaseUrl);\n if (!base) return \"\";\n\n // Explicit TileGroup path already provided.\n if (/\\/TileGroup\\d+$/i.test(base)) return base;\n\n let parsed: URL | null = null;\n try {\n parsed = new URL(base);\n } catch {\n parsed = null;\n }\n\n if (parsed) {\n const origin = `${parsed.protocol}//${parsed.host}`;\n const path = trimTrailingSlash(parsed.pathname || \"\");\n\n // If caller passes /ims, keep /ims and append image path directly:\n // /ims + /tiles/<hash> + /tier/y_x.webp\n if (/\\/ims$/i.test(path)) return `${origin}${path}`;\n if (/\\/tiles$/i.test(path)) return `${origin}${path}`;\n return `${origin}${path}/tiles`;\n }\n\n // Relative path mode\n if (/\\/ims$/i.test(base)) return `/ims`;\n if (/\\/tiles$/i.test(base)) return `${base}`;\n return `${base}/tiles`;\n}\n\nexport function normalizeImageInfo(raw: any, tileBaseUrl: string): WsiImageSource {\n const ims = raw?.imsInfo || {};\n const isIms = !!raw?.imsInfo;\n\n const width = Number(ims.width ?? raw?.width ?? 0);\n const height = Number(ims.height ?? raw?.height ?? 0);\n const tileSize = Number(ims.tileSize ?? raw?.tileSize ?? 0);\n const maxTierZoom = Number(ims.zoom ?? raw?.zoom ?? 0);\n const tilePath = String(ims.path ?? raw?.path ?? \"\");\n const mpp = Number(ims.mpp ?? raw?.mpp ?? 0);\n\n if (!width || !height || !tileSize || !tilePath) {\n throw new Error(\"이미지 메타데이터가 불완전합니다. width/height/tileSize/path 확인 필요\");\n }\n\n const terms: WsiTerm[] = Array.isArray(raw?.terms)\n ? raw.terms.map((term: any) => ({\n termId: String(term?.termId ?? \"\"),\n termName: String(term?.termName ?? \"\"),\n termColor: String(term?.termColor ?? \"\"),\n }))\n : [];\n\n const normalizedPath = ensureLeadingSlash(tilePath);\n const imsTileRoot = joinImsTileRoot(tileBaseUrl);\n const tileUrlBuilder = isIms ? (tier: number, x: number, y: number): string => `${imsTileRoot}${normalizedPath}/${tier}/${y}_${x}.webp` : undefined;\n\n return {\n id: raw?._id || \"unknown\",\n name: raw?.name || \"unknown\",\n width,\n height,\n mpp: Number.isFinite(mpp) && mpp > 0 ? mpp : undefined,\n tileSize,\n maxTierZoom: Number.isFinite(maxTierZoom) ? Math.max(0, Math.floor(maxTierZoom)) : 0,\n tilePath,\n tileBaseUrl,\n terms,\n tileUrlBuilder,\n };\n}\n\nexport function toTileUrl(source: Pick<WsiImageSource, \"tilePath\" | \"tileBaseUrl\" | \"tileUrlBuilder\">, tier: number, x: number, y: number): string {\n if (source.tileUrlBuilder) {\n return source.tileUrlBuilder(tier, x, y);\n }\n const normalizedPath = ensureLeadingSlash(source.tilePath);\n return `${source.tileBaseUrl}${normalizedPath}/${tier}/${y}_${x}.webp`;\n}\n","import {\n\ttype CSSProperties,\n\ttype MutableRefObject,\n\ttype PointerEvent as ReactPointerEvent,\n\ttype RefObject,\n\tuseCallback,\n\tuseEffect,\n\tuseMemo,\n\tuseRef,\n} from \"react\";\nimport { toTileUrl } from \"../wsi/image-info\";\nimport type { WsiImageSource, WsiViewState } from \"../wsi/types\";\nimport { clamp } from \"../wsi/utils\";\n\ntype Bounds = [number, number, number, number];\n\nexport interface OverviewMapProjector {\n\tgetViewState: () => WsiViewState;\n\tsetViewState: (next: Partial<WsiViewState>) => void;\n\tsetViewCenter?: (worldX: number, worldY: number) => void;\n\tgetViewBounds?: () => number[];\n\tgetViewCorners?: () => Array<[number, number]>;\n}\n\nexport type OverviewMapPosition =\n\t| \"bottom-right\"\n\t| \"bottom-left\"\n\t| \"top-right\"\n\t| \"top-left\";\n\nexport interface OverviewMapOptions {\n\twidth: number;\n\theight: number;\n\tmargin: number;\n\tposition: OverviewMapPosition;\n\tborderRadius: number;\n\tborderWidth: number;\n\tbackgroundColor: string;\n\tborderColor: string;\n\tviewportStrokeColor: string;\n\tviewportFillColor: string;\n\tinteractive: boolean;\n\tshowThumbnail: boolean;\n\tmaxThumbnailTiles: number;\n}\n\nexport interface OverviewMapProps {\n\tsource: WsiImageSource;\n\tprojectorRef: RefObject<OverviewMapProjector | null>;\n\tauthToken?: string;\n\toptions?: Partial<OverviewMapOptions>;\n\tinvalidateRef?: MutableRefObject<(() => void) | null>;\n\tclassName?: string;\n\tstyle?: CSSProperties;\n}\n\nconst DEFAULT_OVERVIEW_MAP_OPTIONS: OverviewMapOptions = {\n\twidth: 220,\n\theight: 140,\n\tmargin: 16,\n\tposition: \"bottom-right\",\n\tborderRadius: 10,\n\tborderWidth: 1.5,\n\tbackgroundColor: \"rgba(4, 10, 18, 0.88)\",\n\tborderColor: \"rgba(230, 244, 255, 0.35)\",\n\tviewportStrokeColor: \"rgba(255, 106, 61, 0.95)\",\n\tviewportFillColor: \"rgba(255, 106, 61, 0.2)\",\n\tinteractive: true,\n\tshowThumbnail: true,\n\tmaxThumbnailTiles: 16,\n};\n\nfunction toPositiveNumber(\n\tvalue: number | undefined,\n\tfallback: number,\n\tmin = 1,\n): number {\n\tif (typeof value !== \"number\" || !Number.isFinite(value)) return fallback;\n\treturn Math.max(min, value);\n}\n\nfunction isFiniteBounds(bounds: number[] | null | undefined): bounds is Bounds {\n\treturn (\n\t\tArray.isArray(bounds) &&\n\t\tbounds.length === 4 &&\n\t\tNumber.isFinite(bounds[0]) &&\n\t\tNumber.isFinite(bounds[1]) &&\n\t\tNumber.isFinite(bounds[2]) &&\n\t\tNumber.isFinite(bounds[3])\n\t);\n}\n\nexport function OverviewMap({\n\tsource,\n\tprojectorRef,\n\tauthToken = \"\",\n\toptions,\n\tinvalidateRef,\n\tclassName,\n\tstyle,\n}: OverviewMapProps): React.ReactElement {\n\tconst canvasRef = useRef<HTMLCanvasElement | null>(null);\n\tconst thumbnailRef = useRef<HTMLCanvasElement | null>(null);\n\tconst lastBoundsRef = useRef<Bounds | null>(null);\n\tconst draggingRef = useRef<{ active: boolean; pointerId: number | null }>({\n\t\tactive: false,\n\t\tpointerId: null,\n\t});\n\tconst rafRef = useRef<number | null>(null);\n\tconst drawPendingRef = useRef(false);\n\n\tconst width = toPositiveNumber(\n\t\toptions?.width,\n\t\tDEFAULT_OVERVIEW_MAP_OPTIONS.width,\n\t\t64,\n\t);\n\tconst height = toPositiveNumber(\n\t\toptions?.height,\n\t\tDEFAULT_OVERVIEW_MAP_OPTIONS.height,\n\t\t48,\n\t);\n\tconst margin = toPositiveNumber(\n\t\toptions?.margin,\n\t\tDEFAULT_OVERVIEW_MAP_OPTIONS.margin,\n\t\t0,\n\t);\n\tconst borderRadius = toPositiveNumber(\n\t\toptions?.borderRadius,\n\t\tDEFAULT_OVERVIEW_MAP_OPTIONS.borderRadius,\n\t\t0,\n\t);\n\tconst borderWidth = toPositiveNumber(\n\t\toptions?.borderWidth,\n\t\tDEFAULT_OVERVIEW_MAP_OPTIONS.borderWidth,\n\t\t0,\n\t);\n\tconst maxThumbnailTiles = Math.max(\n\t\t1,\n\t\tMath.round(\n\t\t\ttoPositiveNumber(\n\t\t\t\toptions?.maxThumbnailTiles,\n\t\t\t\tDEFAULT_OVERVIEW_MAP_OPTIONS.maxThumbnailTiles,\n\t\t\t\t1,\n\t\t\t),\n\t\t),\n\t);\n\n\tconst backgroundColor =\n\t\toptions?.backgroundColor || DEFAULT_OVERVIEW_MAP_OPTIONS.backgroundColor;\n\tconst borderColor =\n\t\toptions?.borderColor || DEFAULT_OVERVIEW_MAP_OPTIONS.borderColor;\n\tconst viewportStrokeColor =\n\t\toptions?.viewportStrokeColor ||\n\t\tDEFAULT_OVERVIEW_MAP_OPTIONS.viewportStrokeColor;\n\tconst viewportFillColor =\n\t\toptions?.viewportFillColor ||\n\t\tDEFAULT_OVERVIEW_MAP_OPTIONS.viewportFillColor;\n\tconst interactive =\n\t\toptions?.interactive ?? DEFAULT_OVERVIEW_MAP_OPTIONS.interactive;\n\tconst showThumbnail =\n\t\toptions?.showThumbnail ?? DEFAULT_OVERVIEW_MAP_OPTIONS.showThumbnail;\n\tconst position =\n\t\toptions?.position || DEFAULT_OVERVIEW_MAP_OPTIONS.position;\n\n\tconst mergedStyle = useMemo<CSSProperties>(() => {\n\t\tconst pos: CSSProperties = {};\n\t\tif (position === \"top-left\" || position === \"bottom-left\") pos.left = margin;\n\t\telse pos.right = margin;\n\t\tif (position === \"top-left\" || position === \"top-right\") pos.top = margin;\n\t\telse pos.bottom = margin;\n\n\t\treturn {\n\t\t\tposition: \"absolute\",\n\t\t\t...pos,\n\t\t\twidth,\n\t\t\theight,\n\t\t\tborderRadius,\n\t\t\toverflow: \"hidden\",\n\t\t\tzIndex: 4,\n\t\t\tpointerEvents: interactive ? \"auto\" : \"none\",\n\t\t\ttouchAction: \"none\",\n\t\t\tboxShadow: \"0 10px 22px rgba(0, 0, 0, 0.3)\",\n\t\t\t...style,\n\t\t};\n\t}, [margin, position, width, height, borderRadius, interactive, style]);\n\n\tconst draw = useCallback(() => {\n\t\tconst canvas = canvasRef.current;\n\t\tif (!canvas) return;\n\n\t\tconst ctx = canvas.getContext(\"2d\");\n\t\tif (!ctx) return;\n\n\t\tconst cssW = width;\n\t\tconst cssH = height;\n\t\tconst dpr = Math.max(1, window.devicePixelRatio || 1);\n\n\t\tconst pixelW = Math.max(1, Math.round(cssW * dpr));\n\t\tconst pixelH = Math.max(1, Math.round(cssH * dpr));\n\t\tif (canvas.width !== pixelW || canvas.height !== pixelH) {\n\t\t\tcanvas.width = pixelW;\n\t\t\tcanvas.height = pixelH;\n\t\t}\n\n\t\tctx.setTransform(1, 0, 0, 1, 0, 0);\n\t\tctx.clearRect(0, 0, canvas.width, canvas.height);\n\t\tctx.setTransform(dpr, 0, 0, dpr, 0, 0);\n\n\t\tctx.fillStyle = backgroundColor;\n\t\tctx.fillRect(0, 0, cssW, cssH);\n\n\t\tconst preview = thumbnailRef.current;\n\t\tif (preview) {\n\t\t\tctx.drawImage(preview, 0, 0, cssW, cssH);\n\t\t}\n\n\t\tctx.strokeStyle = borderColor;\n\t\tctx.lineWidth = borderWidth;\n\t\tctx.strokeRect(\n\t\t\tborderWidth * 0.5,\n\t\t\tborderWidth * 0.5,\n\t\t\tcssW - borderWidth,\n\t\t\tcssH - borderWidth,\n\t\t);\n\n\t\tconst projector = projectorRef.current;\n\t\tconst bounds = projector?.getViewBounds?.();\n\t\tconst corners = projector?.getViewCorners?.();\n\t\tconst safeBounds = isFiniteBounds(bounds)\n\t\t\t? bounds\n\t\t\t: isFiniteBounds(lastBoundsRef.current)\n\t\t\t\t? lastBoundsRef.current\n\t\t\t\t: null;\n\t\tif (!safeBounds) return;\n\t\tlastBoundsRef.current = safeBounds;\n\n\t\tconst sx = cssW / Math.max(1, source.width);\n\t\tconst sy = cssH / Math.max(1, source.height);\n\n\t\tconst safeCorners =\n\t\t\tArray.isArray(corners) &&\n\t\t\tcorners.length >= 4 &&\n\t\t\tcorners.every(\n\t\t\t\t(point) =>\n\t\t\t\t\tArray.isArray(point) &&\n\t\t\t\t\tpoint.length >= 2 &&\n\t\t\t\t\tNumber.isFinite(point[0]) &&\n\t\t\t\t\tNumber.isFinite(point[1]),\n\t\t\t)\n\t\t\t\t? (corners as Array<[number, number]>)\n\t\t\t\t: null;\n\n\t\tif (safeCorners) {\n\t\t\tctx.beginPath();\n\t\t\tfor (let i = 0; i < safeCorners.length; i += 1) {\n\t\t\t\tconst point = safeCorners[i];\n\t\t\t\tconst x = clamp(point[0] * sx, 0, cssW);\n\t\t\t\tconst y = clamp(point[1] * sy, 0, cssH);\n\t\t\t\tif (i === 0) ctx.moveTo(x, y);\n\t\t\t\telse ctx.lineTo(x, y);\n\t\t\t}\n\t\t\tctx.closePath();\n\t\t\tctx.fillStyle = viewportFillColor;\n\t\t\tctx.fill();\n\t\t\tctx.strokeStyle = viewportStrokeColor;\n\t\t\tctx.lineWidth = 1.5;\n\t\t\tctx.stroke();\n\t\t\treturn;\n\t\t}\n\n\t\tconst left = clamp(safeBounds[0] * sx, 0, cssW);\n\t\tconst top = clamp(safeBounds[1] * sy, 0, cssH);\n\t\tconst right = clamp(safeBounds[2] * sx, 0, cssW);\n\t\tconst bottom = clamp(safeBounds[3] * sy, 0, cssH);\n\t\tconst rectW = Math.max(1, right - left);\n\t\tconst rectH = Math.max(1, bottom - top);\n\n\t\tctx.fillStyle = viewportFillColor;\n\t\tctx.fillRect(left, top, rectW, rectH);\n\n\t\tctx.strokeStyle = viewportStrokeColor;\n\t\tctx.lineWidth = 1.5;\n\t\tctx.strokeRect(\n\t\t\tleft + 0.5,\n\t\t\ttop + 0.5,\n\t\t\tMath.max(1, rectW - 1),\n\t\t\tMath.max(1, rectH - 1),\n\t\t);\n\t}, [\n\t\twidth,\n\t\theight,\n\t\tbackgroundColor,\n\t\tborderColor,\n\t\tborderWidth,\n\t\tprojectorRef,\n\t\tsource.width,\n\t\tsource.height,\n\t\tviewportFillColor,\n\t\tviewportStrokeColor,\n\t]);\n\n\tconst requestDraw = useCallback(() => {\n\t\tif (drawPendingRef.current) return;\n\t\tdrawPendingRef.current = true;\n\t\trafRef.current = requestAnimationFrame(() => {\n\t\t\tdrawPendingRef.current = false;\n\t\t\trafRef.current = null;\n\t\t\tdraw();\n\t\t});\n\t}, [draw]);\n\n\tconst toWorldFromClient = useCallback(\n\t\t(clientX: number, clientY: number): [number, number] | null => {\n\t\t\tconst canvas = canvasRef.current;\n\t\t\tif (!canvas) return null;\n\n\t\t\tconst rect = canvas.getBoundingClientRect();\n\t\t\tif (!rect.width || !rect.height) return null;\n\n\t\t\tconst nx = clamp((clientX - rect.left) / rect.width, 0, 1);\n\t\t\tconst ny = clamp((clientY - rect.top) / rect.height, 0, 1);\n\t\t\treturn [nx * source.width, ny * source.height];\n\t\t},\n\t\t[source.width, source.height],\n\t);\n\n\tconst recenterTo = useCallback(\n\t\t(worldX: number, worldY: number) => {\n\t\t\tconst projector = projectorRef.current;\n\t\t\tif (!projector) return;\n\n\t\t\tif (projector.setViewCenter) {\n\t\t\t\tprojector.setViewCenter(worldX, worldY);\n\t\t\t\trequestDraw();\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst bounds = projector.getViewBounds?.();\n\t\t\tconst safeBounds = isFiniteBounds(bounds)\n\t\t\t\t? bounds\n\t\t\t\t: isFiniteBounds(lastBoundsRef.current)\n\t\t\t\t\t? lastBoundsRef.current\n\t\t\t\t\t: null;\n\t\t\tif (!safeBounds) return;\n\n\t\t\tconst visibleW = Math.max(1e-6, safeBounds[2] - safeBounds[0]);\n\t\t\tconst visibleH = Math.max(1e-6, safeBounds[3] - safeBounds[1]);\n\n\t\t\tprojector.setViewState({\n\t\t\t\toffsetX: worldX - visibleW * 0.5,\n\t\t\t\toffsetY: worldY - visibleH * 0.5,\n\t\t\t});\n\t\t\trequestDraw();\n\t\t},\n\t\t[projectorRef, requestDraw],\n\t);\n\n\tconst handlePointerDown = useCallback(\n\t\t(event: ReactPointerEvent<HTMLCanvasElement>) => {\n\t\t\tif (!interactive) return;\n\t\t\tif (event.button !== 0) return;\n\n\t\t\tconst canvas = canvasRef.current;\n\t\t\tif (!canvas) return;\n\n\t\t\tconst world = toWorldFromClient(event.clientX, event.clientY);\n\t\t\tif (!world) return;\n\n\t\t\tevent.preventDefault();\n\t\t\tevent.stopPropagation();\n\n\t\t\tcanvas.setPointerCapture(event.pointerId);\n\t\t\tdraggingRef.current = { active: true, pointerId: event.pointerId };\n\t\t\trecenterTo(world[0], world[1]);\n\t\t},\n\t\t[interactive, toWorldFromClient, recenterTo],\n\t);\n\n\tconst handlePointerMove = useCallback(\n\t\t(event: ReactPointerEvent<HTMLCanvasElement>) => {\n\t\t\tconst drag = draggingRef.current;\n\t\t\tif (!drag.active || drag.pointerId !== event.pointerId) return;\n\n\t\t\tconst world = toWorldFromClient(event.clientX, event.clientY);\n\t\t\tif (!world) return;\n\n\t\t\tevent.preventDefault();\n\t\t\tevent.stopPropagation();\n\t\t\trecenterTo(world[0], world[1]);\n\t\t},\n\t\t[toWorldFromClient, recenterTo],\n\t);\n\n\tconst handlePointerUp = useCallback(\n\t\t(event: ReactPointerEvent<HTMLCanvasElement>) => {\n\t\t\tconst drag = draggingRef.current;\n\t\t\tif (!drag.active || drag.pointerId !== event.pointerId) return;\n\n\t\t\tconst canvas = canvasRef.current;\n\t\t\tif (canvas && canvas.hasPointerCapture(event.pointerId)) {\n\t\t\t\ttry {\n\t\t\t\t\tcanvas.releasePointerCapture(event.pointerId);\n\t\t\t\t} catch {\n\t\t\t\t\t// noop\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tdraggingRef.current = { active: false, pointerId: null };\n\t\t\trequestDraw();\n\t\t},\n\t\t[requestDraw],\n\t);\n\n\tuseEffect(() => {\n\t\tlet cancelled = false;\n\t\tthumbnailRef.current = null;\n\t\trequestDraw();\n\n\t\tconst tier = 0;\n\t\tconst levelScale = 2 ** (source.maxTierZoom - tier);\n\t\tconst levelWidth = Math.ceil(source.width / levelScale);\n\t\tconst levelHeight = Math.ceil(source.height / levelScale);\n\t\tconst tilesX = Math.max(1, Math.ceil(levelWidth / source.tileSize));\n\t\tconst tilesY = Math.max(1, Math.ceil(levelHeight / source.tileSize));\n\t\tconst tileCount = tilesX * tilesY;\n\n\t\tif (!showThumbnail || tileCount > maxThumbnailTiles) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tconst preview = document.createElement(\"canvas\");\n\t\tpreview.width = Math.max(1, Math.round(width));\n\t\tpreview.height = Math.max(1, Math.round(height));\n\t\tconst ctx = preview.getContext(\"2d\");\n\t\tif (!ctx) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tctx.fillStyle = backgroundColor;\n\t\tctx.fillRect(0, 0, preview.width, preview.height);\n\n\t\tconst requests: Array<{\n\t\t\turl: string;\n\t\t\tbounds: Bounds;\n\t\t}> = [];\n\n\t\tfor (let y = 0; y < tilesY; y += 1) {\n\t\t\tfor (let x = 0; x < tilesX; x += 1) {\n\t\t\t\tconst left = x * source.tileSize * levelScale;\n\t\t\t\tconst top = y * source.tileSize * levelScale;\n\t\t\t\tconst right =\n\t\t\t\t\tMath.min((x + 1) * source.tileSize, levelWidth) * levelScale;\n\t\t\t\tconst bottom =\n\t\t\t\t\tMath.min((y + 1) * source.tileSize, levelHeight) * levelScale;\n\t\t\t\trequests.push({\n\t\t\t\t\turl: toTileUrl(source, tier, x, y),\n\t\t\t\t\tbounds: [left, top, right, bottom],\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\tvoid Promise.allSettled(\n\t\t\trequests.map(async (tile) => {\n\t\t\t\tconst useAuthHeader = !!authToken;\n\t\t\t\tconst response = await fetch(tile.url, {\n\t\t\t\t\theaders: useAuthHeader ? { Authorization: authToken } : undefined,\n\t\t\t\t});\n\t\t\t\tif (!response.ok) {\n\t\t\t\t\tthrow new Error(`HTTP ${response.status}`);\n\t\t\t\t}\n\t\t\t\tconst bitmap = await createImageBitmap(await response.blob());\n\t\t\t\treturn { tile, bitmap };\n\t\t\t}),\n\t\t).then((results) => {\n\t\t\tif (cancelled) {\n\t\t\t\tfor (const result of results) {\n\t\t\t\t\tif (result.status === \"fulfilled\") {\n\t\t\t\t\t\tresult.value.bitmap.close();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst sx = preview.width / Math.max(1, source.width);\n\t\t\tconst sy = preview.height / Math.max(1, source.height);\n\t\t\tfor (const result of results) {\n\t\t\t\tif (result.status !== \"fulfilled\") continue;\n\t\t\t\tconst {\n\t\t\t\t\ttile: { bounds },\n\t\t\t\t\tbitmap,\n\t\t\t\t} = result.value;\n\t\t\t\tconst dx = bounds[0] * sx;\n\t\t\t\tconst dy = bounds[1] * sy;\n\t\t\t\tconst dw = Math.max(1, (bounds[2] - bounds[0]) * sx);\n\t\t\t\tconst dh = Math.max(1, (bounds[3] - bounds[1]) * sy);\n\t\t\t\tctx.drawImage(bitmap, dx, dy, dw, dh);\n\t\t\t\tbitmap.close();\n\t\t\t}\n\n\t\t\tthumbnailRef.current = preview;\n\t\t\trequestDraw();\n\t\t});\n\n\t\treturn () => {\n\t\t\tcancelled = true;\n\t\t};\n\t}, [\n\t\tsource,\n\t\tauthToken,\n\t\twidth,\n\t\theight,\n\t\tbackgroundColor,\n\t\tshowThumbnail,\n\t\tmaxThumbnailTiles,\n\t\trequestDraw,\n\t]);\n\n\tuseEffect(() => {\n\t\trequestDraw();\n\t}, [requestDraw]);\n\n\tuseEffect(() => {\n\t\tif (!invalidateRef) return undefined;\n\t\tinvalidateRef.current = requestDraw;\n\t\treturn () => {\n\t\t\tif (invalidateRef.current === requestDraw) {\n\t\t\t\tinvalidateRef.current = null;\n\t\t\t}\n\t\t};\n\t}, [invalidateRef, requestDraw]);\n\n\tuseEffect(\n\t\t() => () => {\n\t\t\tdraggingRef.current = { active: false, pointerId: null };\n\t\t\tif (rafRef.current !== null) {\n\t\t\t\tcancelAnimationFrame(rafRef.current);\n\t\t\t\trafRef.current = null;\n\t\t\t}\n\t\t\tdrawPendingRef.current = false;\n\t\t},\n\t\t[],\n\t);\n\n\treturn (\n\t\t<canvas\n\t\t\tref={canvasRef}\n\t\t\tclassName={className}\n\t\t\tstyle={mergedStyle}\n\t\t\tonPointerDown={handlePointerDown}\n\t\t\tonPointerMove={handlePointerMove}\n\t\t\tonPointerUp={handlePointerUp}\n\t\t\tonPointerCancel={handlePointerUp}\n\t\t\tonContextMenu={(event) => {\n\t\t\t\tevent.preventDefault();\n\t\t\t}}\n\t\t\tonWheel={(event) => {\n\t\t\t\tevent.preventDefault();\n\t\t\t\tevent.stopPropagation();\n\t\t\t}}\n\t\t/>\n\t);\n}\n","import { type CSSProperties, useEffect, useMemo, useRef } from \"react\";\nimport { M1TileRenderer } from \"../core/m1-tile-renderer\";\nimport type { ViewState } from \"../core/ortho-camera\";\nimport type { TileDefinition } from \"../core/types\";\n\nexport interface TileViewerCanvasProps {\n\timageWidth: number;\n\timageHeight: number;\n\ttiles: TileDefinition[];\n\tviewState?: Partial<ViewState>;\n\tclassName?: string;\n\tstyle?: CSSProperties;\n}\n\nexport function TileViewerCanvas({\n\timageWidth,\n\timageHeight,\n\ttiles,\n\tviewState,\n\tclassName,\n\tstyle,\n}: TileViewerCanvasProps): React.ReactElement {\n\tconst canvasRef = useRef<HTMLCanvasElement | null>(null);\n\tconst rendererRef = useRef<M1TileRenderer | null>(null);\n\tconst mergedStyle = useMemo(\n\t\t() => ({ width: \"100%\", height: \"100%\", display: \"block\", ...style }),\n\t\t[style],\n\t);\n\n\tuseEffect(() => {\n\t\tconst canvas = canvasRef.current;\n\t\tif (!canvas) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst renderer = new M1TileRenderer({\n\t\t\tcanvas,\n\t\t\timageWidth,\n\t\t\timageHeight,\n\t\t\tinitialViewState: viewState,\n\t\t});\n\n\t\trendererRef.current = renderer;\n\t\tvoid renderer.setTiles(tiles);\n\n\t\treturn () => {\n\t\t\trenderer.destroy();\n\t\t\trendererRef.current = null;\n\t\t};\n\t}, [imageWidth, imageHeight]);\n\n\tuseEffect(() => {\n\t\tconst renderer = rendererRef.current;\n\t\tif (!renderer) {\n\t\t\treturn;\n\t\t}\n\n\t\tvoid renderer.setTiles(tiles);\n\t}, [tiles]);\n\n\tuseEffect(() => {\n\t\tconst renderer = rendererRef.current;\n\t\tif (!renderer || !viewState) {\n\t\t\treturn;\n\t\t}\n\n\t\trenderer.setViewState(viewState);\n\t}, [viewState]);\n\n\treturn <canvas ref={canvasRef} className={className} style={mergedStyle} />;\n}\n","import type { WsiPointData } from \"./types\";\n\nexport type RoiCoordinate = [number, number];\nexport type RoiPolygon = RoiCoordinate[];\n\ninterface PreparedPolygon {\n\tring: RoiPolygon;\n\tminX: number;\n\tminY: number;\n\tmaxX: number;\n\tmaxY: number;\n}\n\nfunction sanitizePointCount(pointData: WsiPointData): number {\n\treturn Math.max(\n\t\t0,\n\t\tMath.min(\n\t\t\tMath.floor(pointData.count ?? 0),\n\t\t\tMath.floor((pointData.positions?.length ?? 0) / 2),\n\t\t\tpointData.paletteIndices?.length ?? 0,\n\t\t),\n\t);\n}\n\nfunction closeRing(coords: RoiPolygon): RoiPolygon {\n\tif (!Array.isArray(coords) || coords.length < 3) return [];\n\tconst out = coords.map(([x, y]) => [x, y] as RoiCoordinate);\n\tconst first = out[0];\n\tconst last = out[out.length - 1];\n\tif (!first || !last) return [];\n\tif (first[0] !== last[0] || first[1] !== last[1]) {\n\t\tout.push([first[0], first[1]]);\n\t}\n\treturn out;\n}\n\nfunction preparePolygons(polygons: RoiPolygon[]): PreparedPolygon[] {\n\tconst prepared: PreparedPolygon[] = [];\n\tfor (const poly of polygons ?? []) {\n\t\tconst ring = closeRing(poly);\n\t\tif (ring.length < 4) continue;\n\t\tlet minX = Infinity;\n\t\tlet minY = Infinity;\n\t\tlet maxX = -Infinity;\n\t\tlet maxY = -Infinity;\n\t\tfor (const [x, y] of ring) {\n\t\t\tif (x < minX) minX = x;\n\t\t\tif (x > maxX) maxX = x;\n\t\t\tif (y < minY) minY = y;\n\t\t\tif (y > maxY) maxY = y;\n\t\t}\n\t\tif (!Number.isFinite(minX) || !Number.isFinite(minY)) continue;\n\t\tprepared.push({ ring, minX, minY, maxX, maxY });\n\t}\n\treturn prepared;\n}\n\nfunction isInsideRing(x: number, y: number, ring: RoiPolygon): boolean {\n\tlet inside = false;\n\tfor (let i = 0, j = ring.length - 1; i < ring.length; j = i, i += 1) {\n\t\tconst xi = ring[i][0];\n\t\tconst yi = ring[i][1];\n\t\tconst xj = ring[j][0];\n\t\tconst yj = ring[j][1];\n\t\tconst intersect =\n\t\t\tyi > y !== yj > y &&\n\t\t\tx < ((xj - xi) * (y - yi)) / ((yj - yi) || Number.EPSILON) + xi;\n\t\tif (intersect) inside = !inside;\n\t}\n\treturn inside;\n}\n\nfunction isInsideAnyPolygon(\n\tx: number,\n\ty: number,\n\tpolygons: PreparedPolygon[],\n): boolean {\n\tfor (const poly of polygons) {\n\t\tif (x < poly.minX || x > poly.maxX || y < poly.minY || y > poly.maxY) {\n\t\t\tcontinue;\n\t\t}\n\t\tif (isInsideRing(x, y, poly.ring)) {\n\t\t\treturn true;\n\t\t}\n\t}\n\treturn false;\n}\n\nexport function filterPointDataByPolygons(\n\tpointData: WsiPointData | null | undefined,\n\tpolygons: RoiPolygon[] | null | undefined,\n): WsiPointData | null {\n\tif (!pointData || !pointData.count || !pointData.positions || !pointData.paletteIndices) {\n\t\treturn null;\n\t}\n\n\tconst prepared = preparePolygons(polygons ?? []);\n\tif (prepared.length === 0) {\n\t\treturn {\n\t\t\tcount: 0,\n\t\t\tpositions: new Float32Array(0),\n\t\t\tpaletteIndices: new Uint16Array(0),\n\t\t};\n\t}\n\n\tconst count = sanitizePointCount(pointData);\n\tconst positions = pointData.positions;\n\tconst terms = pointData.paletteIndices;\n\tconst pointIds =\n\t\tpointData.ids instanceof Uint32Array && pointData.ids.length >= count\n\t\t\t? pointData.ids\n\t\t\t: null;\n\n\tconst nextPositions = new Float32Array(count * 2);\n\tconst nextTerms = new Uint16Array(count);\n\tconst nextIds = pointIds ? new Uint32Array(count) : null;\n\tlet cursor = 0;\n\n\tfor (let i = 0; i < count; i += 1) {\n\t\tconst x = positions[i * 2];\n\t\tconst y = positions[i * 2 + 1];\n\t\tif (!isInsideAnyPolygon(x, y, prepared)) continue;\n\t\tnextPositions[cursor * 2] = x;\n\t\tnextPositions[cursor * 2 + 1] = y;\n\t\tnextTerms[cursor] = terms[i];\n\t\tif (nextIds) {\n\t\t\tnextIds[cursor] = pointIds![i];\n\t\t}\n\t\tcursor += 1;\n\t}\n\n\tconst output: WsiPointData = {\n\t\tcount: cursor,\n\t\tpositions: nextPositions.subarray(0, cursor * 2),\n\t\tpaletteIndices: nextTerms.subarray(0, cursor),\n\t};\n\tif (nextIds) {\n\t\toutput.ids = nextIds.subarray(0, cursor);\n\t}\n\treturn output;\n}\n\nexport function filterPointIndicesByPolygons(\n\tpointData: WsiPointData | null | undefined,\n\tpolygons: RoiPolygon[] | null | undefined,\n): Uint32Array {\n\tif (!pointData || !pointData.count || !pointData.positions || !pointData.paletteIndices) {\n\t\treturn new Uint32Array(0);\n\t}\n\n\tconst prepared = preparePolygons(polygons ?? []);\n\tif (prepared.length === 0) {\n\t\treturn new Uint32Array(0);\n\t}\n\n\tconst count = sanitizePointCount(pointData);\n\tif (count === 0) {\n\t\treturn new Uint32Array(0);\n\t}\n\n\tconst positions = pointData.positions;\n\tconst out = new Uint32Array(count);\n\tlet cursor = 0;\n\n\tfor (let i = 0; i < count; i += 1) {\n\t\tconst x = positions[i * 2];\n\t\tconst y = positions[i * 2 + 1];\n\t\tif (!isInsideAnyPolygon(x, y, prepared)) continue;\n\t\tout[cursor] = i;\n\t\tcursor += 1;\n\t}\n\n\treturn out.subarray(0, cursor);\n}\n","export interface WebGpuCapabilities {\n\tsupported: boolean;\n\tadapterName?: string;\n\tfeatures: string[];\n\tlimits?: {\n\t\tmaxStorageBufferBindingSize: number;\n\t\tmaxComputeInvocationsPerWorkgroup: number;\n\t\tmaxComputeWorkgroupSizeX: number;\n\t};\n}\n\ninterface NavigatorGpuLike {\n\trequestAdapter: () => Promise<GpuAdapterLike | null>;\n}\n\ninterface GpuAdapterLike {\n\tinfo?: {\n\t\tdescription?: string;\n\t\tvendor?: string;\n\t};\n\tfeatures: Iterable<string>;\n\tlimits: {\n\t\tmaxStorageBufferBindingSize: number;\n\t\tmaxComputeInvocationsPerWorkgroup: number;\n\t\tmaxComputeWorkgroupSizeX: number;\n\t};\n\trequestDevice: () => Promise<GpuDeviceLike>;\n}\n\ninterface GpuBufferLike {\n\tdestroy: () => void;\n\tmapAsync: (mode: number) => Promise<void>;\n\tgetMappedRange: () => ArrayBuffer;\n\tunmap: () => void;\n}\n\ninterface GpuComputePassLike {\n\tsetPipeline: (pipeline: GpuComputePipelineLike) => void;\n\tsetBindGroup: (index: number, bindGroup: unknown) => void;\n\tdispatchWorkgroups: (x: number, y?: number, z?: number) => void;\n\tend: () => void;\n}\n\ninterface GpuCommandEncoderLike {\n\tbeginComputePass: () => GpuComputePassLike;\n\tcopyBufferToBuffer: (\n\t\tsource: GpuBufferLike,\n\t\tsourceOffset: number,\n\t\tdestination: GpuBufferLike,\n\t\tdestinationOffset: number,\n\t\tsize: number,\n\t) => void;\n\tfinish: () => unknown;\n}\n\ninterface GpuQueueLike {\n\twriteBuffer: (\n\t\tbuffer: GpuBufferLike,\n\t\tbufferOffset: number,\n\t\tdata: ArrayBufferView | ArrayBufferLike,\n\t\tdataOffset?: number,\n\t\tsize?: number,\n\t) => void;\n\tsubmit: (commands: unknown[]) => void;\n}\n\ninterface GpuComputePipelineLike {\n\treadonly _brand?: \"GpuComputePipelineLike\";\n}\n\ninterface GpuBindGroupLayoutLike {\n\treadonly _brand?: \"GpuBindGroupLayoutLike\";\n}\n\ninterface GpuDeviceLike {\n\tlimits: {\n\t\tmaxStorageBufferBindingSize: number;\n\t};\n\tqueue: GpuQueueLike;\n\tcreateBindGroupLayout: (descriptor: unknown) => GpuBindGroupLayoutLike;\n\tcreatePipelineLayout: (descriptor: unknown) => unknown;\n\tcreateShaderModule: (descriptor: { code: string }) => unknown;\n\tcreateComputePipeline: (descriptor: unknown) => GpuComputePipelineLike;\n\tcreateBuffer: (descriptor: { size: number; usage: number }) => GpuBufferLike;\n\tcreateBindGroup: (descriptor: unknown) => unknown;\n\tcreateCommandEncoder: () => GpuCommandEncoderLike;\n}\n\ninterface WebGpuContext {\n\tdevice: GpuDeviceLike;\n\tpipeline: GpuComputePipelineLike;\n\tbindGroupLayout: GpuBindGroupLayoutLike;\n}\n\nlet contextPromise: Promise<WebGpuContext | null> | null = null;\n\nconst BBOX_PREFILTER_SHADER = `\nstruct Params {\n pointCount: u32,\n boundsCount: u32,\n _pad0: u32,\n _pad1: u32,\n};\n\n@group(0) @binding(0) var<storage, read> positions: array<vec2<f32>>;\n@group(0) @binding(1) var<storage, read> bounds: array<vec4<f32>>;\n@group(0) @binding(2) var<storage, read_write> outputMask: array<u32>;\n@group(0) @binding(3) var<uniform> params: Params;\n\n@compute @workgroup_size(256)\nfn main(@builtin(global_invocation_id) gid: vec3<u32>) {\n let i = gid.x;\n if (i >= params.pointCount) {\n return;\n }\n\n let p = positions[i];\n var inside: u32 = 0u;\n for (var bi: u32 = 0u; bi < params.boundsCount; bi = bi + 1u) {\n let b = bounds[bi];\n if (p.x >= b.x && p.x <= b.z && p.y >= b.y && p.y <= b.w) {\n inside = 1u;\n break;\n }\n }\n outputMask[i] = inside;\n}\n`;\n\nfunction hasWebGpu(): boolean {\n\tif (typeof navigator === \"undefined\") return false;\n\tconst nav = navigator as Navigator & { gpu?: unknown };\n\treturn typeof nav.gpu === \"object\" && nav.gpu !== null;\n}\n\nfunction getNavigatorGpu(): NavigatorGpuLike | null {\n\tif (!hasWebGpu()) return null;\n\tconst nav = navigator as Navigator & { gpu?: unknown };\n\tconst gpu = nav.gpu;\n\tif (!gpu || typeof gpu !== \"object\") return null;\n\tconst candidate = gpu as Partial<NavigatorGpuLike>;\n\tif (typeof candidate.requestAdapter !== \"function\") return null;\n\treturn candidate as NavigatorGpuLike;\n}\n\nconst GPU_SHADER_STAGE_COMPUTE =\n\t(globalThis as { GPUShaderStage?: { COMPUTE?: number } }).GPUShaderStage\n\t\t?.COMPUTE ?? 0x4;\nconst GPU_BUFFER_USAGE_STORAGE =\n\t(globalThis as { GPUBufferUsage?: { STORAGE?: number } }).GPUBufferUsage\n\t\t?.STORAGE ?? 0x80;\nconst GPU_BUFFER_USAGE_COPY_DST =\n\t(globalThis as { GPUBufferUsage?: { COPY_DST?: number } }).GPUBufferUsage\n\t\t?.COPY_DST ?? 0x08;\nconst GPU_BUFFER_USAGE_COPY_SRC =\n\t(globalThis as { GPUBufferUsage?: { COPY_SRC?: number } }).GPUBufferUsage\n\t\t?.COPY_SRC ?? 0x04;\nconst GPU_BUFFER_USAGE_UNIFORM =\n\t(globalThis as { GPUBufferUsage?: { UNIFORM?: number } }).GPUBufferUsage\n\t\t?.UNIFORM ?? 0x40;\nconst GPU_BUFFER_USAGE_MAP_READ =\n\t(globalThis as { GPUBufferUsage?: { MAP_READ?: number } }).GPUBufferUsage\n\t\t?.MAP_READ ?? 0x01;\nconst GPU_MAP_MODE_READ =\n\t(globalThis as { GPUMapMode?: { READ?: number } }).GPUMapMode?.READ ?? 0x01;\n\nexport async function getWebGpuCapabilities(): Promise<WebGpuCapabilities> {\n\tconst navGpu = getNavigatorGpu();\n\tif (!navGpu) {\n\t\treturn { supported: false, features: [] };\n\t}\n\tconst adapter = await navGpu.requestAdapter();\n\tif (!adapter) {\n\t\treturn { supported: false, features: [] };\n\t}\n\n\treturn {\n\t\tsupported: true,\n\t\tadapterName: adapter.info?.description ?? adapter.info?.vendor ?? \"unknown\",\n\t\tfeatures: Array.from(adapter.features),\n\t\tlimits: {\n\t\t\tmaxStorageBufferBindingSize: Number(\n\t\t\t\tadapter.limits.maxStorageBufferBindingSize,\n\t\t\t),\n\t\t\tmaxComputeInvocationsPerWorkgroup: Number(\n\t\t\t\tadapter.limits.maxComputeInvocationsPerWorkgroup,\n\t\t\t),\n\t\t\tmaxComputeWorkgroupSizeX: Number(adapter.limits.maxComputeWorkgroupSizeX),\n\t\t},\n\t};\n}\n\nasync function getContext(): Promise<WebGpuContext | null> {\n\tif (contextPromise) return contextPromise;\n\tcontextPromise = (async () => {\n\t\tconst navGpu = getNavigatorGpu();\n\t\tif (!navGpu) return null;\n\t\tconst adapter = await navGpu.requestAdapter();\n\t\tif (!adapter) return null;\n\t\tconst device = await adapter.requestDevice();\n\n\t\tconst bindGroupLayout = device.createBindGroupLayout({\n\t\t\tentries: [\n\t\t\t\t{\n\t\t\t\t\tbinding: 0,\n\t\t\t\t\tvisibility: GPU_SHADER_STAGE_COMPUTE,\n\t\t\t\t\tbuffer: { type: \"read-only-storage\" },\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tbinding: 1,\n\t\t\t\t\tvisibility: GPU_SHADER_STAGE_COMPUTE,\n\t\t\t\t\tbuffer: { type: \"read-only-storage\" },\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tbinding: 2,\n\t\t\t\t\tvisibility: GPU_SHADER_STAGE_COMPUTE,\n\t\t\t\t\tbuffer: { type: \"storage\" },\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tbinding: 3,\n\t\t\t\t\tvisibility: GPU_SHADER_STAGE_COMPUTE,\n\t\t\t\t\tbuffer: { type: \"uniform\" },\n\t\t\t\t},\n\t\t\t],\n\t\t});\n\n\t\tconst pipeline = device.createComputePipeline({\n\t\t\tlayout: device.createPipelineLayout({ bindGroupLayouts: [bindGroupLayout] }),\n\t\t\tcompute: {\n\t\t\t\tmodule: device.createShaderModule({ code: BBOX_PREFILTER_SHADER }),\n\t\t\t\tentryPoint: \"main\",\n\t\t\t},\n\t\t});\n\n\t\treturn { device, pipeline, bindGroupLayout };\n\t})();\n\n\treturn contextPromise;\n}\n\nfunction align(value: number, step: number): number {\n\treturn Math.ceil(value / step) * step;\n}\n\nexport async function prefilterPointsByBoundsWebGpu(\n\tpositions: Float32Array,\n\tpointCount: number,\n\tbounds: Float32Array,\n): Promise<Uint32Array | null> {\n\tconst ctx = await getContext();\n\tif (!ctx) return null;\n\n\tconst count = Math.max(0, Math.floor(pointCount));\n\tconst boundsCount = Math.max(0, Math.floor(bounds.length / 4));\n\tif (count === 0 || boundsCount === 0) {\n\t\treturn new Uint32Array(0);\n\t}\n\n\tconst safePointCount = Math.min(count, Math.floor(positions.length / 2));\n\tif (safePointCount === 0) {\n\t\treturn new Uint32Array(0);\n\t}\n\n\tconst positionBytes = safePointCount * 2 * Float32Array.BYTES_PER_ELEMENT;\n\tconst boundsBytes = boundsCount * 4 * Float32Array.BYTES_PER_ELEMENT;\n\tconst outputBytes = safePointCount * Uint32Array.BYTES_PER_ELEMENT;\n\n\tconst limit = Number(ctx.device.limits.maxStorageBufferBindingSize);\n\tif (positionBytes > limit || boundsBytes > limit || outputBytes > limit) {\n\t\treturn null;\n\t}\n\n\tconst positionsBuffer = ctx.device.createBuffer({\n\t\tsize: align(positionBytes, 4),\n\t\tusage: GPU_BUFFER_USAGE_STORAGE | GPU_BUFFER_USAGE_COPY_DST,\n\t});\n\tconst boundsBuffer = ctx.device.createBuffer({\n\t\tsize: align(boundsBytes, 4),\n\t\tusage: GPU_BUFFER_USAGE_STORAGE | GPU_BUFFER_USAGE_COPY_DST,\n\t});\n\tconst outputBuffer = ctx.device.createBuffer({\n\t\tsize: align(outputBytes, 4),\n\t\tusage: GPU_BUFFER_USAGE_STORAGE | GPU_BUFFER_USAGE_COPY_SRC,\n\t});\n\tconst uniformBuffer = ctx.device.createBuffer({\n\t\tsize: 16,\n\t\tusage: GPU_BUFFER_USAGE_UNIFORM | GPU_BUFFER_USAGE_COPY_DST,\n\t});\n\tconst readBuffer = ctx.device.createBuffer({\n\t\tsize: align(outputBytes, 4),\n\t\tusage: GPU_BUFFER_USAGE_COPY_DST | GPU_BUFFER_USAGE_MAP_READ,\n\t});\n\n\tctx.device.queue.writeBuffer(\n\t\tpositionsBuffer,\n\t\t0,\n\t\tpositions.buffer,\n\t\tpositions.byteOffset,\n\t\tpositionBytes,\n\t);\n\tctx.device.queue.writeBuffer(\n\t\tboundsBuffer,\n\t\t0,\n\t\tbounds.buffer,\n\t\tbounds.byteOffset,\n\t\tboundsBytes,\n\t);\n\tctx.device.queue.writeBuffer(\n\t\tuniformBuffer,\n\t\t0,\n\t\tnew Uint32Array([safePointCount, boundsCount, 0, 0]),\n\t);\n\n\tconst bindGroup = ctx.device.createBindGroup({\n\t\tlayout: ctx.bindGroupLayout,\n\t\tentries: [\n\t\t\t{ binding: 0, resource: { buffer: positionsBuffer } },\n\t\t\t{ binding: 1, resource: { buffer: boundsBuffer } },\n\t\t\t{ binding: 2, resource: { buffer: outputBuffer } },\n\t\t\t{ binding: 3, resource: { buffer: uniformBuffer } },\n\t\t],\n\t});\n\n\tconst commandEncoder = ctx.device.createCommandEncoder();\n\tconst pass = commandEncoder.beginComputePass();\n\tpass.setPipeline(ctx.pipeline);\n\tpass.setBindGroup(0, bindGroup);\n\tpass.dispatchWorkgroups(Math.ceil(safePointCount / 256));\n\tpass.end();\n\n\tcommandEncoder.copyBufferToBuffer(outputBuffer, 0, readBuffer, 0, outputBytes);\n\tctx.device.queue.submit([commandEncoder.finish()]);\n\n\tawait readBuffer.mapAsync(GPU_MAP_MODE_READ);\n\tconst mapped = readBuffer.getMappedRange();\n\tconst out = new Uint32Array(mapped.slice(0));\n\treadBuffer.unmap();\n\n\tpositionsBuffer.destroy();\n\tboundsBuffer.destroy();\n\toutputBuffer.destroy();\n\tuniformBuffer.destroy();\n\treadBuffer.destroy();\n\n\treturn out;\n}\n","import { filterPointDataByPolygons, type RoiPolygon } from \"./point-clip\";\nimport type { WsiPointData } from \"./types\";\nimport { prefilterPointsByBoundsWebGpu } from \"./webgpu\";\n\ninterface PreparedPolygon {\n ring: RoiPolygon;\n minX: number;\n minY: number;\n maxX: number;\n maxY: number;\n}\n\nexport interface HybridPointClipOptions {\n bridgeToDraw?: boolean;\n}\n\nexport interface HybridPointClipResult {\n data: WsiPointData | null;\n meta: {\n mode: \"hybrid-webgpu\";\n durationMs: number;\n usedWebGpu: boolean;\n candidateCount: number;\n bridgedToDraw?: boolean;\n };\n}\n\nfunction nowMs(): number {\n if (typeof performance !== \"undefined\" && typeof performance.now === \"function\") {\n return performance.now();\n }\n return Date.now();\n}\n\nfunction closeRing(coords: RoiPolygon): RoiPolygon {\n if (!Array.isArray(coords) || coords.length < 3) return [];\n const out = coords.map(([x, y]) => [x, y] as [number, number]);\n const first = out[0];\n const last = out[out.length - 1];\n if (!first || !last) return [];\n if (first[0] !== last[0] || first[1] !== last[1]) {\n out.push([first[0], first[1]]);\n }\n return out;\n}\n\nfunction preparePolygons(polygons: RoiPolygon[]): PreparedPolygon[] {\n const prepared: PreparedPolygon[] = [];\n for (const poly of polygons ?? []) {\n const ring = closeRing(poly);\n if (ring.length < 4) continue;\n let minX = Infinity;\n let minY = Infinity;\n let maxX = -Infinity;\n let maxY = -Infinity;\n for (const [x, y] of ring) {\n if (x < minX) minX = x;\n if (x > maxX) maxX = x;\n if (y < minY) minY = y;\n if (y > maxY) maxY = y;\n }\n if (!Number.isFinite(minX) || !Number.isFinite(minY)) continue;\n prepared.push({ ring, minX, minY, maxX, maxY });\n }\n return prepared;\n}\n\nfunction isInsideRing(x: number, y: number, ring: RoiPolygon): boolean {\n let inside = false;\n for (let i = 0, j = ring.length - 1; i < ring.length; j = i, i += 1) {\n const xi = ring[i][0];\n const yi = ring[i][1];\n const xj = ring[j][0];\n const yj = ring[j][1];\n const intersect = yi > y !== yj > y && x < ((xj - xi) * (y - yi)) / (yj - yi || Number.EPSILON) + xi;\n if (intersect) inside = !inside;\n }\n return inside;\n}\n\nfunction isInsideAnyPolygon(x: number, y: number, polygons: PreparedPolygon[]): boolean {\n for (const poly of polygons) {\n if (x < poly.minX || x > poly.maxX || y < poly.minY || y > poly.maxY) {\n continue;\n }\n if (isInsideRing(x, y, poly.ring)) {\n return true;\n }\n }\n return false;\n}\n\nexport async function filterPointDataByPolygonsHybrid(\n pointData: WsiPointData | null | undefined,\n polygons: RoiPolygon[] | null | undefined,\n options: HybridPointClipOptions = {}\n): Promise<HybridPointClipResult> {\n const start = nowMs();\n const bridgeToDraw = options.bridgeToDraw === true;\n if (!pointData || !pointData.count || !pointData.positions || !pointData.paletteIndices) {\n return {\n data: null,\n meta: {\n mode: \"hybrid-webgpu\",\n durationMs: nowMs() - start,\n usedWebGpu: false,\n candidateCount: 0,\n bridgedToDraw: false,\n },\n };\n }\n\n const prepared = preparePolygons(polygons ?? []);\n if (prepared.length === 0) {\n return {\n data: {\n count: 0,\n positions: new Float32Array(0),\n paletteIndices: new Uint16Array(0),\n },\n meta: {\n mode: \"hybrid-webgpu\",\n durationMs: nowMs() - start,\n usedWebGpu: false,\n candidateCount: 0,\n bridgedToDraw: false,\n },\n };\n }\n\n const safeCount = Math.max(0, Math.min(pointData.count, Math.floor(pointData.positions.length / 2), pointData.paletteIndices.length));\n const pointIds = pointData.ids instanceof Uint32Array && pointData.ids.length >= safeCount ? pointData.ids : null;\n if (safeCount === 0) {\n return {\n data: {\n count: 0,\n positions: new Float32Array(0),\n paletteIndices: new Uint16Array(0),\n },\n meta: {\n mode: \"hybrid-webgpu\",\n durationMs: nowMs() - start,\n usedWebGpu: false,\n candidateCount: 0,\n bridgedToDraw: false,\n },\n };\n }\n\n const bboxFlat = new Float32Array(prepared.length * 4);\n for (let i = 0; i < prepared.length; i += 1) {\n const base = i * 4;\n const poly = prepared[i];\n bboxFlat[base] = poly.minX;\n bboxFlat[base + 1] = poly.minY;\n bboxFlat[base + 2] = poly.maxX;\n bboxFlat[base + 3] = poly.maxY;\n }\n\n let candidateMask: Uint32Array | null = null;\n let usedWebGpu = false;\n try {\n candidateMask = await prefilterPointsByBoundsWebGpu(pointData.positions, safeCount, bboxFlat);\n usedWebGpu = !!candidateMask;\n } catch {\n candidateMask = null;\n usedWebGpu = false;\n }\n\n if (!candidateMask) {\n const fallback = filterPointDataByPolygons(pointData, polygons);\n return {\n data: fallback,\n meta: {\n mode: \"hybrid-webgpu\",\n durationMs: nowMs() - start,\n usedWebGpu: false,\n candidateCount: safeCount,\n bridgedToDraw: false,\n },\n };\n }\n\n let candidateCount = 0;\n for (let i = 0; i < safeCount; i += 1) {\n if (candidateMask[i] === 1) candidateCount += 1;\n }\n\n const candidateIndices = new Uint32Array(candidateCount);\n if (candidateCount > 0) {\n let candidateCursor = 0;\n for (let i = 0; i < safeCount; i += 1) {\n if (candidateMask[i] !== 1) continue;\n candidateIndices[candidateCursor] = i;\n candidateCursor += 1;\n }\n }\n\n if (candidateCount === 0) {\n if (bridgeToDraw) {\n const data: WsiPointData = {\n count: safeCount,\n positions: pointData.positions.subarray(0, safeCount * 2),\n paletteIndices: pointData.paletteIndices.subarray(0, safeCount),\n drawIndices: new Uint32Array(0),\n };\n if (pointIds) {\n data.ids = pointIds.subarray(0, safeCount);\n }\n return {\n data,\n meta: {\n mode: \"hybrid-webgpu\",\n durationMs: nowMs() - start,\n usedWebGpu: true,\n candidateCount: 0,\n bridgedToDraw: true,\n },\n };\n }\n\n return {\n data: {\n count: 0,\n positions: new Float32Array(0),\n paletteIndices: new Uint16Array(0),\n ...(pointIds ? { ids: new Uint32Array(0) } : {}),\n },\n meta: {\n mode: \"hybrid-webgpu\",\n durationMs: nowMs() - start,\n usedWebGpu: true,\n candidateCount: 0,\n bridgedToDraw: false,\n },\n };\n }\n\n if (bridgeToDraw) {\n const drawIndices = new Uint32Array(candidateCount);\n let visibleCount = 0;\n\n for (let i = 0; i < candidateCount; i += 1) {\n const pointIndex = candidateIndices[i] ?? 0;\n const x = pointData.positions[pointIndex * 2];\n const y = pointData.positions[pointIndex * 2 + 1];\n if (!isInsideAnyPolygon(x, y, prepared)) continue;\n drawIndices[visibleCount] = pointIndex;\n visibleCount += 1;\n }\n\n const data: WsiPointData = {\n count: safeCount,\n positions: pointData.positions.subarray(0, safeCount * 2),\n paletteIndices: pointData.paletteIndices.subarray(0, safeCount),\n drawIndices: drawIndices.subarray(0, visibleCount),\n };\n if (pointIds) {\n data.ids = pointIds.subarray(0, safeCount);\n }\n\n return {\n data,\n meta: {\n mode: \"hybrid-webgpu\",\n durationMs: nowMs() - start,\n usedWebGpu: true,\n candidateCount,\n bridgedToDraw: true,\n },\n };\n }\n\n const nextPositions = new Float32Array(candidateCount * 2);\n const nextTerms = new Uint16Array(candidateCount);\n const nextIds = pointIds ? new Uint32Array(candidateCount) : null;\n let cursor = 0;\n\n for (let i = 0; i < candidateCount; i += 1) {\n const pointIndex = candidateIndices[i] ?? 0;\n const x = pointData.positions[pointIndex * 2];\n const y = pointData.positions[pointIndex * 2 + 1];\n if (!isInsideAnyPolygon(x, y, prepared)) continue;\n nextPositions[cursor * 2] = x;\n nextPositions[cursor * 2 + 1] = y;\n nextTerms[cursor] = pointData.paletteIndices[pointIndex];\n if (nextIds) {\n nextIds[cursor] = pointIds![pointIndex];\n }\n cursor += 1;\n }\n\n const compactData: WsiPointData = {\n count: cursor,\n positions: nextPositions.subarray(0, cursor * 2),\n paletteIndices: nextTerms.subarray(0, cursor),\n };\n if (nextIds) {\n compactData.ids = nextIds.subarray(0, cursor);\n }\n\n return {\n data: compactData,\n meta: {\n mode: \"hybrid-webgpu\",\n durationMs: nowMs() - start,\n usedWebGpu: true,\n candidateCount,\n bridgedToDraw: false,\n },\n };\n}\n","import { filterPointDataByPolygons, filterPointIndicesByPolygons, type RoiPolygon } from \"./point-clip\";\nimport type { RoiClipWorkerRequest, RoiClipWorkerResponse } from \"./point-clip-worker-protocol\";\nimport type { WsiPointData } from \"./types\";\n\nexport type PointClipMode = \"sync\" | \"worker\" | \"hybrid-webgpu\";\n\nexport interface PointClipResultMeta {\n mode: PointClipMode;\n durationMs: number;\n}\n\nexport interface PointClipResult {\n data: WsiPointData | null;\n meta: PointClipResultMeta;\n}\n\nexport interface PointClipIndexResult {\n indices: Uint32Array;\n meta: PointClipResultMeta;\n}\n\ninterface PendingDataWorkerRequest {\n kind: \"data\";\n resolve: (result: PointClipResult) => void;\n reject: (reason?: unknown) => void;\n startMs: number;\n}\n\ninterface PendingIndexWorkerRequest {\n kind: \"index\";\n resolve: (result: PointClipIndexResult) => void;\n reject: (reason?: unknown) => void;\n startMs: number;\n}\n\ntype PendingWorkerRequest = PendingDataWorkerRequest | PendingIndexWorkerRequest;\n\nlet workerInstance: Worker | null = null;\nlet workerSupported = true;\nlet requestId = 1;\nconst pendingById = new Map<number, PendingWorkerRequest>();\n\nfunction nowMs(): number {\n if (typeof performance !== \"undefined\" && typeof performance.now === \"function\") {\n return performance.now();\n }\n return Date.now();\n}\n\nfunction createWorker(): Worker | null {\n if (!workerSupported) return null;\n if (workerInstance) return workerInstance;\n try {\n const worker = new Worker(new URL(\"../workers/roi-clip-worker.ts\", import.meta.url), { type: \"module\" });\n worker.addEventListener(\"message\", handleWorkerMessage);\n worker.addEventListener(\"error\", handleWorkerError);\n workerInstance = worker;\n return worker;\n } catch {\n workerSupported = false;\n return null;\n }\n}\n\nfunction handleWorkerMessage(event: MessageEvent<RoiClipWorkerResponse>): void {\n const msg = event.data;\n if (!msg) return;\n const pending = pendingById.get(msg.id);\n if (!pending) return;\n pendingById.delete(msg.id);\n\n if (msg.type === \"roi-clip-failure\") {\n pending.reject(new Error(msg.error || \"worker clip failed\"));\n return;\n }\n\n if (msg.type === \"roi-clip-index-success\") {\n if (pending.kind !== \"index\") {\n pending.reject(new Error(\"worker response mismatch: expected point data result\"));\n return;\n }\n const count = Math.max(0, Math.floor(msg.count));\n const indices = new Uint32Array(msg.indices).subarray(0, count);\n pending.resolve({\n indices,\n meta: {\n mode: \"worker\",\n durationMs: Number.isFinite(msg.durationMs) ? msg.durationMs : nowMs() - pending.startMs,\n },\n });\n return;\n }\n\n if (pending.kind !== \"data\") {\n pending.reject(new Error(\"worker response mismatch: expected index result\"));\n return;\n }\n\n const count = Math.max(0, Math.floor(msg.count));\n const positions = new Float32Array(msg.positions);\n const paletteIndices = new Uint16Array(msg.paletteIndices);\n const ids = msg.ids ? new Uint32Array(msg.ids) : null;\n const output: WsiPointData = {\n count,\n positions: positions.subarray(0, count * 2),\n paletteIndices: paletteIndices.subarray(0, count),\n };\n if (ids) {\n output.ids = ids.subarray(0, count);\n }\n\n pending.resolve({\n data: output,\n meta: {\n mode: \"worker\",\n durationMs: Number.isFinite(msg.durationMs) ? msg.durationMs : nowMs() - pending.startMs,\n },\n });\n}\n\nfunction handleWorkerError(): void {\n workerSupported = false;\n if (workerInstance) {\n workerInstance.removeEventListener(\"message\", handleWorkerMessage);\n workerInstance.removeEventListener(\"error\", handleWorkerError);\n workerInstance.terminate();\n workerInstance = null;\n }\n for (const [, pending] of pendingById) {\n pending.reject(new Error(\"worker crashed\"));\n }\n pendingById.clear();\n}\n\nexport function terminateRoiClipWorker(): void {\n if (!workerInstance) return;\n workerInstance.removeEventListener(\"message\", handleWorkerMessage);\n workerInstance.removeEventListener(\"error\", handleWorkerError);\n workerInstance.terminate();\n workerInstance = null;\n for (const [, pending] of pendingById) {\n pending.reject(new Error(\"worker terminated\"));\n }\n pendingById.clear();\n}\n\nexport async function filterPointDataByPolygonsInWorker(pointData: WsiPointData | null | undefined, polygons: RoiPolygon[] | null | undefined): Promise<PointClipResult> {\n if (!pointData || !pointData.count || !pointData.positions || !pointData.paletteIndices) {\n return {\n data: null,\n meta: { mode: \"worker\", durationMs: 0 },\n };\n }\n\n const worker = createWorker();\n if (!worker) {\n const start = nowMs();\n return {\n data: filterPointDataByPolygons(pointData, polygons),\n meta: { mode: \"sync\", durationMs: nowMs() - start },\n };\n }\n\n const safeCount = Math.max(0, Math.min(pointData.count, Math.floor(pointData.positions.length / 2), pointData.paletteIndices.length));\n const positionsCopy = pointData.positions.slice(0, safeCount * 2);\n const termsCopy = pointData.paletteIndices.slice(0, safeCount);\n const idsCopy = pointData.ids instanceof Uint32Array && pointData.ids.length >= safeCount ? pointData.ids.slice(0, safeCount) : null;\n const id = requestId++;\n const startMs = nowMs();\n\n return new Promise<PointClipResult>((resolve, reject) => {\n pendingById.set(id, { kind: \"data\", resolve, reject, startMs });\n const msg: RoiClipWorkerRequest = {\n type: \"roi-clip-request\",\n id,\n count: safeCount,\n positions: positionsCopy.buffer,\n paletteIndices: termsCopy.buffer,\n ids: idsCopy?.buffer,\n polygons: polygons ?? [],\n };\n const transfer: Transferable[] = [positionsCopy.buffer, termsCopy.buffer];\n if (idsCopy) {\n transfer.push(idsCopy.buffer);\n }\n worker.postMessage(msg, transfer);\n });\n}\n\nexport async function filterPointIndicesByPolygonsInWorker(pointData: WsiPointData | null | undefined, polygons: RoiPolygon[] | null | undefined): Promise<PointClipIndexResult> {\n if (!pointData || !pointData.count || !pointData.positions || !pointData.paletteIndices) {\n return {\n indices: new Uint32Array(0),\n meta: { mode: \"worker\", durationMs: 0 },\n };\n }\n\n const worker = createWorker();\n if (!worker) {\n const start = nowMs();\n return {\n indices: filterPointIndicesByPolygons(pointData, polygons),\n meta: { mode: \"sync\", durationMs: nowMs() - start },\n };\n }\n\n const safeCount = Math.max(0, Math.min(pointData.count, Math.floor(pointData.positions.length / 2), pointData.paletteIndices.length));\n const positionsCopy = pointData.positions.slice(0, safeCount * 2);\n const id = requestId++;\n const startMs = nowMs();\n\n return new Promise<PointClipIndexResult>((resolve, reject) => {\n pendingById.set(id, { kind: \"index\", resolve, reject, startMs });\n const msg: RoiClipWorkerRequest = {\n type: \"roi-clip-index-request\",\n id,\n count: safeCount,\n positions: positionsCopy.buffer,\n polygons: polygons ?? [],\n };\n worker.postMessage(msg, [positionsCopy.buffer]);\n });\n}\n","import type { WsiPointData, WsiRegion } from \"./types\";\n\nexport interface RoiTermCount {\n\ttermId: string;\n\tpaletteIndex: number;\n\tcount: number;\n}\n\nexport interface RoiPointGroup {\n\tregionId: string | number;\n\tregionIndex: number;\n\ttotalCount: number;\n\ttermCounts: RoiTermCount[];\n}\n\nexport interface RoiPointGroupOptions {\n\tpaletteIndexToTermId?: ReadonlyMap<number, string> | readonly string[];\n\tincludeEmptyRegions?: boolean;\n}\n\nexport interface RoiPointGroupStats {\n\tgroups: RoiPointGroup[];\n\tinputPointCount: number;\n\tpointsInsideAnyRegion: number;\n\tunmatchedPointCount: number;\n}\n\ninterface PreparedRegion {\n\tregionId: string | number;\n\tregionIndex: number;\n\tring: Array<[number, number]>;\n\tminX: number;\n\tminY: number;\n\tmaxX: number;\n\tmaxY: number;\n\tarea: number;\n}\n\nfunction closeRing(\n\tcoordinates: readonly [number, number][],\n): Array<[number, number]> {\n\tif (!Array.isArray(coordinates) || coordinates.length < 3) return [];\n\tconst out = coordinates.map(\n\t\t(point): [number, number] => [Number(point[0]), Number(point[1])],\n\t);\n\tconst first = out[0];\n\tconst last = out[out.length - 1];\n\tif (!first || !last) return [];\n\tif (first[0] !== last[0] || first[1] !== last[1]) {\n\t\tout.push([first[0], first[1]]);\n\t}\n\treturn out;\n}\n\nfunction polygonArea(ring: Array<[number, number]>): number {\n\tlet sum = 0;\n\tfor (let i = 0; i < ring.length - 1; i += 1) {\n\t\tconst [ax, ay] = ring[i];\n\t\tconst [bx, by] = ring[i + 1];\n\t\tsum += ax * by - bx * ay;\n\t}\n\treturn Math.abs(sum * 0.5);\n}\n\nfunction prepareRegions(regions: readonly WsiRegion[]): PreparedRegion[] {\n\tconst prepared: PreparedRegion[] = [];\n\tfor (let i = 0; i < regions.length; i += 1) {\n\t\tconst region = regions[i];\n\t\tif (!region?.coordinates?.length) continue;\n\n\t\tconst ring = closeRing(region.coordinates);\n\t\tif (ring.length < 4) continue;\n\n\t\tlet minX = Infinity;\n\t\tlet minY = Infinity;\n\t\tlet maxX = -Infinity;\n\t\tlet maxY = -Infinity;\n\t\tfor (const [x, y] of ring) {\n\t\t\tif (x < minX) minX = x;\n\t\t\tif (x > maxX) maxX = x;\n\t\t\tif (y < minY) minY = y;\n\t\t\tif (y > maxY) maxY = y;\n\t\t}\n\t\tif (\n\t\t\t!Number.isFinite(minX) ||\n\t\t\t!Number.isFinite(minY) ||\n\t\t\t!Number.isFinite(maxX) ||\n\t\t\t!Number.isFinite(maxY)\n\t\t) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tprepared.push({\n\t\t\tregionId: region.id ?? i,\n\t\t\tregionIndex: i,\n\t\t\tring,\n\t\t\tminX,\n\t\t\tminY,\n\t\t\tmaxX,\n\t\t\tmaxY,\n\t\t\tarea: Math.max(1e-6, polygonArea(ring)),\n\t\t});\n\t}\n\treturn prepared;\n}\n\nfunction isInsideRing(x: number, y: number, ring: Array<[number, number]>): boolean {\n\tlet inside = false;\n\tfor (let i = 0, j = ring.length - 1; i < ring.length; j = i, i += 1) {\n\t\tconst xi = ring[i][0];\n\t\tconst yi = ring[i][1];\n\t\tconst xj = ring[j][0];\n\t\tconst yj = ring[j][1];\n\t\tconst intersect =\n\t\t\tyi > y !== yj > y &&\n\t\t\tx < ((xj - xi) * (y - yi)) / ((yj - yi) || Number.EPSILON) + xi;\n\t\tif (intersect) inside = !inside;\n\t}\n\treturn inside;\n}\n\nfunction resolveTermId(\n\tpaletteIndex: number,\n\tpaletteIndexToTermId: RoiPointGroupOptions[\"paletteIndexToTermId\"],\n): string {\n\tif (Array.isArray(paletteIndexToTermId)) {\n\t\tconst fromArray = paletteIndexToTermId[paletteIndex];\n\t\tif (typeof fromArray === \"string\" && fromArray.length > 0) return fromArray;\n\t}\n\tif (paletteIndexToTermId instanceof Map) {\n\t\tconst fromMap = paletteIndexToTermId.get(paletteIndex);\n\t\tif (typeof fromMap === \"string\" && fromMap.length > 0) return fromMap;\n\t}\n\treturn String(paletteIndex);\n}\n\nexport function computeRoiPointGroups(\n\tpointData: WsiPointData | null | undefined,\n\tregions: readonly WsiRegion[] | null | undefined,\n\toptions: RoiPointGroupOptions = {},\n): RoiPointGroupStats {\n\tconst baseCount = Math.max(\n\t\t0,\n\t\tMath.min(\n\t\t\tMath.floor(pointData?.count ?? 0),\n\t\t\tMath.floor((pointData?.positions?.length ?? 0) / 2),\n\t\t\tpointData?.paletteIndices?.length ?? 0,\n\t\t),\n\t);\n\n\tlet drawIndices: Uint32Array | null = null;\n\tif (pointData?.drawIndices instanceof Uint32Array) {\n\t\tconst source = pointData.drawIndices;\n\t\tlet valid = source.length;\n\t\tfor (let i = 0; i < source.length; i += 1) {\n\t\t\tconst idx = source[i];\n\t\t\tif (idx < baseCount) continue;\n\t\t\tvalid -= 1;\n\t\t}\n\t\tif (valid === source.length) {\n\t\t\tdrawIndices = source;\n\t\t} else if (valid > 0) {\n\t\t\tconst filtered = new Uint32Array(valid);\n\t\t\tlet cursor = 0;\n\t\t\tfor (let i = 0; i < source.length; i += 1) {\n\t\t\t\tconst idx = source[i];\n\t\t\t\tif (idx >= baseCount) continue;\n\t\t\t\tfiltered[cursor] = idx;\n\t\t\t\tcursor += 1;\n\t\t\t}\n\t\t\tdrawIndices = filtered;\n\t\t} else {\n\t\t\tdrawIndices = new Uint32Array(0);\n\t\t}\n\t}\n\n\tconst inputCount = drawIndices ? drawIndices.length : baseCount;\n\n\tconst preparedRegions = prepareRegions(regions ?? []);\n\tif (!pointData || inputCount === 0 || preparedRegions.length === 0) {\n\t\treturn {\n\t\t\tgroups: [],\n\t\t\tinputPointCount: inputCount,\n\t\t\tpointsInsideAnyRegion: 0,\n\t\t\tunmatchedPointCount: inputCount,\n\t\t};\n\t}\n\n\tconst regionTermCounters = new Map<number, Map<number, number>>();\n\tconst regionTotalCounters = new Map<number, number>();\n\tlet insideCount = 0;\n\n\tfor (let i = 0; i < inputCount; i += 1) {\n\t\tconst pointIndex = drawIndices ? drawIndices[i] : i;\n\t\tconst x = pointData.positions[pointIndex * 2];\n\t\tconst y = pointData.positions[pointIndex * 2 + 1];\n\t\tlet bestRegion: PreparedRegion | null = null;\n\n\t\tfor (const region of preparedRegions) {\n\t\t\tif (x < region.minX || x > region.maxX || y < region.minY || y > region.maxY) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (!isInsideRing(x, y, region.ring)) continue;\n\t\t\tif (!bestRegion || region.area < bestRegion.area) {\n\t\t\t\tbestRegion = region;\n\t\t\t}\n\t\t}\n\n\t\tif (!bestRegion) continue;\n\t\tinsideCount += 1;\n\n\t\tconst paletteIndex = pointData.paletteIndices[pointIndex] ?? 0;\n\t\tconst regionTermMap =\n\t\t\tregionTermCounters.get(bestRegion.regionIndex) ?? new Map<number, number>();\n\t\tregionTermMap.set(paletteIndex, (regionTermMap.get(paletteIndex) ?? 0) + 1);\n\t\tregionTermCounters.set(bestRegion.regionIndex, regionTermMap);\n\t\tregionTotalCounters.set(\n\t\t\tbestRegion.regionIndex,\n\t\t\t(regionTotalCounters.get(bestRegion.regionIndex) ?? 0) + 1,\n\t\t);\n\t}\n\n\tconst includeEmptyRegions = options.includeEmptyRegions ?? false;\n\tconst groups: RoiPointGroup[] = [];\n\tfor (const region of preparedRegions) {\n\t\tconst totalCount = regionTotalCounters.get(region.regionIndex) ?? 0;\n\t\tif (!includeEmptyRegions && totalCount <= 0) continue;\n\t\tconst termMap = regionTermCounters.get(region.regionIndex) ?? new Map();\n\t\tconst termCounts: RoiTermCount[] = Array.from(termMap.entries())\n\t\t\t.map(([paletteIndex, count]) => ({\n\t\t\t\ttermId: resolveTermId(paletteIndex, options.paletteIndexToTermId),\n\t\t\t\tpaletteIndex,\n\t\t\t\tcount,\n\t\t\t}))\n\t\t\t.sort((a, b) => b.count - a.count || a.paletteIndex - b.paletteIndex);\n\n\t\tgroups.push({\n\t\t\tregionId: region.regionId,\n\t\t\tregionIndex: region.regionIndex,\n\t\t\ttotalCount,\n\t\t\ttermCounts,\n\t\t});\n\t}\n\n\treturn {\n\t\tgroups,\n\t\tinputPointCount: inputCount,\n\t\tpointsInsideAnyRegion: insideCount,\n\t\tunmatchedPointCount: Math.max(0, inputCount - insideCount),\n\t};\n}\n","export type TileBounds = [number, number, number, number];\n\nexport interface ScheduledTile {\n\tkey: string;\n\ttier: number;\n\tx: number;\n\ty: number;\n\tbounds: TileBounds;\n\tdistance2: number;\n\turl: string;\n}\n\nexport interface TileSchedulerSnapshot {\n\tinflight: number;\n\tqueued: number;\n\taborted: number;\n\tretries: number;\n\tfailed: number;\n}\n\nexport interface TileSchedulerOptions {\n\tmaxConcurrency?: number;\n\tmaxRetries?: number;\n\tretryBaseDelayMs?: number;\n\tretryMaxDelayMs?: number;\n\tauthToken?: string;\n\tonTileLoad: (tile: ScheduledTile, bitmap: ImageBitmap) => void;\n\tonTileError?: (\n\t\ttile: ScheduledTile,\n\t\terror: unknown,\n\t\tattemptCount: number,\n\t) => void;\n\tonStateChange?: (snapshot: TileSchedulerSnapshot) => void;\n}\n\ninterface QueueItem {\n\ttile: ScheduledTile;\n\tattempt: number;\n\treadyAt: number;\n}\n\ninterface InflightItem {\n\ttile: ScheduledTile;\n\tattempt: number;\n\tcontroller: AbortController;\n}\n\nfunction nowMs(): number {\n\tif (typeof performance !== \"undefined\" && typeof performance.now === \"function\") {\n\t\treturn performance.now();\n\t}\n\treturn Date.now();\n}\n\nfunction shouldAttachAuthHeader(url: string, authToken: string): boolean {\n\tif (!authToken) return false;\n\ttry {\n\t\tconst parsed = new URL(url, typeof window !== \"undefined\" ? window.location.href : undefined);\n\t\tconst host = parsed.hostname.toLowerCase();\n\t\tconst isAwsS3 =\n\t\t\thost.includes(\"amazonaws.com\") || host.startsWith(\"s3.\") || host.includes(\".s3.\");\n\t\tif (isAwsS3) return false;\n\t} catch {\n\t\t// Fallback to attaching auth if URL parsing fails.\n\t}\n\treturn true;\n}\n\nexport class TileScheduler {\n\tprivate readonly maxConcurrency: number;\n\tprivate readonly maxRetries: number;\n\tprivate readonly retryBaseDelayMs: number;\n\tprivate readonly retryMaxDelayMs: number;\n\tprivate readonly onTileLoad: (tile: ScheduledTile, bitmap: ImageBitmap) => void;\n\tprivate readonly onTileError?:\n\t\t| ((tile: ScheduledTile, error: unknown, attemptCount: number) => void)\n\t\t| undefined;\n\tprivate readonly onStateChange?:\n\t\t| ((snapshot: TileSchedulerSnapshot) => void)\n\t\t| undefined;\n\n\tprivate authToken: string;\n\tprivate destroyed = false;\n\tprivate queue: QueueItem[] = [];\n\tprivate queuedByKey = new Map<string, QueueItem>();\n\tprivate inflight = new Map<string, InflightItem>();\n\tprivate visibleKeys = new Set<string>();\n\tprivate timerId: number | null = null;\n\tprivate abortedCount = 0;\n\tprivate retryCount = 0;\n\tprivate failedCount = 0;\n\n\tconstructor(options: TileSchedulerOptions) {\n\t\tthis.maxConcurrency = Math.max(1, Math.floor(options.maxConcurrency ?? 12));\n\t\tthis.maxRetries = Math.max(0, Math.floor(options.maxRetries ?? 2));\n\t\tthis.retryBaseDelayMs = Math.max(\n\t\t\t10,\n\t\t\tMath.floor(options.retryBaseDelayMs ?? 120),\n\t\t);\n\t\tthis.retryMaxDelayMs = Math.max(\n\t\t\tthis.retryBaseDelayMs,\n\t\t\tMath.floor(options.retryMaxDelayMs ?? 1200),\n\t\t);\n\t\tthis.authToken = options.authToken ?? \"\";\n\t\tthis.onTileLoad = options.onTileLoad;\n\t\tthis.onTileError = options.onTileError;\n\t\tthis.onStateChange = options.onStateChange;\n\t}\n\n\tsetAuthToken(token: string): void {\n\t\tthis.authToken = String(token ?? \"\");\n\t}\n\n\tschedule(tiles: readonly ScheduledTile[]): void {\n\t\tif (this.destroyed) return;\n\n\t\tconst nextVisibleKeys = new Set<string>();\n\t\tfor (const tile of tiles) {\n\t\t\tnextVisibleKeys.add(tile.key);\n\t\t}\n\t\tthis.visibleKeys = nextVisibleKeys;\n\n\t\tthis.dropInvisibleQueued(nextVisibleKeys);\n\t\tthis.abortInvisibleInflight(nextVisibleKeys);\n\n\t\tfor (const tile of tiles) {\n\t\t\tif (this.inflight.has(tile.key)) {\n\t\t\t\tconst inflight = this.inflight.get(tile.key);\n\t\t\t\tif (inflight) inflight.tile = tile;\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst queued = this.queuedByKey.get(tile.key);\n\t\t\tif (queued) {\n\t\t\t\tqueued.tile = tile;\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst item: QueueItem = {\n\t\t\t\ttile,\n\t\t\t\tattempt: 0,\n\t\t\t\treadyAt: nowMs(),\n\t\t\t};\n\t\t\tthis.queue.push(item);\n\t\t\tthis.queuedByKey.set(tile.key, item);\n\t\t}\n\n\t\tthis.sortQueue();\n\t\tthis.pump();\n\t\tthis.emitStateChange();\n\t}\n\n\tclear(): void {\n\t\tthis.clearPumpTimer();\n\t\tthis.visibleKeys.clear();\n\t\tthis.queue = [];\n\t\tthis.queuedByKey.clear();\n\n\t\tfor (const [, item] of this.inflight) {\n\t\t\titem.controller.abort();\n\t\t}\n\t\tthis.inflight.clear();\n\t\tthis.emitStateChange();\n\t}\n\n\tdestroy(): void {\n\t\tif (this.destroyed) return;\n\t\tthis.destroyed = true;\n\t\tthis.clear();\n\t}\n\n\tgetInflightCount(): number {\n\t\treturn this.inflight.size;\n\t}\n\n\tgetSnapshot(): TileSchedulerSnapshot {\n\t\treturn {\n\t\t\tinflight: this.inflight.size,\n\t\t\tqueued: this.queue.length,\n\t\t\taborted: this.abortedCount,\n\t\t\tretries: this.retryCount,\n\t\t\tfailed: this.failedCount,\n\t\t};\n\t}\n\n\tprivate dropInvisibleQueued(visibleKeys: Set<string>): void {\n\t\tif (this.queue.length === 0) return;\n\t\tconst nextQueue: QueueItem[] = [];\n\t\tfor (const item of this.queue) {\n\t\t\tif (!visibleKeys.has(item.tile.key)) {\n\t\t\t\tthis.queuedByKey.delete(item.tile.key);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tnextQueue.push(item);\n\t\t}\n\t\tthis.queue = nextQueue;\n\t}\n\n\tprivate abortInvisibleInflight(visibleKeys: Set<string>): void {\n\t\tfor (const [key, item] of this.inflight) {\n\t\t\tif (visibleKeys.has(key)) continue;\n\t\t\tthis.inflight.delete(key);\n\t\t\tthis.abortedCount += 1;\n\t\t\titem.controller.abort();\n\t\t}\n\t}\n\n\tprivate sortQueue(): void {\n\t\tthis.queue.sort((a, b) => {\n\t\t\tif (a.readyAt !== b.readyAt) return a.readyAt - b.readyAt;\n\t\t\tif (a.tile.distance2 !== b.tile.distance2) {\n\t\t\t\treturn a.tile.distance2 - b.tile.distance2;\n\t\t\t}\n\t\t\tif (a.tile.tier !== b.tile.tier) return b.tile.tier - a.tile.tier;\n\t\t\treturn a.tile.key.localeCompare(b.tile.key);\n\t\t});\n\t}\n\n\tprivate pump(): void {\n\t\tif (this.destroyed) return;\n\t\tthis.clearPumpTimer();\n\n\t\twhile (this.inflight.size < this.maxConcurrency) {\n\t\t\tconst next = this.takeNextReadyQueueItem();\n\t\t\tif (!next) break;\n\t\t\tthis.startFetch(next);\n\t\t}\n\n\t\tif (this.inflight.size >= this.maxConcurrency) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (this.queue.length === 0) return;\n\n\t\tconst earliestReadyAt = this.queue[0]?.readyAt;\n\t\tif (typeof earliestReadyAt !== \"number\") return;\n\t\tconst delay = Math.max(0, earliestReadyAt - nowMs());\n\t\tthis.timerId = window.setTimeout(() => {\n\t\t\tthis.timerId = null;\n\t\t\tthis.pump();\n\t\t}, delay);\n\t}\n\n\tprivate takeNextReadyQueueItem(): QueueItem | null {\n\t\tif (this.queue.length === 0) return null;\n\t\tconst now = nowMs();\n\t\tconst first = this.queue[0];\n\t\tif (!first || first.readyAt > now) return null;\n\n\t\tthis.queue.shift();\n\t\tthis.queuedByKey.delete(first.tile.key);\n\t\treturn first;\n\t}\n\n\tprivate startFetch(item: QueueItem): void {\n\t\tconst controller = new AbortController();\n\t\tconst inflightEntry: InflightItem = {\n\t\t\ttile: item.tile,\n\t\t\tattempt: item.attempt,\n\t\t\tcontroller,\n\t\t};\n\t\tthis.inflight.set(item.tile.key, inflightEntry);\n\t\tthis.emitStateChange();\n\n\t\tconst useAuthHeader = shouldAttachAuthHeader(item.tile.url, this.authToken);\n\t\tfetch(item.tile.url, {\n\t\t\tsignal: controller.signal,\n\t\t\theaders: useAuthHeader ? { Authorization: this.authToken } : undefined,\n\t\t})\n\t\t\t.then((response) => {\n\t\t\t\tif (!response.ok) {\n\t\t\t\t\tthrow new Error(`HTTP ${response.status}`);\n\t\t\t\t}\n\t\t\t\treturn response.blob();\n\t\t\t})\n\t\t\t.then((blob) => createImageBitmap(blob))\n\t\t\t.then((bitmap) => {\n\t\t\t\tif (this.destroyed || controller.signal.aborted) {\n\t\t\t\t\tbitmap.close();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (!this.visibleKeys.has(item.tile.key)) {\n\t\t\t\t\tbitmap.close();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tthis.onTileLoad(item.tile, bitmap);\n\t\t\t})\n\t\t\t.catch((error: unknown) => {\n\t\t\t\tif (controller.signal.aborted || this.destroyed) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst shouldRetry =\n\t\t\t\t\titem.attempt < this.maxRetries && this.visibleKeys.has(item.tile.key);\n\t\t\t\tif (shouldRetry) {\n\t\t\t\t\tthis.retryCount += 1;\n\t\t\t\t\tconst nextAttempt = item.attempt + 1;\n\t\t\t\t\tconst retryDelay = this.getRetryDelay(nextAttempt);\n\t\t\t\t\tconst queued: QueueItem = {\n\t\t\t\t\t\ttile: item.tile,\n\t\t\t\t\t\tattempt: nextAttempt,\n\t\t\t\t\t\treadyAt: nowMs() + retryDelay,\n\t\t\t\t\t};\n\t\t\t\t\tconst existing = this.queuedByKey.get(item.tile.key);\n\t\t\t\t\tif (existing) {\n\t\t\t\t\t\texisting.tile = queued.tile;\n\t\t\t\t\t\texisting.readyAt = Math.min(existing.readyAt, queued.readyAt);\n\t\t\t\t\t\texisting.attempt = Math.max(existing.attempt, queued.attempt);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthis.queue.push(queued);\n\t\t\t\t\t\tthis.queuedByKey.set(queued.tile.key, queued);\n\t\t\t\t\t}\n\t\t\t\t\tthis.sortQueue();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tthis.failedCount += 1;\n\t\t\t\tthis.onTileError?.(item.tile, error, item.attempt + 1);\n\t\t\t})\n\t\t\t.finally(() => {\n\t\t\t\tthis.inflight.delete(item.tile.key);\n\t\t\t\tthis.pump();\n\t\t\t\tthis.emitStateChange();\n\t\t\t});\n\t}\n\n\tprivate getRetryDelay(attempt: number): number {\n\t\tconst exp = Math.max(0, attempt - 1);\n\t\tconst delay = Math.min(\n\t\t\tthis.retryMaxDelayMs,\n\t\t\tthis.retryBaseDelayMs * 2 ** exp,\n\t\t);\n\t\tconst jitter = 0.85 + Math.random() * 0.3;\n\t\treturn Math.round(delay * jitter);\n\t}\n\n\tprivate clearPumpTimer(): void {\n\t\tif (this.timerId === null) return;\n\t\twindow.clearTimeout(this.timerId);\n\t\tthis.timerId = null;\n\t}\n\n\tprivate emitStateChange(): void {\n\t\tthis.onStateChange?.(this.getSnapshot());\n\t}\n}\n","import { toTileUrl } from \"./image-info\";\nimport {\n\tTileScheduler,\n\ttype ScheduledTile,\n\ttype TileBounds,\n} from \"./tile-scheduler\";\nimport type {\n\tWsiImageSource,\n\tWsiPointData,\n\tWsiRenderStats,\n\tWsiViewState,\n} from \"./types\";\nimport { clamp, createProgram } from \"./utils\";\n\ntype Bounds = TileBounds;\n\ninterface CachedTile {\n\tkey: string;\n\ttexture: WebGLTexture;\n\tbounds: Bounds;\n\ttier: number;\n\tlastUsed: number;\n}\n\ninterface TileVertexProgram {\n\tprogram: WebGLProgram;\n\tvao: WebGLVertexArrayObject;\n\tvbo: WebGLBuffer;\n\tuCamera: WebGLUniformLocation;\n\tuBounds: WebGLUniformLocation;\n\tuTexture: WebGLUniformLocation;\n}\n\ninterface PointProgram {\n\tprogram: WebGLProgram;\n\tvao: WebGLVertexArrayObject;\n\tposBuffer: WebGLBuffer;\n\ttermBuffer: WebGLBuffer;\n\tindexBuffer: WebGLBuffer;\n\tpaletteTexture: WebGLTexture;\n\tuCamera: WebGLUniformLocation;\n\tuPointSize: WebGLUniformLocation;\n\tuPalette: WebGLUniformLocation;\n\tuPaletteSize: WebGLUniformLocation;\n}\n\ninterface OrthoViewport {\n\twidth: number;\n\theight: number;\n}\n\ntype WorldPoint = [number, number];\nconst DEFAULT_ROTATION_DRAG_SENSITIVITY = 0.35;\nconst MIN_POINT_SIZE_PX = 0.5;\nconst MAX_POINT_SIZE_PX = 256;\n\ninterface PointSizeStop {\n\tzoom: number;\n\tsize: number;\n}\n\nconst DEFAULT_POINT_SIZE_STOPS: readonly PointSizeStop[] = [\n\t{ zoom: 1, size: 2.8 },\n\t{ zoom: 2, size: 3.4 },\n\t{ zoom: 3, size: 4.2 },\n\t{ zoom: 4, size: 5.3 },\n\t{ zoom: 5, size: 6.8 },\n\t{ zoom: 6, size: 8.4 },\n\t{ zoom: 7, size: 9.8 },\n\t{ zoom: 8, size: 11.2 },\n\t{ zoom: 9, size: 14.0 },\n\t{ zoom: 10, size: 17.5 },\n\t{ zoom: 11, size: 22.0 },\n\t{ zoom: 12, size: 28.0 },\n];\n\nexport type PointSizeByZoom = Readonly<Record<number, number>>;\n\nexport interface WsiTileSchedulerConfig {\n\tmaxConcurrency?: number;\n\tmaxRetries?: number;\n\tretryBaseDelayMs?: number;\n\tretryMaxDelayMs?: number;\n}\n\nexport interface WsiTileRendererOptions {\n\tonViewStateChange?: (next: WsiViewState) => void;\n\tonStats?: (stats: WsiRenderStats) => void;\n\tauthToken?: string;\n\tpointSizeByZoom?: PointSizeByZoom;\n\tmaxCacheTiles?: number;\n\tctrlDragRotate?: boolean;\n\trotationDragSensitivityDegPerPixel?: number;\n\ttileScheduler?: WsiTileSchedulerConfig;\n\tonTileError?: (event: WsiTileErrorEvent) => void;\n\tonContextLost?: () => void;\n\tonContextRestored?: () => void;\n}\n\nexport interface WsiTileErrorEvent {\n\ttile: ScheduledTile;\n\terror: unknown;\n\tattemptCount: number;\n}\n\nclass OrthoCamera {\n\tprivate viewportWidth = 1;\n\tprivate viewportHeight = 1;\n\tprivate viewState: WsiViewState = {\n\t\tzoom: 1,\n\t\toffsetX: 0,\n\t\toffsetY: 0,\n\t\trotationDeg: 0,\n\t};\n\n\tsetViewport(width: number, height: number): void {\n\t\tthis.viewportWidth = Math.max(1, width);\n\t\tthis.viewportHeight = Math.max(1, height);\n\t}\n\n\tgetViewport(): OrthoViewport {\n\t\treturn { width: this.viewportWidth, height: this.viewportHeight };\n\t}\n\n\tsetViewState(next: Partial<WsiViewState>): void {\n\t\tif (typeof next.zoom === \"number\") {\n\t\t\tthis.viewState.zoom = Math.max(0.0001, next.zoom);\n\t\t}\n\t\tif (typeof next.offsetX === \"number\") {\n\t\t\tthis.viewState.offsetX = next.offsetX;\n\t\t}\n\t\tif (typeof next.offsetY === \"number\") {\n\t\t\tthis.viewState.offsetY = next.offsetY;\n\t\t}\n\t\tif (typeof next.rotationDeg === \"number\" && Number.isFinite(next.rotationDeg)) {\n\t\t\tthis.viewState.rotationDeg = next.rotationDeg;\n\t\t}\n\t}\n\n\tgetViewState(): WsiViewState {\n\t\treturn { ...this.viewState };\n\t}\n\n\tgetCenter(): WorldPoint {\n\t\tconst zoom = Math.max(1e-6, this.viewState.zoom);\n\t\treturn [\n\t\t\tthis.viewState.offsetX + this.viewportWidth / (2 * zoom),\n\t\t\tthis.viewState.offsetY + this.viewportHeight / (2 * zoom),\n\t\t];\n\t}\n\n\tsetCenter(centerX: number, centerY: number): void {\n\t\tconst zoom = Math.max(1e-6, this.viewState.zoom);\n\t\tthis.viewState.offsetX = centerX - this.viewportWidth / (2 * zoom);\n\t\tthis.viewState.offsetY = centerY - this.viewportHeight / (2 * zoom);\n\t}\n\n\tscreenToWorld(screenX: number, screenY: number): WorldPoint {\n\t\tconst state = this.viewState;\n\t\tconst zoom = Math.max(1e-6, state.zoom);\n\t\tconst [centerX, centerY] = this.getCenter();\n\t\tconst dx = (screenX - this.viewportWidth * 0.5) / zoom;\n\t\tconst dy = (screenY - this.viewportHeight * 0.5) / zoom;\n\t\tconst rad = toRadians(state.rotationDeg);\n\t\tconst cos = Math.cos(rad);\n\t\tconst sin = Math.sin(rad);\n\t\treturn [centerX + dx * cos - dy * sin, centerY + dx * sin + dy * cos];\n\t}\n\n\tworldToScreen(worldX: number, worldY: number): WorldPoint {\n\t\tconst state = this.viewState;\n\t\tconst zoom = Math.max(1e-6, state.zoom);\n\t\tconst [centerX, centerY] = this.getCenter();\n\t\tconst dx = worldX - centerX;\n\t\tconst dy = worldY - centerY;\n\t\tconst rad = toRadians(state.rotationDeg);\n\t\tconst cos = Math.cos(rad);\n\t\tconst sin = Math.sin(rad);\n\t\tconst rx = dx * cos + dy * sin;\n\t\tconst ry = -dx * sin + dy * cos;\n\t\treturn [\n\t\t\tthis.viewportWidth * 0.5 + rx * zoom,\n\t\t\tthis.viewportHeight * 0.5 + ry * zoom,\n\t\t];\n\t}\n\n\tgetViewCorners(): [WorldPoint, WorldPoint, WorldPoint, WorldPoint] {\n\t\tconst w = this.viewportWidth;\n\t\tconst h = this.viewportHeight;\n\t\treturn [\n\t\t\tthis.screenToWorld(0, 0),\n\t\t\tthis.screenToWorld(w, 0),\n\t\t\tthis.screenToWorld(w, h),\n\t\t\tthis.screenToWorld(0, h),\n\t\t];\n\t}\n\n\tgetMatrix(): Float32Array {\n\t\tconst zoom = Math.max(1e-6, this.viewState.zoom);\n\t\tconst [centerX, centerY] = this.getCenter();\n\t\tconst rad = toRadians(this.viewState.rotationDeg);\n\t\tconst cos = Math.cos(rad);\n\t\tconst sin = Math.sin(rad);\n\n\t\tconst ax = (2 * zoom * cos) / this.viewportWidth;\n\t\tconst bx = (2 * zoom * sin) / this.viewportWidth;\n\t\tconst ay = (2 * zoom * sin) / this.viewportHeight;\n\t\tconst by = (-2 * zoom * cos) / this.viewportHeight;\n\t\tconst tx = -(ax * centerX + bx * centerY);\n\t\tconst ty = -(ay * centerX + by * centerY);\n\n\t\treturn new Float32Array([ax, ay, 0, bx, by, 0, tx, ty, 1]);\n\t}\n}\n\nfunction toRadians(deg: number): number {\n\treturn (deg * Math.PI) / 180;\n}\n\nfunction nowMs(): number {\n\tif (typeof performance !== \"undefined\" && typeof performance.now === \"function\") {\n\t\treturn performance.now();\n\t}\n\treturn Date.now();\n}\n\nfunction requireUniformLocation(\n\tgl: WebGL2RenderingContext,\n\tprogram: WebGLProgram,\n\tname: string,\n): WebGLUniformLocation {\n\tconst location = gl.getUniformLocation(program, name);\n\tif (!location) {\n\t\tthrow new Error(`uniform location lookup failed: ${name}`);\n\t}\n\treturn location;\n}\n\nfunction isSameArrayView(\n\ta: ArrayBufferView | null | undefined,\n\tb: ArrayBufferView | null | undefined,\n): boolean {\n\tif (!a || !b) return a === b;\n\treturn (\n\t\ta.buffer === b.buffer &&\n\t\ta.byteOffset === b.byteOffset &&\n\t\ta.byteLength === b.byteLength\n\t);\n}\n\nfunction clonePointSizeStops(stops: readonly PointSizeStop[]): PointSizeStop[] {\n\treturn stops.map(stop => ({ zoom: stop.zoom, size: stop.size }));\n}\n\nfunction normalizePointSizeStops(pointSizeByZoom: PointSizeByZoom | null | undefined): PointSizeStop[] {\n\tif (!pointSizeByZoom) return clonePointSizeStops(DEFAULT_POINT_SIZE_STOPS);\n\n\tconst parsed = new Map<number, number>();\n\tfor (const [zoomKey, rawSize] of Object.entries(pointSizeByZoom)) {\n\t\tconst zoom = Number(zoomKey);\n\t\tconst size = Number(rawSize);\n\t\tif (!Number.isFinite(zoom) || !Number.isFinite(size) || size <= 0) continue;\n\t\tparsed.set(zoom, size);\n\t}\n\n\tif (parsed.size === 0) {\n\t\treturn clonePointSizeStops(DEFAULT_POINT_SIZE_STOPS);\n\t}\n\n\treturn Array.from(parsed.entries())\n\t\t.sort((a, b) => a[0] - b[0])\n\t\t.map(([zoom, size]) => ({ zoom, size }));\n}\n\nfunction arePointSizeStopsEqual(a: readonly PointSizeStop[], b: readonly PointSizeStop[]): boolean {\n\tif (a === b) return true;\n\tif (a.length !== b.length) return false;\n\tfor (let i = 0; i < a.length; i += 1) {\n\t\tif (a[i].zoom !== b[i].zoom || a[i].size !== b[i].size) {\n\t\t\treturn false;\n\t\t}\n\t}\n\treturn true;\n}\n\nfunction resolvePointSizeByZoomStops(continuousZoom: number, stops: readonly PointSizeStop[]): number {\n\tif (!Number.isFinite(continuousZoom)) return stops[0]?.size ?? MIN_POINT_SIZE_PX;\n\tif (stops.length === 0) return MIN_POINT_SIZE_PX;\n\tif (stops.length === 1) return stops[0].size;\n\tif (continuousZoom <= stops[0].zoom) return stops[0].size;\n\n\tfor (let i = 1; i < stops.length; i += 1) {\n\t\tconst prev = stops[i - 1];\n\t\tconst next = stops[i];\n\t\tif (continuousZoom > next.zoom) continue;\n\t\tconst span = Math.max(1e-6, next.zoom - prev.zoom);\n\t\tconst t = clamp((continuousZoom - prev.zoom) / span, 0, 1);\n\t\treturn prev.size + (next.size - prev.size) * t;\n\t}\n\n\tconst last = stops[stops.length - 1];\n\tconst prev = stops[stops.length - 2];\n\tconst span = Math.max(1e-6, last.zoom - prev.zoom);\n\tconst slope = (last.size - prev.size) / span;\n\treturn last.size + (continuousZoom - last.zoom) * slope;\n}\n\nexport class WsiTileRenderer {\n\tprivate readonly canvas: HTMLCanvasElement;\n\tprivate readonly source: WsiImageSource;\n\tprivate readonly gl: WebGL2RenderingContext;\n\tprivate readonly camera = new OrthoCamera();\n\tprivate readonly onViewStateChange?: (next: WsiViewState) => void;\n\tprivate readonly onStats?: (stats: WsiRenderStats) => void;\n\tprivate readonly onTileError?: (event: WsiTileErrorEvent) => void;\n\tprivate readonly onContextLost?: () => void;\n\tprivate readonly onContextRestored?: () => void;\n\tprivate readonly resizeObserver: ResizeObserver;\n\tprivate tileProgram: TileVertexProgram;\n\tprivate pointProgram: PointProgram;\n\tprivate readonly tileScheduler: TileScheduler;\n\n\tprivate authToken: string;\n\tprivate destroyed = false;\n\tprivate contextLost = false;\n\tprivate frame: number | null = null;\n\tprivate frameSerial = 0;\n\tprivate dragging = false;\n\tprivate interactionMode: \"none\" | \"pan\" | \"rotate\" = \"none\";\n\tprivate rotateLastAngleRad: number | null = null;\n\tprivate pointerId: number | null = null;\n\tprivate lastPointerX = 0;\n\tprivate lastPointerY = 0;\n\tprivate interactionLocked = false;\n\tprivate ctrlDragRotate = true;\n\tprivate rotationDragSensitivityDegPerPixel = 0.35;\n\tprivate maxCacheTiles: number;\n\tprivate fitZoom = 1;\n\tprivate minZoom = 1e-6;\n\tprivate maxZoom = 1;\n\tprivate currentTier = 0;\n\tprivate pointCount = 0;\n\tprivate usePointIndices = false;\n\tprivate pointBuffersDirty = true;\n\tprivate pointPaletteSize = 1;\n\tprivate pointSizeStops: PointSizeStop[] = clonePointSizeStops(DEFAULT_POINT_SIZE_STOPS);\n\tprivate lastPointData: WsiPointData | null = null;\n\tprivate lastPointPalette: Uint8Array | null = null;\n\tprivate cache = new Map<string, CachedTile>();\n\n\tprivate readonly boundPointerDown: (event: PointerEvent) => void;\n\tprivate readonly boundPointerMove: (event: PointerEvent) => void;\n\tprivate readonly boundPointerUp: (event: PointerEvent) => void;\n\tprivate readonly boundWheel: (event: WheelEvent) => void;\n\tprivate readonly boundDoubleClick: (event: MouseEvent) => void;\n\tprivate readonly boundContextMenu: (event: MouseEvent) => void;\n\tprivate readonly boundContextLost: (event: Event) => void;\n\tprivate readonly boundContextRestored: (event: Event) => void;\n\n\tconstructor(\n\t\tcanvas: HTMLCanvasElement,\n\t\tsource: WsiImageSource,\n\t\toptions: WsiTileRendererOptions = {},\n\t) {\n\t\tthis.canvas = canvas;\n\t\tthis.source = source;\n\t\tthis.onViewStateChange = options.onViewStateChange;\n\t\tthis.onStats = options.onStats;\n\t\tthis.onTileError = options.onTileError;\n\t\tthis.onContextLost = options.onContextLost;\n\t\tthis.onContextRestored = options.onContextRestored;\n\t\tthis.authToken = options.authToken ?? \"\";\n\t\tthis.maxCacheTiles = Math.max(32, Math.floor(options.maxCacheTiles ?? 320));\n\t\tthis.ctrlDragRotate = options.ctrlDragRotate ?? true;\n\t\tthis.rotationDragSensitivityDegPerPixel =\n\t\t\ttypeof options.rotationDragSensitivityDegPerPixel === \"number\" &&\n\t\t\tNumber.isFinite(options.rotationDragSensitivityDegPerPixel)\n\t\t\t\t? Math.max(0, options.rotationDragSensitivityDegPerPixel)\n\t\t\t\t: DEFAULT_ROTATION_DRAG_SENSITIVITY;\n\t\tthis.pointSizeStops = normalizePointSizeStops(options.pointSizeByZoom);\n\n\t\tconst gl = canvas.getContext(\"webgl2\", {\n\t\t\talpha: false,\n\t\t\tantialias: false,\n\t\t\tdepth: false,\n\t\t\tstencil: false,\n\t\t\tpowerPreference: \"high-performance\",\n\t\t});\n\t\tif (!gl) {\n\t\t\tthrow new Error(\"WebGL2 not supported\");\n\t\t}\n\t\tthis.gl = gl;\n\n\t\tthis.tileProgram = this.initTileProgram();\n\t\tthis.pointProgram = this.initPointProgram();\n\t\tthis.tileScheduler = new TileScheduler({\n\t\t\tauthToken: this.authToken,\n\t\t\tmaxConcurrency: options.tileScheduler?.maxConcurrency ?? 12,\n\t\t\tmaxRetries: options.tileScheduler?.maxRetries ?? 2,\n\t\t\tretryBaseDelayMs: options.tileScheduler?.retryBaseDelayMs ?? 120,\n\t\t\tretryMaxDelayMs: options.tileScheduler?.retryMaxDelayMs ?? 1200,\n\t\t\tonTileLoad: (tile, bitmap) => this.handleTileLoaded(tile, bitmap),\n\t\t\tonTileError: (tile, error, attemptCount) => {\n\t\t\t\tthis.onTileError?.({ tile, error, attemptCount });\n\t\t\t\tconsole.warn(\"tile load failed\", tile.url, error);\n\t\t\t},\n\t\t});\n\n\t\tthis.resizeObserver = new ResizeObserver(() => this.resize());\n\t\tthis.resizeObserver.observe(canvas);\n\n\t\tthis.boundPointerDown = (event: PointerEvent) => this.onPointerDown(event);\n\t\tthis.boundPointerMove = (event: PointerEvent) => this.onPointerMove(event);\n\t\tthis.boundPointerUp = (event: PointerEvent) => this.onPointerUp(event);\n\t\tthis.boundWheel = (event: WheelEvent) => this.onWheel(event);\n\t\tthis.boundDoubleClick = (event: MouseEvent) => this.onDoubleClick(event);\n\t\tthis.boundContextMenu = (event: MouseEvent) => this.onContextMenu(event);\n\t\tthis.boundContextLost = (event: Event) => this.onWebGlContextLost(event);\n\t\tthis.boundContextRestored = (event: Event) =>\n\t\t\tthis.onWebGlContextRestored(event);\n\n\t\tcanvas.addEventListener(\"pointerdown\", this.boundPointerDown);\n\t\tcanvas.addEventListener(\"pointermove\", this.boundPointerMove);\n\t\tcanvas.addEventListener(\"pointerup\", this.boundPointerUp);\n\t\tcanvas.addEventListener(\"pointercancel\", this.boundPointerUp);\n\t\tcanvas.addEventListener(\"wheel\", this.boundWheel, { passive: false });\n\t\tcanvas.addEventListener(\"dblclick\", this.boundDoubleClick);\n\t\tcanvas.addEventListener(\"contextmenu\", this.boundContextMenu);\n\t\tcanvas.addEventListener(\"webglcontextlost\", this.boundContextLost);\n\t\tcanvas.addEventListener(\"webglcontextrestored\", this.boundContextRestored);\n\n\t\tthis.fitToImage();\n\t\tthis.resize();\n\t}\n\n\tsetAuthToken(token: string): void {\n\t\tthis.authToken = String(token ?? \"\");\n\t\tthis.tileScheduler.setAuthToken(this.authToken);\n\t}\n\n\tsetViewState(next: Partial<WsiViewState>): void {\n\t\tconst normalized: Partial<WsiViewState> = { ...next };\n\t\tif (typeof normalized.zoom === \"number\") {\n\t\t\tnormalized.zoom = clamp(normalized.zoom, this.minZoom, this.maxZoom);\n\t\t}\n\t\tthis.camera.setViewState(normalized);\n\t\tthis.clampViewState();\n\t\tthis.emitViewState();\n\t\tthis.requestRender();\n\t}\n\n\tgetViewState(): WsiViewState {\n\t\treturn this.camera.getViewState();\n\t}\n\n\tsetPointPalette(colors: Uint8Array | null | undefined): void {\n\t\tif (!colors || colors.length === 0) {\n\t\t\tthis.lastPointPalette = null;\n\t\t\treturn;\n\t\t}\n\t\tthis.lastPointPalette = new Uint8Array(colors);\n\t\tif (this.contextLost || this.gl.isContextLost()) return;\n\t\tconst gl = this.gl;\n\t\tconst paletteSize = Math.max(1, Math.floor(this.lastPointPalette.length / 4));\n\t\tthis.pointPaletteSize = paletteSize;\n\t\tgl.bindTexture(gl.TEXTURE_2D, this.pointProgram.paletteTexture);\n\t\tgl.texImage2D(\n\t\t\tgl.TEXTURE_2D,\n\t\t\t0,\n\t\t\tgl.RGBA,\n\t\t\tpaletteSize,\n\t\t\t1,\n\t\t\t0,\n\t\t\tgl.RGBA,\n\t\t\tgl.UNSIGNED_BYTE,\n\t\t\tthis.lastPointPalette,\n\t\t);\n\t\tgl.bindTexture(gl.TEXTURE_2D, null);\n\t\tthis.requestRender();\n\t}\n\n\tsetPointData(points: WsiPointData | null | undefined): void {\n\t\tif (!points || !points.count || !points.positions || !points.paletteIndices) {\n\t\t\tthis.lastPointData = null;\n\t\t\tthis.pointCount = 0;\n\t\t\tthis.usePointIndices = false;\n\t\t\tthis.requestRender();\n\t\t\treturn;\n\t\t}\n\n\t\tconst safeCount = Math.max(\n\t\t\t0,\n\t\t\tMath.min(\n\t\t\t\tpoints.count,\n\t\t\t\tMath.floor(points.positions.length / 2),\n\t\t\t\tpoints.paletteIndices.length,\n\t\t\t),\n\t\t);\n\t\tconst nextPositions = points.positions.subarray(0, safeCount * 2);\n\t\tconst nextPaletteIndices = points.paletteIndices.subarray(0, safeCount);\n\t\tconst hasDrawIndices = points.drawIndices instanceof Uint32Array;\n\t\tconst nextDrawIndices = hasDrawIndices\n\t\t\t? this.sanitizeDrawIndices(points.drawIndices as Uint32Array, safeCount)\n\t\t\t: null;\n\t\tconst prev = this.lastPointData;\n\t\tlet geometryChanged =\n\t\t\tthis.pointBuffersDirty ||\n\t\t\t!prev ||\n\t\t\tprev.count !== safeCount ||\n\t\t\t!isSameArrayView(prev.positions, nextPositions) ||\n\t\t\t!isSameArrayView(prev.paletteIndices, nextPaletteIndices);\n\t\tlet drawIndicesChanged =\n\t\t\tthis.pointBuffersDirty ||\n\t\t\t(hasDrawIndices &&\n\t\t\t\t(!prev?.drawIndices ||\n\t\t\t\t\t!isSameArrayView(prev.drawIndices, nextDrawIndices))) ||\n\t\t\t(!hasDrawIndices && !!prev?.drawIndices);\n\n\t\tthis.lastPointData = {\n\t\t\tcount: safeCount,\n\t\t\tpositions: nextPositions,\n\t\t\tpaletteIndices: nextPaletteIndices,\n\t\t\tdrawIndices: hasDrawIndices ? nextDrawIndices ?? undefined : undefined,\n\t\t};\n\t\tif (this.contextLost || this.gl.isContextLost()) return;\n\n\t\tconst gl = this.gl;\n\t\tif (geometryChanged) {\n\t\t\tgl.bindBuffer(gl.ARRAY_BUFFER, this.pointProgram.posBuffer);\n\t\t\tgl.bufferData(gl.ARRAY_BUFFER, this.lastPointData.positions, gl.STATIC_DRAW);\n\n\t\t\tgl.bindBuffer(gl.ARRAY_BUFFER, this.pointProgram.termBuffer);\n\t\t\tgl.bufferData(\n\t\t\t\tgl.ARRAY_BUFFER,\n\t\t\t\tthis.lastPointData.paletteIndices,\n\t\t\t\tgl.STATIC_DRAW,\n\t\t\t);\n\t\t\tgl.bindBuffer(gl.ARRAY_BUFFER, null);\n\t\t}\n\n\t\tif (hasDrawIndices && drawIndicesChanged) {\n\t\t\tgl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.pointProgram.indexBuffer);\n\t\t\tgl.bufferData(\n\t\t\t\tgl.ELEMENT_ARRAY_BUFFER,\n\t\t\t\tnextDrawIndices ?? new Uint32Array(0),\n\t\t\t\tgl.DYNAMIC_DRAW,\n\t\t\t);\n\t\t\tgl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);\n\t\t}\n\n\t\tthis.usePointIndices = hasDrawIndices;\n\t\tthis.pointCount = hasDrawIndices\n\t\t\t? (nextDrawIndices?.length ?? 0)\n\t\t\t: this.lastPointData.count;\n\t\tif (geometryChanged || drawIndicesChanged) {\n\t\t\tthis.pointBuffersDirty = false;\n\t\t}\n\t\tthis.requestRender();\n\t}\n\n\tprivate sanitizeDrawIndices(\n\t\tdrawIndices: Uint32Array,\n\t\tmaxExclusive: number,\n\t): Uint32Array {\n\t\tif (maxExclusive <= 0 || drawIndices.length === 0) {\n\t\t\treturn new Uint32Array(0);\n\t\t}\n\n\t\tlet validCount = drawIndices.length;\n\t\tfor (let i = 0; i < drawIndices.length; i += 1) {\n\t\t\tif (drawIndices[i] < maxExclusive) continue;\n\t\t\tvalidCount -= 1;\n\t\t}\n\t\tif (validCount === drawIndices.length) {\n\t\t\treturn drawIndices;\n\t\t}\n\t\tif (validCount <= 0) {\n\t\t\treturn new Uint32Array(0);\n\t\t}\n\n\t\tconst filtered = new Uint32Array(validCount);\n\t\tlet cursor = 0;\n\t\tfor (let i = 0; i < drawIndices.length; i += 1) {\n\t\t\tconst idx = drawIndices[i];\n\t\t\tif (idx >= maxExclusive) continue;\n\t\t\tfiltered[cursor] = idx;\n\t\t\tcursor += 1;\n\t\t}\n\t\treturn filtered;\n\t}\n\n\tsetInteractionLock(locked: boolean): void {\n\t\tconst next = Boolean(locked);\n\t\tif (this.interactionLocked === next) return;\n\t\tthis.interactionLocked = next;\n\t\tif (next) this.cancelDrag();\n\t}\n\n\tsetPointSizeByZoom(pointSizeByZoom: PointSizeByZoom | null | undefined): void {\n\t\tconst nextStops = normalizePointSizeStops(pointSizeByZoom);\n\t\tif (arePointSizeStopsEqual(this.pointSizeStops, nextStops)) return;\n\t\tthis.pointSizeStops = nextStops;\n\t\tthis.requestRender();\n\t}\n\n\tcancelDrag(): void {\n\t\tif (this.pointerId !== null && this.canvas.hasPointerCapture(this.pointerId)) {\n\t\t\ttry {\n\t\t\t\tthis.canvas.releasePointerCapture(this.pointerId);\n\t\t\t} catch {\n\t\t\t\t// noop\n\t\t\t}\n\t\t}\n\t\tthis.dragging = false;\n\t\tthis.interactionMode = \"none\";\n\t\tthis.rotateLastAngleRad = null;\n\t\tthis.pointerId = null;\n\t\tthis.canvas.classList.remove(\"dragging\");\n\t}\n\n\tprivate getPointerAngleRad(clientX: number, clientY: number): number {\n\t\tconst rect = this.canvas.getBoundingClientRect();\n\t\tconst x = clientX - rect.left - rect.width * 0.5;\n\t\tconst y = clientY - rect.top - rect.height * 0.5;\n\t\treturn Math.atan2(y, x);\n\t}\n\n\tscreenToWorld(clientX: number, clientY: number): [number, number] {\n\t\tconst rect = this.canvas.getBoundingClientRect();\n\t\tconst sx = clientX - rect.left;\n\t\tconst sy = clientY - rect.top;\n\t\treturn this.camera.screenToWorld(sx, sy);\n\t}\n\n\tworldToScreen(worldX: number, worldY: number): [number, number] {\n\t\treturn this.camera.worldToScreen(worldX, worldY);\n\t}\n\n\tsetViewCenter(worldX: number, worldY: number): void {\n\t\tif (!Number.isFinite(worldX) || !Number.isFinite(worldY)) return;\n\t\tthis.camera.setCenter(worldX, worldY);\n\t\tthis.clampViewState();\n\t\tthis.emitViewState();\n\t\tthis.requestRender();\n\t}\n\n\tgetViewCorners(): [WorldPoint, WorldPoint, WorldPoint, WorldPoint] {\n\t\treturn this.camera.getViewCorners();\n\t}\n\n\tresetRotation(): void {\n\t\tconst state = this.camera.getViewState();\n\t\tif (Math.abs(state.rotationDeg) < 1e-6) return;\n\t\tthis.camera.setViewState({ rotationDeg: 0 });\n\t\tthis.clampViewState();\n\t\tthis.emitViewState();\n\t\tthis.requestRender();\n\t}\n\n\tgetPointSizeByZoom(): number {\n\t\tconst zoom = Math.max(1e-6, this.camera.getViewState().zoom);\n\t\tconst continuousZoom = this.source.maxTierZoom + Math.log2(zoom);\n\t\tconst size = resolvePointSizeByZoomStops(continuousZoom, this.pointSizeStops);\n\t\treturn clamp(size, MIN_POINT_SIZE_PX, MAX_POINT_SIZE_PX);\n\t}\n\n\tfitToImage(): void {\n\t\tconst rect = this.canvas.getBoundingClientRect();\n\t\tconst vw = Math.max(1, rect.width || 1);\n\t\tconst vh = Math.max(1, rect.height || 1);\n\n\t\tconst zoom = Math.min(vw / this.source.width, vh / this.source.height);\n\t\tconst safeZoom = Number.isFinite(zoom) && zoom > 0 ? zoom : 1;\n\n\t\tthis.fitZoom = safeZoom;\n\t\tthis.minZoom = Math.max(this.fitZoom * 0.5, 1e-6);\n\t\tthis.maxZoom = Math.max(1, this.fitZoom * 8);\n\t\tif (this.minZoom > this.maxZoom) {\n\t\t\tthis.minZoom = this.maxZoom;\n\t\t}\n\n\t\tconst visibleWorldW = vw / safeZoom;\n\t\tconst visibleWorldH = vh / safeZoom;\n\n\t\tthis.camera.setViewState({\n\t\t\tzoom: clamp(safeZoom, this.minZoom, this.maxZoom),\n\t\t\toffsetX: (this.source.width - visibleWorldW) * 0.5,\n\t\t\toffsetY: (this.source.height - visibleWorldH) * 0.5,\n\t\t\trotationDeg: 0,\n\t\t});\n\n\t\tthis.clampViewState();\n\t\tthis.emitViewState();\n\t\tthis.requestRender();\n\t}\n\n\tzoomBy(factor: number, screenX: number, screenY: number): void {\n\t\tconst state = this.camera.getViewState();\n\t\tconst nextZoom = clamp(state.zoom * factor, this.minZoom, this.maxZoom);\n\t\tif (nextZoom === state.zoom) return;\n\n\t\tconst [worldX, worldY] = this.camera.screenToWorld(screenX, screenY);\n\n\t\tthis.camera.setViewState({ zoom: nextZoom });\n\n\t\tconst vp = this.camera.getViewport();\n\t\tconst dx = screenX - vp.width * 0.5;\n\t\tconst dy = screenY - vp.height * 0.5;\n\t\tconst rad = toRadians(this.camera.getViewState().rotationDeg);\n\t\tconst cos = Math.cos(rad);\n\t\tconst sin = Math.sin(rad);\n\t\tconst worldDx = (dx / nextZoom) * cos - (dy / nextZoom) * sin;\n\t\tconst worldDy = (dx / nextZoom) * sin + (dy / nextZoom) * cos;\n\t\tthis.camera.setCenter(worldX - worldDx, worldY - worldDy);\n\n\t\tthis.clampViewState();\n\t\tthis.emitViewState();\n\t\tthis.requestRender();\n\t}\n\n\tclampViewState(): void {\n\t\tconst bounds = this.getViewBounds();\n\t\tconst visibleW = Math.max(1e-6, bounds[2] - bounds[0]);\n\t\tconst visibleH = Math.max(1e-6, bounds[3] - bounds[1]);\n\t\tconst marginX = visibleW * 0.2;\n\t\tconst marginY = visibleH * 0.2;\n\n\t\tconst [centerX, centerY] = this.camera.getCenter();\n\t\tconst halfW = visibleW * 0.5;\n\t\tconst halfH = visibleH * 0.5;\n\n\t\tconst minCenterX = halfW - marginX;\n\t\tconst maxCenterX = this.source.width - halfW + marginX;\n\t\tconst minCenterY = halfH - marginY;\n\t\tconst maxCenterY = this.source.height - halfH + marginY;\n\n\t\tconst nextCenterX =\n\t\t\tminCenterX <= maxCenterX\n\t\t\t\t? clamp(centerX, minCenterX, maxCenterX)\n\t\t\t\t: this.source.width * 0.5;\n\t\tconst nextCenterY =\n\t\t\tminCenterY <= maxCenterY\n\t\t\t\t? clamp(centerY, minCenterY, maxCenterY)\n\t\t\t\t: this.source.height * 0.5;\n\n\t\tthis.camera.setCenter(nextCenterX, nextCenterY);\n\t}\n\n\temitViewState(): void {\n\t\tthis.onViewStateChange?.(this.camera.getViewState());\n\t}\n\n\tselectTier(): number {\n\t\tconst zoom = Math.max(1e-6, this.camera.getViewState().zoom);\n\t\tconst rawTier = this.source.maxTierZoom + Math.log2(zoom);\n\t\treturn clamp(Math.floor(rawTier), 0, this.source.maxTierZoom);\n\t}\n\n\tgetViewBounds(): Bounds {\n\t\tconst corners = this.camera.getViewCorners();\n\t\tlet minX = Infinity;\n\t\tlet minY = Infinity;\n\t\tlet maxX = -Infinity;\n\t\tlet maxY = -Infinity;\n\t\tfor (const [x, y] of corners) {\n\t\t\tif (x < minX) minX = x;\n\t\t\tif (x > maxX) maxX = x;\n\t\t\tif (y < minY) minY = y;\n\t\t\tif (y > maxY) maxY = y;\n\t\t}\n\t\treturn [minX, minY, maxX, maxY];\n\t}\n\n\tintersectsBounds(a: Bounds, b: Bounds): boolean {\n\t\treturn !(a[2] <= b[0] || a[0] >= b[2] || a[3] <= b[1] || a[1] >= b[3]);\n\t}\n\n\tgetVisibleTiles(): ScheduledTile[] {\n\t\tconst tier = this.selectTier();\n\t\tthis.currentTier = tier;\n\n\t\tconst viewBounds = this.getViewBounds();\n\n\t\tconst levelScale = Math.pow(2, this.source.maxTierZoom - tier);\n\t\tconst levelWidth = Math.ceil(this.source.width / levelScale);\n\t\tconst levelHeight = Math.ceil(this.source.height / levelScale);\n\n\t\tconst tilesX = Math.max(1, Math.ceil(levelWidth / this.source.tileSize));\n\t\tconst tilesY = Math.max(1, Math.ceil(levelHeight / this.source.tileSize));\n\n\t\tconst viewMinX = viewBounds[0];\n\t\tconst viewMinY = viewBounds[1];\n\t\tconst viewMaxX = viewBounds[2];\n\t\tconst viewMaxY = viewBounds[3];\n\n\t\tconst minTileX = clamp(\n\t\t\tMath.floor(viewMinX / levelScale / this.source.tileSize),\n\t\t\t0,\n\t\t\ttilesX - 1,\n\t\t);\n\t\tconst maxTileX = clamp(\n\t\t\tMath.floor((viewMaxX - 1) / levelScale / this.source.tileSize),\n\t\t\t0,\n\t\t\ttilesX - 1,\n\t\t);\n\t\tconst minTileY = clamp(\n\t\t\tMath.floor(viewMinY / levelScale / this.source.tileSize),\n\t\t\t0,\n\t\t\ttilesY - 1,\n\t\t);\n\t\tconst maxTileY = clamp(\n\t\t\tMath.floor((viewMaxY - 1) / levelScale / this.source.tileSize),\n\t\t\t0,\n\t\t\ttilesY - 1,\n\t\t);\n\n\t\tif (minTileX > maxTileX || minTileY > maxTileY) {\n\t\t\treturn [];\n\t\t}\n\n\t\tconst centerTileX = (viewMinX + viewMaxX) * 0.5 / levelScale / this.source.tileSize;\n\t\tconst centerTileY = (viewMinY + viewMaxY) * 0.5 / levelScale / this.source.tileSize;\n\n\t\tconst visible: ScheduledTile[] = [];\n\t\tfor (let y = minTileY; y <= maxTileY; y += 1) {\n\t\t\tfor (let x = minTileX; x <= maxTileX; x += 1) {\n\t\t\t\tconst left = x * this.source.tileSize * levelScale;\n\t\t\t\tconst top = y * this.source.tileSize * levelScale;\n\t\t\t\tconst right = Math.min((x + 1) * this.source.tileSize, levelWidth) * levelScale;\n\t\t\t\tconst bottom = Math.min((y + 1) * this.source.tileSize, levelHeight) * levelScale;\n\n\t\t\t\tconst dx = x - centerTileX;\n\t\t\t\tconst dy = y - centerTileY;\n\t\t\t\tvisible.push({\n\t\t\t\t\tkey: `${tier}/${x}/${y}`,\n\t\t\t\t\ttier,\n\t\t\t\t\tx,\n\t\t\t\t\ty,\n\t\t\t\t\tbounds: [left, top, right, bottom],\n\t\t\t\t\tdistance2: dx * dx + dy * dy,\n\t\t\t\t\turl: toTileUrl(this.source, tier, x, y),\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\tvisible.sort((a, b) => a.distance2 - b.distance2);\n\t\treturn visible;\n\t}\n\n\ttrimCache(): void {\n\t\tif (this.cache.size <= this.maxCacheTiles) return;\n\n\t\tconst entries = Array.from(this.cache.entries());\n\t\tentries.sort((a, b) => a[1].lastUsed - b[1].lastUsed);\n\n\t\tconst removeCount = this.cache.size - this.maxCacheTiles;\n\t\tfor (let i = 0; i < removeCount; i += 1) {\n\t\t\tconst [key, value] = entries[i];\n\t\t\tthis.gl.deleteTexture(value.texture);\n\t\t\tthis.cache.delete(key);\n\t\t}\n\t}\n\n\trender(): void {\n\t\tif (this.destroyed || this.contextLost || this.gl.isContextLost()) return;\n\t\tconst frameStartMs = nowMs();\n\t\tthis.frameSerial += 1;\n\n\t\tconst gl = this.gl;\n\t\tconst tileProgram = this.tileProgram;\n\t\tconst pointProgram = this.pointProgram;\n\n\t\tgl.clearColor(0.03, 0.06, 0.1, 1);\n\t\tgl.clear(gl.COLOR_BUFFER_BIT);\n\n\t\tconst visible = this.getVisibleTiles();\n\t\tconst viewBounds = this.getViewBounds();\n\t\tconst visibleKeys = new Set(visible.map((tile) => tile.key));\n\n\t\tgl.useProgram(tileProgram.program);\n\t\tgl.bindVertexArray(tileProgram.vao);\n\t\tgl.uniformMatrix3fv(tileProgram.uCamera, false, this.camera.getMatrix());\n\t\tgl.uniform1i(tileProgram.uTexture, 0);\n\n\t\tconst fallbackTiles: CachedTile[] = [];\n\t\tfor (const [, cached] of this.cache) {\n\t\t\tif (visibleKeys.has(cached.key)) continue;\n\t\t\tif (!this.intersectsBounds(cached.bounds, viewBounds)) continue;\n\t\t\tfallbackTiles.push(cached);\n\t\t}\n\n\t\tfallbackTiles.sort((a, b) => a.tier - b.tier);\n\t\tfor (const cached of fallbackTiles) {\n\t\t\tcached.lastUsed = this.frameSerial;\n\t\t\tgl.activeTexture(gl.TEXTURE0);\n\t\t\tgl.bindTexture(gl.TEXTURE_2D, cached.texture);\n\t\t\tgl.uniform4f(\n\t\t\t\ttileProgram.uBounds,\n\t\t\t\tcached.bounds[0],\n\t\t\t\tcached.bounds[1],\n\t\t\t\tcached.bounds[2],\n\t\t\t\tcached.bounds[3],\n\t\t\t);\n\t\t\tgl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);\n\t\t}\n\n\t\tlet renderedTiles = 0;\n\t\tconst missingTiles: ScheduledTile[] = [];\n\t\tfor (const tile of visible) {\n\t\t\tconst cached = this.cache.get(tile.key);\n\t\t\tif (!cached) {\n\t\t\t\tmissingTiles.push(tile);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tcached.lastUsed = this.frameSerial;\n\t\t\tgl.activeTexture(gl.TEXTURE0);\n\t\t\tgl.bindTexture(gl.TEXTURE_2D, cached.texture);\n\t\t\tgl.uniform4f(\n\t\t\t\ttileProgram.uBounds,\n\t\t\t\tcached.bounds[0],\n\t\t\t\tcached.bounds[1],\n\t\t\t\tcached.bounds[2],\n\t\t\t\tcached.bounds[3],\n\t\t\t);\n\t\t\tgl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);\n\t\t\trenderedTiles += 1;\n\t\t}\n\t\tthis.tileScheduler.schedule(missingTiles);\n\n\t\tgl.bindTexture(gl.TEXTURE_2D, null);\n\t\tgl.bindVertexArray(null);\n\n\t\tlet renderedPoints = 0;\n\t\tif (this.pointCount > 0) {\n\t\t\tgl.enable(gl.BLEND);\n\t\t\tgl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);\n\t\t\tgl.useProgram(pointProgram.program);\n\t\t\tgl.bindVertexArray(pointProgram.vao);\n\t\t\tgl.uniformMatrix3fv(pointProgram.uCamera, false, this.camera.getMatrix());\n\t\t\tgl.uniform1f(pointProgram.uPointSize, this.getPointSizeByZoom());\n\t\t\tgl.uniform1f(pointProgram.uPaletteSize, this.pointPaletteSize);\n\t\t\tgl.uniform1i(pointProgram.uPalette, 1);\n\t\t\tgl.activeTexture(gl.TEXTURE1);\n\t\t\tgl.bindTexture(gl.TEXTURE_2D, pointProgram.paletteTexture);\n\t\t\tif (this.usePointIndices) {\n\t\t\t\tgl.drawElements(gl.POINTS, this.pointCount, gl.UNSIGNED_INT, 0);\n\t\t\t} else {\n\t\t\t\tgl.drawArrays(gl.POINTS, 0, this.pointCount);\n\t\t\t}\n\t\t\tgl.bindTexture(gl.TEXTURE_2D, null);\n\t\t\tgl.bindVertexArray(null);\n\t\t\trenderedPoints = this.pointCount;\n\t\t}\n\n\t\tif (this.onStats) {\n\t\t\tconst schedulerStats = this.tileScheduler.getSnapshot();\n\t\t\tconst cacheHits = renderedTiles;\n\t\t\tconst cacheMisses = missingTiles.length;\n\t\t\tconst drawCalls =\n\t\t\t\tfallbackTiles.length + renderedTiles + (renderedPoints > 0 ? 1 : 0);\n\t\t\tthis.onStats({\n\t\t\t\ttier: this.currentTier,\n\t\t\t\tvisible: visible.length,\n\t\t\t\trendered: renderedTiles,\n\t\t\t\tpoints: renderedPoints,\n\t\t\t\tfallback: fallbackTiles.length,\n\t\t\t\tcache: this.cache.size,\n\t\t\t\tinflight: schedulerStats.inflight,\n\t\t\t\tqueued: schedulerStats.queued,\n\t\t\t\tretries: schedulerStats.retries,\n\t\t\t\tfailed: schedulerStats.failed,\n\t\t\t\taborted: schedulerStats.aborted,\n\t\t\t\tcacheHits,\n\t\t\t\tcacheMisses,\n\t\t\t\tdrawCalls,\n\t\t\t\tframeMs: nowMs() - frameStartMs,\n\t\t\t});\n\t\t}\n\t}\n\n\trequestRender(): void {\n\t\tif (\n\t\t\tthis.frame !== null ||\n\t\t\tthis.destroyed ||\n\t\t\tthis.contextLost ||\n\t\t\tthis.gl.isContextLost()\n\t\t)\n\t\t\treturn;\n\t\tthis.frame = requestAnimationFrame(() => {\n\t\t\tthis.frame = null;\n\t\t\tthis.render();\n\t\t});\n\t}\n\n\tresize(): void {\n\t\tconst rect = this.canvas.getBoundingClientRect();\n\t\tconst cssW = Math.max(1, rect.width || this.canvas.clientWidth || 1);\n\t\tconst cssH = Math.max(1, rect.height || this.canvas.clientHeight || 1);\n\t\tconst dpr = Math.max(1, window.devicePixelRatio || 1);\n\n\t\tconst pixelW = Math.max(1, Math.round(cssW * dpr));\n\t\tconst pixelH = Math.max(1, Math.round(cssH * dpr));\n\n\t\tif (this.canvas.width !== pixelW || this.canvas.height !== pixelH) {\n\t\t\tthis.canvas.width = pixelW;\n\t\t\tthis.canvas.height = pixelH;\n\t\t}\n\n\t\tthis.camera.setViewport(cssW, cssH);\n\t\tthis.gl.viewport(0, 0, pixelW, pixelH);\n\t\tthis.requestRender();\n\t}\n\n\tonPointerDown(event: PointerEvent): void {\n\t\tif (this.interactionLocked) return;\n\t\tconst wantsRotate = this.ctrlDragRotate && (event.ctrlKey || event.metaKey);\n\t\tconst allowButton = event.button === 0 || (wantsRotate && event.button === 2);\n\t\tif (!allowButton) return;\n\t\tif (wantsRotate) {\n\t\t\tevent.preventDefault();\n\t\t}\n\t\tthis.dragging = true;\n\t\tthis.interactionMode =\n\t\t\twantsRotate ? \"rotate\" : \"pan\";\n\t\tthis.pointerId = event.pointerId;\n\t\tthis.lastPointerX = event.clientX;\n\t\tthis.lastPointerY = event.clientY;\n\t\tthis.rotateLastAngleRad =\n\t\t\tthis.interactionMode === \"rotate\"\n\t\t\t\t? this.getPointerAngleRad(event.clientX, event.clientY)\n\t\t\t\t: null;\n\t\tthis.canvas.classList.add(\"dragging\");\n\t\tthis.canvas.setPointerCapture(event.pointerId);\n\t}\n\n\tonPointerMove(event: PointerEvent): void {\n\t\tif (this.interactionLocked) return;\n\t\tif (!this.dragging || event.pointerId !== this.pointerId) return;\n\n\t\tconst dx = event.clientX - this.lastPointerX;\n\t\tconst dy = event.clientY - this.lastPointerY;\n\t\tthis.lastPointerX = event.clientX;\n\t\tthis.lastPointerY = event.clientY;\n\n\t\tif (this.interactionMode === \"rotate\") {\n\t\t\tconst nextAngle = this.getPointerAngleRad(event.clientX, event.clientY);\n\t\t\tconst prevAngle = this.rotateLastAngleRad;\n\t\t\tthis.rotateLastAngleRad = nextAngle;\n\t\t\tif (prevAngle !== null) {\n\t\t\t\tconst rawDelta = nextAngle - prevAngle;\n\t\t\t\tconst delta = Math.atan2(Math.sin(rawDelta), Math.cos(rawDelta));\n\n\t\t\t\tconst sensitivityScale =\n\t\t\t\t\tDEFAULT_ROTATION_DRAG_SENSITIVITY > 0\n\t\t\t\t\t\t? this.rotationDragSensitivityDegPerPixel /\n\t\t\t\t\t\t\tDEFAULT_ROTATION_DRAG_SENSITIVITY\n\t\t\t\t\t\t: 1;\n\t\t\t\tconst state = this.camera.getViewState();\n\t\t\t\tthis.camera.setViewState({\n\t\t\t\t\trotationDeg:\n\t\t\t\t\t\tstate.rotationDeg - ((delta * 180) / Math.PI) * sensitivityScale,\n\t\t\t\t});\n\t\t\t}\n\t\t} else {\n\t\t\tconst state = this.camera.getViewState();\n\t\t\tconst zoom = Math.max(1e-6, state.zoom);\n\t\t\tconst rad = toRadians(state.rotationDeg);\n\t\t\tconst cos = Math.cos(rad);\n\t\t\tconst sin = Math.sin(rad);\n\t\t\tconst worldDx = (dx * cos - dy * sin) / zoom;\n\t\t\tconst worldDy = (dx * sin + dy * cos) / zoom;\n\t\t\tthis.camera.setViewState({\n\t\t\t\toffsetX: state.offsetX - worldDx,\n\t\t\t\toffsetY: state.offsetY - worldDy,\n\t\t\t});\n\t\t}\n\n\t\tthis.clampViewState();\n\t\tthis.emitViewState();\n\t\tthis.requestRender();\n\t}\n\n\tonPointerUp(event: PointerEvent): void {\n\t\tif (this.interactionLocked) return;\n\t\tif (event.pointerId !== this.pointerId) return;\n\t\tthis.cancelDrag();\n\t}\n\n\tonWheel(event: WheelEvent): void {\n\t\tif (this.interactionLocked) {\n\t\t\tevent.preventDefault();\n\t\t\treturn;\n\t\t}\n\n\t\tevent.preventDefault();\n\t\tconst rect = this.canvas.getBoundingClientRect();\n\t\tconst x = event.clientX - rect.left;\n\t\tconst y = event.clientY - rect.top;\n\t\tconst factor = event.deltaY < 0 ? 1.12 : 0.89;\n\t\tthis.zoomBy(factor, x, y);\n\t}\n\n\tonDoubleClick(event: MouseEvent): void {\n\t\tif (this.interactionLocked) return;\n\t\tconst rect = this.canvas.getBoundingClientRect();\n\t\tconst x = event.clientX - rect.left;\n\t\tconst y = event.clientY - rect.top;\n\t\tthis.zoomBy(event.shiftKey ? 0.8 : 1.25, x, y);\n\t}\n\n\tonContextMenu(event: MouseEvent): void {\n\t\tif (this.dragging || event.ctrlKey || event.metaKey) {\n\t\t\tevent.preventDefault();\n\t\t}\n\t}\n\n\tprivate onWebGlContextLost(event: Event): void {\n\t\tevent.preventDefault();\n\t\tif (this.destroyed || this.contextLost) return;\n\t\tthis.contextLost = true;\n\t\tthis.pointBuffersDirty = true;\n\n\t\tif (this.frame !== null) {\n\t\t\tcancelAnimationFrame(this.frame);\n\t\t\tthis.frame = null;\n\t\t}\n\n\t\tthis.cancelDrag();\n\t\tthis.tileScheduler.clear();\n\t\tthis.cache.clear();\n\t\tthis.onContextLost?.();\n\t}\n\n\tprivate onWebGlContextRestored(_event: Event): void {\n\t\tif (this.destroyed) return;\n\t\tthis.contextLost = false;\n\t\tthis.cache.clear();\n\n\t\tthis.tileProgram = this.initTileProgram();\n\t\tthis.pointProgram = this.initPointProgram();\n\t\tthis.pointBuffersDirty = true;\n\n\t\tif (this.lastPointPalette && this.lastPointPalette.length > 0) {\n\t\t\tthis.setPointPalette(this.lastPointPalette);\n\t\t}\n\t\tif (this.lastPointData) {\n\t\t\tthis.setPointData(this.lastPointData);\n\t\t} else {\n\t\t\tthis.pointCount = 0;\n\t\t}\n\n\t\tthis.resize();\n\t\tthis.requestRender();\n\t\tthis.onContextRestored?.();\n\t}\n\n\tdestroy(): void {\n\t\tif (this.destroyed) return;\n\t\tthis.destroyed = true;\n\n\t\tif (this.frame !== null) {\n\t\t\tcancelAnimationFrame(this.frame);\n\t\t\tthis.frame = null;\n\t\t}\n\n\t\tthis.resizeObserver.disconnect();\n\t\tthis.canvas.removeEventListener(\"pointerdown\", this.boundPointerDown);\n\t\tthis.canvas.removeEventListener(\"pointermove\", this.boundPointerMove);\n\t\tthis.canvas.removeEventListener(\"pointerup\", this.boundPointerUp);\n\t\tthis.canvas.removeEventListener(\"pointercancel\", this.boundPointerUp);\n\t\tthis.canvas.removeEventListener(\"wheel\", this.boundWheel);\n\t\tthis.canvas.removeEventListener(\"dblclick\", this.boundDoubleClick);\n\t\tthis.canvas.removeEventListener(\"contextmenu\", this.boundContextMenu);\n\t\tthis.canvas.removeEventListener(\"webglcontextlost\", this.boundContextLost);\n\t\tthis.canvas.removeEventListener(\n\t\t\t\"webglcontextrestored\",\n\t\t\tthis.boundContextRestored,\n\t\t);\n\t\tthis.cancelDrag();\n\t\tthis.tileScheduler.destroy();\n\n\t\tif (!this.contextLost && !this.gl.isContextLost()) {\n\t\t\tfor (const [, value] of this.cache) {\n\t\t\t\tthis.gl.deleteTexture(value.texture);\n\t\t\t}\n\t\t\tthis.gl.deleteBuffer(this.tileProgram.vbo);\n\t\t\tthis.gl.deleteVertexArray(this.tileProgram.vao);\n\t\t\tthis.gl.deleteProgram(this.tileProgram.program);\n\n\t\t\tthis.gl.deleteBuffer(this.pointProgram.posBuffer);\n\t\t\tthis.gl.deleteBuffer(this.pointProgram.termBuffer);\n\t\t\tthis.gl.deleteBuffer(this.pointProgram.indexBuffer);\n\t\t\tthis.gl.deleteTexture(this.pointProgram.paletteTexture);\n\t\t\tthis.gl.deleteVertexArray(this.pointProgram.vao);\n\t\t\tthis.gl.deleteProgram(this.pointProgram.program);\n\t\t}\n\t\tthis.cache.clear();\n\t}\n\n\tprivate initTileProgram(): TileVertexProgram {\n\t\tconst gl = this.gl;\n\n\t\tconst vertex = `#version 300 es\n precision highp float;\n in vec2 aUnit;\n in vec2 aUv;\n uniform mat3 uCamera;\n uniform vec4 uBounds;\n out vec2 vUv;\n void main() {\n vec2 world = vec2(\n mix(uBounds.x, uBounds.z, aUnit.x),\n mix(uBounds.y, uBounds.w, aUnit.y)\n );\n vec3 clip = uCamera * vec3(world, 1.0);\n gl_Position = vec4(clip.xy, 0.0, 1.0);\n vUv = aUv;\n }`;\n\n\t\tconst fragment = `#version 300 es\n precision highp float;\n in vec2 vUv;\n uniform sampler2D uTexture;\n out vec4 outColor;\n void main() {\n outColor = texture(uTexture, vUv);\n }`;\n\n\t\tconst program = createProgram(gl, vertex, fragment);\n\t\tconst uCamera = requireUniformLocation(gl, program, \"uCamera\");\n\t\tconst uBounds = requireUniformLocation(gl, program, \"uBounds\");\n\t\tconst uTexture = requireUniformLocation(gl, program, \"uTexture\");\n\n\t\tconst vao = gl.createVertexArray();\n\t\tconst vbo = gl.createBuffer();\n\t\tif (!vao || !vbo) {\n\t\t\tthrow new Error(\"buffer allocation failed\");\n\t\t}\n\n\t\tgl.bindVertexArray(vao);\n\t\tgl.bindBuffer(gl.ARRAY_BUFFER, vbo);\n\t\tgl.bufferData(\n\t\t\tgl.ARRAY_BUFFER,\n\t\t\tnew Float32Array([0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1]),\n\t\t\tgl.STATIC_DRAW,\n\t\t);\n\n\t\tconst aUnit = gl.getAttribLocation(program, \"aUnit\");\n\t\tconst aUv = gl.getAttribLocation(program, \"aUv\");\n\t\tif (aUnit < 0 || aUv < 0) {\n\t\t\tthrow new Error(\"tile attribute lookup failed\");\n\t\t}\n\t\tgl.enableVertexAttribArray(aUnit);\n\t\tgl.enableVertexAttribArray(aUv);\n\t\tgl.vertexAttribPointer(aUnit, 2, gl.FLOAT, false, 16, 0);\n\t\tgl.vertexAttribPointer(aUv, 2, gl.FLOAT, false, 16, 8);\n\n\t\tgl.bindVertexArray(null);\n\t\tgl.bindBuffer(gl.ARRAY_BUFFER, null);\n\n\t\treturn { program, vao, vbo, uCamera, uBounds, uTexture };\n\t}\n\n\tprivate initPointProgram(): PointProgram {\n\t\tconst gl = this.gl;\n\n\t\tconst pointVertex = `#version 300 es\n precision highp float;\n in vec2 aPosition;\n in uint aTerm;\n uniform mat3 uCamera;\n uniform float uPointSize;\n flat out uint vTerm;\n void main() {\n vec3 clip = uCamera * vec3(aPosition, 1.0);\n gl_Position = vec4(clip.xy, 0.0, 1.0);\n gl_PointSize = uPointSize;\n vTerm = aTerm;\n }`;\n\n\t\tconst pointFragment = `#version 300 es\n precision highp float;\n flat in uint vTerm;\n uniform sampler2D uPalette;\n uniform float uPaletteSize;\n uniform float uPointSize;\n out vec4 outColor;\n void main() {\n vec2 pc = gl_PointCoord * 2.0 - 1.0;\n float r = length(pc);\n if (r > 1.0) discard;\n\n float idx = clamp(float(vTerm), 0.0, max(0.0, uPaletteSize - 1.0));\n vec2 uv = vec2((idx + 0.5) / uPaletteSize, 0.5);\n vec4 color = texture(uPalette, uv);\n if (color.a <= 0.0) discard;\n\n float ringWidth = clamp(3.0 / max(1.0, uPointSize), 0.12, 0.62);\n float innerRadius = 1.0 - ringWidth;\n float aa = 1.5 / max(1.0, uPointSize);\n\n float outerMask = 1.0 - smoothstep(1.0 - aa, 1.0 + aa, r);\n float innerMask = smoothstep(innerRadius - aa, innerRadius + aa, r);\n float alpha = outerMask * innerMask * color.a;\n if (alpha <= 0.001) discard;\n\n outColor = vec4(color.rgb * alpha, alpha);\n }`;\n\n\t\tconst program = createProgram(gl, pointVertex, pointFragment);\n\t\tconst uCamera = requireUniformLocation(gl, program, \"uCamera\");\n\t\tconst uPointSize = requireUniformLocation(gl, program, \"uPointSize\");\n\t\tconst uPalette = requireUniformLocation(gl, program, \"uPalette\");\n\t\tconst uPaletteSize = requireUniformLocation(gl, program, \"uPaletteSize\");\n\n\t\tconst vao = gl.createVertexArray();\n\t\tconst posBuffer = gl.createBuffer();\n\t\tconst termBuffer = gl.createBuffer();\n\t\tconst indexBuffer = gl.createBuffer();\n\t\tconst paletteTexture = gl.createTexture();\n\t\tif (!vao || !posBuffer || !termBuffer || !indexBuffer || !paletteTexture) {\n\t\t\tthrow new Error(\"point buffer allocation failed\");\n\t\t}\n\n\t\tgl.bindVertexArray(vao);\n\n\t\tgl.bindBuffer(gl.ARRAY_BUFFER, posBuffer);\n\t\tgl.bufferData(gl.ARRAY_BUFFER, 0, gl.DYNAMIC_DRAW);\n\t\tconst posLoc = gl.getAttribLocation(program, \"aPosition\");\n\t\tif (posLoc < 0) {\n\t\t\tthrow new Error(\"point position attribute not found\");\n\t\t}\n\t\tgl.enableVertexAttribArray(posLoc);\n\t\tgl.vertexAttribPointer(posLoc, 2, gl.FLOAT, false, 0, 0);\n\n\t\tgl.bindBuffer(gl.ARRAY_BUFFER, termBuffer);\n\t\tgl.bufferData(gl.ARRAY_BUFFER, 0, gl.DYNAMIC_DRAW);\n\t\tconst termLoc = gl.getAttribLocation(program, \"aTerm\");\n\t\tif (termLoc < 0) {\n\t\t\tthrow new Error(\"point term attribute not found\");\n\t\t}\n\t\tgl.enableVertexAttribArray(termLoc);\n\t\tgl.vertexAttribIPointer(termLoc, 1, gl.UNSIGNED_SHORT, 0, 0);\n\n\t\tgl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);\n\t\tgl.bufferData(gl.ELEMENT_ARRAY_BUFFER, 0, gl.DYNAMIC_DRAW);\n\n\t\tgl.bindVertexArray(null);\n\t\tgl.bindBuffer(gl.ARRAY_BUFFER, null);\n\t\tgl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);\n\n\t\tgl.bindTexture(gl.TEXTURE_2D, paletteTexture);\n\t\tgl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);\n\t\tgl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);\n\t\tgl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);\n\t\tgl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);\n\t\tgl.texImage2D(\n\t\t\tgl.TEXTURE_2D,\n\t\t\t0,\n\t\t\tgl.RGBA,\n\t\t\t1,\n\t\t\t1,\n\t\t\t0,\n\t\t\tgl.RGBA,\n\t\t\tgl.UNSIGNED_BYTE,\n\t\t\tnew Uint8Array([160, 160, 160, 255]),\n\t\t);\n\t\tgl.bindTexture(gl.TEXTURE_2D, null);\n\n\t\treturn {\n\t\t\tprogram,\n\t\t\tvao,\n\t\t\tposBuffer,\n\t\t\ttermBuffer,\n\t\t\tindexBuffer,\n\t\t\tpaletteTexture,\n\t\t\tuCamera,\n\t\t\tuPointSize,\n\t\t\tuPalette,\n\t\t\tuPaletteSize,\n\t\t};\n\t}\n\n\tprivate handleTileLoaded(tile: ScheduledTile, bitmap: ImageBitmap): void {\n\t\tif (this.destroyed || this.contextLost || this.gl.isContextLost()) {\n\t\t\tbitmap.close();\n\t\t\treturn;\n\t\t}\n\t\tif (this.cache.has(tile.key)) {\n\t\t\tbitmap.close();\n\t\t\treturn;\n\t\t}\n\n\t\tconst texture = this.createTextureFromBitmap(bitmap);\n\t\tbitmap.close();\n\t\tif (!texture) return;\n\n\t\tthis.cache.set(tile.key, {\n\t\t\tkey: tile.key,\n\t\t\ttexture,\n\t\t\tbounds: tile.bounds,\n\t\t\ttier: tile.tier,\n\t\t\tlastUsed: this.frameSerial,\n\t\t});\n\t\tthis.trimCache();\n\t\tthis.requestRender();\n\t}\n\n\tprivate createTextureFromBitmap(bitmap: ImageBitmap): WebGLTexture | null {\n\t\tif (this.contextLost || this.gl.isContextLost()) return null;\n\t\tconst gl = this.gl;\n\t\tconst texture = gl.createTexture();\n\t\tif (!texture) return null;\n\n\t\tgl.bindTexture(gl.TEXTURE_2D, texture);\n\t\tgl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1);\n\t\tgl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);\n\t\tgl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);\n\t\tgl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);\n\t\tgl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);\n\t\tgl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, bitmap);\n\t\tgl.bindTexture(gl.TEXTURE_2D, null);\n\t\treturn texture;\n\t}\n}\n","import { type CSSProperties, type MouseEvent as ReactMouseEvent, type MutableRefObject, type ReactNode, type PointerEvent as ReactPointerEvent, useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { filterPointDataByPolygons, type RoiPolygon } from \"../wsi/point-clip\";\nimport { filterPointDataByPolygonsHybrid } from \"../wsi/point-clip-hybrid\";\nimport { filterPointDataByPolygonsInWorker, type PointClipMode } from \"../wsi/point-clip-worker-client\";\nimport { computeRoiPointGroups, type RoiPointGroupStats } from \"../wsi/roi-term-stats\";\nimport type { WsiImageSource, WsiPointData, WsiRegion, WsiRenderStats, WsiViewState } from \"../wsi/types\";\nimport { type PointSizeByZoom, type WsiTileErrorEvent, WsiTileRenderer } from \"../wsi/wsi-tile-renderer\";\nimport type { BrushOptions, DrawCoordinate, DrawOverlayShape, DrawResult, DrawTool, PatchDrawResult, RegionLabelStyle, RegionStrokeStyle, RegionStrokeStyleResolver, StampOptions } from \"./draw-layer\";\nimport { DrawLayer } from \"./draw-layer\";\nimport { OverviewMap, type OverviewMapOptions } from \"./overview-map\";\n\nconst EMPTY_ROI_REGIONS: WsiRegion[] = [];\nconst EMPTY_ROI_POLYGONS: DrawCoordinate[][] = [];\nconst EMPTY_CLIPPED_POINTS: WsiPointData = {\n count: 0,\n positions: new Float32Array(0),\n paletteIndices: new Uint16Array(0),\n};\nconst POINT_HIT_RADIUS_SCALE = 0.65;\nconst MIN_POINT_HIT_RADIUS_PX = 4;\nconst MIN_POINT_HIT_GRID_SIZE = 24;\nconst MAX_POINT_HIT_GRID_SIZE = 1024;\nconst POINT_HIT_GRID_DENSITY_SCALE = 4;\n\nexport interface RegionHoverEvent {\n region: WsiRegion | null;\n regionId: string | number | null;\n regionIndex: number;\n coordinate: DrawCoordinate | null;\n}\n\nexport interface RegionClickEvent {\n region: WsiRegion;\n regionId: string | number;\n regionIndex: number;\n coordinate: DrawCoordinate;\n}\n\nexport interface PointHitEvent {\n index: number;\n id: number | null;\n coordinate: DrawCoordinate;\n pointCoordinate: DrawCoordinate;\n}\n\nexport interface PointClickEvent extends PointHitEvent {\n button: number;\n}\n\nexport interface PointHoverEvent {\n index: number | null;\n id: number | null;\n coordinate: DrawCoordinate | null;\n pointCoordinate: DrawCoordinate | null;\n}\n\nexport interface PointClipStatsEvent {\n mode: PointClipMode;\n durationMs: number;\n inputCount: number;\n outputCount: number;\n polygonCount: number;\n usedWebGpu?: boolean;\n candidateCount?: number;\n bridgedToDraw?: boolean;\n}\n\nexport interface PointerWorldMoveEvent {\n coordinate: DrawCoordinate | null;\n clientX: number;\n clientY: number;\n insideImage: boolean;\n}\n\nexport interface WsiCustomLayerContext {\n source: WsiImageSource;\n viewState: WsiViewState;\n drawTool: DrawTool;\n interactionLock: boolean;\n worldToScreen: (worldX: number, worldY: number) => DrawCoordinate | null;\n screenToWorld: (clientX: number, clientY: number) => DrawCoordinate | null;\n requestRedraw: () => void;\n}\n\nexport interface WsiCustomLayer {\n id?: string | number;\n zIndex?: number;\n pointerEvents?: CSSProperties[\"pointerEvents\"];\n className?: string;\n style?: CSSProperties;\n render: (context: WsiCustomLayerContext) => ReactNode;\n}\n\ninterface PointSpatialIndex {\n cellSize: number;\n safeCount: number;\n positions: Float32Array;\n ids: Uint32Array | null;\n buckets: Map<number, Map<number, number[]>>;\n}\n\nfunction sanitizePointCount(pointData: WsiPointData): number {\n return Math.max(0, Math.min(Math.floor(pointData.count ?? 0), Math.floor((pointData.positions?.length ?? 0) / 2), pointData.paletteIndices?.length ?? 0));\n}\n\nfunction sanitizeDrawIndices(drawIndices: Uint32Array | undefined, maxExclusive: number): Uint32Array | null {\n if (!(drawIndices instanceof Uint32Array) || maxExclusive <= 0 || drawIndices.length === 0) {\n return null;\n }\n\n let invalidFound = false;\n for (let i = 0; i < drawIndices.length; i += 1) {\n if (drawIndices[i] < maxExclusive) continue;\n invalidFound = true;\n break;\n }\n if (!invalidFound) {\n return drawIndices;\n }\n\n const out = new Uint32Array(drawIndices.length);\n let cursor = 0;\n for (let i = 0; i < drawIndices.length; i += 1) {\n const idx = drawIndices[i];\n if (idx >= maxExclusive) continue;\n out[cursor] = idx;\n cursor += 1;\n }\n return out.subarray(0, cursor);\n}\n\nfunction resolvePointHitGridSize(source: WsiImageSource | null, visibleCount: number): number {\n if (!source || visibleCount <= 0) return 256;\n const area = Math.max(1, source.width * source.height);\n const avgSpacing = Math.sqrt(area / Math.max(1, visibleCount));\n const raw = avgSpacing * POINT_HIT_GRID_DENSITY_SCALE;\n return Math.max(MIN_POINT_HIT_GRID_SIZE, Math.min(MAX_POINT_HIT_GRID_SIZE, raw));\n}\n\nfunction buildPointSpatialIndex(pointData: WsiPointData | null | undefined, source: WsiImageSource | null): PointSpatialIndex | null {\n if (!pointData || !pointData.positions || !pointData.paletteIndices) {\n return null;\n }\n\n const safeCount = sanitizePointCount(pointData);\n if (safeCount <= 0) {\n return null;\n }\n\n const positions = pointData.positions.subarray(0, safeCount * 2);\n const ids = pointData.ids instanceof Uint32Array && pointData.ids.length >= safeCount ? pointData.ids.subarray(0, safeCount) : null;\n const drawIndices = sanitizeDrawIndices(pointData.drawIndices, safeCount);\n const visibleCount = drawIndices ? drawIndices.length : safeCount;\n if (visibleCount === 0) {\n return null;\n }\n\n const cellSize = resolvePointHitGridSize(source, visibleCount);\n const buckets = new Map<number, Map<number, number[]>>();\n\n const pushBucket = (pointIndex: number): void => {\n const px = positions[pointIndex * 2];\n const py = positions[pointIndex * 2 + 1];\n if (!Number.isFinite(px) || !Number.isFinite(py)) return;\n\n const cellX = Math.floor(px / cellSize);\n const cellY = Math.floor(py / cellSize);\n let column = buckets.get(cellX);\n if (!column) {\n column = new Map<number, number[]>();\n buckets.set(cellX, column);\n }\n const bucket = column.get(cellY);\n if (bucket) {\n bucket.push(pointIndex);\n } else {\n column.set(cellY, [pointIndex]);\n }\n };\n\n if (drawIndices) {\n for (let i = 0; i < drawIndices.length; i += 1) {\n pushBucket(drawIndices[i] ?? 0);\n }\n } else {\n for (let i = 0; i < safeCount; i += 1) {\n pushBucket(i);\n }\n }\n\n if (buckets.size === 0) {\n return null;\n }\n\n return {\n cellSize,\n safeCount,\n positions,\n ids,\n buckets,\n };\n}\n\nfunction resolveRegionId(region: WsiRegion, index: number): string | number {\n return region.id ?? index;\n}\n\nfunction isPointInPolygon(point: DrawCoordinate, polygon: DrawCoordinate[]): boolean {\n if (!Array.isArray(polygon) || polygon.length < 3) return false;\n\n const [x, y] = point;\n let inside = false;\n\n for (let i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {\n const [xi, yi] = polygon[i];\n const [xj, yj] = polygon[j];\n const intersect = yi > y !== yj > y && x < ((xj - xi) * (y - yi)) / Math.max(1e-12, yj - yi) + xi;\n if (intersect) inside = !inside;\n }\n\n return inside;\n}\n\nfunction pickRegionAt(\n coord: DrawCoordinate,\n regions: WsiRegion[]\n): {\n region: WsiRegion;\n regionIndex: number;\n regionId: string | number;\n} | null {\n for (let i = regions.length - 1; i >= 0; i -= 1) {\n const region = regions[i];\n if (!region?.coordinates?.length) continue;\n if (!isPointInPolygon(coord, region.coordinates)) continue;\n return {\n region,\n regionIndex: i,\n regionId: resolveRegionId(region, i),\n };\n }\n return null;\n}\n\nexport interface WsiViewerCanvasProps {\n source: WsiImageSource | null;\n viewState?: Partial<WsiViewState> | null;\n onViewStateChange?: (next: WsiViewState) => void;\n onStats?: (stats: WsiRenderStats) => void;\n onTileError?: (event: WsiTileErrorEvent) => void;\n onContextLost?: () => void;\n onContextRestored?: () => void;\n debugOverlay?: boolean;\n debugOverlayStyle?: CSSProperties;\n fitNonce?: number;\n rotationResetNonce?: number;\n authToken?: string;\n ctrlDragRotate?: boolean;\n pointData?: WsiPointData | null;\n pointPalette?: Uint8Array | null;\n pointSizeByZoom?: PointSizeByZoom;\n roiRegions?: WsiRegion[];\n roiPolygons?: DrawCoordinate[][];\n clipPointsToRois?: boolean;\n clipMode?: PointClipMode;\n onClipStats?: (event: PointClipStatsEvent) => void;\n onRoiPointGroups?: (stats: RoiPointGroupStats) => void;\n roiPaletteIndexToTermId?: ReadonlyMap<number, string> | readonly string[];\n interactionLock?: boolean;\n drawTool?: DrawTool;\n stampOptions?: StampOptions;\n brushOptions?: BrushOptions;\n regionStrokeStyle?: Partial<RegionStrokeStyle>;\n regionStrokeHoverStyle?: Partial<RegionStrokeStyle>;\n regionStrokeActiveStyle?: Partial<RegionStrokeStyle>;\n patchStrokeStyle?: Partial<RegionStrokeStyle>;\n resolveRegionStrokeStyle?: RegionStrokeStyleResolver;\n overlayShapes?: DrawOverlayShape[];\n customLayers?: WsiCustomLayer[];\n patchRegions?: WsiRegion[];\n regionLabelStyle?: Partial<RegionLabelStyle>;\n onPointerWorldMove?: (event: PointerWorldMoveEvent) => void;\n onPointHover?: (event: PointHoverEvent) => void;\n onPointClick?: (event: PointClickEvent) => void;\n onRegionHover?: (event: RegionHoverEvent) => void;\n onRegionClick?: (event: RegionClickEvent) => void;\n onActiveRegionChange?: (regionId: string | number | null) => void;\n getCellByCoordinatesRef?: MutableRefObject<((coordinate: DrawCoordinate) => PointHitEvent | null) | null>;\n onDrawComplete?: (result: DrawResult) => void;\n onPatchComplete?: (result: PatchDrawResult) => void;\n showOverviewMap?: boolean;\n overviewMapOptions?: Partial<OverviewMapOptions>;\n className?: string;\n style?: CSSProperties;\n}\n\nexport function WsiViewerCanvas({\n source,\n viewState,\n onViewStateChange,\n onStats,\n onTileError,\n onContextLost,\n onContextRestored,\n debugOverlay = false,\n debugOverlayStyle,\n fitNonce = 0,\n rotationResetNonce = 0,\n authToken = \"\",\n ctrlDragRotate = true,\n pointData = null,\n pointPalette = null,\n pointSizeByZoom,\n roiRegions,\n roiPolygons,\n clipPointsToRois = false,\n clipMode = \"worker\",\n onClipStats,\n onRoiPointGroups,\n roiPaletteIndexToTermId,\n interactionLock = false,\n drawTool = \"cursor\",\n stampOptions,\n brushOptions,\n regionStrokeStyle,\n regionStrokeHoverStyle,\n regionStrokeActiveStyle,\n patchStrokeStyle,\n resolveRegionStrokeStyle,\n overlayShapes,\n customLayers,\n patchRegions,\n regionLabelStyle,\n onPointerWorldMove,\n onPointHover,\n onPointClick,\n onRegionHover,\n onRegionClick,\n onActiveRegionChange,\n getCellByCoordinatesRef,\n onDrawComplete,\n onPatchComplete,\n showOverviewMap = false,\n overviewMapOptions,\n className,\n style,\n}: WsiViewerCanvasProps): React.ReactElement {\n const canvasRef = useRef<HTMLCanvasElement | null>(null);\n const rendererRef = useRef<WsiTileRenderer | null>(null);\n const drawInvalidateRef = useRef<(() => void) | null>(null);\n const overviewInvalidateRef = useRef<(() => void) | null>(null);\n const onViewStateChangeRef = useRef<typeof onViewStateChange>(onViewStateChange);\n const onStatsRef = useRef<typeof onStats>(onStats);\n const debugOverlayRef = useRef(debugOverlay);\n const [isOverviewOpen, setIsOverviewOpen] = useState(true);\n const [hoveredRegionId, setHoveredRegionId] = useState<string | number | null>(null);\n const [activeRegionId, setActiveRegionId] = useState<string | number | null>(null);\n const [customLayerViewState, setCustomLayerViewState] = useState<WsiViewState | null>(null);\n const [debugStats, setDebugStats] = useState<WsiRenderStats | null>(null);\n const hoveredRegionIdRef = useRef<string | number | null>(null);\n const hoveredPointIndexRef = useRef<number | null>(null);\n const hoveredPointIdRef = useRef<number | null>(null);\n const clipRunIdRef = useRef(0);\n const safeRoiRegions = roiRegions ?? EMPTY_ROI_REGIONS;\n const safePatchRegions = patchRegions ?? EMPTY_ROI_REGIONS;\n const safeRoiPolygons = roiPolygons ?? EMPTY_ROI_POLYGONS;\n const shouldTrackCustomLayerViewState = (customLayers?.length ?? 0) > 0;\n\n const mergedStyle = useMemo<CSSProperties>(() => ({ position: \"relative\", width: \"100%\", height: \"100%\", ...style }), [style]);\n const mergedDebugOverlayStyle = useMemo<CSSProperties>(\n () => ({\n position: \"absolute\",\n top: 8,\n left: 8,\n zIndex: 7,\n margin: 0,\n padding: \"8px 10px\",\n maxWidth: \"min(420px, 80%)\",\n pointerEvents: \"none\",\n whiteSpace: \"pre-wrap\",\n lineHeight: 1.35,\n fontFamily: \"ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace\",\n fontSize: 11,\n color: \"#cde6ff\",\n background: \"rgba(6, 12, 20, 0.82)\",\n border: \"1px solid rgba(173, 216, 255, 0.28)\",\n borderRadius: 8,\n boxShadow: \"0 8px 22px rgba(0,0,0,0.35)\",\n ...debugOverlayStyle,\n }),\n [debugOverlayStyle]\n );\n\n const effectiveRoiRegions = useMemo<WsiRegion[]>(() => {\n if (safeRoiRegions.length > 0) {\n return safeRoiRegions;\n }\n if (safeRoiPolygons.length === 0) {\n return EMPTY_ROI_REGIONS;\n }\n return safeRoiPolygons.map((coordinates, index) => ({\n id: index,\n coordinates,\n }));\n }, [safeRoiRegions, safeRoiPolygons]);\n\n const clipPolygons = useMemo(() => effectiveRoiRegions.map(region => region.coordinates), [effectiveRoiRegions]);\n\n const [renderPointData, setRenderPointData] = useState<WsiPointData | null>(pointData);\n\n useEffect(() => {\n const runId = ++clipRunIdRef.current;\n let cancelled = false;\n\n if (!clipPointsToRois) {\n setRenderPointData(pointData);\n return () => {\n cancelled = true;\n };\n }\n\n if (!pointData || !pointData.count || !pointData.positions || !pointData.paletteIndices) {\n setRenderPointData(null);\n return () => {\n cancelled = true;\n };\n }\n\n if (clipPolygons.length === 0) {\n setRenderPointData(EMPTY_CLIPPED_POINTS);\n onClipStats?.({\n mode: clipMode,\n durationMs: 0,\n inputCount: pointData.count,\n outputCount: 0,\n polygonCount: 0,\n });\n return () => {\n cancelled = true;\n };\n }\n\n const applyResult = (data: WsiPointData | null, stats: Omit<PointClipStatsEvent, \"inputCount\" | \"outputCount\" | \"polygonCount\">) => {\n if (cancelled || runId !== clipRunIdRef.current) return;\n const outputCount = data?.drawIndices ? data.drawIndices.length : (data?.count ?? 0);\n setRenderPointData(data);\n onClipStats?.({\n mode: stats.mode,\n durationMs: stats.durationMs,\n inputCount: pointData.count,\n outputCount,\n polygonCount: clipPolygons.length,\n usedWebGpu: stats.usedWebGpu,\n candidateCount: stats.candidateCount,\n bridgedToDraw: stats.bridgedToDraw,\n });\n };\n\n const run = async (): Promise<void> => {\n if (clipMode === \"sync\") {\n const start = performance.now();\n const data = filterPointDataByPolygons(pointData, clipPolygons);\n applyResult(data, {\n mode: \"sync\",\n durationMs: performance.now() - start,\n });\n return;\n }\n\n if (clipMode === \"hybrid-webgpu\") {\n const result = await filterPointDataByPolygonsHybrid(pointData, clipPolygons as RoiPolygon[], { bridgeToDraw: true });\n applyResult(result.data, {\n mode: result.meta.mode,\n durationMs: result.meta.durationMs,\n usedWebGpu: result.meta.usedWebGpu,\n candidateCount: result.meta.candidateCount,\n bridgedToDraw: result.meta.bridgedToDraw,\n });\n return;\n }\n\n try {\n const result = await filterPointDataByPolygonsInWorker(pointData, clipPolygons as RoiPolygon[]);\n applyResult(result.data, {\n mode: result.meta.mode,\n durationMs: result.meta.durationMs,\n });\n } catch {\n const start = performance.now();\n const data = filterPointDataByPolygons(pointData, clipPolygons);\n applyResult(data, {\n mode: \"sync\",\n durationMs: performance.now() - start,\n });\n }\n };\n\n void run();\n return () => {\n cancelled = true;\n };\n }, [clipPointsToRois, clipMode, pointData, clipPolygons, onClipStats]);\n\n const shouldEnablePointHitTest = Boolean(onPointHover || onPointClick || getCellByCoordinatesRef);\n const pointSpatialIndex = useMemo(() => {\n if (!shouldEnablePointHitTest) return null;\n return buildPointSpatialIndex(renderPointData, source);\n }, [shouldEnablePointHitTest, renderPointData, source]);\n\n const getCellByCoordinates = useCallback(\n (coordinate: DrawCoordinate): PointHitEvent | null => {\n const renderer = rendererRef.current;\n if (!renderer || !pointSpatialIndex) return null;\n\n const x = Number(coordinate[0]);\n const y = Number(coordinate[1]);\n if (!Number.isFinite(x) || !Number.isFinite(y)) return null;\n\n const zoom = Math.max(1e-6, renderer.getViewState().zoom);\n const pointSizePx = renderer.getPointSizeByZoom();\n const hitRadiusPx = Math.max(MIN_POINT_HIT_RADIUS_PX, pointSizePx * POINT_HIT_RADIUS_SCALE);\n const hitRadiusWorld = hitRadiusPx / zoom;\n if (!Number.isFinite(hitRadiusWorld) || hitRadiusWorld <= 0) return null;\n\n const cellSize = pointSpatialIndex.cellSize;\n const baseCellX = Math.floor(x / cellSize);\n const baseCellY = Math.floor(y / cellSize);\n const cellRadius = Math.max(1, Math.ceil(hitRadiusWorld / cellSize));\n const maxDist2 = hitRadiusWorld * hitRadiusWorld;\n\n let nearestIndex = -1;\n let nearestDist2 = maxDist2;\n let nearestX = 0;\n let nearestY = 0;\n\n for (let cx = baseCellX - cellRadius; cx <= baseCellX + cellRadius; cx += 1) {\n const column = pointSpatialIndex.buckets.get(cx);\n if (!column) continue;\n\n for (let cy = baseCellY - cellRadius; cy <= baseCellY + cellRadius; cy += 1) {\n const bucket = column.get(cy);\n if (!bucket || bucket.length === 0) continue;\n\n for (let i = 0; i < bucket.length; i += 1) {\n const pointIndex = bucket[i];\n if (pointIndex >= pointSpatialIndex.safeCount) continue;\n\n const px = pointSpatialIndex.positions[pointIndex * 2];\n const py = pointSpatialIndex.positions[pointIndex * 2 + 1];\n const dx = px - x;\n const dy = py - y;\n const dist2 = dx * dx + dy * dy;\n if (dist2 > nearestDist2) continue;\n\n nearestDist2 = dist2;\n nearestIndex = pointIndex;\n nearestX = px;\n nearestY = py;\n }\n }\n }\n\n if (nearestIndex < 0) return null;\n const pointId = pointSpatialIndex.ids ? Number(pointSpatialIndex.ids[nearestIndex]) : null;\n return {\n index: nearestIndex,\n id: pointId,\n coordinate: [x, y],\n pointCoordinate: [nearestX, nearestY],\n };\n },\n [pointSpatialIndex]\n );\n\n const emitPointHover = useCallback(\n (hit: PointHitEvent | null, coordinate: DrawCoordinate | null) => {\n if (!onPointHover) return;\n const nextIndex = hit?.index ?? null;\n const nextId = hit?.id ?? null;\n if (hoveredPointIndexRef.current === nextIndex && hoveredPointIdRef.current === nextId) return;\n hoveredPointIndexRef.current = nextIndex;\n hoveredPointIdRef.current = nextId;\n onPointHover({\n index: nextIndex,\n id: nextId,\n coordinate,\n pointCoordinate: hit?.pointCoordinate ?? null,\n });\n },\n [onPointHover]\n );\n\n const emitPointClick = useCallback(\n (coordinate: DrawCoordinate, button: number) => {\n if (!onPointClick) return;\n const hit = getCellByCoordinates(coordinate);\n if (!hit) return;\n onPointClick({\n ...hit,\n button,\n });\n },\n [onPointClick, getCellByCoordinates]\n );\n\n const overviewWidth = useMemo(() => {\n const value = Number(overviewMapOptions?.width ?? 220);\n return Number.isFinite(value) ? Math.max(64, value) : 220;\n }, [overviewMapOptions?.width]);\n const overviewHeight = useMemo(() => {\n const value = Number(overviewMapOptions?.height ?? 140);\n return Number.isFinite(value) ? Math.max(48, value) : 140;\n }, [overviewMapOptions?.height]);\n const overviewMargin = useMemo(() => {\n const value = Number(overviewMapOptions?.margin ?? 16);\n return Number.isFinite(value) ? Math.max(0, value) : 16;\n }, [overviewMapOptions?.margin]);\n const overviewPosition = overviewMapOptions?.position || \"bottom-right\";\n\n useEffect(() => {\n if (!getCellByCoordinatesRef) return;\n getCellByCoordinatesRef.current = getCellByCoordinates;\n return () => {\n if (getCellByCoordinatesRef.current === getCellByCoordinates) {\n getCellByCoordinatesRef.current = null;\n }\n };\n }, [getCellByCoordinatesRef, getCellByCoordinates]);\n\n const commitActiveRegion = useCallback(\n (next: string | number | null) => {\n setActiveRegionId(prev => {\n if (String(prev) === String(next)) {\n return prev;\n }\n onActiveRegionChange?.(next);\n return next;\n });\n },\n [onActiveRegionChange]\n );\n\n useEffect(() => {\n onViewStateChangeRef.current = onViewStateChange;\n }, [onViewStateChange]);\n\n useEffect(() => {\n onStatsRef.current = onStats;\n }, [onStats]);\n\n useEffect(() => {\n debugOverlayRef.current = debugOverlay;\n if (!debugOverlay) setDebugStats(null);\n }, [debugOverlay]);\n\n const handleRendererStats = useCallback((stats: WsiRenderStats): void => {\n onStatsRef.current?.(stats);\n if (debugOverlayRef.current) {\n setDebugStats(stats);\n }\n }, []);\n\n const debugOverlayText = useMemo(() => {\n if (!debugStats) {\n return \"stats: waiting for first frame...\";\n }\n return [\n `tier ${debugStats.tier} | frame ${debugStats.frameMs?.toFixed(2) ?? \"-\"} ms | drawCalls ${debugStats.drawCalls ?? \"-\"}`,\n `tiles visible ${debugStats.visible} | rendered ${debugStats.rendered} | fallback ${debugStats.fallback}`,\n `cache size ${debugStats.cache} | hit ${debugStats.cacheHits ?? \"-\"} | miss ${debugStats.cacheMisses ?? \"-\"}`,\n `queue inflight ${debugStats.inflight} | queued ${debugStats.queued ?? \"-\"} | retries ${debugStats.retries ?? \"-\"} | failed ${debugStats.failed ?? \"-\"} | aborted ${debugStats.aborted ?? \"-\"}`,\n `points ${debugStats.points}`,\n ].join(\"\\n\");\n }, [debugStats]);\n\n useEffect(() => {\n const hasActive = activeRegionId === null ? true : effectiveRoiRegions.some((region, index) => String(resolveRegionId(region, index)) === String(activeRegionId));\n if (!hasActive && activeRegionId !== null) {\n commitActiveRegion(null);\n }\n\n const currentHover = hoveredRegionIdRef.current;\n const hasHover = currentHover === null ? true : effectiveRoiRegions.some((region, index) => String(resolveRegionId(region, index)) === String(currentHover));\n\n if (!hasHover && currentHover !== null) {\n hoveredRegionIdRef.current = null;\n setHoveredRegionId(null);\n onRegionHover?.({\n region: null,\n regionId: null,\n regionIndex: -1,\n coordinate: null,\n });\n }\n }, [effectiveRoiRegions, activeRegionId, onRegionHover, commitActiveRegion]);\n\n useEffect(() => {\n const hoveredPointIndex = hoveredPointIndexRef.current;\n if (hoveredPointIndex === null) return;\n if (pointSpatialIndex && hoveredPointIndex < pointSpatialIndex.safeCount) return;\n hoveredPointIndexRef.current = null;\n hoveredPointIdRef.current = null;\n onPointHover?.({\n index: null,\n id: null,\n coordinate: null,\n pointCoordinate: null,\n });\n }, [pointSpatialIndex, onPointHover]);\n\n const emitViewStateChange = useCallback(\n (next: WsiViewState): void => {\n if (shouldTrackCustomLayerViewState) {\n setCustomLayerViewState(next);\n }\n const callback = onViewStateChangeRef.current;\n if (callback) {\n callback(next);\n }\n drawInvalidateRef.current?.();\n overviewInvalidateRef.current?.();\n },\n [shouldTrackCustomLayerViewState]\n );\n\n useEffect(() => {\n if (!showOverviewMap) {\n setIsOverviewOpen(false);\n return;\n }\n setIsOverviewOpen(true);\n }, [showOverviewMap, source?.id]);\n\n useEffect(() => {\n if (drawTool === \"cursor\") return;\n if (hoveredRegionIdRef.current === null) return;\n hoveredRegionIdRef.current = null;\n setHoveredRegionId(null);\n onRegionHover?.({\n region: null,\n regionId: null,\n regionIndex: -1,\n coordinate: null,\n });\n }, [drawTool, onRegionHover]);\n\n useEffect(() => {\n if (drawTool === \"cursor\") return;\n if (hoveredPointIndexRef.current === null) return;\n hoveredPointIndexRef.current = null;\n hoveredPointIdRef.current = null;\n onPointHover?.({\n index: null,\n id: null,\n coordinate: null,\n pointCoordinate: null,\n });\n }, [drawTool, onPointHover]);\n\n const resolveWorldCoord = useCallback((clientX: number, clientY: number): DrawCoordinate | null => {\n const renderer = rendererRef.current;\n if (!renderer) return null;\n const raw = renderer.screenToWorld(clientX, clientY);\n if (!Array.isArray(raw) || raw.length < 2) return null;\n const x = Number(raw[0]);\n const y = Number(raw[1]);\n if (!Number.isFinite(x) || !Number.isFinite(y)) return null;\n return [x, y];\n }, []);\n\n const resolveScreenCoord = useCallback((worldX: number, worldY: number): DrawCoordinate | null => {\n const renderer = rendererRef.current;\n if (!renderer) return null;\n const raw = renderer.worldToScreen(worldX, worldY);\n if (!Array.isArray(raw) || raw.length < 2) return null;\n const x = Number(raw[0]);\n const y = Number(raw[1]);\n if (!Number.isFinite(x) || !Number.isFinite(y)) return null;\n return [x, y];\n }, []);\n\n const requestCustomLayerRedraw = useCallback(() => {\n rendererRef.current?.requestRender();\n drawInvalidateRef.current?.();\n overviewInvalidateRef.current?.();\n }, []);\n\n const effectiveCustomLayerViewState = useMemo<WsiViewState | null>(() => {\n return customLayerViewState ?? rendererRef.current?.getViewState() ?? null;\n }, [customLayerViewState]);\n\n const customLayerContext = useMemo<WsiCustomLayerContext | null>(() => {\n if (!source) return null;\n const viewStateForLayer = effectiveCustomLayerViewState;\n if (!viewStateForLayer) return null;\n return {\n source,\n viewState: viewStateForLayer,\n drawTool,\n interactionLock,\n worldToScreen: resolveScreenCoord,\n screenToWorld: resolveWorldCoord,\n requestRedraw: requestCustomLayerRedraw,\n };\n }, [source, effectiveCustomLayerViewState, drawTool, interactionLock, resolveScreenCoord, resolveWorldCoord, requestCustomLayerRedraw]);\n\n const handleRegionPointerMove = useCallback(\n (event: ReactPointerEvent<HTMLDivElement>) => {\n const isCanvasEvent = event.target === canvasRef.current;\n const coord = resolveWorldCoord(event.clientX, event.clientY);\n if (onPointerWorldMove) {\n const insideImage = !!coord && coord[0] >= 0 && coord[1] >= 0 && !!source && coord[0] <= source.width && coord[1] <= source.height;\n onPointerWorldMove({\n coordinate: coord,\n clientX: event.clientX,\n clientY: event.clientY,\n insideImage,\n });\n }\n\n if (drawTool !== \"cursor\") return;\n if (!isCanvasEvent) {\n emitPointHover(null, null);\n if (hoveredRegionIdRef.current !== null) {\n hoveredRegionIdRef.current = null;\n setHoveredRegionId(null);\n onRegionHover?.({\n region: null,\n regionId: null,\n regionIndex: -1,\n coordinate: null,\n });\n }\n return;\n }\n if (!coord) {\n emitPointHover(null, null);\n return;\n }\n\n if (onPointHover) {\n emitPointHover(getCellByCoordinates(coord), coord);\n }\n if (!effectiveRoiRegions.length) return;\n\n const hit = pickRegionAt(coord, effectiveRoiRegions);\n const nextHoverId = hit?.regionId ?? null;\n const prevHoverId = hoveredRegionIdRef.current;\n if (String(prevHoverId) === String(nextHoverId)) return;\n\n hoveredRegionIdRef.current = nextHoverId;\n setHoveredRegionId(nextHoverId);\n onRegionHover?.({\n region: hit?.region ?? null,\n regionId: nextHoverId,\n regionIndex: hit?.regionIndex ?? -1,\n coordinate: coord,\n });\n },\n [drawTool, effectiveRoiRegions, resolveWorldCoord, onRegionHover, onPointerWorldMove, source, emitPointHover, getCellByCoordinates, onPointHover]\n );\n\n const handleRegionPointerLeave = useCallback(() => {\n onPointerWorldMove?.({\n coordinate: null,\n clientX: -1,\n clientY: -1,\n insideImage: false,\n });\n emitPointHover(null, null);\n if (hoveredRegionIdRef.current === null) return;\n hoveredRegionIdRef.current = null;\n setHoveredRegionId(null);\n onRegionHover?.({\n region: null,\n regionId: null,\n regionIndex: -1,\n coordinate: null,\n });\n }, [onRegionHover, onPointerWorldMove, emitPointHover]);\n\n const handleRegionClick = useCallback(\n (event: ReactMouseEvent<HTMLDivElement>) => {\n if (drawTool !== \"cursor\") return;\n if (event.target !== canvasRef.current) return;\n\n const coord = resolveWorldCoord(event.clientX, event.clientY);\n if (!coord) return;\n emitPointClick(coord, event.button);\n\n if (!effectiveRoiRegions.length) {\n commitActiveRegion(null);\n return;\n }\n\n const hit = pickRegionAt(coord, effectiveRoiRegions);\n if (!hit) {\n commitActiveRegion(null);\n return;\n }\n\n const nextActive: string | number | null = activeRegionId !== null && String(activeRegionId) === String(hit.regionId) ? null : hit.regionId;\n commitActiveRegion(nextActive);\n onRegionClick?.({\n region: hit.region,\n regionId: hit.regionId,\n regionIndex: hit.regionIndex,\n coordinate: coord,\n });\n },\n [drawTool, effectiveRoiRegions, resolveWorldCoord, onRegionClick, activeRegionId, commitActiveRegion, emitPointClick]\n );\n\n const handleRegionContextMenu = useCallback(\n (event: ReactMouseEvent<HTMLDivElement>) => {\n if (!onPointClick) return;\n if (drawTool !== \"cursor\") return;\n if (event.target !== canvasRef.current) return;\n event.preventDefault();\n const coord = resolveWorldCoord(event.clientX, event.clientY);\n if (!coord) return;\n emitPointClick(coord, event.button);\n },\n [drawTool, resolveWorldCoord, emitPointClick, onPointClick]\n );\n\n useEffect(() => {\n const canvas = canvasRef.current;\n if (!canvas || !source) {\n return;\n }\n\n const renderer = new WsiTileRenderer(canvas, source, {\n onViewStateChange: emitViewStateChange,\n onStats: handleRendererStats,\n onTileError,\n onContextLost,\n onContextRestored,\n authToken,\n ctrlDragRotate,\n pointSizeByZoom,\n });\n\n rendererRef.current = renderer;\n if (viewState) {\n renderer.setViewState(viewState);\n }\n renderer.setInteractionLock(interactionLock);\n if (shouldTrackCustomLayerViewState) {\n setCustomLayerViewState(renderer.getViewState());\n }\n\n return () => {\n renderer.destroy();\n rendererRef.current = null;\n };\n }, [source, handleRendererStats, onTileError, onContextLost, onContextRestored, authToken, ctrlDragRotate, pointSizeByZoom, emitViewStateChange, shouldTrackCustomLayerViewState]);\n\n useEffect(() => {\n const renderer = rendererRef.current;\n if (!renderer || !viewState) {\n return;\n }\n renderer.setViewState(viewState);\n }, [viewState]);\n\n useEffect(() => {\n const renderer = rendererRef.current;\n if (!renderer) {\n return;\n }\n renderer.fitToImage();\n }, [fitNonce]);\n\n useEffect(() => {\n const renderer = rendererRef.current;\n if (!renderer) return;\n renderer.resetRotation();\n }, [rotationResetNonce]);\n\n useEffect(() => {\n const renderer = rendererRef.current;\n if (!renderer || !pointPalette) {\n return;\n }\n renderer.setPointPalette(pointPalette);\n }, [pointPalette]);\n\n useEffect(() => {\n const renderer = rendererRef.current;\n if (!renderer) {\n return;\n }\n renderer.setPointSizeByZoom(pointSizeByZoom);\n }, [pointSizeByZoom]);\n\n useEffect(() => {\n const renderer = rendererRef.current;\n if (!renderer) {\n return;\n }\n renderer.setPointData(renderPointData);\n }, [renderPointData]);\n\n useEffect(() => {\n if (!onRoiPointGroups) return;\n const sourcePoints = clipPointsToRois ? renderPointData : pointData;\n const stats = computeRoiPointGroups(sourcePoints, effectiveRoiRegions, {\n paletteIndexToTermId: roiPaletteIndexToTermId,\n includeEmptyRegions: true,\n });\n onRoiPointGroups(stats);\n }, [onRoiPointGroups, clipPointsToRois, pointData, renderPointData, effectiveRoiRegions, roiPaletteIndexToTermId]);\n\n useEffect(() => {\n const renderer = rendererRef.current;\n if (!renderer) {\n return;\n }\n renderer.setInteractionLock(interactionLock);\n }, [interactionLock]);\n\n return (\n <div className={className} style={mergedStyle} onPointerMove={handleRegionPointerMove} onPointerLeave={handleRegionPointerLeave} onClick={handleRegionClick} onContextMenu={handleRegionContextMenu}>\n <canvas\n ref={canvasRef}\n className=\"wsi-render-canvas\"\n style={{\n position: \"absolute\",\n inset: 0,\n zIndex: 1,\n width: \"100%\",\n height: \"100%\",\n display: \"block\",\n touchAction: \"none\",\n cursor: drawTool === \"cursor\" && hoveredRegionId !== null ? \"pointer\" : interactionLock ? \"crosshair\" : \"grab\",\n }}\n />\n {source && customLayerContext && Array.isArray(customLayers) && customLayers.length > 0\n ? customLayers.map((layer, index) => (\n <div\n key={layer.id ?? index}\n className={layer.className}\n style={{\n position: \"absolute\",\n inset: 0,\n zIndex: layer.zIndex ?? 3,\n pointerEvents: layer.pointerEvents ?? \"none\",\n ...layer.style,\n }}\n >\n {layer.render(customLayerContext)}\n </div>\n ))\n : null}\n {source ? (\n <DrawLayer\n tool={drawTool}\n enabled={drawTool !== \"cursor\"}\n imageWidth={source.width}\n imageHeight={source.height}\n imageMpp={source.mpp}\n imageZoom={source.maxTierZoom}\n stampOptions={stampOptions}\n brushOptions={brushOptions}\n projectorRef={rendererRef}\n viewStateSignal={viewState}\n persistedRegions={effectiveRoiRegions}\n patchRegions={safePatchRegions}\n regionStrokeStyle={regionStrokeStyle}\n regionStrokeHoverStyle={regionStrokeHoverStyle}\n regionStrokeActiveStyle={regionStrokeActiveStyle}\n patchStrokeStyle={patchStrokeStyle}\n resolveRegionStrokeStyle={resolveRegionStrokeStyle}\n overlayShapes={overlayShapes}\n hoveredRegionId={hoveredRegionId}\n activeRegionId={activeRegionId}\n regionLabelStyle={regionLabelStyle}\n invalidateRef={drawInvalidateRef}\n onDrawComplete={onDrawComplete}\n onPatchComplete={onPatchComplete}\n />\n ) : null}\n {debugOverlay ? (\n <pre data-open-plant-debug-overlay style={mergedDebugOverlayStyle}>\n {debugOverlayText}\n </pre>\n ) : null}\n {source && showOverviewMap ? (\n isOverviewOpen ? (\n <>\n <OverviewMap source={source} projectorRef={rendererRef} authToken={authToken} options={overviewMapOptions} invalidateRef={overviewInvalidateRef} />\n <button\n type=\"button\"\n aria-label=\"Hide overview map\"\n onClick={() => setIsOverviewOpen(false)}\n style={{\n position: \"absolute\",\n zIndex: 6,\n ...(overviewPosition.includes(\"left\") ? { left: overviewMargin } : { right: overviewMargin }),\n ...(overviewPosition.includes(\"top\") ? { top: overviewMargin + overviewHeight + 8 } : { bottom: overviewMargin + overviewHeight + 8 }),\n width: 20,\n height: 20,\n borderRadius: 999,\n border: \"1px solid rgba(255,255,255,0.4)\",\n background: \"rgba(8, 14, 22, 0.9)\",\n color: \"#fff\",\n fontSize: 13,\n lineHeight: 1,\n cursor: \"pointer\",\n padding: 0,\n }}\n >\n ×\n </button>\n </>\n ) : (\n <button\n type=\"button\"\n aria-label=\"Show overview map\"\n onClick={() => setIsOverviewOpen(true)}\n style={{\n position: \"absolute\",\n zIndex: 6,\n ...(overviewPosition.includes(\"left\") ? { left: overviewMargin } : { right: overviewMargin }),\n ...(overviewPosition.includes(\"top\") ? { top: overviewMargin } : { bottom: overviewMargin }),\n height: 24,\n minWidth: 40,\n borderRadius: 999,\n border: \"1px solid rgba(255,255,255,0.45)\",\n background: \"rgba(8, 14, 22, 0.9)\",\n color: \"#dff8ff\",\n fontSize: 11,\n fontWeight: 700,\n cursor: \"pointer\",\n padding: \"0 8px\",\n }}\n >\n Map\n </button>\n )\n ) : null}\n </div>\n );\n}\n"],"names":["compileShader","gl","type","source","shader","log","createProgram","vertexSource","fragmentSource","vertexShader","fragmentShader","program","requireUniformLocation","uniformName","location","requireWebGL2","canvas","context","OrthoCamera$1","__publicField","width","height","next","viewWidth","viewHeight","sx","sy","tx","ty","VERTEX_SHADER","FRAGMENT_SHADER","M1TileRenderer","options","OrthoCamera","vao","quadBuffer","quadVertices","unitLocation","uvLocation","stride","tiles","version","loaded","tile","viewState","response","blob","bitmap","texture","error","rect","cssWidth","cssHeight","dpr","targetWidth","targetHeight","viewport","zoom","safeZoom","visibleWorldWidth","visibleWorldHeight","offsetX","offsetY","DEFAULT_MIN_RASTER_STEP","DEFAULT_MAX_RASTER_PIXELS","DEFAULT_MAX_RASTER_SIZE","DEFAULT_CIRCLE_SIDES","MIN_RADIUS","ALPHA_THRESHOLD","clamp","value","min","max","closeRing","coordinates","out","x","y","first","last","sanitizePath","points","point","prev","createCirclePolygon","center","radius","sides","ring","t","createBoundsFallback","minX","minY","maxX","maxY","pad","computeExpandedBounds","resolveRasterConfig","bounds","minRasterStep","maxRasterPixels","maxRasterSize","widthWorld","heightWorld","step","padding","createRasterContext","worldToRaster","config","rasterizeStrokeMask","path","p","i","image","buildBoundaryEdges","mask","edges","vertex","at","turnPriority","fromDir","toDir","delta","traceLoops","outgoing","entry","used","loops","startVertex","currentVertex","currentDir","loop","guard","guardLimit","candidates","bestIndex","bestPriority","edgeIndex","candidate","priority","toWorldRing","vertexLoop","id","polygonSignedArea","sum","a","b","removeCollinearVertices","epsilon","closed","curr","cross","pointLineDistanceSquared","abx","aby","len2","dx","dy","simplifyRdp","tolerance","keep","tolerance2","stack","start","end","maxDist2","split","dist2","simplifyClosedRing","open","simplified","clampRingToBounds","buildBrushStrokePolygon","circleSides","raster","bestRing","bestArea","area","DEFAULT_POINT_COLOR","calcScaleResolution","imageMpp","imageZoom","currentZoom","mpp","z0","z1","calcScaleLength","length","unit","isSameViewState","toBearerToken","trimmed","token","hexToRgba","hex","match","n","buildTermPalette","terms","palette","termToPaletteIndex","term","termId","colors","vs","fs","DRAW_FILL","FREEHAND_MIN_POINTS","FREEHAND_SCREEN_STEP","CIRCLE_SIDES","MIN_AREA_PX","EMPTY_REGIONS","EMPTY_DASH","MICRONS_PER_MM","DEFAULT_STAMP_RECTANGLE_AREA_MM2","DEFAULT_STAMP_CIRCLE_AREA_MM2","DEFAULT_STAMP_RECTANGLE_PIXEL_SIZE","LEGACY_HPF_CIRCLE_AREA_MM2","WHEEL_ZOOM_IN_FACTOR","WHEEL_ZOOM_OUT_FACTOR","DEFAULT_BRUSH_RADIUS","DEFAULT_BRUSH_FILL_COLOR","DEFAULT_BRUSH_FILL_OPACITY","DEFAULT_BRUSH_CURSOR_COLOR","DEFAULT_BRUSH_CURSOR_ACTIVE_COLOR","DEFAULT_BRUSH_CURSOR_LINE_WIDTH","DEFAULT_BRUSH_CURSOR_DASH","BRUSH_SCREEN_STEP","DEFAULT_REGION_STROKE_STYLE","DEFAULT_PATCH_STROKE_STYLE","DEFAULT_REGION_LABEL_STYLE","isStampTool","tool","clampPositiveOrFallback","fallback","resolveStampOptions","clampUnitOpacity","sanitizeBrushLineDash","item","resolveBrushOptions","cursorLineWidth","mm2ToUm2","areaMm2","createSquareFromCenter","halfLength","createCircleFromCenter","coords","createRectangle","createCircle","centerX","centerY","polygonArea","computeBounds","isValidPolygon","tracePath","ctx","close","drawPath","strokeStyle","fill","resolveStrokeStyle","style","dash","shadowBlur","shadowOffsetX","shadowOffsetY","mergeStrokeStyle","base","override","isSameRegionId","isNestedRingCoordinates","isFiniteNumber","isCoordinatePair","isCoordinateRing","collectOverlayRings","normalizeOverlayRings","sourceRings","normalized","drawInvertedFillMask","outerRing","holeRings","fillColor","resolveLabelStyle","px","py","bw","oy","br","drawRoundedRect","r","getTopAnchor","drawRegionLabel","text","anchor","canvasWidth","canvasHeight","labelStyle","label","boxWidth","boxHeight","left","top","clampWorld","coord","imageWidth","imageHeight","toCoord","DrawLayer","stampOptions","brushOptions","projectorRef","onDrawComplete","onPatchComplete","enabled","viewStateSignal","persistedRegions","patchRegions","persistedPolygons","regionStrokeStyle","regionStrokeHoverStyle","regionStrokeActiveStyle","patchStrokeStyle","resolveRegionStrokeStyle","overlayShapes","hoveredRegionId","activeRegionId","regionLabelStyle","invalidateRef","className","canvasRef","useRef","drawPendingRef","overlayDebugSnapshotRef","lastToolRef","sessionRef","active","mergedPersistedRegions","useMemo","index","mergedPatchRegions","resolvedStrokeStyle","resolvedHoverStrokeStyle","resolvedActiveStrokeStyle","resolvedPatchStrokeStyle","resolvedLabelStyle","resolvedStampOptions","resolvedBrushOptions","mergedStyle","resizeCanvas","useCallback","w","h","worldToScreenPoints","projector","worldRadiusToScreenPixels","worldRadius","micronsToWorldPixels","lengthUm","mppValue","imageZoomValue","viewZoomRaw","viewZoom","continuousZoom","umPerScreenPixel","buildStampCoords","stampTool","areaUm2","buildPreviewCoords","session","drawBrushStrokePreview","screenPoints","radiusPx","drawBrushCursor","cursor","screen","drawOverlay","region","regionKey","state","resolved","debugOverlay","imageOuterRing","shape","renderRings","closedRings","debugKey","debugSignature","preview","line","polygon","anchorWorld","anchorScreen","requestDraw","resetSession","preserveCursor","toWorld","event","raw","finishSession","handleStampAt","intent","result","appendBrushPoint","world","minWorldStep","minWorldStep2","handlePointerDown","handlePointerMove","handlePointerUp","handlePointerLeave","changed","useEffect","observer","onKeyDown","jsx","screenX","screenY","trimTrailingSlash","ensureLeadingSlash","joinImsTileRoot","tileBaseUrl","parsed","origin","normalizeImageInfo","ims","isIms","tileSize","maxTierZoom","tilePath","normalizedPath","imsTileRoot","tileUrlBuilder","tier","toTileUrl","DEFAULT_OVERVIEW_MAP_OPTIONS","toPositiveNumber","isFiniteBounds","OverviewMap","authToken","thumbnailRef","lastBoundsRef","draggingRef","rafRef","margin","borderRadius","borderWidth","maxThumbnailTiles","backgroundColor","borderColor","viewportStrokeColor","viewportFillColor","interactive","showThumbnail","position","pos","draw","cssW","cssH","pixelW","pixelH","corners","safeBounds","safeCorners","right","bottom","rectW","rectH","toWorldFromClient","clientX","clientY","nx","ny","recenterTo","worldX","worldY","visibleW","visibleH","drag","cancelled","levelScale","levelWidth","levelHeight","tilesX","tilesY","tileCount","requests","useAuthHeader","results","dw","dh","TileViewerCanvas","rendererRef","renderer","sanitizePointCount","pointData","preparePolygons","polygons","prepared","poly","isInsideRing","inside","j","xi","yi","xj","yj","isInsideAnyPolygon","filterPointDataByPolygons","count","positions","pointIds","nextPositions","nextTerms","nextIds","output","filterPointIndicesByPolygons","contextPromise","BBOX_PREFILTER_SHADER","hasWebGpu","nav","getNavigatorGpu","gpu","GPU_SHADER_STAGE_COMPUTE","GPU_BUFFER_USAGE_STORAGE","GPU_BUFFER_USAGE_COPY_DST","GPU_BUFFER_USAGE_COPY_SRC","GPU_BUFFER_USAGE_UNIFORM","GPU_BUFFER_USAGE_MAP_READ","GPU_MAP_MODE_READ","getWebGpuCapabilities","navGpu","adapter","getContext","device","bindGroupLayout","pipeline","align","prefilterPointsByBoundsWebGpu","pointCount","boundsCount","safePointCount","positionBytes","boundsBytes","outputBytes","limit","positionsBuffer","boundsBuffer","outputBuffer","uniformBuffer","readBuffer","bindGroup","commandEncoder","pass","mapped","nowMs","filterPointDataByPolygonsHybrid","bridgeToDraw","safeCount","bboxFlat","candidateMask","usedWebGpu","candidateCount","candidateIndices","candidateCursor","data","drawIndices","visibleCount","pointIndex","compactData","workerInstance","workerSupported","requestId","pendingById","createWorker","worker","handleWorkerMessage","handleWorkerError","msg","pending","indices","paletteIndices","ids","terminateRoiClipWorker","filterPointDataByPolygonsInWorker","positionsCopy","termsCopy","idsCopy","startMs","resolve","reject","transfer","filterPointIndicesByPolygonsInWorker","ax","ay","bx","by","prepareRegions","regions","resolveTermId","paletteIndex","paletteIndexToTermId","fromArray","fromMap","computeRoiPointGroups","baseCount","valid","filtered","idx","inputCount","preparedRegions","regionTermCounters","regionTotalCounters","insideCount","bestRegion","regionTermMap","includeEmptyRegions","groups","totalCount","termMap","termCounts","shouldAttachAuthHeader","url","host","TileScheduler","nextVisibleKeys","inflight","queued","visibleKeys","nextQueue","key","earliestReadyAt","delay","now","controller","inflightEntry","nextAttempt","retryDelay","existing","attempt","exp","jitter","DEFAULT_ROTATION_DRAG_SENSITIVITY","MIN_POINT_SIZE_PX","MAX_POINT_SIZE_PX","DEFAULT_POINT_SIZE_STOPS","rad","toRadians","cos","sin","rx","ry","deg","name","isSameArrayView","clonePointSizeStops","stops","stop","normalizePointSizeStops","pointSizeByZoom","zoomKey","rawSize","size","arePointSizeStopsEqual","resolvePointSizeByZoomStops","span","slope","WsiTileRenderer","attemptCount","paletteSize","nextPaletteIndices","hasDrawIndices","nextDrawIndices","geometryChanged","drawIndicesChanged","maxExclusive","validCount","locked","nextStops","vw","vh","visibleWorldW","visibleWorldH","factor","nextZoom","vp","worldDx","worldDy","marginX","marginY","halfW","halfH","minCenterX","maxCenterX","minCenterY","maxCenterY","nextCenterX","nextCenterY","rawTier","viewBounds","viewMinX","viewMinY","viewMaxX","viewMaxY","minTileX","maxTileX","minTileY","maxTileY","centerTileX","centerTileY","visible","entries","removeCount","frameStartMs","tileProgram","pointProgram","fallbackTiles","cached","renderedTiles","missingTiles","renderedPoints","schedulerStats","cacheHits","cacheMisses","drawCalls","wantsRotate","nextAngle","prevAngle","rawDelta","sensitivityScale","_event","uCamera","uBounds","uTexture","vbo","aUnit","aUv","uPointSize","uPalette","uPaletteSize","posBuffer","termBuffer","indexBuffer","paletteTexture","posLoc","termLoc","EMPTY_ROI_REGIONS","EMPTY_ROI_POLYGONS","EMPTY_CLIPPED_POINTS","POINT_HIT_RADIUS_SCALE","MIN_POINT_HIT_RADIUS_PX","MIN_POINT_HIT_GRID_SIZE","MAX_POINT_HIT_GRID_SIZE","POINT_HIT_GRID_DENSITY_SCALE","sanitizeDrawIndices","invalidFound","resolvePointHitGridSize","buildPointSpatialIndex","cellSize","buckets","pushBucket","cellX","cellY","column","bucket","resolveRegionId","isPointInPolygon","pickRegionAt","WsiViewerCanvas","onViewStateChange","onStats","onTileError","onContextLost","onContextRestored","debugOverlayStyle","fitNonce","rotationResetNonce","ctrlDragRotate","pointPalette","roiRegions","roiPolygons","clipPointsToRois","clipMode","onClipStats","onRoiPointGroups","roiPaletteIndexToTermId","interactionLock","drawTool","customLayers","onPointerWorldMove","onPointHover","onPointClick","onRegionHover","onRegionClick","onActiveRegionChange","getCellByCoordinatesRef","showOverviewMap","overviewMapOptions","drawInvalidateRef","overviewInvalidateRef","onViewStateChangeRef","onStatsRef","debugOverlayRef","isOverviewOpen","setIsOverviewOpen","useState","setHoveredRegionId","setActiveRegionId","customLayerViewState","setCustomLayerViewState","debugStats","setDebugStats","hoveredRegionIdRef","hoveredPointIndexRef","hoveredPointIdRef","clipRunIdRef","safeRoiRegions","safePatchRegions","safeRoiPolygons","shouldTrackCustomLayerViewState","mergedDebugOverlayStyle","effectiveRoiRegions","clipPolygons","renderPointData","setRenderPointData","runId","applyResult","stats","outputCount","shouldEnablePointHitTest","pointSpatialIndex","getCellByCoordinates","coordinate","pointSizePx","hitRadiusWorld","baseCellX","baseCellY","cellRadius","nearestIndex","nearestDist2","nearestX","nearestY","cx","cy","pointId","emitPointHover","hit","nextIndex","nextId","emitPointClick","button","overviewHeight","overviewMargin","overviewPosition","commitActiveRegion","handleRendererStats","debugOverlayText","currentHover","hoveredPointIndex","emitViewStateChange","callback","resolveWorldCoord","resolveScreenCoord","requestCustomLayerRedraw","effectiveCustomLayerViewState","customLayerContext","viewStateForLayer","handleRegionPointerMove","isCanvasEvent","insideImage","nextHoverId","prevHoverId","handleRegionPointerLeave","handleRegionClick","nextActive","handleRegionContextMenu","jsxs","layer","Fragment"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/core/gl-utils.ts","../src/core/ortho-camera.ts","../src/core/m1-tile-renderer.ts","../src/wsi/brush-stroke.ts","../src/wsi/constants.ts","../src/wsi/utils.ts","../src/react/draw-layer.tsx","../src/wsi/image-info.ts","../src/react/overview-map.tsx","../src/react/tile-viewer-canvas.tsx","../src/wsi/point-clip.ts","../src/wsi/webgpu.ts","../src/wsi/point-clip-hybrid.ts","../src/wsi/point-clip-worker-client.ts","../src/wsi/roi-term-stats.ts","../src/wsi/tile-scheduler.ts","../src/wsi/wsi-tile-renderer.ts","../src/react/wsi-viewer-canvas.tsx"],"sourcesContent":["function compileShader(gl: WebGL2RenderingContext, type: number, source: string): WebGLShader {\n const shader = gl.createShader(type);\n if (!shader) {\n throw new Error(\"Failed to create shader.\");\n }\n\n gl.shaderSource(shader, source);\n gl.compileShader(shader);\n\n const ok = gl.getShaderParameter(shader, gl.COMPILE_STATUS);\n if (!ok) {\n const log = gl.getShaderInfoLog(shader) ?? \"unknown shader error\";\n gl.deleteShader(shader);\n throw new Error(log);\n }\n\n return shader;\n}\n\nexport function createProgram(gl: WebGL2RenderingContext, vertexSource: string, fragmentSource: string): WebGLProgram {\n const vertexShader = compileShader(gl, gl.VERTEX_SHADER, vertexSource);\n const fragmentShader = compileShader(gl, gl.FRAGMENT_SHADER, fragmentSource);\n\n const program = gl.createProgram();\n if (!program) {\n gl.deleteShader(vertexShader);\n gl.deleteShader(fragmentShader);\n throw new Error(\"Failed to create program.\");\n }\n\n gl.attachShader(program, vertexShader);\n gl.attachShader(program, fragmentShader);\n gl.linkProgram(program);\n\n gl.deleteShader(vertexShader);\n gl.deleteShader(fragmentShader);\n\n const ok = gl.getProgramParameter(program, gl.LINK_STATUS);\n if (!ok) {\n const log = gl.getProgramInfoLog(program) ?? \"unknown link error\";\n gl.deleteProgram(program);\n throw new Error(log);\n }\n\n return program;\n}\n\nexport function requireUniformLocation(\n gl: WebGL2RenderingContext,\n program: WebGLProgram,\n uniformName: string,\n): WebGLUniformLocation {\n const location = gl.getUniformLocation(program, uniformName);\n if (!location) {\n throw new Error(`Failed to get uniform location: ${uniformName}`);\n }\n return location;\n}\n\nexport function requireWebGL2(canvas: HTMLCanvasElement): WebGL2RenderingContext {\n const context = canvas.getContext(\"webgl2\", {\n alpha: false,\n antialias: false,\n depth: false,\n stencil: false,\n preserveDrawingBuffer: false,\n powerPreference: \"high-performance\",\n });\n\n if (!context) {\n throw new Error(\"WebGL2 is not available.\");\n }\n\n return context;\n}\n","export interface ViewState {\n offsetX: number;\n offsetY: number;\n zoom: number;\n}\n\nexport class OrthoCamera {\n private viewportWidth = 1;\n private viewportHeight = 1;\n\n private viewState: ViewState = {\n offsetX: 0,\n offsetY: 0,\n zoom: 1,\n };\n\n setViewport(width: number, height: number): void {\n this.viewportWidth = Math.max(1, width);\n this.viewportHeight = Math.max(1, height);\n }\n\n getViewportSize(): { width: number; height: number } {\n return {\n width: this.viewportWidth,\n height: this.viewportHeight,\n };\n }\n\n setViewState(next: Partial<ViewState>): void {\n if (next.offsetX !== undefined) {\n this.viewState.offsetX = next.offsetX;\n }\n\n if (next.offsetY !== undefined) {\n this.viewState.offsetY = next.offsetY;\n }\n\n if (next.zoom !== undefined) {\n this.viewState.zoom = Math.max(0.0001, next.zoom);\n }\n }\n\n getViewState(): ViewState {\n return { ...this.viewState };\n }\n\n getMatrix(): Float32Array {\n const viewWidth = this.viewportWidth / this.viewState.zoom;\n const viewHeight = this.viewportHeight / this.viewState.zoom;\n\n const sx = 2 / viewWidth;\n const sy = -2 / viewHeight;\n const tx = -1 - this.viewState.offsetX * sx;\n const ty = 1 - this.viewState.offsetY * sy;\n\n return new Float32Array([\n sx,\n 0,\n 0,\n 0,\n sy,\n 0,\n tx,\n ty,\n 1,\n ]);\n }\n}\n","import {\n\tcreateProgram,\n\trequireUniformLocation,\n\trequireWebGL2,\n} from \"./gl-utils\";\nimport { OrthoCamera, type ViewState } from \"./ortho-camera\";\nimport type { Bounds, TileDefinition } from \"./types\";\n\ninterface LoadedTile {\n\tid: string;\n\tbounds: Bounds;\n\ttexture: WebGLTexture;\n}\n\nexport interface M1TileRendererOptions {\n\tcanvas: HTMLCanvasElement;\n\timageWidth: number;\n\timageHeight: number;\n\tclearColor?: [number, number, number, number];\n\tinitialViewState?: Partial<ViewState>;\n}\n\nconst VERTEX_SHADER = `#version 300 es\nprecision highp float;\n\nin vec2 aUnit;\nin vec2 aUv;\n\nuniform mat3 uCamera;\nuniform vec4 uBounds;\n\nout vec2 vUv;\n\nvoid main() {\n vec2 world = vec2(\n mix(uBounds.x, uBounds.z, aUnit.x),\n mix(uBounds.y, uBounds.w, aUnit.y)\n );\n vec3 clip = uCamera * vec3(world, 1.0);\n gl_Position = vec4(clip.xy, 0.0, 1.0);\n vUv = aUv;\n}\n`;\n\nconst FRAGMENT_SHADER = `#version 300 es\nprecision highp float;\n\nin vec2 vUv;\nuniform sampler2D uTexture;\n\nout vec4 outColor;\n\nvoid main() {\n outColor = texture(uTexture, vUv);\n}\n`;\n\nexport class M1TileRenderer {\n\tprivate readonly canvas: HTMLCanvasElement;\n\tprivate readonly gl: WebGL2RenderingContext;\n\tprivate readonly camera = new OrthoCamera();\n\tprivate readonly imageWidth: number;\n\tprivate readonly imageHeight: number;\n\tprivate readonly clearColor: [number, number, number, number];\n\tprivate readonly program: WebGLProgram;\n\tprivate readonly vao: WebGLVertexArrayObject;\n\tprivate readonly quadBuffer: WebGLBuffer;\n\tprivate readonly uCameraLocation: WebGLUniformLocation;\n\tprivate readonly uBoundsLocation: WebGLUniformLocation;\n\tprivate readonly uTextureLocation: WebGLUniformLocation;\n\tprivate readonly resizeObserver: ResizeObserver;\n\n\tprivate tiles: LoadedTile[] = [];\n\tprivate frameId: number | null = null;\n\tprivate loadVersion = 0;\n\tprivate destroyed = false;\n\tprivate fitted = false;\n\tprivate controlledViewState = false;\n\n\tconstructor(options: M1TileRendererOptions) {\n\t\tthis.canvas = options.canvas;\n\t\tthis.imageWidth = Math.max(1, options.imageWidth);\n\t\tthis.imageHeight = Math.max(1, options.imageHeight);\n\t\tthis.clearColor = options.clearColor ?? [0.03, 0.05, 0.08, 1];\n\n\t\tthis.gl = requireWebGL2(this.canvas);\n\t\tthis.program = createProgram(this.gl, VERTEX_SHADER, FRAGMENT_SHADER);\n\n\t\tconst vao = this.gl.createVertexArray();\n\t\tconst quadBuffer = this.gl.createBuffer();\n\t\tif (!vao || !quadBuffer) {\n\t\t\tthrow new Error(\"Failed to create WebGL buffers.\");\n\t\t}\n\n\t\tthis.vao = vao;\n\t\tthis.quadBuffer = quadBuffer;\n\n\t\tthis.gl.bindVertexArray(this.vao);\n\t\tthis.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.quadBuffer);\n\n\t\tconst quadVertices = new Float32Array([\n\t\t\t0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1,\n\t\t]);\n\n\t\tthis.gl.bufferData(this.gl.ARRAY_BUFFER, quadVertices, this.gl.STATIC_DRAW);\n\n\t\tconst unitLocation = this.gl.getAttribLocation(this.program, \"aUnit\");\n\t\tconst uvLocation = this.gl.getAttribLocation(this.program, \"aUv\");\n\t\tif (unitLocation < 0 || uvLocation < 0) {\n\t\t\tthrow new Error(\"Failed to get attribute locations.\");\n\t\t}\n\n\t\tconst stride = 4 * Float32Array.BYTES_PER_ELEMENT;\n\t\tthis.gl.enableVertexAttribArray(unitLocation);\n\t\tthis.gl.vertexAttribPointer(\n\t\t\tunitLocation,\n\t\t\t2,\n\t\t\tthis.gl.FLOAT,\n\t\t\tfalse,\n\t\t\tstride,\n\t\t\t0,\n\t\t);\n\t\tthis.gl.enableVertexAttribArray(uvLocation);\n\t\tthis.gl.vertexAttribPointer(\n\t\t\tuvLocation,\n\t\t\t2,\n\t\t\tthis.gl.FLOAT,\n\t\t\tfalse,\n\t\t\tstride,\n\t\t\t2 * Float32Array.BYTES_PER_ELEMENT,\n\t\t);\n\n\t\tthis.gl.bindVertexArray(null);\n\t\tthis.gl.bindBuffer(this.gl.ARRAY_BUFFER, null);\n\n\t\tthis.uCameraLocation = requireUniformLocation(\n\t\t\tthis.gl,\n\t\t\tthis.program,\n\t\t\t\"uCamera\",\n\t\t);\n\t\tthis.uBoundsLocation = requireUniformLocation(\n\t\t\tthis.gl,\n\t\t\tthis.program,\n\t\t\t\"uBounds\",\n\t\t);\n\t\tthis.uTextureLocation = requireUniformLocation(\n\t\t\tthis.gl,\n\t\t\tthis.program,\n\t\t\t\"uTexture\",\n\t\t);\n\n\t\tif (options.initialViewState) {\n\t\t\tthis.controlledViewState = true;\n\t\t\tthis.camera.setViewState(options.initialViewState);\n\t\t}\n\n\t\tthis.resizeObserver = new ResizeObserver(() => {\n\t\t\tthis.resize();\n\t\t});\n\n\t\tthis.resizeObserver.observe(this.canvas);\n\t\tthis.resize();\n\t}\n\n\tasync setTiles(tiles: TileDefinition[]): Promise<void> {\n\t\tif (this.destroyed) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst version = ++this.loadVersion;\n\n\t\tconst loaded = await Promise.all(\n\t\t\ttiles.map(async (tile) => {\n\t\t\t\tconst loadedTile = await this.loadTile(tile, version);\n\t\t\t\treturn loadedTile;\n\t\t\t}),\n\t\t);\n\n\t\tif (this.destroyed || version !== this.loadVersion) {\n\t\t\tfor (const tile of loaded) {\n\t\t\t\tif (tile) {\n\t\t\t\t\tthis.gl.deleteTexture(tile.texture);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tthis.disposeTiles(this.tiles);\n\t\tthis.tiles = loaded.filter((tile): tile is LoadedTile => tile !== null);\n\t\tthis.requestRender();\n\t}\n\n\tsetViewState(viewState: Partial<ViewState>): void {\n\t\tthis.controlledViewState = true;\n\t\tthis.camera.setViewState(viewState);\n\t\tthis.requestRender();\n\t}\n\n\tgetViewState(): ViewState {\n\t\treturn this.camera.getViewState();\n\t}\n\n\tdestroy(): void {\n\t\tif (this.destroyed) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.destroyed = true;\n\t\tthis.loadVersion += 1;\n\n\t\tif (this.frameId !== null) {\n\t\t\tcancelAnimationFrame(this.frameId);\n\t\t\tthis.frameId = null;\n\t\t}\n\n\t\tthis.resizeObserver.disconnect();\n\t\tthis.disposeTiles(this.tiles);\n\t\tthis.tiles = [];\n\n\t\tthis.gl.deleteBuffer(this.quadBuffer);\n\t\tthis.gl.deleteVertexArray(this.vao);\n\t\tthis.gl.deleteProgram(this.program);\n\t}\n\n\tprivate async loadTile(\n\t\ttile: TileDefinition,\n\t\tversion: number,\n\t): Promise<LoadedTile | null> {\n\t\ttry {\n\t\t\tconst response = await fetch(tile.url);\n\t\t\tif (!response.ok) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Tile fetch failed: ${response.status} ${response.statusText}`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst blob = await response.blob();\n\t\t\tconst bitmap = await createImageBitmap(blob);\n\n\t\t\tif (this.destroyed || version !== this.loadVersion) {\n\t\t\t\tbitmap.close();\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tconst texture = this.gl.createTexture();\n\t\t\tif (!texture) {\n\t\t\t\tbitmap.close();\n\t\t\t\tthrow new Error(\"Failed to create tile texture.\");\n\t\t\t}\n\n\t\t\tthis.gl.bindTexture(this.gl.TEXTURE_2D, texture);\n\t\t\tthis.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL, 1);\n\t\t\tthis.gl.texParameteri(\n\t\t\t\tthis.gl.TEXTURE_2D,\n\t\t\t\tthis.gl.TEXTURE_WRAP_S,\n\t\t\t\tthis.gl.CLAMP_TO_EDGE,\n\t\t\t);\n\t\t\tthis.gl.texParameteri(\n\t\t\t\tthis.gl.TEXTURE_2D,\n\t\t\t\tthis.gl.TEXTURE_WRAP_T,\n\t\t\t\tthis.gl.CLAMP_TO_EDGE,\n\t\t\t);\n\t\t\tthis.gl.texParameteri(\n\t\t\t\tthis.gl.TEXTURE_2D,\n\t\t\t\tthis.gl.TEXTURE_MIN_FILTER,\n\t\t\t\tthis.gl.LINEAR,\n\t\t\t);\n\t\t\tthis.gl.texParameteri(\n\t\t\t\tthis.gl.TEXTURE_2D,\n\t\t\t\tthis.gl.TEXTURE_MAG_FILTER,\n\t\t\t\tthis.gl.LINEAR,\n\t\t\t);\n\t\t\tthis.gl.texImage2D(\n\t\t\t\tthis.gl.TEXTURE_2D,\n\t\t\t\t0,\n\t\t\t\tthis.gl.RGBA,\n\t\t\t\tthis.gl.RGBA,\n\t\t\t\tthis.gl.UNSIGNED_BYTE,\n\t\t\t\tbitmap,\n\t\t\t);\n\t\t\tthis.gl.bindTexture(this.gl.TEXTURE_2D, null);\n\t\t\tbitmap.close();\n\n\t\t\treturn {\n\t\t\t\tid: tile.id,\n\t\t\t\tbounds: tile.bounds,\n\t\t\t\ttexture,\n\t\t\t};\n\t\t} catch (error) {\n\t\t\tconsole.error(`[M1TileRenderer] tile load failed: ${tile.id}`, error);\n\t\t\treturn null;\n\t\t}\n\t}\n\n\tprivate resize(): void {\n\t\tif (this.destroyed) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst rect = this.canvas.getBoundingClientRect();\n\t\tconst cssWidth = Math.max(1, rect.width || this.canvas.clientWidth || 1);\n\t\tconst cssHeight = Math.max(1, rect.height || this.canvas.clientHeight || 1);\n\t\tconst dpr = Math.max(1, window.devicePixelRatio || 1);\n\n\t\tconst targetWidth = Math.max(1, Math.round(cssWidth * dpr));\n\t\tconst targetHeight = Math.max(1, Math.round(cssHeight * dpr));\n\n\t\tif (\n\t\t\tthis.canvas.width !== targetWidth ||\n\t\t\tthis.canvas.height !== targetHeight\n\t\t) {\n\t\t\tthis.canvas.width = targetWidth;\n\t\t\tthis.canvas.height = targetHeight;\n\t\t}\n\n\t\tthis.camera.setViewport(cssWidth, cssHeight);\n\t\tthis.gl.viewport(0, 0, this.canvas.width, this.canvas.height);\n\n\t\tif (!this.fitted && !this.controlledViewState) {\n\t\t\tthis.fitToImage();\n\t\t\tthis.fitted = true;\n\t\t}\n\n\t\tthis.requestRender();\n\t}\n\n\tprivate fitToImage(): void {\n\t\tconst viewport = this.camera.getViewportSize();\n\n\t\tconst zoom = Math.min(\n\t\t\tviewport.width / this.imageWidth,\n\t\t\tviewport.height / this.imageHeight,\n\t\t);\n\t\tconst safeZoom = Number.isFinite(zoom) && zoom > 0 ? zoom : 1;\n\n\t\tconst visibleWorldWidth = viewport.width / safeZoom;\n\t\tconst visibleWorldHeight = viewport.height / safeZoom;\n\n\t\tconst offsetX = (this.imageWidth - visibleWorldWidth) * 0.5;\n\t\tconst offsetY = (this.imageHeight - visibleWorldHeight) * 0.5;\n\n\t\tthis.camera.setViewState({\n\t\t\tzoom: safeZoom,\n\t\t\toffsetX,\n\t\t\toffsetY,\n\t\t});\n\t}\n\n\tprivate requestRender(): void {\n\t\tif (this.frameId !== null || this.destroyed) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.frameId = requestAnimationFrame(() => {\n\t\t\tthis.frameId = null;\n\t\t\tthis.render();\n\t\t});\n\t}\n\n\tprivate render(): void {\n\t\tif (this.destroyed) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.gl.clearColor(\n\t\t\tthis.clearColor[0],\n\t\t\tthis.clearColor[1],\n\t\t\tthis.clearColor[2],\n\t\t\tthis.clearColor[3],\n\t\t);\n\t\tthis.gl.clear(this.gl.COLOR_BUFFER_BIT);\n\n\t\tthis.gl.useProgram(this.program);\n\t\tthis.gl.bindVertexArray(this.vao);\n\t\tthis.gl.uniformMatrix3fv(\n\t\t\tthis.uCameraLocation,\n\t\t\tfalse,\n\t\t\tthis.camera.getMatrix(),\n\t\t);\n\t\tthis.gl.uniform1i(this.uTextureLocation, 0);\n\n\t\tfor (const tile of this.tiles) {\n\t\t\tthis.gl.activeTexture(this.gl.TEXTURE0);\n\t\t\tthis.gl.bindTexture(this.gl.TEXTURE_2D, tile.texture);\n\t\t\tthis.gl.uniform4f(\n\t\t\t\tthis.uBoundsLocation,\n\t\t\t\ttile.bounds[0],\n\t\t\t\ttile.bounds[1],\n\t\t\t\ttile.bounds[2],\n\t\t\t\ttile.bounds[3],\n\t\t\t);\n\t\t\tthis.gl.drawArrays(this.gl.TRIANGLE_STRIP, 0, 4);\n\t\t}\n\n\t\tthis.gl.bindTexture(this.gl.TEXTURE_2D, null);\n\t\tthis.gl.bindVertexArray(null);\n\t}\n\n\tprivate disposeTiles(tiles: LoadedTile[]): void {\n\t\tfor (const tile of tiles) {\n\t\t\tthis.gl.deleteTexture(tile.texture);\n\t\t}\n\t}\n}\n","export type BrushStrokeCoordinate = [number, number];\nexport type BrushStrokeBounds = [number, number, number, number];\n\nexport interface BrushStrokePolygonOptions {\n\tradius: number;\n\tclipBounds?: BrushStrokeBounds;\n\tminRasterStep?: number;\n\tmaxRasterPixels?: number;\n\tmaxRasterSize?: number;\n\tsimplifyTolerance?: number;\n\tcircleSides?: number;\n}\n\ninterface RasterConfig {\n\tminX: number;\n\tminY: number;\n\tstep: number;\n\tpadding: number;\n\twidth: number;\n\theight: number;\n}\n\ninterface BoundaryEdge {\n\tstart: number;\n\tend: number;\n\tdir: 0 | 1 | 2 | 3;\n}\n\nconst DEFAULT_MIN_RASTER_STEP = 0.1;\nconst DEFAULT_MAX_RASTER_PIXELS = 4_000_000;\nconst DEFAULT_MAX_RASTER_SIZE = 4096;\nconst DEFAULT_CIRCLE_SIDES = 64;\nconst MIN_RADIUS = 1e-6;\nconst ALPHA_THRESHOLD = 24;\n\nfunction clamp(value: number, min: number, max: number): number {\n\treturn Math.max(min, Math.min(max, value));\n}\n\nfunction closeRing(\n\tcoordinates: BrushStrokeCoordinate[],\n): BrushStrokeCoordinate[] {\n\tif (!Array.isArray(coordinates) || coordinates.length < 3) return [];\n\tconst out = coordinates.map(([x, y]) => [x, y] as BrushStrokeCoordinate);\n\tconst first = out[0];\n\tconst last = out[out.length - 1];\n\tif (!first || !last) return [];\n\tif (first[0] !== last[0] || first[1] !== last[1]) {\n\t\tout.push([first[0], first[1]]);\n\t}\n\treturn out;\n}\n\nfunction sanitizePath(\n\tpoints: BrushStrokeCoordinate[],\n): BrushStrokeCoordinate[] {\n\tif (!Array.isArray(points) || points.length === 0) return [];\n\tconst out: BrushStrokeCoordinate[] = [];\n\tfor (const point of points) {\n\t\tif (!Array.isArray(point) || point.length < 2) continue;\n\t\tconst x = Number(point[0]);\n\t\tconst y = Number(point[1]);\n\t\tif (!Number.isFinite(x) || !Number.isFinite(y)) continue;\n\t\tconst prev = out[out.length - 1];\n\t\tif (prev && Math.abs(prev[0] - x) < 1e-9 && Math.abs(prev[1] - y) < 1e-9) {\n\t\t\tcontinue;\n\t\t}\n\t\tout.push([x, y]);\n\t}\n\treturn out;\n}\n\nfunction createCirclePolygon(\n\tcenter: BrushStrokeCoordinate,\n\tradius: number,\n\tsides: number,\n): BrushStrokeCoordinate[] {\n\tif (radius <= MIN_RADIUS || sides < 8) return [];\n\tconst ring: BrushStrokeCoordinate[] = [];\n\tfor (let i = 0; i <= sides; i += 1) {\n\t\tconst t = (i / sides) * Math.PI * 2;\n\t\tring.push([\n\t\t\tcenter[0] + Math.cos(t) * radius,\n\t\t\tcenter[1] + Math.sin(t) * radius,\n\t\t]);\n\t}\n\treturn closeRing(ring);\n}\n\nfunction createBoundsFallback(\n\tpoints: BrushStrokeCoordinate[],\n\tradius: number,\n): BrushStrokeCoordinate[] {\n\tif (!points.length) return [];\n\tlet minX = Infinity;\n\tlet minY = Infinity;\n\tlet maxX = -Infinity;\n\tlet maxY = -Infinity;\n\tfor (const [x, y] of points) {\n\t\tif (x < minX) minX = x;\n\t\tif (x > maxX) maxX = x;\n\t\tif (y < minY) minY = y;\n\t\tif (y > maxY) maxY = y;\n\t}\n\tif (!Number.isFinite(minX) || !Number.isFinite(minY)) return [];\n\tconst pad = Math.max(radius, 1);\n\treturn closeRing([\n\t\t[minX - pad, minY - pad],\n\t\t[maxX + pad, minY - pad],\n\t\t[maxX + pad, maxY + pad],\n\t\t[minX - pad, maxY + pad],\n\t]);\n}\n\nfunction computeExpandedBounds(\n\tpoints: BrushStrokeCoordinate[],\n\tradius: number,\n): BrushStrokeBounds {\n\tlet minX = Infinity;\n\tlet minY = Infinity;\n\tlet maxX = -Infinity;\n\tlet maxY = -Infinity;\n\tfor (const [x, y] of points) {\n\t\tif (x < minX) minX = x;\n\t\tif (x > maxX) maxX = x;\n\t\tif (y < minY) minY = y;\n\t\tif (y > maxY) maxY = y;\n\t}\n\tconst pad = Math.max(radius, 1);\n\treturn [minX - pad, minY - pad, maxX + pad, maxY + pad];\n}\n\nfunction resolveRasterConfig(\n\tbounds: BrushStrokeBounds,\n\tradius: number,\n\toptions: BrushStrokePolygonOptions,\n): RasterConfig {\n\tconst minRasterStep = Math.max(\n\t\tDEFAULT_MIN_RASTER_STEP,\n\t\tNumber(options.minRasterStep) || 0,\n\t);\n\tconst maxRasterPixels = Math.max(\n\t\t32_768,\n\t\tMath.floor(options.maxRasterPixels || DEFAULT_MAX_RASTER_PIXELS),\n\t);\n\tconst maxRasterSize = Math.max(\n\t\t256,\n\t\tMath.floor(options.maxRasterSize || DEFAULT_MAX_RASTER_SIZE),\n\t);\n\n\tconst widthWorld = Math.max(1e-3, bounds[2] - bounds[0]);\n\tconst heightWorld = Math.max(1e-3, bounds[3] - bounds[1]);\n\tlet step = Math.max(minRasterStep, Number.EPSILON);\n\tlet padding = 3;\n\tlet width = Math.ceil(widthWorld / step) + padding * 2 + 1;\n\tlet height = Math.ceil(heightWorld / step) + padding * 2 + 1;\n\n\twhile (\n\t\twidth > maxRasterSize ||\n\t\theight > maxRasterSize ||\n\t\twidth * height > maxRasterPixels\n\t) {\n\t\tstep *= 1.15;\n\t\twidth = Math.ceil(widthWorld / step) + padding * 2 + 1;\n\t\theight = Math.ceil(heightWorld / step) + padding * 2 + 1;\n\t\tif (step > Math.max(widthWorld, heightWorld)) {\n\t\t\tbreak;\n\t\t}\n\t}\n\n\twidth = Math.max(8, width);\n\theight = Math.max(8, height);\n\n\treturn {\n\t\tminX: bounds[0],\n\t\tminY: bounds[1],\n\t\tstep,\n\t\tpadding,\n\t\twidth,\n\t\theight,\n\t};\n}\n\ntype AnyCanvas2DContext =\n\t| CanvasRenderingContext2D\n\t| OffscreenCanvasRenderingContext2D;\n\nfunction createRasterContext(\n\twidth: number,\n\theight: number,\n): AnyCanvas2DContext | null {\n\tif (typeof OffscreenCanvas !== \"undefined\") {\n\t\tconst canvas = new OffscreenCanvas(width, height);\n\t\tconst context = canvas.getContext(\"2d\", { willReadFrequently: true });\n\t\tif (context) return context;\n\t}\n\tif (typeof document !== \"undefined\") {\n\t\tconst canvas = document.createElement(\"canvas\");\n\t\tcanvas.width = width;\n\t\tcanvas.height = height;\n\t\treturn canvas.getContext(\"2d\", { willReadFrequently: true });\n\t}\n\treturn null;\n}\n\nfunction worldToRaster(\n\tpoint: BrushStrokeCoordinate,\n\tconfig: RasterConfig,\n): BrushStrokeCoordinate {\n\treturn [\n\t\t(point[0] - config.minX) / config.step + config.padding,\n\t\t(point[1] - config.minY) / config.step + config.padding,\n\t];\n}\n\nfunction rasterizeStrokeMask(\n\tpath: BrushStrokeCoordinate[],\n\tradius: number,\n\tconfig: RasterConfig,\n): Uint8Array {\n\tconst context = createRasterContext(config.width, config.height);\n\tif (!context) return new Uint8Array(0);\n\n\tcontext.clearRect(0, 0, config.width, config.height);\n\tcontext.fillStyle = \"#ffffff\";\n\tcontext.strokeStyle = \"#ffffff\";\n\tcontext.lineCap = \"round\";\n\tcontext.lineJoin = \"round\";\n\tcontext.lineWidth = (radius * 2) / config.step;\n\n\tconst points = path.map(point => worldToRaster(point, config));\n\tif (points.length <= 1) {\n\t\tconst p = points[0];\n\t\tif (!p) return new Uint8Array(0);\n\t\tcontext.beginPath();\n\t\tcontext.arc(p[0], p[1], radius / config.step, 0, Math.PI * 2);\n\t\tcontext.fill();\n\t} else {\n\t\tcontext.beginPath();\n\t\tcontext.moveTo(points[0][0], points[0][1]);\n\t\tfor (let i = 1; i < points.length; i += 1) {\n\t\t\tcontext.lineTo(points[i][0], points[i][1]);\n\t\t}\n\t\tcontext.stroke();\n\t}\n\n\tconst image = context.getImageData(0, 0, config.width, config.height);\n\tconst out = new Uint8Array(config.width * config.height);\n\tfor (let i = 0; i < out.length; i += 1) {\n\t\tout[i] = image.data[i * 4 + 3] >= ALPHA_THRESHOLD ? 1 : 0;\n\t}\n\treturn out;\n}\n\nfunction buildBoundaryEdges(mask: Uint8Array, width: number, height: number): BoundaryEdge[] {\n\tconst edges: BoundaryEdge[] = [];\n\tconst stride = width + 1;\n\tconst vertex = (x: number, y: number): number => y * stride + x;\n\tconst at = (x: number, y: number): boolean =>\n\t\tx >= 0 && y >= 0 && x < width && y < height && mask[y * width + x] > 0;\n\n\tfor (let y = 0; y < height; y += 1) {\n\t\tfor (let x = 0; x < width; x += 1) {\n\t\t\tif (!at(x, y)) continue;\n\t\t\tif (!at(x, y - 1)) {\n\t\t\t\tedges.push({\n\t\t\t\t\tstart: vertex(x, y),\n\t\t\t\t\tend: vertex(x + 1, y),\n\t\t\t\t\tdir: 0,\n\t\t\t\t});\n\t\t\t}\n\t\t\tif (!at(x + 1, y)) {\n\t\t\t\tedges.push({\n\t\t\t\t\tstart: vertex(x + 1, y),\n\t\t\t\t\tend: vertex(x + 1, y + 1),\n\t\t\t\t\tdir: 1,\n\t\t\t\t});\n\t\t\t}\n\t\t\tif (!at(x, y + 1)) {\n\t\t\t\tedges.push({\n\t\t\t\t\tstart: vertex(x + 1, y + 1),\n\t\t\t\t\tend: vertex(x, y + 1),\n\t\t\t\t\tdir: 2,\n\t\t\t\t});\n\t\t\t}\n\t\t\tif (!at(x - 1, y)) {\n\t\t\t\tedges.push({\n\t\t\t\t\tstart: vertex(x, y + 1),\n\t\t\t\t\tend: vertex(x, y),\n\t\t\t\t\tdir: 3,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\treturn edges;\n}\n\nfunction turnPriority(fromDir: number, toDir: number): number {\n\tconst delta = (toDir - fromDir + 4) % 4;\n\tif (delta === 1) return 0; // right\n\tif (delta === 0) return 1; // straight\n\tif (delta === 3) return 2; // left\n\treturn 3; // reverse\n}\n\nfunction traceLoops(edges: BoundaryEdge[]): number[][] {\n\tif (!edges.length) return [];\n\n\tconst outgoing = new Map<number, number[]>();\n\tfor (let i = 0; i < edges.length; i += 1) {\n\t\tconst entry = outgoing.get(edges[i].start);\n\t\tif (entry) {\n\t\t\tentry.push(i);\n\t\t} else {\n\t\t\toutgoing.set(edges[i].start, [i]);\n\t\t}\n\t}\n\n\tconst used = new Uint8Array(edges.length);\n\tconst loops: number[][] = [];\n\n\tfor (let i = 0; i < edges.length; i += 1) {\n\t\tif (used[i]) continue;\n\n\t\tconst first = edges[i];\n\t\tconst startVertex = first.start;\n\t\tlet currentVertex = first.end;\n\t\tlet currentDir = first.dir;\n\t\tconst loop: number[] = [first.start, first.end];\n\t\tused[i] = 1;\n\n\t\tlet guard = 0;\n\t\tconst guardLimit = edges.length * 3;\n\t\twhile (currentVertex !== startVertex && guard < guardLimit) {\n\t\t\tconst candidates = outgoing.get(currentVertex);\n\t\t\tif (!candidates || candidates.length === 0) break;\n\n\t\t\tlet bestIndex = -1;\n\t\t\tlet bestPriority = Infinity;\n\t\t\tfor (const edgeIndex of candidates) {\n\t\t\t\tif (used[edgeIndex]) continue;\n\t\t\t\tconst candidate = edges[edgeIndex];\n\t\t\t\tconst priority = turnPriority(currentDir, candidate.dir);\n\t\t\t\tif (priority < bestPriority) {\n\t\t\t\t\tbestPriority = priority;\n\t\t\t\t\tbestIndex = edgeIndex;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (bestIndex < 0) break;\n\t\t\tused[bestIndex] = 1;\n\t\t\tconst next = edges[bestIndex];\n\t\t\tcurrentVertex = next.end;\n\t\t\tcurrentDir = next.dir;\n\t\t\tloop.push(currentVertex);\n\t\t\tguard += 1;\n\t\t}\n\n\t\tif (\n\t\t\tloop.length >= 4 &&\n\t\t\tloop[0] === loop[loop.length - 1]\n\t\t) {\n\t\t\tloops.push(loop);\n\t\t}\n\t}\n\n\treturn loops;\n}\n\nfunction toWorldRing(\n\tvertexLoop: number[],\n\twidth: number,\n\tconfig: RasterConfig,\n): BrushStrokeCoordinate[] {\n\tconst stride = width + 1;\n\tconst ring: BrushStrokeCoordinate[] = [];\n\tfor (const id of vertexLoop) {\n\t\tconst x = id % stride;\n\t\tconst y = Math.floor(id / stride);\n\t\tring.push([\n\t\t\tconfig.minX + (x - config.padding) * config.step,\n\t\t\tconfig.minY + (y - config.padding) * config.step,\n\t\t]);\n\t}\n\treturn closeRing(ring);\n}\n\nfunction polygonSignedArea(ring: BrushStrokeCoordinate[]): number {\n\tif (ring.length < 4) return 0;\n\tlet sum = 0;\n\tfor (let i = 0; i < ring.length - 1; i += 1) {\n\t\tconst a = ring[i];\n\t\tconst b = ring[i + 1];\n\t\tsum += a[0] * b[1] - b[0] * a[1];\n\t}\n\treturn sum * 0.5;\n}\n\nfunction removeCollinearVertices(\n\tring: BrushStrokeCoordinate[],\n\tepsilon = 1e-9,\n): BrushStrokeCoordinate[] {\n\tconst closed = closeRing(ring);\n\tif (closed.length < 5) return closed;\n\tconst out: BrushStrokeCoordinate[] = [closed[0]];\n\tfor (let i = 1; i < closed.length - 1; i += 1) {\n\t\tconst prev = out[out.length - 1];\n\t\tconst curr = closed[i];\n\t\tconst next = closed[i + 1];\n\t\tconst cross =\n\t\t\t(curr[0] - prev[0]) * (next[1] - curr[1]) -\n\t\t\t(curr[1] - prev[1]) * (next[0] - curr[0]);\n\t\tif (Math.abs(cross) <= epsilon) continue;\n\t\tout.push(curr);\n\t}\n\tout.push(out[0]);\n\treturn closeRing(out);\n}\n\nfunction pointLineDistanceSquared(\n\tp: BrushStrokeCoordinate,\n\ta: BrushStrokeCoordinate,\n\tb: BrushStrokeCoordinate,\n): number {\n\tconst abx = b[0] - a[0];\n\tconst aby = b[1] - a[1];\n\tconst len2 = abx * abx + aby * aby;\n\tif (len2 <= 1e-12) {\n\t\tconst dx = p[0] - a[0];\n\t\tconst dy = p[1] - a[1];\n\t\treturn dx * dx + dy * dy;\n\t}\n\tconst t = clamp(\n\t\t((p[0] - a[0]) * abx + (p[1] - a[1]) * aby) / len2,\n\t\t0,\n\t\t1,\n\t);\n\tconst x = a[0] + abx * t;\n\tconst y = a[1] + aby * t;\n\tconst dx = p[0] - x;\n\tconst dy = p[1] - y;\n\treturn dx * dx + dy * dy;\n}\n\nfunction simplifyRdp(\n\tpoints: BrushStrokeCoordinate[],\n\ttolerance: number,\n): BrushStrokeCoordinate[] {\n\tif (points.length <= 2 || tolerance <= 0) return points.slice();\n\n\tconst keep = new Uint8Array(points.length);\n\tkeep[0] = 1;\n\tkeep[points.length - 1] = 1;\n\tconst tolerance2 = tolerance * tolerance;\n\tconst stack: Array<[number, number]> = [[0, points.length - 1]];\n\n\twhile (stack.length > 0) {\n\t\tconst next = stack.pop();\n\t\tif (!next) break;\n\t\tconst [start, end] = next;\n\t\tif (end - start <= 1) continue;\n\n\t\tlet maxDist2 = 0;\n\t\tlet split = -1;\n\t\tfor (let i = start + 1; i < end; i += 1) {\n\t\t\tconst dist2 = pointLineDistanceSquared(points[i], points[start], points[end]);\n\t\t\tif (dist2 > maxDist2) {\n\t\t\t\tmaxDist2 = dist2;\n\t\t\t\tsplit = i;\n\t\t\t}\n\t\t}\n\n\t\tif (split >= 0 && maxDist2 > tolerance2) {\n\t\t\tkeep[split] = 1;\n\t\t\tstack.push([start, split], [split, end]);\n\t\t}\n\t}\n\n\tconst out: BrushStrokeCoordinate[] = [];\n\tfor (let i = 0; i < points.length; i += 1) {\n\t\tif (keep[i]) out.push(points[i]);\n\t}\n\treturn out;\n}\n\nfunction simplifyClosedRing(\n\tring: BrushStrokeCoordinate[],\n\ttolerance: number,\n): BrushStrokeCoordinate[] {\n\tconst closed = closeRing(ring);\n\tif (closed.length < 5 || tolerance <= 0) return closed;\n\tconst open = closed.slice(0, -1);\n\tconst simplified = simplifyRdp(open, tolerance);\n\tif (simplified.length < 3) return closed;\n\treturn closeRing(simplified);\n}\n\nfunction clampRingToBounds(\n\tring: BrushStrokeCoordinate[],\n\tbounds: BrushStrokeBounds | undefined,\n): BrushStrokeCoordinate[] {\n\tif (!bounds) return ring;\n\treturn closeRing(\n\t\tring.map(([x, y]) => [\n\t\t\tclamp(x, bounds[0], bounds[2]),\n\t\t\tclamp(y, bounds[1], bounds[3]),\n\t\t] as BrushStrokeCoordinate),\n\t);\n}\n\nexport function buildBrushStrokePolygon(\n\tpath: BrushStrokeCoordinate[],\n\toptions: BrushStrokePolygonOptions,\n): BrushStrokeCoordinate[] {\n\tconst points = sanitizePath(path);\n\tconst radius = Math.max(MIN_RADIUS, Number(options.radius) || 0);\n\tif (points.length === 0 || !Number.isFinite(radius)) return [];\n\n\tconst circleSides = Math.max(12, Math.floor(options.circleSides || DEFAULT_CIRCLE_SIDES));\n\tif (points.length === 1) {\n\t\treturn clampRingToBounds(\n\t\t\tcreateCirclePolygon(points[0], radius, circleSides),\n\t\t\toptions.clipBounds,\n\t\t);\n\t}\n\n\tconst bounds = computeExpandedBounds(points, radius);\n\tconst raster = resolveRasterConfig(bounds, radius, options);\n\tconst mask = rasterizeStrokeMask(points, radius, raster);\n\tif (!mask.length) {\n\t\treturn clampRingToBounds(createBoundsFallback(points, radius), options.clipBounds);\n\t}\n\n\tconst edges = buildBoundaryEdges(mask, raster.width, raster.height);\n\tconst loops = traceLoops(edges);\n\tif (!loops.length) {\n\t\treturn clampRingToBounds(createBoundsFallback(points, radius), options.clipBounds);\n\t}\n\n\tlet bestRing: BrushStrokeCoordinate[] = [];\n\tlet bestArea = 0;\n\tfor (const loop of loops) {\n\t\tconst ring = toWorldRing(loop, raster.width, raster);\n\t\tconst area = Math.abs(polygonSignedArea(ring));\n\t\tif (area <= bestArea) continue;\n\t\tbestArea = area;\n\t\tbestRing = ring;\n\t}\n\n\tif (!bestRing.length) {\n\t\treturn clampRingToBounds(createBoundsFallback(points, radius), options.clipBounds);\n\t}\n\n\tconst tolerance =\n\t\ttypeof options.simplifyTolerance === \"number\" && Number.isFinite(options.simplifyTolerance)\n\t\t\t? Math.max(0, options.simplifyTolerance)\n\t\t\t: raster.step * 0.2;\n\tconst simplified = simplifyClosedRing(\n\t\tremoveCollinearVertices(bestRing, raster.step * 1e-3),\n\t\ttolerance,\n\t);\n\treturn clampRingToBounds(simplified, options.clipBounds);\n}\n","export const DEFAULT_POINT_COLOR: [number, number, number, number] = [\n\t160, 160, 160, 255,\n];\n","import { DEFAULT_POINT_COLOR } from \"./constants\";\nimport type { TermPalette, WsiViewState } from \"./types\";\n\nexport function clamp(value: number, min: number, max: number): number {\n\treturn Math.max(min, Math.min(max, value));\n}\n\nexport function calcScaleResolution(\n\timageMpp: number,\n\timageZoom: number,\n\tcurrentZoom: number,\n): number {\n\tconst mpp = Number(imageMpp);\n\tconst z0 = Number(imageZoom);\n\tconst z1 = Number(currentZoom);\n\tif (!Number.isFinite(mpp) || mpp <= 0) return 1;\n\tif (!Number.isFinite(z0) || !Number.isFinite(z1)) return mpp;\n\treturn Math.pow(2, z0 - z1) * mpp;\n}\n\nexport function calcScaleLength(\n\timageMpp: number,\n\timageZoom: number,\n\tcurrentZoom: number,\n): string {\n\tconst resolution = calcScaleResolution(imageMpp, imageZoom, currentZoom);\n\tlet length = 100 * resolution;\n\tif (Number(imageMpp)) {\n\t\tlet unit = \"μm\";\n\t\tif (length > 1000) {\n\t\t\tlength /= 1000;\n\t\t\tunit = \"mm\";\n\t\t}\n\t\treturn `${length.toPrecision(3)} ${unit}`;\n\t}\n\treturn `${Math.round(length * 1000) / 1000} pixels`;\n}\n\nexport function isSameViewState(\n\ta: Partial<WsiViewState> | null | undefined,\n\tb: Partial<WsiViewState> | null | undefined,\n): boolean {\n\tif (!a && !b) return true;\n\tif (!a || !b) return false;\n\treturn (\n\t\tMath.abs((a.zoom ?? 0) - (b.zoom ?? 0)) < 1e-6 &&\n\t\tMath.abs((a.offsetX ?? 0) - (b.offsetX ?? 0)) < 1e-6 &&\n\t\tMath.abs((a.offsetY ?? 0) - (b.offsetY ?? 0)) < 1e-6 &&\n\t\tMath.abs((a.rotationDeg ?? 0) - (b.rotationDeg ?? 0)) < 1e-6\n\t);\n}\n\nexport function toBearerToken(value: string | null | undefined): string {\n\tconst trimmed = String(value ?? \"\").trim();\n\tif (!trimmed) return \"\";\n\tif (/^bearer\\s+/i.test(trimmed)) {\n\t\tconst token = trimmed.replace(/^bearer\\s+/i, \"\").trim();\n\t\treturn token ? `Bearer ${token}` : \"\";\n\t}\n\treturn `Bearer ${trimmed}`;\n}\n\nexport function hexToRgba(\n\thex: string | null | undefined,\n): [number, number, number, number] {\n\tconst value = String(hex ?? \"\").trim();\n\tconst match = value.match(/^#?([0-9a-fA-F]{6})$/);\n\tif (!match) return [...DEFAULT_POINT_COLOR];\n\n\tconst n = Number.parseInt(match[1], 16);\n\treturn [(n >> 16) & 255, (n >> 8) & 255, n & 255, 255];\n}\n\nexport function buildTermPalette(\n\tterms:\n\t\t| Array<{ termId?: string | null; termColor?: string | null }>\n\t\t| null\n\t\t| undefined,\n): TermPalette {\n\tconst palette: Array<[number, number, number, number]> = [\n\t\t[...DEFAULT_POINT_COLOR],\n\t];\n\tconst termToPaletteIndex = new Map<string, number>();\n\n\tfor (const term of terms ?? []) {\n\t\tconst termId = String(term?.termId ?? \"\");\n\t\tif (!termId || termToPaletteIndex.has(termId)) continue;\n\n\t\ttermToPaletteIndex.set(termId, palette.length);\n\t\tpalette.push(hexToRgba(term?.termColor));\n\t}\n\n\tconst colors = new Uint8Array(palette.length * 4);\n\tfor (let i = 0; i < palette.length; i += 1) {\n\t\tcolors[i * 4] = palette[i][0];\n\t\tcolors[i * 4 + 1] = palette[i][1];\n\t\tcolors[i * 4 + 2] = palette[i][2];\n\t\tcolors[i * 4 + 3] = palette[i][3];\n\t}\n\n\treturn { colors, termToPaletteIndex };\n}\n\nexport function createProgram(\n\tgl: WebGL2RenderingContext,\n\tvertexSource: string,\n\tfragmentSource: string,\n): WebGLProgram {\n\tconst vs = gl.createShader(gl.VERTEX_SHADER);\n\tconst fs = gl.createShader(gl.FRAGMENT_SHADER);\n\tif (!vs || !fs) {\n\t\tthrow new Error(\"Shader allocation failed\");\n\t}\n\n\tgl.shaderSource(vs, vertexSource);\n\tgl.compileShader(vs);\n\tif (!gl.getShaderParameter(vs, gl.COMPILE_STATUS)) {\n\t\tthrow new Error(gl.getShaderInfoLog(vs) || \"vertex compile failed\");\n\t}\n\n\tgl.shaderSource(fs, fragmentSource);\n\tgl.compileShader(fs);\n\tif (!gl.getShaderParameter(fs, gl.COMPILE_STATUS)) {\n\t\tthrow new Error(gl.getShaderInfoLog(fs) || \"fragment compile failed\");\n\t}\n\n\tconst program = gl.createProgram();\n\tif (!program) {\n\t\tthrow new Error(\"Program allocation failed\");\n\t}\n\n\tgl.attachShader(program, vs);\n\tgl.attachShader(program, fs);\n\tgl.linkProgram(program);\n\n\tgl.deleteShader(vs);\n\tgl.deleteShader(fs);\n\n\tif (!gl.getProgramParameter(program, gl.LINK_STATUS)) {\n\t\tthrow new Error(gl.getProgramInfoLog(program) || \"program link failed\");\n\t}\n\n\treturn program;\n}\n","import { type CSSProperties, type MutableRefObject, type PointerEvent as ReactPointerEvent, type RefObject, useCallback, useEffect, useMemo, useRef } from \"react\";\nimport { buildBrushStrokePolygon } from \"../wsi/brush-stroke\";\nimport { calcScaleResolution } from \"../wsi/utils\";\n\nexport type StampDrawTool = \"stamp-rectangle\" | \"stamp-circle\" | \"stamp-rectangle-4096px\" | \"stamp-rectangle-2mm2\" | \"stamp-circle-2mm2\" | \"stamp-circle-hpf-0.2mm2\";\n\nexport type DrawTool = \"cursor\" | \"freehand\" | \"rectangle\" | \"circular\" | \"brush\" | StampDrawTool;\n\nexport type DrawCoordinate = [number, number];\n\nexport type DrawBounds = [number, number, number, number];\n\nexport type DrawIntent = \"roi\" | \"patch\" | \"brush\";\n\nexport interface DrawResult {\n tool: Exclude<DrawTool, \"cursor\">;\n intent: DrawIntent;\n coordinates: DrawCoordinate[];\n bbox: DrawBounds;\n areaPx: number;\n}\n\nexport type PatchDrawResult = DrawResult & {\n tool: \"stamp-rectangle-4096px\";\n intent: \"patch\";\n};\n\nexport interface DrawRegion {\n id?: string | number;\n coordinates: DrawCoordinate[];\n label?: string;\n}\n\nexport interface RegionStyleContext {\n region: DrawRegion;\n regionId: string | number;\n regionIndex: number;\n state: \"default\" | \"hover\" | \"active\";\n}\n\nexport type RegionStrokeStyleResolver = (context: RegionStyleContext) => Partial<RegionStrokeStyle> | null | undefined;\n\nexport type DrawOverlayCoordinates = DrawCoordinate[] | DrawCoordinate[][] | DrawCoordinate[][][];\n\nexport interface DrawOverlayShape {\n id?: string | number;\n coordinates: DrawOverlayCoordinates;\n closed?: boolean;\n fill?: boolean;\n stroke?: Partial<RegionStrokeStyle>;\n strokeStyle?: Partial<RegionStrokeStyle>;\n invertedFill?: DrawOverlayInvertedFillStyle;\n visible?: boolean;\n}\n\nexport interface DrawOverlayInvertedFillStyle {\n fillColor: string;\n}\n\nexport interface RegionStrokeStyle {\n color: string;\n width: number;\n lineDash: number[];\n lineJoin: CanvasLineJoin;\n lineCap: CanvasLineCap;\n shadowColor: string;\n shadowBlur: number;\n shadowOffsetX: number;\n shadowOffsetY: number;\n}\n\nexport interface RegionLabelStyle {\n fontFamily: string;\n fontSize: number;\n fontWeight: string | number;\n textColor: string;\n backgroundColor: string;\n borderColor: string;\n borderWidth: number;\n paddingX: number;\n paddingY: number;\n offsetY: number;\n borderRadius: number;\n}\n\nexport interface DrawProjector {\n screenToWorld(clientX: number, clientY: number): DrawCoordinate | number[];\n worldToScreen(worldX: number, worldY: number): DrawCoordinate | number[];\n getViewState?: () => { zoom: number; rotationDeg?: number };\n zoomBy?: (factor: number, screenX: number, screenY: number) => void;\n}\n\nexport interface StampOptions {\n rectangleAreaMm2?: number;\n circleAreaMm2?: number;\n rectanglePixelSize?: number;\n}\n\nexport interface BrushOptions {\n radius: number;\n /**\n * Brush edge detail factor. Higher values create rounder/finer edges.\n * Range: 0.25 ~ 4. Default: 1.\n */\n edgeDetail?: number;\n /**\n * When true, a brush \"tap\" (click without drag) on ROI selects that ROI\n * instead of creating a brush stroke.\n */\n clickSelectRoi?: boolean;\n fillColor?: string;\n fillOpacity?: number;\n cursorColor?: string;\n cursorActiveColor?: string;\n cursorLineWidth?: number;\n cursorLineDash?: number[];\n}\n\nexport interface DrawLayerProps {\n tool: DrawTool;\n imageWidth: number;\n imageHeight: number;\n imageMpp?: number;\n imageZoom?: number;\n stampOptions?: StampOptions;\n brushOptions?: BrushOptions;\n projectorRef: RefObject<DrawProjector | null>;\n onBrushTap?: (coordinate: DrawCoordinate) => boolean;\n onDrawComplete?: (result: DrawResult) => void;\n onPatchComplete?: (result: PatchDrawResult) => void;\n enabled?: boolean;\n viewStateSignal?: unknown;\n persistedRegions?: DrawRegion[];\n patchRegions?: DrawRegion[];\n persistedPolygons?: DrawCoordinate[][];\n regionStrokeStyle?: Partial<RegionStrokeStyle>;\n regionStrokeHoverStyle?: Partial<RegionStrokeStyle>;\n regionStrokeActiveStyle?: Partial<RegionStrokeStyle>;\n patchStrokeStyle?: Partial<RegionStrokeStyle>;\n resolveRegionStrokeStyle?: RegionStrokeStyleResolver;\n overlayShapes?: DrawOverlayShape[];\n hoveredRegionId?: string | number | null;\n activeRegionId?: string | number | null;\n regionLabelStyle?: Partial<RegionLabelStyle>;\n invalidateRef?: MutableRefObject<(() => void) | null>;\n className?: string;\n style?: CSSProperties;\n}\n\ninterface DrawSession {\n isDrawing: boolean;\n pointerId: number | null;\n start: DrawCoordinate | null;\n current: DrawCoordinate | null;\n cursor: DrawCoordinate | null;\n points: DrawCoordinate[];\n stampCenter: DrawCoordinate | null;\n}\n\ninterface ResolvedBrushOptions {\n radius: number;\n edgeDetail: number;\n clickSelectRoi: boolean;\n fillColor: string;\n fillOpacity: number;\n cursorColor: string;\n cursorActiveColor: string;\n cursorLineWidth: number;\n cursorLineDash: number[];\n}\n\nconst DRAW_FILL = \"rgba(255, 77, 79, 0.16)\";\nconst FREEHAND_MIN_POINTS = 3;\nconst FREEHAND_SCREEN_STEP = 2;\nconst CIRCLE_SIDES = 96;\nconst MIN_AREA_PX = 1;\nconst EMPTY_REGIONS: DrawRegion[] = [];\nconst EMPTY_DASH: number[] = [];\nconst MICRONS_PER_MM = 1000;\nconst DEFAULT_STAMP_RECTANGLE_AREA_MM2 = 2;\nconst DEFAULT_STAMP_CIRCLE_AREA_MM2 = 2;\nconst DEFAULT_STAMP_RECTANGLE_PIXEL_SIZE = 4096;\nconst LEGACY_HPF_CIRCLE_AREA_MM2 = 0.2;\nconst WHEEL_ZOOM_IN_FACTOR = 1.12;\nconst WHEEL_ZOOM_OUT_FACTOR = 0.89;\nconst DEFAULT_BRUSH_RADIUS = 32;\nconst DEFAULT_BRUSH_FILL_COLOR = \"#000000\";\nconst DEFAULT_BRUSH_FILL_OPACITY = 0.1;\nconst DEFAULT_BRUSH_CURSOR_COLOR = \"#FFCF00\";\nconst DEFAULT_BRUSH_CURSOR_ACTIVE_COLOR = \"#FF0000\";\nconst DEFAULT_BRUSH_CURSOR_LINE_WIDTH = 1.5;\nconst DEFAULT_BRUSH_CURSOR_DASH = [2, 2];\nconst DEFAULT_BRUSH_EDGE_DETAIL = 1;\nconst MIN_BRUSH_EDGE_DETAIL = 0.25;\nconst MAX_BRUSH_EDGE_DETAIL = 4;\nconst MIN_BRUSH_RASTER_STEP = 0.1;\nconst BRUSH_RASTER_DIAMETER_SAMPLES = 96;\nconst BRUSH_SCREEN_STEP = 1.5;\n\nconst DEFAULT_REGION_STROKE_STYLE: RegionStrokeStyle = {\n color: \"#ff4d4f\",\n width: 2,\n lineDash: EMPTY_DASH,\n lineJoin: \"round\",\n lineCap: \"round\",\n shadowColor: \"rgba(0, 0, 0, 0)\",\n shadowBlur: 0,\n shadowOffsetX: 0,\n shadowOffsetY: 0,\n};\n\nconst DEFAULT_PATCH_STROKE_STYLE: RegionStrokeStyle = {\n color: \"#4cc9f0\",\n width: 2,\n lineDash: [10, 8],\n lineJoin: \"round\",\n lineCap: \"round\",\n shadowColor: \"rgba(0, 0, 0, 0)\",\n shadowBlur: 0,\n shadowOffsetX: 0,\n shadowOffsetY: 0,\n};\n\nconst DEFAULT_REGION_LABEL_STYLE: RegionLabelStyle = {\n fontFamily: \"ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace\",\n fontSize: 12,\n fontWeight: 500,\n textColor: \"#ffffff\",\n backgroundColor: \"rgba(8, 14, 22, 0.88)\",\n borderColor: \"rgba(255, 77, 79, 0.85)\",\n borderWidth: 1,\n paddingX: 6,\n paddingY: 4,\n offsetY: 10,\n borderRadius: 3,\n};\n\nfunction clamp(value: number, min: number, max: number): number {\n return Math.max(min, Math.min(max, value));\n}\n\nfunction isStampTool(tool: DrawTool): tool is StampDrawTool {\n return (\n tool === \"stamp-rectangle\" || tool === \"stamp-circle\" || tool === \"stamp-rectangle-4096px\" || tool === \"stamp-rectangle-2mm2\" || tool === \"stamp-circle-2mm2\" || tool === \"stamp-circle-hpf-0.2mm2\"\n );\n}\n\nfunction clampPositiveOrFallback(value: number | undefined, fallback: number): number {\n if (typeof value !== \"number\" || !Number.isFinite(value) || value <= 0) {\n return fallback;\n }\n return value;\n}\n\nfunction resolveStampOptions(options: StampOptions | undefined): Required<StampOptions> {\n return {\n rectangleAreaMm2: clampPositiveOrFallback(options?.rectangleAreaMm2, DEFAULT_STAMP_RECTANGLE_AREA_MM2),\n circleAreaMm2: clampPositiveOrFallback(options?.circleAreaMm2, DEFAULT_STAMP_CIRCLE_AREA_MM2),\n rectanglePixelSize: clampPositiveOrFallback(options?.rectanglePixelSize, DEFAULT_STAMP_RECTANGLE_PIXEL_SIZE),\n };\n}\n\nfunction clampUnitOpacity(value: number | undefined, fallback: number): number {\n if (typeof value !== \"number\" || !Number.isFinite(value)) return fallback;\n return clamp(value, 0, 1);\n}\n\nfunction sanitizeBrushLineDash(value: number[] | undefined): number[] {\n if (!Array.isArray(value)) return DEFAULT_BRUSH_CURSOR_DASH;\n const out = value.filter(item => Number.isFinite(item) && item >= 0);\n return out.length > 0 ? out : DEFAULT_BRUSH_CURSOR_DASH;\n}\n\nfunction resolveBrushEdgeDetail(value: number | undefined): number {\n if (typeof value !== \"number\" || !Number.isFinite(value)) return DEFAULT_BRUSH_EDGE_DETAIL;\n return clamp(value, MIN_BRUSH_EDGE_DETAIL, MAX_BRUSH_EDGE_DETAIL);\n}\n\nfunction resolveBrushOptions(options: BrushOptions | undefined): ResolvedBrushOptions {\n const radius = clampPositiveOrFallback(options?.radius, DEFAULT_BRUSH_RADIUS);\n const cursorLineWidth = clampPositiveOrFallback(options?.cursorLineWidth, DEFAULT_BRUSH_CURSOR_LINE_WIDTH);\n const edgeDetail = resolveBrushEdgeDetail(options?.edgeDetail);\n return {\n radius,\n edgeDetail,\n clickSelectRoi: options?.clickSelectRoi === true,\n fillColor: options?.fillColor || DEFAULT_BRUSH_FILL_COLOR,\n fillOpacity: clampUnitOpacity(options?.fillOpacity, DEFAULT_BRUSH_FILL_OPACITY),\n cursorColor: options?.cursorColor || DEFAULT_BRUSH_CURSOR_COLOR,\n cursorActiveColor: options?.cursorActiveColor || DEFAULT_BRUSH_CURSOR_ACTIVE_COLOR,\n cursorLineWidth,\n cursorLineDash: sanitizeBrushLineDash(options?.cursorLineDash),\n };\n}\n\nfunction mm2ToUm2(areaMm2: number): number {\n return areaMm2 * MICRONS_PER_MM * MICRONS_PER_MM;\n}\n\nfunction createSquareFromCenter(center: DrawCoordinate | null, halfLength: number): DrawCoordinate[] {\n if (!center || !Number.isFinite(halfLength) || halfLength <= 0) return [];\n return closeRing([\n [center[0] - halfLength, center[1] - halfLength],\n [center[0] + halfLength, center[1] - halfLength],\n [center[0] + halfLength, center[1] + halfLength],\n [center[0] - halfLength, center[1] + halfLength],\n ]);\n}\n\nfunction createCircleFromCenter(center: DrawCoordinate | null, radius: number, sides = CIRCLE_SIDES): DrawCoordinate[] {\n if (!center || !Number.isFinite(radius) || radius <= 0) return [];\n\n const coords: DrawCoordinate[] = [];\n for (let i = 0; i <= sides; i += 1) {\n const t = (i / sides) * Math.PI * 2;\n coords.push([center[0] + Math.cos(t) * radius, center[1] + Math.sin(t) * radius]);\n }\n\n return closeRing(coords);\n}\n\nexport function closeRing(coords: DrawCoordinate[]): DrawCoordinate[] {\n if (!Array.isArray(coords) || coords.length < 3) return [];\n\n const out = coords.map(([x, y]) => [x, y] as DrawCoordinate);\n const first = out[0];\n const last = out[out.length - 1];\n if (!first || !last) return [];\n\n if (first[0] !== last[0] || first[1] !== last[1]) {\n out.push([first[0], first[1]]);\n }\n\n return out;\n}\n\nexport function createRectangle(start: DrawCoordinate | null, end: DrawCoordinate | null): DrawCoordinate[] {\n if (!start || !end) return [];\n\n return closeRing([\n [start[0], start[1]],\n [end[0], start[1]],\n [end[0], end[1]],\n [start[0], end[1]],\n ]);\n}\n\nexport function createCircle(start: DrawCoordinate | null, end: DrawCoordinate | null, sides = CIRCLE_SIDES): DrawCoordinate[] {\n if (!start || !end) return [];\n\n const centerX = (start[0] + end[0]) * 0.5;\n const centerY = (start[1] + end[1]) * 0.5;\n const radius = Math.hypot(end[0] - start[0], end[1] - start[1]) * 0.5;\n if (radius < 1) return [];\n\n const coords: DrawCoordinate[] = [];\n for (let i = 0; i <= sides; i += 1) {\n const t = (i / sides) * Math.PI * 2;\n coords.push([centerX + Math.cos(t) * radius, centerY + Math.sin(t) * radius]);\n }\n\n return closeRing(coords);\n}\n\nfunction polygonArea(coords: DrawCoordinate[]): number {\n if (!Array.isArray(coords) || coords.length < 4) return 0;\n\n let sum = 0;\n for (let i = 0; i < coords.length - 1; i += 1) {\n const a = coords[i];\n const b = coords[i + 1];\n sum += a[0] * b[1] - b[0] * a[1];\n }\n\n return Math.abs(sum * 0.5);\n}\n\nfunction computeBounds(coords: DrawCoordinate[]): DrawBounds {\n if (!Array.isArray(coords) || coords.length === 0) return [0, 0, 0, 0];\n\n let minX = Infinity;\n let minY = Infinity;\n let maxX = -Infinity;\n let maxY = -Infinity;\n\n for (const [x, y] of coords) {\n if (x < minX) minX = x;\n if (x > maxX) maxX = x;\n if (y < minY) minY = y;\n if (y > maxY) maxY = y;\n }\n\n return [minX, minY, maxX, maxY];\n}\n\nfunction isValidPolygon(coords: DrawCoordinate[]): boolean {\n return Array.isArray(coords) && coords.length >= 4 && polygonArea(coords) > MIN_AREA_PX;\n}\n\nfunction tracePath(ctx: CanvasRenderingContext2D, points: DrawCoordinate[], close = false): void {\n if (points.length === 0) return;\n\n ctx.moveTo(points[0][0], points[0][1]);\n for (let i = 1; i < points.length; i += 1) {\n ctx.lineTo(points[i][0], points[i][1]);\n }\n\n if (close) {\n ctx.closePath();\n }\n}\n\nfunction drawPath(ctx: CanvasRenderingContext2D, points: DrawCoordinate[], strokeStyle: RegionStrokeStyle, close = false, fill = false): void {\n if (points.length === 0) return;\n\n ctx.beginPath();\n tracePath(ctx, points, close);\n if (fill && close) {\n ctx.fillStyle = DRAW_FILL;\n ctx.fill();\n }\n\n ctx.strokeStyle = strokeStyle.color;\n ctx.lineWidth = strokeStyle.width;\n ctx.lineJoin = strokeStyle.lineJoin;\n ctx.lineCap = strokeStyle.lineCap;\n ctx.shadowColor = strokeStyle.shadowColor;\n ctx.shadowBlur = strokeStyle.shadowBlur;\n ctx.shadowOffsetX = strokeStyle.shadowOffsetX;\n ctx.shadowOffsetY = strokeStyle.shadowOffsetY;\n ctx.setLineDash(strokeStyle.lineDash);\n ctx.stroke();\n ctx.setLineDash(EMPTY_DASH);\n ctx.shadowColor = \"rgba(0, 0, 0, 0)\";\n ctx.shadowBlur = 0;\n ctx.shadowOffsetX = 0;\n ctx.shadowOffsetY = 0;\n}\n\nfunction resolveStrokeStyle(style: Partial<RegionStrokeStyle> | undefined): RegionStrokeStyle {\n const dash = Array.isArray(style?.lineDash) ? style.lineDash.filter(value => Number.isFinite(value) && value >= 0) : EMPTY_DASH;\n const width = typeof style?.width === \"number\" && Number.isFinite(style.width) ? Math.max(0, style.width) : DEFAULT_REGION_STROKE_STYLE.width;\n const shadowBlur = typeof style?.shadowBlur === \"number\" && Number.isFinite(style.shadowBlur) ? Math.max(0, style.shadowBlur) : DEFAULT_REGION_STROKE_STYLE.shadowBlur;\n const shadowOffsetX = typeof style?.shadowOffsetX === \"number\" && Number.isFinite(style.shadowOffsetX) ? style.shadowOffsetX : DEFAULT_REGION_STROKE_STYLE.shadowOffsetX;\n const shadowOffsetY = typeof style?.shadowOffsetY === \"number\" && Number.isFinite(style.shadowOffsetY) ? style.shadowOffsetY : DEFAULT_REGION_STROKE_STYLE.shadowOffsetY;\n return {\n color: style?.color || DEFAULT_REGION_STROKE_STYLE.color,\n width,\n lineDash: dash.length ? dash : EMPTY_DASH,\n lineJoin: style?.lineJoin || DEFAULT_REGION_STROKE_STYLE.lineJoin,\n lineCap: style?.lineCap || DEFAULT_REGION_STROKE_STYLE.lineCap,\n shadowColor: style?.shadowColor || DEFAULT_REGION_STROKE_STYLE.shadowColor,\n shadowBlur,\n shadowOffsetX,\n shadowOffsetY,\n };\n}\n\nfunction mergeStrokeStyle(base: RegionStrokeStyle, override: Partial<RegionStrokeStyle> | undefined): RegionStrokeStyle {\n if (!override) return base;\n return resolveStrokeStyle({\n color: override.color ?? base.color,\n width: override.width ?? base.width,\n lineDash: override.lineDash ?? base.lineDash,\n lineJoin: override.lineJoin ?? base.lineJoin,\n lineCap: override.lineCap ?? base.lineCap,\n shadowColor: override.shadowColor ?? base.shadowColor,\n shadowBlur: override.shadowBlur ?? base.shadowBlur,\n shadowOffsetX: override.shadowOffsetX ?? base.shadowOffsetX,\n shadowOffsetY: override.shadowOffsetY ?? base.shadowOffsetY,\n });\n}\n\nfunction isSameRegionId(a: string | number | null | undefined, b: string | number | null | undefined): boolean {\n if (a === null || a === undefined || b === null || b === undefined) {\n return false;\n }\n return String(a) === String(b);\n}\n\nfunction isNestedRingCoordinates(coordinates: DrawOverlayCoordinates): boolean {\n const first = coordinates[0];\n return Array.isArray(first) && Array.isArray(first[0]);\n}\n\nfunction isFiniteNumber(value: unknown): value is number {\n return typeof value === \"number\" && Number.isFinite(value);\n}\n\nfunction isCoordinatePair(value: unknown): value is [number, number] {\n return Array.isArray(value) && value.length >= 2 && isFiniteNumber(value[0]) && isFiniteNumber(value[1]);\n}\n\nfunction isCoordinateRing(value: unknown): value is DrawCoordinate[] {\n return Array.isArray(value) && value.length >= 2 && value.every(point => isCoordinatePair(point));\n}\n\nfunction collectOverlayRings(value: unknown, out: DrawCoordinate[][]): void {\n if (!Array.isArray(value) || value.length === 0) return;\n if (isCoordinateRing(value)) {\n out.push(value.map(([x, y]) => [x, y] as DrawCoordinate));\n return;\n }\n for (const item of value) {\n collectOverlayRings(item, out);\n }\n}\n\nfunction normalizeOverlayRings(coordinates: DrawOverlayCoordinates, close: boolean): DrawCoordinate[][] {\n const sourceRings: DrawCoordinate[][] = [];\n collectOverlayRings(coordinates, sourceRings);\n const out: DrawCoordinate[][] = [];\n for (const ring of sourceRings) {\n if (ring.length < 2) continue;\n const normalized = close ? closeRing(ring) : ring;\n if (normalized.length >= (close ? 4 : 2)) {\n out.push(normalized);\n }\n }\n return out;\n}\n\nfunction drawInvertedFillMask(ctx: CanvasRenderingContext2D, outerRing: DrawCoordinate[], holeRings: DrawCoordinate[][], fillColor: string): void {\n if (outerRing.length < 4 || holeRings.length === 0) return;\n ctx.save();\n ctx.beginPath();\n tracePath(ctx, outerRing, true);\n for (const ring of holeRings) {\n if (ring.length < 4) continue;\n tracePath(ctx, ring, true);\n }\n ctx.fillStyle = fillColor;\n ctx.fill(\"evenodd\");\n ctx.restore();\n}\n\nfunction resolveLabelStyle(style: Partial<RegionLabelStyle> | undefined): RegionLabelStyle {\n const px = typeof style?.paddingX === \"number\" && Number.isFinite(style.paddingX) ? Math.max(0, style.paddingX) : DEFAULT_REGION_LABEL_STYLE.paddingX;\n const py = typeof style?.paddingY === \"number\" && Number.isFinite(style.paddingY) ? Math.max(0, style.paddingY) : DEFAULT_REGION_LABEL_STYLE.paddingY;\n const fs = typeof style?.fontSize === \"number\" && Number.isFinite(style.fontSize) ? Math.max(8, style.fontSize) : DEFAULT_REGION_LABEL_STYLE.fontSize;\n const bw = typeof style?.borderWidth === \"number\" && Number.isFinite(style.borderWidth) ? Math.max(0, style.borderWidth) : DEFAULT_REGION_LABEL_STYLE.borderWidth;\n const oy = typeof style?.offsetY === \"number\" && Number.isFinite(style.offsetY) ? style.offsetY : DEFAULT_REGION_LABEL_STYLE.offsetY;\n const br = typeof style?.borderRadius === \"number\" && Number.isFinite(style.borderRadius) ? Math.max(0, style.borderRadius) : DEFAULT_REGION_LABEL_STYLE.borderRadius;\n return {\n fontFamily: style?.fontFamily || DEFAULT_REGION_LABEL_STYLE.fontFamily,\n fontSize: fs,\n fontWeight: style?.fontWeight || DEFAULT_REGION_LABEL_STYLE.fontWeight,\n textColor: style?.textColor || DEFAULT_REGION_LABEL_STYLE.textColor,\n backgroundColor: style?.backgroundColor || DEFAULT_REGION_LABEL_STYLE.backgroundColor,\n borderColor: style?.borderColor || DEFAULT_REGION_LABEL_STYLE.borderColor,\n borderWidth: bw,\n paddingX: px,\n paddingY: py,\n offsetY: oy,\n borderRadius: br,\n };\n}\n\nfunction drawRoundedRect(ctx: CanvasRenderingContext2D, x: number, y: number, width: number, height: number, radius: number): void {\n const r = Math.max(0, Math.min(radius, width * 0.5, height * 0.5));\n ctx.beginPath();\n ctx.moveTo(x + r, y);\n ctx.lineTo(x + width - r, y);\n ctx.quadraticCurveTo(x + width, y, x + width, y + r);\n ctx.lineTo(x + width, y + height - r);\n ctx.quadraticCurveTo(x + width, y + height, x + width - r, y + height);\n ctx.lineTo(x + r, y + height);\n ctx.quadraticCurveTo(x, y + height, x, y + height - r);\n ctx.lineTo(x, y + r);\n ctx.quadraticCurveTo(x, y, x + r, y);\n ctx.closePath();\n}\n\nfunction getTopAnchor(coords: DrawCoordinate[]): DrawCoordinate | null {\n if (!coords.length) return null;\n\n let minY = Infinity;\n for (const point of coords) {\n if (point[1] < minY) minY = point[1];\n }\n if (!Number.isFinite(minY)) return null;\n\n let minX = Infinity;\n let maxX = -Infinity;\n for (const point of coords) {\n if (Math.abs(point[1] - minY) > 0.5) continue;\n if (point[0] < minX) minX = point[0];\n if (point[0] > maxX) maxX = point[0];\n }\n\n if (!Number.isFinite(minX) || !Number.isFinite(maxX)) return null;\n return [(minX + maxX) * 0.5, minY];\n}\n\nfunction drawRegionLabel(ctx: CanvasRenderingContext2D, text: string, anchor: DrawCoordinate, canvasWidth: number, canvasHeight: number, labelStyle: RegionLabelStyle): void {\n const label = text.trim();\n if (!label) return;\n\n ctx.save();\n ctx.font = `${labelStyle.fontWeight} ${labelStyle.fontSize}px ${labelStyle.fontFamily}`;\n ctx.textAlign = \"center\";\n ctx.textBaseline = \"middle\";\n\n const textWidth = ctx.measureText(label).width;\n const boxWidth = textWidth + labelStyle.paddingX * 2;\n const boxHeight = labelStyle.fontSize + labelStyle.paddingY * 2;\n\n const x = clamp(anchor[0], boxWidth * 0.5 + 1, canvasWidth - boxWidth * 0.5 - 1);\n const y = clamp(anchor[1] - labelStyle.offsetY, boxHeight * 0.5 + 1, canvasHeight - boxHeight * 0.5 - 1);\n const left = x - boxWidth * 0.5;\n const top = y - boxHeight * 0.5;\n\n ctx.fillStyle = labelStyle.backgroundColor;\n ctx.strokeStyle = labelStyle.borderColor;\n ctx.lineWidth = labelStyle.borderWidth;\n drawRoundedRect(ctx, left, top, boxWidth, boxHeight, labelStyle.borderRadius);\n ctx.fill();\n if (labelStyle.borderWidth > 0) {\n ctx.stroke();\n }\n\n ctx.fillStyle = labelStyle.textColor;\n ctx.fillText(label, x, y + 0.5);\n ctx.restore();\n}\n\nfunction clampWorld(coord: DrawCoordinate, imageWidth: number, imageHeight: number): DrawCoordinate {\n return [clamp(coord[0], 0, imageWidth), clamp(coord[1], 0, imageHeight)];\n}\n\nfunction toCoord(value: DrawCoordinate | number[]): DrawCoordinate | null {\n if (!Array.isArray(value) || value.length < 2) return null;\n const x = Number(value[0]);\n const y = Number(value[1]);\n if (!Number.isFinite(x) || !Number.isFinite(y)) return null;\n return [x, y];\n}\n\nexport function DrawLayer({\n tool,\n imageWidth,\n imageHeight,\n imageMpp,\n imageZoom,\n stampOptions,\n brushOptions,\n projectorRef,\n onBrushTap,\n onDrawComplete,\n onPatchComplete,\n enabled,\n viewStateSignal,\n persistedRegions,\n patchRegions,\n persistedPolygons,\n regionStrokeStyle,\n regionStrokeHoverStyle,\n regionStrokeActiveStyle,\n patchStrokeStyle,\n resolveRegionStrokeStyle,\n overlayShapes,\n hoveredRegionId = null,\n activeRegionId = null,\n regionLabelStyle,\n invalidateRef,\n className,\n style,\n}: DrawLayerProps): React.ReactElement {\n const canvasRef = useRef<HTMLCanvasElement | null>(null);\n const drawPendingRef = useRef(false);\n const overlayDebugSnapshotRef = useRef<Map<string, string>>(new Map());\n const lastToolRef = useRef<DrawTool>(tool);\n const sessionRef = useRef<DrawSession>({\n isDrawing: false,\n pointerId: null,\n start: null,\n current: null,\n cursor: null,\n points: [],\n stampCenter: null,\n });\n\n const active = enabled ?? tool !== \"cursor\";\n const mergedPersistedRegions = useMemo<DrawRegion[]>(() => {\n if (persistedRegions && persistedRegions.length > 0) {\n return persistedRegions;\n }\n if (!persistedPolygons || persistedPolygons.length === 0) {\n return EMPTY_REGIONS;\n }\n return persistedPolygons.map((coordinates, index) => ({\n id: index,\n coordinates,\n }));\n }, [persistedRegions, persistedPolygons]);\n const mergedPatchRegions = useMemo<DrawRegion[]>(() => patchRegions ?? EMPTY_REGIONS, [patchRegions]);\n\n const resolvedStrokeStyle = useMemo(() => resolveStrokeStyle(regionStrokeStyle), [regionStrokeStyle]);\n const resolvedHoverStrokeStyle = useMemo(() => mergeStrokeStyle(resolvedStrokeStyle, regionStrokeHoverStyle), [resolvedStrokeStyle, regionStrokeHoverStyle]);\n const resolvedActiveStrokeStyle = useMemo(() => mergeStrokeStyle(resolvedStrokeStyle, regionStrokeActiveStyle), [resolvedStrokeStyle, regionStrokeActiveStyle]);\n const resolvedPatchStrokeStyle = useMemo(() => mergeStrokeStyle(DEFAULT_PATCH_STROKE_STYLE, patchStrokeStyle), [patchStrokeStyle]);\n\n const resolvedLabelStyle = useMemo(() => resolveLabelStyle(regionLabelStyle), [regionLabelStyle]);\n const resolvedStampOptions = useMemo(() => resolveStampOptions(stampOptions), [stampOptions]);\n const resolvedBrushOptions = useMemo(() => resolveBrushOptions(brushOptions), [brushOptions]);\n\n const mergedStyle = useMemo<CSSProperties>(\n () => ({\n position: \"absolute\",\n inset: 0,\n zIndex: 2,\n width: \"100%\",\n height: \"100%\",\n display: \"block\",\n touchAction: \"none\",\n pointerEvents: active ? \"auto\" : \"none\",\n cursor: active ? (tool === \"brush\" ? \"none\" : \"crosshair\") : \"default\",\n ...style,\n }),\n [active, tool, style]\n );\n\n const resizeCanvas = useCallback(() => {\n const canvas = canvasRef.current;\n if (!canvas) return;\n\n const rect = canvas.getBoundingClientRect();\n const dpr = Math.max(1, window.devicePixelRatio || 1);\n const w = Math.max(1, Math.round(rect.width * dpr));\n const h = Math.max(1, Math.round(rect.height * dpr));\n\n if (canvas.width !== w || canvas.height !== h) {\n canvas.width = w;\n canvas.height = h;\n }\n }, []);\n\n const worldToScreenPoints = useCallback(\n (points: DrawCoordinate[]): DrawCoordinate[] => {\n const projector = projectorRef.current;\n if (!projector || points.length === 0) return [];\n\n const out = new Array<DrawCoordinate>(points.length);\n for (let i = 0; i < points.length; i += 1) {\n const coord = toCoord(projector.worldToScreen(points[i][0], points[i][1]));\n if (!coord) return [];\n out[i] = coord;\n }\n return out;\n },\n [projectorRef]\n );\n\n const worldRadiusToScreenPixels = useCallback(\n (center: DrawCoordinate, worldRadius: number): number => {\n if (!Number.isFinite(worldRadius) || worldRadius <= 0) return 0;\n const projector = projectorRef.current;\n if (!projector) return 0;\n const a = toCoord(projector.worldToScreen(center[0], center[1]));\n const b = toCoord(projector.worldToScreen(center[0] + worldRadius, center[1]));\n if (!a || !b) return 0;\n return Math.hypot(b[0] - a[0], b[1] - a[1]);\n },\n [projectorRef]\n );\n\n const micronsToWorldPixels = useCallback(\n (lengthUm: number): number => {\n if (!Number.isFinite(lengthUm) || lengthUm <= 0) return 0;\n\n // If mpp is missing, fall back to 1um/px assumption.\n const mppValue = typeof imageMpp === \"number\" && Number.isFinite(imageMpp) && imageMpp > 0 ? imageMpp : 1;\n const imageZoomValue = typeof imageZoom === \"number\" && Number.isFinite(imageZoom) ? imageZoom : 0;\n const viewZoomRaw = projectorRef.current?.getViewState?.().zoom;\n const viewZoom = typeof viewZoomRaw === \"number\" && Number.isFinite(viewZoomRaw) && viewZoomRaw > 0 ? viewZoomRaw : 1;\n const continuousZoom = imageZoomValue + Math.log2(viewZoom);\n const umPerScreenPixel = Math.max(1e-9, calcScaleResolution(mppValue, imageZoomValue, continuousZoom));\n const screenPixels = lengthUm / umPerScreenPixel;\n return screenPixels / viewZoom;\n },\n [imageMpp, imageZoom, projectorRef]\n );\n\n const buildStampCoords = useCallback(\n (stampTool: StampDrawTool, center: DrawCoordinate | null): DrawCoordinate[] => {\n if (!center) return [];\n\n let areaMm2 = 0;\n if (stampTool === \"stamp-rectangle-4096px\") {\n const halfLength = resolvedStampOptions.rectanglePixelSize * 0.5;\n const fixed = createSquareFromCenter(center, halfLength);\n return fixed.map(point => clampWorld(point, imageWidth, imageHeight));\n }\n\n if (stampTool === \"stamp-rectangle\" || stampTool === \"stamp-rectangle-2mm2\") {\n areaMm2 = stampTool === \"stamp-rectangle-2mm2\" ? DEFAULT_STAMP_RECTANGLE_AREA_MM2 : resolvedStampOptions.rectangleAreaMm2;\n } else if (stampTool === \"stamp-circle\" || stampTool === \"stamp-circle-2mm2\" || stampTool === \"stamp-circle-hpf-0.2mm2\") {\n areaMm2 = stampTool === \"stamp-circle-hpf-0.2mm2\" ? LEGACY_HPF_CIRCLE_AREA_MM2 : stampTool === \"stamp-circle-2mm2\" ? DEFAULT_STAMP_CIRCLE_AREA_MM2 : resolvedStampOptions.circleAreaMm2;\n }\n if (!Number.isFinite(areaMm2) || areaMm2 <= 0) return [];\n\n const areaUm2 = mm2ToUm2(areaMm2);\n let coords: DrawCoordinate[] = [];\n if (stampTool === \"stamp-rectangle\" || stampTool === \"stamp-rectangle-2mm2\") {\n const halfLength = micronsToWorldPixels(Math.sqrt(areaUm2) * 0.5);\n coords = createSquareFromCenter(center, halfLength);\n } else if (stampTool === \"stamp-circle\" || stampTool === \"stamp-circle-2mm2\" || stampTool === \"stamp-circle-hpf-0.2mm2\") {\n const radius = micronsToWorldPixels(Math.sqrt(areaUm2 / Math.PI));\n coords = createCircleFromCenter(center, radius);\n }\n\n if (!coords.length) return [];\n return coords.map(point => clampWorld(point, imageWidth, imageHeight));\n },\n [micronsToWorldPixels, imageWidth, imageHeight, resolvedStampOptions]\n );\n\n const buildPreviewCoords = useCallback((): DrawCoordinate[] => {\n const session = sessionRef.current;\n if (isStampTool(tool)) {\n return buildStampCoords(tool, session.stampCenter);\n }\n if (tool === \"brush\") {\n return [];\n }\n if (!session.isDrawing) return [];\n\n if (tool === \"freehand\") {\n return session.points;\n }\n if (tool === \"rectangle\") {\n return createRectangle(session.start, session.current);\n }\n if (tool === \"circular\") {\n return createCircle(session.start, session.current);\n }\n\n return [];\n }, [tool, buildStampCoords]);\n\n const drawBrushStrokePreview = useCallback(\n (ctx: CanvasRenderingContext2D): void => {\n const session = sessionRef.current;\n if (!session.isDrawing || session.points.length === 0) return;\n\n const screenPoints = worldToScreenPoints(session.points);\n if (screenPoints.length === 0) return;\n const anchor = session.points[session.points.length - 1] ?? session.points[0];\n const radiusPx = worldRadiusToScreenPixels(anchor, resolvedBrushOptions.radius);\n if (!Number.isFinite(radiusPx) || radiusPx <= 0) return;\n\n ctx.save();\n ctx.globalAlpha = resolvedBrushOptions.fillOpacity;\n ctx.fillStyle = resolvedBrushOptions.fillColor;\n ctx.strokeStyle = resolvedBrushOptions.fillColor;\n ctx.lineCap = \"round\";\n ctx.lineJoin = \"round\";\n ctx.lineWidth = radiusPx * 2;\n if (screenPoints.length === 1) {\n ctx.beginPath();\n ctx.arc(screenPoints[0][0], screenPoints[0][1], radiusPx, 0, Math.PI * 2);\n ctx.fill();\n } else {\n ctx.beginPath();\n ctx.moveTo(screenPoints[0][0], screenPoints[0][1]);\n for (let i = 1; i < screenPoints.length; i += 1) {\n ctx.lineTo(screenPoints[i][0], screenPoints[i][1]);\n }\n ctx.stroke();\n }\n ctx.restore();\n },\n [worldToScreenPoints, worldRadiusToScreenPixels, resolvedBrushOptions]\n );\n\n const drawBrushCursor = useCallback(\n (ctx: CanvasRenderingContext2D): void => {\n const session = sessionRef.current;\n const cursor = session.cursor;\n if (!cursor) return;\n const screen = toCoord(projectorRef.current?.worldToScreen(cursor[0], cursor[1]) ?? []);\n if (!screen) return;\n const radiusPx = worldRadiusToScreenPixels(cursor, resolvedBrushOptions.radius);\n if (!Number.isFinite(radiusPx) || radiusPx <= 0) return;\n\n ctx.save();\n ctx.beginPath();\n ctx.arc(screen[0], screen[1], radiusPx, 0, Math.PI * 2);\n ctx.strokeStyle = session.isDrawing ? resolvedBrushOptions.cursorActiveColor : resolvedBrushOptions.cursorColor;\n ctx.lineWidth = resolvedBrushOptions.cursorLineWidth;\n ctx.setLineDash(resolvedBrushOptions.cursorLineDash);\n ctx.stroke();\n ctx.setLineDash(EMPTY_DASH);\n ctx.restore();\n },\n [projectorRef, worldRadiusToScreenPixels, resolvedBrushOptions]\n );\n\n const drawOverlay = useCallback(() => {\n resizeCanvas();\n\n const canvas = canvasRef.current;\n if (!canvas) return;\n\n const ctx = canvas.getContext(\"2d\");\n if (!ctx) return;\n\n const dpr = Math.max(1, window.devicePixelRatio || 1);\n const canvasWidth = canvas.width / dpr;\n const canvasHeight = canvas.height / dpr;\n ctx.setTransform(1, 0, 0, 1, 0, 0);\n ctx.clearRect(0, 0, canvas.width, canvas.height);\n ctx.setTransform(dpr, 0, 0, dpr, 0, 0);\n\n // Persisted ROI outlines always remain visible.\n if (mergedPersistedRegions.length > 0) {\n for (let i = 0; i < mergedPersistedRegions.length; i += 1) {\n const region = mergedPersistedRegions[i];\n const ring = region?.coordinates;\n if (!ring || ring.length < 3) continue;\n const closed = closeRing(ring);\n const screen = worldToScreenPoints(closed);\n if (screen.length >= 4) {\n const regionKey = region.id ?? i;\n const state: RegionStyleContext[\"state\"] = isSameRegionId(activeRegionId, regionKey) ? \"active\" : isSameRegionId(hoveredRegionId, regionKey) ? \"hover\" : \"default\";\n let strokeStyle = state === \"active\" ? resolvedActiveStrokeStyle : state === \"hover\" ? resolvedHoverStrokeStyle : resolvedStrokeStyle;\n\n if (resolveRegionStrokeStyle) {\n const resolved = resolveRegionStrokeStyle({\n region,\n regionId: regionKey,\n regionIndex: i,\n state,\n });\n strokeStyle = mergeStrokeStyle(strokeStyle, resolved || undefined);\n }\n drawPath(ctx, screen, strokeStyle, true, false);\n }\n }\n }\n\n if (mergedPatchRegions.length > 0) {\n for (let i = 0; i < mergedPatchRegions.length; i += 1) {\n const region = mergedPatchRegions[i];\n const ring = region?.coordinates;\n if (!ring || ring.length < 3) continue;\n const closed = closeRing(ring);\n const screen = worldToScreenPoints(closed);\n if (screen.length < 4) continue;\n drawPath(ctx, screen, resolvedPatchStrokeStyle, true, false);\n }\n }\n\n if (Array.isArray(overlayShapes) && overlayShapes.length > 0) {\n const debugOverlay = Boolean((globalThis as { __OPEN_PLANT_DEBUG_OVERLAY__?: boolean }).__OPEN_PLANT_DEBUG_OVERLAY__);\n const imageOuterRing = worldToScreenPoints(\n closeRing([\n [0, 0],\n [imageWidth, 0],\n [imageWidth, imageHeight],\n [0, imageHeight],\n ])\n );\n for (let i = 0; i < overlayShapes.length; i += 1) {\n const shape = overlayShapes[i];\n if (!shape?.coordinates?.length || shape.visible === false) continue;\n\n const closed = shape.closed ?? isNestedRingCoordinates(shape.coordinates);\n const renderRings = normalizeOverlayRings(shape.coordinates, closed);\n\n if (shape.invertedFill?.fillColor) {\n const holeRings: DrawCoordinate[][] = [];\n const closedRings = normalizeOverlayRings(shape.coordinates, true);\n for (const ring of closedRings) {\n const screen = worldToScreenPoints(ring);\n if (screen.length >= 4) {\n holeRings.push(screen);\n }\n }\n if (debugOverlay) {\n const debugKey = String(shape.id ?? i);\n const debugSignature = `${imageOuterRing.length}|${closedRings.length}|${holeRings.length}|${shape.invertedFill.fillColor}`;\n if (overlayDebugSnapshotRef.current.get(debugKey) !== debugSignature) {\n overlayDebugSnapshotRef.current.set(debugKey, debugSignature);\n console.debug(\"[open-plant] invertedFill\", {\n id: shape.id ?? i,\n outerRingPoints: imageOuterRing.length,\n sourceRingCount: closedRings.length,\n holeRingCount: holeRings.length,\n fillColor: shape.invertedFill.fillColor,\n });\n }\n }\n drawInvertedFillMask(ctx, imageOuterRing, holeRings, shape.invertedFill.fillColor);\n }\n\n if (renderRings.length === 0) continue;\n const strokeStyle = mergeStrokeStyle(resolvedStrokeStyle, shape.stroke ?? shape.strokeStyle);\n for (const ring of renderRings) {\n const screen = worldToScreenPoints(ring);\n if (screen.length < 2) continue;\n drawPath(ctx, screen, strokeStyle, closed, shape.fill ?? false);\n }\n }\n }\n\n if (active) {\n if (tool === \"brush\") {\n drawBrushStrokePreview(ctx);\n drawBrushCursor(ctx);\n } else {\n const preview = buildPreviewCoords();\n if (preview.length > 0) {\n if (tool === \"freehand\") {\n const line = worldToScreenPoints(preview);\n if (line.length >= 2) {\n drawPath(ctx, line, resolvedStrokeStyle, false, false);\n }\n if (line.length >= 3) {\n drawPath(ctx, worldToScreenPoints(closeRing(preview)), resolvedStrokeStyle, true, true);\n }\n } else {\n const polygon = worldToScreenPoints(preview);\n if (polygon.length >= 4) {\n drawPath(ctx, polygon, resolvedStrokeStyle, true, true);\n }\n }\n }\n }\n }\n\n // Draw labels last so they stay visually on top.\n if (mergedPersistedRegions.length > 0) {\n for (const region of mergedPersistedRegions) {\n if (!region.label) continue;\n const ring = region?.coordinates;\n if (!ring || ring.length < 3) continue;\n const closed = closeRing(ring);\n const anchorWorld = getTopAnchor(closed);\n if (!anchorWorld) continue;\n const anchorScreen = toCoord(projectorRef.current?.worldToScreen(anchorWorld[0], anchorWorld[1]) ?? []);\n if (!anchorScreen) continue;\n drawRegionLabel(ctx, region.label, anchorScreen, canvasWidth, canvasHeight, resolvedLabelStyle);\n }\n }\n }, [\n active,\n tool,\n buildPreviewCoords,\n drawBrushStrokePreview,\n drawBrushCursor,\n resizeCanvas,\n worldToScreenPoints,\n imageWidth,\n imageHeight,\n projectorRef,\n mergedPersistedRegions,\n overlayShapes,\n hoveredRegionId,\n activeRegionId,\n resolvedStrokeStyle,\n resolvedHoverStrokeStyle,\n resolvedActiveStrokeStyle,\n mergedPatchRegions,\n resolvedPatchStrokeStyle,\n resolveRegionStrokeStyle,\n resolvedLabelStyle,\n ]);\n\n const requestDraw = useCallback(() => {\n if (drawPendingRef.current) return;\n drawPendingRef.current = true;\n requestAnimationFrame(() => {\n drawPendingRef.current = false;\n drawOverlay();\n });\n }, [drawOverlay]);\n\n const resetSession = useCallback((preserveCursor = false) => {\n const session = sessionRef.current;\n const canvas = canvasRef.current;\n\n if (canvas && session.pointerId !== null && canvas.hasPointerCapture(session.pointerId)) {\n try {\n canvas.releasePointerCapture(session.pointerId);\n } catch {\n // noop\n }\n }\n\n session.isDrawing = false;\n session.pointerId = null;\n session.start = null;\n session.current = null;\n session.points = [];\n session.stampCenter = null;\n if (!preserveCursor) {\n session.cursor = null;\n }\n }, []);\n\n const toWorld = useCallback(\n (event: ReactPointerEvent<HTMLCanvasElement>): DrawCoordinate | null => {\n const projector = projectorRef.current;\n if (!projector || imageWidth <= 0 || imageHeight <= 0) return null;\n\n const raw = toCoord(projector.screenToWorld(event.clientX, event.clientY));\n if (!raw) return null;\n return clampWorld(raw, imageWidth, imageHeight);\n },\n [projectorRef, imageWidth, imageHeight]\n );\n\n const finishSession = useCallback(() => {\n const session = sessionRef.current;\n if (!session.isDrawing) {\n resetSession(true);\n requestDraw();\n return;\n }\n\n let coordinates: DrawCoordinate[] = [];\n if (tool === \"freehand\") {\n if (session.points.length >= FREEHAND_MIN_POINTS) {\n coordinates = closeRing(session.points);\n }\n } else if (tool === \"rectangle\") {\n coordinates = createRectangle(session.start, session.current);\n } else if (tool === \"circular\") {\n coordinates = createCircle(session.start, session.current);\n } else if (tool === \"brush\") {\n const tapPoint = session.points[session.points.length - 1] ?? session.current ?? session.start;\n if (resolvedBrushOptions.clickSelectRoi && tapPoint && session.points.length <= 1 && onBrushTap?.(tapPoint)) {\n resetSession(true);\n requestDraw();\n return;\n }\n const edgeDetail = resolvedBrushOptions.edgeDetail;\n const minRasterStep = Math.max(\n MIN_BRUSH_RASTER_STEP,\n (resolvedBrushOptions.radius * 2) / (BRUSH_RASTER_DIAMETER_SAMPLES * edgeDetail),\n );\n coordinates = buildBrushStrokePolygon(session.points, {\n radius: resolvedBrushOptions.radius,\n clipBounds: [0, 0, imageWidth, imageHeight],\n minRasterStep,\n circleSides: Math.max(24, Math.round(64 * edgeDetail)),\n simplifyTolerance: minRasterStep * 0.4,\n }) as DrawCoordinate[];\n }\n\n if ((tool === \"freehand\" || tool === \"rectangle\" || tool === \"circular\" || tool === \"brush\") && isValidPolygon(coordinates) && onDrawComplete) {\n const intent: DrawIntent = tool === \"brush\" ? \"brush\" : \"roi\";\n onDrawComplete({\n tool,\n intent,\n coordinates,\n bbox: computeBounds(coordinates),\n areaPx: polygonArea(coordinates),\n });\n }\n\n resetSession(true);\n requestDraw();\n }, [tool, onDrawComplete, resetSession, requestDraw, resolvedBrushOptions.radius, resolvedBrushOptions.edgeDetail, resolvedBrushOptions.clickSelectRoi, imageWidth, imageHeight, onBrushTap]);\n\n const handleStampAt = useCallback(\n (stampTool: StampDrawTool, center: DrawCoordinate): void => {\n const coordinates = buildStampCoords(stampTool, center);\n if (!isValidPolygon(coordinates)) return;\n const intent: DrawIntent = stampTool === \"stamp-rectangle-4096px\" ? \"patch\" : \"roi\";\n const result: DrawResult = {\n tool: stampTool,\n intent,\n coordinates,\n bbox: computeBounds(coordinates),\n areaPx: polygonArea(coordinates),\n };\n onDrawComplete?.(result);\n if (intent === \"patch\" && onPatchComplete) {\n onPatchComplete(result as PatchDrawResult);\n }\n },\n [buildStampCoords, onDrawComplete, onPatchComplete]\n );\n\n const appendBrushPoint = useCallback(\n (session: DrawSession, world: DrawCoordinate): void => {\n const projector = projectorRef.current;\n const zoom = Math.max(1e-6, projector?.getViewState?.().zoom ?? 1);\n const minWorldStep = BRUSH_SCREEN_STEP / zoom;\n const minWorldStep2 = minWorldStep * minWorldStep;\n const prev = session.points[session.points.length - 1];\n if (!prev) {\n session.points.push(world);\n session.current = world;\n return;\n }\n const dx = world[0] - prev[0];\n const dy = world[1] - prev[1];\n if (dx * dx + dy * dy >= minWorldStep2) {\n session.points.push(world);\n } else {\n session.points[session.points.length - 1] = world;\n }\n session.current = world;\n },\n [projectorRef]\n );\n\n const handlePointerDown = useCallback(\n (event: ReactPointerEvent<HTMLCanvasElement>) => {\n if (!active) return;\n if (tool === \"cursor\") return;\n if (event.button !== 0) return;\n\n const world = toWorld(event);\n if (!world) return;\n\n event.preventDefault();\n event.stopPropagation();\n\n if (isStampTool(tool)) {\n const session = sessionRef.current;\n session.stampCenter = world;\n handleStampAt(tool, world);\n requestDraw();\n return;\n }\n\n const canvas = canvasRef.current;\n if (canvas) {\n canvas.setPointerCapture(event.pointerId);\n }\n\n const session = sessionRef.current;\n session.isDrawing = true;\n session.pointerId = event.pointerId;\n session.start = world;\n session.current = world;\n session.cursor = world;\n session.points = tool === \"freehand\" || tool === \"brush\" ? [world] : [];\n requestDraw();\n },\n [active, tool, toWorld, handleStampAt, requestDraw]\n );\n\n const handlePointerMove = useCallback(\n (event: ReactPointerEvent<HTMLCanvasElement>) => {\n if (!active) return;\n if (tool === \"cursor\") return;\n\n const world = toWorld(event);\n if (!world) return;\n\n if (isStampTool(tool)) {\n const session = sessionRef.current;\n session.stampCenter = world;\n event.preventDefault();\n event.stopPropagation();\n requestDraw();\n return;\n }\n\n const session = sessionRef.current;\n if (tool === \"brush\") {\n session.cursor = world;\n if (!session.isDrawing || session.pointerId !== event.pointerId) {\n requestDraw();\n return;\n }\n event.preventDefault();\n event.stopPropagation();\n appendBrushPoint(session, world);\n requestDraw();\n return;\n }\n\n if (!session.isDrawing || session.pointerId !== event.pointerId) {\n return;\n }\n event.preventDefault();\n event.stopPropagation();\n\n if (tool === \"freehand\") {\n const projector = projectorRef.current;\n const zoom = Math.max(1e-6, projector?.getViewState?.().zoom ?? 1);\n const minWorldStep = FREEHAND_SCREEN_STEP / zoom;\n const minWorldStep2 = minWorldStep * minWorldStep;\n const prev = session.points[session.points.length - 1];\n\n if (!prev) {\n session.points.push(world);\n } else {\n const dx = world[0] - prev[0];\n const dy = world[1] - prev[1];\n if (dx * dx + dy * dy >= minWorldStep2) {\n session.points.push(world);\n }\n }\n } else {\n session.current = world;\n }\n\n requestDraw();\n },\n [active, tool, toWorld, requestDraw, projectorRef, appendBrushPoint]\n );\n\n const handlePointerUp = useCallback(\n (event: ReactPointerEvent<HTMLCanvasElement>) => {\n const session = sessionRef.current;\n if (!session.isDrawing || session.pointerId !== event.pointerId) return;\n\n event.preventDefault();\n event.stopPropagation();\n const world = toWorld(event);\n if (world) {\n session.cursor = world;\n if (tool === \"brush\") {\n appendBrushPoint(session, world);\n } else {\n session.current = world;\n }\n }\n const canvas = canvasRef.current;\n if (canvas && canvas.hasPointerCapture(event.pointerId)) {\n try {\n canvas.releasePointerCapture(event.pointerId);\n } catch {\n // noop\n }\n }\n\n finishSession();\n },\n [finishSession, toWorld, tool, appendBrushPoint]\n );\n\n const handlePointerLeave = useCallback(() => {\n const session = sessionRef.current;\n let changed = false;\n if (tool === \"brush\" && !session.isDrawing && session.cursor) {\n session.cursor = null;\n changed = true;\n }\n if (isStampTool(tool) && session.stampCenter) {\n session.stampCenter = null;\n changed = true;\n }\n if (changed) {\n requestDraw();\n }\n }, [tool, requestDraw]);\n\n useEffect(() => {\n resizeCanvas();\n requestDraw();\n\n const canvas = canvasRef.current;\n if (!canvas) return undefined;\n\n const observer = new ResizeObserver(() => {\n resizeCanvas();\n requestDraw();\n });\n observer.observe(canvas);\n\n return () => {\n observer.disconnect();\n };\n }, [resizeCanvas, requestDraw]);\n\n useEffect(() => {\n if (!active) {\n resetSession();\n }\n requestDraw();\n }, [active, requestDraw, resetSession]);\n\n useEffect(() => {\n if (lastToolRef.current === tool) {\n return;\n }\n lastToolRef.current = tool;\n resetSession();\n requestDraw();\n }, [tool, resetSession, requestDraw]);\n\n useEffect(() => {\n requestDraw();\n }, [viewStateSignal, mergedPersistedRegions, overlayShapes, requestDraw]);\n\n useEffect(() => {\n if (!invalidateRef) return undefined;\n invalidateRef.current = requestDraw;\n return () => {\n if (invalidateRef.current === requestDraw) {\n invalidateRef.current = null;\n }\n };\n }, [invalidateRef, requestDraw]);\n\n useEffect(() => {\n if (!active) return undefined;\n\n const onKeyDown = (event: KeyboardEvent): void => {\n if (event.key !== \"Escape\") return;\n resetSession();\n requestDraw();\n };\n\n window.addEventListener(\"keydown\", onKeyDown);\n return () => {\n window.removeEventListener(\"keydown\", onKeyDown);\n };\n }, [active, resetSession, requestDraw]);\n\n return (\n <canvas\n ref={canvasRef}\n className={className}\n style={mergedStyle}\n onPointerDown={handlePointerDown}\n onPointerMove={handlePointerMove}\n onPointerUp={handlePointerUp}\n onPointerCancel={handlePointerUp}\n onPointerLeave={handlePointerLeave}\n onContextMenu={event => {\n if (active) event.preventDefault();\n }}\n onWheel={event => {\n if (!active) return;\n const canvas = canvasRef.current;\n const projector = projectorRef.current;\n if (!canvas || typeof projector?.zoomBy !== \"function\") return;\n event.preventDefault();\n event.stopPropagation();\n const rect = canvas.getBoundingClientRect();\n const screenX = event.clientX - rect.left;\n const screenY = event.clientY - rect.top;\n projector.zoomBy(event.deltaY < 0 ? WHEEL_ZOOM_IN_FACTOR : WHEEL_ZOOM_OUT_FACTOR, screenX, screenY);\n requestDraw();\n }}\n />\n );\n}\n","import type { WsiImageSource, WsiTerm } from \"./types\";\n\nfunction trimTrailingSlash(value: string): string {\n return String(value ?? \"\").replace(/\\/+$/, \"\");\n}\n\nfunction ensureLeadingSlash(value: string): string {\n const raw = String(value ?? \"\");\n return raw.startsWith(\"/\") ? raw : `/${raw}`;\n}\n\nfunction joinImsTileRoot(tileBaseUrl: string): string {\n const base = trimTrailingSlash(tileBaseUrl);\n if (!base) return \"\";\n\n // Explicit TileGroup path already provided.\n if (/\\/TileGroup\\d+$/i.test(base)) return base;\n\n let parsed: URL | null = null;\n try {\n parsed = new URL(base);\n } catch {\n parsed = null;\n }\n\n if (parsed) {\n const origin = `${parsed.protocol}//${parsed.host}`;\n const path = trimTrailingSlash(parsed.pathname || \"\");\n\n // If caller passes /ims, keep /ims and append image path directly:\n // /ims + /tiles/<hash> + /tier/y_x.webp\n if (/\\/ims$/i.test(path)) return `${origin}${path}`;\n if (/\\/tiles$/i.test(path)) return `${origin}${path}`;\n return `${origin}${path}/tiles`;\n }\n\n // Relative path mode\n if (/\\/ims$/i.test(base)) return `/ims`;\n if (/\\/tiles$/i.test(base)) return `${base}`;\n return `${base}/tiles`;\n}\n\nexport function normalizeImageInfo(raw: any, tileBaseUrl: string): WsiImageSource {\n const ims = raw?.imsInfo || {};\n const isIms = !!raw?.imsInfo;\n\n const width = Number(ims.width ?? raw?.width ?? 0);\n const height = Number(ims.height ?? raw?.height ?? 0);\n const tileSize = Number(ims.tileSize ?? raw?.tileSize ?? 0);\n const maxTierZoom = Number(ims.zoom ?? raw?.zoom ?? 0);\n const tilePath = String(ims.path ?? raw?.path ?? \"\");\n const mpp = Number(ims.mpp ?? raw?.mpp ?? 0);\n\n if (!width || !height || !tileSize || !tilePath) {\n throw new Error(\"이미지 메타데이터가 불완전합니다. width/height/tileSize/path 확인 필요\");\n }\n\n const terms: WsiTerm[] = Array.isArray(raw?.terms)\n ? raw.terms.map((term: any) => ({\n termId: String(term?.termId ?? \"\"),\n termName: String(term?.termName ?? \"\"),\n termColor: String(term?.termColor ?? \"\"),\n }))\n : [];\n\n const normalizedPath = ensureLeadingSlash(tilePath);\n const imsTileRoot = joinImsTileRoot(tileBaseUrl);\n const tileUrlBuilder = isIms ? (tier: number, x: number, y: number): string => `${imsTileRoot}${normalizedPath}/${tier}/${y}_${x}.webp` : undefined;\n\n return {\n id: raw?._id || \"unknown\",\n name: raw?.name || \"unknown\",\n width,\n height,\n mpp: Number.isFinite(mpp) && mpp > 0 ? mpp : undefined,\n tileSize,\n maxTierZoom: Number.isFinite(maxTierZoom) ? Math.max(0, Math.floor(maxTierZoom)) : 0,\n tilePath,\n tileBaseUrl,\n terms,\n tileUrlBuilder,\n };\n}\n\nexport function toTileUrl(source: Pick<WsiImageSource, \"tilePath\" | \"tileBaseUrl\" | \"tileUrlBuilder\">, tier: number, x: number, y: number): string {\n if (source.tileUrlBuilder) {\n return source.tileUrlBuilder(tier, x, y);\n }\n const normalizedPath = ensureLeadingSlash(source.tilePath);\n return `${source.tileBaseUrl}${normalizedPath}/${tier}/${y}_${x}.webp`;\n}\n","import {\n\ttype CSSProperties,\n\ttype MutableRefObject,\n\ttype PointerEvent as ReactPointerEvent,\n\ttype RefObject,\n\tuseCallback,\n\tuseEffect,\n\tuseMemo,\n\tuseRef,\n} from \"react\";\nimport { toTileUrl } from \"../wsi/image-info\";\nimport type { WsiImageSource, WsiViewState } from \"../wsi/types\";\nimport { clamp } from \"../wsi/utils\";\n\ntype Bounds = [number, number, number, number];\n\nexport interface OverviewMapProjector {\n\tgetViewState: () => WsiViewState;\n\tsetViewState: (next: Partial<WsiViewState>) => void;\n\tsetViewCenter?: (worldX: number, worldY: number) => void;\n\tgetViewBounds?: () => number[];\n\tgetViewCorners?: () => Array<[number, number]>;\n}\n\nexport type OverviewMapPosition =\n\t| \"bottom-right\"\n\t| \"bottom-left\"\n\t| \"top-right\"\n\t| \"top-left\";\n\nexport interface OverviewMapOptions {\n\twidth: number;\n\theight: number;\n\tmargin: number;\n\tposition: OverviewMapPosition;\n\tborderRadius: number;\n\tborderWidth: number;\n\tbackgroundColor: string;\n\tborderColor: string;\n\tviewportStrokeColor: string;\n\tviewportFillColor: string;\n\tinteractive: boolean;\n\tshowThumbnail: boolean;\n\tmaxThumbnailTiles: number;\n}\n\nexport interface OverviewMapProps {\n\tsource: WsiImageSource;\n\tprojectorRef: RefObject<OverviewMapProjector | null>;\n\tauthToken?: string;\n\toptions?: Partial<OverviewMapOptions>;\n\tinvalidateRef?: MutableRefObject<(() => void) | null>;\n\tclassName?: string;\n\tstyle?: CSSProperties;\n}\n\nconst DEFAULT_OVERVIEW_MAP_OPTIONS: OverviewMapOptions = {\n\twidth: 220,\n\theight: 140,\n\tmargin: 16,\n\tposition: \"bottom-right\",\n\tborderRadius: 10,\n\tborderWidth: 1.5,\n\tbackgroundColor: \"rgba(4, 10, 18, 0.88)\",\n\tborderColor: \"rgba(230, 244, 255, 0.35)\",\n\tviewportStrokeColor: \"rgba(255, 106, 61, 0.95)\",\n\tviewportFillColor: \"rgba(255, 106, 61, 0.2)\",\n\tinteractive: true,\n\tshowThumbnail: true,\n\tmaxThumbnailTiles: 16,\n};\n\nfunction toPositiveNumber(\n\tvalue: number | undefined,\n\tfallback: number,\n\tmin = 1,\n): number {\n\tif (typeof value !== \"number\" || !Number.isFinite(value)) return fallback;\n\treturn Math.max(min, value);\n}\n\nfunction isFiniteBounds(bounds: number[] | null | undefined): bounds is Bounds {\n\treturn (\n\t\tArray.isArray(bounds) &&\n\t\tbounds.length === 4 &&\n\t\tNumber.isFinite(bounds[0]) &&\n\t\tNumber.isFinite(bounds[1]) &&\n\t\tNumber.isFinite(bounds[2]) &&\n\t\tNumber.isFinite(bounds[3])\n\t);\n}\n\nexport function OverviewMap({\n\tsource,\n\tprojectorRef,\n\tauthToken = \"\",\n\toptions,\n\tinvalidateRef,\n\tclassName,\n\tstyle,\n}: OverviewMapProps): React.ReactElement {\n\tconst canvasRef = useRef<HTMLCanvasElement | null>(null);\n\tconst thumbnailRef = useRef<HTMLCanvasElement | null>(null);\n\tconst lastBoundsRef = useRef<Bounds | null>(null);\n\tconst draggingRef = useRef<{ active: boolean; pointerId: number | null }>({\n\t\tactive: false,\n\t\tpointerId: null,\n\t});\n\tconst rafRef = useRef<number | null>(null);\n\tconst drawPendingRef = useRef(false);\n\n\tconst width = toPositiveNumber(\n\t\toptions?.width,\n\t\tDEFAULT_OVERVIEW_MAP_OPTIONS.width,\n\t\t64,\n\t);\n\tconst height = toPositiveNumber(\n\t\toptions?.height,\n\t\tDEFAULT_OVERVIEW_MAP_OPTIONS.height,\n\t\t48,\n\t);\n\tconst margin = toPositiveNumber(\n\t\toptions?.margin,\n\t\tDEFAULT_OVERVIEW_MAP_OPTIONS.margin,\n\t\t0,\n\t);\n\tconst borderRadius = toPositiveNumber(\n\t\toptions?.borderRadius,\n\t\tDEFAULT_OVERVIEW_MAP_OPTIONS.borderRadius,\n\t\t0,\n\t);\n\tconst borderWidth = toPositiveNumber(\n\t\toptions?.borderWidth,\n\t\tDEFAULT_OVERVIEW_MAP_OPTIONS.borderWidth,\n\t\t0,\n\t);\n\tconst maxThumbnailTiles = Math.max(\n\t\t1,\n\t\tMath.round(\n\t\t\ttoPositiveNumber(\n\t\t\t\toptions?.maxThumbnailTiles,\n\t\t\t\tDEFAULT_OVERVIEW_MAP_OPTIONS.maxThumbnailTiles,\n\t\t\t\t1,\n\t\t\t),\n\t\t),\n\t);\n\n\tconst backgroundColor =\n\t\toptions?.backgroundColor || DEFAULT_OVERVIEW_MAP_OPTIONS.backgroundColor;\n\tconst borderColor =\n\t\toptions?.borderColor || DEFAULT_OVERVIEW_MAP_OPTIONS.borderColor;\n\tconst viewportStrokeColor =\n\t\toptions?.viewportStrokeColor ||\n\t\tDEFAULT_OVERVIEW_MAP_OPTIONS.viewportStrokeColor;\n\tconst viewportFillColor =\n\t\toptions?.viewportFillColor ||\n\t\tDEFAULT_OVERVIEW_MAP_OPTIONS.viewportFillColor;\n\tconst interactive =\n\t\toptions?.interactive ?? DEFAULT_OVERVIEW_MAP_OPTIONS.interactive;\n\tconst showThumbnail =\n\t\toptions?.showThumbnail ?? DEFAULT_OVERVIEW_MAP_OPTIONS.showThumbnail;\n\tconst position =\n\t\toptions?.position || DEFAULT_OVERVIEW_MAP_OPTIONS.position;\n\n\tconst mergedStyle = useMemo<CSSProperties>(() => {\n\t\tconst pos: CSSProperties = {};\n\t\tif (position === \"top-left\" || position === \"bottom-left\") pos.left = margin;\n\t\telse pos.right = margin;\n\t\tif (position === \"top-left\" || position === \"top-right\") pos.top = margin;\n\t\telse pos.bottom = margin;\n\n\t\treturn {\n\t\t\tposition: \"absolute\",\n\t\t\t...pos,\n\t\t\twidth,\n\t\t\theight,\n\t\t\tborderRadius,\n\t\t\toverflow: \"hidden\",\n\t\t\tzIndex: 4,\n\t\t\tpointerEvents: interactive ? \"auto\" : \"none\",\n\t\t\ttouchAction: \"none\",\n\t\t\tboxShadow: \"0 10px 22px rgba(0, 0, 0, 0.3)\",\n\t\t\t...style,\n\t\t};\n\t}, [margin, position, width, height, borderRadius, interactive, style]);\n\n\tconst draw = useCallback(() => {\n\t\tconst canvas = canvasRef.current;\n\t\tif (!canvas) return;\n\n\t\tconst ctx = canvas.getContext(\"2d\");\n\t\tif (!ctx) return;\n\n\t\tconst cssW = width;\n\t\tconst cssH = height;\n\t\tconst dpr = Math.max(1, window.devicePixelRatio || 1);\n\n\t\tconst pixelW = Math.max(1, Math.round(cssW * dpr));\n\t\tconst pixelH = Math.max(1, Math.round(cssH * dpr));\n\t\tif (canvas.width !== pixelW || canvas.height !== pixelH) {\n\t\t\tcanvas.width = pixelW;\n\t\t\tcanvas.height = pixelH;\n\t\t}\n\n\t\tctx.setTransform(1, 0, 0, 1, 0, 0);\n\t\tctx.clearRect(0, 0, canvas.width, canvas.height);\n\t\tctx.setTransform(dpr, 0, 0, dpr, 0, 0);\n\n\t\tctx.fillStyle = backgroundColor;\n\t\tctx.fillRect(0, 0, cssW, cssH);\n\n\t\tconst preview = thumbnailRef.current;\n\t\tif (preview) {\n\t\t\tctx.drawImage(preview, 0, 0, cssW, cssH);\n\t\t}\n\n\t\tctx.strokeStyle = borderColor;\n\t\tctx.lineWidth = borderWidth;\n\t\tctx.strokeRect(\n\t\t\tborderWidth * 0.5,\n\t\t\tborderWidth * 0.5,\n\t\t\tcssW - borderWidth,\n\t\t\tcssH - borderWidth,\n\t\t);\n\n\t\tconst projector = projectorRef.current;\n\t\tconst bounds = projector?.getViewBounds?.();\n\t\tconst corners = projector?.getViewCorners?.();\n\t\tconst safeBounds = isFiniteBounds(bounds)\n\t\t\t? bounds\n\t\t\t: isFiniteBounds(lastBoundsRef.current)\n\t\t\t\t? lastBoundsRef.current\n\t\t\t\t: null;\n\t\tif (!safeBounds) return;\n\t\tlastBoundsRef.current = safeBounds;\n\n\t\tconst sx = cssW / Math.max(1, source.width);\n\t\tconst sy = cssH / Math.max(1, source.height);\n\n\t\tconst safeCorners =\n\t\t\tArray.isArray(corners) &&\n\t\t\tcorners.length >= 4 &&\n\t\t\tcorners.every(\n\t\t\t\t(point) =>\n\t\t\t\t\tArray.isArray(point) &&\n\t\t\t\t\tpoint.length >= 2 &&\n\t\t\t\t\tNumber.isFinite(point[0]) &&\n\t\t\t\t\tNumber.isFinite(point[1]),\n\t\t\t)\n\t\t\t\t? (corners as Array<[number, number]>)\n\t\t\t\t: null;\n\n\t\tif (safeCorners) {\n\t\t\tctx.beginPath();\n\t\t\tfor (let i = 0; i < safeCorners.length; i += 1) {\n\t\t\t\tconst point = safeCorners[i];\n\t\t\t\tconst x = clamp(point[0] * sx, 0, cssW);\n\t\t\t\tconst y = clamp(point[1] * sy, 0, cssH);\n\t\t\t\tif (i === 0) ctx.moveTo(x, y);\n\t\t\t\telse ctx.lineTo(x, y);\n\t\t\t}\n\t\t\tctx.closePath();\n\t\t\tctx.fillStyle = viewportFillColor;\n\t\t\tctx.fill();\n\t\t\tctx.strokeStyle = viewportStrokeColor;\n\t\t\tctx.lineWidth = 1.5;\n\t\t\tctx.stroke();\n\t\t\treturn;\n\t\t}\n\n\t\tconst left = clamp(safeBounds[0] * sx, 0, cssW);\n\t\tconst top = clamp(safeBounds[1] * sy, 0, cssH);\n\t\tconst right = clamp(safeBounds[2] * sx, 0, cssW);\n\t\tconst bottom = clamp(safeBounds[3] * sy, 0, cssH);\n\t\tconst rectW = Math.max(1, right - left);\n\t\tconst rectH = Math.max(1, bottom - top);\n\n\t\tctx.fillStyle = viewportFillColor;\n\t\tctx.fillRect(left, top, rectW, rectH);\n\n\t\tctx.strokeStyle = viewportStrokeColor;\n\t\tctx.lineWidth = 1.5;\n\t\tctx.strokeRect(\n\t\t\tleft + 0.5,\n\t\t\ttop + 0.5,\n\t\t\tMath.max(1, rectW - 1),\n\t\t\tMath.max(1, rectH - 1),\n\t\t);\n\t}, [\n\t\twidth,\n\t\theight,\n\t\tbackgroundColor,\n\t\tborderColor,\n\t\tborderWidth,\n\t\tprojectorRef,\n\t\tsource.width,\n\t\tsource.height,\n\t\tviewportFillColor,\n\t\tviewportStrokeColor,\n\t]);\n\n\tconst requestDraw = useCallback(() => {\n\t\tif (drawPendingRef.current) return;\n\t\tdrawPendingRef.current = true;\n\t\trafRef.current = requestAnimationFrame(() => {\n\t\t\tdrawPendingRef.current = false;\n\t\t\trafRef.current = null;\n\t\t\tdraw();\n\t\t});\n\t}, [draw]);\n\n\tconst toWorldFromClient = useCallback(\n\t\t(clientX: number, clientY: number): [number, number] | null => {\n\t\t\tconst canvas = canvasRef.current;\n\t\t\tif (!canvas) return null;\n\n\t\t\tconst rect = canvas.getBoundingClientRect();\n\t\t\tif (!rect.width || !rect.height) return null;\n\n\t\t\tconst nx = clamp((clientX - rect.left) / rect.width, 0, 1);\n\t\t\tconst ny = clamp((clientY - rect.top) / rect.height, 0, 1);\n\t\t\treturn [nx * source.width, ny * source.height];\n\t\t},\n\t\t[source.width, source.height],\n\t);\n\n\tconst recenterTo = useCallback(\n\t\t(worldX: number, worldY: number) => {\n\t\t\tconst projector = projectorRef.current;\n\t\t\tif (!projector) return;\n\n\t\t\tif (projector.setViewCenter) {\n\t\t\t\tprojector.setViewCenter(worldX, worldY);\n\t\t\t\trequestDraw();\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst bounds = projector.getViewBounds?.();\n\t\t\tconst safeBounds = isFiniteBounds(bounds)\n\t\t\t\t? bounds\n\t\t\t\t: isFiniteBounds(lastBoundsRef.current)\n\t\t\t\t\t? lastBoundsRef.current\n\t\t\t\t\t: null;\n\t\t\tif (!safeBounds) return;\n\n\t\t\tconst visibleW = Math.max(1e-6, safeBounds[2] - safeBounds[0]);\n\t\t\tconst visibleH = Math.max(1e-6, safeBounds[3] - safeBounds[1]);\n\n\t\t\tprojector.setViewState({\n\t\t\t\toffsetX: worldX - visibleW * 0.5,\n\t\t\t\toffsetY: worldY - visibleH * 0.5,\n\t\t\t});\n\t\t\trequestDraw();\n\t\t},\n\t\t[projectorRef, requestDraw],\n\t);\n\n\tconst handlePointerDown = useCallback(\n\t\t(event: ReactPointerEvent<HTMLCanvasElement>) => {\n\t\t\tif (!interactive) return;\n\t\t\tif (event.button !== 0) return;\n\n\t\t\tconst canvas = canvasRef.current;\n\t\t\tif (!canvas) return;\n\n\t\t\tconst world = toWorldFromClient(event.clientX, event.clientY);\n\t\t\tif (!world) return;\n\n\t\t\tevent.preventDefault();\n\t\t\tevent.stopPropagation();\n\n\t\t\tcanvas.setPointerCapture(event.pointerId);\n\t\t\tdraggingRef.current = { active: true, pointerId: event.pointerId };\n\t\t\trecenterTo(world[0], world[1]);\n\t\t},\n\t\t[interactive, toWorldFromClient, recenterTo],\n\t);\n\n\tconst handlePointerMove = useCallback(\n\t\t(event: ReactPointerEvent<HTMLCanvasElement>) => {\n\t\t\tconst drag = draggingRef.current;\n\t\t\tif (!drag.active || drag.pointerId !== event.pointerId) return;\n\n\t\t\tconst world = toWorldFromClient(event.clientX, event.clientY);\n\t\t\tif (!world) return;\n\n\t\t\tevent.preventDefault();\n\t\t\tevent.stopPropagation();\n\t\t\trecenterTo(world[0], world[1]);\n\t\t},\n\t\t[toWorldFromClient, recenterTo],\n\t);\n\n\tconst handlePointerUp = useCallback(\n\t\t(event: ReactPointerEvent<HTMLCanvasElement>) => {\n\t\t\tconst drag = draggingRef.current;\n\t\t\tif (!drag.active || drag.pointerId !== event.pointerId) return;\n\n\t\t\tconst canvas = canvasRef.current;\n\t\t\tif (canvas && canvas.hasPointerCapture(event.pointerId)) {\n\t\t\t\ttry {\n\t\t\t\t\tcanvas.releasePointerCapture(event.pointerId);\n\t\t\t\t} catch {\n\t\t\t\t\t// noop\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tdraggingRef.current = { active: false, pointerId: null };\n\t\t\trequestDraw();\n\t\t},\n\t\t[requestDraw],\n\t);\n\n\tuseEffect(() => {\n\t\tlet cancelled = false;\n\t\tthumbnailRef.current = null;\n\t\trequestDraw();\n\n\t\tconst tier = 0;\n\t\tconst levelScale = 2 ** (source.maxTierZoom - tier);\n\t\tconst levelWidth = Math.ceil(source.width / levelScale);\n\t\tconst levelHeight = Math.ceil(source.height / levelScale);\n\t\tconst tilesX = Math.max(1, Math.ceil(levelWidth / source.tileSize));\n\t\tconst tilesY = Math.max(1, Math.ceil(levelHeight / source.tileSize));\n\t\tconst tileCount = tilesX * tilesY;\n\n\t\tif (!showThumbnail || tileCount > maxThumbnailTiles) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tconst preview = document.createElement(\"canvas\");\n\t\tpreview.width = Math.max(1, Math.round(width));\n\t\tpreview.height = Math.max(1, Math.round(height));\n\t\tconst ctx = preview.getContext(\"2d\");\n\t\tif (!ctx) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tctx.fillStyle = backgroundColor;\n\t\tctx.fillRect(0, 0, preview.width, preview.height);\n\n\t\tconst requests: Array<{\n\t\t\turl: string;\n\t\t\tbounds: Bounds;\n\t\t}> = [];\n\n\t\tfor (let y = 0; y < tilesY; y += 1) {\n\t\t\tfor (let x = 0; x < tilesX; x += 1) {\n\t\t\t\tconst left = x * source.tileSize * levelScale;\n\t\t\t\tconst top = y * source.tileSize * levelScale;\n\t\t\t\tconst right =\n\t\t\t\t\tMath.min((x + 1) * source.tileSize, levelWidth) * levelScale;\n\t\t\t\tconst bottom =\n\t\t\t\t\tMath.min((y + 1) * source.tileSize, levelHeight) * levelScale;\n\t\t\t\trequests.push({\n\t\t\t\t\turl: toTileUrl(source, tier, x, y),\n\t\t\t\t\tbounds: [left, top, right, bottom],\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\tvoid Promise.allSettled(\n\t\t\trequests.map(async (tile) => {\n\t\t\t\tconst useAuthHeader = !!authToken;\n\t\t\t\tconst response = await fetch(tile.url, {\n\t\t\t\t\theaders: useAuthHeader ? { Authorization: authToken } : undefined,\n\t\t\t\t});\n\t\t\t\tif (!response.ok) {\n\t\t\t\t\tthrow new Error(`HTTP ${response.status}`);\n\t\t\t\t}\n\t\t\t\tconst bitmap = await createImageBitmap(await response.blob());\n\t\t\t\treturn { tile, bitmap };\n\t\t\t}),\n\t\t).then((results) => {\n\t\t\tif (cancelled) {\n\t\t\t\tfor (const result of results) {\n\t\t\t\t\tif (result.status === \"fulfilled\") {\n\t\t\t\t\t\tresult.value.bitmap.close();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst sx = preview.width / Math.max(1, source.width);\n\t\t\tconst sy = preview.height / Math.max(1, source.height);\n\t\t\tfor (const result of results) {\n\t\t\t\tif (result.status !== \"fulfilled\") continue;\n\t\t\t\tconst {\n\t\t\t\t\ttile: { bounds },\n\t\t\t\t\tbitmap,\n\t\t\t\t} = result.value;\n\t\t\t\tconst dx = bounds[0] * sx;\n\t\t\t\tconst dy = bounds[1] * sy;\n\t\t\t\tconst dw = Math.max(1, (bounds[2] - bounds[0]) * sx);\n\t\t\t\tconst dh = Math.max(1, (bounds[3] - bounds[1]) * sy);\n\t\t\t\tctx.drawImage(bitmap, dx, dy, dw, dh);\n\t\t\t\tbitmap.close();\n\t\t\t}\n\n\t\t\tthumbnailRef.current = preview;\n\t\t\trequestDraw();\n\t\t});\n\n\t\treturn () => {\n\t\t\tcancelled = true;\n\t\t};\n\t}, [\n\t\tsource,\n\t\tauthToken,\n\t\twidth,\n\t\theight,\n\t\tbackgroundColor,\n\t\tshowThumbnail,\n\t\tmaxThumbnailTiles,\n\t\trequestDraw,\n\t]);\n\n\tuseEffect(() => {\n\t\trequestDraw();\n\t}, [requestDraw]);\n\n\tuseEffect(() => {\n\t\tif (!invalidateRef) return undefined;\n\t\tinvalidateRef.current = requestDraw;\n\t\treturn () => {\n\t\t\tif (invalidateRef.current === requestDraw) {\n\t\t\t\tinvalidateRef.current = null;\n\t\t\t}\n\t\t};\n\t}, [invalidateRef, requestDraw]);\n\n\tuseEffect(\n\t\t() => () => {\n\t\t\tdraggingRef.current = { active: false, pointerId: null };\n\t\t\tif (rafRef.current !== null) {\n\t\t\t\tcancelAnimationFrame(rafRef.current);\n\t\t\t\trafRef.current = null;\n\t\t\t}\n\t\t\tdrawPendingRef.current = false;\n\t\t},\n\t\t[],\n\t);\n\n\treturn (\n\t\t<canvas\n\t\t\tref={canvasRef}\n\t\t\tclassName={className}\n\t\t\tstyle={mergedStyle}\n\t\t\tonPointerDown={handlePointerDown}\n\t\t\tonPointerMove={handlePointerMove}\n\t\t\tonPointerUp={handlePointerUp}\n\t\t\tonPointerCancel={handlePointerUp}\n\t\t\tonContextMenu={(event) => {\n\t\t\t\tevent.preventDefault();\n\t\t\t}}\n\t\t\tonWheel={(event) => {\n\t\t\t\tevent.preventDefault();\n\t\t\t\tevent.stopPropagation();\n\t\t\t}}\n\t\t/>\n\t);\n}\n","import { type CSSProperties, useEffect, useMemo, useRef } from \"react\";\nimport { M1TileRenderer } from \"../core/m1-tile-renderer\";\nimport type { ViewState } from \"../core/ortho-camera\";\nimport type { TileDefinition } from \"../core/types\";\n\nexport interface TileViewerCanvasProps {\n\timageWidth: number;\n\timageHeight: number;\n\ttiles: TileDefinition[];\n\tviewState?: Partial<ViewState>;\n\tclassName?: string;\n\tstyle?: CSSProperties;\n}\n\nexport function TileViewerCanvas({\n\timageWidth,\n\timageHeight,\n\ttiles,\n\tviewState,\n\tclassName,\n\tstyle,\n}: TileViewerCanvasProps): React.ReactElement {\n\tconst canvasRef = useRef<HTMLCanvasElement | null>(null);\n\tconst rendererRef = useRef<M1TileRenderer | null>(null);\n\tconst mergedStyle = useMemo(\n\t\t() => ({ width: \"100%\", height: \"100%\", display: \"block\", ...style }),\n\t\t[style],\n\t);\n\n\tuseEffect(() => {\n\t\tconst canvas = canvasRef.current;\n\t\tif (!canvas) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst renderer = new M1TileRenderer({\n\t\t\tcanvas,\n\t\t\timageWidth,\n\t\t\timageHeight,\n\t\t\tinitialViewState: viewState,\n\t\t});\n\n\t\trendererRef.current = renderer;\n\t\tvoid renderer.setTiles(tiles);\n\n\t\treturn () => {\n\t\t\trenderer.destroy();\n\t\t\trendererRef.current = null;\n\t\t};\n\t}, [imageWidth, imageHeight]);\n\n\tuseEffect(() => {\n\t\tconst renderer = rendererRef.current;\n\t\tif (!renderer) {\n\t\t\treturn;\n\t\t}\n\n\t\tvoid renderer.setTiles(tiles);\n\t}, [tiles]);\n\n\tuseEffect(() => {\n\t\tconst renderer = rendererRef.current;\n\t\tif (!renderer || !viewState) {\n\t\t\treturn;\n\t\t}\n\n\t\trenderer.setViewState(viewState);\n\t}, [viewState]);\n\n\treturn <canvas ref={canvasRef} className={className} style={mergedStyle} />;\n}\n","import type { WsiPointData } from \"./types\";\n\nexport type RoiCoordinate = [number, number];\nexport type RoiPolygon = RoiCoordinate[];\n\ninterface PreparedPolygon {\n\tring: RoiPolygon;\n\tminX: number;\n\tminY: number;\n\tmaxX: number;\n\tmaxY: number;\n}\n\nfunction sanitizePointCount(pointData: WsiPointData): number {\n\treturn Math.max(\n\t\t0,\n\t\tMath.min(\n\t\t\tMath.floor(pointData.count ?? 0),\n\t\t\tMath.floor((pointData.positions?.length ?? 0) / 2),\n\t\t\tpointData.paletteIndices?.length ?? 0,\n\t\t),\n\t);\n}\n\nfunction closeRing(coords: RoiPolygon): RoiPolygon {\n\tif (!Array.isArray(coords) || coords.length < 3) return [];\n\tconst out = coords.map(([x, y]) => [x, y] as RoiCoordinate);\n\tconst first = out[0];\n\tconst last = out[out.length - 1];\n\tif (!first || !last) return [];\n\tif (first[0] !== last[0] || first[1] !== last[1]) {\n\t\tout.push([first[0], first[1]]);\n\t}\n\treturn out;\n}\n\nfunction preparePolygons(polygons: RoiPolygon[]): PreparedPolygon[] {\n\tconst prepared: PreparedPolygon[] = [];\n\tfor (const poly of polygons ?? []) {\n\t\tconst ring = closeRing(poly);\n\t\tif (ring.length < 4) continue;\n\t\tlet minX = Infinity;\n\t\tlet minY = Infinity;\n\t\tlet maxX = -Infinity;\n\t\tlet maxY = -Infinity;\n\t\tfor (const [x, y] of ring) {\n\t\t\tif (x < minX) minX = x;\n\t\t\tif (x > maxX) maxX = x;\n\t\t\tif (y < minY) minY = y;\n\t\t\tif (y > maxY) maxY = y;\n\t\t}\n\t\tif (!Number.isFinite(minX) || !Number.isFinite(minY)) continue;\n\t\tprepared.push({ ring, minX, minY, maxX, maxY });\n\t}\n\treturn prepared;\n}\n\nfunction isInsideRing(x: number, y: number, ring: RoiPolygon): boolean {\n\tlet inside = false;\n\tfor (let i = 0, j = ring.length - 1; i < ring.length; j = i, i += 1) {\n\t\tconst xi = ring[i][0];\n\t\tconst yi = ring[i][1];\n\t\tconst xj = ring[j][0];\n\t\tconst yj = ring[j][1];\n\t\tconst intersect =\n\t\t\tyi > y !== yj > y &&\n\t\t\tx < ((xj - xi) * (y - yi)) / ((yj - yi) || Number.EPSILON) + xi;\n\t\tif (intersect) inside = !inside;\n\t}\n\treturn inside;\n}\n\nfunction isInsideAnyPolygon(\n\tx: number,\n\ty: number,\n\tpolygons: PreparedPolygon[],\n): boolean {\n\tfor (const poly of polygons) {\n\t\tif (x < poly.minX || x > poly.maxX || y < poly.minY || y > poly.maxY) {\n\t\t\tcontinue;\n\t\t}\n\t\tif (isInsideRing(x, y, poly.ring)) {\n\t\t\treturn true;\n\t\t}\n\t}\n\treturn false;\n}\n\nexport function filterPointDataByPolygons(\n\tpointData: WsiPointData | null | undefined,\n\tpolygons: RoiPolygon[] | null | undefined,\n): WsiPointData | null {\n\tif (!pointData || !pointData.count || !pointData.positions || !pointData.paletteIndices) {\n\t\treturn null;\n\t}\n\n\tconst prepared = preparePolygons(polygons ?? []);\n\tif (prepared.length === 0) {\n\t\treturn {\n\t\t\tcount: 0,\n\t\t\tpositions: new Float32Array(0),\n\t\t\tpaletteIndices: new Uint16Array(0),\n\t\t};\n\t}\n\n\tconst count = sanitizePointCount(pointData);\n\tconst positions = pointData.positions;\n\tconst terms = pointData.paletteIndices;\n\tconst pointIds =\n\t\tpointData.ids instanceof Uint32Array && pointData.ids.length >= count\n\t\t\t? pointData.ids\n\t\t\t: null;\n\n\tconst nextPositions = new Float32Array(count * 2);\n\tconst nextTerms = new Uint16Array(count);\n\tconst nextIds = pointIds ? new Uint32Array(count) : null;\n\tlet cursor = 0;\n\n\tfor (let i = 0; i < count; i += 1) {\n\t\tconst x = positions[i * 2];\n\t\tconst y = positions[i * 2 + 1];\n\t\tif (!isInsideAnyPolygon(x, y, prepared)) continue;\n\t\tnextPositions[cursor * 2] = x;\n\t\tnextPositions[cursor * 2 + 1] = y;\n\t\tnextTerms[cursor] = terms[i];\n\t\tif (nextIds) {\n\t\t\tnextIds[cursor] = pointIds![i];\n\t\t}\n\t\tcursor += 1;\n\t}\n\n\tconst output: WsiPointData = {\n\t\tcount: cursor,\n\t\tpositions: nextPositions.subarray(0, cursor * 2),\n\t\tpaletteIndices: nextTerms.subarray(0, cursor),\n\t};\n\tif (nextIds) {\n\t\toutput.ids = nextIds.subarray(0, cursor);\n\t}\n\treturn output;\n}\n\nexport function filterPointIndicesByPolygons(\n\tpointData: WsiPointData | null | undefined,\n\tpolygons: RoiPolygon[] | null | undefined,\n): Uint32Array {\n\tif (!pointData || !pointData.count || !pointData.positions || !pointData.paletteIndices) {\n\t\treturn new Uint32Array(0);\n\t}\n\n\tconst prepared = preparePolygons(polygons ?? []);\n\tif (prepared.length === 0) {\n\t\treturn new Uint32Array(0);\n\t}\n\n\tconst count = sanitizePointCount(pointData);\n\tif (count === 0) {\n\t\treturn new Uint32Array(0);\n\t}\n\n\tconst positions = pointData.positions;\n\tconst out = new Uint32Array(count);\n\tlet cursor = 0;\n\n\tfor (let i = 0; i < count; i += 1) {\n\t\tconst x = positions[i * 2];\n\t\tconst y = positions[i * 2 + 1];\n\t\tif (!isInsideAnyPolygon(x, y, prepared)) continue;\n\t\tout[cursor] = i;\n\t\tcursor += 1;\n\t}\n\n\treturn out.subarray(0, cursor);\n}\n","export interface WebGpuCapabilities {\n\tsupported: boolean;\n\tadapterName?: string;\n\tfeatures: string[];\n\tlimits?: {\n\t\tmaxStorageBufferBindingSize: number;\n\t\tmaxComputeInvocationsPerWorkgroup: number;\n\t\tmaxComputeWorkgroupSizeX: number;\n\t};\n}\n\ninterface NavigatorGpuLike {\n\trequestAdapter: () => Promise<GpuAdapterLike | null>;\n}\n\ninterface GpuAdapterLike {\n\tinfo?: {\n\t\tdescription?: string;\n\t\tvendor?: string;\n\t};\n\tfeatures: Iterable<string>;\n\tlimits: {\n\t\tmaxStorageBufferBindingSize: number;\n\t\tmaxComputeInvocationsPerWorkgroup: number;\n\t\tmaxComputeWorkgroupSizeX: number;\n\t};\n\trequestDevice: () => Promise<GpuDeviceLike>;\n}\n\ninterface GpuBufferLike {\n\tdestroy: () => void;\n\tmapAsync: (mode: number) => Promise<void>;\n\tgetMappedRange: () => ArrayBuffer;\n\tunmap: () => void;\n}\n\ninterface GpuComputePassLike {\n\tsetPipeline: (pipeline: GpuComputePipelineLike) => void;\n\tsetBindGroup: (index: number, bindGroup: unknown) => void;\n\tdispatchWorkgroups: (x: number, y?: number, z?: number) => void;\n\tend: () => void;\n}\n\ninterface GpuCommandEncoderLike {\n\tbeginComputePass: () => GpuComputePassLike;\n\tcopyBufferToBuffer: (\n\t\tsource: GpuBufferLike,\n\t\tsourceOffset: number,\n\t\tdestination: GpuBufferLike,\n\t\tdestinationOffset: number,\n\t\tsize: number,\n\t) => void;\n\tfinish: () => unknown;\n}\n\ninterface GpuQueueLike {\n\twriteBuffer: (\n\t\tbuffer: GpuBufferLike,\n\t\tbufferOffset: number,\n\t\tdata: ArrayBufferView | ArrayBufferLike,\n\t\tdataOffset?: number,\n\t\tsize?: number,\n\t) => void;\n\tsubmit: (commands: unknown[]) => void;\n}\n\ninterface GpuComputePipelineLike {\n\treadonly _brand?: \"GpuComputePipelineLike\";\n}\n\ninterface GpuBindGroupLayoutLike {\n\treadonly _brand?: \"GpuBindGroupLayoutLike\";\n}\n\ninterface GpuDeviceLike {\n\tlimits: {\n\t\tmaxStorageBufferBindingSize: number;\n\t};\n\tqueue: GpuQueueLike;\n\tcreateBindGroupLayout: (descriptor: unknown) => GpuBindGroupLayoutLike;\n\tcreatePipelineLayout: (descriptor: unknown) => unknown;\n\tcreateShaderModule: (descriptor: { code: string }) => unknown;\n\tcreateComputePipeline: (descriptor: unknown) => GpuComputePipelineLike;\n\tcreateBuffer: (descriptor: { size: number; usage: number }) => GpuBufferLike;\n\tcreateBindGroup: (descriptor: unknown) => unknown;\n\tcreateCommandEncoder: () => GpuCommandEncoderLike;\n}\n\ninterface WebGpuContext {\n\tdevice: GpuDeviceLike;\n\tpipeline: GpuComputePipelineLike;\n\tbindGroupLayout: GpuBindGroupLayoutLike;\n}\n\nlet contextPromise: Promise<WebGpuContext | null> | null = null;\n\nconst BBOX_PREFILTER_SHADER = `\nstruct Params {\n pointCount: u32,\n boundsCount: u32,\n _pad0: u32,\n _pad1: u32,\n};\n\n@group(0) @binding(0) var<storage, read> positions: array<vec2<f32>>;\n@group(0) @binding(1) var<storage, read> bounds: array<vec4<f32>>;\n@group(0) @binding(2) var<storage, read_write> outputMask: array<u32>;\n@group(0) @binding(3) var<uniform> params: Params;\n\n@compute @workgroup_size(256)\nfn main(@builtin(global_invocation_id) gid: vec3<u32>) {\n let i = gid.x;\n if (i >= params.pointCount) {\n return;\n }\n\n let p = positions[i];\n var inside: u32 = 0u;\n for (var bi: u32 = 0u; bi < params.boundsCount; bi = bi + 1u) {\n let b = bounds[bi];\n if (p.x >= b.x && p.x <= b.z && p.y >= b.y && p.y <= b.w) {\n inside = 1u;\n break;\n }\n }\n outputMask[i] = inside;\n}\n`;\n\nfunction hasWebGpu(): boolean {\n\tif (typeof navigator === \"undefined\") return false;\n\tconst nav = navigator as Navigator & { gpu?: unknown };\n\treturn typeof nav.gpu === \"object\" && nav.gpu !== null;\n}\n\nfunction getNavigatorGpu(): NavigatorGpuLike | null {\n\tif (!hasWebGpu()) return null;\n\tconst nav = navigator as Navigator & { gpu?: unknown };\n\tconst gpu = nav.gpu;\n\tif (!gpu || typeof gpu !== \"object\") return null;\n\tconst candidate = gpu as Partial<NavigatorGpuLike>;\n\tif (typeof candidate.requestAdapter !== \"function\") return null;\n\treturn candidate as NavigatorGpuLike;\n}\n\nconst GPU_SHADER_STAGE_COMPUTE =\n\t(globalThis as { GPUShaderStage?: { COMPUTE?: number } }).GPUShaderStage\n\t\t?.COMPUTE ?? 0x4;\nconst GPU_BUFFER_USAGE_STORAGE =\n\t(globalThis as { GPUBufferUsage?: { STORAGE?: number } }).GPUBufferUsage\n\t\t?.STORAGE ?? 0x80;\nconst GPU_BUFFER_USAGE_COPY_DST =\n\t(globalThis as { GPUBufferUsage?: { COPY_DST?: number } }).GPUBufferUsage\n\t\t?.COPY_DST ?? 0x08;\nconst GPU_BUFFER_USAGE_COPY_SRC =\n\t(globalThis as { GPUBufferUsage?: { COPY_SRC?: number } }).GPUBufferUsage\n\t\t?.COPY_SRC ?? 0x04;\nconst GPU_BUFFER_USAGE_UNIFORM =\n\t(globalThis as { GPUBufferUsage?: { UNIFORM?: number } }).GPUBufferUsage\n\t\t?.UNIFORM ?? 0x40;\nconst GPU_BUFFER_USAGE_MAP_READ =\n\t(globalThis as { GPUBufferUsage?: { MAP_READ?: number } }).GPUBufferUsage\n\t\t?.MAP_READ ?? 0x01;\nconst GPU_MAP_MODE_READ =\n\t(globalThis as { GPUMapMode?: { READ?: number } }).GPUMapMode?.READ ?? 0x01;\n\nexport async function getWebGpuCapabilities(): Promise<WebGpuCapabilities> {\n\tconst navGpu = getNavigatorGpu();\n\tif (!navGpu) {\n\t\treturn { supported: false, features: [] };\n\t}\n\tconst adapter = await navGpu.requestAdapter();\n\tif (!adapter) {\n\t\treturn { supported: false, features: [] };\n\t}\n\n\treturn {\n\t\tsupported: true,\n\t\tadapterName: adapter.info?.description ?? adapter.info?.vendor ?? \"unknown\",\n\t\tfeatures: Array.from(adapter.features),\n\t\tlimits: {\n\t\t\tmaxStorageBufferBindingSize: Number(\n\t\t\t\tadapter.limits.maxStorageBufferBindingSize,\n\t\t\t),\n\t\t\tmaxComputeInvocationsPerWorkgroup: Number(\n\t\t\t\tadapter.limits.maxComputeInvocationsPerWorkgroup,\n\t\t\t),\n\t\t\tmaxComputeWorkgroupSizeX: Number(adapter.limits.maxComputeWorkgroupSizeX),\n\t\t},\n\t};\n}\n\nasync function getContext(): Promise<WebGpuContext | null> {\n\tif (contextPromise) return contextPromise;\n\tcontextPromise = (async () => {\n\t\tconst navGpu = getNavigatorGpu();\n\t\tif (!navGpu) return null;\n\t\tconst adapter = await navGpu.requestAdapter();\n\t\tif (!adapter) return null;\n\t\tconst device = await adapter.requestDevice();\n\n\t\tconst bindGroupLayout = device.createBindGroupLayout({\n\t\t\tentries: [\n\t\t\t\t{\n\t\t\t\t\tbinding: 0,\n\t\t\t\t\tvisibility: GPU_SHADER_STAGE_COMPUTE,\n\t\t\t\t\tbuffer: { type: \"read-only-storage\" },\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tbinding: 1,\n\t\t\t\t\tvisibility: GPU_SHADER_STAGE_COMPUTE,\n\t\t\t\t\tbuffer: { type: \"read-only-storage\" },\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tbinding: 2,\n\t\t\t\t\tvisibility: GPU_SHADER_STAGE_COMPUTE,\n\t\t\t\t\tbuffer: { type: \"storage\" },\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tbinding: 3,\n\t\t\t\t\tvisibility: GPU_SHADER_STAGE_COMPUTE,\n\t\t\t\t\tbuffer: { type: \"uniform\" },\n\t\t\t\t},\n\t\t\t],\n\t\t});\n\n\t\tconst pipeline = device.createComputePipeline({\n\t\t\tlayout: device.createPipelineLayout({ bindGroupLayouts: [bindGroupLayout] }),\n\t\t\tcompute: {\n\t\t\t\tmodule: device.createShaderModule({ code: BBOX_PREFILTER_SHADER }),\n\t\t\t\tentryPoint: \"main\",\n\t\t\t},\n\t\t});\n\n\t\treturn { device, pipeline, bindGroupLayout };\n\t})();\n\n\treturn contextPromise;\n}\n\nfunction align(value: number, step: number): number {\n\treturn Math.ceil(value / step) * step;\n}\n\nexport async function prefilterPointsByBoundsWebGpu(\n\tpositions: Float32Array,\n\tpointCount: number,\n\tbounds: Float32Array,\n): Promise<Uint32Array | null> {\n\tconst ctx = await getContext();\n\tif (!ctx) return null;\n\n\tconst count = Math.max(0, Math.floor(pointCount));\n\tconst boundsCount = Math.max(0, Math.floor(bounds.length / 4));\n\tif (count === 0 || boundsCount === 0) {\n\t\treturn new Uint32Array(0);\n\t}\n\n\tconst safePointCount = Math.min(count, Math.floor(positions.length / 2));\n\tif (safePointCount === 0) {\n\t\treturn new Uint32Array(0);\n\t}\n\n\tconst positionBytes = safePointCount * 2 * Float32Array.BYTES_PER_ELEMENT;\n\tconst boundsBytes = boundsCount * 4 * Float32Array.BYTES_PER_ELEMENT;\n\tconst outputBytes = safePointCount * Uint32Array.BYTES_PER_ELEMENT;\n\n\tconst limit = Number(ctx.device.limits.maxStorageBufferBindingSize);\n\tif (positionBytes > limit || boundsBytes > limit || outputBytes > limit) {\n\t\treturn null;\n\t}\n\n\tconst positionsBuffer = ctx.device.createBuffer({\n\t\tsize: align(positionBytes, 4),\n\t\tusage: GPU_BUFFER_USAGE_STORAGE | GPU_BUFFER_USAGE_COPY_DST,\n\t});\n\tconst boundsBuffer = ctx.device.createBuffer({\n\t\tsize: align(boundsBytes, 4),\n\t\tusage: GPU_BUFFER_USAGE_STORAGE | GPU_BUFFER_USAGE_COPY_DST,\n\t});\n\tconst outputBuffer = ctx.device.createBuffer({\n\t\tsize: align(outputBytes, 4),\n\t\tusage: GPU_BUFFER_USAGE_STORAGE | GPU_BUFFER_USAGE_COPY_SRC,\n\t});\n\tconst uniformBuffer = ctx.device.createBuffer({\n\t\tsize: 16,\n\t\tusage: GPU_BUFFER_USAGE_UNIFORM | GPU_BUFFER_USAGE_COPY_DST,\n\t});\n\tconst readBuffer = ctx.device.createBuffer({\n\t\tsize: align(outputBytes, 4),\n\t\tusage: GPU_BUFFER_USAGE_COPY_DST | GPU_BUFFER_USAGE_MAP_READ,\n\t});\n\n\tctx.device.queue.writeBuffer(\n\t\tpositionsBuffer,\n\t\t0,\n\t\tpositions.buffer,\n\t\tpositions.byteOffset,\n\t\tpositionBytes,\n\t);\n\tctx.device.queue.writeBuffer(\n\t\tboundsBuffer,\n\t\t0,\n\t\tbounds.buffer,\n\t\tbounds.byteOffset,\n\t\tboundsBytes,\n\t);\n\tctx.device.queue.writeBuffer(\n\t\tuniformBuffer,\n\t\t0,\n\t\tnew Uint32Array([safePointCount, boundsCount, 0, 0]),\n\t);\n\n\tconst bindGroup = ctx.device.createBindGroup({\n\t\tlayout: ctx.bindGroupLayout,\n\t\tentries: [\n\t\t\t{ binding: 0, resource: { buffer: positionsBuffer } },\n\t\t\t{ binding: 1, resource: { buffer: boundsBuffer } },\n\t\t\t{ binding: 2, resource: { buffer: outputBuffer } },\n\t\t\t{ binding: 3, resource: { buffer: uniformBuffer } },\n\t\t],\n\t});\n\n\tconst commandEncoder = ctx.device.createCommandEncoder();\n\tconst pass = commandEncoder.beginComputePass();\n\tpass.setPipeline(ctx.pipeline);\n\tpass.setBindGroup(0, bindGroup);\n\tpass.dispatchWorkgroups(Math.ceil(safePointCount / 256));\n\tpass.end();\n\n\tcommandEncoder.copyBufferToBuffer(outputBuffer, 0, readBuffer, 0, outputBytes);\n\tctx.device.queue.submit([commandEncoder.finish()]);\n\n\tawait readBuffer.mapAsync(GPU_MAP_MODE_READ);\n\tconst mapped = readBuffer.getMappedRange();\n\tconst out = new Uint32Array(mapped.slice(0));\n\treadBuffer.unmap();\n\n\tpositionsBuffer.destroy();\n\tboundsBuffer.destroy();\n\toutputBuffer.destroy();\n\tuniformBuffer.destroy();\n\treadBuffer.destroy();\n\n\treturn out;\n}\n","import { filterPointDataByPolygons, type RoiPolygon } from \"./point-clip\";\nimport type { WsiPointData } from \"./types\";\nimport { prefilterPointsByBoundsWebGpu } from \"./webgpu\";\n\ninterface PreparedPolygon {\n ring: RoiPolygon;\n minX: number;\n minY: number;\n maxX: number;\n maxY: number;\n}\n\nexport interface HybridPointClipOptions {\n bridgeToDraw?: boolean;\n}\n\nexport interface HybridPointClipResult {\n data: WsiPointData | null;\n meta: {\n mode: \"hybrid-webgpu\";\n durationMs: number;\n usedWebGpu: boolean;\n candidateCount: number;\n bridgedToDraw?: boolean;\n };\n}\n\nfunction nowMs(): number {\n if (typeof performance !== \"undefined\" && typeof performance.now === \"function\") {\n return performance.now();\n }\n return Date.now();\n}\n\nfunction closeRing(coords: RoiPolygon): RoiPolygon {\n if (!Array.isArray(coords) || coords.length < 3) return [];\n const out = coords.map(([x, y]) => [x, y] as [number, number]);\n const first = out[0];\n const last = out[out.length - 1];\n if (!first || !last) return [];\n if (first[0] !== last[0] || first[1] !== last[1]) {\n out.push([first[0], first[1]]);\n }\n return out;\n}\n\nfunction preparePolygons(polygons: RoiPolygon[]): PreparedPolygon[] {\n const prepared: PreparedPolygon[] = [];\n for (const poly of polygons ?? []) {\n const ring = closeRing(poly);\n if (ring.length < 4) continue;\n let minX = Infinity;\n let minY = Infinity;\n let maxX = -Infinity;\n let maxY = -Infinity;\n for (const [x, y] of ring) {\n if (x < minX) minX = x;\n if (x > maxX) maxX = x;\n if (y < minY) minY = y;\n if (y > maxY) maxY = y;\n }\n if (!Number.isFinite(minX) || !Number.isFinite(minY)) continue;\n prepared.push({ ring, minX, minY, maxX, maxY });\n }\n return prepared;\n}\n\nfunction isInsideRing(x: number, y: number, ring: RoiPolygon): boolean {\n let inside = false;\n for (let i = 0, j = ring.length - 1; i < ring.length; j = i, i += 1) {\n const xi = ring[i][0];\n const yi = ring[i][1];\n const xj = ring[j][0];\n const yj = ring[j][1];\n const intersect = yi > y !== yj > y && x < ((xj - xi) * (y - yi)) / (yj - yi || Number.EPSILON) + xi;\n if (intersect) inside = !inside;\n }\n return inside;\n}\n\nfunction isInsideAnyPolygon(x: number, y: number, polygons: PreparedPolygon[]): boolean {\n for (const poly of polygons) {\n if (x < poly.minX || x > poly.maxX || y < poly.minY || y > poly.maxY) {\n continue;\n }\n if (isInsideRing(x, y, poly.ring)) {\n return true;\n }\n }\n return false;\n}\n\nexport async function filterPointDataByPolygonsHybrid(\n pointData: WsiPointData | null | undefined,\n polygons: RoiPolygon[] | null | undefined,\n options: HybridPointClipOptions = {}\n): Promise<HybridPointClipResult> {\n const start = nowMs();\n const bridgeToDraw = options.bridgeToDraw === true;\n if (!pointData || !pointData.count || !pointData.positions || !pointData.paletteIndices) {\n return {\n data: null,\n meta: {\n mode: \"hybrid-webgpu\",\n durationMs: nowMs() - start,\n usedWebGpu: false,\n candidateCount: 0,\n bridgedToDraw: false,\n },\n };\n }\n\n const prepared = preparePolygons(polygons ?? []);\n if (prepared.length === 0) {\n return {\n data: {\n count: 0,\n positions: new Float32Array(0),\n paletteIndices: new Uint16Array(0),\n },\n meta: {\n mode: \"hybrid-webgpu\",\n durationMs: nowMs() - start,\n usedWebGpu: false,\n candidateCount: 0,\n bridgedToDraw: false,\n },\n };\n }\n\n const safeCount = Math.max(0, Math.min(pointData.count, Math.floor(pointData.positions.length / 2), pointData.paletteIndices.length));\n const pointIds = pointData.ids instanceof Uint32Array && pointData.ids.length >= safeCount ? pointData.ids : null;\n if (safeCount === 0) {\n return {\n data: {\n count: 0,\n positions: new Float32Array(0),\n paletteIndices: new Uint16Array(0),\n },\n meta: {\n mode: \"hybrid-webgpu\",\n durationMs: nowMs() - start,\n usedWebGpu: false,\n candidateCount: 0,\n bridgedToDraw: false,\n },\n };\n }\n\n const bboxFlat = new Float32Array(prepared.length * 4);\n for (let i = 0; i < prepared.length; i += 1) {\n const base = i * 4;\n const poly = prepared[i];\n bboxFlat[base] = poly.minX;\n bboxFlat[base + 1] = poly.minY;\n bboxFlat[base + 2] = poly.maxX;\n bboxFlat[base + 3] = poly.maxY;\n }\n\n let candidateMask: Uint32Array | null = null;\n let usedWebGpu = false;\n try {\n candidateMask = await prefilterPointsByBoundsWebGpu(pointData.positions, safeCount, bboxFlat);\n usedWebGpu = !!candidateMask;\n } catch {\n candidateMask = null;\n usedWebGpu = false;\n }\n\n if (!candidateMask) {\n const fallback = filterPointDataByPolygons(pointData, polygons);\n return {\n data: fallback,\n meta: {\n mode: \"hybrid-webgpu\",\n durationMs: nowMs() - start,\n usedWebGpu: false,\n candidateCount: safeCount,\n bridgedToDraw: false,\n },\n };\n }\n\n let candidateCount = 0;\n for (let i = 0; i < safeCount; i += 1) {\n if (candidateMask[i] === 1) candidateCount += 1;\n }\n\n const candidateIndices = new Uint32Array(candidateCount);\n if (candidateCount > 0) {\n let candidateCursor = 0;\n for (let i = 0; i < safeCount; i += 1) {\n if (candidateMask[i] !== 1) continue;\n candidateIndices[candidateCursor] = i;\n candidateCursor += 1;\n }\n }\n\n if (candidateCount === 0) {\n if (bridgeToDraw) {\n const data: WsiPointData = {\n count: safeCount,\n positions: pointData.positions.subarray(0, safeCount * 2),\n paletteIndices: pointData.paletteIndices.subarray(0, safeCount),\n drawIndices: new Uint32Array(0),\n };\n if (pointIds) {\n data.ids = pointIds.subarray(0, safeCount);\n }\n return {\n data,\n meta: {\n mode: \"hybrid-webgpu\",\n durationMs: nowMs() - start,\n usedWebGpu: true,\n candidateCount: 0,\n bridgedToDraw: true,\n },\n };\n }\n\n return {\n data: {\n count: 0,\n positions: new Float32Array(0),\n paletteIndices: new Uint16Array(0),\n ...(pointIds ? { ids: new Uint32Array(0) } : {}),\n },\n meta: {\n mode: \"hybrid-webgpu\",\n durationMs: nowMs() - start,\n usedWebGpu: true,\n candidateCount: 0,\n bridgedToDraw: false,\n },\n };\n }\n\n if (bridgeToDraw) {\n const drawIndices = new Uint32Array(candidateCount);\n let visibleCount = 0;\n\n for (let i = 0; i < candidateCount; i += 1) {\n const pointIndex = candidateIndices[i] ?? 0;\n const x = pointData.positions[pointIndex * 2];\n const y = pointData.positions[pointIndex * 2 + 1];\n if (!isInsideAnyPolygon(x, y, prepared)) continue;\n drawIndices[visibleCount] = pointIndex;\n visibleCount += 1;\n }\n\n const data: WsiPointData = {\n count: safeCount,\n positions: pointData.positions.subarray(0, safeCount * 2),\n paletteIndices: pointData.paletteIndices.subarray(0, safeCount),\n drawIndices: drawIndices.subarray(0, visibleCount),\n };\n if (pointIds) {\n data.ids = pointIds.subarray(0, safeCount);\n }\n\n return {\n data,\n meta: {\n mode: \"hybrid-webgpu\",\n durationMs: nowMs() - start,\n usedWebGpu: true,\n candidateCount,\n bridgedToDraw: true,\n },\n };\n }\n\n const nextPositions = new Float32Array(candidateCount * 2);\n const nextTerms = new Uint16Array(candidateCount);\n const nextIds = pointIds ? new Uint32Array(candidateCount) : null;\n let cursor = 0;\n\n for (let i = 0; i < candidateCount; i += 1) {\n const pointIndex = candidateIndices[i] ?? 0;\n const x = pointData.positions[pointIndex * 2];\n const y = pointData.positions[pointIndex * 2 + 1];\n if (!isInsideAnyPolygon(x, y, prepared)) continue;\n nextPositions[cursor * 2] = x;\n nextPositions[cursor * 2 + 1] = y;\n nextTerms[cursor] = pointData.paletteIndices[pointIndex];\n if (nextIds) {\n nextIds[cursor] = pointIds![pointIndex];\n }\n cursor += 1;\n }\n\n const compactData: WsiPointData = {\n count: cursor,\n positions: nextPositions.subarray(0, cursor * 2),\n paletteIndices: nextTerms.subarray(0, cursor),\n };\n if (nextIds) {\n compactData.ids = nextIds.subarray(0, cursor);\n }\n\n return {\n data: compactData,\n meta: {\n mode: \"hybrid-webgpu\",\n durationMs: nowMs() - start,\n usedWebGpu: true,\n candidateCount,\n bridgedToDraw: false,\n },\n };\n}\n","import { filterPointDataByPolygons, filterPointIndicesByPolygons, type RoiPolygon } from \"./point-clip\";\nimport type { RoiClipWorkerRequest, RoiClipWorkerResponse } from \"./point-clip-worker-protocol\";\nimport type { WsiPointData } from \"./types\";\n\nexport type PointClipMode = \"sync\" | \"worker\" | \"hybrid-webgpu\";\n\nexport interface PointClipResultMeta {\n mode: PointClipMode;\n durationMs: number;\n}\n\nexport interface PointClipResult {\n data: WsiPointData | null;\n meta: PointClipResultMeta;\n}\n\nexport interface PointClipIndexResult {\n indices: Uint32Array;\n meta: PointClipResultMeta;\n}\n\ninterface PendingDataWorkerRequest {\n kind: \"data\";\n resolve: (result: PointClipResult) => void;\n reject: (reason?: unknown) => void;\n startMs: number;\n}\n\ninterface PendingIndexWorkerRequest {\n kind: \"index\";\n resolve: (result: PointClipIndexResult) => void;\n reject: (reason?: unknown) => void;\n startMs: number;\n}\n\ntype PendingWorkerRequest = PendingDataWorkerRequest | PendingIndexWorkerRequest;\n\nlet workerInstance: Worker | null = null;\nlet workerSupported = true;\nlet requestId = 1;\nconst pendingById = new Map<number, PendingWorkerRequest>();\n\nfunction nowMs(): number {\n if (typeof performance !== \"undefined\" && typeof performance.now === \"function\") {\n return performance.now();\n }\n return Date.now();\n}\n\nfunction createWorker(): Worker | null {\n if (!workerSupported) return null;\n if (workerInstance) return workerInstance;\n try {\n const worker = new Worker(new URL(\"../workers/roi-clip-worker.ts\", import.meta.url), { type: \"module\" });\n worker.addEventListener(\"message\", handleWorkerMessage);\n worker.addEventListener(\"error\", handleWorkerError);\n workerInstance = worker;\n return worker;\n } catch {\n workerSupported = false;\n return null;\n }\n}\n\nfunction handleWorkerMessage(event: MessageEvent<RoiClipWorkerResponse>): void {\n const msg = event.data;\n if (!msg) return;\n const pending = pendingById.get(msg.id);\n if (!pending) return;\n pendingById.delete(msg.id);\n\n if (msg.type === \"roi-clip-failure\") {\n pending.reject(new Error(msg.error || \"worker clip failed\"));\n return;\n }\n\n if (msg.type === \"roi-clip-index-success\") {\n if (pending.kind !== \"index\") {\n pending.reject(new Error(\"worker response mismatch: expected point data result\"));\n return;\n }\n const count = Math.max(0, Math.floor(msg.count));\n const indices = new Uint32Array(msg.indices).subarray(0, count);\n pending.resolve({\n indices,\n meta: {\n mode: \"worker\",\n durationMs: Number.isFinite(msg.durationMs) ? msg.durationMs : nowMs() - pending.startMs,\n },\n });\n return;\n }\n\n if (pending.kind !== \"data\") {\n pending.reject(new Error(\"worker response mismatch: expected index result\"));\n return;\n }\n\n const count = Math.max(0, Math.floor(msg.count));\n const positions = new Float32Array(msg.positions);\n const paletteIndices = new Uint16Array(msg.paletteIndices);\n const ids = msg.ids ? new Uint32Array(msg.ids) : null;\n const output: WsiPointData = {\n count,\n positions: positions.subarray(0, count * 2),\n paletteIndices: paletteIndices.subarray(0, count),\n };\n if (ids) {\n output.ids = ids.subarray(0, count);\n }\n\n pending.resolve({\n data: output,\n meta: {\n mode: \"worker\",\n durationMs: Number.isFinite(msg.durationMs) ? msg.durationMs : nowMs() - pending.startMs,\n },\n });\n}\n\nfunction handleWorkerError(): void {\n workerSupported = false;\n if (workerInstance) {\n workerInstance.removeEventListener(\"message\", handleWorkerMessage);\n workerInstance.removeEventListener(\"error\", handleWorkerError);\n workerInstance.terminate();\n workerInstance = null;\n }\n for (const [, pending] of pendingById) {\n pending.reject(new Error(\"worker crashed\"));\n }\n pendingById.clear();\n}\n\nexport function terminateRoiClipWorker(): void {\n if (!workerInstance) return;\n workerInstance.removeEventListener(\"message\", handleWorkerMessage);\n workerInstance.removeEventListener(\"error\", handleWorkerError);\n workerInstance.terminate();\n workerInstance = null;\n for (const [, pending] of pendingById) {\n pending.reject(new Error(\"worker terminated\"));\n }\n pendingById.clear();\n}\n\nexport async function filterPointDataByPolygonsInWorker(pointData: WsiPointData | null | undefined, polygons: RoiPolygon[] | null | undefined): Promise<PointClipResult> {\n if (!pointData || !pointData.count || !pointData.positions || !pointData.paletteIndices) {\n return {\n data: null,\n meta: { mode: \"worker\", durationMs: 0 },\n };\n }\n\n const worker = createWorker();\n if (!worker) {\n const start = nowMs();\n return {\n data: filterPointDataByPolygons(pointData, polygons),\n meta: { mode: \"sync\", durationMs: nowMs() - start },\n };\n }\n\n const safeCount = Math.max(0, Math.min(pointData.count, Math.floor(pointData.positions.length / 2), pointData.paletteIndices.length));\n const positionsCopy = pointData.positions.slice(0, safeCount * 2);\n const termsCopy = pointData.paletteIndices.slice(0, safeCount);\n const idsCopy = pointData.ids instanceof Uint32Array && pointData.ids.length >= safeCount ? pointData.ids.slice(0, safeCount) : null;\n const id = requestId++;\n const startMs = nowMs();\n\n return new Promise<PointClipResult>((resolve, reject) => {\n pendingById.set(id, { kind: \"data\", resolve, reject, startMs });\n const msg: RoiClipWorkerRequest = {\n type: \"roi-clip-request\",\n id,\n count: safeCount,\n positions: positionsCopy.buffer,\n paletteIndices: termsCopy.buffer,\n ids: idsCopy?.buffer,\n polygons: polygons ?? [],\n };\n const transfer: Transferable[] = [positionsCopy.buffer, termsCopy.buffer];\n if (idsCopy) {\n transfer.push(idsCopy.buffer);\n }\n worker.postMessage(msg, transfer);\n });\n}\n\nexport async function filterPointIndicesByPolygonsInWorker(pointData: WsiPointData | null | undefined, polygons: RoiPolygon[] | null | undefined): Promise<PointClipIndexResult> {\n if (!pointData || !pointData.count || !pointData.positions || !pointData.paletteIndices) {\n return {\n indices: new Uint32Array(0),\n meta: { mode: \"worker\", durationMs: 0 },\n };\n }\n\n const worker = createWorker();\n if (!worker) {\n const start = nowMs();\n return {\n indices: filterPointIndicesByPolygons(pointData, polygons),\n meta: { mode: \"sync\", durationMs: nowMs() - start },\n };\n }\n\n const safeCount = Math.max(0, Math.min(pointData.count, Math.floor(pointData.positions.length / 2), pointData.paletteIndices.length));\n const positionsCopy = pointData.positions.slice(0, safeCount * 2);\n const id = requestId++;\n const startMs = nowMs();\n\n return new Promise<PointClipIndexResult>((resolve, reject) => {\n pendingById.set(id, { kind: \"index\", resolve, reject, startMs });\n const msg: RoiClipWorkerRequest = {\n type: \"roi-clip-index-request\",\n id,\n count: safeCount,\n positions: positionsCopy.buffer,\n polygons: polygons ?? [],\n };\n worker.postMessage(msg, [positionsCopy.buffer]);\n });\n}\n","import type { WsiPointData, WsiRegion } from \"./types\";\n\nexport interface RoiTermCount {\n\ttermId: string;\n\tpaletteIndex: number;\n\tcount: number;\n}\n\nexport interface RoiPointGroup {\n\tregionId: string | number;\n\tregionIndex: number;\n\ttotalCount: number;\n\ttermCounts: RoiTermCount[];\n}\n\nexport interface RoiPointGroupOptions {\n\tpaletteIndexToTermId?: ReadonlyMap<number, string> | readonly string[];\n\tincludeEmptyRegions?: boolean;\n}\n\nexport interface RoiPointGroupStats {\n\tgroups: RoiPointGroup[];\n\tinputPointCount: number;\n\tpointsInsideAnyRegion: number;\n\tunmatchedPointCount: number;\n}\n\ninterface PreparedRegion {\n\tregionId: string | number;\n\tregionIndex: number;\n\tring: Array<[number, number]>;\n\tminX: number;\n\tminY: number;\n\tmaxX: number;\n\tmaxY: number;\n\tarea: number;\n}\n\nfunction closeRing(\n\tcoordinates: readonly [number, number][],\n): Array<[number, number]> {\n\tif (!Array.isArray(coordinates) || coordinates.length < 3) return [];\n\tconst out = coordinates.map(\n\t\t(point): [number, number] => [Number(point[0]), Number(point[1])],\n\t);\n\tconst first = out[0];\n\tconst last = out[out.length - 1];\n\tif (!first || !last) return [];\n\tif (first[0] !== last[0] || first[1] !== last[1]) {\n\t\tout.push([first[0], first[1]]);\n\t}\n\treturn out;\n}\n\nfunction polygonArea(ring: Array<[number, number]>): number {\n\tlet sum = 0;\n\tfor (let i = 0; i < ring.length - 1; i += 1) {\n\t\tconst [ax, ay] = ring[i];\n\t\tconst [bx, by] = ring[i + 1];\n\t\tsum += ax * by - bx * ay;\n\t}\n\treturn Math.abs(sum * 0.5);\n}\n\nfunction prepareRegions(regions: readonly WsiRegion[]): PreparedRegion[] {\n\tconst prepared: PreparedRegion[] = [];\n\tfor (let i = 0; i < regions.length; i += 1) {\n\t\tconst region = regions[i];\n\t\tif (!region?.coordinates?.length) continue;\n\n\t\tconst ring = closeRing(region.coordinates);\n\t\tif (ring.length < 4) continue;\n\n\t\tlet minX = Infinity;\n\t\tlet minY = Infinity;\n\t\tlet maxX = -Infinity;\n\t\tlet maxY = -Infinity;\n\t\tfor (const [x, y] of ring) {\n\t\t\tif (x < minX) minX = x;\n\t\t\tif (x > maxX) maxX = x;\n\t\t\tif (y < minY) minY = y;\n\t\t\tif (y > maxY) maxY = y;\n\t\t}\n\t\tif (\n\t\t\t!Number.isFinite(minX) ||\n\t\t\t!Number.isFinite(minY) ||\n\t\t\t!Number.isFinite(maxX) ||\n\t\t\t!Number.isFinite(maxY)\n\t\t) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tprepared.push({\n\t\t\tregionId: region.id ?? i,\n\t\t\tregionIndex: i,\n\t\t\tring,\n\t\t\tminX,\n\t\t\tminY,\n\t\t\tmaxX,\n\t\t\tmaxY,\n\t\t\tarea: Math.max(1e-6, polygonArea(ring)),\n\t\t});\n\t}\n\treturn prepared;\n}\n\nfunction isInsideRing(x: number, y: number, ring: Array<[number, number]>): boolean {\n\tlet inside = false;\n\tfor (let i = 0, j = ring.length - 1; i < ring.length; j = i, i += 1) {\n\t\tconst xi = ring[i][0];\n\t\tconst yi = ring[i][1];\n\t\tconst xj = ring[j][0];\n\t\tconst yj = ring[j][1];\n\t\tconst intersect =\n\t\t\tyi > y !== yj > y &&\n\t\t\tx < ((xj - xi) * (y - yi)) / ((yj - yi) || Number.EPSILON) + xi;\n\t\tif (intersect) inside = !inside;\n\t}\n\treturn inside;\n}\n\nfunction resolveTermId(\n\tpaletteIndex: number,\n\tpaletteIndexToTermId: RoiPointGroupOptions[\"paletteIndexToTermId\"],\n): string {\n\tif (Array.isArray(paletteIndexToTermId)) {\n\t\tconst fromArray = paletteIndexToTermId[paletteIndex];\n\t\tif (typeof fromArray === \"string\" && fromArray.length > 0) return fromArray;\n\t}\n\tif (paletteIndexToTermId instanceof Map) {\n\t\tconst fromMap = paletteIndexToTermId.get(paletteIndex);\n\t\tif (typeof fromMap === \"string\" && fromMap.length > 0) return fromMap;\n\t}\n\treturn String(paletteIndex);\n}\n\nexport function computeRoiPointGroups(\n\tpointData: WsiPointData | null | undefined,\n\tregions: readonly WsiRegion[] | null | undefined,\n\toptions: RoiPointGroupOptions = {},\n): RoiPointGroupStats {\n\tconst baseCount = Math.max(\n\t\t0,\n\t\tMath.min(\n\t\t\tMath.floor(pointData?.count ?? 0),\n\t\t\tMath.floor((pointData?.positions?.length ?? 0) / 2),\n\t\t\tpointData?.paletteIndices?.length ?? 0,\n\t\t),\n\t);\n\n\tlet drawIndices: Uint32Array | null = null;\n\tif (pointData?.drawIndices instanceof Uint32Array) {\n\t\tconst source = pointData.drawIndices;\n\t\tlet valid = source.length;\n\t\tfor (let i = 0; i < source.length; i += 1) {\n\t\t\tconst idx = source[i];\n\t\t\tif (idx < baseCount) continue;\n\t\t\tvalid -= 1;\n\t\t}\n\t\tif (valid === source.length) {\n\t\t\tdrawIndices = source;\n\t\t} else if (valid > 0) {\n\t\t\tconst filtered = new Uint32Array(valid);\n\t\t\tlet cursor = 0;\n\t\t\tfor (let i = 0; i < source.length; i += 1) {\n\t\t\t\tconst idx = source[i];\n\t\t\t\tif (idx >= baseCount) continue;\n\t\t\t\tfiltered[cursor] = idx;\n\t\t\t\tcursor += 1;\n\t\t\t}\n\t\t\tdrawIndices = filtered;\n\t\t} else {\n\t\t\tdrawIndices = new Uint32Array(0);\n\t\t}\n\t}\n\n\tconst inputCount = drawIndices ? drawIndices.length : baseCount;\n\n\tconst preparedRegions = prepareRegions(regions ?? []);\n\tif (!pointData || inputCount === 0 || preparedRegions.length === 0) {\n\t\treturn {\n\t\t\tgroups: [],\n\t\t\tinputPointCount: inputCount,\n\t\t\tpointsInsideAnyRegion: 0,\n\t\t\tunmatchedPointCount: inputCount,\n\t\t};\n\t}\n\n\tconst regionTermCounters = new Map<number, Map<number, number>>();\n\tconst regionTotalCounters = new Map<number, number>();\n\tlet insideCount = 0;\n\n\tfor (let i = 0; i < inputCount; i += 1) {\n\t\tconst pointIndex = drawIndices ? drawIndices[i] : i;\n\t\tconst x = pointData.positions[pointIndex * 2];\n\t\tconst y = pointData.positions[pointIndex * 2 + 1];\n\t\tlet bestRegion: PreparedRegion | null = null;\n\n\t\tfor (const region of preparedRegions) {\n\t\t\tif (x < region.minX || x > region.maxX || y < region.minY || y > region.maxY) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (!isInsideRing(x, y, region.ring)) continue;\n\t\t\tif (!bestRegion || region.area < bestRegion.area) {\n\t\t\t\tbestRegion = region;\n\t\t\t}\n\t\t}\n\n\t\tif (!bestRegion) continue;\n\t\tinsideCount += 1;\n\n\t\tconst paletteIndex = pointData.paletteIndices[pointIndex] ?? 0;\n\t\tconst regionTermMap =\n\t\t\tregionTermCounters.get(bestRegion.regionIndex) ?? new Map<number, number>();\n\t\tregionTermMap.set(paletteIndex, (regionTermMap.get(paletteIndex) ?? 0) + 1);\n\t\tregionTermCounters.set(bestRegion.regionIndex, regionTermMap);\n\t\tregionTotalCounters.set(\n\t\t\tbestRegion.regionIndex,\n\t\t\t(regionTotalCounters.get(bestRegion.regionIndex) ?? 0) + 1,\n\t\t);\n\t}\n\n\tconst includeEmptyRegions = options.includeEmptyRegions ?? false;\n\tconst groups: RoiPointGroup[] = [];\n\tfor (const region of preparedRegions) {\n\t\tconst totalCount = regionTotalCounters.get(region.regionIndex) ?? 0;\n\t\tif (!includeEmptyRegions && totalCount <= 0) continue;\n\t\tconst termMap = regionTermCounters.get(region.regionIndex) ?? new Map();\n\t\tconst termCounts: RoiTermCount[] = Array.from(termMap.entries())\n\t\t\t.map(([paletteIndex, count]) => ({\n\t\t\t\ttermId: resolveTermId(paletteIndex, options.paletteIndexToTermId),\n\t\t\t\tpaletteIndex,\n\t\t\t\tcount,\n\t\t\t}))\n\t\t\t.sort((a, b) => b.count - a.count || a.paletteIndex - b.paletteIndex);\n\n\t\tgroups.push({\n\t\t\tregionId: region.regionId,\n\t\t\tregionIndex: region.regionIndex,\n\t\t\ttotalCount,\n\t\t\ttermCounts,\n\t\t});\n\t}\n\n\treturn {\n\t\tgroups,\n\t\tinputPointCount: inputCount,\n\t\tpointsInsideAnyRegion: insideCount,\n\t\tunmatchedPointCount: Math.max(0, inputCount - insideCount),\n\t};\n}\n","export type TileBounds = [number, number, number, number];\n\nexport interface ScheduledTile {\n\tkey: string;\n\ttier: number;\n\tx: number;\n\ty: number;\n\tbounds: TileBounds;\n\tdistance2: number;\n\turl: string;\n}\n\nexport interface TileSchedulerSnapshot {\n\tinflight: number;\n\tqueued: number;\n\taborted: number;\n\tretries: number;\n\tfailed: number;\n}\n\nexport interface TileSchedulerOptions {\n\tmaxConcurrency?: number;\n\tmaxRetries?: number;\n\tretryBaseDelayMs?: number;\n\tretryMaxDelayMs?: number;\n\tauthToken?: string;\n\tonTileLoad: (tile: ScheduledTile, bitmap: ImageBitmap) => void;\n\tonTileError?: (\n\t\ttile: ScheduledTile,\n\t\terror: unknown,\n\t\tattemptCount: number,\n\t) => void;\n\tonStateChange?: (snapshot: TileSchedulerSnapshot) => void;\n}\n\ninterface QueueItem {\n\ttile: ScheduledTile;\n\tattempt: number;\n\treadyAt: number;\n}\n\ninterface InflightItem {\n\ttile: ScheduledTile;\n\tattempt: number;\n\tcontroller: AbortController;\n}\n\nfunction nowMs(): number {\n\tif (typeof performance !== \"undefined\" && typeof performance.now === \"function\") {\n\t\treturn performance.now();\n\t}\n\treturn Date.now();\n}\n\nfunction shouldAttachAuthHeader(url: string, authToken: string): boolean {\n\tif (!authToken) return false;\n\ttry {\n\t\tconst parsed = new URL(url, typeof window !== \"undefined\" ? window.location.href : undefined);\n\t\tconst host = parsed.hostname.toLowerCase();\n\t\tconst isAwsS3 =\n\t\t\thost.includes(\"amazonaws.com\") || host.startsWith(\"s3.\") || host.includes(\".s3.\");\n\t\tif (isAwsS3) return false;\n\t} catch {\n\t\t// Fallback to attaching auth if URL parsing fails.\n\t}\n\treturn true;\n}\n\nexport class TileScheduler {\n\tprivate readonly maxConcurrency: number;\n\tprivate readonly maxRetries: number;\n\tprivate readonly retryBaseDelayMs: number;\n\tprivate readonly retryMaxDelayMs: number;\n\tprivate readonly onTileLoad: (tile: ScheduledTile, bitmap: ImageBitmap) => void;\n\tprivate readonly onTileError?:\n\t\t| ((tile: ScheduledTile, error: unknown, attemptCount: number) => void)\n\t\t| undefined;\n\tprivate readonly onStateChange?:\n\t\t| ((snapshot: TileSchedulerSnapshot) => void)\n\t\t| undefined;\n\n\tprivate authToken: string;\n\tprivate destroyed = false;\n\tprivate queue: QueueItem[] = [];\n\tprivate queuedByKey = new Map<string, QueueItem>();\n\tprivate inflight = new Map<string, InflightItem>();\n\tprivate visibleKeys = new Set<string>();\n\tprivate timerId: number | null = null;\n\tprivate abortedCount = 0;\n\tprivate retryCount = 0;\n\tprivate failedCount = 0;\n\n\tconstructor(options: TileSchedulerOptions) {\n\t\tthis.maxConcurrency = Math.max(1, Math.floor(options.maxConcurrency ?? 12));\n\t\tthis.maxRetries = Math.max(0, Math.floor(options.maxRetries ?? 2));\n\t\tthis.retryBaseDelayMs = Math.max(\n\t\t\t10,\n\t\t\tMath.floor(options.retryBaseDelayMs ?? 120),\n\t\t);\n\t\tthis.retryMaxDelayMs = Math.max(\n\t\t\tthis.retryBaseDelayMs,\n\t\t\tMath.floor(options.retryMaxDelayMs ?? 1200),\n\t\t);\n\t\tthis.authToken = options.authToken ?? \"\";\n\t\tthis.onTileLoad = options.onTileLoad;\n\t\tthis.onTileError = options.onTileError;\n\t\tthis.onStateChange = options.onStateChange;\n\t}\n\n\tsetAuthToken(token: string): void {\n\t\tthis.authToken = String(token ?? \"\");\n\t}\n\n\tschedule(tiles: readonly ScheduledTile[]): void {\n\t\tif (this.destroyed) return;\n\n\t\tconst nextVisibleKeys = new Set<string>();\n\t\tfor (const tile of tiles) {\n\t\t\tnextVisibleKeys.add(tile.key);\n\t\t}\n\t\tthis.visibleKeys = nextVisibleKeys;\n\n\t\tthis.dropInvisibleQueued(nextVisibleKeys);\n\t\tthis.abortInvisibleInflight(nextVisibleKeys);\n\n\t\tfor (const tile of tiles) {\n\t\t\tif (this.inflight.has(tile.key)) {\n\t\t\t\tconst inflight = this.inflight.get(tile.key);\n\t\t\t\tif (inflight) inflight.tile = tile;\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst queued = this.queuedByKey.get(tile.key);\n\t\t\tif (queued) {\n\t\t\t\tqueued.tile = tile;\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst item: QueueItem = {\n\t\t\t\ttile,\n\t\t\t\tattempt: 0,\n\t\t\t\treadyAt: nowMs(),\n\t\t\t};\n\t\t\tthis.queue.push(item);\n\t\t\tthis.queuedByKey.set(tile.key, item);\n\t\t}\n\n\t\tthis.sortQueue();\n\t\tthis.pump();\n\t\tthis.emitStateChange();\n\t}\n\n\tclear(): void {\n\t\tthis.clearPumpTimer();\n\t\tthis.visibleKeys.clear();\n\t\tthis.queue = [];\n\t\tthis.queuedByKey.clear();\n\n\t\tfor (const [, item] of this.inflight) {\n\t\t\titem.controller.abort();\n\t\t}\n\t\tthis.inflight.clear();\n\t\tthis.emitStateChange();\n\t}\n\n\tdestroy(): void {\n\t\tif (this.destroyed) return;\n\t\tthis.destroyed = true;\n\t\tthis.clear();\n\t}\n\n\tgetInflightCount(): number {\n\t\treturn this.inflight.size;\n\t}\n\n\tgetSnapshot(): TileSchedulerSnapshot {\n\t\treturn {\n\t\t\tinflight: this.inflight.size,\n\t\t\tqueued: this.queue.length,\n\t\t\taborted: this.abortedCount,\n\t\t\tretries: this.retryCount,\n\t\t\tfailed: this.failedCount,\n\t\t};\n\t}\n\n\tprivate dropInvisibleQueued(visibleKeys: Set<string>): void {\n\t\tif (this.queue.length === 0) return;\n\t\tconst nextQueue: QueueItem[] = [];\n\t\tfor (const item of this.queue) {\n\t\t\tif (!visibleKeys.has(item.tile.key)) {\n\t\t\t\tthis.queuedByKey.delete(item.tile.key);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tnextQueue.push(item);\n\t\t}\n\t\tthis.queue = nextQueue;\n\t}\n\n\tprivate abortInvisibleInflight(visibleKeys: Set<string>): void {\n\t\tfor (const [key, item] of this.inflight) {\n\t\t\tif (visibleKeys.has(key)) continue;\n\t\t\tthis.inflight.delete(key);\n\t\t\tthis.abortedCount += 1;\n\t\t\titem.controller.abort();\n\t\t}\n\t}\n\n\tprivate sortQueue(): void {\n\t\tthis.queue.sort((a, b) => {\n\t\t\tif (a.readyAt !== b.readyAt) return a.readyAt - b.readyAt;\n\t\t\tif (a.tile.distance2 !== b.tile.distance2) {\n\t\t\t\treturn a.tile.distance2 - b.tile.distance2;\n\t\t\t}\n\t\t\tif (a.tile.tier !== b.tile.tier) return b.tile.tier - a.tile.tier;\n\t\t\treturn a.tile.key.localeCompare(b.tile.key);\n\t\t});\n\t}\n\n\tprivate pump(): void {\n\t\tif (this.destroyed) return;\n\t\tthis.clearPumpTimer();\n\n\t\twhile (this.inflight.size < this.maxConcurrency) {\n\t\t\tconst next = this.takeNextReadyQueueItem();\n\t\t\tif (!next) break;\n\t\t\tthis.startFetch(next);\n\t\t}\n\n\t\tif (this.inflight.size >= this.maxConcurrency) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (this.queue.length === 0) return;\n\n\t\tconst earliestReadyAt = this.queue[0]?.readyAt;\n\t\tif (typeof earliestReadyAt !== \"number\") return;\n\t\tconst delay = Math.max(0, earliestReadyAt - nowMs());\n\t\tthis.timerId = window.setTimeout(() => {\n\t\t\tthis.timerId = null;\n\t\t\tthis.pump();\n\t\t}, delay);\n\t}\n\n\tprivate takeNextReadyQueueItem(): QueueItem | null {\n\t\tif (this.queue.length === 0) return null;\n\t\tconst now = nowMs();\n\t\tconst first = this.queue[0];\n\t\tif (!first || first.readyAt > now) return null;\n\n\t\tthis.queue.shift();\n\t\tthis.queuedByKey.delete(first.tile.key);\n\t\treturn first;\n\t}\n\n\tprivate startFetch(item: QueueItem): void {\n\t\tconst controller = new AbortController();\n\t\tconst inflightEntry: InflightItem = {\n\t\t\ttile: item.tile,\n\t\t\tattempt: item.attempt,\n\t\t\tcontroller,\n\t\t};\n\t\tthis.inflight.set(item.tile.key, inflightEntry);\n\t\tthis.emitStateChange();\n\n\t\tconst useAuthHeader = shouldAttachAuthHeader(item.tile.url, this.authToken);\n\t\tfetch(item.tile.url, {\n\t\t\tsignal: controller.signal,\n\t\t\theaders: useAuthHeader ? { Authorization: this.authToken } : undefined,\n\t\t})\n\t\t\t.then((response) => {\n\t\t\t\tif (!response.ok) {\n\t\t\t\t\tthrow new Error(`HTTP ${response.status}`);\n\t\t\t\t}\n\t\t\t\treturn response.blob();\n\t\t\t})\n\t\t\t.then((blob) => createImageBitmap(blob))\n\t\t\t.then((bitmap) => {\n\t\t\t\tif (this.destroyed || controller.signal.aborted) {\n\t\t\t\t\tbitmap.close();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (!this.visibleKeys.has(item.tile.key)) {\n\t\t\t\t\tbitmap.close();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tthis.onTileLoad(item.tile, bitmap);\n\t\t\t})\n\t\t\t.catch((error: unknown) => {\n\t\t\t\tif (controller.signal.aborted || this.destroyed) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst shouldRetry =\n\t\t\t\t\titem.attempt < this.maxRetries && this.visibleKeys.has(item.tile.key);\n\t\t\t\tif (shouldRetry) {\n\t\t\t\t\tthis.retryCount += 1;\n\t\t\t\t\tconst nextAttempt = item.attempt + 1;\n\t\t\t\t\tconst retryDelay = this.getRetryDelay(nextAttempt);\n\t\t\t\t\tconst queued: QueueItem = {\n\t\t\t\t\t\ttile: item.tile,\n\t\t\t\t\t\tattempt: nextAttempt,\n\t\t\t\t\t\treadyAt: nowMs() + retryDelay,\n\t\t\t\t\t};\n\t\t\t\t\tconst existing = this.queuedByKey.get(item.tile.key);\n\t\t\t\t\tif (existing) {\n\t\t\t\t\t\texisting.tile = queued.tile;\n\t\t\t\t\t\texisting.readyAt = Math.min(existing.readyAt, queued.readyAt);\n\t\t\t\t\t\texisting.attempt = Math.max(existing.attempt, queued.attempt);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthis.queue.push(queued);\n\t\t\t\t\t\tthis.queuedByKey.set(queued.tile.key, queued);\n\t\t\t\t\t}\n\t\t\t\t\tthis.sortQueue();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tthis.failedCount += 1;\n\t\t\t\tthis.onTileError?.(item.tile, error, item.attempt + 1);\n\t\t\t})\n\t\t\t.finally(() => {\n\t\t\t\tthis.inflight.delete(item.tile.key);\n\t\t\t\tthis.pump();\n\t\t\t\tthis.emitStateChange();\n\t\t\t});\n\t}\n\n\tprivate getRetryDelay(attempt: number): number {\n\t\tconst exp = Math.max(0, attempt - 1);\n\t\tconst delay = Math.min(\n\t\t\tthis.retryMaxDelayMs,\n\t\t\tthis.retryBaseDelayMs * 2 ** exp,\n\t\t);\n\t\tconst jitter = 0.85 + Math.random() * 0.3;\n\t\treturn Math.round(delay * jitter);\n\t}\n\n\tprivate clearPumpTimer(): void {\n\t\tif (this.timerId === null) return;\n\t\twindow.clearTimeout(this.timerId);\n\t\tthis.timerId = null;\n\t}\n\n\tprivate emitStateChange(): void {\n\t\tthis.onStateChange?.(this.getSnapshot());\n\t}\n}\n","import { toTileUrl } from \"./image-info\";\nimport {\n\tTileScheduler,\n\ttype ScheduledTile,\n\ttype TileBounds,\n} from \"./tile-scheduler\";\nimport type {\n\tWsiImageSource,\n\tWsiPointData,\n\tWsiRenderStats,\n\tWsiViewState,\n} from \"./types\";\nimport { clamp, createProgram } from \"./utils\";\n\ntype Bounds = TileBounds;\n\ninterface CachedTile {\n\tkey: string;\n\ttexture: WebGLTexture;\n\tbounds: Bounds;\n\ttier: number;\n\tlastUsed: number;\n}\n\ninterface TileVertexProgram {\n\tprogram: WebGLProgram;\n\tvao: WebGLVertexArrayObject;\n\tvbo: WebGLBuffer;\n\tuCamera: WebGLUniformLocation;\n\tuBounds: WebGLUniformLocation;\n\tuTexture: WebGLUniformLocation;\n}\n\ninterface PointProgram {\n\tprogram: WebGLProgram;\n\tvao: WebGLVertexArrayObject;\n\tposBuffer: WebGLBuffer;\n\ttermBuffer: WebGLBuffer;\n\tindexBuffer: WebGLBuffer;\n\tpaletteTexture: WebGLTexture;\n\tuCamera: WebGLUniformLocation;\n\tuPointSize: WebGLUniformLocation;\n\tuPalette: WebGLUniformLocation;\n\tuPaletteSize: WebGLUniformLocation;\n}\n\ninterface OrthoViewport {\n\twidth: number;\n\theight: number;\n}\n\ntype WorldPoint = [number, number];\nconst DEFAULT_ROTATION_DRAG_SENSITIVITY = 0.35;\nconst MIN_POINT_SIZE_PX = 0.5;\nconst MAX_POINT_SIZE_PX = 256;\n\ninterface PointSizeStop {\n\tzoom: number;\n\tsize: number;\n}\n\nconst DEFAULT_POINT_SIZE_STOPS: readonly PointSizeStop[] = [\n\t{ zoom: 1, size: 2.8 },\n\t{ zoom: 2, size: 3.4 },\n\t{ zoom: 3, size: 4.2 },\n\t{ zoom: 4, size: 5.3 },\n\t{ zoom: 5, size: 6.8 },\n\t{ zoom: 6, size: 8.4 },\n\t{ zoom: 7, size: 9.8 },\n\t{ zoom: 8, size: 11.2 },\n\t{ zoom: 9, size: 14.0 },\n\t{ zoom: 10, size: 17.5 },\n\t{ zoom: 11, size: 22.0 },\n\t{ zoom: 12, size: 28.0 },\n];\n\nexport type PointSizeByZoom = Readonly<Record<number, number>>;\n\nexport interface WsiTileSchedulerConfig {\n\tmaxConcurrency?: number;\n\tmaxRetries?: number;\n\tretryBaseDelayMs?: number;\n\tretryMaxDelayMs?: number;\n}\n\nexport interface WsiTileRendererOptions {\n\tonViewStateChange?: (next: WsiViewState) => void;\n\tonStats?: (stats: WsiRenderStats) => void;\n\tauthToken?: string;\n\tpointSizeByZoom?: PointSizeByZoom;\n\tmaxCacheTiles?: number;\n\tctrlDragRotate?: boolean;\n\trotationDragSensitivityDegPerPixel?: number;\n\ttileScheduler?: WsiTileSchedulerConfig;\n\tonTileError?: (event: WsiTileErrorEvent) => void;\n\tonContextLost?: () => void;\n\tonContextRestored?: () => void;\n}\n\nexport interface WsiTileErrorEvent {\n\ttile: ScheduledTile;\n\terror: unknown;\n\tattemptCount: number;\n}\n\nclass OrthoCamera {\n\tprivate viewportWidth = 1;\n\tprivate viewportHeight = 1;\n\tprivate viewState: WsiViewState = {\n\t\tzoom: 1,\n\t\toffsetX: 0,\n\t\toffsetY: 0,\n\t\trotationDeg: 0,\n\t};\n\n\tsetViewport(width: number, height: number): void {\n\t\tthis.viewportWidth = Math.max(1, width);\n\t\tthis.viewportHeight = Math.max(1, height);\n\t}\n\n\tgetViewport(): OrthoViewport {\n\t\treturn { width: this.viewportWidth, height: this.viewportHeight };\n\t}\n\n\tsetViewState(next: Partial<WsiViewState>): void {\n\t\tif (typeof next.zoom === \"number\") {\n\t\t\tthis.viewState.zoom = Math.max(0.0001, next.zoom);\n\t\t}\n\t\tif (typeof next.offsetX === \"number\") {\n\t\t\tthis.viewState.offsetX = next.offsetX;\n\t\t}\n\t\tif (typeof next.offsetY === \"number\") {\n\t\t\tthis.viewState.offsetY = next.offsetY;\n\t\t}\n\t\tif (typeof next.rotationDeg === \"number\" && Number.isFinite(next.rotationDeg)) {\n\t\t\tthis.viewState.rotationDeg = next.rotationDeg;\n\t\t}\n\t}\n\n\tgetViewState(): WsiViewState {\n\t\treturn { ...this.viewState };\n\t}\n\n\tgetCenter(): WorldPoint {\n\t\tconst zoom = Math.max(1e-6, this.viewState.zoom);\n\t\treturn [\n\t\t\tthis.viewState.offsetX + this.viewportWidth / (2 * zoom),\n\t\t\tthis.viewState.offsetY + this.viewportHeight / (2 * zoom),\n\t\t];\n\t}\n\n\tsetCenter(centerX: number, centerY: number): void {\n\t\tconst zoom = Math.max(1e-6, this.viewState.zoom);\n\t\tthis.viewState.offsetX = centerX - this.viewportWidth / (2 * zoom);\n\t\tthis.viewState.offsetY = centerY - this.viewportHeight / (2 * zoom);\n\t}\n\n\tscreenToWorld(screenX: number, screenY: number): WorldPoint {\n\t\tconst state = this.viewState;\n\t\tconst zoom = Math.max(1e-6, state.zoom);\n\t\tconst [centerX, centerY] = this.getCenter();\n\t\tconst dx = (screenX - this.viewportWidth * 0.5) / zoom;\n\t\tconst dy = (screenY - this.viewportHeight * 0.5) / zoom;\n\t\tconst rad = toRadians(state.rotationDeg);\n\t\tconst cos = Math.cos(rad);\n\t\tconst sin = Math.sin(rad);\n\t\treturn [centerX + dx * cos - dy * sin, centerY + dx * sin + dy * cos];\n\t}\n\n\tworldToScreen(worldX: number, worldY: number): WorldPoint {\n\t\tconst state = this.viewState;\n\t\tconst zoom = Math.max(1e-6, state.zoom);\n\t\tconst [centerX, centerY] = this.getCenter();\n\t\tconst dx = worldX - centerX;\n\t\tconst dy = worldY - centerY;\n\t\tconst rad = toRadians(state.rotationDeg);\n\t\tconst cos = Math.cos(rad);\n\t\tconst sin = Math.sin(rad);\n\t\tconst rx = dx * cos + dy * sin;\n\t\tconst ry = -dx * sin + dy * cos;\n\t\treturn [\n\t\t\tthis.viewportWidth * 0.5 + rx * zoom,\n\t\t\tthis.viewportHeight * 0.5 + ry * zoom,\n\t\t];\n\t}\n\n\tgetViewCorners(): [WorldPoint, WorldPoint, WorldPoint, WorldPoint] {\n\t\tconst w = this.viewportWidth;\n\t\tconst h = this.viewportHeight;\n\t\treturn [\n\t\t\tthis.screenToWorld(0, 0),\n\t\t\tthis.screenToWorld(w, 0),\n\t\t\tthis.screenToWorld(w, h),\n\t\t\tthis.screenToWorld(0, h),\n\t\t];\n\t}\n\n\tgetMatrix(): Float32Array {\n\t\tconst zoom = Math.max(1e-6, this.viewState.zoom);\n\t\tconst [centerX, centerY] = this.getCenter();\n\t\tconst rad = toRadians(this.viewState.rotationDeg);\n\t\tconst cos = Math.cos(rad);\n\t\tconst sin = Math.sin(rad);\n\n\t\tconst ax = (2 * zoom * cos) / this.viewportWidth;\n\t\tconst bx = (2 * zoom * sin) / this.viewportWidth;\n\t\tconst ay = (2 * zoom * sin) / this.viewportHeight;\n\t\tconst by = (-2 * zoom * cos) / this.viewportHeight;\n\t\tconst tx = -(ax * centerX + bx * centerY);\n\t\tconst ty = -(ay * centerX + by * centerY);\n\n\t\treturn new Float32Array([ax, ay, 0, bx, by, 0, tx, ty, 1]);\n\t}\n}\n\nfunction toRadians(deg: number): number {\n\treturn (deg * Math.PI) / 180;\n}\n\nfunction nowMs(): number {\n\tif (typeof performance !== \"undefined\" && typeof performance.now === \"function\") {\n\t\treturn performance.now();\n\t}\n\treturn Date.now();\n}\n\nfunction requireUniformLocation(\n\tgl: WebGL2RenderingContext,\n\tprogram: WebGLProgram,\n\tname: string,\n): WebGLUniformLocation {\n\tconst location = gl.getUniformLocation(program, name);\n\tif (!location) {\n\t\tthrow new Error(`uniform location lookup failed: ${name}`);\n\t}\n\treturn location;\n}\n\nfunction isSameArrayView(\n\ta: ArrayBufferView | null | undefined,\n\tb: ArrayBufferView | null | undefined,\n): boolean {\n\tif (!a || !b) return a === b;\n\treturn (\n\t\ta.buffer === b.buffer &&\n\t\ta.byteOffset === b.byteOffset &&\n\t\ta.byteLength === b.byteLength\n\t);\n}\n\nfunction clonePointSizeStops(stops: readonly PointSizeStop[]): PointSizeStop[] {\n\treturn stops.map(stop => ({ zoom: stop.zoom, size: stop.size }));\n}\n\nfunction normalizePointSizeStops(pointSizeByZoom: PointSizeByZoom | null | undefined): PointSizeStop[] {\n\tif (!pointSizeByZoom) return clonePointSizeStops(DEFAULT_POINT_SIZE_STOPS);\n\n\tconst parsed = new Map<number, number>();\n\tfor (const [zoomKey, rawSize] of Object.entries(pointSizeByZoom)) {\n\t\tconst zoom = Number(zoomKey);\n\t\tconst size = Number(rawSize);\n\t\tif (!Number.isFinite(zoom) || !Number.isFinite(size) || size <= 0) continue;\n\t\tparsed.set(zoom, size);\n\t}\n\n\tif (parsed.size === 0) {\n\t\treturn clonePointSizeStops(DEFAULT_POINT_SIZE_STOPS);\n\t}\n\n\treturn Array.from(parsed.entries())\n\t\t.sort((a, b) => a[0] - b[0])\n\t\t.map(([zoom, size]) => ({ zoom, size }));\n}\n\nfunction arePointSizeStopsEqual(a: readonly PointSizeStop[], b: readonly PointSizeStop[]): boolean {\n\tif (a === b) return true;\n\tif (a.length !== b.length) return false;\n\tfor (let i = 0; i < a.length; i += 1) {\n\t\tif (a[i].zoom !== b[i].zoom || a[i].size !== b[i].size) {\n\t\t\treturn false;\n\t\t}\n\t}\n\treturn true;\n}\n\nfunction resolvePointSizeByZoomStops(continuousZoom: number, stops: readonly PointSizeStop[]): number {\n\tif (!Number.isFinite(continuousZoom)) return stops[0]?.size ?? MIN_POINT_SIZE_PX;\n\tif (stops.length === 0) return MIN_POINT_SIZE_PX;\n\tif (stops.length === 1) return stops[0].size;\n\tif (continuousZoom <= stops[0].zoom) return stops[0].size;\n\n\tfor (let i = 1; i < stops.length; i += 1) {\n\t\tconst prev = stops[i - 1];\n\t\tconst next = stops[i];\n\t\tif (continuousZoom > next.zoom) continue;\n\t\tconst span = Math.max(1e-6, next.zoom - prev.zoom);\n\t\tconst t = clamp((continuousZoom - prev.zoom) / span, 0, 1);\n\t\treturn prev.size + (next.size - prev.size) * t;\n\t}\n\n\tconst last = stops[stops.length - 1];\n\tconst prev = stops[stops.length - 2];\n\tconst span = Math.max(1e-6, last.zoom - prev.zoom);\n\tconst slope = (last.size - prev.size) / span;\n\treturn last.size + (continuousZoom - last.zoom) * slope;\n}\n\nexport class WsiTileRenderer {\n\tprivate readonly canvas: HTMLCanvasElement;\n\tprivate readonly source: WsiImageSource;\n\tprivate readonly gl: WebGL2RenderingContext;\n\tprivate readonly camera = new OrthoCamera();\n\tprivate readonly onViewStateChange?: (next: WsiViewState) => void;\n\tprivate readonly onStats?: (stats: WsiRenderStats) => void;\n\tprivate readonly onTileError?: (event: WsiTileErrorEvent) => void;\n\tprivate readonly onContextLost?: () => void;\n\tprivate readonly onContextRestored?: () => void;\n\tprivate readonly resizeObserver: ResizeObserver;\n\tprivate tileProgram: TileVertexProgram;\n\tprivate pointProgram: PointProgram;\n\tprivate readonly tileScheduler: TileScheduler;\n\n\tprivate authToken: string;\n\tprivate destroyed = false;\n\tprivate contextLost = false;\n\tprivate frame: number | null = null;\n\tprivate frameSerial = 0;\n\tprivate dragging = false;\n\tprivate interactionMode: \"none\" | \"pan\" | \"rotate\" = \"none\";\n\tprivate rotateLastAngleRad: number | null = null;\n\tprivate pointerId: number | null = null;\n\tprivate lastPointerX = 0;\n\tprivate lastPointerY = 0;\n\tprivate interactionLocked = false;\n\tprivate ctrlDragRotate = true;\n\tprivate rotationDragSensitivityDegPerPixel = 0.35;\n\tprivate maxCacheTiles: number;\n\tprivate fitZoom = 1;\n\tprivate minZoom = 1e-6;\n\tprivate maxZoom = 1;\n\tprivate currentTier = 0;\n\tprivate pointCount = 0;\n\tprivate usePointIndices = false;\n\tprivate pointBuffersDirty = true;\n\tprivate pointPaletteSize = 1;\n\tprivate pointSizeStops: PointSizeStop[] = clonePointSizeStops(DEFAULT_POINT_SIZE_STOPS);\n\tprivate lastPointData: WsiPointData | null = null;\n\tprivate lastPointPalette: Uint8Array | null = null;\n\tprivate cache = new Map<string, CachedTile>();\n\n\tprivate readonly boundPointerDown: (event: PointerEvent) => void;\n\tprivate readonly boundPointerMove: (event: PointerEvent) => void;\n\tprivate readonly boundPointerUp: (event: PointerEvent) => void;\n\tprivate readonly boundWheel: (event: WheelEvent) => void;\n\tprivate readonly boundDoubleClick: (event: MouseEvent) => void;\n\tprivate readonly boundContextMenu: (event: MouseEvent) => void;\n\tprivate readonly boundContextLost: (event: Event) => void;\n\tprivate readonly boundContextRestored: (event: Event) => void;\n\n\tconstructor(\n\t\tcanvas: HTMLCanvasElement,\n\t\tsource: WsiImageSource,\n\t\toptions: WsiTileRendererOptions = {},\n\t) {\n\t\tthis.canvas = canvas;\n\t\tthis.source = source;\n\t\tthis.onViewStateChange = options.onViewStateChange;\n\t\tthis.onStats = options.onStats;\n\t\tthis.onTileError = options.onTileError;\n\t\tthis.onContextLost = options.onContextLost;\n\t\tthis.onContextRestored = options.onContextRestored;\n\t\tthis.authToken = options.authToken ?? \"\";\n\t\tthis.maxCacheTiles = Math.max(32, Math.floor(options.maxCacheTiles ?? 320));\n\t\tthis.ctrlDragRotate = options.ctrlDragRotate ?? true;\n\t\tthis.rotationDragSensitivityDegPerPixel =\n\t\t\ttypeof options.rotationDragSensitivityDegPerPixel === \"number\" &&\n\t\t\tNumber.isFinite(options.rotationDragSensitivityDegPerPixel)\n\t\t\t\t? Math.max(0, options.rotationDragSensitivityDegPerPixel)\n\t\t\t\t: DEFAULT_ROTATION_DRAG_SENSITIVITY;\n\t\tthis.pointSizeStops = normalizePointSizeStops(options.pointSizeByZoom);\n\n\t\tconst gl = canvas.getContext(\"webgl2\", {\n\t\t\talpha: false,\n\t\t\tantialias: false,\n\t\t\tdepth: false,\n\t\t\tstencil: false,\n\t\t\tpowerPreference: \"high-performance\",\n\t\t});\n\t\tif (!gl) {\n\t\t\tthrow new Error(\"WebGL2 not supported\");\n\t\t}\n\t\tthis.gl = gl;\n\n\t\tthis.tileProgram = this.initTileProgram();\n\t\tthis.pointProgram = this.initPointProgram();\n\t\tthis.tileScheduler = new TileScheduler({\n\t\t\tauthToken: this.authToken,\n\t\t\tmaxConcurrency: options.tileScheduler?.maxConcurrency ?? 12,\n\t\t\tmaxRetries: options.tileScheduler?.maxRetries ?? 2,\n\t\t\tretryBaseDelayMs: options.tileScheduler?.retryBaseDelayMs ?? 120,\n\t\t\tretryMaxDelayMs: options.tileScheduler?.retryMaxDelayMs ?? 1200,\n\t\t\tonTileLoad: (tile, bitmap) => this.handleTileLoaded(tile, bitmap),\n\t\t\tonTileError: (tile, error, attemptCount) => {\n\t\t\t\tthis.onTileError?.({ tile, error, attemptCount });\n\t\t\t\tconsole.warn(\"tile load failed\", tile.url, error);\n\t\t\t},\n\t\t});\n\n\t\tthis.resizeObserver = new ResizeObserver(() => this.resize());\n\t\tthis.resizeObserver.observe(canvas);\n\n\t\tthis.boundPointerDown = (event: PointerEvent) => this.onPointerDown(event);\n\t\tthis.boundPointerMove = (event: PointerEvent) => this.onPointerMove(event);\n\t\tthis.boundPointerUp = (event: PointerEvent) => this.onPointerUp(event);\n\t\tthis.boundWheel = (event: WheelEvent) => this.onWheel(event);\n\t\tthis.boundDoubleClick = (event: MouseEvent) => this.onDoubleClick(event);\n\t\tthis.boundContextMenu = (event: MouseEvent) => this.onContextMenu(event);\n\t\tthis.boundContextLost = (event: Event) => this.onWebGlContextLost(event);\n\t\tthis.boundContextRestored = (event: Event) =>\n\t\t\tthis.onWebGlContextRestored(event);\n\n\t\tcanvas.addEventListener(\"pointerdown\", this.boundPointerDown);\n\t\tcanvas.addEventListener(\"pointermove\", this.boundPointerMove);\n\t\tcanvas.addEventListener(\"pointerup\", this.boundPointerUp);\n\t\tcanvas.addEventListener(\"pointercancel\", this.boundPointerUp);\n\t\tcanvas.addEventListener(\"wheel\", this.boundWheel, { passive: false });\n\t\tcanvas.addEventListener(\"dblclick\", this.boundDoubleClick);\n\t\tcanvas.addEventListener(\"contextmenu\", this.boundContextMenu);\n\t\tcanvas.addEventListener(\"webglcontextlost\", this.boundContextLost);\n\t\tcanvas.addEventListener(\"webglcontextrestored\", this.boundContextRestored);\n\n\t\tthis.fitToImage();\n\t\tthis.resize();\n\t}\n\n\tsetAuthToken(token: string): void {\n\t\tthis.authToken = String(token ?? \"\");\n\t\tthis.tileScheduler.setAuthToken(this.authToken);\n\t}\n\n\tsetViewState(next: Partial<WsiViewState>): void {\n\t\tconst normalized: Partial<WsiViewState> = { ...next };\n\t\tif (typeof normalized.zoom === \"number\") {\n\t\t\tnormalized.zoom = clamp(normalized.zoom, this.minZoom, this.maxZoom);\n\t\t}\n\t\tthis.camera.setViewState(normalized);\n\t\tthis.clampViewState();\n\t\tthis.emitViewState();\n\t\tthis.requestRender();\n\t}\n\n\tgetViewState(): WsiViewState {\n\t\treturn this.camera.getViewState();\n\t}\n\n\tsetPointPalette(colors: Uint8Array | null | undefined): void {\n\t\tif (!colors || colors.length === 0) {\n\t\t\tthis.lastPointPalette = null;\n\t\t\treturn;\n\t\t}\n\t\tthis.lastPointPalette = new Uint8Array(colors);\n\t\tif (this.contextLost || this.gl.isContextLost()) return;\n\t\tconst gl = this.gl;\n\t\tconst paletteSize = Math.max(1, Math.floor(this.lastPointPalette.length / 4));\n\t\tthis.pointPaletteSize = paletteSize;\n\t\tgl.bindTexture(gl.TEXTURE_2D, this.pointProgram.paletteTexture);\n\t\tgl.texImage2D(\n\t\t\tgl.TEXTURE_2D,\n\t\t\t0,\n\t\t\tgl.RGBA,\n\t\t\tpaletteSize,\n\t\t\t1,\n\t\t\t0,\n\t\t\tgl.RGBA,\n\t\t\tgl.UNSIGNED_BYTE,\n\t\t\tthis.lastPointPalette,\n\t\t);\n\t\tgl.bindTexture(gl.TEXTURE_2D, null);\n\t\tthis.requestRender();\n\t}\n\n\tsetPointData(points: WsiPointData | null | undefined): void {\n\t\tif (!points || !points.count || !points.positions || !points.paletteIndices) {\n\t\t\tthis.lastPointData = null;\n\t\t\tthis.pointCount = 0;\n\t\t\tthis.usePointIndices = false;\n\t\t\tthis.requestRender();\n\t\t\treturn;\n\t\t}\n\n\t\tconst safeCount = Math.max(\n\t\t\t0,\n\t\t\tMath.min(\n\t\t\t\tpoints.count,\n\t\t\t\tMath.floor(points.positions.length / 2),\n\t\t\t\tpoints.paletteIndices.length,\n\t\t\t),\n\t\t);\n\t\tconst nextPositions = points.positions.subarray(0, safeCount * 2);\n\t\tconst nextPaletteIndices = points.paletteIndices.subarray(0, safeCount);\n\t\tconst hasDrawIndices = points.drawIndices instanceof Uint32Array;\n\t\tconst nextDrawIndices = hasDrawIndices\n\t\t\t? this.sanitizeDrawIndices(points.drawIndices as Uint32Array, safeCount)\n\t\t\t: null;\n\t\tconst prev = this.lastPointData;\n\t\tlet geometryChanged =\n\t\t\tthis.pointBuffersDirty ||\n\t\t\t!prev ||\n\t\t\tprev.count !== safeCount ||\n\t\t\t!isSameArrayView(prev.positions, nextPositions) ||\n\t\t\t!isSameArrayView(prev.paletteIndices, nextPaletteIndices);\n\t\tlet drawIndicesChanged =\n\t\t\tthis.pointBuffersDirty ||\n\t\t\t(hasDrawIndices &&\n\t\t\t\t(!prev?.drawIndices ||\n\t\t\t\t\t!isSameArrayView(prev.drawIndices, nextDrawIndices))) ||\n\t\t\t(!hasDrawIndices && !!prev?.drawIndices);\n\n\t\tthis.lastPointData = {\n\t\t\tcount: safeCount,\n\t\t\tpositions: nextPositions,\n\t\t\tpaletteIndices: nextPaletteIndices,\n\t\t\tdrawIndices: hasDrawIndices ? nextDrawIndices ?? undefined : undefined,\n\t\t};\n\t\tif (this.contextLost || this.gl.isContextLost()) return;\n\n\t\tconst gl = this.gl;\n\t\tif (geometryChanged) {\n\t\t\tgl.bindBuffer(gl.ARRAY_BUFFER, this.pointProgram.posBuffer);\n\t\t\tgl.bufferData(gl.ARRAY_BUFFER, this.lastPointData.positions, gl.STATIC_DRAW);\n\n\t\t\tgl.bindBuffer(gl.ARRAY_BUFFER, this.pointProgram.termBuffer);\n\t\t\tgl.bufferData(\n\t\t\t\tgl.ARRAY_BUFFER,\n\t\t\t\tthis.lastPointData.paletteIndices,\n\t\t\t\tgl.STATIC_DRAW,\n\t\t\t);\n\t\t\tgl.bindBuffer(gl.ARRAY_BUFFER, null);\n\t\t}\n\n\t\tif (hasDrawIndices && drawIndicesChanged) {\n\t\t\tgl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.pointProgram.indexBuffer);\n\t\t\tgl.bufferData(\n\t\t\t\tgl.ELEMENT_ARRAY_BUFFER,\n\t\t\t\tnextDrawIndices ?? new Uint32Array(0),\n\t\t\t\tgl.DYNAMIC_DRAW,\n\t\t\t);\n\t\t\tgl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);\n\t\t}\n\n\t\tthis.usePointIndices = hasDrawIndices;\n\t\tthis.pointCount = hasDrawIndices\n\t\t\t? (nextDrawIndices?.length ?? 0)\n\t\t\t: this.lastPointData.count;\n\t\tif (geometryChanged || drawIndicesChanged) {\n\t\t\tthis.pointBuffersDirty = false;\n\t\t}\n\t\tthis.requestRender();\n\t}\n\n\tprivate sanitizeDrawIndices(\n\t\tdrawIndices: Uint32Array,\n\t\tmaxExclusive: number,\n\t): Uint32Array {\n\t\tif (maxExclusive <= 0 || drawIndices.length === 0) {\n\t\t\treturn new Uint32Array(0);\n\t\t}\n\n\t\tlet validCount = drawIndices.length;\n\t\tfor (let i = 0; i < drawIndices.length; i += 1) {\n\t\t\tif (drawIndices[i] < maxExclusive) continue;\n\t\t\tvalidCount -= 1;\n\t\t}\n\t\tif (validCount === drawIndices.length) {\n\t\t\treturn drawIndices;\n\t\t}\n\t\tif (validCount <= 0) {\n\t\t\treturn new Uint32Array(0);\n\t\t}\n\n\t\tconst filtered = new Uint32Array(validCount);\n\t\tlet cursor = 0;\n\t\tfor (let i = 0; i < drawIndices.length; i += 1) {\n\t\t\tconst idx = drawIndices[i];\n\t\t\tif (idx >= maxExclusive) continue;\n\t\t\tfiltered[cursor] = idx;\n\t\t\tcursor += 1;\n\t\t}\n\t\treturn filtered;\n\t}\n\n\tsetInteractionLock(locked: boolean): void {\n\t\tconst next = Boolean(locked);\n\t\tif (this.interactionLocked === next) return;\n\t\tthis.interactionLocked = next;\n\t\tif (next) this.cancelDrag();\n\t}\n\n\tsetPointSizeByZoom(pointSizeByZoom: PointSizeByZoom | null | undefined): void {\n\t\tconst nextStops = normalizePointSizeStops(pointSizeByZoom);\n\t\tif (arePointSizeStopsEqual(this.pointSizeStops, nextStops)) return;\n\t\tthis.pointSizeStops = nextStops;\n\t\tthis.requestRender();\n\t}\n\n\tcancelDrag(): void {\n\t\tif (this.pointerId !== null && this.canvas.hasPointerCapture(this.pointerId)) {\n\t\t\ttry {\n\t\t\t\tthis.canvas.releasePointerCapture(this.pointerId);\n\t\t\t} catch {\n\t\t\t\t// noop\n\t\t\t}\n\t\t}\n\t\tthis.dragging = false;\n\t\tthis.interactionMode = \"none\";\n\t\tthis.rotateLastAngleRad = null;\n\t\tthis.pointerId = null;\n\t\tthis.canvas.classList.remove(\"dragging\");\n\t}\n\n\tprivate getPointerAngleRad(clientX: number, clientY: number): number {\n\t\tconst rect = this.canvas.getBoundingClientRect();\n\t\tconst x = clientX - rect.left - rect.width * 0.5;\n\t\tconst y = clientY - rect.top - rect.height * 0.5;\n\t\treturn Math.atan2(y, x);\n\t}\n\n\tscreenToWorld(clientX: number, clientY: number): [number, number] {\n\t\tconst rect = this.canvas.getBoundingClientRect();\n\t\tconst sx = clientX - rect.left;\n\t\tconst sy = clientY - rect.top;\n\t\treturn this.camera.screenToWorld(sx, sy);\n\t}\n\n\tworldToScreen(worldX: number, worldY: number): [number, number] {\n\t\treturn this.camera.worldToScreen(worldX, worldY);\n\t}\n\n\tsetViewCenter(worldX: number, worldY: number): void {\n\t\tif (!Number.isFinite(worldX) || !Number.isFinite(worldY)) return;\n\t\tthis.camera.setCenter(worldX, worldY);\n\t\tthis.clampViewState();\n\t\tthis.emitViewState();\n\t\tthis.requestRender();\n\t}\n\n\tgetViewCorners(): [WorldPoint, WorldPoint, WorldPoint, WorldPoint] {\n\t\treturn this.camera.getViewCorners();\n\t}\n\n\tresetRotation(): void {\n\t\tconst state = this.camera.getViewState();\n\t\tif (Math.abs(state.rotationDeg) < 1e-6) return;\n\t\tthis.camera.setViewState({ rotationDeg: 0 });\n\t\tthis.clampViewState();\n\t\tthis.emitViewState();\n\t\tthis.requestRender();\n\t}\n\n\tgetPointSizeByZoom(): number {\n\t\tconst zoom = Math.max(1e-6, this.camera.getViewState().zoom);\n\t\tconst continuousZoom = this.source.maxTierZoom + Math.log2(zoom);\n\t\tconst size = resolvePointSizeByZoomStops(continuousZoom, this.pointSizeStops);\n\t\treturn clamp(size, MIN_POINT_SIZE_PX, MAX_POINT_SIZE_PX);\n\t}\n\n\tfitToImage(): void {\n\t\tconst rect = this.canvas.getBoundingClientRect();\n\t\tconst vw = Math.max(1, rect.width || 1);\n\t\tconst vh = Math.max(1, rect.height || 1);\n\n\t\tconst zoom = Math.min(vw / this.source.width, vh / this.source.height);\n\t\tconst safeZoom = Number.isFinite(zoom) && zoom > 0 ? zoom : 1;\n\n\t\tthis.fitZoom = safeZoom;\n\t\tthis.minZoom = Math.max(this.fitZoom * 0.5, 1e-6);\n\t\tthis.maxZoom = Math.max(1, this.fitZoom * 8);\n\t\tif (this.minZoom > this.maxZoom) {\n\t\t\tthis.minZoom = this.maxZoom;\n\t\t}\n\n\t\tconst visibleWorldW = vw / safeZoom;\n\t\tconst visibleWorldH = vh / safeZoom;\n\n\t\tthis.camera.setViewState({\n\t\t\tzoom: clamp(safeZoom, this.minZoom, this.maxZoom),\n\t\t\toffsetX: (this.source.width - visibleWorldW) * 0.5,\n\t\t\toffsetY: (this.source.height - visibleWorldH) * 0.5,\n\t\t\trotationDeg: 0,\n\t\t});\n\n\t\tthis.clampViewState();\n\t\tthis.emitViewState();\n\t\tthis.requestRender();\n\t}\n\n\tzoomBy(factor: number, screenX: number, screenY: number): void {\n\t\tconst state = this.camera.getViewState();\n\t\tconst nextZoom = clamp(state.zoom * factor, this.minZoom, this.maxZoom);\n\t\tif (nextZoom === state.zoom) return;\n\n\t\tconst [worldX, worldY] = this.camera.screenToWorld(screenX, screenY);\n\n\t\tthis.camera.setViewState({ zoom: nextZoom });\n\n\t\tconst vp = this.camera.getViewport();\n\t\tconst dx = screenX - vp.width * 0.5;\n\t\tconst dy = screenY - vp.height * 0.5;\n\t\tconst rad = toRadians(this.camera.getViewState().rotationDeg);\n\t\tconst cos = Math.cos(rad);\n\t\tconst sin = Math.sin(rad);\n\t\tconst worldDx = (dx / nextZoom) * cos - (dy / nextZoom) * sin;\n\t\tconst worldDy = (dx / nextZoom) * sin + (dy / nextZoom) * cos;\n\t\tthis.camera.setCenter(worldX - worldDx, worldY - worldDy);\n\n\t\tthis.clampViewState();\n\t\tthis.emitViewState();\n\t\tthis.requestRender();\n\t}\n\n\tclampViewState(): void {\n\t\tconst bounds = this.getViewBounds();\n\t\tconst visibleW = Math.max(1e-6, bounds[2] - bounds[0]);\n\t\tconst visibleH = Math.max(1e-6, bounds[3] - bounds[1]);\n\t\tconst marginX = visibleW * 0.2;\n\t\tconst marginY = visibleH * 0.2;\n\n\t\tconst [centerX, centerY] = this.camera.getCenter();\n\t\tconst halfW = visibleW * 0.5;\n\t\tconst halfH = visibleH * 0.5;\n\n\t\tconst minCenterX = halfW - marginX;\n\t\tconst maxCenterX = this.source.width - halfW + marginX;\n\t\tconst minCenterY = halfH - marginY;\n\t\tconst maxCenterY = this.source.height - halfH + marginY;\n\n\t\tconst nextCenterX =\n\t\t\tminCenterX <= maxCenterX\n\t\t\t\t? clamp(centerX, minCenterX, maxCenterX)\n\t\t\t\t: this.source.width * 0.5;\n\t\tconst nextCenterY =\n\t\t\tminCenterY <= maxCenterY\n\t\t\t\t? clamp(centerY, minCenterY, maxCenterY)\n\t\t\t\t: this.source.height * 0.5;\n\n\t\tthis.camera.setCenter(nextCenterX, nextCenterY);\n\t}\n\n\temitViewState(): void {\n\t\tthis.onViewStateChange?.(this.camera.getViewState());\n\t}\n\n\tselectTier(): number {\n\t\tconst zoom = Math.max(1e-6, this.camera.getViewState().zoom);\n\t\tconst rawTier = this.source.maxTierZoom + Math.log2(zoom);\n\t\treturn clamp(Math.floor(rawTier), 0, this.source.maxTierZoom);\n\t}\n\n\tgetViewBounds(): Bounds {\n\t\tconst corners = this.camera.getViewCorners();\n\t\tlet minX = Infinity;\n\t\tlet minY = Infinity;\n\t\tlet maxX = -Infinity;\n\t\tlet maxY = -Infinity;\n\t\tfor (const [x, y] of corners) {\n\t\t\tif (x < minX) minX = x;\n\t\t\tif (x > maxX) maxX = x;\n\t\t\tif (y < minY) minY = y;\n\t\t\tif (y > maxY) maxY = y;\n\t\t}\n\t\treturn [minX, minY, maxX, maxY];\n\t}\n\n\tintersectsBounds(a: Bounds, b: Bounds): boolean {\n\t\treturn !(a[2] <= b[0] || a[0] >= b[2] || a[3] <= b[1] || a[1] >= b[3]);\n\t}\n\n\tgetVisibleTiles(): ScheduledTile[] {\n\t\tconst tier = this.selectTier();\n\t\tthis.currentTier = tier;\n\n\t\tconst viewBounds = this.getViewBounds();\n\n\t\tconst levelScale = Math.pow(2, this.source.maxTierZoom - tier);\n\t\tconst levelWidth = Math.ceil(this.source.width / levelScale);\n\t\tconst levelHeight = Math.ceil(this.source.height / levelScale);\n\n\t\tconst tilesX = Math.max(1, Math.ceil(levelWidth / this.source.tileSize));\n\t\tconst tilesY = Math.max(1, Math.ceil(levelHeight / this.source.tileSize));\n\n\t\tconst viewMinX = viewBounds[0];\n\t\tconst viewMinY = viewBounds[1];\n\t\tconst viewMaxX = viewBounds[2];\n\t\tconst viewMaxY = viewBounds[3];\n\n\t\tconst minTileX = clamp(\n\t\t\tMath.floor(viewMinX / levelScale / this.source.tileSize),\n\t\t\t0,\n\t\t\ttilesX - 1,\n\t\t);\n\t\tconst maxTileX = clamp(\n\t\t\tMath.floor((viewMaxX - 1) / levelScale / this.source.tileSize),\n\t\t\t0,\n\t\t\ttilesX - 1,\n\t\t);\n\t\tconst minTileY = clamp(\n\t\t\tMath.floor(viewMinY / levelScale / this.source.tileSize),\n\t\t\t0,\n\t\t\ttilesY - 1,\n\t\t);\n\t\tconst maxTileY = clamp(\n\t\t\tMath.floor((viewMaxY - 1) / levelScale / this.source.tileSize),\n\t\t\t0,\n\t\t\ttilesY - 1,\n\t\t);\n\n\t\tif (minTileX > maxTileX || minTileY > maxTileY) {\n\t\t\treturn [];\n\t\t}\n\n\t\tconst centerTileX = (viewMinX + viewMaxX) * 0.5 / levelScale / this.source.tileSize;\n\t\tconst centerTileY = (viewMinY + viewMaxY) * 0.5 / levelScale / this.source.tileSize;\n\n\t\tconst visible: ScheduledTile[] = [];\n\t\tfor (let y = minTileY; y <= maxTileY; y += 1) {\n\t\t\tfor (let x = minTileX; x <= maxTileX; x += 1) {\n\t\t\t\tconst left = x * this.source.tileSize * levelScale;\n\t\t\t\tconst top = y * this.source.tileSize * levelScale;\n\t\t\t\tconst right = Math.min((x + 1) * this.source.tileSize, levelWidth) * levelScale;\n\t\t\t\tconst bottom = Math.min((y + 1) * this.source.tileSize, levelHeight) * levelScale;\n\n\t\t\t\tconst dx = x - centerTileX;\n\t\t\t\tconst dy = y - centerTileY;\n\t\t\t\tvisible.push({\n\t\t\t\t\tkey: `${tier}/${x}/${y}`,\n\t\t\t\t\ttier,\n\t\t\t\t\tx,\n\t\t\t\t\ty,\n\t\t\t\t\tbounds: [left, top, right, bottom],\n\t\t\t\t\tdistance2: dx * dx + dy * dy,\n\t\t\t\t\turl: toTileUrl(this.source, tier, x, y),\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\tvisible.sort((a, b) => a.distance2 - b.distance2);\n\t\treturn visible;\n\t}\n\n\ttrimCache(): void {\n\t\tif (this.cache.size <= this.maxCacheTiles) return;\n\n\t\tconst entries = Array.from(this.cache.entries());\n\t\tentries.sort((a, b) => a[1].lastUsed - b[1].lastUsed);\n\n\t\tconst removeCount = this.cache.size - this.maxCacheTiles;\n\t\tfor (let i = 0; i < removeCount; i += 1) {\n\t\t\tconst [key, value] = entries[i];\n\t\t\tthis.gl.deleteTexture(value.texture);\n\t\t\tthis.cache.delete(key);\n\t\t}\n\t}\n\n\trender(): void {\n\t\tif (this.destroyed || this.contextLost || this.gl.isContextLost()) return;\n\t\tconst frameStartMs = nowMs();\n\t\tthis.frameSerial += 1;\n\n\t\tconst gl = this.gl;\n\t\tconst tileProgram = this.tileProgram;\n\t\tconst pointProgram = this.pointProgram;\n\n\t\tgl.clearColor(0.03, 0.06, 0.1, 1);\n\t\tgl.clear(gl.COLOR_BUFFER_BIT);\n\n\t\tconst visible = this.getVisibleTiles();\n\t\tconst viewBounds = this.getViewBounds();\n\t\tconst visibleKeys = new Set(visible.map((tile) => tile.key));\n\n\t\tgl.useProgram(tileProgram.program);\n\t\tgl.bindVertexArray(tileProgram.vao);\n\t\tgl.uniformMatrix3fv(tileProgram.uCamera, false, this.camera.getMatrix());\n\t\tgl.uniform1i(tileProgram.uTexture, 0);\n\n\t\tconst fallbackTiles: CachedTile[] = [];\n\t\tfor (const [, cached] of this.cache) {\n\t\t\tif (visibleKeys.has(cached.key)) continue;\n\t\t\tif (!this.intersectsBounds(cached.bounds, viewBounds)) continue;\n\t\t\tfallbackTiles.push(cached);\n\t\t}\n\n\t\tfallbackTiles.sort((a, b) => a.tier - b.tier);\n\t\tfor (const cached of fallbackTiles) {\n\t\t\tcached.lastUsed = this.frameSerial;\n\t\t\tgl.activeTexture(gl.TEXTURE0);\n\t\t\tgl.bindTexture(gl.TEXTURE_2D, cached.texture);\n\t\t\tgl.uniform4f(\n\t\t\t\ttileProgram.uBounds,\n\t\t\t\tcached.bounds[0],\n\t\t\t\tcached.bounds[1],\n\t\t\t\tcached.bounds[2],\n\t\t\t\tcached.bounds[3],\n\t\t\t);\n\t\t\tgl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);\n\t\t}\n\n\t\tlet renderedTiles = 0;\n\t\tconst missingTiles: ScheduledTile[] = [];\n\t\tfor (const tile of visible) {\n\t\t\tconst cached = this.cache.get(tile.key);\n\t\t\tif (!cached) {\n\t\t\t\tmissingTiles.push(tile);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tcached.lastUsed = this.frameSerial;\n\t\t\tgl.activeTexture(gl.TEXTURE0);\n\t\t\tgl.bindTexture(gl.TEXTURE_2D, cached.texture);\n\t\t\tgl.uniform4f(\n\t\t\t\ttileProgram.uBounds,\n\t\t\t\tcached.bounds[0],\n\t\t\t\tcached.bounds[1],\n\t\t\t\tcached.bounds[2],\n\t\t\t\tcached.bounds[3],\n\t\t\t);\n\t\t\tgl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);\n\t\t\trenderedTiles += 1;\n\t\t}\n\t\tthis.tileScheduler.schedule(missingTiles);\n\n\t\tgl.bindTexture(gl.TEXTURE_2D, null);\n\t\tgl.bindVertexArray(null);\n\n\t\tlet renderedPoints = 0;\n\t\tif (this.pointCount > 0) {\n\t\t\tgl.enable(gl.BLEND);\n\t\t\tgl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);\n\t\t\tgl.useProgram(pointProgram.program);\n\t\t\tgl.bindVertexArray(pointProgram.vao);\n\t\t\tgl.uniformMatrix3fv(pointProgram.uCamera, false, this.camera.getMatrix());\n\t\t\tgl.uniform1f(pointProgram.uPointSize, this.getPointSizeByZoom());\n\t\t\tgl.uniform1f(pointProgram.uPaletteSize, this.pointPaletteSize);\n\t\t\tgl.uniform1i(pointProgram.uPalette, 1);\n\t\t\tgl.activeTexture(gl.TEXTURE1);\n\t\t\tgl.bindTexture(gl.TEXTURE_2D, pointProgram.paletteTexture);\n\t\t\tif (this.usePointIndices) {\n\t\t\t\tgl.drawElements(gl.POINTS, this.pointCount, gl.UNSIGNED_INT, 0);\n\t\t\t} else {\n\t\t\t\tgl.drawArrays(gl.POINTS, 0, this.pointCount);\n\t\t\t}\n\t\t\tgl.bindTexture(gl.TEXTURE_2D, null);\n\t\t\tgl.bindVertexArray(null);\n\t\t\trenderedPoints = this.pointCount;\n\t\t}\n\n\t\tif (this.onStats) {\n\t\t\tconst schedulerStats = this.tileScheduler.getSnapshot();\n\t\t\tconst cacheHits = renderedTiles;\n\t\t\tconst cacheMisses = missingTiles.length;\n\t\t\tconst drawCalls =\n\t\t\t\tfallbackTiles.length + renderedTiles + (renderedPoints > 0 ? 1 : 0);\n\t\t\tthis.onStats({\n\t\t\t\ttier: this.currentTier,\n\t\t\t\tvisible: visible.length,\n\t\t\t\trendered: renderedTiles,\n\t\t\t\tpoints: renderedPoints,\n\t\t\t\tfallback: fallbackTiles.length,\n\t\t\t\tcache: this.cache.size,\n\t\t\t\tinflight: schedulerStats.inflight,\n\t\t\t\tqueued: schedulerStats.queued,\n\t\t\t\tretries: schedulerStats.retries,\n\t\t\t\tfailed: schedulerStats.failed,\n\t\t\t\taborted: schedulerStats.aborted,\n\t\t\t\tcacheHits,\n\t\t\t\tcacheMisses,\n\t\t\t\tdrawCalls,\n\t\t\t\tframeMs: nowMs() - frameStartMs,\n\t\t\t});\n\t\t}\n\t}\n\n\trequestRender(): void {\n\t\tif (\n\t\t\tthis.frame !== null ||\n\t\t\tthis.destroyed ||\n\t\t\tthis.contextLost ||\n\t\t\tthis.gl.isContextLost()\n\t\t)\n\t\t\treturn;\n\t\tthis.frame = requestAnimationFrame(() => {\n\t\t\tthis.frame = null;\n\t\t\tthis.render();\n\t\t});\n\t}\n\n\tresize(): void {\n\t\tconst rect = this.canvas.getBoundingClientRect();\n\t\tconst cssW = Math.max(1, rect.width || this.canvas.clientWidth || 1);\n\t\tconst cssH = Math.max(1, rect.height || this.canvas.clientHeight || 1);\n\t\tconst dpr = Math.max(1, window.devicePixelRatio || 1);\n\n\t\tconst pixelW = Math.max(1, Math.round(cssW * dpr));\n\t\tconst pixelH = Math.max(1, Math.round(cssH * dpr));\n\n\t\tif (this.canvas.width !== pixelW || this.canvas.height !== pixelH) {\n\t\t\tthis.canvas.width = pixelW;\n\t\t\tthis.canvas.height = pixelH;\n\t\t}\n\n\t\tthis.camera.setViewport(cssW, cssH);\n\t\tthis.gl.viewport(0, 0, pixelW, pixelH);\n\t\tthis.requestRender();\n\t}\n\n\tonPointerDown(event: PointerEvent): void {\n\t\tif (this.interactionLocked) return;\n\t\tconst wantsRotate = this.ctrlDragRotate && (event.ctrlKey || event.metaKey);\n\t\tconst allowButton = event.button === 0 || (wantsRotate && event.button === 2);\n\t\tif (!allowButton) return;\n\t\tif (wantsRotate) {\n\t\t\tevent.preventDefault();\n\t\t}\n\t\tthis.dragging = true;\n\t\tthis.interactionMode =\n\t\t\twantsRotate ? \"rotate\" : \"pan\";\n\t\tthis.pointerId = event.pointerId;\n\t\tthis.lastPointerX = event.clientX;\n\t\tthis.lastPointerY = event.clientY;\n\t\tthis.rotateLastAngleRad =\n\t\t\tthis.interactionMode === \"rotate\"\n\t\t\t\t? this.getPointerAngleRad(event.clientX, event.clientY)\n\t\t\t\t: null;\n\t\tthis.canvas.classList.add(\"dragging\");\n\t\tthis.canvas.setPointerCapture(event.pointerId);\n\t}\n\n\tonPointerMove(event: PointerEvent): void {\n\t\tif (this.interactionLocked) return;\n\t\tif (!this.dragging || event.pointerId !== this.pointerId) return;\n\n\t\tconst dx = event.clientX - this.lastPointerX;\n\t\tconst dy = event.clientY - this.lastPointerY;\n\t\tthis.lastPointerX = event.clientX;\n\t\tthis.lastPointerY = event.clientY;\n\n\t\tif (this.interactionMode === \"rotate\") {\n\t\t\tconst nextAngle = this.getPointerAngleRad(event.clientX, event.clientY);\n\t\t\tconst prevAngle = this.rotateLastAngleRad;\n\t\t\tthis.rotateLastAngleRad = nextAngle;\n\t\t\tif (prevAngle !== null) {\n\t\t\t\tconst rawDelta = nextAngle - prevAngle;\n\t\t\t\tconst delta = Math.atan2(Math.sin(rawDelta), Math.cos(rawDelta));\n\n\t\t\t\tconst sensitivityScale =\n\t\t\t\t\tDEFAULT_ROTATION_DRAG_SENSITIVITY > 0\n\t\t\t\t\t\t? this.rotationDragSensitivityDegPerPixel /\n\t\t\t\t\t\t\tDEFAULT_ROTATION_DRAG_SENSITIVITY\n\t\t\t\t\t\t: 1;\n\t\t\t\tconst state = this.camera.getViewState();\n\t\t\t\tthis.camera.setViewState({\n\t\t\t\t\trotationDeg:\n\t\t\t\t\t\tstate.rotationDeg - ((delta * 180) / Math.PI) * sensitivityScale,\n\t\t\t\t});\n\t\t\t}\n\t\t} else {\n\t\t\tconst state = this.camera.getViewState();\n\t\t\tconst zoom = Math.max(1e-6, state.zoom);\n\t\t\tconst rad = toRadians(state.rotationDeg);\n\t\t\tconst cos = Math.cos(rad);\n\t\t\tconst sin = Math.sin(rad);\n\t\t\tconst worldDx = (dx * cos - dy * sin) / zoom;\n\t\t\tconst worldDy = (dx * sin + dy * cos) / zoom;\n\t\t\tthis.camera.setViewState({\n\t\t\t\toffsetX: state.offsetX - worldDx,\n\t\t\t\toffsetY: state.offsetY - worldDy,\n\t\t\t});\n\t\t}\n\n\t\tthis.clampViewState();\n\t\tthis.emitViewState();\n\t\tthis.requestRender();\n\t}\n\n\tonPointerUp(event: PointerEvent): void {\n\t\tif (this.interactionLocked) return;\n\t\tif (event.pointerId !== this.pointerId) return;\n\t\tthis.cancelDrag();\n\t}\n\n\tonWheel(event: WheelEvent): void {\n\t\tif (this.interactionLocked) {\n\t\t\tevent.preventDefault();\n\t\t\treturn;\n\t\t}\n\n\t\tevent.preventDefault();\n\t\tconst rect = this.canvas.getBoundingClientRect();\n\t\tconst x = event.clientX - rect.left;\n\t\tconst y = event.clientY - rect.top;\n\t\tconst factor = event.deltaY < 0 ? 1.12 : 0.89;\n\t\tthis.zoomBy(factor, x, y);\n\t}\n\n\tonDoubleClick(event: MouseEvent): void {\n\t\tif (this.interactionLocked) return;\n\t\tconst rect = this.canvas.getBoundingClientRect();\n\t\tconst x = event.clientX - rect.left;\n\t\tconst y = event.clientY - rect.top;\n\t\tthis.zoomBy(event.shiftKey ? 0.8 : 1.25, x, y);\n\t}\n\n\tonContextMenu(event: MouseEvent): void {\n\t\tif (this.dragging || event.ctrlKey || event.metaKey) {\n\t\t\tevent.preventDefault();\n\t\t}\n\t}\n\n\tprivate onWebGlContextLost(event: Event): void {\n\t\tevent.preventDefault();\n\t\tif (this.destroyed || this.contextLost) return;\n\t\tthis.contextLost = true;\n\t\tthis.pointBuffersDirty = true;\n\n\t\tif (this.frame !== null) {\n\t\t\tcancelAnimationFrame(this.frame);\n\t\t\tthis.frame = null;\n\t\t}\n\n\t\tthis.cancelDrag();\n\t\tthis.tileScheduler.clear();\n\t\tthis.cache.clear();\n\t\tthis.onContextLost?.();\n\t}\n\n\tprivate onWebGlContextRestored(_event: Event): void {\n\t\tif (this.destroyed) return;\n\t\tthis.contextLost = false;\n\t\tthis.cache.clear();\n\n\t\tthis.tileProgram = this.initTileProgram();\n\t\tthis.pointProgram = this.initPointProgram();\n\t\tthis.pointBuffersDirty = true;\n\n\t\tif (this.lastPointPalette && this.lastPointPalette.length > 0) {\n\t\t\tthis.setPointPalette(this.lastPointPalette);\n\t\t}\n\t\tif (this.lastPointData) {\n\t\t\tthis.setPointData(this.lastPointData);\n\t\t} else {\n\t\t\tthis.pointCount = 0;\n\t\t}\n\n\t\tthis.resize();\n\t\tthis.requestRender();\n\t\tthis.onContextRestored?.();\n\t}\n\n\tdestroy(): void {\n\t\tif (this.destroyed) return;\n\t\tthis.destroyed = true;\n\n\t\tif (this.frame !== null) {\n\t\t\tcancelAnimationFrame(this.frame);\n\t\t\tthis.frame = null;\n\t\t}\n\n\t\tthis.resizeObserver.disconnect();\n\t\tthis.canvas.removeEventListener(\"pointerdown\", this.boundPointerDown);\n\t\tthis.canvas.removeEventListener(\"pointermove\", this.boundPointerMove);\n\t\tthis.canvas.removeEventListener(\"pointerup\", this.boundPointerUp);\n\t\tthis.canvas.removeEventListener(\"pointercancel\", this.boundPointerUp);\n\t\tthis.canvas.removeEventListener(\"wheel\", this.boundWheel);\n\t\tthis.canvas.removeEventListener(\"dblclick\", this.boundDoubleClick);\n\t\tthis.canvas.removeEventListener(\"contextmenu\", this.boundContextMenu);\n\t\tthis.canvas.removeEventListener(\"webglcontextlost\", this.boundContextLost);\n\t\tthis.canvas.removeEventListener(\n\t\t\t\"webglcontextrestored\",\n\t\t\tthis.boundContextRestored,\n\t\t);\n\t\tthis.cancelDrag();\n\t\tthis.tileScheduler.destroy();\n\n\t\tif (!this.contextLost && !this.gl.isContextLost()) {\n\t\t\tfor (const [, value] of this.cache) {\n\t\t\t\tthis.gl.deleteTexture(value.texture);\n\t\t\t}\n\t\t\tthis.gl.deleteBuffer(this.tileProgram.vbo);\n\t\t\tthis.gl.deleteVertexArray(this.tileProgram.vao);\n\t\t\tthis.gl.deleteProgram(this.tileProgram.program);\n\n\t\t\tthis.gl.deleteBuffer(this.pointProgram.posBuffer);\n\t\t\tthis.gl.deleteBuffer(this.pointProgram.termBuffer);\n\t\t\tthis.gl.deleteBuffer(this.pointProgram.indexBuffer);\n\t\t\tthis.gl.deleteTexture(this.pointProgram.paletteTexture);\n\t\t\tthis.gl.deleteVertexArray(this.pointProgram.vao);\n\t\t\tthis.gl.deleteProgram(this.pointProgram.program);\n\t\t}\n\t\tthis.cache.clear();\n\t}\n\n\tprivate initTileProgram(): TileVertexProgram {\n\t\tconst gl = this.gl;\n\n\t\tconst vertex = `#version 300 es\n precision highp float;\n in vec2 aUnit;\n in vec2 aUv;\n uniform mat3 uCamera;\n uniform vec4 uBounds;\n out vec2 vUv;\n void main() {\n vec2 world = vec2(\n mix(uBounds.x, uBounds.z, aUnit.x),\n mix(uBounds.y, uBounds.w, aUnit.y)\n );\n vec3 clip = uCamera * vec3(world, 1.0);\n gl_Position = vec4(clip.xy, 0.0, 1.0);\n vUv = aUv;\n }`;\n\n\t\tconst fragment = `#version 300 es\n precision highp float;\n in vec2 vUv;\n uniform sampler2D uTexture;\n out vec4 outColor;\n void main() {\n outColor = texture(uTexture, vUv);\n }`;\n\n\t\tconst program = createProgram(gl, vertex, fragment);\n\t\tconst uCamera = requireUniformLocation(gl, program, \"uCamera\");\n\t\tconst uBounds = requireUniformLocation(gl, program, \"uBounds\");\n\t\tconst uTexture = requireUniformLocation(gl, program, \"uTexture\");\n\n\t\tconst vao = gl.createVertexArray();\n\t\tconst vbo = gl.createBuffer();\n\t\tif (!vao || !vbo) {\n\t\t\tthrow new Error(\"buffer allocation failed\");\n\t\t}\n\n\t\tgl.bindVertexArray(vao);\n\t\tgl.bindBuffer(gl.ARRAY_BUFFER, vbo);\n\t\tgl.bufferData(\n\t\t\tgl.ARRAY_BUFFER,\n\t\t\tnew Float32Array([0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1]),\n\t\t\tgl.STATIC_DRAW,\n\t\t);\n\n\t\tconst aUnit = gl.getAttribLocation(program, \"aUnit\");\n\t\tconst aUv = gl.getAttribLocation(program, \"aUv\");\n\t\tif (aUnit < 0 || aUv < 0) {\n\t\t\tthrow new Error(\"tile attribute lookup failed\");\n\t\t}\n\t\tgl.enableVertexAttribArray(aUnit);\n\t\tgl.enableVertexAttribArray(aUv);\n\t\tgl.vertexAttribPointer(aUnit, 2, gl.FLOAT, false, 16, 0);\n\t\tgl.vertexAttribPointer(aUv, 2, gl.FLOAT, false, 16, 8);\n\n\t\tgl.bindVertexArray(null);\n\t\tgl.bindBuffer(gl.ARRAY_BUFFER, null);\n\n\t\treturn { program, vao, vbo, uCamera, uBounds, uTexture };\n\t}\n\n\tprivate initPointProgram(): PointProgram {\n\t\tconst gl = this.gl;\n\n\t\tconst pointVertex = `#version 300 es\n precision highp float;\n in vec2 aPosition;\n in uint aTerm;\n uniform mat3 uCamera;\n uniform float uPointSize;\n flat out uint vTerm;\n void main() {\n vec3 clip = uCamera * vec3(aPosition, 1.0);\n gl_Position = vec4(clip.xy, 0.0, 1.0);\n gl_PointSize = uPointSize;\n vTerm = aTerm;\n }`;\n\n\t\tconst pointFragment = `#version 300 es\n precision highp float;\n flat in uint vTerm;\n uniform sampler2D uPalette;\n uniform float uPaletteSize;\n uniform float uPointSize;\n out vec4 outColor;\n void main() {\n vec2 pc = gl_PointCoord * 2.0 - 1.0;\n float r = length(pc);\n if (r > 1.0) discard;\n\n float idx = clamp(float(vTerm), 0.0, max(0.0, uPaletteSize - 1.0));\n vec2 uv = vec2((idx + 0.5) / uPaletteSize, 0.5);\n vec4 color = texture(uPalette, uv);\n if (color.a <= 0.0) discard;\n\n float ringWidth = clamp(3.0 / max(1.0, uPointSize), 0.12, 0.62);\n float innerRadius = 1.0 - ringWidth;\n float aa = 1.5 / max(1.0, uPointSize);\n\n float outerMask = 1.0 - smoothstep(1.0 - aa, 1.0 + aa, r);\n float innerMask = smoothstep(innerRadius - aa, innerRadius + aa, r);\n float alpha = outerMask * innerMask * color.a;\n if (alpha <= 0.001) discard;\n\n outColor = vec4(color.rgb * alpha, alpha);\n }`;\n\n\t\tconst program = createProgram(gl, pointVertex, pointFragment);\n\t\tconst uCamera = requireUniformLocation(gl, program, \"uCamera\");\n\t\tconst uPointSize = requireUniformLocation(gl, program, \"uPointSize\");\n\t\tconst uPalette = requireUniformLocation(gl, program, \"uPalette\");\n\t\tconst uPaletteSize = requireUniformLocation(gl, program, \"uPaletteSize\");\n\n\t\tconst vao = gl.createVertexArray();\n\t\tconst posBuffer = gl.createBuffer();\n\t\tconst termBuffer = gl.createBuffer();\n\t\tconst indexBuffer = gl.createBuffer();\n\t\tconst paletteTexture = gl.createTexture();\n\t\tif (!vao || !posBuffer || !termBuffer || !indexBuffer || !paletteTexture) {\n\t\t\tthrow new Error(\"point buffer allocation failed\");\n\t\t}\n\n\t\tgl.bindVertexArray(vao);\n\n\t\tgl.bindBuffer(gl.ARRAY_BUFFER, posBuffer);\n\t\tgl.bufferData(gl.ARRAY_BUFFER, 0, gl.DYNAMIC_DRAW);\n\t\tconst posLoc = gl.getAttribLocation(program, \"aPosition\");\n\t\tif (posLoc < 0) {\n\t\t\tthrow new Error(\"point position attribute not found\");\n\t\t}\n\t\tgl.enableVertexAttribArray(posLoc);\n\t\tgl.vertexAttribPointer(posLoc, 2, gl.FLOAT, false, 0, 0);\n\n\t\tgl.bindBuffer(gl.ARRAY_BUFFER, termBuffer);\n\t\tgl.bufferData(gl.ARRAY_BUFFER, 0, gl.DYNAMIC_DRAW);\n\t\tconst termLoc = gl.getAttribLocation(program, \"aTerm\");\n\t\tif (termLoc < 0) {\n\t\t\tthrow new Error(\"point term attribute not found\");\n\t\t}\n\t\tgl.enableVertexAttribArray(termLoc);\n\t\tgl.vertexAttribIPointer(termLoc, 1, gl.UNSIGNED_SHORT, 0, 0);\n\n\t\tgl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);\n\t\tgl.bufferData(gl.ELEMENT_ARRAY_BUFFER, 0, gl.DYNAMIC_DRAW);\n\n\t\tgl.bindVertexArray(null);\n\t\tgl.bindBuffer(gl.ARRAY_BUFFER, null);\n\t\tgl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);\n\n\t\tgl.bindTexture(gl.TEXTURE_2D, paletteTexture);\n\t\tgl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);\n\t\tgl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);\n\t\tgl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);\n\t\tgl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);\n\t\tgl.texImage2D(\n\t\t\tgl.TEXTURE_2D,\n\t\t\t0,\n\t\t\tgl.RGBA,\n\t\t\t1,\n\t\t\t1,\n\t\t\t0,\n\t\t\tgl.RGBA,\n\t\t\tgl.UNSIGNED_BYTE,\n\t\t\tnew Uint8Array([160, 160, 160, 255]),\n\t\t);\n\t\tgl.bindTexture(gl.TEXTURE_2D, null);\n\n\t\treturn {\n\t\t\tprogram,\n\t\t\tvao,\n\t\t\tposBuffer,\n\t\t\ttermBuffer,\n\t\t\tindexBuffer,\n\t\t\tpaletteTexture,\n\t\t\tuCamera,\n\t\t\tuPointSize,\n\t\t\tuPalette,\n\t\t\tuPaletteSize,\n\t\t};\n\t}\n\n\tprivate handleTileLoaded(tile: ScheduledTile, bitmap: ImageBitmap): void {\n\t\tif (this.destroyed || this.contextLost || this.gl.isContextLost()) {\n\t\t\tbitmap.close();\n\t\t\treturn;\n\t\t}\n\t\tif (this.cache.has(tile.key)) {\n\t\t\tbitmap.close();\n\t\t\treturn;\n\t\t}\n\n\t\tconst texture = this.createTextureFromBitmap(bitmap);\n\t\tbitmap.close();\n\t\tif (!texture) return;\n\n\t\tthis.cache.set(tile.key, {\n\t\t\tkey: tile.key,\n\t\t\ttexture,\n\t\t\tbounds: tile.bounds,\n\t\t\ttier: tile.tier,\n\t\t\tlastUsed: this.frameSerial,\n\t\t});\n\t\tthis.trimCache();\n\t\tthis.requestRender();\n\t}\n\n\tprivate createTextureFromBitmap(bitmap: ImageBitmap): WebGLTexture | null {\n\t\tif (this.contextLost || this.gl.isContextLost()) return null;\n\t\tconst gl = this.gl;\n\t\tconst texture = gl.createTexture();\n\t\tif (!texture) return null;\n\n\t\tgl.bindTexture(gl.TEXTURE_2D, texture);\n\t\tgl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1);\n\t\tgl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);\n\t\tgl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);\n\t\tgl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);\n\t\tgl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);\n\t\tgl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, bitmap);\n\t\tgl.bindTexture(gl.TEXTURE_2D, null);\n\t\treturn texture;\n\t}\n}\n","import { type CSSProperties, type MouseEvent as ReactMouseEvent, type MutableRefObject, type ReactNode, type PointerEvent as ReactPointerEvent, useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { filterPointDataByPolygons, type RoiPolygon } from \"../wsi/point-clip\";\nimport { filterPointDataByPolygonsHybrid } from \"../wsi/point-clip-hybrid\";\nimport { filterPointDataByPolygonsInWorker, type PointClipMode } from \"../wsi/point-clip-worker-client\";\nimport { computeRoiPointGroups, type RoiPointGroupStats } from \"../wsi/roi-term-stats\";\nimport type { WsiImageSource, WsiPointData, WsiRegion, WsiRenderStats, WsiViewState } from \"../wsi/types\";\nimport { type PointSizeByZoom, type WsiTileErrorEvent, WsiTileRenderer } from \"../wsi/wsi-tile-renderer\";\nimport type { BrushOptions, DrawCoordinate, DrawOverlayShape, DrawResult, DrawTool, PatchDrawResult, RegionLabelStyle, RegionStrokeStyle, RegionStrokeStyleResolver, StampOptions } from \"./draw-layer\";\nimport { DrawLayer } from \"./draw-layer\";\nimport { OverviewMap, type OverviewMapOptions } from \"./overview-map\";\n\nconst EMPTY_ROI_REGIONS: WsiRegion[] = [];\nconst EMPTY_ROI_POLYGONS: DrawCoordinate[][] = [];\nconst EMPTY_CLIPPED_POINTS: WsiPointData = {\n count: 0,\n positions: new Float32Array(0),\n paletteIndices: new Uint16Array(0),\n};\nconst POINT_HIT_RADIUS_SCALE = 0.65;\nconst MIN_POINT_HIT_RADIUS_PX = 4;\nconst MIN_POINT_HIT_GRID_SIZE = 24;\nconst MAX_POINT_HIT_GRID_SIZE = 1024;\nconst POINT_HIT_GRID_DENSITY_SCALE = 4;\n\nexport interface RegionHoverEvent {\n region: WsiRegion | null;\n regionId: string | number | null;\n regionIndex: number;\n coordinate: DrawCoordinate | null;\n}\n\nexport interface RegionClickEvent {\n region: WsiRegion;\n regionId: string | number;\n regionIndex: number;\n coordinate: DrawCoordinate;\n}\n\nexport interface PointHitEvent {\n index: number;\n id: number | null;\n coordinate: DrawCoordinate;\n pointCoordinate: DrawCoordinate;\n}\n\nexport interface PointClickEvent extends PointHitEvent {\n button: number;\n}\n\nexport interface PointHoverEvent {\n index: number | null;\n id: number | null;\n coordinate: DrawCoordinate | null;\n pointCoordinate: DrawCoordinate | null;\n}\n\nexport interface PointClipStatsEvent {\n mode: PointClipMode;\n durationMs: number;\n inputCount: number;\n outputCount: number;\n polygonCount: number;\n usedWebGpu?: boolean;\n candidateCount?: number;\n bridgedToDraw?: boolean;\n}\n\nexport interface PointerWorldMoveEvent {\n coordinate: DrawCoordinate | null;\n clientX: number;\n clientY: number;\n insideImage: boolean;\n}\n\nexport interface WsiCustomLayerContext {\n source: WsiImageSource;\n viewState: WsiViewState;\n drawTool: DrawTool;\n interactionLock: boolean;\n worldToScreen: (worldX: number, worldY: number) => DrawCoordinate | null;\n screenToWorld: (clientX: number, clientY: number) => DrawCoordinate | null;\n requestRedraw: () => void;\n}\n\nexport interface WsiCustomLayer {\n id?: string | number;\n zIndex?: number;\n pointerEvents?: CSSProperties[\"pointerEvents\"];\n className?: string;\n style?: CSSProperties;\n render: (context: WsiCustomLayerContext) => ReactNode;\n}\n\ninterface PointSpatialIndex {\n cellSize: number;\n safeCount: number;\n positions: Float32Array;\n ids: Uint32Array | null;\n buckets: Map<number, Map<number, number[]>>;\n}\n\nfunction sanitizePointCount(pointData: WsiPointData): number {\n return Math.max(0, Math.min(Math.floor(pointData.count ?? 0), Math.floor((pointData.positions?.length ?? 0) / 2), pointData.paletteIndices?.length ?? 0));\n}\n\nfunction sanitizeDrawIndices(drawIndices: Uint32Array | undefined, maxExclusive: number): Uint32Array | null {\n if (!(drawIndices instanceof Uint32Array) || maxExclusive <= 0 || drawIndices.length === 0) {\n return null;\n }\n\n let invalidFound = false;\n for (let i = 0; i < drawIndices.length; i += 1) {\n if (drawIndices[i] < maxExclusive) continue;\n invalidFound = true;\n break;\n }\n if (!invalidFound) {\n return drawIndices;\n }\n\n const out = new Uint32Array(drawIndices.length);\n let cursor = 0;\n for (let i = 0; i < drawIndices.length; i += 1) {\n const idx = drawIndices[i];\n if (idx >= maxExclusive) continue;\n out[cursor] = idx;\n cursor += 1;\n }\n return out.subarray(0, cursor);\n}\n\nfunction resolvePointHitGridSize(source: WsiImageSource | null, visibleCount: number): number {\n if (!source || visibleCount <= 0) return 256;\n const area = Math.max(1, source.width * source.height);\n const avgSpacing = Math.sqrt(area / Math.max(1, visibleCount));\n const raw = avgSpacing * POINT_HIT_GRID_DENSITY_SCALE;\n return Math.max(MIN_POINT_HIT_GRID_SIZE, Math.min(MAX_POINT_HIT_GRID_SIZE, raw));\n}\n\nfunction buildPointSpatialIndex(pointData: WsiPointData | null | undefined, source: WsiImageSource | null): PointSpatialIndex | null {\n if (!pointData || !pointData.positions || !pointData.paletteIndices) {\n return null;\n }\n\n const safeCount = sanitizePointCount(pointData);\n if (safeCount <= 0) {\n return null;\n }\n\n const positions = pointData.positions.subarray(0, safeCount * 2);\n const ids = pointData.ids instanceof Uint32Array && pointData.ids.length >= safeCount ? pointData.ids.subarray(0, safeCount) : null;\n const drawIndices = sanitizeDrawIndices(pointData.drawIndices, safeCount);\n const visibleCount = drawIndices ? drawIndices.length : safeCount;\n if (visibleCount === 0) {\n return null;\n }\n\n const cellSize = resolvePointHitGridSize(source, visibleCount);\n const buckets = new Map<number, Map<number, number[]>>();\n\n const pushBucket = (pointIndex: number): void => {\n const px = positions[pointIndex * 2];\n const py = positions[pointIndex * 2 + 1];\n if (!Number.isFinite(px) || !Number.isFinite(py)) return;\n\n const cellX = Math.floor(px / cellSize);\n const cellY = Math.floor(py / cellSize);\n let column = buckets.get(cellX);\n if (!column) {\n column = new Map<number, number[]>();\n buckets.set(cellX, column);\n }\n const bucket = column.get(cellY);\n if (bucket) {\n bucket.push(pointIndex);\n } else {\n column.set(cellY, [pointIndex]);\n }\n };\n\n if (drawIndices) {\n for (let i = 0; i < drawIndices.length; i += 1) {\n pushBucket(drawIndices[i] ?? 0);\n }\n } else {\n for (let i = 0; i < safeCount; i += 1) {\n pushBucket(i);\n }\n }\n\n if (buckets.size === 0) {\n return null;\n }\n\n return {\n cellSize,\n safeCount,\n positions,\n ids,\n buckets,\n };\n}\n\nfunction resolveRegionId(region: WsiRegion, index: number): string | number {\n return region.id ?? index;\n}\n\nfunction isPointInPolygon(point: DrawCoordinate, polygon: DrawCoordinate[]): boolean {\n if (!Array.isArray(polygon) || polygon.length < 3) return false;\n\n const [x, y] = point;\n let inside = false;\n\n for (let i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {\n const [xi, yi] = polygon[i];\n const [xj, yj] = polygon[j];\n const intersect = yi > y !== yj > y && x < ((xj - xi) * (y - yi)) / Math.max(1e-12, yj - yi) + xi;\n if (intersect) inside = !inside;\n }\n\n return inside;\n}\n\nfunction pickRegionAt(\n coord: DrawCoordinate,\n regions: WsiRegion[]\n): {\n region: WsiRegion;\n regionIndex: number;\n regionId: string | number;\n} | null {\n for (let i = regions.length - 1; i >= 0; i -= 1) {\n const region = regions[i];\n if (!region?.coordinates?.length) continue;\n if (!isPointInPolygon(coord, region.coordinates)) continue;\n return {\n region,\n regionIndex: i,\n regionId: resolveRegionId(region, i),\n };\n }\n return null;\n}\n\nexport interface WsiViewerCanvasProps {\n source: WsiImageSource | null;\n viewState?: Partial<WsiViewState> | null;\n onViewStateChange?: (next: WsiViewState) => void;\n onStats?: (stats: WsiRenderStats) => void;\n onTileError?: (event: WsiTileErrorEvent) => void;\n onContextLost?: () => void;\n onContextRestored?: () => void;\n debugOverlay?: boolean;\n debugOverlayStyle?: CSSProperties;\n fitNonce?: number;\n rotationResetNonce?: number;\n authToken?: string;\n ctrlDragRotate?: boolean;\n pointData?: WsiPointData | null;\n pointPalette?: Uint8Array | null;\n pointSizeByZoom?: PointSizeByZoom;\n roiRegions?: WsiRegion[];\n roiPolygons?: DrawCoordinate[][];\n clipPointsToRois?: boolean;\n clipMode?: PointClipMode;\n onClipStats?: (event: PointClipStatsEvent) => void;\n onRoiPointGroups?: (stats: RoiPointGroupStats) => void;\n roiPaletteIndexToTermId?: ReadonlyMap<number, string> | readonly string[];\n interactionLock?: boolean;\n drawTool?: DrawTool;\n stampOptions?: StampOptions;\n brushOptions?: BrushOptions;\n regionStrokeStyle?: Partial<RegionStrokeStyle>;\n regionStrokeHoverStyle?: Partial<RegionStrokeStyle>;\n regionStrokeActiveStyle?: Partial<RegionStrokeStyle>;\n patchStrokeStyle?: Partial<RegionStrokeStyle>;\n resolveRegionStrokeStyle?: RegionStrokeStyleResolver;\n overlayShapes?: DrawOverlayShape[];\n customLayers?: WsiCustomLayer[];\n patchRegions?: WsiRegion[];\n regionLabelStyle?: Partial<RegionLabelStyle>;\n onPointerWorldMove?: (event: PointerWorldMoveEvent) => void;\n onPointHover?: (event: PointHoverEvent) => void;\n onPointClick?: (event: PointClickEvent) => void;\n onRegionHover?: (event: RegionHoverEvent) => void;\n onRegionClick?: (event: RegionClickEvent) => void;\n onActiveRegionChange?: (regionId: string | number | null) => void;\n getCellByCoordinatesRef?: MutableRefObject<((coordinate: DrawCoordinate) => PointHitEvent | null) | null>;\n onDrawComplete?: (result: DrawResult) => void;\n onPatchComplete?: (result: PatchDrawResult) => void;\n showOverviewMap?: boolean;\n overviewMapOptions?: Partial<OverviewMapOptions>;\n className?: string;\n style?: CSSProperties;\n}\n\nexport function WsiViewerCanvas({\n source,\n viewState,\n onViewStateChange,\n onStats,\n onTileError,\n onContextLost,\n onContextRestored,\n debugOverlay = false,\n debugOverlayStyle,\n fitNonce = 0,\n rotationResetNonce = 0,\n authToken = \"\",\n ctrlDragRotate = true,\n pointData = null,\n pointPalette = null,\n pointSizeByZoom,\n roiRegions,\n roiPolygons,\n clipPointsToRois = false,\n clipMode = \"worker\",\n onClipStats,\n onRoiPointGroups,\n roiPaletteIndexToTermId,\n interactionLock = false,\n drawTool = \"cursor\",\n stampOptions,\n brushOptions,\n regionStrokeStyle,\n regionStrokeHoverStyle,\n regionStrokeActiveStyle,\n patchStrokeStyle,\n resolveRegionStrokeStyle,\n overlayShapes,\n customLayers,\n patchRegions,\n regionLabelStyle,\n onPointerWorldMove,\n onPointHover,\n onPointClick,\n onRegionHover,\n onRegionClick,\n onActiveRegionChange,\n getCellByCoordinatesRef,\n onDrawComplete,\n onPatchComplete,\n showOverviewMap = false,\n overviewMapOptions,\n className,\n style,\n}: WsiViewerCanvasProps): React.ReactElement {\n const canvasRef = useRef<HTMLCanvasElement | null>(null);\n const rendererRef = useRef<WsiTileRenderer | null>(null);\n const drawInvalidateRef = useRef<(() => void) | null>(null);\n const overviewInvalidateRef = useRef<(() => void) | null>(null);\n const onViewStateChangeRef = useRef<typeof onViewStateChange>(onViewStateChange);\n const onStatsRef = useRef<typeof onStats>(onStats);\n const debugOverlayRef = useRef(debugOverlay);\n const [isOverviewOpen, setIsOverviewOpen] = useState(true);\n const [hoveredRegionId, setHoveredRegionId] = useState<string | number | null>(null);\n const [activeRegionId, setActiveRegionId] = useState<string | number | null>(null);\n const [customLayerViewState, setCustomLayerViewState] = useState<WsiViewState | null>(null);\n const [debugStats, setDebugStats] = useState<WsiRenderStats | null>(null);\n const hoveredRegionIdRef = useRef<string | number | null>(null);\n const hoveredPointIndexRef = useRef<number | null>(null);\n const hoveredPointIdRef = useRef<number | null>(null);\n const clipRunIdRef = useRef(0);\n const safeRoiRegions = roiRegions ?? EMPTY_ROI_REGIONS;\n const safePatchRegions = patchRegions ?? EMPTY_ROI_REGIONS;\n const safeRoiPolygons = roiPolygons ?? EMPTY_ROI_POLYGONS;\n const shouldTrackCustomLayerViewState = (customLayers?.length ?? 0) > 0;\n\n const mergedStyle = useMemo<CSSProperties>(() => ({ position: \"relative\", width: \"100%\", height: \"100%\", ...style }), [style]);\n const mergedDebugOverlayStyle = useMemo<CSSProperties>(\n () => ({\n position: \"absolute\",\n top: 8,\n left: 8,\n zIndex: 7,\n margin: 0,\n padding: \"8px 10px\",\n maxWidth: \"min(420px, 80%)\",\n pointerEvents: \"none\",\n whiteSpace: \"pre-wrap\",\n lineHeight: 1.35,\n fontFamily: \"ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace\",\n fontSize: 11,\n color: \"#cde6ff\",\n background: \"rgba(6, 12, 20, 0.82)\",\n border: \"1px solid rgba(173, 216, 255, 0.28)\",\n borderRadius: 8,\n boxShadow: \"0 8px 22px rgba(0,0,0,0.35)\",\n ...debugOverlayStyle,\n }),\n [debugOverlayStyle]\n );\n\n const effectiveRoiRegions = useMemo<WsiRegion[]>(() => {\n if (safeRoiRegions.length > 0) {\n return safeRoiRegions;\n }\n if (safeRoiPolygons.length === 0) {\n return EMPTY_ROI_REGIONS;\n }\n return safeRoiPolygons.map((coordinates, index) => ({\n id: index,\n coordinates,\n }));\n }, [safeRoiRegions, safeRoiPolygons]);\n\n const clipPolygons = useMemo(() => effectiveRoiRegions.map(region => region.coordinates), [effectiveRoiRegions]);\n\n const [renderPointData, setRenderPointData] = useState<WsiPointData | null>(pointData);\n\n useEffect(() => {\n const runId = ++clipRunIdRef.current;\n let cancelled = false;\n\n if (!clipPointsToRois) {\n setRenderPointData(pointData);\n return () => {\n cancelled = true;\n };\n }\n\n if (!pointData || !pointData.count || !pointData.positions || !pointData.paletteIndices) {\n setRenderPointData(null);\n return () => {\n cancelled = true;\n };\n }\n\n if (clipPolygons.length === 0) {\n setRenderPointData(EMPTY_CLIPPED_POINTS);\n onClipStats?.({\n mode: clipMode,\n durationMs: 0,\n inputCount: pointData.count,\n outputCount: 0,\n polygonCount: 0,\n });\n return () => {\n cancelled = true;\n };\n }\n\n const applyResult = (data: WsiPointData | null, stats: Omit<PointClipStatsEvent, \"inputCount\" | \"outputCount\" | \"polygonCount\">) => {\n if (cancelled || runId !== clipRunIdRef.current) return;\n const outputCount = data?.drawIndices ? data.drawIndices.length : (data?.count ?? 0);\n setRenderPointData(data);\n onClipStats?.({\n mode: stats.mode,\n durationMs: stats.durationMs,\n inputCount: pointData.count,\n outputCount,\n polygonCount: clipPolygons.length,\n usedWebGpu: stats.usedWebGpu,\n candidateCount: stats.candidateCount,\n bridgedToDraw: stats.bridgedToDraw,\n });\n };\n\n const run = async (): Promise<void> => {\n if (clipMode === \"sync\") {\n const start = performance.now();\n const data = filterPointDataByPolygons(pointData, clipPolygons);\n applyResult(data, {\n mode: \"sync\",\n durationMs: performance.now() - start,\n });\n return;\n }\n\n if (clipMode === \"hybrid-webgpu\") {\n const result = await filterPointDataByPolygonsHybrid(pointData, clipPolygons as RoiPolygon[], { bridgeToDraw: true });\n applyResult(result.data, {\n mode: result.meta.mode,\n durationMs: result.meta.durationMs,\n usedWebGpu: result.meta.usedWebGpu,\n candidateCount: result.meta.candidateCount,\n bridgedToDraw: result.meta.bridgedToDraw,\n });\n return;\n }\n\n try {\n const result = await filterPointDataByPolygonsInWorker(pointData, clipPolygons as RoiPolygon[]);\n applyResult(result.data, {\n mode: result.meta.mode,\n durationMs: result.meta.durationMs,\n });\n } catch {\n const start = performance.now();\n const data = filterPointDataByPolygons(pointData, clipPolygons);\n applyResult(data, {\n mode: \"sync\",\n durationMs: performance.now() - start,\n });\n }\n };\n\n void run();\n return () => {\n cancelled = true;\n };\n }, [clipPointsToRois, clipMode, pointData, clipPolygons, onClipStats]);\n\n const shouldEnablePointHitTest = Boolean(onPointHover || onPointClick || getCellByCoordinatesRef);\n const pointSpatialIndex = useMemo(() => {\n if (!shouldEnablePointHitTest) return null;\n return buildPointSpatialIndex(renderPointData, source);\n }, [shouldEnablePointHitTest, renderPointData, source]);\n\n const getCellByCoordinates = useCallback(\n (coordinate: DrawCoordinate): PointHitEvent | null => {\n const renderer = rendererRef.current;\n if (!renderer || !pointSpatialIndex) return null;\n\n const x = Number(coordinate[0]);\n const y = Number(coordinate[1]);\n if (!Number.isFinite(x) || !Number.isFinite(y)) return null;\n\n const zoom = Math.max(1e-6, renderer.getViewState().zoom);\n const pointSizePx = renderer.getPointSizeByZoom();\n const hitRadiusPx = Math.max(MIN_POINT_HIT_RADIUS_PX, pointSizePx * POINT_HIT_RADIUS_SCALE);\n const hitRadiusWorld = hitRadiusPx / zoom;\n if (!Number.isFinite(hitRadiusWorld) || hitRadiusWorld <= 0) return null;\n\n const cellSize = pointSpatialIndex.cellSize;\n const baseCellX = Math.floor(x / cellSize);\n const baseCellY = Math.floor(y / cellSize);\n const cellRadius = Math.max(1, Math.ceil(hitRadiusWorld / cellSize));\n const maxDist2 = hitRadiusWorld * hitRadiusWorld;\n\n let nearestIndex = -1;\n let nearestDist2 = maxDist2;\n let nearestX = 0;\n let nearestY = 0;\n\n for (let cx = baseCellX - cellRadius; cx <= baseCellX + cellRadius; cx += 1) {\n const column = pointSpatialIndex.buckets.get(cx);\n if (!column) continue;\n\n for (let cy = baseCellY - cellRadius; cy <= baseCellY + cellRadius; cy += 1) {\n const bucket = column.get(cy);\n if (!bucket || bucket.length === 0) continue;\n\n for (let i = 0; i < bucket.length; i += 1) {\n const pointIndex = bucket[i];\n if (pointIndex >= pointSpatialIndex.safeCount) continue;\n\n const px = pointSpatialIndex.positions[pointIndex * 2];\n const py = pointSpatialIndex.positions[pointIndex * 2 + 1];\n const dx = px - x;\n const dy = py - y;\n const dist2 = dx * dx + dy * dy;\n if (dist2 > nearestDist2) continue;\n\n nearestDist2 = dist2;\n nearestIndex = pointIndex;\n nearestX = px;\n nearestY = py;\n }\n }\n }\n\n if (nearestIndex < 0) return null;\n const pointId = pointSpatialIndex.ids ? Number(pointSpatialIndex.ids[nearestIndex]) : null;\n return {\n index: nearestIndex,\n id: pointId,\n coordinate: [x, y],\n pointCoordinate: [nearestX, nearestY],\n };\n },\n [pointSpatialIndex]\n );\n\n const emitPointHover = useCallback(\n (hit: PointHitEvent | null, coordinate: DrawCoordinate | null) => {\n if (!onPointHover) return;\n const nextIndex = hit?.index ?? null;\n const nextId = hit?.id ?? null;\n if (hoveredPointIndexRef.current === nextIndex && hoveredPointIdRef.current === nextId) return;\n hoveredPointIndexRef.current = nextIndex;\n hoveredPointIdRef.current = nextId;\n onPointHover({\n index: nextIndex,\n id: nextId,\n coordinate,\n pointCoordinate: hit?.pointCoordinate ?? null,\n });\n },\n [onPointHover]\n );\n\n const emitPointClick = useCallback(\n (coordinate: DrawCoordinate, button: number) => {\n if (!onPointClick) return;\n const hit = getCellByCoordinates(coordinate);\n if (!hit) return;\n onPointClick({\n ...hit,\n button,\n });\n },\n [onPointClick, getCellByCoordinates]\n );\n\n const overviewWidth = useMemo(() => {\n const value = Number(overviewMapOptions?.width ?? 220);\n return Number.isFinite(value) ? Math.max(64, value) : 220;\n }, [overviewMapOptions?.width]);\n const overviewHeight = useMemo(() => {\n const value = Number(overviewMapOptions?.height ?? 140);\n return Number.isFinite(value) ? Math.max(48, value) : 140;\n }, [overviewMapOptions?.height]);\n const overviewMargin = useMemo(() => {\n const value = Number(overviewMapOptions?.margin ?? 16);\n return Number.isFinite(value) ? Math.max(0, value) : 16;\n }, [overviewMapOptions?.margin]);\n const overviewPosition = overviewMapOptions?.position || \"bottom-right\";\n\n useEffect(() => {\n if (!getCellByCoordinatesRef) return;\n getCellByCoordinatesRef.current = getCellByCoordinates;\n return () => {\n if (getCellByCoordinatesRef.current === getCellByCoordinates) {\n getCellByCoordinatesRef.current = null;\n }\n };\n }, [getCellByCoordinatesRef, getCellByCoordinates]);\n\n const commitActiveRegion = useCallback(\n (next: string | number | null) => {\n setActiveRegionId(prev => {\n if (String(prev) === String(next)) {\n return prev;\n }\n onActiveRegionChange?.(next);\n return next;\n });\n },\n [onActiveRegionChange]\n );\n\n useEffect(() => {\n onViewStateChangeRef.current = onViewStateChange;\n }, [onViewStateChange]);\n\n useEffect(() => {\n onStatsRef.current = onStats;\n }, [onStats]);\n\n useEffect(() => {\n debugOverlayRef.current = debugOverlay;\n if (!debugOverlay) setDebugStats(null);\n }, [debugOverlay]);\n\n const handleRendererStats = useCallback((stats: WsiRenderStats): void => {\n onStatsRef.current?.(stats);\n if (debugOverlayRef.current) {\n setDebugStats(stats);\n }\n }, []);\n\n const debugOverlayText = useMemo(() => {\n if (!debugStats) {\n return \"stats: waiting for first frame...\";\n }\n return [\n `tier ${debugStats.tier} | frame ${debugStats.frameMs?.toFixed(2) ?? \"-\"} ms | drawCalls ${debugStats.drawCalls ?? \"-\"}`,\n `tiles visible ${debugStats.visible} | rendered ${debugStats.rendered} | fallback ${debugStats.fallback}`,\n `cache size ${debugStats.cache} | hit ${debugStats.cacheHits ?? \"-\"} | miss ${debugStats.cacheMisses ?? \"-\"}`,\n `queue inflight ${debugStats.inflight} | queued ${debugStats.queued ?? \"-\"} | retries ${debugStats.retries ?? \"-\"} | failed ${debugStats.failed ?? \"-\"} | aborted ${debugStats.aborted ?? \"-\"}`,\n `points ${debugStats.points}`,\n ].join(\"\\n\");\n }, [debugStats]);\n\n useEffect(() => {\n const hasActive = activeRegionId === null ? true : effectiveRoiRegions.some((region, index) => String(resolveRegionId(region, index)) === String(activeRegionId));\n if (!hasActive && activeRegionId !== null) {\n commitActiveRegion(null);\n }\n\n const currentHover = hoveredRegionIdRef.current;\n const hasHover = currentHover === null ? true : effectiveRoiRegions.some((region, index) => String(resolveRegionId(region, index)) === String(currentHover));\n\n if (!hasHover && currentHover !== null) {\n hoveredRegionIdRef.current = null;\n setHoveredRegionId(null);\n onRegionHover?.({\n region: null,\n regionId: null,\n regionIndex: -1,\n coordinate: null,\n });\n }\n }, [effectiveRoiRegions, activeRegionId, onRegionHover, commitActiveRegion]);\n\n useEffect(() => {\n const hoveredPointIndex = hoveredPointIndexRef.current;\n if (hoveredPointIndex === null) return;\n if (pointSpatialIndex && hoveredPointIndex < pointSpatialIndex.safeCount) return;\n hoveredPointIndexRef.current = null;\n hoveredPointIdRef.current = null;\n onPointHover?.({\n index: null,\n id: null,\n coordinate: null,\n pointCoordinate: null,\n });\n }, [pointSpatialIndex, onPointHover]);\n\n const emitViewStateChange = useCallback(\n (next: WsiViewState): void => {\n if (shouldTrackCustomLayerViewState) {\n setCustomLayerViewState(next);\n }\n const callback = onViewStateChangeRef.current;\n if (callback) {\n callback(next);\n }\n drawInvalidateRef.current?.();\n overviewInvalidateRef.current?.();\n },\n [shouldTrackCustomLayerViewState]\n );\n\n useEffect(() => {\n if (!showOverviewMap) {\n setIsOverviewOpen(false);\n return;\n }\n setIsOverviewOpen(true);\n }, [showOverviewMap, source?.id]);\n\n useEffect(() => {\n if (drawTool === \"cursor\") return;\n if (hoveredRegionIdRef.current === null) return;\n hoveredRegionIdRef.current = null;\n setHoveredRegionId(null);\n onRegionHover?.({\n region: null,\n regionId: null,\n regionIndex: -1,\n coordinate: null,\n });\n }, [drawTool, onRegionHover]);\n\n useEffect(() => {\n if (drawTool === \"cursor\") return;\n if (hoveredPointIndexRef.current === null) return;\n hoveredPointIndexRef.current = null;\n hoveredPointIdRef.current = null;\n onPointHover?.({\n index: null,\n id: null,\n coordinate: null,\n pointCoordinate: null,\n });\n }, [drawTool, onPointHover]);\n\n const resolveWorldCoord = useCallback((clientX: number, clientY: number): DrawCoordinate | null => {\n const renderer = rendererRef.current;\n if (!renderer) return null;\n const raw = renderer.screenToWorld(clientX, clientY);\n if (!Array.isArray(raw) || raw.length < 2) return null;\n const x = Number(raw[0]);\n const y = Number(raw[1]);\n if (!Number.isFinite(x) || !Number.isFinite(y)) return null;\n return [x, y];\n }, []);\n\n const resolveScreenCoord = useCallback((worldX: number, worldY: number): DrawCoordinate | null => {\n const renderer = rendererRef.current;\n if (!renderer) return null;\n const raw = renderer.worldToScreen(worldX, worldY);\n if (!Array.isArray(raw) || raw.length < 2) return null;\n const x = Number(raw[0]);\n const y = Number(raw[1]);\n if (!Number.isFinite(x) || !Number.isFinite(y)) return null;\n return [x, y];\n }, []);\n\n const requestCustomLayerRedraw = useCallback(() => {\n rendererRef.current?.requestRender();\n drawInvalidateRef.current?.();\n overviewInvalidateRef.current?.();\n }, []);\n\n const effectiveCustomLayerViewState = useMemo<WsiViewState | null>(() => {\n return customLayerViewState ?? rendererRef.current?.getViewState() ?? null;\n }, [customLayerViewState]);\n\n const customLayerContext = useMemo<WsiCustomLayerContext | null>(() => {\n if (!source) return null;\n const viewStateForLayer = effectiveCustomLayerViewState;\n if (!viewStateForLayer) return null;\n return {\n source,\n viewState: viewStateForLayer,\n drawTool,\n interactionLock,\n worldToScreen: resolveScreenCoord,\n screenToWorld: resolveWorldCoord,\n requestRedraw: requestCustomLayerRedraw,\n };\n }, [source, effectiveCustomLayerViewState, drawTool, interactionLock, resolveScreenCoord, resolveWorldCoord, requestCustomLayerRedraw]);\n\n const handleRegionPointerMove = useCallback(\n (event: ReactPointerEvent<HTMLDivElement>) => {\n const isCanvasEvent = event.target === canvasRef.current;\n const coord = resolveWorldCoord(event.clientX, event.clientY);\n if (onPointerWorldMove) {\n const insideImage = !!coord && coord[0] >= 0 && coord[1] >= 0 && !!source && coord[0] <= source.width && coord[1] <= source.height;\n onPointerWorldMove({\n coordinate: coord,\n clientX: event.clientX,\n clientY: event.clientY,\n insideImage,\n });\n }\n\n if (drawTool !== \"cursor\") return;\n if (!isCanvasEvent) {\n emitPointHover(null, null);\n if (hoveredRegionIdRef.current !== null) {\n hoveredRegionIdRef.current = null;\n setHoveredRegionId(null);\n onRegionHover?.({\n region: null,\n regionId: null,\n regionIndex: -1,\n coordinate: null,\n });\n }\n return;\n }\n if (!coord) {\n emitPointHover(null, null);\n return;\n }\n\n if (onPointHover) {\n emitPointHover(getCellByCoordinates(coord), coord);\n }\n if (!effectiveRoiRegions.length) return;\n\n const hit = pickRegionAt(coord, effectiveRoiRegions);\n const nextHoverId = hit?.regionId ?? null;\n const prevHoverId = hoveredRegionIdRef.current;\n if (String(prevHoverId) === String(nextHoverId)) return;\n\n hoveredRegionIdRef.current = nextHoverId;\n setHoveredRegionId(nextHoverId);\n onRegionHover?.({\n region: hit?.region ?? null,\n regionId: nextHoverId,\n regionIndex: hit?.regionIndex ?? -1,\n coordinate: coord,\n });\n },\n [drawTool, effectiveRoiRegions, resolveWorldCoord, onRegionHover, onPointerWorldMove, source, emitPointHover, getCellByCoordinates, onPointHover]\n );\n\n const handleRegionPointerLeave = useCallback(() => {\n onPointerWorldMove?.({\n coordinate: null,\n clientX: -1,\n clientY: -1,\n insideImage: false,\n });\n emitPointHover(null, null);\n if (hoveredRegionIdRef.current === null) return;\n hoveredRegionIdRef.current = null;\n setHoveredRegionId(null);\n onRegionHover?.({\n region: null,\n regionId: null,\n regionIndex: -1,\n coordinate: null,\n });\n }, [onRegionHover, onPointerWorldMove, emitPointHover]);\n\n const handleRegionClick = useCallback(\n (event: ReactMouseEvent<HTMLDivElement>) => {\n if (drawTool !== \"cursor\") return;\n if (event.target !== canvasRef.current) return;\n\n const coord = resolveWorldCoord(event.clientX, event.clientY);\n if (!coord) return;\n emitPointClick(coord, event.button);\n\n if (!effectiveRoiRegions.length) {\n commitActiveRegion(null);\n return;\n }\n\n const hit = pickRegionAt(coord, effectiveRoiRegions);\n if (!hit) {\n commitActiveRegion(null);\n return;\n }\n\n const nextActive: string | number | null = activeRegionId !== null && String(activeRegionId) === String(hit.regionId) ? null : hit.regionId;\n commitActiveRegion(nextActive);\n onRegionClick?.({\n region: hit.region,\n regionId: hit.regionId,\n regionIndex: hit.regionIndex,\n coordinate: coord,\n });\n },\n [drawTool, effectiveRoiRegions, resolveWorldCoord, onRegionClick, activeRegionId, commitActiveRegion, emitPointClick]\n );\n\n const handleBrushTap = useCallback(\n (coord: DrawCoordinate): boolean => {\n if (drawTool !== \"brush\") return false;\n if (brushOptions?.clickSelectRoi !== true) return false;\n if (!effectiveRoiRegions.length) return false;\n\n const hit = pickRegionAt(coord, effectiveRoiRegions);\n if (!hit) return false;\n\n const nextActive: string | number | null = activeRegionId !== null && String(activeRegionId) === String(hit.regionId) ? null : hit.regionId;\n commitActiveRegion(nextActive);\n onRegionClick?.({\n region: hit.region,\n regionId: hit.regionId,\n regionIndex: hit.regionIndex,\n coordinate: coord,\n });\n return true;\n },\n [drawTool, brushOptions?.clickSelectRoi, effectiveRoiRegions, activeRegionId, commitActiveRegion, onRegionClick]\n );\n\n const handleRegionContextMenu = useCallback(\n (event: ReactMouseEvent<HTMLDivElement>) => {\n if (!onPointClick) return;\n if (drawTool !== \"cursor\") return;\n if (event.target !== canvasRef.current) return;\n event.preventDefault();\n const coord = resolveWorldCoord(event.clientX, event.clientY);\n if (!coord) return;\n emitPointClick(coord, event.button);\n },\n [drawTool, resolveWorldCoord, emitPointClick, onPointClick]\n );\n\n useEffect(() => {\n const canvas = canvasRef.current;\n if (!canvas || !source) {\n return;\n }\n\n const renderer = new WsiTileRenderer(canvas, source, {\n onViewStateChange: emitViewStateChange,\n onStats: handleRendererStats,\n onTileError,\n onContextLost,\n onContextRestored,\n authToken,\n ctrlDragRotate,\n pointSizeByZoom,\n });\n\n rendererRef.current = renderer;\n if (viewState) {\n renderer.setViewState(viewState);\n }\n renderer.setInteractionLock(interactionLock);\n if (shouldTrackCustomLayerViewState) {\n setCustomLayerViewState(renderer.getViewState());\n }\n\n return () => {\n renderer.destroy();\n rendererRef.current = null;\n };\n }, [source, handleRendererStats, onTileError, onContextLost, onContextRestored, authToken, ctrlDragRotate, pointSizeByZoom, emitViewStateChange, shouldTrackCustomLayerViewState]);\n\n useEffect(() => {\n const renderer = rendererRef.current;\n if (!renderer || !viewState) {\n return;\n }\n renderer.setViewState(viewState);\n }, [viewState]);\n\n useEffect(() => {\n const renderer = rendererRef.current;\n if (!renderer) {\n return;\n }\n renderer.fitToImage();\n }, [fitNonce]);\n\n useEffect(() => {\n const renderer = rendererRef.current;\n if (!renderer) return;\n renderer.resetRotation();\n }, [rotationResetNonce]);\n\n useEffect(() => {\n const renderer = rendererRef.current;\n if (!renderer || !pointPalette) {\n return;\n }\n renderer.setPointPalette(pointPalette);\n }, [pointPalette]);\n\n useEffect(() => {\n const renderer = rendererRef.current;\n if (!renderer) {\n return;\n }\n renderer.setPointSizeByZoom(pointSizeByZoom);\n }, [pointSizeByZoom]);\n\n useEffect(() => {\n const renderer = rendererRef.current;\n if (!renderer) {\n return;\n }\n renderer.setPointData(renderPointData);\n }, [renderPointData]);\n\n useEffect(() => {\n if (!onRoiPointGroups) return;\n const sourcePoints = clipPointsToRois ? renderPointData : pointData;\n const stats = computeRoiPointGroups(sourcePoints, effectiveRoiRegions, {\n paletteIndexToTermId: roiPaletteIndexToTermId,\n includeEmptyRegions: true,\n });\n onRoiPointGroups(stats);\n }, [onRoiPointGroups, clipPointsToRois, pointData, renderPointData, effectiveRoiRegions, roiPaletteIndexToTermId]);\n\n useEffect(() => {\n const renderer = rendererRef.current;\n if (!renderer) {\n return;\n }\n renderer.setInteractionLock(interactionLock);\n }, [interactionLock]);\n\n return (\n <div className={className} style={mergedStyle} onPointerMove={handleRegionPointerMove} onPointerLeave={handleRegionPointerLeave} onClick={handleRegionClick} onContextMenu={handleRegionContextMenu}>\n <canvas\n ref={canvasRef}\n className=\"wsi-render-canvas\"\n style={{\n position: \"absolute\",\n inset: 0,\n zIndex: 1,\n width: \"100%\",\n height: \"100%\",\n display: \"block\",\n touchAction: \"none\",\n cursor: drawTool === \"cursor\" && hoveredRegionId !== null ? \"pointer\" : interactionLock ? \"crosshair\" : \"grab\",\n }}\n />\n {source && customLayerContext && Array.isArray(customLayers) && customLayers.length > 0\n ? customLayers.map((layer, index) => (\n <div\n key={layer.id ?? index}\n className={layer.className}\n style={{\n position: \"absolute\",\n inset: 0,\n zIndex: layer.zIndex ?? 3,\n pointerEvents: layer.pointerEvents ?? \"none\",\n ...layer.style,\n }}\n >\n {layer.render(customLayerContext)}\n </div>\n ))\n : null}\n {source ? (\n <DrawLayer\n tool={drawTool}\n enabled={drawTool !== \"cursor\"}\n imageWidth={source.width}\n imageHeight={source.height}\n imageMpp={source.mpp}\n imageZoom={source.maxTierZoom}\n stampOptions={stampOptions}\n brushOptions={brushOptions}\n projectorRef={rendererRef}\n onBrushTap={handleBrushTap}\n viewStateSignal={viewState}\n persistedRegions={effectiveRoiRegions}\n patchRegions={safePatchRegions}\n regionStrokeStyle={regionStrokeStyle}\n regionStrokeHoverStyle={regionStrokeHoverStyle}\n regionStrokeActiveStyle={regionStrokeActiveStyle}\n patchStrokeStyle={patchStrokeStyle}\n resolveRegionStrokeStyle={resolveRegionStrokeStyle}\n overlayShapes={overlayShapes}\n hoveredRegionId={hoveredRegionId}\n activeRegionId={activeRegionId}\n regionLabelStyle={regionLabelStyle}\n invalidateRef={drawInvalidateRef}\n onDrawComplete={onDrawComplete}\n onPatchComplete={onPatchComplete}\n />\n ) : null}\n {debugOverlay ? (\n <pre data-open-plant-debug-overlay style={mergedDebugOverlayStyle}>\n {debugOverlayText}\n </pre>\n ) : null}\n {source && showOverviewMap ? (\n isOverviewOpen ? (\n <>\n <OverviewMap source={source} projectorRef={rendererRef} authToken={authToken} options={overviewMapOptions} invalidateRef={overviewInvalidateRef} />\n <button\n type=\"button\"\n aria-label=\"Hide overview map\"\n onClick={() => setIsOverviewOpen(false)}\n style={{\n position: \"absolute\",\n zIndex: 6,\n ...(overviewPosition.includes(\"left\") ? { left: overviewMargin } : { right: overviewMargin }),\n ...(overviewPosition.includes(\"top\") ? { top: overviewMargin + overviewHeight + 8 } : { bottom: overviewMargin + overviewHeight + 8 }),\n width: 20,\n height: 20,\n borderRadius: 999,\n border: \"1px solid rgba(255,255,255,0.4)\",\n background: \"rgba(8, 14, 22, 0.9)\",\n color: \"#fff\",\n fontSize: 13,\n lineHeight: 1,\n cursor: \"pointer\",\n padding: 0,\n }}\n >\n ×\n </button>\n </>\n ) : (\n <button\n type=\"button\"\n aria-label=\"Show overview map\"\n onClick={() => setIsOverviewOpen(true)}\n style={{\n position: \"absolute\",\n zIndex: 6,\n ...(overviewPosition.includes(\"left\") ? { left: overviewMargin } : { right: overviewMargin }),\n ...(overviewPosition.includes(\"top\") ? { top: overviewMargin } : { bottom: overviewMargin }),\n height: 24,\n minWidth: 40,\n borderRadius: 999,\n border: \"1px solid rgba(255,255,255,0.45)\",\n background: \"rgba(8, 14, 22, 0.9)\",\n color: \"#dff8ff\",\n fontSize: 11,\n fontWeight: 700,\n cursor: \"pointer\",\n padding: \"0 8px\",\n }}\n >\n Map\n </button>\n )\n ) : null}\n </div>\n );\n}\n"],"names":["compileShader","gl","type","source","shader","log","createProgram","vertexSource","fragmentSource","vertexShader","fragmentShader","program","requireUniformLocation","uniformName","location","requireWebGL2","canvas","context","OrthoCamera$1","__publicField","width","height","next","viewWidth","viewHeight","sx","sy","tx","ty","VERTEX_SHADER","FRAGMENT_SHADER","M1TileRenderer","options","OrthoCamera","vao","quadBuffer","quadVertices","unitLocation","uvLocation","stride","tiles","version","loaded","tile","viewState","response","blob","bitmap","texture","error","rect","cssWidth","cssHeight","dpr","targetWidth","targetHeight","viewport","zoom","safeZoom","visibleWorldWidth","visibleWorldHeight","offsetX","offsetY","DEFAULT_MIN_RASTER_STEP","DEFAULT_MAX_RASTER_PIXELS","DEFAULT_MAX_RASTER_SIZE","DEFAULT_CIRCLE_SIDES","MIN_RADIUS","ALPHA_THRESHOLD","clamp","value","min","max","closeRing","coordinates","out","x","y","first","last","sanitizePath","points","point","prev","createCirclePolygon","center","radius","sides","ring","t","createBoundsFallback","minX","minY","maxX","maxY","pad","computeExpandedBounds","resolveRasterConfig","bounds","minRasterStep","maxRasterPixels","maxRasterSize","widthWorld","heightWorld","step","padding","createRasterContext","worldToRaster","config","rasterizeStrokeMask","path","p","i","image","buildBoundaryEdges","mask","edges","vertex","at","turnPriority","fromDir","toDir","delta","traceLoops","outgoing","entry","used","loops","startVertex","currentVertex","currentDir","loop","guard","guardLimit","candidates","bestIndex","bestPriority","edgeIndex","candidate","priority","toWorldRing","vertexLoop","id","polygonSignedArea","sum","a","b","removeCollinearVertices","epsilon","closed","curr","cross","pointLineDistanceSquared","abx","aby","len2","dx","dy","simplifyRdp","tolerance","keep","tolerance2","stack","start","end","maxDist2","split","dist2","simplifyClosedRing","open","simplified","clampRingToBounds","buildBrushStrokePolygon","circleSides","raster","bestRing","bestArea","area","DEFAULT_POINT_COLOR","calcScaleResolution","imageMpp","imageZoom","currentZoom","mpp","z0","z1","calcScaleLength","length","unit","isSameViewState","toBearerToken","trimmed","token","hexToRgba","hex","match","n","buildTermPalette","terms","palette","termToPaletteIndex","term","termId","colors","vs","fs","DRAW_FILL","FREEHAND_MIN_POINTS","FREEHAND_SCREEN_STEP","CIRCLE_SIDES","MIN_AREA_PX","EMPTY_REGIONS","EMPTY_DASH","MICRONS_PER_MM","DEFAULT_STAMP_RECTANGLE_AREA_MM2","DEFAULT_STAMP_CIRCLE_AREA_MM2","DEFAULT_STAMP_RECTANGLE_PIXEL_SIZE","LEGACY_HPF_CIRCLE_AREA_MM2","WHEEL_ZOOM_IN_FACTOR","WHEEL_ZOOM_OUT_FACTOR","DEFAULT_BRUSH_RADIUS","DEFAULT_BRUSH_FILL_COLOR","DEFAULT_BRUSH_FILL_OPACITY","DEFAULT_BRUSH_CURSOR_COLOR","DEFAULT_BRUSH_CURSOR_ACTIVE_COLOR","DEFAULT_BRUSH_CURSOR_LINE_WIDTH","DEFAULT_BRUSH_CURSOR_DASH","DEFAULT_BRUSH_EDGE_DETAIL","MIN_BRUSH_EDGE_DETAIL","MAX_BRUSH_EDGE_DETAIL","MIN_BRUSH_RASTER_STEP","BRUSH_RASTER_DIAMETER_SAMPLES","BRUSH_SCREEN_STEP","DEFAULT_REGION_STROKE_STYLE","DEFAULT_PATCH_STROKE_STYLE","DEFAULT_REGION_LABEL_STYLE","isStampTool","tool","clampPositiveOrFallback","fallback","resolveStampOptions","clampUnitOpacity","sanitizeBrushLineDash","item","resolveBrushEdgeDetail","resolveBrushOptions","cursorLineWidth","edgeDetail","mm2ToUm2","areaMm2","createSquareFromCenter","halfLength","createCircleFromCenter","coords","createRectangle","createCircle","centerX","centerY","polygonArea","computeBounds","isValidPolygon","tracePath","ctx","close","drawPath","strokeStyle","fill","resolveStrokeStyle","style","dash","shadowBlur","shadowOffsetX","shadowOffsetY","mergeStrokeStyle","base","override","isSameRegionId","isNestedRingCoordinates","isFiniteNumber","isCoordinatePair","isCoordinateRing","collectOverlayRings","normalizeOverlayRings","sourceRings","normalized","drawInvertedFillMask","outerRing","holeRings","fillColor","resolveLabelStyle","px","py","bw","oy","br","drawRoundedRect","r","getTopAnchor","drawRegionLabel","text","anchor","canvasWidth","canvasHeight","labelStyle","label","boxWidth","boxHeight","left","top","clampWorld","coord","imageWidth","imageHeight","toCoord","DrawLayer","stampOptions","brushOptions","projectorRef","onBrushTap","onDrawComplete","onPatchComplete","enabled","viewStateSignal","persistedRegions","patchRegions","persistedPolygons","regionStrokeStyle","regionStrokeHoverStyle","regionStrokeActiveStyle","patchStrokeStyle","resolveRegionStrokeStyle","overlayShapes","hoveredRegionId","activeRegionId","regionLabelStyle","invalidateRef","className","canvasRef","useRef","drawPendingRef","overlayDebugSnapshotRef","lastToolRef","sessionRef","active","mergedPersistedRegions","useMemo","index","mergedPatchRegions","resolvedStrokeStyle","resolvedHoverStrokeStyle","resolvedActiveStrokeStyle","resolvedPatchStrokeStyle","resolvedLabelStyle","resolvedStampOptions","resolvedBrushOptions","mergedStyle","resizeCanvas","useCallback","w","h","worldToScreenPoints","projector","worldRadiusToScreenPixels","worldRadius","micronsToWorldPixels","lengthUm","mppValue","imageZoomValue","viewZoomRaw","viewZoom","continuousZoom","umPerScreenPixel","buildStampCoords","stampTool","areaUm2","buildPreviewCoords","session","drawBrushStrokePreview","screenPoints","radiusPx","drawBrushCursor","cursor","screen","drawOverlay","region","regionKey","state","resolved","debugOverlay","imageOuterRing","shape","renderRings","closedRings","debugKey","debugSignature","preview","line","polygon","anchorWorld","anchorScreen","requestDraw","resetSession","preserveCursor","toWorld","event","raw","finishSession","tapPoint","handleStampAt","intent","result","appendBrushPoint","world","minWorldStep","minWorldStep2","handlePointerDown","handlePointerMove","handlePointerUp","handlePointerLeave","changed","useEffect","observer","onKeyDown","jsx","screenX","screenY","trimTrailingSlash","ensureLeadingSlash","joinImsTileRoot","tileBaseUrl","parsed","origin","normalizeImageInfo","ims","isIms","tileSize","maxTierZoom","tilePath","normalizedPath","imsTileRoot","tileUrlBuilder","tier","toTileUrl","DEFAULT_OVERVIEW_MAP_OPTIONS","toPositiveNumber","isFiniteBounds","OverviewMap","authToken","thumbnailRef","lastBoundsRef","draggingRef","rafRef","margin","borderRadius","borderWidth","maxThumbnailTiles","backgroundColor","borderColor","viewportStrokeColor","viewportFillColor","interactive","showThumbnail","position","pos","draw","cssW","cssH","pixelW","pixelH","corners","safeBounds","safeCorners","right","bottom","rectW","rectH","toWorldFromClient","clientX","clientY","nx","ny","recenterTo","worldX","worldY","visibleW","visibleH","drag","cancelled","levelScale","levelWidth","levelHeight","tilesX","tilesY","tileCount","requests","useAuthHeader","results","dw","dh","TileViewerCanvas","rendererRef","renderer","sanitizePointCount","pointData","preparePolygons","polygons","prepared","poly","isInsideRing","inside","j","xi","yi","xj","yj","isInsideAnyPolygon","filterPointDataByPolygons","count","positions","pointIds","nextPositions","nextTerms","nextIds","output","filterPointIndicesByPolygons","contextPromise","BBOX_PREFILTER_SHADER","hasWebGpu","nav","getNavigatorGpu","gpu","GPU_SHADER_STAGE_COMPUTE","GPU_BUFFER_USAGE_STORAGE","GPU_BUFFER_USAGE_COPY_DST","GPU_BUFFER_USAGE_COPY_SRC","GPU_BUFFER_USAGE_UNIFORM","GPU_BUFFER_USAGE_MAP_READ","GPU_MAP_MODE_READ","getWebGpuCapabilities","navGpu","adapter","getContext","device","bindGroupLayout","pipeline","align","prefilterPointsByBoundsWebGpu","pointCount","boundsCount","safePointCount","positionBytes","boundsBytes","outputBytes","limit","positionsBuffer","boundsBuffer","outputBuffer","uniformBuffer","readBuffer","bindGroup","commandEncoder","pass","mapped","nowMs","filterPointDataByPolygonsHybrid","bridgeToDraw","safeCount","bboxFlat","candidateMask","usedWebGpu","candidateCount","candidateIndices","candidateCursor","data","drawIndices","visibleCount","pointIndex","compactData","workerInstance","workerSupported","requestId","pendingById","createWorker","worker","handleWorkerMessage","handleWorkerError","msg","pending","indices","paletteIndices","ids","terminateRoiClipWorker","filterPointDataByPolygonsInWorker","positionsCopy","termsCopy","idsCopy","startMs","resolve","reject","transfer","filterPointIndicesByPolygonsInWorker","ax","ay","bx","by","prepareRegions","regions","resolveTermId","paletteIndex","paletteIndexToTermId","fromArray","fromMap","computeRoiPointGroups","baseCount","valid","filtered","idx","inputCount","preparedRegions","regionTermCounters","regionTotalCounters","insideCount","bestRegion","regionTermMap","includeEmptyRegions","groups","totalCount","termMap","termCounts","shouldAttachAuthHeader","url","host","TileScheduler","nextVisibleKeys","inflight","queued","visibleKeys","nextQueue","key","earliestReadyAt","delay","now","controller","inflightEntry","nextAttempt","retryDelay","existing","attempt","exp","jitter","DEFAULT_ROTATION_DRAG_SENSITIVITY","MIN_POINT_SIZE_PX","MAX_POINT_SIZE_PX","DEFAULT_POINT_SIZE_STOPS","rad","toRadians","cos","sin","rx","ry","deg","name","isSameArrayView","clonePointSizeStops","stops","stop","normalizePointSizeStops","pointSizeByZoom","zoomKey","rawSize","size","arePointSizeStopsEqual","resolvePointSizeByZoomStops","span","slope","WsiTileRenderer","attemptCount","paletteSize","nextPaletteIndices","hasDrawIndices","nextDrawIndices","geometryChanged","drawIndicesChanged","maxExclusive","validCount","locked","nextStops","vw","vh","visibleWorldW","visibleWorldH","factor","nextZoom","vp","worldDx","worldDy","marginX","marginY","halfW","halfH","minCenterX","maxCenterX","minCenterY","maxCenterY","nextCenterX","nextCenterY","rawTier","viewBounds","viewMinX","viewMinY","viewMaxX","viewMaxY","minTileX","maxTileX","minTileY","maxTileY","centerTileX","centerTileY","visible","entries","removeCount","frameStartMs","tileProgram","pointProgram","fallbackTiles","cached","renderedTiles","missingTiles","renderedPoints","schedulerStats","cacheHits","cacheMisses","drawCalls","wantsRotate","nextAngle","prevAngle","rawDelta","sensitivityScale","_event","uCamera","uBounds","uTexture","vbo","aUnit","aUv","uPointSize","uPalette","uPaletteSize","posBuffer","termBuffer","indexBuffer","paletteTexture","posLoc","termLoc","EMPTY_ROI_REGIONS","EMPTY_ROI_POLYGONS","EMPTY_CLIPPED_POINTS","POINT_HIT_RADIUS_SCALE","MIN_POINT_HIT_RADIUS_PX","MIN_POINT_HIT_GRID_SIZE","MAX_POINT_HIT_GRID_SIZE","POINT_HIT_GRID_DENSITY_SCALE","sanitizeDrawIndices","invalidFound","resolvePointHitGridSize","buildPointSpatialIndex","cellSize","buckets","pushBucket","cellX","cellY","column","bucket","resolveRegionId","isPointInPolygon","pickRegionAt","WsiViewerCanvas","onViewStateChange","onStats","onTileError","onContextLost","onContextRestored","debugOverlayStyle","fitNonce","rotationResetNonce","ctrlDragRotate","pointPalette","roiRegions","roiPolygons","clipPointsToRois","clipMode","onClipStats","onRoiPointGroups","roiPaletteIndexToTermId","interactionLock","drawTool","customLayers","onPointerWorldMove","onPointHover","onPointClick","onRegionHover","onRegionClick","onActiveRegionChange","getCellByCoordinatesRef","showOverviewMap","overviewMapOptions","drawInvalidateRef","overviewInvalidateRef","onViewStateChangeRef","onStatsRef","debugOverlayRef","isOverviewOpen","setIsOverviewOpen","useState","setHoveredRegionId","setActiveRegionId","customLayerViewState","setCustomLayerViewState","debugStats","setDebugStats","hoveredRegionIdRef","hoveredPointIndexRef","hoveredPointIdRef","clipRunIdRef","safeRoiRegions","safePatchRegions","safeRoiPolygons","shouldTrackCustomLayerViewState","mergedDebugOverlayStyle","effectiveRoiRegions","clipPolygons","renderPointData","setRenderPointData","runId","applyResult","stats","outputCount","shouldEnablePointHitTest","pointSpatialIndex","getCellByCoordinates","coordinate","pointSizePx","hitRadiusWorld","baseCellX","baseCellY","cellRadius","nearestIndex","nearestDist2","nearestX","nearestY","cx","cy","pointId","emitPointHover","hit","nextIndex","nextId","emitPointClick","button","overviewHeight","overviewMargin","overviewPosition","commitActiveRegion","handleRendererStats","debugOverlayText","currentHover","hoveredPointIndex","emitViewStateChange","callback","resolveWorldCoord","resolveScreenCoord","requestCustomLayerRedraw","effectiveCustomLayerViewState","customLayerContext","viewStateForLayer","handleRegionPointerMove","isCanvasEvent","insideImage","nextHoverId","prevHoverId","handleRegionPointerLeave","handleRegionClick","nextActive","handleBrushTap","handleRegionContextMenu","jsxs","layer","Fragment"],"mappings":";;;;;AAAA,SAASA,GAAcC,GAA4BC,GAAcC,GAA6B;AAC5F,QAAMC,IAASH,EAAG,aAAaC,CAAI;AACnC,MAAI,CAACE;AACH,UAAM,IAAI,MAAM,0BAA0B;AAO5C,MAJAH,EAAG,aAAaG,GAAQD,CAAM,GAC9BF,EAAG,cAAcG,CAAM,GAGnB,CADOH,EAAG,mBAAmBG,GAAQH,EAAG,cAAc,GACjD;AACP,UAAMI,IAAMJ,EAAG,iBAAiBG,CAAM,KAAK;AAC3C,UAAAH,EAAG,aAAaG,CAAM,GAChB,IAAI,MAAMC,CAAG;AAAA,EACrB;AAEA,SAAOD;AACT;AAEO,SAASE,GAAcL,GAA4BM,GAAsBC,GAAsC;AACpH,QAAMC,IAAeT,GAAcC,GAAIA,EAAG,eAAeM,CAAY,GAC/DG,IAAiBV,GAAcC,GAAIA,EAAG,iBAAiBO,CAAc,GAErEG,IAAUV,EAAG,cAAA;AACnB,MAAI,CAACU;AACH,UAAAV,EAAG,aAAaQ,CAAY,GAC5BR,EAAG,aAAaS,CAAc,GACxB,IAAI,MAAM,2BAA2B;AAW7C,MARAT,EAAG,aAAaU,GAASF,CAAY,GACrCR,EAAG,aAAaU,GAASD,CAAc,GACvCT,EAAG,YAAYU,CAAO,GAEtBV,EAAG,aAAaQ,CAAY,GAC5BR,EAAG,aAAaS,CAAc,GAG1B,CADOT,EAAG,oBAAoBU,GAASV,EAAG,WAAW,GAChD;AACP,UAAMI,IAAMJ,EAAG,kBAAkBU,CAAO,KAAK;AAC7C,UAAAV,EAAG,cAAcU,CAAO,GAClB,IAAI,MAAMN,CAAG;AAAA,EACrB;AAEA,SAAOM;AACT;AAEO,SAASC,GACdX,GACAU,GACAE,GACsB;AACtB,QAAMC,IAAWb,EAAG,mBAAmBU,GAASE,CAAW;AAC3D,MAAI,CAACC;AACH,UAAM,IAAI,MAAM,mCAAmCD,CAAW,EAAE;AAElE,SAAOC;AACT;AAEO,SAASC,GAAcC,GAAmD;AAC/E,QAAMC,IAAUD,EAAO,WAAW,UAAU;AAAA,IAC1C,OAAO;AAAA,IACP,WAAW;AAAA,IACX,OAAO;AAAA,IACP,SAAS;AAAA,IACT,uBAAuB;AAAA,IACvB,iBAAiB;AAAA,EAAA,CAClB;AAED,MAAI,CAACC;AACH,UAAM,IAAI,MAAM,0BAA0B;AAG5C,SAAOA;AACT;ACpEO,IAAAC,KAAA,MAAkB;AAAA,EAAlB;AACG,IAAAC,EAAA,uBAAgB;AAChB,IAAAA,EAAA,wBAAiB;AAEjB,IAAAA,EAAA,mBAAuB;AAAA,MAC7B,SAAS;AAAA,MACT,SAAS;AAAA,MACT,MAAM;AAAA,IAAA;AAAA;AAAA,EAGR,YAAYC,GAAeC,GAAsB;AAC/C,SAAK,gBAAgB,KAAK,IAAI,GAAGD,CAAK,GACtC,KAAK,iBAAiB,KAAK,IAAI,GAAGC,CAAM;AAAA,EAC1C;AAAA,EAEA,kBAAqD;AACnD,WAAO;AAAA,MACL,OAAO,KAAK;AAAA,MACZ,QAAQ,KAAK;AAAA,IAAA;AAAA,EAEjB;AAAA,EAEA,aAAaC,GAAgC;AAC3C,IAAIA,EAAK,YAAY,WACnB,KAAK,UAAU,UAAUA,EAAK,UAG5BA,EAAK,YAAY,WACnB,KAAK,UAAU,UAAUA,EAAK,UAG5BA,EAAK,SAAS,WAChB,KAAK,UAAU,OAAO,KAAK,IAAI,MAAQA,EAAK,IAAI;AAAA,EAEpD;AAAA,EAEA,eAA0B;AACxB,WAAO,EAAE,GAAG,KAAK,UAAA;AAAA,EACnB;AAAA,EAEA,YAA0B;AACxB,UAAMC,IAAY,KAAK,gBAAgB,KAAK,UAAU,MAChDC,IAAa,KAAK,iBAAiB,KAAK,UAAU,MAElDC,IAAK,IAAIF,GACTG,IAAK,KAAKF,GACVG,IAAK,KAAK,KAAK,UAAU,UAAUF,GACnCG,IAAK,IAAI,KAAK,UAAU,UAAUF;AAExC,WAAO,IAAI,aAAa;AAAA,MACtBD;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACAC;AAAA,MACA;AAAA,MACAC;AAAA,MACAC;AAAA,MACA;AAAA,IAAA,CACD;AAAA,EACH;AACF;AC7CA,MAAMC,KAAgB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GAsBhBC,KAAkB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAajB,MAAMC,GAAe;AAAA,EAsB3B,YAAYC,GAAgC;AArB3B,IAAAb,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA,gBAAS,IAAIc,GAAA;AACb,IAAAd,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA;AAET,IAAAA,EAAA,eAAsB,CAAA;AACtB,IAAAA,EAAA,iBAAyB;AACzB,IAAAA,EAAA,qBAAc;AACd,IAAAA,EAAA,mBAAY;AACZ,IAAAA,EAAA,gBAAS;AACT,IAAAA,EAAA,6BAAsB;AAG7B,SAAK,SAASa,EAAQ,QACtB,KAAK,aAAa,KAAK,IAAI,GAAGA,EAAQ,UAAU,GAChD,KAAK,cAAc,KAAK,IAAI,GAAGA,EAAQ,WAAW,GAClD,KAAK,aAAaA,EAAQ,cAAc,CAAC,MAAM,MAAM,MAAM,CAAC,GAE5D,KAAK,KAAKjB,GAAc,KAAK,MAAM,GACnC,KAAK,UAAUT,GAAc,KAAK,IAAIuB,IAAeC,EAAe;AAEpE,UAAMI,IAAM,KAAK,GAAG,kBAAA,GACdC,IAAa,KAAK,GAAG,aAAA;AAC3B,QAAI,CAACD,KAAO,CAACC;AACZ,YAAM,IAAI,MAAM,iCAAiC;AAGlD,SAAK,MAAMD,GACX,KAAK,aAAaC,GAElB,KAAK,GAAG,gBAAgB,KAAK,GAAG,GAChC,KAAK,GAAG,WAAW,KAAK,GAAG,cAAc,KAAK,UAAU;AAExD,UAAMC,IAAe,IAAI,aAAa;AAAA,MACrC;AAAA,MAAG;AAAA,MAAG;AAAA,MAAG;AAAA,MAAG;AAAA,MAAG;AAAA,MAAG;AAAA,MAAG;AAAA,MAAG;AAAA,MAAG;AAAA,MAAG;AAAA,MAAG;AAAA,MAAG;AAAA,MAAG;AAAA,MAAG;AAAA,MAAG;AAAA,IAAA,CAC7C;AAED,SAAK,GAAG,WAAW,KAAK,GAAG,cAAcA,GAAc,KAAK,GAAG,WAAW;AAE1E,UAAMC,IAAe,KAAK,GAAG,kBAAkB,KAAK,SAAS,OAAO,GAC9DC,IAAa,KAAK,GAAG,kBAAkB,KAAK,SAAS,KAAK;AAChE,QAAID,IAAe,KAAKC,IAAa;AACpC,YAAM,IAAI,MAAM,oCAAoC;AAGrD,UAAMC,IAAS,IAAI,aAAa;AAChC,SAAK,GAAG,wBAAwBF,CAAY,GAC5C,KAAK,GAAG;AAAA,MACPA;AAAA,MACA;AAAA,MACA,KAAK,GAAG;AAAA,MACR;AAAA,MACAE;AAAA,MACA;AAAA,IAAA,GAED,KAAK,GAAG,wBAAwBD,CAAU,GAC1C,KAAK,GAAG;AAAA,MACPA;AAAA,MACA;AAAA,MACA,KAAK,GAAG;AAAA,MACR;AAAA,MACAC;AAAA,MACA,IAAI,aAAa;AAAA,IAAA,GAGlB,KAAK,GAAG,gBAAgB,IAAI,GAC5B,KAAK,GAAG,WAAW,KAAK,GAAG,cAAc,IAAI,GAE7C,KAAK,kBAAkB3B;AAAAA,MACtB,KAAK;AAAA,MACL,KAAK;AAAA,MACL;AAAA,IAAA,GAED,KAAK,kBAAkBA;AAAAA,MACtB,KAAK;AAAA,MACL,KAAK;AAAA,MACL;AAAA,IAAA,GAED,KAAK,mBAAmBA;AAAAA,MACvB,KAAK;AAAA,MACL,KAAK;AAAA,MACL;AAAA,IAAA,GAGGoB,EAAQ,qBACX,KAAK,sBAAsB,IAC3B,KAAK,OAAO,aAAaA,EAAQ,gBAAgB,IAGlD,KAAK,iBAAiB,IAAI,eAAe,MAAM;AAC9C,WAAK,OAAA;AAAA,IACN,CAAC,GAED,KAAK,eAAe,QAAQ,KAAK,MAAM,GACvC,KAAK,OAAA;AAAA,EACN;AAAA,EAEA,MAAM,SAASQ,GAAwC;AACtD,QAAI,KAAK;AACR;AAGD,UAAMC,IAAU,EAAE,KAAK,aAEjBC,IAAS,MAAM,QAAQ;AAAA,MAC5BF,EAAM,IAAI,OAAOG,MACG,MAAM,KAAK,SAASA,GAAMF,CAAO,CAEpD;AAAA,IAAA;AAGF,QAAI,KAAK,aAAaA,MAAY,KAAK,aAAa;AACnD,iBAAWE,KAAQD;AAClB,QAAIC,KACH,KAAK,GAAG,cAAcA,EAAK,OAAO;AAGpC;AAAA,IACD;AAEA,SAAK,aAAa,KAAK,KAAK,GAC5B,KAAK,QAAQD,EAAO,OAAO,CAACC,MAA6BA,MAAS,IAAI,GACtE,KAAK,cAAA;AAAA,EACN;AAAA,EAEA,aAAaC,GAAqC;AACjD,SAAK,sBAAsB,IAC3B,KAAK,OAAO,aAAaA,CAAS,GAClC,KAAK,cAAA;AAAA,EACN;AAAA,EAEA,eAA0B;AACzB,WAAO,KAAK,OAAO,aAAA;AAAA,EACpB;AAAA,EAEA,UAAgB;AACf,IAAI,KAAK,cAIT,KAAK,YAAY,IACjB,KAAK,eAAe,GAEhB,KAAK,YAAY,SACpB,qBAAqB,KAAK,OAAO,GACjC,KAAK,UAAU,OAGhB,KAAK,eAAe,WAAA,GACpB,KAAK,aAAa,KAAK,KAAK,GAC5B,KAAK,QAAQ,CAAA,GAEb,KAAK,GAAG,aAAa,KAAK,UAAU,GACpC,KAAK,GAAG,kBAAkB,KAAK,GAAG,GAClC,KAAK,GAAG,cAAc,KAAK,OAAO;AAAA,EACnC;AAAA,EAEA,MAAc,SACbD,GACAF,GAC6B;AAC7B,QAAI;AACH,YAAMI,IAAW,MAAM,MAAMF,EAAK,GAAG;AACrC,UAAI,CAACE,EAAS;AACb,cAAM,IAAI;AAAA,UACT,sBAAsBA,EAAS,MAAM,IAAIA,EAAS,UAAU;AAAA,QAAA;AAI9D,YAAMC,IAAO,MAAMD,EAAS,KAAA,GACtBE,IAAS,MAAM,kBAAkBD,CAAI;AAE3C,UAAI,KAAK,aAAaL,MAAY,KAAK;AACtC,eAAAM,EAAO,MAAA,GACA;AAGR,YAAMC,IAAU,KAAK,GAAG,cAAA;AACxB,UAAI,CAACA;AACJ,cAAAD,EAAO,MAAA,GACD,IAAI,MAAM,gCAAgC;AAGjD,kBAAK,GAAG,YAAY,KAAK,GAAG,YAAYC,CAAO,GAC/C,KAAK,GAAG,YAAY,KAAK,GAAG,qBAAqB,CAAC,GAClD,KAAK,GAAG;AAAA,QACP,KAAK,GAAG;AAAA,QACR,KAAK,GAAG;AAAA,QACR,KAAK,GAAG;AAAA,MAAA,GAET,KAAK,GAAG;AAAA,QACP,KAAK,GAAG;AAAA,QACR,KAAK,GAAG;AAAA,QACR,KAAK,GAAG;AAAA,MAAA,GAET,KAAK,GAAG;AAAA,QACP,KAAK,GAAG;AAAA,QACR,KAAK,GAAG;AAAA,QACR,KAAK,GAAG;AAAA,MAAA,GAET,KAAK,GAAG;AAAA,QACP,KAAK,GAAG;AAAA,QACR,KAAK,GAAG;AAAA,QACR,KAAK,GAAG;AAAA,MAAA,GAET,KAAK,GAAG;AAAA,QACP,KAAK,GAAG;AAAA,QACR;AAAA,QACA,KAAK,GAAG;AAAA,QACR,KAAK,GAAG;AAAA,QACR,KAAK,GAAG;AAAA,QACRD;AAAA,MAAA,GAED,KAAK,GAAG,YAAY,KAAK,GAAG,YAAY,IAAI,GAC5CA,EAAO,MAAA,GAEA;AAAA,QACN,IAAIJ,EAAK;AAAA,QACT,QAAQA,EAAK;AAAA,QACb,SAAAK;AAAA,MAAA;AAAA,IAEF,SAASC,GAAO;AACf,qBAAQ,MAAM,sCAAsCN,EAAK,EAAE,IAAIM,CAAK,GAC7D;AAAA,IACR;AAAA,EACD;AAAA,EAEQ,SAAe;AACtB,QAAI,KAAK;AACR;AAGD,UAAMC,IAAO,KAAK,OAAO,sBAAA,GACnBC,IAAW,KAAK,IAAI,GAAGD,EAAK,SAAS,KAAK,OAAO,eAAe,CAAC,GACjEE,IAAY,KAAK,IAAI,GAAGF,EAAK,UAAU,KAAK,OAAO,gBAAgB,CAAC,GACpEG,IAAM,KAAK,IAAI,GAAG,OAAO,oBAAoB,CAAC,GAE9CC,IAAc,KAAK,IAAI,GAAG,KAAK,MAAMH,IAAWE,CAAG,CAAC,GACpDE,IAAe,KAAK,IAAI,GAAG,KAAK,MAAMH,IAAYC,CAAG,CAAC;AAE5D,KACC,KAAK,OAAO,UAAUC,KACtB,KAAK,OAAO,WAAWC,OAEvB,KAAK,OAAO,QAAQD,GACpB,KAAK,OAAO,SAASC,IAGtB,KAAK,OAAO,YAAYJ,GAAUC,CAAS,GAC3C,KAAK,GAAG,SAAS,GAAG,GAAG,KAAK,OAAO,OAAO,KAAK,OAAO,MAAM,GAExD,CAAC,KAAK,UAAU,CAAC,KAAK,wBACzB,KAAK,WAAA,GACL,KAAK,SAAS,KAGf,KAAK,cAAA;AAAA,EACN;AAAA,EAEQ,aAAmB;AAC1B,UAAMI,IAAW,KAAK,OAAO,gBAAA,GAEvBC,IAAO,KAAK;AAAA,MACjBD,EAAS,QAAQ,KAAK;AAAA,MACtBA,EAAS,SAAS,KAAK;AAAA,IAAA,GAElBE,IAAW,OAAO,SAASD,CAAI,KAAKA,IAAO,IAAIA,IAAO,GAEtDE,IAAoBH,EAAS,QAAQE,GACrCE,IAAqBJ,EAAS,SAASE,GAEvCG,KAAW,KAAK,aAAaF,KAAqB,KAClDG,KAAW,KAAK,cAAcF,KAAsB;AAE1D,SAAK,OAAO,aAAa;AAAA,MACxB,MAAMF;AAAA,MACN,SAAAG;AAAA,MACA,SAAAC;AAAA,IAAA,CACA;AAAA,EACF;AAAA,EAEQ,gBAAsB;AAC7B,IAAI,KAAK,YAAY,QAAQ,KAAK,cAIlC,KAAK,UAAU,sBAAsB,MAAM;AAC1C,WAAK,UAAU,MACf,KAAK,OAAA;AAAA,IACN,CAAC;AAAA,EACF;AAAA,EAEQ,SAAe;AACtB,QAAI,MAAK,WAIT;AAAA,WAAK,GAAG;AAAA,QACP,KAAK,WAAW,CAAC;AAAA,QACjB,KAAK,WAAW,CAAC;AAAA,QACjB,KAAK,WAAW,CAAC;AAAA,QACjB,KAAK,WAAW,CAAC;AAAA,MAAA,GAElB,KAAK,GAAG,MAAM,KAAK,GAAG,gBAAgB,GAEtC,KAAK,GAAG,WAAW,KAAK,OAAO,GAC/B,KAAK,GAAG,gBAAgB,KAAK,GAAG,GAChC,KAAK,GAAG;AAAA,QACP,KAAK;AAAA,QACL;AAAA,QACA,KAAK,OAAO,UAAA;AAAA,MAAU,GAEvB,KAAK,GAAG,UAAU,KAAK,kBAAkB,CAAC;AAE1C,iBAAWnB,KAAQ,KAAK;AACvB,aAAK,GAAG,cAAc,KAAK,GAAG,QAAQ,GACtC,KAAK,GAAG,YAAY,KAAK,GAAG,YAAYA,EAAK,OAAO,GACpD,KAAK,GAAG;AAAA,UACP,KAAK;AAAA,UACLA,EAAK,OAAO,CAAC;AAAA,UACbA,EAAK,OAAO,CAAC;AAAA,UACbA,EAAK,OAAO,CAAC;AAAA,UACbA,EAAK,OAAO,CAAC;AAAA,QAAA,GAEd,KAAK,GAAG,WAAW,KAAK,GAAG,gBAAgB,GAAG,CAAC;AAGhD,WAAK,GAAG,YAAY,KAAK,GAAG,YAAY,IAAI,GAC5C,KAAK,GAAG,gBAAgB,IAAI;AAAA;AAAA,EAC7B;AAAA,EAEQ,aAAaH,GAA2B;AAC/C,eAAWG,KAAQH;AAClB,WAAK,GAAG,cAAcG,EAAK,OAAO;AAAA,EAEpC;AACD;ACvXA,MAAMoB,KAA0B,KAC1BC,KAA4B,KAC5BC,KAA0B,MAC1BC,KAAuB,IACvBC,KAAa,MACbC,KAAkB;AAExB,SAASC,GAAMC,GAAeC,GAAaC,GAAqB;AAC/D,SAAO,KAAK,IAAID,GAAK,KAAK,IAAIC,GAAKF,CAAK,CAAC;AAC1C;AAEA,SAASG,GACRC,GAC0B;AAC1B,MAAI,CAAC,MAAM,QAAQA,CAAW,KAAKA,EAAY,SAAS,EAAG,QAAO,CAAA;AAClE,QAAMC,IAAMD,EAAY,IAAI,CAAC,CAACE,GAAGC,CAAC,MAAM,CAACD,GAAGC,CAAC,CAA0B,GACjEC,IAAQH,EAAI,CAAC,GACbI,IAAOJ,EAAIA,EAAI,SAAS,CAAC;AAC/B,SAAI,CAACG,KAAS,CAACC,IAAa,CAAA,MACxBD,EAAM,CAAC,MAAMC,EAAK,CAAC,KAAKD,EAAM,CAAC,MAAMC,EAAK,CAAC,MAC9CJ,EAAI,KAAK,CAACG,EAAM,CAAC,GAAGA,EAAM,CAAC,CAAC,CAAC,GAEvBH;AACR;AAEA,SAASK,GACRC,GAC0B;AAC1B,MAAI,CAAC,MAAM,QAAQA,CAAM,KAAKA,EAAO,WAAW,EAAG,QAAO,CAAA;AAC1D,QAAMN,IAA+B,CAAA;AACrC,aAAWO,KAASD,GAAQ;AAC3B,QAAI,CAAC,MAAM,QAAQC,CAAK,KAAKA,EAAM,SAAS,EAAG;AAC/C,UAAMN,IAAI,OAAOM,EAAM,CAAC,CAAC,GACnBL,IAAI,OAAOK,EAAM,CAAC,CAAC;AACzB,QAAI,CAAC,OAAO,SAASN,CAAC,KAAK,CAAC,OAAO,SAASC,CAAC,EAAG;AAChD,UAAMM,IAAOR,EAAIA,EAAI,SAAS,CAAC;AAC/B,IAAIQ,KAAQ,KAAK,IAAIA,EAAK,CAAC,IAAIP,CAAC,IAAI,QAAQ,KAAK,IAAIO,EAAK,CAAC,IAAIN,CAAC,IAAI,QAGpEF,EAAI,KAAK,CAACC,GAAGC,CAAC,CAAC;AAAA,EAChB;AACA,SAAOF;AACR;AAEA,SAASS,GACRC,GACAC,GACAC,GAC0B;AAC1B,MAAID,KAAUnB,MAAcoB,IAAQ,UAAU,CAAA;AAC9C,QAAMC,IAAgC,CAAA;AACtC,WAAS,IAAI,GAAG,KAAKD,GAAO,KAAK,GAAG;AACnC,UAAME,IAAK,IAAIF,IAAS,KAAK,KAAK;AAClC,IAAAC,EAAK,KAAK;AAAA,MACTH,EAAO,CAAC,IAAI,KAAK,IAAII,CAAC,IAAIH;AAAA,MAC1BD,EAAO,CAAC,IAAI,KAAK,IAAII,CAAC,IAAIH;AAAA,IAAA,CAC1B;AAAA,EACF;AACA,SAAOb,GAAUe,CAAI;AACtB;AAEA,SAASE,GACRT,GACAK,GAC0B;AAC1B,MAAI,CAACL,EAAO,OAAQ,QAAO,CAAA;AAC3B,MAAIU,IAAO,OACPC,IAAO,OACPC,IAAO,QACPC,IAAO;AACX,aAAW,CAAClB,GAAGC,CAAC,KAAKI;AACpB,IAAIL,IAAIe,MAAMA,IAAOf,IACjBA,IAAIiB,MAAMA,IAAOjB,IACjBC,IAAIe,MAAMA,IAAOf,IACjBA,IAAIiB,MAAMA,IAAOjB;AAEtB,MAAI,CAAC,OAAO,SAASc,CAAI,KAAK,CAAC,OAAO,SAASC,CAAI,EAAG,QAAO,CAAA;AAC7D,QAAMG,IAAM,KAAK,IAAIT,GAAQ,CAAC;AAC9B,SAAOb,GAAU;AAAA,IAChB,CAACkB,IAAOI,GAAKH,IAAOG,CAAG;AAAA,IACvB,CAACF,IAAOE,GAAKH,IAAOG,CAAG;AAAA,IACvB,CAACF,IAAOE,GAAKD,IAAOC,CAAG;AAAA,IACvB,CAACJ,IAAOI,GAAKD,IAAOC,CAAG;AAAA,EAAA,CACvB;AACF;AAEA,SAASC,GACRf,GACAK,GACoB;AACpB,MAAIK,IAAO,OACPC,IAAO,OACPC,IAAO,QACPC,IAAO;AACX,aAAW,CAAClB,GAAGC,CAAC,KAAKI;AACpB,IAAIL,IAAIe,MAAMA,IAAOf,IACjBA,IAAIiB,MAAMA,IAAOjB,IACjBC,IAAIe,MAAMA,IAAOf,IACjBA,IAAIiB,MAAMA,IAAOjB;AAEtB,QAAMkB,IAAM,KAAK,IAAIT,GAAQ,CAAC;AAC9B,SAAO,CAACK,IAAOI,GAAKH,IAAOG,GAAKF,IAAOE,GAAKD,IAAOC,CAAG;AACvD;AAEA,SAASE,GACRC,GACAZ,GACAtD,GACe;AACf,QAAMmE,IAAgB,KAAK;AAAA,IAC1BpC;AAAA,IACA,OAAO/B,EAAQ,aAAa,KAAK;AAAA,EAAA,GAE5BoE,IAAkB,KAAK;AAAA,IAC5B;AAAA,IACA,KAAK,MAAMpE,EAAQ,mBAAmBgC,EAAyB;AAAA,EAAA,GAE1DqC,IAAgB,KAAK;AAAA,IAC1B;AAAA,IACA,KAAK,MAAMrE,EAAQ,iBAAiBiC,EAAuB;AAAA,EAAA,GAGtDqC,IAAa,KAAK,IAAI,MAAMJ,EAAO,CAAC,IAAIA,EAAO,CAAC,CAAC,GACjDK,IAAc,KAAK,IAAI,MAAML,EAAO,CAAC,IAAIA,EAAO,CAAC,CAAC;AACxD,MAAIM,IAAO,KAAK,IAAIL,GAAe,OAAO,OAAO,GAC7CM,IAAU,GACVrF,IAAQ,KAAK,KAAKkF,IAAaE,CAAI,IAAIC,IAAU,IAAI,GACrDpF,IAAS,KAAK,KAAKkF,IAAcC,CAAI,IAAIC,IAAU,IAAI;AAE3D,UACCrF,IAAQiF,KACRhF,IAASgF,KACTjF,IAAQC,IAAS+E,OAEjBI,KAAQ,MACRpF,IAAQ,KAAK,KAAKkF,IAAaE,CAAI,IAAIC,IAAU,IAAI,GACrDpF,IAAS,KAAK,KAAKkF,IAAcC,CAAI,IAAIC,IAAU,IAAI,GACnD,EAAAD,IAAO,KAAK,IAAIF,GAAYC,CAAW;AAA3C;AAKD,SAAAnF,IAAQ,KAAK,IAAI,GAAGA,CAAK,GACzBC,IAAS,KAAK,IAAI,GAAGA,CAAM,GAEpB;AAAA,IACN,MAAM6E,EAAO,CAAC;AAAA,IACd,MAAMA,EAAO,CAAC;AAAA,IACd,MAAAM;AAAA,IACA,SAAAC;AAAA,IACA,OAAArF;AAAA,IACA,QAAAC;AAAA,EAAA;AAEF;AAMA,SAASqF,GACRtF,GACAC,GAC4B;AAC5B,MAAI,OAAO,kBAAoB,KAAa;AAE3C,UAAMJ,IADS,IAAI,gBAAgBG,GAAOC,CAAM,EACzB,WAAW,MAAM,EAAE,oBAAoB,IAAM;AACpE,QAAIJ,EAAS,QAAOA;AAAA,EACrB;AACA,MAAI,OAAO,WAAa,KAAa;AACpC,UAAMD,IAAS,SAAS,cAAc,QAAQ;AAC9C,WAAAA,EAAO,QAAQI,GACfJ,EAAO,SAASK,GACTL,EAAO,WAAW,MAAM,EAAE,oBAAoB,IAAM;AAAA,EAC5D;AACA,SAAO;AACR;AAEA,SAAS2F,GACRzB,GACA0B,GACwB;AACxB,SAAO;AAAA,KACL1B,EAAM,CAAC,IAAI0B,EAAO,QAAQA,EAAO,OAAOA,EAAO;AAAA,KAC/C1B,EAAM,CAAC,IAAI0B,EAAO,QAAQA,EAAO,OAAOA,EAAO;AAAA,EAAA;AAElD;AAEA,SAASC,GACRC,GACAxB,GACAsB,GACa;AACb,QAAM3F,IAAUyF,GAAoBE,EAAO,OAAOA,EAAO,MAAM;AAC/D,MAAI,CAAC3F,EAAS,QAAO,IAAI,WAAW,CAAC;AAErC,EAAAA,EAAQ,UAAU,GAAG,GAAG2F,EAAO,OAAOA,EAAO,MAAM,GACnD3F,EAAQ,YAAY,WACpBA,EAAQ,cAAc,WACtBA,EAAQ,UAAU,SAClBA,EAAQ,WAAW,SACnBA,EAAQ,YAAaqE,IAAS,IAAKsB,EAAO;AAE1C,QAAM3B,IAAS6B,EAAK,IAAI,OAASH,GAAczB,GAAO0B,CAAM,CAAC;AAC7D,MAAI3B,EAAO,UAAU,GAAG;AACvB,UAAM8B,IAAI9B,EAAO,CAAC;AAClB,QAAI,CAAC8B,EAAG,QAAO,IAAI,WAAW,CAAC;AAC/B,IAAA9F,EAAQ,UAAA,GACRA,EAAQ,IAAI8F,EAAE,CAAC,GAAGA,EAAE,CAAC,GAAGzB,IAASsB,EAAO,MAAM,GAAG,KAAK,KAAK,CAAC,GAC5D3F,EAAQ,KAAA;AAAA,EACT,OAAO;AACN,IAAAA,EAAQ,UAAA,GACRA,EAAQ,OAAOgE,EAAO,CAAC,EAAE,CAAC,GAAGA,EAAO,CAAC,EAAE,CAAC,CAAC;AACzC,aAAS+B,IAAI,GAAGA,IAAI/B,EAAO,QAAQ+B,KAAK;AACvC,MAAA/F,EAAQ,OAAOgE,EAAO+B,CAAC,EAAE,CAAC,GAAG/B,EAAO+B,CAAC,EAAE,CAAC,CAAC;AAE1C,IAAA/F,EAAQ,OAAA;AAAA,EACT;AAEA,QAAMgG,IAAQhG,EAAQ,aAAa,GAAG,GAAG2F,EAAO,OAAOA,EAAO,MAAM,GAC9DjC,IAAM,IAAI,WAAWiC,EAAO,QAAQA,EAAO,MAAM;AACvD,WAASI,IAAI,GAAGA,IAAIrC,EAAI,QAAQqC,KAAK;AACpC,IAAArC,EAAIqC,CAAC,IAAIC,EAAM,KAAKD,IAAI,IAAI,CAAC,KAAK5C,KAAkB,IAAI;AAEzD,SAAOO;AACR;AAEA,SAASuC,GAAmBC,GAAkB/F,GAAeC,GAAgC;AAC5F,QAAM+F,IAAwB,CAAA,GACxB7E,IAASnB,IAAQ,GACjBiG,IAAS,CAACzC,GAAWC,MAAsBA,IAAItC,IAASqC,GACxD0C,IAAK,CAAC1C,GAAWC,MACtBD,KAAK,KAAKC,KAAK,KAAKD,IAAIxD,KAASyD,IAAIxD,KAAU8F,EAAKtC,IAAIzD,IAAQwD,CAAC,IAAI;AAEtE,WAASC,IAAI,GAAGA,IAAIxD,GAAQwD,KAAK;AAChC,aAASD,IAAI,GAAGA,IAAIxD,GAAOwD,KAAK;AAC/B,MAAK0C,EAAG1C,GAAGC,CAAC,MACPyC,EAAG1C,GAAGC,IAAI,CAAC,KACfuC,EAAM,KAAK;AAAA,QACV,OAAOC,EAAOzC,GAAGC,CAAC;AAAA,QAClB,KAAKwC,EAAOzC,IAAI,GAAGC,CAAC;AAAA,QACpB,KAAK;AAAA,MAAA,CACL,GAEGyC,EAAG1C,IAAI,GAAGC,CAAC,KACfuC,EAAM,KAAK;AAAA,QACV,OAAOC,EAAOzC,IAAI,GAAGC,CAAC;AAAA,QACtB,KAAKwC,EAAOzC,IAAI,GAAGC,IAAI,CAAC;AAAA,QACxB,KAAK;AAAA,MAAA,CACL,GAEGyC,EAAG1C,GAAGC,IAAI,CAAC,KACfuC,EAAM,KAAK;AAAA,QACV,OAAOC,EAAOzC,IAAI,GAAGC,IAAI,CAAC;AAAA,QAC1B,KAAKwC,EAAOzC,GAAGC,IAAI,CAAC;AAAA,QACpB,KAAK;AAAA,MAAA,CACL,GAEGyC,EAAG1C,IAAI,GAAGC,CAAC,KACfuC,EAAM,KAAK;AAAA,QACV,OAAOC,EAAOzC,GAAGC,IAAI,CAAC;AAAA,QACtB,KAAKwC,EAAOzC,GAAGC,CAAC;AAAA,QAChB,KAAK;AAAA,MAAA,CACL;AAKJ,SAAOuC;AACR;AAEA,SAASG,GAAaC,GAAiBC,GAAuB;AAC7D,QAAMC,KAASD,IAAQD,IAAU,KAAK;AACtC,SAAIE,MAAU,IAAU,IACpBA,MAAU,IAAU,IACpBA,MAAU,IAAU,IACjB;AACR;AAEA,SAASC,GAAWP,GAAmC;AACtD,MAAI,CAACA,EAAM,OAAQ,QAAO,CAAA;AAE1B,QAAMQ,wBAAe,IAAA;AACrB,WAAS,IAAI,GAAG,IAAIR,EAAM,QAAQ,KAAK,GAAG;AACzC,UAAMS,IAAQD,EAAS,IAAIR,EAAM,CAAC,EAAE,KAAK;AACzC,IAAIS,IACHA,EAAM,KAAK,CAAC,IAEZD,EAAS,IAAIR,EAAM,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;AAAA,EAElC;AAEA,QAAMU,IAAO,IAAI,WAAWV,EAAM,MAAM,GAClCW,IAAoB,CAAA;AAE1B,WAAS,IAAI,GAAG,IAAIX,EAAM,QAAQ,KAAK,GAAG;AACzC,QAAIU,EAAK,CAAC,EAAG;AAEb,UAAMhD,IAAQsC,EAAM,CAAC,GACfY,IAAclD,EAAM;AAC1B,QAAImD,IAAgBnD,EAAM,KACtBoD,IAAapD,EAAM;AACvB,UAAMqD,IAAiB,CAACrD,EAAM,OAAOA,EAAM,GAAG;AAC9C,IAAAgD,EAAK,CAAC,IAAI;AAEV,QAAIM,IAAQ;AACZ,UAAMC,IAAajB,EAAM,SAAS;AAClC,WAAOa,MAAkBD,KAAeI,IAAQC,KAAY;AAC3D,YAAMC,IAAaV,EAAS,IAAIK,CAAa;AAC7C,UAAI,CAACK,KAAcA,EAAW,WAAW,EAAG;AAE5C,UAAIC,IAAY,IACZC,IAAe;AACnB,iBAAWC,KAAaH,GAAY;AACnC,YAAIR,EAAKW,CAAS,EAAG;AACrB,cAAMC,IAAYtB,EAAMqB,CAAS,GAC3BE,IAAWpB,GAAaW,GAAYQ,EAAU,GAAG;AACvD,QAAIC,IAAWH,MACdA,IAAeG,GACfJ,IAAYE;AAAA,MAEd;AAEA,UAAIF,IAAY,EAAG;AACnB,MAAAT,EAAKS,CAAS,IAAI;AAClB,YAAMjH,IAAO8F,EAAMmB,CAAS;AAC5B,MAAAN,IAAgB3G,EAAK,KACrB4G,IAAa5G,EAAK,KAClB6G,EAAK,KAAKF,CAAa,GACvBG,KAAS;AAAA,IACV;AAEA,IACCD,EAAK,UAAU,KACfA,EAAK,CAAC,MAAMA,EAAKA,EAAK,SAAS,CAAC,KAEhCJ,EAAM,KAAKI,CAAI;AAAA,EAEjB;AAEA,SAAOJ;AACR;AAEA,SAASa,GACRC,GACAzH,GACAwF,GAC0B;AAC1B,QAAMrE,IAASnB,IAAQ,GACjBoE,IAAgC,CAAA;AACtC,aAAWsD,KAAMD,GAAY;AAC5B,UAAMjE,IAAIkE,IAAKvG,GACTsC,IAAI,KAAK,MAAMiE,IAAKvG,CAAM;AAChC,IAAAiD,EAAK,KAAK;AAAA,MACToB,EAAO,QAAQhC,IAAIgC,EAAO,WAAWA,EAAO;AAAA,MAC5CA,EAAO,QAAQ/B,IAAI+B,EAAO,WAAWA,EAAO;AAAA,IAAA,CAC5C;AAAA,EACF;AACA,SAAOnC,GAAUe,CAAI;AACtB;AAEA,SAASuD,GAAkBvD,GAAuC;AACjE,MAAIA,EAAK,SAAS,EAAG,QAAO;AAC5B,MAAIwD,IAAM;AACV,WAAShC,IAAI,GAAGA,IAAIxB,EAAK,SAAS,GAAGwB,KAAK,GAAG;AAC5C,UAAMiC,IAAIzD,EAAKwB,CAAC,GACVkC,IAAI1D,EAAKwB,IAAI,CAAC;AACpB,IAAAgC,KAAOC,EAAE,CAAC,IAAIC,EAAE,CAAC,IAAIA,EAAE,CAAC,IAAID,EAAE,CAAC;AAAA,EAChC;AACA,SAAOD,IAAM;AACd;AAEA,SAASG,GACR3D,GACA4D,IAAU,MACgB;AAC1B,QAAMC,IAAS5E,GAAUe,CAAI;AAC7B,MAAI6D,EAAO,SAAS,EAAG,QAAOA;AAC9B,QAAM1E,IAA+B,CAAC0E,EAAO,CAAC,CAAC;AAC/C,WAAS,IAAI,GAAG,IAAIA,EAAO,SAAS,GAAG,KAAK,GAAG;AAC9C,UAAMlE,IAAOR,EAAIA,EAAI,SAAS,CAAC,GACzB2E,IAAOD,EAAO,CAAC,GACf/H,IAAO+H,EAAO,IAAI,CAAC,GACnBE,KACJD,EAAK,CAAC,IAAInE,EAAK,CAAC,MAAM7D,EAAK,CAAC,IAAIgI,EAAK,CAAC,MACtCA,EAAK,CAAC,IAAInE,EAAK,CAAC,MAAM7D,EAAK,CAAC,IAAIgI,EAAK,CAAC;AACxC,IAAI,KAAK,IAAIC,CAAK,KAAKH,KACvBzE,EAAI,KAAK2E,CAAI;AAAA,EACd;AACA,SAAA3E,EAAI,KAAKA,EAAI,CAAC,CAAC,GACRF,GAAUE,CAAG;AACrB;AAEA,SAAS6E,GACRzC,GACAkC,GACAC,GACS;AACT,QAAMO,IAAMP,EAAE,CAAC,IAAID,EAAE,CAAC,GAChBS,IAAMR,EAAE,CAAC,IAAID,EAAE,CAAC,GAChBU,IAAOF,IAAMA,IAAMC,IAAMA;AAC/B,MAAIC,KAAQ,OAAO;AAClB,UAAMC,IAAK7C,EAAE,CAAC,IAAIkC,EAAE,CAAC,GACfY,IAAK9C,EAAE,CAAC,IAAIkC,EAAE,CAAC;AACrB,WAAOW,IAAKA,IAAKC,IAAKA;AAAAA,EACvB;AACA,QAAMpE,IAAIpB;AAAAA,MACP0C,EAAE,CAAC,IAAIkC,EAAE,CAAC,KAAKQ,KAAO1C,EAAE,CAAC,IAAIkC,EAAE,CAAC,KAAKS,KAAOC;AAAA,IAC9C;AAAA,IACA;AAAA,EAAA,GAEK/E,IAAIqE,EAAE,CAAC,IAAIQ,IAAMhE,GACjBZ,IAAIoE,EAAE,CAAC,IAAIS,IAAMjE,GACjBmE,IAAK7C,EAAE,CAAC,IAAInC,GACZiF,IAAK9C,EAAE,CAAC,IAAIlC;AAClB,SAAO+E,IAAKA,IAAKC,IAAKA;AACvB;AAEA,SAASC,GACR7E,GACA8E,GAC0B;AAC1B,MAAI9E,EAAO,UAAU,KAAK8E,KAAa,EAAG,QAAO9E,EAAO,MAAA;AAExD,QAAM+E,IAAO,IAAI,WAAW/E,EAAO,MAAM;AACzC,EAAA+E,EAAK,CAAC,IAAI,GACVA,EAAK/E,EAAO,SAAS,CAAC,IAAI;AAC1B,QAAMgF,IAAaF,IAAYA,GACzBG,IAAiC,CAAC,CAAC,GAAGjF,EAAO,SAAS,CAAC,CAAC;AAE9D,SAAOiF,EAAM,SAAS,KAAG;AACxB,UAAM5I,IAAO4I,EAAM,IAAA;AACnB,QAAI,CAAC5I,EAAM;AACX,UAAM,CAAC6I,GAAOC,CAAG,IAAI9I;AACrB,QAAI8I,IAAMD,KAAS,EAAG;AAEtB,QAAIE,IAAW,GACXC,IAAQ;AACZ,aAAStD,IAAImD,IAAQ,GAAGnD,IAAIoD,GAAKpD,KAAK,GAAG;AACxC,YAAMuD,IAAQf,GAAyBvE,EAAO+B,CAAC,GAAG/B,EAAOkF,CAAK,GAAGlF,EAAOmF,CAAG,CAAC;AAC5E,MAAIG,IAAQF,MACXA,IAAWE,GACXD,IAAQtD;AAAA,IAEV;AAEA,IAAIsD,KAAS,KAAKD,IAAWJ,MAC5BD,EAAKM,CAAK,IAAI,GACdJ,EAAM,KAAK,CAACC,GAAOG,CAAK,GAAG,CAACA,GAAOF,CAAG,CAAC;AAAA,EAEzC;AAEA,QAAMzF,IAA+B,CAAA;AACrC,WAASqC,IAAI,GAAGA,IAAI/B,EAAO,QAAQ+B,KAAK;AACvC,IAAIgD,EAAKhD,CAAC,OAAO,KAAK/B,EAAO+B,CAAC,CAAC;AAEhC,SAAOrC;AACR;AAEA,SAAS6F,GACRhF,GACAuE,GAC0B;AAC1B,QAAMV,IAAS5E,GAAUe,CAAI;AAC7B,MAAI6D,EAAO,SAAS,KAAKU,KAAa,EAAG,QAAOV;AAChD,QAAMoB,IAAOpB,EAAO,MAAM,GAAG,EAAE,GACzBqB,IAAaZ,GAAYW,GAAMV,CAAS;AAC9C,SAAIW,EAAW,SAAS,IAAUrB,IAC3B5E,GAAUiG,CAAU;AAC5B;AAEA,SAASC,GACRnF,GACAU,GAC0B;AAC1B,SAAKA,IACEzB;AAAAA,IACNe,EAAK,IAAI,CAAC,CAACZ,GAAGC,CAAC,MAAM;AAAA,MACpBR,GAAMO,GAAGsB,EAAO,CAAC,GAAGA,EAAO,CAAC,CAAC;AAAA,MAC7B7B,GAAMQ,GAAGqB,EAAO,CAAC,GAAGA,EAAO,CAAC,CAAC;AAAA,IAAA,CACJ;AAAA,EAAA,IALPV;AAOrB;AAEO,SAASoF,GACf9D,GACA9E,GAC0B;AAC1B,QAAMiD,IAASD,GAAa8B,CAAI,GAC1BxB,IAAS,KAAK,IAAInB,IAAY,OAAOnC,EAAQ,MAAM,KAAK,CAAC;AAC/D,MAAIiD,EAAO,WAAW,KAAK,CAAC,OAAO,SAASK,CAAM,EAAG,QAAO,CAAA;AAE5D,QAAMuF,IAAc,KAAK,IAAI,IAAI,KAAK,MAAM7I,EAAQ,eAAekC,EAAoB,CAAC;AACxF,MAAIe,EAAO,WAAW;AACrB,WAAO0F;AAAA,MACNvF,GAAoBH,EAAO,CAAC,GAAGK,GAAQuF,CAAW;AAAA,MAClD7I,EAAQ;AAAA,IAAA;AAIV,QAAMkE,IAASF,GAAsBf,GAAQK,CAAM,GAC7CwF,IAAS7E,GAAoBC,GAAQZ,GAAQtD,CAAO,GACpDmF,IAAON,GAAoB5B,GAAQK,GAAQwF,CAAM;AACvD,MAAI,CAAC3D,EAAK;AACT,WAAOwD,GAAkBjF,GAAqBT,GAAQK,CAAM,GAAGtD,EAAQ,UAAU;AAGlF,QAAMoF,IAAQF,GAAmBC,GAAM2D,EAAO,OAAOA,EAAO,MAAM,GAC5D/C,IAAQJ,GAAWP,CAAK;AAC9B,MAAI,CAACW,EAAM;AACV,WAAO4C,GAAkBjF,GAAqBT,GAAQK,CAAM,GAAGtD,EAAQ,UAAU;AAGlF,MAAI+I,IAAoC,CAAA,GACpCC,IAAW;AACf,aAAW7C,KAAQJ,GAAO;AACzB,UAAMvC,IAAOoD,GAAYT,GAAM2C,EAAO,OAAOA,CAAM,GAC7CG,IAAO,KAAK,IAAIlC,GAAkBvD,CAAI,CAAC;AAC7C,IAAIyF,KAAQD,MACZA,IAAWC,GACXF,IAAWvF;AAAA,EACZ;AAEA,MAAI,CAACuF,EAAS;AACb,WAAOJ,GAAkBjF,GAAqBT,GAAQK,CAAM,GAAGtD,EAAQ,UAAU;AAGlF,QAAM+H,IACL,OAAO/H,EAAQ,qBAAsB,YAAY,OAAO,SAASA,EAAQ,iBAAiB,IACvF,KAAK,IAAI,GAAGA,EAAQ,iBAAiB,IACrC8I,EAAO,OAAO,KACZJ,IAAaF;AAAA,IAClBrB,GAAwB4B,GAAUD,EAAO,OAAO,IAAI;AAAA,IACpDf;AAAA,EAAA;AAED,SAAOY,GAAkBD,GAAY1I,EAAQ,UAAU;AACxD;ACnjBO,MAAMkJ,KAAwD;AAAA,EACpE;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAChB;ACCO,SAAS7G,GAAMC,GAAeC,GAAaC,GAAqB;AACtE,SAAO,KAAK,IAAID,GAAK,KAAK,IAAIC,GAAKF,CAAK,CAAC;AAC1C;AAEO,SAAS6G,GACfC,GACAC,GACAC,GACS;AACT,QAAMC,IAAM,OAAOH,CAAQ,GACrBI,IAAK,OAAOH,CAAS,GACrBI,IAAK,OAAOH,CAAW;AAC7B,SAAI,CAAC,OAAO,SAASC,CAAG,KAAKA,KAAO,IAAU,IAC1C,CAAC,OAAO,SAASC,CAAE,KAAK,CAAC,OAAO,SAASC,CAAE,IAAUF,IAClD,KAAK,IAAI,GAAGC,IAAKC,CAAE,IAAIF;AAC/B;AAEO,SAASG,GACfN,GACAC,GACAC,GACS;AAET,MAAIK,IAAS,MADMR,GAAoBC,GAAUC,GAAWC,CAAW;AAEvE,MAAI,OAAOF,CAAQ,GAAG;AACrB,QAAIQ,IAAO;AACX,WAAID,IAAS,QACZA,KAAU,KACVC,IAAO,OAED,GAAGD,EAAO,YAAY,CAAC,CAAC,IAAIC,CAAI;AAAA,EACxC;AACA,SAAO,GAAG,KAAK,MAAMD,IAAS,GAAI,IAAI,GAAI;AAC3C;AAEO,SAASE,GACf5C,GACAC,GACU;AACV,SAAI,CAACD,KAAK,CAACC,IAAU,KACjB,CAACD,KAAK,CAACC,IAAU,KAEpB,KAAK,KAAKD,EAAE,QAAQ,MAAMC,EAAE,QAAQ,EAAE,IAAI,QAC1C,KAAK,KAAKD,EAAE,WAAW,MAAMC,EAAE,WAAW,EAAE,IAAI,QAChD,KAAK,KAAKD,EAAE,WAAW,MAAMC,EAAE,WAAW,EAAE,IAAI,QAChD,KAAK,KAAKD,EAAE,eAAe,MAAMC,EAAE,eAAe,EAAE,IAAI;AAE1D;AAEO,SAAS4C,GAAcxH,GAA0C;AACvE,QAAMyH,IAAU,OAAOzH,KAAS,EAAE,EAAE,KAAA;AACpC,MAAI,CAACyH,EAAS,QAAO;AACrB,MAAI,cAAc,KAAKA,CAAO,GAAG;AAChC,UAAMC,IAAQD,EAAQ,QAAQ,eAAe,EAAE,EAAE,KAAA;AACjD,WAAOC,IAAQ,UAAUA,CAAK,KAAK;AAAA,EACpC;AACA,SAAO,UAAUD,CAAO;AACzB;AAEO,SAASE,GACfC,GACmC;AAEnC,QAAMC,IADQ,OAAOD,KAAO,EAAE,EAAE,KAAA,EACZ,MAAM,sBAAsB;AAChD,MAAI,CAACC,EAAO,QAAO,CAAC,GAAGjB,EAAmB;AAE1C,QAAMkB,IAAI,OAAO,SAASD,EAAM,CAAC,GAAG,EAAE;AACtC,SAAO,CAAEC,KAAK,KAAM,KAAMA,KAAK,IAAK,KAAKA,IAAI,KAAK,GAAG;AACtD;AAEO,SAASC,GACfC,GAIc;AACd,QAAMC,IAAmD;AAAA,IACxD,CAAC,GAAGrB,EAAmB;AAAA,EAAA,GAElBsB,wBAAyB,IAAA;AAE/B,aAAWC,KAAQH,KAAS,IAAI;AAC/B,UAAMI,IAAS,OAAOD,GAAM,UAAU,EAAE;AACxC,IAAI,CAACC,KAAUF,EAAmB,IAAIE,CAAM,MAE5CF,EAAmB,IAAIE,GAAQH,EAAQ,MAAM,GAC7CA,EAAQ,KAAKN,GAAUQ,GAAM,SAAS,CAAC;AAAA,EACxC;AAEA,QAAME,IAAS,IAAI,WAAWJ,EAAQ,SAAS,CAAC;AAChD,WAAS,IAAI,GAAG,IAAIA,EAAQ,QAAQ,KAAK;AACxC,IAAAI,EAAO,IAAI,CAAC,IAAIJ,EAAQ,CAAC,EAAE,CAAC,GAC5BI,EAAO,IAAI,IAAI,CAAC,IAAIJ,EAAQ,CAAC,EAAE,CAAC,GAChCI,EAAO,IAAI,IAAI,CAAC,IAAIJ,EAAQ,CAAC,EAAE,CAAC,GAChCI,EAAO,IAAI,IAAI,CAAC,IAAIJ,EAAQ,CAAC,EAAE,CAAC;AAGjC,SAAO,EAAE,QAAAI,GAAQ,oBAAAH,EAAA;AAClB;AAEO,SAASlM,GACfL,GACAM,GACAC,GACe;AACf,QAAMoM,IAAK3M,EAAG,aAAaA,EAAG,aAAa,GACrC4M,IAAK5M,EAAG,aAAaA,EAAG,eAAe;AAC7C,MAAI,CAAC2M,KAAM,CAACC;AACX,UAAM,IAAI,MAAM,0BAA0B;AAK3C,MAFA5M,EAAG,aAAa2M,GAAIrM,CAAY,GAChCN,EAAG,cAAc2M,CAAE,GACf,CAAC3M,EAAG,mBAAmB2M,GAAI3M,EAAG,cAAc;AAC/C,UAAM,IAAI,MAAMA,EAAG,iBAAiB2M,CAAE,KAAK,uBAAuB;AAKnE,MAFA3M,EAAG,aAAa4M,GAAIrM,CAAc,GAClCP,EAAG,cAAc4M,CAAE,GACf,CAAC5M,EAAG,mBAAmB4M,GAAI5M,EAAG,cAAc;AAC/C,UAAM,IAAI,MAAMA,EAAG,iBAAiB4M,CAAE,KAAK,yBAAyB;AAGrE,QAAMlM,IAAUV,EAAG,cAAA;AACnB,MAAI,CAACU;AACJ,UAAM,IAAI,MAAM,2BAA2B;AAU5C,MAPAV,EAAG,aAAaU,GAASiM,CAAE,GAC3B3M,EAAG,aAAaU,GAASkM,CAAE,GAC3B5M,EAAG,YAAYU,CAAO,GAEtBV,EAAG,aAAa2M,CAAE,GAClB3M,EAAG,aAAa4M,CAAE,GAEd,CAAC5M,EAAG,oBAAoBU,GAASV,EAAG,WAAW;AAClD,UAAM,IAAI,MAAMA,EAAG,kBAAkBU,CAAO,KAAK,qBAAqB;AAGvE,SAAOA;AACR;AC4BA,MAAMmM,KAAY,2BACZC,KAAsB,GACtBC,KAAuB,GACvBC,KAAe,IACfC,KAAc,GACdC,KAA8B,CAAA,GAC9BC,KAAuB,CAAA,GACvBC,KAAiB,KACjBC,KAAmC,GACnCC,KAAgC,GAChCC,KAAqC,MACrCC,KAA6B,KAC7BC,KAAuB,MACvBC,KAAwB,MACxBC,KAAuB,IACvBC,KAA2B,WAC3BC,KAA6B,KAC7BC,KAA6B,WAC7BC,KAAoC,WACpCC,KAAkC,KAClCC,KAA4B,CAAC,GAAG,CAAC,GACjCC,KAA4B,GAC5BC,KAAwB,MACxBC,KAAwB,GACxBC,KAAwB,KACxBC,KAAgC,IAChCC,KAAoB,KAEpBC,KAAiD;AAAA,EACrD,OAAO;AAAA,EACP,OAAO;AAAA,EAEP,UAAU;AAAA,EACV,SAAS;AAAA,EACT,aAAa;AAAA,EACb,YAAY;AAAA,EACZ,eAAe;AAAA,EACf,eAAe;AACjB,GAEMC,KAAgD;AAAA,EACpD,OAAO;AAAA,EACP,OAAO;AAAA,EACP,UAAU,CAAC,IAAI,CAAC;AAAA,EAChB,UAAU;AAAA,EACV,SAAS;AAAA,EACT,aAAa;AAAA,EACb,YAAY;AAAA,EACZ,eAAe;AAAA,EACf,eAAe;AACjB,GAEMC,KAA+C;AAAA,EACnD,YAAY;AAAA,EACZ,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,iBAAiB;AAAA,EACjB,aAAa;AAAA,EACb,aAAa;AAAA,EACb,UAAU;AAAA,EACV,UAAU;AAAA,EACV,SAAS;AAAA,EACT,cAAc;AAChB;AAEA,SAAStK,GAAMC,GAAeC,GAAaC,GAAqB;AAC9D,SAAO,KAAK,IAAID,GAAK,KAAK,IAAIC,GAAKF,CAAK,CAAC;AAC3C;AAEA,SAASsK,GAAYC,GAAuC;AAC1D,SACEA,MAAS,qBAAqBA,MAAS,kBAAkBA,MAAS,4BAA4BA,MAAS,0BAA0BA,MAAS,uBAAuBA,MAAS;AAE9K;AAEA,SAASC,GAAwBxK,GAA2ByK,GAA0B;AACpF,SAAI,OAAOzK,KAAU,YAAY,CAAC,OAAO,SAASA,CAAK,KAAKA,KAAS,IAC5DyK,IAEFzK;AACT;AAEA,SAAS0K,GAAoBhN,GAA2D;AACtF,SAAO;AAAA,IACL,kBAAkB8M,GAAwB9M,GAAS,kBAAkBsL,EAAgC;AAAA,IACrG,eAAewB,GAAwB9M,GAAS,eAAeuL,EAA6B;AAAA,IAC5F,oBAAoBuB,GAAwB9M,GAAS,oBAAoBwL,EAAkC;AAAA,EAAA;AAE/G;AAEA,SAASyB,GAAiB3K,GAA2ByK,GAA0B;AAC7E,SAAI,OAAOzK,KAAU,YAAY,CAAC,OAAO,SAASA,CAAK,IAAUyK,IAC1D1K,GAAMC,GAAO,GAAG,CAAC;AAC1B;AAEA,SAAS4K,GAAsB5K,GAAuC;AACpE,MAAI,CAAC,MAAM,QAAQA,CAAK,EAAG,QAAO4J;AAClC,QAAMvJ,IAAML,EAAM,OAAO,CAAA6K,MAAQ,OAAO,SAASA,CAAI,KAAKA,KAAQ,CAAC;AACnE,SAAOxK,EAAI,SAAS,IAAIA,IAAMuJ;AAChC;AAEA,SAASkB,GAAuB9K,GAAmC;AACjE,SAAI,OAAOA,KAAU,YAAY,CAAC,OAAO,SAASA,CAAK,IAAU6J,KAC1D9J,GAAMC,GAAO8J,IAAuBC,EAAqB;AAClE;AAEA,SAASgB,GAAoBrN,GAAyD;AACpF,QAAMsD,IAASwJ,GAAwB9M,GAAS,QAAQ4L,EAAoB,GACtE0B,IAAkBR,GAAwB9M,GAAS,iBAAiBiM,EAA+B,GACnGsB,IAAaH,GAAuBpN,GAAS,UAAU;AAC7D,SAAO;AAAA,IACL,QAAAsD;AAAA,IACA,YAAAiK;AAAA,IACA,gBAAgBvN,GAAS,mBAAmB;AAAA,IAC5C,WAAWA,GAAS,aAAa6L;AAAA,IACjC,aAAaoB,GAAiBjN,GAAS,aAAa8L,EAA0B;AAAA,IAC9E,aAAa9L,GAAS,eAAe+L;AAAA,IACrC,mBAAmB/L,GAAS,qBAAqBgM;AAAA,IACjD,iBAAAsB;AAAA,IACA,gBAAgBJ,GAAsBlN,GAAS,cAAc;AAAA,EAAA;AAEjE;AAEA,SAASwN,GAASC,GAAyB;AACzC,SAAOA,IAAUpC,KAAiBA;AACpC;AAEA,SAASqC,GAAuBrK,GAA+BsK,GAAsC;AACnG,SAAI,CAACtK,KAAU,CAAC,OAAO,SAASsK,CAAU,KAAKA,KAAc,IAAU,CAAA,IAChElL,GAAU;AAAA,IACf,CAACY,EAAO,CAAC,IAAIsK,GAAYtK,EAAO,CAAC,IAAIsK,CAAU;AAAA,IAC/C,CAACtK,EAAO,CAAC,IAAIsK,GAAYtK,EAAO,CAAC,IAAIsK,CAAU;AAAA,IAC/C,CAACtK,EAAO,CAAC,IAAIsK,GAAYtK,EAAO,CAAC,IAAIsK,CAAU;AAAA,IAC/C,CAACtK,EAAO,CAAC,IAAIsK,GAAYtK,EAAO,CAAC,IAAIsK,CAAU;AAAA,EAAA,CAChD;AACH;AAEA,SAASC,GAAuBvK,GAA+BC,GAAgBC,IAAQ0H,IAAgC;AACrH,MAAI,CAAC5H,KAAU,CAAC,OAAO,SAASC,CAAM,KAAKA,KAAU,EAAG,QAAO,CAAA;AAE/D,QAAMuK,IAA2B,CAAA;AACjC,WAAS,IAAI,GAAG,KAAKtK,GAAO,KAAK,GAAG;AAClC,UAAME,IAAK,IAAIF,IAAS,KAAK,KAAK;AAClC,IAAAsK,EAAO,KAAK,CAACxK,EAAO,CAAC,IAAI,KAAK,IAAII,CAAC,IAAIH,GAAQD,EAAO,CAAC,IAAI,KAAK,IAAII,CAAC,IAAIH,CAAM,CAAC;AAAA,EAClF;AAEA,SAAOb,GAAUoL,CAAM;AACzB;AAEO,SAASpL,GAAUoL,GAA4C;AACpE,MAAI,CAAC,MAAM,QAAQA,CAAM,KAAKA,EAAO,SAAS,EAAG,QAAO,CAAA;AAExD,QAAMlL,IAAMkL,EAAO,IAAI,CAAC,CAACjL,GAAGC,CAAC,MAAM,CAACD,GAAGC,CAAC,CAAmB,GACrDC,IAAQH,EAAI,CAAC,GACbI,IAAOJ,EAAIA,EAAI,SAAS,CAAC;AAC/B,SAAI,CAACG,KAAS,CAACC,IAAa,CAAA,MAExBD,EAAM,CAAC,MAAMC,EAAK,CAAC,KAAKD,EAAM,CAAC,MAAMC,EAAK,CAAC,MAC7CJ,EAAI,KAAK,CAACG,EAAM,CAAC,GAAGA,EAAM,CAAC,CAAC,CAAC,GAGxBH;AACT;AAEO,SAASmL,GAAgB3F,GAA8BC,GAA8C;AAC1G,SAAI,CAACD,KAAS,CAACC,IAAY,CAAA,IAEpB3F,GAAU;AAAA,IACf,CAAC0F,EAAM,CAAC,GAAGA,EAAM,CAAC,CAAC;AAAA,IACnB,CAACC,EAAI,CAAC,GAAGD,EAAM,CAAC,CAAC;AAAA,IACjB,CAACC,EAAI,CAAC,GAAGA,EAAI,CAAC,CAAC;AAAA,IACf,CAACD,EAAM,CAAC,GAAGC,EAAI,CAAC,CAAC;AAAA,EAAA,CAClB;AACH;AAEO,SAAS2F,GAAa5F,GAA8BC,GAA4B7E,IAAQ0H,IAAgC;AAC7H,MAAI,CAAC9C,KAAS,CAACC,UAAY,CAAA;AAE3B,QAAM4F,KAAW7F,EAAM,CAAC,IAAIC,EAAI,CAAC,KAAK,KAChC6F,KAAW9F,EAAM,CAAC,IAAIC,EAAI,CAAC,KAAK,KAChC9E,IAAS,KAAK,MAAM8E,EAAI,CAAC,IAAID,EAAM,CAAC,GAAGC,EAAI,CAAC,IAAID,EAAM,CAAC,CAAC,IAAI;AAClE,MAAI7E,IAAS,EAAG,QAAO,CAAA;AAEvB,QAAMuK,IAA2B,CAAA;AACjC,WAAS7I,IAAI,GAAGA,KAAKzB,GAAOyB,KAAK,GAAG;AAClC,UAAMvB,IAAKuB,IAAIzB,IAAS,KAAK,KAAK;AAClC,IAAAsK,EAAO,KAAK,CAACG,IAAU,KAAK,IAAIvK,CAAC,IAAIH,GAAQ2K,IAAU,KAAK,IAAIxK,CAAC,IAAIH,CAAM,CAAC;AAAA,EAC9E;AAEA,SAAOb,GAAUoL,CAAM;AACzB;AAEA,SAASK,GAAYL,GAAkC;AACrD,MAAI,CAAC,MAAM,QAAQA,CAAM,KAAKA,EAAO,SAAS,EAAG,QAAO;AAExD,MAAI7G,IAAM;AACV,WAAShC,IAAI,GAAGA,IAAI6I,EAAO,SAAS,GAAG7I,KAAK,GAAG;AAC7C,UAAMiC,IAAI4G,EAAO7I,CAAC,GACZkC,IAAI2G,EAAO7I,IAAI,CAAC;AACtB,IAAAgC,KAAOC,EAAE,CAAC,IAAIC,EAAE,CAAC,IAAIA,EAAE,CAAC,IAAID,EAAE,CAAC;AAAA,EACjC;AAEA,SAAO,KAAK,IAAID,IAAM,GAAG;AAC3B;AAEA,SAASmH,GAAcN,GAAsC;AAC3D,MAAI,CAAC,MAAM,QAAQA,CAAM,KAAKA,EAAO,WAAW,EAAG,QAAO,CAAC,GAAG,GAAG,GAAG,CAAC;AAErE,MAAIlK,IAAO,OACPC,IAAO,OACPC,IAAO,QACPC,IAAO;AAEX,aAAW,CAAClB,GAAGC,CAAC,KAAKgL;AACnB,IAAIjL,IAAIe,MAAMA,IAAOf,IACjBA,IAAIiB,MAAMA,IAAOjB,IACjBC,IAAIe,MAAMA,IAAOf,IACjBA,IAAIiB,MAAMA,IAAOjB;AAGvB,SAAO,CAACc,GAAMC,GAAMC,GAAMC,CAAI;AAChC;AAEA,SAASsK,GAAeP,GAAmC;AACzD,SAAO,MAAM,QAAQA,CAAM,KAAKA,EAAO,UAAU,KAAKK,GAAYL,CAAM,IAAI3C;AAC9E;AAEA,SAASmD,GAAUC,GAA+BrL,GAA0BsL,IAAQ,IAAa;AAC/F,MAAItL,EAAO,WAAW,GAEtB;AAAA,IAAAqL,EAAI,OAAOrL,EAAO,CAAC,EAAE,CAAC,GAAGA,EAAO,CAAC,EAAE,CAAC,CAAC;AACrC,aAAS+B,IAAI,GAAGA,IAAI/B,EAAO,QAAQ+B,KAAK;AACtC,MAAAsJ,EAAI,OAAOrL,EAAO+B,CAAC,EAAE,CAAC,GAAG/B,EAAO+B,CAAC,EAAE,CAAC,CAAC;AAGvC,IAAIuJ,KACFD,EAAI,UAAA;AAAA;AAER;AAEA,SAASE,GAASF,GAA+BrL,GAA0BwL,GAAgCF,IAAQ,IAAOG,IAAO,IAAa;AAC5I,EAAIzL,EAAO,WAAW,MAEtBqL,EAAI,UAAA,GACJD,GAAUC,GAAKrL,GAAQsL,CAAK,GACxBG,KAAQH,MACVD,EAAI,YAAYxD,IAChBwD,EAAI,KAAA,IAGNA,EAAI,cAAcG,EAAY,OAC9BH,EAAI,YAAYG,EAAY,OAC5BH,EAAI,WAAWG,EAAY,UAC3BH,EAAI,UAAUG,EAAY,SAC1BH,EAAI,cAAcG,EAAY,aAC9BH,EAAI,aAAaG,EAAY,YAC7BH,EAAI,gBAAgBG,EAAY,eAChCH,EAAI,gBAAgBG,EAAY,eAChCH,EAAI,YAAYG,EAAY,QAAQ,GACpCH,EAAI,OAAA,GACJA,EAAI,YAAYlD,EAAU,GAC1BkD,EAAI,cAAc,oBAClBA,EAAI,aAAa,GACjBA,EAAI,gBAAgB,GACpBA,EAAI,gBAAgB;AACtB;AAEA,SAASK,GAAmBC,GAAkE;AAC5F,QAAMC,IAAO,MAAM,QAAQD,GAAO,QAAQ,IAAIA,EAAM,SAAS,OAAO,CAAAtM,MAAS,OAAO,SAASA,CAAK,KAAKA,KAAS,CAAC,IAAI8I,IAC/GhM,IAAQ,OAAOwP,GAAO,SAAU,YAAY,OAAO,SAASA,EAAM,KAAK,IAAI,KAAK,IAAI,GAAGA,EAAM,KAAK,IAAInC,GAA4B,OAClIqC,IAAa,OAAOF,GAAO,cAAe,YAAY,OAAO,SAASA,EAAM,UAAU,IAAI,KAAK,IAAI,GAAGA,EAAM,UAAU,IAAInC,GAA4B,YACtJsC,IAAgB,OAAOH,GAAO,iBAAkB,YAAY,OAAO,SAASA,EAAM,aAAa,IAAIA,EAAM,gBAAgBnC,GAA4B,eACrJuC,IAAgB,OAAOJ,GAAO,iBAAkB,YAAY,OAAO,SAASA,EAAM,aAAa,IAAIA,EAAM,gBAAgBnC,GAA4B;AAC3J,SAAO;AAAA,IACL,OAAOmC,GAAO,SAASnC,GAA4B;AAAA,IACnD,OAAArN;AAAA,IACA,UAAUyP,EAAK,SAASA,IAAOzD;AAAA,IAC/B,UAAUwD,GAAO,YAAYnC,GAA4B;AAAA,IACzD,SAASmC,GAAO,WAAWnC,GAA4B;AAAA,IACvD,aAAamC,GAAO,eAAenC,GAA4B;AAAA,IAC/D,YAAAqC;AAAA,IACA,eAAAC;AAAA,IACA,eAAAC;AAAA,EAAA;AAEJ;AAEA,SAASC,GAAiBC,GAAyBC,GAAqE;AACtH,SAAKA,IACER,GAAmB;AAAA,IACxB,OAAOQ,EAAS,SAASD,EAAK;AAAA,IAC9B,OAAOC,EAAS,SAASD,EAAK;AAAA,IAC9B,UAAUC,EAAS,YAAYD,EAAK;AAAA,IACpC,UAAUC,EAAS,YAAYD,EAAK;AAAA,IACpC,SAASC,EAAS,WAAWD,EAAK;AAAA,IAClC,aAAaC,EAAS,eAAeD,EAAK;AAAA,IAC1C,YAAYC,EAAS,cAAcD,EAAK;AAAA,IACxC,eAAeC,EAAS,iBAAiBD,EAAK;AAAA,IAC9C,eAAeC,EAAS,iBAAiBD,EAAK;AAAA,EAAA,CAC/C,IAXqBA;AAYxB;AAEA,SAASE,GAAenI,GAAuCC,GAAgD;AAC7G,SAAID,KAAM,QAA2BC,MAAM,QAAQA,MAAM,SAChD,KAEF,OAAOD,CAAC,MAAM,OAAOC,CAAC;AAC/B;AAEA,SAASmI,GAAwB3M,GAA8C;AAC7E,QAAMI,IAAQJ,EAAY,CAAC;AAC3B,SAAO,MAAM,QAAQI,CAAK,KAAK,MAAM,QAAQA,EAAM,CAAC,CAAC;AACvD;AAEA,SAASwM,GAAehN,GAAiC;AACvD,SAAO,OAAOA,KAAU,YAAY,OAAO,SAASA,CAAK;AAC3D;AAEA,SAASiN,GAAiBjN,GAA2C;AACnE,SAAO,MAAM,QAAQA,CAAK,KAAKA,EAAM,UAAU,KAAKgN,GAAehN,EAAM,CAAC,CAAC,KAAKgN,GAAehN,EAAM,CAAC,CAAC;AACzG;AAEA,SAASkN,GAAiBlN,GAA2C;AACnE,SAAO,MAAM,QAAQA,CAAK,KAAKA,EAAM,UAAU,KAAKA,EAAM,MAAM,CAAAY,MAASqM,GAAiBrM,CAAK,CAAC;AAClG;AAEA,SAASuM,GAAoBnN,GAAgBK,GAA+B;AAC1E,MAAI,GAAC,MAAM,QAAQL,CAAK,KAAKA,EAAM,WAAW,IAC9C;AAAA,QAAIkN,GAAiBlN,CAAK,GAAG;AAC3B,MAAAK,EAAI,KAAKL,EAAM,IAAI,CAAC,CAACM,GAAGC,CAAC,MAAM,CAACD,GAAGC,CAAC,CAAmB,CAAC;AACxD;AAAA,IACF;AACA,eAAWsK,KAAQ7K;AACjB,MAAAmN,GAAoBtC,GAAMxK,CAAG;AAAA;AAEjC;AAEA,SAAS+M,GAAsBhN,GAAqC6L,GAAoC;AACtG,QAAMoB,IAAkC,CAAA;AACxC,EAAAF,GAAoB/M,GAAaiN,CAAW;AAC5C,QAAMhN,IAA0B,CAAA;AAChC,aAAWa,KAAQmM,GAAa;AAC9B,QAAInM,EAAK,SAAS,EAAG;AACrB,UAAMoM,IAAarB,IAAQ9L,GAAUe,CAAI,IAAIA;AAC7C,IAAIoM,EAAW,WAAWrB,IAAQ,IAAI,MACpC5L,EAAI,KAAKiN,CAAU;AAAA,EAEvB;AACA,SAAOjN;AACT;AAEA,SAASkN,GAAqBvB,GAA+BwB,GAA6BC,GAA+BC,GAAyB;AAChJ,MAAI,EAAAF,EAAU,SAAS,KAAKC,EAAU,WAAW,IACjD;AAAA,IAAAzB,EAAI,KAAA,GACJA,EAAI,UAAA,GACJD,GAAUC,GAAKwB,GAAW,EAAI;AAC9B,eAAWtM,KAAQuM;AACjB,MAAIvM,EAAK,SAAS,KAClB6K,GAAUC,GAAK9K,GAAM,EAAI;AAE3B,IAAA8K,EAAI,YAAY0B,GAChB1B,EAAI,KAAK,SAAS,GAClBA,EAAI,QAAA;AAAA;AACN;AAEA,SAAS2B,GAAkBrB,GAAgE;AACzF,QAAMsB,IAAK,OAAOtB,GAAO,YAAa,YAAY,OAAO,SAASA,EAAM,QAAQ,IAAI,KAAK,IAAI,GAAGA,EAAM,QAAQ,IAAIjC,GAA2B,UACvIwD,IAAK,OAAOvB,GAAO,YAAa,YAAY,OAAO,SAASA,EAAM,QAAQ,IAAI,KAAK,IAAI,GAAGA,EAAM,QAAQ,IAAIjC,GAA2B,UACvI9B,IAAK,OAAO+D,GAAO,YAAa,YAAY,OAAO,SAASA,EAAM,QAAQ,IAAI,KAAK,IAAI,GAAGA,EAAM,QAAQ,IAAIjC,GAA2B,UACvIyD,IAAK,OAAOxB,GAAO,eAAgB,YAAY,OAAO,SAASA,EAAM,WAAW,IAAI,KAAK,IAAI,GAAGA,EAAM,WAAW,IAAIjC,GAA2B,aAChJ0D,IAAK,OAAOzB,GAAO,WAAY,YAAY,OAAO,SAASA,EAAM,OAAO,IAAIA,EAAM,UAAUjC,GAA2B,SACvH2D,IAAK,OAAO1B,GAAO,gBAAiB,YAAY,OAAO,SAASA,EAAM,YAAY,IAAI,KAAK,IAAI,GAAGA,EAAM,YAAY,IAAIjC,GAA2B;AACzJ,SAAO;AAAA,IACL,YAAYiC,GAAO,cAAcjC,GAA2B;AAAA,IAC5D,UAAU9B;AAAA,IACV,YAAY+D,GAAO,cAAcjC,GAA2B;AAAA,IAC5D,WAAWiC,GAAO,aAAajC,GAA2B;AAAA,IAC1D,iBAAiBiC,GAAO,mBAAmBjC,GAA2B;AAAA,IACtE,aAAaiC,GAAO,eAAejC,GAA2B;AAAA,IAC9D,aAAayD;AAAA,IACb,UAAUF;AAAA,IACV,UAAUC;AAAA,IACV,SAASE;AAAA,IACT,cAAcC;AAAA,EAAA;AAElB;AAEA,SAASC,GAAgBjC,GAA+B1L,GAAWC,GAAWzD,GAAeC,GAAgBiE,GAAsB;AACjI,QAAMkN,IAAI,KAAK,IAAI,GAAG,KAAK,IAAIlN,GAAQlE,IAAQ,KAAKC,IAAS,GAAG,CAAC;AACjE,EAAAiP,EAAI,UAAA,GACJA,EAAI,OAAO1L,IAAI4N,GAAG3N,CAAC,GACnByL,EAAI,OAAO1L,IAAIxD,IAAQoR,GAAG3N,CAAC,GAC3ByL,EAAI,iBAAiB1L,IAAIxD,GAAOyD,GAAGD,IAAIxD,GAAOyD,IAAI2N,CAAC,GACnDlC,EAAI,OAAO1L,IAAIxD,GAAOyD,IAAIxD,IAASmR,CAAC,GACpClC,EAAI,iBAAiB1L,IAAIxD,GAAOyD,IAAIxD,GAAQuD,IAAIxD,IAAQoR,GAAG3N,IAAIxD,CAAM,GACrEiP,EAAI,OAAO1L,IAAI4N,GAAG3N,IAAIxD,CAAM,GAC5BiP,EAAI,iBAAiB1L,GAAGC,IAAIxD,GAAQuD,GAAGC,IAAIxD,IAASmR,CAAC,GACrDlC,EAAI,OAAO1L,GAAGC,IAAI2N,CAAC,GACnBlC,EAAI,iBAAiB1L,GAAGC,GAAGD,IAAI4N,GAAG3N,CAAC,GACnCyL,EAAI,UAAA;AACN;AAEA,SAASmC,GAAa5C,GAAiD;AACrE,MAAI,CAACA,EAAO,OAAQ,QAAO;AAE3B,MAAIjK,IAAO;AACX,aAAWV,KAAS2K;AAClB,IAAI3K,EAAM,CAAC,IAAIU,MAAMA,IAAOV,EAAM,CAAC;AAErC,MAAI,CAAC,OAAO,SAASU,CAAI,EAAG,QAAO;AAEnC,MAAID,IAAO,OACPE,IAAO;AACX,aAAWX,KAAS2K;AAClB,IAAI,KAAK,IAAI3K,EAAM,CAAC,IAAIU,CAAI,IAAI,QAC5BV,EAAM,CAAC,IAAIS,MAAMA,IAAOT,EAAM,CAAC,IAC/BA,EAAM,CAAC,IAAIW,MAAMA,IAAOX,EAAM,CAAC;AAGrC,SAAI,CAAC,OAAO,SAASS,CAAI,KAAK,CAAC,OAAO,SAASE,CAAI,IAAU,OACtD,EAAEF,IAAOE,KAAQ,KAAKD,CAAI;AACnC;AAEA,SAAS8M,GAAgBpC,GAA+BqC,GAAcC,GAAwBC,GAAqBC,GAAsBC,GAAoC;AAC3K,QAAMC,IAAQL,EAAK,KAAA;AACnB,MAAI,CAACK,EAAO;AAEZ,EAAA1C,EAAI,KAAA,GACJA,EAAI,OAAO,GAAGyC,EAAW,UAAU,IAAIA,EAAW,QAAQ,MAAMA,EAAW,UAAU,IACrFzC,EAAI,YAAY,UAChBA,EAAI,eAAe;AAGnB,QAAM2C,IADY3C,EAAI,YAAY0C,CAAK,EAAE,QACZD,EAAW,WAAW,GAC7CG,IAAYH,EAAW,WAAWA,EAAW,WAAW,GAExDnO,IAAIP,GAAMuO,EAAO,CAAC,GAAGK,IAAW,MAAM,GAAGJ,IAAcI,IAAW,MAAM,CAAC,GACzEpO,IAAIR,GAAMuO,EAAO,CAAC,IAAIG,EAAW,SAASG,IAAY,MAAM,GAAGJ,IAAeI,IAAY,MAAM,CAAC,GACjGC,IAAOvO,IAAIqO,IAAW,KACtBG,IAAMvO,IAAIqO,IAAY;AAE5B,EAAA5C,EAAI,YAAYyC,EAAW,iBAC3BzC,EAAI,cAAcyC,EAAW,aAC7BzC,EAAI,YAAYyC,EAAW,aAC3BR,GAAgBjC,GAAK6C,GAAMC,GAAKH,GAAUC,GAAWH,EAAW,YAAY,GAC5EzC,EAAI,KAAA,GACAyC,EAAW,cAAc,KAC3BzC,EAAI,OAAA,GAGNA,EAAI,YAAYyC,EAAW,WAC3BzC,EAAI,SAAS0C,GAAOpO,GAAGC,IAAI,GAAG,GAC9ByL,EAAI,QAAA;AACN;AAEA,SAAS+C,GAAWC,GAAuBC,GAAoBC,GAAqC;AAClG,SAAO,CAACnP,GAAMiP,EAAM,CAAC,GAAG,GAAGC,CAAU,GAAGlP,GAAMiP,EAAM,CAAC,GAAG,GAAGE,CAAW,CAAC;AACzE;AAEA,SAASC,GAAQnP,GAAyD;AACxE,MAAI,CAAC,MAAM,QAAQA,CAAK,KAAKA,EAAM,SAAS,EAAG,QAAO;AACtD,QAAMM,IAAI,OAAON,EAAM,CAAC,CAAC,GACnBO,IAAI,OAAOP,EAAM,CAAC,CAAC;AACzB,SAAI,CAAC,OAAO,SAASM,CAAC,KAAK,CAAC,OAAO,SAASC,CAAC,IAAU,OAChD,CAACD,GAAGC,CAAC;AACd;AAEO,SAAS6O,GAAU;AAAA,EACxB,MAAA7E;AAAA,EACA,YAAA0E;AAAA,EACA,aAAAC;AAAA,EACA,UAAApI;AAAA,EACA,WAAAC;AAAA,EACA,cAAAsI;AAAA,EACA,cAAAC;AAAA,EACA,cAAAC;AAAA,EACA,YAAAC;AAAA,EACA,gBAAAC;AAAA,EACA,iBAAAC;AAAA,EACA,SAAAC;AAAA,EACA,iBAAAC;AAAA,EACA,kBAAAC;AAAA,EACA,cAAAC;AAAA,EACA,mBAAAC;AAAA,EACA,mBAAAC;AAAA,EACA,wBAAAC;AAAA,EACA,yBAAAC;AAAA,EACA,kBAAAC;AAAA,EACA,0BAAAC;AAAA,EACA,eAAAC;AAAA,EACA,iBAAAC,KAAkB;AAAA,EAClB,gBAAAC,KAAiB;AAAA,EACjB,kBAAAC;AAAA,EACA,eAAAC;AAAA,EACA,WAAAC;AAAA,EACA,OAAApE;AACF,GAAuC;AACrC,QAAMqE,IAAYC,EAAiC,IAAI,GACjDC,KAAiBD,EAAO,EAAK,GAC7BE,KAA0BF,EAA4B,oBAAI,KAAK,GAC/DG,KAAcH,EAAiBrG,CAAI,GACnCyG,KAAaJ,EAAoB;AAAA,IACrC,WAAW;AAAA,IACX,WAAW;AAAA,IACX,OAAO;AAAA,IACP,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,QAAQ,CAAA;AAAA,IACR,aAAa;AAAA,EAAA,CACd,GAEKK,IAAStB,KAAWpF,MAAS,UAC7B2G,IAAyBC,GAAsB,MAC/CtB,KAAoBA,EAAiB,SAAS,IACzCA,IAEL,CAACE,KAAqBA,EAAkB,WAAW,IAC9ClH,KAEFkH,EAAkB,IAAI,CAAC3P,GAAagR,OAAW;AAAA,IACpD,IAAIA;AAAA,IACJ,aAAAhR;AAAA,EAAA,EACA,GACD,CAACyP,GAAkBE,CAAiB,CAAC,GAClCsB,IAAqBF,GAAsB,MAAMrB,KAAgBjH,IAAe,CAACiH,CAAY,CAAC,GAE9FwB,IAAsBH,GAAQ,MAAM9E,GAAmB2D,CAAiB,GAAG,CAACA,CAAiB,CAAC,GAC9FuB,IAA2BJ,GAAQ,MAAMxE,GAAiB2E,GAAqBrB,CAAsB,GAAG,CAACqB,GAAqBrB,CAAsB,CAAC,GACrJuB,IAA4BL,GAAQ,MAAMxE,GAAiB2E,GAAqBpB,CAAuB,GAAG,CAACoB,GAAqBpB,CAAuB,CAAC,GACxJuB,KAA2BN,GAAQ,MAAMxE,GAAiBvC,IAA4B+F,CAAgB,GAAG,CAACA,CAAgB,CAAC,GAE3HuB,KAAqBP,GAAQ,MAAMxD,GAAkB6C,CAAgB,GAAG,CAACA,CAAgB,CAAC,GAC1FmB,KAAuBR,GAAQ,MAAMzG,GAAoB2E,CAAY,GAAG,CAACA,CAAY,CAAC,GACtFuC,IAAuBT,GAAQ,MAAMpG,GAAoBuE,CAAY,GAAG,CAACA,CAAY,CAAC,GAEtFuC,KAAcV;AAAA,IAClB,OAAO;AAAA,MACL,UAAU;AAAA,MACV,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,SAAS;AAAA,MACT,aAAa;AAAA,MACb,eAAeF,IAAS,SAAS;AAAA,MACjC,QAAQA,IAAU1G,MAAS,UAAU,SAAS,cAAe;AAAA,MAC7D,GAAG+B;AAAA,IAAA;AAAA,IAEL,CAAC2E,GAAQ1G,GAAM+B,EAAK;AAAA,EAAA,GAGhBwF,KAAeC,EAAY,MAAM;AACrC,UAAMrV,IAASiU,EAAU;AACzB,QAAI,CAACjU,EAAQ;AAEb,UAAMkC,IAAOlC,EAAO,sBAAA,GACdqC,IAAM,KAAK,IAAI,GAAG,OAAO,oBAAoB,CAAC,GAC9CiT,IAAI,KAAK,IAAI,GAAG,KAAK,MAAMpT,EAAK,QAAQG,CAAG,CAAC,GAC5CkT,IAAI,KAAK,IAAI,GAAG,KAAK,MAAMrT,EAAK,SAASG,CAAG,CAAC;AAEnD,KAAIrC,EAAO,UAAUsV,KAAKtV,EAAO,WAAWuV,OAC1CvV,EAAO,QAAQsV,GACftV,EAAO,SAASuV;AAAA,EAEpB,GAAG,CAAA,CAAE,GAECC,IAAsBH;AAAA,IAC1B,CAACpR,MAA+C;AAC9C,YAAMwR,IAAY5C,EAAa;AAC/B,UAAI,CAAC4C,KAAaxR,EAAO,WAAW,UAAU,CAAA;AAE9C,YAAMN,IAAM,IAAI,MAAsBM,EAAO,MAAM;AACnD,eAAS+B,IAAI,GAAGA,IAAI/B,EAAO,QAAQ+B,KAAK,GAAG;AACzC,cAAMsM,IAAQG,GAAQgD,EAAU,cAAcxR,EAAO+B,CAAC,EAAE,CAAC,GAAG/B,EAAO+B,CAAC,EAAE,CAAC,CAAC,CAAC;AACzE,YAAI,CAACsM,EAAO,QAAO,CAAA;AACnB,QAAA3O,EAAIqC,CAAC,IAAIsM;AAAA,MACX;AACA,aAAO3O;AAAA,IACT;AAAA,IACA,CAACkP,CAAY;AAAA,EAAA,GAGT6C,IAA4BL;AAAA,IAChC,CAAChR,GAAwBsR,MAAgC;AACvD,UAAI,CAAC,OAAO,SAASA,CAAW,KAAKA,KAAe,EAAG,QAAO;AAC9D,YAAMF,IAAY5C,EAAa;AAC/B,UAAI,CAAC4C,EAAW,QAAO;AACvB,YAAMxN,IAAIwK,GAAQgD,EAAU,cAAcpR,EAAO,CAAC,GAAGA,EAAO,CAAC,CAAC,CAAC,GACzD6D,IAAIuK,GAAQgD,EAAU,cAAcpR,EAAO,CAAC,IAAIsR,GAAatR,EAAO,CAAC,CAAC,CAAC;AAC7E,aAAI,CAAC4D,KAAK,CAACC,IAAU,IACd,KAAK,MAAMA,EAAE,CAAC,IAAID,EAAE,CAAC,GAAGC,EAAE,CAAC,IAAID,EAAE,CAAC,CAAC;AAAA,IAC5C;AAAA,IACA,CAAC4K,CAAY;AAAA,EAAA,GAGT+C,KAAuBP;AAAA,IAC3B,CAACQ,MAA6B;AAC5B,UAAI,CAAC,OAAO,SAASA,CAAQ,KAAKA,KAAY,EAAG,QAAO;AAGxD,YAAMC,IAAW,OAAO1L,KAAa,YAAY,OAAO,SAASA,CAAQ,KAAKA,IAAW,IAAIA,IAAW,GAClG2L,IAAiB,OAAO1L,KAAc,YAAY,OAAO,SAASA,CAAS,IAAIA,IAAY,GAC3F2L,IAAcnD,EAAa,SAAS,eAAA,EAAiB,MACrDoD,IAAW,OAAOD,KAAgB,YAAY,OAAO,SAASA,CAAW,KAAKA,IAAc,IAAIA,IAAc,GAC9GE,IAAiBH,IAAiB,KAAK,KAAKE,CAAQ,GACpDE,IAAmB,KAAK,IAAI,MAAMhM,GAAoB2L,GAAUC,GAAgBG,CAAc,CAAC;AAErG,aADqBL,IAAWM,IACVF;AAAA,IACxB;AAAA,IACA,CAAC7L,GAAUC,GAAWwI,CAAY;AAAA,EAAA,GAG9BuD,KAAmBf;AAAA,IACvB,CAACgB,GAA0BhS,MAAoD;AAC7E,UAAI,CAACA,EAAQ,QAAO,CAAA;AAEpB,UAAIoK,IAAU;AACd,UAAI4H,MAAc,0BAA0B;AAC1C,cAAM1H,IAAasG,GAAqB,qBAAqB;AAE7D,eADcvG,GAAuBrK,GAAQsK,CAAU,EAC1C,IAAI,CAAAzK,MAASmO,GAAWnO,GAAOqO,GAAYC,CAAW,CAAC;AAAA,MACtE;AAOA,UALI6D,MAAc,qBAAqBA,MAAc,yBACnD5H,IAAU4H,MAAc,yBAAyB/J,KAAmC2I,GAAqB,oBAChGoB,MAAc,kBAAkBA,MAAc,uBAAuBA,MAAc,+BAC5F5H,IAAU4H,MAAc,4BAA4B5J,KAA6B4J,MAAc,sBAAsB9J,KAAgC0I,GAAqB,gBAExK,CAAC,OAAO,SAASxG,CAAO,KAAKA,KAAW,UAAU,CAAA;AAEtD,YAAM6H,IAAU9H,GAASC,CAAO;AAChC,UAAII,IAA2B,CAAA;AAC/B,UAAIwH,MAAc,qBAAqBA,MAAc,wBAAwB;AAC3E,cAAM1H,IAAaiH,GAAqB,KAAK,KAAKU,CAAO,IAAI,GAAG;AAChE,QAAAzH,IAASH,GAAuBrK,GAAQsK,CAAU;AAAA,MACpD,WAAW0H,MAAc,kBAAkBA,MAAc,uBAAuBA,MAAc,2BAA2B;AACvH,cAAM/R,IAASsR,GAAqB,KAAK,KAAKU,IAAU,KAAK,EAAE,CAAC;AAChE,QAAAzH,IAASD,GAAuBvK,GAAQC,CAAM;AAAA,MAChD;AAEA,aAAKuK,EAAO,SACLA,EAAO,IAAI,CAAA3K,MAASmO,GAAWnO,GAAOqO,GAAYC,CAAW,CAAC,IAD1C,CAAA;AAAA,IAE7B;AAAA,IACA,CAACoD,IAAsBrD,GAAYC,GAAayC,EAAoB;AAAA,EAAA,GAGhEsB,KAAqBlB,EAAY,MAAwB;AAC7D,UAAMmB,IAAUlC,GAAW;AAC3B,WAAI1G,GAAYC,CAAI,IACXuI,GAAiBvI,GAAM2I,EAAQ,WAAW,IAE/C3I,MAAS,UACJ,CAAA,IAEJ2I,EAAQ,YAET3I,MAAS,aACJ2I,EAAQ,SAEb3I,MAAS,cACJiB,GAAgB0H,EAAQ,OAAOA,EAAQ,OAAO,IAEnD3I,MAAS,aACJkB,GAAayH,EAAQ,OAAOA,EAAQ,OAAO,IAG7C,CAAA,IAZwB,CAAA;AAAA,EAajC,GAAG,CAAC3I,GAAMuI,EAAgB,CAAC,GAErBK,IAAyBpB;AAAA,IAC7B,CAAC/F,MAAwC;AACvC,YAAMkH,IAAUlC,GAAW;AAC3B,UAAI,CAACkC,EAAQ,aAAaA,EAAQ,OAAO,WAAW,EAAG;AAEvD,YAAME,IAAelB,EAAoBgB,EAAQ,MAAM;AACvD,UAAIE,EAAa,WAAW,EAAG;AAC/B,YAAM9E,IAAS4E,EAAQ,OAAOA,EAAQ,OAAO,SAAS,CAAC,KAAKA,EAAQ,OAAO,CAAC,GACtEG,IAAWjB,EAA0B9D,GAAQsD,EAAqB,MAAM;AAC9E,UAAI,GAAC,OAAO,SAASyB,CAAQ,KAAKA,KAAY,IAS9C;AAAA,YAPArH,EAAI,KAAA,GACJA,EAAI,cAAc4F,EAAqB,aACvC5F,EAAI,YAAY4F,EAAqB,WACrC5F,EAAI,cAAc4F,EAAqB,WACvC5F,EAAI,UAAU,SACdA,EAAI,WAAW,SACfA,EAAI,YAAYqH,IAAW,GACvBD,EAAa,WAAW;AAC1B,UAAApH,EAAI,UAAA,GACJA,EAAI,IAAIoH,EAAa,CAAC,EAAE,CAAC,GAAGA,EAAa,CAAC,EAAE,CAAC,GAAGC,GAAU,GAAG,KAAK,KAAK,CAAC,GACxErH,EAAI,KAAA;AAAA,aACC;AACL,UAAAA,EAAI,UAAA,GACJA,EAAI,OAAOoH,EAAa,CAAC,EAAE,CAAC,GAAGA,EAAa,CAAC,EAAE,CAAC,CAAC;AACjD,mBAAS1Q,IAAI,GAAGA,IAAI0Q,EAAa,QAAQ1Q,KAAK;AAC5C,YAAAsJ,EAAI,OAAOoH,EAAa1Q,CAAC,EAAE,CAAC,GAAG0Q,EAAa1Q,CAAC,EAAE,CAAC,CAAC;AAEnD,UAAAsJ,EAAI,OAAA;AAAA,QACN;AACA,QAAAA,EAAI,QAAA;AAAA;AAAA,IACN;AAAA,IACA,CAACkG,GAAqBE,GAA2BR,CAAoB;AAAA,EAAA,GAGjE0B,KAAkBvB;AAAA,IACtB,CAAC/F,MAAwC;AACvC,YAAMkH,IAAUlC,GAAW,SACrBuC,IAASL,EAAQ;AACvB,UAAI,CAACK,EAAQ;AACb,YAAMC,IAASrE,GAAQI,EAAa,SAAS,cAAcgE,EAAO,CAAC,GAAGA,EAAO,CAAC,CAAC,KAAK,CAAA,CAAE;AACtF,UAAI,CAACC,EAAQ;AACb,YAAMH,IAAWjB,EAA0BmB,GAAQ3B,EAAqB,MAAM;AAC9E,MAAI,CAAC,OAAO,SAASyB,CAAQ,KAAKA,KAAY,MAE9CrH,EAAI,KAAA,GACJA,EAAI,UAAA,GACJA,EAAI,IAAIwH,EAAO,CAAC,GAAGA,EAAO,CAAC,GAAGH,GAAU,GAAG,KAAK,KAAK,CAAC,GACtDrH,EAAI,cAAckH,EAAQ,YAAYtB,EAAqB,oBAAoBA,EAAqB,aACpG5F,EAAI,YAAY4F,EAAqB,iBACrC5F,EAAI,YAAY4F,EAAqB,cAAc,GACnD5F,EAAI,OAAA,GACJA,EAAI,YAAYlD,EAAU,GAC1BkD,EAAI,QAAA;AAAA,IACN;AAAA,IACA,CAACuD,GAAc6C,GAA2BR,CAAoB;AAAA,EAAA,GAG1D6B,KAAc1B,EAAY,MAAM;AACpC,IAAAD,GAAA;AAEA,UAAMpV,IAASiU,EAAU;AACzB,QAAI,CAACjU,EAAQ;AAEb,UAAMsP,IAAMtP,EAAO,WAAW,IAAI;AAClC,QAAI,CAACsP,EAAK;AAEV,UAAMjN,IAAM,KAAK,IAAI,GAAG,OAAO,oBAAoB,CAAC,GAC9CwP,IAAc7R,EAAO,QAAQqC,GAC7ByP,IAAe9R,EAAO,SAASqC;AAMrC,QALAiN,EAAI,aAAa,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,GACjCA,EAAI,UAAU,GAAG,GAAGtP,EAAO,OAAOA,EAAO,MAAM,GAC/CsP,EAAI,aAAajN,GAAK,GAAG,GAAGA,GAAK,GAAG,CAAC,GAGjCmS,EAAuB,SAAS;AAClC,eAASxO,IAAI,GAAGA,IAAIwO,EAAuB,QAAQxO,KAAK,GAAG;AACzD,cAAMgR,IAASxC,EAAuBxO,CAAC,GACjCxB,IAAOwS,GAAQ;AACrB,YAAI,CAACxS,KAAQA,EAAK,SAAS,EAAG;AAC9B,cAAM6D,IAAS5E,GAAUe,CAAI,GACvBsS,KAAStB,EAAoBnN,CAAM;AACzC,YAAIyO,GAAO,UAAU,GAAG;AACtB,gBAAMG,KAAYD,EAAO,MAAMhR,GACzBkR,KAAqC9G,GAAeyD,IAAgBoD,EAAS,IAAI,WAAW7G,GAAewD,IAAiBqD,EAAS,IAAI,UAAU;AACzJ,cAAIxH,KAAcyH,OAAU,WAAWpC,IAA4BoC,OAAU,UAAUrC,IAA2BD;AAElH,cAAIlB,GAA0B;AAC5B,kBAAMyD,IAAWzD,EAAyB;AAAA,cACxC,QAAAsD;AAAA,cACA,UAAUC;AAAA,cACV,aAAajR;AAAA,cACb,OAAAkR;AAAA,YAAA,CACD;AACD,YAAAzH,KAAcQ,GAAiBR,IAAa0H,KAAY,MAAS;AAAA,UACnE;AACA,UAAA3H,GAASF,GAAKwH,IAAQrH,IAAa,IAAM,EAAK;AAAA,QAChD;AAAA,MACF;AAGF,QAAIkF,EAAmB,SAAS;AAC9B,eAAS3O,IAAI,GAAGA,IAAI2O,EAAmB,QAAQ3O,KAAK,GAAG;AAErD,cAAMxB,IADSmQ,EAAmB3O,CAAC,GACd;AACrB,YAAI,CAACxB,KAAQA,EAAK,SAAS,EAAG;AAC9B,cAAM6D,IAAS5E,GAAUe,CAAI,GACvBsS,KAAStB,EAAoBnN,CAAM;AACzC,QAAIyO,GAAO,SAAS,KACpBtH,GAASF,GAAKwH,IAAQ/B,IAA0B,IAAM,EAAK;AAAA,MAC7D;AAGF,QAAI,MAAM,QAAQpB,CAAa,KAAKA,EAAc,SAAS,GAAG;AAC5D,YAAMyD,IAAe,EAAS,WAA0D,8BAClFC,IAAiB7B;AAAA,QACrB/R,GAAU;AAAA,UACR,CAAC,GAAG,CAAC;AAAA,UACL,CAAC8O,GAAY,CAAC;AAAA,UACd,CAACA,GAAYC,CAAW;AAAA,UACxB,CAAC,GAAGA,CAAW;AAAA,QAAA,CAChB;AAAA,MAAA;AAEH,eAASxM,IAAI,GAAGA,IAAI2N,EAAc,QAAQ3N,KAAK,GAAG;AAChD,cAAMsR,IAAQ3D,EAAc3N,CAAC;AAC7B,YAAI,CAACsR,GAAO,aAAa,UAAUA,EAAM,YAAY,GAAO;AAE5D,cAAMjP,KAASiP,EAAM,UAAUjH,GAAwBiH,EAAM,WAAW,GAClEC,KAAc7G,GAAsB4G,EAAM,aAAajP,EAAM;AAEnE,YAAIiP,EAAM,cAAc,WAAW;AACjC,gBAAMvG,KAAgC,CAAA,GAChCyG,IAAc9G,GAAsB4G,EAAM,aAAa,EAAI;AACjE,qBAAW9S,MAAQgT,GAAa;AAC9B,kBAAMV,KAAStB,EAAoBhR,EAAI;AACvC,YAAIsS,GAAO,UAAU,KACnB/F,GAAU,KAAK+F,EAAM;AAAA,UAEzB;AACA,cAAIM,GAAc;AAChB,kBAAMK,KAAW,OAAOH,EAAM,MAAMtR,CAAC,GAC/B0R,KAAiB,GAAGL,EAAe,MAAM,IAAIG,EAAY,MAAM,IAAIzG,GAAU,MAAM,IAAIuG,EAAM,aAAa,SAAS;AACzH,YAAIlD,GAAwB,QAAQ,IAAIqD,EAAQ,MAAMC,OACpDtD,GAAwB,QAAQ,IAAIqD,IAAUC,EAAc,GAC5D,QAAQ,MAAM,6BAA6B;AAAA,cACzC,IAAIJ,EAAM,MAAMtR;AAAA,cAChB,iBAAiBqR,EAAe;AAAA,cAChC,iBAAiBG,EAAY;AAAA,cAC7B,eAAezG,GAAU;AAAA,cACzB,WAAWuG,EAAM,aAAa;AAAA,YAAA,CAC/B;AAAA,UAEL;AACA,UAAAzG,GAAqBvB,GAAK+H,GAAgBtG,IAAWuG,EAAM,aAAa,SAAS;AAAA,QACnF;AAEA,YAAIC,GAAY,WAAW,EAAG;AAC9B,cAAM9H,KAAcQ,GAAiB2E,GAAqB0C,EAAM,UAAUA,EAAM,WAAW;AAC3F,mBAAW9S,MAAQ+S,IAAa;AAC9B,gBAAMT,IAAStB,EAAoBhR,EAAI;AACvC,UAAIsS,EAAO,SAAS,KACpBtH,GAASF,GAAKwH,GAAQrH,IAAapH,IAAQiP,EAAM,QAAQ,EAAK;AAAA,QAChE;AAAA,MACF;AAAA,IACF;AAEA,QAAI/C;AACF,UAAI1G,MAAS;AACX,QAAA4I,EAAuBnH,CAAG,GAC1BsH,GAAgBtH,CAAG;AAAA,WACd;AACL,cAAMqI,IAAUpB,GAAA;AAChB,YAAIoB,EAAQ,SAAS;AACnB,cAAI9J,MAAS,YAAY;AACvB,kBAAM+J,IAAOpC,EAAoBmC,CAAO;AACxC,YAAIC,EAAK,UAAU,KACjBpI,GAASF,GAAKsI,GAAMhD,GAAqB,IAAO,EAAK,GAEnDgD,EAAK,UAAU,KACjBpI,GAASF,GAAKkG,EAAoB/R,GAAUkU,CAAO,CAAC,GAAG/C,GAAqB,IAAM,EAAI;AAAA,UAE1F,OAAO;AACL,kBAAMiD,IAAUrC,EAAoBmC,CAAO;AAC3C,YAAIE,EAAQ,UAAU,KACpBrI,GAASF,GAAKuI,GAASjD,GAAqB,IAAM,EAAI;AAAA,UAE1D;AAAA,MAEJ;AAIF,QAAIJ,EAAuB,SAAS;AAClC,iBAAWwC,KAAUxC,GAAwB;AAC3C,YAAI,CAACwC,EAAO,MAAO;AACnB,cAAMxS,IAAOwS,GAAQ;AACrB,YAAI,CAACxS,KAAQA,EAAK,SAAS,EAAG;AAC9B,cAAM6D,IAAS5E,GAAUe,CAAI,GACvBsT,IAAcrG,GAAapJ,CAAM;AACvC,YAAI,CAACyP,EAAa;AAClB,cAAMC,KAAetF,GAAQI,EAAa,SAAS,cAAciF,EAAY,CAAC,GAAGA,EAAY,CAAC,CAAC,KAAK,CAAA,CAAE;AACtG,QAAKC,MACLrG,GAAgBpC,GAAK0H,EAAO,OAAOe,IAAclG,GAAaC,GAAckD,EAAkB;AAAA,MAChG;AAAA,EAEJ,GAAG;AAAA,IACDT;AAAA,IACA1G;AAAA,IACA0I;AAAA,IACAE;AAAA,IACAG;AAAA,IACAxB;AAAA,IACAI;AAAA,IACAjD;AAAA,IACAC;AAAA,IACAK;AAAA,IACA2B;AAAA,IACAb;AAAA,IACAC;AAAA,IACAC;AAAA,IACAe;AAAA,IACAC;AAAA,IACAC;AAAA,IACAH;AAAA,IACAI;AAAA,IACArB;AAAA,IACAsB;AAAA,EAAA,CACD,GAEKgD,IAAc3C,EAAY,MAAM;AACpC,IAAIlB,GAAe,YACnBA,GAAe,UAAU,IACzB,sBAAsB,MAAM;AAC1B,MAAAA,GAAe,UAAU,IACzB4C,GAAA;AAAA,IACF,CAAC;AAAA,EACH,GAAG,CAACA,EAAW,CAAC,GAEVkB,KAAe5C,EAAY,CAAC6C,IAAiB,OAAU;AAC3D,UAAM1B,IAAUlC,GAAW,SACrBtU,IAASiU,EAAU;AAEzB,QAAIjU,KAAUwW,EAAQ,cAAc,QAAQxW,EAAO,kBAAkBwW,EAAQ,SAAS;AACpF,UAAI;AACF,QAAAxW,EAAO,sBAAsBwW,EAAQ,SAAS;AAAA,MAChD,QAAQ;AAAA,MAER;AAGF,IAAAA,EAAQ,YAAY,IACpBA,EAAQ,YAAY,MACpBA,EAAQ,QAAQ,MAChBA,EAAQ,UAAU,MAClBA,EAAQ,SAAS,CAAA,GACjBA,EAAQ,cAAc,MACjB0B,MACH1B,EAAQ,SAAS;AAAA,EAErB,GAAG,CAAA,CAAE,GAEC2B,KAAU9C;AAAA,IACd,CAAC+C,MAAuE;AACtE,YAAM3C,IAAY5C,EAAa;AAC/B,UAAI,CAAC4C,KAAalD,KAAc,KAAKC,KAAe,EAAG,QAAO;AAE9D,YAAM6F,IAAM5F,GAAQgD,EAAU,cAAc2C,EAAM,SAASA,EAAM,OAAO,CAAC;AACzE,aAAKC,IACEhG,GAAWgG,GAAK9F,GAAYC,CAAW,IAD7B;AAAA,IAEnB;AAAA,IACA,CAACK,GAAcN,GAAYC,CAAW;AAAA,EAAA,GAGlC8F,KAAgBjD,EAAY,MAAM;AACtC,UAAMmB,IAAUlC,GAAW;AAC3B,QAAI,CAACkC,EAAQ,WAAW;AACtB,MAAAyB,GAAa,EAAI,GACjBD,EAAA;AACA;AAAA,IACF;AAEA,QAAItU,IAAgC,CAAA;AACpC,QAAImK,MAAS;AACX,MAAI2I,EAAQ,OAAO,UAAUzK,OAC3BrI,IAAcD,GAAU+S,EAAQ,MAAM;AAAA,aAE/B3I,MAAS;AAClB,MAAAnK,IAAcoL,GAAgB0H,EAAQ,OAAOA,EAAQ,OAAO;AAAA,aACnD3I,MAAS;AAClB,MAAAnK,IAAcqL,GAAayH,EAAQ,OAAOA,EAAQ,OAAO;AAAA,aAChD3I,MAAS,SAAS;AAC3B,YAAM0K,IAAW/B,EAAQ,OAAOA,EAAQ,OAAO,SAAS,CAAC,KAAKA,EAAQ,WAAWA,EAAQ;AACzF,UAAItB,EAAqB,kBAAkBqD,KAAY/B,EAAQ,OAAO,UAAU,KAAK1D,IAAayF,CAAQ,GAAG;AAC3G,QAAAN,GAAa,EAAI,GACjBD,EAAA;AACA;AAAA,MACF;AACA,YAAMzJ,IAAa2G,EAAqB,YAClC/P,IAAgB,KAAK;AAAA,QACzBmI;AAAA,QACC4H,EAAqB,SAAS,KAAM3H,KAAgCgB;AAAA,MAAA;AAEvE,MAAA7K,IAAckG,GAAwB4M,EAAQ,QAAQ;AAAA,QACpD,QAAQtB,EAAqB;AAAA,QAC7B,YAAY,CAAC,GAAG,GAAG3C,GAAYC,CAAW;AAAA,QAC1C,eAAArN;AAAA,QACA,aAAa,KAAK,IAAI,IAAI,KAAK,MAAM,KAAKoJ,CAAU,CAAC;AAAA,QACrD,mBAAmBpJ,IAAgB;AAAA,MAAA,CACpC;AAAA,IACH;AAEA,KAAK0I,MAAS,cAAcA,MAAS,eAAeA,MAAS,cAAcA,MAAS,YAAYuB,GAAe1L,CAAW,KAAKqP,KAE7HA,EAAe;AAAA,MACb,MAAAlF;AAAA,MACA,QAHyBA,MAAS,UAAU,UAAU;AAAA,MAItD,aAAAnK;AAAA,MACA,MAAMyL,GAAczL,CAAW;AAAA,MAC/B,QAAQwL,GAAYxL,CAAW;AAAA,IAAA,CAChC,GAGHuU,GAAa,EAAI,GACjBD,EAAA;AAAA,EACF,GAAG,CAACnK,GAAMkF,GAAgBkF,IAAcD,GAAa9C,EAAqB,QAAQA,EAAqB,YAAYA,EAAqB,gBAAgB3C,GAAYC,GAAaM,CAAU,CAAC,GAEtL0F,KAAgBnD;AAAA,IACpB,CAACgB,GAA0BhS,MAAiC;AAC1D,YAAMX,IAAc0S,GAAiBC,GAAWhS,CAAM;AACtD,UAAI,CAAC+K,GAAe1L,CAAW,EAAG;AAClC,YAAM+U,IAAqBpC,MAAc,2BAA2B,UAAU,OACxEqC,IAAqB;AAAA,QACzB,MAAMrC;AAAA,QACN,QAAAoC;AAAA,QACA,aAAA/U;AAAA,QACA,MAAMyL,GAAczL,CAAW;AAAA,QAC/B,QAAQwL,GAAYxL,CAAW;AAAA,MAAA;AAEjC,MAAAqP,IAAiB2F,CAAM,GACnBD,MAAW,WAAWzF,KACxBA,EAAgB0F,CAAyB;AAAA,IAE7C;AAAA,IACA,CAACtC,IAAkBrD,GAAgBC,CAAe;AAAA,EAAA,GAG9C2F,KAAmBtD;AAAA,IACvB,CAACmB,GAAsBoC,MAAgC;AACrD,YAAMnD,IAAY5C,EAAa,SACzBpQ,IAAO,KAAK,IAAI,MAAMgT,GAAW,eAAA,EAAiB,QAAQ,CAAC,GAC3DoD,IAAerL,KAAoB/K,GACnCqW,IAAgBD,IAAeA,GAC/B1U,IAAOqS,EAAQ,OAAOA,EAAQ,OAAO,SAAS,CAAC;AACrD,UAAI,CAACrS,GAAM;AACT,QAAAqS,EAAQ,OAAO,KAAKoC,CAAK,GACzBpC,EAAQ,UAAUoC;AAClB;AAAA,MACF;AACA,YAAMhQ,IAAKgQ,EAAM,CAAC,IAAIzU,EAAK,CAAC,GACtB0E,IAAK+P,EAAM,CAAC,IAAIzU,EAAK,CAAC;AAC5B,MAAIyE,IAAKA,IAAKC,IAAKA,KAAMiQ,IACvBtC,EAAQ,OAAO,KAAKoC,CAAK,IAEzBpC,EAAQ,OAAOA,EAAQ,OAAO,SAAS,CAAC,IAAIoC,GAE9CpC,EAAQ,UAAUoC;AAAA,IACpB;AAAA,IACA,CAAC/F,CAAY;AAAA,EAAA,GAGTkG,KAAoB1D;AAAA,IACxB,CAAC+C,MAAgD;AAG/C,UAFI,CAAC7D,KACD1G,MAAS,YACTuK,EAAM,WAAW,EAAG;AAExB,YAAMQ,IAAQT,GAAQC,CAAK;AAC3B,UAAI,CAACQ,EAAO;AAKZ,UAHAR,EAAM,eAAA,GACNA,EAAM,gBAAA,GAEFxK,GAAYC,CAAI,GAAG;AACrB,cAAM2I,IAAUlC,GAAW;AAC3BkC,QAAAA,EAAQ,cAAcoC,GACtBJ,GAAc3K,GAAM+K,CAAK,GACzBZ,EAAA;AACA;AAAA,MACF;AAEA,YAAMhY,IAASiU,EAAU;AACzB,MAAIjU,KACFA,EAAO,kBAAkBoY,EAAM,SAAS;AAG1C,YAAM5B,IAAUlC,GAAW;AAC3B,MAAAkC,EAAQ,YAAY,IACpBA,EAAQ,YAAY4B,EAAM,WAC1B5B,EAAQ,QAAQoC,GAChBpC,EAAQ,UAAUoC,GAClBpC,EAAQ,SAASoC,GACjBpC,EAAQ,SAAS3I,MAAS,cAAcA,MAAS,UAAU,CAAC+K,CAAK,IAAI,CAAA,GACrEZ,EAAA;AAAA,IACF;AAAA,IACA,CAACzD,GAAQ1G,GAAMsK,IAASK,IAAeR,CAAW;AAAA,EAAA,GAG9CgB,KAAoB3D;AAAA,IACxB,CAAC+C,MAAgD;AAE/C,UADI,CAAC7D,KACD1G,MAAS,SAAU;AAEvB,YAAM+K,IAAQT,GAAQC,CAAK;AAC3B,UAAI,CAACQ,EAAO;AAEZ,UAAIhL,GAAYC,CAAI,GAAG;AACrB,cAAM2I,IAAUlC,GAAW;AAC3BkC,QAAAA,EAAQ,cAAcoC,GACtBR,EAAM,eAAA,GACNA,EAAM,gBAAA,GACNJ,EAAA;AACA;AAAA,MACF;AAEA,YAAMxB,IAAUlC,GAAW;AAC3B,UAAIzG,MAAS,SAAS;AAEpB,YADA2I,EAAQ,SAASoC,GACb,CAACpC,EAAQ,aAAaA,EAAQ,cAAc4B,EAAM,WAAW;AAC/D,UAAAJ,EAAA;AACA;AAAA,QACF;AACA,QAAAI,EAAM,eAAA,GACNA,EAAM,gBAAA,GACNO,GAAiBnC,GAASoC,CAAK,GAC/BZ,EAAA;AACA;AAAA,MACF;AAEA,UAAI,GAACxB,EAAQ,aAAaA,EAAQ,cAAc4B,EAAM,YAMtD;AAAA,YAHAA,EAAM,eAAA,GACNA,EAAM,gBAAA,GAEFvK,MAAS,YAAY;AACvB,gBAAM4H,IAAY5C,EAAa,SACzBpQ,IAAO,KAAK,IAAI,MAAMgT,GAAW,eAAA,EAAiB,QAAQ,CAAC,GAC3DoD,IAAe7M,KAAuBvJ,GACtCqW,IAAgBD,IAAeA,GAC/B1U,IAAOqS,EAAQ,OAAOA,EAAQ,OAAO,SAAS,CAAC;AAErD,cAAI,CAACrS;AACH,YAAAqS,EAAQ,OAAO,KAAKoC,CAAK;AAAA,eACpB;AACL,kBAAMhQ,IAAKgQ,EAAM,CAAC,IAAIzU,EAAK,CAAC,GACtB0E,KAAK+P,EAAM,CAAC,IAAIzU,EAAK,CAAC;AAC5B,YAAIyE,IAAKA,IAAKC,KAAKA,MAAMiQ,KACvBtC,EAAQ,OAAO,KAAKoC,CAAK;AAAA,UAE7B;AAAA,QACF;AACE,UAAApC,EAAQ,UAAUoC;AAGpB,QAAAZ,EAAA;AAAA;AAAA,IACF;AAAA,IACA,CAACzD,GAAQ1G,GAAMsK,IAASH,GAAanF,GAAc8F,EAAgB;AAAA,EAAA,GAG/DM,KAAkB5D;AAAA,IACtB,CAAC+C,MAAgD;AAC/C,YAAM5B,IAAUlC,GAAW;AAC3B,UAAI,CAACkC,EAAQ,aAAaA,EAAQ,cAAc4B,EAAM,UAAW;AAEjE,MAAAA,EAAM,eAAA,GACNA,EAAM,gBAAA;AACN,YAAMQ,IAAQT,GAAQC,CAAK;AAC3B,MAAIQ,MACFpC,EAAQ,SAASoC,GACb/K,MAAS,UACX8K,GAAiBnC,GAASoC,CAAK,IAE/BpC,EAAQ,UAAUoC;AAGtB,YAAM5Y,IAASiU,EAAU;AACzB,UAAIjU,KAAUA,EAAO,kBAAkBoY,EAAM,SAAS;AACpD,YAAI;AACF,UAAApY,EAAO,sBAAsBoY,EAAM,SAAS;AAAA,QAC9C,QAAQ;AAAA,QAER;AAGF,MAAAE,GAAA;AAAA,IACF;AAAA,IACA,CAACA,IAAeH,IAAStK,GAAM8K,EAAgB;AAAA,EAAA,GAG3CO,KAAqB7D,EAAY,MAAM;AAC3C,UAAMmB,IAAUlC,GAAW;AAC3B,QAAI6E,IAAU;AACd,IAAItL,MAAS,WAAW,CAAC2I,EAAQ,aAAaA,EAAQ,WACpDA,EAAQ,SAAS,MACjB2C,IAAU,KAERvL,GAAYC,CAAI,KAAK2I,EAAQ,gBAC/BA,EAAQ,cAAc,MACtB2C,IAAU,KAERA,KACFnB,EAAA;AAAA,EAEJ,GAAG,CAACnK,GAAMmK,CAAW,CAAC;AAEtB,SAAAoB,EAAU,MAAM;AACd,IAAAhE,GAAA,GACA4C,EAAA;AAEA,UAAMhY,IAASiU,EAAU;AACzB,QAAI,CAACjU,EAAQ;AAEb,UAAMqZ,IAAW,IAAI,eAAe,MAAM;AACxC,MAAAjE,GAAA,GACA4C,EAAA;AAAA,IACF,CAAC;AACD,WAAAqB,EAAS,QAAQrZ,CAAM,GAEhB,MAAM;AACX,MAAAqZ,EAAS,WAAA;AAAA,IACX;AAAA,EACF,GAAG,CAACjE,IAAc4C,CAAW,CAAC,GAE9BoB,EAAU,MAAM;AACd,IAAK7E,KACH0D,GAAA,GAEFD,EAAA;AAAA,EACF,GAAG,CAACzD,GAAQyD,GAAaC,EAAY,CAAC,GAEtCmB,EAAU,MAAM;AACd,IAAI/E,GAAY,YAAYxG,MAG5BwG,GAAY,UAAUxG,GACtBoK,GAAA,GACAD,EAAA;AAAA,EACF,GAAG,CAACnK,GAAMoK,IAAcD,CAAW,CAAC,GAEpCoB,EAAU,MAAM;AACd,IAAApB,EAAA;AAAA,EACF,GAAG,CAAC9E,GAAiBsB,GAAwBb,GAAeqE,CAAW,CAAC,GAExEoB,EAAU,MAAM;AACd,QAAKrF;AACL,aAAAA,GAAc,UAAUiE,GACjB,MAAM;AACX,QAAIjE,GAAc,YAAYiE,MAC5BjE,GAAc,UAAU;AAAA,MAE5B;AAAA,EACF,GAAG,CAACA,IAAeiE,CAAW,CAAC,GAE/BoB,EAAU,MAAM;AACd,QAAI,CAAC7E,EAAQ;AAEb,UAAM+E,IAAY,CAAClB,MAA+B;AAChD,MAAIA,EAAM,QAAQ,aAClBH,GAAA,GACAD,EAAA;AAAA,IACF;AAEA,kBAAO,iBAAiB,WAAWsB,CAAS,GACrC,MAAM;AACX,aAAO,oBAAoB,WAAWA,CAAS;AAAA,IACjD;AAAA,EACF,GAAG,CAAC/E,GAAQ0D,IAAcD,CAAW,CAAC,GAGpC,gBAAAuB;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,KAAKtF;AAAA,MACL,WAAAD;AAAA,MACA,OAAOmB;AAAA,MACP,eAAe4D;AAAA,MACf,eAAeC;AAAA,MACf,aAAaC;AAAA,MACb,iBAAiBA;AAAA,MACjB,gBAAgBC;AAAA,MAChB,eAAe,CAAAd,MAAS;AACtB,QAAI7D,OAAc,eAAA;AAAA,MACpB;AAAA,MACA,SAAS,CAAA6D,MAAS;AAChB,YAAI,CAAC7D,EAAQ;AACb,cAAMvU,IAASiU,EAAU,SACnBwB,IAAY5C,EAAa;AAC/B,YAAI,CAAC7S,KAAU,OAAOyV,GAAW,UAAW,WAAY;AACxD,QAAA2C,EAAM,eAAA,GACNA,EAAM,gBAAA;AACN,cAAMlW,IAAOlC,EAAO,sBAAA,GACdwZ,IAAUpB,EAAM,UAAUlW,EAAK,MAC/BuX,IAAUrB,EAAM,UAAUlW,EAAK;AACrC,QAAAuT,EAAU,OAAO2C,EAAM,SAAS,IAAI1L,KAAuBC,IAAuB6M,GAASC,CAAO,GAClGzB,EAAA;AAAA,MACF;AAAA,IAAA;AAAA,EAAA;AAGN;ACp6CA,SAAS0B,GAAkBpW,GAAuB;AAChD,SAAO,OAAOA,KAAS,EAAE,EAAE,QAAQ,QAAQ,EAAE;AAC/C;AAEA,SAASqW,GAAmBrW,GAAuB;AACjD,QAAM+U,IAAM,OAAO/U,KAAS,EAAE;AAC9B,SAAO+U,EAAI,WAAW,GAAG,IAAIA,IAAM,IAAIA,CAAG;AAC5C;AAEA,SAASuB,GAAgBC,GAA6B;AACpD,QAAM3J,IAAOwJ,GAAkBG,CAAW;AAC1C,MAAI,CAAC3J,EAAM,QAAO;AAGlB,MAAI,mBAAmB,KAAKA,CAAI,EAAG,QAAOA;AAE1C,MAAI4J,IAAqB;AACzB,MAAI;AACF,IAAAA,IAAS,IAAI,IAAI5J,CAAI;AAAA,EACvB,QAAQ;AACN,IAAA4J,IAAS;AAAA,EACX;AAEA,MAAIA,GAAQ;AACV,UAAMC,IAAS,GAAGD,EAAO,QAAQ,KAAKA,EAAO,IAAI,IAC3ChU,IAAO4T,GAAkBI,EAAO,YAAY,EAAE;AAIpD,WAAI,UAAU,KAAKhU,CAAI,IAAU,GAAGiU,CAAM,GAAGjU,CAAI,KAC7C,YAAY,KAAKA,CAAI,IAAU,GAAGiU,CAAM,GAAGjU,CAAI,KAC5C,GAAGiU,CAAM,GAAGjU,CAAI;AAAA,EACzB;AAGA,SAAI,UAAU,KAAKoK,CAAI,IAAU,SAC7B,YAAY,KAAKA,CAAI,IAAU,GAAGA,CAAI,KACnC,GAAGA,CAAI;AAChB;AAEO,SAAS8J,GAAmB3B,GAAUwB,GAAqC;AAChF,QAAMI,IAAM5B,GAAK,WAAW,CAAA,GACtB6B,IAAQ,CAAC,CAAC7B,GAAK,SAEfjY,IAAQ,OAAO6Z,EAAI,SAAS5B,GAAK,SAAS,CAAC,GAC3ChY,IAAS,OAAO4Z,EAAI,UAAU5B,GAAK,UAAU,CAAC,GAC9C8B,IAAW,OAAOF,EAAI,YAAY5B,GAAK,YAAY,CAAC,GACpD+B,IAAc,OAAOH,EAAI,QAAQ5B,GAAK,QAAQ,CAAC,GAC/CgC,IAAW,OAAOJ,EAAI,QAAQ5B,GAAK,QAAQ,EAAE,GAC7C9N,IAAM,OAAO0P,EAAI,OAAO5B,GAAK,OAAO,CAAC;AAE3C,MAAI,CAACjY,KAAS,CAACC,KAAU,CAAC8Z,KAAY,CAACE;AACrC,UAAM,IAAI,MAAM,qDAAqD;AAGvE,QAAM/O,IAAmB,MAAM,QAAQ+M,GAAK,KAAK,IAC7CA,EAAI,MAAM,IAAI,CAAC5M,OAAe;AAAA,IAC5B,QAAQ,OAAOA,GAAM,UAAU,EAAE;AAAA,IACjC,UAAU,OAAOA,GAAM,YAAY,EAAE;AAAA,IACrC,WAAW,OAAOA,GAAM,aAAa,EAAE;AAAA,EAAA,EACvC,IACF,CAAA,GAEE6O,IAAiBX,GAAmBU,CAAQ,GAC5CE,IAAcX,GAAgBC,CAAW,GACzCW,IAAiBN,IAAQ,CAACO,GAAc7W,GAAWC,MAAsB,GAAG0W,CAAW,GAAGD,CAAc,IAAIG,CAAI,IAAI5W,CAAC,IAAID,CAAC,UAAU;AAE1I,SAAO;AAAA,IACL,IAAIyU,GAAK,OAAO;AAAA,IAChB,MAAMA,GAAK,QAAQ;AAAA,IACnB,OAAAjY;AAAA,IACA,QAAAC;AAAA,IACA,KAAK,OAAO,SAASkK,CAAG,KAAKA,IAAM,IAAIA,IAAM;AAAA,IAC7C,UAAA4P;AAAA,IACA,aAAa,OAAO,SAASC,CAAW,IAAI,KAAK,IAAI,GAAG,KAAK,MAAMA,CAAW,CAAC,IAAI;AAAA,IACnF,UAAAC;AAAA,IACA,aAAAR;AAAA,IACA,OAAAvO;AAAA,IACA,gBAAAkP;AAAA,EAAA;AAEJ;AAEO,SAASE,GAAUvb,GAA6Esb,GAAc7W,GAAWC,GAAmB;AACjJ,MAAI1E,EAAO;AACT,WAAOA,EAAO,eAAesb,GAAM7W,GAAGC,CAAC;AAEzC,QAAMyW,IAAiBX,GAAmBxa,EAAO,QAAQ;AACzD,SAAO,GAAGA,EAAO,WAAW,GAAGmb,CAAc,IAAIG,CAAI,IAAI5W,CAAC,IAAID,CAAC;AACjE;AClCA,MAAM+W,KAAmD;AAAA,EACxD,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,UAAU;AAAA,EACV,cAAc;AAAA,EACd,aAAa;AAAA,EACb,iBAAiB;AAAA,EACjB,aAAa;AAAA,EACb,qBAAqB;AAAA,EACrB,mBAAmB;AAAA,EACnB,aAAa;AAAA,EACb,eAAe;AAAA,EACf,mBAAmB;AACpB;AAEA,SAASC,GACRtX,GACAyK,GACAxK,IAAM,GACG;AACT,SAAI,OAAOD,KAAU,YAAY,CAAC,OAAO,SAASA,CAAK,IAAUyK,IAC1D,KAAK,IAAIxK,GAAKD,CAAK;AAC3B;AAEA,SAASuX,GAAe3V,GAAuD;AAC9E,SACC,MAAM,QAAQA,CAAM,KACpBA,EAAO,WAAW,KAClB,OAAO,SAASA,EAAO,CAAC,CAAC,KACzB,OAAO,SAASA,EAAO,CAAC,CAAC,KACzB,OAAO,SAASA,EAAO,CAAC,CAAC,KACzB,OAAO,SAASA,EAAO,CAAC,CAAC;AAE3B;AAEO,SAAS4V,GAAY;AAAA,EAC3B,QAAA3b;AAAA,EACA,cAAA0T;AAAA,EACA,WAAAkI,IAAY;AAAA,EACZ,SAAA/Z;AAAA,EACA,eAAA+S;AAAA,EACA,WAAAC;AAAA,EACA,OAAApE;AACD,GAAyC;AACxC,QAAMqE,IAAYC,EAAiC,IAAI,GACjD8G,IAAe9G,EAAiC,IAAI,GACpD+G,IAAgB/G,EAAsB,IAAI,GAC1CgH,IAAchH,EAAsD;AAAA,IACzE,QAAQ;AAAA,IACR,WAAW;AAAA,EAAA,CACX,GACKiH,IAASjH,EAAsB,IAAI,GACnCC,IAAiBD,EAAO,EAAK,GAE7B9T,IAAQwa;AAAA,IACb5Z,GAAS;AAAA,IACT2Z,GAA6B;AAAA,IAC7B;AAAA,EAAA,GAEKta,IAASua;AAAA,IACd5Z,GAAS;AAAA,IACT2Z,GAA6B;AAAA,IAC7B;AAAA,EAAA,GAEKS,IAASR;AAAA,IACd5Z,GAAS;AAAA,IACT2Z,GAA6B;AAAA,IAC7B;AAAA,EAAA,GAEKU,IAAeT;AAAA,IACpB5Z,GAAS;AAAA,IACT2Z,GAA6B;AAAA,IAC7B;AAAA,EAAA,GAEKW,IAAcV;AAAA,IACnB5Z,GAAS;AAAA,IACT2Z,GAA6B;AAAA,IAC7B;AAAA,EAAA,GAEKY,IAAoB,KAAK;AAAA,IAC9B;AAAA,IACA,KAAK;AAAA,MACJX;AAAA,QACC5Z,GAAS;AAAA,QACT2Z,GAA6B;AAAA,QAC7B;AAAA,MAAA;AAAA,IACD;AAAA,EACD,GAGKa,IACLxa,GAAS,mBAAmB2Z,GAA6B,iBACpDc,IACLza,GAAS,eAAe2Z,GAA6B,aAChDe,IACL1a,GAAS,uBACT2Z,GAA6B,qBACxBgB,KACL3a,GAAS,qBACT2Z,GAA6B,mBACxBiB,KACL5a,GAAS,eAAe2Z,GAA6B,aAChDkB,IACL7a,GAAS,iBAAiB2Z,GAA6B,eAClDmB,KACL9a,GAAS,YAAY2Z,GAA6B,UAE7CxF,KAAcV,GAAuB,MAAM;AAChD,UAAMsH,IAAqB,CAAA;AAC3B,WAAID,OAAa,cAAcA,OAAa,kBAAmB,OAAOV,MAC7D,QAAQA,GACbU,OAAa,cAAcA,OAAa,gBAAiB,MAAMV,MAC1D,SAASA,GAEX;AAAA,MACN,UAAU;AAAA,MACV,GAAGW;AAAA,MACH,OAAA3b;AAAA,MACA,QAAAC;AAAA,MACA,cAAAgb;AAAA,MACA,UAAU;AAAA,MACV,QAAQ;AAAA,MACR,eAAeO,KAAc,SAAS;AAAA,MACtC,aAAa;AAAA,MACb,WAAW;AAAA,MACX,GAAGhM;AAAA,IAAA;AAAA,EAEL,GAAG,CAACwL,GAAQU,IAAU1b,GAAOC,GAAQgb,GAAcO,IAAahM,CAAK,CAAC,GAEhEoM,KAAO3G,EAAY,MAAM;AAC9B,UAAMrV,IAASiU,EAAU;AACzB,QAAI,CAACjU,EAAQ;AAEb,UAAMsP,IAAMtP,EAAO,WAAW,IAAI;AAClC,QAAI,CAACsP,EAAK;AAEV,UAAM2M,IAAO7b,GACP8b,IAAO7b,GACPgC,IAAM,KAAK,IAAI,GAAG,OAAO,oBAAoB,CAAC,GAE9C8Z,KAAS,KAAK,IAAI,GAAG,KAAK,MAAMF,IAAO5Z,CAAG,CAAC,GAC3C+Z,KAAS,KAAK,IAAI,GAAG,KAAK,MAAMF,IAAO7Z,CAAG,CAAC;AACjD,KAAIrC,EAAO,UAAUmc,MAAUnc,EAAO,WAAWoc,QAChDpc,EAAO,QAAQmc,IACfnc,EAAO,SAASoc,KAGjB9M,EAAI,aAAa,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,GACjCA,EAAI,UAAU,GAAG,GAAGtP,EAAO,OAAOA,EAAO,MAAM,GAC/CsP,EAAI,aAAajN,GAAK,GAAG,GAAGA,GAAK,GAAG,CAAC,GAErCiN,EAAI,YAAYkM,GAChBlM,EAAI,SAAS,GAAG,GAAG2M,GAAMC,CAAI;AAE7B,UAAMvE,KAAUqD,EAAa;AAC7B,IAAIrD,MACHrI,EAAI,UAAUqI,IAAS,GAAG,GAAGsE,GAAMC,CAAI,GAGxC5M,EAAI,cAAcmM,GAClBnM,EAAI,YAAYgM,GAChBhM,EAAI;AAAA,MACHgM,IAAc;AAAA,MACdA,IAAc;AAAA,MACdW,IAAOX;AAAA,MACPY,IAAOZ;AAAA,IAAA;AAGR,UAAM7F,IAAY5C,EAAa,SACzB3N,KAASuQ,GAAW,gBAAA,GACpB4G,KAAU5G,GAAW,iBAAA,GACrB6G,IAAazB,GAAe3V,EAAM,IACrCA,KACA2V,GAAeI,EAAc,OAAO,IACnCA,EAAc,UACd;AACJ,QAAI,CAACqB,EAAY;AACjB,IAAArB,EAAc,UAAUqB;AAExB,UAAM7b,IAAKwb,IAAO,KAAK,IAAI,GAAG9c,EAAO,KAAK,GACpCuB,KAAKwb,IAAO,KAAK,IAAI,GAAG/c,EAAO,MAAM,GAErCod,KACL,MAAM,QAAQF,EAAO,KACrBA,GAAQ,UAAU,KAClBA,GAAQ;AAAA,MACP,CAACnY,OACA,MAAM,QAAQA,EAAK,KACnBA,GAAM,UAAU,KAChB,OAAO,SAASA,GAAM,CAAC,CAAC,KACxB,OAAO,SAASA,GAAM,CAAC,CAAC;AAAA,IAAA,IAEtBmY,KACD;AAEJ,QAAIE,IAAa;AAChB,MAAAjN,EAAI,UAAA;AACJ,eAAStJ,KAAI,GAAGA,KAAIuW,GAAY,QAAQvW,MAAK,GAAG;AAC/C,cAAM9B,KAAQqY,GAAYvW,EAAC,GACrBpC,KAAIP,GAAMa,GAAM,CAAC,IAAIzD,GAAI,GAAGwb,CAAI,GAChCpY,KAAIR,GAAMa,GAAM,CAAC,IAAIxD,IAAI,GAAGwb,CAAI;AACtC,QAAIlW,OAAM,IAAGsJ,EAAI,OAAO1L,IAAGC,EAAC,IACvByL,EAAI,OAAO1L,IAAGC,EAAC;AAAA,MACrB;AACA,MAAAyL,EAAI,UAAA,GACJA,EAAI,YAAYqM,IAChBrM,EAAI,KAAA,GACJA,EAAI,cAAcoM,GAClBpM,EAAI,YAAY,KAChBA,EAAI,OAAA;AACJ;AAAA,IACD;AAEA,UAAM6C,KAAO9O,GAAMiZ,EAAW,CAAC,IAAI7b,GAAI,GAAGwb,CAAI,GACxC7J,IAAM/O,GAAMiZ,EAAW,CAAC,IAAI5b,IAAI,GAAGwb,CAAI,GACvCM,KAAQnZ,GAAMiZ,EAAW,CAAC,IAAI7b,GAAI,GAAGwb,CAAI,GACzCQ,KAASpZ,GAAMiZ,EAAW,CAAC,IAAI5b,IAAI,GAAGwb,CAAI,GAC1CQ,IAAQ,KAAK,IAAI,GAAGF,KAAQrK,EAAI,GAChCwK,KAAQ,KAAK,IAAI,GAAGF,KAASrK,CAAG;AAEtC,IAAA9C,EAAI,YAAYqM,IAChBrM,EAAI,SAAS6C,IAAMC,GAAKsK,GAAOC,EAAK,GAEpCrN,EAAI,cAAcoM,GAClBpM,EAAI,YAAY,KAChBA,EAAI;AAAA,MACH6C,KAAO;AAAA,MACPC,IAAM;AAAA,MACN,KAAK,IAAI,GAAGsK,IAAQ,CAAC;AAAA,MACrB,KAAK,IAAI,GAAGC,KAAQ,CAAC;AAAA,IAAA;AAAA,EAEvB,GAAG;AAAA,IACFvc;AAAA,IACAC;AAAA,IACAmb;AAAA,IACAC;AAAA,IACAH;AAAA,IACAzI;AAAA,IACA1T,EAAO;AAAA,IACPA,EAAO;AAAA,IACPwc;AAAA,IACAD;AAAA,EAAA,CACA,GAEK1D,IAAc3C,EAAY,MAAM;AACrC,IAAIlB,EAAe,YACnBA,EAAe,UAAU,IACzBgH,EAAO,UAAU,sBAAsB,MAAM;AAC5C,MAAAhH,EAAe,UAAU,IACzBgH,EAAO,UAAU,MACjBa,GAAA;AAAA,IACD,CAAC;AAAA,EACF,GAAG,CAACA,EAAI,CAAC,GAEHY,KAAoBvH;AAAA,IACzB,CAACwH,GAAiBC,MAA6C;AAC9D,YAAM9c,IAASiU,EAAU;AACzB,UAAI,CAACjU,EAAQ,QAAO;AAEpB,YAAMkC,IAAOlC,EAAO,sBAAA;AACpB,UAAI,CAACkC,EAAK,SAAS,CAACA,EAAK,OAAQ,QAAO;AAExC,YAAM6a,IAAK1Z,IAAOwZ,IAAU3a,EAAK,QAAQA,EAAK,OAAO,GAAG,CAAC,GACnD8a,KAAK3Z,IAAOyZ,IAAU5a,EAAK,OAAOA,EAAK,QAAQ,GAAG,CAAC;AACzD,aAAO,CAAC6a,IAAK5d,EAAO,OAAO6d,KAAK7d,EAAO,MAAM;AAAA,IAC9C;AAAA,IACA,CAACA,EAAO,OAAOA,EAAO,MAAM;AAAA,EAAA,GAGvB8d,KAAa5H;AAAA,IAClB,CAAC6H,GAAgBC,MAAmB;AACnC,YAAM1H,IAAY5C,EAAa;AAC/B,UAAI,CAAC4C,EAAW;AAEhB,UAAIA,EAAU,eAAe;AAC5B,QAAAA,EAAU,cAAcyH,GAAQC,CAAM,GACtCnF,EAAA;AACA;AAAA,MACD;AAEA,YAAM9S,IAASuQ,EAAU,gBAAA,GACnB6G,IAAazB,GAAe3V,CAAM,IACrCA,IACA2V,GAAeI,EAAc,OAAO,IACnCA,EAAc,UACd;AACJ,UAAI,CAACqB,EAAY;AAEjB,YAAMc,KAAW,KAAK,IAAI,MAAMd,EAAW,CAAC,IAAIA,EAAW,CAAC,CAAC,GACvDe,KAAW,KAAK,IAAI,MAAMf,EAAW,CAAC,IAAIA,EAAW,CAAC,CAAC;AAE7D,MAAA7G,EAAU,aAAa;AAAA,QACtB,SAASyH,IAASE,KAAW;AAAA,QAC7B,SAASD,IAASE,KAAW;AAAA,MAAA,CAC7B,GACDrF,EAAA;AAAA,IACD;AAAA,IACA,CAACnF,GAAcmF,CAAW;AAAA,EAAA,GAGrBe,KAAoB1D;AAAA,IACzB,CAAC+C,MAAgD;AAEhD,UADI,CAACwD,MACDxD,EAAM,WAAW,EAAG;AAExB,YAAMpY,IAASiU,EAAU;AACzB,UAAI,CAACjU,EAAQ;AAEb,YAAM4Y,IAAQgE,GAAkBxE,EAAM,SAASA,EAAM,OAAO;AAC5D,MAAKQ,MAELR,EAAM,eAAA,GACNA,EAAM,gBAAA,GAENpY,EAAO,kBAAkBoY,EAAM,SAAS,GACxC8C,EAAY,UAAU,EAAE,QAAQ,IAAM,WAAW9C,EAAM,UAAA,GACvD6E,GAAWrE,EAAM,CAAC,GAAGA,EAAM,CAAC,CAAC;AAAA,IAC9B;AAAA,IACA,CAACgD,IAAagB,IAAmBK,EAAU;AAAA,EAAA,GAGtCjE,KAAoB3D;AAAA,IACzB,CAAC+C,MAAgD;AAChD,YAAMkF,IAAOpC,EAAY;AACzB,UAAI,CAACoC,EAAK,UAAUA,EAAK,cAAclF,EAAM,UAAW;AAExD,YAAMQ,IAAQgE,GAAkBxE,EAAM,SAASA,EAAM,OAAO;AAC5D,MAAKQ,MAELR,EAAM,eAAA,GACNA,EAAM,gBAAA,GACN6E,GAAWrE,EAAM,CAAC,GAAGA,EAAM,CAAC,CAAC;AAAA,IAC9B;AAAA,IACA,CAACgE,IAAmBK,EAAU;AAAA,EAAA,GAGzBhE,IAAkB5D;AAAA,IACvB,CAAC+C,MAAgD;AAChD,YAAMkF,IAAOpC,EAAY;AACzB,UAAI,CAACoC,EAAK,UAAUA,EAAK,cAAclF,EAAM,UAAW;AAExD,YAAMpY,IAASiU,EAAU;AACzB,UAAIjU,KAAUA,EAAO,kBAAkBoY,EAAM,SAAS;AACrD,YAAI;AACH,UAAApY,EAAO,sBAAsBoY,EAAM,SAAS;AAAA,QAC7C,QAAQ;AAAA,QAER;AAGD,MAAA8C,EAAY,UAAU,EAAE,QAAQ,IAAO,WAAW,KAAA,GAClDlD,EAAA;AAAA,IACD;AAAA,IACA,CAACA,CAAW;AAAA,EAAA;AAGb,SAAAoB,EAAU,MAAM;AACf,QAAImE,IAAY;AAChB,IAAAvC,EAAa,UAAU,MACvBhD,EAAA;AAEA,UAAMyC,IAAO,GACP+C,IAAa,MAAMre,EAAO,cAAcsb,IACxCgD,IAAa,KAAK,KAAKte,EAAO,QAAQqe,CAAU,GAChDE,IAAc,KAAK,KAAKve,EAAO,SAASqe,CAAU,GAClDG,KAAS,KAAK,IAAI,GAAG,KAAK,KAAKF,IAAate,EAAO,QAAQ,CAAC,GAC5Dye,KAAS,KAAK,IAAI,GAAG,KAAK,KAAKF,IAAcve,EAAO,QAAQ,CAAC,GAC7D0e,KAAYF,KAASC;AAE3B,QAAI,CAAC/B,KAAiBgC,KAAYtC;AACjC;AAGD,UAAM5D,IAAU,SAAS,cAAc,QAAQ;AAC/C,IAAAA,EAAQ,QAAQ,KAAK,IAAI,GAAG,KAAK,MAAMvX,CAAK,CAAC,GAC7CuX,EAAQ,SAAS,KAAK,IAAI,GAAG,KAAK,MAAMtX,CAAM,CAAC;AAC/C,UAAMiP,KAAMqI,EAAQ,WAAW,IAAI;AACnC,QAAI,CAACrI;AACJ;AAGD,IAAAA,GAAI,YAAYkM,GAChBlM,GAAI,SAAS,GAAG,GAAGqI,EAAQ,OAAOA,EAAQ,MAAM;AAEhD,UAAMmG,KAGD,CAAA;AAEL,aAASja,IAAI,GAAGA,IAAI+Z,IAAQ/Z,KAAK;AAChC,eAASD,IAAI,GAAGA,IAAI+Z,IAAQ/Z,KAAK,GAAG;AACnC,cAAMuO,KAAOvO,IAAIzE,EAAO,WAAWqe,GAC7BpL,KAAMvO,IAAI1E,EAAO,WAAWqe,GAC5BhB,KACL,KAAK,KAAK5Y,IAAI,KAAKzE,EAAO,UAAUse,CAAU,IAAID,GAC7Cf,IACL,KAAK,KAAK5Y,IAAI,KAAK1E,EAAO,UAAUue,CAAW,IAAIF;AACpD,QAAAM,GAAS,KAAK;AAAA,UACb,KAAKpD,GAAUvb,GAAQsb,GAAM7W,GAAGC,CAAC;AAAA,UACjC,QAAQ,CAACsO,IAAMC,IAAKoK,IAAOC,CAAM;AAAA,QAAA,CACjC;AAAA,MACF;AAGD,WAAK,QAAQ;AAAA,MACZqB,GAAS,IAAI,OAAOnc,MAAS;AAC5B,cAAMoc,IAAgB,CAAC,CAAChD,GAClBlZ,KAAW,MAAM,MAAMF,EAAK,KAAK;AAAA,UACtC,SAASoc,IAAgB,EAAE,eAAehD,MAAc;AAAA,QAAA,CACxD;AACD,YAAI,CAAClZ,GAAS;AACb,gBAAM,IAAI,MAAM,QAAQA,GAAS,MAAM,EAAE;AAE1C,cAAME,KAAS,MAAM,kBAAkB,MAAMF,GAAS,MAAM;AAC5D,eAAO,EAAE,MAAAF,GAAM,QAAAI,GAAA;AAAA,MAChB,CAAC;AAAA,IAAA,EACA,KAAK,CAACic,MAAY;AACnB,UAAIT,GAAW;AACd,mBAAW7E,MAAUsF;AACpB,UAAItF,GAAO,WAAW,eACrBA,GAAO,MAAM,OAAO,MAAA;AAGtB;AAAA,MACD;AAEA,YAAMjY,IAAKkX,EAAQ,QAAQ,KAAK,IAAI,GAAGxY,EAAO,KAAK,GAC7CuB,KAAKiX,EAAQ,SAAS,KAAK,IAAI,GAAGxY,EAAO,MAAM;AACrD,iBAAWuZ,MAAUsF,GAAS;AAC7B,YAAItF,GAAO,WAAW,YAAa;AACnC,cAAM;AAAA,UACL,MAAM,EAAE,QAAAxT,GAAA;AAAA,UACR,QAAAnD;AAAA,QAAA,IACG2W,GAAO,OACL9P,KAAK1D,GAAO,CAAC,IAAIzE,GACjBoI,KAAK3D,GAAO,CAAC,IAAIxE,IACjBud,IAAK,KAAK,IAAI,IAAI/Y,GAAO,CAAC,IAAIA,GAAO,CAAC,KAAKzE,CAAE,GAC7Cyd,KAAK,KAAK,IAAI,IAAIhZ,GAAO,CAAC,IAAIA,GAAO,CAAC,KAAKxE,EAAE;AACnD,QAAA4O,GAAI,UAAUvN,GAAQ6G,IAAIC,IAAIoV,GAAIC,EAAE,GACpCnc,EAAO,MAAA;AAAA,MACR;AAEA,MAAAiZ,EAAa,UAAUrD,GACvBK,EAAA;AAAA,IACD,CAAC,GAEM,MAAM;AACZ,MAAAuF,IAAY;AAAA,IACb;AAAA,EACD,GAAG;AAAA,IACFpe;AAAA,IACA4b;AAAA,IACA3a;AAAA,IACAC;AAAA,IACAmb;AAAA,IACAK;AAAA,IACAN;AAAA,IACAvD;AAAA,EAAA,CACA,GAEDoB,EAAU,MAAM;AACf,IAAApB,EAAA;AAAA,EACD,GAAG,CAACA,CAAW,CAAC,GAEhBoB,EAAU,MAAM;AACf,QAAKrF;AACL,aAAAA,EAAc,UAAUiE,GACjB,MAAM;AACZ,QAAIjE,EAAc,YAAYiE,MAC7BjE,EAAc,UAAU;AAAA,MAE1B;AAAA,EACD,GAAG,CAACA,GAAeiE,CAAW,CAAC,GAE/BoB;AAAA,IACC,MAAM,MAAM;AACX,MAAA8B,EAAY,UAAU,EAAE,QAAQ,IAAO,WAAW,KAAA,GAC9CC,EAAO,YAAY,SACtB,qBAAqBA,EAAO,OAAO,GACnCA,EAAO,UAAU,OAElBhH,EAAe,UAAU;AAAA,IAC1B;AAAA,IACA,CAAA;AAAA,EAAC,GAID,gBAAAoF;AAAA,IAAC;AAAA,IAAA;AAAA,MACA,KAAKtF;AAAA,MACL,WAAAD;AAAA,MACA,OAAOmB;AAAA,MACP,eAAe4D;AAAA,MACf,eAAeC;AAAA,MACf,aAAaC;AAAA,MACb,iBAAiBA;AAAA,MACjB,eAAe,CAACb,MAAU;AACzB,QAAAA,EAAM,eAAA;AAAA,MACP;AAAA,MACA,SAAS,CAACA,MAAU;AACnB,QAAAA,EAAM,eAAA,GACNA,EAAM,gBAAA;AAAA,MACP;AAAA,IAAA;AAAA,EAAA;AAGH;ACniBO,SAAS+F,GAAiB;AAAA,EAChC,YAAA5L;AAAA,EACA,aAAAC;AAAA,EACA,OAAAhR;AAAA,EACA,WAAAI;AAAA,EACA,WAAAoS;AAAA,EACA,OAAApE;AACD,GAA8C;AAC7C,QAAMqE,IAAYC,EAAiC,IAAI,GACjDkK,IAAclK,EAA8B,IAAI,GAChDiB,IAAcV;AAAA,IACnB,OAAO,EAAE,OAAO,QAAQ,QAAQ,QAAQ,SAAS,SAAS,GAAG7E;IAC7D,CAACA,CAAK;AAAA,EAAA;AAGP,SAAAwJ,EAAU,MAAM;AACf,UAAMpZ,IAASiU,EAAU;AACzB,QAAI,CAACjU;AACJ;AAGD,UAAMqe,IAAW,IAAItd,GAAe;AAAA,MACnC,QAAAf;AAAA,MACA,YAAAuS;AAAA,MACA,aAAAC;AAAA,MACA,kBAAkB5Q;AAAA,IAAA,CAClB;AAED,WAAAwc,EAAY,UAAUC,GACjBA,EAAS,SAAS7c,CAAK,GAErB,MAAM;AACZ,MAAA6c,EAAS,QAAA,GACTD,EAAY,UAAU;AAAA,IACvB;AAAA,EACD,GAAG,CAAC7L,GAAYC,CAAW,CAAC,GAE5B4G,EAAU,MAAM;AACf,UAAMiF,IAAWD,EAAY;AAC7B,IAAKC,KAIAA,EAAS,SAAS7c,CAAK;AAAA,EAC7B,GAAG,CAACA,CAAK,CAAC,GAEV4X,EAAU,MAAM;AACf,UAAMiF,IAAWD,EAAY;AAC7B,IAAI,CAACC,KAAY,CAACzc,KAIlByc,EAAS,aAAazc,CAAS;AAAA,EAChC,GAAG,CAACA,CAAS,CAAC,sBAEN,UAAA,EAAO,KAAKqS,GAAW,WAAAD,GAAsB,OAAOmB,GAAa;AAC1E;ACzDA,SAASmJ,GAAmBC,GAAiC;AAC5D,SAAO,KAAK;AAAA,IACX;AAAA,IACA,KAAK;AAAA,MACJ,KAAK,MAAMA,EAAU,SAAS,CAAC;AAAA,MAC/B,KAAK,OAAOA,EAAU,WAAW,UAAU,KAAK,CAAC;AAAA,MACjDA,EAAU,gBAAgB,UAAU;AAAA,IAAA;AAAA,EACrC;AAEF;AAEA,SAAS9a,GAAUoL,GAAgC;AAClD,MAAI,CAAC,MAAM,QAAQA,CAAM,KAAKA,EAAO,SAAS,EAAG,QAAO,CAAA;AACxD,QAAMlL,IAAMkL,EAAO,IAAI,CAAC,CAACjL,GAAGC,CAAC,MAAM,CAACD,GAAGC,CAAC,CAAkB,GACpDC,IAAQH,EAAI,CAAC,GACbI,IAAOJ,EAAIA,EAAI,SAAS,CAAC;AAC/B,SAAI,CAACG,KAAS,CAACC,IAAa,CAAA,MACxBD,EAAM,CAAC,MAAMC,EAAK,CAAC,KAAKD,EAAM,CAAC,MAAMC,EAAK,CAAC,MAC9CJ,EAAI,KAAK,CAACG,EAAM,CAAC,GAAGA,EAAM,CAAC,CAAC,CAAC,GAEvBH;AACR;AAEA,SAAS6a,GAAgBC,GAA2C;AACnE,QAAMC,IAA8B,CAAA;AACpC,aAAWC,KAAQF,KAAY,IAAI;AAClC,UAAMja,IAAOf,GAAUkb,CAAI;AAC3B,QAAIna,EAAK,SAAS,EAAG;AACrB,QAAIG,IAAO,OACPC,IAAO,OACPC,IAAO,QACPC,IAAO;AACX,eAAW,CAAClB,GAAGC,CAAC,KAAKW;AACpB,MAAIZ,IAAIe,MAAMA,IAAOf,IACjBA,IAAIiB,MAAMA,IAAOjB,IACjBC,IAAIe,MAAMA,IAAOf,IACjBA,IAAIiB,MAAMA,IAAOjB;AAEtB,IAAI,CAAC,OAAO,SAASc,CAAI,KAAK,CAAC,OAAO,SAASC,CAAI,KACnD8Z,EAAS,KAAK,EAAE,MAAAla,GAAM,MAAAG,GAAM,MAAAC,GAAM,MAAAC,GAAM,MAAAC,GAAM;AAAA,EAC/C;AACA,SAAO4Z;AACR;AAEA,SAASE,GAAahb,GAAWC,GAAWW,GAA2B;AACtE,MAAIqa,IAAS;AACb,WAAS,IAAI,GAAGC,IAAIta,EAAK,SAAS,GAAG,IAAIA,EAAK,QAAQsa,IAAI,GAAG,KAAK,GAAG;AACpE,UAAMC,IAAKva,EAAK,CAAC,EAAE,CAAC,GACdwa,IAAKxa,EAAK,CAAC,EAAE,CAAC,GACdya,IAAKza,EAAKsa,CAAC,EAAE,CAAC,GACdI,IAAK1a,EAAKsa,CAAC,EAAE,CAAC;AAIpB,IAFCE,IAAKnb,KAAMqb,IAAKrb,KAChBD,KAAMqb,IAAKF,MAAOlb,IAAImb,MAASE,IAAKF,KAAO,OAAO,WAAWD,UACtC,CAACF;AAAA,EAC1B;AACA,SAAOA;AACR;AAEA,SAASM,GACRvb,GACAC,GACA4a,GACU;AACV,aAAWE,KAAQF;AAClB,QAAI,EAAA7a,IAAI+a,EAAK,QAAQ/a,IAAI+a,EAAK,QAAQ9a,IAAI8a,EAAK,QAAQ9a,IAAI8a,EAAK,SAG5DC,GAAahb,GAAGC,GAAG8a,EAAK,IAAI;AAC/B,aAAO;AAGT,SAAO;AACR;AAEO,SAASS,GACfb,GACAE,GACsB;AACtB,MAAI,CAACF,KAAa,CAACA,EAAU,SAAS,CAACA,EAAU,aAAa,CAACA,EAAU;AACxE,WAAO;AAGR,QAAMG,IAAWF,GAAgBC,KAAY,EAAE;AAC/C,MAAIC,EAAS,WAAW;AACvB,WAAO;AAAA,MACN,OAAO;AAAA,MACP,WAAW,IAAI,aAAa,CAAC;AAAA,MAC7B,gBAAgB,IAAI,YAAY,CAAC;AAAA,IAAA;AAInC,QAAMW,IAAQf,GAAmBC,CAAS,GACpCe,IAAYf,EAAU,WACtBjT,IAAQiT,EAAU,gBAClBgB,IACLhB,EAAU,eAAe,eAAeA,EAAU,IAAI,UAAUc,IAC7Dd,EAAU,MACV,MAEEiB,IAAgB,IAAI,aAAaH,IAAQ,CAAC,GAC1CI,IAAY,IAAI,YAAYJ,CAAK,GACjCK,IAAUH,IAAW,IAAI,YAAYF,CAAK,IAAI;AACpD,MAAIxI,IAAS;AAEb,WAAS7Q,IAAI,GAAGA,IAAIqZ,GAAOrZ,KAAK,GAAG;AAClC,UAAMpC,IAAI0b,EAAUtZ,IAAI,CAAC,GACnBnC,IAAIyb,EAAUtZ,IAAI,IAAI,CAAC;AAC7B,IAAKmZ,GAAmBvb,GAAGC,GAAG6a,CAAQ,MACtCc,EAAc3I,IAAS,CAAC,IAAIjT,GAC5B4b,EAAc3I,IAAS,IAAI,CAAC,IAAIhT,GAChC4b,EAAU5I,CAAM,IAAIvL,EAAMtF,CAAC,GACvB0Z,MACHA,EAAQ7I,CAAM,IAAI0I,EAAUvZ,CAAC,IAE9B6Q,KAAU;AAAA,EACX;AAEA,QAAM8I,IAAuB;AAAA,IAC5B,OAAO9I;AAAA,IACP,WAAW2I,EAAc,SAAS,GAAG3I,IAAS,CAAC;AAAA,IAC/C,gBAAgB4I,EAAU,SAAS,GAAG5I,CAAM;AAAA,EAAA;AAE7C,SAAI6I,MACHC,EAAO,MAAMD,EAAQ,SAAS,GAAG7I,CAAM,IAEjC8I;AACR;AAEO,SAASC,GACfrB,GACAE,GACc;AACd,MAAI,CAACF,KAAa,CAACA,EAAU,SAAS,CAACA,EAAU,aAAa,CAACA,EAAU;AACxE,WAAO,IAAI,YAAY,CAAC;AAGzB,QAAMG,IAAWF,GAAgBC,KAAY,EAAE;AAC/C,MAAIC,EAAS,WAAW;AACvB,WAAO,IAAI,YAAY,CAAC;AAGzB,QAAMW,IAAQf,GAAmBC,CAAS;AAC1C,MAAIc,MAAU;AACb,WAAO,IAAI,YAAY,CAAC;AAGzB,QAAMC,IAAYf,EAAU,WACtB5a,IAAM,IAAI,YAAY0b,CAAK;AACjC,MAAIxI,IAAS;AAEb,WAAS7Q,IAAI,GAAGA,IAAIqZ,GAAOrZ,KAAK,GAAG;AAClC,UAAMpC,IAAI0b,EAAUtZ,IAAI,CAAC,GACnBnC,IAAIyb,EAAUtZ,IAAI,IAAI,CAAC;AAC7B,IAAKmZ,GAAmBvb,GAAGC,GAAG6a,CAAQ,MACtC/a,EAAIkT,CAAM,IAAI7Q,GACd6Q,KAAU;AAAA,EACX;AAEA,SAAOlT,EAAI,SAAS,GAAGkT,CAAM;AAC9B;AC/EA,IAAIgJ,KAAuD;AAE3D,MAAMC,KAAwB;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;AAiC9B,SAASC,KAAqB;AAC7B,MAAI,OAAO,YAAc,IAAa,QAAO;AAC7C,QAAMC,IAAM;AACZ,SAAO,OAAOA,EAAI,OAAQ,YAAYA,EAAI,QAAQ;AACnD;AAEA,SAASC,KAA2C;AACnD,MAAI,CAACF,GAAA,EAAa,QAAO;AAEzB,QAAMG,IADM,UACI;AAChB,MAAI,CAACA,KAAO,OAAOA,KAAQ,SAAU,QAAO;AAC5C,QAAMxY,IAAYwY;AAClB,SAAI,OAAOxY,EAAU,kBAAmB,aAAmB,OACpDA;AACR;AAEA,MAAMyY,KACJ,WAAyD,gBACvD,WAAW,GACTC,KACJ,WAAyD,gBACvD,WAAW,KACTC,KACJ,WAA0D,gBACxD,YAAY,GACVC,KACJ,WAA0D,gBACxD,YAAY,GACVC,KACJ,WAAyD,gBACvD,WAAW,IACTC,KACJ,WAA0D,gBACxD,YAAY,GACVC,KACJ,WAAkD,YAAY,QAAQ;AAExE,eAAsBC,KAAqD;AAC1E,QAAMC,IAASV,GAAA;AACf,MAAI,CAACU;AACJ,WAAO,EAAE,WAAW,IAAO,UAAU,CAAA,EAAC;AAEvC,QAAMC,IAAU,MAAMD,EAAO,eAAA;AAC7B,SAAKC,IAIE;AAAA,IACN,WAAW;AAAA,IACX,aAAaA,EAAQ,MAAM,eAAeA,EAAQ,MAAM,UAAU;AAAA,IAClE,UAAU,MAAM,KAAKA,EAAQ,QAAQ;AAAA,IACrC,QAAQ;AAAA,MACP,6BAA6B;AAAA,QAC5BA,EAAQ,OAAO;AAAA,MAAA;AAAA,MAEhB,mCAAmC;AAAA,QAClCA,EAAQ,OAAO;AAAA,MAAA;AAAA,MAEhB,0BAA0B,OAAOA,EAAQ,OAAO,wBAAwB;AAAA,IAAA;AAAA,EACzE,IAfO,EAAE,WAAW,IAAO,UAAU,CAAA,EAAC;AAiBxC;AAEA,eAAeC,KAA4C;AAC1D,SAAIhB,OACJA,MAAkB,YAAY;AAC7B,UAAMc,IAASV,GAAA;AACf,QAAI,CAACU,EAAQ,QAAO;AACpB,UAAMC,IAAU,MAAMD,EAAO,eAAA;AAC7B,QAAI,CAACC,EAAS,QAAO;AACrB,UAAME,IAAS,MAAMF,EAAQ,cAAA,GAEvBG,IAAkBD,EAAO,sBAAsB;AAAA,MACpD,SAAS;AAAA,QACR;AAAA,UACC,SAAS;AAAA,UACT,YAAYX;AAAA,UACZ,QAAQ,EAAE,MAAM,oBAAA;AAAA,QAAoB;AAAA,QAErC;AAAA,UACC,SAAS;AAAA,UACT,YAAYA;AAAA,UACZ,QAAQ,EAAE,MAAM,oBAAA;AAAA,QAAoB;AAAA,QAErC;AAAA,UACC,SAAS;AAAA,UACT,YAAYA;AAAA,UACZ,QAAQ,EAAE,MAAM,UAAA;AAAA,QAAU;AAAA,QAE3B;AAAA,UACC,SAAS;AAAA,UACT,YAAYA;AAAA,UACZ,QAAQ,EAAE,MAAM,UAAA;AAAA,QAAU;AAAA,MAC3B;AAAA,IACD,CACA,GAEKa,IAAWF,EAAO,sBAAsB;AAAA,MAC7C,QAAQA,EAAO,qBAAqB,EAAE,kBAAkB,CAACC,CAAe,GAAG;AAAA,MAC3E,SAAS;AAAA,QACR,QAAQD,EAAO,mBAAmB,EAAE,MAAMhB,IAAuB;AAAA,QACjE,YAAY;AAAA,MAAA;AAAA,IACb,CACA;AAED,WAAO,EAAE,QAAAgB,GAAQ,UAAAE,GAAU,iBAAAD,EAAA;AAAA,EAC5B,GAAA,GAEOlB;AACR;AAEA,SAASoB,GAAM3d,GAAekC,GAAsB;AACnD,SAAO,KAAK,KAAKlC,IAAQkC,CAAI,IAAIA;AAClC;AAEA,eAAsB0b,GACrB5B,GACA6B,GACAjc,GAC8B;AAC9B,QAAMoK,IAAM,MAAMuR,GAAA;AAClB,MAAI,CAACvR,EAAK,QAAO;AAEjB,QAAM+P,IAAQ,KAAK,IAAI,GAAG,KAAK,MAAM8B,CAAU,CAAC,GAC1CC,IAAc,KAAK,IAAI,GAAG,KAAK,MAAMlc,EAAO,SAAS,CAAC,CAAC;AAC7D,MAAIma,MAAU,KAAK+B,MAAgB;AAClC,WAAO,IAAI,YAAY,CAAC;AAGzB,QAAMC,IAAiB,KAAK,IAAIhC,GAAO,KAAK,MAAMC,EAAU,SAAS,CAAC,CAAC;AACvE,MAAI+B,MAAmB;AACtB,WAAO,IAAI,YAAY,CAAC;AAGzB,QAAMC,IAAgBD,IAAiB,IAAI,aAAa,mBAClDE,IAAcH,IAAc,IAAI,aAAa,mBAC7CI,IAAcH,IAAiB,YAAY,mBAE3CI,IAAQ,OAAOnS,EAAI,OAAO,OAAO,2BAA2B;AAClE,MAAIgS,IAAgBG,KAASF,IAAcE,KAASD,IAAcC;AACjE,WAAO;AAGR,QAAMC,IAAkBpS,EAAI,OAAO,aAAa;AAAA,IAC/C,MAAM2R,GAAMK,GAAe,CAAC;AAAA,IAC5B,OAAOlB,KAA2BC;AAAA,EAAA,CAClC,GACKsB,IAAerS,EAAI,OAAO,aAAa;AAAA,IAC5C,MAAM2R,GAAMM,GAAa,CAAC;AAAA,IAC1B,OAAOnB,KAA2BC;AAAA,EAAA,CAClC,GACKuB,IAAetS,EAAI,OAAO,aAAa;AAAA,IAC5C,MAAM2R,GAAMO,GAAa,CAAC;AAAA,IAC1B,OAAOpB,KAA2BE;AAAA,EAAA,CAClC,GACKuB,IAAgBvS,EAAI,OAAO,aAAa;AAAA,IAC7C,MAAM;AAAA,IACN,OAAOiR,KAA2BF;AAAA,EAAA,CAClC,GACKyB,IAAaxS,EAAI,OAAO,aAAa;AAAA,IAC1C,MAAM2R,GAAMO,GAAa,CAAC;AAAA,IAC1B,OAAOnB,KAA4BG;AAAA,EAAA,CACnC;AAED,EAAAlR,EAAI,OAAO,MAAM;AAAA,IAChBoS;AAAA,IACA;AAAA,IACApC,EAAU;AAAA,IACVA,EAAU;AAAA,IACVgC;AAAA,EAAA,GAEDhS,EAAI,OAAO,MAAM;AAAA,IAChBqS;AAAA,IACA;AAAA,IACAzc,EAAO;AAAA,IACPA,EAAO;AAAA,IACPqc;AAAA,EAAA,GAEDjS,EAAI,OAAO,MAAM;AAAA,IAChBuS;AAAA,IACA;AAAA,IACA,IAAI,YAAY,CAACR,GAAgBD,GAAa,GAAG,CAAC,CAAC;AAAA,EAAA;AAGpD,QAAMW,IAAYzS,EAAI,OAAO,gBAAgB;AAAA,IAC5C,QAAQA,EAAI;AAAA,IACZ,SAAS;AAAA,MACR,EAAE,SAAS,GAAG,UAAU,EAAE,QAAQoS,IAAgB;AAAA,MAClD,EAAE,SAAS,GAAG,UAAU,EAAE,QAAQC,IAAa;AAAA,MAC/C,EAAE,SAAS,GAAG,UAAU,EAAE,QAAQC,IAAa;AAAA,MAC/C,EAAE,SAAS,GAAG,UAAU,EAAE,QAAQC,IAAc;AAAA,IAAE;AAAA,EACnD,CACA,GAEKG,IAAiB1S,EAAI,OAAO,qBAAA,GAC5B2S,IAAOD,EAAe,iBAAA;AAC5B,EAAAC,EAAK,YAAY3S,EAAI,QAAQ,GAC7B2S,EAAK,aAAa,GAAGF,CAAS,GAC9BE,EAAK,mBAAmB,KAAK,KAAKZ,IAAiB,GAAG,CAAC,GACvDY,EAAK,IAAA,GAELD,EAAe,mBAAmBJ,GAAc,GAAGE,GAAY,GAAGN,CAAW,GAC7ElS,EAAI,OAAO,MAAM,OAAO,CAAC0S,EAAe,OAAA,CAAQ,CAAC,GAEjD,MAAMF,EAAW,SAASrB,EAAiB;AAC3C,QAAMyB,IAASJ,EAAW,eAAA,GACpBne,IAAM,IAAI,YAAYue,EAAO,MAAM,CAAC,CAAC;AAC3C,SAAAJ,EAAW,MAAA,GAEXJ,EAAgB,QAAA,GAChBC,EAAa,QAAA,GACbC,EAAa,QAAA,GACbC,EAAc,QAAA,GACdC,EAAW,QAAA,GAEJne;AACR;AC9TA,SAASwe,KAAgB;AACvB,SAAI,OAAO,cAAgB,OAAe,OAAO,YAAY,OAAQ,aAC5D,YAAY,IAAA,IAEd,KAAK,IAAA;AACd;AAEA,SAAS1e,GAAUoL,GAAgC;AACjD,MAAI,CAAC,MAAM,QAAQA,CAAM,KAAKA,EAAO,SAAS,EAAG,QAAO,CAAA;AACxD,QAAMlL,IAAMkL,EAAO,IAAI,CAAC,CAACjL,GAAGC,CAAC,MAAM,CAACD,GAAGC,CAAC,CAAqB,GACvDC,IAAQH,EAAI,CAAC,GACbI,IAAOJ,EAAIA,EAAI,SAAS,CAAC;AAC/B,SAAI,CAACG,KAAS,CAACC,IAAa,CAAA,MACxBD,EAAM,CAAC,MAAMC,EAAK,CAAC,KAAKD,EAAM,CAAC,MAAMC,EAAK,CAAC,MAC7CJ,EAAI,KAAK,CAACG,EAAM,CAAC,GAAGA,EAAM,CAAC,CAAC,CAAC,GAExBH;AACT;AAEA,SAAS6a,GAAgBC,GAA2C;AAClE,QAAMC,IAA8B,CAAA;AACpC,aAAWC,KAAQF,KAAY,IAAI;AACjC,UAAMja,IAAOf,GAAUkb,CAAI;AAC3B,QAAIna,EAAK,SAAS,EAAG;AACrB,QAAIG,IAAO,OACPC,IAAO,OACPC,IAAO,QACPC,IAAO;AACX,eAAW,CAAClB,GAAGC,CAAC,KAAKW;AACnB,MAAIZ,IAAIe,MAAMA,IAAOf,IACjBA,IAAIiB,MAAMA,IAAOjB,IACjBC,IAAIe,MAAMA,IAAOf,IACjBA,IAAIiB,MAAMA,IAAOjB;AAEvB,IAAI,CAAC,OAAO,SAASc,CAAI,KAAK,CAAC,OAAO,SAASC,CAAI,KACnD8Z,EAAS,KAAK,EAAE,MAAAla,GAAM,MAAAG,GAAM,MAAAC,GAAM,MAAAC,GAAM,MAAAC,GAAM;AAAA,EAChD;AACA,SAAO4Z;AACT;AAEA,SAASE,GAAahb,GAAWC,GAAWW,GAA2B;AACrE,MAAIqa,IAAS;AACb,WAAS,IAAI,GAAGC,IAAIta,EAAK,SAAS,GAAG,IAAIA,EAAK,QAAQsa,IAAI,GAAG,KAAK,GAAG;AACnE,UAAMC,IAAKva,EAAK,CAAC,EAAE,CAAC,GACdwa,IAAKxa,EAAK,CAAC,EAAE,CAAC,GACdya,IAAKza,EAAKsa,CAAC,EAAE,CAAC,GACdI,IAAK1a,EAAKsa,CAAC,EAAE,CAAC;AAEpB,IADkBE,IAAKnb,KAAMqb,IAAKrb,KAAKD,KAAMqb,IAAKF,MAAOlb,IAAImb,MAAQE,IAAKF,KAAM,OAAO,WAAWD,UAC1E,CAACF;AAAA,EAC3B;AACA,SAAOA;AACT;AAEA,SAASM,GAAmBvb,GAAWC,GAAW4a,GAAsC;AACtF,aAAWE,KAAQF;AACjB,QAAI,EAAA7a,IAAI+a,EAAK,QAAQ/a,IAAI+a,EAAK,QAAQ9a,IAAI8a,EAAK,QAAQ9a,IAAI8a,EAAK,SAG5DC,GAAahb,GAAGC,GAAG8a,EAAK,IAAI;AAC9B,aAAO;AAGX,SAAO;AACT;AAEA,eAAsByD,GACpB7D,GACAE,GACAzd,IAAkC,CAAA,GACF;AAChC,QAAMmI,IAAQgZ,GAAA,GACRE,IAAerhB,EAAQ,iBAAiB;AAC9C,MAAI,CAACud,KAAa,CAACA,EAAU,SAAS,CAACA,EAAU,aAAa,CAACA,EAAU;AACvE,WAAO;AAAA,MACL,MAAM;AAAA,MACN,MAAM;AAAA,QACJ,MAAM;AAAA,QACN,YAAY4D,OAAUhZ;AAAA,QACtB,YAAY;AAAA,QACZ,gBAAgB;AAAA,QAChB,eAAe;AAAA,MAAA;AAAA,IACjB;AAIJ,QAAMuV,IAAWF,GAAgBC,KAAY,EAAE;AAC/C,MAAIC,EAAS,WAAW;AACtB,WAAO;AAAA,MACL,MAAM;AAAA,QACJ,OAAO;AAAA,QACP,WAAW,IAAI,aAAa,CAAC;AAAA,QAC7B,gBAAgB,IAAI,YAAY,CAAC;AAAA,MAAA;AAAA,MAEnC,MAAM;AAAA,QACJ,MAAM;AAAA,QACN,YAAYyD,OAAUhZ;AAAA,QACtB,YAAY;AAAA,QACZ,gBAAgB;AAAA,QAChB,eAAe;AAAA,MAAA;AAAA,IACjB;AAIJ,QAAMmZ,IAAY,KAAK,IAAI,GAAG,KAAK,IAAI/D,EAAU,OAAO,KAAK,MAAMA,EAAU,UAAU,SAAS,CAAC,GAAGA,EAAU,eAAe,MAAM,CAAC,GAC9HgB,IAAWhB,EAAU,eAAe,eAAeA,EAAU,IAAI,UAAU+D,IAAY/D,EAAU,MAAM;AAC7G,MAAI+D,MAAc;AAChB,WAAO;AAAA,MACL,MAAM;AAAA,QACJ,OAAO;AAAA,QACP,WAAW,IAAI,aAAa,CAAC;AAAA,QAC7B,gBAAgB,IAAI,YAAY,CAAC;AAAA,MAAA;AAAA,MAEnC,MAAM;AAAA,QACJ,MAAM;AAAA,QACN,YAAYH,OAAUhZ;AAAA,QACtB,YAAY;AAAA,QACZ,gBAAgB;AAAA,QAChB,eAAe;AAAA,MAAA;AAAA,IACjB;AAIJ,QAAMoZ,IAAW,IAAI,aAAa7D,EAAS,SAAS,CAAC;AACrD,WAAS1Y,IAAI,GAAGA,IAAI0Y,EAAS,QAAQ1Y,KAAK,GAAG;AAC3C,UAAMkK,IAAOlK,IAAI,GACX2Y,IAAOD,EAAS1Y,CAAC;AACvB,IAAAuc,EAASrS,CAAI,IAAIyO,EAAK,MACtB4D,EAASrS,IAAO,CAAC,IAAIyO,EAAK,MAC1B4D,EAASrS,IAAO,CAAC,IAAIyO,EAAK,MAC1B4D,EAASrS,IAAO,CAAC,IAAIyO,EAAK;AAAA,EAC5B;AAEA,MAAI6D,IAAoC,MACpCC,IAAa;AACjB,MAAI;AACF,IAAAD,IAAgB,MAAMtB,GAA8B3C,EAAU,WAAW+D,GAAWC,CAAQ,GAC5FE,IAAa,CAAC,CAACD;AAAA,EACjB,QAAQ;AACN,IAAAA,IAAgB,MAChBC,IAAa;AAAA,EACf;AAEA,MAAI,CAACD;AAEH,WAAO;AAAA,MACL,MAFepD,GAA0Bb,GAAWE,CAAQ;AAAA,MAG5D,MAAM;AAAA,QACJ,MAAM;AAAA,QACN,YAAY0D,OAAUhZ;AAAA,QACtB,YAAY;AAAA,QACZ,gBAAgBmZ;AAAA,QAChB,eAAe;AAAA,MAAA;AAAA,IACjB;AAIJ,MAAII,IAAiB;AACrB,WAAS1c,IAAI,GAAGA,IAAIsc,GAAWtc,KAAK;AAClC,IAAIwc,EAAcxc,CAAC,MAAM,MAAG0c,KAAkB;AAGhD,QAAMC,IAAmB,IAAI,YAAYD,CAAc;AACvD,MAAIA,IAAiB,GAAG;AACtB,QAAIE,IAAkB;AACtB,aAAS5c,IAAI,GAAGA,IAAIsc,GAAWtc,KAAK;AAClC,MAAIwc,EAAcxc,CAAC,MAAM,MACzB2c,EAAiBC,CAAe,IAAI5c,GACpC4c,KAAmB;AAAA,EAEvB;AAEA,MAAIF,MAAmB,GAAG;AACxB,QAAIL,GAAc;AAChB,YAAMQ,IAAqB;AAAA,QACzB,OAAOP;AAAA,QACP,WAAW/D,EAAU,UAAU,SAAS,GAAG+D,IAAY,CAAC;AAAA,QACxD,gBAAgB/D,EAAU,eAAe,SAAS,GAAG+D,CAAS;AAAA,QAC9D,aAAa,IAAI,YAAY,CAAC;AAAA,MAAA;AAEhC,aAAI/C,MACFsD,EAAK,MAAMtD,EAAS,SAAS,GAAG+C,CAAS,IAEpC;AAAA,QACL,MAAAO;AAAA,QACA,MAAM;AAAA,UACJ,MAAM;AAAA,UACN,YAAYV,OAAUhZ;AAAA,UACtB,YAAY;AAAA,UACZ,gBAAgB;AAAA,UAChB,eAAe;AAAA,QAAA;AAAA,MACjB;AAAA,IAEJ;AAEA,WAAO;AAAA,MACL,MAAM;AAAA,QACJ,OAAO;AAAA,QACP,WAAW,IAAI,aAAa,CAAC;AAAA,QAC7B,gBAAgB,IAAI,YAAY,CAAC;AAAA,QACjC,GAAIoW,IAAW,EAAE,KAAK,IAAI,YAAY,CAAC,EAAA,IAAM,CAAA;AAAA,MAAC;AAAA,MAEhD,MAAM;AAAA,QACJ,MAAM;AAAA,QACN,YAAY4C,OAAUhZ;AAAA,QACtB,YAAY;AAAA,QACZ,gBAAgB;AAAA,QAChB,eAAe;AAAA,MAAA;AAAA,IACjB;AAAA,EAEJ;AAEA,MAAIkZ,GAAc;AAChB,UAAMS,IAAc,IAAI,YAAYJ,CAAc;AAClD,QAAIK,IAAe;AAEnB,aAAS/c,IAAI,GAAGA,IAAI0c,GAAgB1c,KAAK,GAAG;AAC1C,YAAMgd,KAAaL,EAAiB3c,CAAC,KAAK,GACpCpC,KAAI2a,EAAU,UAAUyE,KAAa,CAAC,GACtCnf,IAAI0a,EAAU,UAAUyE,KAAa,IAAI,CAAC;AAChD,MAAK7D,GAAmBvb,IAAGC,GAAG6a,CAAQ,MACtCoE,EAAYC,CAAY,IAAIC,IAC5BD,KAAgB;AAAA,IAClB;AAEA,UAAMF,IAAqB;AAAA,MACzB,OAAOP;AAAA,MACP,WAAW/D,EAAU,UAAU,SAAS,GAAG+D,IAAY,CAAC;AAAA,MACxD,gBAAgB/D,EAAU,eAAe,SAAS,GAAG+D,CAAS;AAAA,MAC9D,aAAaQ,EAAY,SAAS,GAAGC,CAAY;AAAA,IAAA;AAEnD,WAAIxD,MACFsD,EAAK,MAAMtD,EAAS,SAAS,GAAG+C,CAAS,IAGpC;AAAA,MACL,MAAAO;AAAA,MACA,MAAM;AAAA,QACJ,MAAM;AAAA,QACN,YAAYV,OAAUhZ;AAAA,QACtB,YAAY;AAAA,QACZ,gBAAAuZ;AAAA,QACA,eAAe;AAAA,MAAA;AAAA,IACjB;AAAA,EAEJ;AAEA,QAAMlD,IAAgB,IAAI,aAAakD,IAAiB,CAAC,GACnDjD,IAAY,IAAI,YAAYiD,CAAc,GAC1ChD,IAAUH,IAAW,IAAI,YAAYmD,CAAc,IAAI;AAC7D,MAAI7L,IAAS;AAEb,WAAS7Q,IAAI,GAAGA,IAAI0c,GAAgB1c,KAAK,GAAG;AAC1C,UAAMgd,IAAaL,EAAiB3c,CAAC,KAAK,GACpCpC,IAAI2a,EAAU,UAAUyE,IAAa,CAAC,GACtCnf,IAAI0a,EAAU,UAAUyE,IAAa,IAAI,CAAC;AAChD,IAAK7D,GAAmBvb,GAAGC,GAAG6a,CAAQ,MACtCc,EAAc3I,IAAS,CAAC,IAAIjT,GAC5B4b,EAAc3I,IAAS,IAAI,CAAC,IAAIhT,GAChC4b,EAAU5I,CAAM,IAAI0H,EAAU,eAAeyE,CAAU,GACnDtD,MACFA,EAAQ7I,CAAM,IAAI0I,EAAUyD,CAAU,IAExCnM,KAAU;AAAA,EACZ;AAEA,QAAMoM,IAA4B;AAAA,IAChC,OAAOpM;AAAA,IACP,WAAW2I,EAAc,SAAS,GAAG3I,IAAS,CAAC;AAAA,IAC/C,gBAAgB4I,EAAU,SAAS,GAAG5I,CAAM;AAAA,EAAA;AAE9C,SAAI6I,MACFuD,EAAY,MAAMvD,EAAQ,SAAS,GAAG7I,CAAM,IAGvC;AAAA,IACL,MAAMoM;AAAA,IACN,MAAM;AAAA,MACJ,MAAM;AAAA,MACN,YAAYd,OAAUhZ;AAAA,MACtB,YAAY;AAAA,MACZ,gBAAAuZ;AAAA,MACA,eAAe;AAAA,IAAA;AAAA,EACjB;AAEJ;AClRA,IAAIQ,KAAgC,MAChCC,KAAkB,IAClBC,KAAY;AAChB,MAAMC,yBAAkB,IAAA;AAExB,SAASlB,KAAgB;AACvB,SAAI,OAAO,cAAgB,OAAe,OAAO,YAAY,OAAQ,aAC5D,YAAY,IAAA,IAEd,KAAK,IAAA;AACd;AAEA,SAASmB,KAA8B;AACrC,MAAI,CAACH,GAAiB,QAAO;AAC7B,MAAID,GAAgB,QAAOA;AAC3B,MAAI;AACF,UAAMK,IAAS,IAAI,OAAO,IAAA;AAAA;AAAA,MAAA,KAAA,IAAA,IAAA,sCAAA,YAAA,GAAA,EAAA;AAAA,MAAA,YAAA;AAAA,IAAA,GAA2D,EAAE,MAAM,SAAA,CAAU;AACvG,WAAAA,EAAO,iBAAiB,WAAWC,EAAmB,GACtDD,EAAO,iBAAiB,SAASE,EAAiB,GAClDP,KAAiBK,GACVA;AAAA,EACT,QAAQ;AACN,WAAAJ,KAAkB,IACX;AAAA,EACT;AACF;AAEA,SAASK,GAAoBpL,GAAkD;AAC7E,QAAMsL,IAAMtL,EAAM;AAClB,MAAI,CAACsL,EAAK;AACV,QAAMC,IAAUN,GAAY,IAAIK,EAAI,EAAE;AACtC,MAAI,CAACC,EAAS;AAGd,MAFAN,GAAY,OAAOK,EAAI,EAAE,GAErBA,EAAI,SAAS,oBAAoB;AACnC,IAAAC,EAAQ,OAAO,IAAI,MAAMD,EAAI,SAAS,oBAAoB,CAAC;AAC3D;AAAA,EACF;AAEA,MAAIA,EAAI,SAAS,0BAA0B;AACzC,QAAIC,EAAQ,SAAS,SAAS;AAC5B,MAAAA,EAAQ,OAAO,IAAI,MAAM,sDAAsD,CAAC;AAChF;AAAA,IACF;AACA,UAAMtE,IAAQ,KAAK,IAAI,GAAG,KAAK,MAAMqE,EAAI,KAAK,CAAC,GACzCE,IAAU,IAAI,YAAYF,EAAI,OAAO,EAAE,SAAS,GAAGrE,CAAK;AAC9D,IAAAsE,EAAQ,QAAQ;AAAA,MACd,SAAAC;AAAA,MACA,MAAM;AAAA,QACJ,MAAM;AAAA,QACN,YAAY,OAAO,SAASF,EAAI,UAAU,IAAIA,EAAI,aAAavB,GAAA,IAAUwB,EAAQ;AAAA,MAAA;AAAA,IACnF,CACD;AACD;AAAA,EACF;AAEA,MAAIA,EAAQ,SAAS,QAAQ;AAC3B,IAAAA,EAAQ,OAAO,IAAI,MAAM,iDAAiD,CAAC;AAC3E;AAAA,EACF;AAEA,QAAMtE,IAAQ,KAAK,IAAI,GAAG,KAAK,MAAMqE,EAAI,KAAK,CAAC,GACzCpE,IAAY,IAAI,aAAaoE,EAAI,SAAS,GAC1CG,IAAiB,IAAI,YAAYH,EAAI,cAAc,GACnDI,IAAMJ,EAAI,MAAM,IAAI,YAAYA,EAAI,GAAG,IAAI,MAC3C/D,IAAuB;AAAA,IAC3B,OAAAN;AAAA,IACA,WAAWC,EAAU,SAAS,GAAGD,IAAQ,CAAC;AAAA,IAC1C,gBAAgBwE,EAAe,SAAS,GAAGxE,CAAK;AAAA,EAAA;AAElD,EAAIyE,MACFnE,EAAO,MAAMmE,EAAI,SAAS,GAAGzE,CAAK,IAGpCsE,EAAQ,QAAQ;AAAA,IACd,MAAMhE;AAAA,IACN,MAAM;AAAA,MACJ,MAAM;AAAA,MACN,YAAY,OAAO,SAAS+D,EAAI,UAAU,IAAIA,EAAI,aAAavB,GAAA,IAAUwB,EAAQ;AAAA,IAAA;AAAA,EACnF,CACD;AACH;AAEA,SAASF,KAA0B;AACjC,EAAAN,KAAkB,IACdD,OACFA,GAAe,oBAAoB,WAAWM,EAAmB,GACjEN,GAAe,oBAAoB,SAASO,EAAiB,GAC7DP,GAAe,UAAA,GACfA,KAAiB;AAEnB,aAAW,CAAA,EAAGS,CAAO,KAAKN;AACxB,IAAAM,EAAQ,OAAO,IAAI,MAAM,gBAAgB,CAAC;AAE5C,EAAAN,GAAY,MAAA;AACd;AAEO,SAASU,KAA+B;AAC7C,MAAKb,IACL;AAAA,IAAAA,GAAe,oBAAoB,WAAWM,EAAmB,GACjEN,GAAe,oBAAoB,SAASO,EAAiB,GAC7DP,GAAe,UAAA,GACfA,KAAiB;AACjB,eAAW,CAAA,EAAGS,CAAO,KAAKN;AACxB,MAAAM,EAAQ,OAAO,IAAI,MAAM,mBAAmB,CAAC;AAE/C,IAAAN,GAAY,MAAA;AAAA;AACd;AAEA,eAAsBW,GAAkCzF,GAA4CE,GAAqE;AACvK,MAAI,CAACF,KAAa,CAACA,EAAU,SAAS,CAACA,EAAU,aAAa,CAACA,EAAU;AACvE,WAAO;AAAA,MACL,MAAM;AAAA,MACN,MAAM,EAAE,MAAM,UAAU,YAAY,EAAA;AAAA,IAAE;AAI1C,QAAMgF,IAASD,GAAA;AACf,MAAI,CAACC,GAAQ;AACX,UAAMpa,IAAQgZ,GAAA;AACd,WAAO;AAAA,MACL,MAAM/C,GAA0Bb,GAAWE,CAAQ;AAAA,MACnD,MAAM,EAAE,MAAM,QAAQ,YAAY0D,GAAA,IAAUhZ,EAAA;AAAA,IAAM;AAAA,EAEtD;AAEA,QAAMmZ,IAAY,KAAK,IAAI,GAAG,KAAK,IAAI/D,EAAU,OAAO,KAAK,MAAMA,EAAU,UAAU,SAAS,CAAC,GAAGA,EAAU,eAAe,MAAM,CAAC,GAC9H0F,IAAgB1F,EAAU,UAAU,MAAM,GAAG+D,IAAY,CAAC,GAC1D4B,IAAY3F,EAAU,eAAe,MAAM,GAAG+D,CAAS,GACvD6B,IAAU5F,EAAU,eAAe,eAAeA,EAAU,IAAI,UAAU+D,IAAY/D,EAAU,IAAI,MAAM,GAAG+D,CAAS,IAAI,MAC1Hxa,IAAKsb,MACLgB,IAAUjC,GAAA;AAEhB,SAAO,IAAI,QAAyB,CAACkC,GAASC,MAAW;AACvD,IAAAjB,GAAY,IAAIvb,GAAI,EAAE,MAAM,QAAQ,SAAAuc,GAAS,QAAAC,GAAQ,SAAAF,GAAS;AAC9D,UAAMV,IAA4B;AAAA,MAChC,MAAM;AAAA,MACN,IAAA5b;AAAA,MACA,OAAOwa;AAAA,MACP,WAAW2B,EAAc;AAAA,MACzB,gBAAgBC,EAAU;AAAA,MAC1B,KAAKC,GAAS;AAAA,MACd,UAAU1F,KAAY,CAAA;AAAA,IAAC,GAEnB8F,IAA2B,CAACN,EAAc,QAAQC,EAAU,MAAM;AACxE,IAAIC,KACFI,EAAS,KAAKJ,EAAQ,MAAM,GAE9BZ,EAAO,YAAYG,GAAKa,CAAQ;AAAA,EAClC,CAAC;AACH;AAEA,eAAsBC,GAAqCjG,GAA4CE,GAA0E;AAC/K,MAAI,CAACF,KAAa,CAACA,EAAU,SAAS,CAACA,EAAU,aAAa,CAACA,EAAU;AACvE,WAAO;AAAA,MACL,SAAS,IAAI,YAAY,CAAC;AAAA,MAC1B,MAAM,EAAE,MAAM,UAAU,YAAY,EAAA;AAAA,IAAE;AAI1C,QAAMgF,IAASD,GAAA;AACf,MAAI,CAACC,GAAQ;AACX,UAAMpa,IAAQgZ,GAAA;AACd,WAAO;AAAA,MACL,SAASvC,GAA6BrB,GAAWE,CAAQ;AAAA,MACzD,MAAM,EAAE,MAAM,QAAQ,YAAY0D,GAAA,IAAUhZ,EAAA;AAAA,IAAM;AAAA,EAEtD;AAEA,QAAMmZ,IAAY,KAAK,IAAI,GAAG,KAAK,IAAI/D,EAAU,OAAO,KAAK,MAAMA,EAAU,UAAU,SAAS,CAAC,GAAGA,EAAU,eAAe,MAAM,CAAC,GAC9H0F,IAAgB1F,EAAU,UAAU,MAAM,GAAG+D,IAAY,CAAC,GAC1Dxa,IAAKsb,MACLgB,IAAUjC,GAAA;AAEhB,SAAO,IAAI,QAA8B,CAACkC,GAASC,MAAW;AAC5D,IAAAjB,GAAY,IAAIvb,GAAI,EAAE,MAAM,SAAS,SAAAuc,GAAS,QAAAC,GAAQ,SAAAF,GAAS;AAC/D,UAAMV,IAA4B;AAAA,MAChC,MAAM;AAAA,MACN,IAAA5b;AAAA,MACA,OAAOwa;AAAA,MACP,WAAW2B,EAAc;AAAA,MACzB,UAAUxF,KAAY,CAAA;AAAA,IAAC;AAEzB,IAAA8E,EAAO,YAAYG,GAAK,CAACO,EAAc,MAAM,CAAC;AAAA,EAChD,CAAC;AACH;ACxLA,SAASxgB,GACRC,GAC0B;AAC1B,MAAI,CAAC,MAAM,QAAQA,CAAW,KAAKA,EAAY,SAAS,EAAG,QAAO,CAAA;AAClE,QAAMC,IAAMD,EAAY;AAAA,IACvB,CAACQ,MAA4B,CAAC,OAAOA,EAAM,CAAC,CAAC,GAAG,OAAOA,EAAM,CAAC,CAAC,CAAC;AAAA,EAAA,GAE3DJ,IAAQH,EAAI,CAAC,GACbI,IAAOJ,EAAIA,EAAI,SAAS,CAAC;AAC/B,SAAI,CAACG,KAAS,CAACC,IAAa,CAAA,MACxBD,EAAM,CAAC,MAAMC,EAAK,CAAC,KAAKD,EAAM,CAAC,MAAMC,EAAK,CAAC,MAC9CJ,EAAI,KAAK,CAACG,EAAM,CAAC,GAAGA,EAAM,CAAC,CAAC,CAAC,GAEvBH;AACR;AAEA,SAASuL,GAAY1K,GAAuC;AAC3D,MAAIwD,IAAM;AACV,WAAShC,IAAI,GAAGA,IAAIxB,EAAK,SAAS,GAAGwB,KAAK,GAAG;AAC5C,UAAM,CAACye,GAAIC,CAAE,IAAIlgB,EAAKwB,CAAC,GACjB,CAAC2e,GAAIC,CAAE,IAAIpgB,EAAKwB,IAAI,CAAC;AAC3B,IAAAgC,KAAOyc,IAAKG,IAAKD,IAAKD;AAAA,EACvB;AACA,SAAO,KAAK,IAAI1c,IAAM,GAAG;AAC1B;AAEA,SAAS6c,GAAeC,GAAiD;AACxE,QAAMpG,IAA6B,CAAA;AACnC,WAAS1Y,IAAI,GAAGA,IAAI8e,EAAQ,QAAQ9e,KAAK,GAAG;AAC3C,UAAMgR,IAAS8N,EAAQ9e,CAAC;AACxB,QAAI,CAACgR,GAAQ,aAAa,OAAQ;AAElC,UAAMxS,IAAOf,GAAUuT,EAAO,WAAW;AACzC,QAAIxS,EAAK,SAAS,EAAG;AAErB,QAAIG,IAAO,OACPC,IAAO,OACPC,IAAO,QACPC,IAAO;AACX,eAAW,CAAClB,GAAGC,CAAC,KAAKW;AACpB,MAAIZ,IAAIe,MAAMA,IAAOf,IACjBA,IAAIiB,MAAMA,IAAOjB,IACjBC,IAAIe,MAAMA,IAAOf,IACjBA,IAAIiB,MAAMA,IAAOjB;AAEtB,IACC,CAAC,OAAO,SAASc,CAAI,KACrB,CAAC,OAAO,SAASC,CAAI,KACrB,CAAC,OAAO,SAASC,CAAI,KACrB,CAAC,OAAO,SAASC,CAAI,KAKtB4Z,EAAS,KAAK;AAAA,MACb,UAAU1H,EAAO,MAAMhR;AAAA,MACvB,aAAaA;AAAA,MACb,MAAAxB;AAAA,MACA,MAAAG;AAAA,MACA,MAAAC;AAAA,MACA,MAAAC;AAAA,MACA,MAAAC;AAAA,MACA,MAAM,KAAK,IAAI,MAAMoK,GAAY1K,CAAI,CAAC;AAAA,IAAA,CACtC;AAAA,EACF;AACA,SAAOka;AACR;AAEA,SAASE,GAAahb,GAAWC,GAAWW,GAAwC;AACnF,MAAIqa,IAAS;AACb,WAAS,IAAI,GAAGC,IAAIta,EAAK,SAAS,GAAG,IAAIA,EAAK,QAAQsa,IAAI,GAAG,KAAK,GAAG;AACpE,UAAMC,IAAKva,EAAK,CAAC,EAAE,CAAC,GACdwa,IAAKxa,EAAK,CAAC,EAAE,CAAC,GACdya,IAAKza,EAAKsa,CAAC,EAAE,CAAC,GACdI,IAAK1a,EAAKsa,CAAC,EAAE,CAAC;AAIpB,IAFCE,IAAKnb,KAAMqb,IAAKrb,KAChBD,KAAMqb,IAAKF,MAAOlb,IAAImb,MAASE,IAAKF,KAAO,OAAO,WAAWD,UACtC,CAACF;AAAA,EAC1B;AACA,SAAOA;AACR;AAEA,SAASkG,GACRC,GACAC,GACS;AACT,MAAI,MAAM,QAAQA,CAAoB,GAAG;AACxC,UAAMC,IAAYD,EAAqBD,CAAY;AACnD,QAAI,OAAOE,KAAc,YAAYA,EAAU,SAAS,EAAG,QAAOA;AAAA,EACnE;AACA,MAAID,aAAgC,KAAK;AACxC,UAAME,IAAUF,EAAqB,IAAID,CAAY;AACrD,QAAI,OAAOG,KAAY,YAAYA,EAAQ,SAAS,EAAG,QAAOA;AAAA,EAC/D;AACA,SAAO,OAAOH,CAAY;AAC3B;AAEO,SAASI,GACf7G,GACAuG,GACA9jB,IAAgC,CAAA,GACX;AACrB,QAAMqkB,IAAY,KAAK;AAAA,IACtB;AAAA,IACA,KAAK;AAAA,MACJ,KAAK,MAAM9G,GAAW,SAAS,CAAC;AAAA,MAChC,KAAK,OAAOA,GAAW,WAAW,UAAU,KAAK,CAAC;AAAA,MAClDA,GAAW,gBAAgB,UAAU;AAAA,IAAA;AAAA,EACtC;AAGD,MAAIuE,IAAkC;AACtC,MAAIvE,GAAW,uBAAuB,aAAa;AAClD,UAAMpf,IAASof,EAAU;AACzB,QAAI+G,IAAQnmB,EAAO;AACnB,aAAS6G,IAAI,GAAGA,IAAI7G,EAAO,QAAQ6G,KAAK;AAEvC,MADY7G,EAAO6G,CAAC,IACVqf,MACVC,KAAS;AAEV,QAAIA,MAAUnmB,EAAO;AACpB,MAAA2jB,IAAc3jB;AAAA,aACJmmB,IAAQ,GAAG;AACrB,YAAMC,IAAW,IAAI,YAAYD,CAAK;AACtC,UAAIzO,IAAS;AACb,eAAS7Q,IAAI,GAAGA,IAAI7G,EAAO,QAAQ6G,KAAK,GAAG;AAC1C,cAAMwf,IAAMrmB,EAAO6G,CAAC;AACpB,QAAIwf,KAAOH,MACXE,EAAS1O,CAAM,IAAI2O,GACnB3O,KAAU;AAAA,MACX;AACA,MAAAiM,IAAcyC;AAAA,IACf;AACC,MAAAzC,IAAc,IAAI,YAAY,CAAC;AAAA,EAEjC;AAEA,QAAM2C,IAAa3C,IAAcA,EAAY,SAASuC,GAEhDK,IAAkBb,GAAeC,KAAW,EAAE;AACpD,MAAI,CAACvG,KAAakH,MAAe,KAAKC,EAAgB,WAAW;AAChE,WAAO;AAAA,MACN,QAAQ,CAAA;AAAA,MACR,iBAAiBD;AAAA,MACjB,uBAAuB;AAAA,MACvB,qBAAqBA;AAAA,IAAA;AAIvB,QAAME,wBAAyB,IAAA,GACzBC,wBAA0B,IAAA;AAChC,MAAIC,IAAc;AAElB,WAAS7f,IAAI,GAAGA,IAAIyf,GAAYzf,KAAK,GAAG;AACvC,UAAMgd,IAAaF,IAAcA,EAAY9c,CAAC,IAAIA,GAC5C,IAAIuY,EAAU,UAAUyE,IAAa,CAAC,GACtCnf,IAAI0a,EAAU,UAAUyE,IAAa,IAAI,CAAC;AAChD,QAAI8C,IAAoC;AAExC,eAAW9O,KAAU0O;AACpB,MAAI,IAAI1O,EAAO,QAAQ,IAAIA,EAAO,QAAQnT,IAAImT,EAAO,QAAQnT,IAAImT,EAAO,QAGnE4H,GAAa,GAAG/a,GAAGmT,EAAO,IAAI,MAC/B,CAAC8O,KAAc9O,EAAO,OAAO8O,EAAW,UAC3CA,IAAa9O;AAIf,QAAI,CAAC8O,EAAY;AACjB,IAAAD,KAAe;AAEf,UAAMb,IAAezG,EAAU,eAAeyE,CAAU,KAAK,GACvD+C,IACLJ,EAAmB,IAAIG,EAAW,WAAW,yBAAS,IAAA;AACvD,IAAAC,EAAc,IAAIf,IAAee,EAAc,IAAIf,CAAY,KAAK,KAAK,CAAC,GAC1EW,EAAmB,IAAIG,EAAW,aAAaC,CAAa,GAC5DH,EAAoB;AAAA,MACnBE,EAAW;AAAA,OACVF,EAAoB,IAAIE,EAAW,WAAW,KAAK,KAAK;AAAA,IAAA;AAAA,EAE3D;AAEA,QAAME,IAAsBhlB,EAAQ,uBAAuB,IACrDilB,IAA0B,CAAA;AAChC,aAAWjP,KAAU0O,GAAiB;AACrC,UAAMQ,IAAaN,EAAoB,IAAI5O,EAAO,WAAW,KAAK;AAClE,QAAI,CAACgP,KAAuBE,KAAc,EAAG;AAC7C,UAAMC,IAAUR,EAAmB,IAAI3O,EAAO,WAAW,yBAAS,IAAA,GAC5DoP,IAA6B,MAAM,KAAKD,EAAQ,SAAS,EAC7D,IAAI,CAAC,CAACnB,GAAc3F,CAAK,OAAO;AAAA,MAChC,QAAQ0F,GAAcC,GAAchkB,EAAQ,oBAAoB;AAAA,MAChE,cAAAgkB;AAAA,MACA,OAAA3F;AAAA,IAAA,EACC,EACD,KAAK,CAACpX,GAAGC,MAAMA,EAAE,QAAQD,EAAE,SAASA,EAAE,eAAeC,EAAE,YAAY;AAErE,IAAA+d,EAAO,KAAK;AAAA,MACX,UAAUjP,EAAO;AAAA,MACjB,aAAaA,EAAO;AAAA,MACpB,YAAAkP;AAAA,MACA,YAAAE;AAAA,IAAA,CACA;AAAA,EACF;AAEA,SAAO;AAAA,IACN,QAAAH;AAAA,IACA,iBAAiBR;AAAA,IACjB,uBAAuBI;AAAA,IACvB,qBAAqB,KAAK,IAAI,GAAGJ,IAAaI,CAAW;AAAA,EAAA;AAE3D;AC3MA,SAAS1D,KAAgB;AACxB,SAAI,OAAO,cAAgB,OAAe,OAAO,YAAY,OAAQ,aAC7D,YAAY,IAAA,IAEb,KAAK,IAAA;AACb;AAEA,SAASkE,GAAuBC,GAAavL,GAA4B;AACxE,MAAI,CAACA,EAAW,QAAO;AACvB,MAAI;AAEH,UAAMwL,IADS,IAAI,IAAID,GAAK,OAAO,SAAW,MAAc,OAAO,SAAS,OAAO,MAAS,EACxE,SAAS,YAAA;AAG7B,QADCC,EAAK,SAAS,eAAe,KAAKA,EAAK,WAAW,KAAK,KAAKA,EAAK,SAAS,MAAM,EACpE,QAAO;AAAA,EACrB,QAAQ;AAAA,EAER;AACA,SAAO;AACR;AAEO,MAAMC,GAAc;AAAA,EAwB1B,YAAYxlB,GAA+B;AAvB1B,IAAAb,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA;AAGA,IAAAA,EAAA;AAIT,IAAAA,EAAA;AACA,IAAAA,EAAA,mBAAY;AACZ,IAAAA,EAAA,eAAqB,CAAA;AACrB,IAAAA,EAAA,yCAAkB,IAAA;AAClB,IAAAA,EAAA,sCAAe,IAAA;AACf,IAAAA,EAAA,yCAAkB,IAAA;AAClB,IAAAA,EAAA,iBAAyB;AACzB,IAAAA,EAAA,sBAAe;AACf,IAAAA,EAAA,oBAAa;AACb,IAAAA,EAAA,qBAAc;AAGrB,SAAK,iBAAiB,KAAK,IAAI,GAAG,KAAK,MAAMa,EAAQ,kBAAkB,EAAE,CAAC,GAC1E,KAAK,aAAa,KAAK,IAAI,GAAG,KAAK,MAAMA,EAAQ,cAAc,CAAC,CAAC,GACjE,KAAK,mBAAmB,KAAK;AAAA,MAC5B;AAAA,MACA,KAAK,MAAMA,EAAQ,oBAAoB,GAAG;AAAA,IAAA,GAE3C,KAAK,kBAAkB,KAAK;AAAA,MAC3B,KAAK;AAAA,MACL,KAAK,MAAMA,EAAQ,mBAAmB,IAAI;AAAA,IAAA,GAE3C,KAAK,YAAYA,EAAQ,aAAa,IACtC,KAAK,aAAaA,EAAQ,YAC1B,KAAK,cAAcA,EAAQ,aAC3B,KAAK,gBAAgBA,EAAQ;AAAA,EAC9B;AAAA,EAEA,aAAagK,GAAqB;AACjC,SAAK,YAAY,OAAOA,KAAS,EAAE;AAAA,EACpC;AAAA,EAEA,SAASxJ,GAAuC;AAC/C,QAAI,KAAK,UAAW;AAEpB,UAAMilB,wBAAsB,IAAA;AAC5B,eAAW9kB,KAAQH;AAClB,MAAAilB,EAAgB,IAAI9kB,EAAK,GAAG;AAE7B,SAAK,cAAc8kB,GAEnB,KAAK,oBAAoBA,CAAe,GACxC,KAAK,uBAAuBA,CAAe;AAE3C,eAAW9kB,KAAQH,GAAO;AACzB,UAAI,KAAK,SAAS,IAAIG,EAAK,GAAG,GAAG;AAChC,cAAM+kB,IAAW,KAAK,SAAS,IAAI/kB,EAAK,GAAG;AAC3C,QAAI+kB,QAAmB,OAAO/kB;AAC9B;AAAA,MACD;AAEA,YAAMglB,IAAS,KAAK,YAAY,IAAIhlB,EAAK,GAAG;AAC5C,UAAIglB,GAAQ;AACX,QAAAA,EAAO,OAAOhlB;AACd;AAAA,MACD;AAEA,YAAMwM,IAAkB;AAAA,QACvB,MAAAxM;AAAA,QACA,SAAS;AAAA,QACT,SAASwgB,GAAA;AAAA,MAAM;AAEhB,WAAK,MAAM,KAAKhU,CAAI,GACpB,KAAK,YAAY,IAAIxM,EAAK,KAAKwM,CAAI;AAAA,IACpC;AAEA,SAAK,UAAA,GACL,KAAK,KAAA,GACL,KAAK,gBAAA;AAAA,EACN;AAAA,EAEA,QAAc;AACb,SAAK,eAAA,GACL,KAAK,YAAY,MAAA,GACjB,KAAK,QAAQ,CAAA,GACb,KAAK,YAAY,MAAA;AAEjB,eAAW,CAAA,EAAGA,CAAI,KAAK,KAAK;AAC3B,MAAAA,EAAK,WAAW,MAAA;AAEjB,SAAK,SAAS,MAAA,GACd,KAAK,gBAAA;AAAA,EACN;AAAA,EAEA,UAAgB;AACf,IAAI,KAAK,cACT,KAAK,YAAY,IACjB,KAAK,MAAA;AAAA,EACN;AAAA,EAEA,mBAA2B;AAC1B,WAAO,KAAK,SAAS;AAAA,EACtB;AAAA,EAEA,cAAqC;AACpC,WAAO;AAAA,MACN,UAAU,KAAK,SAAS;AAAA,MACxB,QAAQ,KAAK,MAAM;AAAA,MACnB,SAAS,KAAK;AAAA,MACd,SAAS,KAAK;AAAA,MACd,QAAQ,KAAK;AAAA,IAAA;AAAA,EAEf;AAAA,EAEQ,oBAAoByY,GAAgC;AAC3D,QAAI,KAAK,MAAM,WAAW,EAAG;AAC7B,UAAMC,IAAyB,CAAA;AAC/B,eAAW1Y,KAAQ,KAAK,OAAO;AAC9B,UAAI,CAACyY,EAAY,IAAIzY,EAAK,KAAK,GAAG,GAAG;AACpC,aAAK,YAAY,OAAOA,EAAK,KAAK,GAAG;AACrC;AAAA,MACD;AACA,MAAA0Y,EAAU,KAAK1Y,CAAI;AAAA,IACpB;AACA,SAAK,QAAQ0Y;AAAA,EACd;AAAA,EAEQ,uBAAuBD,GAAgC;AAC9D,eAAW,CAACE,GAAK3Y,CAAI,KAAK,KAAK;AAC9B,MAAIyY,EAAY,IAAIE,CAAG,MACvB,KAAK,SAAS,OAAOA,CAAG,GACxB,KAAK,gBAAgB,GACrB3Y,EAAK,WAAW,MAAA;AAAA,EAElB;AAAA,EAEQ,YAAkB;AACzB,SAAK,MAAM,KAAK,CAAClG,GAAGC,MACfD,EAAE,YAAYC,EAAE,UAAgBD,EAAE,UAAUC,EAAE,UAC9CD,EAAE,KAAK,cAAcC,EAAE,KAAK,YACxBD,EAAE,KAAK,YAAYC,EAAE,KAAK,YAE9BD,EAAE,KAAK,SAASC,EAAE,KAAK,OAAaA,EAAE,KAAK,OAAOD,EAAE,KAAK,OACtDA,EAAE,KAAK,IAAI,cAAcC,EAAE,KAAK,GAAG,CAC1C;AAAA,EACF;AAAA,EAEQ,OAAa;AACpB,QAAI,KAAK,UAAW;AAGpB,SAFA,KAAK,eAAA,GAEE,KAAK,SAAS,OAAO,KAAK,kBAAgB;AAChD,YAAM5H,IAAO,KAAK,uBAAA;AAClB,UAAI,CAACA,EAAM;AACX,WAAK,WAAWA,CAAI;AAAA,IACrB;AAMA,QAJI,KAAK,SAAS,QAAQ,KAAK,kBAI3B,KAAK,MAAM,WAAW,EAAG;AAE7B,UAAMymB,IAAkB,KAAK,MAAM,CAAC,GAAG;AACvC,QAAI,OAAOA,KAAoB,SAAU;AACzC,UAAMC,IAAQ,KAAK,IAAI,GAAGD,IAAkB5E,IAAO;AACnD,SAAK,UAAU,OAAO,WAAW,MAAM;AACtC,WAAK,UAAU,MACf,KAAK,KAAA;AAAA,IACN,GAAG6E,CAAK;AAAA,EACT;AAAA,EAEQ,yBAA2C;AAClD,QAAI,KAAK,MAAM,WAAW,EAAG,QAAO;AACpC,UAAMC,IAAM9E,GAAA,GACNre,IAAQ,KAAK,MAAM,CAAC;AAC1B,WAAI,CAACA,KAASA,EAAM,UAAUmjB,IAAY,QAE1C,KAAK,MAAM,MAAA,GACX,KAAK,YAAY,OAAOnjB,EAAM,KAAK,GAAG,GAC/BA;AAAA,EACR;AAAA,EAEQ,WAAWqK,GAAuB;AACzC,UAAM+Y,IAAa,IAAI,gBAAA,GACjBC,IAA8B;AAAA,MACnC,MAAMhZ,EAAK;AAAA,MACX,SAASA,EAAK;AAAA,MACd,YAAA+Y;AAAA,IAAA;AAED,SAAK,SAAS,IAAI/Y,EAAK,KAAK,KAAKgZ,CAAa,GAC9C,KAAK,gBAAA;AAEL,UAAMpJ,IAAgBsI,GAAuBlY,EAAK,KAAK,KAAK,KAAK,SAAS;AAC1E,UAAMA,EAAK,KAAK,KAAK;AAAA,MACpB,QAAQ+Y,EAAW;AAAA,MACnB,SAASnJ,IAAgB,EAAE,eAAe,KAAK,cAAc;AAAA,IAAA,CAC7D,EACC,KAAK,CAAClc,MAAa;AACnB,UAAI,CAACA,EAAS;AACb,cAAM,IAAI,MAAM,QAAQA,EAAS,MAAM,EAAE;AAE1C,aAAOA,EAAS,KAAA;AAAA,IACjB,CAAC,EACA,KAAK,CAACC,MAAS,kBAAkBA,CAAI,CAAC,EACtC,KAAK,CAACC,MAAW;AACjB,UAAI,KAAK,aAAamlB,EAAW,OAAO,SAAS;AAChD,QAAAnlB,EAAO,MAAA;AACP;AAAA,MACD;AACA,UAAI,CAAC,KAAK,YAAY,IAAIoM,EAAK,KAAK,GAAG,GAAG;AACzC,QAAApM,EAAO,MAAA;AACP;AAAA,MACD;AACA,WAAK,WAAWoM,EAAK,MAAMpM,CAAM;AAAA,IAClC,CAAC,EACA,MAAM,CAACE,MAAmB;AAC1B,UAAIilB,EAAW,OAAO,WAAW,KAAK;AACrC;AAKD,UADC/Y,EAAK,UAAU,KAAK,cAAc,KAAK,YAAY,IAAIA,EAAK,KAAK,GAAG,GACpD;AAChB,aAAK,cAAc;AACnB,cAAMiZ,IAAcjZ,EAAK,UAAU,GAC7BkZ,IAAa,KAAK,cAAcD,CAAW,GAC3CT,IAAoB;AAAA,UACzB,MAAMxY,EAAK;AAAA,UACX,SAASiZ;AAAA,UACT,SAASjF,OAAUkF;AAAA,QAAA,GAEdC,IAAW,KAAK,YAAY,IAAInZ,EAAK,KAAK,GAAG;AACnD,QAAImZ,KACHA,EAAS,OAAOX,EAAO,MACvBW,EAAS,UAAU,KAAK,IAAIA,EAAS,SAASX,EAAO,OAAO,GAC5DW,EAAS,UAAU,KAAK,IAAIA,EAAS,SAASX,EAAO,OAAO,MAE5D,KAAK,MAAM,KAAKA,CAAM,GACtB,KAAK,YAAY,IAAIA,EAAO,KAAK,KAAKA,CAAM,IAE7C,KAAK,UAAA;AACL;AAAA,MACD;AAEA,WAAK,eAAe,GACpB,KAAK,cAAcxY,EAAK,MAAMlM,GAAOkM,EAAK,UAAU,CAAC;AAAA,IACtD,CAAC,EACA,QAAQ,MAAM;AACd,WAAK,SAAS,OAAOA,EAAK,KAAK,GAAG,GAClC,KAAK,KAAA,GACL,KAAK,gBAAA;AAAA,IACN,CAAC;AAAA,EACH;AAAA,EAEQ,cAAcoZ,GAAyB;AAC9C,UAAMC,IAAM,KAAK,IAAI,GAAGD,IAAU,CAAC,GAC7BP,IAAQ,KAAK;AAAA,MAClB,KAAK;AAAA,MACL,KAAK,mBAAmB,KAAKQ;AAAA,IAAA,GAExBC,IAAS,OAAO,KAAK,OAAA,IAAW;AACtC,WAAO,KAAK,MAAMT,IAAQS,CAAM;AAAA,EACjC;AAAA,EAEQ,iBAAuB;AAC9B,IAAI,KAAK,YAAY,SACrB,OAAO,aAAa,KAAK,OAAO,GAChC,KAAK,UAAU;AAAA,EAChB;AAAA,EAEQ,kBAAwB;AAC/B,SAAK,gBAAgB,KAAK,aAAa;AAAA,EACxC;AACD;ACrSA,MAAMC,KAAoC,MACpCC,KAAoB,KACpBC,KAAoB,KAOpBC,KAAqD;AAAA,EAC1D,EAAE,MAAM,GAAG,MAAM,IAAA;AAAA,EACjB,EAAE,MAAM,GAAG,MAAM,IAAA;AAAA,EACjB,EAAE,MAAM,GAAG,MAAM,IAAA;AAAA,EACjB,EAAE,MAAM,GAAG,MAAM,IAAA;AAAA,EACjB,EAAE,MAAM,GAAG,MAAM,IAAA;AAAA,EACjB,EAAE,MAAM,GAAG,MAAM,IAAA;AAAA,EACjB,EAAE,MAAM,GAAG,MAAM,IAAA;AAAA,EACjB,EAAE,MAAM,GAAG,MAAM,KAAA;AAAA,EACjB,EAAE,MAAM,GAAG,MAAM,GAAA;AAAA,EACjB,EAAE,MAAM,IAAI,MAAM,KAAA;AAAA,EAClB,EAAE,MAAM,IAAI,MAAM,GAAA;AAAA,EAClB,EAAE,MAAM,IAAI,MAAM,GAAA;AACnB;AA+BA,MAAM5mB,GAAY;AAAA,EAAlB;AACS,IAAAd,EAAA,uBAAgB;AAChB,IAAAA,EAAA,wBAAiB;AACjB,IAAAA,EAAA,mBAA0B;AAAA,MACjC,MAAM;AAAA,MACN,SAAS;AAAA,MACT,SAAS;AAAA,MACT,aAAa;AAAA,IAAA;AAAA;AAAA,EAGd,YAAYC,GAAeC,GAAsB;AAChD,SAAK,gBAAgB,KAAK,IAAI,GAAGD,CAAK,GACtC,KAAK,iBAAiB,KAAK,IAAI,GAAGC,CAAM;AAAA,EACzC;AAAA,EAEA,cAA6B;AAC5B,WAAO,EAAE,OAAO,KAAK,eAAe,QAAQ,KAAK,eAAA;AAAA,EAClD;AAAA,EAEA,aAAaC,GAAmC;AAC/C,IAAI,OAAOA,EAAK,QAAS,aACxB,KAAK,UAAU,OAAO,KAAK,IAAI,MAAQA,EAAK,IAAI,IAE7C,OAAOA,EAAK,WAAY,aAC3B,KAAK,UAAU,UAAUA,EAAK,UAE3B,OAAOA,EAAK,WAAY,aAC3B,KAAK,UAAU,UAAUA,EAAK,UAE3B,OAAOA,EAAK,eAAgB,YAAY,OAAO,SAASA,EAAK,WAAW,MAC3E,KAAK,UAAU,cAAcA,EAAK;AAAA,EAEpC;AAAA,EAEA,eAA6B;AAC5B,WAAO,EAAE,GAAG,KAAK,UAAA;AAAA,EAClB;AAAA,EAEA,YAAwB;AACvB,UAAMmC,IAAO,KAAK,IAAI,MAAM,KAAK,UAAU,IAAI;AAC/C,WAAO;AAAA,MACN,KAAK,UAAU,UAAU,KAAK,iBAAiB,IAAIA;AAAA,MACnD,KAAK,UAAU,UAAU,KAAK,kBAAkB,IAAIA;AAAA,IAAA;AAAA,EAEtD;AAAA,EAEA,UAAUuM,GAAiBC,GAAuB;AACjD,UAAMxM,IAAO,KAAK,IAAI,MAAM,KAAK,UAAU,IAAI;AAC/C,SAAK,UAAU,UAAUuM,IAAU,KAAK,iBAAiB,IAAIvM,IAC7D,KAAK,UAAU,UAAUwM,IAAU,KAAK,kBAAkB,IAAIxM;AAAA,EAC/D;AAAA,EAEA,cAAc+W,GAAiBC,GAA6B;AAC3D,UAAMvC,IAAQ,KAAK,WACbzU,IAAO,KAAK,IAAI,MAAMyU,EAAM,IAAI,GAChC,CAAClI,GAASC,CAAO,IAAI,KAAK,UAAA,GAC1BrG,KAAM4Q,IAAU,KAAK,gBAAgB,OAAO/W,GAC5CoG,KAAM4Q,IAAU,KAAK,iBAAiB,OAAOhX,GAC7CqlB,IAAMC,GAAU7Q,EAAM,WAAW,GACjC8Q,IAAM,KAAK,IAAIF,CAAG,GAClBG,IAAM,KAAK,IAAIH,CAAG;AACxB,WAAO,CAAC9Y,IAAUpG,IAAKof,IAAMnf,IAAKof,GAAKhZ,IAAUrG,IAAKqf,IAAMpf,IAAKmf,CAAG;AAAA,EACrE;AAAA,EAEA,cAAc9K,GAAgBC,GAA4B;AACzD,UAAMjG,IAAQ,KAAK,WACbzU,IAAO,KAAK,IAAI,MAAMyU,EAAM,IAAI,GAChC,CAAClI,GAASC,CAAO,IAAI,KAAK,UAAA,GAC1BrG,IAAKsU,IAASlO,GACdnG,IAAKsU,IAASlO,GACd6Y,IAAMC,GAAU7Q,EAAM,WAAW,GACjC8Q,IAAM,KAAK,IAAIF,CAAG,GAClBG,IAAM,KAAK,IAAIH,CAAG,GAClBI,IAAKtf,IAAKof,IAAMnf,IAAKof,GACrBE,IAAK,CAACvf,IAAKqf,IAAMpf,IAAKmf;AAC5B,WAAO;AAAA,MACN,KAAK,gBAAgB,MAAME,IAAKzlB;AAAA,MAChC,KAAK,iBAAiB,MAAM0lB,IAAK1lB;AAAA,IAAA;AAAA,EAEnC;AAAA,EAEA,iBAAmE;AAClE,UAAM6S,IAAI,KAAK,eACTC,IAAI,KAAK;AACf,WAAO;AAAA,MACN,KAAK,cAAc,GAAG,CAAC;AAAA,MACvB,KAAK,cAAcD,GAAG,CAAC;AAAA,MACvB,KAAK,cAAcA,GAAGC,CAAC;AAAA,MACvB,KAAK,cAAc,GAAGA,CAAC;AAAA,IAAA;AAAA,EAEzB;AAAA,EAEA,YAA0B;AACzB,UAAM9S,IAAO,KAAK,IAAI,MAAM,KAAK,UAAU,IAAI,GACzC,CAACuM,GAASC,CAAO,IAAI,KAAK,UAAA,GAC1B6Y,IAAMC,GAAU,KAAK,UAAU,WAAW,GAC1CC,IAAM,KAAK,IAAIF,CAAG,GAClBG,IAAM,KAAK,IAAIH,CAAG,GAElBrD,IAAM,IAAIhiB,IAAOulB,IAAO,KAAK,eAC7BrD,IAAM,IAAIliB,IAAOwlB,IAAO,KAAK,eAC7BvD,IAAM,IAAIjiB,IAAOwlB,IAAO,KAAK,gBAC7BrD,IAAM,KAAKniB,IAAOulB,IAAO,KAAK,gBAC9BrnB,IAAK,EAAE8jB,IAAKzV,IAAU2V,IAAK1V,IAC3BrO,IAAK,EAAE8jB,IAAK1V,IAAU4V,IAAK3V;AAEjC,WAAO,IAAI,aAAa,CAACwV,GAAIC,GAAI,GAAGC,GAAIC,GAAI,GAAGjkB,GAAIC,GAAI,CAAC,CAAC;AAAA,EAC1D;AACD;AAEA,SAASmnB,GAAUK,GAAqB;AACvC,SAAQA,IAAM,KAAK,KAAM;AAC1B;AAEA,SAASjG,KAAgB;AACxB,SAAI,OAAO,cAAgB,OAAe,OAAO,YAAY,OAAQ,aAC7D,YAAY,IAAA,IAEb,KAAK,IAAA;AACb;AAEA,SAASviB,GACRX,GACAU,GACA0oB,GACuB;AACvB,QAAMvoB,IAAWb,EAAG,mBAAmBU,GAAS0oB,CAAI;AACpD,MAAI,CAACvoB;AACJ,UAAM,IAAI,MAAM,mCAAmCuoB,CAAI,EAAE;AAE1D,SAAOvoB;AACR;AAEA,SAASwoB,GACRrgB,GACAC,GACU;AACV,SAAI,CAACD,KAAK,CAACC,IAAUD,MAAMC,IAE1BD,EAAE,WAAWC,EAAE,UACfD,EAAE,eAAeC,EAAE,cACnBD,EAAE,eAAeC,EAAE;AAErB;AAEA,SAASqgB,GAAoBC,GAAkD;AAC9E,SAAOA,EAAM,IAAI,CAAAC,OAAS,EAAE,MAAMA,EAAK,MAAM,MAAMA,EAAK,KAAA,EAAO;AAChE;AAEA,SAASC,GAAwBC,GAAsE;AACtG,MAAI,CAACA,EAAiB,QAAOJ,GAAoBV,EAAwB;AAEzE,QAAM/N,wBAAa,IAAA;AACnB,aAAW,CAAC8O,GAASC,CAAO,KAAK,OAAO,QAAQF,CAAe,GAAG;AACjE,UAAMlmB,IAAO,OAAOmmB,CAAO,GACrBE,IAAO,OAAOD,CAAO;AAC3B,IAAI,CAAC,OAAO,SAASpmB,CAAI,KAAK,CAAC,OAAO,SAASqmB,CAAI,KAAKA,KAAQ,KAChEhP,EAAO,IAAIrX,GAAMqmB,CAAI;AAAA,EACtB;AAEA,SAAIhP,EAAO,SAAS,IACZyO,GAAoBV,EAAwB,IAG7C,MAAM,KAAK/N,EAAO,QAAA,CAAS,EAChC,KAAK,CAAC7R,GAAGC,MAAMD,EAAE,CAAC,IAAIC,EAAE,CAAC,CAAC,EAC1B,IAAI,CAAC,CAACzF,GAAMqmB,CAAI,OAAO,EAAE,MAAArmB,GAAM,MAAAqmB,EAAA,EAAO;AACzC;AAEA,SAASC,GAAuB9gB,GAA6BC,GAAsC;AAClG,MAAID,MAAMC,EAAG,QAAO;AACpB,MAAID,EAAE,WAAWC,EAAE,OAAQ,QAAO;AAClC,WAASlC,IAAI,GAAGA,IAAIiC,EAAE,QAAQjC,KAAK;AAClC,QAAIiC,EAAEjC,CAAC,EAAE,SAASkC,EAAElC,CAAC,EAAE,QAAQiC,EAAEjC,CAAC,EAAE,SAASkC,EAAElC,CAAC,EAAE;AACjD,aAAO;AAGT,SAAO;AACR;AAEA,SAASgjB,GAA4B9S,GAAwBsS,GAAyC;AACrG,MAAI,CAAC,OAAO,SAAStS,CAAc,EAAG,QAAOsS,EAAM,CAAC,GAAG,QAAQb;AAC/D,MAAIa,EAAM,WAAW,EAAG,QAAOb;AAE/B,MADIa,EAAM,WAAW,KACjBtS,KAAkBsS,EAAM,CAAC,EAAE,KAAM,QAAOA,EAAM,CAAC,EAAE;AAErD,WAASxiB,IAAI,GAAGA,IAAIwiB,EAAM,QAAQxiB,KAAK,GAAG;AACzC,UAAM7B,IAAOqkB,EAAMxiB,IAAI,CAAC,GAClB1F,IAAOkoB,EAAMxiB,CAAC;AACpB,QAAIkQ,IAAiB5V,EAAK,KAAM;AAChC,UAAM2oB,IAAO,KAAK,IAAI,MAAM3oB,EAAK,OAAO6D,EAAK,IAAI,GAC3CM,IAAIpB,IAAO6S,IAAiB/R,EAAK,QAAQ8kB,GAAM,GAAG,CAAC;AACzD,WAAO9kB,EAAK,QAAQ7D,EAAK,OAAO6D,EAAK,QAAQM;AAAA,EAC9C;AAEA,QAAMV,IAAOykB,EAAMA,EAAM,SAAS,CAAC,GAC7BrkB,IAAOqkB,EAAMA,EAAM,SAAS,CAAC,GAC7BS,IAAO,KAAK,IAAI,MAAMllB,EAAK,OAAOI,EAAK,IAAI,GAC3C+kB,KAASnlB,EAAK,OAAOI,EAAK,QAAQ8kB;AACxC,SAAOllB,EAAK,QAAQmS,IAAiBnS,EAAK,QAAQmlB;AACnD;AAEO,MAAMC,GAAgB;AAAA,EAoD5B,YACCnpB,GACAb,GACA6B,IAAkC,CAAA,GACjC;AAvDe,IAAAb,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA,gBAAS,IAAIc,GAAA;AACb,IAAAd,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA;AACT,IAAAA,EAAA;AACA,IAAAA,EAAA;AACS,IAAAA,EAAA;AAET,IAAAA,EAAA;AACA,IAAAA,EAAA,mBAAY;AACZ,IAAAA,EAAA,qBAAc;AACd,IAAAA,EAAA,eAAuB;AACvB,IAAAA,EAAA,qBAAc;AACd,IAAAA,EAAA,kBAAW;AACX,IAAAA,EAAA,yBAA6C;AAC7C,IAAAA,EAAA,4BAAoC;AACpC,IAAAA,EAAA,mBAA2B;AAC3B,IAAAA,EAAA,sBAAe;AACf,IAAAA,EAAA,sBAAe;AACf,IAAAA,EAAA,2BAAoB;AACpB,IAAAA,EAAA,wBAAiB;AACjB,IAAAA,EAAA,4CAAqC;AACrC,IAAAA,EAAA;AACA,IAAAA,EAAA,iBAAU;AACV,IAAAA,EAAA,iBAAU;AACV,IAAAA,EAAA,iBAAU;AACV,IAAAA,EAAA,qBAAc;AACd,IAAAA,EAAA,oBAAa;AACb,IAAAA,EAAA,yBAAkB;AAClB,IAAAA,EAAA,2BAAoB;AACpB,IAAAA,EAAA,0BAAmB;AACnB,IAAAA,EAAA,wBAAkCooB,GAAoBV,EAAwB;AAC9E,IAAA1nB,EAAA,uBAAqC;AACrC,IAAAA,EAAA,0BAAsC;AACtC,IAAAA,EAAA,mCAAY,IAAA;AAEH,IAAAA,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA;AAOhB,SAAK,SAASH,GACd,KAAK,SAASb,GACd,KAAK,oBAAoB6B,EAAQ,mBACjC,KAAK,UAAUA,EAAQ,SACvB,KAAK,cAAcA,EAAQ,aAC3B,KAAK,gBAAgBA,EAAQ,eAC7B,KAAK,oBAAoBA,EAAQ,mBACjC,KAAK,YAAYA,EAAQ,aAAa,IACtC,KAAK,gBAAgB,KAAK,IAAI,IAAI,KAAK,MAAMA,EAAQ,iBAAiB,GAAG,CAAC,GAC1E,KAAK,iBAAiBA,EAAQ,kBAAkB,IAChD,KAAK,qCACJ,OAAOA,EAAQ,sCAAuC,YACtD,OAAO,SAASA,EAAQ,kCAAkC,IACvD,KAAK,IAAI,GAAGA,EAAQ,kCAAkC,IACtD0mB,IACJ,KAAK,iBAAiBgB,GAAwB1nB,EAAQ,eAAe;AAErE,UAAM/B,IAAKe,EAAO,WAAW,UAAU;AAAA,MACtC,OAAO;AAAA,MACP,WAAW;AAAA,MACX,OAAO;AAAA,MACP,SAAS;AAAA,MACT,iBAAiB;AAAA,IAAA,CACjB;AACD,QAAI,CAACf;AACJ,YAAM,IAAI,MAAM,sBAAsB;AAEvC,SAAK,KAAKA,GAEV,KAAK,cAAc,KAAK,gBAAA,GACxB,KAAK,eAAe,KAAK,iBAAA,GACzB,KAAK,gBAAgB,IAAIunB,GAAc;AAAA,MACtC,WAAW,KAAK;AAAA,MAChB,gBAAgBxlB,EAAQ,eAAe,kBAAkB;AAAA,MACzD,YAAYA,EAAQ,eAAe,cAAc;AAAA,MACjD,kBAAkBA,EAAQ,eAAe,oBAAoB;AAAA,MAC7D,iBAAiBA,EAAQ,eAAe,mBAAmB;AAAA,MAC3D,YAAY,CAACW,GAAMI,MAAW,KAAK,iBAAiBJ,GAAMI,CAAM;AAAA,MAChE,aAAa,CAACJ,GAAMM,GAAOmnB,MAAiB;AAC3C,aAAK,cAAc,EAAE,MAAAznB,GAAM,OAAAM,GAAO,cAAAmnB,GAAc,GAChD,QAAQ,KAAK,oBAAoBznB,EAAK,KAAKM,CAAK;AAAA,MACjD;AAAA,IAAA,CACA,GAED,KAAK,iBAAiB,IAAI,eAAe,MAAM,KAAK,QAAQ,GAC5D,KAAK,eAAe,QAAQjC,CAAM,GAElC,KAAK,mBAAmB,CAACoY,MAAwB,KAAK,cAAcA,CAAK,GACzE,KAAK,mBAAmB,CAACA,MAAwB,KAAK,cAAcA,CAAK,GACzE,KAAK,iBAAiB,CAACA,MAAwB,KAAK,YAAYA,CAAK,GACrE,KAAK,aAAa,CAACA,MAAsB,KAAK,QAAQA,CAAK,GAC3D,KAAK,mBAAmB,CAACA,MAAsB,KAAK,cAAcA,CAAK,GACvE,KAAK,mBAAmB,CAACA,MAAsB,KAAK,cAAcA,CAAK,GACvE,KAAK,mBAAmB,CAACA,MAAiB,KAAK,mBAAmBA,CAAK,GACvE,KAAK,uBAAuB,CAACA,MAC5B,KAAK,uBAAuBA,CAAK,GAElCpY,EAAO,iBAAiB,eAAe,KAAK,gBAAgB,GAC5DA,EAAO,iBAAiB,eAAe,KAAK,gBAAgB,GAC5DA,EAAO,iBAAiB,aAAa,KAAK,cAAc,GACxDA,EAAO,iBAAiB,iBAAiB,KAAK,cAAc,GAC5DA,EAAO,iBAAiB,SAAS,KAAK,YAAY,EAAE,SAAS,IAAO,GACpEA,EAAO,iBAAiB,YAAY,KAAK,gBAAgB,GACzDA,EAAO,iBAAiB,eAAe,KAAK,gBAAgB,GAC5DA,EAAO,iBAAiB,oBAAoB,KAAK,gBAAgB,GACjEA,EAAO,iBAAiB,wBAAwB,KAAK,oBAAoB,GAEzE,KAAK,WAAA,GACL,KAAK,OAAA;AAAA,EACN;AAAA,EAEA,aAAagL,GAAqB;AACjC,SAAK,YAAY,OAAOA,KAAS,EAAE,GACnC,KAAK,cAAc,aAAa,KAAK,SAAS;AAAA,EAC/C;AAAA,EAEA,aAAa1K,GAAmC;AAC/C,UAAMsQ,IAAoC,EAAE,GAAGtQ,EAAA;AAC/C,IAAI,OAAOsQ,EAAW,QAAS,aAC9BA,EAAW,OAAOvN,GAAMuN,EAAW,MAAM,KAAK,SAAS,KAAK,OAAO,IAEpE,KAAK,OAAO,aAAaA,CAAU,GACnC,KAAK,eAAA,GACL,KAAK,cAAA,GACL,KAAK,cAAA;AAAA,EACN;AAAA,EAEA,eAA6B;AAC5B,WAAO,KAAK,OAAO,aAAA;AAAA,EACpB;AAAA,EAEA,gBAAgBjF,GAA6C;AAC5D,QAAI,CAACA,KAAUA,EAAO,WAAW,GAAG;AACnC,WAAK,mBAAmB;AACxB;AAAA,IACD;AAEA,QADA,KAAK,mBAAmB,IAAI,WAAWA,CAAM,GACzC,KAAK,eAAe,KAAK,GAAG,gBAAiB;AACjD,UAAM1M,IAAK,KAAK,IACVoqB,IAAc,KAAK,IAAI,GAAG,KAAK,MAAM,KAAK,iBAAiB,SAAS,CAAC,CAAC;AAC5E,SAAK,mBAAmBA,GACxBpqB,EAAG,YAAYA,EAAG,YAAY,KAAK,aAAa,cAAc,GAC9DA,EAAG;AAAA,MACFA,EAAG;AAAA,MACH;AAAA,MACAA,EAAG;AAAA,MACHoqB;AAAA,MACA;AAAA,MACA;AAAA,MACApqB,EAAG;AAAA,MACHA,EAAG;AAAA,MACH,KAAK;AAAA,IAAA,GAENA,EAAG,YAAYA,EAAG,YAAY,IAAI,GAClC,KAAK,cAAA;AAAA,EACN;AAAA,EAEA,aAAagF,GAA+C;AAC3D,QAAI,CAACA,KAAU,CAACA,EAAO,SAAS,CAACA,EAAO,aAAa,CAACA,EAAO,gBAAgB;AAC5E,WAAK,gBAAgB,MACrB,KAAK,aAAa,GAClB,KAAK,kBAAkB,IACvB,KAAK,cAAA;AACL;AAAA,IACD;AAEA,UAAMqe,IAAY,KAAK;AAAA,MACtB;AAAA,MACA,KAAK;AAAA,QACJre,EAAO;AAAA,QACP,KAAK,MAAMA,EAAO,UAAU,SAAS,CAAC;AAAA,QACtCA,EAAO,eAAe;AAAA,MAAA;AAAA,IACvB,GAEKub,IAAgBvb,EAAO,UAAU,SAAS,GAAGqe,IAAY,CAAC,GAC1DgH,IAAqBrlB,EAAO,eAAe,SAAS,GAAGqe,CAAS,GAChEiH,IAAiBtlB,EAAO,uBAAuB,aAC/CulB,IAAkBD,IACrB,KAAK,oBAAoBtlB,EAAO,aAA4Bqe,CAAS,IACrE,MACGne,IAAO,KAAK;AAClB,QAAIslB,IACH,KAAK,qBACL,CAACtlB,KACDA,EAAK,UAAUme,KACf,CAACgG,GAAgBnkB,EAAK,WAAWqb,CAAa,KAC9C,CAAC8I,GAAgBnkB,EAAK,gBAAgBmlB,CAAkB,GACrDI,IACH,KAAK,qBACJH,MACC,CAACplB,GAAM,eACP,CAACmkB,GAAgBnkB,EAAK,aAAaqlB,CAAe,MACnD,CAACD,KAAkB,CAAC,CAACplB,GAAM;AAQ7B,QANA,KAAK,gBAAgB;AAAA,MACpB,OAAOme;AAAA,MACP,WAAW9C;AAAA,MACX,gBAAgB8J;AAAA,MAChB,aAAaC,IAAiBC,KAAmB,SAAY;AAAA,IAAA,GAE1D,KAAK,eAAe,KAAK,GAAG,gBAAiB;AAEjD,UAAMvqB,IAAK,KAAK;AAChB,IAAIwqB,MACHxqB,EAAG,WAAWA,EAAG,cAAc,KAAK,aAAa,SAAS,GAC1DA,EAAG,WAAWA,EAAG,cAAc,KAAK,cAAc,WAAWA,EAAG,WAAW,GAE3EA,EAAG,WAAWA,EAAG,cAAc,KAAK,aAAa,UAAU,GAC3DA,EAAG;AAAA,MACFA,EAAG;AAAA,MACH,KAAK,cAAc;AAAA,MACnBA,EAAG;AAAA,IAAA,GAEJA,EAAG,WAAWA,EAAG,cAAc,IAAI,IAGhCsqB,KAAkBG,MACrBzqB,EAAG,WAAWA,EAAG,sBAAsB,KAAK,aAAa,WAAW,GACpEA,EAAG;AAAA,MACFA,EAAG;AAAA,MACHuqB,KAAmB,IAAI,YAAY,CAAC;AAAA,MACpCvqB,EAAG;AAAA,IAAA,GAEJA,EAAG,WAAWA,EAAG,sBAAsB,IAAI,IAG5C,KAAK,kBAAkBsqB,GACvB,KAAK,aAAaA,IACdC,GAAiB,UAAU,IAC5B,KAAK,cAAc,QAClBC,KAAmBC,OACtB,KAAK,oBAAoB,KAE1B,KAAK,cAAA;AAAA,EACN;AAAA,EAEQ,oBACP5G,GACA6G,GACc;AACd,QAAIA,KAAgB,KAAK7G,EAAY,WAAW;AAC/C,aAAO,IAAI,YAAY,CAAC;AAGzB,QAAI8G,IAAa9G,EAAY;AAC7B,aAAS9c,IAAI,GAAGA,IAAI8c,EAAY,QAAQ9c,KAAK;AAC5C,MAAI8c,EAAY9c,CAAC,IAAI2jB,MACrBC,KAAc;AAEf,QAAIA,MAAe9G,EAAY;AAC9B,aAAOA;AAER,QAAI8G,KAAc;AACjB,aAAO,IAAI,YAAY,CAAC;AAGzB,UAAMrE,IAAW,IAAI,YAAYqE,CAAU;AAC3C,QAAI/S,IAAS;AACb,aAAS7Q,IAAI,GAAGA,IAAI8c,EAAY,QAAQ9c,KAAK,GAAG;AAC/C,YAAMwf,IAAM1C,EAAY9c,CAAC;AACzB,MAAIwf,KAAOmE,MACXpE,EAAS1O,CAAM,IAAI2O,GACnB3O,KAAU;AAAA,IACX;AACA,WAAO0O;AAAA,EACR;AAAA,EAEA,mBAAmBsE,GAAuB;AACzC,UAAMvpB,IAAO,EAAQupB;AACrB,IAAI,KAAK,sBAAsBvpB,MAC/B,KAAK,oBAAoBA,GACrBA,UAAW,WAAA;AAAA,EAChB;AAAA,EAEA,mBAAmBqoB,GAA2D;AAC7E,UAAMmB,IAAYpB,GAAwBC,CAAe;AACzD,IAAII,GAAuB,KAAK,gBAAgBe,CAAS,MACzD,KAAK,iBAAiBA,GACtB,KAAK,cAAA;AAAA,EACN;AAAA,EAEA,aAAmB;AAClB,QAAI,KAAK,cAAc,QAAQ,KAAK,OAAO,kBAAkB,KAAK,SAAS;AAC1E,UAAI;AACH,aAAK,OAAO,sBAAsB,KAAK,SAAS;AAAA,MACjD,QAAQ;AAAA,MAER;AAED,SAAK,WAAW,IAChB,KAAK,kBAAkB,QACvB,KAAK,qBAAqB,MAC1B,KAAK,YAAY,MACjB,KAAK,OAAO,UAAU,OAAO,UAAU;AAAA,EACxC;AAAA,EAEQ,mBAAmBjN,GAAiBC,GAAyB;AACpE,UAAM5a,IAAO,KAAK,OAAO,sBAAA,GACnB0B,IAAIiZ,IAAU3a,EAAK,OAAOA,EAAK,QAAQ,KACvC2B,IAAIiZ,IAAU5a,EAAK,MAAMA,EAAK,SAAS;AAC7C,WAAO,KAAK,MAAM2B,GAAGD,CAAC;AAAA,EACvB;AAAA,EAEA,cAAciZ,GAAiBC,GAAmC;AACjE,UAAM5a,IAAO,KAAK,OAAO,sBAAA,GACnBzB,IAAKoc,IAAU3a,EAAK,MACpBxB,IAAKoc,IAAU5a,EAAK;AAC1B,WAAO,KAAK,OAAO,cAAczB,GAAIC,CAAE;AAAA,EACxC;AAAA,EAEA,cAAcwc,GAAgBC,GAAkC;AAC/D,WAAO,KAAK,OAAO,cAAcD,GAAQC,CAAM;AAAA,EAChD;AAAA,EAEA,cAAcD,GAAgBC,GAAsB;AACnD,IAAI,CAAC,OAAO,SAASD,CAAM,KAAK,CAAC,OAAO,SAASC,CAAM,MACvD,KAAK,OAAO,UAAUD,GAAQC,CAAM,GACpC,KAAK,eAAA,GACL,KAAK,cAAA,GACL,KAAK,cAAA;AAAA,EACN;AAAA,EAEA,iBAAmE;AAClE,WAAO,KAAK,OAAO,eAAA;AAAA,EACpB;AAAA,EAEA,gBAAsB;AACrB,UAAMjG,IAAQ,KAAK,OAAO,aAAA;AAC1B,IAAI,KAAK,IAAIA,EAAM,WAAW,IAAI,SAClC,KAAK,OAAO,aAAa,EAAE,aAAa,GAAG,GAC3C,KAAK,eAAA,GACL,KAAK,cAAA,GACL,KAAK,cAAA;AAAA,EACN;AAAA,EAEA,qBAA6B;AAC5B,UAAMzU,IAAO,KAAK,IAAI,MAAM,KAAK,OAAO,aAAA,EAAe,IAAI,GACrDyT,IAAiB,KAAK,OAAO,cAAc,KAAK,KAAKzT,CAAI,GACzDqmB,IAAOE,GAA4B9S,GAAgB,KAAK,cAAc;AAC5E,WAAO7S,GAAMylB,GAAMnB,IAAmBC,EAAiB;AAAA,EACxD;AAAA,EAEA,aAAmB;AAClB,UAAM1lB,IAAO,KAAK,OAAO,sBAAA,GACnB6nB,IAAK,KAAK,IAAI,GAAG7nB,EAAK,SAAS,CAAC,GAChC8nB,IAAK,KAAK,IAAI,GAAG9nB,EAAK,UAAU,CAAC,GAEjCO,IAAO,KAAK,IAAIsnB,IAAK,KAAK,OAAO,OAAOC,IAAK,KAAK,OAAO,MAAM,GAC/DtnB,IAAW,OAAO,SAASD,CAAI,KAAKA,IAAO,IAAIA,IAAO;AAE5D,SAAK,UAAUC,GACf,KAAK,UAAU,KAAK,IAAI,KAAK,UAAU,KAAK,IAAI,GAChD,KAAK,UAAU,KAAK,IAAI,GAAG,KAAK,UAAU,CAAC,GACvC,KAAK,UAAU,KAAK,YACvB,KAAK,UAAU,KAAK;AAGrB,UAAMunB,IAAgBF,IAAKrnB,GACrBwnB,IAAgBF,IAAKtnB;AAE3B,SAAK,OAAO,aAAa;AAAA,MACxB,MAAMW,GAAMX,GAAU,KAAK,SAAS,KAAK,OAAO;AAAA,MAChD,UAAU,KAAK,OAAO,QAAQunB,KAAiB;AAAA,MAC/C,UAAU,KAAK,OAAO,SAASC,KAAiB;AAAA,MAChD,aAAa;AAAA,IAAA,CACb,GAED,KAAK,eAAA,GACL,KAAK,cAAA,GACL,KAAK,cAAA;AAAA,EACN;AAAA,EAEA,OAAOC,GAAgB3Q,GAAiBC,GAAuB;AAC9D,UAAMvC,IAAQ,KAAK,OAAO,aAAA,GACpBkT,IAAW/mB,GAAM6T,EAAM,OAAOiT,GAAQ,KAAK,SAAS,KAAK,OAAO;AACtE,QAAIC,MAAalT,EAAM,KAAM;AAE7B,UAAM,CAACgG,GAAQC,CAAM,IAAI,KAAK,OAAO,cAAc3D,GAASC,CAAO;AAEnE,SAAK,OAAO,aAAa,EAAE,MAAM2Q,GAAU;AAE3C,UAAMC,IAAK,KAAK,OAAO,YAAA,GACjBzhB,IAAK4Q,IAAU6Q,EAAG,QAAQ,KAC1BxhB,IAAK4Q,IAAU4Q,EAAG,SAAS,KAC3BvC,IAAMC,GAAU,KAAK,OAAO,aAAA,EAAe,WAAW,GACtDC,IAAM,KAAK,IAAIF,CAAG,GAClBG,IAAM,KAAK,IAAIH,CAAG,GAClBwC,IAAW1hB,IAAKwhB,IAAYpC,IAAOnf,IAAKuhB,IAAYnC,GACpDsC,IAAW3hB,IAAKwhB,IAAYnC,IAAOpf,IAAKuhB,IAAYpC;AAC1D,SAAK,OAAO,UAAU9K,IAASoN,GAASnN,IAASoN,CAAO,GAExD,KAAK,eAAA,GACL,KAAK,cAAA,GACL,KAAK,cAAA;AAAA,EACN;AAAA,EAEA,iBAAuB;AACtB,UAAMrlB,IAAS,KAAK,cAAA,GACdkY,IAAW,KAAK,IAAI,MAAMlY,EAAO,CAAC,IAAIA,EAAO,CAAC,CAAC,GAC/CmY,IAAW,KAAK,IAAI,MAAMnY,EAAO,CAAC,IAAIA,EAAO,CAAC,CAAC,GAC/CslB,IAAUpN,IAAW,KACrBqN,IAAUpN,IAAW,KAErB,CAACrO,GAASC,CAAO,IAAI,KAAK,OAAO,UAAA,GACjCyb,IAAQtN,IAAW,KACnBuN,IAAQtN,IAAW,KAEnBuN,IAAaF,IAAQF,GACrBK,IAAa,KAAK,OAAO,QAAQH,IAAQF,GACzCM,IAAaH,IAAQF,GACrBM,IAAa,KAAK,OAAO,SAASJ,IAAQF,GAE1CO,IACLJ,KAAcC,IACXxnB,GAAM2L,GAAS4b,GAAYC,CAAU,IACrC,KAAK,OAAO,QAAQ,KAClBI,IACLH,KAAcC,IACX1nB,GAAM4L,GAAS6b,GAAYC,CAAU,IACrC,KAAK,OAAO,SAAS;AAEzB,SAAK,OAAO,UAAUC,GAAaC,CAAW;AAAA,EAC/C;AAAA,EAEA,gBAAsB;AACrB,SAAK,oBAAoB,KAAK,OAAO,aAAA,CAAc;AAAA,EACpD;AAAA,EAEA,aAAqB;AACpB,UAAMxoB,IAAO,KAAK,IAAI,MAAM,KAAK,OAAO,aAAA,EAAe,IAAI,GACrDyoB,IAAU,KAAK,OAAO,cAAc,KAAK,KAAKzoB,CAAI;AACxD,WAAOY,GAAM,KAAK,MAAM6nB,CAAO,GAAG,GAAG,KAAK,OAAO,WAAW;AAAA,EAC7D;AAAA,EAEA,gBAAwB;AACvB,UAAM7O,IAAU,KAAK,OAAO,eAAA;AAC5B,QAAI1X,IAAO,OACPC,IAAO,OACPC,IAAO,QACPC,IAAO;AACX,eAAW,CAAClB,GAAGC,CAAC,KAAKwY;AACpB,MAAIzY,IAAIe,MAAMA,IAAOf,IACjBA,IAAIiB,MAAMA,IAAOjB,IACjBC,IAAIe,MAAMA,IAAOf,IACjBA,IAAIiB,MAAMA,IAAOjB;AAEtB,WAAO,CAACc,GAAMC,GAAMC,GAAMC,CAAI;AAAA,EAC/B;AAAA,EAEA,iBAAiBmD,GAAWC,GAAoB;AAC/C,WAAO,EAAED,EAAE,CAAC,KAAKC,EAAE,CAAC,KAAKD,EAAE,CAAC,KAAKC,EAAE,CAAC,KAAKD,EAAE,CAAC,KAAKC,EAAE,CAAC,KAAKD,EAAE,CAAC,KAAKC,EAAE,CAAC;AAAA,EACrE;AAAA,EAEA,kBAAmC;AAClC,UAAMuS,IAAO,KAAK,WAAA;AAClB,SAAK,cAAcA;AAEnB,UAAM0Q,IAAa,KAAK,cAAA,GAElB3N,IAAa,KAAK,IAAI,GAAG,KAAK,OAAO,cAAc/C,CAAI,GACvDgD,IAAa,KAAK,KAAK,KAAK,OAAO,QAAQD,CAAU,GACrDE,IAAc,KAAK,KAAK,KAAK,OAAO,SAASF,CAAU,GAEvDG,IAAS,KAAK,IAAI,GAAG,KAAK,KAAKF,IAAa,KAAK,OAAO,QAAQ,CAAC,GACjEG,IAAS,KAAK,IAAI,GAAG,KAAK,KAAKF,IAAc,KAAK,OAAO,QAAQ,CAAC,GAElE0N,IAAWD,EAAW,CAAC,GACvBE,IAAWF,EAAW,CAAC,GACvBG,IAAWH,EAAW,CAAC,GACvBI,IAAWJ,EAAW,CAAC,GAEvBK,IAAWnoB;AAAAA,MAChB,KAAK,MAAM+nB,IAAW5N,IAAa,KAAK,OAAO,QAAQ;AAAA,MACvD;AAAA,MACAG,IAAS;AAAA,IAAA,GAEJ8N,IAAWpoB;AAAAA,MAChB,KAAK,OAAOioB,IAAW,KAAK9N,IAAa,KAAK,OAAO,QAAQ;AAAA,MAC7D;AAAA,MACAG,IAAS;AAAA,IAAA,GAEJ+N,IAAWroB;AAAAA,MAChB,KAAK,MAAMgoB,IAAW7N,IAAa,KAAK,OAAO,QAAQ;AAAA,MACvD;AAAA,MACAI,IAAS;AAAA,IAAA,GAEJ+N,IAAWtoB;AAAAA,MAChB,KAAK,OAAOkoB,IAAW,KAAK/N,IAAa,KAAK,OAAO,QAAQ;AAAA,MAC7D;AAAA,MACAI,IAAS;AAAA,IAAA;AAGV,QAAI4N,IAAWC,KAAYC,IAAWC;AACrC,aAAO,CAAA;AAGR,UAAMC,KAAeR,IAAWE,KAAY,MAAM9N,IAAa,KAAK,OAAO,UACrEqO,KAAeR,IAAWE,KAAY,MAAM/N,IAAa,KAAK,OAAO,UAErEsO,IAA2B,CAAA;AACjC,aAASjoB,IAAI6nB,GAAU7nB,KAAK8nB,GAAU9nB,KAAK;AAC1C,eAASD,IAAI4nB,GAAU5nB,KAAK6nB,GAAU7nB,KAAK,GAAG;AAC7C,cAAMuO,IAAOvO,IAAI,KAAK,OAAO,WAAW4Z,GAClCpL,KAAMvO,IAAI,KAAK,OAAO,WAAW2Z,GACjChB,KAAQ,KAAK,KAAK5Y,IAAI,KAAK,KAAK,OAAO,UAAU6Z,CAAU,IAAID,GAC/Df,IAAS,KAAK,KAAK5Y,IAAI,KAAK,KAAK,OAAO,UAAU6Z,CAAW,IAAIF,GAEjE5U,KAAKhF,IAAIgoB,GACT/iB,KAAKhF,IAAIgoB;AACf,QAAAC,EAAQ,KAAK;AAAA,UACZ,KAAK,GAAGrR,CAAI,IAAI7W,CAAC,IAAIC,CAAC;AAAA,UACtB,MAAA4W;AAAA,UACA,GAAA7W;AAAA,UACA,GAAAC;AAAA,UACA,QAAQ,CAACsO,GAAMC,IAAKoK,IAAOC,CAAM;AAAA,UACjC,WAAW7T,KAAKA,KAAKC,KAAKA;AAAA,UAC1B,KAAK6R,GAAU,KAAK,QAAQD,GAAM7W,GAAGC,CAAC;AAAA,QAAA,CACtC;AAAA,MACF;AAGD,WAAAioB,EAAQ,KAAK,CAAC7jB,GAAGC,MAAMD,EAAE,YAAYC,EAAE,SAAS,GACzC4jB;AAAA,EACR;AAAA,EAEA,YAAkB;AACjB,QAAI,KAAK,MAAM,QAAQ,KAAK,cAAe;AAE3C,UAAMC,IAAU,MAAM,KAAK,KAAK,MAAM,SAAS;AAC/C,IAAAA,EAAQ,KAAK,CAAC9jB,GAAGC,MAAMD,EAAE,CAAC,EAAE,WAAWC,EAAE,CAAC,EAAE,QAAQ;AAEpD,UAAM8jB,IAAc,KAAK,MAAM,OAAO,KAAK;AAC3C,aAAShmB,IAAI,GAAGA,IAAIgmB,GAAahmB,KAAK,GAAG;AACxC,YAAM,CAAC8gB,GAAKxjB,CAAK,IAAIyoB,EAAQ/lB,CAAC;AAC9B,WAAK,GAAG,cAAc1C,EAAM,OAAO,GACnC,KAAK,MAAM,OAAOwjB,CAAG;AAAA,IACtB;AAAA,EACD;AAAA,EAEA,SAAe;AACd,QAAI,KAAK,aAAa,KAAK,eAAe,KAAK,GAAG,gBAAiB;AACnE,UAAMmF,IAAe9J,GAAA;AACrB,SAAK,eAAe;AAEpB,UAAMljB,IAAK,KAAK,IACVitB,IAAc,KAAK,aACnBC,IAAe,KAAK;AAE1B,IAAAltB,EAAG,WAAW,MAAM,MAAM,KAAK,CAAC,GAChCA,EAAG,MAAMA,EAAG,gBAAgB;AAE5B,UAAM6sB,IAAU,KAAK,gBAAA,GACfX,IAAa,KAAK,cAAA,GAClBvE,IAAc,IAAI,IAAIkF,EAAQ,IAAI,CAACnqB,MAASA,EAAK,GAAG,CAAC;AAE3D,IAAA1C,EAAG,WAAWitB,EAAY,OAAO,GACjCjtB,EAAG,gBAAgBitB,EAAY,GAAG,GAClCjtB,EAAG,iBAAiBitB,EAAY,SAAS,IAAO,KAAK,OAAO,WAAW,GACvEjtB,EAAG,UAAUitB,EAAY,UAAU,CAAC;AAEpC,UAAME,IAA8B,CAAA;AACpC,eAAW,CAAA,EAAGC,CAAM,KAAK,KAAK;AAC7B,MAAIzF,EAAY,IAAIyF,EAAO,GAAG,KACzB,KAAK,iBAAiBA,EAAO,QAAQlB,CAAU,KACpDiB,EAAc,KAAKC,CAAM;AAG1B,IAAAD,EAAc,KAAK,CAACnkB,GAAGC,MAAMD,EAAE,OAAOC,EAAE,IAAI;AAC5C,eAAWmkB,KAAUD;AACpB,MAAAC,EAAO,WAAW,KAAK,aACvBptB,EAAG,cAAcA,EAAG,QAAQ,GAC5BA,EAAG,YAAYA,EAAG,YAAYotB,EAAO,OAAO,GAC5CptB,EAAG;AAAA,QACFitB,EAAY;AAAA,QACZG,EAAO,OAAO,CAAC;AAAA,QACfA,EAAO,OAAO,CAAC;AAAA,QACfA,EAAO,OAAO,CAAC;AAAA,QACfA,EAAO,OAAO,CAAC;AAAA,MAAA,GAEhBptB,EAAG,WAAWA,EAAG,gBAAgB,GAAG,CAAC;AAGtC,QAAIqtB,IAAgB;AACpB,UAAMC,IAAgC,CAAA;AACtC,eAAW5qB,KAAQmqB,GAAS;AAC3B,YAAMO,IAAS,KAAK,MAAM,IAAI1qB,EAAK,GAAG;AACtC,UAAI,CAAC0qB,GAAQ;AACZ,QAAAE,EAAa,KAAK5qB,CAAI;AACtB;AAAA,MACD;AACA,MAAA0qB,EAAO,WAAW,KAAK,aACvBptB,EAAG,cAAcA,EAAG,QAAQ,GAC5BA,EAAG,YAAYA,EAAG,YAAYotB,EAAO,OAAO,GAC5CptB,EAAG;AAAA,QACFitB,EAAY;AAAA,QACZG,EAAO,OAAO,CAAC;AAAA,QACfA,EAAO,OAAO,CAAC;AAAA,QACfA,EAAO,OAAO,CAAC;AAAA,QACfA,EAAO,OAAO,CAAC;AAAA,MAAA,GAEhBptB,EAAG,WAAWA,EAAG,gBAAgB,GAAG,CAAC,GACrCqtB,KAAiB;AAAA,IAClB;AACA,SAAK,cAAc,SAASC,CAAY,GAExCttB,EAAG,YAAYA,EAAG,YAAY,IAAI,GAClCA,EAAG,gBAAgB,IAAI;AAEvB,QAAIutB,IAAiB;AAsBrB,QArBI,KAAK,aAAa,MACrBvtB,EAAG,OAAOA,EAAG,KAAK,GAClBA,EAAG,UAAUA,EAAG,KAAKA,EAAG,mBAAmB,GAC3CA,EAAG,WAAWktB,EAAa,OAAO,GAClCltB,EAAG,gBAAgBktB,EAAa,GAAG,GACnCltB,EAAG,iBAAiBktB,EAAa,SAAS,IAAO,KAAK,OAAO,WAAW,GACxEltB,EAAG,UAAUktB,EAAa,YAAY,KAAK,oBAAoB,GAC/DltB,EAAG,UAAUktB,EAAa,cAAc,KAAK,gBAAgB,GAC7DltB,EAAG,UAAUktB,EAAa,UAAU,CAAC,GACrCltB,EAAG,cAAcA,EAAG,QAAQ,GAC5BA,EAAG,YAAYA,EAAG,YAAYktB,EAAa,cAAc,GACrD,KAAK,kBACRltB,EAAG,aAAaA,EAAG,QAAQ,KAAK,YAAYA,EAAG,cAAc,CAAC,IAE9DA,EAAG,WAAWA,EAAG,QAAQ,GAAG,KAAK,UAAU,GAE5CA,EAAG,YAAYA,EAAG,YAAY,IAAI,GAClCA,EAAG,gBAAgB,IAAI,GACvButB,IAAiB,KAAK,aAGnB,KAAK,SAAS;AACjB,YAAMC,IAAiB,KAAK,cAAc,YAAA,GACpCC,IAAYJ,GACZK,IAAcJ,EAAa,QAC3BK,IACLR,EAAc,SAASE,KAAiBE,IAAiB,IAAI,IAAI;AAClE,WAAK,QAAQ;AAAA,QACZ,MAAM,KAAK;AAAA,QACX,SAASV,EAAQ;AAAA,QACjB,UAAUQ;AAAA,QACV,QAAQE;AAAA,QACR,UAAUJ,EAAc;AAAA,QACxB,OAAO,KAAK,MAAM;AAAA,QAClB,UAAUK,EAAe;AAAA,QACzB,QAAQA,EAAe;AAAA,QACvB,SAASA,EAAe;AAAA,QACxB,QAAQA,EAAe;AAAA,QACvB,SAASA,EAAe;AAAA,QACxB,WAAAC;AAAA,QACA,aAAAC;AAAA,QACA,WAAAC;AAAA,QACA,SAASzK,OAAU8J;AAAA,MAAA,CACnB;AAAA,IACF;AAAA,EACD;AAAA,EAEA,gBAAsB;AACrB,IACC,KAAK,UAAU,QACf,KAAK,aACL,KAAK,eACL,KAAK,GAAG,cAAA,MAGT,KAAK,QAAQ,sBAAsB,MAAM;AACxC,WAAK,QAAQ,MACb,KAAK,OAAA;AAAA,IACN,CAAC;AAAA,EACF;AAAA,EAEA,SAAe;AACd,UAAM/pB,IAAO,KAAK,OAAO,sBAAA,GACnB+Z,IAAO,KAAK,IAAI,GAAG/Z,EAAK,SAAS,KAAK,OAAO,eAAe,CAAC,GAC7Dga,IAAO,KAAK,IAAI,GAAGha,EAAK,UAAU,KAAK,OAAO,gBAAgB,CAAC,GAC/DG,IAAM,KAAK,IAAI,GAAG,OAAO,oBAAoB,CAAC,GAE9C8Z,IAAS,KAAK,IAAI,GAAG,KAAK,MAAMF,IAAO5Z,CAAG,CAAC,GAC3C+Z,IAAS,KAAK,IAAI,GAAG,KAAK,MAAMF,IAAO7Z,CAAG,CAAC;AAEjD,KAAI,KAAK,OAAO,UAAU8Z,KAAU,KAAK,OAAO,WAAWC,OAC1D,KAAK,OAAO,QAAQD,GACpB,KAAK,OAAO,SAASC,IAGtB,KAAK,OAAO,YAAYH,GAAMC,CAAI,GAClC,KAAK,GAAG,SAAS,GAAG,GAAGC,GAAQC,CAAM,GACrC,KAAK,cAAA;AAAA,EACN;AAAA,EAEA,cAAchE,GAA2B;AACxC,QAAI,KAAK,kBAAmB;AAC5B,UAAMyU,IAAc,KAAK,mBAAmBzU,EAAM,WAAWA,EAAM;AAEnE,KADoBA,EAAM,WAAW,KAAMyU,KAAezU,EAAM,WAAW,OAEvEyU,KACHzU,EAAM,eAAA,GAEP,KAAK,WAAW,IAChB,KAAK,kBACJyU,IAAc,WAAW,OAC1B,KAAK,YAAYzU,EAAM,WACvB,KAAK,eAAeA,EAAM,SAC1B,KAAK,eAAeA,EAAM,SAC1B,KAAK,qBACJ,KAAK,oBAAoB,WACtB,KAAK,mBAAmBA,EAAM,SAASA,EAAM,OAAO,IACpD,MACJ,KAAK,OAAO,UAAU,IAAI,UAAU,GACpC,KAAK,OAAO,kBAAkBA,EAAM,SAAS;AAAA,EAC9C;AAAA,EAEA,cAAcA,GAA2B;AAExC,QADI,KAAK,qBACL,CAAC,KAAK,YAAYA,EAAM,cAAc,KAAK,UAAW;AAE1D,UAAMxP,IAAKwP,EAAM,UAAU,KAAK,cAC1BvP,IAAKuP,EAAM,UAAU,KAAK;AAIhC,QAHA,KAAK,eAAeA,EAAM,SAC1B,KAAK,eAAeA,EAAM,SAEtB,KAAK,oBAAoB,UAAU;AACtC,YAAM0U,IAAY,KAAK,mBAAmB1U,EAAM,SAASA,EAAM,OAAO,GAChE2U,IAAY,KAAK;AAEvB,UADA,KAAK,qBAAqBD,GACtBC,MAAc,MAAM;AACvB,cAAMC,IAAWF,IAAYC,GACvBrmB,IAAQ,KAAK,MAAM,KAAK,IAAIsmB,CAAQ,GAAG,KAAK,IAAIA,CAAQ,CAAC,GAEzDC,IAEF,KAAK,qCACNvF,IAEGxQ,IAAQ,KAAK,OAAO,aAAA;AAC1B,aAAK,OAAO,aAAa;AAAA,UACxB,aACCA,EAAM,cAAgBxQ,IAAQ,MAAO,KAAK,KAAMumB;AAAA,QAAA,CACjD;AAAA,MACF;AAAA,IACD,OAAO;AACN,YAAM/V,IAAQ,KAAK,OAAO,aAAA,GACpBzU,IAAO,KAAK,IAAI,MAAMyU,EAAM,IAAI,GAChC4Q,IAAMC,GAAU7Q,EAAM,WAAW,GACjC8Q,IAAM,KAAK,IAAIF,CAAG,GAClBG,IAAM,KAAK,IAAIH,CAAG,GAClBwC,KAAW1hB,IAAKof,IAAMnf,IAAKof,KAAOxlB,GAClC8nB,KAAW3hB,IAAKqf,IAAMpf,IAAKmf,KAAOvlB;AACxC,WAAK,OAAO,aAAa;AAAA,QACxB,SAASyU,EAAM,UAAUoT;AAAA,QACzB,SAASpT,EAAM,UAAUqT;AAAA,MAAA,CACzB;AAAA,IACF;AAEA,SAAK,eAAA,GACL,KAAK,cAAA,GACL,KAAK,cAAA;AAAA,EACN;AAAA,EAEA,YAAYnS,GAA2B;AACtC,IAAI,KAAK,qBACLA,EAAM,cAAc,KAAK,aAC7B,KAAK,WAAA;AAAA,EACN;AAAA,EAEA,QAAQA,GAAyB;AAChC,QAAI,KAAK,mBAAmB;AAC3B,MAAAA,EAAM,eAAA;AACN;AAAA,IACD;AAEA,IAAAA,EAAM,eAAA;AACN,UAAMlW,IAAO,KAAK,OAAO,sBAAA,GACnB0B,IAAIwU,EAAM,UAAUlW,EAAK,MACzB2B,IAAIuU,EAAM,UAAUlW,EAAK,KACzBioB,IAAS/R,EAAM,SAAS,IAAI,OAAO;AACzC,SAAK,OAAO+R,GAAQvmB,GAAGC,CAAC;AAAA,EACzB;AAAA,EAEA,cAAcuU,GAAyB;AACtC,QAAI,KAAK,kBAAmB;AAC5B,UAAMlW,IAAO,KAAK,OAAO,sBAAA,GACnB0B,IAAIwU,EAAM,UAAUlW,EAAK,MACzB2B,IAAIuU,EAAM,UAAUlW,EAAK;AAC/B,SAAK,OAAOkW,EAAM,WAAW,MAAM,MAAMxU,GAAGC,CAAC;AAAA,EAC9C;AAAA,EAEA,cAAcuU,GAAyB;AACtC,KAAI,KAAK,YAAYA,EAAM,WAAWA,EAAM,YAC3CA,EAAM,eAAA;AAAA,EAER;AAAA,EAEQ,mBAAmBA,GAAoB;AAE9C,IADAA,EAAM,eAAA,GACF,OAAK,aAAa,KAAK,iBAC3B,KAAK,cAAc,IACnB,KAAK,oBAAoB,IAErB,KAAK,UAAU,SAClB,qBAAqB,KAAK,KAAK,GAC/B,KAAK,QAAQ,OAGd,KAAK,WAAA,GACL,KAAK,cAAc,MAAA,GACnB,KAAK,MAAM,MAAA,GACX,KAAK,gBAAA;AAAA,EACN;AAAA,EAEQ,uBAAuB8U,GAAqB;AACnD,IAAI,KAAK,cACT,KAAK,cAAc,IACnB,KAAK,MAAM,MAAA,GAEX,KAAK,cAAc,KAAK,gBAAA,GACxB,KAAK,eAAe,KAAK,iBAAA,GACzB,KAAK,oBAAoB,IAErB,KAAK,oBAAoB,KAAK,iBAAiB,SAAS,KAC3D,KAAK,gBAAgB,KAAK,gBAAgB,GAEvC,KAAK,gBACR,KAAK,aAAa,KAAK,aAAa,IAEpC,KAAK,aAAa,GAGnB,KAAK,OAAA,GACL,KAAK,cAAA,GACL,KAAK,oBAAA;AAAA,EACN;AAAA,EAEA,UAAgB;AACf,QAAI,MAAK,WAwBT;AAAA,UAvBA,KAAK,YAAY,IAEb,KAAK,UAAU,SAClB,qBAAqB,KAAK,KAAK,GAC/B,KAAK,QAAQ,OAGd,KAAK,eAAe,WAAA,GACpB,KAAK,OAAO,oBAAoB,eAAe,KAAK,gBAAgB,GACpE,KAAK,OAAO,oBAAoB,eAAe,KAAK,gBAAgB,GACpE,KAAK,OAAO,oBAAoB,aAAa,KAAK,cAAc,GAChE,KAAK,OAAO,oBAAoB,iBAAiB,KAAK,cAAc,GACpE,KAAK,OAAO,oBAAoB,SAAS,KAAK,UAAU,GACxD,KAAK,OAAO,oBAAoB,YAAY,KAAK,gBAAgB,GACjE,KAAK,OAAO,oBAAoB,eAAe,KAAK,gBAAgB,GACpE,KAAK,OAAO,oBAAoB,oBAAoB,KAAK,gBAAgB,GACzE,KAAK,OAAO;AAAA,QACX;AAAA,QACA,KAAK;AAAA,MAAA,GAEN,KAAK,WAAA,GACL,KAAK,cAAc,QAAA,GAEf,CAAC,KAAK,eAAe,CAAC,KAAK,GAAG,iBAAiB;AAClD,mBAAW,CAAA,EAAG5pB,CAAK,KAAK,KAAK;AAC5B,eAAK,GAAG,cAAcA,EAAM,OAAO;AAEpC,aAAK,GAAG,aAAa,KAAK,YAAY,GAAG,GACzC,KAAK,GAAG,kBAAkB,KAAK,YAAY,GAAG,GAC9C,KAAK,GAAG,cAAc,KAAK,YAAY,OAAO,GAE9C,KAAK,GAAG,aAAa,KAAK,aAAa,SAAS,GAChD,KAAK,GAAG,aAAa,KAAK,aAAa,UAAU,GACjD,KAAK,GAAG,aAAa,KAAK,aAAa,WAAW,GAClD,KAAK,GAAG,cAAc,KAAK,aAAa,cAAc,GACtD,KAAK,GAAG,kBAAkB,KAAK,aAAa,GAAG,GAC/C,KAAK,GAAG,cAAc,KAAK,aAAa,OAAO;AAAA,MAChD;AACA,WAAK,MAAM,MAAA;AAAA;AAAA,EACZ;AAAA,EAEQ,kBAAqC;AAC5C,UAAMrE,IAAK,KAAK,IA4BVU,IAAUL,GAAcL,GA1Bf;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAiBE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MASiC,GAC5CkuB,IAAUvtB,GAAuBX,GAAIU,GAAS,SAAS,GACvDytB,IAAUxtB,GAAuBX,GAAIU,GAAS,SAAS,GACvD0tB,IAAWztB,GAAuBX,GAAIU,GAAS,UAAU,GAEzDuB,IAAMjC,EAAG,kBAAA,GACTquB,IAAMruB,EAAG,aAAA;AACf,QAAI,CAACiC,KAAO,CAACosB;AACZ,YAAM,IAAI,MAAM,0BAA0B;AAG3C,IAAAruB,EAAG,gBAAgBiC,CAAG,GACtBjC,EAAG,WAAWA,EAAG,cAAcquB,CAAG,GAClCruB,EAAG;AAAA,MACFA,EAAG;AAAA,MACH,IAAI,aAAa,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;AAAA,MACjEA,EAAG;AAAA,IAAA;AAGJ,UAAMsuB,IAAQtuB,EAAG,kBAAkBU,GAAS,OAAO,GAC7C6tB,IAAMvuB,EAAG,kBAAkBU,GAAS,KAAK;AAC/C,QAAI4tB,IAAQ,KAAKC,IAAM;AACtB,YAAM,IAAI,MAAM,8BAA8B;AAE/C,WAAAvuB,EAAG,wBAAwBsuB,CAAK,GAChCtuB,EAAG,wBAAwBuuB,CAAG,GAC9BvuB,EAAG,oBAAoBsuB,GAAO,GAAGtuB,EAAG,OAAO,IAAO,IAAI,CAAC,GACvDA,EAAG,oBAAoBuuB,GAAK,GAAGvuB,EAAG,OAAO,IAAO,IAAI,CAAC,GAErDA,EAAG,gBAAgB,IAAI,GACvBA,EAAG,WAAWA,EAAG,cAAc,IAAI,GAE5B,EAAE,SAAAU,GAAS,KAAAuB,GAAK,KAAAosB,GAAK,SAAAH,GAAS,SAAAC,GAAS,UAAAC,EAAA;AAAA,EAC/C;AAAA,EAEQ,mBAAiC;AACxC,UAAMpuB,IAAK,KAAK,IA6CVU,IAAUL,GAAcL,GA3CV;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAcE;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,MA6BsC,GACtDkuB,IAAUvtB,GAAuBX,GAAIU,GAAS,SAAS,GACvD8tB,IAAa7tB,GAAuBX,GAAIU,GAAS,YAAY,GAC7D+tB,IAAW9tB,GAAuBX,GAAIU,GAAS,UAAU,GACzDguB,IAAe/tB,GAAuBX,GAAIU,GAAS,cAAc,GAEjEuB,IAAMjC,EAAG,kBAAA,GACT2uB,IAAY3uB,EAAG,aAAA,GACf4uB,IAAa5uB,EAAG,aAAA,GAChB6uB,IAAc7uB,EAAG,aAAA,GACjB8uB,IAAiB9uB,EAAG,cAAA;AAC1B,QAAI,CAACiC,KAAO,CAAC0sB,KAAa,CAACC,KAAc,CAACC,KAAe,CAACC;AACzD,YAAM,IAAI,MAAM,gCAAgC;AAGjD,IAAA9uB,EAAG,gBAAgBiC,CAAG,GAEtBjC,EAAG,WAAWA,EAAG,cAAc2uB,CAAS,GACxC3uB,EAAG,WAAWA,EAAG,cAAc,GAAGA,EAAG,YAAY;AACjD,UAAM+uB,IAAS/uB,EAAG,kBAAkBU,GAAS,WAAW;AACxD,QAAIquB,IAAS;AACZ,YAAM,IAAI,MAAM,oCAAoC;AAErD,IAAA/uB,EAAG,wBAAwB+uB,CAAM,GACjC/uB,EAAG,oBAAoB+uB,GAAQ,GAAG/uB,EAAG,OAAO,IAAO,GAAG,CAAC,GAEvDA,EAAG,WAAWA,EAAG,cAAc4uB,CAAU,GACzC5uB,EAAG,WAAWA,EAAG,cAAc,GAAGA,EAAG,YAAY;AACjD,UAAMgvB,IAAUhvB,EAAG,kBAAkBU,GAAS,OAAO;AACrD,QAAIsuB,IAAU;AACb,YAAM,IAAI,MAAM,gCAAgC;AAEjD,WAAAhvB,EAAG,wBAAwBgvB,CAAO,GAClChvB,EAAG,qBAAqBgvB,GAAS,GAAGhvB,EAAG,gBAAgB,GAAG,CAAC,GAE3DA,EAAG,WAAWA,EAAG,sBAAsB6uB,CAAW,GAClD7uB,EAAG,WAAWA,EAAG,sBAAsB,GAAGA,EAAG,YAAY,GAEzDA,EAAG,gBAAgB,IAAI,GACvBA,EAAG,WAAWA,EAAG,cAAc,IAAI,GACnCA,EAAG,WAAWA,EAAG,sBAAsB,IAAI,GAE3CA,EAAG,YAAYA,EAAG,YAAY8uB,CAAc,GAC5C9uB,EAAG,cAAcA,EAAG,YAAYA,EAAG,gBAAgBA,EAAG,aAAa,GACnEA,EAAG,cAAcA,EAAG,YAAYA,EAAG,gBAAgBA,EAAG,aAAa,GACnEA,EAAG,cAAcA,EAAG,YAAYA,EAAG,oBAAoBA,EAAG,OAAO,GACjEA,EAAG,cAAcA,EAAG,YAAYA,EAAG,oBAAoBA,EAAG,OAAO,GACjEA,EAAG;AAAA,MACFA,EAAG;AAAA,MACH;AAAA,MACAA,EAAG;AAAA,MACH;AAAA,MACA;AAAA,MACA;AAAA,MACAA,EAAG;AAAA,MACHA,EAAG;AAAA,MACH,IAAI,WAAW,CAAC,KAAK,KAAK,KAAK,GAAG,CAAC;AAAA,IAAA,GAEpCA,EAAG,YAAYA,EAAG,YAAY,IAAI,GAE3B;AAAA,MACN,SAAAU;AAAA,MACA,KAAAuB;AAAA,MACA,WAAA0sB;AAAA,MACA,YAAAC;AAAA,MACA,aAAAC;AAAA,MACA,gBAAAC;AAAA,MACA,SAAAZ;AAAA,MACA,YAAAM;AAAA,MACA,UAAAC;AAAA,MACA,cAAAC;AAAA,IAAA;AAAA,EAEF;AAAA,EAEQ,iBAAiBhsB,GAAqBI,GAA2B;AACxE,QAAI,KAAK,aAAa,KAAK,eAAe,KAAK,GAAG,iBAAiB;AAClE,MAAAA,EAAO,MAAA;AACP;AAAA,IACD;AACA,QAAI,KAAK,MAAM,IAAIJ,EAAK,GAAG,GAAG;AAC7B,MAAAI,EAAO,MAAA;AACP;AAAA,IACD;AAEA,UAAMC,IAAU,KAAK,wBAAwBD,CAAM;AAEnD,IADAA,EAAO,MAAA,GACFC,MAEL,KAAK,MAAM,IAAIL,EAAK,KAAK;AAAA,MACxB,KAAKA,EAAK;AAAA,MACV,SAAAK;AAAA,MACA,QAAQL,EAAK;AAAA,MACb,MAAMA,EAAK;AAAA,MACX,UAAU,KAAK;AAAA,IAAA,CACf,GACD,KAAK,UAAA,GACL,KAAK,cAAA;AAAA,EACN;AAAA,EAEQ,wBAAwBI,GAA0C;AACzE,QAAI,KAAK,eAAe,KAAK,GAAG,cAAA,EAAiB,QAAO;AACxD,UAAM9C,IAAK,KAAK,IACV+C,IAAU/C,EAAG,cAAA;AACnB,WAAK+C,KAEL/C,EAAG,YAAYA,EAAG,YAAY+C,CAAO,GACrC/C,EAAG,YAAYA,EAAG,qBAAqB,CAAC,GACxCA,EAAG,cAAcA,EAAG,YAAYA,EAAG,gBAAgBA,EAAG,aAAa,GACnEA,EAAG,cAAcA,EAAG,YAAYA,EAAG,gBAAgBA,EAAG,aAAa,GACnEA,EAAG,cAAcA,EAAG,YAAYA,EAAG,oBAAoBA,EAAG,MAAM,GAChEA,EAAG,cAAcA,EAAG,YAAYA,EAAG,oBAAoBA,EAAG,MAAM,GAChEA,EAAG,WAAWA,EAAG,YAAY,GAAGA,EAAG,MAAMA,EAAG,MAAMA,EAAG,eAAe8C,CAAM,GAC1E9C,EAAG,YAAYA,EAAG,YAAY,IAAI,GAC3B+C,KAVc;AAAA,EAWtB;AACD;ACr4CA,MAAMksB,KAAiC,CAAA,GACjCC,KAAyC,CAAA,GACzCC,KAAqC;AAAA,EACzC,OAAO;AAAA,EACP,WAAW,IAAI,aAAa,CAAC;AAAA,EAC7B,gBAAgB,IAAI,YAAY,CAAC;AACnC,GACMC,KAAyB,MACzBC,KAA0B,GAC1BC,KAA0B,IAC1BC,KAA0B,MAC1BC,KAA+B;AA+ErC,SAASnQ,GAAmBC,GAAiC;AAC3D,SAAO,KAAK,IAAI,GAAG,KAAK,IAAI,KAAK,MAAMA,EAAU,SAAS,CAAC,GAAG,KAAK,OAAOA,EAAU,WAAW,UAAU,KAAK,CAAC,GAAGA,EAAU,gBAAgB,UAAU,CAAC,CAAC;AAC1J;AAEA,SAASmQ,GAAoB5L,GAAsC6G,GAA0C;AAC3G,MAAI,EAAE7G,aAAuB,gBAAgB6G,KAAgB,KAAK7G,EAAY,WAAW;AACvF,WAAO;AAGT,MAAI6L,IAAe;AACnB,WAAS3oB,IAAI,GAAGA,IAAI8c,EAAY,QAAQ9c,KAAK;AAC3C,QAAI,EAAA8c,EAAY9c,CAAC,IAAI2jB,IACrB;AAAA,MAAAgF,IAAe;AACf;AAAA;AAEF,MAAI,CAACA;AACH,WAAO7L;AAGT,QAAMnf,IAAM,IAAI,YAAYmf,EAAY,MAAM;AAC9C,MAAIjM,IAAS;AACb,WAAS7Q,IAAI,GAAGA,IAAI8c,EAAY,QAAQ9c,KAAK,GAAG;AAC9C,UAAMwf,IAAM1C,EAAY9c,CAAC;AACzB,IAAIwf,KAAOmE,MACXhmB,EAAIkT,CAAM,IAAI2O,GACd3O,KAAU;AAAA,EACZ;AACA,SAAOlT,EAAI,SAAS,GAAGkT,CAAM;AAC/B;AAEA,SAAS+X,GAAwBzvB,GAA+B4jB,GAA8B;AAC5F,MAAI,CAAC5jB,KAAU4jB,KAAgB,EAAG,QAAO;AACzC,QAAM9Y,IAAO,KAAK,IAAI,GAAG9K,EAAO,QAAQA,EAAO,MAAM,GAE/CkZ,IADa,KAAK,KAAKpO,IAAO,KAAK,IAAI,GAAG8Y,CAAY,CAAC,IACpC0L;AACzB,SAAO,KAAK,IAAIF,IAAyB,KAAK,IAAIC,IAAyBnW,CAAG,CAAC;AACjF;AAEA,SAASwW,GAAuBtQ,GAA4Cpf,GAAyD;AACnI,MAAI,CAACof,KAAa,CAACA,EAAU,aAAa,CAACA,EAAU;AACnD,WAAO;AAGT,QAAM+D,IAAYhE,GAAmBC,CAAS;AAC9C,MAAI+D,KAAa;AACf,WAAO;AAGT,QAAMhD,IAAYf,EAAU,UAAU,SAAS,GAAG+D,IAAY,CAAC,GACzDwB,IAAMvF,EAAU,eAAe,eAAeA,EAAU,IAAI,UAAU+D,IAAY/D,EAAU,IAAI,SAAS,GAAG+D,CAAS,IAAI,MACzHQ,IAAc4L,GAAoBnQ,EAAU,aAAa+D,CAAS,GAClES,IAAeD,IAAcA,EAAY,SAASR;AACxD,MAAIS,MAAiB;AACnB,WAAO;AAGT,QAAM+L,IAAWF,GAAwBzvB,GAAQ4jB,CAAY,GACvDgM,wBAAc,IAAA,GAEdC,IAAa,CAAChM,MAA6B;AAC/C,UAAM9R,IAAKoO,EAAU0D,IAAa,CAAC,GAC7B7R,IAAKmO,EAAU0D,IAAa,IAAI,CAAC;AACvC,QAAI,CAAC,OAAO,SAAS9R,CAAE,KAAK,CAAC,OAAO,SAASC,CAAE,EAAG;AAElD,UAAM8d,IAAQ,KAAK,MAAM/d,IAAK4d,CAAQ,GAChCI,IAAQ,KAAK,MAAM/d,IAAK2d,CAAQ;AACtC,QAAIK,IAASJ,EAAQ,IAAIE,CAAK;AAC9B,IAAKE,MACHA,wBAAa,IAAA,GACbJ,EAAQ,IAAIE,GAAOE,CAAM;AAE3B,UAAMC,IAASD,EAAO,IAAID,CAAK;AAC/B,IAAIE,IACFA,EAAO,KAAKpM,CAAU,IAEtBmM,EAAO,IAAID,GAAO,CAAClM,CAAU,CAAC;AAAA,EAElC;AAEA,MAAIF;AACF,aAAS9c,IAAI,GAAGA,IAAI8c,EAAY,QAAQ9c,KAAK;AAC3C,MAAAgpB,EAAWlM,EAAY9c,CAAC,KAAK,CAAC;AAAA;AAGhC,aAASA,IAAI,GAAGA,IAAIsc,GAAWtc,KAAK;AAClC,MAAAgpB,EAAWhpB,CAAC;AAIhB,SAAI+oB,EAAQ,SAAS,IACZ,OAGF;AAAA,IACL,UAAAD;AAAA,IACA,WAAAxM;AAAA,IACA,WAAAhD;AAAA,IACA,KAAAwE;AAAA,IACA,SAAAiL;AAAA,EAAA;AAEJ;AAEA,SAASM,GAAgBrY,GAAmBtC,GAAgC;AAC1E,SAAOsC,EAAO,MAAMtC;AACtB;AAEA,SAAS4a,GAAiBprB,GAAuB2T,GAAoC;AACnF,MAAI,CAAC,MAAM,QAAQA,CAAO,KAAKA,EAAQ,SAAS,EAAG,QAAO;AAE1D,QAAM,CAACjU,GAAGC,CAAC,IAAIK;AACf,MAAI2a,IAAS;AAEb,WAAS7Y,IAAI,GAAG8Y,IAAIjH,EAAQ,SAAS,GAAG7R,IAAI6R,EAAQ,QAAQiH,IAAI9Y,KAAK;AACnE,UAAM,CAAC+Y,GAAIC,CAAE,IAAInH,EAAQ7R,CAAC,GACpB,CAACiZ,GAAIC,CAAE,IAAIrH,EAAQiH,CAAC;AAE1B,IADkBE,IAAKnb,KAAMqb,IAAKrb,KAAKD,KAAMqb,IAAKF,MAAOlb,IAAImb,KAAO,KAAK,IAAI,OAAOE,IAAKF,CAAE,IAAID,UACvE,CAACF;AAAA,EAC3B;AAEA,SAAOA;AACT;AAEA,SAAS0Q,GACPjd,GACAwS,GAKO;AACP,WAAS9e,IAAI8e,EAAQ,SAAS,GAAG9e,KAAK,GAAGA,KAAK,GAAG;AAC/C,UAAMgR,IAAS8N,EAAQ9e,CAAC;AACxB,QAAKgR,GAAQ,aAAa,UACrBsY,GAAiBhd,GAAO0E,EAAO,WAAW;AAC/C,aAAO;AAAA,QACL,QAAAA;AAAA,QACA,aAAahR;AAAA,QACb,UAAUqpB,GAAgBrY,GAAQhR,CAAC;AAAA,MAAA;AAAA,EAEvC;AACA,SAAO;AACT;AAsDO,SAASwpB,GAAgB;AAAA,EAC9B,QAAArwB;AAAA,EACA,WAAAyC;AAAA,EACA,mBAAA6tB;AAAA,EACA,SAAAC;AAAA,EACA,aAAAC;AAAA,EACA,eAAAC;AAAA,EACA,mBAAAC;AAAA,EACA,cAAAzY,IAAe;AAAA,EACf,mBAAA0Y;AAAA,EACA,UAAAC,IAAW;AAAA,EACX,oBAAAC,IAAqB;AAAA,EACrB,WAAAjV,IAAY;AAAA,EACZ,gBAAAkV,IAAiB;AAAA,EACjB,WAAA1R,IAAY;AAAA,EACZ,cAAA2R,IAAe;AAAA,EACf,iBAAAvH;AAAA,EACA,YAAAwH;AAAA,EACA,aAAAC;AAAA,EACA,kBAAAC,IAAmB;AAAA,EACnB,UAAAC,IAAW;AAAA,EACX,aAAAC;AAAA,EACA,kBAAAC;AAAA,EACA,yBAAAC;AAAA,EACA,iBAAAC,KAAkB;AAAA,EAClB,UAAAC,IAAW;AAAA,EACX,cAAAhe;AAAA,EACA,cAAAC;AAAA,EACA,mBAAAU;AAAA,EACA,wBAAAC;AAAA,EACA,yBAAAC;AAAA,EACA,kBAAAC;AAAA,EACA,0BAAAC;AAAA,EACA,eAAAC;AAAA,EACA,cAAAid;AAAA,EACA,cAAAxd;AAAA,EACA,kBAAAU;AAAA,EACA,oBAAA+c;AAAA,EACA,cAAAC;AAAA,EACA,cAAAC;AAAA,EACA,eAAAC;AAAA,EACA,eAAAC;AAAA,EACA,sBAAAC;AAAA,EACA,yBAAAC;AAAA,EACA,gBAAApe;AAAA,EACA,iBAAAC;AAAA,EACA,iBAAAoe,IAAkB;AAAA,EAClB,oBAAAC;AAAA,EACA,WAAArd;AAAA,EACA,OAAApE;AACF,GAA6C;AAC3C,QAAMqE,KAAYC,EAAiC,IAAI,GACjDkK,IAAclK,EAA+B,IAAI,GACjDod,KAAoBpd,EAA4B,IAAI,GACpDqd,KAAwBrd,EAA4B,IAAI,GACxDsd,IAAuBtd,EAAiCub,CAAiB,GACzEgC,KAAavd,EAAuBwb,CAAO,GAC3CgC,KAAkBxd,EAAOkD,CAAY,GACrC,CAACua,IAAgBC,EAAiB,IAAIC,GAAS,EAAI,GACnD,CAACje,IAAiBke,EAAkB,IAAID,GAAiC,IAAI,GAC7E,CAAChe,IAAgBke,EAAiB,IAAIF,GAAiC,IAAI,GAC3E,CAACG,IAAsBC,CAAuB,IAAIJ,GAA8B,IAAI,GACpF,CAACK,GAAYC,CAAa,IAAIN,GAAgC,IAAI,GAClEO,IAAqBle,EAA+B,IAAI,GACxDme,IAAuBne,EAAsB,IAAI,GACjDoe,IAAoBpe,EAAsB,IAAI,GAC9Cqe,IAAere,EAAO,CAAC,GACvBse,IAAiBrC,KAAcjC,IAC/BuE,IAAmBrf,KAAgB8a,IACnCwE,KAAkBtC,KAAejC,IACjCwE,MAAmC/B,GAAc,UAAU,KAAK,GAEhEzb,KAAcV,GAAuB,OAAO,EAAE,UAAU,YAAY,OAAO,QAAQ,QAAQ,QAAQ,GAAG7E,GAAA,IAAU,CAACA,EAAK,CAAC,GACvHgjB,KAA0Bne;AAAA,IAC9B,OAAO;AAAA,MACL,UAAU;AAAA,MACV,KAAK;AAAA,MACL,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,SAAS;AAAA,MACT,UAAU;AAAA,MACV,eAAe;AAAA,MACf,YAAY;AAAA,MACZ,YAAY;AAAA,MACZ,YAAY;AAAA,MACZ,UAAU;AAAA,MACV,OAAO;AAAA,MACP,YAAY;AAAA,MACZ,QAAQ;AAAA,MACR,cAAc;AAAA,MACd,WAAW;AAAA,MACX,GAAGqb;AAAA,IAAA;AAAA,IAEL,CAACA,CAAiB;AAAA,EAAA,GAGd+C,IAAsBpe,GAAqB,MAC3C+d,EAAe,SAAS,IACnBA,IAELE,GAAgB,WAAW,IACtBxE,KAEFwE,GAAgB,IAAI,CAAChvB,GAAagR,OAAW;AAAA,IAClD,IAAIA;AAAA,IACJ,aAAAhR;AAAA,EAAA,EACA,GACD,CAAC8uB,GAAgBE,EAAe,CAAC,GAE9BI,KAAere,GAAQ,MAAMoe,EAAoB,IAAI,CAAA7b,MAAUA,EAAO,WAAW,GAAG,CAAC6b,CAAmB,CAAC,GAEzG,CAACE,IAAiBC,EAAkB,IAAInB,GAA8BtT,CAAS;AAErF,EAAAnF,EAAU,MAAM;AACd,UAAM6Z,IAAQ,EAAEV,EAAa;AAC7B,QAAIhV,IAAY;AAEhB,QAAI,CAAC8S;AACH,aAAA2C,GAAmBzU,CAAS,GACrB,MAAM;AACX,QAAAhB,IAAY;AAAA,MACd;AAGF,QAAI,CAACgB,KAAa,CAACA,EAAU,SAAS,CAACA,EAAU,aAAa,CAACA,EAAU;AACvE,aAAAyU,GAAmB,IAAI,GAChB,MAAM;AACX,QAAAzV,IAAY;AAAA,MACd;AAGF,QAAIuV,GAAa,WAAW;AAC1B,aAAAE,GAAmB5E,EAAoB,GACvCmC,IAAc;AAAA,QACZ,MAAMD;AAAA,QACN,YAAY;AAAA,QACZ,YAAY/R,EAAU;AAAA,QACtB,aAAa;AAAA,QACb,cAAc;AAAA,MAAA,CACf,GACM,MAAM;AACX,QAAAhB,IAAY;AAAA,MACd;AAGF,UAAM2V,IAAc,CAACrQ,GAA2BsQ,OAAoF;AAClI,UAAI5V,KAAa0V,MAAUV,EAAa,QAAS;AACjD,YAAMa,KAAcvQ,GAAM,cAAcA,EAAK,YAAY,SAAUA,GAAM,SAAS;AAClF,MAAAmQ,GAAmBnQ,CAAI,GACvB0N,IAAc;AAAA,QACZ,MAAM4C,GAAM;AAAA,QACZ,YAAYA,GAAM;AAAA,QAClB,YAAY5U,EAAU;AAAA,QACtB,aAAA6U;AAAA,QACA,cAAcN,GAAa;AAAA,QAC3B,YAAYK,GAAM;AAAA,QAClB,gBAAgBA,GAAM;AAAA,QACtB,eAAeA,GAAM;AAAA,MAAA,CACtB;AAAA,IACH;AAyCA,YAvCY,YAA2B;AACrC,UAAI7C,MAAa,QAAQ;AACvB,cAAMnnB,IAAQ,YAAY,IAAA,GACpB0Z,KAAOzD,GAA0Bb,GAAWuU,EAAY;AAC9D,QAAAI,EAAYrQ,IAAM;AAAA,UAChB,MAAM;AAAA,UACN,YAAY,YAAY,QAAQ1Z;AAAA,QAAA,CACjC;AACD;AAAA,MACF;AAEA,UAAImnB,MAAa,iBAAiB;AAChC,cAAM5X,IAAS,MAAM0J,GAAgC7D,GAAWuU,IAA8B,EAAE,cAAc,IAAM;AACpH,QAAAI,EAAYxa,EAAO,MAAM;AAAA,UACvB,MAAMA,EAAO,KAAK;AAAA,UAClB,YAAYA,EAAO,KAAK;AAAA,UACxB,YAAYA,EAAO,KAAK;AAAA,UACxB,gBAAgBA,EAAO,KAAK;AAAA,UAC5B,eAAeA,EAAO,KAAK;AAAA,QAAA,CAC5B;AACD;AAAA,MACF;AAEA,UAAI;AACF,cAAMA,IAAS,MAAMsL,GAAkCzF,GAAWuU,EAA4B;AAC9F,QAAAI,EAAYxa,EAAO,MAAM;AAAA,UACvB,MAAMA,EAAO,KAAK;AAAA,UAClB,YAAYA,EAAO,KAAK;AAAA,QAAA,CACzB;AAAA,MACH,QAAQ;AACN,cAAMvP,IAAQ,YAAY,IAAA,GACpB0Z,KAAOzD,GAA0Bb,GAAWuU,EAAY;AAC9D,QAAAI,EAAYrQ,IAAM;AAAA,UAChB,MAAM;AAAA,UACN,YAAY,YAAY,QAAQ1Z;AAAA,QAAA,CACjC;AAAA,MACH;AAAA,IACF,GAEK,GACE,MAAM;AACX,MAAAoU,IAAY;AAAA,IACd;AAAA,EACF,GAAG,CAAC8S,GAAkBC,GAAU/R,GAAWuU,IAAcvC,CAAW,CAAC;AAErE,QAAM8C,KAA2B,GAAQvC,KAAgBC,KAAgBI,IACnEmC,KAAoB7e,GAAQ,MAC3B4e,KACExE,GAAuBkE,IAAiB5zB,CAAM,IADf,MAErC,CAACk0B,IAA0BN,IAAiB5zB,CAAM,CAAC,GAEhDo0B,KAAuBle;AAAA,IAC3B,CAACme,MAAqD;AACpD,YAAMnV,IAAWD,EAAY;AAC7B,UAAI,CAACC,KAAY,CAACiV,GAAmB,QAAO;AAE5C,YAAM1vB,IAAI,OAAO4vB,EAAW,CAAC,CAAC,GACxB3vB,IAAI,OAAO2vB,EAAW,CAAC,CAAC;AAC9B,UAAI,CAAC,OAAO,SAAS5vB,CAAC,KAAK,CAAC,OAAO,SAASC,CAAC,EAAG,QAAO;AAEvD,YAAMpB,IAAO,KAAK,IAAI,MAAM4b,EAAS,aAAA,EAAe,IAAI,GAClDoV,KAAcpV,EAAS,mBAAA,GAEvBqV,KADc,KAAK,IAAIpF,IAAyBmF,KAAcpF,EAAsB,IACrD5rB;AACrC,UAAI,CAAC,OAAO,SAASixB,EAAc,KAAKA,MAAkB,EAAG,QAAO;AAEpE,YAAM5E,KAAWwE,GAAkB,UAC7BK,KAAY,KAAK,MAAM/vB,IAAIkrB,EAAQ,GACnC8E,KAAY,KAAK,MAAM/vB,IAAIirB,EAAQ,GACnC+E,KAAa,KAAK,IAAI,GAAG,KAAK,KAAKH,KAAiB5E,EAAQ,CAAC,GAC7DzlB,KAAWqqB,KAAiBA;AAElC,UAAII,KAAe,IACfC,KAAe1qB,IACf2qB,KAAW,GACXC,KAAW;AAEf,eAASC,KAAKP,KAAYE,IAAYK,MAAMP,KAAYE,IAAYK,MAAM,GAAG;AAC3E,cAAM/E,KAASmE,GAAkB,QAAQ,IAAIY,EAAE;AAC/C,YAAK/E;AAEL,mBAASgF,KAAKP,KAAYC,IAAYM,MAAMP,KAAYC,IAAYM,MAAM,GAAG;AAC3E,kBAAM/E,KAASD,GAAO,IAAIgF,EAAE;AAC5B,gBAAI,GAAC/E,MAAUA,GAAO,WAAW;AAEjC,uBAASppB,KAAI,GAAGA,KAAIopB,GAAO,QAAQppB,MAAK,GAAG;AACzC,sBAAMgd,KAAaoM,GAAOppB,EAAC;AAC3B,oBAAIgd,MAAcsQ,GAAkB,UAAW;AAE/C,sBAAMpiB,KAAKoiB,GAAkB,UAAUtQ,KAAa,CAAC,GAC/C7R,KAAKmiB,GAAkB,UAAUtQ,KAAa,IAAI,CAAC,GACnDpa,KAAKsI,KAAKtN,GACViF,KAAKsI,KAAKtN,GACV0F,KAAQX,KAAKA,KAAKC,KAAKA;AAC7B,gBAAIU,KAAQwqB,OAEZA,KAAexqB,IACfuqB,KAAe9Q,IACfgR,KAAW9iB,IACX+iB,KAAW9iB;AAAA,cACb;AAAA,UACF;AAAA,MACF;AAEA,UAAI2iB,KAAe,EAAG,QAAO;AAC7B,YAAMM,KAAUd,GAAkB,MAAM,OAAOA,GAAkB,IAAIQ,EAAY,CAAC,IAAI;AACtF,aAAO;AAAA,QACL,OAAOA;AAAA,QACP,IAAIM;AAAA,QACJ,YAAY,CAACxwB,GAAGC,CAAC;AAAA,QACjB,iBAAiB,CAACmwB,IAAUC,EAAQ;AAAA,MAAA;AAAA,IAExC;AAAA,IACA,CAACX,EAAiB;AAAA,EAAA,GAGde,KAAiBhf;AAAA,IACrB,CAACif,GAA2Bd,MAAsC;AAChE,UAAI,CAAC1C,EAAc;AACnB,YAAMyD,IAAYD,GAAK,SAAS,MAC1BE,IAASF,GAAK,MAAM;AAC1B,MAAIjC,EAAqB,YAAYkC,KAAajC,EAAkB,YAAYkC,MAChFnC,EAAqB,UAAUkC,GAC/BjC,EAAkB,UAAUkC,GAC5B1D,EAAa;AAAA,QACX,OAAOyD;AAAA,QACP,IAAIC;AAAA,QACJ,YAAAhB;AAAA,QACA,iBAAiBc,GAAK,mBAAmB;AAAA,MAAA,CAC1C;AAAA,IACH;AAAA,IACA,CAACxD,CAAY;AAAA,EAAA,GAGT2D,KAAiBpf;AAAA,IACrB,CAACme,GAA4BkB,MAAmB;AAC9C,UAAI,CAAC3D,EAAc;AACnB,YAAMuD,IAAMf,GAAqBC,CAAU;AAC3C,MAAKc,KACLvD,EAAa;AAAA,QACX,GAAGuD;AAAA,QACH,QAAAI;AAAA,MAAA,CACD;AAAA,IACH;AAAA,IACA,CAAC3D,GAAcwC,EAAoB;AAAA,EAAA;AAGf,EAAA9e,GAAQ,MAAM;AAClC,UAAMnR,IAAQ,OAAO+tB,GAAoB,SAAS,GAAG;AACrD,WAAO,OAAO,SAAS/tB,CAAK,IAAI,KAAK,IAAI,IAAIA,CAAK,IAAI;AAAA,EACxD,GAAG,CAAC+tB,GAAoB,KAAK,CAAC;AAC9B,QAAMsD,KAAiBlgB,GAAQ,MAAM;AACnC,UAAMnR,IAAQ,OAAO+tB,GAAoB,UAAU,GAAG;AACtD,WAAO,OAAO,SAAS/tB,CAAK,IAAI,KAAK,IAAI,IAAIA,CAAK,IAAI;AAAA,EACxD,GAAG,CAAC+tB,GAAoB,MAAM,CAAC,GACzBuD,KAAiBngB,GAAQ,MAAM;AACnC,UAAMnR,IAAQ,OAAO+tB,GAAoB,UAAU,EAAE;AACrD,WAAO,OAAO,SAAS/tB,CAAK,IAAI,KAAK,IAAI,GAAGA,CAAK,IAAI;AAAA,EACvD,GAAG,CAAC+tB,GAAoB,MAAM,CAAC,GACzBwD,KAAmBxD,GAAoB,YAAY;AAEzD,EAAAjY,EAAU,MAAM;AACd,QAAK+X;AACL,aAAAA,EAAwB,UAAUoC,IAC3B,MAAM;AACX,QAAIpC,EAAwB,YAAYoC,OACtCpC,EAAwB,UAAU;AAAA,MAEtC;AAAA,EACF,GAAG,CAACA,GAAyBoC,EAAoB,CAAC;AAElD,QAAMuB,KAAqBzf;AAAA,IACzB,CAAC/U,MAAiC;AAChC,MAAAyxB,GAAkB,CAAA5tB,MACZ,OAAOA,CAAI,MAAM,OAAO7D,CAAI,IACvB6D,KAET+sB,KAAuB5wB,CAAI,GACpBA,EACR;AAAA,IACH;AAAA,IACA,CAAC4wB,EAAoB;AAAA,EAAA;AAGvB,EAAA9X,EAAU,MAAM;AACd,IAAAoY,EAAqB,UAAU/B;AAAA,EACjC,GAAG,CAACA,CAAiB,CAAC,GAEtBrW,EAAU,MAAM;AACd,IAAAqY,GAAW,UAAU/B;AAAA,EACvB,GAAG,CAACA,CAAO,CAAC,GAEZtW,EAAU,MAAM;AACd,IAAAsY,GAAgB,UAAUta,GACrBA,KAAc+a,EAAc,IAAI;AAAA,EACvC,GAAG,CAAC/a,CAAY,CAAC;AAEjB,QAAM2d,KAAsB1f,EAAY,CAAC8d,MAAgC;AACvE,IAAA1B,GAAW,UAAU0B,CAAK,GACtBzB,GAAgB,WAClBS,EAAcgB,CAAK;AAAA,EAEvB,GAAG,CAAA,CAAE,GAEC6B,KAAmBvgB,GAAQ,MAC1Byd,IAGE;AAAA,IACL,QAAQA,EAAW,IAAI,YAAYA,EAAW,SAAS,QAAQ,CAAC,KAAK,GAAG,mBAAmBA,EAAW,aAAa,GAAG;AAAA,IACtH,iBAAiBA,EAAW,OAAO,eAAeA,EAAW,QAAQ,eAAeA,EAAW,QAAQ;AAAA,IACvG,cAAcA,EAAW,KAAK,UAAUA,EAAW,aAAa,GAAG,WAAWA,EAAW,eAAe,GAAG;AAAA,IAC3G,kBAAkBA,EAAW,QAAQ,aAAaA,EAAW,UAAU,GAAG,cAAcA,EAAW,WAAW,GAAG,aAAaA,EAAW,UAAU,GAAG,cAAcA,EAAW,WAAW,GAAG;AAAA,IAC7L,UAAUA,EAAW,MAAM;AAAA,EAAA,EAC3B,KAAK;AAAA,CAAI,IARF,qCASR,CAACA,CAAU,CAAC;AAEf,EAAA9Y,EAAU,MAAM;AAEd,IAAI,EADcvF,OAAmB,OAAO,KAAOgf,EAAoB,KAAK,CAAC7b,GAAQtC,MAAU,OAAO2a,GAAgBrY,GAAQtC,CAAK,CAAC,MAAM,OAAOb,EAAc,CAAC,MAC9IA,OAAmB,QACnCihB,GAAmB,IAAI;AAGzB,UAAMG,IAAe7C,EAAmB;AAGxC,IAAI,EAFa6C,MAAiB,OAAO,KAAOpC,EAAoB,KAAK,CAAC7b,GAAQtC,MAAU,OAAO2a,GAAgBrY,GAAQtC,CAAK,CAAC,MAAM,OAAOugB,CAAY,CAAC,MAE1IA,MAAiB,SAChC7C,EAAmB,UAAU,MAC7BN,GAAmB,IAAI,GACvBd,KAAgB;AAAA,MACd,QAAQ;AAAA,MACR,UAAU;AAAA,MACV,aAAa;AAAA,MACb,YAAY;AAAA,IAAA,CACb;AAAA,EAEL,GAAG,CAAC6B,GAAqBhf,IAAgBmd,IAAe8D,EAAkB,CAAC,GAE3E1b,EAAU,MAAM;AACd,UAAM8b,IAAoB7C,EAAqB;AAC/C,IAAI6C,MAAsB,SACtB5B,MAAqB4B,IAAoB5B,GAAkB,cAC/DjB,EAAqB,UAAU,MAC/BC,EAAkB,UAAU,MAC5BxB,IAAe;AAAA,MACb,OAAO;AAAA,MACP,IAAI;AAAA,MACJ,YAAY;AAAA,MACZ,iBAAiB;AAAA,IAAA,CAClB;AAAA,EACH,GAAG,CAACwC,IAAmBxC,CAAY,CAAC;AAEpC,QAAMqE,KAAsB9f;AAAA,IAC1B,CAAC/U,MAA6B;AAC5B,MAAIqyB,MACFV,EAAwB3xB,CAAI;AAE9B,YAAM80B,IAAW5D,EAAqB;AACtC,MAAI4D,KACFA,EAAS90B,CAAI,GAEfgxB,GAAkB,UAAA,GAClBC,GAAsB,UAAA;AAAA,IACxB;AAAA,IACA,CAACoB,EAA+B;AAAA,EAAA;AAGlC,EAAAvZ,EAAU,MAAM;AACd,QAAI,CAACgY,GAAiB;AACpB,MAAAQ,GAAkB,EAAK;AACvB;AAAA,IACF;AACA,IAAAA,GAAkB,EAAI;AAAA,EACxB,GAAG,CAACR,GAAiBjyB,GAAQ,EAAE,CAAC,GAEhCia,EAAU,MAAM;AACd,IAAIuX,MAAa,YACbyB,EAAmB,YAAY,SACnCA,EAAmB,UAAU,MAC7BN,GAAmB,IAAI,GACvBd,KAAgB;AAAA,MACd,QAAQ;AAAA,MACR,UAAU;AAAA,MACV,aAAa;AAAA,MACb,YAAY;AAAA,IAAA,CACb;AAAA,EACH,GAAG,CAACL,GAAUK,EAAa,CAAC,GAE5B5X,EAAU,MAAM;AACd,IAAIuX,MAAa,YACb0B,EAAqB,YAAY,SACrCA,EAAqB,UAAU,MAC/BC,EAAkB,UAAU,MAC5BxB,IAAe;AAAA,MACb,OAAO;AAAA,MACP,IAAI;AAAA,MACJ,YAAY;AAAA,MACZ,iBAAiB;AAAA,IAAA,CAClB;AAAA,EACH,GAAG,CAACH,GAAUG,CAAY,CAAC;AAE3B,QAAMuE,KAAoBhgB,EAAY,CAACwH,GAAiBC,MAA2C;AACjG,UAAMuB,IAAWD,EAAY;AAC7B,QAAI,CAACC,EAAU,QAAO;AACtB,UAAMhG,IAAMgG,EAAS,cAAcxB,GAASC,CAAO;AACnD,QAAI,CAAC,MAAM,QAAQzE,CAAG,KAAKA,EAAI,SAAS,EAAG,QAAO;AAClD,UAAMzU,IAAI,OAAOyU,EAAI,CAAC,CAAC,GACjBxU,KAAI,OAAOwU,EAAI,CAAC,CAAC;AACvB,WAAI,CAAC,OAAO,SAASzU,CAAC,KAAK,CAAC,OAAO,SAASC,EAAC,IAAU,OAChD,CAACD,GAAGC,EAAC;AAAA,EACd,GAAG,CAAA,CAAE,GAECyxB,KAAqBjgB,EAAY,CAAC6H,GAAgBC,MAA0C;AAChG,UAAMkB,IAAWD,EAAY;AAC7B,QAAI,CAACC,EAAU,QAAO;AACtB,UAAMhG,IAAMgG,EAAS,cAAcnB,GAAQC,CAAM;AACjD,QAAI,CAAC,MAAM,QAAQ9E,CAAG,KAAKA,EAAI,SAAS,EAAG,QAAO;AAClD,UAAMzU,IAAI,OAAOyU,EAAI,CAAC,CAAC,GACjBxU,KAAI,OAAOwU,EAAI,CAAC,CAAC;AACvB,WAAI,CAAC,OAAO,SAASzU,CAAC,KAAK,CAAC,OAAO,SAASC,EAAC,IAAU,OAChD,CAACD,GAAGC,EAAC;AAAA,EACd,GAAG,CAAA,CAAE,GAEC0xB,KAA2BlgB,EAAY,MAAM;AACjD,IAAA+I,EAAY,SAAS,cAAA,GACrBkT,GAAkB,UAAA,GAClBC,GAAsB,UAAA;AAAA,EACxB,GAAG,CAAA,CAAE,GAECiE,KAAgC/gB,GAA6B,MAC1Dud,MAAwB5T,EAAY,SAAS,aAAA,KAAkB,MACrE,CAAC4T,EAAoB,CAAC,GAEnByD,KAAqBhhB,GAAsC,MAAM;AACrE,QAAI,CAACtV,EAAQ,QAAO;AACpB,UAAMu2B,IAAoBF;AAC1B,WAAKE,IACE;AAAA,MACL,QAAAv2B;AAAA,MACA,WAAWu2B;AAAA,MACX,UAAA/E;AAAA,MACA,iBAAAD;AAAA,MACA,eAAe4E;AAAA,MACf,eAAeD;AAAA,MACf,eAAeE;AAAA,IAAA,IARc;AAAA,EAUjC,GAAG,CAACp2B,GAAQq2B,IAA+B7E,GAAUD,IAAiB4E,IAAoBD,IAAmBE,EAAwB,CAAC,GAEhII,KAA0BtgB;AAAA,IAC9B,CAAC+C,MAA6C;AAC5C,YAAMwd,IAAgBxd,EAAM,WAAWnE,GAAU,SAC3C3B,IAAQ+iB,GAAkBjd,EAAM,SAASA,EAAM,OAAO;AAC5D,UAAIyY,GAAoB;AACtB,cAAMgF,KAAc,CAAC,CAACvjB,KAASA,EAAM,CAAC,KAAK,KAAKA,EAAM,CAAC,KAAK,KAAK,CAAC,CAACnT,KAAUmT,EAAM,CAAC,KAAKnT,EAAO,SAASmT,EAAM,CAAC,KAAKnT,EAAO;AAC5H,QAAA0xB,EAAmB;AAAA,UACjB,YAAYve;AAAA,UACZ,SAAS8F,EAAM;AAAA,UACf,SAASA,EAAM;AAAA,UACf,aAAAyd;AAAA,QAAA,CACD;AAAA,MACH;AAEA,UAAIlF,MAAa,SAAU;AAC3B,UAAI,CAACiF,GAAe;AAClB,QAAAvB,GAAe,MAAM,IAAI,GACrBjC,EAAmB,YAAY,SACjCA,EAAmB,UAAU,MAC7BN,GAAmB,IAAI,GACvBd,KAAgB;AAAA,UACd,QAAQ;AAAA,UACR,UAAU;AAAA,UACV,aAAa;AAAA,UACb,YAAY;AAAA,QAAA,CACb;AAEH;AAAA,MACF;AACA,UAAI,CAAC1e,GAAO;AACV,QAAA+hB,GAAe,MAAM,IAAI;AACzB;AAAA,MACF;AAKA,UAHIvD,KACFuD,GAAed,GAAqBjhB,CAAK,GAAGA,CAAK,GAE/C,CAACugB,EAAoB,OAAQ;AAEjC,YAAMyB,IAAM/E,GAAajd,GAAOugB,CAAmB,GAC7CiD,IAAcxB,GAAK,YAAY,MAC/ByB,KAAc3D,EAAmB;AACvC,MAAI,OAAO2D,EAAW,MAAM,OAAOD,CAAW,MAE9C1D,EAAmB,UAAU0D,GAC7BhE,GAAmBgE,CAAW,GAC9B9E,KAAgB;AAAA,QACd,QAAQsD,GAAK,UAAU;AAAA,QACvB,UAAUwB;AAAA,QACV,aAAaxB,GAAK,eAAe;AAAA,QACjC,YAAYhiB;AAAA,MAAA,CACb;AAAA,IACH;AAAA,IACA,CAACqe,GAAUkC,GAAqBwC,IAAmBrE,IAAeH,GAAoB1xB,GAAQk1B,IAAgBd,IAAsBzC,CAAY;AAAA,EAAA,GAG5IkF,KAA2B3gB,EAAY,MAAM;AAQjD,IAPAwb,IAAqB;AAAA,MACnB,YAAY;AAAA,MACZ,SAAS;AAAA,MACT,SAAS;AAAA,MACT,aAAa;AAAA,IAAA,CACd,GACDwD,GAAe,MAAM,IAAI,GACrBjC,EAAmB,YAAY,SACnCA,EAAmB,UAAU,MAC7BN,GAAmB,IAAI,GACvBd,KAAgB;AAAA,MACd,QAAQ;AAAA,MACR,UAAU;AAAA,MACV,aAAa;AAAA,MACb,YAAY;AAAA,IAAA,CACb;AAAA,EACH,GAAG,CAACA,IAAeH,GAAoBwD,EAAc,CAAC,GAEhD4B,KAAoB5gB;AAAA,IACxB,CAAC+C,MAA2C;AAE1C,UADIuY,MAAa,YACbvY,EAAM,WAAWnE,GAAU,QAAS;AAExC,YAAM3B,IAAQ+iB,GAAkBjd,EAAM,SAASA,EAAM,OAAO;AAC5D,UAAI,CAAC9F,EAAO;AAGZ,UAFAmiB,GAAeniB,GAAO8F,EAAM,MAAM,GAE9B,CAACya,EAAoB,QAAQ;AAC/B,QAAAiC,GAAmB,IAAI;AACvB;AAAA,MACF;AAEA,YAAMR,IAAM/E,GAAajd,GAAOugB,CAAmB;AACnD,UAAI,CAACyB,GAAK;AACR,QAAAQ,GAAmB,IAAI;AACvB;AAAA,MACF;AAEA,YAAMoB,IAAqCriB,OAAmB,QAAQ,OAAOA,EAAc,MAAM,OAAOygB,EAAI,QAAQ,IAAI,OAAOA,EAAI;AACnI,MAAAQ,GAAmBoB,CAAU,GAC7BjF,KAAgB;AAAA,QACd,QAAQqD,EAAI;AAAA,QACZ,UAAUA,EAAI;AAAA,QACd,aAAaA,EAAI;AAAA,QACjB,YAAYhiB;AAAA,MAAA,CACb;AAAA,IACH;AAAA,IACA,CAACqe,GAAUkC,GAAqBwC,IAAmBpE,IAAepd,IAAgBihB,IAAoBL,EAAc;AAAA,EAAA,GAGhH0B,KAAiB9gB;AAAA,IACrB,CAAC/C,MAAmC;AAGlC,UAFIqe,MAAa,WACb/d,IAAc,mBAAmB,MACjC,CAACigB,EAAoB,OAAQ,QAAO;AAExC,YAAMyB,IAAM/E,GAAajd,GAAOugB,CAAmB;AACnD,UAAI,CAACyB,EAAK,QAAO;AAEjB,YAAM4B,IAAqCriB,OAAmB,QAAQ,OAAOA,EAAc,MAAM,OAAOygB,EAAI,QAAQ,IAAI,OAAOA,EAAI;AACnI,aAAAQ,GAAmBoB,CAAU,GAC7BjF,KAAgB;AAAA,QACd,QAAQqD,EAAI;AAAA,QACZ,UAAUA,EAAI;AAAA,QACd,aAAaA,EAAI;AAAA,QACjB,YAAYhiB;AAAA,MAAA,CACb,GACM;AAAA,IACT;AAAA,IACA,CAACqe,GAAU/d,IAAc,gBAAgBigB,GAAqBhf,IAAgBihB,IAAoB7D,EAAa;AAAA,EAAA,GAG3GmF,KAA0B/gB;AAAA,IAC9B,CAAC+C,MAA2C;AAG1C,UAFI,CAAC2Y,KACDJ,MAAa,YACbvY,EAAM,WAAWnE,GAAU,QAAS;AACxC,MAAAmE,EAAM,eAAA;AACN,YAAM9F,IAAQ+iB,GAAkBjd,EAAM,SAASA,EAAM,OAAO;AAC5D,MAAK9F,KACLmiB,GAAeniB,GAAO8F,EAAM,MAAM;AAAA,IACpC;AAAA,IACA,CAACuY,GAAU0E,IAAmBZ,IAAgB1D,CAAY;AAAA,EAAA;AAG5D,SAAA3X,EAAU,MAAM;AACd,UAAMpZ,IAASiU,GAAU;AACzB,QAAI,CAACjU,KAAU,CAACb;AACd;AAGF,UAAMkf,IAAW,IAAI8K,GAAgBnpB,GAAQb,GAAQ;AAAA,MACnD,mBAAmBg2B;AAAA,MACnB,SAASJ;AAAA,MACT,aAAApF;AAAA,MACA,eAAAC;AAAA,MACA,mBAAAC;AAAA,MACA,WAAA9U;AAAA,MACA,gBAAAkV;AAAA,MACA,iBAAAtH;AAAA,IAAA,CACD;AAED,WAAAvK,EAAY,UAAUC,GAClBzc,KACFyc,EAAS,aAAazc,CAAS,GAEjCyc,EAAS,mBAAmBqS,EAAe,GACvCiC,MACFV,EAAwB5T,EAAS,cAAc,GAG1C,MAAM;AACX,MAAAA,EAAS,QAAA,GACTD,EAAY,UAAU;AAAA,IACxB;AAAA,EACF,GAAG,CAACjf,GAAQ41B,IAAqBpF,GAAaC,GAAeC,GAAmB9U,GAAWkV,GAAgBtH,GAAiBwM,IAAqBxC,EAA+B,CAAC,GAEjLvZ,EAAU,MAAM;AACd,UAAMiF,IAAWD,EAAY;AAC7B,IAAI,CAACC,KAAY,CAACzc,KAGlByc,EAAS,aAAazc,CAAS;AAAA,EACjC,GAAG,CAACA,CAAS,CAAC,GAEdwX,EAAU,MAAM;AACd,UAAMiF,IAAWD,EAAY;AAC7B,IAAKC,KAGLA,EAAS,WAAA;AAAA,EACX,GAAG,CAAC0R,CAAQ,CAAC,GAEb3W,EAAU,MAAM;AACd,UAAMiF,IAAWD,EAAY;AAC7B,IAAKC,KACLA,EAAS,cAAA;AAAA,EACX,GAAG,CAAC2R,CAAkB,CAAC,GAEvB5W,EAAU,MAAM;AACd,UAAMiF,IAAWD,EAAY;AAC7B,IAAI,CAACC,KAAY,CAAC6R,KAGlB7R,EAAS,gBAAgB6R,CAAY;AAAA,EACvC,GAAG,CAACA,CAAY,CAAC,GAEjB9W,EAAU,MAAM;AACd,UAAMiF,IAAWD,EAAY;AAC7B,IAAKC,KAGLA,EAAS,mBAAmBsK,CAAe;AAAA,EAC7C,GAAG,CAACA,CAAe,CAAC,GAEpBvP,EAAU,MAAM;AACd,UAAMiF,IAAWD,EAAY;AAC7B,IAAKC,KAGLA,EAAS,aAAa0U,EAAe;AAAA,EACvC,GAAG,CAACA,EAAe,CAAC,GAEpB3Z,EAAU,MAAM;AACd,QAAI,CAACoX,EAAkB;AAEvB,UAAM2C,IAAQ/N,GADOiL,IAAmB0C,KAAkBxU,GACRsU,GAAqB;AAAA,MACrE,sBAAsBpC;AAAA,MACtB,qBAAqB;AAAA,IAAA,CACtB;AACD,IAAAD,EAAiB2C,CAAK;AAAA,EACxB,GAAG,CAAC3C,GAAkBH,GAAkB9R,GAAWwU,IAAiBF,GAAqBpC,EAAuB,CAAC,GAEjHrX,EAAU,MAAM;AACd,UAAMiF,IAAWD,EAAY;AAC7B,IAAKC,KAGLA,EAAS,mBAAmBqS,EAAe;AAAA,EAC7C,GAAG,CAACA,EAAe,CAAC,GAGlB,gBAAA2F,GAAC,OAAA,EAAI,WAAAriB,IAAsB,OAAOmB,IAAa,eAAewgB,IAAyB,gBAAgBK,IAA0B,SAASC,IAAmB,eAAeG,IAC1K,UAAA;AAAA,IAAA,gBAAA7c;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,KAAKtF;AAAA,QACL,WAAU;AAAA,QACV,OAAO;AAAA,UACL,UAAU;AAAA,UACV,OAAO;AAAA,UACP,QAAQ;AAAA,UACR,OAAO;AAAA,UACP,QAAQ;AAAA,UACR,SAAS;AAAA,UACT,aAAa;AAAA,UACb,QAAQ0c,MAAa,YAAY/c,OAAoB,OAAO,YAAY8c,KAAkB,cAAc;AAAA,QAAA;AAAA,MAC1G;AAAA,IAAA;AAAA,IAEDvxB,KAAUs2B,MAAsB,MAAM,QAAQ7E,CAAY,KAAKA,EAAa,SAAS,IAClFA,EAAa,IAAI,CAAC0F,GAAO5hB,MACvB,gBAAA6E;AAAA,MAAC;AAAA,MAAA;AAAA,QAEC,WAAW+c,EAAM;AAAA,QACjB,OAAO;AAAA,UACL,UAAU;AAAA,UACV,OAAO;AAAA,UACP,QAAQA,EAAM,UAAU;AAAA,UACxB,eAAeA,EAAM,iBAAiB;AAAA,UACtC,GAAGA,EAAM;AAAA,QAAA;AAAA,QAGV,UAAAA,EAAM,OAAOb,EAAkB;AAAA,MAAA;AAAA,MAV3Ba,EAAM,MAAM5hB;AAAA,IAAA,CAYpB,IACD;AAAA,IACHvV,IACC,gBAAAoa;AAAA,MAAC7G;AAAA,MAAA;AAAA,QACC,MAAMie;AAAA,QACN,SAASA,MAAa;AAAA,QACtB,YAAYxxB,EAAO;AAAA,QACnB,aAAaA,EAAO;AAAA,QACpB,UAAUA,EAAO;AAAA,QACjB,WAAWA,EAAO;AAAA,QAClB,cAAAwT;AAAA,QACA,cAAAC;AAAA,QACA,cAAcwL;AAAA,QACd,YAAY+X;AAAA,QACZ,iBAAiBv0B;AAAA,QACjB,kBAAkBixB;AAAA,QAClB,cAAcJ;AAAA,QACd,mBAAAnf;AAAA,QACA,wBAAAC;AAAA,QACA,yBAAAC;AAAA,QACA,kBAAAC;AAAA,QACA,0BAAAC;AAAA,QACA,eAAAC;AAAA,QACA,iBAAAC;AAAA,QACA,gBAAAC;AAAA,QACA,kBAAAC;AAAA,QACA,eAAewd;AAAA,QACf,gBAAAve;AAAA,QACA,iBAAAC;AAAA,MAAA;AAAA,IAAA,IAEA;AAAA,IACHoE,uBACE,OAAA,EAAI,iCAA6B,IAAC,OAAOwb,IACvC,cACH,IACE;AAAA,IACHzzB,KAAUiyB,IACTO,KACE,gBAAA0E,GAAAE,IAAA,EACE,UAAA;AAAA,MAAA,gBAAAhd,GAACuB,IAAA,EAAY,QAAA3b,GAAgB,cAAcif,GAAa,WAAArD,GAAsB,SAASsW,GAAoB,eAAeE,GAAA,CAAuB;AAAA,MACjJ,gBAAAhY;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,MAAK;AAAA,UACL,cAAW;AAAA,UACX,SAAS,MAAMqY,GAAkB,EAAK;AAAA,UACtC,OAAO;AAAA,YACL,UAAU;AAAA,YACV,QAAQ;AAAA,YACR,GAAIiD,GAAiB,SAAS,MAAM,IAAI,EAAE,MAAMD,GAAA,IAAmB,EAAE,OAAOA,GAAA;AAAA,YAC5E,GAAIC,GAAiB,SAAS,KAAK,IAAI,EAAE,KAAKD,KAAiBD,KAAiB,MAAM,EAAE,QAAQC,KAAiBD,KAAiB,EAAA;AAAA,YAClI,OAAO;AAAA,YACP,QAAQ;AAAA,YACR,cAAc;AAAA,YACd,QAAQ;AAAA,YACR,YAAY;AAAA,YACZ,OAAO;AAAA,YACP,UAAU;AAAA,YACV,YAAY;AAAA,YACZ,QAAQ;AAAA,YACR,SAAS;AAAA,UAAA;AAAA,UAEZ,UAAA;AAAA,QAAA;AAAA,MAAA;AAAA,IAED,EAAA,CACF,IAEA,gBAAApb;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,MAAK;AAAA,QACL,cAAW;AAAA,QACX,SAAS,MAAMqY,GAAkB,EAAI;AAAA,QACrC,OAAO;AAAA,UACL,UAAU;AAAA,UACV,QAAQ;AAAA,UACR,GAAIiD,GAAiB,SAAS,MAAM,IAAI,EAAE,MAAMD,GAAA,IAAmB,EAAE,OAAOA,GAAA;AAAA,UAC5E,GAAIC,GAAiB,SAAS,KAAK,IAAI,EAAE,KAAKD,GAAA,IAAmB,EAAE,QAAQA,GAAA;AAAA,UAC3E,QAAQ;AAAA,UACR,UAAU;AAAA,UACV,cAAc;AAAA,UACd,QAAQ;AAAA,UACR,YAAY;AAAA,UACZ,OAAO;AAAA,UACP,UAAU;AAAA,UACV,YAAY;AAAA,UACZ,QAAQ;AAAA,UACR,SAAS;AAAA,QAAA;AAAA,QAEZ,UAAA;AAAA,MAAA;AAAA,IAAA,IAID;AAAA,EAAA,GACN;AAEJ;"}
|