// === HALVSIES QUEST — SPRITES ========================================
// Bard variants, 3 villager variants, clerk, monster, chest, glowing tape,
// attack swing. All hand-pixeled procedurally.

const { C, TILE, PLAY_TOP, DIRS, ATTACK_MS, drawText } = window;

// =====================================================================
// BARD — variant: noGuitar | withGuitar | celebration
// =====================================================================
function drawPlayer(ctx, p, t, variant, hidden, celebrationItem) {
  if (hidden) return;
  const px = Math.round(p.x * TILE);
  const py = Math.round(p.y * TILE) + PLAY_TOP;
  if (variant === "celebration") drawBardCelebration(ctx, px, py, t, celebrationItem || "guitar");
  else drawBard(ctx, px, py, p.dir, p.moving ? Math.floor(p.step / 70) : 0, variant === "withGuitar");
}

function drawBard(ctx, px, py, dir, stepFrame, withGuitar) {
  const bob = (stepFrame % 2) ? 1 : 0;
  const oy = py + bob;

  // shadow
  ctx.fillStyle = C.darkest;
  ctx.globalAlpha = 0.35;
  ctx.fillRect(px+3, py+14, 10, 2);
  ctx.globalAlpha = 1;

  // Guitar BEHIND when facing up (back to camera) — drawn first
  if (withGuitar && dir === "up") drawCarriedGuitar(ctx, px, oy, dir);

  // Hat (pointed)
  ctx.fillStyle = C.darkest;
  ctx.fillRect(px+7, oy+0, 2, 1);
  ctx.fillRect(px+6, oy+1, 4, 1);
  ctx.fillRect(px+5, oy+2, 6, 1);
  ctx.fillRect(px+4, oy+3, 8, 1);
  ctx.fillStyle = C.dark;
  ctx.fillRect(px+5, oy+3, 6, 1);

  // Face
  ctx.fillStyle = C.dark;
  ctx.fillRect(px+5, oy+4, 6, 3);
  ctx.fillStyle = C.darkest;
  if (dir === "down") {
    ctx.fillRect(px+6, oy+5, 1, 1);
    ctx.fillRect(px+9, oy+5, 1, 1);
    ctx.fillRect(px+7, oy+6, 2, 1);
  } else if (dir === "up") {
    ctx.fillRect(px+5, oy+5, 6, 1);
  } else if (dir === "left") {
    ctx.fillRect(px+5, oy+5, 2, 1);
  } else {
    ctx.fillRect(px+9, oy+5, 2, 1);
  }

  // Torso
  ctx.fillStyle = C.darkest;
  ctx.fillRect(px+4, oy+7, 8, 5);
  ctx.fillStyle = C.dark;
  ctx.fillRect(px+7, oy+8, 2, 3);

  // Empty hands at sides (no guitar) — for stark contrast
  if (!withGuitar) {
    ctx.fillStyle = C.darkest;
    ctx.fillRect(px+3, oy+9, 1, 2);
    ctx.fillRect(px+12, oy+9, 1, 2);
  }

  // Legs
  ctx.fillStyle = C.darkest;
  if (stepFrame % 2 === 0) {
    ctx.fillRect(px+5, oy+12, 2, 3);
    ctx.fillRect(px+9, oy+12, 2, 2);
  } else {
    ctx.fillRect(px+5, oy+12, 2, 2);
    ctx.fillRect(px+9, oy+12, 2, 3);
  }
  ctx.fillStyle = C.dark;
  ctx.fillRect(px+5, oy+14, 2, 1);
  ctx.fillRect(px+9, oy+14, 2, 1);

  if (withGuitar && dir !== "up") drawCarriedGuitar(ctx, px, oy, dir);
}

// ---- Carried guitar (elongated neck + chunky body cluster) ---------
function drawCarriedGuitar(ctx, px, py, dir) {
  if (dir === "down") {
    // Strap diagonal across chest
    ctx.fillStyle = C.dark;
    ctx.fillRect(px+5, py+7,  1, 1);
    ctx.fillRect(px+6, py+8,  1, 1);
    ctx.fillRect(px+7, py+9,  1, 1);
    ctx.fillRect(px+8, py+10, 1, 1);
    // Body cluster behind right shoulder
    ctx.fillStyle = C.light;
    ctx.fillRect(px+12, py+8, 4, 5);
    ctx.fillStyle = C.lightest;
    ctx.fillRect(px+13, py+9, 2, 3);
    ctx.fillStyle = C.darkest;
    ctx.fillRect(px+13, py+10, 1, 1);
    // Elongated neck up over left shoulder (6px)
    ctx.fillStyle = C.light;
    ctx.fillRect(px+3, py+1, 1, 6);
    ctx.fillRect(px+3, py+1, 2, 1);
    // Headstock cluster
    ctx.fillStyle = C.lightest;
    ctx.fillRect(px+2, py-1, 3, 2);
    ctx.fillStyle = C.darkest;
    ctx.fillRect(px+2, py-1, 1, 1);
    ctx.fillRect(px+4, py-1, 1, 1);
  } else if (dir === "up") {
    // Full guitar visible on the back
    ctx.fillStyle = C.light;
    ctx.fillRect(px+4, py+7, 8, 7);
    ctx.fillStyle = C.lightest;
    ctx.fillRect(px+5, py+8, 6, 5);
    ctx.fillStyle = C.darkest;
    ctx.fillRect(px+7, py+9, 2, 2);   // sound hole
    ctx.fillRect(px+7, py+12, 2, 1);  // bridge
    // Long neck up over head (8px)
    ctx.fillStyle = C.light;
    ctx.fillRect(px+7, py-2, 2, 9);
    // Headstock
    ctx.fillStyle = C.lightest;
    ctx.fillRect(px+6, py-4, 4, 3);
    ctx.fillStyle = C.darkest;
    ctx.fillRect(px+6, py-4, 1, 1);
    ctx.fillRect(px+9, py-4, 1, 1);
    ctx.fillRect(px+6, py-2, 1, 1);
    ctx.fillRect(px+9, py-2, 1, 1);
  } else if (dir === "left") {
    // Guitar peeks behind right side (player's back to right)
    ctx.fillStyle = C.light;
    ctx.fillRect(px+12, py+8, 4, 5);
    ctx.fillStyle = C.lightest;
    ctx.fillRect(px+13, py+9, 2, 3);
    ctx.fillStyle = C.light;
    ctx.fillRect(px+13, py+2, 1, 6);
    ctx.fillStyle = C.lightest;
    ctx.fillRect(px+12, py+0, 3, 2);
    ctx.fillStyle = C.darkest;
    ctx.fillRect(px+12, py+0, 1, 1);
    ctx.fillRect(px+14, py+0, 1, 1);
  } else {
    ctx.fillStyle = C.light;
    ctx.fillRect(px+0, py+8, 4, 5);
    ctx.fillStyle = C.lightest;
    ctx.fillRect(px+1, py+9, 2, 3);
    ctx.fillStyle = C.light;
    ctx.fillRect(px+2, py+2, 1, 6);
    ctx.fillStyle = C.lightest;
    ctx.fillRect(px+1, py+0, 3, 2);
    ctx.fillStyle = C.darkest;
    ctx.fillRect(px+1, py+0, 1, 1);
    ctx.fillRect(px+3, py+0, 1, 1);
  }
}

