+ {/* Pins */}
+ {pins.length > 0 && (
+
+ {pins.map((p, i) => (
+
+
+ {p.kind}
+
+ {p.label}
+
+
+ ))}
+
+
+ )}
+
+ {/* Field row */}
+
+
+ {/* Model + capabilities row + meta */}
+
+
+
+ Memory-first · 0 paid calls
+
+
+
+ {/* Suggested chips — kit pattern from Composer.jsx */}
+
+ {DEMOS.map((d) => (
+
+ ))}
+
+
+ {error && (
+
+ {error}
+
+ )}
+
+ );
+}
diff --git a/src/features/financialOperator/components/WorkspaceModePane.tsx b/src/features/financialOperator/components/WorkspaceModePane.tsx
new file mode 100644
index 000000000..f683e48b5
--- /dev/null
+++ b/src/features/financialOperator/components/WorkspaceModePane.tsx
@@ -0,0 +1,288 @@
+/**
+ * WorkspaceModePane — operator-console takeover that follows the kit's
+ * canonical chat-surface layout (per ui_kits/nodebench-web/ChatThread.jsx):
+ *
+ * ┌─ chat header (sticky top, entity icon + title + meta + actions) ─┐
+ * │ │
+ * ├─ scrollable thread area ─────────────────────────────────────────┤
+ * │ [demo picker if no run, OR live operator-console timeline] │
+ * │ │
+ * ├─ composer (pinned bottom) ───────────────────────────────────────┤
+ * │ pins · field with attach + textarea + send · model badge · chips │
+ * └──────────────────────────────────────────────────────────────────┘
+ *
+ * This is built ON TOP of the existing chat surface, not next to it: we
+ * reuse the kit's chat-shell shape so when this pane mounts the user
+ * doesn't perceive a regime change. The model badge + capabilities live
+ * in the composer (where the kit puts them), not in the header.
+ *
+ * URL params drive everything (`?ws=1`, `?finRun=