castle-web-cli 0.4.113 → 0.4.115

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 (57) hide show
  1. package/dist/castleJson.d.ts +1 -0
  2. package/dist/editorConfig.d.ts +34 -0
  3. package/dist/editorConfig.js +101 -0
  4. package/dist/ide.js +245 -120
  5. package/dist/imports.d.ts +6 -0
  6. package/dist/imports.js +90 -7
  7. package/dist/init.js +15 -2
  8. package/dist/serve.js +16 -0
  9. package/dist/shell/assets/index-CUamb8rK.js +144 -0
  10. package/dist/shell/assets/index-Y6cJRRCX.css +1 -0
  11. package/dist/shell/index.html +2 -2
  12. package/dist/unsupportedMedia.d.ts +1 -0
  13. package/dist/unsupportedMedia.js +54 -0
  14. package/dist/vitePlugins.js +12 -19
  15. package/kits/basic-2d/castle.json +1 -1
  16. package/kits/basic-2d/editors/behaviorRegistry.js +5 -7
  17. package/kits/physics-2d/CLAUDE.md +42 -23
  18. package/kits/physics-2d/{physics/behaviors → behaviors}/AnalogStick.jsx +3 -3
  19. package/kits/physics-2d/behaviors/Collider.jsx +1 -1
  20. package/kits/physics-2d/{physics/behaviors → behaviors}/Draggable.jsx +3 -3
  21. package/kits/physics-2d/{physics/behaviors → behaviors}/Joints.jsx +4 -4
  22. package/kits/physics-2d/{physics/behaviors → behaviors}/RigidBody.jsx +2 -2
  23. package/kits/physics-2d/{physics/behaviors → behaviors}/Slingshot.jsx +3 -3
  24. package/kits/physics-2d/behaviors/Sound.jsx +152 -0
  25. package/kits/physics-2d/behaviors/Sprite.jsx +98 -33
  26. package/kits/physics-2d/behaviors/Tone.jsx +83 -0
  27. package/kits/physics-2d/behaviors/Video.jsx +111 -0
  28. package/kits/physics-2d/behaviors/tint.js +24 -9
  29. package/kits/physics-2d/castle.json +64 -2
  30. package/kits/physics-2d/editors/BlueprintLibrary.jsx +7 -3
  31. package/kits/physics-2d/editors/ImageViewer.jsx +206 -0
  32. package/kits/physics-2d/editors/MediaPlayer.jsx +57 -0
  33. package/kits/physics-2d/editors/SceneEditor.jsx +7 -3
  34. package/kits/physics-2d/editors/SingleEditor.jsx +8 -0
  35. package/kits/physics-2d/editors/behaviorRegistry.js +5 -7
  36. package/kits/physics-2d/editors/mediaFile.js +20 -0
  37. package/kits/physics-2d/editors/mediaViewer.module.css +128 -0
  38. package/kits/physics-2d/engine/ScenePlayer.jsx +1 -0
  39. package/kits/physics-2d/engine/art.js +105 -0
  40. package/kits/physics-2d/engine/assets.js +11 -3
  41. package/kits/physics-2d/engine/audioContext.js +34 -0
  42. package/kits/physics-2d/engine/collider.js +28 -17
  43. package/kits/physics-2d/engine/files.js +74 -0
  44. package/kits/physics-2d/engine/media.js +212 -0
  45. package/kits/physics-2d/{physics → engine/physics}/PhysicsSystem.js +1 -1
  46. package/kits/physics-2d/{physics → engine/physics}/jointArt.js +1 -2
  47. package/kits/physics-2d/{physics → engine/physics}/matterBridge.js +2 -9
  48. package/kits/physics-2d/engine/scene.js +12 -0
  49. package/kits/physics-2d/engine/tone.js +112 -0
  50. package/kits/physics-2d/systems/media.js +34 -0
  51. package/kits/physics-2d/systems/physics.js +12 -3
  52. package/package.json +1 -1
  53. package/dist/shell/assets/index-BjOuaDJM.js +0 -144
  54. package/dist/shell/assets/index-CdXEpv_P.css +0 -1
  55. package/kits/physics-2d/physics/index.js +0 -26
  56. /package/kits/physics-2d/{physics → engine/physics}/controls.js +0 -0
  57. /package/kits/physics-2d/{physics → engine/physics}/joints.js +0 -0