// ---- Celebration: arms up, item OVERHEAD ---------------------------
function drawBardCelebration(ctx, px, py, t, item) {
  const bob = Math.floor(t / 180) % 2 ? -1 : 0;
  const gy = py - 8 + bob;

  ctx.fillStyle = C.darkest;
  ctx.globalAlpha = 0.35;
  ctx.fillRect(px+3, py+14, 10, 2);
  ctx.globalAlpha = 1;

  // The held item floats overhead
  drawCelebrationItem(ctx, item || "guitar", px, gy, t);

  // Hat
  ctx.fillStyle = C.darkest;
  ctx.fillRect(px+7, py+0, 2, 1);
  ctx.fillRect(px+6, py+1, 4, 1);
  ctx.fillRect(px+5, py+2, 6, 1);
  ctx.fillRect(px+4, py+3, 8, 1);
  ctx.fillStyle = C.dark;
  ctx.fillRect(px+5, py+3, 6, 1);

  // Face — open-mouth
  ctx.fillStyle = C.dark;
  ctx.fillRect(px+5, py+4, 6, 3);
  ctx.fillStyle = C.darkest;
  ctx.fillRect(px+6, py+5, 1, 1);
  ctx.fillRect(px+9, py+5, 1, 1);
  ctx.fillRect(px+7, py+6, 2, 1);

  // Both arms raised
  ctx.fillStyle = C.darkest;
  ctx.fillRect(px+3, py+0 + bob, 1, 7);
  ctx.fillRect(px+12, py+0 + bob, 1, 7);
  ctx.fillStyle = C.dark;
  ctx.fillRect(px+3, py-1 + bob, 1, 1);
  ctx.fillRect(px+12, py-1 + bob, 1, 1);

  // Torso
  ctx.fillStyle = C.darkest;
  ctx.fillRect(px+4, py+7, 8, 5);
  ctx.fillStyle = C.dark;
  ctx.fillRect(px+7, py+8, 2, 3);

  // Legs apart
  ctx.fillStyle = C.darkest;
  ctx.fillRect(px+5, py+12, 2, 3);
  ctx.fillRect(px+9, py+12, 2, 3);
  ctx.fillStyle = C.dark;
  ctx.fillRect(px+5, py+14, 2, 1);
  ctx.fillRect(px+9, py+14, 2, 1);
}

// =====================================================================
// ATTACK SWING
// =====================================================================
function drawAttack(ctx, p, attackMs) {
  if (attackMs <= 0) return;
  const u = 1 - attackMs / ATTACK_MS;
  const cx = p.x * TILE;
  const cy = p.y * TILE + PLAY_TOP;
  const { dx, dy } = DIRS[p.dir];
  const reach = TILE * (Math.sin(u * Math.PI) * 0.9 + 0.1);

  let px, py;
  if (p.dir === "right" || p.dir === "left") {
    px = cx + dx * reach;
    py = cy + (u < 0.5 ? -3 : 3);
  } else {
    px = cx + (u < 0.5 ? -3 : 3);
    py = cy + dy * reach;
  }
  px = Math.round(px);
  py = Math.round(py);

  ctx.globalAlpha = 0.45;
  ctx.fillStyle = C.light;
  for (let i = 1; i <= 3; i++) {
    const ui = Math.max(0, u - i * 0.06);
    const ri = TILE * (Math.sin(ui * Math.PI) * 0.9 + 0.1);
    let tx, ty;
    if (p.dir === "right" || p.dir === "left") {
      tx = cx + dx * ri;
      ty = cy + (ui < 0.5 ? -3 : 3);
    } else {
      tx = cx + (ui < 0.5 ? -3 : 3);
      ty = cy + dy * ri;
    }
    ctx.fillRect(Math.round(tx)+5, Math.round(ty)+5, 6, 6);
  }
  ctx.globalAlpha = 1;

  drawGuitarSwing(ctx, px, py, p.dir, u);
}

function drawGuitarSwing(ctx, px, py, dir, u) {
  const horiz = dir === "left" || dir === "right";
  ctx.fillStyle = C.darkest;
  if (horiz) {
    ctx.fillRect(px+3, py+5, 8, 7);
    const neckX = dir === "right" ? px+11 : px+1;
    ctx.fillRect(neckX, py+7, 4, 2);
    ctx.fillStyle = C.light;
    ctx.fillRect(neckX, py+7, 4, 1);
    ctx.fillStyle = C.darkest;
    const headX = dir === "right" ? px+14 : px+0;
    ctx.fillRect(headX, py+6, 2, 4);
  } else {
    ctx.fillRect(px+5, py+3, 7, 8);
    const neckY = dir === "down" ? py+11 : py+1;
    ctx.fillRect(px+7, neckY, 2, 4);
    ctx.fillStyle = C.light;
    ctx.fillRect(px+7, neckY, 1, 4);
    ctx.fillStyle = C.darkest;
    const headY = dir === "down" ? py+14 : py+0;
    ctx.fillRect(px+6, headY, 4, 2);
  }

  ctx.fillStyle = C.lightest;
  if (horiz) {
    ctx.fillRect(px+5, py+7, 4, 3);
    ctx.fillStyle = C.dark;
    ctx.fillRect(px+6, py+8, 2, 1);
  } else {
    ctx.fillRect(px+6, py+5, 5, 4);
    ctx.fillStyle = C.dark;
    ctx.fillRect(px+7, py+6, 3, 2);
  }

  const blink = Math.floor(u * 8) % 2 === 0;
  ctx.fillStyle = C.darkest;
  if (blink) {
    if (horiz) {
      const sx = dir === "right" ? px+12 : px+0;
      ctx.fillRect(sx, py+3, 1, 1);
      ctx.fillRect(sx + (dir==="right"?2:-2), py+12, 1, 1);
      ctx.fillRect(sx + (dir==="right"?4:-4), py+6, 1, 1);
    } else {
      const sy = dir === "down" ? py+12 : py+0;
      ctx.fillRect(px+3, sy, 1, 1);
      ctx.fillRect(px+12, sy + (dir==="down"?2:-2), 1, 1);
      ctx.fillRect(px+6, sy + (dir==="down"?4:-4), 1, 1);
    }
  }
}

