@juxtui/ui 0.2.0 → 0.4.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.
Files changed (45) hide show
  1. package/README.md +63 -62
  2. package/dist/components/aspect-ratio/JAspectRatio.vue.d.ts +18 -0
  3. package/dist/components/avatar/JAvatar.vue.d.ts +1 -1
  4. package/dist/components/avatar-group/JAvatarGroup.vue.d.ts +19 -0
  5. package/dist/components/banner/JBanner.vue.d.ts +30 -0
  6. package/dist/components/breadcrumb/JBreadcrumb.vue.d.ts +29 -0
  7. package/dist/components/burger/JBurger.vue.d.ts +25 -0
  8. package/dist/components/card/JCard.vue.d.ts +1 -1
  9. package/dist/components/collapsible/JCollapsible.vue.d.ts +28 -0
  10. package/dist/components/command-palette/JCommandPalette.vue.d.ts +1 -1
  11. package/dist/components/dropdown-menu/JDropdownMenu.vue.d.ts +1 -1
  12. package/dist/components/empty-state/JEmptyState.vue.d.ts +23 -0
  13. package/dist/components/field/JFieldShell.vue.d.ts +1 -1
  14. package/dist/components/footer/JFooter.vue.d.ts +26 -0
  15. package/dist/components/footer/JFooterColumn.vue.d.ts +15 -0
  16. package/dist/components/navbar/JNavbar.vue.d.ts +47 -0
  17. package/dist/components/navbar/JNavbarLink.vue.d.ts +22 -0
  18. package/dist/components/pagination/JPagination.vue.d.ts +25 -0
  19. package/dist/components/primitives/JSlot.d.ts +1 -1
  20. package/dist/components/rating/JRating.vue.d.ts +27 -0
  21. package/dist/components/sidebar/JSidebar.vue.d.ts +23 -0
  22. package/dist/components/sidebar/JSidebarGroup.vue.d.ts +29 -0
  23. package/dist/components/sidebar/JSidebarItem.vue.d.ts +26 -0
  24. package/dist/components/slider/JSlider.vue.d.ts +31 -0
  25. package/dist/components/stat/JStat.vue.d.ts +22 -0
  26. package/dist/components/tag/JTag.vue.d.ts +28 -0
  27. package/dist/components/timeline/JTimeline.vue.d.ts +12 -0
  28. package/dist/components/timeline/JTimelineItem.vue.d.ts +24 -0
  29. package/dist/components/toast/JToaster.vue.d.ts +1 -1
  30. package/dist/components/toggle-group/JToggleGroup.vue.d.ts +33 -0
  31. package/dist/components/toggle-group/JToggleGroupItem.vue.d.ts +19 -0
  32. package/dist/components/toggle-group/context.d.ts +9 -0
  33. package/dist/components/visually-hidden/JVisuallyHidden.vue.d.ts +19 -0
  34. package/dist/components.d.ts +24 -0
  35. package/dist/composables/useModal.d.ts +1 -1
  36. package/dist/composables/useToast.d.ts +1 -1
  37. package/dist/icons.d.ts +4 -0
  38. package/dist/index.d.ts +24 -0
  39. package/dist/index.js +1583 -218
  40. package/dist/index.js.map +1 -1
  41. package/dist/nuxt.js +25 -1
  42. package/dist/nuxt.js.map +1 -1
  43. package/dist/style.css +2147 -606
  44. package/dist/tokens.css +5 -5
  45. package/package.json +1 -1
package/dist/style.css CHANGED
@@ -4,7 +4,7 @@
4
4
  /*
5
5
  * Juxt's component styles live in the `juxt` cascade layer. The order below
6
6
  * puts it above CSS resets (Tailwind's `base`) and below utilities, so a
7
- * class like `hidden` or `w-full` on a component always wins — and any
7
+ * class like `hidden` or `w-full` on a component always wins | and any
8
8
  * unlayered CSS of your own does too. Without Tailwind the extra names are
9
9
  * simply empty layers.
10
10
  */
@@ -13,7 +13,7 @@
13
13
  * Juxt design tokens
14
14
  *
15
15
  * One source of truth for colour, space, radius, type, elevation, motion and
16
- * layering. Components never hardcode these values — they read them here.
16
+ * layering. Components never hardcode these values | they read them here.
17
17
  *
18
18
  * Light is the default. Dark applies under `.dark` or `[data-theme="dark"]`
19
19
  * on any ancestor (usually <html>).
@@ -44,7 +44,7 @@
44
44
  --juxt-fg-muted: #71717a;
45
45
  --juxt-fg-disabled: #a1a1aa;
46
46
 
47
- /* Ink — the inverted neutral used by primary actions */
47
+ /* Ink | the inverted neutral used by primary actions */
48
48
  --juxt-ink: #09090b;
49
49
  --juxt-ink-hover: #27272a;
50
50
  --juxt-ink-fg: #fafafa;
@@ -84,7 +84,7 @@
84
84
  --juxt-success-soft: var(--juxt-accent-soft);
85
85
  --juxt-success-border: var(--juxt-accent-border);
86
86
 
87
- /* Elevation — borders do most of the work, shadows only lift */
87
+ /* Elevation | borders do most of the work, shadows only lift */
88
88
  --juxt-shadow-xs: 0 1px 1px rgb(9 9 11 / 0.04);
89
89
  --juxt-shadow-sm: 0 1px 2px rgb(9 9 11 / 0.05), 0 1px 1px rgb(9 9 11 / 0.03);
90
90
  --juxt-shadow-md: 0 4px 12px -2px rgb(9 9 11 / 0.08), 0 2px 4px -2px rgb(9 9 11 / 0.05);
@@ -186,7 +186,7 @@
186
186
  --juxt-tracking-tight: -0.011em;
187
187
  --juxt-tracking-tighter: -0.022em;
188
188
 
189
- /* Space — a 4px grid */
189
+ /* Space | a 4px grid */
190
190
  --juxt-space-0-5: 0.125rem; /* 2 */
191
191
  --juxt-space-1: 0.25rem; /* 4 */
192
192
  --juxt-space-1-5: 0.375rem; /* 6 */
@@ -239,7 +239,7 @@
239
239
 
240
240
  @media (prefers-reduced-motion: reduce) {
241
241
  :root {
242
- /* Things still fade — they just stop travelling. */
242
+ /* Things still fade | they just stop travelling. */
243
243
  --juxt-motion-shift: 0px;
244
244
  --juxt-motion-scale: 1;
245
245
  --juxt-duration-slow: 140ms;
@@ -462,211 +462,235 @@
462
462
  }
463
463
  }
464
464
 
465
+ @layer theme, base, juxt, components, utilities;
465
466
  @layer juxt {
466
- .j-accordion {
467
- display: flex;
468
- flex-direction: column;
467
+ .j-accordion {
468
+ display: flex;
469
+ flex-direction: column;
469
470
  font-family: var(--juxt-font-sans);
470
471
  }
471
- }
472
+ }
472
473
 
