// Bar layout and name wrapping adapted from BuildingBench figure-kit/bar-static/build.py.
// Data is exclusively the existing Code4Scene data/site.js paper board; no reference benchmark scores.
(async function(){
const {bindChartTooltip}=await import("./chart-interactions.js?v=20261004kit");
await Promise.all([document.fonts.load('400 13px Inter'),document.fonts.load('700 13px Inter'),document.fonts.load('500 15.5px "IBM Plex Mono"')]);
const ALL = {"t2s": [{"name": "Claude Fable 5.1 (max)", "org": "Anthropic", "score": 0.78775, "colour": "#D97757", "ink": "#ffffff", "label": "79", "new": false}, {"name": "GPT-6 Astra (max)", "org": "OpenAI", "score": 0.72382, "colour": "#10A37F", "ink": "#ffffff", "label": "72", "new": false}, {"name": "Claude Opus 5 (max)", "org": "Anthropic", "score": 0.7181599999999999, "colour": "#D97757", "ink": "#ffffff", "label": "72", "new": false}, {"name": "GPT-5.6 Sol (high)", "org": "OpenAI", "score": 0.70704, "colour": "#10A37F", "ink": "#ffffff", "label": "71", "new": false}, {"name": "Gemini 3.8 Flash (high)", "org": "Google", "score": 0.65689, "colour": "#7b1fa2", "ink": "#ffffff", "label": "66", "new": false}, {"name": "Muse Spark 1.3 (medium)", "org": "Meta", "score": 0.646195, "colour": "#42a5f5", "ink": "#111111", "label": "65", "new": false}, {"name": "Grok 4.6 (high)", "org": "xAI", "score": 0.56721, "colour": "#111111", "ink": "#ffffff", "label": "57", "new": false}, {"name": "Qwen 3.8 27B (thinking off)", "org": "Alibaba", "score": 0.55666, "colour": "#fe7016", "ink": "#111111", "label": "56", "new": false}, {"name": "Qwen 3.8 27B (thinking on)", "org": "Alibaba", "score": 0.51571, "colour": "#fe7016", "ink": "#111111", "label": "52", "new": false}, {"name": "GLM-5.3 Flash (max)", "org": "Z.ai", "score": 0.5094299999999999, "colour": "#96650b", "ink": "#ffffff", "label": "51", "new": false}, {"name": "Gemma 4 31B (thinking on)", "org": "Google", "score": 0.470705, "colour": "#7b1fa2", "ink": "#ffffff", "label": "47", "new": false}, {"name": "Gemma 4 31B (thinking off)", "org": "Google", "score": 0.45494, "colour": "#7b1fa2", "ink": "#ffffff", "label": "45", "new": false}, {"name": "Inkling (high)", "org": "Thinking Machines", "score": 0.42498500000000006, "colour": "#686868", "ink": "#ffffff", "label": "42", "new": false}, {"name": "DeepSeek V4.1 Flash (high)", "org": "DeepSeek", "score": 0.24269, "colour": "#3f51e0", "ink": "#ffffff", "label": "24", "new": false}], "i2s": [{"name": "Gemini 3.8 Flash (high)", "org": "Google", "score": 0.5810600533333334, "colour": "#7b1fa2", "ink": "#ffffff", "label": "58", "new": false}, {"name": "GPT-6 Astra (max)", "org": "OpenAI", "score": 0.5148505733333334, "colour": "#10A37F", "ink": "#ffffff", "label": "51", "new": false}, {"name": "Claude Opus 5 (max)", "org": "Anthropic", "score": 0.46809998666666675, "colour": "#D97757", "ink": "#ffffff", "label": "47", "new": false}, {"name": "Claude Fable 5.1 (max)", "org": "Anthropic", "score": 0.4243479600000001, "colour": "#D97757", "ink": "#ffffff", "label": "42", "new": false}, {"name": "GPT-5.6 Sol (high)", "org": "OpenAI", "score": 0.3929589333333333, "colour": "#10A37F", "ink": "#ffffff", "label": "39", "new": false}, {"name": "Muse Spark 1.3 (medium)", "org": "Meta", "score": 0.35821573333333334, "colour": "#42a5f5", "ink": "#111111", "label": "36", "new": false}, {"name": "GLM-5.3 Flash (max)", "org": "Z.ai", "score": 0.3199877333333333, "colour": "#96650b", "ink": "#ffffff", "label": "32", "new": false}, {"name": "Qwen 3.8 27B (thinking on)", "org": "Alibaba", "score": 0.2261779866666667, "colour": "#fe7016", "ink": "#111111", "label": "23", "new": false}, {"name": "DeepSeek V4.1 Flash (high)", "org": "DeepSeek", "score": 0.21048916, "colour": "#3f51e0", "ink": "#ffffff", "label": "21", "new": false}, {"name": "Qwen 3.8 27B (thinking off)", "org": "Alibaba", "score": 0.19970338666666668, "colour": "#fe7016", "ink": "#111111", "label": "20", "new": false}, {"name": "Inkling (high)", "org": "Thinking Machines", "score": 0.19801974666666666, "colour": "#686868", "ink": "#ffffff", "label": "20", "new": false}, {"name": "Grok 4.6 (high)", "org": "xAI", "score": 0.18414012, "colour": "#111111", "ink": "#ffffff", "label": "18", "new": false}, {"name": "Gemma 4 31B (thinking on)", "org": "Google", "score": 0.12554015999999998, "colour": "#7b1fa2", "ink": "#ffffff", "label": "13", "new": false}, {"name": "Gemma 4 31B (thinking off)", "org": "Google", "score": 0.11503794666666667, "colour": "#7b1fa2", "ink": "#ffffff", "label": "12", "new": false}]};
const LOGOS = {"Anthropic": {"icon": "anthropic", "fill": "#141413", "viewBox": "0 0 24 24", "inner": "", "rule": "evenodd"}, "OpenAI": {"icon": "openai", "fill": "#141413", "viewBox": "0 0 24 24", "inner": "", "rule": "evenodd"}, "Meta": {"icon": "meta-color", "viewBox": "0 0 24 24", "inner": "", "rule": null}, "Google": {"icon": "google-color", "viewBox": "0 0 24 24", "inner": "", "rule": null}, "DeepSeek": {"icon": "deepseek-color", "viewBox": "0 0 24 24", "inner": "", "rule": null}, "xAI": {"icon": "xai", "tile": "#111111", "shape": "square", "viewBox": "0 0 24 24", "inner": "", "rule": "evenodd"}, "Z.ai": {"icon": "zai", "tile": "#111111", "shape": "square", "viewBox": "0 0 24 24", "inner": "", "rule": "evenodd"}, "Moonshot": {"icon": "kimi", "tile": "#111111", "shape": "square", "viewBox": "0 0 24 24", "inner": "", "rule": "evenodd"}, "StepFun": {"icon": "stepfun", "tile": "#01d9cf", "shape": "circle", "viewBox": "0 0 24 24", "inner": "", "rule": "evenodd"}, "Undisclosed": {"icon": "unionalpha-color", "viewBox": "0 0 24 24", "inner": "", "rule": null}, "Cognition": {"icon": "devin-color", "viewBox": "0 0 24 24", "inner": "", "rule": null}, "Fireworks": {"icon": "fireworks-color", "viewBox": "0 0 24 24", "inner": "", "rule": null}, "Stealth": {"wordmark": ["STEALTH"]}, "Thinking Machines": {"wordmark": ["THINKING", "MACHINES"]}, "Alibaba": {"icon": "qwen-color", "viewBox": "0 0 24 24", "inner": "", "rule": null}};
for(const [key,DATA] of Object.entries(ALL)){
const svg=document.getElementById('bars-'+key), W=1200, H=420;
const NS='http://www.w3.org/2000/svg', SANS='Inter, Arial, sans-serif', MONO='"IBM Plex Mono", monospace';
const G = { // geometry, CSS px
left: 40, right: 24,
top: 26, // the 100 gridline
base: 248, // zero
barFill: 0.62, // bar width / pitch, as measured off the reference
radius: 4.5, // rounded top corners
logo: 18, logoGap: 8, // logo box, and its gap under the baseline
nameGap: 9, // gap from logo to the end of the name
nameAngle: -60, // degrees
nameSize: 13, nameLead: 14.5,
nameOneLine: 97, // a name this wide or less stays on one line
nameLine: 93, // otherwise, no wrapped line wider than this
nameTol: 12, // splits this close to the most balanced count as ties
};
let current=null;
function el(tag, attrs, parent) {
const e = document.createElementNS(NS, tag);
for (const k in attrs) e.setAttribute(k, attrs[k]);
(parent || current || svg).appendChild(e);
return e;
}
const ctx = document.createElement("canvas").getContext("2d");
function width(text, font) { ctx.font = font; return ctx.measureText(text).width; }
// Wrap a name the way the reference does: one line when it fits; otherwise the
// fewest lines (2, then 3) that keep every line within nameLine. Among those,
// the most balanced split wins -- and splits within nameTol of it count as
// equally balanced, the tie going to the longer last line: the lines are
// right-aligned against the logo, so the weight belongs at the end
// ("DeepSeek / V4.1 / Flash (max)", not "... / V4.1 Flash / (max)").
function wrap(name, font) {
if (width(name, font) <= G.nameOneLine) return [name];
const w = name.split(" ");
const splits = k => {
const out = [];
if (k === 2) for (let i = 1; i < w.length; i++) out.push([w.slice(0, i), w.slice(i)]);
if (k === 3) for (let i = 1; i < w.length; i++) for (let j = i + 1; j < w.length; j++)
out.push([w.slice(0, i), w.slice(i, j), w.slice(j)]);
return out.map(p => p.map(x => x.join(" ")));
};
for (const k of [2, 3]) {
const c = splits(k).map(lines => {
const ws = lines.map(l => width(l, font));
return {lines, worst: Math.max(...ws), last: ws[ws.length - 1]};
}).filter(o => o.worst <= G.nameLine);
if (!c.length) continue;
const floor = Math.min(...c.map(o => o.worst));
return c.filter(o => o.worst <= floor + G.nameTol).sort((a, b) => b.last - a.last)[0].lines;
}
return [name];
}
// A boxed name: at most two lines -- a three-line box is thicker than the spacing
// between neighbouring names at this bar count -- the most balanced split, ties
// to the longer last line.
function wrap2(name, font) {
if (width(name, font) <= G.nameOneLine) return [name];
const w = name.split(" "), c = [];
for (let i = 1; i < w.length; i++) {
const lines = [w.slice(0, i).join(" "), w.slice(i).join(" ")], ws = lines.map(l => width(l, font));
c.push({lines, worst: Math.max(...ws), last: ws[1]});
}
const floor = Math.min(...c.map(o => o.worst));
return c.filter(o => o.worst <= floor + G.nameTol).sort((a, b) => b.last - a.last)[0].lines;
}
// -- grid ---------------------------------------------------------------------
const y = v => G.base - v / 100 * (G.base - G.top);
for (const v of [25, 50, 75, 100])
el("line", {x1: G.left - 8, x2: W - G.right, y1: y(v), y2: y(v), stroke: "#cfcfcf",
"stroke-width": 1.4, "stroke-dasharray": "0.1 4.2", "stroke-linecap": "round"});
el("line", {x1: G.left - 8, x2: W - G.right, y1: G.base, y2: G.base, stroke: "#e6e6e6", "stroke-width": 1});
// -- bars ---------------------------------------------------------------------
const n = DATA.length, pitch = (W - G.left - G.right) / n, bwid = pitch * G.barFill;
const pos = {};
DATA.forEach((d, i) => {
const cx = G.left + (i + 0.5) * pitch, x0 = cx - bwid / 2, x1 = cx + bwid / 2;
const top = y(d.score * 100), r = Math.min(G.radius, bwid / 2);
pos[d.name] = {cx, top, x0, x1};
current=el('g',{'class':'bar-node'},svg);
el('rect',{x:G.left+i*pitch,y:G.top,width:pitch,height:H-G.top,fill:'transparent','class':'bar-hit'});
bindChartTooltip(current,svg,d.name,key,'.bar');
const bar = el("path", {class:"bar", d: `M${x0},${G.base} V${top + r} Q${x0},${top} ${x0 + r},${top} H${x1 - r} ` +
`Q${x1},${top} ${x1},${top + r} V${G.base} Z`, fill: d.colour});
const v = el("text", {x: cx, y: (top + G.base) / 2 + 5.4, "text-anchor": "middle",
"font-family": MONO, "font-weight": 500, "font-size": 15.5, fill: d.ink});
v.textContent = d.label;
// logo
const L = LOGOS[d.org], s = G.logo, lx = cx - s / 2, ly = G.base + G.logoGap;
if (L.wordmark) {
L.wordmark.forEach((w, k) => {
const tw = el("text", {x: cx, y: ly + 7.5 + k * 6.2, "text-anchor": "middle", "font-family": SANS,
"font-weight": 500, "font-size": 5.2, "letter-spacing": 0.35, fill: "#4a4a4a"});
tw.textContent = w;
});
} else {
let pad = 0, fill = L.fill || null;
if (L.tile) {
if (L.shape === "circle") el("circle", {cx, cy: ly + s / 2, r: s / 2, fill: L.tile});
else el("rect", {x: lx, y: ly, width: s, height: s, rx: 3.2, fill: L.tile});
pad = 3.4; fill = "#ffffff";
}
const ic = el("svg", {x: lx + pad, y: ly + pad, width: s - 2 * pad, height: s - 2 * pad, viewBox: L.viewBox});
if (fill) { ic.setAttribute("fill", fill); ic.setAttribute("color", fill); }
if (L.rule) ic.setAttribute("fill-rule", L.rule);
ic.innerHTML = L.inner;
}
// name: rotated, right-aligned against the logo, wrapped
const wt = d.new ? 700 : 400;
const font = `${wt} ${G.nameSize}px ${SANS}`;
const lines = d.new ? wrap2(d.name, font) : wrap(d.name, font);
const ax = cx + 3, ay = G.base + G.logoGap + G.logo + G.nameGap + (d.new ? 5 : 0);
const g = el("g", {transform: `translate(${ax},${ay}) rotate(${G.nameAngle})`});
const off = -(lines.length - 1) / 2 * G.nameLead;
if (d.new) { // the model this figure is about: white on a box of its own colour
const bw_ = Math.max(...lines.map(l => width(l, font)));
const y0_ = off + 4.5 - 0.80 * G.nameSize - 2.5, y1_ = off + (lines.length - 1) * G.nameLead + 4.5 + 0.24 * G.nameSize + 2.5;
el("rect", {x: -bw_ - 5, y: y0_, width: bw_ + 10, height: y1_ - y0_, rx: 4, fill: d.colour}, g);
}
lines.forEach((ln, k) => {
const tl = el("text", {x: 0, y: off + k * G.nameLead + 4.5, "text-anchor": "end", "font-family": SANS,
"font-weight": wt, "font-size": G.nameSize, fill: d.new ? "#ffffff" : "#262626"}, g);
tl.textContent = ln;
});
});
current=null;svg.dataset.ready='true';
}
})();