// =====================================================================
// VILLAGERS — 3 variants
// =====================================================================
function drawNpc(ctx, n, t) {
  const px = Math.round(n.x * TILE);
  const py = Math.round(n.y * TILE) + PLAY_TOP;
  if (n.kind === "clerk")    return drawClerk(ctx, px, py, n, t);
  if (n.kind === "guard")    return drawGuard(ctx, px, py, n, t);
  if (n.kind === "grandma")  return drawGrandma(ctx, px, py, n, t);
  if (n.kind === "sleeper")  return drawSleepingMan(ctx, px, py, n, t);
  // villager (default)
  const v = n.variant || 1;
  if (v === 1) drawVillagerV1(ctx, px, py, n, t);
  else if (v === 2) drawVillagerV2(ctx, px, py, n, t);
  else drawVillagerV3(ctx, px, py, n, t);
}

// =====================================================================
// CELEBRATION ITEMS — floating overhead during celebration sprites
// =====================================================================
function drawCelebrationItem(ctx, kind, px, py, t) {
  switch (kind) {
    case "guitar":  return drawCelebGuitar(ctx, px, py, t);
    case "coin":    return drawCelebCoin(ctx, px, py, t);
    case "glizzy":  return drawCelebGlizzy(ctx, px, py, t);
    case "tape":    return drawCelebTape(ctx, px, py, t);
    default:        return drawCelebGuitar(ctx, px, py, t);
  }
}

function drawCelebGuitar(ctx, px, gy, t) {
  // Horizontal guitar held overhead (existing celebration guitar)
  ctx.fillStyle = C.light;
  ctx.fillRect(px+1, gy,   6, 5);
  ctx.fillStyle = C.lightest;
  ctx.fillRect(px+2, gy+1, 4, 3);
  ctx.fillStyle = C.darkest;
  ctx.fillRect(px+3, gy+1, 2, 2);
  ctx.fillRect(px+3, gy+3, 2, 1);
  ctx.fillStyle = C.light;
  ctx.fillRect(px+7, gy+1, 7, 2);
  ctx.fillStyle = C.lightest;
  ctx.fillRect(px+14, gy,   2, 4);
  ctx.fillStyle = C.darkest;
  ctx.fillRect(px+14, gy,   1, 1);
  ctx.fillRect(px+15, gy+3, 1, 1);
}

function drawCelebCoin(ctx, px, gy, t) {
  // 8x8 coin with $ outline, centered over head
  const cx = px + 4;  // center horizontally over the bard (~px+4..px+12)
  // Outer dark outline (rounded square)
  ctx.fillStyle = C.darkest;
  ctx.fillRect(cx + 1, gy - 1, 6, 1);
  ctx.fillRect(cx + 1, gy + 6, 6, 1);
  ctx.fillRect(cx,     gy,     1, 6);
  ctx.fillRect(cx + 7, gy,     1, 6);
  // Fill (lightest)
  ctx.fillStyle = C.lightest;
  ctx.fillRect(cx + 1, gy,     6, 6);
  // $ symbol (5x7 glyph, but shrunk — just paint a tiny $)
  ctx.fillStyle = C.darkest;
  ctx.fillRect(cx + 3, gy + 0, 2, 1);  // top serif of S
  ctx.fillRect(cx + 2, gy + 1, 4, 1);
  ctx.fillRect(cx + 2, gy + 2, 1, 1);
  ctx.fillRect(cx + 3, gy + 3, 2, 1);
  ctx.fillRect(cx + 5, gy + 4, 1, 1);
  ctx.fillRect(cx + 2, gy + 5, 4, 1);
  // vertical bar of $
  ctx.fillRect(cx + 3, gy - 1, 1, 1);
  ctx.fillRect(cx + 4, gy + 6, 1, 1);

  // Sparkles
  const spark = Math.floor(t / 140) % 4;
  ctx.fillStyle = C.lightest;
  if (spark === 0) { ctx.fillRect(cx - 3, gy - 2, 1, 1); ctx.fillRect(cx + 9, gy + 7, 1, 1); }
  if (spark === 1) { ctx.fillRect(cx + 10, gy - 1, 1, 1); ctx.fillRect(cx - 2, gy + 6, 1, 1); }
  if (spark === 2) { ctx.fillRect(cx - 4, gy + 3, 1, 1); ctx.fillRect(cx + 11, gy + 2, 1, 1); }
}

function drawCelebGlizzy(ctx, px, gy, t) {
  // Hot dog: bun (lightest) + sausage (dark middle stripe) horizontal, ~14x5
  // bun outline (darkest)
  ctx.fillStyle = C.darkest;
  ctx.fillRect(px + 1, gy + 0, 14, 1);
  ctx.fillRect(px + 1, gy + 5, 14, 1);
  ctx.fillRect(px + 0, gy + 1, 1, 4);
  ctx.fillRect(px + 15, gy + 1, 1, 4);
  // bun fill (lightest)
  ctx.fillStyle = C.lightest;
  ctx.fillRect(px + 1, gy + 1, 14, 4);
  // sausage (dark)
  ctx.fillStyle = C.dark;
  ctx.fillRect(px + 2, gy + 2, 12, 2);
  // sausage shading
  ctx.fillStyle = C.darkest;
  ctx.fillRect(px + 2, gy + 3, 12, 1);
  // mustard zigzag (lightest dots)
  ctx.fillStyle = C.lightest;
  ctx.fillRect(px + 3, gy + 2, 1, 1);
  ctx.fillRect(px + 5, gy + 3, 1, 1);
  ctx.fillRect(px + 7, gy + 2, 1, 1);
  ctx.fillRect(px + 9, gy + 3, 1, 1);
  ctx.fillRect(px + 11, gy + 2, 1, 1);
  ctx.fillRect(px + 13, gy + 3, 1, 1);

  // Sparkles
  const spark = Math.floor(t / 140) % 4;
  ctx.fillStyle = C.lightest;
  if (spark === 0) ctx.fillRect(px - 1, gy + 0, 1, 1);
  if (spark === 1) ctx.fillRect(px + 16, gy + 5, 1, 1);
  if (spark === 2) ctx.fillRect(px + 0, gy + 7, 1, 1);
}

function drawCelebTape(ctx, px, gy, t) {
  // Cassette ~12x7
  ctx.fillStyle = C.darkest;
  ctx.fillRect(px + 2, gy + 0, 12, 7);
  ctx.fillStyle = C.lightest;
  ctx.fillRect(px + 3, gy + 1, 10, 5);
  // Reels
  ctx.fillStyle = C.darkest;
  ctx.fillRect(px + 4, gy + 2, 3, 2);
  ctx.fillRect(px + 9, gy + 2, 3, 2);
  ctx.fillStyle = C.lightest;
  ctx.fillRect(px + 5, gy + 2, 1, 1);
  ctx.fillRect(px + 10, gy + 2, 1, 1);
  // Tape window
  ctx.fillStyle = C.dark;
  ctx.fillRect(px + 5, gy + 5, 6, 1);
  // Label
  ctx.fillStyle = C.light;
  ctx.fillRect(px + 3, gy + 1, 10, 1);

  // Sparkles
  const spark = Math.floor(t / 140) % 4;
  ctx.fillStyle = C.lightest;
  if (spark === 0) ctx.fillRect(px + 0, gy + 1, 1, 1);
  if (spark === 1) ctx.fillRect(px + 15, gy + 4, 1, 1);
  if (spark === 2) ctx.fillRect(px + 1, gy + 6, 1, 1);
}

