<!-- RUBY-BACKUP · part 382 -->
0.08);
  footers1.name = 'footers1';
  /* handers1 - nodes in the hands for hand plans */
  var handers1L = M(new T.OctahedronGeometry(0.035), new T.MeshStandardMaterial({color:0xff6600, metalness:0.9, roughness:0.2, emissive:0x442200, emissiveIntensity:0.5}), -0.30, 0.40, 0.05);
  handers1L.name = 'handers1';
  var handers1R = M(new T.OctahedronGeometry(0.035), new T.MeshStandardMaterial({color:0xff6600, metalness:0.9, roughness:0.2, emissive:0x442200, emissiveIntensity:0.5}), 0.30, 0.40, 0.05);
  handers1R.name = 'handers1';
  M(A_GEO.kBelt, stoneMat, 0, 0.36, 0);
  var aL = M(A_GEO.kArm, stoneMat, -0.26, 0.46, 0); aL.rotation.z = 0.25;
  var aR = M(A_GEO.kArm, stoneMat, 0.26, 0.46, 0);  aR.rotation.z = -0.25;
  M(A_GEO.kPack, stoneMat, 0, 0.52, -0.22);
  M(A_GEO.kHead, stoneMat, 0, 0.82, 0);
  M(A_GEO.kEye, eyeGlowMat, -0.09, 0.84, 0.23); M(A_GEO.kEye, eyeGlowMat, 0.09, 0.84, 0.23);
  /* a more intricate face — pupils, glints, brows, nose, ears */
  var pupilMat = new T.MeshBasicMaterial({color:0x1a0f00});
  var glintMat = new T.MeshBasicMaterial({color:0xfff2cc});
  var browMat  = new T.MeshBasicMaterial({color:0x8a6a1a});
  [-0.09, 0.09].forEach(function(ex){
    M(new T.SphereGeometry(0.014, 8, 6), pupilMat, ex, 0.845, 0.258);
    M(new T.SphereGeometry(0.008, 6, 5), glintMat, ex-0.012, 0.852, 0.262);
    var br = M(new T.BoxGeometry(0.07, 0.014, 0.014), browMat, ex, 0.905, 0.225);
    br.rotation.z = ex<0 ? 0.18 : -0.18;
  });
  M(new T.SphereGeometry(0.02, 8, 6), stoneMat, 0, 0.80, 0.238);
  M(new T.SphereGeometry(0.035, 8, 6), stoneMat, -0.235, 0.82, 0);
  M(new T.SphereGeometry(0.035, 8, 6), stoneMat, 0.235, 0.82, 0);
  var sm = M(A_GEO.kSmile, smileMat, 0, 0.755, 0.225); sm.rotation.z = Math.PI;
  M(A_GEO.kCrown, stoneMat, 0, 1.02, 0);
  var i, a, sx, sz;
  for(i=0;i<8;i++){  /* fleur-de-lis points all around */
    a = i*Math.PI/4;
    sx = Math.sin(a)*0.19; sz = Math.cos(a)*0.19;
    M(A_GEO.kSpike, stoneMat, sx, 1.13, sz);
    M(A_GEO.kBall, stoneMat, sx, 1.215, sz);
  }
  var jewels = [[0, jewelRedMat], [-0.35, jewelBlueMat], [0.35, jewelBlueMat], [-0.7, jewelGreenMat], [0.7, jewelGreenMat], [-1.05, pearlMat], [1.05, pearlMat]];
  for(i=0;i<jewels.length;i++){
    a = jewels[i][0];
    M(A_GEO.kJewel, jewels[i][1], Math.sin(a)*0.205, 1.02, Math.cos(a)*0.205);
  }
  return g;
}
function buildSword(){
  var g = new T.Group(), parts = ['blade','tip','guard','grip','pommel'];
  for(var i=0;i<parts.length;i++) g.add(new T.Mesh(A_GEO[parts[i]], stoneMat));
  g.add(new T.Mesh(A_GEO.tipglow, avatarGlowMat));
  g.visible = false; scene.add(g);
  return g;
}
function buildWearable(name){
  /* we build our avatars: a saved build, worn small, following its maker */
  if(typeof SAVES==='undefined' || !SAVES || !SAVES[name]) return null;
  var sts = SAVES[name].stones || [];
  if(!sts.length) return null;
  var inner = new T.Group(), cx=0, cz=0, i;
  for(i=0;i<sts.length;i++){ cx+=sts[i].x; cz+=sts[i].z; }
  cx/=sts.length; cz/=sts.length;
  for(i=0;i<sts.length;i++){
    var st = sts[i], base = shapeBase(st.s), ghostly = st.v===1;
    var m = new T.Mesh(baseGeo(base), (ghostly || LINEWORK_ON) ? intaglioMat : (FAMILY[base] ? familyMat : stoneMat));
    var fs = (st.r||1) * legalK1(base);
    m.scale.set(fs,fs,fs);
    m.position.set(st.x-cx, ((st.y||0)+fs*0.5)*window.MINIMUM, st.z-cz);
    inner.add(m);
  }
  var bb = new T.Box3().setFromObject(inner);
  var sz = bb.getSize(new T.Vector3());
  var sc = 0.45 / Math.max(sz.x, sz.y, sz.z, 0.001);
  inner.position.sub(bb.getCenter(new T.Vector3()));
  var outer = new T.Group();
  outer.add(inner); outer.scale.set(sc,sc,sc);
  return outer;
}
function freeSpawn(cx, cz){
  /* never wake up inside a stone — step to the nearest free cell */
  if(!stoneAt(cx, cz, 0)) return {x:cx, z:cz};
  for(var r=2; r<=10; r+=2){
    for(var a=0; a<8; a++){
      var x = cx + Math.round(Math.cos(a*Math.PI/4)*r/2)*2;
      var z = cz + Math.round(Math.sin(a*Math.PI/4)*r/2)*2;
      if(!stoneAt(x, z, 0)) return {x:x, z:z};
    }
  }
  return {x:cx, z:cz};
}
function setWalk(on){
  WALK = !!on;
  var ju=document.getElementById('joy'), jb=document.getElementById('jumpbtn'),
      fb=document.getElementById('flybtn'), wb=document.getElementById('walk-btn');
  if(ju) ju.style.display = WALK?'block':'none';
  if(jb) jb.style.display = WALK?'block':'none';
  if(fb) fb.style.display = WALK?'block':'none';
  if(wb) wb.classList.toggle('on', WALK);
  if(WALK){
    var lt = (typeof landMesh!=='undefined' && landMesh) ? landTop() : {x:0, z:0};
    var cx = (typeof cursor!=='undefined' && cursor && (cursor.x||cursor.z)) ? cursor.x : lt.x;
    var cz = (typeof cursor!=='undefined' && cursor && (cursor.x||cursor.z)) ? cursor.z : lt.z;
    var sp = freeSpawn(cx, cz);
    if(typeof landMesh!=='undefined' && !landMesh && typeof buildLandMesh==='function'){ try{ buildLandMesh(); }catch(e){} }
    var sgy = groundY(sp.x, sp.z);
    /* walk keeps you where you stand 