commit 372ecdeaa4a2719d071db645776f137c093a7bc5
parent e794391f9bd6ec7b3ed6676a0738aecb985100dc
Author: Brian Graham <brian@buildingbetterteams.de>
Date: Tue, 24 Mar 2026 06:43:14 +0100
Use bar width for methodology score, not border thickness
Height = claim count, width = methodology score. A tall narrow bar
means many claims from weak papers. A short wide bar means few
claims from rigorous papers. Solid fills, no border tricks.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Diffstat:
1 file changed, 11 insertions(+), 11 deletions(-)
diff --git a/explorer/src/views/tensions.ts b/explorer/src/views/tensions.ts
@@ -98,9 +98,10 @@ function renderButterfly(positive: TensionClaim[], nuanced: TensionClaim[], meta
const barMaxH = chartH / 2 - 15;
const colW = chartW / sortedYears.length;
- // Map score to border thickness: 20% → 1px, 70% → 5px
- function borderW(score: number): number {
- return 1 + Math.max(0, Math.min(1, (score - 20) / 50)) * 4;
+ // Map score to bar width: 20% → 30% of column, 70% → 85% of column
+ function barWidth(score: number): number {
+ const t = Math.max(0, Math.min(1, (score - 20) / 50));
+ return colW * (0.25 + t * 0.5);
}
let svg = '';
@@ -122,7 +123,6 @@ function renderButterfly(positive: TensionClaim[], nuanced: TensionClaim[], meta
for (let i = 0; i < sortedYears.length; i++) {
const y = sortedYears[i];
const cx = pad.l + i * colW + colW / 2;
- const barW = colW * 0.55;
const posC = posByYear.get(y) || [];
const nuaC = nuaByYear.get(y) || [];
const posCount = posC.length;
@@ -133,21 +133,21 @@ function renderButterfly(positive: TensionClaim[], nuanced: TensionClaim[], meta
// Year label
svg += `<text x="${cx}" y="${h - 8}" text-anchor="middle" font-size="11" fill="var(--text)">${y}</text>`;
- // Positive bar — thin fill, border thickness = score
+ // Positive bar — width = score, height = count
if (posCount > 0) {
const barH = (posCount / maxCount) * barMaxH;
- const bw = borderW(posMean);
- svg += `<rect x="${cx - barW / 2}" y="${midY - barH - 1}" width="${barW}" height="${barH}" rx="2" fill="var(--accent)" fill-opacity="0.15" stroke="var(--accent)" stroke-width="${bw}">
+ const bw = barWidth(posMean);
+ svg += `<rect x="${cx - bw / 2}" y="${midY - barH - 1}" width="${bw}" height="${barH}" rx="2" fill="var(--accent)" opacity="0.7">
<title>${y} ${meta.positive}: ${posCount} claims, mean score ${Math.round(posMean)}%</title>
</rect>`;
svg += `<text x="${cx}" y="${midY - barH - 5}" text-anchor="middle" font-size="9" fill="var(--text)">${posCount} \u00b7 ${Math.round(posMean)}%</text>`;
}
- // Nuanced bar — thin fill, border thickness = score
+ // Nuanced bar — width = score, height = count
if (nuaCount > 0) {
const barH = (nuaCount / maxCount) * barMaxH;
- const bw = borderW(nuaMean);
- svg += `<rect x="${cx - barW / 2}" y="${midY + 1}" width="${barW}" height="${barH}" rx="2" fill="var(--text-dim)" fill-opacity="0.1" stroke="var(--text-dim)" stroke-width="${bw}">
+ const bw = barWidth(nuaMean);
+ svg += `<rect x="${cx - bw / 2}" y="${midY + 1}" width="${bw}" height="${barH}" rx="2" fill="var(--text-dim)" opacity="0.5">
<title>${y} ${meta.nuanced}: ${nuaCount} claims, mean score ${Math.round(nuaMean)}%</title>
</rect>`;
svg += `<text x="${cx}" y="${midY + barH + 13}" text-anchor="middle" font-size="9" fill="var(--text)">${nuaCount} \u00b7 ${Math.round(nuaMean)}%</text>`;
@@ -188,7 +188,7 @@ function renderButterfly(positive: TensionClaim[], nuanced: TensionClaim[], meta
}
return `<div style="margin:1rem 0">
- <p style="font-size:0.78rem;color:var(--text-dim);margin-bottom:0.5rem"><strong>Height</strong> = claim count. <strong>Border thickness</strong> = methodology score (thicker = more rigorous). A tall thin-bordered bar = many claims from weak papers. Dashed line = quality-weighted balance.</p>
+ <p style="font-size:0.78rem;color:var(--text-dim);margin-bottom:0.5rem"><strong>Height</strong> = claim count. <strong>Width</strong> = methodology score (wider = more rigorous). A tall narrow bar = many claims from weak papers. Dashed line = quality-weighted balance.</p>
<svg viewBox="0 0 ${w} ${h}" style="width:100%;max-width:${w}px">${svg}</svg>
</div>`;
}