@redseed/redseed-ui-tailwindcss 7.56.0 → 7.58.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -153,6 +153,38 @@
153
153
  @apply hover:bg-background-brand-contrast;
154
154
  }
155
155
 
156
+ /*
157
+ * Square off the edge each endpoint faces the range on, so the band closes.
158
+ *
159
+ * The base `.rsui-form-field-date-range__day` is `rounded-lg` on all four
160
+ * corners and the endpoints only override the background, so an endpoint used to
161
+ * sit between two square in-range fills as a rounded square — leaving a white
162
+ * notch at each corner where its curve pulled away from its neighbour. The band
163
+ * read as interrupted by the endpoint rather than containing it.
164
+ *
165
+ * MUI solves the same problem by drawing a continuous highlight band behind the
166
+ * cells and putting the endpoint circle on top of it. That needs a second
167
+ * element per cell; squaring the inner edge of the endpoint's own fill gets the
168
+ * same join out of the existing one.
169
+ */
170
+ .rsui-form-field-date-range__day--range-start {
171
+ @apply rounded-r-none;
172
+ }
173
+
174
+ .rsui-form-field-date-range__day--range-end {
175
+ @apply rounded-l-none;
176
+ }
177
+
178
+ /*
179
+ * Both modifiers land on the same day for a single-day window — `today`, or a
180
+ * range picked start-and-end on one date. There is no band to join, so restore
181
+ * the full radius. This selector is deliberately last and doubly-classed so it
182
+ * outranks the two above.
183
+ */
184
+ .rsui-form-field-date-range__day--range-start.rsui-form-field-date-range__day--range-end {
185
+ @apply rounded-lg;
186
+ }
187
+
156
188
  /*
157
189
  * The day the presets resolve against — "today" as the server sees it.
158
190
  *
@@ -88,42 +88,52 @@
88
88
 
89
89
  .rsui-icon--primary {
90
90
  @apply *:text-text-primary;
91
+ --rsui-icon-pulse: var(--color-text-primary);
91
92
  }
92
93
 
93
94
  .rsui-icon--secondary {
94
95
  @apply *:text-text-secondary;
96
+ --rsui-icon-pulse: var(--color-text-secondary);
95
97
  }
96
98
 
97
99
  .rsui-icon--brand {
98
100
  @apply *:text-text-brand;
101
+ --rsui-icon-pulse: var(--color-text-brand);
99
102
  }
100
103
 
101
104
  .rsui-icon--success {
102
105
  @apply *:text-text-success;
106
+ --rsui-icon-pulse: var(--color-text-success);
103
107
  }
104
108
 
105
109
  .rsui-icon--info {
106
110
  @apply *:text-text-info;
111
+ --rsui-icon-pulse: var(--color-text-info);
107
112
  }
108
113
 
109
114
  .rsui-icon--warning {
110
115
  @apply *:text-text-warning;
116
+ --rsui-icon-pulse: var(--color-text-warning);
111
117
  }
112
118
 
113
119
  .rsui-icon--error {
114
120
  @apply *:text-text-error;
121
+ --rsui-icon-pulse: var(--color-text-error);
115
122
  }
116
123
 
117
124
  .rsui-icon--ai {
118
125
  @apply *:text-text-ai;
126
+ --rsui-icon-pulse: var(--color-text-ai);
119
127
  }
120
128
 
121
129
  .rsui-icon--disabled {
122
130
  @apply *:text-text-disabled;
131
+ --rsui-icon-pulse: var(--color-text-disabled);
123
132
  }
124
133
 
125
134
  .rsui-icon--classic {
126
135
  @apply *:text-pink-500;
136
+ --rsui-icon-pulse: var(--color-pink-500);
127
137
  }
128
138
 
129
139
  .rsui-icon--primary.rsui-icon--invert {
@@ -216,52 +226,145 @@
216
226
  @apply *:text-text-on-color;
217
227
  }
218
228
 
229
+ /*
230
+ * Both flags together is the one combination that puts the glyph back on its
231
+ * variant colour, against a tinted fill — so each of these restates the pulse
232
+ * token alongside it, undoing the on-colour default set below. Kept here rather
233
+ * than in a block of its own so the ring colour is edited in the same place as
234
+ * the glyph colour it has to match.
235
+ */
219
236
  .rsui-icon--primary.rsui-icon--background.rsui-icon--invert {
220
237
  @apply bg-background-primary-invert;
221
238
  @apply *:text-text-primary;
239
+ --rsui-icon-pulse: var(--color-text-primary);
222
240
  }
