@zeyos/zx 4.2.0 → 4.3.4

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 (69) hide show
  1. package/CHANGELOG.md +148 -1
  2. package/README.md +5 -3
  3. package/dist/types/components/calendar/calendar-model.d.ts +22 -0
  4. package/dist/types/components/calendar/calendar.d.ts +19 -2
  5. package/dist/types/components/card-view/card-view.d.ts +1 -1
  6. package/dist/types/components/card-view/record-card.d.ts +47 -5
  7. package/dist/types/components/dialog/dialog.d.ts +6 -1
  8. package/dist/types/components/dropdown/dropdown.d.ts +5 -0
  9. package/dist/types/components/kanban-view/kanban-policy.d.ts +268 -0
  10. package/dist/types/components/kanban-view/kanban-view.d.ts +669 -24
  11. package/dist/types/components/launcher/launcher.d.ts +5 -0
  12. package/dist/types/components/message/message.d.ts +9 -1
  13. package/dist/types/components/modal/modal.d.ts +44 -7
  14. package/dist/types/components/sheet/sheet.d.ts +22 -12
  15. package/dist/types/core/component.d.ts +6 -1
  16. package/dist/types/core/overlay-host.d.ts +12 -0
  17. package/dist/types/index.d.ts +2 -1
  18. package/dist/zx-zeyos.esm.js +173 -43
  19. package/dist/zx-zeyos.esm.min.js +1 -1
  20. package/dist/zx.css +876 -230
  21. package/dist/zx.esm.js +2053 -338
  22. package/dist/zx.esm.min.js +3 -3
  23. package/dist/zx.global.js +2053 -338
  24. package/dist/zx.global.min.js +3 -3
  25. package/dist/zx.min.css +1 -1
  26. package/docs/api.json +250 -2
  27. package/docs/llms.md +67 -48
  28. package/docs/llms.txt +1 -3
  29. package/package.json +1 -2
  30. package/src/components/account-menu/account-menu.css +1 -1
  31. package/src/components/app-rail/app-rail.css +1 -1
  32. package/src/components/calendar/calendar-model.js +45 -0
  33. package/src/components/calendar/calendar.css +96 -34
  34. package/src/components/calendar/calendar.js +122 -29
  35. package/src/components/card-view/card-view.css +211 -9
  36. package/src/components/card-view/card-view.js +7 -7
  37. package/src/components/card-view/record-card.js +92 -19
  38. package/src/components/context-menu/context-menu.css +2 -2
  39. package/src/components/context-menu/context-menu.js +5 -1
  40. package/src/components/date-picker/date-picker.css +18 -11
  41. package/src/components/datebox/date-range-box.css +4 -2
  42. package/src/components/datebox/datebox.css +4 -2
  43. package/src/components/dialog/dialog.css +4 -3
  44. package/src/components/dialog/dialog.js +2 -1
  45. package/src/components/dropdown/dropdown.css +4 -2
  46. package/src/components/dropdown/dropdown.js +7 -2
  47. package/src/components/kanban-view/kanban-policy.js +412 -0
  48. package/src/components/kanban-view/kanban-view.css +480 -36
  49. package/src/components/kanban-view/kanban-view.js +1514 -235
  50. package/src/components/launcher/launcher.css +10 -8
  51. package/src/components/launcher/launcher.js +9 -2
  52. package/src/components/menu-button/menu-button.css +2 -2
  53. package/src/components/message/message.css +15 -25
  54. package/src/components/message/message.js +17 -11
  55. package/src/components/modal/modal.css +6 -4
  56. package/src/components/modal/modal.js +99 -25
  57. package/src/components/select/select.css +9 -7
  58. package/src/components/sheet/sheet.css +25 -7
  59. package/src/components/sheet/sheet.js +43 -23
  60. package/src/components/table/table.css +5 -3
  61. package/src/components/tag-picker/tag-picker.css +5 -3
  62. package/src/components/tooltip/tooltip.css +4 -2
  63. package/src/components/tooltip/tooltip.js +4 -1
  64. package/src/core/component.js +8 -3
  65. package/src/core/overlay-host.js +23 -0
  66. package/src/index.js +8 -3
  67. package/styles/tokens/dark.css +4 -0
  68. package/styles/tokens/semantic.css +83 -8
  69. package/DESIGN-SYSTEM.md +0 -182
