fix(webui): share renderer-output CSS so the console + coordinator highlight code

highlight.js, KaTeX and Mermaid all run on every surface via the shared
renderer (renderer.js), but their theme/wrapper CSS lived only in
ui/static/style.css. The console and coordinator load /static/style.css from
console/static/ — a different file on a different server — so hljs token spans
fell back to --fg (flat monospace for several releases), and the KaTeX/Mermaid
wrappers lacked their overflow containers, letting wide equations/diagrams
overflow the pane.

Move the hljs theme, .katex-display/.katex-error and the .mermaid-* wrappers
into shared_static/chat.css, which every surface loads via /shared/chat.css.
Restate the mermaid width-clamp for the preview pane (.preview-markdown) too,
since its content isn't a .msg.assistant message.

Drop the redundant background on .msg.assistant pre code.hljs so the <pre>
carries the code surface on every surface — otherwise the console/coordinator
(where the pre is --panel, not --code-bg) showed a darker box inside a lighter
padding band.
This commit is contained in:
Patrick Buckley
2026-07-08 01:34:20 -07:00
parent c328bebecd
commit 5dcf66c284
3 changed files with 187 additions and 146 deletions
+165
View File
@@ -1200,6 +1200,171 @@
background: var(--panel-2);
}
/* Syntax highlighting — highlight.js theme (instrument panel).
Lives here (shared) rather than in a per-surface style.css so the
server UI, the console, AND the coordinator all colour hljs token
spans identically. highlight.js emits the <span class="hljs-*">
markup on every surface (postRenderHljs in renderer.js); without
these rules the spans render in the default --fg and code blocks
look unhighlighted. Colours resolve against the palette variables
in base.css (also shared). */
.msg.assistant pre code.hljs {
/* No background here on purpose — the <pre> carries the code-surface colour
on every surface (--code-bg on the server UI via .msg.assistant pre, --panel
on the console/coordinator via the shared .msg-body pre). Painting it on
the inner <code> too made a darker box inside a lighter pad band wherever
the two differ (the console/coordinator seam). Let the code stay
transparent and show the pre. */
color: var(--fg);
padding: 0;
}
.hljs-keyword,
.hljs-selector-tag,
.hljs-built_in,
.hljs-type {
color: var(--magenta);
}
.hljs-string,
.hljs-attr,
.hljs-template-tag,
.hljs-template-variable {
color: var(--green);
}
.hljs-number,
.hljs-literal,
.hljs-variable,
.hljs-symbol,
.hljs-bullet {
color: var(--cyan);
}
.hljs-title,
.hljs-title.class_,
.hljs-title.function_ {
color: var(--accent);
}
.hljs-comment,
.hljs-quote {
color: var(--fg-dim);
font-style: italic;
}
.hljs-meta {
color: var(--fg-dim);
}
.hljs-doctag {
color: var(--cyan);
font-weight: 500;
}
.hljs-char.escape_ {
color: var(--cyan);
}
.hljs-emphasis {
font-style: italic;
}
.hljs-strong {
font-weight: bold;
color: var(--fg-bright);
}
.hljs-attribute {
color: var(--yellow);
}
.hljs-regexp,
.hljs-link {
color: var(--cyan);
}
.hljs-selector-id,
.hljs-selector-class {
color: var(--yellow);
}
.hljs-section {
color: var(--accent);
font-weight: bold;
}
.hljs-tag {
color: var(--fg-dim);
}
.hljs-name {
color: var(--magenta);
}
.hljs-params {
color: var(--fg);
}
.hljs-addition {
color: var(--green);
background: rgba(52, 211, 153, 0.08);
display: inline-block;
width: 100%;
}
.hljs-deletion {
color: var(--red);
background: rgba(248, 113, 113, 0.08);
display: inline-block;
width: 100%;
}
.msg.assistant pre.code-terminal {
border-left: 2px solid var(--green);
}
[data-theme="light"] .hljs-addition {
background: rgba(4, 120, 87, 0.06);
}
[data-theme="light"] .hljs-deletion {
background: rgba(220, 38, 38, 0.06);
}
/* KaTeX math wrappers — shared for the same reason as the hljs theme above:
the console + coordinator load /static/style.css from their own directory
(and do NOT load preview.css), so the app-level frame for rendered math has
to live here. The vendored katex.min.css draws the glyphs; this gives block
equations a horizontal scroll container (wide equations overflow without it)
and colours parse errors. */
.msg.assistant .katex-display {
margin: 8px 0;
padding: 8px 0;
overflow-x: auto;
overflow-y: hidden;
}
.msg.assistant .katex-error {
color: var(--red) !important;
font-size: 12px;
}
/* Mermaid diagram wrappers — shared for the same reason. mermaid.js draws a
self-contained SVG, so diagrams appear even with these missing; but without
them the SVG isn't centred or width-clamped (a wide diagram overflows the
pane) and the loading/error states render unstyled. */
.msg.assistant .mermaid-container {
margin: 8px 0;
text-align: center;
border-radius: var(--radius);
overflow-x: auto;
min-height: 40px;
}
.msg.assistant .mermaid-container svg {
max-width: 100%;
height: auto;
}
.msg.assistant .mermaid-loading {
padding: 16px;
color: var(--fg-dim);
font-size: 12px;
background: var(--bg-surface);
border: 1px solid var(--border);
}
.msg.assistant .mermaid-error {
text-align: left;
}
.msg.assistant .mermaid-error-msg {
padding: 8px 12px;
color: var(--red);
font-size: 12px;
font-weight: 600;
border-bottom: 1px solid var(--border);
}
@media (prefers-reduced-motion: reduce) {
.msg.assistant .mermaid-container svg * {
animation: none !important;
}
}
.msg-body a {
color: var(--accent);
text-decoration: underline;
+16 -3
View File
@@ -145,9 +145,10 @@
font-size: 13px;
color: var(--ink-1);
}
/* Code-block chrome + katex display: the per-ui style.css rules are scoped to
.msg.assistant and don't reach the pane, so restate them on DS tokens. The
hljs TOKEN colors are global and already apply. */
/* Code-block chrome + katex display + mermaid: the .msg.assistant-scoped rules
in shared chat.css don't reach the pane (content is .preview-markdown, not a
.msg.assistant message), so restate them on DS tokens. The hljs TOKEN colors
are global and already apply. */
.preview-markdown code {
padding: 1px 4px;
font-family: var(--font-mono);
@@ -173,6 +174,18 @@
margin: 8px 0;
overflow-x: auto;
}
/* Mermaid: mermaid.js draws a self-contained SVG, but without a width clamp a
wide diagram overflows the pane (the .msg.assistant mermaid rules in chat.css
don't reach .preview-markdown). */
.preview-markdown .mermaid-container {
margin: 8px 0;
text-align: center;
overflow-x: auto;
}
.preview-markdown .mermaid-container svg {
max-width: 100%;
height: auto;
}
.preview-markdown img {
max-width: 100%;
}
+6 -143
View File
@@ -340,149 +340,12 @@ body {
.msg.assistant blockquote blockquote blockquote {
border-left-color: var(--border);
}
.msg.assistant .katex-display {
margin: 8px 0;
padding: 8px 0;
overflow-x: auto;
overflow-y: hidden;
}
.msg.assistant .katex-error {
color: var(--red) !important;
font-size: 12px;
}
/* Syntax highlighting — highlight.js theme (instrument panel) */
.msg.assistant pre code.hljs {
background: var(--code-bg);
color: var(--fg);
padding: 0;
}
.hljs-keyword,
.hljs-selector-tag,
.hljs-built_in,
.hljs-type {
color: var(--magenta);
}
.hljs-string,
.hljs-attr,
.hljs-template-tag,
.hljs-template-variable {
color: var(--green);
}
.hljs-number,
.hljs-literal,
.hljs-variable,
.hljs-symbol,
.hljs-bullet {
color: var(--cyan);
}
.hljs-title,
.hljs-title.class_,
.hljs-title.function_ {
color: var(--accent);
}
.hljs-comment,
.hljs-quote {
color: var(--fg-dim);
font-style: italic;
}
.hljs-meta {
color: var(--fg-dim);
}
.hljs-doctag {
color: var(--cyan);
font-weight: 500;
}
.hljs-char.escape_ {
color: var(--cyan);
}
.hljs-emphasis {
font-style: italic;
}
.hljs-strong {
font-weight: bold;
color: var(--fg-bright);
}
.hljs-attribute {
color: var(--yellow);
}
.hljs-regexp,
.hljs-link {
color: var(--cyan);
}
.hljs-selector-id,
.hljs-selector-class {
color: var(--yellow);
}
.hljs-section {
color: var(--accent);
font-weight: bold;
}
.hljs-tag {
color: var(--fg-dim);
}
.hljs-name {
color: var(--magenta);
}
.hljs-params {
color: var(--fg);
}
.hljs-addition {
color: var(--green);
background: rgba(52, 211, 153, 0.08);
display: inline-block;
width: 100%;
}
.hljs-deletion {
color: var(--red);
background: rgba(248, 113, 113, 0.08);
display: inline-block;
width: 100%;
}
.msg.assistant pre.code-terminal {
border-left: 2px solid var(--green);
}
[data-theme="light"] .hljs-addition {
background: rgba(4, 120, 87, 0.06);
}
[data-theme="light"] .hljs-deletion {
background: rgba(220, 38, 38, 0.06);
}
/* Mermaid diagrams */
.msg.assistant .mermaid-container {
margin: 8px 0;
text-align: center;
border-radius: var(--radius);
overflow-x: auto;
min-height: 40px;
}
.msg.assistant .mermaid-container svg {
max-width: 100%;
height: auto;
}
.msg.assistant .mermaid-loading {
padding: 16px;
color: var(--fg-dim);
font-size: 12px;
background: var(--bg-surface);
border: 1px solid var(--border);
}
.msg.assistant .mermaid-error {
text-align: left;
}
.msg.assistant .mermaid-error-msg {
padding: 8px 12px;
color: var(--red);
font-size: 12px;
font-weight: 600;
border-bottom: 1px solid var(--border);
}
@media (prefers-reduced-motion: reduce) {
.msg.assistant .mermaid-container svg * {
animation: none !important;
}
}
/* Rendered-markdown decoration for code (highlight.js), math (KaTeX
.katex-display/.katex-error) and diagrams (Mermaid .mermaid-*) moved to
shared_static/chat.css. These style the output of the SHARED renderer.js,
which runs on the server UI, the console AND the coordinator — but those
last two load /static/style.css from their own directory, not this file, so
the rules have to be shared. Do not re-add them here. */
/* Safe HTML elements */
.msg.assistant details {