// ===== 쿠니오군 스타일 픽셀아트 스프라이트 시스템 =====
// 모든 캐릭터를 Canvas에서 직접 픽셀 단위로 그림 (외부 에셋 불필요)

const PX = 2; // 1 스프라이트 픽셀 = 2 실제 픽셀

// 팔레트 프리셋 (머리색, 상의색, 하의색, 피부색)
const PALETTES = [
  { hair: '#2a1a0a', shirt: '#e74c3c', pants: '#2c3e50', skin: '#f5cba7', name: '빨강' },
  { hair: '#1a1a2e', shirt: '#3498db', pants: '#2c3e50', skin: '#f5cba7', name: '파랑' },
  { hair: '#5a3d2b', shirt: '#e67e22', pants: '#34495e', skin: '#fad7a0', name: '주황' },
  { hair: '#8e44ad', shirt: '#9b59b6', pants: '#2c3e50', skin: '#f5cba7', name: '보라' },
  { hair: '#c0392b', shirt: '#f1c40f', pants: '#2c3e50', skin: '#fad7a0', name: '노랑' },
  { hair: '#2ecc71', shirt: '#27ae60', pants: '#1a3c34', skin: '#f5cba7', name: '초록' },
  { hair: '#ecf0f1', shirt: '#ecf0f1', pants: '#2c3e50', skin: '#d4a574', name: '화이트' },
  { hair: '#e91e63', shirt: '#e91e63', pants: '#4a148c', skin: '#f5cba7', name: '핑크' },
  { hair: '#1a1a1a', shirt: '#1a1a1a', pants: '#1a1a1a', skin: '#8d6e63', name: '블랙' },
  { hair: '#ff6b6b', shirt: '#00bcd4', pants: '#37474f', skin: '#fad7a0', name: '시안' },
  { hair: '#f39c12', shirt: '#d35400', pants: '#7f8c8d', skin: '#f5cba7', name: '오렌지' },
  { hair: '#3d5afe', shirt: '#ff4081', pants: '#263238', skin: '#d4a574', name: '네온' },
];

// 헤어스타일 정의 (16x16 그리드 기준, 머리 윗부분)
// 1 = 머리카락, 0 = 빈칸
const HAIRSTYLES = {
  spike: [
    [0,0,0,1,0,1,0,0],
    [0,0,1,1,1,1,1,0],
    [0,1,1,1,1,1,1,1],
    [0,1,1,1,1,1,1,1],
  ],
  bowl: [
    [0,0,1,1,1,1,0,0],
    [0,1,1,1,1,1,1,0],
    [1,1,1,1,1,1,1,1],
    [1,1,1,1,1,1,1,1],
  ],
  mohawk: [
    [0,0,0,1,1,0,0,0],
    [0,0,1,1,1,1,0,0],
    [0,0,1,1,1,1,0,0],
    [0,1,1,1,1,1,1,0],
  ],
  long: [
    [0,0,1,1,1,1,0,0],
    [0,1,1,1,1,1,1,0],
    [1,1,1,1,1,1,1,1],
    [1,1,1,1,1,1,1,1],
  ],
  buzz: [
    [0,0,0,0,0,0,0,0],
    [0,0,1,1,1,1,0,0],
    [0,1,1,1,1,1,1,0],
    [0,1,1,1,1,1,1,0],
  ],
  pompadour: [
    [0,1,1,1,0,0,0,0],
    [1,1,1,1,1,1,0,0],
    [0,1,1,1,1,1,1,0],
    [0,1,1,1,1,1,1,0],
  ],
};

const HAIRSTYLE_NAMES = Object.keys(HAIRSTYLES);

// 캐릭터 스프라이트 데이터 (16x24 그리드)
// 0=투명, S=피부, H=머리카락, T=셔츠, P=바지, E=눈, O=외곽선, W=흰색(눈), B=신발
const SPRITE_FRONT = [
  // 프레임 0 (서있기) - row 0~23
  '0000HHHH0000',
  '000HHHHHH000',
  '00HSSSSSSH00',
  '00SWWEWWES00',
  '00SSSSSSSS00',
  '00OSSSSSSO00',
  '000SSSSSS000',
  '0000TTTT0000',
  '000TTTTTT000',
  '00TTTTTTTT00',
  '00TSTTTTST00',
  '00SSTTTTSS00',
  '000STTTS0000',
  '0000PPPP0000',
  '000PPPPPP000',
  '000PP00PP000',
  '000PP00PP000',
  '000BB00BB000',
];