// =====================================================================
// SPEAKER STACK (concert stage interactable)
// =====================================================================
function drawSpeakerStack(ctx, sp, t) {
  // sp: { tx, ty, w, h } — typically 2x2 (32x32)
  const px = sp.tx * TILE;
  const py = sp.ty * TILE + PLAY_TOP;
  const totalW = sp.w * TILE;
  const totalH = sp.h * TILE;

  // Outer cabinet (dark with darker frame)
  ctx.fillStyle = C.darkest;
  ctx.fillRect(px, py, totalW, totalH);
  ctx.fillStyle = C.dark;
  ctx.fillRect(px + 2, py + 2, totalW - 4, totalH - 4);
  // Front grille texture (vertical stripes)
  ctx.fillStyle = C.darkest;
  for (let x = 3; x < totalW - 3; x += 2) {
    ctx.fillRect(px + x, py + 4, 1, totalH - 8);
  }

  // Top tweeter (small)
  const tx0 = px + Math.floor(totalW / 2) - 3;
  const ty0 = py + 4;
  ctx.fillStyle = C.darkest;
  ctx.fillRect(tx0,     ty0,     6, 4);
  ctx.fillStyle = C.light;
  ctx.fillRect(tx0 + 1, ty0 + 1, 4, 2);
  ctx.fillStyle = C.lightest;
  ctx.fillRect(tx0 + 2, ty0 + 1, 1, 1);

  // Big woofer (center)
  const wcx = px + Math.floor(totalW / 2);
  const wcy = py + Math.floor(totalH / 2) + 4;
  // outer ring
  ctx.fillStyle = C.darkest;
  ctx.fillRect(wcx - 7, wcy - 5, 14, 10);
  ctx.fillStyle = C.dark;
  ctx.fillRect(wcx - 6, wcy - 4, 12, 8);
  ctx.fillStyle = C.light;
  ctx.fillRect(wcx - 5, wcy - 3, 10, 6);
  ctx.fillStyle = C.darkest;
  ctx.fillRect(wcx - 3, wcy - 2, 6, 4); // dust cap
  ctx.fillStyle = C.lightest;
  ctx.fillRect(wcx - 2, wcy - 1, 2, 1);

  // Bottom knob row
  ctx.fillStyle = C.darkest;
  for (let i = 0; i < 3; i++) {
    const kx = px + 4 + i * 8;
    const ky = py + totalH - 5;
    ctx.fillRect(kx, ky, 3, 3);
    ctx.fillStyle = C.lightest;
    ctx.fillRect(kx + 1, ky, 1, 1);
    ctx.fillStyle = C.darkest;
  }

  // Subtle pulsing power LED — top-right
  const blink = Math.floor(t / 360) % 2 === 0;
  ctx.fillStyle = blink ? C.lightest : C.dark;
  ctx.fillRect(px + totalW - 4, py + 3, 2, 2);

  // Side highlight
  ctx.fillStyle = C.light;
  ctx.fillRect(px + 1, py + 1, 1, totalH - 2);
  // Bottom shadow
  ctx.fillStyle = C.darkest;
  ctx.fillRect(px, py + totalH - 1, totalW, 1);
}

// Variant 1: Tall pointed hat (2-px hat above head)
function drawVillagerV1(ctx, px, py, n, t) {
  const bob = Math.floor((t + (n.tx * 213) + (n.ty * 137)) / 480) % 2;
  const oy = py + bob;
  shadowBlock(ctx, px, py);

  // 2-pixel-tall pointed hat above head
  ctx.fillStyle = C.darkest;
  ctx.fillRect(px+7, oy+0, 2, 1);   // tip
  ctx.fillRect(px+6, oy+1, 4, 1);
  // brim
  ctx.fillStyle = C.darkest;
  ctx.fillRect(px+4, oy+2, 8, 1);

  // Round head
  ctx.fillStyle = C.darkest;
  ctx.fillRect(px+5, oy+3, 6, 5);
  ctx.fillStyle = C.dark;
  ctx.fillRect(px+5, oy+4, 6, 3);
  npcEyes(ctx, px, oy + 4, n.dir);
  ctx.fillStyle = C.darkest;
  ctx.fillRect(px+6, oy+7, 4, 1);   // frown

  // Body — vest
  ctx.fillStyle = C.dark;
  ctx.fillRect(px+4, oy+8, 8, 5);
  ctx.fillStyle = C.darkest;
  ctx.fillRect(px+5, oy+9, 2, 1);
  ctx.fillRect(px+9, oy+9, 2, 1);
  // Crossed arms
  ctx.fillRect(px+3, oy+9, 1, 3);
  ctx.fillRect(px+12, oy+9, 1, 3);
  // Legs
  ctx.fillRect(px+5, oy+13, 2, 2);
  ctx.fillRect(px+9, oy+13, 2, 2);
}

// Variant 2: Elongated dress/robe base
function drawVillagerV2(ctx, px, py, n, t) {
  const bob = Math.floor((t + (n.tx * 199) + (n.ty * 311)) / 520) % 2;
  const oy = py + bob;
  shadowBlock(ctx, px, py);

  // Hair cap on head (dark fringe)
  ctx.fillStyle = C.darkest;
  ctx.fillRect(px+4, oy+2, 8, 2);
  ctx.fillRect(px+5, oy+1, 6, 1);

  // Face
  ctx.fillStyle = C.dark;
  ctx.fillRect(px+5, oy+4, 6, 3);
  npcEyes(ctx, px, oy + 4, n.dir);
  // small mouth
  ctx.fillStyle = C.darkest;
  ctx.fillRect(px+7, oy+7, 2, 1);

  // Robe / dress — wider and longer (extends to ground)
  ctx.fillStyle = C.darkest;
  // outline
  ctx.fillRect(px+3, oy+8, 10, 7);
  ctx.fillRect(px+2, oy+10, 12, 5);
  // interior
  ctx.fillStyle = C.dark;
  ctx.fillRect(px+4, oy+8, 8, 6);
  ctx.fillRect(px+3, oy+10, 10, 4);
  // sash / belt
  ctx.fillStyle = C.darkest;
  ctx.fillRect(px+4, oy+11, 8, 1);
  // hem trim
  ctx.fillStyle = C.lightest;
  ctx.fillRect(px+3, oy+14, 10, 1);
  // arms
  ctx.fillStyle = C.darkest;
  ctx.fillRect(px+2, oy+9, 1, 3);
  ctx.fillRect(px+13, oy+9, 1, 3);
}