@@ -1,9 +1,18 @@
1
1
  .zx-kanban-view {
2
+ --zx-kanban-column-width: 18.5rem;
3
+ --zx-kanban-thumbnail-size: 2rem;
4
+ --zx-kanban-card-padding-block: var(--zx-space-2);
5
+ --zx-kanban-card-padding-inline: var(--zx-space-3);
6
+ --zx-kanban-card-gap: var(--zx-space-2);
2
7
  inline-size: 100%;
3
8
  min-inline-size: 0;
4
9
  container-type: inline-size;
5
10
  }
6
11
 
12
+ .zx-kanban-view__toolbar {
13
+ margin-block-end: var(--zx-space-1);
14
+ }
15
+
7
16
  .zx-kanban-view__toolbar:empty {
8
17
  display: none;
9
18
  }
@@ -12,53 +21,57 @@
12
21
  min-inline-size: 0;
13
22
  overflow: auto;
14
23
  overscroll-behavior-inline: contain;
15
- border: 1px solid var(--zx-color-border);
16
- border-radius: var(--zx-radius-lg);
17
- background: var(--zx-color-bg-muted);
18
- padding: var(--zx-space-3);
19
24
  scrollbar-gutter: stable;
20
25
  }
21
26
 
22
27
  .zx-kanban-view__lane + .zx-kanban-view__lane {
23
- margin-block-start: var(--zx-space-4);
28
+ margin-block-start: var(--zx-space-3);
24
29
  border-block-start: 1px solid var(--zx-color-border);
25
- padding-block-start: var(--zx-space-3);
30
+ padding-block-start: var(--zx-space-2);
26
31
  }
27
32
 
28
33
  .zx-kanban-view__lane-heading,
29
34
  .zx-kanban-view__column-heading {
30
35
  display: flex;
31
36
  align-items: center;
32
- gap: var(--zx-space-2);
37
+ min-inline-size: 0;
33
38
  margin: 0;
34
39
  color: var(--zx-color-text);
35
- font-size: var(--zx-text-md);
40
+ font-size: var(--zx-text-sm);
36
41
  font-weight: var(--zx-control-font-weight);
37
- line-height: 1.3;
42
+ line-height: 1.25;
38
43
  }
39
44
 
40
45
  .zx-kanban-view__lane-heading {
46
+ min-block-size: 2rem;
47
+ gap: var(--zx-space-1);
48
+ margin-block-end: var(--zx-space-1);
49
+ }
50
+
51
+ .zx-kanban-view__column-heading {
52
+ min-block-size: 2rem;
53
+ gap: var(--zx-space-1);
41
54
  margin-block-end: var(--zx-space-2);
42
55
  }
43
56
 
44
57
  .zx-kanban-view__columns {
45
58
  display: grid;
46
59
  grid-auto-flow: column;
47
- grid-auto-columns: minmax(260px, min(82vw, 340px));
60
+ grid-auto-columns: minmax(18rem, var(--zx-kanban-column-width));
48
61
  align-items: start;
49
- gap: var(--zx-space-3);
62
+ gap: var(--zx-space-4);
50
63
  min-inline-size: max-content;
51
64
  }
52
65
 
66
+ .zx-kanban-view__columns[hidden],
67
+ .zx-kanban-view__cards[hidden] {
68
+ display: none;
69
+ }
70
+
53
71
  .zx-kanban-view__column {
54
72
  display: grid;
55
- grid-template-rows: auto minmax(64px, auto);
56
- gap: var(--zx-space-2);
73
+ grid-template-rows: auto minmax(4rem, auto);
57
74
  min-inline-size: 0;
58
- border: 1px solid var(--zx-color-border);
59
- border-radius: var(--zx-radius-md);
60
- background: var(--zx-color-bg-surface);
61
- padding: var(--zx-space-2);
62
75
  }
63
76
 
64
77
  .zx-kanban-view__column[data-collapsed="true"] {
@@ -66,6 +79,7 @@
66
79
  }
67
80
 
