@thl-ui/styles 0.0.0-stage → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +42 -2
  3. package/dist/components/alert.css +1 -0
  4. package/dist/components/app.css +1 -0
  5. package/dist/components/avatar.css +1 -0
  6. package/dist/components/badge.css +1 -0
  7. package/dist/components/button.css +1 -0
  8. package/dist/components/card.css +1 -0
  9. package/dist/components/form.css +1 -0
  10. package/dist/components/nav.css +1 -0
  11. package/dist/components/overlay.css +1 -0
  12. package/dist/components/pages.css +1 -0
  13. package/dist/components/progress.css +1 -0
  14. package/dist/components/ribbon.css +1 -0
  15. package/dist/components/table.css +1 -0
  16. package/dist/components/widgets.css +1 -0
  17. package/dist/fonts/OFL.txt +93 -0
  18. package/dist/fonts/open-sans-cyrillic-ext-wght-normal.woff2 +0 -0
  19. package/dist/fonts/open-sans-cyrillic-wght-normal.woff2 +0 -0
  20. package/dist/fonts/open-sans-greek-ext-wght-normal.woff2 +0 -0
  21. package/dist/fonts/open-sans-greek-wght-normal.woff2 +0 -0
  22. package/dist/fonts/open-sans-latin-ext-wght-normal.woff2 +0 -0
  23. package/dist/fonts/open-sans-latin-wght-normal.woff2 +0 -0
  24. package/dist/fonts/open-sans-vietnamese-wght-normal.woff2 +0 -0
  25. package/dist/fonts.css +70 -0
  26. package/dist/thl-ui.css +447 -0
  27. package/dist/tokens.css +376 -0
  28. package/package.json +48 -4
  29. package/src/_base.scss +408 -0
  30. package/src/_mixins.scss +53 -0
  31. package/src/components/_alert.scss +183 -0
  32. package/src/components/_avatar.scss +75 -0
  33. package/src/components/_badge.scss +112 -0
  34. package/src/components/_button.scss +242 -0
  35. package/src/components/_card.scss +211 -0
  36. package/src/components/_form.scss +959 -0
  37. package/src/components/_nav.scss +738 -0
  38. package/src/components/_overlay.scss +382 -0
  39. package/src/components/_progress.scss +103 -0
  40. package/src/components/_ribbon.scss +136 -0
  41. package/src/components/_table.scss +215 -0
  42. package/src/components/_widgets.scss +1102 -0
  43. package/src/index.scss +16 -0
  44. package/src/layout/_app.scss +804 -0
  45. package/src/pages/_pages.scss +691 -0