// Variant 3: Altered hair/head shading + bandana — shorter stature
function drawVillagerV3(ctx, px, py, n, t) {
  const bob = Math.floor((t + (n.tx * 157) + (n.ty * 91)) / 440) % 2;
  const oy = py + bob;
  shadowBlock(ctx, px, py);

  // Bandana on head (lightest band) — different hair shading
  ctx.fillStyle = C.darkest;
  ctx.fillRect(px+4, oy+2, 8, 4);   // skull
  ctx.fillStyle = C.lightest;
  ctx.fillRect(px+4, oy+3, 8, 1);   // bandana band
  ctx.fillStyle = C.darkest;
  ctx.fillRect(px+5, oy+3, 1, 1);
  ctx.fillRect(px+10, oy+3, 1, 1);
  // Bandana knot on side
  if (n.dir === "left") {
    ctx.fillStyle = C.lightest;
    ctx.fillRect(px+3, oy+3, 1, 2);
    ctx.fillRect(px+2, oy+4, 1, 1);
  } else {
    ctx.fillStyle = C.lightest;
    ctx.fillRect(px+12, oy+3, 1, 2);
    ctx.fillRect(px+13, oy+4, 1, 1);
  }

  // Face
  ctx.fillStyle = C.dark;
  ctx.fillRect(px+5, oy+5, 6, 3);
  // Cross-hatch sideburns (altered hair shading)
  ctx.fillStyle = C.darkest;
  ctx.fillRect(px+4, oy+6, 1, 1);
  ctx.fillRect(px+11, oy+6, 1, 1);
  // Eyes (sharper, narrow)
  npcEyes(ctx, px, oy + 5, n.dir);
  // Smirk
  ctx.fillStyle = C.darkest;
  ctx.fillRect(px+7, oy+7, 3, 1);
  ctx.fillRect(px+9, oy+8, 1, 1);

  // Body — sleeveless shirt, more skin showing (light arms)
  ctx.fillStyle = C.dark;
  ctx.fillRect(px+5, oy+8, 6, 4);
  ctx.fillStyle = C.darkest;
  ctx.fillRect(px+5, oy+8, 6, 1);
  // Bare arms
  ctx.fillStyle = C.light;
  ctx.fillRect(px+3, oy+8, 2, 4);
  ctx.fillRect(px+11, oy+8, 2, 4);
  // Belt
  ctx.fillStyle = C.darkest;
  ctx.fillRect(px+5, oy+11, 6, 1);
  // Pants
  ctx.fillStyle = C.darkest;
  ctx.fillRect(px+5, oy+12, 6, 2);
  // Boots
  ctx.fillRect(px+5, oy+13, 2, 2);
  ctx.fillRect(px+9, oy+13, 2, 2);
}

function npcEyes(ctx, px, oy, dir) {
  ctx.fillStyle = C.darkest;
  if (dir === "left")  { ctx.fillRect(px+5, oy+1, 2, 1); }
  else if (dir === "right") { ctx.fillRect(px+9, oy+1, 2, 1); }
  else {
    ctx.fillRect(px+5, oy+1, 2, 1);
    ctx.fillRect(px+9, oy+1, 2, 1);
  }
}

function shadowBlock(ctx, px, py) {
  ctx.fillStyle = C.darkest;
  ctx.globalAlpha = 0.35;
  ctx.fillRect(px+3, py+14, 10, 2);
  ctx.globalAlpha = 1;
}

// =====================================================================
// CLERK (on a stool, with visor and apron, behind counter)
// =====================================================================
function drawClerk(ctx, px, py, n, t) {
  shadowBlock(ctx, px, py);

  // Stool legs (behind the clerk, peeking around legs)
  ctx.fillStyle = C.darkest;
  ctx.fillRect(px+4, py+13, 1, 2);
  ctx.fillRect(px+11, py+13, 1, 2);
  // Stool seat (small)
  ctx.fillRect(px+4, py+12, 8, 1);
  ctx.fillStyle = C.dark;
  ctx.fillRect(px+5, py+12, 6, 1);

  // Visor band
  ctx.fillStyle = C.darkest;
  ctx.fillRect(px+4, py+2, 8, 1);
  ctx.fillStyle = C.lightest;
  ctx.fillRect(px+4, py+3, 8, 1);
  ctx.fillStyle = C.darkest;
  ctx.fillRect(px+5, py+1, 6, 1);

  // Face — squint
  ctx.fillStyle = C.dark;
  ctx.fillRect(px+5, py+4, 6, 3);
  ctx.fillStyle = C.darkest;
  ctx.fillRect(px+5, py+5, 2, 1);
  ctx.fillRect(px+9, py+5, 2, 1);
  ctx.fillRect(px+6, py+7, 4, 1);   // scowl

  // Torso — apron over shirt
  ctx.fillStyle = C.darkest;
  ctx.fillRect(px+4, py+7, 8, 6);
  ctx.fillStyle = C.lightest;
  ctx.fillRect(px+5, py+8, 6, 4);   // apron front
  ctx.fillStyle = C.darkest;
  // apron straps over shoulders
  ctx.fillRect(px+6, py+7, 1, 5);
  ctx.fillRect(px+9, py+7, 1, 5);
  // neck tie
  ctx.fillRect(px+7, py+7, 2, 1);
  // pocket
  ctx.fillStyle = C.dark;
  ctx.fillRect(px+7, py+10, 2, 1);

  // Arms gripping counter
  ctx.fillStyle = C.darkest;
  ctx.fillRect(px+3, py+8, 1, 4);
  ctx.fillRect(px+12, py+8, 1, 4);
}

// =====================================================================
// MONSTER
// =====================================================================
function drawMonster(ctx, e, t) {
  const px = Math.round(e.x * TILE);
  const py = Math.round(e.y * TILE) + PLAY_TOP;
  const bob = Math.floor((t + e.wobble * 1000) / 220) % 2;
  const oy = py + bob;

  ctx.fillStyle = C.darkest;
  ctx.globalAlpha = 0.5;
  ctx.fillRect(px+3, py+14, 10, 2);
  ctx.globalAlpha = 1;

  ctx.fillStyle = C.darkest;
  ctx.fillRect(px+4, oy+5, 8, 8);
  ctx.fillRect(px+3, oy+7, 10, 5);
  ctx.fillRect(px+5, oy+4, 6, 1);
  ctx.fillRect(px+4, oy+3, 1, 2);
  ctx.fillRect(px+11, oy+3, 1, 2);
  ctx.fillRect(px+4, oy+13, 2, 1);
  ctx.fillRect(px+10, oy+13, 2, 1);

  let exL = 6, exR = 9, ey = 7;
  if (e.dir === "left")  { exL -= 1; exR -= 1; }
  if (e.dir === "right") { exL += 1; exR += 1; }
  if (e.dir === "up")    { ey -= 1; }
  if (e.dir === "down")  { ey += 1; }
  ctx.fillStyle = C.lightest;
  ctx.fillRect(px+exL, oy+ey, 1, 2);
  ctx.fillRect(px+exR, oy+ey, 1, 2);

  ctx.fillStyle = C.light;
  ctx.fillRect(px+6, oy+11, 1, 1);
  ctx.fillRect(px+8, oy+11, 1, 1);
  ctx.fillRect(px+7, oy+12, 1, 1);
  ctx.fillRect(px+9, oy+12, 1, 1);
}

