Show the Insights token budget as a colour-coded section breakdown

The panel reported one number for the whole prompt and one flat fill bar,
so "3412 / 4000 tokens" never said which section was spending it. Replace
the fill with a stacked bar — one segment per context section, scaled to
the budget so the leftover width is the remaining headroom — plus a legend
ordered biggest-first with each section's share and token count. Hovering
either the bar or a legend row dims the rest; clicking a row jumps to that
section's text below, and each section header now carries its own share.

Section colours move out of CSS into a single SECTION_COLORS map applied
inline, so the bar, the legend and the section headers cannot drift apart,
and related sections keep their hue family without sharing an exact shade
(two identical colours read as one segment in a stacked bar). The narrow
side panel only fits one legend column, so the long tail folds behind a
"+N smaller sections" toggle.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011BC7Dsg4gSQm3NLcZcG5SK
This commit is contained in:
Claude
2026-08-16 08:20:29 +00:00
parent bbcb07c6be
commit 8df36f8d7e
2 changed files with 205 additions and 29 deletions
+59 -18
View File
@@ -1050,14 +1050,64 @@ button:disabled { opacity: 0.45; cursor: default; transform: none; box-shadow: n
.insights-mode button { padding: 2px 8px; font-size: 0.75rem; }
.token-total { font-size: 1rem; color: var(--text); margin-bottom: 4px; }
.token-total.over { color: var(--danger); }
.token-bar { height: 6px; background: var(--bg-input); border-radius: 3px; overflow: hidden; margin-bottom: 8px; }
.token-bar-fill {
height: 100%;
background: linear-gradient(90deg, var(--accent-dim), var(--accent-bright));
box-shadow: 0 0 8px var(--accent-glow);
border-radius: 3px;
transition: width 0.4s ease;
/* Stacked share-of-context bar. Segment colours come from SECTION_COLORS in
Play.jsx so the bar, its legend and each section header stay in sync. */
.token-split {
display: flex;
height: 14px;
background: var(--bg-input);
border-radius: 4px;
overflow: hidden;
margin-bottom: 8px;
}
.token-split.over { box-shadow: 0 0 0 1px var(--danger); }
.token-seg {
min-width: 2px; /* a 0.2% section is still worth seeing */
border-right: 1px solid var(--bg-panel);
transition: opacity 0.15s ease;
}
.token-seg:last-child { border-right: none; }
.token-seg-free { background: transparent; min-width: 0; border-right: none; }
.token-seg.faded, .token-legend-item.faded { opacity: 0.25; }
.token-legend {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
gap: 1px 12px;
margin-bottom: 10px;
}
.token-legend-item {
display: flex;
align-items: center;
gap: 7px;
background: none;
border: none;
border-radius: 4px;
padding: 2px 5px;
font-size: 0.78rem;
color: var(--text-dim);
text-align: left;
transition: opacity 0.15s ease, background 0.15s ease, color 0.15s ease;
}
.token-legend-item:hover { background: rgba(255, 255, 255, 0.05); color: var(--text); }
.token-swatch { width: 9px; height: 9px; border-radius: 2px; flex: none; }
.token-legend-name { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.token-legend-pct { color: var(--text); font-weight: 600; font-variant-numeric: tabular-nums; }
.token-legend-tok {
width: 4.5em;
text-align: right;
opacity: 0.65;
font-variant-numeric: tabular-nums;
}
.token-legend-more {
justify-self: start;
background: none;
border: none;
padding: 2px 5px;
font-size: 0.75rem;
color: var(--text-dim);
}
.token-legend-more:hover { color: var(--accent); background: none; }
.insights-history { color: var(--text-dim); margin-bottom: 8px; }
.insights-cards div { margin-bottom: 3px; }
.insights-cards .dropped { color: var(--danger); }
@@ -1085,17 +1135,8 @@ button:disabled { opacity: 0.45; cursor: default; transform: none; box-shadow: n
max-height: 260px;
overflow-y: auto;
}
.ctx-narrator, .ctx-ai_instructions { border-left-color: #7d8fc9; }
.ctx-narrator .ctx-header, .ctx-ai_instructions .ctx-header { color: #7d8fc9; }
.ctx-plot_essentials, .ctx-script_context { border-left-color: #c97dc0; }
.ctx-plot_essentials .ctx-header, .ctx-script_context .ctx-header { color: #c97dc0; }
.ctx-story_summary { border-left-color: #7dc9a2; }
.ctx-story_summary .ctx-header { color: #7dc9a2; }
.ctx-world_lore { border-left-color: #c9b47d; }
.ctx-world_lore .ctx-header { color: #c9b47d; }
.ctx-history, .ctx-recent_history { border-left-color: #6a6a78; }
.ctx-authors_note, .ctx-front_memory { border-left-color: #c97d7d; }
.ctx-authors_note .ctx-header, .ctx-front_memory .ctx-header { color: #c97d7d; }
/* Per-section border/header colours are applied inline from SECTION_COLORS
(Play.jsx) — one palette drives the bar, the legend and these headers. */
/* ---------- Scripts ---------- */