223
241
 
224
242
  .rsui-icon--secondary.rsui-icon--background.rsui-icon--invert {
225
243
  @apply bg-background-secondary-invert;
226
244
  @apply *:text-text-secondary;
245
+ --rsui-icon-pulse: var(--color-text-secondary);
227
246
  }
228
247
 
229
248
  .rsui-icon--brand.rsui-icon--background.rsui-icon--invert {
230
249
  @apply bg-background-brand-invert;
231
250
  @apply *:text-text-brand;
251
+ --rsui-icon-pulse: var(--color-text-brand);
232
252
  }
233
253
 
234
254
  .rsui-icon--success.rsui-icon--background.rsui-icon--invert {
235
255
  @apply bg-background-success-invert;
236
256
  @apply *:text-text-success;
257
+ --rsui-icon-pulse: var(--color-text-success);
237
258
  }
238
259
 
239
260
  .rsui-icon--info.rsui-icon--background.rsui-icon--invert {
240
261
  @apply bg-background-info-invert;
241
262
  @apply *:text-text-info;
263
+ --rsui-icon-pulse: var(--color-text-info);
242
264
  }
243
265
 
244
266
  .rsui-icon--warning.rsui-icon--background.rsui-icon--invert {
245
267
  @apply bg-background-warning-invert;
246
268
  @apply *:text-text-warning;
269
+ --rsui-icon-pulse: var(--color-text-warning);
247
270
  }
248
271
 
249
272
  .rsui-icon--error.rsui-icon--background.rsui-icon--invert {
250
273
  @apply bg-background-error-invert;
251
274
  @apply *:text-text-error;
275
+ --rsui-icon-pulse: var(--color-text-error);
252
276
  }
253
277
 
254
278
  .rsui-icon--ai.rsui-icon--background.rsui-icon--invert {
255
279
  @apply bg-background-ai-invert;
256
280
  @apply *:text-text-ai;
281
+ --rsui-icon-pulse: var(--color-text-ai);
257
282
  }
258
283
 
259
284
  .rsui-icon--disabled.rsui-icon--background.rsui-icon--invert {
260
285
  @apply bg-background-disabled-invert;
261
286
  @apply *:text-text-disabled;
287
+ --rsui-icon-pulse: var(--color-text-disabled);
262
288
  }
263
289
 
