Models 44

Nemotron 3.5 Super VL (free)

by NVIDIAReasoningClean
Open in new window

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

How it went

Total time
1 min 10 s
Cost
$0
Output tokens
8,594
Spent thinking
4,608 tokens
Speed
124.4 tok/s
Console errors
0
First token after
546 ms
First visible text after
45.7 s
Prompt tokens
378
Code size
11.3 KB
Finish reason
stop
Served by
Nvidia
Model id
nvidia/nemotron-3.5-super-vl:free
Reasoning sent
model default
Max output
32,000 tokens
Generated
Nov 9, 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 · 496 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</title>
<style>
  * { box-sizing: border-box; }
  html, body {
    margin: 0;
    padding: 0;
    width: 100%;
    height: 100%;
    overflow: hidden;
    background: #1a1a2e;
    font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
    color: #fff;
    touch-action: none;
  }
  #game-container {
    position: relative;
    width: 100%;
    max-width: 800px;
    height: 0;
    aspect-ratio: 4 / 3;
    margin: 0 auto;
    background: #000;
    border-radius: 8px;
    box-shadow: 0 10px 40px rgba(0,0,0,0.6);
    overflow: hidden;
  }
  canvas {
    display: block;
    width: 100%;
    height: 100%;
  }
  #overlay {
    position: absolute;
    inset: 0;
    background: rgba(0,0,0,0.55);
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    z-index: 10;
    cursor: pointer;
    text-align: center;
    padding: 20px;
  }
  #overlay.hidden { display: none; }
  h1 {
    margin: 0 0 12px;
    font-size: clamp(1.5rem, 8vw, 2.5rem);
    color: #ff6b6b;
    text-shadow: 2px 2px 0 #000;
    letter-spacing: 2px;
  }
  p {
    margin: 0;
    font-size: clamp(1rem, 5vw, 1.25rem);
    color: #ffeaa7;
    text-shadow: 1px 1px 0 #000;
  }
  #hud {
    position: absolute;
    top: 10px;
    left: 10px;
    right: 10px;
    display: flex;
    justify-content: space-between;
    font-size: clamp(0.9rem, 4vw, 1.2rem);
    font-weight: bold;
    color: #ffeaa7;
    text-shadow: 1px 1px 0 #000;
    pointer-events: none;
    z-index: 5;
  }
</style>
</head>
<body>

<div id="game-container">
  <div id="hud">
    <div id="score">Score: 0</div>
    <div id="lives">Lives: 3</div>
  </div>
  <canvas id="game" width="800" height="600"></canvas>
  <div id="overlay">
    <h1>Hamburger Breakout</h1>
    <p>Click or press any key to start</p>
  </div>
</div>

<script>
const GAME_W = 800;
const GAME_H = 600;

const canvas = document.getElementById('game');
const ctx = canvas.getContext('2d', { alpha: false });
canvas.width = GAME_W;
canvas.height = GAME_H;

const overlay = document.getElementById('overlay');
const scoreEl = document.getElementById('score');
const livesEl = document.getElementById('lives');

// ---------- Game state ----------
let started = false;
let gameOver = false;
let score = 0;
let lives = 3;

const keys = {};
const mouse = { x: GAME_W / 2, active: false };