const SPRITE_FRONT_WALK1 = [
  '0000HHHH0000',
  '000HHHHHH000',
  '00HSSSSSSH00',
  '00SWWEWWES00',
  '00SSSSSSSS00',
  '00OSSSSSSO00',
  '000SSSSSS000',
  '0000TTTT0000',
  '000TTTTTT000',
  '00TTTTTTTT00',
  '00TSTTTTST00',
  '0SSSTTTTSS00',
  '0S00TTTT0000',
  '0000PPPP0000',
  '000PPPPPP000',
  '00PP0000PP00',
  '00PP0000PP00',
  '00BB0000BB00',
];

const SPRITE_FRONT_WALK2 = [
  '0000HHHH0000',
  '000HHHHHH000',
  '00HSSSSSSH00',
  '00SWWEWWES00',
  '00SSSSSSSS00',
  '00OSSSSSSO00',
  '000SSSSSS000',
  '0000TTTT0000',
  '000TTTTTT000',
  '00TTTTTTTT00',
  '00TSTTTTST00',
  '00SSTTTTSS0S',
  '0000TTTT00S0',
  '0000PPPP0000',
  '000PPPPPP000',
  '00PP0000PP00',
  '00PP0000PP00',
  '00BB0000BB00',
];

const SPRITE_SIDE = [
  '000HHHH00000',
  '00HHHHHH0000',
  '00HSSSSSH000',
  '00SWWESSS000',
  '00SSSSSS0000',
  '00OSSSSS0000',
  '000SSSSS0000',
  '0000TTTT0000',
  '000TTTTTT000',
  '00TTTTTTTS00',
  '00TTTTTTSS00',
  '00SSTTTTSS00',
  '000STTTS0000',
  '0000PPPP0000',
  '000PPPPPP000',
  '000PP00PP000',
  '000PP00PP000',
  '000BB00BB000',
];

const SPRITE_SIDE_WALK1 = [
  '000HHHH00000',
  '00HHHHHH0000',
  '00HSSSSSH000',
  '00SWWESSS000',
  '00SSSSSS0000',
  '00OSSSSS0000',
  '000SSSSS0000',
  '0000TTTT0000',
  '000TTTTTT000',
  '00TTTTTTT000',
  '00TTTTTTSS00',
  '00SSTTTTSS00',
  '000STTTS0000',
  '0000PPPP0000',
  '0000PPPP0000',
  '000PP0PP0000',
  '00PP000PP000',
  '00BB000BB000',
];

const SPRITE_SIDE_WALK2 = [
  '000HHHH00000',
  '00HHHHHH0000',
  '00HSSSSSH000',
  '00SWWESSS000',
  '00SSSSSS0000',
  '00OSSSSS0000',
  '000SSSSS0000',
  '0000TTTT0000',
  '000TTTTTT000',
  '00TTTTTTT000',
  '00TTTTTTSS00',
  '00SSTTTTSS00',
  '000STTTS0000',
  '0000PPPP0000',
  '0000PPPP0000',
  '0000PP0PP000',
  '000PP000PP00',
  '000BB000BB00',
];

const SPRITE_BACK = [
  '0000HHHH0000',
  '000HHHHHH000',
  '00HHHHHHHH00',
  '00HHHHHHHH00',
  '00HSSSSSHH00',
  '00SSSSSSSS00',
  '000SSSSSS000',
  '0000TTTT0000',
  '000TTTTTT000',
  '00TTTTTTTT00',
  '00TTTTTTTT00',
  '00SSTTTTSS00',
  '000STTTS0000',
  '0000PPPP0000',
  '000PPPPPP000',
  '000PP00PP000',
  '000PP00PP000',
  '000BB00BB000',
];

// 스프라이트 캐시
const spriteCache = new Map();

function getSpriteFrames(direction) {
  switch (direction) {
    case 'up': return [SPRITE_BACK, SPRITE_BACK, SPRITE_BACK]; // 뒤는 걷기 프레임 생략
    case 'left':
    case 'right': return [SPRITE_SIDE, SPRITE_SIDE_WALK1, SPRITE_SIDE_WALK2];
    default: return [SPRITE_FRONT, SPRITE_FRONT_WALK1, SPRITE_FRONT_WALK2];
  }
}

