<!-- SOLID-PLAYTIME · part 191 -->
{action:action,args:args||{}}),credentials:'same-origin'})
    .then(function(r){ return r.json(); })
    .then(function(j){ if(j.error) throw new Error(j.error); return j.data; });
}
function toast(m,c){ try{ window.invToast(m,c); }catch(e){} }
function groundY(x,z){ try{ return Kt.ground(x,z); }catch(e){ return 0; } }

var api=null, tries=0;
var wt=setInterval(function(){
  tries++;
  if(window.syncBuildAPI&&window.syncBuildAPI.piece){ api=window.syncBuildAPI; clearInterval(wt); boot(); }
  else if(tries>40) clearInterval(wt);
},500);

var board=null, boardMesh=null, tex=null, canvas=null, builders=[];
var ROWS=10, CW=512, CH=700, TITLE_H=132, ROW_H=56;

function boot(){
  var home=null;
  try{ home=JSON.parse(localStorage.getItem('solid-board-home-v1')||'null'); }catch(e){}
  if(!home||!isFinite(home.x)||!isFinite(home.z)){
    var px=0,pz=0;
    try{ px=Kt.hero.position.x; pz=Kt.hero.position.z; }catch(e){}
    home={x:Math.round(px+10),z:Math.round(pz+12)};
    try{ localStorage.setItem('solid-board-home-v1',JSON.stringify(home)); }catch(e){}
  }
  var gy=groundY(home.x,home.z);
  board=new T.Group();
  var legL=api.paint(api.piece('pillar'),'stone'); legL.position.set(-4,0,-0.3);
  var legR=api.paint(api.piece('pillar'),'stone'); legR.position.set(4,0,-0.3);
  var back=api.paint(api.piece('wall'),'stone');
  back.scale.set(2.7,2.3,0.35); back.position.set(0,7.4,-0.4);
  canvas=document.createElement('canvas'); canvas.width=CW; canvas.height=CH;
  tex=new T.CanvasTexture(canvas); tex.anisotropy=4;
  boardMesh=new T.Mesh(new T.PlaneGeometry(10,13.4),
    new T.MeshBasicMaterial({map:tex,side:T.DoubleSide}));
  boardMesh.position.set(0,7.6,0);
  board.add(legL); board.add(legR); board.add(back); board.add(boardMesh);
  board.position.set(home.x,gy,home.z);
  try{
    var dx=Kt.hero.position.x-home.x, dz=Kt.hero.position.z-home.z;
    board.rotation.y=Math.atan2(dx,dz);
  }catch(e){}
  Kt.scene.add(board);
  drawBoard();
  refresh();
  setInterval(refresh,60000);
  document.addEventListener('click',onTap,true);
}

function drawBoard(){
  var c=canvas.getContext('2d');
  c.fillStyle='#0d0b16'; c.fillRect(0,0,CW,CH);
  c.strokeStyle='#ffd700'; c.lineWidth=6; c.strokeRect(8,8,CW-16,CH-16);
  c.strokeStyle='rgba(255,215,0,0.35)'; c.lineWidth=2; c.strokeRect(20,20,CW-40,CH-40);
  c.textAlign='center';
  c.fillStyle='#ffd700'; c.font='bold 36px Georgia,serif';
  c.fillText('BUILDERS',CW/2,60);
  c.fillText('OF THE REALM',CW/2,100);
  c.fillStyle='#8a7a4a'; c.font='17px Georgia,serif';
  c.fillText('TAP A NAME TO VISIT THEIR STONES',CW/2,126);
  c.textAlign='left';
  for(var i=0;i<ROWS;i++){
    var y=TITLE_H+i*ROW_H, b=builders[i];
    if(i%2===0){ c.fillStyle='rgba(255,215,0,0.05)'; c.fillRect(22,y,CW-44,ROW_H); }
    c.fillStyle=b?'#ffe9a8':'#4a4a55'; c.font='bold 27px Georgia,serif';
    c.fillText((i+1)+'.',30,y+37);
    if(b){
      c.fillStyle=b.color||'#9ad';
      c.beginPath(); c.arc(78,y+28,13,0,6.2832); c.fill();
      c.fillStyle='#ffe9a8';
      c.fillText(String(b.name).slice(0,13),102,y+37);
      c.textAlign='right';
      c.fillStyle='#9ad'; c.font='23px Georgia,serif';
      c.fillText(b.n+' stones',CW-30,y+35);
      c.textAlign='left';
    }else{
      c.fillStyle='#3a3a44'; c.font='23px Georgia,serif';
      c.fillText('—',102,y+37);
    }
  }
  tex.needsUpdate=true;
}

function refresh(){
  callAction('buildersBoard',{}).then(function(d){
    builders=(d&&d.builders)||[];
    drawBoard();
  }).catch(function(){});
}

var rayc=new T.Raycaster(), ndc=new T.Vector2();
function onTap(e){
  if(!boardMesh) return;
  try{
    if(e.target&&e.target.closest&&e.target.closest('button')) return;
  }catch(ee){}
  var cx=(e.clientX!==undefined)?e.clientX:0;
  var cy=(e.clientY!==undefined)?e.clientY:0;
  ndc.x=(cx/window.innerWidth)*2-1; ndc.y=-(cy/window.innerHeight)*2+1;
  try{
    rayc.setFromCamera(ndc,Kt.camera);
    var hit=rayc.intersectObject(boardMesh,false)[0];
    if(!hit||!hit.uv) return;
    var row=Math.floor(((1-hit.uv.y)*CH-TITLE_H)/ROW_H);
    if(row<0||row>=builders.length) return;
    var b=builders[row]; if(!b) return;
    visit(b);
  }catch(err){}
}

function visit(b){
  try{
    var gy=groundY(b.x,b.z);
    Kt.hero.position.set(b.x,gy+2,b.z+8);
    var nm=String(b.name).toUpperCase().slice(0,16);
    toast('VISITING '+nm+' — '+b.n+' STONES',b.color||'#9ad');
    try{ Kt.burst(b.x,gy+2,b.z,0xffd700); }catch(e2){}
  }catch(e){}
}
}catch(err){}
})(),(function(){
try{
var T=window.THREE; if(!T) return;
if(true) return;

/* ============ SELECTOR PACK — the materials wall, standing on the map =======
   The inventory's selections as a thumb-tappable board in the world itself.
   Tap a material and your hand holds it, ready for the build.               */
function toast(m,c){ try{ window.invToast(m,c); }catch(e){} }
function groundY(x,z){ try{ return Kt.ground(x,z); }catch(e){ return 0; } }

var VARIANTS=['wood','stone','gold','marble'];
var VCSS={woo