→ Swarm gateway URL
// mr-data@10... / quark@10... → agent card chip (non-link, informational)
const EVIDENCE = {
network: 'sepolia',
escrowContract: '0x1111111111111111111111111111111111111111', // placeholder — replace with real DataEscrow address
addresses: {
'mr-data': { label: 'mr-data', address: '0x42aa420000000000000000000000000000000042' },
'quark': { label: 'quark', address: '0x7373730000000000000000000000000000000073' },
},
};
const etherscanTx = (hash) => `https://sepolia.etherscan.io/tx/${hash}`;
const etherscanAddr = (addr) => `https://sepolia.etherscan.io/address/${addr}`;
const swarmGateway = (ref) => `https://api.gateway.ethswarm.org/bzz/${ref.replace(/[…\.]+$/,'')}`;
// Parse a terminal line's text and return React children with inline links
// for tx hashes, escrow ids, Swarm refs. Caret handling is kept in the host.
function renderWithEvidence(text, { color, linkColor }) {
// Patterns in order — we'll tokenize by matching left-to-right.
const patterns = [
{ re: /0x[0-9a-fA-F]{16,}/g, kind: 'tx' },
{ re: /0x[0-9a-fA-F]{8,15}/g, kind: 'tx' }, // short/truncated hashes
{ re: /escrow\s*#\d+/gi, kind: 'escrow' },
{ re: /Escrow\s*#\d+/g, kind: 'escrow' },
{ re: /(?:Swarm:\s*|bzz:0x)?[a-f0-9]{16,}…?/g, kind: 'swarm', guard: /[a-f0-9]{16,}/ },
];
// Simpler: scan for the first match of each and merge positions.
const out = [];
let cursor = 0;
// Combined regex — order matters. Keep tx first so it doesn't get swallowed.
const combined = /(0x[0-9a-fA-F]{8,})|((?:[Ee]scrow\s*#\d+))|(Swarm:\s*[a-f0-9]{6,}…?)/g;
let m;
while ((m = combined.exec(text)) !== null) {
const before = text.slice(cursor, m.index);
if (before) out.push(before);
const raw = m[0];
let href = null;
if (m[1]) {
href = etherscanTx(m[1]);
} else if (m[2]) {
href = etherscanAddr(EVIDENCE.escrowContract);
} else if (m[3]) {
const ref = m[3].replace(/^Swarm:\s*/, '');
href = swarmGateway(ref);
}
out.push(
{raw}
);
cursor = m.index + raw.length;
}
const tail = text.slice(cursor);
if (tail) out.push(tail);
return out.length ? out : [text];
}
function TerminalLine({ text, startAt = 0, cps = 40, prefix = '', prefixColor, color = '#e5e7eb', bold = false, linkColor }) {
const { localTime } = useSprite();
const hasStarted = localTime >= startAt;
const elapsed = Math.max(0, localTime - startAt);
const chars = Math.floor(elapsed * cps);
const shown = text.slice(0, chars);
const done = chars >= text.length;
const caret = !done && hasStarted;
// Only render evidence chips once the line has fully typed — otherwise
// partial hashes would blink in-and-out as underlined links.
const children = done ? renderWithEvidence(shown, { color, linkColor: linkColor || color }) : [shown];
// Do not render the line (including its prefix) before its startAt time —
// otherwise empty `quark>` / `mr-data>` prompts ghost into the terminal
// ahead of when they should appear.
if (!hasStarted) return null;
return (
{prefix && {prefix}}
{children}
{caret && }
);
}
// A whole terminal window with MOTD header describing the agent.
function Terminal({ motd, agentColor, lines, style, width, height, startAt = 0 }) {
return (
{/* MOTD */}
{motd && (
{motd.name}
{motd.sub}
{motd.ip} · {motd.gpu} · QVAC runtime · PLUR memory
)}
{lines.map((ln, i) => (
))}
);
}
// PLUR logo — official SVG mark (transparent background, works on dark).
function PlurMark({ color, size = 40, palette }) {
return
;
}
// Video-inset picture-in-picture — shows real recording alongside mock terminals.
// Controlled by parent (we forward currentTime) so it stays in sync with the scrubber.
function VideoInset({ src, x, y, w, h, startSec = 0, muted = true, label = 'ORIGINAL RECORDING', color, parentLocalTime, sceneStart, watchUrl }) {
const ref = React.useRef(null);
const [hover, setHover] = React.useState(false);
const [ready, setReady] = React.useState(false);
// Seek + arm on metadata load — if the video isn't fully loaded yet, the
// initial `currentTime = startSec` jump is ignored and we get a black frame.
React.useEffect(() => {
const v = ref.current;
if (!v) return;
const onReady = () => {
setReady(true);
const target = startSec + Math.max(0, parentLocalTime);
try { v.currentTime = Math.min(target, (v.duration || 1e6) - 0.1); } catch {}
v.play && v.play().catch(() => {});
};
if (v.readyState >= 1) onReady();
v.addEventListener('loadedmetadata', onReady);
v.addEventListener('canplay', onReady);
return () => {
v.removeEventListener('loadedmetadata', onReady);
v.removeEventListener('canplay', onReady);
};
}, []);
// Keep video in sync with the stage scrubber.
React.useEffect(() => {
const v = ref.current;
if (!v || !ready) return;
const target = startSec + Math.max(0, parentLocalTime);
// Only correct if drift > 0.25s; otherwise let it play naturally.
if (Math.abs((v.currentTime || 0) - target) > 0.25) {
try { v.currentTime = target; } catch {}
}
v.play && v.play().catch(() => {});
}, [parentLocalTime, startSec, ready]);
const content = (
watchUrl && setHover(true)}
onMouseLeave={() => setHover(false)}
>
{/* REC chip */}
REC · {label}
{/* Timecode */}
{formatTc(startSec + Math.max(0, parentLocalTime))}
{/* Watch-on-Loom affordance */}
{watchUrl && (
▶ Watch full · Loom ↗
)}
);
if (watchUrl) {
return (
{content}
);
}
return content;
}
function formatTc(sec) {
const m = Math.floor(sec / 60);
const s = Math.floor(sec % 60);
return `${String(m).padStart(2,'0')}:${String(s).padStart(2,'0')}`;
}
// Small brand lockup used on intro/outro.
function BrandLockup({ tech, color, size = 13 }) {
return (
{tech.map((t, i) => (
{t}
{i < tech.length - 1 && /}
))}
);
}
// ─── Scene 1: Intro ─────────────────────────────────────────────────────────
function IntroScene({ start, end, config }) {
return (
{({ localTime }) => {
const { bg, ink, dim, gold, magenta } = config;
const gridX = (localTime * 8) % 60;
return (
{/* Grid */}
{/* Two agent glows */}
plur.ai ↗
Sovereign minds.
Sovereign rails.
{(config.introSubtitle || '').split('\n').map((line, i) => (
{i > 0 &&
}
{line}
))}
LIVE ON SEPOLIA
);
}}
);
}
function PlurMarkOLD_REMOVED({ color, size = 36 }) {
return (
);
}
// ─── Scene 2: Setup — meet the two agents ───────────────────────────────────
function SetupScene({ start, end, config }) {
return (
{() => {
const { bg, ink, dim, gold, magenta } = config;
return (
The cast
Two agents. Two machines.
Both running 32B models locally.
Different owner. Different session. No shared memory.
ENGRAM
A unit of learned memory.{' '}
Portable. Installable. Tradeable.
);
}}
);
}
function AgentCard({ at, color, name, role, quote, ip, gpu, trait, config }) {
return (
{ip} · {gpu}
{name}
{role}
"{quote}"
{trait}
);
}
// ─── Scene 3: Terminal scene with overlays ──────────────────────────────────
function TerminalScene({ start, end, config, step, title, subtitle, leftLines, rightLines, leftMotd, rightMotd, highlight, activeSide, evidence, evidenceShowAt = 3, videoSrc, videoStart, videoLabel, videoHref }) {
return (
{({ localTime, duration }) => {
const { bg, ink, dim, gold, magenta } = config;
// Chapter marker band animation
const markerIn = clamp(localTime / 0.5, 0, 1);
const markerOut = clamp((duration - localTime - 0.4) / 0.4, 0, 1);
const markerOpacity = Easing.easeOutCubic(markerIn) * Easing.easeOutCubic(markerOut);
const stepColor = activeSide === 'left' ? gold : activeSide === 'right' ? magenta : ink;
return (
{/* Chapter marker band — top */}
{subtitle}
{/* Two terminals */}
{highlight && (Array.isArray(highlight) ? highlight : [highlight]).map((h, i) => (
localTime > h.showAt ? (
) : null
))}
{videoSrc && (() => {
// Sit the video inset over the IDLE terminal (opposite of activeSide)
// so it never occludes the agent currently typing.
// activeSide='right' (Quark typing) → inset goes LEFT (over Data's idle)
// activeSide='left' (Data typing) → inset goes RIGHT (over Quark's idle)
const insetW = 480, insetH = 270;
const insetY = 1080 - insetH - 170;
const insetX = activeSide === 'right'
? 70 // left
: 1920 - insetW - 70; // right (default)
return (
);
})()}
{evidence && evidence.length > 0 && (
)}
);
}}
);
}
function VerifyBarInner({ evidence, config, localTime, showAt }) {
const o = clamp((localTime - showAt) / 0.5, 0, 1);
if (o <= 0) return null;
return (
Verify on-chain ↗
{evidence.map((e, i) => (
{e.label}
))}
);
}
function VerifyBar({ evidence, config, showAt = 3 }) {
const { localTime } = useSprite();
const o = clamp((localTime - showAt) / 0.5, 0, 1);
if (o <= 0) return null;
return (
Verify ↗
{evidence.map((e, i) => (
{e.label}
))}
);
}
function CalloutBox({ showAt, hideAt, x, y, w = 420, label, note, side = 'right', color, parentLocalTime, config }) {
const local = parentLocalTime - showAt;
const total = (hideAt ?? (showAt + 2.5)) - showAt;
const entryDur = 0.35;
const exitDur = 0.3;
const exitStart = total - exitDur;
let o = 1, dx = 0;
if (local < entryDur) {
const t = Easing.easeOutBack(clamp(local / entryDur, 0, 1));
o = clamp(local / entryDur, 0, 1);
dx = (1 - t) * (side === 'right' ? -16 : 16);
} else if (local > exitStart) {
const t = clamp((local - exitStart) / exitDur, 0, 1);
o = 1 - t;
dx = t * (side === 'right' ? 12 : -12);
}
if (local < 0 || local > total) return null;
const c = color || config.gold;
return (
);
}
// ─── Scene 4: Time-skip card for the commit-reveal delay ────────────────────
function TimeSkipScene({ start, end, config, skippedLabel }) {
return (
{({ localTime, duration }) => {
const { bg, ink, dim, gold, magenta } = config;
const progress = clamp(localTime / Math.max(0.01, duration - 0.4), 0, 1);
return (
{/* Scan lines */}
{Array.from({ length: 14 }).map((_, i) => {
const offset = (localTime * 260 + i * 140) % 1800;
return (
);
})}
Commit · reveal · anti-frontrun
Skipping the
blockchain wait
DataEscrow runs a commit → reveal handshake over {skippedLabel},
so no one can frontrun the key. The agents just wait — you don't have to.
{skippedLabel} real · compressed to {Math.round(duration * 10)/10}s
{/* Progress bar */}
);
}}
);
}
// ─── Scene 5: Payoff — knowledge transferred ────────────────────────────────
function PayoffScene({ start, end, config }) {
return (
{({ localTime }) => {
const { bg, ink, dim, gold, magenta } = config;
// Arc draws from Quark (right) to Data (left)
const arcT = Easing.easeOutCubic(clamp((localTime - 0.3) / 0.9, 0, 1));
return (
{/* Transfer arc visualization */}
Knowledge,
transferred.
Six months of training. Six seconds of transfer.
✓ No cloud APIs
✓ No middleman
✓ On-chain settlement
✓ Encrypted transport
);
}}
);
}
// ─── Scene 6: Outro — one-sentence recap + protocol strip + credits ────────
function OutroScene({ start, end, config, musicTrack }) {
return (
{() => {
const { ink, dim, gold, magenta } = config;
const stack = [
{ label: 'QVAC', sub: 'local 32B inference', by: 'Tether', href: 'https://tether.io/qvac' },
{ label: 'PLUR', sub: 'agent memory', by: 'plur.ai', href: 'https://plur.ai' },
{ label: 'Swarm', sub: 'encrypted storage', by: 'Ethereum', href: 'https://www.ethswarm.org' },
{ label: 'DataEscrow', sub: 'USDT settlement', by: 'Fair Data Society', href: 'https://fairdatasociety.org' },
];
return (
{/* Top mark */}
What you just watched
{/* Big recap sentence — the learning network thesis */}
Agents can learn from each other.
Your knowledge has value.
A learning network. No gatekeeper. No middleman. Settle in{' '}
USDT, not goodwill.
{/* Compact protocol strip — horizontal, one line each */}
{/* Works-with row */}
Works with
{['OpenClaw', 'Hermes Agent', 'Claude Code'].map((name) => (
{name}
))}
Open source · no lock-in
{/* Bottom links — pinned to bottom of 1080 canvas */}
proof of concept · {new Date().getFullYear()}
);
}}
);
}
Object.assign(window, {
Kicker, Chip, Reveal, TerminalLine, Terminal, BrandLockup, PlurMark, AgentCard, VideoInset,
IntroScene, SetupScene, TerminalScene, TimeSkipScene, PayoffScene,
OutroScene, CalloutBox, VerifyBar,
});