castle-web-cli 0.4.177 → 0.4.179
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agent-failures.js +4 -4
- package/dist/agent-prompts.d.ts +9 -1
- package/dist/agent-prompts.js +15 -2
- package/dist/agent.js +125 -40
- package/dist/deckLocatorShape.d.ts +16 -0
- package/dist/deckLocatorShape.js +28 -0
- package/dist/editorConfig.d.ts +1 -0
- package/dist/shell/assets/index-C5DS_7UM.js +447 -0
- package/dist/shell/assets/index-CoU3ETYM.css +1 -0
- package/dist/shell/index.html +2 -2
- package/kits/base/CLAUDE.md +3 -0
- package/kits/base/castle.json +21 -11
- package/kits/physics-2d/CLAUDE.md +41 -8
- package/kits/physics-2d/behaviors/AnalogStick.jsx +80 -4
- package/kits/physics-2d/behaviors/Slingshot.jsx +14 -2
- package/kits/physics-2d/behaviors/Sprite.jsx +17 -8
- package/kits/physics-2d/behaviors/Style.jsx +270 -0
- package/kits/physics-2d/behaviors/Text.jsx +213 -0
- package/kits/physics-2d/behaviors/Video.jsx +8 -4
- package/kits/physics-2d/blueprints/text.scene +12 -0
- package/kits/physics-2d/castle.json +10 -6
- package/kits/physics-2d/editors/SceneEditor.jsx +41 -0
- package/kits/physics-2d/editors/deckFont.js +65 -55
- package/kits/physics-2d/editors/fontPreview.js +6 -38
- package/kits/physics-2d/editors/pixelInspector.jsx +4 -154
- package/kits/physics-2d/engine/blueprint.js +28 -0
- package/kits/physics-2d/engine/fonts.js +125 -23
- package/kits/physics-2d/engine/paletteField.jsx +235 -0
- package/kits/physics-2d/engine/physics/controls.js +5 -81
- package/kits/physics-2d/engine/popoverDismiss.js +17 -0
- package/kits/physics-2d/engine/scene.js +12 -3
- package/kits/physics-2d/engine/spriteField.jsx +2 -15
- package/kits/physics-2d/engine/tap.js +90 -0
- package/kits/physics-2d/engine/text.js +94 -0
- package/kits/physics-2d/engine/ui.jsx +20 -0
- package/kits/physics-2d/engine/ui.module.css +10 -2
- package/kits/physics-3d/castle.json +4 -2
- package/package.json +1 -1
- package/dist/shell/assets/index-BWOEraUy.js +0 -447
- package/dist/shell/assets/index-BkVF1OXc.css +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
:root{--castle-font-body:baltomobile, Balto, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;--castle-font-display:Basteleur, Georgia, "Times New Roman", serif;--castle-font-mono:ui-monospace, SFMono-Regular, Menlo, monospace;--castle-text-size-small:11px;--castle-text-size-base:13px;--castle-text-size-large:15px;--castle-text-style-smallcaps-size:var(--castle-text-size-small);--castle-text-style-smallcaps-letter-spacing:.05em;--castle-text-style-smallcaps-transform:uppercase;--castle-text-primary:#e6e6e6;--castle-text-secondary:#b3b3b3;--castle-text-muted:#888;--castle-text-dim:#525252;--castle-text-dark:#111;--castle-surface-1:#000;--castle-surface-2:#0c0c0c;--castle-surface-3:#181818;--castle-surface-4:#242424;--castle-surface-5:#303030;--castle-surface-6:#3c3c3c;--castle-surface-light:#e6e6e6;--castle-border-1:#2a2a2a;--castle-border-2:#6a6a6a;--castle-border-3:#3a3a3a;--castle-border-4:#e6e6e6;--castle-accent:#793a80;--castle-danger-text:#e86a73;--castle-danger-surface:#73172d;--castle-danger-surface-hover:#b4202a;--castle-warn-text:#e8b25a;--castle-warn-surface:#5a3d0a;--castle-space-small:3px;--castle-space-base:6px;--castle-space-large:12px;--castle-radius-small:4px;--castle-radius-base:8px;--castle-radius-large:16px;--castle-radius-pill:999px;--castle-button-height:24px;--castle-button-icon-size:16px;--castle-button-height-large:36px;--castle-button-icon-size-large:24px;--castle-icon-size-inline:12px;--castle-panel-header-height:36px;--castle-panel-header-height-mobile:48px}.text-style-smallcaps{font-size:var(--castle-text-style-smallcaps-size);letter-spacing:var(--castle-text-style-smallcaps-letter-spacing);text-transform:var(--castle-text-style-smallcaps-transform)}.icon-inline{flex:0 0 var(--castle-icon-size-inline);width:var(--castle-icon-size-inline);height:var(--castle-icon-size-inline);font-size:var(--castle-icon-size-inline)}.icon-slot{flex:0 0 var(--castle-button-icon-size);width:var(--castle-button-icon-size);height:var(--castle-button-icon-size);justify-content:center;align-items:center;display:flex}.icon-cell{flex:0 0 var(--castle-button-height);width:var(--castle-button-height);height:var(--castle-button-height);color:var(--castle-text-dim);pointer-events:none;justify-content:center;align-items:center;display:inline-flex}.icon-slot svg,.icon-slot iconify-icon,.icon-cell svg,.icon-cell iconify-icon{flex:0 0 var(--castle-button-icon-size);width:var(--castle-button-icon-size);height:var(--castle-button-icon-size);font-size:var(--castle-button-icon-size)}.button{justify-content:center;align-items:center;gap:var(--castle-space-base);max-width:100%;height:var(--castle-button-height);padding:0 var(--castle-space-base);border-radius:var(--castle-radius-small);background:var(--castle-surface-4);color:var(--castle-text-primary);font-family:var(--castle-font-body);font-size:var(--castle-text-size-base);white-space:nowrap;cursor:pointer;border:0;line-height:1.3;display:inline-flex}.button:not(.button-icon){min-width:0}.button>span{text-overflow:ellipsis;white-space:nowrap;min-width:0;overflow:hidden}.button:hover,.button.is-hover{background:var(--castle-surface-5)}.button:active,.button.is-pressed{background:var(--castle-surface-3)}.button:focus-visible,.button.is-focus{outline:1px solid var(--castle-border-2);outline-offset:2px}.button[aria-pressed=true],.button[aria-pressed=true]:hover,.button[aria-pressed=true]:active{background:var(--castle-surface-light);color:var(--castle-text-dark)}.button:disabled{opacity:.4;cursor:default}.button-icon{width:var(--castle-button-height);padding:0}.button-icon-large{width:var(--castle-button-height-large);height:var(--castle-button-height-large)}.button-danger{background:var(--castle-danger-surface);color:var(--castle-text-primary)}.button-danger:hover,.button-danger.is-hover{background:var(--castle-danger-surface-hover)}.button-danger:active,.button-danger.is-pressed{background:var(--castle-danger-surface)}.button-quiet{color:var(--castle-text-dim);background:0 0}.button-quiet:hover,.button-quiet.is-hover{background:var(--castle-surface-5);color:var(--castle-text-primary)}.button-quiet:active,.button-quiet.is-pressed{background:var(--castle-surface-3)}.button-quiet[aria-pressed=true],.button-quiet[aria-pressed=true]:hover,.button-quiet[aria-pressed=true]:active{background:var(--castle-surface-5);color:var(--castle-text-primary)}.composer-action{border-radius:var(--castle-radius-pill);color:var(--castle-text-muted);box-shadow:inset 0 0 0 1px var(--castle-border-2);background:0 0}.composer-action:disabled{opacity:1;color:var(--castle-text-muted);box-shadow:inset 0 0 0 1px var(--castle-border-1);background:0 0}.composer-action:not(:disabled),.composer-action:not(:disabled):hover,.composer-action:not(:disabled):active,.composer-action:not(:disabled).is-hover,.composer-action:not(:disabled).is-pressed{background:var(--castle-surface-light);color:var(--castle-text-dark);box-shadow:none}.button svg,.button iconify-icon{width:var(--castle-button-icon-size);height:var(--castle-button-icon-size);font-size:var(--castle-button-icon-size)}.button-icon-large svg,.button-icon-large iconify-icon{width:var(--castle-button-icon-size-large);height:var(--castle-button-icon-size-large);font-size:var(--castle-button-icon-size-large)}.button-badge{min-width:16px;height:16px;padding:0 var(--castle-space-small);border-radius:var(--castle-radius-pill);background:var(--castle-surface-5);color:var(--castle-text-secondary);font-size:var(--castle-text-size-small);font-variant-numeric:tabular-nums;text-align:center;text-overflow:clip;flex:none;line-height:16px;overflow:hidden}.button>.button-badge{text-overflow:clip;min-width:16px;overflow:hidden}.text-field{min-width:0;height:var(--castle-button-height);padding:0 var(--castle-space-base);border:1px solid var(--castle-border-3);border-radius:var(--castle-radius-small);background:var(--castle-surface-3);color:var(--castle-text-primary);font-family:var(--castle-font-body);font-size:var(--castle-text-size-base);cursor:text;outline:0}.text-field::placeholder{color:var(--castle-text-muted)}.text-field:hover,.text-field.is-hover{background:var(--castle-surface-4)}.text-field:focus,.text-field:focus-visible,.text-field.is-focus{outline:1px solid var(--castle-border-2);outline-offset:2px}.text-field:disabled{opacity:.4;cursor:default}.select{min-width:0;height:var(--castle-button-height);padding:0 var(--castle-space-base);border:1px solid var(--castle-border-3);border-radius:var(--castle-radius-small);background:var(--castle-surface-3);color:var(--castle-text-primary);font-family:var(--castle-font-body);font-size:var(--castle-text-size-base);cursor:pointer;outline:0}.select:hover,.select.is-hover{background:var(--castle-surface-4)}.select:focus,.select:focus-visible,.select.is-focus{outline:1px solid var(--castle-border-2);outline-offset:2px}.select:disabled{opacity:.4;cursor:default}.dock-control{justify-content:center;align-items:center;gap:var(--castle-space-base);max-width:100%;height:var(--castle-panel-header-height);padding:0 var(--castle-space-large);border:1px solid var(--castle-border-1);border-radius:var(--castle-radius-base);background:var(--castle-surface-3);color:var(--castle-text-primary);font-family:var(--castle-font-body);font-size:var(--castle-text-size-base);white-space:nowrap;cursor:pointer;font-weight:600;line-height:1;display:inline-flex}.dock-control:not(.dock-control-icon){min-width:0}.dock-control>span{text-overflow:ellipsis;white-space:nowrap;min-width:0;overflow:hidden}.dock-control-icon{width:var(--castle-panel-header-height);padding:0}.dock-control-quiet{background:0 0;border-color:#0000;justify-content:flex-start;min-width:0}.dock-control-mark{background:var(--castle-surface-1)}.dock-control-group{cursor:default;box-shadow:inset 0 0 0 1px var(--castle-border-1);border:none;justify-content:flex-start;align-items:stretch;gap:0;padding:0;overflow:hidden}button.dock-control:hover,button.dock-control.is-hover{background:var(--castle-surface-4);border-color:var(--castle-border-3)}button.dock-control:active,button.dock-control.is-pressed{background:var(--castle-surface-2)}button.dock-control-quiet:active,button.dock-control-quiet.is-pressed{background:var(--castle-surface-3)}button.dock-control:focus-visible,button.dock-control.is-focus{outline:1px solid var(--castle-border-2);outline-offset:2px}.dock-control:disabled{opacity:.4;cursor:default}button.dock-control:disabled:hover,button.dock-control:disabled.is-hover{background:var(--castle-surface-3);border-color:var(--castle-border-1)}button.dock-control-quiet:disabled:hover,button.dock-control-quiet:disabled.is-hover{background:0 0;border-color:#0000}button.dock-control-mark:disabled:hover,button.dock-control-mark:disabled.is-hover{background:var(--castle-surface-1)}.dock-control svg,.dock-control iconify-icon{width:var(--castle-button-icon-size);height:var(--castle-button-icon-size);font-size:var(--castle-button-icon-size);flex-shrink:0}.dock-control-mark svg,.dock-control-mark img{width:20px;height:20px}.dock-control-mark img{object-fit:contain;display:block}.dock-segment{flex:0 0 var(--castle-panel-header-height);width:var(--castle-panel-header-height);height:var(--castle-panel-header-height);color:var(--castle-text-muted);cursor:pointer;background:0 0;border:none;border-radius:0;justify-content:center;align-items:center;padding:0;display:inline-flex}.dock-segment iconify-icon,.dock-segment svg{width:var(--castle-button-icon-size);height:var(--castle-button-icon-size);font-size:var(--castle-button-icon-size)}@media (hover:hover){.dock-segment:hover:not(.is-active){color:var(--castle-text-primary);background:var(--castle-surface-5)}}.dock-segment.is-hover:not(.is-active){color:var(--castle-text-primary);background:var(--castle-surface-5)}.dock-segment.is-active{color:var(--castle-text-dark);background:var(--castle-surface-light)}.dock-segment.is-drag-origin{opacity:0;pointer-events:none;flex:0 0 0;width:0;min-width:0;max-width:0;padding:0;overflow:hidden}.dock-segment-slot{flex:0 0 var(--castle-panel-header-height);width:var(--castle-panel-header-height);height:var(--castle-panel-header-height);color:var(--castle-text-primary);background:var(--castle-surface-6);pointer-events:none;justify-content:center;align-items:center;display:inline-flex}.dock-segment-slot iconify-icon,.dock-segment-slot svg{width:var(--castle-button-icon-size);height:var(--castle-button-icon-size);font-size:var(--castle-button-icon-size)}.dock-segment-ghost{border-radius:var(--castle-radius-small);pointer-events:none;box-shadow:0 8px 24px #00000073}.dock-segment:has(.dock-badge){position:relative}.dock-segment .dock-badge{top:var(--castle-space-small);right:var(--castle-space-small);z-index:1;background:var(--castle-surface-light);color:var(--castle-text-dark);pointer-events:none;transform-origin:50%;position:absolute}.dock-segment .dock-badge:not(.is-appearing){visibility:hidden;opacity:0;transform:scale(.45)}.dock-segment .dock-badge.is-appearing{visibility:visible;animation:.28s cubic-bezier(.2,.8,.2,1) both dock-badge-appear}@keyframes dock-badge-appear{0%{opacity:0;transform:scale(.45)}70%{opacity:1;transform:scale(1.08)}to{opacity:1;transform:scale(1)}}@media (prefers-reduced-motion:reduce){.dock-segment .dock-badge.is-appearing{animation:none}}.menu{gap:var(--castle-space-small);width:max-content;min-width:144px;padding:var(--castle-space-small);border:1px solid var(--castle-border-3);border-radius:var(--castle-radius-base);background:var(--castle-surface-5);flex-direction:column;display:flex;box-shadow:0 8px 24px #0000008c}.menu-item{align-items:center;gap:var(--castle-space-base);width:100%;height:26px;padding:0 var(--castle-space-base);border-radius:var(--castle-radius-small);color:var(--castle-text-primary);font-family:var(--castle-font-body);font-size:var(--castle-text-size-base);cursor:pointer;background:0 0;border:0;display:flex}.menu-icon{flex:0 0 16px;width:16px;height:16px;font-size:16px}svg.menu-icon,iconify-icon.menu-icon{fill:none;stroke:currentColor;stroke-linecap:round;stroke-linejoin:round;stroke-width:1.5px}.menu-icon svg,.menu-icon iconify-icon{width:16px;height:16px;font-size:16px}.menu-item:hover:not(:disabled),.menu-item.is-hover:not(:disabled){background:var(--castle-surface-6)}.menu-item:disabled{opacity:.4;cursor:default}.menu-item-label{text-overflow:ellipsis;white-space:nowrap;text-align:left;flex:auto;min-width:0;overflow:hidden}.menu-check{color:var(--castle-text-primary);flex:none}.menu-keys{margin-left:var(--castle-space-large);color:var(--castle-text-muted);font-size:var(--castle-text-size-small);white-space:nowrap;flex:none}.menu-item:disabled .menu-keys{color:inherit}.menu-item-danger{color:var(--castle-danger-text)}.menu-separator{height:1px;margin:var(--castle-space-small) 0;background:var(--castle-border-3)}.menu-header{padding:var(--castle-space-small) var(--castle-space-base);color:var(--castle-text-muted);font-size:var(--castle-text-size-small);letter-spacing:.04em;text-transform:uppercase}.menu-confirm{gap:var(--castle-space-base);min-width:180px;padding:var(--castle-space-small) var(--castle-space-base);flex-direction:column;display:flex}.menu-confirm-text{color:var(--castle-text-primary);font-size:var(--castle-text-size-base);margin:0}.menu-confirm-actions{justify-content:flex-end;gap:var(--castle-space-base);display:flex}.menu-error{padding:var(--castle-space-small) var(--castle-space-base);color:var(--castle-danger-text);font-size:var(--castle-text-size-small);margin:0}.feedback-quiet{--castle-feedback-text:var(--castle-text-muted);--castle-feedback-surface:var(--castle-surface-3);--castle-feedback-border:var(--castle-border-3)}.feedback-warn{--castle-feedback-text:var(--castle-warn-text);--castle-feedback-surface:var(--castle-warn-surface);--castle-feedback-surface-hover:color-mix(in srgb, var(--castle-warn-text) 35%, var(--castle-warn-surface));--castle-feedback-border:color-mix(in srgb, var(--castle-warn-text), var(--castle-warn-surface))}.feedback-danger{--castle-feedback-text:var(--castle-danger-text);--castle-feedback-surface:var(--castle-danger-surface);--castle-feedback-surface-hover:var(--castle-danger-surface-hover);--castle-feedback-border:color-mix(in srgb, var(--castle-danger-text), var(--castle-danger-surface))}.feedback-note{color:var(--castle-feedback-text);margin:0}.feedback-banner{align-items:center;gap:var(--castle-space-base);min-height:var(--castle-panel-header-height);padding:var(--castle-space-base);border-bottom:1px solid var(--castle-feedback-border);background:var(--castle-feedback-surface);color:var(--castle-feedback-text);font-size:var(--castle-text-size-base);display:flex}.feedback-banner>span:not(.icon-cell){flex:auto;min-width:0}.feedback-banner .icon-cell{color:inherit}.feedback-warn .button,.feedback-danger .button{border:1px solid var(--castle-feedback-border);background:var(--castle-feedback-surface);color:var(--castle-text-primary)}.feedback-warn .button:hover,.feedback-warn .button.is-hover,.feedback-danger .button:hover,.feedback-danger .button.is-hover{background:var(--castle-feedback-surface-hover)}.feedback-warn .button:active,.feedback-warn .button.is-pressed,.feedback-danger .button:active,.feedback-danger .button.is-pressed{background:var(--castle-feedback-surface)}.feedback-takeover{padding:calc(var(--castle-space-large) * 2);border:1px solid var(--castle-feedback-border);border-radius:var(--castle-radius-base);background:var(--castle-feedback-surface);color:var(--castle-feedback-text);font-size:var(--castle-text-size-base);text-align:center;justify-content:center;align-items:center;display:flex}.panel{border:1px solid var(--castle-border-1);border-radius:var(--castle-radius-base);background:var(--castle-surface-2);color:var(--castle-text-primary);font-family:var(--castle-font-body);transition:border-color .12s;position:relative;overflow:hidden}@media (hover:hover){.panel:hover{border-color:var(--castle-border-3)}}.panel.is-hover{border-color:var(--castle-border-3)}.panel.is-active,.panel.is-active:hover,.panel.is-active.is-hover{border-color:var(--castle-border-2)}.panel.is-dragging,.panel.is-dragging:hover,.panel.is-dragging.is-hover,.panel.is-dragging.is-active{border-color:var(--castle-border-4)}.panel-header,.panel-tabs-header{height:var(--castle-panel-header-height);padding:0 var(--castle-space-base);border-bottom:1px solid var(--castle-border-1);background:var(--castle-surface-3);align-items:center;display:flex}@media (hover:hover){.panel-header:hover,.panel-tabs-header:hover{background:var(--castle-surface-4);cursor:grab}}.panel-header.is-hover,.panel-tabs-header.is-hover{background:var(--castle-surface-4);cursor:grab}.panel-header:active,.panel-header.is-pressed,.panel-tabs-header:active,.panel-tabs-header.is-pressed{cursor:grabbing}.panel-tabs-header{align-items:stretch;gap:var(--castle-space-base)}.panel-title{align-items:center;gap:var(--castle-space-base);min-width:0;padding:0 var(--castle-space-base);color:var(--castle-text-primary);font-family:var(--castle-font-display);font-size:var(--castle-text-size-base);margin:0 auto 0 0;font-weight:700;line-height:1.5;display:inline-flex}.panel-title svg,.panel-title iconify-icon{width:var(--castle-button-icon-size);height:var(--castle-button-icon-size);font-size:var(--castle-button-icon-size);flex-shrink:0}.panel-header-actions{align-items:center;gap:var(--castle-space-small);margin-left:auto;display:flex}.panel-type-toggle{align-items:center;gap:var(--castle-space-base);min-width:0;max-width:100%;height:var(--castle-button-height);padding:0 var(--castle-space-base);border-radius:var(--castle-radius-small);color:var(--castle-text-primary);font-family:var(--castle-font-display);font-size:var(--castle-text-size-base);white-space:nowrap;cursor:pointer;background:0 0;border:0;align-self:center;font-weight:700;display:inline-flex}.panel-type-toggle:hover,.panel-type-toggle.is-hover,.panel-type-toggle[aria-pressed=true]{background:var(--castle-surface-5)}.panel-type-toggle svg,.panel-type-toggle iconify-icon{width:var(--castle-button-icon-size);height:var(--castle-button-icon-size);font-size:var(--castle-button-icon-size);flex-shrink:0}.panel-tabs{align-items:center;gap:var(--castle-space-base);flex:auto;min-width:0;display:flex}.panel-tab{max-width:160px;height:var(--castle-button-height);padding:var(--castle-space-small) var(--castle-space-base);border-radius:var(--castle-radius-small);color:var(--castle-text-dim);font-family:var(--castle-font-body);font-size:var(--castle-text-size-base);white-space:nowrap;cursor:pointer;background:0 0;border:0;align-items:center;line-height:18px;display:flex;position:relative;overflow:hidden}.panel-tab>span{text-overflow:ellipsis;min-width:0;overflow:hidden}.panel-tab:hover,.panel-tab.is-hover{background:var(--castle-surface-5);color:var(--castle-text-secondary)}.panel-tab.is-active{background:var(--castle-surface-5);color:var(--castle-text-primary)}.panel-tab:hover>span,.panel-tab.is-hover>span{-webkit-mask-image:linear-gradient(to right, #000 calc(100% - (var(--castle-button-icon-size) + var(--castle-space-large))), transparent 100%);mask-image:linear-gradient(to right, #000 calc(100% - (var(--castle-button-icon-size) + var(--castle-space-large))), transparent 100%)}.panel-tab.is-narrow:not(.is-active):hover>span,.panel-tab.is-narrow:not(.is-active).is-hover>span{-webkit-mask-image:none;mask-image:none}.panel-tab-close{z-index:1;top:var(--castle-space-small);right:var(--castle-space-small);width:calc(var(--castle-button-icon-size) + var(--castle-space-large));height:var(--castle-button-icon-size);border-radius:var(--castle-radius-small);background:linear-gradient(to right, transparent, var(--castle-surface-3) 45%);color:currentColor;cursor:pointer;opacity:0;pointer-events:none;border:0;justify-content:flex-end;align-items:center;padding:0;display:inline-flex;position:absolute}.panel-tab-close svg,.panel-tab-close iconify-icon{width:var(--castle-button-icon-size);height:var(--castle-button-icon-size);font-size:var(--castle-button-icon-size)}.panel-tab:hover .panel-tab-close,.panel-tab.is-hover .panel-tab-close,.panel-tab:focus-within .panel-tab-close{opacity:1;pointer-events:auto;background:linear-gradient(to right, transparent, var(--castle-surface-5) 45%)}.panel-tab.is-active .panel-tab-close{background:linear-gradient(to right, transparent, var(--castle-surface-5) 45%)}.panel-tab-close:hover,.panel-tab-close.is-hover{background:linear-gradient(to right, transparent, var(--castle-surface-5) 45%);color:var(--castle-text-primary)}.panel-tab.is-narrow:not(.is-active):hover .panel-tab-close,.panel-tab.is-narrow:not(.is-active).is-hover .panel-tab-close{opacity:0;pointer-events:none}.panel-tab.is-drag-origin{opacity:0;pointer-events:none;border:0;width:0;min-width:0;max-width:0;padding:0}.panel-tab-insert{width:2px;height:var(--castle-button-height);border-radius:var(--castle-radius-pill);background:var(--castle-border-4);pointer-events:none;flex:0 0 2px}.panel-tab-ghost{padding:var(--castle-space-base) var(--castle-space-large);border:1px solid var(--castle-border-1);border-radius:var(--castle-radius-small);background:var(--castle-surface-3);color:var(--castle-text-primary);font-size:var(--castle-text-size-base);pointer-events:none;box-shadow:0 8px 24px #00000073}.panel-mobile-current{justify-content:center;align-self:center;align-items:center;gap:var(--castle-space-base);min-width:0;max-width:100%;height:var(--castle-button-height-large);padding:0 var(--castle-space-base);border-radius:var(--castle-radius-small);color:var(--castle-text-primary);font-family:var(--castle-font-body);font-size:var(--castle-text-size-base);cursor:pointer;background:0 0;border:0;display:inline-flex}.panel-mobile-current:hover,.panel-mobile-current.is-hover{background:var(--castle-surface-5)}.panel-mobile-current-text{align-items:baseline;gap:var(--castle-space-small);min-width:0;display:flex}.panel-mobile-current-label{text-overflow:ellipsis;white-space:nowrap;min-width:0;overflow:hidden}.panel-mobile-current strong,.panel-mobile-current-type{font-family:var(--castle-font-display);flex-shrink:0;font-weight:700}.panel-mobile-current svg,.panel-mobile-current iconify-icon{width:var(--castle-button-icon-size-large);height:var(--castle-button-icon-size-large);font-size:var(--castle-button-icon-size-large);flex:none}.segmented{border-radius:var(--castle-radius-small);flex-wrap:wrap;align-items:stretch;display:flex;overflow:hidden}.segmented>.button{border-radius:0}.feedback-banner.is-inset{border-radius:var(--castle-radius-small);border-bottom:none}.feedback-banner.is-inset .button{flex:none;width:auto}.popover{width:max-content;max-width:calc(100vw - 24px);max-height:calc(100vh - 16px);padding:var(--castle-space-large);border:1px solid var(--castle-border-3);border-radius:var(--castle-radius-base);background:var(--castle-surface-4);color:var(--castle-text-primary);font-family:var(--castle-font-body);font-size:var(--castle-text-size-base);flex-direction:column;display:flex;overflow:auto;box-shadow:0 8px 24px #0000008c}.popover .button:not(.button-quiet){background:var(--castle-surface-5)}.popover .button:not(.button-quiet):hover,.popover .button:not(.button-quiet).is-hover{background:var(--castle-surface-6)}.popover .button:not(.button-quiet):active,.popover .button:not(.button-quiet).is-pressed{background:var(--castle-surface-4)}.popover .button[aria-pressed=true],.popover .button[aria-pressed=true]:hover,.popover .button[aria-pressed=true]:active{background:var(--castle-surface-light);color:var(--castle-text-dark)}.popover .feedback-warn .button:not(.button-quiet),.popover .feedback-danger .button:not(.button-quiet){border:1px solid var(--castle-feedback-border);background:var(--castle-feedback-surface);color:var(--castle-text-primary)}.popover .feedback-warn .button:not(.button-quiet):hover,.popover .feedback-warn .button:not(.button-quiet).is-hover,.popover .feedback-danger .button:not(.button-quiet):hover,.popover .feedback-danger .button:not(.button-quiet).is-hover{background:var(--castle-feedback-surface-hover)}.popover .feedback-warn .button:not(.button-quiet):active,.popover .feedback-warn .button:not(.button-quiet).is-pressed,.popover .feedback-danger .button:not(.button-quiet):active,.popover .feedback-danger .button:not(.button-quiet).is-pressed{background:var(--castle-feedback-surface)}: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:var(--castle-accent);--v2-accent-hover:color-mix(in srgb, var(--castle-accent) 84%, #fff);--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-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}.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-direction:column;flex:auto;min-width:0;min-height:0;display:flex}.editor-panel-view{flex:auto;min-width:0;min-height:0;position:relative}.editor-import-banner{background:var(--flow-surface,#181818);border-bottom:1px solid var(--v2-border,#2a2a2a);color:var(--v2-muted,#888);flex:none;align-items:center;gap:8px;padding:8px;font:12px ui-sans-serif,system-ui,sans-serif;display:flex}.editor-import-chip{border:1px solid var(--v2-border,#2a2a2a);background:var(--v2-raised,#161616);color:var(--v2-muted,#888);letter-spacing:.02em;border-radius:999px;flex:none;align-items:center;padding:2px 8px;font-size:12px;line-height:1.4;display:inline-flex}.editor-import-banner-text{text-overflow:ellipsis;white-space:nowrap;min-width:0;overflow:hidden}.editor-import-banner-action{border:1px solid var(--v2-border,#2a2a2a);background:var(--v2-raised,#161616);color:var(--v2-text,#ddd);font:inherit;cursor:pointer;border-radius:4px;flex:none;margin-left:auto;padding:2px 10px}.editor-import-banner-action:hover{border-color:var(--v2-muted,#888)}.editor-import-chip.editor-fork-chip{color:var(--v2-text,#ddd)}.editor-fork-modal-scrim{z-index:40;background:#00000080;justify-content:center;align-items:center;display:flex;position:fixed;inset:0}.editor-fork-modal{border:1px solid var(--v2-border,#2a2a2a);background:var(--flow-surface,#181818);max-width:420px;color:var(--v2-text,#ddd);border-radius:6px;padding:16px;font:13px ui-sans-serif,system-ui,sans-serif}.editor-fork-modal-title{margin-bottom:8px;font-weight:600}.editor-fork-modal-body{color:var(--v2-muted,#888);line-height:1.5}.editor-fork-modal-actions{justify-content:flex-end;gap:8px;margin-top:16px;display:flex}.editor-fork-modal-actions button{border:1px solid var(--v2-border,#2a2a2a);background:var(--v2-raised,#161616);color:var(--v2-text,#ddd);font:inherit;cursor:pointer;border-radius:4px;padding:4px 12px}.editor-fork-modal-actions button:hover{border-color:var(--v2-muted,#888)}.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}.editor-contextbar-reload{width:22px;height:22px;color:var(--v2-muted,#888);cursor:pointer;background:0 0;border:none;border-radius:5px;flex:none;justify-content:center;align-items:center;padding:0;display:inline-flex}.editor-contextbar-reload:hover{color:var(--v2-white,#fff);background:var(--v2-overlay-white-hover,#ffffff14)}.editor-contextbar-reload svg{width:13px;height:13px}.deck-panel{background:var(--v2-surface);width:100%;height:100%}.deck-frame{border:0;width:100%;height:100%;display:block}.play-panel{background:var(--castle-surface-2);flex-direction:column;width:100%;height:100%;display:flex}.play-scene-picker{padding:0 var(--castle-space-large) var(--castle-space-large);flex:none;justify-content:center;align-items:center;display:flex}.play-stage{min-height:0;padding:var(--castle-space-large);flex:auto;justify-content:center;align-items:center;display:flex;container-type:size}.play-stage:has(+.play-scene-picker){padding-bottom:var(--castle-space-base)}.play-frame-shell{aspect-ratio:5/7;border-radius:4%/2.85714%;width:min(100cqw,71.4286cqh);height:min(100cqh,140cqw);position:relative;overflow:hidden}.play-frame-shell .deck-frame{width:100%;height:100%}.play-logs{border-top:1px solid var(--castle-border-1);background:var(--castle-surface-2);color:var(--castle-text-secondary);flex:none;position:relative}.play-logs.is-open{--play-logs-height:160px;flex:0 0 var(--play-logs-height);height:var(--play-logs-height);flex-direction:column;min-height:0;display:flex;overflow:hidden}.play-logs-resize{z-index:2;cursor:row-resize;touch-action:none;height:12px;display:none;position:absolute;top:-6px;left:0;right:0}.play-logs.is-open>.play-logs-resize{display:block}body.play-logs-resizing,body.play-logs-resizing *{cursor:row-resize!important;-webkit-user-select:none!important;user-select:none!important}.play-logs-header{min-height:calc(var(--castle-button-height) + 2 * var(--castle-space-base));padding:var(--castle-space-base);align-items:center;column-gap:var(--castle-space-base);cursor:pointer;flex:none;grid-template-columns:minmax(0,1fr) minmax(0,max-content) max-content;display:grid;position:relative}.play-logs-header:hover{background:var(--castle-surface-3)}.play-logs-expand{z-index:0;cursor:pointer;background:0 0;border:0;padding:0;position:absolute;inset:0}.play-logs-expand:focus{outline:none}.play-logs-expand:focus-visible{outline:2px solid var(--castle-border-2);outline-offset:-2px}.play-logs-label{align-items:center;gap:var(--castle-space-base);min-width:0;color:var(--castle-text-dim);pointer-events:none;justify-self:start;display:inline-flex}.play-logs-header:hover .play-logs-label{color:var(--castle-text-primary)}.play-logs-label svg{flex:0 0 var(--castle-button-icon-size);width:var(--castle-button-icon-size);height:var(--castle-button-icon-size);font-size:var(--castle-button-icon-size)}.play-logs-pending{min-width:0;color:var(--castle-text-muted);font-size:var(--castle-text-size-small);text-overflow:ellipsis;white-space:nowrap;pointer-events:none;grid-column:2;margin:0;line-height:1.4;overflow:hidden}.play-logs-restart{z-index:1;grid-column:3;justify-self:end;min-width:max-content;position:relative}.play-logs-restart.is-pending,.play-logs-restart.is-pending:hover,.play-logs-restart.is-pending:active{color:var(--castle-warn-text)}.play-logs-restart-icon{line-height:1;display:inline-flex}.play-logs-restart-icon.is-spinning{animation:.6s linear infinite play-logs-spin}@keyframes play-logs-spin{to{transform:rotate(360deg)}}.play-logs-toolbar{align-items:center;gap:var(--castle-space-base);padding:var(--castle-space-base);border-top:1px solid var(--castle-border-1);flex-wrap:wrap;flex:none;display:flex}.play-logs-body{min-height:0;padding:var(--castle-space-base) var(--castle-space-large);border-top:1px solid var(--castle-border-1);font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:var(--castle-text-size-small);flex:auto;line-height:1.5;overflow-y:auto}.play-logs-line{white-space:pre-wrap;word-break:break-word}.play-logs-warn{color:var(--castle-warn-text)}.play-logs-error{color:var(--castle-danger-text)}.play-logs-empty{color:var(--castle-text-dim)}.flow-root.is-mobile .play-panel{--castle-text-size-small:14px;--castle-text-size-base:16px;--castle-text-style-smallcaps-size:var(--castle-text-size-small);--castle-button-height:var(--castle-button-height-large)}.flow-root.is-mobile .play-panel .button:not(.button-icon){padding-left:var(--castle-space-large);padding-right:var(--castle-space-large)}.flow-root.is-mobile .play-logs.is-open{--play-logs-height:200px}.flow-root.is-mobile .play-logs-header:hover{background:0 0}.flow-root.is-mobile .play-logs-header:hover .play-logs-label{color:var(--castle-text-dim)}.flow-root.is-mobile .play-stage{padding:var(--castle-space-small)}.term-panel{width:100%;height:100%;position:relative}.term-host{overscroll-behavior:contain;padding:6px;position:absolute;inset:0}.shell-root{--operator-pad:var(--castle-space-large);--operator-col-fit:min(var(--operator-col,400px), 100%);background:var(--v2-gutter);height:100%;position:relative}#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;display:flex;position:absolute;top:0;bottom:0;left:0;overflow:hidden}.settings-popover{z-index:2147483000;width:390px;position:fixed}.settings-popover .settings-row{flex-wrap:wrap;justify-content:space-between;align-items:center;gap:6px 10px;display:flex}.settings-popover .settings-row+.settings-row{margin-top:8px}.settings-popover .settings-label{white-space:nowrap}.settings-popover .settings-row-stack{flex-direction:column;align-items:stretch;gap:4px;display:flex}.settings-popover .settings-row-main{flex-wrap:wrap;justify-content:space-between;align-items:center;gap:6px 10px;display:flex}.settings-popover .settings-text-warn{border-color:var(--v2-warn)}.settings-popover .settings-warning{color:var(--v2-warn);text-align:right;font-size:11px;line-height:1.35}.settings-popover .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}.settings-popover .settings-warning-suggest:hover{color:var(--castle-text-primary)}.settings-popover .settings-group+.settings-group{border-top:1px solid var(--castle-border-1);margin-top:12px;padding-top:12px}.settings-popover .settings-credits{margin-top:var(--castle-space-base);color:var(--castle-text-secondary);font-size:var(--castle-text-size-base)}.settings-popover .settings-usage-subtext{margin-top:var(--castle-space-small);color:var(--castle-text-muted);font-size:var(--castle-text-size-small)}.settings-popover .settings-usage-subtext.feedback-note{color:var(--castle-feedback-text)}.settings-popover .settings-split{justify-content:space-between;align-items:center;gap:var(--castle-space-large);margin-top:var(--castle-space-base);display:flex}.settings-popover .settings-group>.settings-split:first-child{margin-top:0}.settings-popover .settings-split-copy,.settings-popover .settings-split>.settings-credits{flex:auto;min-width:0}.settings-popover .settings-split .settings-credits{margin-top:0}.settings-popover .settings-split .button{flex:none;width:auto;margin-left:auto}.settings-popover .settings-group>.feedback-banner.is-inset{margin-top:var(--castle-space-base)}.settings-popover .text-field{flex:auto}.settings-popover .select{flex:0 auto;max-width:60%}.settings-popover .settings-usage-bar{height:4px;margin-top:var(--castle-space-base);background:var(--castle-surface-5);border-radius:2px;overflow:hidden}.settings-popover .settings-usage-fill{background:var(--castle-accent);height:100%}.settings-popover .settings-usage-fill.blocked{background:var(--castle-danger-text)}.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{overflow-anchor:none;min-height:0;font-size:var(--castle-text-size-base);scrollbar-width:none;-ms-overflow-style:none;flex-direction:column;flex:1 1 0;padding:0;line-height:1.5;display:flex;overflow-y:auto}#chat-messages .chat-thread{gap:var(--castle-space-large);padding-bottom:var(--castle-space-large);opacity:0;flex-direction:column;transition:opacity .12s;display:flex}#chat-messages .chat-thread.ready{opacity:1}.shell-root.docked #chat-messages{padding:0}.shell-root.docked #chat-messages>:first-child{margin-top:auto}#chat-messages::-webkit-scrollbar{width:0;height:0}#chat-empty{color:var(--castle-text-muted)}#chat-host .msg{margin:0}#chat-host .msg.user{text-align:right}#chat-host .msg.user span:not(.msg-image){background:var(--castle-surface-light);color:var(--castle-text-dark);padding:var(--castle-space-base) var(--castle-space-large);border-radius:var(--castle-radius-large);text-align:left;white-space:pre-wrap;word-break:break-word;max-width:85%;display:inline-block}#chat-host .msg-image{border:1px solid var(--castle-border-1);border-radius:var(--castle-radius-base);max-width:220px;max-height:150px;margin:0 0 var(--castle-space-base) auto;display:block}#chat-host .assistant-turn{align-items:flex-start;gap:var(--castle-space-base);flex-direction:column;margin:0;display:flex}#chat-host .assistant-turn .feedback-note{max-width:85%}#chat-host .msg.assistant{background:var(--castle-accent);width:fit-content;color:var(--castle-surface-light);padding:var(--castle-space-base) var(--castle-space-large);border-radius:var(--castle-radius-large);word-break:break-word;max-width:85%;margin:0}#chat-host .msg.assistant.errbubble{background:var(--castle-danger-surface);color:var(--castle-danger-text)}#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(--castle-text-muted);font-size:var(--castle-text-size-base);font-family:var(--castle-font-mono);word-break:break-word}#chat-host .msg-error-detail{font-size:var(--castle-text-size-base);color:var(--castle-text-muted)}#chat-host .msg-error-detail summary{cursor:pointer;-webkit-user-select:none;user-select:none}#chat-host .msg-error-detail pre{margin:var(--castle-space-small) 0 0;padding:var(--castle-space-base);background:var(--castle-surface-1);border-radius:var(--castle-radius-small);font-size:var(--castle-text-size-small);white-space:pre-wrap;word-break:break-word;max-height:160px;overflow-y:auto}#chat-host .operator-line,#chat-host .msg-thinking{color:var(--castle-text-muted);font-size:var(--castle-text-size-base)}#chat-host .operator-line{align-items:center;gap:var(--castle-space-base);display:flex}#chat-host .operator-line .icon-inline{flex:0 0 var(--castle-icon-size-inline)}#chat-host .operator-line .icon-inline:not(:first-child){color:var(--castle-text-dim)}#chat-host .operator-line-link{color:inherit;font:inherit;text-underline-offset:2px;cursor:pointer;background:0 0;border:0;padding:0;text-decoration:underline}#chat-host .operator-line-link:hover{color:var(--castle-text-primary)}#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{transform-origin:50%;transition:transform .12s}#chat-host .msg-thinking[open] .thinking-caret{transform:rotate(90deg)}#chat-host .msg-thinking.is-active .thinking-label{background-image:linear-gradient(90deg, var(--castle-text-muted) 20%, var(--castle-text-primary) 50%, var(--castle-text-muted) 80%);color:#0000;-webkit-text-fill-color:transparent;background-size:200% 100%;-webkit-background-clip:text;background-clip:text;animation:1.6s linear infinite thinking-shimmer;display:inline-block}@keyframes thinking-shimmer{0%{background-position:100% 0}to{background-position:-100% 0}}@media (prefers-reduced-motion:reduce){#chat-host .msg-thinking.is-active .thinking-label{color:var(--castle-text-muted);-webkit-text-fill-color:currentColor;background:0 0;animation:none}}#chat-host .msg-thinking-body{max-height:160px;padding:0 var(--castle-space-large) 0 calc(var(--castle-icon-size-inline) + var(--castle-space-base));border-radius:var(--castle-radius-small);background:var(--castle-surface-1);color:var(--castle-text-muted);font-size:var(--castle-text-size-base);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 .task-notes li,#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:not(.msg-link),#chat-host .msg-thinking-body a:not(.msg-link),#chat-host .task-notes a:not(.msg-link),#chat-host .task-feed-msg a:not(.msg-link){color:var(--castle-surface-light);text-underline-offset:2px;text-decoration:underline}#chat-host .msg-link{border-radius:var(--castle-radius-small);color:inherit;font-family:var(--castle-font-mono);-webkit-text-decoration-color:color-mix(in srgb, currentColor 40%, transparent);text-decoration-color:color-mix(in srgb, currentColor 40%, transparent);text-underline-offset:2px;margin:0 -.35em;padding:.1em .35em}#chat-host .msg-link:hover{background:var(--castle-surface-4);color:var(--castle-text-primary);text-decoration-color:currentColor}#chat-host .msg.assistant .msg-link:hover{background:color-mix(in srgb, var(--castle-accent) 84%, #fff)}#chat-host .msg.md code{font-family:var(--castle-font-mono);font-size:var(--castle-text-size-small);background:color-mix(in srgb, var(--castle-accent) 78%, #000);border-radius:var(--castle-radius-small);padding:.1em .35em}#chat-host .msg.md pre{margin:var(--castle-space-base) 0;padding:var(--castle-space-base) var(--castle-space-large);background:color-mix(in srgb, var(--castle-accent) 72%, #000);border-radius:var(--castle-radius-small);white-space:pre-wrap;word-break:break-word;font-family:var(--castle-font-mono);font-size:var(--castle-text-size-small);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{margin:var(--castle-space-base) 0;padding-left:var(--castle-space-large);border-left:3px solid color-mix(in srgb, var(--castle-accent) 60%, #fff)}.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{margin:0 calc(-1 * var(--operator-pad));background:var(--castle-border-1);flex:0 0 1px}.task-stack{gap:var(--castle-space-small);flex-direction:column;display:flex}#task-board{min-height:0;margin-inline:calc(-1 * var(--castle-space-base));padding-inline:var(--castle-space-base);padding-top:0;padding-bottom:var(--castle-space-base);scrollbar-width:thin;scrollbar-color:transparent transparent;flex-direction:column;flex:0 auto;max-height:40vh;display:flex;overflow:hidden auto}#task-board.scrolling{scrollbar-color:var(--castle-text-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(--castle-text-dim)}#chat-host .task{margin:0 calc(-1 * var(--castle-space-base));border-radius:var(--castle-radius-small);cursor:pointer;transition:background .12s,box-shadow .12s}#chat-host .task.open{background:var(--castle-surface-2);box-shadow:inset 0 0 0 1px var(--castle-border-1)}#chat-host .task:hover{background:var(--castle-surface-3)}#chat-host .task-row{align-items:center;gap:var(--castle-space-large);padding:var(--castle-space-small) var(--castle-space-base);display:flex;position:relative}#chat-host .task.open .task-row{align-items:flex-start;padding-bottom:0}#chat-host .pie{background:conic-gradient(var(--castle-surface-light) calc(var(--pct,0) * 3.6deg), var(--castle-surface-5) 0deg);border-radius:50%;flex:0 0 32px;width:32px;height:32px;padding:2px;display:flex;position:relative}#chat-host .pie .avatar{background:var(--castle-surface-3);width:100%;height:100%;color:var(--castle-text-dark);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;font-size: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:var(--castle-space-base);display:flex}#chat-host .task-text{flex:1;min-width:0}#chat-host .task-name{color:var(--castle-text-muted);font-size:var(--castle-text-size-base);text-overflow:ellipsis;white-space:nowrap;overflow:hidden}#chat-host .task-name .tn{color:var(--castle-text-primary);font-weight:600}#chat-host .task-sub{color:var(--castle-text-muted);font-size:var(--castle-text-size-small);text-overflow:ellipsis;white-space:nowrap;font-variant-numeric:tabular-nums;overflow:hidden}#chat-host .task-actions{align-items:center;gap:var(--castle-space-small);visibility:hidden;flex:none;margin-left:auto;display:flex}#chat-host .task:hover .task-actions,#chat-host .task.open .task-actions{visibility:visible}#chat-host .task-board-header{z-index:1;justify-content:space-between;align-items:center;gap:var(--castle-space-base);margin-inline:calc(-1 * var(--castle-space-base));padding:var(--castle-space-large) var(--castle-space-base) var(--castle-space-base);background:var(--castle-surface-1);display:flex;position:sticky;top:0}#chat-host .task-board-actions{align-items:center;gap:var(--castle-space-large);display:flex}#chat-host .task-board-status{font-size:var(--castle-text-size-base);color:var(--castle-text-muted)}#chat-host .task-body{padding:0 0 var(--castle-space-base);font-size:var(--castle-text-size-base);color:var(--castle-text-secondary);display:none}#chat-host .task.open .task-body{display:block}#chat-host .task-notes{margin-top:var(--castle-space-small);font-size:var(--castle-text-size-base);color:var(--castle-text-secondary);word-break:break-word}#chat-host .task-body>.feedback-note{margin-top:var(--castle-space-small)}#chat-host .task-notes code{border-radius:var(--castle-radius-small);font-family:var(--castle-font-mono);padding:1px 4px;font-size:12px}#chat-host .task-playtest-frames{margin-top:var(--castle-space-base)}#chat-host .task-playtest-frames-label{font-size:var(--castle-text-size-small);color:var(--castle-text-muted);margin-bottom:var(--castle-space-small)}#chat-host .task-playtest-frames-row{gap:var(--castle-space-base);flex-wrap:wrap;display:flex}#chat-host .task-playtest-frame{object-fit:cover;border:1px solid var(--castle-border-1);background:var(--castle-text-dark);border-radius:4px;width:64px;height:90px;display:block}#chat-host .task-feed{margin-top:var(--castle-space-base);scrollbar-width:none;-ms-overflow-style:none;max-height:96px;font-size:var(--castle-text-size-base);color:var(--castle-text-secondary);cursor:default;word-break:break-word;line-height:1.5;overflow:hidden auto;-webkit-mask-image:linear-gradient(#0000,#000 8px 100%);mask-image:linear-gradient(#0000,#000 8px 100%)}#chat-host .task-feed::-webkit-scrollbar{width:0;height:0}#chat-host .task-feed-tool{padding-left:var(--castle-space-large);color:var(--castle-text-muted);font-family:var(--castle-font-mono);white-space:pre-wrap;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{font-family:var(--castle-font-mono);font-size:var(--castle-text-size-base)}#chat-host .task-page{min-height:0;margin-inline:calc(-1 * var(--operator-pad));flex-direction:column;flex:1 1 0;display:flex}#chat-host .task-page-header{padding:var(--castle-space-large) var(--operator-pad);border-bottom:1px solid var(--castle-border-1);flex:none}#chat-host .task-page-header .task-row{padding:0}#chat-host .task-page-header .tn{color:var(--castle-text-primary)}#chat-host .task-page-body{min-height:0;padding:var(--castle-space-large) var(--operator-pad);flex:1 1 0;overflow:auto}#chat-host .task-page-body .task-feed{max-height:none;margin-top:0;overflow:visible;-webkit-mask-image:none;mask-image:none}#chat-host .task-page-body:not(.task-board-page) .task-notes{margin-top:var(--castle-space-large);padding-top:var(--castle-space-large);border-top:1px solid var(--castle-border-1)}#chat-host .task-page-body:not(.task-board-page) .task-notes:first-child{border-top:0;margin-top:0;padding-top:0}#chat-host .task-report-label{margin:0 0 var(--castle-space-small);color:var(--castle-text-primary);font-weight:700}#chat-host .task-page-empty{color:var(--castle-text-muted);margin:0}#chat-host .task-board-page{min-height:0;margin-inline:calc(-1 * var(--operator-pad));padding:var(--castle-space-large) var(--operator-pad);flex-direction:column;flex:1 1 0;display:flex;overflow:auto}#chat-host .task-archive{margin-top:var(--castle-space-base);padding-top:var(--castle-space-large);border-top:1px solid var(--castle-border-1)}#chat-host .task-archive:first-child{border-top:0;margin-top:0;padding-top:0}#chat-host .task-archive-heading{margin:0 0 var(--castle-space-large);color:var(--castle-text-muted)}#chat-host .operator-composer{flex-direction:column;flex:0 auto;min-height:0;max-height:50%;display:flex;overflow:auto}.chat-input{padding:0 var(--operator-pad) var(--operator-pad);flex:none;position:relative}#chat-host .chat-input .ta{width:100%;min-height:60px;padding:var(--castle-space-base) var(--castle-space-small);border:1px solid var(--castle-border-1);border-radius:var(--castle-radius-base);background:var(--castle-surface-2);cursor:text;flex-direction:column;display:flex;overflow:hidden}#chat-input{width:100%;min-height:21px;max-height:120px;padding:0 var(--castle-space-base);color:var(--castle-text-primary);font:inherit;font-size:var(--castle-text-size-base);resize:none;scrollbar-width:none;-ms-overflow-style:none;background:0 0;border:none;outline:none;line-height:1.5;display:block;overflow-y:auto}#chat-input::-webkit-scrollbar{width:0;height:0}#chat-input::placeholder{color:var(--castle-text-muted)}#chat-host .chat-input .ta-bottom{justify-content:space-between;align-items:center;gap:var(--castle-space-base);min-width:0;display:flex}#chat-host .composer-settings{flex:auto;min-width:0}#chat-host .composer-settings .button{min-width:0;max-width:100%;font-size:var(--castle-text-size-small);justify-content:flex-start}#chat-host .composer-settings .operator-usage-warn,#chat-host .composer-settings .operator-usage-warn:hover,#chat-host .composer-settings .operator-usage-warn[aria-pressed=true]{color:var(--castle-warn-text)}#chat-host .composer-settings .operator-usage-blocked,#chat-host .composer-settings .operator-usage-blocked:hover,#chat-host .composer-settings .operator-usage-blocked[aria-pressed=true]{color:var(--castle-danger-text)}#chat-host .queue-row .button,#chat-host .ta-bottom .button-icon{flex-shrink:0}#chat-host .composer-action{margin-right:var(--castle-space-small)}#chat-pending{gap:var(--castle-space-base);padding:0 var(--operator-pad) var(--castle-space-base);flex:none;display:flex}#chat-pending .operator-thumb{object-fit:cover;border:1px solid var(--castle-border-1);border-radius:var(--castle-radius-small);cursor:pointer;width:64px;height:44px;margin:0;display:block}#chat-host .chat-input .chat-queue{gap:var(--castle-space-small);margin-bottom:var(--castle-space-base);flex-direction:column;display:flex}#chat-host .chat-input .queue-row{align-items:center;gap:var(--castle-space-base);padding:var(--castle-space-base) var(--castle-space-base) var(--castle-space-base) var(--castle-space-large);border:1px dashed var(--castle-border-1);border-radius:var(--castle-radius-base);background:var(--castle-surface-1);color:var(--castle-text-muted);font-size:var(--castle-text-size-base);display:flex}#chat-host .chat-input .queue-snippet{text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0;overflow:hidden}#chat-host .picker{gap:var(--castle-space-large);width:100%;padding:var(--castle-space-large);border:1px solid var(--castle-border-1);border-radius:var(--castle-radius-base);background:var(--castle-surface-3);flex-direction:column;align-self:stretch;margin:0;display:flex}#chat-host .picker-q{border:none;min-width:0;margin:0;padding:0}#chat-host .picker-q-label{margin:0 0 var(--castle-space-base);color:var(--castle-text-primary);font-size:var(--castle-text-size-base);font-weight:inherit;padding:0}#chat-host .picker-options{gap:var(--castle-space-small);flex-direction:column;display:flex}#chat-host .picker-option{align-items:center;gap:var(--castle-space-base);padding:var(--castle-space-small) var(--castle-space-base);border-radius:var(--castle-radius-small);color:var(--castle-text-secondary);cursor:pointer;display:flex}#chat-host .picker-option input{appearance:none;border:1px solid var(--castle-border-2);border-radius:var(--castle-radius-small);background:var(--castle-surface-3);width:12px;height:12px;cursor:inherit;flex:none;place-content:center;margin:0;display:grid}#chat-host .picker-option input[type=radio]{border-radius:var(--castle-radius-pill)}#chat-host .picker-option input:checked{border-color:var(--castle-surface-light);background:var(--castle-surface-light)}#chat-host .picker-option input:before{content:"";display:block}#chat-host .picker-option input[type=radio]:checked:before{border-radius:var(--castle-radius-pill);background:var(--castle-text-dark);width:4px;height:4px}#chat-host .picker-option input[type=checkbox]:checked:before{border-left:1.5px solid var(--castle-text-dark);border-bottom:1.5px solid var(--castle-text-dark);width:6px;height:3px;margin-top:-2px;transform:rotate(-45deg)}#chat-host .picker:not(.picker-locked) .picker-option:hover,#chat-host .picker-option.is-checked{background:var(--castle-surface-5);color:var(--castle-text-primary)}#chat-host .picker-option:has(input:checked){background:var(--castle-surface-5);color:var(--castle-text-primary)}#chat-host .picker-locked{opacity:.72}#chat-host .picker-locked .picker-option{cursor:default}#chat-host .picker-actions{justify-content:flex-end;display:flex}#chat-host .chips{justify-content:flex-end;align-self:flex-end;gap:var(--castle-space-base);max-width:85%;margin:var(--castle-space-small) 0 var(--castle-space-small);flex-wrap:wrap;display:flex}#chat-host .chip{padding:var(--castle-space-base) var(--castle-space-large);border:1px dotted var(--castle-surface-light);border-radius:var(--castle-radius-pill);color:var(--castle-surface-light);font:inherit;font-size:var(--castle-text-size-base);text-align:left;cursor:pointer;background:0 0;line-height:1.3}#chat-host .chips-inert .chip{border-color:var(--castle-text-dim);color:var(--castle-text-muted);cursor:default}#chat-host .chip.is-picked,#chat-host .chips-inert .chip.is-picked{border-style:solid;border-color:var(--castle-surface-light);background:var(--castle-surface-light);color:var(--castle-text-dark)}#chat-host .msg-file{color:inherit;font:inherit;text-underline-offset:2px;text-decoration:underline;-webkit-text-decoration-color:color-mix(in srgb, currentColor 40%, transparent);text-decoration-color:color-mix(in srgb, currentColor 40%, transparent);cursor:pointer;word-break:break-all;background:0 0;border:0;margin:0;padding:0;display:inline}#chat-host .msg-file:hover{text-decoration-color:currentColor}#chat-host .picker-skeleton{pointer-events:none}#chat-host .picker-skeleton-hint{color:var(--castle-text-muted);font-size:var(--castle-text-size-base)}#chat-host .picker-skeleton-line,#chat-host .picker-skeleton-chip{border-radius:var(--castle-radius-small);background:var(--castle-border-1);display:block}#chat-host .picker-skeleton-label{width:60%;height:11px;margin-bottom:var(--castle-space-base)}#chat-host .picker-skeleton-chip{height:24px}.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}.mention-picker{z-index:2147483100;background:#232323;border:1px solid #3a3a3a;border-radius:8px;width:min(360px,90vw);max-height:40vh;padding:4px;position:fixed;overflow-y:auto;box-shadow:0 16px 48px #0009}.mention-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}.mention-item.active{background:#37506f}.mention-name{white-space:nowrap;flex:none}.mention-dir{text-overflow:ellipsis;white-space:nowrap;color:#8a8a8a;flex:auto;min-width:0;font-size:12px;overflow:hidden}.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}}.cm-url,.cm-md-link{color:var(--v2-link,#82aaff);text-underline-offset:2px;cursor:pointer;text-decoration:underline;text-decoration-thickness:1px}.cm-url:hover,.cm-md-link:hover{color:var(--v2-white,#fff)}.castle-file-panel,.castle-code-panel,.castle-params-panel,.castle-params-overlay,.flow-class-files{--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-toolbar .button-icon{margin-left:auto}.castle-file-toolbar .button-icon+.button-icon{margin-left:0}.castle-file-toolbar.versions-toolbar{padding-left:var(--castle-space-large);justify-content:space-between}.versions-toolbar-label{text-overflow:ellipsis;white-space:nowrap;min-width:0;color:var(--castle-text-muted);line-height:1;overflow:hidden}.castle-versions{flex-direction:column;flex:1 1 0;min-height:0;display:flex}.versions-error{align-items:flex-start}.versions-error>span:not(.icon-cell){white-space:pre-line}.versions-save{align-items:center;gap:var(--castle-space-base);flex-wrap:wrap;padding:0;display:flex}.versions-save .text-field{flex:130px;width:auto;min-width:0}.versions-save .button{white-space:nowrap;flex:none}.versions-note{padding:var(--castle-space-large) var(--castle-space-large) 0;color:var(--castle-text-muted);font-size:var(--castle-text-size-base)}.versions-empty{padding:var(--castle-space-large);color:var(--castle-text-muted);font-size:var(--castle-text-size-base)}.castle-versions-list{flex:1 1 0;min-height:0;overflow-y:auto}.version{align-items:start;column-gap:var(--castle-space-base);padding:var(--castle-space-base) var(--castle-space-base) var(--castle-space-large);border-bottom:1px solid var(--castle-border-1);grid-template-columns:minmax(0,1fr) auto;display:grid}.version-toggle{grid-template-columns:var(--castle-button-height) minmax(0, 1fr);align-items:start;column-gap:var(--castle-space-base);min-width:0;color:inherit;font:inherit;text-align:left;cursor:pointer;background:0 0;border:0;grid-area:1/1/auto/-1;margin:0;padding:0;display:grid}.version.is-expanded:not(.version-new) .version-toggle{grid-column:1}.version-toggle:focus-visible{outline:1px solid var(--castle-border-2);outline-offset:2px}.version.later,.version.later .icon-cell,.version.later .version-message,.version.later .version-nomessage,.version.later .version-meta,.version.later .version-summary{color:var(--castle-text-dim)}.version:hover{background:var(--castle-surface-3)}.version-main{gap:var(--castle-space-small);flex-direction:column;min-width:0;display:flex}.version-heading{align-items:center;gap:var(--castle-space-base);min-width:0;min-height:var(--castle-button-height);display:flex}.version-message{text-overflow:ellipsis;white-space:nowrap;min-width:0;color:var(--castle-text-primary);font-size:var(--castle-text-size-base);flex:auto;overflow:hidden}.version-nomessage{color:var(--castle-text-muted);font-style:italic}.version-meta{color:var(--castle-text-muted);font-size:var(--castle-text-size-small);margin:0;display:block}.version-actions{min-height:var(--castle-button-height);flex:none;grid-area:1/2;align-items:center;display:none}.version.is-expanded .version-actions{display:flex}.version-detail{padding-left:calc(var(--castle-button-height) + var(--castle-space-base));grid-column:1/-1;display:none}.version-new{flex:none}.version.is-expanded .version-detail{gap:var(--castle-space-small);flex-direction:column;display:flex}.version-summary{color:var(--castle-text-secondary);font-size:var(--castle-text-size-base);overflow-wrap:anywhere;margin:0}.files-feedback-banner{flex:none}.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}.castle-file-menu{z-index:1000;min-width:168px;position:fixed}.castle-file-menu .menu-keys{font-family:SFMono-Regular,Consolas,monospace}.castle-file-picker{gap:var(--castle-space-small);flex-direction:column;min-width:180px;display:flex}.castle-file-picker .text-field{width:100%}.castle-file-picker-label{color:var(--castle-text-muted);margin:0}.castle-file-picker-list{gap:var(--castle-space-small);flex-direction:column;max-height:min(40vh,180px);display:flex;overflow-y:auto}.castle-file-picker-list[hidden]{display:none}.fileBrowserBare{flex-direction:column;min-width:0;height:100%;display:flex}.fileTree{min-height:0;padding:var(--castle-space-base);flex:1 1 0;overflow-y:auto}.fileBranch{min-width:0}.file-row,.file-row.folder-row{align-items:center;gap:var(--castle-space-base);width:100%;min-width:0;height:var(--castle-button-height);margin:0 0 var(--castle-space-small);padding:0 var(--castle-space-base);padding-left:calc(var(--castle-space-base) + var(--file-depth,0) * (var(--castle-button-icon-size) + var(--castle-space-base)));border-radius:var(--castle-radius-small);color:var(--castle-text-secondary);font-size:var(--castle-text-size-base);text-align:left;cursor:pointer;background:0 0;border:0;line-height:1;display:flex}.file-row.folder-row{color:var(--castle-text-muted)}.file-row>span:not(.icon-slot):not(.icon-inline):not(.icon-cell){text-overflow:ellipsis;white-space:nowrap;min-width:0;overflow:hidden}.file-row:hover{background:var(--castle-surface-3);color:var(--castle-text-primary)}.file-row.imported-row{color:var(--castle-text-muted);font-style:italic}.file-row.forked-row{color:var(--castle-text-secondary);font-style:normal}.file-row.selected-row,.file-row.selected-row:hover{background:var(--castle-surface-4);color:var(--castle-text-primary)}.file-row.hidden-row{color:var(--castle-text-dim)}:is(.file-row:has(.button-icon),.file-row:has(.icon-cell)){padding-right:0}.file-row .button-icon,.file-row .icon-cell{margin-left:auto}.file-row.edit-row{height:auto;min-height:var(--castle-button-height);cursor:default;flex-wrap:wrap}.file-row.edit-row .text-field{flex:auto;width:auto}.file-suffix{color:var(--castle-text-muted);flex:none}.file-row .file-edit-feedback{padding-left:calc(var(--castle-button-icon-size) + var(--castle-space-base));padding-bottom:var(--castle-space-small);font-size:var(--castle-text-size-small);white-space:normal;flex:1 0 100%;line-height:1.45;overflow:visible}.flow-root.is-mobile .castle-file-panel,.flow-mobile-switch{--castle-button-height:var(--castle-button-height-large)}.flow-mobile-switch{--castle-text-size-small:14px;--castle-text-size-base:16px;--castle-text-style-smallcaps-size:var(--castle-text-size-small)}.flow-root.is-mobile .castle-file-panel .button:not(.button-icon){padding-left:var(--castle-space-large);padding-right:var(--castle-space-large)}.flow-root.is-mobile .file-row,.flow-mobile-switch .file-row{margin-bottom:0}.flow-root.is-mobile .file-row>span:not(.icon-slot):not(.icon-inline):not(.icon-cell),.flow-mobile-switch .file-row>span:not(.icon-slot):not(.icon-inline):not(.icon-cell){line-height:var(--castle-button-height)}.flow-root.is-mobile .file-row:hover,.flow-mobile-switch .file-row:hover{color:var(--castle-text-secondary);background:0 0}.flow-root.is-mobile .file-row.folder-row:hover,.flow-root.is-mobile .file-row.imported-row:hover,.flow-mobile-switch .file-row.folder-row:hover,.flow-mobile-switch .file-row.imported-row:hover{color:var(--castle-text-muted)}.flow-root.is-mobile .file-row.hidden-row:hover,.flow-mobile-switch .file-row.hidden-row:hover{color:var(--castle-text-dim)}.flow-root.is-mobile .file-row.selected-row:hover,.flow-mobile-switch .file-row.selected-row:hover{background:var(--castle-surface-4);color:var(--castle-text-primary)}.flow-root.is-mobile .version:hover{background:0 0}.castle-code-panel{flex-direction:column;width:100%;height:100%;display:flex;position:relative}.mainEditor{background:var(--castle-sheet-bg);flex-direction:column;flex:1 1 0;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}.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-modal>.castle-file-picker{width:100%;min-width:0}.castle-upload-input{opacity:0;pointer-events:none;width:1px;height:1px;position:absolute}.castle-upload-drop{justify-content:center;align-items:center;gap:var(--castle-space-small);width:100%;padding:calc(var(--castle-space-large) + var(--castle-space-base)) var(--castle-space-large);border:1px dashed var(--castle-border-3);border-radius:var(--castle-radius-small);background:var(--castle-surface-3);color:var(--castle-text-primary);font:inherit;cursor:pointer;flex-direction:column;display:flex}.castle-upload-drop:hover,.castle-upload-drop.over{border-color:var(--castle-border-2);background:var(--castle-surface-5)}.castle-upload-drop svg{font-size:var(--castle-button-icon-size)}.castle-upload-drop-label{font-size:var(--castle-text-size-base)}.castle-upload-drop-hint{color:var(--castle-text-muted);font-size:var(--castle-text-size-small)}.castle-upload-picked{flex-direction:column;max-height:132px;display:flex;overflow-y:auto}.castle-upload-picked-row{align-items:center;gap:var(--castle-space-base);min-height:var(--castle-button-height);padding:var(--castle-space-small) 0;display:flex}.castle-upload-picked-row+.castle-upload-picked-row{border-top:1px solid var(--castle-border-1)}.castle-upload-picked-name{min-width:0;font-size:var(--castle-text-size-base);flex-direction:column;flex:auto;justify-content:center;display:flex}.castle-upload-picked-label{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.castle-upload-picked-name .text-field{width:100%}.castle-upload-picked-warning{color:var(--castle-warn-text);font-size:var(--castle-text-size-small);white-space:normal;margin-top:2px;display:block}.castle-upload-picked-size{color:var(--castle-text-muted);font-size:var(--castle-text-size-small);font-variant-numeric:tabular-nums;flex:none}.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:var(--castle-space-large) var(--castle-space-base)}.castle-upload-picked{max-height:104px}.castle-file-picker-list{max-height:132px}}.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}.castle-code-params-strip{border:0;border-bottom:1px solid var(--castle-inspector-border);background:var(--castle-inspector-input-bg);width:100%;color:var(--castle-inspector-muted);font:inherit;text-align:left;cursor:pointer;align-items:center;gap:8px;padding:6px 12px;font-size:12px;display:flex}.castle-code-params-strip:hover{color:var(--castle-inspector-text)}.castle-code-params-icon{flex:none;display:inline-flex}.castle-code-params-count{text-overflow:ellipsis;white-space:nowrap;min-width:0;overflow:hidden}.castle-code-params-action{color:var(--castle-inspector-text);flex:none;margin-left:auto}.castle-code-selection-bar{z-index:2;position:absolute;bottom:12px;right:12px}.castle-params-panel{background:var(--castle-sheet-bg);height:100%;color:var(--castle-inspector-text);-webkit-overflow-scrolling:touch;font-size:14px;overflow:hidden auto}.paramsFields{padding:10px 16px 24px}.paramsGroup+.paramsGroup{margin-top:6px}.paramsGroupTitle{color:var(--castle-inspector-muted);text-transform:uppercase;letter-spacing:.06em;margin:0 0 10px;font-size:12px}.paramsGroup+.paramsGroup>.paramsGroupTitle{border-top:1px solid var(--castle-inspector-divider);margin-top:10px;padding-top:10px}.paramsNotice{color:var(--castle-inspector-muted);padding:16px}.paramsSaveError{border-bottom:1px solid var(--castle-inspector-border);color:var(--castle-inspector-text);background:#be464629;padding:8px 16px;font-size:13px}.paramsScopeBar{z-index:2;border-bottom:1px solid var(--castle-inspector-border);background:var(--castle-sheet-bg);align-items:center;gap:8px;padding:6px 10px;display:flex;position:sticky;top:0}.paramsScopeButton{border:1px solid var(--castle-inspector-border);border-radius:var(--castle-radius);background:var(--castle-inspector-input-bg);min-width:0;color:var(--castle-inspector-text);font:inherit;cursor:pointer;align-items:center;gap:6px;padding:4px 8px;font-size:13px;display:flex}.paramsScopeIcon,.paramsScopeChevron{flex:none;display:inline-flex}.paramsScopeLabel{text-overflow:ellipsis;white-space:nowrap;min-width:0;overflow:hidden}.paramsScopeSummary{color:var(--castle-inspector-muted);font-size:12px}.paramsScopeMenu{max-width:calc(100% - 16px);max-height:60vh;position:absolute;top:100%;left:8px;overflow-y:auto}.paramsScopeMenu .menu-item-label{text-overflow:ellipsis;white-space:nowrap;text-align:left;direction:rtl;overflow:hidden}.paramsScopeDivider{color:var(--castle-inspector-muted);text-transform:uppercase;letter-spacing:.06em;padding:6px 10px 4px;font-size:11px}.paramsScopeCount,.paramsFileCount{color:var(--castle-inspector-muted);font-variant-numeric:tabular-nums;flex:none;margin-left:auto;padding-left:10px;font-size:12px}.paramsFile+.paramsFile{border-top:1px solid var(--castle-inspector-divider)}.paramsFileHead{align-items:center;padding:0 6px 0 0;display:flex}.paramsFileHead~.paramsFields{padding-bottom:6px}.paramsFileToggle{min-width:0;color:var(--castle-inspector-text);font:inherit;text-align:left;cursor:pointer;background:0 0;border:0;flex:1;align-items:center;gap:6px;padding:8px 4px 8px 10px;font-size:12px;display:flex}.paramsFileChevron{color:var(--castle-inspector-muted);flex:none;display:inline-flex}.paramsFilePath{text-overflow:ellipsis;white-space:nowrap;text-align:left;min-width:0;font-family:var(--castle-font-mono);direction:rtl;overflow:hidden}.paramsFileOpen{border-radius:var(--castle-radius);color:var(--castle-inspector-muted);cursor:pointer;background:0 0;border:0;flex:none;padding:4px 6px;display:inline-flex}.paramsFileOpen:hover{color:var(--castle-inspector-text)}.paramsScopeBar .paramsFileOpen{margin-left:auto}.paramsEmpty{max-width:46em;padding:20px 16px}.paramsEmptyLead{color:var(--castle-inspector-text);margin:0 0 10px;font-size:15px}.paramsEmptyBody{color:var(--castle-inspector-muted);margin:0 0 12px;line-height:1.5}.paramsEmpty code{font-family:var(--castle-font-mono);color:var(--castle-inspector-text);font-size:13px}.paramsEmptyCode{border:1px solid var(--castle-inspector-border);border-radius:var(--castle-radius);background:var(--castle-inspector-input-bg);color:var(--castle-inspector-text);font-family:var(--castle-font-mono);margin:0 0 14px;padding:10px 12px;font-size:13px;line-height:1.45;overflow-x:auto}.castle-params-panel .paramExpr{text-overflow:ellipsis;white-space:nowrap;border:1px dashed var(--castle-inspector-border);border-radius:var(--castle-radius);min-width:0;color:var(--castle-inspector-muted);font-family:var(--castle-font-mono);cursor:default;padding:5px 8px;font-size:13px;overflow:hidden}.castle-params-panel .fieldRow{grid-template-columns:minmax(82px,.5fr) minmax(0,1fr);align-items:center;gap:12px;min-height:28px;padding-bottom:12px;display:grid}.castle-params-panel .fieldRow.paramFieldRevealed{animation:1.4s ease-out paramFieldReveal}@keyframes paramFieldReveal{0%,60%{background:var(--castle-inspector-input-bg);box-shadow:0 0 0 4px var(--castle-inspector-input-bg)}to{background:0 0;box-shadow:0 0 0 4px #0000}}.castle-params-panel .fieldLabel{color:var(--castle-inspector-text);text-overflow:ellipsis;font-size:14px;overflow:hidden}.castle-params-panel .input{border:1px solid var(--castle-inspector-border);border-radius:var(--castle-radius);background:var(--castle-inspector-input-bg);width:100%;color:var(--castle-inspector-text);font:inherit;outline:0;padding:5px 8px}.castle-params-panel .numberField{width:100%;position:relative}.castle-params-panel .numberInput{appearance:textfield}.castle-params-panel .numberInput::-webkit-inner-spin-button{appearance:none;margin:0}.castle-params-panel .numberInput::-webkit-outer-spin-button{appearance:none;margin:0}.castle-params-panel .numberScrub{cursor:ew-resize;-webkit-user-select:none;user-select:none;align-items:center;gap:6px;display:flex;position:relative;overflow:hidden}.castle-params-panel .numberValue{z-index:1;text-align:right;font-variant-numeric:tabular-nums;flex:auto;min-width:0;position:relative}.castle-params-panel .scrubGrip{z-index:1;color:var(--castle-inspector-muted);letter-spacing:-2px;opacity:.4;flex:none;font-size:12px;line-height:1;position:relative}.castle-params-panel .colorInput{border:1px solid var(--castle-inspector-border);border-radius:var(--castle-radius);background:var(--castle-inspector-input-bg);cursor:pointer;outline:0;width:100%;height:28px;padding:2px}.castle-params-panel .checkbox{border:1px solid var(--castle-inspector-border);border-radius:var(--castle-radius);background:var(--castle-inspector-input-bg);cursor:pointer;width:20px;height:20px;box-shadow:none;color:var(--castle-text);flex:none;justify-content:center;justify-self:end;align-items:center;padding:0;display:flex}.castle-params-panel .checkboxOn{background:var(--castle-black)}.castle-params-panel .checkboxMark{width:12px;height:12px;display:none}.castle-params-panel .checkboxOn .checkboxMark{display:block}.castle-params-overlay .scrubBubble{z-index:1001;border:1px solid var(--castle-inspector-border);color:var(--castle-inspector-text);font-variant-numeric:tabular-nums;pointer-events:none;background:#14181ef5;border-radius:8px;padding:3px 10px;font-size:15px;position:fixed;transform:translate(-50%,-100%);box-shadow:0 2px 10px #00000073}.castle-params-overlay .numpadBackdrop{z-index:1000;background:#00000059;flex-direction:column;justify-content:flex-end;display:flex;position:fixed;inset:0}.castle-params-overlay .numpadSheet{background:var(--castle-inspector-bg,#16181d);border-top:1px solid var(--castle-inspector-border);padding:10px 10px calc(10px + env(safe-area-inset-bottom,0px));border-radius:14px 14px 0 0;box-shadow:0 -8px 24px #0006}.castle-params-overlay .numpadValueRow{justify-content:space-between;align-items:baseline;gap:12px;padding:6px 8px 12px;display:flex}.castle-params-overlay .numpadValueLabel{color:var(--castle-inspector-text);text-overflow:ellipsis;white-space:nowrap;min-width:0;font-size:22px;overflow:hidden}.castle-params-overlay .numpadValueNum{color:var(--castle-inspector-text);font-variant-numeric:tabular-nums;flex:none;font-size:22px}.castle-params-overlay .numpadGrid{grid-template-columns:repeat(4,1fr);gap:8px;display:grid}.castle-params-overlay .numpadKey{border:1px solid var(--castle-inspector-border);background:var(--castle-inspector-input-bg);height:52px;color:var(--castle-inspector-text);cursor:pointer;touch-action:manipulation;border-radius:10px;font-size:20px}.castle-params-overlay .numpadKey:active{background:var(--castle-inspector-divider)}.castle-params-overlay .numpadKeyZero{grid-column:span 3}.castle-params-overlay .numpadKeyDone{color:#fff;background:#5a8cd2e6;border-color:#0000;font-size:16px}.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}@font-face{font-family:Basteleur;src:url(/__castle/ide/assets/Basteleur-Bold-DKFKedNb.woff2)format("woff2"),url(/__castle/ide/assets/Basteleur-Bold-CK8LF7Pt.woff)format("woff");font-weight:700;font-style:normal}.flow-root{--flow-gutter:#000;--flow-surface:#181818;--flow-chip:#282828;--flow-font-display:"Basteleur", Georgia, "Times New Roman", serif;--flow-fg:#e6e6e6;--flow-secondary:#b3b3b3;--flow-muted:#888;--flow-dim:#525252;--flow-border:#2a2a2a;--flow-border-active:#5a5a5a;--flow-gap:12px;--flow-dock-h:36px;--flow-tab-h:var(--castle-panel-header-height);--flow-icon-dock:var(--castle-button-icon-size);--flow-btn-sm:var(--castle-button-height);--flow-host-l:0px;--flow-host-r:0px;--flow-max-chips:6;--flow-chip-size:36px;--flow-chips-w:calc(var(--flow-max-chips) * var(--flow-chip-size));--flow-fade:22px;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 *{touch-action:none;-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);align-items:center;gap:var(--castle-space-base);z-index:40;pointer-events:none;padding-left:var(--flow-host-l);padding-right:var(--flow-host-r);grid-template-columns:minmax(0,1fr) minmax(0,auto) minmax(0,1fr);display:grid;position:absolute}.flow-topbar-leading{justify-self:start;align-items:center;gap:var(--castle-space-base);pointer-events:none;min-width:0;display:flex}.flow-topbar-leading>*{pointer-events:auto}.flow-castle-wrap{flex-shrink:0;position:relative}.flow-menu-backdrop{z-index:49;position:fixed;inset:0}.flow-castle-menu{top:calc(var(--flow-dock-h) + var(--castle-space-base));z-index:50;position:absolute;left:0}.flow-menu-narrow{display:none}.flow-deck-identity{max-width:260px}.flow-deck-vis{color:var(--flow-secondary);flex-shrink:0;font-size:14px;display:inline-flex}.flow-deck-vis svg{width:14px;height:14px}.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-draft-status{color:var(--flow-muted);font-size:var(--castle-text-size-small);white-space:nowrap;flex-shrink:0}.flow-draft-status.is-error{color:var(--castle-danger-text)}.flow-tabs-wrap{pointer-events:auto;justify-self:center;align-items:center;gap:var(--castle-space-base);min-width:0;max-width:100%;display:flex}.flow-tabs{min-width:0;max-width:var(--flow-chips-w);flex:0 auto;position:relative}.flow-tabs-scroll{scrollbar-width:none;align-items:stretch;gap:0;height:100%;padding:0;display:flex;overflow:auto hidden}.flow-tabs-scroll::-webkit-scrollbar{display:none}.flow-tabs.more-left{-webkit-mask-image:linear-gradient(to right, transparent, #000 var(--flow-fade));-webkit-mask-image:linear-gradient(to right, transparent, #000 var(--flow-fade));mask-image:linear-gradient(to right, transparent, #000 var(--flow-fade));border-top-left-radius:0;border-bottom-left-radius:0}.flow-tabs.more-right{-webkit-mask-image:linear-gradient(to left, transparent, #000 var(--flow-fade));-webkit-mask-image:linear-gradient(to left, transparent, #000 var(--flow-fade));mask-image:linear-gradient(to left, transparent, #000 var(--flow-fade));border-top-right-radius:0;border-bottom-right-radius:0}.flow-tabs.more-left.more-right{-webkit-mask-image:linear-gradient(to right, transparent, #000 var(--flow-fade), #000 calc(100% - var(--flow-fade)), transparent);-webkit-mask-image:linear-gradient(to right, transparent, #000 var(--flow-fade), #000 calc(100% - var(--flow-fade)), transparent);mask-image:linear-gradient(to right, transparent, #000 var(--flow-fade), #000 calc(100% - var(--flow-fade)), transparent)}.button.flow-tabs-add{width:var(--castle-button-height-large);height:var(--castle-button-height-large);border-radius:var(--castle-radius-base);flex-shrink:0}.flow-chip-icon{font-size:var(--flow-icon-dock);display:inline-flex}.flow-chip-icon svg{width:var(--flow-icon-dock);height:var(--flow-icon-dock)}.flow-topbar-trailing{justify-self:end;align-items:center;gap:var(--castle-space-base);pointer-events:none;min-width:0;display:flex}.flow-preview-btn{pointer-events:auto;flex-shrink:0}.flow-preview-btn-failed{color:var(--castle-danger-text);border-color:var(--castle-danger-text)}.flow-preview-label{justify-items:center;display:grid}.flow-preview-label>*{grid-area:1/1}.flow-preview-label-sizer{visibility:hidden;pointer-events:none}.flow-root.is-mobile{--flow-max-chips:4;--flow-gap:var(--castle-space-base);--castle-text-size-small:14px;--castle-text-size-base:16px;--castle-text-style-smallcaps-size:var(--castle-text-size-small);--flow-tab-h:var(--castle-panel-header-height-mobile);--flow-icon-dock:var(--castle-button-icon-size-large);--flow-btn-sm:var(--castle-button-height-large)}.flow-root.is-mobile .flow-deck-identity,.flow-root.is-mobile .flow-topbar-trailing{display:none}.flow-root.is-mobile .flow-topbar{grid-template-columns:auto minmax(0,1fr)}.flow-root.is-mobile .flow-tabs-wrap{justify-self:start}.flow-root.is-mobile .flow-topbar-leading:not(:has(.flow-castle-wrap)):not(:has(.flow-draft-status)){display:none}.flow-root.is-mobile .menu-item.flow-menu-narrow{display:flex}.flow-root.is-mobile .menu-separator.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);padding-right:calc(var(--flow-gap) + var(--flow-overscroll,0px));display:flex}.flow-group{flex-direction:column;min-width:200px;display:flex;overflow:clip}.flow-root.is-mobile .panel:hover,.flow-root.is-mobile .panel.is-hover,.flow-root.is-maximized .panel:hover,.flow-root.is-maximized .panel.is-hover{border-color:var(--castle-border-1)}.flow-root.is-mobile .panel-header:hover,.flow-root.is-mobile .panel-tabs-header:hover{background:var(--castle-surface-3);cursor:default}.operator-chrome{align-items:stretch;gap:var(--castle-space-base);flex:auto;min-width:0;display:flex}.flow-tab-icon{font-size:var(--flow-icon-dock);flex-shrink:0;justify-content:center;align-items:center;display:inline-flex}.flow-drop-indicator{background:var(--castle-border-4);z-index:60;pointer-events:none;border-radius:2px;width:3px;position:fixed;transform:translate(-50%)}.flow-group.pinned{left:var(--flow-gap);z-index:5;position:sticky;box-shadow:0 6px 24px #00000073}.flow-panel-body{flex:auto;min-height:0;position:relative;overflow:hidden}.flow-panel-slot{width:100%;height:100%}.flow-resize-e{top:var(--flow-tab-h);cursor:col-resize;touch-action:none;z-index:20;width:16px;position:absolute;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-picker{z-index:50;max-height:min(60vh,420px);position:fixed}.flow-picker-input{margin-bottom:var(--castle-space-base);color:var(--flow-fg);background:var(--flow-surface);border:1px solid var(--flow-border);border-radius:var(--castle-radius-small);outline:none;flex:none;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-empty{color:var(--flow-muted);padding:10px 8px;font-size:12px}.flow-operator-host{width:100%;height:100%}.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{position:relative;overflow:clip}.flow-root.is-mobile .flow-field{inset:calc(var(--flow-dock-h) + var(--flow-gap) * 2) 0 var(--flow-gap);width:auto;min-width:0;height:auto;min-height:0;position:absolute;overflow:clip}.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 100%;min-width:0;margin:0}.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-check-failed{background:var(--castle-danger-surface)}.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}.flow-tabstrip{height:var(--flow-tab-h);-webkit-user-select:none;user-select:none;touch-action:none;flex-shrink:0}.flow-tabs-row{position:relative;overflow:hidden}.flow-tabs-row .panel-tab{flex:0 auto;min-width:0}.flow-tab-icon svg{width:var(--flow-icon-dock);height:var(--flow-icon-dock)}.flow-tabs-row .panel-tab-insert{z-index:3;height:auto;position:absolute;top:0;bottom:0}.panel-tab-ghost,.dock-segment-ghost{z-index:80;position:fixed}.flow-tabstrip .button{flex-shrink:0;align-self:center}.flow-tab-body{position:absolute;inset:0}.flow-tab-body.inactive{display:none}.flow-class-drawer{background:var(--castle-sheet-bg,var(--v2-surface));border-right:1px solid var(--flow-border);flex-direction:column;flex:none;width:220px;min-height:0;padding:2px 4px 6px;display:flex;overflow:hidden}.flow-class-files{flex:auto;min-height:0;overflow-y:auto}.flow-class-files .fileBrowserBare,.flow-class-files .fileTree{flex:none;height:auto;overflow:visible}.flow-class-recent{border-bottom:1px solid var(--castle-inspector-divider,var(--flow-border));margin-bottom:10px;padding-bottom:10px}.flow-class-section{color:var(--v2-muted,var(--flow-muted));padding:5px 9px;font-size:14px}.flow-class-drawer .flow-view-segments{margin:4px 2px 8px}.flow-class-drawer-empty{color:var(--flow-muted);padding:10px 8px;font-size:12px}.flow-empty-editor{flex:auto;height:100%;min-height:0;display:flex}.flow-empty-editor .flow-class-drawer{flex:0 0 220px}.flow-empty-editor-msg{color:var(--flow-muted);background:var(--castle-sheet-bg,var(--v2-surface));flex:auto;justify-content:center;align-items:center;font-size:13px;display:flex}.flow-tabstrip-mobile{cursor:default;grid-template-columns:1fr auto 1fr;align-items:center;display:grid}.flow-mobile-strip-left,.flow-mobile-strip-right{min-width:0}.flow-mobile-strip-right{justify-content:flex-end;align-items:center;display:flex}.flow-tabstrip-mobile .panel-header-actions{margin-left:0}.panel-mobile-current .flow-tab-icon,.panel-mobile-current .flow-tab-icon svg{width:var(--castle-button-icon-size-large);height:var(--castle-button-icon-size-large)}.flow-mobile-chevron{width:var(--castle-button-icon-size-large);height:var(--castle-button-icon-size-large);opacity:.6;flex-shrink:0;justify-content:center;align-items:center;display:inline-flex}.flow-mobile-chevron svg{width:var(--castle-button-icon-size-large);height:var(--castle-button-icon-size-large);display:block}.flow-mobile-switch-backdrop{z-index:900;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);pointer-events:auto;background:#0000008c;align-items:flex-end;display:flex;position:fixed;inset:0}.flow-mobile-switch{border-top:1px solid var(--flow-border);background:#141414;border-radius:16px 16px 0 0;flex-direction:column;width:100%;max-height:70vh;display:flex;overflow:hidden}.flow-mobile-switch-header{border-bottom:1px solid var(--flow-border);justify-content:space-between;align-items:center;padding:14px 16px;font-weight:600;display:flex}.flow-mobile-switch-close{color:var(--flow-secondary);cursor:pointer;background:0 0;border:none;font-size:22px;line-height:1}.flow-view-segments{background:var(--v2-inset,#0e0e0e);border-radius:8px;flex:none;gap:2px;margin:10px 16px 6px;padding:2px;display:flex}.flow-view-segment{color:var(--flow-secondary);font:inherit;cursor:pointer;background:0 0;border:none;border-radius:6px;flex:1 1 0;padding:7px 10px;font-size:13px;font-weight:600}.flow-view-segment.on{color:var(--flow-text,#eee);background:#282828}.flow-mobile-switch-list{background:var(--v2-surface,#141414);flex-direction:column;flex:auto;min-height:0;display:flex;overflow:hidden}.flow-mobile-switch-list .flow-class-files{padding:4px 6px 10px}
|
package/dist/shell/index.html
CHANGED
|
@@ -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-
|
|
14
|
-
<link rel="stylesheet" crossorigin href="/__castle/ide/assets/index-
|
|
13
|
+
<script type="module" crossorigin src="/__castle/ide/assets/index-C5DS_7UM.js"></script>
|
|
14
|
+
<link rel="stylesheet" crossorigin href="/__castle/ide/assets/index-CoU3ETYM.css">
|
|
15
15
|
</head>
|
|
16
16
|
<body>
|
|
17
17
|
<div id="root"></div>
|
package/kits/base/CLAUDE.md
CHANGED
|
@@ -122,6 +122,9 @@ bottleneck.
|
|
|
122
122
|
- `unsupported` — a refusal: why this deck must NOT be built on this
|
|
123
123
|
format, shown when someone tries to upload one. Only for formats you
|
|
124
124
|
recognize and reject.
|
|
125
|
+
- `width` — preferred card width in px when the shell opens this type's
|
|
126
|
+
editor in a new pane. A layout hint: the shell caps it to the window
|
|
127
|
+
and ignores it on phones. Absent means the shell's default.
|
|
125
128
|
|
|
126
129
|
2. **Write the module** at the declared path. It is handed the file and a way
|
|
127
130
|
to save it; how it renders is yours.
|
package/kits/base/castle.json
CHANGED
|
@@ -12,61 +12,71 @@
|
|
|
12
12
|
"ext": ".png",
|
|
13
13
|
"label": "Image",
|
|
14
14
|
"icon": "file-image",
|
|
15
|
-
"editor": "editors/ImageViewer.js"
|
|
15
|
+
"editor": "editors/ImageViewer.js",
|
|
16
|
+
"width": 480
|
|
16
17
|
},
|
|
17
18
|
{
|
|
18
19
|
"ext": ".jpg",
|
|
19
20
|
"label": "Image",
|
|
20
21
|
"icon": "file-image",
|
|
21
|
-
"editor": "editors/ImageViewer.js"
|
|
22
|
+
"editor": "editors/ImageViewer.js",
|
|
23
|
+
"width": 480
|
|
22
24
|
},
|
|
23
25
|
{
|
|
24
26
|
"ext": ".jpeg",
|
|
25
27
|
"label": "Image",
|
|
26
28
|
"icon": "file-image",
|
|
27
|
-
"editor": "editors/ImageViewer.js"
|
|
29
|
+
"editor": "editors/ImageViewer.js",
|
|
30
|
+
"width": 480
|
|
28
31
|
},
|
|
29
32
|
{
|
|
30
33
|
"ext": ".gif",
|
|
31
34
|
"label": "Image",
|
|
32
35
|
"icon": "file-image",
|
|
33
|
-
"editor": "editors/ImageViewer.js"
|
|
36
|
+
"editor": "editors/ImageViewer.js",
|
|
37
|
+
"width": 480
|
|
34
38
|
},
|
|
35
39
|
{
|
|
36
40
|
"ext": ".webp",
|
|
37
41
|
"label": "Image",
|
|
38
42
|
"icon": "file-image",
|
|
39
|
-
"editor": "editors/ImageViewer.js"
|
|
43
|
+
"editor": "editors/ImageViewer.js",
|
|
44
|
+
"width": 480
|
|
40
45
|
},
|
|
41
46
|
{
|
|
42
47
|
"ext": ".svg",
|
|
43
48
|
"label": "Image",
|
|
44
49
|
"icon": "file-image",
|
|
45
|
-
"editor": "editors/ImageViewer.js"
|
|
50
|
+
"editor": "editors/ImageViewer.js",
|
|
51
|
+
"width": 480
|
|
46
52
|
},
|
|
47
53
|
{
|
|
48
54
|
"ext": ".mp3",
|
|
49
55
|
"label": "Audio",
|
|
50
56
|
"icon": "file-audio",
|
|
51
|
-
"editor": "editors/MediaPlayer.js"
|
|
57
|
+
"editor": "editors/MediaPlayer.js",
|
|
58
|
+
"width": 360
|
|
52
59
|
},
|
|
53
60
|
{
|
|
54
61
|
"ext": ".wav",
|
|
55
62
|
"label": "Audio",
|
|
56
63
|
"icon": "file-audio",
|
|
57
|
-
"editor": "editors/MediaPlayer.js"
|
|
64
|
+
"editor": "editors/MediaPlayer.js",
|
|
65
|
+
"width": 360
|
|
58
66
|
},
|
|
59
67
|
{
|
|
60
68
|
"ext": ".m4a",
|
|
61
69
|
"label": "Audio",
|
|
62
70
|
"icon": "file-audio",
|
|
63
|
-
"editor": "editors/MediaPlayer.js"
|
|
71
|
+
"editor": "editors/MediaPlayer.js",
|
|
72
|
+
"width": 360
|
|
64
73
|
},
|
|
65
74
|
{
|
|
66
75
|
"ext": ".mp4",
|
|
67
76
|
"label": "Video",
|
|
68
77
|
"icon": "file-video",
|
|
69
|
-
"editor": "editors/MediaPlayer.js"
|
|
78
|
+
"editor": "editors/MediaPlayer.js",
|
|
79
|
+
"width": 560
|
|
70
80
|
}
|
|
71
81
|
]
|
|
72
82
|
},
|
|
@@ -74,7 +84,7 @@
|
|
|
74
84
|
"title": "base",
|
|
75
85
|
"deckId": "yRcmH4_aYllE",
|
|
76
86
|
"cardId": "zkFdingmIm3m",
|
|
77
|
-
"publishedVersion": "2026-09-
|
|
87
|
+
"publishedVersion": "2026-09-11T20:21:04.335Z",
|
|
78
88
|
"provides": [
|
|
79
89
|
"castle-web-sdk"
|
|
80
90
|
]
|
|
@@ -22,11 +22,12 @@ Do you already know what you want to make, or do you want to figure it out toget
|
|
|
22
22
|
- 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.
|
|
23
23
|
- Real game objects and scenery should usually be editable sprites: generate `.sprite` with `npm run draw -- name`, then place it via a `Sprite` component pointing at `drawings/name.sprite`. Dynamic UI/effects stay procedural.
|
|
24
24
|
- A deck can also hold uploaded media (the Files panel's Upload button): `Sprite` draws image files as well as `.sprite`, and `Video` plays video files. Point their `file` at the deck path (`assets/logo.png`). For audio see `## Sound` below -- sound effects need no component at all.
|
|
25
|
+
- **Text** — place the kit preset `@imports/castle.physics-2d/blueprints/text.scene`, or add a `Text` component (optional `font`; chrome via sibling `Style`). Dynamic text is `actor.components.Text.text = …`. A sibling `onTap(actor, scene)` fires when that actor is tapped — no extra behavior.
|
|
25
26
|
- The deck's body/UI font is picked in the Theme editor (`theme.style`): canvas text reads `scene.font`. A second display face is imported in the behavior that uses it. See `## Deck font` below.
|
|
26
27
|
- This kit is plain JavaScript. Use `.jsx` for files with JSX, `.js` otherwise; do not add TypeScript files or a new build step.
|
|
27
28
|
- Space is reserved by the editor for play/stop; do not bind Space to gameplay.
|
|
28
29
|
- Two render hooks: `draw(ctx)` is world space and scrolls with `Camera`; `drawUi(ctx)` is screen space (card units, camera-free). On-screen controls, gauges and HUD go in `drawUi`, never `draw`. The React `ui()` hook is deprecated — prefer `drawUi`.
|
|
29
|
-
- 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. Forking is the exception: when you're deliberately copying a kit file into the deck to change it — an editor (see `## Editors`) or a behavior you're shadowing — read the original. `engine/` stays off-limits either way.
|
|
30
|
+
- Do not read `engine/`, `editors/`, or built-in behaviors (`Layout.jsx`, `Sprite.jsx`, `Text.jsx`, `Style.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. Forking is the exception: when you're deliberately copying a kit file into the deck to change it — an editor (see `## Editors`) or a behavior you're shadowing — read the original. `engine/` stays off-limits either way.
|
|
30
31
|
- An editor is for content FILES the creator keeps coming back to (catalogs, dialogue, level tables) that nothing already opens. Scenes, sprites and themes have editors; per-actor settings belong on behavior props in the inspector — not in a new editor.
|
|
31
32
|
- Details below: `## Behavior shape`, `## Scene file`, `## Blueprints`, `## Built-in behaviors`, `## Creating pixel art`, `## SceneRuntime API`, and `## Input shortcuts`.
|
|
32
33
|
|
|
@@ -74,6 +75,9 @@ These are ALL the fields that exist — do not invent others:
|
|
|
74
75
|
- `unsupported` — a refusal: why this deck must NOT be built on this
|
|
75
76
|
format, shown when someone tries to upload one. Only for formats you
|
|
76
77
|
recognize and reject.
|
|
78
|
+
- `width` — preferred card width in px when the shell opens this type's
|
|
79
|
+
editor in a new pane. A layout hint: the shell caps it to the window
|
|
80
|
+
and ignores it on phones. Absent means the shell's default.
|
|
77
81
|
|
|
78
82
|
2. **Write the module** at the declared path, default-exporting a component:
|
|
79
83
|
|
|
@@ -291,6 +295,10 @@ export class MyThing {
|
|
|
291
295
|
// For letting go of anything held outside your own props.
|
|
292
296
|
onDisable(actor, scene) {}
|
|
293
297
|
onEnable(actor, scene) {}
|
|
298
|
+
|
|
299
|
+
// Optional. Fired on pointer release inside this actor (Collider, else
|
|
300
|
+
// Layout box). No extra component — implementing the method is the opt-in.
|
|
301
|
+
onTap(actor, scene) {}
|
|
294
302
|
}
|
|
295
303
|
```
|
|
296
304
|
|
|
@@ -383,12 +391,16 @@ Template `components` keys are behavior names (the `static behaviorName`); add a
|
|
|
383
391
|
- **Never write inline actors** (full `components`, no `blueprint` field). They aren't a lighter-weight alternative: the editor auto-migrates every such actor into its OWN new blueprint file the first time a human opens the scene — mechanically, one blueprint per actor, no dedup. That migration is a compatibility net for pre-blueprint decks, not an authoring workflow; leaning on it turns 10 inline enemies into 10 junk blueprints.
|
|
384
392
|
- Never invent your own `blueprint` path pointing at a file you didn't also create — a dangling reference resolves to "no template" (the instance's own sparse `components` render alone, missing whatever it expected to inherit).
|
|
385
393
|
|
|
394
|
+
The kit also ships a few presets under `blueprints/` (e.g. `text.scene`, `ball.scene`, `cauldron.scene`). Reference one from a deck as `"blueprint": "@imports/castle.physics-2d/blueprints/text.scene"`.
|
|
395
|
+
|
|
386
396
|
## Built-in behaviors
|
|
387
397
|
|
|
388
398
|
- **Layout** — `{ x, y, width, height, z?, rotation? }`. Every actor needs one. `z` orders draw (low first). `rotation` is degrees about the center.
|
|
389
399
|
- **Sprite** — `{ file: "drawings/foo.sprite", 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 `.sprite` 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.
|
|
390
400
|
- **Missing sprites fall back to a placeholder.** If `file` names a sprite that doesn't exist yet, it renders the fallback `drawings/cauldron.sprite` — so you can give an actor its REAL intended sprite name (`drawings/paddle.sprite`) right away and it shows the placeholder until that file is created. Reference real names from the start; don't wait for the art.
|
|
391
401
|
- **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.
|
|
402
|
+
- **Text** — `{ text, font?: '', size?: 24, color?: '#131313', align?: 'left'|'center'|'right', verticalAlign?: 'top'|'middle'|'bottom', lineHeight?: 1.25, space?: 'world'|'screen', outlineWidth?: 0, outlineColor?: '#ffffff' }`. Draws wrapped text into the Layout box (wrap width = box minus sibling `Style.padding`; lines may overflow vertically — no clipping, no auto-resize). `font: ''` (default) uses the deck font; pick any Castle face from the inspector and it is added to `fonts.generated.js`. `space: 'world'` scrolls with the camera; `space: 'screen'` is HUD via `drawUi`. `color` / `outlineColor` are deck-palette hexes (`''` = none — skip fill or stroke). Fill/border/shadow/opacity/padding live on sibling **Style**. Hide with `"$enabled": false`. Kit preset: `@imports/castle.physics-2d/blueprints/text.scene`. Change the string from deck code with `actor.components.Text.text = '…'`.
|
|
403
|
+
- **Style** — `{ background?: '', border?: '', borderWidth?: 0, borderRadius?: 0, padding?: 0, shadowX?: 0, shadowY?: 0, shadowBlur?: 0, shadowColor?: '', opacity?: 1 }`. Shared chrome for **Text** and **Sprite**: background fill, border, corner radius, drop shadow (`shadowColor` + offsets + blur; empty color = no shadow), content padding, and opacity. Draws behind content. `background` / `border` are palette hexes (`''` = none). Add it beside Text or Sprite from the inspector.
|
|
392
404
|
- **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:
|
|
393
405
|
|
|
394
406
|
```jsx
|
|
@@ -492,8 +504,10 @@ behavior imported for itself — before the first frame, so `ctx.font` is safe t
|
|
|
492
504
|
set from the very first `draw`. Each face costs its own 12–90 KB in the bundle,
|
|
493
505
|
so two or three in total is the shape to aim for.
|
|
494
506
|
|
|
495
|
-
|
|
496
|
-
|
|
507
|
+
Use the **Text** behavior for labels and HUD strings (optional per-actor `font`,
|
|
508
|
+
plus sibling **Style** for fill/border/padding). Hand-drawn canvas text
|
|
509
|
+
(`ctx.fillText` in `draw` / `drawUi`) is for per-glyph effects or text that
|
|
510
|
+
follows a body in a way the Layout box cannot.
|
|
497
511
|
|
|
498
512
|
## Physics
|
|
499
513
|
|
|
@@ -525,8 +539,7 @@ make it move.**
|
|
|
525
539
|
- `bodyType: 'dynamic' | 'static' | 'kinematic'`. `dynamic` = simulated
|
|
526
540
|
(gravity, collisions, forces). `static` = never moves (same as a lone
|
|
527
541
|
Collider). `kinematic` = unpushable, but you move it by writing its Layout.
|
|
528
|
-
- `gravityScale` — multiplies world gravity for this body (`0` = floats
|
|
529
|
-
default, so newly added bodies don't fall until you opt in).
|
|
542
|
+
- `gravityScale` — multiplies world gravity for this body (`0` = floats).
|
|
530
543
|
- `drag` — linear damping (air resistance). `angularDrag` — spin damping.
|
|
531
544
|
- `freezeRotation` — keep it from rotating (stays upright).
|
|
532
545
|
- `velocityX` / `velocityY` — initial velocity, applied once when play starts.
|
|
@@ -601,6 +614,26 @@ export class StickSlowDownToggle {
|
|
|
601
614
|
}
|
|
602
615
|
```
|
|
603
616
|
|
|
617
|
+
### Tap hook
|
|
618
|
+
|
|
619
|
+
Any behavior may implement `onTap(actor, scene)`. No extra component: if an
|
|
620
|
+
enabled behavior on the actor has the method, a pointer release inside the hit
|
|
621
|
+
zone fires it on every sibling that implements it (Collider when present, else
|
|
622
|
+
the Layout box; screen-space Text uses screen coords). The finger is claimed so
|
|
623
|
+
it does not also drive a stick or a grab-anywhere sling. A targeted control
|
|
624
|
+
(Draggable, a sling pressed on its own body) still wins. An actor with no
|
|
625
|
+
`onTap` does not claim the finger.
|
|
626
|
+
|
|
627
|
+
```jsx
|
|
628
|
+
export class TapCounter {
|
|
629
|
+
static behaviorName = 'TapCounter';
|
|
630
|
+
onTap(actor, scene) {
|
|
631
|
+
const text = actor.components.Text;
|
|
632
|
+
if (text) text.text = String(Number(text.text || 0) + 1);
|
|
633
|
+
}
|
|
634
|
+
}
|
|
635
|
+
```
|
|
636
|
+
|
|
604
637
|
### Built-in controls (add these behaviors, no code needed)
|
|
605
638
|
|
|
606
639
|
These read input and drive the actor through the physics system, so the actor
|
|
@@ -650,7 +683,7 @@ see the SceneRuntime API below.
|
|
|
650
683
|
### Recipe: a launch-and-bounce game
|
|
651
684
|
|
|
652
685
|
- Ball blueprint: `Layout` (square), `Sprite`, `Collider {shape:'circle',
|
|
653
|
-
bounciness:0.6}`, `RigidBody {bodyType:'dynamic'
|
|
686
|
+
bounciness:0.6}`, `RigidBody {bodyType:'dynamic'}`, `Slingshot {}`.
|
|
654
687
|
- Walls/floor blueprint: `Layout`, `Collider {bounciness:0.4}` (no RigidBody →
|
|
655
688
|
static).
|
|
656
689
|
- Goal blueprint: `Collider {isTrigger:true}` + a `Goal` behavior with
|
|
@@ -853,14 +886,14 @@ if (scene.keys.has('KeyX')) /* launch ball */ ;
|
|
|
853
886
|
|
|
854
887
|
**Space is reserved** — the editor binds it to the play/stop toggle, so don't bind Space to a gameplay action (jump / shoot / launch / ...). Use arrows, WASD, letter keys, or on-screen buttons instead.
|
|
855
888
|
|
|
856
|
-
For HUD text
|
|
889
|
+
For HUD text prefer a `Text` actor with `space: 'screen'` (or `drawUi` for custom canvas HUD). Only in-world text or shapes go in `draw`. Both read `scene.font` — see `## Deck font`. A tappable label is `Text` plus a sibling with `onTap`. The React `ui()` hook is deprecated.
|
|
857
890
|
|
|
858
891
|
## Common breakout-shaped recipe (sketch)
|
|
859
892
|
|
|
860
893
|
- `Paddle` behavior: read keys, clamp x to `[0, 500 - layout.width]`.
|
|
861
894
|
- `Ball` behavior: store `vx, vy` on `actor.runtime`; integrate; bounce off wall edges (`x<0`, `x+w>500`, `y<0`); on `scene.overlaps(actor, paddle)`, flip `vy`; for each `brick` in `scene.actorsWith('Brick')` check `scene.overlaps(actor, brick)` → flip `vy` and `scene.despawnActor(brick.id)`; if `y > 700` lose a life.
|
|
862
895
|
- `Brick` behavior: typically just a marker — `kind: 'solid'` collider is enough. State (hit count) goes on `actor.runtime` or the brick's own props.
|
|
863
|
-
- `GameController` (no Layout needed if you don't draw it): tracks score / lives / status; expose HUD via `drawUi()`.
|
|
896
|
+
- `GameController` (no Layout needed if you don't draw it): tracks score / lives / status; expose HUD via `Text` with `space: 'screen'` or `drawUi()`.
|
|
864
897
|
|
|
865
898
|
## Don't
|
|
866
899
|
|
|
@@ -4,11 +4,8 @@ import { AutoFields, overrideProps } from '../engine/autoInspector';
|
|
|
4
4
|
import {
|
|
5
5
|
GREEDY_CLAIM,
|
|
6
6
|
acquirePress,
|
|
7
|
+
clampLength,
|
|
7
8
|
length,
|
|
8
|
-
screenPoint,
|
|
9
|
-
stickBrake,
|
|
10
|
-
stickDrive,
|
|
11
|
-
stickVector,
|
|
12
9
|
} from '../engine/physics/controls';
|
|
13
10
|
|
|
14
11
|
// AnalogStick: on-screen virtual joystick (press anywhere) that drives the
|
|
@@ -26,6 +23,85 @@ import {
|
|
|
26
23
|
//
|
|
27
24
|
// Sibling hooks (fired on this actor only): onAnalogStickBegin / onAnalogStickEnd
|
|
28
25
|
// (actor, scene) — begin on first nonzero deflection, end on release or disable.
|
|
26
|
+
//
|
|
27
|
+
// Force-mode math lives here (only consumer): stickDrive / stickBrake return
|
|
28
|
+
// velocity deltas via applyImpulse — mass-independent, composable, and
|
|
29
|
+
// restricted to driven axes so gravity on an undriven axis is never clamped.
|
|
30
|
+
|
|
31
|
+
// Stick displacement from origin, clamped to maxRadius.
|
|
32
|
+
function stickVector(pointer, origin, maxRadius = 60) {
|
|
33
|
+
return clampLength({ x: pointer.x - origin.x, y: pointer.y - origin.y }, maxRadius);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Card coords before the camera — for screen-fixed controls reading a pointer.
|
|
37
|
+
function screenPoint(pointer) {
|
|
38
|
+
return { x: pointer.screenX, y: pointer.screenY };
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Keep only the axes the stick is allowed to drive. An undriven axis (gravity
|
|
42
|
+
// in a platformer) must never be clamped or braked by the stick.
|
|
43
|
+
function drivenAxes(v, axes) {
|
|
44
|
+
return {
|
|
45
|
+
x: axes === 'vertical' ? 0 : v.x,
|
|
46
|
+
y: axes === 'horizontal' ? 0 : v.y,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Smallest signed angle from `from` to `to`, wrapped into [−π, π].
|
|
51
|
+
function angleDelta(from, to) {
|
|
52
|
+
let d = Math.atan2(to.y, to.x) - Math.atan2(from.y, from.x);
|
|
53
|
+
if (d > Math.PI) d -= 2 * Math.PI;
|
|
54
|
+
if (d < -Math.PI) d += 2 * Math.PI;
|
|
55
|
+
return d;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// Velocity delta while held: accelerate toward deflection × speed with turn
|
|
59
|
+
// boost on reversals, then clamp driven axes to `speed`. Impulse only.
|
|
60
|
+
function stickDrive(velocity, deflection, props = {}, dt) {
|
|
61
|
+
const speed = props.speed ?? 6;
|
|
62
|
+
const rampTime = props.rampTime ?? 0.2;
|
|
63
|
+
const turnBoost = props.turnBoost ?? 3;
|
|
64
|
+
const axes = props.axes ?? 'both';
|
|
65
|
+
const vDriven = drivenAxes(velocity, axes);
|
|
66
|
+
|
|
67
|
+
let boost = 1;
|
|
68
|
+
if (turnBoost > 0 && length(velocity) > 0 && length(deflection) > 0) {
|
|
69
|
+
boost = 1 + turnBoost * (Math.abs(angleDelta(velocity, deflection)) / Math.PI);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
let delta;
|
|
73
|
+
if (rampTime <= 0) {
|
|
74
|
+
const target = drivenAxes(
|
|
75
|
+
{ x: deflection.x * speed, y: deflection.y * speed },
|
|
76
|
+
axes,
|
|
77
|
+
);
|
|
78
|
+
delta = { x: target.x - vDriven.x, y: target.y - vDriven.y };
|
|
79
|
+
} else {
|
|
80
|
+
const accel = speed / rampTime;
|
|
81
|
+
delta = drivenAxes(
|
|
82
|
+
{ x: deflection.x * accel * boost * dt, y: deflection.y * accel * boost * dt },
|
|
83
|
+
axes,
|
|
84
|
+
);
|
|
85
|
+
const capped = clampLength({ x: vDriven.x + delta.x, y: vDriven.y + delta.y }, speed);
|
|
86
|
+
delta = { x: capped.x - vDriven.x, y: capped.y - vDriven.y };
|
|
87
|
+
}
|
|
88
|
+
return delta;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// Velocity delta while idle: Coulomb brake on driven axes only.
|
|
92
|
+
// `slowDown` is speed units lost per second (px/step per second). 0 = coast.
|
|
93
|
+
function stickBrake(velocity, props = {}, dt) {
|
|
94
|
+
const slowDown = props.slowDown ?? 20;
|
|
95
|
+
if (slowDown <= 0) return { x: 0, y: 0 };
|
|
96
|
+
const axes = props.axes ?? 'both';
|
|
97
|
+
const vDriven = drivenAxes(velocity, axes);
|
|
98
|
+
const len = length(vDriven);
|
|
99
|
+
if (len === 0) return { x: 0, y: 0 };
|
|
100
|
+
const reduce = Math.min(len, slowDown * dt);
|
|
101
|
+
const s = -reduce / len;
|
|
102
|
+
return { x: vDriven.x * s, y: vDriven.y * s };
|
|
103
|
+
}
|
|
104
|
+
|
|
29
105
|
function fireStickHook(actor, scene, hook) {
|
|
30
106
|
scene.forEachBehavior(actor, (inst) => inst[hook]?.(actor, scene));
|
|
31
107
|
}
|
|
@@ -62,6 +62,14 @@ export class Slingshot {
|
|
|
62
62
|
// Anchor at the press point (like castle-client): the aim/launch depends
|
|
63
63
|
// on the drag gesture, not where the press landed relative to the actor.
|
|
64
64
|
rt._slingAnchor = { x: press.x, y: press.y };
|
|
65
|
+
// A same-frame tap (down already false) is not an aim — cancel before we
|
|
66
|
+
// can launch with a zero pull. A TARGETED control that updates later this
|
|
67
|
+
// frame may still steal a greedy claim; we must not freeze velocity yet.
|
|
68
|
+
if (!press.down) {
|
|
69
|
+
rt._slinging = false;
|
|
70
|
+
rt._slingPointerId = null;
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
65
73
|
}
|
|
66
74
|
}
|
|
67
75
|
if (!rt._slinging) return;
|
|
@@ -77,8 +85,12 @@ export class Slingshot {
|
|
|
77
85
|
}
|
|
78
86
|
|
|
79
87
|
if (p.down) {
|
|
80
|
-
// Hold still while aiming
|
|
81
|
-
|
|
88
|
+
// Hold still while aiming — but not on the press frame. A greedy claim can
|
|
89
|
+
// still lose to a higher claim that hasn't updated yet (e.g. a Draggable
|
|
90
|
+
// on the pressed body); freezing here would hitch a mid-air body for one frame
|
|
91
|
+
// and then drop the shot with no launch. Matches claimPointer's contract
|
|
92
|
+
// that the press frame costs a greedy control nothing visible.
|
|
93
|
+
if (!p.justPressed) scene.physics.setVelocity(actor, { x: 0, y: 0 });
|
|
82
94
|
rt._slingAim = { x: p.x, y: p.y };
|
|
83
95
|
} else {
|
|
84
96
|
scene.physics.setVelocity(actor, slingLaunch(rt._slingAnchor, p, this.props));
|