<!-- SOLID-PLAYTIME · part 190 -->
function(){
  if(structures.length>=MAX_STRUCTURES) return;
  if(!document.querySelector('button.attack')) return;
  var heroOk=false;
  try{ heroOk=!!(Kt.hero&&Kt.hero.position&&isFinite(Kt.hero.position.x)); }catch(e){}
  if(!heroOk) return;
  var types=['house','house','tower','wall','gate','house','tower'];
  var s=null; try{ s=findSite(); }catch(e){}
  if(!s) return;
  raise(types[Math.floor(Math.random()*types.length)],s.x,s.z,Math.floor(Math.random()*4)*Math.PI/2,true);
},240000);

}catch(e){ if(window.console&&console.warn) console.warn('kingdom-pack:',e); }
})(),(function(){
try{
var T=window.THREE; if(!T) return;
if(window.syncPackLoaded) return; window.syncPackLoaded=true;

/* ============ SYNC PACK — the shared world: friends build together ============
   Every manual placement is sent to the box; every 12s we pull stones other
   travelers raised and set them in the scene with the builder's name above.
   The autonomous kingdom stays local ambience — only hands sync.          */
var API='/solid/playtime/actions';
function callAction(action,args){
  return fetch(API,{method:'POST',headers:{'Content-Type':'application/json'},
    body:JSON.stringify({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){} }

/* my name in the shared world */
callAction('claimColor',{}).catch(function(){});

/* ---- my placements -> the box ---- */
var syncMap={};
try{ syncMap=JSON.parse(localStorage.getItem('solid-sync-ids-v1')||'{}'); }catch(e){ syncMap={}; }
function fp(s){ return s.x+','+s.y+','+s.z+','+s.shape+','+s.variant; }
window.syncPlaceBlock=function(spec){
  var body={shape:spec.shape,mat:spec.variant,x:spec.x,y:spec.y,z:spec.z,rot:spec.rot||0};
  callAction('placeBlock',body).then(function(d){
    try{ syncMap[fp(spec)]=d.id; localStorage.setItem('solid-sync-ids-v1',JSON.stringify(syncMap)); }catch(e){}
  }).catch(function(){ /* the world keeps turning; the local stone stands */ });
};

/* ---- other travelers' stones -> my scene ---- */
var remote={};
var lastId=0;
try{ lastId=parseInt(localStorage.getItem('solid-sync-last-v1')||'0',10)||0; }catch(e){}
var welcomed=false;
function nameTag(name,color){
  var cv=document.createElement('canvas'); cv.width=256; cv.height=64;
  var c=cv.getContext('2d');
  c.font='bold 30px Georgia,serif'; c.textAlign='center'; c.textBaseline='middle';
  c.shadowColor='rgba(0,0,0,0.9)'; c.shadowBlur=8;
  c.fillStyle=color||'#ffe9a8';
  c.fillText(String(name==null?'traveler':name).slice(0,18),128,34);
  var tx=new T.CanvasTexture(cv); tx.anisotropy=4;
  var sp=new T.Sprite(new T.SpriteMaterial({map:tx,transparent:true,depthWrite:false}));
  sp.scale.set(7,1.75,1);
  return sp;
}
function addRemote(b){
  if(remote[b.id]) return;
  var api=window.syncBuildAPI; if(!api||!api.piece||!api.paint) return;
  try{
    var g=api.paint(api.piece(b.shape),b.mat);
    g.position.set(b.x,b.y,b.z); g.rotation.y=b.rot||0;
    var bb=new T.Box3().setFromObject(g);
    var h=bb.max.y-bb.min.y; if(!isFinite(h)||h<=0) h=2;
    var tag=nameTag(b.name,b.color);
    tag.position.set(b.x,b.y+h+1.8,b.z);
    Kt.scene.add(g); Kt.scene.add(tag);
    remote[b.id]=1;
  }catch(e){}
}
function poll(){
  callAction('listBlocks',{after:lastId}).then(function(d){
    var bs=(d&&d.blocks)||[], n=0;
    for(var i=0;i<bs.length;i++){
      var b=bs[i];
      if(b.id>lastId) lastId=b.id;
      if(b.mine) continue;
      if(!remote[b.id]){ addRemote(b); n++; }
    }
    try{ localStorage.setItem('solid-sync-last-v1',String(lastId)); }catch(e){}
    if(n>0&&!welcomed){ welcomed=true; toast('THE WORLD GREW — FRIENDS ARE BUILDING','#9ad'); }
  }).catch(function(){});
}
setTimeout(poll,4000);
setInterval(poll,12000);
}catch(err){}
})(),(function(){
try{
/* ============ BUILDER GATE — arrive through the portal, land building ============
   When the game boots with ?build=1 in the URL (the portal's doing), step
   straight into build mode once the build pack is awake.                        */
if(!/([?&])build=1(&|$)/.test(location.search)) return;
var tries=0;
var t=setInterval(function(){
  tries++;
  try{
    if(window.syncBuildAPI&&window.syncBuildAPI.setBuild){
      window.syncBuildAPI.setBuild(true);
      clearInterval(t);
      return;
    }
  }catch(e){}
  if(tries>30) clearInterval(t);
},500);
}catch(err){}
})(),(function(){
try{
var T=window.THREE; if(!T) return;
if(true) return;

/* ============ BOARD PACK — the builders' leaderboard, standing on the map ====
   A stone board near where you arrive. Every row is thumb-tappable: tap a
   builder's name and the world carries you to their latest stones.          */
var API='/solid/playtime/actions';
function callAction(action,args){
  return fetch(API,{method:'POST',headers:{'Content-Type':'application/json'},
    body:JSON.stringify(