@rojaostudio/ds 2.0.0-next.2 → 2.0.0-next.20

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 (101) 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 +17 -3
  15. package/dist/components/chart.js +70 -24
  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 +26 -16
  25. package/dist/components/data-table-header.js +75 -12
  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/heading.d.ts +42 -0
  39. package/dist/components/heading.js +25 -0
  40. package/dist/components/icon-button.d.ts +1 -1
  41. package/dist/components/image-crop-dialog.d.ts +60 -0
  42. package/dist/components/image-crop-dialog.js +240 -0
  43. package/dist/components/image-crop-modal.d.ts +12 -55
  44. package/dist/components/image-crop-modal.js +2 -249
  45. package/dist/components/image-upload.d.ts +8 -17
  46. package/dist/components/image-upload.js +3 -3
  47. package/dist/components/index.d.ts +11 -8
  48. package/dist/components/index.js +8 -0
  49. package/dist/components/internal/button.d.ts +1 -1
  50. package/dist/components/internal/icons.d.ts +11 -1
  51. package/dist/components/internal/icons.js +20 -0
  52. package/dist/components/internal/menu.d.ts +3 -2
  53. package/dist/components/internal/menu.js +1 -1
  54. package/dist/components/internal/modal.js +9 -0
  55. package/dist/components/internal/toggle.d.ts +1 -1
  56. package/dist/components/item.d.ts +14 -7
  57. package/dist/components/item.js +5 -2
  58. package/dist/components/marker.d.ts +11 -3
  59. package/dist/components/marker.js +4 -3
  60. package/dist/components/number-input.d.ts +1 -1
  61. package/dist/components/progress.d.ts +3 -3
  62. package/dist/components/progress.js +2 -2
  63. package/dist/components/row-actions.d.ts +3 -0
  64. package/dist/components/row-actions.js +8 -4
  65. package/dist/components/saving-bar.d.ts +16 -4
  66. package/dist/components/saving-bar.js +37 -9
  67. package/dist/components/section-header.d.ts +4 -3
  68. package/dist/components/selectable-card.d.ts +2 -10
  69. package/dist/components/sidebar.d.ts +8 -11
  70. package/dist/components/sidebar.js +4 -5
  71. package/dist/components/spinner.d.ts +9 -6
  72. package/dist/components/spinner.js +3 -3
  73. package/dist/components/star-rating.d.ts +3 -3
  74. package/dist/components/star-rating.js +2 -2
  75. package/dist/components/stat.d.ts +18 -6
  76. package/dist/components/stat.js +9 -3
  77. package/dist/components/status.d.ts +4 -4
  78. package/dist/components/status.js +2 -2
  79. package/dist/components/stepper.d.ts +33 -0
  80. package/dist/components/stepper.js +36 -0
  81. package/dist/components/summary-bar.d.ts +3 -2
  82. package/dist/components/summary-bar.js +10 -1
  83. package/dist/components/tile.d.ts +5 -5
  84. package/dist/components/tile.js +2 -2
  85. package/dist/components/time-picker.d.ts +1 -1
  86. package/dist/components/toast.d.ts +17 -6
  87. package/dist/components/toast.js +5 -3
  88. package/dist/components/toggle-card-compact.d.ts +6 -25
  89. package/dist/components/toggle-card-compact.js +8 -35
  90. package/dist/components/toggle-card.d.ts +23 -9
  91. package/dist/components/toggle-card.js +38 -2
  92. package/dist/components/toggle.d.ts +1 -1
  93. package/dist/components/typing-indicator.d.ts +2 -2
  94. package/dist/components/typing-indicator.js +1 -1
  95. package/package.json +4 -4
  96. package/styles/base.css +13 -1
  97. package/styles/rds/components-styles.css +593 -172
  98. package/styles/rds/components.css +40 -25
  99. package/styles/rds/foundation.css +1 -1
  100. package/styles/rds/theme.css +40 -29
  101. 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,35 @@ 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: no tokens of its own; the Input, FilterChip, Chip, Button, Separator, Checkbox, DropdownMenu,
