@oods/component-styles 0.3.2 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,6 @@
1
1
  @import "@oods/tokens/css";
2
2
  @import "./statusables.css";
3
+ @import "./components-overlay.css";
3
4
 
4
5
  /* Legacy unprefixed geometry used by billing recipes. Values come from the
5
6
  * semantic layer; preserve these names until their authored callers migrate. */
@@ -12,151 +13,313 @@
12
13
  --radius-md: var(--sys-radius-control);
13
14
  }
14
15
 
16
+ /* s222-m01 (#2502 ruling 8): the document root and every brand scope carry the brand's sans and a line height, so no
17
+ * element falls back to the browser's font or its `normal` line height. */
18
+ :where(:root, [data-brand][data-theme]) {
19
+ font-family: var(--sys-font-sans);
20
+ line-height: var(--sys-text-line-height-root);
21
+ -webkit-font-smoothing: antialiased;
22
+ -moz-osx-font-smoothing: grayscale;
23
+ }
24
+
25
+ /* s222-m02 (#2502 ruling 8): a heading inside a component reads on the type scale, never at the browser's default (a
26
+ * bold 24px h2). A component's own rule places its title on a role; any other h1 or h2 is heading-md and h3 to h6
27
+ * heading-sm. The :where() keeps this below every component rule. */
28
+ :where([data-oods-component]) :where(h1, h2) {
29
+ font-size: var(--sys-text-scale-heading-md-font-size, 18px);
30
+ font-weight: var(--sys-text-scale-heading-md-font-weight, 600);
31
+ line-height: var(--sys-text-scale-heading-md-line-height, 24px);
32
+ }
33
+
34
+ :where([data-oods-component]) :where(h3, h4, h5, h6) {
35
+ font-size: var(--sys-text-scale-heading-sm-font-size, 16px);
36
+ font-weight: var(--sys-text-scale-heading-sm-font-weight, 600);
37
+ line-height: var(--sys-text-scale-heading-sm-line-height, 24px);
38
+ }
39
+
40
+ /* s222-m02 (#2502 ruling 11): a badge is a 20px pill, 12/500 with 2px 8px padding, tinted (the tone's step-3 surface
41
+ * and step-11 text) with no border. */
15
42
  :where(.oods-badge, [data-oods-component='Badge']) {
16
43
  display: inline-flex;
17
44
  align-items: center;
18
45
  gap: var(--cmp-badge-gap, 0.25rem);
19
46
  padding: var(--cmp-badge-padding-block, 0.125rem) var(--cmp-badge-padding-inline, 0.5rem);
20
- border: 1px solid var(--cmp-badge-border, var(--cmp-border-default, currentColor));
47
+ border: 0;
21
48
  border-radius: var(--cmp-badge-radius, 999px);
22
49
  background: var(--cmp-badge-background, var(--cmp-surface-subtle, transparent));
23
50
  color: var(--cmp-badge-text, var(--cmp-text-body, currentColor));
24
- font-size: var(--cmp-badge-font-size, 0.875rem);
25
- font-weight: var(--cmp-badge-font-weight, 600);
51
+ font-size: var(--cmp-badge-font-size, 12px);
52
+ font-weight: var(--cmp-badge-font-weight, 500);
26
53
  }
27
54
 
28
- /* Every governed Badge uses the same geometry, including React's legacy statusable class. */
55
+ /* Every governed Badge uses the same geometry, including React's legacy statusable class: the caption role's 16px line
56
+ * and the 2px block padding make the 20px height. */
29
57
  .oods-badge {
30
- min-block-size: var(--cmp-badge-height, 1.5rem);
58
+ min-block-size: var(--cmp-badge-height, 1.25rem);
31
59
  box-sizing: border-box;
32
- font-size: var(--cmp-badge-font-size, 0.875rem);
33
- line-height: var(--sys-text-line-height-tight, 1.2);
60
+ /* s222-m03: a badge hugs its label, also as the item of a stacked (column) layout, which would otherwise stretch it. */
61
+ inline-size: fit-content;
62
+ max-inline-size: 100%;
63
+ font-size: var(--cmp-badge-font-size, 12px);
64
+ line-height: var(--sys-text-scale-caption-line-height, 16px);
34
65
  letter-spacing: normal;
35
66
  text-transform: none;
67
+ white-space: nowrap;
36
68
  gap: var(--cmp-badge-gap, 0.25rem);
37
69
  }
38
- .oods-badge__label { line-height: inherit; }
70
+ /* s221-m02 (#2482 ruling 2): React and Vue render one Badge markup, an icon slot and a label span, styled here; React's
71
+ * former statusable-badge classes no longer apply. s222-m02: a status mark is an SVG drawn in the text colour at the
72
+ * text's size. */
73
+ .oods-badge__label { display: inline-flex; align-items: center; line-height: inherit; }
74
+ .oods-badge__icon { display: inline-flex; align-items: center; }
75
+ :where(.oods-badge__icon, .oods-banner__icon) > svg { display: block; inline-size: 1em; block-size: 1em; }
76
+
77
+ /* s222-m02 (#2502 ruling 11): a tone paints its tint (step-3 surface, step-11 text; a banner also its step-7 border) and,
78
+ * for emphasis, its solid fill (step 9, darkened until its text passes) with the graded text colour, for badges and banners
79
+ * alike. The tone names are the ones every renderer writes to data-tone, so HTML output needs no inline colours; React and
80
+ * Vue also write the same values inline. */
81
+ :where(.oods-badge, [data-oods-component='Badge'], .oods-banner, [data-oods-component='Banner'])[data-tone='neutral'] {
82
+ --cmp-badge-background: var(--sys-status-neutral-surface);
83
+ --cmp-badge-text: var(--sys-status-neutral-text);
84
+ --cmp-banner-background: var(--sys-status-neutral-surface);
85
+ --cmp-banner-border: var(--sys-status-neutral-border);
86
+ --cmp-banner-text: var(--sys-status-neutral-text);
87
+ --oods-tone-solid: var(--sys-status-neutral-solid);
88
+ --oods-tone-on-solid: var(--sys-status-neutral-on-solid);
89
+ }
90
+
91
+ :where(.oods-badge, [data-oods-component='Badge'], .oods-banner, [data-oods-component='Banner'])[data-tone='info'] {
92
+ --cmp-badge-background: var(--sys-status-info-surface);
93
+ --cmp-badge-text: var(--sys-status-info-text);
94
+ --cmp-banner-background: var(--sys-status-info-surface);
95
+ --cmp-banner-border: var(--sys-status-info-border);
96
+ --cmp-banner-text: var(--sys-status-info-text);
97
+ --oods-tone-solid: var(--sys-status-info-solid);
98
+ --oods-tone-on-solid: var(--sys-status-info-on-solid);
99
+ }
100
+
101
+ :where(.oods-badge, [data-oods-component='Badge'], .oods-banner, [data-oods-component='Banner'])[data-tone='accent'] {
102
+ --cmp-badge-background: var(--sys-status-accent-surface);
103
+ --cmp-badge-text: var(--sys-status-accent-text);
104
+ --cmp-banner-background: var(--sys-status-accent-surface);
105
+ --cmp-banner-border: var(--sys-status-accent-border);
106
+ --cmp-banner-text: var(--sys-status-accent-text);
107
+ --oods-tone-solid: var(--sys-status-accent-solid);
108
+ --oods-tone-on-solid: var(--sys-status-accent-on-solid);
109
+ }
110
+
111
+ :where(.oods-badge, [data-oods-component='Badge'], .oods-banner, [data-oods-component='Banner']):is([data-tone='success'], [data-tone='positive']) {
112
+ --cmp-badge-background: var(--sys-status-success-surface);
113
+ --cmp-badge-text: var(--sys-status-success-text);
114
+ --cmp-banner-background: var(--sys-status-success-surface);
115
+ --cmp-banner-border: var(--sys-status-success-border);
116
+ --cmp-banner-text: var(--sys-status-success-text);
117
+ --oods-tone-solid: var(--sys-status-success-solid);
118
+ --oods-tone-on-solid: var(--sys-status-success-on-solid);
119
+ }
120
+
121
+ :where(.oods-badge, [data-oods-component='Badge'], .oods-banner, [data-oods-component='Banner'])[data-tone='warning'] {
122
+ --cmp-badge-background: var(--sys-status-warning-surface);
123
+ --cmp-badge-text: var(--sys-status-warning-text);
124
+ --cmp-banner-background: var(--sys-status-warning-surface);
125
+ --cmp-banner-border: var(--sys-status-warning-border);
126
+ --cmp-banner-text: var(--sys-status-warning-text);
127
+ --oods-tone-solid: var(--sys-status-warning-solid);
128
+ --oods-tone-on-solid: var(--sys-status-warning-on-solid);
129
+ }
130
+
131
+ :where(.oods-badge, [data-oods-component='Badge'], .oods-banner, [data-oods-component='Banner']):is([data-tone='critical'], [data-tone='danger']) {
132
+ --cmp-badge-background: var(--sys-status-critical-surface);
133
+ --cmp-badge-text: var(--sys-status-critical-text);
134
+ --cmp-banner-background: var(--sys-status-critical-surface);
135
+ --cmp-banner-border: var(--sys-status-critical-border);
136
+ --cmp-banner-text: var(--sys-status-critical-text);
137
+ --oods-tone-solid: var(--sys-status-critical-solid);
138
+ --oods-tone-on-solid: var(--sys-status-critical-on-solid);
139
+ }
39
140
 
40
- /* Solid reverses the already contrast-checked status surface/text pair. */
41
141
  :where(.oods-badge, [data-oods-component='Badge'])[data-emphasis='solid'] {
42
- border-color: var(--cmp-badge-text, var(--sys-status-neutral-text, CanvasText));
43
- background: var(--cmp-badge-text, var(--sys-status-neutral-text, CanvasText));
44
- color: var(--cmp-badge-background, var(--sys-status-neutral-surface, Canvas));
142
+ background: var(--oods-tone-solid, var(--sys-status-neutral-solid, CanvasText));
143
+ color: var(--oods-tone-on-solid, var(--sys-status-neutral-on-solid, Canvas));
45
144
  }
46
145
 
47
146
  :where(.oods-banner, [data-oods-component='Banner'])[data-emphasis='solid'] {
48
- border-color: var(--cmp-banner-text, var(--sys-status-neutral-text, CanvasText));
49
- background: var(--cmp-banner-text, var(--sys-status-neutral-text, CanvasText));
50
- color: var(--cmp-banner-background, var(--sys-status-neutral-surface, Canvas));
147
+ border-color: transparent;
148
+ background: var(--oods-tone-solid, var(--sys-status-neutral-solid, CanvasText));
149
+ color: var(--oods-tone-on-solid, var(--sys-status-neutral-on-solid, Canvas));
51
150
  }
52
151
 
152
+ /* s222-m02 (#2502 ruling 11): a banner reads at the small body size (14/20) with 12px by 16px padding and the large
153
+ * control radius; the tone paints its surface, border and text. */
53
154
  :where(.oods-banner, [data-oods-component='Banner']) {
54
155
  display: grid;
55
156
  grid-template-columns: 1fr auto;
56
157
  gap: var(--cmp-spacing-inline-sm, 0.75rem);
57
- padding: var(--cmp-spacing-inset-default, 1rem);
158
+ padding: var(--sys-inset-sm, 0.75rem) var(--sys-inset-md, 1rem);
58
159
  border: 1px solid var(--cmp-banner-border, var(--cmp-border-default, currentColor));
59
- border-radius: var(--cmp-input-radius, 0.5rem);
160
+ border-radius: var(--sys-radius-control-lg, 8px);
60
161
  background: var(--cmp-banner-background, var(--cmp-surface-subtle, transparent));
61
162
  color: var(--cmp-banner-text, var(--cmp-text-body, currentColor));
62
- }
63
-
64
- .oods-banner__title,
65
- .oods-banner-title {
66
- font-weight: var(--ref-typography-weights-bold, 700);
67
- }
68
-
163
+ font-size: var(--sys-text-scale-body-sm-font-size, 14px);
164
+ line-height: var(--sys-text-scale-body-sm-line-height, 20px);
165
+ }
166
+
167
+ /* s221-m02 (#2482 ruling 2): the one Banner markup React and Vue share. A status icon takes its own column; the content
168
+ * stacks the title, detail, body and actions without paragraph margins. React's former statusable-banner classes, which
169
+ * gave React alone a three-column grid, no longer apply. s222-m02: the icon is a 16px SVG on the title's line. */
170
+ :where(.oods-banner:has(> .oods-banner__icon)) { grid-template-columns: auto 1fr auto; }
171
+ .oods-banner__icon { display: inline-flex; align-items: center; justify-content: center; block-size: var(--sys-text-scale-body-sm-line-height, 20px); font-size: var(--sys-control-icon-size, 1rem); }
172
+ .oods-banner__content { display: grid; align-content: start; gap: var(--sys-control-gap-compact, 0.25rem); min-inline-size: 0; }
173
+ /* The title is the heading weight in both the current and the earlier Vue class names. */
174
+ :is(.oods-banner__title, .oods-banner-title) { font-weight: var(--sys-text-scale-heading-sm-font-weight, 600); }
175
+ :is(.oods-banner__detail, .oods-banner__body) { margin: 0; }
176
+ .oods-banner__actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--cmp-spacing-inline-sm, 0.75rem); margin-block-start: var(--sys-control-gap-compact, 0.25rem); }
177
+
178
+ /* s222-m02 (#2502 rulings 9 and 11): a button is its control height at every size (xs 24, sm 28, md 32, lg 40), the same
179
+ * block size as the input, select and segmented control beside it, with 8/10/12/16px side padding and the label role's
180
+ * type (12/16 at xs, 14/20 at sm and md, 16/24 at lg; weight 500). The height centres the line, so no block padding sets
181
+ * it. */
69
182
  :where(.oods-button, [data-oods-component='Button']) {
70
- --oods-button-min-block-size: var(--cmp-button-height, 2.5rem);
71
- --oods-button-padding-block: var(--cmp-button-padding-block, 0.625rem);
72
- --oods-button-padding-inline: var(--cmp-button-padding-inline, 1rem);
73
- --oods-button-font-size: var(--sys-text-size-md, 1rem);
183
+ --oods-button-block-size: var(--cmp-button-height, 2rem);
184
+ --oods-button-padding-inline: var(--cmp-button-padding-inline, 0.75rem);
185
+ --oods-button-font-size: var(--sys-text-scale-label-font-size, 14px);
186
+ --oods-button-line-height: var(--sys-text-scale-label-line-height, 20px);
187
+ --oods-button-gap: var(--cmp-button-gap, 0.5rem);
74
188
  display: inline-flex;
75
- min-block-size: var(--oods-button-min-block-size);
189
+ min-block-size: var(--oods-button-block-size);
76
190
  box-sizing: border-box;
77
191
  align-items: center;
78
192
  justify-content: center;
79
- gap: var(--cmp-button-gap, 0.5rem);
80
- padding: var(--oods-button-padding-block) var(--oods-button-padding-inline);
193
+ gap: var(--oods-button-gap);
194
+ padding: var(--oods-button-padding-block, 0) var(--oods-button-padding-inline);
81
195
  border: 1px solid var(--oods-button-border, var(--cmp-button-border, transparent));
82
- border-radius: var(--cmp-button-radius, 0.5rem);
196
+ border-radius: var(--cmp-button-radius, 6px);
83
197
  background: var(--oods-button-background, var(--cmp-button-background, var(--cmp-surface-action, CanvasText)));
84
198
  color: var(--oods-button-text, var(--cmp-button-text, var(--cmp-text-on-action, Canvas)));
85
199
  font: inherit;
86
200
  font-size: var(--oods-button-font-size);
87
- font-weight: var(--cmp-button-font-weight, 600);
88
- line-height: var(--sys-text-line-height-tight, 1.2);
201
+ font-weight: var(--cmp-button-font-weight, 500);
202
+ line-height: var(--oods-button-line-height);
203
+ white-space: nowrap;
204
+ text-decoration: none;
89
205
  cursor: pointer;
90
206
  }
91
207
 