264
290
  .rsui-icon--classic.rsui-icon--background.rsui-icon--invert {
265
291
  @apply bg-pink-50;
266
292
  @apply *:text-pink-500;
267
- }
293
+ --rsui-icon-pulse: var(--color-pink-500);
294
+ }
295
+ /*
296
+ * On a filled or inverted icon the glyph is repainted to an on-colour token, so
297
+ * the ring follows it rather than staying on a variant colour it no longer
298
+ * matches. Same specificity as the base variant rules and declared after them,
299
+ * so it wins on source order — but it loses to the two-flag rules above, which
300
+ * is the point: those put the glyph back on its variant colour and take the ring
301
+ * with them.
302
+ */
303
+ .rsui-icon--background,
304
+ .rsui-icon--invert {
305
+ --rsui-icon-pulse: var(--color-text-on-color);
306
+ }
307
+
308
+ /*
309
+ * Optional attention pulse: a ring expands out from the icon and fades, a few
310
+ * times, when the icon arrives.
311
+ *
312
+ * Deliberately a fixed number of iterations rather than `infinite`. An animation
313
+ * that repeats for more than five seconds needs a pause control (WCAG 2.2.2), and
314
+ * an icon has nowhere sensible to put one — three bursts draw the eye on arrival
315
+ * without taking on that obligation.
316
+ *
317
+ * Duration x iterations is the number that matters there, and it must stay under
318
+ * five seconds: 1.4s x 3 leaves 800ms of headroom. Slowing the ring to 1.8s to
319
+ * soften it further would put the total at 5.4s and trip the criterion, so the
320
+ * softening is done with opacity, border width and travel instead.
321
+ *
322
+ * The ring takes its colour from `--rsui-icon-pulse`, which each colour variant
323
+ * sets alongside its glyph rule.
324
+ *
325
+ * A custom property rather than `currentColor`: the variants colour the SVG child
326
+ * (`*:text-…`) and not the wrapper, so an inherited ring comes out near-black.
327
+ * Setting `color` on the wrapper instead would fix the base variants but silently
328
+ * miss `--invert` and `--background`, which repaint the glyph and would leave the
329
+ * ring on the old colour. A property the combination rules can override keeps the
330
+ * answer in one place — and, unlike a wrapper colour, it is inert for everything
331
+ * that does not read it.
332
+ *
333
+ * `pointer-events-none` because the ring overflows the icon's box and would
334
+ * otherwise sit over whatever is beside it.
335
+ */
336
+ .rsui-icon--pulse {
337
+ @apply relative;
338
+ }
339
+
340
+ .rsui-icon--pulse::after {
341
+ @apply content-[''] absolute inset-0 rounded-full pointer-events-none;
342
+ border: 1px solid var(--rsui-icon-pulse, currentColor);
343
+ /* Invisible at rest, in both directions. Without this the ring reverts to its
344
+ un-animated state once the iterations finish — full opacity at scale 1 —
345
+ and a solid ring stays welded around the icon for the life of the page. */
346
+ @apply opacity-0;
347
+ animation: rsui-icon-pulse 1.4s ease-out 3;
348
+ }
349
+
350
+ @keyframes rsui-icon-pulse {
351
+ 0% {
352
+ opacity: 0.35;
353
+ transform: scale(1);
354
+ }
355
+ 100% {
356
+ opacity: 0;
357
+ transform: scale(1.8);
358
+ }
359
+ }
360
+
361
+ /*
362
+ * The pulse is decoration on top of an icon that is already visible, so removing
363
+ * it costs nothing — no state is conveyed by the animation alone.
364
+ */
365
+ @media (prefers-reduced-motion: reduce) {
366
+ .rsui-icon--pulse::after {
367
+ animation: none;
368
+ display: none;
369
+ }
370
+ }
@@ -1,5 +1,46 @@
1
+ /*
2
+ * A row: optional icon, the text column, optional close. `items-start` so the
3
+ * icon and the close button align with the first line rather than centring
4
+ * against a tall body.
5
+ */
1
6
  .rsui-message-box {
2
- @apply border rounded-lg overflow-hidden p-4 flex flex-col gap-y-3;
7
+ @apply border rounded-lg overflow-hidden p-4 flex items-start gap-x-3;
8
+ }
9
+
10
+ /*
11
+ * The text column. Carries the vertical rhythm the box itself used to own, so a
12
+ * box with no icon and no actions lays out exactly as it did before.
13
+ */
14
+ .rsui-message-box__main {
15
+ @apply flex-1 flex flex-col gap-y-3;
16
+ }
17
+
18
+ /*
19
+ * Narrow and with an icon: the icon and the close button take a row of their own
20
+ * and the text runs full width beneath them, rather than indenting past a column
21
+ * that costs more than it gives at this width.
22
+ *
23
+ * Ordering is what makes it work — the DOM runs icon, text, close, so without it
24
+ * the full-width text column would wrap between the two and strand the close
25
+ * button on a third row. Scoped to `--with-icon` because a box with no icon has
26
+ * no column to escape: its close button already sits beside the title, and a
27
+ * lone X on its own row would be a wasted line.
28
+ *
29
+ * The box itself sets only `gap-x`, which buys nothing once these become two
30
+ * flex lines — so the row gap is set here, matching the text column's own
31
+ * rhythm. Inert at `sm:flex-nowrap`, where there is only ever one line.
32
+ */
33
+ .rsui-message-box--with-icon {
34
+ @apply flex-wrap gap-y-3 sm:flex-nowrap;
35
+ }
36
+
37
+ .rsui-message-box--with-icon .rsui-message-box__close {
38
+ @apply order-2 ms-auto sm:order-3 sm:ms-0;
39
+ }
40
+
41
+ /* `sm:basis-0` rather than `basis-auto`, to restore exactly what `flex-1` sets. */
42
+ .rsui-message-box--with-icon .rsui-message-box__main {
43
+ @apply order-3 basis-full sm:order-2 sm:basis-0;
3
44
  }