// =====================================================================
// CHEST
// =====================================================================
function drawChest(ctx, chest, opened, t) {
  const px = chest.tx * TILE;
  const py = chest.ty * TILE + PLAY_TOP;

  ctx.fillStyle = C.darkest;
  ctx.globalAlpha = 0.5;
  ctx.fillRect(px+1, py+13, 14, 2);
  ctx.globalAlpha = 1;

  ctx.fillStyle = C.darkest;
  ctx.fillRect(px+1, py+3, 14, 12);
  ctx.fillStyle = opened ? C.dark : C.light;
  ctx.fillRect(px+2, py+4, 12, 10);
  ctx.fillStyle = C.darkest;
  ctx.fillRect(px+2, py+8, 12, 1);
  ctx.fillRect(px+7, py+3, 2, 12);
  ctx.fillRect(px+1, py+7, 14, 2);
  if (!opened) {
    const glint = Math.floor(t / 360) % 4 === 0;
    if (glint) {
      ctx.fillStyle = C.lightest;
      ctx.fillRect(px+4, py+5, 1, 1);
      ctx.fillRect(px+5, py+4, 1, 1);
    }
    ctx.fillStyle = C.darkest;
    ctx.fillRect(px+7, py+9, 2, 3);
  } else {
    ctx.fillStyle = C.darkest;
    ctx.fillRect(px+3, py+4, 10, 4);
  }
}

// =====================================================================
// GLOWING TAPE (drops on monster field)
// =====================================================================
function drawGlowingTape(ctx, item, t) {
  const px = Math.round(item.tx * TILE);
  const py = Math.round(item.ty * TILE) + PLAY_TOP;
  const bob = Math.sin(t / 220) * 2;
  const cy = py + bob;

  // Pulsing halo
  const pulse = (Math.sin(t / 240) + 1) / 2;
  ctx.globalAlpha = 0.25 + 0.25 * pulse;
  ctx.fillStyle = C.lightest;
  ctx.fillRect(px - 1, cy + 4, TILE + 2, 8);
  ctx.fillRect(px + 2, cy + 1, TILE - 4, 14);
  ctx.globalAlpha = 1;

  // Cassette body
  ctx.fillStyle = C.darkest;
  ctx.fillRect(px+2, cy+5, 12, 8);
  ctx.fillStyle = C.lightest;
  ctx.fillRect(px+3, cy+6, 10, 6);
  ctx.fillStyle = C.darkest;
  // Reels
  ctx.fillRect(px+4, cy+7, 3, 3);
  ctx.fillRect(px+9, cy+7, 3, 3);
  ctx.fillStyle = C.lightest;
  ctx.fillRect(px+5, cy+8, 1, 1);
  ctx.fillRect(px+10, cy+8, 1, 1);
  // Tape window
  ctx.fillStyle = C.dark;
  ctx.fillRect(px+5, cy+11, 6, 1);
  // Label "B-SIDES" hint (just a stripe)
  ctx.fillStyle = C.light;
  ctx.fillRect(px+3, cy+6, 10, 1);

  // Sparkles around
  const spark = Math.floor(t / 180) % 6;
  ctx.fillStyle = C.lightest;
  if (spark === 0) ctx.fillRect(px+0, cy+3, 1, 1);
  if (spark === 1) ctx.fillRect(px+15, cy+4, 1, 1);
  if (spark === 2) ctx.fillRect(px+1, cy+14, 1, 1);
  if (spark === 3) ctx.fillRect(px+14, cy+14, 1, 1);
  if (spark === 4) ctx.fillRect(px+7, cy+0, 1, 1);
}

// =====================================================================
// GUARD (south-gate sentry, helmet + spear)
// =====================================================================
function drawGuard(ctx, px, py, n, t) {
  const bob = Math.floor((t + (n.tx * 213)) / 520) % 2;
  const oy = py + bob;
  shadowBlock(ctx, px, py);

  // Spear — diagonal across body
  ctx.fillStyle = C.darkest;
  ctx.fillRect(px+13, oy-3, 1, 18);
  ctx.fillStyle = C.lightest;
  ctx.fillRect(px+13, oy-4, 2, 2);  // spearhead

  // Helmet — rounded with plume
  ctx.fillStyle = C.darkest;
  ctx.fillRect(px+5, oy+1, 6, 3);
  ctx.fillRect(px+4, oy+2, 8, 2);
  // plume crest
  ctx.fillStyle = C.dark;
  ctx.fillRect(px+7, oy+0, 2, 1);
  ctx.fillRect(px+7, oy-1, 2, 1);
  // visor slit
  ctx.fillStyle = C.lightest;
  ctx.fillRect(px+5, oy+3, 6, 1);

  // Face
  ctx.fillStyle = C.dark;
  ctx.fillRect(px+5, oy+4, 6, 3);
  // stern eyes
  ctx.fillStyle = C.darkest;
  ctx.fillRect(px+5, oy+5, 2, 1);
  ctx.fillRect(px+9, oy+5, 2, 1);
  // mustache
  ctx.fillRect(px+5, oy+7, 6, 1);

  // Body — armor breastplate
  ctx.fillStyle = C.darkest;
  ctx.fillRect(px+3, oy+8, 10, 5);
  ctx.fillStyle = C.light;
  ctx.fillRect(px+4, oy+9, 8, 3);
  // central stripe / emblem
  ctx.fillStyle = C.darkest;
  ctx.fillRect(px+7, oy+9, 2, 3);
  ctx.fillStyle = C.lightest;
  ctx.fillRect(px+7, oy+10, 2, 1);
  // shoulder pauldrons
  ctx.fillStyle = C.darkest;
  ctx.fillRect(px+3, oy+8, 2, 2);
  ctx.fillRect(px+11, oy+8, 2, 2);

  // Legs / boots
  ctx.fillStyle = C.darkest;
  ctx.fillRect(px+5, oy+13, 2, 2);
  ctx.fillRect(px+9, oy+13, 2, 2);
}

