import React, { useState } from "react";
import { ShieldAlert } from "lucide-react";
import { C, FD, FB, FM, fmt } from "../theme.js";
// Small presentational atoms lifted verbatim-in-spirit from the validated mock.
// Do NOT restyle these; they carry the Tactical Grey look.
export function Chip({ dot, text }) {
return (
{text}
);
}
export function Stat({ label, v, grad }) {
return (
);
}
export function Hero({ v, label, grad }) {
return (
);
}
export function PanelTitle({ icon: Icon, text, mt }) {
return (
{text}
);
}
export function SecHead({ icon: Icon, c, text }) {
return (
);
}
export function Bar({ label, v, max, c, note }) {
return (
{label}
{fmt(v)}
{note &&
{note}
}
);
}
// A line-style legend row used inside the turn graph (proven vs hypothesis).
export function EdgeLegend({ c, text, dashed }) {
return (
{text}
);
}
export function ChainNode({ icon: Icon, c, title, sub }) {
return (
);
}
// ---------------------------------------------------------------------------
// BINARIES — the real tools run via Bash (npx remotion -> remotion, railway, …),
// a SEPARATE entity dimension from tool calls. Logo served LOCALLY from
// /binary-logos/.svg (pulled by the background enricher); colored-monogram
// fallback when the file isn't there yet. No network on render (NN #2).
// ---------------------------------------------------------------------------
const _MONO = [C.orange, C.cyan, C.amber, C.blue, "#a78bfa", "#f472b6", "#34d399", "#fb923c", "#60a5fa"];
function monoColor(name) {
let h = 0;
for (let i = 0; i < name.length; i++) h = (h * 31 + name.charCodeAt(i)) >>> 0;
return _MONO[h % _MONO.length];
}
export function BinaryLogo({ b, size = 18 }) {
const [err, setErr] = useState(false);
const name = (b.binary || b.name || "?");
const src = b.logo || `/binary-logos/${encodeURIComponent(name)}.svg`;
const col = monoColor(name);
if (err) {
return (
{name[0] ? name[0].toUpperCase() : "?"}
);
}
return (
setErr(true)}
style={{ borderRadius: 4, objectFit: "contain", flexShrink: 0, background: "transparent" }} />
);
}
// Compact chip (logo + product) for session cards / inline lists.
export function BinaryBadge({ b, onClick }) {
const name = b.binary || b.name;
const label = b.product || name;
return (
{label}
{b.security && }
);
}
// A traceable row for the left rails: logo + product, blurb, count, security note,
// and the turns it fired in. `onOpen(turnIndex)` jumps to the first turn.
export function BinaryRow({ b, onOpen, color = C.orange }) {
const name = b.binary || b.name;
const label = b.product || name;
const turns = b.turns || [];
return (
turns.length && onOpen && onOpen(turns[0])}
title={`${b.identified ? label : name + " (not yet identified)"}${b.blurb ? " — " + b.blurb : ""}` +
`${b.via && b.via !== "direct" ? " · via " + b.via : ""}` +
`${turns.length ? " · turn(s) " + turns.join(", ") : ""}` +
`${b.security ? " ⚠ " + b.security : ""}`}
style={{ display: "flex", alignItems: "center", gap: 7, padding: "5px 8px", borderRadius: 6, cursor: turns.length ? "pointer" : "default", borderLeft: `2px solid ${color}` }}>
{label}{!b.identified && · {name}}
{b.blurb && (
{b.blurb}
)}
{b.security && }
×{b.count ?? b.total}
);
}
// "Generated" provenance badge — every piece of narrator prose must be labelled
// generated (NON-NEGOTIABLE #7). Deterministic numbers are NOT badged.
export function GeneratedTag({ cites }) {
return (
GENERATED{cites ? ` · reads ${cites}` : ""}
);
}