68
81
  .zx-kanban-view__column-label {
82
+ order: 1;
69
83
  min-inline-size: 0;
70
84
  overflow: hidden;
71
85
  text-overflow: ellipsis;
@@ -74,6 +88,7 @@
74
88
 
75
89
  .zx-kanban-view__collapse,
76
90
  .zx-kanban-view__move-handle {
91
+ position: relative;
77
92
  display: inline-grid;
78
93
  flex: 0 0 auto;
79
94
  place-items: center;
@@ -85,13 +100,15 @@
85
100
  }
86
101
 
87
102
  .zx-kanban-view__collapse {
88
- inline-size: 26px;
89
- block-size: 26px;
103
+ order: 3;
104
+ inline-size: calc(var(--zx-control-height) - var(--zx-space-1));
105
+ block-size: calc(var(--zx-control-height) - var(--zx-space-1));
106
+ margin-inline-start: auto;
90
107
  }
91
108
 
92
109
  .zx-kanban-view__move-handle {
93
- inline-size: 28px;
94
- block-size: 28px;
110
+ inline-size: calc(var(--zx-control-height) - var(--zx-space-1));
111
+ block-size: calc(var(--zx-control-height) - var(--zx-space-1));
95
112
  cursor: grab;
96
113
  touch-action: none;
97
114
  }
@@ -116,25 +133,34 @@
116
133
  }
117
134
 
118
135
  .zx-kanban-view__count {
136
+ order: 2;
119
137
  flex: 0 0 auto;
120
- margin-inline-start: auto;
121
- border-radius: var(--zx-radius-sm);
122
- background: var(--zx-color-bg-muted);
123
- padding: var(--zx-space-1) var(--zx-space-2);
124
138
  color: var(--zx-color-text-muted);
125
- font-size: var(--zx-control-font-size);
126
- font-weight: var(--zx-control-font-weight);
139
+ font-size: var(--zx-text-xs);
140
+ font-weight: 400;
141
+ line-height: 1.25;
127
142
  white-space: nowrap;
128
143
  }
129
144
 
130
145
  .zx-kanban-view__column[data-wip="limit"] .zx-kanban-view__count {
131
- background: var(--zx-color-warning-bg);
132
146
  color: var(--zx-color-warning);
147
+ font-weight: 600;
133
148
  }
134
149
 
135
150
  .zx-kanban-view__column[data-wip="exceeded"] .zx-kanban-view__count {
136
- background: var(--zx-color-danger-bg);
137
151
  color: var(--zx-color-danger);
152
+ font-weight: 600;
153
+ }
154
+
155
+ /* A lane limit reads the same way a column limit does, on the lane's own heading only. */
156
+ .zx-kanban-view__lane[data-wip="limit"] > .zx-kanban-view__lane-heading .zx-kanban-view__count {
157
+ color: var(--zx-color-warning);
158
+ font-weight: 600;
159
+ }
160
+
161
+ .zx-kanban-view__lane[data-wip="exceeded"] > .zx-kanban-view__lane-heading .zx-kanban-view__count {
162
+ color: var(--zx-color-danger);
163
+ font-weight: 600;
138
164
  }
139
165
 
140
166
  .zx-kanban-view__cards {
@@ -142,16 +168,228 @@
142
168
  display: flex;
143
169
  flex-direction: column;
144
170
  gap: var(--zx-space-2);
145
- min-block-size: 64px;
171
+ min-block-size: 4rem;
146
172
  margin: 0;
147
- border-radius: var(--zx-radius-sm);
148
- padding: var(--zx-space-1);
173
+ padding: 0;
149
174
  list-style: none;
150
175
  }
151
176
 