// ---------- Entities ----------
const paddle = {
  w: 130,
  h: 42,
  x: GAME_W / 2,
  y: GAME_H - 50,
  speed: 7,
  draw() {
    const cx = this.x;
    const cy = this.y;
    const w = this.w;
    const h = this.h;

    ctx.save();
    ctx.translate(cx, cy);

    // Bottom bun
    ctx.fillStyle = '#8D6E63';
    ctx.strokeStyle = '#5D4037';
    ctx.lineWidth = 2;
    ctx.beginPath();
    ctx.rect(-w/2, h*0.35, w, h*0.55);
    ctx.fill();
    ctx.stroke();

    // Lettuce
    ctx.fillStyle = '#66BB6A';
    ctx.strokeStyle = '#2E7D32';
    ctx.beginPath();
    ctx.rect(-w/2 + 6, h*0.24, w - 12, h*0.22);
    ctx.fill();
    ctx.stroke();

    // Cheese
    ctx.fillStyle = '#FFEB3B';
    ctx.strokeStyle = '#FBC02D';
    ctx.beginPath();
    ctx.rect(-w/2 + 8, h*0.08, w - 16, h*0.18);
    ctx.fill();
    ctx.stroke();

    // Patty
    ctx.fillStyle = '#5D4037';
    ctx.strokeStyle = '#3E2723';
    ctx.beginPath();
    ctx.arc(0, -h*0.05, h*0.38, 0, Math.PI);
    ctx.lineTo(0, -h*0.05);
    ctx.fill();
    ctx.stroke();

    // Top bun
    ctx.fillStyle = '#D2B48C';
    ctx.strokeStyle = '#A67C52';
    ctx.beginPath();
    ctx.arc(0, -h*0.32, h*0.4, Math.PI, 0, true);
    ctx.lineTo(h*0.4, -h*0.32);
    ctx.lineTo(-h*0.4, -h*0.32);
    ctx.fill();
    ctx.stroke();

    // Sesame seeds
    ctx.fillStyle = '#fff';
    const seeds = [
      [-28,-34], [-12,-36], [8,-34], [26,-32],
      [-22,-28], [0,-30], [18,-26],
      [-30,-22], [32,-20]
    ];
    for (const [sx, sy] of seeds) {
      ctx.fillRect(sx, sy, 3, 3);
    }

    ctx.restore();
  }
};

const ball = {
  x: GAME_W / 2,
  y: GAME_H / 2,
  r: 8,
  vx: 0,
  vy: 0,
  speed: 5,
  active: false,
  draw() {
    ctx.beginPath();
    ctx.arc(this.x, this.y, this.r, 0, Math.PI * 2);
    ctx.fillStyle = '#fff';
    ctx.fill();
    ctx.strokeStyle = '#ff4757';
    ctx.lineWidth = 2;
    ctx.stroke();
    ctx.closePath();
  },
  reset() {
    this.x = GAME_W / 2;
    this.y = GAME_H / 2 - 60;
    this.vx = (Math.random() > 0.5 ? 1 : -1) * this.speed;
    this.vy = -this.speed;
    this.active = true;
  }
};

const particles = [];
class Particle {
  constructor(x, y) {
    this.x = x;
    this.y = y;
    const ang = Math.random() * Math.PI * 2;
    const spd = 2 + Math.random() * 7;
    this.vx = Math.cos(ang) * spd;
    this.vy = Math.sin(ang) * spd;
    this.life = 1;
    this.decay = 0.012 + Math.random() * 0.025;
    this.size = 3 + Math.random() * 5;
    const hue = 320 + Math.random() * 40; // pinks/reds
    this.color = `hsl(${hue}, 100%, 60%)`;
  }
  update() {
    this.x += this.vx;
    this.y += this.vy;
    this.vy += 0.18; // gravity
    this.life -= this.decay;
  }
  draw() {
    ctx.save();
    ctx.globalAlpha = Math.max(0, this.life);
    drawHeart(ctx, this.x, this.y, this.size, this.color);
    ctx.restore();
  }
}

function drawHeart(ctx, x, y, s, color) {
  ctx.save();
  ctx.translate(x, y);
  ctx.scale(s, s);
  ctx.fillStyle = color;
  ctx.beginPath();
  ctx.moveTo(0, 0);
  ctx.bezierCurveTo(-1, -1, -2, 0, 0, 2);
  ctx.bezierCurveTo(2, 0, 1, -1, 0, 0);
  ctx.closePath();
  ctx.fill();
  ctx.restore();
}

const bricks = [];
const brickCols = 10;
const brickRows = 6;
const brickW = 64;
const brickH = 20;
const brickGap = 7;
const brickOffsetTop = 55;
const brickOffsetLeft = (GAME_W - (brickCols * (brickW + brickGap) - brickGap)) / 2;

