<!-- SAGA · part 65 -->
py+fz*20); ctx.stroke();
  /* coordinates */
  ctx.fillStyle = '#ffd700'; ctx.font = '11px monospace';
  ctx.fillText(Math.round(kingPos.x)+','+Math.round(kingPos.z), 8, H-8);
  /* redraw while open */
  if(mapOpen) requestAnimationFrame(drawMap);
}

/* ===== PRECISE COMPASS — true degrees ===== */
var compassEl = null;
function updateCompass(){
  if(!compassEl){
    compassEl = document.createElement('div');
    compassEl.style.cssText = 'position:fixed;top:70px;left:12px;z-index:90;width:60px;height:60px;border-radius:50%;background:#141006;border:2px solid #d8a920;display:flex;align-items:center;justify-content:center;color:#ffd700;font:11px monospace;';
    document.body.appendChild(compassEl);
  }
  var deg = Math.round(((camYaw*180/Math.PI)%360+360)%360);
  var dirs = ['E','SE','S','SW','W','NW','N','NE'];
  var dir = dirs[Math.round(deg/45)%8];
  compassEl.textContent = deg+'° '+dir;
}
/* update compass in animate loop */
var _origUpdateCam = updateCamera;
updateCamera = function(){
  _origUpdateCam();
  if(compassEl) updateCompass();
};

/* ===== 56 BUTTONS — uniform, intricate ===== */
var BTNS = [
  ['p1-temple','Build district',function(){ nextDistrict(); }],
  ['p1-map','Map',function(){ toggleMap(); }],
  ['p1-camera','Camera',function(){ toggleCamera(); }],
  ['p1-sun','Day',function(){ runCode('daycity'); }],
  ['p1-moon','Night',function(){ runCode('nightcity'); }],
  ['p1-pin','Where am I',function(){ runCode('whereami'); }],
  ['p1-hamburger','Menu',function(){ osOpen=false; osEl.classList.remove('open');; }],
  ['p1-plus','Create',function(){ say('create mode'); }],
  ['p1-minus','Delete',function(){ say('delete mode'); }],
  ['p1-cube','Shapes',function(){ say('shapes'); }],
  ['p1-palette','Render',function(){ say('render options'); }],
  ['p1-walker','Walk',function(){ moveMode='walk'; document.getElementById('joy').style.display='block'; say('walk'); }],
  ['p1-bird','Fly',function(){ moveMode='fly'; document.getElementById('joy').style.display='block'; say('fly'); }],
  ['p1-uparrow','Jump',function(){ say('jump!'); }],
  ['p1-hand','Grab',function(){ say('grab mode'); }],
  ['p1-speech','Chat',function(){ say('chat'); }],
  ['p1-gt','Codes',function(){ codeInput.focus(); }],
  ['p1-link','Go',function(){ say('go to...'); }],
  ['p1-house','Home',function(){ kingPos.set(0,0,0); say('home'); }],
  ['p1-music','Music',function(){ say('music'); }],
  ['p2-continuum','Continuum',function(){ say('continuum'); }],
  ['p2-place','Place',function(){ say('place mode'); }],
  ['p2-help','Help',function(){ say('help'); }],
  ['p2-export','Export',function(){ runCode('exportfbx'); }],
  ['p2-fixstation','Fix station',function(){ say('Playa 2.0 fix station'); }],
  ['p2-sky','Sky',function(){ say('sky options'); }],
  ['p2-treasure','Treasure',function(){ say('treasure hunt'); }],
  ['p2-clearcache','Clear cache',function(){ if(confirm('Clear?')) location.reload(); }],
  ['p2-waypoints','Waypoints',function(){ say('waypoints'); }],
  ['p2-kidmode','Kid mode',function(){ say('kid mode'); }],
  ['p2-crown','Crown',function(){ say('crown view'); }],
  ['p2-dimension','Dimension',function(){ say('dimension'); }],
  ['p3-soliditronium','Soliditronium',function(){ say('soliditronium'); }],
  ['p3-capsule','Capsule',function(){ say('capsule'); }],
  ['p3-fillgaps','Fill gaps',function(){ say('filling gaps'); }],
  ['p3-recolor','Recolor',function(){ say('recolor'); }],
  ['p3-saveview','Save view',function(){ say('view saved'); }],
  ['p3-gotoview','Go to view',function(){ say('going to view'); }],
  ['p3-presets','Presets',function(){ say('presets'); }],
  ['p3-aurora','Aurora',function(){ say('aurora'); }],
  ['p3-ember','Ember',function(){ say('ember'); }],
  ['p3-storm','Storm',function(){ say('storm'); }],
  ['p3-dawn','Dawn',function(){ say('dawn'); }],
  ['p3-invite','Invite',function(){ say('invite'); }],
  ['p4-whiteout','Whiteout',function(){ say('whiteout'); }],
  ['p4-rain','Rain',function(){ say('rain'); }],
  ['p4-wear','Wear',function(){ say('wear'); }],
  ['p4-walkline','Walkline',function(){ say('walkline'); }],
  ['p4-redseams','Red seams',function(){ say('red seams'); }],
  ['p4-glide','Glide',function(){ runCode('glide'); }],
  ['p4-taptocrown','Tap to crown',function(){ say('tap to crown'); }],
  ['p4-tutorial','Tutorial',function(){ say('tutorial'); }],
  ['p4-presence','Presence',function(){ say('presence'); }],
  ['p4-balance','Balance',function(){ say('balance'); }],
  ['p4-ship','Ship',function(){ say('ship'); }],
  ['p4-history','History',function(){ say('history'); }],
];
/* Organize by function with section headers */
var GROUPS = [
  ['CORE', 0, 20],
  ['BUILD', 20, 32],
  ['WORLD', 32, 44],
  ['SYSTEM', 44, 56],
];
GROUPS.forEach(function(g){
  var header = document.createElement('div');
  header.textContent = g[0];
  header.style.cssText = 'width:100%;text-align:center;color:#ffd700;font:16px Georgia,\'Times New Roman\',serif;letter-spacing:6px;