fix(ui): carapace follow-ups — embed font stacks, data-theme-resolved, undefined status tokens (#113724)

* feat(ui): publish carapace embed font stacks to MCP apps

Adopt the carapace embed contract's sandbox-safe font stacks: publish
--font-sans for the first time and switch --font-mono from the host's
JetBrains-led token to the embed mono stack. Both are static, system-
resolvable values byte-identical to carapace candidate/embed.css, since
the sandbox font-src policy silently drops brand faces.

* feat(ui): emit data-theme-resolved alongside theme attributes

Carapace CSS selects on [data-theme-resolved]; keep it in lockstep with
data-theme-mode at boot (index.html IIFE) and on every runtime theme
change (bootstrap publish path). Rename applyStartupPresentation to
applyThemePresentation: it runs on every theme change, not just startup.

* fix(ui): resolve undefined --success/--warning tokens and drop dead hex fallbacks

--success and --warning were never defined (real tokens: --ok/--warn),
so sites with literal fallbacks rendered off-palette one-off colors and
sites without them silently dropped declarations (invalid color-mix in
the chat sidebar warn banner). Map all uses to the semantic tokens
across board, chat sidebar/layout, layout, and components styles, and
strip the stale dead var() hex fallbacks in these global stylesheets.
Code-syntax palette hexes in the file view are documented as deliberate.
This commit is contained in:
Peter Steinberger
2026-07-25 09:32:56 -07:00
committed by GitHub
parent dd606796c1
commit e279076010
9 changed files with 161 additions and 150 deletions

View File

@@ -62,10 +62,10 @@
? "light"
: "dark";
document.documentElement.setAttribute("data-theme", resolved);
document.documentElement.setAttribute(
"data-theme-mode",
resolved.includes("light") ? "light" : "dark",
);
var resolvedMode = resolved.includes("light") ? "light" : "dark";
document.documentElement.setAttribute("data-theme-mode", resolvedMode);
// Carapace CSS selects on [data-theme-resolved]; keep in lockstep.
document.documentElement.setAttribute("data-theme-resolved", resolvedMode);
} catch (e) {}
})();
</script>

View File