92
- :where(.oods-button, [data-oods-component='Button'])[data-intent='neutral'] {
93
- --oods-button-background: var(--sys-surface-inverse, CanvasText);
94
- --oods-button-background-hover: var(--sys-surface-inverse, CanvasText);
95
- --oods-button-border: var(--sys-surface-inverse, CanvasText);
96
- --oods-button-text: var(--sys-text-inverse, Canvas);
208
+ :where(.oods-button, [data-oods-component='Button']) > svg {
209
+ flex: none;
210
+ inline-size: var(--sys-control-icon-size, 1rem);
211
+ block-size: var(--sys-control-icon-size, 1rem);
212
+ }
213
+
214
+ /* s222-m02 (#2502 ruling 11): the variants. neutral, which a button without an intent also gets, is the outline look, so a
215
+ * screen's primary action is its one solid fill; secondary is the subtle fill (neutral steps 3 to 5); ghost and link carry
216
+ * no fill until hovered; destructive and danger share the destructive fill with its graded text; success and warning keep
217
+ * their status solids. */
218
+ :where(.oods-button, [data-oods-component='Button']):is([data-intent='neutral'], [data-intent='outline'], :not([data-intent])) {
219
+ --oods-button-background: var(--sys-surface-raised, Canvas);
220
+ --oods-button-background-hover: var(--sys-surface-interactive-secondary-default, Canvas);
221
+ --oods-button-background-pressed: var(--sys-surface-interactive-secondary-hover, Canvas);
222
+ --oods-button-border: var(--sys-border-strong, CanvasText);
223
+ --oods-button-text: var(--sys-text-primary, CanvasText);
97
224
  }
98
225
 
99
226
  :where(.oods-button, [data-oods-component='Button'])[data-intent='primary'] {
100
227
  --oods-button-background: var(--sys-surface-interactive-primary-default, CanvasText);
101
228
  --oods-button-background-hover: var(--sys-surface-interactive-primary-hover, CanvasText);
102
- --oods-button-border: var(--sys-surface-interactive-primary-default, CanvasText);
229
+ --oods-button-background-pressed: var(--sys-surface-interactive-primary-pressed, CanvasText);
230
+ --oods-button-border: transparent;
103
231
  --oods-button-text: var(--sys-text-on-interactive, Canvas);
104
232
  }
105
233
 
106
234
  :where(.oods-button, [data-oods-component='Button'])[data-intent='secondary'] {
107
- --oods-button-background: var(--sys-surface-subtle, Canvas);
108
- --oods-button-background-hover: var(--sys-surface-canvas, Canvas);
109
- --oods-button-border: var(--sys-border-strong, CanvasText);
235
+ --oods-button-background: var(--sys-surface-interactive-secondary-default, Canvas);
236
+ --oods-button-background-hover: var(--sys-surface-interactive-secondary-hover, Canvas);
237
+ --oods-button-background-pressed: var(--sys-surface-interactive-secondary-pressed, Canvas);
238
+ --oods-button-border: transparent;
110
239
  --oods-button-text: var(--sys-text-primary, CanvasText);
111
240
  }
112
241
 
113
- :where(.oods-button, [data-oods-component='Button'])[data-intent='success'] {
114
- --oods-button-background: var(--sys-status-success-text, CanvasText);
115
- --oods-button-background-hover: var(--sys-status-success-text, CanvasText);
116
- --oods-button-border: var(--sys-status-success-text, CanvasText);
117
- --oods-button-text: var(--sys-status-success-surface, Canvas);
242
+ :where(.oods-button, [data-oods-component='Button'])[data-intent='ghost'] {
243
+ --oods-button-background: transparent;
244
+ --oods-button-background-hover: var(--sys-surface-interactive-secondary-default, Canvas);
245
+ --oods-button-background-pressed: var(--sys-surface-interactive-secondary-hover, Canvas);
246
+ --oods-button-border: transparent;
247
+ --oods-button-text: var(--sys-text-primary, CanvasText);
118
248
  }
119
249
 
120
- :where(.oods-button, [data-oods-component='Button'])[data-intent='warning'] {
121
- --oods-button-background: var(--sys-status-warning-text, CanvasText);
122
- --oods-button-background-hover: var(--sys-status-warning-text, CanvasText);
123
- --oods-button-border: var(--sys-status-warning-text, CanvasText);
124
- --oods-button-text: var(--sys-status-warning-surface, Canvas);
250
+ :where(.oods-button, [data-oods-component='Button'])[data-intent='link'] {
251
+ --oods-button-background: transparent;
252
+ --oods-button-background-hover: transparent;
253
+ --oods-button-background-pressed: transparent;
254
+ --oods-button-border: transparent;
255
+ --oods-button-text: var(--sys-text-accent, LinkText);
256
+ text-underline-offset: 0.25em;
257
+ }
258
+
259
+ :where(.oods-button, [data-oods-component='Button'])[data-intent='link']:hover:not(:disabled) { text-decoration: underline; }
260
+
261
+ :where(.oods-button, [data-oods-component='Button']):is([data-intent='destructive'], [data-intent='danger']) {
262
+ --oods-button-background: var(--sys-surface-interactive-destructive-default, CanvasText);
263
+ --oods-button-background-hover: var(--sys-surface-interactive-destructive-hover, CanvasText);
264
+ --oods-button-background-pressed: var(--sys-surface-interactive-destructive-pressed, CanvasText);
265
+ --oods-button-border: transparent;
266
+ --oods-button-text: var(--sys-text-on-destructive, Canvas);
125
267
  }
126
268
 
127
- :where(.oods-button, [data-oods-component='Button'])[data-intent='danger'] {
128
- --oods-button-background: var(--sys-status-critical-text, CanvasText);
129
- --oods-button-background-hover: var(--sys-status-critical-text, CanvasText);
130
- --oods-button-border: var(--sys-status-critical-text, CanvasText);
131
- --oods-button-text: var(--sys-status-critical-surface, Canvas);
269
+ :where(.oods-button, [data-oods-component='Button'])[data-intent='success'] {
270
+ --oods-button-background: var(--sys-status-success-solid, CanvasText);
271
+ --oods-button-border: transparent;
272
+ --oods-button-text: var(--sys-status-success-on-solid, Canvas);
273
+ }
274
+
275
+ :where(.oods-button, [data-oods-component='Button'])[data-intent='warning'] {
276
+ --oods-button-background: var(--sys-status-warning-solid, CanvasText);
277
+ --oods-button-border: transparent;
278
+ --oods-button-text: var(--sys-status-warning-on-solid, Canvas);
279
+ }
280
+
281
+ /* Each size rule also sets the type, so a page's own reset (button { font: inherit }, at element specificity) cannot undo
282
+ * the size's label role; the base rule's declarations sit at zero specificity. */
283
+ :where(.oods-button, [data-oods-component='Button'])[data-size='xs'] {
284
+ --oods-button-block-size: var(--sys-control-height-xs, 1.5rem);
285
+ --oods-button-padding-inline: var(--sys-control-padding-inline-xs, 0.5rem);
286
+ --oods-button-font-size: var(--sys-text-scale-caption-font-size, 12px);
287
+ --oods-button-line-height: var(--sys-text-scale-caption-line-height, 16px);
288
+ --oods-button-gap: var(--sys-control-icon-gap-sm, 0.375rem);
289
+ font-size: var(--oods-button-font-size);
290
+ line-height: var(--oods-button-line-height);
132
291
  }
133
292
 
134
293
  :where(.oods-button, [data-oods-component='Button'])[data-size='sm'] {
135
- --oods-button-min-block-size: var(--cmp-button-height-sm, 2rem);
136
- --oods-button-padding-block: var(--cmp-button-padding-block-sm, 0.375rem);
137
- --oods-button-padding-inline: var(--cmp-button-padding-inline-sm, 0.75rem);
138
- --oods-button-font-size: var(--sys-text-size-sm, 0.875rem);
294
+ --oods-button-block-size: var(--cmp-button-height-sm, 1.75rem);
295
+ --oods-button-padding-inline: var(--cmp-button-padding-inline-sm, 0.625rem);
296
+ --oods-button-gap: var(--sys-control-icon-gap-sm, 0.375rem);
139
297
  font-size: var(--oods-button-font-size);
298
+ line-height: var(--oods-button-line-height);
140
299
  }
141
300
 
142
301
  :where(.oods-button, [data-oods-component='Button'])[data-size='md'] {
143
- --oods-button-min-block-size: var(--cmp-button-height, 2.5rem);
144
- --oods-button-padding-block: var(--cmp-button-padding-block, 0.625rem);
145
- --oods-button-padding-inline: var(--cmp-button-padding-inline, 1rem);
146
- --oods-button-font-size: var(--sys-text-size-md, 1rem);
302
+ --oods-button-block-size: var(--cmp-button-height, 2rem);
303
+ --oods-button-padding-inline: var(--cmp-button-padding-inline, 0.75rem);
147
304
  font-size: var(--oods-button-font-size);
305
+ line-height: var(--oods-button-line-height);
148
306
  }
149
307
 
150
308
  :where(.oods-button, [data-oods-component='Button'])[data-size='lg'] {
151
- --oods-button-min-block-size: var(--cmp-button-height-lg, 3rem);
152
- --oods-button-padding-block: var(--cmp-button-padding-block-lg, 0.75rem);
153
- --oods-button-padding-inline: var(--cmp-button-padding-inline-lg, 1.5rem);
154
- --oods-button-font-size: var(--sys-text-size-lg, 1.25rem);
309
+ --oods-button-block-size: var(--cmp-button-height-lg, 2.5rem);
310
+ --oods-button-padding-inline: var(--cmp-button-padding-inline-lg, 1rem);
311
+ --oods-button-font-size: var(--sys-text-scale-body-md-font-size, 16px);
312
+ --oods-button-line-height: var(--sys-text-scale-body-md-line-height, 24px);
155
313
  font-size: var(--oods-button-font-size);
314
+ line-height: var(--oods-button-line-height);
156
315
  }
157
316
 
158
317
  :where(.oods-button, [data-oods-component='Button']):hover:not(:disabled) {
159
- background: var(--oods-button-background-hover, var(--cmp-button-background-hover, var(--cmp-surface-action-hover, CanvasText)));
318
+ background: var(--oods-button-background-hover, var(--oods-button-background, var(--cmp-button-background-hover, CanvasText)));
319
+ }
320
+
321
+ :where(.oods-button, [data-oods-component='Button']):active:not(:disabled) {
322
+ background: var(--oods-button-background-pressed, var(--oods-button-background-hover, var(--oods-button-background, var(--cmp-button-background-hover, CanvasText))));
160
323
  }
161
324
 
162
325
  :where(.oods-button, [data-oods-component='Button']):disabled {
@@ -166,6 +329,12 @@
166
329
  cursor: not-allowed;
167
330
  }
168
331
 
332
+ /* A disabled ghost or link button keeps no fill, as it has none at rest. */
333
+ :where(.oods-button, [data-oods-component='Button']):is([data-intent='ghost'], [data-intent='link']):disabled {
334
+ border-color: transparent;
335
+ background: transparent;
336
+ }
337
+
169
338
  /* One focus treatment for every interactive element, native controls included:
170
339
  * token width, colour and offset. Nothing else in this stylesheet paints focus. */
171
340
  :where(.oods-button, [data-oods-component='Button'], .oods-field-control, .oods-tab, .oods-table-row-action, .oods-collection-row,
@@ -177,16 +346,23 @@
177
346
  outline-offset: var(--cmp-focus-offset, 2px);
178
347
  }
179
348
 
349
+ /* s222-m02 (#2502 rulings 9 and 10): a card is border-only on the raised surface with the card radius and 24px padding;
350
+ * its children stack 16px apart with no browser margins, so its header, body and actions sit on the card's own rhythm. */
180
351
  :where(.oods-card, [data-oods-component='Card']) {
181
- padding: var(--cmp-spacing-inset-default, 1rem);
352
+ display: grid;
353
+ align-content: start;
354
+ gap: var(--sys-stack-md, 1rem);
355
+ padding: var(--sys-card-padding, 1.5rem);
182
356
  border: 1px solid var(--cmp-border-default, var(--sys-border-subtle));
183
357
  border-radius: var(--cmp-card-radius, 0.75rem);
184
358
  background: var(--cmp-surface-panel, var(--sys-surface-raised));
185
359
  color: var(--cmp-text-body, var(--sys-text-primary));
186
360
  }
187
361
 
362
+ :where(.oods-card, [data-oods-component='Card']) > :where(p, h1, h2, h3, h4, h5, h6, ul, ol, dl) { margin: 0; }
363
+
188
364
  :where(.oods-card[data-elevated='true'], [data-oods-component='Card'][data-elevated='true']) {
189
- box-shadow: var(--cmp-card-shadow-offset-x, 0px) var(--cmp-card-shadow-offset-y, 16px) var(--cmp-card-shadow-blur, 40px) var(--cmp-card-shadow-spread, -12px) var(--cmp-card-shadow-color, rgba(15, 23, 42, 0.12));
365
+ box-shadow: var(--cmp-card-shadow-offset-x, 0px) var(--cmp-card-shadow-offset-y, 4px) var(--cmp-card-shadow-blur, 8px) var(--cmp-card-shadow-spread, -4px) var(--cmp-card-shadow-color, rgba(15, 23, 42, 0.12));
190
366
  }
191
367
 
192
368
  /* The tokens build scopes colour per brand and theme; the dark elevation tokens are
@@ -204,38 +380,58 @@
204
380
  --cmp-shadow-overlay-color: var(--theme-dark-shadow-elevation-overlay-color);
205
381
  }
206
382
 
383
+ /* s222-m02 (#2502 ruling 8): headings sit on the type roles. A detail header's title is the page title (heading-xl,
384
+ * 30/36 600) over a 16/24 subtitle and 14/20 metadata; a card header's title is heading-sm (16/24 600) over 14/20
385
+ * supporting text. */
207
386
  :where([data-oods-component='DetailHeader'], [data-oods-component='CardHeader']) {
208
387
  --cmp-header-title: var(--sys-text-primary);
209
388
  --cmp-header-subtitle: var(--sys-text-secondary);
210
389
  --cmp-header-metadata: var(--sys-text-muted);
211
390
  display: grid;
212
- gap: var(--sys-spacing-stack-compact, 0.75rem);
391
+ gap: var(--sys-control-gap-compact, 0.25rem);
213
392
  }
214
393
 
394
+ :where([data-oods-component='DetailHeader']) { gap: var(--sys-stack-xs, 0.5rem); }
395
+
215
396
  :where([data-oods-component='DetailHeader'], [data-oods-component='CardHeader']) > :is(h1, h2, h3, h4, h5, h6) {
216
397
  margin: 0;
217
398
  color: var(--cmp-header-title, CanvasText);
218
- font-weight: var(--ref-typography-weights-semibold, 600);
219
- line-height: var(--sys-text-line-height-standard, 1.4);
220
399
  }
221
400
 
222
401
  :where([data-oods-component='DetailHeader']) > :is(h1, h2, h3, h4, h5, h6) {
223
- font-size: var(--sys-text-scale-heading-lg-font-size, 1.5rem);
224
- line-height: var(--sys-text-scale-heading-lg-line-height, 1.2);
402
+ font-size: var(--sys-text-scale-heading-xl-font-size, 30px);
403
+ font-weight: var(--sys-text-scale-heading-xl-font-weight, 600);
404
+ line-height: var(--sys-text-scale-heading-xl-line-height, 36px);
405
+ letter-spacing: var(--sys-text-scale-heading-xl-letter-spacing);
225
406
  }
226
407
 
227
408
  :where([data-oods-component='CardHeader']) > :is(h1, h2, h3, h4, h5, h6) {
228
- font-size: var(--sys-text-size-lg, 1.25rem);
409
+ font-size: var(--sys-text-scale-heading-sm-font-size, 16px);
410
+ font-weight: var(--sys-text-scale-heading-sm-font-weight, 600);
411
+ line-height: var(--sys-text-scale-heading-sm-line-height, 24px);
229
412
  }
230
413
 
231
414
  :where([data-oods-component='DetailHeader']) > [data-oods-subtitle],
232
415
  :where([data-oods-component='CardHeader']) > [data-oods-supporting] {
416
+ margin: 0;
233
417
  color: var(--cmp-header-subtitle, CanvasText);
234
418
  }
235
419
 
420
+ :where([data-oods-component='DetailHeader']) > [data-oods-subtitle] {
421
+ font-size: var(--sys-text-scale-body-md-font-size, 16px);
422
+ line-height: var(--sys-text-scale-body-md-line-height, 24px);
423
+ }
424
+
425
+ :where([data-oods-component='CardHeader']) > [data-oods-supporting] {
426
+ font-size: var(--sys-text-scale-body-sm-font-size, 14px);
427
+ line-height: var(--sys-text-scale-body-sm-line-height, 20px);
428
+ }
429
+
236
430
  :where([data-oods-component='DetailHeader']) > [data-oods-metadata] {
431
+ margin: 0;
237
432
  color: var(--cmp-header-metadata, CanvasText);
238
- font-size: var(--sys-text-size-sm, 0.875rem);
433
+ font-size: var(--sys-text-scale-body-sm-font-size, 14px);
434
+ line-height: var(--sys-text-scale-body-sm-line-height, 20px);
239
435
  }
240
436
 
241
437
  :where([data-oods-component='ColorSwatch']) {
@@ -253,7 +449,7 @@
253
449
  inline-size: 1.25rem;
254
450
  block-size: 1.25rem;
255
451
  border: 1px solid var(--cmp-swatch-border, CanvasText);
256
- border-radius: var(--cmp-input-radius, 0.5rem);
452
+ border-radius: var(--cmp-input-radius, 6px);
257
453
  background: var(--oods-swatch-color, var(--cmp-swatch-chip, CanvasText));
258
454
  }
259
455
 
@@ -266,19 +462,22 @@
266
462
  display: inline-flex;
267
463
  align-items: center;
268
464
  gap: var(--cmp-badge-gap, 0.25rem);
465
+ min-block-size: var(--cmp-badge-height, 1.25rem);
466
+ box-sizing: border-box;
269
467
  padding: var(--cmp-badge-padding-block, 0.125rem) var(--cmp-badge-padding-inline, 0.5rem);
270
- border: 1px solid var(--cmp-badge-border, CanvasText);
468
+ border: 0;
271
469
  border-radius: var(--cmp-badge-radius, 999px);
272
470
  background: var(--cmp-badge-background, Canvas);
273
471
  color: var(--cmp-badge-text, CanvasText);
274
- font-size: var(--cmp-badge-font-size, 0.875rem);
275
- font-weight: var(--cmp-badge-font-weight, 600);
472
+ font-size: var(--cmp-badge-font-size, 12px);
473
+ font-weight: var(--cmp-badge-font-weight, 500);
474
+ line-height: var(--sys-text-scale-caption-line-height, 16px);
475
+ white-space: nowrap;
276
476
  }
277
477
 
278
478
  :where([data-oods-component='ColorizedBadge'])[data-emphasis='solid'] {
279
- border-color: var(--cmp-badge-text, CanvasText);
280
- background: var(--cmp-badge-text, CanvasText);
281
- color: var(--cmp-badge-background, Canvas);
479
+ background: var(--oods-tone-solid, var(--sys-status-neutral-solid, CanvasText));
480
+ color: var(--oods-tone-on-solid, var(--sys-status-neutral-on-solid, Canvas));
282
481
  }
283
482
 
284
483
  :where([data-oods-component='ColorizedBadge']) [data-oods-badge-marker] {
@@ -310,7 +509,7 @@
310
509
  min-block-size: var(--oods-viz-height, 360px);
311
510
  padding: var(--cmp-spacing-inset-default, 1rem);
312
511
  border: 1px dashed var(--cmp-preview-frame, CanvasText);
313
- border-radius: var(--cmp-input-radius, 0.5rem);
512
+ border-radius: var(--cmp-input-radius, 6px);
314
513
  background: var(--sys-surface-canvas, Canvas);
315
514
  }
316
515
 
@@ -327,9 +526,12 @@
327
526
  border: 0;
328
527
  place-items: stretch;
329
528
  }
529
+ /* s222-m02 (#2502 ruling 8): a placed chart's caption is heading-sm (16/24 600). It was an undocumented min() with a
530
+ * 1.25rem literal. */
330
531
  :where([data-viz-rendered='true']) > figcaption {
331
- font-size: min(var(--sys-text-scale-heading-md-font-size, 1.25rem), 1.25rem);
332
- font-weight: var(--ref-typography-weights-semibold, 600);
532
+ font-size: var(--sys-text-scale-heading-sm-font-size, 16px);
533
+ font-weight: var(--sys-text-scale-heading-sm-font-weight, 600);
534
+ line-height: var(--sys-text-scale-heading-sm-line-height, 24px);
333
535
  }
334
536
  :where([data-viz-svg]) { min-inline-size: 0; }
335
537
  :where([data-viz-svg]) > svg { display: block; inline-size: 100%; max-inline-size: var(--oods-viz-width, 100%); block-size: auto; }
@@ -365,18 +567,18 @@
365
567
  --cmp-timeline-marker: var(--sys-border-strong);
366
568
  display: grid;
367
569
  gap: var(--cmp-spacing-stack-sm, 0.75rem);
368
- padding: var(--cmp-spacing-inset-default, 1rem);
570
+ padding: var(--sys-card-padding, 1.5rem);
369
571
  border: 1px solid var(--cmp-timeline-border, CanvasText);
370
- border-radius: var(--cmp-input-radius, 0.5rem);
572
+ border-radius: var(--cmp-card-radius, 0.75rem);
371
573
  background: var(--cmp-timeline-background, Canvas);
372
574
  color: var(--cmp-timeline-text, CanvasText);
373
575
  }
374
576
 
375
577
  :where([data-oods-component='AddressValidationTimeline'], [data-oods-component='MembershipAuditTimeline'], [data-oods-component='MessageEventTimeline'], [data-oods-component='PreferenceTimeline']) > [data-timeline-title] {
376
578
  margin: 0;
377
- font-size: var(--sys-text-size-lg, 1.25rem);
378
- font-weight: var(--ref-typography-weights-semibold, 600);
379
- line-height: var(--sys-text-line-height-standard, 1.4);
579
+ font-size: var(--sys-text-scale-heading-md-font-size, 18px);
580
+ font-weight: var(--sys-text-scale-heading-md-font-weight, 600);
581
+ line-height: var(--sys-text-scale-heading-md-line-height, 24px);
380
582
  }
381
583
 
382
584
  :where([data-oods-component='AddressValidationTimeline'], [data-oods-component='MembershipAuditTimeline'], [data-oods-component='MessageEventTimeline'], [data-oods-component='PreferenceTimeline']) > [data-timeline-events] {
@@ -411,7 +613,7 @@
411
613
  gap: var(--sys-spacing-stack-compact, 0.75rem);
412
614
  padding: var(--cmp-spacing-inset-sm, 0.75rem);
413
615
  border: 1px solid var(--cmp-event-border, CanvasText);
414
- border-radius: var(--cmp-input-radius, 0.5rem);
616
+ border-radius: var(--cmp-input-radius, 6px);
415
617
  background: var(--cmp-event-background, Canvas);
416
618
  color: var(--cmp-event-text, CanvasText);
417
619
  }
@@ -439,19 +641,22 @@
439
641
  display: inline-flex;
440
642
  align-items: center;
441
643
  gap: var(--cmp-badge-gap, 0.25rem);
644
+ min-block-size: var(--cmp-badge-height, 1.25rem);
645
+ box-sizing: border-box;
442
646
  padding: var(--cmp-badge-padding-block, 0.125rem) var(--cmp-badge-padding-inline, 0.5rem);
443
- border: 1px solid var(--cmp-badge-border, CanvasText);
647
+ border: 0;
444
648
  border-radius: var(--cmp-badge-radius, 999px);
445
649
  background: var(--cmp-badge-background, Canvas);
446
650
  color: var(--cmp-badge-text, CanvasText);
447
- font-size: var(--cmp-badge-font-size, 0.875rem);
448
- font-weight: var(--cmp-badge-font-weight, 600);
651
+ font-size: var(--cmp-badge-font-size, 12px);
652
+ font-weight: var(--cmp-badge-font-weight, 500);
653
+ line-height: var(--sys-text-scale-caption-line-height, 16px);
654
+ white-space: nowrap;
449
655
  }
