@kennycorrea/ui 0.9.1 → 0.11.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 (78) hide show
  1. package/CHANGELOG.md +120 -14
  2. package/README.md +204 -273
  3. package/dist/atoms/ActionSheet/ActionSheet.d.ts +30 -0
  4. package/dist/atoms/ActionSheet/ActionSheet.js +42 -0
  5. package/dist/atoms/ActionSheet/confirm.d.ts +21 -0
  6. package/dist/atoms/ActionSheet/confirm.js +65 -0
  7. package/dist/atoms/ActionSheet/index.d.ts +2 -0
  8. package/dist/atoms/ActionSheet/index.js +2 -0
  9. package/dist/atoms/Button/Button.js +3 -3
  10. package/dist/atoms/Button/Button.types.d.ts +7 -1
  11. package/dist/atoms/Card/Card.d.ts +28 -7
  12. package/dist/atoms/Card/Card.js +45 -9
  13. package/dist/atoms/ChipGroup/ChipGroup.d.ts +31 -0
  14. package/dist/atoms/ChipGroup/ChipGroup.js +69 -0
  15. package/dist/atoms/ChipGroup/index.d.ts +1 -0
  16. package/dist/atoms/ChipGroup/index.js +1 -0
  17. package/dist/atoms/Drawer/Drawer.d.ts +1 -1
  18. package/dist/atoms/Drawer/Drawer.js +9 -13
  19. package/dist/atoms/Input/Input.js +7 -1
  20. package/dist/atoms/List/List.d.ts +73 -0
  21. package/dist/atoms/List/List.js +88 -0
  22. package/dist/atoms/List/index.d.ts +1 -0
  23. package/dist/atoms/List/index.js +1 -0
  24. package/dist/atoms/List/swipe.d.ts +68 -0
  25. package/dist/atoms/List/swipe.js +207 -0
  26. package/dist/atoms/NavBar/BackButton.d.ts +10 -0
  27. package/dist/atoms/NavBar/BackButton.js +11 -0
  28. package/dist/atoms/NavBar/NavBar.d.ts +22 -0
  29. package/dist/atoms/NavBar/NavBar.js +29 -0
  30. package/dist/atoms/NavBar/index.d.ts +2 -0
  31. package/dist/atoms/NavBar/index.js +2 -0
  32. package/dist/atoms/NotificationCard/NotificationCard.d.ts +52 -0
  33. package/dist/atoms/NotificationCard/NotificationCard.js +78 -0
  34. package/dist/atoms/NotificationCard/index.d.ts +1 -0
  35. package/dist/atoms/NotificationCard/index.js +1 -0
  36. package/dist/atoms/PullToRefresh/PullToRefresh.d.ts +31 -0
  37. package/dist/atoms/PullToRefresh/PullToRefresh.js +110 -0
  38. package/dist/atoms/PullToRefresh/index.d.ts +1 -0
  39. package/dist/atoms/PullToRefresh/index.js +1 -0
  40. package/dist/atoms/ResponsiveDialog/ResponsiveDialog.d.ts +13 -0
  41. package/dist/atoms/ResponsiveDialog/ResponsiveDialog.js +27 -0
  42. package/dist/atoms/ResponsiveDialog/index.d.ts +1 -0
  43. package/dist/atoms/ResponsiveDialog/index.js +1 -0
  44. package/dist/atoms/ScrollStrip/ScrollStrip.d.ts +17 -0
  45. package/dist/atoms/ScrollStrip/ScrollStrip.js +15 -0
  46. package/dist/atoms/ScrollStrip/index.d.ts +1 -0
  47. package/dist/atoms/ScrollStrip/index.js +1 -0
  48. package/dist/atoms/SegmentedControl/SegmentedControl.d.ts +23 -0
  49. package/dist/atoms/SegmentedControl/SegmentedControl.js +41 -0
  50. package/dist/atoms/SegmentedControl/index.d.ts +1 -0
  51. package/dist/atoms/SegmentedControl/index.js +1 -0
  52. package/dist/atoms/Select/Select.js +1 -1
  53. package/dist/atoms/Sheet/Sheet.d.ts +63 -0
  54. package/dist/atoms/Sheet/Sheet.js +261 -0
  55. package/dist/atoms/Sheet/index.d.ts +1 -0
  56. package/dist/atoms/Sheet/index.js +1 -0
  57. package/dist/atoms/StatTile/StatTile.d.ts +36 -0
  58. package/dist/atoms/StatTile/StatTile.js +17 -0
  59. package/dist/atoms/StatTile/index.d.ts +1 -0
  60. package/dist/atoms/StatTile/index.js +1 -0
  61. package/dist/atoms/TabBar/TabBar.d.ts +42 -0
  62. package/dist/atoms/TabBar/TabBar.js +36 -0
  63. package/dist/atoms/TabBar/index.d.ts +1 -0
  64. package/dist/atoms/TabBar/index.js +1 -0
  65. package/dist/atoms/Textarea/Textarea.d.ts +4 -0
  66. package/dist/atoms/Textarea/Textarea.js +1 -1
  67. package/dist/atoms/Toast/Toast.d.ts +8 -2
  68. package/dist/atoms/Toast/Toast.js +19 -4
  69. package/dist/atoms/index.d.ts +12 -0
  70. package/dist/atoms/index.js +12 -0
  71. package/dist/primitives/index.d.ts +1 -1
  72. package/dist/primitives/index.js +1 -1
  73. package/dist/strings.d.ts +13 -3
  74. package/dist/strings.js +5 -0
  75. package/dist/utils/themePortal.d.ts +19 -0
  76. package/dist/utils/themePortal.js +28 -0
  77. package/package.json +4 -2
  78. package/tokens.css +454 -0
package/tokens.css CHANGED
@@ -209,6 +209,68 @@
209
209
  }
210
210
  }
211
211
 