function getColorForChar(ch, palette) {
  switch (ch) {
    case 'S': return palette.skin;
    case 'H': return palette.hair;
    case 'T': return palette.shirt;
    case 'P': return palette.pants;
    case 'E': return '#1a1a1a';
    case 'W': return '#ffffff';
    case 'O': return palette.skin; // 입 = 피부보다 약간 어둡게
    case 'B': return '#3d2b1f';
    default: return null;
  }
}

function createSpriteCanvas(spriteData, palette, flipX) {
  const key = JSON.stringify({ spriteData: spriteData[0], palette, flipX });
  if (spriteCache.has(key)) return spriteCache.get(key);

  const rows = spriteData.length;
  const cols = spriteData[0].length;
  const offscreen = document.createElement('canvas');
  offscreen.width = cols * PX;
  offscreen.height = rows * PX;
  const octx = offscreen.getContext('2d');

  for (let r = 0; r < rows; r++) {
    for (let c = 0; c < cols; c++) {
      const ch = spriteData[r][flipX ? cols - 1 - c : c];
      const color = getColorForChar(ch, palette);
      if (color) {
        octx.fillStyle = color;
        octx.fillRect(c * PX, r * PX, PX, PX);
      }
    }
  }

  spriteCache.set(key, offscreen);
  return offscreen;
}

// 걷기 프레임 인덱스 (시간 기반)
function getWalkFrame(moving) {
  if (!moving) return 0;
  return (Math.floor(Date.now() / 150) % 2) + 1;
}

// 메인 캐릭터 그리기 함수
function drawPixelCharacter(ctx, x, y, player, isMoving) {
  const paletteIndex = (player.color || 0) % PALETTES.length;
  const palette = PALETTES[paletteIndex];
  const direction = player.direction || 'down';
  const frames = getSpriteFrames(direction);
  const frameIdx = getWalkFrame(isMoving);
  const spriteData = frames[frameIdx] || frames[0];
  const flipX = direction === 'left';

  const spriteCanvas = createSpriteCanvas(spriteData, palette, flipX);

  const drawW = spriteCanvas.width;
  const drawH = spriteCanvas.height;

  // 그림자
  ctx.fillStyle = 'rgba(0,0,0,0.25)';
  ctx.beginPath();
  ctx.ellipse(x, y + drawH / 2 + 2, drawW / 2.5, 4, 0, 0, Math.PI * 2);
  ctx.fill();

  // 스프라이트 그리기 (이미지 스무딩 끄기 = 픽셀 선명하게)
  ctx.imageSmoothingEnabled = false;
  ctx.drawImage(spriteCanvas, x - drawW / 2, y - drawH / 2);
  ctx.imageSmoothingEnabled = true;
}

// 건물 내부용 큰 캐릭터 그리기
function drawPixelCharacterLarge(ctx, x, y, player, scale) {
  const paletteIndex = (player.color || 0) % PALETTES.length;
  const palette = PALETTES[paletteIndex];
  const spriteData = SPRITE_FRONT;
  const spriteCanvas = createSpriteCanvas(spriteData, palette, false);

  const drawW = spriteCanvas.width * scale;
  const drawH = spriteCanvas.height * scale;

  ctx.fillStyle = 'rgba(0,0,0,0.3)';
  ctx.beginPath();
  ctx.ellipse(x, y + drawH / 2 + 4, drawW / 2.5, 6, 0, 0, Math.PI * 2);
  ctx.fill();

  ctx.imageSmoothingEnabled = false;
  ctx.drawImage(spriteCanvas, x - drawW / 2, y - drawH / 2, drawW, drawH);
  ctx.imageSmoothingEnabled = true;
}

// 팔레트 인덱스를 서버 color에서 추출
function getPaletteIndex(color) {
  if (typeof color === 'number') {
    return color % PALETTES.length;
  }
  return 0;
}

// ===== 픽셀아트 맵 타일 =====