450
656
 
451
657
  :where([data-oods-component='ArchivePill'], [data-oods-component='CancellationBadge'], [data-oods-component='OwnerBadge'], [data-oods-component='ClassificationBadge'], [data-oods-component='AddressSummaryBadge'], [data-oods-component='MessageStatusBadge'], [data-oods-component='PreferenceSummaryBadge'])[data-emphasis='solid'] {
452
- border-color: var(--cmp-badge-text, CanvasText);
453
- background: var(--cmp-badge-text, CanvasText);
454
- color: var(--cmp-badge-background, Canvas);
658
+ background: var(--oods-tone-solid, var(--sys-status-neutral-solid, CanvasText));
659
+ color: var(--oods-tone-on-solid, var(--sys-status-neutral-on-solid, Canvas));
455
660
  }
456
661
 
457
662
  :where([data-oods-component='ArchivePill'], [data-oods-component='CancellationBadge'], [data-oods-component='OwnerBadge'], [data-oods-component='ClassificationBadge'], [data-oods-component='AddressSummaryBadge'], [data-oods-component='MessageStatusBadge'], [data-oods-component='PreferenceSummaryBadge']) [data-oods-badge-label] {
@@ -476,13 +681,17 @@
476
681
  :where([data-oods-component='TagPills']) [data-tag-overflow] {
477
682
  display: inline-flex;
478
683
  align-items: center;
684
+ min-block-size: var(--cmp-badge-height, 1.25rem);
685
+ box-sizing: border-box;
479
686
  padding: var(--cmp-badge-padding-block, 0.125rem) var(--cmp-badge-padding-inline, 0.5rem);
480
- border: 1px solid var(--cmp-badge-border, CanvasText);
687
+ border: 0;
481
688
  border-radius: var(--cmp-badge-radius, 999px);
482
689
  background: var(--cmp-badge-background, Canvas);
483
690
  color: var(--cmp-badge-text, CanvasText);
484
- font-size: var(--cmp-badge-font-size, 0.875rem);
485
- font-weight: var(--cmp-badge-font-weight, 600);
691
+ font-size: var(--cmp-badge-font-size, 12px);
692
+ font-weight: var(--cmp-badge-font-weight, 500);
693
+ line-height: var(--sys-text-scale-caption-line-height, 16px);
694
+ white-space: nowrap;
486
695
  }
487
696
 
488
697
  /* Panel, filter and summary sections mirror their HTML renderers; controls stay unwired. */
@@ -493,9 +702,9 @@
493
702
  --cmp-panel-subtitle: var(--sys-text-secondary);
494
703
  display: grid;
495
704
  gap: var(--cmp-spacing-stack-sm, 0.75rem);
496
- padding: var(--cmp-spacing-inset-default, 1rem);
705
+ padding: var(--sys-card-padding, 1.5rem);
497
706
  border: 1px solid var(--cmp-panel-border, CanvasText);
498
- border-radius: var(--cmp-input-radius, 0.5rem);
707
+ border-radius: var(--cmp-card-radius, 0.75rem);
499
708
  background: var(--cmp-panel-background, Canvas);
500
709
  color: var(--cmp-panel-title, CanvasText);
501
710
  }
@@ -508,9 +717,9 @@
508
717
  :where([data-oods-component='AddressCollectionPanel'], [data-oods-component='ClassificationPanel'], [data-oods-component='MembershipPanel'], [data-oods-component='PreferencePanel']) > [data-panel-header] > h2 {
509
718
  margin: 0;
510
719
  color: var(--cmp-panel-title, CanvasText);
511
- font-size: var(--sys-text-size-lg, 1.25rem);
512
- font-weight: var(--ref-typography-weights-semibold, 600);
513
- line-height: var(--sys-text-line-height-standard, 1.4);
720
+ font-size: var(--sys-text-scale-heading-md-font-size, 18px);
721
+ font-weight: var(--sys-text-scale-heading-md-font-weight, 600);
722
+ line-height: var(--sys-text-scale-heading-md-line-height, 24px);
514
723
  }
515
724
 
516
725
  :where([data-oods-component='AddressCollectionPanel'], [data-oods-component='ClassificationPanel'], [data-oods-component='MembershipPanel'], [data-oods-component='PreferencePanel']) > [data-panel-header] > [data-panel-subtitle] {
@@ -529,9 +738,9 @@
529
738
  --cmp-filter-legend: var(--sys-text-secondary);
530
739
  display: grid;
531
740
  gap: var(--cmp-spacing-stack-sm, 0.75rem);
532
- padding: var(--cmp-spacing-inset-default, 1rem);
741
+ padding: var(--sys-card-padding, 1.5rem);
533
742
  border: 1px solid var(--cmp-filter-border, CanvasText);
534
- border-radius: var(--cmp-input-radius, 0.5rem);
743
+ border-radius: var(--cmp-card-radius, 0.75rem);
535
744
  background: var(--cmp-filter-background, Canvas);
536
745
  color: var(--cmp-filter-text, CanvasText);
537
746
  }
@@ -540,7 +749,7 @@
540
749
  margin: 0;
541
750
  padding: var(--cmp-spacing-inset-sm, 0.75rem);
542
751
  border: 1px solid var(--cmp-filter-border, CanvasText);
543
- border-radius: var(--cmp-input-radius, 0.5rem);
752
+ border-radius: var(--cmp-input-radius, 6px);
544
753
  }
545
754
 
546
755
  :where([data-oods-component='FilterPanel']) > [data-filter-section] > legend {
@@ -555,13 +764,19 @@
555
764
  gap: var(--cmp-spacing-inline-sm, 0.75rem);
556
765
  }
557
766
 
767
+ /* s222-m02 (#2502 ruling 11): a filter's button is the small outline button. */
558
768
  :where([data-oods-component='FilterPanel']) button {
559
- padding: var(--cmp-button-padding-block-sm, 0.375rem) var(--cmp-button-padding-inline-sm, 0.75rem);
560
- border: 1px solid var(--cmp-filter-border, CanvasText);
561
- border-radius: var(--cmp-input-radius, 0.5rem);
562
- background: transparent;
769
+ box-sizing: border-box;
770
+ min-block-size: var(--cmp-button-height-sm, 1.75rem);
771
+ padding: 0 var(--cmp-button-padding-inline-sm, 0.625rem);
772
+ border: 1px solid var(--sys-border-strong, CanvasText);
773
+ border-radius: var(--cmp-button-radius, 6px);
774
+ background: var(--sys-surface-raised, Canvas);
563
775
  color: var(--cmp-filter-text, CanvasText);
564
776
  font: inherit;
777
+ font-size: var(--sys-text-scale-label-font-size, 14px);
778
+ font-weight: var(--sys-text-scale-label-font-weight, 500);
779
+ line-height: var(--sys-text-scale-label-line-height, 20px);
565
780
  }
566
781
 
567
782
  :where([data-oods-component='AddressEditor'], [data-oods-component='CancellationForm'], [data-oods-component='ClassificationEditor'], [data-oods-component='PreferenceEditor'], [data-oods-component='RoleAssignmentForm'], [data-oods-component='TagInput'], [data-oods-component='TagManager'], [data-oods-component='TemplatePicker']) {
@@ -572,9 +787,9 @@
572
787
  display: grid;
573
788
  gap: var(--cmp-spacing-stack-sm, 0.75rem);
574
789
  margin: 0;
575
- padding: var(--cmp-spacing-inset-default, 1rem);
790
+ padding: var(--sys-card-padding, 1.5rem);
576
791
  border: 1px solid var(--cmp-form-border, CanvasText);
577
- border-radius: var(--cmp-input-radius, 0.5rem);
792
+ border-radius: var(--cmp-card-radius, 0.75rem);
578
793
  background: var(--cmp-form-background, Canvas);
579
794
  color: var(--cmp-form-text, CanvasText);
580
795
  }
@@ -587,9 +802,9 @@
587
802
  :where([data-oods-component='AddressEditor'], [data-oods-component='CancellationForm'], [data-oods-component='ClassificationEditor'], [data-oods-component='PreferenceEditor'], [data-oods-component='RoleAssignmentForm'], [data-oods-component='TagInput'], [data-oods-component='TagManager'], [data-oods-component='TemplatePicker']) > [data-form-header] > h2 {
588
803
  margin: 0;
589
804
  color: var(--cmp-form-text, CanvasText);
590
- font-size: var(--sys-text-size-lg, 1.25rem);
591
- font-weight: var(--ref-typography-weights-semibold, 600);
592
- line-height: var(--sys-text-line-height-standard, 1.4);
805
+ font-size: var(--sys-text-scale-heading-md-font-size, 18px);
806
+ font-weight: var(--sys-text-scale-heading-md-font-weight, 600);
807
+ line-height: var(--sys-text-scale-heading-md-line-height, 24px);
593
808
  }
594
809
 
595
810
  :where([data-oods-component='AddressEditor'], [data-oods-component='CancellationForm'], [data-oods-component='ClassificationEditor'], [data-oods-component='PreferenceEditor'], [data-oods-component='RoleAssignmentForm'], [data-oods-component='TagInput'], [data-oods-component='TagManager'], [data-oods-component='TemplatePicker']) > [data-form-header] > [data-form-subtitle] {
@@ -604,9 +819,18 @@
604
819
  }
605
820
 
