@goplasmatic/datalogic-ui 5.0.0 → 5.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (114) hide show
  1. package/README.md +3 -3
  2. package/dist/components/logic-editor/AutoFitView.d.ts +7 -0
  3. package/dist/components/logic-editor/AutoFitView.d.ts.map +1 -1
  4. package/dist/components/logic-editor/DataLogicEditor.d.ts +1 -1
  5. package/dist/components/logic-editor/DataLogicEditor.d.ts.map +1 -1
  6. package/dist/components/logic-editor/EditorToolbar.d.ts +4 -1
  7. package/dist/components/logic-editor/EditorToolbar.d.ts.map +1 -1
  8. package/dist/components/logic-editor/UndoRedoToolbar.d.ts +1 -1
  9. package/dist/components/logic-editor/UndoRedoToolbar.d.ts.map +1 -1
  10. package/dist/components/logic-editor/constants/index.d.ts +1 -1
  11. package/dist/components/logic-editor/constants/index.d.ts.map +1 -1
  12. package/dist/components/logic-editor/constants/layout.d.ts +13 -4
  13. package/dist/components/logic-editor/constants/layout.d.ts.map +1 -1
  14. package/dist/components/logic-editor/context/ConnectedHandlesContext.d.ts +1 -1
  15. package/dist/components/logic-editor/context/ConnectedHandlesContext.d.ts.map +1 -1
  16. package/dist/components/logic-editor/context/DirectionContextDef.d.ts +11 -0
  17. package/dist/components/logic-editor/context/DirectionContextDef.d.ts.map +1 -0
  18. package/dist/components/logic-editor/context/debugger/DebuggerProvider.d.ts +1 -1
  19. package/dist/components/logic-editor/context/debugger/DebuggerProvider.d.ts.map +1 -1
  20. package/dist/components/logic-editor/context/editor/EditorContext.d.ts +1 -1
  21. package/dist/components/logic-editor/context/editor/EditorContext.d.ts.map +1 -1
  22. package/dist/components/logic-editor/context/index.d.ts +2 -0
  23. package/dist/components/logic-editor/context/index.d.ts.map +1 -1
  24. package/dist/components/logic-editor/context/useDirection.d.ts +6 -0
  25. package/dist/components/logic-editor/context/useDirection.d.ts.map +1 -0
  26. package/dist/components/logic-editor/context-menu/CanvasContextMenu.d.ts +1 -1
  27. package/dist/components/logic-editor/context-menu/CanvasContextMenu.d.ts.map +1 -1
  28. package/dist/components/logic-editor/context-menu/ContextMenu.d.ts +1 -1
  29. package/dist/components/logic-editor/context-menu/ContextMenu.d.ts.map +1 -1
  30. package/dist/components/logic-editor/debugger-controls/DebuggerControls.d.ts +2 -2
  31. package/dist/components/logic-editor/debugger-controls/DebuggerControls.d.ts.map +1 -1
  32. package/dist/components/logic-editor/edges/EdgeOperatorPicker.d.ts +1 -1
  33. package/dist/components/logic-editor/edges/EdgeOperatorPicker.d.ts.map +1 -1
  34. package/dist/components/logic-editor/edges/EditableEdge.d.ts +1 -1
  35. package/dist/components/logic-editor/edges/EditableEdge.d.ts.map +1 -1
  36. package/dist/components/logic-editor/edges/index.d.ts +1 -1
  37. package/dist/components/logic-editor/hooks/useLogicEditor.d.ts +4 -1
  38. package/dist/components/logic-editor/hooks/useLogicEditor.d.ts.map +1 -1
  39. package/dist/components/logic-editor/nodes/CellHandles.d.ts +1 -1
  40. package/dist/components/logic-editor/nodes/CellHandles.d.ts.map +1 -1
  41. package/dist/components/logic-editor/nodes/CellRow.d.ts +1 -1
  42. package/dist/components/logic-editor/nodes/CellRow.d.ts.map +1 -1
  43. package/dist/components/logic-editor/nodes/DebugInfoBubble.d.ts +1 -1
  44. package/dist/components/logic-editor/nodes/DebugInfoBubble.d.ts.map +1 -1
  45. package/dist/components/logic-editor/nodes/LiteralNode.d.ts +1 -1
  46. package/dist/components/logic-editor/nodes/LiteralNode.d.ts.map +1 -1
  47. package/dist/components/logic-editor/nodes/StructureNode.d.ts +1 -1
  48. package/dist/components/logic-editor/nodes/StructureNode.d.ts.map +1 -1
  49. package/dist/components/logic-editor/nodes/UnifiedOperatorNode.d.ts +1 -1
  50. package/dist/components/logic-editor/nodes/UnifiedOperatorNode.d.ts.map +1 -1
  51. package/dist/components/logic-editor/nodes/shared/CollapseToggleButton.d.ts +1 -1
  52. package/dist/components/logic-editor/nodes/shared/CollapseToggleButton.d.ts.map +1 -1
  53. package/dist/components/logic-editor/nodes/shared/NodeDebugBubble.d.ts +1 -1
  54. package/dist/components/logic-editor/nodes/shared/NodeDebugBubble.d.ts.map +1 -1
  55. package/dist/components/logic-editor/nodes/shared/NodeInputHandles.d.ts +6 -3
  56. package/dist/components/logic-editor/nodes/shared/NodeInputHandles.d.ts.map +1 -1
  57. package/dist/components/logic-editor/panel-inputs/BooleanInput.d.ts +1 -1
  58. package/dist/components/logic-editor/panel-inputs/BooleanInput.d.ts.map +1 -1
  59. package/dist/components/logic-editor/panel-inputs/ExpressionInput.d.ts +1 -1
  60. package/dist/components/logic-editor/panel-inputs/ExpressionInput.d.ts.map +1 -1
  61. package/dist/components/logic-editor/panel-inputs/JsonInput.d.ts +1 -1
  62. package/dist/components/logic-editor/panel-inputs/JsonInput.d.ts.map +1 -1
  63. package/dist/components/logic-editor/panel-inputs/NumberInput.d.ts +1 -1
  64. package/dist/components/logic-editor/panel-inputs/NumberInput.d.ts.map +1 -1
  65. package/dist/components/logic-editor/panel-inputs/PathArrayInput.d.ts +1 -1
  66. package/dist/components/logic-editor/panel-inputs/PathArrayInput.d.ts.map +1 -1
  67. package/dist/components/logic-editor/panel-inputs/PathInput.d.ts +1 -1
  68. package/dist/components/logic-editor/panel-inputs/PathInput.d.ts.map +1 -1
  69. package/dist/components/logic-editor/panel-inputs/SelectInput.d.ts +1 -1
  70. package/dist/components/logic-editor/panel-inputs/SelectInput.d.ts.map +1 -1
  71. package/dist/components/logic-editor/panel-inputs/TextAreaInput.d.ts +1 -1
  72. package/dist/components/logic-editor/panel-inputs/TextAreaInput.d.ts.map +1 -1
  73. package/dist/components/logic-editor/panel-inputs/TextInput.d.ts +1 -1
  74. package/dist/components/logic-editor/panel-inputs/TextInput.d.ts.map +1 -1
  75. package/dist/components/logic-editor/properties-panel/ArgumentItem.d.ts +1 -1
  76. package/dist/components/logic-editor/properties-panel/ArgumentItem.d.ts.map +1 -1
  77. package/dist/components/logic-editor/properties-panel/ArgumentsSection.d.ts +1 -1
  78. package/dist/components/logic-editor/properties-panel/ArgumentsSection.d.ts.map +1 -1
  79. package/dist/components/logic-editor/properties-panel/HelpSection.d.ts +1 -1
  80. package/dist/components/logic-editor/properties-panel/HelpSection.d.ts.map +1 -1
  81. package/dist/components/logic-editor/properties-panel/PropertiesPanel.d.ts +1 -1
  82. package/dist/components/logic-editor/properties-panel/PropertiesPanel.d.ts.map +1 -1
  83. package/dist/components/logic-editor/utils/ExpressionSyntax.d.ts +1 -1
  84. package/dist/components/logic-editor/utils/ExpressionSyntax.d.ts.map +1 -1
  85. package/dist/components/logic-editor/utils/converters/if-else-converter.d.ts +6 -0
  86. package/dist/components/logic-editor/utils/converters/if-else-converter.d.ts.map +1 -1
  87. package/dist/components/logic-editor/utils/converters/operator-converter.d.ts.map +1 -1
  88. package/dist/components/logic-editor/utils/edge-builder.d.ts +5 -4
  89. package/dist/components/logic-editor/utils/edge-builder.d.ts.map +1 -1
  90. package/dist/components/logic-editor/utils/formatting/arg-summary.d.ts +7 -0
  91. package/dist/components/logic-editor/utils/formatting/arg-summary.d.ts.map +1 -1
  92. package/dist/components/logic-editor/utils/formatting/index.d.ts +1 -1
  93. package/dist/components/logic-editor/utils/formatting/index.d.ts.map +1 -1
  94. package/dist/components/logic-editor/utils/inline-vars.d.ts +15 -0
  95. package/dist/components/logic-editor/utils/inline-vars.d.ts.map +1 -0
  96. package/dist/components/logic-editor/utils/layout.d.ts +2 -1
  97. package/dist/components/logic-editor/utils/layout.d.ts.map +1 -1
  98. package/dist/components/logic-editor/utils/node-factory.d.ts.map +1 -1
  99. package/dist/components/logic-editor/utils/nodeShape.d.ts +23 -0
  100. package/dist/components/logic-editor/utils/nodeShape.d.ts.map +1 -0
  101. package/dist/components/logic-editor/utils/signal.d.ts +10 -0
  102. package/dist/components/logic-editor/utils/signal.d.ts.map +1 -0
  103. package/dist/components/logic-editor/utils/trace/node-creators/if-else.d.ts +4 -2
  104. package/dist/components/logic-editor/utils/trace/node-creators/if-else.d.ts.map +1 -1
  105. package/dist/components/logic-editor/utils/trace/node-creators/variable.d.ts.map +1 -1
  106. package/dist/components/logic-editor/utils/trace/node-creators/vertical-cell.d.ts.map +1 -1
  107. package/dist/datalogic_wasm-BwcPSrZk.js +1145 -0
  108. package/dist/datalogic_wasm-dTo8Zxxv.cjs +1148 -0
  109. package/dist/index.cjs +2521 -2028
  110. package/dist/index.js +2522 -2029
  111. package/dist/styles.css +1118 -378
  112. package/package.json +31 -25
  113. package/dist/datalogic_wasm-CF1jcNAu.js +0 -634
  114. package/dist/datalogic_wasm-Dj9TEPTG.cjs +0 -637
package/dist/styles.css CHANGED
@@ -1,113 +1,175 @@
1
1
  /*
2
- * DataLogic UI - Scoped Theme Variables
2
+ * DataLogic UI "Signal Board" theme tokens
3
+ * ============================================================
4
+ * Every design decision in this component is expressed as a CSS custom
5
+ * property, all scoped to `.logic-editor` so nothing leaks into the host app.
3
6
  *
4
- * All variables are scoped to .logic-editor to avoid leaking into consumer apps.
5
- * The library component applies this class to its root element.
7
+ * OVERRIDING FROM A CONSUMER APP
8
+ * ------------------------------
9
+ * Import the stylesheet once, then redefine any token with equal-or-greater
10
+ * specificity. Two supported patterns:
11
+ *
12
+ * 1. Re-tune the whole component:
13
+ * .logic-editor { --sig-number: #0ea5e9; --board: #f7f7f8; }
14
+ * .logic-editor[data-theme="dark"] { --board: #0b0b0f; }
15
+ *
16
+ * 2. Scope an override to one instance (pass className to DataLogicEditor):
17
+ * .my-editor.logic-editor { --accent: #db2777; }
18
+ *
19
+ * The SIGNAL palette (`--sig-*`) is the primary colour axis: a node is
20
+ * coloured by the *type of value it produces*. The neutral board tokens
21
+ * (`--board`, `--ink`, `--hairline`) set the calm substrate everything sits on.
22
+ * Legacy aliases (`--bg-primary`, `--node-bg`, `--syntax-*`, `--debug-*`) are
23
+ * kept and mapped onto the new system so existing consumer overrides keep working.
6
24
  */
7
25
 
