@rojaostudio/ds 2.0.0-next.3 → 2.0.0-next.31

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 (109) hide show
  1. package/README.md +42 -2
  2. package/THIRD_PARTY_NOTICES.md +66 -0
  3. package/dist/components/avatar.d.ts +20 -12
  4. package/dist/components/avatar.js +8 -6
  5. package/dist/components/badge.d.ts +7 -6
  6. package/dist/components/badge.js +2 -1
  7. package/dist/components/breadcrumb.d.ts +4 -4
  8. package/dist/components/breadcrumb.js +1 -1
  9. package/dist/components/bubble.d.ts +26 -11
  10. package/dist/components/bubble.js +3 -3
  11. package/dist/components/button.d.ts +1 -1
  12. package/dist/components/card.d.ts +28 -12
  13. package/dist/components/card.js +4 -2
  14. package/dist/components/chart.d.ts +18 -8
  15. package/dist/components/chart.js +89 -25
  16. package/dist/components/choice-carousel.d.ts +1 -1
  17. package/dist/components/choice-carousel.js +2 -4
  18. package/dist/components/choice-list.d.ts +40 -0
  19. package/dist/components/choice-list.js +122 -0
  20. package/dist/components/choice-preview-card.d.ts +1 -7
  21. package/dist/components/color-input.d.ts +1 -1
  22. package/dist/components/context-menu.d.ts +5 -2
  23. package/dist/components/currency-input.d.ts +0 -2
  24. package/dist/components/data-table-header.d.ts +55 -18
  25. package/dist/components/data-table-header.js +148 -101
  26. package/dist/components/date-picker.d.ts +1 -1
  27. package/dist/components/dialog.d.ts +6 -3
  28. package/dist/components/dialog.js +2 -2
  29. package/dist/components/dropdown-menu.d.ts +5 -2
  30. package/dist/components/dropzone.d.ts +2 -2
  31. package/dist/components/dropzone.js +1 -1
  32. package/dist/components/file-input.d.ts +13 -8
  33. package/dist/components/file-input.js +24 -21
  34. package/dist/components/filter-chip.d.ts +11 -5
  35. package/dist/components/filter-chip.js +15 -6
  36. package/dist/components/floating-stepper.d.ts +11 -28
  37. package/dist/components/floating-stepper.js +2 -30
  38. package/dist/components/form-actions.d.ts +45 -15
  39. package/dist/components/form-actions.js +33 -12
  40. package/dist/components/heading.d.ts +42 -0
  41. package/dist/components/heading.js +25 -0
  42. package/dist/components/icon-button.d.ts +1 -1
  43. package/dist/components/image-crop-dialog.d.ts +60 -0
  44. package/dist/components/image-crop-dialog.js +240 -0
  45. package/dist/components/image-crop-modal.d.ts +12 -55
  46. package/dist/components/image-crop-modal.js +2 -249
  47. package/dist/components/image-upload.d.ts +8 -17
  48. package/dist/components/image-upload.js +3 -3
  49. package/dist/components/index.d.ts +15 -10
  50. package/dist/components/index.js +10 -0
  51. package/dist/components/internal/bottom-bar.d.ts +33 -0
  52. package/dist/components/internal/bottom-bar.js +64 -0
  53. package/dist/components/internal/button.d.ts +1 -1
  54. package/dist/components/internal/icons.d.ts +11 -1
  55. package/dist/components/internal/icons.js +23 -0
  56. package/dist/components/internal/menu.d.ts +3 -2
  57. package/dist/components/internal/menu.js +1 -1
  58. package/dist/components/internal/modal.js +9 -0
  59. package/dist/components/internal/toggle.d.ts +1 -1
  60. package/dist/components/internal/use-on-screen-keyboard.d.ts +12 -0
  61. package/dist/components/internal/use-on-screen-keyboard.js +49 -0
  62. package/dist/components/item.d.ts +14 -7
  63. package/dist/components/item.js +5 -2
  64. package/dist/components/loading-overlay.d.ts +43 -0
  65. package/dist/components/loading-overlay.js +81 -0
  66. package/dist/components/marker.d.ts +11 -3
  67. package/dist/components/marker.js +4 -3
  68. package/dist/components/number-input.d.ts +1 -1
  69. package/dist/components/progress.d.ts +3 -3
  70. package/dist/components/progress.js +2 -2
  71. package/dist/components/row-actions.d.ts +3 -0
  72. package/dist/components/row-actions.js +8 -4
  73. package/dist/components/saving-bar.d.ts +38 -10
  74. package/dist/components/saving-bar.js +30 -7
  75. package/dist/components/section-header.d.ts +4 -3
  76. package/dist/components/selectable-card.d.ts +2 -10
  77. package/dist/components/sidebar.d.ts +8 -11
  78. package/dist/components/sidebar.js +4 -5
  79. package/dist/components/spinner.d.ts +9 -6
  80. package/dist/components/spinner.js +3 -3
  81. package/dist/components/star-rating.d.ts +3 -3
  82. package/dist/components/star-rating.js +2 -2
  83. package/dist/components/stat.d.ts +18 -6
  84. package/dist/components/stat.js +9 -3
  85. package/dist/components/status.d.ts +4 -4
  86. package/dist/components/status.js +2 -2
  87. package/dist/components/stepper.d.ts +33 -0
  88. package/dist/components/stepper.js +36 -0
  89. package/dist/components/summary-bar.d.ts +3 -2
  90. package/dist/components/summary-bar.js +10 -1
  91. package/dist/components/tile.d.ts +5 -5
  92. package/dist/components/tile.js +2 -2
  93. package/dist/components/time-picker.d.ts +1 -1
  94. package/dist/components/toast.d.ts +21 -8
  95. package/dist/components/toast.js +5 -3
  96. package/dist/components/toggle-card-compact.d.ts +6 -25
  97. package/dist/components/toggle-card-compact.js +8 -35
  98. package/dist/components/toggle-card.d.ts +23 -9
  99. package/dist/components/toggle-card.js +38 -2
  100. package/dist/components/toggle.d.ts +1 -1
  101. package/dist/components/typing-indicator.d.ts +2 -2
  102. package/dist/components/typing-indicator.js +1 -1
  103. package/package.json +4 -4
  104. package/styles/base.css +13 -1
  105. package/styles/rds/components-styles.css +799 -266
  106. package/styles/rds/components.css +57 -31
  107. package/styles/rds/foundation.css +1 -1
  108. package/styles/rds/theme.css +40 -29
  109. package/styles/rds.css +1 -1
@@ -554,7 +554,7 @@
554
554
  line-height: var(--type-body-line);
555
555
  }
556
556
 
557
- .rds-avatar--brand.rds-avatar--default {
557
+ .rds-avatar--brand.rds-avatar--md {
558
558
  font-size: var(--type-body-size);
559
559
  line-height: var(--type-body-line);
560
560
  }
@@ -665,8 +665,8 @@
665
665
  --_background: var(--badge-accent-fill-background);
666
666
  --_label: var(--badge-accent-fill-label);
667
667
  }