// 픽셀아트 나무
function drawPixelTree(ctx, x, y) {
  const s = 2; // 스케일

  // 그림자
  ctx.fillStyle = 'rgba(0,0,0,0.15)';
  ctx.fillRect(x - 8 * s, y + 12 * s, 16 * s, 4 * s);

  // 줄기
  ctx.fillStyle = '#8B5E3C';
  ctx.fillRect(x - 2 * s, y + 4 * s, 4 * s, 10 * s);
  ctx.fillStyle = '#6B4226';
  ctx.fillRect(x - 1 * s, y + 4 * s, 2 * s, 10 * s);

  // 잎 (둥근 픽셀 뭉치)
  ctx.fillStyle = '#2d8a4e';
  ctx.fillRect(x - 7 * s, y - 2 * s, 14 * s, 8 * s);
  ctx.fillRect(x - 6 * s, y - 4 * s, 12 * s, 2 * s);
  ctx.fillRect(x - 5 * s, y - 5 * s, 10 * s, 2 * s);

  // 하이라이트
  ctx.fillStyle = '#3aa85c';
  ctx.fillRect(x - 5 * s, y - 3 * s, 6 * s, 4 * s);
  ctx.fillStyle = '#4cc86c';
  ctx.fillRect(x - 3 * s, y - 4 * s, 4 * s, 2 * s);
}

// 픽셀아트 가로등
function drawPixelLamp(ctx, x, y) {
  const s = 2;
  ctx.fillStyle = '#555';
  ctx.fillRect(x - 1 * s, y - 8 * s, 2 * s, 20 * s);
  ctx.fillStyle = '#777';
  ctx.fillRect(x - 3 * s, y - 10 * s, 6 * s, 3 * s);
  ctx.fillStyle = '#FFE082';
  ctx.fillRect(x - 2 * s, y - 9 * s, 4 * s, 2 * s);
}