606
821
  :where([data-oods-component='AddressEditor'], [data-oods-component='CancellationForm'], [data-oods-component='ClassificationEditor'], [data-oods-component='PreferenceEditor'], [data-oods-component='RoleAssignmentForm'], [data-oods-component='TagInput'], [data-oods-component='TagManager'], [data-oods-component='TemplatePicker']) [data-tag-item] {
822
+ display: inline-flex;
823
+ align-items: center;
824
+ min-block-size: var(--cmp-badge-height, 1.25rem);
825
+ box-sizing: border-box;
607
826
  padding: var(--cmp-badge-padding-block, 0.125rem) var(--cmp-badge-padding-inline, 0.5rem);
608
- border: 1px solid var(--cmp-form-border, CanvasText);
827
+ border: 0;
609
828
  border-radius: var(--cmp-badge-radius, 999px);
829
+ background: var(--sys-status-neutral-surface, Canvas);
830
+ color: var(--sys-status-neutral-text, CanvasText);
831
+ font-size: var(--cmp-badge-font-size, 12px);
832
+ font-weight: var(--cmp-badge-font-weight, 500);
833
+ line-height: var(--sys-text-scale-caption-line-height, 16px);
610
834
  }
611
835
 
612
836
  :where([data-oods-component='AddressEditor'], [data-oods-component='CancellationForm'], [data-oods-component='ClassificationEditor'], [data-oods-component='PreferenceEditor'], [data-oods-component='RoleAssignmentForm'], [data-oods-component='TagInput'], [data-oods-component='TagManager'], [data-oods-component='TemplatePicker']) [data-form-control='input'] {
@@ -619,19 +843,24 @@
619
843
  font-size: var(--sys-text-size-sm, 0.875rem);
620
844
  }
621
845
 
622
- :where([data-oods-component='AddressEditor'], [data-oods-component='CancellationForm'], [data-oods-component='ClassificationEditor'], [data-oods-component='PreferenceEditor'], [data-oods-component='RoleAssignmentForm'], [data-oods-component='TagInput'], [data-oods-component='TagManager'], [data-oods-component='TemplatePicker']) input {
623
- padding: var(--cmp-input-padding-block-compact, 0.375rem) var(--cmp-input-padding-inline-compact, 0.5rem);
624
- border: 1px solid var(--cmp-form-border, CanvasText);
625
- border-radius: var(--cmp-input-radius, 0.5rem);
626
- background: transparent;
627
- color: inherit;
846
+ :where([data-oods-component='AddressEditor'], [data-oods-component='CancellationForm'], [data-oods-component='ClassificationEditor'], [data-oods-component='PreferenceEditor'], [data-oods-component='RoleAssignmentForm'], [data-oods-component='TagInput'], [data-oods-component='TagManager'], [data-oods-component='TemplatePicker']) input:not([type='checkbox'], [type='radio']) {
847
+ box-sizing: border-box;
848
+ min-block-size: var(--sys-control-height-md, 2rem);
849
+ padding: 0 var(--cmp-input-padding-inline, 0.75rem);
850
+ border: 1px solid var(--cmp-input-border, CanvasText);
851
+ border-radius: var(--cmp-input-radius, 6px);
852
+ background: var(--cmp-input-background, Canvas);
853
+ color: var(--cmp-input-text, CanvasText);
628
854
  font: inherit;
855
+ font-size: var(--sys-text-scale-body-sm-font-size, 14px);
856
+ line-height: var(--sys-text-scale-body-sm-line-height, 20px);
629
857
  }
630
858
 
631
859
  :where([data-oods-component='AddressEditor'], [data-oods-component='CancellationForm'], [data-oods-component='ClassificationEditor'], [data-oods-component='PreferenceEditor'], [data-oods-component='RoleAssignmentForm'], [data-oods-component='TagInput'], [data-oods-component='TagManager'], [data-oods-component='TemplatePicker']) > legend {
632
860
  padding-inline: var(--sys-control-gap-compact, 0.25rem);
633
- font-size: var(--sys-text-size-lg, 1.25rem);
634
- font-weight: var(--ref-typography-weights-semibold, 600);
861
+ font-size: var(--sys-text-scale-heading-md-font-size, 18px);
862
+ font-weight: var(--sys-text-scale-heading-md-font-weight, 600);
863
+ line-height: var(--sys-text-scale-heading-md-line-height, 24px);
635
864
  }
636
865
 
637
866
  :where([data-oods-component='AddressEditor'], [data-oods-component='CancellationForm'], [data-oods-component='ClassificationEditor'], [data-oods-component='PreferenceEditor'], [data-oods-component='RoleAssignmentForm'], [data-oods-component='TagInput'], [data-oods-component='TagManager'], [data-oods-component='TemplatePicker']) > [data-form-subtitle] {
@@ -656,19 +885,25 @@
656
885
 
657
886
  :where([data-oods-component='AddressEditor'], [data-oods-component='CancellationForm'], [data-oods-component='ClassificationEditor'], [data-oods-component='PreferenceEditor'], [data-oods-component='RoleAssignmentForm'], [data-oods-component='TagInput'], [data-oods-component='TagManager'], [data-oods-component='TemplatePicker']) select,
658
887
  :where([data-oods-component='AddressEditor'], [data-oods-component='CancellationForm'], [data-oods-component='ClassificationEditor'], [data-oods-component='PreferenceEditor'], [data-oods-component='RoleAssignmentForm'], [data-oods-component='TagInput'], [data-oods-component='TagManager'], [data-oods-component='TemplatePicker']) textarea {
659
- padding: var(--cmp-input-padding-block-compact, 0.375rem) var(--cmp-input-padding-inline-compact, 0.5rem);
660
- border: 1px solid var(--cmp-form-border, CanvasText);
661
- border-radius: var(--cmp-input-radius, 0.5rem);
662
- background: transparent;
663
- color: inherit;
888
+ box-sizing: border-box;
889
+ min-block-size: var(--sys-control-height-md, 2rem);
890
+ padding: 0 var(--cmp-input-padding-inline, 0.75rem);
891
+ border: 1px solid var(--cmp-input-border, CanvasText);
892
+ border-radius: var(--cmp-input-radius, 6px);
893
+ background: var(--cmp-input-background, Canvas);
894
+ color: var(--cmp-input-text, CanvasText);
664
895
  font: inherit;
896
+ font-size: var(--sys-text-scale-body-sm-font-size, 14px);
897
+ line-height: var(--sys-text-scale-body-sm-line-height, 20px);
665
898
  }
666
899
 
900
+ :where([data-oods-component='AddressEditor'], [data-oods-component='CancellationForm'], [data-oods-component='ClassificationEditor'], [data-oods-component='PreferenceEditor'], [data-oods-component='RoleAssignmentForm'], [data-oods-component='TagInput'], [data-oods-component='TagManager'], [data-oods-component='TemplatePicker']) textarea { padding-block: var(--sys-control-padding-block-lg, 0.5rem); }
901
+
667
902
  :where([data-oods-component='StatusSelector']) {
668
903
  --cmp-input-background: var(--sys-surface-raised);
669
- --cmp-input-border: var(--sys-border-subtle);
904
+ --cmp-input-border: var(--sys-border-interactive);
670
905
  --cmp-input-text: var(--sys-text-primary);
671
- --cmp-input-focus: var(--sys-border-strong);
906
+ --cmp-input-focus: var(--sys-border-interactive-hover);
672
907
  display: grid;
673
908
  gap: var(--sys-control-gap-compact, 0.25rem);
674
909
  color: var(--cmp-input-text, CanvasText);
@@ -680,12 +915,16 @@
680
915
  }
681
916
 
682
917
  :where([data-oods-component='StatusSelector']) select {
683
- padding: var(--cmp-input-padding-block-compact, 0.375rem) var(--cmp-input-padding-inline-compact, 0.5rem);
918
+ box-sizing: border-box;
919
+ min-block-size: var(--sys-control-height-md, 2rem);
920
+ padding: 0 var(--cmp-input-padding-inline, 0.75rem);
684
921
  border: 1px solid var(--cmp-input-border, CanvasText);
685
- border-radius: var(--cmp-input-radius, 0.5rem);
922
+ border-radius: var(--cmp-input-radius, 6px);
686
923
  background: var(--cmp-input-background, Canvas);
687
924
  color: var(--cmp-input-text, CanvasText);
688
925
  font: inherit;
926
+ font-size: var(--sys-text-scale-body-sm-font-size, 14px);
927
+ line-height: var(--sys-text-scale-body-sm-line-height, 20px);
689
928
  }
690
929
 
691
930
  /* The focus ring is the shared rule above; the focused field also takes the input focus colour on its border. */
@@ -701,18 +940,18 @@
701
940
  --cmp-summary-label: var(--sys-text-secondary);
702
941
  display: grid;
703
942
  gap: var(--cmp-spacing-stack-sm, 0.75rem);
704
- padding: var(--cmp-spacing-inset-default, 1rem);
943
+ padding: var(--sys-card-padding, 1.5rem);
705
944
  border: 1px solid var(--cmp-summary-border, CanvasText);
706
- border-radius: var(--cmp-input-radius, 0.5rem);
945
+ border-radius: var(--cmp-card-radius, 0.75rem);
707
946
  background: var(--cmp-summary-background, Canvas);
708
947
  color: var(--cmp-summary-text, CanvasText);
709
948
  }
710
949
 
711
950
  :where([data-oods-component='ArchiveSummary'], [data-oods-component='OwnershipSummary'], [data-oods-component='TagSummary'], [data-oods-component='PriceSummary']) > [data-summary-title] {
712
951
  margin: 0;
713
- font-size: var(--sys-text-size-lg, 1.25rem);
714
- font-weight: var(--ref-typography-weights-semibold, 600);
715
- line-height: var(--sys-text-line-height-standard, 1.4);
952
+ font-size: var(--sys-text-scale-heading-md-font-size, 18px);
953
+ font-weight: var(--sys-text-scale-heading-md-font-weight, 600);
954
+ line-height: var(--sys-text-scale-heading-md-line-height, 24px);
716
955
  }
717
956
 
718
957
  :where([data-oods-component='ArchiveSummary'], [data-oods-component='OwnershipSummary'], [data-oods-component='TagSummary'], [data-oods-component='PriceSummary']) > dl {
@@ -740,13 +979,23 @@
740
979
  color: var(--cmp-summary-label, CanvasText);
741
980
  }
742
981
 
982
+ /* s222-m02 (#2502 rulings 9 and 11): a field's label is the label role (14/20 500); its control sits on the raised
983
+ * surface with the 3:1 control border and the md control height (32), the same as the button beside it; help text is
984
+ * muted and an error takes the critical text colour, both at 14/20. A textarea grows by its rows. */
743
985
  .oods-field {
744
986
  display: grid;
987
+ /* A field stretched by its row keeps its label on its control instead of spreading the rows apart. */
988
+ align-content: start;
745
989
  gap: var(--cmp-input-gap, 0.375rem);
746
990
  color: var(--cmp-text-body, CanvasText);
747
991
  }
748
992
 
749
- .oods-field-label { font-weight: var(--ref-typography-weights-semibold, 600); }
993
+ .oods-field-label {
994
+ color: var(--sys-text-primary, CanvasText);
995
+ font-size: var(--sys-text-scale-label-font-size, 14px);
996
+ font-weight: var(--sys-text-scale-label-font-weight, 500);
997
+ line-height: var(--sys-text-scale-label-line-height, 20px);
998
+ }
750
999
 
751
1000
  .oods-field-control,
752
1001
  :where(
@@ -757,35 +1006,51 @@
757
1006
  ) {
758
1007
  inline-size: 100%;
759
1008
  box-sizing: border-box;
760
- padding: var(--cmp-input-padding-block, 0.625rem) var(--cmp-input-padding-inline, 0.75rem);
1009
+ min-block-size: var(--sys-control-height-md, 2rem);
1010
+ padding: 0 var(--cmp-input-padding-inline, 0.75rem);
761
1011
  border: 1px solid var(--cmp-input-border, var(--cmp-border-default, currentColor));
762
- border-radius: var(--cmp-input-radius, 0.5rem);
1012
+ border-radius: var(--cmp-input-radius, 6px);
763
1013
  background: var(--cmp-input-background, Canvas);
764
1014
  color: var(--cmp-input-text, CanvasText);
765
1015
  font: inherit;
1016
+ font-size: var(--sys-text-scale-body-sm-font-size, 14px);
1017
+ line-height: var(--sys-text-scale-body-sm-line-height, 20px);
766
1018
  }
767
1019
 
1020
+ /* A compact field's control is the sm control height (28), the small button's. */
1021
+ .oods-field[data-density='compact'] .oods-field-control { min-block-size: var(--sys-control-height-sm, 1.75rem); }
1022
+ :is(textarea.oods-field-control, textarea[data-oods-component='Textarea']) { padding-block: var(--sys-control-padding-block-lg, 0.5rem); }
1023
+ .oods-field-control:hover:not(:disabled, [aria-invalid='true']) { border-color: var(--sys-border-interactive-hover, CanvasText); }
1024
+ .oods-field-control:disabled { background: var(--sys-surface-disabled, Canvas); color: var(--sys-text-disabled, GrayText); cursor: not-allowed; }
768
1025
  .oods-field-control::placeholder { color: var(--cmp-input-placeholder, GrayText); }
769
- .oods-field-control[aria-invalid='true'] { border-color: var(--cmp-input-message-border, Mark); }
1026
+ /* An invalid control's border takes the critical icon role, the status step that reaches 3:1 on the surface. */
1027
+ .oods-field-control[aria-invalid='true'] { border-color: var(--sys-status-critical-icon, Mark); }
770
1028
  .oods-field-help { color: var(--cmp-input-support-text, var(--cmp-text-muted, GrayText)); }
771
- .oods-field-error { color: var(--cmp-input-message-text, MarkText); }
1029
+ .oods-field-error { color: var(--cmp-input-message-text, MarkText); font-size: var(--sys-text-scale-body-sm-font-size, 14px); line-height: var(--sys-text-scale-body-sm-line-height, 20px); margin: 0; }
772
1030
 
1031
+ /* s222-m02 (#2502 ruling 11): the banner's dismiss is a ghost icon button, square at the small control height, centred
1032
+ * on the title's line; its hover tints the banner's own text colour. */
773
1033
  .oods-banner-dismiss {
774
1034
  display: inline-flex;
775
- inline-size: var(--cmp-button-height, 2.5rem);
776
- block-size: var(--cmp-button-height, 2.5rem);
1035
+ inline-size: var(--cmp-button-height-sm, 1.75rem);
1036
+ block-size: var(--cmp-button-height-sm, 1.75rem);
777
1037
  align-items: center;
778
1038
  justify-content: center;
779
1039
  align-self: start;
1040
+ box-sizing: border-box;
1041
+ margin-block: calc(-1 * var(--sys-control-gap-compact, 0.25rem));
780
1042
  padding: 0;
781
- border: 1px solid currentColor;
782
- border-radius: var(--cmp-button-radius, 0.5rem);
1043
+ border: 1px solid transparent;
1044
+ border-radius: var(--cmp-button-radius, 6px);
783
1045
  background: transparent;
784
1046
  color: inherit;
785
1047
  font: inherit;
786
1048
  cursor: pointer;
787
1049
  }
788
1050
 
1051
+ .oods-banner-dismiss:hover { background: color-mix(in oklab, currentColor 12%, transparent); }
1052
+ .oods-banner-dismiss > svg { inline-size: var(--sys-control-icon-size, 1rem); block-size: var(--sys-control-icon-size, 1rem); }
1053
+
789
1054
  :where(.oods-checkbox, [data-oods-component='Checkbox']) {
790
1055
  display: inline-grid;
791
1056
  grid-template-columns: auto 1fr;
@@ -824,54 +1089,110 @@
824
1089
  justify-content: var(--oods-layout-justify, flex-start);
825
1090
  }
826
1091
 
1092
+ /* s222-m02 (#2502 rulings 9 and 11): a table sits in a bordered container with the large control radius on the raised
1093
+ * surface. Rows are 44px (36 dense) with 12px (8) cell padding at the small body size (14/20); the header is 500 in the
1094
+ * muted colour; numbers align at the end in tabular figures; the caption is left-aligned above the header, or visually
1095
+ * hidden when its table asks. */
1096
+ .oods-table__container {
1097
+ box-sizing: border-box;
1098
+ max-inline-size: 100%;
1099
+ overflow-x: auto;
1100
+ border: 1px solid var(--sys-border-subtle, CanvasText);
1101
+ border-radius: var(--sys-radius-control-lg, 8px);
1102
+ background: var(--sys-surface-raised, Canvas);
1103
+ }
1104
+
827
1105
  :where(.oods-table, [data-oods-component='Table']) {
1106
+ --oods-table-row-height: var(--sys-table-row-height, 2.75rem);
1107
+ --oods-table-cell-padding-inline: var(--sys-table-cell-padding-inline, 0.75rem);
828
1108
  inline-size: 100%;
829
1109
  border-collapse: collapse;
830
1110
  background: var(--cmp-surface-panel, Canvas);
831
1111
  color: var(--cmp-text-body, CanvasText);
1112
+ font-size: var(--sys-text-scale-body-sm-font-size, 14px);
1113
+ line-height: var(--sys-text-scale-body-sm-line-height, 20px);
832
1114
  }
833
1115
 
834
1116
  :where(.oods-table, [data-oods-component='Table'])[data-density='compact'] {
835
- --oods-table-cell-padding-block: var(--sys-space-inset-compact, 0.5rem);
836
- --oods-table-cell-padding-inline: var(--sys-space-inline-sm, 0.875rem);
837
- font-size: var(--sys-text-size-sm, 0.875rem);
1117
+ --oods-table-row-height: var(--sys-table-row-height-compact, 2.25rem);
1118
+ --oods-table-cell-padding-inline: var(--sys-table-cell-padding-inline-compact, 0.5rem);
838
1119
  }
839
1120
 
840
1121
  :where(.oods-table, [data-oods-component='Table'])[data-density='default'],
841
1122
  :where(.oods-table, [data-oods-component='Table'])[data-density='comfortable'] {
842
- --oods-table-cell-padding-block: var(--cmp-spacing-inset-sm, 0.75rem);
843
- --oods-table-cell-padding-inline: var(--sys-space-inset-default, 1.5rem);
844
- font-size: var(--sys-text-size-md, 1rem);
1123
+ --oods-table-row-height: var(--sys-table-row-height, 2.75rem);
1124
+ --oods-table-cell-padding-inline: var(--sys-table-cell-padding-inline, 0.75rem);
845
1125
  }
846
1126
 
847
1127
  :where(.oods-table, [data-oods-component='Table']) :is(th, td) {
848
- padding: var(--oods-table-cell-padding-block, var(--cmp-spacing-inset-compact, 0.75rem))
849
- var(--oods-table-cell-padding-inline, var(--cmp-spacing-inset-default, 1rem));
1128
+ box-sizing: border-box;
1129
+ block-size: var(--oods-table-row-height);
1130
+ padding: 0 var(--oods-table-cell-padding-inline);
850
1131
  border-block-end: 1px solid var(--cmp-border-default, currentColor);
851
1132
  text-align: start;
1133
+ vertical-align: middle;
1134
+ }
1135
+
1136
+ :where(.oods-table, [data-oods-component='Table']) th {
1137
+ color: var(--sys-text-muted, GrayText);
1138
+ font-weight: var(--sys-text-scale-label-font-weight, 500);
1139
+ }
1140
+
1141
+ :where(.oods-table, [data-oods-component='Table']) :is(th, td)[data-numeric='true'] { text-align: end; font-variant-numeric: tabular-nums; }
1142
+ :where(.oods-table, [data-oods-component='Table']) tbody > tr:last-child > :is(th, td) { border-block-end: 0; }
1143
+ :where(.oods-table, [data-oods-component='Table']) tbody > tr[data-selectable='true']:hover { background: var(--sys-surface-subtle, Canvas); }
1144
+
1145
+ /* A caption hidden on request stays the table's accessible name. */
1146
+ :where(.oods-table, [data-oods-component='Table']) > caption[data-visually-hidden='true'] { position: absolute; inline-size: 1px; block-size: 1px; margin: -1px; padding: 0; overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0; }
1147
+
1148
+ :where(.oods-table, [data-oods-component='Table']) > caption {
1149
+ padding: var(--sys-inset-sm, 0.75rem) var(--oods-table-cell-padding-inline);
1150
+ border-block-end: 1px solid var(--cmp-border-default, currentColor);
1151
+ color: var(--sys-text-primary, CanvasText);
1152
+ font-weight: var(--sys-text-scale-heading-sm-font-weight, 600);
1153
+ text-align: start;
1154
+ }
1155
+
1156
+ /* A row's action is its first cell's text as a ghost button: no fill and no border, 500 weight, underlined on hover; the
1157
+ * shared rule paints its focus. */
1158
+ :where(.oods-table-row-action) {
1159
+ padding: 0;
1160
+ border: 0;
1161
+ border-radius: var(--sys-radius-control-sm, 4px);
1162
+ background: transparent;
1163
+ color: inherit;
1164
+ font: inherit;
1165
+ font-weight: var(--sys-text-scale-label-font-weight, 500);
1166
+ text-align: start;
1167
+ text-underline-offset: 0.25em;
1168
+ cursor: pointer;
852
1169
  }
853
1170
 
1171
+ :where(.oods-table-row-action):hover { text-decoration: underline; }
1172
+
1173
+ /* s222-m02 (#2502 rulings 8 and 11): a tab is the label role (14/20 500; 16/24 at lg) in the secondary text colour; the
1174
+ * selected tab takes the primary text and a 2px indicator in the brand's primary fill, laid over the list's hairline. */
854
1175
  :where(.oods-tabs, [data-oods-component='Tabs']) {
855
- --oods-tabs-font-size: var(--sys-text-size-md, 1rem);
1176
+ --oods-tabs-font-size: var(--sys-text-scale-label-font-size, 14px);
1177
+ --oods-tabs-line-height: var(--sys-text-scale-label-line-height, 20px);
856
1178
  --oods-tabs-padding-block: var(--cmp-tabs-padding-block, 0.625rem);
857
1179
  --oods-tabs-padding-inline: var(--cmp-tabs-padding-inline, 0.75rem);
858
1180
  color: var(--cmp-text-body, CanvasText);
859
1181
  }
860
1182
 
861
1183
  :where(.oods-tabs, [data-oods-component='Tabs'])[data-size='sm'] {
862
- --oods-tabs-font-size: var(--sys-text-size-sm, 0.875rem);
863
1184
  --oods-tabs-padding-block: var(--cmp-tabs-padding-block-sm, 0.5rem);
864
1185
  --oods-tabs-padding-inline: var(--cmp-tabs-padding-inline-sm, 0.625rem);
865
1186
  }
866
1187
 
867
1188
  :where(.oods-tabs, [data-oods-component='Tabs'])[data-size='md'] {
868
- --oods-tabs-font-size: var(--sys-text-size-md, 1rem);
869
1189
  --oods-tabs-padding-block: var(--cmp-tabs-padding-block, 0.625rem);
870
1190
  --oods-tabs-padding-inline: var(--cmp-tabs-padding-inline, 0.75rem);
871
1191
  }
872
1192
 
873
1193
  :where(.oods-tabs, [data-oods-component='Tabs'])[data-size='lg'] {
874
- --oods-tabs-font-size: var(--sys-text-size-lg, 1.25rem);
1194
+ --oods-tabs-font-size: var(--sys-text-scale-body-md-font-size, 16px);
1195
+ --oods-tabs-line-height: var(--sys-text-scale-body-md-line-height, 24px);
875
1196
  --oods-tabs-padding-block: var(--cmp-tabs-padding-block-lg, 0.75rem);
876
1197
  --oods-tabs-padding-inline: var(--cmp-tabs-padding-inline-lg, 1rem);
877
1198
  }
@@ -881,15 +1202,17 @@
881
1202
  gap: var(--sys-control-gap-compact, 0.25rem);
882
1203
  padding: var(--sys-control-gap-compact, 0.25rem);
883
1204
  border: 1px solid var(--cmp-border-default, currentColor);
884
- border-radius: var(--cmp-button-radius, 0.5rem);
1205
+ border-radius: var(--sys-radius-control-lg, 8px);
885
1206
  background: var(--cmp-surface-panel, Canvas);
886
- box-shadow: var(--cmp-shadow-overlay-offset-x, 0px) var(--cmp-shadow-overlay-offset-y, 24px) var(--cmp-shadow-overlay-blur, 56px) var(--cmp-shadow-overlay-spread, -16px) var(--cmp-shadow-overlay-color, rgba(15, 23, 42, 0.24));
1207
+ box-shadow: var(--cmp-shadow-overlay-offset-x, 0px) var(--cmp-shadow-overlay-offset-y, 8px) var(--cmp-shadow-overlay-blur, 16px) var(--cmp-shadow-overlay-spread, -4px) var(--cmp-shadow-overlay-color, rgba(15, 23, 42, 0.24));
887
1208
  }