// =====================================================================
// GRANDMA (kind/judgmental old lady NPC)
// =====================================================================
// GRANDMA — hi-contrast: heavy darkest outline + lightest filler so she
// reads clearly against the lightest floor.
// =====================================================================
function drawGrandma(ctx, px, py, n, t) {
  const bob = Math.floor((t + (n.tx * 199)) / 540) % 2;
  const oy = py + bob;

  // Shadow under feet (dark on lightest floor)
  ctx.fillStyle = C.darkest;
  ctx.globalAlpha = 0.5;
  ctx.fillRect(px+3, py+14, 10, 2);
  ctx.globalAlpha = 1;

  // ===== HARD DARKEST OUTLINE SILHOUETTE =====
  // Head silhouette outline (rounded square)
  ctx.fillStyle = C.darkest;
  ctx.fillRect(px+4, oy+0, 8, 1);     // top of bun
  ctx.fillRect(px+3, oy+1, 10, 1);
  ctx.fillRect(px+3, oy+2, 10, 6);    // head/hair box
  // Body silhouette (wider dress)
  ctx.fillRect(px+2, oy+8, 12, 7);    // shawl shoulders + dress
  ctx.fillRect(px+1, oy+10, 14, 5);   // wide hem

  // ===== LIGHTEST FACE FILL =====
  ctx.fillStyle = C.lightest;
  ctx.fillRect(px+5, oy+4, 6, 3);     // face panel

  // Glasses (darkest rims, lightest lenses behind)
  ctx.fillStyle = C.darkest;
  ctx.fillRect(px+5, oy+4, 2, 1);
  ctx.fillRect(px+5, oy+5, 1, 2);
  ctx.fillRect(px+6, oy+6, 1, 1);
  ctx.fillRect(px+7, oy+5, 1, 1);     // bridge
  ctx.fillRect(px+9, oy+4, 2, 1);
  ctx.fillRect(px+10, oy+5, 1, 2);
  ctx.fillRect(px+9, oy+6, 1, 1);
  // Tight pursed mouth
  ctx.fillStyle = C.darkest;
  ctx.fillRect(px+7, oy+7, 2, 1);

  // Hair bun on top — lightest highlight
  ctx.fillStyle = C.lightest;
  ctx.fillRect(px+6, oy+1, 4, 1);
  // a couple of grey-hair strands
  ctx.fillStyle = C.light;
  ctx.fillRect(px+4, oy+2, 8, 1);

  // ===== SHAWL (lightest with darkest fringe) =====
  ctx.fillStyle = C.lightest;
  ctx.fillRect(px+3, oy+9, 10, 3);    // shawl over shoulders
  // shawl dotted trim
  ctx.fillStyle = C.darkest;
  ctx.fillRect(px+4, oy+9, 1, 1);
  ctx.fillRect(px+7, oy+9, 1, 1);
  ctx.fillRect(px+10, oy+9, 1, 1);
  ctx.fillRect(px+3, oy+11, 1, 1);
  ctx.fillRect(px+6, oy+11, 1, 1);
  ctx.fillRect(px+9, oy+11, 1, 1);
  ctx.fillRect(px+12, oy+11, 1, 1);

  // ===== DRESS BODY (darkest with lightest hem) =====
  ctx.fillStyle = C.darkest;
  ctx.fillRect(px+3, oy+12, 10, 3);
  ctx.fillStyle = C.lightest;
  ctx.fillRect(px+2, oy+13, 12, 1);   // hem highlight
  ctx.fillRect(px+1, oy+14, 14, 1);   // bottom edge band

  // Folded arms (darkest with lightest cuffs)
  ctx.fillStyle = C.darkest;
  ctx.fillRect(px+2, oy+9, 1, 3);
  ctx.fillRect(px+13, oy+9, 1, 3);
  ctx.fillStyle = C.lightest;
  ctx.fillRect(px+2, oy+11, 1, 1);
  ctx.fillRect(px+13, oy+11, 1, 1);
}

// =====================================================================
// SLEEPING MAN — 2-tile wide horizontal sprite, lying flat on his back.
// Occupies (n.tx, n.ty) AND (n.tx+1, n.ty). Drawn across 32 px.
// =====================================================================
function drawSleepingMan(ctx, px, py, n, t) {
  // Shadow across whole 32-px body
  ctx.fillStyle = C.darkest;
  ctx.globalAlpha = 0.4;
  ctx.fillRect(px+1, py+14, 30, 2);
  ctx.globalAlpha = 1;

  // ===== Hard darkest body outline =====
  // The body runs from x=2 to x=30, head on RIGHT, feet on LEFT.
  ctx.fillStyle = C.darkest;
  // Outline top
  ctx.fillRect(px+3, py+6, 22, 1);
  // Outline bottom
  ctx.fillRect(px+3, py+13, 22, 1);
  // Left + right outline edges
  ctx.fillRect(px+3, py+7, 1, 6);
  // Head silhouette on the right (~24..30)
  ctx.fillRect(px+24, py+4, 7, 1);
  ctx.fillRect(px+24, py+13, 7, 1);
  ctx.fillRect(px+30, py+5, 1, 8);
  ctx.fillRect(px+24, py+5, 1, 8);

  // ===== Body (blanket) =====
  ctx.fillStyle = C.dark;
  ctx.fillRect(px+4, py+7, 20, 6);
  // crease/seam down the middle of the blanket
  ctx.fillStyle = C.darkest;
  ctx.fillRect(px+4, py+10, 20, 1);
  // tiny rumple dots
  ctx.fillStyle = C.lightest;
  ctx.fillRect(px+7, py+8, 1, 1);
  ctx.fillRect(px+12, py+9, 1, 1);
  ctx.fillRect(px+18, py+8, 1, 1);
  ctx.fillRect(px+21, py+11, 1, 1);

  // ===== Head (right end) =====
  ctx.fillStyle = C.lightest;
  ctx.fillRect(px+25, py+5, 5, 8);   // face fill
  // closed eye (under brow)
  ctx.fillStyle = C.darkest;
  ctx.fillRect(px+26, py+8, 3, 1);
  // eyebrow
  ctx.fillRect(px+26, py+6, 3, 1);
  // open snoring mouth
  ctx.fillRect(px+27, py+10, 2, 2);
  ctx.fillStyle = C.dark;
  ctx.fillRect(px+28, py+11, 1, 1);
  // ear/jaw shading
  ctx.fillStyle = C.dark;
  ctx.fillRect(px+29, py+8, 1, 3);

  // ===== Feet (left end) =====
  ctx.fillStyle = C.darkest;
  // boot soles sticking out flat
  ctx.fillRect(px+0, py+8, 3, 5);
  ctx.fillStyle = C.lightest;
  ctx.fillRect(px+0, py+10, 1, 1);
  ctx.fillRect(px+0, py+12, 1, 1);

  // ZZZ snore animation above the head
  const phase = Math.floor(t / 600) % 3;
  ctx.fillStyle = C.darkest;
  for (let i = 0; i <= phase; i++) {
    const off = i * 4;
    drawTinyZ(ctx, px + 28 + off, py - 2 - i * 3);
  }
}

function drawTinyZ(ctx, x, y) {
  ctx.fillRect(x,     y,     3, 1);
  ctx.fillRect(x + 2, y + 1, 1, 1);
  ctx.fillRect(x + 1, y + 2, 1, 1);
  ctx.fillRect(x,     y + 3, 3, 1);
}