212
+ /**
213
+ * The mobile presentation layer: a "grouped" surface style, the list-on-tinted-canvas look of
214
+ * native settings screens. Opt-in — nothing above reads these, so existing atoms are untouched.
215
+ *
216
+ * Colours live on `.radix-themes` for the reason given above, with one rule per appearance
217
+ * because the pairing flips: in light the canvas is the darker of the two (gray-3 under a white
218
+ * card), in dark it is the darker too (gray-1 under a gray-3 card). Both pairs are asserted at
219
+ * WCAG AA for gray-11 and gray-12 text in `test/grouped.test.tsx`.
220
+ *
221
+ * The non-colour tokens carry no Radix variable, so they sit on `:root` and also work in a
222
+ * portal that escapes the Theme.
223
+ */
224
+ :root {
225
+ --press-scale: 0.97;
226
+ --press-duration: 120ms;
227
+ --radius-group: 12px;
228
+ --space-row-y: 10px;
229
+ --space-row-x: 12px;
230
+ --tap-min: 44px;
231
+ --safe-top: env(safe-area-inset-top, 0px);
232
+ --safe-right: env(safe-area-inset-right, 0px);
233
+ --safe-bottom: env(safe-area-inset-bottom, 0px);
234
+ --safe-left: env(safe-area-inset-left, 0px);
235
+ --material-bar-filter: saturate(180%) blur(20px);
236
+ }
237
+
238
+ @layer base {
239
+ .radix-themes {
240
+ /* Card on the tinted canvas: no border, the contrast between the two does the separating. */
241
+ --surface-grouped: var(--color-panel-solid);
242
+ --canvas-grouped: var(--gray-3);
243
+ --separator-inset: var(--gray-a6);
244
+ /* Translucent bar over scrolling content. 80% of the canvas keeps text AA over any content
245
+ the blur leaves behind, and is still a legible bar where backdrop-filter is unsupported. */
246
+ --material-bar: color-mix(in srgb, var(--canvas-grouped) 80%, transparent);
247
+ }
248
+ .radix-themes:is(.dark, .dark-theme) {
249
+ --surface-grouped: var(--gray-3);
250
+ --canvas-grouped: var(--gray-1);
251
+ }
252
+ }
253
+
254
+ @theme inline {
255
+ --color-grouped: var(--surface-grouped);
256
+ --color-canvas-grouped: var(--canvas-grouped);
257
+ --color-separator-inset: var(--separator-inset);
258
+ }
259
+
260
+ @utility rounded-group { border-radius: var(--radius-group); }
261
+ @utility min-h-tap { min-height: var(--tap-min); }
262
+ @utility pt-safe { padding-top: var(--safe-top); }
263
+ @utility pb-safe { padding-bottom: var(--safe-bottom); }
264
+ @utility px-safe {
265
+ padding-left: var(--safe-left);
266
+ padding-right: var(--safe-right);
267
+ }
268
+ @utility bg-material {
269
+ background-color: var(--material-bar);
270
+ -webkit-backdrop-filter: var(--material-bar-filter);
271
+ backdrop-filter: var(--material-bar-filter);
272
+ }
273
+
212
274
  /**
213
275
  * Pins a subtree to the light appearance whatever the provider chose.
214
276
  *
@@ -258,6 +320,13 @@
258
320
  .ui-toast[data-swipe='move'] { transform: translateX(var(--radix-toast-swipe-move-x)); }
259
321
  .ui-toast[data-swipe='cancel'] { transform: translateX(0); transition: transform 200ms ease-out; }
260
322
  .ui-toast[data-swipe='end'] { animation: ui-toast-swipe-out 120ms ease-out forwards; }
323
+ /* Centred stacks dismiss vertically: up when anchored to the top, down at the bottom. */
324
+ @keyframes ui-toast-swipe-out-y {
325
+ to { transform: translateY(calc(var(--radix-toast-swipe-end-y) + (var(--ui-toast-swipe-sign) * 100%))); opacity: 0; }
326
+ }
327
+ .ui-toast[data-swipe-axis='y'][data-swipe='move'] { transform: translateY(var(--radix-toast-swipe-move-y)); }
328
+ .ui-toast[data-swipe-axis='y'][data-swipe='cancel'] { transform: translateY(0); }
329
+ .ui-toast[data-swipe-axis='y'][data-swipe='end'] { animation-name: ui-toast-swipe-out-y; }
261
330
  @media (prefers-reduced-motion: reduce) {
262
331
  .ui-toast[data-state] { animation-duration: 1ms; }
263
332
  }
@@ -455,3 +524,388 @@
455
524
  pointer-events: none;
456
525
  color: var(--gray-a10);
457
526
  }
