)}
);
}
// ── Masthead title lockup — three variants ──────────────────────────
// "paren-lockup" (default) — "The Brief" big LEFT + "(powered by / [logo])" RIGHT in parens
// "inline" — single line: "The Brief (powered by [logo])"
// "stacked" — title big, "powered by" small below, "[logo]" below that, all centered
function MastheadLockup({ style, theme }) {
const LOGO_SRC = theme === "dark" ? "bigdata-logo-white.png" : "bigdata-logo-black.png";
if (style === "inline") {
return (
The Brief
(powered by)
);
}
if (style === "stacked") {
return (
The Brief
powered by
);
}
// Default: "paren-lockup"
return (
The Brief
powered by
);
}
// ── Theme dot ───────────────────────────────────────────────────────
// Derives a vivid, stable colour from any label string via a simple hash.
function hashThemeColor(label) {
if (!label) return "var(--ink-mute)";
let h = 0;
for (let i = 0; i < label.length; i++) {
h = Math.imul(31, h) + label.charCodeAt(i) | 0;
}
const hue = ((h % 360) + 360) % 360;
const dark = document.documentElement.dataset.theme === "dark";
return `hsl(${hue}, 70%, ${dark ? 62 : 38}%)`;
}
function ThemeDot({ theme, color: colorProp }) {
const color = colorProp || hashThemeColor(theme);
return ;
}
// ── Sparkline (saved bullets per day) ───────────────────────────────
function Sparkline({
data,
height = 22,
width = 80,
color = "var(--ink-soft)",
fillColor = null,
showLast = false,
fluid = false,
minVal = null,
maxVal = null,
showZero = false,
}) {
if (!data || data.length === 0) return null;
const max = maxVal !== null ? maxVal : Math.max(...data);
const min = minVal !== null ? minVal : Math.min(...data);
const range = Math.max(max - min, 0.0001);
const span = Math.max(data.length - 1, 1);
const step = width / span;
const points = data.map((v, i) => {
const x = i * step;
const y = height - 2 - (v - min) / range * (height - 4);
return `${x.toFixed(1)},${y.toFixed(1)}`;
}).join(" ");
const last = data[data.length - 1];
const lastY = height - 2 - (last - min) / range * (height - 4);
const lastX = (data.length - 1) * step;
const svgClass = "spark" + (fluid ? " spark--fluid" : "");
const common = {
className: svgClass,
viewBox: `0 0 ${width} ${height}`,
};
const svgProps = fluid
? {
...common,
preserveAspectRatio: "none",
style: { width: "100%", height, display: "block" },
}
: { ...common, width, height };
const zeroY = showZero && min < 0 && max > 0
? height - 2 - (0 - min) / range * (height - 4)
: null;
const fillBase = zeroY !== null ? zeroY : height;
return (
);
}
// ── Bar mini-chart ──────────────────────────────────────────────────
function MiniBars({ data, height = 28, barWidth = 6, gap = 2, color = "var(--ink)", mutedColor = "var(--rule)" }) {
if (!data || data.length === 0) return null;
const max = Math.max(...data.map((d) => typeof d === "number" ? d : d.value), 1);
return (
);
}
// ── Citation popover ────────────────────────────────────────────────
function CitationRef({ citation, idx }) {
return (
{idx + 1}{citation.source} · {citation.date}{citation.headline}{citation.excerpt});
}
// ── Status badges ──────────────────────────────────────────────────
function StatusBadge({ status }) {
const map = {
succeeded: { cls: "tag-novel", label: "Succeeded" },
running: { cls: "tag-running", label: "Running" },
failed: { cls: "tag-discard", label: "Failed" }
};
const m = map[status] || { cls: "", label: status };
return {m.label};
}
// ── DivergingSparkline — two-tone area chart for signed signals ──────────────
function DivergingSparkline({
data,
height = 38,
width = 240,
posColor = "var(--novel)",
negColor = "var(--discard)",
}) {
if (!data || data.length === 0) return null;
const uid = React.useId();
const absMax = Math.max(...data.map(v => Math.abs(v)));
const ext = Math.max(absMax * 1.18, 0.005);
const ymin = -ext;
const ymax = ext;
const range = ymax - ymin;
const h = height;
const w = width;
const yOf = (v) => h - 2 - (v - ymin) / range * (h - 4);
const zeroY = yOf(0);
const step = w / Math.max(data.length - 1, 1);
const pts = data.map((v, i) => [i * step, yOf(v)]);
const line = pts
.map(([x, y], i) => `${i === 0 ? "M" : "L"}${x.toFixed(2)},${y.toFixed(2)}`)
.join(" ");
const last = pts[pts.length - 1];
const area = `${line} L${last[0].toFixed(2)},${zeroY.toFixed(2)} L0,${zeroY.toFixed(2)} Z`;
return (
);
}
window.Masthead = Masthead;
window.MastheadLockup = MastheadLockup;
window.ThemeDot = ThemeDot;
window.Sparkline = Sparkline;
window.DivergingSparkline = DivergingSparkline;
window.MiniBars = MiniBars;
window.CitationRef = CitationRef;
window.StatusBadge = StatusBadge;