diff --git a/docs/API-Reference/features/TaskManager.md b/docs/API-Reference/features/TaskManager.md index d07490a63a..9d13cf300d 100644 --- a/docs/API-Reference/features/TaskManager.md +++ b/docs/API-Reference/features/TaskManager.md @@ -39,6 +39,7 @@ like `showStopIcon`, `hideStopIcon`, etc. | [options.onRetryClick] | function | | Callback function triggered when the retry button is clicked. | | [options.onSelect] | function | | Callback function triggered when the task is selected from the dropdown. | | [options.progressPercent] | number | | Initial progress percentage of the task. | +| [options.hideProgressBar] | boolean | | Hide progress for tasks waiting on a user action. | | [options.noSpinnerNotification] | boolean | | If set to true, will not show the task spinners for this task. This can be used for silent background tasks where user attention is not needed. | **Example** diff --git a/docs/API-Reference/utils/DragAndDrop.md b/docs/API-Reference/utils/DragAndDrop.md index 5800006e76..b1caeda9b8 100644 --- a/docs/API-Reference/utils/DragAndDrop.md +++ b/docs/API-Reference/utils/DragAndDrop.md @@ -18,7 +18,8 @@ Returns true if the drag and drop items contains valid drop objects. ## openDroppedFiles(paths) ⇒ Promise -Open dropped files +Open dropped files in order so the last file becomes active, regardless of load times. +Continue processing the remaining paths if an earlier file cannot be opened. **Kind**: global function **Returns**: Promise - Promise that is resolved if all files are opened, or rejected diff --git a/package-lock.json b/package-lock.json index b4e819d156..b785839fa6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "phoenix", - "version": "5.5.3-0", + "version": "5.5.6-0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "phoenix", - "version": "5.5.3-0", + "version": "5.5.6-0", "hasInstallScript": true, "dependencies": { "@bugsnag/js": "^7.18.0", diff --git a/src-node/package-lock.json b/src-node/package-lock.json index 2832561ed2..5c98351674 100644 --- a/src-node/package-lock.json +++ b/src-node/package-lock.json @@ -1,12 +1,12 @@ { "name": "@phcode/node-core", - "version": "5.5.5-0", + "version": "5.5.6-0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@phcode/node-core", - "version": "5.5.5-0", + "version": "5.5.6-0", "hasInstallScript": true, "license": "GNU-AGPL3.0", "dependencies": { @@ -21,6 +21,7 @@ "node-pty": "^1.1.0", "npm": "11.8.0", "open": "^10.1.0", + "phoenix": "file:..", "vscode-langservers-extracted": "4.10.0", "which": "^2.0.1", "ws": "^8.17.1", @@ -30,6 +31,76 @@ "node": "24" } }, + "..": { + "version": "5.5.6-0", + "hasInstallScript": true, + "dependencies": { + "@bugsnag/js": "^7.18.0", + "@floating-ui/dom": "^0.5.4", + "@fortawesome/fontawesome-free": "^6.1.2", + "@highlightjs/cdn-assets": "^11.5.1", + "@phcode/fs": "^4.0.2", + "@phcode/language-support": "^1.1.0", + "@pixelbrackets/gfm-stylesheet": "^1.1.0", + "@prettier/plugin-php": "^0.22.2", + "@uiw/file-icons": "^1.3.2", + "@xterm/addon-fit": "0.12.0-beta.301", + "@xterm/addon-search": "0.17.0-beta.301", + "@xterm/addon-web-links": "0.13.0-beta.301", + "@xterm/addon-webgl": "0.20.0-beta.300", + "@xterm/xterm": "6.1.0-beta.304", + "bootstrap": "^5.1.3", + "browser-mime": "^1.0.1", + "codemirror": "^5.65.16", + "cross-env": "^7.0.3", + "devicon": "^2.15.1", + "emmet": "^2.4.11", + "file-saver": "^2.0.5", + "idb-keyval": "^6.2.1", + "jshint": "^2.13.5", + "jszip": "^3.8.0", + "less": "^4.1.3", + "lodash": "^4.18.1", + "lru-cache": "^10.2.0", + "marked": "^4.0.18", + "mime-db": "^1.52.0", + "mustache": "^4.2.0", + "prettier": "^3.2.5", + "requirejs": "^2.3.7", + "tern": "^0.24.3", + "tinycolor2": "^1.4.2", + "underscore": "^1.13.4" + }, + "devDependencies": { + "@commitlint/cli": "^16.0.2", + "@commitlint/config-conventional": "^16.0.0", + "@playwright/test": "^1.38.1", + "del": "^6.0.0", + "eslint": "^8.18.0", + "glob": "^8.1.0", + "gulp": "^4.0.2", + "gulp-concat": "^2.6.1", + "gulp-cssnano": "^2.1.3", + "gulp-flatten": "^0.4.0", + "gulp-if": "^3.0.0", + "gulp-minify": "^3.1.0", + "gulp-rename": "^2.0.0", + "gulp-sourcemaps": "^3.0.0", + "gulp-uglify": "^3.0.2", + "gulp-useref": "^5.0.0", + "gulp-webserver": "^0.9.1", + "gulp-zip": "^5.1.0", + "http-proxy": "^1.18.1", + "http-server": "14.1.0", + "husky": "^7.0.4", + "jasmine-core": "^4.2.0", + "jasmine-reporters": "^2.5.0", + "jsdoc-to-markdown": "^9.1.1", + "lmdb": "^3.5.1", + "readable-stream": "^3.6.0", + "through2": "^4.0.2" + } + }, "node_modules/@anthropic-ai/claude-agent-sdk": { "version": "0.3.280", "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-agent-sdk/-/claude-agent-sdk-0.3.280.tgz", @@ -3748,6 +3819,10 @@ "url": "https://opencollective.com/express" } }, + "node_modules/phoenix": { + "resolved": "..", + "link": true + }, "node_modules/picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", diff --git a/src-node/package.json b/src-node/package.json index 62b0f24b0e..7d8f88a340 100644 --- a/src-node/package.json +++ b/src-node/package.json @@ -31,6 +31,7 @@ "node-pty": "^1.1.0", "npm": "11.8.0", "open": "^10.1.0", + "phoenix": "file:..", "vscode-langservers-extracted": "4.10.0", "which": "^2.0.1", "ws": "^8.17.1", diff --git a/src/assets/aiDemos/0000-dave-jungle-temple.json b/src/assets/aiDemos/0000-dave-jungle-temple.json new file mode 100644 index 0000000000..6b14cef45a --- /dev/null +++ b/src/assets/aiDemos/0000-dave-jungle-temple.json @@ -0,0 +1 @@ +{"format":"phoenix-ai-panel-recording","version":1,"recordedAt":"2026-09-21T13:43:53.372Z","appVersion":"5.5.3-0","durationMs":1798755,"preferredSpeed":8,"builtWith":"Claude Fable 5","userMessage":"Surprise me!","prompt":"Surprise me — build a small playable game (specifically: dave (Dangerous Dave-style platformer)) in vanilla HTML/CSS/JS that I can preview right now. Aesthetic: a tropical jungle palette (deep green, papaya, ivory). Make it visually impressive, modern, and polished. The specific pick and the aesthetic are FIXED for your decisions — don't substitute a different game / widget / piece if you think it's safer, and don't drift to a different palette on your own initiative mid-build. How you design and structure the build is fully up to you. If I ask for a different category, aesthetic, theme, or palette in a follow-up, my follow-up wins. Avoid the word \"aurora\" anywhere in the page or filenames — pick fresh names.\n\nThis one has to run smoothly on low-end student laptops and still look great, so:\n- World-building first: a side-scrolling jungle-temple level a few screens wide with parallax background layers, animated water, torches and vines, collectible gems and a key, a few patrolling enemies, hazards, and an exit door that needs the key. Pixel-art style, with every sprite and tile drawn in code — no external assets, fonts or libraries.\n- Render on a small fixed internal canvas (about 320x180) scaled up with CSS image-rendering: pixelated. 2D canvas only — no WebGL or 3D. Pre-render tiles and sprites to offscreen canvases once. No shadowBlur, no getImageData or per-pixel work, no large particle counts. Step the game with delta time, cap the step, and pause when the tab is hidden.\n- Attract mode: until the player presses a key or taps, the game plays itself (a simple scripted player runs the level on a loop) so the preview is alive with nobody touching it. Show a small 'Press any key to play' prompt; any input hands control to the player.\n- Controls: arrow keys / WASD and Space to jump, plus on-screen touch buttons for trackpad and touch users. HUD with gems, key and lives. Win and game-over screens with restart.\n- Sound off by default (tiny WebAudio bleeps behind a mute toggle are fine).\n- When you test with execJsInLivePreview keep every check short and cheap: read state, no long synchronous loops, no simulating long stretches of gameplay in one call, no canvas readbacks, no synthetic input storms. A few quick checks and screenshots are enough.\n\nCRITICAL: Always create a BRAND NEW HTML file for this build. Do NOT Read, Edit, or Write into any file that already existed before this task started — whatever file the user has open is irrelevant, do not touch it. Call getEditorState ONCE up front if you need to learn the project root path (so your Write call uses a correct absolute path), but ignore the active file it reports — that's not your target. Pick a fresh filename that matches the pick (e.g. `.html`) and use the Write tool to create it from scratch in the project root. After that file is created, you SHOULD use Edit on it freely for the incremental build steps below — the rule is only about not touching pre-existing files.\n\nBuild it INCREMENTALLY so I see it come together like a person is hand-building it — never write the whole thing in one Write call:\n1. Start by building a task list with TaskCreate (one call per step: scaffold, sections/features, styling, animations, polish). Use TaskUpdate to mark each step in_progress when you start it and completed when you finish, so progress is always visible.\n2. Write a minimal scaffold HTML file first (a NEW file via the Write tool — not an Edit of any existing file) — basic structure and placeholder content, just enough that something appears in the live preview within a few seconds.\n3. Enhance progressively in coherent chunks — one section, one feature, or one cohesive style/animation block at a time. Each Edit should produce a visible change in the preview but stay focused enough to render quickly. Don't write the whole page in one giant rewrite, and don't fragment into atomic single-property edits — aim for meaningful steps the user can watch land.\n4. Take screenshots only at logical milestones (e.g. after the scaffold lands, after a major section is complete, at the end) — not after every small edit.\n5. At the end, test and inspect the page using execJsInLivePreview — verify there are no console errors and that the controls respond. Keep it to a few cheap checks. Fix anything broken before declaring done.\n\nUse a cohesive design, smooth animations, and a fully responsive layout. Save to a single NEW HTML file (created via Write, not by editing an existing file). Build it in the user's locale (en-US).","events":[{"t":5,"name":"aiProgress","data":{"message":"Analyzing...","phase":"start"}},{"t":3502,"name":"aiProgress","data":{"toolName":"ToolSearch","toolId":1,"phase":"tool_use"}},{"t":3503,"name":"aiToolStream","data":{"toolId":1,"toolName":"ToolSearch","append":"{\"query\": \"select:Task"}},{"t":3779,"name":"aiToolStream","data":{"toolId":1,"toolName":"ToolSearch","append":"Create,TaskUpdate\", \"max_results\": 5}"}},{"t":3786,"name":"aiToolInfo","data":{"toolName":"ToolSearch","toolId":1,"toolInput":{"query":"select:TaskCreate,TaskUpdate","max_results":5}}},{"t":3796,"name":"aiProgress","data":{"toolName":"mcp__phoenix-editor__getEditorState","toolId":2,"phase":"tool_use"}},{"t":3804,"name":"aiToolResult","data":{"toolId":1,"isError":false,"preview":""}},{"t":3888,"name":"aiToolInfo","data":{"toolName":"mcp__phoenix-editor__getEditorState","toolId":2,"toolInput":{}}},{"t":3901,"name":"aiToolResult","data":{"toolId":2,"isError":false,"preview":""}},{"t":862142,"name":"aiProgress","data":{"toolName":"TaskCreate","toolId":3,"phase":"tool_use"}},{"t":862775,"name":"aiToolStream","data":{"toolId":3,"toolName":"TaskCreate","append":"{\"subject\": \"Scaffold page + canvas shell\", \"description\": \"New dave-jungle.html with layout, 320x180 pixelated canvas, game loop w/ delta time"}},{"t":863438,"name":"aiToolStream","data":{"toolId":3,"toolName":"TaskCreate","append":" + visibility pause\", \"activeForm\": \"Scaffolding page\"}"}},{"t":863585,"name":"aiToolInfo","data":{"toolName":"TaskCreate","toolId":3,"toolInput":{"subject":"Scaffold page + canvas shell","description":"New dave-jungle.html with layout, 320x180 pixelated canvas, game loop w/ delta time + visibility pause","activeForm":"Scaffolding page"}}},{"t":863604,"name":"aiProgress","data":{"toolName":"TaskCreate","toolId":4,"phase":"tool_use"}},{"t":863611,"name":"aiToolResult","data":{"toolId":3,"isError":false,"preview":"Task #1 created successfully: Scaffold page + canvas shell"}},{"t":864066,"name":"aiToolStream","data":{"toolId":4,"toolName":"TaskCreate","append":"{\"subject\": \"Tiles, level map & parallax world\", \"description\": \"Pre-rendered tiles, level layout, parallax layers, water"}},{"t":864323,"name":"aiToolStream","data":{"toolId":4,"toolName":"TaskCreate","append":", torches, vines"}},{"t":864702,"name":"aiToolStream","data":{"toolId":4,"toolName":"TaskCreate","append":"\", \"activeForm\": \"Building the world\"}"}},{"t":864817,"name":"aiToolInfo","data":{"toolName":"TaskCreate","toolId":4,"toolInput":{"subject":"Tiles, level map & parallax world","description":"Pre-rendered tiles, level layout, parallax layers, water, torches, vines","activeForm":"Building the world"}}},{"t":864818,"name":"aiProgress","data":{"toolName":"TaskCreate","toolId":5,"phase":"tool_use"}},{"t":864823,"name":"aiToolResult","data":{"toolId":4,"isError":false,"preview":"Task #2 created successfully: Tiles, level map & parallax world"}},{"t":864945,"name":"aiToolStream","data":{"toolId":5,"toolName":"TaskCreate","append":"{\"subject\": \"Player, physics & sprites"}},{"t":865359,"name":"aiToolStream","data":{"toolId":5,"toolName":"TaskCreate","append":"\", \"description\": \"Pixel sprites, platformer physics, camera, keyboard + touch controls"}},{"t":865810,"name":"aiToolStream","data":{"toolId":5,"toolName":"TaskCreate","append":"\", \"activeForm\": \"Adding the player\"}"}},{"t":865994,"name":"aiToolInfo","data":{"toolName":"TaskCreate","toolId":5,"toolInput":{"subject":"Player, physics & sprites","description":"Pixel sprites, platformer physics, camera, keyboard + touch controls","activeForm":"Adding the player"}}},{"t":865994,"name":"aiProgress","data":{"toolName":"TaskCreate","toolId":6,"phase":"tool_use"}},{"t":865999,"name":"aiToolResult","data":{"toolId":5,"isError":false,"preview":"Task #3 created successfully: Player, physics & sprites"}},{"t":866121,"name":"aiToolStream","data":{"toolId":6,"toolName":"TaskCreate","append":"{\"subject\": \"Gems, key, door, enemies, hazards"}},{"t":866372,"name":"aiToolStream","data":{"toolId":6,"toolName":"TaskCreate","append":"\", \"description\": \"Collectibles, patrolling enemies, spikes/water hazards, loc"}},{"t":866682,"name":"aiToolStream","data":{"toolId":6,"toolName":"TaskCreate","append":"ked exit door, lives"}},{"t":866948,"name":"aiToolStream","data":{"toolId":6,"toolName":"TaskCreate","append":"\", \"activeForm\": \"Adding gameplay entities"}},{"t":867345,"name":"aiToolStream","data":{"toolId":6,"toolName":"TaskCreate","append":"\"}"}},{"t":867348,"name":"aiToolInfo","data":{"toolName":"TaskCreate","toolId":6,"toolInput":{"subject":"Gems, key, door, enemies, hazards","description":"Collectibles, patrolling enemies, spikes/water hazards, locked exit door, lives","activeForm":"Adding gameplay entities"}}},{"t":867348,"name":"aiProgress","data":{"toolName":"TaskCreate","toolId":7,"phase":"tool_use"}},{"t":867352,"name":"aiToolResult","data":{"toolId":6,"isError":false,"preview":"Task #4 created successfully: Gems, key, door, enemies, hazards"}},{"t":867527,"name":"aiToolStream","data":{"toolId":7,"toolName":"TaskCreate","append":"{\"subject\": \"Attract mode, HUD, screens, sound\", \"description\": \"Self-playing dem"}},{"t":867824,"name":"aiToolStream","data":{"toolId":7,"toolName":"TaskCreate","append":"o bot, HUD, win/game-over overlays, muted-"}},{"t":868123,"name":"aiToolStream","data":{"toolId":7,"toolName":"TaskCreate","append":"by-default WebAudio bleeps\", \"activeForm\": \"Adding attract"}},{"t":868392,"name":"aiToolStream","data":{"toolId":7,"toolName":"TaskCreate","append":" mode & HUD"}},{"t":868657,"name":"aiToolStream","data":{"toolId":7,"toolName":"TaskCreate","append":"\"}"}},{"t":868659,"name":"aiToolInfo","data":{"toolName":"TaskCreate","toolId":7,"toolInput":{"subject":"Attract mode, HUD, screens, sound","description":"Self-playing demo bot, HUD, win/game-over overlays, muted-by-default WebAudio bleeps","activeForm":"Adding attract mode & HUD"}}},{"t":868659,"name":"aiProgress","data":{"toolName":"TaskCreate","toolId":8,"phase":"tool_use"}},{"t":868667,"name":"aiToolResult","data":{"toolId":7,"isError":false,"preview":"Task #5 created successfully: Attract mode, HUD, screens, sound"}},{"t":868775,"name":"aiToolStream","data":{"toolId":8,"toolName":"TaskCreate","append":"{\"subject\": \"Polish & test\", \"description\": \"Particles"}},{"t":869066,"name":"aiToolStream","data":{"toolId":8,"toolName":"TaskCreate","append":", responsive tuning, cheap live-preview checks, fix bugs"}},{"t":869489,"name":"aiToolStream","data":{"toolId":8,"toolName":"TaskCreate","append":"\", \"activeForm\": \"Polishing & testing\"}"}},{"t":869676,"name":"aiToolInfo","data":{"toolName":"TaskCreate","toolId":8,"toolInput":{"subject":"Polish & test","description":"Particles, responsive tuning, cheap live-preview checks, fix bugs","activeForm":"Polishing & testing"}}},{"t":869680,"name":"aiToolResult","data":{"toolId":8,"isError":false,"preview":"Task #6 created successfully: Polish & test"}},{"t":871362,"name":"aiProgress","data":{"toolName":"TaskUpdate","toolId":9,"phase":"tool_use"}},{"t":871740,"name":"aiToolStream","data":{"toolId":9,"toolName":"TaskUpdate","append":"{\"taskId\": \"1\", \"status\": \"in_progress\"}"}},{"t":871799,"name":"aiToolInfo","data":{"toolName":"TaskUpdate","toolId":9,"toolInput":{"taskId":"1","status":"in_progress"}}},{"t":871806,"name":"aiToolResult","data":{"toolId":9,"isError":false,"preview":"Updated task #1 status"}},{"t":885318,"name":"aiProgress","data":{"toolName":"Write","toolId":10,"phase":"tool_use"}},{"t":885443,"name":"aiToolStream","data":{"toolId":10,"toolName":"Write","append":"{\"file_path\": \"{{PROJECT}}/dave-jungle-temple.html"}},{"t":885884,"name":"aiToolStream","data":{"toolId":10,"toolName":"Write","append":"\", \"content\": \"\\n\\n\\n\\n\\nD"}},{"t":886512,"name":"aiToolStream","data":{"toolId":10,"toolName":"Write","append":"ave & the Papaya Temple\\n\\n\\n\\n
\\n
\\n "}},{"t":892447,"name":"aiToolStream","data":{"toolId":10,"toolName":"Write","append":"

Dave & the Papaya Temple