4
45
 
5
46
  .rsui-message-box--default {
@@ -37,17 +78,76 @@
37
78
  }
38
79
 
39
80
  .rsui-message-box__head {
40
- @apply flex justify-between items-center gap-x-2;
81
+ @apply flex items-center gap-x-2;
41
82
  }
42
83
 
43
84
  .rsui-message-box__content {
44
- @apply flex justify-between items-start gap-x-2;
85
+ @apply flex items-start gap-x-2;
86
+ }
87
+
88
+ /*
89
+ * `items-start` so the icon aligns with the first line of the message rather
90
+ * than centring against a multi-line body. `shrink-0` keeps it from being
91
+ * squeezed by long text.
92
+ */
93
+ .rsui-message-box__icon {
94
+ @apply shrink-0 flex items-center h-6;
95
+ }
96
+
97
+ /*
98
+ * Actions sit under the message, indented to the body rather than the icon, so
99
+ * they read as belonging to the text.
100
+ *
101
+ * Neutral, not variant-coloured: a coloured action on a coloured tint is a
102
+ * contrast problem, and the action is a way out of the message rather than a
103
+ * restatement of its severity. The dismiss is quieter than whatever the consumer
104
+ * puts beside it, which is the only hierarchy this row needs.
105
+ */
106
+ .rsui-message-box__actions {
107
+ @apply flex flex-wrap items-center gap-x-4 gap-y-2 pt-1;
108
+ }
109
+
110
+ .rsui-message-box__dismiss,
111
+ .rsui-message-box__action {
112
+ @apply bg-transparent border-0 p-0 cursor-pointer;
113
+ @apply text-sm font-semibold transition-colors;
114
+ @apply hover:underline underline-offset-4 decoration-2;
115
+ @apply outline-hidden focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-border-primary rounded-sm;
116
+ }
117
+
118
+ /*
119
+ * Two tiers, and the only hierarchy this row needs: dismiss is the quieter of
120
+ * the pair, whatever the consumer puts beside it is the one they want pressed.
121
+ */
122
+ .rsui-message-box__dismiss {
123
+ @apply text-text-secondary hover:text-text-primary;
124
+ }
125
+
126
+ .rsui-message-box__action {
127
+ @apply text-text-primary;
45
128
  }
46
129
 
130
+ /*
131
+ * `-my-2` so the 40px hit target centres on the first 24px line rather than
132
+ * hanging 8px below it. Under `items-start` the button's own box starts at the
133
+ * padding edge, which put its glyph at y=36 against a title centred at y=28 —
134
+ * and, with an icon shown, two icons in the same row not lining up. The negative
135
+ * margin keeps the target size while claiming only 24px of layout height.
136
+ */
47
137
  .rsui-message-box__close {
48
- @apply size-10;
138
+ @apply size-10 shrink-0 -my-2;
49
139
  }
