lecodes-cli 0.17.2 → 0.18.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. package/README.md +1 -1
  2. package/dist/index.js +2376 -755
  3. package/package.json +4 -4
  4. package/runtime/scene-harness.json +1 -1
  5. package/runtime/sdk/compile/aspectMacro.ts +52 -8
  6. package/runtime/sdk/compile/assetMacro.ts +116 -15
  7. package/runtime/sdk/compile/bundler.ts +39 -4
  8. package/runtime/sdk/compile/compileProject.ts +16 -1
  9. package/runtime/sdk/compile/header.ts +6 -1
  10. package/runtime/sdk/compile/index.ts +31 -0
  11. package/runtime/sdk/compile/liteMaterial.ts +247 -0
  12. package/runtime/sdk/compile/sceneEditor.ts +11 -1
  13. package/runtime/sdk/compile/shaderSchema.ts +202 -0
  14. package/runtime/sdk/compile/shaderTargets.ts +81 -0
  15. package/runtime/sdk/core/Aspect.ts +363 -95
  16. package/runtime/sdk/core/compWrite.ts +42 -0
  17. package/runtime/sdk/core/fields.ts +1 -1
  18. package/runtime/sdk/core/time.ts +81 -0
  19. package/runtime/sdk/g2/Camera2D.ts +8 -1
  20. package/runtime/sdk/g2/CharacterController2D.ts +253 -53
  21. package/runtime/sdk/g2/Node2D.ts +80 -10
  22. package/runtime/sdk/g2/OneWay2D.ts +66 -0
  23. package/runtime/sdk/g2/Physics2D.ts +240 -30
  24. package/runtime/sdk/g2/Scene2D.ts +33 -1
  25. package/runtime/sdk/g2/Shape2D.ts +218 -22
  26. package/runtime/sdk/g2/Trigger2D.ts +42 -12
  27. package/runtime/sdk/g2/groups2d.ts +106 -0
  28. package/runtime/sdk/g2/loop.ts +15 -4
  29. package/runtime/sdk/gl/Camera.ts +41 -0
  30. package/runtime/sdk/gl/CameraPlace.ts +52 -0
  31. package/runtime/sdk/gl/CharacterController.ts +184 -55
  32. package/runtime/sdk/gl/Gearbox.ts +212 -0
  33. package/runtime/sdk/gl/Geometry.ts +70 -9
  34. package/runtime/sdk/gl/IK.ts +193 -174
  35. package/runtime/sdk/gl/Light.ts +64 -2
  36. package/runtime/sdk/gl/Lightmap.ts +179 -0
  37. package/runtime/sdk/gl/Material.ts +36 -0
  38. package/runtime/sdk/gl/Mesh.ts +6 -23
  39. package/runtime/sdk/gl/Model.ts +23 -8
  40. package/runtime/sdk/gl/Node.ts +350 -285
  41. package/runtime/sdk/gl/Physics.ts +222 -126
  42. package/runtime/sdk/gl/Scene.ts +175 -8
  43. package/runtime/sdk/gl/Shape.ts +255 -12
  44. package/runtime/sdk/gl/Trigger.ts +1 -6
  45. package/runtime/sdk/gl/Vehicle.ts +473 -0
  46. package/runtime/sdk/gl/Wheel.ts +240 -0
  47. package/runtime/sdk/gl/{AnimationClip.ts → animation/AnimationClip.ts} +37 -7
  48. package/runtime/sdk/gl/animation/Animator.ts +87 -0
  49. package/runtime/sdk/gl/animation/Layer.ts +29 -0
  50. package/runtime/sdk/gl/animation/Loop.ts +25 -0
  51. package/runtime/sdk/gl/animation/Playback.ts +43 -0
  52. package/runtime/sdk/gl/animation/core.ts +294 -0
  53. package/runtime/sdk/gl/scenarios.ts +291 -349
  54. package/runtime/sdk/inject.ts +186 -162
  55. package/runtime/sdk/runtime/app.ts +13 -0
  56. package/runtime/sdk/runtime/input.ts +169 -6
  57. package/runtime/sdk/scene/defineScene.ts +1227 -1016
  58. package/runtime/sdk/scene/gizmos.ts +148 -0
  59. package/runtime/sdk/scene/material.ts +188 -0
  60. package/runtime/sdk-types.json +1 -1
  61. package/runtime/sdk/gl/Animator.ts +0 -642
  62. package/runtime/sdk/gl/ModelAnimation.ts +0 -95