152
177
  .zx-kanban-view__cards > .zx-record-card {
153
178
  inline-size: 100%;
154
179
  min-inline-size: 0;
180
+ overflow: visible;
181
+ border-radius: var(--zx-radius-md);
182
+ }
183
+
184
+ .zx-kanban-view :where(.zx-record-card[data-variant="outlined"]) {
185
+ box-shadow: var(--zx-shadow-1);
186
+ }
187
+
188
+ /* The shared card anatomy stays intact; Kanban constrains media to a compact thumbnail. */
189
+ .zx-kanban-view .zx-record-card:has(> .zx-record-card__preview) {
190
+ grid-template-columns: var(--zx-kanban-thumbnail-size) minmax(0, 1fr);
191
+ align-items: start;
192
+ column-gap: var(--zx-space-2);
193
+ padding-block: var(--zx-kanban-card-padding-block);
194
+ padding-inline: var(--zx-kanban-card-padding-inline);
195
+ }
196
+
197
+ .zx-kanban-view .zx-record-card > .zx-record-card__preview {
198
+ inline-size: var(--zx-kanban-thumbnail-size);
199
+ block-size: var(--zx-kanban-thumbnail-size);
200
+ aspect-ratio: 1;
201
+ align-self: start;
202
+ border: 0;
203
+ border-radius: var(--zx-radius-sm);
204
+ }
205
+
206
+ .zx-kanban-view .zx-record-card:has(> .zx-record-card__preview) > .zx-record-card__body {
207
+ padding: 0;
208
+ }
209
+
210
+ .zx-kanban-view .zx-record-card:not(:has(> .zx-record-card__preview)) > .zx-record-card__body {
211
+ padding-block: var(--zx-kanban-card-padding-block);
212
+ padding-inline: var(--zx-kanban-card-padding-inline);
213
+ }
214
+
215
+ .zx-kanban-view .zx-record-card__body {
216
+ gap: var(--zx-kanban-card-gap);
217
+ }
218
+
219
+ .zx-kanban-view .zx-record-card__header {
220
+ gap: var(--zx-space-2);
221
+ }
222
+
223
+ .zx-kanban-view .zx-record-card__selection {
224
+ min-block-size: calc(var(--zx-control-height) - var(--zx-space-1));
225
+ }
226
+
227
+ .zx-kanban-view .zx-record-card__heading {
228
+ display: -webkit-box;
229
+ overflow: hidden;
230
+ font-size: var(--zx-text-md);
231
+ font-weight: 600;
232
+ line-height: 1.3;
233
+ -webkit-box-orient: vertical;
234
+ -webkit-line-clamp: 2;
235
+ }
236
+
237
+ .zx-kanban-view .zx-record-card__subtitle {
238
+ margin-block-start: var(--zx-space-1);
239
+ overflow: hidden;
240
+ font-size: var(--zx-text-xs);
241
+ line-height: 1.3;
242
+ text-overflow: ellipsis;
243
+ white-space: nowrap;
244
+ }
245
+
246
+ .zx-kanban-view .zx-record-card__actions {
247
+ gap: 0;
248
+ opacity: 0;
249
+ pointer-events: none;
250
+ }
251
+
252
+ .zx-kanban-view .zx-record-card:hover .zx-record-card__actions,
253
+ .zx-kanban-view .zx-record-card:focus-within .zx-record-card__actions,
254
+ .zx-kanban-view .zx-record-card[data-selected="true"] .zx-record-card__actions,
255
+ .zx-kanban-view .zx-record-card[data-grabbed="true"] .zx-record-card__actions {
256
+ opacity: 1;
257
+ pointer-events: auto;
258
+ }
259
+
260
+ .zx-kanban-view .zx-record-card__action {
261
+ inline-size: calc(var(--zx-control-height) - var(--zx-space-1));
262
+ min-block-size: calc(var(--zx-control-height) - var(--zx-space-1));
263
+ padding: 0;
264
+ }
265
+
266
+ .zx-kanban-view .zx-record-card__action-label {
267
+ position: absolute;
268
+ inline-size: 1px;
269
+ block-size: 1px;
270
+ overflow: hidden;
271
+ clip-path: inset(50%);
272
+ white-space: nowrap;
273
+ }
274
+
275
+ .zx-kanban-view .zx-record-card__metadata {
276
+ display: flex;
277
+ flex-wrap: wrap;
278
+ gap: var(--zx-space-2);
279
+ }
280
+
281
+ .zx-kanban-view .zx-record-card__field {
282
+ display: inline-flex;
283
+ align-items: center;
284
+ gap: var(--zx-space-1);
285
+ min-inline-size: 0;
286
+ max-inline-size: 100%;
287
+ min-block-size: 0;
288
+ border: 0;
289
+ padding: 0;
290
+ }
291
+
292
+ .zx-kanban-view .zx-record-card__label,
293
+ .zx-kanban-view .zx-record-card__value {
294
+ overflow: hidden;
295
+ font-size: var(--zx-text-xs);
296
+ line-height: 1.2;
297
+ text-overflow: ellipsis;
298
+ white-space: nowrap;
299
+ }
300
+
301
+ .zx-kanban-view .zx-record-card__label {
302
+ flex: none;
303
+ color: var(--zx-color-text-muted);
304
+ font-weight: 500;
305
+ }
306
+
307
+ .zx-kanban-view .zx-record-card__value {
308
+ min-inline-size: 0;
309
+ }
310
+
311
+ /* Slot fields form a quiet first tier without changing the shared record-card semantics. */
312
+ .zx-kanban-view .zx-record-card__eyebrow {
313
+ display: flex;
314
+ align-items: center;
315
+ gap: var(--zx-space-2);
316
+ min-block-size: 1.25rem;
317
+ min-inline-size: 0;
318
+ }
319
+
320
+ .zx-kanban-view .zx-record-card__eyebrow-group,
321
+ .zx-kanban-view .zx-record-card__title-prefix {
322
+ display: flex;
323
+ align-items: center;
324
+ gap: var(--zx-space-1);
325
+ min-inline-size: 0;
326
+ margin: 0;
327
+ }
328
+
329
+ .zx-kanban-view .zx-record-card__eyebrow-group[data-card-slot="eyebrow-end"] {
330
+ justify-content: flex-end;
331
+ margin-inline-start: auto;
332
+ }
333
+
334
+ .zx-kanban-view .zx-record-card__eyebrow-group .zx-record-card__label,
335
+ .zx-kanban-view .zx-record-card__title-prefix .zx-record-card__label {
336
+ position: absolute;
337
+ inline-size: 1px;
338
+ block-size: 1px;
339
+ overflow: hidden;
340
+ clip-path: inset(50%);
341
+ white-space: nowrap;
342
+ }
343
+
344
+ .zx-kanban-view .zx-record-card__eyebrow-group[data-card-slot="eyebrow-start"] .zx-record-card__field {
345
+ border-radius: var(--zx-radius-full);
346
+ background: var(--zx-color-bg-muted);
347
+ padding: calc(var(--zx-space-1) / 2) var(--zx-space-2);
348
+ }
349
+
350
+ .zx-kanban-view .zx-record-card__eyebrow-group .zx-record-card__value {
351
+ color: var(--zx-color-text-muted);
352
+ }
353
+
354
+ .zx-kanban-view .zx-record-card__eyebrow-group .zx-record-card__value > :only-child {
355
+ display: inline-flex;
356
+ align-items: center;
357
+ gap: var(--zx-space-1);
358
+ min-inline-size: 0;
359
+ }
360
+
361
+ .zx-kanban-view .zx-record-card__title-row {
362
+ display: flex;
363
+ align-items: flex-start;
364
+ gap: var(--zx-space-2);
365
+ min-inline-size: 0;
366
+ }
367
+
368
+ .zx-kanban-view .zx-record-card__title-row .zx-record-card__heading {
369
+ min-inline-size: 0;
370
+ }
371
+
372
+ .zx-kanban-view .zx-record-card__title-prefix {
373
+ flex: none;
374
+ padding-block-start: calc(var(--zx-space-1) + 1px);
375
+ }
376
+
377
+ .zx-kanban-view .zx-record-card__title-prefix .zx-record-card__value {
378
+ display: grid;
379
+ place-items: center;
380
+ color: var(--zx-color-accent);
381
+ line-height: 1;
382
+ }
383
+
384
+ .zx-kanban-view .zx-record-card__title-prefix .zx-icon {
385
+ inline-size: .5rem;
386
+ block-size: .5rem;
387
+ }
388
+
389
+ .zx-kanban-view .zx-record-card__title-prefix .zx-badge {
390
+ border: 0;
391
+ background: transparent;
392
+ padding: 0;
155
393
  }
