window.sketch = (runtime) => {
  const { c2, canvas, startFrame } = runtime;
  const renderer = new c2.Renderer(canvas);

  const people = [];
  const NUM_PEOPLE = 70;

  const skinTones = ['#f4d4b0', '#e8bf94', '#d9a578', '#c98a5c', '#a86b3f', '#fbe2c6', '#e9c69a'];
  const shirtColors = ['#1e3a8a', '#7c2d12', '#064e3b', '#831843', '#1f2937', '#991b1b', '#0c4a6e', '#365314', '#4c1d95', '#7f1d1d', '#92400e', '#0f766e'];
  const pantColors = ['#1a1a2e', '#2d2d44', '#0f172a', '#1e1b4b', '#27272a', '#18181b'];
  const hairStyles = ['black', 'dark', 'ponytail', 'bun', 'short', 'bald'];

  for (let i = 0; i < NUM_PEOPLE; i++) {
    people.push({
      x: Math.random() * canvas.width,
      y: canvas.height * 0.55 + Math.random() * canvas.height * 0.45,
      speed: 0.4 + Math.random() * 0.9,
      bobPhase: Math.random() * Math.PI * 2,
      bobSpeed: 0.08 + Math.random() * 0.05,
      bodyHeight: 36 + Math.random() * 12,
      bodyWidth: 14 + Math.random() * 5,
      skin: skinTones[Math.floor(Math.random() * skinTones.length)],
      shirt: shirtColors[Math.floor(Math.random() * shirtColors.length)],
      pants: pantColors[Math.floor(Math.random() * pantColors.length)],
      hair: hairStyles[Math.floor(Math.random() * hairStyles.length)],
      armPhase: Math.random() * Math.PI * 2,
      scale: 0.7 + Math.random() * 0.4,
      depth: Math.random()
    });
  }

  // Sort by depth so far people render first
  people.sort((a, b) => a.depth - b.depth);

  function drawPerson(p, frameCount) {
    const bob = Math.sin(frameCount * p.bobSpeed + p.bobPhase) * 1.2;
    const x = p.x;
    const y = p.y + bob;
    const s = p.scale;

    // Shadow
    renderer.fill('rgba(0,0,0,0.25)');
    renderer.ellipse(x, p.y + p.bodyHeight * s * 0.55, p.bodyWidth * s * 0.7, 2.5 * s);

    // Legs (with walking motion)
    renderer.fill(p.pants);
    const legSwing = Math.sin(frameCount * p.bobSpeed * 2 + p.bobPhase) * 3 * s;
    renderer.rect(x - p.bodyWidth * 0.3 * s - legSwing, y + p.bodyHeight * 0.3 * s, p.bodyWidth * 0.25 * s, p.bodyHeight * 0.25 * s);
    renderer.rect(x + p.bodyWidth * 0.05 * s + legSwing, y + p.bodyHeight * 0.3 * s, p.bodyWidth * 0.25 * s, p.bodyHeight * 0.25 * s);

    // Body / shirt
    renderer.fill(p.shirt);
    renderer.rect(x - p.bodyWidth * 0.5 * s, y, p.bodyWidth * s, p.bodyHeight * 0.35 * s);

    // Arms
    const armSwing = Math.sin(frameCount * p.bobSpeed * 2 + p.bobPhase + p.armPhase) * 2.5 * s;
    renderer.fill(p.skin);
    renderer.rect(x - p.bodyWidth * 0.6 * s, y + 2 * s - armSwing, 2.5 * s, p.bodyHeight * 0.28 * s);
    renderer.rect(x + p.bodyWidth * 0.5 * s - 2 * s, y + 2 * s + armSwing, 2.5 * s, p.bodyHeight * 0.28 * s);

    // Head
    const headY = y - p.bodyHeight * 0.12 * s;
    renderer.fill(p.skin);
    renderer.circle(x, headY, p.bodyWidth * 0.42 * s);

    // Hair
    renderer.fill('#1a1a1a');
    if (p.hair === 'black' || p.hair === 'dark' || p.hair === 'short') {
      renderer.arc(new c2.Arc({ x: x, y: headY - 1 * s }, p.bodyWidth * 0.45 * s, Math.PI, Math.PI * 2));
    } else if (p.hair === 'ponytail') {
      renderer.arc(new c2.Arc({ x: x, y: headY - 1 * s }, p.bodyWidth * 0.45 * s, Math.PI, Math.PI * 2));
      renderer.fill('#1a1a1a');
      renderer.rect(x - p.bodyWidth * 0.55 * s, headY - 1 * s, 2.5 * s, p.bodyWidth * 0.35 * s);
    } else if (p.hair === 'bun') {
      renderer.arc(new c2.Arc({ x: x, y: headY - 1 * s }, p.bodyWidth * 0.45 * s, Math.PI, Math.PI * 2));
      renderer.fill('#1a1a1a');
      renderer.circle(x, headY - p.bodyWidth * 0.5 * s, p.bodyWidth * 0.22 * s);
    } else {
      // bald - just a slight fringe
      renderer.fill('#1a1a1a');
      renderer.arc(new c2.Arc({ x: x, y: headY + 1 * s }, p.bodyWidth * 0.4 * s, Math.PI * 1.1, Math.PI * 1.9));
    }
  }

  function drawBuilding(x, w, h, color, winColor) {
    renderer.fill(color);
    renderer.rect(x, canvas.height * 0.55 - h, w, h);
    // Windows
    const rows = Math.floor(h / 25);
    const cols = Math.floor(w / 22);
    for (let r = 0; r < rows; r++) {
      for (let c = 0; c < cols; c++) {
        const lit = (Math.sin(x * 0.01 + r * 7 + c * 3) > -0.3);
        renderer.fill(lit ? winColor : '#1a1a25');
        renderer.rect(x + 4 + c * 22, canvas.height * 0.55 - h + 8 + r * 25, 14, 14);
      }
    }
  }

  function drawSign(x, y, w, h, color, text) {
    renderer.fill('#111');
    renderer.rect(x, y, w, h);
    renderer.fill(color);
    renderer.rect(x + 2, y + 2, w - 4, h - 4);
    renderer.fill('#fff');
    renderer.fontSize(Math.min(h * 0.5, 9));
    renderer.fontFamily('sans-serif');
    renderer.textAlign('center');
    renderer.text(text, x + w / 2, y + h * 0.65);
  }

  function drawLantern(x, y, size, phase) {
    const glow = 0.6 + Math.sin(phase) * 0.2;
    renderer.fill(`rgba(255, 140, 40, ${glow * 0.4})`);
    renderer.circle(x, y, size * 1.6);
    renderer.fill(`rgba(220, 60, 30, ${glow})`);
    renderer.circle(x, y, size);
    renderer.fill('#1a1a1a');
    renderer.rect(x - 0.5, y - size * 1.3, 1, size * 0.4);
  }

  startFrame((frameCount) => {
    renderer.clear('#1a1a2a');

    // Sky gradient effect via overlapping rects
    renderer.fill('#2d2d4a');
    renderer.rect(0, 0, canvas.width, canvas.height * 0.55);

    // Distant buildings
    drawBuilding(0, 90, 140, '#3a3a52', '#ffcc66');
    drawBuilding(85, 70, 110, '#2a2a40', '#ffd680');
    drawBuilding(150, 110, 170, '#3d3d58', '#ffaa44');
    drawBuilding(255, 80, 130, '#2e2e46', '#ffcc66');
    drawBuilding(canvas.width - 200, 95, 160, '#38384f', '#ffbb55');
    drawBuilding(canvas.width - 110, 85, 120, '#2c2c44', '#ffd680');
    drawBuilding(canvas.width - 30, 60, 100, '#3a3a52', '#ffcc66');

    // Signs
    drawSign(20, canvas.height * 0.18, 60, 18, '#c0392b', '茶');
    drawSign(100, canvas.height * 0.25, 70, 20, '#d35400', 'RAMEN');
    drawSign(190, canvas.height * 0.12, 50, 16, '#e74c3c', '寿司');
    drawSign(canvas.width - 130, canvas.height * 0.2, 70, 18, '#c0392b', '面馆');
    drawSign(canvas.width - 220, canvas.height * 0.28, 55, 16, '#d35400', 'CAFE');

    // Hanging lanterns
    drawLantern(40, 30, 6, frameCount * 0.03);
    drawLantern(canvas.width - 60, 35, 7, frameCount * 0.04 + 1);
    drawLantern(canvas.width * 0.5, 20, 5, frameCount * 0.05 + 2);

    // Street / ground
    renderer.fill('#0f0f1a');
    renderer.rect(0, canvas.height * 0.55, canvas.width, canvas.height * 0.45);

    // Road markings (dashes moving)
    renderer.fill('#5a5a6a');
    for (let i = 0; i < 20; i++) {
      const mx = ((i * 70 - frameCount * 0.8) % (canvas.width + 70) + canvas.width + 70) % (canvas.width + 70) - 35;
      renderer.rect(mx, canvas.height * 0.78, 35, 2);
    }

    // Sidewalk
    renderer.fill('#3a3a48');
    renderer.rect(0, canvas.height * 0.55, canvas.width, canvas.height * 0.06);
    renderer.stroke('#5a5a6a');
    renderer.lineWidth(1);
    renderer.line(0, canvas.height * 0.61, canvas.width, canvas.height * 0.61);

    // Update and draw people
    for (let p of people) {
      p.x -= p.speed;
      if (p.x < -40) {
        p.x = canvas.width + 30;
        p.y = canvas.height * 0.55 + Math.random() * canvas.height * 0.45;
      }
      drawPerson(p, frameCount);
    }
  });
};