474
+ @layer theme, base, juxt, components, utilities;
473
475
  @layer juxt {
474
- .j-accordion__item {
476
+ .j-accordion__item {
475
477
  border-bottom: 1px solid var(--juxt-border-subtle);
476
478
  }
477
- .dark .j-accordion__item,
478
- [data-theme='dark'] .j-accordion__item {
479
+ .dark .j-accordion__item,
480
+ [data-theme='dark'] .j-accordion__item {
479
481
  border-bottom-color: var(--juxt-border);
480
482
  }
481
- .j-accordion__heading {
482
- margin: 0;
483
+ .j-accordion__heading {
484
+ margin: 0;
483
485
  font: inherit;
484
486
  }
485
- .j-accordion__trigger {
486
- display: flex;
487
- align-items: center;
488
- justify-content: space-between;
489
- gap: var(--juxt-space-4);
490
- width: 100%;
491
- min-height: 3rem;
492
- padding: var(--juxt-space-3) 0;
493
- border: 0;
494
- border-radius: var(--juxt-radius-xs);
495
- background: transparent;
496
- color: var(--juxt-fg);
497
- font: inherit;
498
- font-size: var(--juxt-text-md);
499
- font-weight: var(--juxt-weight-medium);
500
- letter-spacing: var(--juxt-tracking-tight);
501
- text-align: left;
502
- cursor: pointer;
503
- outline: 2px solid transparent;
504
- outline-offset: 0;
505
- -webkit-tap-highlight-color: transparent;
506
- transition:
507
- color var(--juxt-duration-fast) var(--juxt-ease-standard),
508
- outline-color var(--juxt-duration-fast) var(--juxt-ease-out),
487
+ .j-accordion__trigger {
488
+ display: flex;
489
+ align-items: center;
490
+ justify-content: space-between;
491
+ gap: var(--juxt-space-4);
492
+ width: 100%;
493
+ min-height: 3rem;
494
+ padding: var(--juxt-space-3) 0;
495
+ border: 0;
496
+ border-radius: var(--juxt-radius-xs);
497
+ background: transparent;
498
+ color: var(--juxt-fg);
499
+ font: inherit;
500
+ font-size: var(--juxt-text-md);
501
+ font-weight: var(--juxt-weight-medium);
502
+ letter-spacing: var(--juxt-tracking-tight);
503
+ text-align: left;
504
+ cursor: pointer;
505
+ outline: 2px solid transparent;
506
+ outline-offset: 0;
507
+ -webkit-tap-highlight-color: transparent;
508
+ transition:
509
+ color var(--juxt-duration-fast) var(--juxt-ease-standard),
510
+ outline-color var(--juxt-duration-fast) var(--juxt-ease-out),
509
511
  outline-offset var(--juxt-duration-fast) var(--juxt-ease-out);
510
512
  }
511
- .j-accordion__trigger:focus-visible {
512
- outline-color: var(--juxt-ring);
513
+ .j-accordion__trigger:focus-visible {
514
+ outline-color: var(--juxt-ring);
513
515
  outline-offset: 2px;
514
516
  }
515
- .j-accordion__trigger:disabled {
516
- color: var(--juxt-fg-disabled);
517
+ .j-accordion__trigger:disabled {
518
+ color: var(--juxt-fg-disabled);
517
519
  cursor: not-allowed;
518
520
  }
519
- .j-accordion__chevron {
520
- flex: none;
521
- width: 1rem;
522
- height: 1rem;
523
- color: var(--juxt-fg-muted);
524
- transition:
525
- transform var(--juxt-duration-normal) var(--juxt-ease-out),
521
+ .j-accordion__chevron {
522
+ flex: none;
523
+ width: 1rem;
524
+ height: 1rem;
525
+ color: var(--juxt-fg-muted);
526
+ transition:
527
+ transform var(--juxt-duration-normal) var(--juxt-ease-out),
526
528
  color var(--juxt-duration-fast) var(--juxt-ease-standard);
527
529
  }
528
- .j-accordion__trigger:hover:not(:disabled) .j-accordion__chevron {
530
+ .j-accordion__trigger:hover:not(:disabled) .j-accordion__chevron {
529
531
  color: var(--juxt-fg);
530
532
  }
531
- .j-accordion__item[data-state='open'] .j-accordion__chevron {
533
+ .j-accordion__item[data-state='open'] .j-accordion__chevron {
532
534
  transform: rotate(180deg);
533
- }
534
-
535
- /* Height follows content via grid rows — no measuring, no magic numbers. */
536
- .j-accordion__panel {
537
- display: grid;
538
- grid-template-rows: 0fr;
535
+ }
536
+
537
+ /* Height follows content via grid rows | no measuring, no magic numbers. */
538
+ .j-accordion__panel {
539
+ display: grid;
540
+ grid-template-rows: 0fr;
539
541
  transition: grid-template-rows var(--juxt-duration-slow) var(--juxt-ease-out);
540
542
  }
541
- .j-accordion__item[data-state='open'] .j-accordion__panel {
543
+ .j-accordion__item[data-state='open'] .j-accordion__panel {
542
544
  grid-template-rows: 1fr;
543
545
  }
544
- .j-accordion__panel-inner {
545
- min-height: 0;
546
+ .j-accordion__panel-inner {
547
+ min-height: 0;
546
548
  overflow: hidden;
547
549
  }
548
- .j-accordion__content {
549
- padding-bottom: var(--juxt-space-4);
550
- color: var(--juxt-fg-secondary);
551
- font-size: var(--juxt-text-md);
552
- line-height: var(--juxt-leading-normal);
553
- opacity: 0;
550
+ .j-accordion__content {
551
+ padding-bottom: var(--juxt-space-4);
552
+ color: var(--juxt-fg-secondary);
553
+ font-size: var(--juxt-text-md);
554
+ line-height: var(--juxt-leading-normal);
555
+ opacity: 0;
554
556
  transition: opacity var(--juxt-duration-fast) var(--juxt-ease-standard);
555
557
  }
556
- .j-accordion__item[data-state='open'] .j-accordion__content {
557
- opacity: 1;
558
+ .j-accordion__item[data-state='open'] .j-accordion__content {
559
+ opacity: 1;
558
560
  transition-delay: 60ms;
559
561
  }
560
562
  @media (prefers-reduced-motion: reduce) {
561
- .j-accordion__panel,
562
- .j-accordion__chevron {
563
+ .j-accordion__panel,
564
+ .j-accordion__chevron {
563
565
  transition: none;
564
566
  }
565
567
  }
566
- }
568
+ }
567
569
 
568
- @layer juxt {
569
- /*
570
- * Alerts stay on the page's surface. Colour lives in the icon and a hairline
571
- * of the border — enough to be noticed, never enough to shout.
570
+ @layer theme, base, juxt, components, utilities;
571
+ @layer juxt {
572
+ /*
573
+ * Alerts stay on the page's surface. Colour lives in the icon and a hairline
574
+ * of the border | enough to be noticed, never enough to shout.
572
575
  */
573
- .j-alert {
574
- --j-alert-accent: var(--juxt-fg-muted);
575
- --j-alert-border: var(--juxt-border);
576
-
577
- position: relative;
578
- display: flex;
579
- align-items: flex-start;
580
- gap: var(--juxt-space-3);
581
- padding: var(--juxt-space-3) var(--juxt-space-4);
582
- border: 1px solid var(--j-alert-border);
583
- border-radius: var(--juxt-radius-md);
584
- background: var(--juxt-surface);
585
- color: var(--juxt-fg);
576
+ .j-alert {
577
+ --j-alert-accent: var(--juxt-fg-muted);
578
+ --j-alert-border: var(--juxt-border);
579
+
580
+ position: relative;
581
+ display: flex;
582
+ align-items: flex-start;
583
+ gap: var(--juxt-space-3);
584
+ padding: var(--juxt-space-3) var(--juxt-space-4);
585
+ border: 1px solid var(--j-alert-border);
586
+ border-radius: var(--juxt-radius-md);
587
+ background: var(--juxt-surface);
588
+ color: var(--juxt-fg);
586
589
  font-family: var(--juxt-font-sans);
587
590
  }
588
- .j-alert--info {
591
+ .j-alert--info {
589
592
  --j-alert-accent: var(--juxt-info-text);
590
593
  }
591
- .j-alert--success {
594
+ .j-alert--success {
592
595
  --j-alert-accent: var(--juxt-success-text);
593
596
  }
594
- .j-alert--warning {
595
- --j-alert-accent: var(--juxt-warning-text);
597
+ .j-alert--warning {
598
+ --j-alert-accent: var(--juxt-warning-text);
596
599
  --j-alert-border: var(--juxt-warning-border);
597
600
  }
598
- .j-alert--destructive {
599
- --j-alert-accent: var(--juxt-danger-text);
601
+ .j-alert--destructive {
602
+ --j-alert-accent: var(--juxt-danger-text);
600
603
  --j-alert-border: var(--juxt-danger-border);
601
604
  }
602
- .j-alert__icon {
603
- display: grid;
604
- flex: none;
605
- place-items: center;
606
- height: 1.25rem;
605
+ .j-alert__icon {
606
+ display: grid;
607
+ flex: none;
608
+ place-items: center;
609
+ height: 1.25rem;
607
610
  color: var(--j-alert-accent);
608
611
  }
609
- .j-alert__icon > svg {
610
- width: 1rem;
612
+ .j-alert__icon > svg {
613
+ width: 1rem;
611
614
  height: 1rem;
612
615
  }
613
- .j-alert__body {
614
- display: flex;
615
- flex: 1;
616
- flex-direction: column;
617
- gap: var(--juxt-space-0-5);
616
+ .j-alert__body {
617
+ display: flex;
618
+ flex: 1;
619
+ flex-direction: column;
620
+ gap: var(--juxt-space-0-5);
618
621
  min-width: 0;
619
622
  }
620
- .j-alert__title {
621
- margin: 0;
622
- font-size: var(--juxt-text-md);
623
- font-weight: var(--juxt-weight-medium);
624
- line-height: 1.25rem;
623
+ .j-alert__title {
624
+ margin: 0;
625
+ font-size: var(--juxt-text-md);
626
+ font-weight: var(--juxt-weight-medium);
627
+ line-height: 1.25rem;
625
628
  letter-spacing: var(--juxt-tracking-tight);
626
629
  }
627
- .j-alert__description {
628
- color: var(--juxt-fg-secondary);
629
- font-size: var(--juxt-text-sm);
630
+ .j-alert__description {
631
+ color: var(--juxt-fg-secondary);
632
+ font-size: var(--juxt-text-sm);
630
633
  line-height: var(--juxt-leading-normal);
631
634
  }
632
- .j-alert__description > p {
635
+ .j-alert__description > p {
633
636
  margin: 0;
634
637
  }
635
- .j-alert__actions {
636
- display: flex;
637
- flex-wrap: wrap;
638
- gap: var(--juxt-space-2);
638
+ .j-alert__actions {
639
+ display: flex;
640
+ flex-wrap: wrap;
641
+ gap: var(--juxt-space-2);
639
642
  margin-top: var(--juxt-space-2);
640
643
  }
641
- .j-alert:has(.j-alert__close) {
644
+ .j-alert:has(.j-alert__close) {
642
645
  padding-right: var(--juxt-space-10);
643
646
  }
644
- .j-alert__close {
645
- position: absolute;
646
- top: var(--juxt-space-2-5);
647
- right: var(--juxt-space-2-5);
648
- display: grid;
649
- place-items: center;
650
- width: 1.5rem;
651
- height: 1.5rem;
652
- padding: 0;
653
- border: 0;
654
- border-radius: var(--juxt-radius-xs);
655
- background: transparent;
656
- color: var(--juxt-fg-muted);
657
- cursor: pointer;
647
+ .j-alert__close {
648
+ position: absolute;
649
+ top: var(--juxt-space-2-5);
650
+ right: var(--juxt-space-2-5);
651
+ display: grid;
652
+ place-items: center;
653
+ width: 1.5rem;
654
+ height: 1.5rem;
655
+ padding: 0;
656
+ border: 0;
657
+ border-radius: var(--juxt-radius-xs);
658
+ background: transparent;
659
+ color: var(--juxt-fg-muted);
660
+ cursor: pointer;
658
661
  transition-property: background-color, color, outline-color, outline-offset;
659
662
  }
660
- .j-alert__close:hover {
661
- background: var(--juxt-surface-hover);
663
+ .j-alert__close:hover {
664
+ background: var(--juxt-surface-hover);
662
665
  color: var(--juxt-fg);
663
666
  }
664
- .j-alert__close > svg {
665
- width: 0.875rem;
667
+ .j-alert__close > svg {
668
+ width: 0.875rem;
666
669
  height: 0.875rem;
667
670
  }
671
+ }
672
+
673
+ @layer theme, base, juxt, components, utilities;
674
+ @layer juxt {
675
+ .j-aspect-ratio {
676
+ position: relative;
677
+ width: 100%;
678
+ aspect-ratio: var(--j-aspect-ratio, 16 / 9);
679
+ }
680
+ .j-aspect-ratio__content {
681
+ position: absolute;
682
+ inset: 0;
683
+ overflow: hidden;
684
+ }
685
+ .j-aspect-ratio__content > :where(img, video, iframe, canvas) {
686
+ display: block;
687
+ width: 100%;
688
+ height: 100%;
689
+ object-fit: cover;
668
690
  }
691
+ }
669
692
 
693
+ @layer theme, base, juxt, components, utilities;
670
694
  @layer juxt {
671
695
  .j-avatar {
672
696
  --j-avatar-size: 2rem;
@@ -779,9 +803,65 @@
779
803
  }
780
804
  }
781
805
 
806
+ @layer theme, base, juxt, components, utilities;
807
+ @layer juxt {
808
+ .j-avatar-group {
809
+ --j-avatar-group-overlap: 0.5em;
810
+
811
+ display: inline-flex;
812
+ align-items: center;
813
+ font-family: var(--juxt-font-sans);
814
+ }
815
+ .j-avatar-group__item {
816
+ position: relative;
817
+ display: inline-flex;
818
+ flex: none;
819
+ border-radius: var(--juxt-radius-full);
820
+ box-shadow: 0 0 0 2px var(--juxt-bg);
821
+ }
822
+ .j-avatar-group__item:not(:first-child) {
823
+ margin-left: calc(var(--j-avatar-group-overlap) * -1);
824
+ }
825
+ .j-avatar-group__overflow {
826
+ display: grid;
827
+ place-items: center;
828
+ width: 2rem;
829
+ height: 2rem;
830
+ background: var(--juxt-surface-active);
831
+ color: var(--juxt-fg-secondary);
832
+ font-size: var(--juxt-text-xs);
833
+ font-weight: var(--juxt-weight-medium);
834
+ font-variant-numeric: tabular-nums;
835
+ }
836
+ .j-avatar-group--xs .j-avatar-group__overflow {
837
+ width: 1.25rem;
838
+ height: 1.25rem;
839
+ font-size: var(--juxt-text-2xs);
840
+ }
841
+ .j-avatar-group--sm .j-avatar-group__overflow {
842
+ width: 1.5rem;
843
+ height: 1.5rem;
844
+ font-size: 0.625rem;
845
+ }
846
+ .j-avatar-group--lg .j-avatar-group__overflow {
847
+ width: 2.5rem;
848
+ height: 2.5rem;
849
+ font-size: var(--juxt-text-sm);
850
+ }
851
+ .j-avatar-group--xl .j-avatar-group__overflow {
852
+ width: 3.5rem;
853
+ height: 3.5rem;
854
+ font-size: var(--juxt-text-lg);
855
+ }
856
+ .j-avatar-group__overflow--square {
857
+ border-radius: 22%;
858
+ }
859
+ }
860
+
861
+ @layer theme, base, juxt, components, utilities;
782
862
  @layer juxt {
783
863
  /*
784
- * Badges are small, square-shouldered labels — closer to a stamp than a pill.
864
+ * Badges are small, square-shouldered labels | closer to a stamp than a pill.
785
865
  * No borders: a quiet tint and the text colour carry the meaning.
786
866
  */
787
867
  .j-badge {
@@ -828,7 +908,7 @@
828
908
  --j-badge-marker: var(--juxt-danger);
829
909
  }
830
910
 
831
- /* Accent is the only solid badge — reserve it for the thing that matters. */
911
+ /* Accent is the only solid badge | reserve it for the thing that matters. */
832
912
  .j-badge--accent {
833
913
  --j-badge-fg: var(--juxt-accent-fg);
834
914
  --j-badge-bg: var(--juxt-accent-strong);
@@ -862,49 +942,278 @@
862
942
  }
863
943
  }
864
944
 
865
- @layer juxt {
866
- .j-button {
867
- --j-button-height: var(--juxt-control-md);
868
- --j-button-px: var(--juxt-space-3);
869
- --j-button-gap: var(--juxt-space-1-5);
870
- --j-button-font: var(--juxt-text-md);
871
- --j-button-radius: var(--juxt-radius-sm);
945
+ @layer theme, base, juxt, components, utilities;
946
+ @layer juxt {
947
+ /*
948
+ * Banners run edge-to-edge across a page or section, unlike JAlert which sits
949
+ * inline in a card or form. A flat tinted surface and a left accent bar
950
+ * distinguish them from the bordered, neutral surface of an alert.
951
+ */
952
+ .j-banner {
953
+ --j-banner-accent: var(--juxt-fg-muted);
954
+ --j-banner-bg: var(--juxt-surface-sunken);
872
955
 
873
956
  position: relative;
874
- display: inline-flex;
957
+ display: flex;
875
958
  align-items: center;
876
- justify-content: center;
877
- height: var(--j-button-height);
878
- padding: 0 var(--j-button-px);
879
- border: 1px solid transparent;
880
- border-radius: var(--j-button-radius);
881
- font-family: var(--juxt-font-sans);
882
- font-size: var(--j-button-font);
883
- font-weight: var(--juxt-weight-medium);
884
- line-height: 1;
885
- letter-spacing: var(--juxt-tracking-tight);
886
- white-space: nowrap;
887
- text-decoration: none;
888
- cursor: pointer;
889
- user-select: none;
890
- -webkit-tap-highlight-color: transparent;
891
- touch-action: manipulation;
892
- transition-property: background-color, border-color, color, box-shadow, transform, outline-color, outline-offset;
893
- transition-duration: var(--juxt-duration-fast);
894
- transition-timing-function: var(--juxt-ease-standard);
895
- }
896
-
897
- /* Pressed: a short, physical dip. Released slower than pressed. */
898
- .j-button:active:not([aria-disabled='true'], :disabled) {
899
- transform: scale(0.97);
900
- transition-duration: var(--juxt-duration-instant);
959
+ gap: var(--juxt-space-3);
960
+ padding: var(--juxt-space-3) var(--juxt-space-5);
961
+ border-left: 3px solid var(--j-banner-accent);
962
+ background: var(--j-banner-bg);
963
+ color: var(--juxt-fg);
964
+ font-family: var(--juxt-font-sans);
901
965
  }
902
- @media (prefers-reduced-motion: reduce) {
903
- .j-button:active:not([aria-disabled='true'], :disabled) {
904
- transform: none;
966
+ .j-banner--info {
967
+ --j-banner-accent: var(--juxt-info);
968
+ --j-banner-bg: var(--juxt-info-soft);
905
969
  }
970
+ .j-banner--success {
971
+ --j-banner-accent: var(--juxt-success);
972
+ --j-banner-bg: var(--juxt-success-soft);
906
973
  }
907
- .j-button__content {
974
+ .j-banner--warning {
975
+ --j-banner-accent: var(--juxt-warning);
976
+ --j-banner-bg: var(--juxt-warning-soft);
977
+ }
978
+ .j-banner--destructive {
979
+ --j-banner-accent: var(--juxt-danger);
980
+ --j-banner-bg: var(--juxt-danger-soft);
981
+ }
982
+ .j-banner__icon {
983
+ display: grid;
984
+ flex: none;
985
+ place-items: center;
986
+ height: 1.25rem;
987
+ color: var(--j-banner-accent);
988
+ }
989
+ .j-banner__icon > svg {
990
+ width: 1rem;
991
+ height: 1rem;
992
+ }
993
+ .j-banner__body {
994
+ display: flex;
995
+ flex: 1;
996
+ flex-wrap: wrap;
997
+ align-items: baseline;
998
+ gap: var(--juxt-space-1) var(--juxt-space-2);
999
+ min-width: 0;
1000
+ }
1001
+ .j-banner__title {
1002
+ margin: 0;
1003
+ color: var(--juxt-fg);
1004
+ font-size: var(--juxt-text-md);
1005
+ font-weight: var(--juxt-weight-medium);
1006
+ letter-spacing: var(--juxt-tracking-tight);
1007
+ }
1008
+ .j-banner__description {
1009
+ color: var(--juxt-fg-secondary);
1010
+ font-size: var(--juxt-text-sm);
1011
+ line-height: var(--juxt-leading-normal);
1012
+ }
1013
+ .j-banner__description > p {
1014
+ margin: 0;
1015
+ }
1016
+ .j-banner__actions {
1017
+ display: flex;
1018
+ flex: none;
1019
+ flex-wrap: wrap;
1020
+ gap: var(--juxt-space-2);
1021
+ }
1022
+ .j-banner__close {
1023
+ display: grid;
1024
+ flex: none;
1025
+ place-items: center;
1026
+ width: 1.5rem;
1027
+ height: 1.5rem;
1028
+ padding: 0;
1029
+ border: 0;
1030
+ border-radius: var(--juxt-radius-xs);
1031
+ background: transparent;
1032
+ color: var(--juxt-fg-muted);
1033
+ cursor: pointer;
1034
+ transition-property: background-color, color, outline-color, outline-offset;
1035
+ }
1036
+ .j-banner__close:hover {
1037
+ background: var(--juxt-surface-hover);
1038
+ color: var(--juxt-fg);
1039
+ }
1040
+ .j-banner__close > svg {
1041
+ width: 0.875rem;
1042
+ height: 0.875rem;
1043
+ }
1044
+ }
1045
+
1046
+ @layer theme, base, juxt, components, utilities;
1047
+ @layer juxt {
1048
+ .j-breadcrumb {
1049
+ font-family: var(--juxt-font-sans);
1050
+ }
1051
+ .j-breadcrumb__list {
1052
+ display: flex;
1053
+ flex-wrap: wrap;
1054
+ align-items: center;
1055
+ gap: var(--juxt-space-1-5);
1056
+ margin: 0;
1057
+ padding: 0;
1058
+ list-style: none;
1059
+ }
1060
+ .j-breadcrumb__item {
1061
+ display: flex;
1062
+ align-items: center;
1063
+ gap: var(--juxt-space-1-5);
1064
+ color: var(--juxt-fg-muted);
1065
+ font-size: var(--juxt-text-sm);
1066
+ line-height: var(--juxt-leading-snug);
1067
+ }
1068
+ .j-breadcrumb__item:not(:first-child)::before {
1069
+ content: '';
1070
+ display: inline-block;
1071
+ width: 0.3125rem;
1072
+ height: 0.3125rem;
1073
+ margin-right: var(--juxt-space-1-5);
1074
+ border-top: 1.5px solid var(--juxt-fg-disabled);
1075
+ border-right: 1.5px solid var(--juxt-fg-disabled);
1076
+ transform: rotate(45deg);
1077
+ }
1078
+ .j-breadcrumb__link {
1079
+ border-radius: var(--juxt-radius-xs);
1080
+ color: var(--juxt-fg-muted);
1081
+ text-decoration: none;
1082
+ transition: color var(--juxt-duration-fast) var(--juxt-ease-standard);
1083
+ }
1084
+ .j-breadcrumb__link:hover {
1085
+ color: var(--juxt-fg);
1086
+ text-decoration: underline;
1087
+ text-underline-offset: 2px;
1088
+ }
1089
+ .j-breadcrumb__current {
1090
+ color: var(--juxt-fg);
1091
+ font-weight: var(--juxt-weight-medium);
1092
+ letter-spacing: var(--juxt-tracking-tight);
1093
+ }
1094
+ .j-breadcrumb__ellipsis {
1095
+ color: var(--juxt-fg-disabled);
1096
+ user-select: none;
1097
+ }
1098
+ }
1099
+
1100
+ @layer theme, base, juxt, components, utilities;
1101
+ @layer juxt {
1102
+ .j-burger {
1103
+ --j-burger-size: var(--juxt-control-md);
1104
+ --j-burger-width: 1rem;
1105
+ --j-burger-gap: 0.3125rem;
1106
+
1107
+ display: inline-grid;
1108
+ place-items: center;
1109
+ width: var(--j-burger-size);
1110
+ height: var(--j-burger-size);
1111
+ padding: 0;
1112
+ border: 0;
1113
+ border-radius: var(--juxt-radius-sm);
1114
+ background: transparent;
1115
+ color: var(--juxt-fg);
1116
+ cursor: pointer;
1117
+ -webkit-tap-highlight-color: transparent;
1118
+ transition-property: background-color, outline-color, outline-offset;
1119
+ }
1120
+ .j-burger--sm {
1121
+ --j-burger-size: var(--juxt-control-sm);
1122
+ --j-burger-width: 0.875rem;
1123
+ --j-burger-gap: 0.25rem;
1124
+ }
1125
+ .j-burger:hover {
1126
+ background: var(--juxt-surface-hover);
1127
+ }
1128
+ .j-burger__lines {
1129
+ position: relative;
1130
+ display: block;
1131
+ width: var(--j-burger-width);
1132
+ height: calc(var(--j-burger-gap) * 2 + 1.5px);
1133
+ }
1134
+ .j-burger__line {
1135
+ position: absolute;
1136
+ left: 0;
1137
+ width: 100%;
1138
+ height: 1.5px;
1139
+ border-radius: 1px;
1140
+ background: currentColor;
1141
+ transition:
1142
+ transform var(--juxt-duration-normal) var(--juxt-ease-out),
1143
+ opacity var(--juxt-duration-fast) var(--juxt-ease-standard);
1144
+ }
1145
+ .j-burger__line:nth-child(1) {
1146
+ top: 0;
1147
+ }
1148
+ .j-burger__line:nth-child(2) {
1149
+ top: var(--j-burger-gap);
1150
+ }
1151
+ .j-burger__line:nth-child(3) {
1152
+ top: calc(var(--j-burger-gap) * 2);
1153
+ }
1154
+
1155
+ /* Outer lines meet in the middle and cross; the middle one fades. */
1156
+ .j-burger[data-state='open'] .j-burger__line:nth-child(1) {
1157
+ transform: translateY(var(--j-burger-gap)) rotate(45deg);
1158
+ }
1159
+ .j-burger[data-state='open'] .j-burger__line:nth-child(2) {
1160
+ opacity: 0;
1161
+ transform: scaleX(0.4);
1162
+ }
1163
+ .j-burger[data-state='open'] .j-burger__line:nth-child(3) {
1164
+ transform: translateY(calc(var(--j-burger-gap) * -1)) rotate(-45deg);
1165
+ }
1166
+ @media (prefers-reduced-motion: reduce) {
1167
+ .j-burger__line {
1168
+ transition-duration: 0ms;
1169
+ }
1170
+ }
1171
+ }
1172
+
1173
+ @layer theme, base, juxt, components, utilities;
1174
+ @layer juxt {
1175
+ .j-button {
1176
+ --j-button-height: var(--juxt-control-md);
1177
+ --j-button-px: var(--juxt-space-3);
1178
+ --j-button-gap: var(--juxt-space-1-5);
1179
+ --j-button-font: var(--juxt-text-md);
1180
+ --j-button-radius: var(--juxt-radius-sm);
1181
+
1182
+ position: relative;
1183
+ display: inline-flex;
1184
+ align-items: center;
1185
+ justify-content: center;
1186
+ height: var(--j-button-height);
1187
+ padding: 0 var(--j-button-px);
1188
+ border: 1px solid transparent;
1189
+ border-radius: var(--j-button-radius);
1190
+ font-family: var(--juxt-font-sans);
1191
+ font-size: var(--j-button-font);
1192
+ font-weight: var(--juxt-weight-medium);
1193
+ line-height: 1;
1194
+ letter-spacing: var(--juxt-tracking-tight);
1195
+ white-space: nowrap;
1196
+ text-decoration: none;
1197
+ cursor: pointer;
1198
+ user-select: none;
1199
+ -webkit-tap-highlight-color: transparent;
1200
+ touch-action: manipulation;
1201
+ transition-property: background-color, border-color, color, box-shadow, transform, outline-color, outline-offset;
1202
+ transition-duration: var(--juxt-duration-fast);
1203
+ transition-timing-function: var(--juxt-ease-standard);
1204
+ }
1205
+
1206
+ /* Pressed: a short, physical dip. Released slower than pressed. */
1207
+ .j-button:active:not([aria-disabled='true'], :disabled) {
1208
+ transform: scale(0.97);
1209
+ transition-duration: var(--juxt-duration-instant);
1210
+ }
1211
+ @media (prefers-reduced-motion: reduce) {
1212
+ .j-button:active:not([aria-disabled='true'], :disabled) {
1213
+ transform: none;
1214
+ }
1215
+ }
1216
+ .j-button__content {
908
1217
  display: inline-flex;
909
1218
  align-items: center;
910
1219
  gap: var(--j-button-gap);
@@ -1049,6 +1358,7 @@
1049
1358
  }
1050
1359
  }
1051
1360
 
1361
+ @layer theme, base, juxt, components, utilities;
1052
1362
  @layer juxt {
1053
1363
  .j-card {
1054
1364
  --j-card-p: var(--juxt-space-5);
@@ -1141,6 +1451,7 @@
1141
1451
  }
1142
1452
  }
1143
1453
 
1454
+ @layer theme, base, juxt, components, utilities;
1144
1455
  @layer juxt {
1145
1456
  .j-checkbox {
1146
1457
  --j-checkbox-size: 1rem;
@@ -1281,6 +1592,79 @@
1281
1592
  }
1282
1593
  }
1283
1594
 
1595
+ @layer theme, base, juxt, components, utilities;
1596
+ @layer juxt {
1597
+ .j-collapsible {
1598
+ font-family: var(--juxt-font-sans);
1599
+ }
1600
+ .j-collapsible__trigger {
1601
+ display: inline-flex;
1602
+ align-items: center;
1603
+ gap: var(--juxt-space-1-5);
1604
+ padding: var(--juxt-space-1) 0;
1605
+ border: 0;
1606
+ border-radius: var(--juxt-radius-xs);
1607
+ background: transparent;
1608
+ color: var(--juxt-fg);
1609
+ font: inherit;
1610
+ font-size: var(--juxt-text-md);
1611
+ font-weight: var(--juxt-weight-medium);
1612
+ letter-spacing: var(--juxt-tracking-tight);
1613
+ cursor: pointer;
1614
+ outline: 2px solid transparent;
1615
+ outline-offset: 2px;
1616
+ -webkit-tap-highlight-color: transparent;
1617
+ transition:
1618
+ color var(--juxt-duration-fast) var(--juxt-ease-standard),
1619
+ outline-color var(--juxt-duration-fast) var(--juxt-ease-out);
1620
+ }
1621
+ .j-collapsible__trigger:disabled {
1622
+ color: var(--juxt-fg-disabled);
1623
+ cursor: not-allowed;
1624
+ }
1625
+ .j-collapsible__chevron {
1626
+ flex: none;
1627
+ width: 1rem;
1628
+ height: 1rem;
1629
+ color: var(--juxt-fg-muted);
1630
+ transition: transform var(--juxt-duration-normal) var(--juxt-ease-out);
1631
+ }
1632
+ .j-collapsible[data-state='open'] .j-collapsible__chevron {
1633
+ transform: rotate(180deg);
1634
+ }
1635
+ .j-collapsible__panel {
1636
+ display: grid;
1637
+ grid-template-rows: 0fr;
1638
+ transition: grid-template-rows var(--juxt-duration-slow) var(--juxt-ease-out);
1639
+ }
1640
+ .j-collapsible[data-state='open'] .j-collapsible__panel {
1641
+ grid-template-rows: 1fr;
1642
+ }
1643
+ .j-collapsible__panel-inner {
1644
+ min-height: 0;
1645
+ overflow: hidden;
1646
+ }
1647
+ .j-collapsible__content {
1648
+ padding-top: var(--juxt-space-2);
1649
+ color: var(--juxt-fg-secondary);
1650
+ font-size: var(--juxt-text-md);
1651
+ line-height: var(--juxt-leading-normal);
1652
+ opacity: 0;
1653
+ transition: opacity var(--juxt-duration-fast) var(--juxt-ease-standard);
1654
+ }
1655
+ .j-collapsible[data-state='open'] .j-collapsible__content {
1656
+ opacity: 1;
1657
+ transition-delay: 60ms;
1658
+ }
1659
+ @media (prefers-reduced-motion: reduce) {
1660
+ .j-collapsible__panel,
1661
+ .j-collapsible__chevron {
1662
+ transition: none;
1663
+ }
1664
+ }
1665
+ }
1666
+
1667
+ @layer theme, base, juxt, components, utilities;
1284
1668
  @layer juxt {
1285
1669
  .j-command__overlay {
1286
1670
  position: fixed;
@@ -1597,6 +1981,7 @@ to {
1597
1981
  }
1598
1982
  }
1599
1983
 
1984
+ @layer theme, base, juxt, components, utilities;
1600
1985
  @layer juxt {
1601
1986
  .j-dialog__overlay {
1602
1987
  position: fixed;
@@ -1766,6 +2151,7 @@ to {
1766
2151
  }
1767
2152
  }
1768
2153
 
2154
+ @layer theme, base, juxt, components, utilities;
1769
2155
  @layer juxt {
1770
2156
  .j-menu {
1771
2157
  z-index: var(--juxt-z-popover);
@@ -1871,43 +2257,224 @@ to {
1871
2257
  }
1872
2258
  }
1873
2259
 
2260
+ @layer theme, base, juxt, components, utilities;
1874
2261
  @layer juxt {
1875
- .j-field {
2262
+ .j-empty-state {
1876
2263
  display: flex;
1877
2264
  flex-direction: column;
1878
- gap: var(--juxt-space-1-5);
1879
- min-width: 0;
2265
+ align-items: center;
2266
+ max-width: 24rem;
2267
+ margin: 0 auto;
2268
+ padding: var(--juxt-space-8) var(--juxt-space-4);
2269
+ text-align: center;
1880
2270
  font-family: var(--juxt-font-sans);
1881
2271
  }
1882
- .j-field__label {
1883
- display: inline-flex;
1884
- align-items: baseline;
1885
- gap: var(--juxt-space-0-5);
1886
- width: fit-content;
1887
- color: var(--juxt-fg);
1888
- font-size: var(--juxt-text-sm);
1889
- font-weight: var(--juxt-weight-medium);
1890
- line-height: var(--juxt-leading-snug);
1891
- letter-spacing: var(--juxt-tracking-tight);
2272
+ .j-empty-state--sm {
2273
+ max-width: 18rem;
2274
+ padding: var(--juxt-space-6) var(--juxt-space-3);
1892
2275
  }
1893
- .j-field.is-disabled .j-field__label {
1894
- color: var(--juxt-fg-muted);
2276
+ .j-empty-state--lg {
2277
+ max-width: 28rem;
2278
+ padding: var(--juxt-space-12) var(--juxt-space-4);
1895
2279
  }
1896
- .j-field__required {
1897
- color: var(--juxt-fg-muted);
1898
- font-weight: var(--juxt-weight-regular);
2280
+ .j-empty-state__icon {
2281
+ display: grid;
2282
+ place-items: center;
2283
+ width: 2.75rem;
2284
+ height: 2.75rem;
2285
+ margin-bottom: var(--juxt-space-4);
2286
+ border-radius: var(--juxt-radius-full);
2287
+ background: var(--juxt-surface-sunken);
2288
+ color: var(--juxt-fg-muted);
1899
2289
  }
1900
- .j-field__messages:empty {
1901
- display: none;
2290
+ .j-empty-state--lg .j-empty-state__icon {
2291
+ width: 3.5rem;
2292
+ height: 3.5rem;
1902
2293
  }
1903
- .j-field__description,
1904
- .j-field__error {
1905
- margin: 0;
1906
- font-size: var(--juxt-text-xs);
1907
- line-height: var(--juxt-leading-normal);
2294
+ .j-empty-state__icon > svg {
2295
+ width: 1.25rem;
2296
+ height: 1.25rem;
1908
2297
  }
1909
- .j-field__description {
1910
- color: var(--juxt-fg-muted);
2298
+ .j-empty-state--lg .j-empty-state__icon > svg {
2299
+ width: 1.5rem;
2300
+ height: 1.5rem;
2301
+ }
2302
+ .j-empty-state__title {
2303
+ margin: 0;
2304
+ color: var(--juxt-fg);
2305
+ font-size: var(--juxt-text-lg);
2306
+ font-weight: var(--juxt-weight-semibold);
2307
+ letter-spacing: var(--juxt-tracking-tight);
2308
+ }
2309
+ .j-empty-state__description {
2310
+ margin-top: var(--juxt-space-1-5);
2311
+ color: var(--juxt-fg-muted);
2312
+ font-size: var(--juxt-text-sm);
2313
+ line-height: var(--juxt-leading-normal);
2314
+ }
2315
+ .j-empty-state__description > p {
2316
+ margin: 0;
2317
+ }
2318
+ .j-empty-state__actions {
2319
+ display: flex;
2320
+ flex-wrap: wrap;
2321
+ justify-content: center;
2322
+ gap: var(--juxt-space-2);
2323
+ margin-top: var(--juxt-space-5);
2324
+ }
2325
+ }
2326
+
2327
+ @layer theme, base, juxt, components, utilities;
2328
+ @layer juxt {
2329
+ .j-footer {
2330
+ background: var(--juxt-bg);
2331
+ color: var(--juxt-fg-secondary);
2332
+ font-family: var(--juxt-font-sans);
2333
+ font-size: var(--juxt-text-sm);
2334
+ }
2335
+ .j-footer.is-bordered {
2336
+ border-top: 1px solid var(--juxt-border-subtle);
2337
+ }
2338
+ .dark .j-footer.is-bordered,
2339
+ [data-theme='dark'] .j-footer.is-bordered {
2340
+ border-top-color: var(--juxt-border);
2341
+ }
2342
+ .j-footer__inner {
2343
+ max-width: var(--j-footer-max);
2344
+ margin: 0 auto;
2345
+ padding: var(--juxt-space-12) var(--juxt-space-4) var(--juxt-space-8);
2346
+ }
2347
+ .j-footer__top {
2348
+ display: grid;
2349
+ grid-template-columns: minmax(0, 1fr);
2350
+ gap: var(--juxt-space-10);
2351
+ }
2352
+ .j-footer__brand {
2353
+ display: flex;
2354
+ flex-direction: column;
2355
+ gap: var(--juxt-space-3);
2356
+ max-width: 18rem;
2357
+ color: var(--juxt-fg-muted);
2358
+ line-height: var(--juxt-leading-normal);
2359
+ }
2360
+ .j-footer__columns {
2361
+ display: grid;
2362
+ grid-template-columns: repeat(2, minmax(0, 1fr));
2363
+ gap: var(--juxt-space-8) var(--juxt-space-6);
2364
+ }
2365
+ @media (min-width: 768px) {
2366
+ .j-footer__top {
2367
+ grid-template-columns: minmax(12rem, 1fr) minmax(0, 2fr);
2368
+ }
2369
+ .j-footer__columns {
2370
+ grid-template-columns: repeat(auto-fit, minmax(8rem, 1fr));
2371
+ }
2372
+ }
2373
+ .j-footer__bottom {
2374
+ display: flex;
2375
+ flex-wrap: wrap;
2376
+ align-items: center;
2377
+ justify-content: space-between;
2378
+ gap: var(--juxt-space-3) var(--juxt-space-6);
2379
+ margin-top: var(--juxt-space-12);
2380
+ padding-top: var(--juxt-space-6);
2381
+ border-top: 1px solid var(--juxt-border-subtle);
2382
+ color: var(--juxt-fg-muted);
2383
+ font-size: var(--juxt-text-xs);
2384
+ }
2385
+ .dark .j-footer__bottom,
2386
+ [data-theme='dark'] .j-footer__bottom {
2387
+ border-top-color: var(--juxt-border);
2388
+ }
2389
+ .j-footer__bottom a {
2390
+ color: inherit;
2391
+ text-decoration: none;
2392
+ transition: color var(--juxt-duration-fast) var(--juxt-ease-standard);
2393
+ }
2394
+ .j-footer__bottom a:hover {
2395
+ color: var(--juxt-fg);
2396
+ }
2397
+ }
2398
+
2399
+ @layer theme, base, juxt, components, utilities;
2400
+ @layer juxt {
2401
+ .j-footer-column {
2402
+ display: flex;
2403
+ flex-direction: column;
2404
+ gap: var(--juxt-space-3);
2405
+ min-width: 0;
2406
+ }
2407
+ .j-footer-column__title {
2408
+ margin: 0;
2409
+ color: var(--juxt-fg);
2410
+ font-size: var(--juxt-text-sm);
2411
+ font-weight: var(--juxt-weight-medium);
2412
+ letter-spacing: var(--juxt-tracking-tight);
2413
+ }
2414
+ .j-footer-column__links {
2415
+ display: flex;
2416
+ flex-direction: column;
2417
+ align-items: flex-start;
2418
+ gap: var(--juxt-space-2);
2419
+ }
2420
+ .j-footer-column__links a {
2421
+ border-radius: var(--juxt-radius-xs);
2422
+ color: var(--juxt-fg-muted);
2423
+ text-decoration: none;
2424
+ outline: 2px solid transparent;
2425
+ outline-offset: 0;
2426
+ transition:
2427
+ color var(--juxt-duration-fast) var(--juxt-ease-standard),
2428
+ outline-color var(--juxt-duration-fast) var(--juxt-ease-out),
2429
+ outline-offset var(--juxt-duration-fast) var(--juxt-ease-out);
2430
+ }
2431
+ .j-footer-column__links a:hover {
2432
+ color: var(--juxt-fg);
2433
+ }
2434
+ .j-footer-column__links a:focus-visible {
2435
+ outline-color: var(--juxt-ring);
2436
+ outline-offset: 2px;
2437
+ }
2438
+ }
2439
+
2440
+ @layer theme, base, juxt, components, utilities;
2441
+ @layer juxt {
2442
+ .j-field {
2443
+ display: flex;
2444
+ flex-direction: column;
2445
+ gap: var(--juxt-space-1-5);
2446
+ min-width: 0;
2447
+ font-family: var(--juxt-font-sans);
2448
+ }
2449
+ .j-field__label {
2450
+ display: inline-flex;
2451
+ align-items: baseline;
2452
+ gap: var(--juxt-space-0-5);
2453
+ width: fit-content;
2454
+ color: var(--juxt-fg);
2455
+ font-size: var(--juxt-text-sm);
2456
+ font-weight: var(--juxt-weight-medium);
2457
+ line-height: var(--juxt-leading-snug);
2458
+ letter-spacing: var(--juxt-tracking-tight);
2459
+ }
2460
+ .j-field.is-disabled .j-field__label {
2461
+ color: var(--juxt-fg-muted);
2462
+ }
2463
+ .j-field__required {
2464
+ color: var(--juxt-fg-muted);
2465
+ font-weight: var(--juxt-weight-regular);
2466
+ }
2467
+ .j-field__messages:empty {
2468
+ display: none;
2469
+ }
2470
+ .j-field__description,
2471
+ .j-field__error {
2472
+ margin: 0;
2473
+ font-size: var(--juxt-text-xs);
2474
+ line-height: var(--juxt-leading-normal);
2475
+ }
2476
+ .j-field__description {
2477
+ color: var(--juxt-fg-muted);
1911
2478
  }
1912
2479
  .j-field__error {
1913
2480
  color: var(--juxt-danger-text);
@@ -1929,6 +2496,7 @@ to {
1929
2496
  }
1930
2497
  }
1931
2498
 
2499
+ @layer theme, base, juxt, components, utilities;
1932
2500
  @layer juxt {
1933
2501
  .j-input__native {
1934
2502
  flex: 1;
@@ -1955,280 +2523,619 @@ to {
1955
2523
  }
1956
2524
  }
1957
2525
 
2526
+ @layer theme, base, juxt, components, utilities;
1958
2527
  @layer juxt {
1959
- .j-kbd-group {
1960
- display: inline-flex;
1961
- gap: 3px;
2528
+ .j-kbd-group {
2529
+ display: inline-flex;
2530
+ gap: 3px;
1962
2531
  vertical-align: middle;
1963
2532
  }
1964
- .j-kbd-group--sm .j-kbd,
1965
- .j-kbd--sm {
1966
- min-width: 1.0625rem;
1967
- height: 1.0625rem;
2533
+ .j-kbd-group--sm .j-kbd,
2534
+ .j-kbd--sm {
2535
+ min-width: 1.0625rem;
2536
+ height: 1.0625rem;
1968
2537
  font-size: 0.625rem;
1969
2538
  }
1970
- }
1971
-
1972
- @layer juxt {
1973
- .j-popover {
1974
- z-index: var(--juxt-z-popover);
1975
- box-sizing: border-box;
1976
- max-width: calc(100vw - 16px);
1977
- max-height: var(--j-available-height, 32rem);
1978
- padding: var(--juxt-space-4);
1979
- overflow: auto;
1980
- outline: none;
1981
- font-size: var(--juxt-text-md);
1982
- line-height: var(--juxt-leading-normal);
1983
- }
1984
- }
2539
+ }
1985
2540
 
2541
+ @layer theme, base, juxt, components, utilities;
1986
2542
  @layer juxt {
1987
- .j-progress {
1988
- --j-progress-height: 0.375rem;
1989
- --j-progress-fill: var(--juxt-accent);
2543
+ .j-navbar {
2544
+ --j-navbar-height: 3.5rem;
1990
2545
 
1991
- display: flex;
1992
- flex-direction: column;
1993
- gap: var(--juxt-space-2);
1994
- width: 100%;
2546
+ position: relative;
2547
+ z-index: var(--juxt-z-sticky);
2548
+ background: var(--juxt-bg);
2549
+ color: var(--juxt-fg);
1995
2550
  font-family: var(--juxt-font-sans);
1996
2551
  }
1997
- .j-progress--sm {
1998
- --j-progress-height: 0.25rem;
2552
+ .j-navbar.is-sticky {
2553
+ position: sticky;
2554
+ top: 0;
1999
2555
  }
2000
- .j-progress--neutral {
2001
- --j-progress-fill: var(--juxt-fg);
2556
+ .j-navbar.is-bordered {
2557
+ box-shadow: inset 0 -1px 0 var(--juxt-border-subtle);
2558
+ }
2559
+ .dark .j-navbar.is-bordered,
2560
+ [data-theme='dark'] .j-navbar.is-bordered {
2561
+ box-shadow: inset 0 -1px 0 var(--juxt-border);
2002
2562
  }
2003
- .j-progress__header {
2563
+ .j-navbar__bar {
2004
2564
  display: flex;
2005
- align-items: baseline;
2006
- justify-content: space-between;
2007
- gap: var(--juxt-space-3);
2008
- font-size: var(--juxt-text-sm);
2565
+ align-items: center;
2566
+ gap: var(--juxt-space-6);
2567
+ max-width: var(--j-navbar-max);
2568
+ height: var(--j-navbar-height);
2569
+ margin: 0 auto;
2570
+ padding: 0 var(--juxt-space-4);
2009
2571
  }
2010
- .j-progress__label {
2011
- color: var(--juxt-fg);
2012
- font-weight: var(--juxt-weight-medium);
2013
- letter-spacing: var(--juxt-tracking-tight);
2572
+ .j-navbar__brand {
2573
+ display: flex;
2574
+ flex: none;
2575
+ align-items: center;
2014
2576
  }
2015
- .j-progress__value {
2016
- color: var(--juxt-fg-muted);
2017
- font-variant-numeric: tabular-nums;
2577
+ .j-navbar__links {
2578
+ display: flex;
2579
+ align-items: center;
2580
+ gap: var(--juxt-space-1);
2581
+ min-width: 0;
2018
2582
  }
2019
- .j-progress__track {
2020
- position: relative;
2021
- height: var(--j-progress-height);
2022
- overflow: hidden;
2023
- border-radius: var(--juxt-radius-full);
2024
- background: var(--juxt-surface-active);
2583
+ .j-navbar__end {
2584
+ display: flex;
2585
+ align-items: center;
2586
+ gap: var(--juxt-space-2);
2587
+ margin-left: auto;
2588
+ }
2589
+ .j-navbar__actions {
2590
+ display: flex;
2591
+ align-items: center;
2592
+ gap: var(--juxt-space-2);
2593
+ }
2594
+ .j-navbar__burger {
2595
+ display: none;
2596
+ margin-right: calc(var(--juxt-space-2) * -1);
2025
2597
  }
2026
2598
 
2027
- /* Width changes are transforms, so updates glide without reflow. */
2028
- .j-progress__fill {
2599
+ /* Mobile menu: a panel that drops from the bar, links stacked with big targets. */
2600
+ .j-navbar__menu {
2029
2601
  position: absolute;
2030
- inset: 0;
2031
- border-radius: inherit;
2032
- background: var(--j-progress-fill);
2033
- transform: scaleX(0);
2034
- transform-origin: left;
2035
- transition: transform var(--juxt-duration-slow) var(--juxt-ease-out);
2602
+ top: 100%;
2603
+ right: 0;
2604
+ left: 0;
2605
+ display: flex;
2606
+ flex-direction: column;
2607
+ gap: var(--juxt-space-4);
2608
+ max-height: calc(100dvh - var(--j-navbar-height));
2609
+ padding: var(--juxt-space-3) var(--juxt-space-4) var(--juxt-space-5);
2610
+ overflow-y: auto;
2611
+ border-bottom: 1px solid var(--juxt-border);
2612
+ background: var(--juxt-bg);
2613
+ box-shadow: var(--juxt-shadow-md);
2036
2614
  }
2037
- .j-progress.is-indeterminate .j-progress__fill {
2038
- width: 40%;
2039
- transform: none;
2040
- animation: j-progress-indeterminate 1.4s var(--juxt-ease-standard) infinite;
2615
+ .j-navbar__menu-links {
2616
+ display: flex;
2617
+ flex-direction: column;
2618
+ gap: var(--juxt-space-0-5);
2041
2619
  }
2042
- @keyframes j-progress-indeterminate {
2043
- from {
2044
- transform: translateX(-100%);
2620
+ .j-navbar__menu-links .j-navbar-link {
2621
+ justify-content: flex-start;
2622
+ height: 2.75rem;
2623
+ padding: 0 var(--juxt-space-3);
2624
+ font-size: var(--juxt-text-lg);
2045
2625
  }
2046
- to {
2047
- transform: translateX(250%);
2626
+ .j-navbar__menu-footer {
2627
+ display: flex;
2628
+ flex-direction: column;
2629
+ gap: var(--juxt-space-2);
2630
+ padding-top: var(--juxt-space-4);
2631
+ border-top: 1px solid var(--juxt-border-subtle);
2048
2632
  }
2633
+ .j-navbar__menu-footer > * {
2634
+ width: 100%;
2049
2635
  }
2050
- @media (prefers-reduced-motion: reduce) {
2051
- .j-progress.is-indeterminate .j-progress__fill {
2052
- width: 100%;
2053
- animation: j-progress-pulse 1.6s ease-in-out infinite;
2636
+ .j-navbar-menu-enter-active {
2637
+ transition:
2638
+ opacity var(--juxt-duration-fast) var(--juxt-ease-out),
2639
+ transform var(--juxt-duration-normal) var(--juxt-ease-out);
2054
2640
  }
2055
- @keyframes j-progress-pulse {
2056
- 50% {
2057
- opacity: 0.35;
2641
+ .j-navbar-menu-leave-active {
2642
+ transition:
2643
+ opacity var(--juxt-duration-instant) var(--juxt-ease-in),
2644
+ transform var(--juxt-duration-instant) var(--juxt-ease-in);
2058
2645
  }
2646
+ .j-navbar-menu-enter-from,
2647
+ .j-navbar-menu-leave-to {
2648
+ opacity: 0;
2649
+ transform: translateY(calc(var(--juxt-motion-shift) * -1));
2059
2650
  }
2651
+
2652
+ /* Collapse points. Above them the menu never shows, below them the links hide. */
2653
+ .j-navbar--collapse-never .j-navbar__menu {
2654
+ display: none !important;
2060
2655
  }
2656
+ @media (max-width: 639.98px) {
2657
+ .j-navbar--collapse-sm .j-navbar__links { display: none;
2061
2658
  }
2062
-
2063
- @layer juxt {
2064
- .j-radio {
2065
- --j-radio-size: 1rem;
2066
-
2067
- display: inline-flex;
2068
- align-items: flex-start;
2069
- gap: var(--juxt-space-2-5);
2070
- font-family: var(--juxt-font-sans);
2659
+ .j-navbar--collapse-sm .j-navbar__burger { display: inline-grid;
2071
2660
  }
2072
- .j-radio__control {
2073
- position: relative;
2074
- display: inline-flex;
2075
- flex: none;
2076
- margin-top: calc((var(--juxt-text-md) * var(--juxt-leading-snug) - var(--j-radio-size)) / 2);
2077
2661
  }
2078
- .j-radio__input {
2079
- position: absolute;
2080
- inset: -4px;
2081
- z-index: 1;
2082
- width: calc(100% + 8px);
2083
- height: calc(100% + 8px);
2084
- margin: 0;
2085
- opacity: 0;
2086
- cursor: pointer;
2662
+ @media (min-width: 640px) {
2663
+ .j-navbar--collapse-sm .j-navbar__menu { display: none !important;
2087
2664
  }
2088
- .j-radio__input:disabled {
2089
- cursor: not-allowed;
2090
2665
  }
2091
- .j-radio__circle {
2092
- position: relative;
2093
- display: block;
2094
- width: var(--j-radio-size);
2095
- height: var(--j-radio-size);
2096
- border: 1px solid var(--juxt-border-strong);
2097
- border-radius: var(--juxt-radius-full);
2098
- background: var(--juxt-surface);
2099
- box-shadow: var(--juxt-shadow-xs);
2100
- outline: 2px solid transparent;
2101
- outline-offset: 0;
2102
- transition:
2103
- background-color var(--juxt-duration-fast) var(--juxt-ease-standard),
2104
- border-color var(--juxt-duration-fast) var(--juxt-ease-standard),
2105
- transform var(--juxt-duration-fast) var(--juxt-ease-out),
2106
- outline-color var(--juxt-duration-fast) var(--juxt-ease-out),
2107
- outline-offset var(--juxt-duration-fast) var(--juxt-ease-out);
2666
+ @media (max-width: 767.98px) {
2667
+ .j-navbar--collapse-md .j-navbar__links { display: none;
2108
2668
  }
2109
-
2110
- /* The inner dot grows out of the centre once the fill lands. */
2111
- .j-radio__circle::after {
2112
- content: '';
2113
- position: absolute;
2114
- inset: 0;
2115
- margin: auto;
2116
- width: 0.375rem;
2117
- height: 0.375rem;
2118
- border-radius: var(--juxt-radius-full);
2119
- background: var(--juxt-accent-fg);
2120
- opacity: 0;
2121
- transform: scale(0.3);
2122
- transition:
2123
- opacity var(--juxt-duration-instant) var(--juxt-ease-standard),
2124
- transform var(--juxt-duration-normal) var(--juxt-ease-out);
2669
+ .j-navbar--collapse-md .j-navbar__burger { display: inline-grid;
2125
2670
  }
2126
- .j-radio__input:hover:not(:disabled) + .j-radio__circle {
2127
- border-color: var(--juxt-fg-muted);
2128
2671
  }
2129
- .j-radio__input:active:not(:disabled) + .j-radio__circle {
2130
- transform: scale(0.9);
2672
+ @media (min-width: 768px) {
2673
+ .j-navbar--collapse-md .j-navbar__menu { display: none !important;
2131
2674
  }
2132
- .j-radio__input:focus-visible + .j-radio__circle {
2133
- outline-color: var(--juxt-ring);
2134
- outline-offset: 2px;
2135
2675
  }
2136
- .j-radio[data-state='checked'] .j-radio__circle {
2137
- border-color: var(--juxt-accent);
2138
- background: var(--juxt-accent);
2676
+ @media (max-width: 1023.98px) {
2677
+ .j-navbar--collapse-lg .j-navbar__links { display: none;
2139
2678
  }
2140
- .j-radio[data-state='checked'] .j-radio__input:hover:not(:disabled) + .j-radio__circle {
2141
- border-color: var(--juxt-accent-hover);
2142
- background: var(--juxt-accent-hover);
2679
+ .j-navbar--collapse-lg .j-navbar__burger { display: inline-grid;
2143
2680
  }
2144
- .j-radio[data-state='checked'] .j-radio__circle::after {
2145
- opacity: 1;
2146
- transform: none;
2147
- transition-delay: 30ms;
2148
2681
  }
2149
- .j-radio-group.is-invalid .j-radio:not([data-state='checked']) .j-radio__circle {
2682
+ @media (min-width: 1024px) {
2683
+ .j-navbar--collapse-lg .j-navbar__menu { display: none !important;
2684
+ }
2685
+ }
2686
+ }
2687
+
2688
+ @layer theme, base, juxt, components, utilities;
2689
+ @layer juxt {
2690
+ .j-navbar-link {
2691
+ display: inline-flex;
2692
+ align-items: center;
2693
+ gap: var(--juxt-space-1-5);
2694
+ height: var(--juxt-control-sm);
2695
+ padding: 0 var(--juxt-space-2-5);
2696
+ border-radius: var(--juxt-radius-sm);
2697
+ color: var(--juxt-fg-muted);
2698
+ font-size: var(--juxt-text-sm);
2699
+ font-weight: var(--juxt-weight-medium);
2700
+ letter-spacing: var(--juxt-tracking-tight);
2701
+ text-decoration: none;
2702
+ white-space: nowrap;
2703
+ cursor: pointer;
2704
+ -webkit-tap-highlight-color: transparent;
2705
+ transition-property: color, background-color, outline-color, outline-offset;
2706
+ }
2707
+ .j-navbar-link:hover {
2708
+ color: var(--juxt-fg);
2709
+ }
2710
+ .j-navbar-link.is-active {
2711
+ color: var(--juxt-fg);
2712
+ }
2713
+
2714
+ /* In the mobile menu the current page gets a quiet fill, like a selected row. */
2715
+ .j-navbar__menu .j-navbar-link.is-active {
2716
+ background: var(--juxt-surface-hover);
2717
+ }
2718
+ .j-navbar-link__icon {
2719
+ display: inline-flex;
2720
+ color: var(--juxt-fg-muted);
2721
+ }
2722
+ .j-navbar-link__icon > svg {
2723
+ width: 1rem;
2724
+ height: 1rem;
2725
+ }
2726
+ }
2727
+
2728
+ @layer theme, base, juxt, components, utilities;
2729
+ @layer juxt {
2730
+ .j-pagination {
2731
+ --j-pagination-size: var(--juxt-control-md);
2732
+
2733
+ display: flex;
2734
+ align-items: center;
2735
+ gap: var(--juxt-space-1);
2736
+ font-family: var(--juxt-font-sans);
2737
+ }
2738
+ .j-pagination--sm {
2739
+ --j-pagination-size: var(--juxt-control-sm);
2740
+ }
2741
+ .j-pagination__list {
2742
+ display: flex;
2743
+ align-items: center;
2744
+ gap: var(--juxt-space-1);
2745
+ margin: 0;
2746
+ padding: 0;
2747
+ list-style: none;
2748
+ }
2749
+ .j-pagination__nav,
2750
+ .j-pagination__page {
2751
+ display: grid;
2752
+ flex: none;
2753
+ place-items: center;
2754
+ width: var(--j-pagination-size);
2755
+ height: var(--j-pagination-size);
2756
+ border: 1px solid transparent;
2757
+ border-radius: var(--juxt-radius-sm);
2758
+ background: transparent;
2759
+ color: var(--juxt-fg-secondary);
2760
+ font-family: inherit;
2761
+ font-size: var(--juxt-text-sm);
2762
+ font-weight: var(--juxt-weight-medium);
2763
+ font-variant-numeric: tabular-nums;
2764
+ cursor: pointer;
2765
+ transition:
2766
+ background-color var(--juxt-duration-fast) var(--juxt-ease-standard),
2767
+ border-color var(--juxt-duration-fast) var(--juxt-ease-standard),
2768
+ color var(--juxt-duration-fast) var(--juxt-ease-standard);
2769
+ }
2770
+ .j-pagination__nav > svg {
2771
+ width: 1rem;
2772
+ height: 1rem;
2773
+ }
2774
+ .j-pagination__nav:hover:not(:disabled),
2775
+ .j-pagination__page:hover:not(:disabled) {
2776
+ background: var(--juxt-surface-hover);
2777
+ color: var(--juxt-fg);
2778
+ }
2779
+ .j-pagination__nav:disabled {
2780
+ color: var(--juxt-fg-disabled);
2781
+ cursor: not-allowed;
2782
+ }
2783
+ .j-pagination__page.is-current {
2784
+ border-color: var(--juxt-border);
2785
+ background: var(--juxt-surface-active);
2786
+ color: var(--juxt-fg);
2787
+ }
2788
+ .j-pagination__page:disabled {
2789
+ color: var(--juxt-fg-disabled);
2790
+ cursor: not-allowed;
2791
+ }
2792
+ .j-pagination__ellipsis {
2793
+ display: grid;
2794
+ place-items: center;
2795
+ width: var(--j-pagination-size);
2796
+ height: var(--j-pagination-size);
2797
+ color: var(--juxt-fg-disabled);
2798
+ }
2799
+ .j-pagination__ellipsis > svg {
2800
+ width: 1rem;
2801
+ height: 1rem;
2802
+ }
2803
+ }
2804
+
2805
+ @layer theme, base, juxt, components, utilities;
2806
+ @layer juxt {
2807
+ .j-popover {
2808
+ z-index: var(--juxt-z-popover);
2809
+ box-sizing: border-box;
2810
+ max-width: calc(100vw - 16px);
2811
+ max-height: var(--j-available-height, 32rem);
2812
+ padding: var(--juxt-space-4);
2813
+ overflow: auto;
2814
+ outline: none;
2815
+ font-size: var(--juxt-text-md);
2816
+ line-height: var(--juxt-leading-normal);
2817
+ }
2818
+ }
2819
+
2820
+ @layer theme, base, juxt, components, utilities;
2821
+ @layer juxt {
2822
+ .j-progress {
2823
+ --j-progress-height: 0.375rem;
2824
+ --j-progress-fill: var(--juxt-accent);
2825
+
2826
+ display: flex;
2827
+ flex-direction: column;
2828
+ gap: var(--juxt-space-2);
2829
+ width: 100%;
2830
+ font-family: var(--juxt-font-sans);
2831
+ }
2832
+ .j-progress--sm {
2833
+ --j-progress-height: 0.25rem;
2834
+ }
2835
+ .j-progress--neutral {
2836
+ --j-progress-fill: var(--juxt-fg);
2837
+ }
2838
+ .j-progress__header {
2839
+ display: flex;
2840
+ align-items: baseline;
2841
+ justify-content: space-between;
2842
+ gap: var(--juxt-space-3);
2843
+ font-size: var(--juxt-text-sm);
2844
+ }
2845
+ .j-progress__label {
2846
+ color: var(--juxt-fg);
2847
+ font-weight: var(--juxt-weight-medium);
2848
+ letter-spacing: var(--juxt-tracking-tight);
2849
+ }
2850
+ .j-progress__value {
2851
+ color: var(--juxt-fg-muted);
2852
+ font-variant-numeric: tabular-nums;
2853
+ }
2854
+ .j-progress__track {
2855
+ position: relative;
2856
+ height: var(--j-progress-height);
2857
+ overflow: hidden;
2858
+ border-radius: var(--juxt-radius-full);
2859
+ background: var(--juxt-surface-active);
2860
+ }
2861
+
2862
+ /* Width changes are transforms, so updates glide without reflow. */
2863
+ .j-progress__fill {
2864
+ position: absolute;
2865
+ inset: 0;
2866
+ border-radius: inherit;
2867
+ background: var(--j-progress-fill);
2868
+ transform: scaleX(0);
2869
+ transform-origin: left;
2870
+ transition: transform var(--juxt-duration-slow) var(--juxt-ease-out);
2871
+ }
2872
+ .j-progress.is-indeterminate .j-progress__fill {
2873
+ width: 40%;
2874
+ transform: none;
2875
+ animation: j-progress-indeterminate 1.4s var(--juxt-ease-standard) infinite;
2876
+ }
2877
+ @keyframes j-progress-indeterminate {
2878
+ from {
2879
+ transform: translateX(-100%);
2880
+ }
2881
+ to {
2882
+ transform: translateX(250%);
2883
+ }
2884
+ }
2885
+ @media (prefers-reduced-motion: reduce) {
2886
+ .j-progress.is-indeterminate .j-progress__fill {
2887
+ width: 100%;
2888
+ animation: j-progress-pulse 1.6s ease-in-out infinite;
2889
+ }
2890
+ @keyframes j-progress-pulse {
2891
+ 50% {
2892
+ opacity: 0.35;
2893
+ }
2894
+ }
2895
+ }
2896
+ }
2897
+
2898
+ @layer theme, base, juxt, components, utilities;
2899
+ @layer juxt {
2900
+ .j-radio {
2901
+ --j-radio-size: 1rem;
2902
+
2903
+ display: inline-flex;
2904
+ align-items: flex-start;
2905
+ gap: var(--juxt-space-2-5);
2906
+ font-family: var(--juxt-font-sans);
2907
+ }
2908
+ .j-radio__control {
2909
+ position: relative;
2910
+ display: inline-flex;
2911
+ flex: none;
2912
+ margin-top: calc((var(--juxt-text-md) * var(--juxt-leading-snug) - var(--j-radio-size)) / 2);
2913
+ }
2914
+ .j-radio__input {
2915
+ position: absolute;
2916
+ inset: -4px;
2917
+ z-index: 1;
2918
+ width: calc(100% + 8px);
2919
+ height: calc(100% + 8px);
2920
+ margin: 0;
2921
+ opacity: 0;
2922
+ cursor: pointer;
2923
+ }
2924
+ .j-radio__input:disabled {
2925
+ cursor: not-allowed;
2926
+ }
2927
+ .j-radio__circle {
2928
+ position: relative;
2929
+ display: block;
2930
+ width: var(--j-radio-size);
2931
+ height: var(--j-radio-size);
2932
+ border: 1px solid var(--juxt-border-strong);
2933
+ border-radius: var(--juxt-radius-full);
2934
+ background: var(--juxt-surface);
2935
+ box-shadow: var(--juxt-shadow-xs);
2936
+ outline: 2px solid transparent;
2937
+ outline-offset: 0;
2938
+ transition:
2939
+ background-color var(--juxt-duration-fast) var(--juxt-ease-standard),
2940
+ border-color var(--juxt-duration-fast) var(--juxt-ease-standard),
2941
+ transform var(--juxt-duration-fast) var(--juxt-ease-out),
2942
+ outline-color var(--juxt-duration-fast) var(--juxt-ease-out),
2943
+ outline-offset var(--juxt-duration-fast) var(--juxt-ease-out);
2944
+ }
2945
+
2946
+ /* The inner dot grows out of the centre once the fill lands. */
2947
+ .j-radio__circle::after {
2948
+ content: '';
2949
+ position: absolute;
2950
+ inset: 0;
2951
+ margin: auto;
2952
+ width: 0.375rem;
2953
+ height: 0.375rem;
2954
+ border-radius: var(--juxt-radius-full);
2955
+ background: var(--juxt-accent-fg);
2956
+ opacity: 0;
2957
+ transform: scale(0.3);
2958
+ transition:
2959
+ opacity var(--juxt-duration-instant) var(--juxt-ease-standard),
2960
+ transform var(--juxt-duration-normal) var(--juxt-ease-out);
2961
+ }
2962
+ .j-radio__input:hover:not(:disabled) + .j-radio__circle {
2963
+ border-color: var(--juxt-fg-muted);
2964
+ }
2965
+ .j-radio__input:active:not(:disabled) + .j-radio__circle {
2966
+ transform: scale(0.9);
2967
+ }
2968
+ .j-radio__input:focus-visible + .j-radio__circle {
2969
+ outline-color: var(--juxt-ring);
2970
+ outline-offset: 2px;
2971
+ }
2972
+ .j-radio[data-state='checked'] .j-radio__circle {
2973
+ border-color: var(--juxt-accent);
2974
+ background: var(--juxt-accent);
2975
+ }
2976
+ .j-radio[data-state='checked'] .j-radio__input:hover:not(:disabled) + .j-radio__circle {
2977
+ border-color: var(--juxt-accent-hover);
2978
+ background: var(--juxt-accent-hover);
2979
+ }
2980
+ .j-radio[data-state='checked'] .j-radio__circle::after {
2981
+ opacity: 1;
2982
+ transform: none;
2983
+ transition-delay: 30ms;
2984
+ }
2985
+ .j-radio-group.is-invalid .j-radio:not([data-state='checked']) .j-radio__circle {
2150
2986
  border-color: var(--juxt-danger-border);
2151
2987
  }
2152
2988
  @media (prefers-reduced-motion: reduce) {
2153
- .j-radio__input:active:not(:disabled) + .j-radio__circle {
2989
+ .j-radio__input:active:not(:disabled) + .j-radio__circle {
2154
2990
  transform: none;
2155
2991
  }
2156
2992
  }
2157
- .j-radio__text {
2158
- display: flex;
2159
- flex-direction: column;
2160
- gap: var(--juxt-space-0-5);
2993
+ .j-radio__text {
2994
+ display: flex;
2995
+ flex-direction: column;
2996
+ gap: var(--juxt-space-0-5);
2161
2997
  min-width: 0;
2162
2998
  }
2163
- .j-radio__label {
2164
- color: var(--juxt-fg);
2165
- font-size: var(--juxt-text-md);
2166
- line-height: var(--juxt-leading-snug);
2167
- letter-spacing: var(--juxt-tracking-tight);
2168
- cursor: pointer;
2999
+ .j-radio__label {
3000
+ color: var(--juxt-fg);
3001
+ font-size: var(--juxt-text-md);
3002
+ line-height: var(--juxt-leading-snug);
3003
+ letter-spacing: var(--juxt-tracking-tight);
3004
+ cursor: pointer;
2169
3005
  user-select: none;
2170
3006
  }
2171
- .j-radio__description {
2172
- color: var(--juxt-fg-muted);
2173
- font-size: var(--juxt-text-sm);
3007
+ .j-radio__description {
3008
+ color: var(--juxt-fg-muted);
3009
+ font-size: var(--juxt-text-sm);
2174
3010
  line-height: var(--juxt-leading-normal);
2175
3011
  }
2176
- .j-radio.is-disabled .j-radio__circle {
2177
- opacity: 0.5;
3012
+ .j-radio.is-disabled .j-radio__circle {
3013
+ opacity: 0.5;
2178
3014
  box-shadow: none;
2179
3015
  }
2180
- .j-radio.is-disabled .j-radio__label {
2181
- color: var(--juxt-fg-muted);
3016
+ .j-radio.is-disabled .j-radio__label {
3017
+ color: var(--juxt-fg-muted);
2182
3018
  cursor: not-allowed;
2183
3019
  }
2184
- }
3020
+ }
2185
3021
 
3022
+ @layer theme, base, juxt, components, utilities;
2186
3023
  @layer juxt {
2187
- .j-radio-group {
2188
- display: flex;
2189
- flex-direction: column;
2190
- gap: var(--juxt-space-1-5);
2191
- min-width: 0;
2192
- margin: 0;
2193
- padding: 0;
2194
- border: 0;
3024
+ .j-radio-group {
3025
+ display: flex;
3026
+ flex-direction: column;
3027
+ gap: var(--juxt-space-1-5);
3028
+ min-width: 0;
3029
+ margin: 0;
3030
+ padding: 0;
3031
+ border: 0;
2195
3032
  font-family: var(--juxt-font-sans);
2196
3033
  }
2197
- .j-radio-group__legend {
2198
- display: inline-flex;
2199
- gap: var(--juxt-space-0-5);
2200
- margin-bottom: var(--juxt-space-1-5);
2201
- padding: 0;
2202
- color: var(--juxt-fg);
2203
- font-size: var(--juxt-text-sm);
2204
- font-weight: var(--juxt-weight-medium);
2205
- line-height: var(--juxt-leading-snug);
3034
+ .j-radio-group__legend {
3035
+ display: inline-flex;
3036
+ gap: var(--juxt-space-0-5);
3037
+ margin-bottom: var(--juxt-space-1-5);
3038
+ padding: 0;
3039
+ color: var(--juxt-fg);
3040
+ font-size: var(--juxt-text-sm);
3041
+ font-weight: var(--juxt-weight-medium);
3042
+ line-height: var(--juxt-leading-snug);
2206
3043
  letter-spacing: var(--juxt-tracking-tight);
2207
3044
  }
2208
- .j-radio-group__description,
2209
- .j-radio-group__error {
2210
- margin: calc(var(--juxt-space-1) * -1) 0 var(--juxt-space-1-5);
2211
- color: var(--juxt-fg-muted);
2212
- font-size: var(--juxt-text-xs);
3045
+ .j-radio-group__description,
3046
+ .j-radio-group__error {
3047
+ margin: calc(var(--juxt-space-1) * -1) 0 var(--juxt-space-1-5);
3048
+ color: var(--juxt-fg-muted);
3049
+ font-size: var(--juxt-text-xs);
2213
3050
  line-height: var(--juxt-leading-normal);
2214
3051
  }
2215
- .j-radio-group__error {
2216
- margin: var(--juxt-space-1) 0 0;
3052
+ .j-radio-group__error {
3053
+ margin: var(--juxt-space-1) 0 0;
2217
3054
  color: var(--juxt-danger-text);
2218
3055
  }
2219
- .j-radio-group__items {
3056
+ .j-radio-group__items {
2220
3057
  display: flex;
2221
3058
  }
2222
- .j-radio-group__items--vertical {
2223
- flex-direction: column;
3059
+ .j-radio-group__items--vertical {
3060
+ flex-direction: column;
2224
3061
  gap: var(--juxt-space-3);
2225
3062
  }
2226
- .j-radio-group__items--horizontal {
2227
- flex-wrap: wrap;
3063
+ .j-radio-group__items--horizontal {
3064
+ flex-wrap: wrap;
2228
3065
  gap: var(--juxt-space-3) var(--juxt-space-6);
2229
3066
  }
3067
+ }
3068
+
3069
+ @layer theme, base, juxt, components, utilities;
3070
+ @layer juxt {
3071
+ .j-rating {
3072
+ --j-rating-size: 1.25rem;
3073
+
3074
+ display: inline-flex;
3075
+ align-items: center;
3076
+ gap: var(--juxt-space-0-5);
3077
+ font-family: var(--juxt-font-sans);
3078
+ }
3079
+ .j-rating--sm {
3080
+ --j-rating-size: 1rem;
3081
+ }
3082
+ .j-rating--lg {
3083
+ --j-rating-size: 1.5rem;
3084
+ }
3085
+ .j-rating__star,
3086
+ .j-rating__button {
3087
+ position: relative;
3088
+ display: inline-flex;
3089
+ flex: none;
3090
+ width: var(--j-rating-size);
3091
+ height: var(--j-rating-size);
3092
+ padding: 0;
3093
+ border: 0;
3094
+ background: transparent;
3095
+ color: var(--juxt-fg-disabled);
3096
+ cursor: default;
3097
+ }
3098
+ .j-rating__button {
3099
+ border-radius: var(--juxt-radius-xs);
3100
+ cursor: pointer;
3101
+ transition: transform var(--juxt-duration-fast) var(--juxt-ease-out);
3102
+ }
3103
+ .j-rating__button:hover:not(:disabled) {
3104
+ transform: scale(1.1);
2230
3105
  }
3106
+ .j-rating__button:disabled {
3107
+ cursor: not-allowed;
3108
+ }
3109
+ .j-rating.is-disabled .j-rating__button {
3110
+ opacity: 0.5;
3111
+ }
3112
+ .j-rating__star-bg,
3113
+ .j-rating__star-fill > svg {
3114
+ position: absolute;
3115
+ inset: 0;
3116
+ width: 100%;
3117
+ height: 100%;
3118
+ fill: currentColor;
3119
+ stroke: none;
3120
+ }
3121
+ .j-rating__star-fill {
3122
+ position: absolute;
3123
+ inset: 0;
3124
+ overflow: hidden;
3125
+ color: var(--juxt-warning);
3126
+ transition: width var(--juxt-duration-fast) var(--juxt-ease-out);
3127
+ }
3128
+ @media (prefers-reduced-motion: reduce) {
3129
+ .j-rating__button:hover:not(:disabled) {
3130
+ transform: none;
3131
+ }
3132
+ .j-rating__star-fill {
3133
+ transition: none;
3134
+ }
3135
+ }
3136
+ }
2231
3137
 
3138
+ @layer theme, base, juxt, components, utilities;
2232
3139
  @layer juxt {
2233
3140
  .j-select__trigger {
2234
3141
  width: 100%;
@@ -2338,286 +3245,635 @@ to {
2338
3245
  font-size: var(--juxt-text-sm);
2339
3246
  text-align: center;
2340
3247
  }
2341
- }
2342
-
2343
- @layer juxt {
2344
- .j-separator {
2345
- flex: none;
2346
- background: var(--juxt-border-subtle);
3248
+ }
3249
+
3250
+ @layer theme, base, juxt, components, utilities;
3251
+ @layer juxt {
3252
+ .j-separator {
3253
+ flex: none;
3254
+ background: var(--juxt-border-subtle);
3255
+ }
3256
+ .dark .j-separator,
3257
+ [data-theme='dark'] .j-separator {
3258
+ background: var(--juxt-border);
3259
+ }
3260
+ .j-separator--horizontal {
3261
+ width: 100%;
3262
+ height: 1px;
3263
+ }
3264
+ .j-separator--vertical {
3265
+ align-self: stretch;
3266
+ width: 1px;
3267
+ min-height: 1rem;
3268
+ }
3269
+ .j-separator--labelled {
3270
+ display: flex;
3271
+ align-items: center;
3272
+ gap: var(--juxt-space-3);
3273
+ height: auto;
3274
+ background: none !important;
3275
+ color: var(--juxt-fg-muted);
3276
+ font-family: var(--juxt-font-sans);
3277
+ font-size: var(--juxt-text-xs);
3278
+ }
3279
+ .j-separator--labelled::before,
3280
+ .j-separator--labelled::after {
3281
+ content: '';
3282
+ flex: 1;
3283
+ height: 1px;
3284
+ background: var(--juxt-border-subtle);
3285
+ }
3286
+ .dark .j-separator--labelled::before,
3287
+ .dark .j-separator--labelled::after,
3288
+ [data-theme='dark'] .j-separator--labelled::before,
3289
+ [data-theme='dark'] .j-separator--labelled::after {
3290
+ background: var(--juxt-border);
3291
+ }
3292
+ .j-separator__label {
3293
+ flex: none;
3294
+ }
3295
+ }
3296
+
3297
+ @layer theme, base, juxt, components, utilities;
3298
+ @layer juxt {
3299
+ .j-sheet__overlay {
3300
+ position: fixed;
3301
+ inset: 0;
3302
+ z-index: var(--juxt-z-overlay);
3303
+ background: var(--juxt-overlay);
3304
+ }
3305
+ .j-sheet__positioner {
3306
+ position: fixed;
3307
+ inset: 0;
3308
+ z-index: var(--juxt-z-modal);
3309
+ display: flex;
3310
+ padding: var(--juxt-space-2);
3311
+ }
3312
+ .j-sheet__positioner--right {
3313
+ justify-content: flex-end;
3314
+ }
3315
+ .j-sheet__positioner--left {
3316
+ justify-content: flex-start;
3317
+ }
3318
+ .j-sheet__positioner--bottom {
3319
+ align-items: flex-end;
3320
+ padding-bottom: max(var(--juxt-space-2), env(safe-area-inset-bottom));
3321
+ }
3322
+
3323
+ /* A floating panel with a small inset from the edges | calmer than edge-to-edge. */
3324
+ .j-sheet {
3325
+ position: relative;
3326
+ display: flex;
3327
+ flex-direction: column;
3328
+ width: 100%;
3329
+ border: 1px solid var(--juxt-border);
3330
+ border-radius: var(--juxt-radius-lg);
3331
+ background: var(--juxt-surface-raised);
3332
+ box-shadow: var(--juxt-shadow-lg);
3333
+ color: var(--juxt-fg);
3334
+ font-family: var(--juxt-font-sans);
3335
+ outline: none;
3336
+ }
3337
+ .j-sheet--right,
3338
+ .j-sheet--left {
3339
+ height: 100%;
3340
+ }
3341
+ .j-sheet--right.j-sheet--sm,
3342
+ .j-sheet--left.j-sheet--sm {
3343
+ max-width: 20rem;
3344
+ }
3345
+ .j-sheet--right.j-sheet--md,
3346
+ .j-sheet--left.j-sheet--md {
3347
+ max-width: 25rem;
3348
+ }
3349
+ .j-sheet--right.j-sheet--lg,
3350
+ .j-sheet--left.j-sheet--lg {
3351
+ max-width: 35rem;
3352
+ }
3353
+ .j-sheet--bottom.j-sheet--sm {
3354
+ max-height: 20rem;
3355
+ }
3356
+ .j-sheet--bottom.j-sheet--md {
3357
+ max-height: 25rem;
3358
+ }
3359
+ .j-sheet--bottom.j-sheet--lg {
3360
+ max-height: min(35rem, calc(100dvh - var(--juxt-space-12)));
3361
+ }
3362
+ .j-sheet__header {
3363
+ display: flex;
3364
+ flex-direction: column;
3365
+ gap: var(--juxt-space-1-5);
3366
+ padding: var(--juxt-space-5) var(--juxt-space-12) var(--juxt-space-4) var(--juxt-space-5);
3367
+ border-bottom: 1px solid var(--juxt-border-subtle);
3368
+ }
3369
+ .dark .j-sheet__header,
3370
+ [data-theme='dark'] .j-sheet__header {
3371
+ border-bottom-color: var(--juxt-border);
3372
+ }
3373
+ .j-sheet__title {
3374
+ margin: 0;
3375
+ font-size: var(--juxt-text-lg);
3376
+ font-weight: var(--juxt-weight-semibold);
3377
+ line-height: var(--juxt-leading-snug);
3378
+ letter-spacing: var(--juxt-tracking-tight);
3379
+ }
3380
+ .j-sheet__description {
3381
+ margin: 0;
3382
+ color: var(--juxt-fg-secondary);
3383
+ font-size: var(--juxt-text-md);
3384
+ line-height: var(--juxt-leading-normal);
3385
+ }
3386
+ .j-sheet__body {
3387
+ flex: 1;
3388
+ min-height: 0;
3389
+ padding: var(--juxt-space-5);
3390
+ overflow-y: auto;
3391
+ overscroll-behavior: contain;
3392
+ color: var(--juxt-fg-secondary);
3393
+ font-size: var(--juxt-text-md);
3394
+ line-height: var(--juxt-leading-normal);
3395
+ }
3396
+ .j-sheet__footer {
3397
+ display: flex;
3398
+ justify-content: flex-end;
3399
+ gap: var(--juxt-space-2);
3400
+ padding: var(--juxt-space-4) var(--juxt-space-5);
3401
+ border-top: 1px solid var(--juxt-border-subtle);
3402
+ }
3403
+ .dark .j-sheet__footer,
3404
+ [data-theme='dark'] .j-sheet__footer {
3405
+ border-top-color: var(--juxt-border);
3406
+ }
3407
+ .j-sheet__close {
3408
+ position: absolute;
3409
+ top: var(--juxt-space-3);
3410
+ right: var(--juxt-space-3);
3411
+ display: grid;
3412
+ place-items: center;
3413
+ width: var(--juxt-control-sm);
3414
+ height: var(--juxt-control-sm);
3415
+ padding: 0;
3416
+ border: 0;
3417
+ border-radius: var(--juxt-radius-sm);
3418
+ background: transparent;
3419
+ color: var(--juxt-fg-muted);
3420
+ cursor: pointer;
3421
+ transition-property: background-color, color, outline-color, outline-offset;
3422
+ }
3423
+ .j-sheet__close:hover {
3424
+ background: var(--juxt-surface-hover);
3425
+ color: var(--juxt-fg);
3426
+ }
3427
+ .j-sheet__close > svg {
3428
+ width: 1rem;
3429
+ height: 1rem;
3430
+ }
3431
+ .j-sheet.is-nudging {
3432
+ animation: j-sheet-nudge 220ms var(--juxt-ease-out);
3433
+ }
3434
+ @keyframes j-sheet-nudge {
3435
+ 40% {
3436
+ transform: scale(1.006);
3437
+ }
3438
+ }
3439
+
3440
+ /* Motion: the backdrop fades; the sheet slides in from its edge. */
3441
+ .j-sheet-overlay-enter-active {
3442
+ transition: opacity var(--juxt-duration-normal) var(--juxt-ease-out);
3443
+ }
3444
+ .j-sheet-overlay-leave-active {
3445
+ transition: opacity var(--juxt-duration-fast) var(--juxt-ease-in);
2347
3446
  }
2348
- .dark .j-separator,
2349
- [data-theme='dark'] .j-separator {
2350
- background: var(--juxt-border);
3447
+ .j-sheet-overlay-enter-from,
3448
+ .j-sheet-overlay-leave-to {
3449
+ opacity: 0;
2351
3450
  }
2352
- .j-separator--horizontal {
2353
- width: 100%;
2354
- height: 1px;
3451
+ .j-sheet-enter-active .j-sheet {
3452
+ transition: transform 280ms var(--juxt-ease-out);
2355
3453
  }
2356
- .j-separator--vertical {
2357
- align-self: stretch;
2358
- width: 1px;
2359
- min-height: 1rem;
3454
+ .j-sheet-leave-active .j-sheet {
3455
+ transition: transform var(--juxt-duration-normal) var(--juxt-ease-in);
2360
3456
  }
2361
- .j-separator--labelled {
2362
- display: flex;
2363
- align-items: center;
2364
- gap: var(--juxt-space-3);
2365
- height: auto;
2366
- background: none !important;
2367
- color: var(--juxt-fg-muted);
2368
- font-family: var(--juxt-font-sans);
2369
- font-size: var(--juxt-text-xs);
3457
+ .j-sheet-enter-from .j-sheet--right,
3458
+ .j-sheet-leave-to .j-sheet--right {
3459
+ transform: translateX(calc(100% + var(--juxt-space-4)));
2370
3460
  }
2371
- .j-separator--labelled::before,
2372
- .j-separator--labelled::after {
2373
- content: '';
2374
- flex: 1;
2375
- height: 1px;
2376
- background: var(--juxt-border-subtle);
3461
+ .j-sheet-enter-from .j-sheet--left,
3462
+ .j-sheet-leave-to .j-sheet--left {
3463
+ transform: translateX(calc(-100% - var(--juxt-space-4)));
2377
3464
  }
2378
- .dark .j-separator--labelled::before,
2379
- .dark .j-separator--labelled::after,
2380
- [data-theme='dark'] .j-separator--labelled::before,
2381
- [data-theme='dark'] .j-separator--labelled::after {
2382
- background: var(--juxt-border);
3465
+ .j-sheet-enter-from .j-sheet--bottom,
3466
+ .j-sheet-leave-to .j-sheet--bottom {
3467
+ transform: translateY(calc(100% + var(--juxt-space-4)));
3468
+ }
3469
+
3470
+ /* Reduced motion: the sheet fades in place instead of travelling. */
3471
+ @media (prefers-reduced-motion: reduce) {
3472
+ .j-sheet-enter-active .j-sheet,
3473
+ .j-sheet-leave-active .j-sheet {
3474
+ transition: opacity var(--juxt-duration-normal) var(--juxt-ease-standard);
2383
3475
  }
2384
- .j-separator__label {
2385
- flex: none;
3476
+ .j-sheet-enter-from .j-sheet,
3477
+ .j-sheet-leave-to .j-sheet {
3478
+ opacity: 0;
3479
+ transform: none !important;
2386
3480
  }
2387
3481
  }
3482
+ }
2388
3483
 
3484
+ @layer theme, base, juxt, components, utilities;
2389
3485
  @layer juxt {
2390
- .j-sheet__overlay {
2391
- position: fixed;
2392
- inset: 0;
2393
- z-index: var(--juxt-z-overlay);
2394
- background: var(--juxt-overlay);
3486
+ .j-sidebar {
3487
+ display: flex;
3488
+ flex-direction: column;
3489
+ width: 100%;
3490
+ height: 100%;
3491
+ min-height: 0;
3492
+ color: var(--juxt-fg);
3493
+ font-family: var(--juxt-font-sans);
3494
+ }
3495
+ .j-sidebar__header {
3496
+ display: flex;
3497
+ align-items: center;
3498
+ gap: var(--juxt-space-2);
3499
+ padding: var(--juxt-space-3) var(--juxt-space-3) var(--juxt-space-2);
2395
3500
  }
2396
- .j-sheet__positioner {
2397
- position: fixed;
2398
- inset: 0;
2399
- z-index: var(--juxt-z-modal);
3501
+ .j-sidebar__nav {
2400
3502
  display: flex;
3503
+ flex: 1;
3504
+ flex-direction: column;
3505
+ gap: var(--juxt-space-4);
3506
+ min-height: 0;
2401
3507
  padding: var(--juxt-space-2);
3508
+ overflow-y: auto;
3509
+ overscroll-behavior: contain;
2402
3510
  }
2403
- .j-sheet__positioner--right {
2404
- justify-content: flex-end;
3511
+ .j-sidebar__footer {
3512
+ display: flex;
3513
+ flex-direction: column;
3514
+ gap: var(--juxt-space-0-5);
3515
+ padding: var(--juxt-space-2);
3516
+ border-top: 1px solid var(--juxt-border-subtle);
2405
3517
  }
2406
- .j-sheet__positioner--left {
2407
- justify-content: flex-start;
3518
+ .dark .j-sidebar__footer,
3519
+ [data-theme='dark'] .j-sidebar__footer {
3520
+ border-top-color: var(--juxt-border);
2408
3521
  }
2409
- .j-sheet__positioner--bottom {
2410
- align-items: flex-end;
2411
- padding-bottom: max(var(--juxt-space-2), env(safe-area-inset-bottom));
2412
3522
  }
2413
3523
 
2414
- /* A floating panel with a small inset from the edges — calmer than edge-to-edge. */
2415
- .j-sheet {
2416
- position: relative;
3524
+ @layer theme, base, juxt, components, utilities;
3525
+ @layer juxt {
3526
+ .j-sidebar-group {
2417
3527
  display: flex;
2418
3528
  flex-direction: column;
3529
+ gap: var(--juxt-space-0-5);
3530
+ }
3531
+ .j-sidebar-group__title {
3532
+ display: flex;
3533
+ align-items: center;
3534
+ justify-content: space-between;
3535
+ gap: var(--juxt-space-2);
3536
+ margin: 0;
3537
+ padding: var(--juxt-space-1) var(--juxt-space-2);
3538
+ color: var(--juxt-fg-muted);
3539
+ font-size: var(--juxt-text-xs);
3540
+ font-weight: var(--juxt-weight-medium);
3541
+ line-height: var(--juxt-leading-snug);
3542
+ }
3543
+ .j-sidebar-group__toggle {
2419
3544
  width: 100%;
2420
- border: 1px solid var(--juxt-border);
2421
- border-radius: var(--juxt-radius-lg);
2422
- background: var(--juxt-surface-raised);
2423
- box-shadow: var(--juxt-shadow-lg);
2424
- color: var(--juxt-fg);
2425
- font-family: var(--juxt-font-sans);
2426
- outline: none;
3545
+ border: 0;
3546
+ border-radius: var(--juxt-radius-xs);
3547
+ background: transparent;
3548
+ font-family: inherit;
3549
+ text-align: left;
3550
+ cursor: pointer;
3551
+ transition-property: color, outline-color, outline-offset;
2427
3552
  }
2428
- .j-sheet--right,
2429
- .j-sheet--left {
2430
- height: 100%;
3553
+ .j-sidebar-group__toggle:hover {
3554
+ color: var(--juxt-fg-secondary);
2431
3555
  }
2432
- .j-sheet--right.j-sheet--sm,
2433
- .j-sheet--left.j-sheet--sm {
2434
- max-width: 20rem;
3556
+ .j-sidebar-group__chevron {
3557
+ flex: none;
3558
+ width: 0.75rem;
3559
+ height: 0.75rem;
3560
+ opacity: 0;
3561
+ transform: rotate(-90deg);
3562
+ transition:
3563
+ transform var(--juxt-duration-normal) var(--juxt-ease-out),
3564
+ opacity var(--juxt-duration-fast) var(--juxt-ease-standard);
2435
3565
  }
2436
- .j-sheet--right.j-sheet--md,
2437
- .j-sheet--left.j-sheet--md {
2438
- max-width: 25rem;
3566
+
3567
+ /* The chevron only appears on hover or focus, or while the group is folded. */
3568
+ .j-sidebar-group__toggle:hover .j-sidebar-group__chevron,
3569
+ .j-sidebar-group__toggle:focus-visible .j-sidebar-group__chevron,
3570
+ .j-sidebar-group[data-state='closed'] .j-sidebar-group__chevron {
3571
+ opacity: 1;
2439
3572
  }
2440
- .j-sheet--right.j-sheet--lg,
2441
- .j-sheet--left.j-sheet--lg {
2442
- max-width: 35rem;
3573
+ .j-sidebar-group[data-state='open'] .j-sidebar-group__chevron {
3574
+ transform: none;
2443
3575
  }
2444
- .j-sheet--bottom.j-sheet--sm {
2445
- max-height: 20rem;
3576
+ .j-sidebar-group__panel {
3577
+ display: grid;
3578
+ grid-template-rows: 1fr;
3579
+ transition: grid-template-rows var(--juxt-duration-normal) var(--juxt-ease-out);
2446
3580
  }
2447
- .j-sheet--bottom.j-sheet--md {
2448
- max-height: 25rem;
3581
+ .j-sidebar-group[data-state='closed'] .j-sidebar-group__panel {
3582
+ grid-template-rows: 0fr;
2449
3583
  }
2450
- .j-sheet--bottom.j-sheet--lg {
2451
- max-height: min(35rem, calc(100dvh - var(--juxt-space-12)));
3584
+ .j-sidebar-group__panel-inner {
3585
+ min-height: 0;
3586
+ overflow: hidden;
2452
3587
  }
2453
- .j-sheet__header {
3588
+ .j-sidebar-group__items {
2454
3589
  display: flex;
2455
3590
  flex-direction: column;
2456
- gap: var(--juxt-space-1-5);
2457
- padding: var(--juxt-space-5) var(--juxt-space-12) var(--juxt-space-4) var(--juxt-space-5);
2458
- border-bottom: 1px solid var(--juxt-border-subtle);
2459
- }
2460
- .dark .j-sheet__header,
2461
- [data-theme='dark'] .j-sheet__header {
2462
- border-bottom-color: var(--juxt-border);
3591
+ gap: var(--juxt-space-0-5);
2463
3592
  }
2464
- .j-sheet__title {
2465
- margin: 0;
2466
- font-size: var(--juxt-text-lg);
2467
- font-weight: var(--juxt-weight-semibold);
2468
- line-height: var(--juxt-leading-snug);
2469
- letter-spacing: var(--juxt-tracking-tight);
3593
+ @media (prefers-reduced-motion: reduce) {
3594
+ .j-sidebar-group__panel,
3595
+ .j-sidebar-group__chevron {
3596
+ transition: none;
2470
3597
  }
2471
- .j-sheet__description {
2472
- margin: 0;
2473
- color: var(--juxt-fg-secondary);
2474
- font-size: var(--juxt-text-md);
2475
- line-height: var(--juxt-leading-normal);
2476
3598
  }
2477
- .j-sheet__body {
2478
- flex: 1;
2479
- min-height: 0;
2480
- padding: var(--juxt-space-5);
2481
- overflow-y: auto;
2482
- overscroll-behavior: contain;
2483
- color: var(--juxt-fg-secondary);
2484
- font-size: var(--juxt-text-md);
2485
- line-height: var(--juxt-leading-normal);
2486
3599
  }
2487
- .j-sheet__footer {
3600
+
3601
+ @layer theme, base, juxt, components, utilities;
3602
+ @layer juxt {
3603
+ .j-sidebar-item {
3604
+ position: relative;
2488
3605
  display: flex;
2489
- justify-content: flex-end;
3606
+ align-items: center;
2490
3607
  gap: var(--juxt-space-2);
2491
- padding: var(--juxt-space-4) var(--juxt-space-5);
2492
- border-top: 1px solid var(--juxt-border-subtle);
3608
+ min-height: var(--juxt-control-sm);
3609
+ padding: 0 var(--juxt-space-2);
3610
+ border-radius: var(--juxt-radius-sm);
3611
+ color: var(--juxt-fg-secondary);
3612
+ font-size: var(--juxt-text-sm);
3613
+ letter-spacing: var(--juxt-tracking-tight);
3614
+ text-decoration: none;
3615
+ cursor: pointer;
3616
+ -webkit-tap-highlight-color: transparent;
3617
+ transition-property: color, background-color, outline-color, outline-offset;
2493
3618
  }
2494
- .dark .j-sheet__footer,
2495
- [data-theme='dark'] .j-sheet__footer {
2496
- border-top-color: var(--juxt-border);
3619
+ .j-sidebar-item:hover:not(.is-disabled) {
3620
+ background: var(--juxt-surface-hover);
3621
+ color: var(--juxt-fg);
3622
+ }
3623
+ .j-sidebar-item.is-active {
3624
+ background: var(--juxt-surface-hover);
3625
+ color: var(--juxt-fg);
3626
+ font-weight: var(--juxt-weight-medium);
2497
3627
  }
2498
- .j-sheet__close {
3628
+
3629
+ /* Same marker as the command palette: a short accent line where you are. */
3630
+ .j-sidebar-item.is-active::before {
3631
+ content: '';
2499
3632
  position: absolute;
2500
- top: var(--juxt-space-3);
2501
- right: var(--juxt-space-3);
2502
- display: grid;
2503
- place-items: center;
2504
- width: var(--juxt-control-sm);
2505
- height: var(--juxt-control-sm);
2506
- padding: 0;
2507
- border: 0;
2508
- border-radius: var(--juxt-radius-sm);
2509
- background: transparent;
3633
+ top: 0.4375rem;
3634
+ bottom: 0.4375rem;
3635
+ left: 0;
3636
+ width: 2px;
3637
+ border-radius: 0 2px 2px 0;
3638
+ background: var(--juxt-accent);
3639
+ }
3640
+ .j-sidebar-item.is-disabled {
3641
+ color: var(--juxt-fg-disabled);
3642
+ cursor: not-allowed;
3643
+ }
3644
+ .j-sidebar-item__icon {
3645
+ display: inline-flex;
3646
+ flex: none;
2510
3647
  color: var(--juxt-fg-muted);
2511
- cursor: pointer;
2512
- transition-property: background-color, color, outline-color, outline-offset;
2513
3648
  }
2514
- .j-sheet__close:hover {
2515
- background: var(--juxt-surface-hover);
3649
+ .j-sidebar-item.is-active .j-sidebar-item__icon,
3650
+ .j-sidebar-item:hover:not(.is-disabled) .j-sidebar-item__icon {
2516
3651
  color: var(--juxt-fg);
2517
3652
  }
2518
- .j-sheet__close > svg {
3653
+ .j-sidebar-item__icon > svg {
2519
3654
  width: 1rem;
2520
3655
  height: 1rem;
2521
3656
  }
2522
- .j-sheet.is-nudging {
2523
- animation: j-sheet-nudge 220ms var(--juxt-ease-out);
3657
+ .j-sidebar-item__label {
3658
+ flex: 1;
3659
+ min-width: 0;
3660
+ overflow: hidden;
3661
+ text-overflow: ellipsis;
3662
+ white-space: nowrap;
2524
3663
  }
2525
- @keyframes j-sheet-nudge {
2526
- 40% {
2527
- transform: scale(1.006);
3664
+ .j-sidebar-item__trailing {
3665
+ display: inline-flex;
3666
+ flex: none;
3667
+ align-items: center;
3668
+ color: var(--juxt-fg-muted);
3669
+ font-size: var(--juxt-text-xs);
3670
+ font-variant-numeric: tabular-nums;
2528
3671
  }
2529
3672
  }
2530
3673
 
2531
- /* Motion: the backdrop fades; the sheet slides in from its edge. */
2532
- .j-sheet-overlay-enter-active {
2533
- transition: opacity var(--juxt-duration-normal) var(--juxt-ease-out);
2534
- }
2535
- .j-sheet-overlay-leave-active {
2536
- transition: opacity var(--juxt-duration-fast) var(--juxt-ease-in);
3674
+ @layer theme, base, juxt, components, utilities;
3675
+ @layer juxt {
3676
+ .j-skeleton {
3677
+ display: block;
3678
+ width: 100%;
3679
+ height: 1rem;
3680
+ border-radius: var(--juxt-radius-sm);
3681
+ background: var(--juxt-surface-active);
3682
+ animation: j-skeleton-pulse 1.8s var(--juxt-ease-standard) infinite;
2537
3683
  }
2538
- .j-sheet-overlay-enter-from,
2539
- .j-sheet-overlay-leave-to {
2540
- opacity: 0;
3684
+ .j-skeleton--circle {
3685
+ width: 2rem;
3686
+ height: 2rem;
3687
+ border-radius: var(--juxt-radius-full);
2541
3688
  }
2542
- .j-sheet-enter-active .j-sheet {
2543
- transition: transform 280ms var(--juxt-ease-out);
3689
+ .j-skeleton--text {
3690
+ height: 0.75rem;
3691
+ border-radius: var(--juxt-radius-xs);
2544
3692
  }
2545
- .j-sheet-leave-active .j-sheet {
2546
- transition: transform var(--juxt-duration-normal) var(--juxt-ease-in);
3693
+ .j-skeleton-lines {
3694
+ display: flex;
3695
+ flex-direction: column;
3696
+ gap: var(--juxt-space-2);
3697
+ width: 100%;
3698
+ }
3699
+
3700
+ /* A slow breath, not a shimmer | loading shouldn't compete for attention. */
3701
+ @keyframes j-skeleton-pulse {
3702
+ 50% {
3703
+ opacity: 0.5;
2547
3704
  }
2548
- .j-sheet-enter-from .j-sheet--right,
2549
- .j-sheet-leave-to .j-sheet--right {
2550
- transform: translateX(calc(100% + var(--juxt-space-4)));
2551
3705
  }
2552
- .j-sheet-enter-from .j-sheet--left,
2553
- .j-sheet-leave-to .j-sheet--left {
2554
- transform: translateX(calc(-100% - var(--juxt-space-4)));
3706
+ @media (prefers-reduced-motion: reduce) {
3707
+ .j-skeleton {
3708
+ animation: none;
2555
3709
  }
2556
- .j-sheet-enter-from .j-sheet--bottom,
2557
- .j-sheet-leave-to .j-sheet--bottom {
2558
- transform: translateY(calc(100% + var(--juxt-space-4)));
2559
3710
  }
3711
+ }
2560
3712
 
2561
- /* Reduced motion: the sheet fades in place instead of travelling. */
2562
- @media (prefers-reduced-motion: reduce) {
2563
- .j-sheet-enter-active .j-sheet,
2564
- .j-sheet-leave-active .j-sheet {
2565
- transition: opacity var(--juxt-duration-normal) var(--juxt-ease-standard);
3713
+ @layer theme, base, juxt, components, utilities;
3714
+ @layer juxt {
3715
+ .j-slider {
3716
+ --j-slider-track: 0.25rem;
3717
+ --j-slider-thumb: 1rem;
3718
+
3719
+ display: flex;
3720
+ align-items: center;
3721
+ width: 100%;
3722
+ padding: calc(var(--j-slider-thumb) / 2) 0;
3723
+ font-family: var(--juxt-font-sans);
3724
+ touch-action: none;
3725
+ }
3726
+ .j-slider--sm {
3727
+ --j-slider-track: 0.1875rem;
3728
+ --j-slider-thumb: 0.875rem;
3729
+ }
3730
+ .j-slider__track {
3731
+ position: relative;
3732
+ width: 100%;
3733
+ height: var(--j-slider-track);
3734
+ border-radius: var(--juxt-radius-full);
3735
+ background: var(--juxt-surface-active);
3736
+ cursor: pointer;
3737
+ }
3738
+ .j-slider.is-disabled .j-slider__track {
3739
+ cursor: not-allowed;
3740
+ opacity: 0.5;
3741
+ }
3742
+ .j-slider__range {
3743
+ position: absolute;
3744
+ top: 0;
3745
+ bottom: 0;
3746
+ border-radius: var(--juxt-radius-full);
3747
+ background: var(--juxt-accent);
3748
+ }
3749
+ .j-slider__thumb {
3750
+ position: absolute;
3751
+ top: 50%;
3752
+ width: var(--j-slider-thumb);
3753
+ height: var(--j-slider-thumb);
3754
+ border-radius: var(--juxt-radius-full);
3755
+ background: var(--juxt-surface);
3756
+ box-shadow: 0 0 0 1px var(--juxt-border-strong), var(--juxt-shadow-sm);
3757
+ cursor: grab;
3758
+ transform: translate(-50%, -50%);
3759
+ transition:
3760
+ box-shadow var(--juxt-duration-fast) var(--juxt-ease-out),
3761
+ left var(--juxt-duration-fast) var(--juxt-ease-out);
3762
+ }
3763
+ .j-slider__thumb.is-dragging {
3764
+ cursor: grabbing;
3765
+ transition: none;
3766
+ }
3767
+ .j-slider__thumb:hover {
3768
+ box-shadow: 0 0 0 1px var(--juxt-accent), var(--juxt-shadow-sm);
3769
+ }
3770
+ .j-slider__thumb:focus-visible {
3771
+ outline-color: var(--juxt-ring);
3772
+ outline-offset: 3px;
3773
+ }
3774
+ .j-slider.is-disabled .j-slider__thumb {
3775
+ cursor: not-allowed;
3776
+ }
3777
+ .j-slider__bubble {
3778
+ position: absolute;
3779
+ bottom: calc(100% + var(--juxt-space-2));
3780
+ left: 50%;
3781
+ padding: var(--juxt-space-0-5) var(--juxt-space-1-5);
3782
+ border-radius: var(--juxt-radius-xs);
3783
+ background: var(--juxt-tooltip-bg);
3784
+ color: var(--juxt-tooltip-fg);
3785
+ font-size: var(--juxt-text-2xs);
3786
+ font-weight: var(--juxt-weight-medium);
3787
+ font-variant-numeric: tabular-nums;
3788
+ white-space: nowrap;
3789
+ pointer-events: none;
3790
+ transform: translateX(-50%);
2566
3791
  }
2567
- .j-sheet-enter-from .j-sheet,
2568
- .j-sheet-leave-to .j-sheet {
2569
- opacity: 0;
2570
- transform: none !important;
3792
+ @media (prefers-reduced-motion: reduce) {
3793
+ .j-slider__thumb {
3794
+ transition: none;
2571
3795
  }
2572
3796
  }
3797
+ }
3798
+
3799
+ @layer theme, base, juxt, components, utilities;
3800
+ @layer juxt {
3801
+ .j-spinner-wrap {
3802
+ display: inline-flex;
3803
+ color: var(--juxt-fg-muted);
3804
+ vertical-align: middle;
2573
3805
  }
3806
+ }
2574
3807
 
3808
+ @layer theme, base, juxt, components, utilities;
2575
3809
  @layer juxt {
2576
- .j-skeleton {
2577
- display: block;
2578
- width: 100%;
2579
- height: 1rem;
2580
- border-radius: var(--juxt-radius-sm);
2581
- background: var(--juxt-surface-active);
2582
- animation: j-skeleton-pulse 1.8s var(--juxt-ease-standard) infinite;
3810
+ .j-stat {
3811
+ display: flex;
3812
+ flex-direction: column;
3813
+ gap: var(--juxt-space-1-5);
3814
+ font-family: var(--juxt-font-sans);
2583
3815
  }
2584
- .j-skeleton--circle {
2585
- width: 2rem;
2586
- height: 2rem;
2587
- border-radius: var(--juxt-radius-full);
3816
+ .j-stat__header {
3817
+ display: flex;
3818
+ align-items: center;
3819
+ gap: var(--juxt-space-1-5);
2588
3820
  }
2589
- .j-skeleton--text {
2590
- height: 0.75rem;
2591
- border-radius: var(--juxt-radius-xs);
3821
+ .j-stat__icon {
3822
+ display: grid;
3823
+ place-items: center;
3824
+ color: var(--juxt-fg-muted);
2592
3825
  }
2593
- .j-skeleton-lines {
2594
- display: flex;
2595
- flex-direction: column;
2596
- gap: var(--juxt-space-2);
2597
- width: 100%;
3826
+ .j-stat__icon > svg {
3827
+ width: 0.875rem;
3828
+ height: 0.875rem;
2598
3829
  }
2599
-
2600
- /* A slow breath, not a shimmer — loading shouldn't compete for attention. */
2601
- @keyframes j-skeleton-pulse {
2602
- 50% {
2603
- opacity: 0.5;
3830
+ .j-stat__label {
3831
+ color: var(--juxt-fg-muted);
3832
+ font-size: var(--juxt-text-sm);
3833
+ font-weight: var(--juxt-weight-medium);
3834
+ letter-spacing: var(--juxt-tracking-tight);
2604
3835
  }
3836
+ .j-stat__row {
3837
+ display: flex;
3838
+ align-items: baseline;
3839
+ gap: var(--juxt-space-2);
2605
3840
  }
2606
- @media (prefers-reduced-motion: reduce) {
2607
- .j-skeleton {
2608
- animation: none;
3841
+ .j-stat__value {
3842
+ color: var(--juxt-fg);
3843
+ font-size: var(--juxt-text-3xl);
3844
+ font-weight: var(--juxt-weight-semibold);
3845
+ line-height: var(--juxt-leading-tight);
3846
+ letter-spacing: var(--juxt-tracking-tighter);
3847
+ font-variant-numeric: tabular-nums;
2609
3848
  }
3849
+ .j-stat__delta {
3850
+ display: inline-flex;
3851
+ align-items: center;
3852
+ gap: 0.125rem;
3853
+ color: var(--juxt-fg-muted);
3854
+ font-size: var(--juxt-text-sm);
3855
+ font-weight: var(--juxt-weight-medium);
3856
+ font-variant-numeric: tabular-nums;
2610
3857
  }
3858
+ .j-stat__delta > svg {
3859
+ width: 0.875rem;
3860
+ height: 0.875rem;
2611
3861
  }
2612
-
2613
- @layer juxt {
2614
- .j-spinner-wrap {
2615
- display: inline-flex;
2616
- color: var(--juxt-fg-muted);
2617
- vertical-align: middle;
3862
+ .j-stat__delta--up {
3863
+ color: var(--juxt-success-text);
3864
+ }
3865
+ .j-stat__delta--down {
3866
+ color: var(--juxt-danger-text);
2618
3867
  }
3868
+ .j-stat__description {
3869
+ margin: 0;
3870
+ color: var(--juxt-fg-muted);
3871
+ font-size: var(--juxt-text-xs);
3872
+ line-height: var(--juxt-leading-normal);
2619
3873
  }
3874
+ }
2620
3875
 
3876
+ @layer theme, base, juxt, components, utilities;
2621
3877
  @layer juxt {
2622
3878
  .j-switch {
2623
3879
  --j-switch-w: 2rem;
@@ -2728,6 +3984,7 @@ to {
2728
3984
  }
2729
3985
  }
2730
3986
 
3987
+ @layer theme, base, juxt, components, utilities;
2731
3988
  @layer juxt {
2732
3989
  .j-tabs {
2733
3990
  --j-tab-height: var(--juxt-control-md);
@@ -2882,6 +4139,110 @@ from {
2882
4139
  }
2883
4140
  }
2884
4141
 
4142
+ @layer theme, base, juxt, components, utilities;
4143
+ @layer juxt {
4144
+ /*
4145
+ * Tags are pills, not stamps | fully rounded and carrying their own remove
4146
+ * affordance, which is what sets them apart from the static JBadge.
4147
+ */
4148
+ .j-tag {
4149
+ --j-tag-fg: var(--juxt-fg-secondary);
4150
+ --j-tag-bg: var(--juxt-surface-active);
4151
+
4152
+ display: inline-flex;
4153
+ flex: none;
4154
+ align-items: center;
4155
+ gap: 0.3125rem;
4156
+ height: 1.375rem;
4157
+ padding: 0 var(--juxt-space-1) 0 var(--juxt-space-2-5);
4158
+ border-radius: var(--juxt-radius-full);
4159
+ background: var(--j-tag-bg);
4160
+ color: var(--j-tag-fg);
4161
+ font-family: var(--juxt-font-sans);
4162
+ font-size: var(--juxt-text-xs);
4163
+ font-weight: var(--juxt-weight-medium);
4164
+ line-height: 1;
4165
+ white-space: nowrap;
4166
+ }
4167
+ .j-tag--sm {
4168
+ height: 1.125rem;
4169
+ padding: 0 0.1875rem 0 var(--juxt-space-2);
4170
+ font-size: var(--juxt-text-2xs);
4171
+ }
4172
+ .j-tag--success {
4173
+ --j-tag-fg: var(--juxt-success-text);
4174
+ --j-tag-bg: var(--juxt-success-soft);
4175
+ }
4176
+ .j-tag--warning {
4177
+ --j-tag-fg: var(--juxt-warning-text);
4178
+ --j-tag-bg: var(--juxt-warning-soft);
4179
+ }
4180
+ .j-tag--destructive {
4181
+ --j-tag-fg: var(--juxt-danger-text);
4182
+ --j-tag-bg: var(--juxt-danger-soft);
4183
+ }
4184
+ .j-tag--accent {
4185
+ --j-tag-fg: var(--juxt-accent-fg);
4186
+ --j-tag-bg: var(--juxt-accent-strong);
4187
+ }
4188
+ .j-tag__icon {
4189
+ display: inline-flex;
4190
+ margin-left: -0.0625rem;
4191
+ }
4192
+ .j-tag__icon > svg {
4193
+ width: 0.75rem;
4194
+ height: 0.75rem;
4195
+ }
4196
+ .j-tag__label {
4197
+ overflow: hidden;
4198
+ text-overflow: ellipsis;
4199
+ }
4200
+ .j-tag__remove {
4201
+ display: grid;
4202
+ flex: none;
4203
+ place-items: center;
4204
+ width: 1.125rem;
4205
+ height: 1.125rem;
4206
+ padding: 0;
4207
+ border: 0;
4208
+ border-radius: var(--juxt-radius-full);
4209
+ background: transparent;
4210
+ color: inherit;
4211
+ cursor: pointer;
4212
+ opacity: 0.7;
4213
+ transition:
4214
+ background-color var(--juxt-duration-fast) var(--juxt-ease-standard),
4215
+ opacity var(--juxt-duration-fast) var(--juxt-ease-standard);
4216
+ }
4217
+ .j-tag--sm .j-tag__remove {
4218
+ width: 0.875rem;
4219
+ height: 0.875rem;
4220
+ }
4221
+ .j-tag__remove:hover:not(:disabled) {
4222
+ background: rgb(0 0 0 / 0.08);
4223
+ opacity: 1;
4224
+ }
4225
+ .dark .j-tag__remove:hover:not(:disabled),
4226
+ [data-theme='dark'] .j-tag__remove:hover:not(:disabled) {
4227
+ background: rgb(255 255 255 / 0.12);
4228
+ }
4229
+ .j-tag__remove > svg {
4230
+ width: 0.625rem;
4231
+ height: 0.625rem;
4232
+ }
4233
+ .j-tag--sm .j-tag__remove > svg {
4234
+ width: 0.5rem;
4235
+ height: 0.5rem;
4236
+ }
4237
+ .j-tag.is-disabled {
4238
+ opacity: 0.5;
4239
+ }
4240
+ .j-tag__remove:disabled {
4241
+ cursor: not-allowed;
4242
+ }
4243
+ }
4244
+
4245
+ @layer theme, base, juxt, components, utilities;
2885
4246
  @layer juxt {
2886
4247
  .j-textarea {
2887
4248
  align-items: stretch;
@@ -2917,6 +4278,102 @@ from {
2917
4278
  }
2918
4279
  }
2919
4280
 
4281
+ @layer theme, base, juxt, components, utilities;
4282
+ @layer juxt {
4283
+ .j-timeline {
4284
+ display: flex;
4285
+ flex-direction: column;
4286
+ margin: 0;
4287
+ padding: 0;
4288
+ list-style: none;
4289
+ font-family: var(--juxt-font-sans);
4290
+ }
4291
+ }
4292
+
4293
+ @layer theme, base, juxt, components, utilities;
4294
+ @layer juxt {
4295
+ .j-timeline-item {
4296
+ position: relative;
4297
+ display: flex;
4298
+ gap: var(--juxt-space-3);
4299
+ padding-bottom: var(--juxt-space-5);
4300
+ }
4301
+ .j-timeline-item:last-child {
4302
+ padding-bottom: 0;
4303
+ }
4304
+ .j-timeline-item__rail {
4305
+ position: relative;
4306
+ display: flex;
4307
+ flex: none;
4308
+ justify-content: center;
4309
+ width: 1rem;
4310
+ }
4311
+ .j-timeline-item__rail::before {
4312
+ content: '';
4313
+ position: absolute;
4314
+ top: 1rem;
4315
+ bottom: calc(var(--juxt-space-5) * -1);
4316
+ width: 1px;
4317
+ background: var(--juxt-border);
4318
+ }
4319
+ .j-timeline-item:last-child .j-timeline-item__rail::before {
4320
+ display: none;
4321
+ }
4322
+ .j-timeline-item__marker {
4323
+ z-index: 1;
4324
+ display: grid;
4325
+ place-items: center;
4326
+ width: 0.625rem;
4327
+ height: 0.625rem;
4328
+ margin-top: 0.25rem;
4329
+ border: 2px solid var(--juxt-surface);
4330
+ border-radius: var(--juxt-radius-full);
4331
+ background: var(--juxt-fg-disabled);
4332
+ box-shadow: 0 0 0 1px var(--juxt-border);
4333
+ }
4334
+ .j-timeline-item--complete .j-timeline-item__marker {
4335
+ background: var(--juxt-accent);
4336
+ box-shadow: none;
4337
+ }
4338
+ .j-timeline-item--current .j-timeline-item__marker {
4339
+ background: var(--juxt-surface);
4340
+ box-shadow: 0 0 0 2px var(--juxt-accent);
4341
+ }
4342
+ .j-timeline-item__content {
4343
+ flex: 1;
4344
+ min-width: 0;
4345
+ padding-bottom: var(--juxt-space-0-5);
4346
+ }
4347
+ .j-timeline-item__header {
4348
+ display: flex;
4349
+ flex-wrap: wrap;
4350
+ align-items: baseline;
4351
+ gap: var(--juxt-space-2);
4352
+ }
4353
+ .j-timeline-item__title {
4354
+ margin: 0;
4355
+ color: var(--juxt-fg);
4356
+ font-size: var(--juxt-text-md);
4357
+ font-weight: var(--juxt-weight-medium);
4358
+ letter-spacing: var(--juxt-tracking-tight);
4359
+ }
4360
+ .j-timeline-item--upcoming .j-timeline-item__title {
4361
+ color: var(--juxt-fg-muted);
4362
+ }
4363
+ .j-timeline-item__time {
4364
+ color: var(--juxt-fg-muted);
4365
+ font-size: var(--juxt-text-xs);
4366
+ font-variant-numeric: tabular-nums;
4367
+ }
4368
+ .j-timeline-item__body {
4369
+ margin-top: var(--juxt-space-0-5);
4370
+ color: var(--juxt-fg-secondary);
4371
+ font-size: var(--juxt-text-sm);
4372
+ line-height: var(--juxt-leading-normal);
4373
+ }
4374
+ }
4375
+
4376
+ @layer theme, base, juxt, components, utilities;
2920
4377
  @layer juxt {
2921
4378
  .j-toaster {
2922
4379
  --j-toast-width: 22.5rem;
@@ -3171,6 +4628,78 @@ to {
3171
4628
  }
3172
4629
  }
3173
4630
 
4631
+ @layer theme, base, juxt, components, utilities;
4632
+ @layer juxt {
4633
+ .j-toggle-group {
4634
+ --j-toggle-height: var(--juxt-control-md);
4635
+
4636
+ display: inline-flex;
4637
+ align-items: center;
4638
+ gap: 2px;
4639
+ padding: 2px;
4640
+ border-radius: var(--juxt-radius-md);
4641
+ background: var(--juxt-surface-sunken);
4642
+ box-shadow: inset 0 0 0 1px var(--juxt-border-subtle);
4643
+ font-family: var(--juxt-font-sans);
4644
+ }
4645
+ .j-toggle-group--sm {
4646
+ --j-toggle-height: var(--juxt-control-sm);
4647
+ }
4648
+ .j-toggle-group.is-disabled {
4649
+ opacity: 0.6;
4650
+ }
4651
+ }
4652
+
4653
+ @layer theme, base, juxt, components, utilities;
4654
+ @layer juxt {
4655
+ .j-toggle-group__item {
4656
+ display: inline-flex;
4657
+ align-items: center;
4658
+ justify-content: center;
4659
+ gap: var(--juxt-space-1-5);
4660
+ height: var(--j-toggle-height, var(--juxt-control-md));
4661
+ padding: 0 var(--juxt-space-3);
4662
+ border: 0;
4663
+ border-radius: var(--juxt-radius-sm);
4664
+ background: transparent;
4665
+ color: var(--juxt-fg-secondary);
4666
+ font: inherit;
4667
+ font-size: var(--juxt-text-sm);
4668
+ font-weight: var(--juxt-weight-medium);
4669
+ letter-spacing: var(--juxt-tracking-tight);
4670
+ white-space: nowrap;
4671
+ cursor: pointer;
4672
+ outline: 2px solid transparent;
4673
+ outline-offset: 0;
4674
+ -webkit-tap-highlight-color: transparent;
4675
+ transition:
4676
+ background-color var(--juxt-duration-fast) var(--juxt-ease-standard),
4677
+ color var(--juxt-duration-fast) var(--juxt-ease-standard),
4678
+ box-shadow var(--juxt-duration-fast) var(--juxt-ease-standard);
4679
+ }
4680
+ .j-toggle-group__item > svg {
4681
+ width: 1rem;
4682
+ height: 1rem;
4683
+ }
4684
+ .j-toggle-group__item:hover:not(:disabled) {
4685
+ color: var(--juxt-fg);
4686
+ }
4687
+ .j-toggle-group__item.is-selected {
4688
+ background: var(--juxt-surface);
4689
+ box-shadow: var(--juxt-shadow-sm);
4690
+ color: var(--juxt-fg);
4691
+ }
4692
+ .dark .j-toggle-group__item.is-selected,
4693
+ [data-theme='dark'] .j-toggle-group__item.is-selected {
4694
+ background: var(--juxt-surface-active);
4695
+ }
4696
+ .j-toggle-group__item:disabled {
4697
+ color: var(--juxt-fg-disabled);
4698
+ cursor: not-allowed;
4699
+ }
4700
+ }
4701
+
4702
+ @layer theme, base, juxt, components, utilities;
3174
4703
  @layer juxt {
3175
4704
  .j-tooltip {
3176
4705
  z-index: var(--juxt-z-tooltip);
@@ -3217,4 +4746,16 @@ to {
3217
4746
  );
3218
4747
  }
3219
4748
  }
4749
+
4750
+ @layer theme, base, juxt, components, utilities;
4751
+ @layer juxt {
4752
+ /*
4753
+ * Visual hiding is handled entirely by the shared `.j-sr-only` utility in
4754
+ * base.css | this component just gives it a typed, composable wrapper so it
4755
+ * can be used as `<JVisuallyHidden as="label">…</JVisuallyHidden>`.
4756
+ */
4757
+ .j-visually-hidden {
4758
+ display: block;
4759
+ }
4760
+ }
3220
4761
  /*$vite$:1*/