8
26
  .logic-editor {
9
- /* Light theme (default) — zinc-leaning neutrals */
10
- --bg-primary: #fafafa;
11
- --bg-secondary: #ffffff;
12
- --bg-tertiary: #f6f6f7;
13
- --bg-hover: #f0f0f1;
14
- --bg-active: #e8e8ea;
15
-
16
- --text-primary: #18181b;
17
- --text-secondary: #3f3f46;
18
- --text-tertiary: #71717a;
19
- --text-muted: #a1a1aa;
20
- --text-placeholder: #c4c4c7;
21
-
22
- --border-primary: rgba(0, 0, 0, 0.10);
23
- --border-secondary: rgba(0, 0, 0, 0.06);
24
- --border-light: rgba(0, 0, 0, 0.04);
25
-
26
- --accent-blue: #6366f1;
27
- --accent-blue-light: #e0e7ff;
28
- --accent-blue-hover: #4f46e5;
29
-
30
- --accent-amber: #f59e0b;
31
- --accent-amber-light: #fef3c7;
32
-
33
- /* Status colors */
34
- --success-bg: #ecfdf5;
35
- --success-text: #047857;
36
- --success-border: #a7f3d0;
37
-
38
- --error-bg: #fef2f2;
39
- --error-bg-light: #fff7f7;
40
- --error-bg-lighter: #fffafa;
41
- --error-text: #dc2626;
42
- --error-border: #fecaca;
43
-
44
- --warning-bg: #fffbeb;
45
- --warning-text: #b45309;
46
- --warning-border: #fde68a;
47
-
48
- /* Syntax highlighting */
49
- --syntax-key: #0550ae;
50
- --syntax-string: #0a3069;
51
- --syntax-number: #0550ae;
52
- --syntax-boolean: #cf222e;
53
- --syntax-null: #6e7781;
54
- --syntax-bracket: #24292f;
55
- --syntax-punctuation: #24292f;
56
-
57
- /* Node colors */
58
- --node-bg: #ffffff;
59
- --node-shadow: 0 1px 3px rgba(0, 0, 0, 0.06), 0 1px 2px rgba(0, 0, 0, 0.04);
60
- --node-shadow-hover: 0 4px 12px rgba(0, 0, 0, 0.08), 0 2px 4px rgba(0, 0, 0, 0.05);
61
-
62
- /* Code background */
63
- --code-bg: #f8f9fa;
64
-
65
- /* Debug popover colors */
66
- --debug-popover-bg: #ffffff;
67
- --debug-popover-text: #1f2937;
68
- --debug-popover-error-bg: #fef2f2;
69
- --debug-popover-shadow: rgba(0, 0, 0, 0.15);
70
- --debug-popover-value-bg: rgba(0, 0, 0, 0.05);
71
- --debug-iteration-color: #b45309;
72
- --debug-label-color: #6b7280;
73
- --debug-border-color: rgba(0, 0, 0, 0.1);
74
-
75
- /* Debug value type colors */
76
- --debug-value-true: #059669;
77
- --debug-value-false: #dc2626;
78
- --debug-value-number: #2563eb;
79
- --debug-value-string: #059669;
80
- --debug-value-array: #7c3aed;
81
- --debug-value-null: #6b7280;
82
-
83
- /* Radius scale */
84
- --radius-sm: 6px;
27
+ /* ---- Fonts ------------------------------------------------------ */
28
+ --font-ui: 'Space Grotesk', ui-sans-serif, -apple-system, BlinkMacSystemFont,
29
+ 'Segoe UI', Roboto, sans-serif;
30
+ --font-mono: 'JetBrains Mono', ui-monospace, 'SF Mono', 'Cascadia Code',
31
+ 'Consolas', monospace;
32
+
33
+ /* ---- Substrate — cool paper (light default) -------------------- */
34
+ --board: #eef1f5;
35
+ --board-grid: rgba(20, 40, 70, 0.05);
36
+ --surface: #ffffff;
37
+ --surface-2: #f6f8fb;
38
+ --chip: #ffffff;
39
+ --hairline: #d6dde6;
40
+ --hairline-2: #e6ebf1;
41
+
42
+ --ink: #0e1826;
43
+ --ink-2: #33475e;
44
+ --muted: #5b6a7d;
45
+ --faint: #9aa9ba; /* NON-TEXT only: idle wires, dot-grid, dashed slots */
46
+
47
+ /* ---- Structural accent — used ONLY for selection/root/focus ----- */
48
+ --accent: #4b56d6;
49
+ --accent-soft: #e7e9fb;
50
+ --accent-hover: #3a44c0;
51
+
52
+ /* ---- SIGNAL palette — colour = the value that flows OUT --------- */
53
+ --sig-bool-true: #1a7f37;
54
+ --sig-bool-false: #cf222e;
55
+ --sig-bool-rest: #57708a;
56
+ --sig-number: #0959c0;
57
+ --sig-string: #8a5a00;
58
+ --sig-collection: #8250df;
59
+ --sig-data: #1b7c83;
60
+ --sig-temporal: #bf3989;
61
+ --sig-null: #6e7781;
62
+
63
+ --sig-bool-true-bg: rgba(26, 127, 55, 0.10);
64
+ --sig-bool-false-bg: rgba(207, 34, 46, 0.10);
65
+ --sig-number-bg: rgba(9, 105, 218, 0.10);
66
+ --sig-string-bg: rgba(154, 103, 0, 0.12);
67
+ --sig-collection-bg: rgba(130, 80, 223, 0.10);
68
+ --sig-data-bg: rgba(27, 124, 131, 0.10);
69
+ --sig-temporal-bg: rgba(191, 57, 137, 0.10);
70
+ --sig-null-bg: rgba(110, 119, 129, 0.10);
71
+
72
+ /* ---- Radius & spacing scales ----------------------------------- */
73
+ --radius-sm: 7px;
85
74
  --radius-md: 10px;
86
75
  --radius-lg: 14px;
87
76
 
88
- /* Shadow elevation scale (layered: ambient + key) */
89
- --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.04);
90
- --shadow-md: 0 2px 4px rgba(0, 0, 0, 0.04), 0 4px 12px rgba(0, 0, 0, 0.06);
91
- --shadow-lg: 0 4px 8px rgba(0, 0, 0, 0.06), 0 12px 32px rgba(0, 0, 0, 0.10);
77
+ --sp-1: 4px; --sp-2: 8px; --sp-3: 12px; --sp-4: 16px;
78
+ --sp-5: 20px; --sp-6: 24px; --sp-8: 32px;
79
+
80
+ /* ---- Elevation ------------------------------------------------- */
81
+ --shadow-sm: 0 1px 2px rgba(16, 30, 54, 0.05);
82
+ --shadow-md: 0 1px 2px rgba(16, 30, 54, 0.06), 0 2px 6px rgba(16, 30, 54, 0.06);
83
+ --shadow-lg: 0 8px 30px rgba(16, 30, 54, 0.14), 0 2px 8px rgba(16, 30, 54, 0.08);
92
84
 
93
- /* Motion */
85
+ /* ---- Motion ---------------------------------------------------- */
94
86
  --motion-fast: 120ms;
95
87
  --motion-base: 180ms;
96
88
  --motion-slow: 260ms;
97
89
  --ease-out: cubic-bezier(0.4, 0, 0.2, 1);
98
90
 
99
- /* Focus ring */
100
- --focus-ring: 0 0 0 2px var(--accent-blue);
101
-
102
- font-family: -apple-system, BlinkMacSystemFont, 'Inter', 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
91
+ /* ============================================================
92
+ LEGACY ALIASES mapped onto the Signal Board system so existing
93
+ consumer overrides (e.g. dataflow-rs redefines --node-bg / --node-shadow)
94
+ keep working. Prefer the tokens above for new overrides.
95
+ ============================================================ */
96
+ --bg-primary: var(--board);
97
+ --bg-secondary: var(--surface);
98
+ --bg-tertiary: var(--surface-2);
99
+ --bg-hover: var(--surface-2);
100
+ --bg-active: var(--hairline-2);
101
+
102
+ --text-primary: var(--ink);
103
+ --text-secondary: var(--ink-2);
104
+ --text-tertiary: var(--muted);
105
+ --text-muted: var(--muted);
106
+ --text-placeholder: var(--faint);
107
+
108
+ --border-primary: var(--hairline);
109
+ --border-secondary: var(--hairline-2);
110
+ --border-light: var(--hairline-2);
111
+
112
+ --accent-blue: var(--accent);
113
+ --accent-blue-light: var(--accent-soft);
114
+ --accent-blue-hover: var(--accent-hover);
115
+
116
+ --accent-amber: var(--sig-string);
117
+ --accent-amber-light: var(--sig-string-bg);
118
+
119
+ --success-bg: var(--sig-bool-true-bg);
120
+ --success-text: var(--sig-bool-true);
121
+ --success-border: color-mix(in srgb, var(--sig-bool-true) 30%, transparent);
122
+
123
+ --error-bg: var(--sig-bool-false-bg);
124
+ --error-bg-light: color-mix(in srgb, var(--sig-bool-false) 6%, var(--surface));
125
+ --error-bg-lighter: color-mix(in srgb, var(--sig-bool-false) 3%, var(--surface));
126
+ --error-text: var(--sig-bool-false);
127
+ --error-border: color-mix(in srgb, var(--sig-bool-false) 30%, transparent);
128
+
129
+ --warning-bg: var(--sig-string-bg);
130
+ --warning-text: var(--sig-string);
131
+ --warning-border: color-mix(in srgb, var(--sig-string) 30%, transparent);
132
+
133
+ --syntax-key: var(--sig-data);
134
+ --syntax-string: var(--sig-string);
135
+ --syntax-number: var(--sig-number);
136
+ --syntax-boolean: var(--sig-bool-false);
137
+ --syntax-null: var(--sig-null);
138
+ --syntax-bracket: var(--ink-2);
139
+ --syntax-punctuation: var(--muted);
140
+
141
+ --node-bg: var(--chip);
142
+ --node-shadow: var(--shadow-sm);
143
+ --node-shadow-hover: var(--shadow-md);
144
+
145
+ --code-bg: var(--surface-2);
146
+
147
+ --debug-popover-bg: var(--chip);
148
+ --debug-popover-text: var(--ink);
149
+ --debug-popover-error-bg: var(--sig-bool-false-bg);
150
+ --debug-popover-shadow: rgba(16, 30, 54, 0.15);
151
+ --debug-popover-value-bg: var(--surface-2);
152
+ --debug-iteration-color: var(--sig-collection);
153
+ --debug-label-color: var(--muted);
154
+ --debug-border-color: var(--hairline-2);
155
+
156
+ --debug-value-true: var(--sig-bool-true);
157
+ --debug-value-false: var(--sig-bool-false);
158
+ --debug-value-number: var(--sig-number);
159
+ --debug-value-string: var(--sig-string);
160
+ --debug-value-array: var(--sig-collection);
161
+ --debug-value-null: var(--sig-null);
162
+
163
+ --focus-ring: 0 0 0 2px var(--accent);
164
+
165
+ font-family: var(--font-ui);
103
166
  line-height: 1.5;
104
167
  font-weight: 400;
105
- color: var(--text-primary);
168
+ color: var(--ink);
106
169
  font-synthesis: none;
107
170
  text-rendering: optimizeLegibility;
108
171
  -webkit-font-smoothing: antialiased;
109
172
  -moz-osx-font-smoothing: grayscale;
110
- font-feature-settings: 'cv11', 'ss01';
111
173
  }
112
174
 
113
175
  .logic-editor *,
@@ -120,84 +182,51 @@
120
182
  font-family: inherit;
121
183
  }
122
184
 
