diff --git a/packages/dashboard/app/components/WorkflowFieldsPanel.css b/packages/dashboard/app/components/WorkflowFieldsPanel.css
index d49352b1ed..4c0909289e 100644
--- a/packages/dashboard/app/components/WorkflowFieldsPanel.css
+++ b/packages/dashboard/app/components/WorkflowFieldsPanel.css
@@ -124,6 +124,14 @@
color: var(--text-muted);
}
+/*
+FNXC:WorkflowEditorTheme 2026-06-19-05:22:
+Field-list checkboxes share the editor sidebar surface and must stay theme-accented across editable and built-in read-only workflow states.
+*/
+.wf-field--checkbox input[type="checkbox"] {
+ accent-color: var(--todo);
+}
+
.wf-field-required {
flex: 0 0 auto;
white-space: nowrap;
diff --git a/packages/dashboard/app/components/WorkflowNodeEditor.css b/packages/dashboard/app/components/WorkflowNodeEditor.css
index c2ba523966..e94ada1125 100644
--- a/packages/dashboard/app/components/WorkflowNodeEditor.css
+++ b/packages/dashboard/app/components/WorkflowNodeEditor.css
@@ -568,6 +568,53 @@
position: relative;
}
+/*
+FNXC:WorkflowEditorTheme 2026-06-19-05:22:
+React Flow ships white default controls and mini-map chrome, but the workflow editor must inherit Fusion theme tokens in both dark and light modes. Scope overrides to the canvas so other React Flow consumers keep their local contracts.
+*/
+.wf-editor-canvas .react-flow__controls {
+ background: var(--surface);
+ border: var(--btn-border-width) solid var(--border);
+ border-radius: var(--radius-sm);
+ box-shadow: var(--shadow-sm);
+ color: var(--text);
+ overflow: hidden;
+}
+
+.wf-editor-canvas .react-flow__controls-button {
+ background: var(--surface);
+ border: 0;
+ border-bottom: var(--btn-border-width) solid var(--border);
+ color: var(--text);
+ fill: currentColor;
+}
+
+.wf-editor-canvas .react-flow__controls-button:hover {
+ background: var(--surface-hover);
+ color: var(--text);
+}
+
+.wf-editor-canvas .react-flow__controls-button svg {
+ fill: currentColor;
+ stroke: currentColor;
+}
+
+.wf-editor-canvas .react-flow__minimap {
+ background: var(--surface);
+ border: var(--btn-border-width) solid var(--border);
+ border-radius: var(--radius-sm);
+ box-shadow: var(--shadow-sm);
+}
+
+.wf-editor-canvas .react-flow__minimap-node {
+ fill: var(--bg-secondary);
+ stroke: var(--border);
+}
+
+.wf-editor-canvas .react-flow__minimap-mask {
+ fill: color-mix(in srgb, var(--surface) 70%, transparent);
+}
+
.wf-mobile-shell {
display: none;
}
@@ -1483,6 +1530,14 @@
color: var(--text-muted);
}
+/*
+FNXC:WorkflowEditorTheme 2026-06-19-05:22:
+Column trait toggles are left-sidebar workflow controls; keep their enabled and disabled checkbox chrome on the workflow accent token instead of React/browser defaults.
+*/
+.wf-column-trait input[type="checkbox"] {
+ accent-color: var(--todo);
+}
+
.wf-column-traits-label,
.wf-column-agent-label {
font-size: 0.65rem;
diff --git a/packages/dashboard/app/components/WorkflowSettingsPanel.css b/packages/dashboard/app/components/WorkflowSettingsPanel.css
index 13663ecfa9..65f87cbed9 100644
--- a/packages/dashboard/app/components/WorkflowSettingsPanel.css
+++ b/packages/dashboard/app/components/WorkflowSettingsPanel.css
@@ -193,6 +193,14 @@
color: var(--text-muted);
}
+/*
+FNXC:WorkflowEditorTheme 2026-06-19-05:22:
+Boolean workflow settings live in the editor's left sidebar, so their checkboxes must use the same accent token as inspector checkboxes instead of browser-default white controls.
+*/
+.wf-setting--checkbox input[type="checkbox"] {
+ accent-color: var(--todo);
+}
+
.wf-setting-options {
display: flex;
flex-direction: column;
diff --git a/packages/dashboard/app/components/__tests__/WorkflowNodeEditor.css.test.ts b/packages/dashboard/app/components/__tests__/WorkflowNodeEditor.css.test.ts
index 9a9cb36b1f..2e761da5ef 100644
--- a/packages/dashboard/app/components/__tests__/WorkflowNodeEditor.css.test.ts
+++ b/packages/dashboard/app/components/__tests__/WorkflowNodeEditor.css.test.ts
@@ -37,6 +37,70 @@ function findRule(blocks: string[], selector: RegExp): string {
return rule;
}
+function expectNoHardcodedWhiteBackground(rule: string): void {
+ expect(rule).not.toMatch(/background(?:-color)?\s*:[^;]*(?:#fff|#ffffff|\bwhite\b)/i);
+}
+
+describe("WorkflowNodeEditor themed React Flow CSS contract", () => {
+ it("FN-6701 themes zoom controls, mini-map, and sidebar checkboxes with tokens", () => {
+ const baseCss = loadAllAppCssBaseOnly();
+
+ // Surface Enumeration: WorkflowNodeEditor.tsx is the only React Flow / mount; WorkflowResultsTab and MobileWorkflowGraphView do not mount those affordances. Left-sidebar checkbox surfaces are WorkflowSettingsPanel, WorkflowFieldsPanel, and WorkflowColumnPanel trait toggles; inspector .wf-field--checkbox stays covered by WorkflowNodeEditor.css.
+ const controlsRule = findRule([baseCss], /\.wf-editor-canvas \.react-flow__controls\s*\{[^}]*\}/);
+ expect(controlsRule).toMatch(/background\s*:\s*var\(--surface\)\s*;/);
+ expect(controlsRule).toMatch(/border\s*:\s*var\(--btn-border-width\) solid var\(--border\)\s*;/);
+ expect(controlsRule).toMatch(/color\s*:\s*var\(--text\)\s*;/);
+ expectNoHardcodedWhiteBackground(controlsRule);
+
+ const controlsButtonRule = findRule([baseCss], /\.wf-editor-canvas \.react-flow__controls-button\s*\{[^}]*\}/);
+ expect(controlsButtonRule).toMatch(/background\s*:\s*var\(--surface\)\s*;/);
+ expect(controlsButtonRule).toMatch(/border-bottom\s*:\s*var\(--btn-border-width\) solid var\(--border\)\s*;/);
+ expect(controlsButtonRule).toMatch(/color\s*:\s*var\(--text\)\s*;/);
+ expect(controlsButtonRule).toMatch(/fill\s*:\s*currentColor\s*;/);
+ expectNoHardcodedWhiteBackground(controlsButtonRule);
+
+ const controlsButtonHoverRule = findRule(
+ [baseCss],
+ /\.wf-editor-canvas \.react-flow__controls-button:hover\s*\{[^}]*\}/,
+ );
+ expect(controlsButtonHoverRule).toMatch(/background\s*:\s*var\(--surface-hover\)\s*;/);
+ expect(controlsButtonHoverRule).toMatch(/color\s*:\s*var\(--text\)\s*;/);
+ expectNoHardcodedWhiteBackground(controlsButtonHoverRule);
+
+ const controlsSvgRule = findRule([baseCss], /\.wf-editor-canvas \.react-flow__controls-button svg\s*\{[^}]*\}/);
+ expect(controlsSvgRule).toMatch(/fill\s*:\s*currentColor\s*;/);
+ expect(controlsSvgRule).toMatch(/stroke\s*:\s*currentColor\s*;/);
+
+ const minimapRule = findRule([baseCss], /\.wf-editor-canvas \.react-flow__minimap\s*\{[^}]*\}/);
+ expect(minimapRule).toMatch(/background\s*:\s*var\(--surface\)\s*;/);
+ expect(minimapRule).toMatch(/border\s*:\s*var\(--btn-border-width\) solid var\(--border\)\s*;/);
+ expectNoHardcodedWhiteBackground(minimapRule);
+
+ const minimapNodeRule = findRule([baseCss], /\.wf-editor-canvas \.react-flow__minimap-node\s*\{[^}]*\}/);
+ expect(minimapNodeRule).toMatch(/fill\s*:\s*var\(--bg-secondary\)\s*;/);
+ expect(minimapNodeRule).toMatch(/stroke\s*:\s*var\(--border\)\s*;/);
+
+ const minimapMaskRule = findRule([baseCss], /\.wf-editor-canvas \.react-flow__minimap-mask\s*\{[^}]*\}/);
+ expect(minimapMaskRule).toMatch(/fill\s*:\s*color-mix\(in srgb, var\(--surface\) 70%, transparent\)\s*;/);
+
+ for (const selector of [
+ /\.wf-setting--checkbox input\[type="checkbox"\]\s*\{[^}]*\}/,
+ /\.wf-field--checkbox input\[type="checkbox"\]\s*\{[^}]*\}/,
+ /\.wf-column-trait input\[type="checkbox"\]\s*\{[^}]*\}/,
+ ]) {
+ const checkboxRule = findRule([baseCss], selector);
+ expect(checkboxRule).toMatch(/accent-color\s*:\s*var\(--todo\)\s*;/);
+ expectNoHardcodedWhiteBackground(checkboxRule);
+ }
+
+ const lightThemeOverrides = [...baseCss.matchAll(/\[data-theme="light"\][^{]*\{[^}]*\}/g)].map((match) => match[0]);
+ for (const overrideRule of lightThemeOverrides.filter((rule) => /react-flow__|wf-(?:setting|field|column-trait)/.test(rule))) {
+ expect(overrideRule).toMatch(/var\(--/);
+ expectNoHardcodedWhiteBackground(overrideRule);
+ }
+ });
+});
+
describe("WorkflowNodeEditor edge visibility CSS contract", () => {
it("keeps swimlane bands translucent so built-in workflow edges remain visible", () => {
const editorCss = readComponentCss("WorkflowNodeEditor.css");