@nyaruka/temba-components 0.158.1 → 0.159.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,769 @@
1
+ /* TextIt Design System v0.1
2
+ Tokens + base + chrome + reusable components.
3
+
4
+ This stylesheet is the source of truth for the new design language.
5
+ Not yet wired into the application — see static/styleguide/ for the
6
+ showcase page that demonstrates these styles. */
7
+
8
+ /* ─── tokens ─────────────────────────────────────────────────────────── */
9
+ :root {
10
+ /* ─── primary color anchor ────────────────────────────────────────────
11
+ Single source of truth for the brand. Set as a hex value here.
12
+ `design-system.js` reads --primary on load, parses to RGB, and
13
+ dynamically writes the full accent ramp (50, 100, 200, 300, 400,
14
+ 500, 600, 700, 800, 900) onto :root — with 400 == primary and the
15
+ ramp computed outward via sRGB mixing.
16
+
17
+ If JS isn't loaded, the CSS fallback color-mix definitions below
18
+ still produce the same ramp from --primary-rgb. */
19
+ --primary: #497FCE;
20
+ --primary-rgb: 73, 127, 206;
21
+
22
+ /* accent ramp — derived from --primary-rgb via sRGB mixing.
23
+ 400 == primary; the ramp computes outward in both directions. */
24
+ --accent: rgb(var(--primary-rgb));
25
+ --accent-50: color-mix(in srgb, var(--accent) 6%, white);
26
+ --accent-100: color-mix(in srgb, var(--accent) 16%, white);
27
+ --accent-200: color-mix(in srgb, var(--accent) 32%, white);
28
+ --accent-300: color-mix(in srgb, var(--accent) 60%, white);
29
+ --accent-400: var(--accent);
30
+ --accent-500: color-mix(in srgb, var(--accent) 90%, black);
31
+ --accent-600: color-mix(in srgb, var(--accent) 80%, black);
32
+ --accent-700: color-mix(in srgb, var(--accent) 65%, black);
33
+ --accent-800: color-mix(in srgb, var(--accent) 50%, black);
34
+ --accent-900: color-mix(in srgb, var(--accent) 35%, black);
35
+
36
+ /* neutrals */
37
+ --bg: #F6F7F9;
38
+ --surface: #FFFFFF;
39
+ --surface-note: #FFF9C2;
40
+ --sunken: #F1F3F5;
41
+ --border: #E6E8EC;
42
+ --border-strong: #D2D6DC;
43
+ --border-note: #EBDF6F;
44
+ --text-1: #1A1F26; /* primary copy */
45
+ --text-2: #4D5664; /* secondary */
46
+ --text-3: #7B8593; /* tertiary, captions */
47
+ --text-4: #A2ABB8; /* disabled */
48
+
49
+ /* status — full set */
50
+ --success: #16A34A;
51
+ --success-bg: #E8F6EE;
52
+ --success-border: #BFE5CD;
53
+ --info: #2563EB;
54
+ --info-bg: #E8F0FE;
55
+ --info-border: #C7D7F8;
56
+ --warning: #B45309;
57
+ --warning-bg: #FDF3E2;
58
+ --warning-border: #F2D9A9;
59
+ --danger: #D03F3F;
60
+ --danger-bg: #FCEBEB;
61
+ --danger-border: #F4C8C8;
62
+ --neutral: #6B7280;
63
+ --neutral-bg: #EEF0F3;
64
+ --neutral-border: #D8DCE2;
65
+
66
+ /* type */
67
+ --font: "Inter", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
68
+ --font-mono: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
69
+ --w-regular: 400;
70
+ --w-medium: 500;
71
+ --w-semibold: 600;
72
+ --w-bold: 600;
73
+
74
+ /* shape */
75
+ --r: 8px;
76
+ --r-xs: 2px;
77
+ --r-sm: 4px;
78
+ --r-lg: 12px;
79
+
80
+ /* density */
81
+ --row-h: 36px;
82
+ --input-h: 34px;
83
+ --pad: 10px;
84
+ --gap: 14px;
85
+
86
+ /* shadows */
87
+ --shadow-1: 0 1px 1px rgba(15, 22, 36, 0.04), 0 1px 2px rgba(15, 22, 36, 0.04);
88
+ --shadow-2: 0 1px 1px rgba(15, 22, 36, 0.04), 0 4px 12px rgba(15, 22, 36, 0.06);
89
+ --shadow-3: 0 6px 20px rgba(15, 22, 36, 0.10), 0 2px 6px rgba(15, 22, 36, 0.06);
90
+
91
+ /* layout */
92
+ --rail-w: 56px;
93
+ --section-w: 248px;
94
+ --section-w-collapsed: 56px;
95
+ }
96
+
97
+ /* ─── base ───────────────────────────────────────────────────────────── */
98
+ .ds * { box-sizing: border-box; }
99
+ .ds {
100
+ font-family: var(--font);
101
+ font-size: 14px;
102
+ line-height: 1.5;
103
+ color: var(--text-1);
104
+ background: var(--bg);
105
+ -webkit-font-smoothing: antialiased;
106
+ font-feature-settings: "ss01", "cv11", "tnum" 0;
107
+ }
108
+ .ds h1, .ds h2, .ds h3, .ds h4 {
109
+ margin: 0;
110
+ font-weight: var(--w-semibold);
111
+ letter-spacing: -0.01em;
112
+ }
113
+ .ds p { margin: 0; }
114
+ .ds a { color: inherit; text-decoration: none; cursor: pointer; }
115
+ .ds button { font: inherit; cursor: pointer; }
116
+
117
+ /* tabular figures for numeric contexts */
118
+ .ds .t-num,
119
+ .ds .num-big,
120
+ .ds .num-rows b,
121
+ .ds .count-badge {
122
+ font-variant-numeric: tabular-nums;
123
+ }
124
+
125
+ /* ─── app shell ──────────────────────────────────────────────────────── */
126
+ .ds .app {
127
+ display: grid;
128
+ grid-template-columns: var(--rail-w) auto 1fr;
129
+ min-height: 100vh;
130
+ }
131
+
132
+ /* left rail */
133
+ .ds .rail {
134
+ background: var(--accent-400);
135
+ color: rgba(255,255,255,0.95);
136
+ display: flex;
137
+ flex-direction: column;
138
+ justify-content: space-between;
139
+ padding: 10px 0;
140
+ position: sticky;
141
+ top: 0;
142
+ height: 100vh;
143
+ }
144
+ .ds .rail-top,
145
+ .ds .rail-bot {
146
+ display: flex;
147
+ flex-direction: column;
148
+ align-items: stretch;
149
+ gap: 6px;
150
+ padding: 0 8px;
151
+ }
152
+ .ds .rail-org {
153
+ width: 40px; height: 40px;
154
+ border-radius: 999px;
155
+ background: linear-gradient(135deg, #FACC15 0%, #EAB308 100%);
156
+ color: #573E04;
157
+ font-weight: var(--w-bold);
158
+ font-size: 13px;
159
+ display: flex; align-items: center; justify-content: center;
160
+ margin: 4px auto 14px;
161
+ box-shadow: inset 0 0 0 1px rgba(255,255,255,0.4), var(--shadow-1);
162
+ }
163
+ .ds .rail-items {
164
+ display: flex;
165
+ flex-direction: column;
166
+ gap: 6px;
167
+ }
168
+ .ds .rail-item {
169
+ width: 100%;
170
+ min-height: 40px;
171
+ padding: 0 10px;
172
+ display: flex; align-items: center; gap: 10px;
173
+ border: 0; background: transparent;
174
+ color: rgba(255,255,255,0.85);
175
+ border-radius: var(--r);
176
+ transition: background 120ms, color 120ms;
177
+ position: relative;
178
+ }
179
+ .ds .rail-item:hover {
180
+ background: rgba(255,255,255,0.10);
181
+ color: #fff;
182
+ }
183
+ .ds .rail-item.is-active {
184
+ background: rgba(0,0,0,0.15);
185
+ color: #fff;
186
+ }
187
+ .ds .rail-item.is-active::before {
188
+ content: "";
189
+ position: absolute;
190
+ left: -8px; top: 8px; bottom: 8px;
191
+ width: 3px; border-radius: 0 2px 2px 0;
192
+ background: #fff;
193
+ }
194
+ .ds .rail-label {
195
+ font-size: 12.5px;
196
+ font-weight: var(--w-medium);
197
+ letter-spacing: 0.01em;
198
+ }
199
+
200
+ /* section nav */
201
+ .ds .section-nav {
202
+ width: var(--section-w);
203
+ background: var(--surface);
204
+ border-right: 1px solid var(--border);
205
+ display: flex; flex-direction: column;
206
+ position: sticky; top: 0; height: 100vh;
207
+ overflow: hidden;
208
+ transition: width 200ms cubic-bezier(0.2, 0.8, 0.2, 1);
209
+ }
210
+ .ds .section-nav.is-collapsed { width: var(--section-w-collapsed); }
211
+ .ds .section-nav.is-collapsed .sn-h h2,
212
+ .ds .section-nav.is-collapsed .sn-item span,
213
+ .ds .section-nav.is-collapsed .sn-section-label,
214
+ .ds .section-nav.is-collapsed .sn-count { display: none; }
215
+
216
+ .ds .sn-h {
217
+ height: 56px;
218
+ display: flex; align-items: center; justify-content: space-between;
219
+ padding: 0 16px;
220
+ border-bottom: 1px solid var(--border);
221
+ flex-shrink: 0;
222
+ }
223
+ .ds .sn-h h2 { font-size: 15px; color: var(--text-1); }
224
+ .ds .sn-collapse {
225
+ width: 24px; height: 24px;
226
+ display: flex; align-items: center; justify-content: center;
227
+ border: 0; background: transparent;
228
+ color: var(--text-3);
229
+ border-radius: var(--r-sm);
230
+ }
231
+ .ds .sn-collapse:hover { background: var(--sunken); color: var(--text-1); }
232
+
233
+ .ds .sn-items {
234
+ padding: 8px;
235
+ display: flex; flex-direction: column; gap: 1px;
236
+ overflow-y: auto;
237
+ }
238
+ .ds .sn-item {
239
+ display: flex; align-items: center; gap: 10px;
240
+ padding: 0 10px;
241
+ height: 32px;
242
+ border-radius: var(--r-sm);
243
+ color: var(--text-2);
244
+ font-size: 13.5px;
245
+ position: relative;
246
+ }
247
+ .ds .sn-item:hover { background: var(--sunken); color: var(--text-1); }
248
+ .ds .sn-item.is-active {
249
+ background: var(--accent-50);
250
+ color: var(--accent-700);
251
+ font-weight: var(--w-medium);
252
+ }
253
+ .ds .sn-item.is-active svg { color: var(--accent-600); }
254
+ .ds .sn-item span:first-of-type { flex: 1; }
255
+ .ds .sn-count {
256
+ font-size: 11.5px;
257
+ color: var(--text-3);
258
+ background: var(--sunken);
259
+ padding: 1px 6px;
260
+ border-radius: 999px;
261
+ font-variant-numeric: tabular-nums;
262
+ }
263
+ .ds .sn-item.is-active .sn-count {
264
+ background: var(--accent-100);
265
+ color: var(--accent-700);
266
+ }
267
+ .ds .sn-section-label {
268
+ font-size: 11px;
269
+ font-weight: var(--w-semibold);
270
+ letter-spacing: 0.06em;
271
+ text-transform: uppercase;
272
+ color: var(--text-3);
273
+ padding: 14px 10px 4px;
274
+ }
275
+
276
+ /* content area */
277
+ .ds .content {
278
+ padding: 24px 32px 80px;
279
+ max-width: 1280px;
280
+ width: 100%;
281
+ }
282
+
283
+ /* ─── page header ────────────────────────────────────────────────────── */
284
+ .ds .page-header { padding: 8px 0 24px; }
285
+ .ds .page-header-row {
286
+ display: flex; align-items: center; justify-content: space-between;
287
+ margin-bottom: 12px;
288
+ }
289
+ .ds .page-crumbs {
290
+ display: flex; align-items: center; gap: 6px;
291
+ font-size: 12.5px;
292
+ color: var(--text-3);
293
+ }
294
+ .ds .page-crumbs a { color: var(--text-2); }
295
+ .ds .page-crumbs a:hover { color: var(--accent-600); }
296
+ .ds .page-crumbs > span {
297
+ color: var(--text-1);
298
+ font-weight: var(--w-medium);
299
+ }
300
+ .ds .page-crumbs svg { color: var(--text-4); }
301
+
302
+ .ds .page-header-actions {
303
+ display: flex; align-items: center; gap: 8px;
304
+ }
305
+
306
+ .ds .page-title-row {
307
+ display: flex; align-items: flex-end; justify-content: space-between;
308
+ gap: 24px;
309
+ }
310
+ .ds .page-title-row h1 { font-size: 28px; line-height: 1.15; }
311
+ .ds .page-sub {
312
+ color: var(--text-2);
313
+ font-size: 14px;
314
+ margin-top: 4px;
315
+ max-width: 640px;
316
+ }
317
+ .ds .page-meta {
318
+ display: flex; align-items: center; gap: 12px;
319
+ color: var(--text-3);
320
+ font-size: 12.5px;
321
+ }
322
+ .ds .page-meta-sep {
323
+ width: 1px; height: 14px;
324
+ background: var(--border);
325
+ }
326
+
327
+ /* ─── buttons ────────────────────────────────────────────────────────── */
328
+ .ds .btn {
329
+ display: inline-flex; align-items: center; gap: 6px;
330
+ height: 32px;
331
+ padding: 0 12px;
332
+ border: 1px solid transparent;
333
+ border-radius: var(--r-sm);
334
+ font-size: 13px;
335
+ font-weight: var(--w-regular);
336
+ letter-spacing: -0.005em;
337
+ transition: background 120ms, border-color 120ms, color 120ms, box-shadow 120ms;
338
+ white-space: nowrap;
339
+ }
340
+ .ds .btn-sm {
341
+ height: 28px;
342
+ padding: 0 10px;
343
+ font-size: 12.5px;
344
+ }
345
+ .ds .btn-primary {
346
+ background: var(--accent-600);
347
+ color: white;
348
+ box-shadow: inset 0 1px 0 rgba(255,255,255,0.18), 0 1px 1px rgba(15,22,36,0.10);
349
+ }
350
+ .ds .btn-primary:hover { background: var(--accent-700); }
351
+ .ds .btn-secondary {
352
+ background: var(--surface);
353
+ border-color: var(--border-strong);
354
+ color: var(--text-1);
355
+ }
356
+ .ds .btn-secondary:hover { background: var(--sunken); }
357
+ .ds .btn-ghost {
358
+ background: transparent;
359
+ color: var(--text-2);
360
+ }
361
+ .ds .btn-ghost:hover { background: var(--sunken); color: var(--text-1); }
362
+ .ds .btn-danger {
363
+ background: var(--danger);
364
+ color: white;
365
+ }
366
+ .ds .btn-danger:hover {
367
+ background: color-mix(in srgb, var(--danger) 88%, black);
368
+ }
369
+ .ds .btn.is-disabled,
370
+ .ds .btn:disabled { opacity: 0.45; cursor: not-allowed; }
371
+
372
+ .ds .icon-btn {
373
+ width: 28px; height: 28px;
374
+ display: inline-flex; align-items: center; justify-content: center;
375
+ border: 0; background: transparent; color: var(--text-2);
376
+ border-radius: var(--r-sm);
377
+ transition: background 100ms, color 100ms;
378
+ }
379
+ .ds .icon-btn:hover { background: var(--sunken); color: var(--text-1); }
380
+ .ds .icon-btn.is-active { background: var(--accent-50); color: var(--accent-700); }
381
+ .ds .icon-btn-sm { width: 24px; height: 24px; }
382
+
383
+ /* ─── pills ──────────────────────────────────────────────────────────── */
384
+ .ds .pill {
385
+ display: inline-flex; align-items: center; gap: 4px;
386
+ height: 20px;
387
+ padding: 0 7px;
388
+ border-radius: 999px;
389
+ font-size: 11.5px;
390
+ font-weight: var(--w-regular);
391
+ border: 1px solid transparent;
392
+ white-space: nowrap;
393
+ max-width: 200px;
394
+ }
395
+ .ds .pill svg { flex-shrink: 0; }
396
+ .ds .pill-text { overflow: hidden; text-overflow: ellipsis; }
397
+ .ds .pill-x {
398
+ display: inline-flex; align-items: center; justify-content: center;
399
+ width: 14px; height: 14px;
400
+ margin-left: 2px; margin-right: -3px;
401
+ border: 0; background: transparent;
402
+ color: inherit; opacity: 0.55;
403
+ border-radius: 999px;
404
+ }
405
+ .ds .pill-x:hover { opacity: 1; background: rgba(0,0,0,0.08); }
406
+
407
+ /* Flow → green */
408
+ .ds .pill-flow { background: #ECF7F1; color: #166534; border-color: #D2EBDC; }
409
+ /* Recipient color — shared by contact and group. Purple reserved for future use. */
410
+ .ds .pill-contact,
411
+ .ds .pill-group { background: var(--accent-100); color: var(--accent-700); border-color: var(--accent-200); }
412
+ /* Field → amber */
413
+ .ds .pill-field { background: #FEF6E1; color: #854D0E; border-color: #F5E1AC; }
414
+ /* Keyword → mono grey */
415
+ .ds .pill-keyword { background: var(--sunken); color: var(--text-1); border-color: var(--border);
416
+ font-family: var(--font-mono); font-size: 11px; }
417
+ /* Label & neutral → quiet grey (label was previously blue; now neutral so it
418
+ doesn't compete with the recipient / flow variants for color real estate). */
419
+ .ds .pill-label,
420
+ .ds .pill-neutral { background: var(--sunken); color: var(--text-2); border-color: var(--border); }
421
+
422
+ /* ─── status ─────────────────────────────────────────────────────────── */
423
+ .ds .status {
424
+ display: inline-flex; align-items: center; gap: 6px;
425
+ padding: 2px 8px 2px 6px;
426
+ border-radius: 999px;
427
+ font-size: 12px;
428
+ font-weight: var(--w-medium);
429
+ border: 1px solid transparent;
430
+ }
431
+ .ds .status-dot {
432
+ width: 6px; height: 6px;
433
+ border-radius: 999px;
434
+ background: currentColor;
435
+ }
436
+ .ds .status-success { background: var(--success-bg); color: var(--success); border-color: var(--success-border); }
437
+ .ds .status-info { background: var(--info-bg); color: var(--info); border-color: var(--info-border); }
438
+ .ds .status-warning { background: var(--warning-bg); color: var(--warning); border-color: var(--warning-border); }
439
+ .ds .status-danger { background: var(--danger-bg); color: var(--danger); border-color: var(--danger-border); }
440
+ .ds .status-neutral { background: var(--neutral-bg); color: var(--neutral); border-color: var(--neutral-border); }
441
+
442
+ .ds .count-badge {
443
+ display: inline-flex; align-items: center; justify-content: center;
444
+ height: 18px; min-width: 18px; padding: 0 6px;
445
+ border-radius: 999px;
446
+ background: var(--sunken);
447
+ color: var(--text-2);
448
+ font-size: 11px;
449
+ font-weight: var(--w-semibold);
450
+ }
451
+ .ds .count-accent { background: var(--accent-100); color: var(--accent-700); }
452
+ .ds .count-danger { background: var(--danger-bg); color: var(--danger); }
453
+ .ds .count-success { background: var(--success-bg); color: var(--success); }
454
+
455
+ /* ─── avatar / channel icons ─────────────────────────────────────────── */
456
+ .ds .avatar {
457
+ display: inline-flex; align-items: center; justify-content: center;
458
+ border-radius: 999px;
459
+ font-weight: var(--w-bold);
460
+ letter-spacing: 0.01em;
461
+ box-shadow: inset 0 0 0 1px rgba(255,255,255,0.45);
462
+ flex-shrink: 0;
463
+ text-shadow: 0 1px 1px rgba(0,0,0,0.08);
464
+ }
465
+
466
+ .ds .ch-icon {
467
+ display: inline-flex; align-items: center; justify-content: center;
468
+ width: 22px; height: 22px;
469
+ border-radius: 999px;
470
+ color: white;
471
+ flex-shrink: 0;
472
+ }
473
+ .ds .ch-whatsapp { background: #25D366; }
474
+ .ds .ch-tel { background: #3B82F6; }
475
+ .ds .ch-fb { background: #1877F2; }
476
+ .ds .ch-web { background: var(--accent-600); }
477
+
478
+ .ds .contact-line {
479
+ display: inline-flex; align-items: center; gap: 8px;
480
+ padding: 4px 10px 4px 4px;
481
+ background: var(--sunken);
482
+ border-radius: 999px;
483
+ }
484
+ .ds .contact-name { font-size: 13px; font-weight: var(--w-medium); }
485
+ .ds .contact-num { font-size: 12px; color: var(--text-3); font-variant-numeric: tabular-nums; }
486
+
487
+ /* ─── forms ──────────────────────────────────────────────────────────── */
488
+ .ds .form-grid {
489
+ display: grid;
490
+ grid-template-columns: 1fr 1fr;
491
+ gap: 14px;
492
+ }
493
+ .ds .field { display: flex; flex-direction: column; gap: 6px; }
494
+ .ds .field-full { grid-column: 1 / -1; }
495
+ .ds .field-label {
496
+ font-size: 12.5px;
497
+ font-weight: var(--w-medium);
498
+ color: var(--text-1);
499
+ }
500
+ .ds .field-label .opt {
501
+ color: var(--text-3);
502
+ font-weight: var(--w-regular);
503
+ margin-left: 4px;
504
+ font-size: 11.5px;
505
+ }
506
+ .ds .field-help { font-size: 12px; color: var(--text-3); }
507
+
508
+ .ds .input {
509
+ display: flex; align-items: center;
510
+ font: inherit; font-size: 13.5px;
511
+ padding: 0 10px;
512
+ height: 34px;
513
+ border: 1px solid var(--border-strong);
514
+ border-radius: var(--r-sm);
515
+ background: var(--surface);
516
+ color: var(--text-1);
517
+ width: 100%;
518
+ transition: border-color 120ms, box-shadow 120ms;
519
+ }
520
+ .ds textarea.input {
521
+ padding: 8px 10px;
522
+ height: auto;
523
+ font-family: var(--font);
524
+ resize: vertical;
525
+ line-height: 1.45;
526
+ }
527
+ /* Focus styling shared by every form widget (input, textarea,
528
+ select-wrap, search-wrap, input-tokens). Border uses --accent-300
529
+ so the outline reads as a soft tinted edge; halo is a translucent
530
+ accent ring. Single knob — tweak the two values in :root to shift
531
+ every widget at once. */
532
+ .ds .input:focus,
533
+ .ds .input:focus-within {
534
+ outline: 0;
535
+ border-color: var(--accent-300);
536
+ box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 25%, transparent);
537
+ }
538
+
539
+ .ds .input-tokens {
540
+ display: flex; align-items: center; gap: 6px;
541
+ height: auto; min-height: 34px;
542
+ flex-wrap: wrap;
543
+ padding: 5px 8px;
544
+ }
545
+ .ds .input-tokens input {
546
+ border: 0; outline: 0; flex: 1; min-width: 80px;
547
+ font: inherit; font-size: 13.5px; background: transparent;
548
+ }
549
+
550
+ .ds .select-wrap {
551
+ position: relative;
552
+ display: flex; align-items: center;
553
+ height: 34px;
554
+ padding: 0 32px 0 10px;
555
+ border: 1px solid var(--border-strong);
556
+ border-radius: var(--r-sm);
557
+ background: var(--surface);
558
+ cursor: pointer;
559
+ }
560
+ .ds .select-wrap:hover {
561
+ border-color: var(--border-strong);
562
+ background: var(--sunken);
563
+ }
564
+ .ds .select-chev {
565
+ position: absolute; right: 10px;
566
+ color: var(--text-3);
567
+ }
568
+
569
+ .ds .search-wrap { position: relative; }
570
+ .ds .search-wrap .input { padding-left: 32px; padding-right: 50px; }
571
+ .ds .search-icon {
572
+ position: absolute; left: 10px; top: 50%;
573
+ transform: translateY(-50%);
574
+ color: var(--text-3);
575
+ }
576
+ .ds .search-wrap kbd {
577
+ position: absolute; right: 8px; top: 50%;
578
+ transform: translateY(-50%);
579
+ font-family: var(--font-mono);
580
+ font-size: 11px;
581
+ color: var(--text-3);
582
+ background: var(--sunken);
583
+ padding: 1px 5px;
584
+ border-radius: var(--r-xs);
585
+ border: 1px solid var(--border);
586
+ }
587
+
588
+ .ds .checkbox-row { display: flex; flex-wrap: wrap; gap: 12px; }
589
+ .ds .checkbox {
590
+ display: inline-flex; align-items: center; gap: 8px;
591
+ font-size: 13px;
592
+ padding: 6px 10px 6px 6px;
593
+ border: 1px solid var(--border);
594
+ border-radius: var(--r-sm);
595
+ background: var(--surface);
596
+ cursor: pointer;
597
+ transition: border-color 100ms, background 100ms;
598
+ }
599
+ .ds .checkbox:hover { border-color: var(--border-strong); }
600
+ .ds .check-box {
601
+ width: 16px; height: 16px;
602
+ border: 1.5px solid var(--border-strong);
603
+ border-radius: var(--r-xs);
604
+ background: var(--surface);
605
+ display: inline-flex; align-items: center; justify-content: center;
606
+ color: white;
607
+ flex-shrink: 0;
608
+ }
609
+ .ds .checkbox.is-checked {
610
+ border-color: var(--accent-200);
611
+ background: var(--accent-50);
612
+ color: var(--accent-700);
613
+ }
614
+ .ds .checkbox.is-checked .check-box {
615
+ background: var(--accent-600);
616
+ border-color: var(--accent-600);
617
+ }
618
+
619
+ /* ─── tables ─────────────────────────────────────────────────────────── */
620
+ .ds .table-wrap { width: 100%; }
621
+ .ds .t {
622
+ width: 100%;
623
+ border-collapse: separate;
624
+ border-spacing: 0;
625
+ font-size: 13px;
626
+ }
627
+ .ds .t thead th {
628
+ text-align: left;
629
+ font-size: 11px;
630
+ font-weight: var(--w-semibold);
631
+ letter-spacing: 0.06em;
632
+ text-transform: uppercase;
633
+ color: var(--text-3);
634
+ padding: 10px 12px;
635
+ border-bottom: 1px solid var(--border);
636
+ background: var(--surface);
637
+ position: sticky; top: 0;
638
+ }
639
+ .ds .t tbody td {
640
+ padding: 0 12px;
641
+ height: var(--row-h);
642
+ border-bottom: 1px solid var(--border);
643
+ vertical-align: middle;
644
+ color: var(--text-1);
645
+ }
646
+ .ds .t tbody tr { transition: background 80ms; }
647
+ .ds .t tbody tr:hover { background: var(--accent-50); }
648
+ .ds .t tbody tr:hover .row-actions { opacity: 1; }
649
+ .ds .t-check {
650
+ width: 36px;
651
+ padding-left: 12px !important;
652
+ padding-right: 0 !important;
653
+ }
654
+ .ds .t-num { text-align: right; }
655
+ .ds .t-act {
656
+ width: 96px;
657
+ text-align: right;
658
+ padding-right: 8px !important;
659
+ }
660
+ .ds .t-muted { color: var(--text-3); }
661
+ .ds .t-name {
662
+ display: flex; align-items: center; gap: 10px;
663
+ font-weight: var(--w-medium);
664
+ }
665
+ .ds .t-name-icon {
666
+ width: 22px; height: 22px;
667
+ display: inline-flex; align-items: center; justify-content: center;
668
+ background: var(--accent-50);
669
+ color: var(--accent-700);
670
+ border-radius: var(--r-sm);
671
+ }
672
+ .ds .t-ch {
673
+ display: flex; align-items: center; gap: 8px;
674
+ color: var(--text-2);
675
+ }
676
+ .ds .row-actions {
677
+ display: inline-flex; gap: 2px;
678
+ opacity: 0;
679
+ transition: opacity 100ms;
680
+ }
681
+ .ds .t-foot {
682
+ display: flex; align-items: center; justify-content: space-between;
683
+ padding: 10px 12px 4px;
684
+ font-size: 12px;
685
+ color: var(--text-3);
686
+ }
687
+
688
+ /* ─── patterns ───────────────────────────────────────────────────────── */
689
+ .ds .empty {
690
+ display: flex; flex-direction: column; align-items: center; text-align: center;
691
+ padding: 32px 24px;
692
+ gap: 8px;
693
+ }
694
+ .ds .empty-art {
695
+ width: 56px; height: 56px;
696
+ display: flex; align-items: center; justify-content: center;
697
+ background: var(--accent-50);
698
+ color: var(--accent-600);
699
+ border-radius: var(--r-lg);
700
+ margin-bottom: 6px;
701
+ }
702
+ .ds .empty h4 { font-size: 16px; }
703
+ .ds .empty p {
704
+ color: var(--text-2);
705
+ font-size: 13px;
706
+ max-width: 340px;
707
+ margin-bottom: 8px;
708
+ }
709
+
710
+ .ds .modal {
711
+ border: 1px solid var(--border);
712
+ border-radius: var(--r);
713
+ overflow: hidden;
714
+ box-shadow: var(--shadow-2);
715
+ }
716
+ .ds .modal-h {
717
+ display: flex; align-items: center; justify-content: space-between;
718
+ padding: 12px 16px;
719
+ background: var(--accent-600);
720
+ color: white;
721
+ font-size: 13px;
722
+ font-weight: var(--w-semibold);
723
+ }
724
+ .ds .modal-x {
725
+ width: 24px; height: 24px;
726
+ display: inline-flex; align-items: center; justify-content: center;
727
+ border: 0;
728
+ background: rgba(255,255,255,0.15);
729
+ color: white;
730
+ border-radius: var(--r-sm);
731
+ }
732
+ .ds .modal-x:hover { background: rgba(255,255,255,0.25); }
733
+ .ds .modal-b {
734
+ padding: 16px;
735
+ display: flex; flex-direction: column; gap: 14px;
736
+ background: var(--surface);
737
+ }
738
+ .ds .modal-f {
739
+ padding: 12px 16px;
740
+ background: var(--sunken);
741
+ border-top: 1px solid var(--border);
742
+ display: flex; justify-content: flex-end; gap: 8px;
743
+ }
744
+
745
+ .ds .ph-tabs {
746
+ display: flex; gap: 4px;
747
+ margin-top: 18px;
748
+ border-bottom: 1px solid var(--border);
749
+ }
750
+ .ds .ph-tab {
751
+ padding: 8px 14px 10px;
752
+ border: 0;
753
+ background: transparent;
754
+ color: var(--text-2);
755
+ font-size: 13px;
756
+ font-weight: var(--w-medium);
757
+ border-bottom: 2px solid transparent;
758
+ margin-bottom: -1px;
759
+ }
760
+ .ds .ph-tab:hover { color: var(--text-1); }
761
+ .ds .ph-tab.is-active {
762
+ color: var(--accent-700);
763
+ border-bottom-color: var(--accent-600);
764
+ }
765
+
766
+ /* ─── utility ────────────────────────────────────────────────────────── */
767
+ .ds .comp-row {
768
+ display: flex; align-items: center; flex-wrap: wrap; gap: 8px;
769
+ }