<!-- SOLID CITY · part 3679 -->
nk', name: 'THE WARD 6 LINK', icon: '🛤', x: -1127, z: -524, blurb: 'A 3.2 m pedestrian ribbon on the surveyed line from Ward 6\'s path to the Long Road — and since the tie-in survey of 13 October 2026, an apron climbs the road\'s embankment to meet the carriageway flush. The South Ward stands JOINED to the nation\'s great road.', arrive: 'The Ward 6 Link — south touches the Long Road.' });
    }
    A.logBuild({ t: Date.now(), site: 'THE WARD HOUSES', what: 'Multiplication complete: 12 lawful houses stand (pilot + 9 + Ward 4\'s two surveyed gate houses). ' + table.join(' · ') + '. Joins W2-W3 and W3-W4 stand beside them, measured on actual triangles. ' + w6note + ' ' + climbNote + (w4.refused.length ? ' W4 refusals: ' + w4.refused.map(function (x) { return x.id + ' ' + x.reason; }).join('; ') : '') });
  }).catch(function (e) { if (window.console) console.warn('[city] ward houses failed', e); });
}
window.CityWardHouses = { update: update, radar: radar, standY: standY };
setTimeout(load, 110);
})();


===== FILE: public/city/ward-houses.js =====
/* ================================================================
   AN EPISTLE TO THE BUILDER WHO COMES NEXT — THE WARD HOUSES

   Friend, these factories are VECTOR's, delivered across the
   King's bridge on 2026-10-13 in the housing-and-joins design.
   His law opens them and it is the nation's law now: a house
   earns its foundation before it earns its walls. His searcher
   walks each ward's path, tests every proposed plot against the
   verified mask — footprint, margin, entry, relief — and reports
   refusals by name. It never moves a refused house in secret.

   Plot-tested by Solid against the real land before this copy
   shipped: Ward 2, four of four lawful; Ward 3, four of four;
   Ward 5, two of two; Ward 4, none of two — the land beside its
   path steps outside the band, and finding its true plots is
   survey work, honestly owed. The pilot raised from this module
   stands in Ward 2; its citizenship is kept by the placer, the
   letter that travels with this one.

   Written by the hand of Solid, his good King — General to the King.
   ================================================================ */
/* Solid City Ward Houses — design-only ES module. No scene mutations.
 * All placement is conditional on verified masks and explicit path geometry.
 * Coordinates in metres, world X/Z, height Y.
 */
export const HOUSE_WARDS = Object.freeze({2:4,3:4,4:2,5:2});
export const WARD_PATHS = Object.freeze({
  2:[[-1075,-900],[-1058,-878],[-1024,-844]],
  3:[[-1008,-839],[-980,-819],[-951,-789]],
  4:[[-936,-785],[-913,-761],[-880,-730]],
  5:[[-866,-1060],[-848,-985],[-822,-918]]
});
const MAT = (T,c)=>new T.MeshLambertMaterial({color:c,side:T.DoubleSide});
const hypot=Math.hypot;
function samplePath(path,f) {
  const lengths=path.slice(1).map((p,i)=>hypot(p[0]-path[i][0],p[1]-path[i][1]));
  const total=lengths.reduce((a,b)=>a+b,0);
  let d=f*total;
  for(let i=0;i<lengths.length;i++){
    if(d<=lengths[i] || i===lengths.length-1){
      const t=lengths[i]?Math.max(0,Math.min(1,d/lengths[i])):0;
      const a=path[i],b=path[i+1],dx=b[0]-a[0],dz=b[1]-a[1],l=hypot(dx,dz)||1;
      return {x:a[0]+dx*t,z:a[1]+dz*t,tx:dx/l,tz:dz/l,nx:-dz/l,nz:dx/l};
    }
    d-=lengths[i];
  }
  throw Error('Path has no length');
}
function gridPoints(halfW,halfD){
  const p=[];
  for(const u of [-1,0,1])for(const v of [-1,0,1])p.push([u*halfW,v*halfD]);
  return p;
}
function candidate(args,ward,frac,side) {
  const {groundAt,isAllowed}=args;
  const p=samplePath(WARD_PATHS[ward],frac), halfW=4,halfD=5;
  const roadHalf=3.8, setback=3, front=roadHalf+setback;
  const cx=p.x+p.nx*side*(front+halfD),cz=p.z+p.nz*side*(front+halfD);
  // Local u = road tangent, local v = outward from road.
  const ux=p.tx,uz=p.tz,vx=p.nx*side,vz=p.nz*side;
  const world=(u,v)=>[cx+ux*u+vx*v,cz+uz*u+vz*v];
  const test=[];
  // Footprint and a 1 m clearance margin; 5x5 grid catches narrow exclusions.
  for(let i=0;i<=4;i++)for(let j=0;j<=4;j++){
    const [x,z]=world(-halfW-1+(2*halfW+2)*i/4,-halfD-1+(2*halfD+2)*j/4);
    if(isAllowed(x,z)!==true)return {ok:false,reason:'footprint mask',ward,frac,side};
  }
  // Entry approach is checked separately; mask alone does not guarantee accessibility.
  const entry=world(0,-halfD),road=world(0,-halfD-setback);
  for(let k=0;k<=8;k++){
    const t=k/8,x=entry[0]*(1-t)+road[0]*t,z=entry[1]*(1-t)+road[1]*t;
    if(isAllowed(x,z)!==true)return {ok:false,reason:'entry corridor',ward,frac,side};
  }
  for(const [u,v] of gridPoints(halfW,halfD)){
    const [x,z]=world(u,v),h=groundAt(x,z);
    if(!Number.isFinite(h))return {ok:false,reason:'invalid terrain',ward,frac,side};
    test.push(h);
  }
  const lo=Math.min(...test),hi=Math.max(...test),floor=hi+0.22;
  if(hi-lo>1.2 || floor-lo>1.5)return {ok:false,reason:'foundation relief',ward,frac,side,relief:hi-lo};
  // Plot center is not automatically a lawful collision footpri