flexdesk 0.5.0 → 0.6.1

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 (70) hide show
  1. package/README.md +654 -1
  2. package/css/base.css +2868 -0
  3. package/css/flexdesk.css +2868 -0
  4. package/css/tokens.css +72 -0
  5. package/dist/canvas.js +390 -0
  6. package/dist/canvas.js.map +7 -0
  7. package/dist/charts.js +2 -2
  8. package/dist/{chunk-24MS7W5Y.js → chunk-6NG7YVBG.js} +2 -470
  9. package/dist/chunk-6NG7YVBG.js.map +7 -0
  10. package/dist/chunk-H4LT43RS.js +475 -0
  11. package/dist/chunk-H4LT43RS.js.map +7 -0
  12. package/dist/{chunk-KH2GJTKR.js → chunk-IYV5JVYB.js} +29 -1
  13. package/dist/chunk-IYV5JVYB.js.map +7 -0
  14. package/dist/chunk-SN4LSOAR.js +532 -0
  15. package/dist/chunk-SN4LSOAR.js.map +7 -0
  16. package/dist/{chunk-CNXP3SIN.js → chunk-ZMCRDOCF.js} +2 -2
  17. package/dist/flexdesk.css +2868 -0
  18. package/dist/flow.js +10030 -0
  19. package/dist/flow.js.map +7 -0
  20. package/dist/tiles.js +9 -9
  21. package/dist/tokens.css +72 -0
  22. package/dist/widgets.js +87 -5
  23. package/dist/widgets.js.map +3 -3
  24. package/dist/wm.js +4 -2
  25. package/dist/wm.js.map +1 -1
  26. package/package.json +9 -1
  27. package/src/canvas/canvas_adapter.js +523 -0
  28. package/src/canvas/edge_router.js +392 -0
  29. package/src/canvas/graph/connector_router.js +189 -0
  30. package/src/canvas/graph/history_service.js +170 -0
  31. package/src/canvas/graph/node_platform.js +116 -0
  32. package/src/canvas/index.js +16 -0
  33. package/src/flow/canvas_editor/editor.js +1081 -0
  34. package/src/flow/canvas_editor/index.js +16 -0
  35. package/src/flow/canvas_editor/layout.js +118 -0
  36. package/src/flow/canvas_editor/strings.js +37 -0
  37. package/src/flow/kit/always_before.js +325 -0
  38. package/src/flow/kit/catalogue.js +170 -0
  39. package/src/flow/kit/chip_input.js +461 -0
  40. package/src/flow/kit/dom.js +205 -0
  41. package/src/flow/kit/findings.js +129 -0
  42. package/src/flow/kit/history.js +173 -0
  43. package/src/flow/kit/index.js +38 -0
  44. package/src/flow/kit/keys.js +127 -0
  45. package/src/flow/kit/logic_graph.js +210 -0
  46. package/src/flow/kit/references.js +199 -0
  47. package/src/flow/kit/settings_panel.js +357 -0
  48. package/src/flow/kit/settings_schema.js +175 -0
  49. package/src/flow/kit/step_picker.js +209 -0
  50. package/src/flow/kit/strings.js +102 -0
  51. package/src/flow/kit/value_picker.js +238 -0
  52. package/src/flow/kit/widgets.js +763 -0
  53. package/src/flow/lanes/editor.js +1469 -0
  54. package/src/flow/lanes/index.js +26 -0
  55. package/src/flow/lanes/layout.js +525 -0
  56. package/src/flow/lanes/pipeline.js +327 -0
  57. package/src/flow/lanes/preview.js +109 -0
  58. package/src/flow/lanes/strings.js +98 -0
  59. package/src/flow/outline/editor.js +1511 -0
  60. package/src/flow/outline/index.js +20 -0
  61. package/src/flow/outline/mapping.js +286 -0
  62. package/src/flow/outline/menu.js +154 -0
  63. package/src/flow/outline/operations.js +738 -0
  64. package/src/flow/outline/recognise.js +755 -0
  65. package/src/flow/outline/strings.js +135 -0
  66. package/src/ui/components/data_table.js +40 -0
  67. package/src/ui/utils/scroll_lock.js +111 -0
  68. package/dist/chunk-24MS7W5Y.js.map +0 -7
  69. package/dist/chunk-KH2GJTKR.js.map +0 -7
  70. /package/dist/{chunk-CNXP3SIN.js.map → chunk-ZMCRDOCF.js.map} +0 -0
