@vibecook/ice 0.10.0 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-JWRHAM7L.js → chunk-2TNVB2ON.js} +2 -2
- package/dist/{chunk-MFTMPJUF.js → chunk-Q665T4L7.js} +3 -3
- package/dist/{chunk-5FQS7V2C.js → chunk-VGVDJZSP.js} +2 -3
- package/dist/{chunk-5FQS7V2C.js.map → chunk-VGVDJZSP.js.map} +1 -1
- package/dist/devtools.js +1 -1
- package/dist/dom.js +2 -2
- package/dist/ground.js +98 -203
- package/dist/ground.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/r3f.js +3 -3
- package/dist/react.js +3 -3
- package/dist/types/packages/core/src/index.d.ts +1 -1
- package/dist/types/packages/core/src/settings/ground-config.d.ts +13 -15
- package/dist/types/packages/ground/src/index.d.ts +2 -2
- package/dist/types/packages/ground/src/passes/grid-contract.d.ts +28 -0
- package/dist/types/packages/ground/src/passes/grid-magnet-pass.d.ts +2 -0
- package/dist/types/packages/ground/src/passes/grid-magnet.d.ts +2 -2
- package/dist/types/packages/ground/src/passes/grid.d.ts +7 -25
- package/dist/types/packages/ground/src/poles.d.ts +2 -2
- package/package.json +1 -1
- package/dist/types/packages/ground/src/passes/grid-classic.d.ts +0 -30
- /package/dist/{chunk-JWRHAM7L.js.map → chunk-2TNVB2ON.js.map} +0 -0
- /package/dist/{chunk-MFTMPJUF.js.map → chunk-Q665T4L7.js.map} +0 -0
package/dist/ground.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../ground/src/layer.ts","../../ground/src/passes/grid.ts","../../ground/src/passes/grid-classic.ts","../../ground/src/passes/grid-magnet.ts","../../ground/src/passes/soup-collect.ts","../../ground/src/passes/wires-collect.ts","../../ground/src/passes/magnet-collect.ts","../../ground/src/passes/guides-collect.ts","../../ground/src/passes/soup-mesh.ts","../../ground/src/passes/guides.ts","../../ground/src/passes/wires.ts","../../ground/src/renderer.ts","../../ground/src/poles.ts","../../ground/src/index.ts"],"sourcesContent":["/**\n * The ground LAYER — one reflector, one canvas, one render (design-004 §1\n * as-built 2026-07-16: P0 consolidated from three stacked canvases into a\n * single WebGPU canvas; grid, wires and snap-guides are now PASSES of this\n * layer, and future ground effects join the same registry).\n *\n * Coordinate model: the layer renders in SCREEN CSS-px space — an ortho\n * camera maps [0..w]×[0..h] (y-down) to clip, and passes build their geometry\n * through the kernel `worldToScreen` seam per collect (the proven 2D-canvas\n * semantics: geometry rebuilds on the same dirt that re-stroked the old\n * canvases; the grid stays a per-pixel screen-space shader). The Y-flip\n * question never arises here — `worldToScreen` IS the one conversion (L13).\n *\n * Reflector contract (design-002 §5): post-notify, output-only, never reads\n * layout in flush (the ResizeObserver owns sizing), never writes ECS.\n * `always: true` with a private dirty union — an idle scene renders zero\n * frames; ANY dirty pass re-renders the whole canvas (one draw, same cost\n * class as a pan frame under the old grid). WebGPU init is async: flushes\n * before ready are deferred (flags stay armed), the first ready flush paints.\n */\nimport { Camera, type ReflectorDef, type World } from \"@ice/core\";\nimport { OrthographicCamera, Scene } from \"three/webgpu\";\nimport type { GroundFrame, GroundPass } from \"./pass\";\nimport type { GroundRendererLike } from \"./renderer\";\n\nexport interface GroundLayerHost {\n readonly container: HTMLElement;\n readonly contentPlane: HTMLElement;\n}\n\nexport interface GroundReflector extends ReflectorDef {\n /** False while init is pending or after a device/context failure. */\n available(): boolean;\n /** Whole-canvas renders so far (the churn instrument — 0 on an idle scene). */\n redraws(): number;\n}\n\nexport interface GroundLayerInternals {\n reflector: GroundReflector;\n /** Wake every pass + render (config changes, external invalidation). */\n invalidateAll(): void;\n dispose(): void;\n}\n\nexport function createLayer(\n host: GroundLayerHost,\n world: World,\n renderer: GroundRendererLike,\n passes: readonly GroundPass[],\n): GroundLayerInternals {\n const doc = host.container.ownerDocument;\n const canvas = renderer.canvas;\n canvas.style.position = \"absolute\";\n canvas.style.left = \"0\";\n canvas.style.top = \"0\";\n canvas.style.width = \"100%\";\n canvas.style.height = \"100%\";\n canvas.style.display = \"block\";\n // P0 is never a DOM hit target (the router owns picking, design-004 §4).\n canvas.style.pointerEvents = \"none\";\n // The whole ground stratum is this ONE canvas, immediately before content.\n host.container.insertBefore(canvas, host.contentPlane);\n\n const scene = new Scene();\n // Screen-px ortho, y-down: (0,0) = top-left, (w,h) = bottom-right.\n const camera = new OrthographicCamera(0, 1, 0, 1, -1000, 1000);\n for (const pass of passes) scene.add(pass.object);\n\n // --- dirt ------------------------------------------------------------------\n const dirty = new Map<GroundPass, boolean>();\n for (const pass of passes) dirty.set(pass, true);\n let anyDirty = true;\n const wakeAll = (): void => {\n for (const pass of passes) dirty.set(pass, true);\n anyDirty = true;\n };\n const unsubs: Array<() => void> = [\n // Camera moves re-map every pass's screen-space geometry (2D-canvas parity).\n world.reactive.observeResource(Camera, wakeAll),\n ];\n for (const pass of passes) {\n unsubs.push(\n ...pass.arm(world, () => {\n dirty.set(pass, true);\n anyDirty = true;\n }),\n );\n }\n renderer.onReady(wakeAll); // the deferred pre-ready flushes are owed one paint\n\n // --- sizing (RO owns layout reads — never the flush) -----------------------\n let cssW = 0;\n let cssH = 0;\n let dpr = 1;\n const applySize = (w: number, h: number): void => {\n dpr = doc.defaultView?.devicePixelRatio ?? 1;\n cssW = w;\n cssH = h;\n renderer.setSize(w, h, dpr);\n camera.left = 0;\n camera.right = Math.max(1, w);\n camera.top = 0;\n camera.bottom = Math.max(1, h);\n camera.updateProjectionMatrix();\n wakeAll();\n };\n const initialRect = host.container.getBoundingClientRect();\n applySize(initialRect.width, initialRect.height);\n let ro: ResizeObserver | null = null;\n try {\n ro = new ResizeObserver((entries) => {\n const entry = entries[0];\n if (entry === undefined) return;\n applySize(entry.contentRect.width, entry.contentRect.height);\n });\n ro.observe(host.container);\n } catch {\n ro = null;\n }\n\n let redraws = 0;\n\n const reflector: GroundReflector = {\n name: \"ground\",\n // Self-gated on the dirty union (wires/chrome precedent) — the every-frame\n // cost is one boolean check.\n always: true,\n flush(w: World) {\n if (!anyDirty || renderer.failed()) return;\n if (!renderer.ready()) return; // init pending — flags stay armed, retry next frame\n const cam = w.getResource(Camera);\n if (cam === undefined) return;\n anyDirty = false;\n const frame: GroundFrame = { width: cssW, height: cssH, dpr, camera: cam };\n for (const pass of passes) {\n if (dirty.get(pass) === true) {\n dirty.set(pass, false);\n pass.collect(w, frame);\n }\n }\n redraws++;\n renderer.render(scene, camera);\n },\n available: () => renderer.ready() && !renderer.failed(),\n redraws: () => redraws,\n };\n\n return {\n reflector,\n invalidateAll: wakeAll,\n dispose() {\n for (const u of unsubs) u();\n unsubs.length = 0;\n ro?.disconnect();\n ro = null;\n for (const pass of passes) pass.dispose();\n renderer.dispose();\n canvas.remove();\n },\n };\n}\n","/**\n * The grid pass — a MODE FACADE since design-010: the classic analytic dot\n * grid (grid-classic.ts, the default — byte-identical to pre-magnet builds)\n * and the magnet field lattice (grid-magnet.ts + magnet-collect.ts) behind\n * ONE `GridPass` contract. `configure` deep-merges the `magnet` key one level\n * (§3.1) so partial re-tunes never clobber the block.\n *\n * Wake graph (all magnet wakes gated on `enabled` — the idle-scene zero-frame\n * guarantee is untouched when off): camera/resize are layer-owned;\n * `SpatialVersion` re-collects widget sources (gated on `widgets` too);\n * injected pole sources wake through their own subscriptions (D5 — the pass\n * observes no pointer/cursor/presence vocabulary). The magnet renderer is\n * built LAZILY on first enable: classic-only apps pay zero magnet cost.\n */\nimport {\n DEFAULT_GRID_CONFIG,\n SpatialVersion,\n type GridConfig,\n type World,\n} from \"@ice/core\";\nimport { Group } from \"three/webgpu\";\nimport type { GroundFrame, GroundPass } from \"../pass\";\nimport type { Pole, PoleSource } from \"../poles\";\nimport { createClassicGrid, type ClassicGridRenderer } from \"./grid-classic\";\nimport { createMagnetGrid, type MagnetGridRenderer } from \"./grid-magnet\";\nimport {\n MAGNET_SOURCE_FLOATS,\n MAX_MAGNET_SOURCES,\n collectMagnetLevels,\n collectMagnetSources,\n magnetFieldScale,\n resolveMagnet,\n type ReadSpatial,\n} from \"./magnet-collect\";\n\nexport interface GridPass extends GroundPass {\n /** Live re-tune (the react `grid` prop seam) — partial merge over current values. */\n configure(cfg: Partial<GridConfig>): void;\n}\n\n/** Injected magnet inputs (design-010 §3.2) — absent pieces disable their sources. */\nexport interface GridPassDeps {\n readonly poles?: readonly PoleSource[];\n readonly readSpatial?: ReadSpatial;\n}\n\n/** Shallow merge + one-level deep merge of the `magnet` block (design-010 §3.1). */\nfunction mergeGridConfig(base: GridConfig, next: Partial<GridConfig>): GridConfig {\n const merged: GridConfig = { ...base, ...next };\n if (next.magnet !== undefined) merged.magnet = { ...base.magnet, ...next.magnet };\n return merged;\n}\n\nexport function createGridPass(initial: Partial<GridConfig> = {}, deps: GridPassDeps = {}): GridPass {\n let cfg = mergeGridConfig(DEFAULT_GRID_CONFIG, initial);\n\n const group = new Group();\n const classic: ClassicGridRenderer = createClassicGrid(cfg);\n group.add(classic.mesh);\n let magnet: MagnetGridRenderer | null = null;\n\n const poles = deps.poles ?? [];\n const sourceScratch = new Float32Array(MAX_MAGNET_SOURCES * MAGNET_SOURCE_FLOATS);\n const poleScratch: Pole[] = [];\n\n return {\n name: \"grid\",\n object: group,\n arm(world: World, wake: () => void) {\n // Gates read LIVE config so configure() re-tunes never re-arm.\n const wakeIfWidgets = (): void => {\n const m = resolveMagnet(cfg);\n if (m.enabled && m.widgets && deps.readSpatial !== undefined) wake();\n };\n const wakeIfEnabled = (): void => {\n if (resolveMagnet(cfg).enabled) wake();\n };\n const unsubs = [world.reactive.observeResource(SpatialVersion, wakeIfWidgets)];\n for (const source of poles) unsubs.push(source.subscribe(world, wakeIfEnabled));\n return unsubs;\n },\n collect(world: World, frame: GroundFrame) {\n const m = resolveMagnet(cfg);\n if (!m.enabled) {\n classic.mesh.visible = true;\n if (magnet !== null) magnet.group.visible = false;\n classic.setCamera(frame);\n return;\n }\n if (magnet === null) {\n magnet = createMagnetGrid();\n group.add(magnet.group);\n }\n classic.mesh.visible = false;\n magnet.group.visible = true;\n\n const fieldScale = magnetFieldScale(frame.camera.zoom, m.fadeZoom);\n poleScratch.length = 0;\n if (fieldScale > 0) {\n for (const source of poles) poleScratch.push(...source.read(world));\n }\n const sourceCount = collectMagnetSources(\n world,\n frame,\n m,\n fieldScale,\n poleScratch,\n deps.readSpatial,\n sourceScratch,\n );\n const levels = collectMagnetLevels(frame, cfg);\n magnet.update(frame, cfg, m, levels, sourceScratch, sourceCount);\n },\n configure(next) {\n cfg = mergeGridConfig(cfg, next);\n classic.configure(cfg);\n // Magnet uniforms are rewritten wholesale next collect (configureGrid\n // calls invalidateAll) — no push needed here.\n },\n dispose() {\n classic.dispose();\n magnet?.dispose();\n magnet = null;\n },\n };\n}\n","/**\n * The CLASSIC dot-grid renderer — extracted VERBATIM from grid.ts when the\n * magnet mode arrived (design-010 D1: classic stays the default and the\n * pixel-exact baseline; the pass facade in grid.ts owns mode switching).\n *\n * TSL port of the raw-WebGL grid (itself verbatim from v1 GridRenderer.ts;\n * the fragment math below is that shader re-expressed as a node graph, level\n * loop unrolled in JS). Screen-space: a fullscreen triangle whose vertex\n * stage passes clip coords through; the fragment reconstructs world position\n * from `screenCoordinate` (top-left device px on BOTH backends — three\n * normalizes, so the old manual y-flip is gone) + camera uniforms.\n *\n * One deliberate re-expression: the GLSL if/else fade ladder became the\n * closed form `clamp(min(rise, fall), 0, 1)` — identical piecewise output\n * (rise 0→1 across fadeIn, plateau 1, fall 1→0 across fadeOut) with no\n * branching. Everything else (fract-distance dots, 0.5-device-px AA,\n * max-composited levels) matches term for term.\n */\nimport type { GridConfig } from \"@ice/core\";\nimport {\n clamp,\n float,\n fract,\n length,\n max,\n min,\n mix,\n positionGeometry,\n screenCoordinate,\n smoothstep,\n uniform,\n vec4,\n} from \"three/tsl\";\nimport {\n BufferAttribute,\n BufferGeometry,\n Mesh,\n MeshBasicNodeMaterial,\n Vector2,\n Vector3,\n type Node,\n} from \"three/webgpu\";\nimport type { GroundFrame } from \"../pass\";\n\nconst FULLSCREEN_TRIANGLE = new Float32Array([-1, -1, 0, 3, -1, 0, -1, 3, 0]);\n\nexport interface ClassicGridRenderer {\n readonly mesh: Mesh;\n /** Layer-written each collect. */\n setCamera(frame: GroundFrame): void;\n /** Config-written (the configure seam). */\n configure(cfg: GridConfig): void;\n dispose(): void;\n}\n\nexport function createClassicGrid(cfg: GridConfig): ClassicGridRenderer {\n // Camera facts (collect-written).\n const uCamera = uniform(new Vector2(0, 0));\n const uZoom = uniform(1);\n const uDpr = uniform(1);\n // Config (configure-written).\n const uSpacings = uniform(new Vector3(...cfg.spacings));\n const uDotColor = uniform(new Vector3(...cfg.dotColor));\n const uDotAlpha = uniform(cfg.dotAlpha);\n const uFadeIn = uniform(new Vector2(...cfg.fadeIn));\n const uFadeOut = uniform(new Vector2(...cfg.fadeOut));\n const uDotRadius = uniform(new Vector2(...cfg.dotRadius));\n const uLevelWeight = uniform(new Vector2(...cfg.levelWeight));\n\n const effZoom = uZoom.mul(uDpr);\n const worldPos = screenCoordinate.xy.div(effZoom).add(uCamera);\n\n let total: Node<\"float\"> = float(0);\n for (let i = 0; i < 3; i++) {\n const spacing = i === 0 ? uSpacings.x : i === 1 ? uSpacings.y : uSpacings.z;\n const cssSpacing = spacing.mul(uZoom);\n // Fade ladder, closed form (see header).\n const rise = cssSpacing.sub(uFadeIn.x).div(uFadeIn.y.sub(uFadeIn.x));\n const fall = float(1).sub(cssSpacing.sub(uFadeOut.x).div(uFadeOut.y.sub(uFadeOut.x)));\n const opacity = clamp(min(rise, fall), 0, 1);\n // Distance to the nearest grid intersection, in device px.\n const f = fract(worldPos.div(spacing).add(0.5)).sub(0.5);\n const dist = length(f).mul(spacing).mul(effZoom);\n // Radius optionally grows toward sparser levels (min==max ⇒ constant dots).\n const t = clamp(cssSpacing.sub(uFadeIn.x).div(40), 0, 1);\n const radius = mix(uDotRadius.x, uDotRadius.y, t).mul(uDpr);\n // Anti-aliased dot (0.5 device-px smoothstep), max-composited across levels\n // (additive stacking fattens joint intersections — the CAD tell).\n const dot = smoothstep(radius.sub(0.5), radius.add(0.5), dist).oneMinus();\n const weight = uLevelWeight.x.add(float(i).mul(uLevelWeight.y));\n total = max(total, dot.mul(opacity).mul(weight));\n }\n\n const material = new MeshBasicNodeMaterial();\n material.vertexNode = vec4(positionGeometry.xy, 0, 1); // clip-space passthrough\n material.fragmentNode = vec4(uDotColor, clamp(total.mul(uDotAlpha), 0, 1));\n material.transparent = true;\n material.depthTest = false;\n material.depthWrite = false;\n\n const geometry = new BufferGeometry();\n geometry.setAttribute(\"position\", new BufferAttribute(FULLSCREEN_TRIANGLE, 3));\n const mesh = new Mesh(geometry, material);\n mesh.frustumCulled = false;\n mesh.renderOrder = 0;\n\n return {\n mesh,\n setCamera(frame) {\n uCamera.value.set(frame.camera.x, frame.camera.y);\n uZoom.value = frame.camera.zoom;\n uDpr.value = frame.dpr;\n },\n configure(next) {\n uSpacings.value.set(...next.spacings);\n uDotColor.value.set(...next.dotColor);\n uDotAlpha.value = next.dotAlpha;\n uFadeIn.value.set(...next.fadeIn);\n uFadeOut.value.set(...next.fadeOut);\n uDotRadius.value.set(...next.dotRadius);\n uLevelWeight.value.set(...next.levelWeight);\n },\n dispose() {\n geometry.dispose();\n material.dispose();\n },\n };\n}\n","/**\n * The MAGNET grid renderer — TSL port of vibe-field draft/magnet-grid's\n * `magnet.wgsl` (design-010 §5). Three instanced-quad meshes (one per lattice\n * level) whose vertex stage reconstructs sites from `instanceIndex`, evaluates\n * the field (superposition of rounded-box SDF sources; poles are DEGENERATE\n * boxes with half = 0, r = 0 — D3), and shapes the glyph (needle orients\n * along the field; dot swells with |field|).\n *\n * Deltas from the WGSL, per design-010:\n * - ONE source buffer (storage, read-only, `setPBO` for the WebGL fallback —\n * D4); the mouse uniform / `mouseOn` branch are deleted.\n * - fade ladder, level weight and dotAlpha are CPU-baked into ONE per-level\n * alpha (they are per-level constants per frame — magnet-collect owns them).\n * - dot rest radius comes from `GridConfig.dotRadius[0]` (config continuity\n * with the classic grid), not the WGSL's hardcoded `halfLen·0.16`.\n * - coincidence skip (§5.4): sites shared with a visible coarser level drop\n * out (integer spacing ratios), replicating the classic max-composite look.\n * - NDC is computed from CSS-px directly (the WGSL path) — glyph sizes are\n * CSS px, DPR rides the viewport; the layer's ortho camera is bypassed.\n */\nimport type { GridConfig, GridMagnetConfig } from \"@ice/core\";\nimport {\n Fn,\n If,\n Loop,\n abs,\n clamp,\n float,\n instanceIndex,\n int,\n length,\n max,\n min,\n mix,\n mod,\n positionGeometry,\n select,\n sign,\n smoothstep,\n sqrt,\n storage,\n uniform,\n varying,\n vec2,\n vec4,\n Continue,\n Discard,\n} from \"three/tsl\";\nimport {\n BufferAttribute,\n Group,\n InstancedBufferGeometry,\n Mesh,\n MeshBasicNodeMaterial,\n StorageBufferAttribute,\n Vector2,\n Vector3,\n type Node,\n} from \"three/webgpu\";\nimport type { GroundFrame } from \"../pass\";\nimport { MAGNET_SOURCE_FLOATS, MAX_MAGNET_SOURCES, type MagnetLevel } from \"./magnet-collect\";\n\n/** Unit quad corners, 2 triangles (xy in [-1,1]; z unused — vec3 for positionGeometry). */\nconst CORNERS = new Float32Array([-1, -1, 0, 1, -1, 0, 1, 1, 0, -1, -1, 0, 1, 1, 0, -1, 1, 0]);\n\nconst LEVELS = 3;\n\nexport interface MagnetGridRenderer {\n readonly group: Group;\n /** Rewrite every uniform + the source buffer from this frame's collect. */\n update(\n frame: GroundFrame,\n cfg: GridConfig,\n magnet: GridMagnetConfig,\n levels: readonly MagnetLevel[],\n sources: Float32Array,\n sourceCount: number,\n ): void;\n dispose(): void;\n}\n\nexport function createMagnetGrid(): MagnetGridRenderer {\n // --- shared state (one copy across the three level materials) --------------\n const sourceArray = new Float32Array(MAX_MAGNET_SOURCES * MAGNET_SOURCE_FLOATS);\n const sourceAttr = new StorageBufferAttribute(sourceArray, 4);\n // Read-only storage; PBO keeps the WebGL2 fallback functional (D4).\n const sourceBuf = storage(sourceAttr, \"vec4\", MAX_MAGNET_SOURCES * 2)\n .setPBO(true)\n .toReadOnly();\n\n const uCam = uniform(new Vector2(0, 0));\n const uZoom = uniform(1);\n const uView = uniform(new Vector2(1, 1));\n const uDotMode = uniform(0);\n const uHalfLen = uniform(5);\n const uHalfWidth = uniform(0.55);\n const uRestRadius = uniform(0.75);\n const uK = uniform(0);\n const uPad = uniform(0); // √(k/0.02) — the shader-side AABB reject cutoff\n const uPolarity = uniform(1);\n const uAlwaysAlign = uniform(0);\n const uCount = uniform(0, \"int\");\n const uColor = uniform(new Vector3(0.75, 0.77, 0.8));\n\n const EPS = float(25); // magnet.wgsl uniform slot 21 — fixed there too\n const REST = vec2(0, 1); // rest direction: hang \"down\" in y-down screen space\n\n // IQ rounded box; p local (site − center), b half-size, r corner radius.\n const sdRoundBox = Fn(([p, b, r]: [Node<\"vec2\">, Node<\"vec2\">, Node<\"float\">]) => {\n const q = abs(p).sub(b).add(vec2(r, r));\n return length(max(q, vec2(0, 0)))\n .add(min(max(q.x, q.y), 0))\n .sub(r);\n });\n\n // Outward unit normal of the same box (analytic — magnet.wgsl:64-80).\n const roundBoxNormal = Fn(([p, b, r]: [Node<\"vec2\">, Node<\"vec2\">, Node<\"float\">]) => {\n const s = sign(p);\n const q = abs(p);\n const inner = max(b.sub(vec2(r, r)), vec2(0, 0));\n const d = q.sub(inner);\n const n = vec2(0, 0).toVar();\n If(d.x.greaterThan(0).and(d.y.greaterThan(0)), () => {\n const len = length(d);\n If(len.greaterThan(0.0001), () => {\n n.assign(s.mul(d.div(len)));\n }).Else(() => {\n n.assign(vec2(s.x, 0));\n });\n })\n .ElseIf(d.x.greaterThan(d.y), () => {\n n.assign(vec2(s.x, 0));\n })\n .Else(() => {\n n.assign(vec2(0, s.y));\n });\n return n;\n });\n\n const safeNormalize = Fn(([v, fallback]: [Node<\"vec2\">, Node<\"vec2\">]) => {\n const n = length(v);\n return select(n.greaterThan(0.0001), v.div(max(n, 0.0001)), fallback);\n });\n\n const group = new Group();\n const geometries: InstancedBufferGeometry[] = [];\n const materials: MeshBasicNodeMaterial[] = [];\n const meshes: Mesh[] = [];\n const levelUniforms = Array.from({ length: LEVELS }, () => ({\n origin: uniform(new Vector2(0, 0)),\n dims: uniform(new Vector2(1, 1)),\n spacing: uniform(20),\n alpha: uniform(0),\n skipMod: uniform(0),\n }));\n\n for (let level = 0; level < LEVELS; level++) {\n const lu = levelUniforms[level] as (typeof levelUniforms)[number];\n\n const vUv = varying(vec2(0, 0), `vMagnetUv${level}`);\n const vAlpha = varying(float(0), `vMagnetAlpha${level}`);\n\n const vertexNode = Fn(() => {\n const iid = float(instanceIndex);\n const cols = lu.dims.x;\n const col = mod(iid, cols).floor();\n const row = iid.div(cols).floor();\n const world = lu.origin.add(vec2(col, row)).mul(lu.spacing);\n const screen = world.sub(uCam).mul(uZoom);\n\n // Field superposition over the source buffer (magnet.wgsl field_at).\n const field = vec2(0, 0).toVar();\n const minD = float(1e9).toVar();\n Loop({ start: int(0), end: uCount, type: \"int\", condition: \"<\" }, ({ i }) => {\n const a = sourceBuf.element(i.mul(2)); // cx, cy, hx, hy\n const b = sourceBuf.element(i.mul(2).add(1)); // r, strength, 0, 0\n const center = a.xy;\n const half = a.zw;\n const rad = b.x;\n const strength = b.y;\n const rel = screen.sub(center);\n const reach = uPad.mul(sqrt(max(strength, 0.0001)));\n If(\n abs(rel.x)\n .greaterThan(half.x.add(reach))\n .or(abs(rel.y).greaterThan(half.y.add(reach))),\n () => {\n Continue();\n },\n );\n const d = sdRoundBox(rel, half, rad);\n minD.assign(min(minD, d));\n const dist = max(d, 0);\n const r2 = dist.mul(dist).add(EPS);\n const outward = roundBoxNormal(rel, half, rad);\n // Attract toward the body = against the outward normal.\n field.subAssign(outward.mul(uK.mul(strength).mul(uPolarity).div(r2)));\n });\n\n const fieldDir = safeNormalize(field, REST);\n const mag = length(field);\n // Needles want a hard 0–1 blend; dots want the softer 1/r² size curve\n // (saturate plateaus at ~100px and every nearby site looks identical).\n const influence = select(uDotMode.greaterThan(0.5), mag.div(mag.add(1)), clamp(mag, 0, 1));\n\n const corner = positionGeometry.xy;\n // Dot: size encodes |field| — far sites rest at the classic dot radius.\n const dotRadius = mix(uRestRadius, uHalfLen.mul(1.05), influence);\n const dotLocal = corner.mul(dotRadius);\n // Needle: orient along the field (or rest-blended), length/width as cues.\n const dir = select(\n uAlwaysAlign.greaterThan(0.5),\n fieldDir,\n safeNormalize(mix(REST, fieldDir, influence), REST),\n );\n const nrm = vec2(dir.y.negate(), dir.x);\n const nLen = mix(uHalfLen.mul(0.55), uHalfLen.mul(1.35), influence);\n const nWid = mix(uHalfWidth.mul(0.85), uHalfWidth.mul(1.15), influence);\n const needleLocal = nrm.mul(corner.x).mul(nWid).add(dir.mul(corner.y).mul(nLen));\n const local = select(uDotMode.greaterThan(0.5), dotLocal, needleLocal);\n const pos = screen.add(local);\n\n // Needles use alpha as a second cue; dots keep alpha steadier so size reads first.\n const restAlpha = select(uDotMode.greaterThan(0.5), float(0.72), float(0.35));\n const fieldAlpha = mix(restAlpha, float(1), influence);\n const alpha = clamp(lu.alpha.mul(fieldAlpha), 0, 1).toVar();\n // Hide glyphs under a source body — the widget already covers them.\n If(minD.lessThan(-0.5), () => {\n alpha.assign(0);\n });\n // Coincidence skip (§5.4): absolute lattice index ≡ 0 (mod ratio) on both\n // axes belongs to the visible coarser level (mod() is non-negative).\n const absI = lu.origin.x.add(col);\n const absJ = lu.origin.y.add(row);\n If(\n lu.skipMod\n .greaterThan(0.5)\n .and(mod(absI, lu.skipMod).lessThan(0.5))\n .and(mod(absJ, lu.skipMod).lessThan(0.5)),\n () => {\n alpha.assign(0);\n },\n );\n\n vUv.assign(corner);\n vAlpha.assign(alpha);\n\n const ndc = vec2(\n pos.x.div(uView.x).mul(2).sub(1),\n float(1).sub(pos.y.div(uView.y).mul(2)),\n );\n return vec4(ndc, 0, 1);\n })();\n\n const fragmentNode = Fn(() => {\n const dotEdge = float(1).sub(smoothstep(0.62, 1.0, length(vUv)));\n const ax = float(1).sub(smoothstep(0.55, 1.0, abs(vUv.x)));\n const ay = float(1).sub(smoothstep(0.82, 1.0, abs(vUv.y)));\n const edge = select(uDotMode.greaterThan(0.5), dotEdge, ax.mul(ay));\n const a = vAlpha.mul(edge);\n Discard(a.lessThan(0.01));\n return vec4(uColor, a);\n })();\n\n const material = new MeshBasicNodeMaterial();\n material.vertexNode = vertexNode;\n material.fragmentNode = fragmentNode;\n material.transparent = true;\n material.depthTest = false;\n material.depthWrite = false;\n\n const geometry = new InstancedBufferGeometry();\n geometry.setAttribute(\"position\", new BufferAttribute(CORNERS, 3));\n geometry.instanceCount = 0;\n\n const mesh = new Mesh(geometry, material);\n mesh.frustumCulled = false;\n mesh.renderOrder = 0;\n mesh.visible = false;\n\n geometries.push(geometry);\n materials.push(material);\n meshes.push(mesh);\n group.add(mesh);\n }\n\n return {\n group,\n update(frame, cfg, magnet, levels, sources, sourceCount) {\n uCam.value.set(frame.camera.x, frame.camera.y);\n uZoom.value = frame.camera.zoom;\n uView.value.set(Math.max(1, frame.width), Math.max(1, frame.height));\n uDotMode.value = magnet.glyph === \"dot\" ? 1 : 0;\n uHalfLen.value = magnet.needleLength;\n uHalfWidth.value = magnet.needleWidth;\n uRestRadius.value = cfg.dotRadius[0];\n const k = 0.5 * magnet.reach * magnet.reach;\n uK.value = k;\n uPad.value = Math.sqrt(Math.max(k, 1) / 0.02);\n uPolarity.value = magnet.polarity;\n uAlwaysAlign.value = magnet.alwaysAlign ? 1 : 0;\n uCount.value = sourceCount;\n uColor.value.set(...cfg.dotColor);\n\n if (sourceCount > 0) {\n sourceArray.set(sources.subarray(0, sourceCount * MAGNET_SOURCE_FLOATS));\n sourceAttr.needsUpdate = true;\n }\n\n for (let level = 0; level < LEVELS; level++) {\n const win = levels[level];\n const lu = levelUniforms[level] as (typeof levelUniforms)[number];\n const geometry = geometries[level] as InstancedBufferGeometry;\n const mesh = meshes[level] as Mesh;\n if (win === undefined || win.count <= 0) {\n geometry.instanceCount = 0;\n mesh.visible = false;\n continue;\n }\n lu.origin.value.set(win.i0, win.j0);\n lu.dims.value.set(win.cols, win.rows);\n lu.spacing.value = cfg.spacings[level] as number;\n lu.alpha.value = win.alpha;\n lu.skipMod.value = win.skipModulo;\n geometry.instanceCount = win.count;\n mesh.visible = true;\n }\n },\n dispose() {\n for (const g of geometries) g.dispose();\n for (const m of materials) m.dispose();\n },\n };\n}\n","/**\n * Triangle-soup builders — the PURE half of the geometry passes (no three\n * import; unit-tested under happy-dom). Collectors emit screen-px triangles\n * with per-vertex rgba into a growable soup; the three-side `soup-mesh`\n * uploads them. MSAA (renderer antialias) smooths edges, matching the old 2D\n * canvases' stroke AA closely enough at 1–2 px widths.\n */\n\nexport interface TriSoup {\n /** xyz per vertex (z = 0 — the layer renders flat in screen space). */\n positions: Float32Array;\n /** rgba per vertex, 0-1. */\n colors: Float32Array;\n vertexCount: number;\n}\n\nexport type Rgba = readonly [number, number, number, number];\n\nexport class SoupBuilder {\n private pos: number[] = [];\n private col: number[] = [];\n\n private vert(x: number, y: number, c: Rgba): void {\n this.pos.push(x, y, 0);\n this.col.push(c[0], c[1], c[2], c[3]);\n }\n\n /** Axis-aligned rect (two triangles). */\n rect(x: number, y: number, w: number, h: number, c: Rgba): void {\n this.vert(x, y, c);\n this.vert(x + w, y, c);\n this.vert(x + w, y + h, c);\n this.vert(x, y, c);\n this.vert(x + w, y + h, c);\n this.vert(x, y + h, c);\n }\n\n /** Stroke segment (a→b) of `width`, flat caps — a quad across the segment normal. */\n segment(ax: number, ay: number, bx: number, by: number, width: number, c: Rgba): void {\n const dx = bx - ax;\n const dy = by - ay;\n const len = Math.hypot(dx, dy);\n if (len < 1e-6) return;\n const nx = (-dy / len) * (width / 2);\n const ny = (dx / len) * (width / 2);\n this.vert(ax + nx, ay + ny, c);\n this.vert(bx + nx, by + ny, c);\n this.vert(bx - nx, by - ny, c);\n this.vert(ax + nx, ay + ny, c);\n this.vert(bx - nx, by - ny, c);\n this.vert(ax - nx, ay - ny, c);\n }\n\n /** Stroke a polyline (interleaved xy) as per-segment quads (smooth-curve joins). */\n polyline(points: ArrayLike<number>, width: number, c: Rgba): void {\n const n = Math.floor((points.length as number) / 2);\n for (let i = 1; i < n; i++) {\n this.segment(\n points[(i - 1) * 2] as number,\n points[(i - 1) * 2 + 1] as number,\n points[i * 2] as number,\n points[i * 2 + 1] as number,\n width,\n c,\n );\n }\n }\n\n /** Filled disc as a triangle fan (MSAA smooths the rim; 16 segs ≈ round at ≤8 px). */\n disc(cx: number, cy: number, r: number, c: Rgba, segments = 16): void {\n for (let i = 0; i < segments; i++) {\n const a0 = (i / segments) * Math.PI * 2;\n const a1 = ((i + 1) / segments) * Math.PI * 2;\n this.vert(cx, cy, c);\n this.vert(cx + Math.cos(a0) * r, cy + Math.sin(a0) * r, c);\n this.vert(cx + Math.cos(a1) * r, cy + Math.sin(a1) * r, c);\n }\n }\n\n build(): TriSoup {\n return {\n positions: new Float32Array(this.pos),\n colors: new Float32Array(this.col),\n vertexCount: this.pos.length / 3,\n };\n }\n}\n\n/**\n * `rgba(r, g, b, a)` / `rgb(…)` / `#rrggbb` → [r,g,b,a] 0-1 (the WiresConfig\n * colors are CSS strings — v1/2D-canvas heritage). Unknown formats fall back\n * to opaque mid-gray rather than throwing in a reflector path.\n */\nexport function parseCssColor(css: string): Rgba {\n const rgba = /^rgba?\\(\\s*([\\d.]+)\\s*,\\s*([\\d.]+)\\s*,\\s*([\\d.]+)\\s*(?:,\\s*([\\d.]+)\\s*)?\\)$/.exec(css);\n if (rgba !== null) {\n return [\n Number(rgba[1]) / 255,\n Number(rgba[2]) / 255,\n Number(rgba[3]) / 255,\n rgba[4] === undefined ? 1 : Number(rgba[4]),\n ];\n }\n const hex = /^#([0-9a-f]{6})$/i.exec(css);\n if (hex !== null) {\n const v = Number.parseInt(hex[1] as string, 16);\n return [((v >> 16) & 0xff) / 255, ((v >> 8) & 0xff) / 255, (v & 0xff) / 255, 1];\n }\n return [0.5, 0.5, 0.5, 1];\n}\n","/**\n * Wires collector — the pure ECS→triangles half of the wires pass. Port of\n * the 2D-canvas wires reflector's drawing, kernel-tessellated:\n *\n * - Wire geometry NEVER reads a port ENTITY (design-001 §5.3): endpoints\n * resolve from the wire's `WireFrom`/`WireTo` widgets + `WirePorts` ids\n * against the type registry's static port schema (core `portSlots` — the\n * old local resolver's TODO, retired), so a CULLED endpoint still draws.\n * - Cubics build in WORLD space then map control points through the kernel\n * `worldToScreen` seam — bezier curves are affine-invariant, so the mapped\n * cubic IS the screen curve — and `tessellateCubic` (0.25 px tolerance)\n * flattens with density that tracks zoom for free.\n * - Connect preview: solid when snapped-compatible, dashed [6,4] otherwise\n * (dash placement from the tessellation's arc-length prefix).\n * - Materialized port dots: triangle-fan discs, active color while any\n * connect drag is routed.\n */\nimport {\n Active,\n Culled,\n DEFAULT_WIRES_CONFIG,\n Drag,\n MeasuredSize,\n Port,\n PortAnchor,\n Position,\n PrefabId,\n RoutedConnect,\n Selected,\n Size,\n Wire,\n WireFrom,\n WirePorts,\n WireTo,\n defineQuery,\n portSlots,\n widgets,\n type Entity,\n type WidgetType,\n type WirePreviewBuffer,\n type WiresConfig,\n type World,\n} from \"@ice/core\";\nimport {\n portAnchor,\n tessellateCubic,\n wireCubic,\n worldToScreen,\n type Cubic,\n type PortSlot,\n type Rect,\n type Tessellation,\n} from \"@ice/kernel\";\nimport type { GroundFrame } from \"../pass\";\nimport { SoupBuilder, parseCssColor, type Rgba, type TriSoup } from \"./soup-collect\";\n\nexport const wireQ = defineQuery([Wire]);\nexport const geometryQ = defineQuery([Position, Size]);\nexport const measuredQ = defineQuery([MeasuredSize]);\nexport const selectedQ = defineQuery([Selected]);\nexport const portQ = defineQuery([Port, PortAnchor]);\nexport const routedConnectQ = defineQuery([RoutedConnect]);\n/** A live connect drag moves the preview every frame — Drag value dirt covers it. */\nexport const connectDragQ = defineQuery([RoutedConnect, Drag]);\n/** Nav churn signal: Active membership flips re-collect (scope filter below). */\nexport const activeQ = defineQuery([Active]);\n\n/**\n * Scope filter (field bug 2026-07-17: root wires floated inside a folder).\n * Coordinates are FRAME-LOCAL (design-001 §5.1) — a wire whose endpoint\n * belongs to another nav frame is geometric nonsense in this one. The\n * signature of \"out of scope\" is the canonical non-member state the\n * activeMembership system stamps: Culled ∧ ¬Active. A VIEWPORT-culled member\n * is Culled ∧ Active and must keep drawing (long wires with offscreen\n * endpoints), and bare worlds with no membership system (unit tests,\n * membership-less rigs) carry neither tag and draw everything.\n */\nfunction outOfScope(world: World, e: Entity): boolean {\n return world.hasTag(e, Culled) && !world.hasTag(e, Active);\n}\n\nconst TESSELLATION_TOLERANCE_PX = 0.25;\nconst DASH_PX = 6;\nconst GAP_PX = 4;\n\n/** Effective widget rect: non-zero MeasuredSize over Size (design-004 §2).\n * Exported for the magnet collector (design-010 §4) — ONE rect-reading rule. */\nexport function readWidgetRect(world: World, e: Entity): Rect | undefined {\n const p = world.get(e, Position);\n if (p === undefined) return undefined;\n const measured = world.get(e, MeasuredSize);\n const s = measured !== undefined && measured.w > 0 ? measured : world.get(e, Size);\n if (s === undefined) return undefined;\n return { x: p.x, y: p.y, width: s.w, height: s.h };\n}\n\n/** Per-type slot cache (schemas are immutable; mirrors core ops/port-geometry). */\nconst slotCache = new Map<string, Map<string, PortSlot>>();\nfunction slotOf(wt: WidgetType, portId: string): PortSlot | undefined {\n let slots = slotCache.get(wt.type);\n if (slots === undefined) {\n slots = portSlots(wt.ports);\n slotCache.set(wt.type, slots);\n }\n return slots.get(portId);\n}\n\nfunction endpointAnchor(\n world: World,\n widget: Entity | undefined,\n portId: string,\n): { anchor: Rect; slot: PortSlot } | undefined {\n if (widget === undefined) return undefined;\n const rect = readWidgetRect(world, widget);\n if (rect === undefined) return undefined;\n const type = world.get(widget, PrefabId)?.id;\n if (typeof type !== \"string\") return undefined;\n const wt = widgets.get(type);\n if (wt === undefined) return undefined;\n const slot = slotOf(wt, portId);\n if (slot === undefined) return undefined;\n return { anchor: rect, slot };\n}\n\n/** Map a world cubic's control points to screen (affine ⇒ exact curve map). */\nfunction cubicToScreen(c: Cubic, cam: GroundFrame[\"camera\"]): Cubic {\n const p0 = worldToScreen(c.x0, c.y0, cam);\n const p1 = worldToScreen(c.x1, c.y1, cam);\n const p2 = worldToScreen(c.x2, c.y2, cam);\n const p3 = worldToScreen(c.x3, c.y3, cam);\n return { x0: p0.x, y0: p0.y, x1: p1.x, y1: p1.y, x2: p2.x, y2: p2.y, x3: p3.x, y3: p3.y };\n}\n\n/** Point at arc length `d` via the tessellation's prefix sums (binary search + lerp). */\nfunction pointAtLength(t: Tessellation, d: number): { x: number; y: number } {\n const arc = t.arcLength;\n const n = arc.length;\n let lo = 0;\n let hi = n - 1;\n while (lo < hi) {\n const mid = (lo + hi) >> 1;\n if ((arc[mid] as number) < d) lo = mid + 1;\n else hi = mid;\n }\n const i = Math.max(1, lo);\n const a = arc[i - 1] as number;\n const b = arc[i] as number;\n const f = b > a ? (d - a) / (b - a) : 0;\n const x0 = t.points[(i - 1) * 2] as number;\n const y0 = t.points[(i - 1) * 2 + 1] as number;\n const x1 = t.points[i * 2] as number;\n const y1 = t.points[i * 2 + 1] as number;\n return { x: x0 + (x1 - x0) * f, y: y0 + (y1 - y0) * f };\n}\n\n/** Emit a dashed stroke along the tessellation (straight dash segments — canvas parity at 6px dashes). */\nfunction dashedStroke(soup: SoupBuilder, t: Tessellation, width: number, c: Rgba): void {\n const total = t.arcLength[t.arcLength.length - 1] as number;\n for (let d = 0; d < total; d += DASH_PX + GAP_PX) {\n const a = pointAtLength(t, d);\n const b = pointAtLength(t, Math.min(d + DASH_PX, total));\n soup.segment(a.x, a.y, b.x, b.y, width, c);\n }\n}\n\nexport function collectWires(\n world: World,\n frame: GroundFrame,\n config: WiresConfig = DEFAULT_WIRES_CONFIG,\n preview?: WirePreviewBuffer,\n): TriSoup {\n const soup = new SoupBuilder();\n const cam = frame.camera;\n const wireColor = parseCssColor(config.wireColor);\n const selectedColor = parseCssColor(config.selectedColor);\n\n // Committed wires.\n world.query(wireQ).each((batch) => {\n for (const r of batch) {\n const wire = batch.entity(r);\n const ports = world.get(wire, WirePorts);\n if (ports === undefined) continue;\n const fromWidget = world.getRelation(wire, WireFrom);\n const toWidget = world.getRelation(wire, WireTo);\n // Both endpoints must be IN the current nav frame (scope filter above).\n if (fromWidget !== undefined && outOfScope(world, fromWidget)) continue;\n if (toWidget !== undefined && outOfScope(world, toWidget)) continue;\n const from = endpointAnchor(world, fromWidget, ports.from ?? \"\");\n const to = endpointAnchor(world, toWidget, ports.to ?? \"\");\n if (from === undefined || to === undefined) continue;\n const cubic = wireCubic(\n portAnchor(from.anchor, from.slot),\n from.slot.side,\n portAnchor(to.anchor, to.slot),\n to.slot.side,\n );\n const selected = world.hasTag(wire, Selected);\n const t = tessellateCubic(cubicToScreen(cubic, cam), TESSELLATION_TOLERANCE_PX);\n soup.polyline(t.points, selected ? config.selectedWidth : config.wireWidth, selected ? selectedColor : wireColor);\n }\n });\n\n // Connect-drag preview (world coords in the buffer; horizontal-stub cubic —\n // the old reflector's readable stand-in until the wire commits real sides).\n if (preview?.active === true) {\n const stub = Math.max(24, Math.abs(preview.tx - preview.sx) * 0.5);\n const cubic: Cubic = {\n x0: preview.sx,\n y0: preview.sy,\n x1: preview.sx + stub,\n y1: preview.sy,\n x2: preview.tx - stub,\n y2: preview.ty,\n x3: preview.tx,\n y3: preview.ty,\n };\n const t = tessellateCubic(cubicToScreen(cubic, cam), TESSELLATION_TOLERANCE_PX);\n if (preview.compatible) soup.polyline(t.points, config.wireWidth, selectedColor);\n else dashedStroke(soup, t, config.wireWidth, wireColor);\n }\n\n // Materialized port dots.\n const connecting = world.firstOf(routedConnectQ) !== undefined;\n const dotColor = parseCssColor(connecting ? config.portActiveColor : config.portColor);\n world.query(portQ).each((batch) => {\n const ax = batch.col(PortAnchor).x;\n const ay = batch.col(PortAnchor).y;\n for (const r of batch) {\n const s = worldToScreen(ax[r] as number, ay[r] as number, cam);\n soup.disc(s.x, s.y, config.portRadius, dotColor);\n }\n });\n\n return soup.build();\n}\n","/**\n * Magnet-grid collector — the pure ECS→packed-sources half of the magnet pass\n * (design-010 §4; the `*-collect.ts` convention: imports ONLY core/kernel so\n * it unit-tests under happy-dom with no GPU and no three import).\n *\n * Ported from vibe-field draft/magnet-grid `main.js` (latticeWindow,\n * packCards) with the design-010 upgrades the experiment lacked:\n * - rbush broad-phase over the ONE spatial index instead of an all-cards\n * walk (D2 — document size becomes irrelevant by construction);\n * - N poles from injected sources, packed as DEGENERATE rounded boxes\n * (half = 0, r = 0 — reduces exactly to the point-charge formula, D3);\n * - `maxSources` prioritization (largest screen area, then nearest to the\n * viewport center; poles pack first and are never evicted);\n * - `fadeZoom` — the field quiets below a zoom threshold (scale 0 skips the\n * spatial query entirely: the cheap valve is also the right look).\n */\nimport {\n DEFAULT_GRID_MAGNET_CONFIG,\n type Entity,\n type GridConfig,\n type GridMagnetConfig,\n type World,\n} from \"@ice/core\";\nimport { worldToScreen, type AABB, type SpatialEntry } from \"@ice/kernel\";\nimport type { GroundFrame } from \"../pass\";\nimport type { Pole } from \"../poles\";\nimport { readWidgetRect } from \"./wires-collect\";\n\n/** Floats per packed source: [cx, cy, hx, hy] + [r, strength, 0, 0] (screen px). */\nexport const MAGNET_SOURCE_FLOATS = 8;\n/** Source-buffer capacity — the scratch array and GPU buffer are sized to this. */\nexport const MAX_MAGNET_SOURCES = 256;\n/** Per-level instance guard (vibe-field main.js:621 — a level beyond it draws nothing). */\nexport const MAX_MAGNET_INSTANCES = 220_000;\n\n/** The broad-phase reader over the shared spatial index (ctx seam, design-010 §3.2). */\nexport type ReadSpatial = (bounds: AABB) => readonly SpatialEntry<Entity>[];\n\n/** Resolve the partial config block over the defaults — the ONE resolution point. */\nexport function resolveMagnet(cfg: GridConfig): GridMagnetConfig {\n return { ...DEFAULT_GRID_MAGNET_CONFIG, ...cfg.magnet };\n}\n\n/** Closed-form fade ladder (grid.ts:72-74 re-expressed in JS for level skip). */\nexport function fadeOpacity(\n cssSpacing: number,\n fadeIn: readonly [number, number],\n fadeOut: readonly [number, number],\n): number {\n const rise = (cssSpacing - fadeIn[0]) / Math.max(fadeIn[1] - fadeIn[0], 0.0001);\n const fall = 1 - (cssSpacing - fadeOut[0]) / Math.max(fadeOut[1] - fadeOut[0], 0.0001);\n return Math.min(Math.max(Math.min(rise, fall), 0), 1);\n}\n\n/**\n * The field zoom valve: 1 at `zoom ≥ fadeZoom`, lerping to 0 across\n * [0.7·fadeZoom, fadeZoom]. 0 disables the valve entirely.\n */\nexport function magnetFieldScale(zoom: number, fadeZoom: number): number {\n if (fadeZoom <= 0) return 1;\n const t = (zoom - 0.7 * fadeZoom) / (0.3 * fadeZoom);\n return Math.min(Math.max(t, 0), 1);\n}\n\n/** One lattice level's visible window + fade (vibe-field main.js:81-91 port). */\nexport interface MagnetLevel {\n /** Integer lattice coords of the window origin. */\n readonly i0: number;\n readonly j0: number;\n readonly cols: number;\n readonly rows: number;\n /** Instances to draw; 0 = level skipped (faded out or over the guard). */\n readonly count: number;\n /** Fade-ladder opacity × level weight (CPU-baked; the shader gets one alpha). */\n readonly alpha: number;\n /**\n * Coincidence skip (design-010 §5.4): when the NEXT level up is visible and\n * its spacing is an integer multiple m of this one, sites whose absolute\n * lattice index is ≡ 0 (mod m) on both axes drop out — replicating the\n * classic shader's max-composite look. 0 = no skip.\n */\n readonly skipModulo: number;\n}\n\nexport function collectMagnetLevels(frame: GroundFrame, cfg: GridConfig): MagnetLevel[] {\n const { camera } = frame;\n const out: MagnetLevel[] = [];\n const opacities = cfg.spacings.map((s) => fadeOpacity(s * camera.zoom, cfg.fadeIn, cfg.fadeOut));\n for (let i = 0; i < cfg.spacings.length; i++) {\n const spacing = cfg.spacings[i] as number;\n const opacity = opacities[i] as number;\n const weight = cfg.levelWeight[0] + i * cfg.levelWeight[1];\n const alpha = opacity * weight * cfg.dotAlpha;\n if (opacity < 0.01 || alpha <= 0) {\n out.push({ i0: 0, j0: 0, cols: 0, rows: 0, count: 0, alpha: 0, skipModulo: 0 });\n continue;\n }\n const worldW = frame.width / camera.zoom;\n const worldH = frame.height / camera.zoom;\n const i0 = Math.floor(camera.x / spacing) - 1;\n const j0 = Math.floor(camera.y / spacing) - 1;\n const i1 = Math.ceil((camera.x + worldW) / spacing) + 1;\n const j1 = Math.ceil((camera.y + worldH) / spacing) + 1;\n const cols = Math.max(1, i1 - i0);\n const rows = Math.max(1, j1 - j0);\n const count = cols * rows;\n if (count > MAX_MAGNET_INSTANCES) {\n out.push({ i0: 0, j0: 0, cols: 0, rows: 0, count: 0, alpha: 0, skipModulo: 0 });\n continue;\n }\n let skipModulo = 0;\n const next = cfg.spacings[i + 1];\n if (next !== undefined && (opacities[i + 1] as number) >= 0.01) {\n const ratio = next / spacing;\n if (Number.isInteger(ratio) && ratio > 1) skipModulo = ratio;\n }\n out.push({ i0, j0, cols, rows, count, alpha, skipModulo });\n }\n return out;\n}\n\ninterface WidgetCandidate {\n cx: number;\n cy: number;\n hx: number;\n hy: number;\n r: number;\n area: number;\n centerDist: number;\n}\n\n/**\n * Pack field sources into `out` (stride {@link MAGNET_SOURCE_FLOATS}, screen\n * CSS px). Returns the packed count. `fieldScale` multiplies every strength\n * (the zoom valve); 0 short-circuits to an empty buffer — no spatial query.\n */\nexport function collectMagnetSources(\n world: World,\n frame: GroundFrame,\n magnet: GridMagnetConfig,\n fieldScale: number,\n poles: readonly Pole[],\n readSpatial: ReadSpatial | undefined,\n out: Float32Array,\n): number {\n if (fieldScale <= 0) return 0;\n const { camera } = frame;\n const cap = Math.min(magnet.maxSources, MAX_MAGNET_SOURCES, Math.floor(out.length / MAGNET_SOURCE_FLOATS));\n let n = 0;\n\n // Poles first — never evicted by widgets (design-010 §4).\n for (const pole of poles) {\n if (n >= cap) break;\n if (!(pole.strength > 0)) continue;\n const s = pole.space === \"screen\" ? pole : worldToScreen(pole.x, pole.y, camera);\n const o = n * MAGNET_SOURCE_FLOATS;\n out[o + 0] = s.x;\n out[o + 1] = s.y;\n out[o + 2] = 0;\n out[o + 3] = 0;\n out[o + 4] = 0;\n out[o + 5] = pole.strength * fieldScale;\n out[o + 6] = 0;\n out[o + 7] = 0;\n n++;\n }\n\n if (!magnet.widgets || readSpatial === undefined || magnet.widgetStrength <= 0 || n >= cap) {\n return n;\n }\n\n // Broad-phase: viewport ∪ influence halo. The shader's reject cutoff is\n // pad = √(k/0.02) = 5·reach CSS px (influence 0.02 ≈ invisible), scaled by\n // per-source √strength — query with the strength-scaled halo so nothing the\n // shader could show is culled here.\n const haloCss = 5 * magnet.reach * Math.sqrt(Math.max(magnet.widgetStrength * fieldScale, 0.0001));\n const pad = haloCss / camera.zoom;\n const hits = readSpatial({\n minX: camera.x - pad,\n minY: camera.y - pad,\n maxX: camera.x + frame.width / camera.zoom + pad,\n maxY: camera.y + frame.height / camera.zoom + pad,\n });\n\n const viewCx = frame.width / 2;\n const viewCy = frame.height / 2;\n const candidates: WidgetCandidate[] = [];\n for (const hit of hits) {\n // The index also carries wires/ports (they share it) — the rect reader is\n // the widget filter: Position + non-zero MeasuredSize|Size only.\n const rect = readWidgetRect(world, hit.id);\n if (rect === undefined || rect.width <= 0 || rect.height <= 0) continue;\n const hx = (rect.width / 2) * camera.zoom;\n const hy = (rect.height / 2) * camera.zoom;\n const center = worldToScreen(rect.x + rect.width / 2, rect.y + rect.height / 2, camera);\n candidates.push({\n cx: center.x,\n cy: center.y,\n hx,\n hy,\n r: Math.min(magnet.widgetRadius * camera.zoom, hx, hy),\n area: hx * hy,\n centerDist: (center.x - viewCx) ** 2 + (center.y - viewCy) ** 2,\n });\n }\n\n const budget = cap - n;\n if (candidates.length > budget) {\n candidates.sort((a, b) => b.area - a.area || a.centerDist - b.centerDist);\n candidates.length = budget;\n }\n\n const strength = magnet.widgetStrength * fieldScale;\n for (const c of candidates) {\n const o = n * MAGNET_SOURCE_FLOATS;\n out[o + 0] = c.cx;\n out[o + 1] = c.cy;\n out[o + 2] = c.hx;\n out[o + 3] = c.hy;\n out[o + 4] = c.r;\n out[o + 5] = strength;\n out[o + 6] = 0;\n out[o + 7] = 0;\n n++;\n }\n return n;\n}\n","/**\n * Snap-guides collector — the pure ECS→triangles half of the guides pass\n * (v1 SnapGuideRenderer look, carried over from the 2D-canvas reflector it\n * replaces): full-viewport magenta alignment lines (`GuideLine.from == to` ⇒\n * full span — design-003 §6), bounded spans, and equal-spacing bars with 4px\n * end ticks. Screen-px output via the kernel `worldToScreen` seam. NO guide\n * count caps (the pool grows; so does the soup).\n */\nimport {\n DEFAULT_SNAP_GUIDES_CONFIG,\n GuideLine,\n SpacingBar,\n defineQuery,\n type SnapGuidesConfig,\n type World,\n} from \"@ice/core\";\nimport { worldToScreen } from \"@ice/kernel\";\nimport type { GroundFrame } from \"../pass\";\nimport { SoupBuilder, type Rgba, type TriSoup } from \"./soup-collect\";\n\nexport const guideQ = defineQuery([GuideLine]);\nexport const barQ = defineQuery([SpacingBar]);\n\nexport function collectGuides(\n world: World,\n frame: GroundFrame,\n config: SnapGuidesConfig = DEFAULT_SNAP_GUIDES_CONFIG,\n): TriSoup {\n const soup = new SoupBuilder();\n const cam = frame.camera;\n const lw = config.lineWidth;\n const guideColor: Rgba = [config.color[0], config.color[1], config.color[2], config.guideAlpha];\n const barColor: Rgba = [config.color[0], config.color[1], config.color[2], config.spacingAlpha];\n\n world.query(guideQ).each((b) => {\n for (const r of b) {\n const g = world.read(b.entity(r), GuideLine);\n const fullSpan = g.from === g.to;\n if (g.axis === \"x\") {\n const sx = worldToScreen(g.at, 0, cam).x;\n if (frame.width > 0 && (sx < -1 || sx > frame.width + 1)) continue;\n const y0 = fullSpan ? 0 : worldToScreen(0, g.from, cam).y;\n const y1 = fullSpan ? frame.height : worldToScreen(0, g.to, cam).y;\n soup.rect(sx - lw / 2, Math.min(y0, y1), lw, Math.abs(y1 - y0), guideColor);\n } else {\n const sy = worldToScreen(0, g.at, cam).y;\n if (frame.height > 0 && (sy < -1 || sy > frame.height + 1)) continue;\n const x0 = fullSpan ? 0 : worldToScreen(g.from, 0, cam).x;\n const x1 = fullSpan ? frame.width : worldToScreen(g.to, 0, cam).x;\n soup.rect(Math.min(x0, x1), sy - lw / 2, Math.abs(x1 - x0), lw, guideColor);\n }\n }\n });\n\n world.query(barQ).each((b) => {\n for (const r of b) {\n const s = world.read(b.entity(r), SpacingBar);\n const t = config.tickPx;\n if (s.axis === \"x\") {\n // Horizontal gap along x at world-y perp (kernel/v1 axis semantics).\n const a = worldToScreen(s.from, s.perp, cam);\n const bp = worldToScreen(s.to, s.perp, cam);\n if (frame.width > 0 && (Math.max(a.x, bp.x) < 0 || Math.min(a.x, bp.x) > frame.width)) continue;\n soup.rect(Math.min(a.x, bp.x), a.y - lw / 2, Math.abs(bp.x - a.x), lw, barColor);\n soup.rect(a.x - lw / 2, a.y - t, lw, t * 2, barColor);\n soup.rect(bp.x - lw / 2, bp.y - t, lw, t * 2, barColor);\n } else {\n const a = worldToScreen(s.perp, s.from, cam);\n const bp = worldToScreen(s.perp, s.to, cam);\n if (frame.height > 0 && (Math.max(a.y, bp.y) < 0 || Math.min(a.y, bp.y) > frame.height)) continue;\n soup.rect(a.x - lw / 2, Math.min(a.y, bp.y), lw, Math.abs(bp.y - a.y), barColor);\n soup.rect(a.x - t, a.y - lw / 2, t * 2, lw, barColor);\n soup.rect(bp.x - t, bp.y - lw / 2, t * 2, lw, barColor);\n }\n }\n });\n\n return soup.build();\n}\n","/**\n * The three-side half of a triangle-soup pass: a Mesh over a dynamic\n * BufferGeometry (position xyz + color rgba) with an unlit TSL material whose\n * fragment IS the vertex color. Capacity grows geometrically; shrink keeps the\n * buffer and narrows the draw range (guide/wire counts oscillate per frame —\n * reallocating every collect would churn).\n */\nimport { attribute } from \"three/tsl\";\nimport { BufferAttribute, BufferGeometry, DoubleSide, Mesh, MeshBasicNodeMaterial } from \"three/webgpu\";\nimport type { TriSoup } from \"./soup-collect\";\n\nexport interface SoupMesh {\n readonly mesh: Mesh;\n update(soup: TriSoup): void;\n dispose(): void;\n}\n\nexport function createSoupMesh(renderOrder: number): SoupMesh {\n const material = new MeshBasicNodeMaterial();\n material.fragmentNode = attribute(\"color\", \"vec4\");\n material.transparent = true;\n material.depthTest = false;\n material.depthWrite = false;\n // Screen-px collectors emit y-down geometry, which lands CLOCKWISE in NDC\n // through the top=0/bottom=h ortho camera — front-face culling would drop\n // every triangle (the invisible-guides field find, 2026-07-16).\n material.side = DoubleSide;\n\n let geometry = new BufferGeometry();\n let capacity = 0;\n const mesh = new Mesh(geometry, material);\n mesh.frustumCulled = false;\n mesh.renderOrder = renderOrder;\n mesh.visible = false; // until the first non-empty soup\n\n return {\n mesh,\n update(soup) {\n if (soup.vertexCount === 0) {\n mesh.visible = false;\n geometry.setDrawRange(0, 0);\n return;\n }\n if (soup.vertexCount > capacity) {\n capacity = Math.max(soup.vertexCount, capacity * 2, 256);\n const old = geometry;\n geometry = new BufferGeometry();\n const pos = new Float32Array(capacity * 3);\n const col = new Float32Array(capacity * 4);\n pos.set(soup.positions);\n col.set(soup.colors);\n geometry.setAttribute(\"position\", new BufferAttribute(pos, 3));\n geometry.setAttribute(\"color\", new BufferAttribute(col, 4));\n mesh.geometry = geometry;\n old.dispose();\n } else {\n const pos = geometry.getAttribute(\"position\") as BufferAttribute;\n const col = geometry.getAttribute(\"color\") as BufferAttribute;\n (pos.array as Float32Array).set(soup.positions);\n (col.array as Float32Array).set(soup.colors);\n pos.needsUpdate = true;\n col.needsUpdate = true;\n }\n geometry.setDrawRange(0, soup.vertexCount);\n mesh.visible = true;\n },\n dispose() {\n geometry.dispose();\n material.dispose();\n },\n };\n}\n","/**\n * Snap-guides pass — the three-side wrapper over the pure `collectGuides`\n * (renders ABOVE grid and wires within the ground canvas, matching the old\n * P0 stacking order).\n */\nimport { GuideLine, SpacingBar, type World } from \"@ice/core\";\nimport { DEFAULT_SNAP_GUIDES_CONFIG, type SnapGuidesConfig } from \"@ice/core\";\nimport type { GroundFrame, GroundPass } from \"../pass\";\nimport { barQ, collectGuides, guideQ } from \"./guides-collect\";\nimport { createSoupMesh } from \"./soup-mesh\";\n\nexport function createGuidesPass(initial: Partial<SnapGuidesConfig> = {}): GroundPass {\n const config: SnapGuidesConfig = { ...DEFAULT_SNAP_GUIDES_CONFIG, ...initial };\n const soup = createSoupMesh(2);\n\n return {\n name: \"snap-guides\",\n object: soup.mesh,\n arm(world: World, wake: () => void) {\n return [\n world.reactive.observeQuery(guideQ, wake, { cols: [GuideLine] }),\n world.reactive.observeQuery(barQ, wake, { cols: [SpacingBar] }),\n ];\n },\n collect(world: World, frame: GroundFrame) {\n soup.update(collectGuides(world, frame, config));\n },\n dispose() {\n soup.dispose();\n },\n };\n}\n","/**\n * Wires pass — the three-side wrapper over the pure `collectWires` (renders\n * above the grid, below the guides, matching the old P0 canvas order).\n * Dirt mirrors the old 2D reflector's observers; the connect preview rides\n * `[RoutedConnect, Drag]` value dirt (the buffer updates exactly when the\n * connect recognizer's Drag advances) instead of a per-frame value diff.\n */\nimport {\n DEFAULT_WIRES_CONFIG,\n Drag,\n MeasuredSize,\n PortAnchor,\n Position,\n Size,\n type WirePreviewBuffer,\n type WiresConfig,\n type World,\n} from \"@ice/core\";\nimport type { GroundFrame, GroundPass } from \"../pass\";\nimport { createSoupMesh } from \"./soup-mesh\";\nimport {\n activeQ,\n collectWires,\n connectDragQ,\n geometryQ,\n measuredQ,\n portQ,\n routedConnectQ,\n selectedQ,\n wireQ,\n} from \"./wires-collect\";\n\nexport function createWiresPass(\n initial: Partial<WiresConfig> = {},\n readPreview?: () => WirePreviewBuffer,\n): GroundPass {\n const config: WiresConfig = { ...DEFAULT_WIRES_CONFIG, ...initial };\n const soup = createSoupMesh(1);\n\n return {\n name: \"wires\",\n object: soup.mesh,\n arm(world: World, wake: () => void) {\n return [\n world.reactive.observeQuery(wireQ, wake, { cols: [] }),\n world.reactive.observeQuery(geometryQ, wake, { cols: [Position, Size] }),\n // MeasuredSize rides its own observer (readRect prefers it over Size):\n // in geometryQ's cols it would REQUIRE the rider and drop plain widgets.\n world.reactive.observeQuery(measuredQ, wake, { cols: [MeasuredSize] }),\n world.reactive.observeQuery(selectedQ, wake, { cols: [] }),\n // Nav churn: Active membership flips gate the scope filter (a wire\n // whose endpoints left the current frame must disappear this frame).\n world.reactive.observeQuery(activeQ, wake, { cols: [] }),\n world.reactive.observeQuery(portQ, wake, { cols: [PortAnchor] }),\n world.reactive.observeQuery(routedConnectQ, wake, { cols: [] }),\n world.reactive.observeQuery(connectDragQ, wake, { cols: [Drag] }),\n ];\n },\n collect(world: World, frame: GroundFrame) {\n soup.update(collectWires(world, frame, config, readPreview?.()));\n },\n dispose() {\n soup.dispose();\n },\n };\n}\n","/**\n * WebGPU renderer bootstrap for the ground layer.\n *\n * WebGPU-first (James, 2026-07-16): three's `WebGPURenderer` picks the WebGPU\n * backend when `navigator.gpu` exists and falls back to WebGL2 otherwise —\n * one code path, TSL compiles to WGSL or GLSL per backend. Init is ASYNC\n * (`renderer.init()`), but the reflector flush is synchronous: `ready()`\n * gates drawing, the layer keeps its dirty flags armed, and the first flush\n * after resolution paints (the rAF loop retries every frame — no extra wake\n * plumbing). Any construction/init failure (happy-dom, device loss, no\n * WebGL2 either) degrades to `failed()` — the layer reports available() =\n * false and never throws (grid.ts fault-isolation contract, design-002 §5).\n */\nimport { WebGPURenderer } from \"three/webgpu\";\nimport type { Camera, Scene } from \"three/webgpu\";\n\n/** The layer's renderer seam — tests inject a fake (compositor `GlLike` precedent). */\nexport interface GroundRendererLike {\n readonly canvas: HTMLCanvasElement;\n ready(): boolean;\n failed(): boolean;\n /** Register a one-shot \"became ready\" callback (fires immediately if already ready). */\n onReady(cb: () => void): void;\n setSize(cssW: number, cssH: number, dpr: number): void;\n render(scene: Scene, camera: Camera): void;\n dispose(): void;\n}\n\nexport function createGroundRenderer(\n doc: Document,\n opts: { forceWebGL?: boolean } = {},\n): GroundRendererLike {\n const canvas = doc.createElement(\"canvas\");\n let renderer: WebGPURenderer | null = null;\n let isReady = false;\n let isFailed = false;\n const readyCbs: Array<() => void> = [];\n\n // Probe BEFORE constructing: with neither WebGPU nor WebGL2 (happy-dom,\n // ancient browsers), three's WebGL2 fallback dies inside an internal\n // un-awaited promise — an unhandled rejection our init().catch never sees\n // (widgetlab app-mount test, 2026-07-16). The WebGL2 probe uses a SCRATCH\n // canvas: getContext('webgl2') on the real one would lock it out of a\n // 'webgpu' context (contexts are exclusive per canvas).\n const gpu = (globalThis.navigator as { gpu?: unknown } | undefined)?.gpu;\n if (gpu == null || opts.forceWebGL === true) {\n let gl2: unknown = null;\n try {\n gl2 = doc.createElement(\"canvas\").getContext(\"webgl2\");\n } catch {\n gl2 = null;\n }\n if (gl2 === null) isFailed = true;\n }\n\n if (!isFailed) {\n try {\n renderer = new WebGPURenderer({\n canvas: canvas as unknown as HTMLCanvasElement,\n alpha: true, // transparent clear — the page background shows through P0\n antialias: true,\n ...(opts.forceWebGL === true ? { forceWebGL: true } : {}),\n });\n renderer\n .init()\n .then(() => {\n isReady = true;\n for (const cb of readyCbs.splice(0)) cb();\n })\n .catch(() => {\n isFailed = true; // device loss mid-init\n });\n } catch {\n isFailed = true; // constructor threw\n }\n }\n\n let lastW = 0;\n let lastH = 0;\n let lastDpr = 0;\n\n return {\n canvas,\n ready: () => isReady,\n failed: () => isFailed,\n onReady(cb) {\n if (isReady) cb();\n else readyCbs.push(cb);\n },\n setSize(cssW, cssH, dpr) {\n if (renderer === null || (cssW === lastW && cssH === lastH && dpr === lastDpr)) return;\n lastW = cssW;\n lastH = cssH;\n lastDpr = dpr;\n try {\n renderer.setPixelRatio(dpr);\n // false: the layer owns the canvas CSS size (100% inset-0)\n renderer.setSize(Math.max(1, cssW), Math.max(1, cssH), false);\n } catch {\n isFailed = true;\n }\n },\n render(scene, camera) {\n if (renderer === null || !isReady || isFailed) return;\n try {\n renderer.render(scene, camera);\n } catch {\n isFailed = true; // device loss ⇒ silent no-op forever, never a throwing reflector\n }\n },\n dispose() {\n try {\n renderer?.dispose();\n } catch {\n /* already lost */\n }\n renderer = null;\n },\n };\n}\n","/**\n * Magnet pole sources (design-010 §3.3, decision D5): the grid pass is\n * CURSOR-AGNOSTIC — point field sources enter through this injected protocol,\n * never through pass-known vocabulary. No source wired ⇒ no subscription, no\n * reads, widget-only field. The canned helpers below are where any cursor\n * dependency lives; the pass imports NEITHER — apps compose what fits\n * (vibe-field wraps its own `Cur` halo the same way, in its own repo).\n */\nimport {\n CursorVisual,\n defineQuery,\n LocalPointer,\n Pointer,\n PointerWorld,\n Position,\n type World,\n} from \"@ice/core\";\n\n/**\n * One point field source. Packed as a degenerate rounded-box SDF (half = 0,\n * r = 0), which reduces exactly to the point-charge formula (design-010 D3).\n * `space` defaults to \"world\"; \"screen\" is CSS px — zero-conversion for\n * screen-space cursors (field evaluation is screen-space anyway).\n */\nexport interface Pole {\n readonly x: number;\n readonly y: number;\n /** Relative field strength; ≤ 0 poles are skipped at pack time. */\n readonly strength: number;\n readonly space?: \"world\" | \"screen\";\n}\n\nexport interface PoleSource {\n /** Called during collect — read-only world access (GroundPass.collect rules). */\n read(world: World): readonly Pole[];\n /**\n * Called during arm — `wake` marks the grid pass dirty (the pass gates it on\n * `magnet.enabled`, so idle scenes stay at zero frames). Returns unsubscriber.\n */\n subscribe(world: World, wake: () => void): () => void;\n}\n\nconst localPointerQ = defineQuery([Pointer, PointerWorld, LocalPointer]);\n\n/**\n * Poles from the local pointer entity (`LocalPointer` + `PointerWorld`) — the\n * raw-cursor wiring for apps without their own cursor visual. World-space; one\n * pole per local pointer (multi-touch yields one per finger while pressed).\n */\nexport function localPointerPoles(opts: { readonly strength?: number } = {}): PoleSource {\n const strength = opts.strength ?? 1;\n return {\n read(world) {\n const out: Pole[] = [];\n world.query(localPointerQ).each((b) => {\n for (const r of b) {\n const p = world.read(b.entity(r), PointerWorld);\n out.push({ x: p.x, y: p.y, strength, space: \"world\" });\n }\n });\n return out;\n },\n subscribe(world, wake) {\n return world.reactive.observeQuery(localPointerQ, wake, { cols: [PointerWorld] });\n },\n };\n}\n\nconst cursorVisualQ = defineQuery([Position, CursorVisual]);\n\n/**\n * Poles from cursor-visual entities (`Position` + `CursorVisual`) — presence\n * apps: remote collaborators' pooled cursors (core `remote-cursors.ts`) drive\n * the field. This helper is where the CursorVisual dependency lives (D5).\n */\nexport function cursorVisualPoles(opts: { readonly strength?: number } = {}): PoleSource {\n const strength = opts.strength ?? 1;\n return {\n read(world) {\n const out: Pole[] = [];\n world.query(cursorVisualQ).each((b) => {\n for (const r of b) {\n const p = world.read(b.entity(r), Position);\n out.push({ x: p.x, y: p.y, strength, space: \"world\" });\n }\n });\n return out;\n },\n subscribe(world, wake) {\n return world.reactive.observeQuery(cursorVisualQ, wake, { cols: [Position] });\n },\n };\n}\n","/**\n * @ice/ground — the P0 ground stratum as ONE WebGPU canvas (design-004 §1\n * as-built amendment, 2026-07-16). three's WebGPURenderer + TSL, WebGL2\n * fallback automatic. Off the react chain: react receives the layer as an\n * OPAQUE factory (`<InfiniteCanvas ground={ground(...)}>`); imperative apps\n * register `layer.reflector` themselves. Passes: dot grid, wires, snap\n * guides — future ground shaders/effects join the same pass registry.\n * (Selection chrome moved OFF the ground 2026-07-17: rings live with the\n * cards, the multi-select union box is P4 dom chrome — always on top.)\n */\nimport type { GridConfig, SnapGuidesConfig, WirePreviewBuffer, WiresConfig, World } from \"@ice/core\";\nimport { createLayer, type GroundLayerHost, type GroundReflector } from \"./layer\";\nimport type { GroundPass } from \"./pass\";\nimport { createGridPass } from \"./passes/grid\";\nimport { createGuidesPass } from \"./passes/guides\";\nimport type { ReadSpatial } from \"./passes/magnet-collect\";\nimport { createWiresPass } from \"./passes/wires\";\nimport type { PoleSource } from \"./poles\";\nimport { createGroundRenderer, type GroundRendererLike } from \"./renderer\";\n\nexport type { GroundFrame, GroundPass } from \"./pass\";\nexport type { GroundReflector } from \"./layer\";\nexport type { GroundRendererLike } from \"./renderer\";\nexport { SoupBuilder, parseCssColor, type Rgba, type TriSoup } from \"./passes/soup-collect\";\nexport { collectGuides } from \"./passes/guides-collect\";\nexport { collectWires } from \"./passes/wires-collect\";\n// The magnet pole seam (design-010 §3.3) + canned wirings (D5: the pass\n// imports neither — the cursor dependency lives in the helper the app chose).\nexport { cursorVisualPoles, localPointerPoles, type Pole, type PoleSource } from \"./poles\";\nexport {\n collectMagnetLevels,\n collectMagnetSources,\n magnetFieldScale,\n resolveMagnet,\n MAX_MAGNET_SOURCES,\n type MagnetLevel,\n type ReadSpatial,\n} from \"./passes/magnet-collect\";\n// Config vocabulary re-exported for app ergonomics (canonical home: @ice/core).\nexport {\n DEFAULT_GRID_CONFIG,\n DEFAULT_GRID_MAGNET_CONFIG,\n DEFAULT_SNAP_GUIDES_CONFIG,\n DEFAULT_WIRES_CONFIG,\n type GridConfig,\n type GridMagnetConfig,\n type SnapGuidesConfig,\n type WiresConfig,\n} from \"@ice/core\";\n\nexport interface GroundContext {\n readonly host: GroundLayerHost;\n readonly world: World;\n /** Connect-drag preview reader (graph boards); omit on boards without wires. */\n readonly readWirePreview?: () => WirePreviewBuffer;\n /**\n * Broad-phase reader over the ONE spatial index (design-010 §3.2, the\n * readWirePreview precedent) — the magnet grid's widget sources. Facades\n * wire `stack.index.search`; omit ⇒ magnet renders a pole-only field.\n */\n readonly readSpatial?: ReadSpatial;\n}\n\nexport interface GroundLayer {\n readonly reflector: GroundReflector;\n /** Live grid re-tune (the react `grid` prop forwards here). */\n configureGrid(cfg: Partial<GridConfig>): void;\n dispose(): void;\n}\n\nexport interface GroundOptions {\n readonly grid?: Partial<GridConfig>;\n readonly wires?: Partial<WiresConfig>;\n readonly guides?: Partial<SnapGuidesConfig>;\n /**\n * Magnet pole sources (design-010 §3.3) — live app-authored objects, so they\n * live HERE, not in the plain-data GridConfig. Nothing wired ⇒ the magnet\n * field (if enabled) is widget-only; with magnet off they cost one gated\n * no-op subscription each.\n */\n readonly poles?: PoleSource | readonly PoleSource[];\n /** Extra app passes, rendered after the built-ins (renderOrder ≥ 3 is yours). */\n readonly passes?: readonly GroundPass[];\n /** Force the WebGL2 backend (debug / e2e A-B runs). */\n readonly forceWebGL?: boolean;\n /** TEST seam: inject a fake renderer (headless orchestration tests). */\n readonly rendererOverride?: GroundRendererLike;\n}\n\nexport type GroundFactory = (ctx: GroundContext) => GroundLayer;\n\n/**\n * Build the ground layer factory. Usage:\n * react apps: <InfiniteCanvas ground={ground({ grid: {...} })} …>\n * imperative apps: const layer = ground()( { host, world, readWirePreview } );\n * engine.registerReflector(layer.reflector);\n */\nexport function ground(opts: GroundOptions = {}): GroundFactory {\n return (ctx) => {\n const doc = ctx.host.container.ownerDocument;\n const renderer = opts.rendererOverride ?? createGroundRenderer(doc, { forceWebGL: opts.forceWebGL === true });\n const poles = opts.poles === undefined ? [] : Array.isArray(opts.poles) ? opts.poles : [opts.poles];\n const grid = createGridPass(opts.grid ?? {}, { poles, ...(ctx.readSpatial !== undefined ? { readSpatial: ctx.readSpatial } : {}) });\n const wires = createWiresPass(opts.wires ?? {}, ctx.readWirePreview);\n const guides = createGuidesPass(opts.guides ?? {});\n const passes: GroundPass[] = [grid, wires, guides, ...(opts.passes ?? [])];\n const layer = createLayer(ctx.host, ctx.world, renderer, passes);\n return {\n reflector: layer.reflector,\n configureGrid(cfg) {\n grid.configure(cfg);\n layer.invalidateAll();\n },\n dispose: layer.dispose,\n };\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqBA,SAAS,oBAAoB,aAAa;AAuBnC,SAAS,YACd,MACA,OACA,UACA,QACsB;AACtB,QAAM,MAAM,KAAK,UAAU;AAC3B,QAAM,SAAS,SAAS;AACxB,SAAO,MAAM,WAAW;AACxB,SAAO,MAAM,OAAO;AACpB,SAAO,MAAM,MAAM;AACnB,SAAO,MAAM,QAAQ;AACrB,SAAO,MAAM,SAAS;AACtB,SAAO,MAAM,UAAU;AAEvB,SAAO,MAAM,gBAAgB;AAE7B,OAAK,UAAU,aAAa,QAAQ,KAAK,YAAY;AAErD,QAAM,QAAQ,IAAI,MAAM;AAExB,QAAM,SAAS,IAAI,mBAAmB,GAAG,GAAG,GAAG,GAAG,MAAO,GAAI;AAC7D,aAAW,QAAQ,OAAQ,OAAM,IAAI,KAAK,MAAM;AAGhD,QAAM,QAAQ,oBAAI,IAAyB;AAC3C,aAAW,QAAQ,OAAQ,OAAM,IAAI,MAAM,IAAI;AAC/C,MAAI,WAAW;AACf,QAAM,UAAU,MAAY;AAC1B,eAAW,QAAQ,OAAQ,OAAM,IAAI,MAAM,IAAI;AAC/C,eAAW;AAAA,EACb;AACA,QAAM,SAA4B;AAAA;AAAA,IAEhC,MAAM,SAAS,gBAAgB,QAAQ,OAAO;AAAA,EAChD;AACA,aAAW,QAAQ,QAAQ;AACzB,WAAO;AAAA,MACL,GAAG,KAAK,IAAI,OAAO,MAAM;AACvB,cAAM,IAAI,MAAM,IAAI;AACpB,mBAAW;AAAA,MACb,CAAC;AAAA,IACH;AAAA,EACF;AACA,WAAS,QAAQ,OAAO;AAGxB,MAAI,OAAO;AACX,MAAI,OAAO;AACX,MAAI,MAAM;AACV,QAAM,YAAY,CAAC,GAAW,MAAoB;AAChD,UAAM,IAAI,aAAa,oBAAoB;AAC3C,WAAO;AACP,WAAO;AACP,aAAS,QAAQ,GAAG,GAAG,GAAG;AAC1B,WAAO,OAAO;AACd,WAAO,QAAQ,KAAK,IAAI,GAAG,CAAC;AAC5B,WAAO,MAAM;AACb,WAAO,SAAS,KAAK,IAAI,GAAG,CAAC;AAC7B,WAAO,uBAAuB;AAC9B,YAAQ;AAAA,EACV;AACA,QAAM,cAAc,KAAK,UAAU,sBAAsB;AACzD,YAAU,YAAY,OAAO,YAAY,MAAM;AAC/C,MAAI,KAA4B;AAChC,MAAI;AACF,SAAK,IAAI,eAAe,CAAC,YAAY;AACnC,YAAM,QAAQ,QAAQ,CAAC;AACvB,UAAI,UAAU,OAAW;AACzB,gBAAU,MAAM,YAAY,OAAO,MAAM,YAAY,MAAM;AAAA,IAC7D,CAAC;AACD,OAAG,QAAQ,KAAK,SAAS;AAAA,EAC3B,QAAQ;AACN,SAAK;AAAA,EACP;AAEA,MAAI,UAAU;AAEd,QAAM,YAA6B;AAAA,IACjC,MAAM;AAAA;AAAA;AAAA,IAGN,QAAQ;AAAA,IACR,MAAM,GAAU;AACd,UAAI,CAAC,YAAY,SAAS,OAAO,EAAG;AACpC,UAAI,CAAC,SAAS,MAAM,EAAG;AACvB,YAAM,MAAM,EAAE,YAAY,MAAM;AAChC,UAAI,QAAQ,OAAW;AACvB,iBAAW;AACX,YAAM,QAAqB,EAAE,OAAO,MAAM,QAAQ,MAAM,KAAK,QAAQ,IAAI;AACzE,iBAAW,QAAQ,QAAQ;AACzB,YAAI,MAAM,IAAI,IAAI,MAAM,MAAM;AAC5B,gBAAM,IAAI,MAAM,KAAK;AACrB,eAAK,QAAQ,GAAG,KAAK;AAAA,QACvB;AAAA,MACF;AACA;AACA,eAAS,OAAO,OAAO,MAAM;AAAA,IAC/B;AAAA,IACA,WAAW,MAAM,SAAS,MAAM,KAAK,CAAC,SAAS,OAAO;AAAA,IACtD,SAAS,MAAM;AAAA,EACjB;AAEA,SAAO;AAAA,IACL;AAAA,IACA,eAAe;AAAA,IACf,UAAU;AACR,iBAAW,KAAK,OAAQ,GAAE;AAC1B,aAAO,SAAS;AAChB,UAAI,WAAW;AACf,WAAK;AACL,iBAAW,QAAQ,OAAQ,MAAK,QAAQ;AACxC,eAAS,QAAQ;AACjB,aAAO,OAAO;AAAA,IAChB;AAAA,EACF;AACF;;;AC5IA,SAAS,SAAAA,cAAa;;;ACDtB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAEK;AAGP,IAAM,sBAAsB,IAAI,aAAa,CAAC,IAAI,IAAI,GAAG,GAAG,IAAI,GAAG,IAAI,GAAG,CAAC,CAAC;AAWrE,SAAS,kBAAkB,KAAsC;AAEtE,QAAM,UAAU,QAAQ,IAAI,QAAQ,GAAG,CAAC,CAAC;AACzC,QAAM,QAAQ,QAAQ,CAAC;AACvB,QAAM,OAAO,QAAQ,CAAC;AAEtB,QAAM,YAAY,QAAQ,IAAI,QAAQ,GAAG,IAAI,QAAQ,CAAC;AACtD,QAAM,YAAY,QAAQ,IAAI,QAAQ,GAAG,IAAI,QAAQ,CAAC;AACtD,QAAM,YAAY,QAAQ,IAAI,QAAQ;AACtC,QAAM,UAAU,QAAQ,IAAI,QAAQ,GAAG,IAAI,MAAM,CAAC;AAClD,QAAM,WAAW,QAAQ,IAAI,QAAQ,GAAG,IAAI,OAAO,CAAC;AACpD,QAAM,aAAa,QAAQ,IAAI,QAAQ,GAAG,IAAI,SAAS,CAAC;AACxD,QAAM,eAAe,QAAQ,IAAI,QAAQ,GAAG,IAAI,WAAW,CAAC;AAE5D,QAAM,UAAU,MAAM,IAAI,IAAI;AAC9B,QAAM,WAAW,iBAAiB,GAAG,IAAI,OAAO,EAAE,IAAI,OAAO;AAE7D,MAAI,QAAuB,MAAM,CAAC;AAClC,WAAS,IAAI,GAAG,IAAI,GAAG,KAAK;AAC1B,UAAM,UAAU,MAAM,IAAI,UAAU,IAAI,MAAM,IAAI,UAAU,IAAI,UAAU;AAC1E,UAAM,aAAa,QAAQ,IAAI,KAAK;AAEpC,UAAM,OAAO,WAAW,IAAI,QAAQ,CAAC,EAAE,IAAI,QAAQ,EAAE,IAAI,QAAQ,CAAC,CAAC;AACnE,UAAM,OAAO,MAAM,CAAC,EAAE,IAAI,WAAW,IAAI,SAAS,CAAC,EAAE,IAAI,SAAS,EAAE,IAAI,SAAS,CAAC,CAAC,CAAC;AACpF,UAAM,UAAU,MAAM,IAAI,MAAM,IAAI,GAAG,GAAG,CAAC;AAE3C,UAAM,IAAI,MAAM,SAAS,IAAI,OAAO,EAAE,IAAI,GAAG,CAAC,EAAE,IAAI,GAAG;AACvD,UAAM,OAAO,OAAO,CAAC,EAAE,IAAI,OAAO,EAAE,IAAI,OAAO;AAE/C,UAAM,IAAI,MAAM,WAAW,IAAI,QAAQ,CAAC,EAAE,IAAI,EAAE,GAAG,GAAG,CAAC;AACvD,UAAM,SAAS,IAAI,WAAW,GAAG,WAAW,GAAG,CAAC,EAAE,IAAI,IAAI;AAG1D,UAAM,MAAM,WAAW,OAAO,IAAI,GAAG,GAAG,OAAO,IAAI,GAAG,GAAG,IAAI,EAAE,SAAS;AACxE,UAAM,SAAS,aAAa,EAAE,IAAI,MAAM,CAAC,EAAE,IAAI,aAAa,CAAC,CAAC;AAC9D,YAAQ,IAAI,OAAO,IAAI,IAAI,OAAO,EAAE,IAAI,MAAM,CAAC;AAAA,EACjD;AAEA,QAAM,WAAW,IAAI,sBAAsB;AAC3C,WAAS,aAAa,KAAK,iBAAiB,IAAI,GAAG,CAAC;AACpD,WAAS,eAAe,KAAK,WAAW,MAAM,MAAM,IAAI,SAAS,GAAG,GAAG,CAAC,CAAC;AACzE,WAAS,cAAc;AACvB,WAAS,YAAY;AACrB,WAAS,aAAa;AAEtB,QAAM,WAAW,IAAI,eAAe;AACpC,WAAS,aAAa,YAAY,IAAI,gBAAgB,qBAAqB,CAAC,CAAC;AAC7E,QAAM,OAAO,IAAI,KAAK,UAAU,QAAQ;AACxC,OAAK,gBAAgB;AACrB,OAAK,cAAc;AAEnB,SAAO;AAAA,IACL;AAAA,IACA,UAAU,OAAO;AACf,cAAQ,MAAM,IAAI,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC;AAChD,YAAM,QAAQ,MAAM,OAAO;AAC3B,WAAK,QAAQ,MAAM;AAAA,IACrB;AAAA,IACA,UAAU,MAAM;AACd,gBAAU,MAAM,IAAI,GAAG,KAAK,QAAQ;AACpC,gBAAU,MAAM,IAAI,GAAG,KAAK,QAAQ;AACpC,gBAAU,QAAQ,KAAK;AACvB,cAAQ,MAAM,IAAI,GAAG,KAAK,MAAM;AAChC,eAAS,MAAM,IAAI,GAAG,KAAK,OAAO;AAClC,iBAAW,MAAM,IAAI,GAAG,KAAK,SAAS;AACtC,mBAAa,MAAM,IAAI,GAAG,KAAK,WAAW;AAAA,IAC5C;AAAA,IACA,UAAU;AACR,eAAS,QAAQ;AACjB,eAAS,QAAQ;AAAA,IACnB;AAAA,EACF;AACF;;;AC1GA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,SAAAC;AAAA,EACA,SAAAC;AAAA,EACA;AAAA,EACA;AAAA,EACA,UAAAC;AAAA,EACA,OAAAC;AAAA,EACA,OAAAC;AAAA,EACA,OAAAC;AAAA,EACA;AAAA,EACA,oBAAAC;AAAA,EACA;AAAA,EACA;AAAA,EACA,cAAAC;AAAA,EACA;AAAA,EACA;AAAA,EACA,WAAAC;AAAA,EACA;AAAA,EACA;AAAA,EACA,QAAAC;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP;AAAA,EACE,mBAAAC;AAAA,EACA;AAAA,EACA;AAAA,EACA,QAAAC;AAAA,EACA,yBAAAC;AAAA,EACA;AAAA,EACA,WAAAC;AAAA,EACA,WAAAC;AAAA,OAEK;;;ACxCA,IAAM,cAAN,MAAkB;AAAA,EACf,MAAgB,CAAC;AAAA,EACjB,MAAgB,CAAC;AAAA,EAEjB,KAAK,GAAW,GAAW,GAAe;AAChD,SAAK,IAAI,KAAK,GAAG,GAAG,CAAC;AACrB,SAAK,IAAI,KAAK,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,CAAC,CAAC;AAAA,EACtC;AAAA;AAAA,EAGA,KAAK,GAAW,GAAW,GAAW,GAAW,GAAe;AAC9D,SAAK,KAAK,GAAG,GAAG,CAAC;AACjB,SAAK,KAAK,IAAI,GAAG,GAAG,CAAC;AACrB,SAAK,KAAK,IAAI,GAAG,IAAI,GAAG,CAAC;AACzB,SAAK,KAAK,GAAG,GAAG,CAAC;AACjB,SAAK,KAAK,IAAI,GAAG,IAAI,GAAG,CAAC;AACzB,SAAK,KAAK,GAAG,IAAI,GAAG,CAAC;AAAA,EACvB;AAAA;AAAA,EAGA,QAAQ,IAAY,IAAY,IAAY,IAAY,OAAe,GAAe;AACpF,UAAM,KAAK,KAAK;AAChB,UAAM,KAAK,KAAK;AAChB,UAAM,MAAM,KAAK,MAAM,IAAI,EAAE;AAC7B,QAAI,MAAM,KAAM;AAChB,UAAM,KAAM,CAAC,KAAK,OAAQ,QAAQ;AAClC,UAAM,KAAM,KAAK,OAAQ,QAAQ;AACjC,SAAK,KAAK,KAAK,IAAI,KAAK,IAAI,CAAC;AAC7B,SAAK,KAAK,KAAK,IAAI,KAAK,IAAI,CAAC;AAC7B,SAAK,KAAK,KAAK,IAAI,KAAK,IAAI,CAAC;AAC7B,SAAK,KAAK,KAAK,IAAI,KAAK,IAAI,CAAC;AAC7B,SAAK,KAAK,KAAK,IAAI,KAAK,IAAI,CAAC;AAC7B,SAAK,KAAK,KAAK,IAAI,KAAK,IAAI,CAAC;AAAA,EAC/B;AAAA;AAAA,EAGA,SAAS,QAA2B,OAAe,GAAe;AAChE,UAAM,IAAI,KAAK,MAAO,OAAO,SAAoB,CAAC;AAClD,aAAS,IAAI,GAAG,IAAI,GAAG,KAAK;AAC1B,WAAK;AAAA,QACH,QAAQ,IAAI,KAAK,CAAC;AAAA,QAClB,QAAQ,IAAI,KAAK,IAAI,CAAC;AAAA,QACtB,OAAO,IAAI,CAAC;AAAA,QACZ,OAAO,IAAI,IAAI,CAAC;AAAA,QAChB;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA;AAAA,EAGA,KAAK,IAAY,IAAY,GAAW,GAAS,WAAW,IAAU;AACpE,aAAS,IAAI,GAAG,IAAI,UAAU,KAAK;AACjC,YAAM,KAAM,IAAI,WAAY,KAAK,KAAK;AACtC,YAAM,MAAO,IAAI,KAAK,WAAY,KAAK,KAAK;AAC5C,WAAK,KAAK,IAAI,IAAI,CAAC;AACnB,WAAK,KAAK,KAAK,KAAK,IAAI,EAAE,IAAI,GAAG,KAAK,KAAK,IAAI,EAAE,IAAI,GAAG,CAAC;AACzD,WAAK,KAAK,KAAK,KAAK,IAAI,EAAE,IAAI,GAAG,KAAK,KAAK,IAAI,EAAE,IAAI,GAAG,CAAC;AAAA,IAC3D;AAAA,EACF;AAAA,EAEA,QAAiB;AACf,WAAO;AAAA,MACL,WAAW,IAAI,aAAa,KAAK,GAAG;AAAA,MACpC,QAAQ,IAAI,aAAa,KAAK,GAAG;AAAA,MACjC,aAAa,KAAK,IAAI,SAAS;AAAA,IACjC;AAAA,EACF;AACF;AAOO,SAAS,cAAc,KAAmB;AAC/C,QAAM,OAAO,8EAA8E,KAAK,GAAG;AACnG,MAAI,SAAS,MAAM;AACjB,WAAO;AAAA,MACL,OAAO,KAAK,CAAC,CAAC,IAAI;AAAA,MAClB,OAAO,KAAK,CAAC,CAAC,IAAI;AAAA,MAClB,OAAO,KAAK,CAAC,CAAC,IAAI;AAAA,MAClB,KAAK,CAAC,MAAM,SAAY,IAAI,OAAO,KAAK,CAAC,CAAC;AAAA,IAC5C;AAAA,EACF;AACA,QAAM,MAAM,oBAAoB,KAAK,GAAG;AACxC,MAAI,QAAQ,MAAM;AAChB,UAAM,IAAI,OAAO,SAAS,IAAI,CAAC,GAAa,EAAE;AAC9C,WAAO,EAAG,KAAK,KAAM,OAAQ,MAAO,KAAK,IAAK,OAAQ,MAAM,IAAI,OAAQ,KAAK,CAAC;AAAA,EAChF;AACA,SAAO,CAAC,KAAK,KAAK,KAAK,CAAC;AAC1B;;;ACrDO,IAAM,QAAQ,YAAY,CAAC,IAAI,CAAC;AAChC,IAAM,YAAY,YAAY,CAAC,UAAU,IAAI,CAAC;AAC9C,IAAM,YAAY,YAAY,CAAC,YAAY,CAAC;AAC5C,IAAM,YAAY,YAAY,CAAC,QAAQ,CAAC;AACxC,IAAM,QAAQ,YAAY,CAAC,MAAM,UAAU,CAAC;AAC5C,IAAM,iBAAiB,YAAY,CAAC,aAAa,CAAC;AAElD,IAAM,eAAe,YAAY,CAAC,eAAe,IAAI,CAAC;AAEtD,IAAM,UAAU,YAAY,CAAC,MAAM,CAAC;AAY3C,SAAS,WAAW,OAAc,GAAoB;AACpD,SAAO,MAAM,OAAO,GAAG,MAAM,KAAK,CAAC,MAAM,OAAO,GAAG,MAAM;AAC3D;AAEA,IAAM,4BAA4B;AAClC,IAAM,UAAU;AAChB,IAAM,SAAS;AAIR,SAAS,eAAe,OAAc,GAA6B;AACxE,QAAM,IAAI,MAAM,IAAI,GAAG,QAAQ;AAC/B,MAAI,MAAM,OAAW,QAAO;AAC5B,QAAM,WAAW,MAAM,IAAI,GAAG,YAAY;AAC1C,QAAM,IAAI,aAAa,UAAa,SAAS,IAAI,IAAI,WAAW,MAAM,IAAI,GAAG,IAAI;AACjF,MAAI,MAAM,OAAW,QAAO;AAC5B,SAAO,EAAE,GAAG,EAAE,GAAG,GAAG,EAAE,GAAG,OAAO,EAAE,GAAG,QAAQ,EAAE,EAAE;AACnD;AAGA,IAAM,YAAY,oBAAI,IAAmC;AACzD,SAAS,OAAO,IAAgB,QAAsC;AACpE,MAAI,QAAQ,UAAU,IAAI,GAAG,IAAI;AACjC,MAAI,UAAU,QAAW;AACvB,YAAQ,UAAU,GAAG,KAAK;AAC1B,cAAU,IAAI,GAAG,MAAM,KAAK;AAAA,EAC9B;AACA,SAAO,MAAM,IAAI,MAAM;AACzB;AAEA,SAAS,eACP,OACA,QACA,QAC8C;AAC9C,MAAI,WAAW,OAAW,QAAO;AACjC,QAAM,OAAO,eAAe,OAAO,MAAM;AACzC,MAAI,SAAS,OAAW,QAAO;AAC/B,QAAM,OAAO,MAAM,IAAI,QAAQ,QAAQ,GAAG;AAC1C,MAAI,OAAO,SAAS,SAAU,QAAO;AACrC,QAAM,KAAK,QAAQ,IAAI,IAAI;AAC3B,MAAI,OAAO,OAAW,QAAO;AAC7B,QAAM,OAAO,OAAO,IAAI,MAAM;AAC9B,MAAI,SAAS,OAAW,QAAO;AAC/B,SAAO,EAAE,QAAQ,MAAM,KAAK;AAC9B;AAGA,SAAS,cAAc,GAAU,KAAmC;AAClE,QAAM,KAAK,cAAc,EAAE,IAAI,EAAE,IAAI,GAAG;AACxC,QAAM,KAAK,cAAc,EAAE,IAAI,EAAE,IAAI,GAAG;AACxC,QAAM,KAAK,cAAc,EAAE,IAAI,EAAE,IAAI,GAAG;AACxC,QAAM,KAAK,cAAc,EAAE,IAAI,EAAE,IAAI,GAAG;AACxC,SAAO,EAAE,IAAI,GAAG,GAAG,IAAI,GAAG,GAAG,IAAI,GAAG,GAAG,IAAI,GAAG,GAAG,IAAI,GAAG,GAAG,IAAI,GAAG,GAAG,IAAI,GAAG,GAAG,IAAI,GAAG,EAAE;AAC1F;AAGA,SAAS,cAAc,GAAiB,GAAqC;AAC3E,QAAM,MAAM,EAAE;AACd,QAAM,IAAI,IAAI;AACd,MAAI,KAAK;AACT,MAAI,KAAK,IAAI;AACb,SAAO,KAAK,IAAI;AACd,UAAM,MAAO,KAAK,MAAO;AACzB,QAAK,IAAI,GAAG,IAAe,EAAG,MAAK,MAAM;AAAA,QACpC,MAAK;AAAA,EACZ;AACA,QAAM,IAAI,KAAK,IAAI,GAAG,EAAE;AACxB,QAAM,IAAI,IAAI,IAAI,CAAC;AACnB,QAAM,IAAI,IAAI,CAAC;AACf,QAAM,IAAI,IAAI,KAAK,IAAI,MAAM,IAAI,KAAK;AACtC,QAAM,KAAK,EAAE,QAAQ,IAAI,KAAK,CAAC;AAC/B,QAAM,KAAK,EAAE,QAAQ,IAAI,KAAK,IAAI,CAAC;AACnC,QAAM,KAAK,EAAE,OAAO,IAAI,CAAC;AACzB,QAAM,KAAK,EAAE,OAAO,IAAI,IAAI,CAAC;AAC7B,SAAO,EAAE,GAAG,MAAM,KAAK,MAAM,GAAG,GAAG,MAAM,KAAK,MAAM,EAAE;AACxD;AAGA,SAAS,aAAa,MAAmB,GAAiB,OAAe,GAAe;AACtF,QAAM,QAAQ,EAAE,UAAU,EAAE,UAAU,SAAS,CAAC;AAChD,WAAS,IAAI,GAAG,IAAI,OAAO,KAAK,UAAU,QAAQ;AAChD,UAAM,IAAI,cAAc,GAAG,CAAC;AAC5B,UAAM,IAAI,cAAc,GAAG,KAAK,IAAI,IAAI,SAAS,KAAK,CAAC;AACvD,SAAK,QAAQ,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC;AAAA,EAC3C;AACF;AAEO,SAAS,aACd,OACA,OACA,SAAsB,sBACtB,SACS;AACT,QAAM,OAAO,IAAI,YAAY;AAC7B,QAAM,MAAM,MAAM;AAClB,QAAM,YAAY,cAAc,OAAO,SAAS;AAChD,QAAM,gBAAgB,cAAc,OAAO,aAAa;AAGxD,QAAM,MAAM,KAAK,EAAE,KAAK,CAAC,UAAU;AACjC,eAAW,KAAK,OAAO;AACrB,YAAM,OAAO,MAAM,OAAO,CAAC;AAC3B,YAAM,QAAQ,MAAM,IAAI,MAAM,SAAS;AACvC,UAAI,UAAU,OAAW;AACzB,YAAM,aAAa,MAAM,YAAY,MAAM,QAAQ;AACnD,YAAM,WAAW,MAAM,YAAY,MAAM,MAAM;AAE/C,UAAI,eAAe,UAAa,WAAW,OAAO,UAAU,EAAG;AAC/D,UAAI,aAAa,UAAa,WAAW,OAAO,QAAQ,EAAG;AAC3D,YAAM,OAAO,eAAe,OAAO,YAAY,MAAM,QAAQ,EAAE;AAC/D,YAAM,KAAK,eAAe,OAAO,UAAU,MAAM,MAAM,EAAE;AACzD,UAAI,SAAS,UAAa,OAAO,OAAW;AAC5C,YAAM,QAAQ;AAAA,QACZ,WAAW,KAAK,QAAQ,KAAK,IAAI;AAAA,QACjC,KAAK,KAAK;AAAA,QACV,WAAW,GAAG,QAAQ,GAAG,IAAI;AAAA,QAC7B,GAAG,KAAK;AAAA,MACV;AACA,YAAM,WAAW,MAAM,OAAO,MAAM,QAAQ;AAC5C,YAAM,IAAI,gBAAgB,cAAc,OAAO,GAAG,GAAG,yBAAyB;AAC9E,WAAK,SAAS,EAAE,QAAQ,WAAW,OAAO,gBAAgB,OAAO,WAAW,WAAW,gBAAgB,SAAS;AAAA,IAClH;AAAA,EACF,CAAC;AAID,MAAI,SAAS,WAAW,MAAM;AAC5B,UAAM,OAAO,KAAK,IAAI,IAAI,KAAK,IAAI,QAAQ,KAAK,QAAQ,EAAE,IAAI,GAAG;AACjE,UAAM,QAAe;AAAA,MACnB,IAAI,QAAQ;AAAA,MACZ,IAAI,QAAQ;AAAA,MACZ,IAAI,QAAQ,KAAK;AAAA,MACjB,IAAI,QAAQ;AAAA,MACZ,IAAI,QAAQ,KAAK;AAAA,MACjB,IAAI,QAAQ;AAAA,MACZ,IAAI,QAAQ;AAAA,MACZ,IAAI,QAAQ;AAAA,IACd;AACA,UAAM,IAAI,gBAAgB,cAAc,OAAO,GAAG,GAAG,yBAAyB;AAC9E,QAAI,QAAQ,WAAY,MAAK,SAAS,EAAE,QAAQ,OAAO,WAAW,aAAa;AAAA,QAC1E,cAAa,MAAM,GAAG,OAAO,WAAW,SAAS;AAAA,EACxD;AAGA,QAAM,aAAa,MAAM,QAAQ,cAAc,MAAM;AACrD,QAAM,WAAW,cAAc,aAAa,OAAO,kBAAkB,OAAO,SAAS;AACrF,QAAM,MAAM,KAAK,EAAE,KAAK,CAAC,UAAU;AACjC,UAAM,KAAK,MAAM,IAAI,UAAU,EAAE;AACjC,UAAM,KAAK,MAAM,IAAI,UAAU,EAAE;AACjC,eAAW,KAAK,OAAO;AACrB,YAAM,IAAI,cAAc,GAAG,CAAC,GAAa,GAAG,CAAC,GAAa,GAAG;AAC7D,WAAK,KAAK,EAAE,GAAG,EAAE,GAAG,OAAO,YAAY,QAAQ;AAAA,IACjD;AAAA,EACF,CAAC;AAED,SAAO,KAAK,MAAM;AACpB;;;AC7MO,IAAM,uBAAuB;AAE7B,IAAM,qBAAqB;AAE3B,IAAM,uBAAuB;AAM7B,SAAS,cAAc,KAAmC;AAC/D,SAAO,EAAE,GAAG,4BAA4B,GAAG,IAAI,OAAO;AACxD;AAGO,SAAS,YACd,YACA,QACA,SACQ;AACR,QAAM,QAAQ,aAAa,OAAO,CAAC,KAAK,KAAK,IAAI,OAAO,CAAC,IAAI,OAAO,CAAC,GAAG,IAAM;AAC9E,QAAM,OAAO,KAAK,aAAa,QAAQ,CAAC,KAAK,KAAK,IAAI,QAAQ,CAAC,IAAI,QAAQ,CAAC,GAAG,IAAM;AACrF,SAAO,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,MAAM,IAAI,GAAG,CAAC,GAAG,CAAC;AACtD;AAMO,SAAS,iBAAiB,MAAc,UAA0B;AACvE,MAAI,YAAY,EAAG,QAAO;AAC1B,QAAM,KAAK,OAAO,MAAM,aAAa,MAAM;AAC3C,SAAO,KAAK,IAAI,KAAK,IAAI,GAAG,CAAC,GAAG,CAAC;AACnC;AAsBO,SAAS,oBAAoB,OAAoB,KAAgC;AACtF,QAAM,EAAE,OAAO,IAAI;AACnB,QAAM,MAAqB,CAAC;AAC5B,QAAM,YAAY,IAAI,SAAS,IAAI,CAAC,MAAM,YAAY,IAAI,OAAO,MAAM,IAAI,QAAQ,IAAI,OAAO,CAAC;AAC/F,WAAS,IAAI,GAAG,IAAI,IAAI,SAAS,QAAQ,KAAK;AAC5C,UAAM,UAAU,IAAI,SAAS,CAAC;AAC9B,UAAM,UAAU,UAAU,CAAC;AAC3B,UAAM,SAAS,IAAI,YAAY,CAAC,IAAI,IAAI,IAAI,YAAY,CAAC;AACzD,UAAM,QAAQ,UAAU,SAAS,IAAI;AACrC,QAAI,UAAU,QAAQ,SAAS,GAAG;AAChC,UAAI,KAAK,EAAE,IAAI,GAAG,IAAI,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,GAAG,YAAY,EAAE,CAAC;AAC9E;AAAA,IACF;AACA,UAAM,SAAS,MAAM,QAAQ,OAAO;AACpC,UAAM,SAAS,MAAM,SAAS,OAAO;AACrC,UAAM,KAAK,KAAK,MAAM,OAAO,IAAI,OAAO,IAAI;AAC5C,UAAM,KAAK,KAAK,MAAM,OAAO,IAAI,OAAO,IAAI;AAC5C,UAAM,KAAK,KAAK,MAAM,OAAO,IAAI,UAAU,OAAO,IAAI;AACtD,UAAM,KAAK,KAAK,MAAM,OAAO,IAAI,UAAU,OAAO,IAAI;AACtD,UAAM,OAAO,KAAK,IAAI,GAAG,KAAK,EAAE;AAChC,UAAM,OAAO,KAAK,IAAI,GAAG,KAAK,EAAE;AAChC,UAAM,QAAQ,OAAO;AACrB,QAAI,QAAQ,sBAAsB;AAChC,UAAI,KAAK,EAAE,IAAI,GAAG,IAAI,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,GAAG,YAAY,EAAE,CAAC;AAC9E;AAAA,IACF;AACA,QAAI,aAAa;AACjB,UAAM,OAAO,IAAI,SAAS,IAAI,CAAC;AAC/B,QAAI,SAAS,UAAc,UAAU,IAAI,CAAC,KAAgB,MAAM;AAC9D,YAAM,QAAQ,OAAO;AACrB,UAAI,OAAO,UAAU,KAAK,KAAK,QAAQ,EAAG,cAAa;AAAA,IACzD;AACA,QAAI,KAAK,EAAE,IAAI,IAAI,MAAM,MAAM,OAAO,OAAO,WAAW,CAAC;AAAA,EAC3D;AACA,SAAO;AACT;AAiBO,SAAS,qBACd,OACA,OACA,QACA,YACA,OACA,aACA,KACQ;AACR,MAAI,cAAc,EAAG,QAAO;AAC5B,QAAM,EAAE,OAAO,IAAI;AACnB,QAAM,MAAM,KAAK,IAAI,OAAO,YAAY,oBAAoB,KAAK,MAAM,IAAI,SAAS,oBAAoB,CAAC;AACzG,MAAI,IAAI;AAGR,aAAW,QAAQ,OAAO;AACxB,QAAI,KAAK,IAAK;AACd,QAAI,EAAE,KAAK,WAAW,GAAI;AAC1B,UAAM,IAAI,KAAK,UAAU,WAAW,OAAO,cAAc,KAAK,GAAG,KAAK,GAAG,MAAM;AAC/E,UAAM,IAAI,IAAI;AACd,QAAI,IAAI,CAAC,IAAI,EAAE;AACf,QAAI,IAAI,CAAC,IAAI,EAAE;AACf,QAAI,IAAI,CAAC,IAAI;AACb,QAAI,IAAI,CAAC,IAAI;AACb,QAAI,IAAI,CAAC,IAAI;AACb,QAAI,IAAI,CAAC,IAAI,KAAK,WAAW;AAC7B,QAAI,IAAI,CAAC,IAAI;AACb,QAAI,IAAI,CAAC,IAAI;AACb;AAAA,EACF;AAEA,MAAI,CAAC,OAAO,WAAW,gBAAgB,UAAa,OAAO,kBAAkB,KAAK,KAAK,KAAK;AAC1F,WAAO;AAAA,EACT;AAMA,QAAM,UAAU,IAAI,OAAO,QAAQ,KAAK,KAAK,KAAK,IAAI,OAAO,iBAAiB,YAAY,IAAM,CAAC;AACjG,QAAM,MAAM,UAAU,OAAO;AAC7B,QAAM,OAAO,YAAY;AAAA,IACvB,MAAM,OAAO,IAAI;AAAA,IACjB,MAAM,OAAO,IAAI;AAAA,IACjB,MAAM,OAAO,IAAI,MAAM,QAAQ,OAAO,OAAO;AAAA,IAC7C,MAAM,OAAO,IAAI,MAAM,SAAS,OAAO,OAAO;AAAA,EAChD,CAAC;AAED,QAAM,SAAS,MAAM,QAAQ;AAC7B,QAAM,SAAS,MAAM,SAAS;AAC9B,QAAM,aAAgC,CAAC;AACvC,aAAW,OAAO,MAAM;AAGtB,UAAM,OAAO,eAAe,OAAO,IAAI,EAAE;AACzC,QAAI,SAAS,UAAa,KAAK,SAAS,KAAK,KAAK,UAAU,EAAG;AAC/D,UAAM,KAAM,KAAK,QAAQ,IAAK,OAAO;AACrC,UAAM,KAAM,KAAK,SAAS,IAAK,OAAO;AACtC,UAAM,SAAS,cAAc,KAAK,IAAI,KAAK,QAAQ,GAAG,KAAK,IAAI,KAAK,SAAS,GAAG,MAAM;AACtF,eAAW,KAAK;AAAA,MACd,IAAI,OAAO;AAAA,MACX,IAAI,OAAO;AAAA,MACX;AAAA,MACA;AAAA,MACA,GAAG,KAAK,IAAI,OAAO,eAAe,OAAO,MAAM,IAAI,EAAE;AAAA,MACrD,MAAM,KAAK;AAAA,MACX,aAAa,OAAO,IAAI,WAAW,KAAK,OAAO,IAAI,WAAW;AAAA,IAChE,CAAC;AAAA,EACH;AAEA,QAAM,SAAS,MAAM;AACrB,MAAI,WAAW,SAAS,QAAQ;AAC9B,eAAW,KAAK,CAAC,GAAG,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,UAAU;AACxE,eAAW,SAAS;AAAA,EACtB;AAEA,QAAM,WAAW,OAAO,iBAAiB;AACzC,aAAW,KAAK,YAAY;AAC1B,UAAM,IAAI,IAAI;AACd,QAAI,IAAI,CAAC,IAAI,EAAE;AACf,QAAI,IAAI,CAAC,IAAI,EAAE;AACf,QAAI,IAAI,CAAC,IAAI,EAAE;AACf,QAAI,IAAI,CAAC,IAAI,EAAE;AACf,QAAI,IAAI,CAAC,IAAI,EAAE;AACf,QAAI,IAAI,CAAC,IAAI;AACb,QAAI,IAAI,CAAC,IAAI;AACb,QAAI,IAAI,CAAC,IAAI;AACb;AAAA,EACF;AACA,SAAO;AACT;;;AHnKA,IAAM,UAAU,IAAI,aAAa,CAAC,IAAI,IAAI,GAAG,GAAG,IAAI,GAAG,GAAG,GAAG,GAAG,IAAI,IAAI,GAAG,GAAG,GAAG,GAAG,IAAI,GAAG,CAAC,CAAC;AAE7F,IAAM,SAAS;AAgBR,SAAS,mBAAuC;AAErD,QAAM,cAAc,IAAI,aAAa,qBAAqB,oBAAoB;AAC9E,QAAM,aAAa,IAAI,uBAAuB,aAAa,CAAC;AAE5D,QAAM,YAAY,QAAQ,YAAY,QAAQ,qBAAqB,CAAC,EACjE,OAAO,IAAI,EACX,WAAW;AAEd,QAAM,OAAOC,SAAQ,IAAIC,SAAQ,GAAG,CAAC,CAAC;AACtC,QAAM,QAAQD,SAAQ,CAAC;AACvB,QAAM,QAAQA,SAAQ,IAAIC,SAAQ,GAAG,CAAC,CAAC;AACvC,QAAM,WAAWD,SAAQ,CAAC;AAC1B,QAAM,WAAWA,SAAQ,CAAC;AAC1B,QAAM,aAAaA,SAAQ,IAAI;AAC/B,QAAM,cAAcA,SAAQ,IAAI;AAChC,QAAM,KAAKA,SAAQ,CAAC;AACpB,QAAM,OAAOA,SAAQ,CAAC;AACtB,QAAM,YAAYA,SAAQ,CAAC;AAC3B,QAAM,eAAeA,SAAQ,CAAC;AAC9B,QAAM,SAASA,SAAQ,GAAG,KAAK;AAC/B,QAAM,SAASA,SAAQ,IAAIE,SAAQ,MAAM,MAAM,GAAG,CAAC;AAEnD,QAAM,MAAMC,OAAM,EAAE;AACpB,QAAM,OAAO,KAAK,GAAG,CAAC;AAGtB,QAAM,aAAa,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,MAAmD;AAChF,UAAM,IAAI,IAAI,CAAC,EAAE,IAAI,CAAC,EAAE,IAAI,KAAK,GAAG,CAAC,CAAC;AACtC,WAAOC,QAAOC,KAAI,GAAG,KAAK,GAAG,CAAC,CAAC,CAAC,EAC7B,IAAIC,KAAID,KAAI,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,EACzB,IAAI,CAAC;AAAA,EACV,CAAC;AAGD,QAAM,iBAAiB,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,MAAmD;AACpF,UAAM,IAAI,KAAK,CAAC;AAChB,UAAM,IAAI,IAAI,CAAC;AACf,UAAM,QAAQA,KAAI,EAAE,IAAI,KAAK,GAAG,CAAC,CAAC,GAAG,KAAK,GAAG,CAAC,CAAC;AAC/C,UAAM,IAAI,EAAE,IAAI,KAAK;AACrB,UAAM,IAAI,KAAK,GAAG,CAAC,EAAE,MAAM;AAC3B,OAAG,EAAE,EAAE,YAAY,CAAC,EAAE,IAAI,EAAE,EAAE,YAAY,CAAC,CAAC,GAAG,MAAM;AACnD,YAAM,MAAMD,QAAO,CAAC;AACpB,SAAG,IAAI,YAAY,IAAM,GAAG,MAAM;AAChC,UAAE,OAAO,EAAE,IAAI,EAAE,IAAI,GAAG,CAAC,CAAC;AAAA,MAC5B,CAAC,EAAE,KAAK,MAAM;AACZ,UAAE,OAAO,KAAK,EAAE,GAAG,CAAC,CAAC;AAAA,MACvB,CAAC;AAAA,IACH,CAAC,EACE,OAAO,EAAE,EAAE,YAAY,EAAE,CAAC,GAAG,MAAM;AAClC,QAAE,OAAO,KAAK,EAAE,GAAG,CAAC,CAAC;AAAA,IACvB,CAAC,EACA,KAAK,MAAM;AACV,QAAE,OAAO,KAAK,GAAG,EAAE,CAAC,CAAC;AAAA,IACvB,CAAC;AACH,WAAO;AAAA,EACT,CAAC;AAED,QAAM,gBAAgB,GAAG,CAAC,CAAC,GAAG,QAAQ,MAAoC;AACxE,UAAM,IAAIA,QAAO,CAAC;AAClB,WAAO,OAAO,EAAE,YAAY,IAAM,GAAG,EAAE,IAAIC,KAAI,GAAG,IAAM,CAAC,GAAG,QAAQ;AAAA,EACtE,CAAC;AAED,QAAM,QAAQ,IAAI,MAAM;AACxB,QAAM,aAAwC,CAAC;AAC/C,QAAM,YAAqC,CAAC;AAC5C,QAAM,SAAiB,CAAC;AACxB,QAAM,gBAAgB,MAAM,KAAK,EAAE,QAAQ,OAAO,GAAG,OAAO;AAAA,IAC1D,QAAQL,SAAQ,IAAIC,SAAQ,GAAG,CAAC,CAAC;AAAA,IACjC,MAAMD,SAAQ,IAAIC,SAAQ,GAAG,CAAC,CAAC;AAAA,IAC/B,SAASD,SAAQ,EAAE;AAAA,IACnB,OAAOA,SAAQ,CAAC;AAAA,IAChB,SAASA,SAAQ,CAAC;AAAA,EACpB,EAAE;AAEF,WAAS,QAAQ,GAAG,QAAQ,QAAQ,SAAS;AAC3C,UAAM,KAAK,cAAc,KAAK;AAE9B,UAAM,MAAM,QAAQ,KAAK,GAAG,CAAC,GAAG,YAAY,KAAK,EAAE;AACnD,UAAM,SAAS,QAAQG,OAAM,CAAC,GAAG,eAAe,KAAK,EAAE;AAEvD,UAAM,aAAa,GAAG,MAAM;AAC1B,YAAM,MAAMA,OAAM,aAAa;AAC/B,YAAM,OAAO,GAAG,KAAK;AACrB,YAAM,MAAM,IAAI,KAAK,IAAI,EAAE,MAAM;AACjC,YAAM,MAAM,IAAI,IAAI,IAAI,EAAE,MAAM;AAChC,YAAM,QAAQ,GAAG,OAAO,IAAI,KAAK,KAAK,GAAG,CAAC,EAAE,IAAI,GAAG,OAAO;AAC1D,YAAM,SAAS,MAAM,IAAI,IAAI,EAAE,IAAI,KAAK;AAGxC,YAAM,QAAQ,KAAK,GAAG,CAAC,EAAE,MAAM;AAC/B,YAAM,OAAOA,OAAM,GAAG,EAAE,MAAM;AAC9B,WAAK,EAAE,OAAO,IAAI,CAAC,GAAG,KAAK,QAAQ,MAAM,OAAO,WAAW,IAAI,GAAG,CAAC,EAAE,EAAE,MAAM;AAC3E,cAAM,IAAI,UAAU,QAAQ,EAAE,IAAI,CAAC,CAAC;AACpC,cAAM,IAAI,UAAU,QAAQ,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC,CAAC;AAC3C,cAAM,SAAS,EAAE;AACjB,cAAM,OAAO,EAAE;AACf,cAAM,MAAM,EAAE;AACd,cAAM,WAAW,EAAE;AACnB,cAAM,MAAM,OAAO,IAAI,MAAM;AAC7B,cAAM,QAAQ,KAAK,IAAI,KAAKE,KAAI,UAAU,IAAM,CAAC,CAAC;AAClD;AAAA,UACE,IAAI,IAAI,CAAC,EACN,YAAY,KAAK,EAAE,IAAI,KAAK,CAAC,EAC7B,GAAG,IAAI,IAAI,CAAC,EAAE,YAAY,KAAK,EAAE,IAAI,KAAK,CAAC,CAAC;AAAA,UAC/C,MAAM;AACJ,qBAAS;AAAA,UACX;AAAA,QACF;AACA,cAAM,IAAI,WAAW,KAAK,MAAM,GAAG;AACnC,aAAK,OAAOC,KAAI,MAAM,CAAC,CAAC;AACxB,cAAM,OAAOD,KAAI,GAAG,CAAC;AACrB,cAAM,KAAK,KAAK,IAAI,IAAI,EAAE,IAAI,GAAG;AACjC,cAAM,UAAU,eAAe,KAAK,MAAM,GAAG;AAE7C,cAAM,UAAU,QAAQ,IAAI,GAAG,IAAI,QAAQ,EAAE,IAAI,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;AAAA,MACtE,CAAC;AAED,YAAM,WAAW,cAAc,OAAO,IAAI;AAC1C,YAAM,MAAMD,QAAO,KAAK;AAGxB,YAAM,YAAY,OAAO,SAAS,YAAY,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,CAAC,CAAC,GAAGG,OAAM,KAAK,GAAG,CAAC,CAAC;AAEzF,YAAM,SAASC,kBAAiB;AAEhC,YAAM,YAAYC,KAAI,aAAa,SAAS,IAAI,IAAI,GAAG,SAAS;AAChE,YAAM,WAAW,OAAO,IAAI,SAAS;AAErC,YAAM,MAAM;AAAA,QACV,aAAa,YAAY,GAAG;AAAA,QAC5B;AAAA,QACA,cAAcA,KAAI,MAAM,UAAU,SAAS,GAAG,IAAI;AAAA,MACpD;AACA,YAAM,MAAM,KAAK,IAAI,EAAE,OAAO,GAAG,IAAI,CAAC;AACtC,YAAM,OAAOA,KAAI,SAAS,IAAI,IAAI,GAAG,SAAS,IAAI,IAAI,GAAG,SAAS;AAClE,YAAM,OAAOA,KAAI,WAAW,IAAI,IAAI,GAAG,WAAW,IAAI,IAAI,GAAG,SAAS;AACtE,YAAM,cAAc,IAAI,IAAI,OAAO,CAAC,EAAE,IAAI,IAAI,EAAE,IAAI,IAAI,IAAI,OAAO,CAAC,EAAE,IAAI,IAAI,CAAC;AAC/E,YAAM,QAAQ,OAAO,SAAS,YAAY,GAAG,GAAG,UAAU,WAAW;AACrE,YAAM,MAAM,OAAO,IAAI,KAAK;AAG5B,YAAM,YAAY,OAAO,SAAS,YAAY,GAAG,GAAGN,OAAM,IAAI,GAAGA,OAAM,IAAI,CAAC;AAC5E,YAAM,aAAaM,KAAI,WAAWN,OAAM,CAAC,GAAG,SAAS;AACrD,YAAM,QAAQI,OAAM,GAAG,MAAM,IAAI,UAAU,GAAG,GAAG,CAAC,EAAE,MAAM;AAE1D,SAAG,KAAK,SAAS,IAAI,GAAG,MAAM;AAC5B,cAAM,OAAO,CAAC;AAAA,MAChB,CAAC;AAGD,YAAM,OAAO,GAAG,OAAO,EAAE,IAAI,GAAG;AAChC,YAAM,OAAO,GAAG,OAAO,EAAE,IAAI,GAAG;AAChC;AAAA,QACE,GAAG,QACA,YAAY,GAAG,EACf,IAAI,IAAI,MAAM,GAAG,OAAO,EAAE,SAAS,GAAG,CAAC,EACvC,IAAI,IAAI,MAAM,GAAG,OAAO,EAAE,SAAS,GAAG,CAAC;AAAA,QAC1C,MAAM;AACJ,gBAAM,OAAO,CAAC;AAAA,QAChB;AAAA,MACF;AAEA,UAAI,OAAO,MAAM;AACjB,aAAO,OAAO,KAAK;AAEnB,YAAM,MAAM;AAAA,QACV,IAAI,EAAE,IAAI,MAAM,CAAC,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC;AAAA,QAC/BJ,OAAM,CAAC,EAAE,IAAI,IAAI,EAAE,IAAI,MAAM,CAAC,EAAE,IAAI,CAAC,CAAC;AAAA,MACxC;AACA,aAAOO,MAAK,KAAK,GAAG,CAAC;AAAA,IACvB,CAAC,EAAE;AAEH,UAAM,eAAe,GAAG,MAAM;AAC5B,YAAM,UAAUP,OAAM,CAAC,EAAE,IAAIQ,YAAW,MAAM,GAAKP,QAAO,GAAG,CAAC,CAAC;AAC/D,YAAM,KAAKD,OAAM,CAAC,EAAE,IAAIQ,YAAW,MAAM,GAAK,IAAI,IAAI,CAAC,CAAC,CAAC;AACzD,YAAM,KAAKR,OAAM,CAAC,EAAE,IAAIQ,YAAW,MAAM,GAAK,IAAI,IAAI,CAAC,CAAC,CAAC;AACzD,YAAM,OAAO,OAAO,SAAS,YAAY,GAAG,GAAG,SAAS,GAAG,IAAI,EAAE,CAAC;AAClE,YAAM,IAAI,OAAO,IAAI,IAAI;AACzB,cAAQ,EAAE,SAAS,IAAI,CAAC;AACxB,aAAOD,MAAK,QAAQ,CAAC;AAAA,IACvB,CAAC,EAAE;AAEH,UAAM,WAAW,IAAIE,uBAAsB;AAC3C,aAAS,aAAa;AACtB,aAAS,eAAe;AACxB,aAAS,cAAc;AACvB,aAAS,YAAY;AACrB,aAAS,aAAa;AAEtB,UAAM,WAAW,IAAI,wBAAwB;AAC7C,aAAS,aAAa,YAAY,IAAIC,iBAAgB,SAAS,CAAC,CAAC;AACjE,aAAS,gBAAgB;AAEzB,UAAM,OAAO,IAAIC,MAAK,UAAU,QAAQ;AACxC,SAAK,gBAAgB;AACrB,SAAK,cAAc;AACnB,SAAK,UAAU;AAEf,eAAW,KAAK,QAAQ;AACxB,cAAU,KAAK,QAAQ;AACvB,WAAO,KAAK,IAAI;AAChB,UAAM,IAAI,IAAI;AAAA,EAChB;AAEA,SAAO;AAAA,IACL;AAAA,IACA,OAAO,OAAO,KAAK,QAAQ,QAAQ,SAAS,aAAa;AACvD,WAAK,MAAM,IAAI,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC;AAC7C,YAAM,QAAQ,MAAM,OAAO;AAC3B,YAAM,MAAM,IAAI,KAAK,IAAI,GAAG,MAAM,KAAK,GAAG,KAAK,IAAI,GAAG,MAAM,MAAM,CAAC;AACnE,eAAS,QAAQ,OAAO,UAAU,QAAQ,IAAI;AAC9C,eAAS,QAAQ,OAAO;AACxB,iBAAW,QAAQ,OAAO;AAC1B,kBAAY,QAAQ,IAAI,UAAU,CAAC;AACnC,YAAM,IAAI,MAAM,OAAO,QAAQ,OAAO;AACtC,SAAG,QAAQ;AACX,WAAK,QAAQ,KAAK,KAAK,KAAK,IAAI,GAAG,CAAC,IAAI,IAAI;AAC5C,gBAAU,QAAQ,OAAO;AACzB,mBAAa,QAAQ,OAAO,cAAc,IAAI;AAC9C,aAAO,QAAQ;AACf,aAAO,MAAM,IAAI,GAAG,IAAI,QAAQ;AAEhC,UAAI,cAAc,GAAG;AACnB,oBAAY,IAAI,QAAQ,SAAS,GAAG,cAAc,oBAAoB,CAAC;AACvE,mBAAW,cAAc;AAAA,MAC3B;AAEA,eAAS,QAAQ,GAAG,QAAQ,QAAQ,SAAS;AAC3C,cAAM,MAAM,OAAO,KAAK;AACxB,cAAM,KAAK,cAAc,KAAK;AAC9B,cAAM,WAAW,WAAW,KAAK;AACjC,cAAM,OAAO,OAAO,KAAK;AACzB,YAAI,QAAQ,UAAa,IAAI,SAAS,GAAG;AACvC,mBAAS,gBAAgB;AACzB,eAAK,UAAU;AACf;AAAA,QACF;AACA,WAAG,OAAO,MAAM,IAAI,IAAI,IAAI,IAAI,EAAE;AAClC,WAAG,KAAK,MAAM,IAAI,IAAI,MAAM,IAAI,IAAI;AACpC,WAAG,QAAQ,QAAQ,IAAI,SAAS,KAAK;AACrC,WAAG,MAAM,QAAQ,IAAI;AACrB,WAAG,QAAQ,QAAQ,IAAI;AACvB,iBAAS,gBAAgB,IAAI;AAC7B,aAAK,UAAU;AAAA,MACjB;AAAA,IACF;AAAA,IACA,UAAU;AACR,iBAAW,KAAK,WAAY,GAAE,QAAQ;AACtC,iBAAW,KAAK,UAAW,GAAE,QAAQ;AAAA,IACvC;AAAA,EACF;AACF;;;AF9RA,SAAS,gBAAgB,MAAkB,MAAuC;AAChF,QAAM,SAAqB,EAAE,GAAG,MAAM,GAAG,KAAK;AAC9C,MAAI,KAAK,WAAW,OAAW,QAAO,SAAS,EAAE,GAAG,KAAK,QAAQ,GAAG,KAAK,OAAO;AAChF,SAAO;AACT;AAEO,SAAS,eAAe,UAA+B,CAAC,GAAG,OAAqB,CAAC,GAAa;AACnG,MAAI,MAAM,gBAAgB,qBAAqB,OAAO;AAEtD,QAAM,QAAQ,IAAIC,OAAM;AACxB,QAAM,UAA+B,kBAAkB,GAAG;AAC1D,QAAM,IAAI,QAAQ,IAAI;AACtB,MAAI,SAAoC;AAExC,QAAM,QAAQ,KAAK,SAAS,CAAC;AAC7B,QAAM,gBAAgB,IAAI,aAAa,qBAAqB,oBAAoB;AAChF,QAAM,cAAsB,CAAC;AAE7B,SAAO;AAAA,IACL,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,IAAI,OAAc,MAAkB;AAElC,YAAM,gBAAgB,MAAY;AAChC,cAAM,IAAI,cAAc,GAAG;AAC3B,YAAI,EAAE,WAAW,EAAE,WAAW,KAAK,gBAAgB,OAAW,MAAK;AAAA,MACrE;AACA,YAAM,gBAAgB,MAAY;AAChC,YAAI,cAAc,GAAG,EAAE,QAAS,MAAK;AAAA,MACvC;AACA,YAAM,SAAS,CAAC,MAAM,SAAS,gBAAgB,gBAAgB,aAAa,CAAC;AAC7E,iBAAW,UAAU,MAAO,QAAO,KAAK,OAAO,UAAU,OAAO,aAAa,CAAC;AAC9E,aAAO;AAAA,IACT;AAAA,IACA,QAAQ,OAAc,OAAoB;AACxC,YAAM,IAAI,cAAc,GAAG;AAC3B,UAAI,CAAC,EAAE,SAAS;AACd,gBAAQ,KAAK,UAAU;AACvB,YAAI,WAAW,KAAM,QAAO,MAAM,UAAU;AAC5C,gBAAQ,UAAU,KAAK;AACvB;AAAA,MACF;AACA,UAAI,WAAW,MAAM;AACnB,iBAAS,iBAAiB;AAC1B,cAAM,IAAI,OAAO,KAAK;AAAA,MACxB;AACA,cAAQ,KAAK,UAAU;AACvB,aAAO,MAAM,UAAU;AAEvB,YAAM,aAAa,iBAAiB,MAAM,OAAO,MAAM,EAAE,QAAQ;AACjE,kBAAY,SAAS;AACrB,UAAI,aAAa,GAAG;AAClB,mBAAW,UAAU,MAAO,aAAY,KAAK,GAAG,OAAO,KAAK,KAAK,CAAC;AAAA,MACpE;AACA,YAAM,cAAc;AAAA,QAClB;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,KAAK;AAAA,QACL;AAAA,MACF;AACA,YAAM,SAAS,oBAAoB,OAAO,GAAG;AAC7C,aAAO,OAAO,OAAO,KAAK,GAAG,QAAQ,eAAe,WAAW;AAAA,IACjE;AAAA,IACA,UAAU,MAAM;AACd,YAAM,gBAAgB,KAAK,IAAI;AAC/B,cAAQ,UAAU,GAAG;AAAA,IAGvB;AAAA,IACA,UAAU;AACR,cAAQ,QAAQ;AAChB,cAAQ,QAAQ;AAChB,eAAS;AAAA,IACX;AAAA,EACF;AACF;;;AMzGO,IAAM,SAAS,YAAY,CAAC,SAAS,CAAC;AACtC,IAAM,OAAO,YAAY,CAAC,UAAU,CAAC;AAErC,SAAS,cACd,OACA,OACA,SAA2B,4BAClB;AACT,QAAM,OAAO,IAAI,YAAY;AAC7B,QAAM,MAAM,MAAM;AAClB,QAAM,KAAK,OAAO;AAClB,QAAM,aAAmB,CAAC,OAAO,MAAM,CAAC,GAAG,OAAO,MAAM,CAAC,GAAG,OAAO,MAAM,CAAC,GAAG,OAAO,UAAU;AAC9F,QAAM,WAAiB,CAAC,OAAO,MAAM,CAAC,GAAG,OAAO,MAAM,CAAC,GAAG,OAAO,MAAM,CAAC,GAAG,OAAO,YAAY;AAE9F,QAAM,MAAM,MAAM,EAAE,KAAK,CAAC,MAAM;AAC9B,eAAW,KAAK,GAAG;AACjB,YAAM,IAAI,MAAM,KAAK,EAAE,OAAO,CAAC,GAAG,SAAS;AAC3C,YAAM,WAAW,EAAE,SAAS,EAAE;AAC9B,UAAI,EAAE,SAAS,KAAK;AAClB,cAAM,KAAK,cAAc,EAAE,IAAI,GAAG,GAAG,EAAE;AACvC,YAAI,MAAM,QAAQ,MAAM,KAAK,MAAM,KAAK,MAAM,QAAQ,GAAI;AAC1D,cAAM,KAAK,WAAW,IAAI,cAAc,GAAG,EAAE,MAAM,GAAG,EAAE;AACxD,cAAM,KAAK,WAAW,MAAM,SAAS,cAAc,GAAG,EAAE,IAAI,GAAG,EAAE;AACjE,aAAK,KAAK,KAAK,KAAK,GAAG,KAAK,IAAI,IAAI,EAAE,GAAG,IAAI,KAAK,IAAI,KAAK,EAAE,GAAG,UAAU;AAAA,MAC5E,OAAO;AACL,cAAM,KAAK,cAAc,GAAG,EAAE,IAAI,GAAG,EAAE;AACvC,YAAI,MAAM,SAAS,MAAM,KAAK,MAAM,KAAK,MAAM,SAAS,GAAI;AAC5D,cAAM,KAAK,WAAW,IAAI,cAAc,EAAE,MAAM,GAAG,GAAG,EAAE;AACxD,cAAM,KAAK,WAAW,MAAM,QAAQ,cAAc,EAAE,IAAI,GAAG,GAAG,EAAE;AAChE,aAAK,KAAK,KAAK,IAAI,IAAI,EAAE,GAAG,KAAK,KAAK,GAAG,KAAK,IAAI,KAAK,EAAE,GAAG,IAAI,UAAU;AAAA,MAC5E;AAAA,IACF;AAAA,EACF,CAAC;AAED,QAAM,MAAM,IAAI,EAAE,KAAK,CAAC,MAAM;AAC5B,eAAW,KAAK,GAAG;AACjB,YAAM,IAAI,MAAM,KAAK,EAAE,OAAO,CAAC,GAAG,UAAU;AAC5C,YAAM,IAAI,OAAO;AACjB,UAAI,EAAE,SAAS,KAAK;AAElB,cAAM,IAAI,cAAc,EAAE,MAAM,EAAE,MAAM,GAAG;AAC3C,cAAM,KAAK,cAAc,EAAE,IAAI,EAAE,MAAM,GAAG;AAC1C,YAAI,MAAM,QAAQ,MAAM,KAAK,IAAI,EAAE,GAAG,GAAG,CAAC,IAAI,KAAK,KAAK,IAAI,EAAE,GAAG,GAAG,CAAC,IAAI,MAAM,OAAQ;AACvF,aAAK,KAAK,KAAK,IAAI,EAAE,GAAG,GAAG,CAAC,GAAG,EAAE,IAAI,KAAK,GAAG,KAAK,IAAI,GAAG,IAAI,EAAE,CAAC,GAAG,IAAI,QAAQ;AAC/E,aAAK,KAAK,EAAE,IAAI,KAAK,GAAG,EAAE,IAAI,GAAG,IAAI,IAAI,GAAG,QAAQ;AACpD,aAAK,KAAK,GAAG,IAAI,KAAK,GAAG,GAAG,IAAI,GAAG,IAAI,IAAI,GAAG,QAAQ;AAAA,MACxD,OAAO;AACL,cAAM,IAAI,cAAc,EAAE,MAAM,EAAE,MAAM,GAAG;AAC3C,cAAM,KAAK,cAAc,EAAE,MAAM,EAAE,IAAI,GAAG;AAC1C,YAAI,MAAM,SAAS,MAAM,KAAK,IAAI,EAAE,GAAG,GAAG,CAAC,IAAI,KAAK,KAAK,IAAI,EAAE,GAAG,GAAG,CAAC,IAAI,MAAM,QAAS;AACzF,aAAK,KAAK,EAAE,IAAI,KAAK,GAAG,KAAK,IAAI,EAAE,GAAG,GAAG,CAAC,GAAG,IAAI,KAAK,IAAI,GAAG,IAAI,EAAE,CAAC,GAAG,QAAQ;AAC/E,aAAK,KAAK,EAAE,IAAI,GAAG,EAAE,IAAI,KAAK,GAAG,IAAI,GAAG,IAAI,QAAQ;AACpD,aAAK,KAAK,GAAG,IAAI,GAAG,GAAG,IAAI,KAAK,GAAG,IAAI,GAAG,IAAI,QAAQ;AAAA,MACxD;AAAA,IACF;AAAA,EACF,CAAC;AAED,SAAO,KAAK,MAAM;AACpB;;;ACvEA,SAAS,iBAAiB;AAC1B,SAAS,mBAAAC,kBAAiB,kBAAAC,iBAAgB,YAAY,QAAAC,OAAM,yBAAAC,8BAA6B;AASlF,SAAS,eAAe,aAA+B;AAC5D,QAAM,WAAW,IAAIA,uBAAsB;AAC3C,WAAS,eAAe,UAAU,SAAS,MAAM;AACjD,WAAS,cAAc;AACvB,WAAS,YAAY;AACrB,WAAS,aAAa;AAItB,WAAS,OAAO;AAEhB,MAAI,WAAW,IAAIF,gBAAe;AAClC,MAAI,WAAW;AACf,QAAM,OAAO,IAAIC,MAAK,UAAU,QAAQ;AACxC,OAAK,gBAAgB;AACrB,OAAK,cAAc;AACnB,OAAK,UAAU;AAEf,SAAO;AAAA,IACL;AAAA,IACA,OAAO,MAAM;AACX,UAAI,KAAK,gBAAgB,GAAG;AAC1B,aAAK,UAAU;AACf,iBAAS,aAAa,GAAG,CAAC;AAC1B;AAAA,MACF;AACA,UAAI,KAAK,cAAc,UAAU;AAC/B,mBAAW,KAAK,IAAI,KAAK,aAAa,WAAW,GAAG,GAAG;AACvD,cAAM,MAAM;AACZ,mBAAW,IAAID,gBAAe;AAC9B,cAAM,MAAM,IAAI,aAAa,WAAW,CAAC;AACzC,cAAM,MAAM,IAAI,aAAa,WAAW,CAAC;AACzC,YAAI,IAAI,KAAK,SAAS;AACtB,YAAI,IAAI,KAAK,MAAM;AACnB,iBAAS,aAAa,YAAY,IAAID,iBAAgB,KAAK,CAAC,CAAC;AAC7D,iBAAS,aAAa,SAAS,IAAIA,iBAAgB,KAAK,CAAC,CAAC;AAC1D,aAAK,WAAW;AAChB,YAAI,QAAQ;AAAA,MACd,OAAO;AACL,cAAM,MAAM,SAAS,aAAa,UAAU;AAC5C,cAAM,MAAM,SAAS,aAAa,OAAO;AACzC,QAAC,IAAI,MAAuB,IAAI,KAAK,SAAS;AAC9C,QAAC,IAAI,MAAuB,IAAI,KAAK,MAAM;AAC3C,YAAI,cAAc;AAClB,YAAI,cAAc;AAAA,MACpB;AACA,eAAS,aAAa,GAAG,KAAK,WAAW;AACzC,WAAK,UAAU;AAAA,IACjB;AAAA,IACA,UAAU;AACR,eAAS,QAAQ;AACjB,eAAS,QAAQ;AAAA,IACnB;AAAA,EACF;AACF;;;AC5DO,SAAS,iBAAiB,UAAqC,CAAC,GAAe;AACpF,QAAM,SAA2B,EAAE,GAAG,4BAA4B,GAAG,QAAQ;AAC7E,QAAM,OAAO,eAAe,CAAC;AAE7B,SAAO;AAAA,IACL,MAAM;AAAA,IACN,QAAQ,KAAK;AAAA,IACb,IAAI,OAAc,MAAkB;AAClC,aAAO;AAAA,QACL,MAAM,SAAS,aAAa,QAAQ,MAAM,EAAE,MAAM,CAAC,SAAS,EAAE,CAAC;AAAA,QAC/D,MAAM,SAAS,aAAa,MAAM,MAAM,EAAE,MAAM,CAAC,UAAU,EAAE,CAAC;AAAA,MAChE;AAAA,IACF;AAAA,IACA,QAAQ,OAAc,OAAoB;AACxC,WAAK,OAAO,cAAc,OAAO,OAAO,MAAM,CAAC;AAAA,IACjD;AAAA,IACA,UAAU;AACR,WAAK,QAAQ;AAAA,IACf;AAAA,EACF;AACF;;;ACCO,SAAS,gBACd,UAAgC,CAAC,GACjC,aACY;AACZ,QAAM,SAAsB,EAAE,GAAG,sBAAsB,GAAG,QAAQ;AAClE,QAAM,OAAO,eAAe,CAAC;AAE7B,SAAO;AAAA,IACL,MAAM;AAAA,IACN,QAAQ,KAAK;AAAA,IACb,IAAI,OAAc,MAAkB;AAClC,aAAO;AAAA,QACL,MAAM,SAAS,aAAa,OAAO,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC;AAAA,QACrD,MAAM,SAAS,aAAa,WAAW,MAAM,EAAE,MAAM,CAAC,UAAU,IAAI,EAAE,CAAC;AAAA;AAAA;AAAA,QAGvE,MAAM,SAAS,aAAa,WAAW,MAAM,EAAE,MAAM,CAAC,YAAY,EAAE,CAAC;AAAA,QACrE,MAAM,SAAS,aAAa,WAAW,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC;AAAA;AAAA;AAAA,QAGzD,MAAM,SAAS,aAAa,SAAS,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC;AAAA,QACvD,MAAM,SAAS,aAAa,OAAO,MAAM,EAAE,MAAM,CAAC,UAAU,EAAE,CAAC;AAAA,QAC/D,MAAM,SAAS,aAAa,gBAAgB,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC;AAAA,QAC9D,MAAM,SAAS,aAAa,cAAc,MAAM,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC;AAAA,MAClE;AAAA,IACF;AAAA,IACA,QAAQ,OAAc,OAAoB;AACxC,WAAK,OAAO,aAAa,OAAO,OAAO,QAAQ,cAAc,CAAC,CAAC;AAAA,IACjE;AAAA,IACA,UAAU;AACR,WAAK,QAAQ;AAAA,IACf;AAAA,EACF;AACF;;;ACpDA,SAAS,sBAAsB;AAexB,SAAS,qBACd,KACA,OAAiC,CAAC,GACd;AACpB,QAAM,SAAS,IAAI,cAAc,QAAQ;AACzC,MAAI,WAAkC;AACtC,MAAI,UAAU;AACd,MAAI,WAAW;AACf,QAAM,WAA8B,CAAC;AAQrC,QAAM,MAAO,WAAW,WAA6C;AACrE,MAAI,OAAO,QAAQ,KAAK,eAAe,MAAM;AAC3C,QAAI,MAAe;AACnB,QAAI;AACF,YAAM,IAAI,cAAc,QAAQ,EAAE,WAAW,QAAQ;AAAA,IACvD,QAAQ;AACN,YAAM;AAAA,IACR;AACA,QAAI,QAAQ,KAAM,YAAW;AAAA,EAC/B;AAEA,MAAI,CAAC,UAAU;AACb,QAAI;AACF,iBAAW,IAAI,eAAe;AAAA,QAC5B;AAAA,QACA,OAAO;AAAA;AAAA,QACP,WAAW;AAAA,QACX,GAAI,KAAK,eAAe,OAAO,EAAE,YAAY,KAAK,IAAI,CAAC;AAAA,MACzD,CAAC;AACD,eACG,KAAK,EACL,KAAK,MAAM;AACV,kBAAU;AACV,mBAAW,MAAM,SAAS,OAAO,CAAC,EAAG,IAAG;AAAA,MAC1C,CAAC,EACA,MAAM,MAAM;AACX,mBAAW;AAAA,MACb,CAAC;AAAA,IACL,QAAQ;AACN,iBAAW;AAAA,IACb;AAAA,EACF;AAEA,MAAI,QAAQ;AACZ,MAAI,QAAQ;AACZ,MAAI,UAAU;AAEd,SAAO;AAAA,IACL;AAAA,IACA,OAAO,MAAM;AAAA,IACb,QAAQ,MAAM;AAAA,IACd,QAAQ,IAAI;AACV,UAAI,QAAS,IAAG;AAAA,UACX,UAAS,KAAK,EAAE;AAAA,IACvB;AAAA,IACA,QAAQ,MAAM,MAAM,KAAK;AACvB,UAAI,aAAa,QAAS,SAAS,SAAS,SAAS,SAAS,QAAQ,QAAU;AAChF,cAAQ;AACR,cAAQ;AACR,gBAAU;AACV,UAAI;AACF,iBAAS,cAAc,GAAG;AAE1B,iBAAS,QAAQ,KAAK,IAAI,GAAG,IAAI,GAAG,KAAK,IAAI,GAAG,IAAI,GAAG,KAAK;AAAA,MAC9D,QAAQ;AACN,mBAAW;AAAA,MACb;AAAA,IACF;AAAA,IACA,OAAO,OAAO,QAAQ;AACpB,UAAI,aAAa,QAAQ,CAAC,WAAW,SAAU;AAC/C,UAAI;AACF,iBAAS,OAAO,OAAO,MAAM;AAAA,MAC/B,QAAQ;AACN,mBAAW;AAAA,MACb;AAAA,IACF;AAAA,IACA,UAAU;AACR,UAAI;AACF,kBAAU,QAAQ;AAAA,MACpB,QAAQ;AAAA,MAER;AACA,iBAAW;AAAA,IACb;AAAA,EACF;AACF;;;AC7EA,IAAM,gBAAgB,YAAY,CAAC,SAAS,cAAc,YAAY,CAAC;AAOhE,SAAS,kBAAkB,OAAuC,CAAC,GAAe;AACvF,QAAM,WAAW,KAAK,YAAY;AAClC,SAAO;AAAA,IACL,KAAK,OAAO;AACV,YAAM,MAAc,CAAC;AACrB,YAAM,MAAM,aAAa,EAAE,KAAK,CAAC,MAAM;AACrC,mBAAW,KAAK,GAAG;AACjB,gBAAM,IAAI,MAAM,KAAK,EAAE,OAAO,CAAC,GAAG,YAAY;AAC9C,cAAI,KAAK,EAAE,GAAG,EAAE,GAAG,GAAG,EAAE,GAAG,UAAU,OAAO,QAAQ,CAAC;AAAA,QACvD;AAAA,MACF,CAAC;AACD,aAAO;AAAA,IACT;AAAA,IACA,UAAU,OAAO,MAAM;AACrB,aAAO,MAAM,SAAS,aAAa,eAAe,MAAM,EAAE,MAAM,CAAC,YAAY,EAAE,CAAC;AAAA,IAClF;AAAA,EACF;AACF;AAEA,IAAM,gBAAgB,YAAY,CAAC,UAAU,YAAY,CAAC;AAOnD,SAAS,kBAAkB,OAAuC,CAAC,GAAe;AACvF,QAAM,WAAW,KAAK,YAAY;AAClC,SAAO;AAAA,IACL,KAAK,OAAO;AACV,YAAM,MAAc,CAAC;AACrB,YAAM,MAAM,aAAa,EAAE,KAAK,CAAC,MAAM;AACrC,mBAAW,KAAK,GAAG;AACjB,gBAAM,IAAI,MAAM,KAAK,EAAE,OAAO,CAAC,GAAG,QAAQ;AAC1C,cAAI,KAAK,EAAE,GAAG,EAAE,GAAG,GAAG,EAAE,GAAG,UAAU,OAAO,QAAQ,CAAC;AAAA,QACvD;AAAA,MACF,CAAC;AACD,aAAO;AAAA,IACT;AAAA,IACA,UAAU,OAAO,MAAM;AACrB,aAAO,MAAM,SAAS,aAAa,eAAe,MAAM,EAAE,MAAM,CAAC,QAAQ,EAAE,CAAC;AAAA,IAC9E;AAAA,EACF;AACF;;;ACKO,SAAS,OAAO,OAAsB,CAAC,GAAkB;AAC9D,SAAO,CAAC,QAAQ;AACd,UAAM,MAAM,IAAI,KAAK,UAAU;AAC/B,UAAM,WAAW,KAAK,oBAAoB,qBAAqB,KAAK,EAAE,YAAY,KAAK,eAAe,KAAK,CAAC;AAC5G,UAAM,QAAQ,KAAK,UAAU,SAAY,CAAC,IAAI,MAAM,QAAQ,KAAK,KAAK,IAAI,KAAK,QAAQ,CAAC,KAAK,KAAK;AAClG,UAAM,OAAO,eAAe,KAAK,QAAQ,CAAC,GAAG,EAAE,OAAO,GAAI,IAAI,gBAAgB,SAAY,EAAE,aAAa,IAAI,YAAY,IAAI,CAAC,EAAG,CAAC;AAClI,UAAM,QAAQ,gBAAgB,KAAK,SAAS,CAAC,GAAG,IAAI,eAAe;AACnE,UAAM,SAAS,iBAAiB,KAAK,UAAU,CAAC,CAAC;AACjD,UAAM,SAAuB,CAAC,MAAM,OAAO,QAAQ,GAAI,KAAK,UAAU,CAAC,CAAE;AACzE,UAAM,QAAQ,YAAY,IAAI,MAAM,IAAI,OAAO,UAAU,MAAM;AAC/D,WAAO;AAAA,MACL,WAAW,MAAM;AAAA,MACjB,cAAc,KAAK;AACjB,aAAK,UAAU,GAAG;AAClB,cAAM,cAAc;AAAA,MACtB;AAAA,MACA,SAAS,MAAM;AAAA,IACjB;AAAA,EACF;AACF;","names":["Group","clamp","float","length","max","min","mix","positionGeometry","smoothstep","uniform","vec4","BufferAttribute","Mesh","MeshBasicNodeMaterial","Vector2","Vector3","uniform","Vector2","Vector3","float","length","max","min","clamp","positionGeometry","mix","vec4","smoothstep","MeshBasicNodeMaterial","BufferAttribute","Mesh","Group","BufferAttribute","BufferGeometry","Mesh","MeshBasicNodeMaterial"]}
|
|
1
|
+
{"version":3,"sources":["../../ground/src/layer.ts","../../ground/src/passes/grid-contract.ts","../../ground/src/passes/grid-magnet.ts","../../ground/src/passes/soup-collect.ts","../../ground/src/passes/wires-collect.ts","../../ground/src/passes/magnet-collect.ts","../../ground/src/passes/grid-magnet-pass.ts","../../ground/src/passes/guides-collect.ts","../../ground/src/passes/soup-mesh.ts","../../ground/src/passes/guides.ts","../../ground/src/passes/wires.ts","../../ground/src/renderer.ts","../../ground/src/poles.ts","../../ground/src/index.ts"],"sourcesContent":["/**\n * The ground LAYER — one reflector, one canvas, one render (design-004 §1\n * as-built 2026-07-16: P0 consolidated from three stacked canvases into a\n * single WebGPU canvas; grid, wires and snap-guides are now PASSES of this\n * layer, and future ground effects join the same registry).\n *\n * Coordinate model: the layer renders in SCREEN CSS-px space — an ortho\n * camera maps [0..w]×[0..h] (y-down) to clip, and passes build their geometry\n * through the kernel `worldToScreen` seam per collect (the proven 2D-canvas\n * semantics: geometry rebuilds on the same dirt that re-stroked the old\n * canvases; the grid stays a per-pixel screen-space shader). The Y-flip\n * question never arises here — `worldToScreen` IS the one conversion (L13).\n *\n * Reflector contract (design-002 §5): post-notify, output-only, never reads\n * layout in flush (the ResizeObserver owns sizing), never writes ECS.\n * `always: true` with a private dirty union — an idle scene renders zero\n * frames; ANY dirty pass re-renders the whole canvas (one draw, same cost\n * class as a pan frame under the old grid). WebGPU init is async: flushes\n * before ready are deferred (flags stay armed), the first ready flush paints.\n */\nimport { Camera, type ReflectorDef, type World } from \"@ice/core\";\nimport { OrthographicCamera, Scene } from \"three/webgpu\";\nimport type { GroundFrame, GroundPass } from \"./pass\";\nimport type { GroundRendererLike } from \"./renderer\";\n\nexport interface GroundLayerHost {\n readonly container: HTMLElement;\n readonly contentPlane: HTMLElement;\n}\n\nexport interface GroundReflector extends ReflectorDef {\n /** False while init is pending or after a device/context failure. */\n available(): boolean;\n /** Whole-canvas renders so far (the churn instrument — 0 on an idle scene). */\n redraws(): number;\n}\n\nexport interface GroundLayerInternals {\n reflector: GroundReflector;\n /** Wake every pass + render (config changes, external invalidation). */\n invalidateAll(): void;\n dispose(): void;\n}\n\nexport function createLayer(\n host: GroundLayerHost,\n world: World,\n renderer: GroundRendererLike,\n passes: readonly GroundPass[],\n): GroundLayerInternals {\n const doc = host.container.ownerDocument;\n const canvas = renderer.canvas;\n canvas.style.position = \"absolute\";\n canvas.style.left = \"0\";\n canvas.style.top = \"0\";\n canvas.style.width = \"100%\";\n canvas.style.height = \"100%\";\n canvas.style.display = \"block\";\n // P0 is never a DOM hit target (the router owns picking, design-004 §4).\n canvas.style.pointerEvents = \"none\";\n // The whole ground stratum is this ONE canvas, immediately before content.\n host.container.insertBefore(canvas, host.contentPlane);\n\n const scene = new Scene();\n // Screen-px ortho, y-down: (0,0) = top-left, (w,h) = bottom-right.\n const camera = new OrthographicCamera(0, 1, 0, 1, -1000, 1000);\n for (const pass of passes) scene.add(pass.object);\n\n // --- dirt ------------------------------------------------------------------\n const dirty = new Map<GroundPass, boolean>();\n for (const pass of passes) dirty.set(pass, true);\n let anyDirty = true;\n const wakeAll = (): void => {\n for (const pass of passes) dirty.set(pass, true);\n anyDirty = true;\n };\n const unsubs: Array<() => void> = [\n // Camera moves re-map every pass's screen-space geometry (2D-canvas parity).\n world.reactive.observeResource(Camera, wakeAll),\n ];\n for (const pass of passes) {\n unsubs.push(\n ...pass.arm(world, () => {\n dirty.set(pass, true);\n anyDirty = true;\n }),\n );\n }\n renderer.onReady(wakeAll); // the deferred pre-ready flushes are owed one paint\n\n // --- sizing (RO owns layout reads — never the flush) -----------------------\n let cssW = 0;\n let cssH = 0;\n let dpr = 1;\n const applySize = (w: number, h: number): void => {\n dpr = doc.defaultView?.devicePixelRatio ?? 1;\n cssW = w;\n cssH = h;\n renderer.setSize(w, h, dpr);\n camera.left = 0;\n camera.right = Math.max(1, w);\n camera.top = 0;\n camera.bottom = Math.max(1, h);\n camera.updateProjectionMatrix();\n wakeAll();\n };\n const initialRect = host.container.getBoundingClientRect();\n applySize(initialRect.width, initialRect.height);\n let ro: ResizeObserver | null = null;\n try {\n ro = new ResizeObserver((entries) => {\n const entry = entries[0];\n if (entry === undefined) return;\n applySize(entry.contentRect.width, entry.contentRect.height);\n });\n ro.observe(host.container);\n } catch {\n ro = null;\n }\n\n let redraws = 0;\n\n const reflector: GroundReflector = {\n name: \"ground\",\n // Self-gated on the dirty union (wires/chrome precedent) — the every-frame\n // cost is one boolean check.\n always: true,\n flush(w: World) {\n if (!anyDirty || renderer.failed()) return;\n if (!renderer.ready()) return; // init pending — flags stay armed, retry next frame\n const cam = w.getResource(Camera);\n if (cam === undefined) return;\n anyDirty = false;\n const frame: GroundFrame = { width: cssW, height: cssH, dpr, camera: cam };\n for (const pass of passes) {\n if (dirty.get(pass) === true) {\n dirty.set(pass, false);\n pass.collect(w, frame);\n }\n }\n redraws++;\n renderer.render(scene, camera);\n },\n available: () => renderer.ready() && !renderer.failed(),\n redraws: () => redraws,\n };\n\n return {\n reflector,\n invalidateAll: wakeAll,\n dispose() {\n for (const u of unsubs) u();\n unsubs.length = 0;\n ro?.disconnect();\n ro = null;\n for (const pass of passes) pass.dispose();\n renderer.dispose();\n canvas.remove();\n },\n };\n}\n","/**\n * Shared contract for build-time-selectable grid implementations.\n *\n * Both classic and magnet factories accept the same config and dependency\n * shape. `grid.ts` wires exactly one factory into the production entry graph,\n * so selecting an implementation is an import change, never a runtime mode.\n */\nimport { DEFAULT_GRID_CONFIG, type GridConfig } from \"@ice/core\";\nimport type { GroundPass } from \"../pass\";\nimport type { PoleSource } from \"../poles\";\nimport type { ReadSpatial } from \"./magnet-collect\";\n\nexport interface GridPass extends GroundPass {\n /** Live re-tune (the react `grid` prop seam) — partial merge over current values. */\n configure(cfg: Partial<GridConfig>): void;\n}\n\n/**\n * Superset of implementation dependencies. Classic deliberately ignores\n * these; magnet consumes them. Keeping one signature makes the wired factory\n * interchangeable without changing its parent.\n */\nexport interface GridPassDeps {\n readonly poles?: readonly PoleSource[];\n readonly readSpatial?: ReadSpatial;\n}\n\nexport type GridPassFactory = (initial?: Partial<GridConfig>, deps?: GridPassDeps) => GridPass;\n\n/** Shallow grid merge + one-level merge of the optional magnet tuning block. */\nexport function mergeGridConfig(base: GridConfig, next: Partial<GridConfig>): GridConfig {\n const merged: GridConfig = { ...base, ...next };\n if (next.magnet !== undefined) merged.magnet = { ...base.magnet, ...next.magnet };\n return merged;\n}\n\nexport function resolveInitialGridConfig(initial: Partial<GridConfig>): GridConfig {\n return mergeGridConfig(DEFAULT_GRID_CONFIG, initial);\n}\n","/**\n * The MAGNET grid renderer — TSL port of vibe-field draft/magnet-grid's\n * `magnet.wgsl` (design-010 §5). Three instanced-quad meshes (one per lattice\n * level) whose vertex stage reconstructs sites from `instanceIndex`, evaluates\n * the field (superposition of rounded-box SDF sources; poles are DEGENERATE\n * boxes with half = 0, r = 0 — D3), and shapes the glyph (needle orients\n * along the field; dot swells with |field|).\n *\n * Deltas from the WGSL, per design-010:\n * - ONE source buffer (storage, read-only, `setPBO` for the WebGL fallback —\n * D4); the mouse uniform / `mouseOn` branch are deleted.\n * - fade ladder, level weight and dotAlpha are CPU-baked into ONE per-level\n * alpha (they are per-level constants per frame — magnet-collect owns them).\n * - dot rest radius comes from `GridConfig.dotRadius[0]` (shared config\n * continuity), not the WGSL's hardcoded `halfLen·0.16`.\n * - coincidence skip (§5.4): sites shared with a visible coarser level drop\n * out (integer spacing ratios), replicating the classic max-composite look.\n * - NDC is computed from CSS-px directly (the WGSL path) — glyph sizes are\n * CSS px, DPR rides the viewport; the layer's ortho camera is bypassed.\n */\nimport type { GridConfig, GridMagnetConfig } from \"@ice/core\";\nimport {\n Fn,\n If,\n Loop,\n abs,\n clamp,\n float,\n instanceIndex,\n int,\n length,\n max,\n min,\n mix,\n mod,\n positionGeometry,\n select,\n sign,\n smoothstep,\n sqrt,\n storage,\n uniform,\n varying,\n vec2,\n vec4,\n Continue,\n Discard,\n} from \"three/tsl\";\nimport {\n BufferAttribute,\n Group,\n InstancedBufferGeometry,\n Mesh,\n MeshBasicNodeMaterial,\n StorageBufferAttribute,\n Vector2,\n Vector3,\n type Node,\n} from \"three/webgpu\";\nimport type { GroundFrame } from \"../pass\";\nimport { MAGNET_SOURCE_FLOATS, MAX_MAGNET_SOURCES, type MagnetLevel } from \"./magnet-collect\";\n\n/** Unit quad corners, 2 triangles (xy in [-1,1]; z unused — vec3 for positionGeometry). */\nconst CORNERS = new Float32Array([-1, -1, 0, 1, -1, 0, 1, 1, 0, -1, -1, 0, 1, 1, 0, -1, 1, 0]);\n\nconst LEVELS = 3;\n\nexport interface MagnetGridRenderer {\n readonly group: Group;\n /** Rewrite every uniform + the source buffer from this frame's collect. */\n update(\n frame: GroundFrame,\n cfg: GridConfig,\n magnet: GridMagnetConfig,\n levels: readonly MagnetLevel[],\n sources: Float32Array,\n sourceCount: number,\n ): void;\n dispose(): void;\n}\n\nexport function createMagnetGrid(): MagnetGridRenderer {\n // --- shared state (one copy across the three level materials) --------------\n const sourceArray = new Float32Array(MAX_MAGNET_SOURCES * MAGNET_SOURCE_FLOATS);\n const sourceAttr = new StorageBufferAttribute(sourceArray, 4);\n // Read-only storage; PBO keeps the WebGL2 fallback functional (D4).\n const sourceBuf = storage(sourceAttr, \"vec4\", MAX_MAGNET_SOURCES * 2)\n .setPBO(true)\n .toReadOnly();\n\n const uCam = uniform(new Vector2(0, 0));\n const uZoom = uniform(1);\n const uView = uniform(new Vector2(1, 1));\n const uDotMode = uniform(0);\n const uHalfLen = uniform(5);\n const uHalfWidth = uniform(0.55);\n const uRestRadius = uniform(0.75);\n const uK = uniform(0);\n const uPad = uniform(0); // √(k/0.02) — the shader-side AABB reject cutoff\n const uPolarity = uniform(1);\n const uAlwaysAlign = uniform(0);\n const uCount = uniform(0, \"int\");\n const uColor = uniform(new Vector3(0.75, 0.77, 0.8));\n\n const EPS = float(25); // magnet.wgsl uniform slot 21 — fixed there too\n const REST = vec2(0, 1); // rest direction: hang \"down\" in y-down screen space\n\n // IQ rounded box; p local (site − center), b half-size, r corner radius.\n const sdRoundBox = Fn(([p, b, r]: [Node<\"vec2\">, Node<\"vec2\">, Node<\"float\">]) => {\n const q = abs(p).sub(b).add(vec2(r, r));\n return length(max(q, vec2(0, 0)))\n .add(min(max(q.x, q.y), 0))\n .sub(r);\n });\n\n // Outward unit normal of the same box (analytic — magnet.wgsl:64-80).\n const roundBoxNormal = Fn(([p, b, r]: [Node<\"vec2\">, Node<\"vec2\">, Node<\"float\">]) => {\n const s = sign(p);\n const q = abs(p);\n const inner = max(b.sub(vec2(r, r)), vec2(0, 0));\n const d = q.sub(inner);\n const n = vec2(0, 0).toVar();\n If(d.x.greaterThan(0).and(d.y.greaterThan(0)), () => {\n const len = length(d);\n If(len.greaterThan(0.0001), () => {\n n.assign(s.mul(d.div(len)));\n }).Else(() => {\n n.assign(vec2(s.x, 0));\n });\n })\n .ElseIf(d.x.greaterThan(d.y), () => {\n n.assign(vec2(s.x, 0));\n })\n .Else(() => {\n n.assign(vec2(0, s.y));\n });\n return n;\n });\n\n const safeNormalize = Fn(([v, fallback]: [Node<\"vec2\">, Node<\"vec2\">]) => {\n const n = length(v);\n return select(n.greaterThan(0.0001), v.div(max(n, 0.0001)), fallback);\n });\n\n const group = new Group();\n const geometries: InstancedBufferGeometry[] = [];\n const materials: MeshBasicNodeMaterial[] = [];\n const meshes: Mesh[] = [];\n const levelUniforms = Array.from({ length: LEVELS }, () => ({\n origin: uniform(new Vector2(0, 0)),\n dims: uniform(new Vector2(1, 1)),\n spacing: uniform(20),\n alpha: uniform(0),\n skipMod: uniform(0),\n }));\n\n for (let level = 0; level < LEVELS; level++) {\n const lu = levelUniforms[level] as (typeof levelUniforms)[number];\n\n const vUv = varying(vec2(0, 0), `vMagnetUv${level}`);\n const vAlpha = varying(float(0), `vMagnetAlpha${level}`);\n\n const vertexNode = Fn(() => {\n const iid = float(instanceIndex);\n const cols = lu.dims.x;\n // .toVar() pins site reconstruction to the stack BEFORE the source loop:\n // the builder emits expressions at first USE — inside the loop body — so\n // a zero-source frame (fadeZoom valve, no poles, widgets off) would\n // otherwise leave every position at the default-initialized origin and\n // blank the rest lattice (design-010 §10.9).\n const col = mod(iid, cols).floor().toVar();\n const row = iid.div(cols).floor().toVar();\n const world = lu.origin.add(vec2(col, row)).mul(lu.spacing);\n const screen = world.sub(uCam).mul(uZoom).toVar();\n\n // Field superposition over the source buffer (magnet.wgsl field_at).\n const field = vec2(0, 0).toVar();\n const minD = float(1e9).toVar();\n Loop({ start: int(0), end: uCount, type: \"int\", condition: \"<\" }, ({ i }) => {\n const a = sourceBuf.element(i.mul(2)); // cx, cy, hx, hy\n const b = sourceBuf.element(i.mul(2).add(1)); // r, strength, 0, 0\n const center = a.xy;\n const half = a.zw;\n const rad = b.x;\n const strength = b.y;\n const rel = screen.sub(center);\n const reach = uPad.mul(sqrt(max(strength, 0.0001)));\n If(\n abs(rel.x)\n .greaterThan(half.x.add(reach))\n .or(abs(rel.y).greaterThan(half.y.add(reach))),\n () => {\n Continue();\n },\n );\n const d = sdRoundBox(rel, half, rad);\n minD.assign(min(minD, d));\n const dist = max(d, 0);\n const r2 = dist.mul(dist).add(EPS);\n const outward = roundBoxNormal(rel, half, rad);\n // Attract toward the body = against the outward normal.\n field.subAssign(outward.mul(uK.mul(strength).mul(uPolarity).div(r2)));\n });\n\n const fieldDir = safeNormalize(field, REST);\n const mag = length(field);\n // Needles want a hard 0–1 blend; dots want the softer 1/r² size curve\n // (saturate plateaus at ~100px and every nearby site looks identical).\n const influence = select(uDotMode.greaterThan(0.5), mag.div(mag.add(1)), clamp(mag, 0, 1));\n\n const corner = positionGeometry.xy;\n // Dot: size encodes |field| — far sites rest at the classic dot radius.\n const dotRadius = mix(uRestRadius, uHalfLen.mul(1.05), influence);\n // The screen→NDC conversion below flips Y. Reflect this symmetric glyph\n // locally as well so its triangles stay CCW under FrontSide culling. The\n // needle basis is already a reflection (det < 0), so it needs no flip.\n const dotLocal = vec2(corner.x, corner.y.negate()).mul(dotRadius);\n // Needle: orient along the field (or rest-blended), length/width as cues.\n const dir = select(\n uAlwaysAlign.greaterThan(0.5),\n fieldDir,\n safeNormalize(mix(REST, fieldDir, influence), REST),\n );\n const nrm = vec2(dir.y.negate(), dir.x);\n const nLen = mix(uHalfLen.mul(0.55), uHalfLen.mul(1.35), influence);\n const nWid = mix(uHalfWidth.mul(0.85), uHalfWidth.mul(1.15), influence);\n const needleLocal = nrm.mul(corner.x).mul(nWid).add(dir.mul(corner.y).mul(nLen));\n const local = select(uDotMode.greaterThan(0.5), dotLocal, needleLocal);\n const pos = screen.add(local);\n\n // Needles use alpha as a second cue; dots keep alpha steadier so size reads first.\n const restAlpha = select(uDotMode.greaterThan(0.5), float(0.72), float(0.35));\n const fieldAlpha = mix(restAlpha, float(1), influence);\n const alpha = clamp(lu.alpha.mul(fieldAlpha), 0, 1).toVar();\n // Hide glyphs under a source body — the widget already covers them.\n If(minD.lessThan(-0.5), () => {\n alpha.assign(0);\n });\n // Coincidence skip (§5.4): absolute lattice index ≡ 0 (mod ratio) on both\n // axes belongs to the visible coarser level (mod() is non-negative).\n const absI = lu.origin.x.add(col);\n const absJ = lu.origin.y.add(row);\n If(\n lu.skipMod\n .greaterThan(0.5)\n .and(mod(absI, lu.skipMod).lessThan(0.5))\n .and(mod(absJ, lu.skipMod).lessThan(0.5)),\n () => {\n alpha.assign(0);\n },\n );\n\n vUv.assign(corner);\n vAlpha.assign(alpha);\n\n const ndc = vec2(\n pos.x.div(uView.x).mul(2).sub(1),\n float(1).sub(pos.y.div(uView.y).mul(2)),\n );\n return vec4(ndc, 0, 1);\n })();\n\n const fragmentNode = Fn(() => {\n const dotEdge = float(1).sub(smoothstep(0.62, 1.0, length(vUv)));\n const ax = float(1).sub(smoothstep(0.55, 1.0, abs(vUv.x)));\n const ay = float(1).sub(smoothstep(0.82, 1.0, abs(vUv.y)));\n const edge = select(uDotMode.greaterThan(0.5), dotEdge, ax.mul(ay));\n const a = vAlpha.mul(edge);\n Discard(a.lessThan(0.01));\n return vec4(uColor, a);\n })();\n\n const material = new MeshBasicNodeMaterial();\n material.vertexNode = vertexNode;\n material.fragmentNode = fragmentNode;\n material.transparent = true;\n material.depthTest = false;\n material.depthWrite = false;\n\n const geometry = new InstancedBufferGeometry();\n geometry.setAttribute(\"position\", new BufferAttribute(CORNERS, 3));\n geometry.instanceCount = 0;\n\n const mesh = new Mesh(geometry, material);\n mesh.frustumCulled = false;\n mesh.renderOrder = 0;\n mesh.visible = false;\n\n geometries.push(geometry);\n materials.push(material);\n meshes.push(mesh);\n group.add(mesh);\n }\n\n return {\n group,\n update(frame, cfg, magnet, levels, sources, sourceCount) {\n uCam.value.set(frame.camera.x, frame.camera.y);\n uZoom.value = frame.camera.zoom;\n uView.value.set(Math.max(1, frame.width), Math.max(1, frame.height));\n uDotMode.value = magnet.glyph === \"dot\" ? 1 : 0;\n uHalfLen.value = magnet.needleLength;\n uHalfWidth.value = magnet.needleWidth;\n uRestRadius.value = cfg.dotRadius[0];\n const k = 0.5 * magnet.reach * magnet.reach;\n uK.value = k;\n uPad.value = Math.sqrt(Math.max(k, 1) / 0.02);\n uPolarity.value = magnet.polarity;\n uAlwaysAlign.value = magnet.alwaysAlign ? 1 : 0;\n uCount.value = sourceCount;\n uColor.value.set(...cfg.dotColor);\n\n if (sourceCount > 0) {\n sourceArray.set(sources.subarray(0, sourceCount * MAGNET_SOURCE_FLOATS));\n sourceAttr.needsUpdate = true;\n }\n\n for (let level = 0; level < LEVELS; level++) {\n const win = levels[level];\n const lu = levelUniforms[level] as (typeof levelUniforms)[number];\n const geometry = geometries[level] as InstancedBufferGeometry;\n const mesh = meshes[level] as Mesh;\n if (win === undefined || win.count <= 0) {\n geometry.instanceCount = 0;\n mesh.visible = false;\n continue;\n }\n lu.origin.value.set(win.i0, win.j0);\n lu.dims.value.set(win.cols, win.rows);\n lu.spacing.value = cfg.spacings[level] as number;\n lu.alpha.value = win.alpha;\n lu.skipMod.value = win.skipModulo;\n geometry.instanceCount = win.count;\n mesh.visible = true;\n }\n },\n dispose() {\n for (const g of geometries) g.dispose();\n for (const m of materials) m.dispose();\n },\n };\n}\n","/**\n * Triangle-soup builders — the PURE half of the geometry passes (no three\n * import; unit-tested under happy-dom). Collectors emit screen-px triangles\n * with per-vertex rgba into a growable soup; the three-side `soup-mesh`\n * uploads them. MSAA (renderer antialias) smooths edges, matching the old 2D\n * canvases' stroke AA closely enough at 1–2 px widths.\n */\n\nexport interface TriSoup {\n /** xyz per vertex (z = 0 — the layer renders flat in screen space). */\n positions: Float32Array;\n /** rgba per vertex, 0-1. */\n colors: Float32Array;\n vertexCount: number;\n}\n\nexport type Rgba = readonly [number, number, number, number];\n\nexport class SoupBuilder {\n private pos: number[] = [];\n private col: number[] = [];\n\n private vert(x: number, y: number, c: Rgba): void {\n this.pos.push(x, y, 0);\n this.col.push(c[0], c[1], c[2], c[3]);\n }\n\n /** Axis-aligned rect (two triangles). */\n rect(x: number, y: number, w: number, h: number, c: Rgba): void {\n this.vert(x, y, c);\n this.vert(x + w, y, c);\n this.vert(x + w, y + h, c);\n this.vert(x, y, c);\n this.vert(x + w, y + h, c);\n this.vert(x, y + h, c);\n }\n\n /** Stroke segment (a→b) of `width`, flat caps — a quad across the segment normal. */\n segment(ax: number, ay: number, bx: number, by: number, width: number, c: Rgba): void {\n const dx = bx - ax;\n const dy = by - ay;\n const len = Math.hypot(dx, dy);\n if (len < 1e-6) return;\n const nx = (-dy / len) * (width / 2);\n const ny = (dx / len) * (width / 2);\n this.vert(ax + nx, ay + ny, c);\n this.vert(bx + nx, by + ny, c);\n this.vert(bx - nx, by - ny, c);\n this.vert(ax + nx, ay + ny, c);\n this.vert(bx - nx, by - ny, c);\n this.vert(ax - nx, ay - ny, c);\n }\n\n /** Stroke a polyline (interleaved xy) as per-segment quads (smooth-curve joins). */\n polyline(points: ArrayLike<number>, width: number, c: Rgba): void {\n const n = Math.floor((points.length as number) / 2);\n for (let i = 1; i < n; i++) {\n this.segment(\n points[(i - 1) * 2] as number,\n points[(i - 1) * 2 + 1] as number,\n points[i * 2] as number,\n points[i * 2 + 1] as number,\n width,\n c,\n );\n }\n }\n\n /** Filled disc as a triangle fan (MSAA smooths the rim; 16 segs ≈ round at ≤8 px). */\n disc(cx: number, cy: number, r: number, c: Rgba, segments = 16): void {\n for (let i = 0; i < segments; i++) {\n const a0 = (i / segments) * Math.PI * 2;\n const a1 = ((i + 1) / segments) * Math.PI * 2;\n this.vert(cx, cy, c);\n this.vert(cx + Math.cos(a0) * r, cy + Math.sin(a0) * r, c);\n this.vert(cx + Math.cos(a1) * r, cy + Math.sin(a1) * r, c);\n }\n }\n\n build(): TriSoup {\n return {\n positions: new Float32Array(this.pos),\n colors: new Float32Array(this.col),\n vertexCount: this.pos.length / 3,\n };\n }\n}\n\n/**\n * `rgba(r, g, b, a)` / `rgb(…)` / `#rrggbb` → [r,g,b,a] 0-1 (the WiresConfig\n * colors are CSS strings — v1/2D-canvas heritage). Unknown formats fall back\n * to opaque mid-gray rather than throwing in a reflector path.\n */\nexport function parseCssColor(css: string): Rgba {\n const rgba = /^rgba?\\(\\s*([\\d.]+)\\s*,\\s*([\\d.]+)\\s*,\\s*([\\d.]+)\\s*(?:,\\s*([\\d.]+)\\s*)?\\)$/.exec(css);\n if (rgba !== null) {\n return [\n Number(rgba[1]) / 255,\n Number(rgba[2]) / 255,\n Number(rgba[3]) / 255,\n rgba[4] === undefined ? 1 : Number(rgba[4]),\n ];\n }\n const hex = /^#([0-9a-f]{6})$/i.exec(css);\n if (hex !== null) {\n const v = Number.parseInt(hex[1] as string, 16);\n return [((v >> 16) & 0xff) / 255, ((v >> 8) & 0xff) / 255, (v & 0xff) / 255, 1];\n }\n return [0.5, 0.5, 0.5, 1];\n}\n","/**\n * Wires collector — the pure ECS→triangles half of the wires pass. Port of\n * the 2D-canvas wires reflector's drawing, kernel-tessellated:\n *\n * - Wire geometry NEVER reads a port ENTITY (design-001 §5.3): endpoints\n * resolve from the wire's `WireFrom`/`WireTo` widgets + `WirePorts` ids\n * against the type registry's static port schema (core `portSlots` — the\n * old local resolver's TODO, retired), so a CULLED endpoint still draws.\n * - Cubics build in WORLD space then map control points through the kernel\n * `worldToScreen` seam — bezier curves are affine-invariant, so the mapped\n * cubic IS the screen curve — and `tessellateCubic` (0.25 px tolerance)\n * flattens with density that tracks zoom for free.\n * - Connect preview: solid when snapped-compatible, dashed [6,4] otherwise\n * (dash placement from the tessellation's arc-length prefix).\n * - Materialized port dots: triangle-fan discs, active color while any\n * connect drag is routed.\n */\nimport {\n Active,\n Culled,\n DEFAULT_WIRES_CONFIG,\n Drag,\n MeasuredSize,\n Port,\n PortAnchor,\n Position,\n PrefabId,\n RoutedConnect,\n Selected,\n Size,\n Wire,\n WireFrom,\n WirePorts,\n WireTo,\n defineQuery,\n portSlots,\n widgets,\n type Entity,\n type WidgetType,\n type WirePreviewBuffer,\n type WiresConfig,\n type World,\n} from \"@ice/core\";\nimport {\n portAnchor,\n tessellateCubic,\n wireCubic,\n worldToScreen,\n type Cubic,\n type PortSlot,\n type Rect,\n type Tessellation,\n} from \"@ice/kernel\";\nimport type { GroundFrame } from \"../pass\";\nimport { SoupBuilder, parseCssColor, type Rgba, type TriSoup } from \"./soup-collect\";\n\nexport const wireQ = defineQuery([Wire]);\nexport const geometryQ = defineQuery([Position, Size]);\nexport const measuredQ = defineQuery([MeasuredSize]);\nexport const selectedQ = defineQuery([Selected]);\nexport const portQ = defineQuery([Port, PortAnchor]);\nexport const routedConnectQ = defineQuery([RoutedConnect]);\n/** A live connect drag moves the preview every frame — Drag value dirt covers it. */\nexport const connectDragQ = defineQuery([RoutedConnect, Drag]);\n/** Nav churn signal: Active membership flips re-collect (scope filter below). */\nexport const activeQ = defineQuery([Active]);\n\n/**\n * Scope filter (field bug 2026-07-17: root wires floated inside a folder).\n * Coordinates are FRAME-LOCAL (design-001 §5.1) — a wire whose endpoint\n * belongs to another nav frame is geometric nonsense in this one. The\n * signature of \"out of scope\" is the canonical non-member state the\n * activeMembership system stamps: Culled ∧ ¬Active. A VIEWPORT-culled member\n * is Culled ∧ Active and must keep drawing (long wires with offscreen\n * endpoints), and bare worlds with no membership system (unit tests,\n * membership-less rigs) carry neither tag and draw everything.\n */\nfunction outOfScope(world: World, e: Entity): boolean {\n return world.hasTag(e, Culled) && !world.hasTag(e, Active);\n}\n\nconst TESSELLATION_TOLERANCE_PX = 0.25;\nconst DASH_PX = 6;\nconst GAP_PX = 4;\n\n/** Effective widget rect: non-zero MeasuredSize over Size (design-004 §2).\n * Exported for the magnet collector (design-010 §4) — ONE rect-reading rule. */\nexport function readWidgetRect(world: World, e: Entity): Rect | undefined {\n const p = world.get(e, Position);\n if (p === undefined) return undefined;\n const measured = world.get(e, MeasuredSize);\n const s = measured !== undefined && measured.w > 0 ? measured : world.get(e, Size);\n if (s === undefined) return undefined;\n return { x: p.x, y: p.y, width: s.w, height: s.h };\n}\n\n/** Per-type slot cache (schemas are immutable; mirrors core ops/port-geometry). */\nconst slotCache = new Map<string, Map<string, PortSlot>>();\nfunction slotOf(wt: WidgetType, portId: string): PortSlot | undefined {\n let slots = slotCache.get(wt.type);\n if (slots === undefined) {\n slots = portSlots(wt.ports);\n slotCache.set(wt.type, slots);\n }\n return slots.get(portId);\n}\n\nfunction endpointAnchor(\n world: World,\n widget: Entity | undefined,\n portId: string,\n): { anchor: Rect; slot: PortSlot } | undefined {\n if (widget === undefined) return undefined;\n const rect = readWidgetRect(world, widget);\n if (rect === undefined) return undefined;\n const type = world.get(widget, PrefabId)?.id;\n if (typeof type !== \"string\") return undefined;\n const wt = widgets.get(type);\n if (wt === undefined) return undefined;\n const slot = slotOf(wt, portId);\n if (slot === undefined) return undefined;\n return { anchor: rect, slot };\n}\n\n/** Map a world cubic's control points to screen (affine ⇒ exact curve map). */\nfunction cubicToScreen(c: Cubic, cam: GroundFrame[\"camera\"]): Cubic {\n const p0 = worldToScreen(c.x0, c.y0, cam);\n const p1 = worldToScreen(c.x1, c.y1, cam);\n const p2 = worldToScreen(c.x2, c.y2, cam);\n const p3 = worldToScreen(c.x3, c.y3, cam);\n return { x0: p0.x, y0: p0.y, x1: p1.x, y1: p1.y, x2: p2.x, y2: p2.y, x3: p3.x, y3: p3.y };\n}\n\n/** Point at arc length `d` via the tessellation's prefix sums (binary search + lerp). */\nfunction pointAtLength(t: Tessellation, d: number): { x: number; y: number } {\n const arc = t.arcLength;\n const n = arc.length;\n let lo = 0;\n let hi = n - 1;\n while (lo < hi) {\n const mid = (lo + hi) >> 1;\n if ((arc[mid] as number) < d) lo = mid + 1;\n else hi = mid;\n }\n const i = Math.max(1, lo);\n const a = arc[i - 1] as number;\n const b = arc[i] as number;\n const f = b > a ? (d - a) / (b - a) : 0;\n const x0 = t.points[(i - 1) * 2] as number;\n const y0 = t.points[(i - 1) * 2 + 1] as number;\n const x1 = t.points[i * 2] as number;\n const y1 = t.points[i * 2 + 1] as number;\n return { x: x0 + (x1 - x0) * f, y: y0 + (y1 - y0) * f };\n}\n\n/** Emit a dashed stroke along the tessellation (straight dash segments — canvas parity at 6px dashes). */\nfunction dashedStroke(soup: SoupBuilder, t: Tessellation, width: number, c: Rgba): void {\n const total = t.arcLength[t.arcLength.length - 1] as number;\n for (let d = 0; d < total; d += DASH_PX + GAP_PX) {\n const a = pointAtLength(t, d);\n const b = pointAtLength(t, Math.min(d + DASH_PX, total));\n soup.segment(a.x, a.y, b.x, b.y, width, c);\n }\n}\n\nexport function collectWires(\n world: World,\n frame: GroundFrame,\n config: WiresConfig = DEFAULT_WIRES_CONFIG,\n preview?: WirePreviewBuffer,\n): TriSoup {\n const soup = new SoupBuilder();\n const cam = frame.camera;\n const wireColor = parseCssColor(config.wireColor);\n const selectedColor = parseCssColor(config.selectedColor);\n\n // Committed wires.\n world.query(wireQ).each((batch) => {\n for (const r of batch) {\n const wire = batch.entity(r);\n const ports = world.get(wire, WirePorts);\n if (ports === undefined) continue;\n const fromWidget = world.getRelation(wire, WireFrom);\n const toWidget = world.getRelation(wire, WireTo);\n // Both endpoints must be IN the current nav frame (scope filter above).\n if (fromWidget !== undefined && outOfScope(world, fromWidget)) continue;\n if (toWidget !== undefined && outOfScope(world, toWidget)) continue;\n const from = endpointAnchor(world, fromWidget, ports.from ?? \"\");\n const to = endpointAnchor(world, toWidget, ports.to ?? \"\");\n if (from === undefined || to === undefined) continue;\n const cubic = wireCubic(\n portAnchor(from.anchor, from.slot),\n from.slot.side,\n portAnchor(to.anchor, to.slot),\n to.slot.side,\n );\n const selected = world.hasTag(wire, Selected);\n const t = tessellateCubic(cubicToScreen(cubic, cam), TESSELLATION_TOLERANCE_PX);\n soup.polyline(t.points, selected ? config.selectedWidth : config.wireWidth, selected ? selectedColor : wireColor);\n }\n });\n\n // Connect-drag preview (world coords in the buffer; horizontal-stub cubic —\n // the old reflector's readable stand-in until the wire commits real sides).\n if (preview?.active === true) {\n const stub = Math.max(24, Math.abs(preview.tx - preview.sx) * 0.5);\n const cubic: Cubic = {\n x0: preview.sx,\n y0: preview.sy,\n x1: preview.sx + stub,\n y1: preview.sy,\n x2: preview.tx - stub,\n y2: preview.ty,\n x3: preview.tx,\n y3: preview.ty,\n };\n const t = tessellateCubic(cubicToScreen(cubic, cam), TESSELLATION_TOLERANCE_PX);\n if (preview.compatible) soup.polyline(t.points, config.wireWidth, selectedColor);\n else dashedStroke(soup, t, config.wireWidth, wireColor);\n }\n\n // Materialized port dots.\n const connecting = world.firstOf(routedConnectQ) !== undefined;\n const dotColor = parseCssColor(connecting ? config.portActiveColor : config.portColor);\n world.query(portQ).each((batch) => {\n const ax = batch.col(PortAnchor).x;\n const ay = batch.col(PortAnchor).y;\n for (const r of batch) {\n const s = worldToScreen(ax[r] as number, ay[r] as number, cam);\n soup.disc(s.x, s.y, config.portRadius, dotColor);\n }\n });\n\n return soup.build();\n}\n","/**\n * Magnet-grid collector — the pure ECS→packed-sources half of the magnet pass\n * (design-010 §4; the `*-collect.ts` convention: imports ONLY core/kernel so\n * it unit-tests under happy-dom with no GPU and no three import).\n *\n * Ported from vibe-field draft/magnet-grid `main.js` (latticeWindow,\n * packCards) with the design-010 upgrades the experiment lacked:\n * - rbush broad-phase over the ONE spatial index instead of an all-cards\n * walk (D2 — document size becomes irrelevant by construction);\n * - N poles from injected sources, packed as DEGENERATE rounded boxes\n * (half = 0, r = 0 — reduces exactly to the point-charge formula, D3);\n * - `maxSources` prioritization (largest screen area, then nearest to the\n * viewport center; poles pack first and are never evicted);\n * - `fadeZoom` — the field quiets below a zoom threshold (scale 0 skips the\n * spatial query entirely: the cheap valve is also the right look).\n */\nimport {\n DEFAULT_GRID_MAGNET_CONFIG,\n type Entity,\n type GridConfig,\n type GridMagnetConfig,\n type World,\n} from \"@ice/core\";\nimport { worldToScreen, type AABB, type SpatialEntry } from \"@ice/kernel\";\nimport type { GroundFrame } from \"../pass\";\nimport type { Pole } from \"../poles\";\nimport { readWidgetRect } from \"./wires-collect\";\n\n/** Floats per packed source: [cx, cy, hx, hy] + [r, strength, 0, 0] (screen px). */\nexport const MAGNET_SOURCE_FLOATS = 8;\n/** Source-buffer capacity — the scratch array and GPU buffer are sized to this. */\nexport const MAX_MAGNET_SOURCES = 256;\n/** Per-level instance guard (vibe-field main.js:621 — a level beyond it draws nothing). */\nexport const MAX_MAGNET_INSTANCES = 220_000;\n\n/** The broad-phase reader over the shared spatial index (ctx seam, design-010 §3.2). */\nexport type ReadSpatial = (bounds: AABB) => readonly SpatialEntry<Entity>[];\n\n/** Resolve the partial config block over the defaults — the ONE resolution point. */\nexport function resolveMagnet(cfg: GridConfig): GridMagnetConfig {\n return { ...DEFAULT_GRID_MAGNET_CONFIG, ...cfg.magnet };\n}\n\n/** Closed-form fade ladder (grid.ts:72-74 re-expressed in JS for level skip). */\nexport function fadeOpacity(\n cssSpacing: number,\n fadeIn: readonly [number, number],\n fadeOut: readonly [number, number],\n): number {\n const rise = (cssSpacing - fadeIn[0]) / Math.max(fadeIn[1] - fadeIn[0], 0.0001);\n const fall = 1 - (cssSpacing - fadeOut[0]) / Math.max(fadeOut[1] - fadeOut[0], 0.0001);\n return Math.min(Math.max(Math.min(rise, fall), 0), 1);\n}\n\n/**\n * The field zoom valve: 1 at `zoom ≥ fadeZoom`, lerping to 0 across\n * [0.7·fadeZoom, fadeZoom]. 0 disables the valve entirely.\n */\nexport function magnetFieldScale(zoom: number, fadeZoom: number): number {\n if (fadeZoom <= 0) return 1;\n const t = (zoom - 0.7 * fadeZoom) / (0.3 * fadeZoom);\n return Math.min(Math.max(t, 0), 1);\n}\n\n/** One lattice level's visible window + fade (vibe-field main.js:81-91 port). */\nexport interface MagnetLevel {\n /** Integer lattice coords of the window origin. */\n readonly i0: number;\n readonly j0: number;\n readonly cols: number;\n readonly rows: number;\n /** Instances to draw; 0 = level skipped (faded out or over the guard). */\n readonly count: number;\n /** Fade-ladder opacity × level weight (CPU-baked; the shader gets one alpha). */\n readonly alpha: number;\n /**\n * Coincidence skip (design-010 §5.4): when the NEXT level up is visible and\n * its spacing is an integer multiple m of this one, sites whose absolute\n * lattice index is ≡ 0 (mod m) on both axes drop out — replicating the\n * classic shader's max-composite look. 0 = no skip.\n */\n readonly skipModulo: number;\n}\n\nexport function collectMagnetLevels(frame: GroundFrame, cfg: GridConfig): MagnetLevel[] {\n const { camera } = frame;\n const out: MagnetLevel[] = [];\n const opacities = cfg.spacings.map((s) => fadeOpacity(s * camera.zoom, cfg.fadeIn, cfg.fadeOut));\n for (let i = 0; i < cfg.spacings.length; i++) {\n const spacing = cfg.spacings[i] as number;\n const opacity = opacities[i] as number;\n const weight = cfg.levelWeight[0] + i * cfg.levelWeight[1];\n const alpha = opacity * weight * cfg.dotAlpha;\n if (opacity < 0.01 || alpha <= 0) {\n out.push({ i0: 0, j0: 0, cols: 0, rows: 0, count: 0, alpha: 0, skipModulo: 0 });\n continue;\n }\n const worldW = frame.width / camera.zoom;\n const worldH = frame.height / camera.zoom;\n const i0 = Math.floor(camera.x / spacing) - 1;\n const j0 = Math.floor(camera.y / spacing) - 1;\n const i1 = Math.ceil((camera.x + worldW) / spacing) + 1;\n const j1 = Math.ceil((camera.y + worldH) / spacing) + 1;\n const cols = Math.max(1, i1 - i0);\n const rows = Math.max(1, j1 - j0);\n const count = cols * rows;\n if (count > MAX_MAGNET_INSTANCES) {\n out.push({ i0: 0, j0: 0, cols: 0, rows: 0, count: 0, alpha: 0, skipModulo: 0 });\n continue;\n }\n let skipModulo = 0;\n const next = cfg.spacings[i + 1];\n if (next !== undefined && (opacities[i + 1] as number) >= 0.01) {\n const ratio = next / spacing;\n if (Number.isInteger(ratio) && ratio > 1) skipModulo = ratio;\n }\n out.push({ i0, j0, cols, rows, count, alpha, skipModulo });\n }\n return out;\n}\n\ninterface WidgetCandidate {\n cx: number;\n cy: number;\n hx: number;\n hy: number;\n r: number;\n area: number;\n centerDist: number;\n}\n\n/**\n * Pack field sources into `out` (stride {@link MAGNET_SOURCE_FLOATS}, screen\n * CSS px). Returns the packed count. `fieldScale` multiplies every strength\n * (the zoom valve); 0 short-circuits to an empty buffer — no spatial query.\n */\nexport function collectMagnetSources(\n world: World,\n frame: GroundFrame,\n magnet: GridMagnetConfig,\n fieldScale: number,\n poles: readonly Pole[],\n readSpatial: ReadSpatial | undefined,\n out: Float32Array,\n): number {\n if (fieldScale <= 0) return 0;\n const { camera } = frame;\n const cap = Math.min(magnet.maxSources, MAX_MAGNET_SOURCES, Math.floor(out.length / MAGNET_SOURCE_FLOATS));\n let n = 0;\n\n // Poles first — never evicted by widgets (design-010 §4).\n for (const pole of poles) {\n if (n >= cap) break;\n if (!(pole.strength > 0)) continue;\n const s = pole.space === \"screen\" ? pole : worldToScreen(pole.x, pole.y, camera);\n const o = n * MAGNET_SOURCE_FLOATS;\n out[o + 0] = s.x;\n out[o + 1] = s.y;\n out[o + 2] = 0;\n out[o + 3] = 0;\n out[o + 4] = 0;\n out[o + 5] = pole.strength * fieldScale;\n out[o + 6] = 0;\n out[o + 7] = 0;\n n++;\n }\n\n if (!magnet.widgets || readSpatial === undefined || magnet.widgetStrength <= 0 || n >= cap) {\n return n;\n }\n\n // Broad-phase: viewport ∪ influence halo. The shader's reject cutoff is\n // pad = √(k/0.02) = 5·reach CSS px (influence 0.02 ≈ invisible), scaled by\n // per-source √strength — query with the strength-scaled halo so nothing the\n // shader could show is culled here.\n const haloCss = 5 * magnet.reach * Math.sqrt(Math.max(magnet.widgetStrength * fieldScale, 0.0001));\n const pad = haloCss / camera.zoom;\n const hits = readSpatial({\n minX: camera.x - pad,\n minY: camera.y - pad,\n maxX: camera.x + frame.width / camera.zoom + pad,\n maxY: camera.y + frame.height / camera.zoom + pad,\n });\n\n const viewCx = frame.width / 2;\n const viewCy = frame.height / 2;\n const candidates: WidgetCandidate[] = [];\n for (const hit of hits) {\n // The index also carries wires/ports (they share it) — the rect reader is\n // the widget filter: Position + non-zero MeasuredSize|Size only.\n const rect = readWidgetRect(world, hit.id);\n if (rect === undefined || rect.width <= 0 || rect.height <= 0) continue;\n const hx = (rect.width / 2) * camera.zoom;\n const hy = (rect.height / 2) * camera.zoom;\n const center = worldToScreen(rect.x + rect.width / 2, rect.y + rect.height / 2, camera);\n candidates.push({\n cx: center.x,\n cy: center.y,\n hx,\n hy,\n r: Math.min(magnet.widgetRadius * camera.zoom, hx, hy),\n area: hx * hy,\n centerDist: (center.x - viewCx) ** 2 + (center.y - viewCy) ** 2,\n });\n }\n\n const budget = cap - n;\n if (candidates.length > budget) {\n candidates.sort((a, b) => b.area - a.area || a.centerDist - b.centerDist);\n candidates.length = budget;\n }\n\n const strength = magnet.widgetStrength * fieldScale;\n for (const c of candidates) {\n const o = n * MAGNET_SOURCE_FLOATS;\n out[o + 0] = c.cx;\n out[o + 1] = c.cy;\n out[o + 2] = c.hx;\n out[o + 3] = c.hy;\n out[o + 4] = c.r;\n out[o + 5] = strength;\n out[o + 6] = 0;\n out[o + 7] = 0;\n n++;\n }\n return n;\n}\n","/**\n * Magnet lattice as a complete GridPass implementation.\n *\n * There is no classic branch here: source collection, wake subscriptions and\n * rendering all belong to the selected implementation. Dot/needle remains a\n * cheap glyph uniform inside the one magnet renderer.\n */\nimport { SpatialVersion } from \"@ice/core\";\nimport type { Pole } from \"../poles\";\nimport {\n mergeGridConfig,\n resolveInitialGridConfig,\n type GridPassFactory,\n} from \"./grid-contract\";\nimport { createMagnetGrid } from \"./grid-magnet\";\nimport {\n MAGNET_SOURCE_FLOATS,\n MAX_MAGNET_SOURCES,\n collectMagnetLevels,\n collectMagnetSources,\n magnetFieldScale,\n resolveMagnet,\n} from \"./magnet-collect\";\n\nexport const createGridPass: GridPassFactory = (initial = {}, deps = {}) => {\n let cfg = resolveInitialGridConfig(initial);\n const renderer = createMagnetGrid();\n const poles = deps.poles ?? [];\n const sourceScratch = new Float32Array(MAX_MAGNET_SOURCES * MAGNET_SOURCE_FLOATS);\n const poleScratch: Pole[] = [];\n\n return {\n name: \"grid\",\n object: renderer.group,\n arm(world, wake) {\n // Gates read LIVE config so configure() re-tunes never re-arm.\n const wakeIfWidgets = (): void => {\n const magnet = resolveMagnet(cfg);\n if (magnet.widgets && deps.readSpatial !== undefined) wake();\n };\n const unsubs = [world.reactive.observeResource(SpatialVersion, wakeIfWidgets)];\n for (const source of poles) unsubs.push(source.subscribe(world, wake));\n return unsubs;\n },\n collect(world, frame) {\n const magnet = resolveMagnet(cfg);\n const fieldScale = magnetFieldScale(frame.camera.zoom, magnet.fadeZoom);\n poleScratch.length = 0;\n if (fieldScale > 0) {\n for (const source of poles) poleScratch.push(...source.read(world));\n }\n const sourceCount = collectMagnetSources(\n world,\n frame,\n magnet,\n fieldScale,\n poleScratch,\n deps.readSpatial,\n sourceScratch,\n );\n const levels = collectMagnetLevels(frame, cfg);\n renderer.update(frame, cfg, magnet, levels, sourceScratch, sourceCount);\n },\n configure(next) {\n cfg = mergeGridConfig(cfg, next);\n // Every magnet uniform is rewritten on the next collect; configureGrid\n // invalidates the layer after calling this method.\n },\n dispose() {\n renderer.dispose();\n },\n };\n};\n","/**\n * Snap-guides collector — the pure ECS→triangles half of the guides pass\n * (v1 SnapGuideRenderer look, carried over from the 2D-canvas reflector it\n * replaces): full-viewport magenta alignment lines (`GuideLine.from == to` ⇒\n * full span — design-003 §6), bounded spans, and equal-spacing bars with 4px\n * end ticks. Screen-px output via the kernel `worldToScreen` seam. NO guide\n * count caps (the pool grows; so does the soup).\n */\nimport {\n DEFAULT_SNAP_GUIDES_CONFIG,\n GuideLine,\n SpacingBar,\n defineQuery,\n type SnapGuidesConfig,\n type World,\n} from \"@ice/core\";\nimport { worldToScreen } from \"@ice/kernel\";\nimport type { GroundFrame } from \"../pass\";\nimport { SoupBuilder, type Rgba, type TriSoup } from \"./soup-collect\";\n\nexport const guideQ = defineQuery([GuideLine]);\nexport const barQ = defineQuery([SpacingBar]);\n\nexport function collectGuides(\n world: World,\n frame: GroundFrame,\n config: SnapGuidesConfig = DEFAULT_SNAP_GUIDES_CONFIG,\n): TriSoup {\n const soup = new SoupBuilder();\n const cam = frame.camera;\n const lw = config.lineWidth;\n const guideColor: Rgba = [config.color[0], config.color[1], config.color[2], config.guideAlpha];\n const barColor: Rgba = [config.color[0], config.color[1], config.color[2], config.spacingAlpha];\n\n world.query(guideQ).each((b) => {\n for (const r of b) {\n const g = world.read(b.entity(r), GuideLine);\n const fullSpan = g.from === g.to;\n if (g.axis === \"x\") {\n const sx = worldToScreen(g.at, 0, cam).x;\n if (frame.width > 0 && (sx < -1 || sx > frame.width + 1)) continue;\n const y0 = fullSpan ? 0 : worldToScreen(0, g.from, cam).y;\n const y1 = fullSpan ? frame.height : worldToScreen(0, g.to, cam).y;\n soup.rect(sx - lw / 2, Math.min(y0, y1), lw, Math.abs(y1 - y0), guideColor);\n } else {\n const sy = worldToScreen(0, g.at, cam).y;\n if (frame.height > 0 && (sy < -1 || sy > frame.height + 1)) continue;\n const x0 = fullSpan ? 0 : worldToScreen(g.from, 0, cam).x;\n const x1 = fullSpan ? frame.width : worldToScreen(g.to, 0, cam).x;\n soup.rect(Math.min(x0, x1), sy - lw / 2, Math.abs(x1 - x0), lw, guideColor);\n }\n }\n });\n\n world.query(barQ).each((b) => {\n for (const r of b) {\n const s = world.read(b.entity(r), SpacingBar);\n const t = config.tickPx;\n if (s.axis === \"x\") {\n // Horizontal gap along x at world-y perp (kernel/v1 axis semantics).\n const a = worldToScreen(s.from, s.perp, cam);\n const bp = worldToScreen(s.to, s.perp, cam);\n if (frame.width > 0 && (Math.max(a.x, bp.x) < 0 || Math.min(a.x, bp.x) > frame.width)) continue;\n soup.rect(Math.min(a.x, bp.x), a.y - lw / 2, Math.abs(bp.x - a.x), lw, barColor);\n soup.rect(a.x - lw / 2, a.y - t, lw, t * 2, barColor);\n soup.rect(bp.x - lw / 2, bp.y - t, lw, t * 2, barColor);\n } else {\n const a = worldToScreen(s.perp, s.from, cam);\n const bp = worldToScreen(s.perp, s.to, cam);\n if (frame.height > 0 && (Math.max(a.y, bp.y) < 0 || Math.min(a.y, bp.y) > frame.height)) continue;\n soup.rect(a.x - lw / 2, Math.min(a.y, bp.y), lw, Math.abs(bp.y - a.y), barColor);\n soup.rect(a.x - t, a.y - lw / 2, t * 2, lw, barColor);\n soup.rect(bp.x - t, bp.y - lw / 2, t * 2, lw, barColor);\n }\n }\n });\n\n return soup.build();\n}\n","/**\n * The three-side half of a triangle-soup pass: a Mesh over a dynamic\n * BufferGeometry (position xyz + color rgba) with an unlit TSL material whose\n * fragment IS the vertex color. Capacity grows geometrically; shrink keeps the\n * buffer and narrows the draw range (guide/wire counts oscillate per frame —\n * reallocating every collect would churn).\n */\nimport { attribute } from \"three/tsl\";\nimport { BufferAttribute, BufferGeometry, DoubleSide, Mesh, MeshBasicNodeMaterial } from \"three/webgpu\";\nimport type { TriSoup } from \"./soup-collect\";\n\nexport interface SoupMesh {\n readonly mesh: Mesh;\n update(soup: TriSoup): void;\n dispose(): void;\n}\n\nexport function createSoupMesh(renderOrder: number): SoupMesh {\n const material = new MeshBasicNodeMaterial();\n material.fragmentNode = attribute(\"color\", \"vec4\");\n material.transparent = true;\n material.depthTest = false;\n material.depthWrite = false;\n // Screen-px collectors emit y-down geometry, which lands CLOCKWISE in NDC\n // through the top=0/bottom=h ortho camera — front-face culling would drop\n // every triangle (the invisible-guides field find, 2026-07-16).\n material.side = DoubleSide;\n\n let geometry = new BufferGeometry();\n let capacity = 0;\n const mesh = new Mesh(geometry, material);\n mesh.frustumCulled = false;\n mesh.renderOrder = renderOrder;\n mesh.visible = false; // until the first non-empty soup\n\n return {\n mesh,\n update(soup) {\n if (soup.vertexCount === 0) {\n mesh.visible = false;\n geometry.setDrawRange(0, 0);\n return;\n }\n if (soup.vertexCount > capacity) {\n capacity = Math.max(soup.vertexCount, capacity * 2, 256);\n const old = geometry;\n geometry = new BufferGeometry();\n const pos = new Float32Array(capacity * 3);\n const col = new Float32Array(capacity * 4);\n pos.set(soup.positions);\n col.set(soup.colors);\n geometry.setAttribute(\"position\", new BufferAttribute(pos, 3));\n geometry.setAttribute(\"color\", new BufferAttribute(col, 4));\n mesh.geometry = geometry;\n old.dispose();\n } else {\n const pos = geometry.getAttribute(\"position\") as BufferAttribute;\n const col = geometry.getAttribute(\"color\") as BufferAttribute;\n (pos.array as Float32Array).set(soup.positions);\n (col.array as Float32Array).set(soup.colors);\n pos.needsUpdate = true;\n col.needsUpdate = true;\n }\n geometry.setDrawRange(0, soup.vertexCount);\n mesh.visible = true;\n },\n dispose() {\n geometry.dispose();\n material.dispose();\n },\n };\n}\n","/**\n * Snap-guides pass — the three-side wrapper over the pure `collectGuides`\n * (renders ABOVE grid and wires within the ground canvas, matching the old\n * P0 stacking order).\n */\nimport { GuideLine, SpacingBar, type World } from \"@ice/core\";\nimport { DEFAULT_SNAP_GUIDES_CONFIG, type SnapGuidesConfig } from \"@ice/core\";\nimport type { GroundFrame, GroundPass } from \"../pass\";\nimport { barQ, collectGuides, guideQ } from \"./guides-collect\";\nimport { createSoupMesh } from \"./soup-mesh\";\n\nexport function createGuidesPass(initial: Partial<SnapGuidesConfig> = {}): GroundPass {\n const config: SnapGuidesConfig = { ...DEFAULT_SNAP_GUIDES_CONFIG, ...initial };\n const soup = createSoupMesh(2);\n\n return {\n name: \"snap-guides\",\n object: soup.mesh,\n arm(world: World, wake: () => void) {\n return [\n world.reactive.observeQuery(guideQ, wake, { cols: [GuideLine] }),\n world.reactive.observeQuery(barQ, wake, { cols: [SpacingBar] }),\n ];\n },\n collect(world: World, frame: GroundFrame) {\n soup.update(collectGuides(world, frame, config));\n },\n dispose() {\n soup.dispose();\n },\n };\n}\n","/**\n * Wires pass — the three-side wrapper over the pure `collectWires` (renders\n * above the grid, below the guides, matching the old P0 canvas order).\n * Dirt mirrors the old 2D reflector's observers; the connect preview rides\n * `[RoutedConnect, Drag]` value dirt (the buffer updates exactly when the\n * connect recognizer's Drag advances) instead of a per-frame value diff.\n */\nimport {\n DEFAULT_WIRES_CONFIG,\n Drag,\n MeasuredSize,\n PortAnchor,\n Position,\n Size,\n type WirePreviewBuffer,\n type WiresConfig,\n type World,\n} from \"@ice/core\";\nimport type { GroundFrame, GroundPass } from \"../pass\";\nimport { createSoupMesh } from \"./soup-mesh\";\nimport {\n activeQ,\n collectWires,\n connectDragQ,\n geometryQ,\n measuredQ,\n portQ,\n routedConnectQ,\n selectedQ,\n wireQ,\n} from \"./wires-collect\";\n\nexport function createWiresPass(\n initial: Partial<WiresConfig> = {},\n readPreview?: () => WirePreviewBuffer,\n): GroundPass {\n const config: WiresConfig = { ...DEFAULT_WIRES_CONFIG, ...initial };\n const soup = createSoupMesh(1);\n\n return {\n name: \"wires\",\n object: soup.mesh,\n arm(world: World, wake: () => void) {\n return [\n world.reactive.observeQuery(wireQ, wake, { cols: [] }),\n world.reactive.observeQuery(geometryQ, wake, { cols: [Position, Size] }),\n // MeasuredSize rides its own observer (readRect prefers it over Size):\n // in geometryQ's cols it would REQUIRE the rider and drop plain widgets.\n world.reactive.observeQuery(measuredQ, wake, { cols: [MeasuredSize] }),\n world.reactive.observeQuery(selectedQ, wake, { cols: [] }),\n // Nav churn: Active membership flips gate the scope filter (a wire\n // whose endpoints left the current frame must disappear this frame).\n world.reactive.observeQuery(activeQ, wake, { cols: [] }),\n world.reactive.observeQuery(portQ, wake, { cols: [PortAnchor] }),\n world.reactive.observeQuery(routedConnectQ, wake, { cols: [] }),\n world.reactive.observeQuery(connectDragQ, wake, { cols: [Drag] }),\n ];\n },\n collect(world: World, frame: GroundFrame) {\n soup.update(collectWires(world, frame, config, readPreview?.()));\n },\n dispose() {\n soup.dispose();\n },\n };\n}\n","/**\n * WebGPU renderer bootstrap for the ground layer.\n *\n * WebGPU-first (James, 2026-07-16): three's `WebGPURenderer` picks the WebGPU\n * backend when `navigator.gpu` exists and falls back to WebGL2 otherwise —\n * one code path, TSL compiles to WGSL or GLSL per backend. Init is ASYNC\n * (`renderer.init()`), but the reflector flush is synchronous: `ready()`\n * gates drawing, the layer keeps its dirty flags armed, and the first flush\n * after resolution paints (the rAF loop retries every frame — no extra wake\n * plumbing). Any construction/init failure (happy-dom, device loss, no\n * WebGL2 either) degrades to `failed()` — the layer reports available() =\n * false and never throws (grid.ts fault-isolation contract, design-002 §5).\n */\nimport { WebGPURenderer } from \"three/webgpu\";\nimport type { Camera, Scene } from \"three/webgpu\";\n\n/** The layer's renderer seam — tests inject a fake (compositor `GlLike` precedent). */\nexport interface GroundRendererLike {\n readonly canvas: HTMLCanvasElement;\n ready(): boolean;\n failed(): boolean;\n /** Register a one-shot \"became ready\" callback (fires immediately if already ready). */\n onReady(cb: () => void): void;\n setSize(cssW: number, cssH: number, dpr: number): void;\n render(scene: Scene, camera: Camera): void;\n dispose(): void;\n}\n\nexport function createGroundRenderer(\n doc: Document,\n opts: { forceWebGL?: boolean } = {},\n): GroundRendererLike {\n const canvas = doc.createElement(\"canvas\");\n let renderer: WebGPURenderer | null = null;\n let isReady = false;\n let isFailed = false;\n const readyCbs: Array<() => void> = [];\n\n // Probe BEFORE constructing: with neither WebGPU nor WebGL2 (happy-dom,\n // ancient browsers), three's WebGL2 fallback dies inside an internal\n // un-awaited promise — an unhandled rejection our init().catch never sees\n // (widgetlab app-mount test, 2026-07-16). The WebGL2 probe uses a SCRATCH\n // canvas: getContext('webgl2') on the real one would lock it out of a\n // 'webgpu' context (contexts are exclusive per canvas).\n const gpu = (globalThis.navigator as { gpu?: unknown } | undefined)?.gpu;\n if (gpu == null || opts.forceWebGL === true) {\n let gl2: unknown = null;\n try {\n gl2 = doc.createElement(\"canvas\").getContext(\"webgl2\");\n } catch {\n gl2 = null;\n }\n if (gl2 === null) isFailed = true;\n }\n\n if (!isFailed) {\n try {\n renderer = new WebGPURenderer({\n canvas: canvas as unknown as HTMLCanvasElement,\n alpha: true, // transparent clear — the page background shows through P0\n antialias: true,\n ...(opts.forceWebGL === true ? { forceWebGL: true } : {}),\n });\n renderer\n .init()\n .then(() => {\n isReady = true;\n for (const cb of readyCbs.splice(0)) cb();\n })\n .catch(() => {\n isFailed = true; // device loss mid-init\n });\n } catch {\n isFailed = true; // constructor threw\n }\n }\n\n let lastW = 0;\n let lastH = 0;\n let lastDpr = 0;\n\n return {\n canvas,\n ready: () => isReady,\n failed: () => isFailed,\n onReady(cb) {\n if (isReady) cb();\n else readyCbs.push(cb);\n },\n setSize(cssW, cssH, dpr) {\n if (renderer === null || (cssW === lastW && cssH === lastH && dpr === lastDpr)) return;\n lastW = cssW;\n lastH = cssH;\n lastDpr = dpr;\n try {\n renderer.setPixelRatio(dpr);\n // false: the layer owns the canvas CSS size (100% inset-0)\n renderer.setSize(Math.max(1, cssW), Math.max(1, cssH), false);\n } catch {\n isFailed = true;\n }\n },\n render(scene, camera) {\n if (renderer === null || !isReady || isFailed) return;\n try {\n renderer.render(scene, camera);\n } catch {\n isFailed = true; // device loss ⇒ silent no-op forever, never a throwing reflector\n }\n },\n dispose() {\n try {\n renderer?.dispose();\n } catch {\n /* already lost */\n }\n renderer = null;\n },\n };\n}\n","/**\n * Magnet pole sources (design-010 §3.3, decision D5): the grid pass is\n * CURSOR-AGNOSTIC — point field sources enter through this injected protocol,\n * never through pass-known vocabulary. No source wired ⇒ no subscription, no\n * reads, widget-only field. The canned helpers below are where any cursor\n * dependency lives; the pass imports NEITHER — apps compose what fits\n * (vibe-field wraps its own `Cur` halo the same way, in its own repo).\n */\nimport {\n CursorVisual,\n defineQuery,\n LocalPointer,\n Pointer,\n PointerWorld,\n Position,\n type World,\n} from \"@ice/core\";\n\n/**\n * One point field source. Packed as a degenerate rounded-box SDF (half = 0,\n * r = 0), which reduces exactly to the point-charge formula (design-010 D3).\n * `space` defaults to \"world\"; \"screen\" is CSS px — zero-conversion for\n * screen-space cursors (field evaluation is screen-space anyway).\n */\nexport interface Pole {\n readonly x: number;\n readonly y: number;\n /** Relative field strength; ≤ 0 poles are skipped at pack time. */\n readonly strength: number;\n readonly space?: \"world\" | \"screen\";\n}\n\nexport interface PoleSource {\n /** Called during collect — read-only world access (GroundPass.collect rules). */\n read(world: World): readonly Pole[];\n /**\n * Called during arm — `wake` marks the wired magnet grid dirty. The classic\n * implementation never subscribes. Returns an unsubscriber.\n */\n subscribe(world: World, wake: () => void): () => void;\n}\n\nconst localPointerQ = defineQuery([Pointer, PointerWorld, LocalPointer]);\n\n/**\n * Poles from the local pointer entity (`LocalPointer` + `PointerWorld`) — the\n * raw-cursor wiring for apps without their own cursor visual. World-space; one\n * pole per local pointer (multi-touch yields one per finger while pressed).\n */\nexport function localPointerPoles(opts: { readonly strength?: number } = {}): PoleSource {\n const strength = opts.strength ?? 1;\n return {\n read(world) {\n const out: Pole[] = [];\n world.query(localPointerQ).each((b) => {\n for (const r of b) {\n const p = world.read(b.entity(r), PointerWorld);\n out.push({ x: p.x, y: p.y, strength, space: \"world\" });\n }\n });\n return out;\n },\n subscribe(world, wake) {\n return world.reactive.observeQuery(localPointerQ, wake, { cols: [PointerWorld] });\n },\n };\n}\n\nconst cursorVisualQ = defineQuery([Position, CursorVisual]);\n\n/**\n * Poles from cursor-visual entities (`Position` + `CursorVisual`) — presence\n * apps: remote collaborators' pooled cursors (core `remote-cursors.ts`) drive\n * the field. This helper is where the CursorVisual dependency lives (D5).\n */\nexport function cursorVisualPoles(opts: { readonly strength?: number } = {}): PoleSource {\n const strength = opts.strength ?? 1;\n return {\n read(world) {\n const out: Pole[] = [];\n world.query(cursorVisualQ).each((b) => {\n for (const r of b) {\n const p = world.read(b.entity(r), Position);\n out.push({ x: p.x, y: p.y, strength, space: \"world\" });\n }\n });\n return out;\n },\n subscribe(world, wake) {\n return world.reactive.observeQuery(cursorVisualQ, wake, { cols: [Position] });\n },\n };\n}\n","/**\n * @ice/ground — the P0 ground stratum as ONE WebGPU canvas (design-004 §1\n * as-built amendment, 2026-07-16). three's WebGPURenderer + TSL, WebGL2\n * fallback automatic. Off the react chain: react receives the layer as an\n * OPAQUE factory (`<InfiniteCanvas ground={ground(...)}>`); imperative apps\n * register `layer.reflector` themselves. Passes: dot grid, wires, snap\n * guides — future ground shaders/effects join the same pass registry.\n * (Selection chrome moved OFF the ground 2026-07-17: rings live with the\n * cards, the multi-select union box is P4 dom chrome — always on top.)\n */\nimport type { GridConfig, SnapGuidesConfig, WirePreviewBuffer, WiresConfig, World } from \"@ice/core\";\nimport { createLayer, type GroundLayerHost, type GroundReflector } from \"./layer\";\nimport type { GroundPass } from \"./pass\";\nimport { createGridPass } from \"./passes/grid\";\nimport { createGuidesPass } from \"./passes/guides\";\nimport type { ReadSpatial } from \"./passes/magnet-collect\";\nimport { createWiresPass } from \"./passes/wires\";\nimport type { PoleSource } from \"./poles\";\nimport { createGroundRenderer, type GroundRendererLike } from \"./renderer\";\n\nexport type { GroundFrame, GroundPass } from \"./pass\";\nexport type { GroundReflector } from \"./layer\";\nexport type { GroundRendererLike } from \"./renderer\";\nexport { SoupBuilder, parseCssColor, type Rgba, type TriSoup } from \"./passes/soup-collect\";\nexport { collectGuides } from \"./passes/guides-collect\";\nexport { collectWires } from \"./passes/wires-collect\";\n// The magnet pole seam (design-010 §3.3) + canned wirings (D5: the grid\n// implementation imports neither helper — cursor vocabulary lives in the\n// helper the app chose).\nexport { cursorVisualPoles, localPointerPoles, type Pole, type PoleSource } from \"./poles\";\nexport {\n collectMagnetLevels,\n collectMagnetSources,\n magnetFieldScale,\n resolveMagnet,\n MAX_MAGNET_SOURCES,\n type MagnetLevel,\n type ReadSpatial,\n} from \"./passes/magnet-collect\";\n// Config vocabulary re-exported for app ergonomics (canonical home: @ice/core).\nexport {\n DEFAULT_GRID_CONFIG,\n DEFAULT_GRID_MAGNET_CONFIG,\n DEFAULT_SNAP_GUIDES_CONFIG,\n DEFAULT_WIRES_CONFIG,\n type GridConfig,\n type GridMagnetConfig,\n type SnapGuidesConfig,\n type WiresConfig,\n} from \"@ice/core\";\n\nexport interface GroundContext {\n readonly host: GroundLayerHost;\n readonly world: World;\n /** Connect-drag preview reader (graph boards); omit on boards without wires. */\n readonly readWirePreview?: () => WirePreviewBuffer;\n /**\n * Broad-phase reader over the ONE spatial index (design-010 §3.2, the\n * readWirePreview precedent) — the magnet grid's widget sources. Facades\n * wire `stack.index.search`; omit ⇒ magnet renders a pole-only field.\n */\n readonly readSpatial?: ReadSpatial;\n}\n\nexport interface GroundLayer {\n readonly reflector: GroundReflector;\n /** Live grid re-tune (the react `grid` prop forwards here). */\n configureGrid(cfg: Partial<GridConfig>): void;\n dispose(): void;\n}\n\nexport interface GroundOptions {\n readonly grid?: Partial<GridConfig>;\n readonly wires?: Partial<WiresConfig>;\n readonly guides?: Partial<SnapGuidesConfig>;\n /**\n * Magnet pole sources (design-010 §3.3) — live app-authored objects, so they\n * live HERE, not in the plain-data GridConfig. Nothing wired ⇒ the magnet\n * field is widget-only. The classic implementation accepts this same\n * GroundOptions contract and ignores the sources.\n */\n readonly poles?: PoleSource | readonly PoleSource[];\n /** Extra app passes, rendered after the built-ins (renderOrder ≥ 3 is yours). */\n readonly passes?: readonly GroundPass[];\n /** Force the WebGL2 backend (debug / e2e A-B runs). */\n readonly forceWebGL?: boolean;\n /** TEST seam: inject a fake renderer (headless orchestration tests). */\n readonly rendererOverride?: GroundRendererLike;\n}\n\nexport type GroundFactory = (ctx: GroundContext) => GroundLayer;\n\n/**\n * Build the ground layer factory. Usage:\n * react apps: <InfiniteCanvas ground={ground({ grid: {...} })} …>\n * imperative apps: const layer = ground()( { host, world, readWirePreview } );\n * engine.registerReflector(layer.reflector);\n */\nexport function ground(opts: GroundOptions = {}): GroundFactory {\n return (ctx) => {\n const doc = ctx.host.container.ownerDocument;\n const renderer = opts.rendererOverride ?? createGroundRenderer(doc, { forceWebGL: opts.forceWebGL === true });\n const poles = opts.poles === undefined ? [] : Array.isArray(opts.poles) ? opts.poles : [opts.poles];\n const grid = createGridPass(opts.grid ?? {}, { poles, ...(ctx.readSpatial !== undefined ? { readSpatial: ctx.readSpatial } : {}) });\n const wires = createWiresPass(opts.wires ?? {}, ctx.readWirePreview);\n const guides = createGuidesPass(opts.guides ?? {});\n const passes: GroundPass[] = [grid, wires, guides, ...(opts.passes ?? [])];\n const layer = createLayer(ctx.host, ctx.world, renderer, passes);\n return {\n reflector: layer.reflector,\n configureGrid(cfg) {\n grid.configure(cfg);\n layer.invalidateAll();\n },\n dispose: layer.dispose,\n };\n };\n}\n"],"mappings":"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","names":["BufferAttribute","Mesh","MeshBasicNodeMaterial"]}
|
package/dist/index.js
CHANGED
package/dist/r3f.js
CHANGED
|
@@ -2,8 +2,8 @@ import {
|
|
|
2
2
|
EngineProvider,
|
|
3
3
|
hasPreviewSnapshot,
|
|
4
4
|
setPreviewSnapshot
|
|
5
|
-
} from "./chunk-
|
|
6
|
-
import "./chunk-
|
|
5
|
+
} from "./chunk-Q665T4L7.js";
|
|
6
|
+
import "./chunk-2TNVB2ON.js";
|
|
7
7
|
import {
|
|
8
8
|
Active,
|
|
9
9
|
Camera,
|
|
@@ -26,7 +26,7 @@ import {
|
|
|
26
26
|
navFlightActive,
|
|
27
27
|
pickTopAt,
|
|
28
28
|
widgets
|
|
29
|
-
} from "./chunk-
|
|
29
|
+
} from "./chunk-VGVDJZSP.js";
|
|
30
30
|
import {
|
|
31
31
|
compositeCameraFrustum,
|
|
32
32
|
computeIslandPhase,
|
package/dist/react.js
CHANGED
|
@@ -25,9 +25,9 @@ import {
|
|
|
25
25
|
useWidgetProps,
|
|
26
26
|
useWorld,
|
|
27
27
|
useWorldComponent
|
|
28
|
-
} from "./chunk-
|
|
29
|
-
import "./chunk-
|
|
30
|
-
import "./chunk-
|
|
28
|
+
} from "./chunk-Q665T4L7.js";
|
|
29
|
+
import "./chunk-2TNVB2ON.js";
|
|
30
|
+
import "./chunk-VGVDJZSP.js";
|
|
31
31
|
import "./chunk-OR5FNVUE.js";
|
|
32
32
|
export {
|
|
33
33
|
EngineProvider,
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* scene systems · doc kit · publish step · engine facade · reflector registry.
|
|
4
4
|
* Import wall: strata-ecs + @ice/kernel ONLY — never react/dom/three (enforced).
|
|
5
5
|
*/
|
|
6
|
-
export declare const CORE_VERSION = "0.
|
|
6
|
+
export declare const CORE_VERSION = "0.11.0";
|
|
7
7
|
export { defineSchemaOnce, hmrInvalidateOnSchemaChange } from "./boot/hmr";
|
|
8
8
|
export { All, Any, Not, Related, createWorld, defineQuery, defineSystem, defineTickSystem, enumOf, field, Local, } from "@vibecook/strata-ecs";
|
|
9
9
|
export type { Batch, Component, Condition, Entity, OrderPlace, Pipeline, Query, Relation, Resource, System, SystemCtx, Tag, TickSystem, World, } from "@vibecook/strata-ecs";
|
|
@@ -23,13 +23,14 @@ export interface GridConfig {
|
|
|
23
23
|
/** Per-level opacity weight: level i gets (base + i * step). */
|
|
24
24
|
levelWeight: [number, number];
|
|
25
25
|
/**
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
26
|
+
* Magnet-lattice tuning. The production grid implementation is selected at
|
|
27
|
+
* build time; this block never switches renderers at runtime. The magnet
|
|
28
|
+
* implementation resolves an absent/partial block over
|
|
29
|
+
* {@link DEFAULT_GRID_MAGNET_CONFIG}; the classic implementation accepts
|
|
30
|
+
* the same GridConfig contract and ignores this block.
|
|
31
|
+
*
|
|
32
|
+
* `configureGrid` deep-merges this key one level, so a partial re-tune such
|
|
33
|
+
* as `{ magnet: { reach: 80 } }` never clobbers the rest of the block.
|
|
33
34
|
*/
|
|
34
35
|
magnet?: Partial<GridMagnetConfig>;
|
|
35
36
|
}
|
|
@@ -39,8 +40,6 @@ export interface GridConfig {
|
|
|
39
40
|
* strength curves) lives in whichever `PoleSource` the app wired (D5).
|
|
40
41
|
*/
|
|
41
42
|
export interface GridMagnetConfig {
|
|
42
|
-
/** Master switch. false = classic analytic grid (the default). */
|
|
43
|
-
enabled: boolean;
|
|
44
43
|
/** Needles orient along the field; dots stay on the lattice and swell with |field|. */
|
|
45
44
|
glyph: "dot" | "needle";
|
|
46
45
|
/** CSS px at which a lone source has influence 0.5 (k = 0.5·reach²). */
|
|
@@ -66,12 +65,11 @@ export interface GridMagnetConfig {
|
|
|
66
65
|
}
|
|
67
66
|
/** Experiment-calibrated defaults (vibe-field draft/magnet-grid HUD values). */
|
|
68
67
|
export declare const DEFAULT_GRID_MAGNET_CONFIG: GridMagnetConfig;
|
|
69
|
-
/**
|
|
70
|
-
*
|
|
71
|
-
*
|
|
72
|
-
*
|
|
73
|
-
|
|
74
|
-
* found live on the M17 build's first screenshot (design-010 §3.1 amendment). */
|
|
68
|
+
/**
|
|
69
|
+
* Shared visual defaults inherited from the original analytic grid. The
|
|
70
|
+
* magnet block stays optional so apps can state only the magnet values they
|
|
71
|
+
* tune; the wired implementation resolves the remainder independently.
|
|
72
|
+
*/
|
|
75
73
|
export declare const DEFAULT_GRID_CONFIG: GridConfig;
|
|
76
74
|
/** Minimal-neutral wire styling (design-004 §6: chrome is subdued; wires defer to content). */
|
|
77
75
|
export interface WiresConfig {
|