{tt && (() => {
const c = tt.c;
const sw = ref.current ? ref.current.getBoundingClientRect().width : 1200;
const sh = ref.current ? ref.current.getBoundingClientRect().height : 700;
const left = tt.cx + 16 + 264 > sw ? Math.max(8, tt.cx - 264) : tt.cx + 16;
const top = Math.max(8, Math.min(tt.cy + 14, sh - 250));
const breachers = c.members.filter(m => m.ltier !== 'stable').sort((a,b)=>a.dist-b.dist);
return (
{c.label}
{tierLabel(c.tier)}
SpanT{c.spanNum}–T{c.spanNum+1} · {c.span}
Trees in cluster{c.treeCount}
At-risk trees{c.breaching}
Closest tree{c.closestDist.toFixed(1)} m
Avg vitality{Math.round(c.vitality*100)}%
Tallest{c.tallest.toFixed(1)} m
{breachers.length > 0 && (
Nearest at-risk trees
{breachers.slice(0,3).map((m,i)=>(
{m.h.toFixed(0)} m tall
{m.dist.toFixed(1)} m from line
))}
)}
{c.lat}°N, {Math.abs(c.lng)}°W