@@ -0,0 +1 @@
1
+ .dv-scrollable{position:relative;overflow:hidden}.dv-scrollable .dv-scrollbar-horizontal{will-change:background-color, transform;backface-visibility:hidden;background-color:#0000;border-radius:2px;height:4px;transition:background-color 1s ease-in-out;position:absolute;bottom:0;left:0;transform:translate(0,0)}.dv-scrollable:hover .dv-scrollbar-horizontal,.dv-scrollable.dv-scrollable-resizing .dv-scrollbar-horizontal,.dv-scrollable.dv-scrollable-scrolling .dv-scrollbar-horizontal{background-color:var(--dv-scrollbar-background-color,#ffffff40)}.dv-svg{fill:currentColor;stroke:currentColor;stroke-width:0;line-height:1;display:inline-block}.dockview-theme-dark{--dv-paneview-active-outline-color:dodgerblue;--dv-tabs-and-actions-container-font-size:13px;--dv-tabs-and-actions-container-height:35px;--dv-drag-over-background-color:#53595d80;--dv-drag-over-border-color:transparent;--dv-tabs-container-scrollbar-color:#888;--dv-icon-hover-background-color:#5a5d5e4f;--dv-floating-box-shadow:8px 8px 8px 0px #53595d80;--dv-overlay-z-index:999;--dv-tab-font-size:inherit;--dv-border-radius:0px;--dv-tab-margin:0;--dv-sash-color:transparent;--dv-active-sash-color:transparent;--dv-active-sash-transition-duration:.1s;--dv-active-sash-transition-delay:.5s;--dv-group-view-background-color:#1e1e1e;--dv-tabs-and-actions-container-background-color:#252526;--dv-activegroup-visiblepanel-tab-background-color:#1e1e1e;--dv-activegroup-hiddenpanel-tab-background-color:#2d2d2d;--dv-inactivegroup-visiblepanel-tab-background-color:#1e1e1e;--dv-inactivegroup-hiddenpanel-tab-background-color:#2d2d2d;--dv-tab-divider-color:#1e1e1e;--dv-activegroup-visiblepanel-tab-color:white;--dv-activegroup-hiddenpanel-tab-color:#969696;--dv-inactivegroup-visiblepanel-tab-color:#8f8f8f;--dv-inactivegroup-hiddenpanel-tab-color:#626262;--dv-separator-border:#444;--dv-paneview-header-border-color:#ccc3}.dockview-theme-dark .dv-drop-target-container .dv-drop-target-anchor.dv-drop-target-anchor-container-changed{opacity:0;transition:none}.dockview-theme-light{--dv-paneview-active-outline-color:dodgerblue;--dv-tabs-and-actions-container-font-size:13px;--dv-tabs-and-actions-container-height:35px;--dv-drag-over-background-color:#53595d80;--dv-drag-over-border-color:transparent;--dv-tabs-container-scrollbar-color:#888;--dv-icon-hover-background-color:#5a5d5e4f;--dv-floating-box-shadow:8px 8px 8px 0px #53595d80;--dv-overlay-z-index:999;--dv-tab-font-size:inherit;--dv-border-radius:0px;--dv-tab-margin:0;--dv-sash-color:transparent;--dv-active-sash-color:transparent;--dv-active-sash-transition-duration:.1s;--dv-active-sash-transition-delay:.5s;--dv-group-view-background-color:white;--dv-tabs-and-actions-container-background-color:#f3f3f3;--dv-activegroup-visiblepanel-tab-background-color:white;--dv-activegroup-hiddenpanel-tab-background-color:#ececec;--dv-inactivegroup-visiblepanel-tab-background-color:white;--dv-inactivegroup-hiddenpanel-tab-background-color:#ececec;--dv-tab-divider-color:white;--dv-activegroup-visiblepanel-tab-color:#333;--dv-activegroup-hiddenpanel-tab-color:#333333b3;--dv-inactivegroup-visiblepanel-tab-color:#333333b3;--dv-inactivegroup-hiddenpanel-tab-color:#33333359;--dv-separator-border:#80808059;--dv-paneview-header-border-color:#333;--dv-scrollbar-background-color:#00000040}.dockview-theme-light .dv-drop-target-container .dv-drop-target-anchor.dv-drop-target-anchor-container-changed{opacity:0;transition:none}.dockview-theme-vs{--dv-paneview-active-outline-color:dodgerblue;--dv-tabs-and-actions-container-font-size:11px;--dv-tabs-and-actions-container-height:20px;--dv-drag-over-background-color:#53595d80;--dv-drag-over-border-color:transparent;--dv-tabs-container-scrollbar-color:#888;--dv-icon-hover-background-color:#5a5d5e4f;--dv-floating-box-shadow:8px 8px 8px 0px #53595d80;--dv-overlay-z-index:999;--dv-tab-font-size:inherit;--dv-border-radius:0px;--dv-tab-margin:0;--dv-sash-color:transparent;--dv-active-sash-color:transparent;--dv-active-sash-transition-duration:.1s;--dv-active-sash-transition-delay:.5s;--dv-group-view-background-color:#1e1e1e;--dv-tabs-and-actions-container-background-color:#2d2d30;--dv-activegroup-visiblepanel-tab-background-color:#007acc;--dv-activegroup-hiddenpanel-tab-background-color:#2d2d2d;--dv-inactivegroup-visiblepanel-tab-background-color:#3f3f46;--dv-inactivegroup-hiddenpanel-tab-background-color:#2d2d2d;--dv-tab-divider-color:#1e1e1e;--dv-activegroup-visiblepanel-tab-color:white;--dv-activegroup-hiddenpanel-tab-color:white;--dv-inactivegroup-visiblepanel-tab-color:white;--dv-inactivegroup-hiddenpanel-tab-color:white;--dv-separator-border:#444;--dv-paneview-header-border-color:#ccc3}.dockview-theme-vs .dv-drop-target-container .dv-drop-target-anchor.dv-drop-target-anchor-container-changed{opacity:0;transition:none}.dockview-theme-vs .dv-groupview.dv-active-group>.dv-tabs-and-actions-container{box-sizing:content-box;border-bottom:2px solid var(--dv-activegroup-visiblepanel-tab-background-color)}.dockview-theme-vs .dv-groupview.dv-active-group>.dv-tabs-and-actions-container .dv-tab.dv-active-tab{border-top:2px solid var(--dv-activegroup-visiblepanel-tab-background-color)}.dockview-theme-vs .dv-groupview.dv-active-group>.dv-tabs-and-actions-container .dv-tab.dv-inactive-tab{border-top:2px solid var(--dv-activegroup-hiddenpanel-tab-background-color)}.dockview-theme-vs .dv-groupview.dv-inactive-group>.dv-tabs-and-actions-container{box-sizing:content-box;border-bottom:2px solid var(--dv-inactivegroup-visiblepanel-tab-background-color)}.dockview-theme-vs .dv-groupview.dv-inactive-group>.dv-tabs-and-actions-container .dv-tab.dv-active-tab{border-top:2px solid var(--dv-inactivegroup-visiblepanel-tab-background-color)}.dockview-theme-vs .dv-groupview.dv-inactive-group>.dv-tabs-and-actions-container .dv-tab.dv-inactive-tab{border-top:2px solid var(--dv-inactivegroup-hiddenpanel-tab-background-color)}.dockview-theme-abyss{--dv-paneview-active-outline-color:#596f99;--dv-tabs-and-actions-container-font-size:13px;--dv-tabs-and-actions-container-height:35px;--dv-drag-over-background-color:#53595d80;--dv-drag-over-border-color:transparent;--dv-tabs-container-scrollbar-color:#888;--dv-icon-hover-background-color:#5a5d5e4f;--dv-floating-box-shadow:8px 8px 8px 0px #53595d80;--dv-overlay-z-index:999;--dv-tab-font-size:inherit;--dv-border-radius:0px;--dv-tab-margin:0;--dv-sash-color:transparent;--dv-active-sash-color:transparent;--dv-active-sash-transition-duration:.1s;--dv-active-sash-transition-delay:.5s;--dv-color-abyss-dark:#000c18;--dv-color-abyss:#10192c;--dv-color-abyss-light:#1c1c2a;--dv-color-abyss-lighter:#2b2b4a;--dv-color-abyss-accent:#5b1ecf;--dv-color-abyss-primary-text:white;--dv-color-abyss-secondary-text:#9497a9;--dv-group-view-background-color:var(--dv-color-abyss-dark);--dv-tabs-and-actions-container-background-color:var(--dv-color-abyss-light);--dv-activegroup-visiblepanel-tab-background-color:var(--dv-color-abyss-dark);--dv-activegroup-hiddenpanel-tab-background-color:var(--dv-color-abyss);--dv-inactivegroup-visiblepanel-tab-background-color:var(--dv-color-abyss-dark);--dv-inactivegroup-hiddenpanel-tab-background-color:var(--dv-color-abyss);--dv-tab-divider-color:var(--dv-color-abyss-lighter);--dv-activegroup-visiblepanel-tab-color:white;--dv-activegroup-hiddenpanel-tab-color:#ffffff80;--dv-inactivegroup-visiblepanel-tab-color:#ffffff80;--dv-inactivegroup-hiddenpanel-tab-color:#ffffff40;--dv-separator-border:var(--dv-color-abyss-lighter);--dv-paneview-header-border-color:var(--dv-color-abyss-lighter)}.dockview-theme-abyss .dv-drop-target-container .dv-drop-target-anchor.dv-drop-target-anchor-container-changed{opacity:0;transition:none}.dockview-theme-dracula{--dv-paneview-active-outline-color:#6272a4;--dv-tabs-and-actions-container-font-size:13px;--dv-tabs-and-actions-container-height:35px;--dv-drag-over-background-color:#53595d80;--dv-drag-over-border-color:transparent;--dv-tabs-container-scrollbar-color:#888;--dv-icon-hover-background-color:#5a5d5e4f;--dv-floating-box-shadow:8px 8px 8px 0px #53595d80;--dv-overlay-z-index:999;--dv-tab-font-size:inherit;--dv-border-radius:0px;--dv-tab-margin:0;--dv-sash-color:transparent;--dv-active-sash-color:transparent;--dv-active-sash-transition-duration:.1s;--dv-active-sash-transition-delay:.5s;--dv-group-view-background-color:#282a36;--dv-tabs-and-actions-container-background-color:#191a21;--dv-activegroup-visiblepanel-tab-background-color:#282a36;--dv-activegroup-hiddenpanel-tab-background-color:#21222c;--dv-inactivegroup-visiblepanel-tab-background-color:#282a36;--dv-inactivegroup-hiddenpanel-tab-background-color:#21222c;--dv-tab-divider-color:#191a21;--dv-activegroup-visiblepanel-tab-color:#f8f8f2;--dv-activegroup-hiddenpanel-tab-color:#6272a4;--dv-inactivegroup-visiblepanel-tab-color:#f8f8f280;--dv-inactivegroup-hiddenpanel-tab-color:#6272a480;--dv-separator-border:#bd93f9;--dv-paneview-header-border-color:#bd93f9}.dockview-theme-dracula .dv-drop-target-container .dv-drop-target-anchor.dv-drop-target-anchor-container-changed{opacity:0;transition:none}.dockview-theme-dracula .dv-groupview.dv-active-group>.dv-tabs-and-actions-container .dv-tabs-container>.dv-tab.dv-active-tab{position:relative}.dockview-theme-dracula .dv-groupview.dv-active-group>.dv-tabs-and-actions-container .dv-tabs-container>.dv-tab.dv-active-tab:after{content:"";z-index:999;background-color:#94527e;width:100%;height:1px;position:absolute;top:0;left:0}.dockview-theme-dracula .dv-groupview.dv-inactive-group>.dv-tabs-and-actions-container .dv-tabs-container>.dv-tab.dv-active-tab{position:relative}.dockview-theme-dracula .dv-groupview.dv-inactive-group>.dv-tabs-and-actions-container .dv-tabs-container>.dv-tab.dv-active-tab:after{content:"";z-index:999;background-color:#5e3d5a;width:100%;height:1px;position:absolute;bottom:0;left:0}.dockview-theme-replit{--dv-paneview-active-outline-color:dodgerblue;--dv-tabs-and-actions-container-font-size:13px;--dv-tabs-and-actions-container-height:35px;--dv-drag-over-background-color:#53595d80;--dv-drag-over-border-color:transparent;--dv-tabs-container-scrollbar-color:#888;--dv-icon-hover-background-color:#5a5d5e4f;--dv-floating-box-shadow:8px 8px 8px 0px #53595d80;--dv-overlay-z-index:999;--dv-tab-font-size:inherit;--dv-border-radius:0px;--dv-tab-margin:0;--dv-sash-color:#cfd1d3;--dv-active-sash-color:#babbbb;--dv-active-sash-transition-duration:.1s;--dv-active-sash-transition-delay:.5s;box-sizing:border-box;--dv-group-view-background-color:#ebeced;--dv-tabs-and-actions-container-background-color:#fcfcfc;--dv-activegroup-visiblepanel-tab-background-color:#f0f1f2;--dv-activegroup-hiddenpanel-tab-background-color:#fcfcfc;--dv-inactivegroup-visiblepanel-tab-background-color:#f0f1f2;--dv-inactivegroup-hiddenpanel-tab-background-color:#fcfcfc;--dv-tab-divider-color:transparent;--dv-activegroup-visiblepanel-tab-color:#333;--dv-activegroup-hiddenpanel-tab-color:#333;--dv-inactivegroup-visiblepanel-tab-color:#333;--dv-inactivegroup-hiddenpanel-tab-color:#333;--dv-separator-border:transparent;--dv-paneview-header-border-color:#333;background-color:#ebeced;padding:10px}.dockview-theme-replit .dv-drop-target-container .dv-drop-target-anchor.dv-drop-target-anchor-container-changed{opacity:0;transition:none}.dockview-theme-replit .dv-resize-container:has(>.dv-groupview){border-radius:8px}.dockview-theme-replit .dv-resize-container{border:none;border-radius:10px!important}.dockview-theme-replit .dv-groupview{border-radius:10px;overflow:hidden}.dockview-theme-replit .dv-groupview .dv-tabs-and-actions-container{border-bottom:1px solid #80808059}.dockview-theme-replit .dv-groupview .dv-tabs-and-actions-container .dv-tab{border-radius:8px;margin:4px}.dockview-theme-replit .dv-groupview .dv-tabs-and-actions-container .dv-tab .dv-svg{width:8px;height:8px}.dockview-theme-replit .dv-groupview .dv-tabs-and-actions-container .dv-tab:hover{background-color:#e4e5e6!important}.dockview-theme-replit .dv-groupview .dv-content-container{background-color:#fcfcfc}.dockview-theme-replit .dv-groupview.dv-active-group{border:1px solid #80808059}.dockview-theme-replit .dv-groupview.dv-inactive-group{border:1px solid #0000}.dockview-theme-replit .dv-vertical>.dv-sash-container>.dv-sash{background-color:#0000}.dockview-theme-replit .dv-vertical>.dv-sash-container>.dv-sash:not(.disabled):after{content:"";background-color:var(--dv-sash-color);border-radius:2px;width:40px;height:4px;position:absolute;top:50%;left:50%;transform:translate(-50%,-50%)}.dockview-theme-replit .dv-vertical>.dv-sash-container>.dv-sash:not(.disabled):hover,.dockview-theme-replit .dv-vertical>.dv-sash-container>.dv-sash:not(.disabled):active{background-color:#0000}.dockview-theme-replit .dv-vertical>.dv-sash-container>.dv-sash:not(.disabled):hover:after,.dockview-theme-replit .dv-vertical>.dv-sash-container>.dv-sash:not(.disabled):active:after{background-color:var(--dv-active-sash-color)}.dockview-theme-replit .dv-horizontal>.dv-sash-container>.dv-sash{background-color:#0000}.dockview-theme-replit .dv-horizontal>.dv-sash-container>.dv-sash:not(.disabled):after{content:"";background-color:var(--dv-sash-color);border-radius:2px;width:4px;height:40px;position:absolute;top:50%;left:50%;transform:translate(-50%,-50%)}.dockview-theme-replit .dv-horizontal>.dv-sash-container>.dv-sash:not(.disabled):hover,.dockview-theme-replit .dv-horizontal>.dv-sash-container>.dv-sash:not(.disabled):active{background-color:#0000}.dockview-theme-replit .dv-horizontal>.dv-sash-container>.dv-sash:not(.disabled):hover:after,.dockview-theme-replit .dv-horizontal>.dv-sash-container>.dv-sash:not(.disabled):active:after{background-color:var(--dv-active-sash-color)}.dockview-theme-abyss-spaced{--dv-paneview-active-outline-color:dodgerblue;--dv-tabs-and-actions-container-font-size:13px;--dv-tabs-and-actions-container-height:44px;--dv-drag-over-background-color:"";--dv-drag-over-border-color:transparent;--dv-tabs-container-scrollbar-color:#888;--dv-icon-hover-background-color:#5a5d5e4f;--dv-floating-box-shadow:8px 8px 8px 0px #00000080;--dv-overlay-z-index:999;--dv-tab-font-size:12px;--dv-border-radius:20px;--dv-tab-margin:.5rem .25rem;--dv-sash-color:transparent;--dv-active-sash-color:var(--dv-color-abyss-accent);--dv-active-sash-transition-duration:.1s;--dv-active-sash-transition-delay:.5s;box-sizing:border-box;--dv-color-abyss-dark:#0b0611;--dv-color-abyss:#16121f;--dv-color-abyss-light:#201d2b;--dv-color-abyss-lighter:#2a2837;--dv-color-abyss-accent:#5b1ecf;--dv-color-abyss-primary-text:white;--dv-color-abyss-secondary-text:#9497a9;--dv-drag-over-border:2px solid var(--dv-color-abyss-accent);--dv-group-view-background-color:var(--dv-color-abyss-dark);--dv-tabs-and-actions-container-background-color:var(--dv-color-abyss);--dv-activegroup-visiblepanel-tab-background-color:var(--dv-color-abyss-lighter);--dv-activegroup-hiddenpanel-tab-background-color:var(--dv-color-abyss-light);--dv-inactivegroup-visiblepanel-tab-background-color:var(--dv-color-abyss-lighter);--dv-inactivegroup-hiddenpanel-tab-background-color:var(--dv-color-abyss-light);--dv-tab-divider-color:transparent;--dv-activegroup-visiblepanel-tab-color:var(--dv-color-abyss-primary-text);--dv-activegroup-hiddenpanel-tab-color:var(--dv-color-abyss-secondary-text);--dv-inactivegroup-visiblepanel-tab-color:var(--dv-color-abyss-primary-text);--dv-inactivegroup-hiddenpanel-tab-color:var(--dv-color-abyss-secondary-text);--dv-separator-border:transparent;--dv-paneview-header-border-color:#333;background-color:var(--dv-color-abyss-dark);padding:10px}.dockview-theme-abyss-spaced .dv-resize-container:has(>.dv-groupview){border-radius:8px}.dockview-theme-abyss-spaced .dv-sash{border-radius:4px}.dockview-theme-abyss-spaced .dv-drop-target-anchor{border-radius:calc(var(--dv-border-radius) / 4)}.dockview-theme-abyss-spaced .dv-drop-target-anchor.dv-drop-target-content{border-radius:var(--dv-border-radius)}.dockview-theme-abyss-spaced .dv-resize-container{border:none;border-radius:var(--dv-border-radius)!important}.dockview-theme-abyss-spaced .dv-tabs-overflow-container,.dockview-theme-abyss-spaced .dv-tabs-overflow-dropdown-default{border-radius:8px;height:unset!important}.dockview-theme-abyss-spaced .dv-tab{border-radius:8px}.dockview-theme-abyss-spaced .dv-tab .dv-svg{width:8px;height:8px}.dockview-theme-abyss-spaced .dv-groupview{border-radius:var(--dv-border-radius)}.dockview-theme-abyss-spaced .dv-groupview .dv-tabs-and-actions-container{padding:0px calc(var(--dv-border-radius) / 2)}.dockview-theme-abyss-spaced .dv-groupview .dv-content-container{background-color:var(--dv-tabs-and-actions-container-background-color)}.dockview-theme-abyss-spaced .dv-resize-container .dv-groupview{border:2px solid var(--dv-color-abyss-dark)}.dockview-theme-light-spaced{--dv-paneview-active-outline-color:dodgerblue;--dv-tabs-and-actions-container-font-size:13px;--dv-tabs-and-actions-container-height:44px;--dv-drag-over-background-color:"";--dv-drag-over-border-color:transparent;--dv-tabs-container-scrollbar-color:#888;--dv-icon-hover-background-color:#5a5d5e4f;--dv-floating-box-shadow:8px 8px 8px 0px #0000001a;--dv-overlay-z-index:999;--dv-tab-font-size:12px;--dv-border-radius:20px;--dv-tab-margin:.5rem .25rem;--dv-sash-color:transparent;--dv-active-sash-color:#5b1ecf;--dv-active-sash-transition-duration:.1s;--dv-active-sash-transition-delay:.5s;box-sizing:border-box;--dv-drag-over-border:2px solid #5b1ecf;--dv-group-view-background-color:#f6f5f9;--dv-tabs-and-actions-container-background-color:white;--dv-activegroup-visiblepanel-tab-background-color:#ededf0;--dv-activegroup-hiddenpanel-tab-background-color:#f9f9fa;--dv-inactivegroup-visiblepanel-tab-background-color:#ededf0;--dv-inactivegroup-hiddenpanel-tab-background-color:#f9f9fa;--dv-tab-divider-color:transparent;--dv-activegroup-visiblepanel-tab-color:#686b82;--dv-activegroup-hiddenpanel-tab-color:#9497a9;--dv-inactivegroup-visiblepanel-tab-color:#686b82;--dv-inactivegroup-hiddenpanel-tab-color:#9497a9;--dv-separator-border:transparent;--dv-paneview-header-border-color:#333;--dv-scrollbar-background-color:#00000040;background-color:#f6f5f9;padding:10px}.dockview-theme-light-spaced .dv-resize-container:has(>.dv-groupview){border-radius:8px}.dockview-theme-light-spaced .dv-sash{border-radius:4px}.dockview-theme-light-spaced .dv-drop-target-anchor{border-radius:calc(var(--dv-border-radius) / 4)}.dockview-theme-light-spaced .dv-drop-target-anchor.dv-drop-target-content{border-radius:var(--dv-border-radius)}.dockview-theme-light-spaced .dv-resize-container{border:none;border-radius:var(--dv-border-radius)!important}.dockview-theme-light-spaced .dv-tabs-overflow-container,.dockview-theme-light-spaced .dv-tabs-overflow-dropdown-default{border-radius:8px;height:unset!important}.dockview-theme-light-spaced .dv-tab{border-radius:8px}.dockview-theme-light-spaced .dv-tab .dv-svg{width:8px;height:8px}.dockview-theme-light-spaced .dv-groupview{border-radius:var(--dv-border-radius)}.dockview-theme-light-spaced .dv-groupview .dv-tabs-and-actions-container{padding:0px calc(var(--dv-border-radius) / 2)}.dockview-theme-light-spaced .dv-groupview .dv-content-container{background-color:var(--dv-tabs-and-actions-container-background-color)}.dockview-theme-light-spaced .dv-resize-container .dv-groupview{border:2px solid #ffffff1a}.dv-drop-target-container{z-index:9999;pointer-events:none;--dv-transition-duration:.3s;width:100%;height:100%;position:absolute;top:0;left:0;overflow:hidden}.dv-drop-target-container .dv-drop-target-anchor{border:var(--dv-drag-over-border);background-color:var(--dv-drag-over-background-color);opacity:1;will-change:transform, opacity;backface-visibility:hidden;contain:layout paint;transition:opacity var(--dv-transition-duration) ease-in, transform var(--dv-transition-duration) ease-out;position:relative;transform:translate(0,0)}.dv-drop-target{--dv-transition-duration:70ms;position:relative}.dv-drop-target>.dv-drop-target-dropzone{z-index:1000;pointer-events:none;width:100%;height:100%;position:absolute;top:0;left:0}.dv-drop-target>.dv-drop-target-dropzone>.dv-drop-target-selection{box-sizing:border-box;border:var(--dv-drag-over-border);background-color:var(--dv-drag-over-background-color);width:100%;height:100%;transition:top var(--dv-transition-duration) ease-out, left var(--dv-transition-duration) ease-out, width var(--dv-transition-duration) ease-out, height var(--dv-transition-duration) ease-out, opacity var(--dv-transition-duration) ease-out;will-change:transform;pointer-events:none;position:relative}.dv-drop-target>.dv-drop-target-dropzone>.dv-drop-target-selection.dv-drop-target-top.dv-drop-target-small-vertical{border-top:1px solid var(--dv-drag-over-border-color)}.dv-drop-target>.dv-drop-target-dropzone>.dv-drop-target-selection.dv-drop-target-bottom.dv-drop-target-small-vertical{border-bottom:1px solid var(--dv-drag-over-border-color)}.dv-drop-target>.dv-drop-target-dropzone>.dv-drop-target-selection.dv-drop-target-left.dv-drop-target-small-horizontal{border-left:1px solid var(--dv-drag-over-border-color)}.dv-drop-target>.dv-drop-target-dropzone>.dv-drop-target-selection.dv-drop-target-right.dv-drop-target-small-horizontal{border-right:1px solid var(--dv-drag-over-border-color)}.dv-dockview{background-color:var(--dv-group-view-background-color);contain:layout;position:relative}.dv-dockview .dv-watermark-container{z-index:1;width:100%;height:100%;position:absolute;top:0;left:0}.dv-dockview .dv-overlay-render-container{position:relative}.dv-groupview.dv-active-group>.dv-tabs-and-actions-container .dv-tabs-container>.dv-tab.dv-active-tab{background-color:var(--dv-activegroup-visiblepanel-tab-background-color);color:var(--dv-activegroup-visiblepanel-tab-color)}.dv-groupview.dv-active-group>.dv-tabs-and-actions-container .dv-tabs-container>.dv-tab.dv-inactive-tab{background-color:var(--dv-activegroup-hiddenpanel-tab-background-color);color:var(--dv-activegroup-hiddenpanel-tab-color)}.dv-groupview.dv-inactive-group>.dv-tabs-and-actions-container .dv-tabs-container>.dv-tab.dv-active-tab{background-color:var(--dv-inactivegroup-visiblepanel-tab-background-color);color:var(--dv-inactivegroup-visiblepanel-tab-color)}.dv-groupview.dv-inactive-group>.dv-tabs-and-actions-container .dv-tabs-container>.dv-tab.dv-inactive-tab{background-color:var(--dv-inactivegroup-hiddenpanel-tab-background-color);color:var(--dv-inactivegroup-hiddenpanel-tab-color)}.dv-tab.dv-tab-dragging{background-color:var(--dv-activegroup-visiblepanel-tab-background-color);color:var(--dv-activegroup-visiblepanel-tab-color)}.dv-groupview{background-color:var(--dv-group-view-background-color);flex-direction:column;height:100%;display:flex;overflow:hidden}.dv-groupview:focus{outline:none}.dv-groupview>.dv-content-container{outline:none;flex-grow:1;min-height:0}.dv-root-wrapper,.dv-grid-view,.dv-branch-node{width:100%;height:100%}.dv-debug .dv-resize-container .dv-resize-handle-top{background-color:red}.dv-debug .dv-resize-container .dv-resize-handle-bottom{background-color:green}.dv-debug .dv-resize-container .dv-resize-handle-left{background-color:#ff0}.dv-debug .dv-resize-container .dv-resize-handle-right{background-color:#00f}.dv-debug .dv-resize-container .dv-resize-handle-topleft,.dv-debug .dv-resize-container .dv-resize-handle-topright,.dv-debug .dv-resize-container .dv-resize-handle-bottomleft,.dv-debug .dv-resize-container .dv-resize-handle-bottomright{background-color:#0ff}.dv-resize-container{--dv-overlay-z-index:var(--dv-overlay-z-index,999);z-index:calc(var(--dv-overlay-z-index) - 2);border:1px solid var(--dv-tab-divider-color);box-shadow:var(--dv-floating-box-shadow);will-change:transform, opacity;backface-visibility:hidden;position:absolute;transform:translate(0,0)}.dv-resize-container.dv-hidden{display:none}.dv-resize-container.dv-resize-container-dragging{opacity:.5;will-change:transform, opacity}.dv-resize-container .dv-resize-handle-top{width:calc(100% - 8px);height:4px;z-index:var(--dv-overlay-z-index);cursor:ns-resize;position:absolute;top:-2px;left:4px}.dv-resize-container .dv-resize-handle-bottom{width:calc(100% - 8px);height:4px;z-index:var(--dv-overlay-z-index);cursor:ns-resize;position:absolute;bottom:-2px;left:4px}.dv-resize-container .dv-resize-handle-left{width:4px;height:calc(100% - 8px);z-index:var(--dv-overlay-z-index);cursor:ew-resize;position:absolute;top:4px;left:-2px}.dv-resize-container .dv-resize-handle-right{width:4px;height:calc(100% - 8px);z-index:var(--dv-overlay-z-index);cursor:ew-resize;position:absolute;top:4px;right:-2px}.dv-resize-container .dv-resize-handle-topleft{width:4px;height:4px;z-index:var(--dv-overlay-z-index);cursor:nw-resize;position:absolute;top:-2px;left:-2px}.dv-resize-container .dv-resize-handle-topright{width:4px;height:4px;z-index:var(--dv-overlay-z-index);cursor:ne-resize;position:absolute;top:-2px;right:-2px}.dv-resize-container .dv-resize-handle-bottomleft{width:4px;height:4px;z-index:var(--dv-overlay-z-index);cursor:sw-resize;position:absolute;bottom:-2px;left:-2px}.dv-resize-container .dv-resize-handle-bottomright{width:4px;height:4px;z-index:var(--dv-overlay-z-index);cursor:se-resize;position:absolute;bottom:-2px;right:-2px}.dv-render-overlay{--dv-overlay-z-index:var(--dv-overlay-z-index,999);z-index:1;contain:layout paint;isolation:isolate;will-change:transform;backface-visibility:hidden;width:100%;height:100%;position:absolute;transform:translate(0,0)}.dv-render-overlay.dv-render-overlay-float{z-index:calc(var(--dv-overlay-z-index) - 1)}.dv-debug .dv-render-overlay{outline-offset:-1;outline:1px solid red}.dv-pane-container{width:100%;height:100%}.dv-pane-container.dv-animated .dv-view{will-change:transform;backface-visibility:hidden;transition:transform .15s ease-out;transform:translate(0,0)}.dv-pane-container .dv-view{flex-direction:column;display:flex;overflow:hidden;padding:0!important}.dv-pane-container .dv-view:not(:first-child):before{background-color:#0000!important}.dv-pane-container .dv-view:not(:first-child) .dv-pane>.dv-pane-header{border-top:1px solid var(--dv-paneview-header-border-color)}.dv-pane-container .dv-view .dv-default-header{background-color:var(--dv-group-view-background-color);color:var(--dv-activegroup-visiblepanel-tab-color);cursor:pointer;padding:0 8px;display:flex}.dv-pane-container .dv-view .dv-default-header .dv-pane-header-icon{justify-content:center;align-items:center;display:flex}.dv-pane-container .dv-view .dv-default-header>span{flex-grow:1;padding-left:8px}.dv-pane-container:first-of-type>.dv-pane>.dv-pane-header{border-top:none!important}.dv-pane-container .dv-pane{flex-direction:column;height:100%;display:flex;overflow:hidden}.dv-pane-container .dv-pane .dv-pane-header{box-sizing:border-box;-webkit-user-select:none;user-select:none;outline:none;position:relative}.dv-pane-container .dv-pane .dv-pane-header.dv-pane-draggable{cursor:pointer}.dv-pane-container .dv-pane .dv-pane-header:focus:before,.dv-pane-container .dv-pane .dv-pane-header:focus-within:before{z-index:5;content:"";pointer-events:none;outline-offset:-1px;outline:-1px solid;outline-color:var(--dv-paneview-active-outline-color);width:100%;height:100%;position:absolute;top:0;left:0}.dv-pane-container .dv-pane .dv-pane-body{outline:none;flex-grow:1;position:relative;overflow:hidden auto}.dv-pane-container .dv-pane .dv-pane-body:focus:before,.dv-pane-container .dv-pane .dv-pane-body:focus-within:before{z-index:5;content:"";pointer-events:none;outline-offset:-1px;outline:-1px solid;outline-color:var(--dv-paneview-active-outline-color);width:100%;height:100%;position:absolute;top:0;left:0}.dv-debug .dv-split-view-container .dv-sash-container .dv-sash.dv-enabled{background-color:#000}.dv-debug .dv-split-view-container .dv-sash-container .dv-sash.dv-disabled{background-color:orange}.dv-debug .dv-split-view-container .dv-sash-container .dv-sash.dv-maximum{background-color:green}.dv-debug .dv-split-view-container .dv-sash-container .dv-sash.dv-minimum{background-color:red}.dv-split-view-container{width:100%;height:100%;position:relative;overflow:hidden}.dv-split-view-container.dv-splitview-disabled>.dv-sash-container>.dv-sash{pointer-events:none}.dv-split-view-container.dv-animation .dv-view,.dv-split-view-container.dv-animation .dv-sash{will-change:transform;backface-visibility:hidden;transition:transform .15s ease-out;transform:translate(0,0)}.dv-split-view-container.dv-horizontal{height:100%}.dv-split-view-container.dv-horizontal>.dv-sash-container>.dv-sash{width:4px;height:100%}.dv-split-view-container.dv-horizontal>.dv-sash-container>.dv-sash.dv-enabled{cursor:ew-resize}.dv-split-view-container.dv-horizontal>.dv-sash-container>.dv-sash.dv-disabled{cursor:default}.dv-split-view-container.dv-horizontal>.dv-sash-container>.dv-sash.dv-maximum{cursor:w-resize}.dv-split-view-container.dv-horizontal>.dv-sash-container>.dv-sash.dv-minimum{cursor:e-resize}.dv-split-view-container.dv-horizontal>.dv-view-container>.dv-view:not(:first-child):before{width:1px;height:100%}.dv-split-view-container.dv-vertical{width:100%}.dv-split-view-container.dv-vertical>.dv-sash-container>.dv-sash{width:100%;height:4px}.dv-split-view-container.dv-vertical>.dv-sash-container>.dv-sash.dv-enabled{cursor:ns-resize}.dv-split-view-container.dv-vertical>.dv-sash-container>.dv-sash.dv-disabled{cursor:default}.dv-split-view-container.dv-vertical>.dv-sash-container>.dv-sash.dv-maximum{cursor:n-resize}.dv-split-view-container.dv-vertical>.dv-sash-container>.dv-sash.dv-minimum{cursor:s-resize}.dv-split-view-container.dv-vertical>.dv-view-container>.dv-view{width:100%}.dv-split-view-container.dv-vertical>.dv-view-container>.dv-view:not(:first-child):before{width:100%;height:1px}.dv-split-view-container .dv-sash-container{width:100%;height:100%;position:absolute}.dv-split-view-container .dv-sash-container .dv-sash{z-index:99;-webkit-user-select:none;user-select:none;touch-action:none;background-color:var(--dv-sash-color,transparent);outline:none;position:absolute}.dv-split-view-container .dv-sash-container .dv-sash:not(.disabled):active,.dv-split-view-container .dv-sash-container .dv-sash:not(.disabled):hover{background-color:var(--dv-active-sash-color,transparent);transition-property:background-color;transition-timing-function:ease-in-out;transition-duration:var(--dv-active-sash-transition-duration,.1s);transition-delay:var(--dv-active-sash-transition-delay,.5s)}.dv-split-view-container .dv-view-container{width:100%;height:100%;position:relative}.dv-split-view-container .dv-view-container .dv-view{box-sizing:border-box;height:100%;position:absolute;overflow:auto}.dv-split-view-container.dv-separator-border .dv-view:not(:first-child):before{content:" ";z-index:5;pointer-events:none;background-color:var(--dv-separator-border);position:absolute;top:0;left:0}.dv-dragged{transform:translate(0,0)}.dv-tab{flex-shrink:0}.dv-tab:focus-within,.dv-tab:focus{position:relative}.dv-tab:focus-within:after,.dv-tab:focus:after{content:"";pointer-events:none;outline-offset:-1px;z-index:5;width:100%;height:100%;position:absolute;top:0;left:0;outline:1px solid var(--dv-tab-divider-color)!important}.dv-tab.dv-tab-dragging .dv-default-tab-action{background-color:var(--dv-activegroup-visiblepanel-tab-color)}.dv-tab.dv-active-tab .dv-default-tab .dv-default-tab-action{visibility:visible}.dv-tab.dv-inactive-tab .dv-default-tab .dv-default-tab-action{visibility:hidden}.dv-tab.dv-inactive-tab .dv-default-tab:hover .dv-default-tab-action{visibility:visible}.dv-tab .dv-default-tab{white-space:nowrap;text-overflow:ellipsis;align-items:center;height:100%;display:flex;position:relative}.dv-tab .dv-default-tab .dv-default-tab-content{flex-grow:1;margin-right:4px}.dv-tab .dv-default-tab .dv-default-tab-action{box-sizing:border-box;justify-content:center;align-items:center;padding:4px;display:flex}.dv-tab .dv-default-tab .dv-default-tab-action:hover{background-color:var(--dv-icon-hover-background-color);border-radius:2px}.dv-tabs-overflow-dropdown-default{height:100%;color:var(--dv-activegroup-hiddenpanel-tab-color);margin:var(--dv-tab-margin);cursor:pointer;flex-shrink:0;align-items:center;padding:.25rem .5rem;display:flex}.dv-tabs-overflow-dropdown-default>span{padding-left:.25rem}.dv-tabs-overflow-dropdown-default>svg{transform:rotate(90deg)}.dv-tabs-container{scrollbar-width:thin;will-change:scroll-position;height:100%;display:flex;overflow:auto;transform:translate(0,0)}.dv-tabs-container.dv-horizontal .dv-tab:not(:first-child):before{content:" ";z-index:5;pointer-events:none;background-color:var(--dv-tab-divider-color);width:1px;height:100%;position:absolute;top:0;left:0}.dv-tabs-container::-webkit-scrollbar{height:3px}.dv-tabs-container::-webkit-scrollbar-track{background:0 0}.dv-tabs-container::-webkit-scrollbar-thumb{background:var(--dv-tabs-container-scrollbar-color)}.dv-scrollable>.dv-tabs-container{overflow:hidden}.dv-tab{-webkit-user-drag:element;cursor:pointer;box-sizing:border-box;font-size:var(--dv-tab-font-size);margin:var(--dv-tab-margin);outline:none;padding:.25rem .5rem;position:relative}.dv-tabs-overflow-container{height:unset;border:1px solid var(--dv-tab-divider-color);background-color:var(--dv-group-view-background-color);flex-direction:column}.dv-tabs-overflow-container .dv-tab:not(:last-child){border-bottom:1px solid var(--dv-tab-divider-color)}.dv-tabs-overflow-container .dv-active-tab{background-color:var(--dv-activegroup-visiblepanel-tab-background-color);color:var(--dv-activegroup-visiblepanel-tab-color)}.dv-tabs-overflow-container .dv-inactive-tab{background-color:var(--dv-activegroup-hiddenpanel-tab-background-color);color:var(--dv-activegroup-hiddenpanel-tab-color)}.dv-tabs-and-actions-container{background-color:var(--dv-tabs-and-actions-container-background-color);box-sizing:border-box;height:var(--dv-tabs-and-actions-container-height);font-size:var(--dv-tabs-and-actions-container-font-size);flex-shrink:0;display:flex}.dv-tabs-and-actions-container.dv-single-tab.dv-full-width-single-tab .dv-scrollable,.dv-tabs-and-actions-container.dv-single-tab.dv-full-width-single-tab .dv-tabs-container{flex-grow:1}.dv-tabs-and-actions-container.dv-single-tab.dv-full-width-single-tab .dv-tabs-container .dv-tab{flex-grow:1;padding:0}.dv-tabs-and-actions-container.dv-single-tab.dv-full-width-single-tab .dv-void-container{flex-grow:0}.dv-tabs-and-actions-container .dv-void-container{flex-grow:1;display:flex}.dv-tabs-and-actions-container .dv-void-container.dv-draggable{cursor:grab}.dv-tabs-and-actions-container .dv-right-actions-container{display:flex}.dv-watermark{height:100%;display:flex}.castle-file-panel,.castle-code-panel{--castle-font-mono:"SFMono-Regular", Consolas, "Liberation Mono", monospace;--castle-black:var(--v2-ink);--castle-panel-raised:var(--v2-raised);--castle-border:#444;--castle-text:var(--v2-white);--castle-text-dim:var(--v2-muted);--castle-inspector-bg:var(--v2-surface);--castle-inspector-text:var(--v2-fg);--castle-inspector-muted:var(--v2-muted);--castle-inspector-border:var(--v2-border);--castle-inspector-divider:var(--v2-border);--castle-inspector-input-bg:var(--v2-raised);--castle-workspace-bg:var(--v2-surface);--castle-sheet-bg:var(--v2-surface);--castle-radius:4px}.castle-file-panel{background:var(--castle-sheet-bg);flex-direction:column;height:100%;display:flex;overflow:hidden;transform:translateZ(0)}.castle-file-panel>.fileBrowserBare{flex:1 1 0;height:auto;min-height:0}.castle-file-toolbar{border-bottom:1px solid var(--castle-inspector-border);flex-wrap:wrap;flex:none;align-items:center;gap:6px;padding:6px 8px;display:flex}.castle-file-new-btn{color:#e6e6e6;cursor:pointer;background:#2f2f2f;border:1px solid #4a4a4a;border-radius:4px;align-items:center;gap:6px;padding:4px 10px;font-size:13px;display:inline-flex}.castle-file-new-btn:hover{background:#3c3c3c}.castle-file-new-btn svg{width:12px;height:12px}.castle-file-icon-btn{color:#b0b0b0;cursor:pointer;background:#2f2f2f;border:1px solid #4a4a4a;border-radius:4px;justify-content:center;align-items:center;width:28px;height:26px;margin-left:auto;display:inline-flex}.castle-file-icon-btn:hover{color:#e6e6e6;background:#3c3c3c}.castle-file-icon-btn.active{color:#dbe6f5;background:#37506f;border-color:#4a6b95}.castle-file-icon-btn svg{width:14px;height:14px}.castle-file-action-error{color:#e86a73;background:#2a1414;flex:none;justify-content:space-between;align-items:center;gap:8px;padding:5px 10px;font-size:12px;display:flex}.castle-file-action-error button{color:inherit;cursor:pointer;background:0 0;border:0;font-size:15px;line-height:1}.fileEditRow{cursor:default}.fileEditInput{border:1px solid var(--castle-border);background:var(--castle-inspector-input-bg);min-width:0;color:var(--castle-inspector-text);font:inherit;border-radius:3px;flex:auto;padding:1px 4px;font-size:13px}.fileEditInput:focus{border-color:#5a8bd6;outline:none}.fileEditSuffix{color:var(--castle-text-dim);flex:none;font-size:13px}.fileEditError{padding:2px 0 0 calc(20px + var(--file-depth,0) * 20px);color:#e86a73;flex:1 0 100%;font-size:11px}.castle-file-menu{z-index:1000;background:#232323;border:1px solid #3a3a3a;border-radius:6px;min-width:168px;padding:4px;position:fixed;box-shadow:0 8px 24px #0000008c}.castle-file-menu-item{color:#e6e6e6;text-align:left;cursor:pointer;background:0 0;border:0;border-radius:4px;align-items:center;gap:8px;width:100%;padding:6px 8px;font-size:13px;display:flex}.castle-file-menu-item:hover:not(:disabled){background:#3a3a3a}.castle-file-menu-item:disabled{opacity:.4;cursor:default}.castle-file-menu-item.danger{color:#e86a73}.castle-file-menu-item.danger:hover{background:#3a2222}.castle-file-menu-item-icon{color:#b0b0b0;flex:0 0 14px;justify-content:center;align-items:center;width:14px;display:inline-flex}.castle-file-menu-item.danger .castle-file-menu-item-icon{color:inherit}.castle-file-menu-item-icon svg{width:13px;height:13px}.castle-file-menu-confirm{min-width:180px;padding:6px 8px}.castle-file-menu-confirm-text{color:#e6e6e6;margin-bottom:8px;font-size:13px}.castle-file-menu-confirm-actions{justify-content:flex-end;gap:6px;display:flex}.castle-file-menu-confirm-actions button{color:#e6e6e6;cursor:pointer;background:#333;border:1px solid #4a4a4a;border-radius:4px;padding:4px 10px;font-size:12px}.castle-file-menu-confirm-actions button:hover{background:#404040}.castle-file-menu-confirm-actions button.danger{color:#fff;background:#a02828;border-color:#a02828}.castle-file-menu-confirm-actions button.danger:hover{background:#b83030}.castle-file-menu-item-label{text-overflow:ellipsis;white-space:nowrap;flex:auto;min-width:0;overflow:hidden}.castle-file-menu-check{color:#7fd08a;flex:none;font-size:12px}.castle-file-menu-keys{color:gray;white-space:nowrap;flex:none;margin-left:16px;font-family:SFMono-Regular,Consolas,monospace;font-size:11px}.castle-file-menu-item:disabled .castle-file-menu-keys{color:inherit}.castle-file-menu-header{color:#9a9a9a;text-transform:uppercase;letter-spacing:.04em;padding:5px 8px 6px;font-size:11px}.castle-file-menu-sep{background:#3a3a3a;height:1px;margin:4px 2px}.castle-file-menu-error{color:#e86a73;padding:4px 8px;font-size:11px}.castle-file-picker{min-width:180px;max-height:min(60vh,420px);overflow-y:auto}.castle-file-newfolder{align-items:center;gap:6px;padding:4px 6px;display:flex}.castle-file-newfolder .fileEditInput{flex:auto}.castle-file-newfolder-btn{color:#e6e6e6;cursor:pointer;background:#333;border:1px solid #4a4a4a;border-radius:4px;flex:none;padding:3px 10px;font-size:12px}.castle-file-newfolder-btn:hover{background:#404040}.castle-file-newfolder-btn:disabled{opacity:.5;cursor:default}.fileBrowserBare{flex-direction:column;min-width:0;height:100%;display:flex}.fileTree{flex:1 1 0;min-height:0;padding-top:5px;overflow-y:auto}.fileBranch{min-width:0}.fileRow,.fileDirRow{border-radius:var(--castle-radius);width:100%;color:var(--v2-secondary);padding:5px 9px 5px calc(9px + var(--file-depth,0) * 20px);text-align:left;cursor:pointer;background:0 0;border:0;justify-content:flex-start;align-items:center;gap:6px;font-size:14px;display:flex}.fileDirRow{color:var(--v2-muted)}.fileRow:hover,.fileDirRow:hover{background:var(--castle-sheet-bg);color:var(--castle-inspector-text)}.fileRow.fileRowImported{color:var(--v2-muted);font-style:italic}.fileRow.fileRowSelected,.fileRow.fileRowSelected:hover{background:var(--castle-panel-raised);color:var(--castle-inspector-text)}.fileIcon.fileDisclosure{color:var(--v2-placeholder)}.fileDirRow:hover .fileIcon.fileDisclosure{color:inherit}.fileDisclosure svg{width:10px;height:10px}.fileLabel{flex:auto;align-items:center;gap:6px;min-width:0;display:inline-flex}.fileIcon{width:14px;color:var(--castle-inspector-muted);flex:0 0 14px;justify-content:center;align-items:center;font-size:14px;display:inline-flex}.castle-code-panel{width:100%;height:100%;position:relative}.mainEditor{background:var(--castle-sheet-bg);flex-direction:column;width:100%;min-width:0;height:100%;min-height:0;display:flex}.editorBody{flex:1;min-height:0;display:flex;overflow:hidden;container:editor/inline-size}.codeEditor{background:var(--castle-workspace-bg);flex:1;grid-template-columns:1fr;min-width:0;min-height:0;display:grid}.codeMirrorHost{min-width:0;height:100%;min-height:0}.castle-code-overlay{color:var(--castle-inspector-muted);pointer-events:none;font-size:12px;position:absolute;top:10px;left:12px}.castle-code-overlay.castle-code-error{color:var(--v2-error)}.castle-code-savebar{background:var(--v2-error-bg);color:var(--v2-error);padding:4px 10px;font-size:11px;position:absolute;bottom:0;left:0;right:0}.castle-tab-import{color:var(--v2-muted);font-style:italic}.fileImportUpdate{color:var(--castle-inspector-text);align-items:center;margin-left:6px;font-size:11px;display:inline-flex}.castle-modal-scrim{z-index:1000;background:#00000080;justify-content:center;align-items:center;display:flex;position:fixed;inset:0}.castle-modal{color:#e8e8e8;background:#232323;border:1px solid #3a3a3a;border-radius:6px;min-width:260px;max-width:380px;padding:16px;font-size:13px;box-shadow:0 8px 24px #0000008c}.castle-modal-text{margin-bottom:14px}.castle-modal-actions{justify-content:flex-end;gap:8px;margin-top:16px;display:flex}.castle-modal-actions button,.castle-import-link-row button{color:#e8e8e8;cursor:pointer;background:#2e2e2e;border:1px solid #3a3a3a;border-radius:4px;padding:5px 12px;font-size:12px}.castle-modal-actions button:hover:not(:disabled),.castle-import-link-row button:hover:not(:disabled){background:#383838}.castle-modal-actions button:disabled,.castle-import-link-row button:disabled{opacity:.6;cursor:default}.castle-upload-modal{flex-direction:column;gap:10px;width:min(460px,100vw - 24px);max-width:none;max-height:calc(100vh - 32px);display:flex;overflow-y:auto}.castle-upload-modal>.castle-modal-text{margin-bottom:0}.castle-upload-input{opacity:0;pointer-events:none;width:1px;height:1px;position:absolute}.castle-upload-drop{color:#e8e8e8;cursor:pointer;background:#2a2a2a;border:1px dashed #4a4a4a;border-radius:6px;flex-direction:column;justify-content:center;align-items:center;gap:4px;padding:22px 12px;font-size:13px;display:flex}.castle-upload-drop:hover,.castle-upload-drop.over{border-color:var(--castle-accent,#6c8cff);background:#313131}.castle-upload-drop svg{opacity:.8;width:18px;height:18px}.castle-upload-drop-label{font-weight:500}.castle-upload-drop-hint{opacity:.6;font-size:11px}.castle-upload-picked{border:1px solid #3a3a3a;border-radius:4px;flex-direction:column;max-height:132px;display:flex;overflow-y:auto}.castle-upload-picked-row{align-items:center;gap:8px;padding:6px 8px;font-size:12px;display:flex}.castle-upload-picked-row+.castle-upload-picked-row{border-top:1px solid #333}.castle-upload-picked-name{text-overflow:ellipsis;white-space:nowrap;flex:auto;min-width:0;overflow:hidden}.castle-upload-picked-warning{color:#e8b25a;white-space:normal;margin-top:2px;font-size:11px;display:block}.castle-upload-picked-size{opacity:.6;font-variant-numeric:tabular-nums;flex:none}.castle-upload-picked-remove{width:22px;height:22px;color:inherit;cursor:pointer;background:0 0;border:0;border-radius:4px;flex:none;font-size:15px;line-height:1}.castle-upload-picked-remove:hover:not(:disabled){background:#3a3a3a}.castle-upload-dest{flex-direction:column;gap:6px;display:flex}.castle-upload-dest-label{text-transform:uppercase;letter-spacing:.04em;opacity:.6;font-size:11px}.castle-upload-folders{border:1px solid #3a3a3a;border-radius:4px;flex-direction:column;max-height:168px;display:flex;overflow-y:auto}.castle-upload-folder{color:#e8e8e8;text-align:left;cursor:pointer;background:0 0;border:0;align-items:center;gap:8px;padding:9px 10px;font-size:12px;display:flex}.castle-upload-folder+.castle-upload-folder{border-top:1px solid #333}.castle-upload-folder:hover:not(:disabled){background:#303030}.castle-upload-folder.active{background:#35405e}.castle-upload-folder svg{opacity:.7;flex:none;width:12px;height:12px}.castle-upload-folder-name{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.castle-upload-newfolder-btn{color:#e8e8e8;cursor:pointer;background:#2e2e2e;border:1px solid #3a3a3a;border-radius:4px;align-items:center;gap:8px;padding:8px 10px;font-size:12px;display:flex}.castle-upload-newfolder-btn:hover:not(:disabled){background:#383838}.castle-upload-newfolder-btn svg{opacity:.7;width:12px;height:12px}.castle-upload-newfolder{gap:6px;display:flex}.castle-upload-status{text-overflow:ellipsis;white-space:nowrap;opacity:.7;text-align:left;flex:auto;min-width:0;font-size:12px;overflow:hidden}@media (width<=520px){.castle-upload-modal{width:calc(100vw - 16px);min-width:0;padding:12px}.castle-upload-drop{padding:18px 10px}.castle-upload-picked{max-height:104px}.castle-upload-folders{max-height:132px}.castle-upload-folder{padding:11px 10px;font-size:13px}}.castle-import-modal{flex-direction:column;width:min(520px,100vw - 32px);max-width:none;height:min(560px,100vh - 64px);max-height:none;display:flex}.castle-import-modal>.castle-modal-text,.castle-import-modal>.castle-key-tabs,.castle-import-modal>.castle-import-select-bar,.castle-import-modal>.castle-import-filter,.castle-import-modal>.castle-import-note,.castle-import-modal>.castle-import-error,.castle-import-modal>.castle-modal-actions{flex:none}.castle-import-select-bar{align-items:center;gap:10px;margin-bottom:8px;display:flex}.castle-import-select-all{padding:4px 8px}.castle-import-update-row{align-items:center}.castle-import-tick{color:#1b1b1b;border:1px solid #5a5a5a;border-radius:3px;flex:none;justify-content:center;align-items:center;width:16px;height:16px;font-size:10px;display:flex}.castle-import-tick.checked{background:#8ab4f8;border-color:#8ab4f8}.castle-import-filter{margin-bottom:8px}.castle-import-empty{color:#9a9a9a;text-align:center;flex:auto;justify-content:center;align-items:center;min-height:0;padding:10px;font-size:11px;display:flex}.castle-import-tabs .castle-key-tab{min-height:34px}.castle-import-list{background:#1b1b1b;border:1px solid #3a3a3a;border-radius:4px;flex:auto;min-height:0;overflow-y:auto}.castle-import-row{color:#e8e8e8;width:100%;font:inherit;text-align:left;cursor:pointer;background:0 0;border:0;border-bottom:1px solid #2e2e2e;gap:10px;padding:8px;font-size:12px;display:flex}.castle-import-row:last-child{border-bottom:0}.castle-import-row:hover{background:#262626}.castle-import-row.selected{background:#3a3a3a}.castle-import-row.disabled{opacity:.5}.castle-import-thumb{object-fit:cover;background:#2e2e2e;border-radius:3px;flex:none;width:56px;height:79px}.castle-import-row-text{flex-direction:column;gap:3px;min-width:0;display:flex}.castle-import-row-title{white-space:nowrap;text-overflow:ellipsis;overflow:hidden}.castle-import-row-meta{color:#9a9a9a;font-size:11px}.castle-import-link{flex-direction:column;flex:auto;gap:8px;min-height:0;display:flex}.castle-import-link-row{gap:8px;display:flex}.castle-import-link-row button{white-space:nowrap}.castle-import-note{color:#9a9a9a;padding:10px 2px;font-size:11px}.castle-import-error{color:#ff8f8f;margin-top:8px;font-size:11px}.xterm{cursor:text;-webkit-user-select:none;user-select:none;position:relative}.xterm.focus,.xterm:focus{outline:none}.xterm .xterm-helpers{z-index:5;position:absolute;top:0}.xterm .xterm-helper-textarea{opacity:0;z-index:-5;white-space:nowrap;resize:none;border:0;width:0;height:0;margin:0;padding:0;position:absolute;top:0;left:-9999em;overflow:hidden}.xterm .composition-view{color:#fff;white-space:nowrap;z-index:1;background:#000;display:none;position:absolute}.xterm .composition-view.active{display:block}.xterm .xterm-viewport{cursor:default;background-color:#000;position:absolute;inset:0;overflow-y:scroll}.xterm .xterm-screen{position:relative}.xterm .xterm-screen canvas{position:absolute;top:0;left:0}.xterm-char-measure-element{visibility:hidden;line-height:normal;display:inline-block;position:absolute;top:0;left:-9999em}.xterm.enable-mouse-events{cursor:default}.xterm.xterm-cursor-pointer,.xterm .xterm-cursor-pointer{cursor:pointer}.xterm.column-select.focus{cursor:crosshair}.xterm .xterm-accessibility:not(.debug),.xterm .xterm-message{z-index:10;color:#0000;pointer-events:none;position:absolute;inset:0}.xterm .xterm-accessibility-tree:not(.debug) ::selection{color:#0000}.xterm .xterm-accessibility-tree{-webkit-user-select:text;user-select:text;white-space:pre;font-family:monospace}.xterm .xterm-accessibility-tree>div{transform-origin:0;width:fit-content}.xterm .live-region{width:1px;height:1px;position:absolute;left:-9999px;overflow:hidden}.xterm-dim{opacity:1!important}.xterm-underline-1{text-decoration:underline}.xterm-underline-2{-webkit-text-decoration:underline double;text-decoration:underline double}.xterm-underline-3{-webkit-text-decoration:underline wavy;text-decoration:underline wavy}.xterm-underline-4{-webkit-text-decoration:underline dotted;text-decoration:underline dotted}.xterm-underline-5{-webkit-text-decoration:underline dashed;text-decoration:underline dashed}.xterm-overline{text-decoration:overline}.xterm-overline.xterm-underline-1{text-decoration:underline overline}.xterm-overline.xterm-underline-2{-webkit-text-decoration:overline double underline;text-decoration:overline double underline}.xterm-overline.xterm-underline-3{-webkit-text-decoration:overline wavy underline;text-decoration:overline wavy underline}.xterm-overline.xterm-underline-4{-webkit-text-decoration:overline dotted underline;text-decoration:overline dotted underline}.xterm-overline.xterm-underline-5{-webkit-text-decoration:overline dashed underline;text-decoration:overline dashed underline}.xterm-strikethrough{text-decoration:line-through}.xterm-screen .xterm-decoration-container .xterm-decoration{z-index:6;position:absolute}.xterm-screen .xterm-decoration-container .xterm-decoration.xterm-decoration-top-layer{z-index:7}.xterm-decoration-overview-ruler{z-index:8;pointer-events:none;position:absolute;top:0;right:0}.xterm-decoration-top{z-index:2;position:relative}.xterm .xterm-scrollable-element>.scrollbar{cursor:default}.xterm .xterm-scrollable-element>.scrollbar>.scra{cursor:pointer;font-size:11px!important}.xterm .xterm-scrollable-element>.visible{opacity:1;z-index:11;background:0 0;transition:opacity .1s linear}.xterm .xterm-scrollable-element>.invisible{opacity:0;pointer-events:none}.xterm .xterm-scrollable-element>.invisible.fade{transition:opacity .8s linear}.xterm .xterm-scrollable-element>.shadow{display:none;position:absolute}.xterm .xterm-scrollable-element>.shadow.top{width:100%;height:3px;box-shadow:var(--vscode-scrollbar-shadow,#000) 0 6px 6px -6px inset;display:block;top:0;left:3px}.xterm .xterm-scrollable-element>.shadow.left{width:3px;height:100%;box-shadow:var(--vscode-scrollbar-shadow,#000) 6px 0 6px -6px inset;display:block;top:3px;left:0}.xterm .xterm-scrollable-element>.shadow.top-left-corner{width:3px;height:3px;display:block;top:0;left:0}.xterm .xterm-scrollable-element>.shadow.top.left{box-shadow:var(--vscode-scrollbar-shadow,#000) 6px 0 6px -6px inset}.flow-root{--flow-gutter:#000;--flow-surface:#0d0d0d;--flow-raised:#161616;--flow-hover:#1d1d1d;--flow-fg:#e6e6e6;--flow-secondary:#b3b3b3;--flow-muted:#888;--flow-border:#2a2a2a;--flow-border-active:#5a5a5a;--flow-gap:12px;--flow-dock-h:36px;--flow-radius:8px;background:var(--flow-gutter);color:var(--flow-fg);flex-direction:column;font:13px ui-sans-serif,system-ui,-apple-system,sans-serif;display:flex;position:fixed;inset:0;overflow:hidden}.flow-root *{box-sizing:border-box}body.flow-reordering,body.flow-reordering *{-webkit-user-select:none!important;user-select:none!important;cursor:grabbing!important}.flow-topbar{top:var(--flow-gap);left:var(--flow-gap);right:var(--flow-gap);height:var(--flow-dock-h);z-index:40;pointer-events:none;grid-template-columns:minmax(0,1fr) minmax(0,auto) minmax(0,1fr);align-items:center;column-gap:10px;display:grid;position:absolute}.flow-topbar-leading{pointer-events:none;justify-self:start;align-items:center;gap:8px;min-width:0;display:flex}.flow-topbar-leading>*{pointer-events:auto}.flow-castle-wrap{flex-shrink:0;position:relative}.flow-castle-btn{width:var(--flow-dock-h);height:var(--flow-dock-h);color:var(--flow-fg);border:1px solid var(--flow-border);cursor:pointer;background:#000;border-radius:10px;justify-content:center;align-items:center;display:flex;box-shadow:0 8px 24px -12px #000000d9}.flow-castle-btn:hover{background:#111}.flow-menu-backdrop{z-index:49;position:fixed;inset:0}.flow-castle-menu{top:calc(var(--flow-dock-h) + 6px);z-index:50;background:#121212;border:1px solid #2e2e2e;border-radius:8px;flex-direction:column;min-width:170px;padding:4px;display:flex;position:absolute;left:0;box-shadow:0 8px 24px #00000080}.flow-castle-menu button{color:var(--flow-fg);cursor:pointer;text-align:left;font:inherit;background:0 0;border:none;border-radius:6px;align-items:center;padding:8px 10px;font-size:13px;display:flex}.flow-castle-menu button:hover{background:var(--flow-hover)}.flow-castle-menu button:disabled{opacity:.5;cursor:default}.flow-menu-sep{background:var(--flow-border);height:1px;margin:4px 6px}.flow-menu-narrow{display:none}.flow-deck-identity{min-height:var(--flow-dock-h);max-width:260px;color:var(--flow-fg);cursor:pointer;font:inherit;background:0 0;border:1px solid #0000;border-radius:10px;align-items:center;gap:6px;padding:0 10px;font-size:13px;font-weight:600;display:flex}.flow-deck-identity:hover{background:#ffffff0f;border-color:#ffffff14}.flow-deck-vis{color:var(--flow-secondary);flex-shrink:0;display:inline-flex}.flow-deck-name{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.flow-deck-caret{color:var(--flow-muted);flex-shrink:0;display:inline-flex}.flow-tabs-wrap{pointer-events:auto;justify-self:center;align-items:center;gap:6px;min-width:0;max-width:min(600px,100vw - 132px);display:flex}.flow-tabs{min-width:0;height:var(--flow-dock-h);background:var(--flow-raised);border:1px solid var(--flow-border);border-radius:10px;flex:0 auto;padding:3px;position:relative;overflow:hidden;box-shadow:0 8px 24px -12px #000000d9}.flow-tabs-scroll{scrollbar-width:none;align-items:center;gap:4px;height:100%;display:flex;overflow:auto hidden}.flow-tabs-scroll::-webkit-scrollbar{display:none}.flow-tabs:before,.flow-tabs:after{content:"";z-index:1;pointer-events:none;opacity:0;width:24px;transition:opacity .12s;position:absolute;top:1px;bottom:1px}.flow-tabs:before{background:linear-gradient(to right, var(--flow-raised), transparent);border-radius:9px 0 0 9px;left:1px}.flow-tabs:after{background:linear-gradient(to left, var(--flow-raised), transparent);border-radius:0 9px 9px 0;right:1px}.flow-tabs.more-left:before,.flow-tabs.more-right:after{opacity:1}.flow-chip,.flow-tabs-add{width:30px;height:28px;color:var(--flow-muted);cursor:pointer;background:0 0;border:none;border-radius:7px;flex-shrink:0;justify-content:center;align-items:center;padding:0;display:inline-flex;position:relative}@media (hover:hover){.flow-chip:hover,.flow-tabs-add:hover{color:var(--flow-fg);background:#ffffff0d}}.flow-chip.active{color:var(--flow-fg);background:#ffffff1a;box-shadow:inset 0 0 0 1px #ffffff0f}.flow-chip-icon{display:inline-flex}.flow-topbar-trailing{pointer-events:none;justify-self:end;align-items:center;gap:8px;min-width:0;display:flex}.flow-preview-btn{pointer-events:auto;height:var(--flow-dock-h);color:var(--flow-fg);background:var(--flow-raised);border:1px solid var(--flow-border);cursor:pointer;font:inherit;border-radius:10px;flex-shrink:0;align-items:center;gap:6px;padding:0 14px;font-size:13px;font-weight:600;display:flex;box-shadow:0 8px 24px -12px #000000d9}.flow-preview-btn:hover{background:var(--flow-hover)}.flow-preview-btn:disabled{opacity:.6;cursor:default}@media (width<=768px){.flow-deck-identity,.flow-topbar-trailing{display:none}.flow-menu-narrow{display:flex}.flow-menu-sep.flow-menu-narrow{display:block}}.flow-scroller{flex:auto;min-height:0;overflow:auto}.flow-field{width:max-content;min-width:100%;min-height:100%}.flow-row{align-items:flex-start;gap:var(--flow-gap);width:max-content;min-height:100%;padding:calc(var(--flow-dock-h) + var(--flow-gap) * 2) var(--flow-gap) var(--flow-gap);display:flex}.flow-group{background:var(--flow-surface);border:1px solid var(--flow-border);border-radius:var(--flow-radius);flex-direction:column;min-width:200px;transition:border-color .12s;display:flex;position:relative;overflow:hidden}.flow-group.active{border-color:var(--flow-border-active)}.flow-titlebar{background:var(--flow-raised);border-bottom:1px solid var(--flow-border);cursor:grab;touch-action:none;flex:none;align-items:center;gap:6px;height:32px;padding:0 4px;display:flex}.flow-titlebar-btn{width:24px;height:24px;color:var(--flow-muted);cursor:pointer;background:0 0;border:none;border-radius:5px;flex:none;justify-content:center;align-items:center;display:inline-flex}.flow-titlebar-btn:hover{color:var(--flow-fg);background:var(--flow-hover)}.flow-titlebar-btn.pinned,.flow-titlebar-btn.pinned:hover{color:var(--flow-gutter);background:var(--flow-fg)}.flow-group.dragging{border-color:var(--flow-border-active);box-shadow:0 0 0 1px var(--flow-border-active) inset}.flow-drop-indicator{background:var(--flow-fg);z-index:60;pointer-events:none;border-radius:2px;width:3px;position:fixed}.flow-group.pinned{left:var(--flow-gap);z-index:5;position:sticky;box-shadow:0 6px 24px #00000073}.flow-titlebar-icon{color:var(--flow-secondary);flex:none;display:inline-flex}.flow-titlebar-title{text-overflow:ellipsis;white-space:nowrap;color:var(--flow-fg);flex:auto;font-size:12px;overflow:hidden}.flow-tab-icon{flex:none;display:inline-flex}.flow-panel-body{flex:auto;min-height:0;position:relative;overflow:hidden}.flow-panel-slot{width:100%;height:100%}.flow-resize-e{cursor:col-resize;touch-action:none;z-index:20;width:16px;position:absolute;top:32px;bottom:0;right:-8px}.flow-resize-s{cursor:row-resize;touch-action:none;z-index:20;height:16px;position:absolute;bottom:-8px;left:0;right:0}.flow-resize-se{cursor:nwse-resize;touch-action:none;z-index:21;width:22px;height:22px;position:absolute;bottom:-11px;right:-11px}.flow-placeholder{height:100%;color:var(--flow-muted);text-align:center;flex-direction:column;justify-content:center;align-items:center;gap:8px;padding:16px;display:flex}.flow-placeholder-icon :is(svg){width:34px;height:34px}.flow-placeholder-label{color:var(--flow-secondary);font-size:14px}.flow-placeholder-kind{color:var(--flow-muted);font:11px ui-monospace,SFMono-Regular,Menlo,monospace}.flow-placeholder.kind-play{background:repeating-linear-gradient(45deg,#101018,#101018 10px,#0d0d14 10px 20px)}.flow-kind-menu{z-index:50;background:#121212;border:1px solid #2e2e2e;border-radius:8px;flex-direction:column;min-width:150px;padding:4px;display:flex;position:fixed;box-shadow:0 8px 24px #00000080}.flow-kind-menu button{color:var(--flow-fg);cursor:pointer;text-align:left;background:0 0;border:none;border-radius:6px;align-items:center;gap:8px;padding:7px 8px;display:flex}.flow-kind-menu button:hover{background:var(--flow-hover)}.flow-picker{z-index:50;background:#121212;border:1px solid #2e2e2e;border-radius:8px;flex-direction:column;max-height:min(60vh,420px);padding:6px;display:flex;position:fixed;box-shadow:0 8px 24px #00000080}.flow-picker-input{color:var(--flow-fg);background:var(--flow-surface);border:1px solid var(--flow-border);border-radius:6px;outline:none;flex:none;margin-bottom:6px;padding:7px 9px;font:13px ui-sans-serif,system-ui,sans-serif}.flow-picker-input:focus{border-color:var(--flow-border-active)}.flow-picker-list{flex:auto;min-height:0;overflow-y:auto}.flow-picker-item{width:100%;color:var(--flow-fg);cursor:pointer;text-align:left;background:0 0;border:none;border-radius:6px;align-items:center;gap:8px;padding:6px 8px;display:flex}.flow-picker-item.sel,.flow-picker-item:hover{background:var(--flow-hover)}.flow-picker-label{text-overflow:ellipsis;white-space:nowrap;font-size:13px;overflow:hidden}.flow-picker-empty{color:var(--flow-muted);padding:10px 8px;font-size:12px}.flow-operator-host{width:100%;height:100%}.flow-operator-host .operator-resize{display:none}.flow-root.is-maximized .flow-scroller{overflow:hidden}.flow-root.is-maximized .flow-field,.flow-root.is-maximized .flow-row{width:100%;height:100%}.flow-root.is-maximized .flow-row{align-items:stretch}.flow-group.maximized{width:100%;height:100%}.flow-group.hidden{display:none}.flow-root.is-mobile .flow-scroller{overflow:clip}.flow-root.is-mobile .flow-field{width:100%;height:100%;padding-top:calc(var(--flow-gap) + var(--flow-dock-h))}.flow-root.is-mobile .flow-row{width:100%;height:100%;transform:translateX(calc(var(--flow-page,0) * -100% + var(--flow-drag,0px)));will-change:transform;flex-wrap:nowrap;align-items:stretch;gap:0;padding:0;transition:transform .28s cubic-bezier(.22,.61,.36,1);display:flex}.flow-root.is-mobile.flow-dragging .flow-row{transition:none}.flow-root.is-mobile .flow-group{flex:0 0 calc(100% - 8px);min-width:0;margin:4px}.flow-root.is-mobile .flow-resize-e,.flow-root.is-mobile .flow-resize-s,.flow-root.is-mobile .flow-resize-se{display:none}@media (prefers-reduced-motion:reduce){.flow-root.is-mobile .flow-row{transition:none}}.flow-push-modal-backdrop{z-index:1000;-webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px);pointer-events:auto;background:#0000008c;justify-content:center;align-items:center;padding:24px;display:flex;position:fixed;inset:0}.flow-push-modal{border:1px solid var(--flow-border);text-align:center;background:#141414;border-radius:18px;flex-direction:column;align-items:center;gap:10px;width:min(360px,100%);padding:28px 24px;display:flex;box-shadow:0 20px 60px #0009}.flow-push-spinner{border:3px solid #ffffff26;border-top-color:var(--flow-fg);border-radius:50%;width:34px;height:34px;animation:.8s linear infinite flow-push-spin}@keyframes flow-push-spin{to{transform:rotate(360deg)}}.flow-push-check{color:#fff;background:#2e7d32;border-radius:50%;justify-content:center;align-items:center;width:34px;height:34px;font-size:20px;font-weight:700;display:flex}.flow-push-title{color:var(--flow-fg);font-size:16px;font-weight:600}.flow-push-sub{color:var(--flow-secondary);font-size:12px}.flow-push-url{overflow-wrap:anywhere;color:#7aa2ff;max-width:100%;font:13px ui-monospace,SFMono-Regular,Menlo,monospace;text-decoration:none}.flow-push-url:hover{text-decoration:underline}.flow-push-done{background:var(--flow-fg);color:var(--flow-gutter);cursor:pointer;border:none;border-radius:999px;margin-top:8px;padding:9px 24px;font-size:14px;font-weight:600}:root{--lightningcss-light: ;--lightningcss-dark:initial;color-scheme:dark;--v2-gutter:#000;--v2-surface:#0d0d0d;--v2-raised:#161616;--v2-hover:#1d1d1d;--v2-fg:#e6e6e6;--v2-head:#e8e8e8;--v2-secondary:#b3b3b3;--v2-muted:#888;--v2-dim:#525252;--v2-placeholder:#666;--v2-ink:#111;--v2-white:#fff;--v2-border:#2a2a2a;--v2-accent:#622461;--v2-accent-hover:#855484;--v2-running:#6c9ce0;--v2-running-ring:#6c9ce040;--v2-avatar-ring:#fff;--v2-avatar-ring-hover:#b3b3b3;--v2-error-bg:#5a2b2b;--v2-warn:#e2c08d;--v2-error:#e08c8c;--v2-overlay-scrim:#00000059;--v2-overlay-code:#00000038;--v2-overlay-code-block:#00000047;--v2-overlay-task:#141414eb;--v2-overlay-feed-code:#7878784d;--v2-overlay-white-subtle:#ffffff0f;--v2-overlay-white-hover:#ffffff14;--v2-overlay-white-border:#ffffff24;--v2-overlay-white-quote:#fff6;--v2-overlay-white-dim:#ffffffd9;--v2-shadow-pop:0 10px 24px -10px #000000e6;--v2-text-shadow-float:0 1px 3px #000000f2, 0 0 2px #000000d9;--v2-selection:#e6e6e62e;--v2-mono:ui-monospace, SFMono-Regular, Menlo, monospace;--panel-gutter:10px;--panel-chrome-radius:8px}*{box-sizing:border-box}html,body,#root{height:100%;margin:0}body{color:var(--v2-fg);background:var(--v2-surface);font-family:baltomobile,Balto,ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif;overflow:hidden}.shell-dockview{box-sizing:border-box;--dv-tab-font-size:14px;--dv-tabs-and-actions-container-font-size:14px;--dv-tabs-and-actions-container-height:30px;--dv-group-view-background-color:var(--v2-surface);--dv-tabs-and-actions-container-background-color:var(--v2-gutter);--dv-activegroup-visiblepanel-tab-background-color:var(--v2-surface);--dv-activegroup-visiblepanel-tab-color:var(--v2-fg);--dv-activegroup-hiddenpanel-tab-background-color:var(--v2-gutter);--dv-activegroup-hiddenpanel-tab-color:var(--v2-dim);--dv-inactivegroup-visiblepanel-tab-background-color:var(--v2-surface);--dv-inactivegroup-visiblepanel-tab-color:var(--v2-fg);--dv-inactivegroup-hiddenpanel-tab-background-color:var(--v2-gutter);--dv-inactivegroup-hiddenpanel-tab-color:var(--v2-dim);--dv-tab-divider-color:var(--v2-border);--dv-separator-border:transparent;--dv-sash-color:transparent;--dv-active-sash-color:var(--v2-dim);height:100%;padding:var(--panel-gutter) var(--panel-gutter) var(--panel-gutter) 0;background-color:var(--v2-gutter);font-family:baltomobile,Balto,ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif}.shell-dockview.dv-dockview{background-color:var(--v2-gutter)}.shell-dockview .dv-sash{z-index:99}.shell-dockview .dv-sash:before{content:"";position:absolute;inset:-5px}.play-restart-btn{color:#e7e7ef;cursor:pointer;background:#2f2f48;border:1px solid #3a3a52;border-radius:6px;align-items:center;gap:6px;padding:4px 10px;font:12px system-ui,sans-serif;transition:background .12s,border-color .12s;display:inline-flex}.play-restart-btn:hover{background:#3a3a5a;border-color:#565676}.play-restart-btn:active{background:#262638}.play-restart-icon{display:inline-flex}.play-restart-icon.spinning{animation:.6s play-restart-spin}@keyframes play-restart-spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.shell-dockview .dv-default-tab-content{font-family:inherit}.shell-dockview .dv-split-view-container .dv-view:has(>.dv-groupview){border-radius:var(--panel-chrome-radius);box-sizing:border-box;overflow:hidden}.shell-dockview .dv-split-view-container .dv-view:has(>.dv-groupview):after{content:"";z-index:10;pointer-events:none;border:1px solid var(--v2-border);border-radius:inherit;box-sizing:border-box;position:absolute;inset:0}.shell-dockview .dv-view>.dv-groupview{border:none;border-radius:0;width:100%;height:100%}.shell-dockview .dv-split-view-container .dv-view:has(>.dv-groupview.dv-active-group):after{border-color:#6a6a6a}.shell-dockview .dv-resize-container:has(>.dv-groupview.dv-active-group):after{border-color:#6a6a6a}.shell-dockview .dv-resize-container:has(>.dv-groupview){border-radius:var(--panel-chrome-radius);box-sizing:border-box;overflow:hidden}.shell-dockview .dv-resize-container:has(>.dv-groupview):after{content:"";z-index:10;pointer-events:none;border:1px solid var(--v2-border);border-radius:inherit;box-sizing:border-box;position:absolute;inset:0}.shell-dockview .dv-resize-container .dv-groupview{border:none;border-radius:0;width:100%;height:100%}.shell-dockview .dv-tabs-container.dv-horizontal{align-items:stretch;display:flex}.shell-dockview .dv-tab{border:none;border-right:1px solid var(--dv-tab-divider-color);border-radius:0;align-self:stretch;height:100%;padding:0 5px 0 10px}.shell-dockview .dv-tab:not(:first-child){margin-left:0}.shell-dockview .dv-tab.dv-inactive-tab{border-bottom:1px solid var(--dv-tab-divider-color)}.shell-dockview .dv-tab.dv-active-tab{border-bottom:none}.shell-dockview .dv-tabs-and-actions-container .dv-void-container{border-bottom:1px solid var(--dv-tab-divider-color)}.shell-dockview .dv-tabs-and-actions-container .dv-right-actions-container{border-left:1px solid var(--dv-tab-divider-color);border-bottom:1px solid var(--dv-tab-divider-color);align-items:stretch}.shell-dockview .dv-tab .dv-default-tab-content{margin-right:6px}.shell-dockview .dv-tab .dv-default-tab-action{padding:2px}.shell-dockview .dv-tab .dv-default-tab-action .dv-svg{width:8px;height:8px;transform:translateY(1px)}.shell-dockview .dv-tab.dv-inactive-tab .dv-default-tab-action,.shell-dockview .dv-tab.dv-active-tab .dv-default-tab-action{color:var(--v2-dim)}.shell-dockview .dv-tabs-container.dv-horizontal .dv-tab:not(:first-child):before{display:none}.shell-dockview .dv-tab:focus:after,.shell-dockview .dv-tab:focus-within:after{display:none!important}.shell-dockview .dv-tabs-overflow-container{border:1px solid var(--dv-tab-divider-color);border-radius:var(--panel-chrome-radius);background:var(--v2-surface);min-width:180px;box-shadow:var(--v2-shadow-pop);gap:2px;padding:4px;overflow:hidden}.shell-dockview .dv-tabs-overflow-container .dv-tab{border-bottom:none;border-right:none;border-radius:6px;width:100%;padding:4px 8px 4px 10px}.shell-dockview .dv-tabs-overflow-container .dv-tab:hover{background:var(--v2-hover)}.shell-dockview .dv-tabs-overflow-container .dv-tab.dv-active-tab{background:var(--v2-raised)}.shell-dockview .dv-add-panel{align-items:center;height:100%;padding:0 3px;display:flex}.shell-dockview .dv-add-panel-btn{width:22px;height:22px;color:var(--dv-activegroup-visiblepanel-tab-color);cursor:pointer;background:0 0;border:none;border-radius:4px;justify-content:center;align-items:center;padding:0;display:flex}.shell-dockview .dv-add-panel-btn:hover{background:var(--v2-overlay-white-subtle)}.shell-dockview .dv-add-panel-btn svg{display:block}.dv-add-panel-menu{z-index:2147483000;background:var(--v2-surface);border:1px solid var(--v2-border);min-width:180px;box-shadow:var(--v2-shadow-pop);border-radius:8px;padding:4px;font-family:baltomobile,Balto,ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif;position:fixed;transform:translate(-100%)}.dv-add-panel-item{width:100%;color:var(--v2-fg);font:inherit;text-align:left;cursor:pointer;background:0 0;border:none;border-radius:6px;align-items:center;gap:10px;padding:7px 10px;font-size:13px;display:flex}.dv-add-panel-item:hover{background:var(--v2-accent);color:var(--v2-white)}.dv-add-panel-item-icon{color:var(--v2-muted);flex:0 0 16px;justify-content:center;align-items:center;display:flex}.dv-add-panel-item:hover .dv-add-panel-item-icon{color:var(--v2-white)}.dv-add-panel-item-label{white-space:nowrap;flex:1}.empty-dock-state{z-index:20;padding:var(--panel-gutter);pointer-events:auto;justify-content:center;align-items:center;display:flex;position:absolute;inset:0}.empty-dock-card{background:var(--v2-surface);border:1px solid var(--v2-border);border-radius:var(--panel-chrome-radius);width:210px;box-shadow:var(--v2-shadow-pop);padding:6px}.empty-dock-title{color:var(--v2-muted);padding:7px 10px 8px;font-size:12px}.empty-dock-actions{flex-direction:column;gap:2px;display:flex}.empty-dock-item{width:100%;color:var(--v2-fg);font:inherit;text-align:left;cursor:pointer;background:0 0;border:none;border-radius:6px;align-items:center;gap:10px;padding:8px 10px;font-size:13px;display:flex}.empty-dock-item:hover{background:var(--v2-accent);color:var(--v2-white)}.empty-dock-item:hover .dv-add-panel-item-icon{color:var(--v2-white)}.panel-error{height:100%;color:var(--v2-muted);flex-direction:column;align-items:flex-start;gap:8px;padding:14px 16px;font-size:13px;display:flex;overflow:auto}.panel-error-title{color:var(--v2-fg)}.panel-error-msg{white-space:pre-wrap;word-break:break-word;max-width:100%;color:var(--v2-muted);margin:0;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px}.panel-error-retry{font:inherit;border:1px solid var(--v2-border);background:var(--v2-raised);color:var(--v2-fg);cursor:pointer;border-radius:4px;padding:3px 10px;font-size:12px}.panel-error-retry:hover{background:var(--v2-hover)}.editor-panel-root{flex-direction:column;width:100%;height:100%;min-height:0;display:flex}.editor-shell{flex:auto;min-height:0;display:flex}.editor-panel-body{flex:auto;min-width:0;min-height:0;position:relative}.editor-contextbar{background:var(--v2-gutter,#0d0d0d);border-bottom:1px solid var(--v2-border,#2a2a2a);flex:none;align-items:center;gap:8px;padding:5px 8px;display:flex}.editor-drawer-toggle{width:26px;height:24px;color:var(--v2-muted,#888);cursor:pointer;background:0 0;border:1px solid #0000;border-radius:6px;flex:none;justify-content:center;align-items:center;display:inline-flex}.editor-drawer-toggle:hover{color:var(--v2-fg,#e7e7ef);background:var(--v2-surface,#1b1b2b)}.editor-drawer-toggle.on{color:var(--v2-fg,#e7e7ef);background:var(--v2-surface,#1b1b2b);border-color:var(--v2-border,#3a3a52)}.editor-drawer{background:var(--v2-gutter,#0d0d0d);border-right:1px solid var(--v2-border,#2a2a2a);flex:none;width:190px;padding:6px 4px;overflow-y:auto}.editor-drawer-folder{letter-spacing:.03em;text-transform:uppercase;color:var(--v2-muted,#888);padding:6px 8px 2px;font:10px ui-sans-serif,system-ui,sans-serif}.editor-drawer-item{width:100%;color:var(--v2-secondary,#b3b3b3);cursor:pointer;text-align:left;text-overflow:ellipsis;white-space:nowrap;background:0 0;border:none;border-radius:6px;padding:5px 8px;font:12px ui-sans-serif,system-ui,sans-serif;display:block;overflow:hidden}.editor-drawer-item:hover{background:var(--v2-surface,#1b1b2b);color:var(--v2-fg,#e7e7ef)}.editor-drawer-item.current{color:var(--v2-fg,#e7e7ef);background:#ffffff1a}.editor-drawer-empty{color:var(--v2-muted,#888);padding:10px 8px;font-size:12px}.editor-view-picker{background:var(--v2-surface,#1b1b2b);color:var(--v2-fg,#e7e7ef);border:1px solid var(--v2-border,#3a3a52);cursor:pointer;border-radius:6px;flex:none;padding:3px 6px;font:12px system-ui,sans-serif}.editor-contextbar-path{text-overflow:ellipsis;white-space:nowrap;color:var(--v2-muted,#888);flex:auto;font:11px ui-monospace,SFMono-Regular,Menlo,monospace;overflow:hidden}.deck-panel{background:var(--v2-surface);width:100%;height:100%}.deck-frame{border:0;width:100%;height:100%;display:block}.play-panel{background:var(--v2-surface);flex-direction:column;width:100%;height:100%;display:flex}.play-stage{flex:auto;justify-content:center;align-items:center;min-height:0;padding:20px;display:flex;container-type:size}.play-frame-shell{aspect-ratio:5/7;border-radius:4%/2.85714%;width:min(100cqw,71.4286cqh);height:min(100cqh,140cqw);overflow:hidden}.play-frame-shell .deck-frame{width:100%;height:100%}.play-logs{border-top:1px solid var(--v2-border);background:var(--v2-surface);color:var(--v2-secondary);flex:none;font:12px/1.5 ui-monospace,SFMono-Regular,Menlo,monospace}.play-logs-header{justify-content:space-between;align-items:center;height:28px;padding:0 8px;display:flex}.play-logs-toggle{color:var(--v2-muted);cursor:pointer;font:inherit;text-transform:uppercase;letter-spacing:.04em;background:0 0;border:0;align-items:center;gap:6px;padding:0;font-size:11px;display:inline-flex}.play-logs-caret{width:10px;color:var(--v2-muted);display:inline-block}.play-logs-count{color:var(--v2-muted)}.play-logs-actions{align-items:center;gap:6px;display:flex}.play-logs-clear{color:var(--v2-muted);cursor:pointer;font:inherit;background:0 0;border:0;padding:2px 4px;font-size:11px}.play-logs-clear:hover{color:var(--v2-secondary)}.play-logs-btn{width:26px;height:22px;color:var(--v2-secondary);border:1px solid var(--v2-overlay-white-border);cursor:pointer;background:0 0;border-radius:6px;justify-content:center;align-items:center;padding:0;display:inline-flex}.play-logs-btn:hover{background:var(--v2-overlay-white-hover);color:var(--v2-white)}.play-logs-body{border-top:1px solid var(--v2-raised);max-height:200px;padding:4px 10px 8px;overflow-y:auto}.play-logs-line{white-space:pre-wrap;word-break:break-word}.play-logs-warn{color:var(--v2-warn)}.play-logs-error{color:var(--v2-error)}.play-logs-empty{color:var(--v2-dim)}.term-panel{width:100%;height:100%;position:relative}.term-host{overscroll-behavior:contain;padding:6px;position:absolute;inset:0}.shell-root{--operator-pad:10px;--operator-col-fit:min(var(--operator-col,400px), 100%);--composer-reserve:88px;background:var(--v2-gutter);height:100%;position:relative}.shell-root .shell-dockview{height:100%;transition:margin-left .18s,width .18s,opacity .12s}body.operator-resizing .shell-root .shell-dockview{transition:none}.shell-root.dock-hidden .shell-dockview{opacity:0}.shell-root:not(.anim-ready) .shell-dockview,.shell-root:not(.anim-ready) #chat-host{transition:none}.shell-root.docked .shell-dockview{margin-left:var(--operator-col-fit);padding-right:min(var(--panel-gutter), calc(100% - var(--operator-col-fit)));width:calc(100% - var(--operator-col-fit))!important}.shell-root.floating .shell-dockview{margin-left:60px;width:calc(100% - 60px)!important}#chat-host{width:var(--operator-col-fit);background:var(--v2-gutter);color:var(--v2-fg);z-index:10;flex-direction:column;font-family:Balto,system-ui,-apple-system,sans-serif;transition:background-color .18s;display:flex;position:absolute;top:0;bottom:0;left:0}body.operator-resizing #chat-host{transition:none}.shell-root.floating #chat-host{pointer-events:none;z-index:2147482500;background:0 0;width:380px;max-width:86vw}.operator-resize{cursor:col-resize;z-index:30;width:8px;position:absolute;top:0;bottom:0;right:0}body.operator-resizing,body.operator-resizing *{cursor:col-resize;-webkit-user-select:none!important;user-select:none!important}body.shell-sash-resizing,body.shell-sash-resizing *{-webkit-user-select:none!important;user-select:none!important}.shell-root.floating #chat-messages{pointer-events:none;justify-content:flex-end;padding:0 0 0 60px;position:absolute;inset:0 0 88px}.shell-root.floating #chat-messages .chat-bubbles{pointer-events:auto;flex-direction:column;gap:4px;display:flex}.shell-root.floating #chat-pending,.shell-root.floating .chat-input .ta,.shell-root.floating .chat-input .chat-queue{pointer-events:auto}.shell-root.floating .chat-input{z-index:6;pointer-events:none;margin-top:auto;padding-left:60px;padding-right:0;position:relative}.shell-root.floating #chat-host .chat-input.collapsed{pointer-events:none;padding-bottom:13px}.shell-root.floating #chat-host .chat-input.collapsed.revealed{pointer-events:auto}.shell-root.floating #chat-host .chat-input.collapsed .ta{cursor:pointer;opacity:0;pointer-events:none;border-radius:19px;justify-content:center;align-items:center;gap:0;width:38px;height:38px;min-height:0;padding:5px;transform:translateY(6px)}.shell-root.floating #chat-host .chat-input.collapsed.revealed .ta{opacity:1;pointer-events:auto;transform:none}.shell-root.floating #chat-host .chat-input.collapsed .ta-text,.shell-root.floating #chat-host .chat-input.collapsed .ta-bottom,.shell-root.floating #chat-host .chat-input.collapsed .chat-queue,.shell-root.floating #chat-host:not(.chat-expanded) #chat-pending,#chat-host .chat-input .collapse-icon{display:none}.shell-root.floating #chat-host .chat-input.collapsed .collapse-icon{width:28px;height:28px;color:var(--v2-muted);flex-shrink:0;justify-content:center;align-items:center;display:flex}#chat-host .chat-input .collapse-icon svg{width:20px;height:20px;display:block}.shell-root.floating #chat-host .chat-input.collapsed .ta:hover .collapse-icon{color:var(--v2-fg)}.shell-root.floating #chat-host .msg,.shell-root.floating #chat-host .assistant-turn{transition:opacity .55s}.shell-root.floating #chat-host .msg.fading,.shell-root.floating #chat-host .assistant-turn.fading{opacity:0;pointer-events:none}@media (prefers-reduced-motion:reduce){.shell-root.floating #chat-host .msg,.shell-root.floating #chat-host .assistant-turn{transition:none}}.shell-root.floating #chat-host.rail-engaged #chat-messages{opacity:0;pointer-events:none;transition:opacity .14s}.operator-avatar{background:var(--v2-raised);width:36px;height:36px;color:var(--v2-fg);border:2px solid var(--v2-avatar-ring);box-shadow:var(--v2-shadow-pop);cursor:pointer;pointer-events:auto;z-index:80;border-radius:50%;justify-content:center;align-items:center;padding:0;display:flex;position:absolute;bottom:14px;left:12px;overflow:hidden}.operator-avatar:hover{border-color:var(--v2-avatar-ring-hover)}.operator-avatar svg{display:block}.operator-avatar-img{object-fit:cover;border-radius:50%;width:100%;height:100%;display:block}.operator-avatar.active{border-color:var(--v2-running);box-shadow:0 0 0 3px var(--v2-running-ring), var(--v2-shadow-pop)}.operator-gutter{pointer-events:auto;z-index:5;width:60px;max-height:calc(100% - 56px);position:absolute;top:0;left:0;overflow:visible}#chat-host .operator-gutter .task-stack{scrollbar-width:none;-ms-overflow-style:none;flex-direction:column;width:100%;max-height:100%;display:flex;overflow-y:auto}.shell-root.floating #chat-host.rail-engaged .operator-gutter .task-stack{overflow:visible}#chat-host .operator-gutter .task-stack::-webkit-scrollbar{width:0;height:0}#chat-host .operator-gutter .task-row{padding:5px 14px}#chat-host .operator-gutter .task:hover,#chat-host .operator-gutter .task.open{background:var(--v2-overlay-task);width:344px;box-shadow:inset 0 0 0 1px var(--v2-border), var(--v2-shadow-pop);z-index:30;transform:translate(8px)}#chat-host .operator-gutter .task:hover .task-row,#chat-host .operator-gutter .task.open .task-row{gap:10px;padding:5px 6px}#chat-host .operator-gutter .task-meta{opacity:0;pointer-events:none;transition:opacity .14s}#chat-host .operator-gutter .task:hover .task-meta,#chat-host .operator-gutter .task.open .task-meta{opacity:1;pointer-events:auto}#chat-host .operator-gutter .task-name,#chat-host .operator-gutter .task-sub,#chat-host .operator-gutter .task-body{text-shadow:var(--v2-text-shadow-float)}#chat-host .settings-popover{z-index:2147483000;background:var(--v2-surface);width:390px;max-width:calc(100vw - 24px);color:var(--v2-fg);border:1px solid var(--v2-border);box-shadow:var(--v2-shadow-pop);border-radius:8px;padding:10px 12px;font-size:13px;position:fixed;bottom:70px;left:12px}#chat-host .settings-row{flex-wrap:wrap;justify-content:space-between;align-items:center;gap:6px 10px;display:flex}#chat-host .settings-row+.settings-row{margin-top:8px}#chat-host .settings-label{white-space:nowrap}#chat-host .settings-seg{border:1px solid var(--v2-border);border-radius:4px;display:flex;overflow:hidden}#chat-host .settings-opt{font:inherit;background:var(--v2-surface);color:var(--v2-muted);cursor:pointer;white-space:nowrap;border:0;padding:5px 10px;font-size:13px}#chat-host .settings-opt+.settings-opt{border-left:1px solid var(--v2-border)}#chat-host .settings-opt:hover{color:var(--v2-fg)}#chat-host .settings-opt.active{background:var(--v2-accent);color:var(--v2-white)}#chat-host .settings-text{min-width:0;font:inherit;background:var(--v2-surface);color:var(--v2-fg);border:1px solid var(--v2-border);border-radius:4px;flex:auto;padding:5px 8px;font-size:13px}#chat-host .settings-text::placeholder{color:var(--v2-placeholder)}#chat-host .settings-text:focus{border-color:var(--v2-accent);outline:none}#chat-host .settings-row-stack{flex-direction:column;align-items:stretch;gap:4px;display:flex}#chat-host .settings-row-main{flex-wrap:wrap;justify-content:space-between;align-items:center;gap:6px 10px;display:flex}#chat-host .settings-text-warn{border-color:var(--v2-warn)}#chat-host .settings-warning{color:var(--v2-warn);text-align:right;font-size:11px;line-height:1.35}#chat-host .settings-warning-suggest{appearance:none;font:inherit;color:var(--v2-warn);cursor:pointer;background:0 0;border:none;margin:0;padding:0;text-decoration:underline}#chat-host .settings-warning-suggest:hover{color:var(--v2-fg)}#chat-host .settings-select{max-width:60%;font:inherit;background:var(--v2-surface);color:var(--v2-fg);border:1px solid var(--v2-border);cursor:pointer;border-radius:4px;flex:0 auto;padding:5px 8px;font-size:13px}#chat-host .settings-select:focus{border-color:var(--v2-accent);outline:none}#chat-host .settings-select option{background:var(--v2-surface);color:var(--v2-fg)}#chat-host .settings-group+.settings-group{border-top:1px solid var(--v2-border);margin-top:12px;padding-top:12px}#chat-host .settings-usage-text{color:var(--v2-secondary);white-space:nowrap}#chat-host .settings-usage-bar{background:var(--v2-border);border-radius:2px;height:4px;margin-top:6px;overflow:hidden}#chat-host .settings-usage-fill{background:var(--v2-accent-hover);height:100%}#chat-host .settings-usage-fill.blocked{background:var(--v2-error)}#chat-host .settings-account-open{width:100%;font:inherit;background:var(--v2-surface);color:var(--v2-muted);border:1px solid var(--v2-border);cursor:pointer;border-radius:4px;margin-top:10px;padding:7px 12px;font-size:13px}#chat-host .settings-account-open:hover{color:var(--v2-fg)}.castle-key-heading{margin-bottom:4px;font-weight:600}.castle-key-subtitle{color:#9a9a9a;margin-bottom:14px;font-size:12px;line-height:1.5}.castle-key-tabs{border:1px solid #3a3a3a;border-radius:4px;margin-bottom:12px;display:flex;overflow:hidden}.castle-key-tab{color:#9a9a9a;font:inherit;cursor:pointer;background:#2e2e2e;border:0;flex:1;padding:6px 10px;font-size:12px}.castle-key-tab+.castle-key-tab{border-left:1px solid #3a3a3a}.castle-key-tab:hover{color:#e8e8e8}.castle-key-tab.active{color:#e8e8e8;background:#3a3a3a}.castle-key-input{box-sizing:border-box;color:#e8e8e8;width:100%;font:inherit;background:#1b1b1b;border:1px solid #3a3a3a;border-radius:4px;outline:none;padding:7px 9px;font-size:12px;display:block}.castle-key-input:focus{border-color:#4a4a4a}.castle-key-input::placeholder{color:#6a6a6a}.castle-key-stored{color:#8a8a8a;margin-top:8px;font-size:11px}.castle-key-error{color:#e8705a;margin-top:8px;font-size:11px;line-height:1.4}.castle-key-row{color:#c8c8c8;justify-content:space-between;align-items:center;gap:10px;margin-bottom:12px;display:flex}.castle-key-row button{color:#e8e8e8;font:inherit;cursor:pointer;background:#2e2e2e;border:1px solid #3a3a3a;border-radius:4px;padding:5px 12px;font-size:12px}.castle-key-row button:hover{background:#383838}.castle-key-login{margin-bottom:12px}.castle-key-signin{color:#e8e8e8;width:100%;font:inherit;cursor:pointer;background:#2e2e2e;border:1px solid #3a3a3a;border-radius:4px;padding:9px 12px;font-size:13px;display:block}.castle-key-signin:hover{background:#383838}.castle-key-or{color:#7a7a7a;letter-spacing:.08em;text-transform:uppercase;align-items:center;gap:10px;margin:14px 0;font-size:11px;display:flex}.castle-key-or:before,.castle-key-or:after{content:"";background:#3a3a3a;flex:1;height:1px}.castle-key-field-label{color:#c8c8c8;margin-bottom:6px;font-size:12px}.castle-key-url{color:#7aa2f7;word-break:break-all;-webkit-user-select:all;user-select:all;background:#1b1b1b;border:1px solid #3a3a3a;border-radius:4px;padding:8px 9px;font-size:11px;line-height:1.4;display:block}#chat-messages{scrollbar-width:none;-ms-overflow-style:none;flex-direction:column;flex:1 1 0;min-height:0;padding:0;font-size:14px;line-height:1.5;display:flex;overflow-y:auto}#chat-messages .chat-thread{opacity:0;flex-direction:column;transition:opacity .12s;display:flex}#chat-messages .chat-thread.ready{opacity:1}.shell-root.docked #chat-messages{-webkit-mask-image:linear-gradient(to bottom, var(--v2-gutter) calc(100% - var(--composer-reserve,88px)), transparent 100%);-webkit-mask-image:linear-gradient(to bottom, var(--v2-gutter) calc(100% - var(--composer-reserve,88px)), transparent 100%);mask-image:linear-gradient(to bottom, var(--v2-gutter) calc(100% - var(--composer-reserve,88px)), transparent 100%);padding:0}.shell-root.docked #chat-messages .chat-thread{padding-bottom:var(--composer-reserve,88px)}.shell-root.docked #chat-messages>:first-child{margin-top:auto}#chat-messages::-webkit-scrollbar{width:0;height:0}#chat-empty{color:var(--v2-muted)}#chat-host .msg{margin:5px 0}#chat-host .msg.user{text-align:right}#chat-host .msg.user span{background:var(--v2-white);color:var(--v2-ink);text-align:left;white-space:pre-wrap;word-break:break-word;border-radius:17px;max-width:85%;padding:7px 14px;display:inline-block}#chat-host .msg-image{border:1px solid var(--v2-border);border-radius:8px;max-width:220px;max-height:150px;margin:0 0 6px auto;display:block}#chat-host .assistant-turn{flex-direction:column;align-items:flex-start;gap:4px;margin:5px 0;display:flex}#chat-host .msg.assistant{background:var(--v2-accent);width:fit-content;color:var(--v2-white);word-break:break-word;border-radius:17px;max-width:85%;margin:0;padding:7px 14px}#chat-host .msg.assistant.errbubble{background:var(--v2-error-bg)}#chat-host .msg.assistant.streaming:after{content:"▌";opacity:.6;animation:1s step-end infinite chat-blink}@keyframes chat-blink{50%{opacity:0}}#chat-host .msg.toolline{color:var(--v2-muted);font-size:12px;font-family:var(--v2-mono);word-break:break-word;margin:4px 0}#chat-host .msg-activity{color:var(--v2-muted);font-size:12px;animation:1.4s ease-in-out infinite chat-pulse}@keyframes chat-pulse{50%{opacity:.35}}#chat-host .msg-interrupted,#chat-host .msg-error-detail{color:var(--v2-muted);font-size:12px}#chat-host .msg-error-detail summary{cursor:pointer;-webkit-user-select:none;user-select:none}#chat-host .msg-error-detail pre{background:var(--v2-overlay-scrim);white-space:pre-wrap;word-break:break-word;border-radius:6px;max-height:160px;margin:4px 0 0;padding:6px 8px;font-size:11px;overflow-y:auto}#chat-host .msg-thinking{color:var(--v2-muted);font-size:12px}#chat-host div.msg-thinking,#chat-host .msg-thinking summary{align-items:center;gap:8px;display:flex}#chat-host .msg-thinking summary{cursor:pointer;-webkit-user-select:none;user-select:none;list-style:none}#chat-host .msg-thinking summary::-webkit-details-marker{display:none}#chat-host .msg-thinking .thinking-caret{opacity:.7;border-top:4px solid #0000;border-bottom:4px solid #0000;border-left:5px solid;flex:none;width:0;height:0;transition:transform .12s}#chat-host .msg-thinking[open] .thinking-caret{transform:rotate(90deg)}#chat-host .msg-thinking .thinking-dots{gap:4px;display:inline-flex}#chat-host .msg-thinking .thinking-dots i{background:currentColor;border-radius:50%;width:6px;height:6px;animation:1.2s ease-in-out infinite thinking-bounce}#chat-host .msg-thinking .thinking-dots i:nth-child(2){animation-delay:.18s}#chat-host .msg-thinking .thinking-dots i:nth-child(3){animation-delay:.36s}#chat-host .msg-thinking .thinking-dots+.thinking-label{animation:1.4s ease-in-out infinite chat-pulse}@keyframes thinking-bounce{0%,80%,to{opacity:.3;transform:translateY(0)}40%{opacity:1;transform:translateY(-3px)}}@media (prefers-reduced-motion:reduce){#chat-host .msg-thinking .thinking-dots i,#chat-host .msg-thinking .thinking-label{animation:none}#chat-host .msg-thinking .thinking-dots i{opacity:.6}}#chat-host .msg-thinking-body{background:var(--v2-overlay-scrim);color:var(--v2-muted);border-radius:6px;max-height:160px;padding:0 12px;font-size:12px;overflow-y:auto}#chat-host .msg.md>:first-child,#chat-host .task-notes>:first-child{margin-top:0}#chat-host .msg.md>:last-child,#chat-host .task-notes>:last-child{margin-bottom:0}#chat-host .msg.md p:empty{display:none}#chat-host .msg.md p,#chat-host .task-notes p{margin:.4em 0}#chat-host .msg.md ul,#chat-host .msg.md ol,#chat-host .task-notes ul,#chat-host .task-notes ol{margin:.4em 0;padding-left:1.3em}#chat-host .msg.md li{margin:.1em 0}#chat-host .msg.md h1,#chat-host .msg.md h2,#chat-host .msg.md h3{margin:.5em 0 .3em;font-weight:700;line-height:1.25}#chat-host .msg.md h1{font-size:1.2em}#chat-host .msg.md h2{font-size:1.12em}#chat-host .msg.md h3{font-size:1.05em}#chat-host .msg.md a{color:var(--v2-white);text-underline-offset:2px;text-decoration:underline}#chat-host .msg.md code,#chat-host .task-notes code{font-family:var(--v2-mono);background:var(--v2-overlay-code);border-radius:4px;padding:.1em .35em;font-size:.9em}#chat-host .msg.md pre{background:var(--v2-overlay-code-block);white-space:pre-wrap;word-break:break-word;font-family:var(--v2-mono);border-radius:8px;margin:.5em 0;padding:8px 10px;font-size:.9em;line-height:1.4;overflow-x:auto}#chat-host .msg.md pre code{background:0 0;border-radius:0;padding:0}#chat-host .msg.md blockquote{border-left:3px solid var(--v2-overlay-white-quote);color:var(--v2-overlay-white-dim);margin:.5em 0;padding-left:.8em}.shell-root.docked #chat-host .operator-inset{min-height:0;padding:0 var(--operator-pad);flex-direction:column;flex:1 1 0;display:flex;overflow:hidden}.shell-root.docked #chat-host .chat-divider{background:var(--v2-border);flex:0 0 1px}.task-stack{gap:5px;padding-top:10px}#task-board{border-bottom:1px solid var(--v2-border);scrollbar-width:thin;scrollbar-color:transparent transparent;flex-direction:column;flex:0 auto;max-height:40vh;padding-top:0;padding-bottom:12px;display:flex;overflow-y:auto}#task-board.scrolling{scrollbar-color:var(--v2-dim) transparent}#task-board::-webkit-scrollbar{width:6px}#task-board::-webkit-scrollbar-track{background:0 0}#task-board::-webkit-scrollbar-thumb{background:0 0;border-radius:3px;transition:background .25s}#task-board.scrolling::-webkit-scrollbar-thumb{background:var(--v2-dim)}#chat-host .task{cursor:pointer;border-radius:8px;transition:background .12s,box-shadow .12s}#chat-host .task:hover,#chat-host .task.open{background:var(--v2-overlay-task);box-shadow:inset 0 0 0 1px var(--v2-border)}#chat-host .task-row{align-items:center;gap:10px;padding:5px 6px 5px 4px;display:flex;position:relative}#chat-host .task.open .task-row{align-items:flex-start}#chat-host .pie{border-radius:50%;flex:0 0 32px;width:32px;height:32px;padding:2px;display:flex;position:relative}#chat-host .pie .avatar{background:var(--v2-raised);width:100%;height:100%;color:var(--v2-gutter);border-radius:50%;justify-content:center;align-items:center;display:flex;overflow:hidden}#chat-host .pie .avatar .avatar-icon-wrap{justify-content:center;align-items:center;width:16px;height:16px;display:flex}#chat-host .pie .avatar .avatar-icon-wrap svg{width:16px;height:16px;display:block}#chat-host .task-meta{flex:1;min-width:0}#chat-host .task-head{align-items:center;gap:8px;display:flex}#chat-host .task.open .task-head{min-height:32px}#chat-host .task-text{flex:1;min-width:0}#chat-host .task-name{color:var(--v2-fg);white-space:nowrap;text-overflow:ellipsis;font-size:12px;font-weight:400;overflow:hidden}#chat-host .task-name .tn{color:var(--v2-head);font-weight:600}#chat-host .task-sub{color:var(--v2-muted);white-space:nowrap;text-overflow:ellipsis;font-variant-numeric:tabular-nums;margin-top:2px;font-size:10px;overflow:hidden}#chat-host .task-dismiss{border:1px solid var(--v2-border);color:var(--v2-muted);font:inherit;cursor:pointer;visibility:hidden;background:0 0;border-radius:6px;flex-shrink:0;padding:3px 10px;font-size:12px}#chat-host .task-dismiss:hover{color:var(--v2-fg);background:var(--v2-hover)}#chat-host .task-board-header{z-index:1;background:var(--v2-gutter);border-bottom:1px solid var(--v2-border);justify-content:space-between;align-items:center;gap:8px;padding:10px 2px 8px;display:flex;position:sticky;top:0}#chat-host .task-board-heading{align-items:baseline;gap:8px;min-width:0;display:flex}#chat-host .task-board-title{color:var(--v2-fg);font-size:13px;font-weight:600}#chat-host .task-board-status{color:var(--v2-muted);font-size:12px}#chat-host .task-clear-completed{border:1px solid var(--v2-border);color:var(--v2-muted);font:inherit;cursor:pointer;background:0 0;border-radius:6px;flex-shrink:0;padding:3px 10px;font-size:12px}#chat-host .task-clear-completed:hover{color:var(--v2-fg);background:var(--v2-hover)}#chat-host .task:hover .task-dismiss{visibility:visible}#chat-host .task-body{color:var(--v2-fg);padding:0 0 4px;font-size:12px;display:none}#chat-host .task.open .task-body{display:block}#chat-host .task-notes{color:var(--v2-secondary);word-break:break-word;margin-top:6px;font-size:12px}#chat-host .task-notes code{font-size:12px}#chat-host .task-playtest-frames{margin-top:8px}#chat-host .task-playtest-frames-label{color:var(--v2-muted);margin-bottom:4px;font-size:11px}#chat-host .task-playtest-frames-row{flex-wrap:wrap;gap:6px;display:flex}#chat-host .task-playtest-frame{object-fit:cover;border:1px solid var(--v2-border);background:var(--v2-ink);border-radius:4px;width:64px;height:90px;display:block}#chat-host .task-feed{scrollbar-width:none;-ms-overflow-style:none;max-height:96px;color:var(--v2-secondary);cursor:default;word-break:break-word;-webkit-mask-image:linear-gradient(to bottom, transparent, var(--v2-gutter) 5px, var(--v2-gutter) 100%);-webkit-mask-image:linear-gradient(to bottom, transparent, var(--v2-gutter) 5px, var(--v2-gutter) 100%);mask-image:linear-gradient(to bottom, transparent, var(--v2-gutter) 5px, var(--v2-gutter) 100%);margin-top:6px;font-size:12px;line-height:1.5;overflow-y:auto}#chat-host .task-feed::-webkit-scrollbar{width:0;height:0}#chat-host .task-feed-tool{color:var(--v2-muted);font-family:var(--v2-mono);white-space:pre-wrap;padding-left:14px;font-size:12px}#chat-host .task-feed-msg{margin:0}#chat-host .task-feed-msg>:first-child{margin-top:0}#chat-host .task-feed-msg>:last-child{margin-bottom:0}#chat-host .task-feed-msg p{margin:0}#chat-host .task-feed-msg code{background:var(--v2-overlay-feed-code);font-family:var(--v2-mono);border-radius:3px;padding:0 3px;font-size:12px}.chat-input{flex:none;padding:10px 10px 10px 60px}.shell-root.docked .chat-input{padding:0 var(--operator-pad) 10px 60px;pointer-events:none;z-index:6;position:absolute;bottom:0;left:0;right:0}.shell-root.docked .chat-input .ta,.shell-root.docked .chat-input .chat-queue{pointer-events:auto}.shell-root.docked #chat-pending{left:60px;right:var(--operator-pad);bottom:var(--composer-reserve,88px);z-index:6;pointer-events:auto;padding:0;position:absolute}#chat-host .chat-input .ta{background:var(--v2-surface);border:1px solid var(--v2-border);border-radius:var(--panel-chrome-radius);flex-direction:column;gap:6px;width:100%;min-height:60px;padding:8px 4px;transition:width .3s cubic-bezier(.4,0,.2,1),height .3s cubic-bezier(.4,0,.2,1),border-radius .3s cubic-bezier(.4,0,.2,1),padding .3s cubic-bezier(.4,0,.2,1),opacity .18s,transform .18s;display:flex;overflow:hidden}#chat-input{width:100%;min-height:21px;color:var(--v2-fg);font:inherit;resize:none;scrollbar-width:none;-ms-overflow-style:none;background:0 0;border:none;outline:none;max-height:120px;padding:0 6px;font-size:14px;line-height:1.5;display:block;overflow-y:auto}#chat-input::-webkit-scrollbar{width:0;height:0}#chat-input::placeholder{color:var(--v2-muted)}#chat-host .chat-input .ta-bottom{justify-content:space-between;align-items:center;gap:8px;min-width:0;display:flex}#chat-host .composer-settings{flex:auto;min-width:0}#chat-host .composer-pill{max-width:100%;height:26px;color:var(--v2-dim);font:inherit;cursor:pointer;background:0 0;border:none;border-radius:6px;align-items:center;gap:5px;padding:0 6px;font-size:12px;display:inline-flex}#chat-host .composer-pill:hover{color:var(--v2-fg);background:var(--v2-hover)}#chat-host .composer-pill.usage-warn{color:var(--v2-warn)}#chat-host .composer-pill.usage-blocked{color:var(--v2-error)}#chat-host .composer-pill-label{text-overflow:ellipsis;white-space:nowrap;min-width:0;overflow:hidden}#chat-host .composer-pill svg{flex-shrink:0;display:block}#chat-host .composer-pill .mode-caret{opacity:.7}#chat-send{width:26px;height:26px;color:var(--v2-muted);border:1px solid var(--v2-border);cursor:pointer;background:0 0;border-radius:50%;flex-shrink:0;justify-content:center;align-items:center;margin-right:6px;padding:0;display:flex}#chat-send:hover{color:var(--v2-fg);background:var(--v2-hover)}#chat-send svg{display:block}#chat-pending{flex:none;gap:6px;padding:10px 10px 0;display:flex}#chat-pending img{border:1px solid var(--v2-border);cursor:pointer;border-radius:6px;height:44px}#chat-host .chat-input .chat-queue{flex-direction:column;gap:4px;margin-bottom:6px;display:flex}#chat-host .chat-input .queue-row{background:var(--v2-gutter);border:1px dashed var(--v2-border);color:var(--v2-muted);border-radius:8px;align-items:center;gap:8px;padding:5px 6px 5px 12px;font-size:12px;display:flex}#chat-host .chat-input .queue-snippet{text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0;overflow:hidden}#chat-host .chat-input .queue-send-now{border:1px solid var(--v2-border);color:var(--v2-muted);font:inherit;cursor:pointer;background:0 0;border-radius:6px;flex-shrink:0;padding:2px 8px;font-size:11px}#chat-host .chat-input .queue-send-now:hover{color:var(--v2-fg);background:var(--v2-hover)}#chat-host .chat-input .queue-remove{width:20px;height:20px;color:var(--v2-muted);cursor:pointer;background:0 0;border:none;border-radius:5px;flex-shrink:0;justify-content:center;align-items:center;padding:0;font-size:11px;display:flex}#chat-host .chat-input .queue-remove:hover{color:var(--v2-fg);background:var(--v2-hover)}#chat-send.stop{color:var(--v2-fg);border-color:var(--v2-fg)}#chat-send.stop:hover{color:var(--v2-ink);background:var(--v2-fg)}#chat-send:disabled{opacity:.45;cursor:default}#chat-send:disabled:hover{color:var(--v2-muted);background:0 0}#chat-host .picker{background:var(--v2-surface);border:1px dashed var(--v2-border);border-radius:12px;flex-direction:column;align-self:flex-start;gap:12px;width:100%;max-width:100%;margin:4px 0;padding:12px;display:flex}#chat-host .picker-locked{opacity:.72}#chat-host .picker-q{border:none;min-width:0;margin:0;padding:0}#chat-host .picker-q-label{color:var(--v2-head);margin:0 0 6px;padding:0;font-size:13px;font-weight:600}#chat-host .picker-options{flex-wrap:wrap;gap:6px;display:flex}#chat-host .picker-option{background:var(--v2-gutter);border:1px solid var(--v2-border);color:var(--v2-fg);cursor:pointer;border-radius:12px 12px 4px;align-items:center;gap:6px;padding:5px 10px;font-size:13px;line-height:1.3;display:inline-flex}#chat-host .picker:not(.picker-locked) .picker-option:hover{border-color:var(--v2-accent)}#chat-host .picker-option.is-checked{background:var(--v2-accent);border-color:var(--v2-accent);color:var(--v2-white)}#chat-host .picker-option input{accent-color:var(--v2-accent);cursor:inherit;margin:0}#chat-host .picker-locked .picker-option{cursor:default}#chat-host .picker-actions{justify-content:flex-end;display:flex}#chat-host .picker-submit{font:inherit;background:var(--v2-accent);color:var(--v2-white);border:1px solid var(--v2-accent);cursor:pointer;border-radius:8px;padding:6px 16px;font-size:13px}#chat-host .picker-submit:hover{background:var(--v2-accent-hover)}#chat-host .picker-skeleton{pointer-events:none}#chat-host .picker-skeleton-hint{color:var(--v2-muted);letter-spacing:.01em;font-size:12px}#chat-host .picker-skeleton-line,#chat-host .picker-skeleton-chip{background:linear-gradient(90deg, var(--v2-border) 0%, var(--v2-border) 50%, var(--v2-border) 100%);background-size:200% 100%;border-radius:6px;animation:1.3s ease-in-out infinite picker-shimmer;display:block}#chat-host .picker-skeleton-label{width:60%;height:11px;margin-bottom:8px}#chat-host .picker-skeleton-chip{border-radius:12px 12px 4px;height:26px}@keyframes picker-shimmer{0%{background-position:200% 0}to{background-position:-200% 0}}@media (prefers-reduced-motion:reduce){#chat-host .picker-skeleton-line,#chat-host .picker-skeleton-chip{animation:none}}.xterm,.xterm-viewport,.xterm-screen,.xterm-helpers{background-color:#0000!important}.xterm{overscroll-behavior:contain}.xterm-viewport{overscroll-behavior:contain;scrollbar-width:none;-ms-overflow-style:none}.xterm-viewport::-webkit-scrollbar{width:0;height:0}.xterm .xterm-scrollable-element>.scrollbar,.xterm .xterm-scrollable-element>.scrollbar.visible,.xterm .xterm-scrollable-element>.visible.scrollbar,.xterm .xterm-scrollable-element>.invisible.scrollbar,.xterm .xterm-scrollable-element>.xterm-scrollbar{opacity:0!important;pointer-events:none!important;width:0!important;min-width:0!important;height:0!important;min-height:0!important;display:none!important}.xterm .xterm-scrollable-element>.scrollbar>.slider,.xterm .xterm-scrollable-element>.scrollbar>.scra,.xterm .xterm-scrollable-element>.xterm-scrollbar>.xterm-slider{width:0!important;height:0!important;display:none!important}.xterm .xterm-scrollable-element>.shadow{display:none!important}.quick-open-backdrop{z-index:2147483100;justify-content:center;align-items:flex-start;padding-top:12vh;display:flex;position:fixed;inset:0}.quick-open{background:#232323;border:1px solid #3a3a3a;border-radius:8px;flex-direction:column;width:min(600px,90vw);max-height:60vh;display:flex;overflow:hidden;box-shadow:0 16px 48px #0009}.quick-open-input{color:#f0f0f0;background:#161616;border:1px solid #4a4a4a;border-radius:5px;outline:none;flex:none;margin:8px;padding:8px 10px;font-size:14px}.quick-open-input:focus{border-color:#5a8bd6}.quick-open-list{flex:auto;padding:4px;overflow-y:auto}.quick-open-item{color:#e6e6e6;text-align:left;cursor:pointer;background:0 0;border:0;border-radius:4px;align-items:baseline;gap:8px;width:100%;padding:5px 8px;font-size:13px;display:flex}.quick-open-item.active{background:#37506f}.quick-open-name{white-space:nowrap;flex:none}.quick-open-dir{text-overflow:ellipsis;white-space:nowrap;color:#8a8a8a;flex:auto;min-width:0;font-size:12px;overflow:hidden}.quick-open-empty{color:#8a8a8a;text-align:center;padding:12px;font-size:13px}.quick-open-keys{color:#b0b0b0;white-space:nowrap;border:1px solid #4a4a4a;border-radius:4px;flex:none;margin-left:8px;padding:1px 6px;font-family:SFMono-Regular,Consolas,monospace;font-size:11px}.chord-hint{z-index:2147483200;color:#c7c7c7;background:#232323;border:1px solid #3a3a3a;border-radius:8px;align-items:center;gap:8px;padding:6px 12px;font-size:12px;display:flex;position:fixed;bottom:24px;left:50%;transform:translate(-50%);box-shadow:0 8px 24px #0000008c}.chord-hint kbd{color:#f0f0f0;background:#333;border:1px solid #4a4a4a;border-radius:4px;padding:2px 7px;font-family:SFMono-Regular,Consolas,monospace;font-size:12px}@media (pointer:coarse){input,textarea,select,[contenteditable]:not(.cm-content){font-size:16px!important}}
@@ -10,8 +10,8 @@
10
10
  <link rel="icon" type="image/png" sizes="32x32" href="/__castle/ide/favicon-32x32.png" />
11
11
  <link rel="icon" type="image/png" sizes="16x16" href="/__castle/ide/favicon-16x16.png" />
12
12
  <link rel="icon" href="/__castle/ide/favicon.ico" sizes="any" />
13
- <script type="module" crossorigin src="/__castle/ide/assets/index-BjOuaDJM.js"></script>
14
- <link rel="stylesheet" crossorigin href="/__castle/ide/assets/index-CdXEpv_P.css">
13
+ <script type="module" crossorigin src="/__castle/ide/assets/index-CUamb8rK.js"></script>
14
+ <link rel="stylesheet" crossorigin href="/__castle/ide/assets/index-Y6cJRRCX.css">
15
15
  </head>
16
16
  <body>
17
17
  <div id="root"></div>
@@ -0,0 +1 @@
1
+ export declare const UNSUPPORTED_MEDIA: Record<string, string>;
@@ -0,0 +1,54 @@
1
+ // Media formats the PLATFORM knows a deck can't ship, and what to do instead.
2
+ //
3
+ // This is the CLI's own knowledge, not a kit's, for two reasons. First, the trap
4
+ // is one the CLI sets: publishing inlines every asset as a `data:` URI, and a
5
+ // data URI's declared type is taken at face value where a served file gets its
6
+ // bytes sniffed -- so a `.mov` of ordinary H.264 plays all through editing and
7
+ // fails with MEDIA_ERR_SRC_NOT_SUPPORTED the moment the deck is saved. Second,
8
+ // the rest is about the browsers a published deck lands in, which is also the
9
+ // CLI's business and no kit's.
10
+ //
11
+ // It matters that this lives here rather than in a kit's castle.json: a kit's
12
+ // declarations only reach a deck that takes an import update, and the decks most
13
+ // likely to hit this are the ones that already exist. Shipped in the CLI, the
14
+ // warning reaches every deck the next time it is opened.
15
+ //
16
+ // A DECK still wins where it speaks: a format it declares as a file type is one
17
+ // it says it can handle, and nothing here contradicts that (see the shell's
18
+ // `unsupportedReason`). This list only talks about formats nobody claimed.
19
+ //
20
+ // Keep the reasons specific and end with the fix -- "convert it to X" is the
21
+ // whole value of the message.
22
+ export const UNSUPPORTED_MEDIA = {
23
+ // Video. Everything published has to be H.264 in an .mp4 container: it is the
24
+ // one combination that plays in every browser, including iOS.
25
+ ".mov": "QuickTime video plays while you edit but not in a published deck. Convert it to .mp4 (H.264).",
26
+ ".m4v": "Rename it to .mp4 — same container, and .m4v can also carry video browsers refuse.",
27
+ ".webm": "WebM does not play on iOS. Convert it to .mp4 (H.264).",
28
+ ".mkv": "No browser plays Matroska. Convert it to .mp4 (H.264).",
29
+ ".avi": "No browser plays AVI. Convert it to .mp4 (H.264).",
30
+ ".wmv": "No browser plays Windows Media. Convert it to .mp4 (H.264).",
31
+ ".flv": "No browser plays Flash video. Convert it to .mp4 (H.264).",
32
+ ".mpg": "No browser plays MPEG-1/2. Convert it to .mp4 (H.264).",
33
+ ".mpeg": "No browser plays MPEG-1/2. Convert it to .mp4 (H.264).",
34
+ ".3gp": "3GP does not play everywhere. Convert it to .mp4 (H.264).",
35
+ // Audio. .mp3 and .wav play everywhere; .m4a (AAC) rides along with the same
36
+ // decoder an .mp4 needs.
37
+ ".ogg": "Ogg does not play on iOS. Convert it to .mp3 or .m4a.",
38
+ ".oga": "Ogg does not play on iOS. Convert it to .mp3 or .m4a.",
39
+ ".opus": "Bare Opus does not play on iOS. Convert it to .mp3 or .m4a.",
40
+ ".flac": "FLAC does not play everywhere, and is far larger than a deck needs. Convert it to .mp3 or .m4a.",
41
+ ".aif": "AIFF does not play everywhere. Convert it to .mp3 or .wav.",
42
+ ".aiff": "AIFF does not play everywhere. Convert it to .mp3 or .wav.",
43
+ ".wma": "No browser plays Windows Media Audio. Convert it to .mp3 or .m4a.",
44
+ ".amr": "AMR does not play in browsers. Convert it to .mp3 or .m4a.",
45
+ // Images.
46
+ ".heic": "HEIC is an Apple camera format no browser displays. Convert it to .jpg or .png.",
47
+ ".heif": "HEIF is a camera format no browser displays. Convert it to .jpg or .png.",
48
+ ".avif": "AVIF does not display on older iOS. Convert it to .webp or .png.",
49
+ ".tif": "No browser displays TIFF. Convert it to .png or .jpg.",
50
+ ".tiff": "No browser displays TIFF. Convert it to .png or .jpg.",
51
+ ".bmp": "BMP is enormous for what it holds. Convert it to .png.",
52
+ ".psd": "A Photoshop file is not an image a browser can draw. Export it as .png.",
53
+ ".ai": "An Illustrator file is not an image a browser can draw. Export it as .svg or .png.",
54
+ };
@@ -1,6 +1,7 @@
1
1
  import * as path from 'path';
2
2
  import * as fs from 'fs';
3
3
  import { IMPORTS_DIR } from './imports.js';
4
+ import { resolveFileTypes } from './editorConfig.js';
4
5
  // Mirrors castle-web-sdk's IMPORTS_PREFIX, which is the definition deck code
5
6
  // uses. Duplicated rather than imported: the CLI compiles under node16 module
6
7
  // resolution and the SDK's published types don't, and one short string is not
@@ -17,28 +18,20 @@ const IMPORTS_PREFIX = '@imports/';
17
18
  //
18
19
  // `?raw` (and any other query suffix) is left untouched so the engine's
19
20
  // `import.meta.glob(..., { query: '?raw' })` still gets raw text.
20
- // Which extensions are data is the DECK's to say (castle.json `editor.fileTypes`
21
- // entries marked `data`); this list is only the fallback for a deck that
22
- // declares nothing, kept so decks written before the declaration existed behave
21
+ // Which extensions are data is DECLARED, never built in (castle.json
22
+ // `editor.fileTypes` entries marked `data`) -- by the deck or by any deck it
23
+ // imports, since a kit is an imported deck and its scenes and drawings are its
24
+ // own to define. This list is only the fallback for a deck where nothing
25
+ // declares anything, kept so decks written before the declaration existed behave
23
26
  // as they did.
24
27
  const FALLBACK_DATA_FILE_EXTS = ['.scene', '.drawing', '.pxart'];
25
28
  function dataFileExts(root) {
26
- try {
27
- const raw = fs.readFileSync(path.join(root, 'castle.json'), 'utf8');
28
- const types = JSON.parse(raw)?.editor?.fileTypes;
29
- if (Array.isArray(types)) {
30
- const declared = types
31
- .filter((t) => t && t.data === true && typeof t.ext === 'string')
32
- .map((t) => t.ext);
33
- // An explicit `fileTypes` with no data entries means exactly that: a deck
34
- // whose files are all modules.
35
- return declared;
36
- }
37
- }
38
- catch {
39
- /* no castle.json / unreadable -> fall back */
40
- }
41
- return FALLBACK_DATA_FILE_EXTS;
29
+ const resolved = resolveFileTypes(root);
30
+ // Declared file types with no data entries mean exactly that: a deck whose
31
+ // files are all modules. Only "nobody said anything" falls back.
32
+ if (!resolved)
33
+ return FALLBACK_DATA_FILE_EXTS;
34
+ return resolved.filter((t) => t.data === true).map((t) => t.ext);
42
35
  }
43
36
  // `@imports/<alias>/...` is how a deck names a file of another deck it imports,
44
37
  // in JS as in everything else (see castle-web-sdk's resolveDeckFile). Imports are
@@ -53,5 +53,5 @@
53
53
  "deckId": "5R39TxaRfLLQ",
54
54
  "cardId": "AZk0PWHTrFcT",
55
55
  "title": "basic-2d",
56
- "publishedVersion": "2026-07-28T19:19:13.421Z"
56
+ "publishedVersion": "2026-08-06T19:58:54.294Z"
57
57
  }