527
+
528
+ /**
529
+ * NotificationCard — a persistent rich toast. Only Radix Themes variables, so it follows the
530
+ * `.light`/`.dark` class on the nearest <Theme> rather than the OS. z-index sits below Radix
531
+ * Themes dialogs and the Drawer (50) and above page content.
532
+ */
533
+ .ui-notification-card {
534
+ position: fixed;
535
+ z-index: 40;
536
+ width: min(24rem, 100vw - 2rem);
537
+ max-height: calc(100vh - 2rem);
538
+ overflow-y: auto;
539
+ box-sizing: border-box;
540
+ display: flex;
541
+ flex-direction: column;
542
+ gap: var(--space-3);
543
+ padding: var(--space-4);
544
+ background: var(--color-panel-solid);
545
+ color: var(--gray-12);
546
+ border: 1px solid var(--gray-a6);
547
+ border-radius: var(--radius-4);
548
+ box-shadow: var(--shadow-5);
549
+ font-family: var(--default-font-family);
550
+ --ui-nc-from: translateY(calc(100% + 16px));
551
+ }
552
+ .ui-notification-card[data-position='bottom-right'] { bottom: 16px; right: 16px; }
553
+ .ui-notification-card[data-position='bottom-left'] { bottom: 16px; left: 16px; }
554
+ .ui-notification-card[data-position='top-right'] { top: 16px; right: 16px; --ui-nc-from: translateY(calc(-100% - 16px)); }
555
+ .ui-notification-card[data-position='top-left'] { top: 16px; left: 16px; --ui-nc-from: translateY(calc(-100% - 16px)); }
556
+ .ui-notification-card[data-state='open'] { animation: ui-nc-in 220ms ease-out; }
557
+ .ui-notification-card[data-state='closed'] { animation: ui-nc-out 160ms ease-in forwards; }
558
+ @keyframes ui-nc-in { from { transform: var(--ui-nc-from); opacity: 0; } }
559
+ @keyframes ui-nc-out { to { transform: var(--ui-nc-from); opacity: 0; } }
560
+ @media (prefers-reduced-motion: reduce) {
561
+ .ui-notification-card[data-state] { animation-duration: 1ms; }
562
+ }
563
+ .ui-notification-card__header { display: flex; align-items: flex-start; gap: var(--space-3); }
564
+ .ui-notification-card__icon { flex-shrink: 0; display: flex; }
565
+ .ui-notification-card__text { flex: 1; min-width: 0; }
566
+ .ui-notification-card__title { margin: 0; font-size: var(--font-size-3); font-weight: var(--font-weight-medium); line-height: var(--line-height-3); }
567
+ .ui-notification-card__description { margin: var(--space-1) 0 0; font-size: var(--font-size-2); line-height: var(--line-height-2); color: var(--gray-11); }
568
+ .ui-notification-card__close,
569
+ .ui-notification-card__toggle {
570
+ appearance: none; border: 0; background: transparent; color: var(--gray-11);
571
+ cursor: pointer; font: inherit; border-radius: var(--radius-2);
572
+ }
573
+ .ui-notification-card__close {
574
+ flex-shrink: 0; display: flex; align-items: center; justify-content: center;
575
+ width: var(--space-6); height: var(--space-6); margin: calc(var(--space-1) * -1);
576
+ }
577
+ .ui-notification-card__toggle {
578
+ align-self: flex-start; display: inline-flex; align-items: center; gap: var(--space-1);
579
+ padding: var(--space-1) var(--space-2); margin-left: calc(var(--space-2) * -1);
580
+ font-size: var(--font-size-2); color: var(--accent-11);
581
+ }
582
+ .ui-notification-card__close:hover,
583
+ .ui-notification-card__toggle:hover { background: var(--gray-a3); }
584
+ .ui-notification-card__close:focus-visible,
585
+ .ui-notification-card__toggle:focus-visible { outline: 2px solid var(--focus-8); outline-offset: 1px; }
586
+ .ui-notification-card__body { font-size: var(--font-size-2); color: var(--gray-12); }
587
+ .ui-notification-card__actions { display: flex; justify-content: flex-end; gap: var(--space-2); }
588
+
589
+ /**
590
+ * Card variant and density. Generated per Radix Themes breakpoint (xs 520, sm 768, md 1024,
591
+ * lg 1280, xl 1640) because a responsive prop is a data attribute here, not a class: Tailwind's own
592
+ * `md` is 768. Ascending media queries of equal specificity, so the widest match wins. The card's
593
+ * pseudo-elements carry the surface and ring, so grouped/plain switch them off with `content`.
594
+ */
595
+ .ui-card-header, .ui-card-body { padding: 16px 20px; }
596
+ .ui-card-title { font-size: 1rem; font-weight: 500; }
597
+ .ui-card.rt-Card[data-variant="outlined"] { background: transparent; --base-card-border-radius: var(--card-border-radius);}
598
+ .ui-card.rt-Card[data-variant="grouped"] { background: var(--surface-grouped); box-shadow: none; --base-card-border-radius: var(--radius-group);}
599
+ .ui-card.rt-Card[data-variant="plain"] { background: transparent; box-shadow: none; --base-card-border-radius: 0px;}
600
+ .ui-card.rt-Card[data-variant="outlined"]::before { content: '';}
601
+ .ui-card.rt-Card[data-variant="grouped"]::before { content: none;}
602
+ .ui-card.rt-Card[data-variant="plain"]::before { content: none;}
603
+ .ui-card.rt-Card[data-variant="outlined"]::after { content: '';}
604
+ .ui-card.rt-Card[data-variant="grouped"]::after { content: none;}
605
+ .ui-card.rt-Card[data-variant="plain"]::after { content: none;}
606
+ .ui-card-header[data-variant="grouped"] { --color-hairline: var(--separator-inset); }
607
+ .ui-card-header[data-variant="outlined"] { border-bottom-width: 1px; }
608
+ .ui-card-header[data-variant="plain"] { border-bottom-width: 0; }
609
+ .ui-card-header[data-density="comfortable"], .ui-card-body[data-density="comfortable"] { padding: 16px 20px; }
610
+ .ui-card-header[data-density="compact"], .ui-card-body[data-density="compact"] { padding: var(--space-row-y) var(--space-row-x); }
611
+ .ui-card-title[data-density="comfortable"] { font-size: 1rem; font-weight: 500; }
612
+ .ui-card-title[data-density="compact"] { font-size: 0.875rem; font-weight: 400; }
613
+ @media (min-width: 520px) {
614
+ .ui-card.rt-Card[data-variant-xs="outlined"] { background: transparent; --base-card-border-radius: var(--card-border-radius);}
615
+ .ui-card.rt-Card[data-variant-xs="grouped"] { background: var(--surface-grouped); box-shadow: none; --base-card-border-radius: var(--radius-group);}
616
+ .ui-card.rt-Card[data-variant-xs="plain"] { background: transparent; box-shadow: none; --base-card-border-radius: 0px;}
617
+ .ui-card.rt-Card[data-variant-xs="outlined"]::before { content: '';}
618
+ .ui-card.rt-Card[data-variant-xs="grouped"]::before { content: none;}
619
+ .ui-card.rt-Card[data-variant-xs="plain"]::before { content: none;}
620
+ .ui-card.rt-Card[data-variant-xs="outlined"]::after { content: '';}
621
+ .ui-card.rt-Card[data-variant-xs="grouped"]::after { content: none;}
622
+ .ui-card.rt-Card[data-variant-xs="plain"]::after { content: none;}
623
+ .ui-card-header[data-variant-xs="grouped"] { --color-hairline: var(--separator-inset); }
624
+ .ui-card-header[data-variant-xs="outlined"] { border-bottom-width: 1px; }
625
+ .ui-card-header[data-variant-xs="plain"] { border-bottom-width: 0; }
626
+ .ui-card-header[data-density-xs="comfortable"], .ui-card-body[data-density-xs="comfortable"] { padding: 16px 20px; }
627
+ .ui-card-header[data-density-xs="compact"], .ui-card-body[data-density-xs="compact"] { padding: var(--space-row-y) var(--space-row-x); }
628
+ .ui-card-title[data-density-xs="comfortable"] { font-size: 1rem; font-weight: 500; }
629
+ .ui-card-title[data-density-xs="compact"] { font-size: 0.875rem; font-weight: 400; }
630
+ }
631
+ @media (min-width: 768px) {
632
+ .ui-card.rt-Card[data-variant-sm="outlined"] { background: transparent; --base-card-border-radius: var(--card-border-radius);}
633
+ .ui-card.rt-Card[data-variant-sm="grouped"] { background: var(--surface-grouped); box-shadow: none; --base-card-border-radius: var(--radius-group);}
634
+ .ui-card.rt-Card[data-variant-sm="plain"] { background: transparent; box-shadow: none; --base-card-border-radius: 0px;}
635
+ .ui-card.rt-Card[data-variant-sm="outlined"]::before { content: '';}
636
+ .ui-card.rt-Card[data-variant-sm="grouped"]::before { content: none;}
637
+ .ui-card.rt-Card[data-variant-sm="plain"]::before { content: none;}
638
+ .ui-card.rt-Card[data-variant-sm="outlined"]::after { content: '';}
639
+ .ui-card.rt-Card[data-variant-sm="grouped"]::after { content: none;}
640
+ .ui-card.rt-Card[data-variant-sm="plain"]::after { content: none;}
641
+ .ui-card-header[data-variant-sm="grouped"] { --color-hairline: var(--separator-inset); }
642
+ .ui-card-header[data-variant-sm="outlined"] { border-bottom-width: 1px; }
643
+ .ui-card-header[data-variant-sm="plain"] { border-bottom-width: 0; }
644
+ .ui-card-header[data-density-sm="comfortable"], .ui-card-body[data-density-sm="comfortable"] { padding: 16px 20px; }
645
+ .ui-card-header[data-density-sm="compact"], .ui-card-body[data-density-sm="compact"] { padding: var(--space-row-y) var(--space-row-x); }
646
+ .ui-card-title[data-density-sm="comfortable"] { font-size: 1rem; font-weight: 500; }
647
+ .ui-card-title[data-density-sm="compact"] { font-size: 0.875rem; font-weight: 400; }
648
+ }
649
+ @media (min-width: 1024px) {
650
+ .ui-card.rt-Card[data-variant-md="outlined"] { background: transparent; --base-card-border-radius: var(--card-border-radius);}
651
+ .ui-card.rt-Card[data-variant-md="grouped"] { background: var(--surface-grouped); box-shadow: none; --base-card-border-radius: var(--radius-group);}
652
+ .ui-card.rt-Card[data-variant-md="plain"] { background: transparent; box-shadow: none; --base-card-border-radius: 0px;}
653
+ .ui-card.rt-Card[data-variant-md="outlined"]::before { content: '';}
654
+ .ui-card.rt-Card[data-variant-md="grouped"]::before { content: none;}
655
+ .ui-card.rt-Card[data-variant-md="plain"]::before { content: none;}
656
+ .ui-card.rt-Card[data-variant-md="outlined"]::after { content: '';}
657
+ .ui-card.rt-Card[data-variant-md="grouped"]::after { content: none;}
658
+ .ui-card.rt-Card[data-variant-md="plain"]::after { content: none;}
659
+ .ui-card-header[data-variant-md="grouped"] { --color-hairline: var(--separator-inset); }
660
+ .ui-card-header[data-variant-md="outlined"] { border-bottom-width: 1px; }
661
+ .ui-card-header[data-variant-md="plain"] { border-bottom-width: 0; }
662
+ .ui-card-header[data-density-md="comfortable"], .ui-card-body[data-density-md="comfortable"] { padding: 16px 20px; }
663
+ .ui-card-header[data-density-md="compact"], .ui-card-body[data-density-md="compact"] { padding: var(--space-row-y) var(--space-row-x); }
664
+ .ui-card-title[data-density-md="comfortable"] { font-size: 1rem; font-weight: 500; }
665
+ .ui-card-title[data-density-md="compact"] { font-size: 0.875rem; font-weight: 400; }
666
+ }
667
+ @media (min-width: 1280px) {
668
+ .ui-card.rt-Card[data-variant-lg="outlined"] { background: transparent; --base-card-border-radius: var(--card-border-radius);}
669
+ .ui-card.rt-Card[data-variant-lg="grouped"] { background: var(--surface-grouped); box-shadow: none; --base-card-border-radius: var(--radius-group);}
670
+ .ui-card.rt-Card[data-variant-lg="plain"] { background: transparent; box-shadow: none; --base-card-border-radius: 0px;}
671
+ .ui-card.rt-Card[data-variant-lg="outlined"]::before { content: '';}
672
+ .ui-card.rt-Card[data-variant-lg="grouped"]::before { content: none;}
673
+ .ui-card.rt-Card[data-variant-lg="plain"]::before { content: none;}
674
+ .ui-card.rt-Card[data-variant-lg="outlined"]::after { content: '';}
675
+ .ui-card.rt-Card[data-variant-lg="grouped"]::after { content: none;}
676
+ .ui-card.rt-Card[data-variant-lg="plain"]::after { content: none;}
677
+ .ui-card-header[data-variant-lg="grouped"] { --color-hairline: var(--separator-inset); }
678
+ .ui-card-header[data-variant-lg="outlined"] { border-bottom-width: 1px; }
679
+ .ui-card-header[data-variant-lg="plain"] { border-bottom-width: 0; }
680
+ .ui-card-header[data-density-lg="comfortable"], .ui-card-body[data-density-lg="comfortable"] { padding: 16px 20px; }
681
+ .ui-card-header[data-density-lg="compact"], .ui-card-body[data-density-lg="compact"] { padding: var(--space-row-y) var(--space-row-x); }
682
+ .ui-card-title[data-density-lg="comfortable"] { font-size: 1rem; font-weight: 500; }
683
+ .ui-card-title[data-density-lg="compact"] { font-size: 0.875rem; font-weight: 400; }
684
+ }
685
+ @media (min-width: 1640px) {
686
+ .ui-card.rt-Card[data-variant-xl="outlined"] { background: transparent; --base-card-border-radius: var(--card-border-radius);}
687
+ .ui-card.rt-Card[data-variant-xl="grouped"] { background: var(--surface-grouped); box-shadow: none; --base-card-border-radius: var(--radius-group);}
688
+ .ui-card.rt-Card[data-variant-xl="plain"] { background: transparent; box-shadow: none; --base-card-border-radius: 0px;}
689
+ .ui-card.rt-Card[data-variant-xl="outlined"]::before { content: '';}
690
+ .ui-card.rt-Card[data-variant-xl="grouped"]::before { content: none;}
691
+ .ui-card.rt-Card[data-variant-xl="plain"]::before { content: none;}
692
+ .ui-card.rt-Card[data-variant-xl="outlined"]::after { content: '';}
693
+ .ui-card.rt-Card[data-variant-xl="grouped"]::after { content: none;}
694
+ .ui-card.rt-Card[data-variant-xl="plain"]::after { content: none;}
695
+ .ui-card-header[data-variant-xl="grouped"] { --color-hairline: var(--separator-inset); }
696
+ .ui-card-header[data-variant-xl="outlined"] { border-bottom-width: 1px; }
697
+ .ui-card-header[data-variant-xl="plain"] { border-bottom-width: 0; }
698
+ .ui-card-header[data-density-xl="comfortable"], .ui-card-body[data-density-xl="comfortable"] { padding: 16px 20px; }
699
+ .ui-card-header[data-density-xl="compact"], .ui-card-body[data-density-xl="compact"] { padding: var(--space-row-y) var(--space-row-x); }
700
+ .ui-card-title[data-density-xl="comfortable"] { font-size: 1rem; font-weight: 500; }
701
+ .ui-card-title[data-density-xl="compact"] { font-size: 0.875rem; font-weight: 400; }
702
+ }
703
+
704
+ /* ---- Grouped list: ListSection / ListRow ---- */
705
+ .ui-list-section { --list-lead-w: 28px; --list-gap: 12px; }
706
+ .ui-list-section[data-variant="inset"] { margin-inline: var(--space-row-x); }
707
+ .ui-list-header, .ui-list-footer { font-size: 0.8125rem; line-height: 1.3; color: var(--gray-11); padding: 6px calc(var(--space-row-x) + 4px); }
708
+ .ui-list-header { text-transform: uppercase; letter-spacing: 0.02em; font-size: 0.75rem; }
709
+ .ui-list { list-style: none; margin: 0; padding: 0; background: var(--surface-grouped); overflow: hidden; }
710
+ .ui-list-section[data-variant="inset"] .ui-list { border-radius: var(--radius-group); }
711
+ .ui-list-item { position: relative; list-style: none; }
712
+ /* Hairline above every row but the first; it starts after the leading slot when this row has one. */
713
+ .ui-list-item + .ui-list-item::before { content: ""; position: absolute; top: 0; right: 0; height: 1px; background: var(--separator-inset); left: var(--space-row-x); }
714
+ .ui-list-item + .ui-list-item[data-has-lead]::before { left: calc(var(--space-row-x) + var(--list-lead-w) + var(--list-gap)); }
715
+ .ui-list-section[data-variant="full"] .ui-list-item + .ui-list-item::before { left: 0; }
716
+ .ui-list-row { display: flex; align-items: center; gap: var(--list-gap); box-sizing: border-box; width: 100%; min-height: var(--tap-min); padding: var(--space-row-y) var(--space-row-x); background: transparent; border: 0; margin: 0; font: inherit; text-align: start; color: var(--gray-12); text-decoration: none; -webkit-tap-highlight-color: transparent; }
717
+ .ui-list-row[data-interactive] { cursor: pointer; }
718
+ .ui-list-row[data-interactive] { transition: transform var(--press-duration) ease-out, background-color var(--press-duration) ease-out; }
719
+ .ui-list-row[data-interactive]:active { background: var(--gray-a4); transform: scale(var(--press-scale)); }
720
+ @media (hover: hover) { .ui-list-row[data-interactive]:hover { background: var(--gray-a3); } .ui-list-row[data-interactive]:hover:active { background: var(--gray-a4); } }
721
+ .ui-list-row:focus-visible { outline: 2px solid var(--focus-8); outline-offset: -2px; }
722
+ .ui-list-row[data-disabled] { opacity: 0.5; cursor: default; pointer-events: none; }
723
+ .ui-list-row[data-destructive] .ui-list-title { color: var(--red-11); }
724
+ .ui-list-lead { flex: none; width: var(--list-lead-w); height: var(--list-lead-w); display: inline-flex; align-items: center; justify-content: center; }
725
+ .ui-list-text { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
726
+ .ui-list-title, .ui-list-subtitle { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
727
+ .ui-list-title { font-size: 1rem; line-height: 1.3; }
728
+ .ui-list-subtitle { font-size: 0.8125rem; line-height: 1.3; color: var(--gray-11); }
729
+ .ui-list-trailing { flex: none; max-width: 50%; display: inline-flex; align-items: center; gap: 8px; color: var(--gray-11); font-variant-numeric: tabular-nums; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
730
+ .ui-list-chevron { flex: none; color: var(--gray-9); width: 16px; height: 16px; margin-inline-end: -4px; }
731
+ .ui-list-skeleton { display: flex; align-items: center; gap: var(--list-gap); flex: 1; min-width: 0; }
732
+ .ui-list-item-swipe { overflow: hidden; }
733
+ .ui-list-surface { position: relative; display: flex; align-items: stretch; background: var(--surface-grouped); touch-action: pan-y; }
734
+ .ui-list-surface[data-swipe] { transition: transform 220ms cubic-bezier(0.2, 0.8, 0.2, 1); }
735
+ .ui-list-surface[data-dragging] { transition: none; user-select: none; }
736
+ .ui-list-surface > .ui-list-row { flex: 1 1 auto; width: auto; min-width: 0; }
737
+ .ui-list-more { flex: none; align-self: center; display: inline-flex; align-items: center; justify-content: center; width: var(--tap-min); height: var(--tap-min); padding: 0; margin-inline-end: 4px; border: 0; border-radius: 50%; background: transparent; color: var(--gray-11); cursor: pointer; -webkit-tap-highlight-color: transparent; }
738
+ .ui-list-more:hover { background: var(--gray-a3); }
739
+ .ui-list-more:focus-visible { outline: 2px solid var(--focus-8); outline-offset: -2px; }
740
+ .ui-list-more[data-hidden]:not(:focus-visible) { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); margin: 0; }
741
+ .ui-list-tray { position: absolute; top: 0; bottom: 0; display: flex; overflow: hidden; }
742
+ .ui-list-tray[data-side="leading"] { left: 0; }
743
+ .ui-list-tray[data-side="trailing"] { right: 0; }
744
+ .ui-list-action { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 4px; border: 0; padding: 0 4px; font: inherit; font-size: 0.75rem; color: white; cursor: pointer; background: var(--gray-9); }
745
+ .ui-list-action[data-tone="brand"] { background: var(--accent-9); color: var(--accent-contrast, white); }
746
+ .ui-list-action[data-tone="danger"] { background: var(--red-9); }
747
+ .ui-list-action:focus-visible { outline: 2px solid var(--focus-8); outline-offset: -3px; }
748
+ .ui-list-action-label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 100%; }
749
+ @media (prefers-reduced-motion: reduce) { .ui-list-surface[data-swipe] { transition: none; } }
750
+ .ui-list-sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
751
+
752
+ /**
753
+ * Sheet motion. The drag offset is a custom property rather than an inline transform so the exit
754
+ * animation can start from wherever the finger let go.
755
+ */
756
+ .ui-sheet { transform: translateY(var(--sheet-drag, 0px)); }
757
+ .ui-sheet:not([data-dragging]) { transition: transform 200ms ease-out, height 200ms ease-out; }
758
+ .ui-sheet[data-state='open'] { animation: ui-sheet-in 260ms cubic-bezier(0.2, 0.8, 0.2, 1); }
759
+ .ui-sheet[data-state='closed'] { animation: ui-sheet-out 200ms ease-in forwards; }
760
+ .ui-sheet-scrim[data-state='open'] { animation: ui-sheet-fade-in 200ms ease-out; }
761
+ .ui-sheet-scrim[data-state='closed'] { animation: ui-sheet-fade-out 200ms ease-in forwards; }
762
+ @keyframes ui-sheet-in { from { transform: translateY(100%); } }
763
+ @keyframes ui-sheet-out { from { transform: translateY(var(--sheet-drag, 0px)); } to { transform: translateY(100%); } }
764
+ @keyframes ui-sheet-fade-in { from { opacity: 0; } }
765
+ @keyframes ui-sheet-fade-out { to { opacity: 0; } }
766
+ @media (prefers-reduced-motion: reduce) {
767
+ .ui-sheet, .ui-sheet-scrim { transition: none !important; }
768
+ .ui-sheet[data-state], .ui-sheet-scrim[data-state] { animation-duration: 1ms; }
769
+ }
770
+
771
+ /**
772
+ * TabBar. 49px of bar plus the home-indicator inset; `--tabbar-height` is that sum so content can
773
+ * pad itself. Hidden from the chosen Radix Themes breakpoint upward.
774
+ */
775
+ :root { --tabbar-height: calc(49px + var(--safe-bottom, 0px)); }
776
+ .ui-tabbar { position: fixed; inset: auto 0 0 0; z-index: 30; display: flex; box-sizing: border-box;
777
+ height: var(--tabbar-height); padding: 0 var(--safe-right, 0px) var(--safe-bottom, 0px) var(--safe-left, 0px);
778
+ background-color: var(--material-bar); -webkit-backdrop-filter: var(--material-bar-filter); backdrop-filter: var(--material-bar-filter);
779
+ box-shadow: inset 0 0.5px 0 var(--color-hairline); }
780
+ .ui-tabbar-spacer { height: var(--tabbar-height); flex: none; }
781
+ .ui-tabbar__cell { flex: 1 1 0; min-width: 0; display: flex; }
782
+ .ui-tabbar__item { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px;
783
+ min-width: 44px; padding: 0; border: 0; background: none; font: inherit; color: var(--gray-11); text-decoration: none;
784
+ cursor: pointer; -webkit-tap-highlight-color: transparent; touch-action: manipulation; }
785
+ .ui-tabbar__item[data-active="true"] { color: var(--accent-11); }
786
+ .ui-tabbar__item { border-radius: 8px; transition: transform var(--press-duration) ease-out, background-color var(--press-duration) ease-out; }
787
+ .ui-tabbar__item:active { background: var(--gray-a3); transform: scale(var(--press-scale)); }
788
+ .ui-tabbar__item:focus-visible { outline: 2px solid var(--focus-8); outline-offset: -2px; border-radius: 8px; }
789
+ .ui-tabbar__icon { position: relative; display: inline-flex; font-size: 24px; line-height: 1; }
790
+ .ui-tabbar__label { font-size: 10px; line-height: 12px; font-weight: 500; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
791
+ .ui-tabbar__badge { position: absolute; top: -4px; left: calc(100% - 8px); min-width: 16px; height: 16px; padding: 0 4px; box-sizing: border-box;
792
+ border-radius: 8px; background: var(--red-9); color: white; font-size: 11px; line-height: 16px; font-weight: 600; text-align: center; }
793
+ .ui-tabbar__badge[data-dot="true"] { min-width: 8px; width: 8px; height: 8px; padding: 0; top: -1px; left: calc(100% - 4px); }
794
+ @media (prefers-reduced-motion: reduce) { .ui-tabbar__item { transition: none; } .ui-tabbar__item:active { transform: none; } }
795
+ @media (min-width: 520px) { .ui-tabbar[data-hide-from="xs"], .ui-tabbar-spacer[data-hide-from="xs"] { display: none; } }
796
+ @media (min-width: 768px) { .ui-tabbar[data-hide-from="sm"], .ui-tabbar-spacer[data-hide-from="sm"] { display: none; } }
797
+ @media (min-width: 1024px) { .ui-tabbar[data-hide-from="md"], .ui-tabbar-spacer[data-hide-from="md"] { display: none; } }
798
+ @media (min-width: 1280px) { .ui-tabbar[data-hide-from="lg"], .ui-tabbar-spacer[data-hide-from="lg"] { display: none; } }
799
+ @media (min-width: 1640px) { .ui-tabbar[data-hide-from="xl"], .ui-tabbar-spacer[data-hide-from="xl"] { display: none; } }
800
+
801
+ /**
802
+ * NavBar. A sticky 44px bar plus the top inset; transparent until content scrolls beneath it,
803
+ * then `--material-bar` with a hairline. The large title lives in the flow below it.
804
+ */
805
+ :root { --navbar-height: calc(44px + var(--safe-top, 0px)); }
806
+ .ui-navbar { position: sticky; top: 0; z-index: 30; box-sizing: border-box; display: grid; grid-template-columns: 1fr auto 1fr; align-items: center;
807
+ height: var(--navbar-height); padding: var(--safe-top, 0px) max(8px, var(--safe-right, 0px)) 0 max(8px, var(--safe-left, 0px));
808
+ background-color: transparent; box-shadow: inset 0 -0.5px 0 transparent; transition: background-color 150ms, box-shadow 150ms; }
809
+ .ui-navbar[data-scrolled="true"] { background-color: var(--material-bar); -webkit-backdrop-filter: var(--material-bar-filter); backdrop-filter: var(--material-bar-filter);
810
+ box-shadow: inset 0 -0.5px 0 var(--color-hairline); }
811
+ .ui-navbar__side { display: flex; align-items: center; gap: 4px; min-width: 0; }
812
+ .ui-navbar__side--trailing { justify-content: flex-end; }
813
+ .ui-navbar__title { margin: 0; max-width: 60vw; font-size: 17px; line-height: 22px; font-weight: 600; text-align: center; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; transition: opacity 150ms; }
814
+ .ui-navbar[data-large="true"] .ui-navbar__title { opacity: 0; }
815
+ .ui-navbar[data-large="true"][data-scrolled="true"] .ui-navbar__title { opacity: 1; }
816
+ .ui-navbar__large { padding: 0 max(16px, var(--safe-left, 0px)) 8px; }
817
+ .ui-navbar__large-title { margin: 0; font-size: 34px; line-height: 41px; font-weight: 700; letter-spacing: 0.01em; overflow-wrap: anywhere; }
818
+ .ui-navbar__sentinel { height: 0; margin-top: -1px; pointer-events: none; }
819
+ .ui-backbutton { display: inline-flex; align-items: center; min-width: 44px; min-height: 44px; padding: 0 8px 0 0; border: 0; background: none; font: inherit; font-size: 17px;
820
+ color: var(--accent-11); cursor: pointer; -webkit-tap-highlight-color: transparent; touch-action: manipulation; transition: opacity 80ms; }
821
+ .ui-backbutton__icon { width: 28px; height: 28px; flex: none; }
822
+ .ui-backbutton:not(:has(.ui-backbutton__label)) { justify-content: center; padding: 0; }
823
+ .ui-backbutton__label { max-width: 40vw; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
824
+ .ui-backbutton:active { opacity: 0.55; }
825
+ .ui-backbutton:focus-visible { outline: 2px solid var(--focus-8); outline-offset: -2px; border-radius: 8px; }
826
+ @media (prefers-reduced-motion: reduce) { .ui-navbar, .ui-navbar__title, .ui-backbutton { transition: none; } }
827
+
828
+ /* SegmentedControl */
829
+ .ui-segmented { --seg-pad: 2px; position: relative; display: inline-grid; grid-auto-flow: column; grid-auto-columns: 1fr;
830
+ padding: var(--seg-pad); box-sizing: border-box; border-radius: 999px; background: var(--gray-a4); }
831
+ .ui-segmented[data-full="true"] { display: grid; width: 100%; }
832
+ .ui-segmented__thumb { position: absolute; top: var(--seg-pad); bottom: var(--seg-pad); left: var(--seg-pad);
833
+ width: calc((100% - 2 * var(--seg-pad)) / var(--seg-count)); border-radius: 999px; background: var(--color-panel-solid, #fff);
834
+ box-shadow: 0 1px 3px var(--black-a4), 0 0 0 0.5px var(--black-a3);
835
+ transform: translateX(calc(var(--seg-index) * 100%)); transition: transform 220ms cubic-bezier(0.3, 0.7, 0.2, 1); }
836
+ .ui-segmented__item { position: relative; z-index: 1; min-width: 0; border: 0; background: none; font: inherit; font-weight: 500;
837
+ color: var(--gray-11); border-radius: 999px; cursor: pointer; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
838
+ -webkit-tap-highlight-color: transparent; touch-action: manipulation; transition: color 150ms; }
839
+ .ui-segmented[data-size="md"] .ui-segmented__item { min-height: 32px; padding: 0 16px; font-size: 14px; }
840
+ .ui-segmented[data-size="sm"] .ui-segmented__item { min-height: 24px; padding: 0 12px; font-size: 12px; }
841
+ .ui-segmented__item[aria-checked="true"] { color: var(--gray-12); }
842
+ .ui-segmented__item:disabled { opacity: 0.4; cursor: not-allowed; }
843
+ .ui-segmented__item:focus-visible { outline: 2px solid var(--focus-8); outline-offset: 1px; }
844
+ @media (prefers-reduced-motion: reduce) { .ui-segmented__thumb, .ui-segmented__item { transition: none; } }
845
+
846
+ /* ChipGroup */
847
+ .ui-chips { position: relative; min-width: 0; --chips-fade: 24px; }
848
+ .ui-chips__scroller { display: flex; gap: 8px; overflow-x: auto; scroll-snap-type: x proximity; scrollbar-width: none;
849
+ padding: 2px 0; -webkit-overflow-scrolling: touch; }
850
+ .ui-chips__scroller::-webkit-scrollbar { display: none; }
851
+ .ui-chips[data-fade-start="true"] .ui-chips__scroller { -webkit-mask-image: linear-gradient(to right, transparent, #000 var(--chips-fade)); mask-image: linear-gradient(to right, transparent, #000 var(--chips-fade)); }
852
+ .ui-chips[data-fade-end="true"] .ui-chips__scroller { -webkit-mask-image: linear-gradient(to left, transparent, #000 var(--chips-fade)); mask-image: linear-gradient(to left, transparent, #000 var(--chips-fade)); }
853
+ .ui-chips[data-fade-start="true"][data-fade-end="true"] .ui-chips__scroller { -webkit-mask-image: linear-gradient(to right, transparent, #000 var(--chips-fade), #000 calc(100% - var(--chips-fade)), transparent); mask-image: linear-gradient(to right, transparent, #000 var(--chips-fade), #000 calc(100% - var(--chips-fade)), transparent); }
854
+ .ui-chips__chip { flex: none; scroll-snap-align: start; scroll-margin-inline: var(--chips-fade); min-height: 32px; padding: 0 14px;
855
+ border: 0; border-radius: 999px; background: var(--gray-a4); color: var(--gray-12); font: inherit; font-size: 14px; font-weight: 500;
856
+ white-space: nowrap; cursor: pointer; -webkit-tap-highlight-color: transparent; touch-action: manipulation; transition: background-color 120ms, color 120ms; }
857
+ .ui-chips__chip[data-selected="true"] { background: var(--accent-9); color: var(--accent-contrast); }
858
+ .ui-chips__chip:active { opacity: 0.7; }
859
+ .ui-chips__chip:disabled { opacity: 0.4; cursor: not-allowed; }
860
+ .ui-chips__chip:focus-visible { outline: 2px solid var(--focus-8); outline-offset: 1px; }
861
+
862
+ /* ---- StatTile ---- */
863
+ .ui-stat-card { height: 100%; }
864
+ .ui-stat { position: relative; display: flex; flex-direction: column; gap: 4px; width: 100%; height: 100%; padding: 16px 20px; text-align: start; color: inherit; background: none; border: 0; font: inherit; text-decoration: none; }
865
+ .ui-stat-card[data-density="compact"] .ui-stat { padding: var(--space-row-y) var(--space-row-x); }
866
+ .ui-stat[data-interactive] { cursor: pointer; padding-inline-end: 36px; }
867
+ .ui-stat[data-interactive] { transition: transform var(--press-duration) ease-out, background-color var(--press-duration) ease-out; -webkit-tap-highlight-color: transparent; }
868
+ .ui-stat[data-interactive]:active { background: var(--gray-a3); transform: scale(var(--press-scale)); }
869
+ @media (hover: hover) { .ui-stat[data-interactive]:hover { background: var(--gray-a2); } .ui-stat[data-interactive]:hover:active { background: var(--gray-a3); } }
870
+ .ui-stat[data-interactive]:focus-visible { outline: 2px solid var(--focus-8); outline-offset: -2px; border-radius: inherit; }
871
+ .ui-stat-label { font-size: 0.8125rem; color: var(--color-ink-muted); }
872
+ .ui-stat-row { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 8px; }
873
+ .ui-stat-value { font-size: 1.5rem; line-height: 1.2; font-weight: 600; color: var(--color-ink); font-variant-numeric: tabular-nums; }
874
+ .ui-stat-card[data-density="compact"] .ui-stat-value { font-size: 1.25rem; }
875
+ .ui-stat-delta { display: inline-flex; align-items: center; gap: 2px; font-size: 0.8125rem; font-weight: 500; font-variant-numeric: tabular-nums; color: var(--color-ink-muted); }
876
+ .ui-stat-delta[data-tone="positive"] { color: var(--green-11); }
877
+ .ui-stat-delta[data-tone="negative"] { color: var(--color-danger-ink); }
878
+ .ui-stat-spark { display: block; height: 32px; margin-top: 4px; }
879
+ .ui-stat-chevron { position: absolute; inset-inline-end: 12px; top: 50%; transform: translateY(-50%); color: var(--color-ink-muted); }
880
+
881
+ /* ---- ScrollStrip ---- */
882
+ .ui-strip { --strip-item: 78%; display: flex; gap: 12px; overflow-x: auto; overscroll-behavior-x: contain; scroll-snap-type: x mandatory; padding-inline: var(--page-gutter, 16px); scroll-padding-inline: var(--page-gutter, 16px); scrollbar-width: none; -webkit-overflow-scrolling: touch; }
883
+ .ui-strip::-webkit-scrollbar { display: none; }
884
+ .ui-strip > * { flex: 0 0 var(--strip-item); min-width: 0; scroll-snap-align: start; }
885
+ @media (prefers-reduced-motion: no-preference) { .ui-strip { scroll-behavior: smooth; } }
886
+ @media (min-width: 520px) { .ui-strip[data-grid-from="xs"] { display: grid; grid-template-columns: repeat(var(--strip-cols), minmax(0, 1fr)); overflow: visible; scroll-snap-type: none; padding-inline: 0; } .ui-strip[data-grid-from="xs"] > * { scroll-snap-align: none; } }
887
+ @media (min-width: 768px) { .ui-strip[data-grid-from="sm"] { display: grid; grid-template-columns: repeat(var(--strip-cols), minmax(0, 1fr)); overflow: visible; scroll-snap-type: none; padding-inline: 0; } .ui-strip[data-grid-from="sm"] > * { scroll-snap-align: none; } }
888
+ @media (min-width: 1024px) { .ui-strip[data-grid-from="md"] { display: grid; grid-template-columns: repeat(var(--strip-cols), minmax(0, 1fr)); overflow: visible; scroll-snap-type: none; padding-inline: 0; } .ui-strip[data-grid-from="md"] > * { scroll-snap-align: none; } }
889
+ @media (min-width: 1280px) { .ui-strip[data-grid-from="lg"] { display: grid; grid-template-columns: repeat(var(--strip-cols), minmax(0, 1fr)); overflow: visible; scroll-snap-type: none; padding-inline: 0; } .ui-strip[data-grid-from="lg"] > * { scroll-snap-align: none; } }
890
+ @media (min-width: 1640px) { .ui-strip[data-grid-from="xl"] { display: grid; grid-template-columns: repeat(var(--strip-cols), minmax(0, 1fr)); overflow: visible; scroll-snap-type: none; padding-inline: 0; } .ui-strip[data-grid-from="xl"] > * { scroll-snap-align: none; } }
891
+
892
+ /**
893
+ * Touch feedback. One pressed state for every tappable atom: scale to `--press-scale` and a gray
894
+ * tint over `--press-duration`. Our own hover styles sit inside `@media (hover: hover)` so a tap
895
+ * on a touch screen never leaves a sticky hover behind (Radix Themes scopes its own that way).
896
+ */
897
+ .ui-button { -webkit-tap-highlight-color: transparent; touch-action: manipulation; transition: transform var(--press-duration) ease-out, background-color var(--press-duration) ease-out; }
898
+ .ui-button:where(:active:not([data-disabled], :disabled)) { transform: scale(var(--press-scale)); }
899
+ .ui-button[data-variant='ghost']:where(:active:not([data-disabled], :disabled)), .ui-button[data-variant='secondary']:where(:active:not([data-disabled], :disabled)) { background-color: var(--accent-a5); }
900
+ .ui-button[data-size='touch'] { min-height: var(--tap-min); }
901
+ /* Icon-only buttons keep their visual size; the hit area grows with an invisible ::before. */
902
+ .ui-button[data-icon-only] { position: relative; }
903
+ @media (pointer: coarse) {
904
+ .ui-button[data-icon-only]::before { content: ''; position: absolute; top: 50%; left: 50%; width: max(100%, var(--tap-min)); height: max(100%, var(--tap-min)); transform: translate(-50%, -50%); }
905
+ /* iOS Safari zooms the page when a focused field is under 16px. */
906
+ .ui-input, .ui-input input, .ui-textarea, .ui-textarea textarea, .ui-select-trigger { font-size: 16px; }
907
+ }
908
+ @media (prefers-reduced-motion: reduce) {
909
+ .ui-button, .ui-list-row[data-interactive], .ui-tabbar__item, .ui-stat[data-interactive] { transition: none; }
910
+ .ui-button:active, .ui-list-row[data-interactive]:active, .ui-tabbar__item:active, .ui-stat[data-interactive]:active { transform: none; }
911
+ }