\\n
\\n \\n \\n "}},{"t":893199,"name":"aiToolStream","data":{"toolId":10,"toolName":"Write","append":"\\n
\\n\\n\\n\\n\\n"}},{"t":898996,"name":"aiToolStream","data":{"toolId":10,"toolName":"Write","append":"\"}"}},{"t":899011,"name":"aiToolInfo","data":{"toolName":"Write","toolId":10,"toolInput":{"file_path":"{{PROJECT}}/dave-jungle-temple.html","content":"\n\n\n\n\nDave & the Papaya Temple\n\n\n\n
\n
\n

Dave & the Papaya Temple

\n
\n
\n \n
\n
\n\n\n\n\n"}}},{"t":899120,"name":"aiToolEdit","data":{"toolId":10,"edit":{"file":"{{PROJECT}}/dave-jungle-temple.html","oldText":null,"newText":"\n\n\n\n\nDave & the Papaya Temple\n\n\n\n
\n
\n

Dave & the Papaya Temple

\n
\n
\n \n
\n
\n\n\n\n\n","isLivePreviewRelated":false}}},{"t":899120,"name":"aiToolResult","data":{"toolId":10,"isError":false,"preview":"File created successfully at: {{PROJECT}}/dave-jungle-temple.ht"}},{"t":900704,"name":"aiProgress","data":{"toolName":"mcp__phoenix-editor__controlEditor","toolId":11,"phase":"tool_use"}},{"t":901323,"name":"aiToolStream","data":{"toolId":11,"toolName":"mcp__phoenix-editor__controlEditor","append":"{\"operations\": [{\"operation\":\"open\",\"filePath\":\"{{PROJECT}}/dave-jungle-temple.html\"},{\"operation\":\"toggleLivePreview\",\"showPreview\":true}]"}},{"t":901596,"name":"aiToolStream","data":{"toolId":11,"toolName":"mcp__phoenix-editor__controlEditor","append":"}"}},{"t":901599,"name":"aiToolInfo","data":{"toolName":"mcp__phoenix-editor__controlEditor","toolId":11,"toolInput":{"operations":[{"operation":"open","filePath":"{{PROJECT}}/dave-jungle-temple.html"},{"operation":"toggleLivePreview","showPreview":true}]}}},{"t":901634,"name":"aiToolResult","data":{"toolId":11,"isError":false,"preview":"[{\"success\":true},{\"success\":true,\"alreadyInState\":true}]"}},{"t":902795,"name":"aiProgress","data":{"toolName":"TaskUpdate","toolId":12,"phase":"tool_use"}},{"t":903400,"name":"aiToolStream","data":{"toolId":12,"toolName":"TaskUpdate","append":"{\"taskId\": \"1\", \"status\": \"completed\"}"}},{"t":903403,"name":"aiToolInfo","data":{"toolName":"TaskUpdate","toolId":12,"toolInput":{"taskId":"1","status":"completed"}}},{"t":903403,"name":"aiProgress","data":{"toolName":"TaskUpdate","toolId":13,"phase":"tool_use"}},{"t":903408,"name":"aiToolResult","data":{"toolId":12,"isError":false,"preview":"Updated task #1 status"}},{"t":903474,"name":"aiToolStream","data":{"toolId":13,"toolName":"TaskUpdate","append":"{\"taskId\": \"2\", \"status\": \"in_"}},{"t":903773,"name":"aiToolStream","data":{"toolId":13,"toolName":"TaskUpdate","append":"progress\"}"}},{"t":903775,"name":"aiToolInfo","data":{"toolName":"TaskUpdate","toolId":13,"toolInput":{"taskId":"2","status":"in_progress"}}},{"t":903780,"name":"aiToolResult","data":{"toolId":13,"isError":false,"preview":"Updated task #2 status"}},{"t":1118711,"name":"aiTextStream","data":{"text":"Building the world next"}},{"t":1118734,"name":"aiTextStream","data":{"text":": tiles, level map, and parallax layers, in a few focused edits."}},{"t":1118736,"name":"aiProgress","data":{"toolName":"Edit","toolId":14,"phase":"tool_use"}},{"t":1118777,"name":"aiToolStream","data":{"toolId":14,"toolName":"Edit","append":"{\"file_path\": \"{{PROJECT}}/dave-jungle-temple."}},{"t":1119088,"name":"aiToolStream","data":{"toolId":14,"toolName":"Edit","append":"html\", \"old_string\": \"/* ==HELPERS"}},{"t":1119340,"name":"aiToolStream","data":{"toolId":14,"toolName":"Edit","append":"== */\\n\", \"new_string\": \"/* ==HELP"}},{"t":1119596,"name":"aiToolStream","data":{"toolId":14,"toolName":"Edit","append":"ERS== */\\nfunction mk(w,h){ const c=document.createElement('canvas'); c.width=w; c.height=h;"}},{"t":1119904,"name":"aiToolStream","data":{"toolId":14,"toolName":"Edit","append":" const g=c.getContext('2d'); g.imageSmoothingEnabled=false; return [c,g]; }\\nlet _"}},{"t":1120213,"name":"aiToolStream","data":{"toolId":14,"toolName":"Edit","append":"seed = 20260921;\\nfunction rnd(){ _seed = (_seed*"}},{"t":1120463,"name":"aiToolStream","data":{"toolId":14,"toolName":"Edit","append":"1664525 + 1013904223)>>>0; return _seed/4294967296; }"}},{"t":1120715,"name":"aiToolStream","data":{"toolId":14,"toolName":"Edit","append":"\\nfunction ri(a,b){ return a + Math.floor(rnd()*(b-a+1)); }\\nfunction px(g,c"}},{"t":1121026,"name":"aiToolStream","data":{"toolId":14,"toolName":"Edit","append":",x,y,w,h){ g.fillStyle=c; g.fillRect(x|0,y"}},{"t":1121278,"name":"aiToolStream","data":{"toolId":14,"toolName":"Edit","append":"|0,w||1,h||1); }\\nfunction disc(g,c,cx,cy,r){"}},{"t":1121529,"name":"aiToolStream","data":{"toolId":14,"toolName":"Edit","append":" g.fillStyle=c; for(let y=-r;y<=r;y++){ const s=Math.floor("}},{"t":1121843,"name":"aiToolStream","data":{"toolId":14,"toolName":"Edit","append":"Math.sqrt(r*r-y*y)); g.fillRect(cx-s,cy+y"}},{"t":1122094,"name":"aiToolStream","data":{"toolId":14,"toolName":"Edit","append":",s*2+1,1); } }\\nfunction sprite(rows,pal){ const [c,g]=mk("}},{"t":1122404,"name":"aiToolStream","data":{"toolId":14,"toolName":"Edit","append":"rows[0].length,rows.length);\\n rows.forEach((r,y)=>{ for(let x=0;xvb?b:v;\\n\\nconst C = {\\n ink:'#07110c', le"}},{"t":1124097,"name":"aiToolStream","data":{"toolId":14,"toolName":"Edit","append":"af9:'#06150f', leaf8:'#0b2318', leaf7:'#103424',"}},{"t":1124347,"name":"aiToolStream","data":{"toolId":14,"toolName":"Edit","append":" leaf6:'#17482f', leaf5:'#1f6b45', leaf4:'#2f8a57', leaf"}},{"t":1124653,"name":"aiToolStream","data":{"toolId":14,"toolName":"Edit","append":"3:'#58b57c', leaf2:'#9ad9a0',\\n pap:'#ff"}},{"t":1124903,"name":"aiToolStream","data":{"toolId":14,"toolName":"Edit","append":"8a3d', papD:'#e2612a', papDD:'#a83f1c', papL:'#"}},{"t":1125155,"name":"aiToolStream","data":{"toolId":14,"toolName":"Edit","append":"ffc08a',\\n ivo:'#fbf3df', ivoD:'#d9cfb"}},{"t":1125405,"name":"aiToolStream","data":{"toolId":14,"toolName":"Edit","append":"2', ivoDD:'#a59c80',\\n stone:'#8f9a7e', stone"}},{"t":1125721,"name":"aiToolStream","data":{"toolId":14,"toolName":"Edit","append":"D:'#66735a', stoneDD:'#3b4638', stoneL:'#b"}},{"t":1125982,"name":"aiToolStream","data":{"toolId":14,"toolName":"Edit","append":"cc5a4',\\n dirt:'#4a3323', dirtD:'#2"}},{"t":1126244,"name":"aiToolStream","data":{"toolId":14,"toolName":"Edit","append":"f2016', dirtL:'#6b4a30',\\n water:'#1c7a72', waterD:'#0f4f50"}},{"t":1126548,"name":"aiToolStream","data":{"toolId":14,"toolName":"Edit","append":"', waterL:'#7fe0c6',\\n wood:'#9a6a35"}},{"t":1126841,"name":"aiToolStream","data":{"toolId":14,"toolName":"Edit","append":"', woodD:'#5a3520'\\n};\\n\\n/* ==TILES== */\\nconst TILE = {};"}},{"t":1127091,"name":"aiToolStream","data":{"toolId":14,"toolName":"Edit","append":"\\n(function makeTiles(){\\n // temple stone brick,"}},{"t":1127343,"name":"aiToolStream","data":{"toolId":14,"toolName":"Edit","append":" 3 variants\\n TILE.brick = [0,1,2].map(v=>{ const [c,"}},{"t":1127594,"name":"aiToolStream","data":{"toolId":14,"toolName":"Edit","append":"g]=mk(T,T); px(g,C.stone,0,0,T,T);\\n for(let r=0;r<2;"}},{"t":1127904,"name":"aiToolStream","data":{"toolId":14,"toolName":"Edit","append":"r++){ const y=r*8;\\n px(g,C.stoneL,0,y"}},{"t":1128154,"name":"aiToolStream","data":{"toolId":14,"toolName":"Edit","append":",T,1); px(g,C.stoneD,0,y+6,T,1); px(g,C."}},{"t":1128410,"name":"aiToolStream","data":{"toolId":14,"toolName":"Edit","append":"stoneDD,0,y+7,T,1);\\n const vx=(r*8+v*5+3"}},{"t":1128720,"name":"aiToolStream","data":{"toolId":14,"toolName":"Edit","append":")%16; px(g,C.stoneDD,vx,y,1,7); px(g,C.stoneL,("}},{"t":1129033,"name":"aiToolStream","data":{"toolId":14,"toolName":"Edit","append":"vx+1)%16,y+1,1,5); }\\n for(let i=0;i<7;i++) px(g,"}},{"t":1129343,"name":"aiToolStream","data":{"toolId":14,"toolName":"Edit","append":" rnd()<.5?C.stoneD:C.stoneL, ri(1,14), ri("}},{"t":1129600,"name":"aiToolStream","data":{"toolId":14,"toolName":"Edit","append":"1,14));\\n if(v===2){ for(let i=0;i<5;i++) px(g,"}},{"t":1129905,"name":"aiToolStream","data":{"toolId":14,"toolName":"Edit","append":"C.leaf5,ri(0,13),ri(2,13),ri(1,"}},{"t":1130217,"name":"aiToolStream","data":{"toolId":14,"toolName":"Edit","append":"3),1); }\\n return c; });\\n // moss cap drawn over exposed br"}},{"t":1130467,"name":"aiToolStream","data":{"toolId":14,"toolName":"Edit","append":"ick tops\\n TILE.moss = [0,1].map(()=>{ const [c,g]=m"}},{"t":1130721,"name":"aiToolStream","data":{"toolId":14,"toolName":"Edit","append":"k(T,T); px(g,C.leaf5,0,0,T,2); px(g,C.leaf3,0,0,"}},{"t":1131029,"name":"aiToolStream","data":{"toolId":14,"toolName":"Edit","append":"T,1);\\n for(let x=0;x{ const [c,g]=mk(T,T); px"}},{"t":1132472,"name":"aiToolStream","data":{"toolId":14,"toolName":"Edit","append":"(g,C.dirt,0,0,T,T);\\n for(let i=0;i<10;i++) px(g,"}},{"t":1132780,"name":"aiToolStream","data":{"toolId":14,"toolName":"Edit","append":" rnd()<.6?C.dirtD:C.dirtL, ri(0,14"}},{"t":1133030,"name":"aiToolStream","data":{"toolId":14,"toolName":"Edit","append":"), ri(0,15), ri(1,2), 1);\\n px(g,C."}},{"t":1133282,"name":"aiToolStream","data":{"toolId":14,"toolName":"Edit","append":"ivoDD,ri(2,12),ri(5,12),2"}},{"t":1133533,"name":"aiToolStream","data":{"toolId":14,"toolName":"Edit","append":",1); return c; });\\n TILE.grass = [0,1].map(()=>{ const [c,g]=mk(T,"}},{"t":1133855,"name":"aiToolStream","data":{"toolId":14,"toolName":"Edit","append":"T); px(g,C.leaf4,0,0,T,3); px(g,C.leaf3,0,0,T,1);"}},{"t":1134157,"name":"aiToolStream","data":{"toolId":14,"toolName":"Edit","append":"\\n for(let x=0;x{ const [c,g]=mk(T,"}},{"t":1135531,"name":"aiToolStream","data":{"toolId":14,"toolName":"Edit","append":"T); px(g,C.leaf8,0,0,T,T);\\n for(let r="}},{"t":1135781,"name":"aiToolStream","data":{"toolId":14,"toolName":"Edit","append":"0;r<2;r++){ const y=r*8; px(g,C.leaf7,0,y,"}},{"t":1136044,"name":"aiToolStream","data":{"toolId":14,"toolName":"Edit","append":"T,1); px(g,C.ink,0,y+7,T,1); px(g,C.ink,(r*8+v*6"}},{"t":1136345,"name":"aiToolStream","data":{"toolId":14,"toolName":"Edit","append":"+2)%16,y,1,7); }\\n if(v===1) px(g,C.le"}},{"t":1136595,"name":"aiToolStream","data":{"toolId":14,"toolName":"Edit","append":"af6,ri(2,10),ri(2,12),3"}},{"t":1136845,"name":"aiToolStream","data":{"toolId":14,"toolName":"Edit","append":",1); if(v===2){ px(g,C.leaf7,ri(2,10),ri(9,"}},{"t":1137156,"name":"aiToolStream","data":{"toolId":14,"toolName":"Edit","append":"13),4,2); }\\n return c; });\\n {"}},{"t":1137408,"name":"aiToolStream","data":{"toolId":14,"toolName":"Edit","append":" const [c,g]=mk(T,T); px(g,C.leaf7,2,0,12"}},{"t":1137734,"name":"aiToolStream","data":{"toolId":14,"toolName":"Edit","append":",T); px(g,C.leaf6,4,0,3,T); px(g,C.leaf5,5"}},{"t":1138033,"name":"aiToolStream","data":{"toolId":14,"toolName":"Edit","append":",0,1,T); px(g,C."}},{"t":1138376,"name":"aiToolStream","data":{"toolId":14,"toolName":"Edit","append":"ink,2,0,1,T); px(g,C.ink,13,0,1,T); px(g,C.leaf8,10,0,2,T); TILE.column"}},{"t":1138658,"name":"aiToolStream","data":{"toolId":14,"toolName":"Edit","append":"=c; }\\n { const [c,g]=mk(T,T); px(g,"}},{"t":1138908,"name":"aiToolStream","data":{"toolId":14,"toolName":"Edit","append":"C.leaf6,0,4,T,8); px(g,C"}},{"t":1139159,"name":"aiToolStream","data":{"toolId":14,"toolName":"Edit","append":".leaf5,0,4,T,1); px(g,C.ink,0,12,T,1); px(g"}},{"t":1139479,"name":"aiToolStream","data":{"toolId":14,"toolName":"Edit","append":",C.leaf7,1,6,14,4); TILE.capital=c; }\\n /"}},{"t":1139786,"name":"aiToolStream","data":{"toolId":14,"toolName":"Edit","append":"/ bamboo bridge (one-way)\\n { const [c,g]=mk(T,T); px(g,C.wood"}},{"t":1140096,"name":"aiToolStream","data":{"toolId":14,"toolName":"Edit","append":",0,0,T,5); px(g,C.papL,0,0,T,1); px(g,C.woodD,0,4"}},{"t":1140418,"name":"aiToolStream","data":{"toolId":14,"toolName":"Edit","append":",T,2);\\n for(let x=3;x{ const [c,g]=mk(T,T); px(g,C.water,0,4"}},{"t":1143536,"name":"aiToolStream","data":{"toolId":14,"toolName":"Edit","append":",T,12); px(g,C.waterD,0,11,T,5);\\n for(let x="}},{"t":1143850,"name":"aiToolStream","data":{"toolId":14,"toolName":"Edit","append":"0;x{ const [c,g]=mk(T,T); px(g,C.waterD,"}},{"t":1145848,"name":"aiToolStream","data":{"toolId":14,"toolName":"Edit","append":"0,0,T,T); px(g,C.water,(3+f*5)%14"}},{"t":1146158,"name":"aiToolStream","data":{"toolId":14,"toolName":"Edit","append":",4,3,1); px(g,C.water,(10"}},{"t":1146413,"name":"aiToolStream","data":{"toolId":14,"toolName":"Edit","append":"+f*3)%14,11,2,1); px(g,'#0a3a3c"}},{"t":1146722,"name":"aiToolStream","data":{"toolId":14,"toolName":"Edit","append":"',0,12,T,4); return c; });\\n})();\\n"}},{"t":1146996,"name":"aiToolStream","data":{"toolId":14,"toolName":"Edit","append":"\"}"}},{"t":1147016,"name":"aiToolInfo","data":{"toolName":"Edit","toolId":14,"toolInput":{"file_path":"{{PROJECT}}/dave-jungle-temple.html","old_string":"/* ==HELPERS== */\n","new_string":"/* ==HELPERS== */\nfunction mk(w,h){ const c=document.createElement('canvas'); c.width=w; c.height=h; const g=c.getContext('2d'); g.imageSmoothingEnabled=false; return [c,g]; }\nlet _seed = 20260921;\nfunction rnd(){ _seed = (_seed*1664525 + 1013904223)>>>0; return _seed/4294967296; }\nfunction ri(a,b){ return a + Math.floor(rnd()*(b-a+1)); }\nfunction px(g,c,x,y,w,h){ g.fillStyle=c; g.fillRect(x|0,y|0,w||1,h||1); }\nfunction disc(g,c,cx,cy,r){ g.fillStyle=c; for(let y=-r;y<=r;y++){ const s=Math.floor(Math.sqrt(r*r-y*y)); g.fillRect(cx-s,cy+y,s*2+1,1); } }\nfunction sprite(rows,pal){ const [c,g]=mk(rows[0].length,rows.length);\n rows.forEach((r,y)=>{ for(let x=0;xvb?b:v;\n\nconst C = {\n ink:'#07110c', leaf9:'#06150f', leaf8:'#0b2318', leaf7:'#103424', leaf6:'#17482f', leaf5:'#1f6b45', leaf4:'#2f8a57', leaf3:'#58b57c', leaf2:'#9ad9a0',\n pap:'#ff8a3d', papD:'#e2612a', papDD:'#a83f1c', papL:'#ffc08a',\n ivo:'#fbf3df', ivoD:'#d9cfb2', ivoDD:'#a59c80',\n stone:'#8f9a7e', stoneD:'#66735a', stoneDD:'#3b4638', stoneL:'#bcc5a4',\n dirt:'#4a3323', dirtD:'#2f2016', dirtL:'#6b4a30',\n water:'#1c7a72', waterD:'#0f4f50', waterL:'#7fe0c6',\n wood:'#9a6a35', woodD:'#5a3520'\n};\n\n/* ==TILES== */\nconst TILE = {};\n(function makeTiles(){\n // temple stone brick, 3 variants\n TILE.brick = [0,1,2].map(v=>{ const [c,g]=mk(T,T); px(g,C.stone,0,0,T,T);\n for(let r=0;r<2;r++){ const y=r*8;\n px(g,C.stoneL,0,y,T,1); px(g,C.stoneD,0,y+6,T,1); px(g,C.stoneDD,0,y+7,T,1);\n const vx=(r*8+v*5+3)%16; px(g,C.stoneDD,vx,y,1,7); px(g,C.stoneL,(vx+1)%16,y+1,1,5); }\n for(let i=0;i<7;i++) px(g, rnd()<.5?C.stoneD:C.stoneL, ri(1,14), ri(1,14));\n if(v===2){ for(let i=0;i<5;i++) px(g,C.leaf5,ri(0,13),ri(2,13),ri(1,3),1); }\n return c; });\n // moss cap drawn over exposed brick tops\n TILE.moss = [0,1].map(()=>{ const [c,g]=mk(T,T); px(g,C.leaf5,0,0,T,2); px(g,C.leaf3,0,0,T,1);\n for(let x=0;x{ const [c,g]=mk(T,T); px(g,C.dirt,0,0,T,T);\n for(let i=0;i<10;i++) px(g, rnd()<.6?C.dirtD:C.dirtL, ri(0,14), ri(0,15), ri(1,2), 1);\n px(g,C.ivoDD,ri(2,12),ri(5,12),2,1); return c; });\n TILE.grass = [0,1].map(()=>{ const [c,g]=mk(T,T); px(g,C.leaf4,0,0,T,3); px(g,C.leaf3,0,0,T,1);\n for(let x=0;x{ const [c,g]=mk(T,T); px(g,C.leaf8,0,0,T,T);\n for(let r=0;r<2;r++){ const y=r*8; px(g,C.leaf7,0,y,T,1); px(g,C.ink,0,y+7,T,1); px(g,C.ink,(r*8+v*6+2)%16,y,1,7); }\n if(v===1) px(g,C.leaf6,ri(2,10),ri(2,12),3,1); if(v===2){ px(g,C.leaf7,ri(2,10),ri(9,13),4,2); }\n return c; });\n { const [c,g]=mk(T,T); px(g,C.leaf7,2,0,12,T); px(g,C.leaf6,4,0,3,T); px(g,C.leaf5,5,0,1,T); px(g,C.ink,2,0,1,T); px(g,C.ink,13,0,1,T); px(g,C.leaf8,10,0,2,T); TILE.column=c; }\n { const [c,g]=mk(T,T); px(g,C.leaf6,0,4,T,8); px(g,C.leaf5,0,4,T,1); px(g,C.ink,0,12,T,1); px(g,C.leaf7,1,6,14,4); TILE.capital=c; }\n // bamboo bridge (one-way)\n { const [c,g]=mk(T,T); px(g,C.wood,0,0,T,5); px(g,C.papL,0,0,T,1); px(g,C.woodD,0,4,T,2);\n for(let x=3;x{ const [c,g]=mk(T,T); px(g,C.water,0,4,T,12); px(g,C.waterD,0,11,T,5);\n for(let x=0;x{ const [c,g]=mk(T,T); px(g,C.waterD,0,0,T,T); px(g,C.water,(3+f*5)%14,4,3,1); px(g,C.water,(10+f*3)%14,11,2,1); px(g,'#0a3a3c',0,12,T,4); return c; });\n})();\n"}}},{"t":1147090,"name":"aiToolEdit","data":{"toolId":14,"edit":{"file":"{{PROJECT}}/dave-jungle-temple.html","oldText":"/* ==HELPERS== */\n","newText":"/* ==HELPERS== */\nfunction mk(w,h){ const c=document.createElement('canvas'); c.width=w; c.height=h; const g=c.getContext('2d'); g.imageSmoothingEnabled=false; return [c,g]; }\nlet _seed = 20260921;\nfunction rnd(){ _seed = (_seed*1664525 + 1013904223)>>>0; return _seed/4294967296; }\nfunction ri(a,b){ return a + Math.floor(rnd()*(b-a+1)); }\nfunction px(g,c,x,y,w,h){ g.fillStyle=c; g.fillRect(x|0,y|0,w||1,h||1); }\nfunction disc(g,c,cx,cy,r){ g.fillStyle=c; for(let y=-r;y<=r;y++){ const s=Math.floor(Math.sqrt(r*r-y*y)); g.fillRect(cx-s,cy+y,s*2+1,1); } }\nfunction sprite(rows,pal){ const [c,g]=mk(rows[0].length,rows.length);\n rows.forEach((r,y)=>{ for(let x=0;xvb?b:v;\n\nconst C = {\n ink:'#07110c', leaf9:'#06150f', leaf8:'#0b2318', leaf7:'#103424', leaf6:'#17482f', leaf5:'#1f6b45', leaf4:'#2f8a57', leaf3:'#58b57c', leaf2:'#9ad9a0',\n pap:'#ff8a3d', papD:'#e2612a', papDD:'#a83f1c', papL:'#ffc08a',\n ivo:'#fbf3df', ivoD:'#d9cfb2', ivoDD:'#a59c80',\n stone:'#8f9a7e', stoneD:'#66735a', stoneDD:'#3b4638', stoneL:'#bcc5a4',\n dirt:'#4a3323', dirtD:'#2f2016', dirtL:'#6b4a30',\n water:'#1c7a72', waterD:'#0f4f50', waterL:'#7fe0c6',\n wood:'#9a6a35', woodD:'#5a3520'\n};\n\n/* ==TILES== */\nconst TILE = {};\n(function makeTiles(){\n // temple stone brick, 3 variants\n TILE.brick = [0,1,2].map(v=>{ const [c,g]=mk(T,T); px(g,C.stone,0,0,T,T);\n for(let r=0;r<2;r++){ const y=r*8;\n px(g,C.stoneL,0,y,T,1); px(g,C.stoneD,0,y+6,T,1); px(g,C.stoneDD,0,y+7,T,1);\n const vx=(r*8+v*5+3)%16; px(g,C.stoneDD,vx,y,1,7); px(g,C.stoneL,(vx+1)%16,y+1,1,5); }\n for(let i=0;i<7;i++) px(g, rnd()<.5?C.stoneD:C.stoneL, ri(1,14), ri(1,14));\n if(v===2){ for(let i=0;i<5;i++) px(g,C.leaf5,ri(0,13),ri(2,13),ri(1,3),1); }\n return c; });\n // moss cap drawn over exposed brick tops\n TILE.moss = [0,1].map(()=>{ const [c,g]=mk(T,T); px(g,C.leaf5,0,0,T,2); px(g,C.leaf3,0,0,T,1);\n for(let x=0;x{ const [c,g]=mk(T,T); px(g,C.dirt,0,0,T,T);\n for(let i=0;i<10;i++) px(g, rnd()<.6?C.dirtD:C.dirtL, ri(0,14), ri(0,15), ri(1,2), 1);\n px(g,C.ivoDD,ri(2,12),ri(5,12),2,1); return c; });\n TILE.grass = [0,1].map(()=>{ const [c,g]=mk(T,T); px(g,C.leaf4,0,0,T,3); px(g,C.leaf3,0,0,T,1);\n for(let x=0;x{ const [c,g]=mk(T,T); px(g,C.leaf8,0,0,T,T);\n for(let r=0;r<2;r++){ const y=r*8; px(g,C.leaf7,0,y,T,1); px(g,C.ink,0,y+7,T,1); px(g,C.ink,(r*8+v*6+2)%16,y,1,7); }\n if(v===1) px(g,C.leaf6,ri(2,10),ri(2,12),3,1); if(v===2){ px(g,C.leaf7,ri(2,10),ri(9,13),4,2); }\n return c; });\n { const [c,g]=mk(T,T); px(g,C.leaf7,2,0,12,T); px(g,C.leaf6,4,0,3,T); px(g,C.leaf5,5,0,1,T); px(g,C.ink,2,0,1,T); px(g,C.ink,13,0,1,T); px(g,C.leaf8,10,0,2,T); TILE.column=c; }\n { const [c,g]=mk(T,T); px(g,C.leaf6,0,4,T,8); px(g,C.leaf5,0,4,T,1); px(g,C.ink,0,12,T,1); px(g,C.leaf7,1,6,14,4); TILE.capital=c; }\n // bamboo bridge (one-way)\n { const [c,g]=mk(T,T); px(g,C.wood,0,0,T,5); px(g,C.papL,0,0,T,1); px(g,C.woodD,0,4,T,2);\n for(let x=3;x{ const [c,g]=mk(T,T); px(g,C.water,0,4,T,12); px(g,C.waterD,0,11,T,5);\n for(let x=0;x{ const [c,g]=mk(T,T); px(g,C.waterD,0,0,T,T); px(g,C.water,(3+f*5)%14,4,3,1); px(g,C.water,(10+f*3)%14,11,2,1); px(g,'#0a3a3c',0,12,T,4); return c; });\n})();\n","replaceAll":false,"isLivePreviewRelated":true}}},{"t":1147092,"name":"aiToolResult","data":{"toolId":14,"isError":false,"preview":"The file {{PROJECT}}/dave-jungle-temple.html has been updated s"}},{"t":1150339,"name":"aiProgress","data":{"toolName":"Edit","toolId":15,"phase":"tool_use"}},{"t":1150340,"name":"aiToolStream","data":{"toolId":15,"toolName":"Edit","append":"{\"file_path\": \"{{PROJECT}}/dave-jungle-temple.html\", \"old_string\": \"/* ==L"}},{"t":1150961,"name":"aiToolStream","data":{"toolId":15,"toolName":"Edit","append":"EVEL== */\\n\", \"new_string\": \"/* ==LEVEL== */\\nconst LW = 96, LH = 12, WORLD_W = LW*T, WORLD_H = LH*T;\\nconst map = [], back"}},{"t":1151601,"name":"aiToolStream","data":{"toolId":15,"toolName":"Edit","append":" = [];\\nfor(let y=0;ySPAWN.gems.push({x:x*T+4,y:y*T+4"}},{"t":1158764,"name":"aiToolStream","data":{"toolId":15,"toolName":"Edit","append":",k:k||0});\\n [5,6,7].forEach(x=>gem(x,9)); g"}},{"t":1159018,"name":"aiToolStream","data":{"toolId":15,"toolName":"Edit","append":"em(10,7,1); gem(11,7,1);\\n gem(22"}},{"t":1159321,"name":"aiToolStream","data":{"toolId":15,"toolName":"Edit","append":",7); gem(23,7); g"}},{"t":1159572,"name":"aiToolStream","data":{"toolId":15,"toolName":"Edit","append":"em(15,9); gem(18,9);\\n [35,36].forEach(x=>g"}},{"t":1159883,"name":"aiToolStream","data":{"toolId":15,"toolName":"Edit","append":"em(x,7)); [37,38,39].forEach(x=>gem(x,5,1"}},{"t":1160136,"name":"aiToolStream","data":{"toolId":15,"toolName":"Edit","append":")); [42,43,44,45].forEach(x=>gem(x,3,1));\\n gem("}},{"t":1160386,"name":"aiToolStream","data":{"toolId":15,"toolName":"Edit","append":"48,9); gem(50,9); gem(52,9); gem(51,6,1);\\n gem(62,7"}},{"t":1160698,"name":"aiToolStream","data":{"toolId":15,"toolName":"Edit","append":"); gem(63,7); gem(66,9); gem(69,9);\\n [83"}},{"t":1160957,"name":"aiToolStream","data":{"toolId":15,"toolName":"Edit","append":",84,85,86].for"}},{"t":1162348,"name":"aiToolStream","data":{"toolId":15,"toolName":"Edit","append":"Each(x=>gem(x,7)); gem(85,4,1); gem(90,9,1);\\n SPAWN.key = {x:58*T+2, y:8*T+5};\\n SPAWN.door = {x:92*T, y:8*T};\\n SPAWN.enemies.push({t:'snake',x:14*T,y:10*T,x0:13*T,x1:20*T});\\n SPAWN.enemies.push({t:'snake',x:67*T,y:10*T,x0:65*T,x1:71*T});"}},{"t":1162635,"name":"aiToolStream","data":{"toolId":15,"toolName":"Edit","append":"\\n SPAWN.enemies.push({t:'bat',x:50*T,y:6*T"}},{"t":1162885,"name":"aiToolStream","data":{"toolId":15,"toolName":"Edit","append":",x0:47*T,x1:53*T});\\n SPAWN.enemies.push({t:'b"}},{"t":1163202,"name":"aiToolStream","data":{"toolId":15,"toolName":"Edit","append":"at',x:84*T,y:4*T+8,x0:82*T,x1:88*T});\\n [["}},{"t":1163509,"name":"aiToolStream","data":{"toolId":15,"toolName":"Edit","append":"30,6],[38,3],[44,7],[50,4"}},{"t":1163821,"name":"aiToolStream","data":{"toolId":15,"toolName":"Edit","append":"],[58,5],[64,4],[70,6]].forEach(p"}},{"t":1164081,"name":"aiToolStream","data":{"toolId":15,"toolName":"Edit","append":"=>SPAWN.torches.push({x:p[0]*T+8,y:p[1]*T+4"}},{"t":1164386,"name":"aiToolStream","data":{"toolId":15,"toolName":"Edit","append":"}));\\n [[4,0,4],[8,0,3],[16,0,5],[20"}},{"t":1164696,"name":"aiToolStream","data":{"toolId":15,"toolName":"Edit","append":",0,3],[32,2,3],[36,2,2],[43,2,1],[48,2,"}},{"t":1164946,"name":"aiToolStream","data":{"toolId":15,"toolName":"Edit","append":"4],[55,2,3],[60,2,4"}},{"t":1165202,"name":"aiToolStream","data":{"toolId":15,"toolName":"Edit","append":"],[67,2,3],[71,2,2],[75,0,4],[79,0,3],"}},{"t":1165509,"name":"aiToolStream","data":{"toolId":15,"toolName":"Edit","append":"[85,0,2],[90,0,5]]\\n .forEach(v"}},{"t":1165761,"name":"aiToolStream","data":{"toolId":15,"toolName":"Edit","append":"=>SPAWN.vines.push({x:v[0]*T+8,y:v[1]*T,len:v[2]"}},{"t":1166095,"name":"aiToolStream","data":{"toolId":15,"toolName":"Edit","append":"*T+ri(0,8),ph:rnd()*6}));"}},{"t":1166388,"name":"aiToolStream","data":{"toolId":15,"toolName":"Edit","append":"\\n})();\\nconst tileAt=(tx,ty)=> (tx<0||tx"}},{"t":1166702,"name":"aiToolStream","data":{"toolId":15,"toolName":"Edit","append":">=LW) ? '#' : (ty<0||ty>=LH) ? ' ' : map[ty][tx];"}},{"t":1167008,"name":"aiToolStream","data":{"toolId":15,"toolName":"Edit","append":"\\nconst isSolid=ch=> ch==='#'||ch==='G';"}},{"t":1167270,"name":"aiToolStream","data":{"toolId":15,"toolName":"Edit","append":"\\n\\n// Pre-render the entire static level once\\nconst [levelCv"}},{"t":1167579,"name":"aiToolStream","data":{"toolId":15,"toolName":"Edit","append":", lg] = mk(WORLD_W, WORLD_H);\\n(function paintLevel(){\\n "}},{"t":1167887,"name":"aiToolStream","data":{"toolId":15,"toolName":"Edit","append":"for(let y=0;y0 && x>0 && x1) lg.drawImage"}},{"t":1174354,"name":"aiToolStream","data":{"toolId":15,"toolName":"Edit","append":"(TILE.moss[x%2],X,Y);\\n if(y<=1 && !"}},{"t":1174636,"name":"aiToolStream","data":{"toolId":15,"toolName":"Edit","append":"isSolid(tileAt(x,y+1))"}},{"t":1175043,"name":"aiToolStream","data":{"toolId":15,"toolName":"Edit","append":") { px(lg,C.stoneDD,X,Y+13,T,3); px(lg,C.ink,X,Y+15,T,1); } }\\n else if(ch==='G'){ lg.drawImage"}},{"t":1175321,"name":"aiToolStream","data":{"toolId":15,"toolName":"Edit","append":"(TILE.earth[(x+y)%2],X,Y); if(!isSolid(up))"}},{"t":1175571,"name":"aiToolStream","data":{"toolId":15,"toolName":"Edit","append":" lg.drawImage(TILE.grass[x%2],X,Y); }\\n else if(ch"}},{"t":1175821,"name":"aiToolStream","data":{"toolId":15,"toolName":"Edit","append":"==='-') lg.drawImage(TILE.bridge,X,Y);\\n else if(ch"}},{"t":1176071,"name":"aiToolStream","data":{"toolId":15,"toolName":"Edit","append":"==='^') lg.drawImage(TILE.spikes,X,Y"}},{"t":1176323,"name":"aiToolStream","data":{"toolId":15,"toolName":"Edit","append":");\\n }\\n // little plants + papaya flowers on grass\\n for(let x=0;xSPAWN.gems.push({x:x*T+4,y:y*T+4,k:k||0});\n [5,6,7].forEach(x=>gem(x,9)); gem(10,7,1); gem(11,7,1);\n gem(22,7); gem(23,7); gem(15,9); gem(18,9);\n [35,36].forEach(x=>gem(x,7)); [37,38,39].forEach(x=>gem(x,5,1)); [42,43,44,45].forEach(x=>gem(x,3,1));\n gem(48,9); gem(50,9); gem(52,9); gem(51,6,1);\n gem(62,7); gem(63,7); gem(66,9); gem(69,9);\n [83,84,85,86].forEach(x=>gem(x,7)); gem(85,4,1); gem(90,9,1);\n SPAWN.key = {x:58*T+2, y:8*T+5};\n SPAWN.door = {x:92*T, y:8*T};\n SPAWN.enemies.push({t:'snake',x:14*T,y:10*T,x0:13*T,x1:20*T});\n SPAWN.enemies.push({t:'snake',x:67*T,y:10*T,x0:65*T,x1:71*T});\n SPAWN.enemies.push({t:'bat',x:50*T,y:6*T,x0:47*T,x1:53*T});\n SPAWN.enemies.push({t:'bat',x:84*T,y:4*T+8,x0:82*T,x1:88*T});\n [[30,6],[38,3],[44,7],[50,4],[58,5],[64,4],[70,6]].forEach(p=>SPAWN.torches.push({x:p[0]*T+8,y:p[1]*T+4}));\n [[4,0,4],[8,0,3],[16,0,5],[20,0,3],[32,2,3],[36,2,2],[43,2,1],[48,2,4],[55,2,3],[60,2,4],[67,2,3],[71,2,2],[75,0,4],[79,0,3],[85,0,2],[90,0,5]]\n .forEach(v=>SPAWN.vines.push({x:v[0]*T+8,y:v[1]*T,len:v[2]*T+ri(0,8),ph:rnd()*6}));\n})();\nconst tileAt=(tx,ty)=> (tx<0||tx>=LW) ? '#' : (ty<0||ty>=LH) ? ' ' : map[ty][tx];\nconst isSolid=ch=> ch==='#'||ch==='G';\n\n// Pre-render the entire static level once\nconst [levelCv, lg] = mk(WORLD_W, WORLD_H);\n(function paintLevel(){\n for(let y=0;y0 && x>0 && x1) lg.drawImage(TILE.moss[x%2],X,Y);\n if(y<=1 && !isSolid(tileAt(x,y+1))) { px(lg,C.stoneDD,X,Y+13,T,3); px(lg,C.ink,X,Y+15,T,1); } }\n else if(ch==='G'){ lg.drawImage(TILE.earth[(x+y)%2],X,Y); if(!isSolid(up)) lg.drawImage(TILE.grass[x%2],X,Y); }\n else if(ch==='-') lg.drawImage(TILE.bridge,X,Y);\n else if(ch==='^') lg.drawImage(TILE.spikes,X,Y);\n }\n // little plants + papaya flowers on grass\n for(let x=0;xSPAWN.gems.push({x:x*T+4,y:y*T+4,k:k||0});\n [5,6,7].forEach(x=>gem(x,9)); gem(10,7,1); gem(11,7,1);\n gem(22,7); gem(23,7); gem(15,9); gem(18,9);\n [35,36].forEach(x=>gem(x,7)); [37,38,39].forEach(x=>gem(x,5,1)); [42,43,44,45].forEach(x=>gem(x,3,1));\n gem(48,9); gem(50,9); gem(52,9); gem(51,6,1);\n gem(62,7); gem(63,7); gem(66,9); gem(69,9);\n [83,84,85,86].forEach(x=>gem(x,7)); gem(85,4,1); gem(90,9,1);\n SPAWN.key = {x:58*T+2, y:8*T+5};\n SPAWN.door = {x:92*T, y:8*T};\n SPAWN.enemies.push({t:'snake',x:14*T,y:10*T,x0:13*T,x1:20*T});\n SPAWN.enemies.push({t:'snake',x:67*T,y:10*T,x0:65*T,x1:71*T});\n SPAWN.enemies.push({t:'bat',x:50*T,y:6*T,x0:47*T,x1:53*T});\n SPAWN.enemies.push({t:'bat',x:84*T,y:4*T+8,x0:82*T,x1:88*T});\n [[30,6],[38,3],[44,7],[50,4],[58,5],[64,4],[70,6]].forEach(p=>SPAWN.torches.push({x:p[0]*T+8,y:p[1]*T+4}));\n [[4,0,4],[8,0,3],[16,0,5],[20,0,3],[32,2,3],[36,2,2],[43,2,1],[48,2,4],[55,2,3],[60,2,4],[67,2,3],[71,2,2],[75,0,4],[79,0,3],[85,0,2],[90,0,5]]\n .forEach(v=>SPAWN.vines.push({x:v[0]*T+8,y:v[1]*T,len:v[2]*T+ri(0,8),ph:rnd()*6}));\n})();\nconst tileAt=(tx,ty)=> (tx<0||tx>=LW) ? '#' : (ty<0||ty>=LH) ? ' ' : map[ty][tx];\nconst isSolid=ch=> ch==='#'||ch==='G';\n\n// Pre-render the entire static level once\nconst [levelCv, lg] = mk(WORLD_W, WORLD_H);\n(function paintLevel(){\n for(let y=0;y0 && x>0 && x1) lg.drawImage(TILE.moss[x%2],X,Y);\n if(y<=1 && !isSolid(tileAt(x,y+1))) { px(lg,C.stoneDD,X,Y+13,T,3); px(lg,C.ink,X,Y+15,T,1); } }\n else if(ch==='G'){ lg.drawImage(TILE.earth[(x+y)%2],X,Y); if(!isSolid(up)) lg.drawImage(TILE.grass[x%2],X,Y); }\n else if(ch==='-') lg.drawImage(TILE.bridge,X,Y);\n else if(ch==='^') lg.drawImage(TILE.spikes,X,Y);\n }\n // little plants + papaya flowers on grass\n for(let x=0;x{ px(g,b[0],0,y,W,b[1]); if(i){ for(let x=0;xtop;y--){ if(y%9===0) tx+=(pxm%2?1:-1); px(g,col,tx,y,3,1); }\\n for(let f=0;f<7"}},{"t":1204092,"name":"aiToolStream","data":{"toolId":16,"toolName":"Edit","append":";f++){ const a=-2.9+f*.45+rnd()*.1; for(let t=0;t<17;t++){ const fx=tx+1+Math.cos(a)*t, fy=top+"}},{"t":1204842,"name":"aiToolStream","data":{"toolId":16,"toolName":"Edit","append":"Math.sin(a)*t*.7+t*t*.035; px(g,col,fx,fy,2,2); if(t>4) px(g,col,fx,fy+2,1,2);} }\\n disc(g,'"}},{"t":1205593,"name":"aiToolStream","data":{"toolId":16,"toolName":"Edit","append":"#c9642f',tx+2,top+3,2); }\\n BG.mid={c,w,f:.3}; }\\n // near: dark trunks, leaves, undergrowth\\n { const w=512,[c,g"}},{"t":1206345,"name":"aiToolStream","data":{"toolId":16,"toolName":"Edit","append":"]=mk(w,H), col='#0c2a1d', hi='#123a28';\\n for(const t of [[30,12],[150,9],[235"}},{"t":1207093,"name":"aiToolStream","data":{"toolId":16,"toolName":"Edit","append":",14],[350,10],[440,12]]){ px(g,col,t[0],0,t[1],H); px(g,hi,t[0]+2,0,2,H); for(let y=10;y0)x-=w; for(;x{ px(g,b[0],0,y,W,b[1]); if(i){ for(let x=0;xtop;y--){ if(y%9===0) tx+=(pxm%2?1:-1); px(g,col,tx,y,3,1); }\n for(let f=0;f<7;f++){ const a=-2.9+f*.45+rnd()*.1; for(let t=0;t<17;t++){ const fx=tx+1+Math.cos(a)*t, fy=top+Math.sin(a)*t*.7+t*t*.035; px(g,col,fx,fy,2,2); if(t>4) px(g,col,fx,fy+2,1,2);} }\n disc(g,'#c9642f',tx+2,top+3,2); }\n BG.mid={c,w,f:.3}; }\n // near: dark trunks, leaves, undergrowth\n { const w=512,[c,g]=mk(w,H), col='#0c2a1d', hi='#123a28';\n for(const t of [[30,12],[150,9],[235,14],[350,10],[440,12]]){ px(g,col,t[0],0,t[1],H); px(g,hi,t[0]+2,0,2,H); for(let y=10;y0)x-=w; for(;x{ px(g,b[0],0,y,W,b[1]); if(i){ for(let x=0;xtop;y--){ if(y%9===0) tx+=(pxm%2?1:-1); px(g,col,tx,y,3,1); }\n for(let f=0;f<7;f++){ const a=-2.9+f*.45+rnd()*.1; for(let t=0;t<17;t++){ const fx=tx+1+Math.cos(a)*t, fy=top+Math.sin(a)*t*.7+t*t*.035; px(g,col,fx,fy,2,2); if(t>4) px(g,col,fx,fy+2,1,2);} }\n disc(g,'#c9642f',tx+2,top+3,2); }\n BG.mid={c,w,f:.3}; }\n // near: dark trunks, leaves, undergrowth\n { const w=512,[c,g]=mk(w,H), col='#0c2a1d', hi='#123a28';\n for(const t of [[30,12],[150,9],[235,14],[350,10],[440,12]]){ px(g,col,t[0],0,t[1],H); px(g,hi,t[0]+2,0,2,H); for(let y=10;y0)x-=w; for(;xW+40)"}},{"t":1220185,"name":"aiToolStream","data":{"toolId":17,"toolName":"Edit","append":" continue; const sy=o.y-cy;\\n const f=((t*9"}},{"t":1220487,"name":"aiToolStream","data":{"toolId":17,"toolName":"Edit","append":" + o.x)"}},{"t":1220739,"name":"aiToolStream","data":{"toolId":17,"toolName":"Edit","append":"|0)%4; ctx.drawImage(SP.glow[f&"}},{"t":1221076,"name":"aiToolStream","data":{"toolId":17,"toolName":"Edit","append":"1], (sx-24)|0, (sy-26)|0);"}},{"t":1221359,"name":"aiToolStream","data":{"toolId":17,"toolName":"Edit","append":" ctx.drawImage(SP.torch, (sx-3)|0, s"}},{"t":1221611,"name":"aiToolStream","data":{"toolId":17,"toolName":"Edit","append":"y|0); ctx.drawImage(SP.flame[f], (sx-4)|0, (s"}},{"t":1221868,"name":"aiToolStream","data":{"toolId":17,"toolName":"Edit","append":"y-11)|0); }\\n // vines: swaying segment chains\\n for(const v of S"}},{"t":1222177,"name":"aiToolStream","data":{"toolId":17,"toolName":"Edit","append":"PAWN.vines){ const sx=v.x-cx; if(sx<-30||sx>W+30)"}},{"t":1222488,"name":"aiToolStream","data":{"toolId":17,"toolName":"Edit","append":" continue; const n=(v.len/4)|0;\\n for(let i=0;iW+40) continue; const sy=o.y-cy;\n const f=((t*9 + o.x)|0)%4; ctx.drawImage(SP.glow[f&1], (sx-24)|0, (sy-26)|0); ctx.drawImage(SP.torch, (sx-3)|0, sy|0); ctx.drawImage(SP.flame[f], (sx-4)|0, (sy-11)|0); }\n // vines: swaying segment chains\n for(const v of SPAWN.vines){ const sx=v.x-cx; if(sx<-30||sx>W+30) continue; const n=(v.len/4)|0;\n for(let i=0;iW+40) continue; const sy=o.y-cy;\n const f=((t*9 + o.x)|0)%4; ctx.drawImage(SP.glow[f&1], (sx-24)|0, (sy-26)|0); ctx.drawImage(SP.torch, (sx-3)|0, sy|0); ctx.drawImage(SP.flame[f], (sx-4)|0, (sy-11)|0); }\n // vines: swaying segment chains\n for(const v of SPAWN.vines){ const sx=v.x-cx; if(sx<-30||sx>W+30) continue; const n=(v.len/4)|0;\n for(let i=0;i{ const [c,g]=mk(8,12); const lean=[0,1,0"}},{"t":1234286,"name":"aiToolStream","data":{"toolId":18,"toolName":"Edit","append":",-1][f], h=[10,11,9,11"}},{"t":1234618,"name":"aiToolStream","data":{"toolId":18,"toolName":"Edit","append":"][f];\\n for(let y=0;y1) px(g,C.pap,x+1,11-"}},{"t":1236008,"name":"aiToolStream","data":{"toolId":18,"toolName":"Edit","append":"y,wv*2-2,1); if(wv>2&&y{ const ["}},{"t":1237129,"name":"aiToolStream","data":{"toolId":18,"toolName":"Edit","append":"c,g]=mk(48,48); g.globalAlpha=.07; disc(g,C"}},{"t":1237380,"name":"aiToolStream","data":{"toolId":18,"toolName":"Edit","append":".pap,24,24,23-f); disc(g,C.pap,24,24,17-"}},{"t":1237630,"name":"aiToolStream","data":{"toolId":18,"toolName":"Edit","append":"f); g.globalAlpha=.09; disc(g,C.papL,24,24,11"}},{"t":1237881,"name":"aiToolStream","data":{"toolId":18,"toolName":"Edit","append":"-f); disc(g,C.ivo,24,24,6); return c; });\\n SP"}},{"t":1238131,"name":"aiToolStream","data":{"toolId":18,"toolName":"Edit","append":".vine = [0,1,2,3].map(v=>{ const [c,g]=mk(8,"}},{"t":1238384,"name":"aiToolStream","data":{"toolId":18,"toolName":"Edit","append":"4); px(g,C.leaf5,3,0,2,4); px(g,C.leaf"}},{"t":1238708,"name":"aiToolStream","data":{"toolId":18,"toolName":"Edit","append":"3,3,0,1,4);\\n if(v===1){ px(g,C.leaf4,5,1"}},{"t":1239006,"name":"aiToolStream","data":{"toolId":18,"toolName":"Edit","append":",3,2); px(g,C.leaf2,6,1,1,1);} if("}},{"t":1239267,"name":"aiToolStream","data":{"toolId":18,"toolName":"Edit","append":"v===3){ px(g,C.leaf4,0,1,3,2); px(g,C.lea"}},{"t":1239518,"name":"aiToolStream","data":{"toolId":18,"toolName":"Edit","append":"f2,1,1,1,1);} if(v===2) px(g,C.leaf6"}},{"t":1239819,"name":"aiToolStream","data":{"toolId":18,"toolName":"Edit","append":",4,2,1,2); return c; });\\n})();\\n"}},{"t":1240259,"name":"aiToolStream","data":{"toolId":18,"toolName":"Edit","append":"\"}"}},{"t":1240272,"name":"aiToolInfo","data":{"toolName":"Edit","toolId":18,"toolInput":{"file_path":"{{PROJECT}}/dave-jungle-temple.html","old_string":"/* ==SPRITES== */\n","new_string":"/* ==SPRITES== */\nconst SP = {};\n(function makeDecorSprites(){\n { const [c,g]=mk(6,12); px(g,C.woodD,2,2,2,10); px(g,C.wood,2,2,1,9); px(g,C.stoneDD,0,0,6,3); px(g,C.stoneL,0,0,6,1); SP.torch=c; }\n SP.flame = [0,1,2,3].map(f=>{ const [c,g]=mk(8,12); const lean=[0,1,0,-1][f], h=[10,11,9,11][f];\n for(let y=0;y1) px(g,C.pap,x+1,11-y,wv*2-2,1); if(wv>2&&y{ const [c,g]=mk(48,48); g.globalAlpha=.07; disc(g,C.pap,24,24,23-f); disc(g,C.pap,24,24,17-f); g.globalAlpha=.09; disc(g,C.papL,24,24,11-f); disc(g,C.ivo,24,24,6); return c; });\n SP.vine = [0,1,2,3].map(v=>{ const [c,g]=mk(8,4); px(g,C.leaf5,3,0,2,4); px(g,C.leaf3,3,0,1,4);\n if(v===1){ px(g,C.leaf4,5,1,3,2); px(g,C.leaf2,6,1,1,1);} if(v===3){ px(g,C.leaf4,0,1,3,2); px(g,C.leaf2,1,1,1,1);} if(v===2) px(g,C.leaf6,4,2,1,2); return c; });\n})();\n"}}},{"t":1240274,"name":"aiProgress","data":{"toolName":"Edit","toolId":19,"phase":"tool_use"}},{"t":1240319,"name":"aiToolEdit","data":{"toolId":18,"edit":{"file":"{{PROJECT}}/dave-jungle-temple.html","oldText":"/* ==SPRITES== */\n","newText":"/* ==SPRITES== */\nconst SP = {};\n(function makeDecorSprites(){\n { const [c,g]=mk(6,12); px(g,C.woodD,2,2,2,10); px(g,C.wood,2,2,1,9); px(g,C.stoneDD,0,0,6,3); px(g,C.stoneL,0,0,6,1); SP.torch=c; }\n SP.flame = [0,1,2,3].map(f=>{ const [c,g]=mk(8,12); const lean=[0,1,0,-1][f], h=[10,11,9,11][f];\n for(let y=0;y1) px(g,C.pap,x+1,11-y,wv*2-2,1); if(wv>2&&y{ const [c,g]=mk(48,48); g.globalAlpha=.07; disc(g,C.pap,24,24,23-f); disc(g,C.pap,24,24,17-f); g.globalAlpha=.09; disc(g,C.papL,24,24,11-f); disc(g,C.ivo,24,24,6); return c; });\n SP.vine = [0,1,2,3].map(v=>{ const [c,g]=mk(8,4); px(g,C.leaf5,3,0,2,4); px(g,C.leaf3,3,0,1,4);\n if(v===1){ px(g,C.leaf4,5,1,3,2); px(g,C.leaf2,6,1,1,1);} if(v===3){ px(g,C.leaf4,0,1,3,2); px(g,C.leaf2,1,1,1,1);} if(v===2) px(g,C.leaf6,4,2,1,2); return c; });\n})();\n","replaceAll":false,"isLivePreviewRelated":true}}},{"t":1240321,"name":"aiToolResult","data":{"toolId":18,"isError":false,"preview":"The file {{PROJECT}}/dave-jungle-temple.html has been updated s"}},{"t":1240388,"name":"aiToolStream","data":{"toolId":19,"toolName":"Edit","append":"{\"file_path\": \""}},{"t":1240697,"name":"aiToolStream","data":{"toolId":19,"toolName":"Edit","append":"{{PROJECT}}/dave-jungle-temple.html"}},{"t":1241009,"name":"aiToolStream","data":{"toolId":19,"toolName":"Edit","append":"\", \"old_string\": \"function update(dt){\\n G.time += dt;\\n}"}},{"t":1241320,"name":"aiToolStream","data":{"toolId":19,"toolName":"Edit","append":"\", \"new_string\": \"function update(dt){\\n G.time += dt;\\n if(typeof stepGame==='function')"}},{"t":1241589,"name":"aiToolStream","data":{"toolId":19,"toolName":"Edit","append":" stepGame(dt);\\n else G.camX = (Math.sin(G.time*.25-1.57)+1)"}},{"t":1241883,"name":"aiToolStream","data":{"toolId":19,"toolName":"Edit","append":"/2*(WORLD_W-W); // scenic pan until the player ex"}},{"t":1242133,"name":"aiToolStream","data":{"toolId":19,"toolName":"Edit","append":"ists\\n}\"}"}},{"t":1242255,"name":"aiToolInfo","data":{"toolName":"Edit","toolId":19,"toolInput":{"file_path":"{{PROJECT}}/dave-jungle-temple.html","old_string":"function update(dt){\n G.time += dt;\n}","new_string":"function update(dt){\n G.time += dt;\n if(typeof stepGame==='function') stepGame(dt);\n else G.camX = (Math.sin(G.time*.25-1.57)+1)/2*(WORLD_W-W); // scenic pan until the player exists\n}"}}},{"t":1242300,"name":"aiToolEdit","data":{"toolId":19,"edit":{"file":"{{PROJECT}}/dave-jungle-temple.html","oldText":"function update(dt){\n G.time += dt;\n}","newText":"function update(dt){\n G.time += dt;\n if(typeof stepGame==='function') stepGame(dt);\n else G.camX = (Math.sin(G.time*.25-1.57)+1)/2*(WORLD_W-W); // scenic pan until the player exists\n}","replaceAll":false,"isLivePreviewRelated":true}}},{"t":1242304,"name":"aiToolResult","data":{"toolId":19,"isError":false,"preview":"The file {{PROJECT}}/dave-jungle-temple.html has been updated s"}},{"t":1243568,"name":"aiProgress","data":{"toolName":"mcp__phoenix-editor__takeScreenshot","toolId":20,"phase":"tool_use"}},{"t":1244071,"name":"aiToolStream","data":{"toolId":20,"toolName":"mcp__phoenix-editor__takeScreenshot","append":"{\"selector\": \"#panel-live-preview-frame\", \"purePreview\": true}"}},{"t":1244116,"name":"aiToolInfo","data":{"toolName":"mcp__phoenix-editor__takeScreenshot","toolId":20,"toolInput":{"selector":"#panel-live-preview-frame","purePreview":true}}},{"t":1244356,"name":"aiToolResult","data":{"toolId":20,"isError":false,"preview":""}},{"t":1247427,"name":"aiTextStream","data":{"text":"\n\nThe preview is still showing the scaffold"}},{"t":1247468,"name":"aiTextStream","data":{"text":" — reloading to see the world layers."}},{"t":1247471,"name":"aiProgress","data":{"toolName":"mcp__phoenix-editor__takeScreenshot","toolId":21,"phase":"tool_use"}},{"t":1247471,"name":"aiToolStream","data":{"toolId":21,"toolName":"mcp__phoenix-editor__takeScreenshot","append":"{\"selector\": \"#panel-live-preview-frame"}},{"t":1247745,"name":"aiToolStream","data":{"toolId":21,"toolName":"mcp__phoenix-editor__takeScreenshot","append":"\", \"purePreview\": true, \"reload\": true}"}},{"t":1247753,"name":"aiToolInfo","data":{"toolName":"mcp__phoenix-editor__takeScreenshot","toolId":21,"toolInput":{"selector":"#panel-live-preview-frame","purePreview":true,"reload":true}}},{"t":1248583,"name":"aiToolResult","data":{"toolId":21,"isError":false,"preview":""}},{"t":1251806,"name":"aiProgress","data":{"toolName":"TaskUpdate","toolId":22,"phase":"tool_use"}},{"t":1251808,"name":"aiToolStream","data":{"toolId":22,"toolName":"TaskUpdate","append":"{\"taskId\": \"2"}},{"t":1252095,"name":"aiToolStream","data":{"toolId":22,"toolName":"TaskUpdate","append":"\", \"status\": \"completed\"}"}},{"t":1252098,"name":"aiToolInfo","data":{"toolName":"TaskUpdate","toolId":22,"toolInput":{"taskId":"2","status":"completed"}}},{"t":1252098,"name":"aiProgress","data":{"toolName":"TaskUpdate","toolId":23,"phase":"tool_use"}},{"t":1252102,"name":"aiToolResult","data":{"toolId":22,"isError":false,"preview":"Updated task #2 status"}},{"t":1252227,"name":"aiToolStream","data":{"toolId":23,"toolName":"TaskUpdate","append":"{\"taskId\": \"3\", \"status\": \"in_progress"}},{"t":1252520,"name":"aiToolStream","data":{"toolId":23,"toolName":"TaskUpdate","append":"\"}"}},{"t":1252524,"name":"aiToolInfo","data":{"toolName":"TaskUpdate","toolId":23,"toolInput":{"taskId":"3","status":"in_progress"}}},{"t":1252528,"name":"aiToolResult","data":{"toolId":23,"isError":false,"preview":"Updated task #3 status"}},{"t":1311951,"name":"aiProgress","data":{"toolName":"Edit","toolId":24,"phase":"tool_use"}},{"t":1312310,"name":"aiToolStream","data":{"toolId":24,"toolName":"Edit","append":"{\"file_path\": \"{{PROJECT}}"}},{"t":1312568,"name":"aiToolStream","data":{"toolId":24,"toolName":"Edit","append":"/dave-jungle-temple.html"}},{"t":1312831,"name":"aiToolStream","data":{"toolId":24,"toolName":"Edit","append":"\", \"old_string\": \"/* ==TILES== */\", \"new_string\": \""}},{"t":1313145,"name":"aiToolStream","data":{"toolId":24,"toolName":"Edit","append":"/* ==ACTOR SPRITES== */\\nfunction outlined(c){ const [s,sg]=mk(c.width,c"}},{"t":1313436,"name":"aiToolStream","data":{"toolId":24,"toolName":"Edit","append":".height); sg.drawImage(c,0,0); sg.globalCompositeOperation='source-in'; sg.fill"}},{"t":1313732,"name":"aiToolStream","data":{"toolId":24,"toolName":"Edit","append":"Style=C.ink; sg.fillRect(0,0,c.width,c.height);\\n const"}},{"t":1313985,"name":"aiToolStream","data":{"toolId":24,"toolName":"Edit","append":" [o,og]=mk(c.width+2,c.height+2); [[0,1],[2,1],"}},{"t":1314246,"name":"aiToolStream","data":{"toolId":24,"toolName":"Edit","append":"[1,0],[1,2]].forEach(d=>og.drawImage(s,d[0],d"}},{"t":1314526,"name":"aiToolStream","data":{"toolId":24,"toolName":"Edit","append":"[1])); og.drawImage(c,1,1); return o; }\\n(function makeActorSprites(){\\n const pal={p"}},{"t":1314829,"name":"aiToolStream","data":{"toolId":24,"toolName":"Edit","append":":C.pap,P:C.papD,s:'#f2c79a',S:'#c98f5f"}},{"t":1315079,"name":"aiToolStream","data":{"toolId":24,"toolName":"Edit","append":"',i:C.ivo,I:C.ivoD,g:C.leaf4,G:C.leaf6"}},{"t":1315381,"name":"aiToolStream","data":{"toolId":24,"toolName":"Edit","append":",b:C.woodD,k:C.ink,h:'#5a3520',v"}},{"t":1315678,"name":"aiToolStream","data":{"toolId":24,"toolName":"Edit","append":":C.ivo,d:C.papDD};\\n const body=[\\\"....pppp"}},{"t":1315930,"name":"aiToolStream","data":{"toolId":24,"toolName":"Edit","append":"....\\\",\\\"...pppppp...\\\",\\\"..PPPPPPppp.\\\",\\\"...hsssks...\\\",\\\"...hsssss"}},{"t":1316207,"name":"aiToolStream","data":{"toolId":24,"toolName":"Edit","append":"...\\\",\\\"....sSSs....\\\",\\\"...iiiiiI...\\\",\\\"..siiiiiIs..\\\",\\\"..siii"}},{"t":1316458,"name":"aiToolStream","data":{"toolId":24,"toolName":"Edit","append":"iiIs..\\\",\\\"..s.iiiI.s..\\\",\\\"...PPPPPP...\\\",\\\"...ggggGG...\\\"];\\n const bod"}},{"t":1316763,"name":"aiToolStream","data":{"toolId":24,"toolName":"Edit","append":"yJ=[\\\"....pppp....\\\",\\\"...pppppp...\\\",\\\"..PPPPPPppp.\\\",\\\"...hsssks...\\\",\\\".."}},{"t":1317054,"name":"aiToolStream","data":{"toolId":24,"toolName":"Edit","append":"shsssss.s.\\\",\\\"..s.sSSs.s..\\\",\\\"..si"}},{"t":1317342,"name":"aiToolStream","data":{"toolId":24,"toolName":"Edit","append":"iiiiIs..\\\",\\\"...iiiiiI...\\\",\\\"...iiiiiI...\\\",\\\"....iiiI....\\\",\\\"...P"}},{"t":1317649,"name":"aiToolStream","data":{"toolId":24,"toolName":"Edit","append":"PPPPP...\\\",\\\"...ggggGG...\\\"];\\n const legs={idle:[\\\"...gg..GG...\\\",\\\"...gg..GG"}},{"t":1317956,"name":"aiToolStream","data":{"toolId":24,"toolName":"Edit","append":"...\\\",\\\"...bb..bb...\\\",\\\"...bbb.bbb..\\\"],\\n r"}},{"t":1318243,"name":"aiToolStream","data":{"toolId":24,"toolName":"Edit","append":"1:[\\\"..ggg..GG...\\\",\\\".ggg....GG..\\\",\\\".bb.....bb..\\\",\\\".bb.....b"}},{"t":1318556,"name":"aiToolStream","data":{"toolId":24,"toolName":"Edit","append":"bb.\\\"], r2:[\\\"....ggGG....\\\",\\\"....ggGG....\\\",\\\"....bb"}},{"t":1318845,"name":"aiToolStream","data":{"toolId":24,"toolName":"Edit","append":"G.....\\\",\\\"....bbbb....\\\"],\\n r3:[\\\"...GG..gg...\\\",\\\".."}},{"t":1319139,"name":"aiToolStream","data":{"toolId":24,"toolName":"Edit","append":"GG....gg..\\\",\\\"..bb....bb..\\\",\\\"..bbb..."}},{"t":1319394,"name":"aiToolStream","data":{"toolId":24,"toolName":"Edit","append":"bbb.\\\"], j:[\\\"..ggg..GGG..\\\",\\\"..gg....GG..\\\",\\\"..bb....bb..\\\",\\\"............\\\"]};"}},{"t":1319717,"name":"aiToolStream","data":{"toolId":24,"toolName":"Edit","append":"\\n const mkp=(b,l)=>{ const r=outlined(spr"}},{"t":1320020,"name":"aiToolStream","data":{"toolId":24,"toolName":"Edit","append":"ite(b.concat(l),pal)); return [flipH(r),r];"}},{"t":1320276,"name":"aiToolStream","data":{"toolId":24,"toolName":"Edit","append":" }; // [left,right]\\n SP.dave={ idle:mkp(body"}},{"t":1320583,"name":"aiToolStream","data":{"toolId":24,"toolName":"Edit","append":",legs.idle), run:[mkp(body,legs.r1),mkp(body,legs.r2),mkp(body,"}},{"t":1320871,"name":"aiToolStream","data":{"toolId":24,"toolName":"Edit","append":"legs.r3),mkp(body,legs.r2)], jump:mkp(bodyJ,"}},{"t":1321123,"name":"aiToolStream","data":{"toolId":24,"toolName":"Edit","append":"legs.j) };\\n SP.snake=[0,1].map(f=>{ const [c,g]"}},{"t":1321431,"name":"aiToolStream","data":{"toolId":24,"toolName":"Edit","append":"=mk(16,10);\\n for(let x=0;x<11;x++){ const y=6+Math.round(Math.sin"}},{"t":1321711,"name":"aiToolStream","data":{"toolId":24,"toolName":"Edit","append":"(x*.95+f*Math.PI)*1.5); px(g,C.pap"}},{"t":1321962,"name":"aiToolStream","data":{"toolId":24,"toolName":"Edit","append":"D,x,y,1,"}},{"t":1322453,"name":"aiToolStream","data":{"toolId":24,"toolName":"Edit","append":"3); px(g,C.pap,x,y,1,1); if(x%3===0) px(g,C.ivo,x,y+1,1,1); }\\n px(g,C.papD,9,4,2,5); px(g,C.papD,10,1,5,5); px(g"}},{"t":1322768,"name":"aiToolStream","data":{"toolId":24,"toolName":"Edit","append":",C.pap,10,1,5,2); px(g,C.ivo,13,2,1,2"}},{"t":1323436,"name":"aiToolStream","data":{"toolId":24,"toolName":"Edit","append":"); px(g,C.ink,13,3,1,1); px(g,C.ivo,15,5,"}},{"t":1323729,"name":"aiToolStream","data":{"toolId":24,"toolName":"Edit","append":"1,1);\\n const r=outlined(c); return [flipH(r),r]; });\\n const batPal={p:C.papD,P:C.papDD,i:C.ivo,k:C.papDD,v:C.ivo};\\n SP."}},{"t":1324063,"name":"aiToolStream","data":{"toolId":24,"toolName":"Edit","append":"bat=[[\\\"p..............p\\\",\\\"pp............pp\\\",\\\"ppp...k..k...ppp\\\",\\\".pppp.PPP"}},{"t":1324322,"name":"aiToolStream","data":{"toolId":24,"toolName":"Edit","append":"P.pppp.\\\",\\\"..ppppPiPiPppp..\\\",\\\"...pppPPPPppp...\\\","}},{"t":1324586,"name":"aiToolStream","data":{"toolId":24,"toolName":"Edit","append":"\\\".....pPPPPp.....\\\",\\\"......PvvP......\\\"],\\n "}},{"t":1324837,"name":"aiToolStream","data":{"toolId":24,"toolName":"Edit","append":"[\\\"................\\\",\\\"......k..k......\\\",\\\"......PPPP......\\\",\\\"..ppppPiP"}},{"t":1325456,"name":"aiToolStream","data":{"toolId":24,"toolName":"Edit","append":"iPppp..\\\",\\\".pppppPPPPppppp.\\\",\\\"ppp.ppPPPPpp.ppp\\\",\\\"pp....PvvP....pp\\\",\\\"p..............p\\\"]].map(r=>outlined(sprite(r,batPal)));\\n const gemRows=[\\\"..hhhh..\\\","}},{"t":1325795,"name":"aiToolStream","data":{"toolId":24,"toolName":"Edit","append":"\\\".hllllm.\\\",\\\"hllllmmd\\\",\\\"hlllmmmd\\\",\\\".mmmmdd.\\\",\\\"..mmdd..\\\",\\\"...d"}},{"t":1326065,"name":"aiToolStream","data":{"toolId":24,"toolName":"Edit","append":"d...\\\"];\\n SP.gem=[ outlined(sprite(gemRows,{h:"}},{"t":1326401,"name":"aiToolStream","data":{"toolId":24,"toolName":"Edit","append":"C.ivo,l:C.papL,m:C.pap,d:C.papD})), outlined("}},{"t":1327039,"name":"aiToolStream","data":{"toolId":24,"toolName":"Edit","append":"sprite(gemRows,{h:'#ffffff',l:C.ivo,m:C.ivoD,d:C.ivoDD})) ];\\n SP.spark=sprite([\\\"..i..\\\",\\\"..i..\\\",\\\"iiiii\\\",\\\""}},{"t":1327336,"name":"aiToolStream","data":{"toolId":24,"toolName":"Edit","append":"..i..\\\",\\\"..i..\\\"],{i:C.ivo});\\n SP.key=outlined(spr"}},{"t":1327590,"name":"aiToolStream","data":{"toolId":24,"toolName":"Edit","append":"ite([\\\".hhh........\\\",\\\"p"}},{"t":1328290,"name":"aiToolStream","data":{"toolId":24,"toolName":"Edit","append":"p.pp.......\\\",\\\"p...pppppppp\\\",\\\"pp.pp..."}},{"t":1328558,"name":"aiToolStream","data":{"toolId":24,"toolName":"Edit","append":"p.p.\\\",\\\".ddd....d.d.\\\"],{h:C.ivo,p:C.papL,d:C.pap}));\\n SP.heart=outlined(sprite([\\\".pp.pp.\\\",\\\"phpp"}},{"t":1328933,"name":"aiToolStream","data":{"toolId":24,"toolName":"Edit","append":"ppp\\\",\\\"ppppppp\\\",\\\".ppppp.\\\",\\\"..ppp..\\\",\\\"...p.."}},{"t":1329341,"name":"aiToolStream","data":{"toolId":24,"toolName":"Edit","append":".\\\"],{p"}},{"t":1329793,"name":"aiToolStream","data":{"toolId":24,"toolName":"Edit","append":":C.pap,h:C.ivo}));\\n SP.door=[0,1].map(open=>{ const [c,g]=mk(16,32); px(g,C.stoneD,0,2,16,30); px(g,C.st"}},{"t":1330136,"name":"aiToolStream","data":{"toolId":24,"toolName":"Edit","append":"oneD,2,0,12,2); px(g,C.stoneL,2,0,12,1); px(g,C.stoneL,0,2,2,1); px(g,C"}},{"t":1330514,"name":"aiToolStream","data":{"toolId":24,"toolName":"Edit","append":".stoneL,14,2,2,1); px(g,C.stoneDD,0,31,16,1);\\n for(let"}},{"t":1330891,"name":"aiToolStream","data":{"toolId":24,"toolName":"Edit","append":" y=6;y<32;y+=6){ px(g,C.st"}},{"t":1331242,"name":"aiToolStream","data":{"toolId":24,"toolName":"Edit","append":"oneDD,0,y,2,1); px(g,C.stoneDD,14,y,2,1); }\\n if(!open){ px(g,C.wood,2,4,12"}},{"t":1331599,"name":"aiToolStream","data":{"toolId":24,"toolName":"Edit","append":",28); px(g,C.wood,4,2,8,2); for"}},{"t":1331992,"name":"aiToolStream","data":{"toolId":24,"toolName":"Edit","append":"(let x=5;x<14;x+=3) px(g,C.woodD,x,3,1,29"}},{"t":1332371,"name":"aiToolStream","data":{"toolId":24,"toolName":"Edit","append":"); px(g,C.woodD,2,12,12,1); px(g,C.woodD,2,24,12,1); px(g,C"}},{"t":1332733,"name":"aiToolStream","data":{"toolId":24,"toolName":"Edit","append":".papL,2,4,12,1);\\n px(g,C.pap,9,16,4,5"}},{"t":1333110,"name":"aiToolStream","data":{"toolId":24,"toolName":"Edit","append":"); px(g,C.ink,10,17,2,2); px(g,C.ink,10,19,1,1"}},{"t":1333487,"name":"aiToolStream","data":{"toolId":24,"toolName":"Edit","append":"); }\\n else { px(g,C.ink,2,4,12,28); px(g,C.ink,4,2,8,2); px(g,C.papD"}},{"t":1333776,"name":"aiToolStream","data":{"toolId":24,"toolName":"Edit","append":",4,6,8,26); px(g,C.pap,5"}},{"t":1334032,"name":"aiToolStream","data":{"toolId":24,"toolName":"Edit","append":",8,6,24); px(g,C.papL,6,11,4,21"}},{"t":1334322,"name":"aiToolStream","data":{"toolId":24,"toolName":"Edit","append":"); px(g,C.ivo,7,15,2,17); }\\n return c; });\\n})();\\n\\n/* ==TILES=="}},{"t":1334620,"name":"aiToolStream","data":{"toolId":24,"toolName":"Edit","append":" */\"}"}},{"t":1334761,"name":"aiToolInfo","data":{"toolName":"Edit","toolId":24,"toolInput":{"file_path":"{{PROJECT}}/dave-jungle-temple.html","old_string":"/* ==TILES== */","new_string":"/* ==ACTOR SPRITES== */\nfunction outlined(c){ const [s,sg]=mk(c.width,c.height); sg.drawImage(c,0,0); sg.globalCompositeOperation='source-in'; sg.fillStyle=C.ink; sg.fillRect(0,0,c.width,c.height);\n const [o,og]=mk(c.width+2,c.height+2); [[0,1],[2,1],[1,0],[1,2]].forEach(d=>og.drawImage(s,d[0],d[1])); og.drawImage(c,1,1); return o; }\n(function makeActorSprites(){\n const pal={p:C.pap,P:C.papD,s:'#f2c79a',S:'#c98f5f',i:C.ivo,I:C.ivoD,g:C.leaf4,G:C.leaf6,b:C.woodD,k:C.ink,h:'#5a3520',v:C.ivo,d:C.papDD};\n const body=[\"....pppp....\",\"...pppppp...\",\"..PPPPPPppp.\",\"...hsssks...\",\"...hsssss...\",\"....sSSs....\",\"...iiiiiI...\",\"..siiiiiIs..\",\"..siiiiiIs..\",\"..s.iiiI.s..\",\"...PPPPPP...\",\"...ggggGG...\"];\n const bodyJ=[\"....pppp....\",\"...pppppp...\",\"..PPPPPPppp.\",\"...hsssks...\",\"..shsssss.s.\",\"..s.sSSs.s..\",\"..siiiiiIs..\",\"...iiiiiI...\",\"...iiiiiI...\",\"....iiiI....\",\"...PPPPPP...\",\"...ggggGG...\"];\n const legs={idle:[\"...gg..GG...\",\"...gg..GG...\",\"...bb..bb...\",\"...bbb.bbb..\"],\n r1:[\"..ggg..GG...\",\".ggg....GG..\",\".bb.....bb..\",\".bb.....bbb.\"], r2:[\"....ggGG....\",\"....ggGG....\",\"....bbG.....\",\"....bbbb....\"],\n r3:[\"...GG..gg...\",\"..GG....gg..\",\"..bb....bb..\",\"..bbb...bbb.\"], j:[\"..ggg..GGG..\",\"..gg....GG..\",\"..bb....bb..\",\"............\"]};\n const mkp=(b,l)=>{ const r=outlined(sprite(b.concat(l),pal)); return [flipH(r),r]; }; // [left,right]\n SP.dave={ idle:mkp(body,legs.idle), run:[mkp(body,legs.r1),mkp(body,legs.r2),mkp(body,legs.r3),mkp(body,legs.r2)], jump:mkp(bodyJ,legs.j) };\n SP.snake=[0,1].map(f=>{ const [c,g]=mk(16,10);\n for(let x=0;x<11;x++){ const y=6+Math.round(Math.sin(x*.95+f*Math.PI)*1.5); px(g,C.papD,x,y,1,3); px(g,C.pap,x,y,1,1); if(x%3===0) px(g,C.ivo,x,y+1,1,1); }\n px(g,C.papD,9,4,2,5); px(g,C.papD,10,1,5,5); px(g,C.pap,10,1,5,2); px(g,C.ivo,13,2,1,2); px(g,C.ink,13,3,1,1); px(g,C.ivo,15,5,1,1);\n const r=outlined(c); return [flipH(r),r]; });\n const batPal={p:C.papD,P:C.papDD,i:C.ivo,k:C.papDD,v:C.ivo};\n SP.bat=[[\"p..............p\",\"pp............pp\",\"ppp...k..k...ppp\",\".pppp.PPPP.pppp.\",\"..ppppPiPiPppp..\",\"...pppPPPPppp...\",\".....pPPPPp.....\",\"......PvvP......\"],\n [\"................\",\"......k..k......\",\"......PPPP......\",\"..ppppPiPiPppp..\",\".pppppPPPPppppp.\",\"ppp.ppPPPPpp.ppp\",\"pp....PvvP....pp\",\"p..............p\"]].map(r=>outlined(sprite(r,batPal)));\n const gemRows=[\"..hhhh..\",\".hllllm.\",\"hllllmmd\",\"hlllmmmd\",\".mmmmdd.\",\"..mmdd..\",\"...dd...\"];\n SP.gem=[ outlined(sprite(gemRows,{h:C.ivo,l:C.papL,m:C.pap,d:C.papD})), outlined(sprite(gemRows,{h:'#ffffff',l:C.ivo,m:C.ivoD,d:C.ivoDD})) ];\n SP.spark=sprite([\"..i..\",\"..i..\",\"iiiii\",\"..i..\",\"..i..\"],{i:C.ivo});\n SP.key=outlined(sprite([\".hhh........\",\"pp.pp.......\",\"p...pppppppp\",\"pp.pp...p.p.\",\".ddd....d.d.\"],{h:C.ivo,p:C.papL,d:C.pap}));\n SP.heart=outlined(sprite([\".pp.pp.\",\"phppppp\",\"ppppppp\",\".ppppp.\",\"..ppp..\",\"...p...\"],{p:C.pap,h:C.ivo}));\n SP.door=[0,1].map(open=>{ const [c,g]=mk(16,32); px(g,C.stoneD,0,2,16,30); px(g,C.stoneD,2,0,12,2); px(g,C.stoneL,2,0,12,1); px(g,C.stoneL,0,2,2,1); px(g,C.stoneL,14,2,2,1); px(g,C.stoneDD,0,31,16,1);\n for(let y=6;y<32;y+=6){ px(g,C.stoneDD,0,y,2,1); px(g,C.stoneDD,14,y,2,1); }\n if(!open){ px(g,C.wood,2,4,12,28); px(g,C.wood,4,2,8,2); for(let x=5;x<14;x+=3) px(g,C.woodD,x,3,1,29); px(g,C.woodD,2,12,12,1); px(g,C.woodD,2,24,12,1); px(g,C.papL,2,4,12,1);\n px(g,C.pap,9,16,4,5); px(g,C.ink,10,17,2,2); px(g,C.ink,10,19,1,1); }\n else { px(g,C.ink,2,4,12,28); px(g,C.ink,4,2,8,2); px(g,C.papD,4,6,8,26); px(g,C.pap,5,8,6,24); px(g,C.papL,6,11,4,21); px(g,C.ivo,7,15,2,17); }\n return c; });\n})();\n\n/* ==TILES== */"}}},{"t":1334814,"name":"aiToolEdit","data":{"toolId":24,"edit":{"file":"{{PROJECT}}/dave-jungle-temple.html","oldText":"/* ==TILES== */","newText":"/* ==ACTOR SPRITES== */\nfunction outlined(c){ const [s,sg]=mk(c.width,c.height); sg.drawImage(c,0,0); sg.globalCompositeOperation='source-in'; sg.fillStyle=C.ink; sg.fillRect(0,0,c.width,c.height);\n const [o,og]=mk(c.width+2,c.height+2); [[0,1],[2,1],[1,0],[1,2]].forEach(d=>og.drawImage(s,d[0],d[1])); og.drawImage(c,1,1); return o; }\n(function makeActorSprites(){\n const pal={p:C.pap,P:C.papD,s:'#f2c79a',S:'#c98f5f',i:C.ivo,I:C.ivoD,g:C.leaf4,G:C.leaf6,b:C.woodD,k:C.ink,h:'#5a3520',v:C.ivo,d:C.papDD};\n const body=[\"....pppp....\",\"...pppppp...\",\"..PPPPPPppp.\",\"...hsssks...\",\"...hsssss...\",\"....sSSs....\",\"...iiiiiI...\",\"..siiiiiIs..\",\"..siiiiiIs..\",\"..s.iiiI.s..\",\"...PPPPPP...\",\"...ggggGG...\"];\n const bodyJ=[\"....pppp....\",\"...pppppp...\",\"..PPPPPPppp.\",\"...hsssks...\",\"..shsssss.s.\",\"..s.sSSs.s..\",\"..siiiiiIs..\",\"...iiiiiI...\",\"...iiiiiI...\",\"....iiiI....\",\"...PPPPPP...\",\"...ggggGG...\"];\n const legs={idle:[\"...gg..GG...\",\"...gg..GG...\",\"...bb..bb...\",\"...bbb.bbb..\"],\n r1:[\"..ggg..GG...\",\".ggg....GG..\",\".bb.....bb..\",\".bb.....bbb.\"], r2:[\"....ggGG....\",\"....ggGG....\",\"....bbG.....\",\"....bbbb....\"],\n r3:[\"...GG..gg...\",\"..GG....gg..\",\"..bb....bb..\",\"..bbb...bbb.\"], j:[\"..ggg..GGG..\",\"..gg....GG..\",\"..bb....bb..\",\"............\"]};\n const mkp=(b,l)=>{ const r=outlined(sprite(b.concat(l),pal)); return [flipH(r),r]; }; // [left,right]\n SP.dave={ idle:mkp(body,legs.idle), run:[mkp(body,legs.r1),mkp(body,legs.r2),mkp(body,legs.r3),mkp(body,legs.r2)], jump:mkp(bodyJ,legs.j) };\n SP.snake=[0,1].map(f=>{ const [c,g]=mk(16,10);\n for(let x=0;x<11;x++){ const y=6+Math.round(Math.sin(x*.95+f*Math.PI)*1.5); px(g,C.papD,x,y,1,3); px(g,C.pap,x,y,1,1); if(x%3===0) px(g,C.ivo,x,y+1,1,1); }\n px(g,C.papD,9,4,2,5); px(g,C.papD,10,1,5,5); px(g,C.pap,10,1,5,2); px(g,C.ivo,13,2,1,2); px(g,C.ink,13,3,1,1); px(g,C.ivo,15,5,1,1);\n const r=outlined(c); return [flipH(r),r]; });\n const batPal={p:C.papD,P:C.papDD,i:C.ivo,k:C.papDD,v:C.ivo};\n SP.bat=[[\"p..............p\",\"pp............pp\",\"ppp...k..k...ppp\",\".pppp.PPPP.pppp.\",\"..ppppPiPiPppp..\",\"...pppPPPPppp...\",\".....pPPPPp.....\",\"......PvvP......\"],\n [\"................\",\"......k..k......\",\"......PPPP......\",\"..ppppPiPiPppp..\",\".pppppPPPPppppp.\",\"ppp.ppPPPPpp.ppp\",\"pp....PvvP....pp\",\"p..............p\"]].map(r=>outlined(sprite(r,batPal)));\n const gemRows=[\"..hhhh..\",\".hllllm.\",\"hllllmmd\",\"hlllmmmd\",\".mmmmdd.\",\"..mmdd..\",\"...dd...\"];\n SP.gem=[ outlined(sprite(gemRows,{h:C.ivo,l:C.papL,m:C.pap,d:C.papD})), outlined(sprite(gemRows,{h:'#ffffff',l:C.ivo,m:C.ivoD,d:C.ivoDD})) ];\n SP.spark=sprite([\"..i..\",\"..i..\",\"iiiii\",\"..i..\",\"..i..\"],{i:C.ivo});\n SP.key=outlined(sprite([\".hhh........\",\"pp.pp.......\",\"p...pppppppp\",\"pp.pp...p.p.\",\".ddd....d.d.\"],{h:C.ivo,p:C.papL,d:C.pap}));\n SP.heart=outlined(sprite([\".pp.pp.\",\"phppppp\",\"ppppppp\",\".ppppp.\",\"..ppp..\",\"...p...\"],{p:C.pap,h:C.ivo}));\n SP.door=[0,1].map(open=>{ const [c,g]=mk(16,32); px(g,C.stoneD,0,2,16,30); px(g,C.stoneD,2,0,12,2); px(g,C.stoneL,2,0,12,1); px(g,C.stoneL,0,2,2,1); px(g,C.stoneL,14,2,2,1); px(g,C.stoneDD,0,31,16,1);\n for(let y=6;y<32;y+=6){ px(g,C.stoneDD,0,y,2,1); px(g,C.stoneDD,14,y,2,1); }\n if(!open){ px(g,C.wood,2,4,12,28); px(g,C.wood,4,2,8,2); for(let x=5;x<14;x+=3) px(g,C.woodD,x,3,1,29); px(g,C.woodD,2,12,12,1); px(g,C.woodD,2,24,12,1); px(g,C.papL,2,4,12,1);\n px(g,C.pap,9,16,4,5); px(g,C.ink,10,17,2,2); px(g,C.ink,10,19,1,1); }\n else { px(g,C.ink,2,4,12,28); px(g,C.ink,4,2,8,2); px(g,C.papD,4,6,8,26); px(g,C.pap,5,8,6,24); px(g,C.papL,6,11,4,21); px(g,C.ivo,7,15,2,17); }\n return c; });\n})();\n\n/* ==TILES== */","replaceAll":false,"isLivePreviewRelated":true}}},{"t":1334815,"name":"aiToolResult","data":{"toolId":24,"isError":false,"preview":"The file {{PROJECT}}/dave-jungle-temple.html has been updated s"}},{"t":1339582,"name":"aiProgress","data":{"toolName":"Edit","toolId":25,"phase":"tool_use"}},{"t":1339722,"name":"aiToolStream","data":{"toolId":25,"toolName":"Edit","append":"{\"file_path\": \""}},{"t":1340247,"name":"aiToolStream","data":{"toolId":25,"toolName":"Edit","append":"{{PROJECT}}/dave-jungle-temple.html\", \"old_string\": \"/* ==SP"}},{"t":1340544,"name":"aiToolStream","data":{"toolId":25,"toolName":"Edit","append":"RITES== */\\nconst SP = {};\\n(function makeDecorSprites(){\", \"new_string\": \"/* ==SPRITES"}},{"t":1340853,"name":"aiToolStream","data":{"toolId":25,"toolName":"Edit","append":"== */\\n(function makeDecorSprites(){"}},{"t":1341579,"name":"aiToolStream","data":{"toolId":25,"toolName":"Edit","append":"\"}"}},{"t":1341592,"name":"aiToolInfo","data":{"toolName":"Edit","toolId":25,"toolInput":{"file_path":"{{PROJECT}}/dave-jungle-temple.html","old_string":"/* ==SPRITES== */\nconst SP = {};\n(function makeDecorSprites(){","new_string":"/* ==SPRITES== */\n(function makeDecorSprites(){"}}},{"t":1341594,"name":"aiProgress","data":{"toolName":"Edit","toolId":26,"phase":"tool_use"}},{"t":1341594,"name":"aiToolStream","data":{"toolId":26,"toolName":"Edit","append":"{\"file_path\": \""}},{"t":1341641,"name":"aiToolEdit","data":{"toolId":25,"edit":{"file":"{{PROJECT}}/dave-jungle-temple.html","oldText":"/* ==SPRITES== */\nconst SP = {};\n(function makeDecorSprites(){","newText":"/* ==SPRITES== */\n(function makeDecorSprites(){","replaceAll":false,"isLivePreviewRelated":true}}},{"t":1341643,"name":"aiToolResult","data":{"toolId":25,"isError":false,"preview":"The file {{PROJECT}}/dave-jungle-temple.html has been updated s"}},{"t":1341812,"name":"aiToolStream","data":{"toolId":26,"toolName":"Edit","append":"{{PROJECT}}/dave-jungle-temple.html\", \"old_string\": \"/* ==AC"}},{"t":1342162,"name":"aiToolStream","data":{"toolId":26,"toolName":"Edit","append":"TOR SPRITES== */\\nfunction outlined(c"}},{"t":1342551,"name":"aiToolStream","data":{"toolId":26,"toolName":"Edit","append":"){\", \"new_string\": \""}},{"t":1343043,"name":"aiToolStream","data":{"toolId":26,"toolName":"Edit","append":"/* ==ACTOR SPRITES== */\\nconst SP = {};\\nfunction outlined(c){\"}"}},{"t":1343059,"name":"aiToolInfo","data":{"toolName":"Edit","toolId":26,"toolInput":{"file_path":"{{PROJECT}}/dave-jungle-temple.html","old_string":"/* ==ACTOR SPRITES== */\nfunction outlined(c){","new_string":"/* ==ACTOR SPRITES== */\nconst SP = {};\nfunction outlined(c){"}}},{"t":1343114,"name":"aiToolEdit","data":{"toolId":26,"edit":{"file":"{{PROJECT}}/dave-jungle-temple.html","oldText":"/* ==ACTOR SPRITES== */\nfunction outlined(c){","newText":"/* ==ACTOR SPRITES== */\nconst SP = {};\nfunction outlined(c){","replaceAll":false,"isLivePreviewRelated":true}}},{"t":1343116,"name":"aiToolResult","data":{"toolId":26,"isError":false,"preview":"The file {{PROJECT}}/dave-jungle-temple.html has been updated s"}},{"t":1345626,"name":"aiProgress","data":{"toolName":"Edit","toolId":27,"phase":"tool_use"}},{"t":1345627,"name":"aiToolStream","data":{"toolId":27,"toolName":"Edit","append":"{\"file_path\": \"{{PROJECT}}/dave-jungle-"}},{"t":1346273,"name":"aiToolStream","data":{"toolId":27,"toolName":"Edit","append":"temple.html\", \"old_string\": \"/* ==INPUT== */\\n\", \"new_string\": \"/* ==INPUT== *"}},{"t":1346928,"name":"aiToolStream","data":{"toolId":27,"toolName":"Edit","append":"/\\nconst keys = {left:false,right:false,jump:false};\\nconst KEYMAP = {ArrowLeft:'left',KeyA:'left',ArrowRight:'right',KeyD:'right',Ar"}},{"t":1347272,"name":"aiToolStream","data":{"toolId":27,"toolName":"Edit","append":"rowUp:'jump',KeyW:'jump',Space:'jump'};\\nfunction onAnyInput(){ if"}},{"t":1347534,"name":"aiToolStream","data":{"toolId":27,"toolName":"Edit","append":"(typeof takeControl==='function') takeControl(); }\\naddEventListener('keydown',e=>{ if(e.ctrlKey||e."}},{"t":1347809,"name":"aiToolStream","data":{"toolId":27,"toolName":"Edit","append":"metaKey||e.altKey) return; const k=KEYMAP[e.code];"}},{"t":1348113,"name":"aiToolStream","data":{"toolId":27,"toolName":"Edit","append":"\\n if(k){ keys[k]=true; e.preventDefault(); }"}},{"t":1348366,"name":"aiToolStream","data":{"toolId":27,"toolName":"Edit","append":"\\n if(e.code==='KeyM' && typeof to"}},{"t":1348621,"name":"aiToolStream","data":{"toolId":27,"toolName":"Edit","append":"ggleMute==='function'){ toggleMute(); return; }\\n if((e.code==='Enter'||e.code==='K"}},{"t":1348929,"name":"aiToolStream","data":{"toolId":27,"toolName":"Edit","append":"eyR') && typeof restartIfEnded==='function' && restartIfEnded"}},{"t":1349241,"name":"aiToolStream","data":{"toolId":27,"toolName":"Edit","append":"()) return;\\n if(e.key!=='Tab' && e.key!=='Sh"}},{"t":1349512,"name":"aiToolStream","data":{"toolId":27,"toolName":"Edit","append":"ift')"}},{"t":1350174,"name":"aiToolStream","data":{"toolId":27,"toolName":"Edit","append":" onAnyInput(); });\\naddEventListener('keyup',e=>{ const k=KEYMAP[e.code]; if(k){ keys[k]=false; e.preventDefault(); } });\\naddEventListener('blur',()=>{ keys.left=keys.right=keys.jump=false; });\\n\\n/* "}},{"t":1350435,"name":"aiToolStream","data":{"toolId":27,"toolName":"Edit","append":"==PLAYER== */\\nconst RUN=95, ACC=900, GRAV=950, JUM"}},{"t":1350686,"name":"aiToolStream","data":{"toolId":27,"toolName":"Edit","append":"P=310, MAXFALL=330;\\nconst P = {x:0,y:0,w:8,h:"}},{"t":1350939,"name":"aiToolStream","data":{"toolId":27,"toolName":"Edit","append":"14,vx:0,vy:0,dir:1,ground:false,coyote:0,jbuf:0,prevJump:"}},{"t":1351250,"name":"aiToolStream","data":{"toolId":27,"toolName":"Edit","append":"false,anim:0,dead:0,inv:0};\\nfunction placePlayer(x,y"}},{"t":1351560,"name":"aiToolStream","data":{"toolId":27,"toolName":"Edit","append":"){ P.x=x; P.y=y; P.vx=P.vy=0; P.dir"}},{"t":1351814,"name":"aiToolStream","data":{"toolId":27,"toolName":"Edit","append":"=1; P.dead=0; P.ground=false; P.prevJump=false; P.jbuf=0;"}},{"t":1352119,"name":"aiToolStream","data":{"toolId":27,"toolName":"Edit","append":" }\\nfunction movePlayer(dt,inp){\\n const want=(inp.right?1:0)-(inp.left"}},{"t":1352423,"name":"aiToolStream","data":{"toolId":27,"toolName":"Edit","append":"?1:0);\\n if(want){ P.vx+=want*ACC*dt; P.dir="}},{"t":1352689,"name":"aiToolStream","data":{"toolId":27,"toolName":"Edit","append":"want; } else { const d=Math.sign(P.vx); P.vx-=d*Math.min(Math.abs(P."}},{"t":1353003,"name":"aiToolStream","data":{"toolId":27,"toolName":"Edit","append":"vx),ACC*dt); }\\n P.vx=clamp(P.vx,-RUN,RUN);\\n P."}},{"t":1353305,"name":"aiToolStream","data":{"toolId":27,"toolName":"Edit","append":"coyote = P.ground ? .09 : P.coyote-dt;\\n if(inp.jump"}},{"t":1353555,"name":"aiToolStream","data":{"toolId":27,"toolName":"Edit","append":" && !P.prevJump) P.jbuf=.12; P.prevJump=inp.jump;"}},{"t":1353984,"name":"aiToolStream","data":{"toolId":27,"toolName":"Edit","append":" P.jbuf-="}},{"t":1354518,"name":"aiToolStream","data":{"toolId":27,"toolName":"Edit","append":"dt;\\n if(P.jbuf>0 && P.coyote>0){ P.vy=-JUMP; P.jbuf=0; P."}},{"t":1354770,"name":"aiToolStream","data":{"toolId":27,"toolName":"Edit","append":"coyote=0; P.ground=false; if(typeof onJump==='function') onJump(); }\\n if(!inp.jump && P.vy<-110) P.vy=-110; // release early = short h"}},{"t":1355062,"name":"aiToolStream","data":{"toolId":27,"toolName":"Edit","append":"op\\n P.vy=Math.min(P.vy+GRAV*dt,MAXFALL);\\n // horizontal"}},{"t":1355316,"name":"aiToolStream","data":{"toolId":27,"toolName":"Edit","append":"\\n P.x+=P"}},{"t":1355850,"name":"aiToolStream","data":{"toolId":27,"toolName":"Edit","append":".vx*dt;"}},{"t":1356350,"name":"aiToolStream","data":{"toolId":27,"toolName":"Edit","append":"\\n { const top=Math.floor(P.y/T), bot=Math.floor((P.y+P.h-.01)/T);\\n if(P.vx>0){ const tx=Math.floor((P.x+P.w)/T); for(let ty=top;ty<=bot;ty++) if(isSolid(tileAt(tx,ty))){ P.x=tx*T-P.w-.001; P.v"}},{"t":1356695,"name":"aiToolStream","data":{"toolId":27,"toolName":"Edit","append":"x=0; break; } }\\n else if(P.vx<0){ const tx=Math.floor(P.x/T); for(let ty=top;ty<=bot;ty++)"}},{"t":1357075,"name":"aiToolStream","data":{"toolId":27,"toolName":"Edit","append":" if(isSolid(tileAt(tx,ty))){ P.x=(tx+1)*T; P.vx=0; break; } } }\\n // vertical ("}},{"t":1357442,"name":"aiToolStream","data":{"toolId":27,"toolName":"Edit","append":"bridges are one-way)\\n const prevBottom=P.y+P.h, wasGround=P.ground; P.y+=P.vy*dt;"}},{"t":1357818,"name":"aiToolStream","data":{"toolId":27,"toolName":"Edit","append":" P.ground=false;\\n { const l=Math.floor(P.x/T), r=Math.floor((P.x+P.w"}},{"t":1358072,"name":"aiToolStream","data":{"toolId":27,"toolName":"Edit","append":"-.01)/T);\\n if(P.vy>=0){ const ty=Math.floor((P.y+P.h)/T"}},{"t":1358389,"name":"aiToolStream","data":{"toolId":27,"toolName":"Edit","append":");\\n for(let tx=l;tx<=r;tx++){ const ch=tileAt(tx"}},{"t":1358687,"name":"aiToolStream","data":{"toolId":27,"toolName":"Edit","append":",ty); if(isSolid(ch)||(ch==='-'&&prevBottom<="}},{"t":1358938,"name":"aiToolStream","data":{"toolId":27,"toolName":"Edit","append":"ty*T+.5)){ P.y=ty*T-P.h; if"}},{"t":1359191,"name":"aiToolStream","data":{"toolId":27,"toolName":"Edit","append":"(!wasGround&&P.vy>150&&typeof onLand"}},{"t":1359446,"name":"aiToolStream","data":{"toolId":27,"toolName":"Edit","append":"==='function') onLand(); P.vy=0;"}},{"t":1360072,"name":"aiToolStream","data":{"toolId":27,"toolName":"Edit","append":" P.ground=true; break; } } }\\n else { const ty=Math.floor(P.y/T); for(let tx=l;tx<=r;tx++) if(isSolid(tileAt(tx,ty))){ P.y=(ty+1)*T; P.vy=0; break; } } }"}},{"t":1360383,"name":"aiToolStream","data":{"toolId":27,"toolName":"Edit","append":"\\n P.anim += Math.abs(P.vx)*dt*.11;\\n}\\nfunction follow"}},{"t":1360642,"name":"aiToolStream","data":{"toolId":27,"toolName":"Edit","append":"Camera(dt,snap){\\n const tx=clamp(P.x+P.w/2-W/2+P.d"}},{"t":1360938,"name":"aiToolStream","data":{"toolId":27,"toolName":"Edit","append":"ir*18,0,WORLD_W-W), ty=clamp(P.y-92"}},{"t":1361245,"name":"aiToolStream","data":{"toolId":27,"toolName":"Edit","append":",0,WORLD_H-H), k=snap?1:Math.min(1,dt*4"}},{"t":1361558,"name":"aiToolStream","data":{"toolId":27,"toolName":"Edit","append":".5);\\n G.camX+=(tx-G.camX)*k; G.camY+=(ty"}},{"t":1361820,"name":"aiToolStream","data":{"toolId":27,"toolName":"Edit","append":"-G.camY)*Math.min(1,k*.7+"}},{"t":1362135,"name":"aiToolStream","data":{"toolId":27,"toolName":"Edit","append":" (snap?1:0));\\n}\\nfunction drawPl"}},{"t":1362726,"name":"aiToolStream","data":{"toolId":27,"toolName":"Edit","append":"ayer(cx,cy,t){\\n if(P.inv>0 && ((t*16)|0)%2) return;\\n const d=P.dir>0?1:0; let s;\\n if(!"}},{"t":1363076,"name":"aiToolStream","data":{"toolId":27,"toolName":"Edit","append":"P.ground) s=SP.dave.jump[d]; else if(Math.abs(P.vx)>12) s=SP.dave.run[(P.anim|0)%"}},{"t":1363379,"name":"aiToolStream","data":{"toolId":27,"toolName":"Edit","append":"4][d]; else s=SP.dave.idle[d];\\n const bob="}},{"t":1363633,"name":"aiToolStream","data":{"toolId":27,"toolName":"Edit","append":"(P.ground&&Math.abs(P.vx)<=12&"}},{"t":1363941,"name":"aiToolStream","data":{"toolId":27,"toolName":"Edit","append":"&((t*2.2)|0)%"}},{"t":1364226,"name":"aiToolStream","data":{"toolId":27,"toolName":"Edit","append":"2)"}},{"t":1364720,"name":"aiToolStream","data":{"toolId":27,"toolName":"Edit","append":"?1:0;\\n ctx.drawImage(s,Math.round(P.x-c"}},{"t":1365006,"name":"aiToolStream","data":{"toolId":27,"toolName":"Edit","append":"x)-3,Math.round(P.y-cy)-3+bob);\\n}\\n\"}"}},{"t":1365018,"name":"aiToolInfo","data":{"toolName":"Edit","toolId":27,"toolInput":{"file_path":"{{PROJECT}}/dave-jungle-temple.html","old_string":"/* ==INPUT== */\n","new_string":"/* ==INPUT== */\nconst keys = {left:false,right:false,jump:false};\nconst KEYMAP = {ArrowLeft:'left',KeyA:'left',ArrowRight:'right',KeyD:'right',ArrowUp:'jump',KeyW:'jump',Space:'jump'};\nfunction onAnyInput(){ if(typeof takeControl==='function') takeControl(); }\naddEventListener('keydown',e=>{ if(e.ctrlKey||e.metaKey||e.altKey) return; const k=KEYMAP[e.code];\n if(k){ keys[k]=true; e.preventDefault(); }\n if(e.code==='KeyM' && typeof toggleMute==='function'){ toggleMute(); return; }\n if((e.code==='Enter'||e.code==='KeyR') && typeof restartIfEnded==='function' && restartIfEnded()) return;\n if(e.key!=='Tab' && e.key!=='Shift') onAnyInput(); });\naddEventListener('keyup',e=>{ const k=KEYMAP[e.code]; if(k){ keys[k]=false; e.preventDefault(); } });\naddEventListener('blur',()=>{ keys.left=keys.right=keys.jump=false; });\n\n/* ==PLAYER== */\nconst RUN=95, ACC=900, GRAV=950, JUMP=310, MAXFALL=330;\nconst P = {x:0,y:0,w:8,h:14,vx:0,vy:0,dir:1,ground:false,coyote:0,jbuf:0,prevJump:false,anim:0,dead:0,inv:0};\nfunction placePlayer(x,y){ P.x=x; P.y=y; P.vx=P.vy=0; P.dir=1; P.dead=0; P.ground=false; P.prevJump=false; P.jbuf=0; }\nfunction movePlayer(dt,inp){\n const want=(inp.right?1:0)-(inp.left?1:0);\n if(want){ P.vx+=want*ACC*dt; P.dir=want; } else { const d=Math.sign(P.vx); P.vx-=d*Math.min(Math.abs(P.vx),ACC*dt); }\n P.vx=clamp(P.vx,-RUN,RUN);\n P.coyote = P.ground ? .09 : P.coyote-dt;\n if(inp.jump && !P.prevJump) P.jbuf=.12; P.prevJump=inp.jump; P.jbuf-=dt;\n if(P.jbuf>0 && P.coyote>0){ P.vy=-JUMP; P.jbuf=0; P.coyote=0; P.ground=false; if(typeof onJump==='function') onJump(); }\n if(!inp.jump && P.vy<-110) P.vy=-110; // release early = short hop\n P.vy=Math.min(P.vy+GRAV*dt,MAXFALL);\n // horizontal\n P.x+=P.vx*dt;\n { const top=Math.floor(P.y/T), bot=Math.floor((P.y+P.h-.01)/T);\n if(P.vx>0){ const tx=Math.floor((P.x+P.w)/T); for(let ty=top;ty<=bot;ty++) if(isSolid(tileAt(tx,ty))){ P.x=tx*T-P.w-.001; P.vx=0; break; } }\n else if(P.vx<0){ const tx=Math.floor(P.x/T); for(let ty=top;ty<=bot;ty++) if(isSolid(tileAt(tx,ty))){ P.x=(tx+1)*T; P.vx=0; break; } } }\n // vertical (bridges are one-way)\n const prevBottom=P.y+P.h, wasGround=P.ground; P.y+=P.vy*dt; P.ground=false;\n { const l=Math.floor(P.x/T), r=Math.floor((P.x+P.w-.01)/T);\n if(P.vy>=0){ const ty=Math.floor((P.y+P.h)/T);\n for(let tx=l;tx<=r;tx++){ const ch=tileAt(tx,ty); if(isSolid(ch)||(ch==='-'&&prevBottom<=ty*T+.5)){ P.y=ty*T-P.h; if(!wasGround&&P.vy>150&&typeof onLand==='function') onLand(); P.vy=0; P.ground=true; break; } } }\n else { const ty=Math.floor(P.y/T); for(let tx=l;tx<=r;tx++) if(isSolid(tileAt(tx,ty))){ P.y=(ty+1)*T; P.vy=0; break; } } }\n P.anim += Math.abs(P.vx)*dt*.11;\n}\nfunction followCamera(dt,snap){\n const tx=clamp(P.x+P.w/2-W/2+P.dir*18,0,WORLD_W-W), ty=clamp(P.y-92,0,WORLD_H-H), k=snap?1:Math.min(1,dt*4.5);\n G.camX+=(tx-G.camX)*k; G.camY+=(ty-G.camY)*Math.min(1,k*.7+ (snap?1:0));\n}\nfunction drawPlayer(cx,cy,t){\n if(P.inv>0 && ((t*16)|0)%2) return;\n const d=P.dir>0?1:0; let s;\n if(!P.ground) s=SP.dave.jump[d]; else if(Math.abs(P.vx)>12) s=SP.dave.run[(P.anim|0)%4][d]; else s=SP.dave.idle[d];\n const bob=(P.ground&&Math.abs(P.vx)<=12&&((t*2.2)|0)%2)?1:0;\n ctx.drawImage(s,Math.round(P.x-cx)-3,Math.round(P.y-cy)-3+bob);\n}\n"}}},{"t":1365070,"name":"aiToolEdit","data":{"toolId":27,"edit":{"file":"{{PROJECT}}/dave-jungle-temple.html","oldText":"/* ==INPUT== */\n","newText":"/* ==INPUT== */\nconst keys = {left:false,right:false,jump:false};\nconst KEYMAP = {ArrowLeft:'left',KeyA:'left',ArrowRight:'right',KeyD:'right',ArrowUp:'jump',KeyW:'jump',Space:'jump'};\nfunction onAnyInput(){ if(typeof takeControl==='function') takeControl(); }\naddEventListener('keydown',e=>{ if(e.ctrlKey||e.metaKey||e.altKey) return; const k=KEYMAP[e.code];\n if(k){ keys[k]=true; e.preventDefault(); }\n if(e.code==='KeyM' && typeof toggleMute==='function'){ toggleMute(); return; }\n if((e.code==='Enter'||e.code==='KeyR') && typeof restartIfEnded==='function' && restartIfEnded()) return;\n if(e.key!=='Tab' && e.key!=='Shift') onAnyInput(); });\naddEventListener('keyup',e=>{ const k=KEYMAP[e.code]; if(k){ keys[k]=false; e.preventDefault(); } });\naddEventListener('blur',()=>{ keys.left=keys.right=keys.jump=false; });\n\n/* ==PLAYER== */\nconst RUN=95, ACC=900, GRAV=950, JUMP=310, MAXFALL=330;\nconst P = {x:0,y:0,w:8,h:14,vx:0,vy:0,dir:1,ground:false,coyote:0,jbuf:0,prevJump:false,anim:0,dead:0,inv:0};\nfunction placePlayer(x,y){ P.x=x; P.y=y; P.vx=P.vy=0; P.dir=1; P.dead=0; P.ground=false; P.prevJump=false; P.jbuf=0; }\nfunction movePlayer(dt,inp){\n const want=(inp.right?1:0)-(inp.left?1:0);\n if(want){ P.vx+=want*ACC*dt; P.dir=want; } else { const d=Math.sign(P.vx); P.vx-=d*Math.min(Math.abs(P.vx),ACC*dt); }\n P.vx=clamp(P.vx,-RUN,RUN);\n P.coyote = P.ground ? .09 : P.coyote-dt;\n if(inp.jump && !P.prevJump) P.jbuf=.12; P.prevJump=inp.jump; P.jbuf-=dt;\n if(P.jbuf>0 && P.coyote>0){ P.vy=-JUMP; P.jbuf=0; P.coyote=0; P.ground=false; if(typeof onJump==='function') onJump(); }\n if(!inp.jump && P.vy<-110) P.vy=-110; // release early = short hop\n P.vy=Math.min(P.vy+GRAV*dt,MAXFALL);\n // horizontal\n P.x+=P.vx*dt;\n { const top=Math.floor(P.y/T), bot=Math.floor((P.y+P.h-.01)/T);\n if(P.vx>0){ const tx=Math.floor((P.x+P.w)/T); for(let ty=top;ty<=bot;ty++) if(isSolid(tileAt(tx,ty))){ P.x=tx*T-P.w-.001; P.vx=0; break; } }\n else if(P.vx<0){ const tx=Math.floor(P.x/T); for(let ty=top;ty<=bot;ty++) if(isSolid(tileAt(tx,ty))){ P.x=(tx+1)*T; P.vx=0; break; } } }\n // vertical (bridges are one-way)\n const prevBottom=P.y+P.h, wasGround=P.ground; P.y+=P.vy*dt; P.ground=false;\n { const l=Math.floor(P.x/T), r=Math.floor((P.x+P.w-.01)/T);\n if(P.vy>=0){ const ty=Math.floor((P.y+P.h)/T);\n for(let tx=l;tx<=r;tx++){ const ch=tileAt(tx,ty); if(isSolid(ch)||(ch==='-'&&prevBottom<=ty*T+.5)){ P.y=ty*T-P.h; if(!wasGround&&P.vy>150&&typeof onLand==='function') onLand(); P.vy=0; P.ground=true; break; } } }\n else { const ty=Math.floor(P.y/T); for(let tx=l;tx<=r;tx++) if(isSolid(tileAt(tx,ty))){ P.y=(ty+1)*T; P.vy=0; break; } } }\n P.anim += Math.abs(P.vx)*dt*.11;\n}\nfunction followCamera(dt,snap){\n const tx=clamp(P.x+P.w/2-W/2+P.dir*18,0,WORLD_W-W), ty=clamp(P.y-92,0,WORLD_H-H), k=snap?1:Math.min(1,dt*4.5);\n G.camX+=(tx-G.camX)*k; G.camY+=(ty-G.camY)*Math.min(1,k*.7+ (snap?1:0));\n}\nfunction drawPlayer(cx,cy,t){\n if(P.inv>0 && ((t*16)|0)%2) return;\n const d=P.dir>0?1:0; let s;\n if(!P.ground) s=SP.dave.jump[d]; else if(Math.abs(P.vx)>12) s=SP.dave.run[(P.anim|0)%4][d]; else s=SP.dave.idle[d];\n const bob=(P.ground&&Math.abs(P.vx)<=12&&((t*2.2)|0)%2)?1:0;\n ctx.drawImage(s,Math.round(P.x-cx)-3,Math.round(P.y-cy)-3+bob);\n}\n","replaceAll":false,"isLivePreviewRelated":true}}},{"t":1365071,"name":"aiToolResult","data":{"toolId":27,"isError":false,"preview":"The file {{PROJECT}}/dave-jungle-temple.html has been updated s"}},{"t":1398731,"name":"aiProgress","data":{"toolName":"Edit","toolId":28,"phase":"tool_use"}},{"t":1398839,"name":"aiToolStream","data":{"toolId":28,"toolName":"Edit","append":"{\"file_path\": \""}},{"t":1399107,"name":"aiToolStream","data":{"toolId":28,"toolName":"Edit","append":"{{PROJECT}}/dave-jungle-"}},{"t":1399404,"name":"aiToolStream","data":{"toolId":28,"toolName":"Edit","append":"temple.html\", \"old_string\": \"/* ==ENTITIES== *"}},{"t":1399849,"name":"aiToolStream","data":{"toolId":28,"toolName":"Edit","append":"/\", \"new_string\": \"/* ==ENTITIES== */\\nlet gems=[], enemies=[], keyItem=null"}},{"t":1400154,"name":"aiToolStream","data":{"toolId":28,"toolName":"Edit","append":", door=null;\\nlet playSfx=function(){}, showToast=function(){}, syncHud=function(){"}},{"t":1400468,"name":"aiToolStream","data":{"toolId":28,"toolName":"Edit","append":"}, endGame=function(kind){ G.mode=kind; };\\nconst CHECKPOINTS"}},{"t":1400777,"name":"aiToolStream","data":{"toolId":28,"toolName":"Edit","append":"=[26,47,74];\\n// tiny particle pool (hard cap ke"}},{"t":1401031,"name":"aiToolStream","data":{"toolId":28,"toolName":"Edit","append":"eps it cheap)\\nconst fx=[]; const FX_MAX=48;\\nfunction pu"}},{"t":1401338,"name":"aiToolStream","data":{"toolId":28,"toolName":"Edit","append":"ff(x,y,n,col,spd,up){ for(let"}},{"t":1401651,"name":"aiToolStream","data":{"toolId":28,"toolName":"Edit","append":" i=0;i=0;i--){ const p=fx[i]; p.life-=dt; if(p.life<=0){ fx[i]=f"}},{"t":1403532,"name":"aiToolStream","data":{"toolId":28,"toolName":"Edit","append":"x[fx.length-1]; fx.pop(); continue; } p.vy+=p.g*dt; p.x+=p"}},{"t":1403846,"name":"aiToolStream","data":{"toolId":28,"toolName":"Edit","append":".vx*dt; p.y+=p.vy*dt; } }\\nfunction drawFx(cx,"}},{"t":1404096,"name":"aiToolStream","data":{"toolId":28,"toolName":"Edit","append":"cy){ for(const p of fx){ ctx.fillStyle=p.c; const s=p.life>.25"}},{"t":1404420,"name":"aiToolStream","data":{"toolId":28,"toolName":"Edit","append":"?2:1; ctx.fillRect((p.x-cx)|0,(p.y-cy)|0,s,s); }"}},{"t":1404723,"name":"aiToolStream","data":{"toolId":28,"toolName":"Edit","append":" }\\nfunction onJump(){ puff(P.x+4,P.y+P.h,4,C.ivoD,30"}},{"t":1405031,"name":"aiToolStream","data":{"toolId":28,"toolName":"Edit","append":",10); playSfx('jump'); }\\nfunction onLand(){ puff(P."}},{"t":1405281,"name":"aiToolStream","data":{"toolId":28,"toolName":"Edit","append":"x+4,P.y+P.h,5,C.ivoD,36,14"}},{"t":1405532,"name":"aiToolStream","data":{"toolId":28,"toolName":"Edit","append":"); }\\n\\nfunction resetLevel(){\\n gems=SPAWN.gems.map(g=>({x"}},{"t":1405783,"name":"aiToolStream","data":{"toolId":28,"toolName":"Edit","append":":g.x,y:g.y,k:g.k,got:false,ph:Math.random()*6}));\\n enemies=S"}},{"t":1406093,"name":"aiToolStream","data":{"toolId":28,"toolName":"Edit","append":"PAWN.enemies.map(e=>({t:e.t,x:e.x,y:e.t==='snake'?e."}},{"t":1406408,"name":"aiToolStream","data":{"toolId":28,"toolName":"Edit","append":"y-8:e.y,y0:e.y,x0:e.x0,x1:e.x1,d"}},{"t":1406659,"name":"aiToolStream","data":{"toolId":28,"toolName":"Edit","append":"ir:1,dead:0,ph:Math.random()*6,w:e."}},{"t":1407107,"name":"aiToolStream","data":{"toolId":28,"toolName":"Edit","append":"t==='snake'?14:12,h:e.t==='snake'?8:7}));\\n keyItem={x:SPAWN.key.x,y:SPAWN.key.y,got:false}; door={x:SPAWN"}},{"t":1407406,"name":"aiToolStream","data":{"toolId":28,"toolName":"Edit","append":".door.x,y:SPAWN.door.y,open:false};\\n G.gems=0; G."}},{"t":1407665,"name":"aiToolStream","data":{"toolId":28,"toolName":"Edit","append":"total=gems.length; G.hasKey=false; G.lives=3; G.winT=0; G.check"}},{"t":1407967,"name":"aiToolStream","data":{"toolId":28,"toolName":"Edit","append":"=-1; G.doorHint=0;\\n placeP"}},{"t":1408217,"name":"aiToolStream","data":{"toolId":28,"toolName":"Edit","append":"layer(SPAWN.start.x,SPAWN.start.y); P.inv=0; f"}},{"t":1408469,"name":"aiToolStream","data":{"toolId":28,"toolName":"Edit","append":"x.length=0; followCamera(0,true); syncHud();\\n}\\nconst hit=("}},{"t":1408727,"name":"aiToolStream","data":{"toolId":28,"toolName":"Edit","append":"ax,ay,aw,ah,bx,by,bw,bh)=>axbx&&ayby;\\nfunction killPlayer(spl"}},{"t":1409282,"name":"aiToolStream","data":{"toolId":28,"toolName":"Edit","append":"ash){\\n if(P.dead>0||P.inv>0||G.winT>0)"}},{"t":1409534,"name":"aiToolStream","data":{"toolId":28,"toolName":"Edit","append":" return;\\n P.dead=1.2; P.vy=splash?-90"}},{"t":1409843,"name":"aiToolStream","data":{"toolId":28,"toolName":"Edit","append":":-250; P.vx=0; playSfx('hurt');\\n puff(P.x+4"}},{"t":1410156,"name":"aiToolStream","data":{"toolId":28,"toolName":"Edit","append":",P.y+8,10,splash?C.waterL:C.pap,70"}},{"t":1410408,"name":"aiToolStream","data":{"toolId":28,"toolName":"Edit","append":",40);\\n if(G.mode==='play'){ G.lives--;"}},{"t":1410661,"name":"aiToolStream","data":{"toolId":28,"toolName":"Edit","append":" syncHud(); }\\n}\\nfunction afterDeath(){\\n if(G.mode==='play' && G.lives<=0){"}},{"t":1410970,"name":"aiToolStream","data":{"toolId":28,"toolName":"Edit","append":" endGame('over'); return; }\\n const c=G.check; placePlayer(c"}},{"t":1411224,"name":"aiToolStream","data":{"toolId":28,"toolName":"Edit","append":"<0?SPAWN.start.x:CHECKPOINTS[c]*T, 9*T+"}},{"t":1411483,"name":"aiToolStream","data":{"toolId":28,"toolName":"Edit","append":"2); P.inv=1.6;\\n}\\nfunction updateEnemies(dt,alive){\\n for(const"}},{"t":1411784,"name":"aiToolStream","data":{"toolId":28,"toolName":"Edit","append":" e of enemies){\\n if(e.dead>0){ e.dead-=dt; if(e.dead<=0) e."}},{"t":1412096,"name":"aiToolStream","data":{"toolId":28,"toolName":"Edit","append":"gone=true; continue; } if(e.gone) continue;\\n const sp="}},{"t":1412348,"name":"aiToolStream","data":{"toolId":28,"toolName":"Edit","append":"e.t==='snake'?26:42; e.x+=e.dir*sp*dt; if(e.x"}},{"t":1412907,"name":"aiToolStream","data":{"toolId":28,"toolName":"Edit","append":"e.x1){ e.x=e.x1-e.w; e.dir=-1; }\\n if(e.t==='bat')"}},{"t":1413219,"name":"aiToolStream","data":{"toolId":28,"toolName":"Edit","append":" e.y=e.y0+Math.sin(G.time*2.3+e.ph)*11"}},{"t":1413469,"name":"aiToolStream","data":{"toolId":28,"toolName":"Edit","append":";\\n if(alive && hit(P.x,P.y,P.w,P.h,e.x"}},{"t":1413728,"name":"aiToolStream","data":{"toolId":28,"toolName":"Edit","append":"+1,e.y+1,e.w-2,e.h-1)){\\n if(P."}},{"t":1414033,"name":"aiToolStream","data":{"toolId":28,"toolName":"Edit","append":"vy>40 && P.y+P.h-e.y<9){ e.dead="}},{"t":1414283,"name":"aiToolStream","data":{"toolId":28,"toolName":"Edit","append":".35; P.vy=-230; P.in"}},{"t":1414581,"name":"aiToolStream","data":{"toolId":28,"toolName":"Edit","append":"v=Math.max(P.inv,.15); puff(e.x+e"}},{"t":1414851,"name":"aiToolStream","data":{"toolId":28,"toolName":"Edit","append":".w/2,e.y+4,9,C.papL"}},{"t":1415164,"name":"aiToolStream","data":{"toolId":28,"toolName":"Edit","append":",60,20); playSfx('stomp'); }\\n else killPlayer(false);"}},{"t":1415470,"name":"aiToolStream","data":{"toolId":28,"toolName":"Edit","append":"\\n }\\n }\\n}\\nfunction checkWorld(){\\n // hazards\\n const l=Math.floor((P.x"}},{"t":1417048,"name":"aiToolStream","data":{"toolId":28,"toolName":"Edit","append":"+1)/T), r=Math.floor((P.x+P.w-1)/T), by=P.y+P.h, ty=Math.floor((by-1)/T);\\n for(let tx=l;tx<=r;tx++){ const ch=tileAt(tx,ty); if(ch==='^'&&by>ty*T+7){ killPlayer(false); return; } if(ch==='~'&&by>ty*T+10){ killPlayer(true); return; } }\\n if(P.y>WORLD_H+24"}},{"t":1417345,"name":"aiToolStream","data":{"toolId":28,"toolName":"Edit","append":"){ killPlayer(true); return; }\\n // checkpoints\\n if"}},{"t":1417596,"name":"aiToolStream","data":{"toolId":28,"toolName":"Edit","append":"(P.ground) for(let i=CHECKPOINTS.length-1;i"}},{"t":1417860,"name":"aiToolStream","data":{"toolId":28,"toolName":"Edit","append":">G.check;i--) if(P.x>CHECKPOINTS[i]*T){ G.check=i; break; }"}},{"t":1418159,"name":"aiToolStream","data":{"toolId":28,"toolName":"Edit","append":"\\n // pickups\\n for(const g of gems){ if(!g.got && hit(P"}},{"t":1418410,"name":"aiToolStream","data":{"toolId":28,"toolName":"Edit","append":".x,P.y,P.w,P.h,g.x-1,g.y"}},{"t":1418661,"name":"aiToolStream","data":{"toolId":28,"toolName":"Edit","append":"-1,10,10)){ g.got=true; G.gems++; puff(g.x+4,g.y+4,6,g."}},{"t":1418920,"name":"aiToolStream","data":{"toolId":28,"toolName":"Edit","append":"k?C.ivo:C.papL,55,10); playSfx('gem'); syncHud(); } }\\n if("}},{"t":1419219,"name":"aiToolStream","data":{"toolId":28,"toolName":"Edit","append":"!keyItem.got && hit(P.x,P.y,P.w,P.h,keyItem."}},{"t":1419469,"name":"aiToolStream","data":{"toolId":28,"toolName":"Edit","append":"x,keyItem.y-2,12,9)){ keyItem."}},{"t":1419734,"name":"aiToolStream","data":{"toolId":28,"toolName":"Edit","append":"got=true; G.hasKey=true; puff(keyItem.x+6,keyItem.y+2,12"}},{"t":1420033,"name":"aiToolStream","data":{"toolId":28,"toolName":"Edit","append":",C.ivo,70,10); playSfx('key'); showToast('Key found"}},{"t":1420284,"name":"aiToolStream","data":{"toolId":28,"toolName":"Edit","append":" — the exit is unlocked!'); syncHud(); }\\n /"}},{"t":1420597,"name":"aiToolStream","data":{"toolId":28,"toolName":"Edit","append":"/ exit door\\n G.doorHint-=1/60;\\n if(hit(P.x,P.y,P.w,"}},{"t":1420909,"name":"aiToolStream","data":{"toolId":28,"toolName":"Edit","append":"P.h,door.x+4,door.y+8,8,24)){\\n if(G."}},{"t":1421161,"name":"aiToolStream","data":{"toolId":28,"toolName":"Edit","append":"hasKey){ if(!door.open){ door.open=true; G.win"}},{"t":1421414,"name":"aiToolStream","data":{"toolId":28,"toolName":"Edit","append":"T=.9; P.vx=0; puff(door.x+8,door.y+16,14,C.papL,60"}},{"t":1421719,"name":"aiToolStream","data":{"toolId":28,"toolName":"Edit","append":",20); playSfx('win'); } }\\n else if(G.doorHint<=0){ G"}},{"t":1421974,"name":"aiToolStream","data":{"toolId":28,"toolName":"Edit","append":".doorHint=3; showToast('Locked! Find the temple key first.'); playSfx('"}},{"t":1422282,"name":"aiToolStream","data":{"toolId":28,"toolName":"Edit","append":"locked'); }\\n }\\n}\\nfunction stepGame(dt){\\n if(G"}},{"t":1422539,"name":"aiToolStream","data":{"toolId":28,"toolName":"Edit","append":".mode==='win'||G.mode==='over'){ updateEnemies(dt,false); update"}},{"t":1423033,"name":"aiToolStream","data":{"toolId":28,"toolName":"Edit","append":"Fx(dt); return; }\\n const inp=(G.mode==='attract'&&typeof botInput==='function')?botInput(dt):keys;\\n if(G.winT>0){ G"}},{"t":1423290,"name":"aiToolStream","data":{"toolId":28,"toolName":"Edit","append":".winT-=dt; if(G.winT<=0) endGame('win'); }\\n else if(P.dead>0){ P"}},{"t":1423598,"name":"aiToolStream","data":{"toolId":28,"toolName":"Edit","append":".vy+=GRAV*dt; P.y+=P.vy*dt; P.dead-=dt; if(P"}},{"t":1423907,"name":"aiToolStream","data":{"toolId":28,"toolName":"Edit","append":".dead<=0) afterDeath(); }\\n else { movePlayer(dt,inp); chec"}},{"t":1424176,"name":"aiToolStream","data":{"toolId":28,"toolName":"Edit","append":"kWorld(); }\\n updateEnemies(dt, P.dead<=0 "}},{"t":1424722,"name":"aiToolStream","data":{"toolId":28,"toolName":"Edit","append":"&& G.winT<=0); updateFx(dt); followCamera(dt);\\n if(P.inv>0) P.inv-=dt;\\n}\\nfunction drawActors(cx,"}},{"t":1424972,"name":"aiToolStream","data":{"toolId":28,"toolName":"Edit","append":"cy,t){\\n ctx.drawImage(SP.door[door.open?1:0],door.x"}},{"t":1425290,"name":"aiToolStream","data":{"toolId":28,"toolName":"Edit","append":"-cx,door.y-cy);\\n for(const g of gems){ if(g.got) continue; const sx=g.x-c"}},{"t":1425546,"name":"aiToolStream","data":{"toolId":28,"toolName":"Edit","append":"x; if(sx<-12||sx>W+4) continue; const by=Math.round(Math.sin(t"}},{"t":1425845,"name":"aiToolStream","data":{"toolId":28,"toolName":"Edit","append":"*3+g.ph)*1.5);\\n ctx.drawImage(SP"}},{"t":1426099,"name":"aiToolStream","data":{"toolId":28,"toolName":"Edit","append":".gem[g.k],(sx-1)|0,(g.y-cy-1+by)|0);"}},{"t":1426349,"name":"aiToolStream","data":{"toolId":28,"toolName":"Edit","append":" if(((t*1.3+g.ph)%2.2"}},{"t":1426666,"name":"aiToolStream","data":{"toolId":28,"toolName":"Edit","append":")<.18) ctx.drawImage(SP.spark,(sx+3"}},{"t":1426977,"name":"aiToolStream","data":{"toolId":28,"toolName":"Edit","append":")|0,(g.y-cy-3+by)|0); }\\n if(!keyItem.got){ const by="}},{"t":1427286,"name":"aiToolStream","data":{"toolId":28,"toolName":"Edit","append":"Math.round(Math.sin(t*2.6)*2); ctx.drawImage(SP.key,("}},{"t":1427596,"name":"aiToolStream","data":{"toolId":28,"toolName":"Edit","append":"keyItem.x-cx-1)|0,(keyItem.y-cy-1+by)|0"}},{"t":1427850,"name":"aiToolStream","data":{"toolId":28,"toolName":"Edit","append":"); if((t%1.6)<.2) ctx.drawIm"}},{"t":1428160,"name":"aiToolStream","data":{"toolId":28,"toolName":"Edit","append":"age(SP.spark,(keyItem.x-cx+8)|0,(keyItem.y-cy-4+by)|"}},{"t":1428475,"name":"aiToolStream","data":{"toolId":28,"toolName":"Edit","append":"0); }\\n for(const e of enemies){ if(e.gone) continue; const sx=e.x"}},{"t":1428725,"name":"aiToolStream","data":{"toolId":28,"toolName":"Edit","append":"-cx; if(sx<-24||sx>W+8) continue;\\n if(e.dead>0 "}},{"t":1429033,"name":"aiToolStream","data":{"toolId":28,"toolName":"Edit","append":"&& ((t*20)|0)%2) continue;\\n if(e."}},{"t":1429290,"name":"aiToolStream","data":{"toolId":28,"toolName":"Edit","append":"t==='snake') ctx.drawImage(SP.snake[(t*6|0)%2][e.dir>0?"}},{"t":1429597,"name":"aiToolStream","data":{"toolId":28,"toolName":"Edit","append":"1:0],(sx-2)|0,(e.y-cy-3+(e.dead>0?"}},{"t":1429910,"name":"aiToolStream","data":{"toolId":28,"toolName":"Edit","append":"3:0))|0);\\n else ctx.drawImage(SP.bat[(t*9"}},{"t":1430221,"name":"aiToolStream","data":{"toolId":28,"toolName":"Edit","append":"|0)%2],(sx-3)|0,(e.y-cy-2)|0); }\\n if(G.winT<=0"}},{"t":1430534,"name":"aiToolStream","data":{"toolId":28,"toolName":"Edit","append":" || G.winT>.55) drawPlayer(cx,cy,t);"}},{"t":1430792,"name":"aiToolStream","data":{"toolId":28,"toolName":"Edit","append":"\\n}\\nG.mode='play'; resetLevel();\"}"}},{"t":1431044,"name":"aiToolStream","data":{"toolId":28,"toolName":"Edit","append":""}},{"t":1431046,"name":"aiToolInfo","data":{"toolName":"Edit","toolId":28,"toolInput":{"file_path":"{{PROJECT}}/dave-jungle-temple.html","old_string":"/* ==ENTITIES== */","new_string":"/* ==ENTITIES== */\nlet gems=[], enemies=[], keyItem=null, door=null;\nlet playSfx=function(){}, showToast=function(){}, syncHud=function(){}, endGame=function(kind){ G.mode=kind; };\nconst CHECKPOINTS=[26,47,74];\n// tiny particle pool (hard cap keeps it cheap)\nconst fx=[]; const FX_MAX=48;\nfunction puff(x,y,n,col,spd,up){ for(let i=0;i=0;i--){ const p=fx[i]; p.life-=dt; if(p.life<=0){ fx[i]=fx[fx.length-1]; fx.pop(); continue; } p.vy+=p.g*dt; p.x+=p.vx*dt; p.y+=p.vy*dt; } }\nfunction drawFx(cx,cy){ for(const p of fx){ ctx.fillStyle=p.c; const s=p.life>.25?2:1; ctx.fillRect((p.x-cx)|0,(p.y-cy)|0,s,s); } }\nfunction onJump(){ puff(P.x+4,P.y+P.h,4,C.ivoD,30,10); playSfx('jump'); }\nfunction onLand(){ puff(P.x+4,P.y+P.h,5,C.ivoD,36,14); }\n\nfunction resetLevel(){\n gems=SPAWN.gems.map(g=>({x:g.x,y:g.y,k:g.k,got:false,ph:Math.random()*6}));\n enemies=SPAWN.enemies.map(e=>({t:e.t,x:e.x,y:e.t==='snake'?e.y-8:e.y,y0:e.y,x0:e.x0,x1:e.x1,dir:1,dead:0,ph:Math.random()*6,w:e.t==='snake'?14:12,h:e.t==='snake'?8:7}));\n keyItem={x:SPAWN.key.x,y:SPAWN.key.y,got:false}; door={x:SPAWN.door.x,y:SPAWN.door.y,open:false};\n G.gems=0; G.total=gems.length; G.hasKey=false; G.lives=3; G.winT=0; G.check=-1; G.doorHint=0;\n placePlayer(SPAWN.start.x,SPAWN.start.y); P.inv=0; fx.length=0; followCamera(0,true); syncHud();\n}\nconst hit=(ax,ay,aw,ah,bx,by,bw,bh)=>axbx&&ayby;\nfunction killPlayer(splash){\n if(P.dead>0||P.inv>0||G.winT>0) return;\n P.dead=1.2; P.vy=splash?-90:-250; P.vx=0; playSfx('hurt');\n puff(P.x+4,P.y+8,10,splash?C.waterL:C.pap,70,40);\n if(G.mode==='play'){ G.lives--; syncHud(); }\n}\nfunction afterDeath(){\n if(G.mode==='play' && G.lives<=0){ endGame('over'); return; }\n const c=G.check; placePlayer(c<0?SPAWN.start.x:CHECKPOINTS[c]*T, 9*T+2); P.inv=1.6;\n}\nfunction updateEnemies(dt,alive){\n for(const e of enemies){\n if(e.dead>0){ e.dead-=dt; if(e.dead<=0) e.gone=true; continue; } if(e.gone) continue;\n const sp=e.t==='snake'?26:42; e.x+=e.dir*sp*dt; if(e.xe.x1){ e.x=e.x1-e.w; e.dir=-1; }\n if(e.t==='bat') e.y=e.y0+Math.sin(G.time*2.3+e.ph)*11;\n if(alive && hit(P.x,P.y,P.w,P.h,e.x+1,e.y+1,e.w-2,e.h-1)){\n if(P.vy>40 && P.y+P.h-e.y<9){ e.dead=.35; P.vy=-230; P.inv=Math.max(P.inv,.15); puff(e.x+e.w/2,e.y+4,9,C.papL,60,20); playSfx('stomp'); }\n else killPlayer(false);\n }\n }\n}\nfunction checkWorld(){\n // hazards\n const l=Math.floor((P.x+1)/T), r=Math.floor((P.x+P.w-1)/T), by=P.y+P.h, ty=Math.floor((by-1)/T);\n for(let tx=l;tx<=r;tx++){ const ch=tileAt(tx,ty); if(ch==='^'&&by>ty*T+7){ killPlayer(false); return; } if(ch==='~'&&by>ty*T+10){ killPlayer(true); return; } }\n if(P.y>WORLD_H+24){ killPlayer(true); return; }\n // checkpoints\n if(P.ground) for(let i=CHECKPOINTS.length-1;i>G.check;i--) if(P.x>CHECKPOINTS[i]*T){ G.check=i; break; }\n // pickups\n for(const g of gems){ if(!g.got && hit(P.x,P.y,P.w,P.h,g.x-1,g.y-1,10,10)){ g.got=true; G.gems++; puff(g.x+4,g.y+4,6,g.k?C.ivo:C.papL,55,10); playSfx('gem'); syncHud(); } }\n if(!keyItem.got && hit(P.x,P.y,P.w,P.h,keyItem.x,keyItem.y-2,12,9)){ keyItem.got=true; G.hasKey=true; puff(keyItem.x+6,keyItem.y+2,12,C.ivo,70,10); playSfx('key'); showToast('Key found — the exit is unlocked!'); syncHud(); }\n // exit door\n G.doorHint-=1/60;\n if(hit(P.x,P.y,P.w,P.h,door.x+4,door.y+8,8,24)){\n if(G.hasKey){ if(!door.open){ door.open=true; G.winT=.9; P.vx=0; puff(door.x+8,door.y+16,14,C.papL,60,20); playSfx('win'); } }\n else if(G.doorHint<=0){ G.doorHint=3; showToast('Locked! Find the temple key first.'); playSfx('locked'); }\n }\n}\nfunction stepGame(dt){\n if(G.mode==='win'||G.mode==='over'){ updateEnemies(dt,false); updateFx(dt); return; }\n const inp=(G.mode==='attract'&&typeof botInput==='function')?botInput(dt):keys;\n if(G.winT>0){ G.winT-=dt; if(G.winT<=0) endGame('win'); }\n else if(P.dead>0){ P.vy+=GRAV*dt; P.y+=P.vy*dt; P.dead-=dt; if(P.dead<=0) afterDeath(); }\n else { movePlayer(dt,inp); checkWorld(); }\n updateEnemies(dt, P.dead<=0 && G.winT<=0); updateFx(dt); followCamera(dt);\n if(P.inv>0) P.inv-=dt;\n}\nfunction drawActors(cx,cy,t){\n ctx.drawImage(SP.door[door.open?1:0],door.x-cx,door.y-cy);\n for(const g of gems){ if(g.got) continue; const sx=g.x-cx; if(sx<-12||sx>W+4) continue; const by=Math.round(Math.sin(t*3+g.ph)*1.5);\n ctx.drawImage(SP.gem[g.k],(sx-1)|0,(g.y-cy-1+by)|0); if(((t*1.3+g.ph)%2.2)<.18) ctx.drawImage(SP.spark,(sx+3)|0,(g.y-cy-3+by)|0); }\n if(!keyItem.got){ const by=Math.round(Math.sin(t*2.6)*2); ctx.drawImage(SP.key,(keyItem.x-cx-1)|0,(keyItem.y-cy-1+by)|0); if((t%1.6)<.2) ctx.drawImage(SP.spark,(keyItem.x-cx+8)|0,(keyItem.y-cy-4+by)|0); }\n for(const e of enemies){ if(e.gone) continue; const sx=e.x-cx; if(sx<-24||sx>W+8) continue;\n if(e.dead>0 && ((t*20)|0)%2) continue;\n if(e.t==='snake') ctx.drawImage(SP.snake[(t*6|0)%2][e.dir>0?1:0],(sx-2)|0,(e.y-cy-3+(e.dead>0?3:0))|0);\n else ctx.drawImage(SP.bat[(t*9|0)%2],(sx-3)|0,(e.y-cy-2)|0); }\n if(G.winT<=0 || G.winT>.55) drawPlayer(cx,cy,t);\n}\nG.mode='play'; resetLevel();"}}},{"t":1431125,"name":"aiToolEdit","data":{"toolId":28,"edit":{"file":"{{PROJECT}}/dave-jungle-temple.html","oldText":"/* ==ENTITIES== */","newText":"/* ==ENTITIES== */\nlet gems=[], enemies=[], keyItem=null, door=null;\nlet playSfx=function(){}, showToast=function(){}, syncHud=function(){}, endGame=function(kind){ G.mode=kind; };\nconst CHECKPOINTS=[26,47,74];\n// tiny particle pool (hard cap keeps it cheap)\nconst fx=[]; const FX_MAX=48;\nfunction puff(x,y,n,col,spd,up){ for(let i=0;i=0;i--){ const p=fx[i]; p.life-=dt; if(p.life<=0){ fx[i]=fx[fx.length-1]; fx.pop(); continue; } p.vy+=p.g*dt; p.x+=p.vx*dt; p.y+=p.vy*dt; } }\nfunction drawFx(cx,cy){ for(const p of fx){ ctx.fillStyle=p.c; const s=p.life>.25?2:1; ctx.fillRect((p.x-cx)|0,(p.y-cy)|0,s,s); } }\nfunction onJump(){ puff(P.x+4,P.y+P.h,4,C.ivoD,30,10); playSfx('jump'); }\nfunction onLand(){ puff(P.x+4,P.y+P.h,5,C.ivoD,36,14); }\n\nfunction resetLevel(){\n gems=SPAWN.gems.map(g=>({x:g.x,y:g.y,k:g.k,got:false,ph:Math.random()*6}));\n enemies=SPAWN.enemies.map(e=>({t:e.t,x:e.x,y:e.t==='snake'?e.y-8:e.y,y0:e.y,x0:e.x0,x1:e.x1,dir:1,dead:0,ph:Math.random()*6,w:e.t==='snake'?14:12,h:e.t==='snake'?8:7}));\n keyItem={x:SPAWN.key.x,y:SPAWN.key.y,got:false}; door={x:SPAWN.door.x,y:SPAWN.door.y,open:false};\n G.gems=0; G.total=gems.length; G.hasKey=false; G.lives=3; G.winT=0; G.check=-1; G.doorHint=0;\n placePlayer(SPAWN.start.x,SPAWN.start.y); P.inv=0; fx.length=0; followCamera(0,true); syncHud();\n}\nconst hit=(ax,ay,aw,ah,bx,by,bw,bh)=>axbx&&ayby;\nfunction killPlayer(splash){\n if(P.dead>0||P.inv>0||G.winT>0) return;\n P.dead=1.2; P.vy=splash?-90:-250; P.vx=0; playSfx('hurt');\n puff(P.x+4,P.y+8,10,splash?C.waterL:C.pap,70,40);\n if(G.mode==='play'){ G.lives--; syncHud(); }\n}\nfunction afterDeath(){\n if(G.mode==='play' && G.lives<=0){ endGame('over'); return; }\n const c=G.check; placePlayer(c<0?SPAWN.start.x:CHECKPOINTS[c]*T, 9*T+2); P.inv=1.6;\n}\nfunction updateEnemies(dt,alive){\n for(const e of enemies){\n if(e.dead>0){ e.dead-=dt; if(e.dead<=0) e.gone=true; continue; } if(e.gone) continue;\n const sp=e.t==='snake'?26:42; e.x+=e.dir*sp*dt; if(e.xe.x1){ e.x=e.x1-e.w; e.dir=-1; }\n if(e.t==='bat') e.y=e.y0+Math.sin(G.time*2.3+e.ph)*11;\n if(alive && hit(P.x,P.y,P.w,P.h,e.x+1,e.y+1,e.w-2,e.h-1)){\n if(P.vy>40 && P.y+P.h-e.y<9){ e.dead=.35; P.vy=-230; P.inv=Math.max(P.inv,.15); puff(e.x+e.w/2,e.y+4,9,C.papL,60,20); playSfx('stomp'); }\n else killPlayer(false);\n }\n }\n}\nfunction checkWorld(){\n // hazards\n const l=Math.floor((P.x+1)/T), r=Math.floor((P.x+P.w-1)/T), by=P.y+P.h, ty=Math.floor((by-1)/T);\n for(let tx=l;tx<=r;tx++){ const ch=tileAt(tx,ty); if(ch==='^'&&by>ty*T+7){ killPlayer(false); return; } if(ch==='~'&&by>ty*T+10){ killPlayer(true); return; } }\n if(P.y>WORLD_H+24){ killPlayer(true); return; }\n // checkpoints\n if(P.ground) for(let i=CHECKPOINTS.length-1;i>G.check;i--) if(P.x>CHECKPOINTS[i]*T){ G.check=i; break; }\n // pickups\n for(const g of gems){ if(!g.got && hit(P.x,P.y,P.w,P.h,g.x-1,g.y-1,10,10)){ g.got=true; G.gems++; puff(g.x+4,g.y+4,6,g.k?C.ivo:C.papL,55,10); playSfx('gem'); syncHud(); } }\n if(!keyItem.got && hit(P.x,P.y,P.w,P.h,keyItem.x,keyItem.y-2,12,9)){ keyItem.got=true; G.hasKey=true; puff(keyItem.x+6,keyItem.y+2,12,C.ivo,70,10); playSfx('key'); showToast('Key found — the exit is unlocked!'); syncHud(); }\n // exit door\n G.doorHint-=1/60;\n if(hit(P.x,P.y,P.w,P.h,door.x+4,door.y+8,8,24)){\n if(G.hasKey){ if(!door.open){ door.open=true; G.winT=.9; P.vx=0; puff(door.x+8,door.y+16,14,C.papL,60,20); playSfx('win'); } }\n else if(G.doorHint<=0){ G.doorHint=3; showToast('Locked! Find the temple key first.'); playSfx('locked'); }\n }\n}\nfunction stepGame(dt){\n if(G.mode==='win'||G.mode==='over'){ updateEnemies(dt,false); updateFx(dt); return; }\n const inp=(G.mode==='attract'&&typeof botInput==='function')?botInput(dt):keys;\n if(G.winT>0){ G.winT-=dt; if(G.winT<=0) endGame('win'); }\n else if(P.dead>0){ P.vy+=GRAV*dt; P.y+=P.vy*dt; P.dead-=dt; if(P.dead<=0) afterDeath(); }\n else { movePlayer(dt,inp); checkWorld(); }\n updateEnemies(dt, P.dead<=0 && G.winT<=0); updateFx(dt); followCamera(dt);\n if(P.inv>0) P.inv-=dt;\n}\nfunction drawActors(cx,cy,t){\n ctx.drawImage(SP.door[door.open?1:0],door.x-cx,door.y-cy);\n for(const g of gems){ if(g.got) continue; const sx=g.x-cx; if(sx<-12||sx>W+4) continue; const by=Math.round(Math.sin(t*3+g.ph)*1.5);\n ctx.drawImage(SP.gem[g.k],(sx-1)|0,(g.y-cy-1+by)|0); if(((t*1.3+g.ph)%2.2)<.18) ctx.drawImage(SP.spark,(sx+3)|0,(g.y-cy-3+by)|0); }\n if(!keyItem.got){ const by=Math.round(Math.sin(t*2.6)*2); ctx.drawImage(SP.key,(keyItem.x-cx-1)|0,(keyItem.y-cy-1+by)|0); if((t%1.6)<.2) ctx.drawImage(SP.spark,(keyItem.x-cx+8)|0,(keyItem.y-cy-4+by)|0); }\n for(const e of enemies){ if(e.gone) continue; const sx=e.x-cx; if(sx<-24||sx>W+8) continue;\n if(e.dead>0 && ((t*20)|0)%2) continue;\n if(e.t==='snake') ctx.drawImage(SP.snake[(t*6|0)%2][e.dir>0?1:0],(sx-2)|0,(e.y-cy-3+(e.dead>0?3:0))|0);\n else ctx.drawImage(SP.bat[(t*9|0)%2],(sx-3)|0,(e.y-cy-2)|0); }\n if(G.winT<=0 || G.winT>.55) drawPlayer(cx,cy,t);\n}\nG.mode='play'; resetLevel();","replaceAll":false,"isLivePreviewRelated":true}}},{"t":1431129,"name":"aiToolResult","data":{"toolId":28,"isError":false,"preview":"The file {{PROJECT}}/dave-jungle-temple.html has been updated s"}},{"t":1434615,"name":"aiTextStream","data":{"text":"\n\nW"}},{"t":1434615,"name":"aiTextStream","data":{"text":"iring the player and entities together now — fixing initialization order, then a milestone screenshot."}},{"t":1434618,"name":"aiProgress","data":{"toolName":"Edit","toolId":29,"phase":"tool_use"}},{"t":1434737,"name":"aiToolStream","data":{"toolId":29,"toolName":"Edit","append":"{\"file_path\": \""}},{"t":1435214,"name":"aiToolStream","data":{"toolId":29,"toolName":"Edit","append":"{{PROJECT}}/dave-jungle-temple.html\", \"old_string\": \" if(G.win"}},{"t":1435483,"name":"aiToolStream","data":{"toolId":29,"toolName":"Edit","append":"T<=0 || G.winT>.55) drawPlayer(cx,cy,t);\\n}"}},{"t":1435867,"name":"aiToolStream","data":{"toolId":29,"toolName":"Edit","append":"\\nG.mode='play'; resetLevel();\", \"new_string\": \" if(G.winT<=0 || G.winT>.55)"}},{"t":1436176,"name":"aiToolStream","data":{"toolId":29,"toolName":"Edit","append":" drawPlayer(cx,cy,t);\\n}"}},{"t":1436512,"name":"aiToolStream","data":{"toolId":29,"toolName":"Edit","append":"\"}"}},{"t":1436525,"name":"aiToolInfo","data":{"toolName":"Edit","toolId":29,"toolInput":{"file_path":"{{PROJECT}}/dave-jungle-temple.html","old_string":" if(G.winT<=0 || G.winT>.55) drawPlayer(cx,cy,t);\n}\nG.mode='play'; resetLevel();","new_string":" if(G.winT<=0 || G.winT>.55) drawPlayer(cx,cy,t);\n}"}}},{"t":1436527,"name":"aiProgress","data":{"toolName":"Edit","toolId":30,"phase":"tool_use"}},{"t":1436580,"name":"aiToolEdit","data":{"toolId":29,"edit":{"file":"{{PROJECT}}/dave-jungle-temple.html","oldText":" if(G.winT<=0 || G.winT>.55) drawPlayer(cx,cy,t);\n}\nG.mode='play'; resetLevel();","newText":" if(G.winT<=0 || G.winT>.55) drawPlayer(cx,cy,t);\n}","replaceAll":false,"isLivePreviewRelated":true}}},{"t":1436580,"name":"aiToolResult","data":{"toolId":29,"isError":false,"preview":"The file {{PROJECT}}/dave-jungle-temple.html has been updated s"}},{"t":1436617,"name":"aiToolStream","data":{"toolId":30,"toolName":"Edit","append":"{\"file_path\": \""}},{"t":1436869,"name":"aiToolStream","data":{"toolId":30,"toolName":"Edit","append":"{{PROJECT}}"}},{"t":1437173,"name":"aiToolStream","data":{"toolId":30,"toolName":"Edit","append":"/dave-jungle-temple.html"}},{"t":1437430,"name":"aiToolStream","data":{"toolId":30,"toolName":"Edit","append":"\", \"old_string\": \"document.addEventListener('visibilitychange', () => document.hidden ? stop() : start());\\nstart();"}},{"t":1437863,"name":"aiToolStream","data":{"toolId":30,"toolName":"Edit","append":"\", \"new_string\": \"document.addEventListener('visibilitychange', () => document.hidden ? stop()"}},{"t":1438120,"name":"aiToolStream","data":{"toolId":30,"toolName":"Edit","append":" : start());\\n/* ==BOOT== */\\nG.mode='play'; resetLevel();\\nstart();"}},{"t":1438552,"name":"aiToolStream","data":{"toolId":30,"toolName":"Edit","append":"\"}"}},{"t":1438563,"name":"aiToolInfo","data":{"toolName":"Edit","toolId":30,"toolInput":{"file_path":"{{PROJECT}}/dave-jungle-temple.html","old_string":"document.addEventListener('visibilitychange', () => document.hidden ? stop() : start());\nstart();","new_string":"document.addEventListener('visibilitychange', () => document.hidden ? stop() : start());\n/* ==BOOT== */\nG.mode='play'; resetLevel();\nstart();"}}},{"t":1438565,"name":"aiProgress","data":{"toolName":"Edit","toolId":31,"phase":"tool_use"}},{"t":1438614,"name":"aiToolEdit","data":{"toolId":30,"edit":{"file":"{{PROJECT}}/dave-jungle-temple.html","oldText":"document.addEventListener('visibilitychange', () => document.hidden ? stop() : start());\nstart();","newText":"document.addEventListener('visibilitychange', () => document.hidden ? stop() : start());\n/* ==BOOT== */\nG.mode='play'; resetLevel();\nstart();","replaceAll":false,"isLivePreviewRelated":true}}},{"t":1438615,"name":"aiToolResult","data":{"toolId":30,"isError":false,"preview":"The file {{PROJECT}}/dave-jungle-temple.html has been updated s"}},{"t":1438679,"name":"aiToolStream","data":{"toolId":31,"toolName":"Edit","append":"{\"file_path\": \""}},{"t":1438988,"name":"aiToolStream","data":{"toolId":31,"toolName":"Edit","append":"{{PROJECT}}/dave-jungle-"}},{"t":1439251,"name":"aiToolStream","data":{"toolId":31,"toolName":"Edit","append":"temple.html\", \"old_string\": \"const y=6+Math.round(Math.s"}},{"t":1439554,"name":"aiToolStream","data":{"toolId":31,"toolName":"Edit","append":"in(x*.95+f*Math.PI)*1.5); px(g,C.papD,x,y,1,3);"}},{"t":1439989,"name":"aiToolStream","data":{"toolId":31,"toolName":"Edit","append":"\", \"new_string\": \"const y=5+Math.round(Math.sin(x*.95+f*Math.PI)"}},{"t":1440240,"name":"aiToolStream","data":{"toolId":31,"toolName":"Edit","append":"*1.5); px(g,C.papD,x,y,1,3);"}},{"t":1440616,"name":"aiToolStream","data":{"toolId":31,"toolName":"Edit","append":"\"}"}},{"t":1440628,"name":"aiToolInfo","data":{"toolName":"Edit","toolId":31,"toolInput":{"file_path":"{{PROJECT}}/dave-jungle-temple.html","old_string":"const y=6+Math.round(Math.sin(x*.95+f*Math.PI)*1.5); px(g,C.papD,x,y,1,3);","new_string":"const y=5+Math.round(Math.sin(x*.95+f*Math.PI)*1.5); px(g,C.papD,x,y,1,3);"}}},{"t":1440631,"name":"aiProgress","data":{"toolName":"Edit","toolId":32,"phase":"tool_use"}},{"t":1440683,"name":"aiToolEdit","data":{"toolId":31,"edit":{"file":"{{PROJECT}}/dave-jungle-temple.html","oldText":"const y=6+Math.round(Math.sin(x*.95+f*Math.PI)*1.5); px(g,C.papD,x,y,1,3);","newText":"const y=5+Math.round(Math.sin(x*.95+f*Math.PI)*1.5); px(g,C.papD,x,y,1,3);","replaceAll":false,"isLivePreviewRelated":true}}},{"t":1440684,"name":"aiToolResult","data":{"toolId":31,"isError":false,"preview":"The file {{PROJECT}}/dave-jungle-temple.html has been updated s"}},{"t":1440740,"name":"aiToolStream","data":{"toolId":32,"toolName":"Edit","append":"{\"file_path\": \""}},{"t":1441075,"name":"aiToolStream","data":{"toolId":32,"toolName":"Edit","append":"{{PROJECT}}/dave-jungle-"}},{"t":1441345,"name":"aiToolStream","data":{"toolId":32,"toolName":"Edit","append":"temple.html\", \"old_string\": \" const bob=(P.ground&&Math"}},{"t":1441616,"name":"aiToolStream","data":{"toolId":32,"toolName":"Edit","append":".abs(P.vx)<=12&&((t*2.2)|0)%2)?1:0;\\n ctx.draw"}},{"t":1441928,"name":"aiToolStream","data":{"toolId":32,"toolName":"Edit","append":"Image(s,Math.round(P.x-cx)-3,Math.round(P.y-cy)-3+bob);"}},{"t":1442601,"name":"aiToolStream","data":{"toolId":32,"toolName":"Edit","append":"\", \"new_string\": \" ctx.drawImage(s,Math.round(P.x-cx)-3,Math.round(P.y-cy)-3);\"}"}},{"t":1442857,"name":"aiToolStream","data":{"toolId":32,"toolName":"Edit","append":""}},{"t":1442858,"name":"aiToolInfo","data":{"toolName":"Edit","toolId":32,"toolInput":{"file_path":"{{PROJECT}}/dave-jungle-temple.html","old_string":" const bob=(P.ground&&Math.abs(P.vx)<=12&&((t*2.2)|0)%2)?1:0;\n ctx.drawImage(s,Math.round(P.x-cx)-3,Math.round(P.y-cy)-3+bob);","new_string":" ctx.drawImage(s,Math.round(P.x-cx)-3,Math.round(P.y-cy)-3);"}}},{"t":1442905,"name":"aiToolEdit","data":{"toolId":32,"edit":{"file":"{{PROJECT}}/dave-jungle-temple.html","oldText":" const bob=(P.ground&&Math.abs(P.vx)<=12&&((t*2.2)|0)%2)?1:0;\n ctx.drawImage(s,Math.round(P.x-cx)-3,Math.round(P.y-cy)-3+bob);","newText":" ctx.drawImage(s,Math.round(P.x-cx)-3,Math.round(P.y-cy)-3);","replaceAll":false,"isLivePreviewRelated":true}}},{"t":1442907,"name":"aiToolResult","data":{"toolId":32,"isError":false,"preview":"The file {{PROJECT}}/dave-jungle-temple.html has been updated s"}},{"t":1444103,"name":"aiProgress","data":{"toolName":"TaskUpdate","toolId":33,"phase":"tool_use"}},{"t":1444702,"name":"aiToolStream","data":{"toolId":33,"toolName":"TaskUpdate","append":"{\"taskId\": \"3\", \"status\": \"completed\"}"}},{"t":1444704,"name":"aiToolInfo","data":{"toolName":"TaskUpdate","toolId":33,"toolInput":{"taskId":"3","status":"completed"}}},{"t":1444704,"name":"aiProgress","data":{"toolName":"TaskUpdate","toolId":34,"phase":"tool_use"}},{"t":1444708,"name":"aiToolResult","data":{"toolId":33,"isError":false,"preview":"Updated task #3 status"}},{"t":1444781,"name":"aiToolStream","data":{"toolId":34,"toolName":"TaskUpdate","append":"{\"taskId\": \"4"}},{"t":1445348,"name":"aiToolStream","data":{"toolId":34,"toolName":"TaskUpdate","append":"\", \"status\": \"in_progress\"}"}},{"t":1445351,"name":"aiToolInfo","data":{"toolName":"TaskUpdate","toolId":34,"toolInput":{"taskId":"4","status":"in_progress"}}},{"t":1445354,"name":"aiProgress","data":{"toolName":"mcp__phoenix-editor__takeScreenshot","toolId":35,"phase":"tool_use"}},{"t":1445355,"name":"aiToolResult","data":{"toolId":34,"isError":false,"preview":"Updated task #4 status"}},{"t":1445407,"name":"aiToolStream","data":{"toolId":35,"toolName":"mcp__phoenix-editor__takeScreenshot","append":"{\"selector\": \"#panel-live-preview-frame"}},{"t":1445720,"name":"aiToolStream","data":{"toolId":35,"toolName":"mcp__phoenix-editor__takeScreenshot","append":"\", \"purePreview\": true, \"reload\": true"}},{"t":1446002,"name":"aiToolStream","data":{"toolId":35,"toolName":"mcp__phoenix-editor__takeScreenshot","append":"}"}},{"t":1446004,"name":"aiToolInfo","data":{"toolName":"mcp__phoenix-editor__takeScreenshot","toolId":35,"toolInput":{"selector":"#panel-live-preview-frame","purePreview":true,"reload":true}}},{"t":1446842,"name":"aiToolResult","data":{"toolId":35,"isError":false,"preview":""}},{"t":1528650,"name":"aiProgress","data":{"toolName":"TaskUpdate","toolId":36,"phase":"tool_use"}},{"t":1528752,"name":"aiToolStream","data":{"toolId":36,"toolName":"TaskUpdate","append":"{\"taskId\": \"4\", \"status\": \"completed"}},{"t":1529186,"name":"aiToolStream","data":{"toolId":36,"toolName":"TaskUpdate","append":"\"}"}},{"t":1529191,"name":"aiToolInfo","data":{"toolName":"TaskUpdate","toolId":36,"toolInput":{"taskId":"4","status":"completed"}}},{"t":1529195,"name":"aiProgress","data":{"toolName":"TaskUpdate","toolId":37,"phase":"tool_use"}},{"t":1529197,"name":"aiToolResult","data":{"toolId":36,"isError":false,"preview":"Updated task #4 status"}},{"t":1529315,"name":"aiToolStream","data":{"toolId":37,"toolName":"TaskUpdate","append":"{\"taskId\": \"5\", \"status\": \"in_progress"}},{"t":1529629,"name":"aiToolStream","data":{"toolId":37,"toolName":"TaskUpdate","append":"\"}"}},{"t":1529631,"name":"aiToolInfo","data":{"toolName":"TaskUpdate","toolId":37,"toolInput":{"taskId":"5","status":"in_progress"}}},{"t":1529635,"name":"aiToolResult","data":{"toolId":37,"isError":false,"preview":"Updated task #5 status"}},{"t":1531219,"name":"aiProgress","data":{"toolName":"Edit","toolId":38,"phase":"tool_use"}},{"t":1531835,"name":"aiToolStream","data":{"toolId":38,"toolName":"Edit","append":"{\"file_path\": \""}},{"t":1532468,"name":"aiToolStream","data":{"toolId":38,"toolName":"Edit","append":"{{PROJECT}}/dave-jungle-temple.html\", \"old_string\": \"/* ==UPDATE== */\", \"new_string\": \"/* ==ATTRACT MODE BOT== */\\n// A tiny scripted runner: always heads right, h"}},{"t":1533088,"name":"aiToolStream","data":{"toolId":38,"toolName":"Edit","append":"ops walls, gaps, spikes, water and snakes.\\nconst bot={jumpT:0,air:false,stuck:0,lastX:0,restart:0};\\nfunction botInput(dt){"}},{"t":1533393,"name":"aiToolStream","data":{"toolId":38,"toolName":"Edit","append":"\\n const inp={left:false,right:true,jump:"}},{"t":1533713,"name":"aiToolStream","data":{"toolId":38,"toolName":"Edit","append":"false};\\n if(bot.restart>0){ bot.restart-=dt; inp.right=false; if(bot.restart<=0) startAttract(); return inp"}},{"t":1534008,"name":"aiToolStream","data":{"toolId":38,"toolName":"Edit","append":"; }\\n if(P.dead>0) return inp;\\n bot.jumpT-=dt;"}},{"t":1534373,"name":"aiToolStream","data":{"toolId":38,"toolName":"Edit","append":"\\n const front=P.x+P.w, feet=P.y+P.h;\\n if(P.ground){\\n if(bot.j"}},{"t":1534633,"name":"aiToolStream","data":{"toolId":38,"toolName":"Edit","append":"umpT>0&&bot.air) bot.jumpT=0; bot.air=false;\\n const col=Math.floor(("}},{"t":1534893,"name":"aiToolStream","data":{"toolId":38,"toolName":"Edit","append":"front+6)/T), row=Math.floor((feet-2)/T), t0=tileAt(col,row); let need=false;"}},{"t":1535198,"name":"aiToolStream","data":{"toolId":38,"toolName":"Edit","append":"\\n if(isSolid(t0)||t0==='^') need=true;\\n else { let safe=false"}},{"t":1535474,"name":"aiToolStream","data":{"toolId":38,"toolName":"Edit","append":"; for(let r=row+1;r<=row+3;r++){ const ch=tileAt(col,r); if(ch==='"}},{"t":1535760,"name":"aiToolStream","data":{"toolId":38,"toolName":"Edit","append":" ') continue; safe=isSolid(ch)||ch==='-'; break; } need"}},{"t":1536021,"name":"aiToolStream","data":{"toolId":38,"toolName":"Edit","append":"=!safe; }\\n for(const e of enemies){ if(e.gone||e.dead>0)"}},{"t":1536337,"name":"aiToolStream","data":{"toolId":38,"toolName":"Edit","append":" continue; const dx=e.x-front; if(dx>-6&&dx<("}},{"t":1536590,"name":"aiToolStream","data":{"toolId":38,"toolName":"Edit","append":"e.dir<0?34:20)&&Math.abs(e.y+e.h-feet)<14) need"}},{"t":1536899,"name":"aiToolStream","data":{"toolId":38,"toolName":"Edit","append":"=true; }\\n if(need&&bot.jumpT<=0&&!P.prevJump) bot.jumpT=."}},{"t":1537212,"name":"aiToolStream","data":{"toolId":38,"toolName":"Edit","append":"4;\\n } else bot.air=true;\\n inp.jump=bot.jumpT>0;\\n // failsafe: if"}},{"t":1537465,"name":"aiToolStream","data":{"toolId":38,"toolName":"Edit","append":" wedged somewhere, hop;"}},{"t":1537718,"name":"aiToolStream","data":{"toolId":38,"toolName":"Edit","append":" if hopeless, restart the demo\\n if(Math.abs(P.x-b"}},{"t":1538003,"name":"aiToolStream","data":{"toolId":38,"toolName":"Edit","append":"ot.lastX)>3){ bot.lastX=P.x; bot.stuck=0;"}},{"t":1538275,"name":"aiToolStream","data":{"toolId":38,"toolName":"Edit","append":" } else { bot.stuck+=dt; if(bot.stuck>1.2&&P.ground"}},{"t":1538568,"name":"aiToolStream","data":{"toolId":38,"toolName":"Edit","append":"&&!P.prevJump) inp.jump=true; if(bot.stu"}},{"t":1539283,"name":"aiToolStream","data":{"toolId":38,"toolName":"Edit","append":"ck>6) startAttract"}},{"t":1539564,"name":"aiToolStream","data":{"toolId":38,"toolName":"Edit","append":"(); }\\n return inp;\\n}\\nfunction startAttract(){ G.mode='attract'; bot.jumpT=0; bot.stuck=0; bot.restart=0; bot.air=false; resetLevel(); if"}},{"t":1539924,"name":"aiToolStream","data":{"toolId":38,"toolName":"Edit","append":"(typeof syncUi==='function') syncUi(); }\\nfunction takeControl(){ if(G.mode!=='attract') return; G.mode='play'; resetLevel(); if(typeof syncUi==='function') sync"}},{"t":1540202,"name":"aiToolStream","data":{"toolId":38,"toolName":"Edit","append":"Ui(); }\\nfunction restartIfEnded(){ if(G.mode!=='win'&&G.mode!=='over') return false; G.mode='play'; resetLevel(); if(type"}},{"t":1540455,"name":"aiToolStream","data":{"toolId":38,"toolName":"Edit","append":"of syncUi==='function') syncUi(); return true; }\\nendGame=function(kind){\\n if"}},{"t":1540767,"name":"aiToolStream","data":{"toolId":38,"toolName":"Edit","append":"(G.mode==='attract'){ bot.restart=1.6; G.winT=0; return; } // demo just"}},{"t":1541029,"name":"aiToolStream","data":{"toolId":38,"toolName":"Edit","append":" loops\\n G.mode=kind; playSfx(kind==='win'?'f"}},{"t":1541328,"name":"aiToolStream","data":{"toolId":38,"toolName":"Edit","append":"anfare':'over'); if(typeof syncUi==='function') syncUi();\\n};"}},{"t":1541581,"name":"aiToolStream","data":{"toolId":38,"toolName":"Edit","append":"\\n\\n/* ==UPDATE== */\"}"}},{"t":1541769,"name":"aiToolInfo","data":{"toolName":"Edit","toolId":38,"toolInput":{"file_path":"{{PROJECT}}/dave-jungle-temple.html","old_string":"/* ==UPDATE== */","new_string":"/* ==ATTRACT MODE BOT== */\n// A tiny scripted runner: always heads right, hops walls, gaps, spikes, water and snakes.\nconst bot={jumpT:0,air:false,stuck:0,lastX:0,restart:0};\nfunction botInput(dt){\n const inp={left:false,right:true,jump:false};\n if(bot.restart>0){ bot.restart-=dt; inp.right=false; if(bot.restart<=0) startAttract(); return inp; }\n if(P.dead>0) return inp;\n bot.jumpT-=dt;\n const front=P.x+P.w, feet=P.y+P.h;\n if(P.ground){\n if(bot.jumpT>0&&bot.air) bot.jumpT=0; bot.air=false;\n const col=Math.floor((front+6)/T), row=Math.floor((feet-2)/T), t0=tileAt(col,row); let need=false;\n if(isSolid(t0)||t0==='^') need=true;\n else { let safe=false; for(let r=row+1;r<=row+3;r++){ const ch=tileAt(col,r); if(ch===' ') continue; safe=isSolid(ch)||ch==='-'; break; } need=!safe; }\n for(const e of enemies){ if(e.gone||e.dead>0) continue; const dx=e.x-front; if(dx>-6&&dx<(e.dir<0?34:20)&&Math.abs(e.y+e.h-feet)<14) need=true; }\n if(need&&bot.jumpT<=0&&!P.prevJump) bot.jumpT=.4;\n } else bot.air=true;\n inp.jump=bot.jumpT>0;\n // failsafe: if wedged somewhere, hop; if hopeless, restart the demo\n if(Math.abs(P.x-bot.lastX)>3){ bot.lastX=P.x; bot.stuck=0; } else { bot.stuck+=dt; if(bot.stuck>1.2&&P.ground&&!P.prevJump) inp.jump=true; if(bot.stuck>6) startAttract(); }\n return inp;\n}\nfunction startAttract(){ G.mode='attract'; bot.jumpT=0; bot.stuck=0; bot.restart=0; bot.air=false; resetLevel(); if(typeof syncUi==='function') syncUi(); }\nfunction takeControl(){ if(G.mode!=='attract') return; G.mode='play'; resetLevel(); if(typeof syncUi==='function') syncUi(); }\nfunction restartIfEnded(){ if(G.mode!=='win'&&G.mode!=='over') return false; G.mode='play'; resetLevel(); if(typeof syncUi==='function') syncUi(); return true; }\nendGame=function(kind){\n if(G.mode==='attract'){ bot.restart=1.6; G.winT=0; return; } // demo just loops\n G.mode=kind; playSfx(kind==='win'?'fanfare':'over'); if(typeof syncUi==='function') syncUi();\n};\n\n/* ==UPDATE== */"}}},{"t":1541831,"name":"aiToolEdit","data":{"toolId":38,"edit":{"file":"{{PROJECT}}/dave-jungle-temple.html","oldText":"/* ==UPDATE== */","newText":"/* ==ATTRACT MODE BOT== */\n// A tiny scripted runner: always heads right, hops walls, gaps, spikes, water and snakes.\nconst bot={jumpT:0,air:false,stuck:0,lastX:0,restart:0};\nfunction botInput(dt){\n const inp={left:false,right:true,jump:false};\n if(bot.restart>0){ bot.restart-=dt; inp.right=false; if(bot.restart<=0) startAttract(); return inp; }\n if(P.dead>0) return inp;\n bot.jumpT-=dt;\n const front=P.x+P.w, feet=P.y+P.h;\n if(P.ground){\n if(bot.jumpT>0&&bot.air) bot.jumpT=0; bot.air=false;\n const col=Math.floor((front+6)/T), row=Math.floor((feet-2)/T), t0=tileAt(col,row); let need=false;\n if(isSolid(t0)||t0==='^') need=true;\n else { let safe=false; for(let r=row+1;r<=row+3;r++){ const ch=tileAt(col,r); if(ch===' ') continue; safe=isSolid(ch)||ch==='-'; break; } need=!safe; }\n for(const e of enemies){ if(e.gone||e.dead>0) continue; const dx=e.x-front; if(dx>-6&&dx<(e.dir<0?34:20)&&Math.abs(e.y+e.h-feet)<14) need=true; }\n if(need&&bot.jumpT<=0&&!P.prevJump) bot.jumpT=.4;\n } else bot.air=true;\n inp.jump=bot.jumpT>0;\n // failsafe: if wedged somewhere, hop; if hopeless, restart the demo\n if(Math.abs(P.x-bot.lastX)>3){ bot.lastX=P.x; bot.stuck=0; } else { bot.stuck+=dt; if(bot.stuck>1.2&&P.ground&&!P.prevJump) inp.jump=true; if(bot.stuck>6) startAttract(); }\n return inp;\n}\nfunction startAttract(){ G.mode='attract'; bot.jumpT=0; bot.stuck=0; bot.restart=0; bot.air=false; resetLevel(); if(typeof syncUi==='function') syncUi(); }\nfunction takeControl(){ if(G.mode!=='attract') return; G.mode='play'; resetLevel(); if(typeof syncUi==='function') syncUi(); }\nfunction restartIfEnded(){ if(G.mode!=='win'&&G.mode!=='over') return false; G.mode='play'; resetLevel(); if(typeof syncUi==='function') syncUi(); return true; }\nendGame=function(kind){\n if(G.mode==='attract'){ bot.restart=1.6; G.winT=0; return; } // demo just loops\n G.mode=kind; playSfx(kind==='win'?'fanfare':'over'); if(typeof syncUi==='function') syncUi();\n};\n\n/* ==UPDATE== */","replaceAll":false,"isLivePreviewRelated":true}}},{"t":1541834,"name":"aiToolResult","data":{"toolId":38,"isError":false,"preview":"The file {{PROJECT}}/dave-jungle-temple.html has been updated s"}},{"t":1548832,"name":"aiProgress","data":{"toolName":"Edit","toolId":39,"phase":"tool_use"}},{"t":1548957,"name":"aiToolStream","data":{"toolId":39,"toolName":"Edit","append":"{\"file_path\": \""}},{"t":1549208,"name":"aiToolStream","data":{"toolId":39,"toolName":"Edit","append":"{{PROJECT}}/dave-jungle-temple.html"}},{"t":1549704,"name":"aiToolStream","data":{"toolId":39,"toolName":"Edit","append":"\", \"old_string\": \" if(G.winT>0){ G.winT-=dt; if(G.winT<=0) endGame('win'); }"}},{"t":1550023,"name":"aiToolStream","data":{"toolId":39,"toolName":"Edit","append":"\", \"new_string\": \" if(G.winT>0){ G.winT-=dt; if(G.winT"}},{"t":1550274,"name":"aiToolStream","data":{"toolId":39,"toolName":"Edit","append":"<=0){ G.inDoor=true; endGame('win'); } }"}},{"t":1550652,"name":"aiToolStream","data":{"toolId":39,"toolName":"Edit","append":"\"}"}},{"t":1550665,"name":"aiToolInfo","data":{"toolName":"Edit","toolId":39,"toolInput":{"file_path":"{{PROJECT}}/dave-jungle-temple.html","old_string":" if(G.winT>0){ G.winT-=dt; if(G.winT<=0) endGame('win'); }","new_string":" if(G.winT>0){ G.winT-=dt; if(G.winT<=0){ G.inDoor=true; endGame('win'); } }"}}},{"t":1550668,"name":"aiProgress","data":{"toolName":"Edit","toolId":40,"phase":"tool_use"}},{"t":1550718,"name":"aiToolEdit","data":{"toolId":39,"edit":{"file":"{{PROJECT}}/dave-jungle-temple.html","oldText":" if(G.winT>0){ G.winT-=dt; if(G.winT<=0) endGame('win'); }","newText":" if(G.winT>0){ G.winT-=dt; if(G.winT<=0){ G.inDoor=true; endGame('win'); } }","replaceAll":false,"isLivePreviewRelated":true}}},{"t":1550721,"name":"aiToolResult","data":{"toolId":39,"isError":false,"preview":"The file {{PROJECT}}/dave-jungle-temple.html has been updated s"}},{"t":1550779,"name":"aiToolStream","data":{"toolId":40,"toolName":"Edit","append":"{\"file_path\": \""}},{"t":1551087,"name":"aiToolStream","data":{"toolId":40,"toolName":"Edit","append":"{{PROJECT}}/dave-jungle-temple.html"}},{"t":1551402,"name":"aiToolStream","data":{"toolId":40,"toolName":"Edit","append":"\", \"old_string\": \" if(G.winT<=0 || G.winT>.55) drawPlayer(cx,"}},{"t":1551652,"name":"aiToolStream","data":{"toolId":40,"toolName":"Edit","append":"cy,t);\", \"new_string\": \" if(!G"}},{"t":1551903,"name":"aiToolStream","data":{"toolId":40,"toolName":"Edit","append":".inDoor && (G.winT<=0 || G.winT>.55)) drawPlayer("}},{"t":1552155,"name":"aiToolStream","data":{"toolId":40,"toolName":"Edit","append":"cx,cy,t);"}},{"t":1552407,"name":"aiToolStream","data":{"toolId":40,"toolName":"Edit","append":"\"}"}},{"t":1552420,"name":"aiToolInfo","data":{"toolName":"Edit","toolId":40,"toolInput":{"file_path":"{{PROJECT}}/dave-jungle-temple.html","old_string":" if(G.winT<=0 || G.winT>.55) drawPlayer(cx,cy,t);","new_string":" if(!G.inDoor && (G.winT<=0 || G.winT>.55)) drawPlayer(cx,cy,t);"}}},{"t":1552423,"name":"aiProgress","data":{"toolName":"Edit","toolId":41,"phase":"tool_use"}},{"t":1552474,"name":"aiToolEdit","data":{"toolId":40,"edit":{"file":"{{PROJECT}}/dave-jungle-temple.html","oldText":" if(G.winT<=0 || G.winT>.55) drawPlayer(cx,cy,t);","newText":" if(!G.inDoor && (G.winT<=0 || G.winT>.55)) drawPlayer(cx,cy,t);","replaceAll":false,"isLivePreviewRelated":true}}},{"t":1552475,"name":"aiToolResult","data":{"toolId":40,"isError":false,"preview":"The file {{PROJECT}}/dave-jungle-temple.html has been updated s"}},{"t":1552532,"name":"aiToolStream","data":{"toolId":41,"toolName":"Edit","append":"{\"file_path\": \""}},{"t":1552784,"name":"aiToolStream","data":{"toolId":41,"toolName":"Edit","append":"{{PROJECT}}/dave-jungle-temple.html"}},{"t":1553158,"name":"aiToolStream","data":{"toolId":41,"toolName":"Edit","append":"\", \"old_string\": \" G.gems=0; G.total=gems.length; G.hasKey=false; G.lives=3; G.win"}},{"t":1553469,"name":"aiToolStream","data":{"toolId":41,"toolName":"Edit","append":"T=0; G.check=-1; G.doorHint=0;"}},{"t":1553795,"name":"aiToolStream","data":{"toolId":41,"toolName":"Edit","append":"\", \"new_string\": \" G.gems=0; G.total=gems.length; G.hasKey=false; G.lives=3; G.winT="}},{"t":1554109,"name":"aiToolStream","data":{"toolId":41,"toolName":"Edit","append":"0; G.check=-1; G.doorHint=0; G.inDoor"}},{"t":1554494,"name":"aiToolStream","data":{"toolId":41,"toolName":"Edit","append":"=false;\"}"}},{"t":1554624,"name":"aiToolInfo","data":{"toolName":"Edit","toolId":41,"toolInput":{"file_path":"{{PROJECT}}/dave-jungle-temple.html","old_string":" G.gems=0; G.total=gems.length; G.hasKey=false; G.lives=3; G.winT=0; G.check=-1; G.doorHint=0;","new_string":" G.gems=0; G.total=gems.length; G.hasKey=false; G.lives=3; G.winT=0; G.check=-1; G.doorHint=0; G.inDoor=false;"}}},{"t":1554625,"name":"aiProgress","data":{"toolName":"Edit","toolId":42,"phase":"tool_use"}},{"t":1554670,"name":"aiToolEdit","data":{"toolId":41,"edit":{"file":"{{PROJECT}}/dave-jungle-temple.html","oldText":" G.gems=0; G.total=gems.length; G.hasKey=false; G.lives=3; G.winT=0; G.check=-1; G.doorHint=0;","newText":" G.gems=0; G.total=gems.length; G.hasKey=false; G.lives=3; G.winT=0; G.check=-1; G.doorHint=0; G.inDoor=false;","replaceAll":false,"isLivePreviewRelated":true}}},{"t":1554670,"name":"aiToolResult","data":{"toolId":41,"isError":false,"preview":"The file {{PROJECT}}/dave-jungle-temple.html has been updated s"}},{"t":1554688,"name":"aiToolStream","data":{"toolId":42,"toolName":"Edit","append":"{\"file_path\": \"{{PROJECT}}"}},{"t":1554991,"name":"aiToolStream","data":{"toolId":42,"toolName":"Edit","append":"/dave-jungle-temple.html\", \"old_string\": \" SPAWN"}},{"t":1555289,"name":"aiToolStream","data":{"toolId":42,"toolName":"Edit","append":".enemies.push({t:'snake',x:67*T,y:10*T,x0:65*T,x1:71*T"}},{"t":1555605,"name":"aiToolStream","data":{"toolId":42,"toolName":"Edit","append":"});\\n SPAWN.enemies.push({t:'bat',x:50*T,y:6*T,x0:47*T,"}},{"t":1555925,"name":"aiToolStream","data":{"toolId":42,"toolName":"Edit","append":"x1:53*T});\", \"new_string\": \" SPAWN.enemies."}},{"t":1556223,"name":"aiToolStream","data":{"toolId":42,"toolName":"Edit","append":"push({t:'snake',x:69*T,y:10*T,x0:67*T,x1:72*"}},{"t":1556478,"name":"aiToolStream","data":{"toolId":42,"toolName":"Edit","append":"T});\\n SPAWN.enemies.push({t:'bat',x:50*T,y:6*T,x0:49*T"}},{"t":1556787,"name":"aiToolStream","data":{"toolId":42,"toolName":"Edit","append":",x1:53*T});"}},{"t":1557041,"name":"aiToolStream","data":{"toolId":42,"toolName":"Edit","append":"\"}"}},{"t":1557053,"name":"aiToolInfo","data":{"toolName":"Edit","toolId":42,"toolInput":{"file_path":"{{PROJECT}}/dave-jungle-temple.html","old_string":" SPAWN.enemies.push({t:'snake',x:67*T,y:10*T,x0:65*T,x1:71*T});\n SPAWN.enemies.push({t:'bat',x:50*T,y:6*T,x0:47*T,x1:53*T});","new_string":" SPAWN.enemies.push({t:'snake',x:69*T,y:10*T,x0:67*T,x1:72*T});\n SPAWN.enemies.push({t:'bat',x:50*T,y:6*T,x0:49*T,x1:53*T});"}}},{"t":1557056,"name":"aiProgress","data":{"toolName":"Edit","toolId":43,"phase":"tool_use"}},{"t":1557118,"name":"aiToolEdit","data":{"toolId":42,"edit":{"file":"{{PROJECT}}/dave-jungle-temple.html","oldText":" SPAWN.enemies.push({t:'snake',x:67*T,y:10*T,x0:65*T,x1:71*T});\n SPAWN.enemies.push({t:'bat',x:50*T,y:6*T,x0:47*T,x1:53*T});","newText":" SPAWN.enemies.push({t:'snake',x:69*T,y:10*T,x0:67*T,x1:72*T});\n SPAWN.enemies.push({t:'bat',x:50*T,y:6*T,x0:49*T,x1:53*T});","replaceAll":false,"isLivePreviewRelated":true}}},{"t":1557119,"name":"aiToolResult","data":{"toolId":42,"isError":false,"preview":"The file {{PROJECT}}/dave-jungle-temple.html has been updated s"}},{"t":1557163,"name":"aiToolStream","data":{"toolId":43,"toolName":"Edit","append":"{\"file_path\": \""}},{"t":1557473,"name":"aiToolStream","data":{"toolId":43,"toolName":"Edit","append":"{{PROJECT}}/dave-jungle-"}},{"t":1557723,"name":"aiToolStream","data":{"toolId":43,"toolName":"Edit","append":"temple.html\", \"old_string\": \"G.mode='play"}},{"t":1557979,"name":"aiToolStream","data":{"toolId":43,"toolName":"Edit","append":"'; resetLevel();\\nstart();"}},{"t":1558254,"name":"aiToolStream","data":{"toolId":43,"toolName":"Edit","append":"\", \"new_string\": \"startAttract();\\nstart();\"}"}},{"t":1558406,"name":"aiToolInfo","data":{"toolName":"Edit","toolId":43,"toolInput":{"file_path":"{{PROJECT}}/dave-jungle-temple.html","old_string":"G.mode='play'; resetLevel();\nstart();","new_string":"startAttract();\nstart();"}}},{"t":1558457,"name":"aiToolEdit","data":{"toolId":43,"edit":{"file":"{{PROJECT}}/dave-jungle-temple.html","oldText":"G.mode='play'; resetLevel();\nstart();","newText":"startAttract();\nstart();","replaceAll":false,"isLivePreviewRelated":true}}},{"t":1558460,"name":"aiToolResult","data":{"toolId":43,"isError":false,"preview":"The file {{PROJECT}}/dave-jungle-temple.html has been updated s"}},{"t":1560719,"name":"aiTextStream","data":{"text":"\n\nNow the HU"}},{"t":1560720,"name":"aiTextStream","data":{"text":"D, prompt, overlays and touch controls markup."}},{"t":1560723,"name":"aiProgress","data":{"toolName":"Edit","toolId":44,"phase":"tool_use"}},{"t":1560724,"name":"aiToolStream","data":{"toolId":44,"toolName":"Edit","append":"{\"file_path\": \"{{PROJECT}}/dave-jungle"}},{"t":1561349,"name":"aiToolStream","data":{"toolId":44,"toolName":"Edit","append":"-temple.html\", \"old_string\": \"
\\n

Dave & the Papaya Temple

\\n
\\n
\\n \\n
\", \"new_string\": \"
\\n
\\n \\n

Dave "}},{"t":1562639,"name":"aiToolStream","data":{"toolId":44,"toolName":"Edit","append":"& the Papaya Temple

\\n
\\n "}},{"t":1563758,"name":"aiToolStream","data":{"toolId":44,"toolName":"Edit","append":"\\n
\\n\\n
\\n \\n
\\n
0"}},{"t":1564596,"name":"aiToolStream","data":{"toolId":44,"toolName":"Edit","append":"/0
\\n
No key
\\n "}},{"t":1565158,"name":"aiToolStream","data":{"toolId":44,"toolName":"Edit","append":"
\\n \\n
Demo
\\n "}},{"t":1565722,"name":"aiToolStream","data":{"toolId":44,"toolName":"Edit","append":"
Press any key to play
\\n "}},{"t":1565973,"name":"aiToolStream","data":{"toolId":44,"toolName":"Edit","append":"
\\n "}},{"t":1567721,"name":"aiToolStream","data":{"toolId":44,"toolName":"Edit","append":"\\n
\\n\\n
\\n
\\n \\n
\\n

←"}},{"t":1569219,"name":"aiToolStream","data":{"toolId":44,"toolName":"Edit","append":" → / A D move · "}},{"t":1569470,"name":"aiToolStream","data":{"toolId":44,"toolName":"Edit","append":"Space jump · M sound

\\n \\n \\n
\\n
"}},{"t":1570284,"name":"aiToolStream","data":{"toolId":44,"toolName":"Edit","append":"\"}"}},{"t":1570296,"name":"aiToolInfo","data":{"toolName":"Edit","toolId":44,"toolInput":{"file_path":"{{PROJECT}}/dave-jungle-temple.html","old_string":"
\n

Dave & the Papaya Temple

\n
\n
\n \n
","new_string":"
\n
\n \n

Dave & the Papaya Temple

\n
\n \n
\n\n
\n \n
\n
0/0
\n
No key
\n
\n
\n
Demo
\n
Press any key to play
\n
\n \n
\n\n
\n
\n \n \n
\n

← → / A D move · Space jump · M sound

\n
\n \n
\n
"}}},{"t":1570361,"name":"aiToolEdit","data":{"toolId":44,"edit":{"file":"{{PROJECT}}/dave-jungle-temple.html","oldText":"
\n

Dave & the Papaya Temple

\n
\n
\n \n
","newText":"
\n
\n \n

Dave & the Papaya Temple

\n
\n \n
\n\n
\n \n
\n
0/0
\n
No key
\n
\n
\n
Demo
\n
Press any key to play
\n
\n \n
\n\n
\n
\n \n \n
\n

← → / A D move · Space jump · M sound

\n
\n \n
\n
","replaceAll":false,"isLivePreviewRelated":true}}},{"t":1570364,"name":"aiToolResult","data":{"toolId":44,"isError":false,"preview":"The file {{PROJECT}}/dave-jungle-temple.html has been updated s"}},{"t":1571618,"name":"aiProgress","data":{"toolName":"Edit","toolId":45,"phase":"tool_use"}},{"t":1572247,"name":"aiToolStream","data":{"toolId":45,"toolName":"Edit","append":"{\"file_path\": \""}},{"t":1572865,"name":"aiToolStream","data":{"toolId":45,"toolName":"Edit","append":"{{PROJECT}}/dave-jungle-temple.html\", \"old_string\": \" canvas#game{\\n width:100%; height:100%; display:block;\\n image-rendering:pixelated; image-rendering:crisp-edges;\\n }\", \"new_string\": \" canvas#game{\\n width:"}},{"t":1573115,"name":"aiToolStream","data":{"toolId":45,"toolName":"Edit","append":"100%; height:100%;"}},{"t":1573881,"name":"aiToolStream","data":{"toolId":45,"toolName":"Edit","append":" display:block;\\n image-"}},{"t":1574380,"name":"aiToolStream","data":{"toolId":45,"toolName":"Edit","append":"rendering:crisp-edges; image-rendering:pixelated;\\n }\\n body{\\n background:\\n radial-gradient(120% 80% at 50% 0%, #12382a 0%, transparent 60%),"}},{"t":1574764,"name":"aiToolStream","data":{"toolId":45,"toolName":"Edit","append":"\\n radial-gradient(90% 60% at 50% 110%, rgba(226,97,42,.16) 0%, transparent 60%),\\n var(--leaf-900);\\n }\\n .shell{max-width:1500px}\\n .top, .pad{width:min(96vw, calc((100vh - 170px)"}},{"t":1575145,"name":"aiToolStream","data":{"toolId":45,"toolName":"Edit","append":" * 16 / 9)); display:flex; align-items:center; justify-content:space-between; gap:12px}\\n .brand{display:flex"}},{"t":1575531,"name":"aiToolStream","data":{"toolId":45,"toolName":"Edit","append":"; align-items:center; gap:10px; min-width:0}\\n .leaf{width:14px; height:14px; flex:"}},{"t":1575918,"name":"aiToolStream","data":{"toolId":45,"toolName":"Edit","append":"none; background:var(--papaya); border-radius:0 70% 0 70"}},{"t":1576627,"name":"aiToolStream","data":{"toolId":45,"toolName":"Edit","append":"%; box-shadow:"}},{"t":1577119,"name":"aiToolStream","data":{"toolId":45,"toolName":"Edit","append":"inset -3px -3px 0 var(--papaya-deep)}\\n h1{font-size:clamp(14px,2.2vw,22px); letter-spacing:.06em; text-transform:uppercase; font-weight:800; white-space:nowrap; overflow:hidden; text-overflow:ellipsis}\\n "}},{"t":1577390,"name":"aiToolStream","data":{"toolId":45,"toolName":"Edit","append":"h1 em{font-style:normal; color:var(--papaya)}\\n .pill{\\n font:inherit; font-size:12"}},{"t":1577665,"name":"aiToolStream","data":{"toolId":45,"toolName":"Edit","append":"px; letter-spacing:.08em; text-transform:u"}},{"t":1577980,"name":"aiToolStream","data":{"toolId":45,"toolName":"Edit","append":"ppercase; color:var(--ivory);\\n background:rgba(251,243,223,.06); border:1px solid r"}},{"t":1578269,"name":"aiToolStream","data":{"toolId":45,"toolName":"Edit","append":"gba(251,243,223"}},{"t":1578923,"name":"aiToolStream","data":{"toolId":45,"toolName":"Edit","append":",.22); border-radius:999px;\\n padding"}},{"t":1579235,"name":"aiToolStream","data":{"toolId":45,"toolName":"Edit","append":":7px 12px; display:inline-flex; align-items"}},{"t":1579884,"name":"aiToolStream","data":{"toolId":45,"toolName":"Edit","append":":center; gap:8px; cursor:pointer; flex:none;\\n transition:background .2s, border-color .2s, transform .15s;\\n }\\n .pill:hover{background:rgba(251,243,223,.12); border-color:var(--papaya-soft)}\\n .pill:active{transform:scale(.96)}\\n .pill .dot{width:8px; height:8px; border-radius:50%; background:var(--ivory-dim); transition:background .2"}},{"t":1580261,"name":"aiToolStream","data":{"toolId":45,"toolName":"Edit","append":"s, box-shadow .2s}\\n .pill[aria-pressed=\\\"true\\\"] .dot{background:var(--papaya); box-shadow:0 0 0 3"}},{"t":1581221,"name":"aiToolStream","data":{"toolId":45,"toolName":"Edit","append":"px rgba(255,138,61,.25)}\\n .stage{\\n box-shadow:0 0 0 2px #"}},{"t":1581606,"name":"aiToolStream","data":{"toolId":45,"toolName":"Edit","append":"1b4a33, 0 0 0 5px var(--leaf-800), 0 24px 60px -18px rgba(0,0,0,.8);\\n touch-action:none"}},{"t":1581980,"name":"aiToolStream","data":{"toolId":45,"toolName":"Edit","append":"; user-select:none; -webkit-user-select:none;\\n }\\n .stage::after{ /* soft vignette,"}},{"t":1582343,"name":"aiToolStream","data":{"toolId":45,"toolName":"Edit","append":" one static layer */\\n content:\\\"\\\"; position:absolute; inset:0; pointer-events:none;\\n background:radial-gradient("}},{"t":1582719,"name":"aiToolStream","data":{"toolId":45,"toolName":"Edit","append":"ellipse at center, transparent 58%, rgba(3,12"}},{"t":1583102,"name":"aiToolStream","data":{"toolId":45,"toolName":"Edit","append":",8,.5) 100%);\\n }\\n .hud{position:absolute; z-index:2; top"}},{"t":1583486,"name":"aiToolStream","data":{"toolId":45,"toolName":"Edit","append":":2.2%; left:1.6%; right:1.6%; display:flex; g"}},{"t":1583742,"name":"aiToolStream","data":{"toolId":45,"toolName":"Edit","append":"ap:1.2%; align-items:center; pointer-events:none}\\n .ch"}},{"t":1584077,"name":"aiToolStream","data":{"toolId":45,"toolName":"Edit","append":"ip{\\n display:flex; align-items:center; gap:.5em; pad"}},{"t":1584864,"name":"aiToolStream","data":{"toolId":45,"toolName":"Edit","append":"ding:.35em .7"}},{"t":1585332,"name":"aiToolStream","data":{"toolId":45,"toolName":"Edit","append":"em; font-size:clamp(10px,1.5vw,16px); font-weight:700;"}},{"t":1585611,"name":"aiToolStream","data":{"toolId":45,"toolName":"Edit","append":" letter-spacing:.05em;\\n background:rgba(6,21,15,.72); border:1px solid rgba(251,243,223,.18); border-radius:8px; color:var(--ivory);\\n }\\n .chip canvas{height:1.1em; width:auto; image"}},{"t":1585995,"name":"aiToolStream","data":{"toolId":45,"toolName":"Edit","append":"-rendering:pixel"}},{"t":1586612,"name":"aiToolStream","data":{"toolId":45,"toolName":"Edit","append":"ated}\\n .chip.lives{margin-left:auto; gap:.3em}\\n .chip.lives canvas{transition:opacity .25s, transform .25s}\\n .chip.lives canvas.lost{opacity:.18; transform:scale(.8)}\\n #keyChip{color:var(--ivory-dim)} #keyChip canvas{opacity:.35"}},{"t":1587499,"name":"aiToolStream","data":{"toolId":45,"toolName":"Edit","append":"; transition:opacity .3s}\\n #keyChip.has{color:var(--papaya-soft); border-color"}},{"t":1587883,"name":"aiToolStream","data":{"toolId":45,"toolName":"Edit","append":":var(--papaya)} #keyChip.has canvas{opacity:1}\\n .bump{animation:bump .25s ease-out}\\n @keyframes bump{0%{transform:scale(1)}40%{transform:scale(1.14)}100%{transform:scale(1)}}"}},{"t":1588297,"name":"aiToolStream","data":{"toolId":45,"toolName":"Edit","append":"\\n .demo-tag{\\n position:absolute; z-index:2; left:50%; top:2.6"}},{"t":1588733,"name":"aiToolStream","data":{"toolId":45,"toolName":"Edit","append":"%; transform:translateX(-50%); font-size:clamp(9px,1.2vw,13px); letter-spacing:.3"}},{"t":1589168,"name":"aiToolStream","data":{"toolId":45,"toolName":"Edit","append":"em; text-transform:uppercase;\\n color:var(--leaf-900); background:var(--papaya); padding:.25em .7em ."}},{"t":1589420,"name":"aiToolStream","data":{"toolId":45,"toolName":"Edit","append":"25em "}},{"t":1589764,"name":"aiToolStream","data":{"toolId":45,"toolName":"Edit","append":"1em; border-radius:"}},{"t":1590413,"name":"aiToolStream","data":{"toolId":45,"toolName":"Edit","append":"4px; font-weight:800;\\n }\\n .prompt{position:absolute; z-index:2; left:0; right:0; bottom:9%; text-align:center; pointer-events:none}\\n .prompt span{\\n display:inline-block; font-size:clamp(11px,1.9vw,20px); font-weight:800; letter-spacing:.16em; text-transform"}},{"t":1590772,"name":"aiToolStream","data":{"toolId":45,"toolName":"Edit","append":":uppercase;\\n color:var(--ivory); background:rgba(6,21,15,.78); border:1px solid var(--papaya); border-radius:8px; padding:.55"}},{"t":1591156,"name":"aiToolStream","data":{"toolId":45,"toolName":"Edit","append":"em 1.1em;\\n animation:blink 1.4s steps(2,jump-none"}},{"t":1591967,"name":"aiToolStream","data":{"toolId":45,"toolName":"Edit","append":") infinite;\\n }\\n @keyframes blink{0%{opacity:1}100%{opacity:.45}}\\n .toast{\\n position:absolute; z-index:2; left:50%; bottom:6%; transform:translate(-50%,12px); opacity:0; pointer"}},{"t":1592311,"name":"aiToolStream","data":{"toolId":45,"toolName":"Edit","append":"-events:none; white-space:nowrap;\\n "}},{"t":1592928,"name":"aiToolStream","data":{"toolId":45,"toolName":"Edit","append":"font-size:clamp(10px,1.4vw,15px); font-weight:700; color:var(--leaf-900); background:var(--ivory); border-radius:8px; padding:.5em .9em;\\n box-shadow:0 3px 0 var(--papaya-deep); transition:opacity .25s, transform .25s;\\n "}},{"t":1593257,"name":"aiToolStream","data":{"toolId":45,"toolName":"Edit","append":"}\\n .toast.show{opacity:1; transform:translate(-50%,0)}\\n .overlay{position:absolute"}},{"t":1593521,"name":"aiToolStream","data":{"toolId":45,"toolName":"Edit","append":"; z-index:3; inset:0; display:fl"}},{"t":1593781,"name":"aiToolStream","data":{"toolId":45,"toolName":"Edit","append":"ex; align-items:center; justify-content:center; background:rgba(4,14"}},{"t":1594031,"name":"aiToolStream","data":{"toolId":45,"toolName":"Edit","append":",10,.72); animation:fade .35s ease-out}\\n .overlay[hidden]{"}},{"t":1594296,"name":"aiToolStream","data":{"toolId":45,"toolName":"Edit","append":"display:none}\\n .card{\\n text-align:center; pad"}},{"t":1594546,"name":"aiToolStream","data":{"toolId":45,"toolName":"Edit","append":"ding:clamp(14px,3vw,30px) clamp(18px,4vw,44px); border-radius:14"}},{"t":1594845,"name":"aiToolStream","data":{"toolId":45,"toolName":"Edit","append":"px; max-width:86%;\\n background:linear-gradient(180deg"}},{"t":1595602,"name":"aiToolStream","data":{"toolId":45,"toolName":"Edit","append":","}},{"t":1595881,"name":"aiToolStream","data":{"toolId":45,"toolName":"Edit","append":"#123a29,#0b2318); border:2px solid var(--papaya); box-shadow:0 6px 0 var(--papaya-deep), 0 22px 40px -12px #000;\\n animation:pop .4"}},{"t":1596590,"name":"aiToolStream","data":{"toolId":45,"toolName":"Edit","append":"s cubic-bezier(.2,1"}},{"t":1596886,"name":"aiToolStream","data":{"toolId":45,"toolName":"Edit","append":".4,.4,1);\\n }\\n .eyebrow{font-size:clamp(9"}},{"t":1597269,"name":"aiToolStream","data":{"toolId":45,"toolName":"Edit","append":"px,1.2vw,13px); letter-spacing:.3em; text-transform:uppercase; color:var(--papaya-soft)}\\n .card h2{font-size:clamp(18px,3.6vw,40px); margin:.2em 0 .25em; letter-spacing:.04"}},{"t":1597650,"name":"aiToolStream","data":{"toolId":45,"toolName":"Edit","append":"em; color:var(--ivory)}\\n .card p{font-size:clamp(10px,1.5vw,16px); color:var(--ivory-dim)}\\n .card .hint{margin-top:.9"}},{"t":1597919,"name":"aiToolStream","data":{"toolId":45,"toolName":"Edit","append":"em; font-size:clamp(9px,1.1"}},{"t":1598183,"name":"aiToolStream","data":{"toolId":45,"toolName":"Edit","append":"vw,12px); opacity:.7}\\n .cta{\\n margin-top:1em; font:inherit; font-weight:800; font"}},{"t":1598618,"name":"aiToolStream","data":{"toolId":45,"toolName":"Edit","append":"-size:clamp(11px,1.6vw,17px); letter-spacing:.12em; text-transform:u"}},{"t":1598999,"name":"aiToolStream","data":{"toolId":45,"toolName":"Edit","append":"ppercase; cursor:pointer;\\n color:var(--leaf-900); background:var(--papaya); border:0; border-radius:10px; padding:.7em "}},{"t":1599383,"name":"aiToolStream","data":{"toolId":45,"toolName":"Edit","append":"1.5em; box-shadow:0 4px 0 var(--papaya-deep"}},{"t":1600204,"name":"aiToolStream","data":{"toolId":45,"toolName":"Edit","append":");\\n transition:transform .12s, box-shadow .12s, background .2s;\\n }\\n .cta:hover{background:var(--papaya-soft)} .cta:active{transform:translateY(3px); box-shadow:0 1px 0 var(--papaya-deep)}\\n @keyfram"}},{"t":1600535,"name":"aiToolStream","data":{"toolId":45,"toolName":"Edit","append":"es fade{from{opacity:0}to{opacity:1}}\\n @keyframes pop{from{transform:scale(."}},{"t":1601292,"name":"aiToolStream","data":{"toolId":45,"toolName":"Edit","append":"85) translateY(10px); opacity:0}to{transform:none; opacity:1}}\\n .pad{user-select:none; -webkit-user-select:none}\\n .pad-group{display:flex; gap:10px}\\n .pbtn{\\n width:clamp("}},{"t":1601678,"name":"aiToolStream","data":{"toolId":45,"toolName":"Edit","append":"52px,9vw,72px); height:clamp(44px,7vw,56px); border-radius:12px; cursor:pointer; touch"}},{"t":1602067,"name":"aiToolStream","data":{"toolId":45,"toolName":"Edit","append":"-action:none;\\n font:inherit; font-weight:800; font-size:12px; letter-spacing:.12em; text-"}},{"t":1602914,"name":"aiToolStream","data":{"toolId":45,"toolName":"Edit","append":"transform:uppercase;"}},{"t":1603273,"name":"aiToolStream","data":{"toolId":45,"toolName":"Edit","append":" color:var(--ivory);\\n background:linear-gradient(180deg,#1b4a33,#103424); border:1px solid rgba(251,243,223,.2); box-shadow:0 4px 0 #"}},{"t":1603653,"name":"aiToolStream","data":{"toolId":45,"toolName":"Edit","append":"051009;\\n display:flex; align-items:center; justify-content:center; transition:transform .08s, box-shadow .08s, background"}},{"t":1604014,"name":"aiToolStream","data":{"toolId":45,"toolName":"Edit","append":" .15s;\\n }\\n .pbtn.jump{width:clamp(84px,14vw,120px); background:linear-gradient(180deg,var(--papaya),var(--papaya-deep)); color:var(--leaf-900); border-color:var"}},{"t":1604403,"name":"aiToolStream","data":{"toolId":45,"toolName":"Edit","append":"(--papaya-soft"}},{"t":1605180,"name":"aiToolStream","data":{"toolId":45,"toolName":"Edit","append":"); box-shadow:0 4px 0 #7a2f12"}},{"t":1605459,"name":"aiToolStream","data":{"toolId":45,"toolName":"Edit","append":"}\\n .pbtn.on, .pbtn:active{transform:translateY(3px); box-shadow:0 1px 0 #051009}\\n .tri{width:0; height:0; border:9px solid transparent}\\n .tri.l{border-right-color:var(--ivory); marg"}},{"t":1605842,"name":"aiToolStream","data":{"toolId":45,"toolName":"Edit","append":"in-left:-9px} .tri.r{border-left-color:var(--ivory); margin-right:-9px}\\n .keys{font-size:11px; color:var(--ivory-dim); letter-spacing:.04em; text-align:center;"}},{"t":1606226,"name":"aiToolStream","data":{"toolId":45,"toolName":"Edit","append":" line-height:1.5}\\n .keys b{color:var(--ivory); font-weight:700}\\n button:focus-visible{outline:2px solid var"}},{"t":1606613,"name":"aiToolStream","data":{"toolId":45,"toolName":"Edit","append":"(--papaya-soft); outline-offset:3px}\\n @media (max-width:620px){ .keys{display:none} .stage{border-radius:6"}},{"t":1606997,"name":"aiToolStream","data":{"toolId":45,"toolName":"Edit","append":"px} .pill span#muteTxt{display:none} .pill{padding:9px}"}},{"t":1607377,"name":"aiToolStream","data":{"toolId":45,"toolName":"Edit","append":" }\\n @media (max-height:520px) and (orientation:landscape){\\n .top{display:none} .sh"}},{"t":1607761,"name":"aiToolStream","data":{"toolId":45,"toolName":"Edit","append":"ell{padding:4px; gap:0}\\n .stage{width:min(100"}},{"t":1609157,"name":"aiToolStream","data":{"toolId":45,"toolName":"Edit","append":"vw, calc("}},{"t":1610504,"name":"aiToolStream","data":{"toolId":45,"toolName":"Edit","append":"100vh * 16 / 9)); border-radius:0}\\n .pad{position:fixed; left:0; right:0; bottom:8px; width:auto; padding:0 12px; z-index:5; pointer-events:none}\\n .pad .pbtn{pointer-events:auto; opacity:.8} .keys{display:none}\\n }\\n @media (prefers-reduced-motion:reduce){ .prompt span,.card,.overlay,.bump{animation:none} }\"}"}},{"t":1610518,"name":"aiToolInfo","data":{"toolName":"Edit","toolId":45,"toolInput":{"file_path":"{{PROJECT}}/dave-jungle-temple.html","old_string":" canvas#game{\n width:100%; height:100%; display:block;\n image-rendering:pixelated; image-rendering:crisp-edges;\n }","new_string":" canvas#game{\n width:100%; height:100%; display:block;\n image-rendering:crisp-edges; image-rendering:pixelated;\n }\n body{\n background:\n radial-gradient(120% 80% at 50% 0%, #12382a 0%, transparent 60%),\n radial-gradient(90% 60% at 50% 110%, rgba(226,97,42,.16) 0%, transparent 60%),\n var(--leaf-900);\n }\n .shell{max-width:1500px}\n .top, .pad{width:min(96vw, calc((100vh - 170px) * 16 / 9)); display:flex; align-items:center; justify-content:space-between; gap:12px}\n .brand{display:flex; align-items:center; gap:10px; min-width:0}\n .leaf{width:14px; height:14px; flex:none; background:var(--papaya); border-radius:0 70% 0 70%; box-shadow:inset -3px -3px 0 var(--papaya-deep)}\n h1{font-size:clamp(14px,2.2vw,22px); letter-spacing:.06em; text-transform:uppercase; font-weight:800; white-space:nowrap; overflow:hidden; text-overflow:ellipsis}\n h1 em{font-style:normal; color:var(--papaya)}\n .pill{\n font:inherit; font-size:12px; letter-spacing:.08em; text-transform:uppercase; color:var(--ivory);\n background:rgba(251,243,223,.06); border:1px solid rgba(251,243,223,.22); border-radius:999px;\n padding:7px 12px; display:inline-flex; align-items:center; gap:8px; cursor:pointer; flex:none;\n transition:background .2s, border-color .2s, transform .15s;\n }\n .pill:hover{background:rgba(251,243,223,.12); border-color:var(--papaya-soft)}\n .pill:active{transform:scale(.96)}\n .pill .dot{width:8px; height:8px; border-radius:50%; background:var(--ivory-dim); transition:background .2s, box-shadow .2s}\n .pill[aria-pressed=\"true\"] .dot{background:var(--papaya); box-shadow:0 0 0 3px rgba(255,138,61,.25)}\n .stage{\n box-shadow:0 0 0 2px #1b4a33, 0 0 0 5px var(--leaf-800), 0 24px 60px -18px rgba(0,0,0,.8);\n touch-action:none; user-select:none; -webkit-user-select:none;\n }\n .stage::after{ /* soft vignette, one static layer */\n content:\"\"; position:absolute; inset:0; pointer-events:none;\n background:radial-gradient(ellipse at center, transparent 58%, rgba(3,12,8,.5) 100%);\n }\n .hud{position:absolute; z-index:2; top:2.2%; left:1.6%; right:1.6%; display:flex; gap:1.2%; align-items:center; pointer-events:none}\n .chip{\n display:flex; align-items:center; gap:.5em; padding:.35em .7em; font-size:clamp(10px,1.5vw,16px); font-weight:700; letter-spacing:.05em;\n background:rgba(6,21,15,.72); border:1px solid rgba(251,243,223,.18); border-radius:8px; color:var(--ivory);\n }\n .chip canvas{height:1.1em; width:auto; image-rendering:pixelated}\n .chip.lives{margin-left:auto; gap:.3em}\n .chip.lives canvas{transition:opacity .25s, transform .25s}\n .chip.lives canvas.lost{opacity:.18; transform:scale(.8)}\n #keyChip{color:var(--ivory-dim)} #keyChip canvas{opacity:.35; transition:opacity .3s}\n #keyChip.has{color:var(--papaya-soft); border-color:var(--papaya)} #keyChip.has canvas{opacity:1}\n .bump{animation:bump .25s ease-out}\n @keyframes bump{0%{transform:scale(1)}40%{transform:scale(1.14)}100%{transform:scale(1)}}\n .demo-tag{\n position:absolute; z-index:2; left:50%; top:2.6%; transform:translateX(-50%); font-size:clamp(9px,1.2vw,13px); letter-spacing:.3em; text-transform:uppercase;\n color:var(--leaf-900); background:var(--papaya); padding:.25em .7em .25em 1em; border-radius:4px; font-weight:800;\n }\n .prompt{position:absolute; z-index:2; left:0; right:0; bottom:9%; text-align:center; pointer-events:none}\n .prompt span{\n display:inline-block; font-size:clamp(11px,1.9vw,20px); font-weight:800; letter-spacing:.16em; text-transform:uppercase;\n color:var(--ivory); background:rgba(6,21,15,.78); border:1px solid var(--papaya); border-radius:8px; padding:.55em 1.1em;\n animation:blink 1.4s steps(2,jump-none) infinite;\n }\n @keyframes blink{0%{opacity:1}100%{opacity:.45}}\n .toast{\n position:absolute; z-index:2; left:50%; bottom:6%; transform:translate(-50%,12px); opacity:0; pointer-events:none; white-space:nowrap;\n font-size:clamp(10px,1.4vw,15px); font-weight:700; color:var(--leaf-900); background:var(--ivory); border-radius:8px; padding:.5em .9em;\n box-shadow:0 3px 0 var(--papaya-deep); transition:opacity .25s, transform .25s;\n }\n .toast.show{opacity:1; transform:translate(-50%,0)}\n .overlay{position:absolute; z-index:3; inset:0; display:flex; align-items:center; justify-content:center; background:rgba(4,14,10,.72); animation:fade .35s ease-out}\n .overlay[hidden]{display:none}\n .card{\n text-align:center; padding:clamp(14px,3vw,30px) clamp(18px,4vw,44px); border-radius:14px; max-width:86%;\n background:linear-gradient(180deg,#123a29,#0b2318); border:2px solid var(--papaya); box-shadow:0 6px 0 var(--papaya-deep), 0 22px 40px -12px #000;\n animation:pop .4s cubic-bezier(.2,1.4,.4,1);\n }\n .eyebrow{font-size:clamp(9px,1.2vw,13px); letter-spacing:.3em; text-transform:uppercase; color:var(--papaya-soft)}\n .card h2{font-size:clamp(18px,3.6vw,40px); margin:.2em 0 .25em; letter-spacing:.04em; color:var(--ivory)}\n .card p{font-size:clamp(10px,1.5vw,16px); color:var(--ivory-dim)}\n .card .hint{margin-top:.9em; font-size:clamp(9px,1.1vw,12px); opacity:.7}\n .cta{\n margin-top:1em; font:inherit; font-weight:800; font-size:clamp(11px,1.6vw,17px); letter-spacing:.12em; text-transform:uppercase; cursor:pointer;\n color:var(--leaf-900); background:var(--papaya); border:0; border-radius:10px; padding:.7em 1.5em; box-shadow:0 4px 0 var(--papaya-deep);\n transition:transform .12s, box-shadow .12s, background .2s;\n }\n .cta:hover{background:var(--papaya-soft)} .cta:active{transform:translateY(3px); box-shadow:0 1px 0 var(--papaya-deep)}\n @keyframes fade{from{opacity:0}to{opacity:1}}\n @keyframes pop{from{transform:scale(.85) translateY(10px); opacity:0}to{transform:none; opacity:1}}\n .pad{user-select:none; -webkit-user-select:none}\n .pad-group{display:flex; gap:10px}\n .pbtn{\n width:clamp(52px,9vw,72px); height:clamp(44px,7vw,56px); border-radius:12px; cursor:pointer; touch-action:none;\n font:inherit; font-weight:800; font-size:12px; letter-spacing:.12em; text-transform:uppercase; color:var(--ivory);\n background:linear-gradient(180deg,#1b4a33,#103424); border:1px solid rgba(251,243,223,.2); box-shadow:0 4px 0 #051009;\n display:flex; align-items:center; justify-content:center; transition:transform .08s, box-shadow .08s, background .15s;\n }\n .pbtn.jump{width:clamp(84px,14vw,120px); background:linear-gradient(180deg,var(--papaya),var(--papaya-deep)); color:var(--leaf-900); border-color:var(--papaya-soft); box-shadow:0 4px 0 #7a2f12}\n .pbtn.on, .pbtn:active{transform:translateY(3px); box-shadow:0 1px 0 #051009}\n .tri{width:0; height:0; border:9px solid transparent}\n .tri.l{border-right-color:var(--ivory); margin-left:-9px} .tri.r{border-left-color:var(--ivory); margin-right:-9px}\n .keys{font-size:11px; color:var(--ivory-dim); letter-spacing:.04em; text-align:center; line-height:1.5}\n .keys b{color:var(--ivory); font-weight:700}\n button:focus-visible{outline:2px solid var(--papaya-soft); outline-offset:3px}\n @media (max-width:620px){ .keys{display:none} .stage{border-radius:6px} .pill span#muteTxt{display:none} .pill{padding:9px} }\n @media (max-height:520px) and (orientation:landscape){\n .top{display:none} .shell{padding:4px; gap:0}\n .stage{width:min(100vw, calc(100vh * 16 / 9)); border-radius:0}\n .pad{position:fixed; left:0; right:0; bottom:8px; width:auto; padding:0 12px; z-index:5; pointer-events:none}\n .pad .pbtn{pointer-events:auto; opacity:.8} .keys{display:none}\n }\n @media (prefers-reduced-motion:reduce){ .prompt span,.card,.overlay,.bump{animation:none} }"}}},{"t":1610602,"name":"aiToolEdit","data":{"toolId":45,"edit":{"file":"{{PROJECT}}/dave-jungle-temple.html","oldText":" canvas#game{\n width:100%; height:100%; display:block;\n image-rendering:pixelated; image-rendering:crisp-edges;\n }","newText":" canvas#game{\n width:100%; height:100%; display:block;\n image-rendering:crisp-edges; image-rendering:pixelated;\n }\n body{\n background:\n radial-gradient(120% 80% at 50% 0%, #12382a 0%, transparent 60%),\n radial-gradient(90% 60% at 50% 110%, rgba(226,97,42,.16) 0%, transparent 60%),\n var(--leaf-900);\n }\n .shell{max-width:1500px}\n .top, .pad{width:min(96vw, calc((100vh - 170px) * 16 / 9)); display:flex; align-items:center; justify-content:space-between; gap:12px}\n .brand{display:flex; align-items:center; gap:10px; min-width:0}\n .leaf{width:14px; height:14px; flex:none; background:var(--papaya); border-radius:0 70% 0 70%; box-shadow:inset -3px -3px 0 var(--papaya-deep)}\n h1{font-size:clamp(14px,2.2vw,22px); letter-spacing:.06em; text-transform:uppercase; font-weight:800; white-space:nowrap; overflow:hidden; text-overflow:ellipsis}\n h1 em{font-style:normal; color:var(--papaya)}\n .pill{\n font:inherit; font-size:12px; letter-spacing:.08em; text-transform:uppercase; color:var(--ivory);\n background:rgba(251,243,223,.06); border:1px solid rgba(251,243,223,.22); border-radius:999px;\n padding:7px 12px; display:inline-flex; align-items:center; gap:8px; cursor:pointer; flex:none;\n transition:background .2s, border-color .2s, transform .15s;\n }\n .pill:hover{background:rgba(251,243,223,.12); border-color:var(--papaya-soft)}\n .pill:active{transform:scale(.96)}\n .pill .dot{width:8px; height:8px; border-radius:50%; background:var(--ivory-dim); transition:background .2s, box-shadow .2s}\n .pill[aria-pressed=\"true\"] .dot{background:var(--papaya); box-shadow:0 0 0 3px rgba(255,138,61,.25)}\n .stage{\n box-shadow:0 0 0 2px #1b4a33, 0 0 0 5px var(--leaf-800), 0 24px 60px -18px rgba(0,0,0,.8);\n touch-action:none; user-select:none; -webkit-user-select:none;\n }\n .stage::after{ /* soft vignette, one static layer */\n content:\"\"; position:absolute; inset:0; pointer-events:none;\n background:radial-gradient(ellipse at center, transparent 58%, rgba(3,12,8,.5) 100%);\n }\n .hud{position:absolute; z-index:2; top:2.2%; left:1.6%; right:1.6%; display:flex; gap:1.2%; align-items:center; pointer-events:none}\n .chip{\n display:flex; align-items:center; gap:.5em; padding:.35em .7em; font-size:clamp(10px,1.5vw,16px); font-weight:700; letter-spacing:.05em;\n background:rgba(6,21,15,.72); border:1px solid rgba(251,243,223,.18); border-radius:8px; color:var(--ivory);\n }\n .chip canvas{height:1.1em; width:auto; image-rendering:pixelated}\n .chip.lives{margin-left:auto; gap:.3em}\n .chip.lives canvas{transition:opacity .25s, transform .25s}\n .chip.lives canvas.lost{opacity:.18; transform:scale(.8)}\n #keyChip{color:var(--ivory-dim)} #keyChip canvas{opacity:.35; transition:opacity .3s}\n #keyChip.has{color:var(--papaya-soft); border-color:var(--papaya)} #keyChip.has canvas{opacity:1}\n .bump{animation:bump .25s ease-out}\n @keyframes bump{0%{transform:scale(1)}40%{transform:scale(1.14)}100%{transform:scale(1)}}\n .demo-tag{\n position:absolute; z-index:2; left:50%; top:2.6%; transform:translateX(-50%); font-size:clamp(9px,1.2vw,13px); letter-spacing:.3em; text-transform:uppercase;\n color:var(--leaf-900); background:var(--papaya); padding:.25em .7em .25em 1em; border-radius:4px; font-weight:800;\n }\n .prompt{position:absolute; z-index:2; left:0; right:0; bottom:9%; text-align:center; pointer-events:none}\n .prompt span{\n display:inline-block; font-size:clamp(11px,1.9vw,20px); font-weight:800; letter-spacing:.16em; text-transform:uppercase;\n color:var(--ivory); background:rgba(6,21,15,.78); border:1px solid var(--papaya); border-radius:8px; padding:.55em 1.1em;\n animation:blink 1.4s steps(2,jump-none) infinite;\n }\n @keyframes blink{0%{opacity:1}100%{opacity:.45}}\n .toast{\n position:absolute; z-index:2; left:50%; bottom:6%; transform:translate(-50%,12px); opacity:0; pointer-events:none; white-space:nowrap;\n font-size:clamp(10px,1.4vw,15px); font-weight:700; color:var(--leaf-900); background:var(--ivory); border-radius:8px; padding:.5em .9em;\n box-shadow:0 3px 0 var(--papaya-deep); transition:opacity .25s, transform .25s;\n }\n .toast.show{opacity:1; transform:translate(-50%,0)}\n .overlay{position:absolute; z-index:3; inset:0; display:flex; align-items:center; justify-content:center; background:rgba(4,14,10,.72); animation:fade .35s ease-out}\n .overlay[hidden]{display:none}\n .card{\n text-align:center; padding:clamp(14px,3vw,30px) clamp(18px,4vw,44px); border-radius:14px; max-width:86%;\n background:linear-gradient(180deg,#123a29,#0b2318); border:2px solid var(--papaya); box-shadow:0 6px 0 var(--papaya-deep), 0 22px 40px -12px #000;\n animation:pop .4s cubic-bezier(.2,1.4,.4,1);\n }\n .eyebrow{font-size:clamp(9px,1.2vw,13px); letter-spacing:.3em; text-transform:uppercase; color:var(--papaya-soft)}\n .card h2{font-size:clamp(18px,3.6vw,40px); margin:.2em 0 .25em; letter-spacing:.04em; color:var(--ivory)}\n .card p{font-size:clamp(10px,1.5vw,16px); color:var(--ivory-dim)}\n .card .hint{margin-top:.9em; font-size:clamp(9px,1.1vw,12px); opacity:.7}\n .cta{\n margin-top:1em; font:inherit; font-weight:800; font-size:clamp(11px,1.6vw,17px); letter-spacing:.12em; text-transform:uppercase; cursor:pointer;\n color:var(--leaf-900); background:var(--papaya); border:0; border-radius:10px; padding:.7em 1.5em; box-shadow:0 4px 0 var(--papaya-deep);\n transition:transform .12s, box-shadow .12s, background .2s;\n }\n .cta:hover{background:var(--papaya-soft)} .cta:active{transform:translateY(3px); box-shadow:0 1px 0 var(--papaya-deep)}\n @keyframes fade{from{opacity:0}to{opacity:1}}\n @keyframes pop{from{transform:scale(.85) translateY(10px); opacity:0}to{transform:none; opacity:1}}\n .pad{user-select:none; -webkit-user-select:none}\n .pad-group{display:flex; gap:10px}\n .pbtn{\n width:clamp(52px,9vw,72px); height:clamp(44px,7vw,56px); border-radius:12px; cursor:pointer; touch-action:none;\n font:inherit; font-weight:800; font-size:12px; letter-spacing:.12em; text-transform:uppercase; color:var(--ivory);\n background:linear-gradient(180deg,#1b4a33,#103424); border:1px solid rgba(251,243,223,.2); box-shadow:0 4px 0 #051009;\n display:flex; align-items:center; justify-content:center; transition:transform .08s, box-shadow .08s, background .15s;\n }\n .pbtn.jump{width:clamp(84px,14vw,120px); background:linear-gradient(180deg,var(--papaya),var(--papaya-deep)); color:var(--leaf-900); border-color:var(--papaya-soft); box-shadow:0 4px 0 #7a2f12}\n .pbtn.on, .pbtn:active{transform:translateY(3px); box-shadow:0 1px 0 #051009}\n .tri{width:0; height:0; border:9px solid transparent}\n .tri.l{border-right-color:var(--ivory); margin-left:-9px} .tri.r{border-left-color:var(--ivory); margin-right:-9px}\n .keys{font-size:11px; color:var(--ivory-dim); letter-spacing:.04em; text-align:center; line-height:1.5}\n .keys b{color:var(--ivory); font-weight:700}\n button:focus-visible{outline:2px solid var(--papaya-soft); outline-offset:3px}\n @media (max-width:620px){ .keys{display:none} .stage{border-radius:6px} .pill span#muteTxt{display:none} .pill{padding:9px} }\n @media (max-height:520px) and (orientation:landscape){\n .top{display:none} .shell{padding:4px; gap:0}\n .stage{width:min(100vw, calc(100vh * 16 / 9)); border-radius:0}\n .pad{position:fixed; left:0; right:0; bottom:8px; width:auto; padding:0 12px; z-index:5; pointer-events:none}\n .pad .pbtn{pointer-events:auto; opacity:.8} .keys{display:none}\n }\n @media (prefers-reduced-motion:reduce){ .prompt span,.card,.overlay,.bump{animation:none} }","replaceAll":false,"isLivePreviewRelated":true}}},{"t":1610604,"name":"aiToolResult","data":{"toolId":45,"isError":false,"preview":"The file {{PROJECT}}/dave-jungle-temple.html has been updated s"}},{"t":1612886,"name":"aiProgress","data":{"toolName":"Edit","toolId":46,"phase":"tool_use"}},{"t":1612886,"name":"aiToolStream","data":{"toolId":46,"toolName":"Edit","append":"{\"file_path\": \"{{PROJECT}}/dave-jungle-temple.html"}},{"t":1613524,"name":"aiToolStream","data":{"toolId":46,"toolName":"Edit","append":"\", \"old_string\": \"/* ==BOOT== */\", \"new_string\": \"/* ==UI: HUD, overlays, touch== */\\nconst $=id=>document.getElementById"}},{"t":1614201,"name":"aiToolStream","data":{"toolId":46,"toolName":"Edit","append":"(id);\\nconst ui={gem:$('gemTxt'),keyChip:$('keyChip'),keyTxt:$('keyTxt'),lives:$('lives'),prompt:$('prompt'),demo:$('dem"}},{"t":1614455,"name":"aiToolStream","data":{"toolId":46,"toolName":"Edit","append":"oTag'),toast:$('toast'),"}},{"t":1614855,"name":"aiToolStream","data":{"toolId":46,"toolName":"Edit","append":"ov:$('overlay'),ovE:$('ovEyebrow'),ovT:$('ovTitle'),ovP:$('ovText'),ovB:$('ovBtn'),mute:$('mu"}},{"t":1615157,"name":"aiToolStream","data":{"toolId":46,"toolName":"Edit","append":"teBtn'),muteTxt:$('muteT"}},{"t":1615521,"name":"aiToolStream","data":{"toolId":46,"toolName":"Edit","append":"xt')};\\n$('icoGem').getContext('2d').drawImage(SP.gem[0],0,0);\\n$('icoKey').getContext('2d').drawImage("}},{"t":1615771,"name":"aiToolStream","data":{"toolId":46,"toolName":"Edit","append":"SP.key,0,0);\\nconst hearts=[0,1,2].map(()=>{ const c=document.createElement('canv"}},{"t":1616150,"name":"aiToolStream","data":{"toolId":46,"toolName":"Edit","append":"as'); c.width=9; c.height=8; c.getContext('2d').drawImage(SP.heart,0,0); "}},{"t":1616456,"name":"aiToolStream","data":{"toolId":46,"toolName":"Edit","append":"ui.lives.appendChild(c); return c; });\\nlet lastGems=-1;\\nsy"}},{"t":1616710,"name":"aiToolStream","data":{"toolId":46,"toolName":"Edit","append":"ncHud=function(){\\n ui.gem.textContent=G.gems+'/'+G.total;\\n if(G.gems"}},{"t":1617017,"name":"aiToolStream","data":{"toolId":46,"toolName":"Edit","append":"!==lastGems && G.gems>0){ const ch=ui.gem.parentN"}},{"t":1617267,"name":"aiToolStream","data":{"toolId":46,"toolName":"Edit","append":"ode; ch.classList.remove('bump'); void ch.offsetWidth; ch."}},{"t":1617522,"name":"aiToolStream","data":{"toolId":46,"toolName":"Edit","append":"classList.add('bump'); } lastGems=G.gems;\\n ui.keyChip.classList.to"}},{"t":1617833,"name":"aiToolStream","data":{"toolId":46,"toolName":"Edit","append":"ggle('has',!!G.hasKey); ui.keyTxt.textContent=G.h"}},{"t":1618084,"name":"aiToolStream","data":{"toolId":46,"toolName":"Edit","append":"asKey?'Key':'No key';\\n hearts.forEach((h,i)=>h.classList.toggle('lost',"}},{"t":1618394,"name":"aiToolStream","data":{"toolId":46,"toolName":"Edit","append":"i>=G.lives));\\n};\\nlet toastTimer=0;\\nshowToast=function(ms"}},{"t":1618644,"name":"aiToolStream","data":{"toolId":46,"toolName":"Edit","append":"g){ if(G.mode==='attract') return; ui.toast.textContent=msg; ui."}},{"t":1618895,"name":"aiToolStream","data":{"toolId":46,"toolName":"Edit","append":"toast.classList.add('show'); clearTimeout(toastTimer); toastTimer=setT"}},{"t":1619150,"name":"aiToolStream","data":{"toolId":46,"toolName":"Edit","append":"imeout(()=>ui.toast.classList.remove('show'),2200); };\\nfunction syncUi(){\\n const dem"}},{"t":1619455,"name":"aiToolStream","data":{"toolId":46,"toolName":"Edit","append":"o=G.mode==='attract', ended=G.mode==='win'||G.mode"}},{"t":1619717,"name":"aiToolStream","data":{"toolId":46,"toolName":"Edit","append":"==='over';\\n ui.prompt.style.display=demo?'':'none'; ui.demo.style.display=demo"}},{"t":1620018,"name":"aiToolStream","data":{"toolId":46,"toolName":"Edit","append":"?'':'none';\\n if(ended){\\n const win"}},{"t":1620270,"name":"aiToolStream","data":{"toolId":46,"toolName":"Edit","append":"=G.mode==='win';\\n ui.ovE.textContent=win?'Temple cleared':'Out"}},{"t":1620580,"name":"aiToolStream","data":{"toolId":46,"toolName":"Edit","append":" of lives';\\n ui.ovT.textContent=win?'You escaped!':'Game over';"}},{"t":1620834,"name":"aiToolStream","data":{"toolId":46,"toolName":"Edit","append":"\\n ui.ovP.textContent=win?('Gems collected: '+G.gems"}},{"t":1621084,"name":"aiToolStream","data":{"toolId":46,"toolName":"Edit","append":"+' of '+G.total+(G.gems===G.total?' — a perfect run!':'')"}},{"t":1621336,"name":"aiToolStream","data":{"toolId":46,"toolName":"Edit","append":"):('The jungle keeps its tre"}},{"t":1621592,"name":"aiToolStream","data":{"toolId":46,"toolName":"Edit","append":"asure… '+G.gems+' of '+G.total+' gems found.');\\n ui.ovB.textContent"}},{"t":1621893,"name":"aiToolStream","data":{"toolId":46,"toolName":"Edit","append":"=win?'Play again':'Try again';\\n }\\n ui.ov.hidden=!ended; if"}},{"t":1622203,"name":"aiToolStream","data":{"toolId":46,"toolName":"Edit","append":"(ended) ui.ovB.focus({preventScroll:true});\\n ui.toast."}},{"t":1622454,"name":"aiToolStream","data":{"toolId":46,"toolName":"Edit","append":"classList.remove('show'); syncHud();\\n}\\nui.ovB.addEventListener('click',"}},{"t":1622704,"name":"aiToolStream","data":{"toolId":46,"toolName":"Edit","append":"e=>{ e.stopPropagation(); restartIfEnded(); });\\n$('st"}},{"t":1622962,"name":"aiToolStream","data":{"toolId":46,"toolName":"Edit","append":"age').addEventListener('pointerdown',e=>{ if(G.mode==='attract'){ tak"}},{"t":1623267,"name":"aiToolStream","data":{"toolId":46,"toolName":"Edit","append":"eControl(); e.preventDefault(); } });\\ndocument.querySelector"}},{"t":1623542,"name":"aiToolStream","data":{"toolId":46,"toolName":"Edit","append":"All('.pbtn').forEach(b=>{ const k=b.dataset.k;\\n const set=(v,e)=>{ ke"}},{"t":1623858,"name":"aiToolStream","data":{"toolId":46,"toolName":"Edit","append":"ys[k]=v; b.classList.toggle('on',v); if(v){ onAnyInput(); try"}},{"t":1624144,"name":"aiToolStream","data":{"toolId":46,"toolName":"Edit","append":"{ b.setPointerCapture(e.pointerId); }catch(_){} } e"}},{"t":1624419,"name":"aiToolStream","data":{"toolId":46,"toolName":"Edit","append":".preventDefault(); };\\n b.addEventListener('pointerdown',e=>set(true,e)); "}},{"t":1624713,"name":"aiToolStream","data":{"toolId":46,"toolName":"Edit","append":"['pointerup','pointercancel','lostpointercapture'].forEach(n=>b.addEventListener(n,e="}},{"t":1625019,"name":"aiToolStream","data":{"toolId":46,"toolName":"Edit","append":">set(false,e)));\\n b.addEventListener('contextmenu',e=>e.preventD"}},{"t":1625270,"name":"aiToolStream","data":{"toolId":46,"toolName":"Edit","append":"efault()); });\\n\\n/* ==AUDIO: tiny bleeps, off until"}},{"t":1625587,"name":"aiToolStream","data":{"toolId":46,"toolName":"Edit","append":" the toggle is pressed== */\\nconst AU={on:false,ac:"}},{"t":1625838,"name":"aiToolStream","data":{"toolId":46,"toolName":"Edit","append":"null};\\nfunction tone(f0,f1,d"}},{"t":1626104,"name":"aiToolStream","data":{"toolId":46,"toolName":"Edit","append":"ur,type,vol,delay){ const ac=AU.ac, t=ac.currentT"}},{"t":1626393,"name":"aiToolStream","data":{"toolId":46,"toolName":"Edit","append":"ime+(delay||0), o=ac.createOscillator(), g=ac.createGain();\\n o.type=type||'square'"}},{"t":1626708,"name":"aiToolStream","data":{"toolId":46,"toolName":"Edit","append":"; o.frequency.setValueAtTime(f0,t); o.frequency.exponentialRampToValueAt"}},{"t":1627016,"name":"aiToolStream","data":{"toolId":46,"toolName":"Edit","append":"Time(Math.max(30,f1),t+dur);\\n g.gain."}},{"t":1627267,"name":"aiToolStream","data":{"toolId":46,"toolName":"Edit","append":"setValueAtTime(vol||.05,t); g.gain.exponentialRampToVal"}},{"t":1627520,"name":"aiToolStream","data":{"toolId":46,"toolName":"Edit","append":"ueAtTime(.0008,t+dur); o.connect(g); g.connect(ac."}},{"t":1627833,"name":"aiToolStream","data":{"toolId":46,"toolName":"Edit","append":"destination); o.start(t); o.stop(t+dur+.02); }\\nconst SFX={"}},{"t":1628508,"name":"aiToolStream","data":{"toolId":46,"toolName":"Edit","append":" jump:()=>tone(300,560,.1), gem:()=>{ tone(880,1320,.07,'triangle',.07); tone(1320"}},{"t":1628771,"name":"aiToolStream","data":{"toolId":46,"toolName":"Edit","append":",1760,.08,'triangle',.05,.06); }, key"}},{"t":1629084,"name":"aiToolStream","data":{"toolId":46,"toolName":"Edit","append":":()=>[660,880,1175].forEach((f,i)=>tone(f,f,.1"}},{"t":1629390,"name":"aiToolStream","data":{"toolId":46,"toolName":"Edit","append":",'square',.05,i*.08)),\\n stomp:()=>tone(220,"}},{"t":1629640,"name":"aiToolStream","data":{"toolId":46,"toolName":"Edit","append":"70,.12), hurt:()=>tone(320,60"}},{"t":1629952,"name":"aiToolStream","data":{"toolId":46,"toolName":"Edit","append":",.3,'sawtooth',.06), locked:()="}},{"t":1630209,"name":"aiToolStream","data":{"toolId":46,"toolName":"Edit","append":">tone(130,110,.14), win:()=>tone(440,880"}},{"t":1630515,"name":"aiToolStream","data":{"toolId":46,"toolName":"Edit","append":",.2,'triangle',.06),\\n fanfare:"}},{"t":1630767,"name":"aiToolStream","data":{"toolId":46,"toolName":"Edit","append":"()=>[523,659,784,1047].forEach((f,i)=>tone(f,f,.16,'square"}},{"t":1631082,"name":"aiToolStream","data":{"toolId":46,"toolName":"Edit","append":"',.05,i*.12)), over:()=>[392,330,262,196].forEach((f"}},{"t":1631393,"name":"aiToolStream","data":{"toolId":46,"toolName":"Edit","append":",i)=>tone(f,f*.97,.2"}},{"t":1631644,"name":"aiToolStream","data":{"toolId":46,"toolName":"Edit","append":",'triangle',.06,i*.16)) };\\nplaySfx=function(n){ if(!AU"}},{"t":1631895,"name":"aiToolStream","data":{"toolId":46,"toolName":"Edit","append":".on||!AU.ac||G.mode==='attract'||!SFX[n]) return; try{ SF"}},{"t":1632206,"name":"aiToolStream","data":{"toolId":46,"toolName":"Edit","append":"X[n](); }catch(_){} };\\nfunction toggleMute(){ AU.on=!AU.on;"}},{"t":1632516,"name":"aiToolStream","data":{"toolId":46,"toolName":"Edit","append":"\\n if(AU.on && !AU.ac){ const A"}},{"t":1632802,"name":"aiToolStream","data":{"toolId":46,"toolName":"Edit","append":"=window.AudioContext||window.webkitAudioContext; if(A) AU.ac=new A(); else AU.on="}},{"t":1633085,"name":"aiToolStream","data":{"toolId":46,"toolName":"Edit","append":"false; }\\n if(AU.on && AU.ac.state==='suspended') AU.ac.resume();\\n ui.m"}},{"t":1633390,"name":"aiToolStream","data":{"toolId":46,"toolName":"Edit","append":"ute.setAttribute('aria-pressed',AU.on?'true':'false'); ui.mute"}},{"t":1633643,"name":"aiToolStream","data":{"toolId":46,"toolName":"Edit","append":"Txt.textContent=AU.on?'Sound on':'Sound off'; if(AU.on){"}},{"t":1633952,"name":"aiToolStream","data":{"toolId":46,"toolName":"Edit","append":" try{ tone(660,990,.08,'triangle',.06); }catch(_"}},{"t":1634267,"name":"aiToolStream","data":{"toolId":46,"toolName":"Edit","append":"){} } }\\nui.mute.addEventListener('click',e=>{ e.st"}},{"t":1634526,"name":"aiToolStream","data":{"toolId":46,"toolName":"Edit","append":"opPropagation(); toggleMute(); ui.mute.blur(); });\\n\\n/* ==BOOT== *"}},{"t":1634894,"name":"aiToolStream","data":{"toolId":46,"toolName":"Edit","append":"/\"}"}},{"t":1634906,"name":"aiToolInfo","data":{"toolName":"Edit","toolId":46,"toolInput":{"file_path":"{{PROJECT}}/dave-jungle-temple.html","old_string":"/* ==BOOT== */","new_string":"/* ==UI: HUD, overlays, touch== */\nconst $=id=>document.getElementById(id);\nconst ui={gem:$('gemTxt'),keyChip:$('keyChip'),keyTxt:$('keyTxt'),lives:$('lives'),prompt:$('prompt'),demo:$('demoTag'),toast:$('toast'),ov:$('overlay'),ovE:$('ovEyebrow'),ovT:$('ovTitle'),ovP:$('ovText'),ovB:$('ovBtn'),mute:$('muteBtn'),muteTxt:$('muteTxt')};\n$('icoGem').getContext('2d').drawImage(SP.gem[0],0,0);\n$('icoKey').getContext('2d').drawImage(SP.key,0,0);\nconst hearts=[0,1,2].map(()=>{ const c=document.createElement('canvas'); c.width=9; c.height=8; c.getContext('2d').drawImage(SP.heart,0,0); ui.lives.appendChild(c); return c; });\nlet lastGems=-1;\nsyncHud=function(){\n ui.gem.textContent=G.gems+'/'+G.total;\n if(G.gems!==lastGems && G.gems>0){ const ch=ui.gem.parentNode; ch.classList.remove('bump'); void ch.offsetWidth; ch.classList.add('bump'); } lastGems=G.gems;\n ui.keyChip.classList.toggle('has',!!G.hasKey); ui.keyTxt.textContent=G.hasKey?'Key':'No key';\n hearts.forEach((h,i)=>h.classList.toggle('lost',i>=G.lives));\n};\nlet toastTimer=0;\nshowToast=function(msg){ if(G.mode==='attract') return; ui.toast.textContent=msg; ui.toast.classList.add('show'); clearTimeout(toastTimer); toastTimer=setTimeout(()=>ui.toast.classList.remove('show'),2200); };\nfunction syncUi(){\n const demo=G.mode==='attract', ended=G.mode==='win'||G.mode==='over';\n ui.prompt.style.display=demo?'':'none'; ui.demo.style.display=demo?'':'none';\n if(ended){\n const win=G.mode==='win';\n ui.ovE.textContent=win?'Temple cleared':'Out of lives';\n ui.ovT.textContent=win?'You escaped!':'Game over';\n ui.ovP.textContent=win?('Gems collected: '+G.gems+' of '+G.total+(G.gems===G.total?' — a perfect run!':'')):('The jungle keeps its treasure… '+G.gems+' of '+G.total+' gems found.');\n ui.ovB.textContent=win?'Play again':'Try again';\n }\n ui.ov.hidden=!ended; if(ended) ui.ovB.focus({preventScroll:true});\n ui.toast.classList.remove('show'); syncHud();\n}\nui.ovB.addEventListener('click',e=>{ e.stopPropagation(); restartIfEnded(); });\n$('stage').addEventListener('pointerdown',e=>{ if(G.mode==='attract'){ takeControl(); e.preventDefault(); } });\ndocument.querySelectorAll('.pbtn').forEach(b=>{ const k=b.dataset.k;\n const set=(v,e)=>{ keys[k]=v; b.classList.toggle('on',v); if(v){ onAnyInput(); try{ b.setPointerCapture(e.pointerId); }catch(_){} } e.preventDefault(); };\n b.addEventListener('pointerdown',e=>set(true,e)); ['pointerup','pointercancel','lostpointercapture'].forEach(n=>b.addEventListener(n,e=>set(false,e)));\n b.addEventListener('contextmenu',e=>e.preventDefault()); });\n\n/* ==AUDIO: tiny bleeps, off until the toggle is pressed== */\nconst AU={on:false,ac:null};\nfunction tone(f0,f1,dur,type,vol,delay){ const ac=AU.ac, t=ac.currentTime+(delay||0), o=ac.createOscillator(), g=ac.createGain();\n o.type=type||'square'; o.frequency.setValueAtTime(f0,t); o.frequency.exponentialRampToValueAtTime(Math.max(30,f1),t+dur);\n g.gain.setValueAtTime(vol||.05,t); g.gain.exponentialRampToValueAtTime(.0008,t+dur); o.connect(g); g.connect(ac.destination); o.start(t); o.stop(t+dur+.02); }\nconst SFX={ jump:()=>tone(300,560,.1), gem:()=>{ tone(880,1320,.07,'triangle',.07); tone(1320,1760,.08,'triangle',.05,.06); }, key:()=>[660,880,1175].forEach((f,i)=>tone(f,f,.1,'square',.05,i*.08)),\n stomp:()=>tone(220,70,.12), hurt:()=>tone(320,60,.3,'sawtooth',.06), locked:()=>tone(130,110,.14), win:()=>tone(440,880,.2,'triangle',.06),\n fanfare:()=>[523,659,784,1047].forEach((f,i)=>tone(f,f,.16,'square',.05,i*.12)), over:()=>[392,330,262,196].forEach((f,i)=>tone(f,f*.97,.2,'triangle',.06,i*.16)) };\nplaySfx=function(n){ if(!AU.on||!AU.ac||G.mode==='attract'||!SFX[n]) return; try{ SFX[n](); }catch(_){} };\nfunction toggleMute(){ AU.on=!AU.on;\n if(AU.on && !AU.ac){ const A=window.AudioContext||window.webkitAudioContext; if(A) AU.ac=new A(); else AU.on=false; }\n if(AU.on && AU.ac.state==='suspended') AU.ac.resume();\n ui.mute.setAttribute('aria-pressed',AU.on?'true':'false'); ui.muteTxt.textContent=AU.on?'Sound on':'Sound off'; if(AU.on){ try{ tone(660,990,.08,'triangle',.06); }catch(_){} } }\nui.mute.addEventListener('click',e=>{ e.stopPropagation(); toggleMute(); ui.mute.blur(); });\n\n/* ==BOOT== */"}}},{"t":1634982,"name":"aiToolEdit","data":{"toolId":46,"edit":{"file":"{{PROJECT}}/dave-jungle-temple.html","oldText":"/* ==BOOT== */","newText":"/* ==UI: HUD, overlays, touch== */\nconst $=id=>document.getElementById(id);\nconst ui={gem:$('gemTxt'),keyChip:$('keyChip'),keyTxt:$('keyTxt'),lives:$('lives'),prompt:$('prompt'),demo:$('demoTag'),toast:$('toast'),ov:$('overlay'),ovE:$('ovEyebrow'),ovT:$('ovTitle'),ovP:$('ovText'),ovB:$('ovBtn'),mute:$('muteBtn'),muteTxt:$('muteTxt')};\n$('icoGem').getContext('2d').drawImage(SP.gem[0],0,0);\n$('icoKey').getContext('2d').drawImage(SP.key,0,0);\nconst hearts=[0,1,2].map(()=>{ const c=document.createElement('canvas'); c.width=9; c.height=8; c.getContext('2d').drawImage(SP.heart,0,0); ui.lives.appendChild(c); return c; });\nlet lastGems=-1;\nsyncHud=function(){\n ui.gem.textContent=G.gems+'/'+G.total;\n if(G.gems!==lastGems && G.gems>0){ const ch=ui.gem.parentNode; ch.classList.remove('bump'); void ch.offsetWidth; ch.classList.add('bump'); } lastGems=G.gems;\n ui.keyChip.classList.toggle('has',!!G.hasKey); ui.keyTxt.textContent=G.hasKey?'Key':'No key';\n hearts.forEach((h,i)=>h.classList.toggle('lost',i>=G.lives));\n};\nlet toastTimer=0;\nshowToast=function(msg){ if(G.mode==='attract') return; ui.toast.textContent=msg; ui.toast.classList.add('show'); clearTimeout(toastTimer); toastTimer=setTimeout(()=>ui.toast.classList.remove('show'),2200); };\nfunction syncUi(){\n const demo=G.mode==='attract', ended=G.mode==='win'||G.mode==='over';\n ui.prompt.style.display=demo?'':'none'; ui.demo.style.display=demo?'':'none';\n if(ended){\n const win=G.mode==='win';\n ui.ovE.textContent=win?'Temple cleared':'Out of lives';\n ui.ovT.textContent=win?'You escaped!':'Game over';\n ui.ovP.textContent=win?('Gems collected: '+G.gems+' of '+G.total+(G.gems===G.total?' — a perfect run!':'')):('The jungle keeps its treasure… '+G.gems+' of '+G.total+' gems found.');\n ui.ovB.textContent=win?'Play again':'Try again';\n }\n ui.ov.hidden=!ended; if(ended) ui.ovB.focus({preventScroll:true});\n ui.toast.classList.remove('show'); syncHud();\n}\nui.ovB.addEventListener('click',e=>{ e.stopPropagation(); restartIfEnded(); });\n$('stage').addEventListener('pointerdown',e=>{ if(G.mode==='attract'){ takeControl(); e.preventDefault(); } });\ndocument.querySelectorAll('.pbtn').forEach(b=>{ const k=b.dataset.k;\n const set=(v,e)=>{ keys[k]=v; b.classList.toggle('on',v); if(v){ onAnyInput(); try{ b.setPointerCapture(e.pointerId); }catch(_){} } e.preventDefault(); };\n b.addEventListener('pointerdown',e=>set(true,e)); ['pointerup','pointercancel','lostpointercapture'].forEach(n=>b.addEventListener(n,e=>set(false,e)));\n b.addEventListener('contextmenu',e=>e.preventDefault()); });\n\n/* ==AUDIO: tiny bleeps, off until the toggle is pressed== */\nconst AU={on:false,ac:null};\nfunction tone(f0,f1,dur,type,vol,delay){ const ac=AU.ac, t=ac.currentTime+(delay||0), o=ac.createOscillator(), g=ac.createGain();\n o.type=type||'square'; o.frequency.setValueAtTime(f0,t); o.frequency.exponentialRampToValueAtTime(Math.max(30,f1),t+dur);\n g.gain.setValueAtTime(vol||.05,t); g.gain.exponentialRampToValueAtTime(.0008,t+dur); o.connect(g); g.connect(ac.destination); o.start(t); o.stop(t+dur+.02); }\nconst SFX={ jump:()=>tone(300,560,.1), gem:()=>{ tone(880,1320,.07,'triangle',.07); tone(1320,1760,.08,'triangle',.05,.06); }, key:()=>[660,880,1175].forEach((f,i)=>tone(f,f,.1,'square',.05,i*.08)),\n stomp:()=>tone(220,70,.12), hurt:()=>tone(320,60,.3,'sawtooth',.06), locked:()=>tone(130,110,.14), win:()=>tone(440,880,.2,'triangle',.06),\n fanfare:()=>[523,659,784,1047].forEach((f,i)=>tone(f,f,.16,'square',.05,i*.12)), over:()=>[392,330,262,196].forEach((f,i)=>tone(f,f*.97,.2,'triangle',.06,i*.16)) };\nplaySfx=function(n){ if(!AU.on||!AU.ac||G.mode==='attract'||!SFX[n]) return; try{ SFX[n](); }catch(_){} };\nfunction toggleMute(){ AU.on=!AU.on;\n if(AU.on && !AU.ac){ const A=window.AudioContext||window.webkitAudioContext; if(A) AU.ac=new A(); else AU.on=false; }\n if(AU.on && AU.ac.state==='suspended') AU.ac.resume();\n ui.mute.setAttribute('aria-pressed',AU.on?'true':'false'); ui.muteTxt.textContent=AU.on?'Sound on':'Sound off'; if(AU.on){ try{ tone(660,990,.08,'triangle',.06); }catch(_){} } }\nui.mute.addEventListener('click',e=>{ e.stopPropagation(); toggleMute(); ui.mute.blur(); });\n\n/* ==BOOT== */","replaceAll":false,"isLivePreviewRelated":true}}},{"t":1634984,"name":"aiToolResult","data":{"toolId":46,"isError":false,"preview":"The file {{PROJECT}}/dave-jungle-temple.html has been updated s"}},{"t":1640167,"name":"aiProgress","data":{"toolName":"Bash","toolId":47,"phase":"tool_use"}},{"t":1640168,"name":"aiToolStream","data":{"toolId":47,"toolName":"Bash","append":"{\"command\": \"which node &&"}},{"t":1640502,"name":"aiToolStream","data":{"toolId":47,"toolName":"Bash","append":" node --version\", \"description\": \"Check whether Node is available\"}"}},{"t":1640522,"name":"aiToolInfo","data":{"toolName":"Bash","toolId":47,"toolInput":{"command":"which node && node --version","description":"Check whether Node is available"}}},{"t":1640631,"name":"aiToolResult","data":{"toolId":47,"isError":false,"preview":""}},{"t":1660672,"name":"aiProgress","data":{"toolName":"Write","toolId":49,"phase":"tool_use"}},{"t":1660673,"name":"aiToolStream","data":{"toolId":49,"toolName":"Write","append":"{\"file_path\": \"/tmp/davesim/sim.js\", \"content\": \"const fs=require('fs');\\nconst html=fs.readFileSync('"}},{"t":1661307,"name":"aiToolStream","data":{"toolId":49,"toolName":"Write","append":"{{PROJECT}}/dave-jungle-temple.html','utf8');\\nlet src=html.match(/