How to place ${tip.kind === 'block' ? 'Drag for a line, Shift-drag for a rectangle; out of reach becomes ghosts.' : 'Click to place.'}${tip.dirs && tip.kind === 'block' ? ' A dragged line runs the way you drag it; a single click uses R.' : tip.dirs ? ' R turns it.' : pieceUsesWall(tip) ? ' R cycles materials; F opens the material menu.' : ''}
${tip.filter ? `
New ones will ${esc(filterSentence(GAME.filterCfg))}. F sets materials and mode (or click materials in the bag, or T over one); F on a placed filter changes its whole row.
` : ''}
hold G replace · Ctrl+Z undo · right click take back · middle mouse pick · hold C/X copy/cut · V paste
`;
const tile = bar.querySelector(`[data-piece="${tip.id}"]`); if (!tile) { pop.hidden = true; return; }
const r = tile.getBoundingClientRect(), br = bar.getBoundingClientRect(), w = pop.getBoundingClientRect().width;
pop.style.left = `${Math.max(8, Math.min(innerWidth - w - 8, r.left + r.width / 2 - w / 2)) - br.left}px`;
}
function setupBuildBar() {
$('selcard').addEventListener('click', e => { if (e.target.closest('[data-wall-picker]')) openWallPicker(); });
const bar = $('buildbar'); if (!bar) return;
bar.addEventListener('click', e => {
const t = e.target.closest('[data-cat],[data-piece]'); if (!t) return;
if (t.dataset.cat != null) { selectBuildCat(+t.dataset.cat); return; }
GAME.pieceIdx = PIECE_BY_ID[t.dataset.piece].index; GAME.buildCat = catOf(t.dataset.piece);
GAME.catPick = GAME.catPick || {}; GAME.catPick[catOf(piece().id)] = piece().id;
GAME.drag = null; hudDirty = true; lastBuildKey = ''; playSfx('ui');
});
bar.addEventListener('mouseover', e => { const t = e.target.closest('[data-piece]'); const id = t ? t.dataset.piece : null; if (id !== GAME.bbHover) { GAME.bbHover = id; } });
bar.addEventListener('mouseleave', () => { GAME.bbHover = null; });
// clicks on the menu never reach the world
bar.addEventListener('mousedown', e => e.stopPropagation());
}