<!-- CODERS100 · part 25 -->
{ 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;margin:10px 0 6px 0;border-bottom:1px solid #d8a920;padding-bottom:6px;';
  osEl.appendChild(header);
  for(var i=g[1]; i<g[2]; i++){
    (function(b){
      var cell = document.createElement('div');
      cell.style.cssText = 'display:flex;flex-direction:column;align-items:center;gap:2px;width:72px;flex-shrink:0;';
      var btn = document.createElement('button');
  btn.title = b[1];
  btn.innerHTML = '<img src="/coders100/buttons/'+b[0]+'.webp" style="width:100%;height:100%;border-radius:50%;object-fit:cover;" draggable="false">';
  btn.style.cssText = 'width:48px;height:48px;min-width:48px;min-height:48px;border-radius:50%;padding:0;margin:0;border:2px solid #d8a920;background:#141006;cursor:pointer;flex-shrink:0;overflow:hidden;';
      btn.onclick = (function(fn){ return function(){ fn(); }; })(b[2]);
      cell.appendChild(btn);
      var lbl = document.createElement('div');
      lbl.textContent = b[1];
      lbl.style.cssText = 'color:#d8a920;font-size:13px;font-family:Georgia,\'Times New Roman\',serif;text-align:center;line-height:1.2;max-width:72px;letter-spacing:0.5px;';
      cell.appendChild(lbl);
      osEl.appendChild(cell);
    })(BTNS[i]);
  }
});
/* REAL TOGGLES — switches with on/off state */











/* ===== DUAL JOYSTICKS — left: body, right: camera ===== */
function makeJoystick(pos, onMove){
  var base = document.createElement('div');
  base.style.cssText = 'position:fixed;'+pos+';width:100px;height:100px;border-radius:50%;border:2px solid #8a6a1c;background:rgba(20,14,6,0.4);z-index:998;touch-action:none;';
  var knob = document.createElement('div');
  knob.style.cssText = 'position:absolute;left:50%;top:50%;width:44px;height:44px;margin:-22px 0 0 -22px;border-radius:50%;background:radial-gradient(circle at 30% 30%, #ffd700, #8a6a1c);box-shadow:0 0 8px rgba(255,215,0,0.5);';
  base.appendChild(knob);
  document.body.appendChild(base);
  var touchId = null, cx = 0, cy = 0;
  function setKnob(dx, dy){
    var max = 28;
    var len = Math.sqrt(dx*dx + dy*dy);
    if(len > max){ dx = dx/len*max; dy = dy/len*max; }
    knob.style.transform = 'translate('+dx+'px,'+dy+'px)';
    onMove(dx/max, dy/max);
  }
  base.addEventListener('touchstart', function(e){
    e.stopPropagation(); e.preventDefault();
    var t = e.changedTouches[0];
    touchId = t.identifier;
    var r = base.getBoundingClientRect();
    cx = r.left + r.width/2; cy = r.top + r.height/2;
  }, {passive:false});
  base.addEventListener('touchmove', function(e){
    e.stopPropagation(); e.preventDefault();
    for(var i=0; i<e.changedTouches.length; i++){
      var t = e.changedTouches[i];
      if(t.identifier === touchId){
        setKnob(t.clientX - cx, t.clientY - cy);
      }
    }
  }, {passive:false});
  base.addEventListener('touchend', function(e){
    e.stopPropagation();
    for(var i=0; i<e.changedTouches.length; i++){
      if(e.changedTouches[i].identifier === touchId){
        touchId = null;
        knob.style.transform = 'translate(0,0)';
        onMove(0, 0);
      }
    }
  }, {passive:true});
  return base;
}

/* LEFT joystick — moves the body */
var lastDX = 0, lastDZ = 0, walkPhase = 0;
makeJoystick('left:8%;bottom:100px;', function(dx, dy){
  var sp = 0.5;
  if(moveMode === 'fly'){
    /* FLIGHT: 3D movement — dx left/right, dy up/down */
    var fwdX = -Math.cos(camYaw), fwdZ = -Math.sin(camYaw);
    var rightX = Math.sin(camYaw), rightZ = -Math.cos(camYaw);
    var mx = rightX * dx * sp;
    var mz = rightZ * dx * sp;
    var my = -dy * sp; /* Push up = fly up, push down = descend */
    lastDX = mx;
    lastDZ = mz;
    kingPos.x += mx;
    kingPos.z += mz;
    kingPos.y = Math.max(0.5, kingPos.y + my);
    /* Tilt body when flying */
    if(typeof playerBody !== 'undefined' && playerBody){
      playerBody.rotation.x = -dy * 0.3;
    }
  } else if(moveMode === 'swim'){
    /* SWIM: water movement — fluid, buoyant, dive/surface */
    var spSwim = 0.3; /* Slower in water */
    var fwdX = -Math.cos(camYaw), fwdZ = -Math.sin(camYaw);
    var rightX = Math.sin(camYaw), rightZ = -Math.cos(camYaw);
  