@rippleflow/water-distortion 0.1.4 → 0.1.6
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 +13 -2
- package/dist/WaterDistortion.d.ts +4 -3
- package/dist/WaterDistortion.d.ts.map +1 -1
- package/dist/core/waterRenderer.d.ts +4 -0
- package/dist/core/waterRenderer.d.ts.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/water-distortion.cjs +19 -11
- package/dist/water-distortion.cjs.map +1 -1
- package/dist/water-distortion.js +385 -336
- package/dist/water-distortion.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"water-distortion.js","sources":["../src/core/math.ts","../src/core/waterRenderer.ts","../src/core/waterInteraction.ts","../src/WaterDistortion.tsx"],"sourcesContent":["export interface Vector2 {\n x: number;\n y: number;\n}\n\nexport function clamp(value: number, min: number, max: number): number {\n return Math.min(max, Math.max(min, value));\n}\n\nexport function distance(a: Vector2, b: Vector2): number {\n return Math.hypot(b.x - a.x, b.y - a.y);\n}\n\nexport function lerp(a: number, b: number, amount: number): number {\n return a + (b - a) * amount;\n}\n\nexport function normalize(vector: Vector2): Vector2 {\n const length = Math.hypot(vector.x, vector.y);\n\n if (length < 0.0001) {\n return { x: 0, y: 0 };\n }\n\n return {\n x: vector.x / length,\n y: vector.y / length\n };\n}\n\nexport function smoothVector(\n previous: Vector2,\n next: Vector2,\n amount: number\n): Vector2 {\n return {\n x: lerp(previous.x, next.x, amount),\n y: lerp(previous.y, next.y, amount)\n };\n}\n","import type { WaterDisturbance } from \"./waterInteraction\";\n\nexport type WaterRenderMode = \"dom\" | \"texture\" | \"canvas\";\nexport type WaterTextureSource = TexImageSource | string;\n\nexport interface WaterRendererSettings {\n mode: WaterRenderMode;\n damping: number;\n waveSpeed: number;\n normalScale: number;\n refractionStrength: number;\n specularIntensity: number;\n crestIntensity: number;\n causticIntensity: number;\n simulationResolution: number;\n texture?: WaterTextureSource;\n}\n\nexport interface WaterActivityThresholds {\n gradient: number;\n curvature: number;\n trough: number;\n velocity: number;\n}\n\n/** @internal */\nexport interface WaterHighlightColor {\n r: number;\n g: number;\n b: number;\n}\n\n/** @internal */\nexport interface WaterDomHighlightOverlay {\n color: WaterHighlightColor;\n alpha: number;\n}\n\ntype WaterGL = WebGLRenderingContext | WebGL2RenderingContext;\n\ninterface ProgramInfo {\n program: WebGLProgram;\n position: number;\n}\n\nconst MAX_WAKE_SEGMENTS = 24;\nconst CAUSTIC_MAP_SIZE = 128;\nconst CAUSTIC_CELL_COUNT = 8;\nconst TAU = Math.PI * 2;\n/** @internal */\nexport const DOM_HIGHLIGHT_SETTINGS = {\n causticGain: 0.1,\n screenCompensation: 1.35,\n maxAlpha: 0.9\n} as const;\nconst DEFAULT_ACTIVITY_THRESHOLDS: WaterActivityThresholds = {\n gradient: 0.0008,\n curvature: 0.0008,\n trough: 0.006,\n velocity: 0.0008\n};\nconst VERTEX_SHADER = `\nattribute vec2 a_position;\nvarying vec2 v_uv;\n\nvoid main() {\n v_uv = a_position * 0.5 + 0.5;\n gl_Position = vec4(a_position, 0.0, 1.0);\n}\n`;\n\nconst SIMULATION_SHADER = `\nprecision highp float;\n\n#define MAX_WAKE_SEGMENTS ${MAX_WAKE_SEGMENTS}\n\nvarying vec2 v_uv;\n\nuniform sampler2D u_state;\nuniform vec2 u_texel;\nuniform float u_delta;\nuniform float u_damping;\nuniform float u_stiffness;\nuniform float u_aspect;\nuniform int u_wakeCount;\nuniform vec4 u_wakeA[MAX_WAKE_SEGMENTS];\nuniform vec4 u_wakeB[MAX_WAKE_SEGMENTS];\nuniform vec4 u_wakeShape[MAX_WAKE_SEGMENTS];\n\nfloat segmentWake(vec2 uv, vec4 wakeA, vec4 wakeB, vec4 shape) {\n vec2 a = wakeA.xy;\n vec2 b = wakeB.xy;\n vec2 scale = vec2(u_aspect, 1.0);\n vec2 p = uv * scale;\n vec2 start = a * scale;\n vec2 end = b * scale;\n vec2 segment = end - start;\n float segmentLength = max(length(segment), 0.000001);\n vec2 dir = segment / segmentLength;\n vec2 normal = vec2(-dir.y, dir.x);\n float longitudinal = dot(p - start, dir);\n float clampedLongitudinal = clamp(longitudinal, 0.0, segmentLength);\n vec2 closest = start + dir * clampedLongitudinal;\n vec2 delta = p - closest;\n float perpendicular = abs(dot(delta, normal));\n float safeRadius = max(wakeA.z, 0.00001);\n float wakeStrength = wakeA.w;\n float wakeLength = max(wakeB.z, safeRadius);\n float troughStrength = shape.x;\n float ridgeStrength = shape.y;\n float ridgeOffset = max(shape.z, safeRadius * 0.35);\n float minFeatureWidth = u_texel.y * 2.25;\n float troughWidth = max(safeRadius * 0.82, minFeatureWidth);\n float ridgeWidth = max(safeRadius * 0.9, minFeatureWidth);\n float signedFromHead = dot(p - end, dir);\n float behindDistance = max(-signedFromHead, 0.0);\n float aheadDistance = max(signedFromHead, 0.0);\n float frontMask = 1.0 - smoothstep(safeRadius * 0.35, safeRadius * 1.8, aheadDistance);\n float trailMask = 1.0 - smoothstep(safeRadius * 0.5, wakeLength, behindDistance);\n float segmentMask =\n smoothstep(-safeRadius, safeRadius * 0.35, longitudinal) *\n (1.0 - smoothstep(segmentLength + wakeLength * 0.18, segmentLength + wakeLength, longitudinal));\n float pressureMask = frontMask * segmentMask;\n float centerTrough = exp(-pow(perpendicular / troughWidth, 2.0));\n float sideFade = 1.0 - smoothstep(safeRadius * 0.9, safeRadius * 2.35, perpendicular);\n float sideRidges =\n exp(-pow((perpendicular - ridgeOffset) / ridgeWidth, 2.0)) *\n sideFade;\n float trough = -centerTrough * troughStrength * pressureMask * (0.58 + trailMask * 0.42);\n float ridges = sideRidges * ridgeStrength * 0.5 * pressureMask * (0.36 + trailMask * 0.64);\n\n return wakeStrength * (trough + ridges);\n}\n\nvoid main() {\n vec4 state = texture2D(u_state, v_uv);\n float height = state.r;\n float velocity = state.g;\n\n float left = texture2D(u_state, v_uv - vec2(u_texel.x, 0.0)).r;\n float right = texture2D(u_state, v_uv + vec2(u_texel.x, 0.0)).r;\n float down = texture2D(u_state, v_uv - vec2(0.0, u_texel.y)).r;\n float up = texture2D(u_state, v_uv + vec2(0.0, u_texel.y)).r;\n float neighborAverage = (left + right + down + up) * 0.25;\n\n velocity += (neighborAverage - height) * u_stiffness * u_delta;\n\n for (int i = 0; i < MAX_WAKE_SEGMENTS; i++) {\n if (i >= u_wakeCount) {\n break;\n }\n\n float wake = segmentWake(v_uv, u_wakeA[i], u_wakeB[i], u_wakeShape[i]);\n\n velocity += wake * 0.12;\n height += wake * 0.014;\n }\n\n velocity *= pow(u_damping, u_delta);\n height *= pow(0.9985, u_delta);\n height += velocity * u_delta;\n\n gl_FragColor = vec4(height, velocity, 0.0, 1.0);\n}\n`;\n\nconst MATERIAL_SHADER = `\nprecision highp float;\n\nvarying vec2 v_uv;\n\nuniform sampler2D u_state;\nuniform sampler2D u_background;\nuniform sampler2D u_causticMap;\nuniform vec2 u_texel;\nuniform float u_domMode;\nuniform float u_normalScale;\nuniform float u_refractionStrength;\nuniform float u_specularIntensity;\nuniform float u_crestIntensity;\nuniform float u_causticIntensity;\nuniform float u_time;\n\nconst float DOM_CAUSTIC_GAIN = ${DOM_HIGHLIGHT_SETTINGS.causticGain.toFixed(2)};\nconst float DOM_SCREEN_COMPENSATION = ${DOM_HIGHLIGHT_SETTINGS.screenCompensation.toFixed(2)};\nconst float DOM_MAX_ALPHA = ${DOM_HIGHLIGHT_SETTINGS.maxAlpha.toFixed(2)};\n\nvec4 causticLayer(vec2 uv, vec2 bend, mat2 rotation, float scale, vec2 drift) {\n vec2 p = rotation * (uv * scale + drift * u_time);\n\n return texture2D(u_causticMap, p + bend * 0.22);\n}\n\nvoid main() {\n vec4 center = texture2D(u_state, v_uv);\n float height = center.r;\n float velocity = center.g;\n float left = texture2D(u_state, v_uv - vec2(u_texel.x, 0.0)).r;\n float right = texture2D(u_state, v_uv + vec2(u_texel.x, 0.0)).r;\n float down = texture2D(u_state, v_uv - vec2(0.0, u_texel.y)).r;\n float up = texture2D(u_state, v_uv + vec2(0.0, u_texel.y)).r;\n float dx = right - left;\n float dy = up - down;\n float signedCurvature = left + right + down + up - height * 4.0;\n vec3 normal = normalize(vec3(-dx * u_normalScale, 1.0, -dy * u_normalScale));\n vec2 refractedUv = clamp(\n v_uv + normal.xz * u_refractionStrength * 0.025,\n vec2(0.001),\n vec2(0.999)\n );\n\n vec3 base = texture2D(u_background, refractedUv).rgb;\n\n float gradient = length(vec2(dx, dy)) * u_normalScale;\n float crest = smoothstep(0.012, 0.24, gradient);\n float trough = smoothstep(0.018, 0.09, -height);\n float heightActivity = smoothstep(0.0005, 0.018, abs(height));\n float aspect = u_texel.y / u_texel.x;\n vec2 causticUv = vec2(v_uv.x * aspect, v_uv.y);\n float rawActivity =\n gradient * 0.72 +\n abs(signedCurvature) * u_normalScale * 0.42 +\n abs(velocity) * 14.0 +\n heightActivity * 0.22;\n float edgeFade = smoothstep(0.0, 0.52, rawActivity);\n float visibleCrest = crest * edgeFade;\n float visibleTrough = trough * edgeFade;\n vec2 causticBend = normal.xz * (0.22 + visibleCrest * 0.08);\n float slopeActivity = smoothstep(0.004, 0.18, gradient);\n float convergence = smoothstep(0.004, 0.065, max(signedCurvature * u_normalScale, 0.0));\n float defocus = smoothstep(0.004, 0.065, max(-signedCurvature * u_normalScale, 0.0));\n float velocityActivity = smoothstep(0.0006, 0.006, abs(velocity));\n float activitySignal =\n slopeActivity * 0.38 +\n convergence * 0.58 +\n velocityActivity * 0.28 +\n heightActivity * 0.22;\n float activityGate = edgeFade * smoothstep(0.0, 0.58, activitySignal);\n float causticFocus =\n activityGate *\n (1.0 - defocus * 0.65) *\n mix(0.35, 1.25, convergence);\n vec4 causticA = causticLayer(\n causticUv,\n causticBend,\n mat2(0.94, -0.34, 0.34, 0.94),\n 1.45,\n vec2(0.032, -0.021)\n );\n vec4 causticB = causticLayer(\n causticUv,\n -causticBend * 0.72,\n mat2(0.62, 0.78, -0.78, 0.62),\n 2.05,\n vec2(-0.019, 0.034)\n );\n float sparklePhase = sin(u_time * 8.0 + causticA.b * 6.28318 + causticB.a * 3.14159);\n float primaryLines = smoothstep(0.10, 0.76, causticA.r * 0.72 + causticB.g * 0.18);\n float softFill = smoothstep(0.08, 0.62, causticA.g) * 0.2;\n float sparkle = smoothstep(\n 0.62,\n 0.96,\n max(causticA.a, causticB.b) * (0.9 + sparklePhase * 0.1)\n );\n float detailModulation = mix(0.58, 1.2, causticB.b);\n float brightnessModulation = mix(0.7, 1.12, causticA.b);\n float causticPattern = clamp(\n (primaryLines * detailModulation + softFill + sparkle * 0.1) *\n brightnessModulation,\n 0.0,\n 1.0\n );\n float caustic = causticPattern * causticFocus;\n float baseLuminance = dot(base, vec3(0.2126, 0.7152, 0.0722));\n float causticEnergy = 1.0 - exp(-caustic * u_causticIntensity * 0.82);\n float textureCausticGain = mix(0.12, 0.045, smoothstep(0.46, 0.9, baseLuminance));\n vec3 lightDirection = normalize(vec3(-0.32, 0.64, 0.42));\n vec3 viewDirection = vec3(0.0, 1.0, 0.0);\n vec3 halfDirection = normalize(lightDirection + viewDirection);\n float specular = pow(max(dot(normal, halfDirection), 0.0), 82.0) * activityGate;\n\n float causticGain = u_domMode > 0.5 ? DOM_CAUSTIC_GAIN : textureCausticGain;\n vec3 highlight =\n vec3(1.0, 0.98, 0.88) * specular * u_specularIntensity +\n vec3(0.75, 0.95, 1.0) * visibleCrest * u_crestIntensity * 0.11 +\n vec3(0.84, 1.0, 0.92) * causticEnergy * causticGain;\n\n if (u_domMode > 0.5) {\n float domEnergy = max(max(highlight.r, highlight.g), highlight.b);\n vec3 overlay = highlight / max(domEnergy, 0.00001);\n float alpha = clamp(domEnergy * DOM_SCREEN_COMPENSATION, 0.0, DOM_MAX_ALPHA);\n\n gl_FragColor = vec4(overlay, alpha);\n return;\n }\n\n vec3 color = base + highlight - vec3(0.015, 0.055, 0.070) * visibleTrough * 0.45;\n gl_FragColor = vec4(color, 1.0);\n}\n`;\n\nexport class HeightfieldWaterRenderer {\n private readonly gl: WaterGL;\n private readonly isWebGL2: boolean;\n private readonly canLinearFloat: boolean;\n private readonly quadBuffer: WebGLBuffer;\n private readonly simulationProgram: ProgramInfo;\n private readonly materialProgram: ProgramInfo;\n private readonly backgroundTexture: WebGLTexture;\n private readonly causticTexture: WebGLTexture;\n private stateTextures: [WebGLTexture, WebGLTexture] | undefined;\n private framebuffers: [WebGLFramebuffer, WebGLFramebuffer] | undefined;\n private readIndex = 0;\n private simWidth = 1;\n private simHeight = 1;\n private cssWidth = 1;\n private cssHeight = 1;\n private textureSource: WaterTextureSource | undefined;\n private textureImage: TexImageSource | undefined;\n private textureReady = false;\n private textureNeedsUpload = false;\n private activityPixels: Float32Array | undefined;\n private readonly wakeAUniforms = new Float32Array(MAX_WAKE_SEGMENTS * 4);\n private readonly wakeBUniforms = new Float32Array(MAX_WAKE_SEGMENTS * 4);\n private readonly wakeShapeUniforms = new Float32Array(MAX_WAKE_SEGMENTS * 4);\n\n constructor(\n private readonly canvas: HTMLCanvasElement,\n private readonly requestRender: () => void = () => undefined\n ) {\n const { gl, isWebGL2, canLinearFloat } = createContext(canvas);\n\n this.gl = gl;\n this.isWebGL2 = isWebGL2;\n this.canLinearFloat = canLinearFloat;\n this.quadBuffer = mustCreate(gl.createBuffer(), \"WebGL buffer\");\n this.simulationProgram = createProgramInfo(gl, VERTEX_SHADER, SIMULATION_SHADER);\n this.materialProgram = createProgramInfo(gl, VERTEX_SHADER, MATERIAL_SHADER);\n this.backgroundTexture = mustCreate(gl.createTexture(), \"WebGL texture\");\n this.causticTexture = mustCreate(gl.createTexture(), \"WebGL texture\");\n\n gl.bindBuffer(gl.ARRAY_BUFFER, this.quadBuffer);\n gl.bufferData(\n gl.ARRAY_BUFFER,\n new Float32Array([-1, -1, 1, -1, -1, 1, 1, 1]),\n gl.STATIC_DRAW\n );\n gl.disable(gl.DEPTH_TEST);\n gl.disable(gl.STENCIL_TEST);\n gl.disable(gl.BLEND);\n this.initializeBackgroundTexture();\n this.initializeCausticTexture();\n this.resize(1, 1, 1, 192);\n }\n\n resize(\n cssWidth: number,\n cssHeight: number,\n pixelRatio: number,\n simulationResolution: number\n ): void {\n this.cssWidth = Math.max(1, cssWidth);\n this.cssHeight = Math.max(1, cssHeight);\n const ratio = Math.min(2, Math.max(1, pixelRatio || 1));\n const renderWidth = Math.max(1, Math.round(this.cssWidth * ratio));\n const renderHeight = Math.max(1, Math.round(this.cssHeight * ratio));\n\n if (this.canvas.width !== renderWidth || this.canvas.height !== renderHeight) {\n this.canvas.width = renderWidth;\n this.canvas.height = renderHeight;\n }\n\n const longestSide = Math.max(32, Math.round(simulationResolution));\n const aspect = this.cssWidth / this.cssHeight;\n const nextSimWidth =\n aspect >= 1 ? longestSide : Math.max(1, Math.round(longestSide * aspect));\n const nextSimHeight =\n aspect >= 1 ? Math.max(1, Math.round(longestSide / aspect)) : longestSide;\n\n if (nextSimWidth === this.simWidth && nextSimHeight === this.simHeight) {\n return;\n }\n\n this.simWidth = nextSimWidth;\n this.simHeight = nextSimHeight;\n this.recreateState();\n }\n\n setTextureSource(source: WaterTextureSource | undefined): void {\n if (source === this.textureSource) {\n return;\n }\n\n this.textureSource = source;\n this.textureImage = undefined;\n this.textureReady = false;\n this.textureNeedsUpload = false;\n\n if (!source) {\n return;\n }\n\n if (typeof source !== \"string\") {\n this.textureImage = source;\n this.textureNeedsUpload = true;\n return;\n }\n\n const image = new Image();\n\n image.crossOrigin = \"anonymous\";\n image.onload = () => {\n if (this.textureSource === source) {\n this.textureImage = image;\n this.textureNeedsUpload = true;\n this.requestRender();\n }\n };\n image.onerror = () => {\n if (this.textureSource === source) {\n this.textureImage = undefined;\n this.textureReady = false;\n this.textureNeedsUpload = false;\n }\n };\n image.src = source;\n }\n\n step(\n disturbances: readonly WaterDisturbance[],\n settings: WaterRendererSettings,\n delta: number\n ): void {\n if (!this.stateTextures || !this.framebuffers) {\n return;\n }\n\n const gl = this.gl;\n const writeIndex = 1 - this.readIndex;\n\n gl.useProgram(this.simulationProgram.program);\n gl.bindFramebuffer(gl.FRAMEBUFFER, this.framebuffers[writeIndex]);\n gl.viewport(0, 0, this.simWidth, this.simHeight);\n gl.activeTexture(gl.TEXTURE0);\n gl.bindTexture(gl.TEXTURE_2D, this.stateTextures[this.readIndex]);\n this.prepareQuad(this.simulationProgram);\n this.setSimulationUniforms(disturbances, settings, delta);\n gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);\n gl.bindFramebuffer(gl.FRAMEBUFFER, null);\n this.readIndex = writeIndex;\n }\n\n render(settings: WaterRendererSettings, timeSeconds = 0): void {\n const gl = this.gl;\n\n if (!this.stateTextures) {\n return;\n }\n\n if (settings.texture) {\n this.setTextureSource(settings.texture);\n } else {\n this.setTextureSource(undefined);\n }\n\n this.uploadTextureIfNeeded(settings);\n\n gl.useProgram(this.materialProgram.program);\n gl.bindFramebuffer(gl.FRAMEBUFFER, null);\n gl.viewport(0, 0, this.canvas.width, this.canvas.height);\n gl.clearColor(0, 0, 0, 0);\n gl.clear(gl.COLOR_BUFFER_BIT);\n\n if (settings.mode !== \"dom\" && !this.textureReady) {\n return;\n }\n\n gl.activeTexture(gl.TEXTURE0);\n gl.bindTexture(gl.TEXTURE_2D, this.stateTextures[this.readIndex]);\n gl.activeTexture(gl.TEXTURE1);\n gl.bindTexture(gl.TEXTURE_2D, this.backgroundTexture);\n gl.activeTexture(gl.TEXTURE2);\n gl.bindTexture(gl.TEXTURE_2D, this.causticTexture);\n this.prepareQuad(this.materialProgram);\n this.setMaterialUniforms(settings, timeSeconds);\n gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);\n }\n\n hasVisibleActivity(): boolean {\n if (!this.framebuffers) {\n return false;\n }\n\n const gl = this.gl;\n const framebuffer = this.framebuffers[this.readIndex];\n const pixelCount = this.simWidth * this.simHeight * 4;\n\n if (!this.activityPixels || this.activityPixels.length !== pixelCount) {\n this.activityPixels = new Float32Array(pixelCount);\n }\n\n gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);\n\n try {\n gl.readPixels(\n 0,\n 0,\n this.simWidth,\n this.simHeight,\n gl.RGBA,\n gl.FLOAT,\n this.activityPixels\n );\n } finally {\n gl.bindFramebuffer(gl.FRAMEBUFFER, null);\n }\n\n return hasVisibleWaterActivity(\n this.activityPixels,\n this.simWidth,\n this.simHeight\n );\n }\n\n clear(): void {\n const gl = this.gl;\n\n if (this.framebuffers) {\n gl.viewport(0, 0, this.simWidth, this.simHeight);\n\n for (const framebuffer of this.framebuffers) {\n gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);\n gl.clearColor(0, 0, 0, 1);\n gl.clear(gl.COLOR_BUFFER_BIT);\n }\n }\n\n gl.bindFramebuffer(gl.FRAMEBUFFER, null);\n gl.viewport(0, 0, this.canvas.width, this.canvas.height);\n gl.clearColor(0, 0, 0, 0);\n gl.clear(gl.COLOR_BUFFER_BIT);\n }\n\n dispose(): void {\n const gl = this.gl;\n\n this.stateTextures?.forEach((texture) => gl.deleteTexture(texture));\n this.framebuffers?.forEach((framebuffer) => gl.deleteFramebuffer(framebuffer));\n gl.deleteTexture(this.backgroundTexture);\n gl.deleteTexture(this.causticTexture);\n gl.deleteBuffer(this.quadBuffer);\n gl.deleteProgram(this.simulationProgram.program);\n gl.deleteProgram(this.materialProgram.program);\n }\n\n private recreateState(): void {\n const gl = this.gl;\n\n this.stateTextures?.forEach((texture) => gl.deleteTexture(texture));\n this.framebuffers?.forEach((framebuffer) => gl.deleteFramebuffer(framebuffer));\n\n const firstTexture = this.createStateTexture();\n const secondTexture = this.createStateTexture();\n const firstFramebuffer = this.createFramebuffer(firstTexture);\n const secondFramebuffer = this.createFramebuffer(secondTexture);\n\n this.stateTextures = [firstTexture, secondTexture];\n this.framebuffers = [firstFramebuffer, secondFramebuffer];\n this.readIndex = 0;\n this.clear();\n }\n\n private createStateTexture(): WebGLTexture {\n const gl = this.gl;\n const texture = mustCreate(gl.createTexture(), \"WebGL texture\");\n\n gl.bindTexture(gl.TEXTURE_2D, texture);\n gl.texParameteri(\n gl.TEXTURE_2D,\n gl.TEXTURE_MIN_FILTER,\n this.canLinearFloat ? gl.LINEAR : gl.NEAREST\n );\n gl.texParameteri(\n gl.TEXTURE_2D,\n gl.TEXTURE_MAG_FILTER,\n this.canLinearFloat ? gl.LINEAR : gl.NEAREST\n );\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);\n\n if (this.isWebGL2) {\n const gl2 = gl as WebGL2RenderingContext;\n\n gl2.texImage2D(\n gl2.TEXTURE_2D,\n 0,\n gl2.RGBA32F,\n this.simWidth,\n this.simHeight,\n 0,\n gl2.RGBA,\n gl2.FLOAT,\n null\n );\n } else {\n gl.texImage2D(\n gl.TEXTURE_2D,\n 0,\n gl.RGBA,\n this.simWidth,\n this.simHeight,\n 0,\n gl.RGBA,\n gl.FLOAT,\n null\n );\n }\n\n return texture;\n }\n\n private createFramebuffer(texture: WebGLTexture): WebGLFramebuffer {\n const gl = this.gl;\n const framebuffer = mustCreate(gl.createFramebuffer(), \"WebGL framebuffer\");\n\n gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);\n gl.framebufferTexture2D(\n gl.FRAMEBUFFER,\n gl.COLOR_ATTACHMENT0,\n gl.TEXTURE_2D,\n texture,\n 0\n );\n\n if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) !== gl.FRAMEBUFFER_COMPLETE) {\n throw new Error(\"WaterDistortion could not create a float simulation target.\");\n }\n\n gl.bindFramebuffer(gl.FRAMEBUFFER, null);\n\n return framebuffer;\n }\n\n private initializeBackgroundTexture(): void {\n const gl = this.gl;\n\n gl.bindTexture(gl.TEXTURE_2D, this.backgroundTexture);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);\n gl.texImage2D(\n gl.TEXTURE_2D,\n 0,\n gl.RGBA,\n 1,\n 1,\n 0,\n gl.RGBA,\n gl.UNSIGNED_BYTE,\n new Uint8Array([18, 28, 26, 255])\n );\n }\n\n private initializeCausticTexture(): void {\n const gl = this.gl;\n\n gl.bindTexture(gl.TEXTURE_2D, this.causticTexture);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT);\n gl.texImage2D(\n gl.TEXTURE_2D,\n 0,\n gl.RGBA,\n CAUSTIC_MAP_SIZE,\n CAUSTIC_MAP_SIZE,\n 0,\n gl.RGBA,\n gl.UNSIGNED_BYTE,\n createCausticMap()\n );\n gl.generateMipmap(gl.TEXTURE_2D);\n }\n\n private uploadTextureIfNeeded(settings: WaterRendererSettings): void {\n if (\n settings.mode === \"dom\" ||\n !this.textureImage ||\n (!this.textureNeedsUpload && !shouldUploadEveryFrame(this.textureImage))\n ) {\n return;\n }\n\n const gl = this.gl;\n\n try {\n gl.bindTexture(gl.TEXTURE_2D, this.backgroundTexture);\n gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1);\n gl.texImage2D(\n gl.TEXTURE_2D,\n 0,\n gl.RGBA,\n gl.RGBA,\n gl.UNSIGNED_BYTE,\n this.textureImage\n );\n gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 0);\n this.textureReady = true;\n this.textureNeedsUpload = false;\n } catch {\n this.textureReady = false;\n this.textureNeedsUpload = false;\n }\n }\n\n private prepareQuad(program: ProgramInfo): void {\n const gl = this.gl;\n\n gl.bindBuffer(gl.ARRAY_BUFFER, this.quadBuffer);\n gl.enableVertexAttribArray(program.position);\n gl.vertexAttribPointer(program.position, 2, gl.FLOAT, false, 0, 0);\n }\n\n private setSimulationUniforms(\n disturbances: readonly WaterDisturbance[],\n settings: WaterRendererSettings,\n delta: number\n ): void {\n const gl = this.gl;\n const program = this.simulationProgram.program;\n const count = Math.min(disturbances.length, MAX_WAKE_SEGMENTS);\n const wakeA = this.wakeAUniforms;\n const wakeB = this.wakeBUniforms;\n const wakeShape = this.wakeShapeUniforms;\n const start = Math.max(0, disturbances.length - MAX_WAKE_SEGMENTS);\n\n wakeA.fill(0);\n wakeB.fill(0);\n wakeShape.fill(0);\n\n for (let index = 0; index < count; index += 1) {\n const disturbance = disturbances[start + index];\n const offset = index * 4;\n\n wakeA[offset] = disturbance.ax;\n wakeA[offset + 1] = disturbance.ay;\n wakeA[offset + 2] = disturbance.radius;\n wakeA[offset + 3] = disturbance.wakeStrength;\n wakeB[offset] = disturbance.bx;\n wakeB[offset + 1] = disturbance.by;\n wakeB[offset + 2] = disturbance.wakeLength;\n wakeB[offset + 3] = disturbance.velocity;\n wakeShape[offset] = disturbance.troughStrength;\n wakeShape[offset + 1] = disturbance.ridgeStrength;\n wakeShape[offset + 2] = disturbance.ridgeOffset;\n }\n\n gl.uniform1i(getUniform(gl, program, \"u_state\"), 0);\n gl.uniform2f(getUniform(gl, program, \"u_texel\"), 1 / this.simWidth, 1 / this.simHeight);\n gl.uniform1f(getUniform(gl, program, \"u_delta\"), delta);\n gl.uniform1f(getUniform(gl, program, \"u_damping\"), settings.damping);\n gl.uniform1f(getUniform(gl, program, \"u_stiffness\"), settings.waveSpeed);\n gl.uniform1f(getUniform(gl, program, \"u_aspect\"), this.cssWidth / this.cssHeight);\n gl.uniform1i(getUniform(gl, program, \"u_wakeCount\"), count);\n gl.uniform4fv(getUniform(gl, program, \"u_wakeA[0]\"), wakeA);\n gl.uniform4fv(getUniform(gl, program, \"u_wakeB[0]\"), wakeB);\n gl.uniform4fv(getUniform(gl, program, \"u_wakeShape[0]\"), wakeShape);\n }\n\n private setMaterialUniforms(\n settings: WaterRendererSettings,\n timeSeconds: number\n ): void {\n const gl = this.gl;\n const program = this.materialProgram.program;\n\n gl.uniform1i(getUniform(gl, program, \"u_state\"), 0);\n gl.uniform1i(getUniform(gl, program, \"u_background\"), 1);\n gl.uniform1i(getUniform(gl, program, \"u_causticMap\"), 2);\n gl.uniform2f(getUniform(gl, program, \"u_texel\"), 1 / this.simWidth, 1 / this.simHeight);\n gl.uniform1f(getUniform(gl, program, \"u_domMode\"), settings.mode === \"dom\" ? 1 : 0);\n gl.uniform1f(getUniform(gl, program, \"u_normalScale\"), settings.normalScale);\n gl.uniform1f(getUniform(gl, program, \"u_refractionStrength\"), settings.refractionStrength);\n gl.uniform1f(getUniform(gl, program, \"u_specularIntensity\"), settings.specularIntensity);\n gl.uniform1f(getUniform(gl, program, \"u_crestIntensity\"), settings.crestIntensity);\n gl.uniform1f(getUniform(gl, program, \"u_causticIntensity\"), settings.causticIntensity);\n gl.uniform1f(getUniform(gl, program, \"u_time\"), timeSeconds % 1000);\n }\n}\n\n/** @internal */\nexport function createCausticMap(): Uint8Array {\n const data = new Uint8Array(CAUSTIC_MAP_SIZE * CAUSTIC_MAP_SIZE * 4);\n\n for (let y = 0; y < CAUSTIC_MAP_SIZE; y += 1) {\n for (let x = 0; x < CAUSTIC_MAP_SIZE; x += 1) {\n const u = (x + 0.5) / CAUSTIC_MAP_SIZE;\n const v = (y + 0.5) / CAUSTIC_MAP_SIZE;\n const red = Math.round(createCausticChannel(u, v, 0.0) * 255);\n const green = Math.round(createCausticChannel(u, v, 11.0) * 255);\n const blue = Math.round(createCausticChannel(u, v, 23.0) * 255);\n const alpha = Math.round(createCausticChannel(u, v, 37.0) * 255);\n const index = (y * CAUSTIC_MAP_SIZE + x) * 4;\n\n data[index] = red;\n data[index + 1] = green;\n data[index + 2] = blue;\n data[index + 3] = alpha;\n }\n }\n\n return data;\n}\n\nfunction createCausticChannel(u: number, v: number, seed: number): number {\n const warpX =\n Math.sin(TAU * (v * 2 + seed * 0.013)) * 0.12 +\n Math.sin(TAU * (u * 3 + v + seed * 0.021)) * 0.06;\n const warpY =\n Math.cos(TAU * (u * 2 + seed * 0.017)) * 0.12 +\n Math.sin(TAU * (v * 3 - u + seed * 0.019)) * 0.06;\n const sampleX = u * CAUSTIC_CELL_COUNT + warpX;\n const sampleY = v * CAUSTIC_CELL_COUNT + warpY;\n const cellX = Math.floor(sampleX);\n const cellY = Math.floor(sampleY);\n let nearest = Number.POSITIVE_INFINITY;\n let secondNearest = Number.POSITIVE_INFINITY;\n let nearestCellX = 0;\n let nearestCellY = 0;\n\n for (let offsetY = -1; offsetY <= 1; offsetY += 1) {\n for (let offsetX = -1; offsetX <= 1; offsetX += 1) {\n const candidateX = cellX + offsetX;\n const candidateY = cellY + offsetY;\n const wrappedX = positiveModulo(candidateX, CAUSTIC_CELL_COUNT);\n const wrappedY = positiveModulo(candidateY, CAUSTIC_CELL_COUNT);\n const pointX =\n candidateX + 0.16 + hash2(wrappedX, wrappedY, seed) * 0.68;\n const pointY =\n candidateY + 0.16 + hash2(wrappedX, wrappedY, seed + 1) * 0.68;\n const distance = Math.hypot(sampleX - pointX, sampleY - pointY);\n\n if (distance < nearest) {\n secondNearest = nearest;\n nearest = distance;\n nearestCellX = wrappedX;\n nearestCellY = wrappedY;\n } else if (distance < secondNearest) {\n secondNearest = distance;\n }\n }\n }\n\n const edgeDistance = secondNearest - nearest;\n const core = 1 - smoothstepNumber(0.025, 0.13, edgeDistance);\n const glow = 1 - smoothstepNumber(0.08, 0.34, edgeDistance);\n const variation = 0.74 + hash2(nearestCellX, nearestCellY, seed + 2) * 0.26;\n const value = core * core * 0.58 + glow * 0.34;\n\n return clamp01(Math.pow(value * variation, 1.12));\n}\n\nfunction hash2(x: number, y: number, seed: number): number {\n const value = Math.sin(x * 127.1 + y * 311.7 + seed * 74.7) * 43758.5453123;\n\n return value - Math.floor(value);\n}\n\nfunction positiveModulo(value: number, divisor: number): number {\n return ((value % divisor) + divisor) % divisor;\n}\n\nfunction smoothstepNumber(edge0: number, edge1: number, value: number): number {\n const amount = clamp01((value - edge0) / (edge1 - edge0));\n\n return amount * amount * (3 - amount * 2);\n}\n\nfunction clamp01(value: number): number {\n return Math.min(1, Math.max(0, value));\n}\n\nfunction createContext(canvas: HTMLCanvasElement): {\n gl: WaterGL;\n isWebGL2: boolean;\n canLinearFloat: boolean;\n} {\n const attributes: WebGLContextAttributes = {\n alpha: true,\n antialias: false,\n depth: false,\n stencil: false,\n premultipliedAlpha: false,\n preserveDrawingBuffer: false\n };\n const webgl2 = canvas.getContext(\"webgl2\", attributes);\n\n if (webgl2) {\n if (!webgl2.getExtension(\"EXT_color_buffer_float\")) {\n throw new Error(\"WaterDistortion requires float render targets.\");\n }\n\n return {\n gl: webgl2,\n isWebGL2: true,\n canLinearFloat: !!webgl2.getExtension(\"OES_texture_float_linear\")\n };\n }\n\n const webgl1 =\n (canvas.getContext(\"webgl\", attributes) as WebGLRenderingContext | null) ||\n (canvas.getContext(\n \"experimental-webgl\",\n attributes\n ) as WebGLRenderingContext | null);\n\n if (!webgl1) {\n throw new Error(\"WaterDistortion requires WebGL.\");\n }\n\n if (\n !webgl1.getExtension(\"OES_texture_float\") ||\n (!webgl1.getExtension(\"WEBGL_color_buffer_float\") &&\n !webgl1.getExtension(\"EXT_color_buffer_float\"))\n ) {\n throw new Error(\"WaterDistortion requires float texture support.\");\n }\n\n return {\n gl: webgl1,\n isWebGL2: false,\n canLinearFloat: !!webgl1.getExtension(\"OES_texture_float_linear\")\n };\n}\n\nfunction createProgramInfo(\n gl: WaterGL,\n vertexSource: string,\n fragmentSource: string\n): ProgramInfo {\n const vertexShader = compileShader(gl, gl.VERTEX_SHADER, vertexSource);\n const fragmentShader = compileShader(gl, gl.FRAGMENT_SHADER, fragmentSource);\n const program = mustCreate(gl.createProgram(), \"WebGL program\");\n\n gl.attachShader(program, vertexShader);\n gl.attachShader(program, fragmentShader);\n gl.linkProgram(program);\n gl.deleteShader(vertexShader);\n gl.deleteShader(fragmentShader);\n\n if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {\n const error = gl.getProgramInfoLog(program) || \"Unknown shader link error.\";\n\n gl.deleteProgram(program);\n throw new Error(error);\n }\n\n const position = gl.getAttribLocation(program, \"a_position\");\n\n if (position < 0) {\n throw new Error(\"WaterDistortion could not bind its quad attribute.\");\n }\n\n return { program, position };\n}\n\nfunction compileShader(\n gl: WaterGL,\n type: number,\n source: string\n): WebGLShader {\n const shader = mustCreate(gl.createShader(type), \"WebGL shader\");\n\n gl.shaderSource(shader, source);\n gl.compileShader(shader);\n\n if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {\n const error = gl.getShaderInfoLog(shader) || \"Unknown shader compile error.\";\n\n gl.deleteShader(shader);\n throw new Error(error);\n }\n\n return shader;\n}\n\nfunction getUniform(\n gl: WaterGL,\n program: WebGLProgram,\n name: string\n): WebGLUniformLocation {\n const location = gl.getUniformLocation(program, name);\n\n if (!location) {\n throw new Error(`WaterDistortion could not bind uniform ${name}.`);\n }\n\n return location;\n}\n\nfunction mustCreate<T>(value: T | null, label: string): T {\n if (!value) {\n throw new Error(`WaterDistortion could not create ${label}.`);\n }\n\n return value;\n}\n\nfunction shouldUploadEveryFrame(source: TexImageSource): boolean {\n if (typeof HTMLCanvasElement !== \"undefined\" && source instanceof HTMLCanvasElement) {\n return true;\n }\n\n if (typeof HTMLVideoElement !== \"undefined\" && source instanceof HTMLVideoElement) {\n return true;\n }\n\n if (typeof OffscreenCanvas !== \"undefined\" && source instanceof OffscreenCanvas) {\n return true;\n }\n\n return false;\n}\n\nexport function hasVisibleWaterActivity(\n state: ArrayLike<number>,\n width: number,\n height: number,\n thresholds: WaterActivityThresholds = DEFAULT_ACTIVITY_THRESHOLDS\n): boolean {\n const safeWidth = Math.max(0, Math.floor(width));\n const safeHeight = Math.max(0, Math.floor(height));\n\n if (safeWidth === 0 || safeHeight === 0) {\n return false;\n }\n\n const readHeight = (x: number, y: number) =>\n state[(y * safeWidth + x) * 4] ?? 0;\n\n for (let y = 0; y < safeHeight; y += 1) {\n for (let x = 0; x < safeWidth; x += 1) {\n const index = (y * safeWidth + x) * 4;\n const current = state[index] ?? 0;\n const velocity = state[index + 1] ?? 0;\n\n if (\n current < -thresholds.trough ||\n Math.abs(velocity) > thresholds.velocity\n ) {\n return true;\n }\n\n const left = x > 0 ? readHeight(x - 1, y) : current;\n const right = x < safeWidth - 1 ? readHeight(x + 1, y) : current;\n const down = y > 0 ? readHeight(x, y - 1) : current;\n const up = y < safeHeight - 1 ? readHeight(x, y + 1) : current;\n const gradient = Math.hypot(right - left, up - down);\n const curvature = Math.abs(left + right + down + up - current * 4);\n\n if (\n gradient > thresholds.gradient ||\n curvature > thresholds.curvature\n ) {\n return true;\n }\n }\n }\n\n return false;\n}\n\n/** @internal */\nexport function mapHighlightToDomOverlay(\n highlight: WaterHighlightColor\n): WaterDomHighlightOverlay {\n const domEnergy = Math.max(0, highlight.r, highlight.g, highlight.b);\n const safeEnergy = Math.max(domEnergy, 0.00001);\n\n return {\n color: {\n r: Math.max(0, highlight.r) / safeEnergy,\n g: Math.max(0, highlight.g) / safeEnergy,\n b: Math.max(0, highlight.b) / safeEnergy\n },\n alpha: Math.min(\n DOM_HIGHLIGHT_SETTINGS.maxAlpha,\n domEnergy * DOM_HIGHLIGHT_SETTINGS.screenCompensation\n )\n };\n}\n","import { clamp, distance, lerp } from \"./math\";\n\nexport interface PointerSample {\n x: number;\n y: number;\n time: number;\n}\n\nexport interface WaterDisturbance {\n ax: number;\n ay: number;\n bx: number;\n by: number;\n radius: number;\n wakeStrength: number;\n troughStrength: number;\n ridgeStrength: number;\n ridgeOffset: number;\n wakeLength: number;\n velocity: number;\n}\n\nexport interface PointerDisturbanceOptions {\n width: number;\n height: number;\n interactionRadius: number;\n wakeStrength: number;\n troughStrength: number;\n ridgeStrength: number;\n ridgeOffset: number;\n wakeLength: number;\n velocityScale: number;\n velocityClamp: number;\n cursorSmoothing: number;\n segmentSpacing: number;\n}\n\nexport interface PointerEventLike {\n clientX: number;\n clientY: number;\n timeStamp: number;\n getCoalescedEvents?: () => PointerEventLike[];\n}\n\nexport interface BoundsLike {\n left: number;\n top: number;\n}\n\nconst DEFAULT_OPTIONS: PointerDisturbanceOptions = {\n width: 1,\n height: 1,\n interactionRadius: 25,\n wakeStrength: 0.54,\n troughStrength: 0.92,\n ridgeStrength: 0.46,\n ridgeOffset: 10,\n wakeLength: 84,\n velocityScale: 1,\n velocityClamp: 1.35,\n cursorSmoothing: 0.2,\n segmentSpacing: 18\n};\nconst MAX_SEGMENTS_PER_SAMPLE = 24;\n\nfunction normalizeOptions(\n options: Partial<PointerDisturbanceOptions>\n): PointerDisturbanceOptions {\n return {\n width: Math.max(1, options.width ?? DEFAULT_OPTIONS.width),\n height: Math.max(1, options.height ?? DEFAULT_OPTIONS.height),\n interactionRadius: Math.max(\n 1,\n options.interactionRadius ?? DEFAULT_OPTIONS.interactionRadius\n ),\n wakeStrength: Math.max(\n 0,\n options.wakeStrength ?? DEFAULT_OPTIONS.wakeStrength\n ),\n troughStrength: Math.max(\n 0,\n options.troughStrength ?? DEFAULT_OPTIONS.troughStrength\n ),\n ridgeStrength: Math.max(\n 0,\n options.ridgeStrength ?? DEFAULT_OPTIONS.ridgeStrength\n ),\n ridgeOffset: Math.max(0, options.ridgeOffset ?? DEFAULT_OPTIONS.ridgeOffset),\n wakeLength: Math.max(1, options.wakeLength ?? DEFAULT_OPTIONS.wakeLength),\n velocityScale: Math.max(\n 0.01,\n options.velocityScale ?? DEFAULT_OPTIONS.velocityScale\n ),\n velocityClamp: Math.max(\n 0.05,\n options.velocityClamp ?? DEFAULT_OPTIONS.velocityClamp\n ),\n cursorSmoothing: clamp(\n options.cursorSmoothing ?? DEFAULT_OPTIONS.cursorSmoothing,\n 0,\n 0.9\n ),\n segmentSpacing: Math.max(\n 1,\n options.segmentSpacing ?? DEFAULT_OPTIONS.segmentSpacing\n )\n };\n}\n\nexport function getPointerSamples(\n event: PointerEventLike,\n bounds: BoundsLike,\n now = event.timeStamp\n): PointerSample[] {\n const events =\n typeof event.getCoalescedEvents === \"function\"\n ? event.getCoalescedEvents()\n : [];\n const sourceEvents = events.length > 0 ? events : [event];\n const clockOffset = now - event.timeStamp;\n\n return sourceEvents.map((pointerEvent) => ({\n x: pointerEvent.clientX - bounds.left,\n y: pointerEvent.clientY - bounds.top,\n time: pointerEvent.timeStamp + clockOffset\n }));\n}\n\nexport class PointerDisturbanceTracker {\n private options: PointerDisturbanceOptions;\n private previous: PointerSample | undefined;\n private smoothedVelocity = 0;\n private readonly disturbances: WaterDisturbance[] = [];\n\n constructor(options: Partial<PointerDisturbanceOptions> = {}) {\n this.options = normalizeOptions(options);\n }\n\n configure(options: Partial<PointerDisturbanceOptions>): void {\n this.options = normalizeOptions({\n ...this.options,\n ...options\n });\n }\n\n reset(): void {\n this.previous = undefined;\n this.smoothedVelocity = 0;\n this.disturbances.length = 0;\n }\n\n addSample(sample: PointerSample): readonly WaterDisturbance[] {\n this.disturbances.length = 0;\n\n const raw = this.clampSample(sample);\n const previous = this.previous;\n\n if (!previous) {\n this.previous = raw;\n return this.disturbances;\n }\n\n if (raw.time <= previous.time) {\n raw.time = previous.time + 0.01;\n }\n\n const current = this.smoothSample(previous, raw);\n const segmentLength = distance(previous, current);\n\n if (segmentLength < 0.35) {\n this.previous = current;\n return this.disturbances;\n }\n\n const velocity = segmentLength / Math.max(0.01, current.time - previous.time);\n const velocityFollow = clamp(1 - this.options.cursorSmoothing, 0.12, 1);\n\n this.smoothedVelocity = lerp(\n this.smoothedVelocity,\n velocity,\n velocityFollow\n );\n this.previous = current;\n\n const segmentCount = Math.min(\n MAX_SEGMENTS_PER_SAMPLE,\n Math.max(1, Math.ceil(segmentLength / this.options.segmentSpacing))\n );\n\n for (let index = 0; index < segmentCount; index += 1) {\n const start = index / segmentCount;\n const end = (index + 1) / segmentCount;\n\n this.disturbances.push(\n createDisturbance(\n interpolateSample(previous, current, start),\n interpolateSample(previous, current, end),\n this.smoothedVelocity,\n this.options\n )\n );\n }\n\n return this.disturbances;\n }\n\n private clampSample(sample: PointerSample): PointerSample {\n return {\n x: clamp(sample.x, 0, this.options.width),\n y: clamp(sample.y, 0, this.options.height),\n time: sample.time\n };\n }\n\n private smoothSample(previous: PointerSample, raw: PointerSample): PointerSample {\n const follow = 1 - this.options.cursorSmoothing;\n\n return {\n x: lerp(previous.x, raw.x, follow),\n y: lerp(previous.y, raw.y, follow),\n time: raw.time\n };\n }\n}\n\nexport function createDisturbance(\n from: PointerSample,\n to: PointerSample,\n velocityPxMs: number,\n options: Partial<PointerDisturbanceOptions>\n): WaterDisturbance {\n const normalized = normalizeOptions(options);\n const speedAmount = clamp(\n (velocityPxMs * normalized.velocityScale) / normalized.velocityClamp,\n 0,\n 1\n );\n const fromY = clamp(from.y / normalized.height, 0, 1);\n const toY = clamp(to.y / normalized.height, 0, 1);\n const wakeLengthPx = normalized.wakeLength * lerp(0.55, 1.35, speedAmount);\n\n return {\n ax: clamp(from.x / normalized.width, 0, 1),\n ay: 1 - fromY,\n bx: clamp(to.x / normalized.width, 0, 1),\n by: 1 - toY,\n radius: normalized.interactionRadius / normalized.height,\n wakeStrength: normalized.wakeStrength * lerp(0.18, 1, speedAmount),\n troughStrength: normalized.troughStrength,\n ridgeStrength: normalized.ridgeStrength,\n ridgeOffset: normalized.ridgeOffset / normalized.height,\n wakeLength: wakeLengthPx / normalized.height,\n velocity: speedAmount\n };\n}\n\nfunction interpolateSample(\n from: PointerSample,\n to: PointerSample,\n amount: number\n): PointerSample {\n return {\n x: lerp(from.x, to.x, amount),\n y: lerp(from.y, to.y, amount),\n time: lerp(from.time, to.time, amount)\n };\n}\n\nexport function estimateSettleDuration(damping: number): number {\n const safeDamping = clamp(damping, 0.85, 0.998);\n const frames = Math.ceil(Math.log(0.012) / Math.log(safeDamping));\n\n return clamp(frames * (1000 / 60), 900, 5200);\n}\n","import type { CSSProperties, ReactNode } from \"react\";\nimport {\n forwardRef,\n useEffect,\n useImperativeHandle,\n useRef,\n useState\n} from \"react\";\nimport { clamp } from \"./core/math\";\nimport {\n HeightfieldWaterRenderer,\n type WaterRenderMode,\n type WaterRendererSettings,\n type WaterTextureSource\n} from \"./core/waterRenderer\";\nimport {\n PointerDisturbanceTracker,\n createDisturbance,\n estimateSettleDuration,\n getPointerSamples,\n type WaterDisturbance\n} from \"./core/waterInteraction\";\n\nexport type ReducedMotionBehavior = \"respect\" | \"disable\" | \"ignore\";\nexport type WaterInteractionMode = \"move\" | \"click\" | \"drag\" | \"event\";\n\nexport interface WaterRipplePosition {\n /** Horizontal position normalized from 0 (left) to 1 (right). */\n x: number;\n /** Vertical position normalized from 0 (top) to 1 (bottom). */\n y: number;\n}\n\nexport interface WaterDistortionHandle {\n triggerRipple(position: WaterRipplePosition): void;\n}\n\nexport interface WaterDistortionProps {\n underlay?: ReactNode;\n children?: ReactNode;\n foreground?: ReactNode;\n mode?: WaterRenderMode;\n texture?: WaterTextureSource;\n rippleStrength?: number;\n wakeStrength?: number;\n interactionRadius?: number;\n troughStrength?: number;\n ridgeStrength?: number;\n ridgeOffset?: number;\n wakeLength?: number;\n velocityScale?: number;\n velocityClamp?: number;\n cursorSmoothing?: number;\n segmentSpacing?: number;\n strength?: number;\n damping?: number;\n dissipation?: number;\n waveSpeed?: number;\n normalScale?: number;\n refractionStrength?: number;\n specularIntensity?: number;\n crestIntensity?: number;\n causticIntensity?: number;\n simulationResolution?: number;\n idleTimeout?: number;\n blur?: number;\n maxTrailPoints?: number;\n maxStamps?: number;\n trailSpacing?: number;\n className?: string;\n style?: CSSProperties;\n reducedMotion?: ReducedMotionBehavior;\n interactionMode?: WaterInteractionMode;\n runInBackground?: boolean;\n pauseKey?: string;\n}\n\ninterface RuntimeSettings extends WaterRendererSettings {\n wakeStrength: number;\n interactionRadius: number;\n troughStrength: number;\n ridgeStrength: number;\n ridgeOffset: number;\n wakeLength: number;\n velocityScale: number;\n velocityClamp: number;\n cursorSmoothing: number;\n segmentSpacing: number;\n idleTimeout: number;\n interactionMode: WaterInteractionMode;\n runInBackground: boolean;\n pauseKey?: string;\n}\n\nconst DEFAULT_SETTINGS: RuntimeSettings = {\n mode: \"texture\",\n damping: 0.98,\n waveSpeed: 0.4,\n normalScale: 20,\n refractionStrength: 0.7,\n specularIntensity: 1,\n crestIntensity: 0.2,\n causticIntensity: 0,\n simulationResolution: 192,\n wakeStrength: 0.54,\n interactionRadius: 25,\n troughStrength: 0.92,\n ridgeStrength: 0.46,\n ridgeOffset: 10,\n wakeLength: 84,\n velocityScale: 1,\n velocityClamp: 1.35,\n cursorSmoothing: 0.2,\n segmentSpacing: 18,\n idleTimeout: 900,\n interactionMode: \"move\",\n runInBackground: false,\n pauseKey: undefined\n};\n\nconst STEP_MS = 1000 / 60;\nconst MAX_FRAME_STEPS = 4;\nconst MAX_BACKGROUND_FRAME_STEPS = 360;\nconst MAX_PENDING_DISTURBANCES = 24;\nconst SETTLE_CHECK_INTERVAL_MS = 200;\n\nfunction isInteractiveKeyboardTarget(target: EventTarget | null): boolean {\n return (\n target instanceof Element &&\n target.closest(\n \"a, button, input, select, textarea, [contenteditable]:not([contenteditable=false])\"\n ) !== null\n );\n}\n\nfunction getRuntimeSettings(props: WaterDistortionProps): RuntimeSettings {\n const legacyStrength =\n props.strength === undefined ? undefined : props.strength / 48;\n\n return {\n mode: props.mode ?? DEFAULT_SETTINGS.mode,\n texture: props.texture,\n damping: clamp(\n props.damping ?? props.dissipation ?? DEFAULT_SETTINGS.damping,\n 0.85,\n 0.998\n ),\n waveSpeed: clamp(props.waveSpeed ?? DEFAULT_SETTINGS.waveSpeed, 0.05, 1),\n normalScale: clamp(\n props.normalScale ?? DEFAULT_SETTINGS.normalScale,\n 1,\n 80\n ),\n refractionStrength: clamp(\n props.refractionStrength ?? DEFAULT_SETTINGS.refractionStrength,\n 0,\n 2.5\n ),\n specularIntensity: clamp(\n props.specularIntensity ?? DEFAULT_SETTINGS.specularIntensity,\n 0,\n 3\n ),\n crestIntensity: clamp(\n props.crestIntensity ?? DEFAULT_SETTINGS.crestIntensity,\n 0,\n 3\n ),\n causticIntensity: clamp(\n props.causticIntensity ?? DEFAULT_SETTINGS.causticIntensity,\n 0,\n 3\n ),\n simulationResolution: clamp(\n Math.round(\n props.simulationResolution ?? DEFAULT_SETTINGS.simulationResolution\n ),\n 64,\n 384\n ),\n wakeStrength: clamp(\n props.wakeStrength ??\n props.rippleStrength ??\n legacyStrength ??\n DEFAULT_SETTINGS.wakeStrength,\n 0,\n 3\n ),\n interactionRadius: clamp(\n props.interactionRadius ?? DEFAULT_SETTINGS.interactionRadius,\n 2,\n 80\n ),\n troughStrength: clamp(\n props.troughStrength ?? DEFAULT_SETTINGS.troughStrength,\n 0,\n 3\n ),\n ridgeStrength: clamp(\n props.ridgeStrength ?? DEFAULT_SETTINGS.ridgeStrength,\n 0,\n 3\n ),\n ridgeOffset: clamp(\n props.ridgeOffset ?? DEFAULT_SETTINGS.ridgeOffset,\n 0,\n 80\n ),\n wakeLength: clamp(\n props.wakeLength ?? DEFAULT_SETTINGS.wakeLength,\n 1,\n 240\n ),\n velocityScale: clamp(\n props.velocityScale ?? DEFAULT_SETTINGS.velocityScale,\n 0.01,\n 4\n ),\n velocityClamp: clamp(\n props.velocityClamp ?? DEFAULT_SETTINGS.velocityClamp,\n 0.05,\n 8\n ),\n cursorSmoothing: clamp(\n props.cursorSmoothing ?? DEFAULT_SETTINGS.cursorSmoothing,\n 0,\n 0.9\n ),\n segmentSpacing: clamp(\n props.segmentSpacing ?? DEFAULT_SETTINGS.segmentSpacing,\n 1,\n 96\n ),\n idleTimeout: Math.max(120, props.idleTimeout ?? DEFAULT_SETTINGS.idleTimeout),\n interactionMode:\n props.interactionMode ?? DEFAULT_SETTINGS.interactionMode,\n runInBackground:\n props.runInBackground ?? DEFAULT_SETTINGS.runInBackground,\n pauseKey: props.pauseKey || DEFAULT_SETTINGS.pauseKey\n };\n}\n\nfunction createRippleDisturbances(\n position: WaterRipplePosition,\n settings: RuntimeSettings,\n size: { width: number; height: number }\n): WaterDisturbance[] {\n const centerX = clamp(position.x, 0, 1) * size.width;\n const centerY = clamp(position.y, 0, 1) * size.height;\n const halfSegment = Math.max(0.5, settings.interactionRadius * 0.08);\n const velocity = settings.velocityClamp / settings.velocityScale;\n const options = {\n ...settings,\n width: size.width,\n height: size.height,\n wakeLength: settings.interactionRadius * 1.5\n };\n\n return [\n createDisturbance(\n { x: centerX - halfSegment, y: centerY, time: 0 },\n { x: centerX + halfSegment, y: centerY, time: 1 },\n velocity,\n options\n ),\n createDisturbance(\n { x: centerX, y: centerY - halfSegment, time: 0 },\n { x: centerX, y: centerY + halfSegment, time: 1 },\n velocity,\n options\n )\n ];\n}\n\nfunction usePrefersReducedMotion(enabled: boolean): boolean {\n const [prefersReducedMotion, setPrefersReducedMotion] = useState(false);\n\n useEffect(() => {\n if (!enabled || typeof window === \"undefined\" || !window.matchMedia) {\n setPrefersReducedMotion(false);\n return;\n }\n\n const query = window.matchMedia(\"(prefers-reduced-motion: reduce)\");\n\n setPrefersReducedMotion(query.matches);\n\n const handleChange = (event: MediaQueryListEvent) => {\n setPrefersReducedMotion(event.matches);\n };\n\n query.addEventListener(\"change\", handleChange);\n\n return () => {\n query.removeEventListener(\"change\", handleChange);\n };\n }, [enabled]);\n\n return prefersReducedMotion;\n}\n\nexport const WaterDistortion = forwardRef<\n WaterDistortionHandle,\n WaterDistortionProps\n>(function WaterDistortion(props, ref) {\n const {\n underlay,\n children,\n foreground,\n className,\n style,\n reducedMotion = \"respect\"\n } = props;\n const containerRef = useRef<HTMLDivElement | null>(null);\n const canvasRef = useRef<HTMLCanvasElement | null>(null);\n const rendererRef = useRef<HeightfieldWaterRenderer | null>(null);\n const trackerRef = useRef(new PointerDisturbanceTracker());\n const frameRef = useRef<number | null>(null);\n const backgroundTimerRef = useRef<number | null>(null);\n const requestFrameRef = useRef<() => void>(() => undefined);\n const syncFocusBehaviorRef = useRef<() => void>(() => undefined);\n const queueDisturbancesRef = useRef<\n (disturbances: readonly WaterDisturbance[]) => void\n >(() => undefined);\n const pendingDisturbancesRef = useRef<WaterDisturbance[]>([]);\n const visibleRef = useRef(true);\n const focusedRef = useRef(true);\n const disabledRef = useRef(false);\n const pausedRef = useRef(false);\n const activeDragPointerIdRef = useRef<number | null>(null);\n const idleUntilRef = useRef(0);\n const fallbackActiveUntilRef = useRef(0);\n const nextSettleCheckRef = useRef(0);\n const settings = getRuntimeSettings(props);\n const settingsRef = useRef(settings);\n const sizeRef = useRef({ width: 1, height: 1 });\n const prefersReducedMotion = usePrefersReducedMotion(\n reducedMotion === \"respect\"\n );\n const effectDisabled =\n reducedMotion === \"disable\" ||\n (reducedMotion === \"respect\" && prefersReducedMotion);\n const foregroundContent = foreground ?? children;\n\n settingsRef.current = settings;\n\n useImperativeHandle(\n ref,\n () => ({\n triggerRipple(position) {\n if (disabledRef.current || pausedRef.current) {\n return;\n }\n\n queueDisturbancesRef.current(\n createRippleDisturbances(\n position,\n settingsRef.current,\n sizeRef.current\n )\n );\n }\n }),\n []\n );\n\n useEffect(() => {\n disabledRef.current = effectDisabled;\n\n if (effectDisabled) {\n trackerRef.current.reset();\n activeDragPointerIdRef.current = null;\n pendingDisturbancesRef.current = [];\n idleUntilRef.current = 0;\n fallbackActiveUntilRef.current = 0;\n nextSettleCheckRef.current = 0;\n rendererRef.current?.clear();\n }\n\n requestFrameRef.current();\n }, [effectDisabled]);\n\n useEffect(() => {\n const renderer = rendererRef.current;\n\n if (!renderer) {\n return;\n }\n\n const { width, height } = sizeRef.current;\n\n renderer.resize(\n width,\n height,\n window.devicePixelRatio,\n settings.simulationResolution\n );\n renderer.setTextureSource(settings.texture);\n requestFrameRef.current();\n }, [\n settings.mode,\n settings.texture,\n settings.damping,\n settings.waveSpeed,\n settings.normalScale,\n settings.refractionStrength,\n settings.specularIntensity,\n settings.crestIntensity,\n settings.causticIntensity,\n settings.simulationResolution\n ]);\n\n useEffect(() => {\n const container = containerRef.current;\n const canvas = canvasRef.current;\n\n if (!container || !canvas) {\n return;\n }\n\n focusedRef.current =\n typeof document.hasFocus === \"function\" ? document.hasFocus() : true;\n\n let renderer: HeightfieldWaterRenderer | null = null;\n let lastFrameTime: number | undefined;\n let accumulator = STEP_MS;\n let activityReadbackFailed = false;\n let pausedAt: number | undefined;\n\n const cancelFrame = () => {\n if (frameRef.current !== null) {\n window.cancelAnimationFrame(frameRef.current);\n frameRef.current = null;\n }\n\n if (backgroundTimerRef.current !== null) {\n window.clearTimeout(backgroundTimerRef.current);\n backgroundTimerRef.current = null;\n }\n };\n\n const updateTrackerSize = (width: number, height: number) => {\n trackerRef.current.configure({\n width,\n height,\n interactionRadius: settingsRef.current.interactionRadius,\n wakeStrength: settingsRef.current.wakeStrength,\n troughStrength: settingsRef.current.troughStrength,\n ridgeStrength: settingsRef.current.ridgeStrength,\n ridgeOffset: settingsRef.current.ridgeOffset,\n wakeLength: settingsRef.current.wakeLength,\n velocityScale: settingsRef.current.velocityScale,\n velocityClamp: settingsRef.current.velocityClamp,\n cursorSmoothing: settingsRef.current.cursorSmoothing,\n segmentSpacing: settingsRef.current.segmentSpacing\n });\n };\n\n const updateSize = (width: number, height: number) => {\n const safeWidth = Math.max(1, width);\n const safeHeight = Math.max(1, height);\n\n sizeRef.current = { width: safeWidth, height: safeHeight };\n updateTrackerSize(safeWidth, safeHeight);\n renderer?.resize(\n safeWidth,\n safeHeight,\n window.devicePixelRatio,\n settingsRef.current.simulationResolution\n );\n };\n\n const renderStatic = () => {\n renderer?.render(settingsRef.current, performance.now() * 0.001);\n };\n\n const sleep = () => {\n lastFrameTime = undefined;\n accumulator = STEP_MS;\n };\n\n const pauseAnimation = () => {\n cancelFrame();\n trackerRef.current.reset();\n activeDragPointerIdRef.current = null;\n sleep();\n\n if (pausedAt === undefined) {\n pausedAt = performance.now();\n }\n };\n\n const resumeAnimation = () => {\n const currentSettings = settingsRef.current;\n let resumedFromPause = false;\n const canRun =\n !disabledRef.current &&\n !pausedRef.current &&\n visibleRef.current &&\n (currentSettings.runInBackground ||\n (!document.hidden && focusedRef.current));\n\n if (!canRun) {\n sleep();\n return;\n }\n\n if (pausedAt !== undefined) {\n const pausedDuration = performance.now() - pausedAt;\n\n idleUntilRef.current += pausedDuration;\n fallbackActiveUntilRef.current += pausedDuration;\n nextSettleCheckRef.current += pausedDuration;\n pausedAt = undefined;\n resumedFromPause = true;\n }\n\n if (!currentSettings.runInBackground || resumedFromPause) {\n sleep();\n }\n\n renderStatic();\n requestFrameRef.current();\n };\n\n const frame = (time: number) => {\n frameRef.current = null;\n const currentSettings = settingsRef.current;\n\n if (\n !renderer ||\n pausedRef.current ||\n !visibleRef.current ||\n (!currentSettings.runInBackground &&\n (document.hidden || !focusedRef.current))\n ) {\n sleep();\n return;\n }\n\n if (disabledRef.current) {\n pendingDisturbancesRef.current = [];\n renderer.render(currentSettings, time * 0.001);\n sleep();\n return;\n }\n\n const maxFrameSteps = currentSettings.runInBackground\n ? MAX_BACKGROUND_FRAME_STEPS\n : MAX_FRAME_STEPS;\n const elapsed =\n lastFrameTime === undefined\n ? STEP_MS\n : clamp(\n time - lastFrameTime,\n 0,\n currentSettings.runInBackground\n ? STEP_MS * MAX_BACKGROUND_FRAME_STEPS\n : 64\n );\n\n lastFrameTime = time;\n accumulator = Math.min(\n accumulator + elapsed,\n STEP_MS * maxFrameSteps\n );\n\n let disturbances = pendingDisturbancesRef.current.splice(0);\n let steps = 0;\n\n while (accumulator >= STEP_MS && steps < maxFrameSteps) {\n renderer.step(disturbances, currentSettings, 1);\n disturbances = [];\n accumulator -= STEP_MS;\n steps += 1;\n }\n\n renderer.render(currentSettings, time * 0.001);\n\n if (pendingDisturbancesRef.current.length > 0) {\n requestFrameRef.current();\n return;\n }\n\n if (time < idleUntilRef.current) {\n requestFrameRef.current();\n return;\n }\n\n if (activityReadbackFailed) {\n if (time < fallbackActiveUntilRef.current) {\n requestFrameRef.current();\n } else {\n sleep();\n }\n\n return;\n }\n\n if (time < nextSettleCheckRef.current) {\n requestFrameRef.current();\n return;\n }\n\n try {\n if (renderer.hasVisibleActivity()) {\n nextSettleCheckRef.current = time + SETTLE_CHECK_INTERVAL_MS;\n requestFrameRef.current();\n } else {\n sleep();\n }\n } catch {\n activityReadbackFailed = true;\n\n if (time < fallbackActiveUntilRef.current) {\n requestFrameRef.current();\n } else {\n sleep();\n }\n }\n };\n\n const requestFrame = () => {\n if (\n pausedRef.current ||\n frameRef.current !== null ||\n backgroundTimerRef.current !== null\n ) {\n return;\n }\n\n if (settingsRef.current.runInBackground && document.hidden) {\n backgroundTimerRef.current = window.setTimeout(() => {\n backgroundTimerRef.current = null;\n frame(performance.now());\n }, STEP_MS);\n } else {\n frameRef.current = window.requestAnimationFrame(frame);\n }\n };\n\n requestFrameRef.current = requestFrame;\n\n try {\n renderer = new HeightfieldWaterRenderer(canvas, () => {\n requestFrameRef.current();\n });\n rendererRef.current = renderer;\n renderer.setTextureSource(settingsRef.current.texture);\n } catch {\n canvas.style.display = \"none\";\n rendererRef.current = null;\n requestFrameRef.current = () => undefined;\n return () => undefined;\n }\n\n const syncSize = () => {\n const rect = canvas.getBoundingClientRect();\n updateSize(rect.width, rect.height);\n\n return rect;\n };\n\n const readSize = () => {\n syncSize();\n renderStatic();\n };\n\n const queueDisturbances = (\n disturbances: readonly WaterDisturbance[]\n ) => {\n if (pausedRef.current || disturbances.length === 0) {\n return;\n }\n\n const pending = pendingDisturbancesRef.current;\n\n for (const disturbance of disturbances) {\n pending.push(disturbance);\n }\n\n if (pending.length > MAX_PENDING_DISTURBANCES) {\n pending.splice(0, pending.length - MAX_PENDING_DISTURBANCES);\n }\n\n const now = performance.now();\n const idleUntil = now + settingsRef.current.idleTimeout;\n\n idleUntilRef.current = Math.max(idleUntilRef.current, idleUntil);\n fallbackActiveUntilRef.current = Math.max(\n fallbackActiveUntilRef.current,\n idleUntil + estimateSettleDuration(settingsRef.current.damping)\n );\n nextSettleCheckRef.current = 0;\n requestFrame();\n };\n\n queueDisturbancesRef.current = queueDisturbances;\n\n const handlePointerStart = (event: PointerEvent) => {\n const currentSettings = settingsRef.current;\n\n if (\n disabledRef.current ||\n pausedRef.current ||\n !visibleRef.current ||\n currentSettings.interactionMode === \"event\" ||\n (!currentSettings.runInBackground &&\n (document.hidden || !focusedRef.current))\n ) {\n return;\n }\n\n if (event.pointerType === \"touch\" && !event.isPrimary) {\n return;\n }\n\n trackerRef.current.reset();\n const rect = syncSize();\n const [sample] = getPointerSamples(event, rect, performance.now());\n\n if (sample) {\n if (\n currentSettings.interactionMode === \"click\" ||\n currentSettings.interactionMode === \"drag\"\n ) {\n queueDisturbances(\n createRippleDisturbances(\n {\n x: sample.x / sizeRef.current.width,\n y: sample.y / sizeRef.current.height\n },\n currentSettings,\n sizeRef.current\n )\n );\n }\n\n if (currentSettings.interactionMode === \"drag\") {\n activeDragPointerIdRef.current = event.pointerId;\n trackerRef.current.addSample(sample);\n } else if (currentSettings.interactionMode === \"move\") {\n trackerRef.current.addSample(sample);\n }\n }\n };\n\n const handlePointerMove = (event: PointerEvent) => {\n const currentSettings = settingsRef.current;\n\n if (\n disabledRef.current ||\n pausedRef.current ||\n !visibleRef.current ||\n (currentSettings.interactionMode !== \"move\" &&\n (currentSettings.interactionMode !== \"drag\" ||\n activeDragPointerIdRef.current !== event.pointerId)) ||\n (!currentSettings.runInBackground &&\n (document.hidden || !focusedRef.current))\n ) {\n return;\n }\n\n if (event.pointerType === \"touch\" && !event.isPrimary) {\n return;\n }\n\n const rect = syncSize();\n const samples = getPointerSamples(event, rect, performance.now());\n\n for (const sample of samples) {\n queueDisturbances(trackerRef.current.addSample(sample));\n }\n };\n\n const handleStrokeEnd = (event: PointerEvent) => {\n if (\n activeDragPointerIdRef.current !== null &&\n activeDragPointerIdRef.current !== event.pointerId\n ) {\n return;\n }\n\n activeDragPointerIdRef.current = null;\n trackerRef.current.reset();\n };\n\n const handleKeyDown = (event: KeyboardEvent) => {\n const pauseKey = settingsRef.current.pauseKey;\n\n if (\n !pauseKey ||\n event.code !== pauseKey ||\n event.repeat ||\n event.altKey ||\n event.ctrlKey ||\n event.metaKey ||\n isInteractiveKeyboardTarget(event.target)\n ) {\n return;\n }\n\n event.preventDefault();\n pausedRef.current = !pausedRef.current;\n\n if (pausedRef.current) {\n pauseAnimation();\n } else {\n cancelFrame();\n resumeAnimation();\n }\n };\n\n const handleVisibilityChange = () => {\n cancelFrame();\n\n if (document.hidden && !settingsRef.current.runInBackground) {\n pauseAnimation();\n } else {\n resumeAnimation();\n }\n };\n\n const handleWindowBlur = () => {\n focusedRef.current = false;\n\n if (settingsRef.current.runInBackground) {\n cancelFrame();\n resumeAnimation();\n } else {\n pauseAnimation();\n }\n };\n\n const handleWindowFocus = () => {\n focusedRef.current = true;\n cancelFrame();\n resumeAnimation();\n };\n\n const syncFocusBehavior = () => {\n cancelFrame();\n\n if (\n !settingsRef.current.runInBackground &&\n (document.hidden || !focusedRef.current)\n ) {\n pauseAnimation();\n } else {\n resumeAnimation();\n }\n };\n\n syncFocusBehaviorRef.current = syncFocusBehavior;\n\n readSize();\n\n const resizeObserver = new ResizeObserver(() => {\n syncSize();\n requestFrame();\n });\n\n resizeObserver.observe(canvas);\n\n let intersectionObserver: IntersectionObserver | undefined;\n\n if (\"IntersectionObserver\" in window) {\n intersectionObserver = new IntersectionObserver((entries) => {\n const entry = entries[0];\n\n visibleRef.current = entry ? entry.isIntersecting : true;\n\n if (!visibleRef.current) {\n pauseAnimation();\n } else {\n resumeAnimation();\n }\n });\n intersectionObserver.observe(container);\n }\n\n container.addEventListener(\"pointerdown\", handlePointerStart, {\n passive: true\n });\n container.addEventListener(\"pointermove\", handlePointerMove, {\n passive: true\n });\n container.addEventListener(\"pointerup\", handleStrokeEnd, {\n passive: true\n });\n container.addEventListener(\"pointerleave\", handleStrokeEnd, {\n passive: true\n });\n container.addEventListener(\"pointercancel\", handleStrokeEnd, {\n passive: true\n });\n window.addEventListener(\"blur\", handleWindowBlur);\n window.addEventListener(\"focus\", handleWindowFocus);\n document.addEventListener(\"keydown\", handleKeyDown);\n document.addEventListener(\"visibilitychange\", handleVisibilityChange);\n\n return () => {\n cancelFrame();\n resizeObserver.disconnect();\n intersectionObserver?.disconnect();\n container.removeEventListener(\"pointerdown\", handlePointerStart);\n container.removeEventListener(\"pointermove\", handlePointerMove);\n container.removeEventListener(\"pointerup\", handleStrokeEnd);\n container.removeEventListener(\"pointerleave\", handleStrokeEnd);\n container.removeEventListener(\"pointercancel\", handleStrokeEnd);\n window.removeEventListener(\"blur\", handleWindowBlur);\n window.removeEventListener(\"focus\", handleWindowFocus);\n document.removeEventListener(\"keydown\", handleKeyDown);\n document.removeEventListener(\"visibilitychange\", handleVisibilityChange);\n rendererRef.current?.dispose();\n rendererRef.current = null;\n requestFrameRef.current = () => undefined;\n syncFocusBehaviorRef.current = () => undefined;\n queueDisturbancesRef.current = () => undefined;\n };\n }, []);\n\n useEffect(() => {\n trackerRef.current.reset();\n activeDragPointerIdRef.current = null;\n }, [settings.interactionMode]);\n\n useEffect(() => {\n syncFocusBehaviorRef.current();\n }, [settings.runInBackground]);\n\n useEffect(() => {\n if (!settings.pauseKey && pausedRef.current) {\n pausedRef.current = false;\n syncFocusBehaviorRef.current();\n }\n }, [settings.pauseKey]);\n\n const containerStyle: CSSProperties = {\n ...style,\n position: \"relative\",\n overflow: \"hidden\",\n isolation: \"isolate\"\n };\n\n return (\n <div ref={containerRef} className={className} style={containerStyle}>\n {underlay ? (\n <div\n style={{\n position: \"absolute\",\n inset: 0,\n zIndex: 0,\n pointerEvents: \"none\",\n transform: \"translateZ(0)\"\n }}\n >\n {underlay}\n </div>\n ) : null}\n <canvas\n ref={canvasRef}\n aria-hidden=\"true\"\n style={{\n position: \"absolute\",\n inset: 0,\n zIndex: 1,\n width: \"100%\",\n height: \"100%\",\n pointerEvents: \"none\",\n mixBlendMode: settings.mode === \"dom\" ? \"screen\" : \"normal\"\n }}\n />\n <div\n style={{\n position: \"relative\",\n zIndex: 2\n }}\n >\n {foregroundContent}\n </div>\n </div>\n );\n});\n\nexport const WaterLayer = WaterDistortion;\nexport type { WaterRenderMode, WaterTextureSource };\n"],"names":["clamp","value","min","max","distance","a","b","lerp","amount","MAX_WAKE_SEGMENTS","CAUSTIC_MAP_SIZE","CAUSTIC_CELL_COUNT","TAU","DOM_HIGHLIGHT_SETTINGS","DEFAULT_ACTIVITY_THRESHOLDS","VERTEX_SHADER","SIMULATION_SHADER","MATERIAL_SHADER","HeightfieldWaterRenderer","canvas","requestRender","__publicField","gl","isWebGL2","canLinearFloat","createContext","mustCreate","createProgramInfo","cssWidth","cssHeight","pixelRatio","simulationResolution","ratio","renderWidth","renderHeight","longestSide","aspect","nextSimWidth","nextSimHeight","source","image","disturbances","settings","delta","writeIndex","timeSeconds","framebuffer","pixelCount","hasVisibleWaterActivity","_a","texture","_b","firstTexture","secondTexture","firstFramebuffer","secondFramebuffer","gl2","createCausticMap","shouldUploadEveryFrame","program","count","wakeA","wakeB","wakeShape","start","index","disturbance","offset","getUniform","data","y","x","u","v","red","createCausticChannel","green","blue","alpha","seed","warpX","warpY","sampleX","sampleY","cellX","cellY","nearest","secondNearest","nearestCellX","nearestCellY","offsetY","offsetX","candidateX","candidateY","wrappedX","positiveModulo","wrappedY","pointX","hash2","pointY","edgeDistance","core","smoothstepNumber","glow","variation","clamp01","divisor","edge0","edge1","attributes","webgl2","webgl1","vertexSource","fragmentSource","vertexShader","compileShader","fragmentShader","error","position","type","shader","name","location","label","state","width","height","thresholds","safeWidth","safeHeight","readHeight","current","velocity","left","right","down","up","gradient","curvature","DEFAULT_OPTIONS","MAX_SEGMENTS_PER_SAMPLE","normalizeOptions","options","getPointerSamples","event","bounds","now","events","sourceEvents","clockOffset","pointerEvent","PointerDisturbanceTracker","sample","raw","previous","segmentLength","velocityFollow","segmentCount","end","createDisturbance","interpolateSample","follow","from","to","velocityPxMs","normalized","speedAmount","fromY","toY","wakeLengthPx","estimateSettleDuration","damping","safeDamping","frames","DEFAULT_SETTINGS","STEP_MS","MAX_FRAME_STEPS","MAX_BACKGROUND_FRAME_STEPS","MAX_PENDING_DISTURBANCES","SETTLE_CHECK_INTERVAL_MS","isInteractiveKeyboardTarget","target","getRuntimeSettings","props","legacyStrength","createRippleDisturbances","size","centerX","centerY","halfSegment","usePrefersReducedMotion","enabled","prefersReducedMotion","setPrefersReducedMotion","useState","useEffect","query","handleChange","WaterDistortion","forwardRef","ref","underlay","children","foreground","className","style","reducedMotion","containerRef","useRef","canvasRef","rendererRef","trackerRef","frameRef","backgroundTimerRef","requestFrameRef","syncFocusBehaviorRef","queueDisturbancesRef","pendingDisturbancesRef","visibleRef","focusedRef","disabledRef","pausedRef","activeDragPointerIdRef","idleUntilRef","fallbackActiveUntilRef","nextSettleCheckRef","settingsRef","sizeRef","effectDisabled","foregroundContent","useImperativeHandle","renderer","container","lastFrameTime","accumulator","activityReadbackFailed","pausedAt","cancelFrame","updateTrackerSize","updateSize","renderStatic","sleep","pauseAnimation","resumeAnimation","currentSettings","resumedFromPause","pausedDuration","frame","time","maxFrameSteps","elapsed","steps","requestFrame","syncSize","rect","readSize","queueDisturbances","pending","idleUntil","handlePointerStart","handlePointerMove","samples","handleStrokeEnd","handleKeyDown","pauseKey","handleVisibilityChange","handleWindowBlur","handleWindowFocus","syncFocusBehavior","resizeObserver","intersectionObserver","entries","entry","containerStyle","jsx","WaterLayer"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"water-distortion.js","sources":["../src/core/math.ts","../src/core/waterRenderer.ts","../src/core/waterInteraction.ts","../src/WaterDistortion.tsx"],"sourcesContent":["export interface Vector2 {\n x: number;\n y: number;\n}\n\nexport function clamp(value: number, min: number, max: number): number {\n return Math.min(max, Math.max(min, value));\n}\n\nexport function distance(a: Vector2, b: Vector2): number {\n return Math.hypot(b.x - a.x, b.y - a.y);\n}\n\nexport function lerp(a: number, b: number, amount: number): number {\n return a + (b - a) * amount;\n}\n\nexport function normalize(vector: Vector2): Vector2 {\n const length = Math.hypot(vector.x, vector.y);\n\n if (length < 0.0001) {\n return { x: 0, y: 0 };\n }\n\n return {\n x: vector.x / length,\n y: vector.y / length\n };\n}\n\nexport function smoothVector(\n previous: Vector2,\n next: Vector2,\n amount: number\n): Vector2 {\n return {\n x: lerp(previous.x, next.x, amount),\n y: lerp(previous.y, next.y, amount)\n };\n}\n","import type { WaterDisturbance } from \"./waterInteraction\";\n\nexport type WaterRenderMode = \"dom\" | \"texture\" | \"canvas\";\nexport type WaterTextureFit = \"fill\" | \"cover\" | \"contain\" | \"none\";\nexport type WaterTextureSource = TexImageSource | string;\n\nexport interface WaterRendererSettings {\n mode: WaterRenderMode;\n textureFit: WaterTextureFit;\n damping: number;\n waveSpeed: number;\n normalScale: number;\n refractionStrength: number;\n specularIntensity: number;\n crestIntensity: number;\n causticIntensity: number;\n simulationResolution: number;\n texture?: WaterTextureSource;\n}\n\nexport interface WaterActivityThresholds {\n gradient: number;\n curvature: number;\n trough: number;\n velocity: number;\n}\n\n/** @internal */\nexport interface WaterHighlightColor {\n r: number;\n g: number;\n b: number;\n}\n\n/** @internal */\nexport interface WaterDomHighlightOverlay {\n color: WaterHighlightColor;\n alpha: number;\n}\n\ntype WaterGL = WebGLRenderingContext | WebGL2RenderingContext;\n\ninterface ProgramInfo {\n program: WebGLProgram;\n position: number;\n}\n\nconst MAX_WAKE_SEGMENTS = 24;\nconst MIN_SIMULATION_AXIS = 32;\nconst CAUSTIC_MAP_SIZE = 128;\nconst CAUSTIC_CELL_COUNT = 8;\nconst TAU = Math.PI * 2;\n/** @internal */\nexport const DOM_HIGHLIGHT_SETTINGS = {\n causticGain: 0.1,\n screenCompensation: 1.35,\n maxAlpha: 0.9\n} as const;\nconst DEFAULT_ACTIVITY_THRESHOLDS: WaterActivityThresholds = {\n gradient: 0.0008,\n curvature: 0.0008,\n trough: 0.006,\n velocity: 0.0008\n};\nconst VERTEX_SHADER = `\nattribute vec2 a_position;\nvarying vec2 v_uv;\n\nvoid main() {\n v_uv = a_position * 0.5 + 0.5;\n gl_Position = vec4(a_position, 0.0, 1.0);\n}\n`;\n\nconst SIMULATION_SHADER = `\nprecision highp float;\n\n#define MAX_WAKE_SEGMENTS ${MAX_WAKE_SEGMENTS}\n\nvarying vec2 v_uv;\n\nuniform sampler2D u_state;\nuniform vec2 u_texel;\nuniform float u_delta;\nuniform float u_damping;\nuniform float u_stiffness;\nuniform float u_aspect;\nuniform int u_wakeCount;\nuniform vec4 u_wakeA[MAX_WAKE_SEGMENTS];\nuniform vec4 u_wakeB[MAX_WAKE_SEGMENTS];\nuniform vec4 u_wakeShape[MAX_WAKE_SEGMENTS];\n\nfloat segmentWake(vec2 uv, vec4 wakeA, vec4 wakeB, vec4 shape) {\n vec2 a = wakeA.xy;\n vec2 b = wakeB.xy;\n vec2 scale = vec2(u_aspect, 1.0);\n vec2 p = uv * scale;\n vec2 start = a * scale;\n vec2 end = b * scale;\n vec2 segment = end - start;\n float segmentLength = max(length(segment), 0.000001);\n vec2 dir = segment / segmentLength;\n vec2 normal = vec2(-dir.y, dir.x);\n float longitudinal = dot(p - start, dir);\n float clampedLongitudinal = clamp(longitudinal, 0.0, segmentLength);\n vec2 closest = start + dir * clampedLongitudinal;\n vec2 delta = p - closest;\n float perpendicular = abs(dot(delta, normal));\n float safeRadius = max(wakeA.z, 0.00001);\n float wakeStrength = wakeA.w;\n float wakeLength = max(wakeB.z, safeRadius);\n float troughStrength = shape.x;\n float ridgeStrength = shape.y;\n float ridgeOffset = max(shape.z, safeRadius * 0.35);\n float minFeatureWidth = u_texel.y * 2.25;\n float troughWidth = max(safeRadius * 0.82, minFeatureWidth);\n float ridgeWidth = max(safeRadius * 0.9, minFeatureWidth);\n float signedFromHead = dot(p - end, dir);\n float behindDistance = max(-signedFromHead, 0.0);\n float aheadDistance = max(signedFromHead, 0.0);\n float frontMask = 1.0 - smoothstep(safeRadius * 0.35, safeRadius * 1.8, aheadDistance);\n float trailMask = 1.0 - smoothstep(safeRadius * 0.5, wakeLength, behindDistance);\n float segmentMask =\n smoothstep(-safeRadius, safeRadius * 0.35, longitudinal) *\n (1.0 - smoothstep(segmentLength + wakeLength * 0.18, segmentLength + wakeLength, longitudinal));\n float pressureMask = frontMask * segmentMask;\n float centerTrough = exp(-pow(perpendicular / troughWidth, 2.0));\n float sideFade = 1.0 - smoothstep(safeRadius * 0.9, safeRadius * 2.35, perpendicular);\n float sideRidges =\n exp(-pow((perpendicular - ridgeOffset) / ridgeWidth, 2.0)) *\n sideFade;\n float trough = -centerTrough * troughStrength * pressureMask * (0.58 + trailMask * 0.42);\n float ridges = sideRidges * ridgeStrength * 0.5 * pressureMask * (0.36 + trailMask * 0.64);\n\n return wakeStrength * (trough + ridges);\n}\n\nvoid main() {\n vec4 state = texture2D(u_state, v_uv);\n float height = state.r;\n float velocity = state.g;\n\n float left = texture2D(u_state, v_uv - vec2(u_texel.x, 0.0)).r;\n float right = texture2D(u_state, v_uv + vec2(u_texel.x, 0.0)).r;\n float down = texture2D(u_state, v_uv - vec2(0.0, u_texel.y)).r;\n float up = texture2D(u_state, v_uv + vec2(0.0, u_texel.y)).r;\n float neighborAverage = (left + right + down + up) * 0.25;\n\n velocity += (neighborAverage - height) * u_stiffness * u_delta;\n\n for (int i = 0; i < MAX_WAKE_SEGMENTS; i++) {\n if (i >= u_wakeCount) {\n break;\n }\n\n float wake = segmentWake(v_uv, u_wakeA[i], u_wakeB[i], u_wakeShape[i]);\n\n velocity += wake * 0.12;\n height += wake * 0.014;\n }\n\n velocity *= pow(u_damping, u_delta);\n height *= pow(0.9985, u_delta);\n height += velocity * u_delta;\n\n gl_FragColor = vec4(height, velocity, 0.0, 1.0);\n}\n`;\n\nconst MATERIAL_SHADER = `\nprecision highp float;\n\nvarying vec2 v_uv;\n\nuniform sampler2D u_state;\nuniform sampler2D u_background;\nuniform sampler2D u_causticMap;\nuniform vec2 u_texel;\nuniform vec2 u_backgroundScale;\nuniform float u_domMode;\nuniform float u_normalScale;\nuniform float u_refractionStrength;\nuniform float u_specularIntensity;\nuniform float u_crestIntensity;\nuniform float u_causticIntensity;\nuniform float u_time;\n\nconst float DOM_CAUSTIC_GAIN = ${DOM_HIGHLIGHT_SETTINGS.causticGain.toFixed(2)};\nconst float DOM_SCREEN_COMPENSATION = ${DOM_HIGHLIGHT_SETTINGS.screenCompensation.toFixed(2)};\nconst float DOM_MAX_ALPHA = ${DOM_HIGHLIGHT_SETTINGS.maxAlpha.toFixed(2)};\n\nvec4 causticLayer(vec2 uv, vec2 bend, mat2 rotation, float scale, vec2 drift) {\n vec2 p = rotation * (uv * scale + drift * u_time);\n\n return texture2D(u_causticMap, p + bend * 0.22);\n}\n\nvoid main() {\n vec4 center = texture2D(u_state, v_uv);\n float height = center.r;\n float velocity = center.g;\n float left = texture2D(u_state, v_uv - vec2(u_texel.x, 0.0)).r;\n float right = texture2D(u_state, v_uv + vec2(u_texel.x, 0.0)).r;\n float down = texture2D(u_state, v_uv - vec2(0.0, u_texel.y)).r;\n float up = texture2D(u_state, v_uv + vec2(0.0, u_texel.y)).r;\n float dx = right - left;\n float dy = up - down;\n float signedCurvature = left + right + down + up - height * 4.0;\n vec3 normal = normalize(vec3(-dx * u_normalScale, 1.0, -dy * u_normalScale));\n vec2 backgroundUv = (v_uv - vec2(0.5)) * u_backgroundScale + vec2(0.5);\n vec2 refractedUv = (\n v_uv + normal.xz * u_refractionStrength * 0.025 - vec2(0.5)\n ) * u_backgroundScale + vec2(0.5);\n vec2 textureBounds =\n step(vec2(0.0), backgroundUv) * step(backgroundUv, vec2(1.0));\n float textureAlpha = textureBounds.x * textureBounds.y;\n refractedUv = clamp(\n refractedUv,\n vec2(0.001),\n vec2(0.999)\n );\n\n vec3 base = texture2D(u_background, refractedUv).rgb;\n\n float gradient = length(vec2(dx, dy)) * u_normalScale;\n float crest = smoothstep(0.012, 0.24, gradient);\n float trough = smoothstep(0.018, 0.09, -height);\n float heightActivity = smoothstep(0.0005, 0.018, abs(height));\n float aspect = u_texel.y / u_texel.x;\n vec2 causticUv = vec2(v_uv.x * aspect, v_uv.y);\n float rawActivity =\n gradient * 0.72 +\n abs(signedCurvature) * u_normalScale * 0.42 +\n abs(velocity) * 14.0 +\n heightActivity * 0.22;\n float edgeFade = smoothstep(0.0, 0.52, rawActivity);\n float visibleCrest = crest * edgeFade;\n float visibleTrough = trough * edgeFade;\n vec2 causticBend = normal.xz * (0.22 + visibleCrest * 0.08);\n float slopeActivity = smoothstep(0.004, 0.18, gradient);\n float convergence = smoothstep(0.004, 0.065, max(signedCurvature * u_normalScale, 0.0));\n float defocus = smoothstep(0.004, 0.065, max(-signedCurvature * u_normalScale, 0.0));\n float velocityActivity = smoothstep(0.0006, 0.006, abs(velocity));\n float activitySignal =\n slopeActivity * 0.38 +\n convergence * 0.58 +\n velocityActivity * 0.28 +\n heightActivity * 0.22;\n float activityGate = edgeFade * smoothstep(0.0, 0.58, activitySignal);\n float causticFocus =\n activityGate *\n (1.0 - defocus * 0.65) *\n mix(0.35, 1.25, convergence);\n vec4 causticA = causticLayer(\n causticUv,\n causticBend,\n mat2(0.94, -0.34, 0.34, 0.94),\n 1.45,\n vec2(0.032, -0.021)\n );\n vec4 causticB = causticLayer(\n causticUv,\n -causticBend * 0.72,\n mat2(0.62, 0.78, -0.78, 0.62),\n 2.05,\n vec2(-0.019, 0.034)\n );\n float sparklePhase = sin(u_time * 8.0 + causticA.b * 6.28318 + causticB.a * 3.14159);\n float primaryLines = smoothstep(0.10, 0.76, causticA.r * 0.72 + causticB.g * 0.18);\n float softFill = smoothstep(0.08, 0.62, causticA.g) * 0.2;\n float sparkle = smoothstep(\n 0.62,\n 0.96,\n max(causticA.a, causticB.b) * (0.9 + sparklePhase * 0.1)\n );\n float detailModulation = mix(0.58, 1.2, causticB.b);\n float brightnessModulation = mix(0.7, 1.12, causticA.b);\n float causticPattern = clamp(\n (primaryLines * detailModulation + softFill + sparkle * 0.1) *\n brightnessModulation,\n 0.0,\n 1.0\n );\n float caustic = causticPattern * causticFocus;\n float baseLuminance = dot(base, vec3(0.2126, 0.7152, 0.0722));\n float causticEnergy = 1.0 - exp(-caustic * u_causticIntensity * 0.82);\n float textureCausticGain = mix(0.12, 0.045, smoothstep(0.46, 0.9, baseLuminance));\n vec3 lightDirection = normalize(vec3(-0.32, 0.64, 0.42));\n vec3 viewDirection = vec3(0.0, 1.0, 0.0);\n vec3 halfDirection = normalize(lightDirection + viewDirection);\n float specular = pow(max(dot(normal, halfDirection), 0.0), 82.0) * activityGate;\n\n float causticGain = u_domMode > 0.5 ? DOM_CAUSTIC_GAIN : textureCausticGain;\n vec3 highlight =\n vec3(1.0, 0.98, 0.88) * specular * u_specularIntensity +\n vec3(0.75, 0.95, 1.0) * visibleCrest * u_crestIntensity * 0.11 +\n vec3(0.84, 1.0, 0.92) * causticEnergy * causticGain;\n\n if (u_domMode > 0.5) {\n float domEnergy = max(max(highlight.r, highlight.g), highlight.b);\n vec3 overlay = highlight / max(domEnergy, 0.00001);\n float alpha = clamp(domEnergy * DOM_SCREEN_COMPENSATION, 0.0, DOM_MAX_ALPHA);\n\n gl_FragColor = vec4(overlay, alpha);\n return;\n }\n\n vec3 color = base + highlight - vec3(0.015, 0.055, 0.070) * visibleTrough * 0.45;\n gl_FragColor = vec4(color, textureAlpha);\n}\n`;\n\nexport class HeightfieldWaterRenderer {\n private readonly gl: WaterGL;\n private readonly isWebGL2: boolean;\n private readonly canLinearFloat: boolean;\n private readonly quadBuffer: WebGLBuffer;\n private readonly simulationProgram: ProgramInfo;\n private readonly materialProgram: ProgramInfo;\n private readonly backgroundTexture: WebGLTexture;\n private readonly causticTexture: WebGLTexture;\n private stateTextures: [WebGLTexture, WebGLTexture] | undefined;\n private framebuffers: [WebGLFramebuffer, WebGLFramebuffer] | undefined;\n private readIndex = 0;\n private simWidth = 1;\n private simHeight = 1;\n private cssWidth = 1;\n private cssHeight = 1;\n private textureSource: WaterTextureSource | undefined;\n private textureImage: TexImageSource | undefined;\n private textureReady = false;\n private textureNeedsUpload = false;\n private textureWidth = 0;\n private textureHeight = 0;\n private activityPixels: Float32Array | undefined;\n private readonly wakeAUniforms = new Float32Array(MAX_WAKE_SEGMENTS * 4);\n private readonly wakeBUniforms = new Float32Array(MAX_WAKE_SEGMENTS * 4);\n private readonly wakeShapeUniforms = new Float32Array(MAX_WAKE_SEGMENTS * 4);\n\n constructor(\n private readonly canvas: HTMLCanvasElement,\n private readonly requestRender: () => void = () => undefined\n ) {\n const { gl, isWebGL2, canLinearFloat } = createContext(canvas);\n\n this.gl = gl;\n this.isWebGL2 = isWebGL2;\n this.canLinearFloat = canLinearFloat;\n this.quadBuffer = mustCreate(gl.createBuffer(), \"WebGL buffer\");\n this.simulationProgram = createProgramInfo(gl, VERTEX_SHADER, SIMULATION_SHADER);\n this.materialProgram = createProgramInfo(gl, VERTEX_SHADER, MATERIAL_SHADER);\n this.backgroundTexture = mustCreate(gl.createTexture(), \"WebGL texture\");\n this.causticTexture = mustCreate(gl.createTexture(), \"WebGL texture\");\n\n gl.bindBuffer(gl.ARRAY_BUFFER, this.quadBuffer);\n gl.bufferData(\n gl.ARRAY_BUFFER,\n new Float32Array([-1, -1, 1, -1, -1, 1, 1, 1]),\n gl.STATIC_DRAW\n );\n gl.disable(gl.DEPTH_TEST);\n gl.disable(gl.STENCIL_TEST);\n gl.disable(gl.BLEND);\n this.initializeBackgroundTexture();\n this.initializeCausticTexture();\n this.resize(1, 1, 1, 192);\n }\n\n resize(\n cssWidth: number,\n cssHeight: number,\n pixelRatio: number,\n simulationResolution: number\n ): void {\n this.cssWidth = Math.max(1, cssWidth);\n this.cssHeight = Math.max(1, cssHeight);\n const ratio = Math.min(2, Math.max(1, pixelRatio || 1));\n const renderWidth = Math.max(1, Math.round(this.cssWidth * ratio));\n const renderHeight = Math.max(1, Math.round(this.cssHeight * ratio));\n\n if (this.canvas.width !== renderWidth || this.canvas.height !== renderHeight) {\n this.canvas.width = renderWidth;\n this.canvas.height = renderHeight;\n }\n\n const longestSide = Math.max(\n MIN_SIMULATION_AXIS,\n Math.round(simulationResolution)\n );\n const aspect = this.cssWidth / this.cssHeight;\n let nextSimWidth = longestSide;\n let nextSimHeight = longestSide;\n\n if (aspect >= 1) {\n nextSimHeight = Math.round(longestSide / aspect);\n\n if (nextSimHeight < MIN_SIMULATION_AXIS) {\n nextSimHeight = MIN_SIMULATION_AXIS;\n nextSimWidth = Math.round(MIN_SIMULATION_AXIS * aspect);\n }\n } else {\n nextSimWidth = Math.round(longestSide * aspect);\n\n if (nextSimWidth < MIN_SIMULATION_AXIS) {\n nextSimWidth = MIN_SIMULATION_AXIS;\n nextSimHeight = Math.round(MIN_SIMULATION_AXIS / aspect);\n }\n }\n\n if (nextSimWidth === this.simWidth && nextSimHeight === this.simHeight) {\n return;\n }\n\n this.simWidth = nextSimWidth;\n this.simHeight = nextSimHeight;\n this.recreateState();\n }\n\n setTextureSource(source: WaterTextureSource | undefined): void {\n if (source === this.textureSource) {\n return;\n }\n\n this.textureSource = source;\n this.textureImage = undefined;\n this.textureReady = false;\n this.textureNeedsUpload = false;\n this.textureWidth = 0;\n this.textureHeight = 0;\n\n if (!source) {\n return;\n }\n\n if (typeof source !== \"string\") {\n this.textureImage = source;\n this.textureNeedsUpload = true;\n return;\n }\n\n const image = new Image();\n\n image.crossOrigin = \"anonymous\";\n image.onload = () => {\n if (this.textureSource === source) {\n this.textureImage = image;\n this.textureNeedsUpload = true;\n this.requestRender();\n }\n };\n image.onerror = () => {\n if (this.textureSource === source) {\n this.textureImage = undefined;\n this.textureReady = false;\n this.textureNeedsUpload = false;\n }\n };\n image.src = source;\n }\n\n step(\n disturbances: readonly WaterDisturbance[],\n settings: WaterRendererSettings,\n delta: number\n ): void {\n if (!this.stateTextures || !this.framebuffers) {\n return;\n }\n\n const gl = this.gl;\n const writeIndex = 1 - this.readIndex;\n\n gl.useProgram(this.simulationProgram.program);\n gl.bindFramebuffer(gl.FRAMEBUFFER, this.framebuffers[writeIndex]);\n gl.viewport(0, 0, this.simWidth, this.simHeight);\n gl.activeTexture(gl.TEXTURE0);\n gl.bindTexture(gl.TEXTURE_2D, this.stateTextures[this.readIndex]);\n this.prepareQuad(this.simulationProgram);\n this.setSimulationUniforms(disturbances, settings, delta);\n gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);\n gl.bindFramebuffer(gl.FRAMEBUFFER, null);\n this.readIndex = writeIndex;\n }\n\n render(settings: WaterRendererSettings, timeSeconds = 0): void {\n const gl = this.gl;\n\n if (!this.stateTextures) {\n return;\n }\n\n if (settings.texture) {\n this.setTextureSource(settings.texture);\n } else {\n this.setTextureSource(undefined);\n }\n\n this.uploadTextureIfNeeded(settings);\n\n gl.useProgram(this.materialProgram.program);\n gl.bindFramebuffer(gl.FRAMEBUFFER, null);\n gl.viewport(0, 0, this.canvas.width, this.canvas.height);\n gl.clearColor(0, 0, 0, 0);\n gl.clear(gl.COLOR_BUFFER_BIT);\n\n if (settings.mode !== \"dom\" && !this.textureReady) {\n return;\n }\n\n gl.activeTexture(gl.TEXTURE0);\n gl.bindTexture(gl.TEXTURE_2D, this.stateTextures[this.readIndex]);\n gl.activeTexture(gl.TEXTURE1);\n gl.bindTexture(gl.TEXTURE_2D, this.backgroundTexture);\n gl.activeTexture(gl.TEXTURE2);\n gl.bindTexture(gl.TEXTURE_2D, this.causticTexture);\n this.prepareQuad(this.materialProgram);\n this.setMaterialUniforms(settings, timeSeconds);\n gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);\n }\n\n hasVisibleActivity(): boolean {\n if (!this.framebuffers) {\n return false;\n }\n\n const gl = this.gl;\n const framebuffer = this.framebuffers[this.readIndex];\n const pixelCount = this.simWidth * this.simHeight * 4;\n\n if (!this.activityPixels || this.activityPixels.length !== pixelCount) {\n this.activityPixels = new Float32Array(pixelCount);\n }\n\n gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);\n\n try {\n gl.readPixels(\n 0,\n 0,\n this.simWidth,\n this.simHeight,\n gl.RGBA,\n gl.FLOAT,\n this.activityPixels\n );\n } finally {\n gl.bindFramebuffer(gl.FRAMEBUFFER, null);\n }\n\n return hasVisibleWaterActivity(\n this.activityPixels,\n this.simWidth,\n this.simHeight\n );\n }\n\n clear(): void {\n const gl = this.gl;\n\n if (this.framebuffers) {\n gl.viewport(0, 0, this.simWidth, this.simHeight);\n\n for (const framebuffer of this.framebuffers) {\n gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);\n gl.clearColor(0, 0, 0, 1);\n gl.clear(gl.COLOR_BUFFER_BIT);\n }\n }\n\n gl.bindFramebuffer(gl.FRAMEBUFFER, null);\n gl.viewport(0, 0, this.canvas.width, this.canvas.height);\n gl.clearColor(0, 0, 0, 0);\n gl.clear(gl.COLOR_BUFFER_BIT);\n }\n\n dispose(): void {\n const gl = this.gl;\n\n this.stateTextures?.forEach((texture) => gl.deleteTexture(texture));\n this.framebuffers?.forEach((framebuffer) => gl.deleteFramebuffer(framebuffer));\n gl.deleteTexture(this.backgroundTexture);\n gl.deleteTexture(this.causticTexture);\n gl.deleteBuffer(this.quadBuffer);\n gl.deleteProgram(this.simulationProgram.program);\n gl.deleteProgram(this.materialProgram.program);\n }\n\n private recreateState(): void {\n const gl = this.gl;\n\n this.stateTextures?.forEach((texture) => gl.deleteTexture(texture));\n this.framebuffers?.forEach((framebuffer) => gl.deleteFramebuffer(framebuffer));\n\n const firstTexture = this.createStateTexture();\n const secondTexture = this.createStateTexture();\n const firstFramebuffer = this.createFramebuffer(firstTexture);\n const secondFramebuffer = this.createFramebuffer(secondTexture);\n\n this.stateTextures = [firstTexture, secondTexture];\n this.framebuffers = [firstFramebuffer, secondFramebuffer];\n this.readIndex = 0;\n this.clear();\n }\n\n private createStateTexture(): WebGLTexture {\n const gl = this.gl;\n const texture = mustCreate(gl.createTexture(), \"WebGL texture\");\n\n gl.bindTexture(gl.TEXTURE_2D, texture);\n gl.texParameteri(\n gl.TEXTURE_2D,\n gl.TEXTURE_MIN_FILTER,\n this.canLinearFloat ? gl.LINEAR : gl.NEAREST\n );\n gl.texParameteri(\n gl.TEXTURE_2D,\n gl.TEXTURE_MAG_FILTER,\n this.canLinearFloat ? gl.LINEAR : gl.NEAREST\n );\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);\n\n if (this.isWebGL2) {\n const gl2 = gl as WebGL2RenderingContext;\n\n gl2.texImage2D(\n gl2.TEXTURE_2D,\n 0,\n gl2.RGBA32F,\n this.simWidth,\n this.simHeight,\n 0,\n gl2.RGBA,\n gl2.FLOAT,\n null\n );\n } else {\n gl.texImage2D(\n gl.TEXTURE_2D,\n 0,\n gl.RGBA,\n this.simWidth,\n this.simHeight,\n 0,\n gl.RGBA,\n gl.FLOAT,\n null\n );\n }\n\n return texture;\n }\n\n private createFramebuffer(texture: WebGLTexture): WebGLFramebuffer {\n const gl = this.gl;\n const framebuffer = mustCreate(gl.createFramebuffer(), \"WebGL framebuffer\");\n\n gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);\n gl.framebufferTexture2D(\n gl.FRAMEBUFFER,\n gl.COLOR_ATTACHMENT0,\n gl.TEXTURE_2D,\n texture,\n 0\n );\n\n if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) !== gl.FRAMEBUFFER_COMPLETE) {\n throw new Error(\"WaterDistortion could not create a float simulation target.\");\n }\n\n gl.bindFramebuffer(gl.FRAMEBUFFER, null);\n\n return framebuffer;\n }\n\n private initializeBackgroundTexture(): void {\n const gl = this.gl;\n\n gl.bindTexture(gl.TEXTURE_2D, this.backgroundTexture);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);\n gl.texImage2D(\n gl.TEXTURE_2D,\n 0,\n gl.RGBA,\n 1,\n 1,\n 0,\n gl.RGBA,\n gl.UNSIGNED_BYTE,\n new Uint8Array([18, 28, 26, 255])\n );\n }\n\n private initializeCausticTexture(): void {\n const gl = this.gl;\n\n gl.bindTexture(gl.TEXTURE_2D, this.causticTexture);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT);\n gl.texImage2D(\n gl.TEXTURE_2D,\n 0,\n gl.RGBA,\n CAUSTIC_MAP_SIZE,\n CAUSTIC_MAP_SIZE,\n 0,\n gl.RGBA,\n gl.UNSIGNED_BYTE,\n createCausticMap()\n );\n gl.generateMipmap(gl.TEXTURE_2D);\n }\n\n private uploadTextureIfNeeded(settings: WaterRendererSettings): void {\n if (\n settings.mode === \"dom\" ||\n !this.textureImage ||\n (!this.textureNeedsUpload && !shouldUploadEveryFrame(this.textureImage))\n ) {\n return;\n }\n\n const gl = this.gl;\n\n try {\n gl.bindTexture(gl.TEXTURE_2D, this.backgroundTexture);\n gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1);\n gl.texImage2D(\n gl.TEXTURE_2D,\n 0,\n gl.RGBA,\n gl.RGBA,\n gl.UNSIGNED_BYTE,\n this.textureImage\n );\n gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 0);\n [this.textureWidth, this.textureHeight] = getTextureDimensions(\n this.textureImage\n );\n this.textureReady = true;\n this.textureNeedsUpload = false;\n } catch {\n this.textureReady = false;\n this.textureNeedsUpload = false;\n this.textureWidth = 0;\n this.textureHeight = 0;\n }\n }\n\n private prepareQuad(program: ProgramInfo): void {\n const gl = this.gl;\n\n gl.bindBuffer(gl.ARRAY_BUFFER, this.quadBuffer);\n gl.enableVertexAttribArray(program.position);\n gl.vertexAttribPointer(program.position, 2, gl.FLOAT, false, 0, 0);\n }\n\n private setSimulationUniforms(\n disturbances: readonly WaterDisturbance[],\n settings: WaterRendererSettings,\n delta: number\n ): void {\n const gl = this.gl;\n const program = this.simulationProgram.program;\n const count = Math.min(disturbances.length, MAX_WAKE_SEGMENTS);\n const wakeA = this.wakeAUniforms;\n const wakeB = this.wakeBUniforms;\n const wakeShape = this.wakeShapeUniforms;\n const start = Math.max(0, disturbances.length - MAX_WAKE_SEGMENTS);\n\n wakeA.fill(0);\n wakeB.fill(0);\n wakeShape.fill(0);\n\n for (let index = 0; index < count; index += 1) {\n const disturbance = disturbances[start + index];\n const offset = index * 4;\n\n wakeA[offset] = disturbance.ax;\n wakeA[offset + 1] = disturbance.ay;\n wakeA[offset + 2] = disturbance.radius;\n wakeA[offset + 3] = disturbance.wakeStrength;\n wakeB[offset] = disturbance.bx;\n wakeB[offset + 1] = disturbance.by;\n wakeB[offset + 2] = disturbance.wakeLength;\n wakeB[offset + 3] = disturbance.velocity;\n wakeShape[offset] = disturbance.troughStrength;\n wakeShape[offset + 1] = disturbance.ridgeStrength;\n wakeShape[offset + 2] = disturbance.ridgeOffset;\n }\n\n gl.uniform1i(getUniform(gl, program, \"u_state\"), 0);\n gl.uniform2f(getUniform(gl, program, \"u_texel\"), 1 / this.simWidth, 1 / this.simHeight);\n gl.uniform1f(getUniform(gl, program, \"u_delta\"), delta);\n gl.uniform1f(getUniform(gl, program, \"u_damping\"), settings.damping);\n gl.uniform1f(getUniform(gl, program, \"u_stiffness\"), settings.waveSpeed);\n gl.uniform1f(getUniform(gl, program, \"u_aspect\"), this.cssWidth / this.cssHeight);\n gl.uniform1i(getUniform(gl, program, \"u_wakeCount\"), count);\n gl.uniform4fv(getUniform(gl, program, \"u_wakeA[0]\"), wakeA);\n gl.uniform4fv(getUniform(gl, program, \"u_wakeB[0]\"), wakeB);\n gl.uniform4fv(getUniform(gl, program, \"u_wakeShape[0]\"), wakeShape);\n }\n\n private setMaterialUniforms(\n settings: WaterRendererSettings,\n timeSeconds: number\n ): void {\n const gl = this.gl;\n const program = this.materialProgram.program;\n const [backgroundScaleX, backgroundScaleY] = calculateTextureUvScale(\n settings.textureFit,\n this.textureWidth,\n this.textureHeight,\n this.cssWidth,\n this.cssHeight\n );\n\n gl.uniform1i(getUniform(gl, program, \"u_state\"), 0);\n gl.uniform1i(getUniform(gl, program, \"u_background\"), 1);\n gl.uniform1i(getUniform(gl, program, \"u_causticMap\"), 2);\n gl.uniform2f(getUniform(gl, program, \"u_texel\"), 1 / this.simWidth, 1 / this.simHeight);\n gl.uniform2f(\n getUniform(gl, program, \"u_backgroundScale\"),\n backgroundScaleX,\n backgroundScaleY\n );\n gl.uniform1f(getUniform(gl, program, \"u_domMode\"), settings.mode === \"dom\" ? 1 : 0);\n gl.uniform1f(getUniform(gl, program, \"u_normalScale\"), settings.normalScale);\n gl.uniform1f(getUniform(gl, program, \"u_refractionStrength\"), settings.refractionStrength);\n gl.uniform1f(getUniform(gl, program, \"u_specularIntensity\"), settings.specularIntensity);\n gl.uniform1f(getUniform(gl, program, \"u_crestIntensity\"), settings.crestIntensity);\n gl.uniform1f(getUniform(gl, program, \"u_causticIntensity\"), settings.causticIntensity);\n gl.uniform1f(getUniform(gl, program, \"u_time\"), timeSeconds % 1000);\n }\n}\n\n/** @internal */\nexport function calculateTextureUvScale(\n fit: WaterTextureFit,\n sourceWidth: number,\n sourceHeight: number,\n targetWidth: number,\n targetHeight: number\n): [number, number] {\n if (\n fit === \"fill\" ||\n !Number.isFinite(sourceWidth) ||\n !Number.isFinite(sourceHeight) ||\n !Number.isFinite(targetWidth) ||\n !Number.isFinite(targetHeight) ||\n sourceWidth <= 0 ||\n sourceHeight <= 0 ||\n targetWidth <= 0 ||\n targetHeight <= 0\n ) {\n return [1, 1];\n }\n\n if (fit === \"none\") {\n return [targetWidth / sourceWidth, targetHeight / sourceHeight];\n }\n\n const sourceAspect = sourceWidth / sourceHeight;\n const targetAspect = targetWidth / targetHeight;\n\n if (fit === \"cover\") {\n return sourceAspect > targetAspect\n ? [targetAspect / sourceAspect, 1]\n : [1, sourceAspect / targetAspect];\n }\n\n return sourceAspect > targetAspect\n ? [1, sourceAspect / targetAspect]\n : [targetAspect / sourceAspect, 1];\n}\n\nfunction getTextureDimensions(source: TexImageSource): [number, number] {\n const dimensions = source as TexImageSource & {\n naturalWidth?: number;\n naturalHeight?: number;\n videoWidth?: number;\n videoHeight?: number;\n displayWidth?: number;\n displayHeight?: number;\n width?: number;\n height?: number;\n };\n const candidates = [\n [dimensions.naturalWidth, dimensions.naturalHeight],\n [dimensions.videoWidth, dimensions.videoHeight],\n [dimensions.displayWidth, dimensions.displayHeight],\n [dimensions.width, dimensions.height]\n ];\n\n for (const [width, height] of candidates) {\n if (\n typeof width === \"number\" &&\n typeof height === \"number\" &&\n Number.isFinite(width) &&\n Number.isFinite(height) &&\n width > 0 &&\n height > 0\n ) {\n return [width, height];\n }\n }\n\n return [0, 0];\n}\n\n/** @internal */\nexport function createCausticMap(): Uint8Array {\n const data = new Uint8Array(CAUSTIC_MAP_SIZE * CAUSTIC_MAP_SIZE * 4);\n\n for (let y = 0; y < CAUSTIC_MAP_SIZE; y += 1) {\n for (let x = 0; x < CAUSTIC_MAP_SIZE; x += 1) {\n const u = (x + 0.5) / CAUSTIC_MAP_SIZE;\n const v = (y + 0.5) / CAUSTIC_MAP_SIZE;\n const red = Math.round(createCausticChannel(u, v, 0.0) * 255);\n const green = Math.round(createCausticChannel(u, v, 11.0) * 255);\n const blue = Math.round(createCausticChannel(u, v, 23.0) * 255);\n const alpha = Math.round(createCausticChannel(u, v, 37.0) * 255);\n const index = (y * CAUSTIC_MAP_SIZE + x) * 4;\n\n data[index] = red;\n data[index + 1] = green;\n data[index + 2] = blue;\n data[index + 3] = alpha;\n }\n }\n\n return data;\n}\n\nfunction createCausticChannel(u: number, v: number, seed: number): number {\n const warpX =\n Math.sin(TAU * (v * 2 + seed * 0.013)) * 0.12 +\n Math.sin(TAU * (u * 3 + v + seed * 0.021)) * 0.06;\n const warpY =\n Math.cos(TAU * (u * 2 + seed * 0.017)) * 0.12 +\n Math.sin(TAU * (v * 3 - u + seed * 0.019)) * 0.06;\n const sampleX = u * CAUSTIC_CELL_COUNT + warpX;\n const sampleY = v * CAUSTIC_CELL_COUNT + warpY;\n const cellX = Math.floor(sampleX);\n const cellY = Math.floor(sampleY);\n let nearest = Number.POSITIVE_INFINITY;\n let secondNearest = Number.POSITIVE_INFINITY;\n let nearestCellX = 0;\n let nearestCellY = 0;\n\n for (let offsetY = -1; offsetY <= 1; offsetY += 1) {\n for (let offsetX = -1; offsetX <= 1; offsetX += 1) {\n const candidateX = cellX + offsetX;\n const candidateY = cellY + offsetY;\n const wrappedX = positiveModulo(candidateX, CAUSTIC_CELL_COUNT);\n const wrappedY = positiveModulo(candidateY, CAUSTIC_CELL_COUNT);\n const pointX =\n candidateX + 0.16 + hash2(wrappedX, wrappedY, seed) * 0.68;\n const pointY =\n candidateY + 0.16 + hash2(wrappedX, wrappedY, seed + 1) * 0.68;\n const distance = Math.hypot(sampleX - pointX, sampleY - pointY);\n\n if (distance < nearest) {\n secondNearest = nearest;\n nearest = distance;\n nearestCellX = wrappedX;\n nearestCellY = wrappedY;\n } else if (distance < secondNearest) {\n secondNearest = distance;\n }\n }\n }\n\n const edgeDistance = secondNearest - nearest;\n const core = 1 - smoothstepNumber(0.025, 0.13, edgeDistance);\n const glow = 1 - smoothstepNumber(0.08, 0.34, edgeDistance);\n const variation = 0.74 + hash2(nearestCellX, nearestCellY, seed + 2) * 0.26;\n const value = core * core * 0.58 + glow * 0.34;\n\n return clamp01(Math.pow(value * variation, 1.12));\n}\n\nfunction hash2(x: number, y: number, seed: number): number {\n const value = Math.sin(x * 127.1 + y * 311.7 + seed * 74.7) * 43758.5453123;\n\n return value - Math.floor(value);\n}\n\nfunction positiveModulo(value: number, divisor: number): number {\n return ((value % divisor) + divisor) % divisor;\n}\n\nfunction smoothstepNumber(edge0: number, edge1: number, value: number): number {\n const amount = clamp01((value - edge0) / (edge1 - edge0));\n\n return amount * amount * (3 - amount * 2);\n}\n\nfunction clamp01(value: number): number {\n return Math.min(1, Math.max(0, value));\n}\n\nfunction createContext(canvas: HTMLCanvasElement): {\n gl: WaterGL;\n isWebGL2: boolean;\n canLinearFloat: boolean;\n} {\n const attributes: WebGLContextAttributes = {\n alpha: true,\n antialias: false,\n depth: false,\n stencil: false,\n premultipliedAlpha: false,\n preserveDrawingBuffer: false\n };\n const webgl2 = canvas.getContext(\"webgl2\", attributes);\n\n if (webgl2) {\n if (!webgl2.getExtension(\"EXT_color_buffer_float\")) {\n throw new Error(\"WaterDistortion requires float render targets.\");\n }\n\n return {\n gl: webgl2,\n isWebGL2: true,\n canLinearFloat: !!webgl2.getExtension(\"OES_texture_float_linear\")\n };\n }\n\n const webgl1 =\n (canvas.getContext(\"webgl\", attributes) as WebGLRenderingContext | null) ||\n (canvas.getContext(\n \"experimental-webgl\",\n attributes\n ) as WebGLRenderingContext | null);\n\n if (!webgl1) {\n throw new Error(\"WaterDistortion requires WebGL.\");\n }\n\n if (\n !webgl1.getExtension(\"OES_texture_float\") ||\n (!webgl1.getExtension(\"WEBGL_color_buffer_float\") &&\n !webgl1.getExtension(\"EXT_color_buffer_float\"))\n ) {\n throw new Error(\"WaterDistortion requires float texture support.\");\n }\n\n return {\n gl: webgl1,\n isWebGL2: false,\n canLinearFloat: !!webgl1.getExtension(\"OES_texture_float_linear\")\n };\n}\n\nfunction createProgramInfo(\n gl: WaterGL,\n vertexSource: string,\n fragmentSource: string\n): ProgramInfo {\n const vertexShader = compileShader(gl, gl.VERTEX_SHADER, vertexSource);\n const fragmentShader = compileShader(gl, gl.FRAGMENT_SHADER, fragmentSource);\n const program = mustCreate(gl.createProgram(), \"WebGL program\");\n\n gl.attachShader(program, vertexShader);\n gl.attachShader(program, fragmentShader);\n gl.linkProgram(program);\n gl.deleteShader(vertexShader);\n gl.deleteShader(fragmentShader);\n\n if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {\n const error = gl.getProgramInfoLog(program) || \"Unknown shader link error.\";\n\n gl.deleteProgram(program);\n throw new Error(error);\n }\n\n const position = gl.getAttribLocation(program, \"a_position\");\n\n if (position < 0) {\n throw new Error(\"WaterDistortion could not bind its quad attribute.\");\n }\n\n return { program, position };\n}\n\nfunction compileShader(\n gl: WaterGL,\n type: number,\n source: string\n): WebGLShader {\n const shader = mustCreate(gl.createShader(type), \"WebGL shader\");\n\n gl.shaderSource(shader, source);\n gl.compileShader(shader);\n\n if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {\n const error = gl.getShaderInfoLog(shader) || \"Unknown shader compile error.\";\n\n gl.deleteShader(shader);\n throw new Error(error);\n }\n\n return shader;\n}\n\nfunction getUniform(\n gl: WaterGL,\n program: WebGLProgram,\n name: string\n): WebGLUniformLocation {\n const location = gl.getUniformLocation(program, name);\n\n if (!location) {\n throw new Error(`WaterDistortion could not bind uniform ${name}.`);\n }\n\n return location;\n}\n\nfunction mustCreate<T>(value: T | null, label: string): T {\n if (!value) {\n throw new Error(`WaterDistortion could not create ${label}.`);\n }\n\n return value;\n}\n\nfunction shouldUploadEveryFrame(source: TexImageSource): boolean {\n if (typeof HTMLCanvasElement !== \"undefined\" && source instanceof HTMLCanvasElement) {\n return true;\n }\n\n if (typeof HTMLVideoElement !== \"undefined\" && source instanceof HTMLVideoElement) {\n return true;\n }\n\n if (typeof OffscreenCanvas !== \"undefined\" && source instanceof OffscreenCanvas) {\n return true;\n }\n\n return false;\n}\n\nexport function hasVisibleWaterActivity(\n state: ArrayLike<number>,\n width: number,\n height: number,\n thresholds: WaterActivityThresholds = DEFAULT_ACTIVITY_THRESHOLDS\n): boolean {\n const safeWidth = Math.max(0, Math.floor(width));\n const safeHeight = Math.max(0, Math.floor(height));\n\n if (safeWidth === 0 || safeHeight === 0) {\n return false;\n }\n\n const readHeight = (x: number, y: number) =>\n state[(y * safeWidth + x) * 4] ?? 0;\n\n for (let y = 0; y < safeHeight; y += 1) {\n for (let x = 0; x < safeWidth; x += 1) {\n const index = (y * safeWidth + x) * 4;\n const current = state[index] ?? 0;\n const velocity = state[index + 1] ?? 0;\n\n if (\n current < -thresholds.trough ||\n Math.abs(velocity) > thresholds.velocity\n ) {\n return true;\n }\n\n const left = x > 0 ? readHeight(x - 1, y) : current;\n const right = x < safeWidth - 1 ? readHeight(x + 1, y) : current;\n const down = y > 0 ? readHeight(x, y - 1) : current;\n const up = y < safeHeight - 1 ? readHeight(x, y + 1) : current;\n const gradient = Math.hypot(right - left, up - down);\n const curvature = Math.abs(left + right + down + up - current * 4);\n\n if (\n gradient > thresholds.gradient ||\n curvature > thresholds.curvature\n ) {\n return true;\n }\n }\n }\n\n return false;\n}\n\n/** @internal */\nexport function mapHighlightToDomOverlay(\n highlight: WaterHighlightColor\n): WaterDomHighlightOverlay {\n const domEnergy = Math.max(0, highlight.r, highlight.g, highlight.b);\n const safeEnergy = Math.max(domEnergy, 0.00001);\n\n return {\n color: {\n r: Math.max(0, highlight.r) / safeEnergy,\n g: Math.max(0, highlight.g) / safeEnergy,\n b: Math.max(0, highlight.b) / safeEnergy\n },\n alpha: Math.min(\n DOM_HIGHLIGHT_SETTINGS.maxAlpha,\n domEnergy * DOM_HIGHLIGHT_SETTINGS.screenCompensation\n )\n };\n}\n","import { clamp, distance, lerp } from \"./math\";\n\nexport interface PointerSample {\n x: number;\n y: number;\n time: number;\n}\n\nexport interface WaterDisturbance {\n ax: number;\n ay: number;\n bx: number;\n by: number;\n radius: number;\n wakeStrength: number;\n troughStrength: number;\n ridgeStrength: number;\n ridgeOffset: number;\n wakeLength: number;\n velocity: number;\n}\n\nexport interface PointerDisturbanceOptions {\n width: number;\n height: number;\n interactionRadius: number;\n wakeStrength: number;\n troughStrength: number;\n ridgeStrength: number;\n ridgeOffset: number;\n wakeLength: number;\n velocityScale: number;\n velocityClamp: number;\n cursorSmoothing: number;\n segmentSpacing: number;\n}\n\nexport interface PointerEventLike {\n clientX: number;\n clientY: number;\n timeStamp: number;\n getCoalescedEvents?: () => PointerEventLike[];\n}\n\nexport interface BoundsLike {\n left: number;\n top: number;\n}\n\nconst DEFAULT_OPTIONS: PointerDisturbanceOptions = {\n width: 1,\n height: 1,\n interactionRadius: 25,\n wakeStrength: 0.54,\n troughStrength: 0.92,\n ridgeStrength: 0.46,\n ridgeOffset: 10,\n wakeLength: 84,\n velocityScale: 1,\n velocityClamp: 1.35,\n cursorSmoothing: 0.2,\n segmentSpacing: 18\n};\nconst MAX_SEGMENTS_PER_SAMPLE = 24;\n\nfunction normalizeOptions(\n options: Partial<PointerDisturbanceOptions>\n): PointerDisturbanceOptions {\n return {\n width: Math.max(1, options.width ?? DEFAULT_OPTIONS.width),\n height: Math.max(1, options.height ?? DEFAULT_OPTIONS.height),\n interactionRadius: Math.max(\n 1,\n options.interactionRadius ?? DEFAULT_OPTIONS.interactionRadius\n ),\n wakeStrength: Math.max(\n 0,\n options.wakeStrength ?? DEFAULT_OPTIONS.wakeStrength\n ),\n troughStrength: Math.max(\n 0,\n options.troughStrength ?? DEFAULT_OPTIONS.troughStrength\n ),\n ridgeStrength: Math.max(\n 0,\n options.ridgeStrength ?? DEFAULT_OPTIONS.ridgeStrength\n ),\n ridgeOffset: Math.max(0, options.ridgeOffset ?? DEFAULT_OPTIONS.ridgeOffset),\n wakeLength: Math.max(1, options.wakeLength ?? DEFAULT_OPTIONS.wakeLength),\n velocityScale: Math.max(\n 0.01,\n options.velocityScale ?? DEFAULT_OPTIONS.velocityScale\n ),\n velocityClamp: Math.max(\n 0.05,\n options.velocityClamp ?? DEFAULT_OPTIONS.velocityClamp\n ),\n cursorSmoothing: clamp(\n options.cursorSmoothing ?? DEFAULT_OPTIONS.cursorSmoothing,\n 0,\n 0.9\n ),\n segmentSpacing: Math.max(\n 1,\n options.segmentSpacing ?? DEFAULT_OPTIONS.segmentSpacing\n )\n };\n}\n\nexport function getPointerSamples(\n event: PointerEventLike,\n bounds: BoundsLike,\n now = event.timeStamp\n): PointerSample[] {\n const events =\n typeof event.getCoalescedEvents === \"function\"\n ? event.getCoalescedEvents()\n : [];\n const sourceEvents = events.length > 0 ? events : [event];\n const clockOffset = now - event.timeStamp;\n\n return sourceEvents.map((pointerEvent) => ({\n x: pointerEvent.clientX - bounds.left,\n y: pointerEvent.clientY - bounds.top,\n time: pointerEvent.timeStamp + clockOffset\n }));\n}\n\nexport class PointerDisturbanceTracker {\n private options: PointerDisturbanceOptions;\n private previous: PointerSample | undefined;\n private smoothedVelocity = 0;\n private readonly disturbances: WaterDisturbance[] = [];\n\n constructor(options: Partial<PointerDisturbanceOptions> = {}) {\n this.options = normalizeOptions(options);\n }\n\n configure(options: Partial<PointerDisturbanceOptions>): void {\n this.options = normalizeOptions({\n ...this.options,\n ...options\n });\n }\n\n reset(): void {\n this.previous = undefined;\n this.smoothedVelocity = 0;\n this.disturbances.length = 0;\n }\n\n addSample(sample: PointerSample): readonly WaterDisturbance[] {\n this.disturbances.length = 0;\n\n const raw = this.clampSample(sample);\n const previous = this.previous;\n\n if (!previous) {\n this.previous = raw;\n return this.disturbances;\n }\n\n if (raw.time <= previous.time) {\n raw.time = previous.time + 0.01;\n }\n\n const current = this.smoothSample(previous, raw);\n const segmentLength = distance(previous, current);\n\n if (segmentLength < 0.35) {\n this.previous = current;\n return this.disturbances;\n }\n\n const velocity = segmentLength / Math.max(0.01, current.time - previous.time);\n const velocityFollow = clamp(1 - this.options.cursorSmoothing, 0.12, 1);\n\n this.smoothedVelocity = lerp(\n this.smoothedVelocity,\n velocity,\n velocityFollow\n );\n this.previous = current;\n\n const segmentCount = Math.min(\n MAX_SEGMENTS_PER_SAMPLE,\n Math.max(1, Math.ceil(segmentLength / this.options.segmentSpacing))\n );\n\n for (let index = 0; index < segmentCount; index += 1) {\n const start = index / segmentCount;\n const end = (index + 1) / segmentCount;\n\n this.disturbances.push(\n createDisturbance(\n interpolateSample(previous, current, start),\n interpolateSample(previous, current, end),\n this.smoothedVelocity,\n this.options\n )\n );\n }\n\n return this.disturbances;\n }\n\n private clampSample(sample: PointerSample): PointerSample {\n return {\n x: clamp(sample.x, 0, this.options.width),\n y: clamp(sample.y, 0, this.options.height),\n time: sample.time\n };\n }\n\n private smoothSample(previous: PointerSample, raw: PointerSample): PointerSample {\n const follow = 1 - this.options.cursorSmoothing;\n\n return {\n x: lerp(previous.x, raw.x, follow),\n y: lerp(previous.y, raw.y, follow),\n time: raw.time\n };\n }\n}\n\nexport function createDisturbance(\n from: PointerSample,\n to: PointerSample,\n velocityPxMs: number,\n options: Partial<PointerDisturbanceOptions>\n): WaterDisturbance {\n const normalized = normalizeOptions(options);\n const speedAmount = clamp(\n (velocityPxMs * normalized.velocityScale) / normalized.velocityClamp,\n 0,\n 1\n );\n const fromY = clamp(from.y / normalized.height, 0, 1);\n const toY = clamp(to.y / normalized.height, 0, 1);\n const wakeLengthPx = normalized.wakeLength * lerp(0.55, 1.35, speedAmount);\n\n return {\n ax: clamp(from.x / normalized.width, 0, 1),\n ay: 1 - fromY,\n bx: clamp(to.x / normalized.width, 0, 1),\n by: 1 - toY,\n radius: normalized.interactionRadius / normalized.height,\n wakeStrength: normalized.wakeStrength * lerp(0.18, 1, speedAmount),\n troughStrength: normalized.troughStrength,\n ridgeStrength: normalized.ridgeStrength,\n ridgeOffset: normalized.ridgeOffset / normalized.height,\n wakeLength: wakeLengthPx / normalized.height,\n velocity: speedAmount\n };\n}\n\nfunction interpolateSample(\n from: PointerSample,\n to: PointerSample,\n amount: number\n): PointerSample {\n return {\n x: lerp(from.x, to.x, amount),\n y: lerp(from.y, to.y, amount),\n time: lerp(from.time, to.time, amount)\n };\n}\n\nexport function estimateSettleDuration(damping: number): number {\n const safeDamping = clamp(damping, 0.85, 0.998);\n const frames = Math.ceil(Math.log(0.012) / Math.log(safeDamping));\n\n return clamp(frames * (1000 / 60), 900, 5200);\n}\n","import type { CSSProperties, ReactNode } from \"react\";\nimport {\n forwardRef,\n useEffect,\n useImperativeHandle,\n useRef,\n useState\n} from \"react\";\nimport { clamp } from \"./core/math\";\nimport {\n HeightfieldWaterRenderer,\n type WaterRenderMode,\n type WaterRendererSettings,\n type WaterTextureFit,\n type WaterTextureSource\n} from \"./core/waterRenderer\";\nimport {\n PointerDisturbanceTracker,\n createDisturbance,\n estimateSettleDuration,\n getPointerSamples,\n type WaterDisturbance\n} from \"./core/waterInteraction\";\n\nexport type ReducedMotionBehavior = \"respect\" | \"disable\" | \"ignore\";\nexport type WaterInteractionMode =\n | \"move\"\n | \"click\"\n | \"both\"\n | \"drag\"\n | \"event\";\n\nexport interface WaterRipplePosition {\n /** Horizontal position normalized from 0 (left) to 1 (right). */\n x: number;\n /** Vertical position normalized from 0 (top) to 1 (bottom). */\n y: number;\n}\n\nexport interface WaterDistortionHandle {\n triggerRipple(position: WaterRipplePosition): void;\n}\n\nexport interface WaterDistortionProps {\n underlay?: ReactNode;\n children?: ReactNode;\n foreground?: ReactNode;\n mode?: WaterRenderMode;\n texture?: WaterTextureSource;\n textureFit?: WaterTextureFit;\n rippleStrength?: number;\n wakeStrength?: number;\n interactionRadius?: number;\n troughStrength?: number;\n ridgeStrength?: number;\n ridgeOffset?: number;\n wakeLength?: number;\n velocityScale?: number;\n velocityClamp?: number;\n cursorSmoothing?: number;\n segmentSpacing?: number;\n strength?: number;\n damping?: number;\n dissipation?: number;\n waveSpeed?: number;\n normalScale?: number;\n refractionStrength?: number;\n specularIntensity?: number;\n crestIntensity?: number;\n causticIntensity?: number;\n simulationResolution?: number;\n idleTimeout?: number;\n blur?: number;\n maxTrailPoints?: number;\n maxStamps?: number;\n trailSpacing?: number;\n className?: string;\n style?: CSSProperties;\n reducedMotion?: ReducedMotionBehavior;\n interactionMode?: WaterInteractionMode;\n runInBackground?: boolean;\n pauseKey?: string;\n}\n\ninterface RuntimeSettings extends WaterRendererSettings {\n wakeStrength: number;\n interactionRadius: number;\n troughStrength: number;\n ridgeStrength: number;\n ridgeOffset: number;\n wakeLength: number;\n velocityScale: number;\n velocityClamp: number;\n cursorSmoothing: number;\n segmentSpacing: number;\n idleTimeout: number;\n interactionMode: WaterInteractionMode;\n runInBackground: boolean;\n pauseKey?: string;\n}\n\nconst DEFAULT_SETTINGS: RuntimeSettings = {\n mode: \"texture\",\n textureFit: \"fill\",\n damping: 0.98,\n waveSpeed: 0.4,\n normalScale: 20,\n refractionStrength: 0.7,\n specularIntensity: 1,\n crestIntensity: 0.2,\n causticIntensity: 0,\n simulationResolution: 192,\n wakeStrength: 0.54,\n interactionRadius: 25,\n troughStrength: 0.92,\n ridgeStrength: 0.46,\n ridgeOffset: 10,\n wakeLength: 84,\n velocityScale: 1,\n velocityClamp: 1.35,\n cursorSmoothing: 0.2,\n segmentSpacing: 18,\n idleTimeout: 900,\n interactionMode: \"move\",\n runInBackground: false,\n pauseKey: undefined\n};\n\nconst STEP_MS = 1000 / 60;\nconst MAX_FRAME_STEPS = 4;\nconst MAX_BACKGROUND_FRAME_STEPS = 360;\nconst MAX_PENDING_DISTURBANCES = 24;\nconst SETTLE_CHECK_INTERVAL_MS = 200;\n\nfunction isInteractiveKeyboardTarget(target: EventTarget | null): boolean {\n return (\n target instanceof Element &&\n target.closest(\n \"a, button, input, select, textarea, [contenteditable]:not([contenteditable=false])\"\n ) !== null\n );\n}\n\nfunction getRuntimeSettings(props: WaterDistortionProps): RuntimeSettings {\n const legacyStrength =\n props.strength === undefined ? undefined : props.strength / 48;\n\n return {\n mode: props.mode ?? DEFAULT_SETTINGS.mode,\n texture: props.texture,\n textureFit: props.textureFit ?? DEFAULT_SETTINGS.textureFit,\n damping: clamp(\n props.damping ?? props.dissipation ?? DEFAULT_SETTINGS.damping,\n 0.85,\n 0.998\n ),\n waveSpeed: clamp(props.waveSpeed ?? DEFAULT_SETTINGS.waveSpeed, 0.05, 1),\n normalScale: clamp(\n props.normalScale ?? DEFAULT_SETTINGS.normalScale,\n 1,\n 80\n ),\n refractionStrength: clamp(\n props.refractionStrength ?? DEFAULT_SETTINGS.refractionStrength,\n 0,\n 2.5\n ),\n specularIntensity: clamp(\n props.specularIntensity ?? DEFAULT_SETTINGS.specularIntensity,\n 0,\n 3\n ),\n crestIntensity: clamp(\n props.crestIntensity ?? DEFAULT_SETTINGS.crestIntensity,\n 0,\n 3\n ),\n causticIntensity: clamp(\n props.causticIntensity ?? DEFAULT_SETTINGS.causticIntensity,\n 0,\n 3\n ),\n simulationResolution: clamp(\n Math.round(\n props.simulationResolution ?? DEFAULT_SETTINGS.simulationResolution\n ),\n 64,\n 384\n ),\n wakeStrength: clamp(\n props.wakeStrength ??\n props.rippleStrength ??\n legacyStrength ??\n DEFAULT_SETTINGS.wakeStrength,\n 0,\n 3\n ),\n interactionRadius: clamp(\n props.interactionRadius ?? DEFAULT_SETTINGS.interactionRadius,\n 2,\n 80\n ),\n troughStrength: clamp(\n props.troughStrength ?? DEFAULT_SETTINGS.troughStrength,\n 0,\n 3\n ),\n ridgeStrength: clamp(\n props.ridgeStrength ?? DEFAULT_SETTINGS.ridgeStrength,\n 0,\n 3\n ),\n ridgeOffset: clamp(\n props.ridgeOffset ?? DEFAULT_SETTINGS.ridgeOffset,\n 0,\n 80\n ),\n wakeLength: clamp(\n props.wakeLength ?? DEFAULT_SETTINGS.wakeLength,\n 1,\n 240\n ),\n velocityScale: clamp(\n props.velocityScale ?? DEFAULT_SETTINGS.velocityScale,\n 0.01,\n 4\n ),\n velocityClamp: clamp(\n props.velocityClamp ?? DEFAULT_SETTINGS.velocityClamp,\n 0.05,\n 8\n ),\n cursorSmoothing: clamp(\n props.cursorSmoothing ?? DEFAULT_SETTINGS.cursorSmoothing,\n 0,\n 0.9\n ),\n segmentSpacing: clamp(\n props.segmentSpacing ?? DEFAULT_SETTINGS.segmentSpacing,\n 1,\n 96\n ),\n idleTimeout: Math.max(120, props.idleTimeout ?? DEFAULT_SETTINGS.idleTimeout),\n interactionMode:\n props.interactionMode ?? DEFAULT_SETTINGS.interactionMode,\n runInBackground:\n props.runInBackground ?? DEFAULT_SETTINGS.runInBackground,\n pauseKey: props.pauseKey || DEFAULT_SETTINGS.pauseKey\n };\n}\n\nfunction createRippleDisturbances(\n position: WaterRipplePosition,\n settings: RuntimeSettings,\n size: { width: number; height: number }\n): WaterDisturbance[] {\n const centerX = clamp(position.x, 0, 1) * size.width;\n const centerY = clamp(position.y, 0, 1) * size.height;\n const halfSegment = Math.max(0.5, settings.interactionRadius * 0.08);\n const velocity = settings.velocityClamp / settings.velocityScale;\n const options = {\n ...settings,\n width: size.width,\n height: size.height,\n wakeLength: settings.interactionRadius * 1.5\n };\n\n return [\n createDisturbance(\n { x: centerX - halfSegment, y: centerY, time: 0 },\n { x: centerX + halfSegment, y: centerY, time: 1 },\n velocity,\n options\n ),\n createDisturbance(\n { x: centerX, y: centerY - halfSegment, time: 0 },\n { x: centerX, y: centerY + halfSegment, time: 1 },\n velocity,\n options\n )\n ];\n}\n\nfunction usePrefersReducedMotion(enabled: boolean): boolean {\n const [prefersReducedMotion, setPrefersReducedMotion] = useState(false);\n\n useEffect(() => {\n if (!enabled || typeof window === \"undefined\" || !window.matchMedia) {\n setPrefersReducedMotion(false);\n return;\n }\n\n const query = window.matchMedia(\"(prefers-reduced-motion: reduce)\");\n\n setPrefersReducedMotion(query.matches);\n\n const handleChange = (event: MediaQueryListEvent) => {\n setPrefersReducedMotion(event.matches);\n };\n\n query.addEventListener(\"change\", handleChange);\n\n return () => {\n query.removeEventListener(\"change\", handleChange);\n };\n }, [enabled]);\n\n return prefersReducedMotion;\n}\n\nexport const WaterDistortion = forwardRef<\n WaterDistortionHandle,\n WaterDistortionProps\n>(function WaterDistortion(props, ref) {\n const {\n underlay,\n children,\n foreground,\n className,\n style,\n reducedMotion = \"respect\"\n } = props;\n const containerRef = useRef<HTMLDivElement | null>(null);\n const canvasRef = useRef<HTMLCanvasElement | null>(null);\n const rendererRef = useRef<HeightfieldWaterRenderer | null>(null);\n const trackerRef = useRef(new PointerDisturbanceTracker());\n const frameRef = useRef<number | null>(null);\n const backgroundTimerRef = useRef<number | null>(null);\n const requestFrameRef = useRef<() => void>(() => undefined);\n const syncFocusBehaviorRef = useRef<() => void>(() => undefined);\n const queueDisturbancesRef = useRef<\n (disturbances: readonly WaterDisturbance[]) => void\n >(() => undefined);\n const pendingDisturbancesRef = useRef<WaterDisturbance[]>([]);\n const visibleRef = useRef(true);\n const focusedRef = useRef(true);\n const disabledRef = useRef(false);\n const pausedRef = useRef(false);\n const activeDragPointerIdRef = useRef<number | null>(null);\n const idleUntilRef = useRef(0);\n const fallbackActiveUntilRef = useRef(0);\n const nextSettleCheckRef = useRef(0);\n const settings = getRuntimeSettings(props);\n const settingsRef = useRef(settings);\n const sizeRef = useRef({ width: 1, height: 1 });\n const prefersReducedMotion = usePrefersReducedMotion(\n reducedMotion === \"respect\"\n );\n const effectDisabled =\n reducedMotion === \"disable\" ||\n (reducedMotion === \"respect\" && prefersReducedMotion);\n const foregroundContent = foreground ?? children;\n\n settingsRef.current = settings;\n\n useImperativeHandle(\n ref,\n () => ({\n triggerRipple(position) {\n if (disabledRef.current || pausedRef.current) {\n return;\n }\n\n queueDisturbancesRef.current(\n createRippleDisturbances(\n position,\n settingsRef.current,\n sizeRef.current\n )\n );\n }\n }),\n []\n );\n\n useEffect(() => {\n disabledRef.current = effectDisabled;\n\n if (effectDisabled) {\n trackerRef.current.reset();\n activeDragPointerIdRef.current = null;\n pendingDisturbancesRef.current = [];\n idleUntilRef.current = 0;\n fallbackActiveUntilRef.current = 0;\n nextSettleCheckRef.current = 0;\n rendererRef.current?.clear();\n }\n\n requestFrameRef.current();\n }, [effectDisabled]);\n\n useEffect(() => {\n const renderer = rendererRef.current;\n\n if (!renderer) {\n return;\n }\n\n const { width, height } = sizeRef.current;\n\n renderer.resize(\n width,\n height,\n window.devicePixelRatio,\n settings.simulationResolution\n );\n renderer.setTextureSource(settings.texture);\n requestFrameRef.current();\n }, [\n settings.mode,\n settings.texture,\n settings.textureFit,\n settings.damping,\n settings.waveSpeed,\n settings.normalScale,\n settings.refractionStrength,\n settings.specularIntensity,\n settings.crestIntensity,\n settings.causticIntensity,\n settings.simulationResolution\n ]);\n\n useEffect(() => {\n const container = containerRef.current;\n const canvas = canvasRef.current;\n\n if (!container || !canvas) {\n return;\n }\n\n focusedRef.current =\n typeof document.hasFocus === \"function\" ? document.hasFocus() : true;\n\n let renderer: HeightfieldWaterRenderer | null = null;\n let lastFrameTime: number | undefined;\n let accumulator = STEP_MS;\n let activityReadbackFailed = false;\n let pausedAt: number | undefined;\n\n const cancelFrame = () => {\n if (frameRef.current !== null) {\n window.cancelAnimationFrame(frameRef.current);\n frameRef.current = null;\n }\n\n if (backgroundTimerRef.current !== null) {\n window.clearTimeout(backgroundTimerRef.current);\n backgroundTimerRef.current = null;\n }\n };\n\n const updateTrackerSize = (width: number, height: number) => {\n trackerRef.current.configure({\n width,\n height,\n interactionRadius: settingsRef.current.interactionRadius,\n wakeStrength: settingsRef.current.wakeStrength,\n troughStrength: settingsRef.current.troughStrength,\n ridgeStrength: settingsRef.current.ridgeStrength,\n ridgeOffset: settingsRef.current.ridgeOffset,\n wakeLength: settingsRef.current.wakeLength,\n velocityScale: settingsRef.current.velocityScale,\n velocityClamp: settingsRef.current.velocityClamp,\n cursorSmoothing: settingsRef.current.cursorSmoothing,\n segmentSpacing: settingsRef.current.segmentSpacing\n });\n };\n\n const updateSize = (width: number, height: number) => {\n const safeWidth = Math.max(1, width);\n const safeHeight = Math.max(1, height);\n\n sizeRef.current = { width: safeWidth, height: safeHeight };\n updateTrackerSize(safeWidth, safeHeight);\n renderer?.resize(\n safeWidth,\n safeHeight,\n window.devicePixelRatio,\n settingsRef.current.simulationResolution\n );\n };\n\n const renderStatic = () => {\n renderer?.render(settingsRef.current, performance.now() * 0.001);\n };\n\n const sleep = () => {\n lastFrameTime = undefined;\n accumulator = STEP_MS;\n };\n\n const pauseAnimation = () => {\n cancelFrame();\n trackerRef.current.reset();\n activeDragPointerIdRef.current = null;\n sleep();\n\n if (pausedAt === undefined) {\n pausedAt = performance.now();\n }\n };\n\n const resumeAnimation = () => {\n const currentSettings = settingsRef.current;\n let resumedFromPause = false;\n const canRun =\n !disabledRef.current &&\n !pausedRef.current &&\n visibleRef.current &&\n (currentSettings.runInBackground ||\n (!document.hidden && focusedRef.current));\n\n if (!canRun) {\n sleep();\n return;\n }\n\n if (pausedAt !== undefined) {\n const pausedDuration = performance.now() - pausedAt;\n\n idleUntilRef.current += pausedDuration;\n fallbackActiveUntilRef.current += pausedDuration;\n nextSettleCheckRef.current += pausedDuration;\n pausedAt = undefined;\n resumedFromPause = true;\n }\n\n if (!currentSettings.runInBackground || resumedFromPause) {\n sleep();\n }\n\n renderStatic();\n requestFrameRef.current();\n };\n\n const frame = (time: number) => {\n frameRef.current = null;\n const currentSettings = settingsRef.current;\n\n if (\n !renderer ||\n pausedRef.current ||\n !visibleRef.current ||\n (!currentSettings.runInBackground &&\n (document.hidden || !focusedRef.current))\n ) {\n sleep();\n return;\n }\n\n if (disabledRef.current) {\n pendingDisturbancesRef.current = [];\n renderer.render(currentSettings, time * 0.001);\n sleep();\n return;\n }\n\n const maxFrameSteps = currentSettings.runInBackground\n ? MAX_BACKGROUND_FRAME_STEPS\n : MAX_FRAME_STEPS;\n const elapsed =\n lastFrameTime === undefined\n ? STEP_MS\n : clamp(\n time - lastFrameTime,\n 0,\n currentSettings.runInBackground\n ? STEP_MS * MAX_BACKGROUND_FRAME_STEPS\n : 64\n );\n\n lastFrameTime = time;\n accumulator = Math.min(\n accumulator + elapsed,\n STEP_MS * maxFrameSteps\n );\n\n let disturbances = pendingDisturbancesRef.current.splice(0);\n let steps = 0;\n\n while (accumulator >= STEP_MS && steps < maxFrameSteps) {\n renderer.step(disturbances, currentSettings, 1);\n disturbances = [];\n accumulator -= STEP_MS;\n steps += 1;\n }\n\n renderer.render(currentSettings, time * 0.001);\n\n if (pendingDisturbancesRef.current.length > 0) {\n requestFrameRef.current();\n return;\n }\n\n if (time < idleUntilRef.current) {\n requestFrameRef.current();\n return;\n }\n\n if (activityReadbackFailed) {\n if (time < fallbackActiveUntilRef.current) {\n requestFrameRef.current();\n } else {\n sleep();\n }\n\n return;\n }\n\n if (time < nextSettleCheckRef.current) {\n requestFrameRef.current();\n return;\n }\n\n try {\n if (renderer.hasVisibleActivity()) {\n nextSettleCheckRef.current = time + SETTLE_CHECK_INTERVAL_MS;\n requestFrameRef.current();\n } else {\n sleep();\n }\n } catch {\n activityReadbackFailed = true;\n\n if (time < fallbackActiveUntilRef.current) {\n requestFrameRef.current();\n } else {\n sleep();\n }\n }\n };\n\n const requestFrame = () => {\n if (\n pausedRef.current ||\n frameRef.current !== null ||\n backgroundTimerRef.current !== null\n ) {\n return;\n }\n\n if (settingsRef.current.runInBackground && document.hidden) {\n backgroundTimerRef.current = window.setTimeout(() => {\n backgroundTimerRef.current = null;\n frame(performance.now());\n }, STEP_MS);\n } else {\n frameRef.current = window.requestAnimationFrame(frame);\n }\n };\n\n requestFrameRef.current = requestFrame;\n\n try {\n renderer = new HeightfieldWaterRenderer(canvas, () => {\n requestFrameRef.current();\n });\n rendererRef.current = renderer;\n renderer.setTextureSource(settingsRef.current.texture);\n } catch {\n canvas.style.display = \"none\";\n rendererRef.current = null;\n requestFrameRef.current = () => undefined;\n return () => undefined;\n }\n\n const syncSize = () => {\n const rect = canvas.getBoundingClientRect();\n updateSize(rect.width, rect.height);\n\n return rect;\n };\n\n const readSize = () => {\n syncSize();\n renderStatic();\n };\n\n const queueDisturbances = (\n disturbances: readonly WaterDisturbance[]\n ) => {\n if (pausedRef.current || disturbances.length === 0) {\n return;\n }\n\n const pending = pendingDisturbancesRef.current;\n\n for (const disturbance of disturbances) {\n pending.push(disturbance);\n }\n\n if (pending.length > MAX_PENDING_DISTURBANCES) {\n pending.splice(0, pending.length - MAX_PENDING_DISTURBANCES);\n }\n\n const now = performance.now();\n const idleUntil = now + settingsRef.current.idleTimeout;\n\n idleUntilRef.current = Math.max(idleUntilRef.current, idleUntil);\n fallbackActiveUntilRef.current = Math.max(\n fallbackActiveUntilRef.current,\n idleUntil + estimateSettleDuration(settingsRef.current.damping)\n );\n nextSettleCheckRef.current = 0;\n requestFrame();\n };\n\n queueDisturbancesRef.current = queueDisturbances;\n\n const handlePointerStart = (event: PointerEvent) => {\n const currentSettings = settingsRef.current;\n\n if (\n disabledRef.current ||\n pausedRef.current ||\n !visibleRef.current ||\n currentSettings.interactionMode === \"event\" ||\n (!currentSettings.runInBackground &&\n (document.hidden || !focusedRef.current))\n ) {\n return;\n }\n\n if (event.pointerType === \"touch\" && !event.isPrimary) {\n return;\n }\n\n trackerRef.current.reset();\n const rect = syncSize();\n const [sample] = getPointerSamples(event, rect, performance.now());\n\n if (sample) {\n if (\n currentSettings.interactionMode === \"click\" ||\n currentSettings.interactionMode === \"both\" ||\n currentSettings.interactionMode === \"drag\"\n ) {\n queueDisturbances(\n createRippleDisturbances(\n {\n x: sample.x / sizeRef.current.width,\n y: sample.y / sizeRef.current.height\n },\n currentSettings,\n sizeRef.current\n )\n );\n }\n\n if (currentSettings.interactionMode === \"drag\") {\n activeDragPointerIdRef.current = event.pointerId;\n trackerRef.current.addSample(sample);\n } else if (\n currentSettings.interactionMode === \"move\" ||\n currentSettings.interactionMode === \"both\"\n ) {\n trackerRef.current.addSample(sample);\n }\n }\n };\n\n const handlePointerMove = (event: PointerEvent) => {\n const currentSettings = settingsRef.current;\n\n if (\n disabledRef.current ||\n pausedRef.current ||\n !visibleRef.current ||\n (currentSettings.interactionMode !== \"move\" &&\n currentSettings.interactionMode !== \"both\" &&\n (currentSettings.interactionMode !== \"drag\" ||\n activeDragPointerIdRef.current !== event.pointerId)) ||\n (!currentSettings.runInBackground &&\n (document.hidden || !focusedRef.current))\n ) {\n return;\n }\n\n if (event.pointerType === \"touch\" && !event.isPrimary) {\n return;\n }\n\n const rect = syncSize();\n const samples = getPointerSamples(event, rect, performance.now());\n\n for (const sample of samples) {\n queueDisturbances(trackerRef.current.addSample(sample));\n }\n };\n\n const handleStrokeEnd = (event: PointerEvent) => {\n if (\n activeDragPointerIdRef.current !== null &&\n activeDragPointerIdRef.current !== event.pointerId\n ) {\n return;\n }\n\n activeDragPointerIdRef.current = null;\n trackerRef.current.reset();\n };\n\n const handleKeyDown = (event: KeyboardEvent) => {\n const pauseKey = settingsRef.current.pauseKey;\n\n if (\n !pauseKey ||\n event.code !== pauseKey ||\n event.repeat ||\n event.altKey ||\n event.ctrlKey ||\n event.metaKey ||\n isInteractiveKeyboardTarget(event.target)\n ) {\n return;\n }\n\n event.preventDefault();\n pausedRef.current = !pausedRef.current;\n\n if (pausedRef.current) {\n pauseAnimation();\n } else {\n cancelFrame();\n resumeAnimation();\n }\n };\n\n const handleVisibilityChange = () => {\n cancelFrame();\n\n if (document.hidden && !settingsRef.current.runInBackground) {\n pauseAnimation();\n } else {\n resumeAnimation();\n }\n };\n\n const handleWindowBlur = () => {\n focusedRef.current = false;\n\n if (settingsRef.current.runInBackground) {\n cancelFrame();\n resumeAnimation();\n } else {\n pauseAnimation();\n }\n };\n\n const handleWindowFocus = () => {\n focusedRef.current = true;\n cancelFrame();\n resumeAnimation();\n };\n\n const syncFocusBehavior = () => {\n cancelFrame();\n\n if (\n !settingsRef.current.runInBackground &&\n (document.hidden || !focusedRef.current)\n ) {\n pauseAnimation();\n } else {\n resumeAnimation();\n }\n };\n\n syncFocusBehaviorRef.current = syncFocusBehavior;\n\n readSize();\n\n const resizeObserver = new ResizeObserver(() => {\n readSize();\n requestFrame();\n });\n\n resizeObserver.observe(canvas);\n\n let intersectionObserver: IntersectionObserver | undefined;\n\n if (\"IntersectionObserver\" in window) {\n intersectionObserver = new IntersectionObserver((entries) => {\n const entry = entries[0];\n\n visibleRef.current = entry ? entry.isIntersecting : true;\n\n if (!visibleRef.current) {\n pauseAnimation();\n } else {\n resumeAnimation();\n }\n });\n intersectionObserver.observe(container);\n }\n\n container.addEventListener(\"pointerdown\", handlePointerStart, {\n passive: true\n });\n container.addEventListener(\"pointermove\", handlePointerMove, {\n passive: true\n });\n container.addEventListener(\"pointerup\", handleStrokeEnd, {\n passive: true\n });\n container.addEventListener(\"pointerleave\", handleStrokeEnd, {\n passive: true\n });\n container.addEventListener(\"pointercancel\", handleStrokeEnd, {\n passive: true\n });\n window.addEventListener(\"blur\", handleWindowBlur);\n window.addEventListener(\"focus\", handleWindowFocus);\n document.addEventListener(\"keydown\", handleKeyDown);\n document.addEventListener(\"visibilitychange\", handleVisibilityChange);\n\n return () => {\n cancelFrame();\n resizeObserver.disconnect();\n intersectionObserver?.disconnect();\n container.removeEventListener(\"pointerdown\", handlePointerStart);\n container.removeEventListener(\"pointermove\", handlePointerMove);\n container.removeEventListener(\"pointerup\", handleStrokeEnd);\n container.removeEventListener(\"pointerleave\", handleStrokeEnd);\n container.removeEventListener(\"pointercancel\", handleStrokeEnd);\n window.removeEventListener(\"blur\", handleWindowBlur);\n window.removeEventListener(\"focus\", handleWindowFocus);\n document.removeEventListener(\"keydown\", handleKeyDown);\n document.removeEventListener(\"visibilitychange\", handleVisibilityChange);\n rendererRef.current?.dispose();\n rendererRef.current = null;\n requestFrameRef.current = () => undefined;\n syncFocusBehaviorRef.current = () => undefined;\n queueDisturbancesRef.current = () => undefined;\n };\n }, []);\n\n useEffect(() => {\n trackerRef.current.reset();\n activeDragPointerIdRef.current = null;\n }, [settings.interactionMode]);\n\n useEffect(() => {\n syncFocusBehaviorRef.current();\n }, [settings.runInBackground]);\n\n useEffect(() => {\n if (!settings.pauseKey && pausedRef.current) {\n pausedRef.current = false;\n syncFocusBehaviorRef.current();\n }\n }, [settings.pauseKey]);\n\n const containerStyle: CSSProperties = {\n ...style,\n position: \"relative\",\n overflow: \"hidden\",\n isolation: \"isolate\"\n };\n\n return (\n <div ref={containerRef} className={className} style={containerStyle}>\n {underlay ? (\n <div\n style={{\n position: \"absolute\",\n inset: 0,\n zIndex: 0,\n pointerEvents: \"none\",\n transform: \"translateZ(0)\"\n }}\n >\n {underlay}\n </div>\n ) : null}\n <canvas\n ref={canvasRef}\n aria-hidden=\"true\"\n style={{\n position: \"absolute\",\n inset: 0,\n zIndex: 1,\n width: \"100%\",\n height: \"100%\",\n pointerEvents: \"none\",\n mixBlendMode: settings.mode === \"dom\" ? \"screen\" : \"normal\"\n }}\n />\n <div\n style={{\n position: \"relative\",\n zIndex: 2\n }}\n >\n {foregroundContent}\n </div>\n </div>\n );\n});\n\nexport const WaterLayer = WaterDistortion;\nexport type { WaterRenderMode, WaterTextureFit, WaterTextureSource };\n"],"names":["clamp","value","min","max","distance","a","b","lerp","amount","MAX_WAKE_SEGMENTS","MIN_SIMULATION_AXIS","CAUSTIC_MAP_SIZE","CAUSTIC_CELL_COUNT","TAU","DOM_HIGHLIGHT_SETTINGS","DEFAULT_ACTIVITY_THRESHOLDS","VERTEX_SHADER","SIMULATION_SHADER","MATERIAL_SHADER","HeightfieldWaterRenderer","canvas","requestRender","__publicField","gl","isWebGL2","canLinearFloat","createContext","mustCreate","createProgramInfo","cssWidth","cssHeight","pixelRatio","simulationResolution","ratio","renderWidth","renderHeight","longestSide","aspect","nextSimWidth","nextSimHeight","source","image","disturbances","settings","delta","writeIndex","timeSeconds","framebuffer","pixelCount","hasVisibleWaterActivity","_a","texture","_b","firstTexture","secondTexture","firstFramebuffer","secondFramebuffer","gl2","createCausticMap","shouldUploadEveryFrame","getTextureDimensions","program","count","wakeA","wakeB","wakeShape","start","index","disturbance","offset","getUniform","backgroundScaleX","backgroundScaleY","calculateTextureUvScale","fit","sourceWidth","sourceHeight","targetWidth","targetHeight","sourceAspect","targetAspect","dimensions","candidates","width","height","data","y","x","u","v","red","createCausticChannel","green","blue","alpha","seed","warpX","warpY","sampleX","sampleY","cellX","cellY","nearest","secondNearest","nearestCellX","nearestCellY","offsetY","offsetX","candidateX","candidateY","wrappedX","positiveModulo","wrappedY","pointX","hash2","pointY","edgeDistance","core","smoothstepNumber","glow","variation","clamp01","divisor","edge0","edge1","attributes","webgl2","webgl1","vertexSource","fragmentSource","vertexShader","compileShader","fragmentShader","error","position","type","shader","name","location","label","state","thresholds","safeWidth","safeHeight","readHeight","current","velocity","left","right","down","up","gradient","curvature","DEFAULT_OPTIONS","MAX_SEGMENTS_PER_SAMPLE","normalizeOptions","options","getPointerSamples","event","bounds","now","events","sourceEvents","clockOffset","pointerEvent","PointerDisturbanceTracker","sample","raw","previous","segmentLength","velocityFollow","segmentCount","end","createDisturbance","interpolateSample","follow","from","to","velocityPxMs","normalized","speedAmount","fromY","toY","wakeLengthPx","estimateSettleDuration","damping","safeDamping","frames","DEFAULT_SETTINGS","STEP_MS","MAX_FRAME_STEPS","MAX_BACKGROUND_FRAME_STEPS","MAX_PENDING_DISTURBANCES","SETTLE_CHECK_INTERVAL_MS","isInteractiveKeyboardTarget","target","getRuntimeSettings","props","legacyStrength","createRippleDisturbances","size","centerX","centerY","halfSegment","usePrefersReducedMotion","enabled","prefersReducedMotion","setPrefersReducedMotion","useState","useEffect","query","handleChange","WaterDistortion","forwardRef","ref","underlay","children","foreground","className","style","reducedMotion","containerRef","useRef","canvasRef","rendererRef","trackerRef","frameRef","backgroundTimerRef","requestFrameRef","syncFocusBehaviorRef","queueDisturbancesRef","pendingDisturbancesRef","visibleRef","focusedRef","disabledRef","pausedRef","activeDragPointerIdRef","idleUntilRef","fallbackActiveUntilRef","nextSettleCheckRef","settingsRef","sizeRef","effectDisabled","foregroundContent","useImperativeHandle","renderer","container","lastFrameTime","accumulator","activityReadbackFailed","pausedAt","cancelFrame","updateTrackerSize","updateSize","renderStatic","sleep","pauseAnimation","resumeAnimation","currentSettings","resumedFromPause","pausedDuration","frame","time","maxFrameSteps","elapsed","steps","requestFrame","syncSize","rect","readSize","queueDisturbances","pending","idleUntil","handlePointerStart","handlePointerMove","samples","handleStrokeEnd","handleKeyDown","pauseKey","handleVisibilityChange","handleWindowBlur","handleWindowFocus","syncFocusBehavior","resizeObserver","intersectionObserver","entries","entry","containerStyle","jsx","WaterLayer"],"mappings":";;;;;AAKO,SAASA,EAAMC,GAAeC,GAAaC,GAAqB;AACrE,SAAO,KAAK,IAAIA,GAAK,KAAK,IAAID,GAAKD,CAAK,CAAC;AAC3C;AAEO,SAASG,GAASC,GAAYC,GAAoB;AACvD,SAAO,KAAK,MAAMA,EAAE,IAAID,EAAE,GAAGC,EAAE,IAAID,EAAE,CAAC;AACxC;AAEO,SAASE,EAAKF,GAAWC,GAAWE,GAAwB;AACjE,SAAOH,KAAKC,IAAID,KAAKG;AACvB;ACgCA,MAAMC,KAAoB,IACpBC,IAAsB,IACtBC,IAAmB,KACnBC,KAAqB,GACrBC,KAAM,KAAK,KAAK,GAETC,KAAyB;AAAA,EACpC,aAAa;AAAA,EACb,oBAAoB;AAAA,EACpB,UAAU;AACZ,GACMC,KAAuD;AAAA,EAC3D,UAAU;AAAA,EACV,WAAW;AAAA,EACX,QAAQ;AAAA,EACR,UAAU;AACZ,GACMC,KAAgB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GAUhBC,KAAoB;AAAA;AAAA;AAAA,4BAGER,EAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GA4FvCS,KAAkB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,iCAkBSJ,GAAuB,YAAY,QAAQ,CAAC,CAAC;AAAA,wCACtCA,GAAuB,mBAAmB,QAAQ,CAAC,CAAC;AAAA,8BAC9DA,GAAuB,SAAS,QAAQ,CAAC,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA2HjE,MAAMK,GAAyB;AAAA,EA2BpC,YACmBC,GACAC,IAA4B,MAAA;AAAA,KAC7C;AA7Be,IAAAC,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA;AACT,IAAAA,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA,mBAAY;AACZ,IAAAA,EAAA,kBAAW;AACX,IAAAA,EAAA,mBAAY;AACZ,IAAAA,EAAA,kBAAW;AACX,IAAAA,EAAA,mBAAY;AACZ,IAAAA,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA,sBAAe;AACf,IAAAA,EAAA,4BAAqB;AACrB,IAAAA,EAAA,sBAAe;AACf,IAAAA,EAAA,uBAAgB;AAChB,IAAAA,EAAA;AACS,IAAAA,EAAA,uBAAgB,IAAI,aAAab,KAAoB,CAAC;AACtD,IAAAa,EAAA,uBAAgB,IAAI,aAAab,KAAoB,CAAC;AACtD,IAAAa,EAAA,2BAAoB,IAAI,aAAab,KAAoB,CAAC;AAGxD,SAAA,SAAAW,GACA,KAAA,gBAAAC;AAEjB,UAAM,EAAE,IAAAE,GAAI,UAAAC,GAAU,gBAAAC,EAAA,IAAmBC,GAAcN,CAAM;AAE7D,SAAK,KAAKG,GACV,KAAK,WAAWC,GAChB,KAAK,iBAAiBC,GACtB,KAAK,aAAaE,EAAWJ,EAAG,aAAA,GAAgB,cAAc,GAC9D,KAAK,oBAAoBK,GAAkBL,GAAIP,IAAeC,EAAiB,GAC/E,KAAK,kBAAkBW,GAAkBL,GAAIP,IAAeE,EAAe,GAC3E,KAAK,oBAAoBS,EAAWJ,EAAG,cAAA,GAAiB,eAAe,GACvE,KAAK,iBAAiBI,EAAWJ,EAAG,cAAA,GAAiB,eAAe,GAEpEA,EAAG,WAAWA,EAAG,cAAc,KAAK,UAAU,GAC9CA,EAAG;AAAA,MACDA,EAAG;AAAA,MACH,IAAI,aAAa,CAAC,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,GAAG,CAAC,CAAC;AAAA,MAC7CA,EAAG;AAAA,IAAA,GAELA,EAAG,QAAQA,EAAG,UAAU,GACxBA,EAAG,QAAQA,EAAG,YAAY,GAC1BA,EAAG,QAAQA,EAAG,KAAK,GACnB,KAAK,4BAAA,GACL,KAAK,yBAAA,GACL,KAAK,OAAO,GAAG,GAAG,GAAG,GAAG;AAAA,EAC1B;AAAA,EAEA,OACEM,GACAC,GACAC,GACAC,GACM;AACN,SAAK,WAAW,KAAK,IAAI,GAAGH,CAAQ,GACpC,KAAK,YAAY,KAAK,IAAI,GAAGC,CAAS;AACtC,UAAMG,IAAQ,KAAK,IAAI,GAAG,KAAK,IAAI,GAAGF,KAAc,CAAC,CAAC,GAChDG,IAAc,KAAK,IAAI,GAAG,KAAK,MAAM,KAAK,WAAWD,CAAK,CAAC,GAC3DE,IAAe,KAAK,IAAI,GAAG,KAAK,MAAM,KAAK,YAAYF,CAAK,CAAC;AAEnE,KAAI,KAAK,OAAO,UAAUC,KAAe,KAAK,OAAO,WAAWC,OAC9D,KAAK,OAAO,QAAQD,GACpB,KAAK,OAAO,SAASC;AAGvB,UAAMC,IAAc,KAAK;AAAA,MACvB1B;AAAA,MACA,KAAK,MAAMsB,CAAoB;AAAA,IAAA,GAE3BK,IAAS,KAAK,WAAW,KAAK;AACpC,QAAIC,IAAeF,GACfG,IAAgBH;AAkBpB,IAhBIC,KAAU,KACZE,IAAgB,KAAK,MAAMH,IAAcC,CAAM,GAE3CE,IAAgB7B,MAClB6B,IAAgB7B,GAChB4B,IAAe,KAAK,MAAM5B,IAAsB2B,CAAM,OAGxDC,IAAe,KAAK,MAAMF,IAAcC,CAAM,GAE1CC,IAAe5B,MACjB4B,IAAe5B,GACf6B,IAAgB,KAAK,MAAM7B,IAAsB2B,CAAM,KAIvD,EAAAC,MAAiB,KAAK,YAAYC,MAAkB,KAAK,eAI7D,KAAK,WAAWD,GAChB,KAAK,YAAYC,GACjB,KAAK,cAAA;AAAA,EACP;AAAA,EAEA,iBAAiBC,GAA8C;AAY7D,QAXIA,MAAW,KAAK,kBAIpB,KAAK,gBAAgBA,GACrB,KAAK,eAAe,QACpB,KAAK,eAAe,IACpB,KAAK,qBAAqB,IAC1B,KAAK,eAAe,GACpB,KAAK,gBAAgB,GAEjB,CAACA;AACH;AAGF,QAAI,OAAOA,KAAW,UAAU;AAC9B,WAAK,eAAeA,GACpB,KAAK,qBAAqB;AAC1B;AAAA,IACF;AAEA,UAAMC,IAAQ,IAAI,MAAA;AAElB,IAAAA,EAAM,cAAc,aACpBA,EAAM,SAAS,MAAM;AACnB,MAAI,KAAK,kBAAkBD,MACzB,KAAK,eAAeC,GACpB,KAAK,qBAAqB,IAC1B,KAAK,cAAA;AAAA,IAET,GACAA,EAAM,UAAU,MAAM;AACpB,MAAI,KAAK,kBAAkBD,MACzB,KAAK,eAAe,QACpB,KAAK,eAAe,IACpB,KAAK,qBAAqB;AAAA,IAE9B,GACAC,EAAM,MAAMD;AAAA,EACd;AAAA,EAEA,KACEE,GACAC,GACAC,GACM;AACN,QAAI,CAAC,KAAK,iBAAiB,CAAC,KAAK;AAC/B;AAGF,UAAMrB,IAAK,KAAK,IACVsB,IAAa,IAAI,KAAK;AAE5B,IAAAtB,EAAG,WAAW,KAAK,kBAAkB,OAAO,GAC5CA,EAAG,gBAAgBA,EAAG,aAAa,KAAK,aAAasB,CAAU,CAAC,GAChEtB,EAAG,SAAS,GAAG,GAAG,KAAK,UAAU,KAAK,SAAS,GAC/CA,EAAG,cAAcA,EAAG,QAAQ,GAC5BA,EAAG,YAAYA,EAAG,YAAY,KAAK,cAAc,KAAK,SAAS,CAAC,GAChE,KAAK,YAAY,KAAK,iBAAiB,GACvC,KAAK,sBAAsBmB,GAAcC,GAAUC,CAAK,GACxDrB,EAAG,WAAWA,EAAG,gBAAgB,GAAG,CAAC,GACrCA,EAAG,gBAAgBA,EAAG,aAAa,IAAI,GACvC,KAAK,YAAYsB;AAAA,EACnB;AAAA,EAEA,OAAOF,GAAiCG,IAAc,GAAS;AAC7D,UAAMvB,IAAK,KAAK;AAEhB,IAAK,KAAK,kBAINoB,EAAS,UACX,KAAK,iBAAiBA,EAAS,OAAO,IAEtC,KAAK,iBAAiB,MAAS,GAGjC,KAAK,sBAAsBA,CAAQ,GAEnCpB,EAAG,WAAW,KAAK,gBAAgB,OAAO,GAC1CA,EAAG,gBAAgBA,EAAG,aAAa,IAAI,GACvCA,EAAG,SAAS,GAAG,GAAG,KAAK,OAAO,OAAO,KAAK,OAAO,MAAM,GACvDA,EAAG,WAAW,GAAG,GAAG,GAAG,CAAC,GACxBA,EAAG,MAAMA,EAAG,gBAAgB,GAExB,EAAAoB,EAAS,SAAS,SAAS,CAAC,KAAK,kBAIrCpB,EAAG,cAAcA,EAAG,QAAQ,GAC5BA,EAAG,YAAYA,EAAG,YAAY,KAAK,cAAc,KAAK,SAAS,CAAC,GAChEA,EAAG,cAAcA,EAAG,QAAQ,GAC5BA,EAAG,YAAYA,EAAG,YAAY,KAAK,iBAAiB,GACpDA,EAAG,cAAcA,EAAG,QAAQ,GAC5BA,EAAG,YAAYA,EAAG,YAAY,KAAK,cAAc,GACjD,KAAK,YAAY,KAAK,eAAe,GACrC,KAAK,oBAAoBoB,GAAUG,CAAW,GAC9CvB,EAAG,WAAWA,EAAG,gBAAgB,GAAG,CAAC;AAAA,EACvC;AAAA,EAEA,qBAA8B;AAC5B,QAAI,CAAC,KAAK;AACR,aAAO;AAGT,UAAMA,IAAK,KAAK,IACVwB,IAAc,KAAK,aAAa,KAAK,SAAS,GAC9CC,IAAa,KAAK,WAAW,KAAK,YAAY;AAEpD,KAAI,CAAC,KAAK,kBAAkB,KAAK,eAAe,WAAWA,OACzD,KAAK,iBAAiB,IAAI,aAAaA,CAAU,IAGnDzB,EAAG,gBAAgBA,EAAG,aAAawB,CAAW;AAE9C,QAAI;AACF,MAAAxB,EAAG;AAAA,QACD;AAAA,QACA;AAAA,QACA,KAAK;AAAA,QACL,KAAK;AAAA,QACLA,EAAG;AAAA,QACHA,EAAG;AAAA,QACH,KAAK;AAAA,MAAA;AAAA,IAET,UAAA;AACE,MAAAA,EAAG,gBAAgBA,EAAG,aAAa,IAAI;AAAA,IACzC;AAEA,WAAO0B;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,IAAA;AAAA,EAET;AAAA,EAEA,QAAc;AACZ,UAAM1B,IAAK,KAAK;AAEhB,QAAI,KAAK,cAAc;AACrB,MAAAA,EAAG,SAAS,GAAG,GAAG,KAAK,UAAU,KAAK,SAAS;AAE/C,iBAAWwB,KAAe,KAAK;AAC7B,QAAAxB,EAAG,gBAAgBA,EAAG,aAAawB,CAAW,GAC9CxB,EAAG,WAAW,GAAG,GAAG,GAAG,CAAC,GACxBA,EAAG,MAAMA,EAAG,gBAAgB;AAAA,IAEhC;AAEA,IAAAA,EAAG,gBAAgBA,EAAG,aAAa,IAAI,GACvCA,EAAG,SAAS,GAAG,GAAG,KAAK,OAAO,OAAO,KAAK,OAAO,MAAM,GACvDA,EAAG,WAAW,GAAG,GAAG,GAAG,CAAC,GACxBA,EAAG,MAAMA,EAAG,gBAAgB;AAAA,EAC9B;AAAA,EAEA,UAAgB;;AACd,UAAMA,IAAK,KAAK;AAEhB,KAAA2B,IAAA,KAAK,kBAAL,QAAAA,EAAoB,QAAQ,CAACC,MAAY5B,EAAG,cAAc4B,CAAO,KACjEC,IAAA,KAAK,iBAAL,QAAAA,EAAmB,QAAQ,CAACL,MAAgBxB,EAAG,kBAAkBwB,CAAW,IAC5ExB,EAAG,cAAc,KAAK,iBAAiB,GACvCA,EAAG,cAAc,KAAK,cAAc,GACpCA,EAAG,aAAa,KAAK,UAAU,GAC/BA,EAAG,cAAc,KAAK,kBAAkB,OAAO,GAC/CA,EAAG,cAAc,KAAK,gBAAgB,OAAO;AAAA,EAC/C;AAAA,EAEQ,gBAAsB;;AAC5B,UAAMA,IAAK,KAAK;AAEhB,KAAA2B,IAAA,KAAK,kBAAL,QAAAA,EAAoB,QAAQ,CAACC,MAAY5B,EAAG,cAAc4B,CAAO,KACjEC,IAAA,KAAK,iBAAL,QAAAA,EAAmB,QAAQ,CAACL,MAAgBxB,EAAG,kBAAkBwB,CAAW;AAE5E,UAAMM,IAAe,KAAK,mBAAA,GACpBC,IAAgB,KAAK,mBAAA,GACrBC,IAAmB,KAAK,kBAAkBF,CAAY,GACtDG,IAAoB,KAAK,kBAAkBF,CAAa;AAE9D,SAAK,gBAAgB,CAACD,GAAcC,CAAa,GACjD,KAAK,eAAe,CAACC,GAAkBC,CAAiB,GACxD,KAAK,YAAY,GACjB,KAAK,MAAA;AAAA,EACP;AAAA,EAEQ,qBAAmC;AACzC,UAAMjC,IAAK,KAAK,IACV4B,IAAUxB,EAAWJ,EAAG,cAAA,GAAiB,eAAe;AAgB9D,QAdAA,EAAG,YAAYA,EAAG,YAAY4B,CAAO,GACrC5B,EAAG;AAAA,MACDA,EAAG;AAAA,MACHA,EAAG;AAAA,MACH,KAAK,iBAAiBA,EAAG,SAASA,EAAG;AAAA,IAAA,GAEvCA,EAAG;AAAA,MACDA,EAAG;AAAA,MACHA,EAAG;AAAA,MACH,KAAK,iBAAiBA,EAAG,SAASA,EAAG;AAAA,IAAA,GAEvCA,EAAG,cAAcA,EAAG,YAAYA,EAAG,gBAAgBA,EAAG,aAAa,GACnEA,EAAG,cAAcA,EAAG,YAAYA,EAAG,gBAAgBA,EAAG,aAAa,GAE/D,KAAK,UAAU;AACjB,YAAMkC,IAAMlC;AAEZ,MAAAkC,EAAI;AAAA,QACFA,EAAI;AAAA,QACJ;AAAA,QACAA,EAAI;AAAA,QACJ,KAAK;AAAA,QACL,KAAK;AAAA,QACL;AAAA,QACAA,EAAI;AAAA,QACJA,EAAI;AAAA,QACJ;AAAA,MAAA;AAAA,IAEJ;AACE,MAAAlC,EAAG;AAAA,QACDA,EAAG;AAAA,QACH;AAAA,QACAA,EAAG;AAAA,QACH,KAAK;AAAA,QACL,KAAK;AAAA,QACL;AAAA,QACAA,EAAG;AAAA,QACHA,EAAG;AAAA,QACH;AAAA,MAAA;AAIJ,WAAO4B;AAAA,EACT;AAAA,EAEQ,kBAAkBA,GAAyC;AACjE,UAAM5B,IAAK,KAAK,IACVwB,IAAcpB,EAAWJ,EAAG,kBAAA,GAAqB,mBAAmB;AAW1E,QATAA,EAAG,gBAAgBA,EAAG,aAAawB,CAAW,GAC9CxB,EAAG;AAAA,MACDA,EAAG;AAAA,MACHA,EAAG;AAAA,MACHA,EAAG;AAAA,MACH4B;AAAA,MACA;AAAA,IAAA,GAGE5B,EAAG,uBAAuBA,EAAG,WAAW,MAAMA,EAAG;AACnD,YAAM,IAAI,MAAM,6DAA6D;AAG/E,WAAAA,EAAG,gBAAgBA,EAAG,aAAa,IAAI,GAEhCwB;AAAA,EACT;AAAA,EAEQ,8BAAoC;AAC1C,UAAMxB,IAAK,KAAK;AAEhB,IAAAA,EAAG,YAAYA,EAAG,YAAY,KAAK,iBAAiB,GACpDA,EAAG,cAAcA,EAAG,YAAYA,EAAG,oBAAoBA,EAAG,MAAM,GAChEA,EAAG,cAAcA,EAAG,YAAYA,EAAG,oBAAoBA,EAAG,MAAM,GAChEA,EAAG,cAAcA,EAAG,YAAYA,EAAG,gBAAgBA,EAAG,aAAa,GACnEA,EAAG,cAAcA,EAAG,YAAYA,EAAG,gBAAgBA,EAAG,aAAa,GACnEA,EAAG;AAAA,MACDA,EAAG;AAAA,MACH;AAAA,MACAA,EAAG;AAAA,MACH;AAAA,MACA;AAAA,MACA;AAAA,MACAA,EAAG;AAAA,MACHA,EAAG;AAAA,MACH,IAAI,WAAW,CAAC,IAAI,IAAI,IAAI,GAAG,CAAC;AAAA,IAAA;AAAA,EAEpC;AAAA,EAEQ,2BAAiC;AACvC,UAAMA,IAAK,KAAK;AAEhB,IAAAA,EAAG,YAAYA,EAAG,YAAY,KAAK,cAAc,GACjDA,EAAG,cAAcA,EAAG,YAAYA,EAAG,oBAAoBA,EAAG,oBAAoB,GAC9EA,EAAG,cAAcA,EAAG,YAAYA,EAAG,oBAAoBA,EAAG,MAAM,GAChEA,EAAG,cAAcA,EAAG,YAAYA,EAAG,gBAAgBA,EAAG,MAAM,GAC5DA,EAAG,cAAcA,EAAG,YAAYA,EAAG,gBAAgBA,EAAG,MAAM,GAC5DA,EAAG;AAAA,MACDA,EAAG;AAAA,MACH;AAAA,MACAA,EAAG;AAAA,MACHZ;AAAA,MACAA;AAAA,MACA;AAAA,MACAY,EAAG;AAAA,MACHA,EAAG;AAAA,MACHmC,GAAA;AAAA,IAAiB,GAEnBnC,EAAG,eAAeA,EAAG,UAAU;AAAA,EACjC;AAAA,EAEQ,sBAAsBoB,GAAuC;AACnE,QACEA,EAAS,SAAS,SAClB,CAAC,KAAK,gBACL,CAAC,KAAK,sBAAsB,CAACgB,GAAuB,KAAK,YAAY;AAEtE;AAGF,UAAMpC,IAAK,KAAK;AAEhB,QAAI;AACF,MAAAA,EAAG,YAAYA,EAAG,YAAY,KAAK,iBAAiB,GACpDA,EAAG,YAAYA,EAAG,qBAAqB,CAAC,GACxCA,EAAG;AAAA,QACDA,EAAG;AAAA,QACH;AAAA,QACAA,EAAG;AAAA,QACHA,EAAG;AAAA,QACHA,EAAG;AAAA,QACH,KAAK;AAAA,MAAA,GAEPA,EAAG,YAAYA,EAAG,qBAAqB,CAAC,GACxC,CAAC,KAAK,cAAc,KAAK,aAAa,IAAIqC;AAAA,QACxC,KAAK;AAAA,MAAA,GAEP,KAAK,eAAe,IACpB,KAAK,qBAAqB;AAAA,IAC5B,QAAQ;AACN,WAAK,eAAe,IACpB,KAAK,qBAAqB,IAC1B,KAAK,eAAe,GACpB,KAAK,gBAAgB;AAAA,IACvB;AAAA,EACF;AAAA,EAEQ,YAAYC,GAA4B;AAC9C,UAAMtC,IAAK,KAAK;AAEhB,IAAAA,EAAG,WAAWA,EAAG,cAAc,KAAK,UAAU,GAC9CA,EAAG,wBAAwBsC,EAAQ,QAAQ,GAC3CtC,EAAG,oBAAoBsC,EAAQ,UAAU,GAAGtC,EAAG,OAAO,IAAO,GAAG,CAAC;AAAA,EACnE;AAAA,EAEQ,sBACNmB,GACAC,GACAC,GACM;AACN,UAAMrB,IAAK,KAAK,IACVsC,IAAU,KAAK,kBAAkB,SACjCC,IAAQ,KAAK,IAAIpB,EAAa,QAAQjC,EAAiB,GACvDsD,IAAQ,KAAK,eACbC,IAAQ,KAAK,eACbC,IAAY,KAAK,mBACjBC,IAAQ,KAAK,IAAI,GAAGxB,EAAa,SAASjC,EAAiB;AAEjE,IAAAsD,EAAM,KAAK,CAAC,GACZC,EAAM,KAAK,CAAC,GACZC,EAAU,KAAK,CAAC;AAEhB,aAASE,IAAQ,GAAGA,IAAQL,GAAOK,KAAS,GAAG;AAC7C,YAAMC,IAAc1B,EAAawB,IAAQC,CAAK,GACxCE,IAASF,IAAQ;AAEvB,MAAAJ,EAAMM,CAAM,IAAID,EAAY,IAC5BL,EAAMM,IAAS,CAAC,IAAID,EAAY,IAChCL,EAAMM,IAAS,CAAC,IAAID,EAAY,QAChCL,EAAMM,IAAS,CAAC,IAAID,EAAY,cAChCJ,EAAMK,CAAM,IAAID,EAAY,IAC5BJ,EAAMK,IAAS,CAAC,IAAID,EAAY,IAChCJ,EAAMK,IAAS,CAAC,IAAID,EAAY,YAChCJ,EAAMK,IAAS,CAAC,IAAID,EAAY,UAChCH,EAAUI,CAAM,IAAID,EAAY,gBAChCH,EAAUI,IAAS,CAAC,IAAID,EAAY,eACpCH,EAAUI,IAAS,CAAC,IAAID,EAAY;AAAA,IACtC;AAEA,IAAA7C,EAAG,UAAU+C,EAAW/C,GAAIsC,GAAS,SAAS,GAAG,CAAC,GAClDtC,EAAG,UAAU+C,EAAW/C,GAAIsC,GAAS,SAAS,GAAG,IAAI,KAAK,UAAU,IAAI,KAAK,SAAS,GACtFtC,EAAG,UAAU+C,EAAW/C,GAAIsC,GAAS,SAAS,GAAGjB,CAAK,GACtDrB,EAAG,UAAU+C,EAAW/C,GAAIsC,GAAS,WAAW,GAAGlB,EAAS,OAAO,GACnEpB,EAAG,UAAU+C,EAAW/C,GAAIsC,GAAS,aAAa,GAAGlB,EAAS,SAAS,GACvEpB,EAAG,UAAU+C,EAAW/C,GAAIsC,GAAS,UAAU,GAAG,KAAK,WAAW,KAAK,SAAS,GAChFtC,EAAG,UAAU+C,EAAW/C,GAAIsC,GAAS,aAAa,GAAGC,CAAK,GAC1DvC,EAAG,WAAW+C,EAAW/C,GAAIsC,GAAS,YAAY,GAAGE,CAAK,GAC1DxC,EAAG,WAAW+C,EAAW/C,GAAIsC,GAAS,YAAY,GAAGG,CAAK,GAC1DzC,EAAG,WAAW+C,EAAW/C,GAAIsC,GAAS,gBAAgB,GAAGI,CAAS;AAAA,EACpE;AAAA,EAEQ,oBACNtB,GACAG,GACM;AACN,UAAMvB,IAAK,KAAK,IACVsC,IAAU,KAAK,gBAAgB,SAC/B,CAACU,GAAkBC,CAAgB,IAAIC;AAAA,MAC3C9B,EAAS;AAAA,MACT,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,IAAA;AAGP,IAAApB,EAAG,UAAU+C,EAAW/C,GAAIsC,GAAS,SAAS,GAAG,CAAC,GAClDtC,EAAG,UAAU+C,EAAW/C,GAAIsC,GAAS,cAAc,GAAG,CAAC,GACvDtC,EAAG,UAAU+C,EAAW/C,GAAIsC,GAAS,cAAc,GAAG,CAAC,GACvDtC,EAAG,UAAU+C,EAAW/C,GAAIsC,GAAS,SAAS,GAAG,IAAI,KAAK,UAAU,IAAI,KAAK,SAAS,GACtFtC,EAAG;AAAA,MACD+C,EAAW/C,GAAIsC,GAAS,mBAAmB;AAAA,MAC3CU;AAAA,MACAC;AAAA,IAAA,GAEFjD,EAAG,UAAU+C,EAAW/C,GAAIsC,GAAS,WAAW,GAAGlB,EAAS,SAAS,QAAQ,IAAI,CAAC,GAClFpB,EAAG,UAAU+C,EAAW/C,GAAIsC,GAAS,eAAe,GAAGlB,EAAS,WAAW,GAC3EpB,EAAG,UAAU+C,EAAW/C,GAAIsC,GAAS,sBAAsB,GAAGlB,EAAS,kBAAkB,GACzFpB,EAAG,UAAU+C,EAAW/C,GAAIsC,GAAS,qBAAqB,GAAGlB,EAAS,iBAAiB,GACvFpB,EAAG,UAAU+C,EAAW/C,GAAIsC,GAAS,kBAAkB,GAAGlB,EAAS,cAAc,GACjFpB,EAAG,UAAU+C,EAAW/C,GAAIsC,GAAS,oBAAoB,GAAGlB,EAAS,gBAAgB,GACrFpB,EAAG,UAAU+C,EAAW/C,GAAIsC,GAAS,QAAQ,GAAGf,IAAc,GAAI;AAAA,EACpE;AACF;AAGO,SAAS2B,GACdC,GACAC,GACAC,GACAC,GACAC,GACkB;AAClB,MACEJ,MAAQ,UACR,CAAC,OAAO,SAASC,CAAW,KAC5B,CAAC,OAAO,SAASC,CAAY,KAC7B,CAAC,OAAO,SAASC,CAAW,KAC5B,CAAC,OAAO,SAASC,CAAY,KAC7BH,KAAe,KACfC,KAAgB,KAChBC,KAAe,KACfC,KAAgB;AAEhB,WAAO,CAAC,GAAG,CAAC;AAGd,MAAIJ,MAAQ;AACV,WAAO,CAACG,IAAcF,GAAaG,IAAeF,CAAY;AAGhE,QAAMG,IAAeJ,IAAcC,GAC7BI,IAAeH,IAAcC;AAEnC,SAAIJ,MAAQ,UACHK,IAAeC,IAClB,CAACA,IAAeD,GAAc,CAAC,IAC/B,CAAC,GAAGA,IAAeC,CAAY,IAG9BD,IAAeC,IAClB,CAAC,GAAGD,IAAeC,CAAY,IAC/B,CAACA,IAAeD,GAAc,CAAC;AACrC;AAEA,SAASnB,GAAqBpB,GAA0C;AACtE,QAAMyC,IAAazC,GAUb0C,IAAa;AAAA,IACjB,CAACD,EAAW,cAAcA,EAAW,aAAa;AAAA,IAClD,CAACA,EAAW,YAAYA,EAAW,WAAW;AAAA,IAC9C,CAACA,EAAW,cAAcA,EAAW,aAAa;AAAA,IAClD,CAACA,EAAW,OAAOA,EAAW,MAAM;AAAA,EAAA;AAGtC,aAAW,CAACE,GAAOC,CAAM,KAAKF;AAC5B,QACE,OAAOC,KAAU,YACjB,OAAOC,KAAW,YAClB,OAAO,SAASD,CAAK,KACrB,OAAO,SAASC,CAAM,KACtBD,IAAQ,KACRC,IAAS;AAET,aAAO,CAACD,GAAOC,CAAM;AAIzB,SAAO,CAAC,GAAG,CAAC;AACd;AAGO,SAAS1B,KAA+B;AAC7C,QAAM2B,IAAO,IAAI,WAAW1E,IAAmBA,IAAmB,CAAC;AAEnE,WAAS2E,IAAI,GAAGA,IAAI3E,GAAkB2E,KAAK;AACzC,aAASC,IAAI,GAAGA,IAAI5E,GAAkB4E,KAAK,GAAG;AAC5C,YAAMC,KAAKD,IAAI,OAAO5E,GAChB8E,KAAKH,IAAI,OAAO3E,GAChB+E,IAAM,KAAK,MAAMC,GAAqBH,GAAGC,GAAG,CAAG,IAAI,GAAG,GACtDG,IAAQ,KAAK,MAAMD,GAAqBH,GAAGC,GAAG,EAAI,IAAI,GAAG,GACzDI,IAAO,KAAK,MAAMF,GAAqBH,GAAGC,GAAG,EAAI,IAAI,GAAG,GACxDK,IAAQ,KAAK,MAAMH,GAAqBH,GAAGC,GAAG,EAAI,IAAI,GAAG,GACzDtB,KAASmB,IAAI3E,IAAmB4E,KAAK;AAE3C,MAAAF,EAAKlB,CAAK,IAAIuB,GACdL,EAAKlB,IAAQ,CAAC,IAAIyB,GAClBP,EAAKlB,IAAQ,CAAC,IAAI0B,GAClBR,EAAKlB,IAAQ,CAAC,IAAI2B;AAAA,IACpB;AAGF,SAAOT;AACT;AAEA,SAASM,GAAqBH,GAAWC,GAAWM,GAAsB;AACxE,QAAMC,IACJ,KAAK,IAAInF,MAAO4E,IAAI,IAAIM,IAAO,MAAM,IAAI,OACzC,KAAK,IAAIlF,MAAO2E,IAAI,IAAIC,IAAIM,IAAO,MAAM,IAAI,MACzCE,IACJ,KAAK,IAAIpF,MAAO2E,IAAI,IAAIO,IAAO,MAAM,IAAI,OACzC,KAAK,IAAIlF,MAAO4E,IAAI,IAAID,IAAIO,IAAO,MAAM,IAAI,MACzCG,IAAUV,IAAI5E,KAAqBoF,GACnCG,IAAUV,IAAI7E,KAAqBqF,GACnCG,IAAQ,KAAK,MAAMF,CAAO,GAC1BG,IAAQ,KAAK,MAAMF,CAAO;AAChC,MAAIG,IAAU,OAAO,mBACjBC,IAAgB,OAAO,mBACvBC,IAAe,GACfC,IAAe;AAEnB,WAASC,IAAU,IAAIA,KAAW,GAAGA,KAAW;AAC9C,aAASC,IAAU,IAAIA,KAAW,GAAGA,KAAW,GAAG;AACjD,YAAMC,IAAaR,IAAQO,GACrBE,IAAaR,IAAQK,GACrBI,IAAWC,GAAeH,GAAYhG,EAAkB,GACxDoG,IAAWD,GAAeF,GAAYjG,EAAkB,GACxDqG,IACJL,IAAa,OAAOM,GAAMJ,GAAUE,GAAUjB,CAAI,IAAI,MAClDoB,IACJN,IAAa,OAAOK,GAAMJ,GAAUE,GAAUjB,IAAO,CAAC,IAAI,MACtD3F,IAAW,KAAK,MAAM8F,IAAUe,GAAQd,IAAUgB,CAAM;AAE9D,MAAI/G,IAAWkG,KACbC,IAAgBD,GAChBA,IAAUlG,GACVoG,IAAeM,GACfL,IAAeO,KACN5G,IAAWmG,MACpBA,IAAgBnG;AAAA,IAEpB;AAGF,QAAMgH,IAAeb,IAAgBD,GAC/Be,IAAO,IAAIC,GAAiB,OAAO,MAAMF,CAAY,GACrDG,IAAO,IAAID,GAAiB,MAAM,MAAMF,CAAY,GACpDI,IAAY,OAAON,GAAMV,GAAcC,GAAcV,IAAO,CAAC,IAAI,MACjE9F,IAAQoH,IAAOA,IAAO,OAAOE,IAAO;AAE1C,SAAOE,GAAQ,KAAK,IAAIxH,IAAQuH,GAAW,IAAI,CAAC;AAClD;AAEA,SAASN,GAAM3B,GAAWD,GAAWS,GAAsB;AACzD,QAAM9F,IAAQ,KAAK,IAAIsF,IAAI,QAAQD,IAAI,QAAQS,IAAO,IAAI,IAAI;AAE9D,SAAO9F,IAAQ,KAAK,MAAMA,CAAK;AACjC;AAEA,SAAS8G,GAAe9G,GAAeyH,GAAyB;AAC9D,UAASzH,IAAQyH,IAAWA,KAAWA;AACzC;AAEA,SAASJ,GAAiBK,GAAeC,GAAe3H,GAAuB;AAC7E,QAAMO,IAASiH,IAASxH,IAAQ0H,MAAUC,IAAQD,EAAM;AAExD,SAAOnH,IAASA,KAAU,IAAIA,IAAS;AACzC;AAEA,SAASiH,GAAQxH,GAAuB;AACtC,SAAO,KAAK,IAAI,GAAG,KAAK,IAAI,GAAGA,CAAK,CAAC;AACvC;AAEA,SAASyB,GAAcN,GAIrB;AACA,QAAMyG,IAAqC;AAAA,IACzC,OAAO;AAAA,IACP,WAAW;AAAA,IACX,OAAO;AAAA,IACP,SAAS;AAAA,IACT,oBAAoB;AAAA,IACpB,uBAAuB;AAAA,EAAA,GAEnBC,IAAS1G,EAAO,WAAW,UAAUyG,CAAU;AAErD,MAAIC,GAAQ;AACV,QAAI,CAACA,EAAO,aAAa,wBAAwB;AAC/C,YAAM,IAAI,MAAM,gDAAgD;AAGlE,WAAO;AAAA,MACL,IAAIA;AAAA,MACJ,UAAU;AAAA,MACV,gBAAgB,CAAC,CAACA,EAAO,aAAa,0BAA0B;AAAA,IAAA;AAAA,EAEpE;AAEA,QAAMC,IACH3G,EAAO,WAAW,SAASyG,CAAU,KACrCzG,EAAO;AAAA,IACN;AAAA,IACAyG;AAAA,EAAA;AAGJ,MAAI,CAACE;AACH,UAAM,IAAI,MAAM,iCAAiC;AAGnD,MACE,CAACA,EAAO,aAAa,mBAAmB,KACvC,CAACA,EAAO,aAAa,0BAA0B,KAC9C,CAACA,EAAO,aAAa,wBAAwB;AAE/C,UAAM,IAAI,MAAM,iDAAiD;AAGnE,SAAO;AAAA,IACL,IAAIA;AAAA,IACJ,UAAU;AAAA,IACV,gBAAgB,CAAC,CAACA,EAAO,aAAa,0BAA0B;AAAA,EAAA;AAEpE;AAEA,SAASnG,GACPL,GACAyG,GACAC,GACa;AACb,QAAMC,IAAeC,GAAc5G,GAAIA,EAAG,eAAeyG,CAAY,GAC/DI,IAAiBD,GAAc5G,GAAIA,EAAG,iBAAiB0G,CAAc,GACrEpE,IAAUlC,EAAWJ,EAAG,cAAA,GAAiB,eAAe;AAQ9D,MANAA,EAAG,aAAasC,GAASqE,CAAY,GACrC3G,EAAG,aAAasC,GAASuE,CAAc,GACvC7G,EAAG,YAAYsC,CAAO,GACtBtC,EAAG,aAAa2G,CAAY,GAC5B3G,EAAG,aAAa6G,CAAc,GAE1B,CAAC7G,EAAG,oBAAoBsC,GAAStC,EAAG,WAAW,GAAG;AACpD,UAAM8G,IAAQ9G,EAAG,kBAAkBsC,CAAO,KAAK;AAE/C,UAAAtC,EAAG,cAAcsC,CAAO,GAClB,IAAI,MAAMwE,CAAK;AAAA,EACvB;AAEA,QAAMC,IAAW/G,EAAG,kBAAkBsC,GAAS,YAAY;AAE3D,MAAIyE,IAAW;AACb,UAAM,IAAI,MAAM,oDAAoD;AAGtE,SAAO,EAAE,SAAAzE,GAAS,UAAAyE,EAAA;AACpB;AAEA,SAASH,GACP5G,GACAgH,GACA/F,GACa;AACb,QAAMgG,IAAS7G,EAAWJ,EAAG,aAAagH,CAAI,GAAG,cAAc;AAK/D,MAHAhH,EAAG,aAAaiH,GAAQhG,CAAM,GAC9BjB,EAAG,cAAciH,CAAM,GAEnB,CAACjH,EAAG,mBAAmBiH,GAAQjH,EAAG,cAAc,GAAG;AACrD,UAAM8G,IAAQ9G,EAAG,iBAAiBiH,CAAM,KAAK;AAE7C,UAAAjH,EAAG,aAAaiH,CAAM,GAChB,IAAI,MAAMH,CAAK;AAAA,EACvB;AAEA,SAAOG;AACT;AAEA,SAASlE,EACP/C,GACAsC,GACA4E,GACsB;AACtB,QAAMC,IAAWnH,EAAG,mBAAmBsC,GAAS4E,CAAI;AAEpD,MAAI,CAACC;AACH,UAAM,IAAI,MAAM,0CAA0CD,CAAI,GAAG;AAGnE,SAAOC;AACT;AAEA,SAAS/G,EAAc1B,GAAiB0I,GAAkB;AACxD,MAAI,CAAC1I;AACH,UAAM,IAAI,MAAM,oCAAoC0I,CAAK,GAAG;AAG9D,SAAO1I;AACT;AAEA,SAAS0D,GAAuBnB,GAAiC;AAS/D,SARI,OAAO,oBAAsB,OAAeA,aAAkB,qBAI9D,OAAO,mBAAqB,OAAeA,aAAkB,oBAI7D,OAAO,kBAAoB,OAAeA,aAAkB;AAKlE;AAEO,SAASS,GACd2F,GACAzD,GACAC,GACAyD,IAAsC9H,IAC7B;AACT,QAAM+H,IAAY,KAAK,IAAI,GAAG,KAAK,MAAM3D,CAAK,CAAC,GACzC4D,IAAa,KAAK,IAAI,GAAG,KAAK,MAAM3D,CAAM,CAAC;AAEjD,MAAI0D,MAAc,KAAKC,MAAe;AACpC,WAAO;AAGT,QAAMC,IAAa,CAACzD,GAAWD,MAC7BsD,GAAOtD,IAAIwD,IAAYvD,KAAK,CAAC,KAAK;AAEpC,WAASD,IAAI,GAAGA,IAAIyD,GAAYzD,KAAK;AACnC,aAASC,IAAI,GAAGA,IAAIuD,GAAWvD,KAAK,GAAG;AACrC,YAAMpB,KAASmB,IAAIwD,IAAYvD,KAAK,GAC9B0D,IAAUL,EAAMzE,CAAK,KAAK,GAC1B+E,IAAWN,EAAMzE,IAAQ,CAAC,KAAK;AAErC,UACE8E,IAAU,CAACJ,EAAW,UACtB,KAAK,IAAIK,CAAQ,IAAIL,EAAW;AAEhC,eAAO;AAGT,YAAMM,IAAO5D,IAAI,IAAIyD,EAAWzD,IAAI,GAAGD,CAAC,IAAI2D,GACtCG,IAAQ7D,IAAIuD,IAAY,IAAIE,EAAWzD,IAAI,GAAGD,CAAC,IAAI2D,GACnDI,IAAO/D,IAAI,IAAI0D,EAAWzD,GAAGD,IAAI,CAAC,IAAI2D,GACtCK,IAAKhE,IAAIyD,IAAa,IAAIC,EAAWzD,GAAGD,IAAI,CAAC,IAAI2D,GACjDM,IAAW,KAAK,MAAMH,IAAQD,GAAMG,IAAKD,CAAI,GAC7CG,IAAY,KAAK,IAAIL,IAAOC,IAAQC,IAAOC,IAAKL,IAAU,CAAC;AAEjE,UACEM,IAAWV,EAAW,YACtBW,IAAYX,EAAW;AAEvB,eAAO;AAAA,IAEX;AAGF,SAAO;AACT;AC1nCA,MAAMY,IAA6C;AAAA,EACjD,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,mBAAmB;AAAA,EACnB,cAAc;AAAA,EACd,gBAAgB;AAAA,EAChB,eAAe;AAAA,EACf,aAAa;AAAA,EACb,YAAY;AAAA,EACZ,eAAe;AAAA,EACf,eAAe;AAAA,EACf,iBAAiB;AAAA,EACjB,gBAAgB;AAClB,GACMC,KAA0B;AAEhC,SAASC,GACPC,GAC2B;AAC3B,SAAO;AAAA,IACL,OAAO,KAAK,IAAI,GAAGA,EAAQ,SAASH,EAAgB,KAAK;AAAA,IACzD,QAAQ,KAAK,IAAI,GAAGG,EAAQ,UAAUH,EAAgB,MAAM;AAAA,IAC5D,mBAAmB,KAAK;AAAA,MACtB;AAAA,MACAG,EAAQ,qBAAqBH,EAAgB;AAAA,IAAA;AAAA,IAE/C,cAAc,KAAK;AAAA,MACjB;AAAA,MACAG,EAAQ,gBAAgBH,EAAgB;AAAA,IAAA;AAAA,IAE1C,gBAAgB,KAAK;AAAA,MACnB;AAAA,MACAG,EAAQ,kBAAkBH,EAAgB;AAAA,IAAA;AAAA,IAE5C,eAAe,KAAK;AAAA,MAClB;AAAA,MACAG,EAAQ,iBAAiBH,EAAgB;AAAA,IAAA;AAAA,IAE3C,aAAa,KAAK,IAAI,GAAGG,EAAQ,eAAeH,EAAgB,WAAW;AAAA,IAC3E,YAAY,KAAK,IAAI,GAAGG,EAAQ,cAAcH,EAAgB,UAAU;AAAA,IACxE,eAAe,KAAK;AAAA,MAClB;AAAA,MACAG,EAAQ,iBAAiBH,EAAgB;AAAA,IAAA;AAAA,IAE3C,eAAe,KAAK;AAAA,MAClB;AAAA,MACAG,EAAQ,iBAAiBH,EAAgB;AAAA,IAAA;AAAA,IAE3C,iBAAiBzJ;AAAA,MACf4J,EAAQ,mBAAmBH,EAAgB;AAAA,MAC3C;AAAA,MACA;AAAA,IAAA;AAAA,IAEF,gBAAgB,KAAK;AAAA,MACnB;AAAA,MACAG,EAAQ,kBAAkBH,EAAgB;AAAA,IAAA;AAAA,EAC5C;AAEJ;AAEO,SAASI,GACdC,GACAC,GACAC,IAAMF,EAAM,WACK;AACjB,QAAMG,IACJ,OAAOH,EAAM,sBAAuB,aAChCA,EAAM,mBAAA,IACN,CAAA,GACAI,IAAeD,EAAO,SAAS,IAAIA,IAAS,CAACH,CAAK,GAClDK,IAAcH,IAAMF,EAAM;AAEhC,SAAOI,EAAa,IAAI,CAACE,OAAkB;AAAA,IACzC,GAAGA,EAAa,UAAUL,EAAO;AAAA,IACjC,GAAGK,EAAa,UAAUL,EAAO;AAAA,IACjC,MAAMK,EAAa,YAAYD;AAAA,EAAA,EAC/B;AACJ;AAEO,MAAME,GAA0B;AAAA,EAMrC,YAAYT,IAA8C,IAAI;AALtD,IAAAtI,EAAA;AACA,IAAAA,EAAA;AACA,IAAAA,EAAA,0BAAmB;AACV,IAAAA,EAAA,sBAAmC,CAAA;AAGlD,SAAK,UAAUqI,GAAiBC,CAAO;AAAA,EACzC;AAAA,EAEA,UAAUA,GAAmD;AAC3D,SAAK,UAAUD,GAAiB;AAAA,MAC9B,GAAG,KAAK;AAAA,MACR,GAAGC;AAAA,IAAA,CACJ;AAAA,EACH;AAAA,EAEA,QAAc;AACZ,SAAK,WAAW,QAChB,KAAK,mBAAmB,GACxB,KAAK,aAAa,SAAS;AAAA,EAC7B;AAAA,EAEA,UAAUU,GAAoD;AAC5D,SAAK,aAAa,SAAS;AAE3B,UAAMC,IAAM,KAAK,YAAYD,CAAM,GAC7BE,IAAW,KAAK;AAEtB,QAAI,CAACA;AACH,kBAAK,WAAWD,GACT,KAAK;AAGd,IAAIA,EAAI,QAAQC,EAAS,SACvBD,EAAI,OAAOC,EAAS,OAAO;AAG7B,UAAMvB,IAAU,KAAK,aAAauB,GAAUD,CAAG,GACzCE,IAAgBrK,GAASoK,GAAUvB,CAAO;AAEhD,QAAIwB,IAAgB;AAClB,kBAAK,WAAWxB,GACT,KAAK;AAGd,UAAMC,IAAWuB,IAAgB,KAAK,IAAI,MAAMxB,EAAQ,OAAOuB,EAAS,IAAI,GACtEE,IAAiB1K,EAAM,IAAI,KAAK,QAAQ,iBAAiB,MAAM,CAAC;AAEtE,SAAK,mBAAmBO;AAAA,MACtB,KAAK;AAAA,MACL2I;AAAA,MACAwB;AAAA,IAAA,GAEF,KAAK,WAAWzB;AAEhB,UAAM0B,IAAe,KAAK;AAAA,MACxBjB;AAAA,MACA,KAAK,IAAI,GAAG,KAAK,KAAKe,IAAgB,KAAK,QAAQ,cAAc,CAAC;AAAA,IAAA;AAGpE,aAAStG,IAAQ,GAAGA,IAAQwG,GAAcxG,KAAS,GAAG;AACpD,YAAMD,IAAQC,IAAQwG,GAChBC,KAAOzG,IAAQ,KAAKwG;AAE1B,WAAK,aAAa;AAAA,QAChBE;AAAA,UACEC,GAAkBN,GAAUvB,GAAS/E,CAAK;AAAA,UAC1C4G,GAAkBN,GAAUvB,GAAS2B,CAAG;AAAA,UACxC,KAAK;AAAA,UACL,KAAK;AAAA,QAAA;AAAA,MACP;AAAA,IAEJ;AAEA,WAAO,KAAK;AAAA,EACd;AAAA,EAEQ,YAAYN,GAAsC;AACxD,WAAO;AAAA,MACL,GAAGtK,EAAMsK,EAAO,GAAG,GAAG,KAAK,QAAQ,KAAK;AAAA,MACxC,GAAGtK,EAAMsK,EAAO,GAAG,GAAG,KAAK,QAAQ,MAAM;AAAA,MACzC,MAAMA,EAAO;AAAA,IAAA;AAAA,EAEjB;AAAA,EAEQ,aAAaE,GAAyBD,GAAmC;AAC/E,UAAMQ,IAAS,IAAI,KAAK,QAAQ;AAEhC,WAAO;AAAA,MACL,GAAGxK,EAAKiK,EAAS,GAAGD,EAAI,GAAGQ,CAAM;AAAA,MACjC,GAAGxK,EAAKiK,EAAS,GAAGD,EAAI,GAAGQ,CAAM;AAAA,MACjC,MAAMR,EAAI;AAAA,IAAA;AAAA,EAEd;AACF;AAEO,SAASM,GACdG,GACAC,GACAC,GACAtB,GACkB;AAClB,QAAMuB,IAAaxB,GAAiBC,CAAO,GACrCwB,IAAcpL;AAAA,IACjBkL,IAAeC,EAAW,gBAAiBA,EAAW;AAAA,IACvD;AAAA,IACA;AAAA,EAAA,GAEIE,IAAQrL,EAAMgL,EAAK,IAAIG,EAAW,QAAQ,GAAG,CAAC,GAC9CG,IAAMtL,EAAMiL,EAAG,IAAIE,EAAW,QAAQ,GAAG,CAAC,GAC1CI,IAAeJ,EAAW,aAAa5K,EAAK,MAAM,MAAM6K,CAAW;AAEzE,SAAO;AAAA,IACL,IAAIpL,EAAMgL,EAAK,IAAIG,EAAW,OAAO,GAAG,CAAC;AAAA,IACzC,IAAI,IAAIE;AAAA,IACR,IAAIrL,EAAMiL,EAAG,IAAIE,EAAW,OAAO,GAAG,CAAC;AAAA,IACvC,IAAI,IAAIG;AAAA,IACR,QAAQH,EAAW,oBAAoBA,EAAW;AAAA,IAClD,cAAcA,EAAW,eAAe5K,EAAK,MAAM,GAAG6K,CAAW;AAAA,IACjE,gBAAgBD,EAAW;AAAA,IAC3B,eAAeA,EAAW;AAAA,IAC1B,aAAaA,EAAW,cAAcA,EAAW;AAAA,IACjD,YAAYI,IAAeJ,EAAW;AAAA,IACtC,UAAUC;AAAA,EAAA;AAEd;AAEA,SAASN,GACPE,GACAC,GACAzK,GACe;AACf,SAAO;AAAA,IACL,GAAGD,EAAKyK,EAAK,GAAGC,EAAG,GAAGzK,CAAM;AAAA,IAC5B,GAAGD,EAAKyK,EAAK,GAAGC,EAAG,GAAGzK,CAAM;AAAA,IAC5B,MAAMD,EAAKyK,EAAK,MAAMC,EAAG,MAAMzK,CAAM;AAAA,EAAA;AAEzC;AAEO,SAASgL,GAAuBC,GAAyB;AAC9D,QAAMC,IAAc1L,EAAMyL,GAAS,MAAM,KAAK,GACxCE,IAAS,KAAK,KAAK,KAAK,IAAI,KAAK,IAAI,KAAK,IAAID,CAAW,CAAC;AAEhE,SAAO1L,EAAM2L,KAAU,MAAO,KAAK,KAAK,IAAI;AAC9C;AC5KA,MAAMC,IAAoC;AAAA,EACxC,MAAM;AAAA,EACN,YAAY;AAAA,EACZ,SAAS;AAAA,EACT,WAAW;AAAA,EACX,aAAa;AAAA,EACb,oBAAoB;AAAA,EACpB,mBAAmB;AAAA,EACnB,gBAAgB;AAAA,EAChB,kBAAkB;AAAA,EAClB,sBAAsB;AAAA,EACtB,cAAc;AAAA,EACd,mBAAmB;AAAA,EACnB,gBAAgB;AAAA,EAChB,eAAe;AAAA,EACf,aAAa;AAAA,EACb,YAAY;AAAA,EACZ,eAAe;AAAA,EACf,eAAe;AAAA,EACf,iBAAiB;AAAA,EACjB,gBAAgB;AAAA,EAChB,aAAa;AAAA,EACb,iBAAiB;AAAA,EACjB,iBAAiB;AAAA,EACjB,UAAU;AACZ,GAEMC,IAAU,MAAO,IACjBC,KAAkB,GAClBC,KAA6B,KAC7BC,KAA2B,IAC3BC,KAA2B;AAEjC,SAASC,GAA4BC,GAAqC;AACxE,SACEA,aAAkB,WAClBA,EAAO;AAAA,IACL;AAAA,EAAA,MACI;AAEV;AAEA,SAASC,GAAmBC,GAA8C;AACxE,QAAMC,IACJD,EAAM,aAAa,SAAY,SAAYA,EAAM,WAAW;AAE9D,SAAO;AAAA,IACL,MAAMA,EAAM,QAAQT,EAAiB;AAAA,IACrC,SAASS,EAAM;AAAA,IACf,YAAYA,EAAM,cAAcT,EAAiB;AAAA,IACjD,SAAS5L;AAAA,MACPqM,EAAM,WAAWA,EAAM,eAAeT,EAAiB;AAAA,MACvD;AAAA,MACA;AAAA,IAAA;AAAA,IAEF,WAAW5L,EAAMqM,EAAM,aAAaT,EAAiB,WAAW,MAAM,CAAC;AAAA,IACvE,aAAa5L;AAAA,MACXqM,EAAM,eAAeT,EAAiB;AAAA,MACtC;AAAA,MACA;AAAA,IAAA;AAAA,IAEF,oBAAoB5L;AAAA,MAClBqM,EAAM,sBAAsBT,EAAiB;AAAA,MAC7C;AAAA,MACA;AAAA,IAAA;AAAA,IAEF,mBAAmB5L;AAAA,MACjBqM,EAAM,qBAAqBT,EAAiB;AAAA,MAC5C;AAAA,MACA;AAAA,IAAA;AAAA,IAEF,gBAAgB5L;AAAA,MACdqM,EAAM,kBAAkBT,EAAiB;AAAA,MACzC;AAAA,MACA;AAAA,IAAA;AAAA,IAEF,kBAAkB5L;AAAA,MAChBqM,EAAM,oBAAoBT,EAAiB;AAAA,MAC3C;AAAA,MACA;AAAA,IAAA;AAAA,IAEF,sBAAsB5L;AAAA,MACpB,KAAK;AAAA,QACHqM,EAAM,wBAAwBT,EAAiB;AAAA,MAAA;AAAA,MAEjD;AAAA,MACA;AAAA,IAAA;AAAA,IAEF,cAAc5L;AAAA,MACZqM,EAAM,gBACJA,EAAM,kBACNC,KACAV,EAAiB;AAAA,MACnB;AAAA,MACA;AAAA,IAAA;AAAA,IAEF,mBAAmB5L;AAAA,MACjBqM,EAAM,qBAAqBT,EAAiB;AAAA,MAC5C;AAAA,MACA;AAAA,IAAA;AAAA,IAEF,gBAAgB5L;AAAA,MACdqM,EAAM,kBAAkBT,EAAiB;AAAA,MACzC;AAAA,MACA;AAAA,IAAA;AAAA,IAEF,eAAe5L;AAAA,MACbqM,EAAM,iBAAiBT,EAAiB;AAAA,MACxC;AAAA,MACA;AAAA,IAAA;AAAA,IAEF,aAAa5L;AAAA,MACXqM,EAAM,eAAeT,EAAiB;AAAA,MACtC;AAAA,MACA;AAAA,IAAA;AAAA,IAEF,YAAY5L;AAAA,MACVqM,EAAM,cAAcT,EAAiB;AAAA,MACrC;AAAA,MACA;AAAA,IAAA;AAAA,IAEF,eAAe5L;AAAA,MACbqM,EAAM,iBAAiBT,EAAiB;AAAA,MACxC;AAAA,MACA;AAAA,IAAA;AAAA,IAEF,eAAe5L;AAAA,MACbqM,EAAM,iBAAiBT,EAAiB;AAAA,MACxC;AAAA,MACA;AAAA,IAAA;AAAA,IAEF,iBAAiB5L;AAAA,MACfqM,EAAM,mBAAmBT,EAAiB;AAAA,MAC1C;AAAA,MACA;AAAA,IAAA;AAAA,IAEF,gBAAgB5L;AAAA,MACdqM,EAAM,kBAAkBT,EAAiB;AAAA,MACzC;AAAA,MACA;AAAA,IAAA;AAAA,IAEF,aAAa,KAAK,IAAI,KAAKS,EAAM,eAAeT,EAAiB,WAAW;AAAA,IAC5E,iBACES,EAAM,mBAAmBT,EAAiB;AAAA,IAC5C,iBACES,EAAM,mBAAmBT,EAAiB;AAAA,IAC5C,UAAUS,EAAM,YAAYT,EAAiB;AAAA,EAAA;AAEjD;AAEA,SAASW,GACPjE,GACA3F,GACA6J,GACoB;AACpB,QAAMC,IAAUzM,EAAMsI,EAAS,GAAG,GAAG,CAAC,IAAIkE,EAAK,OACzCE,IAAU1M,EAAMsI,EAAS,GAAG,GAAG,CAAC,IAAIkE,EAAK,QACzCG,IAAc,KAAK,IAAI,KAAKhK,EAAS,oBAAoB,IAAI,GAC7DuG,IAAWvG,EAAS,gBAAgBA,EAAS,eAC7CiH,IAAU;AAAA,IACd,GAAGjH;AAAA,IACH,OAAO6J,EAAK;AAAA,IACZ,QAAQA,EAAK;AAAA,IACb,YAAY7J,EAAS,oBAAoB;AAAA,EAAA;AAG3C,SAAO;AAAA,IACLkI;AAAA,MACE,EAAE,GAAG4B,IAAUE,GAAa,GAAGD,EAAiB;AAAA,MAChD,EAAE,GAAGD,IAAUE,GAAa,GAAGD,EAAiB;AAAA,MAChDxD;AAAA,MACAU;AAAA,IAAA;AAAA,IAEFiB;AAAA,MACE,EAAE,GAAG4B,GAAS,GAAGC,IAAUC,EAAqB;AAAA,MAChD,EAAE,GAAGF,GAAS,GAAGC,IAAUC,EAAqB;AAAA,MAChDzD;AAAA,MACAU;AAAA,IAAA;AAAA,EACF;AAEJ;AAEA,SAASgD,GAAwBC,GAA2B;AAC1D,QAAM,CAACC,GAAsBC,CAAuB,IAAIC,GAAS,EAAK;AAEtE,SAAAC,EAAU,MAAM;AACd,QAAI,CAACJ,KAAW,OAAO,SAAW,OAAe,CAAC,OAAO,YAAY;AACnE,MAAAE,EAAwB,EAAK;AAC7B;AAAA,IACF;AAEA,UAAMG,IAAQ,OAAO,WAAW,kCAAkC;AAElE,IAAAH,EAAwBG,EAAM,OAAO;AAErC,UAAMC,IAAe,CAACrD,MAA+B;AACnD,MAAAiD,EAAwBjD,EAAM,OAAO;AAAA,IACvC;AAEA,WAAAoD,EAAM,iBAAiB,UAAUC,CAAY,GAEtC,MAAM;AACX,MAAAD,EAAM,oBAAoB,UAAUC,CAAY;AAAA,IAClD;AAAA,EACF,GAAG,CAACN,CAAO,CAAC,GAELC;AACT;AAEO,MAAMM,KAAkBC,GAG7B,SAAyBhB,GAAOiB,GAAK;AACrC,QAAM;AAAA,IACJ,UAAAC;AAAA,IACA,UAAAC;AAAA,IACA,YAAAC;AAAA,IACA,WAAAC;AAAA,IACA,OAAAC;AAAA,IACA,eAAAC,IAAgB;AAAA,EAAA,IACdvB,GACEwB,IAAeC,EAA8B,IAAI,GACjDC,IAAYD,EAAiC,IAAI,GACjDE,IAAcF,EAAwC,IAAI,GAC1DG,IAAaH,EAAO,IAAIzD,IAA2B,GACnD6D,IAAWJ,EAAsB,IAAI,GACrCK,IAAqBL,EAAsB,IAAI,GAC/CM,IAAkBN,EAAmB,MAAA;AAAA,GAAe,GACpDO,IAAuBP,EAAmB,MAAA;AAAA,GAAe,GACzDQ,IAAuBR,EAE3B,MAAA;AAAA,GAAe,GACXS,IAAyBT,EAA2B,EAAE,GACtDU,IAAaV,EAAO,EAAI,GACxBW,IAAaX,EAAO,EAAI,GACxBY,IAAcZ,EAAO,EAAK,GAC1Ba,IAAYb,EAAO,EAAK,GACxBc,IAAyBd,EAAsB,IAAI,GACnDe,IAAef,EAAO,CAAC,GACvBgB,IAAyBhB,EAAO,CAAC,GACjCiB,IAAqBjB,EAAO,CAAC,GAC7BnL,IAAWyJ,GAAmBC,CAAK,GACnC2C,IAAclB,EAAOnL,CAAQ,GAC7BsM,IAAUnB,EAAO,EAAE,OAAO,GAAG,QAAQ,GAAG,GACxChB,KAAuBF;AAAA,IAC3BgB,MAAkB;AAAA,EAAA,GAEdsB,KACJtB,MAAkB,aACjBA,MAAkB,aAAad,IAC5BqC,KAAoB1B,KAAcD;AAExC,EAAAwB,EAAY,UAAUrM,GAEtByM;AAAA,IACE9B;AAAA,IACA,OAAO;AAAA,MACL,cAAchF,GAAU;AACtB,QAAIoG,EAAY,WAAWC,EAAU,WAIrCL,EAAqB;AAAA,UACnB/B;AAAA,YACEjE;AAAA,YACA0G,EAAY;AAAA,YACZC,EAAQ;AAAA,UAAA;AAAA,QACV;AAAA,MAEJ;AAAA,IAAA;AAAA,IAEF,CAAA;AAAA,EAAC,GAGHhC,EAAU,MAAM;;AACd,IAAAyB,EAAY,UAAUQ,IAElBA,OACFjB,EAAW,QAAQ,MAAA,GACnBW,EAAuB,UAAU,MACjCL,EAAuB,UAAU,CAAA,GACjCM,EAAa,UAAU,GACvBC,EAAuB,UAAU,GACjCC,EAAmB,UAAU,IAC7B7L,IAAA8K,EAAY,YAAZ,QAAA9K,EAAqB,UAGvBkL,EAAgB,QAAA;AAAA,EAClB,GAAG,CAACc,EAAc,CAAC,GAEnBjC,EAAU,MAAM;AACd,UAAMoC,IAAWrB,EAAY;AAE7B,QAAI,CAACqB;AACH;AAGF,UAAM,EAAE,OAAAlK,GAAO,QAAAC,EAAA,IAAW6J,EAAQ;AAElC,IAAAI,EAAS;AAAA,MACPlK;AAAA,MACAC;AAAA,MACA,OAAO;AAAA,MACPzC,EAAS;AAAA,IAAA,GAEX0M,EAAS,iBAAiB1M,EAAS,OAAO,GAC1CyL,EAAgB,QAAA;AAAA,EAClB,GAAG;AAAA,IACDzL,EAAS;AAAA,IACTA,EAAS;AAAA,IACTA,EAAS;AAAA,IACTA,EAAS;AAAA,IACTA,EAAS;AAAA,IACTA,EAAS;AAAA,IACTA,EAAS;AAAA,IACTA,EAAS;AAAA,IACTA,EAAS;AAAA,IACTA,EAAS;AAAA,IACTA,EAAS;AAAA,EAAA,CACV,GAEDsK,EAAU,MAAM;AACd,UAAMqC,IAAYzB,EAAa,SACzBzM,IAAS2M,EAAU;AAEzB,QAAI,CAACuB,KAAa,CAAClO;AACjB;AAGF,IAAAqN,EAAW,UACT,OAAO,SAAS,YAAa,aAAa,SAAS,aAAa;AAElE,QAAIY,IAA4C,MAC5CE,IACAC,KAAc3D,GACd4D,KAAyB,IACzBC;AAEJ,UAAMC,IAAc,MAAM;AACxB,MAAIzB,EAAS,YAAY,SACvB,OAAO,qBAAqBA,EAAS,OAAO,GAC5CA,EAAS,UAAU,OAGjBC,EAAmB,YAAY,SACjC,OAAO,aAAaA,EAAmB,OAAO,GAC9CA,EAAmB,UAAU;AAAA,IAEjC,GAEMyB,KAAoB,CAACzK,GAAeC,MAAmB;AAC3D,MAAA6I,EAAW,QAAQ,UAAU;AAAA,QAC3B,OAAA9I;AAAA,QACA,QAAAC;AAAA,QACA,mBAAmB4J,EAAY,QAAQ;AAAA,QACvC,cAAcA,EAAY,QAAQ;AAAA,QAClC,gBAAgBA,EAAY,QAAQ;AAAA,QACpC,eAAeA,EAAY,QAAQ;AAAA,QACnC,aAAaA,EAAY,QAAQ;AAAA,QACjC,YAAYA,EAAY,QAAQ;AAAA,QAChC,eAAeA,EAAY,QAAQ;AAAA,QACnC,eAAeA,EAAY,QAAQ;AAAA,QACnC,iBAAiBA,EAAY,QAAQ;AAAA,QACrC,gBAAgBA,EAAY,QAAQ;AAAA,MAAA,CACrC;AAAA,IACH,GAEMa,KAAa,CAAC1K,GAAeC,MAAmB;AACpD,YAAM0D,IAAY,KAAK,IAAI,GAAG3D,CAAK,GAC7B4D,IAAa,KAAK,IAAI,GAAG3D,CAAM;AAErC,MAAA6J,EAAQ,UAAU,EAAE,OAAOnG,GAAW,QAAQC,EAAA,GAC9C6G,GAAkB9G,GAAWC,CAAU,GACvCsG,KAAA,QAAAA,EAAU;AAAA,QACRvG;AAAA,QACAC;AAAA,QACA,OAAO;AAAA,QACPiG,EAAY,QAAQ;AAAA;AAAA,IAExB,GAEMc,KAAe,MAAM;AACzB,MAAAT,KAAA,QAAAA,EAAU,OAAOL,EAAY,SAAS,YAAY,IAAA,IAAQ;AAAA,IAC5D,GAEMe,IAAQ,MAAM;AAClB,MAAAR,KAAgB,QAChBC,KAAc3D;AAAA,IAChB,GAEMmE,KAAiB,MAAM;AAC3B,MAAAL,EAAA,GACA1B,EAAW,QAAQ,MAAA,GACnBW,EAAuB,UAAU,MACjCmB,EAAA,GAEIL,OAAa,WACfA,KAAW,YAAY,IAAA;AAAA,IAE3B,GAEMO,IAAkB,MAAM;AAC5B,YAAMC,IAAkBlB,EAAY;AACpC,UAAImB,IAAmB;AAQvB,UAAI,EANF,CAACzB,EAAY,WACb,CAACC,EAAU,WACXH,EAAW,YACV0B,EAAgB,mBACd,CAAC,SAAS,UAAUzB,EAAW,WAEvB;AACX,QAAAsB,EAAA;AACA;AAAA,MACF;AAEA,UAAIL,OAAa,QAAW;AAC1B,cAAMU,IAAiB,YAAY,IAAA,IAAQV;AAE3C,QAAAb,EAAa,WAAWuB,GACxBtB,EAAuB,WAAWsB,GAClCrB,EAAmB,WAAWqB,GAC9BV,KAAW,QACXS,IAAmB;AAAA,MACrB;AAEA,OAAI,CAACD,EAAgB,mBAAmBC,MACtCJ,EAAA,GAGFD,GAAA,GACA1B,EAAgB,QAAA;AAAA,IAClB,GAEMiC,KAAQ,CAACC,MAAiB;AAC9B,MAAApC,EAAS,UAAU;AACnB,YAAMgC,IAAkBlB,EAAY;AAEpC,UACE,CAACK,KACDV,EAAU,WACV,CAACH,EAAW,WACX,CAAC0B,EAAgB,oBACf,SAAS,UAAU,CAACzB,EAAW,UAClC;AACA,QAAAsB,EAAA;AACA;AAAA,MACF;AAEA,UAAIrB,EAAY,SAAS;AACvB,QAAAH,EAAuB,UAAU,CAAA,GACjCc,EAAS,OAAOa,GAAiBI,IAAO,IAAK,GAC7CP,EAAA;AACA;AAAA,MACF;AAEA,YAAMQ,IAAgBL,EAAgB,kBAClCnE,KACAD,IACE0E,IACJjB,OAAkB,SACd1D,IACA7L;AAAA,QACEsQ,IAAOf;AAAA,QACP;AAAA,QACAW,EAAgB,kBACZrE,IAAUE,KACV;AAAA,MAAA;AAGZ,MAAAwD,KAAgBe,GAChBd,KAAc,KAAK;AAAA,QACjBA,KAAcgB;AAAA,QACd3E,IAAU0E;AAAA,MAAA;AAGZ,UAAI7N,IAAe6L,EAAuB,QAAQ,OAAO,CAAC,GACtDkC,KAAQ;AAEZ,aAAOjB,MAAe3D,KAAW4E,KAAQF;AACvC,QAAAlB,EAAS,KAAK3M,GAAcwN,GAAiB,CAAC,GAC9CxN,IAAe,CAAA,GACf8M,MAAe3D,GACf4E,MAAS;AAKX,UAFApB,EAAS,OAAOa,GAAiBI,IAAO,IAAK,GAEzC/B,EAAuB,QAAQ,SAAS,GAAG;AAC7C,QAAAH,EAAgB,QAAA;AAChB;AAAA,MACF;AAEA,UAAIkC,IAAOzB,EAAa,SAAS;AAC/B,QAAAT,EAAgB,QAAA;AAChB;AAAA,MACF;AAEA,UAAIqB,IAAwB;AAC1B,QAAIa,IAAOxB,EAAuB,UAChCV,EAAgB,QAAA,IAEhB2B,EAAA;AAGF;AAAA,MACF;AAEA,UAAIO,IAAOvB,EAAmB,SAAS;AACrC,QAAAX,EAAgB,QAAA;AAChB;AAAA,MACF;AAEA,UAAI;AACF,QAAIiB,EAAS,wBACXN,EAAmB,UAAUuB,IAAOrE,IACpCmC,EAAgB,QAAA,KAEhB2B,EAAA;AAAA,MAEJ,QAAQ;AACN,QAAAN,KAAyB,IAErBa,IAAOxB,EAAuB,UAChCV,EAAgB,QAAA,IAEhB2B,EAAA;AAAA,MAEJ;AAAA,IACF,GAEMW,KAAe,MAAM;AACzB,MACE/B,EAAU,WACVT,EAAS,YAAY,QACrBC,EAAmB,YAAY,SAK7Ba,EAAY,QAAQ,mBAAmB,SAAS,SAClDb,EAAmB,UAAU,OAAO,WAAW,MAAM;AACnD,QAAAA,EAAmB,UAAU,MAC7BkC,GAAM,YAAY,KAAK;AAAA,MACzB,GAAGxE,CAAO,IAEVqC,EAAS,UAAU,OAAO,sBAAsBmC,EAAK;AAAA,IAEzD;AAEA,IAAAjC,EAAgB,UAAUsC;AAE1B,QAAI;AACF,MAAArB,IAAW,IAAIlO,GAAyBC,GAAQ,MAAM;AACpD,QAAAgN,EAAgB,QAAA;AAAA,MAClB,CAAC,GACDJ,EAAY,UAAUqB,GACtBA,EAAS,iBAAiBL,EAAY,QAAQ,OAAO;AAAA,IACvD,QAAQ;AACN,aAAA5N,EAAO,MAAM,UAAU,QACvB4M,EAAY,UAAU,MACtBI,EAAgB,UAAU;SACnB;;IACT;AAEA,UAAMuC,KAAW,MAAM;AACrB,YAAMC,IAAOxP,EAAO,sBAAA;AACpB,aAAAyO,GAAWe,EAAK,OAAOA,EAAK,MAAM,GAE3BA;AAAA,IACT,GAEMC,KAAW,MAAM;AACrB,MAAAF,GAAA,GACAb,GAAA;AAAA,IACF,GAEMgB,KAAoB,CACxBpO,MACG;AACH,UAAIiM,EAAU,WAAWjM,EAAa,WAAW;AAC/C;AAGF,YAAMqO,IAAUxC,EAAuB;AAEvC,iBAAWnK,KAAe1B;AACxB,QAAAqO,EAAQ,KAAK3M,CAAW;AAG1B,MAAI2M,EAAQ,SAAS/E,MACnB+E,EAAQ,OAAO,GAAGA,EAAQ,SAAS/E,EAAwB;AAI7D,YAAMgF,IADM,YAAY,IAAA,IACAhC,EAAY,QAAQ;AAE5C,MAAAH,EAAa,UAAU,KAAK,IAAIA,EAAa,SAASmC,CAAS,GAC/DlC,EAAuB,UAAU,KAAK;AAAA,QACpCA,EAAuB;AAAA,QACvBkC,IAAYxF,GAAuBwD,EAAY,QAAQ,OAAO;AAAA,MAAA,GAEhED,EAAmB,UAAU,GAC7B2B,GAAA;AAAA,IACF;AAEA,IAAApC,EAAqB,UAAUwC;AAE/B,UAAMG,KAAqB,CAACnH,MAAwB;AAClD,YAAMoG,IAAkBlB,EAAY;AAapC,UAVEN,EAAY,WACZC,EAAU,WACV,CAACH,EAAW,WACZ0B,EAAgB,oBAAoB,WACnC,CAACA,EAAgB,oBACf,SAAS,UAAU,CAACzB,EAAW,YAKhC3E,EAAM,gBAAgB,WAAW,CAACA,EAAM;AAC1C;AAGF,MAAAmE,EAAW,QAAQ,MAAA;AACnB,YAAM2C,IAAOD,GAAA,GACP,CAACrG,CAAM,IAAIT,GAAkBC,GAAO8G,GAAM,YAAY,KAAK;AAEjE,MAAItG,OAEA4F,EAAgB,oBAAoB,WACpCA,EAAgB,oBAAoB,UACpCA,EAAgB,oBAAoB,WAEpCY;AAAA,QACEvE;AAAA,UACE;AAAA,YACE,GAAGjC,EAAO,IAAI2E,EAAQ,QAAQ;AAAA,YAC9B,GAAG3E,EAAO,IAAI2E,EAAQ,QAAQ;AAAA,UAAA;AAAA,UAEhCiB;AAAA,UACAjB,EAAQ;AAAA,QAAA;AAAA,MACV,GAIAiB,EAAgB,oBAAoB,UACtCtB,EAAuB,UAAU9E,EAAM,WACvCmE,EAAW,QAAQ,UAAU3D,CAAM,MAEnC4F,EAAgB,oBAAoB,UACpCA,EAAgB,oBAAoB,WAEpCjC,EAAW,QAAQ,UAAU3D,CAAM;AAAA,IAGzC,GAEM4G,KAAoB,CAACpH,MAAwB;AACjD,YAAMoG,IAAkBlB,EAAY;AAgBpC,UAbEN,EAAY,WACZC,EAAU,WACV,CAACH,EAAW,WACX0B,EAAgB,oBAAoB,UACnCA,EAAgB,oBAAoB,WACnCA,EAAgB,oBAAoB,UACnCtB,EAAuB,YAAY9E,EAAM,cAC5C,CAACoG,EAAgB,oBACf,SAAS,UAAU,CAACzB,EAAW,YAKhC3E,EAAM,gBAAgB,WAAW,CAACA,EAAM;AAC1C;AAGF,YAAM8G,IAAOD,GAAA,GACPQ,IAAUtH,GAAkBC,GAAO8G,GAAM,YAAY,KAAK;AAEhE,iBAAWtG,KAAU6G;AACnB,QAAAL,GAAkB7C,EAAW,QAAQ,UAAU3D,CAAM,CAAC;AAAA,IAE1D,GAEM8G,IAAkB,CAACtH,MAAwB;AAC/C,MACE8E,EAAuB,YAAY,QACnCA,EAAuB,YAAY9E,EAAM,cAK3C8E,EAAuB,UAAU,MACjCX,EAAW,QAAQ,MAAA;AAAA,IACrB,GAEMoD,KAAgB,CAACvH,MAAyB;AAC9C,YAAMwH,IAAWtC,EAAY,QAAQ;AAErC,MACE,CAACsC,KACDxH,EAAM,SAASwH,KACfxH,EAAM,UACNA,EAAM,UACNA,EAAM,WACNA,EAAM,WACNoC,GAA4BpC,EAAM,MAAM,MAK1CA,EAAM,eAAA,GACN6E,EAAU,UAAU,CAACA,EAAU,SAE3BA,EAAU,UACZqB,GAAA,KAEAL,EAAA,GACAM,EAAA;AAAA,IAEJ,GAEMsB,KAAyB,MAAM;AACnC,MAAA5B,EAAA,GAEI,SAAS,UAAU,CAACX,EAAY,QAAQ,kBAC1CgB,GAAA,IAEAC,EAAA;AAAA,IAEJ,GAEMuB,KAAmB,MAAM;AAC7B,MAAA/C,EAAW,UAAU,IAEjBO,EAAY,QAAQ,mBACtBW,EAAA,GACAM,EAAA,KAEAD,GAAA;AAAA,IAEJ,GAEMyB,KAAoB,MAAM;AAC9B,MAAAhD,EAAW,UAAU,IACrBkB,EAAA,GACAM,EAAA;AAAA,IACF,GAEMyB,KAAoB,MAAM;AAC9B,MAAA/B,EAAA,GAGE,CAACX,EAAY,QAAQ,oBACpB,SAAS,UAAU,CAACP,EAAW,WAEhCuB,GAAA,IAEAC,EAAA;AAAA,IAEJ;AAEA,IAAA5B,EAAqB,UAAUqD,IAE/Bb,GAAA;AAEA,UAAMc,KAAiB,IAAI,eAAe,MAAM;AAC9C,MAAAd,GAAA,GACAH,GAAA;AAAA,IACF,CAAC;AAED,IAAAiB,GAAe,QAAQvQ,CAAM;AAE7B,QAAIwQ;AAEJ,WAAI,0BAA0B,WAC5BA,KAAuB,IAAI,qBAAqB,CAACC,MAAY;AAC3D,YAAMC,IAAQD,EAAQ,CAAC;AAEvB,MAAArD,EAAW,UAAUsD,IAAQA,EAAM,iBAAiB,IAE/CtD,EAAW,UAGdyB,EAAA,IAFAD,GAAA;AAAA,IAIJ,CAAC,GACD4B,GAAqB,QAAQtC,CAAS,IAGxCA,EAAU,iBAAiB,eAAe2B,IAAoB;AAAA,MAC5D,SAAS;AAAA,IAAA,CACV,GACD3B,EAAU,iBAAiB,eAAe4B,IAAmB;AAAA,MAC3D,SAAS;AAAA,IAAA,CACV,GACD5B,EAAU,iBAAiB,aAAa8B,GAAiB;AAAA,MACvD,SAAS;AAAA,IAAA,CACV,GACD9B,EAAU,iBAAiB,gBAAgB8B,GAAiB;AAAA,MAC1D,SAAS;AAAA,IAAA,CACV,GACD9B,EAAU,iBAAiB,iBAAiB8B,GAAiB;AAAA,MAC3D,SAAS;AAAA,IAAA,CACV,GACD,OAAO,iBAAiB,QAAQI,EAAgB,GAChD,OAAO,iBAAiB,SAASC,EAAiB,GAClD,SAAS,iBAAiB,WAAWJ,EAAa,GAClD,SAAS,iBAAiB,oBAAoBE,EAAsB,GAE7D,MAAM;;AACX,MAAA5B,EAAA,GACAgC,GAAe,WAAA,GACfC,MAAA,QAAAA,GAAsB,cACtBtC,EAAU,oBAAoB,eAAe2B,EAAkB,GAC/D3B,EAAU,oBAAoB,eAAe4B,EAAiB,GAC9D5B,EAAU,oBAAoB,aAAa8B,CAAe,GAC1D9B,EAAU,oBAAoB,gBAAgB8B,CAAe,GAC7D9B,EAAU,oBAAoB,iBAAiB8B,CAAe,GAC9D,OAAO,oBAAoB,QAAQI,EAAgB,GACnD,OAAO,oBAAoB,SAASC,EAAiB,GACrD,SAAS,oBAAoB,WAAWJ,EAAa,GACrD,SAAS,oBAAoB,oBAAoBE,EAAsB,IACvErO,IAAA8K,EAAY,YAAZ,QAAA9K,EAAqB,WACrB8K,EAAY,UAAU,MACtBI,EAAgB,UAAU;SAC1BC,EAAqB,UAAU;SAC/BC,EAAqB,UAAU;;IACjC;AAAA,EACF,GAAG,CAAA,CAAE,GAELrB,EAAU,MAAM;AACd,IAAAgB,EAAW,QAAQ,MAAA,GACnBW,EAAuB,UAAU;AAAA,EACnC,GAAG,CAACjM,EAAS,eAAe,CAAC,GAE7BsK,EAAU,MAAM;AACd,IAAAoB,EAAqB,QAAA;AAAA,EACvB,GAAG,CAAC1L,EAAS,eAAe,CAAC,GAE7BsK,EAAU,MAAM;AACd,IAAI,CAACtK,EAAS,YAAYgM,EAAU,YAClCA,EAAU,UAAU,IACpBN,EAAqB,QAAA;AAAA,EAEzB,GAAG,CAAC1L,EAAS,QAAQ,CAAC;AAEtB,QAAMoP,KAAgC;AAAA,IACpC,GAAGpE;AAAA,IACH,UAAU;AAAA,IACV,UAAU;AAAA,IACV,WAAW;AAAA,EAAA;AAGb,4BACG,OAAA,EAAI,KAAKE,GAAc,WAAAH,GAAsB,OAAOqE,IAClD,UAAA;AAAA,IAAAxE,IACC,gBAAAyE;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,OAAO;AAAA,UACL,UAAU;AAAA,UACV,OAAO;AAAA,UACP,QAAQ;AAAA,UACR,eAAe;AAAA,UACf,WAAW;AAAA,QAAA;AAAA,QAGZ,UAAAzE;AAAA,MAAA;AAAA,IAAA,IAED;AAAA,IACJ,gBAAAyE;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,KAAKjE;AAAA,QACL,eAAY;AAAA,QACZ,OAAO;AAAA,UACL,UAAU;AAAA,UACV,OAAO;AAAA,UACP,QAAQ;AAAA,UACR,OAAO;AAAA,UACP,QAAQ;AAAA,UACR,eAAe;AAAA,UACf,cAAcpL,EAAS,SAAS,QAAQ,WAAW;AAAA,QAAA;AAAA,MACrD;AAAA,IAAA;AAAA,IAEF,gBAAAqP;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,OAAO;AAAA,UACL,UAAU;AAAA,UACV,QAAQ;AAAA,QAAA;AAAA,QAGT,UAAA7C;AAAA,MAAA;AAAA,IAAA;AAAA,EACH,GACF;AAEJ,CAAC,GAEY8C,KAAa7E;"}
|