156
394
 
157
395
  .zx-kanban-view__cards[data-drop="append"],
@@ -180,7 +418,7 @@
180
418
  .zx-kanban-view__empty {
181
419
  display: grid;
182
420
  place-items: center;
183
- min-block-size: 160px;
421
+ min-block-size: 6rem;
184
422
  color: var(--zx-color-text-muted);
185
423
  text-align: center;
186
424
  }
@@ -199,18 +437,224 @@
199
437
  }
200
438
 
201
439
  @container (max-width: 420px) {
202
- .zx-kanban-view__columns {
203
- grid-auto-columns: minmax(240px, 88vw);
440
+ .zx-kanban-view .zx-record-card__label {
441
+ position: absolute;
442
+ inline-size: 1px;
443
+ block-size: 1px;
444
+ overflow: hidden;
445
+ clip-path: inset(50%);
446
+ white-space: nowrap;
447
+ }
448
+ }
449
+
450
+ @media (hover: none), (pointer: coarse) {
451
+ .zx-kanban-view .zx-record-card__actions {
452
+ opacity: 1;
453
+ pointer-events: auto;
454
+ }
455
+ }
456
+
457
+ @media (pointer: coarse) {
458
+ .zx-kanban-view__collapse,
459
+ .zx-kanban-view__move-handle,
460
+ .zx-kanban-view .zx-record-card__action,
461
+ .zx-kanban-view .zx-record-card__selection {
462
+ inline-size: 2.75rem;
463
+ min-block-size: 2.75rem;
204
464
  }
205
465
  }
206
466
 
467
+ [data-zx-density="compact"] .zx-kanban-view {
468
+ --zx-kanban-card-padding-inline: var(--zx-space-2);
469
+ }
470
+
207
471
  @media (prefers-reduced-motion: no-preference) {
208
472
  .zx-kanban-view__collapse,
209
473
  .zx-kanban-view__move-handle,
210
- .zx-kanban-view .zx-record-card {
474
+ .zx-kanban-view .zx-record-card,
475
+ .zx-kanban-view .zx-record-card__actions {
211
476
  transition: color var(--zx-dur-fast) var(--zx-ease),
212
477
  background var(--zx-dur-fast) var(--zx-ease),
213
478
  box-shadow var(--zx-dur-fast) var(--zx-ease),
214
479
  opacity var(--zx-dur-fast) var(--zx-ease);
215
480
  }
216
481
  }
482
+
483
+ /* ── Toolbar controls ─────────────────────────────────────────────────────────────────────── */
484
+
485
+ .zx-kanban-view__toolbar {
486
+ display: flex;
487
+ flex-wrap: wrap;
488
+ align-items: center;
489
+ gap: var(--zx-space-2);
490
+ }
491
+
492
+ .zx-kanban-view__search {
493
+ position: relative;
494
+ display: inline-flex;
495
+ align-items: center;
496
+ gap: var(--zx-space-1);
497
+ min-inline-size: 0;
498
+ }
499
+
500
+ .zx-kanban-view__search > .zx-icon {
501
+ position: absolute;
502
+ inset-inline-start: var(--zx-control-pad-x);
503
+ color: var(--zx-color-text-muted);
504
+ pointer-events: none;
505
+ }
506
+
507
+ .zx-kanban-view__search-input {
508
+ min-inline-size: 12rem;
509
+ max-inline-size: 100%;
510
+ padding-inline-start: calc(var(--zx-control-pad-x) * 2 + 13px);
511
+ }
512
+
513
+ .zx-kanban-view__search-input::-webkit-search-cancel-button {
514
+ cursor: pointer;
515
+ }
516
+
517
+ .zx-kanban-view__history {
518
+ display: inline-flex;
519
+ gap: var(--zx-space-1);
520
+ margin-inline-start: auto;
521
+ }
522
+
523
+ /* ── Column scroll regions ────────────────────────────────────────────────────────────────── */
524
+
525
+ /* A fixed column height turns each card list into its own scroll region, so a long column stops
526
+ stretching the board and the headers stay reachable. */
527
+ .zx-kanban-view[data-column-scroll="true"] .zx-kanban-view__cards {
528
+ max-block-size: var(--zx-kanban-column-height);
529
+ overflow-y: auto;
530
+ overscroll-behavior-block: contain;
531
+ scrollbar-gutter: stable;
532
+ }
533
+
534
+ /* ── Add control ──────────────────────────────────────────────────────────────────────────── */
535
+
536
+ .zx-kanban-view__add {
537
+ display: inline-flex;
538
+ align-items: center;
539
+ justify-content: center;
540
+ gap: var(--zx-space-1);
541
+ margin-block-start: var(--zx-space-2);
542
+ border: 1px dashed var(--zx-color-border);
543
+ border-radius: var(--zx-radius-md);
544
+ background: transparent;
545
+ padding-block: var(--zx-space-1);
546
+ color: var(--zx-color-text-muted);
547
+ font-size: var(--zx-text-xs);
548
+ cursor: pointer;
549
+ }
550
+
551
+ .zx-kanban-view__add:hover {
552
+ border-color: var(--zx-color-border-strong);
553
+ background: var(--zx-color-bg-hover);
554
+ color: var(--zx-color-text);
555
+ }
556
+
557
+ .zx-kanban-view__add:focus-visible {
558
+ outline: none;
559
+ box-shadow: var(--zx-focus-ring);
560
+ }
561
+
562
+ .zx-kanban-view__add[hidden] {
563
+ display: none;
564
+ }
565
+
566
+ /* ── Empty column placeholder ─────────────────────────────────────────────────────────────── */
567
+
568
+ .zx-kanban-view__column-empty {
569
+ display: grid;
570
+ place-items: center;
571
+ min-block-size: 4rem;
572
+ padding: var(--zx-space-2);
573
+ color: var(--zx-color-text-muted);
574
+ font-size: var(--zx-text-xs);
575
+ text-align: center;
576
+ }
577
+
578
+ /* ── Card rules ───────────────────────────────────────────────────────────────────────────── */
579
+
580
+ /* The first matching rule paints an inline start marker. Rule badges and the card's accessible
581
+ description carry the same meaning, so the colour is never the only signal. */
582
+ .zx-kanban-view .zx-record-card[data-rule-tone] {
583
+ position: relative;
584
+ overflow: hidden;
585
+ }
586
+
587
+ .zx-kanban-view .zx-record-card[data-rule-tone]::before {
588
+ position: absolute;
589
+ inset-block: 0;
590
+ inset-inline-start: 0;
591
+ inline-size: 3px;
592
+ background: var(--zx-color-border-strong);
593
+ content: "";
594
+ }
595
+
596
+ .zx-kanban-view .zx-record-card[data-rule-tone="accent"]::before {
597
+ background: var(--zx-color-accent);
598
+ }
599
+
600
+ .zx-kanban-view .zx-record-card[data-rule-tone="success"]::before {
601
+ background: var(--zx-color-success);
602
+ }
603
+
604
+ .zx-kanban-view .zx-record-card[data-rule-tone="warning"]::before {
605
+ background: var(--zx-color-warning);
606
+ }
607
+
608
+ .zx-kanban-view .zx-record-card[data-rule-tone="danger"]::before {
609
+ background: var(--zx-color-danger);
610
+ }
611
+
612
+ .zx-kanban-view .zx-record-card[data-rule-tone="info"]::before {
613
+ background: var(--zx-color-info);
614
+ }
615
+
616
+ .zx-kanban-view__rules {
617
+ display: flex;
618
+ flex-wrap: wrap;
619
+ gap: var(--zx-space-1);
620
+ margin: 0;
621
+ }
622
+
623
+ /* ── Pointer dragging ─────────────────────────────────────────────────────────────────────── */
624
+
625
+ .zx-kanban-view__board[data-dragging="true"] {
626
+ cursor: grabbing;
627
+ user-select: none;
628
+ }
629
+
630
+ .zx-kanban-view__board[data-dragging="true"] .zx-record-card {
631
+ cursor: grabbing;
632
+ }
633
+
634
+ /* The preview tracks the pointer in the viewport and must never be hit-tested: the drop target is
635
+ resolved from the element under the pointer. */
636
+ .zx-kanban-view__drag-preview {
637
+ position: fixed;
638
+ inset-block-start: 0;
639
+ inset-inline-start: 0;
640
+ z-index: 2;
641
+ max-inline-size: var(--zx-kanban-column-width);
642
+ border: 1px solid var(--zx-color-border);
643
+ border-radius: var(--zx-radius-md);
644
+ background: var(--zx-color-bg-raised);
645
+ box-shadow: var(--zx-shadow-2);
646
+ padding: var(--zx-space-1) var(--zx-space-2);
647
+ color: var(--zx-color-text);
648
+ font-size: var(--zx-text-xs);
649
+ white-space: nowrap;
650
+ overflow: hidden;
651
+ text-overflow: ellipsis;
652
+ pointer-events: none;
653
+ translate: var(--zx-space-3) var(--zx-space-3);
654
+ }
655
+
656
+ @media (pointer: coarse) {
657
+ .zx-kanban-view__add {
658
+ min-block-size: 2.75rem;
659
+ }
660
+ }