baseline-foundry 0.1.5 → 0.1.6

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.
package/README.md CHANGED
@@ -115,7 +115,7 @@ The verified GitHub release artifact remains available as a fallback for
115
115
  environments that cannot reach the npm registry:
116
116
 
117
117
  ```bash
118
- npm install https://github.com/lyubomir-popov/baseline-foundry/releases/download/v0.1.5/baseline-foundry-0.1.5.tgz
118
+ npm install https://github.com/lyubomir-popov/baseline-foundry/releases/download/v0.1.6/baseline-foundry-0.1.6.tgz
119
119
  ```
120
120
 
121
121
  Use the attached `.tgz`, not the GitHub source archive: generated `dist/`
@@ -15,6 +15,12 @@ ${scoped(" :where(.bf-form-label, .bf-form-help, .bf-button, .bf-button.is-base,
15
15
  line-height: var(--bf-body-line-height);
16
16
  }
17
17
 
18
+ /* Preserve the public nested fit after the preset's general typography pass.
19
+ The modifier remains explicit and zero-specificity in every app scope. */
20
+ ${scoped(" :where(.bf-status-label.is-nested, .bf-chip.is-nested)")} {
21
+ line-height: var(--bf-nested-auxiliary-line-height);
22
+ }
23
+
18
24
  ${scoped(" :where(.bf-input, .bf-button, .bf-button.is-base)")} {
19
25
  font-family: inherit;
20
26
  font-size: var(--bf-body-font-size);
@@ -10,7 +10,7 @@ export function chipBadgeStatusCss(options) {
10
10
  ${bodyTypeStyles} align-items: baseline;
11
11
  background-color: var(--bf-ui-chip-background);
12
12
  border: var(--bf-border-width) solid var(--bf-ui-chip-border);
13
- border-radius: 1rem;
13
+ border-radius: var(--bf-ui-chip-radius);
14
14
  color: var(--bf-color-text-default);
15
15
  display: inline-flex;
16
16
  gap: 0;
@@ -173,5 +173,37 @@ ${bodyTypeStyles} margin: 0 0 var(--bf-single-line-row-margin-block-end);
173
173
  --bf-ui-status-background: var(--bf-color-border-negative);
174
174
  --bf-ui-status-color: var(--bf-color-button-negative-text);
175
175
  }
176
+
177
+ /* Nested auxiliary surfaces fit a body-sized flex/grid host instead of
178
+ carrying a second standalone occupied-row contract. This modifier is
179
+ explicit so component density never changes merely because of ancestry. */
180
+ :where(.bf-theme) :where(.bf-chip.is-nested, .bf-status-label.is-nested) {
181
+ line-height: var(--bf-nested-auxiliary-line-height);
182
+ margin-block: 0;
183
+ padding-block: var(--bf-nested-auxiliary-padding-block);
184
+ }
185
+
186
+ :where(.bf-theme) :where(.bf-chip.is-nested) {
187
+ border: 0;
188
+ box-shadow: inset 0 0 0 var(--bf-border-width) var(--bf-ui-chip-border);
189
+ }
190
+
191
+ :where(.bf-theme) :where(.bf-chip.is-nested:hover) {
192
+ box-shadow: inset 0 0 0 var(--bf-border-width) var(--bf-ui-chip-border-hover);
193
+ }
194
+
195
+ :where(.bf-theme) :where(.bf-chip.is-nested:is(:active, [aria-pressed='true'], .is-selected)) {
196
+ box-shadow: inset 0 0 0 var(--bf-border-width) var(--bf-ui-chip-border-active);
197
+ }
198
+
199
+ :where(.bf-theme) :where(.bf-status-label.is-nested) {
200
+ border-block-width: 0;
201
+ }
202
+
203
+ :where(.bf-theme) :where(.bf-badge.is-nested) {
204
+ align-self: center;
205
+ line-height: var(--bf-nested-auxiliary-line-height);
206
+ vertical-align: middle;
207
+ }
176
208
  `;
177
209
  }
@@ -11,6 +11,7 @@ export function legacyNavigationCss(options) {
11
11
  --bf-side-navigation-disclosure-inset: max(0rem, calc(var(--bf-component-inline-inset-continuation) - var(--bf-disclosure-icon-inline-size) - var(--bf-disclosure-gap)));
12
12
  --bf-side-navigation-depth-step: var(--bf-space-2);
13
13
  --bf-side-navigation-group-gap: 1.5rem;
14
+ --bf-side-navigation-heading-list-gap: 0.5rem;
14
15
  color: var(--bf-color-text-inactive);
15
16
  display: block;
16
17
  inline-size: 100%;
@@ -23,11 +24,31 @@ export function legacyNavigationCss(options) {
23
24
  }
24
25
 
25
26
  :where(.bf-theme) :where(.bf-side-navigation-group) {
27
+ display: grid;
28
+ gap: var(--bf-side-navigation-heading-list-gap);
29
+ min-inline-size: 0;
30
+ }
31
+
32
+ /* Keep the divider and heading as one tight header. The group owns only the
33
+ larger transition from that header to its list, so the compensated rule
34
+ cannot change the heading/list phase. */
35
+ :where(.bf-theme) :where(.bf-side-navigation-group-header) {
26
36
  display: grid;
27
37
  gap: 0rem;
28
38
  min-inline-size: 0;
29
39
  }
30
40
 
41
+ :where(.bf-theme) :where(.bf-side-navigation-group-header) > hr {
42
+ inline-size: auto;
43
+ margin-inline: var(--bf-side-navigation-content-inset) 0;
44
+ }
45
+
46
+ /* A single-line group heading occupies four baselines. min-block-size keeps
47
+ that phase exact while still allowing a long heading to wrap and grow. */
48
+ :where(.bf-theme) :where(.bf-side-navigation-group-header) > :where(.bf-side-navigation-heading) {
49
+ min-block-size: calc((var(--bf-baseline) * 4) - var(--bf-body-margin-bottom));
50
+ }
51
+
31
52
  :where(.bf-theme) :where(.bf-side-navigation-drawer) {
32
53
  background: var(--bf-color-background-default);
33
54
  bottom: 0;
@@ -145,6 +166,7 @@ ${bodySemiboldTypeStyles} display: block;
145
166
 
146
167
  :where(.bf-theme) :where(.bf-side-navigation-list) {
147
168
  display: grid;
169
+ grid-auto-rows: var(--bf-single-line-row-block-size);
148
170
  list-style: none;
149
171
  margin: 0;
150
172
  padding: 0;
@@ -158,6 +180,7 @@ ${bodySemiboldTypeStyles} display: block;
158
180
 
159
181
  :where(.bf-theme) :where(.bf-side-navigation-link, .bf-side-navigation-text, .bf-side-navigation-accordion-button) {
160
182
  ${bodyTypeStyles} align-items: center;
183
+ align-self: start;
161
184
  background: transparent;
162
185
  border: 0;
163
186
  border-block: var(--bf-border-width) solid transparent;
@@ -69,13 +69,11 @@ export function navigationLayoutCss() {
69
69
  line-height: var(--bf-top-navigation-logo-title-line-height, var(--bf-body-line-height, 1.5));
70
70
  overflow: visible;
71
71
  overflow-wrap: anywhere;
72
- /* The first title line and the 1rem mark share the mark's fixed centre:
73
- * tag block-end minus the 0.375rem inset minus half the mark. Symmetric title
74
- * padding keeps the occupied row stable across all four type-density tiers. */
72
+ /* The first title line and the 1rem mark share the public brand-line centre.
73
+ * The derived brand block is twice that fixed centre, so the orange tag can
74
+ * extend upward without changing the title or adjacent-header baseline. */
75
75
  padding-block: calc(
76
- var(--bf-top-navigation-logo-tag-block-size)
77
- - var(--bf-top-navigation-logo-icon-bottom-offset)
78
- - (var(--bf-top-navigation-logo-icon-size) / 2)
76
+ var(--bf-navigation-brand-line-center-block)
79
77
  - (var(--bf-top-navigation-logo-title-line-height, var(--bf-body-line-height, 1.5rem)) / 2)
80
78
  );
81
79
  text-overflow: clip;
@@ -52,10 +52,6 @@ export function panelCss(options) {
52
52
  inline-size: 100%;
53
53
  }
54
54
 
55
- :where(.bf-theme) :where(.bf-panel-header.is-navigation-brand) :where(.bf-top-navigation-logo-title) {
56
- transform: translateY(var(--bf-navigation-brand-title-optical-offset-block));
57
- }
58
-
59
55
  :where(.bf-theme) :where(.bf-panel-header) > :where(.bf-panel-title) {
60
56
  min-inline-size: 0;
61
57
  }
@@ -69,10 +69,6 @@ ${bodyMediumTypeStyles} color: var(--bf-color-text-default);
69
69
  border-block-end-color: var(--bf-color-border-low-contrast);
70
70
  }
71
71
 
72
- :where(.bf-theme) :where(tbody tr:has(.bf-status-label) > td) {
73
- padding-block: calc((var(--bf-baseline) - var(--bf-table-row-border-size)) / 2);
74
- }
75
-
76
72
  :where(.bf-theme) :where(tbody tr:hover td) {
77
73
  background: color-mix(in srgb, var(--bf-color-background-hover) 68%, transparent);
78
74
  }
@@ -89,8 +89,6 @@ export function componentsCss(tokens, themeSurfaces) {
89
89
  const h6 = tokens.roles.h6 ?? body;
90
90
  const baselineUnit = tokens.baselineUnit;
91
91
  const components = tokens.components;
92
- const controlBlockPaddingVar = "var(--bf-control-block-padding)";
93
- const controlCompactBlockPaddingVar = "var(--bf-control-block-padding-compact)";
94
92
  const inputBlockPaddingVar = "var(--bf-input-block-padding)";
95
93
  const buttonBlockPaddingVar = "var(--bf-button-block-padding)";
96
94
  const bodyLineHeight = roleLineHeightVar("body", body.lineHeight);
@@ -125,14 +123,21 @@ ${componentAlignmentVars(components)} /* Action surfaces keep comfortable comma
125
123
  padding and trailing baseline compensation must resolve through this pair. */
126
124
  --bf-single-line-row-padding-block: max(0rem, calc(var(--bf-button-block-padding) - var(--bf-border-width)));
127
125
  --bf-single-line-row-margin-block-end: ${singleLineRowMarginBottom};
126
+ --bf-single-line-row-block-size: calc(${bodyLineHeight} + (var(--bf-single-line-row-padding-block) * 2) + (var(--bf-border-width) * 2) + var(--bf-single-line-row-margin-block-end));
127
+ --bf-single-line-row-in-box-padding-block-start: ${bodySelectedStartNudge};
128
+ --bf-single-line-row-in-box-padding-block-end: max(0rem, calc(var(--bf-single-line-row-block-size) - ${bodyLineHeight} - var(--bf-single-line-row-in-box-padding-block-start)));
128
129
  --bf-single-line-row-visual-offset: ${alignedVisualStart(bodyLineHeight, "var(--bf-control-visual-size)", bodySelectedStartNudge)};
130
+ /* Auxiliary surfaces may opt into a host-owned nested composition. The
131
+ shorter line and capped symmetric padding fit their complete paint inside
132
+ the host body line without introducing a second row rhythm. */
133
+ --bf-nested-auxiliary-line-height: max(1em, calc(var(--bf-body-line-height) - var(--bf-baseline)));
134
+ --bf-nested-auxiliary-padding-block: min(var(--bf-single-line-row-padding-block), max(0rem, calc((var(--bf-body-line-height) - var(--bf-nested-auxiliary-line-height)) / 2)));
129
135
  --bf-slider-track-size: calc(var(--bf-baseline) * 0.25);
130
- --bf-slider-row-block-size: max(var(--bf-control-box-size-compact), calc(${bodySelectedStartNudge} + ${bodyLineHeight} + ${bodySelectedEndNudge}));
136
+ --bf-slider-row-block-size: var(--bf-single-line-row-block-size);
131
137
  --bf-slider-track-offset: ${alignedVisualStart(bodyLineHeight, "var(--bf-slider-track-size)", bodySelectedStartNudge)};
132
138
  --bf-table-row-border-size: var(--bf-border-width);
133
- --bf-table-row-padding-block-start: ${bodySelectedStartNudge};
134
- --bf-table-row-content-size: calc(${bodyLineHeight} + (var(--bf-table-row-padding-block-start) * 2) + var(--bf-table-row-border-size));
135
- --bf-table-row-block-size: calc(var(--bf-table-row-content-size) + mod(calc(var(--bf-baseline) - mod(var(--bf-table-row-content-size), var(--bf-baseline))), var(--bf-baseline)));
139
+ --bf-table-row-padding-block-start: var(--bf-single-line-row-in-box-padding-block-start);
140
+ --bf-table-row-block-size: var(--bf-single-line-row-block-size);
136
141
  --bf-table-row-padding-block-end: max(0rem, calc(var(--bf-table-row-block-size) - ${bodyLineHeight} - var(--bf-table-row-padding-block-start) - var(--bf-table-row-border-size)));
137
142
  --bf-table-row-line-height: ${bodyLineHeight};
138
143
  --bf-switch-track-offset: var(--bf-single-line-row-visual-offset);
@@ -182,7 +187,8 @@ ${componentAlignmentVars(components)} /* Action surfaces keep comfortable comma
182
187
  --bf-top-navigation-logo-tag-gap: 0.25rem;
183
188
  --bf-top-navigation-logo-icon-bottom-offset: 0.375rem;
184
189
  --bf-top-navigation-logo-icon-optical-offset-inline: -0.0125rem;
185
- --bf-navigation-brand-title-optical-offset-block: 0rem;
190
+ --bf-navigation-brand-line-center-block: calc(var(--bf-top-navigation-logo-tag-block-size) - var(--bf-top-navigation-logo-icon-bottom-offset) - (var(--bf-top-navigation-logo-icon-size) / 2));
191
+ --bf-navigation-brand-block-size: calc(var(--bf-navigation-brand-line-center-block) * 2);
186
192
  --bf-icon-size-default: 1rem;
187
193
  --bf-icon-size-medium: 2.5rem;
188
194
  --bf-icon-size-large: 4rem;
@@ -192,6 +198,7 @@ ${componentAlignmentVars(components)} /* Action surfaces keep comfortable comma
192
198
  --bf-leading-icon-gap: var(--bf-leading-mark-gap);
193
199
  --bf-leading-icon-offset: var(--bf-single-line-row-visual-offset);
194
200
  --bf-ui-chip-padding-inline: var(--bf-component-inline-inset-field);
201
+ --bf-ui-chip-radius: 999rem;
195
202
  --bf-ui-badge-padding-inline: calc(${bodyLineHeight} * 0.25);
196
203
  --bf-ui-badge-overhang: calc(var(--bf-ui-badge-padding-inline) * -0.75);
197
204
  --bf-grid-max-inline-size: var(--bf-content-max-width);
@@ -377,10 +384,33 @@ ${typeStyles(body, { includeCase: false })} appearance: none;
377
384
  ${controlPadding(inputBlockPaddingVar)} padding-inline: var(--bf-component-inline-inset-field);
378
385
  }
379
386
 
380
- :where(.bf-theme) :where(input[type='color'].bf-color-input) {
387
+ :where(.bf-theme) :where(.bf-color-control) {
388
+ display: grid;
389
+ grid-template-areas: "color-control";
381
390
  inline-size: 4rem;
382
- min-block-size: var(--bf-control-box-size);
383
- padding: calc(var(--bf-baseline) * 0.5);
391
+ }
392
+
393
+ /* Native color inputs do not expose a body-text line box. This invisible
394
+ metric strut gives their wrapper the same natural padding/border/margin
395
+ construction as every textual control, including under browser zoom. */
396
+ :where(.bf-theme) :where(.bf-color-control)::before {
397
+ border-block: var(--bf-border-width) solid transparent;
398
+ content: "\\00a0";
399
+ grid-area: color-control;
400
+ line-height: var(--bf-body-line-height);
401
+ margin-bottom: var(--bf-single-line-row-margin-block-end);
402
+ padding-block: var(--bf-single-line-row-padding-block);
403
+ visibility: hidden;
404
+ }
405
+
406
+ :where(.bf-theme) :where(.bf-color-control) > :where(input[type='color'].bf-color-input) {
407
+ align-self: stretch;
408
+ block-size: auto;
409
+ grid-area: color-control;
410
+ inline-size: 100%;
411
+ margin-bottom: var(--bf-single-line-row-margin-block-end);
412
+ min-block-size: 0;
413
+ padding: var(--bf-border-width);
384
414
  }
385
415
 
386
416
  :where(.bf-theme) :where(.bf-input, input[type='text'], input[type='number'], input[type='search'], input[type='password'], input[type='email'], input[type='url'], textarea, select):hover {
@@ -416,13 +446,13 @@ ${controlPadding(inputBlockPaddingVar)} padding-inline: var(--bf-component-inli
416
446
  :where(.bf-theme) :where(input[type='file']) {
417
447
  ${typeStyles(body, { includeCase: false })} background: transparent;
418
448
  border: 0 solid transparent;
419
- border-bottom: var(--bf-border-width) solid var(--bf-color-border-default);
420
- border-top: var(--bf-border-width) solid transparent;
449
+ box-shadow: inset 0 calc(var(--bf-border-width) * -1) 0 var(--bf-color-border-default);
421
450
  color: var(--bf-color-text-default);
422
451
  margin-bottom: ${inputMarginBottom};
423
452
  max-inline-size: 100%;
424
453
  min-inline-size: 0;
425
- ${controlPadding(inputBlockPaddingVar)} padding-inline: 0;
454
+ padding-block: 0;
455
+ padding-inline: 0;
426
456
  width: 100%;
427
457
  }
428
458
 
@@ -434,8 +464,9 @@ ${typeStyles(body, { includeCase: false })} appearance: none;
434
464
  color: var(--bf-color-text-default);
435
465
  cursor: pointer;
436
466
  margin-inline-end: var(--bf-field-gap);
437
- min-block-size: var(--bf-control-box-size-compact);
438
- ${controlPadding(controlCompactBlockPaddingVar)} padding-inline: var(--bf-control-inline-padding-action-bordered);
467
+ min-block-size: 0;
468
+ padding-block: var(--bf-single-line-row-padding-block);
469
+ padding-inline: var(--bf-control-inline-padding-action-bordered);
439
470
  }
440
471
 
441
472
  :where(.bf-theme) :where(input[type='file'])::file-selector-button:hover {
@@ -779,6 +810,15 @@ ${typeStyles(body, { includeCase: false })} border-block: var(--bf-border-width
779
810
  padding: 0;
780
811
  }
781
812
 
813
+ /* A composite slider's numeric field owns the shared occupied row. Stretching
814
+ the track within that real sibling height avoids a second nominal-height
815
+ calculation that can diverge when rem borders are rasterised under zoom. */
816
+ :where(.bf-theme) :where(.bf-slider:not(.is-stacked)):not(:where(.bf-field.is-range.is-stacked) :where(.bf-slider)) > :where(input[type='range']) {
817
+ align-self: stretch;
818
+ block-size: auto;
819
+ margin-block: 0;
820
+ }
821
+
782
822
  :where(.bf-theme) :where(input[type='range']):focus:not(:focus-visible) {
783
823
  outline: none;
784
824
  }
@@ -1038,7 +1078,8 @@ ${typeStyles(body, { includeCase: false })} background: transparent;
1038
1078
  display: block;
1039
1079
  margin: 0;
1040
1080
  overflow: hidden;
1041
- padding-block: var(--bf-control-block-padding-compact);
1081
+ padding-block-end: var(--bf-single-line-row-in-box-padding-block-end);
1082
+ padding-block-start: var(--bf-single-line-row-in-box-padding-block-start);
1042
1083
  padding-inline: var(--bf-component-inline-inset-action);
1043
1084
  text-align: left;
1044
1085
  text-decoration: none;
@@ -924,14 +924,21 @@ html.u-baseline-grid::after {
924
924
  padding and trailing baseline compensation must resolve through this pair. */
925
925
  --bf-single-line-row-padding-block: max(0rem, calc(var(--bf-button-block-padding) - var(--bf-border-width)));
926
926
  --bf-single-line-row-margin-block-end: calc(0rem + mod(calc(var(--bf-baseline) - mod(calc(var(--bf-body-line-height, 1.5rem) + (var(--bf-button-block-padding) * 2)), var(--bf-baseline))), var(--bf-baseline)));
927
+ --bf-single-line-row-block-size: calc(var(--bf-body-line-height, 1.5rem) + (var(--bf-single-line-row-padding-block) * 2) + (var(--bf-border-width) * 2) + var(--bf-single-line-row-margin-block-end));
928
+ --bf-single-line-row-in-box-padding-block-start: var(--bf-body-nudge-start, 0.375rem);
929
+ --bf-single-line-row-in-box-padding-block-end: max(0rem, calc(var(--bf-single-line-row-block-size) - var(--bf-body-line-height, 1.5rem) - var(--bf-single-line-row-in-box-padding-block-start)));
927
930
  --bf-single-line-row-visual-offset: calc(var(--bf-body-nudge-start, 0.375rem) + ((var(--bf-body-line-height, 1.5rem) - var(--bf-control-visual-size)) / 2));
931
+ /* Auxiliary surfaces may opt into a host-owned nested composition. The
932
+ shorter line and capped symmetric padding fit their complete paint inside
933
+ the host body line without introducing a second row rhythm. */
934
+ --bf-nested-auxiliary-line-height: max(1em, calc(var(--bf-body-line-height) - var(--bf-baseline)));
935
+ --bf-nested-auxiliary-padding-block: min(var(--bf-single-line-row-padding-block), max(0rem, calc((var(--bf-body-line-height) - var(--bf-nested-auxiliary-line-height)) / 2)));
928
936
  --bf-slider-track-size: calc(var(--bf-baseline) * 0.25);
929
- --bf-slider-row-block-size: max(var(--bf-control-box-size-compact), calc(var(--bf-body-nudge-start, 0.375rem) + var(--bf-body-line-height, 1.5rem) + var(--bf-body-nudge-end)));
937
+ --bf-slider-row-block-size: var(--bf-single-line-row-block-size);
930
938
  --bf-slider-track-offset: calc(var(--bf-body-nudge-start, 0.375rem) + ((var(--bf-body-line-height, 1.5rem) - var(--bf-slider-track-size)) / 2));
931
939
  --bf-table-row-border-size: var(--bf-border-width);
932
- --bf-table-row-padding-block-start: var(--bf-body-nudge-start, 0.375rem);
933
- --bf-table-row-content-size: calc(var(--bf-body-line-height, 1.5rem) + (var(--bf-table-row-padding-block-start) * 2) + var(--bf-table-row-border-size));
934
- --bf-table-row-block-size: calc(var(--bf-table-row-content-size) + mod(calc(var(--bf-baseline) - mod(var(--bf-table-row-content-size), var(--bf-baseline))), var(--bf-baseline)));
940
+ --bf-table-row-padding-block-start: var(--bf-single-line-row-in-box-padding-block-start);
941
+ --bf-table-row-block-size: var(--bf-single-line-row-block-size);
935
942
  --bf-table-row-padding-block-end: max(0rem, calc(var(--bf-table-row-block-size) - var(--bf-body-line-height, 1.5rem) - var(--bf-table-row-padding-block-start) - var(--bf-table-row-border-size)));
936
943
  --bf-table-row-line-height: var(--bf-body-line-height, 1.5rem);
937
944
  --bf-switch-track-offset: var(--bf-single-line-row-visual-offset);
@@ -981,7 +988,8 @@ html.u-baseline-grid::after {
981
988
  --bf-top-navigation-logo-tag-gap: 0.25rem;
982
989
  --bf-top-navigation-logo-icon-bottom-offset: 0.375rem;
983
990
  --bf-top-navigation-logo-icon-optical-offset-inline: -0.0125rem;
984
- --bf-navigation-brand-title-optical-offset-block: 0rem;
991
+ --bf-navigation-brand-line-center-block: calc(var(--bf-top-navigation-logo-tag-block-size) - var(--bf-top-navigation-logo-icon-bottom-offset) - (var(--bf-top-navigation-logo-icon-size) / 2));
992
+ --bf-navigation-brand-block-size: calc(var(--bf-navigation-brand-line-center-block) * 2);
985
993
  --bf-icon-size-default: 1rem;
986
994
  --bf-icon-size-medium: 2.5rem;
987
995
  --bf-icon-size-large: 4rem;
@@ -991,6 +999,7 @@ html.u-baseline-grid::after {
991
999
  --bf-leading-icon-gap: var(--bf-leading-mark-gap);
992
1000
  --bf-leading-icon-offset: var(--bf-single-line-row-visual-offset);
993
1001
  --bf-ui-chip-padding-inline: var(--bf-component-inline-inset-field);
1002
+ --bf-ui-chip-radius: 999rem;
994
1003
  --bf-ui-badge-padding-inline: calc(var(--bf-body-line-height, 1.5rem) * 0.25);
995
1004
  --bf-ui-badge-overhang: calc(var(--bf-ui-badge-padding-inline) * -0.75);
996
1005
  --bf-grid-max-inline-size: var(--bf-content-max-width);
@@ -1293,10 +1302,33 @@ html.u-baseline-grid::after {
1293
1302
  padding-inline: var(--bf-component-inline-inset-field);
1294
1303
  }
1295
1304
 
1296
- :where(.bf-theme) :where(input[type='color'].bf-color-input) {
1305
+ :where(.bf-theme) :where(.bf-color-control) {
1306
+ display: grid;
1307
+ grid-template-areas: "color-control";
1297
1308
  inline-size: 4rem;
1298
- min-block-size: var(--bf-control-box-size);
1299
- padding: calc(var(--bf-baseline) * 0.5);
1309
+ }
1310
+
1311
+ /* Native color inputs do not expose a body-text line box. This invisible
1312
+ metric strut gives their wrapper the same natural padding/border/margin
1313
+ construction as every textual control, including under browser zoom. */
1314
+ :where(.bf-theme) :where(.bf-color-control)::before {
1315
+ border-block: var(--bf-border-width) solid transparent;
1316
+ content: "\00a0";
1317
+ grid-area: color-control;
1318
+ line-height: var(--bf-body-line-height);
1319
+ margin-bottom: var(--bf-single-line-row-margin-block-end);
1320
+ padding-block: var(--bf-single-line-row-padding-block);
1321
+ visibility: hidden;
1322
+ }
1323
+
1324
+ :where(.bf-theme) :where(.bf-color-control) > :where(input[type='color'].bf-color-input) {
1325
+ align-self: stretch;
1326
+ block-size: auto;
1327
+ grid-area: color-control;
1328
+ inline-size: 100%;
1329
+ margin-bottom: var(--bf-single-line-row-margin-block-end);
1330
+ min-block-size: 0;
1331
+ padding: var(--bf-border-width);
1300
1332
  }
1301
1333
 
1302
1334
  :where(.bf-theme) :where(.bf-input, input[type='text'], input[type='number'], input[type='search'], input[type='password'], input[type='email'], input[type='url'], textarea, select):hover {
@@ -1337,13 +1369,12 @@ html.u-baseline-grid::after {
1337
1369
  line-height: var(--bf-body-line-height, 1.5rem);
1338
1370
  background: transparent;
1339
1371
  border: 0 solid transparent;
1340
- border-bottom: var(--bf-border-width) solid var(--bf-color-border-default);
1341
- border-top: var(--bf-border-width) solid transparent;
1372
+ box-shadow: inset 0 calc(var(--bf-border-width) * -1) 0 var(--bf-color-border-default);
1342
1373
  color: var(--bf-color-text-default);
1343
1374
  margin-bottom: calc(0rem + mod(calc(var(--bf-baseline) - mod(calc(var(--bf-body-line-height, 1.5rem) + (var(--bf-input-block-padding) * 2)), var(--bf-baseline))), var(--bf-baseline)));
1344
1375
  max-inline-size: 100%;
1345
1376
  min-inline-size: 0;
1346
- padding-block: max(0rem, calc(var(--bf-input-block-padding) - var(--bf-border-width)));
1377
+ padding-block: 0;
1347
1378
  padding-inline: 0;
1348
1379
  width: 100%;
1349
1380
  }
@@ -1361,8 +1392,8 @@ html.u-baseline-grid::after {
1361
1392
  color: var(--bf-color-text-default);
1362
1393
  cursor: pointer;
1363
1394
  margin-inline-end: var(--bf-field-gap);
1364
- min-block-size: var(--bf-control-box-size-compact);
1365
- padding-block: max(0rem, calc(var(--bf-control-block-padding-compact) - var(--bf-border-width)));
1395
+ min-block-size: 0;
1396
+ padding-block: var(--bf-single-line-row-padding-block);
1366
1397
  padding-inline: var(--bf-control-inline-padding-action-bordered);
1367
1398
  }
1368
1399
 
@@ -1722,6 +1753,15 @@ html.u-baseline-grid::after {
1722
1753
  padding: 0;
1723
1754
  }
1724
1755
 
1756
+ /* A composite slider's numeric field owns the shared occupied row. Stretching
1757
+ the track within that real sibling height avoids a second nominal-height
1758
+ calculation that can diverge when rem borders are rasterised under zoom. */
1759
+ :where(.bf-theme) :where(.bf-slider:not(.is-stacked)):not(:where(.bf-field.is-range.is-stacked) :where(.bf-slider)) > :where(input[type='range']) {
1760
+ align-self: stretch;
1761
+ block-size: auto;
1762
+ margin-block: 0;
1763
+ }
1764
+
1725
1765
  :where(.bf-theme) :where(input[type='range']):focus:not(:focus-visible) {
1726
1766
  outline: none;
1727
1767
  }
@@ -4055,10 +4095,6 @@ html.u-baseline-grid::after {
4055
4095
  inline-size: 100%;
4056
4096
  }
4057
4097
 
4058
- :where(.bf-theme) :where(.bf-panel-header.is-navigation-brand) :where(.bf-top-navigation-logo-title) {
4059
- transform: translateY(var(--bf-navigation-brand-title-optical-offset-block));
4060
- }
4061
-
4062
4098
  :where(.bf-theme) :where(.bf-panel-header) > :where(.bf-panel-title) {
4063
4099
  min-inline-size: 0;
4064
4100
  }
@@ -5675,10 +5711,6 @@ html.u-baseline-grid::after {
5675
5711
  border-block-end-color: var(--bf-color-border-low-contrast);
5676
5712
  }
5677
5713
 
5678
- :where(.bf-theme) :where(tbody tr:has(.bf-status-label) > td) {
5679
- padding-block: calc((var(--bf-baseline) - var(--bf-table-row-border-size)) / 2);
5680
- }
5681
-
5682
5714
  :where(.bf-theme) :where(tbody tr:hover td) {
5683
5715
  background: color-mix(in srgb, var(--bf-color-background-hover) 68%, transparent);
5684
5716
  }
@@ -5699,7 +5731,7 @@ html.u-baseline-grid::after {
5699
5731
  align-items: baseline;
5700
5732
  background-color: var(--bf-ui-chip-background);
5701
5733
  border: var(--bf-border-width) solid var(--bf-ui-chip-border);
5702
- border-radius: 1rem;
5734
+ border-radius: var(--bf-ui-chip-radius);
5703
5735
  color: var(--bf-color-text-default);
5704
5736
  display: inline-flex;
5705
5737
  gap: 0;
@@ -5888,6 +5920,38 @@ html.u-baseline-grid::after {
5888
5920
  --bf-ui-status-color: var(--bf-color-button-negative-text);
5889
5921
  }
5890
5922
 
5923
+ /* Nested auxiliary surfaces fit a body-sized flex/grid host instead of
5924
+ carrying a second standalone occupied-row contract. This modifier is
5925
+ explicit so component density never changes merely because of ancestry. */
5926
+ :where(.bf-theme) :where(.bf-chip.is-nested, .bf-status-label.is-nested) {
5927
+ line-height: var(--bf-nested-auxiliary-line-height);
5928
+ margin-block: 0;
5929
+ padding-block: var(--bf-nested-auxiliary-padding-block);
5930
+ }
5931
+
5932
+ :where(.bf-theme) :where(.bf-chip.is-nested) {
5933
+ border: 0;
5934
+ box-shadow: inset 0 0 0 var(--bf-border-width) var(--bf-ui-chip-border);
5935
+ }
5936
+
5937
+ :where(.bf-theme) :where(.bf-chip.is-nested:hover) {
5938
+ box-shadow: inset 0 0 0 var(--bf-border-width) var(--bf-ui-chip-border-hover);
5939
+ }
5940
+
5941
+ :where(.bf-theme) :where(.bf-chip.is-nested:is(:active, [aria-pressed='true'], .is-selected)) {
5942
+ box-shadow: inset 0 0 0 var(--bf-border-width) var(--bf-ui-chip-border-active);
5943
+ }
5944
+
5945
+ :where(.bf-theme) :where(.bf-status-label.is-nested) {
5946
+ border-block-width: 0;
5947
+ }
5948
+
5949
+ :where(.bf-theme) :where(.bf-badge.is-nested) {
5950
+ align-self: center;
5951
+ line-height: var(--bf-nested-auxiliary-line-height);
5952
+ vertical-align: middle;
5953
+ }
5954
+
5891
5955
 
5892
5956
  :where(.bf-theme) :where(.bf-chip-dismiss, .bf-search-box-reset, .bf-search-and-filter-clear) {
5893
5957
  appearance: none;
@@ -6332,6 +6396,7 @@ html.u-baseline-grid::after {
6332
6396
  --bf-side-navigation-disclosure-inset: max(0rem, calc(var(--bf-component-inline-inset-continuation) - var(--bf-disclosure-icon-inline-size) - var(--bf-disclosure-gap)));
6333
6397
  --bf-side-navigation-depth-step: var(--bf-space-2);
6334
6398
  --bf-side-navigation-group-gap: 1.5rem;
6399
+ --bf-side-navigation-heading-list-gap: 0.5rem;
6335
6400
  color: var(--bf-color-text-inactive);
6336
6401
  display: block;
6337
6402
  inline-size: 100%;
@@ -6344,11 +6409,31 @@ html.u-baseline-grid::after {
6344
6409
  }
6345
6410
 
6346
6411
  :where(.bf-theme) :where(.bf-side-navigation-group) {
6412
+ display: grid;
6413
+ gap: var(--bf-side-navigation-heading-list-gap);
6414
+ min-inline-size: 0;
6415
+ }
6416
+
6417
+ /* Keep the divider and heading as one tight header. The group owns only the
6418
+ larger transition from that header to its list, so the compensated rule
6419
+ cannot change the heading/list phase. */
6420
+ :where(.bf-theme) :where(.bf-side-navigation-group-header) {
6347
6421
  display: grid;
6348
6422
  gap: 0rem;
6349
6423
  min-inline-size: 0;
6350
6424
  }
6351
6425
 
6426
+ :where(.bf-theme) :where(.bf-side-navigation-group-header) > hr {
6427
+ inline-size: auto;
6428
+ margin-inline: var(--bf-side-navigation-content-inset) 0;
6429
+ }
6430
+
6431
+ /* A single-line group heading occupies four baselines. min-block-size keeps
6432
+ that phase exact while still allowing a long heading to wrap and grow. */
6433
+ :where(.bf-theme) :where(.bf-side-navigation-group-header) > :where(.bf-side-navigation-heading) {
6434
+ min-block-size: calc((var(--bf-baseline) * 4) - var(--bf-body-margin-bottom));
6435
+ }
6436
+
6352
6437
  :where(.bf-theme) :where(.bf-side-navigation-drawer) {
6353
6438
  background: var(--bf-color-background-default);
6354
6439
  bottom: 0;
@@ -6477,6 +6562,7 @@ html.u-baseline-grid::after {
6477
6562
 
6478
6563
  :where(.bf-theme) :where(.bf-side-navigation-list) {
6479
6564
  display: grid;
6565
+ grid-auto-rows: var(--bf-single-line-row-block-size);
6480
6566
  list-style: none;
6481
6567
  margin: 0;
6482
6568
  padding: 0;
@@ -6495,6 +6581,7 @@ html.u-baseline-grid::after {
6495
6581
  font-weight: var(--bf-body-font-weight, 400);
6496
6582
  line-height: var(--bf-body-line-height, 1.5rem);
6497
6583
  align-items: center;
6584
+ align-self: start;
6498
6585
  background: transparent;
6499
6586
  border: 0;
6500
6587
  border-block: var(--bf-border-width) solid transparent;
@@ -7232,7 +7319,8 @@ html.u-baseline-grid::after {
7232
7319
  display: block;
7233
7320
  margin: 0;
7234
7321
  overflow: hidden;
7235
- padding-block: var(--bf-control-block-padding-compact);
7322
+ padding-block-end: var(--bf-single-line-row-in-box-padding-block-end);
7323
+ padding-block-start: var(--bf-single-line-row-in-box-padding-block-start);
7236
7324
  padding-inline: var(--bf-component-inline-inset-action);
7237
7325
  text-align: left;
7238
7326
  text-decoration: none;
@@ -8321,13 +8409,11 @@ html.u-baseline-grid::after {
8321
8409
  line-height: var(--bf-top-navigation-logo-title-line-height, var(--bf-body-line-height, 1.5));
8322
8410
  overflow: visible;
8323
8411
  overflow-wrap: anywhere;
8324
- /* The first title line and the 1rem mark share the mark's fixed centre:
8325
- * tag block-end minus the 0.375rem inset minus half the mark. Symmetric title
8326
- * padding keeps the occupied row stable across all four type-density tiers. */
8412
+ /* The first title line and the 1rem mark share the public brand-line centre.
8413
+ * The derived brand block is twice that fixed centre, so the orange tag can
8414
+ * extend upward without changing the title or adjacent-header baseline. */
8327
8415
  padding-block: calc(
8328
- var(--bf-top-navigation-logo-tag-block-size)
8329
- - var(--bf-top-navigation-logo-icon-bottom-offset)
8330
- - (var(--bf-top-navigation-logo-icon-size) / 2)
8416
+ var(--bf-navigation-brand-line-center-block)
8331
8417
  - (var(--bf-top-navigation-logo-title-line-height, var(--bf-body-line-height, 1.5rem)) / 2)
8332
8418
  );
8333
8419
  text-overflow: clip;