@@ -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\"\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 InstancedMesh: typeof SDK.InstancedMesh\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 InstanceTransform = SDK.InstanceTransform\n type InstancedMesh = SDK.InstancedMesh\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/InstancedMesh.d.ts":"import { Mat4, type Mat4Like } from \"../math/mat4\";\nimport { type QuatLike } from \"../math/quat\";\nimport { type Vec3Like } from \"../math/vec\";\nimport type { Geometry } from \"./Geometry\";\nimport { Material } from \"./Material\";\nimport type { MeshOptions } from \"./Mesh\";\nimport { Node } from \"./Node\";\n/** One instance's placement, local to the InstancedMesh node. Omitted fields mean identity. */\nexport type InstanceTransform = {\n position?: Vec3Like;\n /** Quaternion; wins over `eulerAngles`. */\n rotation?: QuatLike;\n /** Degrees (YXZ), like `Node.eulerAngles`. */\n eulerAngles?: Vec3Like;\n scale?: Vec3Like | number;\n};\nexport declare class InstancedMesh extends Node {\n /** Instance capacity, fixed at construction. Unset instances are hidden. */\n readonly count: number;\n private _geometry;\n private _material;\n private _data;\n private _lo;\n private _hi;\n constructor(geometry: Geometry, count: number, options?: MeshOptions);\n get geometry(): Geometry;\n get material(): Material;\n set material(m: Material);\n /** Shadow flags for all instances (both at once — the engine sets them per draw). */\n setShadows(cast: boolean, receive?: boolean): this;\n private _touch;\n /** Place instance `i`. Pending until `commit()`. */\n setAt(i: number, t: InstanceTransform): this;\n /** Place instance `i` from a 4×4 column-major matrix (local to this node). */\n setMatrixAt(i: number, m: Mat4Like): this;\n /** Hide instance `i` (a zero matrix — no geometry is emitted for it). */\n hideAt(i: number): this;\n /** Bulk write: `matrices` holds 16 floats per instance, starting at instance `offset`. */\n setMatrices(matrices: ArrayLike<number>, offset?: number): this;\n /** The 4×4 of instance `i` as stored (a copy). */\n matrixAt(i: number): Mat4;\n /** Upload every change since the last commit (one bridge call covering the dirty range). */\n commit(): this;\n /** Whether edits are waiting for `commit()`. */\n get dirty(): boolean;\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 /** (`render` quad / stretch) a second sheet on the same grid, ADDED as `emissiveMap × emissiveColor`\n * — keyed by `map`'s alpha, not tinted by the particle colour. A fireball = a smoke `map` whose\n * colour curve goes dark + a fire `emissiveMap` that keeps glowing while alpha lasts. */\n emissiveMap?: Texture | null;\n /** Multiplier for `emissiveMap`; an `[r, g, b]` array may exceed 1 (HDR glow). Default 0 (off). */\n emissiveColor?: ColorInput;\n /** (`render` quad / stretch) crossfade each flipbook frame into the next by the fractional frame\n * index instead of snapping — smooth sheet playback at any frame rate. Default false. */\n frameBlend?: boolean;\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 * Same rule the Animator binds clips with: exact name first, then the part after the last `:` / `|`\n * (Mixamo `mixamorig:Hips` matches `Hips`); a skinned joint beats a plain node of the same name.\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 type { Geometry } from \"./Geometry\";\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} | {});\n/** Where particles are born, in emitter space. Sphere / hemisphere / cone have an axis of +Y (the\n * hemisphere is the +Y half, the cone opens along +Y from its base disc at `center`) — aim the\n * node with `lookAt(target, 'y')`. `thickness` 0 emits from the surface only, 1 (default) from the\n * whole volume. A sphere or cone also sets the LAUNCH DIRECTION (outward / from the cone's apex)\n * when `startVelocity` gives a speed but no direction, like Unity's shapes. */\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} | {\n type: \"sphere\";\n center?: Vec3Like;\n radius: number;\n thickness?: number;\n} | {\n type: \"hemisphere\";\n center?: Vec3Like;\n radius: number;\n thickness?: number;\n} | {\n type: \"cone\";\n center?: Vec3Like;\n radius: number; /** half-angle, radians */\n angle?: number; /** emit this far up the axis too */\n length?: number;\n thickness?: number;\n};\n/** Extra velocity over each particle's life — evaluated from the curves every frame and ADDED as a\n * displacement (not accumulated like `acceleration`): `radial` pushes outward along the particle's\n * birth direction (a burst that decays: `curve(4).to(0)`), `x`/`y`/`z` drift in the simulation\n * space (rising smoke: `y: curve(2).from(0).to(1)`). Unity's velocityOverLifetime. */\nexport type VelocityOverLife = {\n radial?: ParticleValue;\n x?: ParticleValue;\n y?: ParticleValue;\n z?: ParticleValue;\n};\ntype Noise = {\n strength?: number;\n frequency?: number;\n speed?: number;\n};\n/** Ground plane for bouncing particles (all render modes). `height` is in the simulation space:\n * world y with `space: 'world'`, emitter-local y otherwise. */\nexport type ParticleGround = {\n /** Plane height (default 0). */\n height?: number;\n /** Contact radius — particles stop `radius` above the plane (a mesh's half-extent; default 0). */\n radius?: number;\n /** Fraction of the vertical speed kept on impact, 0..1 (default 0.3). */\n bounce?: number;\n /** Tangential damping while in contact, per second — like `drag` (default 8). */\n friction?: number;\n};\nexport type ParticlesOptions = ParticlesMaterialOptions & {\n /** Draw every particle as this mesh — lit, tumbling 3D debris (shell casings, rubble, leaves,\n * shrapnel) in one draw call. The system switches to the mesh render mode; the default\n * material becomes `Material.lit()` (pass `material` for color/roughness/metallic — the\n * sprite look options are ignored). `size` scales the mesh (default 1); `rotation`/`opacity`/\n * `frame` don't apply. See `angularVelocity` and `ground`. */\n mesh?: Geometry;\n /** (mesh) Spin, radians per second about the particle's own axes — a vector, or a per-component\n * `{ min, max }` range randomized at spawn. Particles are born in the emitter's orientation. */\n angularVelocity?: Vec3Like | {\n min: Vec3Like;\n max: Vec3Like;\n };\n /** A ground plane the particles bounce on and come to rest on (any render mode); `null`\n * disables it. */\n ground?: ParticleGround | null;\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 /** Draw order among blended systems at the same depth — higher draws later, i.e. on top (Unity's\n * sortingOrder). Systems are depth-sorted by their node, so the emitters of one effect tie and\n * without this the engine picks who covers whom per frame (smoke popping over a fireball).\n * Default 0; a fireball wants 2, its smoke 1, a smoke trail -1. */\n order?: number;\n shape?: Shape;\n /** Extra velocity over life (radial burst that decays, axis drift) — see `VelocityOverLife`. */\n velocityOverLife?: VelocityOverLife;\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 order(val: number);\n set velocityOverLife(v: VelocityOverLife);\n set shape(shape: Shape);\n /** (mesh mode) Replace the particle mesh; live particles keep flying as the new shape. */\n set mesh(g: Geometry);\n set angularVelocity(v: Vec3Like | {\n min: Vec3Like;\n max: Vec3Like;\n });\n set ground(g: ParticleGround | null);\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 /** Tone mapping operator. `'aces'` (default, filament's ACES legacy) desaturates bright colours\n * towards white — HDR fire reads pale; `'neutral'` (Khronos PBR Neutral) keeps hue and\n * saturation until very bright; `'linear'` clips each channel (what an engine without a\n * tonemapper shows — saturated, Unity-without-post-processing look); `'filmic'` (Uncharted). */\n toneMapping?: \"aces\" | \"neutral\" | \"linear\" | \"filmic\";\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 /** The node's own triangles (a Mesh's geometry or a Model's GLB, world scale applied).\n * `true` = exact triangle mesh — static/kinematic bodies, triggers, characters' ground and picking\n * only (a dynamic body can't be a triangle mesh; Physics throws). `'convex'` = convex hull of the\n * vertices, works for dynamic bodies too. A Model uses its bind pose (skinned parts skipped). */\n mesh?: boolean | \"convex\";\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 private _buildMesh;\n private _buildAutoBox;\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 { InstancedMesh } from \"./gl/InstancedMesh\";\nexport type { InstanceTransform } from \"./gl/InstancedMesh\";\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"}
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 CameraPlace: typeof SDK.CameraPlace\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 Gearbox: typeof SDK.Gearbox\n const Geolocation: typeof SDK.Geolocation\n const Geometry: typeof SDK.Geometry\n const Gizmos: typeof SDK.Gizmos\n const IK: typeof SDK.IK\n const Input: typeof SDK.Input\n const InputChannel: typeof SDK.InputChannel\n const InspectorUI: typeof SDK.InspectorUI\n const InstancedMesh: typeof SDK.InstancedMesh\n const Layer: typeof SDK.Layer\n const Light: typeof SDK.Light\n const Lightmap: typeof SDK.Lightmap\n const LongPressEvent: typeof SDK.LongPressEvent\n const LookAt: typeof SDK.LookAt\n const Loop: typeof SDK.Loop\n const Mat4: typeof SDK.Mat4\n const Material: typeof SDK.Material\n const MaterialHandle: typeof SDK.MaterialHandle\n const Mathf: typeof SDK.Mathf\n const Mesh: typeof SDK.Mesh\n const Model: typeof SDK.Model\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 OneWay2D: typeof SDK.OneWay2D\n const Particles: typeof SDK.Particles\n const Physics: typeof SDK.Physics\n const Physics2D: typeof SDK.Physics2D\n const PhysicsGroup2D: typeof SDK.PhysicsGroup2D\n const Plane: typeof SDK.Plane\n const PlayAnimation: typeof SDK.PlayAnimation\n const Playback: typeof SDK.Playback\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 System: typeof SDK.System\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 Time: typeof SDK.Time\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 Vehicle: typeof SDK.Vehicle\n const VideoPlayer: typeof SDK.VideoPlayer\n const WebSocket: typeof SDK.WebSocket\n const Wheel: typeof SDK.Wheel\n const __GizmoBuffer: typeof SDK.__GizmoBuffer\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 __applyEditorPose: typeof SDK.__applyEditorPose\n const __applyMaterialParam: typeof SDK.__applyMaterialParam\n const __assignMaterialDef: typeof SDK.__assignMaterialDef\n const __channel: typeof SDK.__channel\n const __compOp: typeof SDK.__compOp\n const __compWrite: typeof SDK.__compWrite\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 __withGizmoScope: typeof SDK.__withGizmoScope\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 defineMaterial: typeof SDK.defineMaterial\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 AeroConfig = SDK.AeroConfig\n type AnimationClip = SDK.AnimationClip\n type Animator = SDK.Animator\n type AppState = SDK.AppState\n type Aspect<K extends string, P = Node, E extends EventMap = {}> = SDK.Aspect<K, P, E>\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 BlendPosition = SDK.BlendPosition\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 CameraPlace = SDK.CameraPlace\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 CompAxis = SDK.CompAxis\n type CompWriter = SDK.CompWriter\n type Computed<T> = SDK.Computed<T>\n type DateInput = SDK.DateInput\n type DateValue = SDK.DateValue\n type DifferentialMode = SDK.DifferentialMode\n type DriveLayout = SDK.DriveLayout\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 EngineConfig = SDK.EngineConfig\n type EventMap = SDK.EventMap\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 GamepadAxisName = SDK.GamepadAxisName\n type GamepadState = SDK.GamepadState\n type Gearbox = SDK.Gearbox\n type GeoOptions = SDK.GeoOptions\n type GeoPosition = SDK.GeoPosition\n type GeoWatch = SDK.GeoWatch\n type Geometry = SDK.Geometry\n type GizmoAnchor = SDK.GizmoAnchor\n type GizmoStyle = SDK.GizmoStyle\n type HapticStyle = SDK.HapticStyle\n type IKLookAt = SDK.IKLookAt\n type IKTwoBone = SDK.IKTwoBone\n type InputEventName = SDK.InputEventName\n type InputGamepadEvent = SDK.InputGamepadEvent\n type InputKeyEvent = SDK.InputKeyEvent\n type InspectorUI = SDK.InspectorUI\n type InstanceTransform = SDK.InstanceTransform\n type InstancedMesh = SDK.InstancedMesh\n type Layer = SDK.Layer\n type LayerOptions = SDK.LayerOptions\n type Light = SDK.Light\n type LightDef = SDK.LightDef\n type Lightmap = SDK.Lightmap\n type LitMaterialDef = SDK.LitMaterialDef\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 Loop = SDK.Loop\n type LoopDef = SDK.LoopDef\n type LoopOptions = SDK.LoopOptions\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 MaterialData = SDK.MaterialData\n type MaterialDef = SDK.MaterialDef\n type MaterialHandle = SDK.MaterialHandle\n type MaterialParamValue = SDK.MaterialParamValue\n type Mesh = SDK.Mesh\n type MeshDef = SDK.MeshDef\n type Model = SDK.Model\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 OneWay2D = SDK.OneWay2D\n type OrientationLock = SDK.OrientationLock\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 PhysicsGroup2D = SDK.PhysicsGroup2D\n type Plane = SDK.Plane\n type PlayAnimation = SDK.PlayAnimation\n type PlayOptions = SDK.PlayOptions\n type Playback = SDK.Playback\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 SceneInstance<D extends SceneDef> = SDK.SceneInstance<D>\n type SceneNodeDef = SDK.SceneNodeDef\n type Service = SDK.Service\n type ShaderMaterialDef = SDK.ShaderMaterialDef\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 SteeringConfig = SDK.SteeringConfig\n type StopOptions = SDK.StopOptions\n type System<K extends string, S extends SystemHost = Scene, E extends EventMap = {}> = SDK.System<K, S, E>\n type SystemHost = SDK.SystemHost\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 TireCurve = SDK.TireCurve\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 UnlitMaterialDef = SDK.UnlitMaterialDef\n type VRScene = SDK.VRScene\n type Vec2 = SDK.Vec2\n type Vec3 = SDK.Vec3\n type Vehicle = SDK.Vehicle\n type VideoPlayer = SDK.VideoPlayer\n type WebSocket = SDK.WebSocket\n type Wheel = SDK.Wheel\n type WheelSuspension = SDK.WheelSuspension\n type WheelTire = SDK.WheelTire\n type WheelVisual = SDK.WheelVisual\n type With<N, A extends Aspect<any, any, any>> = SDK.With<N, A>\n type __GizmoBuffer = SDK.__GizmoBuffer\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. The file must exist — a path that resolves to nothing fails the compile\n * (`asset not found: ./hero.png (main.ts:3)`); there is no runtime fallback. Calls inside\n * comments and string literals are text, not macros. */\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 type { Scene } from \"../gl/Scene\";\nimport { 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, any>> = abstract new () => A;\n/** The accessor name carried in the aspect's generic. */\nexport type KeyOf<A> = A extends Aspect<infer K, any, any> ? K : never;\n/** The node kind an aspect targets (the scene kind for a System). */\nexport type TargetOf<A> = A extends Aspect<any, infer P, any> ? P : never;\n/** `{ name: Aspect }` — the field an aspect contributes to its node. */\nexport type FieldOf<A extends Aspect<any, 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, 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, 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, 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, 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, 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 * `E` = the events this aspect emits (`{ explode: (b: Barrel) => void }`): `this.emit('explode', …)`\n * inside, `node.barrel.on('explode', fn)` outside.\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, E extends EventMap = {}> {\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 /** Tick AFTER these classes within the same phase (`static after = [Controls]`). A constraint\n * always beats the numeric `updateOrder`. Classes absent from the phase are ignored. */\n static after?: Function[];\n /** Tick BEFORE these classes within the same phase (`static before = [Camera]`). */\n static before?: Function[];\n /** Every live instance of an aspect/system class, in attach order — the registry a game used to\n * hand-roll as `static all[]`. Live, read-only: copy it (`[...Aspect.all(Barrel)]`) before a loop\n * that detaches. Empty in the scene editor (aspects are inert data there). */\n static all<A extends Aspect<any, any, any>>(ctor: AspectCtor<A>): readonly A[];\n /** The node this aspect is attached to (set at attach time). For a System: the scene. */\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 readonly version: number;\n };\n /**\n * GENERATOR aspects attached through a scene file: the `Scene` the host node was built into —\n * what `handle.instantiate({ scene })` / `scene.add()` need inside `rebuild()`. Set by the scene\n * loader (edit AND play mode); undefined for aspects attached by hand. 3D only (2D aspects own\n * their `scene` field). For a System: always set — the scene it is attached to.\n */\n readonly scene: P extends Node ? Scene : P extends SystemHost ? P : unknown;\n protected readonly __key__?: K;\n protected readonly __events__?: E;\n private _listeners?;\n /** The node (or scene) is set — initialize here, not in a constructor. */\n protected onAttach?(): void;\n /** Release what onAttach acquired. */\n protected onDetach?(): void;\n /** Called after `node.aspect(Ctor, opts)` re-assigns options on an ALREADY attached aspect (a\n * pre-attached one like `model.anim`): rebuild whatever was derived from the options at attach. */\n protected onReconfigure?(): 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 * LATE phase — every frame while attached, after the physics step + transform sync + animators,\n * right before the frame draws: reads of `node.worldPosition` are the final drawn position\n * (cameras/followers have no 1-frame lag) and what you write to a plain node is what this frame\n * shows. The default home for game logic. `dt` = GAME seconds since the last frame (`Time.scale`\n * applied; 0 while paused — see `updateWhilePaused`).\n */\n protected update?(dt: number): void;\n /**\n * EARLY phase — every frame BEFORE the physics step, so what you feed the simulation (velocity,\n * `controller.move()`, forces, kinematic transforms) is consumed by this same frame's step: zero\n * input latency. Use it only when you FEED the simulation. Reads here see last frame's settled\n * state. A class rarely needs both phases — that is two aspects on one node.\n */\n protected updateBefore?(dt: number): void;\n /** Tick order within a phase and rank — ascending; default 0, ties keep attach order. A declared\n * `static after` / `static before` constraint always beats this number. Read once, at attach —\n * set it as a class field. */\n protected updateOrder: number;\n /** Keep ticking while `Time.paused` (a HUD fade, the pause menu). `dt` is still 0 then — read\n * `Time.unscaledDt` for wall-clock motion. Checked every frame; may be toggled at any time. */\n protected updateWhilePaused: boolean;\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 protected updateWhenVisible: boolean;\n /** Listen to one of this aspect's events. Chainable. Cleared on detach. */\n on<C extends keyof E & string>(channel: C, callback: E[C]): this;\n /** Remove a listener added with `on` (same function reference). */\n off<C extends keyof E & string>(channel: C, callback: E[C]): this;\n /** Fire one of this aspect's events. Protected: only the aspect itself emits. */\n protected emit<C extends keyof E & string>(channel: C, ...args: Parameters<E[C]>): void;\n}\n/**\n * An aspect of a SCENE: game logic with no single node to live on — input mapping, the FX pools, the\n * HUD, the game mode. Same lifecycle (`onAttach`/`onDetach`), same two phases (`updateBefore` /\n * `update`), same ordering (`updateOrder`, `static after`) and events as a node aspect; `this.scene` is the\n * scene it was attached to. `S` = the scene kind (`Scene` by default, `Scene2D` for 2D games).\n *\n * class Hud extends System<'hud'> {\n * static after = [Player]\n * update(dt: number) { … }\n * }\n * scene.system(Hud) // attach\n * scene.hud // the typed accessor\n */\nexport declare abstract class System<K extends string, S extends SystemHost = Scene, E extends EventMap = {}> extends Aspect<K, S, E> {\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/compWrite.d.ts":"export type CompAxis = \"x\" | \"y\" | \"z\" | \"w\";\n/** Implemented by a class whose vector getters accept component writes (see above). The class also\n * carries `static _comps: string[]` naming those getters — compile-time data, absent at runtime. */\nexport interface CompWriter {\n _writeComp(prop: string, axis: CompAxis, value: number): void;\n}\n/** `<o>.<prop>.<axis> = value`, routed to the owner when it has the hook. Returns the value. */\nexport declare const __compWrite: (o: any, prop: string, axis: CompAxis, value: number) => number;\n/** `<o>.<prop>.<axis> op= v` — `op`: 0 `+=`, 1 `-=`, 2 `*=`, 3 `/=`. The current component is read\n * through the normal getter (one fresh vector), the result written like `__compWrite`. */\nexport declare const __compOp: (o: any, prop: string, axis: CompAxis, op: number, v: number) => number;\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/core/time.d.ts":"declare class TimeClock {\n private _scale;\n private _paused;\n /** Seconds of GAME time since the app started (scaled; stops while paused). */\n now: number;\n /** Seconds of wall-clock time since the app started (never stops). */\n unscaledNow: number;\n /** This frame's delta in game seconds — what `update(dt)` receives. 0 while paused. */\n dt: number;\n /** This frame's wall-clock delta in seconds (the host's frame time, clamped by the engine). */\n unscaledDt: number;\n /** Frames dispatched since the app started (counts paused frames too). */\n frame: number;\n /** Speed of the game relative to wall-clock: 1 normal, 0.5 half speed, 2 double. Applied to\n * `dt`, `now` AND the engines' physics / animation / particle clocks. Negative or NaN → 0. */\n get scale(): number;\n set scale(v: number);\n /** Freeze the game: `dt` reads 0, aspects without `updateWhilePaused` are skipped, the engines'\n * simulations stop. `scale` is remembered and restored on resume. */\n get paused(): boolean;\n set paused(v: boolean);\n /** The scale the engines currently run at (0 while paused). */\n get effectiveScale(): number;\n private _push;\n}\n/** The game clock — scale / pause the whole game, read `dt` / `now` anywhere. */\nexport declare const Time: TimeClock;\nexport {};\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\";\nimport type { CompAxis, CompWriter } from \"../core/compWrite\";\nexport declare class Camera2D implements CompWriter {\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 _writeComp(_prop: string, axis: CompAxis, v: number): void;\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 { FieldMeta } from \"../core/fields\";\nimport { Vec2, type Vec2Like } from \"../math/vec\";\nimport type { CompWriter } from \"../core/compWrite\";\nimport { PhysicsGroup2D } from \"./groups2d\";\nimport { type Node2D } from \"./Node2D\";\n/** Where the character's feet are, as reported by the solver after the last step. */\nexport type GroundState2D = \"ground\" | \"slope\" | \"air\";\n/** One surface the mover pushed out of this step. `normal` points back at the character. */\nexport type Collision2D = {\n node: Node2D | null;\n normal: Vec2;\n};\nexport declare class CharacterController2D extends Aspect<\"controller\", Node2D> implements CompWriter {\n static readonly aspect = \"controller\";\n static fields: FieldMeta<CharacterController2D>;\n private _id;\n private _gravityScale;\n private _maxSlope;\n private _group;\n private _dropThrough;\n private _repush;\n onAttach(): void;\n onDetach(): void;\n /** Native character id (0 until attached / no physics support). */\n get id(): number;\n /**\n * This frame's movement command, in world units/s — NOT normalized, NOT a per-frame displacement\n * (that is what Unity's `Move` takes; passing `v * dt` here gives a character 60× too slow).\n *\n * ONE component = horizontal, the everyday platformer call. TWO = the whole velocity, for free mode\n * (`gravityScale = 0`); with gravity on, a two-component call fights the ballistic vertical and the\n * character hangs in the air, so that combination warns once.\n *\n * Sticky only within the frame: the command expires once the engine consumes it. It also **takes the\n * axis back from a latched `velocity`** — commanding is claiming ownership, which is what keeps the\n * two horizontal sources from ever fighting.\n */\n move(x: number): void;\n move(x: number, y: number): void;\n move(v: Vec2Like): void;\n private _warnFree;\n /** Vertical velocity (world units/s) — LATCHED: gravity works on it, you seed it. `= 700` to jump,\n * `+= 300` to stack an explosion on top of the current motion. No ground check: guard it yourself\n * with `grounded` (or don't, for a double jump). Does nothing in free mode. `velocity.y = 700` is\n * the same channel — pick whichever reads better. */\n get velocityY(): number;\n set velocityY(v: number);\n /**\n * READ — the velocity the solver ended up with after the most recent step (world units/s, fresh\n * Vec2): what HAPPENED, not what you asked for. Walking into a wall reads ~0, sliding along one\n * reads the tangent.\n *\n * WRITE — LATCH the whole velocity: a knockback, a wall jump, a launch pad. Unlike `move()` it does\n * not expire, so the character keeps flying, and gravity still pulls the vertical down into a real\n * ballistic arc. It stays until `move()` takes the axis back — so a game simply doesn't call\n * `move()` while the throw lasts, and ends it on its own terms:\n *\n * hero.controller.velocity = [dir.x * 600, 400] // hit by the blast\n * if (thrown) { if (hero.controller.grounded) thrown = false } // landing ends it\n * else hero.controller.move(ix * SPEED) // …and this reclaims the axis\n *\n * Nothing clears the latch by itself, landing included — a kinematic controller has no friction.\n * Reading is not the inverse of writing: against a wall the read is ~0 and would cancel the throw.\n *\n * `c.velocity.y = 700` (the direct spelling) is a jump — the compiler routes it to the exact\n * `velocityY` channel via `_writeComp` below — and `c.velocity.x = 300` latches the whole vector\n * with the measured vertical filling in. A STORED copy is still a copy (`const v = c.velocity`).\n */\n get velocity(): Vec2;\n set velocity(v: Vec2Like);\n /** Compile-time list (chisel reads it, then strips it) — see CharacterController / core/compWrite.ts. */\n static _comps: string[];\n /** True while standing on walkable ground. */\n get grounded(): boolean;\n /** Where the feet are after the last step: walkable ground, too-steep ground, or the air. */\n get groundState(): GroundState2D;\n /** The surface normal under the feet — for orienting a sprite to a slope, or deciding a slide. */\n get groundNormal(): Vec2;\n /** What the character is standing on: a moving platform, a hazard, an ice patch whose `friction`\n * the game can read. The engine already carries the character along a kinematic platform. */\n get groundNode(): Node2D | null;\n /**\n * Every surface the mover pushed out of during the last step, with the normal pointing back at the\n * character. This is what wall jumps and box pushing are written against — a kinematic mover is not\n * a body, so those contacts do not arrive as 'enter' events.\n *\n * const wall = c.collisions.find(h => Math.abs(h.normal.x) > 0.7)\n * if (wall && jumpPressed) c.velocity = [-wall.normal.x * KICK, JUMP]\n *\n * for (const h of c.collisions) h.node?.physics?.applyImpulse([-h.normal.x * PUSH, 0])\n */\n get collisions(): Collision2D[];\n /** Multiplier over the world gravity; default 1. **0 = free mode**: no gravity, no ground, no\n * stick-to-floor — a swimmer, a drone, a ladder climber, or a top-down hero, driven by the\n * two-component `move()`. */\n get gravityScale(): number;\n set gravityScale(v: number);\n /** Max ground slope (degrees) the character treats as walkable; default 45. Live. */\n get maxSlope(): number;\n set maxSlope(v: number);\n /** Which collision group the character belongs to. Live. */\n get group(): PhysicsGroup2D | undefined;\n set group(g: PhysicsGroup2D | undefined);\n /**\n * While this names a node, that node's `OneWay2D` surfaces are not solid for this character — how\n * you drop off a semisolid platform. A plain latch: whoever sets it clears it.\n *\n * if (downPressed && jumpPressed && c.grounded) {\n * const platform = c.groundNode\n * c.dropThrough = platform\n * setTimeout(() => { if (c.dropThrough === platform) c.dropThrough = null }, 200)\n * }\n *\n * Because it names ONE node, the timeout is not delicate: too long merely means you could have\n * re-landed on that platform for a moment, and the platform below stays solid either way.\n */\n get dropThrough(): Node2D | null;\n set dropThrough(n: Node2D | null);\n /**\n * True while a requested collider resize hasn't taken — you asked to stand up and there is something\n * overhead. Resizing goes through the `Shape2D` aspect itself:\n *\n * hero.aspect(Shape2D, { capsule: CROUCHED }) // always fits — you are shrinking\n * hero.aspect(Shape2D, { capsule: STANDING }) // may be refused under a low ceiling\n * if (hero.controller.resizing) … // still crouched; call it again next frame\n *\n * A refusal changes nothing, so the retry is just the same call again — and it is an exact headroom\n * test against the real capsule, unlike a hand-rolled raycast (a ray is a line; a capsule has\n * girth). The FEET stay planted across a resize, so the character neither hovers nor sinks.\n */\n get resizing(): boolean;\n private _state;\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/groups2d.d.ts":"/** Collides with everything. */\nexport declare const ALL_GROUPS = 4294967295;\nexport declare class PhysicsGroup2D {\n /** The single category bit this group owns. */\n readonly bit: number;\n /** Optional debug label, so an inspector says \"bullets\" rather than \"group #3\". */\n readonly label: string;\n private _ignored;\n /**\n * Stop colliding with these groups — symmetric, so naming it on one side is enough. Safe to call\n * after bodies exist: their filters are re-pushed.\n */\n ignore(...groups: PhysicsGroup2D[]): this;\n /** Members of this group don't collide with EACH OTHER — bullets, debris, a ragdoll's own bones. */\n ignoreSelf(): this;\n}\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 type { CompAxis, CompWriter } from \"../core/compWrite\";\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 (the other node, plus where and how hard). The\n * contact's `normal` points AWAY from the other node, so `normal.y > 0.7` reads as \"I landed on\n * top of it\". Sensor overlaps and `exit` carry zeros. */\n enter: (other: Node2D, contact: Contact2D) => void;\n exit: (other: Node2D, contact: Contact2D) => 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/** Where a contact happened, delivered as the second argument of 'enter'. `speed` is the approach\n * speed at impact (world units/s) — scale an impact sound with it. Zeros on sensor and 'exit'\n * events, which have no manifold. */\nexport type Contact2D = {\n point: Vec2;\n normal: Vec2;\n speed: number;\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> implements CompWriter {\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 _pushXf;\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 _writeComp(_prop: string, axis: CompAxis, v: number): void;\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/OneWay2D.d.ts":"import { Aspect } from \"../core/Aspect\";\nimport { type Vec2Like } from \"../math/vec\";\nimport type { Node2D } from \"./Node2D\";\nexport declare class OneWay2D extends Aspect<\"oneWay\", Node2D> {\n static readonly aspect = \"oneWay\";\n private _normal;\n private _arc;\n private _enabled;\n /** Which side is solid. Default `[0, 1]` — solid from above, i.e. a floor you pass through from\n * below. `[1, 0]` is a wall you can only enter from the left. */\n get normal(): Vec2Like;\n set normal(v: Vec2Like);\n /** How far off `normal` an approach still counts as coming from the solid side, in degrees.\n * Default 90 — the whole half-plane, which is what a platform wants. */\n get arc(): number;\n set arc(v: number);\n /** Turn the one-way behaviour off, making the surface solid from both sides again. */\n get enabled(): boolean;\n set enabled(v: boolean);\n onAttach(): void;\n onDetach(): void;\n onReconfigure(): void;\n private _push;\n}\n","types/g2/Physics2D.d.ts":"import { Aspect } from \"../core/Aspect\";\nimport { Vec2, type Vec2Like } from \"../math/vec\";\nimport { type Node2D } from \"./Node2D\";\nimport { PhysicsGroup2D } from \"./groups2d\";\nexport type MotionType = \"static\" | \"kinematic\" | \"dynamic\";\n/** A neutral solid surface. Deliberately the same default as 3D `Physics.friction`. */\nexport declare const DEFAULT_FRICTION = 0.6;\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 * Only applies before the world exists (it is a global solver tolerance). */\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 private _motion;\n /** Static (walls, floors), kinematic (script-driven platforms), or dynamic (fully simulated).\n * Default \"dynamic\", and LIVE: freeze a crate into `'static'`, hand a ragdoll to `'dynamic'`. */\n get motion(): MotionType;\n set motion(m: MotionType);\n /** Lock rotation (essential for platformer characters). */\n fixedRotation: boolean;\n /** Continuous collision for fast-moving bodies (projectiles). */\n bullet: boolean;\n private _mass;\n private _friction;\n private _bounce;\n private _gravityScale;\n private _linearDamping;\n private _angularDamping;\n private _group;\n private _repush;\n private _h;\n /** Which collision group this body belongs to (see Physics2D.addGroup). Live. */\n get group(): PhysicsGroup2D | undefined;\n set group(g: PhysicsGroup2D | undefined);\n /** Mass in world units. Omitted (or 0) = derived from the collider's AREA, so a big crate really is\n * heavier than a small one. Setting it scales the shape-derived mass data, keeping the rotational\n * inertia in the same ratio — a lopsided collider still tips the way its geometry says. */\n get mass(): number;\n set mass(v: number);\n /** Surface friction. 0 is frictionless, ~1 grippy; two bodies COMBINE as sqrt(a×b), so the lower\n * value wins the argument. Default 0.6 — a neutral solid, matching 3D. */\n get friction(): number;\n set friction(v: number);\n /** Bounciness, 0..1 — the fraction of the approach speed returned on impact. Two bodies combine as\n * MAX (the bouncier one wins — the opposite of friction), and below ~64 units/s no bounce is\n * applied at all, which is what stops a ball jittering on the floor forever. */\n get bounce(): number;\n set bounce(v: number);\n private _pushMaterial;\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 /** Re-applying options (`node.aspect(Physics2D, {…})`) pushes the live ones through. */\n onReconfigure(): 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 get angularVelocity(): number;\n set angularVelocity(degPerSec: number);\n /** Per-body gravity multiplier: 1 = full world gravity, 0 = floats, <0 = repelled. */\n get gravityScale(): number;\n set gravityScale(scale: number);\n get linearDamping(): number;\n set linearDamping(d: number);\n get angularDamping(): number;\n set angularDamping(d: number);\n /** Pause this body — it stops simulating and stops colliding until re-enabled. */\n set enabled(v: boolean);\n /** Box2D puts resting bodies to sleep; wake one to make it react to a change you made by hand. */\n set awake(v: boolean);\n /** Apply an instantaneous impulse at the centre of mass (never spins the body) and wake it. */\n applyImpulse(v: Vec2Like): this;\n /** Apply an impulse at a WORLD point — the lever arm becomes spin. Use this when the push has a real\n * point of contact: a bullet's hit point, a blast pushing a prop at its base. */\n applyImpulseAt(v: Vec2Like, worldPoint: Vec2Like): this;\n /** Apply a continuous force (world units) and wake the body. */\n applyForce(v: Vec2Like): this;\n /** Set the world's gravity / solver settings. OPTIONAL: the world is created on the first body with\n * gravity [0, -980], 64 px/m and 4 sub-steps. Calling this later changes gravity LIVE and leaves\n * bodies alone. */\n static configure(config?: PhysicsConfig): void;\n /** World gravity, live. */\n static get gravity(): Vec2;\n static set gravity(g: Vec2Like);\n private static _gravity;\n /** Whether this build has physics support (CREATOR_2D_PHYSICS). NOTE: this reports the BUILD, not\n * the world — there is nothing else to guard, since the world creates itself. */\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 /**\n * Register a collision group. Groups are SUBTRACTIVE and SYMMETRIC (see groups2d.ts):\n *\n * const player = Physics2D.addGroup()\n * const bullets = Physics2D.addGroup().ignoreSelf().ignore(player)\n */\n static addGroup(label?: string): PhysicsGroup2D;\n /** The implicit group of every body that never named one - name it to exclude \"everything else\". */\n static get defaultGroup(): PhysicsGroup2D;\n /** Closest body hit by the segment, or null. `node` resolves the hit entity. */\n static raycast(from: Vec2Like, to: Vec2Like, q?: Query2D): RayHit | null;\n /** Every body along the segment, NEAREST FIRST - a piercing bullet, a laser, \"how many walls are\n * between us\". Capped at 32 hits. */\n static raycastAll(from: Vec2Like, to: Vec2Like, q?: Query2D): RayHit[];\n /** Topmost body (solid or sensor) whose shape contains the world point, or null. \"Topmost\" means\n * by DRAW order - layer, then z - so picking agrees with what the player sees. */\n static overlapPoint(p: Vec2Like, q?: Query2D): Node2D | null;\n /** Everything within `radius` of a point - an explosion, an aura, an aggro range. */\n static overlapCircle(centre: Vec2Like, radius: number, q?: Query2D): Node2D[];\n /** Everything inside an axis-aligned box (centre + HALF-extents) - a room, a camera bound. */\n static overlapBox(centre: Vec2Like, half: Vec2Like, q?: Query2D): Node2D[];\n /**\n * Everything touching a capsule from-to of the given radius. A capsule is the shape a DIRECTED\n * question has: a beam with width, a sword arc, \"does my radius fit through this gap\" - none of\n * which an axis-aligned box can express.\n *\n * It is also the SWEPT test: a circle of radius r moving from A to B during a frame sweeps exactly\n * this capsule, so a fast projectile checked this way cannot tunnel through a thin wall the way two\n * separate position checks do.\n */\n static overlapCapsule(from: Vec2Like, to: Vec2Like, radius: number, q?: Query2D): Node2D[];\n}\n/** Which groups a query may hit, and what to skip. */\nexport type Query2D = {\n /** Only hit bodies in these groups. Omitted = everything. */\n groups?: PhysicsGroup2D[];\n /** Skip these nodes - the \"don't hit myself\" case a ray fired from inside its own body needs. */\n ignore?: Node2D | Node2D[];\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 { type Aspect, type AspectCtor, type FieldOf, type TargetOf } from \"../core/Aspect\";\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 /** Attach (and configure) a system, or reconfigure it if already present. Returns the scene typed\n * as now-having it (`scene.system(Hud).hud`). A 3D `System<'x'>` (target Scene) is rejected here. */\n system<Self extends TargetOf<A>, A extends Aspect<any, any, any>>(this: Self, ctor: AspectCtor<A>, opts?: Partial<A>): Self & FieldOf<A>;\n /** Safe access — undefined if the system isn't attached. */\n get<A extends Aspect<any, any, any>>(ctor: AspectCtor<A>): A | undefined;\n /** Existence check AND type guard: inside `if (scene.has(Hud))`, `scene.hud` is present. */\n has<A extends Aspect<any, any, any>>(ctor: AspectCtor<A>): this is this & FieldOf<A>;\n /** Detach a system (runs its onDetach). Chainable. */\n removeSystem<A extends Aspect<any, any, any>>(ctor: AspectCtor<A>): 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) 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 — a CONCAVE outline silently\n * becomes its hull; use `chain` for those). */\n polygon?: Vec2Like[];\n /**\n * A polyline of connected segments — the one shape that expresses a long CONCAVE surface (rolling\n * terrain, a cave wall) in one piece, seam-free. Pass only the points that should be solid; the\n * tangent points Box2D needs at the ends are synthesised here.\n *\n * STATIC bodies only (a polyline has no area, so no mass), at least 2 points (4 with `loop`), and it\n * must not self-intersect. It is ONE-SIDED: solid on the right of the point order — walk the points\n * so that the solid material is on your right, or set `flip`.\n */\n chain?: Vec2Like[];\n /** `chain`: close the contour (an island / a room boundary). Needs at least 4 points. */\n loop?: boolean;\n /** `chain`: put the solid side on the other side of the line. */\n flip?: boolean;\n /** The collider's centre relative to the node, in world units. Applies to EVERY kind — it\n * translates a capsule's / segment's / polygon's / chain's points too, unlike the old `offset`. */\n origin?: Vec2Like;\n private _handle;\n onDetach(): void;\n /**\n * Re-configuring the aspect swaps the fixture in place — same body, same id, same velocity, same\n * position. Nothing happens when the geometry is unchanged, so re-applying the same options in a\n * loop is free.\n */\n onReconfigure(): void;\n private _create;\n /**\n * Box2D's chain wants the two TANGENT points as extra entries and does not collide on its first or\n * last edge — pass it your outline verbatim and you lose both end segments (four points give ONE).\n * So the caller passes only the solid points and the ends are extrapolated here: `p0 + (p0 - p1)`.\n * A loop needs none of that (every point is interior) but does need 4 of them.\n */\n private _createChain;\n private _signature;\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 { PhysicsGroup2D } from \"./groups2d\";\nimport type { Node2D } from \"./Node2D\";\nexport declare class Trigger2D extends Aspect<\"trigger\", Node2D> {\n static readonly aspect = \"trigger\";\n private _h;\n private _enabled;\n private _group;\n private _repush;\n /** Which collision group this zone belongs to. Live. */\n get group(): PhysicsGroup2D | undefined;\n set group(g: PhysicsGroup2D | undefined);\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 /** Switch the zone off and on — a spent pickup, a hitbox that is only live during a swing. */\n get enabled(): boolean;\n set enabled(v: boolean);\n}\n","types/gl/animation/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 /** Mark a moment of the clip (SECONDS from its start) with an event name: `kick.addEvent(0.4, 'hit')`\n * → `anim.on('hit', (clip, layer) => …)` fires when the playhead crosses it, loops included.\n * Events are part of the clip: every model playing it gets them; `slice()` keeps the ones inside\n * the range, re-timed. Chainable. */\n addEvent(time: number, name: string): this;\n private _pushEvents;\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/animation/Animator.d.ts":"import { Aspect } from \"../../core/Aspect\";\nimport type { Node } from \"../Node\";\nimport type { AnimationClip } from \"./AnimationClip\";\nimport { type ClipEventHandler, type LayerOptions, type LoopDef, type LoopOptions, type PlayOptions, type StopOptions } from \"./core\";\nimport type { Loop } from \"./Loop\";\nimport type { Layer } from \"./Layer\";\nimport type { Playback } from \"./Playback\";\nexport declare class Animator extends Aspect<\"anim\", Node> {\n static readonly aspect = \"anim\";\n private _c;\n private _rootMotion;\n onAttach(): void;\n onDetach(): void;\n /** The clip list, in order: the GLB's embedded clips (file order), then the clips you added. An\n * added clip with an embedded clip's name takes its place. */\n get clips(): readonly AnimationClip[];\n /** One clip by name, or by index into `clips` — e.g. to `slice()` it. `undefined` if there is none. */\n clip(ref: string | number): AnimationClip | undefined;\n /** Add a clip under a name (default: its own `name`) — from another file, procedural, or sliced.\n * Overrides an embedded clip of the same name. Chainable. */\n addClip(name: string | AnimationClip, clip?: AnimationClip): this;\n /** Play a one-shot on the base layer — by name, index, or the first clip with no argument.\n * Crossfades per the options (default: cut). Returns a Playback: `await` it — it resolves at the\n * clip's hand-over (`true`; `false` if cut short), and what you start right after is what the clip\n * fades into (another one-shot, `playLoop(next)`; nothing = back to the loop). */\n play(clip?: string | number, options?: PlayOptions): Playback;\n /** Set the base layer's LOOP — what it shows when no one-shot plays: a clip (`playLoop('Idle')`) or\n * a blend space (`playLoop({ Idle: 0, Run: 6 })`, drive the returned object's `value`). Crossfades\n * over `fade` from whatever plays — a one-shot included (it is cut short). `stop()` removes it. */\n playLoop(def: LoopDef, options?: LoopOptions): Loop | undefined;\n /** Fade everything out, on every layer (loops included) → rest pose. */\n stop(options?: StopOptions): this;\n /** The base layer's current loop (the object the last `playLoop()` returned), if any. */\n get loop(): Loop | undefined;\n /** A one-shot on the base layer hasn't handed over yet. */\n get busy(): boolean;\n /** A new layer on top (masked override / additive). The returned object is its handle. */\n addLayer(options?: LayerOptions): Layer;\n on(event: string, cb: ClipEventHandler): this;\n off(event: string, cb: ClipEventHandler): this;\n /** Global playback rate: 0.3 = slow-mo, 0 = pause. */\n get speed(): number;\n set speed(v: number);\n /** Root motion: the root bone's horizontal travel comes OFF the pose and moves the node instead —\n * or its CharacterController (on this node or an ancestor) as a velocity, so it collides. For\n * clips whose hips actually travel (Mixamo without \"In Place\", lunges, rolls). */\n get rootMotion(): boolean;\n set rootMotion(on: boolean);\n}\n","types/gl/animation/core.d.ts":"import { AnimationClip } from \"./AnimationClip\";\nimport { Loop } from \"./Loop\";\nimport { Layer } from \"./Layer\";\nimport { Playback } from \"./Playback\";\nimport type { Node } from \"../Node\";\n/** A position on a blend axis (1D) or plane (2D). */\nexport type BlendPosition = number | readonly [number, number];\nexport type PlayOptions = {\n /** Crossfade seconds for BOTH ends (default 0 = cut). */\n fade?: number;\n /** Fade-in seconds (overrides `fade`). */\n fadeIn?: number;\n /** One-shots: fade-back seconds at the END (overrides `fade`). The return fade starts this long\n * BEFORE the clip ends, while it still plays — no freeze-frame on the last pose. On a layer with\n * no blend to return to, giving `fadeOut` releases the layer at the end instead of holding the\n * last frame. */\n fadeOut?: number;\n /** Playback rate for this clip (default 1). */\n speed?: number;\n /** Rewind even if the clip is already playing (default: rewind only if it isn't). */\n restart?: boolean;\n};\nexport type StopOptions = {\n fade?: number;\n};\nexport type LoopOptions = {\n /** Crossfade seconds from whatever the layer shows — the previous loop, or a one-shot still playing\n * (default 0 = cut). */\n fade?: number;\n /** Playback rate of the loop's clips (default 1). */\n speed?: number;\n};\n/** What a layer loops: one clip (name / index), or a blend space `{ name: position }`. */\nexport type LoopDef = string | number | Record<string, BlendPosition>;\nexport type LayerOptions = {\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). */\n weight?: number;\n};\nexport type ClipEventHandler = (clip: string, layer: Layer) => void;\nexport type SlotRec = {\n name: string;\n clip: AnimationClip;\n slot: number;\n layer: LayerRec;\n inBlend: boolean;\n playback?: PlaybackRec;\n};\nexport type PlaybackRec = {\n slot: SlotRec;\n playing: boolean;\n done: Promise<boolean>;\n resolve: (natural: boolean) => void;\n};\nexport type LayerRec = {\n index: number;\n view: Layer;\n slots: SlotRec[];\n byName: Map<string, SlotRec>;\n loop?: LoopRec;\n weight: number;\n mask: string;\n additive: boolean;\n};\nexport type LoopRec = {\n layer: LayerRec;\n members: {\n name: string;\n slot: SlotRec;\n }[];\n value: BlendPosition;\n view: Loop;\n dead: boolean;\n};\nexport declare class Core {\n id: number;\n /** Added clips by name (`addClip`) — the lookup index; an added name overrides an embedded one. */\n readonly table: Map<string, AnimationClip>;\n readonly layers: LayerRec[];\n speed: number;\n private _embedded?;\n private readonly _added;\n private _list?;\n private readonly _listeners;\n readonly node: Node;\n constructor(node: Node);\n embedded(): AnimationClip[];\n /** The ordered clip list: the GLB's clips in file order (an added clip of the same name takes the\n * embedded one's place), then the remaining added clips in insertion order. Cached until addClip. */\n clips(): AnimationClip[];\n addClip(name: string, clip: AnimationClip): void;\n /** A clip by name (added first, then embedded), or by index into `clips()` (none = the first). */\n resolveClip(ref: string | number | undefined): [string, AnimationClip] | undefined;\n private clipNames;\n /** Create the native animator on demand. False = nothing to animate (warned). */\n ensure(): boolean;\n destroy(): void;\n newLayer(options?: LayerOptions): LayerRec;\n addLayer(options: LayerOptions): Layer;\n pushLayer(L: LayerRec): void;\n /** Bind a clip on a layer (once per name). */\n slotFor(L: LayerRec, name: string, clip: AnimationClip): SlotRec | undefined;\n play(L: LayerRec, ref: string | number | undefined, o: PlayOptions): Playback;\n /** A one-shot on the layer hasn't handed over yet. */\n busy(L: LayerRec): boolean;\n settle(p: PlaybackRec, natural: boolean): void;\n stopSlot(s: SlotRec, fade: number): void;\n stopLayer(L: LayerRec, fade: number): void;\n stopAll(fade: number): void;\n loop(L: LayerRec, def: LoopDef, o: LoopOptions): Loop | undefined;\n setLoopValue(b: LoopRec, v: BlendPosition): void;\n slotWeight(s: SlotRec): number;\n slotTime(s: SlotRec): number;\n seek(s: SlotRec, time: number): void;\n setSpeed(v: number): void;\n setRootMotion(on: boolean): void;\n on(event: string, cb: ClipEventHandler): void;\n off(event: string, cb: ClipEventHandler): void;\n /** Native slot event: 0 completed / 1 loop / 2 settled (faded to 0) / 3 hand-over / 4+i clip event i. */\n private onEvent;\n}\n","types/gl/animation/Layer.d.ts":"import type { LoopDef, LoopOptions, PlayOptions, StopOptions } from \"./core\";\nimport type { Loop } from \"./Loop\";\nimport type { Playback } from \"./Playback\";\nexport declare class Layer {\n private readonly _r;\n private readonly _c;\n /** Play a one-shot on this layer (crossfading per the options); resolves at its hand-over. */\n play(clip?: string | number, options?: PlayOptions): Playback;\n /** Set / transition this layer's loop (a clip, or a blend space) — crossfades over `fade` from whatever\n * the layer shows, a one-shot included (it is cut short). */\n playLoop(def: LoopDef, options?: LoopOptions): Loop | undefined;\n /** Fade everything on this layer out — one-shots and its loop. */\n stop(options?: StopOptions): this;\n /** This layer's current loop (the object the last `playLoop()` returned), if any. */\n get loop(): Loop | undefined;\n /** Layer contribution 0–1. */\n get weight(): number;\n set weight(v: number);\n /** A one-shot on this layer hasn't handed over yet. */\n get busy(): boolean;\n}\n","types/gl/animation/Loop.d.ts":"import type { BlendPosition } from \"./core\";\nexport declare class Loop {\n private readonly _r;\n private readonly _c;\n /** Position on the axis (number) or plane (`[x, y]`) — units are whatever the positions use. Live\n * even while a one-shot plays (the loop returns at the new mix). */\n get value(): BlendPosition;\n set value(v: BlendPosition);\n /** Each member's current contribution, 0–1 (fades included). */\n get weights(): Record<string, number>;\n}\n","types/gl/animation/Playback.d.ts":"import type { AnimationClip } from \"./AnimationClip\";\nimport type { StopOptions } from \"./core\";\nimport type { Layer } from \"./Layer\";\nexport declare class Playback implements PromiseLike<boolean> {\n private readonly _r;\n private readonly _c;\n /** The clip that plays. */\n get clip(): AnimationClip;\n /** The layer it plays on. */\n get layer(): Layer;\n /** Clock (s). */\n get time(): number;\n /** 0–1 through the clip (the current cycle, when looping). */\n get progress(): number;\n /** Not handed over yet (the clip still owns the layer). */\n get playing(): boolean;\n /** Current contribution to the pose, 0–1 — moves during crossfades. */\n get weight(): number;\n /** Resolves at the hand-over (`true`) or when cut short (`false`) — the promise `await playback`\n * uses; the one to return from async functions or put in `Promise.all`. */\n get done(): Promise<boolean>;\n then<A = boolean, B = never>(onFulfilled?: ((v: boolean) => A | PromiseLike<A>) | null, onRejected?: ((e: unknown) => B | PromiseLike<B>) | null): Promise<A | B>;\n /** Move the clock (s). */\n seek(time: number): this;\n /** Cut this clip short: fade it out (the layer's loop returns if nothing else is coming in). */\n stop(options?: StopOptions): 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 private _following;\n /** The node the camera currently follows (`follow()`), or null. */\n get following(): Node | null;\n /**\n * Make the camera ride a node: every late frame the camera takes the node's WORLD pose (−Z =\n * view direction), so movement aspects / animation on that node are camera moves — dolly shots,\n * a cutscene path, a `CameraPlace` in a scene file. A node carrying a `CameraPlace` also hands\n * over its projection (fov / near / far). `follow(null)` releases the camera where it is.\n * One camera per scene: following a new node stops following the previous one.\n */\n follow(target: Node | {\n node: Node;\n applyTo(camera: Camera): void;\n } | null): this;\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/CameraPlace.d.ts":"import { Aspect } from \"../core/Aspect\";\nimport type { FieldMeta } from \"../core/fields\";\nimport type { Camera } from \"./Camera\";\nimport type { Node } from \"./Node\";\nexport declare class CameraPlace extends Aspect<\"cameraPlace\", Node> {\n static readonly aspect = \"cameraPlace\";\n /** Vertical field of view in degrees (default 60) — smaller is a longer lens. */\n fov: number;\n /** Near clip distance. */\n near: number;\n /** Far clip distance = view range. */\n far: number;\n /** The place that drives `scene.camera` when the file declaring it RUNS. Exactly one per file;\n * ignored inside prefabs / instantiated subtrees (the host scene owns its camera). */\n active: boolean;\n /** Aspect ratio of the frustum gizmo only (the real aspect is the viewport's). */\n static fields: FieldMeta<CameraPlace>;\n static editor: {\n rebuild: boolean;\n };\n /** Copy this place's projection onto a camera (`camera.follow(place)` does it for you). */\n applyTo(camera: Camera): void;\n /** Edit mode: the frustum marker (−Z = view), anchored on the node so it follows drags live and\n * clicking it selects the node. Play mode never calls this. */\n rebuild(): void;\n}\n","types/gl/CharacterController.d.ts":"import { Aspect } from \"../core/Aspect\";\nimport type { FieldMeta } from \"../core/fields\";\nimport { Vec3, type Vec2Like, type Vec3Like } from \"../math/vec\";\nimport type { CompWriter } from \"../core/compWrite\";\nimport type { Node } from \"./Node\";\n/** Where the character's feet are, as reported by the solver after the last step. */\nexport type GroundState = \"ground\" | \"slope\" | \"unsupported\" | \"air\";\nexport declare class CharacterController extends Aspect<\"controller\", Node> implements CompWriter {\n static readonly aspect = \"controller\";\n static fields: FieldMeta<CharacterController>;\n private _charId;\n private _gravityScale;\n private _maxSlope;\n onAttach(): void;\n onDetach(): void;\n /** Native character id (0 until attached / no physics support). */\n get id(): number;\n /**\n * This frame's movement command, in world units/s — NOT normalized, NOT a per-frame displacement\n * (that is what Unity's `Move` takes; passing `v * dt` here gives a character 60× too slow).\n *\n * Two components = horizontal `(x, z)`, the everyday call. Three = the whole velocity, for free mode\n * (`gravityScale = 0`); with gravity on, the vertical component fights the ballistic one and the\n * character barely falls, so that combination warns.\n *\n * Sticky only within the frame: the command expires once the engine consumes it. It also **takes the\n * axis back from a latched `velocity`** — commanding is claiming ownership, which is what keeps the\n * two horizontal sources from ever fighting.\n */\n move(x: number, z: number): void;\n move(v: Vec2Like | Vec3Like): void;\n /** Vertical velocity (world units/s) — LATCHED: gravity works on it, you seed it. `= 7` to jump,\n * `+= 3` to stack an explosion on top of the current motion. No ground check: guard it yourself\n * with `grounded` (or don't, for a double jump). Overridden every frame by a 3-component `move()`.\n * `velocity.y = 7` is the same channel — pick whichever reads better. */\n get velocityY(): number;\n set velocityY(v: number);\n /** Multiplier over the world gravity (`Physics.configure({ gravity })`); default 2, for the snappier\n * fall games want. **0 = free mode**: no gravity, no stick-to-floor, no stair stepping — a swimmer\n * or a drone, driven by the 3-component `move()`. */\n get gravityScale(): number;\n set gravityScale(v: number);\n /** Max ground slope (degrees) the character treats as walkable; default 45. Live. */\n get maxSlope(): number;\n set maxSlope(v: number);\n /**\n * True while a requested collider resize hasn't taken — you asked to stand up and there is something\n * overhead. Resizing goes through the `Shape` aspect itself:\n *\n * hero.aspect(Shape, { capsule: CROUCHED }) // always fits — you are shrinking\n * hero.aspect(Shape, { capsule: STANDING }) // may be refused under a low ceiling\n * if (hero.controller.resizing) … // still crouched; call it again next frame\n *\n * A refusal changes nothing, so the retry is just the same call again — and it is an exact headroom\n * test against the real capsule, unlike a hand-rolled raycast (a ray is a line; a capsule has girth).\n * The FEET stay planted across a resize, so the character neither hovers nor sinks.\n */\n get resizing(): boolean;\n /** True while standing on walkable ground. */\n get grounded(): boolean;\n /** Where the feet are after the last step: on walkable ground, on too-steep ground, touching\n * something that can't support it, or in the air. */\n get groundState(): GroundState;\n /**\n * READ — the velocity the solver ended up with after the most recent step (world units/s, fresh\n * Vec3): what HAPPENED, not what you asked for. Walking into a wall reads ~0, sliding along one\n * reads the tangent. Unlike Unity's synchronous `Move`, our step runs later in the frame, so a read\n * is up to one frame old — irrelevant for animation speed, fall damage or \"am I blocked\", which is\n * what it is for. (Exact wall contact would need a contact normal; the engine has none yet.)\n *\n * WRITE — LATCH the whole velocity: a knockback, a wall jump, a launch pad. Unlike `move()` it does\n * not expire, so the character keeps flying, and gravity still pulls the vertical down into a real\n * ballistic arc. It stays until `move()` takes the axis back — so a game simply doesn't call\n * `move()` while the throw lasts, and ends it on its own terms:\n *\n * hero.controller.velocity = [dir.x * 12, 6, dir.z * 12] // hit by the blast\n * // …in the loop:\n * if (thrown) { if (hero.controller.grounded) thrown = false } // landing ends it\n * else hero.controller.move(ix * SPEED, iz * SPEED) // …and this reclaims the axis\n *\n * Note nothing clears the latch by itself, landing included — so a thrown character that never gets\n * a `move()` keeps sliding along the ground (a kinematic controller has no friction).\n *\n * Reading is not the inverse of writing: `c.velocity = c.velocity` is NOT a no-op, because the read\n * reports the measured result (against a wall it is ~0 and would cancel the throw). In flight the\n * two agree closely, so read-modify-write mid-air behaves as expected.\n *\n * `c.velocity.y = 7` (the direct spelling) is a jump — the compiler routes it to the exact\n * `velocityY` channel via `_writeComp` below, no vector allocated — and `c.velocity.x = 3` latches\n * the whole vector with the measured velocity filling in the other two, i.e. the read-modify-write\n * above spelled naturally. A STORED copy is still a copy: `const v = c.velocity; v.y = 7` does nothing.\n */\n get velocity(): Vec3;\n set velocity(v: Vec3Like);\n /** Compile-time list (chisel reads it, then strips it): the getters whose `c.<getter>.<axis> = v`\n * spelling is routed to `_writeComp` below. See core/compWrite.ts. */\n static _comps: string[];\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/Gearbox.d.ts":"import { Aspect } from \"../core/Aspect\";\nimport type { FieldMeta } from \"../core/fields\";\nimport type { Node } from \"./Node\";\nimport type { Vehicle } from \"./Vehicle\";\nexport declare class Gearbox extends Aspect<\"gearbox\", Node> {\n static readonly aspect = \"gearbox\";\n /** Forward gear ratios, first gear first. Engine RPM = wheel speed × ratio × the differential. */\n ratios: number[];\n /** Reverse ratio — negative, because a ratio's SIGN is what reverse means to the engine. */\n reverse: number;\n /** Shift up when the engine passes this fraction of its redline. */\n shiftUp: number;\n /** Shift down when it falls below this fraction. */\n shiftDown: number;\n /** How long a shift takes, in seconds — the clutch is out for this long. */\n shiftTime: number;\n /** How long the clutch takes to re-engage afterwards. */\n clutchTime: number;\n /** How long to wait after a shift before another is allowed — without it a car sitting on a\n * threshold hunts between two gears. */\n latency: number;\n /** How far the clutch bites the instant drive is asked for from rest, 0..1. It only has to COUPLE\n * the shafts — how much torque that passes is the engine's business, so a feathered throttle\n * still pulls away gently at the same bite point. */\n bite: number;\n static fields: FieldMeta<Gearbox>;\n /** Current gear: −1 reverse, 0 neutral, 1… forward. Read it for a HUD. */\n gear: number;\n /** True while a shift is in progress — the clutch is out and the engine is not driving the wheels. */\n get shifting(): boolean;\n private _shiftLeft;\n private _engageLeft;\n private _waitLeft;\n private _take;\n /** EARLY phase: the pair has to be latched before this frame's step consumes it. */\n updateBefore(dt: number): void;\n /**\n * The driver's left foot: where the clutch pedal is, ignoring shifts. Returns the new engagement.\n *\n * A driver does not compute anything. They watch the tacho: **revs sinking to idle means the\n * wheels are about to drag the engine under, and that is when you push the clutch in.** That\n * single test replaces every ratio and threshold — the crossover it finds is the exact speed where\n * engine braking stops and the engine would start PUSHING instead, and it finds it per gear\n * without being told the gear.\n *\n * The pedal comes back UP only for the throttle. Healthy revs are not on their own a reason to\n * engage: a car standing still shows healthy revs too — the wheels simply are not turning to say\n * otherwise — and a clutch dropped on that evidence lurches the car off with no throttle at all.\n *\n * Three things fall out of it for free:\n *\n * - **A braked car stops.** The engine cannot stall, so a clutch left in at 0 km/h feeds idle\n * torque to the wheels forever and the car creeps against its own brakes. Here the revs pin at\n * idle, so the pedal goes down and the brakes have nothing to fight.\n * - **Reverse is not a special case.** No ratio takes part, so it needs no separate number — which\n * is exactly why a fixed road-speed threshold got reverse wrong.\n * - **Hill starts judder instead of stalling.** Let the pedal out, the load pulls the revs down,\n * the rule pushes it straight back in, and the clutch sits slipping at the bite point until the\n * car moves. So the test deliberately ignores the throttle — gating it on \"no throttle\" would\n * stall the car under load. Throttle only holds the floor at `bite`.\n *\n * The cost is honest and small: once the pedal is down the revs sit at idle and cannot rise on\n * their own, so **coasting downhill gives no engine braking until you touch the throttle** — which\n * is precisely what a car with the clutch in does. Slipping it permanently to keep listening would\n * bring the creep straight back.\n */\n protected takeUp(v: Vehicle, dt: number): number;\n /**\n * Which gear the car should be in. The default is an ordinary automatic: pull away from neutral in\n * the direction of the throttle, shift up past `shiftUp` of the redline and down below `shiftDown`,\n * and refuse to shift again for `latency` seconds. Override this and nothing else.\n */\n select(v: Vehicle): number;\n /** Change gear now, with the clutch envelope. Safe to call from `select()` or from game code\n * (a sequential manual is `if (Input.key('KeyE')) car.gearbox.shift(car.gearbox.gear + 1)`). */\n shift(gear: number): void;\n /** The ratio the engine should be running: 0 in neutral, negative in reverse. */\n get ratio(): number;\n /**\n * The clutch scalar 0..1 the engine is given: the SHIFT envelope (out during a shift, ramping back\n * over `clutchTime`) times the driver's pedal (`takeUp`). Two independent reasons for the clutch\n * to be out, so they multiply: mid-shift is out however healthy the revs are, and an engine being\n * dragged to idle is out whatever gear it just picked.\n */\n get clutch(): number;\n}\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 /** Lightmap UV set (2 floats per vertex, non-overlapping, inside the unit square) — the\n * `Lightmap` atlas samples a Mesh through it. The box and cylinder builders fill it (their `uv`\n * tiles per face, which would fold every face onto the same texels); absent = the host reuses\n * `uv`, which is right for a plane. */\n uv1?: 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 /** A box; `size` (default 1) scales the vertices AND lays the lightmap chart out in proportion to\n * the faces' areas (a floor's top face gets the texels, not its 1 m side strips). */\n static box(size?: Vec3Like | number): 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 { Quat } from \"../math/quat\";\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 /** World rotation the END bone takes after the solve — a Node (its world rotation) or a Quat.\n * Unset = the end bone keeps its animated local rotation (a hand on a grip, a foot on a slope\n * want it set). Blended by `weight · rotationWeight`. */\n rotation?: Node | Quat;\n /** 0–1 contribution of `rotation` (on top of `weight`). */\n rotationWeight: number;\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/InstancedMesh.d.ts":"import { Mat4, type Mat4Like } from \"../math/mat4\";\nimport { type QuatLike } from \"../math/quat\";\nimport { type Vec3Like } from \"../math/vec\";\nimport type { Geometry } from \"./Geometry\";\nimport { Material } from \"./Material\";\nimport type { MeshOptions } from \"./Mesh\";\nimport { Node } from \"./Node\";\n/** One instance's placement, local to the InstancedMesh node. Omitted fields mean identity. */\nexport type InstanceTransform = {\n position?: Vec3Like;\n /** Quaternion; wins over `eulerAngles`. */\n rotation?: QuatLike;\n /** Degrees (YXZ), like `Node.eulerAngles`. */\n eulerAngles?: Vec3Like;\n scale?: Vec3Like | number;\n};\nexport declare class InstancedMesh extends Node {\n /** Instance capacity, fixed at construction. Unset instances are hidden. */\n readonly count: number;\n private _geometry;\n private _material;\n private _data;\n private _lo;\n private _hi;\n constructor(geometry: Geometry, count: number, options?: MeshOptions);\n get geometry(): Geometry;\n get material(): Material;\n set material(m: Material);\n /** Shadow flags for all instances (both at once — the engine sets them per draw). */\n setShadows(cast: boolean, receive?: boolean): this;\n private _touch;\n /** Place instance `i`. Pending until `commit()`. */\n setAt(i: number, t: InstanceTransform): this;\n /** Place instance `i` from a 4×4 column-major matrix (local to this node). */\n setMatrixAt(i: number, m: Mat4Like): this;\n /** Hide instance `i` (a zero matrix — no geometry is emitted for it). */\n hideAt(i: number): this;\n /** Bulk write: `matrices` holds 16 floats per instance, starting at instance `offset`. */\n setMatrices(matrices: ArrayLike<number>, offset?: number): this;\n /** The 4×4 of instance `i` as stored (a copy). */\n matrixAt(i: number): Mat4;\n /** Upload every change since the last commit (one bridge call covering the dirty range). */\n commit(): this;\n /** Whether edits are waiting for `commit()`. */\n get dirty(): boolean;\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 type PointOptions = {\n /**\n * Luminous POWER in lumens — the same physical scale as the sun's lux and `environmentIntensity`,\n * so a light keeps its look when the scene's exposure changes. A candle is ~12 lm, a bare 60 W\n * bulb ~800, a car headlight ~1500, a fireball millions. Default 1000.\n */\n intensity?: number;\n color?: ColorInput;\n /**\n * Metres of influence — past it the light contributes nothing. This is the performance knob:\n * overlapping point lights are the expensive case, so keep it as small as the look allows.\n * Default 10.\n */\n range?: number;\n /** Point-light shadows are a cubemap render per light; off by default. */\n castShadows?: boolean;\n};\nexport declare class Light extends Node {\n private _intensity;\n /** The most recently created sun — what `Lightmap.load` uses unless told otherwise. */\n static lastSun: Light | null;\n /** A directional sun light. */\n static sun(options?: SunOptions): Light;\n /**\n * A point light — a lamp, a muzzle flash, a fireball. Position it like any node.\n *\n * Feature-detected: hosts that predate it create the node and light nothing, which keeps a scene\n * that adds atmosphere on top of its sun renderable everywhere. Check `Light.supportsPoint`\n * before making one carry the scene.\n */\n static point(options?: PointOptions): Light;\n /** Whether this host can create point lights at all. */\n static get supportsPoint(): boolean;\n /** Live intensity (sun: lux, point: lumens) — animate a flash without rebuilding the light. */\n get intensity(): number;\n set intensity(value: number);\n set color(value: ColorInput);\n}\n","types/gl/Lightmap.d.ts":"import { Node } from \"./Node\";\nimport type { Scene } from \"./Scene\";\nexport type LightmapLoadOptions = {\n /** 1 = baked sun shadows at full strength, 0 = ambient occlusion only. Default 1. */\n sunStrength?: number;\n /** Multiplier on the ambient (IBL) share in the shadow math — how bright a fully shadowed texel\n * stays. 1 reproduces filament's own real-time shadow darkness (the shader reads the scene's sun\n * and IBL from filament's per-frame uniforms); raise it for lighter shadows, lower for deeper. Default 1. */\n ambientScale?: number;\n};\nexport type LightmapInfo = {\n size: number;\n texel: number;\n /** keys applied / keys in the file / registered statics without a rect */\n applied: number;\n total: number;\n missing: string[];\n};\nexport declare class Lightmap {\n /** True while `lecodes lightmap bake` runs the app — skip menus and build the scene straight away. */\n static get baking(): boolean;\n private static entries;\n private static ordinals;\n private static warned;\n /** Register static geometry — a Model, a Mesh, or any node whose subtree holds them. Statics are\n * both receivers and occluders in the bake. `key` names the entry in lightmap.bake (default:\n * the node's name + a running number, `container#3`); pass one when names are not stable. */\n static add(node: Node, key?: string): Node;\n private static next;\n /** Forget every registration (a scene rebuild). */\n static clear(): void;\n /** Apply a bake — or, under `lecodes lightmap bake`, run it. Resolves to null when nothing was\n * applied (no bake yet, a host without the feature, bake mode). */\n static load(scene: Scene, files: {\n data: string;\n texture: string;\n }, options?: LightmapLoadOptions): Promise<LightmapInfo | null>;\n /** A Mesh keeps its look (colour / map / roughness / metallic) but moves to the lightmap material. */\n private static swapMeshMaterial;\n private static bake;\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 /** (`render` quad / stretch) a second sheet on the same grid, ADDED as `emissiveMap × emissiveColor`\n * — keyed by `map`'s alpha, not tinted by the particle colour. A fireball = a smoke `map` whose\n * colour curve goes dark + a fire `emissiveMap` that keeps glowing while alpha lasts. */\n emissiveMap?: Texture | null;\n /** Multiplier for `emissiveMap`; an `[r, g, b]` array may exceed 1 (HDR glow). Default 0 (off). */\n emissiveColor?: ColorInput;\n /** (`render` quad / stretch) crossfade each flipbook frame into the next by the fractional frame\n * index instead of snapping — smooth sheet playback at any frame rate. Default false. */\n frameBlend?: boolean;\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 /** Soft particles: fade each sprite out over this many metres as it cuts into the scene geometry\n * behind it (Unity's \"Soft Particles Factor\"), so smoke and dust no longer slice through the\n * ground and walls with a hard edge. 0 = off (default). Reads the scene's depth buffer, which the\n * engine keeps bound while any soft system is on screen — the extra depth pass is only paid then.\n * Filament hosts (desktop / web / Android / Apple); web-lite draws such sprites unfaded. */\n depthFade?: number;\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 /** The lightmap material (docs/lightmap-plan.md): PBR base colour × a baked shadow/AO atlas on UV1.\n * Models take it through `Model.load(…, { lightmap: true })`; `Lightmap.load` builds one per static\n * Mesh. Parameters use gltfio's names (`baseColorFactor`, `baseColorMap`, `roughnessFactor`,\n * `metallicFactor`) plus `lightmap`, `lightmapST`, `ambientScale`, `sunStrength` (the sun / IBL terms come from\n * filament's per-frame uniforms inside the shader). */\n static lightmap(): Material;\n private static _lmTemplate;\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 constructor(geometry?: Geometry, material?: Material);\n get geometry(): Geometry | undefined;\n /** A Mesh always carries a material (slot 0) — see Node.setMaterial for the slot API. */\n get material(): Material;\n set material(m: Material);\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 { Animator } from \"./animation/Animator\";\nexport declare class Model extends Node {\n /** The model's Animator — always present, its clip table = the GLB's embedded clips. Configure\n * more (external clips, blend spaces, layers) with `model.aspect(Animator, {...})`. */\n readonly anim: Animator;\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 /** Load through the lightmap material so `Lightmap.load` can bind a baked atlas (the GLB needs\n * TEXCOORD_1 — `lecodes assets doctor --lightmap-uv`). Hosts without lightmap support ignore it. */\n lightmap?: boolean;\n }): Promise<Model>;\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 { Material } from \"./Material\";\nimport type { CompAxis, CompWriter } from \"../core/compWrite\";\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 /** 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> implements CompWriter {\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 _worldMatrix?;\n private _boneCache?;\n /** Materials assigned through setMaterial, by primitive slot (a Mesh fills slot 0 itself). */\n protected _materials?: Material[];\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 private _setOwnedPosition;\n private _setOwnedRotation;\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 _writeComp(_prop: string, axis: CompAxis, v: number): void;\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 /** The material assigned to slot 0 through this API (null before one is set — a GLB part's own\n * glTF material stays native-side). */\n get material(): Material | null;\n set material(m: Material);\n /** Replace the material of one primitive slot (`index` = the primitive's order in the glTF\n * mesh; a primitive-shape Mesh has one slot). */\n setMaterial(material: Material, index?: number): this;\n /** The material previously assigned to `index` (null when none was — see Mesh for the probe). */\n getMaterial(index?: number): Material | null;\n /** Find a descendant by name — bones of a loaded Model included (`hero.bone('RightHand').add(sword)`).\n * Same rule the Animator binds clips with: exact name first, then the part after the last `:` / `|`\n * (Mixamo `mixamorig:Hips` matches `Hips`); a skinned joint beats a plain node of the same name.\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 this node and its whole subtree. Every aspect in the subtree is detached first (its\n * `onDetach` runs: physics bodies released, updaters unregistered, listeners dropped) — native\n * `destroyEntity` frees the entity tree but knows nothing about JS-side aspects, and a destroyed\n * node's `update()` must not keep ticking. Deepest nodes go first, then this one. */\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 type { Geometry } from \"./Geometry\";\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} | {});\n/** Where particles are born, in emitter space. Sphere / hemisphere / cone have an axis of +Y (the\n * hemisphere is the +Y half, the cone opens along +Y from its base disc at `center`) — aim the\n * node with `lookAt(target, 'y')`. `thickness` 0 emits from the surface only, 1 (default) from the\n * whole volume. A sphere or cone also sets the LAUNCH DIRECTION (outward / from the cone's apex)\n * when `startVelocity` gives a speed but no direction, like Unity's shapes. */\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} | {\n type: \"sphere\";\n center?: Vec3Like;\n radius: number;\n thickness?: number;\n} | {\n type: \"hemisphere\";\n center?: Vec3Like;\n radius: number;\n thickness?: number;\n} | {\n type: \"cone\";\n center?: Vec3Like;\n radius: number; /** half-angle, radians */\n angle?: number; /** emit this far up the axis too */\n length?: number;\n thickness?: number;\n};\n/** Extra velocity over each particle's life — evaluated from the curves every frame and ADDED as a\n * displacement (not accumulated like `acceleration`): `radial` pushes outward along the particle's\n * birth direction (a burst that decays: `curve(4).to(0)`), `x`/`y`/`z` drift in the simulation\n * space (rising smoke: `y: curve(2).from(0).to(1)`). Unity's velocityOverLifetime. */\nexport type VelocityOverLife = {\n radial?: ParticleValue;\n x?: ParticleValue;\n y?: ParticleValue;\n z?: ParticleValue;\n};\ntype Noise = {\n strength?: number;\n frequency?: number;\n speed?: number;\n};\n/** Ground plane for bouncing particles (all render modes). `height` is in the simulation space:\n * world y with `space: 'world'`, emitter-local y otherwise. */\nexport type ParticleGround = {\n /** Plane height (default 0). */\n height?: number;\n /** Contact radius — particles stop `radius` above the plane (a mesh's half-extent; default 0). */\n radius?: number;\n /** Fraction of the vertical speed kept on impact, 0..1 (default 0.3). */\n bounce?: number;\n /** Tangential damping while in contact, per second — like `drag` (default 8). */\n friction?: number;\n};\nexport type ParticlesOptions = ParticlesMaterialOptions & {\n /** Draw every particle as this mesh — lit, tumbling 3D debris (shell casings, rubble, leaves,\n * shrapnel) in one draw call. The system switches to the mesh render mode; the default\n * material becomes `Material.lit()` (pass `material` for color/roughness/metallic — the\n * sprite look options are ignored). `size` scales the mesh (default 1); `rotation`/`opacity`/\n * `frame` don't apply. See `angularVelocity` and `ground`. */\n mesh?: Geometry;\n /** (mesh) Spin, radians per second about the particle's own axes — a vector, or a per-component\n * `{ min, max }` range randomized at spawn. Particles are born in the emitter's orientation. */\n angularVelocity?: Vec3Like | {\n min: Vec3Like;\n max: Vec3Like;\n };\n /** A ground plane the particles bounce on and come to rest on (any render mode); `null`\n * disables it. */\n ground?: ParticleGround | null;\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 /** Draw order among blended systems at the same depth — higher draws later, i.e. on top (Unity's\n * sortingOrder). Systems are depth-sorted by their node, so the emitters of one effect tie and\n * without this the engine picks who covers whom per frame (smoke popping over a fireball).\n * Default 0; a fireball wants 2, its smoke 1, a smoke trail -1. */\n order?: number;\n shape?: Shape;\n /** Extra velocity over life (radial burst that decays, axis drift) — see `VelocityOverLife`. */\n velocityOverLife?: VelocityOverLife;\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 order(val: number);\n set velocityOverLife(v: VelocityOverLife);\n set shape(shape: Shape);\n /** (mesh mode) Replace the particle mesh; live particles keep flying as the new shape. */\n set mesh(g: Geometry);\n set angularVelocity(v: Vec3Like | {\n min: Vec3Like;\n max: Vec3Like;\n });\n set ground(g: ParticleGround | null);\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 type { FieldMeta } from \"../core/fields\";\nimport type { CompAxis, CompWriter } from \"../core/compWrite\";\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}\n/**\n * What a body's friction already is the moment the host creates it. This is part of the ABI, not an\n * assumption: bridges.d.ts states it, so every host owes us this value. Knowing it lets attach skip\n * a bridge call per body whenever nobody named a surface.\n */\nexport declare const DEFAULT_FRICTION = 0.6;\nexport declare class Physics extends Aspect<\"physics\", Node> implements CompWriter {\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 /**\n * Surface friction: 0 = ice, ~1 = grippy asphalt, and values above 1 are allowed (rubber on\n * tarmac).\n *\n * The engine COMBINES the two touching bodies as `sqrt(a * b)`, so the LOWER value dominates and\n * the floor caps everything standing on it. The default **0.6** is a neutral solid surface (the\n * raw Jolt default of 0.2 is ice by game standards); dry tarmac a car should corner on wants a\n * `1`, ice `0.02`. A Vehicle's tires read the GROUND body's value, so this is the single number\n * that decides how well a car corners.\n *\n * Change it at runtime by re-configuring — `floor.aspect(Physics, { friction: 0.02 })` (an ice\n * patch) — or by assigning `floor.physics.friction = 0.02`; either way the setter pushes the new\n * surface to the live body at once. (chisel keeps an instance setter whose name appears as an\n * object-literal key anywhere in the bundle, so the config-object route survives tree-shaking\n * even when no code reads `.friction`.)\n */\n get friction(): number;\n set friction(v: number);\n private _friction;\n /** Scene-editor inspector: `motion` as a dropdown (a string default alone infers a text box). */\n static fields: FieldMeta<Physics>;\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; `velocity.y = 5` written directly on\n * the aspect is compiled to a component write — see `_writeComp`). */\n get velocity(): Vec3;\n set velocity(v: Vec3Like);\n /**\n * Angular velocity — **degrees/second about each world axis** (the SDK's angle unit everywhere;\n * the engine works in radians and converts here). Fresh Vec3 on read.\n *\n * This is the only handle on a body's spin, and placing an object usually needs it: a `position`\n * write is a pure teleport, so a crate that was tumbling keeps tumbling at its new home. Putting\n * something down is `body.velocity = [0,0,0]; body.angularVelocity = [0,0,0]; node.position = p`.\n */\n get angularVelocity(): Vec3;\n set angularVelocity(v: Vec3Like);\n _writeComp(prop: string, axis: CompAxis, v: number): void;\n /** Apply an instantaneous impulse (kg·m/s) and wake the body. */\n applyImpulse(v: Vec3Like): this;\n /** The same impulse applied at a WORLD-SPACE point instead of the centre of mass: the lever arm\n * becomes angular impulse, so the body spins as well as moves (a bullet hitting a crate off\n * centre, a blast lifting it by its base). Falls back to the central impulse on an older host. */\n applyImpulseAt(v: Vec3Like, point: 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 private _preview?;\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 { type Aspect, type AspectCtor, type FieldOf, type TargetOf } from \"../core/Aspect\";\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 AmbientOcclusionOptions = {\n /** Strength of the darkening (default 1). */\n intensity?: number;\n /** How far the occlusion reaches, in metres (default 0.3). */\n radius?: number;\n /** Falloff contrast; >1 tightens it into the crease (default 1). */\n power?: number;\n /** Sample count + filtering (default 'medium'). Not the buffer resolution — that stays half. */\n quality?: \"low\" | \"medium\" | \"high\" | \"ultra\";\n};\nexport type FogOptions = {\n /** A TINT on the in-scattered ambient, not an absolute colour: the engine multiplies it by the\n * environment luminance, so white (the default) means \"fog as bright as the ambient\" and the fog\n * brightens with `environmentIntensity`. Do NOT expect the same hex to look like it does in\n * `skybox` — that one IS an absolute radiance and reads roughly an order of magnitude brighter.\n * Tint towards the sky's hue; leave it white to sit at the ambient level. */\n color?: ColorInput;\n /** Metres from the camera before the fog starts (default 0). */\n start?: number;\n /** Extinction per metre at `height`; 0.01 ≈ clearly visible over ~100 m (default 0.01). */\n density?: number;\n /** The fog's \"sea level\" in world Y (default 0). */\n height?: number;\n /** How fast it thins with altitude, 1/m. 0 = uniform everywhere; higher = a ground-hugging layer\n * you can see over (default 0). */\n heightFalloff?: number;\n /** Cap on how opaque it can get, 0–1 — keeps far shapes readable (default 1). */\n maxOpacity?: number;\n /** Metres after which fog stops applying; 0 = everywhere (default 0). */\n cutoff?: number;\n /** Take the colour from the environment in the view direction, tinted by `color`, instead of a\n * flat `color`. Convincing when the IBL is a real sky (default false). */\n fromEnvironment?: boolean;\n};\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 /** Tone mapping operator. `'aces'` (default, filament's ACES legacy) desaturates bright colours\n * towards white — HDR fire reads pale; `'neutral'` (Khronos PBR Neutral) keeps hue and\n * saturation until very bright; `'linear'` clips each channel (what an engine without a\n * tonemapper shows — saturated, Unity-without-post-processing look); `'filmic'` (Uncharted). */\n toneMapping?: \"aces\" | \"neutral\" | \"linear\" | \"filmic\";\n /** The sky. Three forms:\n * - a colour — a flat clear colour;\n * - `{ texture }` — a KTX1 **cubemap**, the sharp `<name>_skybox.ktx` that filament's `cmgen`\n * produces from an equirectangular .hdr/.exr. This is the one to use for a real sky. Pass an\n * `asset('../assets/sky.ktx')` handle or a bare staged filename;\n * - `'environment'` — reuse the scene's IBL cubemap. Cheapest (no second texture) but that file\n * is prefiltered for roughness, so the sky comes out soft; fine as a fallback, not as the goal.\n *\n * Either texture form draws through filament's own skybox pass: a full-screen pass in device\n * space after the opaque queue. No geometry, no meridian seam, no pole distortion — do NOT build\n * a sky dome or a fullscreen equirect material by hand, both are strictly worse. */\n skybox?: ColorInput | \"environment\" | {\n texture: string;\n };\n /** Screen-space ambient occlusion — the contact darkening in creases and where props meet the\n * ground. Without it an IBL lights a crease exactly as brightly as an open face, so everything\n * reads as pasted onto the floor rather than standing on it. `true` takes defaults tuned for\n * human-scale props; `radius` is world-space metres and is the one knob that must follow the\n * scene's scale (~0.3 for objects on a table, ~0.6-1 for a yard of crates and containers). */\n ambientOcclusion?: boolean | AmbientOcclusionOptions;\n /** Distance fog / aerial perspective: distant geometry loses contrast so the eye reads depth, and\n * the hard edge where a finite level ends against the skybox goes away. By default the fog applies\n * at every distance — the skybox included — so the sky itself takes the fog colour and the horizon\n * blends on its own; `cutoff` opts geometry beyond a distance back out. */\n fog?: FogOptions;\n /** Multisample anti-aliasing: `true` = 4×, `2`/`4` = that many samples, `false` = off (FXAA\n * takes over). Unset keeps the host default (desktop 4×, mobile/web off). The biggest single\n * fill-rate cost after resolution — turn it down on big screens before anything else. */\n antialias?: boolean | 2 | 4;\n /** Render the 3D at this fraction of the viewport (0.25–1) and upscale; the UI stays at native\n * resolution. A fixed, predictable cut of per-pixel GPU work — `0.75` is ~45 % cheaper and\n * barely visible in motion, `0.5` quarters it. Headless renders ignore it. */\n renderScale?: number;\n /** Let the engine shrink the 3D buffers under `renderScale` only when frames run over budget\n * (Filament dynamic resolution, sharpened upscale) down to `min` (default 0.5). Off by default:\n * it makes the output frame-time dependent, so flow tests / headless renders never enable it. */\n dynamicResolution?: boolean | {\n min?: number;\n };\n /** Anisotropic filtering, 1 (off) … 16. Default 2. What it buys is detail on surfaces seen at a\n * GRAZING angle — a first-person weapon, a floor, a wall — where the sample footprint is far\n * longer in one axis than the other and isotropic filtering has to pick a mip for the long one,\n * several levels coarser than the short axis deserves. Measured on a weapon seen from the side\n * (local contrast): 8.18 at 1× → 10.02 at 2× → 10.84 at 4× → 11.29 at 8×. The default is 2\n * because it is where the curve is steepest per unit of memory bandwidth; raise it if you have\n * the headroom.\n *\n * It is an ENGINE-WIDE default, not a property of this scene: a sampler is baked when its\n * texture is bound, so this reaches the models a scene loads AFTER it (which is every model in a\n * scene file — `env` is applied before the nodes build) and leaves already-loaded ones alone.\n * On the desktop host `CREATOR_TEXTURE_ANISOTROPY` overrides it, for tuning without a rebuild. */\n anisotropy?: number;\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 /** Runtime form of `renderScale` / `dynamicResolution` (a graphics-settings menu). `renderScale`\n * 0.25–1; older hosts without the method ignore it. */\n setRenderOptions(renderScale: number, dynamicResolution?: boolean | {\n min?: number;\n }): void;\n /** Scene occlusion material. */\n get occlusionMaterial(): Material;\n set skybox(sky: ColorInput | \"environment\" | {\n texture: string;\n });\n /** Runtime form of `ambientOcclusion` (a graphics-settings menu). `false` turns it off. */\n setAmbientOcclusion(options: boolean | AmbientOcclusionOptions): void;\n /** Runtime form of `fog` (weather, entering a building). `false` turns it off. */\n setFog(options: FogOptions | false): void;\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 /** Attach (and configure) a system, or reconfigure it if already present. Returns the scene typed\n * as now-having it (`scene.system(Hud).hud`). A `System<'x', Scene2D>` is rejected here. */\n system<Self extends TargetOf<A>, A extends Aspect<any, any, any>>(this: Self, ctor: AspectCtor<A>, opts?: Partial<A>): Self & FieldOf<A>;\n /** Safe access — undefined if the system isn't attached. */\n get<A extends Aspect<any, any, any>>(ctor: AspectCtor<A>): A | undefined;\n /** Existence check AND type guard: inside `if (scene.has(Hud))`, `scene.hud` is present. */\n has<A extends Aspect<any, any, any>>(ctor: AspectCtor<A>): this is this & FieldOf<A>;\n /** Detach a system (runs its onDetach). Chainable. */\n removeSystem<A extends Aspect<any, any, any>>(ctor: AspectCtor<A>): this;\n /** Tear the scene down: every system detaches (last-attached first) and the scene closes. Nodes\n * are yours — destroy the ones you own; the native scene object itself is not released. */\n destroy(): void;\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\";\n/** Which geometry a Shape uses — the one-of the fields below encode (see `_build`'s order). */\nexport type ShapeKind = \"auto\" | \"box\" | \"sphere\" | \"cylinder\" | \"capsule\" | \"mesh\" | \"convex\";\n/** A node-local AABB, in the node's OWN frame (its own transform excluded), before world scale. */\nexport type ShapeBounds = {\n min: [number, number, number];\n max: [number, number, number];\n};\n/** Dimensions measured from a node's rendered geometry — what `Shape.fit` writes, and the numbers\n * the scene editor's \"Fit to mesh\" button puts in the file. Exactly one dimension key is set (none\n * for a mesh/convex kind, whose geometry is the mesh itself); `origin` centres it on the art. */\nexport type ShapeFit = {\n box?: [number, number, number];\n sphere?: number;\n cylinder?: {\n halfHeight: number;\n radius: number;\n };\n capsule?: {\n halfHeight: number;\n radius: number;\n };\n origin: [number, number, number];\n};\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 /** The node's own triangles (a Mesh's geometry or a Model's GLB, world scale applied).\n * `true` = exact triangle mesh — static/kinematic bodies, triggers, characters' ground and picking\n * only (a dynamic body can't be a triangle mesh; Physics throws). `'convex'` = convex hull of the\n * vertices, works for dynamic bodies too. A Model uses its bind pose (skinned parts skipped). */\n mesh?: boolean | \"convex\";\n /**\n * The shape's centre, relative to the node's origin — world units in the node's ROTATED frame\n * (the node's scale is ignored, exactly like the explicit dimensions above). Default [0, 0, 0].\n *\n * A model's pivot is rarely its centre of volume (a character stands ON its origin, a wheel hangs\n * off its axle), so a collider centred on the pivot is half sunk into the floor. `origin` lifts it\n * without moving the node: `{ capsule: { halfHeight: 0.6, radius: 0.3 }, origin: [0, 0.9, 0] }`.\n * `fit()` and the scene editor's \"Fit to mesh\" fill it in from the rendered bounds.\n *\n * On a DYNAMIC body the offset also moves the centre of mass, so a lopsided collider tips the way\n * you would expect. With no `origin` an auto shape (`{}`) still centres itself on the node's own\n * mesh bounds — only explicit dimensions sit on the pivot by default.\n */\n origin?: Vec3Like;\n /** Whether pointer rays can hit this shape (click / touchstart). Default true. */\n raycast: boolean;\n private _shapeId;\n private _bodyId;\n /** Centre the \"auto\" box measured for itself — used when `origin` isn't set explicitly. */\n private _autoOrigin;\n /** Geometry props as of the last build (see onReconfigure). */\n private _sig;\n onAttach(): void;\n onDetach(): void;\n /** Re-configuring (`node.aspect(Shape, { origin })`) rebuilds the geometry when a dimension, the\n * kind or the origin changed, and re-applies pickability. The body keeps its id and velocity. */\n onReconfigure(): void;\n /**\n * Measure the node's rendered geometry and size the collider to it — the code half of the scene\n * editor's \"Fit to mesh\". Keeps the current kind unless one is passed; `auto` becomes an explicit\n * box, and a mesh/convex shape only has its `origin` cleared (its geometry IS the mesh).\n *\n * crate.aspect(Shape, {}).shape.fit() // box around what the model actually draws\n * hero.aspect(Shape, {}).shape.fit('capsule') // capsule of the same height + girth\n *\n * A model loads asynchronously, so fit AFTER its `load()` resolves — an empty subtree measures as\n * nothing and the call is a no-op (it warns). Rebuilds the live shape, keeping the body.\n */\n fit(kind?: ShapeKind): this;\n /** Which geometry this shape currently uses (the `_build` dispatch, as a name). */\n get kind(): ShapeKind;\n /**\n * The node's subtree AABB in its OWN local frame (its own transform excluded), or null when there\n * is nothing to measure. Reads the engine's bounds — which cover a loaded GLB and every child —\n * and falls back to a Mesh node's own CPU geometry on hosts without them.\n */\n static boundsOf(node: Node): ShapeBounds | null;\n /**\n * Dimensions + origin that make `kind` hug what `node` renders — world units, so the node's world\n * scale is baked in exactly as the Shape fields expect. Null when the node has no geometry (a\n * model that hasn't loaded, an empty).\n */\n static fitTo(node: Node, kind?: ShapeKind): ShapeFit | null;\n /**\n * The measuring itself, over plain numbers: a node-local AABB + the node's world scale in, shape\n * dimensions out. Separate from `fitTo` so the scene-editor harness can measure a node from\n * ANOTHER bundle without touching accessors the bundler may have shaken out of it.\n *\n * A sphere takes the LARGEST half-extent and a cylinder/capsule the larger of X/Z, so the fit\n * reads as the object's silhouette rather than as an enclosing ball; adjust from there.\n */\n static fitBounds(bounds: ShapeBounds, scale: Vec3Like, kind?: ShapeKind): ShapeFit;\n private _createPickBody;\n private _rebuild;\n private _build;\n private _applyOrigin;\n private _signature;\n private _buildMesh;\n private _buildAutoBox;\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 { 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}\n","types/gl/Vehicle.d.ts":"import { Aspect } from \"../core/Aspect\";\nimport type { FieldMeta } from \"../core/fields\";\nimport { Vec3, type Vec3Like } from \"../math/vec\";\nimport { type QuatLike } from \"../math/quat\";\nimport { Node } from \"./Node\";\nimport { Wheel } from \"./Wheel\";\n/** Which axle the engine drives. A wheel's own `drive` overrides it. */\nexport type DriveLayout = \"rear\" | \"front\" | \"all\";\n/**\n * How an axle's two wheels share torque.\n * - `lsd` — limited slip (Jolt's 1.4 ratio), the sane default.\n * - `open` — fully open: a lifted or spinning wheel takes ALL the torque.\n * - `locked` — both wheels forced to the same speed. Breaks traction predictably: the drift diff.\n * A number is the raw max/min wheel-speed ratio (> 1; smaller is more locked).\n */\nexport type DifferentialMode = \"lsd\" | \"open\" | \"locked\";\nexport interface EngineConfig {\n /** Peak torque in N·m (default 500). The single biggest \"how fast is it\" knob. */\n torque?: number;\n /** Redline in RPM (default 6000). */\n maxRpm?: number;\n /** Idle RPM (default 1000) — the engine never falls below it. */\n idleRpm?: number;\n /**\n * The engine's CHARACTER: a flat list `[rpm, torque, rpm, torque, …]` in NORMALISED units — x is\n * a fraction of the redline, y a fraction of `torque`. Left out, Jolt's own broad curve is used.\n *\n * `[0, 0.8, 0.66, 1, 1, 0.8]` is an ordinary petrol engine (peak two thirds up, falling to the\n * redline); `[0, 1, 1, 1]` is flat, which is what an electric motor feels like.\n */\n curve?: number[];\n /** Moment of inertia in kg·m² (default 0.5) — how eagerly it revs when the clutch is out. */\n inertia?: number;\n /** Engine braking: angular damping of the engine itself (default 0.2). */\n braking?: number;\n}\nexport interface SteeringConfig {\n /** Steering lock in degrees at a standstill (default 35). */\n lock?: number;\n /**\n * The lock still available, in degrees, once the car reaches `speed` (default 10) — what stops a\n * car over-driving its own front tires.\n *\n * A tire makes its peak grip at a few degrees of slip angle, and the steering angle a corner needs\n * falls with the SQUARE of speed. Holding full lock at 100 km/h therefore asks the front for\n * several times what it can give: the tires saturate, the car ploughs on, and the wheel stops\n * answering. In between the lock eases on `(1 − v/speed)²`, which tracks the real curve closely.\n * `0` turns the taper off — full lock at any speed.\n */\n atSpeed?: number;\n /** The speed in m/s at which the lock has fallen to `atSpeed` (default 30 ≈ 108 km/h). */\n speed?: number;\n /** How fast the front wheels may turn, in degrees per second (default 220). A keyboard asks for\n * full lock in one frame, which no steering wheel can do, and that step alone snaps a tire past\n * its peak. `0` = instantly. */\n rate?: number;\n}\n/**\n * Aerodynamics. Both numbers are quoted the same way — **a fraction of the car's own weight at\n * 30 m/s (108 km/h)** — and both grow with the SQUARE of speed from there, so `0.5` at 30 m/s is\n * `2.0` at 60 m/s. One mental model for both, and no drag coefficients or frontal areas to invent.\n */\nexport interface AeroConfig {\n /**\n * Downforce (default 0 — a car with no wing). The knob that decides whether a car corners better\n * or worse the faster it goes: tire grip is a constant, but the force a corner demands grows with\n * v², so with no downforce every car runs out of road at speed. `0.6` roughly doubles a car's\n * cornering at 150 km/h; a road car is nearer `0.1`, a race car well past `1`.\n *\n * It presses along the CHASSIS' own down axis (that is what keeps a car planted over a crest) and\n * only while a wheel is on the ground — a car on its roof is never launched by its own wing.\n */\n downforce?: number;\n /** Air resistance (default 0.03 — an ordinary car). What gives a car a top speed at all. */\n drag?: number;\n}\nexport declare class Vehicle extends Aspect<\"vehicle\", Node> {\n static readonly aspect = \"vehicle\";\n /** Chassis mass in kg (default 1200). Wheels are massless in this model. */\n mass: number;\n /** Centre of mass height in chassis space (metres, negative = lower). Left out, it drops to halfway\n * down the chassis shape — a car with its mass at the shape's centre tips over. */\n centerOfMass?: number;\n /** Which axle the engine drives (default \"rear\"). A wheel's own `drive` overrides it. */\n driveAxle: DriveLayout;\n /** Differential lock across each driven axle. `locked` is the drift setup — both wheels turn\n * together, so the pair lets go as a pair. Live: re-configure the aspect to switch it mid-drive. */\n differential: DifferentialMode | number;\n /**\n * Anti-roll bars between each axle's wheels — what stops a car rolling onto its inside wheels in a\n * fast corner. `true` (default) is a bar 0.01 as stiff as the wheel's own spring; a number is that\n * ratio directly, and `0` / `false` removes the bars.\n *\n * **The numbers are far smaller than they look and the gain is steep** — Jolt's bar feeds\n * `lengthDifference × stiffness × dt` as a bias into the suspension's own soft constraint, so 4%\n * of the spring already flattens the body. Measured on a 1250 kg car: `0` → 1.3° of roll at 0.86 g,\n * `0.01` → 0.6°, `0.15` → 0.2° (flat), `0.5` → the car HOPS.\n *\n * This is the knob for how much a car visibly LEANS, not for wheel lift: bars change how far the\n * body tips, not how much load transfers. For lift, lower `centerOfMass`.\n */\n antiRoll: boolean | number;\n /** Pitch/roll limit in degrees (default 60) before the constraint rights the car. 180 turns it off. */\n maxTilt: number;\n /** Friction of the CHASSIS body itself — how it slides when it lands on its roof or side. Nothing\n * to do with the tires; those are the `Wheel`'s `tire.grip` × the ground's friction. */\n friction: number;\n /** Strength of the clutch when fully engaged (default 10). Small values slip; large ones weld the\n * engine to the wheels. The `Gearbox` scales it 0..1 while shifting. */\n clutchStrength: number;\n engine: EngineConfig;\n steering: SteeringConfig;\n aero: AeroConfig;\n /** Scene-editor inspector: the flat, tunable half. The grouped objects are edited in code. */\n static fields: FieldMeta<Vehicle>;\n static editor: {\n rebuild: boolean;\n };\n private _id;\n private _bodyId;\n private _builtMass;\n private _wheels;\n private _state;\n private _stateFrame;\n private _throttle;\n private _steer;\n private _brake;\n private _handbrake;\n onAttach(): void;\n onDetach(): void;\n /**\n * Re-configuring an attached vehicle retunes it in place — the way a drift button switches the\n * differential without the car so much as blinking:\n *\n * car.aspect(Vehicle, { differential: drift ? 'locked' : 'lsd' })\n *\n * Live: `differential`, `engine`, `steering`, `aero`, `maxTilt`, `friction`, `clutchStrength`, and\n * every `Wheel`'s `tire.grip` and brake torques. Everything else describes the car's STRUCTURE —\n * `mass`, `centerOfMass`, which wheels exist and where, their suspension, `driveAxle`, `antiRoll` — and\n * is baked into the constraint at attach; to change one of those, re-attach the aspect.\n */\n onReconfigure(): void;\n /** Native vehicle id (0 until attached / no physics support). */\n get id(): number;\n /** The chassis rigid-body id — the same handle the plain body calls take. */\n get bodyId(): number;\n /** The wheels, in blob order (front axle first). */\n get wheels(): readonly Wheel[];\n /**\n * The driver's controls, all in [-1, 1] (brakes in [0, 1]). Sticky: the last values keep applying\n * until the next call, so a held key does not need re-sending. `forward < 0` asks for reverse; the\n * `Gearbox` engages it once the car has stopped.\n */\n drive(forward: number, steer?: number, brake?: number, handbrake?: number): this;\n /** Teleport upright and clear all motion (velocity, engine, gearbox, wheel spin). Defaults to the\n * chassis node's current pose — `reset()` alone un-flips a car where it lies. */\n reset(position?: Vec3Like, rotation?: QuatLike): this;\n /** Push the chassis (a boost pad, an explosion) — an instantaneous impulse in kg·m/s. */\n applyImpulse(v: Vec3Like): this;\n private _read;\n /** Speed along the car's forward axis in m/s — negative when reversing (× 3.6 for km/h). */\n get speed(): number;\n /** Engine revolutions per minute. */\n get rpm(): number;\n /** How many wheels are touching the ground. */\n get wheelsOnGround(): number;\n /** Any wheel on the ground — false while airborne. */\n get grounded(): boolean;\n /** Chassis velocity in world units/s (fresh Vec3). */\n get velocity(): Vec3;\n /** The last throttle handed to `drive()` — what the gearbox reads to know which way you want to go. */\n get throttle(): number;\n /** The last steer input handed to `drive()`, [-1, 1]. */\n get steerInput(): number;\n /** The last foot-brake input handed to `drive()`, [0, 1] — the pedal, not the resulting force. */\n get brake(): number;\n /** The last handbrake input handed to `drive()`, [0, 1]. */\n get handbrake(): number;\n /** Current gear from the attached `Gearbox`: −1 reverse, 0 neutral, 1… forward. */\n get gear(): number;\n /** The steering lock, in degrees, the car is allowed at its current speed — the full lock at rest,\n * falling to `steering.atSpeed`. The same curve the engine applies; useful on a HUD. */\n get steerLock(): number;\n /** Every Wheel under the chassis, ordered front axle first, with its axle group resolved. */\n private _collectWheels;\n /** Pack the whole configuration into the one blob the host ABI takes (see bridges.d.ts). */\n private _buildSettings;\n /** Edit mode: which way the chassis faces. Each wheel draws its own circle and travel range — see\n * `Wheel.rebuild()`. Play mode never calls this. */\n rebuild(): void;\n}\n","types/gl/Wheel.d.ts":"import { Aspect } from \"../core/Aspect\";\nimport type { FieldMeta } from \"../core/fields\";\nimport { type Vec3Like } from \"../math/vec\";\nimport { Node } from \"./Node\";\n/** Floats `vehicleGetState` writes before the per-wheel block: speed, rpm, contacts, vx, vy, vz. */\nexport declare const STATE_HEADER = 6;\n/** Floats per wheel: contact, slip, slipAngle, suspensionLength, steerDeg, spin. */\nexport declare const WHEEL_STATE = 6;\n/** How a tire behaves past its grip peak. `road` is Jolt's own curve — grip falls off after the peak,\n * so the car can be made to let go. `arcade` holds the peak all the way out: much harder to spin. */\nexport type TireCurve = \"road\" | \"arcade\";\nexport interface WheelSuspension {\n /** Total travel in metres, full droop to fully compressed (default 0.4). */\n travel?: number;\n /** Spring frequency in Hz — bigger is stiffer (default 1.4; a race car ~2.5, a truck ~1). It also\n * sets the ride-height sag, and the sag is how far the wheel can still extend DOWN. */\n stiffness?: number;\n /** Damping ratio 0..1 (default 0.5). Low values pogo. */\n damping?: number;\n}\nexport interface WheelTire {\n /** Grip multiplier on the friction curves (default 1). The grip a wheel actually gets is combined\n * with the ground it stands on as `sqrt(tire × groundFriction)`, and a body's friction defaults to\n * 0.6 — so a road a car should really corner on wants `Physics { friction: 1 }`. */\n grip?: number;\n /** Which friction curve (default `road`). */\n curve?: TireCurve;\n}\nexport interface WheelVisual {\n /** The MODEL's axle direction in its own space (default `[1, 0, 0]`). Set it instead of parenting\n * the mesh under a corrective node when the art points another way. */\n axis?: Vec3Like;\n /** Drawn radius, if the art is not exactly the physical `radius` — sinks a wheel into its arch or\n * lets a fat tire overhang, with no effect on the simulation. Default: the physical radius. */\n radius?: number;\n /** Let the model spin (default true). `false` keeps the steer angle and suspension travel but not\n * the rotation — a brake caliper. */\n spin?: boolean;\n}\nexport declare class Wheel extends Aspect<\"wheel\", Node> {\n static readonly aspect = \"wheel\";\n /** Wheel radius in metres. Default: measured from the node's rendered bounds, else 0.35. Too small\n * and the car scrapes, too large and it floats. */\n radius?: number;\n /** Wheel width in metres. Default: measured, else 0.25. */\n width?: number;\n /** Does this wheel steer? Default: the wheels on the front axle. */\n steer?: boolean;\n /** Does the engine drive it? Default: from the vehicle's `drive` layout. */\n drive?: boolean;\n /** Foot brake on this wheel. */\n brake: boolean;\n /** Handbrake on this wheel. Default: every non-steering wheel (locking the front wheels of a moving\n * car is not a handbrake turn, it is a crash). */\n handbrake?: boolean;\n /** Axle group, front to back. Default: derived from Z. Set it for a car whose wheels are not in neat\n * left/right pairs — an axle's wheels are paired for the differential and the anti-roll bar. */\n axle?: number;\n /** Foot-brake torque in N·m (default 1500); the handbrake pulls 3× on the wheels that have it. */\n brakeTorque: number;\n suspension: WheelSuspension;\n tire: WheelTire;\n visual: WheelVisual;\n /** Scene-editor inspector. `steer` / `drive` / `handbrake` are deliberately absent: they are\n * tri-state (undefined = derive it from the axle), which a switch cannot express. */\n static fields: FieldMeta<Wheel>;\n static editor: {\n rebuild: boolean;\n };\n private _angle;\n private _scale;\n private _local;\n onAttach(): void;\n onDetach(): void;\n private _state;\n /** Touching the ground this step. */\n get contact(): boolean;\n /** Longitudinal slip RATIO: 0 = rolling in sync with the ground, ~1 = spinning up or locked.\n * Unsigned — smoke, tire marks and wheelspin sound key off this. */\n get slip(): number;\n /** Slip ANGLE in degrees: how far the tire's travel direction is off from where it points.\n * Unsigned, 0..90 — past the curve's peak (~3°) the tire is sliding sideways. Drift particles. */\n get slipAngle(): number;\n /** Steer angle in degrees, positive to the right. */\n get steerAngle(): number;\n /** Wheel spin in rad/s (× radius ≈ the speed the tire is laying down). */\n get spin(): number;\n /** Suspension compression, 0 = fully extended (drooping) … 1 = fully compressed. */\n get compression(): number;\n /** LATE phase: after the step and the transform sync, right before the frame draws. */\n update(dt: number): void;\n /** Edit mode: this wheel's own circle at its resting height, its travel range, and a mark when the\n * engine drives it — enough to place a wheel without running the game. */\n rebuild(): void;\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, System, type With, type SystemHost } from \"./core/Aspect\";\nexport { type EventMap } from \"./core/events\";\nexport { Time } from \"./core/time\";\nexport { InspectorUI } from \"./core/InspectorUI\";\nexport { signal, computed, effect, type Signal, type Computed } from \"./core/signals\";\nexport { __compWrite, __compOp, type CompAxis, type CompWriter } from \"./core/compWrite\";\nexport { Canvas, Bitmap } from \"./canvas/Canvas\";\nexport { toast, openURL, SvgSource } from \"./runtime/misc\";\nexport { app, type AppState, type OrientationLock } 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, InputChannel, type InputKeyEvent, type InputGamepadEvent, type InputEventName, type GamepadState, type GamepadAxisName } 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 { OneWay2D } from \"./g2/OneWay2D\";\nexport { PhysicsGroup2D } from \"./g2/groups2d\";\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, applyEditorPose as __applyEditorPose } from \"./scene/defineScene\";\nexport { defineMaterial, MaterialHandle, assignMaterialDef as __assignMaterialDef, applyMaterialParam as __applyMaterialParam, } from \"./scene/material\";\nexport type { MaterialData, MaterialParamValue, ShaderMaterialDef, LitMaterialDef, UnlitMaterialDef } from \"./scene/material\";\nexport type { SceneDef, SceneNodeDef, MeshDef, LightDef, MaterialDef, CameraNodeDef, AspectEntry, MakeEntry, LoadedScene, SceneInstance } from \"./scene/defineScene\";\nexport { CameraPlace } from \"./gl/CameraPlace\";\nexport type { FieldMeta } from \"./core/fields\";\nexport { Gizmos, GizmoBuffer as __GizmoBuffer, withGizmoScope as __withGizmoScope } from \"./scene/gizmos\";\nexport type { GizmoStyle, GizmoAnchor } from \"./scene/gizmos\";\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 { Vehicle } from \"./gl/Vehicle\";\nexport type { DriveLayout, DifferentialMode, EngineConfig, SteeringConfig, AeroConfig } from \"./gl/Vehicle\";\nexport { Wheel } from \"./gl/Wheel\";\nexport type { TireCurve, WheelSuspension, WheelTire, WheelVisual } from \"./gl/Wheel\";\nexport { Gearbox } from \"./gl/Gearbox\";\nexport { AnimationClip } from \"./gl/animation/AnimationClip\";\nexport type { ClipDef, ClipTrackDef, ClipKey } from \"./gl/animation/AnimationClip\";\nexport { Animator } from \"./gl/animation/Animator\";\nexport { Playback } from \"./gl/animation/Playback\";\nexport { Loop } from \"./gl/animation/Loop\";\nexport { Layer } from \"./gl/animation/Layer\";\nexport type { PlayOptions, StopOptions, LayerOptions, LoopOptions, LoopDef, BlendPosition } from \"./gl/animation/core\";\nexport { IK } from \"./gl/IK\";\nexport type { IKTwoBone, IKLookAt } from \"./gl/IK\";\nexport { Light } from \"./gl/Light\";\nexport { Lightmap } from \"./gl/Lightmap\";\nexport { Material } from \"./gl/Material\";\nexport { Geometry } from \"./gl/Geometry\";\nexport { InstancedMesh } from \"./gl/InstancedMesh\";\nexport type { InstanceTransform } from \"./gl/InstancedMesh\";\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\";\n/** `\"landscape\"` — either landscape direction (sensor landscape), `\"portrait\"` — upright only,\n * `\"auto\"` — released: the device's own rotation rules apply. */\nexport type OrientationLock = \"auto\" | \"portrait\" | \"landscape\";\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 /** Lock the screen orientation — `\"landscape\"` for a horizontal game (the device rotates to\n * landscape right away and stays there whichever way it is held), `\"portrait\"` for upright\n * only, `\"auto\"` to release. Call it once at startup; the lock is per app run (it resets\n * when the app quits or restarts), so there is nothing to undo. The rotation arrives as an\n * ordinary resize — layouts reflow, a scene's viewport follows. Silent no-op on hosts\n * without a rotatable screen (desktop, headless, web). */\n setOrientation(mode: OrientationLock): void;\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":"/** Continuous channel ids — the `_creatorUtils.inputRead` contract (bridges.d.ts). */\nexport declare const InputChannel: {\n readonly MouseX: 0;\n readonly MouseY: 1;\n readonly MouseDX: 2;\n readonly MouseDY: 3;\n readonly WheelX: 4;\n readonly WheelY: 5;\n readonly PointerLocked: 6;\n readonly GamepadCount: 7;\n readonly GamepadBase: 16;\n readonly GamepadStride: 16;\n readonly PadConnected: 0;\n readonly PadLeftX: 1;\n readonly PadLeftY: 2;\n readonly PadRightX: 3;\n readonly PadRightY: 4;\n readonly PadLeftTrigger: 5;\n readonly PadRightTrigger: 6;\n};\nexport type InputEventName = \"keydown\" | \"keyup\" | \"gamepadconnected\" | \"gamepaddisconnected\";\n/** `keydown` / `keyup` payload. `code` is the same string `Input.key()` takes. */\nexport interface InputKeyEvent {\n readonly type: \"keydown\" | \"keyup\";\n /** Button code: KeyboardEvent.code ('KeyW', 'Space'), 'MouseLeft|Right|Middle|Back|Forward', or\n * 'GamepadSouth|East|West|North|L1|R1|L2|R2|Select|Start|L3|R3|Up|Down|Left|Right'. */\n readonly code: string;\n /** Which device: 'keyboard' | 'mouse' | 'gamepad'. */\n readonly source: \"keyboard\" | \"mouse\" | \"gamepad\";\n /** Pad index (0..3) for gamepad buttons, undefined otherwise. */\n readonly gamepad?: number;\n /** OS auto-repeat keydown (key still held) — ignore for one-shot actions. */\n readonly repeat: boolean;\n}\nexport interface InputGamepadEvent {\n readonly type: \"gamepadconnected\" | \"gamepaddisconnected\";\n readonly gamepad: number;\n}\ntype Listener<E> = (e: E) => void;\ntype InputEventMap = {\n keydown: InputKeyEvent;\n keyup: InputKeyEvent;\n gamepadconnected: InputGamepadEvent;\n gamepaddisconnected: InputGamepadEvent;\n};\n/** Mouse state — polled. Position is the cursor inside the viewport in logical px; `delta` is the\n * motion during the previous frame (raw where the OS offers it) and keeps counting while locked —\n * that's FPS look. Hosts without a mouse report zeros. */\nexport declare const mouse: {\n readonly position: {\n x: number;\n y: number;\n };\n readonly delta: {\n x: number;\n y: number;\n };\n /** Wheel notches during the previous frame (+y = wheel toward you / scroll down). */\n readonly wheel: {\n x: number;\n y: number;\n };\n /** Pointer lock: cursor hidden + confined, `delta` keeps flowing. Web grants it only from a user\n * gesture (call it in a 'keydown' handler for MouseLeft); hosts drop it on focus loss and\n * re-acquire on focus. Escape does NOT unlock by itself on native hosts — call `unlock()`. */\n readonly locked: boolean;\n lock(): boolean;\n unlock(): void;\n};\nexport type GamepadAxisName = \"leftX\" | \"leftY\" | \"rightX\" | \"rightY\" | \"leftTrigger\" | \"rightTrigger\";\nexport interface GamepadState {\n readonly index: number;\n readonly connected: boolean;\n /** Stick axes −1..1 (+Y = down, like the web Gamepad API), triggers 0..1. `deadzone` (default\n * 0.15) zeroes small stick drift — pass 0 for the raw value. */\n axis(name: GamepadAxisName, deadzone?: number): number;\n /** Held? Same as `Input.key(code, index)`. */\n button(code: string): boolean;\n}\nexport declare const Input: {\n /**\n * Is a button held? `code` is the physical key (`KeyboardEvent.code`: 'ArrowRight', 'KeyW',\n * 'Space'), a mouse button ('MouseLeft', 'MouseRight', 'MouseMiddle') or a gamepad button\n * ('GamepadSouth' = A/Cross, 'GamepadR2' = right trigger as a button …). Poll inside setLoop for\n * frame-independent movement. `gamepad` scopes a Gamepad* code to one pad; omitted = any pad.\n */\n key(code: string, gamepad?: number): boolean;\n /** Listen for a discrete input moment. `keydown`/`keyup` cover EVERY button — keyboard, mouse,\n * gamepad — filter on `e.code`. Use these for one-shot actions (jump, shoot, charge-release);\n * `Input.key` for continuous ones (walk). */\n on<K extends InputEventName>(name: K, listener: Listener<InputEventMap[K]>): void;\n off<K extends InputEventName>(name: K, listener: Listener<InputEventMap[K]>): void;\n mouse: {\n readonly position: {\n x: number;\n y: number;\n };\n readonly delta: {\n x: number;\n y: number;\n };\n /** Wheel notches during the previous frame (+y = wheel toward you / scroll down). */\n readonly wheel: {\n x: number;\n y: number;\n };\n /** Pointer lock: cursor hidden + confined, `delta` keeps flowing. Web grants it only from a user\n * gesture (call it in a 'keydown' handler for MouseLeft); hosts drop it on focus loss and\n * re-acquire on focus. Escape does NOT unlock by itself on native hosts — call `unlock()`. */\n readonly locked: boolean;\n lock(): boolean;\n unlock(): void;\n };\n /** Gamepad `index` (0..3). Always returns an object — check `.connected`. */\n gamepad(index?: number): GamepadState;\n /** Indices of the currently connected gamepads. */\n gamepads(): number[];\n /** @internal — hosts/tests: deliver an event exactly as the host listener would. */\n _emit(kind: number, code: string, gamepad: number, repeat: number): void;\n};\nexport {};\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 { 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 { type MaterialDef } from \"./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 };\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 /** Materials by primitive SLOT of this part (`0` for a single-material mesh; the editor lists\n * the slots with their glTF material names): a material asset, an inline def, or a custom\n * shader. Slots left out keep the glTF material. */\n materials?: Record<number | string, MaterialDef>;\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 /** Editor-only, `model` nodes: the POSE the scene editor shows — a clip looped while editing\n * (`time` freezes it at that second instead), so attachments / sight lines / a first-person eye\n * are placed against the animated pose, not the rest pose. Never applied when the scene runs. */\n editor?: {\n clip?: string;\n time?: number;\n };\n castShadows?: boolean;\n receiveShadows?: boolean;\n /** Baked lighting (a scene with `env.lightmap`): is this model/mesh node a lightmap STATIC — a\n * receiver and an occluder in the bake, real-time shadow casting off once the bake applies?\n * Default: static unless a `Physics` aspect moves the node (`dynamic` — Physics' default — or\n * `kinematic`). Set it only to override that rule; prefab subtrees inherit the verdict. */\n lightmap?: 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};\n/** `env.lightmap` — the level's baked lighting (see lightmap.md): the two files\n * `lecodes lightmap bake` writes, plus how the bake is applied. Absent = real-time only. */\nexport type SceneLightmapDef = {\n /** `asset('./assets/lightmap/lightmap.bake')` */\n data: string;\n /** `asset('./assets/lightmap/lightmap.ktx2')` */\n texture: string;\n /** 1 = baked sun shadows at full strength, 0 = ambient occlusion only. Default 1. */\n sunStrength?: number;\n /** Multiplier on the ambient share in the shadow math (1 = filament's own darkness). Default 1. */\n ambientScale?: number;\n};\nexport type SceneDef = {\n env?: SceneOptions & {\n lightmap?: SceneLightmapDef;\n };\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 instance of a scene file built as a subtree (`handle.instantiate`). */\nexport type SceneInstance<D extends SceneDef> = {\n /** The wrapper node the file's nodes build under — position it, parent it, hide it. */\n root: Node;\n nodes: SceneNodes<D>;\n /** Anchor the instance on one of its own nodes: `root`'s local transform is set so that\n * `inner` coincides with the frame `root` is parented to (its origin and axes). One-shot,\n * from the CURRENT pose of `inner` — a rig's attachment frame (the eye place of a\n * first-person arms scene, the grip of a held prop). */\n alignTo(inner: Node): void;\n get: LoadedScene<D>[\"get\"];\n /** Remove the subtree from the scene and destroy it. */\n dispose(): void;\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[];\n/** The static verdict for one node def (the editor's \"Baked lighting\" switch shows the same rule). */\nexport declare const isLightmapStatic: (def: SceneNodeDef) => boolean;\n/** Edit mode: play the preview pose on a model node (`editor: { clip, time }`) — idempotent, the\n * harness re-applies it on inspector edits. No clip = back to the rest pose. */\nexport declare const applyEditorPose: (node: Node, pose: {\n clip?: string;\n time?: number;\n} | undefined) => void;\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 * Build this scene file as a reusable SUBTREE inside an existing scene — a weapon under a hand\n * bone, a streetlamp per street corner — as many times as you like (unlike `load()`, which is\n * the one-instance \"scene as a level\" path). The nodes build under a fresh wrapper node (`root`)\n * parented to `parent` (or left unparented); `env` / `camera` are ignored like a prefab's. The\n * file's transforms are local to the wrapper, so author it with the wrapper as the attachment\n * point. `ref()`s resolve per instance; aspects attach per instance. `dispose()` removes the\n * subtree from the scene and destroys it.\n */\n instantiate(opts: {\n scene: Scene;\n parent?: Node | null;\n name?: string;\n }): Promise<SceneInstance<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/gizmos.d.ts":"import { type Mat4Like } from \"../math/mat4\";\nimport type { Vec3Like } from \"../math/vec\";\n/** The anchor of a gizmo call: any object with an engine entity id (a `Node`). */\nexport type GizmoAnchor = {\n readonly id: number;\n};\nexport type GizmoStyle = {\n /** CSS hex color (`#rgb` / `#rrggbb`); default a neutral light gray. */\n color?: string;\n /** 0..1, default 1. */\n alpha?: number;\n /** Anchor: points are in this node's LOCAL frame (scale ignored); the lines follow the node\n * live, are pickable (a click selects the node) and turn the selection accent when it is\n * selected. Omit for world-space lines (not pickable). */\n node?: GizmoAnchor | null;\n};\n/** One color batch of LINES (flat `[x,y,z, x,y,z]` per segment) — what a host hands the engine.\n * With `entityId` the segments are in that entity's local frame (see GizmoStyle.node). */\nexport type GizmoBatch = {\n color: string;\n alpha: number;\n segments: number[];\n entityId?: number;\n};\n/** The per-run collector (owned by the scene loader's EditorRun). Batches are keyed by style so a\n * hundred same-colored segments cost one draw. */\nexport declare class GizmoBuffer {\n batches: GizmoBatch[];\n private _byStyle;\n clear(): void;\n segments(style: GizmoStyle | undefined): number[];\n}\n/**\n * Editor-only line drawing, available inside generator `rebuild()`, `make()` factories and editor\n * tool hooks. Points are WORLD space. Drawn by the scene editor's viewport overlay (depth-test\n * off — a path through a wall is still a path); invisible everywhere else.\n */\nexport declare const Gizmos: {\n /** One segment from `a` to `b`. */\n line(a: Vec3Like, b: Vec3Like, style?: GizmoStyle): void;\n /** Consecutive segments through `points`; `closed` joins the last point back to the first. */\n polyline(points: readonly Vec3Like[], style?: GizmoStyle & {\n closed?: boolean;\n }): void;\n /** A wireframe camera frustum looking down −Z: the four edges from the origin to a rect\n * `length` metres ahead sized by `fov` (vertical, degrees) × `aspect` (default 16:9), plus an\n * \"up\" fin above the rect. Anchor it (`{ node }`) for a camera node's marker — the frustum\n * then follows the node's pose; `matrix` places an unanchored one in world space. */\n frustum(fov: number, style?: GizmoStyle & {\n aspect?: number;\n length?: number;\n matrix?: Mat4Like;\n }): void;\n /** A three-axis cross centred on `p` (a point marker); `size` = half extent, default 0.1. */\n cross(p: Vec3Like, size?: number, style?: GizmoStyle): void;\n};\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/scene/material.d.ts":"import type { ColorInput } from \"../core/color\";\nimport { Material, type LitMaterialOptions, type MaterialColorOptions } from \"../gl/Material\";\nimport type { Node } from \"../gl/Node\";\n/** A shader parameter value as scene files write it: number, boolean, `#colour`, texture URL\n * (`asset('./x.png')`), or a numeric vector. */\nexport type MaterialParamValue = number | boolean | string | number[];\ntype WithMapUrl<T> = Omit<T, \"map\"> & {\n /** Base-colour texture — a `Texture`, a `Canvas`, or `asset('./x.png')` (a URL string). */\n map?: LitMaterialOptions[\"map\"] | string;\n};\nexport type LitMaterialDef = WithMapUrl<LitMaterialOptions>;\nexport type UnlitMaterialDef = WithMapUrl<MaterialColorOptions>;\n/** A custom Filament shader (`asset('./x.mat')` — compiled by the platform / `lecodes shaders`)\n * plus its parameter values. */\nexport type ShaderMaterialDef = {\n shader: string;\n params?: Record<string, MaterialParamValue>;\n};\nexport type MaterialDef = {\n lit: LitMaterialDef;\n} | {\n unlit: UnlitMaterialDef;\n} | {\n shadow: ColorInput;\n} | ShaderMaterialDef\n/** A material asset (`import m from './x.material'`) — one shared instance. */\n | MaterialHandle\n/** A code-level Material instance — valid at runtime; the editor shows it read-only. */\n | Material;\n/** The data forms of MaterialDef (everything but a live instance / handle). */\nexport type MaterialData = Exclude<MaterialDef, MaterialHandle | Material>;\n/** Push one parameter into a live material. Textures load asynchronously — the returned promise\n * settles once the value is applied (immediately for scalars). */\nexport declare const applyMaterialParam: (material: Material, name: string, value: MaterialParamValue | null) => Promise<void>;\n/** Build a live Material from a data def. Resolves once every texture it names has loaded. */\nexport declare const createMaterialFromData: (def: MaterialData) => Promise<Material>;\n/**\n * A material asset: the default export of a `*.material.ts` file. `load()` yields ONE shared\n * `Material` (cached); scene files hand the handle to `material:` and the loader resolves it.\n * The editor edits the asset live through `setParam` / `reset` — every node the handle was\n * applied to follows (`_users`).\n */\nexport declare class MaterialHandle {\n def: MaterialData;\n private _instance;\n private _loading;\n /** Every (node, slot) this handle was applied to through a scene — the editor re-assigns them\n * when the asset's shader changes. */\n readonly _users: Set<{\n node: Node;\n slot: number;\n }>;\n constructor(def: MaterialData);\n /** The shared material instance (built on first use). */\n load(): Promise<Material>;\n /** The live instance, if built yet. */\n get material(): Material | null;\n /** Editor: assign this material to `node`'s `slot`, remembering the user. */\n _applyTo(node: Node, slot: number): Promise<Material>;\n /** Editor: one parameter value, applied live to the shared instance (a texture loads in). */\n setParam(name: string, value: MaterialParamValue | null): void;\n /** Editor: replace the whole definition (a shader/kind switch) — rebuilds the instance and\n * re-assigns every user. */\n reset(def: MaterialData): Promise<Material>;\n}\n/** Resolve any `material:` value to a live Material (a handle's shared instance, a data def's\n * fresh one, a code instance as is). */\nexport declare const resolveMaterialDef: (def: MaterialDef) => Promise<Material>;\n/** Resolve and assign a `material:` value to one slot of a node (tracking handle users). */\nexport declare const assignMaterialDef: (node: Node, slot: number, def: MaterialDef) => Promise<Material>;\n/**\n * Define a material as data — the default export of a `*.material.ts` file. Import it into scene\n * files (`material: handle`) or code (`const m = await handle.load()`).\n */\nexport declare const defineMaterial: (def: MaterialData) => MaterialHandle;\nexport {};\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"}