3586
+ * Popover and Drawer bring theirs. One row, 8 apart, 12 above the table, packed to the right: the search on the left
3587
+ * takes the free width, at least 320 (never wider than the bar); the quick filters, the filters, the view control
3588
+ * and the actions follow it on the right, and what does not fit wraps.
3589
+ * Two arrangements, by the screen width, as the Figma viewport mode (layout/compact below lg 1024; the SavingBar's cut):
3590
+ * expanded from 1024 (the __wide parts: Separator, Buttons with labels); compact below it (the __narrow parts: the
3591
+ * filter as an IconButton of 44), where the search accepts 200. On the IconButton, while a filter is on, a dot of 8
3592
+ * (badge neutral fill, 6 in from the top right corner) or a neutral number Badge over the corner (-6 top, -12 right).
3593
+ * In the Popover and the Drawer the filters stack 16 apart, each one a caption-sized label over its chips.
3401
3594
  */
3402
3595
  .rds-data-table-header {
3596
+ box-sizing: border-box;
3597
+ width: 100%;
3403
3598
  display: flex;
3404
3599
  flex-wrap: wrap;
3405
3600
  align-items: center;
3601
+ justify-content: flex-end;
3406
3602
  gap: var(--space-8);
3407
3603
  margin-bottom: var(--space-12);
3408
3604
  }
3409
3605
 
3410
- .rds-data-table-header__search {
3411
- flex: 1 1 calc(var(--space-64) * 4);
3606
+ /* Scoped to the bar: the field's own `min-width: 0` (internal/field.css) comes later in the bundle. */
3607
+ .rds-data-table-header .rds-data-table-header__search {
3608
+ flex: 1 1 calc(var(--space-64) * 5);
3609
+ min-width: min(calc(var(--space-64) * 5), 100%);
3412
3610
  }
3413
3611
 
3612
+ .rds-data-table-header__quick,
3613
+ .rds-data-table-header__view,
3414
3614
  .rds-data-table-header__wide,
3415
3615
  .rds-data-table-header__actions,
3416
3616
  .rds-data-table-header__narrow {
@@ -3420,17 +3620,55 @@ input:focus-visible + .rds-checkbox__box {
3420
3620
  gap: var(--space-8);
3421
3621
  }
3422
3622
 
3423
- .rds-data-table-header__wide {
3623
+ .rds-data-table-header__narrow {
3424
3624
  display: none;
3425
3625
  }
3426
3626
 
3427
- @media (min-width: 768px) {
3627
+ @media (max-width: 1023px) {
3428
3628
  .rds-data-table-header__wide {
3429
- display: flex;
3629
+ display: none;
3430
3630
  }
3431
3631
 
3432
3632
  .rds-data-table-header__narrow {
3433
- display: none;
3633
+ display: flex;
3634
+ }
3635
+
3636
+ /* Compact: the search accepts 200 (40 × 5), so it sits on one line with the filter and an IconButton at 390. */
3637
+ .rds-data-table-header .rds-data-table-header__search {
3638
+ flex-basis: calc(var(--space-40) * 5);
3639
+ min-width: min(calc(var(--space-40) * 5), 100%);
3640
+ }
3641
+ }
3642
+
3643
+ /* The compact filter: the IconButton with its indicator on the corner. */
3644
+ .rds-data-table-header__trigger {
3645
+ position: relative;
3646
+ display: inline-flex;
3647
+ }
3648
+
3649
+ .rds-data-table-header__dot,
3650
+ .rds-data-table-header__count {
3651
+ position: absolute;
3652
+ pointer-events: none;
3653
+ }
3654
+
3655
+ .rds-data-table-header__dot {
3656
+ top: calc(var(--space-4) * 1.5);
3657
+ right: calc(var(--space-4) * 1.5);
3658
+ width: var(--space-8);
3659
+ height: var(--space-8);
3660
+ border-radius: var(--radius-full);
3661
+ background: var(--badge-neutral-fill-background);
3662
+ }
3663
+
3664
+ .rds-data-table-header__count {
3665
+ top: calc(var(--space-4) * -1.5);
3666
+ right: calc(var(--space-12) * -1);
3667
+ }
3668
+
3669
+ @media (forced-colors: active) {
3670
+ .rds-data-table-header__dot {
3671
+ background: CanvasText;
3434
3672
  }
3435
3673
  }
3436
3674
 
@@ -3590,6 +3828,8 @@ input:focus-visible + .rds-checkbox__box {
3590
3828
  * Drawer (Overlays collection, drawer/*): stuck to the bottom, the top corners in radius/container; 12 above (the
3591
3829
  * handle, 40 × 4), 24 on the sides, 32 below, 20 between parts; no border and no ×. On a wide screen it stops at
3592
3830
  * 560 and centres (the Figma draws it on a 390 phone only).
3831
+ * Height by the content, up to 85% of the screen (717 on an 844): past it, only the content scrolls inside; the
3832
+ * handle, the title and the footer stay put.
3593
3833
  */
3594
3834
  .rds-drawer__scrim {
3595
3835
  background: var(--drawer-scrim);
@@ -3601,7 +3841,7 @@ input:focus-visible + .rds-checkbox__box {
3601
3841
  left: 0;
3602
3842
  gap: calc(var(--space-16) + var(--space-4));
3603
3843
  max-width: 560px;
3604
- max-height: calc(100dvh - var(--space-48));
3844
+ max-height: 85dvh;
3605
3845
  margin-inline: auto;
3606
3846
  padding: var(--space-12) var(--space-24) var(--space-32);
3607
3847
  border-radius: var(--radius-container) var(--radius-container) 0 0;
@@ -3625,6 +3865,18 @@ input:focus-visible + .rds-checkbox__box {
3625
3865
  background: var(--drawer-handle);
3626
3866
  }
3627
3867
 
3868
+ .rds-drawer .rds-modal__header,
3869
+ .rds-drawer .rds-modal__footer {
3870
+ flex: none;
3871
+ }
3872
+
3873
+ .rds-drawer .rds-modal__body {
3874
+ flex: 1;
3875
+ min-height: 0;
3876
+ overflow-y: auto;
3877
+ overscroll-behavior: contain;
3878
+ }
3879
+
3628
3880
  .rds-drawer .rds-modal__heading {
3629
3881
  padding-top: 0;
3630
3882
  }
@@ -4105,7 +4357,7 @@ input:focus-visible + .rds-checkbox__box {
4105
4357
  * FilterChip (Forms collection, filter-chip/*): 32 tall, pill, 12 inside, 4 between icon, label and count;
4106
4358
  * label 14/20 medium. inactive: card fill and a hairline; hover: muted fill, strong hairline; active: the brand
4107
4359
  * 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.
4360
+ * The count reads in the label's colour, at full opacity. Icon 14, in the label's colour.
4109
4361
  */
4110
4362
  .rds-filter-chip-group {
4111
4363
  display: flex;
@@ -4149,14 +4401,14 @@ input:focus-visible + .rds-checkbox__box {
4149
4401
  }
4150
4402
 
4151
4403
  @media (hover: hover) {
4152
- .rds-filter-chip:not(.rds-filter-chip--active, [aria-disabled='true']):hover {
4404
+ .rds-filter-chip:not(.rds-filter-chip--pressed, [aria-disabled='true']):hover {
4153
4405
  --_surface: var(--filter-chip-surface-hover);
4154
4406
  --_stroke: var(--filter-chip-stroke-hover);
4155
4407
  --_text: var(--filter-chip-text-hover);
4156
4408
  }
4157
4409
  }
4158
4410
 
4159
- .rds-filter-chip--active {
4411
+ .rds-filter-chip--pressed {
4160
4412
  --_surface: color-mix(in srgb, var(--filter-chip-surface-active) 12%, transparent);
4161
4413
  --_stroke: var(--filter-chip-stroke-active);
4162
4414
  --_text: var(--filter-chip-text-active);
@@ -4196,7 +4448,6 @@ input:focus-visible + .rds-checkbox__box {
4196
4448
  }
4197
4449
 
4198
4450
  .rds-filter-chip__count {
4199
- color: color-mix(in srgb, currentColor 60%, transparent);
4200
4451
  font-variant-numeric: tabular-nums;
4201
4452
  }
4202
4453
 
@@ -4205,7 +4456,7 @@ input:focus-visible + .rds-checkbox__box {
4205
4456
  border-color: CanvasText;
4206
4457
  }
4207
4458
 
4208
- .rds-filter-chip--active {
4459
+ .rds-filter-chip--pressed {
4209
4460
  border-color: Highlight;
4210
4461
  outline: var(--border-width) solid Highlight;
4211
4462
  }
@@ -4215,38 +4466,6 @@ input:focus-visible + .rds-checkbox__box {
4215
4466
  }
4216
4467
  }
4217
4468
 
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
4469
  /* components/footer.css */
4251
4470
  /* @tokens footer */
4252
4471
  /*
@@ -4595,6 +4814,48 @@ input:focus-visible + .rds-checkbox__box {
4595
4814
  }
4596
4815
  }
4597
4816
 
4817
+ /* components/heading.css */
4818
+ /* @tokens heading */
4819
+ /*
4820
+ * Heading (Content collection, heading/*): a title in the brand pair. heading/default is text/heading, heading/accent
4821
+ * the logo orange; .heading/mark paints a stretch in the other one. level follows the type scale (band, heading,
4822
+ * value), all bold.
4823
+ */
4824
+ .rds-heading {
4825
+ margin: 0;
4826
+ font-family: var(--type-font-stack);
4827
+ font-weight: var(--type-heading-weight);
4828
+ color: var(--heading-default);
4829
+ text-wrap: balance;
4830
+ }
4831
+
4832
+ .rds-heading--band {
4833
+ font-size: var(--type-band-size);
4834
+ line-height: var(--type-band-line);
4835
+ }
4836
+
4837
+ .rds-heading--heading {
4838
+ font-size: var(--type-heading-size);
4839
+ line-height: var(--type-heading-line);
4840
+ }
4841
+
4842
+ .rds-heading--value {
4843
+ font-size: var(--type-value-size);
4844
+ line-height: var(--type-value-line);
4845
+ }
4846
+
4847
+ .rds-heading--accent {
4848
+ color: var(--heading-accent);
4849
+ }
4850
+
4851
+ .rds-heading__mark {
4852
+ color: var(--heading-accent);
4853
+ }
4854
+
4855
+ .rds-heading--accent .rds-heading__mark {
4856
+ color: var(--heading-default);
4857
+ }
4858
+
4598
4859
  /* components/hover-card.css */
4599
4860
  /* @tokens hovercard */
4600
4861
  /* HoverCard (Feedback collection, hovercard/*): 320 wide, 16 inside, 12 between avatar and text, elevation/overlay. */
@@ -4669,13 +4930,14 @@ input:focus-visible + .rds-checkbox__box {
4669
4930
  }
4670
4931
  }
4671
4932
 
4672
- /* components/image-crop-modal.css */
4673
- /* @tokens image-crop-modal */
4933
+ /* components/image-crop-dialog.css */
4934
+ /* @tokens image-crop-dialog */
4674
4935
  /*
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.
4936
+ * ImageCropDialog (Figma [RDS] Overlays/ImageCropDialog): the Dialog, the ToggleGroup, the Alert and the Spinner bring
4937
+ * their tokens; the crop brings its own (Overlays, image-crop-dialog/*). 12 apart: the presets (they share the
4938
+ * width), the stage (320 tall, on image-crop-dialog/stage/background, the image letterboxed inside 16 of padding, a
4939
+ * line in the dialog's border colour), the error or the hint. Over the image, outside the crop, the shade; the crop's
4940
+ * line and its handles in their own colours. While sending, the dialog's scrim covers the stage.
4679
4941
  */
4680
4942
  .rds-image-crop {
4681
4943
  display: flex;
@@ -4698,17 +4960,42 @@ input:focus-visible + .rds-checkbox__box {
4698
4960
  display: flex;
4699
4961
  align-items: center;
4700
4962
  justify-content: center;
4701
- min-height: 300px;
4963
+ height: 320px;
4964
+ /* On a short viewport (a phone on its side) the stage gives way so the footer stays in view. */
4702
4965
  max-height: 60vh;
4703
4966
  padding: var(--space-16);
4704
4967
  overflow: hidden;
4968
+ background: var(--image-crop-dialog-stage-background);
4705
4969
  border: var(--border-width) solid var(--dialog-border);
4706
4970
  border-radius: var(--radius-control);
4707
4971
  }
4708
4972
 
4973
+ /*
4974
+ * react-image-crop's own stylesheet is unlayered, so it wins over these layered rules wherever both set the same
4975
+ * property. The shade is an SVG rect with fill as an attribute (black at 50%): any CSS beats it. The handles read
4976
+ * the library's variables, set here. The selection's marching ants are hard-coded: the two !important take them
4977
+ * off so the crop is one solid line in the selection colour (the library's focus outline stays).
4978
+ */
4709
4979
  .rds-image-crop__crop {
4710
4980
  max-width: 100%;
4711
- max-height: calc(60vh - var(--space-32));
4981
+ max-height: calc(min(320px, 60vh) - var(--space-32));
4982
+ --rc-drag-handle-bg-colour: var(--image-crop-dialog-handle);
4983
+ --rc-border-color: var(--image-crop-dialog-handle);
4984
+ }
4985
+
4986
+ .rds-image-crop__crop .ReactCrop__crop-mask > rect {
4987
+ fill: var(--image-crop-dialog-shade);
4988
+ fill-opacity: 1;
4989
+ }
4990
+
4991
+ .rds-image-crop__crop .ReactCrop__crop-selection {
4992
+ background-image: none !important;
4993
+ border: var(--border-width) solid var(--image-crop-dialog-selection);
4994
+ animation: none !important;
4995
+ }
4996
+
4997
+ .rds-image-crop__crop .ReactCrop__drag-handle {
4998
+ border-radius: var(--radius-xs);
4712
4999
  }
4713
5000
 
4714
5001
  .rds-image-crop__image {
@@ -5298,6 +5585,23 @@ input:focus-visible + .rds-checkbox__box {
5298
5585
  font: inherit;
5299
5586
  }
5300
5587
 
5588
+ /*
5589
+ * Browser autofill paints the control's own background (blue in light, yellow in dark) and the control is smaller
5590
+ * than the box that draws the border: it showed as a patch in the middle of the field. Cover it with the box
5591
+ * colour and keep the value colour. The background-color transition is the fallback for browsers that ignore the
5592
+ * inset shadow on autofill.
5593
+ */
5594
+ .rds-field__control:-webkit-autofill,
5595
+ .rds-field__control:-webkit-autofill:hover,
5596
+ .rds-field__control:-webkit-autofill:focus,
5597
+ .rds-field__control:autofill {
5598
+ -webkit-box-shadow: 0 0 0 1000px var(--_background) inset;
5599
+ box-shadow: 0 0 0 1000px var(--_background) inset;
5600
+ -webkit-text-fill-color: var(--_value);
5601
+ caret-color: var(--_value);
5602
+ transition: background-color 600000s 0s;
5603
+ }
5604
+
5301
5605
  .rds-field__control::placeholder {
5302
5606
  color: var(--_placeholder);
5303
5607
  opacity: 1;
@@ -6319,7 +6623,7 @@ body:has(.rds-modal) {
6319
6623
  /* components/item.css */
6320
6624
  /* @tokens item */
6321
6625
  /*
6322
- * Item (Content collection, item/*): one list row, at least 44 tall. default pads 12 16, gap 16; sm pads 8 12,
6626
+ * Item (Content collection, item/*): one list row, at least 44 tall. md pads 12 16, gap 16; sm pads 8 12,
6323
6627
  * gap 12. Corners in radius/container. Title in label (16/24 medium), description in small (14/20); sm one step down.
6324
6628
  */
6325
6629
  .rds-item-group {
@@ -6331,11 +6635,11 @@ body:has(.rds-modal) {
6331
6635
  list-style: none;
6332
6636
  }
6333
6637
 
6334
- .rds-item-group:has(> .rds-item--default) {
6638
+ .rds-item-group:has(> .rds-item--ghost) {
6335
6639
  gap: 0;
6336
6640
  }
6337
6641
 
6338
- .rds-item-group > .rds-item--default + .rds-item--default {
6642
+ .rds-item-group > .rds-item--ghost + .rds-item--ghost {
6339
6643
  border-top: var(--border-width) solid var(--item-border);
6340
6644
  }
6341
6645
 
@@ -6361,7 +6665,7 @@ body:has(.rds-modal) {
6361
6665
  --_gap: var(--space-12);
6362
6666
  }
6363
6667
 
6364
- .rds-item--default {
6668
+ .rds-item--ghost {
6365
6669
  padding: var(--_pad-y) var(--_pad-x);
6366
6670
  border-width: 0;
6367
6671
  border-radius: 0;
@@ -6371,7 +6675,7 @@ body:has(.rds-modal) {
6371
6675
  border-color: var(--item-border);
6372
6676
  }
6373
6677
 
6374
- .rds-item--muted {
6678
+ .rds-item--soft {
6375
6679
  background: var(--item-muted-background);
6376
6680
  }
6377
6681
 
@@ -6417,7 +6721,7 @@ body:has(.rds-modal) {
6417
6721
 
6418
6722
  @media (forced-colors: active) {
6419
6723
  .rds-item--outline,
6420
- .rds-item--muted {
6724
+ .rds-item--soft {
6421
6725
  border-color: CanvasText;
6422
6726
  }
6423
6727
  }
@@ -7109,8 +7413,9 @@ body:has(.rds-modal) {
7109
7413
  /* @tokens page-skeleton */
7110
7414
  /*
7111
7415
  * PageSkeleton and CardsSkeleton: no tokens of their own; the Skeleton and the Card bring theirs. Blocks 24 apart
7112
- * (24 padding when padded). The table is a small Card: the header row on the card's footer background, a line
7113
- * between rows. The cards: 2 per row (4 from 1024), the charts 1 (2 from 1024), 16 apart.
7416
+ * (24 padding when padded). The Cards keep their elevation/raised, as in the Figma. The table is a small Card: the
7417
+ * header row on the table header background (table/header/background), a line between rows. The cards: 2 per row (4 from 1024), the charts
7418
+ * 1 (2 from 1024), 16 apart.
7114
7419
  */
7115
7420
  .rds-page-skeleton {
7116
7421
  display: flex;
@@ -7129,10 +7434,6 @@ body:has(.rds-modal) {
7129
7434
  gap: var(--space-16);
7130
7435
  }
7131
7436
 
7132
- .rds-page-skeleton__table {
7133
- box-shadow: none;
7134
- }
7135
-
7136
7437
  .rds-page-skeleton__row {
7137
7438
  display: flex;
7138
7439
  align-items: center;
@@ -7145,7 +7446,7 @@ body:has(.rds-modal) {
7145
7446
  }
7146
7447
 
7147
7448
  .rds-page-skeleton__row--head {
7148
- background: var(--card-footer-background);
7449
+ background: var(--table-header-background);
7149
7450
  }
7150
7451
 
7151
7452
  .rds-page-skeleton__row .rds-skeleton {
@@ -7179,7 +7480,6 @@ body:has(.rds-modal) {
7179
7480
  .rds-page-skeleton__card {
7180
7481
  gap: var(--space-12);
7181
7482
  padding: var(--space-16);
7182
- box-shadow: none;
7183
7483
  }
7184
7484
 
7185
7485
  .rds-page-skeleton__card .rds-skeleton {
@@ -8143,15 +8443,20 @@ input:focus-visible + .rds-radio__circle {
8143
8443
  /* @tokens savingbar */
8144
8444
  /*
8145
8445
  * SavingBar (Actions collection, savingbar/*): full width (at least 320), 12 24 padding, 16 between the
8146
- * message (label, medium) and the actions (8 apart). The message grows. The Buttons use the inverse
8147
- * tone, drawn for this band in both modes, so the bar needs no theme switch of its own.
8446
+ * message (label, medium, at most 2 lines with an ellipsis) and the actions (8 apart). The bar is the brand plate
8447
+ * (.ds-plate on the element, set by the component): savingbar/background is surface/page and savingbar/text is text/body,
8448
+ * read in the brand mode, so it comes out the same over a light or a dark page. The Buttons are tone action (Salvar)
8449
+ * and tone neutral ghost (Descartar), read on the plate too.
8450
+ * Two arrangements, by the screen width, as the Figma viewport mode (layout/compact below lg 1024): expanded from 1024,
8451
+ * the message grows (at least 160) beside the actions; compact below it, the message on top and Descartar and
8452
+ * Salvar under it, sharing the width.
8453
+ * Details (showDetails, onDetails in code): in compact, the unsaved message becomes a text button with chevron-up 20 at
8454
+ * the right (12 apart) that opens the Drawer with what is missing; hover underlines, focus draws the ring
8455
+ * savingbar/focus/ring (focus/ring-width, radius/focus) 4 around the message box, inside stroke, as the Figma
8456
+ * focus-ring frame. The touch area is 44 tall without changing the drawing. Expanded, the message stays text.
8148
8457
  */
8149
8458
  .rds-savingbar {
8150
8459
  box-sizing: border-box;
8151
- display: flex;
8152
- flex-wrap: wrap;
8153
- align-items: center;
8154
- gap: var(--space-16);
8155
8460
  width: 100%;
8156
8461
  min-width: min(320px, 100%);
8157
8462
  padding: var(--space-12) var(--space-24);
@@ -8160,18 +8465,34 @@ input:focus-visible + .rds-radio__circle {
8160
8465
  font-family: var(--type-font-stack);
8161
8466
  }
8162
8467
 
8468
+ .rds-savingbar__row {
8469
+ display: flex;
8470
+ align-items: center;
8471
+ gap: var(--space-16);
8472
+ }
8473
+
8163
8474
  .rds-savingbar__message {
8164
8475
  display: flex;
8165
- flex: 1;
8476
+ flex: 1 1 160px;
8166
8477
  align-items: center;
8167
8478
  gap: var(--space-12);
8168
- min-width: 0;
8479
+ min-width: 160px;
8169
8480
  margin: 0;
8170
8481
  font-size: var(--type-label-size);
8171
8482
  font-weight: 500;
8172
8483
  line-height: var(--type-label-line);
8173
8484
  }
8174
8485
 
8486
+ .rds-savingbar__text {
8487
+ display: -webkit-box;
8488
+ flex: 1;
8489
+ min-width: 0;
8490
+ overflow: hidden;
8491
+ -webkit-box-orient: vertical;
8492
+ -webkit-line-clamp: 2;
8493
+ line-clamp: 2;
8494
+ }
8495
+
8175
8496
  .rds-savingbar__icon {
8176
8497
  display: inline-flex;
8177
8498
  flex: none;
@@ -8202,10 +8523,74 @@ input:focus-visible + .rds-radio__circle {
8202
8523
 
8203
8524
  .rds-savingbar__actions {
8204
8525
  display: flex;
8205
- flex-wrap: wrap;
8526
+ flex: none;
8206
8527
  gap: var(--space-8);
8207
8528
  }
8208
8529
 
8530
+ .rds-savingbar__details {
8531
+ position: relative;
8532
+ display: none;
8533
+ flex: 1;
8534
+ align-items: center;
8535
+ gap: var(--space-12);
8536
+ min-width: 0;
8537
+ margin: 0;
8538
+ padding: 0;
8539
+ border: 0;
8540
+ border-radius: var(--radius-focus);
8541
+ background: none;
8542
+ color: inherit;
8543
+ font: inherit;
8544
+ text-align: start;
8545
+ cursor: pointer;
8546
+ }
8547
+
8548
+ /* The touch area: 44 tall around the message, invisible. */
8549
+ .rds-savingbar__details::after {
8550
+ content: '';
8551
+ position: absolute;
8552
+ top: 50%;
8553
+ right: 0;
8554
+ left: 0;
8555
+ min-height: 44px;
8556
+ height: 100%;
8557
+ transform: translateY(-50%);
8558
+ }
8559
+
8560
+ .rds-savingbar__details:hover .rds-savingbar__text {
8561
+ text-decoration: underline;
8562
+ }
8563
+
8564
+ .rds-savingbar__details:focus-visible {
8565
+ outline: var(--focus-ring-width) solid var(--savingbar-focus-ring);
8566
+ outline-offset: var(--focus-ring-width);
8567
+ }
8568
+
8569
+ @media (max-width: 1023px) {
8570
+ .rds-savingbar__row {
8571
+ flex-direction: column;
8572
+ align-items: stretch;
8573
+ }
8574
+
8575
+ .rds-savingbar__message {
8576
+ flex: none;
8577
+ min-width: 0;
8578
+ }
8579
+
8580
+ .rds-savingbar__actions > * {
8581
+ flex: 1 1 0;
8582
+ min-width: 0;
8583
+ }
8584
+
8585
+ .rds-savingbar__message--details > .rds-savingbar__text {
8586
+ display: none;
8587
+ }
8588
+
8589
+ .rds-savingbar__details {
8590
+ display: flex;
8591
+ }
8592
+ }
8593
+
8209
8594
  @media (forced-colors: active) {
8210
8595
  .rds-savingbar {
8211
8596
  border-top: var(--border-width) solid CanvasText;
@@ -8573,9 +8958,12 @@ input:focus-visible + .rds-radio__circle {
8573
8958
  /*
8574
8959
  * Sidebar (Navigation collection, sidebar/*): 240 wide (64 collapsed), 12 × 8 inside, a 1px border on the right.
8575
8960
  * Header: the brand mark (24) and the module (16/24 medium), 10 apart, 44 tall. Entries of 44, 12 inside, 12 between
8576
- * icon (20) and label (14/20 medium), 4 apart; the current one on the brand tint with the label in colors/primary.
8961
+ * icon (20) and label (14/20 medium), 4 apart; the current one on the brand tint, its label semibold in
8962
+ * sidebar/item/label/active and a 3 × 20 marker on the left in sidebar/item/indicator, so the current entry does not
8963
+ * rest on colour alone.
8577
8964
  * Section labels 11/14 bold, 16 above and 6 below, with a 14 chevron. Foot: who is signed in (12/16) and Sair.
8578
- * dark (deprecated in the Figma) reads sidebar/dark/*; the current entry stays the light pill.
8965
+ * No tone: the Sidebar follows its container's mode. The brand-coloured bar is a `.ds-plate` around it (the brand
8966
+ * mode), the dark one a `.dark`.
8579
8967
  */
8580
8968
  .rds-sidebar {
8581
8969
  --_background: var(--sidebar-background);
@@ -8601,21 +8989,6 @@ input:focus-visible + .rds-radio__circle {
8601
8989
  font-family: var(--type-font-stack);
8602
8990
  }
8603
8991
 
8604
- .rds-sidebar--dark {
8605
- --_background: var(--sidebar-dark-background);
8606
- --_label: var(--sidebar-dark-item-label-default);
8607
- --_label-hover: var(--sidebar-dark-item-label-hover);
8608
- --_hover: var(--sidebar-dark-item-background-hover);
8609
- --_module: var(--sidebar-dark-module);
8610
- --_user: var(--sidebar-dark-user);
8611
- --_section: var(--sidebar-dark-section-label);
8612
- --_count: var(--sidebar-dark-item-label-default);
8613
- /* No dark ring token: the strongest text over the brand, which is what the ring needs to show there. */
8614
- --_ring: var(--sidebar-dark-module);
8615
-
8616
- border-right-color: transparent;
8617
- }
8618
-
8619
8992
  .rds-sidebar--collapsed {
8620
8993
  width: var(--space-64);
8621
8994
  }
@@ -8678,6 +9051,7 @@ input:focus-visible + .rds-radio__circle {
8678
9051
  }
8679
9052
 
8680
9053
  .rds-sidebar__item {
9054
+ position: relative;
8681
9055
  box-sizing: border-box;
8682
9056
  display: flex;
8683
9057
  align-items: center;
@@ -8737,8 +9111,21 @@ input:focus-visible + .rds-radio__circle {
8737
9111
  color: var(--sidebar-item-label-active);
8738
9112
  }
8739
9113
 
8740
- .rds-sidebar__item[aria-current='page'] .rds-sidebar__count {
8741
- color: var(--sidebar-item-label-active);
9114
+ .rds-sidebar__item[aria-current='page'] .rds-sidebar__label {
9115
+ font-weight: 600;
9116
+ }
9117
+
9118
+ /* Figma .sidebar/item state=active: the marker, 3 × 20, on the left edge, vertically centred, radius 2. */
9119
+ .rds-sidebar__item[aria-current='page']::before {
9120
+ content: '';
9121
+ position: absolute;
9122
+ inset-inline-start: 0;
9123
+ top: 50%;
9124
+ width: 3px;
9125
+ height: var(--size-20);
9126
+ border-radius: 2px;
9127
+ background: var(--sidebar-item-indicator);
9128
+ transform: translateY(-50%);
8742
9129
  }
8743
9130
 
8744
9131
  .rds-sidebar__item:focus-visible,
@@ -8772,9 +9159,12 @@ input:focus-visible + .rds-radio__circle {
8772
9159
  cursor: pointer;
8773
9160
  }
8774
9161
 
9162
+ /* Figma .sidebar/section: label in caps with 6% tracking; the count keeps its own case and no tracking. */
8775
9163
  .rds-sidebar__section-label {
8776
9164
  flex: 1;
8777
9165
  min-width: 0;
9166
+ text-transform: uppercase;
9167
+ letter-spacing: 0.06em;
8778
9168
  }
8779
9169
 
8780
9170
  .rds-sidebar__section-count {
@@ -8804,6 +9194,10 @@ input:focus-visible + .rds-radio__circle {
8804
9194
  .rds-sidebar__item[aria-current='page'] {
8805
9195
  outline: var(--border-width) solid CanvasText;
8806
9196
  }
9197
+
9198
+ .rds-sidebar__item[aria-current='page']::before {
9199
+ background: Highlight;
9200
+ }
8807
9201
  }
8808
9202
 
8809
9203
  /* components/skeleton.css */
@@ -9197,6 +9591,7 @@ input:focus-visible + .rds-radio__circle {
9197
9591
  /*
9198
9592
  * Stat (Content collection, stat/*): 8 between the text and the sparkline. Text: the label 14/20, the row (the
9199
9593
  * value in type/value bold and the Delta, 8 apart, wrapping 4 below) and the caption 12/16, 4 apart.
9594
+ * tone neutral (default), success, danger, warning; muted greys a zero out.
9200
9595
  * framed=true: 16 inside, a 1px border, corners radius/container. framed=false (the SummaryBar cell): 12 16, no border.
9201
9596
  */
9202
9597
  .rds-stat {
@@ -9218,11 +9613,11 @@ input:focus-visible + .rds-radio__circle {
9218
9613
  border-radius: var(--radius-container);
9219
9614
  }
9220
9615
 
9221
- .rds-stat--positive {
9616
+ .rds-stat--success {
9222
9617
  --_value: var(--stat-value-positive);
9223
9618
  }
9224
9619
 
9225
- .rds-stat--negative {
9620
+ .rds-stat--danger {
9226
9621
  --_value: var(--stat-value-negative);
9227
9622
  }
9228
9623
 
@@ -9230,6 +9625,7 @@ input:focus-visible + .rds-radio__circle {
9230
9625
  --_value: var(--stat-value-warning);
9231
9626
  }
9232
9627
 
9628
+ /* muted (zero, nothing to see) wins over the tone: the Figma draws it only on neutral. */
9233
9629
  .rds-stat--muted {
9234
9630
  --_value: var(--stat-value-muted);
9235
9631
  }
@@ -9456,6 +9852,35 @@ input:focus-visible + .rds-radio__circle {
9456
9852
  }
9457
9853
  }
9458
9854
 
9855
+ /* components/stepper.css */
9856
+ /* @tokens stepper */
9857
+ /*
9858
+ * Stepper: no tokens of its own; the Card and the Buttons bring theirs. A pill (radius/full) of 44 Buttons,
9859
+ * 4 inside and 4 apart, raised by elevation/overlay because it floats over the page. A vertical Separator, 24
9860
+ * tall, before the action.
9861
+ */
9862
+ .rds-stepper {
9863
+ flex-direction: row;
9864
+ align-items: center;
9865
+ gap: var(--space-4);
9866
+ width: max-content;
9867
+ max-width: 100%;
9868
+ padding: var(--space-4);
9869
+ border-radius: var(--radius-full);
9870
+ box-shadow: var(--elevation-overlay);
9871
+ overflow-x: auto;
9872
+ }
9873
+
9874
+ .rds-stepper > .rds-button {
9875
+ flex: none;
9876
+ border-radius: var(--radius-full);
9877
+ }
9878
+
9879
+ .rds-stepper > .rds-stepper__divider {
9880
+ align-self: center;
9881
+ height: var(--size-24);
9882
+ }
9883
+
9459
9884
  /* components/summary-bar.css */
9460
9885
  /* @tokens summary-bar */
9461
9886
  /*
@@ -10390,23 +10815,13 @@ tbody > tr:last-child > .rds-table__status {
10390
10815
  }
10391
10816
  }
10392
10817
 
10393
- /* components/toggle-card-compact.css */
10394
- /* @tokens toggle-card-compact */
10395
- /*
10396
- * ToggleCardCompact: no tokens of its own; the Item, the Switch and the IconButton bring theirs. The pencil and the
10397
- * Switch 8 apart at the end of the row.
10398
- */
10399
- .rds-toggle-card-compact__actions {
10400
- display: inline-flex;
10401
- align-items: center;
10402
- gap: var(--space-8);
10403
- }
10404
-
10405
10818
  /* components/toggle-card.css */
10406
10819
  /* @tokens toggle-card */
10407
10820
  /*
10408
- * ToggleCard: no tokens of its own; the Card and the Switch bring theirs. The Switch row pads 16 on the sides (4 top and
10409
- * bottom); the options under it pad 16, 16 apart, after a line in the card's border colour.
10821
+ * ToggleCard: no tokens of its own; the Card, the Item, the Switch and the IconButton bring theirs.
10822
+ * layout=default: the Switch row pads 16 on the sides (4 top and bottom); the options under it pad 16, 16 apart,
10823
+ * after a line in the card's border colour.
10824
+ * layout=compact: the outline Item; the pencil and the Switch 8 apart at the end of the row.
10410
10825
  */
10411
10826
  .rds-toggle-card__header {
10412
10827
  padding: var(--space-4) var(--space-16);
@@ -10420,6 +10835,12 @@ tbody > tr:last-child > .rds-table__status {
10420
10835
  border-top: var(--border-width) solid var(--card-border);
10421
10836
  }
10422
10837
 
10838
+ .rds-toggle-card__actions {
10839
+ display: inline-flex;
10840
+ align-items: center;
10841
+ gap: var(--space-8);
10842
+ }
10843
+
10423
10844
  /* components/toggle-group.css */
10424
10845
  /* @tokens toggle-group */
10425
10846
  /* ToggleGroup: Toggles side by side, 4 apart (Figma: slot items, gap space/4). No tokens of its own. */