// 픽셀아트 건물 그리기
function drawPixelBuilding(ctx, b, idx, players) {
  // 광장은 별도 렌더링
  if (b.isPlaza) {
    drawPixelPlaza(ctx, b, idx, players);
    return;
  }

  const s = 2;

  // 그림자
  ctx.fillStyle = 'rgba(0,0,0,0.2)';
  ctx.fillRect(b.x + 4, b.y + 4, b.w, b.h);

  // 건물별 색상
  const buildingColors = [
    { wall: '#c0392b', wallDark: '#a93226', roof: '#e74c3c' },  // 카페
    { wall: '#2c3e50', wallDark: '#1a252f', roof: '#34495e' },  // 바
    { wall: '#8e6f3e', wallDark: '#725a32', roof: '#a0845c' },  // 서점
    { wall: '#27ae60', wallDark: '#1e8449', roof: '#2ecc71' },  // 공원
    { wall: '#7f8c8d', wallDark: '#616a6b', roof: '#95a5a6' },  // 광장 (사용 안됨)
    { wall: '#2c3e50', wallDark: '#1a252f', roof: '#2980b9' },  // 영화관
    { wall: '#d4a76a', wallDark: '#b8935a', roof: '#e8c48a' },  // 레스토랑
    { wall: '#e8a0bf', wallDark: '#d4879e', roof: '#f0b8d0' },  // 꽃집
    { wall: '#6c3483', wallDark: '#5b2c6f', roof: '#8e44ad' },  // 음악카페
  ];
  const bc = buildingColors[idx % buildingColors.length];

  // 벽면
  ctx.fillStyle = bc.wall;
  ctx.fillRect(b.x, b.y, b.w, b.h);

  // 벽면 어두운 부분 (오른쪽)
  ctx.fillStyle = bc.wallDark;
  ctx.fillRect(b.x + b.w - 6, b.y, 6, b.h);

  // 지붕
  ctx.fillStyle = bc.roof;
  ctx.fillRect(b.x - 4, b.y - 8, b.w + 8, 12);
  ctx.fillStyle = '#333';
  ctx.fillRect(b.x - 4, b.y + 2, b.w + 8, 2);

  // 창문 (픽셀 스타일)
  const winW = 16, winH = 14, winGap = 8;
  const windowCols = Math.floor((b.w - 20) / (winW + winGap));
  const windowRows = Math.floor((b.h - 60) / (winH + winGap));
  const winStartX = b.x + (b.w - windowCols * (winW + winGap) + winGap) / 2;

  for (let row = 0; row < windowRows; row++) {
    for (let col = 0; col < windowCols; col++) {
      const wx = winStartX + col * (winW + winGap);
      const wy = b.y + 20 + row * (winH + winGap);

      ctx.fillStyle = '#1a1a2e';
      ctx.fillRect(wx, wy, winW, winH);

      const lit = ((idx * 7 + row * 3 + col * 5) % 3) !== 0;
      ctx.fillStyle = lit ? '#FFE082' : '#3a3a5e';
      ctx.fillRect(wx + 2, wy + 2, winW - 4, winH - 4);

      if (lit) {
        ctx.fillStyle = '#1a1a2e';
        ctx.fillRect(wx + winW / 2 - 1, wy + 2, 2, winH - 4);
        ctx.fillRect(wx + 2, wy + winH / 2 - 1, winW - 4, 2);
      }
    }
  }

  // 문
  const doorW = 20, doorH = 28;
  const doorX = b.x + b.w / 2 - doorW / 2;
  const doorY = b.y + b.h - doorH;
  ctx.fillStyle = '#5a3d2b';
  ctx.fillRect(doorX, doorY, doorW, doorH);
  ctx.fillStyle = '#3d2517';
  ctx.fillRect(doorX + doorW / 2 - 1, doorY, 2, doorH);
  ctx.fillStyle = '#FFD700';
  ctx.fillRect(doorX + doorW - 6, doorY + doorH / 2 - 1, 3, 3);

  // 간판
  const signW = Math.min(b.w - 20, 80);
  const signX = b.x + b.w / 2 - signW / 2;
  ctx.fillStyle = '#f5f0e0';
  ctx.fillRect(signX, b.y + b.h + 4, signW, 16);
  ctx.fillStyle = '#333';
  ctx.fillRect(signX, b.y + b.h + 4, signW, 2);
  ctx.fillRect(signX, b.y + b.h + 18, signW, 2);

  ctx.fillStyle = '#333';
  ctx.font = 'bold 11px "Noto Sans KR", monospace';
  ctx.textAlign = 'center';
  ctx.fillText(`${b.emoji || ''} ${b.label}`, b.x + b.w / 2, b.y + b.h + 16);

  // 건물 안 인원 뱃지
  let insideCount = 0;
  for (const pid of Object.keys(players)) {
    if (players[pid].insideBuilding === idx) insideCount++;
  }
  if (insideCount > 0) {
    ctx.fillStyle = '#e74c3c';
    ctx.fillRect(b.x + b.w - 14, b.y - 6, 16, 12);
    ctx.fillStyle = '#fff';
    ctx.font = 'bold 9px monospace';
    ctx.fillText(insideCount, b.x + b.w - 6, b.y + 3);
  }

  ctx.textAlign = 'left';
}

