// Pipeline SVG — the CDE architecture diagram.
//
// GRAPH → X(0) → ┌─[DIFFUSION div(D⊙∇X)]─┐
// │ ⊕ → dX/dt → ODE → X(T) → CLS → ŷ
// └─[CONVECTION div(V⊙X)]──┘
// ↑
// [VELOCITY V_ij = σ(W(x_j-x_i))] ★ Eq.10
//
// Blocks are clickable: clicking jumps to the step they represent.
const { useMemo } = React;
// KaTeX-rendered sub-text inside SVG via foreignObject.
function SubKatex({ x, y, w, h, tex, color }) {
const ref = React.useRef(null);
React.useEffect(() => {
if (!ref.current || !window.katex) return;
try {
window.katex.render(tex, ref.current, {
throwOnError: false, displayMode: false, strict: "ignore",
});
} catch(e) {
if (ref.current) ref.current.textContent = tex;
}
}, [tex]);
return (
);
}
function PipeBlock({ x, y, w, h, label, sub, subTex, color, active, dim, onClick, hoverable, featured }) {
const stroke = active ? color : "#c8c1b4";
const textFill = active ? color : "#3d3a35";
const subFill = active ? color : "#827d75";
const textOp = active ? 1 : (dim ? 0.55 : 0.9);
const rectOp = active ? 1 : (dim ? 0.5 : 0.85);
const [hover, setHover] = React.useState(false);
const isClickable = !!onClick;
const rectStroke = hover && isClickable ? color : stroke;
const hasSub = !!(sub || subTex);
// Featured blocks get gold inline highlight (analogous to FEATURED_CHIPS in formulas)
const fillBg = featured
? (hover && isClickable ? "oklch(0.97 0.05 80)" : "oklch(0.965 0.04 80)")
: (hover && isClickable ? "oklch(0.985 0.01 85)" : "#fffdf7");
return (
setHover(true)}
onMouseLeave={()=>setHover(false)}
>
{isClickable && (
)}
{active && }
{featured && !active && }
{featured && "★ "}{label}
{subTex ? (
) : sub && (
{sub}
)}
);
}
function Arrow({ from, to, active, curve=0, color="#9a9388", dashed }) {
const [x1,y1]=from, [x2,y2]=to;
const mx=(x1+x2)/2, my=(y1+y2)/2 - curve;
const op = active?1:0.6;
const stroke = active ? color : "#bdb6a8";
return (
);
}
function PlusBadge({ x, y, active, color }){
return (
+
);
}
function PipelineDiagram({ activeSet, tweaks, onStepJump }) {
// Color palette for CDE (same as formulas.jsx)
const A_DIFF = "oklch(0.55 0.13 250)"; // diffusion blue
const A_CONV = "oklch(0.58 0.13 35)"; // convection amber
const A_VEL = "oklch(0.52 0.13 300)"; // velocity violet (Eq.10)
const A_OUT = "oklch(0.55 0.13 150)"; // ODE / classifier green
const A_LOSS = "oklch(0.50 0.05 260)"; // benchmark slate
const w = 1410, h = 320;
const on = k => activeSet.has(k);
const go = id => onStepJump && onStepJump(id);
// X positions for stage columns
const X = {
graph: 20,
input: 170,
diff: 320,
combine: 620,
ode: 790,
xT: 950,
cls: 1080,
yhat: 1240,
};
// Y bands
const Y = {
diff: 75, // top row (diffusion)
conv: 175, // bottom row (convection)
mid: 125, // middle (combine/ODE/X(T)/cls/ŷ)
vel: 238, // below convection (velocity source — Eq.10)
loss: 22, // top bar (benchmark / ACC)
col: 297, // column title row (lifted to clear velocity block)
};
return (
);
}
window.PipelineDiagram = PipelineDiagram;