function createBricks() {
  bricks.length = 0;
  for (let r = 0; r < brickRows; r++) {
    for (let c = 0; c < brickCols; c++) {
      const x = brickOffsetLeft + c * (brickW + brickGap);
      const y = brickOffsetTop + r * (brickH + brickGap);
      bricks.push({
        x, y, w: brickW, h: brickH,
        alive: true,
        color: `hsl(${(r * 45 + c * 12) % 360}, 75%, 60%)`
      });
    }
  }
}

function spawnHearts(x, y, count = 30) {
  for (let i = 0; i < count; i++) {
    particles.push(new Particle(x, y));
  }
}

// ---------- Input ----------
window.addEventListener('keydown', e => {
  keys[e.code] = true;
  if (!started) startGame();
});
window.addEventListener('keyup', e => { keys[e.code] = false; });

canvas.addEventListener('pointermove', e => {
  const rect = canvas.getBoundingClientRect();
  const scaleX = GAME_W / rect.width;
  mouse.x = (e.clientX - rect.left) * scaleX;
  mouse.active = true;
});
canvas.addEventListener('pointerdown', startGame);
window.addEventListener('pointerdown', () => { if (!started) startGame(); });

function startGame() {
  if (started) return;
  started = true;
  gameOver = false;
  overlay.classList.add('hidden');
  resetGame();
  loop();
}

function resetGame() {
  score = 0;
  lives = 3;
  updateHud();
  createBricks();
  particles.length = 0;
  paddle.x = GAME_W / 2;
  ball.reset();
  ball.active = false;
  // wait a moment then launch
  setTimeout(() => { ball.active = true; }, 600);
}

function updateHud() {
  scoreEl.textContent = `Score: ${score}`;
  livesEl.textContent = `Lives: ${lives}`;
}

// ---------- Core ----------
function update() {
  if (gameOver) return;

  // Demo AI before game fully starts / after game over handled elsewhere
  if (!started) {
    // paddle follows ball slowly
    const target = ball.x;
    paddle.x += (target - paddle.x) * 0.08;
    clampPaddle();
    return;
  }

  // Player control
  if (mouse.active) {
    paddle.x = mouse.x;
  } else {
    if (keys['ArrowLeft'] || keys['KeyA']) paddle.x -= paddle.speed;
    if (keys['ArrowRight'] || keys['KeyD']) paddle.x += paddle.speed;
  }
  clampPaddle();

  if (ball.active) {
    ball.x += ball.vx;
    ball.y += ball.vy;

    // Walls
    if (ball.x - ball.r < 0) { ball.x = ball.r; ball.vx *= -1; }
    if (ball.x + ball.r > GAME_W) { ball.x = GAME_W - ball.r; ball.vx *= -1; }
    if (ball.y - ball.r < 0) { ball.y = ball.r; ball.vy *= -1; }

    // Paddle collision
    if (
      ball.vy > 0 &&
      ball.y + ball.r >= paddle.y - paddle.h / 2 &&
      ball.y - ball.r <= paddle.y + paddle.h / 2 &&
      ball.x >= paddle.x - paddle.w / 2 - 4 &&
      ball.x <= paddle.x + paddle.w / 2 + 4
    ) {
      const hitPos = (ball.x - paddle.x) / (paddle.w / 2);
      ball.vx = hitPos * 7;
      ball.vy = -Math.abs(ball.vy) - 0.5;
      if (ball.vy > -ball.speed) ball.vy = -ball.speed;
      // nudge out
      ball.y = paddle.y - paddle.h / 2 - ball.r - 0.5;
    }

    // Floor / lose life
    if (ball.y - ball.r > GAME_H) {
      lives--;
      updateHud();
      if (lives <= 0) {
        gameOver = true;
        overlay.querySelector('h1').textContent = 'Game Over';
        overlay.querySelector('p').textContent = 'Click or press any key to restart';
        overlay.classList.remove('hidden');
        started = false;
      } else {
        ball.active = false;
        setTimeout(() => {
          ball.x = GAME_W / 2;
          ball.y = GAME_H / 2 - 60;
          ball.active = true;
        }, 700);
      }
    }

    // Bricks
    for (let i = 0; i < bricks.length; i++) {
      const b = bricks[i];
      if (!b.alive) continue;
      if (
        ball.x + ball.r > b.x &&
        ball.x - ball.r < b.x + b.w &&
        ball.y + ball.r > b.y &&
        ball.y - ball.r < b.y + b.h
      ) {
        b.alive = false;
        score += 10;
        updateHud();
        spawnHearts(b.x + b.w / 2, b.y + b.h / 2, 28);
        ball.vy *= -1;
        break;
      }
    }

    // Win condition
    if (bricks.every(b => !b.alive)) {
      score += 100;
      updateHud();
      createBricks();
      ball.active = false;
      setTimeout(() => { ball.active = true; }, 600);
    }
  }

  // Particles
  for (let i = particles.length - 1; i >= 0; i--) {
    const p = particles[i];
    p.update();
    if (p.life <= 0) particles.splice(i, 1);
  }
}