// 픽셀아트 지면 타일
function drawPixelGround(ctx, mapData) {
  // 잔디
  ctx.fillStyle = '#5a8f4a';
  ctx.fillRect(0, 0, mapData.width, mapData.height);

  // 잔디 텍스처 (점 패턴)
  ctx.fillStyle = '#4d7a3e';
  for (let x = 0; x < mapData.width; x += 16) {
    for (let y = 0; y < mapData.height; y += 16) {
      if ((x + y) % 32 === 0) {
        ctx.fillRect(x, y, 4, 4);
      }
    }
  }

  // 도로 (가로)
  for (let y = 320; y < mapData.height; y += 320) {
    // 도로 바닥
    ctx.fillStyle = '#6b6b7b';
    ctx.fillRect(0, y - 44, mapData.width, 88);

    // 도로 밝은 부분
    ctx.fillStyle = '#7a7a8a';
    ctx.fillRect(0, y - 42, mapData.width, 84);

    // 보도블럭 (위)
    ctx.fillStyle = '#a0a0a0';
    ctx.fillRect(0, y - 44, mapData.width, 6);
    // 보도블럭 (아래)
    ctx.fillRect(0, y + 38, mapData.width, 6);

    // 중앙선
    ctx.fillStyle = '#f0c040';
    for (let x = 0; x < mapData.width; x += 24) {
      ctx.fillRect(x, y - 2, 14, 4);
    }
  }

  // 도로 (세로)
  for (let x = 448; x < mapData.width; x += 384) {
    ctx.fillStyle = '#6b6b7b';
    ctx.fillRect(x - 44, 0, 88, mapData.height);
    ctx.fillStyle = '#7a7a8a';
    ctx.fillRect(x - 42, 0, 84, mapData.height);

    // 보도블럭
    ctx.fillStyle = '#a0a0a0';
    ctx.fillRect(x - 44, 0, 6, mapData.height);
    ctx.fillRect(x + 38, 0, 6, mapData.height);

    // 중앙선
    ctx.fillStyle = '#f0c040';
    for (let y = 0; y < mapData.height; y += 24) {
      ctx.fillRect(x - 2, y, 4, 14);
    }
  }

  // 교차로 채우기
  for (let y = 320; y < mapData.height; y += 320) {
    for (let x = 448; x < mapData.width; x += 384) {
      ctx.fillStyle = '#7a7a8a';
      ctx.fillRect(x - 44, y - 44, 88, 88);
    }
  }

  // 횡단보도 (픽셀 스타일)
  ctx.fillStyle = '#e0e0e0';
  for (let y = 320; y < mapData.height; y += 320) {
    for (let x = 448; x < mapData.width; x += 384) {
      // 위쪽 횡단보도
      for (let i = -36; i < 36; i += 10) {
        ctx.fillRect(x + i, y - 56, 6, 12);
        ctx.fillRect(x + i, y + 44, 6, 12);
      }
      // 옆쪽 횡단보도
      for (let i = -36; i < 36; i += 10) {
        ctx.fillRect(x - 56, y + i, 12, 6);
        ctx.fillRect(x + 44, y + i, 12, 6);
      }
    }
  }
}

