feat(ui): terminal, charts and low-contrast text follow the selected theme

- The lane terminal (xterm) takes its palette from the selected DARK theme —
  it stays dark in light mode, as a terminal should — and repaints live when
  the theme changes (`client/src/lib/terminalTheme.ts`).
- Charts on the Dashboard and Workflows pages draw their grid, axes, labels
  and tooltips from theme tokens instead of hardcoded near-black/white, and
  the activity heatmap ramps from the page surface to the accent, so it reads
  on every theme instead of going near-black on light ones.
- Status/brand text that only worked on dark backgrounds
  (`text-*-300/400`) gets a darker light-mode shade (`text-*-700
  dark:text-*-300`) across sessions, conversations, workflows, config and
  settings. Categorical chart colours are kept.
This commit is contained in:
2026-09-24 09:50:44 +07:00
parent 6353e88c9e
commit 8ea40260ad
36 changed files with 919 additions and 635 deletions
@@ -262,7 +262,7 @@ export function SessionComplexityScatter({ data, onSessionClick }: SessionComple
.range([MIN_BUBBLE_R, MAX_BUBBLE_R]);
// Grid lines
const gridColor = "#2a2a3d";
const gridColor = "rgb(var(--border))";
g.append("g")
.attr("class", "grid-x")
@@ -303,9 +303,9 @@ export function SessionComplexityScatter({ data, onSessionClick }: SessionComple
.tickFormat((d) => fmtXTick(d as number))
)
.call((sel) => {
sel.select(".domain").attr("stroke", "#363650");
sel.selectAll(".tick line").attr("stroke", "#363650");
sel.selectAll(".tick text").attr("fill", "#6b7280").attr("font-size", "11");
sel.select(".domain").attr("stroke", "rgb(var(--border-light))");
sel.selectAll(".tick line").attr("stroke", "rgb(var(--border-light))");
sel.selectAll(".tick text").attr("fill", "rgb(var(--fg-muted))").attr("font-size", "11");
});
// X axis label
@@ -313,7 +313,7 @@ export function SessionComplexityScatter({ data, onSessionClick }: SessionComple
.attr("x", innerW / 2)
.attr("y", innerH + 44)
.attr("text-anchor", "middle")
.attr("fill", "#6b7280")
.attr("fill", "rgb(var(--fg-muted))")
.attr("font-size", "11")
.text(t("complexity.duration"));
@@ -321,9 +321,9 @@ export function SessionComplexityScatter({ data, onSessionClick }: SessionComple
g.append("g")
.call(d3.axisLeft(yScale).ticks(5).tickFormat(d3.format("d")))
.call((sel) => {
sel.select(".domain").attr("stroke", "#363650");
sel.selectAll(".tick line").attr("stroke", "#363650");
sel.selectAll(".tick text").attr("fill", "#6b7280").attr("font-size", "11");
sel.select(".domain").attr("stroke", "rgb(var(--border-light))");
sel.selectAll(".tick line").attr("stroke", "rgb(var(--border-light))");
sel.selectAll(".tick text").attr("fill", "rgb(var(--fg-muted))").attr("font-size", "11");
});
// Y axis label
@@ -332,7 +332,7 @@ export function SessionComplexityScatter({ data, onSessionClick }: SessionComple
.attr("x", -innerH / 2)
.attr("y", -40)
.attr("text-anchor", "middle")
.attr("fill", "#6b7280")
.attr("fill", "rgb(var(--fg-muted))")
.attr("font-size", "11")
.text(t("complexity.agentCount"));