Models 44

Muse Ember

Open in new window

Running live in a sandboxed frame. Click inside it before using the keyboard.

How it went

Total time
20.2 s
Cost
$0.0054
Output tokens
10,808
Spent thinking
2,788 tokens
Speed
599.8 tok/s
Console errors
0
First token after
2.1 s
First visible text after
9.3 s
Prompt tokens
375
Code size
22.6 KB
Finish reason
stop
Served by
Meta
Model id
meta/muse-ember
Reasoning sent
{"effort":"high"}
Max output
943,718 tokens
Generated
Nov 12, 2026

What it was asked

The prompt
“i want a breakout game where the paddle is a hamburger and every brick you break explodes into tons of little hearts”
System prompt, sent with every prompt
You are generating a self-contained web demo. It will be rendered automatically in a sandboxed iframe and compared side by side with the output of other AI models given the exact same task.

Output rules:
- Reply with exactly ONE fenced code block containing the complete file: ```html (or ```svg when the task asks for an SVG). No text before or after the code block.
- Everything must be inline: CSS in <style>, JavaScript in <script>. No external files, images, fonts or network requests, except the CDN URLs explicitly allowed by the task.
- Do not use localStorage, sessionStorage, cookies, IndexedDB, alert(), confirm(), prompt() or window.open(): they are blocked in the sandbox and will throw.
- The page must look right in a 1280×800 viewport and adapt gracefully down to 375px wide. No horizontal scrollbar.
- Something meaningful must be visible on first paint: a screenshot is taken automatically about 3 seconds after load, without any interaction.
- Everything that makes the demo interesting must be visible within the first seconds: nothing hidden behind a high score, a later level or a long play session.
- Games must start in a self-playing demo mode (a simple AI plays) behind a "Click or press a key to start" message, so the game can be judged in action without playing.
- The iframe only receives keyboard events after the user clicks it: if the demo uses the keyboard, display a clear "Click or press a key to start" message.
- The code must run with zero errors in the console of the latest Chrome.