package/css/base.css CHANGED
@@ -686,6 +686,39 @@ body.twm-dt-col-resizing {
686
686
  color: var(--text-dim, #666);
687
687
  font-style: italic;
688
688
  }
689
+ /* 0.6.1 `diff` — one side of a comparison. A row that is NEW on this side is
690
+ * green, one that is GONE on this side red, a changed row carries an amber
691
+ * left edge and its changed cells an amber fill, and a GAP — the place a row
692
+ * holds on the other side — is hatched, so the eye reads it as "nothing here"
693
+ * rather than as an empty row. (0,3,2) and up, for `twm-dt-cell--null`'s
694
+ * reason above; a selected row keeps its own colour (`:not(.selected)`). */
695
+ .twm-data-table-component .twm-preview-table tbody tr.twm-dt-diff--added:not(.selected) > td {
696
+ background: color-mix(in srgb, var(--color-success, #3fb950) 16%, transparent);
697
+ }
698
+ .twm-data-table-component .twm-preview-table tbody tr.twm-dt-diff--removed:not(.selected) > td {
699
+ background: color-mix(in srgb, var(--color-danger, #c74e4e) 18%, transparent);
700
+ }
701
+ .twm-data-table-component .twm-preview-table tbody tr.twm-dt-diff--removed > td {
702
+ text-decoration: line-through;
703
+ text-decoration-color: color-mix(in srgb, var(--color-danger, #c74e4e) 70%, transparent);
704
+ }
705
+ .twm-data-table-component .twm-preview-table tbody tr.twm-dt-diff--added > td:first-child {
706
+ box-shadow: inset 3px 0 0 0 var(--color-success, #3fb950);
707
+ }
708
+ .twm-data-table-component .twm-preview-table tbody tr.twm-dt-diff--removed > td:first-child {
709
+ box-shadow: inset 3px 0 0 0 var(--color-danger, #c74e4e);
710
+ }
711
+ .twm-data-table-component .twm-preview-table tbody tr.twm-dt-diff--changed > td:first-child {
712
+ box-shadow: inset 3px 0 0 0 var(--color-warning, #ff9800);
713
+ }
714
+ .twm-data-table-component .twm-preview-table tbody tr.twm-dt-diff:not(.selected) > td.twm-dt-diff__cell--changed {
715
+ background: color-mix(in srgb, var(--color-warning, #ff9800) 22%, transparent);
716
+ }
717
+ .twm-data-table-component .twm-preview-table tbody tr.twm-dt-diff--gap > td.twm-dt-diff__gap {
718
+ background: repeating-linear-gradient(135deg,
719
+ transparent 0 6px,
720
+ color-mix(in srgb, var(--text-muted, #888) 14%, transparent) 6px 7px);
721
+ }
689
722
  /* `emptyState` and `setError` with no rows: the box's own words, which may
690
723
  * wrap — muted for an empty state, red for a failure, in both densities. Quiet
691
724
  * while loading — an empty table that is still loading is not empty. */
@@ -5019,3 +5052,2838 @@ button.twm-about-dialog__btn--close:focus {
5019
5052
  .twm-autoscroll-bar--active .twm-autoscroll-thumb {
5020
5053
  background: rgba(255, 255, 255, 0.45);
5021
5054
  }
5055
+
5056
+
5057
+ /* ══ FLOW · KIT ═══════════════════════════════════════════════════════ */
5058
+ /* The shared flow-editor kit (36 §3, §3.12): the settings panel and its
5059
+ * fields, the generic widgets, reference chips and the chip input, the two
5060
+ * pickers and the findings strip. Every colour is a token (`tokens.css`'s
5061
+ * `--twm-flow-*` and the canonical ones); a category's TONE picks a pair.
5062
+ * Every class here is set by a module under src/flow/kit/, and every class
5063
+ * those modules set has a rule here — tests/flow_kit_css.test.mjs holds both
5064
+ * directions, because jsdom applies no stylesheet. */
5065
+
5066
+ /* `hidden` must win over the `display: flex` these blocks use. */
5067
+ .twm-flow-panel[hidden],
5068
+ .twm-flow-panel [hidden],
5069
+ .twm-flow-popover [hidden],
5070
+ .twm-flow-strip[hidden],
5071
+ .twm-flow-strip [hidden] {
5072
+ display: none !important;
5073
+ }
5074
+
5075
+ /* ── the settings panel ─────────────────────────────────────────────── */
5076
+ .twm-flow-panel {
5077
+ display: flex;
5078
+ flex-direction: column;
5079
+ gap: 14px;
5080
+ min-width: 0;
5081
+ box-sizing: border-box;
5082
+ padding: 16px 20px 28px;
5083
+ background: var(--surface-1);
5084
+ color: var(--text-body);
5085
+ font-family: var(--font-family-sans);
5086
+ font-size: var(--font-size-sm);
5087
+ line-height: 1.4;
5088
+ }
5089
+ .twm-flow-panel .twm-btn {
5090
+ min-height: 26px;
5091
+ padding: 0 9px;
5092
+ font-size: var(--font-size-sm);
5093
+ border-radius: 3px;
5094
+ }
5095
+ .twm-flow-panel__readonly {
5096
+ margin: 0;
5097
+ padding: 8px 10px;
5098
+ border-radius: var(--radius-sm);
5099
+ background: var(--twm-flow-warning-bg);
5100
+ border: 1px solid var(--twm-flow-warning-line);
5101
+ color: var(--twm-flow-warning-text);
5102
+ }
5103
+ .twm-flow-panel__head {
5104
+ display: flex;
5105
+ flex-wrap: wrap;
5106
+ gap: 12px;
5107
+ align-items: flex-start;
5108
+ }
5109
+ .twm-flow-panel__icon {
5110
+ flex: 0 0 34px;
5111
+ height: 34px;
5112
+ display: flex;
5113
+ align-items: center;
5114
+ justify-content: center;
5115
+ border-radius: 7px;
5116
+ }
5117
+ .twm-flow-panel__icon .material-symbols-outlined { font-size: 20px; }
5118
+ .twm-flow-panel__icon--violet { background: var(--twm-flow-violet-bg); color: var(--twm-flow-violet-fg); }
5119
+ .twm-flow-panel__icon--teal { background: var(--twm-flow-teal-bg); color: var(--twm-flow-teal-fg); }
5120
+ .twm-flow-panel__icon--amber { background: var(--twm-flow-amber-bg); color: var(--twm-flow-amber-fg); }
5121
+ .twm-flow-panel__icon--grey { background: var(--twm-flow-grey-bg); color: var(--twm-flow-grey-fg); }
5122
+ .twm-flow-panel__icon--blue { background: var(--twm-flow-blue-bg); color: var(--twm-flow-blue-fg); }
5123
+ .twm-flow-panel__icon--indigo { background: var(--twm-flow-indigo-bg); color: var(--twm-flow-indigo-fg); }
5124
+ .twm-flow-panel__titles {
5125
+ flex: 1 1 240px;
5126
+ min-width: 0;
5127
+ display: flex;
5128
+ flex-direction: column;
5129
+ gap: 2px;
5130
+ }
5131
+ .twm-flow-panel__type {
5132
+ font-size: var(--font-size-xs);
5133
+ color: var(--twm-flow-muted);
5134
+ text-transform: uppercase;
5135
+ letter-spacing: .05em;
5136
+ }
5137
+ .twm-flow-panel__title {
5138
+ margin: 0;
5139
+ font-size: 17px;
5140
+ font-weight: var(--font-weight-semibold);
5141
+ color: var(--text-primary);
5142
+ overflow-wrap: anywhere;
5143
+ }
5144
+ .twm-flow-panel__title-input {
5145
+ box-sizing: border-box;
5146
+ width: 100%;
5147
+ margin-left: -5px;
5148
+ padding: 1px 4px;
5149
+ font: inherit;
5150
+ font-size: 17px;
5151
+ font-weight: var(--font-weight-semibold);
5152
+ color: var(--text-primary);
5153
+ background: transparent;
5154
+ border: 1px solid transparent;
5155
+ border-radius: 3px;
5156
+ user-select: text;
5157
+ }
5158
+ .twm-flow-panel__title-input:hover { border-color: var(--twm-flow-control-border); }
5159
+ .twm-flow-panel__title-input:focus {
5160
+ outline: none;
5161
+ border-color: var(--twm-flow-focus);
5162
+ background: var(--twm-flow-control-bg);
5163
+ }
5164
+ .twm-flow-panel__where { color: var(--twm-flow-muted); }
5165
+ .twm-flow-panel__actions {
5166
+ display: flex;
5167
+ flex-wrap: wrap;
5168
+ gap: 6px;
5169
+ align-items: flex-start;
5170
+ }
5171
+ .twm-flow-panel__action { white-space: nowrap; }
5172
+ .twm-flow-panel__action-wrap {
5173
+ display: inline-flex;
5174
+ flex-direction: column;
5175
+ gap: 2px;
5176
+ max-width: 240px;
5177
+ }
5178
+ .twm-flow-panel__refusal {
5179
+ font-size: var(--font-size-xs);
5180
+ color: var(--twm-flow-warning);
5181
+ }
5182
+ .twm-flow-panel__description { margin: 0; color: var(--text-secondary); }
5183
+ .twm-flow-panel__id {
5184
+ padding: 6px 9px;
5185
+ font-family: var(--font-family-mono);
5186
+ font-size: var(--font-size-xs);
5187
+ color: var(--text-secondary);
5188
+ background: var(--surface-0);
5189
+ border: 1px solid var(--border-default);
5190
+ border-radius: var(--radius-sm);
5191
+ overflow-wrap: anywhere;
5192
+ }
5193
+ .twm-flow-panel__findings {
5194
+ margin: 0;
5195
+ padding: 0;
5196
+ list-style: none;
5197
+ display: flex;
5198
+ flex-direction: column;
5199
+ gap: 4px;
5200
+ }
5201
+ .twm-flow-panel__finding {
5202
+ display: flex;
5203
+ gap: 6px;
5204
+ align-items: flex-start;
5205
+ color: var(--twm-flow-error);
5206
+ }
5207
+ .twm-flow-panel__finding--warning { color: var(--twm-flow-warning); }
5208
+ .twm-flow-panel__finding-icon.material-symbols-outlined { font-size: 15px; line-height: 18px; }
5209
+ .twm-flow-panel__finding-text { min-width: 0; overflow-wrap: anywhere; }
5210
+ .twm-flow-panel__slot {
5211
+ display: flex;
5212
+ flex-direction: column;
5213
+ gap: 8px;
5214
+ min-width: 0;
5215
+ }
5216
+ .twm-flow-panel__fields {
5217
+ display: flex;
5218
+ flex-direction: column;
5219
+ gap: 13px;
5220
+ }
5221
+ .twm-flow-panel__note {
5222
+ margin: 0;
5223
+ padding: 8px 10px;
5224
+ border-radius: var(--radius-sm);
5225
+ background: var(--state-hover);
5226
+ color: var(--text-secondary);
5227
+ }
5228
+ .twm-flow-panel__note--info { border-left: 2px solid var(--twm-flow-blue-line); }
5229
+ .twm-flow-panel__note--warning {
5230
+ background: var(--twm-flow-warning-bg);
5231
+ color: var(--twm-flow-warning-text);
5232
+ }
5233
+
5234
+ /* ── a field: its label, its control, its finding, its help ─────────── */
5235
+ .twm-flow-field {
5236
+ display: flex;
5237
+ flex-wrap: wrap;
5238
+ gap: 4px 16px;
5239
+ align-items: flex-start;
5240
+ min-width: 0;
5241
+ }
5242
+ .twm-flow-field__label {
5243
+ flex: 0 0 150px;
5244
+ min-width: 0;
5245
+ padding-top: 5px;
5246
+ color: var(--text-secondary);
5247
+ }
5248
+ .twm-flow-field__name { overflow-wrap: anywhere; }
5249
+ .twm-flow-field__required { color: var(--twm-flow-error); }
5250
+ .twm-flow-field__body {
5251
+ flex: 1 1 280px;
5252
+ min-width: 0;
5253
+ display: flex;
5254
+ flex-direction: column;
5255
+ gap: 5px;
5256
+ }
5257
+ .twm-flow-field__error {
5258
+ margin: 0;
5259
+ display: flex;
5260
+ gap: 5px;
5261
+ align-items: flex-start;
5262
+ color: var(--twm-flow-error);
5263
+ }
5264
+ .twm-flow-field__error-icon.material-symbols-outlined { font-size: 15px; line-height: 17px; }
5265
+ .twm-flow-field__error-text { min-width: 0; overflow-wrap: anywhere; }
5266
+ .twm-flow-field--warning .twm-flow-field__error { color: var(--twm-flow-warning); }
5267
+ .twm-flow-field--error > .twm-flow-field__body > .twm-flow-input,
5268
+ .twm-flow-field--error > .twm-flow-field__body > .twm-flow-refbox,
5269
+ .twm-flow-field--error > .twm-flow-field__body > .twm-flow-togglechips {
5270
+ border-color: var(--twm-flow-error);
5271
+ }
5272
+ .twm-flow-field__help {
5273
+ margin: 0;
5274
+ font-size: var(--font-size-xs);
5275
+ color: var(--twm-flow-muted);
5276
+ }
5277
+ .twm-flow-field__note {
5278
+ margin: 0;
5279
+ padding-top: 5px;
5280
+ font-size: var(--font-size-xs);
5281
+ color: var(--twm-flow-muted);
5282
+ }
5283
+ .twm-flow-field__kept {
5284
+ font-family: var(--font-family-mono);
5285
+ color: var(--text-secondary);
5286
+ }
5287
+ .twm-flow-field__refusal {
5288
+ margin: 0;
5289
+ padding: 6px 8px;
5290
+ border-radius: var(--radius-sm);
5291
+ background: var(--twm-flow-warning-bg);
5292
+ border: 1px solid var(--twm-flow-warning-line);
5293
+ color: var(--twm-flow-warning-text);
5294
+ }
5295
+ .twm-flow-field--group > .twm-flow-field__body { gap: 8px; }
5296
+ .twm-flow-field__group {
5297
+ display: flex;
5298
+ flex-direction: column;
5299
+ gap: 8px;
5300
+ min-width: 0;
5301
+ }
5302
+ .twm-flow-field__group > .twm-flow-field__summary {
5303
+ display: flex;
5304
+ align-items: center;
5305
+ gap: 6px;
5306
+ min-height: 26px;
5307
+ color: var(--text-secondary);
5308
+ cursor: pointer;
5309
+ list-style: none;
5310
+ }
5311
+ .twm-flow-field__group > .twm-flow-field__summary::-webkit-details-marker { display: none; }
5312
+ .twm-flow-field__group > .twm-flow-field__summary::before {
5313
+ content: '▸';
5314
+ flex: 0 0 auto;
5315
+ color: var(--twm-flow-muted);
5316
+ }
5317
+ .twm-flow-field__group[open] > .twm-flow-field__summary::before { content: '▾'; }
5318
+ .twm-flow-field__group > .twm-flow-field__summary:focus-visible {
5319
+ outline: 2px solid var(--twm-flow-focus);
5320
+ outline-offset: 1px;
5321
+ }
5322
+ .twm-flow-field__summary-text {
5323
+ min-width: 0;
5324
+ color: var(--twm-flow-muted);
5325
+ overflow-wrap: anywhere;
5326
+ }
5327
+ .twm-flow-field__group > .twm-flow-field > .twm-flow-field__label { flex-basis: 120px; }
5328
+ .twm-flow-field__rows {
5329
+ display: flex;
5330
+ flex-direction: column;
5331
+ gap: 5px;
5332
+ min-width: 0;
5333
+ }
5334
+ .twm-flow-field__row {
5335
+ display: flex;
5336
+ gap: 6px;
5337
+ align-items: center;
5338
+ min-width: 0;
5339
+ }
5340
+ .twm-flow-field__row > .twm-flow-input { flex: 0 0 34%; min-width: 0; }
5341
+ .twm-flow-field__row > .twm-flow-input--select { flex: 0 0 auto; width: auto; }
5342
+ .twm-flow-field__row > .twm-flow-refbox { flex: 1 1 auto; }
5343
+ .twm-flow-field__slot {
5344
+ display: flex;
5345
+ flex: 1 1 auto;
5346
+ min-width: 0;
5347
+ }
5348
+ .twm-flow-field__slot > .twm-flow-refbox { flex: 1 1 auto; }
5349
+ .twm-flow-field__add { align-self: flex-start; border-style: dashed; }
5350
+ .twm-flow-field__remove { flex: 0 0 26px; padding: 0; }
5351
+ .twm-flow-field__remove .twm-btn__glyph.material-symbols-outlined { font-size: 15px; }
5352
+
5353
+ /* ── controls ───────────────────────────────────────────────────────── */
5354
+ .twm-flow-input {
5355
+ box-sizing: border-box;
5356
+ width: 100%;
5357
+ min-width: 0;
5358
+ height: 26px;
5359
+ padding: 0 8px;
5360
+ font: inherit;
5361
+ font-size: var(--font-size-sm);
5362
+ color: var(--text-primary);
5363
+ background: var(--twm-flow-control-bg);
5364
+ border: 1px solid var(--twm-flow-control-border);
5365
+ border-radius: 3px;
5366
+ user-select: text;
5367
+ }
5368
+ .twm-flow-input:focus {
5369
+ outline: none;
5370
+ border-color: var(--twm-flow-focus);
5371
+ box-shadow: 0 0 0 1px var(--twm-flow-focus);
5372
+ }
5373
+ .twm-flow-input:disabled { opacity: 0.6; cursor: not-allowed; }
5374
+ .twm-flow-input--select { padding-right: 4px; cursor: pointer; }
5375
+ .twm-flow-input--area {
5376
+ height: auto;
5377
+ min-height: 52px;
5378
+ padding: 5px 8px;
5379
+ line-height: 1.4;
5380
+ resize: vertical;
5381
+ }
5382
+ .twm-flow-checkbox {
5383
+ margin: 6px 0 0;
5384
+ accent-color: var(--twm-flow-focus);
5385
+ }
5386
+
5387
+ /* ── a chip input, and the box with its Insert a value ──────────────── */
5388
+ .twm-flow-refbox {
5389
+ display: flex;
5390
+ align-items: flex-start;
5391
+ gap: 6px;
5392
+ min-width: 0;
5393
+ min-height: 26px;
5394
+ box-sizing: border-box;
5395
+ padding: 3px 4px 3px 8px;
5396
+ background: var(--twm-flow-control-bg);
5397
+ border: 1px solid var(--twm-flow-control-border);
5398
+ border-radius: 3px;
5399
+ }
5400
+ .twm-flow-refbox:focus-within {
5401
+ border-color: var(--twm-flow-focus);
5402
+ box-shadow: 0 0 0 1px var(--twm-flow-focus);
5403
+ }
5404
+ .twm-flow-refbox--mono { background: var(--surface-0); }
5405
+ .twm-flow-refbox__insert {
5406
+ flex: 0 0 auto;
5407
+ height: 20px;
5408
+ padding: 0 6px;
5409
+ font-family: var(--font-family-mono);
5410
+ font-size: var(--font-size-xs);
5411
+ color: var(--twm-flow-blue-fg);
5412
+ background: var(--surface-2);
5413
+ border: 1px solid var(--twm-flow-control-border);
5414
+ border-radius: 3px;
5415
+ cursor: pointer;
5416
+ }
5417
+ .twm-flow-refbox__insert:hover { border-color: var(--twm-flow-focus); }
5418
+ .twm-flow-refbox__insert:focus-visible {
5419
+ outline: 2px solid var(--twm-flow-focus);
5420
+ outline-offset: 1px;
5421
+ }
5422
+ .twm-flow-chipinput {
5423
+ position: relative;
5424
+ flex: 1 1 auto;
5425
+ min-width: 0;
5426
+ min-height: 18px;
5427
+ line-height: 18px;
5428
+ color: var(--text-primary);
5429
+ white-space: pre-wrap;
5430
+ overflow-wrap: anywhere;
5431
+ outline: none;
5432
+ cursor: text;
5433
+ -webkit-user-select: text;
5434
+ user-select: text;
5435
+ }
5436
+ .twm-flow-chipinput--mono {
5437
+ font-family: var(--font-family-mono);
5438
+ font-size: var(--font-size-sm);
5439
+ line-height: 21px;
5440
+ }
5441
+ .twm-flow-chipinput--multiline { min-height: 36px; }
5442
+ .twm-flow-chipinput--empty::before {
5443
+ content: attr(data-placeholder);
5444
+ position: absolute;
5445
+ left: 0;
5446
+ top: 0;
5447
+ color: var(--text-muted);
5448
+ pointer-events: none;
5449
+ }
5450
+ .twm-flow-chipinput[contenteditable="false"] { cursor: default; }
5451
+ .twm-flow-chip {
5452
+ display: inline-flex;
5453
+ align-items: center;
5454
+ height: 18px;
5455
+ padding: 0 6px;
5456
+ margin: 0 1px;
5457
+ box-sizing: border-box;
5458
+ border: 1px solid transparent;
5459
+ border-radius: 3px;
5460
+ font-family: var(--font-family-sans);
5461
+ font-size: var(--font-size-xs);
5462
+ line-height: 16px;
5463
+ white-space: nowrap;
5464
+ vertical-align: baseline;
5465
+ cursor: default;
5466
+ }
5467
+ .twm-flow-chip--violet { background: var(--twm-flow-violet-bg); border-color: var(--twm-flow-violet-line); color: var(--twm-flow-violet-fg); }
5468
+ .twm-flow-chip--teal { background: var(--twm-flow-teal-bg); border-color: var(--twm-flow-teal-line); color: var(--twm-flow-teal-fg); }
5469
+ .twm-flow-chip--amber { background: var(--twm-flow-amber-bg); border-color: var(--twm-flow-amber-line); color: var(--twm-flow-amber-fg); }
5470
+ .twm-flow-chip--grey { background: var(--twm-flow-grey-bg); border-color: var(--twm-flow-grey-line); color: var(--twm-flow-grey-fg); }
5471
+ .twm-flow-chip--blue { background: var(--twm-flow-blue-bg); border-color: var(--twm-flow-blue-line); color: var(--twm-flow-blue-fg); }
5472
+ .twm-flow-chip--indigo { background: var(--twm-flow-indigo-bg); border-color: var(--twm-flow-indigo-line); color: var(--twm-flow-indigo-fg); }
5473
+ .twm-flow-chip.twm-flow-chip--unknown {
5474
+ border-style: dashed;
5475
+ border-color: var(--twm-flow-error);
5476
+ color: var(--twm-flow-error);
5477
+ }
5478
+
5479
+ /* ── chips that toggle: enum-chips, upstream-columns ────────────────── */
5480
+ .twm-flow-togglechips {
5481
+ display: flex;
5482
+ flex-wrap: wrap;
5483
+ gap: 4px;
5484
+ align-items: center;
5485
+ min-height: 26px;
5486
+ box-sizing: border-box;
5487
+ padding: 3px 6px;
5488
+ background: var(--twm-flow-control-bg);
5489
+ border: 1px solid var(--twm-flow-control-border);
5490
+ border-radius: 3px;
5491
+ }
5492
+ .twm-flow-togglechip {
5493
+ height: 18px;
5494
+ padding: 0 8px;
5495
+ font: inherit;
5496
+ font-size: var(--font-size-xs);
5497
+ color: var(--twm-flow-muted);
5498
+ background: transparent;
5499
+ border: 1px solid var(--border-strong);
5500
+ border-radius: 9px;
5501
+ cursor: pointer;
5502
+ }
5503
+ .twm-flow-togglechip[aria-pressed="true"] {
5504
+ color: var(--text-primary);
5505
+ background: var(--surface-3);
5506
+ border-color: var(--surface-3);
5507
+ }
5508
+ .twm-flow-togglechip.twm-flow-togglechip--missing {
5509
+ border-style: dashed;
5510
+ border-color: var(--twm-flow-warning);
5511
+ color: var(--twm-flow-warning);
5512
+ }
5513
+ .twm-flow-togglechip:disabled { cursor: default; opacity: 0.7; }
5514
+ .twm-flow-togglechip:focus-visible {
5515
+ outline: 2px solid var(--twm-flow-focus);
5516
+ outline-offset: 1px;
5517
+ }
5518
+
5519
+ /* ── choice-cards ───────────────────────────────────────────────────── */
5520
+ .twm-flow-choices {
5521
+ display: flex;
5522
+ flex-direction: column;
5523
+ gap: 6px;
5524
+ padding-top: 4px;
5525
+ }
5526
+ .twm-flow-choice {
5527
+ display: flex;
5528
+ align-items: flex-start;
5529
+ gap: 8px;
5530
+ color: var(--text-primary);
5531
+ cursor: pointer;
5532
+ }
5533
+ .twm-flow-choice__radio {
5534
+ flex: 0 0 auto;
5535
+ margin: 2px 0 0;
5536
+ accent-color: var(--twm-flow-focus);
5537
+ }
5538
+ .twm-flow-choice__words {
5539
+ display: flex;
5540
+ flex-direction: column;
5541
+ gap: 1px;
5542
+ min-width: 0;
5543
+ }
5544
+ .twm-flow-choice__label { overflow-wrap: anywhere; }
5545
+ .twm-flow-choice__sub {
5546
+ font-size: var(--font-size-xs);
5547
+ color: var(--twm-flow-muted);
5548
+ }
5549
+
5550
+ /* ── the popover both pickers are drawn in ──────────────────────────── */
5551
+ .twm-flow-popover {
5552
+ position: fixed;
5553
+ z-index: var(--z-popover);
5554
+ display: flex;
5555
+ flex-direction: column;
5556
+ box-sizing: border-box;
5557
+ max-width: calc(100vw - 16px);
5558
+ max-height: calc(100vh - 16px);
5559
+ background: var(--surface-1);
5560
+ color: var(--text-body);
5561
+ border: 1px solid var(--twm-flow-control-border);
5562
+ border-radius: var(--radius-md);
5563
+ box-shadow: 0 12px 32px rgba(0, 0, 0, 0.55);
5564
+ font-family: var(--font-family-sans);
5565
+ font-size: var(--font-size-sm);
5566
+ line-height: 1.4;
5567
+ outline: none;
5568
+ }
5569
+ .twm-flow-popover--picker { width: 420px; }
5570
+ .twm-flow-popover--values { width: 430px; }
5571
+
5572
+ /* ── the step picker ────────────────────────────────────────────────── */
5573
+ .twm-flow-picker {
5574
+ display: flex;
5575
+ flex-direction: column;
5576
+ flex: 1 1 auto;
5577
+ min-height: 0;
5578
+ }
5579
+ .twm-flow-picker__head {
5580
+ display: flex;
5581
+ flex-direction: column;
5582
+ gap: 2px;
5583
+ padding: 12px 14px 8px;
5584
+ }
5585
+ .twm-flow-picker__title {
5586
+ font-size: var(--font-size-md);
5587
+ font-weight: var(--font-weight-semibold);
5588
+ color: var(--text-primary);
5589
+ }
5590
+ .twm-flow-picker__where { color: var(--twm-flow-muted); }
5591
+ .twm-flow-picker__search,
5592
+ .twm-flow-values__search {
5593
+ display: flex;
5594
+ align-items: center;
5595
+ gap: 6px;
5596
+ height: 28px;
5597
+ box-sizing: border-box;
5598
+ padding: 0 8px;
5599
+ background: var(--surface-0);
5600
+ border: 1px solid var(--twm-flow-control-border);
5601
+ border-radius: 3px;
5602
+ }
5603
+ .twm-flow-picker__search { margin: 0 14px 8px; }
5604
+ .twm-flow-picker__search:focus-within,
5605
+ .twm-flow-values__search:focus-within { border-color: var(--twm-flow-focus); }
5606
+ .twm-flow-picker__search-icon.material-symbols-outlined,
5607
+ .twm-flow-values__search-icon.material-symbols-outlined {
5608
+ font-size: 15px;
5609
+ color: var(--twm-flow-muted);
5610
+ }
5611
+ .twm-flow-picker__input,
5612
+ .twm-flow-values__input {
5613
+ flex: 1 1 auto;
5614
+ min-width: 0;
5615
+ height: 24px;
5616
+ padding: 0;
5617
+ font: inherit;
5618
+ color: var(--text-primary);
5619
+ background: transparent;
5620
+ border: 0;
5621
+ outline: none;
5622
+ user-select: text;
5623
+ }
5624
+ .twm-flow-picker__list {
5625
+ display: flex;
5626
+ flex-direction: column;
5627
+ flex: 1 1 auto;
5628
+ min-height: 0;
5629
+ overflow-y: auto;
5630
+ padding: 0 6px 6px;
5631
+ }
5632
+ .twm-flow-picker__group { display: flex; flex-direction: column; }
5633
+ .twm-flow-picker__group-label {
5634
+ padding: 6px 8px 3px;
5635
+ font-size: 10px;
5636
+ font-weight: var(--font-weight-semibold);
5637
+ letter-spacing: .08em;
5638
+ text-transform: uppercase;
5639
+ color: var(--twm-flow-muted);
5640
+ }
5641
+ .twm-flow-picker__items { display: flex; flex-direction: column; }
5642
+ .twm-flow-picker__items--grid {
5643
+ display: grid;
5644
+ grid-template-columns: repeat(2, minmax(0, 1fr));
5645
+ gap: 0 4px;
5646
+ }
5647
+ .twm-flow-picker__option {
5648
+ display: flex;
5649
+ align-items: center;
5650
+ gap: 10px;
5651
+ padding: 5px 8px;
5652
+ border-radius: var(--radius-sm);
5653
+ color: var(--text-primary);
5654
+ cursor: pointer;
5655
+ }
5656
+ .twm-flow-picker__option:hover { background: var(--state-hover); }
5657
+ .twm-flow-picker__option.twm-flow-picker__option--active { background: var(--state-selected); }
5658
+ .twm-flow-picker__option.twm-flow-picker__option--refused { cursor: not-allowed; }
5659
+ .twm-flow-picker__option--refused .twm-flow-picker__label { color: var(--twm-flow-muted); }
5660
+ .twm-flow-picker__option--refused .twm-flow-picker__chip { opacity: 0.5; }
5661
+ .twm-flow-picker__chip {
5662
+ flex: 0 0 22px;
5663
+ height: 22px;
5664
+ display: flex;
5665
+ align-items: center;
5666
+ justify-content: center;
5667
+ border-radius: 5px;
5668
+ }
5669
+ .twm-flow-picker__chip .material-symbols-outlined { font-size: 15px; }
5670
+ .twm-flow-picker__chip--violet { background: var(--twm-flow-violet-bg); color: var(--twm-flow-violet-fg); }
5671
+ .twm-flow-picker__chip--teal { background: var(--twm-flow-teal-bg); color: var(--twm-flow-teal-fg); }
5672
+ .twm-flow-picker__chip--amber { background: var(--twm-flow-amber-bg); color: var(--twm-flow-amber-fg); }
5673
+ .twm-flow-picker__chip--grey { background: var(--twm-flow-grey-bg); color: var(--twm-flow-grey-fg); }
5674
+ .twm-flow-picker__chip--blue { background: var(--twm-flow-blue-bg); color: var(--twm-flow-blue-fg); }
5675
+ .twm-flow-picker__chip--indigo { background: var(--twm-flow-indigo-bg); color: var(--twm-flow-indigo-fg); }
5676
+ .twm-flow-picker__words {
5677
+ display: flex;
5678
+ flex-direction: column;
5679
+ min-width: 0;
5680
+ }
5681
+ .twm-flow-picker__label { overflow-wrap: anywhere; }
5682
+ .twm-flow-picker__sub,
5683
+ .twm-flow-picker__description {
5684
+ font-size: var(--font-size-xs);
5685
+ color: var(--twm-flow-muted);
5686
+ }
5687
+ .twm-flow-picker__refusal {
5688
+ font-size: var(--font-size-xs);
5689
+ color: var(--twm-flow-warning);
5690
+ }
5691
+ .twm-flow-picker__empty {
5692
+ margin: 0;
5693
+ padding: 4px 14px 10px;
5694
+ color: var(--twm-flow-muted);
5695
+ }
5696
+ .twm-flow-picker__foot {
5697
+ display: flex;
5698
+ flex-wrap: wrap;
5699
+ align-items: center;
5700
+ gap: 6px 14px;
5701
+ padding: 8px 14px;
5702
+ border-top: 1px solid var(--border-strong);
5703
+ font-size: var(--font-size-xs);
5704
+ color: var(--twm-flow-muted);
5705
+ }
5706
+ .twm-flow-picker__keys { flex: 1 1 auto; }
5707
+ .twm-flow-picker__paste {
5708
+ padding: 0;
5709
+ font: inherit;
5710
+ font-size: var(--font-size-xs);
5711
+ color: var(--twm-flow-blue-fg);
5712
+ background: transparent;
5713
+ border: 0;
5714
+ cursor: pointer;
5715
+ }
5716
+ .twm-flow-picker__paste:hover { text-decoration: underline; }
5717
+ .twm-flow-picker__paste:focus-visible {
5718
+ outline: 2px solid var(--twm-flow-focus);
5719
+ outline-offset: 1px;
5720
+ }
5721
+
5722
+ /* ── Insert a value ─────────────────────────────────────────────────── */
5723
+ .twm-flow-values {
5724
+ display: flex;
5725
+ flex-direction: column;
5726
+ flex: 1 1 auto;
5727
+ min-height: 0;
5728
+ }
5729
+ .twm-flow-values__head {
5730
+ display: flex;
5731
+ flex-direction: column;
5732
+ gap: 8px;
5733
+ padding: 12px 14px 8px;
5734
+ }
5735
+ .twm-flow-values__title {
5736
+ font-size: var(--font-size-md);
5737
+ font-weight: var(--font-weight-semibold);
5738
+ color: var(--text-primary);
5739
+ }
5740
+ .twm-flow-values__crumb {
5741
+ display: flex;
5742
+ align-items: center;
5743
+ gap: 8px;
5744
+ padding: 0 14px 6px;
5745
+ }
5746
+ .twm-flow-values__back {
5747
+ display: inline-flex;
5748
+ align-items: center;
5749
+ gap: 2px;
5750
+ height: 22px;
5751
+ padding: 0 6px 0 2px;
5752
+ font: inherit;
5753
+ color: var(--text-secondary);
5754
+ background: transparent;
5755
+ border: 1px solid var(--twm-flow-control-border);
5756
+ border-radius: 3px;
5757
+ cursor: pointer;
5758
+ }
5759
+ .twm-flow-values__back .material-symbols-outlined { font-size: 16px; }
5760
+ .twm-flow-values__back:focus-visible {
5761
+ outline: 2px solid var(--twm-flow-focus);
5762
+ outline-offset: 1px;
5763
+ }
5764
+ .twm-flow-values__path { color: var(--twm-flow-muted); }
5765
+ .twm-flow-values__list {
5766
+ display: flex;
5767
+ flex-direction: column;
5768
+ flex: 1 1 auto;
5769
+ min-height: 0;
5770
+ overflow-y: auto;
5771
+ padding: 0 6px 6px;
5772
+ }
5773
+ .twm-flow-values__group { display: flex; flex-direction: column; }
5774
+ .twm-flow-values__group-label {
5775
+ display: flex;
5776
+ flex-wrap: wrap;
5777
+ align-items: baseline;
5778
+ gap: 6px;
5779
+ padding: 8px 8px 3px;
5780
+ }
5781
+ .twm-flow-values__group-name {
5782
+ font-size: 10px;
5783
+ font-weight: var(--font-weight-semibold);
5784
+ letter-spacing: .08em;
5785
+ text-transform: uppercase;
5786
+ color: var(--twm-flow-muted);
5787
+ }
5788
+ .twm-flow-values__group-sub,
5789
+ .twm-flow-values__group-empty {
5790
+ font-size: var(--font-size-xs);
5791
+ color: var(--twm-flow-muted);
5792
+ }
5793
+ .twm-flow-values__grid {
5794
+ display: grid;
5795
+ grid-template-columns: repeat(2, minmax(0, 1fr));
5796
+ gap: 0 4px;
5797
+ }
5798
+ .twm-flow-values__chips {
5799
+ display: flex;
5800
+ flex-wrap: wrap;
5801
+ gap: 4px;
5802
+ padding: 2px 8px;
5803
+ }
5804
+ .twm-flow-values__option {
5805
+ color: var(--text-primary);
5806
+ cursor: pointer;
5807
+ }
5808
+ .twm-flow-values__option--row {
5809
+ display: flex;
5810
+ justify-content: space-between;
5811
+ gap: 8px;
5812
+ padding: 4px 8px;
5813
+ border-radius: var(--radius-sm);
5814
+ }
5815
+ .twm-flow-values__option--chip {
5816
+ display: inline-flex;
5817
+ align-items: center;
5818
+ height: 22px;
5819
+ box-sizing: border-box;
5820
+ padding: 0 8px;
5821
+ border: 1px solid var(--border-strong);
5822
+ border-radius: 11px;
5823
+ }
5824
+ .twm-flow-values__option:hover { background: var(--state-hover); }
5825
+ .twm-flow-values__option.twm-flow-values__option--active {
5826
+ background: var(--state-selected);
5827
+ box-shadow: inset 0 0 0 1px var(--twm-flow-focus);
5828
+ }
5829
+ .twm-flow-values__label { min-width: 0; overflow-wrap: anywhere; }
5830
+ .twm-flow-values__type {
5831
+ flex: 0 0 auto;
5832
+ font-size: var(--font-size-xs);
5833
+ color: var(--twm-flow-muted);
5834
+ }
5835
+ .twm-flow-values__empty {
5836
+ margin: 0;
5837
+ padding: 8px;
5838
+ color: var(--twm-flow-muted);
5839
+ }
5840
+ .twm-flow-values__foot {
5841
+ display: flex;
5842
+ flex-direction: column;
5843
+ gap: 3px;
5844
+ padding: 8px 14px 10px;
5845
+ border-top: 1px solid var(--border-strong);
5846
+ font-size: var(--font-size-xs);
5847
+ color: var(--twm-flow-muted);
5848
+ }
5849
+ .twm-flow-values__note { overflow-wrap: anywhere; }
5850
+ .twm-flow-values__inserts {
5851
+ min-height: 15px;
5852
+ overflow-wrap: anywhere;
5853
+ }
5854
+
5855
+ /* ── the findings strip ─────────────────────────────────────────────── */
5856
+ .twm-flow-strip {
5857
+ display: flex;
5858
+ flex-direction: column;
5859
+ gap: 4px;
5860
+ padding: 6px 12px;
5861
+ background: var(--twm-flow-error-bg);
5862
+ border-bottom: 1px solid var(--twm-flow-error-line);
5863
+ color: var(--twm-flow-error-text);
5864
+ font-size: var(--font-size-sm);
5865
+ }
5866
+ .twm-flow-strip.twm-flow-strip--warning {
5867
+ background: var(--twm-flow-warning-bg);
5868
+ border-bottom-color: var(--twm-flow-warning-line);
5869
+ color: var(--twm-flow-warning-text);
5870
+ }
5871
+ .twm-flow-strip__head {
5872
+ display: flex;
5873
+ align-items: center;
5874
+ gap: 8px;
5875
+ }
5876
+ .twm-flow-strip__icon.material-symbols-outlined { font-size: 16px; }
5877
+ .twm-flow-strip__title { font-weight: var(--font-weight-semibold); }
5878
+ .twm-flow-strip__list {
5879
+ margin: 0;
5880
+ padding: 0 0 0 24px;
5881
+ list-style: none;
5882
+ display: flex;
5883
+ flex-direction: column;
5884
+ gap: 2px;
5885
+ }
5886
+ .twm-flow-strip__line {
5887
+ display: flex;
5888
+ flex-wrap: wrap;
5889
+ align-items: center;
5890
+ gap: 4px 8px;
5891
+ }
5892
+ .twm-flow-strip__line--warning { color: var(--twm-flow-warning); }
5893
+ .twm-flow-strip__text { min-width: 0; overflow-wrap: anywhere; }
5894
+ .twm-flow-strip .twm-flow-strip__go {
5895
+ min-height: 22px;
5896
+ padding: 0 8px;
5897
+ color: inherit;
5898
+ background: transparent;
5899
+ border-color: var(--twm-flow-error-line);
5900
+ border-radius: 3px;
5901
+ }
5902
+ /* ══ end FLOW · KIT ══ */
5903
+
5904
+
5905
+ /* ══ FLOW · CANVAS ════════════════════════════════════════════════════ */
5906
+ /* Owned by the canvas agent (B) (36 §2): the canvas kernel (twm-canvas,
5907
+ * twm-edge) and the canvas editor (twm-flow-graph). Every class here is set by
5908
+ * a module under src/canvas/ or src/flow/canvas_editor/, and every class those
5909
+ * modules set has a rule here — tests/flow_canvas_css.test.mjs holds both
5910
+ * directions, and holds the node box (208 × 34 + 22 a row) to the editor's
5911
+ * CANVAS_NODE, because the edges are anchored by arithmetic, not measured. */
5912
+
5913
+ /* ── the kernel: the surface ────────────────────────────────────────── */
5914
+ /* The ground is SEVEN background layers, in this order, because
5915
+ * `CanvasAdapter._apply` writes seven sizes and positions: 1. a grain, 2. a
5916
+ * soft light from the upper left, 3–4. a coarse rule every fifth cell, 5–6. a
5917
+ * fine grid — the unit a drag snaps to — and 7. under it all, a gradient. Only
5918
+ * the four GRID layers follow the pan and the zoom. An embedder restyling the
5919
+ * ground keeps seven layers, or the browser cycles a short list and layer 5
5920
+ * takes layer 1's size. */
5921
+ .twm-canvas {
5922
+ position: absolute;
5923
+ inset: 0;
5924
+ overflow: hidden;
5925
+ cursor: default;
5926
+ outline: none;
5927
+ background-color: var(--surface-0);
5928
+ background-image:
5929
+ url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20width%3D%27160%27%20height%3D%27160%27%3E%3Cfilter%20id%3D%27n%27%3E%3CfeTurbulence%20type%3D%27fractalNoise%27%20baseFrequency%3D%270.85%27%20numOctaves%3D%273%27%20stitchTiles%3D%27stitch%27%2F%3E%3CfeColorMatrix%20type%3D%27saturate%27%20values%3D%270%27%2F%3E%3C%2Ffilter%3E%3Crect%20width%3D%27160%27%20height%3D%27160%27%20filter%3D%27url%28%23n%29%27%20opacity%3D%270.5%27%2F%3E%3C%2Fsvg%3E"),
5930
+ radial-gradient(120% 90% at 22% 0%, rgba(255, 255, 255, 0.055) 0%, rgba(255, 255, 255, 0) 55%),
5931
+ linear-gradient(to right, rgba(255, 255, 255, 0.05) 1px, transparent 1px),
5932
+ linear-gradient(to bottom, rgba(255, 255, 255, 0.05) 1px, transparent 1px),
5933
+ linear-gradient(to right, rgba(255, 255, 255, 0.02) 1px, transparent 1px),
5934
+ linear-gradient(to bottom, rgba(255, 255, 255, 0.02) 1px, transparent 1px),
5935
+ linear-gradient(160deg, #2b2e33 0%, #212327 55%, #1b1d20 100%);
5936
+ background-blend-mode: overlay, screen, normal, normal, normal, normal, normal;
5937
+ box-shadow: inset 0 1px 0 rgba(0, 0, 0, 0.55), inset 0 0 120px rgba(0, 0, 0, 0.35);
5938
+ }
5939
+ .twm-canvas:focus-visible {
5940
+ box-shadow: inset 0 0 0 1px var(--twm-flow-focus), inset 0 0 120px rgba(0, 0, 0, 0.35);
5941
+ }
5942
+ .twm-canvas__surface { position: absolute; transform-origin: 0 0; }
5943
+ /* The edge layer takes no pointer: a line that wants one (a hit path) opts
5944
+ * back in with `pointer-events: stroke`. */
5945
+ .twm-canvas__edges { position: absolute; overflow: visible; pointer-events: none; }
5946
+ .twm-canvas__nodes { position: absolute; }
5947
+ .twm-canvas__marquee {
5948
+ position: absolute;
5949
+ pointer-events: none;
5950
+ border: 1px solid var(--accent-bright);
5951
+ background: rgba(0, 122, 204, 0.12);
5952
+ }
5953
+ .twm-canvas__marquee[hidden] { display: none; }
5954
+
5955
+ /* ── the kernel: a crow's foot ──────────────────────────────────────── */
5956
+ .twm-edge__marker line { stroke: #5a7f96; stroke-width: 1.4; }
5957
+ .twm-edge__marker circle { fill: none; stroke: #5a7f96; stroke-width: 1.4; }
5958
+
5959
+ /* ── the canvas editor ──────────────────────────────────────────────── */
5960
+ .twm-flow-graph [hidden] { display: none !important; }
5961
+
5962
+ /* The editor fills its host: a flex column in any parent that gives it a
5963
+ * height. `container-type: inline-size` is for the narrow layouts below, and
5964
+ * safe here: the editor's width comes from its parent, never its contents. */
5965
+ .twm-flow-graph {
5966
+ flex: 1 1 auto;
5967
+ height: 100%;
5968
+ min-height: 0;
5969
+ min-width: 0;
5970
+ display: flex;
5971
+ flex-direction: column;
5972
+ box-sizing: border-box;
5973
+ background: var(--surface-0);
5974
+ color: var(--text-body);
5975
+ font-family: var(--font-family-sans);
5976
+ font-size: var(--font-size-sm);
5977
+ container-type: inline-size;
5978
+ container-name: twm-flow-graph;
5979
+ }
5980
+ .twm-flow-graph__toolbar {
5981
+ display: flex;
5982
+ flex-wrap: wrap;
5983
+ align-items: center;
5984
+ gap: 6px;
5985
+ padding: 6px 8px;
5986
+ background: var(--surface-1);
5987
+ border-bottom: 1px solid var(--border-default);
5988
+ }
5989
+ .twm-flow-graph .twm-flow-graph__tool {
5990
+ min-height: 26px;
5991
+ padding: 0 9px;
5992
+ font-size: var(--font-size-sm);
5993
+ border-radius: 3px;
5994
+ }
5995
+ .twm-flow-graph__tool .twm-btn__glyph.material-symbols-outlined { font-size: 16px; }
5996
+ .twm-flow-graph__tool--busy { cursor: progress; }
5997
+ .twm-flow-graph__status {
5998
+ margin-left: auto;
5999
+ color: var(--twm-flow-muted);
6000
+ font-size: var(--font-size-xs);
6001
+ }
6002
+ .twm-flow-graph__toolbar-end { display: inline-flex; align-items: center; gap: 6px; }
6003
+ .twm-flow-graph__toolbar-end:empty { display: none; }
6004
+ .twm-flow-graph__why,
6005
+ .twm-flow-graph__message,
6006
+ .twm-flow-graph__readonly,
6007
+ .twm-flow-graph__banner {
6008
+ margin: 0;
6009
+ padding: 4px 10px;
6010
+ font-size: var(--font-size-xs);
6011
+ line-height: 1.4;
6012
+ }
6013
+ .twm-flow-graph__why { color: var(--twm-flow-muted); border-bottom: 1px solid var(--border-subtle); }
6014
+ .twm-flow-graph__message:empty { display: none; }
6015
+ .twm-flow-graph__message--warning { color: var(--twm-flow-warning); }
6016
+ .twm-flow-graph__message--ok { color: var(--twm-flow-ok); }
6017
+ .twm-flow-graph__readonly {
6018
+ background: var(--twm-flow-warning-bg);
6019
+ color: var(--twm-flow-warning-text);
6020
+ border-bottom: 1px solid var(--twm-flow-warning-line);
6021
+ }
6022
+ .twm-flow-graph__banner {
6023
+ background: var(--twm-flow-blue-bg);
6024
+ color: var(--twm-flow-blue-fg);
6025
+ border-bottom: 1px solid var(--twm-flow-blue-line);
6026
+ }
6027
+
6028
+ /* Three columns; the CANVAS is the one that flexes — `flex: 1 1 0px` AND
6029
+ * `min-width: 0`, or an open settings panel squeezes the palette instead. */
6030
+ .twm-flow-graph__body { flex: 1 1 0px; min-height: 0; display: flex; flex-direction: row; }
6031
+ .twm-flow-graph__palette {
6032
+ flex: 0 0 176px;
6033
+ min-width: 0;
6034
+ overflow-y: auto;
6035
+ box-sizing: border-box;
6036
+ padding: 8px;
6037
+ display: flex;
6038
+ flex-direction: column;
6039
+ gap: 2px;
6040
+ background: var(--surface-1);
6041
+ border-right: 1px solid var(--border-default);
6042
+ }
6043
+ .twm-flow-graph__palette-title { margin: 2px 0 6px; font-size: var(--font-size-sm); font-weight: 600; }
6044
+ .twm-flow-graph__palette-group {
6045
+ margin: 10px 0 2px;
6046
+ font-size: var(--font-size-xs);
6047
+ font-weight: 600;
6048
+ letter-spacing: 0.06em;
6049
+ text-transform: uppercase;
6050
+ color: var(--twm-flow-muted);
6051
+ }
6052
+ /* A press must not select the label's text, and a touch press must not pan the
6053
+ * page instead of dragging. */
6054
+ .twm-flow-graph__palette-item {
6055
+ display: flex;
6056
+ align-items: center;
6057
+ gap: 6px;
6058
+ width: 100%;
6059
+ min-height: 26px;
6060
+ padding: 3px 6px;
6061
+ text-align: left;
6062
+ background: none;
6063
+ border: 1px solid transparent;
6064
+ border-radius: 3px;
6065
+ color: inherit;
6066
+ font: inherit;
6067
+ cursor: pointer;
6068
+ user-select: none;
6069
+ touch-action: none;
6070
+ }
6071
+ .twm-flow-graph__palette-item:hover:not(:disabled) { background: var(--state-hover); border-color: var(--border-default); }
6072
+ .twm-flow-graph__palette-item:focus-visible { outline: none; border-color: var(--twm-flow-focus); }
6073
+ .twm-flow-graph__palette-item:disabled { opacity: 0.45; cursor: not-allowed; }
6074
+ .twm-flow-graph__palette-icon {
6075
+ flex: 0 0 20px;
6076
+ height: 20px;
6077
+ display: inline-flex;
6078
+ align-items: center;
6079
+ justify-content: center;
6080
+ border-radius: 4px;
6081
+ }
6082
+ .twm-flow-graph__palette-icon .material-symbols-outlined,
6083
+ .twm-flow-graph__node-icon .material-symbols-outlined { font-size: 15px; }
6084
+ .twm-flow-graph__palette-icon--violet, .twm-flow-graph__node-icon--violet { background: var(--twm-flow-violet-bg); color: var(--twm-flow-violet-fg); }
6085
+ .twm-flow-graph__palette-icon--teal, .twm-flow-graph__node-icon--teal { background: var(--twm-flow-teal-bg); color: var(--twm-flow-teal-fg); }
6086
+ .twm-flow-graph__palette-icon--amber, .twm-flow-graph__node-icon--amber { background: var(--twm-flow-amber-bg); color: var(--twm-flow-amber-fg); }
6087
+ .twm-flow-graph__palette-icon--grey, .twm-flow-graph__node-icon--grey { background: var(--twm-flow-grey-bg); color: var(--twm-flow-grey-fg); }
6088
+ .twm-flow-graph__palette-icon--blue, .twm-flow-graph__node-icon--blue { background: var(--twm-flow-blue-bg); color: var(--twm-flow-blue-fg); }
6089
+ .twm-flow-graph__palette-icon--indigo, .twm-flow-graph__node-icon--indigo { background: var(--twm-flow-indigo-bg); color: var(--twm-flow-indigo-fg); }
6090
+ .twm-flow-graph__palette-label { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
6091
+ .twm-flow-graph__palette-why {
6092
+ margin: 0 0 4px 32px;
6093
+ font-size: var(--font-size-xs);
6094
+ color: var(--twm-flow-muted);
6095
+ }
6096
+ .twm-flow-graph__canvas { position: relative; flex: 1 1 0px; min-width: 0; min-height: 0; }
6097
+ .twm-flow-graph__canvas--drop { outline: 2px dashed var(--twm-flow-focus); outline-offset: -2px; }
6098
+ .twm-flow-graph__aside {
6099
+ flex: 0 0 300px;
6100
+ min-width: 0;
6101
+ min-height: 0;
6102
+ overflow-y: auto;
6103
+ background: var(--surface-1);
6104
+ border-left: 1px solid var(--border-default);
6105
+ }
6106
+ .twm-flow-graph__connection {
6107
+ display: flex;
6108
+ flex-direction: column;
6109
+ align-items: flex-start;
6110
+ gap: 8px;
6111
+ padding: 16px 20px;
6112
+ }
6113
+ .twm-flow-graph__connection-title { margin: 0; font-size: var(--font-size-md); font-weight: 600; }
6114
+ .twm-flow-graph__connection-line { margin: 0; color: var(--twm-flow-muted); overflow-wrap: anywhere; }
6115
+ .twm-flow-graph .twm-flow-graph__connection-remove { min-height: 26px; padding: 0 9px; font-size: var(--font-size-sm); }
6116
+
6117
+ /* A narrow editor: under 900px the side columns take less, and under 740px the
6118
+ * canvas takes the whole width on top with the palette and the settings side
6119
+ * by side under it — a container query, on the editor's own width. */
6120
+ @container twm-flow-graph (max-width: 900px) {
6121
+ .twm-flow-graph__palette { flex: 0 0 150px; }
6122
+ .twm-flow-graph__aside { flex: 0 0 232px; }
6123
+ }
6124
+ @container twm-flow-graph (max-width: 740px) {
6125
+ .twm-flow-graph__body {
6126
+ display: grid;
6127
+ grid-template-columns: minmax(132px, 2fr) minmax(0, 3fr);
6128
+ grid-template-rows: minmax(220px, 11fr) minmax(0, 9fr);
6129
+ }
6130
+ .twm-flow-graph__canvas { grid-column: 1 / -1; grid-row: 1; min-width: 0; }
6131
+ .twm-flow-graph__palette { grid-column: 1; grid-row: 2; min-height: 0; border-right: 0; border-top: 1px solid var(--border-default); }
6132
+ .twm-flow-graph__aside { grid-column: 2; grid-row: 2; border-left: 0; border-top: 1px solid var(--border-default); }
6133
+ }
6134
+
6135
+ /* ── a node ─────────────────────────────────────────────────────────── */
6136
+ /* THE BOX IS ARITHMETIC: a line meets a port at `header + row × i + row / 2`
6137
+ * (layout.js's portAnchor), so the header and a row are exactly these heights.
6138
+ * A consumer that passes `node: {width, header, row}` sets the three custom
6139
+ * properties on the editor's root. */
6140
+ .twm-flow-graph__node {
6141
+ position: absolute;
6142
+ box-sizing: border-box;
6143
+ width: var(--twm-canvas-node-width, 208px);
6144
+ background: var(--surface-2);
6145
+ border: 1px solid var(--border-strong);
6146
+ border-radius: 4px;
6147
+ box-shadow: 0 2px 12px rgba(0, 0, 0, 0.55);
6148
+ color: var(--text-body);
6149
+ font-size: var(--font-size-xs);
6150
+ outline: none;
6151
+ }
6152
+ .twm-flow-graph__node:focus-visible { box-shadow: 0 0 0 2px var(--twm-flow-focus), 0 2px 12px rgba(0, 0, 0, 0.55); }
6153
+ .twm-flow-graph__node--picked {
6154
+ border-color: var(--twm-flow-focus);
6155
+ box-shadow: 0 0 0 1px var(--twm-flow-focus), 0 6px 18px rgba(0, 0, 0, 0.45);
6156
+ }
6157
+ .twm-flow-graph__node--connect-source { outline: 2px solid var(--twm-flow-focus); outline-offset: 1px; }
6158
+ .twm-flow-graph__node--error { border-color: var(--twm-flow-error); }
6159
+ .twm-flow-graph__node--warning { border-color: var(--twm-flow-warning); }
6160
+ .twm-flow-graph__node--skipped { opacity: 0.55; }
6161
+ .twm-flow-graph__node-head {
6162
+ box-sizing: border-box;
6163
+ height: var(--twm-canvas-node-header, 34px);
6164
+ display: flex;
6165
+ align-items: center;
6166
+ gap: 6px;
6167
+ padding: 0 8px;
6168
+ background: var(--surface-3);
6169
+ border-bottom: 1px solid var(--border-strong);
6170
+ border-radius: 3px 3px 0 0;
6171
+ font-size: var(--font-size-sm);
6172
+ font-weight: 600;
6173
+ user-select: none;
6174
+ cursor: move;
6175
+ }
6176
+ .twm-flow-graph--readonly .twm-flow-graph__node-head { cursor: default; }
6177
+ .twm-flow-graph__node-icon {
6178
+ flex: 0 0 20px;
6179
+ height: 20px;
6180
+ display: inline-flex;
6181
+ align-items: center;
6182
+ justify-content: center;
6183
+ border-radius: 4px;
6184
+ }
6185
+ .twm-flow-graph__node-title { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
6186
+ /* ONE LINE, and never more than half the header: a tag that wrapped squeezed
6187
+ * the title beside it to a few letters. */
6188
+ .twm-flow-graph__node-tag {
6189
+ margin-left: auto;
6190
+ flex: none;
6191
+ max-width: 50%;
6192
+ padding: 1px 5px;
6193
+ overflow: hidden;
6194
+ text-overflow: ellipsis;
6195
+ white-space: nowrap;
6196
+ font-size: var(--font-size-xs);
6197
+ font-weight: 500;
6198
+ color: #b8cbe0;
6199
+ background: rgba(127, 154, 198, 0.18);
6200
+ border-radius: 2px;
6201
+ }
6202
+ .twm-flow-graph__node-row {
6203
+ box-sizing: border-box;
6204
+ height: var(--twm-canvas-node-row, 22px);
6205
+ display: flex;
6206
+ align-items: center;
6207
+ justify-content: space-between;
6208
+ }
6209
+ .twm-flow-graph__node-gap { flex: 1 1 auto; }
6210
+ .twm-flow-graph__node-summary,
6211
+ .twm-flow-graph__node-run {
6212
+ margin: 0;
6213
+ padding: 2px 8px 4px;
6214
+ color: var(--twm-flow-muted);
6215
+ overflow-wrap: anywhere;
6216
+ }
6217
+ .twm-flow-graph__node-summary:empty,
6218
+ .twm-flow-graph__node-run:empty { display: none; }
6219
+ .twm-flow-graph__node-findings { padding: 0 8px; }
6220
+ .twm-flow-graph__node-finding { margin: 4px 0; color: var(--twm-flow-error); overflow-wrap: anywhere; }
6221
+ .twm-flow-graph__node-finding--warning { color: var(--twm-flow-warning); }
6222
+ .twm-flow-graph__node-run[data-state="completed"], .twm-flow-graph__node-run[data-tone="ok"] { color: var(--twm-flow-ok); }
6223
+ .twm-flow-graph__node-run[data-state="failed"], .twm-flow-graph__node-run[data-tone="error"] { color: var(--twm-flow-error); }
6224
+ .twm-flow-graph__node-run[data-tone="warning"] { color: var(--twm-flow-warning); }
6225
+ .twm-flow-graph__node-run[data-state="running"] { color: var(--twm-flow-focus); }
6226
+ .twm-flow-graph__node-run[data-state="skipped"],
6227
+ .twm-flow-graph__node-run[data-state="cancelled"],
6228
+ .twm-flow-graph__node-run[data-state="not-reached"] { font-style: italic; }
6229
+
6230
+ /* ── a port ─────────────────────────────────────────────────────────── */
6231
+ .twm-flow-graph__port {
6232
+ display: flex;
6233
+ align-items: center;
6234
+ gap: 4px;
6235
+ height: var(--twm-canvas-node-row, 22px);
6236
+ padding: 0 6px;
6237
+ background: none;
6238
+ border: 0;
6239
+ color: inherit;
6240
+ font: inherit;
6241
+ font-size: var(--font-size-xs);
6242
+ cursor: crosshair;
6243
+ }
6244
+ .twm-flow-graph__port:disabled { cursor: default; }
6245
+ .twm-flow-graph__port:focus-visible { outline: 1px solid var(--twm-flow-focus); outline-offset: -1px; }
6246
+ .twm-flow-graph__port--in { margin-left: -6px; }
6247
+ .twm-flow-graph__port--out { flex-direction: row-reverse; margin-right: -6px; }
6248
+ .twm-flow-graph__port-dot {
6249
+ flex: 0 0 10px;
6250
+ width: 10px;
6251
+ height: 10px;
6252
+ box-sizing: border-box;
6253
+ border-radius: 50%;
6254
+ background: var(--surface-3);
6255
+ border: 2px solid var(--twm-flow-focus);
6256
+ }
6257
+ .twm-flow-graph__port-label { white-space: nowrap; }
6258
+ .twm-flow-graph__port-count { color: var(--twm-flow-muted); white-space: nowrap; }
6259
+ .twm-flow-graph__port-count:empty { display: none; }
6260
+ .twm-flow-graph__port:hover:not(:disabled) .twm-flow-graph__port-dot { background: var(--twm-flow-focus); }
6261
+ .twm-flow-graph__port--data { opacity: 0.7; }
6262
+ .twm-flow-graph__port--data .twm-flow-graph__port-dot { border-color: #8a8f98; border-radius: 2px; }
6263
+ .twm-flow-graph--connecting .twm-flow-graph__port--in:not(:disabled) .twm-flow-graph__port-dot {
6264
+ background: var(--twm-flow-focus);
6265
+ box-shadow: 0 0 0 3px rgba(0, 122, 204, 0.35);
6266
+ }
6267
+ .twm-flow-graph__port--taken .twm-flow-graph__port-dot { border-color: var(--twm-flow-ok); background: var(--twm-flow-ok); }
6268
+ .twm-flow-graph__port--taken .twm-flow-graph__port-count { color: var(--twm-flow-ok); }
6269
+ .twm-flow-graph__port--untaken { opacity: 0.5; }
6270
+
6271
+ /* ── a line ─────────────────────────────────────────────────────────── */
6272
+ .twm-flow-graph__edge { fill: none; stroke: #8fb4d8; stroke-width: 1.6; }
6273
+ .twm-flow-graph__edge--picked { stroke: var(--twm-flow-focus); stroke-width: 2.4; }
6274
+ /* A loop's body handing back to the loop: DASHED, and routed under both steps
6275
+ * by the kernel's `returnEdge`, so it reads as "round again", not as one more
6276
+ * step forward. */
6277
+ .twm-flow-graph__edge--back { stroke-dasharray: 6 4; }
6278
+ .twm-flow-graph__edge--taken { stroke: var(--twm-flow-ok); }
6279
+ .twm-flow-graph__edge--untaken { opacity: 0.35; }
6280
+ /* The 14px target a 1.6px line cannot be. It opts back into the pointer the
6281
+ * edge layer turns off. */
6282
+ .twm-flow-graph__edge-hit { fill: none; stroke: transparent; stroke-width: 14; pointer-events: stroke; cursor: pointer; }
6283
+
6284
+ /* ── the palette drag's ghost ───────────────────────────────────────── */
6285
+ /* It lives on <body>, follows the pointer and never takes it — `pointer-events:
6286
+ * none`, or the release lands on the ghost rather than on the canvas. */
6287
+ .twm-flow-graph__ghost {
6288
+ position: fixed;
6289
+ z-index: var(--z-toast);
6290
+ pointer-events: none;
6291
+ display: flex;
6292
+ align-items: center;
6293
+ gap: 6px;
6294
+ padding: 4px 8px;
6295
+ background: var(--surface-2);
6296
+ border: 1px solid var(--twm-flow-focus);
6297
+ border-radius: 3px;
6298
+ color: var(--text-body);
6299
+ font-family: var(--font-family-sans);
6300
+ font-size: var(--font-size-sm);
6301
+ opacity: 0.92;
6302
+ box-shadow: var(--shadow-md);
6303
+ }
6304
+ .twm-flow-graph__ghost .material-symbols-outlined { font-size: 16px; }
6305
+ .twm-flow-graph__ghost-label { white-space: nowrap; }
6306
+ /* ══ end FLOW · CANVAS ══ */
6307
+
6308
+
6309
+ /* ══ FLOW · OUTLINE ═══════════════════════════════════════════════════ */
6310
+ /* The outline editor (36 §6, the Main, AddStep, StepMenu and Run mocks): a
6311
+ * logic flow drawn as a list of blocks. A row is indented 22px a level
6312
+ * (`--twm-outline-depth`, set by src/flow/outline/editor.js, whose
6313
+ * OUTLINE_INDENT is the same number); its guides are the lines at 14px +
6314
+ * 22px a level. Every class here is set by a module under src/flow/outline/,
6315
+ * and every class those modules set has a rule here —
6316
+ * tests/flow_outline_css.test.mjs holds both directions. */
6317
+
6318
+ .twm-flow-outline[hidden],
6319
+ .twm-flow-outline [hidden],
6320
+ .twm-flow-popover--menu [hidden] {
6321
+ display: none !important;
6322
+ }
6323
+
6324
+ .twm-flow-outline {
6325
+ container: twm-flow-outline / inline-size;
6326
+ display: flex;
6327
+ flex-direction: column;
6328
+ height: 100%;
6329
+ min-height: 0;
6330
+ box-sizing: border-box;
6331
+ background: var(--surface-0);
6332
+ color: var(--text-body);
6333
+ font-family: var(--font-family-sans);
6334
+ font-size: var(--font-size-sm);
6335
+ line-height: 1.4;
6336
+ outline: none;
6337
+ }
6338
+ .twm-flow-outline--dragging,
6339
+ .twm-flow-outline--dragging * {
6340
+ cursor: grabbing !important;
6341
+ user-select: none;
6342
+ }
6343
+ .twm-flow-outline--readonly .twm-flow-outline__keys { display: none; }
6344
+ .twm-flow-outline--run .twm-flow-outline__type { display: none; }
6345
+
6346
+ /* ── the toolbar ────────────────────────────────────────────────────── */
6347
+ .twm-flow-outline__toolbar {
6348
+ display: flex;
6349
+ flex-wrap: wrap;
6350
+ align-items: center;
6351
+ gap: 6px;
6352
+ padding: 6px 10px;
6353
+ background: var(--surface-1);
6354
+ border-bottom: 1px solid var(--border-default);
6355
+ }
6356
+ .twm-flow-outline__toolbar .twm-btn {
6357
+ min-height: 26px;
6358
+ padding: 0 9px;
6359
+ font-size: var(--font-size-sm);
6360
+ border-radius: 3px;
6361
+ }
6362
+ .twm-flow-outline__tool { white-space: nowrap; }
6363
+ .twm-flow-outline__tool--busy { cursor: progress; opacity: .7; }
6364
+ .twm-flow-outline__sep {
6365
+ width: 1px;
6366
+ height: 18px;
6367
+ margin: 0 4px;
6368
+ background: var(--border-default);
6369
+ }
6370
+ .twm-flow-outline__tool-wrap {
6371
+ display: inline-flex;
6372
+ align-items: center;
6373
+ gap: 6px;
6374
+ }
6375
+ .twm-flow-outline__refusal {
6376
+ max-width: 260px;
6377
+ font-size: var(--font-size-xs);
6378
+ color: var(--twm-flow-warning);
6379
+ }
6380
+ .twm-flow-outline__status {
6381
+ margin-left: 8px;
6382
+ color: var(--twm-flow-muted);
6383
+ }
6384
+ .twm-flow-outline__spacer { flex: 1 1 auto; }
6385
+ .twm-flow-outline__toolbar-end {
6386
+ display: flex;
6387
+ align-items: center;
6388
+ gap: 6px;
6389
+ }
6390
+
6391
+ /* ── the banners: read only, and the run drawn ─────────────────────── */
6392
+ .twm-flow-outline__readonly {
6393
+ display: flex;
6394
+ align-items: flex-start;
6395
+ gap: 8px;
6396
+ padding: 6px 12px;
6397
+ background: var(--twm-flow-warning-bg);
6398
+ border-bottom: 1px solid var(--twm-flow-warning-line);
6399
+ color: var(--twm-flow-warning-text);
6400
+ }
6401
+ .twm-flow-outline__readonly-icon {
6402
+ flex: 0 0 auto;
6403
+ font-size: 16px;
6404
+ color: var(--twm-flow-warning);
6405
+ }
6406
+ .twm-flow-outline__readonly-text { min-width: 0; }
6407
+ .twm-flow-outline__banner {
6408
+ display: flex;
6409
+ align-items: center;
6410
+ gap: 8px;
6411
+ padding: 6px 12px;
6412
+ background: var(--twm-flow-blue-bg);
6413
+ border-bottom: 1px solid var(--twm-flow-blue-line);
6414
+ color: var(--twm-flow-blue-fg);
6415
+ }
6416
+ .twm-flow-outline__banner-icon {
6417
+ flex: 0 0 auto;
6418
+ font-size: 16px;
6419
+ color: var(--twm-flow-blue-dot);
6420
+ }
6421
+ .twm-flow-outline__banner-text { min-width: 0; }
6422
+
6423
+ /* ── the three columns ──────────────────────────────────────────────── */
6424
+ /* Side by side, each column scrolling on its own inside the editor's height —
6425
+ * the list's keys line stays at its foot and a long panel scrolls past a
6426
+ * short outline; in a narrow editor they wrap, one under the other, and the
6427
+ * body scrolls as one. */
6428
+ .twm-flow-outline__body {
6429
+ display: flex;
6430
+ flex-wrap: nowrap;
6431
+ align-items: stretch;
6432
+ flex: 1 1 auto;
6433
+ min-height: 0;
6434
+ overflow: hidden;
6435
+ }
6436
+ .twm-flow-outline__list {
6437
+ flex: 0 1 440px;
6438
+ min-width: 300px;
6439
+ max-width: 100%;
6440
+ min-height: 0;
6441
+ box-sizing: border-box;
6442
+ display: flex;
6443
+ flex-direction: column;
6444
+ border-right: 1px solid var(--border-default);
6445
+ }
6446
+ @container twm-flow-outline (max-width: 1000px) {
6447
+ .twm-flow-outline__body {
6448
+ flex-wrap: wrap;
6449
+ overflow: auto;
6450
+ }
6451
+ .twm-flow-outline__list { flex: 1 1 100%; border-right: 0; }
6452
+ .twm-flow-outline__settings,
6453
+ .twm-flow-outline__aside { overflow: visible; }
6454
+ }
6455
+ .twm-flow-outline__settings {
6456
+ flex: 3 1 460px;
6457
+ min-width: 0;
6458
+ box-sizing: border-box;
6459
+ overflow: auto;
6460
+ background: var(--surface-1);
6461
+ border-right: 1px solid var(--border-default);
6462
+ }
6463
+ .twm-flow-outline__aside {
6464
+ flex: 1 1 300px;
6465
+ min-width: 260px;
6466
+ box-sizing: border-box;
6467
+ padding: 16px;
6468
+ overflow: auto;
6469
+ }
6470
+
6471
+ /* ── the list's head, find, the status line ─────────────────────────── */
6472
+ .twm-flow-outline__list-head {
6473
+ flex: 0 0 auto;
6474
+ display: flex;
6475
+ align-items: center;
6476
+ gap: 8px;
6477
+ padding: 10px 12px 8px;
6478
+ }
6479
+ .twm-flow-outline__heading {
6480
+ margin: 0;
6481
+ font-size: 11px;
6482
+ font-weight: var(--font-weight-semibold);
6483
+ letter-spacing: .06em;
6484
+ text-transform: uppercase;
6485
+ color: var(--text-secondary);
6486
+ }
6487
+ .twm-flow-outline__count { color: var(--twm-flow-muted); }
6488
+ .twm-flow-outline__fold-all {
6489
+ height: 22px;
6490
+ padding: 0 7px;
6491
+ border: 0;
6492
+ border-radius: 3px;
6493
+ background: transparent;
6494
+ color: var(--text-secondary);
6495
+ font: inherit;
6496
+ cursor: pointer;
6497
+ }
6498
+ .twm-flow-outline__fold-all:hover:not(:disabled) { background: var(--state-hover); }
6499
+ .twm-flow-outline__fold-all:disabled { cursor: default; opacity: .45; }
6500
+ .twm-flow-outline__find {
6501
+ flex: 0 0 auto;
6502
+ box-sizing: border-box;
6503
+ width: calc(100% - 24px);
6504
+ height: 26px;
6505
+ margin: 0 12px 8px;
6506
+ padding: 0 8px;
6507
+ background: var(--twm-flow-control-bg);
6508
+ border: 1px solid var(--twm-flow-control-border);
6509
+ border-radius: 3px;
6510
+ color: var(--text-primary);
6511
+ font: inherit;
6512
+ }
6513
+ .twm-flow-outline__find:focus {
6514
+ outline: none;
6515
+ border-color: var(--twm-flow-focus);
6516
+ }
6517
+ .twm-flow-outline__scroll {
6518
+ flex: 1 1 auto;
6519
+ min-height: 0;
6520
+ overflow: auto;
6521
+ padding: 0 8px 12px;
6522
+ }
6523
+ .twm-flow-outline__message {
6524
+ flex: 0 0 auto;
6525
+ margin: 0 12px 6px;
6526
+ font-size: 11px;
6527
+ color: var(--twm-flow-warning-text);
6528
+ }
6529
+ .twm-flow-outline__keys {
6530
+ flex: 0 0 auto;
6531
+ margin: 0;
6532
+ padding: 10px 12px;
6533
+ border-top: 1px solid var(--border-subtle);
6534
+ font-size: 11px;
6535
+ color: var(--twm-flow-muted);
6536
+ }
6537
+
6538
+ /* ── the tree and its rows ──────────────────────────────────────────── */
6539
+ .twm-flow-outline__tree {
6540
+ position: relative;
6541
+ display: flex;
6542
+ flex-direction: column;
6543
+ }
6544
+ .twm-flow-outline__item,
6545
+ .twm-flow-outline__inside,
6546
+ .twm-flow-outline__arm {
6547
+ display: flex;
6548
+ flex-direction: column;
6549
+ }
6550
+ .twm-flow-outline__item { outline: none; }
6551
+ .twm-flow-outline__item:focus-visible > .twm-flow-outline__row {
6552
+ outline: 2px solid var(--twm-flow-focus);
6553
+ outline-offset: -2px;
6554
+ }
6555
+ .twm-flow-outline__item--flow { margin-bottom: 6px; }
6556
+ .twm-flow-outline__item--context > .twm-flow-outline__row { opacity: .55; }
6557
+ .twm-flow-outline__row {
6558
+ position: relative;
6559
+ display: flex;
6560
+ align-items: center;
6561
+ gap: 4px;
6562
+ box-sizing: border-box;
6563
+ padding-left: calc(8px + var(--twm-outline-depth, 0) * 22px);
6564
+ border-radius: 4px;
6565
+ }
6566
+ .twm-flow-outline__row--step { min-height: 42px; }
6567
+ .twm-flow-outline__row--step:hover,
6568
+ .twm-flow-outline__row--flow:hover { background-color: var(--state-hover); }
6569
+ .twm-flow-outline__row--flow {
6570
+ gap: 10px;
6571
+ padding: 8px 10px;
6572
+ background: var(--surface-1);
6573
+ border: 1px solid var(--border-subtle);
6574
+ }
6575
+ .twm-flow-outline__row--selected,
6576
+ .twm-flow-outline__row--selected:hover {
6577
+ background: var(--twm-flow-blue-bg);
6578
+ box-shadow: inset 0 0 0 1px var(--twm-flow-focus);
6579
+ }
6580
+ .twm-flow-outline__row--off .twm-flow-outline__title {
6581
+ font-style: italic;
6582
+ color: var(--text-dim);
6583
+ }
6584
+ .twm-flow-outline__row--off .twm-flow-outline__chip { opacity: .45; }
6585
+ .twm-flow-outline__row--dragging { opacity: .45; }
6586
+ .twm-flow-outline__guide {
6587
+ position: absolute;
6588
+ top: 0;
6589
+ bottom: 0;
6590
+ left: calc(14px + var(--twm-outline-guide, 0) * 22px);
6591
+ width: 1px;
6592
+ background: var(--border-default);
6593
+ pointer-events: none;
6594
+ }
6595
+
6596
+ /* an arm: its words in its tone — Then green, Otherwise grey, a failure amber */
6597
+ .twm-flow-outline__row--arm {
6598
+ height: 24px;
6599
+ gap: 6px;
6600
+ padding-left: calc(24px + var(--twm-outline-depth, 0) * 22px);
6601
+ font-size: 11px;
6602
+ font-weight: var(--font-weight-semibold);
6603
+ color: var(--twm-flow-muted);
6604
+ }
6605
+ .twm-flow-outline__row--then { color: var(--twm-flow-ok); }
6606
+ .twm-flow-outline__row--else { color: var(--text-secondary); }
6607
+ .twm-flow-outline__row--fail { color: var(--twm-flow-warning); }
6608
+ .twm-flow-outline__row--arm.twm-flow-outline__row--off { color: var(--text-dim); }
6609
+ .twm-flow-outline__arm-icon { font-size: 13px; }
6610
+ .twm-flow-outline__arm-label { white-space: nowrap; }
6611
+ .twm-flow-outline__arm-note {
6612
+ margin-left: auto;
6613
+ padding-right: 8px;
6614
+ font-weight: var(--font-weight-regular);
6615
+ color: var(--text-muted);
6616
+ }
6617
+ .twm-flow-outline__arm-remove {
6618
+ width: 20px;
6619
+ height: 20px;
6620
+ margin-left: auto;
6621
+ margin-right: 6px;
6622
+ display: flex;
6623
+ align-items: center;
6624
+ justify-content: center;
6625
+ padding: 0;
6626
+ border: 0;
6627
+ border-radius: 3px;
6628
+ background: transparent;
6629
+ color: var(--text-secondary);
6630
+ opacity: .6;
6631
+ cursor: pointer;
6632
+ }
6633
+ .twm-flow-outline__arm-note + .twm-flow-outline__arm-remove { margin-left: 0; }
6634
+ .twm-flow-outline__arm-remove .material-symbols-outlined { font-size: 14px; }
6635
+ .twm-flow-outline__row:hover > .twm-flow-outline__arm-remove,
6636
+ .twm-flow-outline__arm-remove:focus-visible { opacity: 1; }
6637
+ .twm-flow-outline__arm-remove:hover { background: var(--state-hover); }
6638
+
6639
+ /* a foot: Next row, Go on with the next row, Then wait for every branch */
6640
+ .twm-flow-outline__row--foot {
6641
+ height: 26px;
6642
+ gap: 6px;
6643
+ padding-left: calc(24px + var(--twm-outline-depth, 0) * 22px);
6644
+ font-size: 11px;
6645
+ color: var(--twm-flow-muted);
6646
+ }
6647
+ .twm-flow-outline__foot-icon { font-size: 13px; }
6648
+ .twm-flow-outline__foot-label { white-space: nowrap; }
6649
+ .twm-flow-outline__foot-note {
6650
+ margin-left: auto;
6651
+ padding-right: 8px;
6652
+ color: var(--text-muted);
6653
+ }
6654
+
6655
+ /* an add row: Add a step, Add a step to the loop, Add a branch */
6656
+ .twm-flow-outline__row--add { padding: 2px 8px 6px calc(24px + var(--twm-outline-depth, 0) * 22px); }
6657
+ .twm-flow-outline__row--add-top { padding-left: 8px; }
6658
+ .twm-flow-outline__row--add-top .twm-flow-outline__add { width: 100%; }
6659
+ .twm-flow-outline__add {
6660
+ box-sizing: border-box;
6661
+ display: flex;
6662
+ align-items: center;
6663
+ gap: 6px;
6664
+ height: 26px;
6665
+ padding: 0 9px;
6666
+ border: 1px dashed var(--border-strong);
6667
+ border-radius: 4px;
6668
+ background: transparent;
6669
+ color: var(--text-secondary);
6670
+ font: inherit;
6671
+ font-size: 11px;
6672
+ cursor: pointer;
6673
+ }
6674
+ .twm-flow-outline__add .material-symbols-outlined { font-size: 14px; }
6675
+ .twm-flow-outline__add:hover,
6676
+ .twm-flow-outline__add:focus-visible {
6677
+ color: var(--twm-flow-blue-fg);
6678
+ border-color: var(--twm-flow-focus);
6679
+ outline: none;
6680
+ }
6681
+ .twm-flow-outline__add-label { white-space: nowrap; }
6682
+
6683
+ /* a step row's parts */
6684
+ .twm-flow-outline__grip {
6685
+ flex: 0 0 12px;
6686
+ display: flex;
6687
+ color: var(--text-muted);
6688
+ opacity: 0;
6689
+ cursor: grab;
6690
+ touch-action: none;
6691
+ }
6692
+ .twm-flow-outline__grip .material-symbols-outlined { font-size: 14px; }
6693
+ .twm-flow-outline__row:hover > .twm-flow-outline__grip,
6694
+ .twm-flow-outline__row--selected > .twm-flow-outline__grip { opacity: 1; }
6695
+ .twm-flow-outline__grip--off { visibility: hidden; }
6696
+ .twm-flow-outline__fold {
6697
+ flex: 0 0 18px;
6698
+ width: 18px;
6699
+ height: 18px;
6700
+ display: flex;
6701
+ align-items: center;
6702
+ justify-content: center;
6703
+ padding: 0;
6704
+ border: 0;
6705
+ border-radius: 3px;
6706
+ background: transparent;
6707
+ color: var(--text-secondary);
6708
+ cursor: pointer;
6709
+ }
6710
+ .twm-flow-outline__fold:hover { background: var(--state-hover); }
6711
+ .twm-flow-outline__fold .material-symbols-outlined { font-size: 16px; }
6712
+ .twm-flow-outline__fold-space { flex: 0 0 18px; }
6713
+ .twm-flow-outline__chip {
6714
+ flex: 0 0 24px;
6715
+ height: 24px;
6716
+ display: flex;
6717
+ align-items: center;
6718
+ justify-content: center;
6719
+ margin-left: 5px;
6720
+ border-radius: 5px;
6721
+ }
6722
+ .twm-flow-outline__row--flow > .twm-flow-outline__chip { margin-left: 0; }
6723
+ .twm-flow-outline__chip .material-symbols-outlined { font-size: 15px; }
6724
+ .twm-flow-outline__chip--violet { background: var(--twm-flow-violet-bg); color: var(--twm-flow-violet-fg); }
6725
+ .twm-flow-outline__chip--teal { background: var(--twm-flow-teal-bg); color: var(--twm-flow-teal-fg); }
6726
+ .twm-flow-outline__chip--amber { background: var(--twm-flow-amber-bg); color: var(--twm-flow-amber-fg); }
6727
+ .twm-flow-outline__chip--grey { background: var(--twm-flow-grey-bg); color: var(--twm-flow-grey-fg); }
6728
+ .twm-flow-outline__chip--blue { background: var(--twm-flow-blue-bg); color: var(--twm-flow-blue-fg); }
6729
+ .twm-flow-outline__chip--indigo { background: var(--twm-flow-indigo-bg); color: var(--twm-flow-indigo-fg); }
6730
+ .twm-flow-outline__words {
6731
+ flex: 1 1 auto;
6732
+ min-width: 0;
6733
+ display: flex;
6734
+ flex-direction: column;
6735
+ gap: 1px;
6736
+ padding: 5px 4px;
6737
+ }
6738
+ .twm-flow-outline__line {
6739
+ display: flex;
6740
+ align-items: baseline;
6741
+ gap: 7px;
6742
+ min-width: 0;
6743
+ }
6744
+ .twm-flow-outline__title {
6745
+ min-width: 0;
6746
+ overflow: hidden;
6747
+ white-space: nowrap;
6748
+ text-overflow: ellipsis;
6749
+ font-weight: var(--font-weight-medium);
6750
+ color: var(--text-primary);
6751
+ }
6752
+ .twm-flow-outline__row--flow .twm-flow-outline__title { font-weight: var(--font-weight-semibold); }
6753
+ .twm-flow-outline__type {
6754
+ font-size: 11px;
6755
+ white-space: nowrap;
6756
+ color: var(--text-muted);
6757
+ }
6758
+ .twm-flow-outline__summary {
6759
+ overflow: hidden;
6760
+ white-space: nowrap;
6761
+ text-overflow: ellipsis;
6762
+ font-size: 11px;
6763
+ color: var(--text-secondary);
6764
+ }
6765
+ .twm-flow-outline__summary--mono {
6766
+ font-family: var(--font-family-mono);
6767
+ font-size: 11px;
6768
+ }
6769
+ .twm-flow-outline__summary--error { color: var(--twm-flow-error); }
6770
+ .twm-flow-outline__summary--warning { color: var(--twm-flow-warning); }
6771
+ .twm-flow-outline__note {
6772
+ flex: 0 0 auto;
6773
+ padding: 1px 6px;
6774
+ border-radius: 8px;
6775
+ background: var(--surface-2);
6776
+ font-size: 11px;
6777
+ white-space: nowrap;
6778
+ color: var(--text-secondary);
6779
+ }
6780
+ .twm-flow-outline__run {
6781
+ flex: 0 0 auto;
6782
+ display: inline-flex;
6783
+ align-items: center;
6784
+ height: 20px;
6785
+ padding: 0 7px;
6786
+ border-radius: 10px;
6787
+ font-size: 11px;
6788
+ white-space: nowrap;
6789
+ }
6790
+ .twm-flow-outline__run--ok { background: color-mix(in srgb, var(--twm-flow-ok) 14%, transparent); color: var(--twm-flow-ok); }
6791
+ .twm-flow-outline__run--warn { background: var(--twm-flow-warning-bg); color: var(--twm-flow-warning); }
6792
+ .twm-flow-outline__run--fail { background: var(--twm-flow-error-bg); color: var(--twm-flow-error); }
6793
+ .twm-flow-outline__run--skip { background: var(--twm-flow-grey-bg); color: var(--text-muted); }
6794
+ .twm-flow-outline__run--running { background: var(--twm-flow-blue-bg); color: var(--twm-flow-blue-fg); }
6795
+ .twm-flow-outline__badge {
6796
+ flex: 0 0 auto;
6797
+ display: flex;
6798
+ color: var(--twm-flow-error);
6799
+ }
6800
+ .twm-flow-outline__badge--warning { color: var(--twm-flow-warning); }
6801
+ .twm-flow-outline__badge .material-symbols-outlined { font-size: 15px; }
6802
+ .twm-flow-outline__menu {
6803
+ flex: 0 0 24px;
6804
+ width: 24px;
6805
+ height: 24px;
6806
+ margin-right: 4px;
6807
+ display: flex;
6808
+ align-items: center;
6809
+ justify-content: center;
6810
+ padding: 0;
6811
+ border: 0;
6812
+ border-radius: 3px;
6813
+ background: transparent;
6814
+ color: var(--text-secondary);
6815
+ opacity: .6;
6816
+ cursor: pointer;
6817
+ }
6818
+ .twm-flow-outline__menu .material-symbols-outlined { font-size: 16px; }
6819
+ .twm-flow-outline__row:hover > .twm-flow-outline__menu,
6820
+ .twm-flow-outline__row--selected > .twm-flow-outline__menu,
6821
+ .twm-flow-outline__menu:focus-visible { opacity: 1; }
6822
+ .twm-flow-outline__menu:hover { background: var(--state-hover); }
6823
+
6824
+ /* "+" between two rows: drawn on a row's bottom edge at the indent of the
6825
+ * list it adds to, shown on the row's hover AND on its own focus; only its
6826
+ * circle takes the pointer, so it never covers the row below */
6827
+ .twm-flow-outline__gap {
6828
+ position: absolute;
6829
+ z-index: 2;
6830
+ left: calc(8px + var(--twm-outline-depth, 0) * 22px);
6831
+ right: 8px;
6832
+ bottom: -7px;
6833
+ height: 14px;
6834
+ padding: 0;
6835
+ border: 0;
6836
+ background: transparent;
6837
+ opacity: 0;
6838
+ pointer-events: none;
6839
+ }
6840
+ .twm-flow-outline__row:hover > .twm-flow-outline__gap,
6841
+ .twm-flow-outline__gap:hover,
6842
+ .twm-flow-outline__gap:focus-visible {
6843
+ opacity: 1;
6844
+ outline: none;
6845
+ }
6846
+ .twm-flow-outline__gap-line {
6847
+ position: absolute;
6848
+ left: 10px;
6849
+ right: 0;
6850
+ top: 6px;
6851
+ height: 2px;
6852
+ border-radius: 1px;
6853
+ background: var(--twm-flow-focus);
6854
+ }
6855
+ .twm-flow-outline__gap-plus {
6856
+ position: absolute;
6857
+ left: 0;
6858
+ top: -2px;
6859
+ width: 18px;
6860
+ height: 18px;
6861
+ display: flex;
6862
+ align-items: center;
6863
+ justify-content: center;
6864
+ border-radius: 9px;
6865
+ background: var(--twm-flow-focus);
6866
+ color: #ffffff;
6867
+ font-size: 13px;
6868
+ pointer-events: none;
6869
+ cursor: pointer;
6870
+ }
6871
+ /* the circle takes the pointer only while it is drawn: an invisible "+" must
6872
+ * not catch a press meant for the top-left corner of the row below */
6873
+ .twm-flow-outline__row:hover > .twm-flow-outline__gap .twm-flow-outline__gap-plus,
6874
+ .twm-flow-outline__gap:focus-visible .twm-flow-outline__gap-plus { pointer-events: auto; }
6875
+ .twm-flow-outline__gap:focus-visible .twm-flow-outline__gap-plus { box-shadow: 0 0 0 2px var(--surface-0), 0 0 0 4px var(--twm-flow-focus); }
6876
+
6877
+ /* the grip drag: a ghost under the pointer, and a drop line naming the place */
6878
+ .twm-flow-outline__ghost {
6879
+ position: fixed;
6880
+ z-index: var(--z-popover);
6881
+ box-sizing: border-box;
6882
+ display: flex;
6883
+ align-items: center;
6884
+ gap: 9px;
6885
+ min-width: 200px;
6886
+ max-width: 320px;
6887
+ height: 40px;
6888
+ padding: 0 10px;
6889
+ background: var(--surface-2);
6890
+ border: 1px solid var(--twm-flow-focus);
6891
+ border-radius: 4px;
6892
+ box-shadow: 0 10px 24px rgba(0, 0, 0, 0.6);
6893
+ color: var(--text-primary);
6894
+ font-family: var(--font-family-sans);
6895
+ font-size: var(--font-size-sm);
6896
+ pointer-events: none;
6897
+ transform: rotate(-1.5deg);
6898
+ }
6899
+ .twm-flow-outline__ghost .twm-flow-outline__chip { margin-left: 0; }
6900
+ .twm-flow-outline__ghost-grip { font-size: 14px; color: var(--text-secondary); }
6901
+ .twm-flow-outline__ghost-title {
6902
+ overflow: hidden;
6903
+ white-space: nowrap;
6904
+ text-overflow: ellipsis;
6905
+ font-weight: var(--font-weight-medium);
6906
+ }
6907
+ .twm-flow-outline__drop {
6908
+ position: absolute;
6909
+ z-index: 3;
6910
+ left: calc(8px + var(--twm-outline-depth, 0) * 22px);
6911
+ right: 8px;
6912
+ height: 2px;
6913
+ margin-top: -1px;
6914
+ border-radius: 1px;
6915
+ background: var(--twm-flow-focus);
6916
+ pointer-events: none;
6917
+ }
6918
+ .twm-flow-outline__drop-label {
6919
+ position: absolute;
6920
+ right: 8px;
6921
+ top: -9px;
6922
+ box-sizing: border-box;
6923
+ max-width: calc(100% - 16px);
6924
+ min-height: 18px;
6925
+ display: flex;
6926
+ align-items: center;
6927
+ padding: 1px 7px;
6928
+ border-radius: 3px;
6929
+ background: var(--twm-flow-focus);
6930
+ color: #ffffff;
6931
+ font-size: 11px;
6932
+ line-height: 1.35;
6933
+ }
6934
+ .twm-flow-outline__drop--refused { background: var(--twm-flow-warning); }
6935
+ .twm-flow-outline__drop--refused .twm-flow-outline__drop-label {
6936
+ background: var(--surface-2);
6937
+ border: 1px solid var(--twm-flow-warning-line);
6938
+ color: var(--twm-flow-warning-text);
6939
+ }
6940
+
6941
+ /* the step menu (StepMenu mock), in the kit's popover */
6942
+ .twm-flow-popover--menu { width: 260px; }
6943
+ .twm-flow-outline__menu-list {
6944
+ position: relative;
6945
+ display: flex;
6946
+ flex-direction: column;
6947
+ box-sizing: border-box;
6948
+ padding: 5px;
6949
+ }
6950
+ .twm-flow-outline__menu-sub {
6951
+ position: absolute;
6952
+ left: calc(100% - 4px);
6953
+ z-index: 1;
6954
+ width: 190px;
6955
+ background: var(--surface-1);
6956
+ border: 1px solid var(--twm-flow-control-border);
6957
+ border-radius: var(--radius-md);
6958
+ box-shadow: 0 12px 32px rgba(0, 0, 0, 0.55);
6959
+ }
6960
+ .twm-flow-outline__menu-item {
6961
+ display: flex;
6962
+ align-items: center;
6963
+ justify-content: space-between;
6964
+ gap: 12px;
6965
+ min-height: 26px;
6966
+ padding: 3px 8px;
6967
+ border: 0;
6968
+ border-radius: 4px;
6969
+ background: transparent;
6970
+ color: var(--text-primary);
6971
+ font: inherit;
6972
+ text-align: left;
6973
+ cursor: pointer;
6974
+ }
6975
+ .twm-flow-outline__menu-item:hover:not(:disabled),
6976
+ .twm-flow-outline__menu-item:focus-visible,
6977
+ .twm-flow-outline__menu-item--open {
6978
+ outline: none;
6979
+ background: var(--twm-flow-blue-bg);
6980
+ }
6981
+ .twm-flow-outline__menu-item:disabled {
6982
+ color: var(--text-dim);
6983
+ cursor: not-allowed;
6984
+ }
6985
+ .twm-flow-outline__menu-item--danger { color: var(--twm-flow-error); }
6986
+ .twm-flow-outline__menu-item--danger:disabled { color: var(--text-dim); }
6987
+ .twm-flow-outline__menu-words {
6988
+ display: flex;
6989
+ align-items: center;
6990
+ gap: 8px;
6991
+ min-width: 0;
6992
+ }
6993
+ .twm-flow-outline__menu-label { overflow-wrap: anywhere; }
6994
+ .twm-flow-outline__menu-key {
6995
+ flex: 0 0 auto;
6996
+ font-size: 11px;
6997
+ color: var(--text-muted);
6998
+ }
6999
+ .twm-flow-outline__menu-sep {
7000
+ height: 1px;
7001
+ margin: 4px 6px;
7002
+ background: var(--border-default);
7003
+ }
7004
+ .twm-flow-outline__menu-chip {
7005
+ flex: 0 0 20px;
7006
+ height: 20px;
7007
+ display: flex;
7008
+ align-items: center;
7009
+ justify-content: center;
7010
+ border-radius: 4px;
7011
+ }
7012
+ .twm-flow-outline__menu-chip .material-symbols-outlined { font-size: 14px; }
7013
+ .twm-flow-outline__menu-chip--violet { background: var(--twm-flow-violet-bg); color: var(--twm-flow-violet-fg); }
7014
+ .twm-flow-outline__menu-chip--teal { background: var(--twm-flow-teal-bg); color: var(--twm-flow-teal-fg); }
7015
+ .twm-flow-outline__menu-chip--amber { background: var(--twm-flow-amber-bg); color: var(--twm-flow-amber-fg); }
7016
+ .twm-flow-outline__menu-chip--grey { background: var(--twm-flow-grey-bg); color: var(--twm-flow-grey-fg); }
7017
+ .twm-flow-outline__menu-chip--blue { background: var(--twm-flow-blue-bg); color: var(--twm-flow-blue-fg); }
7018
+ .twm-flow-outline__menu-chip--indigo { background: var(--twm-flow-indigo-bg); color: var(--twm-flow-indigo-fg); }
7019
+ /* ══ end FLOW · OUTLINE ══ */
7020
+
7021
+
7022
+ /* ══ FLOW · LANES ═════════════════════════════════════════════════════ */
7023
+ /* Owned by the lanes agent (D) (36 §2): the lane editor (twm-flow-lanes). */
7024
+ /*
7025
+ * The lane editor: a data flow drawn as lanes, left to right. Every class is
7026
+ * set by src/flow/lanes/editor.js, and every one it sets has a rule here
7027
+ * (tests/flow_lanes_css.test.mjs).
7028
+ *
7029
+ * THE CARD SIZES BELOW MUST MATCH `LANE_GEOMETRY` in src/flow/lanes/layout.js
7030
+ * — the layout places cards and draws wires from those numbers, the sheet
7031
+ * sizes and clips the cards, and the suite holds the two equal.
7032
+ */
7033
+ .twm-flow-lanes [hidden] {
7034
+ display: none !important;
7035
+ }
7036
+ .twm-flow-lanes {
7037
+ --twm-lanes-wire: #5b9bd5;
7038
+ --twm-lanes-surface: #1b1b1c;
7039
+ --twm-lanes-ring: #1683c4;
7040
+ display: flex;
7041
+ flex-direction: column;
7042
+ box-sizing: border-box;
7043
+ height: 100%;
7044
+ min-height: 0;
7045
+ min-width: 0;
7046
+ background: var(--surface-0);
7047
+ color: var(--text-body);
7048
+ font-family: var(--font-family-sans);
7049
+ font-size: var(--font-size-sm);
7050
+ line-height: 1.4;
7051
+ }
7052
+ .twm-flow-lanes--regular {
7053
+ --twm-lanes-card-w: 200px;
7054
+ --twm-lanes-card-h: 62px;
7055
+ --twm-lanes-notch: 12px;
7056
+ --twm-lanes-icon-w: 50px;
7057
+ --twm-lanes-icon-w-source: 40px;
7058
+ }
7059
+ .twm-flow-lanes--small {
7060
+ --twm-lanes-card-w: 160px;
7061
+ --twm-lanes-card-h: 50px;
7062
+ --twm-lanes-notch: 10px;
7063
+ --twm-lanes-icon-w: 42px;
7064
+ --twm-lanes-icon-w-source: 34px;
7065
+ }
7066
+ .twm-flow-lanes--strip {
7067
+ --twm-lanes-card-w: 92px;
7068
+ --twm-lanes-card-h: 26px;
7069
+ --twm-lanes-notch: 8px;
7070
+ }
7071
+ .twm-flow-lanes--auto {
7072
+ height: auto;
7073
+ }
7074
+ .twm-flow-lanes--compact {
7075
+ height: auto;
7076
+ background: transparent;
7077
+ }
7078
+ .twm-flow-lanes--readonly .twm-flow-lanes__flow {
7079
+ background: #1a1a1b;
7080
+ }
7081
+
7082
+ /* ── read only ──────────────────────────────────────────────────────── */
7083
+ .twm-flow-lanes__readonly {
7084
+ flex: 0 0 auto;
7085
+ padding: 7px 12px;
7086
+ background: var(--twm-flow-warning-bg);
7087
+ border-bottom: 1px solid var(--twm-flow-warning-line);
7088
+ color: var(--twm-flow-warning-text);
7089
+ }
7090
+ .twm-flow-lanes__readonly-line {
7091
+ margin: 0;
7092
+ }
7093
+
7094
+ /* ── the toolbar ────────────────────────────────────────────────────── */
7095
+ .twm-flow-lanes__toolbar {
7096
+ flex: 0 0 auto;
7097
+ display: flex;
7098
+ flex-wrap: wrap;
7099
+ align-items: center;
7100
+ gap: 6px;
7101
+ padding: 6px 10px;
7102
+ background: var(--surface-1);
7103
+ border-bottom: 1px solid var(--border-default);
7104
+ }
7105
+ .twm-flow-lanes__toolbar .twm-btn,
7106
+ .twm-flow-lanes__form .twm-btn {
7107
+ min-height: 26px;
7108
+ padding: 0 9px;
7109
+ font-size: var(--font-size-sm);
7110
+ border-radius: 3px;
7111
+ }
7112
+ .twm-flow-lanes__toolbar-slot,
7113
+ .twm-flow-lanes__actions,
7114
+ .twm-flow-lanes__action {
7115
+ display: flex;
7116
+ flex-wrap: wrap;
7117
+ align-items: center;
7118
+ gap: 6px;
7119
+ }
7120
+ .twm-flow-lanes__toolbar-sep {
7121
+ width: 1px;
7122
+ height: 18px;
7123
+ margin: 0 4px;
7124
+ background: var(--surface-3);
7125
+ }
7126
+ .twm-flow-lanes__action--busy .twm-btn {
7127
+ cursor: progress;
7128
+ }
7129
+ .twm-flow-lanes__refusal {
7130
+ color: var(--twm-flow-warning);
7131
+ font-size: var(--font-size-xs);
7132
+ }
7133
+ .twm-flow-lanes__status {
7134
+ margin-left: 8px;
7135
+ color: #a0a0a0;
7136
+ }
7137
+ .twm-flow-lanes__spacer {
7138
+ flex: 1 1 auto;
7139
+ }
7140
+ .twm-flow-lanes__show-label {
7141
+ color: var(--twm-flow-muted);
7142
+ }
7143
+ .twm-flow-lanes__show {
7144
+ display: flex;
7145
+ border: 1px solid var(--surface-3);
7146
+ border-radius: 3px;
7147
+ overflow: hidden;
7148
+ }
7149
+ .twm-flow-lanes__show-btn {
7150
+ height: 24px;
7151
+ padding: 0 10px;
7152
+ border: 0;
7153
+ background: var(--surface-2);
7154
+ color: #c8c8c8;
7155
+ font: inherit;
7156
+ cursor: pointer;
7157
+ }
7158
+ .twm-flow-lanes__show-btn + .twm-flow-lanes__show-btn {
7159
+ border-left: 1px solid var(--surface-3);
7160
+ }
7161
+ .twm-flow-lanes__show-btn[aria-pressed="true"] {
7162
+ background: #0f6fa8;
7163
+ color: var(--text-bright);
7164
+ }
7165
+ .twm-flow-lanes__show-btn:focus-visible,
7166
+ .twm-flow-lanes__param:focus-visible,
7167
+ .twm-flow-lanes__param-add:focus-visible,
7168
+ .twm-flow-lanes__add-source:focus-visible,
7169
+ .twm-flow-lanes__tab:focus-visible,
7170
+ .twm-flow-lanes__datatab:focus-visible,
7171
+ .twm-flow-lanes__menu-item:focus-visible {
7172
+ outline: 2px solid var(--twm-lanes-ring);
7173
+ outline-offset: -2px;
7174
+ }
7175
+
7176
+ /* ── parameters ─────────────────────────────────────────────────────── */
7177
+ .twm-flow-lanes__params {
7178
+ flex: 0 0 auto;
7179
+ display: flex;
7180
+ flex-wrap: wrap;
7181
+ align-items: center;
7182
+ gap: 8px 12px;
7183
+ padding: 7px 12px;
7184
+ background: #222223;
7185
+ border-bottom: 1px solid var(--border-default);
7186
+ }
7187
+ .twm-flow-lanes__params-title {
7188
+ font-size: var(--font-size-xs);
7189
+ font-weight: 600;
7190
+ letter-spacing: .06em;
7191
+ text-transform: uppercase;
7192
+ color: #c4c4c4;
7193
+ }
7194
+ .twm-flow-lanes__param {
7195
+ display: flex;
7196
+ align-items: center;
7197
+ gap: 8px;
7198
+ height: 24px;
7199
+ padding: 0 9px;
7200
+ border: 1px solid var(--surface-3);
7201
+ border-radius: 12px;
7202
+ background: var(--twm-flow-control-bg);
7203
+ color: var(--text-primary);
7204
+ font: inherit;
7205
+ cursor: pointer;
7206
+ }
7207
+ .twm-flow-lanes__param:hover,
7208
+ .twm-flow-lanes__param-add:hover,
7209
+ .twm-flow-lanes__add-source:hover {
7210
+ background: rgba(255, 255, 255, 0.06);
7211
+ }
7212
+ .twm-flow-lanes__param-name {
7213
+ font-family: var(--font-family-mono);
7214
+ color: var(--twm-flow-violet-fg);
7215
+ }
7216
+ .twm-flow-lanes__param-line {
7217
+ color: var(--twm-flow-muted);
7218
+ }
7219
+ .twm-flow-lanes__param-add {
7220
+ display: flex;
7221
+ align-items: center;
7222
+ gap: 5px;
7223
+ height: 24px;
7224
+ padding: 0 8px;
7225
+ border: 1px dashed #4a4a4a;
7226
+ border-radius: 12px;
7227
+ background: transparent;
7228
+ color: #b0b0b0;
7229
+ font: inherit;
7230
+ font-size: var(--font-size-xs);
7231
+ cursor: pointer;
7232
+ }
7233
+ .twm-flow-lanes__param-add .material-symbols-outlined,
7234
+ .twm-flow-lanes__add-source .material-symbols-outlined {
7235
+ font-size: 14px;
7236
+ }
7237
+ .twm-flow-lanes__params-help {
7238
+ color: #a0a0a0;
7239
+ font-size: var(--font-size-xs);
7240
+ }
7241
+
7242
+ /* ── the lanes ──────────────────────────────────────────────────────── */
7243
+ .twm-flow-lanes__flow {
7244
+ flex: 0 1 auto;
7245
+ min-height: 0;
7246
+ overflow-y: auto;
7247
+ background: var(--twm-lanes-surface);
7248
+ border-bottom: 1px solid var(--border-default);
7249
+ }
7250
+ .twm-flow-lanes__banner {
7251
+ margin: 8px 16px 0;
7252
+ padding: 6px 10px;
7253
+ border-radius: var(--radius-sm);
7254
+ background: var(--twm-flow-blue-bg);
7255
+ color: var(--twm-flow-blue-fg);
7256
+ }
7257
+ .twm-flow-lanes__scroller {
7258
+ overflow-x: auto;
7259
+ padding: 14px 0 6px;
7260
+ }
7261
+ /* The page's own scrollbars may be light; these sit on dark surfaces. */
7262
+ .twm-flow-lanes__scroller,
7263
+ .twm-flow-lanes__flow,
7264
+ .twm-flow-lanes__settings,
7265
+ .twm-flow-lanes__databody {
7266
+ scrollbar-color: #4a4a4a transparent;
7267
+ }
7268
+ .twm-flow-lanes__surface {
7269
+ position: relative;
7270
+ z-index: 0;
7271
+ margin: 0 16px;
7272
+ }
7273
+ .twm-flow-lanes__empty {
7274
+ margin: 0;
7275
+ padding: 18px 16px 4px;
7276
+ color: var(--twm-flow-muted);
7277
+ }
7278
+ /* A lane: its band is a pseudo-element, so the lane itself has no border and
7279
+ * a card's `left`/`top` inside it are exactly the layout's numbers. */
7280
+ .twm-flow-lanes__lane {
7281
+ position: absolute;
7282
+ left: 0;
7283
+ right: 0;
7284
+ }
7285
+ .twm-flow-lanes__lane::before {
7286
+ content: '';
7287
+ position: absolute;
7288
+ inset: 0;
7289
+ box-sizing: border-box;
7290
+ border: 1px dashed #2c2c2c;
7291
+ border-radius: 6px;
7292
+ background: rgba(255, 255, 255, 0.018);
7293
+ }
7294
+ .twm-flow-lanes__lane--unconnected::before {
7295
+ border-color: var(--twm-flow-warning-line);
7296
+ }
7297
+ .twm-flow-lanes__flag {
7298
+ position: absolute;
7299
+ top: -8px;
7300
+ left: 12px;
7301
+ padding: 0 6px;
7302
+ font-size: 10px;
7303
+ line-height: 16px;
7304
+ color: var(--twm-flow-warning);
7305
+ background: var(--twm-lanes-surface);
7306
+ }
7307
+ .twm-flow-lanes__wires {
7308
+ position: absolute;
7309
+ left: 0;
7310
+ top: 0;
7311
+ z-index: 1;
7312
+ overflow: visible;
7313
+ pointer-events: none;
7314
+ }
7315
+ .twm-flow-lanes__wire {
7316
+ fill: none;
7317
+ stroke: var(--twm-lanes-wire);
7318
+ stroke-width: 2;
7319
+ stroke-linecap: round;
7320
+ stroke-linejoin: round;
7321
+ }
7322
+ .twm-flow-lanes__wire--cycle {
7323
+ stroke: var(--twm-flow-error);
7324
+ stroke-dasharray: 4 3;
7325
+ }
7326
+ .twm-flow-lanes__port {
7327
+ fill: var(--twm-lanes-wire);
7328
+ stroke: var(--twm-lanes-surface);
7329
+ stroke-width: 3;
7330
+ }
7331
+
7332
+ /* ── a card: an unclipped holder (focus, selection, "+") round a clipped body ── */
7333
+ .twm-flow-lanes__node {
7334
+ position: absolute;
7335
+ z-index: 2;
7336
+ width: var(--twm-lanes-card-w);
7337
+ height: var(--twm-lanes-card-h);
7338
+ }
7339
+ .twm-flow-lanes__node--teal,
7340
+ .twm-flow-lanes__tab--teal {
7341
+ --twm-lanes-icon-bg: var(--twm-flow-teal-icon-bg);
7342
+ --twm-lanes-text-bg: var(--twm-flow-teal-text-bg);
7343
+ --twm-lanes-fg: var(--twm-flow-teal-fg);
7344
+ --twm-lanes-dot: var(--twm-flow-teal-dot);
7345
+ }
7346
+ .twm-flow-lanes__node--indigo,
7347
+ .twm-flow-lanes__tab--indigo {
7348
+ --twm-lanes-icon-bg: var(--twm-flow-indigo-icon-bg);
7349
+ --twm-lanes-text-bg: var(--twm-flow-indigo-text-bg);
7350
+ --twm-lanes-fg: var(--twm-flow-indigo-fg);
7351
+ --twm-lanes-dot: var(--twm-flow-indigo-dot);
7352
+ }
7353
+ .twm-flow-lanes__node--violet,
7354
+ .twm-flow-lanes__tab--violet {
7355
+ --twm-lanes-icon-bg: var(--twm-flow-violet-icon-bg);
7356
+ --twm-lanes-text-bg: var(--twm-flow-violet-text-bg);
7357
+ --twm-lanes-fg: var(--twm-flow-violet-fg);
7358
+ --twm-lanes-dot: var(--twm-flow-violet-dot);
7359
+ }
7360
+ .twm-flow-lanes__node--amber,
7361
+ .twm-flow-lanes__tab--amber {
7362
+ --twm-lanes-icon-bg: var(--twm-flow-amber-icon-bg);
7363
+ --twm-lanes-text-bg: var(--twm-flow-amber-text-bg);
7364
+ --twm-lanes-fg: var(--twm-flow-amber-fg);
7365
+ --twm-lanes-dot: var(--twm-flow-amber-dot);
7366
+ }
7367
+ .twm-flow-lanes__node--blue,
7368
+ .twm-flow-lanes__tab--blue {
7369
+ --twm-lanes-icon-bg: var(--twm-flow-blue-icon-bg);
7370
+ --twm-lanes-text-bg: var(--twm-flow-blue-text-bg);
7371
+ --twm-lanes-fg: var(--twm-flow-blue-fg);
7372
+ --twm-lanes-dot: var(--twm-flow-blue-dot);
7373
+ }
7374
+ .twm-flow-lanes__node--grey,
7375
+ .twm-flow-lanes__tab--grey {
7376
+ --twm-lanes-icon-bg: var(--twm-flow-grey-icon-bg);
7377
+ --twm-lanes-text-bg: var(--twm-flow-grey-text-bg);
7378
+ --twm-lanes-fg: var(--twm-flow-grey-fg);
7379
+ --twm-lanes-dot: var(--twm-flow-grey-dot);
7380
+ }
7381
+ .twm-flow-lanes__card {
7382
+ display: block;
7383
+ width: 100%;
7384
+ height: 100%;
7385
+ padding: 0;
7386
+ border: 0;
7387
+ background: transparent;
7388
+ color: inherit;
7389
+ font: inherit;
7390
+ text-align: left;
7391
+ cursor: pointer;
7392
+ outline: none;
7393
+ }
7394
+ /* The ring is a `drop-shadow` on the unclipped holder: a clip-path cuts a
7395
+ * box-shadow off, a filter on its parent follows the clipped shape. */
7396
+ .twm-flow-lanes__node--warning .twm-flow-lanes__card {
7397
+ filter: drop-shadow(0 0 1px var(--twm-flow-warning)) drop-shadow(0 0 1px var(--twm-flow-warning));
7398
+ }
7399
+ .twm-flow-lanes__node--error .twm-flow-lanes__card {
7400
+ filter: drop-shadow(0 0 1px var(--twm-flow-error)) drop-shadow(0 0 1px var(--twm-flow-error));
7401
+ }
7402
+ .twm-flow-lanes__node--selected .twm-flow-lanes__card,
7403
+ .twm-flow-lanes__card:focus-visible {
7404
+ filter: drop-shadow(0 0 1px var(--twm-lanes-ring)) drop-shadow(0 0 1px var(--twm-lanes-ring))
7405
+ drop-shadow(0 0 5px rgba(22, 131, 196, 0.8));
7406
+ }
7407
+ .twm-flow-lanes__card:hover .twm-flow-lanes__body {
7408
+ filter: brightness(1.12);
7409
+ }
7410
+ .twm-flow-lanes__body {
7411
+ display: flex;
7412
+ width: 100%;
7413
+ height: 100%;
7414
+ background: var(--twm-lanes-text-bg);
7415
+ }
7416
+ /* Three shapes: a source flat on the left, a step notched, a sink flat on the right. */
7417
+ .twm-flow-lanes__node--source .twm-flow-lanes__body {
7418
+ clip-path: polygon(0 0, calc(100% - var(--twm-lanes-notch)) 0, 100% 50%,
7419
+ calc(100% - var(--twm-lanes-notch)) 100%, 0 100%);
7420
+ }
7421
+ .twm-flow-lanes__node--transform .twm-flow-lanes__body,
7422
+ .twm-flow-lanes__node--operation .twm-flow-lanes__body {
7423
+ clip-path: polygon(0 0, calc(100% - var(--twm-lanes-notch)) 0, 100% 50%,
7424
+ calc(100% - var(--twm-lanes-notch)) 100%, 0 100%, var(--twm-lanes-notch) 50%);
7425
+ }
7426
+ .twm-flow-lanes__node--sink .twm-flow-lanes__body {
7427
+ clip-path: polygon(0 0, 100% 0, 100% 100%, 0 100%, var(--twm-lanes-notch) 50%);
7428
+ }
7429
+ .twm-flow-lanes__icon {
7430
+ flex: 0 0 var(--twm-lanes-icon-w);
7431
+ display: flex;
7432
+ align-items: center;
7433
+ justify-content: center;
7434
+ box-sizing: border-box;
7435
+ padding-left: calc(var(--twm-lanes-notch) - 2px);
7436
+ background: var(--twm-lanes-icon-bg);
7437
+ color: var(--twm-lanes-fg);
7438
+ overflow: hidden;
7439
+ }
7440
+ .twm-flow-lanes__node--source .twm-flow-lanes__icon {
7441
+ flex-basis: var(--twm-lanes-icon-w-source);
7442
+ padding-left: 0;
7443
+ }
7444
+ .twm-flow-lanes__icon .material-symbols-outlined {
7445
+ font-size: 18px;
7446
+ line-height: 1;
7447
+ }
7448
+ .twm-flow-lanes__sep {
7449
+ flex: 0 0 1px;
7450
+ background: rgba(255, 255, 255, 0.08);
7451
+ }
7452
+ .twm-flow-lanes__text {
7453
+ flex: 1 1 auto;
7454
+ min-width: 0;
7455
+ display: flex;
7456
+ flex-direction: column;
7457
+ justify-content: center;
7458
+ gap: 1px;
7459
+ padding: 0 18px 0 9px;
7460
+ }
7461
+ .twm-flow-lanes__title,
7462
+ .twm-flow-lanes__sub,
7463
+ .twm-flow-lanes__line {
7464
+ white-space: nowrap;
7465
+ overflow: hidden;
7466
+ text-overflow: ellipsis;
7467
+ }
7468
+ .twm-flow-lanes__title {
7469
+ color: #ececec;
7470
+ font-weight: 600;
7471
+ }
7472
+ .twm-flow-lanes__sub {
7473
+ color: #b0b0b0;
7474
+ font-size: var(--font-size-xs);
7475
+ }
7476
+ .twm-flow-lanes__line {
7477
+ font-size: 10px;
7478
+ }
7479
+ .twm-flow-lanes__line--ok { color: var(--twm-flow-ok); }
7480
+ .twm-flow-lanes__line--warning { color: var(--twm-flow-warning); }
7481
+ .twm-flow-lanes__line--error { color: var(--twm-flow-error); }
7482
+ .twm-flow-lanes__line--muted { color: #b0b0b0; }
7483
+ .twm-flow-lanes__line--info { color: var(--twm-flow-blue-fg); }
7484
+ /* "+" on the card's right tip: on hover, on focus and on the chosen card —
7485
+ * never on hover alone. */
7486
+ .twm-flow-lanes__add {
7487
+ position: absolute;
7488
+ right: -14px;
7489
+ top: -9px;
7490
+ z-index: 3;
7491
+ width: 18px;
7492
+ height: 18px;
7493
+ display: flex;
7494
+ align-items: center;
7495
+ justify-content: center;
7496
+ padding: 0;
7497
+ border: 1px solid #4a4a4a;
7498
+ border-radius: 9px;
7499
+ background: var(--surface-1);
7500
+ color: #d0d0d0;
7501
+ cursor: pointer;
7502
+ opacity: 0;
7503
+ }
7504
+ .twm-flow-lanes__node:hover .twm-flow-lanes__add,
7505
+ .twm-flow-lanes__node:focus-within .twm-flow-lanes__add,
7506
+ .twm-flow-lanes__node--selected .twm-flow-lanes__add {
7507
+ opacity: 1;
7508
+ }
7509
+ .twm-flow-lanes__add:hover,
7510
+ .twm-flow-lanes__add:focus-visible {
7511
+ background: var(--twm-lanes-ring);
7512
+ border-color: var(--twm-lanes-ring);
7513
+ color: var(--text-bright);
7514
+ outline: none;
7515
+ }
7516
+ .twm-flow-lanes__add .material-symbols-outlined {
7517
+ font-size: 14px;
7518
+ line-height: 1;
7519
+ }
7520
+
7521
+ /* the small cards: a title and one line */
7522
+ .twm-flow-lanes--small .twm-flow-lanes__sub {
7523
+ display: none;
7524
+ }
7525
+ .twm-flow-lanes--small .twm-flow-lanes__text {
7526
+ padding: 0 16px 0 8px;
7527
+ }
7528
+ .twm-flow-lanes--small .twm-flow-lanes__line {
7529
+ font-size: 10.5px;
7530
+ }
7531
+ .twm-flow-lanes--small .twm-flow-lanes__icon .material-symbols-outlined {
7532
+ font-size: 14px;
7533
+ }
7534
+
7535
+ /* the compact strip: a title a card, and nothing to press */
7536
+ .twm-flow-lanes--compact .twm-flow-lanes__flow {
7537
+ background: transparent;
7538
+ border-bottom: 0;
7539
+ overflow: visible;
7540
+ }
7541
+ .twm-flow-lanes--compact .twm-flow-lanes__scroller {
7542
+ padding: 0;
7543
+ }
7544
+ .twm-flow-lanes--compact .twm-flow-lanes__surface {
7545
+ margin: 0;
7546
+ }
7547
+ .twm-flow-lanes--strip .twm-flow-lanes__lane::before {
7548
+ display: none;
7549
+ }
7550
+ .twm-flow-lanes--strip .twm-flow-lanes__body {
7551
+ background: var(--twm-lanes-icon-bg);
7552
+ }
7553
+ .twm-flow-lanes--strip .twm-flow-lanes__text {
7554
+ padding: 0 12px 0 13px;
7555
+ }
7556
+ .twm-flow-lanes--strip .twm-flow-lanes__node--source .twm-flow-lanes__text {
7557
+ padding: 0 12px 0 8px;
7558
+ }
7559
+ .twm-flow-lanes--strip .twm-flow-lanes__node--sink .twm-flow-lanes__text {
7560
+ padding: 0 6px 0 13px;
7561
+ }
7562
+ .twm-flow-lanes--strip .twm-flow-lanes__title {
7563
+ color: #e6e6e6;
7564
+ font-size: 10.5px;
7565
+ font-weight: 400;
7566
+ }
7567
+
7568
+ /* ── under the lanes: Add a source ──────────────────────────────────── */
7569
+ .twm-flow-lanes__foot {
7570
+ display: flex;
7571
+ flex-wrap: wrap;
7572
+ align-items: center;
7573
+ gap: 10px 16px;
7574
+ padding: 4px 16px 12px;
7575
+ }
7576
+ .twm-flow-lanes__add-source {
7577
+ display: flex;
7578
+ align-items: center;
7579
+ gap: 6px;
7580
+ height: 28px;
7581
+ padding: 0 12px;
7582
+ border: 1px dashed #4a4a4a;
7583
+ border-radius: var(--radius-sm);
7584
+ background: transparent;
7585
+ color: #b8b8b8;
7586
+ font: inherit;
7587
+ cursor: pointer;
7588
+ }
7589
+ .twm-flow-lanes__hint {
7590
+ color: #9a9a9a;
7591
+ font-size: var(--font-size-xs);
7592
+ }
7593
+
7594
+ /* ── a tab per step ─────────────────────────────────────────────────── */
7595
+ .twm-flow-lanes__tabs {
7596
+ flex: 0 0 auto;
7597
+ display: flex;
7598
+ flex-wrap: wrap;
7599
+ align-items: stretch;
7600
+ gap: 0 2px;
7601
+ padding: 0 12px;
7602
+ background: var(--surface-1);
7603
+ border-bottom: 1px solid var(--border-default);
7604
+ }
7605
+ .twm-flow-lanes__tab,
7606
+ .twm-flow-lanes__datatab {
7607
+ display: flex;
7608
+ align-items: center;
7609
+ gap: 7px;
7610
+ height: 32px;
7611
+ padding: 0 11px;
7612
+ border: 0;
7613
+ border-bottom: 2px solid transparent;
7614
+ background: transparent;
7615
+ color: #b4b4b4;
7616
+ font: inherit;
7617
+ cursor: pointer;
7618
+ }
7619
+ .twm-flow-lanes__tab:hover,
7620
+ .twm-flow-lanes__datatab:hover {
7621
+ background: rgba(255, 255, 255, 0.05);
7622
+ }
7623
+ .twm-flow-lanes__tab[aria-selected="true"],
7624
+ .twm-flow-lanes__datatab[aria-pressed="true"] {
7625
+ border-bottom-color: var(--twm-lanes-ring);
7626
+ color: var(--text-bright);
7627
+ }
7628
+ .twm-flow-lanes__tab-dot {
7629
+ flex: 0 0 7px;
7630
+ height: 7px;
7631
+ border-radius: 4px;
7632
+ background: var(--twm-lanes-dot);
7633
+ }
7634
+ .twm-flow-lanes__tab-label {
7635
+ max-width: 220px;
7636
+ white-space: nowrap;
7637
+ overflow: hidden;
7638
+ text-overflow: ellipsis;
7639
+ }
7640
+
7641
+ /* ── the dock: the settings beside what the step gives ──────────────── */
7642
+ .twm-flow-lanes__dock {
7643
+ flex: 1 1 0;
7644
+ min-height: 240px;
7645
+ display: flex;
7646
+ align-items: stretch;
7647
+ }
7648
+ .twm-flow-lanes--auto .twm-flow-lanes__dock {
7649
+ flex: 0 0 auto;
7650
+ }
7651
+ .twm-flow-lanes__settings {
7652
+ flex: 1 1 400px;
7653
+ min-width: 260px;
7654
+ min-height: 0;
7655
+ overflow-y: auto;
7656
+ background: #232324;
7657
+ border-right: 1px solid var(--border-default);
7658
+ }
7659
+ .twm-flow-lanes__settings .twm-flow-panel {
7660
+ background: transparent;
7661
+ }
7662
+ .twm-flow-lanes__settings-hint {
7663
+ margin: 0;
7664
+ padding: 16px 20px;
7665
+ color: var(--twm-flow-muted);
7666
+ }
7667
+ .twm-flow-lanes__data {
7668
+ flex: 1.2 1 440px;
7669
+ min-width: 0;
7670
+ min-height: 0;
7671
+ display: flex;
7672
+ flex-direction: column;
7673
+ }
7674
+ .twm-flow-lanes__datatabs {
7675
+ flex: 0 0 auto;
7676
+ display: flex;
7677
+ align-items: stretch;
7678
+ gap: 0 2px;
7679
+ padding: 0 12px;
7680
+ border-bottom: 1px solid var(--border-default);
7681
+ }
7682
+ .twm-flow-lanes__datastate {
7683
+ display: flex;
7684
+ align-items: center;
7685
+ gap: 6px;
7686
+ min-width: 0;
7687
+ color: #a0a0a0;
7688
+ font-size: var(--font-size-xs);
7689
+ white-space: nowrap;
7690
+ }
7691
+ .twm-flow-lanes__datastate-text {
7692
+ overflow: hidden;
7693
+ text-overflow: ellipsis;
7694
+ }
7695
+ .twm-flow-lanes__datastate-dot {
7696
+ flex: 0 0 7px;
7697
+ height: 7px;
7698
+ border-radius: 4px;
7699
+ }
7700
+ .twm-flow-lanes__datastate--ok .twm-flow-lanes__datastate-dot { background: var(--twm-flow-ok); }
7701
+ .twm-flow-lanes__datastate--busy .twm-flow-lanes__datastate-dot { background: var(--twm-flow-warning); }
7702
+ .twm-flow-lanes__datastate--error .twm-flow-lanes__datastate-dot { background: var(--twm-flow-error); }
7703
+ .twm-flow-lanes__databody {
7704
+ flex: 1 1 0;
7705
+ min-height: 0;
7706
+ display: flex;
7707
+ flex-direction: column;
7708
+ padding: 0 14px 12px;
7709
+ overflow: auto;
7710
+ }
7711
+ .twm-flow-lanes__caption {
7712
+ flex: 0 0 auto;
7713
+ margin: 0;
7714
+ padding: 8px 0 6px;
7715
+ color: #b4b4b4;
7716
+ }
7717
+ /* A DataTable fills this box, so the box has a size: one with none draws a
7718
+ * header and no rows. */
7719
+ .twm-flow-lanes__table {
7720
+ flex: 1 1 0;
7721
+ min-height: 120px;
7722
+ border: 1px solid #333;
7723
+ border-radius: 3px;
7724
+ overflow: hidden;
7725
+ }
7726
+ .twm-flow-lanes__cell--new,
7727
+ .twm-flow-lanes__cell--changed {
7728
+ background: rgba(22, 131, 196, 0.07);
7729
+ }
7730
+ .twm-flow-lanes__error {
7731
+ flex: 0 0 auto;
7732
+ margin: 8px 0 0;
7733
+ padding: 7px 10px;
7734
+ border-radius: var(--radius-sm);
7735
+ background: var(--twm-flow-error-bg);
7736
+ border: 1px solid var(--twm-flow-error-line);
7737
+ color: var(--twm-flow-error-text);
7738
+ }
7739
+ .twm-flow-lanes__nodata {
7740
+ margin: 0;
7741
+ padding: 12px 0;
7742
+ color: var(--twm-flow-muted);
7743
+ }
7744
+ .twm-flow-lanes__columns {
7745
+ list-style: none;
7746
+ margin: 0;
7747
+ padding: 0;
7748
+ display: grid;
7749
+ grid-template-columns: repeat(2, minmax(0, 1fr));
7750
+ gap: 4px 12px;
7751
+ }
7752
+ .twm-flow-lanes__column {
7753
+ display: flex;
7754
+ align-items: baseline;
7755
+ gap: 8px;
7756
+ min-width: 0;
7757
+ padding: 5px 8px;
7758
+ border-bottom: 1px solid var(--border-subtle);
7759
+ }
7760
+ .twm-flow-lanes__column--new,
7761
+ .twm-flow-lanes__column--changed {
7762
+ background: rgba(22, 131, 196, 0.14);
7763
+ }
7764
+ .twm-flow-lanes__column-name {
7765
+ font-family: var(--font-family-mono);
7766
+ font-size: var(--font-size-xs);
7767
+ color: #e6e6e6;
7768
+ }
7769
+ .twm-flow-lanes__column-type {
7770
+ color: #9a9a9a;
7771
+ font-size: var(--font-size-xs);
7772
+ }
7773
+ .twm-flow-lanes__column--new .twm-flow-lanes__column-type,
7774
+ .twm-flow-lanes__column--changed .twm-flow-lanes__column-type {
7775
+ color: #9fd0f0;
7776
+ }
7777
+ .twm-flow-lanes__column-origin {
7778
+ margin-left: auto;
7779
+ color: #a0a0a0;
7780
+ font-size: var(--font-size-xs);
7781
+ text-align: right;
7782
+ }
7783
+ .twm-flow-lanes__rejects {
7784
+ list-style: none;
7785
+ margin: 0;
7786
+ padding: 0;
7787
+ display: flex;
7788
+ flex-direction: column;
7789
+ gap: 4px;
7790
+ }
7791
+ .twm-flow-lanes__reject {
7792
+ display: flex;
7793
+ flex-wrap: wrap;
7794
+ align-items: baseline;
7795
+ gap: 4px 12px;
7796
+ padding: 7px 10px;
7797
+ background: var(--twm-flow-warning-bg);
7798
+ border: 1px solid var(--twm-flow-warning-line);
7799
+ border-radius: var(--radius-sm);
7800
+ }
7801
+ .twm-flow-lanes__reject-key {
7802
+ font-family: var(--font-family-mono);
7803
+ font-size: var(--font-size-xs);
7804
+ color: #ecc788;
7805
+ }
7806
+ .twm-flow-lanes__reject-value {
7807
+ color: var(--text-primary);
7808
+ }
7809
+ .twm-flow-lanes__reject-reason {
7810
+ flex: 1 1 260px;
7811
+ color: #d0c0a4;
7812
+ }
7813
+
7814
+ /* ── a parameter's form and a card's menu, in the kit's popover ─────── */
7815
+ .twm-flow-lanes__popover {
7816
+ min-width: 220px;
7817
+ }
7818
+ .twm-flow-lanes__form {
7819
+ display: flex;
7820
+ flex-direction: column;
7821
+ gap: 8px;
7822
+ box-sizing: border-box;
7823
+ width: 320px;
7824
+ max-width: 100%;
7825
+ padding: 12px;
7826
+ }
7827
+ .twm-flow-lanes__form-title {
7828
+ font-weight: 600;
7829
+ color: var(--text-primary);
7830
+ }
7831
+ .twm-flow-lanes__form-row {
7832
+ display: grid;
7833
+ grid-template-columns: 90px minmax(0, 1fr);
7834
+ align-items: center;
7835
+ gap: 8px;
7836
+ }
7837
+ .twm-flow-lanes__form-label {
7838
+ color: #c8c8c8;
7839
+ }
7840
+ .twm-flow-lanes__form-control {
7841
+ display: block;
7842
+ min-width: 0;
7843
+ }
7844
+ .twm-flow-lanes__form-refusal {
7845
+ margin: 0;
7846
+ color: var(--twm-flow-error);
7847
+ }
7848
+ .twm-flow-lanes__form-actions {
7849
+ display: flex;
7850
+ flex-wrap: wrap;
7851
+ justify-content: flex-end;
7852
+ gap: 6px;
7853
+ }
7854
+ .twm-flow-lanes__menu {
7855
+ display: flex;
7856
+ flex-direction: column;
7857
+ min-width: 200px;
7858
+ padding: 4px;
7859
+ }
7860
+ .twm-flow-lanes__menu-item {
7861
+ display: flex;
7862
+ align-items: center;
7863
+ gap: 8px;
7864
+ height: 28px;
7865
+ padding: 0 10px;
7866
+ border: 0;
7867
+ border-radius: 3px;
7868
+ background: transparent;
7869
+ color: var(--text-body);
7870
+ font: inherit;
7871
+ text-align: left;
7872
+ cursor: pointer;
7873
+ }
7874
+ .twm-flow-lanes__menu-item:hover,
7875
+ .twm-flow-lanes__menu-item:focus-visible {
7876
+ background: var(--state-active);
7877
+ }
7878
+ .twm-flow-lanes__menu-item:disabled {
7879
+ opacity: 0.45;
7880
+ cursor: not-allowed;
7881
+ }
7882
+ .twm-flow-lanes__menu-item--danger {
7883
+ color: var(--twm-flow-error);
7884
+ }
7885
+ .twm-flow-lanes__menu-item .material-symbols-outlined {
7886
+ font-size: 16px;
7887
+ line-height: 1;
7888
+ }
7889
+ /* ══ end FLOW · LANES ══ */