185
+ /* ============================================================
186
+ DARK — "lit logic board"
187
+ ============================================================ */
123
188
  .logic-editor[data-theme="dark"] {
124
- --bg-primary: #0c0c0d;
125
- --bg-secondary: #161618;
126
- --bg-tertiary: #1c1c1f;
127
- --bg-hover: #242427;
128
- --bg-active: #2c2c30;
129
-
130
- --text-primary: #fafafa;
131
- --text-secondary: #d4d4d8;
132
- --text-tertiary: #a1a1aa;
133
- --text-muted: #71717a;
134
- --text-placeholder: #52525b;
135
-
136
- --border-primary: rgba(255, 255, 255, 0.10);
137
- --border-secondary: rgba(255, 255, 255, 0.06);
138
- --border-light: rgba(255, 255, 255, 0.04);
139
-
140
- --accent-blue: #818cf8;
141
- --accent-blue-light: #1e1b4b;
142
- --accent-blue-hover: #a5b4fc;
143
-
144
- --accent-amber: #fbbf24;
145
- --accent-amber-light: #422006;
146
-
147
- /* Status colors - darker variants */
148
- --success-bg: #052e1c;
149
- --success-text: #6ee7b7;
150
- --success-border: #065f46;
151
-
152
- --error-bg: #2c0a0c;
153
- --error-bg-light: #240a0c;
154
- --error-bg-lighter: #1a0a0c;
155
- --error-text: #fca5a5;
156
- --error-border: #7f1d1d;
157
-
158
- --warning-bg: #2a1c05;
159
- --warning-text: #fcd34d;
160
- --warning-border: #78350f;
161
-
162
- /* Syntax highlighting - dark theme */
163
- --syntax-key: #79c0ff;
164
- --syntax-string: #a5d6ff;
165
- --syntax-number: #79c0ff;
166
- --syntax-boolean: #ff7b72;
167
- --syntax-null: #8b949e;
168
- --syntax-bracket: #c9d1d9;
169
- --syntax-punctuation: #c9d1d9;
170
-
171
- /* Node colors */
172
- --node-bg: #18181b;
173
- --node-shadow: 0 1px 3px rgba(0, 0, 0, 0.4), 0 1px 2px rgba(0, 0, 0, 0.3);
174
- --node-shadow-hover: 0 8px 24px rgba(0, 0, 0, 0.5), 0 2px 6px rgba(0, 0, 0, 0.3);
175
-
176
- /* Code background */
177
- --code-bg: #1f1f1f;
178
-
179
- /* Debug popover colors */
180
- --debug-popover-bg: #1f2937;
181
- --debug-popover-text: #f3f4f6;
182
- --debug-popover-error-bg: #7f1d1d;
183
- --debug-popover-shadow: rgba(0, 0, 0, 0.4);
184
- --debug-popover-value-bg: rgba(0, 0, 0, 0.2);
185
- --debug-iteration-color: #fbbf24;
186
- --debug-label-color: #9ca3af;
187
- --debug-border-color: rgba(255, 255, 255, 0.1);
188
-
189
- /* Debug value type colors */
190
- --debug-value-true: #86efac;
191
- --debug-value-false: #fca5a5;
192
- --debug-value-number: #93c5fd;
193
- --debug-value-string: #86efac;
194
- --debug-value-array: #d8b4fe;
195
- --debug-value-null: #9ca3af;
196
-
197
- /* Dark mode shadow tweaks */
198
- --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.3);
199
- --shadow-md: 0 2px 4px rgba(0, 0, 0, 0.3), 0 4px 12px rgba(0, 0, 0, 0.5);
200
- --shadow-lg: 0 4px 8px rgba(0, 0, 0, 0.4), 0 12px 32px rgba(0, 0, 0, 0.6);
189
+ --board: #0a0f16;
190
+ --board-grid: rgba(120, 170, 255, 0.06);
191
+ --surface: #10161f;
192
+ --surface-2: #141b26;
193
+ --chip: #161d28;
194
+ --hairline: #263140;
195
+ --hairline-2: #1d2632;
196
+
197
+ --ink: #e6edf5;
198
+ --ink-2: #b3c1d1;
199
+ --muted: #8a9cb0;
200
+ --faint: #566172;
201
+
202
+ --accent: #7c86f5;
203
+ --accent-soft: #1b2140;
204
+ --accent-hover: #9aa2f8;
205
+
206
+ --sig-bool-true: #3fb950;
207
+ --sig-bool-false: #f85149;
208
+ --sig-bool-rest: #8098b0;
209
+ --sig-number: #58a6ff;
210
+ --sig-string: #e3b341;
211
+ --sig-collection: #bc8cff;
212
+ --sig-data: #39c5cf;
213
+ --sig-temporal: #db61a2;
214
+ --sig-null: #8b949e;
215
+
216
+ --sig-bool-true-bg: rgba(63, 185, 80, 0.13);
217
+ --sig-bool-false-bg: rgba(248, 81, 73, 0.13);
218
+ --sig-number-bg: rgba(88, 166, 255, 0.13);
219
+ --sig-string-bg: rgba(227, 179, 65, 0.14);
220
+ --sig-collection-bg: rgba(188, 140, 255, 0.13);
221
+ --sig-data-bg: rgba(57, 197, 207, 0.13);
222
+ --sig-temporal-bg: rgba(219, 97, 162, 0.14);
223
+ --sig-null-bg: rgba(139, 148, 158, 0.14);
224
+
225
+ --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.5);
226
+ --shadow-md: 0 1px 2px rgba(0, 0, 0, 0.5), 0 2px 8px rgba(0, 0, 0, 0.4);
227
+ --shadow-lg: 0 12px 40px rgba(0, 0, 0, 0.6), 0 2px 10px rgba(0, 0, 0, 0.4);
228
+
229
+ --debug-popover-shadow: rgba(0, 0, 0, 0.5);
201
230
  }
202
231
  /*
203
232
  * ReactFlow base styles - bundled locally so they're included in the library's styles.css
@@ -1102,7 +1131,7 @@ svg.react-flow__connectionline {
1102
1131
  }
1103
1132
 
1104
1133
  .dl-edge-picker-operator-name {
1105
- font-family: 'SF Mono', Monaco, 'Cascadia Code', monospace;
1134
+ font-family: var(--font-mono);
1106
1135
  font-weight: 600;
1107
1136
  min-width: 50px;
1108
1137
  }
@@ -1173,27 +1202,9 @@ svg.react-flow__connectionline {
1173
1202
  display: none;
1174
1203
  }
1175
1204
  }
1176
- /* Inline variant (used in toolbar) */
1177
- .dl-debugger-controls--inline {
1178
- display: flex;
1179
- align-items: center;
1180
- flex-shrink: 0;
1181
- }
1205
+ /* Transport bar floating over the board, or chrome-stripped inline in the toolbar.
1206
+ Mirrors the design-system .transport. */
1182
1207
 