function clampPaddle() {
  if (paddle.x < paddle.w / 2) paddle.x = paddle.w / 2;
  if (paddle.x > GAME_W - paddle.w / 2) paddle.x = GAME_W - paddle.w / 2;
}

function draw() {
  // Clear
  ctx.fillStyle = '#000';
  ctx.fillRect(0, 0, GAME_W, GAME_H);

  // Subtle grid
  ctx.strokeStyle = '#111';
  ctx.lineWidth = 1;
  for (let x = 0; x <= GAME_W; x += 40) {
    ctx.beginPath(); ctx.moveTo(x, 0); ctx.lineTo(x, GAME_H); ctx.stroke();
  }
  for (let y = 0; y <= GAME_H; y += 40) {
    ctx.beginPath(); ctx.moveTo(0, y); ctx.lineTo(GAME_W, y); ctx.stroke();
  }

  // Bricks
  for (const b of bricks) {
    if (!b.alive) continue;
    ctx.fillStyle = b.color;
    ctx.strokeStyle = '#000';
    ctx.lineWidth = 2;
    ctx.fillRect(b.x, b.y, b.w, b.h);
    ctx.strokeRect(b.x, b.y, b.w, b.h);
  }

  // Particles (hearts)
  for (const p of particles) p.draw();

  // Paddle
  paddle.draw();

  // Ball
  ball.draw();

  // Ready indicator
  if (!ball.active && started && !gameOver) {
    ctx.fillStyle = 'rgba(255,255,255,0.6)';
    ctx.font = 'bold 24px sans-serif';
    ctx.textAlign = 'center';
    ctx.fillText('GET READY', GAME_W / 2, GAME_H / 2);
  }
}

function loop() {
  update();
  draw();
  requestAnimationFrame(loop);
}

// Start the demo loop immediately (self-playing behind overlay)
loop();
</script>
</body>
</html>
Reasoning trace (4,608 tokens)
The user wants a Breakout-style game with these specifics:
1. Paddle is a hamburger
2. Bricks break into tons of little hearts (particle explosion effect)
3. Self-contained web demo (single HTML file)
4. Everything inline (CSS in <style>, JS in <script>)
5. No external resources except allowed CDNs (but better to avoid network entirely for reliability)
6. Responsive: 1280x800 viewport, adapt down to 375px, no horizontal scrollbar
7. Something meaningful visible on first paint (screenshot at 3s)
8. Self-playing demo mode behind "Click or press a key to start" message
9. Keyboard events only after click
10. Zero errors in latest Chrome