// ===== 픽셀아트 광장 렌더링 =====
function drawPixelPlaza(ctx, b, idx, players) {
  const cx = b.x + b.w / 2;
  const cy = b.y + b.h / 2;

  // 바닥 타일 (밝은 벽돌 패턴)
  ctx.fillStyle = '#c8b89a';
  ctx.fillRect(b.x, b.y, b.w, b.h);

  // 타일 패턴
  for (let tx = b.x; tx < b.x + b.w; tx += 16) {
    for (let ty = b.y; ty < b.y + b.h; ty += 16) {
      const offset = (Math.floor(ty / 16) % 2) * 8;
      ctx.fillStyle = ((tx + offset) / 16 + ty / 16) % 2 === 0 ? '#baa888' : '#d0c0a0';
      ctx.fillRect(tx, ty, 16, 16);
      // 타일 줄눈
      ctx.fillStyle = '#a89878';
      ctx.fillRect(tx, ty, 16, 1);
      ctx.fillRect(tx, ty, 1, 16);
    }
  }

  // 테두리 (낮은 돌담)
  ctx.fillStyle = '#8a8070';
  ctx.fillRect(b.x, b.y, b.w, 4);
  ctx.fillRect(b.x, b.y + b.h - 4, b.w, 4);
  ctx.fillRect(b.x, b.y, 4, b.h);
  ctx.fillRect(b.x + b.w - 4, b.y, 4, b.h);
  // 테두리 하이라이트
  ctx.fillStyle = '#a09888';
  ctx.fillRect(b.x, b.y, b.w, 2);
  ctx.fillRect(b.x, b.y, 2, b.h);

  // 입구 (아래쪽 가운데 열림)
  ctx.fillStyle = '#c8b89a';
  ctx.fillRect(cx - 20, b.y + b.h - 4, 40, 4);
  // 입구 (위쪽 가운데 열림)
  ctx.fillRect(cx - 20, b.y, 40, 4);

  // 분수대 (가운데)
  // 분수대 받침
  ctx.fillStyle = '#706860';
  ctx.fillRect(cx - 24, cy - 12, 48, 32);
  ctx.fillStyle = '#887870';
  ctx.fillRect(cx - 22, cy - 10, 44, 28);
  // 물
  ctx.fillStyle = '#5090c0';
  ctx.fillRect(cx - 18, cy - 6, 36, 20);
  ctx.fillStyle = '#60a8d8';
  ctx.fillRect(cx - 14, cy - 2, 28, 12);
  // 분수 기둥
  ctx.fillStyle = '#888078';
  ctx.fillRect(cx - 4, cy - 20, 8, 16);
  ctx.fillRect(cx - 6, cy - 22, 12, 4);
  // 물줄기 (애니메이션)
  const t = Date.now() / 200;
  ctx.fillStyle = '#80c8f0';
  for (let i = 0; i < 5; i++) {
    const angle = (t + i * 1.25) % (Math.PI * 2);
    const wx = cx + Math.cos(angle) * 8;
    const wy = cy - 18 + Math.sin(angle) * 3 - 4;
    ctx.fillRect(wx - 1, wy, 2, 2);
  }
  // 물 반짝임
  ctx.fillStyle = '#b0e0ff';
  const sparkle = Math.floor(t) % 4;
  ctx.fillRect(cx - 10 + sparkle * 6, cy, 3, 2);
  ctx.fillRect(cx + 4 - sparkle * 4, cy + 6, 3, 2);

  // 벤치 4개 (광장 모서리)
  const benchPositions = [
    [b.x + 16, b.y + 20],
    [b.x + b.w - 40, b.y + 20],
    [b.x + 16, b.y + b.h - 32],
    [b.x + b.w - 40, b.y + b.h - 32],
  ];
  benchPositions.forEach(([bx, by]) => {
    // 벤치 다리
    ctx.fillStyle = '#5a4a3a';
    ctx.fillRect(bx + 2, by + 8, 3, 6);
    ctx.fillRect(bx + 19, by + 8, 3, 6);
    // 벤치 좌석
    ctx.fillStyle = '#8B5E3C';
    ctx.fillRect(bx, by + 4, 24, 5);
    // 벤치 등받이
    ctx.fillStyle = '#7a4e2c';
    ctx.fillRect(bx, by, 24, 5);
  });

  // 가로등 2개
  const lampXs = [b.x + 50, b.x + b.w - 50];
  lampXs.forEach((lx) => {
    ctx.fillStyle = '#555';
    ctx.fillRect(lx - 1, cy - 16, 3, 32);
    ctx.fillStyle = '#777';
    ctx.fillRect(lx - 4, cy - 18, 9, 4);
    ctx.fillStyle = '#FFE082';
    ctx.fillRect(lx - 3, cy - 17, 7, 3);
  });

  // 화분/꽃 장식
  const flowerSpots = [
    [b.x + 36, cy - 4], [b.x + b.w - 44, cy - 4],
    [cx - 40, b.y + 14], [cx + 32, b.y + 14],
  ];
  flowerSpots.forEach(([fx, fy], i) => {
    // 화분
    ctx.fillStyle = '#a0604a';
    ctx.fillRect(fx, fy + 4, 10, 8);
    ctx.fillStyle = '#b07058';
    ctx.fillRect(fx - 1, fy + 3, 12, 3);
    // 꽃
    const colors = ['#e74c3c', '#f1c40f', '#e91e63', '#9b59b6'];
    ctx.fillStyle = colors[i % colors.length];
    ctx.fillRect(fx + 1, fy - 2, 4, 4);
    ctx.fillRect(fx + 5, fy, 4, 4);
    // 줄기
    ctx.fillStyle = '#27ae60';
    ctx.fillRect(fx + 4, fy + 2, 2, 3);
  });

  // 라벨
  ctx.fillStyle = '#f5f0e0';
  const signW = 70;
  ctx.fillRect(cx - signW / 2, b.y + b.h + 4, signW, 16);
  ctx.fillStyle = '#333';
  ctx.fillRect(cx - signW / 2, b.y + b.h + 4, signW, 2);
  ctx.fillRect(cx - signW / 2, b.y + b.h + 18, signW, 2);
  ctx.font = 'bold 11px "Noto Sans KR", monospace';
  ctx.textAlign = 'center';
  ctx.fillText('⛲ 광장', cx, b.y + b.h + 16);

  // 광장 안 인원 뱃지
  let insideCount = 0;
  for (const pid of Object.keys(players)) {
    if (players[pid].insideBuilding === idx) insideCount++;
  }
  if (insideCount > 0) {
    ctx.fillStyle = '#e74c3c';
    ctx.fillRect(b.x + b.w - 14, b.y - 6, 16, 12);
    ctx.fillStyle = '#fff';
    ctx.font = 'bold 9px monospace';
    ctx.fillText(insideCount, b.x + b.w - 6, b.y + 3);
  }
  ctx.textAlign = 'left';
}