@@ -0,0 +1,1102 @@
1
+ @use '../mixins' as *;
2
+
3
+ /* info-box */
4
+ .#{$p}-info-box {
5
+ --_c: #{v(theme)};
6
+ --_on: #{v(on-theme)};
7
+ --_t: #{v(theme-text)};
8
+ display: flex;
9
+ gap: 20px;
10
+ align-items: flex-start;
11
+ /* when the box is too narrow for icon + text side by side (e.g. four boxes in a docs-width row),
12
+ the text wraps below the icon instead of breaking the title one letter per line */
13
+ flex-wrap: wrap;
14
+ row-gap: 12px;
15
+ background: v(surface);
16
+ padding: 30px 25px;
17
+ border: 1px solid v(border-color);
18
+ border-radius: v(radius);
19
+ height: 100%;
20
+ /* the box is a size container so icon and value can shrink when four boxes share a narrow row */
21
+ container-type: inline-size;
22
+ @each $c in $colors {
23
+ &--#{$c} {
24
+ --_c: #{v(color-#{$c})};
25
+ --_on: #{on($c)};
26
+ --_t: #{tx($c)};
27
+ }
28
+ }
29
+ &__icon {
30
+ width: 60px;
31
+ height: 60px;
32
+ flex-shrink: 0;
33
+ border-radius: 50%;
34
+ display: inline-flex;
35
+ align-items: center;
36
+ justify-content: center;
37
+ font-size: 26px;
38
+ color: var(--_on);
39
+ background: var(--_c);
40
+ }
41
+ &__body {
42
+ flex: 1 1 110px;
43
+ min-width: 0;
44
+ }
45
+ &__value {
46
+ font-size: 30px !important;
47
+ line-height: 1.1 !important;
48
+ margin: 0 0 4px !important;
49
+ color: var(--_t) !important;
50
+ font-weight: 400;
51
+ }
52
+ &__title {
53
+ font-size: 12px;
54
+ text-transform: uppercase;
55
+ color: v(text);
56
+ margin: 0;
57
+ letter-spacing: 0.03em;
58
+ }
59
+ &__line {
60
+ display: block;
61
+ height: 1px;
62
+ background: v(border-color);
63
+ margin: 12px 0;
64
+ }
65
+ &__foot {
66
+ display: flex;
67
+ flex-wrap: wrap;
68
+ justify-content: space-between;
69
+ align-items: center;
70
+ gap: 4px 8px;
71
+ font-size: 14px;
72
+ color: v(text-strong);
73
+ margin: 0;
74
+ }
75
+ @container (max-width: 230px) {
76
+ &__icon {
77
+ width: 44px;
78
+ height: 44px;
79
+ font-size: 20px;
80
+ }
81
+ &__value {
82
+ font-size: 24px !important;
83
+ }
84
+ }
85
+
86
+ &--filled {
87
+ background: var(--_c);
88
+ border-color: var(--_c);
89
+ color: var(--_on);
90
+ .#{$p}-info-box__icon {
91
+ background: rgba(255, 255, 255, 0.2);
92
+ }
93
+ .#{$p}-info-box__value,
94
+ .#{$p}-info-box__title,
95
+ .#{$p}-info-box__foot {
96
+ color: var(--_on) !important;
97
+ }
98
+ .#{$p}-info-box__line {
99
+ background: rgba(255, 255, 255, 0.3);
100
+ }
101
+ }
102
+ &--soft .#{$p}-info-box__icon {
103
+ background: color-mix(in srgb, var(--_c) 15%, transparent);
104
+ color: var(--_t);
105
+ }
106
+ }
107
+ /* stat-widget with progress (index2–4) */
108
+ .#{$p}-stat {
109
+ --_c: #{v(theme)};
110
+ --_t: #{v(theme-text)};
111
+ background: v(surface);
112
+ border: 1px solid v(border-color);
113
+ border-radius: v(radius);
114
+ padding: 25px;
115
+ height: 100%;
116
+ @each $c in $colors {
117
+ &--#{$c} {
118
+ --_c: #{v(color-#{$c})};
119
+ --_t: #{tx($c)};
120
+ }
121
+ }
122
+ &__head {
123
+ display: flex;
124
+ justify-content: space-between;
125
+ align-items: center;
126
+ gap: 10px;
127
+ }
128
+ &__title {
129
+ margin: 0 !important;
130
+ font-size: 14px !important;
131
+ line-height: 22px !important;
132
+ text-transform: uppercase;
133
+ font-weight: 600;
134
+ color: v(heading);
135
+ letter-spacing: 0.03em;
136
+ }
137
+ &__icon {
138
+ font-size: 30px;
139
+ color: var(--_t);
140
+ }
141
+ &__value {
142
+ font-size: 28px;
143
+ color: v(heading);
144
+ margin: 12px 0 6px;
145
+ font-weight: 300;
146
+ display: flex;
147
+ align-items: baseline;
148
+ gap: 10px;
149
+ }
150
+ &__delta {
151
+ font-size: 13px;
152
+ font-weight: 600;
153
+ &--up {
154
+ color: v(color-success-text);
155
+ }
156
+ &--down {
157
+ color: v(color-danger-text);
158
+ }
159
+ }
160
+ .#{$p}-progress {
161
+ margin: 10px 0 0;
162
+ }
163
+ }
164
+ /* color-box / small box */
165
+ .#{$p}-color-box {
166
+ --_c: #{v(theme)};
167
+ --_on: #{v(on-theme)};
168
+ background: var(--_c);
169
+ color: var(--_on);
170
+ padding: 25px;
171
+ border-radius: v(radius);
172
+ position: relative;
173
+ overflow: hidden;
174
+ height: 100%;
175
+ @each $c in $colors {
176
+ &--#{$c} {
177
+ --_c: #{v(color-#{$c})};
178
+ --_on: #{on($c)};
179
+ }
180
+ }
181
+ h3,
182
+ h4,
183
+ h1,
184
+ h2,
185
+ &__value {
186
+ color: var(--_on) !important;
187
+ margin: 0 !important;
188
+ }
189
+ &__value {
190
+ font-size: v(h2);
191
+ line-height: 36px;
192
+ font-weight: 400;
193
+ }
194
+ &__icon {
195
+ position: absolute;
196
+ inset-inline-end: 20px;
197
+ top: 50%;
198
+ transform: translateY(-50%);
199
+ font-size: 60px;
200
+ opacity: 0.25;
201
+ }
202
+ &__label {
203
+ font-size: 13px;
204
+ text-transform: uppercase;
205
+ }
206
+ }
207
+
208
+ /* analytics row (stats-row / stat-item) */
209
+ .#{$p}-stats-row {
210
+ display: flex;
211
+ flex-wrap: wrap;
212
+ gap: 0;
213
+ border-top: 1px solid v(border-color);
214
+ &__item {
215
+ flex: 1;
216
+ min-width: 100px;
217
+ padding: 15px 10px;
218
+ text-align: center;
219
+ border-inline-end: 1px solid v(border-color);
220
+ &:last-child {
221
+ border: 0;
222
+ }
223
+ h6,
224
+ .#{$p}-stats-row__label {
225
+ margin: 0 0 4px !important;
226
+ color: v(text) !important;
227
+ text-transform: uppercase;
228
+ font-size: 12px !important;
229
+ }
230
+ b {
231
+ font-size: 18px;
232
+ color: v(heading);
233
+ font-weight: 600;
234
+ }
235
+ }
236
+ }
237
+
238
+ /* feed / list widgets */
239
+ .#{$p}-list {
240
+ list-style: none;
241
+ margin: 0;
242
+ padding: 0;
243
+ &__item {
244
+ display: flex;
245
+ gap: 14px;
246
+ align-items: center;
247
+ padding: 14px 0;
248
+ border-bottom: 1px solid v(border-color);
249
+ &:last-child {
250
+ border-bottom: 0;
251
+ }
252
+ }
253
+ &__body {
254
+ flex: 1;
255
+ min-width: 0;
256
+ }
257
+ &__title {
258
+ color: v(text-strong);
259
+ font-weight: 500;
260
+ margin: 0 0 2px;
261
+ overflow: hidden;
262
+ text-overflow: ellipsis;
263
+ white-space: nowrap;
264
+ }
265
+ &__desc {
266
+ font-size: 13px;
267
+ color: v(text);
268
+ margin: 0;
269
+ }
270
+ &__meta {
271
+ font-size: 12px;
272
+ color: v(text);
273
+ white-space: nowrap;
274
+ }
275
+ &__icon {
276
+ --_c: #{v(theme)};
277
+ --_on: #{v(on-theme)};
278
+ width: 40px;
279
+ height: 40px;
280
+ flex-shrink: 0;
281
+ border-radius: 50%;
282
+ display: inline-flex;
283
+ align-items: center;
284
+ justify-content: center;
285
+ color: var(--_on);
286
+ background: var(--_c);
287
+ @each $c in $colors {
288
+ &--#{$c} {
289
+ --_c: #{v(color-#{$c})};
290
+ --_on: #{on($c)};
291
+ }
292
+ }
293
+ }
294
+ &--hover &__item {
295
+ cursor: pointer;
296
+ padding-inline: 10px;
297
+ &:hover {
298
+ background: v(surface-muted);
299
+ }
300
+ }
301
+ }
302
+
303
+ /* chat (chat-widget / chat listing) */
304
+ .#{$p}-chat {
305
+ list-style: none;
306
+ margin: 0;
307
+ padding: 0;
308
+ display: flex;
309
+ flex-direction: column;
310
+ gap: 18px;
311
+ container-type: inline-size;
312
+ &__msg {
313
+ display: flex;
314
+ gap: 12px;
315
+ align-items: flex-end;
316
+ max-width: 85%;
317
+ /* the text column takes the free width, so a narrow card does not squeeze bubbles to one word per line */
318
+ > :not(img) {
319
+ flex: 1 1 auto;
320
+ min-width: 0;
321
+ }
322
+ &--me {
323
+ flex-direction: row-reverse;
324
+ align-self: flex-end;
325
+ .#{$p}-chat__bubble {
326
+ background: v(theme);
327
+ color: v(on-theme);
328
+ border-end-end-radius: 0;
329
+ border-end-start-radius: v(radius-lg);
330
+ }
331
+ }
332
+ }
333
+ &__bubble {
334
+ padding: 10px 14px;
335
+ border-radius: v(radius-lg);
336
+ border-end-start-radius: 0;
337
+ background: v(surface-muted);
338
+ color: v(text-strong);
339
+ font-size: 14px;
340
+ }
341
+ &__name {
342
+ font-size: 12px;
343
+ font-weight: 600;
344
+ color: v(heading);
345
+ margin-bottom: 2px;
346
+ }
347
+ &__time {
348
+ font-size: 11px;
349
+ color: v(text);
350
+ margin-top: 4px;
351
+ }
352
+ &__composer {
353
+ display: flex;
354
+ gap: 8px;
355
+ margin-top: 15px;
356
+ padding-top: 15px;
357
+ border-top: 1px solid v(border-color);
358
+ }
359
+ /* narrow card: bubbles use the full width and avatars shrink, so text is not one word per line */
360
+ @container (max-width: 260px) {
361
+ &__msg {
362
+ max-width: 100%;
363
+ gap: 8px;
364
+ > img {
365
+ width: 28px !important;
366
+ height: 28px !important;
367
+ }
368
+ }
369
+ }
370
+ }
371
+
372
+ /* todo / task widget */
373
+ .#{$p}-todo {
374
+ list-style: none;
375
+ margin: 0;
376
+ padding: 0;
377
+ container-type: inline-size;
378
+ &__item {
379
+ display: flex;
380
+ flex-wrap: wrap;
381
+ align-items: center;
382
+ gap: 6px 10px;
383
+ padding: 12px 14px;
384
+ margin-bottom: 8px;
385
+ background: v(surface-muted);
386
+ border-radius: v(radius);
387
+ border-inline-start: 4px solid v(color-warning);
388
+ &.is-done {
389
+ border-inline-start-color: v(theme);
390
+ .#{$p}-todo__text {
391
+ text-decoration: line-through;
392
+ color: v(text);
393
+ }
394
+ }
395
+ }
396
+ &__text {
397
+ flex: 1 1 120px;
398
+ min-width: 0;
399
+ color: v(text-strong);
400
+ }
401
+ &__remove {
402
+ background: none;
403
+ border: 0;
404
+ cursor: pointer;
405
+ color: v(text);
406
+ opacity: 0;
407
+ &:hover {
408
+ color: v(color-danger-text);
409
+ }
410
+ }
411
+ &__item:hover &__remove,
412
+ &__remove:focus-visible {
413
+ opacity: 1;
414
+ }
415
+ }
416
+
417
+ /* profile widget / user-bg */
418
+ .#{$p}-profile-card {
419
+ background: v(surface);
420
+ border: 1px solid v(border-color);
421
+ border-radius: v(radius);
422
+ overflow: hidden;
423
+ margin-bottom: v(space-7);
424
+ &__cover {
425
+ position: relative;
426
+ height: 230px;
427
+ overflow: hidden;
428
+ background: linear-gradient(to right, #{v(topbar-1)}, #{v(topbar-2)});
429
+ > img {
430
+ width: 100%;
431
+ height: 100%;
432
+ object-fit: cover;
433
+ filter: blur(3px);
434
+ transform: scale(1.1);
435
+ opacity: 0.7;
436
+ }
437
+ }
438
+ &__overlay {
439
+ position: absolute;
440
+ inset: 0;
441
+ display: flex;
442
+ flex-direction: column;
443
+ align-items: center;
444
+ justify-content: center;
445
+ gap: 8px;
446
+ color: #fff;
447
+ text-align: center;
448
+ h4,
449
+ h5,
450
+ h2 {
451
+ color: #fff !important;
452
+ margin: 0 !important;
453
+ }
454
+ h2 {
455
+ font-size: v(h4) !important;
456
+ line-height: 22px;
457
+ }
458
+ > div {
459
+ font-size: v(h5);
460
+ }
461
+ }
462
+ &__stats {
463
+ display: grid;
464
+ grid-template-columns: repeat(3, 1fr);
465
+ text-align: center;
466
+ border-bottom: 1px solid v(border-color);
467
+ > div {
468
+ padding: 15px 8px;
469
+ border-inline-end: 1px solid v(border-color);
470
+ &:last-child {
471
+ border: 0;
472
+ }
473
+ }
474
+ b {
475
+ display: block;
476
+ font-size: 20px;
477
+ color: v(heading);
478
+ font-weight: 400;
479
+ }
480
+ small {
481
+ color: v(text);
482
+ }
483
+ }
484
+ &__body {
485
+ padding: 20px 25px;
486
+ }
487
+ }
488
+
489
+ /* user card with hover overlay */
490
+ .#{$p}-user-card {
491
+ background: v(surface);
492
+ border: 1px solid v(border-color);
493
+ border-radius: v(radius);
494
+ overflow: hidden;
495
+ margin-bottom: v(space-7);
496
+ text-align: center;
497
+ &__media {
498
+ position: relative;
499
+ overflow: hidden;
500
+ aspect-ratio: 1 / 1;
501
+ img {
502
+ width: 100%;
503
+ height: 100%;
504
+ object-fit: cover;
505
+ display: block;
506
+ transition: transform 0.4s;
507
+ }
508
+ }
509
+ &__overlay {
510
+ position: absolute;
511
+ inset: 0;
512
+ display: flex;
513
+ align-items: center;
514
+ justify-content: center;
515
+ gap: 8px;
516
+ background: rgba(0, 0, 0, 0.6);
517
+ opacity: 0;
518
+ transition: opacity 0.3s;
519
+ .#{$p}-btn {
520
+ transform: translateY(-20px);
521
+ transition: transform 0.3s;
522
+ }
523
+ }
524
+ &__media:hover img,
525
+ &__media:focus-within img {
526
+ transform: scale(1.12);
527
+ }
528
+ &__media:hover &__overlay,
529
+ &__media:focus-within &__overlay {
530
+ opacity: 1;
531
+ .#{$p}-btn {
532
+ transform: none;
533
+ }
534
+ }
535
+ &__content {
536
+ padding: 15px;
537
+ h2,
538
+ h3,
539
+ h4 {
540
+ margin: 0 0 2px !important;
541
+ font-size: 18px !important;
542
+ color: v(heading);
543
+ }
544
+ small {
545
+ color: v(text);
546
+ }
547
+ }
548
+ }
549
+
550
+ /* pricing */
551
+ /* columns follow the table's own width (not the viewport), so 4 plans never wrap 3 + 1:
552
+ 4 across when there is room, then 2 × 2, then a single column. */
553
+ .#{$p}-pricing-wrap {
554
+ container-type: inline-size;
555
+ }
556
+ .#{$p}-pricing {
557
+ --_cols: 4;
558
+ display: grid;
559
+ grid-template-columns: repeat(min(var(--_cols), var(--_n, 4)), minmax(0, 1fr));
560
+ gap: 0;
561
+ align-items: center;
562
+ }
563
+ @container (max-width: 879px) {
564
+ .#{$p}-pricing {
565
+ --_cols: 2;
566
+ row-gap: 30px;
567
+ }
568
+ /* in a 2 × 2 grid an enlarged plan would cover its neighbours */
569
+ .#{$p}-pricing-plan--featured {
570
+ transform: none;
571
+ }
572
+ }
573
+ @container (max-width: 479px) {
574
+ .#{$p}-pricing {
575
+ --_cols: 1;
576
+ }
577
+ }
578
+ .#{$p}-pricing-plan {
579
+ position: relative;
580
+ background: v(surface);
581
+ border: 1px solid v(border-color);
582
+ text-align: center;
583
+ transition: all 0.3s;
584
+ & + & {
585
+ margin-inline-start: -1px;
586
+ }
587
+ &__header {
588
+ padding: 30px 20px 15px;
589
+ border-bottom: 1px solid v(border-color);
590
+ h2,
591
+ h4 {
592
+ margin: 0 0 10px !important;
593
+ font-weight: 500;
594
+ color: v(heading);
595
+ text-transform: uppercase;
596
+ font-size: 18px !important;
597
+ line-height: 22px;
598
+ }
599
+ }
600
+ &__price {
601
+ font-size: 60px;
602
+ font-weight: 600;
603
+ color: v(heading);
604
+ line-height: 1;
605
+ margin: 10px 0;
606
+ display: flex;
607
+ justify-content: center;
608
+ align-items: flex-start;
609
+ gap: 2px;
610
+ sup {
611
+ font-size: 24px;
612
+ margin-top: 8px;
613
+ color: v(text);
614
+ }
615
+ }
616
+ &__period {
617
+ text-transform: uppercase;
618
+ color: v(text);
619
+ font-size: 13px;
620
+ margin: 0;
621
+ }
622
+ &__features {
623
+ list-style: none;
624
+ margin: 0;
625
+ padding: 0;
626
+ }
627
+ &__feature {
628
+ padding: 14px 20px;
629
+ border-bottom: 1px solid v(border-color);
630
+ color: v(text-strong);
631
+ display: flex;
632
+ gap: 8px;
633
+ justify-content: center;
634
+ align-items: center;
635
+ }
636
+ &__action {
637
+ padding: 25px 20px;
638
+ }
639
+ &__tag {
640
+ position: absolute;
641
+ top: 0;
642
+ inset-inline: 0;
643
+ background: v(color-danger);
644
+ color: v(on-danger);
645
+ padding: 4px;
646
+ font-size: 12px;
647
+ text-transform: uppercase;
648
+ letter-spacing: 0.05em;
649
+ }
650
+ &--featured {
651
+ z-index: 1;
652
+ transform: scale(1.06);
653
+ box-shadow: v(shadow-lg);
654
+ border-color: transparent;
655
+ .#{$p}-pricing-plan__header {
656
+ padding-top: 46px;
657
+ }
658
+ .#{$p}-pricing-plan__price {
659
+ color: v(theme-text);
660
+ }
661
+ }
662
+ @include down(sm) {
663
+ & + & {
664
+ margin: 0 0 20px;
665
+ }
666
+ &--featured {
667
+ transform: none;
668
+ }
669
+ }
670
+ }
671
+
672
+ /* weather (temp-widget) */
673
+ .#{$p}-weather {
674
+ --_c1: #{v(topbar-1)};
675
+ --_c2: #{v(topbar-2)};
676
+ background: linear-gradient(135deg, var(--_c1), var(--_c2));
677
+ color: #fff;
678
+ border-radius: v(radius);
679
+ padding: 25px;
680
+ height: 100%;
681
+ &__temp {
682
+ font-size: 54px;
683
+ font-weight: 300;
684
+ line-height: 1;
685
+ sup {
686
+ font-size: 24px;
687
+ }
688
+ }
689
+ &__icon {
690
+ font-size: 50px;
691
+ }
692
+ &__days {
693
+ display: grid;
694
+ grid-auto-flow: column;
695
+ grid-auto-columns: minmax(0, 1fr);
696
+ gap: 4px;
697
+ margin-top: 20px;
698
+ padding-top: 15px;
699
+ border-top: 1px solid rgba(255, 255, 255, 0.25);
700
+ text-align: center;
701
+ font-size: 13px;
702
+ /* icon on its own centered line between day and temperature */
703
+ .#{$p}-icon {
704
+ display: block;
705
+ margin: 4px auto;
706
+ font-size: 18px;
707
+ }
708
+ b {
709
+ display: block;
710
+ font-size: 16px;
711
+ }
712
+ }
713
+ }
714
+
715
+ /* counter / mini chart host */
716
+ .#{$p}-chart {
717
+ position: relative;
718
+ width: 100%;
719
+ min-height: 60px;
720
+ svg {
721
+ display: block;
722
+ width: 100%;
723
+ overflow: visible;
724
+ }
725
+ }
726
+ .#{$p}-chart-legend {
727
+ display: flex;
728
+ flex-wrap: wrap;
729
+ gap: 14px;
730
+ list-style: none;
731
+ margin: 0 0 10px;
732
+ padding: 0;
733
+ font-size: 13px;
734
+ color: v(text-strong);
735
+ li {
736
+ display: inline-flex;
737
+ align-items: center;
738
+ gap: 6px;
739
+ }
740
+ i {
741
+ width: 10px;
742
+ height: 10px;
743
+ border-radius: 50%;
744
+ display: inline-block;
745
+ }
746
+ }
747
+ .#{$p}-chart-tooltip {
748
+ position: absolute;
749
+ pointer-events: none;
750
+ z-index: 5;
751
+ background: v(color-inverse);
752
+ color: #fff;
753
+ font-size: 12px;
754
+ padding: 6px 10px;
755
+ border-radius: v(radius-sm);
756
+ white-space: nowrap;
757
+ transform: translate(-50%, calc(-100% - 10px));
758
+ }
759
+
760
+ /* carousel */
761
+ .#{$p}-carousel {
762
+ position: relative;
763
+ overflow: hidden;
764
+ border-radius: v(radius);
765
+ &__track {
766
+ display: flex;
767
+ transition: transform 0.5s ease;
768
+ }
769
+ &__slide {
770
+ flex: 0 0 100%;
771
+ min-width: 0;
772
+ position: relative;
773
+ img {
774
+ width: 100%;
775
+ display: block;
776
+ }
777
+ }
778
+ &__caption {
779
+ position: absolute;
780
+ inset-inline: 15%;
781
+ bottom: 20px;
782
+ text-align: center;
783
+ color: #fff;
784
+ text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);
785
+ background: rgba(0, 0, 0, 0.55);
786
+ padding: 6px 14px;
787
+ border-radius: v(radius);
788
+ h3,
789
+ h4 {
790
+ color: #fff !important;
791
+ }
792
+ }
793
+ &__arrow {
794
+ position: absolute;
795
+ top: 50%;
796
+ transform: translateY(-50%);
797
+ width: 44px;
798
+ height: 44px;
799
+ border-radius: 50%;
800
+ border: 0;
801
+ background: rgba(0, 0, 0, 0.35);
802
+ color: #fff;
803
+ font-size: 22px;
804
+ cursor: pointer;
805
+ z-index: 2;
806
+ &:hover {
807
+ background: rgba(0, 0, 0, 0.6);
808
+ }
809
+ &--prev {
810
+ inset-inline-start: 12px;
811
+ }
812
+ &--next {
813
+ inset-inline-end: 12px;
814
+ }
815
+ }
816
+ &__dots {
817
+ position: absolute;
818
+ bottom: 10px;
819
+ inset-inline: 0;
820
+ display: flex;
821
+ justify-content: center;
822
+ gap: 6px;
823
+ z-index: 2;
824
+ button {
825
+ width: 10px;
826
+ height: 10px;
827
+ border-radius: 50%;
828
+ border: 0;
829
+ background: rgba(255, 255, 255, 0.5);
830
+ cursor: pointer;
831
+ padding: 0;
832
+ &.is-active {
833
+ background: #fff;
834
+ width: 22px;
835
+ border-radius: 5px;
836
+ }
837
+ }
838
+ }
839
+ &--fade &__track {
840
+ display: grid;
841
+ }
842
+ &--fade &__slide {
843
+ grid-area: 1 / 1;
844
+ opacity: 0;
845
+ transition: opacity 0.6s;
846
+ &.is-active {
847
+ opacity: 1;
848
+ }
849
+ }
850
+ }
851
+ [dir='rtl'] .#{$p}-carousel__track {
852
+ flex-direction: row-reverse;
853
+ }
854
+
855
+ /* gallery */
856
+ .#{$p}-gallery {
857
+ display: grid;
858
+ gap: 15px;
859
+ grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
860
+ &__item {
861
+ position: relative;
862
+ overflow: hidden;
863
+ border-radius: v(radius);
864
+ cursor: zoom-in;
865
+ aspect-ratio: 4 / 3;
866
+ border: 0;
867
+ padding: 0;
868
+ background: none;
869
+ img {
870
+ width: 100%;
871
+ height: 100%;
872
+ object-fit: cover;
873
+ display: block;
874
+ transition: transform 0.4s;
875
+ }
876
+ &:hover img {
877
+ transform: scale(1.08);
878
+ }
879
+ }
880
+ }
881
+ .#{$p}-lightbox {
882
+ position: fixed;
883
+ inset: 0;
884
+ z-index: v(z-modal);
885
+ background: rgba(0, 0, 0, 0.9);
886
+ display: flex;
887
+ align-items: center;
888
+ justify-content: center;
889
+ animation: #{$p}-fade-in 0.2s;
890
+ img {
891
+ max-width: 90vw;
892
+ max-height: 85vh;
893
+ box-shadow: 0 0 30px rgba(0, 0, 0, 0.6);
894
+ animation: #{$p}-zoom-in 0.25s;
895
+ }
896
+ &__close,
897
+ &__nav {
898
+ position: absolute;
899
+ background: none;
900
+ border: 0;
901
+ color: #fff;
902
+ font-size: 34px;
903
+ cursor: pointer;
904
+ padding: 10px;
905
+ opacity: 0.8;
906
+ &:hover {
907
+ opacity: 1;
908
+ }
909
+ }
910
+ &__close {
911
+ top: 10px;
912
+ inset-inline-end: 16px;
913
+ }
914
+ &__nav--prev {
915
+ inset-inline-start: 10px;
916
+ }
917
+ &__nav--next {
918
+ inset-inline-end: 10px;
919
+ }
920
+ &__caption {
921
+ position: absolute;
922
+ bottom: 16px;
923
+ inset-inline: 0;
924
+ text-align: center;
925
+ color: #fff;
926
+ }
927
+ }
928
+
929
+ /* calendar (month view) */
930
+ .#{$p}-calendar {
931
+ &__toolbar {
932
+ display: flex;
933
+ align-items: center;
934
+ justify-content: space-between;
935
+ gap: 10px;
936
+ flex-wrap: wrap;
937
+ margin-bottom: 15px;
938
+ h2,
939
+ h3 {
940
+ margin: 0 !important;
941
+ font-size: v(h3);
942
+ line-height: 30px;
943
+ }
944
+ }
945
+ &__grid {
946
+ display: grid;
947
+ grid-template-columns: repeat(7, minmax(0, 1fr));
948
+ border-top: 1px solid v(border-color);
949
+ border-inline-start: 1px solid v(border-color);
950
+ }
951
+ &__dow {
952
+ padding: 10px 6px;
953
+ text-align: center;
954
+ font-weight: 600;
955
+ color: v(heading);
956
+ border-inline-end: 1px solid v(border-color);
957
+ border-bottom: 1px solid v(border-color);
958
+ background: v(surface-muted);
959
+ font-size: 13px;
960
+ }
961
+ &__cell {
962
+ min-height: 110px;
963
+ padding: 6px;
964
+ border-inline-end: 1px solid v(border-color);
965
+ border-bottom: 1px solid v(border-color);
966
+ position: relative;
967
+ cursor: pointer;
968
+ transition: background 0.2s;
969
+ &:hover {
970
+ background: v(surface-muted);
971
+ }
972
+ &.is-outside {
973
+ background: v(surface-muted);
974
+ .#{$p}-calendar__date {
975
+ color: v(text);
976
+ }
977
+ }
978
+ &.is-today {
979
+ background: color-mix(in srgb, #{v(color-warning)} 10%, transparent);
980
+ }
981
+ &.is-drop {
982
+ outline: 2px dashed v(theme);
983
+ outline-offset: -2px;
984
+ }
985
+ }
986
+ &__date {
987
+ font-size: 13px;
988
+ color: v(text-strong);
989
+ text-align: end;
990
+ display: block;
991
+ margin-bottom: 4px;
992
+ }
993
+ &__event {
994
+ --_c: #{v(theme)};
995
+ --_on: #{v(on-theme)};
996
+ display: block;
997
+ width: 100%;
998
+ padding: 3px 6px;
999
+ margin-bottom: 3px;
1000
+ font-size: 12px;
1001
+ color: var(--_on);
1002
+ background: var(--_c);
1003
+ border-radius: v(radius-sm);
1004
+ border: 0;
1005
+ text-align: start;
1006
+ overflow: hidden;
1007
+ text-overflow: ellipsis;
1008
+ white-space: nowrap;
1009
+ cursor: grab;
1010
+ @each $c in $colors {
1011
+ &--#{$c} {
1012
+ --_c: #{v(color-#{$c})};
1013
+ --_on: #{on($c)};
1014
+ }
1015
+ }
1016
+ }
1017
+ @include down(sm) {
1018
+ &__cell {
1019
+ min-height: 64px;
1020
+ }
1021
+ &__event {
1022
+ font-size: 0;
1023
+ height: 6px;
1024
+ padding: 0;
1025
+ }
1026
+ }
1027
+ }
1028
+
1029
+ /* map placeholder */
1030
+ .#{$p}-map {
1031
+ position: relative;
1032
+ width: 100%;
1033
+ min-height: 360px;
1034
+ border-radius: v(radius);
1035
+ overflow: hidden;
1036
+ background: v(surface-muted);
1037
+ iframe {
1038
+ position: absolute;
1039
+ inset: 0;
1040
+ width: 100%;
1041
+ height: 100%;
1042
+ border: 0;
1043
+ }
1044
+ svg {
1045
+ width: 100%;
1046
+ height: auto;
1047
+ display: block;
1048
+ }
1049
+ &__region {
1050
+ fill: v(color-light);
1051
+ stroke: v(surface);
1052
+ stroke-width: 0.5;
1053
+ transition: fill 0.2s;
1054
+ cursor: pointer;
1055
+ &:hover,
1056
+ &.is-active {
1057
+ fill: v(theme);
1058
+ }
1059
+ }
1060
+ }
1061
+
1062
+ /* icon grid */
1063
+ .#{$p}-icon-grid {
1064
+ display: grid;
1065
+ grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
1066
+ gap: 4px;
1067
+ &__item {
1068
+ display: flex;
1069
+ align-items: center;
1070
+ gap: 10px;
1071
+ padding: 10px;
1072
+ border-radius: v(radius-sm);
1073
+ color: v(text-strong);
1074
+ font-size: 13px;
1075
+ cursor: pointer;
1076
+ border: 0;
1077
+ background: none;
1078
+ text-align: start;
1079
+ &:hover {
1080
+ background: v(theme);
1081
+ color: v(on-theme);
1082
+ }
1083
+ svg {
1084
+ flex-shrink: 0;
1085
+ }
1086
+ }
1087
+ }
1088
+
1089
+ /* dashboard widgets stack like cards: rows rely on each block's bottom margin for vertical rhythm.
1090
+ They fill the column height (equal-height boxes in a row), so subtract the margin from 100%. */
1091
+ .#{$p}-info-box,
1092
+ .#{$p}-stat,
1093
+ .#{$p}-color-box,
1094
+ .#{$p}-weather {
1095
+ margin-bottom: v(space-7);
1096
+ }
1097
+ .#{$p}-info-box,
1098
+ .#{$p}-stat,
1099
+ .#{$p}-color-box,
1100
+ .#{$p}-weather {
1101
+ height: calc(100% - #{v(space-7)});
1102
+ }