@voriel_salut/ds 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/theme.css ADDED
@@ -0,0 +1,855 @@
1
+ /*
2
+ * @voriel_salut/ds 0.1.0 theme for Tailwind CSS v4 projects.
3
+ * Import after Tailwind: @import "tailwindcss"; @import "@voriel_salut/ds/theme.css";
4
+ */
5
+
6
+ /* Brand fonts. Kept apart from base.css so the published CSS imports them from the font packages
7
+ instead of embedding every font file. */
8
+ @import "@fontsource-variable/montserrat";
9
+ @import "@fontsource-variable/lora";
10
+ @import "@fontsource/space-mono/400.css";
11
+ @import "@fontsource/space-mono/700.css";
12
+
13
+ /* Generate the utilities the components use */
14
+ @source "./index.js";
15
+
16
+ /*
17
+ * Everything the design system needs on top of Tailwind except fonts (see fonts.css): plugins,
18
+ * tokens, dark mode and base styles. Shared by styles.css (this repo), package.css (compiled
19
+ * dist/styles.css) and dist/theme.css (for consumers who run Tailwind themselves).
20
+ */
21
+ @import "tw-animate-css";
22
+ /* From shadcn/tailwind.css — MIT License, Copyright (c) 2023 shadcn. See THIRD_PARTY_NOTICES.md. */
23
+ @theme inline {
24
+ @keyframes accordion-down {
25
+ from {
26
+ height: 0;
27
+ }
28
+ to {
29
+ height: var(
30
+ --radix-accordion-content-height,
31
+ var(--accordion-panel-height, auto)
32
+ );
33
+ }
34
+ }
35
+
36
+ @keyframes accordion-up {
37
+ from {
38
+ height: var(
39
+ --radix-accordion-content-height,
40
+ var(--accordion-panel-height, auto)
41
+ );
42
+ }
43
+ to {
44
+ height: 0;
45
+ }
46
+ }
47
+ }
48
+
49
+ /* Custom variants */
50
+ @custom-variant data-open {
51
+ &:where([data-state="open"]),
52
+ &:where([data-open]:not([data-open="false"])) {
53
+ @slot;
54
+ }
55
+ }
56
+
57
+ @custom-variant data-closed {
58
+ &:where([data-state="closed"]),
59
+ &:where([data-closed]:not([data-closed="false"])) {
60
+ @slot;
61
+ }
62
+ }
63
+
64
+ @custom-variant data-checked {
65
+ &:where([data-state="checked"]),
66
+ &:where([data-checked]:not([data-checked="false"])) {
67
+ @slot;
68
+ }
69
+ }
70
+
71
+ @custom-variant data-unchecked {
72
+ &:where([data-state="unchecked"]),
73
+ &:where([data-unchecked]:not([data-unchecked="false"])) {
74
+ @slot;
75
+ }
76
+ }
77
+
78
+ @custom-variant data-selected {
79
+ &:where([data-selected="true"]) {
80
+ @slot;
81
+ }
82
+ }
83
+
84
+ @custom-variant data-disabled {
85
+ &:where([data-disabled="true"]),
86
+ &:where([data-disabled]:not([data-disabled="false"])) {
87
+ @slot;
88
+ }
89
+ }
90
+
91
+ @custom-variant data-active {
92
+ &:where([data-state="active"]),
93
+ &:where([data-active]:not([data-active="false"])) {
94
+ @slot;
95
+ }
96
+ }
97
+
98
+ @custom-variant data-horizontal {
99
+ &:where([data-orientation="horizontal"]) {
100
+ @slot;
101
+ }
102
+ }
103
+
104
+ @custom-variant data-vertical {
105
+ &:where([data-orientation="vertical"]) {
106
+ @slot;
107
+ }
108
+ }
109
+
110
+ @utility no-scrollbar {
111
+ -ms-overflow-style: none;
112
+ scrollbar-width: none;
113
+
114
+ &::-webkit-scrollbar {
115
+ display: none;
116
+ }
117
+ }
118
+
119
+ /* scroll-fade */
120
+ @property --scroll-fade-t {
121
+ syntax: "<length-percentage>";
122
+ inherits: false;
123
+ initial-value: 0px;
124
+ }
125
+ @property --scroll-fade-b {
126
+ syntax: "<length-percentage>";
127
+ inherits: false;
128
+ initial-value: 0px;
129
+ }
130
+ @property --scroll-fade-s {
131
+ syntax: "<length-percentage>";
132
+ inherits: false;
133
+ initial-value: 0px;
134
+ }
135
+ @property --scroll-fade-e {
136
+ syntax: "<length-percentage>";
137
+ inherits: false;
138
+ initial-value: 0px;
139
+ }
140
+ @property --scroll-fade-mask {
141
+ syntax: "*";
142
+ inherits: false;
143
+ }
144
+
145
+ @theme inline {
146
+ @keyframes scroll-fade-reveal-t {
147
+ from {
148
+ --scroll-fade-t: 0px;
149
+ }
150
+ to {
151
+ --scroll-fade-t: var(--_scroll-fade-size-t, var(--scroll-fade-size, min(12%, calc(var(--spacing) * 10))));
152
+ }
153
+ }
154
+ @keyframes scroll-fade-reveal-b {
155
+ from {
156
+ --scroll-fade-b: var(--_scroll-fade-size-b, var(--scroll-fade-size, min(12%, calc(var(--spacing) * 10))));
157
+ }
158
+ to {
159
+ --scroll-fade-b: 0px;
160
+ }
161
+ }
162
+ @keyframes scroll-fade-reveal-s {
163
+ from {
164
+ --scroll-fade-s: 0px;
165
+ }
166
+ to {
167
+ --scroll-fade-s: var(--_scroll-fade-size-s, var(--scroll-fade-size, min(12%, calc(var(--spacing) * 10))));
168
+ }
169
+ }
170
+ @keyframes scroll-fade-reveal-e {
171
+ from {
172
+ --scroll-fade-e: var(--_scroll-fade-size-e, var(--scroll-fade-size, min(12%, calc(var(--spacing) * 10))));
173
+ }
174
+ to {
175
+ --scroll-fade-e: 0px;
176
+ }
177
+ }
178
+ }
179
+
180
+ @utility scroll-fade {
181
+ --_scroll-fade-size-t: var(
182
+ --scroll-fade-t-size,
183
+ var(--scroll-fade-size, min(12%, calc(var(--spacing) * 10)))
184
+ );
185
+ --_scroll-fade-size-b: var(
186
+ --scroll-fade-b-size,
187
+ var(--scroll-fade-size, min(12%, calc(var(--spacing) * 10)))
188
+ );
189
+ --scroll-fade-block: linear-gradient(
190
+ to bottom,
191
+ transparent 0,
192
+ #000 var(--scroll-fade-t, 0px),
193
+ #000 calc(100% - var(--scroll-fade-b, 0px)),
194
+ transparent 100%
195
+ );
196
+ -webkit-mask-image: var(--scroll-fade-mask, var(--scroll-fade-block));
197
+ mask-image: var(--scroll-fade-mask, var(--scroll-fade-block));
198
+ -webkit-mask-composite: source-in;
199
+ mask-composite: intersect;
200
+ -webkit-mask-repeat: no-repeat;
201
+ mask-repeat: no-repeat;
202
+
203
+ @supports (animation-timeline: scroll()) {
204
+ animation:
205
+ scroll-fade-reveal-t 1ms ease-in-out,
206
+ scroll-fade-reveal-b 1ms ease-in-out;
207
+ animation-timeline: scroll(self y), scroll(self y);
208
+ animation-range:
209
+ 0 var(--scroll-fade-reveal, calc(var(--spacing) * 24)),
210
+ calc(100% - var(--scroll-fade-reveal, calc(var(--spacing) * 24))) 100%;
211
+ animation-fill-mode: both;
212
+ }
213
+
214
+ @supports not (animation-timeline: scroll()) {
215
+ --scroll-fade-t: var(--_scroll-fade-size-t);
216
+ --scroll-fade-b: var(--_scroll-fade-size-b);
217
+ }
218
+ }
219
+
220
+ @utility scroll-fade-y {
221
+ --_scroll-fade-size-t: var(
222
+ --scroll-fade-t-size,
223
+ var(--scroll-fade-size, min(12%, calc(var(--spacing) * 10)))
224
+ );
225
+ --_scroll-fade-size-b: var(
226
+ --scroll-fade-b-size,
227
+ var(--scroll-fade-size, min(12%, calc(var(--spacing) * 10)))
228
+ );
229
+ --scroll-fade-block: linear-gradient(
230
+ to bottom,
231
+ transparent 0,
232
+ #000 var(--scroll-fade-t, 0px),
233
+ #000 calc(100% - var(--scroll-fade-b, 0px)),
234
+ transparent 100%
235
+ );
236
+ -webkit-mask-image: var(--scroll-fade-mask, var(--scroll-fade-block));
237
+ mask-image: var(--scroll-fade-mask, var(--scroll-fade-block));
238
+ -webkit-mask-composite: source-in;
239
+ mask-composite: intersect;
240
+ -webkit-mask-repeat: no-repeat;
241
+ mask-repeat: no-repeat;
242
+
243
+ @supports (animation-timeline: scroll()) {
244
+ animation:
245
+ scroll-fade-reveal-t 1ms ease-in-out,
246
+ scroll-fade-reveal-b 1ms ease-in-out;
247
+ animation-timeline: scroll(self y), scroll(self y);
248
+ animation-range:
249
+ 0 var(--scroll-fade-reveal, calc(var(--spacing) * 24)),
250
+ calc(100% - var(--scroll-fade-reveal, calc(var(--spacing) * 24))) 100%;
251
+ animation-fill-mode: both;
252
+ }
253
+
254
+ @supports not (animation-timeline: scroll()) {
255
+ --scroll-fade-t: var(--_scroll-fade-size-t);
256
+ --scroll-fade-b: var(--_scroll-fade-size-b);
257
+ }
258
+ }
259
+
260
+ @utility scroll-fade-x {
261
+ --_scroll-fade-size-s: var(
262
+ --scroll-fade-s-size,
263
+ var(--scroll-fade-size, min(12%, calc(var(--spacing) * 10)))
264
+ );
265
+ --_scroll-fade-size-e: var(
266
+ --scroll-fade-e-size,
267
+ var(--scroll-fade-size, min(12%, calc(var(--spacing) * 10)))
268
+ );
269
+ --scroll-fade-inline: linear-gradient(
270
+ to right,
271
+ transparent 0,
272
+ #000 var(--scroll-fade-s, 0px),
273
+ #000 calc(100% - var(--scroll-fade-e, 0px)),
274
+ transparent 100%
275
+ );
276
+ &:where([dir="rtl"], [dir="rtl"] *) {
277
+ --scroll-fade-inline: linear-gradient(
278
+ to left,
279
+ transparent 0,
280
+ #000 var(--scroll-fade-s, 0px),
281
+ #000 calc(100% - var(--scroll-fade-e, 0px)),
282
+ transparent 100%
283
+ );
284
+ }
285
+ -webkit-mask-image: var(--scroll-fade-mask, var(--scroll-fade-inline));
286
+ mask-image: var(--scroll-fade-mask, var(--scroll-fade-inline));
287
+ -webkit-mask-composite: source-in;
288
+ mask-composite: intersect;
289
+ -webkit-mask-repeat: no-repeat;
290
+ mask-repeat: no-repeat;
291
+
292
+ @supports (animation-timeline: scroll()) {
293
+ animation:
294
+ scroll-fade-reveal-s 1ms ease-in-out,
295
+ scroll-fade-reveal-e 1ms ease-in-out;
296
+ animation-timeline: scroll(self inline), scroll(self inline);
297
+ animation-range:
298
+ 0 var(--scroll-fade-reveal, calc(var(--spacing) * 24)),
299
+ calc(100% - var(--scroll-fade-reveal, calc(var(--spacing) * 24))) 100%;
300
+ animation-fill-mode: both;
301
+ }
302
+
303
+ @supports not (animation-timeline: scroll()) {
304
+ --scroll-fade-s: var(--_scroll-fade-size-s);
305
+ --scroll-fade-e: var(--_scroll-fade-size-e);
306
+ }
307
+ }
308
+
309
+ @utility scroll-fade-t {
310
+ --_scroll-fade-size-t: var(
311
+ --scroll-fade-t-size,
312
+ var(--scroll-fade-size, min(12%, calc(var(--spacing) * 10)))
313
+ );
314
+ --scroll-fade-mask: linear-gradient(
315
+ to bottom,
316
+ transparent 0,
317
+ #000 var(--scroll-fade-t, 0px),
318
+ #000 100%
319
+ );
320
+ -webkit-mask-image: var(--scroll-fade-mask);
321
+ mask-image: var(--scroll-fade-mask);
322
+ -webkit-mask-composite: source-in;
323
+ mask-composite: intersect;
324
+ -webkit-mask-repeat: no-repeat;
325
+ mask-repeat: no-repeat;
326
+
327
+ @supports (animation-timeline: scroll()) {
328
+ animation: scroll-fade-reveal-t 1ms ease-in-out;
329
+ animation-timeline: scroll(self y);
330
+ animation-range: 0 var(--scroll-fade-reveal, calc(var(--spacing) * 24));
331
+ animation-fill-mode: both;
332
+ }
333
+
334
+ @supports not (animation-timeline: scroll()) {
335
+ --scroll-fade-t: var(--_scroll-fade-size-t);
336
+ }
337
+ }
338
+
339
+ @utility scroll-fade-b {
340
+ --_scroll-fade-size-b: var(
341
+ --scroll-fade-b-size,
342
+ var(--scroll-fade-size, min(12%, calc(var(--spacing) * 10)))
343
+ );
344
+ --scroll-fade-mask: linear-gradient(
345
+ to bottom,
346
+ #000 0,
347
+ #000 calc(100% - var(--scroll-fade-b, 0px)),
348
+ transparent 100%
349
+ );
350
+ -webkit-mask-image: var(--scroll-fade-mask);
351
+ mask-image: var(--scroll-fade-mask);
352
+ -webkit-mask-composite: source-in;
353
+ mask-composite: intersect;
354
+ -webkit-mask-repeat: no-repeat;
355
+ mask-repeat: no-repeat;
356
+
357
+ @supports (animation-timeline: scroll()) {
358
+ animation: scroll-fade-reveal-b 1ms ease-in-out;
359
+ animation-timeline: scroll(self y);
360
+ animation-range: calc(
361
+ 100% - var(--scroll-fade-reveal, calc(var(--spacing) * 24))
362
+ )
363
+ 100%;
364
+ animation-fill-mode: both;
365
+ }
366
+
367
+ @supports not (animation-timeline: scroll()) {
368
+ --scroll-fade-b: var(--_scroll-fade-size-b);
369
+ }
370
+ }
371
+
372
+ @utility scroll-fade-l {
373
+ --_scroll-fade-size-s: var(
374
+ --scroll-fade-s-size,
375
+ var(--scroll-fade-size, min(12%, calc(var(--spacing) * 10)))
376
+ );
377
+ --scroll-fade-mask: linear-gradient(
378
+ to right,
379
+ transparent 0,
380
+ #000 var(--scroll-fade-s, 0px),
381
+ #000 100%
382
+ );
383
+ -webkit-mask-image: var(--scroll-fade-mask);
384
+ mask-image: var(--scroll-fade-mask);
385
+ -webkit-mask-composite: source-in;
386
+ mask-composite: intersect;
387
+ -webkit-mask-repeat: no-repeat;
388
+ mask-repeat: no-repeat;
389
+
390
+ @supports (animation-timeline: scroll()) {
391
+ animation: scroll-fade-reveal-s 1ms ease-in-out;
392
+ animation-timeline: scroll(self x);
393
+ animation-range: 0 var(--scroll-fade-reveal, calc(var(--spacing) * 24));
394
+ animation-fill-mode: both;
395
+ }
396
+
397
+ @supports not (animation-timeline: scroll()) {
398
+ --scroll-fade-s: var(--_scroll-fade-size-s);
399
+ }
400
+ }
401
+
402
+ @utility scroll-fade-r {
403
+ --_scroll-fade-size-e: var(
404
+ --scroll-fade-e-size,
405
+ var(--scroll-fade-size, min(12%, calc(var(--spacing) * 10)))
406
+ );
407
+ --scroll-fade-mask: linear-gradient(
408
+ to right,
409
+ #000 0,
410
+ #000 calc(100% - var(--scroll-fade-e, 0px)),
411
+ transparent 100%
412
+ );
413
+ -webkit-mask-image: var(--scroll-fade-mask);
414
+ mask-image: var(--scroll-fade-mask);
415
+ -webkit-mask-composite: source-in;
416
+ mask-composite: intersect;
417
+ -webkit-mask-repeat: no-repeat;
418
+ mask-repeat: no-repeat;
419
+
420
+ @supports (animation-timeline: scroll()) {
421
+ animation: scroll-fade-reveal-e 1ms ease-in-out;
422
+ animation-timeline: scroll(self x);
423
+ animation-range: calc(
424
+ 100% - var(--scroll-fade-reveal, calc(var(--spacing) * 24))
425
+ )
426
+ 100%;
427
+ animation-fill-mode: both;
428
+ }
429
+
430
+ @supports not (animation-timeline: scroll()) {
431
+ --scroll-fade-e: var(--_scroll-fade-size-e);
432
+ }
433
+ }
434
+
435
+ @utility scroll-fade-s {
436
+ --_scroll-fade-size-s: var(
437
+ --scroll-fade-s-size,
438
+ var(--scroll-fade-size, min(12%, calc(var(--spacing) * 10)))
439
+ );
440
+ --scroll-fade-mask: linear-gradient(
441
+ to right,
442
+ transparent 0,
443
+ #000 var(--scroll-fade-s, 0px),
444
+ #000 100%
445
+ );
446
+ &:where([dir="rtl"], [dir="rtl"] *) {
447
+ --scroll-fade-mask: linear-gradient(
448
+ to left,
449
+ transparent 0,
450
+ #000 var(--scroll-fade-s, 0px),
451
+ #000 100%
452
+ );
453
+ }
454
+ -webkit-mask-image: var(--scroll-fade-mask);
455
+ mask-image: var(--scroll-fade-mask);
456
+ -webkit-mask-composite: source-in;
457
+ mask-composite: intersect;
458
+ -webkit-mask-repeat: no-repeat;
459
+ mask-repeat: no-repeat;
460
+
461
+ @supports (animation-timeline: scroll()) {
462
+ animation: scroll-fade-reveal-s 1ms ease-in-out;
463
+ animation-timeline: scroll(self inline);
464
+ animation-range: 0 var(--scroll-fade-reveal, calc(var(--spacing) * 24));
465
+ animation-fill-mode: both;
466
+ }
467
+
468
+ @supports not (animation-timeline: scroll()) {
469
+ --scroll-fade-s: var(--_scroll-fade-size-s);
470
+ }
471
+ }
472
+
473
+ @utility scroll-fade-e {
474
+ --_scroll-fade-size-e: var(
475
+ --scroll-fade-e-size,
476
+ var(--scroll-fade-size, min(12%, calc(var(--spacing) * 10)))
477
+ );
478
+ --scroll-fade-mask: linear-gradient(
479
+ to right,
480
+ #000 0,
481
+ #000 calc(100% - var(--scroll-fade-e, 0px)),
482
+ transparent 100%
483
+ );
484
+ &:where([dir="rtl"], [dir="rtl"] *) {
485
+ --scroll-fade-mask: linear-gradient(
486
+ to left,
487
+ #000 0,
488
+ #000 calc(100% - var(--scroll-fade-e, 0px)),
489
+ transparent 100%
490
+ );
491
+ }
492
+ -webkit-mask-image: var(--scroll-fade-mask);
493
+ mask-image: var(--scroll-fade-mask);
494
+ -webkit-mask-composite: source-in;
495
+ mask-composite: intersect;
496
+ -webkit-mask-repeat: no-repeat;
497
+ mask-repeat: no-repeat;
498
+
499
+ @supports (animation-timeline: scroll()) {
500
+ animation: scroll-fade-reveal-e 1ms ease-in-out;
501
+ animation-timeline: scroll(self inline);
502
+ animation-range: calc(
503
+ 100% - var(--scroll-fade-reveal, calc(var(--spacing) * 24))
504
+ )
505
+ 100%;
506
+ animation-fill-mode: both;
507
+ }
508
+
509
+ @supports not (animation-timeline: scroll()) {
510
+ --scroll-fade-e: var(--_scroll-fade-size-e);
511
+ }
512
+ }
513
+
514
+ @utility scroll-fade-* {
515
+ --scroll-fade-size: calc(var(--spacing) * --value(integer));
516
+ --scroll-fade-size: --value([length], [percentage]);
517
+ }
518
+
519
+ @utility scroll-fade-t-* {
520
+ --scroll-fade-t-size: calc(var(--spacing) * --value(integer));
521
+ --scroll-fade-t-size: --value([length], [percentage]);
522
+ }
523
+
524
+ @utility scroll-fade-b-* {
525
+ --scroll-fade-b-size: calc(var(--spacing) * --value(integer));
526
+ --scroll-fade-b-size: --value([length], [percentage]);
527
+ }
528
+
529
+ @utility scroll-fade-s-* {
530
+ --scroll-fade-s-size: calc(var(--spacing) * --value(integer));
531
+ --scroll-fade-s-size: --value([length], [percentage]);
532
+ }
533
+
534
+ @utility scroll-fade-e-* {
535
+ --scroll-fade-e-size: calc(var(--spacing) * --value(integer));
536
+ --scroll-fade-e-size: --value([length], [percentage]);
537
+ }
538
+
539
+ @utility scroll-fade-none {
540
+ --scroll-fade-mask: none;
541
+ }
542
+
543
+ /* shimmer */
544
+ @property --shimmer-angle {
545
+ syntax: "<angle>";
546
+ inherits: true;
547
+ initial-value: 20deg;
548
+ }
549
+ @property --shimmer-image {
550
+ syntax: "*";
551
+ inherits: false;
552
+ }
553
+ @property --shimmer-text-fill {
554
+ syntax: "*";
555
+ inherits: false;
556
+ }
557
+
558
+ @theme inline {
559
+ @keyframes tw-shimmer {
560
+ from {
561
+ background-position: 100% 0;
562
+ }
563
+ to {
564
+ background-position: 0 0;
565
+ }
566
+ }
567
+ }
568
+
569
+ @utility shimmer {
570
+ --_spread: var(--shimmer-spread, calc(3ch + 40px));
571
+ --_base: currentColor;
572
+ --_highlight: var(
573
+ --shimmer-color,
574
+ oklch(from currentColor l c h / calc(alpha* 0.2))
575
+ );
576
+
577
+ background-image: var(
578
+ --shimmer-image,
579
+ linear-gradient(
580
+ calc(90deg + var(--shimmer-angle)),
581
+ var(--_base) calc(50% - var(--_spread)),
582
+ color-mix(in oklch, var(--_highlight), var(--_base) 50%)
583
+ calc(50% - var(--_spread) * 0.5),
584
+ var(--_highlight) 50%,
585
+ color-mix(in oklch, var(--_highlight), var(--_base) 50%)
586
+ calc(50% + var(--_spread) * 0.5),
587
+ var(--_base) calc(50% + var(--_spread))
588
+ )
589
+ );
590
+ background-repeat: no-repeat;
591
+ background-size: calc(200% + var(--_spread) * 2) 100%;
592
+ background-position: 0 0;
593
+ background-clip: text;
594
+ -webkit-background-clip: text;
595
+ -webkit-text-fill-color: var(--shimmer-text-fill, transparent);
596
+ animation: tw-shimmer var(--shimmer-duration, 2s) linear infinite;
597
+
598
+ @variant dark {
599
+ --_highlight: var(
600
+ --shimmer-color,
601
+ oklch(from currentColor max(0.8, calc(l + 0.4)) c h / calc(alpha + 0.4))
602
+ );
603
+ }
604
+
605
+ &:where([dir="rtl"], [dir="rtl"] *) {
606
+ animation-direction: reverse;
607
+ }
608
+ }
609
+
610
+ @utility shimmer-once {
611
+ animation-iteration-count: 1;
612
+ }
613
+
614
+ @utility shimmer-reverse {
615
+ animation-direction: reverse;
616
+ }
617
+
618
+ @utility shimmer-none {
619
+ --shimmer-image: none;
620
+ --shimmer-text-fill: currentColor;
621
+ }
622
+
623
+ @utility shimmer-color-* {
624
+ --shimmer-color: --value(--color, [color]);
625
+ --shimmer-color: color-mix(
626
+ in oklch,
627
+ --value(--color, [color]) calc(--modifier(integer) * 1%),
628
+ transparent
629
+ );
630
+ }
631
+
632
+ @utility shimmer-duration-* {
633
+ --shimmer-duration: calc(--value(integer) * 1ms);
634
+ }
635
+
636
+ @utility shimmer-spread-* {
637
+ --shimmer-spread: calc(var(--spacing) * --value(integer));
638
+ --shimmer-spread: --value([length], [percentage]);
639
+ }
640
+
641
+ @utility shimmer-angle-* {
642
+ --shimmer-angle: calc(--value(integer) * 1deg);
643
+ }
644
+
645
+ @media (prefers-reduced-motion: reduce) {
646
+ .shimmer {
647
+ animation: none;
648
+ background-image: none;
649
+ -webkit-text-fill-color: currentColor;
650
+ }
651
+ }
652
+
653
+ /*
654
+ * Design tokens for lets-vibe-ds, based on the MX-Brutalist theme from tweakcn
655
+ * (https://tweakcn.com/themes/cmllfu8oc000004l1a0tidj2g).
656
+ * :root and .dark hold the raw values; @theme inline maps them to Tailwind utilities.
657
+ */
658
+
659
+ @theme inline {
660
+ /* Typography */
661
+ --font-sans: var(--font-sans);
662
+ --font-serif: var(--font-serif);
663
+ --font-mono: var(--font-mono);
664
+ --font-heading: var(--font-sans);
665
+
666
+ --tracking-tighter: calc(var(--tracking-normal) - 0.05em);
667
+ --tracking-tight: calc(var(--tracking-normal) - 0.025em);
668
+ --tracking-normal: var(--tracking-normal);
669
+ --tracking-wide: calc(var(--tracking-normal) + 0.025em);
670
+ --tracking-wider: calc(var(--tracking-normal) + 0.05em);
671
+ --tracking-widest: calc(var(--tracking-normal) + 0.1em);
672
+
673
+ /* Colours */
674
+ --color-background: var(--background);
675
+ --color-foreground: var(--foreground);
676
+ --color-card: var(--card);
677
+ --color-card-foreground: var(--card-foreground);
678
+ --color-popover: var(--popover);
679
+ --color-popover-foreground: var(--popover-foreground);
680
+ --color-primary: var(--primary);
681
+ --color-primary-foreground: var(--primary-foreground);
682
+ --color-secondary: var(--secondary);
683
+ --color-secondary-foreground: var(--secondary-foreground);
684
+ --color-muted: var(--muted);
685
+ --color-muted-foreground: var(--muted-foreground);
686
+ --color-accent: var(--accent);
687
+ --color-accent-foreground: var(--accent-foreground);
688
+ --color-destructive: var(--destructive);
689
+ --color-destructive-foreground: var(--destructive-foreground);
690
+ --color-border: var(--border);
691
+ --color-input: var(--input);
692
+ --color-ring: var(--ring);
693
+ --color-chart-1: var(--chart-1);
694
+ --color-chart-2: var(--chart-2);
695
+ --color-chart-3: var(--chart-3);
696
+ --color-chart-4: var(--chart-4);
697
+ --color-chart-5: var(--chart-5);
698
+ --color-sidebar: var(--sidebar);
699
+ --color-sidebar-foreground: var(--sidebar-foreground);
700
+ --color-sidebar-primary: var(--sidebar-primary);
701
+ --color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
702
+ --color-sidebar-accent: var(--sidebar-accent);
703
+ --color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
704
+ --color-sidebar-border: var(--sidebar-border);
705
+ --color-sidebar-ring: var(--sidebar-ring);
706
+ --color-shader-1: var(--shader-1);
707
+ --color-shader-2: var(--shader-2);
708
+ --color-shader-3: var(--shader-3);
709
+ --color-shader-4: var(--shader-4);
710
+
711
+ /* Radius (0 in this theme, so every step resolves to square corners) */
712
+ --radius-sm: calc(var(--radius) * 0.6);
713
+ --radius-md: calc(var(--radius) * 0.8);
714
+ --radius-lg: var(--radius);
715
+ --radius-xl: calc(var(--radius) * 1.4);
716
+ --radius-2xl: calc(var(--radius) * 1.8);
717
+ --radius-3xl: calc(var(--radius) * 2.2);
718
+ --radius-4xl: calc(var(--radius) * 2.6);
719
+
720
+ /* Shadows: hard, offset, no blur */
721
+ --shadow-2xs: var(--shadow-2xs);
722
+ --shadow-xs: var(--shadow-xs);
723
+ --shadow-sm: var(--shadow-sm);
724
+ --shadow: var(--shadow);
725
+ --shadow-md: var(--shadow-md);
726
+ --shadow-lg: var(--shadow-lg);
727
+ --shadow-xl: var(--shadow-xl);
728
+ --shadow-2xl: var(--shadow-2xl);
729
+ }
730
+
731
+ :root {
732
+ /* Typography */
733
+ --font-sans: 'Montserrat Variable', 'Montserrat', sans-serif;
734
+ --font-serif: 'Lora Variable', 'Lora', serif;
735
+ --font-mono: 'Space Mono', monospace;
736
+ --tracking-normal: 0.04em;
737
+
738
+ /* Colours */
739
+ --background: oklch(0.9923 0.0104 91.4994);
740
+ --foreground: oklch(0.1759 0.0275 161.2531);
741
+ --card: oklch(1 0 0);
742
+ --card-foreground: oklch(0.1759 0.0275 161.2531);
743
+ --popover: oklch(1 0 0);
744
+ --popover-foreground: oklch(0.1759 0.0275 161.2531);
745
+ --primary: oklch(0.5687 0.1498 151.938);
746
+ --primary-foreground: oklch(1 0 0);
747
+ --secondary: oklch(0.6088 0.2498 29.2339);
748
+ --secondary-foreground: oklch(1 0 0);
749
+ --muted: oklch(0.9465 0.0314 91.6628);
750
+ --muted-foreground: oklch(0.3525 0.0379 91.7268);
751
+ --accent: oklch(0.7721 0.1727 64.1585);
752
+ --accent-foreground: oklch(0.1759 0.0275 161.2531);
753
+ --destructive: oklch(0.5799 0.238 29.2339);
754
+ --destructive-foreground: oklch(1 0 0);
755
+ --border: oklch(0 0 0);
756
+ --input: oklch(1 0 0);
757
+ --ring: oklch(0.5687 0.1498 151.938);
758
+ --chart-1: oklch(0.5687 0.1498 151.938);
759
+ --chart-2: oklch(0.6088 0.2498 29.2339);
760
+ --chart-3: oklch(0.7721 0.1727 64.1585);
761
+ --chart-4: oklch(0.6829 0.2615 345.7533);
762
+ --chart-5: oklch(0.7443 0.1347 219.0676);
763
+ --sidebar: oklch(0.3167 0.0793 154.3757);
764
+ --sidebar-foreground: oklch(1 0 0);
765
+ --sidebar-primary: oklch(0.7721 0.1727 64.1585);
766
+ --sidebar-primary-foreground: oklch(0.3167 0.0793 154.3757);
767
+ --sidebar-accent: oklch(0.4156 0.1071 152.9714);
768
+ --sidebar-accent-foreground: oklch(1 0 0);
769
+ --sidebar-border: oklch(0 0 0);
770
+ --sidebar-ring: oklch(0.7721 0.1727 64.1585);
771
+
772
+ /*
773
+ * Shader palette (low → high) for ShaderBackground. Same in both modes: the hero is always a
774
+ * dark scene. Values reuse theme colours: dark --sidebar, light --sidebar-accent,
775
+ * dark --primary and dark --foreground.
776
+ */
777
+ --shader-1: oklch(0.1292 0.027 165.3808);
778
+ --shader-2: oklch(0.4156 0.1071 152.9714);
779
+ --shader-3: oklch(0.8484 0.2275 151.1487);
780
+ --shader-4: oklch(0.9809 0.026 91.6197);
781
+
782
+ /* Radius */
783
+ --radius: 0px;
784
+
785
+ /* Shadows: black, 4px offset */
786
+ --shadow-2xs: 4px 4px 0px 0px hsl(0 0% 0% / 0.5);
787
+ --shadow-xs: 4px 4px 0px 0px hsl(0 0% 0% / 0.5);
788
+ --shadow-sm: 4px 4px 0px 0px hsl(0 0% 0% / 1), 4px 1px 2px -1px hsl(0 0% 0% / 1);
789
+ --shadow: 4px 4px 0px 0px hsl(0 0% 0% / 1), 4px 1px 2px -1px hsl(0 0% 0% / 1);
790
+ --shadow-md: 4px 4px 0px 0px hsl(0 0% 0% / 1), 4px 2px 4px -1px hsl(0 0% 0% / 1);
791
+ --shadow-lg: 4px 4px 0px 0px hsl(0 0% 0% / 1), 4px 4px 6px -1px hsl(0 0% 0% / 1);
792
+ --shadow-xl: 4px 4px 0px 0px hsl(0 0% 0% / 1), 4px 8px 10px -1px hsl(0 0% 0% / 1);
793
+ --shadow-2xl: 4px 4px 0px 0px hsl(0 0% 0% / 1);
794
+ }
795
+
796
+ .dark {
797
+ /* Colours */
798
+ --background: oklch(0.1649 0.0308 162.2739);
799
+ --foreground: oklch(0.9809 0.026 91.6197);
800
+ --card: oklch(0.2283 0.0445 158.2398);
801
+ --card-foreground: oklch(0.9809 0.026 91.6197);
802
+ --popover: oklch(0.2283 0.0445 158.2398);
803
+ --popover-foreground: oklch(0.9809 0.026 91.6197);
804
+ --primary: oklch(0.8484 0.2275 151.1487);
805
+ --primary-foreground: oklch(0.1292 0.027 165.3808);
806
+ --secondary: oklch(0.6489 0.237 26.9728);
807
+ --secondary-foreground: oklch(1 0 0);
808
+ --muted: oklch(0.2724 0.0467 159.1721);
809
+ --muted-foreground: oklch(0.8253 0.027 91.6606);
810
+ --accent: oklch(0.7951 0.1631 68.6392);
811
+ --accent-foreground: oklch(0.1292 0.027 165.3808);
812
+ --destructive: oklch(0.628 0.2577 29.2339);
813
+ --destructive-foreground: oklch(1 0 0);
814
+ --border: oklch(0.9809 0.026 91.6197);
815
+ --input: oklch(0.2642 0.0387 160.3481);
816
+ --ring: oklch(0.7951 0.1631 68.6392);
817
+ --chart-1: oklch(0.8484 0.2275 151.1487);
818
+ --chart-2: oklch(0.6489 0.237 26.9728);
819
+ --chart-3: oklch(0.7951 0.1631 68.6392);
820
+ --chart-4: oklch(0.7337 0.2145 342.8759);
821
+ --chart-5: oklch(0.8296 0.1375 215.2952);
822
+ --sidebar: oklch(0.1292 0.027 165.3808);
823
+ --sidebar-foreground: oklch(0.9809 0.026 91.6197);
824
+ --sidebar-primary: oklch(0.8484 0.2275 151.1487);
825
+ --sidebar-primary-foreground: oklch(0.1292 0.027 165.3808);
826
+ --sidebar-accent: oklch(0.2449 0.0403 159.5177);
827
+ --sidebar-accent-foreground: oklch(0.9809 0.026 91.6197);
828
+ --sidebar-border: oklch(0.9809 0.026 91.6197);
829
+ --sidebar-ring: oklch(0.7951 0.1631 68.6392);
830
+
831
+ /* Shadows: pale yellow, 4px offset */
832
+ --shadow-2xs: 4px 4px 0px 0px hsl(45 100% 80% / 0.5);
833
+ --shadow-xs: 4px 4px 0px 0px hsl(45 100% 80% / 0.5);
834
+ --shadow-sm: 4px 4px 0px 0px hsl(45 100% 80% / 1), 4px 1px 2px -1px hsl(45 100% 80% / 1);
835
+ --shadow: 4px 4px 0px 0px hsl(45 100% 80% / 1), 4px 1px 2px -1px hsl(45 100% 80% / 1);
836
+ --shadow-md: 4px 4px 0px 0px hsl(45 100% 80% / 1), 4px 2px 4px -1px hsl(45 100% 80% / 1);
837
+ --shadow-lg: 4px 4px 0px 0px hsl(45 100% 80% / 1), 4px 4px 6px -1px hsl(45 100% 80% / 1);
838
+ --shadow-xl: 4px 4px 0px 0px hsl(45 100% 80% / 1), 4px 8px 10px -1px hsl(45 100% 80% / 1);
839
+ --shadow-2xl: 4px 4px 0px 0px hsl(45 100% 80% / 1);
840
+ }
841
+
842
+ @custom-variant dark (&:is(.dark *));
843
+
844
+ @layer base {
845
+ * {
846
+ @apply border-border outline-ring/50;
847
+ }
848
+ body {
849
+ @apply bg-background text-foreground;
850
+ letter-spacing: var(--tracking-normal);
851
+ }
852
+ html {
853
+ @apply font-sans;
854
+ }
855
+ }