(function(){
"use strict";
function sfpfMountIdentityGraph(){(function () {
"use strict";
var REDUCE = window.matchMedia && window.matchMedia("(prefers-reduced-motion: reduce)").matches;
var TAU = 6.283185307179586;
function hash(n) { n = (n * 2654435761) % 2147483647; return (n ^ (n >>> 15)) / 2147483647; }
function pal(light) {
return light
? { a: function (o) { return "rgba(168,22,22," + o + ")"; },
n: function (o) { return "rgba(10,10,10," + o + ")"; } }
: { a: function (o) { return "rgba(209,28,28," + o + ")"; },
n: function (o) { return "rgba(255,255,255," + o + ")"; } };
}
var DRAW = {};
DRAW["identity-graph"] = function (g, w, h, t, P, sp, sc, calm) {
var S = g.__ig, i, j;
if (!S) {
var N = 18, n = [], e = [];
for (i = 0; i < N; i++) {
var a0 = hash(i * 7 + 3) * TAU, d0 = 0.30 + hash(i * 13 + 11) * 0.70;
n.push({ x: Math.cos(a0) * d0, y: Math.sin(a0) * d0, vx: 0, vy: 0, fx: 0, fy: 0, deg: 0, ix: i });
}
for (i = 1; i < N; i++) { e.push([Math.floor(hash(i * 29 + 5) * i) % i, i]); }
for (i = 0; i < 5; i++) {
var a1 = Math.floor(hash(i * 97 + 41) * N) % N, b1 = Math.floor(hash(i * 131 + 17) * N) % N;
if (a1 !== b1) { e.push([a1, b1]); }
}
for (i = 0; i < e.length; i++) { n[e[i][0]].deg++; n[e[i][1]].deg++; }
S = g.__ig = { n: n, e: e, cyc: -1, hot: -1, hotT: -9999, warm: 1 };
}
var n2 = S.n, e2 = S.e, m = n2.length;
function relax() {
var a, b, dx, dy, d2, d, f, ux, uy, en = 0;
for (a = 0; a < m; a++) { n2[a].fx = 0; n2[a].fy = 0; }
for (a = 0; a < m; a++) {
for (b = a + 1; b < m; b++) {
dx = n2[b].x - n2[a].x; dy = n2[b].y - n2[a].y;
d2 = dx * dx + dy * dy + 0.004; d = Math.sqrt(d2);
f = 0.016 / d2; ux = dx / d; uy = dy / d;
n2[a].fx -= ux * f; n2[a].fy -= uy * f; n2[b].fx += ux * f; n2[b].fy += uy * f;
}
}
for (a = 0; a < e2.length; a++) {
var A = n2[e2[a][0]], B = n2[e2[a][1]];
dx = B.x - A.x; dy = B.y - A.y; d = Math.sqrt(dx * dx + dy * dy) + 0.0001;
f = (d - 0.44) * 0.055; ux = dx / d; uy = dy / d;
A.fx += ux * f; A.fy += uy * f; B.fx -= ux * f; B.fy -= uy * f;
}
for (a = 0; a < m; a++) {
n2[a].fx -= n2[a].x * 0.012; n2[a].fy -= n2[a].y * 0.012;
n2[a].vx = (n2[a].vx + n2[a].fx) * 0.85; n2[a].vy = (n2[a].vy + n2[a].fy) * 0.85;
n2[a].x += n2[a].vx; n2[a].y += n2[a].vy;
en += n2[a].vx * n2[a].vx + n2[a].vy * n2[a].vy;
}
return en;
}
if (S.warm) { for (i = 0; i < 420; i++) { relax(); } S.warm = 0; }
/* the layout advances by integration steps, not by t: scaling t alone would
only hurry the re-seed cycle and leave the nodes drifting at the same rate */
var steps = Math.max(1, Math.round(2 * (sp || 1))), energy = 0;
for (i = 0; i < steps; i++) { energy = relax(); }var pad = Math.min(w, h) * 0.13 + 6, x0 = 1e9, x1 = -1e9, y0 = 1e9, y1 = -1e9;
for (i = 0; i < m; i++) {
if (n2[i].x x1) { x1 = n2[i].x; }
if (n2[i].y y1) { y1 = n2[i].y; }
}
var bw = Math.max(0.4, x1 - x0), bh = Math.max(0.4, y1 - y0);
var fx = (w - 2 * pad) / bw, fy = (h - 2 * pad) / bh;
var sx = Math.min(fx, fy * 1.9), sy = Math.min(fy, fx * 1.9);
var cx = w * 0.5 - (x0 + x1) * 0.5 * sx, cy = h * 0.5 - (y0 + y1) * 0.5 * sy;
/* the viewport eases instead of snapping, or the re-seed makes the whole
drawing jump one frame after the throw */
if (S.vw !== w || S.vh !== h) { S.vw = w; S.vh = h; S.sx = sx; S.sy = sy; S.cx = cx; S.cy = cy; }
else { S.sx += (sx - S.sx) * 0.07; S.sy += (sy - S.sy) * 0.07;
S.cx += (cx - S.cx) * 0.07; S.cy += (cy - S.cy) * 0.07; }
sx = S.sx; sy = S.sy; cx = S.cx; cy = S.cy;
/* a ground wants to sit smaller in its box than an instrument does; the
cluster shrinks about its own centre so the fit logic above is untouched */
if (sc && sc !== 1) {
cx += (w * 0.5 - cx) * (1 - sc); cy += (h * 0.5 - cy) * (1 - sc);
sx *= sc; sy *= sc;
}/* the re-seed throws one entity clear across the frame — legible as an event
in a captioned instrument, but as a page ground it is just a jump. */
var cyc = calm ? 0 : Math.floor(t / 300);
if (!calm && cyc !== S.cyc) {
if (S.cyc >= 0 || cyc > 0) {
var ext = Math.max(Math.abs(x0), Math.abs(x1), Math.abs(y0), Math.abs(y1)) * 1.12;
var kk = Math.floor(hash(cyc * 57 + 13) * m) % m, ka = hash(cyc * 91 + 7) * TAU;
n2[kk].x = Math.cos(ka) * ext; n2[kk].y = Math.sin(ka) * ext; n2[kk].vx = 0; n2[kk].vy = 0;
S.hot = kk; S.hotT = t;
}
S.cyc = cyc;
}
var u = Math.max(0.62, Math.min(w, h) / 400), gx = pad * 0.5, gy = pad * 0.5;
function px(o) { var driftX = Math.sin(t * 0.012 + o.ix * 1.731) * 0.018; return Math.max(gx, Math.min(w - gx, cx + (o.x + driftX) * sx)); }
function py(o) { var driftY = Math.cos(t * 0.010 + o.ix * 1.193) * 0.014; return Math.max(gy, Math.min(h - gy, cy + (o.y + driftY) * sy)); }g.lineWidth = 1;
g.strokeStyle = P.a(0.30); g.beginPath();
for (i = 0; i = 0 ? Math.max(0, 1 - (t - S.hotT) / 90) : 0;
if (hotA > 0.02) {
g.strokeStyle = P.n((0.50 * hotA).toFixed(3)); g.beginPath();
for (i = 0; i < e2.length; i++) {
if (e2[i][0] === S.hot || e2[i][1] === S.hot) {
g.moveTo(px(n2[e2[i][0]]), py(n2[e2[i][0]])); g.lineTo(px(n2[e2[i][1]]), py(n2[e2[i][1]]));
}
}
g.stroke();
}
for (i = 0; i = 4) {
g.beginPath(); g.arc(px(o), py(o), rr + 3.4 * u, 0, TAU);
g.strokeStyle = P.a(0.26); g.stroke();
}
}
if (hotA > 0.02) {
var ho = n2[S.hot];
g.beginPath(); g.arc(px(ho), py(ho), (3 + 14 * (1 - hotA)) * u, 0, TAU);
g.strokeStyle = P.n((0.55 * hotA).toFixed(3)); g.stroke();
g.beginPath(); g.arc(px(ho), py(ho), 2.2 * u, 0, TAU);
g.fillStyle = P.n((0.85 * hotA).toFixed(3)); g.fill();
}
var span = Math.min(w, h) * 0.28, bar = Math.min(1, Math.sqrt(energy) * 11) * span, by = h - pad * 0.55;
g.strokeStyle = P.n(0.16); g.beginPath(); g.moveTo(pad, by); g.lineTo(pad + span, by); g.stroke();
g.strokeStyle = P.a(0.75); g.beginPath(); g.moveTo(pad, by); g.lineTo(pad + Math.max(1, bar), by); g.stroke();
};/* ---- runner -----------------------------------------------------------
Device-pixel correct, one frame for reduced motion, and only the plates
actually on screen are stepped. One plate throwing must not take the
page down, so every paint is guarded. */
function fit(cv) {
var dpr = Math.min(window.devicePixelRatio || 1, 2);
var w = cv.clientWidth, h = cv.clientHeight;
cv.width = Math.max(1, Math.round(w * dpr));
cv.height = Math.max(1, Math.round(h * dpr));
var g = cv.getContext("2d");
g.setTransform(dpr, 0, 0, dpr, 0, 0);
return { g: g, w: w, h: h };
}var plates = [];
var list = document.querySelectorAll("canvas[data-sfpf-identity-graph]");
for (var i = 0; i = p.jumpAt && p.m.g.__ig) {
var firstState = p.m.g.__ig, firstNode = firstState.n[6], firstAngle = 5.58, firstRadius = 1.34;
firstNode.x = Math.cos(firstAngle) * firstRadius; firstNode.y = Math.sin(firstAngle) * firstRadius;
firstNode.vx = 0; firstNode.vy = 0; firstState.hot = 6; firstState.hotT = t * (p.sp || 1);
p.jumped = true; p.cv.__sfpfFirstJump = { at: performance.now(), node: 6, x: firstNode.x, y: firstNode.y };
}
p.m.g.clearRect(0, 0, p.m.w, p.m.h);
p.draw(p.m.g, p.m.w, p.m.h, t * (p.sp || 1), p.P, p.sp || 1, p.sc || 1, p.calm);
} catch (e) { /* one bad plate must not take the page down */ }
}
function paintAll(t) { for (var k = 0; k < plates.length; k++) { paint(plates[k], t); } }var frame = 0, raf = 0, running = false;
function tick() {
frame++;
for (var k = 0; k < plates.length; k++) { if (plates[k].on) { paint(plates[k], frame); } }
raf = window.requestAnimationFrame(tick);
}
function start() { if (!running) { running = true; tick(); } }
function stop() { if (running) { running = false; window.cancelAnimationFrame(raf); } }if ("IntersectionObserver" in window) {
var io = new IntersectionObserver(function (en) {
for (var k = 0; k < en.length; k++) {
for (var q = 0; q < plates.length; q++) {
if (plates[q].cv === en[k].target) {
plates[q].on = en[k].isIntersecting;
if (en[k].isIntersecting) { paint(plates[q], frame); }
}
}
}
}, { rootMargin: "160px" });
for (var j = 0; j < plates.length; j++) { io.observe(plates[j].cv); }
}paintAll(0); /* frame zero always composes */
if (!REDUCE) { start(); }var rz;
window.addEventListener("resize", function () {
window.clearTimeout(rz);
rz = window.setTimeout(function () {
for (var k = 0; k < plates.length; k++) {
plates[k].m = fit(plates[k].cv);
/* the graph caches a fitted viewport; drop it so it re-fits cleanly */
delete plates[k].m.g.__ig;
}
paintAll(frame);
}, 180);
});
})();
}
if (document.readyState === "complete") {
sfpfMountIdentityGraph();
} else {
window.addEventListener("load", sfpfMountIdentityGraph, {once:true});
}
})();
Plate 01 · duotone #D11C1CMask · linear 20 → 80%Grade · grayscale 1 / b .90Push · 3 → 10% over 38s
WeBuildLegends.
SEO For Public Figures helps entrepreneurs, investors, and public figures build a clearer, more credible presence across search and authoritative online sources.