lecodes-cli 0.16.1 → 0.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/README.md +27 -4
  2. package/dist/index.js +171621 -382
  3. package/package.json +13 -7
  4. package/runtime/sdk/compile/bundler.ts +10 -2
  5. package/runtime/sdk/compile/compileProject.ts +10 -2
  6. package/runtime/sdk/compile/detectEntry.ts +5 -2
  7. package/runtime/sdk/compile/index.ts +17 -1
  8. package/runtime/sdk/compile/serverSplit.ts +233 -0
  9. package/runtime/sdk/compile/serverTypes.ts +227 -0
  10. package/runtime/sdk/gl/AnimationClip.ts +174 -0
  11. package/runtime/sdk/gl/Animator.ts +642 -0
  12. package/runtime/sdk/gl/CharacterController.ts +6 -1
  13. package/runtime/sdk/gl/IK.ts +170 -0
  14. package/runtime/sdk/gl/Material.ts +1 -1
  15. package/runtime/sdk/gl/ModelAnimation.ts +34 -3
  16. package/runtime/sdk/gl/Node.ts +27 -1
  17. package/runtime/sdk/gl/Scene.ts +291 -289
  18. package/runtime/sdk/gl/state.ts +6 -6
  19. package/runtime/sdk/inject.ts +10 -0
  20. package/runtime/sdk/plugins/oauth.ts +61 -0
  21. package/runtime/sdk/runtime/rpc.ts +218 -0
  22. package/runtime/sdk/server/auth/appConfig.ts +12 -0
  23. package/runtime/sdk/server/auth/global.ts +80 -0
  24. package/runtime/sdk/server/auth/host.ts +318 -0
  25. package/runtime/sdk/server/auth/models.ts +83 -0
  26. package/runtime/sdk/server/auth/types.ts +50 -0
  27. package/runtime/sdk/server/channel.ts +56 -0
  28. package/runtime/sdk/server/context.ts +36 -0
  29. package/runtime/sdk/server/db/defineDb.ts +237 -0
  30. package/runtime/sdk/server/db/fields.ts +132 -0
  31. package/runtime/sdk/server/db/httpTransport.ts +93 -0
  32. package/runtime/sdk/server/db/index.ts +7 -0
  33. package/runtime/sdk/server/db/marci/query.ts +412 -0
  34. package/runtime/sdk/server/db/types.ts +202 -0
  35. package/runtime/sdk/server/errors.ts +12 -0
  36. package/runtime/sdk/server/host.ts +74 -0
  37. package/runtime/sdk/server/inject.ts +13 -0
  38. package/runtime/sdk/server/runtime.ts +133 -0
  39. package/runtime/sdk/server/validate.ts +87 -0
  40. package/runtime/sdk-types.json +1 -1
@@ -1 +1 @@
1
- {"global.d.ts":"// AUTO-GENERATED by build-types.ts. The import-free type surface for le.codes projects:\n// every SDK global declared ambiently, so user code uses Scene / Sprite / UIScreen / … \n// with no imports and full editor autocomplete.\n\nimport type * as SDK from \"./types/inject\"\n\ndeclare global {\n const ARScene: typeof SDK.ARScene\n const Aspect: typeof SDK.Aspect\n const AudioPlayer: typeof SDK.AudioPlayer\n const Autotile2D: typeof SDK.Autotile2D\n const Bitmap: typeof SDK.Bitmap\n const Camera: typeof SDK.Camera\n const Camera2D: typeof SDK.Camera2D\n const CameraFollow: typeof SDK.CameraFollow\n const CameraView: typeof SDK.CameraView\n const Canvas: typeof SDK.Canvas\n const CharacterController: typeof SDK.CharacterController\n const CharacterController2D: typeof SDK.CharacterController2D\n const ClickEvent: typeof SDK.ClickEvent\n const Color: typeof SDK.Color\n const DateValue: typeof SDK.DateValue\n const File: typeof SDK.File\n const FollowPath: typeof SDK.FollowPath\n const FormData: typeof SDK.FormData\n const Geolocation: typeof SDK.Geolocation\n const Geometry: typeof SDK.Geometry\n const Input: typeof SDK.Input\n const InspectorUI: typeof SDK.InspectorUI\n const Light: typeof SDK.Light\n const LongPressEvent: typeof SDK.LongPressEvent\n const LookAt: typeof SDK.LookAt\n const Mat4: typeof SDK.Mat4\n const Material: typeof SDK.Material\n const Mathf: typeof SDK.Mathf\n const Mesh: typeof SDK.Mesh\n const Model: typeof SDK.Model\n const ModelAnimation: typeof SDK.ModelAnimation\n const MoveTo: typeof SDK.MoveTo\n const NativeView: typeof SDK.NativeView\n const Node: typeof SDK.Node\n const Node2D: typeof SDK.Node2D\n const Noise: typeof SDK.Noise\n const Particles: typeof SDK.Particles\n const Physics: typeof SDK.Physics\n const Physics2D: typeof SDK.Physics2D\n const Plane: typeof SDK.Plane\n const PlayAnimation: typeof SDK.PlayAnimation\n const Presentable: typeof SDK.Presentable\n const Push: typeof SDK.Push\n const QRScanner: typeof SDK.QRScanner\n const Quat: typeof SDK.Quat\n const Ray: typeof SDK.Ray\n const Router: typeof SDK.Router\n const Scene: typeof SDK.Scene\n const Scene2D: typeof SDK.Scene2D\n const Scene2dHandle: typeof SDK.Scene2dHandle\n const SceneHandle: typeof SDK.SceneHandle\n const Service: typeof SDK.Service\n const Shape: typeof SDK.Shape\n const Shape2D: typeof SDK.Shape2D\n const Spin: typeof SDK.Spin\n const Sprite: typeof SDK.Sprite\n const SpriteAnimation: typeof SDK.SpriteAnimation\n const SpriteSheet: typeof SDK.SpriteSheet\n const SvgSource: typeof SDK.SvgSource\n const Texture: typeof SDK.Texture\n const Texture2D: typeof SDK.Texture2D\n const Tilemap: typeof SDK.Tilemap\n const Tileset: typeof SDK.Tileset\n const TouchStartEvent: typeof SDK.TouchStartEvent\n const Trail: typeof SDK.Trail\n const Trigger: typeof SDK.Trigger\n const Trigger2D: typeof SDK.Trigger2D\n const UIBottomSheet: typeof SDK.UIBottomSheet\n const UIBox: typeof SDK.UIBox\n const UIButton: typeof SDK.UIButton\n const UIColumn: typeof SDK.UIColumn\n const UIImage: typeof SDK.UIImage\n const UIInput: typeof SDK.UIInput\n const UIModal: typeof SDK.UIModal\n const UIPager: typeof SDK.UIPager\n const UIPopover: typeof SDK.UIPopover\n const UIRow: typeof SDK.UIRow\n const UIScreen: typeof SDK.UIScreen\n const UIScrollable: typeof SDK.UIScrollable\n const UISpacer: typeof SDK.UISpacer\n const UITabs: typeof SDK.UITabs\n const UIText: typeof SDK.UIText\n const UITextArea: typeof SDK.UITextArea\n const UIVideo: typeof SDK.UIVideo\n const UIVirtualizedList: typeof SDK.UIVirtualizedList\n const UIWidget: typeof SDK.UIWidget\n const VRScene: typeof SDK.VRScene\n const Vec2: typeof SDK.Vec2\n const Vec3: typeof SDK.Vec3\n const VideoPlayer: typeof SDK.VideoPlayer\n const WebSocket: typeof SDK.WebSocket\n const __UIBox: typeof SDK.__UIBox\n const __UIButton: typeof SDK.__UIButton\n const __UIColumn: typeof SDK.__UIColumn\n const __UIRow: typeof SDK.__UIRow\n const __UIScreen: typeof SDK.__UIScreen\n const __UIScrollable: typeof SDK.__UIScrollable\n const __UIWidget: typeof SDK.__UIWidget\n const __editorPlugins: typeof SDK.__editorPlugins\n const __uiMap: typeof SDK.__uiMap\n const animate: typeof SDK.animate\n const animateMat4: typeof SDK.animateMat4\n const app: typeof SDK.app\n const cells: typeof SDK.cells\n const clipboard: typeof SDK.clipboard\n const colorCurve: typeof SDK.colorCurve\n const computed: typeof SDK.computed\n const cubicBezier: typeof SDK.cubicBezier\n const curve: typeof SDK.curve\n const date: typeof SDK.date\n const defineScene: typeof SDK.defineScene\n const defineScene2d: typeof SDK.defineScene2d\n const defineSpriteSheet: typeof SDK.defineSpriteSheet\n const defineTabs: typeof SDK.defineTabs\n const defineTileset: typeof SDK.defineTileset\n const device: typeof SDK.device\n const easeIn: typeof SDK.easeIn\n const easeInOut: typeof SDK.easeInOut\n const easeOut: typeof SDK.easeOut\n const effect: typeof SDK.effect\n const encodeCells: typeof SDK.encodeCells\n const fetch: typeof SDK.fetch\n const fetchLocal: typeof SDK.fetchLocal\n const flipX: typeof SDK.flipX\n const isRawCell: typeof SDK.isRawCell\n const localStorage: typeof SDK.localStorage\n const make: typeof SDK.make\n const openFilePicker: typeof SDK.openFilePicker\n const openURL: typeof SDK.openURL\n const packTile: typeof SDK.packTile\n const pauseAnimation: typeof SDK.pauseAnimation\n const rawCell: typeof SDK.rawCell\n const rawIndex: typeof SDK.rawIndex\n const ref: typeof SDK.ref\n const registerEditorTool: typeof SDK.registerEditorTool\n const registerEditorWindow: typeof SDK.registerEditorWindow\n const registerFont: typeof SDK.registerFont\n const resumeAnimation: typeof SDK.resumeAnimation\n const rot180: typeof SDK.rot180\n const rot270: typeof SDK.rot270\n const rot90: typeof SDK.rot90\n const share: typeof SDK.share\n const signal: typeof SDK.signal\n const stopAnimation: typeof SDK.stopAnimation\n const theme: typeof SDK.theme\n const tileFlip: typeof SDK.tileFlip\n const tileIndex: typeof SDK.tileIndex\n const tileOriented: typeof SDK.tileOriented\n const tileTurns: typeof SDK.tileTurns\n const toast: typeof SDK.toast\n const use: typeof SDK.use\n type ARScene<T extends ARMode = \"default\"> = SDK.ARScene<T>\n type AppState = SDK.AppState\n type Aspect<K extends string, P = Node> = SDK.Aspect<K, P>\n type AspectEntry<A extends Aspect<any, any> = Aspect<any, any>> = SDK.AspectEntry<A>\n type AudioPlayer = SDK.AudioPlayer\n type Autotile2D = SDK.Autotile2D\n type Bitmap = SDK.Bitmap\n type BlockEntry = SDK.BlockEntry\n type Camera = SDK.Camera\n type Camera2D = SDK.Camera2D\n type Camera2dNodeDef = SDK.Camera2dNodeDef\n type CameraFacing = SDK.CameraFacing\n type CameraFollow = SDK.CameraFollow\n type CameraNodeDef = SDK.CameraNodeDef\n type CameraView = SDK.CameraView\n type Canvas = SDK.Canvas\n type CellsData = SDK.CellsData\n type CharacterController = SDK.CharacterController\n type CharacterController2D = SDK.CharacterController2D\n type ClickEvent<T = any> = SDK.ClickEvent<T>\n type Computed<T> = SDK.Computed<T>\n type DateInput = SDK.DateInput\n type DateValue = SDK.DateValue\n type EdgeSlot = SDK.EdgeSlot\n type EditorApi = SDK.EditorApi\n type EditorRayHit = SDK.EditorRayHit\n type EditorToolHooks = SDK.EditorToolHooks\n type EditorWindowFn = SDK.EditorWindowFn\n type FetchResponse = SDK.FetchResponse\n type FieldMeta<T = unknown> = SDK.FieldMeta<T>\n type File = SDK.File\n type FillBlock = SDK.FillBlock\n type FollowPath = SDK.FollowPath\n type FormData = SDK.FormData\n type GeoOptions = SDK.GeoOptions\n type GeoPosition = SDK.GeoPosition\n type GeoWatch = SDK.GeoWatch\n type Geometry = SDK.Geometry\n type HapticStyle = SDK.HapticStyle\n type InspectorUI = SDK.InspectorUI\n type Light = SDK.Light\n type LightDef = SDK.LightDef\n type LoadedScene<D extends SceneDef> = SDK.LoadedScene<D>\n type LoadedScene2d<D extends Scene2dDef> = SDK.LoadedScene2d<D>\n type Locale = SDK.Locale\n type LongPressEvent<T = any> = SDK.LongPressEvent<T>\n type LookAt = SDK.LookAt\n type MakeEntry<A extends Record<string, unknown> = Record<string, unknown>> = SDK.MakeEntry<A>\n type Mat4 = SDK.Mat4\n type Material = SDK.Material\n type MaterialDef = SDK.MaterialDef\n type Mesh = SDK.Mesh\n type MeshDef = SDK.MeshDef\n type Model = SDK.Model\n type ModelAnimation = SDK.ModelAnimation\n type MotionOptions = SDK.MotionOptions\n type MoveTo = SDK.MoveTo\n type NativeView = SDK.NativeView\n type Node = SDK.Node\n type Node2D = SDK.Node2D\n type Noise = SDK.Noise\n type Particles = SDK.Particles\n type PatchMaterial = SDK.PatchMaterial\n type PatchSlots = SDK.PatchSlots\n type PathMaterial = SDK.PathMaterial\n type Physics = SDK.Physics\n type Physics2D = SDK.Physics2D\n type Plane = SDK.Plane\n type PlayAnimation = SDK.PlayAnimation\n type PresentOptions = SDK.PresentOptions\n type Presentable = SDK.Presentable\n type PushEvent = SDK.PushEvent\n type PushPayload = SDK.PushPayload\n type PushRegisterOptions = SDK.PushRegisterOptions\n type PushStatus = SDK.PushStatus\n type QRScanner = SDK.QRScanner\n type Quat = SDK.Quat\n type Ray = SDK.Ray\n type Scene = SDK.Scene\n type Scene2D = SDK.Scene2D\n type Scene2dDef = SDK.Scene2dDef\n type Scene2dEnv = SDK.Scene2dEnv\n type Scene2dHandle<D extends Scene2dDef = Scene2dDef> = SDK.Scene2dHandle<D>\n type Scene2dNodeDef = SDK.Scene2dNodeDef\n type SceneDef = SDK.SceneDef\n type SceneHandle<D extends SceneDef = SceneDef> = SDK.SceneHandle<D>\n type SceneNodeDef = SDK.SceneNodeDef\n type Service = SDK.Service\n type Shape = SDK.Shape\n type Shape2D = SDK.Shape2D\n type SheetSprite = SDK.SheetSprite\n type Signal<T> = SDK.Signal<T>\n type Spin = SDK.Spin\n type Sprite = SDK.Sprite\n type SpriteAnimation = SDK.SpriteAnimation\n type SpriteMakeOptions = SDK.SpriteMakeOptions\n type SpriteSheet = SDK.SpriteSheet\n type SpriteSheetDef = SDK.SpriteSheetDef\n type SpriteSourceDef = SDK.SpriteSourceDef\n type TabDef = SDK.TabDef\n type TabsHandle<T extends Record<string, TabDef>> = SDK.TabsHandle<T>\n type Texture = SDK.Texture\n type Texture2D = SDK.Texture2D\n type ThemeAccessors<T> = SDK.ThemeAccessors<T>\n type ThemeValues = SDK.ThemeValues\n type TileBlock = SDK.TileBlock\n type TileMaterial = SDK.TileMaterial\n type TilePart = SDK.TilePart\n type Tilemap = SDK.Tilemap\n type TilemapSourceDef = SDK.TilemapSourceDef\n type Tileset = SDK.Tileset\n type TilesetDef = SDK.TilesetDef\n type TouchStartEvent<T = any> = SDK.TouchStartEvent<T>\n type Trail = SDK.Trail\n type Transition = SDK.Transition\n type TransitionName = SDK.TransitionName\n type TransitionSpec = SDK.TransitionSpec\n type TransitionTransform = SDK.TransitionTransform\n type Trigger = SDK.Trigger\n type Trigger2D = SDK.Trigger2D\n type UIBottomSheet = SDK.UIBottomSheet\n type UIBottomSheetStyle = SDK.UIBottomSheetStyle\n type UIBox = SDK.UIBox\n type UIButton = SDK.UIButton\n type UIButtonStyle = SDK.UIButtonStyle\n type UIColumn = SDK.UIColumn\n type UIContainerStyle = SDK.UIContainerStyle\n type UIImage = SDK.UIImage\n type UIImageStyle = SDK.UIImageStyle\n type UIInput = SDK.UIInput\n type UIInputStyle = SDK.UIInputStyle\n type UIModal = SDK.UIModal\n type UIModalStyle = SDK.UIModalStyle\n type UINativeViewStyle = SDK.UINativeViewStyle\n type UINode = SDK.UINode\n type UINodeChild = SDK.UINodeChild\n type UIPager = SDK.UIPager\n type UIPagerStyle = SDK.UIPagerStyle\n type UIPopover = SDK.UIPopover\n type UIPopoverStyle = SDK.UIPopoverStyle\n type UIRow = SDK.UIRow\n type UIScreen = SDK.UIScreen\n type UIScreenStyle = SDK.UIScreenStyle\n type UIScrollable = SDK.UIScrollable\n type UIScrollableStyle = SDK.UIScrollableStyle\n type UISpacer = SDK.UISpacer\n type UISpacerStyle = SDK.UISpacerStyle\n type UITabDef = SDK.UITabDef\n type UITabs = SDK.UITabs\n type UIText = SDK.UIText\n type UITextArea = SDK.UITextArea\n type UITextStyle = SDK.UITextStyle\n type UIVideo = SDK.UIVideo\n type UIVideoStyle = SDK.UIVideoStyle\n type UIVirtualizedList<T = unknown> = SDK.UIVirtualizedList<T>\n type UIWidget = SDK.UIWidget\n type UIWidgetStyle = SDK.UIWidgetStyle\n type Unit = SDK.Unit\n type VRScene = SDK.VRScene\n type Vec2 = SDK.Vec2\n type Vec3 = SDK.Vec3\n type VideoPlayer = SDK.VideoPlayer\n type WebSocket = SDK.WebSocket\n type With<N, A extends Aspect<any, any>> = SDK.With<N, A>\n}\n\nexport {}\n","host.d.ts":"// JS-runtime globals provided by the host engine (web viewer / desktop / iOS), NOT by the SDK.\n// Declared only so SDK and user code type-check — never bundled or injected. Mirrors\n// packages/projects/src/global.d.ts.\n\ndeclare global {\n function setTimeout(handler: (...args: any[]) => void, timeout?: number): number\n function setInterval(handler: (...args: any[]) => void, timeout?: number): number\n function clearTimeout(id: number): void\n function clearInterval(id: number): void\n /** Per-frame loop, driven by the host (viewer RAF / desktop runTick). `dt` is **seconds** since\n * the previous frame. */\n function setLoop(handler: (dt: number) => void): number\n function clearLoop(id: number): void\n\n /** π/180 — substituted at compile time (bundler `define`). */\n var DEG2RAD: number\n /** 180/π — substituted at compile time (bundler `define`). */\n var RAD2DEG: number\n\n /** Compile-time boolean: `true` in scene-editor bundles, `false` (const-folded + DCE'd) in\n * shipped ones — `if (EDITOR) { … }` costs zero bytes in production. `*.editor.ts` files are\n * the file-level form. */\n var EDITOR: boolean\n\n var console: {\n log(...data: any[]): void\n warn(...data: any[]): void\n info(...data: any[]): void\n error(...data: any[]): void\n }\n\n /** Compile-time macro: `asset('./hero.png')` is desugared by the bundler into the module import\n * for that resource. */\n function asset(path: string): string\n\n /** Compile-time macro: installs a font and returns its family name — using a font IS declaring\n * it. A registry id (`font(\"manrope\")`) resolves against the font registry; a project path\n * (`font(\"./fonts/Brand.ttf\")`) reads family/weight/italic from the file itself. `opts`\n * narrows/extends the face set (default: the family's standard weights). String-literal\n * argument only. No awaiting — faces load with app boot and the host holds first paint for\n * them. */\n function font(id: string, opts?: { weights?: number[], italic?: boolean }): string\n\n /** Compile-time macro: resolves one icon from the icon registry at build time and inlines it as\n * an image source for `UIImage(...)` — offline, identical on every host. `id` is `\"pack:name\"`\n * (e.g. `\"lucide:bell\"`), string literal only. Recolor via `{ color }`: a hex LITERAL is baked\n * into the SVG at compile time, a token/expression is applied as a tint (as is the `tintColor`\n * style prop). */\n function assetIcon(id: string, opts?: { color?: string }): { readonly svg: string, tintColor: string | null }\n\n /** Type-only editor convenience: the style object type of a UI element. `Style<UIButton>` (or\n * `Style<typeof myButton>`) is what you'd pass to `el.style(...)` — for typing reusable style\n * presets. Deliberately no `Partial<>` wrapper: every style prop is already optional, and\n * Partial over ClassStyles' `$`-index signature adds `| undefined`, breaking assignability back\n * into `.style(...)`. Round-trip guarded by sdk/tests/ui-types.test.ts. */\n type Style<T> = T extends { style: (s: infer S) => any } ? S : never\n}\n\nexport {}\n","types/animate/animate.d.ts":"type mat4 = Float32Array | number[];\ntype quat = Float32Array | number[];\ntype vec2 = Float32Array | number[];\ntype vec3 = Float32Array | number[];\nimport type { Easing } from \"./easings\";\ntype AnimateProps = number | string | vec2 | vec3 | quat;\nexport type AnimateOptions<T> = {\n from: T;\n to: T;\n duration: number;\n onUpdate(val: T): void;\n onComplete?(): void;\n easing?: Easing;\n};\nexport declare const animate: <T extends AnimateProps>(options: AnimateOptions<T>) => number;\nexport declare const stopAnimation: (id: number) => void;\nexport declare const pauseAnimation: (id: number) => void;\nexport declare const resumeAnimation: (id: number) => void;\nexport declare const animateMat4: (options: AnimateOptions<mat4>) => number;\nexport {};\n","types/animate/bezier.d.ts":"import type { Easing } from \"./easings\";\nexport declare function cubicBezier(mX1: number, mY1: number, mX2: number, mY2: number): Easing;\n","types/animate/easings.d.ts":"export type Easing = (v: number) => number;\nexport type EasingModifier = (easing: Easing) => Easing;\nexport declare function linear(p: number): number;\nexport declare function bounceOut(p: number): number;\nexport declare function bounceInOut(p: number): number;\nexport declare function reverseEasing(easing: Easing): Easing;\nexport declare function mirrorEasing(easing: Easing): Easing;\nexport declare function createExpoIn(power: number): Easing;\nexport declare function createBackIn(power: number): Easing;\nexport declare function createAnticipate(power: number): Easing;\nexport declare function bounceIn(p: number): number;\nexport declare function easeIn(p: number): number;\nexport declare function easeOut(p: number): number;\nexport declare function easeInOut(p: number): number;\nexport declare function circIn(p: number): number;\nexport declare function circOut(p: number): number;\nexport declare function circInOut(p: number): number;\nexport declare function backIn(p: number): number;\nexport declare function backOut(p: number): number;\nexport declare function backInOut(p: number): number;\nexport declare function anticipate(p: number): number;\n","types/canvas/Canvas.d.ts":"import { Texture2D } from \"../g2/Texture2D\";\nimport { File, type FetchResponse } from \"../runtime/fetch\";\nimport type { SvgSourceValue } from \"../runtime/misc\";\ndeclare const ALIGN: {\n readonly left: 0;\n readonly center: 1;\n readonly right: 2;\n readonly start: 3;\n readonly end: 4;\n};\ndeclare const BASELINE: {\n readonly alphabetic: 0;\n readonly top: 1;\n readonly middle: 2;\n readonly bottom: 3;\n readonly hanging: 4;\n readonly ideographic: 5;\n};\ndeclare const JOIN: {\n readonly miter: 0;\n readonly round: 1;\n readonly bevel: 2;\n};\ndeclare const CAP: {\n readonly butt: 0;\n readonly round: 1;\n readonly square: 2;\n};\nexport type TextAlign = keyof typeof ALIGN;\nexport type TextBaseline = keyof typeof BASELINE;\nexport type LineJoin = keyof typeof JOIN;\nexport type LineCap = keyof typeof CAP;\nexport interface CanvasTextMetrics {\n width: number;\n ascent: number;\n descent: number;\n}\nexport declare class Canvas {\n /** Brand so `Sprite`/`UIImage`/`Material` can accept a Canvas anywhere a texture source is expected. */\n readonly __canvas: true;\n width: number;\n height: number;\n /** Device-pixel multiplier (draw at 2 for crisp retina text). Applied by the backend. */\n pixelRatio: number;\n private _cmd;\n private _refs;\n private _globalAlpha;\n private _fillStyle;\n private _strokeStyle;\n private _lineWidth;\n private _lineJoin;\n private _lineCap;\n private _font;\n private _textAlign;\n private _textBaseline;\n private _surfaceId;\n private _tex2d?;\n private _uiBound;\n constructor(width: number, height: number, opts?: {\n pixelRatio?: number;\n });\n private _ref;\n /** Discard the recorded drawing to start a new one (for dynamic canvases). */\n reset(): this;\n /** Change the surface size; takes effect on the next bake. */\n resize(width: number, height: number): this;\n save(): this;\n restore(): this;\n translate(x: number, y: number): this;\n scale(sx: number, sy: number): this;\n rotate(rad: number): this;\n get globalAlpha(): number;\n set globalAlpha(a: number);\n get fillStyle(): string;\n set fillStyle(color: string);\n get strokeStyle(): string;\n set strokeStyle(color: string);\n get lineWidth(): number;\n set lineWidth(w: number);\n get lineJoin(): LineJoin;\n set lineJoin(j: LineJoin);\n get lineCap(): LineCap;\n set lineCap(c: LineCap);\n get font(): string;\n set font(f: string);\n get textAlign(): TextAlign;\n set textAlign(a: TextAlign);\n get textBaseline(): TextBaseline;\n set textBaseline(b: TextBaseline);\n beginPath(): this;\n closePath(): this;\n moveTo(x: number, y: number): this;\n lineTo(x: number, y: number): this;\n quadraticCurveTo(cx: number, cy: number, x: number, y: number): this;\n bezierCurveTo(c1x: number, c1y: number, c2x: number, c2y: number, x: number, y: number): this;\n arc(x: number, y: number, r: number, a0: number, a1: number, ccw?: boolean): this;\n rect(x: number, y: number, w: number, h: number): this;\n roundRect(x: number, y: number, w: number, h: number, r: number): this;\n fill(evenOdd?: boolean): this;\n stroke(): this;\n fillRect(x: number, y: number, w: number, h: number): this;\n strokeRect(x: number, y: number, w: number, h: number): this;\n clearRect(x: number, y: number, w: number, h: number): this;\n fillText(text: string, x: number, y: number, maxWidth?: number): this;\n strokeText(text: string, x: number, y: number, maxWidth?: number): this;\n /** Blit a `Bitmap` (a snapshot from `toBitmap()`) onto this canvas. All coordinates are LOGICAL —\n * including the source sub-rect in the 9-arg form (it's scaled by the bitmap's pixelRatio here).\n * Records a DRAW_IMAGE op, so the blit runs at bake time: keep the Bitmap alive until the next\n * `update()`/`toBitmap()`/`texture()`. Three browser-style forms:\n * drawImage(bmp, dx, dy) — whole bitmap at its natural size\n * drawImage(bmp, dx, dy, dw, dh) — whole bitmap, scaled into dw×dh\n * drawImage(bmp, sx, sy, sw, sh, dx, dy, dw, dh) — a sub-rect of the bitmap, scaled into dw×dh */\n drawImage(img: Bitmap, dx: number, dy: number): this;\n drawImage(img: Bitmap, dx: number, dy: number, dw: number, dh: number): this;\n drawImage(img: Bitmap, sx: number, sy: number, sw: number, sh: number, dx: number, dy: number, dw: number, dh: number): this;\n /** Decode an image source into a standalone `Bitmap` you can blit with `drawImage()` — either an\n * `SvgSource(...)` (rasterized) or a `FetchResponse` holding already-fetched image bytes (decoded).\n * This is async because turning SVG markup / encoded bytes into pixels needs a decode step (on the\n * web, `createImageBitmap` / an `<img>` load); `await` it ONCE, then `drawImage(bitmap, …)` is\n * synchronous and the Bitmap is reusable. The returned Bitmap owns a native surface at the image's\n * natural pixel size (`pixelRatio` 1) — `destroy()` it when done. Typical use:\n * const logo = await canvas.loadImage(SvgSource(svg)) // or: await fetch(url) → the response\n * canvas.drawImage(logo, 0, 0) // sync, blit as often as you like */\n loadImage(source: SvgSourceValue | FetchResponse): Promise<Bitmap>;\n /** Measure `text` in the current font on THIS platform. The one synchronous round-trip. */\n measureText(text: string): CanvasTextMetrics;\n /** Bake and return the 2D texture (created once, then cached). */\n texture(): Texture2D;\n /** Re-rasterize and re-upload to every texture this canvas produced (call after redrawing) — the\n * cached 2D and/or 3D texture, whichever engines this canvas was baked into. */\n update(): this;\n /** Copy the current pixels into a standalone, immutable `Bitmap` — independent of this canvas, so\n * later drawing/`reset()` never touches it. Draw it back with `drawImage()`, export it with\n * `toDataURL()`, or use it to \"flatten\" an ever-growing drawing so re-bakes stay O(1):\n * const snap = canvas.toBitmap()\n * canvas.reset(); canvas.drawImage(snap, 0, 0) // one op replaces the whole history\n * // …keep drawing on top; snap.destroy() once it's been drawn in. */\n toBitmap(): Bitmap;\n /** Encode the current pixels to an image `File` — 'image/png' (default) or 'image/jpeg'. The File\n * is an opaque host buffer handle (`name`/`size` only): append it to a FormData to upload, load it\n * as a texture (`Texture2D.load(file)`), or hand it to a share/save sheet. */\n toFile(name?: string, type?: string): Promise<File>;\n destroy(): void;\n}\n/** Duck-type guard so consumers can accept a Canvas anywhere a texture source is expected. */\nexport declare const isCanvas: (v: unknown) => v is Canvas;\n/** An immutable RGBA8 snapshot of a canvas, produced by `Canvas.toBitmap()`. It owns its own baked\n * surface (a copy), so the source canvas can keep drawing or `reset()` without affecting it. Use it\n * to stamp/blit back (`canvas.drawImage(bitmap, …)`), to export (`bitmap.toDataURL()`), or as a\n * cheap \"layer\" you composite. Call `destroy()` when done — it holds a native surface. */\nexport declare class Bitmap {\n readonly __bitmap: true;\n /** Logical width, matching the Canvas it was captured from (pixelRatio is crispness, not size). */\n readonly width: number;\n readonly height: number;\n readonly pixelRatio: number;\n constructor(surfaceId: number, width: number, height: number, pixelRatio: number);\n /** Device-pixel dimensions of the stored bitmap (`width * pixelRatio`, rounded). */\n get pixelWidth(): number;\n get pixelHeight(): number;\n /** Encode to an image `File` — 'image/png' (default) or 'image/jpeg'. See `Canvas.toFile`. */\n toFile(name?: string, type?: string): Promise<File>;\n /** Free the native surface. The bitmap must not be drawn or encoded afterwards. */\n destroy(): void;\n}\n/** Duck-type guard for a Bitmap (see `isCanvas`). */\nexport declare const isBitmap: (v: unknown) => v is Bitmap;\nexport {};\n","types/core/Aspect.d.ts":"import { Emitter, type EventMap } from \"./events\";\nimport type { InspectorUI } from \"./InspectorUI\";\nimport type { Node } from \"../gl/Node\";\n/** The class object of an aspect — accepted even when its constructor is protected/abstract. */\nexport type AspectCtor<A extends Aspect<any, any>> = abstract new () => A;\n/** The accessor name carried in the aspect's generic. */\nexport type KeyOf<A> = A extends Aspect<infer K, any> ? K : never;\n/** The node kind an aspect targets. */\nexport type TargetOf<A> = A extends Aspect<any, infer P> ? P : never;\n/** `{ name: Aspect }` — the field an aspect contributes to its node. */\nexport type FieldOf<A extends Aspect<any, any>> = {\n [P in KeyOf<A>]: A;\n};\ntype UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (k: infer I) => void ? I : never;\n/**\n * A variable typed as a node KNOWN to carry the given aspect(s). Union, not a tuple — reads as\n * English and mirrors the runtime guard `node.has(Health)`:\n * let boss: With<Sprite, Health | Physics>\n */\nexport type With<N, A extends Aspect<any, any>> = N & UnionToIntersection<A extends any ? FieldOf<A> : never>;\n/**\n * Base for anything that can carry aspects. Extends Emitter, so node kinds get events too. Provides\n * the four verbs; the named accessor (node.physics, node.health, …) is set as an own property at\n * attach time, keyed by the aspect class's runtime `aspect` name.\n */\nexport declare abstract class AspectHost<E extends EventMap = EventMap> extends Emitter<E> {\n /** Attach (and configure) an aspect, or reconfigure it if already present. Returns the node typed\n * as now-having that aspect (so no guard/`?.` is needed afterwards). Rejects a wrong target node. */\n aspect<Self extends TargetOf<A>, A extends Aspect<any, any>>(this: Self, ctor: AspectCtor<A>, opts?: Partial<A>): Self & FieldOf<A>;\n /** Safe access — undefined if the aspect isn't attached. */\n get<A extends Aspect<any, any>>(ctor: AspectCtor<A>): A | undefined;\n /** Existence check AND type guard: inside `if (node.has(Physics))`, `node.physics` is present. */\n has<A extends Aspect<any, any>>(ctor: AspectCtor<A>): this is this & FieldOf<A>;\n /** Detach an aspect (runs its onDetach). Named `removeAspect` so it never collides with the\n * child-management `add`/`remove` semantics some node kinds expose. */\n removeAspect<A extends Aspect<any, any>>(ctor: AspectCtor<A>): this;\n}\n/**\n * Base for everything you attach. `K` = accessor name (extracted by chisel for the runtime). `P` =\n * the target node kind: `this.node` is typed to it, AND attaching to a wrong node is a compile error.\n * Initialize in `onAttach` (the node is set by then) — not a constructor; aspects are created by the\n * engine via `node.aspect()`, never `new`.\n */\nexport declare abstract class Aspect<K extends string, P = Node> {\n /**\n * Opt this aspect class into EDITOR-RUN mode (generators): while a scene is edited, the scene\n * loader constructs the instance (refs resolved, `node`/`generated` set — never `onAttach`) and\n * calls `rebuild()` — again on inspector prop edits and when a `ref()`-referenced node moves.\n * `static editor = { rebuild: true }`.\n */\n static editor?: {\n rebuild?: boolean;\n };\n /**\n * Custom inspector card for this aspect in the scene editor (immediate-mode — see\n * core/InspectorUI.ts): re-runs on every edit/event and emits a widget list. Without it, the\n * editor shows the inferred fields; `ui.auto()` emits those same fields, so a custom inspector\n * usually starts with `ui.auto()` and appends status lines / buttons / dynamic dropdowns:\n *\n * static inspector(ui: InspectorUI, self: MyAspect) {\n * ui.auto()\n * if (ui.button('Randomize')) self.rebuild()\n * }\n */\n static inspector?: (ui: InspectorUI, aspect: any) => void;\n /** The node this aspect is attached to (set at attach time). */\n readonly node: P;\n /**\n * GENERATOR aspects (`static editor = { rebuild: true }`, attached through a scene file): a\n * scene-added container child for the aspect's generated output — `rebuild()` clears and refills\n * it. Provided by the scene loader before `onAttach`/`rebuild` run; nodes `add()`ed to it join\n * the scene's draw set automatically (membership is separate from parenting). Undefined for\n * aspects attached by hand outside scene files. See docs/3d/scene-files.md.\n */\n readonly generated: Node & {\n clear(): void;\n };\n onAttach?(): void;\n onDetach?(): void;\n /**\n * GENERATOR aspects: (re)build the derived output under `this.generated` — must be idempotent\n * (clear, then create). Call it from `onAttach()` for play mode; a class opting in with\n * `static editor = { rebuild: true }` ALSO runs it while a scene is being edited: once at load,\n * and again whenever an inspector prop changes or a `ref()`-referenced node moves.\n */\n rebuild?(): void;\n /**\n * Called every frame while attached (dt = seconds since the last frame). Render-synced: runs in the\n * LATE phase by default — after the physics step + transform sync, right before the frame draws — so\n * reads of `node.worldPosition` are the final drawn position (cameras/followers have no 1-frame lag).\n * Set `updateBeforePhysics = true` (an instance field) to run in the EARLY phase (before the step)\n * instead — for aspects that WRITE velocity/force/kinematic transforms and want the same frame's\n * step to consume them. Cameras/followers READ, so they stay in the default LATE phase.\n */\n update?(dt: number): void;\n /** Run update(dt) in the EARLY phase (before the physics step) rather than the default LATE phase.\n * An instance field (like `updateWhenVisible`) — set it as a class field: `updateBeforePhysics = true`.\n * Use only when you FEED the simulation (velocity/force/kinematic transform). Read once, at attach. */\n updateBeforePhysics: boolean;\n /** Tick order within a phase — ascending; default 0, ties keep attach order. Read once, at attach. */\n order: number;\n /** Opt-in: only run update(dt) while the node is on-screen. NOOP for now — visibility culling isn't\n * wired yet, so every updater ticks regardless; declared so aspects can opt in ahead of it. */\n updateWhenVisible: boolean;\n}\nexport {};\n","types/core/color.d.ts":"export type ColorInput = string | number | readonly [number, number, number] | readonly [number, number, number, number];\nexport declare const Color: {\n /** [r,g,b] in 0..1 — for the 2D engine's float color setters. */\n toRgb01(c: ColorInput): [number, number, number];\n /** [r,g,b,a] in 0..1. */\n toRgba01(c: ColorInput): [number, number, number, number];\n /** 0xRRGGBB packed int — for the 3D engine's color uniforms / skybox. */\n toPackedRgb(c: ColorInput): number;\n /** 0xRRGGBBAA packed int (unsigned). */\n toPackedRgba(c: ColorInput): number;\n /** '#rrggbb' (or '#rrggbbaa' when alpha < 1) — for the 3D material color uniforms. */\n toHexString(c: ColorInput): string;\n};\n","types/core/events.d.ts":"export type EventMap = Record<string, (...args: any[]) => void>;\nexport declare class Emitter<E extends EventMap> {\n private _listeners;\n addEventListener<K extends keyof E>(channel: K, callback: E[K]): void;\n removeEventListener<K extends keyof E>(channel: K, callback: E[K]): void;\n /** Fire all listeners on a channel. Protected: only the owning class emits. */\n protected dispatch<K extends keyof E>(channel: K, ...args: Parameters<E[K]>): void;\n protected hasListeners<K extends keyof E>(channel: K): boolean;\n /** Drop every listener on every channel (used when the owning object is disposed). */\n protected clearListeners(): void;\n}\n","types/core/fields.d.ts":"/** Editor widget kinds the inspector knows how to render. `\"node\"` = a scene-node reference\n * (`ref('name')` in the file, name dropdown + pick-in-viewport in the inspector) — declare it via\n * `static fields` on fields typed `Node | null`; a `Node | null` type annotation is also picked\n * up syntactically by the editor's source scan. `\"asset\"` = a project-asset path (the editor\n * fills the dropdown with the project's GLBs — `ui.asset()` in windows/tools/cards). */\nexport type FieldEditor = \"number\" | \"text\" | \"color\" | \"switch\" | \"select\" | \"vec2\" | \"vec3\" | \"vec4\" | \"node\" | \"asset\";\nexport type FieldMetaEntry = {\n /** Inspector label (default: the field name). */\n label?: string;\n min?: number;\n max?: number;\n step?: number;\n /** Allowed values — renders a dropdown (editor \"select\"). */\n options?: readonly (string | number)[];\n /** Override the editor inferred from the default value. */\n editor?: FieldEditor;\n /** Exclude the field from the inspector. */\n hidden?: boolean;\n};\n/** Declared on an aspect class as `static fields: FieldMeta<MyAspect> = { … }`. All optional. */\nexport type FieldMeta<T = unknown> = {\n [K in Extract<keyof T, string>]?: FieldMetaEntry;\n};\n/** One editable field: key + default value + resolved editor + merged metadata. */\nexport type FieldDescriptor = {\n key: string;\n label: string;\n /** The default value (from a freshly constructed instance; undefined if only declared in meta). */\n value: unknown;\n /** Resolved editor kind; undefined = no editor known (inspector shows it read-only). */\n editor: FieldEditor | undefined;\n min?: number;\n max?: number;\n step?: number;\n options?: readonly (string | number)[];\n};\nexport type AspectClassInfo = {\n /** The accessor name (`static aspect`, injected by chisel for user aspects). */\n name: string;\n className: string;\n fields: FieldDescriptor[];\n /** True for editor-run classes (`static editor` — generators). The editor routes their\n * structural changes through a re-run instead of a live patch. */\n editor?: boolean;\n /** True when the class declares a custom `static inspector(ui, aspect)` card. */\n inspector?: boolean;\n};\n/** Infer the editor widget from a default value's shape. */\nexport declare const inferFieldEditor: (value: unknown) => FieldEditor | undefined;\n/**\n * Enumerate the editable fields of a class: construct a default instance, take its own enumerable\n * non-underscore fields (minus the Aspect base plumbing), infer editors from the default values, and\n * merge the class's optional `static fields` metadata (which can also add keys that have no runtime\n * default, e.g. fields declared without an initializer).\n */\nexport declare const describeFields: (ctor: abstract new () => unknown) => FieldDescriptor[];\n/** Describe an aspect class for the inspector: accessor name + class name + editable fields. */\nexport declare const describeAspect: (ctor: abstract new () => unknown) => AspectClassInfo;\n","types/core/InspectorUI.d.ts":"import type { FieldEditor } from \"./fields\";\n/** One user interaction coming back from the editor panel: the widget's id (+ value for fields). */\nexport type InspectorEvent = {\n id: string;\n value?: unknown;\n};\nexport type InspectorFieldWidget = {\n kind: \"field\";\n id: string;\n /** The bound key — an aspect field (doc-bound) or an editor-state key. */\n key: string;\n label: string;\n editor: FieldEditor | undefined;\n value: unknown;\n /** True = persisted to the scene file by the editor; false = transient editor state. */\n doc: boolean;\n /** True = emitted by `ui.auto()` — the editor may overlay its syntactic hints (options/node). */\n auto?: boolean;\n min?: number;\n max?: number;\n step?: number;\n options?: readonly (string | number)[];\n};\nexport type InspectorWidget = InspectorFieldWidget | {\n kind: \"button\";\n id: string;\n label: string;\n} | {\n kind: \"toolButton\";\n id: string;\n label: string;\n tool: string;\n} | {\n kind: \"header\";\n id: string;\n label: string;\n} | {\n kind: \"info\" | \"warn\";\n id: string;\n text: string;\n};\ntype FieldOpts = {\n label?: string;\n min?: number;\n max?: number;\n step?: number;\n /** Default for EDITOR-STATE keys (doc keys default from the class field). */\n value?: unknown;\n};\n/**\n * The widget builder handed to `static inspector(ui, aspect)` (and to editor windows/tools later).\n * One instance lives per card and persists across runs — it carries the card's editor state.\n */\nexport declare class InspectorUI {\n /** Numeric field (min/max/step render as a slider-style scrub range). */\n number(key: string, opts?: FieldOpts): number;\n /** Alias of `number` — give it min/max/step and the editor renders a scrubable range. */\n slider(key: string, opts?: FieldOpts): number;\n text(key: string, opts?: FieldOpts): string;\n color(key: string, opts?: FieldOpts): string;\n switch(key: string, opts?: FieldOpts): boolean;\n /** Dropdown — `options` may be computed fresh every run (dynamic lists come free). */\n select(key: string, options: readonly (string | number)[], opts?: FieldOpts): string | number;\n vec2(key: string, opts?: FieldOpts): [number, number];\n vec3(key: string, opts?: FieldOpts): [number, number, number];\n vec4(key: string, opts?: FieldOpts): [number, number, number, number];\n /** Scene-node reference (`ref()` fields): name dropdown + pick-in-viewport. Returns the RAW doc\n * value (`{ $ref }` marker or null) — read the resolved live node off the aspect instance. */\n node(key: string, opts?: FieldOpts): unknown;\n /** Project-asset path (the editor renders a dropdown of the project's GLBs). \"\" = none picked. */\n asset(key: string, opts?: FieldOpts): string;\n /** True on the run that consumes this button's click — do the action right there. */\n button(label: string, opts?: {\n id?: string;\n }): boolean;\n /** A toggle that activates/deactivates the named viewport tool (`registerEditorTool`). The\n * editor owns the active-tool state — the click never round-trips into the scene world. */\n toolButton(label: string, tool: string): void;\n header(label: string): void;\n info(text: string): void;\n warn(text: string): void;\n /** Emit the inferred field widgets (all declared aspect fields, or just the named ones) — the\n * zero-ceremony baseline; append custom widgets around it. */\n auto(...keys: string[]): void;\n private _vec;\n private _field;\n}\nexport {};\n","types/core/registry.d.ts":"export declare class Registry<T> {\n private map;\n set(id: number, value: T): void;\n get(id: number): T | undefined;\n delete(id: number): void;\n has(id: number): boolean;\n}\n","types/core/signals.d.ts":"/** Runs every pending effect now instead of waiting for the microtask (test/host hook). */\nexport declare const flushEffects: () => void;\nexport interface Signal<T> {\n value: T;\n /** Read without subscribing the current effect/computed. */\n peek(): T;\n}\nexport interface Computed<T> {\n readonly value: T;\n /** Read without subscribing the current effect/computed (still recomputes if stale). */\n peek(): T;\n}\n/**\n * A reactive value. Reading `.value` inside an `effect`/`computed` (or a function-valued style\n * prop / `UIText` content) subscribes it; writing `.value` re-runs subscribers (batched — once\n * per microtask).\n */\nexport declare function signal<T>(initialValue: T): Signal<T>;\nexport declare function signal<T = undefined>(): Signal<T | undefined>;\n/** A lazily-cached derived value: recomputes on read after any of its dependencies changed. */\nexport declare function computed<T>(fn: () => T): Computed<T>;\n/**\n * Runs `fn` now and again whenever any signal/computed it read changes (batched per microtask).\n * Returns a dispose function; an undisposed effect lives for the rest of the app run.\n */\nexport declare function effect(fn: () => void): () => void;\n/** The shape UINode's Element exposes for binding ownership. */\nexport interface BindingHost {\n}\n","types/g2/autotile.d.ts":"/** A fill entry: an atlas index, or [index, weight] for seeded scatter variants. */\nexport type FillEntry = number | [number, number];\nexport type Dir4 = [number, number, number, number];\n/** One side's tiles: a single index (used for every cell along that side), or — with `size` > 1 —\n * the `size` indices ALONG it (n/s run left→right, w/e run top→bottom). */\nexport type EdgeSlot = number | number[];\n/** A whole `size`×`size` piece: one index (drawn in every cell of the block), or size² indices\n * row-major. Path pieces and parts are blocks — at size 1 they are just a tile. */\nexport type TileBlock = number | number[];\n/** `size`² indices, row-major within the block. */\nexport type FillBlock = number[];\n/** A named element placed BY HAND (a pedestrian crossing in a road, a gate in a fence). It carries\n * its own `id`, so the map stores it like any material — but it CONNECTS as its parent, so the\n * run continues straight through it. Never picked at random: you paint it from the palette, ONE\n * CELL at a time, and the tile is worked out from where that cell sits. */\nexport type TilePart = {\n /** Stable small int, unique across every material and part of the tileset. */\n id: number;\n /** Which run the art is drawn for — 'v' vertical, 'h' horizontal. It also picks the art: the\n * element varies ACROSS the line (a crossing has one tile per lane) and repeats along it, so\n * `tiles` is `size` long, indexed by row for 'h' and by column for 'v'. */\n axis?: \"v\" | \"h\";\n /** The tiles — one index, `size` across the run when `axis` is set, else the size² block. */\n tiles?: TileBlock;\n};\n/** A block variant: the block, or [block, weight] for seeded scatter. */\nexport type BlockEntry = FillBlock | [FillBlock, number];\n/** One transition set of a patch material — the tiles its border shows against a neighbor. */\nexport type PatchSlots = {\n /** Edge line tiles [n, e, s, w] — e.g. `edges[0]` draws where the patch stops toward the top. */\n edges?: [EdgeSlot, EdgeSlot, EdgeSlot, EdgeSlot];\n /** Convex corner tiles [ne, se, sw, nw] — the patch's outside corners. Always one cell. */\n outer?: Dir4;\n /** Concave corner tiles [ne, se, sw, nw] — the notch where two patch arms meet. One cell. */\n inner?: Dir4;\n};\nexport type PatchMaterial = {\n /** Stable small int — what `cells('…')` stores when a map carries Autotile2D. */\n id: number;\n kind: \"patch\";\n /** Editor swatch color ('#4a7c3a'). */\n color?: string;\n /** Block size in cells (default 1). With 2 or 3 the material is classified block-to-block on a\n * lattice anchored at the map origin, `fill` holds size² tiles and each edge `size` tiles. */\n size?: number;\n /** Interior tile — one index, or an ARRAY of scatter variants (each `index` or\n * `[index, weight]`; bare indices weigh 1): `fill: [261, [262, 0.1], [263, 0.05]]`.\n * With `size` > 1 it is instead the row-major BLOCK of size² indices\n * (`fill: [130, 131, 146, 147]`), or a list of such blocks for scatter variants. */\n fill: number | FillEntry[] | BlockEntry[];\n /** Transition sets keyed by the neighboring material's name; '*' = any other neighbor\n * (including empty). Baked packs draw a material fading into a SPECIFIC background. */\n over?: Record<string, PatchSlots>;\n /** Hand-placed elements that connect as this material (see TilePart). */\n parts?: Record<string, TilePart>;\n};\nexport type PathMaterial = {\n id: number;\n kind: \"path\";\n color?: string;\n /** Cells ACROSS the line (default 1). A `size: 2` road is two lanes wide: connectivity runs\n * block to block and every piece below is a 2×2 block instead of one tile. */\n size?: number;\n /** No connections at all. */\n isolated?: TileBlock;\n /** End caps [n, e, s, w] — `ends[0]` connects toward the top only. */\n ends?: [TileBlock, TileBlock, TileBlock, TileBlock];\n /** [vertical (n+s), horizontal (e+w)]. */\n straights?: [TileBlock, TileBlock];\n /** Elbows [ne, se, sw, nw] — `corners[0]` connects top + right. */\n corners?: [TileBlock, TileBlock, TileBlock, TileBlock];\n /** T pieces [n, e, s, w] — `tees[0]` is the tee MISSING the top connection. */\n tees?: [TileBlock, TileBlock, TileBlock, TileBlock];\n /** All four connections. */\n cross?: TileBlock;\n /** Hand-placed elements that connect as this material (see TilePart). */\n parts?: Record<string, TilePart>;\n};\nexport type TileMaterial = PatchMaterial | PathMaterial;\nexport type TilesetDef = {\n /** The atlas image — write `asset('./TileSet.png')`. */\n image: string;\n /** Atlas cell size in image pixels — a number (square) or [w, h]. */\n tile: number | [number, number];\n /** Named materials; names are the editor/`over:` vocabulary, `id`s are what maps store. */\n materials?: Record<string, TileMaterial>;\n};\nexport declare const normalizeFill: (fill: number | FillEntry[]) => [number, number][];\n/** A material's block size — 1 unless it declares `size` (clamped to a positive int). */\nexport declare const blockSize: (mat: TileMaterial) => number;\n/** One cell of a block: a scalar covers the whole block, an array reads row-major. Undefined =\n * unassigned (missing, or the negative sentinel the editor writes for a blank slot). */\nexport declare const blockTile: (block: TileBlock | undefined, n: number, lx: number, ly: number) => number | undefined;\n/** How many tiles a part holds: `size` across the run when it declares an axis, else the block. */\nexport declare const partSlots: (part: TilePart, n: number) => number;\n/** The cell value that draws atlas tile `index` verbatim in a material map. */\nexport declare const rawCell: (index: number) => number;\n/** True for a cell holding a raw atlas tile rather than a material id. */\nexport declare const isRawCell: (v: number) => boolean;\n/** The atlas index behind a raw cell (garbage in, garbage out — guard with isRawCell). */\nexport declare const rawIndex: (v: number) => number;\nexport declare const TILE_INDEX_MASK = 268435455;\n/** The atlas index behind a (possibly oriented) tile value. */\nexport declare const tileIndex: (v: number) => number;\n/** Clockwise quarter-turns (0–3) of a tile value. */\nexport declare const tileTurns: (v: number) => number;\n/** Whether the tile is mirrored horizontally (the mirror applies before the rotation). */\nexport declare const tileFlip: (v: number) => boolean;\n/** True when the value carries any orientation (renderers keep the fast path otherwise). */\nexport declare const tileOriented: (v: number) => boolean;\n/** Build an oriented tile value: `index`, mirrored when `flip`, then `turns` quarter-turns CW. */\nexport declare const packTile: (index: number, turns?: number, flip?: boolean) => number;\n/** The value rotated a further 90° clockwise. */\nexport declare const rot90: (v: number) => number;\n/** The value rotated a further 180°. */\nexport declare const rot180: (v: number) => number;\n/** The value rotated a further 270° clockwise (90° counter-clockwise). */\nexport declare const rot270: (v: number) => number;\n/** The value mirrored horizontally (on screen — existing turns are re-based, group math). */\nexport declare const flipX: (v: number) => number;\n/** The tile a part draws in a cell — indexed ACROSS the run ('h' by row, 'v' by column) so one\n * element covers a lane each and repeats along the run; without an axis it is a plain block. */\nexport declare const partTile: (part: TilePart, n: number, lx: number, ly: number) => number | undefined;\n/** `fill` as weighted BLOCKS of `size`² indices (row-major). Size 1 keeps the scalar/scatter\n * reading; with size > 1 a flat number array is one positional block, an array of arrays is the\n * variant list, and a bare number fills the whole block. Missing entries read as -1. */\nexport declare const fillBlocks: (fill: PatchMaterial[\"fill\"], size?: number) => [number[], number][];\n/**\n * Derive display atlas indices from a material-id grid (row-major, row 0 = top, -1 = empty).\n * Values that match no material id pass through unchanged (so converting maps degrades\n * gracefully); -1 stays -1. Deterministic: same inputs + seed → same output on every platform.\n */\nexport declare const deriveCells: (def: TilesetDef, cols: number, rows: number, cells: ArrayLike<number>, seed?: number) => Int32Array;\n","types/g2/Camera2D.d.ts":"import { Vec2, type Vec2Like } from \"../math/vec\";\nexport declare class Camera2D {\n private _x;\n private _y;\n private _zoom;\n private _rotation;\n private readonly sceneId;\n constructor(sceneId: number);\n get position(): Vec2;\n set position(v: Vec2Like);\n get zoom(): number;\n set zoom(z: number);\n get rotation(): number;\n set rotation(deg: number);\n screenToWorld(screenX: number, screenY: number): Vec2;\n worldToScreen(worldX: number, worldY: number): Vec2;\n}\n","types/g2/cells.d.ts":"export type CellsData = {\n cols: number;\n rows: number;\n /** Row-major tile values (row 0 = the top row), length cols*rows. */\n data: Int32Array;\n};\n/** Encode a grid into a `cells()` payload (the editor / tools side of the codec). */\nexport declare const encodeCells: (cols: number, rows: number, data: ArrayLike<number>) => string;\n/**\n * Decode a `cells('…')` payload into the grid a tilemap block consumes. Scene files call this via\n * the injected global; the value is plain data, so hand-written code may pass any\n * `{ cols, rows, data }` of its own instead (procedural maps).\n */\nexport declare const cells: (payload: string) => CellsData;\n","types/g2/CharacterController2D.d.ts":"import { Aspect } from \"../core/Aspect\";\nimport type { Node2D } from \"./Node2D\";\nexport declare class CharacterController2D extends Aspect<\"controller\", Node2D> {\n static readonly aspect = \"controller\";\n /** Horizontal move speed (world units/s). */\n speed: number;\n /** Jump take-off speed (world units/s). */\n jumpSpeed: number;\n /** Extra probe distance below the body's feet used for the grounded check (world units). */\n groundProbe: number;\n /** Distance from the node origin down to the feet. Defaults to half the sprite height. */\n footOffset?: number;\n private _moveX;\n private _jumpQueued;\n private _grounded;\n /** Horizontal intent in [-1, 1] (e.g. from input). Sticky — set 0 to stop. Applied next frame. */\n move(dir: number): void;\n /** Queue a jump; consumed on the next frame if grounded. */\n jump(): void;\n /** True while standing on something (updated each frame). */\n get grounded(): boolean;\n private get phys();\n onAttach(): void;\n update(_dt: number): void;\n private _spriteHalfHeight;\n}\n","types/g2/defineScene2d.d.ts":"import type { ColorInput } from \"../core/color\";\nimport type { Vec2Like } from \"../math/vec\";\nimport { type AspectEntry, type MakeEntry as SharedMakeEntry } from \"../scene/grammar\";\nimport { Scene2D } from \"./Scene2D\";\nimport { Node2D } from \"./Node2D\";\nimport { Sprite } from \"./Sprite\";\nimport { Tilemap } from \"./Tilemap\";\nimport { SpriteSheet } from \"./SpriteSheet\";\nimport type { SpriteAnimation } from \"./SpriteAnimation\";\nimport type { CellsData } from \"./cells\";\nimport type { With } from \"../core/Aspect\";\nexport type Scene2dEnv = {\n /** Background color — '#5a6b3b', 0x5a6b3b, or [r,g,b] in 0..1. */\n background?: ColorInput;\n /** Texture sampling: 'nearest' (crisp pixel art, engine default) or 'linear'. */\n filter?: \"nearest\" | \"linear\";\n /** Pixel-art crispness: snap the camera to whole screen pixels (seeds CameraFollow's\n * `pixelSnap`, and the initial camera position lands on whole world units). */\n pixelPerfect?: boolean;\n /** Physics world gravity (Y-up: down is negative). Presence configures the world before any\n * body is created — `[0, 0]` for top-down worlds. Omit to leave the world unconfigured. */\n gravity?: Vec2Like;\n};\n/** A sprite node: one named entry of an imported `.sprite.ts` sheet. The sheet is ART only —\n * colliders/bodies are scene semantics: put Shape2D / Physics2D / Trigger2D in `aspects`. */\nexport type SpriteSourceDef = {\n /** The imported sheet handle: `import props from './props.sprite'` … `sheet: props`. */\n sheet: SpriteSheet;\n /** The entry name; omit when the sheet declares exactly one sprite. */\n name?: string;\n /** Start this clip immediately (sliced entries with clips). */\n clip?: string;\n /** Initial facing for `perDirection` clips. */\n direction?: string;\n};\nexport type TilemapSourceDef = {\n /** The tileset image — `asset('./TileSet.png')`. */\n texture: string;\n /** On-screen cell size in world units — a number (square) or [w, h]. */\n tile: number | [number, number];\n /** Atlas grid: how the texture slices into tiles, [atlasCols, atlasRows]. */\n atlas: [number, number];\n /** The map: a `cells('…')` payload — or any `{ cols, rows, data }` of your own. */\n cells: CellsData | {\n cols: number;\n rows: number;\n data: number[] | Int32Array;\n };\n};\n/** A camera marker node: seeds the scene camera's starting position (+ zoom). To MOVE the camera\n * in play, attach `CameraFollow` to the node being followed — not aspects on this marker. */\nexport type Camera2dNodeDef = {\n zoom?: number;\n};\nexport type Scene2dNodeDef = {\n sprite?: SpriteSourceDef;\n tilemap?: TilemapSourceDef;\n camera?: Camera2dNodeDef;\n /** A code-built subtree — `make(factoryFn, { ...literal args })`, factory returns a Node2D. */\n make?: SharedMakeEntry<any, Node2D>;\n position?: Vec2Like;\n /** Degrees, CCW. */\n rotation?: number;\n scale?: Vec2Like | number;\n /** Draw layer (int) — higher renders on top. */\n layer?: number;\n /** Intra-layer depth for non-Y-sorted layers. */\n z?: number;\n /** Sprite tint (sprite nodes only). */\n color?: ColorInput;\n /** Sprite opacity 0..1 (sprite nodes only). */\n opacity?: number;\n flipX?: boolean;\n flipY?: boolean;\n visible?: boolean;\n /** Editor-only: the move gizmo won't target this node (fields still edit). No runtime effect. */\n locked?: boolean;\n aspects?: readonly AspectEntry<any>[];\n children?: Record<string, Scene2dNodeDef>;\n};\nexport type Scene2dCameraDef = {\n position?: Vec2Like;\n zoom?: number;\n};\nexport type Scene2dDef = {\n env?: Scene2dEnv;\n /** Per-layer config, keyed by layer number: `layers: { 1: { ySort: true } }`. */\n layers?: Record<number | string, {\n ySort?: boolean;\n }>;\n /** Starting camera when there's no camera NODE (a camera node wins). */\n camera?: Scene2dCameraDef;\n nodes?: Record<string, Scene2dNodeDef>;\n};\ntype SourceNodeOf<N extends Scene2dNodeDef> = N extends {\n sprite: {\n clip: string;\n };\n} ? Sprite & {\n anim: SpriteAnimation;\n} : N extends {\n sprite: SpriteSourceDef;\n} ? Sprite : N extends {\n tilemap: TilemapSourceDef;\n} ? Tilemap : Node2D;\ntype AspectsOf<N extends Scene2dNodeDef> = N extends {\n aspects: readonly AspectEntry<infer A>[];\n} ? A : never;\ntype NodeOf<N extends Scene2dNodeDef> = [\n AspectsOf<N>\n] extends [never] ? SourceNodeOf<N> : With<SourceNodeOf<N>, AspectsOf<N>>;\ntype UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (k: infer I) => void ? I : never;\ntype ChildMapsOf<T extends Record<string, Scene2dNodeDef>> = {\n [K in keyof T]: T[K] extends {\n children: infer C extends Record<string, Scene2dNodeDef>;\n } ? NodesOf<C> : never;\n}[keyof T];\ntype NodesOf<T extends Record<string, Scene2dNodeDef>> = {\n [K in keyof T]: NodeOf<T[K]>;\n} & ([ChildMapsOf<T>] extends [never] ? unknown : UnionToIntersection<ChildMapsOf<T>>);\nexport type Scene2dNodes<D extends Scene2dDef> = D[\"nodes\"] extends Record<string, Scene2dNodeDef> ? NodesOf<D[\"nodes\"]> : Record<string, Node2D>;\nexport type LoadedScene2d<D extends Scene2dDef> = {\n scene: Scene2D;\n nodes: Scene2dNodes<D>;\n};\nexport declare class Scene2dHandle<D extends Scene2dDef = Scene2dDef> {\n readonly def: D;\n private _loading?;\n constructor(def: D);\n /** Instantiate the scene (idempotent — subsequent calls return the same instance). Does not open. */\n load(): Promise<LoadedScene2d<D>>;\n /** Load and make active (only the active 2D scene renders). */\n open(): Promise<LoadedScene2d<D>>;\n}\n/**\n * Define a 2D scene as data — the default export of a `.scene2d.ts` file. Returns a typed handle:\n * `const { scene, nodes } = await handle.open()` gives `nodes.<name>` typed by its source block\n * (Sprite / Tilemap / Node2D) with its `use(...)`d aspects attached.\n */\nexport declare const defineScene2d: <const D extends Scene2dDef>(def: D) => Scene2dHandle<D>;\nexport {};\n","types/g2/loop.d.ts":"export declare const onUpdate: (callback: (dt: number) => void) => void;\nexport declare const offUpdate: (callback: (dt: number) => void) => void;\nexport declare const ensureAnimEvents: () => void;\nexport declare const ensurePhysicsEvents: () => void;\n","types/g2/Node2D.d.ts":"import { AspectHost } from \"../core/Aspect\";\nimport { Registry } from \"../core/registry\";\nimport { Vec2, type Vec2Like } from \"../math/vec\";\nimport type { ClickEvent, TouchStartEvent } from \"../runtime/touch\";\nexport { Vec2, type Vec2Like };\nexport type Node2DEvents = {\n /** A looping animation clip wrapped around (fires each loop). */\n loopReached: (clip: string) => void;\n /** A non-looping animation clip finished. */\n completed: (clip: string) => void;\n /** A physics contact / sensor overlap began / ended (the other node). */\n enter: (other: Node2D) => void;\n exit: (other: Node2D) => void;\n /** Pointer up over this node's Physics2D shape (a tap/click). */\n click: (ev: ClickEvent<Node2D | null>) => void;\n /** Pointer down on this node's Physics2D shape. Call ev.track(...) to capture the drag. */\n touchstart: (ev: TouchStartEvent<Node2D | null>) => void;\n};\n/** id → Node2D, so host callbacks (animation events) route back to the owning JS object. */\nexport declare const node2dRegistry: Registry<Node2D>;\nexport declare class Node2D extends AspectHost<Node2DEvents> {\n /** Native entity handle. */\n readonly id: number;\n /** Optional debug/editor name (plain JS data — scene2d files stamp their node names here). */\n name?: string;\n protected _x: number;\n protected _y: number;\n protected _rotation: number;\n protected _sx: number;\n protected _sy: number;\n protected _layer: number;\n protected _z: number;\n protected _visible: boolean;\n private _parent;\n private _children;\n constructor(internalId?: number);\n private _pull;\n get x(): number;\n set x(v: number);\n get y(): number;\n set y(v: number);\n get position(): Vec2;\n set position(v: Vec2Like);\n /** Rotation in degrees (CCW). */\n get rotation(): number;\n set rotation(deg: number);\n get scale(): Vec2;\n set scale(v: Vec2Like | number);\n /** Draw layer (int). Higher layers render on top. */\n get layer(): number;\n set layer(v: number);\n /** Intra-layer depth for non-Y-sorted layers (higher z = on top). */\n get z(): number;\n set z(v: number);\n get visible(): boolean;\n set visible(v: boolean);\n get parent(): Node2D | null;\n set parent(p: Node2D | null);\n get children(): readonly Node2D[];\n /** Attach children to this node (each keeps its current world transform). Returns this. */\n add(...children: Node2D[]): this;\n /** Detach a direct child (reparents it to root, keeping its world transform). Returns this. */\n remove(child: Node2D): this;\n /**\n * Reparent this node. `keepWorld` (default true) recomputes the local transform so the on-screen\n * position/rotation/scale is unchanged; pass false to keep the local transform and move with the\n * new parent. Self/descendant parents are rejected natively (no cycles).\n */\n setParent(parent: Node2D | null, keepWorld?: boolean): this;\n /** World-space position (composes all ancestors). */\n get worldPosition(): Vec2;\n /** Convert a world-space point into this node's local space (and back). */\n worldToLocal(p: Vec2Like): Vec2;\n localToWorld(p: Vec2Like): Vec2;\n private _syncLocalFromNative;\n addEventListener<K extends keyof Node2DEvents>(channel: K, callback: Node2DEvents[K]): void;\n destroy(): void;\n}\n","types/g2/Physics2D.d.ts":"import { Aspect } from \"../core/Aspect\";\nimport { Vec2, type Vec2Like } from \"../math/vec\";\nimport { type Node2D } from \"./Node2D\";\nexport type MotionType = \"static\" | \"kinematic\" | \"dynamic\";\nexport interface PhysicsConfig {\n /** Gravity in world units/s² (Y-up: down is negative). Default [0, -980]. */\n gravity?: Vec2Like;\n /** Pixels per meter — tunes Box2D's internal tolerances; you still author in world units. Default 64. */\n pixelsPerMeter?: number;\n /** Solver sub-steps per fixed step. Default 4. */\n subSteps?: number;\n}\n/** Closest raycast hit. */\nexport interface RayHit {\n node: Node2D | null;\n point: Vec2;\n normal: Vec2;\n fraction: number;\n}\nexport declare class Physics2D extends Aspect<\"physics\", Node2D> {\n static readonly aspect = \"physics\";\n /** Default \"dynamic\". */\n motion: MotionType;\n density: number;\n friction: number;\n restitution: number;\n /** Lock rotation (essential for platformer characters). */\n fixedRotation: boolean;\n /** Continuous collision for fast-moving bodies (projectiles). */\n bullet: boolean;\n private _gravityScale;\n private _h;\n /** Native physics body id. 0 until attached, or if the build has no physics support. Mirrors 3D `Physics.id`. */\n get id(): number;\n onAttach(): void;\n onDetach(): void;\n /** Linear velocity in world units/second (fresh Vec2 on read). */\n get velocity(): Vec2;\n set velocity(v: Vec2Like);\n /** Angular velocity in degrees/second. */\n set angularVelocity(degPerSec: number);\n /** Per-body gravity multiplier: 1 = full world gravity, 0 = floats, <0 = repelled. Set at attach\n * time (as an option) or live. */\n get gravityScale(): number;\n set gravityScale(scale: number);\n set linearDamping(d: number);\n set enabled(v: boolean);\n /** Apply an instantaneous impulse (world units) and wake the body. */\n applyImpulse(v: Vec2Like): this;\n /** Apply a continuous force (world units) and wake the body. */\n applyForce(v: Vec2Like): this;\n /** Teleport / drive a kinematic (or dynamic) body to a world position (+ optional rotation degrees). */\n moveTo(p: Vec2Like, deg?: number): this;\n /** Create / reset the physics world. Call once before creating bodies. */\n static configure(config?: PhysicsConfig): void;\n /** Whether this build has physics support (CREATOR_2D_PHYSICS). */\n static get supported(): boolean;\n /** Render interpolation of body transforms between the fixed 60 Hz steps (global; default on). Turn\n * off to save per-frame transform writes when you have many moving bodies / don't need >60 Hz\n * smoothness — bodies then advance in discrete steps. */\n private static _interpolation;\n static get interpolation(): boolean;\n static set interpolation(on: boolean);\n /** Closest body hit by the segment from→to, or null. `node` resolves the hit entity. */\n static raycast(from: Vec2Like, to: Vec2Like): RayHit | null;\n /** Topmost body (solid or sensor) whose shape contains the world point, or null. */\n static overlapPoint(p: Vec2Like): Node2D | null;\n}\n","types/g2/scenarios2d.d.ts":"import { Aspect } from \"../core/Aspect\";\nimport type { Node2D } from \"./Node2D\";\nimport type { Scene2D } from \"./Scene2D\";\n/**\n * Ease the scene camera toward this node every frame (attach it to the player). In a `.scene2d.ts`\n * file the loader wires `scene` automatically; from hand-written code pass it yourself:\n * `hero.aspect(CameraFollow, { scene })`.\n *\n * The eased position accumulates at full precision and only the value PUSHED to the camera is\n * snapped — reading the snapped camera back as the ease-from value would let tiny sub-pixel steps\n * round to zero near settle (the follow would stall a few px off-centre, then jump).\n */\nexport declare class CameraFollow extends Aspect<\"cameraFollow\", Node2D> {\n static readonly aspect = \"cameraFollow\";\n /** The scene2d loader injects the scene into aspects that declare this. */\n static readonly wantsScene = true;\n /** The scene whose camera follows (wired by the scene file loader). */\n scene: Scene2D | null;\n /** Exponential time constant in seconds; smaller = snappier, 0 = pin the node to centre. */\n smooth: number;\n /** Camera offset from the node, in world units. */\n offset: [number, number];\n /** Quantize the camera to whole screen pixels so eased motion never shimmers pixel art.\n * Defaults to the scene's `env.pixelPerfect` (true when unset). */\n pixelSnap: boolean;\n private _x;\n private _y;\n private readonly _grid;\n update(dt: number): void;\n}\n","types/g2/Scene2D.d.ts":"import { type ColorInput } from \"../core/color\";\nimport { Presentable, type PresentOptions } from \"../ui/presentable\";\nimport { type Vec2Like } from \"../math/vec\";\nimport type { ClickEvent, TouchStartEvent } from \"../runtime/touch\";\nimport { Camera2D } from \"./Camera2D\";\nimport { type Node2D } from \"./Node2D\";\nexport type Scene2DOptions = {\n /** Background color — '#10131a', 0x10131a, or [r,g,b]/[r,g,b,a] in 0..1. */\n background?: ColorInput;\n /** Texture sampling for the 2D renderer: `'nearest'` (default — crisp pixel art) or `'linear'`\n * (smooth — for hi-res / non-pixel-art assets). Applied when the scene is opened, so switching\n * scenes restores the active scene's choice. NOTE: this is a GLOBAL renderer setting (one sampler\n * for ALL textures, not per-texture), so the currently-open scene's filter wins. Omit to leave the\n * current setting (engine default is nearest). */\n filter?: 'nearest' | 'linear';\n};\n/** Returned by scene2d.layer(n); chain .ySort() to enable top-down depth sorting for that layer. */\ndeclare class LayerHandle {\n private readonly sceneId;\n private readonly layer;\n constructor(sceneId: number, layer: number);\n /** In this layer, lower-on-screen sprites overlap higher ones (top-down feet sorting). */\n ySort(enabled?: boolean): this;\n}\nexport declare class Scene2D implements Presentable {\n /** Native scene handle. */\n readonly id: number;\n readonly camera: Camera2D;\n private static _active;\n static get active(): Scene2D | null;\n readonly _touchStartListeners: Array<(ev: TouchStartEvent<Node2D | null>) => void>;\n /** Texture filter to (re)assert on open(); the sampler is global, so each scene reclaims it. */\n private readonly _filter?;\n constructor(options?: Scene2DOptions);\n set background(color: ColorInput);\n /** Address a draw layer to configure it, e.g. scene2d.layer(1).ySort(). */\n layer(n: number): LayerHandle;\n /** Topmost visible sprite whose world bounds contain the world point, or null. Body-free\n * hit-test for tap/click picking — pair with camera.screenToWorld(). */\n pick(worldPoint: Vec2Like): Node2D | null;\n /** Scene-level pointer events. The handler fires for every tap/press in the scene, with\n * `ev.target` = the hit Physics2D node (or null). On 'touchstart' you can ev.track(...) a drag. */\n addEventListener(channel: \"click\", callback: (ev: ClickEvent<Node2D | null>) => void): void;\n addEventListener(channel: \"touchstart\", callback: (ev: TouchStartEvent<Node2D | null>) => void): void;\n removeEventListener(channel: \"click\" | \"touchstart\", callback: (ev: any) => void): void;\n add(...nodes: Node2D[]): this;\n remove(...nodes: Node2D[]): this;\n readonly cl: (() => void)[];\n _backButtonCallback?: () => void;\n private _vd?;\n /** Fires when the scene becomes the visible destination (incl. a pop revealing it). */\n onOpen(callback: () => void): this;\n /** Fires when the scene stops being visible (closed, replaced, or covered by a push). */\n onClose(callback: () => void): this;\n onBackPressed(callback: () => void): this;\n /** Make this the active scene — shows it as the current destination (replaces a screen /\n * another scene; only the active scene renders). */\n open(options?: PresentOptions): this;\n close(): this;\n destroy(): void;\n}\nexport {};\n","types/g2/Shape2D.d.ts":"import { Aspect } from \"../core/Aspect\";\nimport { type Vec2Like } from \"../math/vec\";\nimport type { Node2D } from \"./Node2D\";\nexport declare class Shape2D extends Aspect<\"shape\", Node2D> {\n static readonly aspect = \"shape\";\n /** Box half-extents [hw, hh] (world units). */\n box?: Vec2Like;\n /** Circle radius. */\n circle?: number;\n /** Capsule between two local points, with a radius. */\n capsule?: {\n from: Vec2Like;\n to: Vec2Like;\n radius: number;\n };\n /** Thin segment (an edge — for static ground/walls/slopes) between two local points. */\n segment?: {\n from: Vec2Like;\n to: Vec2Like;\n };\n /** Convex polygon, up to 8 local points (a convex hull is computed). */\n polygon?: Vec2Like[];\n /** Local offset of the shape from the node origin. */\n offset?: Vec2Like;\n}\n","types/g2/Sprite.d.ts":"import { type ColorInput } from \"../core/color\";\nimport { Vec2, type Vec2Like } from \"../math/vec\";\nimport { Canvas } from \"../canvas/Canvas\";\nimport { Node2D } from \"./Node2D\";\nimport type { Texture2D } from \"./Texture2D\";\n/** Anything that can back a sprite: a texture, or a Canvas (baked to a texture on assign). */\nexport type TextureSource = Texture2D | Canvas;\nexport type SpriteOptions = {\n texture?: TextureSource;\n /** Pivot, [0,0] = top-left .. [1,1] = bottom-right. Use [0.5, 1] (feet) for Y-sorted depth. */\n anchor?: Vec2Like;\n /** World size; defaults to the texture's pixel dimensions. */\n size?: Vec2Like;\n /** Normalized UV sub-rect [u0,v0,u1,v1]. */\n frame?: [number, number, number, number];\n /** Tint multiplied with the texture. */\n color?: ColorInput;\n opacity?: number;\n layer?: number;\n position?: Vec2Like;\n};\nexport declare class Sprite extends Node2D {\n private _texture?;\n private _anchor;\n private _color;\n private _opacity;\n private _flipX;\n private _flipY;\n private _size;\n constructor(options?: SpriteOptions);\n get texture(): Texture2D | undefined;\n set texture(t: TextureSource | undefined);\n /** Current world size: explicit override if set, else the texture's pixel dimensions (a Canvas-backed\n * sprite defaults to the canvas's LOGICAL size, so pixelRatio is crispness only, not size). */\n get size(): Vec2;\n set size(v: Vec2Like);\n get anchor(): Vec2;\n set anchor(v: Vec2Like);\n /** Set the UV sub-rect (normalized). */\n set frame(uv: [number, number, number, number]);\n /** Set the sub-rect in texture pixels. */\n setFramePx(px: number, py: number, pw: number, ph: number): this;\n get color(): ColorInput;\n set color(c: ColorInput);\n get opacity(): number;\n set opacity(a: number);\n get flipX(): boolean;\n set flipX(v: boolean);\n get flipY(): boolean;\n set flipY(v: boolean);\n}\n","types/g2/SpriteAnimation.d.ts":"import { Aspect } from \"../core/Aspect\";\nimport { type Vec2Like } from \"../math/vec\";\nimport type { Sprite } from \"./Sprite\";\n/** Per-clip frame list, or an object for per-clip fps/loop/direction overrides. */\nexport type Clip = number[] | {\n frames: number[];\n fps?: number;\n loop?: boolean;\n perDirection?: boolean;\n};\nexport declare class SpriteAnimation extends Aspect<\"anim\", Sprite> {\n static readonly aspect = \"anim\";\n /** Grid cell size in texture pixels (defaults to the full texture). */\n size?: [number, number];\n /** Grid columns override — for sheets with padding; defaults to floor(texWidth / cellWidth). */\n cols?: number;\n /** Pixel origin of the grid in the texture — cells index from here (a SpriteSheet region). */\n origin?: [number, number];\n /** Default fps for clips that don't override it. */\n fps: number;\n /** Default loop for clips that don't override it. */\n loop: boolean;\n /** Named clips; frame indices are row-major into the grid. Set via the attach opts. */\n clips: Record<string, Clip>;\n /** Facing names in texture-row order (row i = directions[i]) for `perDirection` clips. */\n directions?: string[];\n private _clipIds;\n private _clipNames;\n private _current;\n private _defined;\n private _queued;\n private _dir;\n onAttach(): void;\n /** (Re)build native clips from `this.clips`. Called on attach; call again after changing clips. */\n define(): this;\n private _define;\n /**\n * Play a clip by name. Re-playing the active clip is a no-op (keeps it running smoothly).\n * For a `perDirection` clip, `dir` picks the facing — a direction name or a movement vector\n * (nearest compass row wins); omitted, the last direction (or the first row) is kept.\n */\n play(name: string, dir?: string | Vec2Like): this;\n stop(): this;\n /** Current facing (last direction resolved by play()), or null before the first directional play. */\n get direction(): string | null;\n set speed(value: number);\n get current(): string | null;\n get frame(): number;\n private _resolveDir;\n}\n","types/g2/SpriteSheet.d.ts":"import { type Vec2Like } from \"../math/vec\";\nimport { Sprite } from \"./Sprite\";\nimport { SpriteAnimation, type Clip } from \"./SpriteAnimation\";\nimport { Texture2D } from \"./Texture2D\";\n/**\n * A named region of the image. Just a rect is a static sprite; `slice` subdivides the rect into an\n * animation grid ([cols, rows] — the cell is rect size / counts); `clips` names frame runs over\n * that grid (local, row-major). A sliced entry with NO clips loops all of its cells in order.\n */\nexport type SheetSprite = {\n /** Pixel rect [x, y, w, h] in the image. */\n rect?: [number, number, number, number];\n /** Subdivide the rect into an animation grid: [cols, rows]. */\n slice?: [number, number];\n /** Playback fps for this sprite's animation (defaults to the sheet fps, then 12). */\n fps?: number;\n /** Named clips over the local grid (see SpriteAnimation). Omit to loop every cell. */\n clips?: Record<string, Clip>;\n /** Facing names in local-row order for `perDirection` clips (compass tokens: S/SE/E/…). */\n directions?: string[];\n /** Overrides the sheet anchor. */\n anchor?: Vec2Like;\n};\nexport type SpriteSheetDef = {\n /** The image URL — write `asset('./sheet.png')`. */\n image: string;\n /** Default pivot for every sprite made from this sheet ([0.5, 1] = feet, for Y-sorted worlds). */\n anchor?: Vec2Like;\n /** Default fps for sliced sprites / clips that don't override it. */\n fps?: number;\n /** The named sprites. */\n sprites?: Record<string, SheetSprite>;\n};\nexport type SpriteMakeOptions = {\n position?: Vec2Like;\n layer?: number;\n /** Overrides the sheet/sprite anchor. */\n anchor?: Vec2Like;\n /** Start this clip immediately (sliced sprites with clips). */\n clip?: string;\n /** Initial facing for `perDirection` clips. */\n direction?: string;\n};\nexport declare class SpriteSheet {\n private _def;\n private _tex;\n private _loading;\n constructor(def: SpriteSheetDef);\n /** The sheet definition (read-only by convention — the editor owns the file). */\n get def(): SpriteSheetDef;\n /** The loaded texture, or null before load() resolves. */\n get texture(): Texture2D | null;\n /** Load the sheet's texture (idempotent). make() starts this automatically. */\n load(): Promise<Texture2D>;\n /** Names of the sheet's sprites. */\n get spriteNames(): string[];\n /** Build a named sprite; starting a clip hands back the animation handle. */\n make(name: string, opts: SpriteMakeOptions & {\n clip: string;\n }): Sprite & {\n anim: SpriteAnimation;\n };\n make(name: string, opts?: SpriteMakeOptions): Sprite;\n /** The pixel rect [x, y, w, h] of a named sprite's REGION (the whole rect, sliced or not). */\n rectOf(name: string): [number, number, number, number] | null;\n private _applyTexture;\n}\n/** Declare a sprite sheet (the default export of a `.sprite.ts` file). */\nexport declare const defineSpriteSheet: (def: SpriteSheetDef) => SpriteSheet;\n","types/g2/Texture2D.d.ts":"import { type FetchResponse, type File } from \"../runtime/fetch\";\nexport declare class Texture2D {\n /** Native texture handle. */\n readonly id: number;\n readonly width: number;\n readonly height: number;\n constructor(id: number, width: number, height: number);\n static fromCanvas(canvas: {\n _bakeSurface(): number;\n width: number;\n height: number;\n pixelRatio: number;\n }): Texture2D;\n static load(source: string | FetchResponse | File): Promise<Texture2D>;\n destroy(): void;\n}\n","types/g2/Tilemap.d.ts":"import { Node2D } from \"./Node2D\";\nimport type { Texture2D } from \"./Texture2D\";\nexport type TilemapOptions = {\n texture: Texture2D;\n /** Map grid size (in tiles). */\n cols: number;\n rows: number;\n /** On-screen cell size in world units — a single number (square) or [w, h]. */\n tile: number | [number, number];\n /** Atlas grid: how the texture is sliced into tiles, [atlasCols, atlasRows]. */\n atlas: [number, number];\n /** Row-major tile indices into the atlas (-1 = empty), length cols*rows. Row 0 is the top row. */\n data: number[] | Int32Array;\n};\nexport declare class Tilemap extends Node2D {\n readonly cols: number;\n readonly rows: number;\n constructor(options: TilemapOptions);\n setTile(x: number, y: number, index: number): this;\n}\n","types/g2/Tileset.d.ts":"import { Aspect } from \"../core/Aspect\";\nimport type { Node2D } from \"./Node2D\";\nimport { type TilesetDef, type TileMaterial } from \"./autotile\";\nexport declare class Tileset {\n private _def;\n constructor(def: TilesetDef);\n /** The tileset definition (read-only by convention — the editor owns the file). */\n get def(): TilesetDef;\n /** Names of the declared materials, in file order. */\n get materialNames(): string[];\n /** A material by name. */\n material(name: string): TileMaterial | undefined;\n /** The cell value maps store for a named material (what you paint / pass in `data`). */\n id(name: string): number | undefined;\n /** Derive display atlas indices from a material-id grid (what Autotile2D does at load). */\n derive(cols: number, rows: number, data: ArrayLike<number>, seed?: number): Int32Array;\n}\n/** Declare a tileset (the default export of a `.tiles.ts` file). */\nexport declare const defineTileset: (def: TilesetDef) => Tileset;\n/**\n * Marks a tilemap node's `cells` as MATERIAL ids of a tileset instead of raw atlas indices:\n * `aspects: [use(Autotile2D, { tileset: world })]`. The scene2d loader derives the display\n * indices (neighbor-mask autotile + seeded scatter, deterministic) before building the tilemap;\n * the aspect itself holds no behavior. Change `seed` to reshuffle scatter variants.\n */\nexport declare class Autotile2D extends Aspect<\"autotile\", Node2D> {\n static readonly aspect = \"autotile\";\n /** The imported `.tiles.ts` handle. */\n tileset: Tileset | null;\n /** Scatter seed — same seed, same map, same result on every platform. */\n seed: number;\n}\n","types/g2/touch.d.ts":"/** Register the host pointer callback once, on the first click/touchstart listener (node or scene). */\nexport declare const ensurePointerEvents: () => void;\n","types/g2/Trigger2D.d.ts":"import { Aspect } from \"../core/Aspect\";\nimport { type Vec2Like } from \"../math/vec\";\nimport type { Node2D } from \"./Node2D\";\nexport declare class Trigger2D extends Aspect<\"trigger\", Node2D> {\n static readonly aspect = \"trigger\";\n private _h;\n /** Native physics body id (0 if no physics support). Mirrors 3D `Trigger.id`. */\n get id(): number;\n onAttach(): void;\n onDetach(): void;\n /** Reposition the trigger zone to a world point. */\n moveTo(p: Vec2Like): this;\n}\n","types/gl/Camera.d.ts":"import { Vec3 } from \"../math/vec\";\nimport { Node } from \"./Node\";\nimport { Ray } from \"./Ray\";\n/** Projection every host starts a scene with (creator-gl scene.cpp / the lite core agree on these). */\nexport declare const CAMERA_DEFAULTS: {\n fov: number;\n near: number;\n far: number;\n};\nexport declare class Camera extends Node {\n private _sceneId;\n /** Live projection matrix (updated by the host when the viewport/fov changes). */\n readonly projectionMatrix: Float32Array<ArrayBuffer>;\n private _fov;\n private _near;\n private _far;\n /** Stay quiet until the app actually sets something — hosts may be configured with their own\n * defaults (the headless core takes a `fov` option) and a blind push would overwrite them. */\n private _projSet;\n /** Vertical field of view in degrees (default 60) — a smaller angle is a longer lens. */\n get fov(): number;\n set fov(degrees: number);\n get horizontalFov(): number;\n /** Near clip distance (default 0.01) — nothing closer than this draws. */\n get near(): number;\n set near(distance: number);\n /** Far clip distance / view range (default 1000) — geometry past it is culled. Shadows keep\n * their own (shorter) range, so a long view distance doesn't cost shadow sharpness. */\n get far(): number;\n set far(distance: number);\n /** Set any of fov / near / far in one call: `camera.setProjection({ fov: 45, far: 5000 })`. */\n setProjection(projection: {\n fov?: number;\n near?: number;\n far?: number;\n }): this;\n /** Hosts that predate the call keep the fixed defaults (older wasm / native builds). */\n private _applyProjection;\n get displaySize(): [number, number];\n /** World-space ray direction through a screen pixel. */\n getViewDirection(screenX: number, screenY: number): Vec3;\n /** A pick ray from the camera through a screen pixel. */\n getRay(screenX: number, screenY: number): Ray;\n}\n","types/gl/CharacterController.d.ts":"import { Aspect } from \"../core/Aspect\";\nimport { Vec3 } from \"../math/vec\";\nimport type { Node } from \"./Node\";\nexport declare class CharacterController extends Aspect<\"controller\", Node> {\n static readonly aspect = \"controller\";\n /** Horizontal move speed (world units/s). */\n speed: number;\n /** Jump take-off speed (world units/s). */\n jumpSpeed: number;\n /** Character-tuned gravity (world units/s²), separate from the world gravity — usually stronger for\n * snappier feel. Applied to the vertical velocity each frame. */\n gravity: number;\n /** Max ground slope (degrees) the character treats as walkable. Set before attach. */\n maxSlope: number;\n updateBeforePhysics: boolean;\n private _charId;\n private _mx;\n private _mz;\n private _jumpQueued;\n private _vy;\n onAttach(): void;\n onDetach(): void;\n /** Native character id (0 until attached / no physics support). */\n get id(): number;\n /** Horizontal move intent; each component in [-1, 1] (e.g. from input). Sticky — set 0 to stop. */\n move(x: number, z: number): void;\n /** Queue a jump; consumed on the next frame if grounded. */\n jump(): void;\n /** True while standing on walkable ground (OnGround). */\n get grounded(): boolean;\n /** Ground state: 0 on-ground, 1 on-steep-slope, 2 touching-but-unsupported, 3 in-air. */\n get groundState(): number;\n /** Current velocity (world units/s, fresh Vec3). */\n get velocity(): Vec3;\n /** Teleport to a world position (clears vertical velocity). */\n teleport(x: number, y: number, z: number): this;\n update(dt: number): void;\n}\n","types/gl/controls.d.ts":"import type { Node } from \"./Node\";\nimport type { Scene } from \"./Scene\";\nexport type ControlsOptions = {\n /** Smallest uniform scale the pinch gesture allows (default 0.08). */\n minScale?: number;\n /** Largest uniform scale the pinch gesture allows (default 2). */\n maxScale?: number;\n /** One-finger drag moves the target across the ground plane (default true). */\n pan?: boolean;\n /** Two-finger pinch scales the target (default true). */\n pinch?: boolean;\n /** Two-finger twist rotates the target around its Y axis (default true). */\n twist?: boolean;\n};\n/** Returned by `addControls` — call `remove()` to detach the gesture listeners. */\nexport type ControlsHandle = {\n remove(): void;\n};\nexport declare const attachControls: (scene: Scene, target: Node, options?: ControlsOptions) => ControlsHandle;\n","types/gl/Geometry.d.ts":"import { type Vec3Like } from \"../math/vec\";\nexport type MeshKind = \"triangles\" | \"vertices\" | \"edges\";\nexport declare class Geometry {\n vertices: Float32Array;\n normals: Float32Array;\n indices: Uint16Array;\n uv: Float32Array;\n constructor(vertices: Float32Array, normals: Float32Array, indices: Uint16Array, uv: Float32Array);\n translate(x: number, y: number, z: number): this;\n scale(x: number, y: number, z: number): this;\n scaleUV(x: number, y: number): this;\n set kind(kind: MeshKind);\n static box(): Geometry;\n static sphere(options?: SphereOptions): Geometry;\n static cylinder(options?: CylinderOptions): Geometry;\n static plane(options?: PlaneOptions): Geometry;\n}\nexport type SphereOptions = {\n radius?: number;\n widthSegments?: number;\n heightSegments?: number;\n};\nexport type CylinderOptions = {\n radius?: number;\n radiusTop?: number;\n radiusBottom?: number;\n edges?: number;\n smooth?: boolean;\n};\nexport type PlaneOptions = {\n normal?: Vec3Like;\n};\n","types/gl/Light.d.ts":"import { type ColorInput } from \"../core/color\";\nimport type { Vec3Like } from \"../math/vec\";\nimport { Node } from \"./Node\";\nexport type SunOptions = {\n /** Light direction (points where the light travels). Defaults to a typical key-light angle. */\n direction?: Vec3Like;\n /** Luminous intensity. */\n intensity?: number;\n color?: ColorInput;\n /**\n * Shadow quality (default 1):\n * 0 - no shadows\n * 1 - standard (1024 shadow map, hard PCF edges)\n * 2 - high (2048 + stable, soft contact-hardening edges)\n * 3 - best (4096 + stable, PCSS soft shadows)\n * Higher values cost more GPU/memory.\n */\n shadowsQuality?: 0 | 1 | 2 | 3;\n};\nexport declare class Light extends Node {\n /** A directional sun light. */\n static sun(options?: SunOptions): Light;\n}\n","types/gl/Material.d.ts":"import { type ColorInput } from \"../core/color\";\nimport { type FetchResponse } from \"../runtime/fetch\";\nimport { Texture } from \"./Texture\";\nimport type { Canvas } from \"../canvas/Canvas\";\ntype UniformValue = string | Texture | number | boolean | number[] | Float32Array | null;\nexport type MaterialColorOptions = {\n color?: ColorInput;\n map?: Texture | Canvas | null;\n};\n/** `Material.particles` options — the default point-sprite material for particle systems. */\nexport type ParticlesMaterialOptions = {\n /** Sprite texture — a single image or a flipbook sheet of frames. Unset = soft round dot. */\n map?: Texture | null;\n /** Flipbook grid: `N` = an N×N sheet, `[cols, rows]` = a non-square one. Frames run\n * left-to-right, top-to-bottom; drive the index via `particles.frame`. Default 1. */\n sheet?: number | [number, number];\n /** Extra brightness multiplier for a glow look (0 = off). */\n emissive?: number;\n /** Compositing: `\"alpha\"` (default — smoke, dust) or `\"add\"` (fire, sparks, magic). */\n blend?: \"alpha\" | \"add\";\n /** Soft radial falloff toward the sprite edge. Defaults to true without a map, false with one. */\n soft?: boolean;\n /** How each particle is drawn: `'point'` (default — GPU point sprites, cheapest), `'quad'`\n * (real camera-facing quads — no driver size cap, geometric rotation), or `'stretch'`\n * (quads stretched along velocity — sparks, rain, speed streaks). `'ribbon'` is what `Trail`\n * uses internally. */\n render?: \"point\" | \"quad\" | \"stretch\" | \"ribbon\";\n /** (`render: 'stretch'`) extra sprite length in world units per unit of speed:\n * length = size + stretch·|velocity|. Default 0.05. */\n stretch?: number;\n};\n/** `Material.lit` options — PBR scalars on top of the color/map pair. */\nexport type LitMaterialOptions = MaterialColorOptions & {\n /** Perceptual roughness, 0 (mirror) … 1 (matte). Unset = the shader's default. */\n roughness?: number;\n /** Metallic factor, 0 (dielectric) … 1 (metal). Unset = the shader's default. */\n metallic?: number;\n};\nexport declare class Material {\n readonly shader: FetchResponse | \"unknown\";\n readonly uniforms: Record<string, UniformValue>;\n private _colorKey;\n private _useMapFlag;\n constructor(shader: FetchResponse | number);\n /** Set a uniform (chainable). */\n set(key: string, value: UniformValue): this;\n set color(c: ColorInput);\n set map(value: Texture | Canvas | null);\n /** PBR lit material. */\n static lit(options?: LitMaterialOptions): Material;\n /** Unlit (flat) material. */\n static unlit(options?: MaterialColorOptions): Material;\n /** Default particle material — camera-facing point sprites with tint/opacity/rotation/flipbook\n * driven by the particle curves. Uniforms all default to 0 on a fresh instance, so every look\n * knob is primed here; JS writes after construction override them. */\n static particles(options?: ParticlesMaterialOptions): Material;\n /** Material that samples a VideoPlayer's texture. */\n static video(map?: Texture): Material;\n /** Shadow-catcher material (transparent except where shadows fall). */\n static shadow(color?: ColorInput): Material;\n /** Load a custom compiled shader (.mat URL) as a material. */\n static load(url: string): Promise<Material>;\n}\nexport {};\n","types/gl/Mesh.d.ts":"import { type Vec3Like } from \"../math/vec\";\nimport { Geometry, type CylinderOptions, type PlaneOptions, type SphereOptions } from \"./Geometry\";\nimport { Material } from \"./Material\";\nimport { Node } from \"./Node\";\n/** Common transform/render options every primitive factory accepts. */\nexport type MeshOptions = {\n material?: Material;\n position?: Vec3Like;\n eulerAngles?: Vec3Like;\n scale?: Vec3Like | number;\n name?: string;\n castShadows?: boolean;\n receiveShadows?: boolean;\n};\nexport declare class Mesh extends Node {\n private _geometry?;\n private _materials;\n constructor(geometry?: Geometry, material?: Material);\n get geometry(): Geometry | undefined;\n get material(): Material;\n set material(m: Material);\n setMaterial(material: Material, index?: number): this;\n getMaterial(index?: number): Material | null;\n set culling(v: boolean);\n set castShadows(v: boolean);\n set receiveShadows(v: boolean);\n static box(options?: MeshOptions & {\n size?: Vec3Like | number;\n }): Mesh;\n static sphere(options?: MeshOptions & SphereOptions): Mesh;\n static cylinder(options?: MeshOptions & CylinderOptions): Mesh;\n static plane(options?: MeshOptions & PlaneOptions): Mesh;\n /** Wrap a custom Geometry. */\n static from(geometry: Geometry, options?: MeshOptions): Mesh;\n}\n","types/gl/Model.d.ts":"import { type FetchResponse } from \"../runtime/fetch\";\nimport { Node } from \"./Node\";\nimport { ModelAnimation } from \"./ModelAnimation\";\nexport declare class Model extends Node {\n /** GLB skeletal animation — always present on a Model. */\n readonly anim: ModelAnimation;\n constructor(internalId: number);\n /** Duplicate this model — a deep copy of the GLB (meshes, skeleton, animation clips), attached to\n * the same parent and scene and sharing this model's current transform. The clone has its own\n * independent animation state (reach it via clone.anim). Mirrors Model.load's culling default. */\n clone(): Model;\n /** Load a GLB model. Returns its root as a Model; play its baked clips via model.anim. */\n static load(source: string | FetchResponse, options?: {\n culling?: boolean;\n onProgress?: (p: {\n loaded: number;\n total?: number;\n }) => void;\n }): Promise<Model>;\n}\n","types/gl/ModelAnimation.d.ts":"import { Aspect } from \"../core/Aspect\";\nimport type { Model } from \"./Model\";\nexport declare class ModelAnimation extends Aspect<\"anim\", Model> {\n static readonly aspect = \"anim\";\n private _playing;\n private _clip;\n private _speed;\n private _loop;\n onAttach(): void;\n /** The clips baked into the glb. */\n get clips(): {\n name: string;\n duration: number;\n }[];\n get playing(): boolean;\n set playing(value: boolean);\n /** Play a clip by name or index. Chainable. */\n play(clip?: string | number, options?: {\n loop?: boolean;\n }): this;\n stop(): this;\n get loop(): boolean;\n set loop(v: boolean);\n get speed(): number;\n set speed(v: number);\n get time(): number;\n set time(v: number);\n}\n","types/gl/Node.d.ts":"import { AspectHost } from \"../core/Aspect\";\nimport { Registry } from \"../core/registry\";\nimport { Vec3, type Vec3Like } from \"../math/vec\";\nimport { Quat, type QuatLike } from \"../math/quat\";\nimport { Mat4, type Mat4Like } from \"../math/mat4\";\nimport type { Geometry } from \"./Geometry\";\nimport type { ClickEvent, TouchStartEvent } from \"../runtime/touch\";\n/** id → Node, so host callbacks (touch hits, animation events) route back to the owning object. */\nexport declare const nodeRegistry: Registry<Node>;\nexport type NodeEvents = {\n click: (ev: ClickEvent<Node | null>) => void;\n touchstart: (ev: TouchStartEvent<Node | null>) => void;\n /** A looping GLB animation clip wrapped around. */\n loopReached: (clip: number) => void;\n /** A non-looping GLB animation clip finished. */\n completed: (clip: number) => void;\n /** AR anchors only (`scene.root` / `scene.createAnchor()`): the anchor began tracking. */\n track: () => void;\n /** AR anchors only: the anchor lost tracking. */\n untrack: () => void;\n /** A physics contact/trigger overlap began (the other body's node). Needs a Shape + Physics/Trigger. */\n enter: (other: Node) => void;\n /** A physics contact/trigger overlap ended. */\n exit: (other: Node) => void;\n};\nexport declare class Node extends AspectHost<NodeEvents> {\n /** Native entity handle. */\n readonly id: number;\n /** AR anchors only — whether the anchor is currently being tracked. Kept in step with the\n * 'track' / 'untrack' events; `false` for any non-anchor node. */\n isTracked: boolean;\n private _matrix?;\n private _lastSync;\n private _worldMatrix?;\n private _scaleCache?;\n constructor(internalId?: number);\n /** Geometry, if this node is a Mesh (used by physics auto-shape). Overridden by Mesh. */\n get geometry(): Geometry | undefined;\n get name(): string;\n set name(value: string);\n get visible(): boolean;\n set visible(value: boolean);\n private _sync;\n get matrix(): Mat4;\n set matrix(m: Mat4Like);\n get worldMatrix(): Mat4;\n set worldMatrix(m: Mat4Like);\n get position(): Vec3;\n set position(v: Vec3Like);\n get x(): number;\n set x(v: number);\n get y(): number;\n set y(v: number);\n get z(): number;\n set z(v: number);\n get scale(): Vec3;\n set scale(v: Vec3Like | number);\n get quaternion(): Quat;\n set quaternion(v: QuatLike);\n get eulerAngles(): Vec3;\n set eulerAngles(v: Vec3Like);\n get forward(): Vec3;\n get worldPosition(): Vec3;\n get worldScale(): Vec3;\n get worldQuaternion(): Quat;\n get worldEulerAngles(): Vec3;\n get parent(): Node | null;\n get children(): Node[];\n get childCount(): number;\n getChild(index: number): Node | null;\n /** Parent the given nodes under this one. */\n add(...children: Node[]): this;\n setParent(parent: Node | null, worldPositionStays?: boolean): this;\n traverse(callback: (node: Node) => void): void;\n /** Orient the node so the given axis (default \"-z\", \"forward\") points at a world point. */\n lookAt(point: Vec3Like, mode?: \"z\" | \"-z\" | \"x\" | \"-x\" | \"y\" | \"-y\", ortho?: Vec3Like): this;\n addEventListener<K extends keyof NodeEvents>(channel: K, callback: NodeEvents[K]): void;\n destroy(): void;\n}\n","types/gl/Noise.d.ts":"export declare class Noise {\n private readonly _id;\n constructor();\n /** Sample 2D noise. */\n get(x: number, y: number): number;\n /** Sample 3D noise. */\n get3d(x: number, y: number, z: number): number;\n private _frequency;\n get frequency(): number;\n set frequency(v: number);\n private _octaves;\n get octaves(): number;\n set octaves(v: number);\n private _fractalLacunarity;\n get fractalLacunarity(): number;\n set fractalLacunarity(v: number);\n private _fractalGain;\n get fractalGain(): number;\n set fractalGain(v: number);\n}\n","types/gl/Particles.d.ts":"import { type ColorInput } from \"../core/color\";\nimport { type Vec3Like } from \"../math/vec\";\nimport { Material, type ParticlesMaterialOptions } from \"./Material\";\nimport { Node } from \"./Node\";\ntype Range<T> = T | {\n min: T;\n max: T;\n};\nexport declare class CurveBuilder {\n private _kind;\n private _lo;\n private _hi;\n private _stops;\n constructor(base: Range<number>, mode: \"multiply\" | \"add\");\n /** Curve value at birth (t = 0). Must come before any other stop. */\n from(v: Range<number>): this;\n /** Curve value at `t` (0..1 of the particle's life). Stops must be added in ascending t order. */\n via(t: number, v: Range<number>): this;\n /** Curve value at death (t = 1). */\n to(v: Range<number>): this;\n /** The classic opacity envelope: rise over the first `fadeIn`, fall over the last `fadeOut`. */\n fade(fadeIn?: number, fadeOut?: number): this;\n /** The PARAM_CURVE record payload (sans slot): [kind, baseLo, baseHi, n, (t, lo, hi)×n]. */\n get _data(): Float32Array;\n}\nexport declare class ColorCurveBuilder {\n private _lo;\n private _hi;\n private _stops;\n constructor(base: Range<ColorInput>);\n /** Curve color at birth (t = 0). Must come first. The curve multiplies the base color. */\n from(c: Range<ColorInput>): this;\n /** Curve color at `t` (0..1 of the particle's life), in ascending t order. */\n via(t: number, c: Range<ColorInput>): this;\n /** Curve color at death (t = 1). */\n to(c: Range<ColorInput>): this;\n /** The COLOR_CURVE record payload: [baseLo rgba, baseHi rgba, n, (t, lo rgba, hi rgba)×n]. */\n get _data(): Float32Array;\n}\n/** A value curve over each particle's lifetime. Default mode `multiply` (the curve scales the\n * base); `add` offsets it instead. */\nexport declare const curve: (base?: Range<number>, mode?: \"multiply\" | \"add\") => CurveBuilder;\n/** A color curve over each particle's lifetime — always multiplies the base color. */\nexport declare const colorCurve: (base?: Range<ColorInput>) => ColorCurveBuilder;\nexport type ParticleValue = Range<number> | CurveBuilder | {\n _data: Float32Array;\n};\nexport type ParticleColor = ColorInput | {\n min: ColorInput;\n max: ColorInput;\n} | ColorCurveBuilder | {\n _data: Float32Array;\n};\ntype VelocityValue = {\n speed?: Range<number>;\n /** Cone half-angle in radians — jitter the launch direction uniformly within it. */\n spread?: number;\n /** Asymmetric jitter: two angles (u, v — the x/y components) in radians. */\n randomizeAngle?: {\n min: Vec3Like;\n max: Vec3Like;\n };\n} & ({\n from: Vec3Like;\n} | {\n to: Vec3Like;\n} | {\n dir: Vec3Like;\n} | {});\ntype Shape = {\n type: \"point\";\n v: Vec3Like;\n} | {\n type: \"box\";\n min: Vec3Like;\n max: Vec3Like;\n} | {\n type: \"circle\";\n center: Vec3Like;\n radius: number;\n};\ntype Noise = {\n strength?: number;\n frequency?: number;\n speed?: number;\n};\nexport type ParticlesOptions = ParticlesMaterialOptions & {\n /** Custom draw material. Unset = the default point-sprite material, configured by the\n * `ParticlesMaterialOptions` sugar (map/sheet/emissive/blend/soft) — which is ignored\n * when an explicit material is passed. */\n material?: Material;\n /** Particle pool capacity (default 1000). */\n maxParticles?: number;\n /** Particles emitted per second. */\n rate?: number;\n /** Simulation space. `'local'` (default) — particles ride the node's transform; `'world'` —\n * each particle stays where it was born as the emitter moves on (trails: drift smoke, mud,\n * wake). Switching at runtime resets live particles. */\n space?: \"local\" | \"world\";\n /** Fraction (usually 0..1) of the emitter's own velocity added to each particle at spawn —\n * smoke \"thrown\" off a moving car. Takes effect with `space: 'world'`. */\n inheritVelocity?: number;\n /** Particles emitted per world unit the emitter MOVES, on top of `rate`, with spawn points\n * spread evenly along the path — trail density independent of speed, no per-frame clumps.\n * Meant for `space: 'world'`. */\n rateOverDistance?: number;\n shape?: Shape;\n startVelocity?: Vec3Like | VelocityValue;\n /** Downward acceleration, world units/s² — positive pulls particles DOWN (sugar for\n * `acceleration: [0, -g, 0]`). */\n gravity?: number;\n /** Constant acceleration vector (gravity, wind, …). Wins over `gravity` when both are set. */\n acceleration?: Vec3Like;\n drag?: number;\n lifetime?: Range<number>;\n color?: ParticleColor;\n /** World-unit diameter (alias of custom[0]). Default 1. */\n size?: ParticleValue;\n /** Radians (alias of custom[1]). */\n rotation?: ParticleValue;\n /** Per-particle opacity 0..1 (alias of custom[2]). Default 1. */\n opacity?: ParticleValue;\n /** Flipbook frame index (alias of custom[3]). With `sheet` set and no explicit frame, the\n * default is one full sheet cycle over each particle's lifetime, starting at `startFrame`. */\n frame?: ParticleValue;\n /** Where the default flipbook cycle begins: `'random'` (default — desynchronized loops like\n * fire/smoke) or a frame index (`0` plays the sheet in order — explosions, one-shot bursts).\n * Only shapes the default; an explicit `frame` wins. */\n startFrame?: number | \"random\";\n noise?: Noise | null;\n /** Fixed random seed for deterministic tests. */\n seed?: number;\n};\nexport declare class Particles extends Node {\n private _material;\n /** Custom curve-param slots (0..3); size/rotation/opacity/frame alias slots 0-3. */\n readonly custom: ParticleValue[];\n constructor(options?: ParticlesOptions);\n /** Emit `count` particles immediately (a burst). */\n spawn(count: number): this;\n private _send;\n set rate(val: number);\n /** `'world'` leaves particles behind where they were born (trails). Switching resets live ones. */\n set space(val: \"local\" | \"world\");\n set inheritVelocity(val: number);\n set rateOverDistance(val: number);\n set shape(shape: Shape);\n set startVelocity(val: Vec3Like | VelocityValue);\n /** Positive pulls particles down — sugar for `acceleration = [0, -g, 0]`. */\n set gravity(val: number);\n set acceleration(a: Vec3Like);\n set drag(val: number);\n set seed(val: number);\n set lifetime(val: Range<number>);\n set size(val: ParticleValue);\n set rotation(val: ParticleValue);\n set opacity(val: ParticleValue);\n set frame(val: ParticleValue);\n set color(value: ParticleColor);\n get material(): Material;\n set material(material: Material);\n set noise(noise: Noise | null);\n}\n/** `Trail` options. The look options (map/sheet/emissive/blend/soft) come from\n * `ParticlesMaterialOptions`, same as `Particles`. */\nexport type TrailOptions = Omit<ParticlesMaterialOptions, \"render\" | \"stretch\"> & {\n /** Seconds each trail point lives — the trail's length in time. Default 0.5. */\n time?: number;\n /** Strip width in world units; a curve tapers it over each point's life (head → tail).\n * Default 0.1. */\n width?: ParticleValue;\n /** Minimum emitter movement (world units) between recorded points. Default 0.05. */\n minDistance?: number;\n /** Point capacity (default 128). */\n maxPoints?: number;\n color?: ParticleColor;\n /** Opacity along the trail. Defaults to fading the tail out (`curve().to(0)`). */\n opacity?: ParticleValue;\n};\n/** A ribbon strip that follows this node through the world — sword swings, skid marks, missile\n * trails. Attach it to (or under) the moving node and just move; points are laid down per\n * `minDistance` of movement, live for `time` seconds, and the strip stays glued to the node at\n * its head. Width/opacity/color accept the same curves as `Particles`, evaluated over each\n * point's life — i.e. along the trail from head (fresh) to tail (dying). */\nexport declare class Trail extends Node {\n private _material;\n private _rateDistance;\n constructor(options?: TrailOptions);\n private _send;\n /** Trail length in seconds — how long each laid-down point lives. */\n set time(val: number);\n set width(val: ParticleValue);\n set opacity(val: ParticleValue);\n set color(value: ParticleColor);\n set minDistance(val: number);\n /** Pause/resume laying down points — existing ones still age out, so the trail fades naturally\n * after e.g. a sword swing ends. */\n set emitting(val: boolean);\n get material(): Material;\n}\nexport {};\n","types/gl/Physics.d.ts":"import { Aspect } from \"../core/Aspect\";\nimport { Vec3, type Vec3Like } from \"../math/vec\";\nimport { type Node } from \"./Node\";\nexport type MotionType = \"static\" | \"dynamic\" | \"kinematic\";\nexport interface PhysicsConfig {\n /** Gravity in world units/s² (Y-up: down is negative). Default [0, -9.81, 0]. */\n gravity?: Vec3Like;\n /** Max simultaneous bodies (resizes the world; only before any body exists). Default 4096. */\n maxBodies?: number;\n}\n/** Closest raycast hit. */\nexport interface RayHit {\n node: Node | null;\n point: Vec3;\n normal: Vec3;\n fraction: number;\n}\nexport declare class Physics extends Aspect<\"physics\", Node> {\n static readonly aspect = \"physics\";\n /** Render interpolation of body transforms between the fixed 60 Hz steps (global; default on). Turn\n * off to save per-frame transform writes when you have many moving bodies / don't need >60 Hz\n * smoothness — bodies then advance in discrete steps. */\n private static _interpolation;\n static get interpolation(): boolean;\n static set interpolation(on: boolean);\n /** Default \"dynamic\". */\n motion: MotionType;\n /** Mass in kg for dynamic bodies (default 1). Ignored for static/kinematic. */\n mass: number;\n private _bodyId;\n onAttach(): void;\n onDetach(): void;\n /** Native Jolt body id. 0 until attached, or if the build has no physics support. */\n get id(): number;\n /** Linear velocity in world units/second (fresh Vec3 on read). */\n get velocity(): Vec3;\n set velocity(v: Vec3Like);\n /** Apply an instantaneous impulse (kg·m/s) and wake the body. */\n applyImpulse(v: Vec3Like): this;\n /** Teleport / drive a kinematic (or dynamic) body to a world position. */\n moveTo(p: Vec3Like): this;\n /** Configure gravity / limits. Call once before creating bodies. */\n static configure(config?: PhysicsConfig): void;\n /** Whether this build has physics support (CREATOR_GL_PHYSICS). */\n static get supported(): boolean;\n /** Closest pickable body hit by the ray from `origin` along `dir` (up to `maxDist`), or null. */\n static raycast(origin: Vec3Like, dir: Vec3Like, maxDist?: number): RayHit | null;\n}\n","types/gl/physicsEvents.d.ts":"export declare const ensurePhysicsEvents: () => void;\n","types/gl/Plane.d.ts":"import { Vec3, type Vec3Like } from \"../math/vec\";\nimport type { Ray } from \"./Ray\";\nexport declare class Plane {\n /** Unit normal. */\n readonly normal: Vec3;\n /** Scalar offset: dot(normal, point). */\n readonly d: number;\n constructor(normal: Vec3Like, point: Vec3Like);\n static fromPoints(a: Vec3Like, b: Vec3Like, c: Vec3Like): Plane;\n static fromCoefficients(a: number, b: number, c: number, d: number): Plane;\n /** Ray-plane parameter t (≥0), or null on a miss (parallel / behind origin). */\n intersectRay(ray: Ray): number | null;\n /** Like intersectRay but allows hits behind the origin (line-plane). */\n intersectLine(ray: Ray): number | null;\n /** Signed distance from a point (positive on the normal's side). */\n signedDistance(point: Vec3Like): number;\n /** Project a point onto the plane. */\n projectPoint(point: Vec3Like): Vec3;\n}\n","types/gl/Ray.d.ts":"import { Vec3, type Vec3Like } from \"../math/vec\";\nexport declare class Ray {\n readonly origin: Vec3;\n readonly dir: Vec3;\n constructor(origin: Vec3Like, dir: Vec3Like);\n /** The world-space point origin + t·dir. */\n getPoint(t: number): Vec3;\n}\n","types/gl/scenarios.d.ts":"import { Aspect } from \"../core/Aspect\";\nimport type { FieldMeta } from \"../core/fields\";\nimport type { InspectorUI } from \"../core/InspectorUI\";\nimport { Node } from \"./Node\";\nimport { Model } from \"./Model\";\ntype LoopMode = \"once\" | \"loop\" | \"pingpong\";\n/** Travel from the node's starting position to a target node in `duration` seconds. */\nexport declare class MoveTo extends Aspect<\"moveTo\"> {\n /** Where to travel — place an Empty node and pick it. */\n target: Node | null;\n /** Seconds for the full trip. */\n duration: number;\n /** Seconds to wait before starting. */\n delay: number;\n /** once = stop at the target · loop = restart from the start point · pingpong = back and forth. */\n mode: LoopMode;\n /** Motion curve. */\n easing: \"smooth\" | \"linear\";\n static readonly aspect = \"moveTo\";\n static editor: {\n rebuild: boolean;\n };\n static fields: FieldMeta<MoveTo>;\n private _t;\n private _start;\n update(dt: number): void;\n /** Editor-only path line (edit mode; play mode never calls this). */\n rebuild(): void;\n}\n/** Travel through the children of a path node (add an Empty per waypoint) in `duration` seconds.\n * `loop` runs the circuit closed (last → first); `pingpong` goes back and forth along the open\n * path; `once` stops at the last waypoint. */\nexport declare class FollowPath extends Aspect<\"followPath\"> {\n /** A node whose CHILDREN are the waypoints, in file order. */\n path: Node | null;\n /** Seconds for one full pass of the path. */\n duration: number;\n /** Seconds to wait before starting. */\n delay: number;\n mode: LoopMode;\n /** Turn to face the direction of travel. */\n orient: boolean;\n /** Which local axis leads when orienting. */\n forward: \"-z\" | \"z\" | \"x\" | \"-x\";\n static readonly aspect = \"followPath\";\n static editor: {\n rebuild: boolean;\n };\n static fields: FieldMeta<FollowPath>;\n private _t;\n private _points;\n update(dt: number): void;\n /** Editor-only waypoint polyline (edit mode; play mode never calls this). */\n rebuild(): void;\n}\n/** Continuous rotation about one of the node's local axes, degrees per second. */\nexport declare class Spin extends Aspect<\"spin\"> {\n /** Degrees per second. */\n speed: number;\n /** Local axis to spin around. */\n axis: \"x\" | \"y\" | \"z\";\n static readonly aspect = \"spin\";\n static fields: FieldMeta<Spin>;\n update(dt: number): void;\n}\n/** Keep the node facing a target node (a turret tracking, a signpost, a camera aimed at a hero).\n * Accessor `node.facing` — NOT `lookAt`, which would shadow the `Node.lookAt()` method. */\nexport declare class LookAt extends Aspect<\"facing\"> {\n /** The node to face. */\n target: Node | null;\n /** Which local axis points at the target. */\n forward: \"-z\" | \"z\" | \"x\" | \"-x\";\n /** 0 = snap instantly; otherwise seconds of turn lag (bigger = slower, smoother). */\n smoothing: number;\n static readonly aspect = \"facing\";\n static editor: {\n rebuild: boolean;\n };\n static fields: FieldMeta<LookAt>;\n update(dt: number): void;\n /** Editor-only sight line (edit mode; play mode never calls this). */\n rebuild(): void;\n}\n/** Start a GLB animation clip when the scene runs. Attach to a `model:` node; the inspector card\n * lists the model's clips live and can preview them while editing. */\nexport declare class PlayAnimation extends Aspect<\"playAnimation\", Model> {\n /** Clip name; empty = the model's first clip. */\n clip: string;\n loop: boolean;\n /** Playback rate (1 = authored speed). */\n speed: number;\n static readonly aspect = \"playAnimation\";\n static fields: FieldMeta<PlayAnimation>;\n onAttach(): void;\n static inspector(ui: InspectorUI, a: PlayAnimation): void;\n}\nexport {};\n","types/gl/Scene.d.ts":"import { type ColorInput } from \"../core/color\";\nimport { Presentable, type PresentOptions } from \"../ui/presentable\";\nimport type { ClickEvent, TouchStartEvent } from \"../runtime/touch\";\nimport type { FetchResponse } from \"../runtime/fetch\";\nimport { Camera } from \"./Camera\";\nimport { type ControlsHandle, type ControlsOptions } from \"./controls\";\nimport { Material } from \"./Material\";\nimport { Node } from \"./Node\";\nexport type SceneOptions = {\n /** Image-based ambient lighting (default on). */\n ibl?: boolean;\n /** IBL intensity (default 20000). */\n environmentIntensity?: number;\n /** Bloom post-processing. */\n bloom?: boolean;\n bloomIntensity?: number;\n /** Skybox / clear color. */\n skybox?: ColorInput;\n /** Multisample anti-aliasing. */\n antialias?: boolean;\n};\nexport declare class Scene implements Presentable {\n readonly camera: Camera;\n readonly _touchStartListeners: Array<(ev: TouchStartEvent<Node | null>) => void>;\n private _material?;\n private static _active;\n static get active(): Scene | null;\n constructor(options?: SceneOptions);\n /** Scene occlusion material. */\n get occlusionMaterial(): Material;\n set skybox(color: ColorInput);\n setMaterialGlobalParameter(i: number, x: number, y: number, z: number, w: number): void;\n setAntialias(enabled: boolean, scale?: number): void;\n add(...nodes: Node[]): this;\n remove(...nodes: Node[]): this;\n createOverlay(options?: SceneOptions): Scene;\n warmRender(): Promise<void>;\n readonly cl: (() => void)[];\n _backButtonCallback?: () => void;\n private _vd?;\n /** Fires when the scene becomes the visible destination (incl. a pop revealing it). */\n onOpen(callback: () => void): this;\n /** Fires when the scene stops being visible (closed, replaced, or covered by a push). */\n onClose(callback: () => void): this;\n onBackPressed(callback: () => void): this;\n /** Make this the active scene — shows it as the current destination (replaces a screen /\n * another scene; only the active scene renders). */\n open(options?: PresentOptions): void | Promise<void>;\n close(): void;\n addEventListener(channel: \"click\", callback: (ev: ClickEvent<Node | null>) => void): void;\n addEventListener(channel: \"touchstart\", callback: (ev: TouchStartEvent<Node | null>) => void): void;\n removeEventListener(channel: \"click\" | \"touchstart\", callback: (ev: any) => void): void;\n}\nexport type ARMode = \"default\" | \"markers\" | \"arcore\" | \"detached\";\nexport declare class ARScene<T extends ARMode = \"default\"> extends Scene {\n readonly mode: T;\n useWarmRender: boolean;\n private _root?;\n constructor(options?: SceneOptions & {\n mode?: T;\n });\n /** Root anchor node (not available in marker mode). */\n get root(): Node;\n /** Create an anchor from a tracking source (e.g. an image target). */\n createAnchor(source: FetchResponse, physicalWidth?: number): Node;\n /**\n * Let the user place & manipulate a node with touch gestures — the staple AR object-placement\n * interaction: ONE finger drags it across the floor (relative to where the camera looks), TWO fingers\n * pinch to scale and twist to rotate. Returns a handle; call `.remove()` to detach. Tunable via\n * options (min/max scale, and toggles for `pan` / `pinch` / `twist`).\n */\n addControls(target: Node, options?: ControlsOptions): ControlsHandle;\n open(options?: PresentOptions): Promise<void>;\n close(): void;\n}\n/**\n * A 3D scene rendered in a VR headset (OpenXR — e.g. Meta Quest). The headset drives the camera:\n * every frame both eyes are rendered from the tracked head pose, so `scene.camera` position/lookAt\n * have no effect while the scene is open. The world origin is at floor level (stage space) —\n * author content with the ground at y = 0 and the user standing at the origin.\n *\n * `open()` rejects on hosts without a VR runtime (\"VR is not supported on this device\").\n */\nexport declare class VRScene extends Scene {\n open(options?: PresentOptions): Promise<void>;\n close(): void;\n}\n","types/gl/Shape.d.ts":"import { Aspect } from \"../core/Aspect\";\nimport { type Vec3Like } from \"../math/vec\";\nimport type { Node } from \"./Node\";\nexport declare class Shape extends Aspect<\"shape\", Node> {\n static readonly aspect = \"shape\";\n /** Box half-extents [hx, hy, hz] (world units). */\n box?: Vec3Like;\n /** Sphere radius. */\n sphere?: number;\n /** Cylinder aligned on Y: half-height + radius. */\n cylinder?: {\n halfHeight: number;\n radius: number;\n };\n /** Capsule aligned on Y: half-height of the cylinder section + radius. */\n capsule?: {\n halfHeight: number;\n radius: number;\n };\n /** Whether pointer rays can hit this shape (click / touchstart). Default true. */\n raycast: boolean;\n private _shapeId;\n private _bodyId;\n onAttach(): void;\n onDetach(): void;\n private _createPickBody;\n private _build;\n}\n","types/gl/state.d.ts":"import type { Scene } from \"./Scene\";\nexport declare const glState: {\n activeScene: Scene | null;\n};\n","types/gl/Texture.d.ts":"import { type FetchResponse, type File } from \"../runtime/fetch\";\nexport declare class Texture {\n readonly width: number;\n readonly height: number;\n /** Horizontal wrap mode (U). */\n wrapS: number;\n /** Vertical wrap mode (V). */\n wrapT: number;\n constructor(width: number, height: number, id: number);\n static fromCanvas(canvas: {\n _bakeSurface(): number;\n width: number;\n height: number;\n pixelRatio: number;\n _tex3dId: number;\n }): Texture;\n static load(source: string | FetchResponse | File): Promise<Texture>;\n}\n","types/gl/touch.d.ts":"export declare const registerTouchStartEvent: () => void;\nexport declare const registerTouchEndEvent: () => void;\n","types/gl/Trigger.d.ts":"import { Aspect } from \"../core/Aspect\";\nimport { type Vec3Like } from \"../math/vec\";\nimport type { Node } from \"./Node\";\nexport declare class Trigger extends Aspect<\"trigger\", Node> {\n static readonly aspect = \"trigger\";\n private _bodyId;\n /** Native body id (0 if no physics support). */\n get id(): number;\n onAttach(): void;\n onDetach(): void;\n /** Reposition the trigger zone to a world point. */\n moveTo(p: Vec3Like): this;\n}\n","types/inject.d.ts":"export { Mathf } from \"./math/Mathf\";\nexport { Vec2, Vec3 } from \"./math/vec\";\nexport { Quat } from \"./math/quat\";\nexport { Mat4 } from \"./math/mat4\";\nexport { Color } from \"./core/color\";\nexport { Aspect, type With } from \"./core/Aspect\";\nexport { InspectorUI } from \"./core/InspectorUI\";\nexport { signal, computed, effect, type Signal, type Computed } from \"./core/signals\";\nexport { Canvas, Bitmap } from \"./canvas/Canvas\";\nexport { toast, openURL, SvgSource } from \"./runtime/misc\";\nexport { app, type AppState } from \"./runtime/app\";\nexport { clipboard } from \"./runtime/clipboard\";\nexport { date, type DateValue, type DateInput, type Unit, type Locale } from \"./runtime/datetime\";\nexport { fetch, fetchLocal, FormData, File, type FetchResponse } from \"./runtime/fetch\";\nexport { localStorage } from \"./runtime/storage\";\nexport { device, type HapticStyle, type MotionOptions } from \"./runtime/device\";\nexport { Input } from \"./runtime/input\";\nexport { WebSocket } from \"./runtime/net\";\nexport { AudioPlayer, VideoPlayer } from \"./runtime/media\";\nexport { openFilePicker } from \"./runtime/files\";\nexport { share } from \"./runtime/share\";\nexport { ClickEvent, TouchStartEvent, LongPressEvent } from \"./runtime/touch\";\nexport { Scene2D } from \"./g2/Scene2D\";\nexport { Node2D } from \"./g2/Node2D\";\nexport { Camera2D } from \"./g2/Camera2D\";\nexport { Sprite } from \"./g2/Sprite\";\nexport { SpriteAnimation } from \"./g2/SpriteAnimation\";\nexport { Shape2D } from \"./g2/Shape2D\";\nexport { Physics2D } from \"./g2/Physics2D\";\nexport { Trigger2D } from \"./g2/Trigger2D\";\nexport { CharacterController2D } from \"./g2/CharacterController2D\";\nexport { Tilemap } from \"./g2/Tilemap\";\nexport { Texture2D } from \"./g2/Texture2D\";\nexport { SpriteSheet, defineSpriteSheet } from \"./g2/SpriteSheet\";\nexport type { SpriteSheetDef, SheetSprite, SpriteMakeOptions } from \"./g2/SpriteSheet\";\nexport { Tileset, defineTileset, Autotile2D } from \"./g2/Tileset\";\nexport { rawCell, isRawCell, rawIndex } from \"./g2/autotile\";\nexport { rot90, rot180, rot270, flipX, packTile, tileIndex, tileTurns, tileFlip, tileOriented } from \"./g2/autotile\";\nexport type { TilesetDef, TileMaterial, PatchMaterial, PathMaterial, PatchSlots, EdgeSlot, FillBlock, BlockEntry, TileBlock, TilePart, } from \"./g2/autotile\";\nexport { defineScene2d, Scene2dHandle } from \"./g2/defineScene2d\";\nexport type { Scene2dDef, Scene2dNodeDef, Scene2dEnv, SpriteSourceDef, TilemapSourceDef, Camera2dNodeDef, LoadedScene2d } from \"./g2/defineScene2d\";\nexport { cells, encodeCells, type CellsData } from \"./g2/cells\";\nexport { CameraFollow } from \"./g2/scenarios2d\";\nexport { UIScreen, type UIScreenStyle, UIRow, UIColumn, UIBox, type UIContainerStyle, UIText, type UITextStyle, UIButton, type UIButtonStyle, UIImage, type UIImageStyle, UIVideo, type UIVideoStyle, UIInput, UITextArea, type UIInputStyle, UIScrollable, type UIScrollableStyle, UIPager, type UIPagerStyle, UITabs, type UITabDef, defineTabs, type TabDef, type TabsHandle, UIWidget, type UIWidgetStyle, UIModal, type UIModalStyle, UIBottomSheet, type UIBottomSheetStyle, UIPopover, type UIPopoverStyle, UISpacer, type UISpacerStyle, UIVirtualizedList, Router, NativeView, type UINativeViewStyle, registerFont, __uiMap, __UIColumn, __UIRow, __UIBox, __UIButton, __UIScreen, __UIScrollable, __UIWidget, } from \"./ui/UI\";\nexport { Presentable } from \"./ui/UI\";\nexport type { PresentOptions, Transition, TransitionName, TransitionSpec, TransitionTransform } from \"./ui/UI\";\nexport type { UINode, UINodeChild } from \"./ui/UINode\";\nexport { theme, type ThemeValues, type ThemeAccessors } from \"./ui/theme\";\nexport { animate, animateMat4, stopAnimation, pauseAnimation, resumeAnimation } from \"./animate/animate\";\nexport { cubicBezier } from \"./animate/bezier\";\nexport { easeIn, easeOut, easeInOut } from \"./animate/easings\";\nexport { QRScanner } from \"./plugins/qr\";\nexport { CameraView, type CameraFacing } from \"./plugins/camera\";\nexport { Geolocation, type GeoPosition, type GeoOptions, type GeoWatch } from \"./plugins/geolocation\";\nexport { Push, type PushPayload, type PushStatus, type PushRegisterOptions, type PushEvent } from \"./plugins/push\";\nexport { Service } from \"./plugins/service\";\nexport { defineScene, use, ref, make, SceneHandle } from \"./scene/defineScene\";\nexport type { SceneDef, SceneNodeDef, MeshDef, LightDef, MaterialDef, CameraNodeDef, AspectEntry, MakeEntry, LoadedScene } from \"./scene/defineScene\";\nexport type { FieldMeta } from \"./core/fields\";\nexport { MoveTo, FollowPath, Spin, LookAt, PlayAnimation } from \"./gl/scenarios\";\nexport { registerEditorWindow, registerEditorTool, __editorPlugins } from \"./scene/editorPlugins\";\nexport type { EditorApi, EditorRayHit, EditorToolHooks, EditorWindowFn } from \"./scene/editorPlugins\";\nexport { Scene, ARScene, VRScene } from \"./gl/Scene\";\nexport { Node } from \"./gl/Node\";\nexport { Mesh } from \"./gl/Mesh\";\nexport { Model } from \"./gl/Model\";\nexport { Shape } from \"./gl/Shape\";\nexport { Physics } from \"./gl/Physics\";\nexport { Trigger } from \"./gl/Trigger\";\nexport { CharacterController } from \"./gl/CharacterController\";\nexport { ModelAnimation } from \"./gl/ModelAnimation\";\nexport { Light } from \"./gl/Light\";\nexport { Material } from \"./gl/Material\";\nexport { Geometry } from \"./gl/Geometry\";\nexport { Texture } from \"./gl/Texture\";\nexport { Camera } from \"./gl/Camera\";\nexport { Ray } from \"./gl/Ray\";\nexport { Plane } from \"./gl/Plane\";\nexport { Noise } from \"./gl/Noise\";\nexport { Particles, Trail, curve, colorCurve } from \"./gl/Particles\";\n","types/math/mat4.d.ts":"import { Vec3, type Vec3Like } from \"./vec\";\nimport { Quat, type QuatLike, type EulerOrder } from \"./quat\";\nexport type Mat4Like = Mat4 | number[] | Float32Array | readonly number[];\nexport declare class Mat4 {\n /** The raw column-major elements (length 16). Public on purpose — read/write directly when you want\n * the metal: `mat.m[12] += vx * dt`. The fluent methods never mutate it (they return a new Mat4). */\n m: number[];\n constructor(src?: Mat4Like);\n set(values: ArrayLike<number>): this;\n copy(src: Mat4Like): this;\n /** `this · b` (apply `b` first in local space, then `this`). */\n mul(b: Mat4Like): Mat4;\n /** `b · this` — multiply on the other side (apply `this` first, then `b`). */\n premul(b: Mat4Like): Mat4;\n invert(): Mat4;\n transpose(): Mat4;\n determinant(): number;\n /** `this · translate(v)`. */\n translate(v: Vec3Like): Mat4;\n /** `this · scale(v)`. Accepts a vector or a uniform scalar. */\n scale(v: Vec3Like | number): Mat4;\n /** `this · rotate(axis, rad)`. */\n rotate(rad: number, axis: Vec3Like): Mat4;\n rotateX(rad: number): Mat4;\n rotateY(rad: number): Mat4;\n rotateZ(rad: number): Mat4;\n /** Transform a point (applies translation + perspective divide). */\n transformPoint(v: Vec3Like): Vec3;\n /** Transform a direction (rotation/scale only — no translation, no divide). */\n transformDirection(v: Vec3Like): Vec3;\n get position(): Vec3;\n get scaling(): Vec3;\n get rotation(): Quat;\n get eulerAngles(): Vec3;\n toEuler(order?: EulerOrder): Vec3;\n /** `{ position, rotation, scale }` in one shot. */\n decompose(): {\n position: Vec3;\n rotation: Quat;\n scale: Vec3;\n };\n /** Column basis vectors (the local X / Y / Z axes in world space). */\n get basisX(): Vec3;\n get basisY(): Vec3;\n get basisZ(): Vec3;\n clone(): Mat4;\n toArray(): number[];\n toFloat32Array(): Float32Array;\n equals(b: Mat4Like, eps?: number): boolean;\n static identity(): Mat4;\n static from(src: Mat4Like): Mat4;\n /** Translation · Rotation · Scale into one matrix. `scale` defaults to 1 and accepts a scalar. */\n static compose(position: Vec3Like, rotation: QuatLike, scale?: Vec3Like | number): Mat4;\n static fromQuat(q: QuatLike): Mat4;\n static fromTranslation(v: Vec3Like): Mat4;\n static fromScale(v: Vec3Like | number): Mat4;\n static fromEuler(x: number, y: number, z: number, order?: EulerOrder): Mat4;\n /** A view matrix that looks from `eye` toward `center` with `up`. */\n static lookAt(eye: Vec3Like, center: Vec3Like, up?: Vec3Like): Mat4;\n /** A world matrix that places something at `eye` oriented to look at `target`. */\n static targetTo(eye: Vec3Like, target: Vec3Like, up?: Vec3Like): Mat4;\n /** Perspective projection (WebGL/OpenGL clip, NDC z ∈ [−1, 1]). `fovy` is in RADIANS. */\n static perspective(fovy: number, aspect: number, near: number, far: number): Mat4;\n /** Orthographic projection (WebGL/OpenGL clip, NDC z ∈ [−1, 1]). */\n static ortho(left: number, right: number, bottom: number, top: number, near: number, far: number): Mat4;\n}\n","types/math/Mathf.d.ts":"export type Damper<T extends number | number[]> = ((target: T, dt: number) => T) & {\n /** Snap the damper's internal current value (e.g. on teleport). */\n setValue(value: T): void;\n};\ndeclare function smoothDamp(initial: number, smoothTime: number, maxSpeed?: number): Damper<number>;\ndeclare function smoothDamp(initial: number[], smoothTime: number, maxSpeed?: number): Damper<number[]>;\nexport declare const Mathf: {\n PI: number;\n TAU: number;\n EPSILON: number;\n DEG2RAD: number;\n RAD2DEG: number;\n deg2rad: (deg: number) => number;\n rad2deg: (rad: number) => number;\n clamp: (v: number, min: number, max: number) => number;\n clamp01: (v: number) => number;\n lerp: (a: number, b: number, t: number) => number;\n inverseLerp: (a: number, b: number, v: number) => number;\n remap: (v: number, inMin: number, inMax: number, outMin: number, outMax: number) => number;\n /** Move `a` toward `b` by at most `maxDelta`. */\n moveTowards: (a: number, b: number, maxDelta: number) => number;\n /** Frame-rate-independent exponential approach (good default: lambda 5..15). */\n damp: (a: number, b: number, lambda: number, dt: number) => number;\n sign: (x: number) => number;\n /** Loop a value into [0, length). */\n repeat: (t: number, length: number) => number;\n /** Ping-pong a value in [0, length]. */\n pingPong: (t: number, length: number) => number;\n random: (min?: number, max?: number) => number;\n randomInt: (min: number, max: number) => number;\n /**\n * Critically-damped follow (Unity SmoothDamp). Returns a stateful damper you call every frame:\n * const d = Mathf.smoothDamp([x, y], 0.15)\n * pos = d(targetPos, dt)\n * Works on a number or a numeric array (vec2 / vec3).\n */\n smoothDamp: typeof smoothDamp;\n};\nexport {};\n","types/math/quat.d.ts":"import { Vec3, type Vec3Like } from \"./vec\";\nexport type QuatLike = Quat | readonly [number, number, number, number] | number[] | Float32Array;\nexport type EulerOrder = \"XYZ\" | \"YXZ\" | \"ZXY\" | \"ZYX\" | \"YZX\" | \"XZY\";\n/** Read the w / 4th component of any quaternion-like (wrapper `.w`, or array-like `[3]`). */\nexport declare const cw: (q: {\n w?: number;\n} | ArrayLike<number>) => number;\nexport declare class Quat {\n x: number;\n y: number;\n z: number;\n w: number;\n constructor(x?: number | QuatLike, y?: number, z?: number, w?: number);\n set(x: number, y: number, z: number, w: number): this;\n copy(q: QuatLike): this;\n /** Hamilton product `this ⊗ b` (apply `b` first, then `this`). */\n mul(b: QuatLike): Quat;\n normalize(): Quat;\n conjugate(): Quat;\n /** Inverse rotation. For a unit quaternion this equals `conjugate()`. */\n invert(): Quat;\n dot(b: QuatLike): number;\n /** Spherical interpolation toward `b` by `t ∈ [0, 1]`. */\n slerp(b: QuatLike, t: number): Quat;\n /** Angular distance (radians) between two unit quaternions. */\n angle(b: QuatLike): number;\n /** Rotate a vector by this quaternion → a new `Vec3`. */\n rotateVec3(v: Vec3Like): Vec3;\n /** Extract euler angles (DEGREES) in the given order. */\n toEuler(order?: EulerOrder): Vec3;\n equals(b: QuatLike, eps?: number): boolean;\n /** True if the two unit quaternions represent the same rotation (±q are equal). */\n sameRotation(b: QuatLike, eps?: number): boolean;\n clone(): Quat;\n toArray(): [number, number, number, number];\n [Symbol.iterator](): Iterator<number>;\n static from(q: QuatLike): Quat;\n static get identity(): Quat;\n /** From euler angles in DEGREES (default order \"YXZ\"). Inverts `toEuler`. */\n static fromEuler(x: number, y: number, z: number, order?: EulerOrder): Quat;\n /** From a rotation `axis` and an angle in RADIANS. The axis is normalized for you. */\n static fromAxisAngle(axis: Vec3Like, rad: number): Quat;\n /** The shortest rotation that takes direction `a` onto direction `b`. */\n static fromTo(a: Vec3Like, b: Vec3Like): Quat;\n /** A rotation whose forward (−Z) points along `forward`, with `up` as the reference up axis. */\n static lookRotation(forward: Vec3Like, up?: Vec3Like): Quat;\n}\n/** Quaternion from a column-major rotation matrix (≥3×3, indices 0,1,2,4,5,6,8,9,10). gl-matrix's\n * `getRotation` algorithm — the exact inverse of building a matrix from a quaternion. */\nexport declare const quatFromColMajor: (m: ArrayLike<number>) => Quat;\n/** Euler angles (DEGREES) from a column-major rotation matrix, standard three.js extraction.\n * Element naming follows the column-major layout: mRC = m[(C-1)*4 + (R-1)]. */\nexport declare const eulerFromColMajor: (m: ArrayLike<number>, order?: EulerOrder) => Vec3;\n","types/math/vec.d.ts":"export type Vec2Like = Vec2 | readonly [number, number] | number[] | Float32Array;\nexport type Vec3Like = Vec3 | readonly [number, number, number] | number[] | Float32Array;\n/** Read the x / first component of any vector-like (wrapper, tuple, or typed array). `?? ` is safe on\n * 0 and NaN — it only falls through on `undefined` (i.e. a non-wrapper that has no `.x`). */\nexport declare const cx: (v: {\n x?: number;\n} | ArrayLike<number>) => number;\nexport declare const cy: (v: {\n y?: number;\n} | ArrayLike<number>) => number;\nexport declare const cz: (v: {\n z?: number;\n} | ArrayLike<number>) => number;\nexport declare class Vec2 {\n x: number;\n y: number;\n constructor(x?: number | Vec2Like, y?: number);\n /** Mutate the components in place. Returns `this`. */\n set(x: number, y: number): this;\n /** Copy another vector's components into this one. Returns `this`. */\n copy(v: Vec2Like): this;\n add(v: Vec2Like): Vec2;\n sub(v: Vec2Like): Vec2;\n mul(v: Vec2Like): Vec2;\n div(v: Vec2Like): Vec2;\n scale(s: number): Vec2;\n /** `this + v * s` (fused multiply-add). */\n scaleAndAdd(v: Vec2Like, s: number): Vec2;\n negate(): Vec2;\n dot(v: Vec2Like): number;\n /** 2D cross product → the scalar z of the 3D cross (signed parallelogram area). */\n cross(v: Vec2Like): number;\n length(): number;\n lengthSq(): number;\n distanceTo(v: Vec2Like): number;\n distanceSqTo(v: Vec2Like): number;\n normalize(): Vec2;\n lerp(v: Vec2Like, t: number): Vec2;\n clamp(min: Vec2Like, max: Vec2Like): Vec2;\n min(v: Vec2Like): Vec2;\n max(v: Vec2Like): Vec2;\n /** Left-hand perpendicular: (-y, x), a 90° CCW turn. */\n perp(): Vec2;\n /** Rotate by `rad` (CCW) around `origin` (default 0). */\n rotate(rad: number, origin?: Vec2Like): Vec2;\n /** The vector's heading in radians: `atan2(y, x)`. */\n heading(): number;\n /** Angle (radians) between this and `v`. */\n angle(v: Vec2Like): number;\n withX(x: number): Vec2;\n withY(y: number): Vec2;\n equals(v: Vec2Like, eps?: number): boolean;\n clone(): Vec2;\n toArray(): [number, number];\n [Symbol.iterator](): Iterator<number>;\n static from(v: Vec2Like): Vec2;\n static get zero(): Vec2;\n static get one(): Vec2;\n static get up(): Vec2;\n static get down(): Vec2;\n static get left(): Vec2;\n static get right(): Vec2;\n}\nexport declare class Vec3 {\n x: number;\n y: number;\n z: number;\n constructor(x?: number | Vec3Like, y?: number, z?: number);\n set(x: number, y: number, z: number): this;\n copy(v: Vec3Like): this;\n add(v: Vec3Like): Vec3;\n sub(v: Vec3Like): Vec3;\n mul(v: Vec3Like): Vec3;\n div(v: Vec3Like): Vec3;\n scale(s: number): Vec3;\n /** `this + v * s` (fused multiply-add). */\n scaleAndAdd(v: Vec3Like, s: number): Vec3;\n negate(): Vec3;\n dot(v: Vec3Like): number;\n cross(v: Vec3Like): Vec3;\n length(): number;\n lengthSq(): number;\n distanceTo(v: Vec3Like): number;\n distanceSqTo(v: Vec3Like): number;\n normalize(): Vec3;\n lerp(v: Vec3Like, t: number): Vec3;\n clamp(min: Vec3Like, max: Vec3Like): Vec3;\n min(v: Vec3Like): Vec3;\n max(v: Vec3Like): Vec3;\n /** Reflect this vector about a (unit) `normal`: `v - 2·(v·n)·n`. */\n reflect(normal: Vec3Like): Vec3;\n /** Vector projection of this onto `onto`. */\n project(onto: Vec3Like): Vec3;\n /** Angle (radians) between this and `v`. */\n angle(v: Vec3Like): number;\n /** Rotate this point around the X axis through `origin` (default 0) by `rad`. */\n rotateX(rad: number, origin?: Vec3Like): Vec3;\n rotateY(rad: number, origin?: Vec3Like): Vec3;\n rotateZ(rad: number, origin?: Vec3Like): Vec3;\n /** Rotate this vector by a quaternion (x, y, z, w). Accepts a `Quat` or a raw `[x,y,z,w]`. */\n rotate(q: ArrayLike<number> | {\n x: number;\n y: number;\n z: number;\n w: number;\n }): Vec3;\n /** Transform this point by a column-major mat4 (a `Mat4`, its `.m`, or a raw length-16 array),\n * applying translation and the perspective divide. */\n transform(m: ArrayLike<number> | {\n m: ArrayLike<number>;\n }): Vec3;\n withX(x: number): Vec3;\n withY(y: number): Vec3;\n withZ(z: number): Vec3;\n equals(v: Vec3Like, eps?: number): boolean;\n clone(): Vec3;\n toArray(): [number, number, number];\n [Symbol.iterator](): Iterator<number>;\n static from(v: Vec3Like): Vec3;\n static get zero(): Vec3;\n static get one(): Vec3;\n static get up(): Vec3;\n static get down(): Vec3;\n static get left(): Vec3;\n static get right(): Vec3;\n /** Forward is −Z (the engine's cameras look down −Z; `node.forward` is −Z at identity). */\n static get forward(): Vec3;\n static get back(): Vec3;\n}\n","types/plugins/camera.d.ts":"import { File } from \"../runtime/fetch\";\nimport { type PresentOptions } from \"../ui/presentable\";\nimport { NativeView } from \"../ui/NativeView\";\nexport type CameraFacing = \"front\" | \"back\";\nexport interface CameraView extends NativeView {\n /** Request camera permission, then present the preview. The current destination stays visible\n * until the camera is ready; rejects if permission is denied, the host has no camera, or\n * another navigation superseded this one. */\n open(options?: PresentOptions): Promise<void>;\n /** Capture a still frame as an image `File` (host-encoded). */\n takePhoto(): Promise<File>;\n /** Switch between the front and back camera while the preview is live. */\n setFacingMode(facingMode: CameraFacing): Promise<void>;\n}\n/**\n * Create a camera view (default: the back camera). `CameraView.isSupported` reports whether this\n * host has a camera capability — check it before offering the feature.\n */\nexport declare const CameraView: {\n (options?: {\n facingMode?: CameraFacing;\n }): CameraView;\n /** Whether this host registered a \"camera\" view. */\n readonly isSupported: boolean;\n};\n","types/plugins/geolocation.d.ts":"export interface GeoPosition {\n latitude: number;\n longitude: number;\n /** Horizontal accuracy radius, meters. */\n accuracy: number;\n /** Meters above sea level, or null when the provider doesn't know. */\n altitude: number | null;\n /** Direction of travel in degrees clockwise from north, or null when stationary/unknown. */\n heading: number | null;\n /** Ground speed in m/s, or null when unknown. */\n speed: number | null;\n /** When this fix was taken, ms epoch. */\n timestamp: number;\n}\nexport interface GeoOptions {\n /** Prefer the precise (GPS) provider — slower first fix, more battery. Default false. */\n highAccuracy?: boolean;\n /** getCurrent only: reject with \"timeout\" if no fix arrives in this many ms. */\n timeout?: number;\n}\n/** A live `Geolocation.watch()` subscription — `stop()` it when the screen goes away. */\nexport interface GeoWatch {\n stop(): void;\n}\n/**\n * The device position. `Geolocation.isSupported` reports whether this host registered the\n * service — check it before offering location features.\n */\nexport declare const Geolocation: {\n /** Whether this host registered a \"geolocation\" service. */\n readonly isSupported: boolean;\n /** One position fix. Prompts for permission on first use; rejects on denial (\"denied\"), no\n * provider (\"unavailable\"), or `options.timeout` elapsing (\"timeout\"). */\n getCurrent(options?: GeoOptions): Promise<GeoPosition>;\n /** Continuous updates. Resolves once watching (permission granted + provider started) — so a\n * denial is a rejection, never a silently dead callback. One host watch serves every\n * subscriber; the options of the watch that starts it win. Always `stop()` when done. */\n watch(callback: (position: GeoPosition) => void, options?: GeoOptions): Promise<GeoWatch>;\n};\n","types/plugins/permission.d.ts":"export declare const _requestCameraPermission: () => Promise<void>;\n","types/plugins/push.d.ts":"/** A delivered notification, as the app sees it. */\nexport interface PushPayload {\n title: string;\n body?: string;\n /** Deep link — also delivered through `app.launchUrl` / the app \"url\" event. */\n url?: string;\n /** The developer's own JSON, ≤ 2 KB serialized. */\n data?: Record<string, any>;\n badge?: number;\n}\nexport interface PushStatus {\n /** OS notification permission for the host app. \"prompt\" = not asked yet. */\n permission: \"granted\" | \"denied\" | \"prompt\";\n /** Whether this device already holds a registration (an address) for this app. */\n registered: boolean;\n}\nexport interface PushRegisterOptions {\n /** Your app's OWN user id (\"external user id\"): lets your server send to `users: [\"u42\"]`\n * instead of storing addresses, fanning out to all the user's devices. CLIENT-ASSERTED and\n * unverified — never target sensitive content by user. The registration reflects the latest\n * `register()` call, so registering without `user` clears it (logout). */\n user?: string;\n}\nexport type PushEvent = \"message\" | \"tap\";\n/**\n * Remote push notifications. `Push.isSupported` reports whether this host registered the\n * service — check it before offering notification features.\n */\nexport declare const Push: {\n /** Whether this host registered a \"push\" service. */\n readonly isSupported: boolean;\n /** Permission + registration state. Never prompts. */\n getStatus(): Promise<PushStatus>;\n /** Ask for permission (first time) and register this device → the opaque address your server\n * targets. Idempotent — safe to call every launch; rejects \"denied\" / \"unavailable\". */\n register(options?: PushRegisterOptions): Promise<{\n address: string;\n }>;\n /** Remove this device's registration (the address stops receiving). */\n unregister(): Promise<void>;\n /** The notification that cold-started this app run, or null. Stable across calls. */\n getLaunch(): Promise<PushPayload | null>;\n /** \"message\" = received while the app is open; \"tap\" = the user tapped one while it ran. */\n addEventListener(event: PushEvent, callback: (payload: PushPayload) => void): void;\n removeEventListener(event: PushEvent, callback: (payload: PushPayload) => void): void;\n};\n","types/plugins/qr.d.ts":"import { type PresentOptions } from \"../ui/presentable\";\nimport { NativeView } from \"../ui/NativeView\";\nexport interface QRScanner extends NativeView {\n /** Fires per decoded camera frame: the decoded string, or `null` for a frame with no readable\n * code (expect those repeatedly while the user aims). The same code can be reported more than\n * once — `close()` or debounce once you have what you need. */\n onScan(callback: (data: string | null) => void): this;\n /** Request camera permission, then present the scanner. The current destination (and its\n * loading state) stays visible until the scanner is ready; rejects if the camera is denied,\n * the host can't scan, or another navigation superseded this one. */\n open(options?: PresentOptions): Promise<void>;\n}\n/**\n * Create a QR scanner view. `QRScanner.isSupported` reports whether this host can scan at all —\n * check it before offering the feature.\n */\nexport declare const QRScanner: {\n (): QRScanner;\n /** Whether this host registered a \"qrScanner\" view. */\n readonly isSupported: boolean;\n};\n","types/plugins/service.d.ts":"export interface Service {\n /** Invoke a method on the service (`battery.call(\"level\")`). Arguments and the result are\n * JSON-serialized; rejects when the host has no such service or the method reports an\n * error. The host session opens lazily on the first call. */\n call(method: string, ...args: any[]): Promise<any>;\n /** Subscribe to an event the service emits while a session is open\n * (`battery.on(\"change\", data => …)`). Payloads are JSON-decoded. */\n on(event: string, callback: (data?: any) => void): this;\n /** Remove a previously added listener. */\n off(event: string, callback: (data?: any) => void): this;\n /** Close the host session (stops whatever the service was doing). Listeners stay\n * registered — a later `call()` opens a fresh session that delivers to them again. */\n close(): void;\n}\n/**\n * A host-registered headless service — the UI-less sibling of `NativeView`. Use it for\n * services without a typed wrapper: native code registered in your app shell\n * (`engine.registerService(\"app.battery\") { … }`) or a third-party plugin's channel.\n * **Host-optional** — gate on `Service.isSupported` (the web editor registers none of them).\n *\n * ```ts\n * if (Service.isSupported(\"app.battery\")) {\n * const battery = Service(\"app.battery\")\n * battery.on(\"change\", data => { level.text = data.level + \"%\" })\n * const { level } = await battery.call(\"level\")\n * }\n * ```\n */\nexport declare const Service: {\n (name: string, params?: any): Service;\n /** Whether this host registered a service under `name`. */\n isSupported(name: string): boolean;\n};\n","types/runtime/app.d.ts":"export type AppState = \"active\" | \"background\";\ntype AppEventMap = {\n /** The app left the foreground (home button, tab hidden, another app on top). Delivered before\n * the host halts the frame loop — the last chance to persist state / pause work. */\n pause: () => void;\n /** The app returned to the foreground; frames are running again. */\n resume: () => void;\n /** A link arrived while the app was running (warm deep link). `app.launchUrl` is already\n * updated to the same value when this fires. */\n url: (url: string) => void;\n /** The on-screen keyboard changed. `height` mirrors `app.keyboardHeight` (the raw overlap, see\n * there); `duration` is the platform's keyboard animation duration in ms (0 where none) — pass\n * it to `animateTo` to move a composer in sync with the keyboard. */\n keyboard: (height: number, duration: number) => void;\n};\nexport declare const app: {\n /** Current lifecycle state. `\"background\"` while the app is not the foreground app / the tab is\n * hidden. `\"active\"` on hosts that don't track it. */\n readonly state: AppState;\n /** The URL the app was (most recently) opened with — the deep link — or `null` for a plain\n * launch. Warm links update it and fire the `\"url\"` event. */\n readonly launchUrl: string | null;\n /** On-screen keyboard height in logical px currently overlapping the app viewport, `0` when\n * hidden. This is the RAW overlap, independent of the focused input's `keyboardShrink` policy —\n * with the default shrink the layout already avoids the keyboard; the main consumer is overlay\n * mode (`keyboardShrink: false`), e.g. a chat composer's `pb`. `0` on hosts without an\n * on-screen keyboard. */\n readonly keyboardHeight: number;\n /** Re-run this app's bundle in a fresh world — the platform's `location.reload()`. Pass `url`\n * to reboot with different launch arguments (the new run reads them via `app.launchUrl`),\n * `null` to reboot with a cleared one, or omit it to replay the current one. No-op on hosts\n * without world control (headless). */\n restart(url?: string | null): void;\n /** Leave this app. Inside the LeCodes viewer that returns to the launcher (the LeCodes home\n * screen); a standalone-built app leaves to the platform instead — Android backgrounds it,\n * iOS ignores the call (the platform forbids programmatic exit). */\n quit(): void;\n /** Global back-press fallback (Android back button/gesture — iOS has no system back). Fires\n * only when nothing else consumed the press: no open widget/modal claimed it, the current\n * screen has no `onBackPressed`, every pager is at its tab root and the router is at its\n * stack root. The place for app-wide policy — e.g. double-press-to-quit:\n *\n * ```ts\n * let armedAt = 0\n * app.onBackPressed(() => {\n * if (Date.now() - armedAt < 2000) { app.quit(); return }\n * armedAt = Date.now()\n * toast(\"Press back again to exit\")\n * })\n * ```\n *\n * Replaces the previous handler; pass `null` to remove. */\n onBackPressed(callback: (() => void) | null): void;\n addEventListener<E extends keyof AppEventMap>(event: E, callback: AppEventMap[E]): void;\n removeEventListener<E extends keyof AppEventMap>(event: E, callback: AppEventMap[E]): void;\n};\nexport {};\n","types/runtime/appEvents.d.ts":"type AppEventCallback = (data?: string) => void;\nexport declare const appEventsOn: (event: string, cb: AppEventCallback) => void;\nexport declare const appEventsOff: (event: string, cb: AppEventCallback) => void;\ntype KeyboardCallback = (height: number, duration: number) => void;\nexport declare const keyboardEventsOn: (cb: KeyboardCallback) => void;\nexport declare const keyboardEventsOff: (cb: KeyboardCallback) => void;\nexport {};\n","types/runtime/channel.d.ts":"export {};\n","types/runtime/clipboard.d.ts":"export declare const clipboard: {\n /** Put `text` on the system clipboard. Silent no-op on hosts without clipboard access. */\n write(text: string): void;\n /** Read text from the system clipboard. Rejects when the platform has no clipboard access, the\n * user denied it, or there is nothing readable. */\n read(): Promise<string>;\n};\n","types/runtime/datetime.d.ts":"export type Locale = \"en\" | \"ru\";\nexport type DateInput = Date | number | string | DateValue;\nexport type Unit = \"ms\" | \"second\" | \"minute\" | \"hour\" | \"day\" | \"week\" | \"month\" | \"year\";\n/**\n * An immutable moment in time — the value returned by [`date()`]. Wraps a single epoch-millisecond\n * scalar (`t`); every method returns a new `DateValue` or a plain scalar, never mutating. Construct\n * it with `date(...)`, not `new`.\n */\nexport declare class DateValue {\n /** Epoch milliseconds — the one canonical scalar. Prefer `valueOf()`; this is public so `date(a)`\n * can read it back cheaply and so tooling can treat it as the value's single component. */\n readonly t: number;\n constructor(ms: number);\n /**\n * Format against a `day.js`-style token pattern (default `\"D MMMM YYYY\"`). Locale defaults to the\n * current device language.\n *\n * Tokens: `YYYY`/`YY` year · `MMMM`/`MMM`/`MM`/`M` month · `DD`/`D` day · `dddd`/`ddd` weekday ·\n * `HH`/`H` 24-hour · `hh`/`h` 12-hour · `mm`/`m` minute · `ss`/`s` second · `A`/`a` AM/PM.\n *\n * ```ts\n * date().format() // \"10 July 2026\" / \"10 июля 2026\"\n * date(ts).format(\"DD.MM.YYYY HH:mm\") // \"10.07.2026 14:05\"\n * date(ts).format(\"MMMM YYYY\", \"ru\") // \"Июль 2026\" (nominative — no day token)\n * ```\n */\n format(pattern?: string, locale?: Locale): string;\n /**\n * Human relative time vs `now` (default: the current time) — \"5 minutes ago\", \"in 2 days\",\n * \"5 минут назад\", \"через 2 дня\". Reads as \"just now\" under ~45 seconds; handles Russian number\n * agreement (`1 минуту` / `2 минуты` / `5 минут`). Locale defaults to the device language.\n */\n timeAgo(locale?: Locale, now?: DateInput): string;\n /** Add `n` of a unit, returning a new value. Linear units (`ms`…`week`) are scalar ms math;\n * `month`/`year` are calendar-aware (clamp on short months, like day.js). */\n add(n: number, unit: Unit): DateValue;\n /** Subtract `n` of a unit. Equivalent to `add(-n, unit)`. */\n subtract(n: number, unit: Unit): DateValue;\n /** Snap down to the start of a unit (local time): start of day/hour/month/year, etc. */\n startOf(unit: Unit): DateValue;\n /** Snap up to the end of a unit (local time): the last millisecond of the day/hour/month/… */\n endOf(unit: Unit): DateValue;\n /** Epoch milliseconds. Enables `+date(x)`, `date(a) < date(b)`, `date(a) - date(b)` via coercion. */\n valueOf(): number;\n /** Whole seconds since the epoch (Unix time). */\n unix(): number;\n /** Signed difference to `other`, in whole `unit`s (default `ms`), truncated toward zero. */\n diff(other: DateInput, unit?: Unit): number;\n isBefore(other: DateInput): boolean;\n isAfter(other: DateInput): boolean;\n isSame(other: DateInput): boolean;\n year(): number;\n /** 0-based month (0 = January), matching `Date.getMonth`. */\n month(): number;\n /** Day of the month, 1–31. */\n day(): number;\n /** Day of the week, 0 (Sunday)–6 (Saturday), matching `Date.getDay`. */\n weekday(): number;\n hour(): number;\n minute(): number;\n second(): number;\n /** A native `Date` snapshot of this value. */\n toDate(): Date;\n}\n/**\n * Create a `DateValue` — a locale-aware, immutable moment, dayjs-style. Accepts a `Date`, a\n * millisecond timestamp (`Date.now()`), a parseable string, or another `DateValue`; with no argument\n * it's the current time. Chain arithmetic and finish with `format` / `timeAgo`, both of which\n * understand **English** and **Russian** and default to the current device language\n * ([`device.language`](../runtime/device.ts)).\n *\n * ```ts\n * date().format(\"dddd, D MMMM\") // \"Friday, 10 July\" / \"пятница, 10 июля\"\n * date(ts).timeAgo() // \"5 minutes ago\" / \"5 минут назад\"\n * date().add(3, \"day\").startOf(\"day\").format(\"D MMMM\")\n * date(a).diff(b, \"hour\") // signed whole hours\n * date(a).isBefore(b) // boolean\n * ```\n */\nexport declare const date: (value?: DateInput) => DateValue;\n","types/runtime/device.d.ts":"import { Quat } from \"../math/quat\";\nimport { Vec3 } from \"../math/vec\";\ntype ResizeCallback = (width: number, height: number) => void;\ntype DeviceEventMap = {\n resize: ResizeCallback;\n /** Connectivity came back (best-effort, navigator.onLine semantics). */\n online: () => void;\n /** Connectivity was lost. */\n offline: () => void;\n};\n/** Semantic haptic styles for `device.vibrate`. Impact styles (`light`/`medium`/`heavy`/`soft`/\n * `rigid`) are a physical \"tap\" of varying weight; notification styles (`success`/`warning`/`error`)\n * cue an outcome; `selection` is a light tick for a value change. Chosen to map 1:1 onto iOS\n * `UIFeedbackGenerator` and, on Android, `HapticFeedbackConstants` / `VibrationEffect` — so the same\n * call feels native everywhere, rather than a duration that only web/Android can honor. */\nexport type HapticStyle = \"light\" | \"medium\" | \"heavy\" | \"soft\" | \"rigid\" | \"success\" | \"warning\" | \"error\" | \"selection\";\n/** Options for `device.motion.start`. */\nexport interface MotionOptions {\n /** Sensor update interval in seconds (default 1/60). The sensor fuses at ≥ this rate in the\n * background; you poll the freshest sample each frame, so this is a floor, not a sync. */\n interval?: number;\n /** Frame the readables are delivered in. \"world\" (default): engine Y-up, screen-oriented — drops\n * straight into `camera.quaternion` / any node. \"device\": the raw sensor frame, no conversion. */\n frame?: \"world\" | \"device\";\n}\nexport declare const device: {\n readonly platform: \"web\" | \"android\" | \"ios\" | string;\n readonly language: string;\n /** Display device-pixel ratio (physical px per logical/CSS px): 1 on standard displays, 2–3 on\n * retina / iOS. Bake a Canvas at this ratio for crisp output without hardcoding, e.g.\n * `new Canvas(w, h, { pixelRatio: device.pixelRatio })`. NOTE: the web 2D/GL surface currently\n * renders at logical resolution, so on web this only helps UI canvases / is forward-looking for\n * 2D; on iOS (physical surface) it makes 2D canvases crisp. Falls back to 1 if the host omits it. */\n readonly pixelRatio: number;\n /** Current display width in logical px — the same value the \"resize\" event delivers, but readable at\n * any time (not only inside the listener). 0 until the host has reported a size. */\n readonly width: number;\n /** Current display height in logical px — the same value the \"resize\" event delivers, readable at any\n * time. 0 until the host has reported a size. */\n readonly height: number;\n /** Opt into the precise-touch system where the platform supports it. OFF by default. When on, fast\n * strokes are sampled at the touch digitizer's full rate (iOS coalesced touches, ≈120–240 Hz) instead\n * of once per display frame (~60 Hz), so a pointer-heavy app (drawing, handwriting, dragging) gets more\n * points and smoother lines. Leave it off for tap/button UIs. No-op on hosts without a coalesced-input\n * concept (web already coalesces pointermove; headless). */\n setPreciseTouch(enabled: boolean): void;\n /** Fire a one-shot haptic of the given semantic `style` (default `\"medium\"`) — a physical tap on\n * supported hardware (iOS Taptic Engine, Android vibrator). Chosen by meaning, not duration, so it\n * feels native on each platform; see {@link HapticStyle}. Host-gated: a silent no-op where there's\n * no haptic hardware (iPad, older iPhones, web, headless). */\n vibrate(style?: HapticStyle): void;\n /** Device-orientation sensor (gyro + accelerometer, fused) for tilt/steering and magic-window /\n * 360° panoramas. Poll `attitude` / `gravity` inside setLoop; they return the freshest fused\n * sample, so the sensor rate need not match your frame rate. Host-gated: a no-op with no sensor. */\n motion: {\n /** Whether this device has the motion sensors at all (no gyro → false; iPad/older, web, headless). */\n readonly available: boolean;\n /** Whether updates are currently running (start succeeded and stop hasn't been called). */\n readonly enabled: boolean;\n /** Begin sensor updates. Resolves to whether it actually started (false = no sensor / denied).\n * Async so a web host can await its permission prompt; native resolves immediately. */\n start(options?: MotionOptions): Promise<boolean>;\n /** Stop sensor updates and release the sensor (battery). */\n stop(): void;\n /** Capture the current heading as \"forward\" — a yaw-only recenter (pitch/roll stay gravity-\n * referenced, so the horizon stays level). No-op in the \"device\" frame. */\n recenter(): void;\n /** The device's current orientation as a `Quat`. In the \"world\" frame (default) it's engine Y-up\n * and screen-oriented, so `camera.quaternion = device.motion.attitude` is a complete magic-window\n * / panorama camera. `Quat.identity` until the first sample arrives / when not running. */\n readonly attitude: Quat;\n /** Gravity direction for tilt controls. In the \"world\" frame it's SCREEN space (x → right, y →\n * down, matching clientX/clientY), orientation-aware — a 2D game reads `gravity.x / gravity.y`.\n * `(0,0,0)` when not running. */\n readonly gravity: Vec3;\n };\n /** Current connectivity — best-effort navigator.onLine semantics: `false` only when the platform\n * is sure there's no network. `true` on hosts that don't track it. Change events: `\"online\"` /\n * `\"offline\"`. */\n readonly online: boolean;\n addEventListener<E extends keyof DeviceEventMap>(channel: E, callback: DeviceEventMap[E]): void;\n removeEventListener<E extends keyof DeviceEventMap>(channel: E, callback: DeviceEventMap[E]): void;\n};\nexport {};\n","types/runtime/fetch.d.ts":"export type FetchOptions = {\n body?: any;\n method?: string;\n headers?: Record<string, string>;\n useOnce?: boolean;\n onProgress?: (progress: {\n loaded: number;\n total?: number;\n }) => void;\n};\nexport interface FetchResponse {\n readonly status: number;\n json<T = any>(): T;\n text(): string;\n dispose(): void;\n}\nexport declare const fetch: (url: string, options?: FetchOptions) => Promise<FetchResponse>;\nexport declare const fetchLocal: (path: string) => FetchResponse;\n/** A handle to a picked / fetched file (see openFilePicker). */\nexport declare class File {\n readonly name: string;\n readonly size: number;\n constructor(systemId: number, name: string, size: number);\n}\ntype FormDataValue = string | number | boolean | File | FetchResponse;\nexport declare class FormData {\n private _entries;\n append(name: string, value: FormDataValue, filename?: string): void;\n delete(name: string): void;\n}\nexport {};\n","types/runtime/files.d.ts":"import { File } from \"./fetch\";\ntype OpenFilePickerOptions = {\n accept?: string;\n};\nexport declare function openFilePicker(options?: OpenFilePickerOptions & {\n multiple?: false;\n}): Promise<File | null>;\nexport declare function openFilePicker(options: OpenFilePickerOptions & {\n multiple: true;\n}): Promise<File[]>;\nexport {};\n","types/runtime/input.d.ts":"export declare const Input: {\n /**\n * Is a key currently held? `code` is a KeyboardEvent.code-style string, e.g. 'ArrowRight',\n * 'KeyW', 'Space'. Poll this inside setLoop for frame-independent movement.\n */\n key(code: string): boolean;\n};\n","types/runtime/media.d.ts":"import { Emitter } from \"../core/events\";\nimport { Texture } from \"../gl/Texture\";\ntype MediaEvents = {\n /** Fired at each loop boundary while `loop` is true. */\n loopReached: () => void;\n /** Fired once when playback reaches the end while `loop` is false. */\n completed: () => void;\n};\ndeclare abstract class MediaPlayer extends Emitter<MediaEvents> {\n protected _id: number;\n protected _src: string;\n private _playing;\n private _loop;\n private _volume;\n private _disposed;\n private _assertAlive;\n play(): void;\n pause(): void;\n get playing(): boolean;\n set playing(value: boolean);\n get volume(): number;\n set volume(value: number);\n get loop(): boolean;\n set loop(value: boolean);\n /** Current playback position, in seconds. Settable to seek. */\n get time(): number;\n set time(value: number);\n /** Total media length in seconds (0 until metadata has loaded). */\n get duration(): number;\n /** True once {@link dispose} has been called; the player is unusable afterwards. */\n get disposed(): boolean;\n /**\n * Release the underlying host media resource (decoder, network, buffers) immediately and detach\n * all listeners. Idempotent. Any further use of the player throws.\n */\n dispose(): void;\n}\nexport declare class AudioPlayer extends MediaPlayer {\n constructor(src?: string);\n}\nexport declare class VideoPlayer extends MediaPlayer {\n constructor(src?: string);\n /** A 3D Texture that samples this video (e.g. for a Material.video()). */\n get texture(): Texture;\n}\nexport {};\n","types/runtime/misc.d.ts":"/** Show a transient toast notification. */\nexport declare const toast: (msg: string) => void;\n/** Open `url` in the system browser / external handler (fire-and-forget, like `share`). Silent\n * no-op on hosts without one (headless). */\nexport declare const openURL: (url: string) => void;\nexport type SvgSourceValue = {\n readonly svg: string;\n tintColor: string | null;\n};\n/** Wrap raw SVG XML so it can be used as an image source. */\nexport declare const SvgSource: (svg: string) => SvgSourceValue;\n","types/runtime/net.d.ts":"import { Emitter } from \"../core/events\";\ntype SocketEvents = {\n open: () => void;\n message: (data: any) => void;\n close: (code?: number) => void;\n error: () => void;\n};\nexport declare class WebSocket extends Emitter<SocketEvents> {\n private _id;\n constructor(url: string, headers?: Record<string, string>);\n send(message: string | ArrayBuffer): void;\n close(): void;\n private _onMessage;\n}\nexport {};\n","types/runtime/service.d.ts":"export {};\n","types/runtime/share.d.ts":"import type { File, FetchResponse } from \"./fetch\";\nexport declare function share(media: File | FetchResponse, text?: string): void;\n","types/runtime/storage.d.ts":"export declare const localStorage: {\n getItem(key: string): string | null;\n setItem(key: string, value: string): void;\n removeItem(key: string): void;\n};\n","types/runtime/touch.d.ts":"export declare class ClickEvent<T = any> {\n readonly type = \"click\";\n readonly pointerId: number;\n readonly clientX: number;\n readonly clientY: number;\n /** World-space hit position (2D scenes only; undefined in 3D). */\n worldX?: number;\n worldY?: number;\n target: T;\n constructor(clientX: number, clientY: number, pointerId: number);\n}\nexport interface TrackHandler {\n onMove?(pos: {\n clientX: number;\n clientY: number;\n deltaX: number;\n deltaY: number;\n }): void;\n onEnd?(pos: {\n clientX: number;\n clientY: number;\n deltaX: number;\n deltaY: number;\n }): void;\n onCancel?(): void;\n claim?: boolean | \"pan-x\" | \"pan-y\" | \"pan-down\" | \"pan-up\" | \"pan-left\" | \"pan-right\";\n}\nexport declare class TouchStartEvent<T = any> {\n readonly type = \"touchstart\";\n readonly pointerId: number;\n readonly clientX: number;\n readonly clientY: number;\n /** World-space hit position (2D scenes only; undefined in 3D). */\n worldX?: number;\n worldY?: number;\n target: T;\n constructor(clientX: number, clientY: number, pointerId: number);\n /** Capture subsequent moves/end for this pointer (drag/pan gestures). */\n track(handler: TrackHandler): void;\n}\n/** Delivered to a `UIButton` `onLongPress` handler when a finger is held on the button past the\n * host's long-press threshold. Like `TouchStartEvent` it can `track(...)` the rest of the gesture —\n * so the common \"press-and-hold, then drag to move\" flow is one handler: start the drag from here. */\nexport declare class LongPressEvent<T = any> {\n readonly type = \"longpress\";\n readonly pointerId: number;\n readonly clientX: number;\n readonly clientY: number;\n /** World-space hit position (2D scenes only; undefined in 3D). */\n worldX?: number;\n worldY?: number;\n target: T;\n constructor(clientX: number, clientY: number, pointerId: number);\n /** Capture subsequent moves/end for this pointer — drag the element after the hold. */\n track(handler: TrackHandler): void;\n}\n","types/scene/defineScene.d.ts":"import { type With } from \"../core/Aspect\";\nimport { use, ref, make, type AspectEntry, type MakeEntry as SharedMakeEntry } from \"./grammar\";\nimport type { ColorInput } from \"../core/color\";\nimport type { Vec3Like } from \"../math/vec\";\nimport { Scene, type SceneOptions } from \"../gl/Scene\";\nimport { Node } from \"../gl/Node\";\nimport { Mesh } from \"../gl/Mesh\";\nimport { Model } from \"../gl/Model\";\nimport { Light, type SunOptions } from \"../gl/Light\";\nimport { Material, type LitMaterialOptions, type MaterialColorOptions } from \"../gl/Material\";\nimport type { CylinderOptions, PlaneOptions, SphereOptions } from \"../gl/Geometry\";\nexport type MeshDef = {\n kind: \"box\";\n size?: Vec3Like | number;\n} | ({\n kind: \"sphere\";\n} & SphereOptions) | ({\n kind: \"cylinder\";\n} & CylinderOptions) | ({\n kind: \"plane\";\n} & PlaneOptions);\nexport type LightDef = {\n kind: \"sun\";\n} & SunOptions;\nexport type MaterialDef = {\n lit: LitMaterialOptions;\n} | {\n unlit: MaterialColorOptions;\n} | {\n shadow: ColorInput;\n} | Material;\nexport { use, ref, make };\nexport type { AspectEntry };\n/** A `make(fn, args)` source entry whose factory returns a 3D {@link Node}. */\nexport type MakeEntry<A extends Record<string, unknown> = Record<string, unknown>> = SharedMakeEntry<A, Node>;\n/** Transform overrides for one INTERNAL node of a GLB model or a prefab instance\n * (`overrides` on a model/prefab node, keyed by part path). */\nexport type ModelOverrideDef = {\n position?: Vec3Like;\n eulerAngles?: Vec3Like;\n scale?: Vec3Like | number;\n visible?: boolean;\n};\n/** Camera projection settings, shared by the `camera:` source block and the top-level `camera:`\n * block. All optional — an omitted key keeps the host default (60° / 0.01 / 1000). */\nexport type CameraProjectionDef = {\n /** Vertical field of view in degrees (default 60) — smaller is a longer lens. */\n fov?: number;\n /** Near clip distance (default 0.01). */\n near?: number;\n /** Far clip distance = view range (default 1000); geometry past it is culled. */\n far?: number;\n};\n/** The `camera: {}` source block — projection settings for the node that drives the view. */\nexport type CameraNodeDef = CameraProjectionDef;\nexport type SceneNodeDef = {\n mesh?: MeshDef;\n /** GLB url — `asset('./hero.glb')`. */\n model?: string;\n light?: LightDef;\n /** The scene camera as a NODE: in play mode `scene.camera` follows this node's world transform\n * every frame (so movement aspects on it are camera flythroughs); the editor shows a frustum\n * marker and refuses to delete the last camera node. The first camera node in file order wins;\n * cameras inside prefabs are ignored (like a prefab's `camera:` block). */\n camera?: CameraNodeDef;\n /** A code-built subtree — `make(factoryFn, { ...literal args })`. */\n make?: MakeEntry<any>;\n /** Another scene file used as a reusable composition — the imported handle:\n * `import streetlamp from './streetlamp.scene'` … `lamp: { prefab: streetlamp }`. Its nodes\n * instantiate under this node per instance (env/camera are the instancing file's business and\n * are ignored); `ref()`s inside the prefab resolve file-locally, per instance. */\n prefab?: SceneHandle<any>;\n /** Material for a `mesh` source. */\n material?: MaterialDef;\n /** Model/prefab sources: transform overrides for the INTERNAL nodes, keyed by part path\n * (see the part-path grammar above `modelPartRows`). Unresolved paths are ignored. */\n overrides?: Record<string, ModelOverrideDef>;\n /** On a CHILD of a model/prefab node: parent this node to that INTERNAL part of the parent's\n * asset at build time (part path — the same grammar `overrides` keys use), e.g. a flashlight\n * in a hand. The transform stays local to the part. A stale path (asset changed) falls back\n * to the parent root with a console warning. */\n mount?: string;\n position?: Vec3Like;\n eulerAngles?: Vec3Like;\n scale?: Vec3Like | number;\n visible?: boolean;\n /** Editor-only: viewport manipulation won't target this node (fields still edit). No runtime effect. */\n locked?: boolean;\n castShadows?: boolean;\n receiveShadows?: boolean;\n aspects?: readonly AspectEntry<any>[];\n children?: Record<string, SceneNodeDef>;\n};\nexport type SceneCameraDef = CameraProjectionDef & {\n position?: Vec3Like;\n /** Point the camera looks at. */\n target?: Vec3Like;\n};\nexport type SceneDef = {\n env?: SceneOptions;\n camera?: SceneCameraDef;\n nodes?: Record<string, SceneNodeDef>;\n};\ntype SourceNodeOf<N extends SceneNodeDef> = N extends {\n model: string;\n} ? Model : N extends {\n mesh: MeshDef;\n} ? Mesh : N extends {\n light: LightDef;\n} ? Light : Node;\ntype AspectsOf<N extends SceneNodeDef> = N extends {\n aspects: readonly AspectEntry<infer A>[];\n} ? A : never;\ntype NodeOf<N extends SceneNodeDef> = [\n AspectsOf<N>\n] extends [never] ? SourceNodeOf<N> : With<SourceNodeOf<N>, AspectsOf<N>>;\ntype UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (k: infer I) => void ? I : never;\ntype ChildMapsOf<T extends Record<string, SceneNodeDef>, P extends string> = {\n [K in keyof T & string]: T[K] extends {\n children: infer C extends Record<string, SceneNodeDef>;\n } ? NodesOf<C, `${P}${K}/`> : never;\n}[keyof T & string];\ntype NodesOf<T extends Record<string, SceneNodeDef>, P extends string = \"\"> = {\n [K in keyof T & string as `${P}${K}`]: NodeOf<T[K]>;\n} & ([ChildMapsOf<T, P>] extends [never] ? unknown : UnionToIntersection<ChildMapsOf<T, P>>);\nexport type SceneNodes<D extends SceneDef> = D[\"nodes\"] extends Record<string, SceneNodeDef> ? NodesOf<D[\"nodes\"]> : Record<string, Node>;\nexport type LoadedScene<D extends SceneDef> = {\n scene: Scene;\n nodes: SceneNodes<D>;\n /** Path lookup — typed for this scene's literal paths, `Node | null` for arbitrary strings. */\n get: {\n <P extends keyof SceneNodes<D> & string>(path: P): SceneNodes<D>[P];\n (path: string): Node | null;\n };\n};\n/** One INTERNAL node of a loaded GLB (editor introspection). */\nexport type ModelPartRow = {\n path: string;\n name: string;\n depth: number;\n node: Node;\n};\n/** Flatten a model's (or prefab instance's) internal hierarchy to rows (depth-first, the root\n * excluded). `__generated` containers are derived output, and def-built nodes (`_sceneDef` —\n * plain or `mount`ed children of the model) are addressed by their own def paths — both are\n * not parts, skipped. Filtering BEFORE segment math keeps `name[i]` indices stable no matter\n * what defs are parented in. */\nexport declare const modelPartRows: (root: Node) => ModelPartRow[];\nexport declare class SceneHandle<D extends SceneDef = SceneDef> {\n readonly def: D;\n private _loading?;\n constructor(def: D);\n /** Instantiate the scene (idempotent — subsequent calls return the same instance). Does not open. */\n load(): Promise<LoadedScene<D>>;\n /** Load and make active. */\n open(): Promise<LoadedScene<D>>;\n}\n/**\n * Define a scene as data — the default export of a `.scene.ts` file. Returns a typed handle:\n * `const { scene, nodes, get } = await handle.open()` gives `nodes[path]` typed by its source\n * block (Mesh / Model / Light / Node) with its `use(...)`d aspects attached — root nodes read as\n * plain properties (`nodes.hero`), nested ones by path (`nodes['hero/halo']` / `get('hero/halo')`).\n */\nexport declare const defineScene: <const D extends SceneDef>(def: D) => SceneHandle<D>;\n","types/scene/editorPlugins.d.ts":"import type { InspectorUI } from \"../core/InspectorUI\";\n/** A geometry hit under the viewport pointer, handed to tools. Physics builds raycast the scene's\n * meshes (precise); otherwise (and on misses) the hit falls back to the ground plane (y = 0). */\nexport type EditorRayHit = {\n point: [number, number, number];\n normal: [number, number, number];\n /** Absolute path of the scene-file node the hit belongs to (\"city/in1/pt1\") — null for\n * ground-plane fallback hits. */\n node: string | null;\n};\n/**\n * The editor scripting API handed to windows and tools. Nodes are addressed by ABSOLUTE PATH —\n * '/'-joined names from the scene root; a root node's path is its bare name. Doc-op methods write\n * the scene DOCUMENT through the editor's normal commit path (undo, file, live patching all\n * included); they return false / no-op when the document can't take the edit (sibling-name\n * collision, unknown path).\n */\nexport type EditorApi = {\n /** The currently selected node path (or `path::part` key for asset internals), null when\n * nothing is selected. */\n readonly selection: string | null;\n select(path: string | null): void;\n /** The scene document's nodes: absolute path, sibling-unique display name, source kind\n * (mesh / model / light / group / …). */\n nodes(): {\n path: string;\n name: string;\n kind: string;\n }[];\n /** First unused \"base\", \"base2\", \"base3\", … name among the SIBLINGS under `parentPath`\n * (scene root when omitted). */\n uniqueName(base: string, parentPath?: string): string;\n /** Add a ROOT node from plain def data (scene-file grammar; a string `model` value means an\n * asset path). `name` may not contain '/' or ':'. One undo step unless grouped by `transact`. */\n addNode(name: string, def: Record<string, unknown>): boolean;\n /** Write one def prop (transforms apply live; anything else patches/re-runs the node). */\n setProp(path: string, key: string, value: unknown): boolean;\n removeNode(path: string): void;\n /** Duplicate a node; returns the copy's path (null when it can't). */\n duplicate(path: string): string | null;\n /** Raycast the scene under a viewport pixel (same hit rules as tool clicks). */\n raycast(screenX: number, screenY: number): EditorRayHit | null;\n /** Group every doc edit inside `fn` into ONE undo step. */\n transact(fn: () => void): void;\n};\nexport type EditorWindowFn = (ui: InspectorUI, editor: EditorApi) => void;\nexport type EditorToolHooks = {\n /** CSS cursor for the viewport while this tool is active (default \"crosshair\"). */\n cursor?: string;\n /** A short glyph (one character / emoji) for the tool's toolbar button — tools without one all\n * share the generic wand icon, so any editor with two or more tools should set it. */\n icon?: string;\n /** A viewport click while the tool is active — `hit` is the raycast result under the pointer.\n * Viewport clicks route to the tool while it is active. */\n onViewportClick?(hit: EditorRayHit, editor: EditorApi): void;\n};\n/** Register an editor panel — a collapsible overlay docked over the viewport (the inspector rail\n * stays selection-scoped). A window that emits `ui.toolButton` for a tool becomes that tool's\n * settings panel: activating the tool expands and highlights it. `render` re-runs immediate-mode\n * on every interaction — same protocol as `static inspector` cards. */\nexport declare const registerEditorWindow: (title: string, render: EditorWindowFn) => void;\n/** Register a viewport tool — a toolbar entry beside move/rotate/scale (activate it there or via\n * `ui.toolButton(label, name)`). While active, viewport clicks arrive as raycast hits. */\nexport declare const registerEditorTool: (name: string, hooks: EditorToolHooks) => void;\n","types/scene/grammar.d.ts":"import type { Aspect, AspectCtor } from \"../core/Aspect\";\nimport type { Node } from \"../gl/Node\";\n/** One aspect to attach, created by `use(Ctor, props)`. */\nexport type AspectEntry<A extends Aspect<any, any> = Aspect<any, any>> = {\n ctor: AspectCtor<A>;\n props?: Partial<A>;\n};\n/** Reference an aspect in a scene file: `aspects: [use(Physics, { motion: 'static' })]`. Props are\n * typechecked against the aspect's fields, exactly like `node.aspect(Ctor, props)`. */\nexport declare const use: <A extends Aspect<any, any>>(ctor: AspectCtor<A>, props?: Partial<A>) => AspectEntry<A>;\n/** A `make(fn, args)` source entry — see {@link make}. `N` is the node family the factory returns\n * (3D `Node` by default; a `.scene2d.ts` file's factories return `Node2D`). */\nexport type MakeEntry<A extends Record<string, unknown> = Record<string, unknown>, N = Node> = {\n fn: (args: A) => N | Promise<N>;\n args?: A;\n};\n/**\n * A code-created source in a scene file: `tower: { make: make(buildTower, { floors: 5 }), … }`.\n * The factory runs after every scene node exists (so `ref()` args resolve, forward references\n * included) and its returned subtree mounts under the def node — the def's transform stays\n * editor-owned, so moving the node never re-calls the factory. Args must be literal data (same\n * grammar as aspect props); in the editor they edit as fields, and an arg change re-CALLS the\n * factory live — the code is already in the bundle, so no compile happens. Keep factories pure\n * builders: same args → same subtree, no side effects outside the returned nodes.\n */\nexport declare const make: <A extends Record<string, unknown>, N>(fn: (args: A) => N | Promise<N>, args?: A) => MakeEntry<A, N>;\n/**\n * Reference another scene node by PATH in an aspect's props:\n * `use(Road, { from: ref('pointA'), to: ref('lane/pointB') })`. Resolves to the live node when\n * aspects attach — after EVERY node of the scene exists, so declaration order doesn't matter.\n * Resolution is scoped upward from the host node (like variable scoping): the host's own children\n * first, then its siblings, then each ancestor's scope up to the scene root. The FIRST segment\n * binds the scope; the remaining segments descend from there. Refs address def nodes only (no\n * `::`/`name[i]` asset-internal segments); an unknown path resolves to `null` (type your aspect\n * field `Node | null`). Scene files only — hand-written code passes nodes directly:\n * `node.aspect(Road, { from: nodes.pointA })`.\n */\nexport declare const ref: <T = Node>(path: string) => T;\nexport declare const isNodeRef: (v: unknown) => v is {\n $ref: string;\n};\n/** Resolve one ref string against a path-keyed nodes record, scoped upward from `hostPath` (own\n * children → parent's scope (siblings + the host itself) → each ancestor scope → root, `\"\"`).\n * The ref's FIRST segment binds the scope — a match there is final even when the rest of the\n * path doesn't exist (lexical shadowing). Returns the target's ABSOLUTE path, or null.\n * `Object.hasOwn`, not indexing: a node named `constructor` must not resolve via the prototype. */\nexport declare const resolveRefPath: (nodes: Record<string, unknown>, hostPath: string, ref: string) => string | null;\n/** Swap `ref()` markers in aspect props for the live nodes (top level + one array level deep),\n * resolved scoped-upward from `hostPath` (\"\" = root scope only — the 2D flat-map case). */\nexport declare const resolveRefs: <N>(props: Record<string, unknown> | undefined, nodes: Record<string, N>, hostPath?: string) => Record<string, unknown> | undefined;\n/** ABSOLUTE paths of the nodes a props record's ref() values resolve to (editor dep tracking).\n * An unresolved ref contributes no dep — the handle re-derives deps after structural changes. */\nexport declare const collectRefDeps: (props: Record<string, unknown>, nodes: Record<string, unknown>, hostPath: string) => Set<string>;\n/** The edit-mode flag an editor host sets before running the bundle (shared by both formats). */\nexport declare const EDIT_FLAG = \"__lecodesSceneEdit\";\nexport declare const isEditMode: () => boolean;\n","types/ui/fonts.d.ts":"type FontOptions = {\n weight?: number;\n style?: \"normal\" | \"italic\";\n};\n/** Register a font face from a URL at runtime under `fontFamily`; resolves once it's ready to\n * use in styles. For registry/project fonts prefer the compile-time `font()` macro — this is the\n * dynamic escape hatch. */\nexport declare function registerFont(fontFamily: string, url: string, options?: FontOptions): Promise<void>;\nexport {};\n","types/ui/NativeView.d.ts":"import { type PresentOptions } from \"./presentable\";\nimport { type BaseStyle, type DrawableStyle, type ElementStyle, type UIElementBase } from \"./UINode\";\nexport type UINativeViewStyle = ElementStyle & DrawableStyle;\n/** An instance of a host-registered platform view (map, QR scanner, camera preview, …) —\n * embeddable among a screen's children AND fullscreen-presentable (`open()`); one instance lives\n * in one place at a time. Talk to it via the `call`/`on` channel. */\nexport interface NativeView extends UIElementBase<UINativeViewStyle, DrawableStyle & BaseStyle> {\n readonly type: \"native\";\n /** The registered view kind this instance resolves to (the `registerView` name). */\n readonly viewName: string;\n /** Creation params, passed to the host factory (JSON-serializable). */\n readonly params: any;\n /** Show fullscreen as the current destination (see Presentable). */\n open(options?: PresentOptions): void;\n /** Dismiss if this is the visible destination. */\n close(): void;\n /** Became the visible destination. */\n onOpen(callback: () => void): this;\n /** Stopped being the visible destination. */\n onClose(callback: () => void): this;\n /** Hardware/system back while current. */\n onBackPressed(callback: () => void): this;\n /** Invoke a method on the native view (`map.call(\"setCenter\", [lng, lat])`). Args and the\n * result are JSON-serialized. Rejects if the host has no such view/method. */\n call(method: string, ...args: any[]): Promise<any>;\n /** Subscribe to an event the native view emits (`map.on(\"markerTap\", cb)`). */\n on(event: string, callback: (data?: any) => void): this;\n off(event: string, callback: (data?: any) => void): this;\n}\n/**\n * Create an instance of a host-registered platform view. `NativeView.isSupported(name)` reports\n * whether this host registered a factory for it. Style via the chained `.style()`.\n */\nexport declare const NativeView: {\n (name: string, params?: object): NativeView;\n /** Whether this host registered a `registerView` factory under `name`. */\n isSupported(name: string): boolean;\n};\n","types/ui/presentable.d.ts":"/** Built-in transition catalog. `push`/`pop` are the stacked-navigation pair (slide + parallax +\n * dim + edge shadow); the rest are simple two-view moves. */\nexport type TransitionName = \"push\" | \"pop\" | \"slide-from-left\" | \"slide-from-right\" | \"slide-from-top\" | \"slide-from-bottom\" | \"zoom\" | \"zoom-in\" | \"zoom-out\" | \"fade\" | \"none\";\n/** Start/end pose of one side of a custom transition. `x`/`y` are logical px, or a percentage of\n * the destination's size (e.g. `\"100%\"` = one full width to the right). */\nexport type TransitionTransform = {\n x?: number | `${number}%`;\n y?: number | `${number}%`;\n scale?: number;\n opacity?: number;\n};\n/**\n * A custom transition: declarative poses for the incoming/outgoing destination, played natively.\n * Serializes onto each platform's existing transition machinery — there is no per-frame JS.\n * Fields omitted keep the identity pose. Interactive back-swipe stays system-native (push/pop\n * only); a spec applies to non-interactive transitions.\n */\nexport interface TransitionSpec {\n /** Duration in ms (default 300). */\n duration?: number;\n /** cubic-bezier control points (default ease-out). */\n easing?: [number, number, number, number];\n /** The entering destination animates FROM this pose to identity. */\n incoming?: {\n from?: TransitionTransform;\n };\n /** The leaving destination animates from identity TO this pose. */\n outgoing?: {\n to?: TransitionTransform;\n };\n /** Scrim alpha (0..1) painted over whichever destination is underneath. */\n dim?: number;\n /** Which side stacks on top during the animation (default \"incoming\"). On Android, transitions\n * involving a scene always animate the screen side on top — the scene view itself never moves. */\n onTop?: \"incoming\" | \"outgoing\";\n}\nexport type Transition = TransitionName | TransitionSpec;\nexport type PresentOptions = {\n /** Transition to play while this destination replaces the current one (default \"none\" for a\n * direct open(); the Router applies its own defaults — push/pop, and the theme's\n * `replaceTransition` for replace). */\n transition?: Transition;\n};\n/**\n * Anything that can be shown as the app's current destination: a `UIScreen`, a `Scene` /\n * `ARScene`, a `Scene2D`, a `NativeView`, or a `UIVideo`. One Presentable is visible at a time;\n * open it directly (`p.open()` — replaces the current destination, suspending an active Router\n * until `Router.restore()`) or navigate with `Router.push/replace/pop`.\n *\n * `onOpen`/`onClose` are the presentation lifecycle (fired when the destination becomes / stops\n * being the visible one — including router pushes covering it and pops revealing it).\n */\nexport interface Presentable {\n open(options?: PresentOptions): void | this | Promise<void>;\n close(): void;\n onOpen(callback: () => void): this;\n onClose(callback: () => void): this;\n onBackPressed(callback: () => void): this;\n}\n/** Runtime companion of the `Presentable` interface (declaration merging): the navigation\n * state that isn't tied to the Router. */\nexport declare const Presentable: Readonly<{\n /** The destination visible right now (a `UIScreen`, `Scene`, `Scene2D`, `NativeView` or\n * `UIVideo`), or `null` before the first open. Distinct from `Router.current` — that is the\n * top of the router stack, which stays meaningful while the router is suspended by a direct\n * `open()`; this is what is actually on screen. `UIWidget.show()` attaches to it. */\n readonly current: Presentable | null;\n}>;\n","types/ui/router.d.ts":"import { Presentable, type Transition } from \"./presentable\";\ntype RouterOptions = {\n showDefaultBackButton?: boolean;\n};\ntype NavigateOptions = {\n /** Transition to play. Defaults: `\"push\"` for push, `\"pop\"` for pop; replace follows the\n * theme's `replaceTransition` (`\"none\"` out of the box). */\n transition?: Transition;\n};\n/** Stack navigation over `Presentable` destinations. `init` once with the home page, then\n * `push`/`replace`/`pop`; the back gesture/button pops natively. A direct `page.open()` suspends\n * the router until `restore()`. */\ntype Router = {\n /** The top of the router stack (not necessarily what's on screen — see `Presentable.current`). */\n get current(): Presentable;\n /** Mount the router with `homePage` as the stack root — the app's navigation entry point. */\n init(homePage: Presentable, opts?: RouterOptions): void;\n /** Push a destination onto the stack — a `UIScreen`, a `Scene`, a `Scene2D`, a `NativeView`,\n * or a `UIVideo`. The back gesture/button pops it. Destinations with async preparation\n * (`ARScene`: camera permission + warm render) return a Promise — the current page stays\n * visible until they're ready, and a rejection (permission denied / superseded) leaves the\n * stack untouched. */\n push(page: Presentable, opts?: NavigateOptions): void | Promise<void>;\n /** Swap the top of the stack for `page` — no back entry to the replaced one. */\n replace(page: Presentable, opts?: NavigateOptions): void | Promise<void>;\n /** Pop the top destination (the programmatic twin of the back gesture); `to` unwinds to a\n * stack index in one step. */\n pop(to?: number, opts?: NavigateOptions): void;\n /** Blank the router's page, keeping the stack — `restore()` brings it back. A destination\n * opened directly stays visible. */\n hide(): void;\n /** Re-present the stack top after `hide()` or a direct `open()` suspended the router. */\n restore(): void;\n /** `\"change\"` fires on every stack change — pushes, pops, and native back gestures — with the\n * new top destination. */\n addEventListener(channel: \"change\", callback: (page: Presentable) => void): void;\n removeEventListener(channel: \"change\", callback: (page: Presentable) => void): void;\n};\nexport declare const Router: Router;\nexport {};\n","types/ui/theme.d.ts":"import type { Transition } from \"./presentable\";\nexport type ThemeValues = Record<string, string | number | null>;\nexport type ThemeAccessors<T> = {\n readonly [K in keyof T]: K extends string ? `var(--${K})` : never;\n};\n/** App theme: callable to merge variables (`theme({...})` — re-calling re-styles the live UI, so\n * dark mode is just a second call), with the system vars as static properties\n * (`theme.primaryColor`, `theme[\"comfort-top\"]`, …). */\nexport declare const theme: (<T extends Record<string, string | number | Transition | null>>(values: T & { [K in Exclude<keyof T, \"replaceTransition\">]: string | number | null; }) => ThemeAccessors<Omit<T, \"replaceTransition\">>) & {\n /** The app accent color. Kit components will read it via `var(--primaryColor, <fallback>)`. */\n readonly primaryColor: \"var(--primaryColor)\";\n /** Secondary / inactive content color for kit components. */\n readonly mutedColor: \"var(--mutedColor)\";\n /** DEFAULT text color — text without an explicit `color` follows it (hosts source their\n * default from the theme; unset = the host default, white on dark screens). Set it once for\n * a light theme instead of `color: \"black\"` on every label. */\n readonly color: \"var(--color)\";\n /** DEFAULT text font — text without an explicit `fontFamily` follows it. */\n readonly fontFamily: \"var(--fontFamily)\";\n /** Raw comfort knobs (logical px). The bare `comfort-top` style TOKEN applies the safe-area\n * formula — these accessors read the knob value itself, for manual composition. */\n readonly \"comfort-top\": \"var(--comfort-top)\";\n readonly \"comfort-bottom\": \"var(--comfort-bottom)\";\n readonly \"comfort-left\": \"var(--comfort-left)\";\n readonly \"comfort-right\": \"var(--comfort-right)\";\n};\n","types/ui/UI.d.ts":"export { UIButton, type UIButtonStyle } from './UIButton';\nexport { UIScreen, type UIScreenStyle } from './UIScreen';\nexport { UISpacer, type UISpacerStyle } from './UISpacer';\nexport { UIText, type UITextStyle } from './UIText';\nexport { registerFont } from './fonts';\nexport { UIImage, type UIImageStyle } from './UIImage';\nexport { UIVideo, type UIVideoStyle } from './UIVideo';\nexport { UIInput, UITextArea, type UIInputStyle } from './UIInput';\nexport { UIWidget, type UIWidgetStyle } from './UIWidget';\nexport { UIModal, type UIModalStyle } from './UIModal';\nexport { UIBottomSheet, type UIBottomSheetStyle } from './UIBottomSheet';\nexport { UIPopover, type UIPopoverStyle, type UIPopoverAnchor } from './UIPopover';\nexport { UIRow, UIColumn, UIBox, type UIContainerStyle } from './UIContainer';\nexport { UIScrollable, type UIScrollableStyle } from './UIScrollable';\nexport { UIPager, type UIPagerStyle } from './UIPager';\nexport { UITabs, type UITabDef, defineTabs, type TabDef, type TabsHandle } from './UITabs';\nexport { UIVirtualizedList } from './UIVirtualizedList';\nexport { Router } from './router';\nexport { NativeView, type UINativeViewStyle } from './NativeView';\nexport { Presentable } from './presentable';\nexport type { PresentOptions, Transition, TransitionName, TransitionSpec, TransitionTransform } from './presentable';\nexport { __uiMap } from './UINode';\nexport { __UIColumn, __UIRow, __UIBox } from './UIContainer';\nexport { __UIButton } from './UIButton';\nexport { __UIScreen } from './UIScreen';\nexport { __UIScrollable } from './UIScrollable';\nexport { __UIWidget } from './UIWidget';\n","types/ui/UIBottomSheet.d.ts":"import { ModalElement, type UIModalStyle } from \"./UIModal\";\nimport type { UIWidget } from \"./UIWidget\";\nimport { type ChildrenFn, type UIChildArg, type UINodeChild } from \"./UINode\";\nexport type UIBottomSheetStyle = UIModalStyle;\n/**\n * A bottom sheet: a `UIWidget` pinned to the bottom edge. By default it is **content-sized** —\n * as tall as what's inside (capped at the screen), one position, drag down to dismiss (the\n * action-sheet shape). Call `detents()` for the multi-position map-app model instead: snap\n * positions the user drags between on native hosts. Ships as a widget node on the wire (no new\n * node type — docs/bottom-sheet-plan.md): hosts without sheet support show a static bottom panel.\n *\n * With detents, content lays out at the HIGHEST detent's size; lower detents show the top\n * slice. The scrim, `onOpen`/`onClose`, back-button and scrim-tap dismissal all come from the\n * modal machinery.\n *\n * ```ts\n * const actions = UIBottomSheet({ bgColor: \"#1c1c1e\", borderRadius: 16 }, [rows]) // content-sized\n *\n * const mapSheet = UIBottomSheet({ bgColor: \"#1c1c1e\", borderRadius: 16 }, [results])\n * .detents([0.3, 0.6, 1])\n * .onDetentChange(i => map.setPadding(...))\n * ```\n */\nexport interface UIBottomSheet extends UIWidget {\n /** Snap positions as fractions of screen height, ascending. Also sizes the sheet: its box is\n * the last (highest) detent; set this before `show()`. Without a `detents()` call the sheet\n * is CONTENT-SIZED instead — one position, as tall as its children (up to the screen). */\n detents(list: number[]): this;\n /** Snap to a detent (animated). Clamped to the detents range; fires `onDetentChange`. */\n setDetent(index: number): void;\n /** Current detent index. */\n readonly detent: number;\n /** Fires on every settle: a finger snap on native hosts, or a `setDetent()` call. */\n onDetentChange(callback: (index: number) => void): this;\n /** Mount and slide in to the current detent. No-op while already open. */\n show(): void;\n /** Slide out, fade the scrim, then unmount. No-op while closed. */\n hide(): void;\n /** True from `show()` until `hide()` starts. */\n readonly isOpen: boolean;\n /** Called when `show()` mounts the sheet. */\n onOpen(callback: () => void): this;\n /** Called when the sheet starts closing — scrim tap, back button, drag-dismiss, or `hide()`. */\n onClose(callback: () => void): this;\n /** `dismissible(false)`: scrim taps, the back button and dragging below the lowest detent no\n * longer close the sheet (a drag collapses to the lowest detent instead). Default `true`. */\n dismissible(enabled: boolean): this;\n}\nexport declare class BottomSheetElement extends ModalElement {\n _detents: number[];\n _detent: number;\n /** Host-facing (the `sl`/`otl` contract): hosts read `dtl` at mount and call it with the\n * settled detent index for GESTURE settles only — programmatic `setDetent` fires JS-side.\n * `-1` = dragged below the lowest detent while dismissible. */\n readonly dtl: any[];\n readonly _detentListeners: ((index: number) => void)[];\n constructor(style: UIBottomSheetStyle, children: UINodeChild[] | ChildrenFn);\n detents(list: number[]): this;\n get detent(): number;\n setDetent(index: number): void;\n onDetentChange(callback: (index: number) => void): this;\n show(): void;\n hide(): void;\n dismissible(enabled: boolean): this;\n}\n/** Create a bottom sheet (see {@link UIBottomSheet}) — content-sized by default; call\n * `.detents([...])` for snap positions. Same argument forms as `UIColumn`. */\nexport declare function UIBottomSheet(...children: UIChildArg[]): UIBottomSheet;\nexport declare function UIBottomSheet(children: UINodeChild[] | ChildrenFn): UIBottomSheet;\n/** @deprecated Style as the first argument is legacy — use chained `.style({...})`. */\nexport declare function UIBottomSheet(style: UIBottomSheetStyle, children?: UINodeChild[] | ChildrenFn): UIBottomSheet;\n","types/ui/UIButton.d.ts":"import type { ClickEvent as ClickEventType, TouchStartEvent as TouchStartEventType, LongPressEvent as LongPressEventType } from \"../runtime/touch\";\nimport { type ElementStyle, type ContainerStyle, type DrawableStyle, type UIChildArg, type UIContainerBase, type UINodeChild, type ChildrenFn, type BaseStyle, type Color } from \"./UINode\";\nexport type UIButtonStyle = ElementStyle & DrawableStyle & ContainerStyle & {\n rippleColor?: Color | \"default\";\n};\n/** A tappable container — row + centered children by default. Press feedback via the `onPressed`\n * style block, the `$pressed` class, or `rippleColor`. */\nexport interface UIButton extends UIContainerBase<UIButtonStyle & {\n onPressed?: UIButtonStyle & {\n duration?: number;\n };\n}, DrawableStyle & BaseStyle> {\n readonly type: \"button\";\n /** Fired on a completed tap/click. */\n onClick(callback: (ev: ClickEventType<UIButton>) => void): this;\n /** Fired when a touch begins; `ev.track(...)` takes over the rest of the gesture (dragging). */\n onTouchStart(callback: (ev: TouchStartEventType<UIButton>) => void): this;\n /** Fired when a finger is held on the button past the long-press threshold. The event can\n * `ev.track(...)` the rest of the gesture (like `onTouchStart`), so a hold can flow straight into\n * dragging the element. A handled long-press suppresses the click that would follow the release. */\n onLongPress(callback: (ev: LongPressEventType<UIButton>) => void): this;\n /** Is a finger currently down on the button? */\n isPressed(): boolean;\n}\n/** Create a button (row + centered by default — the icon+label shape). Same argument forms as\n * `UIColumn`; attach behavior with `.onClick(...)`. */\nexport declare function UIButton(...children: UIChildArg[]): UIButton;\nexport declare function UIButton(children: UINodeChild[] | ChildrenFn): UIButton;\n/** @deprecated Style as the first argument is legacy — use chained `.style({...})`. */\nexport declare function UIButton(style: UIButtonStyle, children?: UINodeChild[] | ChildrenFn): UIButton;\n","types/ui/UIContainer.d.ts":"import { type ChildrenFn, type ContainerStyle, type DrawableStyle, type ElementStyle, type UIChildArg, type UIContainerBase, type UINodeChild } from \"./UINode\";\nexport type UIContainerStyle = ElementStyle & DrawableStyle & ContainerStyle;\n/** A vertical flex container — children stack top to bottom. */\nexport interface UIColumn extends UIContainerBase<UIContainerStyle> {\n readonly type: \"column\";\n}\nexport declare const __UIRow: (children: UINodeChild[] | ChildrenFn) => UIRow;\nexport declare const __UIBox: (children: UINodeChild[] | ChildrenFn) => UIBox;\n/** Create a vertical flex container. Children are variadic — arrays flatten one level, falsy\n * entries are skipped; a lone function makes the children reactive. */\nexport declare function UIColumn(...children: UIChildArg[]): UIColumn;\nexport declare function UIColumn(children: UINodeChild[] | ChildrenFn): UIColumn;\n/** @deprecated Style as the first argument is legacy — use chained `.style({...})`. */\nexport declare function UIColumn(style: UIContainerStyle, children?: UINodeChild[] | ChildrenFn): UIColumn;\n/** A horizontal flex container — children flow left to right. */\nexport interface UIRow extends UIContainerBase<UIContainerStyle> {\n readonly type: \"row\";\n}\n/** Create a horizontal flex container (same argument forms as `UIColumn`). */\nexport declare function UIRow(...children: UIChildArg[]): UIRow;\nexport declare function UIRow(children: UINodeChild[] | ChildrenFn): UIRow;\n/** @deprecated Style as the first argument is legacy — use chained `.style({...})`. */\nexport declare function UIRow(style: UIContainerStyle, children?: UINodeChild[] | ChildrenFn): UIRow;\n/** A centering container — `justifyContent`/`alignItems` default to center. */\nexport interface UIBox extends UIContainerBase<UIContainerStyle> {\n readonly type: \"box\";\n}\n/** Create a centering container — children are centered on both axes by default (icon badges,\n * avatars, empty states). Same argument forms as `UIColumn`. */\nexport declare function UIBox(...children: UIChildArg[]): UIBox;\nexport declare function UIBox(children: UINodeChild[] | ChildrenFn): UIBox;\n/** @deprecated Style as the first argument is legacy — use chained `.style({...})`. */\nexport declare function UIBox(style: UIContainerStyle, children?: UINodeChild[] | ChildrenFn): UIBox;\n","types/ui/UIImage.d.ts":"import type { FetchResponse } from \"../runtime/fetch\";\nimport type { SvgSourceValue as SvgSource } from \"../runtime/misc\";\nimport type { File } from \"../runtime/fetch\";\nimport { Canvas } from \"../canvas/Canvas\";\nimport { type Color, type ElementStyle, type UIElementBase } from \"./UINode\";\nexport type UIImageStyle = ElementStyle & {\n borderRadius?: number;\n objectFit?: \"cover\" | \"contain\" | \"fill\";\n tintColor?: Color;\n};\n/** A baked Canvas surface as an image source. The UI backend resolves it to a UI texture — see\n * docs/canvas-contract.md (\"Pending\"). */\nexport type CanvasImageSource = {\n canvasSurface: number;\n};\n/** Accepted image sources. A Canvas is baked to a surface marker on assign. */\nexport type ImageSource = string | FetchResponse | File | SvgSource | Canvas;\n/** The stored/resolved image source (a Canvas is resolved to a surface marker). */\nexport type ResolvedImageSource = string | FetchResponse | File | SvgSource | CanvasImageSource;\n/** An image element. Sources: URL / `asset(...)`, fetch response / File, an SVG source\n * (`assetIcon`), or a live Canvas (`canvas.update()` refreshes the node in place). */\nexport interface UIImage extends UIElementBase<UIImageStyle> {\n readonly type: \"image\";\n /** The image source — writable to swap the picture in place. */\n get src(): ResolvedImageSource;\n set src(value: ImageSource);\n /** Render only a sub-rectangle of the source texture (texture pixels) — the atlas/spritesheet\n * primitive: crop once, then swap the rect per frame for sprite animation. The rect's w/h\n * become the node's intrinsic size and override `objectFit` — the cropped frame fills the box. */\n setSourceRect(x: number, y: number, w: number, h: number): this;\n}\n/** Create an image element from a source (see {@link ImageSource}). */\nexport declare function UIImage(src: ImageSource): UIImage;\n/** @deprecated Style as the first argument is legacy — use chained `.style({...})`. */\nexport declare function UIImage(style: UIImageStyle, src: ImageSource): UIImage;\n","types/ui/UIInput.d.ts":"import { type ElementStyle, type DrawableStyle, type TextStyle, type Color, type BaseStyle, type UIElementBase } from \"./UINode\";\ntype InputStyle = {\n placeholder?: string;\n placeholderColor?: Color;\n /**\n * Keyboard hint, NOT a validator — `number` does not block pasted letters; validate in your own\n * onChange. The phone-pad value is `phone` (LeCodes has no `tel`).\n *\n * `date` / `time` are PICKER kinds, not keyboards: the host opens its native picker in the\n * keyboard slot (iOS wheels / browser calendar) and free typing is disabled. `value` is always\n * canonical — `YYYY-MM-DD` for `date`, `HH:MM` (24h) for `time` — while the field displays a\n * localized string; set/compare values in the canonical form only.\n */\n type?: \"text\" | \"password\" | \"search\" | \"phone\" | \"email\" | \"number\" | \"decimal\" | \"url\" | \"date\" | \"time\";\n /**\n * What the layout does while the keyboard is up (decided by the FOCUSED input). `true` (default):\n * the layout viewport shrinks to the area above the keyboard — one relayout. `false`: the keyboard\n * overlays the UI with NO layout recalculation — for chat composers that manage their own inset\n * (pair with `app.keyboardHeight` / the app `\"keyboard\"` event) and full-screen canvases where a\n * reflow is worse than overlap.\n */\n keyboardShrink?: boolean;\n /**\n * Whether a tap on a non-interactive area dismisses the keyboard while THIS input is focused\n * (like `keyboardShrink`, the policy of the focused input). `true` (default): tapping dead\n * space blurs — but a tap on a button or another input NEVER dismisses; the control acts and\n * focus stays. `false`: taps never dismiss — the chat-composer policy. `blur()`, the return\n * key (per `enterKey`), and the platform's own gestures (iOS drag-down over the keyboard)\n * still work in both modes. Scrolling never dismisses the keyboard on any setting.\n */\n keyboardDismiss?: boolean;\n /** Hard cap on the text length — enforced by the host while typing/pasting. */\n maxLength?: number;\n /** Auto-capitalization hint; omitted = platform default. */\n autocapitalize?: \"none\" | \"words\" | \"sentences\" | \"characters\";\n /** Enable/disable the platform autocorrection & suggestions; omitted = platform default. */\n autocorrect?: boolean;\n};\nexport type UIInputStyle = ElementStyle & DrawableStyle & TextStyle & InputStyle;\n/** UIInput-only (a UITextArea's Enter is a newline, period): the return-key label. */\ntype SubmitStyle = {\n /**\n * Return-key label. On submit the keyboard dismisses UNLESS `enterKey` is `\"next\"` — then the\n * app is expected to call `otherInput.focus()` from `onSubmit`, so the keyboard never blinks.\n */\n enterKey?: \"done\" | \"go\" | \"next\" | \"search\" | \"send\";\n};\n/** A single-line text input. Keyboard/picker kind via the `type` style, return-key behavior via\n * `enterKey` + `onSubmit`; keyboard policy on `keyboardShrink`/`keyboardDismiss`. */\nexport interface UIInput extends UIElementBase<UIInputStyle & SubmitStyle & {\n onFocused?: UIInputStyle & {\n duration?: number;\n };\n}, DrawableStyle & BaseStyle> {\n readonly type: \"input\";\n /**\n * The field's text. Writable at any time — set it BEFORE the screen opens to pre-fill a form\n * (settings, edit-profile); the value is stashed on the node and applied when the host builds\n * it. Reads return the live text while the screen is open, and the last value you set while it\n * isn't. The user's typing is not preserved across close/open (use `keepAlive()` for that).\n */\n value: string;\n /** The text changed — fires on every user edit. */\n onChange(callback: (value: string) => void): UIInput;\n /** Gained focus (keyboard opens). */\n onFocus(callback: () => void): UIInput;\n /** Lost focus. */\n onBlur(callback: () => void): UIInput;\n /** The keyboard's return key was pressed. `value` is the current text. See `enterKey`. */\n onSubmit(callback: (value: string) => void): UIInput;\n /** Focus the input (opens the keyboard). No-op before mount. */\n focus(): void;\n /** Release focus (dismisses the keyboard when this input held it). */\n blur(): void;\n}\n/** A multi-line text field — see the {@link UITextArea} factory for the auto-grow contract. */\nexport interface UITextArea extends UIElementBase<UIInputStyle & {\n onFocused?: UIInputStyle & {\n duration?: number;\n };\n}, DrawableStyle & BaseStyle> {\n readonly type: \"textarea\";\n /** The field's text — same contract as {@link UIInput.value}: settable before mount to pre-fill. */\n value: string;\n /** The text changed — fires on every user edit. */\n onChange(callback: (value: string) => void): UITextArea;\n /** Gained focus (keyboard opens). */\n onFocus(callback: () => void): UITextArea;\n /** Lost focus. */\n onBlur(callback: () => void): UITextArea;\n /** Focus the text area (opens the keyboard). No-op before mount. */\n focus(): void;\n /** Release focus (dismisses the keyboard when this text area held it). */\n blur(): void;\n}\n/** Create a single-line text input. Read/write the text via `.value`, listen with\n * `onChange`/`onSubmit`; style keys `placeholder`, `type`, `enterKey`, … configure it. */\nexport declare function UIInput(): UIInput;\nexport declare function UIInput(style: UIInputStyle): UIInput;\n/**\n * Multi-line text field. Enter is a newline (submit lives on UIInput / your own button).\n *\n * Auto-grow: with no explicit `height` the field measures its own content and grows line by\n * line — clamp the range with `minHeight` / `maxHeight` (past `maxHeight` the text scrolls\n * inside). A fixed `height` opts out and scrolls internally from the start. Chat composers are\n * the canonical use: a bare textarea in a padded pill, `maxHeight` at ~5 lines.\n */\nexport declare function UITextArea(): UITextArea;\nexport declare function UITextArea(style: UIInputStyle): UITextArea;\nexport {};\n","types/ui/UIModal.d.ts":"import { type UIWidget, type UIWidgetStyle, WidgetElement } from \"./UIWidget\";\nimport { type BaseStyle, type ChildrenFn, type Color, type DrawableStyle, type UIChildArg, type UINodeChild } from \"./UINode\";\nexport type UIModalStyle = UIWidgetStyle;\n/**\n * The modal's hidden pose: `show()` animates from it, `hide()` animates to it. `duration` (ms)\n * applies to both directions.\n */\nexport type UIModalTransition = DrawableStyle & BaseStyle & {\n overlayColor?: Color | null;\n duration?: number;\n};\n/**\n * A dialog: a `UIWidget` with the modal boilerplate built in. Comes with a scrim\n * (`overlayColor: \"rgba(0, 0, 0, 0.5)\"` unless overridden), animates on `show()`/`hide()`\n * (a 200 ms fade by default — swap the pose via `transition()`; the exit plays with\n * `commit: false`, so the style is intact for the next show), and closes itself on a scrim tap\n * or the Android back button (disable via `dismissible(false)`). Everything else is a plain\n * widget — same styling, children, touch and `attachTo()` surface; create it **once** at module\n * scope and reuse it.\n */\nexport interface UIModal extends UIWidget {\n /** Mount as an overlay and play the entrance transition. No-op while already open. */\n show(): void;\n /** Play the exit transition, then unmount. No-op while closed or already closing. */\n hide(): void;\n /** True from `show()` until `hide()` starts (already false during the exit animation). */\n readonly isOpen: boolean;\n /**\n * Replace the show/hide animation. `hidden` is the off-screen pose — `show()` animates from\n * it, `hide()` animates to it. Default `{ opacity: 0, duration: 200 }` (a fade); the pose\n * replaces it wholesale, so a slide without a fade is just the slide. The scrim keeps its own\n * fade unless the pose sets `overlayColor` itself.\n *\n * ```ts\n * sheet.transition({ transform: \"translateY(480px)\", duration: 250 }) // bottom sheet\n * ```\n */\n transition(hidden: UIModalTransition): this;\n /** Called when `show()` mounts the modal. */\n onOpen(callback: () => void): this;\n /** Called when the modal starts closing — scrim tap, back button, or a `hide()` call. */\n onClose(callback: () => void): this;\n /** `dismissible(false)` keeps scrim taps and the back button from closing the modal\n * (forced-choice dialogs). Default `true`. */\n dismissible(enabled: boolean): this;\n}\nexport declare class ModalElement extends WidgetElement {\n _open: boolean;\n _dismissible: boolean;\n _transition: UIModalTransition;\n _closeTimer?: ReturnType<typeof setTimeout>;\n readonly _openListeners: (() => void)[];\n readonly _closeListeners: (() => void)[];\n constructor(style: UIModalStyle, children: UINodeChild[] | ChildrenFn);\n private _pose;\n private get _duration();\n transition(hidden: UIModalTransition): this;\n show(): void;\n hide(): void;\n get isOpen(): boolean;\n onOpen(callback: () => void): this;\n onClose(callback: () => void): this;\n dismissible(enabled: boolean): this;\n}\n/** Create a modal dialog (see {@link UIModal}) — create once at module scope, then\n * `show()`/`hide()`. Same argument forms as `UIColumn`. */\nexport declare function UIModal(...children: UIChildArg[]): UIModal;\nexport declare function UIModal(children: UINodeChild[] | ChildrenFn): UIModal;\n/** @deprecated Style as the first argument is legacy — use chained `.style({...})`. */\nexport declare function UIModal(style: UIModalStyle, children?: UINodeChild[] | ChildrenFn): UIModal;\n","types/ui/UINode.d.ts":"import type { FetchResponse } from \"../runtime/fetch\";\nexport interface UINode {\n readonly type: string;\n /** Author-given semantic name (a stable selector for tests + AI review feedback). */\n readonly name?: string;\n style: Style<this, any>;\n /** Style-class proxy — read/set/toggle/bind the `$`-classes declared in `.style()`. See {@link Classes}. */\n readonly class: Classes<this>;\n}\n/** A child slot value: a node, or falsy (conditional rendering — falsy entries are skipped). */\nexport type UINodeChild = UINode | null | undefined | false;\n/** A factory child argument: a node (or falsy for conditionals), or an array of them — arrays are\n * flattened one level at the argument position, so `UIColumn(header, items.map(row), footer)`\n * needs no spread. */\nexport type UIChildArg = UINodeChild | UINodeChild[];\n/** A color: CSS-style string (`\"#1c1c1e\"`, `\"rgba(0,0,0,0.5)\"`, `\"var(--primaryColor)\"`) or\n * packed number; `null` clears. */\nexport type Color = number | string | null;\n/** Style props every element accepts. */\nexport type BaseStyle = {\n opacity?: number | `${number}`;\n transform?: string | null;\n backgroundColor?: Color | null;\n bgColor?: Color | null;\n overflow?: \"visible\" | \"hidden\";\n boxSizing?: \"border-box\" | \"content-box\";\n /**\n * Author-given semantic name — a stable selector for tests and for marking elements in the AI\n * code-review feedback loop. NOT a style: it's extracted at construction (never sent to the layout\n * engine) and surfaced on the node + in the renderer's serialized output. Available on every element.\n */\n name?: string;\n};\n/** Painted-box props: background, gradient, border, radius. */\nexport type DrawableStyle = {\n backgroundImage?: FetchResponse | File | string | null;\n bgGradient?: string;\n backgroundGradient?: string;\n bgImage?: FetchResponse | File | string | null;\n backgroundSize?: \"cover\" | \"contain\" | \"tile\";\n bgSize?: \"cover\" | \"contain\" | \"tile\";\n border?: string | number | null;\n borderWidth?: number;\n borderColor?: Color;\n borderLeft?: string | number | null;\n borderLeftWidth?: number;\n borderLeftColor?: Color;\n borderTop?: string | number | null;\n borderTopWidth?: number;\n borderTopColor?: Color;\n borderRight?: string | number | null;\n borderRightWidth?: number;\n borderRightColor?: Color;\n borderBottom?: string | number | null;\n borderBottomWidth?: number;\n borderBottomColor?: Color;\n borderRadius?: UIValue | string;\n borderTopLeftRadius?: UIValue;\n borderTopRightRadius?: UIValue;\n borderBottomLeftRadius?: UIValue;\n borderBottomRightRadius?: UIValue;\n pointerEvents?: \"all\" | \"none\";\n};\n/** Flex-layout props of a container (how it lays out its children). */\nexport type ContainerStyle = {\n flexDirection?: \"row\" | \"column\";\n justifyContent?: \"flex-start\" | \"center\" | \"flex-end\" | \"space-between\" | \"space-evenly\";\n alignItems?: \"flex-start\" | \"center\" | \"flex-end\" | \"stretch\";\n gap?: UIValue;\n flexWrap?: \"nowrap\" | \"wrap\" | \"wrap-reverse\";\n};\n/** A dimension: a number (logical px) or a CSS-style unit / function string. */\ntype UIValue = number | `${number}px` | `${number}vw` | `${number}vh` | `${number}vmin` | `${number}vmax` | `${number}em` | `calc(${string})` | `min(${string})` | `max(${string})` | `${string}%` | `clamp(${string})` | `var(--${string})`;\n/** Padding, with `p`/`px`/`pl`… shorthands. `safe-*` insets by the device safe area,\n * `comfort-*` by the theme's comfort knobs (max of both). */\nexport type PaddingStyle = {\n paddingLeft?: UIValue | \"safe-left\" | \"comfort-left\";\n paddingTop?: UIValue | \"safe-top\" | \"comfort-top\";\n paddingRight?: UIValue | \"safe-right\" | \"comfort-right\";\n paddingBottom?: UIValue | \"safe-bottom\" | \"comfort-bottom\";\n padding?: UIValue | \"safe-all\" | \"comfort-all\";\n paddingHorizontal?: UIValue | \"comfort-x\";\n paddingVertical?: UIValue | \"comfort-y\";\n pl?: UIValue | \"safe-left\" | \"comfort-left\";\n pt?: UIValue | \"safe-top\" | \"comfort-top\";\n pr?: UIValue | \"safe-right\" | \"comfort-right\";\n pb?: UIValue | \"safe-bottom\" | \"comfort-bottom\";\n p?: UIValue | \"safe-all\" | \"comfort-all\";\n px?: UIValue | \"comfort-x\";\n py?: UIValue | \"comfort-y\";\n};\n/** Margin, with `m`/`mx`/`ml`… shorthands; `\"auto\"` centers/pushes like CSS. */\nexport type MarginStyle = {\n marginLeft?: UIValue | \"auto\" | \"safe-left\" | \"comfort-left\";\n marginTop?: UIValue | \"auto\" | \"safe-top\" | \"comfort-top\";\n marginRight?: UIValue | \"auto\" | \"safe-right\" | \"comfort-right\";\n marginBottom?: UIValue | \"auto\" | \"safe-bottom\" | \"comfort-bottom\";\n margin?: UIValue | \"auto\" | \"safe-all\" | \"comfort-all\";\n marginHorizontal?: UIValue | \"auto\" | \"comfort-x\";\n marginVertical?: UIValue | \"auto\" | \"comfort-y\";\n ml?: UIValue | \"auto\" | \"safe-left\" | \"comfort-left\";\n mt?: UIValue | \"auto\" | \"safe-top\" | \"comfort-top\";\n mr?: UIValue | \"auto\" | \"safe-right\" | \"comfort-right\";\n mb?: UIValue | \"auto\" | \"safe-bottom\" | \"comfort-bottom\";\n m?: UIValue | \"auto\" | \"safe-all\" | \"comfort-all\";\n mx?: UIValue | \"auto\" | \"comfort-x\";\n my?: UIValue | \"auto\" | \"comfort-y\";\n};\n/** Box position (for `position: \"absolute\"`) and size constraints. */\nexport type PositionStyle = {\n top?: UIValue | `${number}%` | 'safe-top' | 'comfort-top';\n left?: UIValue | `${number}%` | 'safe-left' | 'comfort-left';\n bottom?: UIValue | `${number}%` | 'safe-bottom' | 'comfort-bottom';\n right?: UIValue | `${number}%` | 'safe-right' | 'comfort-right';\n /** Shorthand for all four edges at one value. A longhand (`top`, `left`, …) overrides it. */\n inset?: UIValue | `${number}%` | \"auto\";\n width?: UIValue | `${number}%` | \"auto\";\n height?: UIValue | `${number}%` | \"auto\";\n maxWidth?: UIValue | `${number}%` | \"auto\";\n maxHeight?: UIValue | `${number}%` | \"auto\";\n minWidth?: UIValue | `${number}%` | \"auto\";\n minHeight?: UIValue | `${number}%` | \"auto\";\n};\n/** The base style of every element: box + flex-child props. */\nexport type ElementStyle = PaddingStyle & MarginStyle & BaseStyle & PositionStyle & {\n position?: \"absolute\" | \"static\" | \"relative\";\n aspectRatio?: number;\n flex?: number | string;\n flexGrow?: number;\n flexShrink?: number;\n flexBase?: UIValue | `${number}%` | \"auto\";\n alignSelf?: \"flex-start\" | \"center\" | \"flex-end\" | \"stretch\";\n display?: \"none\" | \"flex\";\n};\n/** Typography props. */\nexport type TextStyle = {\n textAlign?: \"start\" | \"center\" | \"end\" | \"left\" | \"right\";\n fontFamily?: string;\n fontSize?: UIValue;\n lineHeight?: UIValue | \"normal\";\n fontWeight?: number | `${number}` | \"normal\" | \"bold\";\n fontStyle?: \"normal\" | \"italic\";\n color?: Color;\n textDecoration?: \"underline\" | \"line-through\" | \"none\";\n letterSpacing?: UIValue;\n /** Cap the text at N lines; the box is measured to the clamped height. 0 / omitted = unbounded. */\n lineClamp?: number;\n /** How a clamped line ends. Only meaningful together with `lineClamp`. Default \"ellipsis\". */\n textOverflow?: \"ellipsis\" | \"clip\";\n};\n/** Reactive style input: every primitive-valued prop also accepts a `() => value` binding that\n * re-applies when a signal it read changes. Nested state blocks (onPressed, onLandscape, …) stay\n * static — bindings are extracted at the top level only. */\nexport type Reactive<T> = {\n [K in keyof T]: NonNullable<T[K]> extends object ? T[K] : T[K] | (() => T[K]);\n};\n/** User-defined style classes: any `$`-prefixed key in `.style()` declares a state block toggled\n * from code via the `el.class` proxy; `duration`/`delay` animate the swap. Class state INHERITS\n * down the tree (CSS-`.dark`-on-body style): a class set on a node also activates same-name `$`\n * blocks on all descendants within the same root (docs/style-class-cascade-plan.md).\n * `$pressed`/`$focused` are reserved — hosts toggle them on press/focus (they beat other\n * classes, lose to onPressed/onFocused), so children can react to an ancestor's press.\n *\n * Instantiated with the node's FULL style `T` — a class block accepts everything the node's\n * `.style()` does, like `onLandscape`. Narrowing it wrongly rejects valid props such as\n * `$active: { color }`; guarded by tests/ui-types.test.ts. */\nexport type ClassStyles<T> = {\n [key: `$${string}`]: T & {\n duration?: number;\n delay?: number;\n };\n};\n/** Value accepted by a `el.class` write: a boolean sets the class, a `() => boolean` binds it —\n * the class then tracks the signals the function reads (re-evaluated on change). Reads through\n * the proxy always return a plain boolean, never the bound function. */\nexport type ClassValue = boolean | (() => boolean);\n/** The `el.class` proxy — the runtime switch for `$`-class blocks declared in `.style()`\n * (see {@link ClassStyles}). One surface, mirroring `el.style`:\n *\n * ```ts\n * el.class.checked // read: is it active on THIS element? → boolean\n * el.class.checked = true // activate (false deactivates)\n * el.class.open = !el.class.open // toggle\n * el.class.done = () => todo.done.value // reactive binding (signals)\n * el.class({ checked: true, done: () => … }) // batch form — returns the element, chainable\n * ```\n *\n * Class names are accepted with or without the declaration-site `$` prefix. `R` is the concrete\n * node type, so the batch form chains like `.style()`.\n *\n * Typing note: property access is `any` because an index signature can't give reads (`boolean`)\n * and writes ({@link ClassValue}) different types — the batch form is the fully typed path;\n * single-key writes are runtime-coerced with `!!`. */\nexport type Classes<R> = ((classes: Record<string, ClassValue>) => R) & {\n [key: string]: any;\n};\n/** Members every UI element shares — element interfaces extend this so docs and types live in one\n * place. `S` is the element's style object; `A` is the subset `animateTo` accepts (defaults to `S`). */\nexport interface UIElementBase<S extends object, A extends object = S> {\n /** Style: `.style({...})` merges (chainable); `el.style.key = v` writes one prop, a `() => v`\n * value binds it to signals — see {@link Style}. */\n style: Style<this, S>;\n /** Tween to the target style — meta keys `duration`/`delay`/`loop`/…, see {@link AnimateStyle}. */\n animateTo: AnimateStyle<this, A>;\n /** Tween from the given style to the current one (entrance animations). */\n animateFrom: AnimateStyle<this, A>;\n /** Fires after every layout pass with the parent-relative box. */\n onLayout(onLayout: OnLayoutCallback): this;\n /** Absolute rect in device space, read live (includes scroll); `null` before mount. */\n getBoundingClientRect(): BoundingClientRect | null;\n /** Style-class proxy — read `el.class.checked`, set `el.class.checked = true`, toggle with\n * `!el.class.checked`, bind `el.class.done = () => sig.value`, batch/chain `el.class({ … })`.\n * Classes cascade to descendants. See {@link Classes}. */\n readonly class: Classes<this>;\n}\n/** {@link UIElementBase} plus the child-management surface every container shares. */\nexport interface UIContainerBase<S extends object, A extends object = S> extends UIElementBase<S, A> {\n /** Append children. */\n append(...nodes: UINodeChild[]): this;\n /** Insert children at `index`. */\n insert(index: number, ...nodes: UINodeChild[]): this;\n /** Remove (unmount) the given children. */\n remove(...nodes: UINodeChild[]): this;\n /** Replace all children — an array, or a function for reactive children. */\n setContent(nodes: UINodeChild[] | ChildrenFn): this;\n /** The children array — mutate via `append`/`insert`/`remove`/`setContent`. */\n readonly children: UINodeChild[];\n}\n/** Orientation state blocks — override props applied only in landscape / portrait (like a\n * `$`-class, keyed by device orientation instead of `el.class`). Same full-`T` rule as class\n * blocks. */\nexport type OrientationStyles<T> = {\n onLandscape?: T;\n onPortrait?: T;\n /** @deprecated Misspelling of `onPortrait` (no second \"r\"). Kept so existing projects and published\n * bundles keep working — hosts still honour it — but new code should use `onPortrait`. */\n onPortait?: T;\n};\nexport type StyleFn<R, T extends object> = ((style: Reactive<T> & OrientationStyles<T> & ClassStyles<T>) => R);\n/** The `el.style` surface: callable — `.style({...})` merges and returns the element for\n * chaining — and per-key readable/writable (`el.style.opacity = 0.5`; a `() => value` write\n * installs a reactive binding). */\nexport type Style<R, T extends object> = StyleFn<R, T> & T & OrientationStyles<T> & ClassStyles<T>;\n/** The `animateTo`/`animateFrom` surface: target style props plus the flat meta keys below\n * (stripped before the commit into the element's style). */\nexport type AnimateStyle<R, T extends object> = ((style: T & {\n /** Tween length in **milliseconds** (default 225). */\n duration?: number;\n /** Wait before starting, in **milliseconds**. A looping animation delays once, not per cycle. */\n delay?: number;\n /** Escape hatch: target an internal style layer (the onPressed/orientation mechanism). Not part of the supported surface. */\n layer?: number;\n /** `false` = animate without writing the targets into the element's style (e.g. a fade-out right before `.hide()`). */\n commit?: boolean;\n /** Repeat the animation: `true` = forever, a number = that many cycles. A looping animation is an\n * effect, not a state change — it never commits, and the element ends back at its base style.\n * The loop stops when a later `animateTo`/`animateFrom` runs on the element or it leaves the screen. */\n loop?: boolean | number;\n /** `\"ping-pong\"` (default) animates there and back each cycle — no jump. `\"restart\"` snaps back and\n * replays forward — for full-turn spinners (`transform: \"rotate(360deg)\"`) and shimmers. Only meaningful with `loop`. */\n loopMode?: \"restart\" | \"ping-pong\";\n}) => R);\nexport type AppearStyle<R, T> = (arg: {\n from: T;\n duration?: number;\n delay?: number;\n}) => R;\nexport type DisappearStyle<R, T> = (arg: {\n to: T;\n duration?: number;\n delay?: number;\n}) => R;\n/** `onLayout` payload — the node's box in PARENT-relative coordinates. */\nexport type OnLayoutCallback = (layout: {\n left: number;\n top: number;\n width: number;\n height: number;\n}) => void;\n/** Web-DOMRect shape on purpose (getBoundingClientRect priors must hold): all eight fields, with\n * right/bottom/x/y derived SDK-side — hosts only report [left, top, width, height]. */\nexport type BoundingClientRect = {\n x: number;\n y: number;\n left: number;\n top: number;\n right: number;\n bottom: number;\n width: number;\n height: number;\n};\nexport declare class Element<T extends string> {\n readonly type: T;\n /** Author-given semantic name (LeCodes `name`) — see BaseStyle.name. Extracted from the options\n * object so it never reaches the layout engine; the renderer reads it off the node. */\n readonly name?: string;\n protected _style: any;\n protected _id: number;\n protected _styleProxy: any;\n protected _appear: any;\n protected _disappear: any;\n constructor(type: T, style: any);\n get style(): any;\n /** Tween to the target style and commit it (unless `commit: false` or looping — a loop is an\n * effect, not a state change). Meta keys: `duration`/`delay`/`loop`/… — see {@link AnimateStyle}. */\n animateTo(style: any): this;\n /** Tween FROM the given style to the element's current one (entrance animations). */\n animateFrom(style: any): this;\n protected _classProxy?: any;\n /** Style-class control — flips the `$`-class blocks declared in `.style()`. One proxy, same\n * contract as `el.style`:\n *\n * - `el.class.checked` — read: is the class active on THIS element? → `boolean`\n * - `el.class.checked = true` / `= false` — activate / deactivate\n * - `el.class.open = !el.class.open` — toggle\n * - `el.class.done = () => todo.done.value` — reactive: the class tracks the signals the\n * function reads; a later write to the same class (plain or function) replaces the binding\n * - `el.class({ checked: true, done: () => … })` — batch form, returns the element (chainable)\n *\n * Names are accepted with or without the leading `$`. A class set on an element CASCADES: it is\n * also active on every descendant (their same-name `$` blocks light up), until the subtree's\n * root — hosted screens/widgets don't inherit. Reads reflect only this element's own classes;\n * there is no opt-out below an active ancestor. `Object.keys(el.class)` lists the active names. */\n get class(): any;\n protected ll?: OnLayoutCallback[];\n /** Observe layout: fires after every host layout pass with the parent-relative box. */\n onLayout(onLayout: OnLayoutCallback): this;\n /** Absolute rect in device space — the space `UIWidget` positions in and touch events report\n * `clientX`/`clientY` in — including scroll offsets, read live at call time (unlike `onLayout`,\n * whose coordinates are parent-relative and go stale when an ancestor scrolls). `null` before\n * the element is mounted and on hosts without the bridge read. Anchor popovers position-once\n * at open; don't poll per frame. */\n getBoundingClientRect(): BoundingClientRect | null;\n}\n/** Reactive children: re-runs when a signal it read changes; the result is reconciled against\n * the mounted children (kept nodes stay mounted, state intact). */\nexport type ChildrenFn = () => UINodeChild[];\n/**\n * Compiler-emitted memoized map for reactive children. The chisel `reactiveUi` pass rewrites\n * `list.map(fn)` inside a children binding to `__uiMap(list, fn, \"<file>:<offset>\")`, so unchanged\n * items keep their element identity across re-runs (the reconciler then leaves them mounted).\n * Cache: per (binding owner, call-site slot), keyed by item reference; duplicate items consume\n * cached nodes in order. Outside a children binding, for non-array inputs, or for non-element\n * results it behaves exactly like Array.prototype.map — a wrong rewrite can't change behavior.\n */\nexport declare function __uiMap(list: any, render: (item: any, index: number) => any, slot: string): any[];\nexport declare class ContainerElement<T extends string> extends Element<T> {\n children: any[];\n constructor(type: T, style: any, children: any[] | ChildrenFn);\n /** Append children (falsy entries are kept in the array but never mounted). */\n append(...nodes: UINodeChild[]): this;\n /** Insert children at `index` of the children array. */\n insert(index: number, ...nodes: UINodeChild[]): this;\n /** Remove (unmount) the given children. */\n remove(...nodesToDelete: UINode[]): this;\n /** Replace all children — a plain array, or a function for reactive children. */\n setContent(children: UINodeChild[] | ChildrenFn): this;\n}\nexport {};\n","types/ui/UIPager.d.ts":"import { ContainerElement, type BaseStyle, type ChildrenFn, type DrawableStyle, type ElementStyle, type UIElementBase, type UINodeChild } from \"./UINode\";\nimport type { UIScreen } from \"./UIScreen\";\n/** Styles a pager accepts — layout box + drawable (background, borders, …). Pages style\n * themselves; the pager only owns its own slot. */\nexport type UIPagerStyle = ElementStyle & DrawableStyle;\n/**\n * The screen-navigation element: sibling **tabs** that swipe natively side to side, each with its\n * own navigation **stack**. `push` opens a screen on top of the current tab (within the pager);\n * `pop` / the native edge back-swipe unwinds it. A one-tab pager is a plain navigation stack.\n *\n * ```ts\n * const pager = UIPager([ HomeScreen(), ProfileScreen() ]) // two tabs, side by side\n * Router.init(UIScreen([ pager.style({ flexGrow: 1 }), tabBar ]))\n *\n * // from anywhere inside a hosted screen — no reference threading:\n * UIPager.push(PostScreen(id))\n * ```\n *\n * To open something over *everything* (above bars, above the pager), use `Router.push` instead.\n */\nexport interface UIPager extends UIElementBase<UIPagerStyle, DrawableStyle & BaseStyle> {\n readonly type: \"pager\";\n /** Replace the pager's tabs — one screen per tab, in order. Every tab becomes a fresh\n * one-screen stack (pushed screens are dropped) and the selection is clamped into range;\n * screens that were already tabs keep their state. Pass a function for reactive tabs. */\n setContent(tabs: UIScreen[] | (() => UIScreen[])): this;\n /** Switch to tab `index`. **Instant by default** — the tab-bar convention (tabs are parallel\n * modes, not neighbors); pass `animated: true` for the direction-aware slide of top-tab /\n * pager UIs. Out-of-range and same-index calls are no-ops. Tabs keep their stacks: selecting\n * away and back restores the tab exactly where it was, pushed screens included. */\n select(index: number, animated?: boolean): this;\n /** The selected tab index (0-based). */\n readonly index: number;\n /** Fires when the selected tab changes and has settled — a user swipe or `select()`. */\n onSelect(callback: (index: number) => void): this;\n /** Push `screen` on top of the **current tab** — slides in natively; the edge back-swipe (or\n * `pop()`) removes it. Other tabs are unaffected. */\n push(screen: UIScreen): this;\n /** Pop the current tab's top screen (no-op at the tab root — the root never pops). The\n * programmatic twin of the native edge back-swipe. */\n pop(): this;\n /** Unwind the current tab back to its root screen in one step. */\n popToRoot(): this;\n /** Swap the current tab's top screen for `screen` without growing the stack (at depth 1 this\n * swaps the tab's root). */\n replace(screen: UIScreen): this;\n /** The current tab's screens, root → top (read-only snapshot). */\n readonly stack: UIScreen[];\n /** The current tab's stack depth — 1 means only the root. While `depth > 1`, swiping between\n * tabs is disabled (the horizontal gesture belongs to the back-swipe). */\n readonly depth: number;\n /** Fires when the current tab's depth changes — push, pop, replace, or a back-swipe. */\n onChange(callback: (depth: number) => void): this;\n}\nexport declare class PagerElement extends ContainerElement<\"pager\"> {\n /** Per-tab stack lengths — partitions the flat tab-major `children`. Named `_*` so chisel\n * keeps it (the host reads it live). */\n _lens: number[];\n /** Selected tab. */\n _index: number;\n _openCount: number;\n private scl;\n private ncl;\n constructor(style: UIPagerStyle | null, tabs: UIScreen[]);\n /** Start offset of tab `i`'s segment in the flat `children`. */\n private _offset;\n get index(): number;\n get stack(): UIScreen[];\n get depth(): number;\n onSelect(callback: (index: number) => void): this;\n onChange(callback: (depth: number) => void): this;\n select(index: number, animated?: boolean): this;\n push(screen: UIScreen): this;\n pop(): this;\n popToRoot(): this;\n replace(screen: UIScreen): this;\n private _rebuild;\n setContent(children: UINodeChild[] | ChildrenFn): this;\n append(...nodes: UINodeChild[]): this;\n insert(index: number, ...nodes: UINodeChild[]): this;\n remove(...nodesToDelete: UIScreen[]): this;\n _reconcile(next: UINodeChild[]): void;\n _hostDidSelect(index: number): void;\n _hostDidPop(depth: number): void;\n private _emitSelect;\n private _emitChange;\n private _track;\n _activate(): void;\n _deactivate(): void;\n}\n/** Callable factory + ambient statics. The name `UIPager` is a value (this factory) and a type\n * (the instance interface above) — a standard value/type merge. */\ninterface UIPagerConstructor {\n /** Tabs — each argument is a screen or an array of screens (arrays flatten one level, falsy\n * entries are skipped). One screen → a plain navigation stack rooted at it (push/pop, no tab\n * swiping); several → swipeable sibling tabs, fixed at construction, each starting as its own\n * one-screen stack. */\n (...tabs: (UIScreen | UIScreen[] | false | null | undefined)[]): UIPager;\n /** @deprecated Style as the first argument is legacy — use chained `.style({...})`. */\n (style: UIPagerStyle, content?: UIScreen | UIScreen[]): UIPager;\n /** The pager that owns the currently visible screen, or `null` when the visible screen isn't\n * hosted by one. With pagers nested inside pages, resolves to the **innermost** — so ambient\n * calls act on the pager the user is actually looking at. */\n readonly current: UIPager | null;\n /** `UIPager.current.push(screen)` — push onto the pager owning the visible screen, no\n * reference threading. No-op with a console warning when there is no current pager. */\n push(screen: UIScreen): void;\n /** `UIPager.current.pop()` — pop the visible pager's current tab (no-op at the tab root, or\n * with a warning when there is no current pager). */\n pop(): void;\n /** `UIPager.current.popToRoot()` — unwind the visible pager's current tab to its root. */\n popToRoot(): void;\n}\n/**\n * Create a pager — THE screen-navigation element: an array of screens becomes swipeable sibling\n * tabs, a single screen becomes a plain stack. Navigate within it via `pager.push/pop/replace`\n * (per-tab) and `pager.select(i)` (between tabs), or from any child screen via the ambient\n * `UIPager.push` / `UIPager.pop` / `UIPager.current`. Pages are full `UIScreen`s (own\n * `onOpen`/`onClose`); give the pager `flexGrow: 1` or a size so it doesn't\n * collapse. `Router` stays the way to open a destination ON TOP of the pager.\n */\nexport declare const UIPager: UIPagerConstructor;\nexport {};\n","types/ui/UIPopover.d.ts":"import { ModalElement, type UIModal, type UIModalStyle } from \"./UIModal\";\nimport { type BoundingClientRect, type ChildrenFn, type UIChildArg, type UINodeChild } from \"./UINode\";\nexport type UIPopoverStyle = UIModalStyle;\n/** What a popover can anchor to: any element (it reads `getBoundingClientRect()`), or a raw\n * `{x, y}` point — a long-press context menu anchors to the touch position. */\nexport type UIPopoverAnchor = {\n getBoundingClientRect(): BoundingClientRect | null;\n} | {\n x: number;\n y: number;\n};\n/**\n * An anchored menu: a `UIModal` whose scrim is transparent (invisible but still intercepting —\n * an outside tap dismisses, and nothing underneath can scroll while it's open) and whose\n * position comes from the anchor passed to `show(anchor)`: below the anchor's left edge,\n * flipped above when there's no room, clamped into the viewport. Position is computed once per\n * show — anchored popovers don't follow their anchor. Backs dropdowns, context menus, and\n * tooltips; create it **once** at module scope and reuse it.\n */\nexport interface UIPopover extends UIModal {\n /** Position next to `anchor` (an element or an `{x, y}` point), attach to\n * `Presentable.current` (unless an owner was set via `attachTo`), and play the entrance\n * transition. Without an anchor the popover shows wherever its own style puts it. */\n show(anchor?: UIPopoverAnchor): void;\n}\nexport declare class PopoverElement extends ModalElement {\n private _anchorRect?;\n private _placedLeft?;\n private _placedTop?;\n constructor(style: UIPopoverStyle, children: UINodeChild[] | ChildrenFn);\n show(anchor?: UIPopoverAnchor): void;\n private _place;\n}\n/** Create an anchored popover (see {@link UIPopover}) — create once at module scope, then\n * `show(anchor)` next to an element or `{x, y}` point. Same argument forms as `UIColumn`. */\nexport declare function UIPopover(...children: UIChildArg[]): UIPopover;\nexport declare function UIPopover(children: UINodeChild[] | ChildrenFn): UIPopover;\n/** @deprecated Style as the first argument is legacy — use chained `.style({...})`. */\nexport declare function UIPopover(style: UIPopoverStyle, children?: UINodeChild[] | ChildrenFn): UIPopover;\n","types/ui/UIScreen.d.ts":"import { TouchStartEvent } from \"../runtime/touch\";\nimport { type PresentOptions } from \"./presentable\";\nimport { ContainerElement, type BaseStyle, type ContainerStyle, type DrawableStyle, type PaddingStyle, type UIChildArg, type UIContainerBase, type UINodeChild, type ChildrenFn } from \"./UINode\";\nexport type UIScreenStyle = ContainerStyle & DrawableStyle & PaddingStyle & BaseStyle;\n/** A screen — the root the router/host mounts, sized to its slot. A screen NEVER scrolls: it is\n * fixed chrome (header, tab bar) plus, when the content overflows, one `UIScrollable` body child\n * (`flexGrow: 1`). Scroll events and pull-to-refresh live on the scroll containers\n * (`UIScrollable`, `UIVirtualizedList`). */\nexport interface UIScreen extends UIContainerBase<UIScreenStyle, DrawableStyle & BaseStyle> {\n readonly type: \"screen\";\n /** Show this screen as the current destination (replaces whatever is visible — a screen, a\n * scene, a native view — suspending an active Router until `Router.restore()`). */\n open(options?: PresentOptions): void;\n /** Dismiss if this screen is the visible destination. */\n close(): void;\n /** Hardware/system back while this screen is current. */\n onBackPressed(callback: () => void): this;\n /** The screen became the visible destination (first open, or revealed by a pop). */\n onOpen(callback: () => void): this;\n /** The screen stopped being visible — closed, replaced, or covered by a push. */\n onClose(callback: () => void): this;\n /**\n * Keep this screen's built native tree alive when a host detaches it: instead of being destroyed,\n * its views + layout + live state (scroll position, input text) are retained, so re-hosting the\n * SAME screen object restores it in place rather than rebuilding. `onClose`/`onOpen` still fire on\n * detach/re-attach. You own the lifetime — a kept tree is freed only by `dispose()` or when the\n * project unloads. (Native-only today; web rebuilds.)\n */\n keepAlive(enabled?: boolean): this;\n /** Free a `keepAlive()` screen's retained tree now. No-op unless it's currently detached-and-kept. */\n dispose(): this;\n /** Touch began on the screen; `ev.track(...)` takes over the rest of the gesture. */\n onTouchStart(callback: (ev: TouchStartEvent<UIScreen>) => void): this;\n}\nexport declare class ScreenElement extends ContainerElement<\"screen\"> {\n open(options?: PresentOptions): void;\n close(): void;\n protected ol: (() => void)[];\n onOpen(callback: () => void): this;\n protected cl: (() => void)[];\n onClose(callback: () => void): this;\n _keepAlive: boolean;\n keepAlive(enabled?: boolean): this;\n dispose(): this;\n readonly touchStartListeners: any[];\n _interactive: boolean;\n onTouchStart(callback: any): this;\n _emitTouchStart(pointerId: number, clientX: number, clientY: number): any;\n _backButtonCallback?: () => void;\n onBackPressed(callback: any): this;\n}\n/** Create a screen. Present it with `.open()`, or via `Router` / `UIPager`. Same argument forms\n * as `UIColumn`. */\nexport declare function UIScreen(...children: UIChildArg[]): UIScreen;\nexport declare function UIScreen(children: UINodeChild[] | ChildrenFn): UIScreen;\n/** @deprecated Style as the first argument is legacy — use chained `.style({...})`. */\nexport declare function UIScreen(style: UIScreenStyle, children?: UINodeChild[] | ChildrenFn): UIScreen;\n","types/ui/UIScrollable.d.ts":"import type { UIContainerStyle } from \"./UIContainer\";\nimport { type UIChildArg, type UIContainerBase, type UINodeChild, type ChildrenFn, type Color } from \"./UINode\";\nexport type ScrollStyle = {\n showScrollbar?: boolean;\n overscrollMode?: \"none\" | \"absorb\" | \"default\";\n /** Tint of the native pull-to-refresh spinner (pairs with `onRefresh`). */\n refreshControlColor?: Color;\n /** How a scroll gesture in THIS scrollable dismisses the keyboard: `\"interactive\"` (default) —\n * dragging over the keyboard slides it away (chat feel); `\"scroll\"` — any drag dismisses\n * immediately; `\"none\"` — never (tap-outside policy still applies). */\n keyboardDismissMode?: \"interactive\" | \"scroll\" | \"none\";\n /** Paging: when the drag ends, rest on a direct child's boundary along the scroll axis — the\n * value picks where the child sits in the viewport; `\"none\"` (default) is free scrolling. Snap\n * targets are the children themselves, so item widths can differ (card-carousel-with-peek); a\n * carousel is a horizontal scrollable of full-width children + `snap: \"start\"`. */\n snap?: \"none\" | \"start\" | \"center\" | \"end\";\n};\nexport type UIScrollableStyle = UIContainerStyle & ScrollStyle & {\n scrollDirection?: \"horizontal\" | \"vertical\";\n};\n/** A scroll container — vertical by default, `scrollDirection: \"horizontal\"` for carousels/chip\n * rows. The scrolling body of a screen (screens themselves never scroll). */\nexport interface UIScrollable extends UIContainerBase<UIScrollableStyle> {\n readonly type: \"scrollable\";\n /** Scroll position changed (px from the start edge). */\n onScroll(callback: (scrollPosition: number) => void): UIScrollable;\n /** The scroll gesture ended (finger lifted). */\n onScrollRelease(callback: () => void): UIScrollable;\n /** Pulled past the content edge by `delta` px. */\n onOverscroll(callback: (delta: number) => void): UIScrollable;\n /** Pull-to-refresh: the spinner stays until the returned promise settles. Attach BEFORE the\n * node mounts (hosts read it at creation). Vertical only; native hosts — no-op on web. */\n onRefresh(callback: () => void | Promise<void>): UIScrollable;\n}\n/** Create a scroll container (same argument forms as `UIColumn`). As a screen body, pair with\n * `flexGrow: 1`. */\nexport declare function UIScrollable(...children: UIChildArg[]): UIScrollable;\nexport declare function UIScrollable(children: UINodeChild[] | ChildrenFn): UIScrollable;\n/** @deprecated Style as the first argument is legacy — use chained `.style({...})`. */\nexport declare function UIScrollable(style: UIScrollableStyle, children?: UINodeChild[] | ChildrenFn): UIScrollable;\n","types/ui/UISpacer.d.ts":"import { type ElementStyle, type UIElementBase } from \"./UINode\";\nexport type UISpacerStyle = ElementStyle;\n/** A flexible gap — `flexGrow: 1` by default, pushes its siblings apart. */\nexport interface UISpacer extends UIElementBase<UISpacerStyle> {\n readonly type: \"spacer\";\n}\n/** Create a flexible gap (`flexGrow: 1`) — e.g. between a header's title and its actions. */\nexport declare function UISpacer(): UISpacer;\nexport declare function UISpacer(style: UISpacerStyle): UISpacer;\n","types/ui/UITabs.d.ts":"import { type UIPager } from \"./UIPager\";\nimport { ScreenElement, UIScreen } from \"./UIScreen\";\nimport { type UIRow as UIRowType } from \"./UIContainer\";\nimport { type ImageSource } from \"./UIImage\";\nimport type { UIChildArg } from \"./UINode\";\nexport type UITabDef = {\n label: string;\n /** Tab icon — typically `assetIcon(\"lucide:…\")`. Tinted active/inactive by the bar. */\n icon?: ImageSource;\n /** The tab's root screen. Tabs are fixed at construction (like UIPager's). */\n screen: UIScreen;\n};\n/**\n * A bottom-tab app shell: swipeable tabs (a `UIPager`) plus a themed tab bar, as one\n * `UIScreen` — present it directly (`Router.init(tabs)`). Keys are tab ids, in tab order:\n *\n * ```ts\n * const tabs = UITabs({\n * home: { label: \"Home\", icon: assetIcon(\"lucide:house\"), screen: homeScreen },\n * profile: { label: \"Profile\", icon: assetIcon(\"lucide:user\"), screen: profileScreen },\n * })\n * Router.init(tabs)\n * ```\n *\n * In-tab navigation stays the pager's: `UIPager.push(detail)` from any screen (bar stays);\n * `Router.push` opens above the shell (bar covered). Restyle via `theme()` (primaryColor,\n * mutedColor, tabbarBg, …) or the `bar` handle; for a fully custom bar build on `UIPager`.\n */\nexport interface UITabs extends UIScreen {\n /** The active tab id. */\n readonly tab: string;\n /** Switch tabs (instant, the tab-bar convention; `animated: true` slides). */\n select(id: string, animated?: boolean): this;\n /** Fires when the active tab changes and has settled — a bar tap, swipe, or `select()`. */\n onSelect(callback: (id: string, index: number) => void): this;\n /** Show a badge on a tab: `true` = dot, a number/string = count pill, `false`/`null`/`0` clears. */\n badge(id: string, value: number | string | boolean | null): this;\n /** The pager under the bar — in-tab stacks (`push`/`pop`/`depth`). */\n readonly pager: UIPager;\n /** The bar row (named \"tabbar\") — for restyling beyond the theme variables. */\n readonly bar: UIRowType;\n}\nexport declare class TabsElement extends ScreenElement {\n private readonly ids;\n private readonly _pagerEl;\n private readonly _bar;\n private readonly _icons;\n private readonly _labels;\n private readonly _badges;\n private readonly _badgeTexts;\n private readonly _buttons;\n private readonly _selectListeners;\n constructor(defs: Record<string, UITabDef>);\n private _applyActive;\n get tab(): string;\n get pager(): any;\n get bar(): any;\n select(id: string, animated?: boolean): this;\n onSelect(callback: (id: string, index: number) => void): this;\n badge(id: string, value: number | string | boolean | null | undefined): this;\n}\n/** Create the standard bottom-tab shell — see {@link UITabs}. Keys are tab ids in tab order;\n * each tab needs a `label` and its root `screen` (plus an optional `icon`). */\nexport declare function UITabs(tabs: Record<string, UITabDef>): UITabs;\n/** A `defineTabs` tab: `label` + optional `icon` (an `assetIcon(\"lucide:…\")` call — never a\n * hand-written source object). `UITabDef` is this plus the tab's root `screen`. */\nexport type TabDef = Omit<UITabDef, \"screen\">;\n/** What `defineTabs` returns: the bar (mount it yourself when the screen owns its whole layout)\n * and the standard screen shell around it. `active` must be a declared tab id, as a literal. */\nexport type TabsHandle<T extends Record<string, TabDef>> = {\n /** Tab ids in declaration order. */\n ids: (keyof T & string)[];\n /** The bar alone — one button per tab, the `active` one highlighted. */\n bar(active: keyof T & string): UIRowType;\n /** A screen sitting ON the bar: `[ padded content column, bar ]`. */\n screen(active: keyof T & string, ...children: UIChildArg[]): UIScreen;\n};\n/**\n * Declare a tab bar WITHOUT screens — the design-stage twin of {@link UITabs} (same keys, same\n * `tab-<id>` button names, same theme variables), for mockups where every screen is its own file\n * and mounts the bar with a literal tab id:\n *\n * ```ts\n * export const mainTabs = defineTabs({\n * home: { label: \"Home\", icon: assetIcon(\"lucide:house\") },\n * profile: { label: \"Profile\", icon: assetIcon(\"lucide:user\") },\n * })\n * // in a screen file:\n * export default () => mainTabs.screen(\"home\", [ ...content ])\n * ```\n *\n * Restyle through the theme — `theme({ primaryColor, mutedColor, tabbarBg, screenBg })` recolors\n * every bar at once. The built app passes the same keys (plus each tab's root screen) to `UITabs`,\n * which renders the identical bar interactively.\n */\nexport declare function defineTabs<T extends Record<string, TabDef>>(tabs: T): TabsHandle<T>;\n","types/ui/UIText.d.ts":"import { Element, type BaseStyle, type DrawableStyle, type ElementStyle, type TextStyle, type UIElementBase } from \"./UINode\";\nexport type UITextStyle = ElementStyle & TextStyle & DrawableStyle;\n/** A text label. */\nexport interface UIText extends UIElementBase<UITextStyle, DrawableStyle & BaseStyle & TextStyle> {\n readonly type: \"text\";\n /** The displayed string — writable at any time. */\n text: string;\n}\nexport declare class TextElement extends Element<\"text\"> {\n private _text;\n constructor(style: any, text: string | (() => string));\n get text(): string;\n set text(value: string);\n}\n/** Create a text label — a string, or `() => string` for reactive text that re-renders when a\n * signal it read changes. */\nexport declare function UIText(text: string | (() => string)): UIText;\n/** @deprecated Style as the first argument is legacy — use chained `.style({...})`. */\nexport declare function UIText(style: UITextStyle, text: string | (() => string)): UIText;\n","types/ui/UIVideo.d.ts":"import type { VideoPlayer } from \"../runtime/media\";\nimport { type PresentOptions } from \"./presentable\";\nimport { type BaseStyle, type DrawableStyle, type ElementStyle, type UIElementBase } from \"./UINode\";\nexport type UIVideoStyle = ElementStyle & DrawableStyle & {\n objectFit?: \"cover\" | \"contain\" | \"fill\";\n};\n/** A video surface showing a `VideoPlayer`'s output — embeddable in a screen AND\n * fullscreen-presentable (`open()`), with seamless promotion between the two. */\nexport interface UIVideo extends UIElementBase<UIVideoStyle, DrawableStyle & BaseStyle> {\n readonly type: \"video\";\n /** The player driving this surface (playback control lives on it). */\n player: VideoPlayer;\n /** Show fullscreen as the current destination. Promotion: if this video is mounted in a screen,\n * the SAME native player moves fullscreen — playback uninterrupted; a pop moves it back. */\n open(options?: PresentOptions): void;\n /** Dismiss if this is the visible destination. */\n close(): void;\n /** Became the visible destination. */\n onOpen(callback: () => void): this;\n /** Stopped being the visible destination. */\n onClose(callback: () => void): this;\n /** Hardware/system back while current. */\n onBackPressed(callback: () => void): this;\n}\n/** Create a video node showing `player`'s output. */\nexport declare function UIVideo(player: VideoPlayer): UIVideo;\n/** @deprecated Style as the first argument is legacy — use chained `.style({...})`. */\nexport declare function UIVideo(style: UIVideoStyle, player: VideoPlayer): UIVideo;\n","types/ui/UIVirtualizedList.d.ts":"import { Element, type Color, type DrawableStyle, type ElementStyle, type UIElementBase, type UINodeChild } from \"./UINode\";\nexport type UIVirtualizedListStyle = DrawableStyle & ElementStyle & {\n /** Tint of the native pull-to-refresh spinner (pairs with `onRefresh`). */\n refreshControlColor?: Color;\n /** Same key and semantics as UIScrollable's; `\"none\"` keeps a chat composer's keyboard up no\n * matter how the history is scrolled. */\n keyboardDismissMode?: \"interactive\" | \"scroll\" | \"none\";\n};\nexport interface VListConfig<T> {\n /** Stable unique key of an item. */\n keyOf: (item: T) => string;\n /** Subtree factory — called when the item enters the window; the subtree lives until it\n * leaves. */\n render: (item: T) => UINodeChild;\n /** Height estimate (px) used before the first measurement — a number, or a per-item function\n * (chat: `msg => 40 + Math.ceil(msg.text.length / 35) * 20`). Computed once when the item is\n * added. */\n estimatedHeight: number | ((item: T) => number);\n /** Extra px around the viewport kept mounted. Default: one viewport height. */\n overscan?: number;\n /** Chat mode: the first layout starts scrolled to the end, and appends auto-scroll while the\n * list sits at the bottom. */\n inverted?: boolean;\n}\n/** A windowed (virtualized) list: only the items near the viewport are mounted — for long feeds\n * and chats. Items are keyed; feed it via `setData`/`append`/`prepend`. */\nexport interface UIVirtualizedList<T = unknown> extends UIElementBase<UIVirtualizedListStyle> {\n readonly type: \"vlist\";\n /** Replace the data wholesale — vanished keys are unmounted by the host's window sync. */\n setData(items: T[]): this;\n /** Append items to the end (auto-scrolls when `inverted` and resting at the bottom). */\n append(...items: T[]): this;\n /** Insert at the start WITHOUT a scroll jump (the host compensates the offset). */\n prepend(...items: T[]): this;\n /** Update items with the same keys: mounted ones re-render; the cached height persists until\n * re-measured. */\n update(...items: T[]): this;\n /** Remove items by key. */\n removeByKey(...keys: string[]): this;\n /** Number of data items (mounted or not). */\n readonly itemCount: number;\n /** The data item under `key`, if any. */\n getItem(key: string): T | undefined;\n /** Scroll to `offset` px. */\n scrollTo(offset: number, animated?: boolean): void;\n /** Scroll to the item with `key`. */\n scrollToKey(key: string, animated?: boolean): void;\n /** Scroll to the end of the content. */\n scrollToEnd(animated?: boolean): void;\n /** Scroll position changed (px from the start edge). */\n onScroll(callback: (scrollPosition: number) => void): this;\n /** Pull-to-refresh: the spinner stays until the returned promise settles. Attach BEFORE the\n * node mounts (hosts read it at creation). Native hosts only — no-op on web. */\n onRefresh(callback: () => void | Promise<void>): this;\n /** Fires within `thresholdPx` of the content's bottom edge — once, re-armed after leaving the\n * edge (host-side latch). Infinite-scroll loading. */\n onEndReached(thresholdPx: number, callback: () => void): this;\n /** Same, for the top edge — chat history loading. */\n onStartReached(thresholdPx: number, callback: () => void): this;\n}\nexport declare class VListElement<T> extends Element<\"vlist\"> implements UIVirtualizedList<T> {\n _overscan: number;\n _inverted: boolean;\n _keys: string[];\n _estimates: number[];\n _endThreshold: number;\n _startThreshold: number;\n protected sl: ((scrollPosition: number) => void)[];\n protected erl: (() => void)[];\n protected strl: (() => void)[];\n private items;\n private mounted;\n private keyOf;\n private renderItem;\n private estimate;\n constructor(config: VListConfig<T>);\n private get isAttached();\n private register;\n setData(items: T[]): this;\n append(...items: T[]): this;\n prepend(...items: T[]): this;\n update(...items: T[]): this;\n removeByKey(...keys: string[]): this;\n get itemCount(): number;\n getItem(key: string): T | undefined;\n scrollTo(offset: number, animated?: boolean): void;\n scrollToKey(key: string, animated?: boolean): void;\n scrollToEnd(animated?: boolean): void;\n onScroll(callback: (scrollPosition: number) => void): this;\n _refreshCallback: any;\n onRefresh(callback: () => void | Promise<void>): this;\n onEndReached(thresholdPx: number, callback: () => void): this;\n onStartReached(thresholdPx: number, callback: () => void): this;\n}\n/** Create a virtualized list from a config (`keyOf` + `render` + `estimatedHeight` required),\n * then feed it via `setData`/`append`/`prepend`. Give it a size (`flexGrow: 1` as a screen body). */\nexport declare function UIVirtualizedList<T>(config: VListConfig<T>): UIVirtualizedList<T>;\n","types/ui/UIWidget.d.ts":"import { TouchStartEvent } from \"../runtime/touch\";\nimport { Presentable } from \"./presentable\";\nimport { ContainerElement, type BaseStyle, type Color, type ContainerStyle, type DrawableStyle, type PaddingStyle, type PositionStyle, type UIChildArg, type UIContainerBase, type UINodeChild, type ChildrenFn } from \"./UINode\";\nexport type UIWidgetStyle = ContainerStyle & DrawableStyle & PaddingStyle & BaseStyle & PositionStyle & {\n /** A layer behind the widget that intercepts clicks — `\"transparent\"` still intercepts, `null`\n * removes the layer. A tap on it fires `onOverlayTap`. */\n overlayColor?: Color | null;\n};\n/** A floating overlay — absolutely positioned in device coordinates, mounted above the page as\n * its own layout root (never a child of what's underneath). The base of dialogs, toasts,\n * mini-players and scene HUDs; `UIModal`/`UIPopover`/`UIBottomSheet` build on it. */\nexport interface UIWidget extends UIContainerBase<UIWidgetStyle, DrawableStyle & BaseStyle & {\n overlayColor?: Color | null;\n}> {\n readonly type: \"widget\";\n /**\n * Attach this widget to a destination (a `Scene`, a `UIScreen`, …): the widget lives on that\n * page's layer — it shows/hides with the page and rides its transition, and a screen pushed\n * on top covers it (a scene HUD behaves like part of the scene). Sticky until `attachTo(null)`\n * (= back to a global overlay). Set it while the widget is hidden. The widget is always its own\n * overlay root mounted into the owner's page view — it never becomes a child of the owner, so it\n * stays topmost and its updates never trigger the owner's relayout. Works with a `UIScreen` that\n * is a page inside a `UIPager`: the widget mounts into that tab and rides its swipe. (Web shows\n * and hides it with the owner but does not yet ride the transition.)\n */\n attachTo(owner: Presentable | null): this;\n /** Show the widget. By default it is a global overlay above every destination — it stays\n * visible across navigation until `hide()` (dialogs, mini-player, global loader). If the\n * widget was attached via `attachTo(owner)`, it mounts on that page's layer instead and is\n * only visible while the owner is presented. */\n show(): void;\n /** Unmount the widget. */\n hide(): void;\n /** Mounted right now (`show()` ran, `hide()` hasn't). */\n readonly isShow: boolean;\n /** Touch began on the widget; `ev.track(...)` takes over the rest of the gesture. */\n onTouchStart(callback: (ev: TouchStartEvent<UIWidget>) => void): this;\n /** Tap on the overlay layer (requires an `overlayColor`). */\n onOverlayTap(callback: () => void): this;\n /** Hardware/system back while the widget is shown. */\n onBackPressed(callback: () => void): this;\n}\nexport declare class WidgetElement extends ContainerElement<\"widget\"> {\n scrollable: false;\n _owner?: Presentable;\n constructor(type: \"widget\", style: UIWidgetStyle, children: UINodeChild[] | ChildrenFn);\n attachTo(owner: Presentable | null): this;\n show(): void;\n hide(): void;\n get isShow(): boolean;\n _interactive: boolean;\n readonly touchStartListeners: any[];\n onTouchStart(callback: any): this;\n _emitTouchStart(pointerId: number, clientX: number, clientY: number): any;\n readonly otl: (() => void)[];\n onOverlayTap(callback: () => void): this;\n _backButtonCallback?: () => void;\n onBackPressed(callback: any): this;\n}\n/** Create a widget (same argument forms as `UIColumn`). Position it with absolute-style props\n * (`top`/`left`/`bottom`/`right`), then `show()`/`hide()`. */\nexport declare function UIWidget(...children: UIChildArg[]): UIWidget;\nexport declare function UIWidget(children: UINodeChild[] | ChildrenFn): UIWidget;\n/** @deprecated Style as the first argument is legacy — use chained `.style({...})`. */\nexport declare function UIWidget(style: UIWidgetStyle, children?: UINodeChild[] | ChildrenFn): UIWidget;\n"}
1
+ {"global.d.ts":"// AUTO-GENERATED by build-types.ts. The import-free type surface for le.codes projects:\n// every SDK global declared ambiently, so user code uses Scene / Sprite / UIScreen / … \n// with no imports and full editor autocomplete.\n\nimport type * as SDK from \"./types/inject\"\nimport type * as SERVER from \"./types/server/inject\"\n\ndeclare global {\n const ARScene: typeof SDK.ARScene\n const AnimationClip: typeof SDK.AnimationClip\n const Animator: typeof SDK.Animator\n const Aspect: typeof SDK.Aspect\n const AudioPlayer: typeof SDK.AudioPlayer\n const Autotile2D: typeof SDK.Autotile2D\n const Bitmap: typeof SDK.Bitmap\n const Camera: typeof SDK.Camera\n const Camera2D: typeof SDK.Camera2D\n const CameraFollow: typeof SDK.CameraFollow\n const CameraView: typeof SDK.CameraView\n const Canvas: typeof SDK.Canvas\n const CharacterController: typeof SDK.CharacterController\n const CharacterController2D: typeof SDK.CharacterController2D\n const ClickEvent: typeof SDK.ClickEvent\n const Color: typeof SDK.Color\n const DateValue: typeof SDK.DateValue\n const File: typeof SDK.File\n const FollowPath: typeof SDK.FollowPath\n const FormData: typeof SDK.FormData\n const Geolocation: typeof SDK.Geolocation\n const Geometry: typeof SDK.Geometry\n const IK: typeof SDK.IK\n const Input: typeof SDK.Input\n const InspectorUI: typeof SDK.InspectorUI\n const Light: typeof SDK.Light\n const LongPressEvent: typeof SDK.LongPressEvent\n const LookAt: typeof SDK.LookAt\n const Mat4: typeof SDK.Mat4\n const Material: typeof SDK.Material\n const Mathf: typeof SDK.Mathf\n const Mesh: typeof SDK.Mesh\n const Model: typeof SDK.Model\n const ModelAnimation: typeof SDK.ModelAnimation\n const MoveTo: typeof SDK.MoveTo\n const NativeView: typeof SDK.NativeView\n const Node: typeof SDK.Node\n const Node2D: typeof SDK.Node2D\n const Noise: typeof SDK.Noise\n const OAuth: typeof SDK.OAuth\n const Particles: typeof SDK.Particles\n const Physics: typeof SDK.Physics\n const Physics2D: typeof SDK.Physics2D\n const Plane: typeof SDK.Plane\n const PlayAnimation: typeof SDK.PlayAnimation\n const Presentable: typeof SDK.Presentable\n const Push: typeof SDK.Push\n const QRScanner: typeof SDK.QRScanner\n const Quat: typeof SDK.Quat\n const Ray: typeof SDK.Ray\n const Router: typeof SDK.Router\n const RpcError: typeof SDK.RpcError\n const Scene: typeof SDK.Scene\n const Scene2D: typeof SDK.Scene2D\n const Scene2dHandle: typeof SDK.Scene2dHandle\n const SceneHandle: typeof SDK.SceneHandle\n const Service: typeof SDK.Service\n const Shape: typeof SDK.Shape\n const Shape2D: typeof SDK.Shape2D\n const Spin: typeof SDK.Spin\n const Sprite: typeof SDK.Sprite\n const SpriteAnimation: typeof SDK.SpriteAnimation\n const SpriteSheet: typeof SDK.SpriteSheet\n const SvgSource: typeof SDK.SvgSource\n const Texture: typeof SDK.Texture\n const Texture2D: typeof SDK.Texture2D\n const Tilemap: typeof SDK.Tilemap\n const Tileset: typeof SDK.Tileset\n const TouchStartEvent: typeof SDK.TouchStartEvent\n const Trail: typeof SDK.Trail\n const Trigger: typeof SDK.Trigger\n const Trigger2D: typeof SDK.Trigger2D\n const UIBottomSheet: typeof SDK.UIBottomSheet\n const UIBox: typeof SDK.UIBox\n const UIButton: typeof SDK.UIButton\n const UIColumn: typeof SDK.UIColumn\n const UIImage: typeof SDK.UIImage\n const UIInput: typeof SDK.UIInput\n const UIModal: typeof SDK.UIModal\n const UIPager: typeof SDK.UIPager\n const UIPopover: typeof SDK.UIPopover\n const UIRow: typeof SDK.UIRow\n const UIScreen: typeof SDK.UIScreen\n const UIScrollable: typeof SDK.UIScrollable\n const UISpacer: typeof SDK.UISpacer\n const UITabs: typeof SDK.UITabs\n const UIText: typeof SDK.UIText\n const UITextArea: typeof SDK.UITextArea\n const UIVideo: typeof SDK.UIVideo\n const UIVirtualizedList: typeof SDK.UIVirtualizedList\n const UIWidget: typeof SDK.UIWidget\n const VRScene: typeof SDK.VRScene\n const Vec2: typeof SDK.Vec2\n const Vec3: typeof SDK.Vec3\n const VideoPlayer: typeof SDK.VideoPlayer\n const WebSocket: typeof SDK.WebSocket\n const __UIBox: typeof SDK.__UIBox\n const __UIButton: typeof SDK.__UIButton\n const __UIColumn: typeof SDK.__UIColumn\n const __UIRow: typeof SDK.__UIRow\n const __UIScreen: typeof SDK.__UIScreen\n const __UIScrollable: typeof SDK.__UIScrollable\n const __UIWidget: typeof SDK.__UIWidget\n const __channel: typeof SDK.__channel\n const __editorPlugins: typeof SDK.__editorPlugins\n const __rpc: typeof SDK.__rpc\n const __serverOnly: typeof SDK.__serverOnly\n const __uiMap: typeof SDK.__uiMap\n const animate: typeof SDK.animate\n const animateMat4: typeof SDK.animateMat4\n const app: typeof SDK.app\n const cells: typeof SDK.cells\n const clipboard: typeof SDK.clipboard\n const colorCurve: typeof SDK.colorCurve\n const computed: typeof SDK.computed\n const cubicBezier: typeof SDK.cubicBezier\n const curve: typeof SDK.curve\n const date: typeof SDK.date\n const defineScene: typeof SDK.defineScene\n const defineScene2d: typeof SDK.defineScene2d\n const defineSpriteSheet: typeof SDK.defineSpriteSheet\n const defineTabs: typeof SDK.defineTabs\n const defineTileset: typeof SDK.defineTileset\n const device: typeof SDK.device\n const easeIn: typeof SDK.easeIn\n const easeInOut: typeof SDK.easeInOut\n const easeOut: typeof SDK.easeOut\n const effect: typeof SDK.effect\n const encodeCells: typeof SDK.encodeCells\n const fetch: typeof SDK.fetch\n const fetchLocal: typeof SDK.fetchLocal\n const flipX: typeof SDK.flipX\n const isRawCell: typeof SDK.isRawCell\n const localStorage: typeof SDK.localStorage\n const make: typeof SDK.make\n const openFilePicker: typeof SDK.openFilePicker\n const openURL: typeof SDK.openURL\n const packTile: typeof SDK.packTile\n const pauseAnimation: typeof SDK.pauseAnimation\n const rawCell: typeof SDK.rawCell\n const rawIndex: typeof SDK.rawIndex\n const ref: typeof SDK.ref\n const registerEditorTool: typeof SDK.registerEditorTool\n const registerEditorWindow: typeof SDK.registerEditorWindow\n const registerFont: typeof SDK.registerFont\n const resumeAnimation: typeof SDK.resumeAnimation\n const rot180: typeof SDK.rot180\n const rot270: typeof SDK.rot270\n const rot90: typeof SDK.rot90\n const share: typeof SDK.share\n const signal: typeof SDK.signal\n const stopAnimation: typeof SDK.stopAnimation\n const theme: typeof SDK.theme\n const tileFlip: typeof SDK.tileFlip\n const tileIndex: typeof SDK.tileIndex\n const tileOriented: typeof SDK.tileOriented\n const tileTurns: typeof SDK.tileTurns\n const toast: typeof SDK.toast\n const use: typeof SDK.use\n type ARScene<T extends ARMode = \"default\"> = SDK.ARScene<T>\n type AnimationClip = SDK.AnimationClip\n type Animator = SDK.Animator\n type AnimatorPlayOptions = SDK.AnimatorPlayOptions\n type AppState = SDK.AppState\n type Aspect<K extends string, P = Node> = SDK.Aspect<K, P>\n type AspectEntry<A extends Aspect<any, any> = Aspect<any, any>> = SDK.AspectEntry<A>\n type AudioPlayer = SDK.AudioPlayer\n type Autotile2D = SDK.Autotile2D\n type Bitmap = SDK.Bitmap\n type BlockEntry = SDK.BlockEntry\n type Camera = SDK.Camera\n type Camera2D = SDK.Camera2D\n type Camera2dNodeDef = SDK.Camera2dNodeDef\n type CameraFacing = SDK.CameraFacing\n type CameraFollow = SDK.CameraFollow\n type CameraNodeDef = SDK.CameraNodeDef\n type CameraView = SDK.CameraView\n type Canvas = SDK.Canvas\n type CellsData = SDK.CellsData\n type CharacterController = SDK.CharacterController\n type CharacterController2D = SDK.CharacterController2D\n type ClickEvent<T = any> = SDK.ClickEvent<T>\n type ClientChannel<E extends Record<string, unknown> = Record<string, unknown>> = SDK.ClientChannel<E>\n type ClipDef = SDK.ClipDef\n type ClipKey<V> = SDK.ClipKey<V>\n type ClipTrackDef = SDK.ClipTrackDef\n type Computed<T> = SDK.Computed<T>\n type DateInput = SDK.DateInput\n type DateValue = SDK.DateValue\n type EdgeSlot = SDK.EdgeSlot\n type EditorApi = SDK.EditorApi\n type EditorRayHit = SDK.EditorRayHit\n type EditorToolHooks = SDK.EditorToolHooks\n type EditorWindowFn = SDK.EditorWindowFn\n type FetchResponse = SDK.FetchResponse\n type FieldMeta<T = unknown> = SDK.FieldMeta<T>\n type File = SDK.File\n type FillBlock = SDK.FillBlock\n type FollowPath = SDK.FollowPath\n type FormData = SDK.FormData\n type GeoOptions = SDK.GeoOptions\n type GeoPosition = SDK.GeoPosition\n type GeoWatch = SDK.GeoWatch\n type Geometry = SDK.Geometry\n type HapticStyle = SDK.HapticStyle\n type IKLookAt = SDK.IKLookAt\n type IKTwoBone = SDK.IKTwoBone\n type InspectorUI = SDK.InspectorUI\n type Light = SDK.Light\n type LightDef = SDK.LightDef\n type LoadedScene<D extends SceneDef> = SDK.LoadedScene<D>\n type LoadedScene2d<D extends Scene2dDef> = SDK.LoadedScene2d<D>\n type Locale = SDK.Locale\n type LongPressEvent<T = any> = SDK.LongPressEvent<T>\n type LookAt = SDK.LookAt\n type MakeEntry<A extends Record<string, unknown> = Record<string, unknown>> = SDK.MakeEntry<A>\n type Mat4 = SDK.Mat4\n type Material = SDK.Material\n type MaterialDef = SDK.MaterialDef\n type Mesh = SDK.Mesh\n type MeshDef = SDK.MeshDef\n type Model = SDK.Model\n type ModelAnimation = SDK.ModelAnimation\n type MotionOptions = SDK.MotionOptions\n type MoveTo = SDK.MoveTo\n type NativeView = SDK.NativeView\n type Node = SDK.Node\n type Node2D = SDK.Node2D\n type Noise = SDK.Noise\n type OAuthCredential = SDK.OAuthCredential\n type OAuthProviderName = SDK.OAuthProviderName\n type Particles = SDK.Particles\n type PatchMaterial = SDK.PatchMaterial\n type PatchSlots = SDK.PatchSlots\n type PathMaterial = SDK.PathMaterial\n type Physics = SDK.Physics\n type Physics2D = SDK.Physics2D\n type Plane = SDK.Plane\n type PlayAnimation = SDK.PlayAnimation\n type PresentOptions = SDK.PresentOptions\n type Presentable = SDK.Presentable\n type PushEvent = SDK.PushEvent\n type PushPayload = SDK.PushPayload\n type PushRegisterOptions = SDK.PushRegisterOptions\n type PushStatus = SDK.PushStatus\n type QRScanner = SDK.QRScanner\n type Quat = SDK.Quat\n type Ray = SDK.Ray\n type RpcError = SDK.RpcError\n type Scene = SDK.Scene\n type Scene2D = SDK.Scene2D\n type Scene2dDef = SDK.Scene2dDef\n type Scene2dEnv = SDK.Scene2dEnv\n type Scene2dHandle<D extends Scene2dDef = Scene2dDef> = SDK.Scene2dHandle<D>\n type Scene2dNodeDef = SDK.Scene2dNodeDef\n type SceneDef = SDK.SceneDef\n type SceneHandle<D extends SceneDef = SceneDef> = SDK.SceneHandle<D>\n type SceneNodeDef = SDK.SceneNodeDef\n type Service = SDK.Service\n type Shape = SDK.Shape\n type Shape2D = SDK.Shape2D\n type SheetSprite = SDK.SheetSprite\n type Signal<T> = SDK.Signal<T>\n type Spin = SDK.Spin\n type Sprite = SDK.Sprite\n type SpriteAnimation = SDK.SpriteAnimation\n type SpriteMakeOptions = SDK.SpriteMakeOptions\n type SpriteSheet = SDK.SpriteSheet\n type SpriteSheetDef = SDK.SpriteSheetDef\n type SpriteSourceDef = SDK.SpriteSourceDef\n type TabDef = SDK.TabDef\n type TabsHandle<T extends Record<string, TabDef>> = SDK.TabsHandle<T>\n type Texture = SDK.Texture\n type Texture2D = SDK.Texture2D\n type ThemeAccessors<T> = SDK.ThemeAccessors<T>\n type ThemeValues = SDK.ThemeValues\n type TileBlock = SDK.TileBlock\n type TileMaterial = SDK.TileMaterial\n type TilePart = SDK.TilePart\n type Tilemap = SDK.Tilemap\n type TilemapSourceDef = SDK.TilemapSourceDef\n type Tileset = SDK.Tileset\n type TilesetDef = SDK.TilesetDef\n type TouchStartEvent<T = any> = SDK.TouchStartEvent<T>\n type Trail = SDK.Trail\n type Transition = SDK.Transition\n type TransitionName = SDK.TransitionName\n type TransitionSpec = SDK.TransitionSpec\n type TransitionTransform = SDK.TransitionTransform\n type Trigger = SDK.Trigger\n type Trigger2D = SDK.Trigger2D\n type UIBottomSheet = SDK.UIBottomSheet\n type UIBottomSheetStyle = SDK.UIBottomSheetStyle\n type UIBox = SDK.UIBox\n type UIButton = SDK.UIButton\n type UIButtonStyle = SDK.UIButtonStyle\n type UIColumn = SDK.UIColumn\n type UIContainerStyle = SDK.UIContainerStyle\n type UIImage = SDK.UIImage\n type UIImageStyle = SDK.UIImageStyle\n type UIInput = SDK.UIInput\n type UIInputStyle = SDK.UIInputStyle\n type UIModal = SDK.UIModal\n type UIModalStyle = SDK.UIModalStyle\n type UINativeViewStyle = SDK.UINativeViewStyle\n type UINode = SDK.UINode\n type UINodeChild = SDK.UINodeChild\n type UIPager = SDK.UIPager\n type UIPagerStyle = SDK.UIPagerStyle\n type UIPopover = SDK.UIPopover\n type UIPopoverStyle = SDK.UIPopoverStyle\n type UIRow = SDK.UIRow\n type UIScreen = SDK.UIScreen\n type UIScreenStyle = SDK.UIScreenStyle\n type UIScrollable = SDK.UIScrollable\n type UIScrollableStyle = SDK.UIScrollableStyle\n type UISpacer = SDK.UISpacer\n type UISpacerStyle = SDK.UISpacerStyle\n type UITabDef = SDK.UITabDef\n type UITabs = SDK.UITabs\n type UIText = SDK.UIText\n type UITextArea = SDK.UITextArea\n type UITextStyle = SDK.UITextStyle\n type UIVideo = SDK.UIVideo\n type UIVideoStyle = SDK.UIVideoStyle\n type UIVirtualizedList<T = unknown> = SDK.UIVirtualizedList<T>\n type UIWidget = SDK.UIWidget\n type UIWidgetStyle = SDK.UIWidgetStyle\n type Unit = SDK.Unit\n type VRScene = SDK.VRScene\n type Vec2 = SDK.Vec2\n type Vec3 = SDK.Vec3\n type VideoPlayer = SDK.VideoPlayer\n type WebSocket = SDK.WebSocket\n type With<N, A extends Aspect<any, any>> = SDK.With<N, A>\n // ---- server globals (available in *.server.ts; using them in client code is a build error) ----\n const ApiError: typeof SERVER.ApiError\n const auth: typeof SERVER.auth\n const channel: typeof SERVER.channel\n const defineDb: typeof SERVER.defineDb\n const model: typeof SERVER.model\n const ref: typeof SERVER.ref\n const request: typeof SERVER.request\n const t: typeof SERVER.t\n type ApiError = SERVER.ApiError\n}\n\nexport {}\n","host.d.ts":"// JS-runtime globals provided by the host engine (web viewer / desktop / iOS), NOT by the SDK.\n// Declared only so SDK and user code type-check — never bundled or injected. Mirrors\n// packages/projects/src/global.d.ts.\n\ndeclare global {\n function setTimeout(handler: (...args: any[]) => void, timeout?: number): number\n function setInterval(handler: (...args: any[]) => void, timeout?: number): number\n function clearTimeout(id: number): void\n function clearInterval(id: number): void\n /** Per-frame loop, driven by the host (viewer RAF / desktop runTick). `dt` is **seconds** since\n * the previous frame. */\n function setLoop(handler: (dt: number) => void): number\n function clearLoop(id: number): void\n\n /** π/180 — substituted at compile time (bundler `define`). */\n var DEG2RAD: number\n /** 180/π — substituted at compile time (bundler `define`). */\n var RAD2DEG: number\n\n /** Compile-time boolean: `true` in scene-editor bundles, `false` (const-folded + DCE'd) in\n * shipped ones — `if (EDITOR) { … }` costs zero bytes in production. `*.editor.ts` files are\n * the file-level form. */\n var EDITOR: boolean\n\n var console: {\n log(...data: any[]): void\n warn(...data: any[]): void\n info(...data: any[]): void\n error(...data: any[]): void\n }\n\n /** Compile-time macro: `asset('./hero.png')` is desugared by the bundler into the module import\n * for that resource. */\n function asset(path: string): string\n\n /** Compile-time macro: installs a font and returns its family name — using a font IS declaring\n * it. A registry id (`font(\"manrope\")`) resolves against the font registry; a project path\n * (`font(\"./fonts/Brand.ttf\")`) reads family/weight/italic from the file itself. `opts`\n * narrows/extends the face set (default: the family's standard weights). String-literal\n * argument only. No awaiting — faces load with app boot and the host holds first paint for\n * them. */\n function font(id: string, opts?: { weights?: number[], italic?: boolean }): string\n\n /** Compile-time macro: resolves one icon from the icon registry at build time and inlines it as\n * an image source for `UIImage(...)` — offline, identical on every host. `id` is `\"pack:name\"`\n * (e.g. `\"lucide:bell\"`), string literal only. Recolor via `{ color }`: a hex LITERAL is baked\n * into the SVG at compile time, a token/expression is applied as a tint (as is the `tintColor`\n * style prop). */\n function assetIcon(id: string, opts?: { color?: string }): { readonly svg: string, tintColor: string | null }\n\n /** Type-only editor convenience: the style object type of a UI element. `Style<UIButton>` (or\n * `Style<typeof myButton>`) is what you'd pass to `el.style(...)` — for typing reusable style\n * presets. Deliberately no `Partial<>` wrapper: every style prop is already optional, and\n * Partial over ClassStyles' `$`-index signature adds `| undefined`, breaking assignability back\n * into `.style(...)`. Round-trip guarded by sdk/tests/ui-types.test.ts. */\n type Style<T> = T extends { style: (s: infer S) => any } ? S : never\n}\n\nexport {}\n","types/animate/animate.d.ts":"type mat4 = Float32Array | number[];\ntype quat = Float32Array | number[];\ntype vec2 = Float32Array | number[];\ntype vec3 = Float32Array | number[];\nimport type { Easing } from \"./easings\";\ntype AnimateProps = number | string | vec2 | vec3 | quat;\nexport type AnimateOptions<T> = {\n from: T;\n to: T;\n duration: number;\n onUpdate(val: T): void;\n onComplete?(): void;\n easing?: Easing;\n};\nexport declare const animate: <T extends AnimateProps>(options: AnimateOptions<T>) => number;\nexport declare const stopAnimation: (id: number) => void;\nexport declare const pauseAnimation: (id: number) => void;\nexport declare const resumeAnimation: (id: number) => void;\nexport declare const animateMat4: (options: AnimateOptions<mat4>) => number;\nexport {};\n","types/animate/bezier.d.ts":"import type { Easing } from \"./easings\";\nexport declare function cubicBezier(mX1: number, mY1: number, mX2: number, mY2: number): Easing;\n","types/animate/easings.d.ts":"export type Easing = (v: number) => number;\nexport type EasingModifier = (easing: Easing) => Easing;\nexport declare function linear(p: number): number;\nexport declare function bounceOut(p: number): number;\nexport declare function bounceInOut(p: number): number;\nexport declare function reverseEasing(easing: Easing): Easing;\nexport declare function mirrorEasing(easing: Easing): Easing;\nexport declare function createExpoIn(power: number): Easing;\nexport declare function createBackIn(power: number): Easing;\nexport declare function createAnticipate(power: number): Easing;\nexport declare function bounceIn(p: number): number;\nexport declare function easeIn(p: number): number;\nexport declare function easeOut(p: number): number;\nexport declare function easeInOut(p: number): number;\nexport declare function circIn(p: number): number;\nexport declare function circOut(p: number): number;\nexport declare function circInOut(p: number): number;\nexport declare function backIn(p: number): number;\nexport declare function backOut(p: number): number;\nexport declare function backInOut(p: number): number;\nexport declare function anticipate(p: number): number;\n","types/canvas/Canvas.d.ts":"import { Texture2D } from \"../g2/Texture2D\";\nimport { File, type FetchResponse } from \"../runtime/fetch\";\nimport type { SvgSourceValue } from \"../runtime/misc\";\ndeclare const ALIGN: {\n readonly left: 0;\n readonly center: 1;\n readonly right: 2;\n readonly start: 3;\n readonly end: 4;\n};\ndeclare const BASELINE: {\n readonly alphabetic: 0;\n readonly top: 1;\n readonly middle: 2;\n readonly bottom: 3;\n readonly hanging: 4;\n readonly ideographic: 5;\n};\ndeclare const JOIN: {\n readonly miter: 0;\n readonly round: 1;\n readonly bevel: 2;\n};\ndeclare const CAP: {\n readonly butt: 0;\n readonly round: 1;\n readonly square: 2;\n};\nexport type TextAlign = keyof typeof ALIGN;\nexport type TextBaseline = keyof typeof BASELINE;\nexport type LineJoin = keyof typeof JOIN;\nexport type LineCap = keyof typeof CAP;\nexport interface CanvasTextMetrics {\n width: number;\n ascent: number;\n descent: number;\n}\nexport declare class Canvas {\n /** Brand so `Sprite`/`UIImage`/`Material` can accept a Canvas anywhere a texture source is expected. */\n readonly __canvas: true;\n width: number;\n height: number;\n /** Device-pixel multiplier (draw at 2 for crisp retina text). Applied by the backend. */\n pixelRatio: number;\n private _cmd;\n private _refs;\n private _globalAlpha;\n private _fillStyle;\n private _strokeStyle;\n private _lineWidth;\n private _lineJoin;\n private _lineCap;\n private _font;\n private _textAlign;\n private _textBaseline;\n private _surfaceId;\n private _tex2d?;\n private _uiBound;\n constructor(width: number, height: number, opts?: {\n pixelRatio?: number;\n });\n private _ref;\n /** Discard the recorded drawing to start a new one (for dynamic canvases). */\n reset(): this;\n /** Change the surface size; takes effect on the next bake. */\n resize(width: number, height: number): this;\n save(): this;\n restore(): this;\n translate(x: number, y: number): this;\n scale(sx: number, sy: number): this;\n rotate(rad: number): this;\n get globalAlpha(): number;\n set globalAlpha(a: number);\n get fillStyle(): string;\n set fillStyle(color: string);\n get strokeStyle(): string;\n set strokeStyle(color: string);\n get lineWidth(): number;\n set lineWidth(w: number);\n get lineJoin(): LineJoin;\n set lineJoin(j: LineJoin);\n get lineCap(): LineCap;\n set lineCap(c: LineCap);\n get font(): string;\n set font(f: string);\n get textAlign(): TextAlign;\n set textAlign(a: TextAlign);\n get textBaseline(): TextBaseline;\n set textBaseline(b: TextBaseline);\n beginPath(): this;\n closePath(): this;\n moveTo(x: number, y: number): this;\n lineTo(x: number, y: number): this;\n quadraticCurveTo(cx: number, cy: number, x: number, y: number): this;\n bezierCurveTo(c1x: number, c1y: number, c2x: number, c2y: number, x: number, y: number): this;\n arc(x: number, y: number, r: number, a0: number, a1: number, ccw?: boolean): this;\n rect(x: number, y: number, w: number, h: number): this;\n roundRect(x: number, y: number, w: number, h: number, r: number): this;\n fill(evenOdd?: boolean): this;\n stroke(): this;\n fillRect(x: number, y: number, w: number, h: number): this;\n strokeRect(x: number, y: number, w: number, h: number): this;\n clearRect(x: number, y: number, w: number, h: number): this;\n fillText(text: string, x: number, y: number, maxWidth?: number): this;\n strokeText(text: string, x: number, y: number, maxWidth?: number): this;\n /** Blit a `Bitmap` (a snapshot from `toBitmap()`) onto this canvas. All coordinates are LOGICAL —\n * including the source sub-rect in the 9-arg form (it's scaled by the bitmap's pixelRatio here).\n * Records a DRAW_IMAGE op, so the blit runs at bake time: keep the Bitmap alive until the next\n * `update()`/`toBitmap()`/`texture()`. Three browser-style forms:\n * drawImage(bmp, dx, dy) — whole bitmap at its natural size\n * drawImage(bmp, dx, dy, dw, dh) — whole bitmap, scaled into dw×dh\n * drawImage(bmp, sx, sy, sw, sh, dx, dy, dw, dh) — a sub-rect of the bitmap, scaled into dw×dh */\n drawImage(img: Bitmap, dx: number, dy: number): this;\n drawImage(img: Bitmap, dx: number, dy: number, dw: number, dh: number): this;\n drawImage(img: Bitmap, sx: number, sy: number, sw: number, sh: number, dx: number, dy: number, dw: number, dh: number): this;\n /** Decode an image source into a standalone `Bitmap` you can blit with `drawImage()` — either an\n * `SvgSource(...)` (rasterized) or a `FetchResponse` holding already-fetched image bytes (decoded).\n * This is async because turning SVG markup / encoded bytes into pixels needs a decode step (on the\n * web, `createImageBitmap` / an `<img>` load); `await` it ONCE, then `drawImage(bitmap, …)` is\n * synchronous and the Bitmap is reusable. The returned Bitmap owns a native surface at the image's\n * natural pixel size (`pixelRatio` 1) — `destroy()` it when done. Typical use:\n * const logo = await canvas.loadImage(SvgSource(svg)) // or: await fetch(url) → the response\n * canvas.drawImage(logo, 0, 0) // sync, blit as often as you like */\n loadImage(source: SvgSourceValue | FetchResponse): Promise<Bitmap>;\n /** Measure `text` in the current font on THIS platform. The one synchronous round-trip. */\n measureText(text: string): CanvasTextMetrics;\n /** Bake and return the 2D texture (created once, then cached). */\n texture(): Texture2D;\n /** Re-rasterize and re-upload to every texture this canvas produced (call after redrawing) — the\n * cached 2D and/or 3D texture, whichever engines this canvas was baked into. */\n update(): this;\n /** Copy the current pixels into a standalone, immutable `Bitmap` — independent of this canvas, so\n * later drawing/`reset()` never touches it. Draw it back with `drawImage()`, export it with\n * `toDataURL()`, or use it to \"flatten\" an ever-growing drawing so re-bakes stay O(1):\n * const snap = canvas.toBitmap()\n * canvas.reset(); canvas.drawImage(snap, 0, 0) // one op replaces the whole history\n * // …keep drawing on top; snap.destroy() once it's been drawn in. */\n toBitmap(): Bitmap;\n /** Encode the current pixels to an image `File` — 'image/png' (default) or 'image/jpeg'. The File\n * is an opaque host buffer handle (`name`/`size` only): append it to a FormData to upload, load it\n * as a texture (`Texture2D.load(file)`), or hand it to a share/save sheet. */\n toFile(name?: string, type?: string): Promise<File>;\n destroy(): void;\n}\n/** Duck-type guard so consumers can accept a Canvas anywhere a texture source is expected. */\nexport declare const isCanvas: (v: unknown) => v is Canvas;\n/** An immutable RGBA8 snapshot of a canvas, produced by `Canvas.toBitmap()`. It owns its own baked\n * surface (a copy), so the source canvas can keep drawing or `reset()` without affecting it. Use it\n * to stamp/blit back (`canvas.drawImage(bitmap, …)`), to export (`bitmap.toDataURL()`), or as a\n * cheap \"layer\" you composite. Call `destroy()` when done — it holds a native surface. */\nexport declare class Bitmap {\n readonly __bitmap: true;\n /** Logical width, matching the Canvas it was captured from (pixelRatio is crispness, not size). */\n readonly width: number;\n readonly height: number;\n readonly pixelRatio: number;\n constructor(surfaceId: number, width: number, height: number, pixelRatio: number);\n /** Device-pixel dimensions of the stored bitmap (`width * pixelRatio`, rounded). */\n get pixelWidth(): number;\n get pixelHeight(): number;\n /** Encode to an image `File` — 'image/png' (default) or 'image/jpeg'. See `Canvas.toFile`. */\n toFile(name?: string, type?: string): Promise<File>;\n /** Free the native surface. The bitmap must not be drawn or encoded afterwards. */\n destroy(): void;\n}\n/** Duck-type guard for a Bitmap (see `isCanvas`). */\nexport declare const isBitmap: (v: unknown) => v is Bitmap;\nexport {};\n","types/core/Aspect.d.ts":"import { Emitter, type EventMap } from \"./events\";\nimport type { InspectorUI } from \"./InspectorUI\";\nimport type { Node } from \"../gl/Node\";\n/** The class object of an aspect — accepted even when its constructor is protected/abstract. */\nexport type AspectCtor<A extends Aspect<any, any>> = abstract new () => A;\n/** The accessor name carried in the aspect's generic. */\nexport type KeyOf<A> = A extends Aspect<infer K, any> ? K : never;\n/** The node kind an aspect targets. */\nexport type TargetOf<A> = A extends Aspect<any, infer P> ? P : never;\n/** `{ name: Aspect }` — the field an aspect contributes to its node. */\nexport type FieldOf<A extends Aspect<any, any>> = {\n [P in KeyOf<A>]: A;\n};\ntype UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (k: infer I) => void ? I : never;\n/**\n * A variable typed as a node KNOWN to carry the given aspect(s). Union, not a tuple — reads as\n * English and mirrors the runtime guard `node.has(Health)`:\n * let boss: With<Sprite, Health | Physics>\n */\nexport type With<N, A extends Aspect<any, any>> = N & UnionToIntersection<A extends any ? FieldOf<A> : never>;\n/**\n * Base for anything that can carry aspects. Extends Emitter, so node kinds get events too. Provides\n * the four verbs; the named accessor (node.physics, node.health, …) is set as an own property at\n * attach time, keyed by the aspect class's runtime `aspect` name.\n */\nexport declare abstract class AspectHost<E extends EventMap = EventMap> extends Emitter<E> {\n /** Attach (and configure) an aspect, or reconfigure it if already present. Returns the node typed\n * as now-having that aspect (so no guard/`?.` is needed afterwards). Rejects a wrong target node. */\n aspect<Self extends TargetOf<A>, A extends Aspect<any, any>>(this: Self, ctor: AspectCtor<A>, opts?: Partial<A>): Self & FieldOf<A>;\n /** Safe access — undefined if the aspect isn't attached. */\n get<A extends Aspect<any, any>>(ctor: AspectCtor<A>): A | undefined;\n /** Existence check AND type guard: inside `if (node.has(Physics))`, `node.physics` is present. */\n has<A extends Aspect<any, any>>(ctor: AspectCtor<A>): this is this & FieldOf<A>;\n /** Detach an aspect (runs its onDetach). Named `removeAspect` so it never collides with the\n * child-management `add`/`remove` semantics some node kinds expose. */\n removeAspect<A extends Aspect<any, any>>(ctor: AspectCtor<A>): this;\n}\n/**\n * Base for everything you attach. `K` = accessor name (extracted by chisel for the runtime). `P` =\n * the target node kind: `this.node` is typed to it, AND attaching to a wrong node is a compile error.\n * Initialize in `onAttach` (the node is set by then) — not a constructor; aspects are created by the\n * engine via `node.aspect()`, never `new`.\n */\nexport declare abstract class Aspect<K extends string, P = Node> {\n /**\n * Opt this aspect class into EDITOR-RUN mode (generators): while a scene is edited, the scene\n * loader constructs the instance (refs resolved, `node`/`generated` set — never `onAttach`) and\n * calls `rebuild()` — again on inspector prop edits and when a `ref()`-referenced node moves.\n * `static editor = { rebuild: true }`.\n */\n static editor?: {\n rebuild?: boolean;\n };\n /**\n * Custom inspector card for this aspect in the scene editor (immediate-mode — see\n * core/InspectorUI.ts): re-runs on every edit/event and emits a widget list. Without it, the\n * editor shows the inferred fields; `ui.auto()` emits those same fields, so a custom inspector\n * usually starts with `ui.auto()` and appends status lines / buttons / dynamic dropdowns:\n *\n * static inspector(ui: InspectorUI, self: MyAspect) {\n * ui.auto()\n * if (ui.button('Randomize')) self.rebuild()\n * }\n */\n static inspector?: (ui: InspectorUI, aspect: any) => void;\n /** The node this aspect is attached to (set at attach time). */\n readonly node: P;\n /**\n * GENERATOR aspects (`static editor = { rebuild: true }`, attached through a scene file): a\n * scene-added container child for the aspect's generated output — `rebuild()` clears and refills\n * it. Provided by the scene loader before `onAttach`/`rebuild` run; nodes `add()`ed to it join\n * the scene's draw set automatically (membership is separate from parenting). Undefined for\n * aspects attached by hand outside scene files. See docs/3d/scene-files.md.\n */\n readonly generated: Node & {\n clear(): void;\n };\n onAttach?(): void;\n onDetach?(): void;\n /**\n * GENERATOR aspects: (re)build the derived output under `this.generated` — must be idempotent\n * (clear, then create). Call it from `onAttach()` for play mode; a class opting in with\n * `static editor = { rebuild: true }` ALSO runs it while a scene is being edited: once at load,\n * and again whenever an inspector prop changes or a `ref()`-referenced node moves.\n */\n rebuild?(): void;\n /**\n * Called every frame while attached (dt = seconds since the last frame). Render-synced: runs in the\n * LATE phase by default — after the physics step + transform sync, right before the frame draws — so\n * reads of `node.worldPosition` are the final drawn position (cameras/followers have no 1-frame lag).\n * Set `updateBeforePhysics = true` (an instance field) to run in the EARLY phase (before the step)\n * instead — for aspects that WRITE velocity/force/kinematic transforms and want the same frame's\n * step to consume them. Cameras/followers READ, so they stay in the default LATE phase.\n */\n update?(dt: number): void;\n /** Run update(dt) in the EARLY phase (before the physics step) rather than the default LATE phase.\n * An instance field (like `updateWhenVisible`) — set it as a class field: `updateBeforePhysics = true`.\n * Use only when you FEED the simulation (velocity/force/kinematic transform). Read once, at attach. */\n updateBeforePhysics: boolean;\n /** Tick order within a phase — ascending; default 0, ties keep attach order. Read once, at attach. */\n order: number;\n /** Opt-in: only run update(dt) while the node is on-screen. NOOP for now — visibility culling isn't\n * wired yet, so every updater ticks regardless; declared so aspects can opt in ahead of it. */\n updateWhenVisible: boolean;\n}\nexport {};\n","types/core/color.d.ts":"export type ColorInput = string | number | readonly [number, number, number] | readonly [number, number, number, number];\nexport declare const Color: {\n /** [r,g,b] in 0..1 — for the 2D engine's float color setters. */\n toRgb01(c: ColorInput): [number, number, number];\n /** [r,g,b,a] in 0..1. */\n toRgba01(c: ColorInput): [number, number, number, number];\n /** 0xRRGGBB packed int — for the 3D engine's color uniforms / skybox. */\n toPackedRgb(c: ColorInput): number;\n /** 0xRRGGBBAA packed int (unsigned). */\n toPackedRgba(c: ColorInput): number;\n /** '#rrggbb' (or '#rrggbbaa' when alpha < 1) — for the 3D material color uniforms. */\n toHexString(c: ColorInput): string;\n};\n","types/core/events.d.ts":"export type EventMap = Record<string, (...args: any[]) => void>;\nexport declare class Emitter<E extends EventMap> {\n private _listeners;\n addEventListener<K extends keyof E>(channel: K, callback: E[K]): void;\n removeEventListener<K extends keyof E>(channel: K, callback: E[K]): void;\n /** Fire all listeners on a channel. Protected: only the owning class emits. */\n protected dispatch<K extends keyof E>(channel: K, ...args: Parameters<E[K]>): void;\n protected hasListeners<K extends keyof E>(channel: K): boolean;\n /** Drop every listener on every channel (used when the owning object is disposed). */\n protected clearListeners(): void;\n}\n","types/core/fields.d.ts":"/** Editor widget kinds the inspector knows how to render. `\"node\"` = a scene-node reference\n * (`ref('name')` in the file, name dropdown + pick-in-viewport in the inspector) — declare it via\n * `static fields` on fields typed `Node | null`; a `Node | null` type annotation is also picked\n * up syntactically by the editor's source scan. `\"asset\"` = a project-asset path (the editor\n * fills the dropdown with the project's GLBs — `ui.asset()` in windows/tools/cards). */\nexport type FieldEditor = \"number\" | \"text\" | \"color\" | \"switch\" | \"select\" | \"vec2\" | \"vec3\" | \"vec4\" | \"node\" | \"asset\";\nexport type FieldMetaEntry = {\n /** Inspector label (default: the field name). */\n label?: string;\n min?: number;\n max?: number;\n step?: number;\n /** Allowed values — renders a dropdown (editor \"select\"). */\n options?: readonly (string | number)[];\n /** Override the editor inferred from the default value. */\n editor?: FieldEditor;\n /** Exclude the field from the inspector. */\n hidden?: boolean;\n};\n/** Declared on an aspect class as `static fields: FieldMeta<MyAspect> = { … }`. All optional. */\nexport type FieldMeta<T = unknown> = {\n [K in Extract<keyof T, string>]?: FieldMetaEntry;\n};\n/** One editable field: key + default value + resolved editor + merged metadata. */\nexport type FieldDescriptor = {\n key: string;\n label: string;\n /** The default value (from a freshly constructed instance; undefined if only declared in meta). */\n value: unknown;\n /** Resolved editor kind; undefined = no editor known (inspector shows it read-only). */\n editor: FieldEditor | undefined;\n min?: number;\n max?: number;\n step?: number;\n options?: readonly (string | number)[];\n};\nexport type AspectClassInfo = {\n /** The accessor name (`static aspect`, injected by chisel for user aspects). */\n name: string;\n className: string;\n fields: FieldDescriptor[];\n /** True for editor-run classes (`static editor` — generators). The editor routes their\n * structural changes through a re-run instead of a live patch. */\n editor?: boolean;\n /** True when the class declares a custom `static inspector(ui, aspect)` card. */\n inspector?: boolean;\n};\n/** Infer the editor widget from a default value's shape. */\nexport declare const inferFieldEditor: (value: unknown) => FieldEditor | undefined;\n/**\n * Enumerate the editable fields of a class: construct a default instance, take its own enumerable\n * non-underscore fields (minus the Aspect base plumbing), infer editors from the default values, and\n * merge the class's optional `static fields` metadata (which can also add keys that have no runtime\n * default, e.g. fields declared without an initializer).\n */\nexport declare const describeFields: (ctor: abstract new () => unknown) => FieldDescriptor[];\n/** Describe an aspect class for the inspector: accessor name + class name + editable fields. */\nexport declare const describeAspect: (ctor: abstract new () => unknown) => AspectClassInfo;\n","types/core/InspectorUI.d.ts":"import type { FieldEditor } from \"./fields\";\n/** One user interaction coming back from the editor panel: the widget's id (+ value for fields). */\nexport type InspectorEvent = {\n id: string;\n value?: unknown;\n};\nexport type InspectorFieldWidget = {\n kind: \"field\";\n id: string;\n /** The bound key — an aspect field (doc-bound) or an editor-state key. */\n key: string;\n label: string;\n editor: FieldEditor | undefined;\n value: unknown;\n /** True = persisted to the scene file by the editor; false = transient editor state. */\n doc: boolean;\n /** True = emitted by `ui.auto()` — the editor may overlay its syntactic hints (options/node). */\n auto?: boolean;\n min?: number;\n max?: number;\n step?: number;\n options?: readonly (string | number)[];\n};\nexport type InspectorWidget = InspectorFieldWidget | {\n kind: \"button\";\n id: string;\n label: string;\n} | {\n kind: \"toolButton\";\n id: string;\n label: string;\n tool: string;\n} | {\n kind: \"header\";\n id: string;\n label: string;\n} | {\n kind: \"info\" | \"warn\";\n id: string;\n text: string;\n};\ntype FieldOpts = {\n label?: string;\n min?: number;\n max?: number;\n step?: number;\n /** Default for EDITOR-STATE keys (doc keys default from the class field). */\n value?: unknown;\n};\n/**\n * The widget builder handed to `static inspector(ui, aspect)` (and to editor windows/tools later).\n * One instance lives per card and persists across runs — it carries the card's editor state.\n */\nexport declare class InspectorUI {\n /** Numeric field (min/max/step render as a slider-style scrub range). */\n number(key: string, opts?: FieldOpts): number;\n /** Alias of `number` — give it min/max/step and the editor renders a scrubable range. */\n slider(key: string, opts?: FieldOpts): number;\n text(key: string, opts?: FieldOpts): string;\n color(key: string, opts?: FieldOpts): string;\n switch(key: string, opts?: FieldOpts): boolean;\n /** Dropdown — `options` may be computed fresh every run (dynamic lists come free). */\n select(key: string, options: readonly (string | number)[], opts?: FieldOpts): string | number;\n vec2(key: string, opts?: FieldOpts): [number, number];\n vec3(key: string, opts?: FieldOpts): [number, number, number];\n vec4(key: string, opts?: FieldOpts): [number, number, number, number];\n /** Scene-node reference (`ref()` fields): name dropdown + pick-in-viewport. Returns the RAW doc\n * value (`{ $ref }` marker or null) — read the resolved live node off the aspect instance. */\n node(key: string, opts?: FieldOpts): unknown;\n /** Project-asset path (the editor renders a dropdown of the project's GLBs). \"\" = none picked. */\n asset(key: string, opts?: FieldOpts): string;\n /** True on the run that consumes this button's click — do the action right there. */\n button(label: string, opts?: {\n id?: string;\n }): boolean;\n /** A toggle that activates/deactivates the named viewport tool (`registerEditorTool`). The\n * editor owns the active-tool state — the click never round-trips into the scene world. */\n toolButton(label: string, tool: string): void;\n header(label: string): void;\n info(text: string): void;\n warn(text: string): void;\n /** Emit the inferred field widgets (all declared aspect fields, or just the named ones) — the\n * zero-ceremony baseline; append custom widgets around it. */\n auto(...keys: string[]): void;\n private _vec;\n private _field;\n}\nexport {};\n","types/core/registry.d.ts":"export declare class Registry<T> {\n private map;\n set(id: number, value: T): void;\n get(id: number): T | undefined;\n delete(id: number): void;\n has(id: number): boolean;\n}\n","types/core/signals.d.ts":"/** Runs every pending effect now instead of waiting for the microtask (test/host hook). */\nexport declare const flushEffects: () => void;\nexport interface Signal<T> {\n value: T;\n /** Read without subscribing the current effect/computed. */\n peek(): T;\n}\nexport interface Computed<T> {\n readonly value: T;\n /** Read without subscribing the current effect/computed (still recomputes if stale). */\n peek(): T;\n}\n/**\n * A reactive value. Reading `.value` inside an `effect`/`computed` (or a function-valued style\n * prop / `UIText` content) subscribes it; writing `.value` re-runs subscribers (batched — once\n * per microtask).\n */\nexport declare function signal<T>(initialValue: T): Signal<T>;\nexport declare function signal<T = undefined>(): Signal<T | undefined>;\n/** A lazily-cached derived value: recomputes on read after any of its dependencies changed. */\nexport declare function computed<T>(fn: () => T): Computed<T>;\n/**\n * Runs `fn` now and again whenever any signal/computed it read changes (batched per microtask).\n * Returns a dispose function; an undisposed effect lives for the rest of the app run.\n */\nexport declare function effect(fn: () => void): () => void;\n/** The shape UINode's Element exposes for binding ownership. */\nexport interface BindingHost {\n}\n","types/g2/autotile.d.ts":"/** A fill entry: an atlas index, or [index, weight] for seeded scatter variants. */\nexport type FillEntry = number | [number, number];\nexport type Dir4 = [number, number, number, number];\n/** One side's tiles: a single index (used for every cell along that side), or — with `size` > 1 —\n * the `size` indices ALONG it (n/s run left→right, w/e run top→bottom). */\nexport type EdgeSlot = number | number[];\n/** A whole `size`×`size` piece: one index (drawn in every cell of the block), or size² indices\n * row-major. Path pieces and parts are blocks — at size 1 they are just a tile. */\nexport type TileBlock = number | number[];\n/** `size`² indices, row-major within the block. */\nexport type FillBlock = number[];\n/** A named element placed BY HAND (a pedestrian crossing in a road, a gate in a fence). It carries\n * its own `id`, so the map stores it like any material — but it CONNECTS as its parent, so the\n * run continues straight through it. Never picked at random: you paint it from the palette, ONE\n * CELL at a time, and the tile is worked out from where that cell sits. */\nexport type TilePart = {\n /** Stable small int, unique across every material and part of the tileset. */\n id: number;\n /** Which run the art is drawn for — 'v' vertical, 'h' horizontal. It also picks the art: the\n * element varies ACROSS the line (a crossing has one tile per lane) and repeats along it, so\n * `tiles` is `size` long, indexed by row for 'h' and by column for 'v'. */\n axis?: \"v\" | \"h\";\n /** The tiles — one index, `size` across the run when `axis` is set, else the size² block. */\n tiles?: TileBlock;\n};\n/** A block variant: the block, or [block, weight] for seeded scatter. */\nexport type BlockEntry = FillBlock | [FillBlock, number];\n/** One transition set of a patch material — the tiles its border shows against a neighbor. */\nexport type PatchSlots = {\n /** Edge line tiles [n, e, s, w] — e.g. `edges[0]` draws where the patch stops toward the top. */\n edges?: [EdgeSlot, EdgeSlot, EdgeSlot, EdgeSlot];\n /** Convex corner tiles [ne, se, sw, nw] — the patch's outside corners. Always one cell. */\n outer?: Dir4;\n /** Concave corner tiles [ne, se, sw, nw] — the notch where two patch arms meet. One cell. */\n inner?: Dir4;\n};\nexport type PatchMaterial = {\n /** Stable small int — what `cells('…')` stores when a map carries Autotile2D. */\n id: number;\n kind: \"patch\";\n /** Editor swatch color ('#4a7c3a'). */\n color?: string;\n /** Block size in cells (default 1). With 2 or 3 the material is classified block-to-block on a\n * lattice anchored at the map origin, `fill` holds size² tiles and each edge `size` tiles. */\n size?: number;\n /** Interior tile — one index, or an ARRAY of scatter variants (each `index` or\n * `[index, weight]`; bare indices weigh 1): `fill: [261, [262, 0.1], [263, 0.05]]`.\n * With `size` > 1 it is instead the row-major BLOCK of size² indices\n * (`fill: [130, 131, 146, 147]`), or a list of such blocks for scatter variants. */\n fill: number | FillEntry[] | BlockEntry[];\n /** Transition sets keyed by the neighboring material's name; '*' = any other neighbor\n * (including empty). Baked packs draw a material fading into a SPECIFIC background. */\n over?: Record<string, PatchSlots>;\n /** Hand-placed elements that connect as this material (see TilePart). */\n parts?: Record<string, TilePart>;\n};\nexport type PathMaterial = {\n id: number;\n kind: \"path\";\n color?: string;\n /** Cells ACROSS the line (default 1). A `size: 2` road is two lanes wide: connectivity runs\n * block to block and every piece below is a 2×2 block instead of one tile. */\n size?: number;\n /** No connections at all. */\n isolated?: TileBlock;\n /** End caps [n, e, s, w] — `ends[0]` connects toward the top only. */\n ends?: [TileBlock, TileBlock, TileBlock, TileBlock];\n /** [vertical (n+s), horizontal (e+w)]. */\n straights?: [TileBlock, TileBlock];\n /** Elbows [ne, se, sw, nw] — `corners[0]` connects top + right. */\n corners?: [TileBlock, TileBlock, TileBlock, TileBlock];\n /** T pieces [n, e, s, w] — `tees[0]` is the tee MISSING the top connection. */\n tees?: [TileBlock, TileBlock, TileBlock, TileBlock];\n /** All four connections. */\n cross?: TileBlock;\n /** Hand-placed elements that connect as this material (see TilePart). */\n parts?: Record<string, TilePart>;\n};\nexport type TileMaterial = PatchMaterial | PathMaterial;\nexport type TilesetDef = {\n /** The atlas image — write `asset('./TileSet.png')`. */\n image: string;\n /** Atlas cell size in image pixels — a number (square) or [w, h]. */\n tile: number | [number, number];\n /** Named materials; names are the editor/`over:` vocabulary, `id`s are what maps store. */\n materials?: Record<string, TileMaterial>;\n};\nexport declare const normalizeFill: (fill: number | FillEntry[]) => [number, number][];\n/** A material's block size — 1 unless it declares `size` (clamped to a positive int). */\nexport declare const blockSize: (mat: TileMaterial) => number;\n/** One cell of a block: a scalar covers the whole block, an array reads row-major. Undefined =\n * unassigned (missing, or the negative sentinel the editor writes for a blank slot). */\nexport declare const blockTile: (block: TileBlock | undefined, n: number, lx: number, ly: number) => number | undefined;\n/** How many tiles a part holds: `size` across the run when it declares an axis, else the block. */\nexport declare const partSlots: (part: TilePart, n: number) => number;\n/** The cell value that draws atlas tile `index` verbatim in a material map. */\nexport declare const rawCell: (index: number) => number;\n/** True for a cell holding a raw atlas tile rather than a material id. */\nexport declare const isRawCell: (v: number) => boolean;\n/** The atlas index behind a raw cell (garbage in, garbage out — guard with isRawCell). */\nexport declare const rawIndex: (v: number) => number;\nexport declare const TILE_INDEX_MASK = 268435455;\n/** The atlas index behind a (possibly oriented) tile value. */\nexport declare const tileIndex: (v: number) => number;\n/** Clockwise quarter-turns (0–3) of a tile value. */\nexport declare const tileTurns: (v: number) => number;\n/** Whether the tile is mirrored horizontally (the mirror applies before the rotation). */\nexport declare const tileFlip: (v: number) => boolean;\n/** True when the value carries any orientation (renderers keep the fast path otherwise). */\nexport declare const tileOriented: (v: number) => boolean;\n/** Build an oriented tile value: `index`, mirrored when `flip`, then `turns` quarter-turns CW. */\nexport declare const packTile: (index: number, turns?: number, flip?: boolean) => number;\n/** The value rotated a further 90° clockwise. */\nexport declare const rot90: (v: number) => number;\n/** The value rotated a further 180°. */\nexport declare const rot180: (v: number) => number;\n/** The value rotated a further 270° clockwise (90° counter-clockwise). */\nexport declare const rot270: (v: number) => number;\n/** The value mirrored horizontally (on screen — existing turns are re-based, group math). */\nexport declare const flipX: (v: number) => number;\n/** The tile a part draws in a cell — indexed ACROSS the run ('h' by row, 'v' by column) so one\n * element covers a lane each and repeats along the run; without an axis it is a plain block. */\nexport declare const partTile: (part: TilePart, n: number, lx: number, ly: number) => number | undefined;\n/** `fill` as weighted BLOCKS of `size`² indices (row-major). Size 1 keeps the scalar/scatter\n * reading; with size > 1 a flat number array is one positional block, an array of arrays is the\n * variant list, and a bare number fills the whole block. Missing entries read as -1. */\nexport declare const fillBlocks: (fill: PatchMaterial[\"fill\"], size?: number) => [number[], number][];\n/**\n * Derive display atlas indices from a material-id grid (row-major, row 0 = top, -1 = empty).\n * Values that match no material id pass through unchanged (so converting maps degrades\n * gracefully); -1 stays -1. Deterministic: same inputs + seed → same output on every platform.\n */\nexport declare const deriveCells: (def: TilesetDef, cols: number, rows: number, cells: ArrayLike<number>, seed?: number) => Int32Array;\n","types/g2/Camera2D.d.ts":"import { Vec2, type Vec2Like } from \"../math/vec\";\nexport declare class Camera2D {\n private _x;\n private _y;\n private _zoom;\n private _rotation;\n private readonly sceneId;\n constructor(sceneId: number);\n get position(): Vec2;\n set position(v: Vec2Like);\n get zoom(): number;\n set zoom(z: number);\n get rotation(): number;\n set rotation(deg: number);\n screenToWorld(screenX: number, screenY: number): Vec2;\n worldToScreen(worldX: number, worldY: number): Vec2;\n}\n","types/g2/cells.d.ts":"export type CellsData = {\n cols: number;\n rows: number;\n /** Row-major tile values (row 0 = the top row), length cols*rows. */\n data: Int32Array;\n};\n/** Encode a grid into a `cells()` payload (the editor / tools side of the codec). */\nexport declare const encodeCells: (cols: number, rows: number, data: ArrayLike<number>) => string;\n/**\n * Decode a `cells('…')` payload into the grid a tilemap block consumes. Scene files call this via\n * the injected global; the value is plain data, so hand-written code may pass any\n * `{ cols, rows, data }` of its own instead (procedural maps).\n */\nexport declare const cells: (payload: string) => CellsData;\n","types/g2/CharacterController2D.d.ts":"import { Aspect } from \"../core/Aspect\";\nimport type { Node2D } from \"./Node2D\";\nexport declare class CharacterController2D extends Aspect<\"controller\", Node2D> {\n static readonly aspect = \"controller\";\n /** Horizontal move speed (world units/s). */\n speed: number;\n /** Jump take-off speed (world units/s). */\n jumpSpeed: number;\n /** Extra probe distance below the body's feet used for the grounded check (world units). */\n groundProbe: number;\n /** Distance from the node origin down to the feet. Defaults to half the sprite height. */\n footOffset?: number;\n private _moveX;\n private _jumpQueued;\n private _grounded;\n /** Horizontal intent in [-1, 1] (e.g. from input). Sticky — set 0 to stop. Applied next frame. */\n move(dir: number): void;\n /** Queue a jump; consumed on the next frame if grounded. */\n jump(): void;\n /** True while standing on something (updated each frame). */\n get grounded(): boolean;\n private get phys();\n onAttach(): void;\n update(_dt: number): void;\n private _spriteHalfHeight;\n}\n","types/g2/defineScene2d.d.ts":"import type { ColorInput } from \"../core/color\";\nimport type { Vec2Like } from \"../math/vec\";\nimport { type AspectEntry, type MakeEntry as SharedMakeEntry } from \"../scene/grammar\";\nimport { Scene2D } from \"./Scene2D\";\nimport { Node2D } from \"./Node2D\";\nimport { Sprite } from \"./Sprite\";\nimport { Tilemap } from \"./Tilemap\";\nimport { SpriteSheet } from \"./SpriteSheet\";\nimport type { SpriteAnimation } from \"./SpriteAnimation\";\nimport type { CellsData } from \"./cells\";\nimport type { With } from \"../core/Aspect\";\nexport type Scene2dEnv = {\n /** Background color — '#5a6b3b', 0x5a6b3b, or [r,g,b] in 0..1. */\n background?: ColorInput;\n /** Texture sampling: 'nearest' (crisp pixel art, engine default) or 'linear'. */\n filter?: \"nearest\" | \"linear\";\n /** Pixel-art crispness: snap the camera to whole screen pixels (seeds CameraFollow's\n * `pixelSnap`, and the initial camera position lands on whole world units). */\n pixelPerfect?: boolean;\n /** Physics world gravity (Y-up: down is negative). Presence configures the world before any\n * body is created — `[0, 0]` for top-down worlds. Omit to leave the world unconfigured. */\n gravity?: Vec2Like;\n};\n/** A sprite node: one named entry of an imported `.sprite.ts` sheet. The sheet is ART only —\n * colliders/bodies are scene semantics: put Shape2D / Physics2D / Trigger2D in `aspects`. */\nexport type SpriteSourceDef = {\n /** The imported sheet handle: `import props from './props.sprite'` … `sheet: props`. */\n sheet: SpriteSheet;\n /** The entry name; omit when the sheet declares exactly one sprite. */\n name?: string;\n /** Start this clip immediately (sliced entries with clips). */\n clip?: string;\n /** Initial facing for `perDirection` clips. */\n direction?: string;\n};\nexport type TilemapSourceDef = {\n /** The tileset image — `asset('./TileSet.png')`. */\n texture: string;\n /** On-screen cell size in world units — a number (square) or [w, h]. */\n tile: number | [number, number];\n /** Atlas grid: how the texture slices into tiles, [atlasCols, atlasRows]. */\n atlas: [number, number];\n /** The map: a `cells('…')` payload — or any `{ cols, rows, data }` of your own. */\n cells: CellsData | {\n cols: number;\n rows: number;\n data: number[] | Int32Array;\n };\n};\n/** A camera marker node: seeds the scene camera's starting position (+ zoom). To MOVE the camera\n * in play, attach `CameraFollow` to the node being followed — not aspects on this marker. */\nexport type Camera2dNodeDef = {\n zoom?: number;\n};\nexport type Scene2dNodeDef = {\n sprite?: SpriteSourceDef;\n tilemap?: TilemapSourceDef;\n camera?: Camera2dNodeDef;\n /** A code-built subtree — `make(factoryFn, { ...literal args })`, factory returns a Node2D. */\n make?: SharedMakeEntry<any, Node2D>;\n position?: Vec2Like;\n /** Degrees, CCW. */\n rotation?: number;\n scale?: Vec2Like | number;\n /** Draw layer (int) — higher renders on top. */\n layer?: number;\n /** Intra-layer depth for non-Y-sorted layers. */\n z?: number;\n /** Sprite tint (sprite nodes only). */\n color?: ColorInput;\n /** Sprite opacity 0..1 (sprite nodes only). */\n opacity?: number;\n flipX?: boolean;\n flipY?: boolean;\n visible?: boolean;\n /** Editor-only: the move gizmo won't target this node (fields still edit). No runtime effect. */\n locked?: boolean;\n aspects?: readonly AspectEntry<any>[];\n children?: Record<string, Scene2dNodeDef>;\n};\nexport type Scene2dCameraDef = {\n position?: Vec2Like;\n zoom?: number;\n};\nexport type Scene2dDef = {\n env?: Scene2dEnv;\n /** Per-layer config, keyed by layer number: `layers: { 1: { ySort: true } }`. */\n layers?: Record<number | string, {\n ySort?: boolean;\n }>;\n /** Starting camera when there's no camera NODE (a camera node wins). */\n camera?: Scene2dCameraDef;\n nodes?: Record<string, Scene2dNodeDef>;\n};\ntype SourceNodeOf<N extends Scene2dNodeDef> = N extends {\n sprite: {\n clip: string;\n };\n} ? Sprite & {\n anim: SpriteAnimation;\n} : N extends {\n sprite: SpriteSourceDef;\n} ? Sprite : N extends {\n tilemap: TilemapSourceDef;\n} ? Tilemap : Node2D;\ntype AspectsOf<N extends Scene2dNodeDef> = N extends {\n aspects: readonly AspectEntry<infer A>[];\n} ? A : never;\ntype NodeOf<N extends Scene2dNodeDef> = [\n AspectsOf<N>\n] extends [never] ? SourceNodeOf<N> : With<SourceNodeOf<N>, AspectsOf<N>>;\ntype UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (k: infer I) => void ? I : never;\ntype ChildMapsOf<T extends Record<string, Scene2dNodeDef>> = {\n [K in keyof T]: T[K] extends {\n children: infer C extends Record<string, Scene2dNodeDef>;\n } ? NodesOf<C> : never;\n}[keyof T];\ntype NodesOf<T extends Record<string, Scene2dNodeDef>> = {\n [K in keyof T]: NodeOf<T[K]>;\n} & ([ChildMapsOf<T>] extends [never] ? unknown : UnionToIntersection<ChildMapsOf<T>>);\nexport type Scene2dNodes<D extends Scene2dDef> = D[\"nodes\"] extends Record<string, Scene2dNodeDef> ? NodesOf<D[\"nodes\"]> : Record<string, Node2D>;\nexport type LoadedScene2d<D extends Scene2dDef> = {\n scene: Scene2D;\n nodes: Scene2dNodes<D>;\n};\nexport declare class Scene2dHandle<D extends Scene2dDef = Scene2dDef> {\n readonly def: D;\n private _loading?;\n constructor(def: D);\n /** Instantiate the scene (idempotent — subsequent calls return the same instance). Does not open. */\n load(): Promise<LoadedScene2d<D>>;\n /** Load and make active (only the active 2D scene renders). */\n open(): Promise<LoadedScene2d<D>>;\n}\n/**\n * Define a 2D scene as data — the default export of a `.scene2d.ts` file. Returns a typed handle:\n * `const { scene, nodes } = await handle.open()` gives `nodes.<name>` typed by its source block\n * (Sprite / Tilemap / Node2D) with its `use(...)`d aspects attached.\n */\nexport declare const defineScene2d: <const D extends Scene2dDef>(def: D) => Scene2dHandle<D>;\nexport {};\n","types/g2/loop.d.ts":"export declare const onUpdate: (callback: (dt: number) => void) => void;\nexport declare const offUpdate: (callback: (dt: number) => void) => void;\nexport declare const ensureAnimEvents: () => void;\nexport declare const ensurePhysicsEvents: () => void;\n","types/g2/Node2D.d.ts":"import { AspectHost } from \"../core/Aspect\";\nimport { Registry } from \"../core/registry\";\nimport { Vec2, type Vec2Like } from \"../math/vec\";\nimport type { ClickEvent, TouchStartEvent } from \"../runtime/touch\";\nexport { Vec2, type Vec2Like };\nexport type Node2DEvents = {\n /** A looping animation clip wrapped around (fires each loop). */\n loopReached: (clip: string) => void;\n /** A non-looping animation clip finished. */\n completed: (clip: string) => void;\n /** A physics contact / sensor overlap began / ended (the other node). */\n enter: (other: Node2D) => void;\n exit: (other: Node2D) => void;\n /** Pointer up over this node's Physics2D shape (a tap/click). */\n click: (ev: ClickEvent<Node2D | null>) => void;\n /** Pointer down on this node's Physics2D shape. Call ev.track(...) to capture the drag. */\n touchstart: (ev: TouchStartEvent<Node2D | null>) => void;\n};\n/** id → Node2D, so host callbacks (animation events) route back to the owning JS object. */\nexport declare const node2dRegistry: Registry<Node2D>;\nexport declare class Node2D extends AspectHost<Node2DEvents> {\n /** Native entity handle. */\n readonly id: number;\n /** Optional debug/editor name (plain JS data — scene2d files stamp their node names here). */\n name?: string;\n protected _x: number;\n protected _y: number;\n protected _rotation: number;\n protected _sx: number;\n protected _sy: number;\n protected _layer: number;\n protected _z: number;\n protected _visible: boolean;\n private _parent;\n private _children;\n constructor(internalId?: number);\n private _pull;\n get x(): number;\n set x(v: number);\n get y(): number;\n set y(v: number);\n get position(): Vec2;\n set position(v: Vec2Like);\n /** Rotation in degrees (CCW). */\n get rotation(): number;\n set rotation(deg: number);\n get scale(): Vec2;\n set scale(v: Vec2Like | number);\n /** Draw layer (int). Higher layers render on top. */\n get layer(): number;\n set layer(v: number);\n /** Intra-layer depth for non-Y-sorted layers (higher z = on top). */\n get z(): number;\n set z(v: number);\n get visible(): boolean;\n set visible(v: boolean);\n get parent(): Node2D | null;\n set parent(p: Node2D | null);\n get children(): readonly Node2D[];\n /** Attach children to this node (each keeps its current world transform). Returns this. */\n add(...children: Node2D[]): this;\n /** Detach a direct child (reparents it to root, keeping its world transform). Returns this. */\n remove(child: Node2D): this;\n /**\n * Reparent this node. `keepWorld` (default true) recomputes the local transform so the on-screen\n * position/rotation/scale is unchanged; pass false to keep the local transform and move with the\n * new parent. Self/descendant parents are rejected natively (no cycles).\n */\n setParent(parent: Node2D | null, keepWorld?: boolean): this;\n /** World-space position (composes all ancestors). */\n get worldPosition(): Vec2;\n /** Convert a world-space point into this node's local space (and back). */\n worldToLocal(p: Vec2Like): Vec2;\n localToWorld(p: Vec2Like): Vec2;\n private _syncLocalFromNative;\n addEventListener<K extends keyof Node2DEvents>(channel: K, callback: Node2DEvents[K]): void;\n destroy(): void;\n}\n","types/g2/Physics2D.d.ts":"import { Aspect } from \"../core/Aspect\";\nimport { Vec2, type Vec2Like } from \"../math/vec\";\nimport { type Node2D } from \"./Node2D\";\nexport type MotionType = \"static\" | \"kinematic\" | \"dynamic\";\nexport interface PhysicsConfig {\n /** Gravity in world units/s² (Y-up: down is negative). Default [0, -980]. */\n gravity?: Vec2Like;\n /** Pixels per meter — tunes Box2D's internal tolerances; you still author in world units. Default 64. */\n pixelsPerMeter?: number;\n /** Solver sub-steps per fixed step. Default 4. */\n subSteps?: number;\n}\n/** Closest raycast hit. */\nexport interface RayHit {\n node: Node2D | null;\n point: Vec2;\n normal: Vec2;\n fraction: number;\n}\nexport declare class Physics2D extends Aspect<\"physics\", Node2D> {\n static readonly aspect = \"physics\";\n /** Default \"dynamic\". */\n motion: MotionType;\n density: number;\n friction: number;\n restitution: number;\n /** Lock rotation (essential for platformer characters). */\n fixedRotation: boolean;\n /** Continuous collision for fast-moving bodies (projectiles). */\n bullet: boolean;\n private _gravityScale;\n private _h;\n /** Native physics body id. 0 until attached, or if the build has no physics support. Mirrors 3D `Physics.id`. */\n get id(): number;\n onAttach(): void;\n onDetach(): void;\n /** Linear velocity in world units/second (fresh Vec2 on read). */\n get velocity(): Vec2;\n set velocity(v: Vec2Like);\n /** Angular velocity in degrees/second. */\n set angularVelocity(degPerSec: number);\n /** Per-body gravity multiplier: 1 = full world gravity, 0 = floats, <0 = repelled. Set at attach\n * time (as an option) or live. */\n get gravityScale(): number;\n set gravityScale(scale: number);\n set linearDamping(d: number);\n set enabled(v: boolean);\n /** Apply an instantaneous impulse (world units) and wake the body. */\n applyImpulse(v: Vec2Like): this;\n /** Apply a continuous force (world units) and wake the body. */\n applyForce(v: Vec2Like): this;\n /** Teleport / drive a kinematic (or dynamic) body to a world position (+ optional rotation degrees). */\n moveTo(p: Vec2Like, deg?: number): this;\n /** Create / reset the physics world. Call once before creating bodies. */\n static configure(config?: PhysicsConfig): void;\n /** Whether this build has physics support (CREATOR_2D_PHYSICS). */\n static get supported(): boolean;\n /** Render interpolation of body transforms between the fixed 60 Hz steps (global; default on). Turn\n * off to save per-frame transform writes when you have many moving bodies / don't need >60 Hz\n * smoothness — bodies then advance in discrete steps. */\n private static _interpolation;\n static get interpolation(): boolean;\n static set interpolation(on: boolean);\n /** Closest body hit by the segment from→to, or null. `node` resolves the hit entity. */\n static raycast(from: Vec2Like, to: Vec2Like): RayHit | null;\n /** Topmost body (solid or sensor) whose shape contains the world point, or null. */\n static overlapPoint(p: Vec2Like): Node2D | null;\n}\n","types/g2/scenarios2d.d.ts":"import { Aspect } from \"../core/Aspect\";\nimport type { Node2D } from \"./Node2D\";\nimport type { Scene2D } from \"./Scene2D\";\n/**\n * Ease the scene camera toward this node every frame (attach it to the player). In a `.scene2d.ts`\n * file the loader wires `scene` automatically; from hand-written code pass it yourself:\n * `hero.aspect(CameraFollow, { scene })`.\n *\n * The eased position accumulates at full precision and only the value PUSHED to the camera is\n * snapped — reading the snapped camera back as the ease-from value would let tiny sub-pixel steps\n * round to zero near settle (the follow would stall a few px off-centre, then jump).\n */\nexport declare class CameraFollow extends Aspect<\"cameraFollow\", Node2D> {\n static readonly aspect = \"cameraFollow\";\n /** The scene2d loader injects the scene into aspects that declare this. */\n static readonly wantsScene = true;\n /** The scene whose camera follows (wired by the scene file loader). */\n scene: Scene2D | null;\n /** Exponential time constant in seconds; smaller = snappier, 0 = pin the node to centre. */\n smooth: number;\n /** Camera offset from the node, in world units. */\n offset: [number, number];\n /** Quantize the camera to whole screen pixels so eased motion never shimmers pixel art.\n * Defaults to the scene's `env.pixelPerfect` (true when unset). */\n pixelSnap: boolean;\n private _x;\n private _y;\n private readonly _grid;\n update(dt: number): void;\n}\n","types/g2/Scene2D.d.ts":"import { type ColorInput } from \"../core/color\";\nimport { Presentable, type PresentOptions } from \"../ui/presentable\";\nimport { type Vec2Like } from \"../math/vec\";\nimport type { ClickEvent, TouchStartEvent } from \"../runtime/touch\";\nimport { Camera2D } from \"./Camera2D\";\nimport { type Node2D } from \"./Node2D\";\nexport type Scene2DOptions = {\n /** Background color — '#10131a', 0x10131a, or [r,g,b]/[r,g,b,a] in 0..1. */\n background?: ColorInput;\n /** Texture sampling for the 2D renderer: `'nearest'` (default — crisp pixel art) or `'linear'`\n * (smooth — for hi-res / non-pixel-art assets). Applied when the scene is opened, so switching\n * scenes restores the active scene's choice. NOTE: this is a GLOBAL renderer setting (one sampler\n * for ALL textures, not per-texture), so the currently-open scene's filter wins. Omit to leave the\n * current setting (engine default is nearest). */\n filter?: 'nearest' | 'linear';\n};\n/** Returned by scene2d.layer(n); chain .ySort() to enable top-down depth sorting for that layer. */\ndeclare class LayerHandle {\n private readonly sceneId;\n private readonly layer;\n constructor(sceneId: number, layer: number);\n /** In this layer, lower-on-screen sprites overlap higher ones (top-down feet sorting). */\n ySort(enabled?: boolean): this;\n}\nexport declare class Scene2D implements Presentable {\n /** Native scene handle. */\n readonly id: number;\n readonly camera: Camera2D;\n private static _active;\n static get active(): Scene2D | null;\n readonly _touchStartListeners: Array<(ev: TouchStartEvent<Node2D | null>) => void>;\n /** Texture filter to (re)assert on open(); the sampler is global, so each scene reclaims it. */\n private readonly _filter?;\n constructor(options?: Scene2DOptions);\n set background(color: ColorInput);\n /** Address a draw layer to configure it, e.g. scene2d.layer(1).ySort(). */\n layer(n: number): LayerHandle;\n /** Topmost visible sprite whose world bounds contain the world point, or null. Body-free\n * hit-test for tap/click picking — pair with camera.screenToWorld(). */\n pick(worldPoint: Vec2Like): Node2D | null;\n /** Scene-level pointer events. The handler fires for every tap/press in the scene, with\n * `ev.target` = the hit Physics2D node (or null). On 'touchstart' you can ev.track(...) a drag. */\n addEventListener(channel: \"click\", callback: (ev: ClickEvent<Node2D | null>) => void): void;\n addEventListener(channel: \"touchstart\", callback: (ev: TouchStartEvent<Node2D | null>) => void): void;\n removeEventListener(channel: \"click\" | \"touchstart\", callback: (ev: any) => void): void;\n add(...nodes: Node2D[]): this;\n remove(...nodes: Node2D[]): this;\n readonly cl: (() => void)[];\n _backButtonCallback?: () => void;\n private _vd?;\n /** Fires when the scene becomes the visible destination (incl. a pop revealing it). */\n onOpen(callback: () => void): this;\n /** Fires when the scene stops being visible (closed, replaced, or covered by a push). */\n onClose(callback: () => void): this;\n onBackPressed(callback: () => void): this;\n /** Make this the active scene — shows it as the current destination (replaces a screen /\n * another scene; only the active scene renders). */\n open(options?: PresentOptions): this;\n close(): this;\n destroy(): void;\n}\nexport {};\n","types/g2/Shape2D.d.ts":"import { Aspect } from \"../core/Aspect\";\nimport { type Vec2Like } from \"../math/vec\";\nimport type { Node2D } from \"./Node2D\";\nexport declare class Shape2D extends Aspect<\"shape\", Node2D> {\n static readonly aspect = \"shape\";\n /** Box half-extents [hw, hh] (world units). */\n box?: Vec2Like;\n /** Circle radius. */\n circle?: number;\n /** Capsule between two local points, with a radius. */\n capsule?: {\n from: Vec2Like;\n to: Vec2Like;\n radius: number;\n };\n /** Thin segment (an edge — for static ground/walls/slopes) between two local points. */\n segment?: {\n from: Vec2Like;\n to: Vec2Like;\n };\n /** Convex polygon, up to 8 local points (a convex hull is computed). */\n polygon?: Vec2Like[];\n /** Local offset of the shape from the node origin. */\n offset?: Vec2Like;\n}\n","types/g2/Sprite.d.ts":"import { type ColorInput } from \"../core/color\";\nimport { Vec2, type Vec2Like } from \"../math/vec\";\nimport { Canvas } from \"../canvas/Canvas\";\nimport { Node2D } from \"./Node2D\";\nimport type { Texture2D } from \"./Texture2D\";\n/** Anything that can back a sprite: a texture, or a Canvas (baked to a texture on assign). */\nexport type TextureSource = Texture2D | Canvas;\nexport type SpriteOptions = {\n texture?: TextureSource;\n /** Pivot, [0,0] = top-left .. [1,1] = bottom-right. Use [0.5, 1] (feet) for Y-sorted depth. */\n anchor?: Vec2Like;\n /** World size; defaults to the texture's pixel dimensions. */\n size?: Vec2Like;\n /** Normalized UV sub-rect [u0,v0,u1,v1]. */\n frame?: [number, number, number, number];\n /** Tint multiplied with the texture. */\n color?: ColorInput;\n opacity?: number;\n layer?: number;\n position?: Vec2Like;\n};\nexport declare class Sprite extends Node2D {\n private _texture?;\n private _anchor;\n private _color;\n private _opacity;\n private _flipX;\n private _flipY;\n private _size;\n constructor(options?: SpriteOptions);\n get texture(): Texture2D | undefined;\n set texture(t: TextureSource | undefined);\n /** Current world size: explicit override if set, else the texture's pixel dimensions (a Canvas-backed\n * sprite defaults to the canvas's LOGICAL size, so pixelRatio is crispness only, not size). */\n get size(): Vec2;\n set size(v: Vec2Like);\n get anchor(): Vec2;\n set anchor(v: Vec2Like);\n /** Set the UV sub-rect (normalized). */\n set frame(uv: [number, number, number, number]);\n /** Set the sub-rect in texture pixels. */\n setFramePx(px: number, py: number, pw: number, ph: number): this;\n get color(): ColorInput;\n set color(c: ColorInput);\n get opacity(): number;\n set opacity(a: number);\n get flipX(): boolean;\n set flipX(v: boolean);\n get flipY(): boolean;\n set flipY(v: boolean);\n}\n","types/g2/SpriteAnimation.d.ts":"import { Aspect } from \"../core/Aspect\";\nimport { type Vec2Like } from \"../math/vec\";\nimport type { Sprite } from \"./Sprite\";\n/** Per-clip frame list, or an object for per-clip fps/loop/direction overrides. */\nexport type Clip = number[] | {\n frames: number[];\n fps?: number;\n loop?: boolean;\n perDirection?: boolean;\n};\nexport declare class SpriteAnimation extends Aspect<\"anim\", Sprite> {\n static readonly aspect = \"anim\";\n /** Grid cell size in texture pixels (defaults to the full texture). */\n size?: [number, number];\n /** Grid columns override — for sheets with padding; defaults to floor(texWidth / cellWidth). */\n cols?: number;\n /** Pixel origin of the grid in the texture — cells index from here (a SpriteSheet region). */\n origin?: [number, number];\n /** Default fps for clips that don't override it. */\n fps: number;\n /** Default loop for clips that don't override it. */\n loop: boolean;\n /** Named clips; frame indices are row-major into the grid. Set via the attach opts. */\n clips: Record<string, Clip>;\n /** Facing names in texture-row order (row i = directions[i]) for `perDirection` clips. */\n directions?: string[];\n private _clipIds;\n private _clipNames;\n private _current;\n private _defined;\n private _queued;\n private _dir;\n onAttach(): void;\n /** (Re)build native clips from `this.clips`. Called on attach; call again after changing clips. */\n define(): this;\n private _define;\n /**\n * Play a clip by name. Re-playing the active clip is a no-op (keeps it running smoothly).\n * For a `perDirection` clip, `dir` picks the facing — a direction name or a movement vector\n * (nearest compass row wins); omitted, the last direction (or the first row) is kept.\n */\n play(name: string, dir?: string | Vec2Like): this;\n stop(): this;\n /** Current facing (last direction resolved by play()), or null before the first directional play. */\n get direction(): string | null;\n set speed(value: number);\n get current(): string | null;\n get frame(): number;\n private _resolveDir;\n}\n","types/g2/SpriteSheet.d.ts":"import { type Vec2Like } from \"../math/vec\";\nimport { Sprite } from \"./Sprite\";\nimport { SpriteAnimation, type Clip } from \"./SpriteAnimation\";\nimport { Texture2D } from \"./Texture2D\";\n/**\n * A named region of the image. Just a rect is a static sprite; `slice` subdivides the rect into an\n * animation grid ([cols, rows] — the cell is rect size / counts); `clips` names frame runs over\n * that grid (local, row-major). A sliced entry with NO clips loops all of its cells in order.\n */\nexport type SheetSprite = {\n /** Pixel rect [x, y, w, h] in the image. */\n rect?: [number, number, number, number];\n /** Subdivide the rect into an animation grid: [cols, rows]. */\n slice?: [number, number];\n /** Playback fps for this sprite's animation (defaults to the sheet fps, then 12). */\n fps?: number;\n /** Named clips over the local grid (see SpriteAnimation). Omit to loop every cell. */\n clips?: Record<string, Clip>;\n /** Facing names in local-row order for `perDirection` clips (compass tokens: S/SE/E/…). */\n directions?: string[];\n /** Overrides the sheet anchor. */\n anchor?: Vec2Like;\n};\nexport type SpriteSheetDef = {\n /** The image URL — write `asset('./sheet.png')`. */\n image: string;\n /** Default pivot for every sprite made from this sheet ([0.5, 1] = feet, for Y-sorted worlds). */\n anchor?: Vec2Like;\n /** Default fps for sliced sprites / clips that don't override it. */\n fps?: number;\n /** The named sprites. */\n sprites?: Record<string, SheetSprite>;\n};\nexport type SpriteMakeOptions = {\n position?: Vec2Like;\n layer?: number;\n /** Overrides the sheet/sprite anchor. */\n anchor?: Vec2Like;\n /** Start this clip immediately (sliced sprites with clips). */\n clip?: string;\n /** Initial facing for `perDirection` clips. */\n direction?: string;\n};\nexport declare class SpriteSheet {\n private _def;\n private _tex;\n private _loading;\n constructor(def: SpriteSheetDef);\n /** The sheet definition (read-only by convention — the editor owns the file). */\n get def(): SpriteSheetDef;\n /** The loaded texture, or null before load() resolves. */\n get texture(): Texture2D | null;\n /** Load the sheet's texture (idempotent). make() starts this automatically. */\n load(): Promise<Texture2D>;\n /** Names of the sheet's sprites. */\n get spriteNames(): string[];\n /** Build a named sprite; starting a clip hands back the animation handle. */\n make(name: string, opts: SpriteMakeOptions & {\n clip: string;\n }): Sprite & {\n anim: SpriteAnimation;\n };\n make(name: string, opts?: SpriteMakeOptions): Sprite;\n /** The pixel rect [x, y, w, h] of a named sprite's REGION (the whole rect, sliced or not). */\n rectOf(name: string): [number, number, number, number] | null;\n private _applyTexture;\n}\n/** Declare a sprite sheet (the default export of a `.sprite.ts` file). */\nexport declare const defineSpriteSheet: (def: SpriteSheetDef) => SpriteSheet;\n","types/g2/Texture2D.d.ts":"import { type FetchResponse, type File } from \"../runtime/fetch\";\nexport declare class Texture2D {\n /** Native texture handle. */\n readonly id: number;\n readonly width: number;\n readonly height: number;\n constructor(id: number, width: number, height: number);\n static fromCanvas(canvas: {\n _bakeSurface(): number;\n width: number;\n height: number;\n pixelRatio: number;\n }): Texture2D;\n static load(source: string | FetchResponse | File): Promise<Texture2D>;\n destroy(): void;\n}\n","types/g2/Tilemap.d.ts":"import { Node2D } from \"./Node2D\";\nimport type { Texture2D } from \"./Texture2D\";\nexport type TilemapOptions = {\n texture: Texture2D;\n /** Map grid size (in tiles). */\n cols: number;\n rows: number;\n /** On-screen cell size in world units — a single number (square) or [w, h]. */\n tile: number | [number, number];\n /** Atlas grid: how the texture is sliced into tiles, [atlasCols, atlasRows]. */\n atlas: [number, number];\n /** Row-major tile indices into the atlas (-1 = empty), length cols*rows. Row 0 is the top row. */\n data: number[] | Int32Array;\n};\nexport declare class Tilemap extends Node2D {\n readonly cols: number;\n readonly rows: number;\n constructor(options: TilemapOptions);\n setTile(x: number, y: number, index: number): this;\n}\n","types/g2/Tileset.d.ts":"import { Aspect } from \"../core/Aspect\";\nimport type { Node2D } from \"./Node2D\";\nimport { type TilesetDef, type TileMaterial } from \"./autotile\";\nexport declare class Tileset {\n private _def;\n constructor(def: TilesetDef);\n /** The tileset definition (read-only by convention — the editor owns the file). */\n get def(): TilesetDef;\n /** Names of the declared materials, in file order. */\n get materialNames(): string[];\n /** A material by name. */\n material(name: string): TileMaterial | undefined;\n /** The cell value maps store for a named material (what you paint / pass in `data`). */\n id(name: string): number | undefined;\n /** Derive display atlas indices from a material-id grid (what Autotile2D does at load). */\n derive(cols: number, rows: number, data: ArrayLike<number>, seed?: number): Int32Array;\n}\n/** Declare a tileset (the default export of a `.tiles.ts` file). */\nexport declare const defineTileset: (def: TilesetDef) => Tileset;\n/**\n * Marks a tilemap node's `cells` as MATERIAL ids of a tileset instead of raw atlas indices:\n * `aspects: [use(Autotile2D, { tileset: world })]`. The scene2d loader derives the display\n * indices (neighbor-mask autotile + seeded scatter, deterministic) before building the tilemap;\n * the aspect itself holds no behavior. Change `seed` to reshuffle scatter variants.\n */\nexport declare class Autotile2D extends Aspect<\"autotile\", Node2D> {\n static readonly aspect = \"autotile\";\n /** The imported `.tiles.ts` handle. */\n tileset: Tileset | null;\n /** Scatter seed — same seed, same map, same result on every platform. */\n seed: number;\n}\n","types/g2/touch.d.ts":"/** Register the host pointer callback once, on the first click/touchstart listener (node or scene). */\nexport declare const ensurePointerEvents: () => void;\n","types/g2/Trigger2D.d.ts":"import { Aspect } from \"../core/Aspect\";\nimport { type Vec2Like } from \"../math/vec\";\nimport type { Node2D } from \"./Node2D\";\nexport declare class Trigger2D extends Aspect<\"trigger\", Node2D> {\n static readonly aspect = \"trigger\";\n private _h;\n /** Native physics body id (0 if no physics support). Mirrors 3D `Trigger.id`. */\n get id(): number;\n onAttach(): void;\n onDetach(): void;\n /** Reposition the trigger zone to a world point. */\n moveTo(p: Vec2Like): this;\n}\n","types/gl/AnimationClip.d.ts":"import { type FetchResponse } from \"../runtime/fetch\";\nimport type { Vec3Like } from \"../math/vec\";\nimport type { QuatLike } from \"../math/quat\";\n/** A keyframe: `[time (s), value]`. */\nexport type ClipKey<V> = [number, V];\nexport type ClipInterpolation = \"linear\" | \"step\";\n/** Curves for one target node (bone name), any subset of the three channels. */\nexport type ClipTrackDef = {\n position?: ClipKey<Vec3Like | [number, number, number]>[];\n rotation?: ClipKey<QuatLike | [number, number, number, number]>[];\n scale?: ClipKey<Vec3Like | [number, number, number]>[];\n interpolation?: ClipInterpolation;\n};\nexport type ClipDef = {\n /** Clip length in seconds — defaults to the last key time across all tracks. */\n duration?: number;\n /** Target node name → its curves. Names bind to bones (or any child node) at Animator attach. */\n tracks: Record<string, ClipTrackDef>;\n};\nexport type ClipInfo = {\n name: string;\n duration: number;\n trackCount: number;\n};\nexport declare class AnimationClip {\n /** Source name (the clip's name inside its file; `\"clip\"` for procedural clips). Informational —\n * an Animator addresses clips by the key YOU give it. */\n readonly name: string;\n /** Length in seconds. */\n readonly duration: number;\n /** Number of animated (node, channel) tracks. */\n readonly trackCount: number;\n private constructor();\n /** Load ONE clip from a GLB: the file's only/first clip, or the one named / at the given index. */\n static load(source: string | FetchResponse, clip?: string | number): Promise<AnimationClip>;\n /** Load EVERY clip of a GLB (library files), keyed by clip name. */\n static loadAll(source: string | FetchResponse): Promise<Record<string, AnimationClip>>;\n /** Build a clip from curves in code — no DCC needed. Keys are `[time, value]`; a track binds to the\n * node of that name when the clip is used by an Animator (bones, or any child node). */\n static from(def: ClipDef): AnimationClip;\n /** A sub-range of this clip as a NEW clip — `[start, end]` seconds of the source, re-timed to 0\n * (`end` defaults to the clip's end; array-slice semantics). Cut a too-long take down to the\n * action, or carve several sub-clips out of one packed timeline:\n *\n * clips: { Kick: kick.slice(0.2, 1.1) }\n *\n * Keys outside the range are dropped and exact boundary values are interpolated in, so the\n * sliced clip starts and ends precisely on the source's pose at the cut points. Everything\n * downstream (blend spaces, events' 0–1 times, root motion, phase sync) sees a normal clip of\n * the new duration. */\n slice(start: number, end?: number): AnimationClip;\n private static _label;\n private static _loadSet;\n}\n","types/gl/Animator.d.ts":"import { Aspect } from \"../core/Aspect\";\nimport { AnimationClip } from \"./AnimationClip\";\nimport type { Node } from \"./Node\";\nimport { Vec3 } from \"../math/vec\";\n/** A position on a layer's blend axis (1D) or plane (2D). */\nexport type BlendPosition = number | readonly [number, number];\nexport type AnimatorPlayOptions = {\n /** Crossfade seconds for BOTH ends (default: `animator.fade`, 0.2). 0 = cut. */\n fade?: number;\n /** Fade-in seconds (overrides `fade`). */\n fadeIn?: number;\n /** One-shots only: fade-back seconds at the END (overrides `fade`). The return fade starts this\n * long BEFORE the clip ends, while it still plays — no freeze-frame on the last pose. On a layer\n * with no blend to return to, an explicit `fadeOut` releases the layer at the end instead of\n * holding the last frame. */\n fadeOut?: number;\n /** Loop the clip (default false for one-shots; blend members always loop). */\n loop?: boolean;\n /** Playback rate for this clip (default 1). */\n speed?: number;\n /** Restart from t=0 even if the clip is already playing (default: restart only if it isn't). */\n restart?: boolean;\n};\nexport type AnimatorLayerOptions = {\n /** Blend space: clip name → position, 1D (`{ idle: 0, run: 6 }`) or 2D (`{ idle: [0,0], fwd: [0,1] }`).\n * Members loop in phase with each other; the layer's `value` picks the mix. */\n blend?: Record<string, BlendPosition>;\n /** A clip to start looping at attach (an ambient layer: breathing, an aim pose). */\n clip?: string;\n /** Bone name(s): the layer drives only these subtrees (`'Spine1'` = upper body). Default: the whole rig. */\n mask?: string | string[];\n /** Blend each clip's DELTA from its own first frame on top of the layers below (lean, breathe, recoil)\n * instead of overriding them. */\n additive?: boolean;\n /** Layer contribution 0–1 (default 1). A layer with nothing playing contributes nothing regardless. */\n weight?: number;\n};\ntype AnimatorEvents = {\n /** A non-looping clip reached its end. */\n completed: (clip: string, layer: string) => void;\n /** A looping clip wrapped around (once per cycle for a blend space). */\n loop: (clip: string, layer: string) => void;\n /** Clip events declared in `events: { clip: { 0.4: 'hit' } }`. */\n [event: string]: (clip: string, layer: string) => void;\n};\n/** One layer of an Animator. The Animator's own play/stop/value/… ARE its `base` layer. */\nexport declare class AnimatorLayer {\n /** Position on the blend axis (number) or plane ([x, y]) — units are whatever `blend` uses. */\n value: BlendPosition;\n /** Layer contribution 0–1. */\n weight: number;\n /** Bone name(s) whose subtrees this layer drives; undefined = the whole rig. */\n mask?: string | string[];\n /** Blend deltas (vs each clip's first frame) on top of the layers below instead of overriding. */\n additive: boolean;\n /** The blend space this layer was declared with (read at attach). */\n blend?: Record<string, BlendPosition>;\n /** The layer's name (`'base'` for the Animator's own). */\n readonly name: string;\n private readonly _a;\n /** The clip names bound on this layer so far. */\n get names(): string[];\n /** Play a clip on this layer (crossfading from whatever it plays). A blend member brings the whole\n * blend back; anything else is a one-shot that returns to the blend when it ends (unless `loop`),\n * or holds its last frame on a layer without a blend (call `stop()`). Resolves when the clip\n * completes or is faded out by a later play()/stop(). */\n play(name: string, options?: AnimatorPlayOptions): Promise<void>;\n /** Fade a clip out (or, with no name, everything on this layer — the blend included). */\n stop(name?: string, options?: {\n fade?: number;\n fadeOut?: number;\n }): this;\n /** Whether the clip is playing on this layer (its clock advancing). No name = anything on this layer. */\n playing(name?: string): boolean;\n /** Current time (s) of a clip's clock. */\n time(name: string): number;\n /** Set a clip's clock (s). Seeking a blend member moves the whole blend (they share one phase). */\n seek(name: string, time: number): this;\n /** 0–1 progress through a clip. */\n progress(name: string): number;\n /** Current contribution (0–1) of a clip to this layer's pose. */\n weightOf(name: string): number;\n private _maskString;\n private _pushLayer;\n /** One-shots: plant a hidden slot event where the fade-back must START so the return crossfade\n * finishes right at the clip's end while it is still moving (no freeze-frame). Loops and blend\n * members get none; `_onSlotEvent` keeps the reactive at-completion fade as the fallback. */\n private _scheduleOut;\n private _resolve;\n /** Blend-space weights for the current value → each member's blendW. 1D: linear between the two\n * neighbours. 2D: gradient-band interpolation (exact at samples, smooth in between, no triangulation). */\n private _computeBlend;\n}\nexport declare class Animator extends Aspect<\"animator\", Node> {\n static readonly aspect = \"animator\";\n /** Clips from other files / procedural clips, keyed by the name you play them with. Read at attach;\n * the table also contains the model's embedded clips under their own names. */\n clips: Record<string, AnimationClip>;\n /** Blend space of the base layer (shorthand for `layers: { base: { blend } }`). Read at attach. */\n blend?: Record<string, BlendPosition>;\n /** Layers on top of `base` (declared in stacking order). Read at attach; `layer(name)` reaches them —\n * and creates an undeclared one on first use. */\n layers?: Record<string, AnimatorLayerOptions>;\n /** Clip events: clip name → { normalizedTime: eventName } → `animator.on(eventName, (clip) => …)`. Read at attach. */\n events?: Record<string, Record<number | string, string>>;\n /** Global playback rate (slow-mo). */\n speed: number;\n /** Freeze every clock (game pause). */\n paused: boolean;\n /** Default crossfade seconds for play()/stop(). */\n fade: number;\n /** Root motion: strip the root bone's horizontal travel from the pose and move the NODE with it\n * instead (or drive its CharacterController — on this node or an ancestor — when it has one; the\n * vertical part stays on the bone, so a jump's height is the clip's) — for clips whose hips actually travel\n * (Mixamo without \"In Place\", lunges, rolls). `true` = auto-detect the root bone (the shallowest bone\n * a clip translates), or a bone name. Read at attach. */\n rootMotion?: boolean | string;\n /** Apply the extracted root motion to the node/controller each frame (default). Set false to read\n * `rootDelta` yourself. */\n applyRootMotion: boolean;\n updateBeforePhysics: boolean;\n order: number;\n private _rootBuf;\n private _rootDelta;\n /** Last frame's root-motion delta in the node's local space (zero without `rootMotion`). */\n get rootDelta(): Vec3;\n private _base;\n private _layers;\n private _all;\n private _lastSpeed;\n private _lastPaused;\n private _weights;\n private _events;\n /** Position on the base layer's blend axis/plane. */\n get value(): BlendPosition;\n set value(v: BlendPosition);\n onAttach(): void;\n onDetach(): void;\n /** The names in the clip table. */\n get names(): string[];\n /** A layer by name (`'base'` is the Animator itself). An undeclared name creates a new override\n * layer on top; configure it through its properties (`mask`, `additive`, `weight`). */\n layer(name: string): AnimatorLayer;\n /** All layers, bottom to top. */\n get layerList(): readonly AnimatorLayer[];\n /** Play a clip on the base layer (crossfading from whatever is playing there). A blend member brings\n * the whole blend back; anything else is a one-shot that returns to the blend when it ends (unless\n * `loop`). Resolves when the clip completes or is faded out by a later play()/stop(). */\n play(name: string, options?: AnimatorPlayOptions): Promise<void>;\n /** Fade a clip out on the base layer — or, with no name, everything on every layer. */\n stop(name?: string, options?: {\n fade?: number;\n }): this;\n /** Whether the clip is playing on the base layer. No name = anything playing on any layer. */\n playing(name?: string): boolean;\n /** Current time (s) of a base-layer clip's clock. */\n time(name: string): number;\n /** Set a base-layer clip's clock (s). */\n seek(name: string, time: number): this;\n /** 0–1 progress through a base-layer clip. */\n progress(name: string): number;\n /** Current contribution (0–1) of a base-layer clip to the pose. */\n weightOf(name: string): number;\n on<K extends keyof AnimatorEvents>(channel: K, cb: AnimatorEvents[K]): this;\n off<K extends keyof AnimatorEvents>(channel: K, cb: AnimatorEvents[K]): this;\n update(dt: number): void;\n /** The CharacterController root motion feeds: on this node, or on the nearest ANCESTOR — the usual\n * rig is a capsule node holding Shape + CharacterController with the model parented under it,\n * shifted down so its feet sit at the capsule's bottom (the controller centers the shape on its node). */\n private _controller;\n /** Root motion (last native frame's delta, node-local, horizontal): move the node, or feed the\n * CharacterController's velocity so it collides/slides like any other movement. */\n private _applyRootMotion;\n private _push;\n}\nexport {};\n","types/gl/Camera.d.ts":"import { Vec3 } from \"../math/vec\";\nimport { Node } from \"./Node\";\nimport { Ray } from \"./Ray\";\n/** Projection every host starts a scene with (creator-gl scene.cpp / the lite core agree on these). */\nexport declare const CAMERA_DEFAULTS: {\n fov: number;\n near: number;\n far: number;\n};\nexport declare class Camera extends Node {\n private _sceneId;\n /** Live projection matrix (updated by the host when the viewport/fov changes). */\n readonly projectionMatrix: Float32Array<ArrayBuffer>;\n private _fov;\n private _near;\n private _far;\n /** Stay quiet until the app actually sets something — hosts may be configured with their own\n * defaults (the headless core takes a `fov` option) and a blind push would overwrite them. */\n private _projSet;\n /** Vertical field of view in degrees (default 60) — a smaller angle is a longer lens. */\n get fov(): number;\n set fov(degrees: number);\n get horizontalFov(): number;\n /** Near clip distance (default 0.01) — nothing closer than this draws. */\n get near(): number;\n set near(distance: number);\n /** Far clip distance / view range (default 1000) — geometry past it is culled. Shadows keep\n * their own (shorter) range, so a long view distance doesn't cost shadow sharpness. */\n get far(): number;\n set far(distance: number);\n /** Set any of fov / near / far in one call: `camera.setProjection({ fov: 45, far: 5000 })`. */\n setProjection(projection: {\n fov?: number;\n near?: number;\n far?: number;\n }): this;\n /** Hosts that predate the call keep the fixed defaults (older wasm / native builds). */\n private _applyProjection;\n get displaySize(): [number, number];\n /** World-space ray direction through a screen pixel. */\n getViewDirection(screenX: number, screenY: number): Vec3;\n /** A pick ray from the camera through a screen pixel. */\n getRay(screenX: number, screenY: number): Ray;\n}\n","types/gl/CharacterController.d.ts":"import { Aspect } from \"../core/Aspect\";\nimport { Vec3 } from \"../math/vec\";\nimport type { Node } from \"./Node\";\nexport declare class CharacterController extends Aspect<\"controller\", Node> {\n static readonly aspect = \"controller\";\n /** Horizontal move speed (world units/s). */\n speed: number;\n /** Jump take-off speed (world units/s). */\n jumpSpeed: number;\n /** Character-tuned gravity (world units/s²), separate from the world gravity — usually stronger for\n * snappier feel. Applied to the vertical velocity each frame. */\n gravity: number;\n /** Max ground slope (degrees) the character treats as walkable. Set before attach. */\n maxSlope: number;\n updateBeforePhysics: boolean;\n private _charId;\n private _mx;\n private _mz;\n private _jumpQueued;\n private _vy;\n private _ex;\n private _ez;\n onAttach(): void;\n onDetach(): void;\n /** Native character id (0 until attached / no physics support). */\n get id(): number;\n /** Horizontal move intent; each component in [-1, 1] (e.g. from input). Sticky — set 0 to stop. */\n move(x: number, z: number): void;\n /** Queue a jump; consumed on the next frame if grounded. */\n jump(): void;\n /** True while standing on walkable ground (OnGround). */\n get grounded(): boolean;\n /** Ground state: 0 on-ground, 1 on-steep-slope, 2 touching-but-unsupported, 3 in-air. */\n get groundState(): number;\n /** Current velocity (world units/s, fresh Vec3). */\n get velocity(): Vec3;\n /** Teleport to a world position (clears vertical velocity). */\n teleport(x: number, y: number, z: number): this;\n update(dt: number): void;\n}\n","types/gl/controls.d.ts":"import type { Node } from \"./Node\";\nimport type { Scene } from \"./Scene\";\nexport type ControlsOptions = {\n /** Smallest uniform scale the pinch gesture allows (default 0.08). */\n minScale?: number;\n /** Largest uniform scale the pinch gesture allows (default 2). */\n maxScale?: number;\n /** One-finger drag moves the target across the ground plane (default true). */\n pan?: boolean;\n /** Two-finger pinch scales the target (default true). */\n pinch?: boolean;\n /** Two-finger twist rotates the target around its Y axis (default true). */\n twist?: boolean;\n};\n/** Returned by `addControls` — call `remove()` to detach the gesture listeners. */\nexport type ControlsHandle = {\n remove(): void;\n};\nexport declare const attachControls: (scene: Scene, target: Node, options?: ControlsOptions) => ControlsHandle;\n","types/gl/Geometry.d.ts":"import { type Vec3Like } from \"../math/vec\";\nexport type MeshKind = \"triangles\" | \"vertices\" | \"edges\";\nexport declare class Geometry {\n vertices: Float32Array;\n normals: Float32Array;\n indices: Uint16Array;\n uv: Float32Array;\n constructor(vertices: Float32Array, normals: Float32Array, indices: Uint16Array, uv: Float32Array);\n translate(x: number, y: number, z: number): this;\n scale(x: number, y: number, z: number): this;\n scaleUV(x: number, y: number): this;\n set kind(kind: MeshKind);\n static box(): Geometry;\n static sphere(options?: SphereOptions): Geometry;\n static cylinder(options?: CylinderOptions): Geometry;\n static plane(options?: PlaneOptions): Geometry;\n}\nexport type SphereOptions = {\n radius?: number;\n widthSegments?: number;\n heightSegments?: number;\n};\nexport type CylinderOptions = {\n radius?: number;\n radiusTop?: number;\n radiusBottom?: number;\n edges?: number;\n smooth?: boolean;\n};\nexport type PlaneOptions = {\n normal?: Vec3Like;\n};\n","types/gl/IK.d.ts":"import { Aspect } from \"../core/Aspect\";\nimport { type Vec3Like } from \"../math/vec\";\nimport type { Node } from \"./Node\";\ntype Target = Node | Vec3Like;\n/** Two-bone analytic IK (limbs). Attach to the END bone: `foot.aspect(IK.TwoBone, { target })`\n * solves upper (grandparent) + mid (parent) so the end reaches `target`; `pole` steers the bend\n * (knee/elbow) — a Node or world point. */\ndeclare class TwoBone extends Aspect<\"ik\", Node> {\n static readonly aspect = \"ik\";\n /** Where the end bone should be (Node or world position). */\n target?: Target;\n /** Bend hint — the mid joint is pulled toward it (Node or world position). */\n pole?: Target;\n /** 0–1 contribution (blend in/out, e.g. foot planting only while grounded). */\n weight: number;\n /** Solve every frame (default). Set false to drive `solve()` yourself. */\n enabled: boolean;\n update(): void;\n /** One solve at the current pose. Safe to call manually (e.g. from a later-ordered aspect). */\n solve(): void;\n}\n/** Aim a bone at a target (head / eyes / turret). Attach to the bone itself:\n * `head.aspect(IK.LookAt, { target: camera, limit: 70 })`. `axis` is the bone's LOCAL forward\n * (the direction that should point at the target) — rigs differ; default −Z, Mixamo heads look\n * along +Z of the head bone in most exports, so pass `axis: [0, 0, 1]` there if it faces backwards. */\ndeclare class LookAt extends Aspect<\"lookAt\", Node> {\n static readonly aspect = \"lookAt\";\n target?: Target;\n /** The bone's local axis that should point at the target. */\n axis: Vec3Like;\n /** Max deflection from the animated direction, in degrees (default 80). */\n limit: number;\n /** 0–1 contribution. */\n weight: number;\n enabled: boolean;\n update(): void;\n solve(): void;\n}\n/** Inverse kinematics aspects — attach to bones (see file header). */\nexport declare const IK: {\n TwoBone: typeof TwoBone;\n LookAt: typeof LookAt;\n};\nexport type IKTwoBone = TwoBone;\nexport type IKLookAt = LookAt;\nexport {};\n","types/gl/Light.d.ts":"import { type ColorInput } from \"../core/color\";\nimport type { Vec3Like } from \"../math/vec\";\nimport { Node } from \"./Node\";\nexport type SunOptions = {\n /** Light direction (points where the light travels). Defaults to a typical key-light angle. */\n direction?: Vec3Like;\n /** Luminous intensity. */\n intensity?: number;\n color?: ColorInput;\n /**\n * Shadow quality (default 1):\n * 0 - no shadows\n * 1 - standard (1024 shadow map, hard PCF edges)\n * 2 - high (2048 + stable, soft contact-hardening edges)\n * 3 - best (4096 + stable, PCSS soft shadows)\n * Higher values cost more GPU/memory.\n */\n shadowsQuality?: 0 | 1 | 2 | 3;\n};\nexport declare class Light extends Node {\n /** A directional sun light. */\n static sun(options?: SunOptions): Light;\n}\n","types/gl/Material.d.ts":"import { type ColorInput } from \"../core/color\";\nimport { type FetchResponse } from \"../runtime/fetch\";\nimport { Texture } from \"./Texture\";\nimport type { Canvas } from \"../canvas/Canvas\";\ntype UniformValue = string | Texture | number | boolean | number[] | Float32Array | null;\nexport type MaterialColorOptions = {\n color?: ColorInput;\n map?: Texture | Canvas | null;\n};\n/** `Material.particles` options — the default point-sprite material for particle systems. */\nexport type ParticlesMaterialOptions = {\n /** Sprite texture — a single image or a flipbook sheet of frames. Unset = soft round dot. */\n map?: Texture | null;\n /** Flipbook grid: `N` = an N×N sheet, `[cols, rows]` = a non-square one. Frames run\n * left-to-right, top-to-bottom; drive the index via `particles.frame`. Default 1. */\n sheet?: number | [number, number];\n /** Extra brightness multiplier for a glow look (0 = off). */\n emissive?: number;\n /** Compositing: `\"alpha\"` (default — smoke, dust) or `\"add\"` (fire, sparks, magic). */\n blend?: \"alpha\" | \"add\";\n /** Soft radial falloff toward the sprite edge. Defaults to true without a map, false with one. */\n soft?: boolean;\n /** How each particle is drawn: `'point'` (default — GPU point sprites, cheapest), `'quad'`\n * (real camera-facing quads — no driver size cap, geometric rotation), or `'stretch'`\n * (quads stretched along velocity — sparks, rain, speed streaks). `'ribbon'` is what `Trail`\n * uses internally. */\n render?: \"point\" | \"quad\" | \"stretch\" | \"ribbon\";\n /** (`render: 'stretch'`) extra sprite length in world units per unit of speed:\n * length = size + stretch·|velocity|. Default 0.05. */\n stretch?: number;\n};\n/** `Material.lit` options — PBR scalars on top of the color/map pair. */\nexport type LitMaterialOptions = MaterialColorOptions & {\n /** Perceptual roughness, 0 (mirror) … 1 (matte). Unset = the shader's default. */\n roughness?: number;\n /** Metallic factor, 0 (dielectric) … 1 (metal). Unset = the shader's default. */\n metallic?: number;\n};\nexport declare class Material {\n readonly shader: FetchResponse | \"unknown\";\n readonly uniforms: Record<string, UniformValue>;\n private _colorKey;\n private _useMapFlag;\n constructor(shader: FetchResponse | number);\n /** Set a uniform (chainable). */\n set(key: string, value: UniformValue): this;\n set color(c: ColorInput);\n set map(value: Texture | Canvas | null);\n /** PBR lit material. */\n static lit(options?: LitMaterialOptions): Material;\n /** Unlit (flat) material. */\n static unlit(options?: MaterialColorOptions): Material;\n /** Default particle material — camera-facing point sprites with tint/opacity/rotation/flipbook\n * driven by the particle curves. Uniforms all default to 0 on a fresh instance, so every look\n * knob is primed here; JS writes after construction override them. */\n static particles(options?: ParticlesMaterialOptions): Material;\n /** Material that samples a VideoPlayer's texture. */\n static video(map?: Texture): Material;\n /** Shadow-catcher material (transparent except where shadows fall). */\n static shadow(color?: ColorInput): Material;\n /** Load a custom compiled shader (.mat URL) as a material. */\n static load(url: string): Promise<Material>;\n}\nexport {};\n","types/gl/Mesh.d.ts":"import { type Vec3Like } from \"../math/vec\";\nimport { Geometry, type CylinderOptions, type PlaneOptions, type SphereOptions } from \"./Geometry\";\nimport { Material } from \"./Material\";\nimport { Node } from \"./Node\";\n/** Common transform/render options every primitive factory accepts. */\nexport type MeshOptions = {\n material?: Material;\n position?: Vec3Like;\n eulerAngles?: Vec3Like;\n scale?: Vec3Like | number;\n name?: string;\n castShadows?: boolean;\n receiveShadows?: boolean;\n};\nexport declare class Mesh extends Node {\n private _geometry?;\n private _materials;\n constructor(geometry?: Geometry, material?: Material);\n get geometry(): Geometry | undefined;\n get material(): Material;\n set material(m: Material);\n setMaterial(material: Material, index?: number): this;\n getMaterial(index?: number): Material | null;\n set culling(v: boolean);\n set castShadows(v: boolean);\n set receiveShadows(v: boolean);\n static box(options?: MeshOptions & {\n size?: Vec3Like | number;\n }): Mesh;\n static sphere(options?: MeshOptions & SphereOptions): Mesh;\n static cylinder(options?: MeshOptions & CylinderOptions): Mesh;\n static plane(options?: MeshOptions & PlaneOptions): Mesh;\n /** Wrap a custom Geometry. */\n static from(geometry: Geometry, options?: MeshOptions): Mesh;\n}\n","types/gl/Model.d.ts":"import { type FetchResponse } from \"../runtime/fetch\";\nimport { Node } from \"./Node\";\nimport { ModelAnimation } from \"./ModelAnimation\";\nexport declare class Model extends Node {\n /** GLB skeletal animation — always present on a Model. */\n readonly anim: ModelAnimation;\n constructor(internalId: number);\n /** Duplicate this model — a deep copy of the GLB (meshes, skeleton, animation clips), attached to\n * the same parent and scene and sharing this model's current transform. The clone has its own\n * independent animation state (reach it via clone.anim). Mirrors Model.load's culling default. */\n clone(): Model;\n /** Load a GLB model. Returns its root as a Model; play its baked clips via model.anim. */\n static load(source: string | FetchResponse, options?: {\n culling?: boolean;\n onProgress?: (p: {\n loaded: number;\n total?: number;\n }) => void;\n }): Promise<Model>;\n}\n","types/gl/ModelAnimation.d.ts":"import { Aspect } from \"../core/Aspect\";\nimport { AnimationClip } from \"./AnimationClip\";\nimport type { Model } from \"./Model\";\nexport declare class ModelAnimation extends Aspect<\"anim\", Model> {\n static readonly aspect = \"anim\";\n private _playing;\n private _clip;\n private _speed;\n private _loop;\n private _suspended;\n private _clips?;\n onAttach(): void;\n /** The clips baked into the glb, as AnimationClip objects (usable in an Animator's clip table —\n * e.g. share one model's baked clip with another model of the same rig). */\n get clips(): AnimationClip[];\n private _blocked;\n get playing(): boolean;\n set playing(value: boolean);\n /** Play a clip by name or index. Chainable. */\n play(clip?: string | number, options?: {\n loop?: boolean;\n }): this;\n stop(): this;\n get loop(): boolean;\n set loop(v: boolean);\n get speed(): number;\n set speed(v: number);\n get time(): number;\n set time(v: number);\n}\n","types/gl/Node.d.ts":"import { AspectHost } from \"../core/Aspect\";\nimport { Registry } from \"../core/registry\";\nimport { Vec3, type Vec3Like } from \"../math/vec\";\nimport { Quat, type QuatLike } from \"../math/quat\";\nimport { Mat4, type Mat4Like } from \"../math/mat4\";\nimport type { Geometry } from \"./Geometry\";\nimport type { ClickEvent, TouchStartEvent } from \"../runtime/touch\";\n/** id → Node, so host callbacks (touch hits, animation events) route back to the owning object. */\nexport declare const nodeRegistry: Registry<Node>;\nexport type NodeEvents = {\n click: (ev: ClickEvent<Node | null>) => void;\n touchstart: (ev: TouchStartEvent<Node | null>) => void;\n /** A looping GLB animation clip wrapped around. */\n loopReached: (clip: number) => void;\n /** A non-looping GLB animation clip finished. */\n completed: (clip: number) => void;\n /** AR anchors only (`scene.root` / `scene.createAnchor()`): the anchor began tracking. */\n track: () => void;\n /** AR anchors only: the anchor lost tracking. */\n untrack: () => void;\n /** A physics contact/trigger overlap began (the other body's node). Needs a Shape + Physics/Trigger. */\n enter: (other: Node) => void;\n /** A physics contact/trigger overlap ended. */\n exit: (other: Node) => void;\n};\nexport declare class Node extends AspectHost<NodeEvents> {\n /** Native entity handle. */\n readonly id: number;\n /** AR anchors only — whether the anchor is currently being tracked. Kept in step with the\n * 'track' / 'untrack' events; `false` for any non-anchor node. */\n isTracked: boolean;\n private _matrix?;\n private _lastSync;\n private _syncFrame;\n private _worldMatrix?;\n private _scaleCache?;\n private _boneCache?;\n constructor(internalId?: number);\n /** Geometry, if this node is a Mesh (used by physics auto-shape). Overridden by Mesh. */\n get geometry(): Geometry | undefined;\n get name(): string;\n set name(value: string);\n get visible(): boolean;\n set visible(value: boolean);\n private _sync;\n get matrix(): Mat4;\n set matrix(m: Mat4Like);\n get worldMatrix(): Mat4;\n set worldMatrix(m: Mat4Like);\n get position(): Vec3;\n set position(v: Vec3Like);\n get x(): number;\n set x(v: number);\n get y(): number;\n set y(v: number);\n get z(): number;\n set z(v: number);\n get scale(): Vec3;\n set scale(v: Vec3Like | number);\n get quaternion(): Quat;\n set quaternion(v: QuatLike);\n get eulerAngles(): Vec3;\n set eulerAngles(v: Vec3Like);\n get forward(): Vec3;\n get worldPosition(): Vec3;\n get worldScale(): Vec3;\n get worldQuaternion(): Quat;\n get worldEulerAngles(): Vec3;\n get parent(): Node | null;\n get children(): Node[];\n get childCount(): number;\n getChild(index: number): Node | null;\n /** Parent the given nodes under this one. */\n add(...children: Node[]): this;\n setParent(parent: Node | null, worldPositionStays?: boolean): this;\n traverse(callback: (node: Node) => void): void;\n /** Find a descendant by name — bones of a loaded Model included (`hero.bone('RightHand').add(sword)`).\n * Exact name first, then the part after the last `:` / `|` (Mixamo `mixamorig:Hips` matches `Hips`).\n * Cached per name; null if absent. */\n bone(name: string): Node | null;\n /** Orient the node so the given axis (default \"-z\", \"forward\") points at a world point. */\n lookAt(point: Vec3Like, mode?: \"z\" | \"-z\" | \"x\" | \"-x\" | \"y\" | \"-y\", ortho?: Vec3Like): this;\n addEventListener<K extends keyof NodeEvents>(channel: K, callback: NodeEvents[K]): void;\n destroy(): void;\n}\n","types/gl/Noise.d.ts":"export declare class Noise {\n private readonly _id;\n constructor();\n /** Sample 2D noise. */\n get(x: number, y: number): number;\n /** Sample 3D noise. */\n get3d(x: number, y: number, z: number): number;\n private _frequency;\n get frequency(): number;\n set frequency(v: number);\n private _octaves;\n get octaves(): number;\n set octaves(v: number);\n private _fractalLacunarity;\n get fractalLacunarity(): number;\n set fractalLacunarity(v: number);\n private _fractalGain;\n get fractalGain(): number;\n set fractalGain(v: number);\n}\n","types/gl/Particles.d.ts":"import { type ColorInput } from \"../core/color\";\nimport { type Vec3Like } from \"../math/vec\";\nimport { Material, type ParticlesMaterialOptions } from \"./Material\";\nimport { Node } from \"./Node\";\ntype Range<T> = T | {\n min: T;\n max: T;\n};\nexport declare class CurveBuilder {\n private _kind;\n private _lo;\n private _hi;\n private _stops;\n constructor(base: Range<number>, mode: \"multiply\" | \"add\");\n /** Curve value at birth (t = 0). Must come before any other stop. */\n from(v: Range<number>): this;\n /** Curve value at `t` (0..1 of the particle's life). Stops must be added in ascending t order. */\n via(t: number, v: Range<number>): this;\n /** Curve value at death (t = 1). */\n to(v: Range<number>): this;\n /** The classic opacity envelope: rise over the first `fadeIn`, fall over the last `fadeOut`. */\n fade(fadeIn?: number, fadeOut?: number): this;\n /** The PARAM_CURVE record payload (sans slot): [kind, baseLo, baseHi, n, (t, lo, hi)×n]. */\n get _data(): Float32Array;\n}\nexport declare class ColorCurveBuilder {\n private _lo;\n private _hi;\n private _stops;\n constructor(base: Range<ColorInput>);\n /** Curve color at birth (t = 0). Must come first. The curve multiplies the base color. */\n from(c: Range<ColorInput>): this;\n /** Curve color at `t` (0..1 of the particle's life), in ascending t order. */\n via(t: number, c: Range<ColorInput>): this;\n /** Curve color at death (t = 1). */\n to(c: Range<ColorInput>): this;\n /** The COLOR_CURVE record payload: [baseLo rgba, baseHi rgba, n, (t, lo rgba, hi rgba)×n]. */\n get _data(): Float32Array;\n}\n/** A value curve over each particle's lifetime. Default mode `multiply` (the curve scales the\n * base); `add` offsets it instead. */\nexport declare const curve: (base?: Range<number>, mode?: \"multiply\" | \"add\") => CurveBuilder;\n/** A color curve over each particle's lifetime — always multiplies the base color. */\nexport declare const colorCurve: (base?: Range<ColorInput>) => ColorCurveBuilder;\nexport type ParticleValue = Range<number> | CurveBuilder | {\n _data: Float32Array;\n};\nexport type ParticleColor = ColorInput | {\n min: ColorInput;\n max: ColorInput;\n} | ColorCurveBuilder | {\n _data: Float32Array;\n};\ntype VelocityValue = {\n speed?: Range<number>;\n /** Cone half-angle in radians — jitter the launch direction uniformly within it. */\n spread?: number;\n /** Asymmetric jitter: two angles (u, v — the x/y components) in radians. */\n randomizeAngle?: {\n min: Vec3Like;\n max: Vec3Like;\n };\n} & ({\n from: Vec3Like;\n} | {\n to: Vec3Like;\n} | {\n dir: Vec3Like;\n} | {});\ntype Shape = {\n type: \"point\";\n v: Vec3Like;\n} | {\n type: \"box\";\n min: Vec3Like;\n max: Vec3Like;\n} | {\n type: \"circle\";\n center: Vec3Like;\n radius: number;\n};\ntype Noise = {\n strength?: number;\n frequency?: number;\n speed?: number;\n};\nexport type ParticlesOptions = ParticlesMaterialOptions & {\n /** Custom draw material. Unset = the default point-sprite material, configured by the\n * `ParticlesMaterialOptions` sugar (map/sheet/emissive/blend/soft) — which is ignored\n * when an explicit material is passed. */\n material?: Material;\n /** Particle pool capacity (default 1000). */\n maxParticles?: number;\n /** Particles emitted per second. */\n rate?: number;\n /** Simulation space. `'local'` (default) — particles ride the node's transform; `'world'` —\n * each particle stays where it was born as the emitter moves on (trails: drift smoke, mud,\n * wake). Switching at runtime resets live particles. */\n space?: \"local\" | \"world\";\n /** Fraction (usually 0..1) of the emitter's own velocity added to each particle at spawn —\n * smoke \"thrown\" off a moving car. Takes effect with `space: 'world'`. */\n inheritVelocity?: number;\n /** Particles emitted per world unit the emitter MOVES, on top of `rate`, with spawn points\n * spread evenly along the path — trail density independent of speed, no per-frame clumps.\n * Meant for `space: 'world'`. */\n rateOverDistance?: number;\n shape?: Shape;\n startVelocity?: Vec3Like | VelocityValue;\n /** Downward acceleration, world units/s² — positive pulls particles DOWN (sugar for\n * `acceleration: [0, -g, 0]`). */\n gravity?: number;\n /** Constant acceleration vector (gravity, wind, …). Wins over `gravity` when both are set. */\n acceleration?: Vec3Like;\n drag?: number;\n lifetime?: Range<number>;\n color?: ParticleColor;\n /** World-unit diameter (alias of custom[0]). Default 1. */\n size?: ParticleValue;\n /** Radians (alias of custom[1]). */\n rotation?: ParticleValue;\n /** Per-particle opacity 0..1 (alias of custom[2]). Default 1. */\n opacity?: ParticleValue;\n /** Flipbook frame index (alias of custom[3]). With `sheet` set and no explicit frame, the\n * default is one full sheet cycle over each particle's lifetime, starting at `startFrame`. */\n frame?: ParticleValue;\n /** Where the default flipbook cycle begins: `'random'` (default — desynchronized loops like\n * fire/smoke) or a frame index (`0` plays the sheet in order — explosions, one-shot bursts).\n * Only shapes the default; an explicit `frame` wins. */\n startFrame?: number | \"random\";\n noise?: Noise | null;\n /** Fixed random seed for deterministic tests. */\n seed?: number;\n};\nexport declare class Particles extends Node {\n private _material;\n /** Custom curve-param slots (0..3); size/rotation/opacity/frame alias slots 0-3. */\n readonly custom: ParticleValue[];\n constructor(options?: ParticlesOptions);\n /** Emit `count` particles immediately (a burst). */\n spawn(count: number): this;\n private _send;\n set rate(val: number);\n /** `'world'` leaves particles behind where they were born (trails). Switching resets live ones. */\n set space(val: \"local\" | \"world\");\n set inheritVelocity(val: number);\n set rateOverDistance(val: number);\n set shape(shape: Shape);\n set startVelocity(val: Vec3Like | VelocityValue);\n /** Positive pulls particles down — sugar for `acceleration = [0, -g, 0]`. */\n set gravity(val: number);\n set acceleration(a: Vec3Like);\n set drag(val: number);\n set seed(val: number);\n set lifetime(val: Range<number>);\n set size(val: ParticleValue);\n set rotation(val: ParticleValue);\n set opacity(val: ParticleValue);\n set frame(val: ParticleValue);\n set color(value: ParticleColor);\n get material(): Material;\n set material(material: Material);\n set noise(noise: Noise | null);\n}\n/** `Trail` options. The look options (map/sheet/emissive/blend/soft) come from\n * `ParticlesMaterialOptions`, same as `Particles`. */\nexport type TrailOptions = Omit<ParticlesMaterialOptions, \"render\" | \"stretch\"> & {\n /** Seconds each trail point lives — the trail's length in time. Default 0.5. */\n time?: number;\n /** Strip width in world units; a curve tapers it over each point's life (head → tail).\n * Default 0.1. */\n width?: ParticleValue;\n /** Minimum emitter movement (world units) between recorded points. Default 0.05. */\n minDistance?: number;\n /** Point capacity (default 128). */\n maxPoints?: number;\n color?: ParticleColor;\n /** Opacity along the trail. Defaults to fading the tail out (`curve().to(0)`). */\n opacity?: ParticleValue;\n};\n/** A ribbon strip that follows this node through the world — sword swings, skid marks, missile\n * trails. Attach it to (or under) the moving node and just move; points are laid down per\n * `minDistance` of movement, live for `time` seconds, and the strip stays glued to the node at\n * its head. Width/opacity/color accept the same curves as `Particles`, evaluated over each\n * point's life — i.e. along the trail from head (fresh) to tail (dying). */\nexport declare class Trail extends Node {\n private _material;\n private _rateDistance;\n constructor(options?: TrailOptions);\n private _send;\n /** Trail length in seconds — how long each laid-down point lives. */\n set time(val: number);\n set width(val: ParticleValue);\n set opacity(val: ParticleValue);\n set color(value: ParticleColor);\n set minDistance(val: number);\n /** Pause/resume laying down points — existing ones still age out, so the trail fades naturally\n * after e.g. a sword swing ends. */\n set emitting(val: boolean);\n get material(): Material;\n}\nexport {};\n","types/gl/Physics.d.ts":"import { Aspect } from \"../core/Aspect\";\nimport { Vec3, type Vec3Like } from \"../math/vec\";\nimport { type Node } from \"./Node\";\nexport type MotionType = \"static\" | \"dynamic\" | \"kinematic\";\nexport interface PhysicsConfig {\n /** Gravity in world units/s² (Y-up: down is negative). Default [0, -9.81, 0]. */\n gravity?: Vec3Like;\n /** Max simultaneous bodies (resizes the world; only before any body exists). Default 4096. */\n maxBodies?: number;\n}\n/** Closest raycast hit. */\nexport interface RayHit {\n node: Node | null;\n point: Vec3;\n normal: Vec3;\n fraction: number;\n}\nexport declare class Physics extends Aspect<\"physics\", Node> {\n static readonly aspect = \"physics\";\n /** Render interpolation of body transforms between the fixed 60 Hz steps (global; default on). Turn\n * off to save per-frame transform writes when you have many moving bodies / don't need >60 Hz\n * smoothness — bodies then advance in discrete steps. */\n private static _interpolation;\n static get interpolation(): boolean;\n static set interpolation(on: boolean);\n /** Default \"dynamic\". */\n motion: MotionType;\n /** Mass in kg for dynamic bodies (default 1). Ignored for static/kinematic. */\n mass: number;\n private _bodyId;\n onAttach(): void;\n onDetach(): void;\n /** Native Jolt body id. 0 until attached, or if the build has no physics support. */\n get id(): number;\n /** Linear velocity in world units/second (fresh Vec3 on read). */\n get velocity(): Vec3;\n set velocity(v: Vec3Like);\n /** Apply an instantaneous impulse (kg·m/s) and wake the body. */\n applyImpulse(v: Vec3Like): this;\n /** Teleport / drive a kinematic (or dynamic) body to a world position. */\n moveTo(p: Vec3Like): this;\n /** Configure gravity / limits. Call once before creating bodies. */\n static configure(config?: PhysicsConfig): void;\n /** Whether this build has physics support (CREATOR_GL_PHYSICS). */\n static get supported(): boolean;\n /** Closest pickable body hit by the ray from `origin` along `dir` (up to `maxDist`), or null. */\n static raycast(origin: Vec3Like, dir: Vec3Like, maxDist?: number): RayHit | null;\n}\n","types/gl/physicsEvents.d.ts":"export declare const ensurePhysicsEvents: () => void;\n","types/gl/Plane.d.ts":"import { Vec3, type Vec3Like } from \"../math/vec\";\nimport type { Ray } from \"./Ray\";\nexport declare class Plane {\n /** Unit normal. */\n readonly normal: Vec3;\n /** Scalar offset: dot(normal, point). */\n readonly d: number;\n constructor(normal: Vec3Like, point: Vec3Like);\n static fromPoints(a: Vec3Like, b: Vec3Like, c: Vec3Like): Plane;\n static fromCoefficients(a: number, b: number, c: number, d: number): Plane;\n /** Ray-plane parameter t (≥0), or null on a miss (parallel / behind origin). */\n intersectRay(ray: Ray): number | null;\n /** Like intersectRay but allows hits behind the origin (line-plane). */\n intersectLine(ray: Ray): number | null;\n /** Signed distance from a point (positive on the normal's side). */\n signedDistance(point: Vec3Like): number;\n /** Project a point onto the plane. */\n projectPoint(point: Vec3Like): Vec3;\n}\n","types/gl/Ray.d.ts":"import { Vec3, type Vec3Like } from \"../math/vec\";\nexport declare class Ray {\n readonly origin: Vec3;\n readonly dir: Vec3;\n constructor(origin: Vec3Like, dir: Vec3Like);\n /** The world-space point origin + t·dir. */\n getPoint(t: number): Vec3;\n}\n","types/gl/scenarios.d.ts":"import { Aspect } from \"../core/Aspect\";\nimport type { FieldMeta } from \"../core/fields\";\nimport type { InspectorUI } from \"../core/InspectorUI\";\nimport { Node } from \"./Node\";\nimport { Model } from \"./Model\";\ntype LoopMode = \"once\" | \"loop\" | \"pingpong\";\n/** Travel from the node's starting position to a target node in `duration` seconds. */\nexport declare class MoveTo extends Aspect<\"moveTo\"> {\n /** Where to travel — place an Empty node and pick it. */\n target: Node | null;\n /** Seconds for the full trip. */\n duration: number;\n /** Seconds to wait before starting. */\n delay: number;\n /** once = stop at the target · loop = restart from the start point · pingpong = back and forth. */\n mode: LoopMode;\n /** Motion curve. */\n easing: \"smooth\" | \"linear\";\n static readonly aspect = \"moveTo\";\n static editor: {\n rebuild: boolean;\n };\n static fields: FieldMeta<MoveTo>;\n private _t;\n private _start;\n update(dt: number): void;\n /** Editor-only path line (edit mode; play mode never calls this). */\n rebuild(): void;\n}\n/** Travel through the children of a path node (add an Empty per waypoint) in `duration` seconds.\n * `loop` runs the circuit closed (last → first); `pingpong` goes back and forth along the open\n * path; `once` stops at the last waypoint. */\nexport declare class FollowPath extends Aspect<\"followPath\"> {\n /** A node whose CHILDREN are the waypoints, in file order. */\n path: Node | null;\n /** Seconds for one full pass of the path. */\n duration: number;\n /** Seconds to wait before starting. */\n delay: number;\n mode: LoopMode;\n /** Turn to face the direction of travel. */\n orient: boolean;\n /** Which local axis leads when orienting. */\n forward: \"-z\" | \"z\" | \"x\" | \"-x\";\n static readonly aspect = \"followPath\";\n static editor: {\n rebuild: boolean;\n };\n static fields: FieldMeta<FollowPath>;\n private _t;\n private _points;\n update(dt: number): void;\n /** Editor-only waypoint polyline (edit mode; play mode never calls this). */\n rebuild(): void;\n}\n/** Continuous rotation about one of the node's local axes, degrees per second. */\nexport declare class Spin extends Aspect<\"spin\"> {\n /** Degrees per second. */\n speed: number;\n /** Local axis to spin around. */\n axis: \"x\" | \"y\" | \"z\";\n static readonly aspect = \"spin\";\n static fields: FieldMeta<Spin>;\n update(dt: number): void;\n}\n/** Keep the node facing a target node (a turret tracking, a signpost, a camera aimed at a hero).\n * Accessor `node.facing` — NOT `lookAt`, which would shadow the `Node.lookAt()` method. */\nexport declare class LookAt extends Aspect<\"facing\"> {\n /** The node to face. */\n target: Node | null;\n /** Which local axis points at the target. */\n forward: \"-z\" | \"z\" | \"x\" | \"-x\";\n /** 0 = snap instantly; otherwise seconds of turn lag (bigger = slower, smoother). */\n smoothing: number;\n static readonly aspect = \"facing\";\n static editor: {\n rebuild: boolean;\n };\n static fields: FieldMeta<LookAt>;\n update(dt: number): void;\n /** Editor-only sight line (edit mode; play mode never calls this). */\n rebuild(): void;\n}\n/** Start a GLB animation clip when the scene runs. Attach to a `model:` node; the inspector card\n * lists the model's clips live and can preview them while editing. */\nexport declare class PlayAnimation extends Aspect<\"playAnimation\", Model> {\n /** Clip name; empty = the model's first clip. */\n clip: string;\n loop: boolean;\n /** Playback rate (1 = authored speed). */\n speed: number;\n static readonly aspect = \"playAnimation\";\n static fields: FieldMeta<PlayAnimation>;\n onAttach(): void;\n static inspector(ui: InspectorUI, a: PlayAnimation): void;\n}\nexport {};\n","types/gl/Scene.d.ts":"import { type ColorInput } from \"../core/color\";\nimport { Presentable, type PresentOptions } from \"../ui/presentable\";\nimport type { ClickEvent, TouchStartEvent } from \"../runtime/touch\";\nimport type { FetchResponse } from \"../runtime/fetch\";\nimport { Camera } from \"./Camera\";\nimport { type ControlsHandle, type ControlsOptions } from \"./controls\";\nimport { Material } from \"./Material\";\nimport { Node } from \"./Node\";\nexport type SceneOptions = {\n /** Image-based ambient lighting (default on). */\n ibl?: boolean;\n /** IBL intensity (default 20000). */\n environmentIntensity?: number;\n /** Bloom post-processing. */\n bloom?: boolean;\n bloomIntensity?: number;\n /** Skybox / clear color. */\n skybox?: ColorInput;\n /** Multisample anti-aliasing. */\n antialias?: boolean;\n};\nexport declare class Scene implements Presentable {\n readonly camera: Camera;\n readonly _touchStartListeners: Array<(ev: TouchStartEvent<Node | null>) => void>;\n private _material?;\n private static _active;\n static get active(): Scene | null;\n constructor(options?: SceneOptions);\n /** Scene occlusion material. */\n get occlusionMaterial(): Material;\n set skybox(color: ColorInput);\n setMaterialGlobalParameter(i: number, x: number, y: number, z: number, w: number): void;\n setAntialias(enabled: boolean, scale?: number): void;\n add(...nodes: Node[]): this;\n remove(...nodes: Node[]): this;\n createOverlay(options?: SceneOptions): Scene;\n warmRender(): Promise<void>;\n readonly cl: (() => void)[];\n _backButtonCallback?: () => void;\n private _vd?;\n /** Fires when the scene becomes the visible destination (incl. a pop revealing it). */\n onOpen(callback: () => void): this;\n /** Fires when the scene stops being visible (closed, replaced, or covered by a push). */\n onClose(callback: () => void): this;\n onBackPressed(callback: () => void): this;\n /** Make this the active scene — shows it as the current destination (replaces a screen /\n * another scene; only the active scene renders). */\n open(options?: PresentOptions): void | Promise<void>;\n close(): void;\n addEventListener(channel: \"click\", callback: (ev: ClickEvent<Node | null>) => void): void;\n addEventListener(channel: \"touchstart\", callback: (ev: TouchStartEvent<Node | null>) => void): void;\n removeEventListener(channel: \"click\" | \"touchstart\", callback: (ev: any) => void): void;\n}\nexport type ARMode = \"default\" | \"markers\" | \"arcore\" | \"detached\";\nexport declare class ARScene<T extends ARMode = \"default\"> extends Scene {\n readonly mode: T;\n useWarmRender: boolean;\n private _root?;\n constructor(options?: SceneOptions & {\n mode?: T;\n });\n /** Root anchor node (not available in marker mode). */\n get root(): Node;\n /** Create an anchor from a tracking source (e.g. an image target). */\n createAnchor(source: FetchResponse, physicalWidth?: number): Node;\n /**\n * Let the user place & manipulate a node with touch gestures — the staple AR object-placement\n * interaction: ONE finger drags it across the floor (relative to where the camera looks), TWO fingers\n * pinch to scale and twist to rotate. Returns a handle; call `.remove()` to detach. Tunable via\n * options (min/max scale, and toggles for `pan` / `pinch` / `twist`).\n */\n addControls(target: Node, options?: ControlsOptions): ControlsHandle;\n open(options?: PresentOptions): Promise<void>;\n close(): void;\n}\n/**\n * A 3D scene rendered in a VR headset (OpenXR — e.g. Meta Quest). The headset drives the camera:\n * every frame both eyes are rendered from the tracked head pose, so `scene.camera` position/lookAt\n * have no effect while the scene is open. The world origin is at floor level (stage space) —\n * author content with the ground at y = 0 and the user standing at the origin.\n *\n * `open()` rejects on hosts without a VR runtime (\"VR is not supported on this device\").\n */\nexport declare class VRScene extends Scene {\n open(options?: PresentOptions): Promise<void>;\n close(): void;\n}\n","types/gl/Shape.d.ts":"import { Aspect } from \"../core/Aspect\";\nimport { type Vec3Like } from \"../math/vec\";\nimport type { Node } from \"./Node\";\nexport declare class Shape extends Aspect<\"shape\", Node> {\n static readonly aspect = \"shape\";\n /** Box half-extents [hx, hy, hz] (world units). */\n box?: Vec3Like;\n /** Sphere radius. */\n sphere?: number;\n /** Cylinder aligned on Y: half-height + radius. */\n cylinder?: {\n halfHeight: number;\n radius: number;\n };\n /** Capsule aligned on Y: half-height of the cylinder section + radius. */\n capsule?: {\n halfHeight: number;\n radius: number;\n };\n /** Whether pointer rays can hit this shape (click / touchstart). Default true. */\n raycast: boolean;\n private _shapeId;\n private _bodyId;\n onAttach(): void;\n onDetach(): void;\n private _createPickBody;\n private _build;\n}\n","types/gl/state.d.ts":"import type { Scene } from \"./Scene\";\nexport declare const glState: {\n activeScene: Scene | null;\n frame: number;\n};\n","types/gl/Texture.d.ts":"import { type FetchResponse, type File } from \"../runtime/fetch\";\nexport declare class Texture {\n readonly width: number;\n readonly height: number;\n /** Horizontal wrap mode (U). */\n wrapS: number;\n /** Vertical wrap mode (V). */\n wrapT: number;\n constructor(width: number, height: number, id: number);\n static fromCanvas(canvas: {\n _bakeSurface(): number;\n width: number;\n height: number;\n pixelRatio: number;\n _tex3dId: number;\n }): Texture;\n static load(source: string | FetchResponse | File): Promise<Texture>;\n}\n","types/gl/touch.d.ts":"export declare const registerTouchStartEvent: () => void;\nexport declare const registerTouchEndEvent: () => void;\n","types/gl/Trigger.d.ts":"import { Aspect } from \"../core/Aspect\";\nimport { type Vec3Like } from \"../math/vec\";\nimport type { Node } from \"./Node\";\nexport declare class Trigger extends Aspect<\"trigger\", Node> {\n static readonly aspect = \"trigger\";\n private _bodyId;\n /** Native body id (0 if no physics support). */\n get id(): number;\n onAttach(): void;\n onDetach(): void;\n /** Reposition the trigger zone to a world point. */\n moveTo(p: Vec3Like): this;\n}\n","types/inject.d.ts":"export { Mathf } from \"./math/Mathf\";\nexport { Vec2, Vec3 } from \"./math/vec\";\nexport { Quat } from \"./math/quat\";\nexport { Mat4 } from \"./math/mat4\";\nexport { Color } from \"./core/color\";\nexport { Aspect, type With } from \"./core/Aspect\";\nexport { InspectorUI } from \"./core/InspectorUI\";\nexport { signal, computed, effect, type Signal, type Computed } from \"./core/signals\";\nexport { Canvas, Bitmap } from \"./canvas/Canvas\";\nexport { toast, openURL, SvgSource } from \"./runtime/misc\";\nexport { app, type AppState } from \"./runtime/app\";\nexport { clipboard } from \"./runtime/clipboard\";\nexport { date, type DateValue, type DateInput, type Unit, type Locale } from \"./runtime/datetime\";\nexport { fetch, fetchLocal, FormData, File, type FetchResponse } from \"./runtime/fetch\";\nexport { localStorage } from \"./runtime/storage\";\nexport { device, type HapticStyle, type MotionOptions } from \"./runtime/device\";\nexport { Input } from \"./runtime/input\";\nexport { WebSocket } from \"./runtime/net\";\nexport { __rpc, __channel, __serverOnly, RpcError, type ClientChannel } from \"./runtime/rpc\";\nexport { AudioPlayer, VideoPlayer } from \"./runtime/media\";\nexport { openFilePicker } from \"./runtime/files\";\nexport { share } from \"./runtime/share\";\nexport { ClickEvent, TouchStartEvent, LongPressEvent } from \"./runtime/touch\";\nexport { Scene2D } from \"./g2/Scene2D\";\nexport { Node2D } from \"./g2/Node2D\";\nexport { Camera2D } from \"./g2/Camera2D\";\nexport { Sprite } from \"./g2/Sprite\";\nexport { SpriteAnimation } from \"./g2/SpriteAnimation\";\nexport { Shape2D } from \"./g2/Shape2D\";\nexport { Physics2D } from \"./g2/Physics2D\";\nexport { Trigger2D } from \"./g2/Trigger2D\";\nexport { CharacterController2D } from \"./g2/CharacterController2D\";\nexport { Tilemap } from \"./g2/Tilemap\";\nexport { Texture2D } from \"./g2/Texture2D\";\nexport { SpriteSheet, defineSpriteSheet } from \"./g2/SpriteSheet\";\nexport type { SpriteSheetDef, SheetSprite, SpriteMakeOptions } from \"./g2/SpriteSheet\";\nexport { Tileset, defineTileset, Autotile2D } from \"./g2/Tileset\";\nexport { rawCell, isRawCell, rawIndex } from \"./g2/autotile\";\nexport { rot90, rot180, rot270, flipX, packTile, tileIndex, tileTurns, tileFlip, tileOriented } from \"./g2/autotile\";\nexport type { TilesetDef, TileMaterial, PatchMaterial, PathMaterial, PatchSlots, EdgeSlot, FillBlock, BlockEntry, TileBlock, TilePart, } from \"./g2/autotile\";\nexport { defineScene2d, Scene2dHandle } from \"./g2/defineScene2d\";\nexport type { Scene2dDef, Scene2dNodeDef, Scene2dEnv, SpriteSourceDef, TilemapSourceDef, Camera2dNodeDef, LoadedScene2d } from \"./g2/defineScene2d\";\nexport { cells, encodeCells, type CellsData } from \"./g2/cells\";\nexport { CameraFollow } from \"./g2/scenarios2d\";\nexport { UIScreen, type UIScreenStyle, UIRow, UIColumn, UIBox, type UIContainerStyle, UIText, type UITextStyle, UIButton, type UIButtonStyle, UIImage, type UIImageStyle, UIVideo, type UIVideoStyle, UIInput, UITextArea, type UIInputStyle, UIScrollable, type UIScrollableStyle, UIPager, type UIPagerStyle, UITabs, type UITabDef, defineTabs, type TabDef, type TabsHandle, UIWidget, type UIWidgetStyle, UIModal, type UIModalStyle, UIBottomSheet, type UIBottomSheetStyle, UIPopover, type UIPopoverStyle, UISpacer, type UISpacerStyle, UIVirtualizedList, Router, NativeView, type UINativeViewStyle, registerFont, __uiMap, __UIColumn, __UIRow, __UIBox, __UIButton, __UIScreen, __UIScrollable, __UIWidget, } from \"./ui/UI\";\nexport { Presentable } from \"./ui/UI\";\nexport type { PresentOptions, Transition, TransitionName, TransitionSpec, TransitionTransform } from \"./ui/UI\";\nexport type { UINode, UINodeChild } from \"./ui/UINode\";\nexport { theme, type ThemeValues, type ThemeAccessors } from \"./ui/theme\";\nexport { animate, animateMat4, stopAnimation, pauseAnimation, resumeAnimation } from \"./animate/animate\";\nexport { cubicBezier } from \"./animate/bezier\";\nexport { easeIn, easeOut, easeInOut } from \"./animate/easings\";\nexport { QRScanner } from \"./plugins/qr\";\nexport { CameraView, type CameraFacing } from \"./plugins/camera\";\nexport { Geolocation, type GeoPosition, type GeoOptions, type GeoWatch } from \"./plugins/geolocation\";\nexport { Push, type PushPayload, type PushStatus, type PushRegisterOptions, type PushEvent } from \"./plugins/push\";\nexport { OAuth, type OAuthCredential, type OAuthProviderName } from \"./plugins/oauth\";\nexport { Service } from \"./plugins/service\";\nexport { defineScene, use, ref, make, SceneHandle } from \"./scene/defineScene\";\nexport type { SceneDef, SceneNodeDef, MeshDef, LightDef, MaterialDef, CameraNodeDef, AspectEntry, MakeEntry, LoadedScene } from \"./scene/defineScene\";\nexport type { FieldMeta } from \"./core/fields\";\nexport { MoveTo, FollowPath, Spin, LookAt, PlayAnimation } from \"./gl/scenarios\";\nexport { registerEditorWindow, registerEditorTool, __editorPlugins } from \"./scene/editorPlugins\";\nexport type { EditorApi, EditorRayHit, EditorToolHooks, EditorWindowFn } from \"./scene/editorPlugins\";\nexport { Scene, ARScene, VRScene } from \"./gl/Scene\";\nexport { Node } from \"./gl/Node\";\nexport { Mesh } from \"./gl/Mesh\";\nexport { Model } from \"./gl/Model\";\nexport { Shape } from \"./gl/Shape\";\nexport { Physics } from \"./gl/Physics\";\nexport { Trigger } from \"./gl/Trigger\";\nexport { CharacterController } from \"./gl/CharacterController\";\nexport { ModelAnimation } from \"./gl/ModelAnimation\";\nexport { AnimationClip } from \"./gl/AnimationClip\";\nexport type { ClipDef, ClipTrackDef, ClipKey } from \"./gl/AnimationClip\";\nexport { Animator } from \"./gl/Animator\";\nexport type { AnimatorPlayOptions } from \"./gl/Animator\";\nexport { IK } from \"./gl/IK\";\nexport type { IKTwoBone, IKLookAt } from \"./gl/IK\";\nexport { Light } from \"./gl/Light\";\nexport { Material } from \"./gl/Material\";\nexport { Geometry } from \"./gl/Geometry\";\nexport { Texture } from \"./gl/Texture\";\nexport { Camera } from \"./gl/Camera\";\nexport { Ray } from \"./gl/Ray\";\nexport { Plane } from \"./gl/Plane\";\nexport { Noise } from \"./gl/Noise\";\nexport { Particles, Trail, curve, colorCurve } from \"./gl/Particles\";\n","types/math/mat4.d.ts":"import { Vec3, type Vec3Like } from \"./vec\";\nimport { Quat, type QuatLike, type EulerOrder } from \"./quat\";\nexport type Mat4Like = Mat4 | number[] | Float32Array | readonly number[];\nexport declare class Mat4 {\n /** The raw column-major elements (length 16). Public on purpose — read/write directly when you want\n * the metal: `mat.m[12] += vx * dt`. The fluent methods never mutate it (they return a new Mat4). */\n m: number[];\n constructor(src?: Mat4Like);\n set(values: ArrayLike<number>): this;\n copy(src: Mat4Like): this;\n /** `this · b` (apply `b` first in local space, then `this`). */\n mul(b: Mat4Like): Mat4;\n /** `b · this` — multiply on the other side (apply `this` first, then `b`). */\n premul(b: Mat4Like): Mat4;\n invert(): Mat4;\n transpose(): Mat4;\n determinant(): number;\n /** `this · translate(v)`. */\n translate(v: Vec3Like): Mat4;\n /** `this · scale(v)`. Accepts a vector or a uniform scalar. */\n scale(v: Vec3Like | number): Mat4;\n /** `this · rotate(axis, rad)`. */\n rotate(rad: number, axis: Vec3Like): Mat4;\n rotateX(rad: number): Mat4;\n rotateY(rad: number): Mat4;\n rotateZ(rad: number): Mat4;\n /** Transform a point (applies translation + perspective divide). */\n transformPoint(v: Vec3Like): Vec3;\n /** Transform a direction (rotation/scale only — no translation, no divide). */\n transformDirection(v: Vec3Like): Vec3;\n get position(): Vec3;\n get scaling(): Vec3;\n get rotation(): Quat;\n get eulerAngles(): Vec3;\n toEuler(order?: EulerOrder): Vec3;\n /** `{ position, rotation, scale }` in one shot. */\n decompose(): {\n position: Vec3;\n rotation: Quat;\n scale: Vec3;\n };\n /** Column basis vectors (the local X / Y / Z axes in world space). */\n get basisX(): Vec3;\n get basisY(): Vec3;\n get basisZ(): Vec3;\n clone(): Mat4;\n toArray(): number[];\n toFloat32Array(): Float32Array;\n equals(b: Mat4Like, eps?: number): boolean;\n static identity(): Mat4;\n static from(src: Mat4Like): Mat4;\n /** Translation · Rotation · Scale into one matrix. `scale` defaults to 1 and accepts a scalar. */\n static compose(position: Vec3Like, rotation: QuatLike, scale?: Vec3Like | number): Mat4;\n static fromQuat(q: QuatLike): Mat4;\n static fromTranslation(v: Vec3Like): Mat4;\n static fromScale(v: Vec3Like | number): Mat4;\n static fromEuler(x: number, y: number, z: number, order?: EulerOrder): Mat4;\n /** A view matrix that looks from `eye` toward `center` with `up`. */\n static lookAt(eye: Vec3Like, center: Vec3Like, up?: Vec3Like): Mat4;\n /** A world matrix that places something at `eye` oriented to look at `target`. */\n static targetTo(eye: Vec3Like, target: Vec3Like, up?: Vec3Like): Mat4;\n /** Perspective projection (WebGL/OpenGL clip, NDC z ∈ [−1, 1]). `fovy` is in RADIANS. */\n static perspective(fovy: number, aspect: number, near: number, far: number): Mat4;\n /** Orthographic projection (WebGL/OpenGL clip, NDC z ∈ [−1, 1]). */\n static ortho(left: number, right: number, bottom: number, top: number, near: number, far: number): Mat4;\n}\n","types/math/Mathf.d.ts":"export type Damper<T extends number | number[]> = ((target: T, dt: number) => T) & {\n /** Snap the damper's internal current value (e.g. on teleport). */\n setValue(value: T): void;\n};\ndeclare function smoothDamp(initial: number, smoothTime: number, maxSpeed?: number): Damper<number>;\ndeclare function smoothDamp(initial: number[], smoothTime: number, maxSpeed?: number): Damper<number[]>;\nexport declare const Mathf: {\n PI: number;\n TAU: number;\n EPSILON: number;\n DEG2RAD: number;\n RAD2DEG: number;\n deg2rad: (deg: number) => number;\n rad2deg: (rad: number) => number;\n clamp: (v: number, min: number, max: number) => number;\n clamp01: (v: number) => number;\n lerp: (a: number, b: number, t: number) => number;\n inverseLerp: (a: number, b: number, v: number) => number;\n remap: (v: number, inMin: number, inMax: number, outMin: number, outMax: number) => number;\n /** Move `a` toward `b` by at most `maxDelta`. */\n moveTowards: (a: number, b: number, maxDelta: number) => number;\n /** Frame-rate-independent exponential approach (good default: lambda 5..15). */\n damp: (a: number, b: number, lambda: number, dt: number) => number;\n sign: (x: number) => number;\n /** Loop a value into [0, length). */\n repeat: (t: number, length: number) => number;\n /** Ping-pong a value in [0, length]. */\n pingPong: (t: number, length: number) => number;\n random: (min?: number, max?: number) => number;\n randomInt: (min: number, max: number) => number;\n /**\n * Critically-damped follow (Unity SmoothDamp). Returns a stateful damper you call every frame:\n * const d = Mathf.smoothDamp([x, y], 0.15)\n * pos = d(targetPos, dt)\n * Works on a number or a numeric array (vec2 / vec3).\n */\n smoothDamp: typeof smoothDamp;\n};\nexport {};\n","types/math/quat.d.ts":"import { Vec3, type Vec3Like } from \"./vec\";\nexport type QuatLike = Quat | readonly [number, number, number, number] | number[] | Float32Array;\nexport type EulerOrder = \"XYZ\" | \"YXZ\" | \"ZXY\" | \"ZYX\" | \"YZX\" | \"XZY\";\n/** Read the w / 4th component of any quaternion-like (wrapper `.w`, or array-like `[3]`). */\nexport declare const cw: (q: {\n w?: number;\n} | ArrayLike<number>) => number;\nexport declare class Quat {\n x: number;\n y: number;\n z: number;\n w: number;\n constructor(x?: number | QuatLike, y?: number, z?: number, w?: number);\n set(x: number, y: number, z: number, w: number): this;\n copy(q: QuatLike): this;\n /** Hamilton product `this ⊗ b` (apply `b` first, then `this`). */\n mul(b: QuatLike): Quat;\n normalize(): Quat;\n conjugate(): Quat;\n /** Inverse rotation. For a unit quaternion this equals `conjugate()`. */\n invert(): Quat;\n dot(b: QuatLike): number;\n /** Spherical interpolation toward `b` by `t ∈ [0, 1]`. */\n slerp(b: QuatLike, t: number): Quat;\n /** Angular distance (radians) between two unit quaternions. */\n angle(b: QuatLike): number;\n /** Rotate a vector by this quaternion → a new `Vec3`. */\n rotateVec3(v: Vec3Like): Vec3;\n /** Extract euler angles (DEGREES) in the given order. */\n toEuler(order?: EulerOrder): Vec3;\n equals(b: QuatLike, eps?: number): boolean;\n /** True if the two unit quaternions represent the same rotation (±q are equal). */\n sameRotation(b: QuatLike, eps?: number): boolean;\n clone(): Quat;\n toArray(): [number, number, number, number];\n [Symbol.iterator](): Iterator<number>;\n static from(q: QuatLike): Quat;\n static get identity(): Quat;\n /** From euler angles in DEGREES (default order \"YXZ\"). Inverts `toEuler`. */\n static fromEuler(x: number, y: number, z: number, order?: EulerOrder): Quat;\n /** From a rotation `axis` and an angle in RADIANS. The axis is normalized for you. */\n static fromAxisAngle(axis: Vec3Like, rad: number): Quat;\n /** The shortest rotation that takes direction `a` onto direction `b`. */\n static fromTo(a: Vec3Like, b: Vec3Like): Quat;\n /** A rotation whose forward (−Z) points along `forward`, with `up` as the reference up axis. */\n static lookRotation(forward: Vec3Like, up?: Vec3Like): Quat;\n}\n/** Quaternion from a column-major rotation matrix (≥3×3, indices 0,1,2,4,5,6,8,9,10). gl-matrix's\n * `getRotation` algorithm — the exact inverse of building a matrix from a quaternion. */\nexport declare const quatFromColMajor: (m: ArrayLike<number>) => Quat;\n/** Euler angles (DEGREES) from a column-major rotation matrix, standard three.js extraction.\n * Element naming follows the column-major layout: mRC = m[(C-1)*4 + (R-1)]. */\nexport declare const eulerFromColMajor: (m: ArrayLike<number>, order?: EulerOrder) => Vec3;\n","types/math/vec.d.ts":"export type Vec2Like = Vec2 | readonly [number, number] | number[] | Float32Array;\nexport type Vec3Like = Vec3 | readonly [number, number, number] | number[] | Float32Array;\n/** Read the x / first component of any vector-like (wrapper, tuple, or typed array). `?? ` is safe on\n * 0 and NaN — it only falls through on `undefined` (i.e. a non-wrapper that has no `.x`). */\nexport declare const cx: (v: {\n x?: number;\n} | ArrayLike<number>) => number;\nexport declare const cy: (v: {\n y?: number;\n} | ArrayLike<number>) => number;\nexport declare const cz: (v: {\n z?: number;\n} | ArrayLike<number>) => number;\nexport declare class Vec2 {\n x: number;\n y: number;\n constructor(x?: number | Vec2Like, y?: number);\n /** Mutate the components in place. Returns `this`. */\n set(x: number, y: number): this;\n /** Copy another vector's components into this one. Returns `this`. */\n copy(v: Vec2Like): this;\n add(v: Vec2Like): Vec2;\n sub(v: Vec2Like): Vec2;\n mul(v: Vec2Like): Vec2;\n div(v: Vec2Like): Vec2;\n scale(s: number): Vec2;\n /** `this + v * s` (fused multiply-add). */\n scaleAndAdd(v: Vec2Like, s: number): Vec2;\n negate(): Vec2;\n dot(v: Vec2Like): number;\n /** 2D cross product → the scalar z of the 3D cross (signed parallelogram area). */\n cross(v: Vec2Like): number;\n length(): number;\n lengthSq(): number;\n distanceTo(v: Vec2Like): number;\n distanceSqTo(v: Vec2Like): number;\n normalize(): Vec2;\n lerp(v: Vec2Like, t: number): Vec2;\n clamp(min: Vec2Like, max: Vec2Like): Vec2;\n min(v: Vec2Like): Vec2;\n max(v: Vec2Like): Vec2;\n /** Left-hand perpendicular: (-y, x), a 90° CCW turn. */\n perp(): Vec2;\n /** Rotate by `rad` (CCW) around `origin` (default 0). */\n rotate(rad: number, origin?: Vec2Like): Vec2;\n /** The vector's heading in radians: `atan2(y, x)`. */\n heading(): number;\n /** Angle (radians) between this and `v`. */\n angle(v: Vec2Like): number;\n withX(x: number): Vec2;\n withY(y: number): Vec2;\n equals(v: Vec2Like, eps?: number): boolean;\n clone(): Vec2;\n toArray(): [number, number];\n [Symbol.iterator](): Iterator<number>;\n static from(v: Vec2Like): Vec2;\n static get zero(): Vec2;\n static get one(): Vec2;\n static get up(): Vec2;\n static get down(): Vec2;\n static get left(): Vec2;\n static get right(): Vec2;\n}\nexport declare class Vec3 {\n x: number;\n y: number;\n z: number;\n constructor(x?: number | Vec3Like, y?: number, z?: number);\n set(x: number, y: number, z: number): this;\n copy(v: Vec3Like): this;\n add(v: Vec3Like): Vec3;\n sub(v: Vec3Like): Vec3;\n mul(v: Vec3Like): Vec3;\n div(v: Vec3Like): Vec3;\n scale(s: number): Vec3;\n /** `this + v * s` (fused multiply-add). */\n scaleAndAdd(v: Vec3Like, s: number): Vec3;\n negate(): Vec3;\n dot(v: Vec3Like): number;\n cross(v: Vec3Like): Vec3;\n length(): number;\n lengthSq(): number;\n distanceTo(v: Vec3Like): number;\n distanceSqTo(v: Vec3Like): number;\n normalize(): Vec3;\n lerp(v: Vec3Like, t: number): Vec3;\n clamp(min: Vec3Like, max: Vec3Like): Vec3;\n min(v: Vec3Like): Vec3;\n max(v: Vec3Like): Vec3;\n /** Reflect this vector about a (unit) `normal`: `v - 2·(v·n)·n`. */\n reflect(normal: Vec3Like): Vec3;\n /** Vector projection of this onto `onto`. */\n project(onto: Vec3Like): Vec3;\n /** Angle (radians) between this and `v`. */\n angle(v: Vec3Like): number;\n /** Rotate this point around the X axis through `origin` (default 0) by `rad`. */\n rotateX(rad: number, origin?: Vec3Like): Vec3;\n rotateY(rad: number, origin?: Vec3Like): Vec3;\n rotateZ(rad: number, origin?: Vec3Like): Vec3;\n /** Rotate this vector by a quaternion (x, y, z, w). Accepts a `Quat` or a raw `[x,y,z,w]`. */\n rotate(q: ArrayLike<number> | {\n x: number;\n y: number;\n z: number;\n w: number;\n }): Vec3;\n /** Transform this point by a column-major mat4 (a `Mat4`, its `.m`, or a raw length-16 array),\n * applying translation and the perspective divide. */\n transform(m: ArrayLike<number> | {\n m: ArrayLike<number>;\n }): Vec3;\n withX(x: number): Vec3;\n withY(y: number): Vec3;\n withZ(z: number): Vec3;\n equals(v: Vec3Like, eps?: number): boolean;\n clone(): Vec3;\n toArray(): [number, number, number];\n [Symbol.iterator](): Iterator<number>;\n static from(v: Vec3Like): Vec3;\n static get zero(): Vec3;\n static get one(): Vec3;\n static get up(): Vec3;\n static get down(): Vec3;\n static get left(): Vec3;\n static get right(): Vec3;\n /** Forward is −Z (the engine's cameras look down −Z; `node.forward` is −Z at identity). */\n static get forward(): Vec3;\n static get back(): Vec3;\n}\n","types/plugins/camera.d.ts":"import { File } from \"../runtime/fetch\";\nimport { type PresentOptions } from \"../ui/presentable\";\nimport { NativeView } from \"../ui/NativeView\";\nexport type CameraFacing = \"front\" | \"back\";\nexport interface CameraView extends NativeView {\n /** Request camera permission, then present the preview. The current destination stays visible\n * until the camera is ready; rejects if permission is denied, the host has no camera, or\n * another navigation superseded this one. */\n open(options?: PresentOptions): Promise<void>;\n /** Capture a still frame as an image `File` (host-encoded). */\n takePhoto(): Promise<File>;\n /** Switch between the front and back camera while the preview is live. */\n setFacingMode(facingMode: CameraFacing): Promise<void>;\n}\n/**\n * Create a camera view (default: the back camera). `CameraView.isSupported` reports whether this\n * host has a camera capability — check it before offering the feature.\n */\nexport declare const CameraView: {\n (options?: {\n facingMode?: CameraFacing;\n }): CameraView;\n /** Whether this host registered a \"camera\" view. */\n readonly isSupported: boolean;\n};\n","types/plugins/geolocation.d.ts":"export interface GeoPosition {\n latitude: number;\n longitude: number;\n /** Horizontal accuracy radius, meters. */\n accuracy: number;\n /** Meters above sea level, or null when the provider doesn't know. */\n altitude: number | null;\n /** Direction of travel in degrees clockwise from north, or null when stationary/unknown. */\n heading: number | null;\n /** Ground speed in m/s, or null when unknown. */\n speed: number | null;\n /** When this fix was taken, ms epoch. */\n timestamp: number;\n}\nexport interface GeoOptions {\n /** Prefer the precise (GPS) provider — slower first fix, more battery. Default false. */\n highAccuracy?: boolean;\n /** getCurrent only: reject with \"timeout\" if no fix arrives in this many ms. */\n timeout?: number;\n}\n/** A live `Geolocation.watch()` subscription — `stop()` it when the screen goes away. */\nexport interface GeoWatch {\n stop(): void;\n}\n/**\n * The device position. `Geolocation.isSupported` reports whether this host registered the\n * service — check it before offering location features.\n */\nexport declare const Geolocation: {\n /** Whether this host registered a \"geolocation\" service. */\n readonly isSupported: boolean;\n /** One position fix. Prompts for permission on first use; rejects on denial (\"denied\"), no\n * provider (\"unavailable\"), or `options.timeout` elapsing (\"timeout\"). */\n getCurrent(options?: GeoOptions): Promise<GeoPosition>;\n /** Continuous updates. Resolves once watching (permission granted + provider started) — so a\n * denial is a rejection, never a silently dead callback. One host watch serves every\n * subscriber; the options of the watch that starts it win. Always `stop()` when done. */\n watch(callback: (position: GeoPosition) => void, options?: GeoOptions): Promise<GeoWatch>;\n};\n","types/plugins/oauth.d.ts":"export type OAuthProviderName = \"google\" | \"apple\" | \"yandex\" | \"vk\";\n/** What a native provider SDK yields — pass it verbatim to your endpoint / `auth.oauth.signIn`. */\nexport type OAuthCredential = {\n provider: OAuthProviderName;\n /** OAuth access token (Yandex, VK ID). */\n accessToken?: string;\n /** OpenID identity token (Google, Apple). */\n idToken?: string;\n /** Apple only sends the name once, on the first sign-in — forward it so the server can store it. */\n name?: string;\n email?: string;\n};\n/**\n * Native provider sign-in. `OAuth.isSupported` reports whether this host registered the service;\n * `OAuth.providers()` which providers it has SDKs for. Otherwise open `auth.oauth.url(provider)` (server)\n * with `openURL` — the browser broker.\n */\nexport declare const OAuth: {\n /** Whether this host registered an \"oauth\" service. */\n readonly isSupported: boolean;\n /** The providers this host can sign in with natively. */\n providers(): Promise<OAuthProviderName[]>;\n /** Run the provider's native sheet; resolves with the credential for `auth.oauth.signIn`. Rejects \"cancelled\" / \"unavailable\". */\n signIn(provider: OAuthProviderName): Promise<OAuthCredential>;\n};\n","types/plugins/permission.d.ts":"export declare const _requestCameraPermission: () => Promise<void>;\n","types/plugins/push.d.ts":"/** A delivered notification, as the app sees it. */\nexport interface PushPayload {\n title: string;\n body?: string;\n /** Deep link — also delivered through `app.launchUrl` / the app \"url\" event. */\n url?: string;\n /** The developer's own JSON, ≤ 2 KB serialized. */\n data?: Record<string, any>;\n badge?: number;\n}\nexport interface PushStatus {\n /** OS notification permission for the host app. \"prompt\" = not asked yet. */\n permission: \"granted\" | \"denied\" | \"prompt\";\n /** Whether this device already holds a registration (an address) for this app. */\n registered: boolean;\n}\nexport interface PushRegisterOptions {\n /** Your app's OWN user id (\"external user id\"): lets your server send to `users: [\"u42\"]`\n * instead of storing addresses, fanning out to all the user's devices. CLIENT-ASSERTED and\n * unverified — never target sensitive content by user. The registration reflects the latest\n * `register()` call, so registering without `user` clears it (logout). */\n user?: string;\n}\nexport type PushEvent = \"message\" | \"tap\";\n/**\n * Remote push notifications. `Push.isSupported` reports whether this host registered the\n * service — check it before offering notification features.\n */\nexport declare const Push: {\n /** Whether this host registered a \"push\" service. */\n readonly isSupported: boolean;\n /** Permission + registration state. Never prompts. */\n getStatus(): Promise<PushStatus>;\n /** Ask for permission (first time) and register this device → the opaque address your server\n * targets. Idempotent — safe to call every launch; rejects \"denied\" / \"unavailable\". */\n register(options?: PushRegisterOptions): Promise<{\n address: string;\n }>;\n /** Remove this device's registration (the address stops receiving). */\n unregister(): Promise<void>;\n /** The notification that cold-started this app run, or null. Stable across calls. */\n getLaunch(): Promise<PushPayload | null>;\n /** \"message\" = received while the app is open; \"tap\" = the user tapped one while it ran. */\n addEventListener(event: PushEvent, callback: (payload: PushPayload) => void): void;\n removeEventListener(event: PushEvent, callback: (payload: PushPayload) => void): void;\n};\n","types/plugins/qr.d.ts":"import { type PresentOptions } from \"../ui/presentable\";\nimport { NativeView } from \"../ui/NativeView\";\nexport interface QRScanner extends NativeView {\n /** Fires per decoded camera frame: the decoded string, or `null` for a frame with no readable\n * code (expect those repeatedly while the user aims). The same code can be reported more than\n * once — `close()` or debounce once you have what you need. */\n onScan(callback: (data: string | null) => void): this;\n /** Request camera permission, then present the scanner. The current destination (and its\n * loading state) stays visible until the scanner is ready; rejects if the camera is denied,\n * the host can't scan, or another navigation superseded this one. */\n open(options?: PresentOptions): Promise<void>;\n}\n/**\n * Create a QR scanner view. `QRScanner.isSupported` reports whether this host can scan at all —\n * check it before offering the feature.\n */\nexport declare const QRScanner: {\n (): QRScanner;\n /** Whether this host registered a \"qrScanner\" view. */\n readonly isSupported: boolean;\n};\n","types/plugins/service.d.ts":"export interface Service {\n /** Invoke a method on the service (`battery.call(\"level\")`). Arguments and the result are\n * JSON-serialized; rejects when the host has no such service or the method reports an\n * error. The host session opens lazily on the first call. */\n call(method: string, ...args: any[]): Promise<any>;\n /** Subscribe to an event the service emits while a session is open\n * (`battery.on(\"change\", data => …)`). Payloads are JSON-decoded. */\n on(event: string, callback: (data?: any) => void): this;\n /** Remove a previously added listener. */\n off(event: string, callback: (data?: any) => void): this;\n /** Close the host session (stops whatever the service was doing). Listeners stay\n * registered — a later `call()` opens a fresh session that delivers to them again. */\n close(): void;\n}\n/**\n * A host-registered headless service — the UI-less sibling of `NativeView`. Use it for\n * services without a typed wrapper: native code registered in your app shell\n * (`engine.registerService(\"app.battery\") { … }`) or a third-party plugin's channel.\n * **Host-optional** — gate on `Service.isSupported` (the web editor registers none of them).\n *\n * ```ts\n * if (Service.isSupported(\"app.battery\")) {\n * const battery = Service(\"app.battery\")\n * battery.on(\"change\", data => { level.text = data.level + \"%\" })\n * const { level } = await battery.call(\"level\")\n * }\n * ```\n */\nexport declare const Service: {\n (name: string, params?: any): Service;\n /** Whether this host registered a service under `name`. */\n isSupported(name: string): boolean;\n};\n","types/runtime/app.d.ts":"export type AppState = \"active\" | \"background\";\ntype AppEventMap = {\n /** The app left the foreground (home button, tab hidden, another app on top). Delivered before\n * the host halts the frame loop — the last chance to persist state / pause work. */\n pause: () => void;\n /** The app returned to the foreground; frames are running again. */\n resume: () => void;\n /** A link arrived while the app was running (warm deep link). `app.launchUrl` is already\n * updated to the same value when this fires. */\n url: (url: string) => void;\n /** The on-screen keyboard changed. `height` mirrors `app.keyboardHeight` (the raw overlap, see\n * there); `duration` is the platform's keyboard animation duration in ms (0 where none) — pass\n * it to `animateTo` to move a composer in sync with the keyboard. */\n keyboard: (height: number, duration: number) => void;\n};\nexport declare const app: {\n /** Current lifecycle state. `\"background\"` while the app is not the foreground app / the tab is\n * hidden. `\"active\"` on hosts that don't track it. */\n readonly state: AppState;\n /** The URL the app was (most recently) opened with — the deep link — or `null` for a plain\n * launch. Warm links update it and fire the `\"url\"` event. */\n readonly launchUrl: string | null;\n /** On-screen keyboard height in logical px currently overlapping the app viewport, `0` when\n * hidden. This is the RAW overlap, independent of the focused input's `keyboardShrink` policy —\n * with the default shrink the layout already avoids the keyboard; the main consumer is overlay\n * mode (`keyboardShrink: false`), e.g. a chat composer's `pb`. `0` on hosts without an\n * on-screen keyboard. */\n readonly keyboardHeight: number;\n /** Re-run this app's bundle in a fresh world — the platform's `location.reload()`. Pass `url`\n * to reboot with different launch arguments (the new run reads them via `app.launchUrl`),\n * `null` to reboot with a cleared one, or omit it to replay the current one. No-op on hosts\n * without world control (headless). */\n restart(url?: string | null): void;\n /** Leave this app. Inside the LeCodes viewer that returns to the launcher (the LeCodes home\n * screen); a standalone-built app leaves to the platform instead — Android backgrounds it,\n * iOS ignores the call (the platform forbids programmatic exit). */\n quit(): void;\n /** Global back-press fallback (Android back button/gesture — iOS has no system back). Fires\n * only when nothing else consumed the press: no open widget/modal claimed it, the current\n * screen has no `onBackPressed`, every pager is at its tab root and the router is at its\n * stack root. The place for app-wide policy — e.g. double-press-to-quit:\n *\n * ```ts\n * let armedAt = 0\n * app.onBackPressed(() => {\n * if (Date.now() - armedAt < 2000) { app.quit(); return }\n * armedAt = Date.now()\n * toast(\"Press back again to exit\")\n * })\n * ```\n *\n * Replaces the previous handler; pass `null` to remove. */\n onBackPressed(callback: (() => void) | null): void;\n addEventListener<E extends keyof AppEventMap>(event: E, callback: AppEventMap[E]): void;\n removeEventListener<E extends keyof AppEventMap>(event: E, callback: AppEventMap[E]): void;\n};\nexport {};\n","types/runtime/appEvents.d.ts":"type AppEventCallback = (data?: string) => void;\nexport declare const appEventsOn: (event: string, cb: AppEventCallback) => void;\nexport declare const appEventsOff: (event: string, cb: AppEventCallback) => void;\ntype KeyboardCallback = (height: number, duration: number) => void;\nexport declare const keyboardEventsOn: (cb: KeyboardCallback) => void;\nexport declare const keyboardEventsOff: (cb: KeyboardCallback) => void;\nexport {};\n","types/runtime/channel.d.ts":"export {};\n","types/runtime/clipboard.d.ts":"export declare const clipboard: {\n /** Put `text` on the system clipboard. Silent no-op on hosts without clipboard access. */\n write(text: string): void;\n /** Read text from the system clipboard. Rejects when the platform has no clipboard access, the\n * user denied it, or there is nothing readable. */\n read(): Promise<string>;\n};\n","types/runtime/datetime.d.ts":"export type Locale = \"en\" | \"ru\";\nexport type DateInput = Date | number | string | DateValue;\nexport type Unit = \"ms\" | \"second\" | \"minute\" | \"hour\" | \"day\" | \"week\" | \"month\" | \"year\";\n/**\n * An immutable moment in time — the value returned by [`date()`]. Wraps a single epoch-millisecond\n * scalar (`t`); every method returns a new `DateValue` or a plain scalar, never mutating. Construct\n * it with `date(...)`, not `new`.\n */\nexport declare class DateValue {\n /** Epoch milliseconds — the one canonical scalar. Prefer `valueOf()`; this is public so `date(a)`\n * can read it back cheaply and so tooling can treat it as the value's single component. */\n readonly t: number;\n constructor(ms: number);\n /**\n * Format against a `day.js`-style token pattern (default `\"D MMMM YYYY\"`). Locale defaults to the\n * current device language.\n *\n * Tokens: `YYYY`/`YY` year · `MMMM`/`MMM`/`MM`/`M` month · `DD`/`D` day · `dddd`/`ddd` weekday ·\n * `HH`/`H` 24-hour · `hh`/`h` 12-hour · `mm`/`m` minute · `ss`/`s` second · `A`/`a` AM/PM.\n *\n * ```ts\n * date().format() // \"10 July 2026\" / \"10 июля 2026\"\n * date(ts).format(\"DD.MM.YYYY HH:mm\") // \"10.07.2026 14:05\"\n * date(ts).format(\"MMMM YYYY\", \"ru\") // \"Июль 2026\" (nominative — no day token)\n * ```\n */\n format(pattern?: string, locale?: Locale): string;\n /**\n * Human relative time vs `now` (default: the current time) — \"5 minutes ago\", \"in 2 days\",\n * \"5 минут назад\", \"через 2 дня\". Reads as \"just now\" under ~45 seconds; handles Russian number\n * agreement (`1 минуту` / `2 минуты` / `5 минут`). Locale defaults to the device language.\n */\n timeAgo(locale?: Locale, now?: DateInput): string;\n /** Add `n` of a unit, returning a new value. Linear units (`ms`…`week`) are scalar ms math;\n * `month`/`year` are calendar-aware (clamp on short months, like day.js). */\n add(n: number, unit: Unit): DateValue;\n /** Subtract `n` of a unit. Equivalent to `add(-n, unit)`. */\n subtract(n: number, unit: Unit): DateValue;\n /** Snap down to the start of a unit (local time): start of day/hour/month/year, etc. */\n startOf(unit: Unit): DateValue;\n /** Snap up to the end of a unit (local time): the last millisecond of the day/hour/month/… */\n endOf(unit: Unit): DateValue;\n /** Epoch milliseconds. Enables `+date(x)`, `date(a) < date(b)`, `date(a) - date(b)` via coercion. */\n valueOf(): number;\n /** Whole seconds since the epoch (Unix time). */\n unix(): number;\n /** Signed difference to `other`, in whole `unit`s (default `ms`), truncated toward zero. */\n diff(other: DateInput, unit?: Unit): number;\n isBefore(other: DateInput): boolean;\n isAfter(other: DateInput): boolean;\n isSame(other: DateInput): boolean;\n year(): number;\n /** 0-based month (0 = January), matching `Date.getMonth`. */\n month(): number;\n /** Day of the month, 1–31. */\n day(): number;\n /** Day of the week, 0 (Sunday)–6 (Saturday), matching `Date.getDay`. */\n weekday(): number;\n hour(): number;\n minute(): number;\n second(): number;\n /** A native `Date` snapshot of this value. */\n toDate(): Date;\n}\n/**\n * Create a `DateValue` — a locale-aware, immutable moment, dayjs-style. Accepts a `Date`, a\n * millisecond timestamp (`Date.now()`), a parseable string, or another `DateValue`; with no argument\n * it's the current time. Chain arithmetic and finish with `format` / `timeAgo`, both of which\n * understand **English** and **Russian** and default to the current device language\n * ([`device.language`](../runtime/device.ts)).\n *\n * ```ts\n * date().format(\"dddd, D MMMM\") // \"Friday, 10 July\" / \"пятница, 10 июля\"\n * date(ts).timeAgo() // \"5 minutes ago\" / \"5 минут назад\"\n * date().add(3, \"day\").startOf(\"day\").format(\"D MMMM\")\n * date(a).diff(b, \"hour\") // signed whole hours\n * date(a).isBefore(b) // boolean\n * ```\n */\nexport declare const date: (value?: DateInput) => DateValue;\n","types/runtime/device.d.ts":"import { Quat } from \"../math/quat\";\nimport { Vec3 } from \"../math/vec\";\ntype ResizeCallback = (width: number, height: number) => void;\ntype DeviceEventMap = {\n resize: ResizeCallback;\n /** Connectivity came back (best-effort, navigator.onLine semantics). */\n online: () => void;\n /** Connectivity was lost. */\n offline: () => void;\n};\n/** Semantic haptic styles for `device.vibrate`. Impact styles (`light`/`medium`/`heavy`/`soft`/\n * `rigid`) are a physical \"tap\" of varying weight; notification styles (`success`/`warning`/`error`)\n * cue an outcome; `selection` is a light tick for a value change. Chosen to map 1:1 onto iOS\n * `UIFeedbackGenerator` and, on Android, `HapticFeedbackConstants` / `VibrationEffect` — so the same\n * call feels native everywhere, rather than a duration that only web/Android can honor. */\nexport type HapticStyle = \"light\" | \"medium\" | \"heavy\" | \"soft\" | \"rigid\" | \"success\" | \"warning\" | \"error\" | \"selection\";\n/** Options for `device.motion.start`. */\nexport interface MotionOptions {\n /** Sensor update interval in seconds (default 1/60). The sensor fuses at ≥ this rate in the\n * background; you poll the freshest sample each frame, so this is a floor, not a sync. */\n interval?: number;\n /** Frame the readables are delivered in. \"world\" (default): engine Y-up, screen-oriented — drops\n * straight into `camera.quaternion` / any node. \"device\": the raw sensor frame, no conversion. */\n frame?: \"world\" | \"device\";\n}\nexport declare const device: {\n readonly platform: \"web\" | \"android\" | \"ios\" | string;\n readonly language: string;\n /** Display device-pixel ratio (physical px per logical/CSS px): 1 on standard displays, 2–3 on\n * retina / iOS. Bake a Canvas at this ratio for crisp output without hardcoding, e.g.\n * `new Canvas(w, h, { pixelRatio: device.pixelRatio })`. NOTE: the web 2D/GL surface currently\n * renders at logical resolution, so on web this only helps UI canvases / is forward-looking for\n * 2D; on iOS (physical surface) it makes 2D canvases crisp. Falls back to 1 if the host omits it. */\n readonly pixelRatio: number;\n /** Current display width in logical px — the same value the \"resize\" event delivers, but readable at\n * any time (not only inside the listener). 0 until the host has reported a size. */\n readonly width: number;\n /** Current display height in logical px — the same value the \"resize\" event delivers, readable at any\n * time. 0 until the host has reported a size. */\n readonly height: number;\n /** Opt into the precise-touch system where the platform supports it. OFF by default. When on, fast\n * strokes are sampled at the touch digitizer's full rate (iOS coalesced touches, ≈120–240 Hz) instead\n * of once per display frame (~60 Hz), so a pointer-heavy app (drawing, handwriting, dragging) gets more\n * points and smoother lines. Leave it off for tap/button UIs. No-op on hosts without a coalesced-input\n * concept (web already coalesces pointermove; headless). */\n setPreciseTouch(enabled: boolean): void;\n /** Fire a one-shot haptic of the given semantic `style` (default `\"medium\"`) — a physical tap on\n * supported hardware (iOS Taptic Engine, Android vibrator). Chosen by meaning, not duration, so it\n * feels native on each platform; see {@link HapticStyle}. Host-gated: a silent no-op where there's\n * no haptic hardware (iPad, older iPhones, web, headless). */\n vibrate(style?: HapticStyle): void;\n /** Device-orientation sensor (gyro + accelerometer, fused) for tilt/steering and magic-window /\n * 360° panoramas. Poll `attitude` / `gravity` inside setLoop; they return the freshest fused\n * sample, so the sensor rate need not match your frame rate. Host-gated: a no-op with no sensor. */\n motion: {\n /** Whether this device has the motion sensors at all (no gyro → false; iPad/older, web, headless). */\n readonly available: boolean;\n /** Whether updates are currently running (start succeeded and stop hasn't been called). */\n readonly enabled: boolean;\n /** Begin sensor updates. Resolves to whether it actually started (false = no sensor / denied).\n * Async so a web host can await its permission prompt; native resolves immediately. */\n start(options?: MotionOptions): Promise<boolean>;\n /** Stop sensor updates and release the sensor (battery). */\n stop(): void;\n /** Capture the current heading as \"forward\" — a yaw-only recenter (pitch/roll stay gravity-\n * referenced, so the horizon stays level). No-op in the \"device\" frame. */\n recenter(): void;\n /** The device's current orientation as a `Quat`. In the \"world\" frame (default) it's engine Y-up\n * and screen-oriented, so `camera.quaternion = device.motion.attitude` is a complete magic-window\n * / panorama camera. `Quat.identity` until the first sample arrives / when not running. */\n readonly attitude: Quat;\n /** Gravity direction for tilt controls. In the \"world\" frame it's SCREEN space (x → right, y →\n * down, matching clientX/clientY), orientation-aware — a 2D game reads `gravity.x / gravity.y`.\n * `(0,0,0)` when not running. */\n readonly gravity: Vec3;\n };\n /** Current connectivity — best-effort navigator.onLine semantics: `false` only when the platform\n * is sure there's no network. `true` on hosts that don't track it. Change events: `\"online\"` /\n * `\"offline\"`. */\n readonly online: boolean;\n addEventListener<E extends keyof DeviceEventMap>(channel: E, callback: DeviceEventMap[E]): void;\n removeEventListener<E extends keyof DeviceEventMap>(channel: E, callback: DeviceEventMap[E]): void;\n};\nexport {};\n","types/runtime/fetch.d.ts":"export type FetchOptions = {\n body?: any;\n method?: string;\n headers?: Record<string, string>;\n useOnce?: boolean;\n onProgress?: (progress: {\n loaded: number;\n total?: number;\n }) => void;\n};\nexport interface FetchResponse {\n readonly status: number;\n json<T = any>(): T;\n text(): string;\n dispose(): void;\n}\nexport declare const fetch: (url: string, options?: FetchOptions) => Promise<FetchResponse>;\nexport declare const fetchLocal: (path: string) => FetchResponse;\n/** A handle to a picked / fetched file (see openFilePicker). */\nexport declare class File {\n readonly name: string;\n readonly size: number;\n constructor(systemId: number, name: string, size: number);\n}\ntype FormDataValue = string | number | boolean | File | FetchResponse;\nexport declare class FormData {\n private _entries;\n append(name: string, value: FormDataValue, filename?: string): void;\n delete(name: string): void;\n}\nexport {};\n","types/runtime/files.d.ts":"import { File } from \"./fetch\";\ntype OpenFilePickerOptions = {\n accept?: string;\n};\nexport declare function openFilePicker(options?: OpenFilePickerOptions & {\n multiple?: false;\n}): Promise<File | null>;\nexport declare function openFilePicker(options: OpenFilePickerOptions & {\n multiple: true;\n}): Promise<File[]>;\nexport {};\n","types/runtime/input.d.ts":"export declare const Input: {\n /**\n * Is a key currently held? `code` is a KeyboardEvent.code-style string, e.g. 'ArrowRight',\n * 'KeyW', 'Space'. Poll this inside setLoop for frame-independent movement.\n */\n key(code: string): boolean;\n};\n","types/runtime/media.d.ts":"import { Emitter } from \"../core/events\";\nimport { Texture } from \"../gl/Texture\";\ntype MediaEvents = {\n /** Fired at each loop boundary while `loop` is true. */\n loopReached: () => void;\n /** Fired once when playback reaches the end while `loop` is false. */\n completed: () => void;\n};\ndeclare abstract class MediaPlayer extends Emitter<MediaEvents> {\n protected _id: number;\n protected _src: string;\n private _playing;\n private _loop;\n private _volume;\n private _disposed;\n private _assertAlive;\n play(): void;\n pause(): void;\n get playing(): boolean;\n set playing(value: boolean);\n get volume(): number;\n set volume(value: number);\n get loop(): boolean;\n set loop(value: boolean);\n /** Current playback position, in seconds. Settable to seek. */\n get time(): number;\n set time(value: number);\n /** Total media length in seconds (0 until metadata has loaded). */\n get duration(): number;\n /** True once {@link dispose} has been called; the player is unusable afterwards. */\n get disposed(): boolean;\n /**\n * Release the underlying host media resource (decoder, network, buffers) immediately and detach\n * all listeners. Idempotent. Any further use of the player throws.\n */\n dispose(): void;\n}\nexport declare class AudioPlayer extends MediaPlayer {\n constructor(src?: string);\n}\nexport declare class VideoPlayer extends MediaPlayer {\n constructor(src?: string);\n /** A 3D Texture that samples this video (e.g. for a Material.video()). */\n get texture(): Texture;\n}\nexport {};\n","types/runtime/misc.d.ts":"/** Show a transient toast notification. */\nexport declare const toast: (msg: string) => void;\n/** Open `url` in the system browser / external handler (fire-and-forget, like `share`). Silent\n * no-op on hosts without one (headless). */\nexport declare const openURL: (url: string) => void;\nexport type SvgSourceValue = {\n readonly svg: string;\n tintColor: string | null;\n};\n/** Wrap raw SVG XML so it can be used as an image source. */\nexport declare const SvgSource: (svg: string) => SvgSourceValue;\n","types/runtime/net.d.ts":"import { Emitter } from \"../core/events\";\ntype SocketEvents = {\n open: () => void;\n message: (data: any) => void;\n close: (code?: number) => void;\n error: () => void;\n};\nexport declare class WebSocket extends Emitter<SocketEvents> {\n private _id;\n constructor(url: string, headers?: Record<string, string>);\n send(message: string | ArrayBuffer): void;\n close(): void;\n private _onMessage;\n}\nexport {};\n","types/runtime/rpc.d.ts":"/**\n * Client transport for the app backend (docs/backend-plan.md §3.2 / §3.3). The compiler replaces\n * every `*.server.ts` module in the client bundle with a stub whose exports are built by the three\n * globals below — user code never calls them; it imports the server function and calls it.\n *\n * export const listNotes = __rpc(\"<serverUrl>\", \"notes.server.ts#listNotes\")\n * export const chat = __channel(\"<serverUrl>\", \"chat.server.ts#chat\")\n * export const db = __serverOnly(\"schema.server.ts#db\")\n *\n * Wire (implemented by the runner):\n * POST <serverUrl>/api/<id> body {\"args\":[…]}, `authorization: Bearer <session>` when known\n * → 200 {\"ok\":true,\"result\":…,\"session\"?:\"…\"} | {\"ok\":false,\"status\":n,\"message\":\"…\",\"session\"?:\"…\"}\n * WS <serverUrl>/ws frames: → {t:\"hello\",session} {t:\"sub\",id,ch,topic} {t:\"unsub\",id}\n * ← {t:\"session\",session} {t:\"ok\",id} {t:\"err\",id,status,message} {t:\"ev\",ch,topic,event,data}\n * (`ev` is addressed by channel + topic, not by subscription id, so the server can fan one publish out\n * to every socket of a topic natively; the client delivers it to each matching subscription.)\n *\n * The session token is transport-owned (cookie-like): stored under `lecodes.session:<serverUrl>` in\n * localStorage, sent on every call and on the socket, replaced whenever a response carries `session`.\n * User code never sees it — \"am I logged in\" is an endpoint (`me()`), see the plan.\n */\n/** Rejection value of a failed endpoint call: `status` mirrors the server's `ApiError`\n * (0 = the request itself failed: no network / no server). */\nexport declare class RpcError extends Error {\n readonly status: number;\n constructor(status: number, message: string);\n}\n/** Build the client proxy of endpoint `id`. Positional args travel as a JSON array. */\nexport declare const __rpc: (serverUrl: string, id: string) => (...args: unknown[]) => Promise<any>;\n/** A server-only export (db, models, helpers) referenced from client code: any use throws. */\nexport declare const __serverOnly: (id: string) => any;\nexport interface ClientChannel<E extends Record<string, unknown> = Record<string, unknown>> {\n /** Subscribe to `topic`; handlers are keyed by event name (+ `reconnect`/`error`). Returns `{ close }`. */\n subscribe(topic: string, handlers: {\n [K in keyof E]?: (payload: E[K]) => void;\n } & {\n reconnect?: () => void;\n error?: (e: RpcError) => void;\n }): {\n close(): void;\n };\n}\n/** Build the client proxy of channel `id`. */\nexport declare const __channel: (serverUrl: string, id: string) => ClientChannel<any>;\n","types/runtime/service.d.ts":"export {};\n","types/runtime/share.d.ts":"import type { File, FetchResponse } from \"./fetch\";\nexport declare function share(media: File | FetchResponse, text?: string): void;\n","types/runtime/storage.d.ts":"export declare const localStorage: {\n getItem(key: string): string | null;\n setItem(key: string, value: string): void;\n removeItem(key: string): void;\n};\n","types/runtime/touch.d.ts":"export declare class ClickEvent<T = any> {\n readonly type = \"click\";\n readonly pointerId: number;\n readonly clientX: number;\n readonly clientY: number;\n /** World-space hit position (2D scenes only; undefined in 3D). */\n worldX?: number;\n worldY?: number;\n target: T;\n constructor(clientX: number, clientY: number, pointerId: number);\n}\nexport interface TrackHandler {\n onMove?(pos: {\n clientX: number;\n clientY: number;\n deltaX: number;\n deltaY: number;\n }): void;\n onEnd?(pos: {\n clientX: number;\n clientY: number;\n deltaX: number;\n deltaY: number;\n }): void;\n onCancel?(): void;\n claim?: boolean | \"pan-x\" | \"pan-y\" | \"pan-down\" | \"pan-up\" | \"pan-left\" | \"pan-right\";\n}\nexport declare class TouchStartEvent<T = any> {\n readonly type = \"touchstart\";\n readonly pointerId: number;\n readonly clientX: number;\n readonly clientY: number;\n /** World-space hit position (2D scenes only; undefined in 3D). */\n worldX?: number;\n worldY?: number;\n target: T;\n constructor(clientX: number, clientY: number, pointerId: number);\n /** Capture subsequent moves/end for this pointer (drag/pan gestures). */\n track(handler: TrackHandler): void;\n}\n/** Delivered to a `UIButton` `onLongPress` handler when a finger is held on the button past the\n * host's long-press threshold. Like `TouchStartEvent` it can `track(...)` the rest of the gesture —\n * so the common \"press-and-hold, then drag to move\" flow is one handler: start the drag from here. */\nexport declare class LongPressEvent<T = any> {\n readonly type = \"longpress\";\n readonly pointerId: number;\n readonly clientX: number;\n readonly clientY: number;\n /** World-space hit position (2D scenes only; undefined in 3D). */\n worldX?: number;\n worldY?: number;\n target: T;\n constructor(clientX: number, clientY: number, pointerId: number);\n /** Capture subsequent moves/end for this pointer — drag the element after the hold. */\n track(handler: TrackHandler): void;\n}\n","types/scene/defineScene.d.ts":"import { type With } from \"../core/Aspect\";\nimport { use, ref, make, type AspectEntry, type MakeEntry as SharedMakeEntry } from \"./grammar\";\nimport type { ColorInput } from \"../core/color\";\nimport type { Vec3Like } from \"../math/vec\";\nimport { Scene, type SceneOptions } from \"../gl/Scene\";\nimport { Node } from \"../gl/Node\";\nimport { Mesh } from \"../gl/Mesh\";\nimport { Model } from \"../gl/Model\";\nimport { Light, type SunOptions } from \"../gl/Light\";\nimport { Material, type LitMaterialOptions, type MaterialColorOptions } from \"../gl/Material\";\nimport type { CylinderOptions, PlaneOptions, SphereOptions } from \"../gl/Geometry\";\nexport type MeshDef = {\n kind: \"box\";\n size?: Vec3Like | number;\n} | ({\n kind: \"sphere\";\n} & SphereOptions) | ({\n kind: \"cylinder\";\n} & CylinderOptions) | ({\n kind: \"plane\";\n} & PlaneOptions);\nexport type LightDef = {\n kind: \"sun\";\n} & SunOptions;\nexport type MaterialDef = {\n lit: LitMaterialOptions;\n} | {\n unlit: MaterialColorOptions;\n} | {\n shadow: ColorInput;\n} | Material;\nexport { use, ref, make };\nexport type { AspectEntry };\n/** A `make(fn, args)` source entry whose factory returns a 3D {@link Node}. */\nexport type MakeEntry<A extends Record<string, unknown> = Record<string, unknown>> = SharedMakeEntry<A, Node>;\n/** Transform overrides for one INTERNAL node of a GLB model or a prefab instance\n * (`overrides` on a model/prefab node, keyed by part path). */\nexport type ModelOverrideDef = {\n position?: Vec3Like;\n eulerAngles?: Vec3Like;\n scale?: Vec3Like | number;\n visible?: boolean;\n};\n/** Camera projection settings, shared by the `camera:` source block and the top-level `camera:`\n * block. All optional — an omitted key keeps the host default (60° / 0.01 / 1000). */\nexport type CameraProjectionDef = {\n /** Vertical field of view in degrees (default 60) — smaller is a longer lens. */\n fov?: number;\n /** Near clip distance (default 0.01). */\n near?: number;\n /** Far clip distance = view range (default 1000); geometry past it is culled. */\n far?: number;\n};\n/** The `camera: {}` source block — projection settings for the node that drives the view. */\nexport type CameraNodeDef = CameraProjectionDef;\nexport type SceneNodeDef = {\n mesh?: MeshDef;\n /** GLB url — `asset('./hero.glb')`. */\n model?: string;\n light?: LightDef;\n /** The scene camera as a NODE: in play mode `scene.camera` follows this node's world transform\n * every frame (so movement aspects on it are camera flythroughs); the editor shows a frustum\n * marker and refuses to delete the last camera node. The first camera node in file order wins;\n * cameras inside prefabs are ignored (like a prefab's `camera:` block). */\n camera?: CameraNodeDef;\n /** A code-built subtree — `make(factoryFn, { ...literal args })`. */\n make?: MakeEntry<any>;\n /** Another scene file used as a reusable composition — the imported handle:\n * `import streetlamp from './streetlamp.scene'` … `lamp: { prefab: streetlamp }`. Its nodes\n * instantiate under this node per instance (env/camera are the instancing file's business and\n * are ignored); `ref()`s inside the prefab resolve file-locally, per instance. */\n prefab?: SceneHandle<any>;\n /** Material for a `mesh` source. */\n material?: MaterialDef;\n /** Model/prefab sources: transform overrides for the INTERNAL nodes, keyed by part path\n * (see the part-path grammar above `modelPartRows`). Unresolved paths are ignored. */\n overrides?: Record<string, ModelOverrideDef>;\n /** On a CHILD of a model/prefab node: parent this node to that INTERNAL part of the parent's\n * asset at build time (part path — the same grammar `overrides` keys use), e.g. a flashlight\n * in a hand. The transform stays local to the part. A stale path (asset changed) falls back\n * to the parent root with a console warning. */\n mount?: string;\n position?: Vec3Like;\n eulerAngles?: Vec3Like;\n scale?: Vec3Like | number;\n visible?: boolean;\n /** Editor-only: viewport manipulation won't target this node (fields still edit). No runtime effect. */\n locked?: boolean;\n castShadows?: boolean;\n receiveShadows?: boolean;\n aspects?: readonly AspectEntry<any>[];\n children?: Record<string, SceneNodeDef>;\n};\nexport type SceneCameraDef = CameraProjectionDef & {\n position?: Vec3Like;\n /** Point the camera looks at. */\n target?: Vec3Like;\n};\nexport type SceneDef = {\n env?: SceneOptions;\n camera?: SceneCameraDef;\n nodes?: Record<string, SceneNodeDef>;\n};\ntype SourceNodeOf<N extends SceneNodeDef> = N extends {\n model: string;\n} ? Model : N extends {\n mesh: MeshDef;\n} ? Mesh : N extends {\n light: LightDef;\n} ? Light : Node;\ntype AspectsOf<N extends SceneNodeDef> = N extends {\n aspects: readonly AspectEntry<infer A>[];\n} ? A : never;\ntype NodeOf<N extends SceneNodeDef> = [\n AspectsOf<N>\n] extends [never] ? SourceNodeOf<N> : With<SourceNodeOf<N>, AspectsOf<N>>;\ntype UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (k: infer I) => void ? I : never;\ntype ChildMapsOf<T extends Record<string, SceneNodeDef>, P extends string> = {\n [K in keyof T & string]: T[K] extends {\n children: infer C extends Record<string, SceneNodeDef>;\n } ? NodesOf<C, `${P}${K}/`> : never;\n}[keyof T & string];\ntype NodesOf<T extends Record<string, SceneNodeDef>, P extends string = \"\"> = {\n [K in keyof T & string as `${P}${K}`]: NodeOf<T[K]>;\n} & ([ChildMapsOf<T, P>] extends [never] ? unknown : UnionToIntersection<ChildMapsOf<T, P>>);\nexport type SceneNodes<D extends SceneDef> = D[\"nodes\"] extends Record<string, SceneNodeDef> ? NodesOf<D[\"nodes\"]> : Record<string, Node>;\nexport type LoadedScene<D extends SceneDef> = {\n scene: Scene;\n nodes: SceneNodes<D>;\n /** Path lookup — typed for this scene's literal paths, `Node | null` for arbitrary strings. */\n get: {\n <P extends keyof SceneNodes<D> & string>(path: P): SceneNodes<D>[P];\n (path: string): Node | null;\n };\n};\n/** One INTERNAL node of a loaded GLB (editor introspection). */\nexport type ModelPartRow = {\n path: string;\n name: string;\n depth: number;\n node: Node;\n};\n/** Flatten a model's (or prefab instance's) internal hierarchy to rows (depth-first, the root\n * excluded). `__generated` containers are derived output, and def-built nodes (`_sceneDef` —\n * plain or `mount`ed children of the model) are addressed by their own def paths — both are\n * not parts, skipped. Filtering BEFORE segment math keeps `name[i]` indices stable no matter\n * what defs are parented in. */\nexport declare const modelPartRows: (root: Node) => ModelPartRow[];\nexport declare class SceneHandle<D extends SceneDef = SceneDef> {\n readonly def: D;\n private _loading?;\n constructor(def: D);\n /** Instantiate the scene (idempotent — subsequent calls return the same instance). Does not open. */\n load(): Promise<LoadedScene<D>>;\n /** Load and make active. */\n open(): Promise<LoadedScene<D>>;\n}\n/**\n * Define a scene as data — the default export of a `.scene.ts` file. Returns a typed handle:\n * `const { scene, nodes, get } = await handle.open()` gives `nodes[path]` typed by its source\n * block (Mesh / Model / Light / Node) with its `use(...)`d aspects attached — root nodes read as\n * plain properties (`nodes.hero`), nested ones by path (`nodes['hero/halo']` / `get('hero/halo')`).\n */\nexport declare const defineScene: <const D extends SceneDef>(def: D) => SceneHandle<D>;\n","types/scene/editorPlugins.d.ts":"import type { InspectorUI } from \"../core/InspectorUI\";\n/** A geometry hit under the viewport pointer, handed to tools. Physics builds raycast the scene's\n * meshes (precise); otherwise (and on misses) the hit falls back to the ground plane (y = 0). */\nexport type EditorRayHit = {\n point: [number, number, number];\n normal: [number, number, number];\n /** Absolute path of the scene-file node the hit belongs to (\"city/in1/pt1\") — null for\n * ground-plane fallback hits. */\n node: string | null;\n};\n/**\n * The editor scripting API handed to windows and tools. Nodes are addressed by ABSOLUTE PATH —\n * '/'-joined names from the scene root; a root node's path is its bare name. Doc-op methods write\n * the scene DOCUMENT through the editor's normal commit path (undo, file, live patching all\n * included); they return false / no-op when the document can't take the edit (sibling-name\n * collision, unknown path).\n */\nexport type EditorApi = {\n /** The currently selected node path (or `path::part` key for asset internals), null when\n * nothing is selected. */\n readonly selection: string | null;\n select(path: string | null): void;\n /** The scene document's nodes: absolute path, sibling-unique display name, source kind\n * (mesh / model / light / group / …). */\n nodes(): {\n path: string;\n name: string;\n kind: string;\n }[];\n /** First unused \"base\", \"base2\", \"base3\", … name among the SIBLINGS under `parentPath`\n * (scene root when omitted). */\n uniqueName(base: string, parentPath?: string): string;\n /** Add a ROOT node from plain def data (scene-file grammar; a string `model` value means an\n * asset path). `name` may not contain '/' or ':'. One undo step unless grouped by `transact`. */\n addNode(name: string, def: Record<string, unknown>): boolean;\n /** Write one def prop (transforms apply live; anything else patches/re-runs the node). */\n setProp(path: string, key: string, value: unknown): boolean;\n removeNode(path: string): void;\n /** Duplicate a node; returns the copy's path (null when it can't). */\n duplicate(path: string): string | null;\n /** Raycast the scene under a viewport pixel (same hit rules as tool clicks). */\n raycast(screenX: number, screenY: number): EditorRayHit | null;\n /** Group every doc edit inside `fn` into ONE undo step. */\n transact(fn: () => void): void;\n};\nexport type EditorWindowFn = (ui: InspectorUI, editor: EditorApi) => void;\nexport type EditorToolHooks = {\n /** CSS cursor for the viewport while this tool is active (default \"crosshair\"). */\n cursor?: string;\n /** A short glyph (one character / emoji) for the tool's toolbar button — tools without one all\n * share the generic wand icon, so any editor with two or more tools should set it. */\n icon?: string;\n /** A viewport click while the tool is active — `hit` is the raycast result under the pointer.\n * Viewport clicks route to the tool while it is active. */\n onViewportClick?(hit: EditorRayHit, editor: EditorApi): void;\n};\n/** Register an editor panel — a collapsible overlay docked over the viewport (the inspector rail\n * stays selection-scoped). A window that emits `ui.toolButton` for a tool becomes that tool's\n * settings panel: activating the tool expands and highlights it. `render` re-runs immediate-mode\n * on every interaction — same protocol as `static inspector` cards. */\nexport declare const registerEditorWindow: (title: string, render: EditorWindowFn) => void;\n/** Register a viewport tool — a toolbar entry beside move/rotate/scale (activate it there or via\n * `ui.toolButton(label, name)`). While active, viewport clicks arrive as raycast hits. */\nexport declare const registerEditorTool: (name: string, hooks: EditorToolHooks) => void;\n","types/scene/grammar.d.ts":"import type { Aspect, AspectCtor } from \"../core/Aspect\";\nimport type { Node } from \"../gl/Node\";\n/** One aspect to attach, created by `use(Ctor, props)`. */\nexport type AspectEntry<A extends Aspect<any, any> = Aspect<any, any>> = {\n ctor: AspectCtor<A>;\n props?: Partial<A>;\n};\n/** Reference an aspect in a scene file: `aspects: [use(Physics, { motion: 'static' })]`. Props are\n * typechecked against the aspect's fields, exactly like `node.aspect(Ctor, props)`. */\nexport declare const use: <A extends Aspect<any, any>>(ctor: AspectCtor<A>, props?: Partial<A>) => AspectEntry<A>;\n/** A `make(fn, args)` source entry — see {@link make}. `N` is the node family the factory returns\n * (3D `Node` by default; a `.scene2d.ts` file's factories return `Node2D`). */\nexport type MakeEntry<A extends Record<string, unknown> = Record<string, unknown>, N = Node> = {\n fn: (args: A) => N | Promise<N>;\n args?: A;\n};\n/**\n * A code-created source in a scene file: `tower: { make: make(buildTower, { floors: 5 }), … }`.\n * The factory runs after every scene node exists (so `ref()` args resolve, forward references\n * included) and its returned subtree mounts under the def node — the def's transform stays\n * editor-owned, so moving the node never re-calls the factory. Args must be literal data (same\n * grammar as aspect props); in the editor they edit as fields, and an arg change re-CALLS the\n * factory live — the code is already in the bundle, so no compile happens. Keep factories pure\n * builders: same args → same subtree, no side effects outside the returned nodes.\n */\nexport declare const make: <A extends Record<string, unknown>, N>(fn: (args: A) => N | Promise<N>, args?: A) => MakeEntry<A, N>;\n/**\n * Reference another scene node by PATH in an aspect's props:\n * `use(Road, { from: ref('pointA'), to: ref('lane/pointB') })`. Resolves to the live node when\n * aspects attach — after EVERY node of the scene exists, so declaration order doesn't matter.\n * Resolution is scoped upward from the host node (like variable scoping): the host's own children\n * first, then its siblings, then each ancestor's scope up to the scene root. The FIRST segment\n * binds the scope; the remaining segments descend from there. Refs address def nodes only (no\n * `::`/`name[i]` asset-internal segments); an unknown path resolves to `null` (type your aspect\n * field `Node | null`). Scene files only — hand-written code passes nodes directly:\n * `node.aspect(Road, { from: nodes.pointA })`.\n */\nexport declare const ref: <T = Node>(path: string) => T;\nexport declare const isNodeRef: (v: unknown) => v is {\n $ref: string;\n};\n/** Resolve one ref string against a path-keyed nodes record, scoped upward from `hostPath` (own\n * children → parent's scope (siblings + the host itself) → each ancestor scope → root, `\"\"`).\n * The ref's FIRST segment binds the scope — a match there is final even when the rest of the\n * path doesn't exist (lexical shadowing). Returns the target's ABSOLUTE path, or null.\n * `Object.hasOwn`, not indexing: a node named `constructor` must not resolve via the prototype. */\nexport declare const resolveRefPath: (nodes: Record<string, unknown>, hostPath: string, ref: string) => string | null;\n/** Swap `ref()` markers in aspect props for the live nodes (top level + one array level deep),\n * resolved scoped-upward from `hostPath` (\"\" = root scope only — the 2D flat-map case). */\nexport declare const resolveRefs: <N>(props: Record<string, unknown> | undefined, nodes: Record<string, N>, hostPath?: string) => Record<string, unknown> | undefined;\n/** ABSOLUTE paths of the nodes a props record's ref() values resolve to (editor dep tracking).\n * An unresolved ref contributes no dep — the handle re-derives deps after structural changes. */\nexport declare const collectRefDeps: (props: Record<string, unknown>, nodes: Record<string, unknown>, hostPath: string) => Set<string>;\n/** The edit-mode flag an editor host sets before running the bundle (shared by both formats). */\nexport declare const EDIT_FLAG = \"__lecodesSceneEdit\";\nexport declare const isEditMode: () => boolean;\n","types/server/auth/appConfig.d.ts":"/**\n * The project's `app.json` subset the server runtime reads (name, auth providers).\n *\n * This module is a placeholder the COMPILER REPLACES: `compileServerBundle({ app })` puts a module with the\n * real values at this same path in chisel's file map (project files win over SDK files), so every SDK module\n * that imports `app` gets the project's config as a plain dependency — no globals, no evaluation-order games.\n * Outside a compiled bundle (tests, tooling) `globalThis.__lecodesApp` can stand in.\n */\nexport type AuthProvider = \"email\" | \"google\" | \"apple\" | \"yandex\" | \"vk\";\nexport type AppConfig = {\n name?: string;\n auth?: {\n providers?: AuthProvider[];\n };\n};\nexport declare const app: AppConfig;\n","types/server/auth/global.d.ts":"/**\n * The `auth` server global (docs/backend-plan.md §3.4) — the BUNDLE side. State (`auth.user`,\n * `auth.session`) is read from the current request, which the host resolved before the endpoint ran;\n * operations (`auth.email.*`, `auth.oauth.url`, `signIn/signOut`, `sessions`) forward to the host's\n * `AuthOps` on `globalThis.__lecodesAuth` (a seam: the compiled bundle carries its own SDK copy). Nothing\n * here touches the db or a secret; `auth.model.*` are pure schema factories.\n */\nimport type { Model, Query } from \"../db/types\";\nimport { type AuthProvider, type SessionFields, type UserFields } from \"./models\";\nimport type { AuthUser, OAuthCredential } from \"./types\";\n/** The schema of the two built-in models, for typing `auth.sessions` (developer extras aren't visible here). */\ntype AuthSchema = {\n User: Model<UserFields>;\n Session: Model<SessionFields>;\n};\nexport declare const auth: {\n /** The signed-in user (built-in fields; custom ones via `db.user`) or `null`. Request-scoped. */\n readonly user: AuthUser | null;\n /** The device session — exists from the first request, before any login. */\n readonly session: {\n readonly id: number;\n };\n /**\n * The signed-in user, or `throw new ApiError(401)`; with `match`, every given field must equal the user's\n * (`{ role: \"admin\" }`, `{ plan: \"pro\" }`) or it's a 403.\n */\n requireUser(match?: Record<string, unknown>): AuthUser;\n email: {\n /** Emails a 6-digit code to `email` (always resolves — no \"email exists\" oracle; rate-limited). Needs `\"email\"` in app.json providers. */\n sendCode: (email: string) => Promise<void>;\n /** The only email sign-in: checks the code sent to this device session, finds/creates the `User`, binds the session. */\n verify: (email: string, code: string) => Promise<AuthUser>;\n };\n oauth: {\n /** A one-time sign-in URL for the platform's OAuth broker (`\"google\" | \"apple\" | \"yandex\" | \"vk\"`), bound to this device session — open it in the browser. */\n url: (provider: Exclude<AuthProvider, \"email\">) => Promise<string>;\n /**\n * Sign in with a credential a NATIVE provider SDK produced in the app (client `OAuth.signIn(provider)`):\n * the platform verifies it with the provider, finds/links/creates the `User`, binds this session. The\n * in-app counterpart of the browser broker — same accounts either way.\n */\n signIn: (provider: Exclude<AuthProvider, \"email\">, credential: OAuthCredential) => Promise<AuthUser>;\n };\n /** Escape hatch for developer-verified identities (Telegram initData, SSO): binds this session to `userId`. */\n signIn: (userId: number) => Promise<AuthUser>;\n /** Unbinds the user; the device stays a guest with the same `session.id` (token rotated). */\n signOut: () => Promise<void>;\n /** The current user's sessions (\"my devices\"): a `db.session` query — `await`, `.select()`, `.where(...).updateMany({ revoked: true })`. */\n readonly sessions: Query<AuthSchema, \"Session\">;\n /** Schema-time factories — see ./models.ts. */\n model: {\n user: <E extends import(\"../db/types\").Fields = {}>(extra?: E) => import(\"./models\").AuthModel<UserFields & E>;\n session: <E extends import(\"../db/types\").Fields = {}>(extra?: E) => import(\"./models\").AuthModel<SessionFields & E>;\n };\n};\nexport type { AuthUser };\n","types/server/auth/models.d.ts":"/**\n * `auth.model.user({...})` / `auth.model.session()` — the ONLY place auth touches the schema\n * (docs/backend-plan.md §3.4 / decision 10). Both return ordinary `model(...)`s: the developer registers\n * them in `defineDb({ User, Session, … })` under exactly those keys (other models relate to them with\n * `t.one(\"User\")` / `t.one(\"Session\")`), and `defineDb` adds `Session` itself when it isn't declared —\n * a device session exists from the first request, before any login, so every project db has one.\n *\n * Provider identity columns (`googleId`, `appleId`) follow `app.json` `auth.providers`, which the\n * compiler hands the server bundle through ./appConfig.ts (a module it replaces at compile time).\n */\nimport { type Field } from \"../db/fields\";\nimport type { Fields, Model } from \"../db/types\";\nimport { type AppConfig, type AuthProvider } from \"./appConfig\";\nexport type { AppConfig, AuthProvider };\n/** The project's `app.json` subset: the compiled-in module, else the test/tooling seam, else empty. */\nexport declare const appConfig: () => AppConfig;\nexport declare const enabledProviders: () => AuthProvider[];\n/** The model name the auth runtime binds to. */\nexport declare const AUTH_USER_MODEL = \"User\";\nexport declare const AUTH_SESSION_MODEL = \"Session\";\n/** Marker on the two auth models (`model()` objects are otherwise plain). */\nexport type AuthModelKind = \"user\" | \"session\";\nexport type AuthModel<F extends Fields> = Model<F> & {\n readonly __auth: AuthModelKind;\n};\n/** Built-in `User` fields (what `auth.user` is typed with). */\nexport declare const userFields: () => {\n email: Field<string, {\n kind: \"scalar\";\n scalar: \"string\";\n optional: true;\n hasDefault: false;\n array: false;\n isId: false;\n model: \"\";\n }>;\n name: Field<string, {\n kind: \"scalar\";\n scalar: \"string\";\n optional: true;\n hasDefault: false;\n array: false;\n isId: false;\n model: \"\";\n }>;\n avatar: Field<string, {\n kind: \"scalar\";\n scalar: \"string\";\n optional: true;\n hasDefault: false;\n array: false;\n isId: false;\n model: \"\";\n }>;\n /** Plain string column, `\"user\"` by default — `auth.requireUser({ role: \"admin\" })` is field equality. */\n role: Field<string, {\n kind: \"scalar\";\n scalar: \"string\";\n optional: false;\n hasDefault: true;\n array: false;\n isId: false;\n model: \"\";\n }>;\n createdAt: Field<number, {\n kind: \"scalar\";\n scalar: \"date\";\n optional: false;\n hasDefault: true;\n array: false;\n isId: false;\n model: \"\";\n }>;\n};\nexport type UserFields = ReturnType<typeof userFields>;\n/** Built-in `Session` fields. `user` is added by `defineDb` when a `User` model exists (schema-time, so a\n * db without an auth user model has sessions without a user column). */\nexport declare const sessionFields: () => {\n /** sha256 of the bearer token the device holds — the token itself is never stored. */\n tokenHash: Field<string, import(\"../db/fields\").Meta<{\n kind: \"scalar\";\n scalar: \"string\";\n }>>;\n createdAt: Field<number, {\n kind: \"scalar\";\n scalar: \"date\";\n optional: false;\n hasDefault: true;\n array: false;\n isId: false;\n model: \"\";\n }>;\n lastSeenAt: Field<number, {\n kind: \"scalar\";\n scalar: \"date\";\n optional: false;\n hasDefault: true;\n array: false;\n isId: false;\n model: \"\";\n }>;\n revoked: Field<boolean, {\n kind: \"scalar\";\n scalar: \"bool\";\n optional: false;\n hasDefault: true;\n array: false;\n isId: false;\n model: \"\";\n }>;\n pendingEmail: Field<string, {\n kind: \"scalar\";\n scalar: \"string\";\n optional: true;\n hasDefault: false;\n array: false;\n isId: false;\n model: \"\";\n }>;\n codeHash: Field<string, {\n kind: \"scalar\";\n scalar: \"string\";\n optional: true;\n hasDefault: false;\n array: false;\n isId: false;\n model: \"\";\n }>;\n codeExpires: Field<number, {\n kind: \"scalar\";\n scalar: \"date\";\n optional: true;\n hasDefault: false;\n array: false;\n isId: false;\n model: \"\";\n }>;\n codeAttempts: Field<number, {\n kind: \"scalar\";\n scalar: \"int\";\n optional: false;\n hasDefault: true;\n array: false;\n isId: false;\n model: \"\";\n }>;\n};\nexport type SessionFields = ReturnType<typeof sessionFields> & {\n user: ReturnType<typeof sessionUserField>;\n};\nexport declare const sessionUserField: () => Field<never, {\n kind: \"one\";\n scalar: \"\";\n optional: true;\n hasDefault: false;\n array: false;\n isId: false;\n model: \"User\";\n}>;\n/** `auth.model.user({...extra})` — the built-in user (+ provider ids from app.json) plus the developer's fields. */\nexport declare const authUserModel: <E extends Fields = {}>(extra?: E) => AuthModel<UserFields & E>;\n/** `auth.model.session({...extra})` — declare it only to relate to sessions (`t.one(\"Session\")`) or to add fields. */\nexport declare const authSessionModel: <E extends Fields = {}>(extra?: E) => AuthModel<SessionFields & E>;\nexport declare const isAuthModel: (m: unknown, kind?: AuthModelKind) => m is AuthModel<any>;\n","types/server/auth/types.d.ts":"/**\n * Shared shapes of the auth layer (docs/backend-plan.md §3.4). Two sides meet through them:\n * - the BUNDLE side (`auth` global, ./global.ts) — what `*.server.ts` code calls;\n * - the HOST side (./host.ts) — sessions, email codes and OAuth binding, run by the runner with the\n * project's db handle and the platform's secrets. Installed on `globalThis.__lecodesAuth`.\n */\nimport type { RequestContext } from \"../context\";\nimport type { AuthProvider } from \"./models\";\n/** The built-in user row — what `auth.user` is typed with (custom fields exist at runtime; select them via `db.user`). */\nexport type AuthUser = {\n id: number;\n email: string | null;\n name: string | null;\n avatar: string | null;\n role: string;\n createdAt: number;\n};\n/** Per-request auth state, resolved by the host before the endpoint runs (`RequestContext.auth`). */\nexport type AuthState = {\n sessionId: number;\n userId: number | null;\n user: AuthUser | null;\n /** A token to hand back to the client in this response (a new guest session, or a rotation). */\n issuedToken?: string;\n};\n/** What an OAuth provider hands the runner after a successful web sign-in. */\nexport type OAuthProfile = {\n sub: string;\n email?: string | null;\n emailVerified?: boolean;\n name?: string | null;\n avatar?: string | null;\n};\n/** A credential a NATIVE provider SDK produced in the app (client plugin `OAuth.signIn`): an access token\n * (Yandex, VK ID) or an OpenID identity token (Google, Apple). Verified server-side, never trusted as-is. */\nexport type OAuthCredential = {\n accessToken?: string;\n idToken?: string;\n name?: string | null;\n email?: string | null;\n};\n/** Host operations the bundle's `auth` global forwards to (all request-scoped through `ctx`). */\nexport type AuthOps = {\n email: {\n sendCode(ctx: RequestContext, email: string): Promise<void>;\n verify(ctx: RequestContext, email: string, code: string): Promise<AuthUser>;\n };\n oauth: {\n url(ctx: RequestContext, provider: Exclude<AuthProvider, \"email\">): Promise<string>;\n signIn(ctx: RequestContext, provider: Exclude<AuthProvider, \"email\">, credential: OAuthCredential): Promise<AuthUser>;\n };\n signIn(ctx: RequestContext, userId: number): Promise<AuthUser>;\n signOut(ctx: RequestContext): Promise<void>;\n /** `db.session` filtered to the current user's sessions (or just this device's, when signed out). */\n sessions(ctx: RequestContext): any;\n};\n","types/server/channel.d.ts":"/**\n * Server side of channels (docs/backend-plan.md §3.3): typed pub/sub, server → client only.\n *\n * type ChatEvents = { message: { from: string; text: string }; typing: { from: string } }\n * export const chat = channel<ChatEvents>({ onJoin: room => { auth.requireUser() } })\n * chat.publish(room, \"message\", { from, text })\n *\n * A channel's identity is its export (`<path>#<name>`), assigned by the runtime when the bundle is\n * loaded (`loadServerModules`); `publish` before that is an error. Delivery goes through the\n * `globalThis.__lecodesPublish` seam the runner installs (same reason as ./context.ts: the bundle\n * carries its own SDK copy).\n */\nexport type ChannelEvents = Record<string, unknown>;\nexport type ChannelOptions = {\n /** Called when a client subscribes to `topic`; throw (e.g. `ApiError(403)`) to refuse. */\n onJoin?: (topic: string) => void | Promise<void>;\n};\nexport interface Channel<E extends ChannelEvents> {\n readonly options: ChannelOptions;\n /** Deliver `event` with `payload` to every subscriber of `topic` (at-most-once). */\n publish<K extends keyof E & string>(topic: string, event: K, payload: E[K]): void;\n}\ntype Publisher = (channelId: string, topic: string, event: string, payload: unknown) => void;\n/** Host hook (runner / test harness): where `publish` delivers to. */\nexport declare const setChannelPublisher: (publisher: Publisher | null) => void;\nexport declare const channel: <E extends ChannelEvents>(options?: ChannelOptions) => Channel<E>;\nexport declare const isChannel: (v: unknown) => v is Channel<any>;\nexport {};\n","types/server/context.d.ts":"/**\n * Request context for server code. The runner keeps the current request in an AsyncLocalStorage\n * and exposes it through `globalThis.__lecodesRequest` — a *global* seam on purpose: the compiled\n * server bundle carries its own copy of this module (chisel bundles the SDK in), so the host can't\n * hand it a value by import. `request` reads through that seam; outside a request (module load,\n * timers after the response) every member is undefined.\n */\nexport type RequestContext = {\n /** Endpoint id `<path>#<export>` (or the channel id for `onJoin`). */\n id: string;\n headers: Record<string, string>;\n ip?: string;\n /** Bearer session token as sent by the client transport (raw; auth resolves it). */\n sessionToken?: string;\n /** Set by the auth runtime after resolving the token — read via `auth.*`, not here. */\n auth?: unknown;\n};\ntype Provider = () => RequestContext | undefined;\n/** Host hook (runner / test harness): install the current-request provider. */\nexport declare const setRequestProvider: (provider: Provider | null) => void;\n/** The current request (server global). Undefined members outside a request. */\nexport declare const request: {\n readonly id: string | undefined;\n readonly headers: Record<string, string>;\n readonly ip: string | undefined;\n};\nexport {};\n","types/server/db/defineDb.d.ts":"/**\n * `model({...})` + `defineDb({ User, Post })` — the schema registry and the typed db handle.\n *\n * Runtime responsibilities: validate relation names, resolve `t.many()` back-fields, emit the `.marci`\n * schema text (`db.$schema`), and turn collection calls into lazy `Op`s over a `MarciTransport`\n * (`marcidb-embedded` handle, HTTP client, or a test fake). The transport is either passed to\n * `defineDb(models, { transport })` or provided by the host through `setDbTransport()` — user code\n * never sees a connection string.\n */\nimport type { FieldDef } from \"./fields\";\nimport { type MarciTransport } from \"./marci/query\";\nimport type { Db, Fields, Model, Schema, ValidateRefs } from \"./types\";\nexport declare const model: <F extends Fields>(fields: F) => Model<F>;\n/** Host hook: the runner/dev-server installs the project's transport before loading user code. */\nexport declare const setDbTransport: (transport: MarciTransport | null) => void;\n/**\n * Every `defineDb` call registers its handle here so the host finds the schema whether or not the\n * project exports `db` (`const db = defineDb(...)` used only inside endpoints is the common case).\n * The host reads and clears the list after evaluating a bundle (`loadServerModules`).\n */\nexport declare const takeRegisteredDbs: () => Db<any>[];\n/** A reference to a previous operation's result inside `$transaction` (resolved server-side): `ref(\"0.id\")`. */\nexport declare const ref: (path: string) => any;\ntype ModelMeta = {\n name: string;\n fields: Record<string, FieldDef>;\n idKeys: string[];\n /** id is a single uuid key we generate on insert. */\n uuidId: boolean;\n};\nexport declare const toMarci: (metas: Record<string, ModelMeta>) => string;\nexport type DefineDbOptions = {\n transport?: MarciTransport;\n};\nexport declare const defineDb: <const S extends Schema>(declared: S & ValidateRefs<S>, options?: DefineDbOptions) => Db<S>;\nexport {};\n","types/server/db/fields.d.ts":"/**\n * `t` — field builders for `model({...})`. Each builder returns an immutable `Field` carrying a runtime\n * `FieldDef` (what `.marci` is emitted from) and two phantom type parameters: the TS value type and a\n * `FieldMeta` record (kind / optional / default / …) that `defineDb`'s type layer projects into row,\n * insert, update, select and where types. Chained modifiers return a NEW field (builders are never\n * mutated), so `const s = t.string(); { a: s, b: s.optional() }` behaves as expected.\n */\nimport type { JsonValue } from \"./marci/query\";\nexport type ScalarKind = \"string\" | \"int\" | \"float\" | \"bool\" | \"date\" | \"uuid\" | \"\";\nexport type FieldKind = \"scalar\" | \"json\" | \"enum\" | \"struct\" | \"one\" | \"many\" | \"list\";\nexport type OnDelete = \"cascade\" | \"setNull\" | \"restrict\";\n/** Phantom metadata — the type-level twin of `FieldDef`. */\nexport type FieldMeta = {\n kind: FieldKind;\n scalar: ScalarKind;\n optional: boolean;\n hasDefault: boolean;\n array: boolean;\n isId: boolean;\n /** Related model name for one/many/list; \"\" otherwise. */\n model: string;\n};\ntype DefaultMeta = {\n kind: \"scalar\";\n scalar: \"\";\n optional: false;\n hasDefault: false;\n array: false;\n isId: false;\n model: \"\";\n};\nexport type Meta<O extends Partial<FieldMeta>> = {\n [P in keyof FieldMeta]: P extends keyof O ? O[P] : DefaultMeta[P];\n};\ntype SetMeta<M extends FieldMeta, K extends keyof FieldMeta, V> = {\n [P in keyof FieldMeta]: P extends K ? V : M[P];\n};\n/** Runtime field definition — everything the `.marci` emitter and the runtime need. */\nexport type FieldDef = {\n kind: FieldKind;\n scalar?: ScalarKind;\n optional: boolean;\n unique: boolean;\n index: boolean;\n hasDefault: boolean;\n default?: unknown;\n array: boolean;\n isId: boolean;\n onDelete?: OnDelete;\n fulltext?: \"multi\" | \"english\" | \"russian\";\n vector?: {\n size: number;\n metric: \"cosine\" | \"euclidean\";\n };\n /** enum */\n values?: readonly string[];\n /** struct */\n fields?: Record<string, Field<any, any>>;\n /** one / many / list */\n model?: string;\n /** many: the field on the related model that holds the reference (`@bind`); resolved by defineDb when omitted. */\n back?: string;\n};\ntype DefaultOf<T, M extends FieldMeta> = M[\"scalar\"] extends \"date\" ? \"now\" | number : M[\"array\"] extends true ? T[] : T;\nexport interface Field<T, M extends FieldMeta = FieldMeta> {\n /** phantom (type-level only — never set at runtime) */ readonly __t?: T;\n /** phantom (type-level only — never set at runtime) */ readonly __m?: M;\n readonly def: FieldDef;\n /** Nullable column (`String?`). */\n optional(): Field<T, SetMeta<M, \"optional\", true>>;\n /** `@unique` (on a relation: one-to-one). */\n unique(): Field<T, M>;\n /** `@index` — used by `$where`, `$order`, aggregations. */\n index(): Field<T, M>;\n /** `@default(...)`; `\"now\"` on `t.date()` → `now()`. Makes the field optional on insert. */\n default(value: DefaultOf<T, M>): Field<T, SetMeta<M, \"hasDefault\", true>>;\n /** Primitive list (`String[]`). */\n array(): Field<T, SetMeta<M, \"array\", true>>;\n /** `@id` — primary key (several → composite). A field literally named `id` is the key implicitly. */\n id(): Field<T, SetMeta<M, \"isId\", true>>;\n /** Referential policy for `t.one()` (defaults: required → restrict, optional → setNull). */\n onDelete(policy: OnDelete): Field<T, M>;\n /** `@fulltext(...)` module index on a string field; query with `$search`. */\n fulltext(lang?: \"multi\" | \"english\" | \"russian\"): Field<T, M>;\n /** `Float[n] @vector(metric)` — nearest-neighbour index; query with `$near`. */\n vector(size: number, metric?: \"cosine\" | \"euclidean\"): Field<T, M>;\n}\nexport declare const t: {\n string: () => Field<string, Meta<{\n kind: \"scalar\";\n scalar: \"string\";\n }>>;\n /** 64-bit signed integer. */\n int: () => Field<number, Meta<{\n kind: \"scalar\";\n scalar: \"int\";\n }>>;\n /** 64-bit float. */\n float: () => Field<number, Meta<{\n kind: \"scalar\";\n scalar: \"float\";\n }>>;\n bool: () => Field<boolean, Meta<{\n kind: \"scalar\";\n scalar: \"bool\";\n }>>;\n /** Epoch milliseconds — reads and writes as `number`. */\n date: () => Field<number, Meta<{\n kind: \"scalar\";\n scalar: \"date\";\n }>>;\n /** UUID string (16 bytes in storage). On an `id` field the runtime generates it on insert. */\n uuid: () => Field<string, Meta<{\n kind: \"scalar\";\n scalar: \"uuid\";\n }>>;\n /** Any JSON value; `J` is TS-only (marcidb stores it schemaless). Filter by dot-path in `$where`. */\n json: <J = JsonValue>() => Field<J, Meta<{\n kind: \"json\";\n }>>;\n /** String enum: `t.enum(\"draft\", \"published\")`. */\n enum: <const V extends readonly [string, ...string[]]>(...values: V) => Field<V[number], Meta<{\n kind: \"enum\";\n }>>;\n /** Owned nested object (marcidb `struct`): created/updated with the parent, no id of its own. */\n struct: <F extends Record<string, Field<any, any>>>(fields: F) => Field<F, Meta<{\n kind: \"struct\";\n }>>;\n /** Reference to one row of `model` (by id). Required unless `.optional()`. */\n one: <N extends string>(model: N) => Field<never, Meta<{\n kind: \"one\";\n model: N;\n }>>;\n /** Reverse side of a `t.one()` on `model` (the field is inferred when unambiguous). Read-only list. */\n many: <N extends string>(model: N, backField?: string) => Field<never, Meta<{\n kind: \"many\";\n model: N;\n }>>;\n /** Ordered relation list stored inline (`@list`) — hand-arranged collections, duplicates allowed. */\n list: <N extends string>(model: N) => Field<never, Meta<{\n kind: \"list\";\n model: N;\n }>>;\n};\nexport type T = typeof t;\nexport {};\n","types/server/db/index.d.ts":"export { t } from \"./fields\";\nexport type { Field, FieldDef, FieldMeta } from \"./fields\";\nexport { model, defineDb, ref, setDbTransport, toMarci } from \"./defineDb\";\nexport type { DefineDbOptions } from \"./defineDb\";\nexport type { Db, Model, Schema, Row, Id, Insert, Update, Select, Where, Query, QueryObject, Result, Collection, ScalarSelect, Types } from \"./types\";\nexport type { Op, MarciOp, MarciTransport, JsonValue, Sub } from \"./marci/query\";\n","types/server/db/marci/query.d.ts":"export type ServiceKeys = \"$where\" | \"$order\" | \"$limit\" | \"$skip\" | \"$cursor\";\nexport type JsonValue = string | number | boolean | null | JsonValue[] | {\n [key: string]: JsonValue;\n};\nexport type AggregateKeys = {\n $count: true;\n} | {\n $sum: string;\n} | {\n $avg: string;\n} | {\n $min: string;\n} | {\n $max: string;\n};\nexport type GetResult<TModel, TSelect> = TModel extends any ? {\n -readonly [K in keyof Omit<TSelect, ServiceKeys> as TSelect[K] extends false | undefined ? never : K extends keyof TModel ? K : never]: K extends keyof TModel ? TSelect[K] extends true ? TModel[K] : TSelect[K] extends Record<string, any> ? TModel[K] extends readonly object[] ? TSelect[K] extends AggregateKeys ? AggregateResult<NonNullable<TModel[K][number]>, TSelect[K]> : GetResult<NonNullable<TModel[K][number]>, TSelect[K]>[] : GetResult<NonNullable<TModel[K]>, TSelect[K]> | Extract<TModel[K], null> : TModel[K] : never;\n} : never;\nexport type RefUpdate<I> = {\n \"$connect\"?: I;\n};\nexport type RefUpdateStruct<I, U> = {\n \"$update\"?: U;\n \"$ensure\"?: I;\n \"$set\"?: I;\n};\n/** Relation to independent rows — link operations only, the rows themselves are never created\n * or deleted. `$set` replaces link membership with exactly the given set (missing links are\n * disconnected, new ones connected); `$connect` links (idempotent); `$remove` unlinks. */\nexport type RefListUpdate<I> = {\n \"$set\"?: I[];\n \"$connect\"?: I | I[];\n \"$remove\"?: I | I[];\n};\n/** `@list` relation: an ordered inline id array — a sequence, so the same id may appear several\n * times. `$set` replaces the whole array (also the reorder operation); `$connect` appends at the\n * end (an already-present id gains another occurrence); `$connectUnique` appends only ids not\n * already present; `$remove` removes every occurrence. */\nexport type RefListUpdateOrdered<I> = {\n \"$set\"?: I[];\n \"$connect\"?: I | I[];\n \"$connectUnique\"?: I | I[];\n \"$remove\"?: I | I[];\n};\n/** Owned (struct) list: the children live and die with the parent. `$push` creates children,\n * `$update` edits single children in place (each item is the child's id fields — the shape\n * query results return — plus the changes under `data`), `$remove` deletes children by id,\n * `$set` replaces all children (deletes the current ones, creates the new). */\nexport type RefListUpdateStruct<I, U, Id> = {\n \"$push\"?: I | I[];\n \"$update\"?: (Id & {\n data: U;\n }) | (Id & {\n data: U;\n })[];\n \"$remove\"?: Id | Id[];\n \"$set\"?: I[];\n};\n/** Variable-length primitive array — a sequence, so the same value may appear several times.\n * `$push` appends at the end (duplicates kept); `$pushUnique` appends only values not already\n * present; `$remove` removes every occurrence; `$set` replaces the whole array (also the\n * positional-edit path — send the full new array). One operator per update. */\nexport type PrimitiveListUpdate<T> = {\n \"$set\"?: T[];\n \"$push\"?: T | T[];\n \"$pushUnique\"?: T | T[];\n \"$remove\"?: T | T[];\n};\nexport type Never<T> = {\n [K in keyof T]?: never;\n};\nexport type FieldOps = {\n \"$eq\": unknown;\n \"$ne\": unknown;\n \"$not\": unknown;\n \"$in\": unknown;\n \"$notIn\": unknown;\n \"$gt\": unknown;\n \"$gte\": unknown;\n \"$lt\": unknown;\n \"$lte\": unknown;\n \"$startsWith\": unknown;\n \"$includes\": unknown;\n \"$every\": unknown;\n \"$some\": unknown;\n \"$none\": unknown;\n \"$near\": unknown;\n \"$search\": unknown;\n};\nexport type Only<K extends keyof FieldOps, V> = {\n [P in K]: V;\n} & Never<Omit<FieldOps, K>>;\nexport type WhereValue<T> = (T & Never<{\n \"$and\": unknown;\n \"$or\": unknown;\n \"$not\": unknown;\n}>) | ({\n \"$and\": WhereValue<T>[];\n} & Never<T> & Never<{\n \"$or\": unknown;\n \"$not\": unknown;\n}>) | ({\n \"$or\": WhereValue<T>[];\n} & Never<T> & Never<{\n \"$and\": unknown;\n \"$not\": unknown;\n}>) | ({\n \"$not\": WhereValue<T>;\n} & Never<T> & Never<{\n \"$and\": unknown;\n \"$or\": unknown;\n}>);\nexport type ValueOps<T> = {\n \"$eq\"?: T;\n \"$ne\"?: T;\n \"$not\"?: T;\n \"$in\"?: T[];\n \"$notIn\"?: T[];\n};\nexport type NumOps<T> = {\n \"$gt\"?: T;\n \"$gte\"?: T;\n \"$lt\"?: T;\n \"$lte\"?: T;\n};\nexport type StrOps = {\n \"$includes\"?: string;\n \"$startsWith\"?: string;\n};\nexport type CompareValue<T> = T | (ValueOps<T> & Never<Omit<FieldOps, keyof ValueOps<T>>>);\nexport type CompareNumValue<T> = ValueOps<T> & NumOps<T> & Never<Omit<FieldOps, keyof ValueOps<T> | keyof NumOps<T>>>;\nexport type CompareStrValue<T> = ValueOps<T> & StrOps & Never<Omit<FieldOps, keyof ValueOps<T> | keyof StrOps>>;\nexport type UpdateNumValue = {\n \"$increment\": number;\n};\nexport type JsonType = \"string\" | \"number\" | \"boolean\" | \"object\" | \"array\" | \"null\";\nexport type JsonCondition = JsonValue | {\n \"$eq\"?: JsonValue;\n \"$ne\"?: JsonValue;\n \"$not\"?: JsonValue;\n \"$gt\"?: number | string;\n \"$gte\"?: number | string;\n \"$lt\"?: number | string;\n \"$lte\"?: number | string;\n \"$in\"?: JsonValue[];\n \"$notIn\"?: JsonValue[];\n \"$startsWith\"?: string;\n \"$includes\"?: string;\n \"$contains\"?: JsonValue;\n \"$exists\"?: boolean;\n \"$type\"?: JsonType;\n};\nexport type JsonPathWhere = {\n [path: string]: JsonCondition;\n};\nexport type CompareRefValue<T> = T | Only<\"$not\", T>;\nexport type CompareRefListValue<T> = Only<\"$every\", T> | Only<\"$some\", T> | Only<\"$none\", T>;\nexport type VectorSearch = {\n vector: number[];\n k?: number;\n threshold?: number;\n};\nexport type FullTextSearch = string | {\n query: string;\n limit?: number;\n};\nexport type CustomSearch = Record<string, any>;\nexport type CustomSearchValue<P> = Only<\"$near\", P> | Only<\"$search\", P>;\nexport type AggregateResult<TModel, T> = (T extends {\n $count: true;\n} ? {\n count: number;\n} : {}) & (T extends {\n $sum: string;\n} ? {\n sum: number | null;\n} : {}) & (T extends {\n $avg: string;\n} ? {\n avg: number | null;\n} : {}) & (T extends {\n $min: infer F;\n} ? {\n min: (F extends keyof TModel ? TModel[F] : never) | null;\n} : {}) & (T extends {\n $max: infer F;\n} ? {\n max: (F extends keyof TModel ? TModel[F] : never) | null;\n} : {});\ndeclare const __op: unique symbol;\nexport type Op<T> = PromiseLike<T> & {\n readonly [__op]: T;\n};\nexport type MarciOp = {\n model: string;\n action: string;\n query?: any;\n data?: any;\n id?: any;\n};\nexport type MarciTransport = {\n exec(op: MarciOp): Promise<any>;\n batch(ops: MarciOp[]): Promise<any[]>;\n};\nexport type ModelTypes = {\n name: string;\n model: any;\n id: Record<string, any>;\n /** What an empty select returns: id + every scalar field, as a `{ field: true }` shape. */\n scalars: Record<string, true>;\n select: Record<string, any>;\n query: Record<string, any>;\n where: any;\n order: Record<string, any>;\n insert: any;\n update: any;\n aggregate: Record<string, any>;\n reindex: boolean;\n};\ndeclare const __sub: unique symbol;\ndeclare const __sel: unique symbol;\nexport type Sub<Name extends string, Shape = any> = {\n readonly [__sub]: Name;\n readonly [__sel]: Shape;\n};\nexport type Effective<T extends ModelTypes, S> = [Exclude<keyof S, ServiceKeys>] extends [never] ? T[\"scalars\"] : S;\nexport type Resolve<S> = S extends {\n readonly [__sel]: infer X;\n} ? Resolve<X> : S extends object ? {\n [K in keyof S]: K extends `$${string}` ? S[K] : Resolve<S[K]>;\n} : S;\nexport type Rows<T extends ModelTypes, Sel> = GetResult<T[\"model\"], Resolve<Effective<T, Sel>>>;\nexport type BareId<I> = I extends {\n id: infer V;\n} ? V : never;\nexport type IdArg<I> = I | BareId<I>;\n/**\n * A lazy, immutable query over one model — `db.user` itself is one. Every clause returns a new query, so\n * queries compose (`const active = db.user.where({ active: true })`). `await` runs it as `findMany`; passing\n * it to `$transaction` batches it; placing it in another query's select makes it a sub-select. `Sel` is the\n * projection: id + scalars until `select(...)` sets a shape.\n */\nexport interface Query<T extends ModelTypes, Sel = T[\"scalars\"]> extends PromiseLike<Rows<T, Sel>[]> {\n readonly [__op]: Rows<T, Sel>[];\n readonly [__sub]: T[\"name\"];\n readonly [__sel]: Effective<T, Sel>;\n /** Filter (marcidb `$where`). Repeated calls are ANDed. */\n where(where: T[\"where\"]): Query<T, Sel>;\n /** Sort by one field: `order(\"age\", \"desc\")` or `order({ age: \"desc\" })`. */\n order(field: keyof T[\"order\"] & string, direction?: \"asc\" | \"desc\"): Query<T, Sel>;\n order(order: T[\"order\"]): Query<T, Sel>;\n limit(n: number): Query<T, Sel>;\n skip(n: number): Query<T, Sel>;\n /** Keyset cursor: rows strictly after this id in the current order (`$cursor`). */\n after(id: IdArg<T[\"id\"]>): Query<T, Sel>;\n /**\n * The projection. Values are `true`, a nested shape, or a sub-query of the relation's model\n * (`posts: db.post.limit(5)`, `posts: db.post.where({ published: true }).count()`). No argument, or no\n * field keys, selects id + every scalar. `$`-clauses are accepted here too (the object form).\n */\n select<S extends T[\"query\"] = T[\"scalars\"]>(shape?: S): Query<T, S>;\n /** The first matching row or `null`. */\n first(): Op<Rows<T, Sel> | null>;\n /** Row count; inside a select it becomes `{ count }` for the relation. */\n count(): Op<number> & Sub<T[\"name\"], {\n $count: true;\n }>;\n /** @deprecated pass the filter through the chain: `db.user.where(w).count()` (removed in the next minor). */\n count(query: {\n $where?: T[\"where\"];\n }): Op<number> & Sub<T[\"name\"], {\n $count: true;\n }>;\n aggregate<A extends T[\"aggregate\"]>(query: A): Op<AggregateResult<T[\"model\"], A>> & Sub<T[\"name\"], NoInfer<A>>;\n insert(data: T[\"insert\"]): Op<T[\"id\"]>;\n update(id: IdArg<T[\"id\"]>, data: T[\"update\"]): Op<void>;\n /** Applies `data` to every row the chain's `where` matches (all rows without one); resolves to the number of rows. */\n updateMany(data: T[\"update\"]): Op<number>;\n /** @deprecated pass the filter through the chain: `db.user.where(w).updateMany(data)` (removed in the next minor). */\n updateMany(query: {\n $where?: T[\"where\"];\n }, data: T[\"update\"]): Op<number>;\n delete(id: IdArg<T[\"id\"]>): Op<void>;\n /**\n * Deletes every row the chain's `where` matches (cascades apply, as for `delete`); resolves to the number\n * deleted. Refuses to run without a `where` — write `.where({})` to mean \"every row\".\n */\n deleteMany(): Op<number>;\n /** @deprecated use `.select(query)` — it takes the same object, merged with the chain (removed in the next minor). */\n findMany<Q extends T[\"query\"] = {}>(query?: Q): Op<Rows<T, Q>[]>;\n /** @deprecated use `.select(query).first()` (removed in the next minor). */\n findFirst<Q extends T[\"query\"] = {}>(query?: Q): Op<Rows<T, Q> | null>;\n}\n/** `db.<model>`: the root query, plus `reindex()` for models with a `@custom` (vector / full-text) index. */\nexport type Collection<T extends ModelTypes> = Query<T> & (T[\"reindex\"] extends true ? {\n reindex(): Op<{\n ok: boolean;\n indexed: number;\n }>;\n} : {});\n/** One field of a model, in slot order: `n` name, `k` key | body | one | many, `m` the relation's target model. */\nexport type FieldDesc = {\n n: string;\n k: \"key\" | \"body\" | \"one\" | \"many\";\n t?: string | null;\n m?: string;\n};\n/** Model name → its field descriptors (structs included, as relation targets). */\nexport type ModelsMeta = Record<string, readonly FieldDesc[]>;\nexport type QueryLayerOptions = {\n models: ModelsMeta;\n /** Runs one operation (a query, or a write) and resolves its result. */\n run(op: MarciOp): Promise<any>;\n /** Hook for `insert` payloads (the lecodes SDK generates uuid ids here). */\n prepareInsert?(model: string, data: any): any;\n};\n/**\n * The query builder over a set of models and a `run` function. Returns `op(descriptor)` — a lazy operation\n * (`await` runs it, `$transaction` takes its `__op`) — and `collection(model)`, the immutable `db.<model>`\n * root query. Transport-agnostic: the generated client and the embedded/HTTP transports supply `run`.\n */\nexport declare function createQueryLayer(options: QueryLayerOptions): {\n op: (descriptor: MarciOp) => any;\n collection: (model: string) => any;\n};\nexport {};\n","types/server/db/types.d.ts":"/**\n * Type layer: projects a `defineDb({ User: model({...}), … })` literal into marcidb's generic query\n * types (./marci/query.ts — vendored from marcidb, see scripts/sync-marcidb.ts): each model becomes the\n * `ModelTypes` bag marcidb's codegen would have emitted, and `db.<model>` is marcidb's own `Query<T>`.\n * Everything here is type-only; the runtime lives in ./defineDb.ts.\n *\n * Naming: `S` = the schema record (model name → Model), `N` = a model name, `F` = a fields record.\n */\nimport type { Field, FieldMeta } from \"./fields\";\nimport type { CompareNumValue, CompareRefListValue, CompareRefValue, CompareStrValue, CompareValue, CustomSearchValue, FullTextSearch, JsonCondition, JsonPathWhere, Op, PrimitiveListUpdate, Query as MarciQuery, RefListUpdate, RefListUpdateOrdered, RefUpdate, RefUpdateStruct, Rows, Sub, UpdateNumValue, VectorSearch, WhereValue } from \"./marci/query\";\nexport type Fields = Record<string, Field<any, any>>;\nexport type Model<F extends Fields = Fields> = {\n readonly fields: F;\n readonly __model: true;\n};\nexport type Schema = Record<string, Model<any>>;\nexport type FieldsOf<M> = M extends Model<infer F> ? F : never;\ntype TsOf<Fld> = Fld extends Field<infer T, any> ? T : never;\ntype StructFieldsOf<Fld> = TsOf<Fld> extends Fields ? TsOf<Fld> : never;\ntype MetaOf<Fld> = Fld extends Field<any, infer M> ? M : never;\ntype ModelName<S, Fld> = MetaOf<Fld>[\"model\"] & keyof S & string;\ntype Nullable<M extends FieldMeta, T> = M[\"optional\"] extends true ? T | null : T;\ntype Arr<M extends FieldMeta, T> = M[\"array\"] extends true ? T[] : T;\ntype IsNum<M extends FieldMeta> = M[\"scalar\"] extends \"int\" | \"float\" | \"date\" ? true : false;\n/** Explicit `.id()` fields, or a field literally named `id`. */\ntype IdKeys<F extends Fields> = {\n [K in keyof F]: MetaOf<F[K]>[\"isId\"] extends true ? K : K extends \"id\" ? K : never;\n}[keyof F];\ntype IdValue<S, Fld> = MetaOf<Fld>[\"kind\"] extends \"one\" ? Id<S, ModelName<S, Fld>> : TsOf<Fld>;\n/** The id object of a model: `{ id: number }` implicitly, or the declared key fields. */\nexport type Id<S, N extends keyof S> = [\n IdKeys<FieldsOf<S[N]>>\n] extends [never] ? {\n id: number;\n} : {\n [K in IdKeys<FieldsOf<S[N]>>]: IdValue<S, FieldsOf<S[N]>[K]>;\n};\n/** What `update`/`delete` accept: the id object, or the bare value when the key is a single scalar. */\nexport type IdArg<S, N extends keyof S> = Id<S, N> | (Id<S, N> extends {\n id: infer V;\n} ? V : never);\ntype FieldRow<S, Fld, M extends FieldMeta = MetaOf<Fld>> = M[\"kind\"] extends \"one\" ? Nullable<M, Row<S, ModelName<S, Fld>>> : M[\"kind\"] extends \"many\" | \"list\" ? Row<S, ModelName<S, Fld>>[] : M[\"kind\"] extends \"struct\" ? Nullable<M, StructRow<S, StructFieldsOf<Fld>>> : Nullable<M, Arr<M, TsOf<Fld>>>;\n/** Full row type of a model (relations included) — the `TModel` marcidb's `GetResult` selects from. */\nexport type Row<S, N extends keyof S> = Id<S, N> & {\n [K in Exclude<keyof FieldsOf<S[N]>, IdKeys<FieldsOf<S[N]>>>]: FieldRow<S, FieldsOf<S[N]>[K]>;\n};\ntype StructRow<S, F extends Fields> = {\n [K in keyof F]: FieldRow<S, F[K]>;\n};\ntype ScalarKeys<F extends Fields> = {\n [K in keyof F]: MetaOf<F[K]>[\"kind\"] extends \"scalar\" | \"enum\" | \"json\" ? K : never;\n}[keyof F];\ntype NumKeys<F extends Fields> = {\n [K in keyof F]: IsNum<MetaOf<F[K]>> extends true ? (MetaOf<F[K]>[\"array\"] extends true ? never : K) : never;\n}[keyof F];\n/** What an empty select returns: id + every scalar field. */\nexport type Scalars<S, N extends keyof S> = Pick<Row<S, N>, (ScalarKeys<FieldsOf<S[N]>> | keyof Id<S, N>) & keyof Row<S, N>>;\n/** The same, as the `{ field: true }` select shape a query starts with. */\nexport type ScalarSelect<S, N extends keyof S> = {\n [K in (ScalarKeys<FieldsOf<S[N]>> | keyof Id<S, N>) & keyof Row<S, N>]: true;\n};\ntype FieldInsert<S, Fld, M extends FieldMeta = MetaOf<Fld>> = M[\"kind\"] extends \"one\" ? Nullable<M, Id<S, ModelName<S, Fld>>> : M[\"kind\"] extends \"many\" | \"list\" ? Id<S, ModelName<S, Fld>>[] : M[\"kind\"] extends \"struct\" ? Nullable<M, StructInsert<S, StructFieldsOf<Fld>>> : Nullable<M, Arr<M, TsOf<Fld>>>;\ntype RequiredKeys<F extends Fields> = {\n [K in keyof F]: K extends IdKeys<F> ? never : MetaOf<F[K]>[\"optional\"] extends true ? never : MetaOf<F[K]>[\"hasDefault\"] extends true ? never : MetaOf<F[K]>[\"kind\"] extends \"many\" | \"list\" ? never : K;\n}[keyof F];\ntype Simplify<T> = {\n [K in keyof T]: T[K];\n} & {};\ntype InsertOf<S, F extends Fields> = Simplify<{\n [K in RequiredKeys<F>]: FieldInsert<S, F[K]>;\n} & {\n [K in Exclude<keyof F, RequiredKeys<F>>]?: FieldInsert<S, F[K]>;\n}>;\nexport type Insert<S, N extends keyof S> = InsertOf<S, FieldsOf<S[N]>>;\ntype StructInsert<S, F extends Fields> = InsertOf<S, F>;\ntype FieldUpdate<S, Fld, M extends FieldMeta = MetaOf<Fld>> = M[\"kind\"] extends \"one\" ? Nullable<M, RefUpdate<Id<S, ModelName<S, Fld>>>> : M[\"kind\"] extends \"many\" ? RefListUpdate<Id<S, ModelName<S, Fld>>> : M[\"kind\"] extends \"list\" ? RefListUpdateOrdered<Id<S, ModelName<S, Fld>>> : M[\"kind\"] extends \"struct\" ? RefUpdateStruct<StructInsert<S, StructFieldsOf<Fld>>, UpdateOf<S, StructFieldsOf<Fld>>> | null : M[\"array\"] extends true ? TsOf<Fld>[] | PrimitiveListUpdate<TsOf<Fld>> : Nullable<M, TsOf<Fld> | (IsNum<M> extends true ? UpdateNumValue : never)>;\ntype UpdateOf<S, F extends Fields> = {\n [K in Exclude<keyof F, IdKeys<F>>]?: FieldUpdate<S, F[K]>;\n};\nexport type Update<S, N extends keyof S> = UpdateOf<S, FieldsOf<S[N]>>;\ntype FieldSelect<S, Fld, M extends FieldMeta = MetaOf<Fld>> = M[\"kind\"] extends \"one\" ? Select<S, ModelName<S, Fld>> | boolean | Sub<ModelName<S, Fld>> : M[\"kind\"] extends \"many\" | \"list\" ? QueryObject<S, ModelName<S, Fld>> | AggregateQuery<S, ModelName<S, Fld>> | boolean | Sub<ModelName<S, Fld>> : M[\"kind\"] extends \"struct\" ? StructSelect<S, StructFieldsOf<Fld>> | boolean : boolean;\nexport type Select<S, N extends keyof S> = {\n [K in keyof Row<S, N>]?: K extends keyof FieldsOf<S[N]> ? FieldSelect<S, FieldsOf<S[N]>[K]> : boolean;\n};\ntype StructSelect<S, F extends Fields> = {\n [K in keyof F]?: FieldSelect<S, F[K]>;\n};\ntype ScalarWhere<T, M extends FieldMeta> = Nullable<M, CompareValue<T>> | (IsNum<M> extends true ? CompareNumValue<T> : M[\"scalar\"] extends \"string\" ? CompareStrValue<T> : never);\ntype FieldWhere<S, Fld, M extends FieldMeta = MetaOf<Fld>> = M[\"kind\"] extends \"one\" ? CompareRefValue<Where<S, ModelName<S, Fld>> | null> : M[\"kind\"] extends \"many\" | \"list\" ? CompareRefListValue<Where<S, ModelName<S, Fld>>> : M[\"kind\"] extends \"struct\" ? CompareRefValue<WhereValue<StructWhereFields<S, StructFieldsOf<Fld>>> | null> : M[\"kind\"] extends \"json\" ? JsonPathWhere | JsonCondition : M[\"array\"] extends true ? CompareValue<TsOf<Fld>> : ScalarWhere<TsOf<Fld>, M> | CustomSearchValue<FullTextSearch> | CustomSearchValue<VectorSearch>;\ntype WhereFieldsOf<S, F extends Fields> = {\n [K in keyof F]?: FieldWhere<S, F[K]>;\n};\ntype IdWhere<S, N extends keyof S> = {\n [K in keyof Id<S, N> as K extends keyof FieldsOf<S[N]> ? never : K]?: CompareValue<Id<S, N>[K]> | CompareNumValue<number>;\n};\nexport type Where<S, N extends keyof S> = WhereValue<WhereFieldsOf<S, FieldsOf<S[N]>> & IdWhere<S, N>>;\ntype StructWhereFields<S, F extends Fields> = WhereFieldsOf<S, F>;\nexport type Order<S, N extends keyof S> = {\n [K in (ScalarKeys<FieldsOf<S[N]>> | keyof Id<S, N>) & keyof Row<S, N>]?: \"asc\" | \"desc\";\n};\n/** The query object — marcidb's wire form: a select shape plus the `$`-clauses. */\nexport type QueryObject<S, N extends keyof S> = Select<S, N> & {\n $where?: Where<S, N>;\n $order?: Order<S, N>;\n $limit?: number;\n $skip?: number;\n $cursor?: Id<S, N>;\n};\nexport type AggregateQuery<S, N extends keyof S> = {\n $where?: Where<S, N>;\n $count?: true;\n $sum?: NumKeys<FieldsOf<S[N]>> & string;\n $avg?: NumKeys<FieldsOf<S[N]>> & string;\n $min?: (ScalarKeys<FieldsOf<S[N]>> | keyof Id<S, N>) & string;\n $max?: (ScalarKeys<FieldsOf<S[N]>> | keyof Id<S, N>) & string;\n};\n/** The per-model type bag marcidb's generic `Query<T>` is parametrised by (what its codegen emits as `UserTypes`). */\nexport type Types<S, N extends keyof S> = {\n name: N & string;\n model: Row<S, N>;\n id: Id<S, N>;\n scalars: ScalarSelect<S, N>;\n select: Select<S, N>;\n query: QueryObject<S, N>;\n where: Where<S, N>;\n order: Order<S, N>;\n insert: Insert<S, N>;\n update: Update<S, N>;\n aggregate: AggregateQuery<S, N>;\n reindex: false;\n};\n/**\n * `db.<model>` — marcidb's lazy, immutable query over one model: clauses (`where/order/limit/skip/after`)\n * return a new query, `select(shape)` sets the projection, `await` runs it, `first/count/aggregate` terminate,\n * `updateMany(data)`/`deleteMany()` write through the chain's `where`; a query placed in another query's\n * select is a sub-query. `Sel` is the projection: id + scalars until `select(...)` sets a shape.\n */\nexport type Query<S, N extends keyof S, Sel = ScalarSelect<S, N>> = MarciQuery<Types<S, N>, Sel>;\n/** The rows a query with projection `Q` resolves to (no field keys = id + scalars; sub-queries resolved). */\nexport type Result<S, N extends keyof S, Q> = Rows<Types<S, N>, Q>;\n/** `db.<model>` — the root query of a model. */\nexport type Collection<S, N extends keyof S> = Query<S, N>;\nexport type Db<S extends Schema> = {\n [N in keyof S & string as Uncapitalize<N>]: Query<S, N>;\n} & {\n /** Atomic batch: all ops commit or none. `ref(\"0.id\")` feeds a generated id into a later op. */\n $transaction<P extends readonly Op<any>[]>(ops: [...P]): Promise<{\n [K in keyof P]: P[K] extends Op<infer T> ? T : never;\n }>;\n /** The `.marci` schema text this db syncs with. */\n readonly $schema: string;\n};\ntype RelKinds = \"one\" | \"many\" | \"list\";\ntype CheckField<S, Fld> = MetaOf<Fld>[\"kind\"] extends RelKinds ? MetaOf<Fld>[\"model\"] extends keyof S ? Fld : `Unknown model \"${MetaOf<Fld>[\"model\"]}\" — not a key of defineDb({...})` : Fld;\n/** Intersected with `S` in `defineDb`'s parameter: an unknown relation target fails to type-check on that field. */\nexport type ValidateRefs<S extends Schema> = {\n [N in keyof S]: {\n readonly fields: {\n [K in keyof FieldsOf<S[N]>]: CheckField<S, FieldsOf<S[N]>[K]>;\n };\n };\n};\nexport {};\n","types/server/errors.d.ts":"/**\n * `throw new ApiError(404, \"Not found\")` inside an endpoint → the client's promise rejects with the\n * same status + message. Any other throw is a 500 (message hidden, logged to the server console).\n */\nexport declare class ApiError extends Error {\n readonly status: number;\n constructor(status: number, message?: string);\n}\n","types/server/inject.d.ts":"export { t, model, defineDb, ref } from \"./db\";\nexport { ApiError } from \"./errors\";\nexport { channel } from \"./channel\";\nexport { request } from \"./context\";\nexport { auth } from \"./auth/global\";\n","types/ui/fonts.d.ts":"type FontOptions = {\n weight?: number;\n style?: \"normal\" | \"italic\";\n};\n/** Register a font face from a URL at runtime under `fontFamily`; resolves once it's ready to\n * use in styles. For registry/project fonts prefer the compile-time `font()` macro — this is the\n * dynamic escape hatch. */\nexport declare function registerFont(fontFamily: string, url: string, options?: FontOptions): Promise<void>;\nexport {};\n","types/ui/NativeView.d.ts":"import { type PresentOptions } from \"./presentable\";\nimport { type BaseStyle, type DrawableStyle, type ElementStyle, type UIElementBase } from \"./UINode\";\nexport type UINativeViewStyle = ElementStyle & DrawableStyle;\n/** An instance of a host-registered platform view (map, QR scanner, camera preview, …) —\n * embeddable among a screen's children AND fullscreen-presentable (`open()`); one instance lives\n * in one place at a time. Talk to it via the `call`/`on` channel. */\nexport interface NativeView extends UIElementBase<UINativeViewStyle, DrawableStyle & BaseStyle> {\n readonly type: \"native\";\n /** The registered view kind this instance resolves to (the `registerView` name). */\n readonly viewName: string;\n /** Creation params, passed to the host factory (JSON-serializable). */\n readonly params: any;\n /** Show fullscreen as the current destination (see Presentable). */\n open(options?: PresentOptions): void;\n /** Dismiss if this is the visible destination. */\n close(): void;\n /** Became the visible destination. */\n onOpen(callback: () => void): this;\n /** Stopped being the visible destination. */\n onClose(callback: () => void): this;\n /** Hardware/system back while current. */\n onBackPressed(callback: () => void): this;\n /** Invoke a method on the native view (`map.call(\"setCenter\", [lng, lat])`). Args and the\n * result are JSON-serialized. Rejects if the host has no such view/method. */\n call(method: string, ...args: any[]): Promise<any>;\n /** Subscribe to an event the native view emits (`map.on(\"markerTap\", cb)`). */\n on(event: string, callback: (data?: any) => void): this;\n off(event: string, callback: (data?: any) => void): this;\n}\n/**\n * Create an instance of a host-registered platform view. `NativeView.isSupported(name)` reports\n * whether this host registered a factory for it. Style via the chained `.style()`.\n */\nexport declare const NativeView: {\n (name: string, params?: object): NativeView;\n /** Whether this host registered a `registerView` factory under `name`. */\n isSupported(name: string): boolean;\n};\n","types/ui/presentable.d.ts":"/** Built-in transition catalog. `push`/`pop` are the stacked-navigation pair (slide + parallax +\n * dim + edge shadow); the rest are simple two-view moves. */\nexport type TransitionName = \"push\" | \"pop\" | \"slide-from-left\" | \"slide-from-right\" | \"slide-from-top\" | \"slide-from-bottom\" | \"zoom\" | \"zoom-in\" | \"zoom-out\" | \"fade\" | \"none\";\n/** Start/end pose of one side of a custom transition. `x`/`y` are logical px, or a percentage of\n * the destination's size (e.g. `\"100%\"` = one full width to the right). */\nexport type TransitionTransform = {\n x?: number | `${number}%`;\n y?: number | `${number}%`;\n scale?: number;\n opacity?: number;\n};\n/**\n * A custom transition: declarative poses for the incoming/outgoing destination, played natively.\n * Serializes onto each platform's existing transition machinery — there is no per-frame JS.\n * Fields omitted keep the identity pose. Interactive back-swipe stays system-native (push/pop\n * only); a spec applies to non-interactive transitions.\n */\nexport interface TransitionSpec {\n /** Duration in ms (default 300). */\n duration?: number;\n /** cubic-bezier control points (default ease-out). */\n easing?: [number, number, number, number];\n /** The entering destination animates FROM this pose to identity. */\n incoming?: {\n from?: TransitionTransform;\n };\n /** The leaving destination animates from identity TO this pose. */\n outgoing?: {\n to?: TransitionTransform;\n };\n /** Scrim alpha (0..1) painted over whichever destination is underneath. */\n dim?: number;\n /** Which side stacks on top during the animation (default \"incoming\"). On Android, transitions\n * involving a scene always animate the screen side on top — the scene view itself never moves. */\n onTop?: \"incoming\" | \"outgoing\";\n}\nexport type Transition = TransitionName | TransitionSpec;\nexport type PresentOptions = {\n /** Transition to play while this destination replaces the current one (default \"none\" for a\n * direct open(); the Router applies its own defaults — push/pop, and the theme's\n * `replaceTransition` for replace). */\n transition?: Transition;\n};\n/**\n * Anything that can be shown as the app's current destination: a `UIScreen`, a `Scene` /\n * `ARScene`, a `Scene2D`, a `NativeView`, or a `UIVideo`. One Presentable is visible at a time;\n * open it directly (`p.open()` — replaces the current destination, suspending an active Router\n * until `Router.restore()`) or navigate with `Router.push/replace/pop`.\n *\n * `onOpen`/`onClose` are the presentation lifecycle (fired when the destination becomes / stops\n * being the visible one — including router pushes covering it and pops revealing it).\n */\nexport interface Presentable {\n open(options?: PresentOptions): void | this | Promise<void>;\n close(): void;\n onOpen(callback: () => void): this;\n onClose(callback: () => void): this;\n onBackPressed(callback: () => void): this;\n}\n/** Runtime companion of the `Presentable` interface (declaration merging): the navigation\n * state that isn't tied to the Router. */\nexport declare const Presentable: Readonly<{\n /** The destination visible right now (a `UIScreen`, `Scene`, `Scene2D`, `NativeView` or\n * `UIVideo`), or `null` before the first open. Distinct from `Router.current` — that is the\n * top of the router stack, which stays meaningful while the router is suspended by a direct\n * `open()`; this is what is actually on screen. `UIWidget.show()` attaches to it. */\n readonly current: Presentable | null;\n}>;\n","types/ui/router.d.ts":"import { Presentable, type Transition } from \"./presentable\";\ntype RouterOptions = {\n showDefaultBackButton?: boolean;\n};\ntype NavigateOptions = {\n /** Transition to play. Defaults: `\"push\"` for push, `\"pop\"` for pop; replace follows the\n * theme's `replaceTransition` (`\"none\"` out of the box). */\n transition?: Transition;\n};\n/** Stack navigation over `Presentable` destinations. `init` once with the home page, then\n * `push`/`replace`/`pop`; the back gesture/button pops natively. A direct `page.open()` suspends\n * the router until `restore()`. */\ntype Router = {\n /** The top of the router stack (not necessarily what's on screen — see `Presentable.current`). */\n get current(): Presentable;\n /** Mount the router with `homePage` as the stack root — the app's navigation entry point. */\n init(homePage: Presentable, opts?: RouterOptions): void;\n /** Push a destination onto the stack — a `UIScreen`, a `Scene`, a `Scene2D`, a `NativeView`,\n * or a `UIVideo`. The back gesture/button pops it. Destinations with async preparation\n * (`ARScene`: camera permission + warm render) return a Promise — the current page stays\n * visible until they're ready, and a rejection (permission denied / superseded) leaves the\n * stack untouched. */\n push(page: Presentable, opts?: NavigateOptions): void | Promise<void>;\n /** Swap the top of the stack for `page` — no back entry to the replaced one. */\n replace(page: Presentable, opts?: NavigateOptions): void | Promise<void>;\n /** Pop the top destination (the programmatic twin of the back gesture); `to` unwinds to a\n * stack index in one step. */\n pop(to?: number, opts?: NavigateOptions): void;\n /** Blank the router's page, keeping the stack — `restore()` brings it back. A destination\n * opened directly stays visible. */\n hide(): void;\n /** Re-present the stack top after `hide()` or a direct `open()` suspended the router. */\n restore(): void;\n /** `\"change\"` fires on every stack change — pushes, pops, and native back gestures — with the\n * new top destination. */\n addEventListener(channel: \"change\", callback: (page: Presentable) => void): void;\n removeEventListener(channel: \"change\", callback: (page: Presentable) => void): void;\n};\nexport declare const Router: Router;\nexport {};\n","types/ui/theme.d.ts":"import type { Transition } from \"./presentable\";\nexport type ThemeValues = Record<string, string | number | null>;\nexport type ThemeAccessors<T> = {\n readonly [K in keyof T]: K extends string ? `var(--${K})` : never;\n};\n/** App theme: callable to merge variables (`theme({...})` — re-calling re-styles the live UI, so\n * dark mode is just a second call), with the system vars as static properties\n * (`theme.primaryColor`, `theme[\"comfort-top\"]`, …). */\nexport declare const theme: (<T extends Record<string, string | number | Transition | null>>(values: T & { [K in Exclude<keyof T, \"replaceTransition\">]: string | number | null; }) => ThemeAccessors<Omit<T, \"replaceTransition\">>) & {\n /** The app accent color. Kit components will read it via `var(--primaryColor, <fallback>)`. */\n readonly primaryColor: \"var(--primaryColor)\";\n /** Secondary / inactive content color for kit components. */\n readonly mutedColor: \"var(--mutedColor)\";\n /** DEFAULT text color — text without an explicit `color` follows it (hosts source their\n * default from the theme; unset = the host default, white on dark screens). Set it once for\n * a light theme instead of `color: \"black\"` on every label. */\n readonly color: \"var(--color)\";\n /** DEFAULT text font — text without an explicit `fontFamily` follows it. */\n readonly fontFamily: \"var(--fontFamily)\";\n /** Raw comfort knobs (logical px). The bare `comfort-top` style TOKEN applies the safe-area\n * formula — these accessors read the knob value itself, for manual composition. */\n readonly \"comfort-top\": \"var(--comfort-top)\";\n readonly \"comfort-bottom\": \"var(--comfort-bottom)\";\n readonly \"comfort-left\": \"var(--comfort-left)\";\n readonly \"comfort-right\": \"var(--comfort-right)\";\n};\n","types/ui/UI.d.ts":"export { UIButton, type UIButtonStyle } from './UIButton';\nexport { UIScreen, type UIScreenStyle } from './UIScreen';\nexport { UISpacer, type UISpacerStyle } from './UISpacer';\nexport { UIText, type UITextStyle } from './UIText';\nexport { registerFont } from './fonts';\nexport { UIImage, type UIImageStyle } from './UIImage';\nexport { UIVideo, type UIVideoStyle } from './UIVideo';\nexport { UIInput, UITextArea, type UIInputStyle } from './UIInput';\nexport { UIWidget, type UIWidgetStyle } from './UIWidget';\nexport { UIModal, type UIModalStyle } from './UIModal';\nexport { UIBottomSheet, type UIBottomSheetStyle } from './UIBottomSheet';\nexport { UIPopover, type UIPopoverStyle, type UIPopoverAnchor } from './UIPopover';\nexport { UIRow, UIColumn, UIBox, type UIContainerStyle } from './UIContainer';\nexport { UIScrollable, type UIScrollableStyle } from './UIScrollable';\nexport { UIPager, type UIPagerStyle } from './UIPager';\nexport { UITabs, type UITabDef, defineTabs, type TabDef, type TabsHandle } from './UITabs';\nexport { UIVirtualizedList } from './UIVirtualizedList';\nexport { Router } from './router';\nexport { NativeView, type UINativeViewStyle } from './NativeView';\nexport { Presentable } from './presentable';\nexport type { PresentOptions, Transition, TransitionName, TransitionSpec, TransitionTransform } from './presentable';\nexport { __uiMap } from './UINode';\nexport { __UIColumn, __UIRow, __UIBox } from './UIContainer';\nexport { __UIButton } from './UIButton';\nexport { __UIScreen } from './UIScreen';\nexport { __UIScrollable } from './UIScrollable';\nexport { __UIWidget } from './UIWidget';\n","types/ui/UIBottomSheet.d.ts":"import { ModalElement, type UIModalStyle } from \"./UIModal\";\nimport type { UIWidget } from \"./UIWidget\";\nimport { type ChildrenFn, type UIChildArg, type UINodeChild } from \"./UINode\";\nexport type UIBottomSheetStyle = UIModalStyle;\n/**\n * A bottom sheet: a `UIWidget` pinned to the bottom edge. By default it is **content-sized** —\n * as tall as what's inside (capped at the screen), one position, drag down to dismiss (the\n * action-sheet shape). Call `detents()` for the multi-position map-app model instead: snap\n * positions the user drags between on native hosts. Ships as a widget node on the wire (no new\n * node type — docs/bottom-sheet-plan.md): hosts without sheet support show a static bottom panel.\n *\n * With detents, content lays out at the HIGHEST detent's size; lower detents show the top\n * slice. The scrim, `onOpen`/`onClose`, back-button and scrim-tap dismissal all come from the\n * modal machinery.\n *\n * ```ts\n * const actions = UIBottomSheet({ bgColor: \"#1c1c1e\", borderRadius: 16 }, [rows]) // content-sized\n *\n * const mapSheet = UIBottomSheet({ bgColor: \"#1c1c1e\", borderRadius: 16 }, [results])\n * .detents([0.3, 0.6, 1])\n * .onDetentChange(i => map.setPadding(...))\n * ```\n */\nexport interface UIBottomSheet extends UIWidget {\n /** Snap positions as fractions of screen height, ascending. Also sizes the sheet: its box is\n * the last (highest) detent; set this before `show()`. Without a `detents()` call the sheet\n * is CONTENT-SIZED instead — one position, as tall as its children (up to the screen). */\n detents(list: number[]): this;\n /** Snap to a detent (animated). Clamped to the detents range; fires `onDetentChange`. */\n setDetent(index: number): void;\n /** Current detent index. */\n readonly detent: number;\n /** Fires on every settle: a finger snap on native hosts, or a `setDetent()` call. */\n onDetentChange(callback: (index: number) => void): this;\n /** Mount and slide in to the current detent. No-op while already open. */\n show(): void;\n /** Slide out, fade the scrim, then unmount. No-op while closed. */\n hide(): void;\n /** True from `show()` until `hide()` starts. */\n readonly isOpen: boolean;\n /** Called when `show()` mounts the sheet. */\n onOpen(callback: () => void): this;\n /** Called when the sheet starts closing — scrim tap, back button, drag-dismiss, or `hide()`. */\n onClose(callback: () => void): this;\n /** `dismissible(false)`: scrim taps, the back button and dragging below the lowest detent no\n * longer close the sheet (a drag collapses to the lowest detent instead). Default `true`. */\n dismissible(enabled: boolean): this;\n}\nexport declare class BottomSheetElement extends ModalElement {\n _detents: number[];\n _detent: number;\n /** Host-facing (the `sl`/`otl` contract): hosts read `dtl` at mount and call it with the\n * settled detent index for GESTURE settles only — programmatic `setDetent` fires JS-side.\n * `-1` = dragged below the lowest detent while dismissible. */\n readonly dtl: any[];\n readonly _detentListeners: ((index: number) => void)[];\n constructor(style: UIBottomSheetStyle, children: UINodeChild[] | ChildrenFn);\n detents(list: number[]): this;\n get detent(): number;\n setDetent(index: number): void;\n onDetentChange(callback: (index: number) => void): this;\n show(): void;\n hide(): void;\n dismissible(enabled: boolean): this;\n}\n/** Create a bottom sheet (see {@link UIBottomSheet}) — content-sized by default; call\n * `.detents([...])` for snap positions. Same argument forms as `UIColumn`. */\nexport declare function UIBottomSheet(...children: UIChildArg[]): UIBottomSheet;\nexport declare function UIBottomSheet(children: UINodeChild[] | ChildrenFn): UIBottomSheet;\n/** @deprecated Style as the first argument is legacy — use chained `.style({...})`. */\nexport declare function UIBottomSheet(style: UIBottomSheetStyle, children?: UINodeChild[] | ChildrenFn): UIBottomSheet;\n","types/ui/UIButton.d.ts":"import type { ClickEvent as ClickEventType, TouchStartEvent as TouchStartEventType, LongPressEvent as LongPressEventType } from \"../runtime/touch\";\nimport { type ElementStyle, type ContainerStyle, type DrawableStyle, type UIChildArg, type UIContainerBase, type UINodeChild, type ChildrenFn, type BaseStyle, type Color } from \"./UINode\";\nexport type UIButtonStyle = ElementStyle & DrawableStyle & ContainerStyle & {\n rippleColor?: Color | \"default\";\n};\n/** A tappable container — row + centered children by default. Press feedback via the `onPressed`\n * style block, the `$pressed` class, or `rippleColor`. */\nexport interface UIButton extends UIContainerBase<UIButtonStyle & {\n onPressed?: UIButtonStyle & {\n duration?: number;\n };\n}, DrawableStyle & BaseStyle> {\n readonly type: \"button\";\n /** Fired on a completed tap/click. */\n onClick(callback: (ev: ClickEventType<UIButton>) => void): this;\n /** Fired when a touch begins; `ev.track(...)` takes over the rest of the gesture (dragging). */\n onTouchStart(callback: (ev: TouchStartEventType<UIButton>) => void): this;\n /** Fired when a finger is held on the button past the long-press threshold. The event can\n * `ev.track(...)` the rest of the gesture (like `onTouchStart`), so a hold can flow straight into\n * dragging the element. A handled long-press suppresses the click that would follow the release. */\n onLongPress(callback: (ev: LongPressEventType<UIButton>) => void): this;\n /** Is a finger currently down on the button? */\n isPressed(): boolean;\n}\n/** Create a button (row + centered by default — the icon+label shape). Same argument forms as\n * `UIColumn`; attach behavior with `.onClick(...)`. */\nexport declare function UIButton(...children: UIChildArg[]): UIButton;\nexport declare function UIButton(children: UINodeChild[] | ChildrenFn): UIButton;\n/** @deprecated Style as the first argument is legacy — use chained `.style({...})`. */\nexport declare function UIButton(style: UIButtonStyle, children?: UINodeChild[] | ChildrenFn): UIButton;\n","types/ui/UIContainer.d.ts":"import { type ChildrenFn, type ContainerStyle, type DrawableStyle, type ElementStyle, type UIChildArg, type UIContainerBase, type UINodeChild } from \"./UINode\";\nexport type UIContainerStyle = ElementStyle & DrawableStyle & ContainerStyle;\n/** A vertical flex container — children stack top to bottom. */\nexport interface UIColumn extends UIContainerBase<UIContainerStyle> {\n readonly type: \"column\";\n}\nexport declare const __UIRow: (children: UINodeChild[] | ChildrenFn) => UIRow;\nexport declare const __UIBox: (children: UINodeChild[] | ChildrenFn) => UIBox;\n/** Create a vertical flex container. Children are variadic — arrays flatten one level, falsy\n * entries are skipped; a lone function makes the children reactive. */\nexport declare function UIColumn(...children: UIChildArg[]): UIColumn;\nexport declare function UIColumn(children: UINodeChild[] | ChildrenFn): UIColumn;\n/** @deprecated Style as the first argument is legacy — use chained `.style({...})`. */\nexport declare function UIColumn(style: UIContainerStyle, children?: UINodeChild[] | ChildrenFn): UIColumn;\n/** A horizontal flex container — children flow left to right. */\nexport interface UIRow extends UIContainerBase<UIContainerStyle> {\n readonly type: \"row\";\n}\n/** Create a horizontal flex container (same argument forms as `UIColumn`). */\nexport declare function UIRow(...children: UIChildArg[]): UIRow;\nexport declare function UIRow(children: UINodeChild[] | ChildrenFn): UIRow;\n/** @deprecated Style as the first argument is legacy — use chained `.style({...})`. */\nexport declare function UIRow(style: UIContainerStyle, children?: UINodeChild[] | ChildrenFn): UIRow;\n/** A centering container — `justifyContent`/`alignItems` default to center. */\nexport interface UIBox extends UIContainerBase<UIContainerStyle> {\n readonly type: \"box\";\n}\n/** Create a centering container — children are centered on both axes by default (icon badges,\n * avatars, empty states). Same argument forms as `UIColumn`. */\nexport declare function UIBox(...children: UIChildArg[]): UIBox;\nexport declare function UIBox(children: UINodeChild[] | ChildrenFn): UIBox;\n/** @deprecated Style as the first argument is legacy — use chained `.style({...})`. */\nexport declare function UIBox(style: UIContainerStyle, children?: UINodeChild[] | ChildrenFn): UIBox;\n","types/ui/UIImage.d.ts":"import type { FetchResponse } from \"../runtime/fetch\";\nimport type { SvgSourceValue as SvgSource } from \"../runtime/misc\";\nimport type { File } from \"../runtime/fetch\";\nimport { Canvas } from \"../canvas/Canvas\";\nimport { type Color, type ElementStyle, type UIElementBase } from \"./UINode\";\nexport type UIImageStyle = ElementStyle & {\n borderRadius?: number;\n objectFit?: \"cover\" | \"contain\" | \"fill\";\n tintColor?: Color;\n};\n/** A baked Canvas surface as an image source. The UI backend resolves it to a UI texture — see\n * docs/canvas-contract.md (\"Pending\"). */\nexport type CanvasImageSource = {\n canvasSurface: number;\n};\n/** Accepted image sources. A Canvas is baked to a surface marker on assign. */\nexport type ImageSource = string | FetchResponse | File | SvgSource | Canvas;\n/** The stored/resolved image source (a Canvas is resolved to a surface marker). */\nexport type ResolvedImageSource = string | FetchResponse | File | SvgSource | CanvasImageSource;\n/** An image element. Sources: URL / `asset(...)`, fetch response / File, an SVG source\n * (`assetIcon`), or a live Canvas (`canvas.update()` refreshes the node in place). */\nexport interface UIImage extends UIElementBase<UIImageStyle> {\n readonly type: \"image\";\n /** The image source — writable to swap the picture in place. */\n get src(): ResolvedImageSource;\n set src(value: ImageSource);\n /** Render only a sub-rectangle of the source texture (texture pixels) — the atlas/spritesheet\n * primitive: crop once, then swap the rect per frame for sprite animation. The rect's w/h\n * become the node's intrinsic size and override `objectFit` — the cropped frame fills the box. */\n setSourceRect(x: number, y: number, w: number, h: number): this;\n}\n/** Create an image element from a source (see {@link ImageSource}). */\nexport declare function UIImage(src: ImageSource): UIImage;\n/** @deprecated Style as the first argument is legacy — use chained `.style({...})`. */\nexport declare function UIImage(style: UIImageStyle, src: ImageSource): UIImage;\n","types/ui/UIInput.d.ts":"import { type ElementStyle, type DrawableStyle, type TextStyle, type Color, type BaseStyle, type UIElementBase } from \"./UINode\";\ntype InputStyle = {\n placeholder?: string;\n placeholderColor?: Color;\n /**\n * Keyboard hint, NOT a validator — `number` does not block pasted letters; validate in your own\n * onChange. The phone-pad value is `phone` (LeCodes has no `tel`).\n *\n * `date` / `time` are PICKER kinds, not keyboards: the host opens its native picker in the\n * keyboard slot (iOS wheels / browser calendar) and free typing is disabled. `value` is always\n * canonical — `YYYY-MM-DD` for `date`, `HH:MM` (24h) for `time` — while the field displays a\n * localized string; set/compare values in the canonical form only.\n */\n type?: \"text\" | \"password\" | \"search\" | \"phone\" | \"email\" | \"number\" | \"decimal\" | \"url\" | \"date\" | \"time\";\n /**\n * What the layout does while the keyboard is up (decided by the FOCUSED input). `true` (default):\n * the layout viewport shrinks to the area above the keyboard — one relayout. `false`: the keyboard\n * overlays the UI with NO layout recalculation — for chat composers that manage their own inset\n * (pair with `app.keyboardHeight` / the app `\"keyboard\"` event) and full-screen canvases where a\n * reflow is worse than overlap.\n */\n keyboardShrink?: boolean;\n /**\n * Whether a tap on a non-interactive area dismisses the keyboard while THIS input is focused\n * (like `keyboardShrink`, the policy of the focused input). `true` (default): tapping dead\n * space blurs — but a tap on a button or another input NEVER dismisses; the control acts and\n * focus stays. `false`: taps never dismiss — the chat-composer policy. `blur()`, the return\n * key (per `enterKey`), and the platform's own gestures (iOS drag-down over the keyboard)\n * still work in both modes. Scrolling never dismisses the keyboard on any setting.\n */\n keyboardDismiss?: boolean;\n /** Hard cap on the text length — enforced by the host while typing/pasting. */\n maxLength?: number;\n /** Auto-capitalization hint; omitted = platform default. */\n autocapitalize?: \"none\" | \"words\" | \"sentences\" | \"characters\";\n /** Enable/disable the platform autocorrection & suggestions; omitted = platform default. */\n autocorrect?: boolean;\n};\nexport type UIInputStyle = ElementStyle & DrawableStyle & TextStyle & InputStyle;\n/** UIInput-only (a UITextArea's Enter is a newline, period): the return-key label. */\ntype SubmitStyle = {\n /**\n * Return-key label. On submit the keyboard dismisses UNLESS `enterKey` is `\"next\"` — then the\n * app is expected to call `otherInput.focus()` from `onSubmit`, so the keyboard never blinks.\n */\n enterKey?: \"done\" | \"go\" | \"next\" | \"search\" | \"send\";\n};\n/** A single-line text input. Keyboard/picker kind via the `type` style, return-key behavior via\n * `enterKey` + `onSubmit`; keyboard policy on `keyboardShrink`/`keyboardDismiss`. */\nexport interface UIInput extends UIElementBase<UIInputStyle & SubmitStyle & {\n onFocused?: UIInputStyle & {\n duration?: number;\n };\n}, DrawableStyle & BaseStyle> {\n readonly type: \"input\";\n /**\n * The field's text. Writable at any time — set it BEFORE the screen opens to pre-fill a form\n * (settings, edit-profile); the value is stashed on the node and applied when the host builds\n * it. Reads return the live text while the screen is open, and the last value you set while it\n * isn't. The user's typing is not preserved across close/open (use `keepAlive()` for that).\n */\n value: string;\n /** The text changed — fires on every user edit. */\n onChange(callback: (value: string) => void): UIInput;\n /** Gained focus (keyboard opens). */\n onFocus(callback: () => void): UIInput;\n /** Lost focus. */\n onBlur(callback: () => void): UIInput;\n /** The keyboard's return key was pressed. `value` is the current text. See `enterKey`. */\n onSubmit(callback: (value: string) => void): UIInput;\n /** Focus the input (opens the keyboard). No-op before mount. */\n focus(): void;\n /** Release focus (dismisses the keyboard when this input held it). */\n blur(): void;\n}\n/** A multi-line text field — see the {@link UITextArea} factory for the auto-grow contract. */\nexport interface UITextArea extends UIElementBase<UIInputStyle & {\n onFocused?: UIInputStyle & {\n duration?: number;\n };\n}, DrawableStyle & BaseStyle> {\n readonly type: \"textarea\";\n /** The field's text — same contract as {@link UIInput.value}: settable before mount to pre-fill. */\n value: string;\n /** The text changed — fires on every user edit. */\n onChange(callback: (value: string) => void): UITextArea;\n /** Gained focus (keyboard opens). */\n onFocus(callback: () => void): UITextArea;\n /** Lost focus. */\n onBlur(callback: () => void): UITextArea;\n /** Focus the text area (opens the keyboard). No-op before mount. */\n focus(): void;\n /** Release focus (dismisses the keyboard when this text area held it). */\n blur(): void;\n}\n/** Create a single-line text input. Read/write the text via `.value`, listen with\n * `onChange`/`onSubmit`; style keys `placeholder`, `type`, `enterKey`, … configure it. */\nexport declare function UIInput(): UIInput;\nexport declare function UIInput(style: UIInputStyle): UIInput;\n/**\n * Multi-line text field. Enter is a newline (submit lives on UIInput / your own button).\n *\n * Auto-grow: with no explicit `height` the field measures its own content and grows line by\n * line — clamp the range with `minHeight` / `maxHeight` (past `maxHeight` the text scrolls\n * inside). A fixed `height` opts out and scrolls internally from the start. Chat composers are\n * the canonical use: a bare textarea in a padded pill, `maxHeight` at ~5 lines.\n */\nexport declare function UITextArea(): UITextArea;\nexport declare function UITextArea(style: UIInputStyle): UITextArea;\nexport {};\n","types/ui/UIModal.d.ts":"import { type UIWidget, type UIWidgetStyle, WidgetElement } from \"./UIWidget\";\nimport { type BaseStyle, type ChildrenFn, type Color, type DrawableStyle, type UIChildArg, type UINodeChild } from \"./UINode\";\nexport type UIModalStyle = UIWidgetStyle;\n/**\n * The modal's hidden pose: `show()` animates from it, `hide()` animates to it. `duration` (ms)\n * applies to both directions.\n */\nexport type UIModalTransition = DrawableStyle & BaseStyle & {\n overlayColor?: Color | null;\n duration?: number;\n};\n/**\n * A dialog: a `UIWidget` with the modal boilerplate built in. Comes with a scrim\n * (`overlayColor: \"rgba(0, 0, 0, 0.5)\"` unless overridden), animates on `show()`/`hide()`\n * (a 200 ms fade by default — swap the pose via `transition()`; the exit plays with\n * `commit: false`, so the style is intact for the next show), and closes itself on a scrim tap\n * or the Android back button (disable via `dismissible(false)`). Everything else is a plain\n * widget — same styling, children, touch and `attachTo()` surface; create it **once** at module\n * scope and reuse it.\n */\nexport interface UIModal extends UIWidget {\n /** Mount as an overlay and play the entrance transition. No-op while already open. */\n show(): void;\n /** Play the exit transition, then unmount. No-op while closed or already closing. */\n hide(): void;\n /** True from `show()` until `hide()` starts (already false during the exit animation). */\n readonly isOpen: boolean;\n /**\n * Replace the show/hide animation. `hidden` is the off-screen pose — `show()` animates from\n * it, `hide()` animates to it. Default `{ opacity: 0, duration: 200 }` (a fade); the pose\n * replaces it wholesale, so a slide without a fade is just the slide. The scrim keeps its own\n * fade unless the pose sets `overlayColor` itself.\n *\n * ```ts\n * sheet.transition({ transform: \"translateY(480px)\", duration: 250 }) // bottom sheet\n * ```\n */\n transition(hidden: UIModalTransition): this;\n /** Called when `show()` mounts the modal. */\n onOpen(callback: () => void): this;\n /** Called when the modal starts closing — scrim tap, back button, or a `hide()` call. */\n onClose(callback: () => void): this;\n /** `dismissible(false)` keeps scrim taps and the back button from closing the modal\n * (forced-choice dialogs). Default `true`. */\n dismissible(enabled: boolean): this;\n}\nexport declare class ModalElement extends WidgetElement {\n _open: boolean;\n _dismissible: boolean;\n _transition: UIModalTransition;\n _closeTimer?: ReturnType<typeof setTimeout>;\n readonly _openListeners: (() => void)[];\n readonly _closeListeners: (() => void)[];\n constructor(style: UIModalStyle, children: UINodeChild[] | ChildrenFn);\n private _pose;\n private get _duration();\n transition(hidden: UIModalTransition): this;\n show(): void;\n hide(): void;\n get isOpen(): boolean;\n onOpen(callback: () => void): this;\n onClose(callback: () => void): this;\n dismissible(enabled: boolean): this;\n}\n/** Create a modal dialog (see {@link UIModal}) — create once at module scope, then\n * `show()`/`hide()`. Same argument forms as `UIColumn`. */\nexport declare function UIModal(...children: UIChildArg[]): UIModal;\nexport declare function UIModal(children: UINodeChild[] | ChildrenFn): UIModal;\n/** @deprecated Style as the first argument is legacy — use chained `.style({...})`. */\nexport declare function UIModal(style: UIModalStyle, children?: UINodeChild[] | ChildrenFn): UIModal;\n","types/ui/UINode.d.ts":"import type { FetchResponse } from \"../runtime/fetch\";\nexport interface UINode {\n readonly type: string;\n /** Author-given semantic name (a stable selector for tests + AI review feedback). */\n readonly name?: string;\n style: Style<this, any>;\n /** Style-class proxy — read/set/toggle/bind the `$`-classes declared in `.style()`. See {@link Classes}. */\n readonly class: Classes<this>;\n}\n/** A child slot value: a node, or falsy (conditional rendering — falsy entries are skipped). */\nexport type UINodeChild = UINode | null | undefined | false;\n/** A factory child argument: a node (or falsy for conditionals), or an array of them — arrays are\n * flattened one level at the argument position, so `UIColumn(header, items.map(row), footer)`\n * needs no spread. */\nexport type UIChildArg = UINodeChild | UINodeChild[];\n/** A color: CSS-style string (`\"#1c1c1e\"`, `\"rgba(0,0,0,0.5)\"`, `\"var(--primaryColor)\"`) or\n * packed number; `null` clears. */\nexport type Color = number | string | null;\n/** Style props every element accepts. */\nexport type BaseStyle = {\n opacity?: number | `${number}`;\n transform?: string | null;\n backgroundColor?: Color | null;\n bgColor?: Color | null;\n overflow?: \"visible\" | \"hidden\";\n boxSizing?: \"border-box\" | \"content-box\";\n /**\n * Author-given semantic name — a stable selector for tests and for marking elements in the AI\n * code-review feedback loop. NOT a style: it's extracted at construction (never sent to the layout\n * engine) and surfaced on the node + in the renderer's serialized output. Available on every element.\n */\n name?: string;\n};\n/** Painted-box props: background, gradient, border, radius. */\nexport type DrawableStyle = {\n backgroundImage?: FetchResponse | File | string | null;\n bgGradient?: string;\n backgroundGradient?: string;\n bgImage?: FetchResponse | File | string | null;\n backgroundSize?: \"cover\" | \"contain\" | \"tile\";\n bgSize?: \"cover\" | \"contain\" | \"tile\";\n border?: string | number | null;\n borderWidth?: number;\n borderColor?: Color;\n borderLeft?: string | number | null;\n borderLeftWidth?: number;\n borderLeftColor?: Color;\n borderTop?: string | number | null;\n borderTopWidth?: number;\n borderTopColor?: Color;\n borderRight?: string | number | null;\n borderRightWidth?: number;\n borderRightColor?: Color;\n borderBottom?: string | number | null;\n borderBottomWidth?: number;\n borderBottomColor?: Color;\n borderRadius?: UIValue | string;\n borderTopLeftRadius?: UIValue;\n borderTopRightRadius?: UIValue;\n borderBottomLeftRadius?: UIValue;\n borderBottomRightRadius?: UIValue;\n pointerEvents?: \"all\" | \"none\";\n};\n/** Flex-layout props of a container (how it lays out its children). */\nexport type ContainerStyle = {\n flexDirection?: \"row\" | \"column\";\n justifyContent?: \"flex-start\" | \"center\" | \"flex-end\" | \"space-between\" | \"space-evenly\";\n alignItems?: \"flex-start\" | \"center\" | \"flex-end\" | \"stretch\";\n gap?: UIValue;\n flexWrap?: \"nowrap\" | \"wrap\" | \"wrap-reverse\";\n};\n/** A dimension: a number (logical px) or a CSS-style unit / function string. */\ntype UIValue = number | `${number}px` | `${number}vw` | `${number}vh` | `${number}vmin` | `${number}vmax` | `${number}em` | `calc(${string})` | `min(${string})` | `max(${string})` | `${string}%` | `clamp(${string})` | `var(--${string})`;\n/** Padding, with `p`/`px`/`pl`… shorthands. `safe-*` insets by the device safe area,\n * `comfort-*` by the theme's comfort knobs (max of both). */\nexport type PaddingStyle = {\n paddingLeft?: UIValue | \"safe-left\" | \"comfort-left\";\n paddingTop?: UIValue | \"safe-top\" | \"comfort-top\";\n paddingRight?: UIValue | \"safe-right\" | \"comfort-right\";\n paddingBottom?: UIValue | \"safe-bottom\" | \"comfort-bottom\";\n padding?: UIValue | \"safe-all\" | \"comfort-all\";\n paddingHorizontal?: UIValue | \"comfort-x\";\n paddingVertical?: UIValue | \"comfort-y\";\n pl?: UIValue | \"safe-left\" | \"comfort-left\";\n pt?: UIValue | \"safe-top\" | \"comfort-top\";\n pr?: UIValue | \"safe-right\" | \"comfort-right\";\n pb?: UIValue | \"safe-bottom\" | \"comfort-bottom\";\n p?: UIValue | \"safe-all\" | \"comfort-all\";\n px?: UIValue | \"comfort-x\";\n py?: UIValue | \"comfort-y\";\n};\n/** Margin, with `m`/`mx`/`ml`… shorthands; `\"auto\"` centers/pushes like CSS. */\nexport type MarginStyle = {\n marginLeft?: UIValue | \"auto\" | \"safe-left\" | \"comfort-left\";\n marginTop?: UIValue | \"auto\" | \"safe-top\" | \"comfort-top\";\n marginRight?: UIValue | \"auto\" | \"safe-right\" | \"comfort-right\";\n marginBottom?: UIValue | \"auto\" | \"safe-bottom\" | \"comfort-bottom\";\n margin?: UIValue | \"auto\" | \"safe-all\" | \"comfort-all\";\n marginHorizontal?: UIValue | \"auto\" | \"comfort-x\";\n marginVertical?: UIValue | \"auto\" | \"comfort-y\";\n ml?: UIValue | \"auto\" | \"safe-left\" | \"comfort-left\";\n mt?: UIValue | \"auto\" | \"safe-top\" | \"comfort-top\";\n mr?: UIValue | \"auto\" | \"safe-right\" | \"comfort-right\";\n mb?: UIValue | \"auto\" | \"safe-bottom\" | \"comfort-bottom\";\n m?: UIValue | \"auto\" | \"safe-all\" | \"comfort-all\";\n mx?: UIValue | \"auto\" | \"comfort-x\";\n my?: UIValue | \"auto\" | \"comfort-y\";\n};\n/** Box position (for `position: \"absolute\"`) and size constraints. */\nexport type PositionStyle = {\n top?: UIValue | `${number}%` | 'safe-top' | 'comfort-top';\n left?: UIValue | `${number}%` | 'safe-left' | 'comfort-left';\n bottom?: UIValue | `${number}%` | 'safe-bottom' | 'comfort-bottom';\n right?: UIValue | `${number}%` | 'safe-right' | 'comfort-right';\n /** Shorthand for all four edges at one value. A longhand (`top`, `left`, …) overrides it. */\n inset?: UIValue | `${number}%` | \"auto\";\n width?: UIValue | `${number}%` | \"auto\";\n height?: UIValue | `${number}%` | \"auto\";\n maxWidth?: UIValue | `${number}%` | \"auto\";\n maxHeight?: UIValue | `${number}%` | \"auto\";\n minWidth?: UIValue | `${number}%` | \"auto\";\n minHeight?: UIValue | `${number}%` | \"auto\";\n};\n/** The base style of every element: box + flex-child props. */\nexport type ElementStyle = PaddingStyle & MarginStyle & BaseStyle & PositionStyle & {\n position?: \"absolute\" | \"static\" | \"relative\";\n aspectRatio?: number;\n flex?: number | string;\n flexGrow?: number;\n flexShrink?: number;\n flexBase?: UIValue | `${number}%` | \"auto\";\n alignSelf?: \"flex-start\" | \"center\" | \"flex-end\" | \"stretch\";\n display?: \"none\" | \"flex\";\n};\n/** Typography props. */\nexport type TextStyle = {\n textAlign?: \"start\" | \"center\" | \"end\" | \"left\" | \"right\";\n fontFamily?: string;\n fontSize?: UIValue;\n lineHeight?: UIValue | \"normal\";\n fontWeight?: number | `${number}` | \"normal\" | \"bold\";\n fontStyle?: \"normal\" | \"italic\";\n color?: Color;\n textDecoration?: \"underline\" | \"line-through\" | \"none\";\n letterSpacing?: UIValue;\n /** Cap the text at N lines; the box is measured to the clamped height. 0 / omitted = unbounded. */\n lineClamp?: number;\n /** How a clamped line ends. Only meaningful together with `lineClamp`. Default \"ellipsis\". */\n textOverflow?: \"ellipsis\" | \"clip\";\n};\n/** Reactive style input: every primitive-valued prop also accepts a `() => value` binding that\n * re-applies when a signal it read changes. Nested state blocks (onPressed, onLandscape, …) stay\n * static — bindings are extracted at the top level only. */\nexport type Reactive<T> = {\n [K in keyof T]: NonNullable<T[K]> extends object ? T[K] : T[K] | (() => T[K]);\n};\n/** User-defined style classes: any `$`-prefixed key in `.style()` declares a state block toggled\n * from code via the `el.class` proxy; `duration`/`delay` animate the swap. Class state INHERITS\n * down the tree (CSS-`.dark`-on-body style): a class set on a node also activates same-name `$`\n * blocks on all descendants within the same root (docs/style-class-cascade-plan.md).\n * `$pressed`/`$focused` are reserved — hosts toggle them on press/focus (they beat other\n * classes, lose to onPressed/onFocused), so children can react to an ancestor's press.\n *\n * Instantiated with the node's FULL style `T` — a class block accepts everything the node's\n * `.style()` does, like `onLandscape`. Narrowing it wrongly rejects valid props such as\n * `$active: { color }`; guarded by tests/ui-types.test.ts. */\nexport type ClassStyles<T> = {\n [key: `$${string}`]: T & {\n duration?: number;\n delay?: number;\n };\n};\n/** Value accepted by a `el.class` write: a boolean sets the class, a `() => boolean` binds it —\n * the class then tracks the signals the function reads (re-evaluated on change). Reads through\n * the proxy always return a plain boolean, never the bound function. */\nexport type ClassValue = boolean | (() => boolean);\n/** The `el.class` proxy — the runtime switch for `$`-class blocks declared in `.style()`\n * (see {@link ClassStyles}). One surface, mirroring `el.style`:\n *\n * ```ts\n * el.class.checked // read: is it active on THIS element? → boolean\n * el.class.checked = true // activate (false deactivates)\n * el.class.open = !el.class.open // toggle\n * el.class.done = () => todo.done.value // reactive binding (signals)\n * el.class({ checked: true, done: () => … }) // batch form — returns the element, chainable\n * ```\n *\n * Class names are accepted with or without the declaration-site `$` prefix. `R` is the concrete\n * node type, so the batch form chains like `.style()`.\n *\n * Typing note: property access is `any` because an index signature can't give reads (`boolean`)\n * and writes ({@link ClassValue}) different types — the batch form is the fully typed path;\n * single-key writes are runtime-coerced with `!!`. */\nexport type Classes<R> = ((classes: Record<string, ClassValue>) => R) & {\n [key: string]: any;\n};\n/** Members every UI element shares — element interfaces extend this so docs and types live in one\n * place. `S` is the element's style object; `A` is the subset `animateTo` accepts (defaults to `S`). */\nexport interface UIElementBase<S extends object, A extends object = S> {\n /** Style: `.style({...})` merges (chainable); `el.style.key = v` writes one prop, a `() => v`\n * value binds it to signals — see {@link Style}. */\n style: Style<this, S>;\n /** Tween to the target style — meta keys `duration`/`delay`/`loop`/…, see {@link AnimateStyle}. */\n animateTo: AnimateStyle<this, A>;\n /** Tween from the given style to the current one (entrance animations). */\n animateFrom: AnimateStyle<this, A>;\n /** Fires after every layout pass with the parent-relative box. */\n onLayout(onLayout: OnLayoutCallback): this;\n /** Absolute rect in device space, read live (includes scroll); `null` before mount. */\n getBoundingClientRect(): BoundingClientRect | null;\n /** Style-class proxy — read `el.class.checked`, set `el.class.checked = true`, toggle with\n * `!el.class.checked`, bind `el.class.done = () => sig.value`, batch/chain `el.class({ … })`.\n * Classes cascade to descendants. See {@link Classes}. */\n readonly class: Classes<this>;\n}\n/** {@link UIElementBase} plus the child-management surface every container shares. */\nexport interface UIContainerBase<S extends object, A extends object = S> extends UIElementBase<S, A> {\n /** Append children. */\n append(...nodes: UINodeChild[]): this;\n /** Insert children at `index`. */\n insert(index: number, ...nodes: UINodeChild[]): this;\n /** Remove (unmount) the given children. */\n remove(...nodes: UINodeChild[]): this;\n /** Replace all children — an array, or a function for reactive children. */\n setContent(nodes: UINodeChild[] | ChildrenFn): this;\n /** The children array — mutate via `append`/`insert`/`remove`/`setContent`. */\n readonly children: UINodeChild[];\n}\n/** Orientation state blocks — override props applied only in landscape / portrait (like a\n * `$`-class, keyed by device orientation instead of `el.class`). Same full-`T` rule as class\n * blocks. */\nexport type OrientationStyles<T> = {\n onLandscape?: T;\n onPortrait?: T;\n /** @deprecated Misspelling of `onPortrait` (no second \"r\"). Kept so existing projects and published\n * bundles keep working — hosts still honour it — but new code should use `onPortrait`. */\n onPortait?: T;\n};\nexport type StyleFn<R, T extends object> = ((style: Reactive<T> & OrientationStyles<T> & ClassStyles<T>) => R);\n/** The `el.style` surface: callable — `.style({...})` merges and returns the element for\n * chaining — and per-key readable/writable (`el.style.opacity = 0.5`; a `() => value` write\n * installs a reactive binding). */\nexport type Style<R, T extends object> = StyleFn<R, T> & T & OrientationStyles<T> & ClassStyles<T>;\n/** The `animateTo`/`animateFrom` surface: target style props plus the flat meta keys below\n * (stripped before the commit into the element's style). */\nexport type AnimateStyle<R, T extends object> = ((style: T & {\n /** Tween length in **milliseconds** (default 225). */\n duration?: number;\n /** Wait before starting, in **milliseconds**. A looping animation delays once, not per cycle. */\n delay?: number;\n /** Escape hatch: target an internal style layer (the onPressed/orientation mechanism). Not part of the supported surface. */\n layer?: number;\n /** `false` = animate without writing the targets into the element's style (e.g. a fade-out right before `.hide()`). */\n commit?: boolean;\n /** Repeat the animation: `true` = forever, a number = that many cycles. A looping animation is an\n * effect, not a state change — it never commits, and the element ends back at its base style.\n * The loop stops when a later `animateTo`/`animateFrom` runs on the element or it leaves the screen. */\n loop?: boolean | number;\n /** `\"ping-pong\"` (default) animates there and back each cycle — no jump. `\"restart\"` snaps back and\n * replays forward — for full-turn spinners (`transform: \"rotate(360deg)\"`) and shimmers. Only meaningful with `loop`. */\n loopMode?: \"restart\" | \"ping-pong\";\n}) => R);\nexport type AppearStyle<R, T> = (arg: {\n from: T;\n duration?: number;\n delay?: number;\n}) => R;\nexport type DisappearStyle<R, T> = (arg: {\n to: T;\n duration?: number;\n delay?: number;\n}) => R;\n/** `onLayout` payload — the node's box in PARENT-relative coordinates. */\nexport type OnLayoutCallback = (layout: {\n left: number;\n top: number;\n width: number;\n height: number;\n}) => void;\n/** Web-DOMRect shape on purpose (getBoundingClientRect priors must hold): all eight fields, with\n * right/bottom/x/y derived SDK-side — hosts only report [left, top, width, height]. */\nexport type BoundingClientRect = {\n x: number;\n y: number;\n left: number;\n top: number;\n right: number;\n bottom: number;\n width: number;\n height: number;\n};\nexport declare class Element<T extends string> {\n readonly type: T;\n /** Author-given semantic name (LeCodes `name`) — see BaseStyle.name. Extracted from the options\n * object so it never reaches the layout engine; the renderer reads it off the node. */\n readonly name?: string;\n protected _style: any;\n protected _id: number;\n protected _styleProxy: any;\n protected _appear: any;\n protected _disappear: any;\n constructor(type: T, style: any);\n get style(): any;\n /** Tween to the target style and commit it (unless `commit: false` or looping — a loop is an\n * effect, not a state change). Meta keys: `duration`/`delay`/`loop`/… — see {@link AnimateStyle}. */\n animateTo(style: any): this;\n /** Tween FROM the given style to the element's current one (entrance animations). */\n animateFrom(style: any): this;\n protected _classProxy?: any;\n /** Style-class control — flips the `$`-class blocks declared in `.style()`. One proxy, same\n * contract as `el.style`:\n *\n * - `el.class.checked` — read: is the class active on THIS element? → `boolean`\n * - `el.class.checked = true` / `= false` — activate / deactivate\n * - `el.class.open = !el.class.open` — toggle\n * - `el.class.done = () => todo.done.value` — reactive: the class tracks the signals the\n * function reads; a later write to the same class (plain or function) replaces the binding\n * - `el.class({ checked: true, done: () => … })` — batch form, returns the element (chainable)\n *\n * Names are accepted with or without the leading `$`. A class set on an element CASCADES: it is\n * also active on every descendant (their same-name `$` blocks light up), until the subtree's\n * root — hosted screens/widgets don't inherit. Reads reflect only this element's own classes;\n * there is no opt-out below an active ancestor. `Object.keys(el.class)` lists the active names. */\n get class(): any;\n protected ll?: OnLayoutCallback[];\n /** Observe layout: fires after every host layout pass with the parent-relative box. */\n onLayout(onLayout: OnLayoutCallback): this;\n /** Absolute rect in device space — the space `UIWidget` positions in and touch events report\n * `clientX`/`clientY` in — including scroll offsets, read live at call time (unlike `onLayout`,\n * whose coordinates are parent-relative and go stale when an ancestor scrolls). `null` before\n * the element is mounted and on hosts without the bridge read. Anchor popovers position-once\n * at open; don't poll per frame. */\n getBoundingClientRect(): BoundingClientRect | null;\n}\n/** Reactive children: re-runs when a signal it read changes; the result is reconciled against\n * the mounted children (kept nodes stay mounted, state intact). */\nexport type ChildrenFn = () => UINodeChild[];\n/**\n * Compiler-emitted memoized map for reactive children. The chisel `reactiveUi` pass rewrites\n * `list.map(fn)` inside a children binding to `__uiMap(list, fn, \"<file>:<offset>\")`, so unchanged\n * items keep their element identity across re-runs (the reconciler then leaves them mounted).\n * Cache: per (binding owner, call-site slot), keyed by item reference; duplicate items consume\n * cached nodes in order. Outside a children binding, for non-array inputs, or for non-element\n * results it behaves exactly like Array.prototype.map — a wrong rewrite can't change behavior.\n */\nexport declare function __uiMap(list: any, render: (item: any, index: number) => any, slot: string): any[];\nexport declare class ContainerElement<T extends string> extends Element<T> {\n children: any[];\n constructor(type: T, style: any, children: any[] | ChildrenFn);\n /** Append children (falsy entries are kept in the array but never mounted). */\n append(...nodes: UINodeChild[]): this;\n /** Insert children at `index` of the children array. */\n insert(index: number, ...nodes: UINodeChild[]): this;\n /** Remove (unmount) the given children. */\n remove(...nodesToDelete: UINode[]): this;\n /** Replace all children — a plain array, or a function for reactive children. */\n setContent(children: UINodeChild[] | ChildrenFn): this;\n}\nexport {};\n","types/ui/UIPager.d.ts":"import { ContainerElement, type BaseStyle, type ChildrenFn, type DrawableStyle, type ElementStyle, type UIElementBase, type UINodeChild } from \"./UINode\";\nimport type { UIScreen } from \"./UIScreen\";\n/** Styles a pager accepts — layout box + drawable (background, borders, …). Pages style\n * themselves; the pager only owns its own slot. */\nexport type UIPagerStyle = ElementStyle & DrawableStyle;\n/**\n * The screen-navigation element: sibling **tabs** that swipe natively side to side, each with its\n * own navigation **stack**. `push` opens a screen on top of the current tab (within the pager);\n * `pop` / the native edge back-swipe unwinds it. A one-tab pager is a plain navigation stack.\n *\n * ```ts\n * const pager = UIPager([ HomeScreen(), ProfileScreen() ]) // two tabs, side by side\n * Router.init(UIScreen([ pager.style({ flexGrow: 1 }), tabBar ]))\n *\n * // from anywhere inside a hosted screen — no reference threading:\n * UIPager.push(PostScreen(id))\n * ```\n *\n * To open something over *everything* (above bars, above the pager), use `Router.push` instead.\n */\nexport interface UIPager extends UIElementBase<UIPagerStyle, DrawableStyle & BaseStyle> {\n readonly type: \"pager\";\n /** Replace the pager's tabs — one screen per tab, in order. Every tab becomes a fresh\n * one-screen stack (pushed screens are dropped) and the selection is clamped into range;\n * screens that were already tabs keep their state. Pass a function for reactive tabs. */\n setContent(tabs: UIScreen[] | (() => UIScreen[])): this;\n /** Switch to tab `index`. **Instant by default** — the tab-bar convention (tabs are parallel\n * modes, not neighbors); pass `animated: true` for the direction-aware slide of top-tab /\n * pager UIs. Out-of-range and same-index calls are no-ops. Tabs keep their stacks: selecting\n * away and back restores the tab exactly where it was, pushed screens included. */\n select(index: number, animated?: boolean): this;\n /** The selected tab index (0-based). */\n readonly index: number;\n /** Fires when the selected tab changes and has settled — a user swipe or `select()`. */\n onSelect(callback: (index: number) => void): this;\n /** Push `screen` on top of the **current tab** — slides in natively; the edge back-swipe (or\n * `pop()`) removes it. Other tabs are unaffected. */\n push(screen: UIScreen): this;\n /** Pop the current tab's top screen (no-op at the tab root — the root never pops). The\n * programmatic twin of the native edge back-swipe. */\n pop(): this;\n /** Unwind the current tab back to its root screen in one step. */\n popToRoot(): this;\n /** Swap the current tab's top screen for `screen` without growing the stack (at depth 1 this\n * swaps the tab's root). */\n replace(screen: UIScreen): this;\n /** The current tab's screens, root → top (read-only snapshot). */\n readonly stack: UIScreen[];\n /** The current tab's stack depth — 1 means only the root. While `depth > 1`, swiping between\n * tabs is disabled (the horizontal gesture belongs to the back-swipe). */\n readonly depth: number;\n /** Fires when the current tab's depth changes — push, pop, replace, or a back-swipe. */\n onChange(callback: (depth: number) => void): this;\n}\nexport declare class PagerElement extends ContainerElement<\"pager\"> {\n /** Per-tab stack lengths — partitions the flat tab-major `children`. Named `_*` so chisel\n * keeps it (the host reads it live). */\n _lens: number[];\n /** Selected tab. */\n _index: number;\n _openCount: number;\n private scl;\n private ncl;\n constructor(style: UIPagerStyle | null, tabs: UIScreen[]);\n /** Start offset of tab `i`'s segment in the flat `children`. */\n private _offset;\n get index(): number;\n get stack(): UIScreen[];\n get depth(): number;\n onSelect(callback: (index: number) => void): this;\n onChange(callback: (depth: number) => void): this;\n select(index: number, animated?: boolean): this;\n push(screen: UIScreen): this;\n pop(): this;\n popToRoot(): this;\n replace(screen: UIScreen): this;\n private _rebuild;\n setContent(children: UINodeChild[] | ChildrenFn): this;\n append(...nodes: UINodeChild[]): this;\n insert(index: number, ...nodes: UINodeChild[]): this;\n remove(...nodesToDelete: UIScreen[]): this;\n _reconcile(next: UINodeChild[]): void;\n _hostDidSelect(index: number): void;\n _hostDidPop(depth: number): void;\n private _emitSelect;\n private _emitChange;\n private _track;\n _activate(): void;\n _deactivate(): void;\n}\n/** Callable factory + ambient statics. The name `UIPager` is a value (this factory) and a type\n * (the instance interface above) — a standard value/type merge. */\ninterface UIPagerConstructor {\n /** Tabs — each argument is a screen or an array of screens (arrays flatten one level, falsy\n * entries are skipped). One screen → a plain navigation stack rooted at it (push/pop, no tab\n * swiping); several → swipeable sibling tabs, fixed at construction, each starting as its own\n * one-screen stack. */\n (...tabs: (UIScreen | UIScreen[] | false | null | undefined)[]): UIPager;\n /** @deprecated Style as the first argument is legacy — use chained `.style({...})`. */\n (style: UIPagerStyle, content?: UIScreen | UIScreen[]): UIPager;\n /** The pager that owns the currently visible screen, or `null` when the visible screen isn't\n * hosted by one. With pagers nested inside pages, resolves to the **innermost** — so ambient\n * calls act on the pager the user is actually looking at. */\n readonly current: UIPager | null;\n /** `UIPager.current.push(screen)` — push onto the pager owning the visible screen, no\n * reference threading. No-op with a console warning when there is no current pager. */\n push(screen: UIScreen): void;\n /** `UIPager.current.pop()` — pop the visible pager's current tab (no-op at the tab root, or\n * with a warning when there is no current pager). */\n pop(): void;\n /** `UIPager.current.popToRoot()` — unwind the visible pager's current tab to its root. */\n popToRoot(): void;\n}\n/**\n * Create a pager — THE screen-navigation element: an array of screens becomes swipeable sibling\n * tabs, a single screen becomes a plain stack. Navigate within it via `pager.push/pop/replace`\n * (per-tab) and `pager.select(i)` (between tabs), or from any child screen via the ambient\n * `UIPager.push` / `UIPager.pop` / `UIPager.current`. Pages are full `UIScreen`s (own\n * `onOpen`/`onClose`); give the pager `flexGrow: 1` or a size so it doesn't\n * collapse. `Router` stays the way to open a destination ON TOP of the pager.\n */\nexport declare const UIPager: UIPagerConstructor;\nexport {};\n","types/ui/UIPopover.d.ts":"import { ModalElement, type UIModal, type UIModalStyle } from \"./UIModal\";\nimport { type BoundingClientRect, type ChildrenFn, type UIChildArg, type UINodeChild } from \"./UINode\";\nexport type UIPopoverStyle = UIModalStyle;\n/** What a popover can anchor to: any element (it reads `getBoundingClientRect()`), or a raw\n * `{x, y}` point — a long-press context menu anchors to the touch position. */\nexport type UIPopoverAnchor = {\n getBoundingClientRect(): BoundingClientRect | null;\n} | {\n x: number;\n y: number;\n};\n/**\n * An anchored menu: a `UIModal` whose scrim is transparent (invisible but still intercepting —\n * an outside tap dismisses, and nothing underneath can scroll while it's open) and whose\n * position comes from the anchor passed to `show(anchor)`: below the anchor's left edge,\n * flipped above when there's no room, clamped into the viewport. Position is computed once per\n * show — anchored popovers don't follow their anchor. Backs dropdowns, context menus, and\n * tooltips; create it **once** at module scope and reuse it.\n */\nexport interface UIPopover extends UIModal {\n /** Position next to `anchor` (an element or an `{x, y}` point), attach to\n * `Presentable.current` (unless an owner was set via `attachTo`), and play the entrance\n * transition. Without an anchor the popover shows wherever its own style puts it. */\n show(anchor?: UIPopoverAnchor): void;\n}\nexport declare class PopoverElement extends ModalElement {\n private _anchorRect?;\n private _placedLeft?;\n private _placedTop?;\n constructor(style: UIPopoverStyle, children: UINodeChild[] | ChildrenFn);\n show(anchor?: UIPopoverAnchor): void;\n private _place;\n}\n/** Create an anchored popover (see {@link UIPopover}) — create once at module scope, then\n * `show(anchor)` next to an element or `{x, y}` point. Same argument forms as `UIColumn`. */\nexport declare function UIPopover(...children: UIChildArg[]): UIPopover;\nexport declare function UIPopover(children: UINodeChild[] | ChildrenFn): UIPopover;\n/** @deprecated Style as the first argument is legacy — use chained `.style({...})`. */\nexport declare function UIPopover(style: UIPopoverStyle, children?: UINodeChild[] | ChildrenFn): UIPopover;\n","types/ui/UIScreen.d.ts":"import { TouchStartEvent } from \"../runtime/touch\";\nimport { type PresentOptions } from \"./presentable\";\nimport { ContainerElement, type BaseStyle, type ContainerStyle, type DrawableStyle, type PaddingStyle, type UIChildArg, type UIContainerBase, type UINodeChild, type ChildrenFn } from \"./UINode\";\nexport type UIScreenStyle = ContainerStyle & DrawableStyle & PaddingStyle & BaseStyle;\n/** A screen — the root the router/host mounts, sized to its slot. A screen NEVER scrolls: it is\n * fixed chrome (header, tab bar) plus, when the content overflows, one `UIScrollable` body child\n * (`flexGrow: 1`). Scroll events and pull-to-refresh live on the scroll containers\n * (`UIScrollable`, `UIVirtualizedList`). */\nexport interface UIScreen extends UIContainerBase<UIScreenStyle, DrawableStyle & BaseStyle> {\n readonly type: \"screen\";\n /** Show this screen as the current destination (replaces whatever is visible — a screen, a\n * scene, a native view — suspending an active Router until `Router.restore()`). */\n open(options?: PresentOptions): void;\n /** Dismiss if this screen is the visible destination. */\n close(): void;\n /** Hardware/system back while this screen is current. */\n onBackPressed(callback: () => void): this;\n /** The screen became the visible destination (first open, or revealed by a pop). */\n onOpen(callback: () => void): this;\n /** The screen stopped being visible — closed, replaced, or covered by a push. */\n onClose(callback: () => void): this;\n /**\n * Keep this screen's built native tree alive when a host detaches it: instead of being destroyed,\n * its views + layout + live state (scroll position, input text) are retained, so re-hosting the\n * SAME screen object restores it in place rather than rebuilding. `onClose`/`onOpen` still fire on\n * detach/re-attach. You own the lifetime — a kept tree is freed only by `dispose()` or when the\n * project unloads. (Native-only today; web rebuilds.)\n */\n keepAlive(enabled?: boolean): this;\n /** Free a `keepAlive()` screen's retained tree now. No-op unless it's currently detached-and-kept. */\n dispose(): this;\n /** Touch began on the screen; `ev.track(...)` takes over the rest of the gesture. */\n onTouchStart(callback: (ev: TouchStartEvent<UIScreen>) => void): this;\n}\nexport declare class ScreenElement extends ContainerElement<\"screen\"> {\n open(options?: PresentOptions): void;\n close(): void;\n protected ol: (() => void)[];\n onOpen(callback: () => void): this;\n protected cl: (() => void)[];\n onClose(callback: () => void): this;\n _keepAlive: boolean;\n keepAlive(enabled?: boolean): this;\n dispose(): this;\n readonly touchStartListeners: any[];\n _interactive: boolean;\n onTouchStart(callback: any): this;\n _emitTouchStart(pointerId: number, clientX: number, clientY: number): any;\n _backButtonCallback?: () => void;\n onBackPressed(callback: any): this;\n}\n/** Create a screen. Present it with `.open()`, or via `Router` / `UIPager`. Same argument forms\n * as `UIColumn`. */\nexport declare function UIScreen(...children: UIChildArg[]): UIScreen;\nexport declare function UIScreen(children: UINodeChild[] | ChildrenFn): UIScreen;\n/** @deprecated Style as the first argument is legacy — use chained `.style({...})`. */\nexport declare function UIScreen(style: UIScreenStyle, children?: UINodeChild[] | ChildrenFn): UIScreen;\n","types/ui/UIScrollable.d.ts":"import type { UIContainerStyle } from \"./UIContainer\";\nimport { type UIChildArg, type UIContainerBase, type UINodeChild, type ChildrenFn, type Color } from \"./UINode\";\nexport type ScrollStyle = {\n showScrollbar?: boolean;\n overscrollMode?: \"none\" | \"absorb\" | \"default\";\n /** Tint of the native pull-to-refresh spinner (pairs with `onRefresh`). */\n refreshControlColor?: Color;\n /** How a scroll gesture in THIS scrollable dismisses the keyboard: `\"interactive\"` (default) —\n * dragging over the keyboard slides it away (chat feel); `\"scroll\"` — any drag dismisses\n * immediately; `\"none\"` — never (tap-outside policy still applies). */\n keyboardDismissMode?: \"interactive\" | \"scroll\" | \"none\";\n /** Paging: when the drag ends, rest on a direct child's boundary along the scroll axis — the\n * value picks where the child sits in the viewport; `\"none\"` (default) is free scrolling. Snap\n * targets are the children themselves, so item widths can differ (card-carousel-with-peek); a\n * carousel is a horizontal scrollable of full-width children + `snap: \"start\"`. */\n snap?: \"none\" | \"start\" | \"center\" | \"end\";\n};\nexport type UIScrollableStyle = UIContainerStyle & ScrollStyle & {\n scrollDirection?: \"horizontal\" | \"vertical\";\n};\n/** A scroll container — vertical by default, `scrollDirection: \"horizontal\"` for carousels/chip\n * rows. The scrolling body of a screen (screens themselves never scroll). */\nexport interface UIScrollable extends UIContainerBase<UIScrollableStyle> {\n readonly type: \"scrollable\";\n /** Scroll position changed (px from the start edge). */\n onScroll(callback: (scrollPosition: number) => void): UIScrollable;\n /** The scroll gesture ended (finger lifted). */\n onScrollRelease(callback: () => void): UIScrollable;\n /** Pulled past the content edge by `delta` px. */\n onOverscroll(callback: (delta: number) => void): UIScrollable;\n /** Pull-to-refresh: the spinner stays until the returned promise settles. Attach BEFORE the\n * node mounts (hosts read it at creation). Vertical only; native hosts — no-op on web. */\n onRefresh(callback: () => void | Promise<void>): UIScrollable;\n}\n/** Create a scroll container (same argument forms as `UIColumn`). As a screen body, pair with\n * `flexGrow: 1`. */\nexport declare function UIScrollable(...children: UIChildArg[]): UIScrollable;\nexport declare function UIScrollable(children: UINodeChild[] | ChildrenFn): UIScrollable;\n/** @deprecated Style as the first argument is legacy — use chained `.style({...})`. */\nexport declare function UIScrollable(style: UIScrollableStyle, children?: UINodeChild[] | ChildrenFn): UIScrollable;\n","types/ui/UISpacer.d.ts":"import { type ElementStyle, type UIElementBase } from \"./UINode\";\nexport type UISpacerStyle = ElementStyle;\n/** A flexible gap — `flexGrow: 1` by default, pushes its siblings apart. */\nexport interface UISpacer extends UIElementBase<UISpacerStyle> {\n readonly type: \"spacer\";\n}\n/** Create a flexible gap (`flexGrow: 1`) — e.g. between a header's title and its actions. */\nexport declare function UISpacer(): UISpacer;\nexport declare function UISpacer(style: UISpacerStyle): UISpacer;\n","types/ui/UITabs.d.ts":"import { type UIPager } from \"./UIPager\";\nimport { ScreenElement, UIScreen } from \"./UIScreen\";\nimport { type UIRow as UIRowType } from \"./UIContainer\";\nimport { type ImageSource } from \"./UIImage\";\nimport type { UIChildArg } from \"./UINode\";\nexport type UITabDef = {\n label: string;\n /** Tab icon — typically `assetIcon(\"lucide:…\")`. Tinted active/inactive by the bar. */\n icon?: ImageSource;\n /** The tab's root screen. Tabs are fixed at construction (like UIPager's). */\n screen: UIScreen;\n};\n/**\n * A bottom-tab app shell: swipeable tabs (a `UIPager`) plus a themed tab bar, as one\n * `UIScreen` — present it directly (`Router.init(tabs)`). Keys are tab ids, in tab order:\n *\n * ```ts\n * const tabs = UITabs({\n * home: { label: \"Home\", icon: assetIcon(\"lucide:house\"), screen: homeScreen },\n * profile: { label: \"Profile\", icon: assetIcon(\"lucide:user\"), screen: profileScreen },\n * })\n * Router.init(tabs)\n * ```\n *\n * In-tab navigation stays the pager's: `UIPager.push(detail)` from any screen (bar stays);\n * `Router.push` opens above the shell (bar covered). Restyle via `theme()` (primaryColor,\n * mutedColor, tabbarBg, …) or the `bar` handle; for a fully custom bar build on `UIPager`.\n */\nexport interface UITabs extends UIScreen {\n /** The active tab id. */\n readonly tab: string;\n /** Switch tabs (instant, the tab-bar convention; `animated: true` slides). */\n select(id: string, animated?: boolean): this;\n /** Fires when the active tab changes and has settled — a bar tap, swipe, or `select()`. */\n onSelect(callback: (id: string, index: number) => void): this;\n /** Show a badge on a tab: `true` = dot, a number/string = count pill, `false`/`null`/`0` clears. */\n badge(id: string, value: number | string | boolean | null): this;\n /** The pager under the bar — in-tab stacks (`push`/`pop`/`depth`). */\n readonly pager: UIPager;\n /** The bar row (named \"tabbar\") — for restyling beyond the theme variables. */\n readonly bar: UIRowType;\n}\nexport declare class TabsElement extends ScreenElement {\n private readonly ids;\n private readonly _pagerEl;\n private readonly _bar;\n private readonly _icons;\n private readonly _labels;\n private readonly _badges;\n private readonly _badgeTexts;\n private readonly _buttons;\n private readonly _selectListeners;\n constructor(defs: Record<string, UITabDef>);\n private _applyActive;\n get tab(): string;\n get pager(): any;\n get bar(): any;\n select(id: string, animated?: boolean): this;\n onSelect(callback: (id: string, index: number) => void): this;\n badge(id: string, value: number | string | boolean | null | undefined): this;\n}\n/** Create the standard bottom-tab shell — see {@link UITabs}. Keys are tab ids in tab order;\n * each tab needs a `label` and its root `screen` (plus an optional `icon`). */\nexport declare function UITabs(tabs: Record<string, UITabDef>): UITabs;\n/** A `defineTabs` tab: `label` + optional `icon` (an `assetIcon(\"lucide:…\")` call — never a\n * hand-written source object). `UITabDef` is this plus the tab's root `screen`. */\nexport type TabDef = Omit<UITabDef, \"screen\">;\n/** What `defineTabs` returns: the bar (mount it yourself when the screen owns its whole layout)\n * and the standard screen shell around it. `active` must be a declared tab id, as a literal. */\nexport type TabsHandle<T extends Record<string, TabDef>> = {\n /** Tab ids in declaration order. */\n ids: (keyof T & string)[];\n /** The bar alone — one button per tab, the `active` one highlighted. */\n bar(active: keyof T & string): UIRowType;\n /** A screen sitting ON the bar: `[ padded content column, bar ]`. */\n screen(active: keyof T & string, ...children: UIChildArg[]): UIScreen;\n};\n/**\n * Declare a tab bar WITHOUT screens — the design-stage twin of {@link UITabs} (same keys, same\n * `tab-<id>` button names, same theme variables), for mockups where every screen is its own file\n * and mounts the bar with a literal tab id:\n *\n * ```ts\n * export const mainTabs = defineTabs({\n * home: { label: \"Home\", icon: assetIcon(\"lucide:house\") },\n * profile: { label: \"Profile\", icon: assetIcon(\"lucide:user\") },\n * })\n * // in a screen file:\n * export default () => mainTabs.screen(\"home\", [ ...content ])\n * ```\n *\n * Restyle through the theme — `theme({ primaryColor, mutedColor, tabbarBg, screenBg })` recolors\n * every bar at once. The built app passes the same keys (plus each tab's root screen) to `UITabs`,\n * which renders the identical bar interactively.\n */\nexport declare function defineTabs<T extends Record<string, TabDef>>(tabs: T): TabsHandle<T>;\n","types/ui/UIText.d.ts":"import { Element, type BaseStyle, type DrawableStyle, type ElementStyle, type TextStyle, type UIElementBase } from \"./UINode\";\nexport type UITextStyle = ElementStyle & TextStyle & DrawableStyle;\n/** A text label. */\nexport interface UIText extends UIElementBase<UITextStyle, DrawableStyle & BaseStyle & TextStyle> {\n readonly type: \"text\";\n /** The displayed string — writable at any time. */\n text: string;\n}\nexport declare class TextElement extends Element<\"text\"> {\n private _text;\n constructor(style: any, text: string | (() => string));\n get text(): string;\n set text(value: string);\n}\n/** Create a text label — a string, or `() => string` for reactive text that re-renders when a\n * signal it read changes. */\nexport declare function UIText(text: string | (() => string)): UIText;\n/** @deprecated Style as the first argument is legacy — use chained `.style({...})`. */\nexport declare function UIText(style: UITextStyle, text: string | (() => string)): UIText;\n","types/ui/UIVideo.d.ts":"import type { VideoPlayer } from \"../runtime/media\";\nimport { type PresentOptions } from \"./presentable\";\nimport { type BaseStyle, type DrawableStyle, type ElementStyle, type UIElementBase } from \"./UINode\";\nexport type UIVideoStyle = ElementStyle & DrawableStyle & {\n objectFit?: \"cover\" | \"contain\" | \"fill\";\n};\n/** A video surface showing a `VideoPlayer`'s output — embeddable in a screen AND\n * fullscreen-presentable (`open()`), with seamless promotion between the two. */\nexport interface UIVideo extends UIElementBase<UIVideoStyle, DrawableStyle & BaseStyle> {\n readonly type: \"video\";\n /** The player driving this surface (playback control lives on it). */\n player: VideoPlayer;\n /** Show fullscreen as the current destination. Promotion: if this video is mounted in a screen,\n * the SAME native player moves fullscreen — playback uninterrupted; a pop moves it back. */\n open(options?: PresentOptions): void;\n /** Dismiss if this is the visible destination. */\n close(): void;\n /** Became the visible destination. */\n onOpen(callback: () => void): this;\n /** Stopped being the visible destination. */\n onClose(callback: () => void): this;\n /** Hardware/system back while current. */\n onBackPressed(callback: () => void): this;\n}\n/** Create a video node showing `player`'s output. */\nexport declare function UIVideo(player: VideoPlayer): UIVideo;\n/** @deprecated Style as the first argument is legacy — use chained `.style({...})`. */\nexport declare function UIVideo(style: UIVideoStyle, player: VideoPlayer): UIVideo;\n","types/ui/UIVirtualizedList.d.ts":"import { Element, type Color, type DrawableStyle, type ElementStyle, type UIElementBase, type UINodeChild } from \"./UINode\";\nexport type UIVirtualizedListStyle = DrawableStyle & ElementStyle & {\n /** Tint of the native pull-to-refresh spinner (pairs with `onRefresh`). */\n refreshControlColor?: Color;\n /** Same key and semantics as UIScrollable's; `\"none\"` keeps a chat composer's keyboard up no\n * matter how the history is scrolled. */\n keyboardDismissMode?: \"interactive\" | \"scroll\" | \"none\";\n};\nexport interface VListConfig<T> {\n /** Stable unique key of an item. */\n keyOf: (item: T) => string;\n /** Subtree factory — called when the item enters the window; the subtree lives until it\n * leaves. */\n render: (item: T) => UINodeChild;\n /** Height estimate (px) used before the first measurement — a number, or a per-item function\n * (chat: `msg => 40 + Math.ceil(msg.text.length / 35) * 20`). Computed once when the item is\n * added. */\n estimatedHeight: number | ((item: T) => number);\n /** Extra px around the viewport kept mounted. Default: one viewport height. */\n overscan?: number;\n /** Chat mode: the first layout starts scrolled to the end, and appends auto-scroll while the\n * list sits at the bottom. */\n inverted?: boolean;\n}\n/** A windowed (virtualized) list: only the items near the viewport are mounted — for long feeds\n * and chats. Items are keyed; feed it via `setData`/`append`/`prepend`. */\nexport interface UIVirtualizedList<T = unknown> extends UIElementBase<UIVirtualizedListStyle> {\n readonly type: \"vlist\";\n /** Replace the data wholesale — vanished keys are unmounted by the host's window sync. */\n setData(items: T[]): this;\n /** Append items to the end (auto-scrolls when `inverted` and resting at the bottom). */\n append(...items: T[]): this;\n /** Insert at the start WITHOUT a scroll jump (the host compensates the offset). */\n prepend(...items: T[]): this;\n /** Update items with the same keys: mounted ones re-render; the cached height persists until\n * re-measured. */\n update(...items: T[]): this;\n /** Remove items by key. */\n removeByKey(...keys: string[]): this;\n /** Number of data items (mounted or not). */\n readonly itemCount: number;\n /** The data item under `key`, if any. */\n getItem(key: string): T | undefined;\n /** Scroll to `offset` px. */\n scrollTo(offset: number, animated?: boolean): void;\n /** Scroll to the item with `key`. */\n scrollToKey(key: string, animated?: boolean): void;\n /** Scroll to the end of the content. */\n scrollToEnd(animated?: boolean): void;\n /** Scroll position changed (px from the start edge). */\n onScroll(callback: (scrollPosition: number) => void): this;\n /** Pull-to-refresh: the spinner stays until the returned promise settles. Attach BEFORE the\n * node mounts (hosts read it at creation). Native hosts only — no-op on web. */\n onRefresh(callback: () => void | Promise<void>): this;\n /** Fires within `thresholdPx` of the content's bottom edge — once, re-armed after leaving the\n * edge (host-side latch). Infinite-scroll loading. */\n onEndReached(thresholdPx: number, callback: () => void): this;\n /** Same, for the top edge — chat history loading. */\n onStartReached(thresholdPx: number, callback: () => void): this;\n}\nexport declare class VListElement<T> extends Element<\"vlist\"> implements UIVirtualizedList<T> {\n _overscan: number;\n _inverted: boolean;\n _keys: string[];\n _estimates: number[];\n _endThreshold: number;\n _startThreshold: number;\n protected sl: ((scrollPosition: number) => void)[];\n protected erl: (() => void)[];\n protected strl: (() => void)[];\n private items;\n private mounted;\n private keyOf;\n private renderItem;\n private estimate;\n constructor(config: VListConfig<T>);\n private get isAttached();\n private register;\n setData(items: T[]): this;\n append(...items: T[]): this;\n prepend(...items: T[]): this;\n update(...items: T[]): this;\n removeByKey(...keys: string[]): this;\n get itemCount(): number;\n getItem(key: string): T | undefined;\n scrollTo(offset: number, animated?: boolean): void;\n scrollToKey(key: string, animated?: boolean): void;\n scrollToEnd(animated?: boolean): void;\n onScroll(callback: (scrollPosition: number) => void): this;\n _refreshCallback: any;\n onRefresh(callback: () => void | Promise<void>): this;\n onEndReached(thresholdPx: number, callback: () => void): this;\n onStartReached(thresholdPx: number, callback: () => void): this;\n}\n/** Create a virtualized list from a config (`keyOf` + `render` + `estimatedHeight` required),\n * then feed it via `setData`/`append`/`prepend`. Give it a size (`flexGrow: 1` as a screen body). */\nexport declare function UIVirtualizedList<T>(config: VListConfig<T>): UIVirtualizedList<T>;\n","types/ui/UIWidget.d.ts":"import { TouchStartEvent } from \"../runtime/touch\";\nimport { Presentable } from \"./presentable\";\nimport { ContainerElement, type BaseStyle, type Color, type ContainerStyle, type DrawableStyle, type PaddingStyle, type PositionStyle, type UIChildArg, type UIContainerBase, type UINodeChild, type ChildrenFn } from \"./UINode\";\nexport type UIWidgetStyle = ContainerStyle & DrawableStyle & PaddingStyle & BaseStyle & PositionStyle & {\n /** A layer behind the widget that intercepts clicks — `\"transparent\"` still intercepts, `null`\n * removes the layer. A tap on it fires `onOverlayTap`. */\n overlayColor?: Color | null;\n};\n/** A floating overlay — absolutely positioned in device coordinates, mounted above the page as\n * its own layout root (never a child of what's underneath). The base of dialogs, toasts,\n * mini-players and scene HUDs; `UIModal`/`UIPopover`/`UIBottomSheet` build on it. */\nexport interface UIWidget extends UIContainerBase<UIWidgetStyle, DrawableStyle & BaseStyle & {\n overlayColor?: Color | null;\n}> {\n readonly type: \"widget\";\n /**\n * Attach this widget to a destination (a `Scene`, a `UIScreen`, …): the widget lives on that\n * page's layer — it shows/hides with the page and rides its transition, and a screen pushed\n * on top covers it (a scene HUD behaves like part of the scene). Sticky until `attachTo(null)`\n * (= back to a global overlay). Set it while the widget is hidden. The widget is always its own\n * overlay root mounted into the owner's page view — it never becomes a child of the owner, so it\n * stays topmost and its updates never trigger the owner's relayout. Works with a `UIScreen` that\n * is a page inside a `UIPager`: the widget mounts into that tab and rides its swipe. (Web shows\n * and hides it with the owner but does not yet ride the transition.)\n */\n attachTo(owner: Presentable | null): this;\n /** Show the widget. By default it is a global overlay above every destination — it stays\n * visible across navigation until `hide()` (dialogs, mini-player, global loader). If the\n * widget was attached via `attachTo(owner)`, it mounts on that page's layer instead and is\n * only visible while the owner is presented. */\n show(): void;\n /** Unmount the widget. */\n hide(): void;\n /** Mounted right now (`show()` ran, `hide()` hasn't). */\n readonly isShow: boolean;\n /** Touch began on the widget; `ev.track(...)` takes over the rest of the gesture. */\n onTouchStart(callback: (ev: TouchStartEvent<UIWidget>) => void): this;\n /** Tap on the overlay layer (requires an `overlayColor`). */\n onOverlayTap(callback: () => void): this;\n /** Hardware/system back while the widget is shown. */\n onBackPressed(callback: () => void): this;\n}\nexport declare class WidgetElement extends ContainerElement<\"widget\"> {\n scrollable: false;\n _owner?: Presentable;\n constructor(type: \"widget\", style: UIWidgetStyle, children: UINodeChild[] | ChildrenFn);\n attachTo(owner: Presentable | null): this;\n show(): void;\n hide(): void;\n get isShow(): boolean;\n _interactive: boolean;\n readonly touchStartListeners: any[];\n onTouchStart(callback: any): this;\n _emitTouchStart(pointerId: number, clientX: number, clientY: number): any;\n readonly otl: (() => void)[];\n onOverlayTap(callback: () => void): this;\n _backButtonCallback?: () => void;\n onBackPressed(callback: any): this;\n}\n/** Create a widget (same argument forms as `UIColumn`). Position it with absolute-style props\n * (`top`/`left`/`bottom`/`right`), then `show()`/`hide()`. */\nexport declare function UIWidget(...children: UIChildArg[]): UIWidget;\nexport declare function UIWidget(children: UINodeChild[] | ChildrenFn): UIWidget;\n/** @deprecated Style as the first argument is legacy — use chained `.style({...})`. */\nexport declare function UIWidget(style: UIWidgetStyle, children?: UINodeChild[] | ChildrenFn): UIWidget;\n"}