50
140
 
141
+ /*
142
+ * The glyph colour is set on the Icon itself (`secondary`), not here — the
143
+ * variant rules target the SVG child directly, so a colour on this button would
144
+ * lose to them.
145
+ *
146
+ * It was `disabled` before, which painted a working control in the disabled text
147
+ * colour — Grey-400, 2.41:1 on white — so it looked permanently greyed out and
148
+ * fell under the 3:1 WCAG 1.4.11 asks of a control. Grey-700 reads as quiet
149
+ * without reading as dead.
150
+ */
51
151
  .rsui-message-box__close-icon {
52
152
  @apply size-10 cursor-pointer rounded-lg flex items-center justify-center hover:bg-border-secondary transition duration-200;
53
153
  /* Reset native <button> chrome so it matches the prior inline affordance ... */
@@ -1,4 +1,18 @@
1
1
  .rsui-meta-info {
2
+ /* TIGHT PAIR — 4px between a label and its value, deliberately off the brand's 8px
3
+ rhythm. See the note above .rsui-card-header__text in card_header.css for the full
4
+ reasoning. Do not "fix" it back to space-xs.
5
+
6
+ The book assigns 8px to a label/value pair, but that assumes 16px body text, where
7
+ 8px is a third of a line box. This component sets 12px with a 16px line box, so 8px
8
+ is HALF a line — measured — and at that size the pair stops reading as one field and
9
+ reads as two loose rows. 4px is a quarter of the line, and against the 16px between
10
+ fields it gives a 1:4 grouping instead of 1:2.
11
+
12
+ The real cause is that the meta is 12px at all, which is below the brand's own 14px
13
+ caption floor. Fix the size and 8px becomes correct; that belongs with the MetaInfo
14
+ size ramp in #316, not here. Until then this is the size the component ships at, and
15
+ the gap has to suit it. */
2
16
  @apply flex flex-col gap-y-1;
3
17
  }
4
18
 
@@ -6,7 +20,7 @@
6
20
  legacy pattern, double-counts against any gap and breaks once the row wraps. Every other
7
21
  component in the library spaces with gap. */
8
22
  .rsui-meta-info__top {
9
- @apply flex gap-x-1 items-center;
23
+ @apply flex gap-x-space-xs items-center;
10
24
  }
11
25
 
12
26
  .rsui-meta-info__label-icon {
@@ -18,7 +32,7 @@
18
32
  eye landed on "Age" instead of on the number. Grey-600 on white measures 7.26:1, so it stays
19
33
  comfortably readable at 12px. */
20
34
  .rsui-meta-info__label {
21
- @apply font-medium text-xs text-text-tertiary;
35
+ @apply font-medium text-text-tertiary;
22
36
  }
23
37
 
24
38
  .rsui-meta-info__help {
@@ -32,25 +46,37 @@
32
46
  /* The value carries the information, so it takes the emphasis the label gave up. */
33
47
  .rsui-meta-info__value {
34
48
  @apply flex items-center gap-x-space-xs;
35
- @apply text-xs font-semibold text-text-primary;
49
+ @apply font-semibold text-text-primary;
36
50
  }
37
51
 
38
- .rsui-meta-info--md .rsui-meta-info__label {
39
- @apply text-sm;
52
+ /* SIZE RAMP. Three steps, matching StageDial. The label and value always share a
53
+ size — they are one field, and a field whose descriptor and content disagree on
54
+ size reads as two things.
55
+
56
+ `sm` is the default, and it is now DECLARED rather than left implicit in the base
57
+ rules. The size used to live on .rsui-meta-info__label and __value directly, so
58
+ the default had no class of its own: it could not be targeted, and the ramp read
59
+ as "md, lg, or nothing".
60
+
61
+ The names sit one step below the scale they produce — sm is text-xs, md is
62
+ text-sm, lg is text-base. That predates this change and is deliberately not
63
+ renamed: md and lg are used in consuming apps, so renaming them is a breaking
64
+ change for a cosmetic gain. */
65
+ .rsui-meta-info--sm .rsui-meta-info__label,
66
+ .rsui-meta-info--sm .rsui-meta-info__value {
67
+ @apply text-xs;
40
68
  }
41
69
 
70
+ .rsui-meta-info--md .rsui-meta-info__label,
42
71
  .rsui-meta-info--md .rsui-meta-info__value {
43
72
  @apply text-sm;
44
73
  }
45
74
 
46
- .rsui-meta-info--lg .rsui-meta-info__label {
47
- @apply text-base;
48
- }
49
-
75
+ .rsui-meta-info--lg .rsui-meta-info__label,
50
76
  .rsui-meta-info--lg .rsui-meta-info__value {
51
77
  @apply text-base;
52
78
  }
53
79
 
54
80
  .rsui-meta-info--inline {
55
- @apply flex-row flex-wrap items-center gap-x-2 gap-y-1;
81
+ @apply flex-row flex-wrap items-center gap-x-space-xs gap-y-space-xs;
56
82
  }
@@ -14,7 +14,7 @@
14
14
  }
15
15
 
16
16
  .rsui-metric-card__heading {
17
- @apply w-full flex items-center gap-space-sm;
17
+ @apply w-full flex items-center gap-space-md;
18
18
  }
19
19
 
20
20
  .rsui-metric-card__icon {
@@ -1,39 +1,71 @@
1
+ /* gap, not space-y. space-* adds margins to children, which is the legacy pattern the
2
+ rest of the library has moved off — see the note in meta_info.css. It double-counts
3
+ against any margin a child sets for itself and it breaks once a row wraps. Both
4
+ happened here: see __title below. */
1
5
  .rsui-page-header {
2
- @apply w-full flex justify-between space-y-4;
6
+ @apply w-full flex justify-between gap-y-space-md;
3
7
  @apply lg:flex-col;
4
8
  }
5
9
 
6
10
  .rsui-page-header__top {
7
- @apply w-full flex flex-col items-start space-y-2 flex-wrap;
8
- @apply lg:flex-row lg:space-y-0 lg:items-center;
11
+ @apply w-full flex flex-col items-start gap-y-space-xs flex-wrap;
12
+ @apply lg:flex-row lg:gap-y-0 lg:items-center;
9
13
  }
10
14
 
15
+ /* 16px avatar -> title, matching the card family's avatar gap, and set once as a gap
16
+ rather than twice as margins.
17
+
18
+ It was space-x-6 here plus mr-3 on the avatar. In Tailwind v4 space-x-* sets
19
+ margin-inline-end on every child but the last, so the avatar's own mr-3 overrode it
20
+ and the rendered gap was 12px, not the 24px this rule reads as. Measured. Neither
21
+ value was reachable by editing the other, which is the whole problem with space-*. */
11
22
  .rsui-page-header__title {
12
- @apply pr-2 flex flex-row items-start space-x-6;
23
+ @apply pr-space-xs flex flex-row items-start gap-x-space-md;
13
24
  }
14
25
 
26
+ /* Material 3 puts a prominent page title in its Headline range and sets all UI type in
27
+ a sans face — so this drops Newsreader and lands on the two RedSeed steps that cover
28
+ that range: Header 3 (Inter Bold 28/120%) below lg, Header 2 (Inter Black 40/115%,
29
+ -1% tracking) from lg up.
30
+
31
+ It was font-redseed-heading — which resolves to Newsreader — at 30 -> 36px. Off-brand
32
+ twice over: the book restricts Newsreader to Header 1 and says not to push it below
33
+ Header 1 sizes, and neither 30 nor 36 is a step on the scale at all.
34
+
35
+ 40px also keeps a page title a clear step above SectionHeader's 28px, which is the
36
+ hierarchy M3 maintains between a top app bar and a heading inside content.
37
+
38
+ Deviation worth naming: M3 sets top-app-bar titles at weight 400 Regular. RedSeed's
39
+ scale specifies Bold for Header 3 and Black for Header 2, and the tokens win here per
40
+ the same rule the card family followed — M3's structure, RedSeed's type.
41
+
42
+ lg:mr-4 removed. __title-text-container already supplies a 24px gap between the title
43
+ and the status slot, so the margin added to it and the rendered gap was 40px — the
44
+ same accidental sum the avatar had. */
15
45
  .rsui-page-header__title h1 {
16
- @apply font-redseed-heading text-3xl lg:text-4xl font-semibold text-text-primary lg:mr-4;
46
+ @apply text-[1.75rem] leading-[1.2] font-bold text-text-primary;
47
+ @apply lg:text-[2.5rem] lg:leading-[1.15] lg:tracking-[-0.01em] lg:font-black;
17
48
  }
18
49
 
19
50
  .rsui-page-header__title-text-container {
20
- @apply flex flex-row space-x-6 items-center;
51
+ @apply flex flex-row gap-x-space-lg items-center;
21
52
  }
22
53
 
23
54
  .rsui-page-header__status {
24
55
  @apply flex-shrink-0;
25
56
  }
26
57
 
58
+ /* Brand body: 16px at 150%. leading-relaxed is 1.625, so this rendered 16/26. */
27
59
  .rsui-page-header__subtitle {
28
- @apply text-base text-text-secondary leading-relaxed;
60
+ @apply text-base leading-normal text-text-secondary;
29
61
  }
30
62
 
31
63
  .rsui-page-header__status-actions {
32
- @apply flex-1 flex space-x-2 items-center justify-between lg:pr-2;
64
+ @apply flex-1 flex gap-x-space-xs items-center justify-between lg:pr-space-xs;
33
65
  }
34
66
 
35
67
  .rsui-page-header__actions {
36
- @apply flex-1 flex space-x-2 items-center justify-end;
68
+ @apply flex-1 flex flex-wrap gap-space-xs items-center justify-end;
37
69
  }
38
70
 
39
71
  .rsui-page-header__meta-action {
@@ -41,7 +73,7 @@
41
73
  }
42
74
 
43
75
  .rsui-page-header__search {
44
- @apply w-full pt-2 lg:pt-0 lg:w-auto;
76
+ @apply w-full pt-space-xs lg:pt-0 lg:w-auto;
45
77
  }
46
78
 
47
79
  .rsui-page-header__meta-modal {
@@ -49,15 +81,15 @@
49
81
  }
50
82
 
51
83
  .rsui-page-header__meta-modal__body {
52
- @apply flex flex-col space-y-4;
84
+ @apply flex flex-col gap-y-space-md;
53
85
  }
54
86
 
55
87
  .rsui-page-header__meta {
56
- @apply hidden lg:flex space-x-8;
88
+ @apply hidden lg:flex gap-x-space-xl;
57
89
  }
58
90
 
59
91
  .rsui-page-header__avatar {
60
- @apply shrink-0 size-12 mr-3;
92
+ @apply shrink-0 size-12;
61
93
  }
62
94
 
63
95
  /* Profile variant — larger avatar, bottom-aligned text, inline subtitle */
@@ -65,16 +97,18 @@
65
97
  @apply lg:items-end;
66
98
  }
67
99
 
100
+ /* The profile avatar is larger, so it takes more room beside the title than the
101
+ default 16px — 24px from lg up, added to the gap rather than replacing it. */
68
102
  .rsui-page-header--profile .rsui-page-header__avatar {
69
- @apply shrink-0 size-auto mr-3 lg:mr-6 lg:pb-4;
103
+ @apply shrink-0 size-auto lg:me-space-xs lg:pb-space-md;
70
104
  }
71
105
 
72
106
  .rsui-page-header--profile .rsui-page-header__status-actions {
73
- @apply lg:self-end lg:pb-6;
107
+ @apply lg:self-end lg:pb-space-lg;
74
108
  }
75
109
 
76
110
  .rsui-page-header--profile .rsui-page-header__subtitle {
77
- @apply flex flex-col gap-1 lg:flex-row lg:items-center lg:gap-4;
111
+ @apply flex flex-col gap-space-xs lg:flex-row lg:items-center lg:gap-space-md;
78
112
  }
79
113
 
80
114
 
@@ -99,7 +133,7 @@
99
133
  /* Fallbacks keep an unrecognised tone legible rather than transparent. */
100
134
  background: var(--rsui-page-header-bg, var(--color-background-secondary));
101
135
 
102
- @apply py-space-lg px-space-xl;
136
+ @apply p-space-lg;
103
137
  }
104
138
 
105
139
  .rsui-page-header--tone-green {
@@ -1,11 +1,15 @@
1
1
  .rsui-radio-card {
2
2
  @apply relative cursor-pointer transition-all;
3
3
  /* No resting shadow: this was the only card in the family that sat lifted while the
4
- other seven are flat. Padding matches the family's 24/32 rhythm rather than the 12/12
5
- it used to carry alone. ring-offset-2 matches the focus geometry every other card
6
- uses — this ring previously hugged the border with no offset. */
4
+ other seven are flat. ring-offset-2 matches the focus geometry every other card
5
+ uses — this ring previously hugged the border with no offset.
6
+
7
+ Padding is 24/24, the same as every other member — but it has to be written here
8
+ rather than inherited, because RadioCard is the one family member that does NOT
9
+ render a <Card>, so the padding rule in card.css never reaches it. Keep the two in
10
+ step. The 32px sides it used to carry were 20% of its fixed 320px width. */
7
11
  @apply rounded-xl outline-hidden select-none;
8
- @apply flex flex-col gap-3 py-space-lg px-space-xl max-w-80 w-80;
12
+ @apply flex flex-col gap-space-md py-space-lg px-space-lg max-w-80 w-80;
9
13
  @apply bg-background-primary border border-border-primary;
10
14
  @apply focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-border-primary;
11
15
  }
@@ -48,7 +52,7 @@
48
52
  }
49
53
 
50
54
  .rsui-radio-card__title-row {
51
- @apply relative text-base font-medium text-text-primary line-clamp-3 min-h-6 pr-8;
55
+ @apply relative text-xl leading-[1.3] font-medium text-text-primary line-clamp-3 min-h-6 pr-8;
52
56
 
53
57
  @apply after:content-[''] after:absolute after:top-0 after:right-0;
54
58
  @apply after:size-6 after:rounded-full after:transition-all;
@@ -72,8 +76,11 @@
72
76
  @apply after:border-7 after:border-background-primary after:bg-border-primary;
73
77
  }
74
78
 
79
+ /* Brand Header 4, matching .rsui-card-header__title. The row above carries the same
80
+ size deliberately: line-clamp-3 lives there, and it measures against the clamped
81
+ element's own line-height, so a mismatch clips at the wrong place. */
75
82
  .rsui-radio-card__title {
76
- @apply flex-1 text-base font-semibold text-text-primary;
83
+ @apply flex-1 text-xl leading-[1.3] font-semibold text-text-primary;
77
84
  }
78
85
 
79
86
  .rsui-radio-card__content-row {
@@ -85,9 +92,9 @@
85
92
  }
86
93
 
87
94
  .rsui-radio-card__meta-row {
88
- @apply grid grid-cols-1 sm:grid-cols-2 gap-x-8 gap-y-2;
95
+ @apply grid grid-cols-1 sm:grid-cols-2 gap-x-space-xl gap-y-space-xs;
89
96
  }
90
97
 
91
98
  .rsui-radio-card__action-row {
92
- @apply flex flex-wrap gap-2;
99
+ @apply flex flex-wrap gap-space-xs;
93
100
  }