@@ -76,7 +76,7 @@ function normalizeInitialApplicationLocation(
};
}
function applyStartupPresentation(settings: ReturnType<typeof loadSettings>): void {
function applyThemePresentation(settings: ReturnType<typeof loadSettings>): void {
if (typeof document === "undefined") {
return;
}
@@ -84,6 +84,9 @@ function applyStartupPresentation(settings: ReturnType<typeof loadSettings>): vo
const resolvedTheme = resolveTheme(settings.theme, settings.themeMode);
root.dataset.theme = resolvedTheme;
root.dataset.themeMode = resolvedTheme.endsWith("light") ? "light" : "dark";
// Carapace CSS (openclaw/carapace) selects on [data-theme-resolved]; keep it
// in lockstep with data-theme-mode so its stylesheets work unmodified here.
root.dataset.themeResolved = root.dataset.themeMode;
root.classList.toggle("wa-light", root.dataset.themeMode === "light");
root.classList.toggle("wa-dark", root.dataset.themeMode === "dark");
root.style.colorScheme = root.dataset.themeMode;
@@ -99,7 +102,7 @@ function createApplicationTheme(
const listeners = new Set<() => void>();
const publish = () => {
applyStartupPresentation(settings);
applyThemePresentation(settings);
for (const listener of listeners) {
listener();
}
@@ -328,7 +331,7 @@ export function bootstrapApplication(): ApplicationRuntime {
const webPush = createWebPushCapability(gateway);
const skillWorkshopRevision = createSkillWorkshopRevisionHandoff();
const initialUserMessage = createInitialUserMessageHandoff();
applyStartupPresentation(settings);
applyThemePresentation(settings);
const router = createApplicationRouter();
let pendingGatewayConnection =
startup.pendingGatewayUrl !== null

View File

@@ -66,11 +66,13 @@ describe("collectMcpAppStyleVariables", () => {
);
// Font requests are limited to resource domains the app declares, so a
// host-led webfont resolves to an arbitrary system face rather than
// failing visibly. Apps own their sans stack until Control UI can supply
// a sandbox-safe one.
expect(variables).not.toHaveProperty("--font-sans");
expect(variables?.["--font-mono"]).toContain("monospace");
// host-led brand face resolves to an arbitrary system face rather than
// failing visibly. The published stacks are the carapace embed stacks:
// system resolvable, independent of the host's own font tokens.
expect(variables?.["--font-sans"]).toMatch(/^system-ui,/);
expect(variables?.["--font-sans"]).not.toContain("Inter");
expect(variables?.["--font-mono"]).toMatch(/^ui-monospace,/);
expect(variables?.["--font-mono"]).not.toContain("JetBrains");
});
it("publishes trimmed, non-empty values", () => {

View File

@@ -33,17 +33,6 @@ const HOST_TOKEN_SOURCES = {
"--color-border-inverse": "--bg",
"--color-ring-primary": "--ring",
/*
* Only the monospace stack is published. Control UI's body font leads with a
* webfont, and an embedded app cannot load it: the sandbox policy allows
* font requests only from resource domains the app itself declares. Sending
* it would resolve to an arbitrary system face instead of failing visibly.
* The monospace stack degrades correctly because its fallbacks are system
* faces. Apps supply their own sans stack until Control UI adopts the
* carapace embed tokens, which define a sandbox-safe one.
*/
"--font-mono": "--mono",
"--font-text-xs-size": "--control-ui-text-xs",
"--font-text-sm-size": "--control-ui-text-sm",
"--font-text-md-size": "--control-ui-text-md",
@@ -61,13 +50,27 @@ const HOST_TOKEN_SOURCES = {
"--shadow-lg": "--shadow-lg",
} as const;
/** Values with no Control UI source, fixed by the specification's own scale. */
/**
* Values with no Control UI source, fixed by the specification's own scale or
* the carapace embed contract.
*
* The font stacks are the carapace embed stacks (`--oc-font-embed-sans` /
* `--oc-font-embed-mono`), sent in place of Control UI's own font tokens. The
* sandbox policy allows font requests only from resource domains the app
* itself declares, so a stack leading with a brand face would silently
* resolve to an arbitrary system font; every family here is system
* resolvable. Keep them byte-identical to carapace `candidate/embed.css`.
*/
const STATIC_VARIABLES = {
"--border-width-regular": "1px",
"--font-weight-normal": "400",
"--font-weight-medium": "500",
"--font-weight-semibold": "600",
"--font-weight-bold": "700",
"--font-sans":
'system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI Variable Text", "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji"',
"--font-mono":
'ui-monospace, "SFMono-Regular", "SF Mono", Menlo, Consolas, "Liberation Mono", monospace',
} as const;
type StyleVariableKey = keyof typeof HOST_TOKEN_SOURCES | keyof typeof STATIC_VARIABLES;

View File

@@ -5,8 +5,8 @@ openclaw-board-view {
}
.board-view {
--board-line: color-mix(in srgb, var(--border, #2c313a) 84%, transparent);
--board-surface: color-mix(in srgb, var(--panel, #171a20) 94%, transparent);
--board-line: color-mix(in srgb, var(--border) 84%, transparent);
--board-surface: color-mix(in srgb, var(--panel) 94%, transparent);
display: grid;
gap: 12px;
min-width: 0;
@@ -14,10 +14,10 @@ openclaw-board-view {
}
.board-view__error {
background: color-mix(in srgb, var(--danger, #ff6b6b) 8%, var(--panel, #171a20));
border: 1px solid color-mix(in srgb, var(--danger, #ff6b6b) 42%, transparent);
background: color-mix(in srgb, var(--danger) 8%, var(--panel));
border: 1px solid color-mix(in srgb, var(--danger) 42%, transparent);
border-radius: 9px;
color: var(--danger, #ff6b6b);
color: var(--danger);
font-size: 12px;
padding: 9px 12px;
}
@@ -51,7 +51,7 @@ openclaw-board-view {
}
.board-tabs__tab {
color: var(--muted, #8a919e);
color: var(--muted);
flex: 0 0 auto;
}
@@ -68,18 +68,18 @@ openclaw-board-view {
.board-tabs__tab:hover::part(base),
.board-tabs__tab:focus-visible::part(base) {
background: color-mix(in srgb, var(--text, #d7dae0) 6%, transparent);
color: var(--text, #d7dae0);
background: color-mix(in srgb, var(--text) 6%, transparent);
color: var(--text);
}
.board-tabs__tab--active::part(base) {
border-bottom-color: var(--accent, #ff5c5c);
color: var(--text, #d7dae0);
border-bottom-color: var(--accent);
color: var(--text);
}
.board-tabs__tab--drop::part(base) {
background: color-mix(in srgb, var(--accent, #ff5c5c) 14%, transparent);
box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--accent, #ff5c5c) 70%, transparent);
background: color-mix(in srgb, var(--accent) 14%, transparent);
box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--accent) 70%, transparent);
}
.board-tabs__overflow,
@@ -94,7 +94,7 @@ openclaw-board-view {
background: transparent;
border: 0;
border-radius: 7px;
color: var(--muted, #8a919e);
color: var(--muted);
cursor: pointer;
display: inline-flex;
justify-content: center;
@@ -108,13 +108,13 @@ openclaw-board-view {
.board-tabs__overflow-trigger:hover,
.board-widget__menu-trigger:hover {
background: color-mix(in srgb, var(--text, #d7dae0) 10%, transparent);
color: var(--text, #d7dae0);
background: color-mix(in srgb, var(--text) 10%, transparent);
color: var(--text);
}
.board-tabs__overflow::part(menu),
.board-widget__menu::part(menu) {
background: var(--panel, #171a20);
background: var(--panel);
border: 1px solid var(--board-line);
border-radius: 10px;
box-shadow: 0 18px 48px rgb(0 0 0 / 32%);
@@ -136,7 +136,7 @@ openclaw-board-view {
}
.board-grid__append-zone {
border-top: 1px dashed color-mix(in srgb, var(--accent, #ff5c5c) 48%, transparent);
border-top: 1px dashed color-mix(in srgb, var(--accent) 48%, transparent);
bottom: -42px;
height: 38px;
left: 0;
@@ -167,12 +167,12 @@ openclaw-board-widget-cell {
}
.board-widget:focus-visible {
box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent, #ff5c5c) 70%, transparent);
box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent) 70%, transparent);
outline: none;
}
.board-widget--dragging {
border-color: color-mix(in srgb, var(--accent, #ff5c5c) 72%, transparent);
border-color: color-mix(in srgb, var(--accent) 72%, transparent);
box-shadow: 0 16px 36px rgb(0 0 0 / 28%);
opacity: 0.88;
transform: scale(0.995);
@@ -181,7 +181,7 @@ openclaw-board-widget-cell {
.board-widget__bar {
align-items: center;
background: color-mix(in srgb, var(--text, #d7dae0) 3%, transparent);
background: color-mix(in srgb, var(--text) 3%, transparent);
border-bottom: 1px solid var(--board-line);
border-radius: 11px 11px 0 0;
display: flex;
@@ -194,7 +194,7 @@ openclaw-board-widget-cell {
.board-widget__resize-handle {
background: transparent;
border: 0;
color: var(--muted, #8a919e);
color: var(--muted);
}
.board-widget__drag-handle {
@@ -211,12 +211,12 @@ openclaw-board-widget-cell {
}
.board-widget__drag-handle:hover {
background: color-mix(in srgb, var(--text, #d7dae0) 9%, transparent);
color: var(--text, #d7dae0);
background: color-mix(in srgb, var(--text) 9%, transparent);
color: var(--text);
}
.board-widget__title {
color: var(--text, #d7dae0);
color: var(--text);
font-size: 12.5px;
font-weight: 590;
min-width: 0;
@@ -228,7 +228,7 @@ openclaw-board-widget-cell {
.board-widget__kind {
border: 1px solid var(--board-line);
border-radius: 999px;
color: var(--muted, #8a919e);
color: var(--muted);
font-size: 8px;
letter-spacing: 0.08em;
line-height: 15px;
@@ -248,7 +248,7 @@ openclaw-board-widget-cell {
}
.board-widget__menu-heading {
color: var(--muted, #8a919e);
color: var(--muted);
font-size: 9px;
letter-spacing: 0.08em;
padding: 7px 9px 3px;
@@ -256,7 +256,7 @@ openclaw-board-widget-cell {
}
.board-widget__menu-empty {
color: var(--muted, #8a919e);
color: var(--muted);
font-size: 11px;
padding: 5px 9px;
}
@@ -271,7 +271,7 @@ openclaw-board-widget-cell {
}
.board-widget__menu-danger {
color: var(--danger, #ff6b6b);
color: var(--danger);
}
.board-widget__body {
@@ -324,9 +324,9 @@ openclaw-board-widget-cell {
}
.observer-widget__current {
background: color-mix(in srgb, var(--text, #d7dae0) 4%, transparent);
background: color-mix(in srgb, var(--text) 4%, transparent);
border: 1px solid var(--board-line);
border-left: 3px solid var(--muted, #8a919e);
border-left: 3px solid var(--muted);
border-radius: 9px;
display: grid;
gap: 8px;
@@ -336,17 +336,17 @@ openclaw-board-widget-cell {
.observer-widget__current[data-health="on-track"],
.observer-widget__current[data-health="done"],
.observer-widget__current[data-health="wrapping-up"] {
border-left-color: var(--success, #45c486);
border-left-color: var(--ok);
}
.observer-widget__current[data-health="grinding"] {
border-left-color: var(--warning, #e7b85c);
border-left-color: var(--warn);
}
.observer-widget__current[data-health="stuck"],
.observer-widget__current[data-health="waiting-on-user"],
.observer-widget__current[data-health="failed"] {
border-left-color: var(--danger, #ff6b6b);
border-left-color: var(--danger);
}
.observer-widget__current-heading {
@@ -365,20 +365,20 @@ openclaw-board-widget-cell {
.observer-widget__eyebrow,
.observer-widget__timeline-title,
.observer-widget__run {
color: var(--muted, #8a919e);
color: var(--muted);
font-size: 9px;
letter-spacing: 0.08em;
text-transform: uppercase;
}
.observer-widget__current-heading strong {
color: var(--text, #d7dae0);
color: var(--text);
font-size: 13px;
line-height: 1.35;
}
.observer-widget__assessment {
color: var(--muted, #8a919e);
color: var(--muted);
font-size: 11px;
line-height: 1.45;
margin: 0 0 0 19px;
@@ -386,7 +386,7 @@ openclaw-board-widget-cell {
.observer-widget__progress {
align-items: center;
color: var(--muted, #8a919e);
color: var(--muted);
display: grid;
font-size: 9px;
gap: 7px;
@@ -395,19 +395,19 @@ openclaw-board-widget-cell {
}
.observer-widget__progress strong {
color: var(--text, #d7dae0);
color: var(--text);
font-weight: 600;
}
.observer-widget__progress-track {
background: color-mix(in srgb, var(--text, #d7dae0) 9%, transparent);
background: color-mix(in srgb, var(--text) 9%, transparent);
border-radius: 999px;
height: 3px;
overflow: hidden;
}
.observer-widget__progress-track > span {
background: var(--accent, #ff5c5c);
background: var(--accent);
display: block;
height: 100%;
}
@@ -438,11 +438,11 @@ openclaw-board-widget-cell {
}
.observer-widget__run[data-current="true"] > span {
color: var(--text, #d7dae0);
color: var(--text);
}
.observer-widget__run code {
color: var(--muted, #8a919e);
color: var(--muted);
font-size: 9px;
letter-spacing: 0;
overflow: hidden;
@@ -462,18 +462,18 @@ openclaw-board-widget-cell {
}
.observer-widget__timeline-row--transition {
background: color-mix(in srgb, var(--text, #d7dae0) 4%, transparent);
background: color-mix(in srgb, var(--text) 4%, transparent);
box-shadow: inset 2px 0 color-mix(in srgb, currentcolor 48%, transparent);
}
.observer-widget__timeline-row > time,
.observer-widget__health-label {
color: var(--muted, #8a919e);
color: var(--muted);
font-size: 9px;
}
.observer-widget__timeline-headline {
color: var(--text, #d7dae0);
color: var(--text);
font-size: 10.5px;
overflow: hidden;
text-overflow: ellipsis;
@@ -481,7 +481,7 @@ openclaw-board-widget-cell {
}
.observer-widget__health-dot {
background: var(--muted, #8a919e);
background: var(--muted);
border-radius: 50%;
height: 8px;
margin-top: 3px;
@@ -491,22 +491,22 @@ openclaw-board-widget-cell {
.observer-widget__health-dot[data-health="on-track"],
.observer-widget__health-dot[data-health="done"],
.observer-widget__health-dot[data-health="wrapping-up"] {
background: var(--success, #45c486);
background: var(--ok);
}
.observer-widget__health-dot[data-health="grinding"] {
background: var(--warning, #e7b85c);
background: var(--warn);
}
.observer-widget__health-dot[data-health="stuck"],
.observer-widget__health-dot[data-health="waiting-on-user"],
.observer-widget__health-dot[data-health="failed"] {
background: var(--danger, #ff6b6b);
background: var(--danger);
}
.observer-widget__unread-boundary {
align-items: center;
color: var(--accent, #ff5c5c);
color: var(--accent);
display: grid;
font-size: 8px;
gap: 8px;
@@ -518,7 +518,7 @@ openclaw-board-widget-cell {
.observer-widget__unread-boundary::before,
.observer-widget__unread-boundary::after {
border-top: 1px solid color-mix(in srgb, var(--accent, #ff5c5c) 42%, transparent);
border-top: 1px solid color-mix(in srgb, var(--accent) 42%, transparent);
content: "";
}
@@ -536,7 +536,7 @@ openclaw-board-widget-cell {
.board-widget__disabled-plugin,
.workboard-widget__state {
align-content: center;
color: var(--muted, #8a919e);
color: var(--muted);
display: grid;
font-size: 11px;
gap: 10px;
@@ -548,7 +548,7 @@ openclaw-board-widget-cell {
}
.board-widget__disabled-plugin strong {
color: var(--text, #d7dae0);
color: var(--text);
}
openclaw-workboard-card-widget,
@@ -576,7 +576,7 @@ openclaw-workboard-mini-widget {
.workboard-widget-card__heading > strong,
.workboard-widget-mini__card > strong {
color: var(--text, #d7dae0);
color: var(--text);
font-size: 12px;
overflow: hidden;
text-overflow: ellipsis;
@@ -586,7 +586,7 @@ openclaw-workboard-mini-widget {
.workboard-widget__status {
border: 1px solid var(--board-line);
border-radius: 999px;
color: var(--muted, #8a919e);
color: var(--muted);
flex: 0 0 auto;
font-size: 9px;
padding: 2px 6px;
@@ -594,8 +594,8 @@ openclaw-workboard-mini-widget {
.workboard-widget__status--ready,
.workboard-widget__status--running {
border-color: color-mix(in srgb, var(--accent, #ff5c5c) 45%, transparent);
color: var(--accent, #ff5c5c);
border-color: color-mix(in srgb, var(--accent) 45%, transparent);
color: var(--accent);
}
.workboard-widget-card__meta {
@@ -607,7 +607,7 @@ openclaw-workboard-mini-widget {
.workboard-widget-card__meta div,
.workboard-widget-mini__counts span {
background: color-mix(in srgb, var(--text, #d7dae0) 3%, transparent);
background: color-mix(in srgb, var(--text) 3%, transparent);
border: 1px solid var(--board-line);
border-radius: 8px;
min-width: 0;
@@ -616,13 +616,13 @@ openclaw-workboard-mini-widget {
.workboard-widget-card__meta dt,
.workboard-widget-card__move > span {
color: var(--muted, #8a919e);
color: var(--muted);
font-size: 9px;
text-transform: uppercase;
}
.workboard-widget-card__meta dd {
color: var(--text, #d7dae0);
color: var(--text);
font-size: 11px;
margin: 3px 0 0;
overflow: hidden;
@@ -636,16 +636,16 @@ openclaw-workboard-mini-widget {
}
.workboard-widget-card__move select {
background: var(--panel, #171a20);
background: var(--panel);
border: 1px solid var(--board-line);
border-radius: 7px;
color: var(--text, #d7dae0);
color: var(--text);
font: inherit;
padding: 6px 8px;
}
.workboard-widget-mini > header a {
color: var(--accent, #ff5c5c);
color: var(--accent);
font-size: 10px;
}
@@ -656,7 +656,7 @@ openclaw-workboard-mini-widget {
}
.workboard-widget-mini__counts span {
color: var(--muted, #8a919e);
color: var(--muted);
display: grid;
font-size: 8px;
gap: 2px;
@@ -664,7 +664,7 @@ openclaw-workboard-mini-widget {
}
.workboard-widget-mini__counts b {
color: var(--text, #d7dae0);
color: var(--text);
font-size: 13px;
}
@@ -700,7 +700,7 @@ openclaw-workboard-mini-widget {
.board-widget__app-loading,
.board-widget__stale {
align-content: center;
color: var(--muted, #8a919e);
color: var(--muted);
display: grid;
font-size: 11px;
gap: 8px;
@@ -711,7 +711,7 @@ openclaw-workboard-mini-widget {
}
.board-widget__stale strong {
color: var(--text, #d7dae0);
color: var(--text);
font-size: 13px;
}
@@ -804,7 +804,7 @@ openclaw-workboard-mini-widget {
bar's corner; the revealed bar carries the full capabilities chip, so the
dot fades out together with the chrome fade-in. */
.board-widget__grant-dot {
background: var(--ok, #4ec9a8);
background: var(--ok);
border-radius: 50%;
display: block;
height: 6px;
@@ -858,20 +858,20 @@ openclaw-workboard-mini-widget {
.board-widget__grant strong,
.board-widget__error strong {
color: var(--text, #d7dae0);
color: var(--text);
font-size: 13px;
}
.board-widget__grant > span,
.board-widget__error > span {
color: var(--muted, #8a919e);
color: var(--muted);
font-size: 11px;
line-height: 1.45;
max-width: 32ch;
}
.board-widget__grant-summary {
color: var(--muted, #8a919e);
color: var(--muted);
display: grid;
font-size: 11px;
gap: 4px;
@@ -895,16 +895,16 @@ openclaw-workboard-mini-widget {
}
.board-widget__grant-groups section > strong {
color: var(--text, #d7dae0);
color: var(--text);
font-size: 10px;
text-transform: uppercase;
}
.board-widget__capabilities {
background: color-mix(in srgb, var(--success, #4fbf78) 13%, transparent);
border: 1px solid color-mix(in srgb, var(--success, #4fbf78) 45%, transparent);
background: color-mix(in srgb, var(--ok) 13%, transparent);
border: 1px solid color-mix(in srgb, var(--ok) 45%, transparent);
border-radius: 999px;
color: var(--success, #4fbf78);
color: var(--ok);
display: inline-flex;
font-size: 9px;
font-weight: 650;
@@ -915,10 +915,10 @@ openclaw-workboard-mini-widget {
.board-widget__grant-mark {
align-items: center;
background: color-mix(in srgb, var(--warning, #e6ad55) 15%, transparent);
border: 1px solid color-mix(in srgb, var(--warning, #e6ad55) 55%, transparent);
background: color-mix(in srgb, var(--warn) 15%, transparent);
border: 1px solid color-mix(in srgb, var(--warn) 55%, transparent);
border-radius: 50%;
color: var(--warning, #e6ad55);
color: var(--warn);
display: flex;
font-size: 13px;
font-weight: 700;
@@ -943,7 +943,7 @@ openclaw-workboard-mini-widget {
}
.board-widget__error {
background: color-mix(in srgb, var(--danger, #ff6b6b) 7%, transparent);
background: color-mix(in srgb, var(--danger) 7%, transparent);
}
.board-widget__error--inline {
@@ -954,7 +954,7 @@ openclaw-workboard-mini-widget {
}
.board-widget__error details {
color: var(--muted, #8a919e);
color: var(--muted);
font-size: 10px;
max-width: 100%;
}
@@ -968,9 +968,9 @@ openclaw-workboard-mini-widget {
.board-empty {
align-items: center;
border: 1px dashed color-mix(in srgb, var(--muted, #8a919e) 38%, transparent);
border: 1px dashed color-mix(in srgb, var(--muted) 38%, transparent);
border-radius: 14px;
color: var(--muted, #8a919e);
color: var(--muted);
display: flex;
flex-direction: column;
gap: 7px;
@@ -981,7 +981,7 @@ openclaw-workboard-mini-widget {
}
.board-empty strong {
color: var(--text, #d7dae0);
color: var(--text);
font-size: 14px;
}
@@ -990,7 +990,7 @@ openclaw-workboard-mini-widget {
}
.board-empty__mark {
color: var(--accent, #ff5c5c);
color: var(--accent);
font-size: 24px;
}

View File

@@ -924,21 +924,21 @@ openclaw-chat-page {
}
.agent-chat__goal--active {
color: var(--success);
background: color-mix(in srgb, var(--success) 9%, var(--card));
border-color: color-mix(in srgb, var(--success) 28%, var(--border));
color: var(--ok);
background: color-mix(in srgb, var(--ok) 9%, var(--card));
border-color: color-mix(in srgb, var(--ok) 28%, var(--border));
}
.agent-chat__goal--blocked,
.agent-chat__goal--budget_limited,
.agent-chat__goal--usage_limited {
color: var(--warning);
background: color-mix(in srgb, var(--warning) 10%, var(--card));
border-color: color-mix(in srgb, var(--warning) 30%, var(--border));
color: var(--warn);
background: color-mix(in srgb, var(--warn) 10%, var(--card));
border-color: color-mix(in srgb, var(--warn) 30%, var(--border));
}
.agent-chat__goal--complete {
color: color-mix(in srgb, var(--success) 72%, var(--text));
color: color-mix(in srgb, var(--ok) 72%, var(--text));
}
/* Image attachments preview */

View File

@@ -79,7 +79,7 @@
padding: 0 3px;
border-radius: var(--radius-full);
background: var(--primary);
color: var(--primary-foreground, #fff);
color: var(--primary-foreground);
font-size: 9px;
font-weight: 650;
line-height: 14px;
@@ -343,7 +343,7 @@
}
.chat-workspace-rail__state--error {
color: var(--danger, #ef4444);
color: var(--danger);
}
.chat-workspace-rail__scroll {
@@ -469,7 +469,7 @@
}
.chat-workspace-rail__file-open:focus-visible {
outline: 2px solid color-mix(in srgb, var(--accent, #7dd3fc) 65%, transparent);
outline: 2px solid color-mix(in srgb, var(--accent) 65%, transparent);
outline-offset: -2px;
}
@@ -506,8 +506,8 @@
.chat-workspace-rail__file-badge {
padding: 2px 6px;
border-radius: var(--radius-full);
background: color-mix(in srgb, var(--danger, #ef4444) 12%, transparent);
color: var(--danger, #ef4444);
background: color-mix(in srgb, var(--danger) 12%, transparent);
color: var(--danger);
font-size: 12px; /* was 10px */
line-height: 1.2;
}
@@ -703,7 +703,7 @@
}
.chat-tasks-rail__state--error {
color: var(--danger, #ef4444);
color: var(--danger);
}
.chat-tasks-rail__scroll {
@@ -841,7 +841,7 @@
width: 7px;
height: 7px;
border-radius: var(--radius-full);
background: var(--warn, #f59e0b);
background: var(--warn);
animation: chat-tasks-pulse 1.6s ease-in-out infinite;
}
@@ -877,7 +877,7 @@
.chat-tasks-rail__task-stop:focus-visible {
border-color: color-mix(in srgb, var(--border-strong) 72%, transparent);
background: color-mix(in srgb, var(--bg-elevated) 82%, transparent);
color: var(--danger, #ef4444);
color: var(--danger);
}
.chat-tasks-rail__task-stop svg {
@@ -905,15 +905,15 @@
}
.chat-tasks-rail__task-status--ok {
color: var(--ok, #22c55e);
color: var(--ok);
}
.chat-tasks-rail__task-status--warn {
color: var(--warn, #f59e0b);
color: var(--warn);
}
.chat-tasks-rail__task-status--danger {
color: var(--danger, #ef4444);
color: var(--danger);
}
.chat-tasks-rail__task-status--muted {
@@ -978,7 +978,7 @@
height: 28px;
padding: 0;
place-items: center;
color: var(--danger, #ef4444);
color: var(--danger);
}
.chat-tasks-rail__detail-stop svg {
@@ -994,13 +994,13 @@
flex-direction: column;
gap: 3px;
padding: 10px;
border: 1px solid color-mix(in srgb, var(--warn, #f59e0b) 24%, var(--border));
border: 1px solid color-mix(in srgb, var(--warn) 24%, var(--border));
border-radius: var(--radius-md);
background: color-mix(in srgb, var(--warn, #f59e0b) 6%, transparent);
background: color-mix(in srgb, var(--warn) 6%, transparent);
}
.chat-tasks-rail__detail-activity span {
color: var(--warn, #f59e0b);
color: var(--warn);
font-family: var(--mono);
font-size: var(--control-ui-text-xs);
font-weight: 650;
@@ -1060,8 +1060,8 @@
}
.chat-tasks-rail__task-inspector-state--error {
border-color: color-mix(in srgb, var(--danger, #ef4444) 30%, var(--border));
color: var(--danger, #ef4444);
border-color: color-mix(in srgb, var(--danger) 30%, var(--border));
color: var(--danger);
}
/* Quiet by default so a column of rows is not a column of accent links;
@@ -1403,6 +1403,9 @@ openclaw-session-discussion {
background: color-mix(in srgb, var(--accent) 22%, transparent);
}
/* Code syntax palette (dark below, light overrides further down): deliberate
literal hexes tuned for code legibility, not theme tokens — the UI palette
has no per-token-kind roles and retinting per theme family is not wanted. */
.file-view .tok-comment {
color: var(--muted);
font-style: italic;
@@ -1503,8 +1506,8 @@ openclaw-session-discussion {
justify-content: space-between;
gap: 10px;
padding: 8px 10px;
border-bottom: 1px solid color-mix(in srgb, var(--warning) 40%, var(--border));
background: color-mix(in srgb, var(--warning) 10%, var(--panel));
border-bottom: 1px solid color-mix(in srgb, var(--warn) 40%, var(--border));
background: color-mix(in srgb, var(--warn) 10%, var(--panel));
color: var(--text);
font-size: 12px;
}
@@ -1828,19 +1831,19 @@ openclaw-session-discussion {
}
.session-diff__status--added {
background: var(--ok, #22c55e);
background: var(--ok);
}
.session-diff__status--deleted {
background: var(--destructive, #ef4444);
background: var(--destructive);
}
.session-diff__status--renamed {
background: var(--accent, #a855f7);
background: var(--accent);
}
.session-diff__status--modified {
background: var(--warning, #eab308);
background: var(--warn);
}
.session-diff__path {

View File

@@ -2272,7 +2272,7 @@ openclaw-chat-session-rail {
.code-block-copy.copied .code-block-copy__done {
display: inline;
color: var(--success, #22c55e);
color: var(--ok);
}
.json-collapse {
@@ -3146,8 +3146,8 @@ td.data-table-key-col {
.exec-approval-card--inline {
padding: 14px 16px;
border-color: color-mix(in srgb, var(--warning) 45%, var(--border));
background: color-mix(in srgb, var(--warning) 5%, var(--card));
border-color: color-mix(in srgb, var(--warn) 45%, var(--border));
background: color-mix(in srgb, var(--warn) 5%, var(--card));
animation: none;
}
@@ -3230,7 +3230,7 @@ td.data-table-key-col {
.exec-approval-warning {
margin-top: 10px;
font-size: 13px;
color: var(--warning, #b7791f);
color: var(--warn);
}
.exec-approval-actions {
@@ -3307,7 +3307,7 @@ td.data-table-key-col {
}
.exec-approval-list__expiry {
color: var(--warning);
color: var(--warn);
font: 11px/1.2 var(--mono);
font-variant-numeric: tabular-nums;
}
@@ -5526,7 +5526,7 @@ td.data-table-key-col {
.session-approval-badge {
display: inline-flex;
align-items: center;
color: var(--warning);
color: var(--warn);
}
.session-approval-badge svg {

View File

@@ -1000,12 +1000,12 @@ html.openclaw-native-web-chrome .shell-chrome-controls {
}
.sidebar-attention__item--warning {
border-color: var(--warning-subtle, rgba(234, 179, 8, 0.25));
border-color: var(--warn-subtle);
background: rgba(234, 179, 8, 0.06);
}
.sidebar-attention__item--error {
border-color: var(--danger-subtle, rgba(239, 68, 68, 0.25));
border-color: var(--danger-subtle);
background: rgba(239, 68, 68, 0.06);
}
@@ -1346,7 +1346,7 @@ html.openclaw-native-macos
display: inline-flex;
align-items: center;
justify-content: center;
color: var(--warning);
color: var(--warn);
}
.sidebar-session-group-count--error svg {
@@ -1612,7 +1612,7 @@ html.openclaw-native-macos
display: inline-flex;
align-items: center;
justify-content: center;
color: var(--warning);
color: var(--warn);
}
.sidebar-session-catalog-host__count--error svg {
@@ -2948,8 +2948,8 @@ wa-dropdown.sidebar-session-sort-menu::part(menu) {
justify-content: center;
padding: 0 5px;
border-radius: var(--radius-full);
background: color-mix(in srgb, var(--warning) 18%, transparent);
color: var(--warning);
background: color-mix(in srgb, var(--warn) 18%, transparent);
color: var(--warn);
font-size: 10px;
font-weight: 700;
font-variant-numeric: tabular-nums;