888
1209
 
889
- .oods-tab-list { display: flex; gap: var(--cmp-spacing-inline-xs, 0.5rem); overflow-x: auto; border-block-end: 1px solid var(--cmp-border-default, currentColor); }
890
- .oods-tab { padding: var(--oods-tabs-padding-block) var(--oods-tabs-padding-inline); border: 0; border-block-end: var(--cmp-tabs-indicator-width, 0.1875rem) solid transparent; background: transparent; color: inherit; font: inherit; font-size: var(--oods-tabs-font-size); line-height: var(--sys-text-line-height-standard, 1.4); }
891
- :where(.oods-tabs-overflow-trigger, .tabs__overflow-trigger) { padding: var(--oods-tabs-padding-block) var(--oods-tabs-padding-inline); font: inherit; font-size: var(--oods-tabs-font-size); line-height: var(--sys-text-line-height-standard, 1.4); }
892
- .oods-tab[aria-selected='true'] { border-block-end-color: var(--cmp-text-accent, Highlight); font-weight: var(--ref-typography-weights-semibold, 600); }
1210
+ .oods-tab-list { display: flex; gap: 0; overflow-x: auto; border-block-end: 1px solid var(--cmp-border-default, currentColor); }
1211
+ .oods-tab { margin-block-end: -1px; padding: var(--oods-tabs-padding-block) var(--oods-tabs-padding-inline); border: 0; border-block-end: var(--cmp-tabs-indicator-width, 0.125rem) solid transparent; background: transparent; color: var(--sys-text-secondary, CanvasText); font: inherit; font-size: var(--oods-tabs-font-size); font-weight: var(--sys-text-scale-label-font-weight, 500); line-height: var(--oods-tabs-line-height); cursor: pointer; }
1212
+ .oods-tab:hover:not(:disabled) { color: var(--sys-text-primary, CanvasText); }
1213
+ .oods-tab:disabled { color: var(--sys-text-disabled, GrayText); cursor: not-allowed; }
1214
+ :where(.oods-tabs-overflow-trigger, .tabs__overflow-trigger) { padding: var(--oods-tabs-padding-block) var(--oods-tabs-padding-inline); font: inherit; font-size: var(--oods-tabs-font-size); font-weight: var(--sys-text-scale-label-font-weight, 500); line-height: var(--oods-tabs-line-height); }
1215
+ .oods-tab[aria-selected='true'] { border-block-end-color: var(--sys-surface-interactive-primary-default, Highlight); color: var(--sys-text-primary, CanvasText); }
893
1216
  .oods-tab-panel { padding-block: var(--cmp-spacing-stack-default, 1rem); }
894
1217
 
895
1218
  :where(.oods-text, [data-oods-component='Text']) {
@@ -897,18 +1220,19 @@
897
1220
  font: inherit;
898
1221
  }
899
1222
 
1223
+ /* s222-m02 (#2502 ruling 8): the small and medium text sizes are the body roles, 14/20 and 16/24. */
900
1224
  :where(.oods-text, [data-oods-component='Text'])[data-size='sm'] {
901
- font-size: var(--sys-text-size-sm, 0.875rem);
902
- line-height: var(--sys-text-line-height-relaxed, 1.5);
1225
+ font-size: var(--sys-text-scale-body-sm-font-size, 14px);
1226
+ line-height: var(--sys-text-scale-body-sm-line-height, 20px);
903
1227
  }
904
1228
 
905
1229
  :where(.oods-text, [data-oods-component='Text'])[data-size='md'] {
906
- font-size: var(--sys-text-size-md, 1rem);
907
- line-height: var(--sys-text-line-height-relaxed, 1.5);
1230
+ font-size: var(--sys-text-scale-body-md-font-size, 16px);
1231
+ line-height: var(--sys-text-scale-body-md-line-height, 24px);
908
1232
  }
909
1233
 
910
1234
  :where(.oods-text, [data-oods-component='Text'])[data-size='lg'] {
911
- font-size: var(--sys-text-size-lg, 1.25rem);
1235
+ font-size: var(--sys-text-size-lg, 18px);
912
1236
  line-height: var(--sys-text-line-height-standard, 1.4);
913
1237
  }
914
1238
 
@@ -949,16 +1273,28 @@
949
1273
  border-color: CanvasText;
950
1274
  background: CanvasText;
951
1275
  }
1276
+
1277
+ :where([data-oods-component='ColorizedBadge'], [data-oods-component='ArchivePill'], [data-oods-component='CancellationBadge'], [data-oods-component='OwnerBadge'], [data-oods-component='ClassificationBadge'], [data-oods-component='AddressSummaryBadge'], [data-oods-component='MessageStatusBadge'], [data-oods-component='PreferenceSummaryBadge'], .oods-badge, [data-oods-component='RoleBadgeList'] [data-role-badge], [data-oods-component='TagPills'] :is([data-tag-pill], [data-tag-overflow])) {
1278
+ box-shadow: inset 0 0 0 1px CanvasText;
1279
+ }
952
1280
  }
953
1281
 