I need to:
- Create an HTML5 canvas game
- Draw a hamburger paddle (since no external images, I'll draw it with canvas paths)
- Draw bricks that when destroyed spawn many heart particles
- Heart particles should be little hearts (can draw with canvas path or use emoji? Emoji might not render consistently but "💖" could work. Better to draw heart shapes with canvas for control)
- Demo mode: AI plays automatically until user clicks/presses key
- Start screen overlay
- Responsive canvas scaling
- Collision detection, ball physics
- Score, lives maybe
- Colors: hamburger brown/tan, bricks colorful, hearts red/pink

Structure:
- HTML: canvas, overlay div with "Click or press a key to start", maybe score/lives HUD
- CSS: full screen, flexbox center, canvas max-width etc, responsive
- JS:
  - Canvas setup with resize handling
  - Game state: startScreen, demoMode, playing, gameOver
  - Entities: ball, paddle (hamburger), bricks array, particles array
  - Hamburger drawing function: bun top, patty, cheese, lettuce, bun bottom
  - Heart particle class: position, velocity, life, draw heart shape
  - Brick class: x,y,w,h,color, alive
  - Input handling: mouse/touch for paddle, keyboard arrows
  - AI demo: paddle follows ball x
  - Update loop: move ball, wall collisions, paddle collision, brick collisions -> spawn hearts
  - Render loop: clear, draw bricks, draw paddle, draw ball, draw particles, draw HUD
  - Start overlay click/key to transition to playing (or demo mode playing behind it)

First paint: The canvas should show bricks, hamburger paddle, ball, and the start overlay immediately. That's meaningful.

Responsive: canvas should fit container, maybe use CSS `max-width: 100%; height: auto;` but canvas internal resolution vs display size. Better to set canvas width/height via JS to match container but capped. Or use a fixed logical resolution (e.g., 800x600) and scale via CSS. For simplicity, logical width = min(window.innerWidth, 800) maybe, height = 600 scaled down? Let's do a container with max-width 100%, canvas display block max-width 100%, and internally set canvas dimensions to something like 700x500 but scale down on small screens using CSS transform? Simpler: make canvas resolution match CSS size via `canvas.width = container.clientWidth`, `canvas.height = container.clientHeight` but cap height. However game logic depends on aspect ratio. Let's use fixed logical size 800x600 and scale canvas to fit parent using CSS `object-fit: contain` inside a fixed aspect-ratio container? That might be complex.

Alternative: Use `canvas { width: 100%; height: auto; }` and set internal resolution to `displayWidth x displayHeight` but that changes physics. Better to keep internal resolution fixed at 800x600, and CSS scales it down to fit screen. Container: `width: 100%; max-width: 800px; aspect-ratio: 4/3; position: relative; canvas { width: 100%; height: 100%; }`. This preserves aspect ratio and no horizontal scrollbar. On mobile 375px, canvas will be 375x281 roughly, scaled down. Game remains playable.

No external images. Draw hamburger with canvas.

Heart drawing: A heart shape can be made with bezier curves:
```
ctx.beginPath();
ctx.moveTo(x, y);
ctx.bezierCurveTo(x, y, x - size, y - size, x - size, y + size/2);
... etc
```
Simpler heart: two circles and a triangle bottom, or path:
```
ctx.beginPath();
ctx.moveTo(x, y);
ctx.bezierCurveTo(x - s, y - s, x - s*2, y + s*0.5, x, y + s*1.5);
ctx.bezierCurveTo(x + s*2, y + s*0.5, x + s, y - s, x, y);
ctx.fill();
ctx.stroke();
```
Need to verify heart path looks decent. Common heart path:
```
beginPath();
moveTo(x, y);
bezierCurveTo(x - size, y - size, x - size*1.5, y + size, x, y + size*1.5);
bezierCurveTo(x + size*1.5, y + size, x + size, y - size, x, y);
closePath();
```
Actually standard:
```
ctx.beginPath();
ctx.moveTo(x, y);
ctx.bezierCurveTo(x, y, x - r, y - r, x - r, y + r/2);
ctx.bezierCurveTo(x - r, y + r, x, y + r*1.5, x, y + r*1.5);
ctx.bezierCurveTo(x, y + r*1.5, x + r, y + r, x + r, y + r/2);
ctx.bezierCurveTo(x + r, y - r, x, y, x, y);
```
I'll make a `drawHeart(ctx, x, y, size, color)` function.

Particles: when brick breaks, spawn 20-40 hearts with random velocities, gravity, fade out.

Paddle hamburger drawing:
- Top bun: rounded rectangle, tan color (#D2B48C)
- Sesame seeds: small ovals
- Patty: dark brown circle/oval
- Cheese: yellow rectangle dripping
- Lettuce: green wavy shape
- Bottom bun: tan rounded rect

Since paddle moves, drawing relative to paddle center.

Ball: white circle with maybe a red outline.

Bricks: rows of colored rectangles with slight gap.

Game over / win: restart demo.

Demo mode: AI paddle moves toward ball.x with some lag/speed limit.

Overlay: semi-transparent dark background, text "Click or press a key to start", maybe "Hamburger Breakout" title.

Controls: Arrow keys / A-D / mouse move. Touch drag.

Let's write code carefully.

Canvas sizing:
```
const container = document.getElementById('game-container');
const canvas = document.getElementById('game');
function resize() {
  const w = Math.min(window.innerWidth, 800);
  const h = Math.floor(w * 0.75); // 4:3
  container.style.width = w + 'px';
  container.style.height = h + 'px';
  canvas.width = w;
  canvas.height = h;
}
```
But game logic coordinates should scale. Better to keep internal coordinate system fixed at 800x600 and scale drawing via CSS. But if canvas width/height change, coordinate system changes. Could use a fixed internal resolution and `ctx.scale()` based on display size. Let's do:

```
const GAME_W = 800;
const GAME_H = 600;
canvas.width = GAME_W;
canvas.height = GAME_H;
```
CSS:
```
#game-container { width: 100%; max-width: 800px; aspect-ratio: 4/3; margin: 0 auto; position: relative; }
canvas { width: 100%; height: 100%; display: block; }
#overlay { position: absolute; inset: 0; ... }
```
This way internal coords are always 800x600, CSS scales it. On mobile 375px width, canvas is scaled down but coords remain 800x600. Perfect.

Overlay text should be visible on first paint. Yes.

Demo mode starts automatically: ball moves, AI paddle moves. Overlay says click to start. When clicked, overlay hides, game continues but now player controls (or still demo? Usually "click to start" means take over). I'll make it: overlay visible, demo AI playing behind it. On click/key, overlay removed, player controls active. Ball and bricks continue from where they were? Or reset? Better reset when starting to give clean state. But user said "self-playing demo mode behind a Click or press a key to start message". So demo is active behind message. When they click, they start playing (probably reset level). I'll reset game on start.

Lives: 3. Score: 0.

Brick layout: rows, colors. When all bricks cleared, reset level (demo continues or player continues). Simple.

Particle system:
```
class Particle {
  constructor(x, y) {
    this.x = x; this.y = y;
    const angle = Math.random() * Math.PI * 2;
    const speed = 2 + Math.random() * 6;
    this.vx = Math.cos(angle) * speed;
    this.vy = Math.sin(angle) * speed;
    this.life = 1.0;
    this.decay = 0.015 + Math.random() * 0.02;
    this.size = 4 + Math.random() * 6;
    this.color = `hsl(${320 + Math.random()*40}, 100%, 60%)`; // pink/red
  }
  update() { this.x += this.vx; this.y += this.vy; this.vy += 0.15; this.life -= this.decay; }
  draw(ctx) { ctx.globalAlpha = this.life; drawHeart(...); ctx.globalAlpha = 1; }
}
```

Brick break: spawn ~25 particles at brick center.

Ball-paddle collision: reflect based on hit position.

Ball-brick collision: simple AABB, reflect velocity.

Drawing hamburger paddle:
Paddle width maybe 120, height 40.
Draw at paddle.x - w/2, paddle.y - h/2.
Layers:
- Bottom bun: fill #CD853F, rounded rect, y offset +10
- Lettuce: #4CAF50, wavy rect above bottom bun
- Cheese: #FFEB3B, rect above lettuce, dripping triangles
- Patty: #5D4037, circle/oval above cheese
- Top bun: #DEB887, rounded rect top, sesame seeds.

I'll write a `drawBurger(ctx, x, y, w, h)` function.

Ball: draw circle at ball.x, ball.y radius 8, white with orange outline maybe to look like a food item? Could be a "cherry" or just ball. Keep white.

Let's code.

Edge cases: `globalAlpha` needs restore. `ctx.save()`/`ctx.restore()`.

Responsive overlay text size: use relative units or JS font size based on canvas width. CSS can handle with `clamp()`. But overlay is inside container absolute. Use `font-size: clamp(1rem, 5vw, 1.5rem);`.

No horizontal scrollbar: `body { margin: 0; overflow: hidden; }`.

Start overlay:
```
<div id="overlay" class="overlay">
  <h1>Hamburger Breakout</h1>
  <p>Click or press any key to start</p>
</div>
```

Click on canvas or document to start. Keypress to start (only after click? The instructions say iframe only receives keyboard after click. So we can listen for click anywhere to start, then keydown works. Or just click to start and also enable keys after click.)

Implementation:
```
let started = false;
function startGame() { if(started) return; started = true; overlay.style.display='none'; resetGame(); requestAnimationFrame(loop); }
canvas.addEventListener('pointerdown', startGame);
window.addEventListener('keydown', (e)=>{ if(!started) startGame; });
```
But if user presses key before click, it starts. That's okay because click on page focuses it? Actually iframe only receives keyboard after click, but `window.addEventListener('keydown')` might not work before click in cross-origin iframe. However since we start on any click, and demo is running before that, it's fine. After click, keyboard works. I'll add click listener on document to be safe.

Demo AI:
```
if (demoMode) {
  const target = ball.x;
  paddle.x += (target - paddle.x) * 0.1;
  clamp paddle.x
}
```
When started, demoMode = false.

Controls:
- Pointer move: paddle.x = clientX scaled to canvas coords. Need to handle CSS scaling. Since canvas is 800x600 internal but displayed scaled, we need to get mouse position relative to canvas and map to internal coords.
```
function getMouseX(e) {
  const rect = canvas.getBoundingClientRect();
  const scaleX = GAME_W / rect.width;
  return (e.clientX - rect.left) * scaleX;
}
```
- Arrow keys left/right move paddle.

Game loop:
```
function loop() {
  update();
  draw();
  requestAnimationFrame(loop);
}
```

Update:
- move ball
- wall collisions: left/right reverse vx; top reverse vy; bottom: lose life, reset ball/paddle, if lives 0 game over (reset to demo)
- paddle collision: if ball.y + r > paddle.y - h/2 && ball.y - r < paddle.y + h/2 && x overlap: reverse vy, adjust vx based on hit position. Push ball out.
- brick collision: iterate bricks, if intersect, mark dead, spawn particles, reverse vy (simple). Break out after one collision per frame or handle multiple? Simple one per frame.
- particles update, remove dead.
- if all bricks dead, reset level.

Reset level: generate bricks. Reset ball, paddle.

Brick generation:
```
const cols = 10, rows = 6;
const brickW = 70, brickH = 24;
const gap = 6;
const offsetTop = 50;
const offsetLeft = (GAME_W - (cols*(brickW+gap) - gap))/2;
for r... for c... color = hue based on row.
```

Colors: `hsl(${r*40 + c*10}, 70%, 60%)`.

Hearts: `tons of little hearts` -> maybe 30 per brick.

Let's write full HTML.

Check for console errors: ensure all variables defined, no external assets.

Heart path function:
```
function drawHeart(ctx, x, y, size, color) {
  ctx.save();
  ctx.translate(x, y);
  ctx.scale(size, size);
  ctx.fillStyle = color;
  ctx.beginPath();
  ctx.moveTo(0, 0);
  ctx.bezierCurveTo(-1, -1, -2, 0, 0, 2);
  ctx.bezierCurveTo(2, 0, 1, -1, 0, 0);
  ctx.closePath();
  ctx.fill();
  ctx.restore();
}
```
Does this look like a heart? Let's test mentally:
Points: (0,0) bottom? Curve to (-1,-1), (-2,0), (0,2) -> left top bump to top center. Then (2,0), (1,-1), (0,0) -> right bump back to bottom. Actually (0,0) is bottom center? Let's trace:
start at (0,0).
curve to (-1,-1), control (-2,0), end (0,2): This goes up-left then to top center.
curve to (2,0), control (1,-1), end (0,0): from top center down-right to bottom center.
This creates a heart shape pointing down? Actually top center is (0,2), bottom is (0,0). Left bump around (-1,-1), right bump around (1,-1). Yes that's a heart upright. Good. Scale will make size.

But `ctx.scale(size, size)` scales line width too, but we just fill so fine.

Hamburger drawing function:
```
function drawBurger(ctx, x, y, w, h) {
  const cx = x, cy = y;
  // shadow? skip
  // bottom bun
  ctx.fillStyle = '#D2691E';
  ctx.beginPath();
  ctx.roundRect(cx - w/2, cy + h/4, w, h/2, h/4); // maybe not supported? roundRect is newer but Chrome supports. To be safe use arc or rect.
```
`roundRect` is supported in latest Chrome. But safest to use rect or custom. I'll use `rect` with some manual rounding or just rect. It's a demo, rects are okay but burger looks better rounded. I can do:
```
ctx.beginPath();
ctx.moveTo(cx-w/2, cy+h/4+h/8);
ctx.arcTo(cx-w/2, cy+h/2, cx, cy+h/2, h/8);
...
```
Too complex. Let's just use `rect` and colors, maybe add arc for bun top. Actually bun top can be arc.

Simpler burger:
- Bottom bun: rect fill #D2691E at bottom half.
- Lettuce: rect fill #7CB342 above bottom bun, slightly wavy? just rect.
- Cheese: rect fill #FFD54F above lettuce.
- Patty: arc fill #5D4037 above cheese (semi circle).
- Top bun: arc fill #DEB887 top.

Paddle y is center. Let's define burger height h. Bottom bun occupies cy + h/4 to cy + h/2. Lettuce cy + h/8 to cy + h/4. Cheese cy to cy + h/8. Patty cy - h/8 to cy? Top bun cy - h/2 to cy - h/8.

I'll draw:
```
ctx.fillStyle = '#8D6E63'; // bottom bun darker
ctx.fillRect(cx - w/2, cy + h*0.35, w, h*0.55);
// lettuce
ctx.fillStyle = '#66BB6A';
ctx.fillRect(cx - w/2 + 4, cy + h*0.25, w - 8, h*0.2);
// cheese
ctx.fillStyle = '#FFEB3B';
ctx.fillRect(cx - w/2 + 6, cy + h*0.1, w - 12, h*0.18);
// patty
ctx.fillStyle = '#5D4037';
ctx.beginPath();
ctx.arc(cx, cy - h*0.1, h*0.35, 0, Math.PI);
ctx.fill();
// top bun
ctx.fillStyle = '#D2B48C';
ctx.beginPath();
ctx.arc(cx, cy - h*0.35, h*0.35, Math.PI, 0);
ctx.lineTo(cx + h*0.35, cy - h*0.35);
ctx.lineTo(cx - h*0.35, cy - h*0.35);
ctx.fill();
// sesame seeds
ctx.fillStyle = '#fff';
for (...) ctx.fillRect(...)
```
This is rough but recognizable as a hamburger stack. Add outline stroke for definition.

Actually to make it look more like a bun, top bun should be a dome:
```
ctx.beginPath();
ctx.arc(cx, cy - h*0.3, h*0.4, Math.PI, 0, true); // top half?
```
I'll just draw it stylized.

Let's ensure `ctx.arc` calls are correct.

Full code now.

Also include "Score" and "Lives" text at top.

Game over: if lives <=0, show overlay again with "Game Over - Click to restart". Demo resumes.

Win: if no bricks, next level or reset.

Let's code.

Potential issue: `document.fonts` not needed.

Use `requestAnimationFrame`.

No network.

Let's write it.

I'll keep the code clean and comment.

One more thing: "something meaningful must be visible on first paint". The canvas with bricks and burger and ball will be visible behind overlay. Overlay has text. Good.

Responsive: body overflow hidden, container centered.

Let's produce final HTML.