@cratis/components 4.10.4 → 4.11.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.
@@ -0,0 +1,1612 @@
1
+ @layer cratis-components {
2
+ /* @cratis/components/Toolbar/styles — requires @cratis/components/styles/base. Areas: Common, Notifications, Toolbar. */
3
+ /* ── ./Common/ActionMenubar.css ─────────────────────────────────────── */
4
+ /* Copyright (c) Cratis. All rights reserved. */
5
+ /* Licensed under the MIT license. See LICENSE file in the project root for full license information. */
6
+
7
+ .cratis-action-menubar {
8
+ display: flex;
9
+ align-items: center;
10
+ gap: 0.25rem;
11
+ flex-wrap: wrap;
12
+ }
13
+
14
+ /* ── ./Common/Button.css ─────────────────────────────────────── */
15
+ /* Copyright (c) Cratis. All rights reserved. */
16
+ /* Licensed under the MIT license. See LICENSE file in the project root for full license information. */
17
+
18
+ .cratis-button {
19
+ display: inline-flex;
20
+ box-sizing: border-box;
21
+ min-height: var(--cratis-control-height);
22
+ padding: 0.75rem 1.25rem;
23
+ align-items: center;
24
+ justify-content: center;
25
+ gap: 0.45rem;
26
+ border: 1px solid var(--cratis-action-background);
27
+ border-radius: var(--cratis-border-radius);
28
+ background: var(--cratis-action-background);
29
+ color: var(--cratis-action-text);
30
+ font: inherit;
31
+ font-weight: 600;
32
+ line-height: 1;
33
+ cursor: pointer;
34
+ transition:
35
+ background-color 140ms ease,
36
+ border-color 140ms ease,
37
+ color 140ms ease,
38
+ opacity 140ms ease;
39
+ }
40
+ .cratis-button:not([data-tone])[data-variant='solid']:hover:not(:disabled) {
41
+ border-color: var(--cratis-action-background-hover);
42
+ background: var(--cratis-action-background-hover);
43
+ }
44
+ .cratis-button:not([data-tone])[data-variant='solid']:active:not(:disabled) {
45
+ border-color: var(--cratis-action-background-active);
46
+ background: var(--cratis-action-background-active);
47
+ }
48
+ .cratis-button:is([data-variant='outline'], [data-variant='ghost']):hover:not(:disabled) {
49
+ background: color-mix(in srgb, currentColor 4%, transparent);
50
+ }
51
+ .cratis-button:is([data-variant='outline'], [data-variant='ghost']):active:not(
52
+ :disabled
53
+ ) {
54
+ background: color-mix(in srgb, currentColor 16%, transparent);
55
+ }
56
+ .cratis-button:focus-visible {
57
+ outline: none;
58
+ box-shadow: var(--cratis-focus-ring);
59
+ }
60
+ .cratis-button:disabled {
61
+ cursor: not-allowed;
62
+ opacity: var(--cratis-disabled-opacity);
63
+ }
64
+ .cratis-button[data-size='small'] {
65
+ min-height: var(--cratis-control-height-small);
66
+ padding: 0.5rem 0.75rem;
67
+ font-size: 0.8rem;
68
+ }
69
+ .cratis-button[data-size='large'] {
70
+ min-height: var(--cratis-control-height-large);
71
+ padding: 0.875rem 1.5rem;
72
+ font-size: 1rem;
73
+ }
74
+ .cratis-button[data-shape='pill'],
75
+ .cratis-button[data-icon-only='true'] {
76
+ border-radius: 999px;
77
+ }
78
+ .cratis-button[data-icon-only='true'] {
79
+ width: var(--cratis-control-height);
80
+ padding: 0;
81
+ }
82
+ .cratis-button[data-size='small'][data-icon-only='true'] {
83
+ width: var(--cratis-control-height-small);
84
+ }
85
+ .cratis-button[data-size='large'][data-icon-only='true'] {
86
+ width: var(--cratis-control-height-large);
87
+ }
88
+
89
+ .cratis-button[data-variant='outline'] {
90
+ border-color: currentColor;
91
+ background: transparent;
92
+ color: var(--cratis-primary-color);
93
+ }
94
+ .cratis-button[data-variant='ghost'] {
95
+ border-color: transparent;
96
+ background: transparent;
97
+ color: var(--cratis-text-color);
98
+ }
99
+ .cratis-button[data-variant='link'] {
100
+ min-height: auto;
101
+ padding: 0;
102
+ border-color: transparent;
103
+ background: transparent;
104
+ color: var(--cratis-primary-color);
105
+ text-decoration: underline;
106
+ }
107
+
108
+ .cratis-button[data-tone='neutral'] {
109
+ --cratis-button-tone: var(--cratis-text-color);
110
+ --cratis-button-fill: var(--cratis-surface-100);
111
+ --cratis-button-fill-text: var(--cratis-text-color);
112
+ }
113
+ .cratis-button[data-tone='accent'] {
114
+ --cratis-button-tone: var(--cratis-info-background);
115
+ --cratis-button-fill: var(--cratis-info-background);
116
+ --cratis-button-fill-text: var(--cratis-info-text);
117
+ }
118
+ .cratis-button[data-tone='positive'] {
119
+ --cratis-button-tone: var(--cratis-success-background);
120
+ --cratis-button-fill: var(--cratis-success-background);
121
+ --cratis-button-fill-text: var(--cratis-success-text);
122
+ }
123
+ .cratis-button[data-tone='caution'] {
124
+ --cratis-button-tone: var(--cratis-warning-background);
125
+ --cratis-button-fill: var(--cratis-warning-background);
126
+ --cratis-button-fill-text: var(--cratis-warning-text);
127
+ }
128
+ .cratis-button[data-tone='critical'] {
129
+ --cratis-button-tone: var(--cratis-danger-background);
130
+ --cratis-button-fill: var(--cratis-danger-background);
131
+ --cratis-button-fill-text: var(--cratis-danger-text);
132
+ }
133
+ .cratis-button[data-tone='accent'][data-severity='help'] {
134
+ --cratis-button-tone: var(--cratis-primary-600);
135
+ --cratis-button-fill: var(--cratis-primary-600);
136
+ --cratis-button-fill-text: var(--cratis-primary-600-text);
137
+ }
138
+ .cratis-button[data-tone='neutral'][data-severity='contrast'] {
139
+ --cratis-button-tone: var(--cratis-text-color);
140
+ --cratis-button-fill: var(--cratis-text-color);
141
+ --cratis-button-fill-text: var(--cratis-surface-0);
142
+ }
143
+ .cratis-button[data-tone][data-variant='solid'] {
144
+ border-color: var(--cratis-button-fill);
145
+ background: var(--cratis-button-fill);
146
+ color: var(--cratis-button-fill-text);
147
+ }
148
+ .cratis-button[data-tone][data-variant='solid']:hover:not(:disabled) {
149
+ border-color: color-mix(in srgb, var(--cratis-button-fill) 88%, black);
150
+ background: color-mix(in srgb, var(--cratis-button-fill) 88%, black);
151
+ }
152
+ .cratis-button[data-tone][data-variant='solid']:active:not(:disabled) {
153
+ border-color: color-mix(in srgb, var(--cratis-button-fill) 76%, black);
154
+ background: color-mix(in srgb, var(--cratis-button-fill) 76%, black);
155
+ }
156
+ .cratis-button[data-tone]:is(
157
+ [data-variant='outline'],
158
+ [data-variant='ghost'],
159
+ [data-variant='link']
160
+ ) {
161
+ color: var(--cratis-button-tone);
162
+ }
163
+
164
+ .cratis-button__icon,
165
+ .cratis-button__spinner {
166
+ display: inline-flex;
167
+ flex: 0 0 auto;
168
+ }
169
+ .cratis-button__spinner {
170
+ width: 1em;
171
+ height: 1em;
172
+ border: 2px solid currentColor;
173
+ border-right-color: transparent;
174
+ border-radius: 50%;
175
+ animation: cratis-button-spin 700ms linear infinite;
176
+ }
177
+
178
+ @keyframes cratis-button-spin {
179
+ to {
180
+ transform: rotate(360deg);
181
+ }
182
+ }
183
+
184
+ @media (prefers-reduced-motion: reduce) {
185
+ .cratis-button,
186
+ .cratis-button__spinner {
187
+ transition: none;
188
+ animation: none;
189
+ }
190
+ }
191
+
192
+ @media (forced-colors: active) {
193
+ .cratis-button {
194
+ border-color: ButtonText;
195
+ }
196
+ .cratis-button:focus-visible {
197
+ outline: 2px solid Highlight;
198
+ outline-offset: 2px;
199
+ box-shadow: none;
200
+ }
201
+ }
202
+
203
+ /* ── ./Common/ComboBox.css ─────────────────────────────────────── */
204
+ /* Copyright (c) Cratis. All rights reserved. */
205
+ /* Licensed under the MIT license. See LICENSE file in the project root for full license information. */
206
+
207
+ .cratis-combobox {
208
+ display: inline-flex;
209
+ flex-direction: column;
210
+ min-width: 10rem;
211
+ color: var(--cratis-text-color);
212
+ }
213
+ .cratis-combobox__control {
214
+ display: flex;
215
+ min-height: var(--cratis-control-height);
216
+ border: 1px solid var(--cratis-control-border);
217
+ border-radius: var(--cratis-border-radius);
218
+ background: var(--cratis-control-background);
219
+ }
220
+ .cratis-combobox__control:focus-within {
221
+ border-color: var(--cratis-primary-color);
222
+ box-shadow: var(--cratis-focus-ring);
223
+ }
224
+ .cratis-combobox[data-invalid='true'] .cratis-combobox__control {
225
+ border-color: var(--cratis-red-500);
226
+ }
227
+ .cratis-combobox[data-disabled='true'] {
228
+ cursor: not-allowed;
229
+ opacity: var(--cratis-disabled-opacity);
230
+ }
231
+ .cratis-combobox__input,
232
+ .cratis-combobox__trigger {
233
+ border: 0;
234
+ background: transparent;
235
+ color: inherit;
236
+ font: inherit;
237
+ }
238
+ .cratis-combobox__input {
239
+ flex: 1 1 auto;
240
+ min-width: 0;
241
+ padding: 0.625rem 0.75rem;
242
+ outline: 0;
243
+ }
244
+ .cratis-combobox__trigger {
245
+ padding: 0 0.75rem;
246
+ color: var(--cratis-text-color-secondary);
247
+ }
248
+ .cratis-combobox__popover {
249
+ width: var(--trigger-width);
250
+ overflow: auto;
251
+ border: 1px solid var(--cratis-surface-border);
252
+ border-radius: var(--cratis-border-radius);
253
+ background: var(--cratis-surface-overlay);
254
+ box-shadow: var(--cratis-shadow-overlay);
255
+ }
256
+ .cratis-combobox__listbox {
257
+ max-height: 18rem;
258
+ padding: 0.25rem;
259
+ }
260
+ .cratis-combobox__option,
261
+ .cratis-combobox__action,
262
+ .cratis-combobox__message {
263
+ display: flex;
264
+ gap: 0.5rem;
265
+ padding: 0.5rem 0.75rem;
266
+ border-radius: var(--cratis-border-radius);
267
+ }
268
+ .cratis-combobox__listbox[data-option-layout='stacked'] .cratis-combobox__option {
269
+ flex-direction: column;
270
+ }
271
+ .cratis-combobox__option[data-focused],
272
+ .cratis-combobox__action[data-focused] {
273
+ background: var(--cratis-surface-hover);
274
+ }
275
+ .cratis-combobox__option[data-selected='true'] {
276
+ background: var(--cratis-highlight-bg);
277
+ color: var(--cratis-highlight-text-color);
278
+ }
279
+ .cratis-combobox__option[data-disabled='true'] {
280
+ opacity: var(--cratis-disabled-opacity);
281
+ }
282
+ .cratis-combobox__option-description,
283
+ .cratis-combobox__message,
284
+ .cratis-combobox__description {
285
+ color: var(--cratis-text-color-secondary);
286
+ }
287
+ .cratis-combobox__action {
288
+ border-top: 1px solid var(--cratis-surface-border);
289
+ color: var(--cratis-primary-color);
290
+ }
291
+ .cratis-combobox__description,
292
+ .cratis-combobox__error {
293
+ margin-top: 0.25rem;
294
+ font-size: 0.875em;
295
+ }
296
+ .cratis-combobox__error {
297
+ color: var(--cratis-red-500);
298
+ }
299
+
300
+ /* ── ./Common/Collections.css ─────────────────────────────────────── */
301
+ /* Copyright (c) Cratis. All rights reserved. */
302
+ /* Licensed under the MIT license. See LICENSE file in the project root for full license information. */
303
+
304
+ /* Toggle group, tabs, tag group and breadcrumbs share a token vocabulary and a focus treatment, so
305
+ they share one stylesheet rather than repeating it four times in the published aggregate. */
306
+
307
+ .cratis-toggle-group,
308
+ .cratis-tabs__list,
309
+ .cratis-tag-group,
310
+ .cratis-breadcrumbs {
311
+ display: flex;
312
+ align-items: center;
313
+ color: var(--cratis-text-color);
314
+ }
315
+ .cratis-toggle-group__option:focus-visible,
316
+ .cratis-tabs__tab:focus-visible,
317
+ .cratis-tag-group__tag:focus-visible,
318
+ .cratis-tag-group__remove:focus-visible,
319
+ .cratis-tag-group__input:focus-visible,
320
+ .cratis-breadcrumbs__link:focus-visible {
321
+ outline: none;
322
+ box-shadow: var(--cratis-focus-ring);
323
+ }
324
+ .cratis-toggle-group[data-disabled],
325
+ .cratis-tabs[data-disabled] {
326
+ cursor: not-allowed;
327
+ opacity: var(--cratis-disabled-opacity);
328
+ }
329
+ /* A disabled tag group keeps its values readable — they are information, not an inactive control,
330
+ and fading them takes their contrast below the threshold. Only the affordances dim. */
331
+ .cratis-tag-group[data-disabled] {
332
+ cursor: not-allowed;
333
+ background: var(--cratis-surface-ground);
334
+ }
335
+ .cratis-tag-group[data-disabled] .cratis-tag-group__tag {
336
+ border-style: dashed;
337
+ }
338
+
339
+ /* Toggle group */
340
+ .cratis-toggle-group {
341
+ gap: 0.125rem;
342
+ padding: 0.125rem;
343
+ border: 1px solid var(--cratis-surface-border);
344
+ border-radius: var(--cratis-border-radius);
345
+ background: var(--cratis-surface-ground);
346
+ }
347
+ .cratis-toggle-group__option {
348
+ display: inline-flex;
349
+ align-items: center;
350
+ gap: 0.35rem;
351
+ padding: 0.25rem 0.75rem;
352
+ border: 0;
353
+ border-radius: calc(var(--cratis-border-radius) - 1px);
354
+ background: transparent;
355
+ color: inherit;
356
+ font: inherit;
357
+ cursor: pointer;
358
+ }
359
+ .cratis-toggle-group__option[data-selected] {
360
+ background: var(--cratis-surface-card);
361
+ box-shadow: var(--cratis-shadow-card, none);
362
+ font-weight: 600;
363
+ }
364
+ .cratis-toggle-group__option[data-disabled] {
365
+ cursor: not-allowed;
366
+ opacity: var(--cratis-disabled-opacity);
367
+ }
368
+ .cratis-toggle-group__icon {
369
+ display: inline-flex;
370
+ }
371
+ .cratis-toggle-group[data-invalid] {
372
+ border-color: var(--cratis-red-500);
373
+ }
374
+
375
+ /* Tabs */
376
+ .cratis-tabs {
377
+ display: flex;
378
+ flex-direction: column;
379
+ }
380
+ .cratis-tabs__list {
381
+ gap: 0.25rem;
382
+ border-bottom: 1px solid var(--cratis-surface-border);
383
+ }
384
+ .cratis-tabs__tab {
385
+ padding: 0.5rem 0.75rem;
386
+ border: 0;
387
+ border-bottom: 2px solid transparent;
388
+ background: transparent;
389
+ color: var(--cratis-text-color-secondary);
390
+ font: inherit;
391
+ cursor: pointer;
392
+ }
393
+ .cratis-tabs__tab[data-selected] {
394
+ border-bottom-color: var(--cratis-primary-color);
395
+ color: var(--cratis-text-color);
396
+ font-weight: 600;
397
+ }
398
+ .cratis-tabs__tab[data-disabled] {
399
+ cursor: not-allowed;
400
+ opacity: var(--cratis-disabled-opacity);
401
+ }
402
+ .cratis-tabs__panel {
403
+ padding: 0.75rem 0;
404
+ outline: none;
405
+ }
406
+
407
+ /* Tag group */
408
+ .cratis-tag-group {
409
+ flex-wrap: wrap;
410
+ gap: 0.35rem;
411
+ min-height: var(--cratis-control-height);
412
+ padding: 0.25rem 0.5rem;
413
+ border: 1px solid var(--cratis-control-border);
414
+ border-radius: var(--cratis-border-radius);
415
+ background: var(--cratis-control-background);
416
+ }
417
+ .cratis-tag-group:focus-within {
418
+ border-color: var(--cratis-primary-color);
419
+ box-shadow: var(--cratis-focus-ring);
420
+ }
421
+ .cratis-tag-group[data-invalid] {
422
+ border-color: var(--cratis-red-500);
423
+ }
424
+ .cratis-tag-group__group,
425
+ .cratis-tag-group__list {
426
+ display: contents;
427
+ }
428
+ .cratis-tag-group__tag {
429
+ display: inline-flex;
430
+ align-items: center;
431
+ gap: 0.25rem;
432
+ padding: 0.1rem 0.5rem;
433
+ border: 1px solid var(--cratis-surface-border);
434
+ border-radius: 999px;
435
+ background: var(--cratis-surface-ground);
436
+ font-size: 0.9em;
437
+ }
438
+ .cratis-tag-group__remove {
439
+ display: inline-flex;
440
+ align-items: center;
441
+ justify-content: center;
442
+ padding: 0;
443
+ border: 0;
444
+ background: transparent;
445
+ color: var(--cratis-text-color-secondary);
446
+ line-height: 1;
447
+ cursor: pointer;
448
+ }
449
+ .cratis-tag-group__remove:hover {
450
+ color: var(--cratis-text-color);
451
+ }
452
+ .cratis-tag-group__input {
453
+ flex: 1 1 6rem;
454
+ min-width: 4rem;
455
+ border: 0;
456
+ background: transparent;
457
+ color: inherit;
458
+ font: inherit;
459
+ outline: none;
460
+ }
461
+
462
+ /* Breadcrumbs */
463
+ .cratis-breadcrumbs {
464
+ flex-wrap: wrap;
465
+ gap: 0.35rem;
466
+ padding: 0;
467
+ margin: 0;
468
+ list-style: none;
469
+ }
470
+ .cratis-breadcrumbs__item {
471
+ display: inline-flex;
472
+ align-items: center;
473
+ gap: 0.35rem;
474
+ }
475
+ .cratis-breadcrumbs__link {
476
+ border-radius: var(--cratis-border-radius);
477
+ color: var(--cratis-text-color-secondary);
478
+ text-decoration: none;
479
+ cursor: pointer;
480
+ }
481
+ .cratis-breadcrumbs__link:hover {
482
+ color: var(--cratis-text-color);
483
+ text-decoration: underline;
484
+ }
485
+ .cratis-breadcrumbs__item[data-selected] {
486
+ color: var(--cratis-text-color);
487
+ font-weight: 600;
488
+ }
489
+ .cratis-breadcrumbs__separator {
490
+ color: var(--cratis-text-color-secondary);
491
+ }
492
+
493
+ @media (forced-colors: active) {
494
+ .cratis-toggle-group__option[data-selected],
495
+ .cratis-tabs__tab[data-selected] {
496
+ forced-color-adjust: none;
497
+ background: Highlight;
498
+ color: HighlightText;
499
+ }
500
+ }
501
+
502
+ /* ── ./Common/DatePickerInput.css ─────────────────────────────────────── */
503
+ /* Copyright (c) Cratis. All rights reserved. */
504
+ /* Licensed under the MIT license. See LICENSE file in the project root for full license information. */
505
+
506
+ .cratis-date-picker {
507
+ display: inline-flex;
508
+ width: 100%;
509
+ color: var(--cratis-text-color);
510
+ }
511
+ .cratis-date-picker__picker {
512
+ width: 100%;
513
+ }
514
+ .cratis-date-picker__group {
515
+ position: relative;
516
+ display: flex;
517
+ width: 100%;
518
+ box-sizing: border-box;
519
+ min-height: var(--cratis-control-height);
520
+ align-items: center;
521
+ overflow: hidden;
522
+ border: 1px solid var(--cratis-control-border);
523
+ border-radius: var(--cratis-border-radius);
524
+ background: var(--cratis-control-background);
525
+ }
526
+ .cratis-date-picker__group[data-focus-within] {
527
+ border-color: var(--cratis-primary-color);
528
+ box-shadow: var(--cratis-focus-ring);
529
+ }
530
+ .cratis-date-picker[data-invalid='true'] .cratis-date-picker__group {
531
+ border-color: var(--cratis-red-500);
532
+ }
533
+ .cratis-date-picker[data-disabled='true'] {
534
+ opacity: var(--cratis-disabled-opacity);
535
+ }
536
+ .cratis-date-picker__input {
537
+ display: flex;
538
+ flex: 1;
539
+ flex-wrap: wrap;
540
+ min-width: 0;
541
+ padding: 0.625rem 0.75rem;
542
+ }
543
+ .cratis-date-picker__group[data-empty='true']:not([data-focus-within])
544
+ .cratis-date-picker__input {
545
+ opacity: 0;
546
+ }
547
+ .cratis-date-picker__placeholder {
548
+ position: absolute;
549
+ inset-inline-start: 0.7rem;
550
+ color: var(--cratis-text-color-secondary);
551
+ pointer-events: none;
552
+ }
553
+ .cratis-date-picker__group[data-focus-within] .cratis-date-picker__placeholder {
554
+ display: none;
555
+ }
556
+ .cratis-date-picker__segment {
557
+ padding: 0 0.1rem;
558
+ border-radius: 0.2rem;
559
+ outline: none;
560
+ font-variant-numeric: tabular-nums;
561
+ }
562
+ .cratis-date-picker__segment:not([data-type='literal']) {
563
+ display: flex;
564
+ min-width: 24px;
565
+ min-height: 24px;
566
+ align-items: center;
567
+ justify-content: center;
568
+ }
569
+ .cratis-date-picker__segment[data-placeholder] {
570
+ color: var(--cratis-text-color-secondary);
571
+ }
572
+ .cratis-date-picker__segment[data-focused] {
573
+ background: var(--cratis-highlight-bg);
574
+ color: var(--cratis-highlight-text-color);
575
+ }
576
+ .cratis-date-picker__trigger {
577
+ align-self: stretch;
578
+ min-width: var(--cratis-control-height);
579
+ border: 0;
580
+ border-inline-start: 1px solid var(--cratis-control-border);
581
+ background: transparent;
582
+ color: var(--cratis-text-color-secondary);
583
+ cursor: pointer;
584
+ }
585
+ .cratis-date-picker__trigger:hover {
586
+ background: var(--cratis-surface-hover);
587
+ color: var(--cratis-text-color);
588
+ }
589
+ .cratis-date-picker__trigger:focus-visible {
590
+ outline: none;
591
+ box-shadow: inset var(--cratis-focus-ring);
592
+ }
593
+ .cratis-date-picker__popover {
594
+ z-index: var(--cratis-z-index-overlay);
595
+ overflow: auto;
596
+ border: 1px solid var(--cratis-surface-border);
597
+ border-radius: var(--cratis-border-radius);
598
+ background: var(--cratis-surface-overlay);
599
+ color: var(--cratis-text-color);
600
+ box-shadow: var(--cratis-shadow-overlay);
601
+ }
602
+ .cratis-date-picker__dialog {
603
+ padding: 0.75rem;
604
+ outline: none;
605
+ }
606
+ .cratis-date-picker__calendar {
607
+ width: max-content;
608
+ }
609
+ .cratis-date-picker__header {
610
+ display: grid;
611
+ grid-template-columns: 2rem 1fr 2rem;
612
+ align-items: center;
613
+ gap: 0.5rem;
614
+ margin-bottom: 0.5rem;
615
+ }
616
+ .cratis-date-picker__heading {
617
+ margin: 0;
618
+ text-align: center;
619
+ font-size: 0.95rem;
620
+ }
621
+ .cratis-date-picker__nav,
622
+ .cratis-date-picker__action {
623
+ min-height: 2rem;
624
+ border: 1px solid var(--cratis-surface-border);
625
+ border-radius: calc(var(--cratis-border-radius) * 0.75);
626
+ background: transparent;
627
+ color: inherit;
628
+ cursor: pointer;
629
+ }
630
+ .cratis-date-picker__nav:hover,
631
+ .cratis-date-picker__action:hover {
632
+ background: var(--cratis-surface-hover);
633
+ }
634
+ .cratis-date-picker__nav:focus-visible,
635
+ .cratis-date-picker__action:focus-visible {
636
+ outline: none;
637
+ box-shadow: var(--cratis-focus-ring);
638
+ }
639
+ .cratis-date-picker__grid {
640
+ border-collapse: collapse;
641
+ }
642
+ .cratis-date-picker__grid th {
643
+ width: 2.25rem;
644
+ height: 2rem;
645
+ color: var(--cratis-text-color-secondary);
646
+ font-size: 0.75rem;
647
+ font-weight: 500;
648
+ }
649
+ .cratis-date-picker__cell {
650
+ display: flex;
651
+ width: 2.5rem;
652
+ height: 2.5rem;
653
+ align-items: center;
654
+ justify-content: center;
655
+ border-radius: 50%;
656
+ outline: none;
657
+ cursor: default;
658
+ }
659
+ .cratis-date-picker__cell[data-hovered] {
660
+ background: var(--cratis-surface-hover);
661
+ }
662
+ .cratis-date-picker__cell[data-selected] {
663
+ background: var(--cratis-action-background);
664
+ color: var(--cratis-action-text);
665
+ }
666
+ .cratis-date-picker__cell[data-focused] {
667
+ box-shadow: var(--cratis-focus-ring);
668
+ }
669
+ .cratis-date-picker__cell[data-disabled],
670
+ .cratis-date-picker__cell[data-outside-month] {
671
+ opacity: 0.45;
672
+ }
673
+ .cratis-date-picker__button-bar {
674
+ display: flex;
675
+ justify-content: flex-end;
676
+ gap: 0.5rem;
677
+ margin-top: 0.6rem;
678
+ padding-top: 0.6rem;
679
+ border-top: 1px solid var(--cratis-surface-border);
680
+ }
681
+ .cratis-date-picker__action {
682
+ padding: 0.35rem 0.65rem;
683
+ }
684
+
685
+ @media (forced-colors: active) {
686
+ .cratis-date-picker__group,
687
+ .cratis-date-picker__popover,
688
+ .cratis-date-picker__nav,
689
+ .cratis-date-picker__action {
690
+ border-color: CanvasText;
691
+ }
692
+ .cratis-date-picker__cell[data-selected] {
693
+ background: Highlight;
694
+ color: HighlightText;
695
+ }
696
+ }
697
+
698
+ /* ── ./Common/FormElement.css ─────────────────────────────────────── */
699
+ /* Copyright (c) Cratis. All rights reserved. */
700
+ /* Licensed under the MIT license. See LICENSE file in the project root for full license information. */
701
+
702
+ .cratis-form-element {
703
+ display: flex;
704
+ flex: 1 1 auto;
705
+ align-items: stretch;
706
+ }
707
+
708
+ .cratis-form-element__addon {
709
+ display: inline-flex;
710
+ align-items: center;
711
+ justify-content: center;
712
+ padding: 0 0.75rem;
713
+ color: var(--cratis-text-color-secondary);
714
+ background: var(--cratis-surface-100);
715
+ border: 1px solid var(--cratis-control-border);
716
+ border-right: 0;
717
+ border-top-left-radius: var(--cratis-border-radius);
718
+ border-bottom-left-radius: var(--cratis-border-radius);
719
+ }
720
+
721
+ .cratis-form-element > *:not(.cratis-form-element__addon) {
722
+ flex: 1 1 auto;
723
+ min-width: 0;
724
+ }
725
+
726
+ /* ── ./Common/NumberInput.css ─────────────────────────────────────── */
727
+ /* Copyright (c) Cratis. All rights reserved. */
728
+ /* Licensed under the MIT license. See LICENSE file in the project root for full license information. */
729
+
730
+ .cratis-number-input {
731
+ box-sizing: border-box;
732
+ width: 100%;
733
+ max-width: 100%;
734
+ color: var(--cratis-text-color);
735
+ }
736
+ .cratis-number-input__group {
737
+ display: flex;
738
+ box-sizing: border-box;
739
+ min-width: 0;
740
+ min-height: var(--cratis-control-height);
741
+ align-items: stretch;
742
+ overflow: hidden;
743
+ border: 1px solid var(--cratis-control-border);
744
+ border-radius: var(--cratis-border-radius);
745
+ background: var(--cratis-control-background);
746
+ box-shadow: var(--cratis-shadow-subtle);
747
+ }
748
+ .cratis-number-input__control,
749
+ .cratis-number-input__steps {
750
+ display: flex;
751
+ min-width: 0;
752
+ align-items: stretch;
753
+ }
754
+ .cratis-number-input__control {
755
+ flex: 1 1 auto;
756
+ }
757
+ .cratis-number-input__steps {
758
+ flex: 0 0 auto;
759
+ }
760
+ .cratis-number-input__group:focus-within {
761
+ border-color: var(--cratis-primary-color);
762
+ box-shadow: var(--cratis-focus-ring);
763
+ }
764
+ .cratis-number-input[data-invalid='true'] .cratis-number-input__group {
765
+ border-color: var(--cratis-red-500);
766
+ }
767
+ .cratis-number-input[data-disabled='true'] {
768
+ cursor: not-allowed;
769
+ opacity: var(--cratis-disabled-opacity);
770
+ }
771
+ .cratis-number-input:is([data-disabled='true'], [data-readonly='true'])
772
+ .cratis-number-input__group {
773
+ background: var(--cratis-surface-100);
774
+ }
775
+ .cratis-number-input__input {
776
+ box-sizing: border-box;
777
+ width: 100%;
778
+ min-width: 0;
779
+ min-height: var(--cratis-control-height);
780
+ padding: 0.625rem 0.75rem;
781
+ flex: 1 1 auto;
782
+ border: 0;
783
+ outline: 0;
784
+ background: transparent;
785
+ color: var(--cratis-text-color);
786
+ font: inherit;
787
+ font-variant-numeric: tabular-nums;
788
+ }
789
+ .cratis-number-input__input::placeholder {
790
+ color: var(--cratis-text-color-secondary);
791
+ }
792
+ .cratis-number-input__adornment {
793
+ display: inline-flex;
794
+ min-width: 0;
795
+ padding-inline: 0.75rem;
796
+ align-items: center;
797
+ color: var(--cratis-number-input-adornment-color);
798
+ white-space: nowrap;
799
+ }
800
+ .cratis-number-input__prefix {
801
+ padding-inline-end: 0;
802
+ }
803
+ .cratis-number-input__suffix {
804
+ padding-inline-start: 0;
805
+ }
806
+ .cratis-number-input__step {
807
+ display: inline-flex;
808
+ box-sizing: border-box;
809
+ width: var(--cratis-control-height);
810
+ min-width: 2.75rem;
811
+ min-height: var(--cratis-control-height);
812
+ padding: 0;
813
+ align-items: center;
814
+ justify-content: center;
815
+ border: 0;
816
+ border-inline-start: 1px solid var(--cratis-control-border);
817
+ background: var(--cratis-number-input-step-background);
818
+ color: var(--cratis-text-color);
819
+ font: inherit;
820
+ cursor: pointer;
821
+ }
822
+ .cratis-number-input__step:hover:not(:disabled) {
823
+ background: var(--cratis-number-input-step-background-hover);
824
+ }
825
+ .cratis-number-input__step:focus-visible {
826
+ outline: 2px solid var(--cratis-primary-color);
827
+ outline-offset: -3px;
828
+ }
829
+ .cratis-number-input__step:disabled {
830
+ cursor: not-allowed;
831
+ opacity: var(--cratis-disabled-opacity);
832
+ }
833
+ .cratis-number-input__description,
834
+ .cratis-number-input__error {
835
+ display: block;
836
+ margin-block-start: 0.35rem;
837
+ line-height: 1.4;
838
+ }
839
+ .cratis-number-input__description {
840
+ color: var(--cratis-text-color-secondary);
841
+ }
842
+ .cratis-number-input__error {
843
+ color: var(--cratis-red-500);
844
+ }
845
+
846
+ @media (max-width: 24rem) {
847
+ .cratis-number-input__group {
848
+ flex-wrap: wrap;
849
+ }
850
+ .cratis-number-input__control,
851
+ .cratis-number-input__steps {
852
+ width: 100%;
853
+ flex-basis: 100%;
854
+ border-block-start: 1px solid var(--cratis-control-border);
855
+ }
856
+ .cratis-number-input__step {
857
+ width: 50%;
858
+ min-width: 0;
859
+ flex: 1 1 50%;
860
+ }
861
+ .cratis-number-input__step:first-child {
862
+ border-inline-start: 0;
863
+ }
864
+ }
865
+
866
+ @media (forced-colors: active) {
867
+ .cratis-number-input__group,
868
+ .cratis-number-input__step {
869
+ border-color: CanvasText;
870
+ }
871
+ .cratis-number-input__group:focus-within,
872
+ .cratis-number-input__step:focus-visible {
873
+ outline: 2px solid Highlight;
874
+ outline-offset: 2px;
875
+ box-shadow: none;
876
+ }
877
+ }
878
+
879
+ /* ── ./Common/Primitives.css ─────────────────────────────────────── */
880
+ /* Copyright (c) Cratis. All rights reserved. */
881
+ /* Licensed under the MIT license. See LICENSE file in the project root for full license information. */
882
+
883
+ .cratis-text-input,
884
+ .cratis-text-area {
885
+ box-sizing: border-box;
886
+ min-height: var(--cratis-control-height);
887
+ padding: 0.625rem 0.75rem;
888
+ border: 1px solid var(--cratis-control-border);
889
+ border-radius: var(--cratis-border-radius);
890
+ background: var(--cratis-control-background);
891
+ color: var(--cratis-text-color);
892
+ font: inherit;
893
+ box-shadow: var(--cratis-shadow-subtle);
894
+ }
895
+ .cratis-text-area {
896
+ resize: vertical;
897
+ }
898
+ .cratis-text-input::placeholder,
899
+ .cratis-text-area::placeholder {
900
+ color: var(--cratis-text-color-secondary);
901
+ }
902
+ .cratis-text-input:focus-visible,
903
+ .cratis-text-area:focus-visible {
904
+ outline: none;
905
+ border-color: var(--cratis-primary-color);
906
+ box-shadow: var(--cratis-focus-ring);
907
+ }
908
+ .cratis-text-input:is(:disabled, [data-readonly='true']),
909
+ .cratis-text-area:is(:disabled, [data-readonly='true']) {
910
+ background: var(--cratis-surface-100);
911
+ }
912
+ .cratis-text-input:disabled,
913
+ .cratis-text-area:disabled {
914
+ cursor: not-allowed;
915
+ opacity: var(--cratis-disabled-opacity);
916
+ }
917
+ .cratis-text-input[data-invalid='true'],
918
+ .cratis-text-area[data-invalid='true'] {
919
+ border-color: var(--cratis-red-500);
920
+ }
921
+
922
+ .cratis-choice {
923
+ position: relative;
924
+ display: inline-flex;
925
+ align-items: center;
926
+ gap: 0.5rem;
927
+ color: var(--cratis-text-color);
928
+ cursor: pointer;
929
+ }
930
+ .cratis-choice[data-disabled='true'] {
931
+ cursor: not-allowed;
932
+ opacity: var(--cratis-disabled-opacity);
933
+ }
934
+ .cratis-choice[data-readonly='true']:not([data-disabled='true']) {
935
+ cursor: default;
936
+ }
937
+ .cratis-choice__input {
938
+ position: absolute;
939
+ width: 1px;
940
+ height: 1px;
941
+ margin: -1px;
942
+ overflow: hidden;
943
+ clip: rect(0 0 0 0);
944
+ clip-path: inset(50%);
945
+ white-space: nowrap;
946
+ }
947
+ .cratis-checkbox__box,
948
+ .cratis-radio__box,
949
+ .cratis-switch__control {
950
+ display: inline-flex;
951
+ box-sizing: border-box;
952
+ flex: 0 0 auto;
953
+ align-items: center;
954
+ border: 1px solid var(--cratis-control-border);
955
+ background: var(--cratis-control-background);
956
+ }
957
+ .cratis-checkbox__box,
958
+ .cratis-radio__box {
959
+ width: 1.25rem;
960
+ height: 1.25rem;
961
+ justify-content: center;
962
+ }
963
+ .cratis-checkbox__box {
964
+ border-radius: var(--cratis-border-radius);
965
+ }
966
+ .cratis-checkbox__indicator {
967
+ color: var(--cratis-primary-color-text);
968
+ font-size: 0.85rem;
969
+ line-height: 1;
970
+ opacity: 0;
971
+ }
972
+ .cratis-radio__box {
973
+ border-radius: 50%;
974
+ }
975
+ .cratis-radio__indicator {
976
+ width: 0.65rem;
977
+ height: 0.65rem;
978
+ border-radius: 50%;
979
+ background: var(--cratis-primary-color);
980
+ opacity: 0;
981
+ }
982
+ .cratis-switch__control {
983
+ width: 2.5rem;
984
+ height: 1.4rem;
985
+ padding: 0.15rem;
986
+ border-radius: 999px;
987
+ background: var(--cratis-surface-100);
988
+ transition: background-color 140ms ease;
989
+ }
990
+ .cratis-switch__handle {
991
+ width: 1rem;
992
+ height: 1rem;
993
+ border-radius: 50%;
994
+ background: var(--cratis-control-background);
995
+ box-shadow: var(--cratis-shadow-subtle);
996
+ transition: transform 140ms ease;
997
+ }
998
+ .cratis-choice__input:focus-visible
999
+ + :is(.cratis-checkbox__box, .cratis-radio__box, .cratis-switch__control) {
1000
+ box-shadow: var(--cratis-focus-ring);
1001
+ }
1002
+ .cratis-choice__input:checked + .cratis-checkbox__box,
1003
+ .cratis-choice__input:checked + .cratis-switch__control {
1004
+ border-color: var(--cratis-primary-color);
1005
+ background: var(--cratis-primary-color);
1006
+ }
1007
+ .cratis-choice__input:checked + .cratis-checkbox__box .cratis-checkbox__indicator,
1008
+ .cratis-choice__input:checked + .cratis-radio__box .cratis-radio__indicator {
1009
+ opacity: 1;
1010
+ }
1011
+ .cratis-choice__input:checked + .cratis-radio__box {
1012
+ border-color: var(--cratis-primary-color);
1013
+ }
1014
+ .cratis-choice__input:checked + .cratis-switch__control .cratis-switch__handle {
1015
+ transform: translateX(1.05rem);
1016
+ }
1017
+ .cratis-choice:dir(rtl)
1018
+ .cratis-choice__input:checked
1019
+ + .cratis-switch__control
1020
+ .cratis-switch__handle {
1021
+ transform: translateX(-1.05rem);
1022
+ }
1023
+ .cratis-choice[data-invalid='true']
1024
+ :is(.cratis-checkbox__box, .cratis-radio__box, .cratis-switch__control) {
1025
+ border-color: var(--cratis-red-500);
1026
+ }
1027
+
1028
+ .cratis-surface {
1029
+ box-sizing: border-box;
1030
+ border: 1px solid var(--cratis-surface-border);
1031
+ border-radius: var(--cratis-border-radius);
1032
+ background: var(--cratis-surface-card);
1033
+ color: var(--cratis-text-color);
1034
+ box-shadow: var(--cratis-shadow-subtle);
1035
+ }
1036
+
1037
+ @media (prefers-reduced-motion: reduce) {
1038
+ .cratis-switch__control,
1039
+ .cratis-switch__handle {
1040
+ transition: none;
1041
+ }
1042
+ }
1043
+
1044
+ @media (forced-colors: active) {
1045
+ .cratis-text-input,
1046
+ .cratis-text-area,
1047
+ .cratis-checkbox__box,
1048
+ .cratis-radio__box,
1049
+ .cratis-switch__control,
1050
+ .cratis-surface {
1051
+ border-color: CanvasText;
1052
+ }
1053
+ .cratis-choice__input:checked
1054
+ + :is(.cratis-checkbox__box, .cratis-switch__control) {
1055
+ background: Highlight;
1056
+ }
1057
+ .cratis-choice__input:checked + .cratis-radio__box .cratis-radio__indicator {
1058
+ background: Highlight;
1059
+ }
1060
+ .cratis-choice__input:focus-visible
1061
+ + :is(.cratis-checkbox__box, .cratis-radio__box, .cratis-switch__control),
1062
+ .cratis-text-input:focus-visible,
1063
+ .cratis-text-area:focus-visible {
1064
+ outline: 2px solid Highlight;
1065
+ outline-offset: 2px;
1066
+ box-shadow: none;
1067
+ }
1068
+ }
1069
+
1070
+ /* ── ./Common/Tooltip.css ─────────────────────────────────────── */
1071
+ /* Copyright (c) Cratis. All rights reserved. */
1072
+ /* Licensed under the MIT license. See LICENSE file in the project root for full license information. */
1073
+
1074
+ /* ── Tooltip bubble ──────────────────────────────────────────────────────── */
1075
+ .cratis-tooltip-popup {
1076
+ background: var(--cratis-surface-100);
1077
+ color: var(--cratis-text-color);
1078
+ border: 1px solid var(--cratis-surface-border);
1079
+ box-shadow: var(--cratis-shadow-overlay);
1080
+ border-radius: var(--cratis-border-radius);
1081
+ padding: 0.25rem 0.5rem;
1082
+ font-size: 0.75rem;
1083
+ font-family: inherit;
1084
+ max-width: 24rem;
1085
+ z-index: var(--cratis-z-index-tooltip);
1086
+ }
1087
+
1088
+ /* ── ./Notifications/Toaster.css ─────────────────────────────────────── */
1089
+ /* Copyright (c) Cratis. All rights reserved. */
1090
+ /* Licensed under the MIT license. See LICENSE file in the project root for full license information. */
1091
+
1092
+ .cratis-toaster {
1093
+ position: fixed;
1094
+ z-index: var(--cratis-z-index-toast);
1095
+ display: flex;
1096
+ width: min(26rem, calc(100vw - 2rem));
1097
+ flex-direction: column;
1098
+ gap: 0.75rem;
1099
+ pointer-events: none;
1100
+ }
1101
+ .cratis-toaster[data-position^='top'] {
1102
+ top: 1rem;
1103
+ }
1104
+ .cratis-toaster[data-position^='bottom'] {
1105
+ bottom: 1rem;
1106
+ }
1107
+ .cratis-toaster[data-position$='left'] {
1108
+ left: 1rem;
1109
+ }
1110
+ .cratis-toaster[data-position$='right'] {
1111
+ right: 1rem;
1112
+ }
1113
+ .cratis-toaster[data-position$='center'] {
1114
+ left: 50%;
1115
+ transform: translateX(-50%);
1116
+ }
1117
+
1118
+ .cratis-toast {
1119
+ display: flex;
1120
+ min-width: 18rem;
1121
+ max-width: 26rem;
1122
+ padding: 0.75rem 1rem;
1123
+ align-items: flex-start;
1124
+ gap: 0.625rem;
1125
+ border: 1px solid var(--cratis-surface-border);
1126
+ border-inline-start: 4px solid var(--cratis-surface-border);
1127
+ border-radius: var(--cratis-border-radius);
1128
+ background: var(--cratis-surface-overlay);
1129
+ color: var(--cratis-text-color);
1130
+ box-shadow: var(--cratis-shadow-toast);
1131
+ pointer-events: auto;
1132
+ }
1133
+ .cratis-toast__content {
1134
+ display: flex;
1135
+ min-width: 0;
1136
+ flex: 1;
1137
+ flex-direction: column;
1138
+ gap: 0.125rem;
1139
+ }
1140
+ .cratis-toast__title {
1141
+ font-weight: 600;
1142
+ }
1143
+ .cratis-toast__description {
1144
+ color: var(--cratis-text-color-secondary);
1145
+ font-size: 0.875rem;
1146
+ white-space: pre-line;
1147
+ }
1148
+ .cratis-toast__icon {
1149
+ flex: 0 0 auto;
1150
+ }
1151
+ .cratis-toast__close {
1152
+ display: inline-flex;
1153
+ width: 1.75rem;
1154
+ height: 1.75rem;
1155
+ padding: 0;
1156
+ align-items: center;
1157
+ justify-content: center;
1158
+ border: 0;
1159
+ border-radius: 50%;
1160
+ background: transparent;
1161
+ color: var(--cratis-text-color-secondary);
1162
+ cursor: pointer;
1163
+ }
1164
+ .cratis-toast__close:hover {
1165
+ background: var(--cratis-surface-hover);
1166
+ color: var(--cratis-text-color);
1167
+ }
1168
+ .cratis-toast__close:focus-visible {
1169
+ outline: none;
1170
+ box-shadow: var(--cratis-focus-ring);
1171
+ }
1172
+ .cratis-toast__action {
1173
+ align-self: flex-start;
1174
+ margin-top: 0.4rem;
1175
+ }
1176
+ .cratis-toast[data-loading='true'] .cratis-toast__icon {
1177
+ animation: cratis-toast-spin 800ms linear infinite;
1178
+ }
1179
+ .cratis-toast[data-severity='success'] {
1180
+ border-inline-start-color: var(--cratis-green-500);
1181
+ }
1182
+ .cratis-toast[data-severity='info'] {
1183
+ border-inline-start-color: var(--cratis-primary-color);
1184
+ }
1185
+ .cratis-toast[data-severity='warn'] {
1186
+ border-inline-start-color: var(--cratis-orange-500);
1187
+ }
1188
+ .cratis-toast[data-severity='error'] {
1189
+ border-inline-start-color: var(--cratis-red-500);
1190
+ }
1191
+ .cratis-toast[data-severity='success'] .cratis-toast__icon {
1192
+ color: var(--cratis-green-500);
1193
+ }
1194
+ .cratis-toast[data-severity='info'] .cratis-toast__icon {
1195
+ color: var(--cratis-primary-color);
1196
+ }
1197
+ .cratis-toast[data-severity='warn'] .cratis-toast__icon {
1198
+ color: var(--cratis-orange-500);
1199
+ }
1200
+ .cratis-toast[data-severity='error'] .cratis-toast__icon {
1201
+ color: var(--cratis-red-500);
1202
+ }
1203
+
1204
+ @keyframes cratis-toast-spin {
1205
+ to {
1206
+ transform: rotate(360deg);
1207
+ }
1208
+ }
1209
+ @media (prefers-reduced-motion: reduce) {
1210
+ .cratis-toast__icon {
1211
+ animation: none !important;
1212
+ }
1213
+ }
1214
+ @media (forced-colors: active) {
1215
+ .cratis-toast {
1216
+ border-color: CanvasText;
1217
+ }
1218
+ .cratis-toast__close:focus-visible {
1219
+ outline: 2px solid Highlight;
1220
+ outline-offset: 2px;
1221
+ box-shadow: none;
1222
+ }
1223
+ }
1224
+
1225
+ /* ── ./Toolbar/Toolbar.css ─────────────────────────────────────── */
1226
+ /* Copyright (c) Cratis. All rights reserved. */
1227
+ /* Licensed under the MIT license. See LICENSE file in the project root for full license information. */
1228
+
1229
+ /* ── Toolbar container ───────────────────────────────────────────────────── */
1230
+ .toolbar {
1231
+ background: var(--cratis-surface-card);
1232
+ border: 1px solid var(--cratis-surface-border);
1233
+ box-shadow: var(--cratis-shadow-overlay);
1234
+ }
1235
+
1236
+ /* ── Toolbar button ──────────────────────────────────────────────────────── */
1237
+ .toolbar-button {
1238
+ color: var(--cratis-text-color-secondary);
1239
+ background: transparent;
1240
+ border: none;
1241
+ transition:
1242
+ background 0.15s,
1243
+ color 0.15s;
1244
+ }
1245
+
1246
+ .toolbar-button:hover {
1247
+ background: var(--cratis-surface-100);
1248
+ color: var(--cratis-text-color);
1249
+ }
1250
+
1251
+ .toolbar-button--active {
1252
+ background: var(--cratis-action-background);
1253
+ color: var(--cratis-action-text);
1254
+ }
1255
+
1256
+ .toolbar-button--active:hover {
1257
+ background: var(--cratis-action-background-hover);
1258
+ color: var(--cratis-action-text);
1259
+ }
1260
+
1261
+ .toolbar-button--draggable {
1262
+ cursor: grab;
1263
+ }
1264
+
1265
+ .toolbar-button--draggable:active {
1266
+ cursor: grabbing;
1267
+ }
1268
+
1269
+ .toolbar-button__text {
1270
+ font-size: 0.875rem;
1271
+ font-weight: 600;
1272
+ line-height: 1;
1273
+ white-space: nowrap;
1274
+ }
1275
+
1276
+ /* ── Toolbar project name label ──────────────────────────────────────────── */
1277
+ .toolbar-project-name {
1278
+ padding: 0 8px;
1279
+ font-size: 0.875rem;
1280
+ font-weight: 500;
1281
+ color: var(--cratis-text-color);
1282
+ white-space: nowrap;
1283
+ }
1284
+
1285
+ /* ── Toolbar section (context switching) ────────────────────────────────── */
1286
+
1287
+ /*
1288
+ * The section is a fixed-size container that transitions smoothly between
1289
+ * the dimensions required by each context.
1290
+ * Overflow stays visible in the settled state so absolutely-positioned
1291
+ * children (e.g. fan-out panels) can extend beyond the section's bounds.
1292
+ * During a context resize transition, a temporary modifier clips incoming
1293
+ * content so buttons do not float outside the current toolbar bounds.
1294
+ */
1295
+ .toolbar-section {
1296
+ position: relative;
1297
+ transition:
1298
+ width 0.35s cubic-bezier(0.4, 0, 0.2, 1),
1299
+ height 0.35s cubic-bezier(0.4, 0, 0.2, 1);
1300
+ }
1301
+
1302
+ .toolbar-section--transitioning {
1303
+ overflow: hidden;
1304
+ }
1305
+
1306
+ /*
1307
+ * Every context is absolutely stacked at the top-left of the section.
1308
+ * Only the active one is visible; the others fade out and lose pointer events.
1309
+ */
1310
+ .toolbar-context {
1311
+ position: absolute;
1312
+ top: 0;
1313
+ left: 0;
1314
+ transition: opacity 0.2s ease;
1315
+ }
1316
+
1317
+ .toolbar-context--active {
1318
+ opacity: 1;
1319
+ pointer-events: auto;
1320
+ }
1321
+
1322
+ .toolbar-context--inactive {
1323
+ opacity: 0;
1324
+ pointer-events: none;
1325
+ }
1326
+
1327
+ /* ── Toolbar separator ───────────────────────────────────────────────────── */
1328
+
1329
+ .toolbar-separator {
1330
+ background: var(--cratis-surface-border);
1331
+ flex-shrink: 0;
1332
+ align-self: stretch;
1333
+ }
1334
+
1335
+ /* Separator inside a vertical toolbar — renders as a horizontal rule */
1336
+ .toolbar-separator--in-vertical {
1337
+ height: 1px;
1338
+ margin: 0.125rem 0.25rem;
1339
+ }
1340
+
1341
+ /* Separator inside a horizontal toolbar — renders as a vertical rule */
1342
+ .toolbar-separator--in-horizontal {
1343
+ width: 1px;
1344
+ margin: 0.25rem 0.125rem;
1345
+ }
1346
+
1347
+ /* ── Toolbar fan-out item ────────────────────────────────────────────────── */
1348
+
1349
+ /*
1350
+ * The wrapper provides the positioning context for the absolutely-placed panel.
1351
+ */
1352
+ .toolbar-fanout-item {
1353
+ position: relative;
1354
+ }
1355
+
1356
+ /*
1357
+ * The fan-out panel is a floating pill that mirrors the Toolbar container style.
1358
+ * When collapsed, it's hidden. When expanded, it appears elevated at the same
1359
+ * position as the trigger button, with the trigger button as the first item.
1360
+ * Vertically centered with where the collapsed button would be.
1361
+ */
1362
+ .toolbar-fanout-panel {
1363
+ position: absolute;
1364
+ top: 50%;
1365
+ left: calc(-0.5rem - 1px);
1366
+ transform: translateY(-50%);
1367
+ display: inline-flex;
1368
+ flex-direction: row;
1369
+ align-items: center;
1370
+ gap: 0.25rem;
1371
+ padding: 0.5rem;
1372
+ background: var(--cratis-surface-card);
1373
+ border: 1px solid var(--cratis-surface-border);
1374
+ box-shadow: var(--cratis-shadow-overlay);
1375
+ border-radius: 1rem;
1376
+ white-space: nowrap;
1377
+ z-index: 10;
1378
+ pointer-events: none;
1379
+ opacity: 0;
1380
+ clip-path: inset(0 100% 0 0 round 1rem);
1381
+ transition:
1382
+ clip-path 0.35s cubic-bezier(0.4, 0, 0.2, 1),
1383
+ opacity 0.2s ease;
1384
+ }
1385
+
1386
+ /* Panel fans out to the left — reveal animates right → left */
1387
+ .toolbar-fanout-panel--left {
1388
+ left: auto;
1389
+ right: calc(-0.5rem - 1px);
1390
+ clip-path: inset(0 0 0 100% round 1rem);
1391
+ }
1392
+
1393
+ .toolbar-fanout-panel--up {
1394
+ top: auto;
1395
+ right: auto;
1396
+ bottom: calc(100% + 0.5rem);
1397
+ left: 50%;
1398
+ transform: translateX(-50%);
1399
+ clip-path: inset(100% 0 0 0 round 1rem);
1400
+ }
1401
+
1402
+ .toolbar-fanout-panel--down {
1403
+ top: calc(100% + 0.5rem);
1404
+ right: auto;
1405
+ left: 50%;
1406
+ transform: translateX(-50%);
1407
+ clip-path: inset(0 0 100% 0 round 1rem);
1408
+ }
1409
+
1410
+ /* Expanded state — fully visible, pointer events restored */
1411
+ .toolbar-fanout-panel--visible {
1412
+ clip-path: inset(0 0 0 0 round 1rem);
1413
+ opacity: 1;
1414
+ pointer-events: auto;
1415
+ }
1416
+
1417
+ /*
1418
+ * Reveal complete. The clip-path did its job — the wipe cannot run without it,
1419
+ * because `clip-path: none` is a discrete value that snaps instead of
1420
+ * interpolating. But clip-path also clips every descendant, so leaving a zero
1421
+ * inset in place slices off the hover tooltips of the outermost buttons, which
1422
+ * paint outside the panel by design.
1423
+ *
1424
+ * ToolbarFanOutItem therefore adds this class once the reveal transition ends,
1425
+ * and takes it off again (restoring an interpolable inset) before the close
1426
+ * transition starts — so both wipes keep their exact timing and a settled panel
1427
+ * clips nothing.
1428
+ */
1429
+ .toolbar-fanout-panel--settled {
1430
+ clip-path: none;
1431
+ }
1432
+
1433
+ /* ── Toolbar folder ──────────────────────────────────────────────────────── */
1434
+
1435
+ .toolbar-folder-item {
1436
+ position: relative;
1437
+ }
1438
+
1439
+ /*
1440
+ * Folder panel is a floating grid that grows naturally with item count.
1441
+ * The trigger stays in place while the panel animates in/out.
1442
+ */
1443
+ .toolbar-folder-panel {
1444
+ position: absolute;
1445
+ top: 50%;
1446
+ left: calc(100% + 0.75rem);
1447
+ transform: translateY(-50%) scale(0.92);
1448
+ transform-origin: left center;
1449
+ display: grid;
1450
+ grid-auto-rows: minmax(2.5rem, auto);
1451
+ gap: 0.25rem;
1452
+ padding: 0.5rem;
1453
+ background: var(--cratis-surface-card);
1454
+ border: 1px solid var(--cratis-surface-border);
1455
+ box-shadow: var(--cratis-shadow-overlay);
1456
+ border-radius: 1rem;
1457
+ z-index: 10;
1458
+ pointer-events: none;
1459
+ opacity: 0;
1460
+ clip-path: inset(0 100% 0 0 round 1rem);
1461
+ transition:
1462
+ clip-path 0.35s cubic-bezier(0.4, 0, 0.2, 1),
1463
+ transform 0.35s cubic-bezier(0.4, 0, 0.2, 1),
1464
+ opacity 0.2s ease;
1465
+ }
1466
+
1467
+ .toolbar-folder-panel--left {
1468
+ left: auto;
1469
+ right: calc(100% + 0.75rem);
1470
+ transform-origin: right center;
1471
+ clip-path: inset(0 0 0 100% round 1rem);
1472
+ }
1473
+
1474
+ .toolbar-folder-panel--visible {
1475
+ clip-path: none;
1476
+ transform: translateY(-50%) scale(1);
1477
+ opacity: 1;
1478
+ pointer-events: auto;
1479
+ }
1480
+
1481
+ /* List-mode folder panel — vertical stack instead of a grid */
1482
+ .toolbar-folder-panel--list {
1483
+ display: flex;
1484
+ flex-direction: column;
1485
+ min-width: 10rem;
1486
+ }
1487
+
1488
+ /* ── Toolbar button — list mode ──────────────────────────────────────────── */
1489
+
1490
+ /*
1491
+ * Inside a list-mode folder the button fills the available width and renders
1492
+ * its icon and title label side by side, left-aligned.
1493
+ */
1494
+ .toolbar-button--list {
1495
+ width: 100%;
1496
+ justify-content: flex-start;
1497
+ }
1498
+
1499
+ .toolbar-button__label {
1500
+ font-size: 0.875rem;
1501
+ font-weight: 500;
1502
+ color: inherit;
1503
+ white-space: nowrap;
1504
+ }
1505
+
1506
+ /* ── Toolbar group ───────────────────────────────────────────────────────── */
1507
+
1508
+ /*
1509
+ * When a Toolbar contains ToolbarGroup children it becomes a transparent
1510
+ * layout wrapper — each group renders as its own pill.
1511
+ */
1512
+ .toolbar:has(> .toolbar-group) {
1513
+ background: transparent;
1514
+ border: none;
1515
+ box-shadow: none;
1516
+ padding: 0;
1517
+ gap: 0.5rem;
1518
+ }
1519
+
1520
+ /*
1521
+ * Each ToolbarGroup is a self-contained pill that matches the visual style
1522
+ * of a standalone Toolbar.
1523
+ */
1524
+ .toolbar-group {
1525
+ background: var(--cratis-surface-card);
1526
+ border: 1px solid var(--cratis-surface-border);
1527
+ box-shadow: var(--cratis-shadow-overlay);
1528
+ }
1529
+
1530
+ /* ── Toolbar slot transition (ToolbarGroup slot content) ─────────────────── */
1531
+
1532
+ /*
1533
+ * Size-morphing container for slot content inside a ToolbarGroup or ToolbarLayout.
1534
+ * Mirrors the .toolbar-section transition parameters for visual consistency —
1535
+ * the container resizes smoothly while content cross-fades.
1536
+ * Overflow stays visible in the settled state so absolutely-positioned children
1537
+ * (fan-out and folder panels, and the hover tooltips inside them) can escape the
1538
+ * section's bounds; it is only clipped while outgoing content is fading out, so
1539
+ * that content does not bleed past the container mid-transition.
1540
+ */
1541
+ .toolbar-slot-section {
1542
+ position: relative;
1543
+ transition:
1544
+ width 0.35s cubic-bezier(0.4, 0, 0.2, 1),
1545
+ height 0.35s cubic-bezier(0.4, 0, 0.2, 1);
1546
+ }
1547
+
1548
+ .toolbar-slot-section--transitioning {
1549
+ overflow: hidden;
1550
+ }
1551
+
1552
+ @keyframes toolbar-slot-fade-in {
1553
+ from {
1554
+ opacity: 0;
1555
+ }
1556
+ to {
1557
+ opacity: 1;
1558
+ }
1559
+ }
1560
+
1561
+ @keyframes toolbar-slot-fade-out {
1562
+ from {
1563
+ opacity: 1;
1564
+ }
1565
+ to {
1566
+ opacity: 0;
1567
+ }
1568
+ }
1569
+
1570
+ /*
1571
+ * Incoming slot content — fades in on mount.
1572
+ * Duration matches the toolbar-context opacity transition (0.2s ease).
1573
+ */
1574
+ .toolbar-slot-incoming {
1575
+ position: absolute;
1576
+ top: 0;
1577
+ left: 0;
1578
+ animation: toolbar-slot-fade-in 0.2s ease forwards;
1579
+ }
1580
+
1581
+ /*
1582
+ * Outgoing slot content — fades out, then React unmounts it after
1583
+ * the animation completes.
1584
+ */
1585
+ .toolbar-slot-outgoing {
1586
+ position: absolute;
1587
+ top: 0;
1588
+ left: 0;
1589
+ animation: toolbar-slot-fade-out 0.2s ease forwards;
1590
+ pointer-events: none;
1591
+ }
1592
+
1593
+ @media (prefers-reduced-motion: reduce) {
1594
+ .toolbar,
1595
+ .toolbar-button,
1596
+ .toolbar-section,
1597
+ .toolbar-context,
1598
+ .toolbar-fanout-panel,
1599
+ .toolbar-folder-panel,
1600
+ .toolbar-slot-section,
1601
+ .toolbar-slot-incoming,
1602
+ .toolbar-slot-outgoing {
1603
+ transition: none !important;
1604
+ animation: none !important;
1605
+ }
1606
+
1607
+ .toolbar-fanout-panel--visible {
1608
+ clip-path: none !important;
1609
+ }
1610
+ }
1611
+
1612
+ }