@@ -1,17 +1,15 @@
1
- // Discover every behavior class from `behaviors/*.jsx` and the physics module's
2
- // `physics/behaviors/**/*.jsx`. Vite HMR is off, so a newly-added behavior file is
3
- // picked up on the next reload/restart. The physics glob is what lets the
4
- // self-contained physics module ship its behaviors without polluting the core
5
- // `behaviors/` folder — a kit adopts physics by copying `physics/` in.
1
+ // Discover every behavior class from `behaviors/**/*.jsx`. Vite HMR is off, so a
2
+ // newly-added behavior file is picked up on the next reload/restart.
6
3
  // Root-anchored so the kit finds the DECK's behaviors even when the kit is
7
4
  // itself an import (see engine/files.js). Imports are swept first and the deck's
8
5
  // own behaviors last: collectBehaviors keys by behaviorName, so a behavior the
9
6
  // deck defines wins over one of the same name from a dependency.
7
+ // `behaviors/` is the ONE place behaviors live -- the rest of the system (the
8
+ // deck file map, the editor's visible paths, lint, the duplicate gate) keys off
9
+ // that directory, so a behavior kept anywhere else is invisible to all of it.
10
10
  const modules = {
11
11
  ...import.meta.glob('/imports/*/behaviors/**/*.jsx', { eager: true }),
12
- ...import.meta.glob('/imports/*/physics/behaviors/**/*.jsx', { eager: true }),
13
12
  ...import.meta.glob('/behaviors/**/*.jsx', { eager: true }),
14
- ...import.meta.glob('/physics/behaviors/**/*.jsx', { eager: true }),
15
13
  };