954
- [data-theme='hc'] :where([data-oods-component='ColorSwatch'], [data-oods-component='ColorizedBadge'], [data-oods-component='ArchivePill'], [data-oods-component='CancellationBadge'], [data-oods-component='OwnerBadge'], [data-oods-component='ClassificationBadge'], [data-oods-component='AddressSummaryBadge'], [data-oods-component='MessageStatusBadge'], [data-oods-component='PreferenceSummaryBadge'], [data-oods-component='RoleBadgeList'], [data-oods-component='TagPills']) {
1282
+ /* s221-m02 (#2482 ruling 4): a theme works in any element, so an hc rule reaches only what hc themes most closely:
1283
+ * never the inside of a panel that sets another theme within an hc page. The :where() adds no specificity. */
1284
+ [data-theme='hc'] :where([data-oods-component='ColorSwatch'], [data-oods-component='ColorizedBadge'], [data-oods-component='ArchivePill'], [data-oods-component='CancellationBadge'], [data-oods-component='OwnerBadge'], [data-oods-component='ClassificationBadge'], [data-oods-component='AddressSummaryBadge'], [data-oods-component='MessageStatusBadge'], [data-oods-component='PreferenceSummaryBadge'], [data-oods-component='RoleBadgeList'], [data-oods-component='TagPills']):not(:where([data-theme='hc'] [data-theme]:not([data-theme='hc']) *)) {
955
1285
  border-color: CanvasText;
956
1286
  background: Canvas;
957
1287
  color: CanvasText;
958
1288
  }
959
1289
 
960
- [data-theme='hc'] :where([data-oods-component='ColorSwatch']) > [data-oods-swatch-chip],
961
- [data-theme='hc'] :where([data-oods-component='ColorizedBadge']) [data-oods-badge-marker] {
1290
+ /* s222-m02 (#2502 ruling 11): the badge families have no border, so their high-contrast outline is drawn inside the
1291
+ * pill, as the Badge's is. */
1292
+ [data-theme='hc'] :where([data-oods-component='ColorizedBadge'], [data-oods-component='ArchivePill'], [data-oods-component='CancellationBadge'], [data-oods-component='OwnerBadge'], [data-oods-component='ClassificationBadge'], [data-oods-component='AddressSummaryBadge'], [data-oods-component='MessageStatusBadge'], [data-oods-component='PreferenceSummaryBadge'], [data-oods-component='RoleBadgeList'] [data-role-badge], [data-oods-component='TagPills'] :is([data-tag-pill], [data-tag-overflow]), [data-oods-component='StatusBadge'], [data-oods-component='PriceBadge']):not(:where([data-theme='hc'] [data-theme]:not([data-theme='hc']) *)) {
1293
+ box-shadow: inset 0 0 0 1px CanvasText;
1294
+ }
1295
+
1296
+ [data-theme='hc'] :where([data-oods-component='ColorSwatch']) > [data-oods-swatch-chip]:not(:where([data-theme='hc'] [data-theme]:not([data-theme='hc']) *)),
1297
+ [data-theme='hc'] :where([data-oods-component='ColorizedBadge']) [data-oods-badge-marker]:not(:where([data-theme='hc'] [data-theme]:not([data-theme='hc']) *)) {
962
1298
  border-color: CanvasText;
963
1299
  background: CanvasText;
964
1300
  }
@@ -969,27 +1305,47 @@
969
1305
  * HighlightText (which is only guaranteed against a Highlight background).
970
1306
  */
971
1307
  [data-theme='hc'] :where(
972
- .oods-badge,
973
- [data-oods-component='Badge'],
974
1308
  .oods-banner,
975
1309
  [data-oods-component='Banner']
976
- ) {
977
- border-color: Highlight;
1310
+ ):not(:where([data-theme='hc'] [data-theme]:not([data-theme='hc']) *)) {
1311
+ border-color: CanvasText;
978
1312
  background: Canvas;
979
1313
  color: CanvasText;
980
1314
  }
981
1315
 
982
- [data-theme='hc'] .oods-field-error {
1316
+ /* s222-m02 (#2502 rulings 6 and 11): a badge has no border, so in high contrast its outline is drawn inside its box and
1317
+ * the 20px height holds; subtle and solid both read CanvasText on Canvas. */
1318
+ [data-theme='hc'] :where(
1319
+ .oods-badge,
1320
+ [data-oods-component='Badge']
1321
+ ):not(:where([data-theme='hc'] [data-theme]:not([data-theme='hc']) *)) {
1322
+ background: Canvas;
983
1323
  color: CanvasText;
1324
+ box-shadow: inset 0 0 0 1px CanvasText;
984
1325
  }
985
1326
 
986
- [data-theme='hc'] :where(.oods-button, [data-oods-component='Button']):not(:disabled) {
1327
+ [data-theme='hc'] .oods-field-error:not(:where([data-theme='hc'] [data-theme]:not([data-theme='hc']) *)) {
1328
+ color: CanvasText;
1329
+ }
1330
+
1331
+ /* s222-m02: the banner's ghost dismiss takes the CanvasText outline every non-primary action has in high contrast. */
1332
+ [data-theme='hc'] .oods-banner-dismiss:not(:where([data-theme='hc'] [data-theme]:not([data-theme='hc']) *)) { border-color: CanvasText; }
1333
+
1334
+ /* s222-m01 (#2502 ruling 6): in high contrast only the primary action is Highlight on HighlightText; every other intent is
1335
+ * Canvas and CanvasText with a 1px CanvasText border, so the intents stay apart. */
1336
+ [data-theme='hc'] :where(.oods-button, [data-oods-component='Button']):not(:disabled):not(:where([data-theme='hc'] [data-theme]:not([data-theme='hc']) *)) {
1337
+ border-color: CanvasText;
1338
+ background: Canvas;
1339
+ color: CanvasText;
1340
+ }
1341
+
1342
+ [data-theme='hc'] :where(.oods-button, [data-oods-component='Button'])[data-intent='primary']:not(:disabled):not(:where([data-theme='hc'] [data-theme]:not([data-theme='hc']) *)) {
987
1343
  border-color: Highlight;
988
1344
  background: Highlight;
989
1345
  color: HighlightText;
990
1346
  }
991
1347
 
992
- [data-theme='hc'] :where(.oods-button, [data-oods-component='Button']):disabled {
1348
+ [data-theme='hc'] :where(.oods-button, [data-oods-component='Button']):disabled:not(:where([data-theme='hc'] [data-theme]:not([data-theme='hc']) *)) {
993
1349
  border-color: GrayText;
994
1350
  background: Canvas;
995
1351
  color: GrayText;
@@ -1004,7 +1360,7 @@
1004
1360
  }
1005
1361
  }
1006
1362
 
1007
- [data-theme='hc'] :where([data-oods-component='AddressCollectionPanel'], [data-oods-component='ClassificationPanel'], [data-oods-component='MembershipPanel'], [data-oods-component='PreferencePanel'], [data-oods-component='FilterPanel'], [data-oods-component='ArchiveSummary'], [data-oods-component='OwnershipSummary'], [data-oods-component='TagSummary'], [data-oods-component='PriceSummary'], [data-oods-component='TagManager'], [data-oods-component='AddressValidationTimeline'], [data-oods-component='MembershipAuditTimeline'], [data-oods-component='MessageEventTimeline'], [data-oods-component='PreferenceTimeline'], [data-oods-component='AuditEvent'], [data-oods-component='AddressEditor'], [data-oods-component='CancellationForm'], [data-oods-component='ClassificationEditor'], [data-oods-component='PreferenceEditor'], [data-oods-component='RoleAssignmentForm'], [data-oods-component='StatusSelector'], [data-oods-component='TagInput'], [data-oods-component='TemplatePicker']) {
1363
+ [data-theme='hc'] :where([data-oods-component='AddressCollectionPanel'], [data-oods-component='ClassificationPanel'], [data-oods-component='MembershipPanel'], [data-oods-component='PreferencePanel'], [data-oods-component='FilterPanel'], [data-oods-component='ArchiveSummary'], [data-oods-component='OwnershipSummary'], [data-oods-component='TagSummary'], [data-oods-component='PriceSummary'], [data-oods-component='TagManager'], [data-oods-component='AddressValidationTimeline'], [data-oods-component='MembershipAuditTimeline'], [data-oods-component='MessageEventTimeline'], [data-oods-component='PreferenceTimeline'], [data-oods-component='AuditEvent'], [data-oods-component='AddressEditor'], [data-oods-component='CancellationForm'], [data-oods-component='ClassificationEditor'], [data-oods-component='PreferenceEditor'], [data-oods-component='RoleAssignmentForm'], [data-oods-component='StatusSelector'], [data-oods-component='TagInput'], [data-oods-component='TemplatePicker']):not(:where([data-theme='hc'] [data-theme]:not([data-theme='hc']) *)) {
1008
1364
  border-color: CanvasText;
1009
1365
  background: Canvas;
1010
1366
  color: CanvasText;
@@ -1018,34 +1374,35 @@
1018
1374
  display: inline-flex;
1019
1375
  align-items: center;
1020
1376
  gap: var(--cmp-badge-gap, 0.25rem);
1021
- min-block-size: var(--cmp-badge-height, 1.5rem);
1377
+ min-block-size: var(--cmp-badge-height, 1.25rem);
1022
1378
  box-sizing: border-box;
1023
1379
  padding: var(--cmp-badge-padding-block, 0.125rem) var(--cmp-badge-padding-inline, 0.5rem);
1024
- border: 1px solid var(--cmp-badge-border, var(--cmp-border-default, currentColor));
1380
+ border: 0;
1025
1381
  border-radius: var(--cmp-badge-radius, 999px);
1026
1382
  background: var(--cmp-badge-background, var(--cmp-surface-subtle, transparent));
1027
1383
  color: var(--cmp-badge-text, var(--cmp-text-body, currentColor));
1028
- font-size: var(--cmp-badge-font-size, 0.875rem);
1029
- font-weight: var(--cmp-badge-font-weight, 600);
1030
- line-height: var(--sys-text-line-height-tight, 1.2);
1384
+ font-size: var(--cmp-badge-font-size, 12px);
1385
+ font-weight: var(--cmp-badge-font-weight, 500);
1386
+ line-height: var(--sys-text-scale-caption-line-height, 16px);
1387
+ white-space: nowrap;
1031
1388
  }
1032
1389
 
1033
- :where([data-oods-component='StatusBadge'])[data-status='active'],
1034
- :where([data-oods-component='StatusBadge'])[data-status='success'] {
1390
+ :where([data-oods-component='StatusBadge'])[data-status='active']:not([data-tone]),
1391
+ :where([data-oods-component='StatusBadge'])[data-status='success']:not([data-tone]) {
1035
1392
  --cmp-badge-background: var(--sys-status-success-surface, Canvas);
1036
1393
  --cmp-badge-border: var(--sys-status-success-border, currentColor);
1037
1394
  --cmp-badge-text: var(--sys-status-success-text, CanvasText);
1038
1395
  }
1039
1396
 
1040
- :where([data-oods-component='StatusBadge'])[data-status='past_due'],
1041
- :where([data-oods-component='StatusBadge'])[data-status='warning'] {
1397
+ :where([data-oods-component='StatusBadge'])[data-status='past_due']:not([data-tone]),
1398
+ :where([data-oods-component='StatusBadge'])[data-status='warning']:not([data-tone]) {
1042
1399
  --cmp-badge-background: var(--sys-status-warning-surface, Canvas);
1043
1400
  --cmp-badge-border: var(--sys-status-warning-border, currentColor);
1044
1401
  --cmp-badge-text: var(--sys-status-warning-text, CanvasText);
1045
1402
  }
1046
1403
 
1047
- :where([data-oods-component='StatusBadge'])[data-status='cancelled'],
1048
- :where([data-oods-component='StatusBadge'])[data-status='error'] {
1404
+ :where([data-oods-component='StatusBadge'])[data-status='cancelled']:not([data-tone]),
1405
+ :where([data-oods-component='StatusBadge'])[data-status='error']:not([data-tone]) {
1049
1406
  --cmp-badge-background: var(--sys-status-critical-surface, Canvas);
1050
1407
  --cmp-badge-border: var(--sys-status-critical-border, currentColor);
1051
1408
  --cmp-badge-text: var(--sys-status-critical-text, CanvasText);
@@ -1081,9 +1438,9 @@
1081
1438
  :where([data-oods-component='CancellationSummary']) {
1082
1439
  display: grid;
1083
1440
  gap: var(--cmp-spacing-stack-sm, 0.75rem);
1084
- padding: var(--cmp-spacing-inset-default, 1rem);
1441
+ padding: var(--sys-card-padding, 1.5rem);
1085
1442
  border: 1px solid var(--cmp-border-default, currentColor);
1086
- border-radius: var(--cmp-input-radius, 0.5rem);
1443
+ border-radius: var(--cmp-card-radius, 0.75rem);
1087
1444
  background: var(--cmp-surface-panel, Canvas);
1088
1445
  color: var(--cmp-text-body, CanvasText);
1089
1446
  }
@@ -1112,26 +1469,45 @@
1112
1469
  :where([data-oods-component='SearchInput']) input[type='search'] {
1113
1470
  inline-size: 100%;
1114
1471
  box-sizing: border-box;
1115
- padding: var(--cmp-input-padding-block, 0.625rem) var(--cmp-input-padding-inline, 0.75rem);
1472
+ min-block-size: var(--sys-control-height-md, 2rem);
1473
+ padding: 0 var(--cmp-input-padding-inline, 0.75rem);
1116
1474
  border: 1px solid var(--cmp-input-border, var(--cmp-border-default, currentColor));
1117
- border-radius: var(--cmp-input-radius, 0.5rem);
1475
+ border-radius: var(--cmp-input-radius, 6px);
1118
1476
  background: var(--cmp-input-background, Canvas);
1119
1477
  color: var(--cmp-input-text, CanvasText);
1120
1478
  font: inherit;
1479
+ font-size: var(--sys-text-scale-body-sm-font-size, 14px);
1480
+ line-height: var(--sys-text-scale-body-sm-line-height, 20px);
1121
1481
  }
1122
1482
 
1483
+ /* s222-m02 (#2502 ruling 11): search and pagination buttons are the outline button at the control height; a page
1484
+ * number is square. */
1123
1485
  :where([data-oods-component='SearchInput']) button,
1124
1486
  :where([data-oods-component='PaginationBar']) button {
1125
1487
  display: inline-flex;
1126
- min-inline-size: var(--cmp-button-height, 2.5rem);
1127
- min-block-size: var(--cmp-button-height, 2.5rem);
1488
+ box-sizing: border-box;
1489
+ min-inline-size: var(--cmp-button-height, 2rem);
1490
+ min-block-size: var(--cmp-button-height, 2rem);
1128
1491
  align-items: center;
1129
1492
  justify-content: center;
1130
- border: 1px solid var(--cmp-button-border, var(--cmp-border-default, currentColor));
1131
- border-radius: var(--cmp-button-radius, 0.5rem);
1132
- background: var(--cmp-button-background, Canvas);
1133
- color: var(--cmp-button-text, CanvasText);
1493
+ padding: 0 var(--cmp-button-padding-inline-sm, 0.625rem);
1494
+ border: 1px solid var(--sys-border-strong, CanvasText);
1495
+ border-radius: var(--cmp-button-radius, 6px);
1496
+ background: var(--sys-surface-raised, Canvas);
1497
+ color: var(--sys-text-primary, CanvasText);
1134
1498
  font: inherit;
1499
+ font-size: var(--sys-text-scale-label-font-size, 14px);
1500
+ font-weight: var(--sys-text-scale-label-font-weight, 500);
1501
+ line-height: var(--sys-text-scale-label-line-height, 20px);
1502
+ cursor: pointer;
1503
+ }
1504
+
1505
+ :where([data-oods-component='SearchInput'], [data-oods-component='PaginationBar']) button:hover:not(:disabled) { background: var(--sys-surface-interactive-secondary-default, Canvas); }
1506
+ :where([data-oods-component='SearchInput'], [data-oods-component='PaginationBar']) button > svg { flex: none; inline-size: var(--sys-control-icon-size, 1rem); block-size: var(--sys-control-icon-size, 1rem); }
1507
+ :where([data-oods-component='PaginationBar']) button[aria-current='page'] {
1508
+ border-color: transparent;
1509
+ background: var(--sys-surface-interactive-primary-default, Highlight);
1510
+ color: var(--sys-text-on-interactive, HighlightText);
1135
1511
  }
1136
1512
 
1137
1513
  :where([data-oods-component='PaginationBar']) {
@@ -1143,6 +1519,8 @@
1143
1519
  }
1144
1520
 
1145
1521
  :where([data-oods-component='PaginationBar']) button:disabled {
1522
+ border-color: var(--sys-border-subtle, GrayText);
1523
+ background: var(--sys-surface-disabled, Canvas);
1146
1524
  color: var(--cmp-button-text-disabled, GrayText);
1147
1525
  cursor: not-allowed;
1148
1526
  }
@@ -1244,18 +1622,21 @@
1244
1622
  width: 100%;
1245
1623
  min-width: 0;
1246
1624
  box-sizing: border-box;
1247
- padding: var(--space-2) var(--space-3);
1625
+ min-block-size: var(--sys-control-height-md);
1626
+ padding: 0 var(--space-3);
1248
1627
  font: inherit;
1628
+ font-size: var(--sys-text-scale-body-sm-font-size);
1629
+ line-height: var(--sys-text-scale-body-sm-line-height);
1249
1630
  color: inherit;
1250
- background: var(--sys-surface-default);
1251
- border: 1px solid var(--sys-border-default);
1631
+ background: var(--sys-surface-raised);
1632
+ border: 1px solid var(--sys-border-interactive);
1252
1633
  border-radius: var(--radius-md);
1253
1634
  }
1254
1635
  :where([data-oods-component='BillingAmountInput'], [data-oods-component='BillingIntervalSelector']) > select {
1255
1636
  color: var(--cmp-billing-interval-text, var(--sys-text-subtle));
1256
1637
  }
1257
1638
  :where([data-oods-component='BillingAmountInput'], [data-oods-component='BillingIntervalSelector']) > [aria-invalid='true'] {
1258
- border-color: var(--sys-status-critical-border);
1639
+ border-color: var(--sys-status-critical-icon);
1259
1640
  }
1260
1641
  :where([data-oods-component='BillingAmountInput'], [data-oods-component='BillingIntervalSelector']) > [role='alert'] {
1261
1642
  color: var(--sys-status-critical-text);
@@ -1266,30 +1647,31 @@
1266
1647
  [data-oods-component='CycleProgressCard'],
1267
1648
  :where([data-oods-component='PaymentTimeline'], [data-oods-component='PaymentEventTimeline']) {
1268
1649
  min-width: 0;
1269
- padding: var(--space-4, 1rem);
1650
+ padding: var(--sys-card-padding, 1.5rem);
1270
1651
  border: 1px solid var(--sys-border-default, GrayText);
1271
- border-radius: var(--radius-md, 0.5rem);
1652
+ border-radius: var(--cmp-card-radius, 0.75rem);
1272
1653
  background: var(--sys-surface-default, Canvas);
1273
1654
  color: var(--cmp-billing-timeline-text, var(--sys-text-default, CanvasText));
1274
1655
  }
1275
1656
  [data-oods-component='CycleProgressCard'] h2,
1276
- :where([data-oods-component='PaymentTimeline'], [data-oods-component='PaymentEventTimeline']) h2 { margin: 0 0 var(--space-3, 0.75rem); }
1657
+ :where([data-oods-component='PaymentTimeline'], [data-oods-component='PaymentEventTimeline']) h2 { margin: 0 0 var(--space-3, 0.75rem); font-size: var(--sys-text-scale-heading-md-font-size, 18px); font-weight: var(--sys-text-scale-heading-md-font-weight, 600); line-height: var(--sys-text-scale-heading-md-line-height, 24px); }
1277
1658
  [data-oods-component='CycleProgressCard'] p,
1278
1659
  :where([data-oods-component='PaymentTimeline'], [data-oods-component='PaymentEventTimeline']) p { margin: var(--space-2, 0.5rem) 0; }
1279
1660
  /* s213-m01: the track takes the border role, so the whole cycle reads against the card in both themes (raised surface
1280
- was whiter than the light card, 1.04:1) while the accent fill keeps at least 3:1 against it. */
1661
+ was whiter than the light card, 1.04:1) while the accent fill keeps at least 3:1 against it. s222-m01: the strong
1662
+ border, since the neutral-first subtle border (#e5e5e5) is 1.26:1 on a white card. */
1281
1663
  [data-oods-component='CycleProgressCard'] progress {
1282
1664
  width: 100%;
1283
1665
  height: var(--cmp-billing-cycle-progress-height, 0.5rem);
1284
1666
  appearance: none;
1285
1667
  border: 0;
1286
- border-radius: var(--sys-radius-control, 0.5rem);
1668
+ border-radius: var(--sys-radius-control, 6px);
1287
1669
  overflow: hidden;
1288
- background: var(--sys-border-default, Canvas);
1670
+ background: var(--sys-border-strong, Canvas);
1289
1671
  color: var(--cmp-billing-cycle-progress-fill, var(--sys-text-accent, Highlight));
1290
1672
  }
1291
1673
  [data-oods-component='CycleProgressCard'] progress::-webkit-progress-bar {
1292
- background: var(--sys-border-default, Canvas);
1674
+ background: var(--sys-border-strong, Canvas);
1293
1675
  }
1294
1676
  [data-oods-component='CycleProgressCard'] progress::-webkit-progress-value {
1295
1677
  background: var(--cmp-billing-cycle-progress-fill, var(--sys-text-accent, Highlight));
@@ -1325,17 +1707,24 @@
1325
1707
  [data-oods-component='ArchivedRowOverlay'][data-archived='true']:has(> .oods-collection-row) {
1326
1708
  box-sizing: border-box;
1327
1709
  border: 1px solid var(--sys-border-strong, CanvasText);
1328
- border-radius: var(--cmp-button-radius, 0.5rem);
1710
+ border-radius: var(--cmp-button-radius, 6px);
1329
1711
  background: var(--sys-surface-raised, Canvas);
1330
1712
  padding-inline-end: var(--space-4, 1rem);
1331
1713
  }
1332
1714
  [data-oods-component='ArchivedRowOverlay'][data-archived='true'] > .oods-collection-row { border: 0; background: transparent; }
1715
+ /* s222-m02 (#2502 ruling 11): the archive mark is a badge: a 20px pill at 12/500. */
1333
1716
  .oods-archive-badge {
1334
- display: inline-block;
1717
+ display: inline-flex;
1718
+ align-items: center;
1719
+ box-sizing: border-box;
1720
+ min-block-size: var(--cmp-badge-height, 1.25rem);
1335
1721
  white-space: nowrap;
1336
1722
  flex-shrink: 0;
1337
- padding: var(--space-1, 0.25rem) var(--space-2, 0.5rem);
1338
- border-radius: var(--radius-sm, 0.5rem);
1723
+ padding: var(--cmp-badge-padding-block, 0.125rem) var(--cmp-badge-padding-inline, 0.5rem);
1724
+ border-radius: var(--cmp-badge-radius, 999px);
1725
+ font-size: var(--cmp-badge-font-size, 12px);
1726
+ font-weight: var(--cmp-badge-font-weight, 500);
1727
+ line-height: var(--sys-text-scale-caption-line-height, 16px);
1339
1728
  color: var(--status-archive-text, var(--sys-text-primary));
1340
1729
  background: var(--status-archive-bg, var(--sys-surface-raised));
1341
1730
  }
@@ -1347,7 +1736,8 @@
1347
1736
  }
1348
1737
  [data-oods-component='CancellationSummary'] [data-summary-item] { min-width: 0; }
1349
1738
  [data-oods-component='CancellationSummary'] dd { margin: 0; overflow-wrap: break-word; }
1350
- .oods-field-help { display: block; margin: var(--cmp-input-gap, 0.375rem) 0 var(--cmp-spacing-stack-md, 1rem); font-size: var(--sys-text-size-sm, 0.875rem); color: var(--sys-text-subtle, GrayText); }
1739
+ /* s222-m02 (#2502 ruling 11): help text is muted at 14/20 and spaced by its field's gap, not by margins of its own. */
1740
+ .oods-field-help { display: block; margin: 0; font-size: var(--sys-text-scale-body-sm-font-size, 14px); line-height: var(--sys-text-scale-body-sm-line-height, 20px); color: var(--sys-text-muted, GrayText); }
1351
1741
  .oods-cancellation-form { margin: 0; min-width: 0; }
1352
1742
  .oods-field:has(input[type='checkbox']) { display: block; }
1353
1743
  .oods-field label:has(input[type='checkbox']) { display: flex; flex-direction: row; align-items: center; gap: var(--cmp-checkbox-gap, 0.5rem); }
@@ -1362,25 +1752,26 @@
1362
1752
  .workflow-content [data-oods-collection-toolbar] > [data-oods-component='Select'],
1363
1753
  .workflow-content [data-oods-collection-toolbar] > .oods-field:has(select) { flex: 1 1 180px; min-width: min(180px, 100%); }
1364
1754
  [data-oods-collection-toolbar] select { width: 100%; box-sizing: border-box; }
1365
- [data-oods-component='Stack']:has(> [data-oods-collection-toolbar]) { font-family: var(--ref-typography-families-sans, system-ui, sans-serif); }
1366
- .oods-collection-row { --oods-button-background: var(--sys-surface-raised); --oods-button-background-hover: var(--sys-surface-subtle); --oods-button-border: var(--sys-border-subtle); --oods-button-text: var(--sys-text-primary); width: 100%; display: flex; flex-wrap: wrap; align-items: center; gap: var(--cmp-spacing-inline-sm, 0.75rem); text-align: left; padding: var(--cmp-spacing-inset-default, 1rem); }
1367
- [data-theme='hc'] .oods-collection-row:not(:disabled) { background: var(--sys-surface-raised); color: var(--sys-text-primary); }
1755
+ /* s222-m02: the toolbar's stack reads in the brand's own sans (it named the shared reference family, which is not brand B's). */
1756
+ [data-oods-component='Stack']:has(> [data-oods-collection-toolbar]) { font-family: var(--sys-font-sans); }
1757
+ .oods-collection-row { --oods-button-background: var(--sys-surface-raised); --oods-button-background-hover: var(--sys-surface-subtle); --oods-button-border: var(--sys-border-subtle); --oods-button-text: var(--sys-text-primary); width: 100%; display: flex; flex-wrap: wrap; white-space: normal; align-items: center; gap: var(--cmp-spacing-inline-sm, 0.75rem); text-align: left; padding: var(--cmp-spacing-inset-default, 1rem); }
1758
+ [data-theme='hc'] .oods-collection-row:not(:disabled):not(:where([data-theme='hc'] [data-theme]:not([data-theme='hc']) *)) { background: var(--sys-surface-raised); color: var(--sys-text-primary); }
1368
1759
  .oods-collection-row > :first-child { min-width: 0; flex: 1 1 140px; font-weight: var(--ref-typography-weights-semibold, 600); }
1369
1760
  .oods-collection-row .oods-badge { max-width: 100%; width: fit-content; flex: 0 0 auto; text-transform: none; letter-spacing: normal; }
1370
1761
  [data-oods-collection="events"] time { display: block; margin-top: var(--cmp-spacing-stack-xs, 0.5rem); font-size: var(--sys-text-size-sm, 0.875rem); }
1371
1762
  .oods-pagination-bar__pages { display: flex; gap: var(--sys-control-gap-tight, 0.375rem); list-style: none; margin: 0; padding: 0; }
1372
1763
  @media (max-width: 600px) { .oods-collection-row { flex-direction: column; align-items: flex-start; } .oods-collection-row > :first-child { flex-basis: auto; width: 100%; } }
1373
1764
 
1374
- :where(.oods-audit-summary, [data-oods-component='AuditSummaryCard']) { padding: var(--cmp-spacing-inset-default); border: 1px solid var(--cmp-border-default); border-radius: var(--cmp-input-radius); background: var(--cmp-surface-panel); color: var(--cmp-text-body); }
1375
- .oods-audit-summary h2 { margin-top: 0; }
1765
+ :where(.oods-audit-summary, [data-oods-component='AuditSummaryCard']) { padding: var(--sys-card-padding); border: 1px solid var(--cmp-border-default); border-radius: var(--cmp-card-radius); background: var(--cmp-surface-panel); color: var(--cmp-text-body); }
1766
+ .oods-audit-summary h2 { margin-top: 0; font-size: var(--sys-text-scale-heading-md-font-size); font-weight: var(--sys-text-scale-heading-md-font-weight); line-height: var(--sys-text-scale-heading-md-line-height); }
1376
1767
  .oods-audit-summary dl { display: grid; grid-template-columns: auto 1fr; gap: var(--cmp-spacing-inline-sm); }
1377
1768
  .oods-audit-summary dd { margin: 0; }
1378
1769
  :where(.oods-sort-indicator, [data-oods-component='SortIndicator']) { border-collapse: collapse; color: var(--cmp-text-body); }
1379
- .oods-sort-indicator button { padding: var(--cmp-spacing-inline-sm); background: var(--cmp-surface-panel); color: var(--cmp-text-body); border: 1px solid var(--cmp-border-default); border-radius: var(--cmp-input-radius); cursor: pointer; }
1770
+ .oods-sort-indicator button { box-sizing: border-box; min-block-size: var(--cmp-button-height-sm); padding: 0 var(--cmp-button-padding-inline-sm); background: var(--sys-surface-raised); color: var(--cmp-text-body); border: 1px solid var(--sys-border-strong); border-radius: var(--cmp-button-radius); font: inherit; font-size: var(--sys-text-scale-label-font-size); font-weight: var(--sys-text-scale-label-font-weight); line-height: var(--sys-text-scale-label-line-height); cursor: pointer; }
1380
1771
  [data-oods-component='TimelineEntryLabel'] { color: var(--cmp-text-body); }
1381
1772
 
1382
- .oods-trait-recipe, :where([data-oods-component='ArchiveEvent'], [data-oods-component='CancellationEvent'], [data-oods-component='ColorStatePicker'], [data-oods-component='CommunicationDetailPanel'], [data-oods-component='GeoFieldMappingForm'], [data-oods-component='GeocodablePreview'], [data-oods-component='StateTransitionEvent'], [data-oods-component='StatusColorLegend'], [data-oods-component='VizAreaControls'], [data-oods-component='VizAxisControls'], [data-oods-component='VizAxisSummary'], [data-oods-component='VizColorControls'], [data-oods-component='VizColorLegendConfig'], [data-oods-component='VizHeatmapControls'], [data-oods-component='VizLineControls'], [data-oods-component='VizMarkControls'], [data-oods-component='VizOpacityControls'], [data-oods-component='VizOpacitySummary'], [data-oods-component='VizPointControls'], [data-oods-component='VizScaleControls'], [data-oods-component='VizScaleSummary'], [data-oods-component='VizScatterControls'], [data-oods-component='VizShapeControls'], [data-oods-component='VizShapeLegend'], [data-oods-component='VizSizeControls'], [data-oods-component='VizSizeSummary']) { min-width: 0; margin: 0; padding: var(--cmp-spacing-inset-default); border: 1px solid var(--cmp-border-default); border-radius: var(--cmp-input-radius); background: var(--cmp-surface-panel); color: var(--cmp-text-body); overflow-wrap: anywhere; }
1383
- .oods-trait-recipe h2 { margin-top: 0; }
1773
+ .oods-trait-recipe, :where([data-oods-component='ArchiveEvent'], [data-oods-component='CancellationEvent'], [data-oods-component='ColorStatePicker'], [data-oods-component='CommunicationDetailPanel'], [data-oods-component='GeoFieldMappingForm'], [data-oods-component='GeocodablePreview'], [data-oods-component='StateTransitionEvent'], [data-oods-component='StatusColorLegend'], [data-oods-component='VizAreaControls'], [data-oods-component='VizAxisControls'], [data-oods-component='VizAxisSummary'], [data-oods-component='VizColorControls'], [data-oods-component='VizColorLegendConfig'], [data-oods-component='VizHeatmapControls'], [data-oods-component='VizLineControls'], [data-oods-component='VizMarkControls'], [data-oods-component='VizOpacityControls'], [data-oods-component='VizOpacitySummary'], [data-oods-component='VizPointControls'], [data-oods-component='VizScaleControls'], [data-oods-component='VizScaleSummary'], [data-oods-component='VizScatterControls'], [data-oods-component='VizShapeControls'], [data-oods-component='VizShapeLegend'], [data-oods-component='VizSizeControls'], [data-oods-component='VizSizeSummary']) { min-width: 0; margin: 0; padding: var(--sys-card-padding); border: 1px solid var(--cmp-border-default); border-radius: var(--cmp-card-radius); background: var(--cmp-surface-panel); color: var(--cmp-text-body); overflow-wrap: anywhere; }
1774
+ .oods-trait-recipe h2 { margin-top: 0; font-size: var(--sys-text-scale-heading-md-font-size); font-weight: var(--sys-text-scale-heading-md-font-weight); line-height: var(--sys-text-scale-heading-md-line-height); }
1384
1775
  .oods-trait-recipe dd { margin: 0 0 var(--cmp-spacing-inline-sm); }
1385
1776
  .oods-trait-recipe dt { font-weight: var(--ref-typography-weights-semibold, 600); }
1386
1777
  .oods-trait-recipe .oods-field { margin-block: var(--cmp-spacing-inline-sm); }
@@ -1390,22 +1781,33 @@
1390
1781
 
1391
1782
  /* Producer-owned read fields stay labelled and readable in every context. */
1392
1783
  [data-oods-component='Stack'][id$='-read-field'] { gap: var(--sys-control-gap-compact, 0.25rem); min-width: 0; }
1393
- [data-oods-component='Stack'][id$='-read-fields'] { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 240px), 1fr)); gap: var(--sys-space-scale-lg, 1.25rem); }
1784
+ [data-oods-component='Stack'][id$='-read-fields'] { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 240px), 1fr)); gap: var(--sys-space-scale-lg, 24px); }
1394
1785
  [data-oods-component='Stack'][id$='-read-fields'] > :not([id$='-read-field']) { grid-column: 1 / -1; }
1395
1786
  [data-oods-component='Stack'][id$='-read-field'] > :first-child { color: var(--sys-text-secondary); }
1396
1787
  [data-oods-component='Stack'][id$='-read-field'] > :last-child { overflow-wrap: anywhere; align-self: flex-start; max-width: 100%; }
1397
1788
  /* s213-m03: a declared major-unit amount reads through PriceBadge in a detail row; its pill hugs the amount instead of
1398
1789
  stretching across the row. */
1399
1790
  [data-oods-component='Stack'][id$='-read-field'] > [data-oods-component='PriceBadge'] { align-self: flex-start; }
1791
+ /* s221-m02 (#2482 ruling 7; the website's Warehouse, message dfc707d1): at desktop width a panel of read-only rows uses
1792
+ * the room, in two columns. The panel's stack layout is inline in the generated source, so display is overridden here
1793
+ * and the generated source does not move. */
1794
+ @media (min-width: 48rem) {
1795
+ [data-oods-component='Stack']:has(> [data-oods-component='Stack'][id$='-read-field']):not([id$='-read-fields']) {
1796
+ display: grid !important;
1797
+ grid-template-columns: repeat(2, minmax(0, 1fr));
1798
+ align-items: start;
1799
+ }
1800
+ [data-oods-component='Stack']:has(> [data-oods-component='Stack'][id$='-read-field']):not([id$='-read-fields']) > :not([id$='-read-field']) { grid-column: 1 / -1; }
1801
+ }
1400
1802
  [data-oods-component='StatusBadge'] { text-transform: none; letter-spacing: normal; width: fit-content; }
1401
1803
 
1402
1804
  /* Keep the frozen ported block intact; current recipe roles follow semantic fallbacks. */
1403
1805
  :where([data-oods-component='CancellationSummary']) {
1404
1806
  display: grid;
1405
1807
  gap: var(--cmp-spacing-stack-sm, 0.75rem);
1406
- padding: var(--cmp-spacing-inset-default, 1rem);
1808
+ padding: var(--sys-card-padding, 1.5rem);
1407
1809
  border: 1px solid var(--cmp-border-default, var(--sys-border-subtle));
1408
- border-radius: var(--cmp-input-radius, 0.5rem);
1810
+ border-radius: var(--cmp-card-radius, 0.75rem);
1409
1811
  background: var(--cmp-surface-panel, var(--sys-surface-raised));
1410
1812
  color: var(--cmp-text-body, var(--sys-text-primary));
1411
1813
  }
@@ -1421,7 +1823,17 @@
1421
1823
  div.oods-field[data-oods-component='Checkbox'] { display: grid; grid-template-columns: minmax(0, 1fr); }
1422
1824
  .oods-field.oods-checkbox > label,
1423
1825
  .oods-field > label.oods-checkbox { display: flex; align-items: center; gap: var(--cmp-checkbox-gap, 0.5rem); }
1424
- input[data-oods-component='Checkbox'], .oods-field input[type='checkbox'] { margin: 0; flex: 0 0 auto; inline-size: var(--cmp-input-height, 3rem); block-size: var(--cmp-input-height, 3rem); }
1826
+ /* s222-m02 (#2502 ruling 9): a checkbox or radio is 16px, the control icon size, in every component; its help text lines up
1827
+ * with its label. (It read an undefined --cmp-input-height and fell back to 48px.) */
1828
+ :is(input[data-oods-component='Checkbox'], [data-oods-component] input:is([type='checkbox'], [type='radio']), .oods-field input:is([type='checkbox'], [type='radio'])) {
1829
+ margin: 0;
1830
+ flex: 0 0 auto;
1831
+ inline-size: var(--sys-control-icon-size, 1rem);
1832
+ block-size: var(--sys-control-icon-size, 1rem);
1833
+ accent-color: var(--cmp-checkbox-background-checked, Highlight);
1834
+ }
1835
+ .oods-field.oods-checkbox > .oods-field-help,
1836
+ .oods-field.oods-checkbox > .oods-field-error { padding-inline-start: calc(var(--sys-control-icon-size, 1rem) + var(--cmp-checkbox-gap, 0.5rem)); }
1425
1837
  .workflow-field > input { width: 100%; min-width: 0; box-sizing: border-box; font: inherit; }
1426
1838
 
1427
1839
  /* Catalog choices may have long labels; form grids must shrink with their screen. */
@@ -1433,11 +1845,13 @@ input[data-oods-component='Checkbox'], .oods-field input[type='checkbox'] { marg
1433
1845
  * places by the page gutter, and the composer's page-level regions carry no side padding of their own, so a heading,
1434
1846
  * the controls under it and the cards below share one edge. The page's own heading reads as a detail page's does. */
1435
1847
  [data-oods-shell] { display: block; box-sizing: border-box; padding: var(--sys-page-gutter, 1.5rem); }
1848
+ /* s222-m02 (#2502 ruling 8): the page title is heading-xl (30/36 600), as a detail page's is. */
1436
1849
  [data-oods-shell-heading] {
1437
- margin: 0 0 var(--sys-stack-md, 1rem);
1438
- font-size: var(--sys-text-scale-heading-lg-font-size, 1.5rem);
1439
- font-weight: var(--ref-typography-weights-semibold, 600);
1440
- line-height: var(--sys-text-scale-heading-lg-line-height, 1.2);
1850
+ margin: 0 0 var(--sys-stack-lg, 1.5rem);
1851
+ font-size: var(--sys-text-scale-heading-xl-font-size, 30px);
1852
+ font-weight: var(--sys-text-scale-heading-xl-font-weight, 600);
1853
+ line-height: var(--sys-text-scale-heading-xl-line-height, 36px);
1854
+ letter-spacing: var(--sys-text-scale-heading-xl-letter-spacing);
1441
1855
  }
1442
1856
 
1443
1857
  /* s211-m02: a tab label never breaks inside a word ("Ru/n" at 390); a list with more tabs than fit scrolls instead, and
@@ -1449,6 +1863,7 @@ input[data-oods-component='Checkbox'], .oods-field input[type='checkbox'] { marg
1449
1863
  * event (on the event, not also on its list item) and a quieter time under its label. The frozen block above stays. */
1450
1864
  :where([data-oods-component='StatusTimeline'], [data-oods-component='AuditTimeline']) { gap: var(--sys-stack-sm, 0.75rem); }
1451
1865
  :where([data-oods-component='StatusTimeline'], [data-oods-component='AuditTimeline']) > :is(h2, p) { margin: 0; }
1866
+ :where([data-oods-component='StatusTimeline'], [data-oods-component='AuditTimeline']) > h2 { font-size: var(--sys-text-scale-heading-md-font-size, 18px); font-weight: var(--sys-text-scale-heading-md-font-weight, 600); line-height: var(--sys-text-scale-heading-md-line-height, 24px); }
1452
1867
  :where([data-oods-component='StatusTimeline'], [data-oods-component='AuditTimeline']) ol { list-style: none; padding-inline-start: 0; }
1453
1868
  :where([data-oods-component='StatusTimeline'], [data-oods-component='AuditTimeline']) li { border-inline-start: 0; padding-inline-start: 0; }
1454
1869
  :where([data-oods-component='StatusTimeline'], [data-oods-component='AuditTimeline']) article {
@@ -1478,12 +1893,125 @@ input[data-oods-component='Checkbox'], .oods-field input[type='checkbox'] { marg
1478
1893
  [data-oods-reference-inspection] code { overflow-wrap: anywhere; }
1479
1894
 
1480
1895
  /* A destructive action remains distinguishable when every action uses the
1481
- * user's HC system colors: shape and a warning glyph carry the distinction. */
1482
- [data-theme='hc'] :where(.oods-button, [data-oods-component='Button'])[data-intent='danger']:not(:disabled) {
1483
- border: 3px double CanvasText;
1896
+ * user's HC system colors: a warning glyph carries the distinction (s222-m01: with the 1px CanvasText border every
1897
+ * non-primary intent has; s222-m02: the destructive variant too, which shares danger's fill). */
1898
+ [data-theme='hc'] :where(.oods-button, [data-oods-component='Button']):is([data-intent='danger'], [data-intent='destructive']):not(:disabled):not(:where([data-theme='hc'] [data-theme]:not([data-theme='hc']) *)) {
1899
+ border: 1px solid CanvasText;
1484
1900
  background: Canvas;
1485
1901
  color: CanvasText;
1486
1902
  }
1487
- [data-theme='hc'] :where(.oods-button, [data-oods-component='Button'])[data-intent='danger']::before {
1903
+ [data-theme='hc'] :where(.oods-button, [data-oods-component='Button']):is([data-intent='danger'], [data-intent='destructive']):not(:where([data-theme='hc'] [data-theme]:not([data-theme='hc']) *))::before {
1488
1904
  content: "⚠" / "";
1489
1905
  }
1906
+
1907
+ /* ─── s222-m02 F7 (#2502 ruling 12): a placed chart follows the theme ─────────────────────────────────────────────────
1908
+ * A placed chart carries its renders in each theme, each set in a [data-viz-theme] wrapper (vizPreviewLayers in
1909
+ * @oods/component-contracts; the wrapper repeats data-viz-narrow and data-viz-wide, so the size rules above apply inside
1910
+ * it). Each [data-theme] names its theme for the charts under it, and custom properties inherit, so the nearest
1911
+ * [data-theme] decides: dark shows the dark renders, hc the hc ones, any other theme the light ones. With no [data-theme]
1912
+ * on the page the light renders show. A chart without dark or hc renders has no wrapper and shows in every theme. */
1913
+ :where([data-theme]) { --oods-viz-show-light: block; --oods-viz-show-dark: none; --oods-viz-show-hc: none; }
1914
+ :where([data-theme='dark']) { --oods-viz-show-light: none; --oods-viz-show-dark: block; }
1915
+ :where([data-theme='hc']) { --oods-viz-show-light: none; --oods-viz-show-hc: block; }
1916
+ :where([data-viz-theme]) { min-inline-size: 0; }
1917
+ :where([data-viz-theme='light']) { display: var(--oods-viz-show-light, block); }
1918
+ :where([data-viz-theme='dark']) { display: var(--oods-viz-show-dark, none); }
1919
+ :where([data-viz-theme='hc']) { display: var(--oods-viz-show-hc, none); }
1920
+ /* ─── end s222-m02 F7 ──────────────────────────────────────────────────────────────────────────────────────────────── */
1921
+
1922
+ /* ─── s222-m03 (#2502 ruling 13): screens read as a product ──────────────────────────────────────────────────────────
1923
+ * A detail page's header: the record's title and its summary (status and key meta) on the left and the screen's actions
1924
+ * on the right, on one row from 48rem; the sections below it take the full width. The generated stack sets its own
1925
+ * display inline, so the grid is set here with !important, as the read-only rows' columns are (s221-m02). */
1926
+ @media (min-width: 48rem) {
1927
+ [data-oods-component='Stack']:has(> [data-oods-component='DetailHeader']):has(> .oods-action-bar) {
1928
+ display: grid !important;
1929
+ grid-template-columns: minmax(0, 1fr) auto;
1930
+ align-items: start;
1931
+ }
1932
+ [data-oods-component='Stack']:has(> [data-oods-component='DetailHeader']):has(> .oods-action-bar) > * { grid-column: 1 / -1; }
1933
+ [data-oods-component='Stack']:has(> [data-oods-component='DetailHeader']):has(> .oods-action-bar) > [data-oods-component='DetailHeader'] { grid-column: 1; grid-row: 1; }
1934
+ [data-oods-component='Stack']:has(> [data-oods-component='DetailHeader']):has(> .oods-action-bar) > [data-oods-component='Stack'][id$='-record-summary'] { grid-column: 1; grid-row: 2; }
1935
+ [data-oods-component='Stack']:has(> [data-oods-component='DetailHeader']):has(> .oods-action-bar) > .oods-action-bar { grid-column: 2; grid-row: 1 / span 2; justify-self: end; }
1936
+ }
1937
+
1938
+ /* Never a card inside a card: a panel placed inside a card (a tab panel's billing cycle or payments, a summary in a
1939
+ * card's body) is a section of that card. It keeps its heading and content and drops its own border, fill, radius and
1940
+ * inset; the card's gap separates it from its neighbours. */
1941
+ :where(.oods-card, [data-oods-component='Card']) :is(.oods-card, [data-oods-component='Card'], [data-oods-component='AddressCollectionPanel'], [data-oods-component='ClassificationPanel'], [data-oods-component='MembershipPanel'], [data-oods-component='PreferencePanel'], [data-oods-component='FilterPanel'], [data-oods-component='ArchiveSummary'], [data-oods-component='OwnershipSummary'], [data-oods-component='TagSummary'], [data-oods-component='PriceSummary'], [data-oods-component='CancellationSummary'], [data-oods-component='AuditSummaryCard'], [data-oods-component='CycleProgressCard'], [data-oods-component='PaymentTimeline'], [data-oods-component='PaymentEventTimeline'], [data-oods-component='AddressValidationTimeline'], [data-oods-component='MembershipAuditTimeline'], [data-oods-component='MessageEventTimeline'], [data-oods-component='PreferenceTimeline'], .oods-trait-recipe) {
1942
+ padding: 0;
1943
+ border: 0;
1944
+ border-radius: 0;
1945
+ background: transparent;
1946
+ box-shadow: none;
1947
+ }
1948
+
1949
+ /* A list reads as one list: its rows sit in one bordered container on the raised surface, divided by hairlines. A row
1950
+ * is the record's title (500) over its muted secondary line on the left, then its status, meta and time, which the
1951
+ * title's growth pushes to the right. */
1952
+ [data-oods-collection='rows'] > .oods-collection {
1953
+ gap: 0;
1954
+ border: 1px solid var(--sys-border-subtle, CanvasText);
1955
+ border-radius: var(--sys-radius-control-lg, 8px);
1956
+ background: var(--sys-surface-raised, Canvas);
1957
+ overflow: hidden;
1958
+ }
1959
+ [data-oods-collection='rows'] > .oods-collection > li:not(:last-child) { border-block-end: 1px solid var(--sys-border-subtle, CanvasText); }
1960
+ [data-oods-collection='rows'] > .oods-collection .oods-collection-row {
1961
+ --oods-button-border: transparent;
1962
+ --oods-button-background: transparent;
1963
+ --oods-button-background-hover: var(--sys-surface-subtle, Canvas);
1964
+ --oods-button-background-pressed: var(--sys-surface-interactive-secondary-default, Canvas);
1965
+ justify-content: flex-start;
1966
+ padding: var(--sys-inset-sm, 0.75rem) var(--sys-inset-md, 1rem);
1967
+ border-radius: 0;
1968
+ font-weight: var(--sys-text-scale-body-sm-font-weight, 400);
1969
+ }
1970
+ [data-oods-collection='rows'] > .oods-collection .oods-collection-row > :first-child {
1971
+ gap: var(--sys-control-gap-compact, 0.25rem);
1972
+ font-size: var(--sys-text-scale-body-sm-font-size, 14px);
1973
+ line-height: var(--sys-text-scale-body-sm-line-height, 20px);
1974
+ font-weight: var(--sys-text-scale-label-font-weight, 500);
1975
+ }
1976
+ [data-oods-collection='rows'] > .oods-collection .oods-collection-row > :first-child > * { margin: 0; font-size: inherit; line-height: inherit; }
1977
+ /* Money in a row reads as text beside the status, as the time does, not as a tag. */
1978
+ [data-oods-collection='rows'] > .oods-collection .oods-collection-row > :is([data-oods-component='PriceBadge'], [data-oods-component='BillingSummaryBadge']) {
1979
+ padding: 0;
1980
+ background: transparent;
1981
+ color: var(--sys-text-primary, CanvasText);
1982
+ font-size: var(--sys-text-scale-body-sm-font-size, 14px);
1983
+ line-height: var(--sys-text-scale-body-sm-line-height, 20px);
1984
+ font-variant-numeric: tabular-nums;
1985
+ }
1986
+ [data-oods-collection='rows'] > .oods-collection .oods-collection-row > :first-child :is([data-size='sm'], [data-oods-component='Text'] + [data-oods-component='Text']) { color: var(--sys-text-muted, GrayText); font-weight: var(--sys-text-scale-body-sm-font-weight, 400); }
1987
+ [data-oods-collection='rows'] > .oods-collection .oods-collection-row :is(time, [data-oods-component='RelativeTimestamp']) { color: var(--sys-text-muted, GrayText); font-size: var(--sys-text-scale-body-sm-font-size, 14px); }
1988
+ /* The time reads last, after the status and meta. On a phone the title takes the first line and the status, meta and time
1989
+ * wrap together under it, instead of one line each. */
1990
+ [data-oods-collection='rows'] > .oods-collection .oods-collection-row > :is(time, [data-oods-component='RelativeTimestamp']) { order: 1; }
1991
+ @media (max-width: 600px) {
1992
+ [data-oods-collection='rows'] > .oods-collection .oods-collection-row { flex-direction: row; align-items: center; column-gap: var(--sys-control-gap, 0.5rem); row-gap: var(--sys-control-gap-compact, 0.25rem); }
1993
+ [data-oods-collection='rows'] > .oods-collection .oods-collection-row > :first-child { flex: none; inline-size: 100%; }
1994
+ }
1995
+ /* An archived row inside the list keeps its dimming and badge; the list's container and dividers are its border. */
1996
+ [data-oods-collection='rows'] > .oods-collection [data-oods-component='ArchivedRowOverlay'][data-archived='true']:has(> .oods-collection-row) { border: 0; border-radius: 0; background: transparent; }
1997
+ /* A section of a card that holds nothing (an unfilled body slot) takes no room, so the card's own spacing is all there is
1998
+ * between its header and footer. */
1999
+ :where(.oods-card, [data-oods-component='Card']) [data-oods-component='Stack']:not(:has(:not([data-oods-component='Stack']))) { display: none !important; }
2000
+
2001
+ /* A record's events read as one timeline: each event sits on a rail at the left instead of in a card of its own. */
2002
+ [data-oods-collection='events'] > .oods-collection { gap: 0; }
2003
+ [data-oods-collection='events'] > .oods-collection > li > :is(.oods-card, [data-oods-component='Card']) {
2004
+ gap: var(--sys-control-gap-compact, 0.25rem);
2005
+ padding: 0 0 var(--sys-stack-md, 1rem) var(--sys-inset-md, 1rem);
2006
+ border: 0;
2007
+ border-inline-start: var(--ref-border-width-bold, 2px) solid var(--sys-border-strong, CanvasText);
2008
+ border-radius: 0;
2009
+ background: transparent;
2010
+ }
2011
+ [data-oods-collection='events'] > .oods-collection > li:last-child > :is(.oods-card, [data-oods-component='Card']) { padding-block-end: 0; }
2012
+ [data-oods-collection='events'] > .oods-collection time { color: var(--sys-text-muted, GrayText); font-size: var(--sys-text-scale-body-sm-font-size, 14px); }
2013
+ /* An event's title reads at the list title's weight in every renderer (React and Vue write a plain strong; HTML's Text
2014
+ * inherits its weight). */
2015
+ [data-oods-collection='events'] > .oods-collection > li > :is(.oods-card, [data-oods-component='Card']) > strong { font-weight: var(--sys-text-scale-label-font-weight, 500); }
2016
+
2017
+ /* ─── end s222-m03 ──────────────────────────────────────────────────────────────────────────────────────────────── */