668
- /* The brand's highlighter: the one badge that reads as a marker. */
669
- .rds-badge--accent-highlight {
668
+ /* accent soft: the brand's highlighter, the one badge that reads as a marker (the old `highlight`). */
669
+ .rds-badge--accent-soft {
670
670
  --_background: var(--badge-accent-highlight-background);
671
671
  --_label: var(--badge-accent-highlight-label);
672
672
  }
@@ -1156,27 +1156,30 @@ button.rds-breadcrumb__link:focus-visible {
1156
1156
  --_text: var(--bubble-fill-text);
1157
1157
  }
1158
1158
 
1159
- .rds-bubble--muted {
1159
+ /* soft + neutral (the old `muted`): the one answering. */
1160
+ .rds-bubble--soft {
1160
1161
  --_background: var(--bubble-muted-background);
1161
1162
  --_text: var(--bubble-muted-text);
1162
1163
  }
1163
1164
 
1164
- .rds-bubble--tinted {
1165
+ /* soft + action (the old `tinted`): the one answering, on the brand tint. */
1166
+ .rds-bubble--soft.rds-bubble--action {
1165
1167
  --_background: var(--bubble-tinted-background);
1166
1168
  --_text: var(--bubble-tinted-text);
1167
1169
  }
1168
1170
 
1171
+ /* soft + danger (the old `error`): it was not sent. */
1172
+ .rds-bubble--soft.rds-bubble--danger {
1173
+ --_background: var(--bubble-error-background);
1174
+ --_text: var(--bubble-error-text);
1175
+ }
1176
+
1169
1177
  .rds-bubble--outline {
1170
1178
  --_background: var(--bubble-outline-background);
1171
1179
  --_text: var(--bubble-outline-text);
1172
1180
  border-color: var(--bubble-outline-border);
1173
1181
  }
1174
1182
 
1175
- .rds-bubble--error {
1176
- --_background: var(--bubble-error-background);
1177
- --_text: var(--bubble-error-text);
1178
- }
1179
-
1180
1183
  .rds-bubble--ghost {
1181
1184
  --_background: transparent;
1182
1185
  --_text: var(--bubble-ghost-text);
@@ -1749,34 +1752,45 @@ button.rds-breadcrumb__link:focus-visible {
1749
1752
  /* components/card.css */
1750
1753
  /* @tokens card */
1751
1754
  /*
1752
- * Card (Content collection, card/*): header, content and footer. default pads 16, sm pads 12. tint is the brand's
1753
- * light background, with no border. Corners in radius/container, shadow elevation/raised.
1755
+ * Card (Content collection, card/*): header, content and footer. md pads 24, sm pads 16; 24 between the
1756
+ * header, the content and the actions (sm: 16). Corners in radius/container. The Figma `variant`:
1757
+ * surface: card/background, a card/border hairline and elevation/raised (the default).
1758
+ * outline: only the hairline, no fill, no shadow; it takes the surface underneath (cards side by side in a grid,
1759
+ * inside a panel or a list, where stacked shadows turn into noise).
1760
+ * soft: the brand's light plate (card/tint/background), no border, no shadow, title in card/tint/title.
1761
+ * The footer has no band and no rule: the actions sit side by side, the main one last (on the right). The
1762
+ * card/footer/background tokens are obsolete in Figma (03/10/2026) and not read here.
1754
1763
  */
1755
1764
  .rds-card {
1756
- --_pad: var(--space-16);
1757
- --_background: var(--card-background);
1758
- --_footer: var(--card-footer-background);
1759
- --_border: var(--card-border);
1765
+ --_pad: var(--space-24);
1766
+ --_title: var(--card-title);
1760
1767
 
1761
1768
  box-sizing: border-box;
1762
1769
  display: flex;
1763
1770
  flex-direction: column;
1764
1771
  overflow: hidden;
1765
- border: var(--border-width) solid var(--_border);
1772
+ border: var(--border-width) solid var(--card-border);
1766
1773
  border-radius: var(--radius-container);
1767
- background: var(--_background);
1774
+ background: var(--card-background);
1768
1775
  box-shadow: var(--elevation-raised);
1769
1776
  font-family: var(--type-font-stack);
1770
1777
  }
1771
1778
 
1772
1779
  .rds-card--sm {
1773
- --_pad: var(--space-12);
1780
+ --_pad: var(--space-16);
1774
1781
  }
1775
1782
 
1776
- .rds-card--tint {
1777
- --_background: var(--card-tint-background);
1778
- --_footer: var(--card-tint-footer-background);
1779
- --_border: transparent;
1783
+ .rds-card--outline {
1784
+ background: transparent;
1785
+ box-shadow: none;
1786
+ }
1787
+
1788
+ .rds-card--soft {
1789
+ --_title: var(--card-tint-title);
1790
+
1791
+ border-color: transparent;
1792
+ background: var(--card-tint-background);
1793
+ box-shadow: none;
1780
1794
  }
1781
1795
 
1782
1796
  .rds-card__header {
@@ -1807,7 +1821,7 @@ button.rds-breadcrumb__link:focus-visible {
1807
1821
 
1808
1822
  .rds-card__title {
1809
1823
  margin: 0;
1810
- color: var(--card-title);
1824
+ color: var(--_title);
1811
1825
  font-size: var(--type-label-size);
1812
1826
  line-height: var(--type-label-line);
1813
1827
  font-weight: 500;
@@ -1846,32 +1860,27 @@ button.rds-breadcrumb__link:focus-visible {
1846
1860
  display: flex;
1847
1861
  flex-direction: column;
1848
1862
  gap: var(--space-16);
1849
- padding: var(--_pad);
1850
- border-top: var(--border-width) solid var(--card-border);
1851
- background: var(--_footer);
1852
- }
1853
-
1854
- .rds-card--tint .rds-card__footer {
1855
- border-top-color: transparent;
1863
+ padding: 0 var(--_pad) var(--_pad);
1856
1864
  }
1857
1865
 
1858
1866
  .rds-card__actions {
1859
1867
  display: flex;
1860
1868
  flex-wrap: wrap;
1861
- gap: var(--space-16);
1869
+ gap: var(--space-12);
1862
1870
  }
1863
1871
 
1864
1872
  .rds-card__footer--end .rds-card__actions {
1865
1873
  justify-content: flex-end;
1866
1874
  }
1867
1875
 
1876
+ /* full: the two actions side by side, half each, for a narrow card on a phone. */
1868
1877
  .rds-card__footer--full .rds-card__actions {
1869
- flex-direction: column;
1870
- gap: var(--space-8);
1878
+ flex-wrap: nowrap;
1871
1879
  }
1872
1880
 
1873
1881
  .rds-card__footer--full .rds-card__actions > * {
1874
- width: 100%;
1882
+ flex: 1 1 0;
1883
+ min-width: 0;
1875
1884
  }
1876
1885
 
1877
1886
  .rds-card__note {
@@ -1882,8 +1891,7 @@ button.rds-breadcrumb__link:focus-visible {
1882
1891
  }
1883
1892
 
1884
1893
  @media (forced-colors: active) {
1885
- .rds-card,
1886
- .rds-card--tint .rds-card__footer {
1894
+ .rds-card {
1887
1895
  border-color: CanvasText;
1888
1896
  }
1889
1897
  }
@@ -1992,6 +2000,8 @@ button.rds-breadcrumb__link:focus-visible {
1992
2000
  * in --_series: chart.tsx picks one of the --_series-N locals below, each one a chart/series-color/N token.
1993
2001
  */
1994
2002
  .rds-chart {
2003
+ /* Anchors the hidden alternative table (and any absolute part) to the chart, not to the page. */
2004
+ position: relative;
1995
2005
  --_series-1: var(--chart-series-color-1);
1996
2006
  --_series-2: var(--chart-series-color-2);
1997
2007
  --_series-3: var(--chart-series-color-3);
@@ -2180,14 +2190,31 @@ button.rds-breadcrumb__link:focus-visible {
2180
2190
  white-space: nowrap;
2181
2191
  }
2182
2192
 
2183
- .rds-chart__labels-track--line .rds-chart__label:first-child {
2193
+ .rds-chart__labels-track--line .rds-chart__label:first-of-type {
2184
2194
  transform: none;
2185
2195
  }
2186
2196
 
2187
- .rds-chart__labels-track--line .rds-chart__label:last-child {
2197
+ .rds-chart__labels-track--line .rds-chart__label:last-of-type {
2188
2198
  transform: translateX(-100%);
2189
2199
  }
2190
2200
 
2201
+ /* dateEvery: a 1x4 tick on every point, the labels under them. */
2202
+ .rds-chart__labels-track--ticks {
2203
+ height: calc(var(--type-caption-line) + var(--space-4));
2204
+ }
2205
+
2206
+ .rds-chart__labels-track--ticks .rds-chart__label {
2207
+ top: var(--space-4);
2208
+ }
2209
+
2210
+ .rds-chart__tick {
2211
+ position: absolute;
2212
+ top: 0;
2213
+ width: 1px;
2214
+ height: var(--space-4);
2215
+ background: var(--chart-tick);
2216
+ }
2217
+
2191
2218
  /* Bars: label, track, value. */
2192
2219
  .rds-chart__bars {
2193
2220
  display: flex;
@@ -2218,6 +2245,50 @@ button.rds-breadcrumb__link:focus-visible {
2218
2245
  background: var(--_series);
2219
2246
  }
2220
2247
 
2248
+ /* A bar with a destination (hrefs or onSelect): the row is the link or button. */
2249
+ .rds-chart__bar-row--link {
2250
+ box-sizing: border-box;
2251
+ width: 100%;
2252
+ margin: 0;
2253
+ padding: 0;
2254
+ border: 0;
2255
+ border-radius: var(--radius-focus);
2256
+ background: none;
2257
+ color: inherit;
2258
+ font: inherit;
2259
+ text-align: start;
2260
+ text-decoration: none;
2261
+ cursor: pointer;
2262
+ }
2263
+
2264
+ .rds-chart__bar-row--link:hover .rds-chart__track {
2265
+ background: var(--chart-bar-hover);
2266
+ }
2267
+
2268
+ .rds-chart__bar-row--link:hover .rds-chart__bar-label {
2269
+ text-decoration: underline;
2270
+ }
2271
+
2272
+ .rds-chart__bar-row--link:focus-visible,
2273
+ .rds-chart__table-link:focus-visible {
2274
+ outline: var(--focus-ring-width) solid var(--chart-focus-ring);
2275
+ outline-offset: var(--focus-ring-width);
2276
+ }
2277
+
2278
+ .rds-chart--linked.rds-chart--column .rds-chart__plot {
2279
+ cursor: pointer;
2280
+ }
2281
+
2282
+ .rds-chart__table-link {
2283
+ padding: 0;
2284
+ border: 0;
2285
+ background: none;
2286
+ color: inherit;
2287
+ font: inherit;
2288
+ text-decoration: underline;
2289
+ cursor: pointer;
2290
+ }
2291
+
2221
2292
  .rds-chart__bar-value {
2222
2293
  color: var(--chart-axis);
2223
2294
  font-variant-numeric: tabular-nums;
@@ -2251,7 +2322,8 @@ button.rds-breadcrumb__link:focus-visible {
2251
2322
  background: CanvasText;
2252
2323
  }
2253
2324
 
2254
- .rds-chart__plot:focus-visible {
2325
+ .rds-chart__plot:focus-visible,
2326
+ .rds-chart__bar-row--link:focus-visible {
2255
2327
  outline-color: Highlight;
2256
2328
  }
2257
2329
  }
@@ -2608,10 +2680,10 @@ input:focus-visible + .rds-checkbox__box {
2608
2680
  * an 8 dot. Selected fills the card with the brand. Disabled is the same card at half opacity (as in Figma).
2609
2681
  * tile: a grid cell, 16 inside, centred: the icon, then the label 14/20 semibold and the description 12/16 (8 below
2610
2682
  * the icon). Selected fills it with the brand, the icon square at 10% of choice-card/icon/background/selected, the
2611
- * description at 70%, and a 16 check (11 glyph) 8 from the top right corner.
2683
+ * description at full opacity, and a 16 check (11 glyph) 8 from the top right corner.
2612
2684
  * preview: 8 inside, the picture on top (16:9, a 1px border, corners radius/container, a 24 placeholder icon), then
2613
2685
  * the label 16/24 semibold and the description 14/20, 4 in from the sides. Selected keeps the surface: a 2px border
2614
- * in the brand, the description at 70% and a 20 check (12 glyph) in the picture's bottom right corner.
2686
+ * in the brand, the description at full opacity and a 20 check (12 glyph) in the picture's bottom right corner.
2615
2687
  * The group stacks rows 8 apart; tiles and previews go in a grid (cells of at least 160 and 240), 8 apart.
2616
2688
  */
2617
2689
  .rds-choice-card-group {
@@ -2803,11 +2875,6 @@ input:focus-visible + .rds-checkbox__box {
2803
2875
  color: var(--choice-card-icon-color-selected);
2804
2876
  }
2805
2877
 
2806
- .rds-choice-card--tile.rds-choice-card--selected .rds-choice-card__description,
2807
- .rds-choice-card--preview.rds-choice-card--selected .rds-choice-card__description {
2808
- color: color-mix(in srgb, var(--_description) 70%, transparent);
2809
- }
2810
-
2811
2878
  .rds-choice-card--tile .rds-choice-card__check {
2812
2879
  position: absolute;
2813
2880
  top: calc(var(--space-8) - var(--border-width));
@@ -2914,7 +2981,7 @@ input:focus-visible + .rds-checkbox__box {
2914
2981
  /*
2915
2982
  * ChoiceCarousel: no tokens of its own; the IconButtons bring theirs. A row that scrolls sideways and snaps to each
2916
2983
  * option (160 wide, 200 from 768), 12 apart, no scrollbar. From 768 the outline arrows sit on the row's edges, half
2917
- * outside, and fade away when there is nothing more that way.
2984
+ * outside, and are not there when there is nothing more that way.
2918
2985
  */
2919
2986
  .rds-choice-carousel {
2920
2987
  position: relative;
@@ -2968,7 +3035,6 @@ input:focus-visible + .rds-checkbox__box {
2968
3035
  display: inline-flex;
2969
3036
  border-radius: var(--radius-full);
2970
3037
  box-shadow: var(--elevation-raised);
2971
- transition: opacity var(--motion-duration-base) var(--motion-easing-standard);
2972
3038
  }
2973
3039
 
2974
3040
  .rds-choice-carousel__arrow--prev {
@@ -2980,11 +3046,6 @@ input:focus-visible + .rds-checkbox__box {
2980
3046
  right: 0;
2981
3047
  transform: translate(50%, -50%);
2982
3048
  }
2983
-
2984
- .rds-choice-carousel__arrow[aria-disabled='true'] {
2985
- opacity: 0;
2986
- pointer-events: none;
2987
- }
2988
3049
  }
2989
3050
 
2990
3051
  @media (prefers-reduced-motion: reduce) {
@@ -2993,6 +3054,132 @@ input:focus-visible + .rds-checkbox__box {
2993
3054
  }
2994
3055
  }
2995
3056
 
3057
+ /* components/choice-list.css */
3058
+ /* @tokens choice-list */
3059
+ /*
3060
+ * ChoiceList (Content collection, choice-list/*): the dense list to choose one from. Each row pads 12 16 with 12
3061
+ * between media, text and trailing; a line of border-width only at the bottom (padding-bottom gives it back, so the
3062
+ * row is 60 with a description, 44 without). Title small medium, description caption, trailing small.
3063
+ * Hover: choice-list/item/background/hover. Chosen: the tint and a bar of border-width-strong on the left, no hover.
3064
+ * Focus: the list holds it (aria-activedescendant); the active row draws the ring inside its box, as the rows touch.
3065
+ * Disabled: text in the disabled tokens, media at half; it stays chosen if it was.
3066
+ */
3067
+ .rds-choice-list {
3068
+ box-sizing: border-box;
3069
+ margin: 0;
3070
+ padding: 0;
3071
+ overflow-y: auto;
3072
+ font-family: var(--type-font-stack);
3073
+ list-style: none;
3074
+ outline: none;
3075
+ }
3076
+
3077
+ .rds-choice-list__item {
3078
+ --_background: transparent;
3079
+ --_title: var(--choice-list-item-title-default);
3080
+ --_description: var(--choice-list-item-description-default);
3081
+ --_trailing: var(--choice-list-item-trailing-default);
3082
+
3083
+ box-sizing: border-box;
3084
+ display: flex;
3085
+ align-items: center;
3086
+ gap: var(--space-12);
3087
+ min-height: calc(var(--space-12) * 2 + var(--type-button-line));
3088
+ padding: var(--space-12) var(--space-16) calc(var(--space-12) - var(--border-width));
3089
+ border-bottom: var(--border-width) solid var(--choice-list-item-border);
3090
+ background: var(--_background);
3091
+ cursor: pointer;
3092
+ user-select: none;
3093
+ }
3094
+
3095
+ @media (hover: hover) {
3096
+ .rds-choice-list__item:not([aria-selected='true'], [aria-disabled='true']):hover {
3097
+ --_background: var(--choice-list-item-background-hover);
3098
+ }
3099
+ }
3100
+
3101
+ .rds-choice-list__item[aria-selected='true'] {
3102
+ --_background: var(--choice-list-item-background-selected);
3103
+ /* On the tint the muted line does not hold contrast in dark: it takes text/on/tint. */
3104
+ --_description: var(--choice-list-item-description-selected);
3105
+
3106
+ box-shadow: inset var(--border-width-strong) 0 0 var(--choice-list-item-indicator);
3107
+ }
3108
+
3109
+ .rds-choice-list:focus-visible .rds-choice-list__item[data-active] {
3110
+ outline: var(--focus-ring-width) solid var(--choice-list-focus-ring);
3111
+ outline-offset: calc(-1 * var(--focus-ring-width));
3112
+ }
3113
+
3114
+ .rds-choice-list__item[aria-disabled='true'] {
3115
+ --_title: var(--choice-list-item-title-disabled);
3116
+ --_description: var(--choice-list-item-description-disabled);
3117
+ --_trailing: var(--choice-list-item-trailing-disabled);
3118
+
3119
+ cursor: not-allowed;
3120
+ }
3121
+
3122
+ .rds-choice-list__media {
3123
+ display: inline-flex;
3124
+ flex: none;
3125
+ }
3126
+
3127
+ .rds-choice-list__item[aria-disabled='true'] .rds-choice-list__media {
3128
+ opacity: 0.5;
3129
+ }
3130
+
3131
+ .rds-choice-list__content {
3132
+ display: flex;
3133
+ flex: 1;
3134
+ flex-direction: column;
3135
+ min-width: 0;
3136
+ }
3137
+
3138
+ .rds-choice-list__title,
3139
+ .rds-choice-list__description {
3140
+ overflow: hidden;
3141
+ text-overflow: ellipsis;
3142
+ white-space: nowrap;
3143
+ }
3144
+
3145
+ .rds-choice-list__title {
3146
+ color: var(--_title);
3147
+ font-size: var(--type-small-size);
3148
+ line-height: var(--type-small-line);
3149
+ font-weight: 500;
3150
+ }
3151
+
3152
+ .rds-choice-list__description {
3153
+ color: var(--_description);
3154
+ font-size: var(--type-caption-size);
3155
+ line-height: var(--type-caption-line);
3156
+ }
3157
+
3158
+ .rds-choice-list__trailing {
3159
+ flex: none;
3160
+ color: var(--_trailing);
3161
+ font-size: var(--type-small-size);
3162
+ line-height: var(--type-small-line);
3163
+ font-variant-numeric: tabular-nums;
3164
+ text-align: right;
3165
+ }
3166
+
3167
+ @media (forced-colors: active) {
3168
+ .rds-choice-list__item[aria-selected='true'] {
3169
+ forced-color-adjust: none;
3170
+ background: Highlight;
3171
+ color: HighlightText;
3172
+ }
3173
+
3174
+ .rds-choice-list__item[aria-selected='true'] :is(.rds-choice-list__title, .rds-choice-list__description, .rds-choice-list__trailing) {
3175
+ color: HighlightText;
3176
+ }
3177
+
3178
+ .rds-choice-list:focus-visible .rds-choice-list__item[data-active] {
3179
+ outline-color: CanvasText;
3180
+ }
3181
+ }
3182
+
2996
3183
  /* components/color-input.css */
2997
3184
  /* @tokens color-input */
2998
3185
  /*
@@ -3045,7 +3232,7 @@ input:focus-visible + .rds-checkbox__box {
3045
3232
  .rds-color-input__swatch:focus-visible,
3046
3233
  .rds-color-input__swatch:has(.rds-color-input__native:focus-visible) {
3047
3234
  outline: var(--focus-ring-width) solid var(--_border-focus);
3048
- outline-offset: var(--border-width);
3235
+ outline-offset: var(--focus-ring-width);
3049
3236
  }
3050
3237
 
3051
3238
  .rds-color-input__native {
@@ -3112,14 +3299,15 @@ input:focus-visible + .rds-checkbox__box {
3112
3299
  cursor: pointer;
3113
3300
  }
3114
3301
 
3302
+ /* Selected and focus: the ring of Button and Checkbox, focus-ring-width wide and as far off the swatch (a gap). */
3115
3303
  .rds-color-input__choice[aria-pressed='true'] {
3116
- outline: calc(var(--border-width) * 2) solid var(--color-input-swatch-selected);
3117
- outline-offset: var(--border-width);
3304
+ outline: var(--focus-ring-width) solid var(--color-input-swatch-selected);
3305
+ outline-offset: var(--focus-ring-width);
3118
3306
  }
3119
3307
 
3120
3308
  .rds-color-input__choice:focus-visible {
3121
3309
  outline: var(--focus-ring-width) solid var(--color-input-border-focus);
3122
- outline-offset: var(--border-width);
3310
+ outline-offset: var(--focus-ring-width);
3123
3311
  }
3124
3312
 
3125
3313
  @media (forced-colors: active) {
@@ -3394,23 +3582,79 @@ input:focus-visible + .rds-checkbox__box {
3394
3582
  /* components/data-table-header.css */
3395
3583
  /* @tokens data-table-header */
3396
3584
  /*
3397
- * DataTableHeader: no tokens of its own; the Input, FilterChip, Chip, Button, Badge, Separator, DropdownMenu,
3398
- * Popover and Drawer bring theirs. One row, 8 apart, 12 above the table; the search takes the free width. The wide
3399
- * parts show from 768, the narrow ones below it. In the Popover and the Drawer the filters stack 16 apart, each
3400
- * one a caption-sized label over its chips.
3585
+ * DataTableHeader (Figma [RDS] DataTableHeader, no variants). One component token, local to this stylesheet:
3586
+ * --data-table-header-search-min, the search's minimum width (Figma `data-table-header/search-min`, viewport
3587
+ * collection of the Base Tokens, not published yet): 320 from lg 1024, 200 below it. Everything else comes from the
3588
+ * Input, FilterChip, Chip, Button, IconButton, Checkbox, DropdownMenu, Popover and Drawer; the count borrows the
3589
+ * table's muted label (--table-header-label, text/muted), the bar being the table's.
3590
+ *
3591
+ * The bar is a column, 8 apart, 12 above the table:
3592
+ * - `row`, which never wraps, aligned to the top: the `tools` group (the search, the quick filters, the filter
3593
+ * trigger, the view control, the count) takes the free width and is what wraps, packed to the start, the search
3594
+ * first taking the free width, at least search-min (never wider than the group); the action sits outside it,
3595
+ * fixed at the end of the FIRST line, on the right, and never goes down.
3596
+ * - `active`, only while a filter is on: the `chips` (wrapping, at least 280 before "Limpar filtros" goes down)
3597
+ * and "Limpar filtros" at the end.
3598
+ * Two arrangements, by the screen width, as the Figma viewport mode (layout/compact below lg 1024; the SavingBar's
3599
+ * cut): expanded from 1024 (the __wide parts: the trigger as a Button with its label); compact below it (the __narrow
3600
+ * parts: the trigger as an IconButton of 44, or a fill Button with the number while a filter is on).
3601
+ * In the Popover and the Drawer the filters stack 16 apart, each one a caption-sized label over its chips.
3401
3602
  */
3402
3603
  .rds-data-table-header {
3604
+ --data-table-header-search-min: 320px;
3605
+
3606
+ box-sizing: border-box;
3607
+ width: 100%;
3608
+ display: flex;
3609
+ flex-direction: column;
3610
+ gap: var(--space-8);
3611
+ margin-bottom: var(--space-12);
3612
+ }
3613
+
3614
+ @media (max-width: 1023px) {
3615
+ .rds-data-table-header {
3616
+ --data-table-header-search-min: 200px;
3617
+ }
3618
+ }
3619
+
3620
+ /* Figma `row`: tools + actions, never wraps. */
3621
+ .rds-data-table-header__row {
3622
+ display: flex;
3623
+ flex-wrap: nowrap;
3624
+ align-items: flex-start;
3625
+ gap: var(--space-8);
3626
+ }
3627
+
3628
+ /* Figma `tools`: horizontal, wrap, fill, packed to the start. */
3629
+ .rds-data-table-header__tools {
3630
+ flex: 1 1 0;
3631
+ min-width: 0;
3403
3632
  display: flex;
3404
3633
  flex-wrap: wrap;
3405
3634
  align-items: center;
3635
+ justify-content: flex-start;
3406
3636
  gap: var(--space-8);
3407
- margin-bottom: var(--space-12);
3408
3637
  }
3409
3638
 
3639
+ /* Figma `actions`: outside `tools`, at the end of the first line. */
3640
+ .rds-data-table-header__actions {
3641
+ flex: none;
3642
+ align-self: flex-start;
3643
+ }
3644
+
3645
+ /* The search takes the free width, at least search-min, never wider than the group: it wraps before it squeezes. */
3410
3646
  .rds-data-table-header__search {
3411
- flex: 1 1 calc(var(--space-64) * 4);
3647
+ flex: 1 1 var(--data-table-header-search-min);
3648
+ min-width: min(var(--data-table-header-search-min), 100%);
3649
+ display: flex;
3650
+ }
3651
+
3652
+ .rds-data-table-header__search > * {
3653
+ flex: 1 1 auto;
3412
3654
  }
3413
3655
 
3656
+ .rds-data-table-header__quick,
3657
+ .rds-data-table-header__view,
3414
3658
  .rds-data-table-header__wide,
3415
3659
  .rds-data-table-header__actions,
3416
3660
  .rds-data-table-header__narrow {
@@ -3420,20 +3664,47 @@ input:focus-visible + .rds-checkbox__box {
3420
3664
  gap: var(--space-8);
3421
3665
  }
3422
3666
 
3423
- .rds-data-table-header__wide {
3667
+ .rds-data-table-header__narrow {
3424
3668
  display: none;
3425
3669
  }
3426
3670
 
3427
- @media (min-width: 768px) {
3671
+ @media (max-width: 1023px) {
3428
3672
  .rds-data-table-header__wide {
3429
- display: flex;
3673
+ display: none;
3430
3674
  }
3431
3675
 
3432
3676
  .rds-data-table-header__narrow {
3433
- display: none;
3677
+ display: flex;
3434
3678
  }
3435
3679
  }
3436
3680
 
3681
+ /* Figma `count`: "128 resultados", a live region at the end of the tools. */
3682
+ .rds-data-table-header__count {
3683
+ font-family: var(--type-font-stack);
3684
+ font-size: var(--type-small-size);
3685
+ line-height: var(--type-small-line);
3686
+ color: var(--table-header-label);
3687
+ white-space: nowrap;
3688
+ }
3689
+
3690
+ /* Figma `activeFilters`: its own line, wrap, 8 apart. */
3691
+ .rds-data-table-header__active {
3692
+ display: flex;
3693
+ flex-wrap: wrap;
3694
+ align-items: center;
3695
+ gap: var(--space-8);
3696
+ }
3697
+
3698
+ /* Figma `chips`: fill, wrap, at least 280 before "Limpar filtros" goes down. */
3699
+ .rds-data-table-header__chips {
3700
+ flex: 1 1 280px;
3701
+ min-width: 0;
3702
+ display: flex;
3703
+ flex-wrap: wrap;
3704
+ align-items: center;
3705
+ gap: var(--space-8);
3706
+ }
3707
+
3437
3708
  .rds-data-table-header__scroll {
3438
3709
  max-height: 70vh;
3439
3710
  overflow-y: auto;
@@ -3590,6 +3861,8 @@ input:focus-visible + .rds-checkbox__box {
3590
3861
  * Drawer (Overlays collection, drawer/*): stuck to the bottom, the top corners in radius/container; 12 above (the
3591
3862
  * handle, 40 × 4), 24 on the sides, 32 below, 20 between parts; no border and no ×. On a wide screen it stops at
3592
3863
  * 560 and centres (the Figma draws it on a 390 phone only).
3864
+ * Height by the content, up to 85% of the screen (717 on an 844): past it, only the content scrolls inside; the
3865
+ * handle, the title and the footer stay put.
3593
3866
  */
3594
3867
  .rds-drawer__scrim {
3595
3868
  background: var(--drawer-scrim);
@@ -3601,7 +3874,7 @@ input:focus-visible + .rds-checkbox__box {
3601
3874
  left: 0;
3602
3875
  gap: calc(var(--space-16) + var(--space-4));
3603
3876
  max-width: 560px;
3604
- max-height: calc(100dvh - var(--space-48));
3877
+ max-height: 85dvh;
3605
3878
  margin-inline: auto;
3606
3879
  padding: var(--space-12) var(--space-24) var(--space-32);
3607
3880
  border-radius: var(--radius-container) var(--radius-container) 0 0;
@@ -3625,6 +3898,18 @@ input:focus-visible + .rds-checkbox__box {
3625
3898
  background: var(--drawer-handle);
3626
3899
  }
3627
3900
 
3901
+ .rds-drawer .rds-modal__header,
3902
+ .rds-drawer .rds-modal__footer {
3903
+ flex: none;
3904
+ }
3905
+
3906
+ .rds-drawer .rds-modal__body {
3907
+ flex: 1;
3908
+ min-height: 0;
3909
+ overflow-y: auto;
3910
+ overscroll-behavior: contain;
3911
+ }
3912
+
3628
3913
  .rds-drawer .rds-modal__heading {
3629
3914
  padding-top: 0;
3630
3915
  }
@@ -4105,7 +4390,7 @@ input:focus-visible + .rds-checkbox__box {
4105
4390
  * FilterChip (Forms collection, filter-chip/*): 32 tall, pill, 12 inside, 4 between icon, label and count;
4106
4391
  * label 14/20 medium. inactive: card fill and a hairline; hover: muted fill, strong hairline; active: the brand
4107
4392
  * at 12% over what is behind, brand border and label; disabled: the whole chip at 50%, the label at 40%.
4108
- * The count reads at 60% of the label. Icon 14, in the label's colour.
4393
+ * The count reads in the label's colour, at full opacity. Icon 14, in the label's colour.
4109
4394
  */
4110
4395
  .rds-filter-chip-group {
4111
4396
  display: flex;
@@ -4149,14 +4434,14 @@ input:focus-visible + .rds-checkbox__box {
4149
4434
  }
4150
4435
 
4151
4436
  @media (hover: hover) {
4152
- .rds-filter-chip:not(.rds-filter-chip--active, [aria-disabled='true']):hover {
4437
+ .rds-filter-chip:not(.rds-filter-chip--pressed, [aria-disabled='true']):hover {
4153
4438
  --_surface: var(--filter-chip-surface-hover);
4154
4439
  --_stroke: var(--filter-chip-stroke-hover);
4155
4440
  --_text: var(--filter-chip-text-hover);
4156
4441
  }
4157
4442
  }
4158
4443
 
4159
- .rds-filter-chip--active {
4444
+ .rds-filter-chip--pressed {
4160
4445
  --_surface: color-mix(in srgb, var(--filter-chip-surface-active) 12%, transparent);
4161
4446
  --_stroke: var(--filter-chip-stroke-active);
4162
4447
  --_text: var(--filter-chip-text-active);
@@ -4196,7 +4481,6 @@ input:focus-visible + .rds-checkbox__box {
4196
4481
  }
4197
4482
 
4198
4483
  .rds-filter-chip__count {
4199
- color: color-mix(in srgb, currentColor 60%, transparent);
4200
4484
  font-variant-numeric: tabular-nums;
4201
4485
  }
4202
4486
 
@@ -4205,7 +4489,7 @@ input:focus-visible + .rds-checkbox__box {
4205
4489
  border-color: CanvasText;
4206
4490
  }
4207
4491
 
4208
- .rds-filter-chip--active {
4492
+ .rds-filter-chip--pressed {
4209
4493
  border-color: Highlight;
4210
4494
  outline: var(--border-width) solid Highlight;
4211
4495
  }
@@ -4215,38 +4499,6 @@ input:focus-visible + .rds-checkbox__box {
4215
4499
  }
4216
4500
  }
4217
4501
 
4218
- /* components/floating-stepper.css */
4219
- /* @tokens floating-stepper */
4220
- /*
4221
- * FloatingStepper: no tokens of its own; the Card and the Buttons bring theirs. A pill (radius/full) of 44 Buttons,
4222
- * 4 inside and 4 apart, raised by elevation/overlay because it floats over the page. A 1 × 24 line in the card's
4223
- * border colour before the action.
4224
- */
4225
- .rds-floating-stepper {
4226
- flex-direction: row;
4227
- align-items: center;
4228
- gap: var(--space-4);
4229
- width: max-content;
4230
- max-width: 100%;
4231
- padding: var(--space-4);
4232
- border-radius: var(--radius-full);
4233
- box-shadow: var(--elevation-overlay);
4234
- overflow-x: auto;
4235
- }
4236
-
4237
- .rds-floating-stepper > .rds-button {
4238
- flex: none;
4239
- border-radius: var(--radius-full);
4240
- }
4241
-
4242
- .rds-floating-stepper__divider {
4243
- flex: none;
4244
- width: var(--border-width);
4245
- height: var(--size-24);
4246
- margin-inline: var(--space-4);
4247
- background: var(--card-border);
4248
- }
4249
-
4250
4502
  /* components/footer.css */
4251
4503
  /* @tokens footer */
4252
4504
  /*
@@ -4390,77 +4642,42 @@ input:focus-visible + .rds-checkbox__box {
4390
4642
  width: auto;
4391
4643
  }
4392
4644
  }
4393
-
4394
- @media (forced-colors: active) {
4395
- .rds-footer a:focus-visible {
4396
- outline-color: Highlight;
4397
- }
4398
- }
4399
-
4400
- /* components/form-actions.css */
4401
- /* @tokens form-actions */
4402
- /*
4403
- * FormActions (Actions collection, form-actions/*): the actions at the end of a form, on the card
4404
- * surface with a hairline. inline floats (container radius, raised elevation, 16 24 padding, 24 between
4405
- * sentence and actions); stacked sticks to the foot edge to edge (16 padding, hairline on top).
4406
- */
4407
- .rds-form-actions {
4408
- box-sizing: border-box;
4409
- display: flex;
4410
- align-items: center;
4411
- background: var(--form-actions-background);
4412
- color: var(--form-actions-text);
4413
- font-family: var(--type-font-stack);
4414
- }
4415
-
4416
- .rds-form-actions__helper {
4417
- flex: 1;
4418
- min-width: 0;
4419
- margin: 0;
4420
- font-size: var(--type-label-size);
4421
- line-height: var(--type-label-line);
4422
- }
4423
-
4424
- .rds-form-actions__actions {
4425
- display: flex;
4426
- flex-wrap: wrap;
4427
- gap: var(--space-8);
4428
- }
4429
-
4430
- /* inline: floats and hugs its content; the page decides where. */
4431
- .rds-form-actions--inline {
4432
- display: inline-flex;
4433
- flex-wrap: wrap;
4434
- justify-content: flex-end;
4435
- gap: var(--space-24);
4436
- max-width: 100%;
4437
- padding: var(--space-16) var(--space-24);
4438
- border: var(--border-width) solid var(--form-actions-border);
4439
- border-radius: var(--radius-container);
4440
- box-shadow: var(--elevation-raised);
4645
+
4646
+ @media (forced-colors: active) {
4647
+ .rds-footer a:focus-visible {
4648
+ outline-color: Highlight;
4649
+ }
4441
4650
  }
4442
4651
 
4443
- /* stacked: edge to edge at the foot, the buttons full width. */
4444
- .rds-form-actions--stacked {
4445
- flex-direction: column;
4446
- align-items: stretch;
4652
+ /* components/form-actions.css */
4653
+ /* @tokens bottom-bar */
4654
+ /*
4655
+ * FormActions: no tokens of its own; the shell (internal/bottom-bar.css, bottom-bar/*) brings the colour, the height,
4656
+ * the padding, the place and the Buttons' colours (the X too: the neutral ghost reads bottom-bar/button/ghost/label,
4657
+ * its hover that colour at 15%, its ring bottom-bar/focus/ring). Here only the actions: on the right, 8 apart,
4658
+ * Cancelar then the primary. Compact (below lg 1024, by the screen width as the Figma viewport mode), Cancelar is the
4659
+ * X (an IconButton) and the primary; the actions between them are not shown.
4660
+ */
4661
+ .rds-form-actions__actions {
4662
+ display: flex;
4663
+ flex: none;
4447
4664
  gap: var(--space-8);
4448
- width: 100%;
4449
- padding: var(--space-16);
4450
- border-top: var(--border-width) solid var(--form-actions-border);
4665
+ margin-inline-start: auto;
4451
4666
  }
4452
4667
 
4453
- .rds-form-actions--stacked .rds-form-actions__actions {
4454
- flex-direction: column;
4668
+ /* Expanded: the labelled Cancelar; the X is the compact one. */
4669
+ .rds-form-actions__actions > .rds-form-actions__cancel-icon {
4670
+ display: none;
4455
4671
  }
4456
4672
 
4457
- .rds-form-actions--stacked .rds-form-actions__actions > * {
4458
- width: 100%;
4459
- }
4673
+ @media (max-width: 1023px) {
4674
+ /* The X and the primary (the last action): every other action leaves. */
4675
+ .rds-form-actions__actions > :not(:last-child) {
4676
+ display: none;
4677
+ }
4460
4678
 
4461
- @media (forced-colors: active) {
4462
- .rds-form-actions {
4463
- border-color: CanvasText;
4679
+ .rds-form-actions__actions > .rds-form-actions__cancel-icon {
4680
+ display: inline-flex;
4464
4681
  }
4465
4682
  }
4466
4683
 
@@ -4595,6 +4812,48 @@ input:focus-visible + .rds-checkbox__box {
4595
4812
  }
4596
4813
  }
4597
4814
 
4815
+ /* components/heading.css */
4816
+ /* @tokens heading */
4817
+ /*
4818
+ * Heading (Content collection, heading/*): a title in the brand pair. heading/default is text/heading, heading/accent
4819
+ * the logo orange; .heading/mark paints a stretch in the other one. level follows the type scale (band, heading,
4820
+ * value), all bold.
4821
+ */
4822
+ .rds-heading {
4823
+ margin: 0;
4824
+ font-family: var(--type-font-stack);
4825
+ font-weight: var(--type-heading-weight);
4826
+ color: var(--heading-default);
4827
+ text-wrap: balance;
4828
+ }
4829
+
4830
+ .rds-heading--band {
4831
+ font-size: var(--type-band-size);
4832
+ line-height: var(--type-band-line);
4833
+ }
4834
+
4835
+ .rds-heading--heading {
4836
+ font-size: var(--type-heading-size);
4837
+ line-height: var(--type-heading-line);
4838
+ }
4839
+
4840
+ .rds-heading--value {
4841
+ font-size: var(--type-value-size);
4842
+ line-height: var(--type-value-line);
4843
+ }
4844
+
4845
+ .rds-heading--accent {
4846
+ color: var(--heading-accent);
4847
+ }
4848
+
4849
+ .rds-heading__mark {
4850
+ color: var(--heading-accent);
4851
+ }
4852
+
4853
+ .rds-heading--accent .rds-heading__mark {
4854
+ color: var(--heading-default);
4855
+ }
4856
+
4598
4857
  /* components/hover-card.css */
4599
4858
  /* @tokens hovercard */
4600
4859
  /* HoverCard (Feedback collection, hovercard/*): 320 wide, 16 inside, 12 between avatar and text, elevation/overlay. */
@@ -4669,13 +4928,14 @@ input:focus-visible + .rds-checkbox__box {
4669
4928
  }
4670
4929
  }
4671
4930
 
4672
- /* components/image-crop-modal.css */
4673
- /* @tokens image-crop-modal */
4931
+ /* components/image-crop-dialog.css */
4932
+ /* @tokens image-crop-dialog */
4674
4933
  /*
4675
- * ImageCropModal: no tokens of its own; the Dialog, the ToggleGroup, the Alert and the Spinner bring theirs. 12
4676
- * apart: the presets (they share the width), the stage (at least 300, at most 60% of the viewport, the image
4677
- * letterboxed inside 16 of padding, a line in the dialog's border colour), the error or the hint. While sending,
4678
- * the dialog's scrim covers the image.
4934
+ * ImageCropDialog (Figma [RDS] Overlays/ImageCropDialog): the Dialog, the ToggleGroup, the Alert and the Spinner bring
4935
+ * their tokens; the crop brings its own (Overlays, image-crop-dialog/*). 12 apart: the presets (they share the
4936
+ * width), the stage (320 tall, on image-crop-dialog/stage/background, the image letterboxed inside 16 of padding, a
4937
+ * line in the dialog's border colour), the error or the hint. Over the image, outside the crop, the shade; the crop's
4938
+ * line and its handles in their own colours. While sending, the dialog's scrim covers the stage.
4679
4939
  */
4680
4940
  .rds-image-crop {
4681
4941
  display: flex;
@@ -4698,17 +4958,42 @@ input:focus-visible + .rds-checkbox__box {
4698
4958
  display: flex;
4699
4959
  align-items: center;
4700
4960
  justify-content: center;
4701
- min-height: 300px;
4961
+ height: 320px;
4962
+ /* On a short viewport (a phone on its side) the stage gives way so the footer stays in view. */
4702
4963
  max-height: 60vh;
4703
4964
  padding: var(--space-16);
4704
4965
  overflow: hidden;
4966
+ background: var(--image-crop-dialog-stage-background);
4705
4967
  border: var(--border-width) solid var(--dialog-border);
4706
4968
  border-radius: var(--radius-control);
4707
4969
  }
4708
4970
 
4971
+ /*
4972
+ * react-image-crop's own stylesheet is unlayered, so it wins over these layered rules wherever both set the same
4973
+ * property. The shade is an SVG rect with fill as an attribute (black at 50%): any CSS beats it. The handles read
4974
+ * the library's variables, set here. The selection's marching ants are hard-coded: the two !important take them
4975
+ * off so the crop is one solid line in the selection colour (the library's focus outline stays).
4976
+ */
4709
4977
  .rds-image-crop__crop {
4710
4978
  max-width: 100%;
4711
- max-height: calc(60vh - var(--space-32));
4979
+ max-height: calc(min(320px, 60vh) - var(--space-32));
4980
+ --rc-drag-handle-bg-colour: var(--image-crop-dialog-handle);
4981
+ --rc-border-color: var(--image-crop-dialog-handle);
4982
+ }
4983
+
4984
+ .rds-image-crop__crop .ReactCrop__crop-mask > rect {
4985
+ fill: var(--image-crop-dialog-shade);
4986
+ fill-opacity: 1;
4987
+ }
4988
+
4989
+ .rds-image-crop__crop .ReactCrop__crop-selection {
4990
+ background-image: none !important;
4991
+ border: var(--border-width) solid var(--image-crop-dialog-selection);
4992
+ animation: none !important;
4993
+ }
4994
+
4995
+ .rds-image-crop__crop .ReactCrop__drag-handle {
4996
+ border-radius: var(--radius-xs);
4712
4997
  }
4713
4998
 
4714
4999
  .rds-image-crop__image {
@@ -5116,6 +5401,133 @@ input:focus-visible + .rds-checkbox__box {
5116
5401
  }
5117
5402
  }
5118
5403
 
5404
+ /* components/internal/bottom-bar.css */
5405
+ /* @tokens bottom-bar */
5406
+ /*
5407
+ * The shell at the foot of the screen (Actions collection, bottom-bar/*), private, under the FormActions and the
5408
+ * SavingBar. The brand's primary colour: bottom-bar/background (colors/primary/default) with bottom-bar/text
5409
+ * (text/on/primary), in light, dark and every brand. Full width (at least 320), sticky at the bottom of the scrolling
5410
+ * container, bottom-bar/padding-x (24) at the sides, bottom-bar/gap (16) between the parts.
5411
+ * Height, by the screen width as the Figma viewport mode (layout/compact below lg 1024): compact, bottom-bar/padding-y
5412
+ * (10) above and below, 64 = 10 + 44 + 10, plus the safe area at the bottom; expanded, 2 more inside each side, 68.
5413
+ * The leading slot, only when there is one, reserves bottom-bar/leading/min-width (44, the md Button height) and no
5414
+ * height of its own.
5415
+ * floating, from 1024 only: in the bottom right corner of the scrolling container, bottom-bar/floating/margin (24) off
5416
+ * the foot and the right; it hugs its content (width: fit-content, never wider than the container minus the margins),
5417
+ * with bottom-bar/floating/padding-y (8) and padding-x (12) plus the 2 of the expanded arrangement above and below:
5418
+ * 64 = 10 + 44 + 10; bottom-bar/floating/radius and elevation/overlay. Still sticky, not fixed: it stays inside the
5419
+ * scrolling container (a page beside a sidebar never has the sidebar covered, a panel keeps its bar), and the room it
5420
+ * takes at the end of the content is the room the content needs below. Below 1024 it is docked: no radius, no
5421
+ * shadow, no margin, the full width.
5422
+ * While it is on screen, BottomBar fills --toast-offset-bottom on the root (its height, plus the margin when
5423
+ * floating, plus 16): the Toaster's stack rises above it (toast.css).
5424
+ * The Buttons on it stay the Button: the action fill and the neutral ghost read their tokens, redeclared here in the
5425
+ * bar's colours (bottom-bar/button/*): the fill's hover at 85% over the bar (active 70%), the ghost's hover the label
5426
+ * colour at 15% (active 25%), disabled at 40% over the bar (the Figma layer opacity), the focus ring
5427
+ * bottom-bar/focus/ring (the default focus/ring would vanish on the band).
5428
+ */
5429
+ .rds-bottom-bar {
5430
+ position: sticky;
5431
+ bottom: 0;
5432
+ z-index: var(--z-sticky);
5433
+ box-sizing: border-box;
5434
+ display: flex;
5435
+ align-items: center;
5436
+ gap: var(--bottom-bar-gap);
5437
+ width: 100%;
5438
+ min-width: min(320px, 100%);
5439
+ padding: calc(var(--bottom-bar-padding-y) + 2px) var(--bottom-bar-padding-x);
5440
+ background: var(--bottom-bar-background);
5441
+ color: var(--bottom-bar-text);
5442
+ font-family: var(--type-font-stack);
5443
+
5444
+ /* The Button tokens the action fill and the neutral ghost read, in the bar's colours. */
5445
+ --button-focus-ring: var(--bottom-bar-focus-ring);
5446
+ --button-action-fill-background-default: var(--bottom-bar-button-fill-background);
5447
+ --button-action-fill-background-hover: color-mix(in srgb, var(--bottom-bar-button-fill-background) 85%, var(--bottom-bar-background));
5448
+ --button-action-fill-background-active: color-mix(in srgb, var(--bottom-bar-button-fill-background) 70%, var(--bottom-bar-background));
5449
+ --button-action-fill-label: var(--bottom-bar-button-fill-label);
5450
+ --button-action-fill-icon: var(--bottom-bar-button-fill-label);
5451
+ --button-neutral-ghost-label: var(--bottom-bar-button-ghost-label);
5452
+ --button-neutral-ghost-icon: var(--bottom-bar-button-ghost-label);
5453
+ --button-neutral-ghost-background-hover: color-mix(in srgb, var(--bottom-bar-button-ghost-label) 15%, transparent);
5454
+ --button-neutral-ghost-background-active: color-mix(in srgb, var(--bottom-bar-button-ghost-label) 25%, transparent);
5455
+ --button-disabled-fill-background: color-mix(in srgb, var(--bottom-bar-button-fill-background) 40%, var(--bottom-bar-background));
5456
+ --button-disabled-fill-label: color-mix(in srgb, var(--bottom-bar-button-fill-label) 40%, var(--bottom-bar-background));
5457
+ --button-disabled-fill-icon: var(--button-disabled-fill-label);
5458
+ --button-disabled-ghost-label: color-mix(in srgb, var(--bottom-bar-button-ghost-label) 40%, var(--bottom-bar-background));
5459
+ --button-disabled-ghost-icon: var(--button-disabled-ghost-label);
5460
+ }
5461
+
5462
+ /* The leading slot: one ~44 control; its width stays reserved while the control comes and goes. */
5463
+ .rds-bottom-bar__leading {
5464
+ display: flex;
5465
+ flex: none;
5466
+ align-items: center;
5467
+ min-width: var(--bottom-bar-leading-min-width);
5468
+ }
5469
+
5470
+ /* Compact: by the screen width (the Figma viewport mode), not a container query. */
5471
+ @media (max-width: 1023px) {
5472
+ .rds-bottom-bar {
5473
+ padding-block: var(--bottom-bar-padding-y);
5474
+ padding-bottom: calc(var(--bottom-bar-padding-y) + env(safe-area-inset-bottom, 0px));
5475
+ }
5476
+ }
5477
+
5478
+ /* floating: only from lg 1024; below it the bar is docked, square, edge to edge. */
5479
+ @media (min-width: 1024px) {
5480
+ .rds-bottom-bar--floating {
5481
+ bottom: var(--bottom-bar-floating-margin);
5482
+ width: fit-content;
5483
+ min-width: 0;
5484
+ max-width: calc(100% - 2 * var(--bottom-bar-floating-margin));
5485
+ margin-inline: auto var(--bottom-bar-floating-margin);
5486
+ margin-bottom: var(--bottom-bar-floating-margin);
5487
+ padding: calc(var(--bottom-bar-floating-padding-y) + 2px) var(--bottom-bar-floating-padding-x);
5488
+ border-radius: var(--bottom-bar-floating-radius);
5489
+ box-shadow: var(--elevation-overlay);
5490
+ }
5491
+ }
5492
+
5493
+ @media (forced-colors: active) {
5494
+ .rds-bottom-bar {
5495
+ border-top: var(--border-width) solid CanvasText;
5496
+ }
5497
+ }
5498
+
5499
+ @media (forced-colors: active) and (min-width: 1024px) {
5500
+ .rds-bottom-bar--floating {
5501
+ border: var(--border-width) solid CanvasText;
5502
+ }
5503
+ }
5504
+
5505
+ /*
5506
+ * The on-screen keyboard (compact only, the class comes from useOnScreenKeyboard): the bar slides down out of the way
5507
+ * while a field is being typed in, and comes back when the keyboard closes. visibility takes it out of the tab order
5508
+ * and the accessibility tree meanwhile; it waits for the slide to end before hiding.
5509
+ */
5510
+ @media (max-width: 1023px) {
5511
+ .rds-bottom-bar--keyboard {
5512
+ visibility: hidden;
5513
+ transform: translateY(100%);
5514
+ }
5515
+ }
5516
+
5517
+ @media (max-width: 1023px) and (prefers-reduced-motion: no-preference) {
5518
+ .rds-bottom-bar {
5519
+ transition:
5520
+ transform var(--motion-duration-base) var(--motion-easing-enter),
5521
+ visibility 0s;
5522
+ }
5523
+
5524
+ .rds-bottom-bar--keyboard {
5525
+ transition:
5526
+ transform var(--motion-duration-base) var(--motion-easing-exit),
5527
+ visibility 0s var(--motion-duration-base);
5528
+ }
5529
+ }
5530
+
5119
5531
  /* components/internal/choice.css */
5120
5532
  /* @tokens internal */
5121
5533
  /*
@@ -6336,7 +6748,7 @@ body:has(.rds-modal) {
6336
6748
  /* components/item.css */
6337
6749
  /* @tokens item */
6338
6750
  /*
6339
- * Item (Content collection, item/*): one list row, at least 44 tall. default pads 12 16, gap 16; sm pads 8 12,
6751
+ * Item (Content collection, item/*): one list row, at least 44 tall. md pads 12 16, gap 16; sm pads 8 12,
6340
6752
  * gap 12. Corners in radius/container. Title in label (16/24 medium), description in small (14/20); sm one step down.
6341
6753
  */
6342
6754
  .rds-item-group {
@@ -6348,11 +6760,11 @@ body:has(.rds-modal) {
6348
6760
  list-style: none;
6349
6761
  }
6350
6762
 
6351
- .rds-item-group:has(> .rds-item--default) {
6763
+ .rds-item-group:has(> .rds-item--ghost) {
6352
6764
  gap: 0;
6353
6765
  }
6354
6766
 
6355
- .rds-item-group > .rds-item--default + .rds-item--default {
6767
+ .rds-item-group > .rds-item--ghost + .rds-item--ghost {
6356
6768
  border-top: var(--border-width) solid var(--item-border);
6357
6769
  }
6358
6770
 
@@ -6378,7 +6790,7 @@ body:has(.rds-modal) {
6378
6790
  --_gap: var(--space-12);
6379
6791
  }
6380
6792
 
6381
- .rds-item--default {
6793
+ .rds-item--ghost {
6382
6794
  padding: var(--_pad-y) var(--_pad-x);
6383
6795
  border-width: 0;
6384
6796
  border-radius: 0;
@@ -6388,7 +6800,7 @@ body:has(.rds-modal) {
6388
6800
  border-color: var(--item-border);
6389
6801
  }
6390
6802
 
6391
- .rds-item--muted {
6803
+ .rds-item--soft {
6392
6804
  background: var(--item-muted-background);
6393
6805
  }
6394
6806
 
@@ -6434,7 +6846,7 @@ body:has(.rds-modal) {
6434
6846
 
6435
6847
  @media (forced-colors: active) {
6436
6848
  .rds-item--outline,
6437
- .rds-item--muted {
6849
+ .rds-item--soft {
6438
6850
  border-color: CanvasText;
6439
6851
  }
6440
6852
  }
@@ -6479,6 +6891,70 @@ body:has(.rds-modal) {
6479
6891
  }
6480
6892
  }
6481
6893
 
6894
+ /* components/loading-overlay.css */
6895
+ /* @tokens loading-overlay */
6896
+ /*
6897
+ * LoadingOverlay (Overlays collection, loading-overlay/*): a veil over the whole screen (loading-overlay/scrim,
6898
+ * surface/scrim) in the overlay layer (z/overlay), and a panel in the middle (loading-overlay/background,
6899
+ * surface/card; radius/container, 24 padding, 16 between the Spinner lg and the label, at most 320 wide,
6900
+ * elevation/modal). The label is type/label Medium in loading-overlay/text (text/body), centred. The panel gives the
6901
+ * text its own surface, so it reads over any screen, light, dark or in the brand. It fades in; with reduced motion,
6902
+ * no fade (and the Spinner turns slowly, spinner.css).
6903
+ */
6904
+ .rds-loading-overlay {
6905
+ position: fixed;
6906
+ inset: 0;
6907
+ z-index: var(--z-overlay);
6908
+ display: flex;
6909
+ align-items: center;
6910
+ justify-content: center;
6911
+ padding: var(--space-16);
6912
+ background: var(--loading-overlay-scrim);
6913
+ animation: rds-loading-overlay-in 150ms ease-out;
6914
+ }
6915
+
6916
+ .rds-loading-overlay__panel {
6917
+ box-sizing: border-box;
6918
+ display: flex;
6919
+ flex-direction: column;
6920
+ align-items: center;
6921
+ gap: var(--space-16);
6922
+ max-width: min(320px, 100%);
6923
+ padding: var(--space-24);
6924
+ border-radius: var(--radius-container);
6925
+ background: var(--loading-overlay-background);
6926
+ box-shadow: var(--elevation-modal);
6927
+ color: var(--loading-overlay-text);
6928
+ font-family: var(--type-font-stack);
6929
+ outline: none;
6930
+ }
6931
+
6932
+ .rds-loading-overlay__label {
6933
+ margin: 0;
6934
+ font-size: var(--type-label-size);
6935
+ font-weight: 500;
6936
+ line-height: var(--type-label-line);
6937
+ text-align: center;
6938
+ }
6939
+
6940
+ @keyframes rds-loading-overlay-in {
6941
+ from {
6942
+ opacity: 0;
6943
+ }
6944
+ }
6945
+
6946
+ @media (prefers-reduced-motion: reduce) {
6947
+ .rds-loading-overlay {
6948
+ animation: none;
6949
+ }
6950
+ }
6951
+
6952
+ @media (forced-colors: active) {
6953
+ .rds-loading-overlay__panel {
6954
+ border: var(--border-width) solid CanvasText;
6955
+ }
6956
+ }
6957
+
6482
6958
  /* components/marker.css */
6483
6959
  /* @tokens marker */
6484
6960
  /*
@@ -7126,8 +7602,9 @@ body:has(.rds-modal) {
7126
7602
  /* @tokens page-skeleton */
7127
7603
  /*
7128
7604
  * PageSkeleton and CardsSkeleton: no tokens of their own; the Skeleton and the Card bring theirs. Blocks 24 apart
7129
- * (24 padding when padded). The table is a small Card: the header row on the card's footer background, a line
7130
- * between rows. The cards: 2 per row (4 from 1024), the charts 1 (2 from 1024), 16 apart.
7605
+ * (24 padding when padded). The Cards keep their elevation/raised, as in the Figma. The table is a small Card: the
7606
+ * header row on the table header background (table/header/background), a line between rows. The cards: 2 per row (4 from 1024), the charts
7607
+ * 1 (2 from 1024), 16 apart.
7131
7608
  */
7132
7609
  .rds-page-skeleton {
7133
7610
  display: flex;
@@ -7146,10 +7623,6 @@ body:has(.rds-modal) {
7146
7623
  gap: var(--space-16);
7147
7624
  }
7148
7625
 
7149
- .rds-page-skeleton__table {
7150
- box-shadow: none;
7151
- }
7152
-
7153
7626
  .rds-page-skeleton__row {
7154
7627
  display: flex;
7155
7628
  align-items: center;
@@ -7162,7 +7635,7 @@ body:has(.rds-modal) {
7162
7635
  }
7163
7636
 
7164
7637
  .rds-page-skeleton__row--head {
7165
- background: var(--card-footer-background);
7638
+ background: var(--table-header-background);
7166
7639
  }
7167
7640
 
7168
7641
  .rds-page-skeleton__row .rds-skeleton {
@@ -7196,7 +7669,6 @@ body:has(.rds-modal) {
7196
7669
  .rds-page-skeleton__card {
7197
7670
  gap: var(--space-12);
7198
7671
  padding: var(--space-16);
7199
- box-shadow: none;
7200
7672
  }
7201
7673
 
7202
7674
  .rds-page-skeleton__card .rds-skeleton {
@@ -8157,38 +8629,38 @@ input:focus-visible + .rds-radio__circle {
8157
8629
  }
8158
8630
 
8159
8631
  /* components/saving-bar.css */
8160
- /* @tokens savingbar */
8632
+ /* @tokens bottom-bar */
8161
8633
  /*
8162
- * SavingBar (Actions collection, savingbar/*): full width (at least 320), 12 24 padding, 16 between the
8163
- * message (label, medium) and the actions (8 apart). The message grows. The Buttons use the inverse
8164
- * tone, drawn for this band in both modes, so the bar needs no theme switch of its own.
8634
+ * SavingBar: no tokens of its own; the shell (internal/bottom-bar.css, bottom-bar/*) brings the colour, the height,
8635
+ * the padding, the place and the Buttons' colours. Here the message (label, medium, in bottom-bar/text, at most 2
8636
+ * lines with an ellipsis; on error the alert 20 before it, 12 apart) and the actions (8 apart, Descartar then Salvar).
8637
+ * Expanded (from lg 1024) the message grows (at least 160) beside Descartar and Salvar; floating there, the bar hugs
8638
+ * them but stays at least 320 wide. Compact (below 1024, by the screen width as the Figma viewport mode) one row, the
8639
+ * message (flex 1) on the left, Descartar as the undo IconButton (its colours and ring from the shell's neutral ghost)
8640
+ * and Salvar on the right.
8165
8641
  */
8166
- .rds-savingbar {
8167
- box-sizing: border-box;
8168
- display: flex;
8169
- flex-wrap: wrap;
8170
- align-items: center;
8171
- gap: var(--space-16);
8172
- width: 100%;
8173
- min-width: min(320px, 100%);
8174
- padding: var(--space-12) var(--space-24);
8175
- background: var(--savingbar-background);
8176
- color: var(--savingbar-text);
8177
- font-family: var(--type-font-stack);
8178
- }
8179
-
8180
8642
  .rds-savingbar__message {
8181
8643
  display: flex;
8182
- flex: 1;
8644
+ flex: 1 1 160px;
8183
8645
  align-items: center;
8184
8646
  gap: var(--space-12);
8185
- min-width: 0;
8647
+ min-width: 160px;
8186
8648
  margin: 0;
8187
8649
  font-size: var(--type-label-size);
8188
8650
  font-weight: 500;
8189
8651
  line-height: var(--type-label-line);
8190
8652
  }
8191
8653
 
8654
+ .rds-savingbar__text {
8655
+ display: -webkit-box;
8656
+ flex: 1;
8657
+ min-width: 0;
8658
+ overflow: hidden;
8659
+ -webkit-box-orient: vertical;
8660
+ -webkit-line-clamp: 2;
8661
+ line-clamp: 2;
8662
+ }
8663
+
8192
8664
  .rds-savingbar__icon {
8193
8665
  display: inline-flex;
8194
8666
  flex: none;
@@ -8201,31 +8673,35 @@ input:focus-visible + .rds-radio__circle {
8201
8673
  height: 100%;
8202
8674
  }
8203
8675
 
8204
- .rds-savingbar__loader > svg {
8205
- animation: rds-savingbar-turn 1s linear infinite;
8676
+ .rds-savingbar__actions {
8677
+ display: flex;
8678
+ flex: none;
8679
+ gap: var(--space-8);
8206
8680
  }
8207
8681
 
8208
- @keyframes rds-savingbar-turn {
8209
- to {
8210
- transform: rotate(360deg);
8211
- }
8682
+ /* Expanded: the labelled Descartar; the undo icon is the compact one. */
8683
+ .rds-savingbar__actions > .rds-savingbar__discard-icon {
8684
+ display: none;
8212
8685
  }
8213
8686
 
8214
- @media (prefers-reduced-motion: reduce) {
8215
- .rds-savingbar__loader > svg {
8216
- animation-duration: 3s;
8687
+ @media (min-width: 1024px) {
8688
+ .rds-savingbar.rds-bottom-bar--floating {
8689
+ min-width: 320px;
8217
8690
  }
8218
8691
  }
8219
8692
 
8220
- .rds-savingbar__actions {
8221
- display: flex;
8222
- flex-wrap: wrap;
8223
- gap: var(--space-8);
8224
- }
8693
+ @media (max-width: 1023px) {
8694
+ .rds-savingbar__message {
8695
+ flex: 1 1 0;
8696
+ min-width: 0;
8697
+ }
8225
8698
 
8226
- @media (forced-colors: active) {
8227
- .rds-savingbar {
8228
- border-top: var(--border-width) solid CanvasText;
8699
+ .rds-savingbar__actions > .rds-savingbar__discard {
8700
+ display: none;
8701
+ }
8702
+
8703
+ .rds-savingbar__actions > .rds-savingbar__discard-icon {
8704
+ display: inline-flex;
8229
8705
  }
8230
8706
  }
8231
8707
 
@@ -8590,9 +9066,12 @@ input:focus-visible + .rds-radio__circle {
8590
9066
  /*
8591
9067
  * Sidebar (Navigation collection, sidebar/*): 240 wide (64 collapsed), 12 × 8 inside, a 1px border on the right.
8592
9068
  * Header: the brand mark (24) and the module (16/24 medium), 10 apart, 44 tall. Entries of 44, 12 inside, 12 between
8593
- * icon (20) and label (14/20 medium), 4 apart; the current one on the brand tint with the label in colors/primary.
9069
+ * icon (20) and label (14/20 medium), 4 apart; the current one on the brand tint, its label semibold in
9070
+ * sidebar/item/label/active and a 3 × 20 marker on the left in sidebar/item/indicator, so the current entry does not
9071
+ * rest on colour alone.
8594
9072
  * Section labels 11/14 bold, 16 above and 6 below, with a 14 chevron. Foot: who is signed in (12/16) and Sair.
8595
- * dark (deprecated in the Figma) reads sidebar/dark/*; the current entry stays the light pill.
9073
+ * No tone: the Sidebar follows its container's mode. The brand-coloured bar is a `.ds-plate` around it (the brand
9074
+ * mode), the dark one a `.dark`.
8596
9075
  */
8597
9076
  .rds-sidebar {
8598
9077
  --_background: var(--sidebar-background);
@@ -8618,21 +9097,6 @@ input:focus-visible + .rds-radio__circle {
8618
9097
  font-family: var(--type-font-stack);
8619
9098
  }
8620
9099
 
8621
- .rds-sidebar--dark {
8622
- --_background: var(--sidebar-dark-background);
8623
- --_label: var(--sidebar-dark-item-label-default);
8624
- --_label-hover: var(--sidebar-dark-item-label-hover);
8625
- --_hover: var(--sidebar-dark-item-background-hover);
8626
- --_module: var(--sidebar-dark-module);
8627
- --_user: var(--sidebar-dark-user);
8628
- --_section: var(--sidebar-dark-section-label);
8629
- --_count: var(--sidebar-dark-item-label-default);
8630
- /* No dark ring token: the strongest text over the brand, which is what the ring needs to show there. */
8631
- --_ring: var(--sidebar-dark-module);
8632
-
8633
- border-right-color: transparent;
8634
- }
8635
-
8636
9100
  .rds-sidebar--collapsed {
8637
9101
  width: var(--space-64);
8638
9102
  }
@@ -8695,6 +9159,7 @@ input:focus-visible + .rds-radio__circle {
8695
9159
  }
8696
9160
 
8697
9161
  .rds-sidebar__item {
9162
+ position: relative;
8698
9163
  box-sizing: border-box;
8699
9164
  display: flex;
8700
9165
  align-items: center;
@@ -8754,8 +9219,21 @@ input:focus-visible + .rds-radio__circle {
8754
9219
  color: var(--sidebar-item-label-active);
8755
9220
  }
8756
9221
 
8757
- .rds-sidebar__item[aria-current='page'] .rds-sidebar__count {
8758
- color: var(--sidebar-item-label-active);
9222
+ .rds-sidebar__item[aria-current='page'] .rds-sidebar__label {
9223
+ font-weight: 600;
9224
+ }
9225
+
9226
+ /* Figma .sidebar/item state=active: the marker, 3 × 20, on the left edge, vertically centred, radius 2. */
9227
+ .rds-sidebar__item[aria-current='page']::before {
9228
+ content: '';
9229
+ position: absolute;
9230
+ inset-inline-start: 0;
9231
+ top: 50%;
9232
+ width: 3px;
9233
+ height: var(--size-20);
9234
+ border-radius: 2px;
9235
+ background: var(--sidebar-item-indicator);
9236
+ transform: translateY(-50%);
8759
9237
  }
8760
9238
 
8761
9239
  .rds-sidebar__item:focus-visible,
@@ -8789,9 +9267,12 @@ input:focus-visible + .rds-radio__circle {
8789
9267
  cursor: pointer;
8790
9268
  }
8791
9269
 
9270
+ /* Figma .sidebar/section: label in caps with 6% tracking; the count keeps its own case and no tracking. */
8792
9271
  .rds-sidebar__section-label {
8793
9272
  flex: 1;
8794
9273
  min-width: 0;
9274
+ text-transform: uppercase;
9275
+ letter-spacing: 0.06em;
8795
9276
  }
8796
9277
 
8797
9278
  .rds-sidebar__section-count {
@@ -8821,6 +9302,10 @@ input:focus-visible + .rds-radio__circle {
8821
9302
  .rds-sidebar__item[aria-current='page'] {
8822
9303
  outline: var(--border-width) solid CanvasText;
8823
9304
  }
9305
+
9306
+ .rds-sidebar__item[aria-current='page']::before {
9307
+ background: Highlight;
9308
+ }
8824
9309
  }
8825
9310
 
8826
9311
  /* components/skeleton.css */
@@ -9214,6 +9699,7 @@ input:focus-visible + .rds-radio__circle {
9214
9699
  /*
9215
9700
  * Stat (Content collection, stat/*): 8 between the text and the sparkline. Text: the label 14/20, the row (the
9216
9701
  * value in type/value bold and the Delta, 8 apart, wrapping 4 below) and the caption 12/16, 4 apart.
9702
+ * tone neutral (default), success, danger, warning; muted greys a zero out.
9217
9703
  * framed=true: 16 inside, a 1px border, corners radius/container. framed=false (the SummaryBar cell): 12 16, no border.
9218
9704
  */
9219
9705
  .rds-stat {
@@ -9235,11 +9721,11 @@ input:focus-visible + .rds-radio__circle {
9235
9721
  border-radius: var(--radius-container);
9236
9722
  }
9237
9723
 
9238
- .rds-stat--positive {
9724
+ .rds-stat--success {
9239
9725
  --_value: var(--stat-value-positive);
9240
9726
  }
9241
9727
 
9242
- .rds-stat--negative {
9728
+ .rds-stat--danger {
9243
9729
  --_value: var(--stat-value-negative);
9244
9730
  }
9245
9731
 
@@ -9247,6 +9733,7 @@ input:focus-visible + .rds-radio__circle {
9247
9733
  --_value: var(--stat-value-warning);
9248
9734
  }
9249
9735
 
9736
+ /* muted (zero, nothing to see) wins over the tone: the Figma draws it only on neutral. */
9250
9737
  .rds-stat--muted {
9251
9738
  --_value: var(--stat-value-muted);
9252
9739
  }
@@ -9473,6 +9960,35 @@ input:focus-visible + .rds-radio__circle {
9473
9960
  }
9474
9961
  }
9475
9962
 
9963
+ /* components/stepper.css */
9964
+ /* @tokens stepper */
9965
+ /*
9966
+ * Stepper: no tokens of its own; the Card and the Buttons bring theirs. A pill (radius/full) of 44 Buttons,
9967
+ * 4 inside and 4 apart, raised by elevation/overlay because it floats over the page. A vertical Separator, 24
9968
+ * tall, before the action.
9969
+ */
9970
+ .rds-stepper {
9971
+ flex-direction: row;
9972
+ align-items: center;
9973
+ gap: var(--space-4);
9974
+ width: max-content;
9975
+ max-width: 100%;
9976
+ padding: var(--space-4);
9977
+ border-radius: var(--radius-full);
9978
+ box-shadow: var(--elevation-overlay);
9979
+ overflow-x: auto;
9980
+ }
9981
+
9982
+ .rds-stepper > .rds-button {
9983
+ flex: none;
9984
+ border-radius: var(--radius-full);
9985
+ }
9986
+
9987
+ .rds-stepper > .rds-stepper__divider {
9988
+ align-self: center;
9989
+ height: var(--size-24);
9990
+ }
9991
+
9476
9992
  /* components/summary-bar.css */
9477
9993
  /* @tokens summary-bar */
9478
9994
  /*
@@ -9652,8 +10168,18 @@ input:focus-visible + .rds-switch__track {
9652
10168
  * A line under every row but the last: the Table's border closes it. Corners in radius/container; the sort button in
9653
10169
  * radius/xs. The status rows hold an Empty, 32 24 around it.
9654
10170
  */
10171
+ /*
10172
+ * The scroll region is a one-column grid, minmax(0, 1fr), so it does not hand the table's min-content up to the page:
10173
+ * as a plain block it did, and any ancestor sized by its content (a flex item without min-width: 0, a grid item in an
10174
+ * auto track, a start-aligned stack, an inline-block) grew to the table's width, so a Card holding a wide table went
10175
+ * past the screen and was cut instead of the table scrolling. Under a min-content constraint the fr track is 0; under
10176
+ * max-content it is the table's max-content (a hugging parent still hugs the table); with a definite width it fills,
10177
+ * and the table, never narrower than its min-content, scrolls inside.
10178
+ */
9655
10179
  .rds-table {
9656
10180
  box-sizing: border-box;
10181
+ display: grid;
10182
+ grid-template-columns: minmax(0, 1fr);
9657
10183
  max-width: 100%;
9658
10184
  overflow-x: auto;
9659
10185
  border: var(--border-width) solid var(--table-border);
@@ -10214,13 +10740,23 @@ tbody > tr:last-child > .rds-table__status {
10214
10740
  /*
10215
10741
  * Toast (Feedback collection, toast/*): 460 wide, 8 8 8 16 inside, 12 between icon, text, action and ×,
10216
10742
  * elevation/overlay. outline: white with a border, the icon in the tone; soft and fill: the tone's plate, and
10217
- * everything on it (icon, text, action, ×) in the plate's text colour. Stacked in the bottom-right corner,
10218
- * 16 from the edges and 8 apart.
10743
+ * everything on it (icon, text, action, ×) in the plate's text colour. Stacked at the bottom centre on every screen
10744
+ * width (bottom-center, no switch by breakpoint: the bottom right corner belongs to the floating bar at the foot),
10745
+ * 16 from the foot and 8 apart; on the phone, the screen width minus 16 on each side (calc(100% - 32px)).
10746
+ * With a bar at the foot on screen (FormActions, SavingBar), the stack rises above it: --toast-offset-bottom, filled
10747
+ * on the root by the bar while it is mounted and visible (its height, plus its margin when floating, plus 16), and
10748
+ * back to 16 when it leaves or the on-screen keyboard hides it. The default lives on the root; the bar sets it inline
10749
+ * on the root (so it wins) and removes it.
10219
10750
  */
10751
+ :root {
10752
+ --toast-offset-bottom: var(--space-16);
10753
+ }
10754
+
10220
10755
  .rds-toast-viewport {
10221
10756
  position: fixed;
10222
10757
  right: 0;
10223
10758
  bottom: 0;
10759
+ left: 0;
10224
10760
  z-index: var(--z-toast);
10225
10761
  box-sizing: border-box;
10226
10762
  display: flex;
@@ -10228,8 +10764,9 @@ tbody > tr:last-child > .rds-table__status {
10228
10764
  gap: var(--space-8);
10229
10765
  width: min(calc(460px + var(--space-16) * 2), 100vw);
10230
10766
  max-width: 100vw;
10231
- margin: 0;
10767
+ margin: 0 auto;
10232
10768
  padding: var(--space-16);
10769
+ padding-bottom: var(--toast-offset-bottom);
10233
10770
  list-style: none;
10234
10771
  outline: none;
10235
10772
  }
@@ -10407,23 +10944,13 @@ tbody > tr:last-child > .rds-table__status {
10407
10944
  }
10408
10945
  }
10409
10946
 
10410
- /* components/toggle-card-compact.css */
10411
- /* @tokens toggle-card-compact */
10412
- /*
10413
- * ToggleCardCompact: no tokens of its own; the Item, the Switch and the IconButton bring theirs. The pencil and the
10414
- * Switch 8 apart at the end of the row.
10415
- */
10416
- .rds-toggle-card-compact__actions {
10417
- display: inline-flex;
10418
- align-items: center;
10419
- gap: var(--space-8);
10420
- }
10421
-
10422
10947
  /* components/toggle-card.css */
10423
10948
  /* @tokens toggle-card */
10424
10949
  /*
10425
- * ToggleCard: no tokens of its own; the Card and the Switch bring theirs. The Switch row pads 16 on the sides (4 top and
10426
- * bottom); the options under it pad 16, 16 apart, after a line in the card's border colour.
10950
+ * ToggleCard: no tokens of its own; the Card, the Item, the Switch and the IconButton bring theirs.
10951
+ * layout=default: the Switch row pads 16 on the sides (4 top and bottom); the options under it pad 16, 16 apart,
10952
+ * after a line in the card's border colour.
10953
+ * layout=compact: the outline Item; the pencil and the Switch 8 apart at the end of the row.
10427
10954
  */
10428
10955
  .rds-toggle-card__header {
10429
10956
  padding: var(--space-4) var(--space-16);
@@ -10437,6 +10964,12 @@ tbody > tr:last-child > .rds-table__status {
10437
10964
  border-top: var(--border-width) solid var(--card-border);
10438
10965
  }
10439
10966
 
10967
+ .rds-toggle-card__actions {
10968
+ display: inline-flex;
10969
+ align-items: center;
10970
+ gap: var(--space-8);
10971
+ }
10972
+
10440
10973
  /* components/toggle-group.css */
10441
10974
  /* @tokens toggle-group */
10442
10975
  /* ToggleGroup: Toggles side by side, 4 apart (Figma: slot items, gap space/4). No tokens of its own. */