diff --git a/viz/board.html b/viz/board.html
index dd2eb394dd..339ec63ccd 100644
--- a/viz/board.html
+++ b/viz/board.html
@@ -69,7 +69,7 @@
padding-top:11px; line-height:1.6}
-
+
Republic OS · the board
Every county in America, and what it's made of.
@@ -90,10 +90,10 @@
-
+
- Coverage is the fog of war: a county is lit once its officeholders are mirrored. Today that is Florida — 67 counties. The other 3,000+ are demographic nodes waiting to be filled. Switch lenses to read what each place is made of.
+ Every one of 3,131 counties carries Census demographics — switch lenses to read income, population, or poverty across the whole country. Hover any county for its full profile; every value resolves to a sourced Jurisdiction file.
@@ -122,16 +122,13 @@ function pathFor(g){let d="";(g.type==="Polygon"?[g.coordinates]:g.coordinates).
// ---- lenses ----
const LENSES={
- coverage:{label:"Coverage", kind:"cov"},
- pop:{label:"Population", field:"pop", fmt:fmtN, lo:[22,48,60], hi:[96,236,244]},
income:{label:"Median income", field:"income", fmt:fmt$, lo:[28,54,42], hi:[150,246,142]},
+ pop:{label:"Population", field:"pop", fmt:fmtN, lo:[22,48,60], hi:[96,236,244]},
poverty:{label:"Poverty rate", field:"poverty", fmt:fmtP, lo:[48,40,36], hi:[252,150,96]},
};
-const ORDER=["coverage","pop","income","poverty"];
-const BASE=[26,34,46]; // --dark-terr-ish
-let cur="income", domains={}, maxOH=0;
+const ORDER=["income","pop","poverty"];
+let cur="income", domains={};
-Object.values(D).forEach(v=>{ if(v.oh>maxOH)maxOH=v.oh; });
const ranks={}; // sorted value arrays, for percentile (rank) coloring
for(const key of ORDER){ const L=LENSES[key]; if(!L.field)continue;
let lo=1e15,hi=-1e15; const vals=[];
@@ -144,13 +141,9 @@ function rankT(key,x){ const a=ranks[key]; let lo=0,hi=a.length;
return a.length>1 ? lo/(a.length-1) : 0.5; }
function mix(a,b,t){return `rgb(${a.map((x,i)=>Math.round(x+(b[i]-x)*t)).join(",")})`;}
function colorFor(fips){
- const v=D[fips]; const L=LENSES[cur];
- if(!v) return "#101720";
- if(L.kind==="cov"){
- if(!(v.oh>0)) return "#18212e";
- return mix([120,82,34],[250,201,105], 0.45+0.55*Math.sqrt(v.oh/maxOH));
- }
- const x=v[L.field]; if(x==null) return "#18212e";
+ const v=D[fips]; if(!v) return "#101720";
+ const L=LENSES[cur]; const x=v[L.field];
+ if(x==null) return "#18212e";
return mix(L.lo, L.hi, 0.14+0.86*rankT(cur,x)); // percentile spread, per-lens ramp
}
@@ -171,7 +164,7 @@ function show(fips){
const v=D[fips]; if(!v)return;
readout.innerHTML=`
${v.name}
- ${v.state} · ${v.oh>0?`${v.oh} officeholders mapped`:"not yet mapped"}
+ ${v.state}${v.oh>0?` · ${v.oh} officeholders`:""}
Population${fmtN(v.pop)}
Median household income${fmt$(v.income)}
@@ -188,24 +181,16 @@ map.addEventListener("mousemove",e=>{
// ---- legend ----
function renderLegend(){
- const L=LENSES[cur]; const el=document.getElementById("legend");
+ const L=LENSES[cur]; const[lo,hi]=domains[cur];
document.getElementById("legend-title").textContent=L.label;
- if(L.kind==="cov"){
- el.innerHTML=`
-
Not yet mapped — no officeholders
-
Lit — officeholders mirrored (few → many)
`;
- }else{
- const[lo,hi]=domains[cur];
- el.innerHTML=`
-
-
${L.fmt(lo)}${L.fmt(hi)}
-
no data
`;
- }
+ document.getElementById("legend").innerHTML=`
+
+
${L.fmt(lo)}${L.fmt(hi)}
+
no data
`;
}
// ---- lens buttons ----
const foot={
- coverage:"3,109 contiguous counties shown (AK, HI & territories omitted from the projection). Lit counties resolve to sourced officeholder files; the rest are demographic nodes on the frontier.",
pop:"Population by county, Census ACS 2023. Darkest are the least populous; brightest the metropolitan cores.",
income:"Median household income by county, ACS 2023. Every value resolves to a sourced Jurisdiction file.",
poverty:"Poverty rate by county, ACS 2023. Brighter is higher — the map of where need concentrates.",
@@ -224,11 +209,8 @@ function setLens(k){
}
// ---- totals ----
-const nLit=Object.values(D).filter(v=>v.oh>0).length;
-const nOH=Object.values(D).reduce((a,v)=>a+(v.oh||0),0);
document.getElementById("t-people").textContent="11,285";
document.getElementById("t-counties").textContent=Object.keys(D).length.toLocaleString();
-document.getElementById("t-lit").textContent=nLit;
render(); renderLegend(); document.getElementById("stagefoot").textContent=foot[cur];
requestAnimationFrame(()=>requestAnimationFrame(()=>document.getElementById("board").classList.remove("booting")));