// Mission 001 — staged network graph. Layer rings, not degree rings: this system claims no view of anyone's network.
const NetGraph = ({ stage, density = "standard", mini = false }) => {
const { NODES, EDGES, AMBIENT } = MD;
const N = Object.fromEntries(NODES.map(n => [n.id, n]));
const complete = MD.STAGES[stage].complete;
const visN = NODES.filter(n => stage >= n.s && (n.until == null || stage < n.until));
const visE = EDGES.filter(([a, b, s, o]) => stage >= s && (o.until == null || stage < o.until)
&& visN.some(n => n.id === a) && visN.some(n => n.id === b));
const isHot = (o) => o.hot && stage >= o.hot[0] && stage < o.hot[1];
const isDown = (o) => o.downAt != null && stage >= o.downAt;
const tierMax = density === "sparse" ? 0 : density === "dense" ? 2 : 1;
const nodeState = (n) => {
if (n.deadAt != null && stage >= n.deadAt) return "dead";
if (n.clearedAt != null && stage >= n.clearedAt) return "cleared";
return "norm";
};
const shape = (n) => {
const st = nodeState(n);
if (n.type === "dest") {
const lead = MD.STAGES[stage].dest === n.dest;
const won = complete && lead;
const dim = (complete && !lead) || st === "dead";
return (
{won && }
{lead && !won && }
);
}
if (n.type === "you") return (
);
if (n.type === "frontier") return ;
if (n.type === "org") return ;
if (n.type === "event") return ;
if (st === "dead") return (
);
if (st === "cleared") return (
);
return ;
};
return (
);
};
const GraphLegend = ({ stage }) => (
person
event
org
candidate destination
queued probe
{stage >= 4 && cleared}
{stage >= 6 && dead end}
rings: mapped → contacted → committed · earned edges only, no inferred network
);
Object.assign(window, { NetGraph, GraphLegend });