16
14
  function isBehaviorClass(value) {
17
15
  return typeof value === 'function' && typeof value.behaviorName === 'string';
@@ -22,10 +22,12 @@ Do you already know what you want to make, or do you want to figure it out toget
22
22
  - Editable screens live in `scenes/*.scene` files (plain JSON). Use a separate scene file per distinct screen, and switch with `scene.loadFromFile('name.scene')`.
23
23
  - Every actor is an instance of a **blueprint** (`blueprints/*.scene`) — see `## Blueprints` below. Always author the blueprint file yourself and reference it via `"blueprint"`. Don't write inline actors (full `components`, no `blueprint` field): the editor auto-migrates each one into its own new blueprint file on open, one per actor with no dedup, which litters the deck with junk blueprints.
24
24
  - Real game objects and scenery should usually be editable sprites: generate `.pxart` with `npm run draw -- name`, then place it via a `Sprite` component pointing at `drawings/name.pxart`. Dynamic UI/effects stay procedural.
25
+ - A deck can also hold uploaded media (the Files panel's Upload button): `Sprite` draws image files as well as `.pxart`, `Sound` and `Video` play audio and video files, and `Tone` synthesizes a note with no file at all. Point their `file` at the deck path (`assets/logo.png`).
26
+ - **Supported media formats are exactly**: `.png` `.jpg` `.jpeg` `.gif` `.webp` `.svg` images, `.mp3` `.wav` `.m4a` audio, `.mp4` (H.264) video. Nothing else — a published deck inlines every asset as a `data:` URI, where the browser trusts the declared type instead of sniffing the bytes, so a format that merely works while serving (`.mov` is the classic case) can be dead once published. Convert, don't improvise.
25
27
  - This kit is plain JavaScript. Use `.jsx` for files with JSX, `.js` otherwise; do not add TypeScript files or a new build step.
26
28
  - After any code, scene, or drawing edit, run `npm run restart`.
27
29
  - Space is reserved by the editor for play/stop; do not bind Space to gameplay.
28
- - Do not read `engine/`, `editors/`, or built-in behaviors (`Layout.jsx`, `Sprite.jsx`, `Collider.jsx`, `Camera.jsx`) to build a game. Their public API is documented below.
30
+ - Do not read `engine/`, `editors/`, or built-in behaviors (`Layout.jsx`, `Sprite.jsx`, `Collider.jsx`, `Camera.jsx`, and the physics ones — `RigidBody.jsx`, `Joints.jsx`, `Draggable.jsx`, `Slingshot.jsx`, `AnalogStick.jsx`) to build a game. Their public API is documented below.
29
31
  - Details below: `## Behavior shape`, `## Scene file`, `## Blueprints`, `## Built-in behaviors`, `## Creating pixel art`, `## SceneRuntime API`, and `## Input shortcuts`.
30
32
 
31
33
  ## Files and imports
@@ -143,7 +145,7 @@ Template `components` keys are behavior names (the `static behaviorName`); add a
143
145
  ## Built-in behaviors
144
146
 
145
147
  - **Layout** — `{ x, y, width, height, z?, rotation? }`. Every actor needs one. `z` orders draw (low first). `rotation` is degrees about the center.
146
- - **Sprite** — `{ file: "drawings/foo.pxart", tint?: "#rrggbbaa", playing?: true, tag?: "", mode?: 'cover'|'fit'|'stretch'|'tile', tileSize?: 50 }`. Renders a `.pxart` pixel-art sprite into the Layout box: scaled up preserving the art's aspect ratio to fill the whole box, cropping whatever overflows a mismatched box (`mode: 'cover'`, the default -- CSS object-fit: cover), scaled preserving the art's aspect ratio and centered so the whole sprite stays visible, letterboxing a mismatched box instead of cropping (`mode: 'fit'` -- CSS object-fit: contain), scaled to fill the box exactly and distorting the art when the aspect ratios don't match (`mode: 'stretch'`), or repeated (`mode: 'tile'`). `tint` multiplies; use white (`#ffffffff`) or omit for the original colors. Animated sprites play automatically; set `playing: false` to hold the first frame, or `tag` to play a named animation tag. Tile mode repeats the art at a fixed cell size (`tileSize` card units tall, width scaled by the art's aspect) instead of stretching it across the Layout box.
148
+ - **Sprite** — `{ file: "drawings/foo.pxart", tint?: "#rrggbbaa", playing?: true, tag?: "", mode?: 'cover'|'fit'|'stretch'|'tile', tileSize?: 50 }`. Renders the deck's 2D art into the Layout box. `file` is either a `.pxart` pixel-art sprite or an uploaded **image file** (`.png`, `.jpg`, `.jpeg`, `.gif`, `.webp`, `.svg`) — every prop below works the same on both, except that an image is a single still (no frames or tags) and is drawn smoothed rather than nearest-neighbour, which is what you want for a photo and not for pixel art. Draw modes: scaled up preserving the art's aspect ratio to fill the whole box, cropping whatever overflows a mismatched box (`mode: 'cover'`, the default -- CSS object-fit: cover), scaled preserving the art's aspect ratio and centered so the whole sprite stays visible, letterboxing a mismatched box instead of cropping (`mode: 'fit'` -- CSS object-fit: contain), scaled to fill the box exactly and distorting the art when the aspect ratios don't match (`mode: 'stretch'`), or repeated (`mode: 'tile'`). `tint` multiplies; use white (`#ffffffff`) or omit for the original colors. Animated sprites play automatically; set `playing: false` to hold the first frame, or `tag` to play a named animation tag. Tile mode repeats the art at a fixed cell size (`tileSize` card units tall, width scaled by the art's aspect) instead of stretching it across the Layout box.
147
149
  - **Missing sprites fall back to a placeholder.** If `file` names a sprite that doesn't exist yet, it renders the fallback `drawings/cauldron.pxart` — so you can give an actor its REAL intended sprite name (`drawings/paddle.pxart`) right away and it shows the placeholder until that file is created. Reference real names from the start; don't wait for the art.
148
150
  - **Fill the box, don't distort.** The default `mode: 'cover'` fills the Layout box with the art undistorted, cropping whatever overflows when the box aspect doesn't match the art's — so treat the Layout box like an image frame in a design tool: size it to frame what matters and keep the sprite's important content toward the center, since the edges may be cropped. Keeping an actor's Layout aspect ratio close to its sprite's native aspect ratio minimizes how much gets cropped. When the whole sprite must stay visible (nothing is safe to crop), use `mode: 'fit'`, which preserves the art and letterboxes the mismatched box instead. Avoid `mode: 'stretch'` for pixel art — filling a long/tall box by distorting wrecks the pixels (a brick sprite stretched into a wall ruins the bricks). For long surfaces (walls, floors, platforms), use `mode: 'tile'` on one actor to repeat the art at a fixed cell size instead of stretching or cropping a single sprite.
149
151
  - **Collider** — `{ kind: 'solid'|'pickup', mode?: 'auto'|'manual', width, height, offsetX?, offsetY?, debug? }`. Just a rect; `offsetX`/`offsetY` nudge the collider from its default position (so `0,0` is the default). `mode: 'auto'` (the default) fits the rect to the actor's Sprite's opaque pixels, mapped through the Sprite's draw mode (`fit`'s letterboxed dest rect, `stretch`'s full Layout box, `cover`'s filled box clipped to the Layout box; `tile` mode and a missing/unresolved Sprite use the whole Layout box instead). `width`/`height` only apply in `mode: 'manual'` (a rect of that size, centered in the Layout box); they're ignored in `auto`. The framework does NOT auto-resolve collisions for you. Use it as data:
@@ -158,6 +160,24 @@ Template `components` keys are behavior names (the `static behaviorName`); add a
158
160
  ```
159
161
 
160
162
  - **Camera** — `{ target: actorId, followX, followY, roomWidth, roomHeight }`. Place on a dedicated actor; sets `scene.camera` clamped to the room. Omit entirely for a fixed view (no camera = no translation).
163
+ - **Sound** — `{ file: "assets/hit.mp3", volume?: 1, playbackRate?: 1, pan?: 0, loop?: false, polyphonic?: false, playOnStart?: true }`. Plays an audio file (`.mp3`/`.wav`/`.m4a`) from an actor. `playbackRate` retunes it (2 = an octave up and twice as fast, 0.5 = an octave down); `pan` places it left (−1) to right (+1); `polyphonic` overlaps copies instead of cutting the last one off, which is what a sound effect fired twice in a row should do (leave it off for music). With `playOnStart` it starts with the scene; otherwise trigger it from code through the handle it puts on the actor:
164
+
165
+ ```jsx
166
+ scene.getActor('sfx').runtime.sound.play(); // restarts from the beginning
167
+ await actor.runtime.sound.play(); // ...and wait for it to finish
168
+ actor.runtime.sound.stop(); // also: pause(), resume(), .playing
169
+ scene.sound.stopAll(); // everything the scene is playing, off
170
+ ```
171
+
172
+ Sound only plays during play, never in the editor, and everything stops on Stop / a scene change. Browsers refuse audio until the player has touched the page; a sound that starts before that is queued and begins on the first tap or key, so don't work around it.
173
+ - **Tone** — `{ note?: 60, waveform?: 'square'|'sawtooth'|'sine'|'triangle'|'noise', attack?: 0, release?: 0.3, volume?: 0.5, pan?: 0, playOnStart?: false }`. Plays a synthesized note — no audio file, nothing downloaded, nothing stored. Reach for this before an audio file for blips, thuds and pickups. `note` is MIDI (60 = middle C, +12 an octave, +1 a semitone), and the note lasts `attack + release` seconds.
174
+
175
+ ```jsx
176
+ actor.runtime.tone.play(); // the note as configured
177
+ actor.runtime.tone.play({ note: 72 }); // ...or override per play, e.g. a rising scale
178
+ await actor.runtime.tone.play({ note: 48, waveform: 'noise' });
179
+ ```
180
+ - **Video** — `{ file: "assets/clip.mp4", mode?: 'cover'|'fit'|'stretch', playing?: true, loop?: true, muted?: true, volume?: 1 }`. Plays an `.mp4` (H.264) video inside the Layout box, drawn into the scene like a sprite: it moves with Layout, draws in `z` order, and can carry a Collider. `mode` frames it exactly as Sprite's does. In the editor it holds its first frame so you can place it. Leave `muted: true` unless the player has already interacted — an unmuted autoplaying video is blocked by browsers, a muted one isn't.
161
181
 
162
182
  ## Physics
163
183
 
@@ -349,27 +369,26 @@ draw(actor, scene, ctx) {
349
369
  - **A global max-speed clamp (`MAX_SPEED` in matterBridge)** backstops any joint
350
370
  blow-up so a body can't be flung off screen — normal motion never reaches it.
351
371
 
352
- ## Adding physics to another kit
353
-
354
- The physics module (`physics/`) is self-contained and portable. To add it to a
355
- different kit:
356
-
357
- 1. Copy the `physics/` folder into the kit.
358
- 2. Add `matter-js` to the kit's `package.json` dependencies.
359
- 3. In the kit's `engine/scene.js`: add a systems registry to `SceneRuntime`
360
- (`this.systems = []`, a `registerSystem(system)` method, at the end of
361
- `update(dt)` a `for (const s of this.systems) s.afterBehaviors?.(this, dt);`,
362
- and at the START of `load(sceneData)` a
363
- `for (const s of this.systems) s.reset?.(this);` so a reload/restart/scene
364
- transition resets the simulation to the authored layout instead of carrying
365
- over body positions + joints), then call `installPhysics(runtime)` from
366
- `makeScene` (and route `clone()` through `makeScene` so clones get it too).
367
- 4. In the kit's `editors/behaviorRegistry`, also glob
368
- `../physics/behaviors/*.jsx` so the physics behaviors auto-register.
369
-
370
- The module reuses the kit's `engine/collider.js` `getColliderRect(actor,
371
- sprites)` for shape geometry, so a kit needs that (both `basic-2d` and this kit
372
- have it).
372
+ ## Where physics lives in the kit
373
+
374
+ Physics is a normal part of this kit, not a bolt-on module. It uses the same
375
+ directories as everything else, because the rest of the system only looks in
376
+ those places:
377
+
378
+ - `behaviors/` `RigidBody`, `Joints`, `Draggable`, `Slingshot`, `AnalogStick`
379
+ sit alongside `Layout`/`Sprite`/`Collider`/`Camera`. This is the ONE directory
380
+ behaviors live in: the deck file map (`engine/files.js`), the editor's visible
381
+ paths (`castle.json`), the lint config, and the duplicate gate all key off it,
382
+ so a behavior kept anywhere else is invisible to all of them.
383
+ - `engine/physics/` the simulation itself (`PhysicsSystem.js`, `matterBridge.js`,
384
+ `joints.js`, `jointArt.js`, `controls.js`). Internal, like the rest of `engine/`.
385
+ - `systems/physics.js` the installer, auto-discovered by
386
+ `engine/systemRegistry.js` and invoked by `makeScene`, so the shared engine
387
+ never references physics directly.
388
+
389
+ That last seam is the generic one: any kit can add a per-frame system by dropping
390
+ a file in `systems/` that exports `installSystem(runtime)`, with no engine edits.
391
+ Physics is just this kit's use of it.
373
392
 
374
393
  ## Creating pixel art (`.pxart`)
375
394
 
@@ -1,7 +1,7 @@
1
1
  import React from 'react';
2
- import { Panel, SelectField } from '../../engine/ui';
3
- import { AutoFields, overrideProps } from '../../engine/autoInspector';
4
- import { analogVelocity, inActorWorldSpace, pressOnDraggable, stickVector } from '../controls';
2
+ import { Panel, SelectField } from '../engine/ui';
3
+ import { AutoFields, overrideProps } from '../engine/autoInspector';
4
+ import { analogVelocity, inActorWorldSpace, pressOnDraggable, stickVector } from '../engine/physics/controls';
5
5
 
6
6
  // AnalogStick: an on-screen virtual joystick that drives the actor it's on --
7
7
  // the look and feel of castle-client's Analog Stick. Press anywhere to place
@@ -88,7 +88,7 @@ export class Collider {
88
88
  // zone for pickup/goal logic) but doesn't block -- collisions are data.
89
89
  isTrigger: false,
90
90
  debug: false,
91
- // Physics material, read by physics/matterBridge.js. `bounciness` =
91
+ // Physics material, read by engine/physics/matterBridge.js. `bounciness` =
92
92
  // restitution (0 dead .. ~1 very bouncy); `friction` = surface friction;
93
93
  // `density` sets mass (= density x total shape area); matter's default 0.001.
94
94
  bounciness: 0,
@@ -1,7 +1,7 @@
1
1
  import React from 'react';
2
- import { Panel } from '../../engine/ui';
3
- import { AutoFields } from '../../engine/autoInspector';
4
- import { centerOf, chaseVelocity, inActorWorldSpace } from '../controls';
2
+ import { Panel } from '../engine/ui';
3
+ import { AutoFields } from '../engine/autoInspector';
4
+ import { centerOf, chaseVelocity, inActorWorldSpace } from '../engine/physics/controls';
5
5
 
6
6
  // Draggable: grab the actor with the pointer and fling it around. Chases the
7
7
  // pointer with a springy velocity (via the physics system) so it still collides
@@ -1,8 +1,8 @@
1
1
  import React, { useState } from 'react';
2
- import { Panel, SelectField, NumberField, CheckboxField, Button } from '../../engine/ui';
3
- import { centerOf, inActorWorldSpace } from '../controls';
4
- import { JOINT_TYPES } from '../joints';
5
- import { drawJointArt } from '../jointArt';
2
+ import { Panel, SelectField, NumberField, CheckboxField, Button } from '../engine/ui';
3
+ import { centerOf, inActorWorldSpace } from '../engine/physics/controls';
4
+ import { JOINT_TYPES } from '../engine/physics/joints';
5
+ import { drawJointArt } from '../engine/physics/jointArt';
6
6
 
7
7
  const RENDER_MODES = ['line', 'hidden', 'sprite'];
8
8
  // Bound anchor offsets (px, local frame). A large offset lengthens the pivot's
@@ -1,6 +1,6 @@
1
1
  import React from 'react';
2
- import { Panel, SelectField } from '../../engine/ui';
3
- import { AutoFields, overrideProps } from '../../engine/autoInspector';
2
+ import { Panel, SelectField } from '../engine/ui';
3
+ import { AutoFields, overrideProps } from '../engine/autoInspector';
4
4
 
5
5
  // RigidBody makes an actor a physics object. Pair it with a Collider (which
6
6
  // gives the shape + material). The simulation reads these props each frame; the
@@ -1,7 +1,7 @@
1
1
  import React from 'react';
2
- import { Panel } from '../../engine/ui';
3
- import { AutoFields } from '../../engine/autoInspector';
4
- import { inActorWorldSpace, pressOnDraggable, slingLaunch, slingPull } from '../controls';
2
+ import { Panel } from '../engine/ui';
3
+ import { AutoFields } from '../engine/autoInspector';
4
+ import { inActorWorldSpace, pressOnDraggable, slingLaunch, slingPull } from '../engine/physics/controls';
5
5
 
6
6
  // Slingshot: pull back and release to fling the actor the opposite way
7
7
  // (angry-birds style) -- the physics feel of castle-client's Sling. While