// =====================================================================
// BAT (flying enemy)
// =====================================================================
function drawBat(ctx, e, t) {
  const px = Math.round(e.x * TILE);
  const py = Math.round(e.y * TILE) + PLAY_TOP;
  const flap = Math.floor((t + e.wobble * 1000) / 110) % 2;
  const fy = Math.floor(Math.sin((t + e.wobble * 600) / 220) * 2);

  // shadow (no ground shadow — flying — tiny pulsing dot)
  ctx.fillStyle = C.darkest;
  ctx.globalAlpha = 0.35;
  ctx.fillRect(px+5, py+14, 6, 2);
  ctx.globalAlpha = 1;

  // Body (small triangular)
  ctx.fillStyle = C.darkest;
  ctx.fillRect(px+6, py+5+fy, 4, 5);
  // pointed ears
  ctx.fillRect(px+6, py+3+fy, 1, 2);
  ctx.fillRect(px+9, py+3+fy, 1, 2);
  // glowing eyes
  ctx.fillStyle = C.lightest;
  ctx.fillRect(px+6, py+6+fy, 1, 1);
  ctx.fillRect(px+9, py+6+fy, 1, 1);
  // fangs
  ctx.fillStyle = C.lightest;
  ctx.fillRect(px+7, py+9+fy, 1, 1);
  ctx.fillRect(px+8, py+9+fy, 1, 1);

  // Wings (alternating flap)
  ctx.fillStyle = C.darkest;
  if (flap === 0) {
    // wings up
    ctx.fillRect(px+1, py+3+fy, 5, 1);
    ctx.fillRect(px+2, py+4+fy, 4, 2);
    ctx.fillRect(px+3, py+6+fy, 3, 1);
    ctx.fillRect(px+10, py+3+fy, 5, 1);
    ctx.fillRect(px+10, py+4+fy, 4, 2);
    ctx.fillRect(px+10, py+6+fy, 3, 1);
  } else {
    // wings down
    ctx.fillRect(px+1, py+7+fy, 5, 1);
    ctx.fillRect(px+2, py+6+fy, 4, 2);
    ctx.fillRect(px+3, py+5+fy, 3, 1);
    ctx.fillRect(px+10, py+7+fy, 5, 1);
    ctx.fillRect(px+10, py+6+fy, 4, 2);
    ctx.fillRect(px+10, py+5+fy, 3, 1);
  }
}

// =====================================================================
// PURSE (on grandma's counter)
// =====================================================================
// PURSE (sits on grandma's counter) — hi-contrast: darkest outline + lightest fill
// =====================================================================
function drawPurse(ctx, item, t) {
  const px = Math.round(item.tx * TILE);
  const py = Math.round(item.ty * TILE) + PLAY_TOP;

  // Drop shadow underneath
  ctx.fillStyle = C.darkest;
  ctx.globalAlpha = 0.45;
  ctx.fillRect(px+2, py+14, 12, 1);
  ctx.globalAlpha = 1;

  // ===== Outline silhouette (heavy darkest border) =====
  ctx.fillStyle = C.darkest;
  // Body box
  ctx.fillRect(px+2, py+5, 12, 1);  // top
  ctx.fillRect(px+2, py+14, 12, 1); // bottom
  ctx.fillRect(px+1, py+6, 1, 8);   // left
  ctx.fillRect(px+14, py+6, 1, 8);  // right
  // Corner rounding
  ctx.fillRect(px+2, py+13, 1, 1);
  ctx.fillRect(px+13, py+13, 1, 1);

  // ===== Lightest body fill =====
  ctx.fillStyle = C.lightest;
  ctx.fillRect(px+2, py+6, 12, 8);

  // Stitch / belt
  ctx.fillStyle = C.darkest;
  ctx.fillRect(px+2, py+9, 12, 1);
  // Stud accents
  ctx.fillRect(px+4, py+11, 1, 1);
  ctx.fillRect(px+8, py+11, 1, 1);
  ctx.fillRect(px+11, py+11, 1, 1);

  // Center clasp — darkest disc with lightest spot
  ctx.fillStyle = C.darkest;
  ctx.fillRect(px+7, py+7, 2, 2);
  // Clasp gemstone
  ctx.fillStyle = C.lightest;
  ctx.fillRect(px+7, py+7, 1, 1);

  // Handle (arched darkest line above body)
  ctx.fillStyle = C.darkest;
  ctx.fillRect(px+5, py+2, 6, 1);
  ctx.fillRect(px+4, py+3, 1, 2);
  ctx.fillRect(px+11, py+3, 1, 2);
  ctx.fillRect(px+5, py+4, 1, 1);
  ctx.fillRect(px+10, py+4, 1, 1);

  // Cash/coin sparkle peeking from top — animated
  const sparkle = Math.floor(t / 240) % 4;
  if (sparkle === 0) {
    ctx.fillStyle = C.lightest;
    ctx.fillRect(px+12, py+3, 1, 1);
  } else if (sparkle === 1) {
    ctx.fillStyle = C.lightest;
    ctx.fillRect(px+3, py+4, 1, 1);
  } else if (sparkle === 2) {
    ctx.fillStyle = C.darkest;
    ctx.fillRect(px+13, py+1, 1, 1);
  }
}

// =====================================================================
// PUSHABLE BLOCK (cave puzzle)
// =====================================================================
function drawBlock(ctx, block, t) {
  const px = Math.round(block.x * TILE);
  const py = Math.round(block.y * TILE) + PLAY_TOP;

  // Outer dark frame
  ctx.fillStyle = C.darkest;
  ctx.fillRect(px+1, py+1, TILE-2, TILE-2);
  // Mid block
  ctx.fillStyle = C.dark;
  ctx.fillRect(px+2, py+2, TILE-4, TILE-4);
  // Inner highlight
  ctx.fillStyle = C.light;
  ctx.fillRect(px+3, py+3, TILE-6, TILE-6);
  // Cross-brace lines
  ctx.fillStyle = C.darkest;
  ctx.fillRect(px+3, py+4, TILE-6, 1);
  ctx.fillRect(px+3, py+11, TILE-6, 1);
  ctx.fillRect(px+4, py+5, 1, 6);
  ctx.fillRect(px+11, py+5, 1, 6);
  // Corner studs
  ctx.fillStyle = C.darkest;
  ctx.fillRect(px+2, py+2, 1, 1);
  ctx.fillRect(px+13, py+2, 1, 1);
  ctx.fillRect(px+2, py+13, 1, 1);
  ctx.fillRect(px+13, py+13, 1, 1);
}

// =====================================================================
// EXPORTS
// =====================================================================
Object.assign(window, {
  drawPlayer, drawBard, drawBardCelebration, drawCarriedGuitar,
  drawAttack, drawGuitarSwing,
  drawNpc, drawVillagerV1, drawVillagerV2, drawVillagerV3,
  drawClerk, drawGuard, drawGrandma, drawSleepingMan,
  drawMonster, drawBat, drawChest, drawGlowingTape, drawPurse, drawBlock,
  drawSpeakerStack, drawCelebrationItem,
});