1183
- .dl-debugger-controls--inline .dl-debugger-controls-inner {
1184
- display: flex;
1185
- align-items: center;
1186
- gap: 12px;
1187
- padding: 0;
1188
- background: none;
1189
- border: none;
1190
- border-radius: 0;
1191
- box-shadow: none;
1192
- backdrop-filter: none;
1193
- flex-shrink: 0;
1194
- }
1195
-
1196
- /* Floating overlay variant (legacy, used inside ReactFlow) */
1197
1208
  .dl-debugger-controls--floating {
1198
1209
  position: absolute;
1199
1210
  top: 12px;
@@ -1203,188 +1214,205 @@ svg.react-flow__connectionline {
1203
1214
  pointer-events: auto;
1204
1215
  }
1205
1216
 
1206
- .dl-debugger-controls--floating .dl-debugger-controls-inner {
1207
- display: flex;
1217
+ .dl-debugger-controls-inner {
1218
+ position: relative;
1219
+ display: inline-flex;
1208
1220
  align-items: center;
1209
- gap: 16px;
1210
- padding: 8px 16px;
1211
- background: var(--bg-secondary);
1212
- border: 1px solid var(--border-primary);
1213
- border-radius: 8px;
1214
- box-shadow: 0 4px 12px var(--node-shadow);
1215
- backdrop-filter: blur(8px);
1221
+ gap: 12px;
1222
+ height: 48px;
1223
+ padding: 0 12px 0 15px;
1224
+ border-radius: 13px;
1225
+ background: color-mix(in srgb, var(--surface) 92%, transparent);
1226
+ backdrop-filter: blur(14px);
1227
+ border: 1px solid var(--hairline);
1228
+ box-shadow: var(--shadow-lg);
1229
+ font-family: var(--font-ui);
1230
+ }
1231
+
1232
+ /* left rail — resting slate, accent while playing */
1233
+ .dl-debugger-controls-inner::before {
1234
+ content: "";
1235
+ position: absolute;
1236
+ left: 0;
1237
+ top: 10px;
1238
+ bottom: 10px;
1239
+ width: 3px;
1240
+ border-radius: 3px;
1241
+ background: var(--sig-bool-rest);
1242
+ }
1243
+ .dl-debugger-controls-inner.is-playing::before {
1244
+ background: var(--accent);
1216
1245
  }
1217
1246
 
1218
- /* Bug icon indicator */
1219
1247
  .dl-debugger-icon {
1220
- display: flex;
1248
+ display: inline-flex;
1221
1249
  align-items: center;
1222
- justify-content: center;
1223
- color: var(--accent-amber);
1250
+ color: var(--sig-string);
1224
1251
  }
1225
1252
 
1226
- /* Navigation buttons */
1227
1253
  .dl-debugger-buttons {
1228
- display: flex;
1254
+ display: inline-flex;
1229
1255
  align-items: center;
1230
- gap: 4px;
1256
+ gap: 6px;
1231
1257
  flex-shrink: 0;
1232
1258
  }
1233
1259
 
1234
1260
  .dl-debugger-btn {
1235
- display: flex;
1236
- align-items: center;
1237
- justify-content: center;
1238
- width: 32px;
1239
- height: 32px;
1261
+ width: 34px;
1262
+ height: 34px;
1240
1263
  padding: 0;
1241
- border: none;
1242
- border-radius: 6px;
1243
- background: var(--bg-hover);
1244
- color: var(--text-secondary);
1264
+ border-radius: 8px;
1265
+ display: grid;
1266
+ place-items: center;
1245
1267
  cursor: pointer;
1246
- transition: background-color 0.15s, color 0.15s, transform 0.1s;
1268
+ background: var(--surface-2);
1269
+ border: 1px solid var(--hairline);
1270
+ color: var(--ink-2);
1271
+ transition: border-color 0.15s ease, transform 0.1s ease, background 0.15s ease, color 0.15s ease;
1247
1272
  }
1248
-
1249
1273
  .dl-debugger-btn:hover:not(:disabled) {
1250
- background: var(--bg-tertiary);
1251
- color: var(--text-primary);
1274
+ border-color: color-mix(in srgb, var(--accent) 55%, var(--hairline));
1275
+ color: var(--ink);
1252
1276
  }
1253
-
1254
1277
  .dl-debugger-btn:active:not(:disabled) {
1255
- transform: scale(0.95);
1278
+ transform: scale(0.94);
1256
1279
  }
1257
-
1258
1280
  .dl-debugger-btn:disabled {
1259
- opacity: 0.4;
1260
- cursor: not-allowed;
1281
+ opacity: 0.35;
1282
+ cursor: default;
1261
1283
  }
1262
-
1263
1284
  .dl-debugger-btn-primary {
1264
- width: 36px;
1265
- height: 36px;
1266
- background: var(--accent-blue);
1267
- color: white;
1285
+ width: 40px;
1286
+ height: 40px;
1287
+ background: var(--accent);
1288
+ border-color: var(--accent);
1289
+ color: #fff;
1290
+ box-shadow: 0 0 0 3px var(--accent-soft);
1268
1291
  }
1269
-
1270
1292
  .dl-debugger-btn-primary:hover:not(:disabled) {
1271
- background: var(--accent-blue-hover);
1272
- color: white;
1293
+ filter: brightness(1.08);
1294
+ color: #fff;
1295
+ border-color: var(--accent);
1273
1296
  }
1274
1297
 
1275
- /* Step counter */
1298
+ /* step counter — a mono readout whose underline fills with progress */
1276
1299
  .dl-debugger-step-counter {
1277
- display: flex;
1300
+ position: relative;
1301
+ display: inline-flex;
1278
1302
  align-items: baseline;
1279
- gap: 2px;
1280
- font-family: 'SF Mono', 'Consolas', monospace;
1281
- font-size: 13px;
1282
- min-width: 60px;
1303
+ gap: 3px;
1304
+ min-width: 58px;
1283
1305
  justify-content: center;
1306
+ padding: 6px 12px 8px;
1307
+ border-radius: 8px;
1308
+ overflow: hidden;
1284
1309
  flex-shrink: 0;
1310
+ font-family: var(--font-mono);
1311
+ background: linear-gradient(180deg, color-mix(in srgb, var(--accent) 8%, var(--surface-2)), var(--surface-2));
1312
+ border: 1px solid color-mix(in srgb, var(--accent) 34%, var(--hairline));
1285
1313
  }
1286
-
1287
1314
  .dl-step-current {
1288
- color: var(--text-primary);
1289
- font-weight: 600;
1315
+ font-size: 15px;
1316
+ font-weight: 700;
1317
+ color: var(--ink);
1290
1318
  }
1291
-
1292
- .dl-step-separator {
1293
- color: var(--text-muted);
1294
- margin: 0 2px;
1319
+ .dl-debugger-controls-inner.is-playing .dl-step-current {
1320
+ color: var(--accent);
1295
1321
  }
1296
-
1322
+ .dl-step-separator,
1297
1323
  .dl-step-total {
1298
- color: var(--text-secondary);
1324
+ color: var(--muted);
1325
+ font-size: 12px;
1326
+ }
1327
+ .dl-step-progress {
1328
+ position: absolute;
1329
+ left: 0;
1330
+ bottom: 0;
1331
+ height: 2px;
1332
+ background: var(--accent);
1333
+ border-radius: 2px;
1334
+ transition: width 0.2s ease;
1299
1335
  }
1300
1336
 
1301
- /* Speed control */
1337
+ /* speed slider */
1302
1338
  .dl-debugger-speed {
1303
- display: flex;
1339
+ display: inline-flex;
1304
1340
  align-items: center;
1305
1341
  gap: 8px;
1306
1342
  flex-shrink: 0;
1307
1343
  }
1308
-
1309
1344
  .dl-speed-label {
1310
- font-size: 12px;
1311
- color: var(--text-tertiary);
1345
+ font-family: var(--font-mono);
1346
+ font-size: 9.5px;
1347
+ font-weight: 700;
1348
+ letter-spacing: 0.1em;
1349
+ text-transform: uppercase;
1350
+ color: var(--muted);
1312
1351
  white-space: nowrap;
1313
1352
  }
1314
-
1315
1353
  .dl-speed-slider {
1316
- width: 80px;
1317
- height: 4px;
1318
1354
  -webkit-appearance: none;
1319
1355
  appearance: none;
1320
- background: var(--bg-tertiary);
1321
- border-radius: 2px;
1356
+ width: 84px;
1357
+ height: 4px;
1358
+ border-radius: 3px;
1359
+ background: var(--hairline);
1322
1360
  cursor: pointer;
1323
1361
  }
1324
-
1325
1362
  .dl-speed-slider::-webkit-slider-thumb {
1326
1363
  -webkit-appearance: none;
1327
1364
  appearance: none;
1328
1365
  width: 14px;
1329
1366
  height: 14px;
1330
- background: var(--accent-blue);
1331
1367
  border-radius: 50%;
1368
+ background: var(--chip);
1369
+ border: 2px solid var(--sig-number);
1332
1370
  cursor: pointer;
1333
- transition: transform 0.1s;
1334
- }
1335
-
1336
- .dl-speed-slider::-webkit-slider-thumb:hover {
1337
- transform: scale(1.15);
1338
1371
  }
1339
-
1340
1372
  .dl-speed-slider::-moz-range-thumb {
1341
1373
  width: 14px;
1342
1374
  height: 14px;
1343
- background: var(--accent-blue);
1344
1375
  border-radius: 50%;
1345
- border: none;
1376
+ background: var(--chip);
1377
+ border: 2px solid var(--sig-number);
1346
1378
  cursor: pointer;
1347
1379
  }
1348
1380
 
1349
- /* Dark mode adjustments */
1350
- .logic-editor[data-theme="dark"] .dl-debugger-controls--floating .dl-debugger-controls-inner {
1351
- background: rgba(31, 41, 55, 0.95);
1352
- border-color: var(--border-light);
1381
+ /* inline variant chrome stripped, lives in the toolbar strip */
1382
+ .dl-debugger-controls--inline {
1383
+ display: flex;
1384
+ align-items: center;
1385
+ flex-shrink: 0;
1353
1386
  }
1354
-
1355
- .logic-editor[data-theme="dark"] .dl-debugger-btn {
1356
- background: rgba(55, 65, 81, 0.8);
1387
+ .dl-debugger-controls--inline .dl-debugger-controls-inner {
1388
+ background: none;
1389
+ backdrop-filter: none;
1390
+ border: none;
1391
+ box-shadow: none;
1392
+ height: auto;
1393
+ padding: 0;
1394
+ gap: 10px;
1357
1395
  }
1358
-
1359
- .logic-editor[data-theme="dark"] .dl-debugger-btn:hover:not(:disabled) {
1360
- background: rgba(75, 85, 99, 0.9);
1396
+ .dl-debugger-controls--inline .dl-debugger-controls-inner::before {
1397
+ display: none;
1361
1398
  }
1362
-
1363
- .logic-editor[data-theme="dark"] .dl-speed-slider {
1364
- background: rgba(75, 85, 99, 0.8);
1399
+ .dl-debugger-controls--inline .dl-debugger-icon,
1400
+ .dl-debugger-controls--inline .dl-debugger-speed {
1401
+ display: none;
1402
+ }
1403
+ .dl-debugger-controls--inline .dl-debugger-btn {
1404
+ width: 30px;
1405
+ height: 30px;
1406
+ }
1407
+ .dl-debugger-controls--inline .dl-debugger-btn-primary {
1408
+ width: 34px;
1409
+ height: 34px;
1365
1410
  }
1366
1411
 
1367
- /* Mobile adjustments */
1368
1412
  @media (max-width: 1024px) {
1369
1413
  .dl-debugger-controls--inline .dl-debugger-controls-inner {
1370
1414
  gap: 8px;
1371
1415
  }
1372
-
1373
- .dl-debugger-btn {
1374
- width: 36px;
1375
- height: 36px;
1376
- }
1377
-
1378
- .dl-debugger-btn-primary {
1379
- width: 40px;
1380
- height: 40px;
1381
- }
1382
-
1383
- .dl-debugger-step-counter {
1384
- min-width: 50px;
1385
- font-size: 12px;
1386
- }
1387
-
1388
1416
  .dl-speed-slider {
1389
1417
  width: 60px;
1390
1418
  }
@@ -1597,7 +1625,7 @@ svg.react-flow__connectionline {
1597
1625
  }
1598
1626
 
1599
1627
  .help-badge code {
1600
- font-family: var(--dl-font-mono, 'SF Mono', 'Monaco', 'Inconsolata', monospace);
1628
+ font-family: var(--font-mono);
1601
1629
  }
1602
1630
 
1603
1631
  .help-badge-arity {
@@ -1712,7 +1740,7 @@ svg.react-flow__connectionline {
1712
1740
  .help-example-code {
1713
1741
  margin: 0;
1714
1742
  padding: 8px;
1715
- font-family: var(--dl-font-mono, 'SF Mono', 'Monaco', 'Inconsolata', monospace);
1743
+ font-family: var(--font-mono);
1716
1744
  font-size: 11px;
1717
1745
  line-height: 1.5;
1718
1746
  background: var(--dl-bg-code, #fff);
@@ -1749,7 +1777,7 @@ svg.react-flow__connectionline {
1749
1777
 
1750
1778
  .help-example-data code,
1751
1779
  .help-example-result code {
1752
- font-family: var(--dl-font-mono, 'SF Mono', 'Monaco', 'Inconsolata', monospace);
1780
+ font-family: var(--font-mono);
1753
1781
  color: var(--dl-text-primary, #1a1a1a);
1754
1782
  }
1755
1783
 
@@ -1759,7 +1787,7 @@ svg.react-flow__connectionline {
1759
1787
  }
1760
1788
 
1761
1789
  .help-example-error code {
1762
- font-family: var(--dl-font-mono, 'SF Mono', 'Monaco', 'Inconsolata', monospace);
1790
+ font-family: var(--font-mono);
1763
1791
  color: var(--dl-error, #ef4444);
1764
1792
  }
1765
1793
 
@@ -1978,7 +2006,7 @@ svg.react-flow__connectionline {
1978
2006
  flex: 1;
1979
2007
  padding: 4px 8px;
1980
2008
  font-size: 12px;
1981
- font-family: 'SF Mono', Monaco, 'Cascadia Code', monospace;
2009
+ font-family: var(--font-mono);
1982
2010
  color: var(--text-primary, #1a1a1a);
1983
2011
  background: transparent;
1984
2012
  border: none;
@@ -2096,7 +2124,7 @@ svg.react-flow__connectionline {
2096
2124
  width: 100%;
2097
2125
  padding: 6px 8px;
2098
2126
  font-size: 12px;
2099
- font-family: 'SF Mono', Monaco, 'Cascadia Code', monospace;
2127
+ font-family: var(--font-mono);
2100
2128
  color: var(--text-primary, #1a1a1a);
2101
2129
  background: var(--bg-primary, #ffffff);
2102
2130
  border: 1px solid var(--border-color, #d0d0d0);
@@ -2178,7 +2206,7 @@ svg.react-flow__connectionline {
2178
2206
  flex: 1;
2179
2207
  padding: 6px 8px;
2180
2208
  font-size: 12px;
2181
- font-family: 'SF Mono', Monaco, 'Cascadia Code', monospace;
2209
+ font-family: var(--font-mono);
2182
2210
  color: var(--color-primary, #2563eb);
2183
2211
  background: var(--bg-primary, #ffffff);
2184
2212
  border: 1px solid var(--border-color, #d0d0d0);
@@ -2218,7 +2246,7 @@ svg.react-flow__connectionline {
2218
2246
  width: 100%;
2219
2247
  padding: 6px 8px;
2220
2248
  font-size: 12px;
2221
- font-family: 'SF Mono', Monaco, 'Cascadia Code', monospace;
2249
+ font-family: var(--font-mono);
2222
2250
  color: var(--text-secondary, #666);
2223
2251
  background: var(--bg-tertiary, #f5f5f5);
2224
2252
  border: 1px solid var(--border-color, #e0e0e0);
@@ -2393,7 +2421,7 @@ svg.react-flow__connectionline {
2393
2421
  }
2394
2422
 
2395
2423
  .properties-panel-operator-symbol {
2396
- font-family: 'SF Mono', Monaco, 'Cascadia Code', monospace;
2424
+ font-family: var(--font-mono);
2397
2425
  font-size: 11px;
2398
2426
  color: var(--text-tertiary, #999);
2399
2427
  padding: 2px 6px;
@@ -2580,7 +2608,7 @@ svg.react-flow__connectionline {
2580
2608
  .panel-input-textarea {
2581
2609
  resize: vertical;
2582
2610
  min-height: 60px;
2583
- font-family: var(--dl-font-mono, 'SF Mono', 'Monaco', 'Inconsolata', monospace);
2611
+ font-family: var(--font-mono);
2584
2612
  }
2585
2613
 
2586
2614
  /* ==========================================================================
@@ -2704,7 +2732,7 @@ svg.react-flow__connectionline {
2704
2732
  .panel-input-path-prefix {
2705
2733
  padding: 8px 0 8px 10px;
2706
2734
  font-size: 13px;
2707
- font-family: var(--dl-font-mono, 'SF Mono', 'Monaco', 'Inconsolata', monospace);
2735
+ font-family: var(--font-mono);
2708
2736
  color: var(--dl-text-tertiary, #999);
2709
2737
  user-select: none;
2710
2738
  }
@@ -2712,7 +2740,7 @@ svg.react-flow__connectionline {
2712
2740
  .panel-input-path {
2713
2741
  border: none;
2714
2742
  padding-left: 4px;
2715
- font-family: var(--dl-font-mono, 'SF Mono', 'Monaco', 'Inconsolata', monospace);
2743
+ font-family: var(--font-mono);
2716
2744
  }
2717
2745
 
2718
2746
  .panel-input-path:focus {
@@ -2737,7 +2765,7 @@ svg.react-flow__connectionline {
2737
2765
 
2738
2766
  .panel-input-segment {
2739
2767
  flex: 1;
2740
- font-family: var(--dl-font-mono, 'SF Mono', 'Monaco', 'Inconsolata', monospace);
2768
+ font-family: var(--font-mono);
2741
2769
  }
2742
2770
 
2743
2771
  .panel-input-segment-remove {
@@ -2791,7 +2819,7 @@ svg.react-flow__connectionline {
2791
2819
 
2792
2820
  .panel-input-path-preview {
2793
2821
  font-size: 11px;
2794
- font-family: var(--dl-font-mono, 'SF Mono', 'Monaco', 'Inconsolata', monospace);
2822
+ font-family: var(--font-mono);
2795
2823
  color: var(--dl-text-tertiary, #999);
2796
2824
  padding: 4px 0;
2797
2825
  }
@@ -2824,7 +2852,7 @@ svg.react-flow__connectionline {
2824
2852
  }
2825
2853
 
2826
2854
  .panel-input-expression-summary {
2827
- font-family: var(--dl-font-mono, 'SF Mono', 'Monaco', 'Inconsolata', monospace);
2855
+ font-family: var(--font-mono);
2828
2856
  color: var(--dl-text-primary, #1a1a1a);
2829
2857
  overflow: hidden;
2830
2858
  text-overflow: ellipsis;
@@ -2852,7 +2880,7 @@ svg.react-flow__connectionline {
2852
2880
  }
2853
2881
 
2854
2882
  .panel-input-json {
2855
- font-family: var(--dl-font-mono, 'SF Mono', 'Monaco', 'Inconsolata', monospace);
2883
+ font-family: var(--font-mono);
2856
2884
  font-size: 12px;
2857
2885
  line-height: 1.5;
2858
2886
  resize: vertical;
@@ -2960,7 +2988,7 @@ svg.react-flow__connectionline {
2960
2988
  }
2961
2989
 
2962
2990
  .panel-hint-description code {
2963
- font-family: var(--dl-font-mono, 'SF Mono', 'Monaco', 'Inconsolata', monospace);
2991
+ font-family: var(--font-mono);
2964
2992
  font-size: 11px;
2965
2993
  background: var(--dl-bg-code, #e8e8e8);
2966
2994
  padding: 1px 4px;
@@ -2995,7 +3023,7 @@ svg.react-flow__connectionline {
2995
3023
  }
2996
3024
 
2997
3025
  .panel-context-example {
2998
- font-family: var(--dl-font-mono, 'SF Mono', 'Monaco', 'Inconsolata', monospace);
3026
+ font-family: var(--font-mono);
2999
3027
  font-size: 11px;
3000
3028
  background: var(--dl-bg-code, rgba(0, 0, 0, 0.06));
3001
3029
  padding: 2px 6px;
@@ -3015,6 +3043,529 @@ svg.react-flow__connectionline {
3015
3043
  font-size: 11px;
3016
3044
  color: var(--dl-text-tertiary, #999);
3017
3045
  }
3046
+ /* ============================================
3047
+ Signal Board — operand pills, LEDs, op glyphs, shape silhouettes
3048
+ ============================================ */
3049
+
3050
+ /* type-coloured operand pills (colour = the operand's value type) */
3051
+ .dl-pill {
3052
+ display: inline-flex;
3053
+ align-items: center;
3054
+ gap: 5px;
3055
+ padding: 2px 8px;
3056
+ border-radius: 6px;
3057
+ font-family: var(--font-mono);
3058
+ font-size: 12px;
3059
+ font-weight: 500;
3060
+ border: 1px solid transparent;
3061
+ white-space: nowrap;
3062
+ max-width: 100%;
3063
+ overflow: hidden;
3064
+ text-overflow: ellipsis;
3065
+ min-width: 0;
3066
+ }
3067
+ .dl-pill-tap { color: var(--sig-data); background: var(--sig-data-bg); border-color: color-mix(in srgb, var(--sig-data) 24%, transparent); }
3068
+ .dl-pill-tap::before { content: "\2041"; font-size: 11px; opacity: 0.8; }
3069
+ .dl-pill-num { color: var(--sig-number); background: var(--sig-number-bg); border-color: color-mix(in srgb, var(--sig-number) 22%, transparent); }
3070
+ .dl-pill-str { color: var(--sig-string); background: var(--sig-string-bg); border-color: color-mix(in srgb, var(--sig-string) 26%, transparent); }
3071
+ .dl-pill-bool { color: var(--sig-bool-true); background: var(--sig-bool-true-bg); border-color: color-mix(in srgb, var(--sig-bool-true) 24%, transparent); }
3072
+ .dl-pill-coll { color: var(--sig-collection); background: var(--sig-collection-bg); border-color: color-mix(in srgb, var(--sig-collection) 24%, transparent); }
3073
+ .dl-pill-temp { color: var(--sig-temporal); background: var(--sig-temporal-bg); border-color: color-mix(in srgb, var(--sig-temporal) 24%, transparent); }
3074
+ .dl-pill-nul { color: var(--sig-null); background: var(--sig-null-bg); border-color: color-mix(in srgb, var(--sig-null) 22%, transparent); font-style: italic; }
3075
+
3076
+ /* boolean gate/quantifier LED */
3077
+ .dl-led {
3078
+ width: 10px;
3079
+ height: 10px;
3080
+ border-radius: 50%;
3081
+ flex-shrink: 0;
3082
+ border: 1.5px solid var(--sig-bool-rest);
3083
+ background: transparent;
3084
+ }
3085
+ .dl-node.debug-executed .dl-led {
3086
+ border-color: var(--sig-bool-true);
3087
+ background: var(--sig-bool-true);
3088
+ box-shadow: 0 0 0 3px var(--sig-bool-true-bg);
3089
+ }
3090
+ .dl-node.debug-error .dl-led {
3091
+ border-color: var(--sig-bool-false);
3092
+ background: var(--sig-bool-false);
3093
+ }
3094
+
3095
+ /* operator math glyph (gate / arithmetic) */
3096
+ .dl-op-glyph {
3097
+ font-family: var(--font-mono);
3098
+ font-size: 17px;
3099
+ font-weight: 700;
3100
+ line-height: 1;
3101
+ color: var(--dl-sig);
3102
+ flex-shrink: 0;
3103
+ min-width: 14px;
3104
+ text-align: center;
3105
+ }
3106
+
3107
+ /* gate & arithmetic: the op-glyph carries the meaning, so drop the category
3108
+ badge and demote the verbose label to a small-caps eyebrow */
3109
+ .dl-shape-gate .vertical-cell-icon,
3110
+ .dl-shape-arith .vertical-cell-icon {
3111
+ display: none;
3112
+ }
3113
+ .dl-shape-gate .vertical-cell-label,
3114
+ .dl-shape-arith .vertical-cell-label {
3115
+ font-size: 10.5px;
3116
+ font-weight: 600;
3117
+ letter-spacing: 0.04em;
3118
+ text-transform: uppercase;
3119
+ color: var(--muted);
3120
+ }
3121
+
3122
+ /* data tap (var / val / exists): a teal PLUG that reads from the data and points
3123
+ into the flow. The node box itself is transparent; the inner .dl-tap carries the
3124
+ silhouette (clip-path), so the ReactFlow output handle — a sibling of .dl-tap —
3125
+ stays at the plug's tip and is never clipped. */
3126
+ .dl-shape-tap { --dl-sig: var(--sig-data); }
3127
+ .dl-node.dl-shape-tap {
3128
+ background: transparent !important;
3129
+ border: none;
3130
+ box-shadow: none;
3131
+ width: fit-content;
3132
+ display: inline-flex;
3133
+ align-items: center;
3134
+ gap: 5px;
3135
+ overflow: visible;
3136
+ }
3137
+ .dl-node.dl-shape-tap::before { display: none; } /* no left rail — the plug is fully tinted */
3138
+ .dl-node.dl-shape-tap:hover { box-shadow: none; }
3139
+ /* keep the plug's 1px drop-shadow outline from being clipped in debug states */
3140
+ .dl-node.dl-shape-tap[class*="debug-"]:not(.debug-current) { overflow: visible; }
3141
+
3142
+ .dl-tap {
3143
+ --tap-line: color-mix(in srgb, var(--sig-data) 55%, var(--node-bg));
3144
+ position: relative;
3145
+ display: inline-flex;
3146
+ align-items: center;
3147
+ gap: 6px;
3148
+ white-space: nowrap;
3149
+ padding: 6px 19px 6px 12px; /* extra right padding leaves room for the plug point */
3150
+ font-family: var(--font-mono);
3151
+ font-size: 12px; /* matches the operand pills so operands read at one size */
3152
+ font-weight: 500;
3153
+ color: var(--sig-data);
3154
+ background: color-mix(in srgb, var(--sig-data) 15%, var(--node-bg));
3155
+ clip-path: polygon(0 0, calc(100% - 10px) 0, 100% 50%, calc(100% - 10px) 100%, 0 100%);
3156
+ filter:
3157
+ drop-shadow(1px 0 0 var(--tap-line)) drop-shadow(-1px 0 0 var(--tap-line))
3158
+ drop-shadow(0 1px 0 var(--tap-line)) drop-shadow(0 -1px 0 var(--tap-line))
3159
+ drop-shadow(0.8px 0.8px 0 var(--tap-line)) drop-shadow(-0.8px 0.8px 0 var(--tap-line))
3160
+ drop-shadow(0.8px -0.8px 0 var(--tap-line)) drop-shadow(-0.8px -0.8px 0 var(--tap-line));
3161
+ transition: filter var(--motion-base) var(--ease-out);
3162
+ }
3163
+ .dl-tap-glyph { opacity: 0.85; font-size: 11px; }
3164
+ .dl-tap-path { color: var(--sig-data); font-weight: 600; }
3165
+ .dl-tap-val { color: var(--muted); font-size: 11px; }
3166
+
3167
+ /* hover: deepen the plug outline (parallels the border-tint hover on card nodes) */
3168
+ .dl-node.dl-shape-tap:hover .dl-tap {
3169
+ --tap-line: color-mix(in srgb, var(--sig-data) 82%, var(--node-bg));
3170
+ }
3171
+
3172
+ /* selection ring FOLLOWS the plug silhouette: an accent copy of the plug shape
3173
+ rendered 2px larger BEHIND the plug, on the un-clipped node wrapper. (A
3174
+ box-shadow / drop-shadow on the plug itself is swallowed by its own clip-path.) */
3175
+ .dl-node.dl-shape-tap.selected { box-shadow: none; }
3176
+ .dl-node.dl-shape-tap .dl-tap { z-index: 1; }
3177
+ .dl-node.dl-shape-tap.selected::after {
3178
+ content: "";
3179
+ position: absolute;
3180
+ inset: -2px;
3181
+ z-index: 0;
3182
+ background: var(--accent);
3183
+ clip-path: polygon(0 0, calc(100% - 12px) 0, 100% 50%, calc(100% - 12px) 100%, 0 100%);
3184
+ pointer-events: none;
3185
+ }
3186
+
3187
+ /* debug rings: an accent-free copy of the plug silhouette, tinted per state, so the
3188
+ highlight follows the plug SHAPE. The node box is transparent, so the generic
3189
+ rectangular box-shadow debug rings would halo empty space — suppress them here
3190
+ and let the clip-path ::after ring carry every debug state instead. */
3191
+ .dl-node.dl-shape-tap[class*="debug-"] {
3192
+ box-shadow: none !important;
3193
+ animation: none !important;
3194
+ }
3195
+ .dl-node.dl-shape-tap[class*="debug-"]::after {
3196
+ content: "";
3197
+ position: absolute;
3198
+ inset: -2px;
3199
+ z-index: 0;
3200
+ clip-path: polygon(0 0, calc(100% - 12px) 0, 100% 50%, calc(100% - 12px) 100%, 0 100%);
3201
+ pointer-events: none;
3202
+ }
3203
+ .dl-node.dl-shape-tap.debug-executed::after { background: var(--debug-executed-color); }
3204
+ .dl-node.dl-shape-tap.debug-on-path::after { background: var(--debug-current-color); opacity: 0.55; }
3205
+ .dl-node.dl-shape-tap.debug-error::after { background: var(--debug-error-color); }
3206
+ .dl-node.dl-shape-tap.debug-current::after {
3207
+ background: var(--debug-current-color);
3208
+ animation: debug-pulse-plug 1.5s ease-in-out infinite;
3209
+ }
3210
+ .dl-node.dl-shape-tap.debug-error.debug-current::after { background: var(--debug-error-color); }
3211
+
3212
+ /* box-shadow can't follow the clip-path, so pulse the silhouette ring's own
3213
+ size/opacity to echo the card nodes' debug-current pulse. */
3214
+ @keyframes debug-pulse-plug {
3215
+ 0%, 100% { inset: -2px; opacity: 1; }
3216
+ 50% { inset: -4px; opacity: 0.7; }
3217
+ }
3218
+
3219
+ /* branch (if / switch / match): structural accent */
3220
+ .dl-shape-branch { --dl-sig: var(--accent); }
3221
+ .dl-shape-branch .vertical-cell-icon {
3222
+ color: var(--accent);
3223
+ background: var(--accent-soft);
3224
+ }
3225
+
3226
+ /* iterator / quantifier: stacked "collection" frame — an offset card outline
3227
+ behind the node (drawn with layered box-shadows so it renders above canvas) */
3228
+ .dl-shape-iterator,
3229
+ .dl-shape-quantifier { --dl-sig: var(--sig-collection); }
3230
+ .dl-shape-iterator,
3231
+ .dl-shape-quantifier {
3232
+ box-shadow:
3233
+ 5px -5px 0 -1px var(--node-bg),
3234
+ 5px -5px 0 0 color-mix(in srgb, var(--sig-collection) 38%, var(--hairline)),
3235
+ var(--node-shadow);
3236
+ }
3237
+ .dl-shape-iterator:hover,
3238
+ .dl-shape-quantifier:hover {
3239
+ box-shadow:
3240
+ 5px -5px 0 -1px var(--node-bg),
3241
+ 5px -5px 0 0 color-mix(in srgb, var(--sig-collection) 50%, var(--hairline)),
3242
+ var(--node-shadow-hover);
3243
+ }
3244
+ .dl-shape-quantifier { --dl-sig: var(--sig-bool-rest); }
3245
+ .dl-shape-quantifier .vertical-cell-icon {
3246
+ color: var(--sig-collection);
3247
+ background: color-mix(in srgb, var(--sig-collection) 14%, transparent);
3248
+ }
3249
+
3250
+ /* literal: a folded-corner CONSTANT TAG, tinted by its value type. The fold +
3251
+ outline live on the inner .dl-lit (clip-path); the .dl-node wrapper stays
3252
+ UNCLIPPED and transparent so it can host a selection / debug ring (::after)
3253
+ that follows the fold shape — a box-shadow ring is swallowed by the clip.
3254
+ Mirrors the data-tap plug. */
3255
+ .dl-node.dl-shape-literal {
3256
+ background: transparent !important;
3257
+ border: none;
3258
+ border-radius: 0;
3259
+ box-shadow: none;
3260
+ padding: 0;
3261
+ width: fit-content;
3262
+ display: inline-flex;
3263
+ align-items: center;
3264
+ overflow: visible;
3265
+ }
3266
+ .dl-node.dl-shape-literal::before { display: none; } /* no left rail — the tag is fully tinted */
3267
+ .dl-node.dl-shape-literal:hover { box-shadow: none; }
3268
+ .dl-node.dl-shape-literal[class*="debug-"]:not(.debug-current) { overflow: visible; }
3269
+
3270
+ .dl-lit {
3271
+ --lit-line: color-mix(in srgb, var(--dl-sig) 55%, var(--node-bg));
3272
+ position: relative;
3273
+ z-index: 1;
3274
+ display: inline-flex;
3275
+ align-items: center;
3276
+ gap: 7px;
3277
+ padding: 6px 12px;
3278
+ font-family: var(--font-mono);
3279
+ font-size: 12px; /* matches the operand pills / data taps */
3280
+ font-weight: 600;
3281
+ color: var(--dl-sig);
3282
+ background: color-mix(in srgb, var(--dl-sig) 12%, var(--node-bg));
3283
+ clip-path: polygon(9px 0, 100% 0, 100% 100%, 0 100%, 0 9px);
3284
+ filter:
3285
+ drop-shadow(1px 0 0 var(--lit-line)) drop-shadow(-1px 0 0 var(--lit-line))
3286
+ drop-shadow(0 1px 0 var(--lit-line)) drop-shadow(0 -1px 0 var(--lit-line))
3287
+ drop-shadow(0.8px 0.8px 0 var(--lit-line)) drop-shadow(-0.8px 0.8px 0 var(--lit-line))
3288
+ drop-shadow(0.8px -0.8px 0 var(--lit-line)) drop-shadow(-0.8px -0.8px 0 var(--lit-line));
3289
+ transition: filter var(--motion-base) var(--ease-out);
3290
+ }
3291
+ /* hover: deepen the fold outline (parallels the card border-tint hover) */
3292
+ .dl-node.dl-shape-literal:hover .dl-lit {
3293
+ --lit-line: color-mix(in srgb, var(--dl-sig) 82%, var(--node-bg));
3294
+ }
3295
+
3296
+ /* selection ring FOLLOWS the fold silhouette: an accent copy of the tag shape,
3297
+ 2px larger, BEHIND the tag (a box-shadow ring is swallowed by the clip-path). */
3298
+ .dl-node.dl-shape-literal.selected { box-shadow: none; }
3299
+ .dl-node.dl-shape-literal.selected::after {
3300
+ content: "";
3301
+ position: absolute;
3302
+ inset: -2px;
3303
+ z-index: 0;
3304
+ background: var(--accent);
3305
+ clip-path: polygon(11px 0, 100% 0, 100% 100%, 0 100%, 0 11px);
3306
+ pointer-events: none;
3307
+ }
3308
+
3309
+ /* debug rings: the same folded silhouette tinted per state — the transparent box
3310
+ would otherwise halo empty space with the generic rectangular ring. */
3311
+ .dl-node.dl-shape-literal[class*="debug-"] {
3312
+ box-shadow: none !important;
3313
+ animation: none !important;
3314
+ }
3315
+ .dl-node.dl-shape-literal[class*="debug-"]::after {
3316
+ content: "";
3317
+ position: absolute;
3318
+ inset: -2px;
3319
+ z-index: 0;
3320
+ clip-path: polygon(11px 0, 100% 0, 100% 100%, 0 100%, 0 11px);
3321
+ pointer-events: none;
3322
+ }
3323
+ .dl-node.dl-shape-literal.debug-executed::after { background: var(--debug-executed-color); }
3324
+ .dl-node.dl-shape-literal.debug-on-path::after { background: var(--debug-current-color); opacity: 0.55; }
3325
+ .dl-node.dl-shape-literal.debug-error::after { background: var(--debug-error-color); }
3326
+ .dl-node.dl-shape-literal.debug-current::after {
3327
+ background: var(--debug-current-color);
3328
+ animation: debug-pulse-plug 1.5s ease-in-out infinite;
3329
+ }
3330
+ .dl-node.dl-shape-literal.debug-error.debug-current::after { background: var(--debug-error-color); }
3331
+ .dl-lit-ptag {
3332
+ font-family: var(--font-mono);
3333
+ font-size: 8px;
3334
+ letter-spacing: 0.1em;
3335
+ text-transform: uppercase;
3336
+ color: var(--muted);
3337
+ font-weight: 600;
3338
+ margin-left: 3px; /* clear the folded corner */
3339
+ }
3340
+ .dl-shape-literal .literal-value {
3341
+ color: var(--dl-sig);
3342
+ font-weight: 600;
3343
+ font-size: 12px; /* override the legacy .literal-value 13px so operands read at one size */
3344
+ word-break: break-word;
3345
+ }
3346
+
3347
+ /* ============================================
3348
+ Infix operator chips — the readable "shape = role" forms for the two most
3349
+ common families:
3350
+ • compare (== != < > in …): a chip with a boolean LED + infix glyph
3351
+ • arithmetic (+ − × ÷ …): the op glyph in a round number-tinted badge
3352
+ Both keep the .dl-node chip (border, signal rail, shadow); only the BODY is
3353
+ a horizontal infix run of operand pills instead of stacked cell rows.
3354
+ ============================================ */
3355
+ .dl-node.dl-infix-node {
3356
+ display: inline-flex;
3357
+ align-items: center;
3358
+ width: max-content; /* size to the unwrapped infix run, not the RF wrapper width */
3359
+ max-width: 520px;
3360
+ }
3361
+ .dl-infix {
3362
+ display: inline-flex;
3363
+ align-items: center;
3364
+ gap: 7px;
3365
+ flex-wrap: nowrap;
3366
+ white-space: nowrap;
3367
+ padding: 7px 13px 7px 15px;
3368
+ min-width: 0;
3369
+ }
3370
+
3371
+ /* operator glyph */
3372
+ .dl-inop {
3373
+ font-family: var(--font-mono);
3374
+ line-height: 1;
3375
+ flex-shrink: 0;
3376
+ }
3377
+ .dl-infix-gate .dl-inop {
3378
+ font-size: 17px;
3379
+ font-weight: 700;
3380
+ color: var(--ink);
3381
+ padding: 0 1px;
3382
+ }
3383
+ /* arithmetic op glyph rides in a round badge — the "operation node" convention */
3384
+ .dl-infix-arith .dl-inop {
3385
+ display: inline-grid;
3386
+ place-items: center;
3387
+ width: 23px;
3388
+ height: 23px;
3389
+ border-radius: 50%;
3390
+ font-size: 13.5px;
3391
+ font-weight: 600;
3392
+ color: var(--sig-number);
3393
+ background: color-mix(in srgb, var(--sig-number) 13%, var(--node-bg));
3394
+ border: 1px solid color-mix(in srgb, var(--sig-number) 42%, var(--hairline));
3395
+ }
3396
+
3397
+ /* the boolean LED leads the compare chip */
3398
+ .dl-infix-gate .dl-led { margin-right: 2px; }
3399
+
3400
+ /* the (single) wired operand connects at the chip's LEFT edge, centred, so the
3401
+ arrow points at the edge instead of into the middle of the chip */
3402
+ .dl-node.dl-infix-node .dl-infix-in.react-flow__handle {
3403
+ left: -6px;
3404
+ top: 50%;
3405
+ transform: translateY(-50%);
3406
+ }
3407
+ .dl-pill-expr {
3408
+ color: var(--ink-2);
3409
+ background: var(--surface-2);
3410
+ border-color: var(--hairline);
3411
+ font-family: var(--font-mono);
3412
+ max-width: 210px;
3413
+ }
3414
+
3415
+ /* ============================================
3416
+ Boolean logic-gate silhouettes — AND / OR / NOT
3417
+ Rendered when a logical op's operands are ALL wired children. The node box is
3418
+ transparent; the SVG silhouette carries the shape, input ports spread down the
3419
+ left edge, output on the right. The child nodes carry the logic.
3420
+ ============================================ */
3421
+ .dl-node.dl-gate-node {
3422
+ background: transparent !important;
3423
+ border: none;
3424
+ box-shadow: none;
3425
+ width: fit-content;
3426
+ min-width: 84px;
3427
+ /* floor only; the true height is pinned inline (gateNodeHeight) so the drawn
3428
+ silhouette matches the footprint the layout reserved for it. */
3429
+ min-height: 44px;
3430
+ display: grid;
3431
+ place-items: center;
3432
+ position: relative;
3433
+ padding: 2px 8px;
3434
+ }
3435
+ .dl-node.dl-gate-node::before { display: none; }
3436
+ .dl-node.dl-gate-node:hover { box-shadow: none; }
3437
+ .dl-gate-svg {
3438
+ position: absolute;
3439
+ inset: 0;
3440
+ width: 100%;
3441
+ height: 100%;
3442
+ overflow: visible;
3443
+ }
3444
+ .dl-gate-sil {
3445
+ fill: color-mix(in srgb, var(--dl-sig) 12%, var(--node-bg));
3446
+ stroke: var(--dl-sig);
3447
+ stroke-width: 1.5;
3448
+ vector-effect: non-scaling-stroke;
3449
+ }
3450
+ .dl-gate-label {
3451
+ position: relative;
3452
+ z-index: 2;
3453
+ font-family: var(--font-mono);
3454
+ font-weight: 700;
3455
+ font-size: 11px;
3456
+ letter-spacing: 0.04em;
3457
+ color: var(--dl-sig);
3458
+ pointer-events: none;
3459
+ transform: translateX(-8px);
3460
+ }
3461
+ .dl-node.dl-gate-node .dl-gate-in.react-flow__handle {
3462
+ width: 8px;
3463
+ height: 8px;
3464
+ }
3465
+ /* selection follows the gate silhouette — suppress the generic rectangular ring */
3466
+ .dl-node.dl-gate-node.selected { box-shadow: none; }
3467
+ .dl-node.dl-gate-node.selected .dl-gate-sil { stroke: var(--accent); stroke-width: 2.5; }
3468
+ .dl-node.dl-gate-node.selected .dl-gate-svg {
3469
+ filter: drop-shadow(0 0 3px color-mix(in srgb, var(--accent) 45%, transparent));
3470
+ }
3471
+ .dl-node.dl-gate-node[class*="debug-"] { box-shadow: none !important; }
3472
+ .dl-node.dl-gate-node.debug-executed .dl-gate-sil { stroke: var(--debug-executed-color); }
3473
+ .dl-node.dl-gate-node.debug-error .dl-gate-sil { stroke: var(--debug-error-color); }
3474
+ .dl-node.dl-gate-node.debug-current .dl-gate-sil { stroke: var(--debug-current-color); }
3475
+
3476
+ /* ============================================
3477
+ Decision diamond — if / else-if
3478
+ Each condition is its own standalone flowchart diamond. Three inputs on the
3479
+ left (when / then / else, colour-coded); an else-if chains into the else input.
3480
+ ============================================ */
3481
+ .dl-node.dl-decision-node {
3482
+ background: transparent !important;
3483
+ border: none;
3484
+ box-shadow: none;
3485
+ width: fit-content;
3486
+ /* 72px square (was 90) — reserved to match in getNodeDimensions/DECISION_NODE,
3487
+ so the diamond sits as tight to its neighbours as any other node. */
3488
+ min-width: 72px;
3489
+ min-height: 72px;
3490
+ display: grid;
3491
+ place-items: center;
3492
+ position: relative;
3493
+ padding: 2px;
3494
+ }
3495
+ .dl-node.dl-decision-node::before { display: none; }
3496
+ .dl-node.dl-decision-node:hover { box-shadow: none; }
3497
+ .dl-dec-svg {
3498
+ position: absolute;
3499
+ inset: 0;
3500
+ width: 100%;
3501
+ height: 100%;
3502
+ overflow: visible;
3503
+ }
3504
+ .dl-dec-sil {
3505
+ fill: var(--accent-soft);
3506
+ stroke: var(--accent);
3507
+ stroke-width: 1.5;
3508
+ vector-effect: non-scaling-stroke;
3509
+ }
3510
+ .dl-dec-label {
3511
+ position: relative;
3512
+ z-index: 2;
3513
+ font-family: var(--font-mono);
3514
+ font-weight: 700;
3515
+ font-size: 15px;
3516
+ color: var(--accent);
3517
+ pointer-events: none;
3518
+ }
3519
+ .dl-node.dl-decision-node .dl-dec-port.react-flow__handle {
3520
+ width: 9px;
3521
+ height: 9px;
3522
+ border: 1.5px solid var(--node-bg);
3523
+ }
3524
+ .dl-node.dl-decision-node .dl-dec-when.react-flow__handle { background: var(--sig-bool-rest); }
3525
+ .dl-node.dl-decision-node .dl-dec-then.react-flow__handle { background: var(--sig-bool-true); }
3526
+ .dl-node.dl-decision-node .dl-dec-else.react-flow__handle { background: var(--sig-bool-false); }
3527
+ /* selection follows the diamond silhouette — suppress the generic rectangular ring */
3528
+ .dl-node.dl-decision-node.selected { box-shadow: none; }
3529
+ .dl-node.dl-decision-node.selected .dl-dec-sil {
3530
+ stroke: var(--accent);
3531
+ stroke-width: 2.5;
3532
+ fill: color-mix(in srgb, var(--accent) 20%, var(--node-bg));
3533
+ }
3534
+ .dl-node.dl-decision-node.selected .dl-dec-svg {
3535
+ filter: drop-shadow(0 0 3px color-mix(in srgb, var(--accent) 45%, transparent));
3536
+ }
3537
+ .dl-node.dl-decision-node[class*="debug-"] { box-shadow: none !important; }
3538
+ .dl-node.dl-decision-node.debug-executed .dl-dec-sil { stroke: var(--debug-executed-color); }
3539
+ .dl-node.dl-decision-node.debug-error .dl-dec-sil { stroke: var(--debug-error-color); }
3540
+ .dl-node.dl-decision-node.debug-current .dl-dec-sil { stroke: var(--debug-current-color); }
3541
+
3542
+ /* ============================================
3543
+ Direction: hierarchy (root on the left)
3544
+ Mirrors the compact directional cues so plugs/chips point toward their
3545
+ consumer, which now sits on the LEFT. Layout, handles and edges are flipped
3546
+ in JS (see utils/layout, edge-builder, and the handle components); only the
3547
+ pure-visual silhouettes are mirrored here.
3548
+ ============================================ */
3549
+ .logic-editor[data-direction="hierarchy"] .dl-tap {
3550
+ padding: 6px 12px 6px 19px; /* room for the plug point on the LEFT */
3551
+ clip-path: polygon(10px 0, 100% 0, 100% 100%, 10px 100%, 0 50%);
3552
+ }
3553
+ .logic-editor[data-direction="hierarchy"] .dl-node.dl-shape-tap.selected::after,
3554
+ .logic-editor[data-direction="hierarchy"] .dl-node.dl-shape-tap[class*="debug-"]::after {
3555
+ clip-path: polygon(12px 0, 100% 0, 100% 100%, 12px 100%, 0 50%);
3556
+ }
3557
+ .logic-editor[data-direction="hierarchy"] .dl-node.dl-infix-node .dl-infix-in.react-flow__handle {
3558
+ left: auto;
3559
+ right: -6px;
3560
+ }
3561
+ /* gate points toward its output, which is on the LEFT in hierarchy → mirror it */
3562
+ .logic-editor[data-direction="hierarchy"] .dl-gate-svg {
3563
+ transform: scaleX(-1);
3564
+ }
3565
+ .logic-editor[data-direction="hierarchy"] .dl-gate-label {
3566
+ transform: translateX(8px);
3567
+ }
3568
+
3018
3569
  /* ============================================
3019
3570
  CSS Variables - Debug Colors
3020
3571
  ============================================ */
@@ -3042,25 +3593,45 @@ svg.react-flow__connectionline {
3042
3593
  ============================================ */
3043
3594
 
3044
3595
  .dl-node {
3596
+ --dl-sig: var(--sig-bool-rest); /* set per-node from its signal (return type) */
3045
3597
  border-radius: var(--radius-md);
3046
- border: 2px solid;
3598
+ border: 1px solid var(--hairline);
3047
3599
  font-family: inherit;
3048
3600
  font-size: 13px;
3049
3601
  width: 100%;
3050
3602
  box-sizing: border-box;
3051
3603
  box-shadow: var(--node-shadow);
3052
3604
  transition: box-shadow var(--motion-base) var(--ease-out),
3605
+ border-color var(--motion-base) var(--ease-out),
3053
3606
  transform var(--motion-fast) var(--ease-out);
3054
3607
  background: var(--node-bg) !important;
3055
3608
  position: relative;
3056
3609
  }
3057
3610
 
3611
+ /* thin left "signal rail" — tinted by the value type this node outputs.
3612
+ Quiet by default; the chip stays near-neutral so colour reads as meaning. */
3613
+ .dl-node::before {
3614
+ content: "";
3615
+ position: absolute;
3616
+ left: 0;
3617
+ top: 8px;
3618
+ bottom: 8px;
3619
+ width: 3px;
3620
+ border-radius: 0 3px 3px 0;
3621
+ background: var(--dl-sig);
3622
+ opacity: 0.9;
3623
+ z-index: 1;
3624
+ pointer-events: none;
3625
+ }
3626
+
3058
3627
  .dl-node:hover {
3628
+ border-color: color-mix(in srgb, var(--dl-sig) 45%, var(--hairline));
3059
3629
  box-shadow: var(--node-shadow-hover);
3060
3630
  }
3061
3631
 
3062
3632
  .dl-node.selected {
3063
- box-shadow: 0 0 0 2px var(--accent-blue), var(--node-shadow-hover);
3633
+ border-color: var(--accent);
3634
+ box-shadow: 0 0 0 2px var(--accent), var(--node-shadow-hover);
3064
3635
  }
3065
3636
 
3066
3637
  /* ============================================
@@ -3142,12 +3713,12 @@ svg.react-flow__connectionline {
3142
3713
  ============================================ */
3143
3714
 
3144
3715
  .vertical-cell-header {
3145
- padding: 4px 10px;
3146
- border-radius: calc(var(--radius-md) - 2px) calc(var(--radius-md) - 2px) 0 0;
3147
- color: white;
3716
+ padding: 7px 12px 7px 15px;
3717
+ color: var(--ink);
3148
3718
  display: flex;
3149
3719
  align-items: center;
3150
3720
  gap: 8px;
3721
+ border-bottom: 1px solid var(--hairline-2);
3151
3722
  }
3152
3723
 
3153
3724
  .vertical-cell-header .vertical-cell-label {
@@ -3158,15 +3729,24 @@ svg.react-flow__connectionline {
3158
3729
  margin-left: auto;
3159
3730
  }
3160
3731
 
3732
+ /* category glyph reads as a monochrome badge tinted by the node's signal */
3161
3733
  .vertical-cell-icon {
3162
- font-size: 16px;
3734
+ width: 20px;
3735
+ height: 20px;
3736
+ border-radius: 6px;
3737
+ display: grid;
3738
+ place-items: center;
3739
+ flex-shrink: 0;
3740
+ color: var(--dl-sig);
3741
+ background: color-mix(in srgb, var(--dl-sig) 14%, transparent);
3163
3742
  }
3164
3743
 
3165
3744
  .vertical-cell-label {
3166
3745
  font-weight: 600;
3167
- font-size: 16px;
3168
- letter-spacing: 0.5px;
3746
+ font-size: 13px;
3747
+ letter-spacing: -0.01em;
3169
3748
  white-space: nowrap;
3749
+ color: var(--ink);
3170
3750
  }
3171
3751
 
3172
3752
  .vertical-cell-body {
@@ -3174,7 +3754,7 @@ svg.react-flow__connectionline {
3174
3754
  }
3175
3755
 
3176
3756
  .vertical-cell-row {
3177
- padding: 6px 12px;
3757
+ padding: 6px 12px 6px 15px;
3178
3758
  border-bottom: 1px solid var(--border-light);
3179
3759
  display: flex;
3180
3760
  align-items: center;
@@ -3182,10 +3762,11 @@ svg.react-flow__connectionline {
3182
3762
  position: relative;
3183
3763
  }
3184
3764
 
3185
- /* Handle positioned inside cell row */
3765
+ /* Handle positioned inside cell row — LEFT edge (children/operands flow in from
3766
+ the left in the Signal Board left->right data flow) */
3186
3767
  .vertical-cell-row .cell-handle {
3187
3768
  position: absolute;
3188
- right: -5px;
3769
+ left: -5px;
3189
3770
  top: 50%;
3190
3771
  transform: translateY(-50%);
3191
3772
  }
@@ -3221,7 +3802,7 @@ svg.react-flow__connectionline {
3221
3802
  }
3222
3803
 
3223
3804
  .vertical-cell-inline {
3224
- font-family: 'SF Mono', 'Consolas', monospace;
3805
+ font-family: var(--font-mono);
3225
3806
  font-size: 12px;
3226
3807
  color: var(--text-primary);
3227
3808
  word-break: break-word;
@@ -3247,6 +3828,91 @@ svg.react-flow__connectionline {
3247
3828
  border-left-color: #64748b;
3248
3829
  }
3249
3830
 
3831
+ /* Branch rails — a wired child operand. The child's logic lives in its own node,
3832
+ so the row shows a compact type-tinted "extends to child" chip (dl-child-link
3833
+ reuses the dl-pill tint) instead of repeating the expression. */
3834
+ .dl-child-link {
3835
+ flex-shrink: 0;
3836
+ padding: 1px 9px;
3837
+ cursor: default;
3838
+ }
3839
+ .dl-child-glyph {
3840
+ font-size: 13px;
3841
+ line-height: 1;
3842
+ opacity: 0.9;
3843
+ }
3844
+
3845
+ /* If / Then / Else rows read as coloured rails (design-system When/Then/Else). */
3846
+ .branch-rail .vertical-cell-row-label {
3847
+ letter-spacing: 0.03em;
3848
+ }
3849
+ .branch-rail-when .vertical-cell-row-label { color: var(--sig-bool-rest); }
3850
+ .branch-rail-then .vertical-cell-row-label { color: var(--sig-bool-true); }
3851
+ .branch-rail-else .vertical-cell-row-label { color: var(--sig-bool-false); }
3852
+
3853
+ /* If as a chained decision — flowchart diamonds ("if" / "elif") down a spine,
3854
+ with the Then / Else rails indented beneath each (design-system diamond). */
3855
+ .dl-shape-branch .vertical-cell-body {
3856
+ position: relative;
3857
+ }
3858
+ .dl-shape-branch .vertical-cell-body::before {
3859
+ content: "";
3860
+ position: absolute;
3861
+ left: 34px; /* through the diamond centres */
3862
+ top: 12px;
3863
+ bottom: 12px;
3864
+ width: 1.5px;
3865
+ background: color-mix(in srgb, var(--accent) 30%, var(--hairline));
3866
+ z-index: 0;
3867
+ }
3868
+ .dl-shape-branch .vertical-cell-row {
3869
+ z-index: 1;
3870
+ }
3871
+ /* condition diamond — the decision shape, "if" / "elif" chained down the spine */
3872
+ .dl-cond-diamond {
3873
+ position: relative;
3874
+ display: inline-grid;
3875
+ place-items: center;
3876
+ width: 40px;
3877
+ height: 40px;
3878
+ flex-shrink: 0;
3879
+ margin: -3px 4px -3px 0;
3880
+ }
3881
+ .dl-cond-diamond svg {
3882
+ position: absolute;
3883
+ inset: 0;
3884
+ width: 100%;
3885
+ height: 100%;
3886
+ overflow: visible;
3887
+ }
3888
+ .dl-cond-diamond svg path {
3889
+ fill: var(--accent-soft);
3890
+ stroke: var(--accent);
3891
+ stroke-width: 1.5;
3892
+ }
3893
+ .dl-cond-label {
3894
+ position: relative;
3895
+ z-index: 1;
3896
+ font-family: var(--font-mono);
3897
+ font-weight: 700;
3898
+ font-size: 10px;
3899
+ letter-spacing: 0.02em;
3900
+ color: var(--accent);
3901
+ }
3902
+ /* Then / Else rails sit indented under the diamond, colour-coded */
3903
+ .vertical-cell-row.branch-rail-then,
3904
+ .vertical-cell-row.branch-rail-else {
3905
+ padding-left: 48px;
3906
+ }
3907
+ .branch-rail-then .vertical-cell-row-icon { color: var(--sig-bool-true); }
3908
+ .branch-rail-else .vertical-cell-row-icon { color: var(--sig-bool-false); }
3909
+ .branch-rail-then .vertical-cell-row-label,
3910
+ .branch-rail-else .vertical-cell-row-label {
3911
+ text-transform: uppercase;
3912
+ letter-spacing: 0.08em;
3913
+ font-size: 9.5px;
3914
+ }
3915
+
3250
3916
  /* Header right section for result badge and collapse toggle */
3251
3917
  .header-right {
3252
3918
  display: flex;
@@ -3259,7 +3925,7 @@ svg.react-flow__connectionline {
3259
3925
  .collapse-toggle {
3260
3926
  background: transparent;
3261
3927
  border: none;
3262
- color: white;
3928
+ color: var(--muted);
3263
3929
  font-size: 10px;
3264
3930
  cursor: pointer;
3265
3931
  padding: 2px 6px;
@@ -3274,7 +3940,7 @@ svg.react-flow__connectionline {
3274
3940
 
3275
3941
  /* Expression text for collapsed nodes */
3276
3942
  .expression-text {
3277
- font-family: 'SF Mono', 'Consolas', monospace;
3943
+ font-family: var(--font-mono);
3278
3944
  font-size: 12px;
3279
3945
  color: var(--text-primary);
3280
3946
  padding: 4px 8px;
@@ -3318,7 +3984,7 @@ svg.react-flow__connectionline {
3318
3984
  }
3319
3985
 
3320
3986
  .arg-label {
3321
- font-family: 'SF Mono', 'Consolas', monospace;
3987
+ font-family: var(--font-mono);
3322
3988
  color: var(--text-primary);
3323
3989
  white-space: nowrap;
3324
3990
  overflow: hidden;
@@ -3330,7 +3996,7 @@ svg.react-flow__connectionline {
3330
3996
  ============================================ */
3331
3997
 
3332
3998
  .literal-node {
3333
- padding: 8px 12px;
3999
+ padding: 8px 12px 8px 15px;
3334
4000
  }
3335
4001
 
3336
4002
  .literal-node-content {
@@ -3347,7 +4013,7 @@ svg.react-flow__connectionline {
3347
4013
  }
3348
4014
 
3349
4015
  .literal-value {
3350
- font-family: 'SF Mono', 'Consolas', monospace;
4016
+ font-family: var(--font-mono);
3351
4017
  font-size: 13px;
3352
4018
  color: var(--text-primary);
3353
4019
  word-break: break-all;
@@ -3364,33 +4030,38 @@ svg.react-flow__connectionline {
3364
4030
  }
3365
4031
 
3366
4032
  .structure-node-header {
3367
- padding: 6px 12px;
3368
- border-radius: calc(var(--radius-md) - 2px) calc(var(--radius-md) - 2px) 0 0;
3369
- color: white;
4033
+ padding: 6px 12px 6px 15px;
4034
+ color: var(--ink);
3370
4035
  display: flex;
3371
4036
  align-items: center;
3372
4037
  gap: 8px;
3373
4038
  height: 32px;
3374
4039
  box-sizing: border-box;
4040
+ border-bottom: 1px solid var(--hairline-2);
3375
4041
  }
3376
4042
 
3377
4043
  .structure-node-icon {
3378
- font-size: 14px;
3379
- display: flex;
3380
- align-items: center;
4044
+ width: 20px;
4045
+ height: 20px;
4046
+ border-radius: 6px;
4047
+ display: grid;
4048
+ place-items: center;
4049
+ color: var(--dl-sig);
4050
+ background: color-mix(in srgb, var(--dl-sig) 14%, transparent);
3381
4051
  }
3382
4052
 
3383
4053
  .structure-node-label {
3384
4054
  font-weight: 600;
3385
- font-size: 14px;
3386
- letter-spacing: 0.5px;
4055
+ font-size: 13px;
4056
+ letter-spacing: -0.01em;
3387
4057
  flex: 1;
4058
+ color: var(--ink);
3388
4059
  }
3389
4060
 
3390
4061
  .structure-node-body {
3391
4062
  padding: 8px 12px;
3392
4063
  padding-right: 24px;
3393
- font-family: 'SF Mono', 'Consolas', monospace;
4064
+ font-family: var(--font-mono);
3394
4065
  font-size: 12px;
3395
4066
  white-space: pre;
3396
4067
  line-height: 18px;
@@ -3473,20 +4144,17 @@ svg.react-flow__connectionline {
3473
4144
  bottom: -6px;
3474
4145
  }
3475
4146
 
4147
+ /* input handles (connection to parent) now sit on the RIGHT, centred */
3476
4148
  .react-flow__handle-right {
3477
4149
  right: -6px;
3478
- }
3479
-
3480
- .react-flow__handle-left {
3481
- left: -6px;
3482
4150
  top: 50% !important;
3483
4151
  transform: translateY(-50%) !important;
3484
4152
  }
3485
4153
 
3486
- /* Ensure left handles are centered on simple nodes */
3487
- .literal-node .react-flow__handle-left {
3488
- top: 50% !important;
3489
- transform: translateY(-50%) !important;
4154
+ /* left handles are the per-cell branch handles — their vertical position is set
4155
+ inline / by .cell-handle, so do NOT force-centre them here */
4156
+ .react-flow__handle-left {
4157
+ left: -6px;
3490
4158
  }
3491
4159
 
3492
4160
  /* Edge styles */
@@ -3514,7 +4182,7 @@ svg.react-flow__connectionline {
3514
4182
  padding: 2px 8px;
3515
4183
  border-radius: 4px;
3516
4184
  font-size: 11px;
3517
- font-family: 'SF Mono', 'Consolas', monospace;
4185
+ font-family: var(--font-mono);
3518
4186
  font-weight: 500;
3519
4187
  max-width: 120px;
3520
4188
  overflow: hidden;
@@ -3557,7 +4225,7 @@ svg.react-flow__connectionline {
3557
4225
  margin: 0;
3558
4226
  white-space: pre-wrap;
3559
4227
  word-break: break-word;
3560
- font-family: 'SF Mono', 'Consolas', monospace;
4228
+ font-family: var(--font-mono);
3561
4229
  }
3562
4230
 
3563
4231
  .result-popover.error {
@@ -3776,17 +4444,34 @@ svg.react-flow__connectionline {
3776
4444
 
3777
4445
  .debug-info-bubble {
3778
4446
  position: absolute;
3779
- background: var(--debug-popover-bg);
3780
- color: var(--debug-popover-text);
3781
- border-radius: var(--radius-md);
3782
- padding: 10px 12px;
4447
+ width: 264px;
4448
+ max-width: 300px;
4449
+ background: var(--chip);
4450
+ color: var(--ink-2);
4451
+ border: 1px solid var(--hairline);
4452
+ border-radius: 11px;
4453
+ padding: 0;
4454
+ font-family: var(--font-mono);
3783
4455
  font-size: 11px;
3784
4456
  z-index: 9999;
3785
4457
  box-shadow: var(--shadow-lg);
3786
- min-width: 180px;
3787
- max-width: 280px;
3788
4458
  pointer-events: auto;
3789
4459
  }
4460
+ /* signal rail — accent by default, red on error (design-system .pop::before) */
4461
+ .debug-info-bubble::before {
4462
+ content: "";
4463
+ position: absolute;
4464
+ left: 0;
4465
+ top: 8px;
4466
+ bottom: 8px;
4467
+ width: 3px;
4468
+ border-radius: 3px;
4469
+ background: var(--accent);
4470
+ z-index: 1;
4471
+ }
4472
+ .debug-info-bubble.error::before {
4473
+ background: var(--sig-bool-false);
4474
+ }
3790
4475
 
3791
4476
  .debug-info-bubble.debug-info-top {
3792
4477
  bottom: 100%;
@@ -3870,45 +4555,61 @@ svg.react-flow__connectionline {
3870
4555
  }
3871
4556
 
3872
4557
  .debug-info-iteration {
3873
- font-size: 10px;
3874
- font-weight: 600;
3875
- color: var(--debug-iteration-color);
3876
- margin-bottom: 8px;
3877
- padding-bottom: 6px;
3878
- border-bottom: 1px solid var(--debug-border-color);
4558
+ display: flex;
4559
+ align-items: center;
4560
+ gap: 5px;
4561
+ font-family: var(--font-ui);
4562
+ font-size: 9.5px;
4563
+ font-weight: 700;
4564
+ letter-spacing: 0.04em;
4565
+ color: var(--sig-collection);
4566
+ padding: 8px 12px 8px 15px;
4567
+ border-bottom: 1px solid var(--hairline-2);
3879
4568
  }
3880
4569
 
3881
4570
  .debug-info-section {
3882
- margin-bottom: 8px;
4571
+ padding: 9px 12px 9px 15px;
4572
+ border-bottom: 1px solid var(--hairline-2);
3883
4573
  }
3884
4574
 
3885
4575
  .debug-info-section:last-child {
3886
- margin-bottom: 0;
4576
+ border-bottom: none;
3887
4577
  }
3888
4578
 
3889
4579
  .debug-info-label {
3890
- display: block;
3891
- font-size: 10px;
3892
- font-weight: 600;
3893
- color: var(--debug-label-color);
4580
+ display: flex;
4581
+ align-items: center;
4582
+ font-family: var(--font-ui);
4583
+ font-size: 9.5px;
4584
+ font-weight: 700;
4585
+ color: var(--muted);
3894
4586
  text-transform: uppercase;
3895
- letter-spacing: 0.5px;
3896
- margin-bottom: 4px;
4587
+ letter-spacing: 0.1em;
4588
+ margin-bottom: 6px;
3897
4589
  }
3898
4590
 
3899
4591
  .debug-info-value {
3900
4592
  margin: 0;
3901
- padding: 4px 6px;
3902
- background: var(--debug-popover-value-bg);
3903
- border-radius: 4px;
3904
- font-family: 'SF Mono', 'Consolas', monospace;
3905
- font-size: 10px;
4593
+ padding: 7px 9px;
4594
+ background: var(--surface-2);
4595
+ border: 1px solid var(--hairline-2);
4596
+ border-radius: 7px;
4597
+ font-family: var(--font-mono);
4598
+ font-size: 10.5px;
4599
+ line-height: 1.6;
4600
+ color: var(--ink-2);
3906
4601
  white-space: pre-wrap;
3907
4602
  word-break: break-word;
3908
- max-height: 100px;
4603
+ max-height: 116px;
3909
4604
  overflow: auto;
3910
4605
  }
3911
4606
 
4607
+ .debug-info-simple-value {
4608
+ font-family: var(--font-mono);
4609
+ font-size: 18px;
4610
+ font-weight: 700;
4611
+ }
4612
+
3912
4613
  /* Custom scrollbar styling */
3913
4614
  .debug-info-value::-webkit-scrollbar {
3914
4615
  width: 6px;
@@ -3968,7 +4669,7 @@ svg.react-flow__connectionline {
3968
4669
  }
3969
4670
 
3970
4671
  .debug-info-simple-value {
3971
- font-family: 'SF Mono', 'Consolas', monospace;
4672
+ font-family: var(--font-mono);
3972
4673
  font-size: 12px;
3973
4674
  font-weight: 500;
3974
4675
  }
@@ -4070,6 +4771,45 @@ svg.react-flow__connectionline {
4070
4771
  cursor: pointer;
4071
4772
  }
4072
4773
 
4774
+ /* Direction toggle — a compact segmented control: Data flow ⇄ Hierarchy */
4775
+ .logic-editor-toolbar .dl-direction-toggle {
4776
+ display: inline-flex;
4777
+ align-items: center;
4778
+ flex-shrink: 0;
4779
+ border: 1px solid var(--hairline, #ddd);
4780
+ border-radius: var(--radius-sm, 6px);
4781
+ overflow: hidden;
4782
+ }
4783
+
4784
+ .logic-editor-toolbar .dl-direction-toggle button {
4785
+ appearance: none;
4786
+ border: none;
4787
+ background: transparent;
4788
+ color: var(--text-secondary, #666);
4789
+ font: inherit;
4790
+ font-size: 12px;
4791
+ line-height: 1;
4792
+ padding: 4px 10px;
4793
+ cursor: pointer;
4794
+ white-space: nowrap;
4795
+ transition: background var(--motion-fast) var(--ease-out),
4796
+ color var(--motion-fast) var(--ease-out);
4797
+ }
4798
+
4799
+ .logic-editor-toolbar .dl-direction-toggle button + button {
4800
+ border-left: 1px solid var(--hairline, #ddd);
4801
+ }
4802
+
4803
+ .logic-editor-toolbar .dl-direction-toggle button:hover:not(.active) {
4804
+ background: var(--bg-hover, #f0f0f0);
4805
+ color: var(--text-primary, #1a1a1a);
4806
+ }
4807
+
4808
+ .logic-editor-toolbar .dl-direction-toggle button.active {
4809
+ background: var(--accent, #6366f1);
4810
+ color: #fff;
4811
+ }
4812
+
4073
4813
  /* Shared toolbar button style (undo/redo, etc.) */
4074
4814
  .dl-toolbar-btn {
4075
4815
  display: flex;
@@ -4312,8 +5052,8 @@ svg.react-flow__connectionline {
4312
5052
  gap: 4px;
4313
5053
  padding: 4px 8px;
4314
5054
  margin: 4px 8px 8px;
4315
- border: 1.5px dashed var(--color-primary, #2563eb);
4316
- border-radius: 4px;
5055
+ border: 1.5px dashed color-mix(in srgb, var(--accent) 55%, var(--hairline));
5056
+ border-radius: var(--radius-sm);
4317
5057
  background: transparent;
4318
5058
  color: var(--color-primary, #2563eb);
4319
5059
  font-size: 11px;