Code run-1.html · 513 lines

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>Hamburger Breakout — Heart Burst</title>
<style>
  *{box-sizing:border-box;margin:0;padding:0}
  html,body{width:100%;min-height:100%}
  body{
    font-family:system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;
    background:linear-gradient(135deg,#fff1f3 0%,#ffe9c9 48%,#ffd6e0 100%);
    color:#432818;
    overflow-x:hidden;
    padding:14px 12px 20px;
  }
  .wrap{max-width:960px;margin:0 auto}
  header{
    display:flex;align-items:center;justify-content:space-between;gap:14px;flex-wrap:wrap;
    margin-bottom:10px;
  }
  .logo{display:flex;align-items:center;gap:11px}
  .burger-ico{
    width:56px;height:56px;border-radius:18px;background:#fff;
    box-shadow:0 6px 0 #ffb3c1,0 12px 24px rgba(244,114,143,.35);
    display:grid;place-items:center;font-size:34px;line-height:1;
    transform:rotate(-3deg);
  }
  h1{
    font-size:clamp(24px,4.5vw,38px);line-height:.9;font-weight:950;letter-spacing:-.03em;
    color:#c9184a;text-transform:uppercase;
  }
  h1 span{display:block;color:#7a4a21;font-size:.52em;letter-spacing:.14em;margin-top:3px}
  .tag{
    background:#c9184a;color:#fff;font-weight:900;font-size:12px;letter-spacing:.08em;
    padding:8px 11px;border-radius:999px;box-shadow:0 4px 0 #590d22;white-space:nowrap;
  }
  .hud{
    display:grid;grid-template-columns:repeat(4,1fr);gap:8px;margin-bottom:10px;
  }
  .card{
    background:#fff;border:2px solid #432818;border-radius:16px;
    padding:8px 10px;box-shadow:0 4px 0 #432818;
    min-width:0;
  }
  .card label{font-size:10px;font-weight:900;letter-spacing:.14em;color:#ff5a7a;display:block;line-height:1}
  .card strong{font-size:clamp(18px,3vw,24px);font-weight:950;letter-spacing:-.02em;display:block;margin-top:2px;white-space:nowrap}
  .card strong.heart{color:#ff2a5f;font-size:18px;letter-spacing:1px}
  .stage{
    position:relative;background:#fff7e8;border:3px solid #432818;border-radius:24px;
    box-shadow:0 8px 0 #432818,0 22px 40px rgba(122,74,33,.22);
    overflow:hidden;
  }
  canvas{display:block;width:100%;height:auto;background:linear-gradient(180deg,#fff3d6 0%,#ffe5ec 58%,#ffc8dd 100%);touch-action:none;cursor:pointer}
  #overlay{
    position:absolute;inset:0;display:flex;align-items:center;justify-content:center;
    background:rgba(255,244,220,.42);backdrop-filter:blur(2px);z-index:5;padding:14px;
  }
  #overlay.hidden{display:none}
  .panel{
    background:#fff;border:3px solid #432818;border-radius:22px;box-shadow:0 7px 0 #432818;
    max-width:520px;width:100%;text-align:center;padding:20px 18px 16px;
  }
  .panel .big{font-size:34px;line-height:1}
  .panel h2{font-size:clamp(24px,5vw,36px);font-weight:950;letter-spacing:-.03em;color:#c9184a;line-height:.95;margin:6px 0 6px;text-transform:uppercase}
  .panel h2 em{font-style:normal;color:#f59e0b}
  .panel p{font-size:14px;line-height:1.45;color:#5c3d2e;font-weight:600}
  .panel p b{color:#c9184a}
  .keys{margin:12px auto 0;display:flex;gap:6px;justify-content:center;flex-wrap:wrap}
  .keys span{background:#fff1f3;border:2px solid #432818;border-radius:999px;padding:5px 9px;font-size:11px;font-weight:900}
  .btns{display:flex;gap:8px;justify-content:center;flex-wrap:wrap;margin-top:14px}
  button{
    font-family:inherit;font-weight:950;letter-spacing:.02em;border:2px solid #432818;border-radius:999px;
    padding:11px 18px;font-size:15px;cursor:pointer;box-shadow:0 4px 0 #432818;transition:transform .08s,box-shadow .08s;
    background:#ff2a5f;color:#fff;
  }
  button:active{transform:translateY(3px);box-shadow:0 1px 0 #432818}
  button.alt{background:#ffb703;color:#432818}
  .controls{
    display:flex;gap:8px;align-items:center;justify-content:space-between;flex-wrap:wrap;margin-top:10px;
  }
  .hint{font-size:13px;font-weight:700;color:#6b4230;background:rgba(255,255,255,.75);border:2px solid rgba(67,40,24,.18);padding:9px 11px;border-radius:999px}
  .mini{display:flex;gap:7px}
  .mini button{padding:9px 14px;font-size:13px;background:#fff;color:#432818}
  .mini button.primary{background:#ff2a5f;color:#fff}
  .progress{height:12px;background:#fff;border:2px solid #432818;border-radius:999px;overflow:hidden;margin-top:10px;box-shadow:0 3px 0 #432818}
  .progress i{display:block;height:100%;width:0%;background:repeating-linear-gradient(45deg,#ff2a5f 0 10px,#ff8fab 10px 20px);transition:width .25s}
  @media (max-width:560px){
    body{padding:10px 8px 16px}
    .hud{grid-template-columns:1fr 1fr}
    .burger-ico{width:46px;height:46px;font-size:28px;border-radius:15px}
    .tag{display:none}
    .panel{padding:16px 12px 13px}
    .hint{font-size:12px}
  }
</style>
</head>
<body>
<div class="wrap">
  <header>
    <div class="logo">
      <div class="burger-ico">🍔</div>
      <h1>Hamburger<br>Breakout <span>★ HEART BURST EDITION ★</span></h1>
    </div>
    <div class="tag">BREAK A BRICK = HEART EXPLOSION!</div>
  </header>

  <div class="hud">
    <div class="card"><label>SCORE</label><strong id="score">0</strong></div>
    <div class="card"><label>HEARTS BURST</label><strong id="hearts">0</strong></div>
    <div class="card"><label>LEVEL</label><strong id="level">1</strong></div>
    <div class="card"><label>LIVES</label><strong class="heart" id="lives">♥♥♥</strong></div>
  </div>

  <div class="stage">
    <canvas id="game" width="900" height="620"></canvas>
    <div id="overlay">
      <div class="panel" id="panel">
        <div class="big">🍔💥❤️</div>
        <h2>Hamburger<br><em>Breakout</em></h2>
        <p>Your paddle is a <b>delicious hamburger</b>!<br>Smash every brick and watch it <b>explode into tons of little hearts</b>. Catch golden hearts for extra life.</p>
        <div class="keys"><span>🖱️ MOUSE / TOUCH</span><span>← → ARROWS</span><span>SPACE = LAUNCH</span><span>P = PAUSE</span></div>
        <div class="btns"><button id="playBtn">▶ &nbsp;PLAY NOW</button></div>
        <p style="margin-top:10px;font-size:12px;opacity:.75">Demo is playing behind this card — click anywhere to take control!</p>
      </div>
    </div>
  </div>

  <div class="progress"><i id="bar"></i></div>

  <div class="controls">
    <div class="hint">Move the burger to bounce the tomato ball. Golden ♥ = +1 life!</div>
    <div class="mini">
      <button id="pauseBtn">⏸ Pause</button>
      <button id="restartBtn" class="primary">↺ Restart</button>
    </div>
  </div>
</div>

<script>
const canvas = document.getElementById('game');
const ctx = canvas.getContext('2d');
const W = 900, H = 620;
const $ = id => document.getElementById(id);
const overlay = $('overlay'), panel = $('panel');

let state = 'demo'; // demo | playing | paused | over
let score = 0, heartsBurst = 0, level = 1, lives = 3, totalBricks = 1;
let bricks = [], particles = [], popups = [], powerups = [], trail = [], ambient = [];
let keys = {}, mouseX = null, paddleVX = 0, frame = 0, clearTimer = 0;
let audioCtx = null;

const paddle = { x: W/2-62, y: H-48, w: 124, h: 38, tilt: 0 };
const ball = { x: W/2, y: H-62, r: 11, vx: 0, vy: 0, speed: 5.4, stuck: true };

const brickColors = ['#ff2a5f','#ff7a18','#ffb703','#2ec4b6','#4361ee','#9b5de5','#f15bb5'];
const heartColors = ['#ff2a5f','#ff5a7a','#ff8fab','#ff4d6d','#fb6f92','#ff0a54','#ff758f','#ffb3c1','#ffd166'];
const phrases = ['YUM!','LOVE!','SWEET!','POP!','HEART BURST!','DELICIOUS!','♥ POP!'];

function rr(c,x,y,w,h,r){
  r=Math.min(r,w/2,h/2);
  c.beginPath();
  c.moveTo(x+r,y);c.lineTo(x+w-r,y);c.quadraticCurveTo(x+w,y,x+w,y+r);
  c.lineTo(x+w,y+h-r);c.quadraticCurveTo(x+w,y+h,x+w-r,y+h);
  c.lineTo(x+r,y+h);c.quadraticCurveTo(x,y+h,x,y+h-r);
  c.lineTo(x,y+r);c.quadraticCurveTo(x,y,x+r,y);c.closePath();
}
function heartPath(c,x,y,s,rot){
  c.save();c.translate(x,y);c.rotate(rot);c.scale(s,s);
  c.beginPath();
  c.moveTo(0,4);
  c.bezierCurveTo(-7,-3,-10,-1,-10,2.5);
  c.bezierCurveTo(-10,6,-5,9,0,13);
  c.bezierCurveTo(5,9,10,6,10,2.5);
  c.bezierCurveTo(10,-1,7,-3,0,4);
  c.closePath();c.restoreNode ? null : null;
  c.restore();
}
function drawHeart(c,x,y,s,rot,color,alpha=1){
  c.save();c.globalAlpha=alpha;c.translate(x,y);c.rotate(rot);c.scale(s,s);
  c.fillStyle=color;
  c.beginPath();
  c.moveTo(0,4);
  c.bezierCurveTo(-7,-3,-10,-1,-10,2.5);
  c.bezierCurveTo(-10,6,-5,9,0,13);
  c.bezierCurveTo(5,9,10,6,10,2.5);
  c.bezierCurveTo(10,-1,7,-3,0,4);
  c.closePath();c.fill();
  c.fillStyle='rgba(255,255,255,.55)';
  c.beginPath();c.ellipse(-3,2,2.4,1.5,-.6,0,7);c.fill();
  c.restore();
}
function playTone(f,d=0.07,type='sine',v=0.12){
  try{
    if(!audioCtx) audioCtx = new (window.AudioContext||window.webkitAudioContext)();
    if(audioCtx.state==='suspended') audioCtx.resume();
    const o=audioCtx.createOscillator(), g=audioCtx.createGain();
    o.type=type;o.frequency.value=f;g.gain.value=v;
    g.gain.exponentialRampToValueAtTime(.001,audioCtx.currentTime+d);
    o.connect(g);g.connect(audioCtx.destination);o.start();o.stop(audioCtx.currentTime+d);
  }catch(e){}
}
function buildBricks(lv){
  bricks=[]; powerups=[]; 
  const cols=9, rows=Math.min(4+lv,7);
  const left=38, top=78, gap=8;
  const bw=(W-left*2-(cols-1)*gap)/cols, bh=26;
  for(let r=0;r<rows;r++){
    for(let c=0;c<cols;c++){
      bricks.push({x:left+c*(bw+gap),y:top+r*(bh+gap),w:bw,h:bh,color:brickColors[r%brickColors.length],alive:true,rr:r,cc:c});
    }
  }
  totalBricks=bricks.length;
  updateHUD();
}
function resetBall(stuck=true){
  ball.x=paddle.x+paddle.w/2; ball.y=paddle.y-16; ball.vx=0; ball.vy=0;
  ball.speed=5.1+level*0.35; ball.stuck=stuck; trail=[];
  if(!stuck) launchBall();
}
function launchBall(){
  if(!ball.stuck) return;
  const a=(-55-Math.random()*20)*Math.PI/180;
  ball.vx=Math.cos(a)*ball.speed; ball.vy=Math.sin(a)*ball.speed; ball.stuck=false;
}
function spawnHearts(x,y,n=36,gold=false){
  for(let i=0;i<n;i++){
    const a=Math.random()*Math.PI*2, sp=1.2+Math.random()*6.2;
    const col=gold?'#ffb703':heartColors[Math.floor(Math.random()*heartColors.length)];
    particles.push({
      x,y,vx:Math.cos(a)*sp,vy:Math.sin(a)*sp-1.4,
      s:0.55+Math.random()*1.05,rot:Math.random()*Math.PI*2,vr:(Math.random()-.5)*.28,
      life:0,max:55+Math.random()*55,color:col,gold
    });
  }
  // crumbs
  for(let i=0;i<10;i++){
    particles.push({x,y,vx:(Math.random()-.5)*6,vy:-Math.random()*4,s:.25+Math.random()*.4,rot:0,vr:.2,life:0,max:35,color:'#7a4a21',crumb:true});
  }
  heartsBurst += n;
}
function popup(x,y,text,color='#c9184a'){
  popups.push({x,y,text,color,life:0});
}
function updateHUD(){
  $('score').textContent=score;
  $('hearts').textContent=heartsBurst;
  $('level').textContent=level;
  $('lives').textContent='♥'.repeat(Math.max(0,lives))||'—';
  const alive=bricks.filter(b=>b.alive).length;
  $('bar').style.width=(totalBricks?((totalBricks-alive)/totalBricks*100):0)+'%';
}
function startGame(){
  score=0;heartsBurst=0;level=1;lives=3;
  buildBricks(level); resetBall(true);
  state='playing'; overlay.classList.add('hidden'); updateHUD(); playTone(660,.1,'triangle',.14);
  popup(W/2,260,'GO! 🍔','#c9184a');
}
function gameOver(){
  state='over';
  panel.innerHTML=`<div class="big">💔🍔</div><h2>Game<br><em>Over!</em></h2>
  <p>You burst <b>${heartsBurst} hearts</b> and scored <b>${score}</b> points!<br>The burger is a little tired… want another bite?</p>
  <div class="btns"><button id="againBtn">↺ &nbsp;PLAY AGAIN</button></div>`;
  overlay.classList.remove('hidden');
  $('againBtn').onclick=e=>{e.stopPropagation();startGame();};
}
function pauseToggle(){
  if(state==='playing'){state='paused';panel.innerHTML=`<div class="big">⏸️🍔</div><h2>Paused</h2><p>Take a breather. The burger is waiting!</p><div class="btns"><button id="resumeBtn">▶ Resume</button><button id="quitBtn" class="alt">Restart</button></div>`;overlay.classList.remove('hidden');$('resumeBtn').onclick=e=>{e.stopPropagation();state='playing';overlay.classList.add('hidden')};$('quitBtn').onclick=e=>{e.stopPropagation();startGame()};}
  else if(state==='paused'){state='playing';overlay.classList.add('hidden');}
}
overlay.addEventListener('click',()=>{ if(state==='demo'||state==='over') startGame(); });
$('playBtn').addEventListener('click',e=>{e.stopPropagation();startGame();});
$('pauseBtn').addEventListener('click',()=>{ if(state==='playing'||state==='paused') pauseToggle(); });
$('restartBtn').addEventListener('click',startGame);

function canvasX(clientX){
  const r=canvas.getBoundingClientRect();
  return (clientX-r.left)/r.width*W;
}
canvas.addEventListener('mousemove',e=>{mouseX=canvasX(e.clientX);});
canvas.addEventListener('click',()=>{ if(state==='demo') startGame(); else if(state==='playing') launchBall(); });
canvas.addEventListener('touchstart',e=>{e.preventDefault(); mouseX=canvasX(e.touches[0].clientX); if(state==='demo') startGame(); else launchBall();},{passive:false});
canvas.addEventListener('touchmove',e=>{e.preventDefault(); mouseX=canvasX(e.touches[0].clientX);},{passive:false});

window.addEventListener('keydown',e=>{
  if(['ArrowLeft','ArrowRight','Space'].includes(e.code)) e.preventDefault();
  keys[e.code]=true;
  if(state==='demo' && (e.code==='Space'||e.code==='Enter')) startGame();
  else if(state==='over' && e.code==='Enter') startGame();
  else if(state==='playing' && e.code==='Space') launchBall();
  if(e.code==='KeyP'||e.code==='Escape'){ if(state==='playing'||state==='paused') pauseToggle(); }
});
window.addEventListener('keyup',e=>keys[e.code]=false);

// ambient background hearts
for(let i=0;i<16;i++) ambient.push({x:Math.random()*W,y:Math.random()*H,s:.5+Math.random()*1.1,vy:.18+Math.random()*.35,rot:Math.random()*6,color:heartColors[i%heartColors.length]});

function drawBurger(){
  const {x,y,w,h}=paddle;
  ctx.save();
  ctx.translate(x+w/2,y+h/2); ctx.rotate(paddle.tilt); ctx.translate(-w/2,-h/2);
  ctx.shadowColor='rgba(67,40,24,.35)';ctx.shadowBlur=8;ctx.shadowOffsetY=5;
  // bottom bun
  ctx.fillStyle='#f4a950'; rr(ctx,5,26,w-10,11,5); ctx.fill();
  ctx.fillStyle='#7a4a21'; rr(ctx,3,20,w-6,8,4); ctx.fill();
  ctx.fillStyle='#ffd166'; rr(ctx,3,17,w-6,5,3); ctx.fill(); // cheese
  ctx.fillStyle='#ff3b30'; rr(ctx,6,13,w-12,6,3); ctx.fill(); // tomato
  // lettuce wavy
  ctx.fillStyle='#6ac84f'; ctx.beginPath();
  ctx.moveTo(0,12);
  for(let i=0;i<=10;i++){ ctx.quadraticCurveTo(i*(w/10)+w/20, i%2?18:10, (i+1)*(w/10),12); }
  ctx.lineTo(w,15); ctx.lineTo(0,15); ctx.closePath(); ctx.fill();
  // top bun dome
  ctx.shadowBlur=0;
  ctx.fillStyle='#ffb84d';
  ctx.beginPath();
  ctx.moveTo(2,14); ctx.lineTo(2,9);
  ctx.bezierCurveTo(2,1,w*0.28,-2,w/2,-2);
  ctx.bezierCurveTo(w*0.72,-2,w-2,1,w-2,9);
  ctx.lineTo(w-2,14); ctx.closePath(); ctx.fill();
  ctx.strokeStyle='rgba(122,74,33,.55)';ctx.lineWidth=1.5;ctx.stroke();
  // sesame
  ctx.fillStyle='#fff3d6';
  for(let i=0;i<6;i++){ const sx=16+i*(w-32)/5, sy=5+Math.sin(i*1.7)*2; ctx.beginPath(); ctx.ellipse(sx,sy,5,2.4,.5,0,7); ctx.fill(); }
  // face on top bun - cute!
  ctx.fillStyle='#432818';
  ctx.beginPath();ctx.arc(w/2-13,9,2.2,0,7);ctx.arc(w/2+13,9,2.2,0,7);ctx.fill();
  ctx.strokeStyle='#432818';ctx.lineWidth=1.8;ctx.beginPath();ctx.arc(w/2,10,7,.2,Math.PI-.2);ctx.stroke();
  ctx.restore();
}
function drawBall(){
  trail.push({x:ball.x,y:ball.y}); if(trail.length>10) trail.shift();
  trail.forEach((t,i)=>{ ctx.globalAlpha=i/10*.35; drawHeart(ctx,t.x,t.y,.55,0,'#ff8fab'); });
  ctx.globalAlpha=1;
  // tomato ball
  const g=ctx.createRadialGradient(ball.x-4,ball.y-4,2,ball.x,ball.y,ball.r);
  g.addColorStop(0,'#ff8fab'); g.addColorStop(.4,'#ff2a5f'); g.addColorStop(1,'#c9184a');
  ctx.fillStyle=g; ctx.shadowColor='rgba(201,24,74,.4)';ctx.shadowBlur=8;ctx.shadowOffsetY=3;
  ctx.beginPath();ctx.arc(ball.x,ball.y,ball.r,0,7);ctx.fill(); ctx.shadowBlur=0;
  ctx.fillStyle='#2ec4b6';
  ctx.beginPath();ctx.ellipse(ball.x,ball.y-ball.r+1,7,3,0,0,7);ctx.fill();
  ctx.fillStyle='rgba(255,255,255,.75)';ctx.beginPath();ctx.ellipse(ball.x-4,ball.y-4,3.5,2,-.6,0,7);ctx.fill();
  // cute face
  ctx.fillStyle='#fff';ctx.beginPath();ctx.arc(ball.x-3.5,ball.y+1,1.9,0,7);ctx.arc(ball.x+3.5,ball.y+1,1.9,0,7);ctx.fill();
  ctx.fillStyle='#432818';ctx.beginPath();ctx.arc(ball.x-3.5,ball.y+1,1,0,7);ctx.arc(ball.x+3.5,ball.y+1,1,0,7);ctx.fill();
}
function drawBricks(){
  bricks.forEach(b=>{
    if(!b.alive) return;
    ctx.save();
    ctx.shadowColor='rgba(67,40,24,.25)';ctx.shadowBlur=5;ctx.shadowOffsetY=3;
    ctx.fillStyle=b.color; rr(ctx,b.x,b.y,b.w,b.h,8); ctx.fill();
    ctx.shadowBlur=0;
    ctx.fillStyle='rgba(255,255,255,.38)'; rr(ctx,b.x+4,b.y+3,b.w-8,8,5); ctx.fill();
    ctx.strokeStyle='rgba(67,40,24,.45)';ctx.lineWidth=1.6; rr(ctx,b.x,b.y,b.w,b.h,8); ctx.stroke();
    drawHeart(ctx,b.x+b.w/2,b.y+b.h/2+1,.62,0,'rgba(255,255,255,.85)',.9);
    ctx.restore();
  });
}
function update(){
  frame++;
  // ambient
  ambient.forEach(a=>{ a.y-=a.vy; a.x+=Math.sin(frame*.02+a.rot)*.3; if(a.y<-20){a.y=H+20;a.x=Math.random()*W;} });

  // paddle control
  let target=null;
  if(state==='demo'){
    if(ball.stuck && frame%90===0) launchBall();
    target = ball.x - paddle.w/2;
    // add slight imperfection
    target += Math.sin(frame*.01)*8;
  } else {
    if(mouseX!==null) target=mouseX-paddle.w/2;
    if(keys.ArrowLeft) target=(target??paddle.x)-11;
    if(keys.ArrowRight) target=(target??paddle.x)+11;
  }
  if(target!==null){
    const old=paddle.x;
    paddle.x += (target-paddle.x)* (state==='demo'?0.16:0.45);
    paddle.x=Math.max(4,Math.min(W-paddle.w-4,paddle.x));
    paddleVX=paddle.x-old;
  } else paddleVX=0;
  paddle.tilt = Math.max(-.12,Math.min(.12,paddleVX*.012));

  if(ball.stuck){ ball.x=paddle.x+paddle.w/2; ball.y=paddle.y-14; }

  // ball physics
  if(!ball.stuck && (state==='playing'||state==='demo')){
    ball.x+=ball.vx; ball.y+=ball.vy;
    const sp=Math.hypot(ball.vx,ball.vy)||1;
    if(sp<ball.speed){ ball.vx*=ball.speed/sp; ball.vy*=ball.speed/sp; }

    if(ball.x<ball.r+2){ball.x=ball.r+2;ball.vx=Math.abs(ball.vx);playTone(300,.05,'square',.06);}
    if(ball.x>W-ball.r-2){ball.x=W-ball.r-2;ball.vx=-Math.abs(ball.vx);playTone(300,.05,'square',.06);}
    if(ball.y<ball.r+2){ball.y=ball.r+2;ball.vy=Math.abs(ball.vy);playTone(300,.05,'square',.06);}

    // paddle collision
    if(ball.vy>0 && ball.y+ball.r>=paddle.y && ball.y+ball.r<=paddle.y+18 && ball.x>=paddle.x-6 && ball.x<=paddle.x+paddle.w+6){
      const rel=Math.max(-1,Math.min(1,(ball.x-(paddle.x+paddle.w/2))/(paddle.w/2)));
      const ang=(-90+rel*62)*Math.PI/180;
      ball.vx=Math.cos(ang)*ball.speed; ball.vy=Math.sin(ang)*ball.speed;
      ball.y=paddle.y-ball.r-1; playTone(520+Math.abs(rel)*200,.07,'triangle',.12);
      spawnHearts(ball.x,paddle.y,3);
    }

    // bricks
    for(const b of bricks){
      if(!b.alive) continue;
      const cx=Math.max(b.x,Math.min(ball.x,b.x+b.w)), cy=Math.max(b.y,Math.min(ball.y,b.y+b.h));
      const dx=ball.x-cx, dy=ball.y-cy;
      if(dx*dx+dy*dy < ball.r*ball.r){
        b.alive=false;
        const bcx=b.x+b.w/2, bcy=b.y+b.h/2;
        // decide bounce axis
        if(Math.abs(ball.x-bcx) > b.w/2-2 && Math.abs(ball.y-bcy) < b.h/2) ball.vx*=-1; else ball.vy*=-1;
        const n=38;
        spawnHearts(bcx,bcy,n);
        score+=50+level*10;
        popup(bcx,bcy-12,phrases[Math.floor(Math.random()*phrases.length)],'#c9184a');
        playTone(700+Math.random()*400,.09,'sine',.14);
        setTimeout(()=>playTone(1000,.08,'sine',.1),40);
        if(Math.random()<0.16) powerups.push({x:bcx,y:bcy,vy:2.2,t:0});
        updateHUD();
        break;
      }
    }

    // bottom
    if(ball.y>H+18){
      if(state==='demo'){ resetBall(true); spawnHearts(paddle.x+paddle.w/2,paddle.y,10); }
      else {
        lives--; updateHUD(); playTone(160,.25,'sawtooth',.12);
        popup(W/2,H-90,'OUCH!','#7a4a21');
        if(lives<=0) gameOver(); else resetBall(true);
      }
    }

    // level clear
    if(bricks.length && bricks.every(b=>!b.alive) && clearTimer===0){
      clearTimer=55; score+=300; popup(W/2,250,'LEVEL CLEAR! +300','#c9184a'); spawnHearts(W/2,260,60,true); updateHUD();
    }
  }

  if(clearTimer>0){ clearTimer--; if(clearTimer===0){ level++; buildBricks(level); resetBall(true); popup(W/2,240,'LEVEL '+level,'#4361ee'); } }

  // powerups
  powerups=powerups.filter(p=>{
    p.y+=p.vy; p.t++;
    if(p.y>paddle.y && p.y<paddle.y+26 && p.x>paddle.x-8 && p.x<paddle.x+paddle.w+8){
      lives=Math.min(5,lives+1); score+=250; popup(p.x,p.y-14,'+1 LIFE! ♥','#ffb703'); spawnHearts(p.x,p.y,26,true); playTone(880,.12,'triangle',.15); updateHUD(); return false;
    }
    return p.y<H+20;
  });

  // particles
  particles=particles.filter(p=>{
    p.life++; p.x+=p.vx; p.y+=p.vy; p.vy+= p.gold?0.02:0.07; p.vx*=0.99; p.rot+=p.vr;
    return p.life<p.max;
  });
  popups=popups.filter(p=>{p.life++;p.y-=.9;return p.life<55;});
}
function draw(){
  ctx.clearRect(0,0,W,H);
  // dotted bg
  ctx.fillStyle='rgba(255,255,255,.45)';
  for(let x=22;x<W;x+=46) for(let y=22;y<H;y+=46){ ctx.beginPath();ctx.arc(x+((y/46)%2)*14,y,2,0,7);ctx.fill(); }
  ambient.forEach(a=>drawHeart(ctx,a.x,a.y,a.s,a.rot*0.1,a.color,.16));
  // top score strip inside canvas
  ctx.fillStyle='rgba(255,255,255,.75)'; rr(ctx,14,14,W-28,44,14); ctx.fill();
  ctx.strokeStyle='rgba(67,40,24,.25)';ctx.lineWidth=2; rr(ctx,14,14,W-28,44,14); ctx.stroke();
  ctx.fillStyle='#432818';ctx.font='900 15px system-ui';ctx.textAlign='left';
  ctx.fillText('🍔 BURGER PADDLE',28,42);
  ctx.textAlign='right'; 
  ctx.fillStyle='#c9184a'; ctx.font='900 20px system-ui';
  ctx.fillText('SCORE '+score,W-28,42);
  ctx.textAlign='center';ctx.font='900 13px system-ui';ctx.fillStyle='#7a4a21';
  const alive=bricks.filter(b=>b.alive).length;
  ctx.fillText('BRICKS '+alive+' / '+totalBricks,W/2,42);

  drawBricks();
  // powerups
  powerups.forEach(p=>{ const bob=Math.sin(p.t*.15)*3; drawHeart(ctx,p.x,p.y+bob,1.35,Math.sin(p.t*.08)*.3,'#ffb703'); ctx.strokeStyle='#7a4a21';ctx.lineWidth=1.5; drawHeart(ctx,p.x,p.y+bob,1.35,Math.sin(p.t*.08)*.3,'#ffb703'); });
  drawBurger();
  drawBall();

  particles.forEach(p=>{
    const a=1-p.life/p.max;
    if(p.crumb){ ctx.save();ctx.globalAlpha=a;ctx.fillStyle=p.color;ctx.translate(p.x,p.y);ctx.rotate(p.rot);ctx.fillRect(-2,-2,4,4);ctx.restore(); }
    else drawHeart(ctx,p.x,p.y,p.s,p.rot,p.color,a);
  });
  popups.forEach(p=>{
    ctx.save();ctx.globalAlpha=1-p.life/55;ctx.font='950 22px system-ui';ctx.textAlign='center';
    ctx.lineWidth=5;ctx.strokeStyle='#fff';ctx.strokeText(p.text,p.x,p.y);
    ctx.fillStyle=p.color;ctx.fillText(p.text,p.x,p.y);ctx.restore();
  });

  if(ball.stuck && state==='playing'){
    ctx.save();ctx.font='900 16px system-ui';ctx.textAlign='center';ctx.fillStyle='#432818';
    ctx.fillText('CLICK OR PRESS SPACE TO LAUNCH!',W/2,paddle.y-34);
    ctx.restore();
  }
  if(state==='paused'){ ctx.fillStyle='rgba(255,255,255,.35)';ctx.fillRect(0,0,W,H); }
}
function loop(){ update(); draw(); requestAnimationFrame(loop); }

// init demo
buildBricks(1);
resetBall(true);
updateHUD();
loop();
</script>
</body>
</html>
Reasoning trace (2,788 tokens)
Designing a single-file responsive canvas breakout with hamburger paddle, heart particles, AI demo mode, and start overlay.Expanding the design with hamburger paddle rendering, heart particle effects, and responsive canvas layout.Adding game states, HUD, input handling, and overlay UI while keeping the canvas responsive.Detailing canvas drawing routines and collision handling for paddle, ball, bricks, and powerups.