@helixui/library 3.2.0-next.98 → 3.3.0-next.111

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (146) hide show
  1. package/custom-elements.json +30 -18
  2. package/dist/components/hx-alert/hx-alert.styles.d.ts.map +1 -1
  3. package/dist/components/hx-alert/index.js +1 -1
  4. package/dist/components/hx-banner/hx-banner.styles.d.ts.map +1 -1
  5. package/dist/components/hx-banner/index.js +1 -1
  6. package/dist/components/hx-button/hx-button.d.ts +8 -6
  7. package/dist/components/hx-button/hx-button.d.ts.map +1 -1
  8. package/dist/components/hx-button/hx-button.styles.d.ts.map +1 -1
  9. package/dist/components/hx-button/index.js +1 -1
  10. package/dist/components/hx-checkbox/hx-checkbox.styles.d.ts.map +1 -1
  11. package/dist/components/hx-checkbox/index.js +1 -1
  12. package/dist/components/hx-code-snippet/hx-code-snippet.styles.d.ts.map +1 -1
  13. package/dist/components/hx-code-snippet/index.js +1 -1
  14. package/dist/components/hx-combobox/hx-combobox.styles.d.ts.map +1 -1
  15. package/dist/components/hx-combobox/index.js +1 -1
  16. package/dist/components/hx-date-picker/hx-date-picker.styles.d.ts.map +1 -1
  17. package/dist/components/hx-date-picker/index.js +1 -1
  18. package/dist/components/hx-link/hx-link.styles.d.ts.map +1 -1
  19. package/dist/components/hx-link/index.js +1 -1
  20. package/dist/components/hx-list/hx-list-item.styles.d.ts.map +1 -1
  21. package/dist/components/hx-list/index.js +1 -1
  22. package/dist/components/hx-radio-group/hx-radio.styles.d.ts.map +1 -1
  23. package/dist/components/hx-radio-group/index.js +1 -1
  24. package/dist/components/hx-rating/hx-rating.styles.d.ts.map +1 -1
  25. package/dist/components/hx-rating/index.js +1 -1
  26. package/dist/components/hx-select/hx-select.styles.d.ts.map +1 -1
  27. package/dist/components/hx-select/index.js +1 -1
  28. package/dist/components/hx-side-nav/hx-side-nav.d.ts +4 -3
  29. package/dist/components/hx-side-nav/hx-side-nav.d.ts.map +1 -1
  30. package/dist/components/hx-side-nav/hx-side-nav.styles.d.ts.map +1 -1
  31. package/dist/components/hx-side-nav/index.js +1 -1
  32. package/dist/components/hx-slider/hx-slider.styles.d.ts.map +1 -1
  33. package/dist/components/hx-slider/index.js +1 -1
  34. package/dist/components/hx-split-button/hx-split-button.styles.d.ts.map +1 -1
  35. package/dist/components/hx-split-button/index.js +1 -1
  36. package/dist/components/hx-switch/hx-switch.styles.d.ts.map +1 -1
  37. package/dist/components/hx-switch/index.js +1 -1
  38. package/dist/components/hx-tabs/hx-tab-panel.styles.d.ts.map +1 -1
  39. package/dist/components/hx-tabs/hx-tab.styles.d.ts.map +1 -1
  40. package/dist/components/hx-tabs/index.js +1 -1
  41. package/dist/components/hx-text-input/hx-text-input.styles.d.ts.map +1 -1
  42. package/dist/components/hx-text-input/index.js +1 -1
  43. package/dist/components/hx-textarea/hx-textarea.styles.d.ts.map +1 -1
  44. package/dist/components/hx-textarea/index.js +1 -1
  45. package/dist/components/hx-theme/hx-theme.d.ts +14 -2
  46. package/dist/components/hx-theme/hx-theme.d.ts.map +1 -1
  47. package/dist/components/hx-theme/index.js +1 -1
  48. package/dist/components/hx-toggle-button/hx-toggle-button.styles.d.ts.map +1 -1
  49. package/dist/components/hx-toggle-button/index.js +1 -1
  50. package/dist/components/hx-tree-view/hx-tree-view.styles.d.ts.map +1 -1
  51. package/dist/components/hx-tree-view/index.js +1 -1
  52. package/dist/css/helix-all.css +122 -120
  53. package/dist/css/helix-core.css +53 -23
  54. package/dist/css/helix-data.css +20 -6
  55. package/dist/css/helix-feedback.css +3 -12
  56. package/dist/css/helix-forms.css +16 -63
  57. package/dist/css/helix-navigation.css +28 -8
  58. package/dist/css/helix-tokens.css +8 -8
  59. package/dist/css/helix-utility.css +2 -8
  60. package/dist/css/hx-alert.css +1 -4
  61. package/dist/css/hx-banner.css +2 -8
  62. package/dist/css/hx-button.css +52 -19
  63. package/dist/css/hx-checkbox.css +1 -4
  64. package/dist/css/hx-code-snippet.css +20 -6
  65. package/dist/css/hx-combobox.css +2 -8
  66. package/dist/css/hx-date-picker.css +5 -21
  67. package/dist/css/hx-link.css +1 -4
  68. package/dist/css/hx-rating.css +1 -2
  69. package/dist/css/hx-select.css +1 -4
  70. package/dist/css/hx-side-nav.css +27 -6
  71. package/dist/css/hx-slider.css +1 -4
  72. package/dist/css/hx-split-button.css +2 -8
  73. package/dist/css/hx-switch.css +1 -4
  74. package/dist/css/hx-text-input.css +2 -8
  75. package/dist/css/hx-textarea.css +1 -4
  76. package/dist/css/hx-toggle-button.css +1 -4
  77. package/dist/css/hx-tree-view.css +1 -2
  78. package/dist/css/index.css +1 -1
  79. package/dist/css/manifest.json +20 -18
  80. package/dist/index.js +22 -22
  81. package/dist/shared/{hx-alert-C597yHpD.js → hx-alert-CLn7CstP.js} +2 -5
  82. package/dist/shared/hx-alert-CLn7CstP.js.map +1 -0
  83. package/dist/shared/{hx-banner-Cxd7eFUP.js → hx-banner-D3DzpfcP.js} +7 -13
  84. package/dist/shared/hx-banner-D3DzpfcP.js.map +1 -0
  85. package/dist/shared/{hx-button-9OUjJnk7.js → hx-button-DPY6SPVT.js} +58 -25
  86. package/dist/shared/hx-button-DPY6SPVT.js.map +1 -0
  87. package/dist/shared/{hx-checkbox-DBD-gMoz.js → hx-checkbox-D7xma9YH.js} +6 -9
  88. package/dist/shared/hx-checkbox-D7xma9YH.js.map +1 -0
  89. package/dist/shared/{hx-code-snippet-CJrFeyz0.js → hx-code-snippet-fVV3Z2DZ.js} +55 -41
  90. package/dist/shared/hx-code-snippet-fVV3Z2DZ.js.map +1 -0
  91. package/dist/shared/{hx-combobox-ClhNRAS5.js → hx-combobox-DDzqNKEW.js} +6 -12
  92. package/dist/shared/hx-combobox-DDzqNKEW.js.map +1 -0
  93. package/dist/shared/{hx-date-picker-BJm7Yrda.js → hx-date-picker-2iRG1p74.js} +12 -28
  94. package/dist/shared/hx-date-picker-2iRG1p74.js.map +1 -0
  95. package/dist/shared/{hx-link-9Ig2DW6L.js → hx-link-C-O6vq0Q.js} +2 -5
  96. package/dist/shared/hx-link-C-O6vq0Q.js.map +1 -0
  97. package/dist/shared/{hx-list-CkphGi9T.js → hx-list-MyEhh8c7.js} +3 -5
  98. package/dist/shared/hx-list-MyEhh8c7.js.map +1 -0
  99. package/dist/shared/{hx-nav-item-DH2tXcj1.js → hx-nav-item-xqRPOCWX.js} +58 -37
  100. package/dist/shared/hx-nav-item-xqRPOCWX.js.map +1 -0
  101. package/dist/shared/{hx-radio-dFjUAost.js → hx-radio-CJvNU2yP.js} +2 -5
  102. package/dist/shared/{hx-radio-dFjUAost.js.map → hx-radio-CJvNU2yP.js.map} +1 -1
  103. package/dist/shared/{hx-rating-CGtsejNf.js → hx-rating-C3QP53k9.js} +2 -3
  104. package/dist/shared/hx-rating-C3QP53k9.js.map +1 -0
  105. package/dist/shared/{hx-select-Bf4usFts.js → hx-select-C8fEHQhC.js} +2 -5
  106. package/dist/shared/hx-select-C8fEHQhC.js.map +1 -0
  107. package/dist/shared/{hx-slider-m0aEClH1.js → hx-slider-Blmv_rwS.js} +23 -26
  108. package/dist/shared/hx-slider-Blmv_rwS.js.map +1 -0
  109. package/dist/shared/{hx-split-button-BxDFfx4D.js → hx-split-button-Djnc5Aeg.js} +3 -9
  110. package/dist/shared/hx-split-button-Djnc5Aeg.js.map +1 -0
  111. package/dist/shared/{hx-switch-DvAW4YY-.js → hx-switch-BrZFaRue.js} +6 -9
  112. package/dist/shared/hx-switch-BrZFaRue.js.map +1 -0
  113. package/dist/shared/{hx-tab-panel-SWOEHuJc.js → hx-tab-panel-DspCrKqo.js} +3 -9
  114. package/dist/shared/{hx-tab-panel-SWOEHuJc.js.map → hx-tab-panel-DspCrKqo.js.map} +1 -1
  115. package/dist/shared/{hx-text-input-Bn7Gn8CI.js → hx-text-input-D6FlOZM-.js} +3 -9
  116. package/dist/shared/hx-text-input-D6FlOZM-.js.map +1 -0
  117. package/dist/shared/{hx-textarea-Jx1xnhgv.js → hx-textarea-CNG590KY.js} +6 -9
  118. package/dist/shared/hx-textarea-CNG590KY.js.map +1 -0
  119. package/dist/shared/{hx-theme-BiyQ7UUK.js → hx-theme-BsefFWTO.js} +83 -113
  120. package/dist/shared/hx-theme-BsefFWTO.js.map +1 -0
  121. package/dist/shared/{hx-toggle-button-DPAIh_Xo.js → hx-toggle-button-iLiYrMbD.js} +2 -5
  122. package/dist/shared/hx-toggle-button-iLiYrMbD.js.map +1 -0
  123. package/dist/shared/{hx-tree-item-Dt0Ozqyr.js → hx-tree-item-C2CiWuDE.js} +2 -3
  124. package/dist/shared/hx-tree-item-C2CiWuDE.js.map +1 -0
  125. package/figma-inventory.json +34 -19
  126. package/package.json +2 -2
  127. package/dist/shared/hx-alert-C597yHpD.js.map +0 -1
  128. package/dist/shared/hx-banner-Cxd7eFUP.js.map +0 -1
  129. package/dist/shared/hx-button-9OUjJnk7.js.map +0 -1
  130. package/dist/shared/hx-checkbox-DBD-gMoz.js.map +0 -1
  131. package/dist/shared/hx-code-snippet-CJrFeyz0.js.map +0 -1
  132. package/dist/shared/hx-combobox-ClhNRAS5.js.map +0 -1
  133. package/dist/shared/hx-date-picker-BJm7Yrda.js.map +0 -1
  134. package/dist/shared/hx-link-9Ig2DW6L.js.map +0 -1
  135. package/dist/shared/hx-list-CkphGi9T.js.map +0 -1
  136. package/dist/shared/hx-nav-item-DH2tXcj1.js.map +0 -1
  137. package/dist/shared/hx-rating-CGtsejNf.js.map +0 -1
  138. package/dist/shared/hx-select-Bf4usFts.js.map +0 -1
  139. package/dist/shared/hx-slider-m0aEClH1.js.map +0 -1
  140. package/dist/shared/hx-split-button-BxDFfx4D.js.map +0 -1
  141. package/dist/shared/hx-switch-DvAW4YY-.js.map +0 -1
  142. package/dist/shared/hx-text-input-Bn7Gn8CI.js.map +0 -1
  143. package/dist/shared/hx-textarea-Jx1xnhgv.js.map +0 -1
  144. package/dist/shared/hx-theme-BiyQ7UUK.js.map +0 -1
  145. package/dist/shared/hx-toggle-button-DPAIh_Xo.js.map +0 -1
  146. package/dist/shared/hx-tree-item-Dt0Ozqyr.js.map +0 -1
@@ -309,10 +309,7 @@
309
309
 
310
310
  .alert__close-button:focus-visible {
311
311
  outline: var(--hx-focus-ring-width, 2px) solid
312
- var(
313
- --hx-alert-close-btn-focus-ring-color,
314
- var(--hx-focus-ring-color, var(--hx-color-primary-600, #0f7078))
315
- );
312
+ var(--hx-alert-close-btn-focus-ring-color, var(--hx-focus-ring-color, #0f7078));
316
313
  outline-offset: var(--hx-focus-ring-offset, 2px);
317
314
  opacity: 1;
318
315
  }
@@ -832,10 +829,7 @@
832
829
 
833
830
  .banner__action:focus-visible {
834
831
  outline: var(--hx-focus-ring-width, 2px) solid
835
- var(
836
- --hx-banner-action-focus-ring-color,
837
- var(--hx-focus-ring-color, var(--hx-color-primary-600, #0f7078))
838
- );
832
+ var(--hx-banner-action-focus-ring-color, var(--hx-focus-ring-color, #0f7078));
839
833
  outline-offset: var(--hx-focus-ring-offset, 2px);
840
834
  border-radius: var(--hx-border-radius-sm, 0.25rem);
841
835
  }
@@ -876,10 +870,7 @@
876
870
 
877
871
  .banner__close-button:focus-visible {
878
872
  outline: var(--hx-focus-ring-width, 2px) solid
879
- var(
880
- --hx-banner-close-btn-focus-ring-color,
881
- var(--hx-focus-ring-color, var(--hx-color-primary-600, #0f7078))
882
- );
873
+ var(--hx-banner-close-btn-focus-ring-color, var(--hx-focus-ring-color, #0f7078));
883
874
  outline-offset: var(--hx-focus-ring-offset, 2px);
884
875
  opacity: 1;
885
876
  }
@@ -1255,15 +1246,16 @@
1255
1246
 
1256
1247
  /* ─── Inverted Mode ─── */
1257
1248
 
1258
- /* Inline-fallback contract for --hx-color-border-on-dark-* in this section:
1249
+ /* Inline-fallback contract for the on-dark-* tokens in this section:
1259
1250
  the literal rgba(255, 255, 255, 0.X) arms are a LIGHT-MODE-only last
1260
1251
  resort (cold-start, CSS-not-loaded). At runtime, hx-theme injects
1261
- dark.color.border.on-dark-* as overlay-black-* so dark-mode inverted
1262
- buttons stay visible on the now-light surface.inverse (#EBEEE9). The
1263
- inline white overlays would render invisible (≈1.1:1) on a light surface,
1264
- but they never paint when the theme is mounted. If a future change moves
1265
- these into a context where hx-theme is not guaranteed, replace with
1266
- mode-aware tokens. */
1252
+ the dark.* override (overlay-black-* for the strong border and the
1253
+ surface.on-dark-overlay-* fills) so dark-mode inverted buttons stay
1254
+ visible on the now-light surface.inverse (#EBEEE9). The inline white
1255
+ overlays would render invisible (≈1.1:1) on a light surface, but
1256
+ they never paint when the theme is mounted. If a future change
1257
+ moves these into a context where hx-theme is not guaranteed,
1258
+ replace with mode-aware tokens. */
1267
1259
 
1268
1260
  /* Override text color and filter-based hover/active for all variants */
1269
1261
  :host([inverted]) .button {
@@ -1281,8 +1273,12 @@
1281
1273
 
1282
1274
  :host([inverted]) .button:focus-visible {
1283
1275
  /* WCAG 1.4.11: focus indicator needs ≥3:1 against adjacent colors.
1284
- border-on-dark-default (overlay-white-30) ≈ 2.7:1 on neutral-900 — fails.
1285
- border-on-dark-strong (overlay-white-70) 5:1 passes. */
1276
+ border-on-dark-strong (overlay-white-70) ≈ 5:1 on neutral-900 — passes.
1277
+ The lower-alpha siblings used to live in border.* but were sub-3:1
1278
+ against any plausible surface and could not honour a border contract;
1279
+ they're now surface.on-dark-overlay-{default,subtle} (translucent
1280
+ fills, not borders) and used elsewhere in this file. See
1281
+ tokens.json color.surface.on-dark-overlay-* for canonical ratios. */
1286
1282
  outline-color: var(
1287
1283
  --hx-button-inverted-focus-ring-color,
1288
1284
  var(--hx-color-border-on-dark-strong, rgba(255, 255, 255, 0.7))
@@ -1293,8 +1289,16 @@
1293
1289
  so dark mode can flip the fill to primary-600. surface.inverse becomes light
1294
1290
  (#EBEEE9) in dark mode; primary-500 on #EBEEE9 = 2.94:1 (sub-3:1 UI floor
1295
1291
  fail for the inverted-button boundary). primary-600 on #EBEEE9 = 4.97:1
1296
- (AA pass). Light mode tracks action.primary.bg (primary-500, 5.20:1 on
1297
- dark surface.inverse). */
1292
+ (AA pass). Light mode tracks action.primary.bg-inverted-rest's base value
1293
+ (primary-500, 5.20:1 on dark surface.inverse).
1294
+
1295
+ Override path note (codex round-11): this binds --hx-button-bg directly,
1296
+ matching the cascade convention every other .button--{variant} rule uses
1297
+ (light primary at line 89, danger at 120, secondary, tertiary, ghost). The
1298
+ consumer override path for inverted-primary rest is
1299
+ --hx-color-action-primary-bg-inverted-rest, NOT --hx-button-bg — the same
1300
+ pattern as light primary (consumers override --hx-color-action-primary-bg).
1301
+ Pinned by dark-mode-resolution.test.ts:185-197 across both modes. */
1298
1302
  :host([inverted]) .button--primary {
1299
1303
  --hx-button-bg: var(--hx-color-action-primary-bg-inverted-rest, #429797);
1300
1304
  }
@@ -1346,20 +1350,34 @@
1346
1350
  --hx-button-border-color: var(--hx-color-border-on-dark-strong, rgba(255, 255, 255, 0.7));
1347
1351
  }
1348
1352
 
1353
+ /* Inverted overlay fills read both names so consumer overrides reach paint
1354
+ regardless of which token they target: the deprecated --hx-color-border-on-dark-*
1355
+ names (3.2.0/3.2.1 public API, scheduled for removal in 4.0.0) and the canonical
1356
+ --hx-color-surface-on-dark-overlay-* names (round-8 rename). Deprecated name
1357
+ wins when set; otherwise resolves through the canonical alias chain. */
1349
1358
  :host([inverted]) .button--secondary:hover {
1350
- --hx-button-bg: var(--hx-color-border-on-dark-default, rgba(255, 255, 255, 0.3));
1359
+ --hx-button-bg: var(
1360
+ --hx-color-border-on-dark-default,
1361
+ var(--hx-color-surface-on-dark-overlay-default, rgba(255, 255, 255, 0.3))
1362
+ );
1351
1363
  }
1352
1364
 
1353
- /* Tertiary inverted — resting at subtle (10%) lifts to default (30%) on hover
1354
- so the runtime hover delta is visually distinct, not collapsed onto a
1355
- single token. */
1365
+ /* Tertiary inverted — resting at the subtle overlay (10%) lifts to the default
1366
+ overlay (30%) on hover so the runtime hover delta is visually distinct, not
1367
+ collapsed onto a single token. */
1356
1368
  :host([inverted]) .button--tertiary {
1357
- --hx-button-bg: var(--hx-color-border-on-dark-subtle, rgba(255, 255, 255, 0.1));
1369
+ --hx-button-bg: var(
1370
+ --hx-color-border-on-dark-subtle,
1371
+ var(--hx-color-surface-on-dark-overlay-subtle, rgba(255, 255, 255, 0.1))
1372
+ );
1358
1373
  --hx-button-border-color: transparent;
1359
1374
  }
1360
1375
 
1361
1376
  :host([inverted]) .button--tertiary:hover {
1362
- --hx-button-bg: var(--hx-color-border-on-dark-default, rgba(255, 255, 255, 0.3));
1377
+ --hx-button-bg: var(
1378
+ --hx-color-border-on-dark-default,
1379
+ var(--hx-color-surface-on-dark-overlay-default, rgba(255, 255, 255, 0.3))
1380
+ );
1363
1381
  }
1364
1382
 
1365
1383
  /* Ghost inverted — transparent base, translucent hover bg */
@@ -1371,7 +1389,10 @@
1371
1389
  :host([inverted]) .button--ghost:hover {
1372
1390
  --hx-button-bg: var(
1373
1391
  --hx-button-inverted-ghost-hover-bg,
1374
- var(--hx-color-border-on-dark-default, rgba(255, 255, 255, 0.3))
1392
+ var(
1393
+ --hx-color-border-on-dark-default,
1394
+ var(--hx-color-surface-on-dark-overlay-default, rgba(255, 255, 255, 0.3))
1395
+ )
1375
1396
  );
1376
1397
  }
1377
1398
 
@@ -1381,7 +1402,10 @@
1381
1402
  }
1382
1403
 
1383
1404
  :host([inverted]) .button--outline:hover {
1384
- --hx-button-bg: var(--hx-color-border-on-dark-default, rgba(255, 255, 255, 0.3));
1405
+ --hx-button-bg: var(
1406
+ --hx-color-border-on-dark-default,
1407
+ var(--hx-color-surface-on-dark-overlay-default, rgba(255, 255, 255, 0.3))
1408
+ );
1385
1409
  }
1386
1410
 
1387
1411
  /* ─── Prefix / Suffix / Label ─── */
@@ -2058,10 +2082,7 @@
2058
2082
 
2059
2083
  .checkbox__input:focus-visible ~ .checkbox__box {
2060
2084
  outline: var(--hx-checkbox-focus-ring-width, var(--hx-focus-ring-width, 2px)) solid
2061
- var(
2062
- --hx-checkbox-focus-ring-color,
2063
- var(--hx-focus-ring-color, var(--hx-color-primary-600, #0f7078))
2064
- );
2085
+ var(--hx-checkbox-focus-ring-color, var(--hx-focus-ring-color, #0f7078));
2065
2086
  outline-offset: var(--hx-checkbox-focus-ring-offset, var(--hx-focus-ring-offset, 2px));
2066
2087
  }
2067
2088
 
@@ -2727,7 +2748,8 @@
2727
2748
  min-width: var(--hx-touch-target-min, 2.75rem);
2728
2749
  min-height: var(--hx-touch-target-min, 2.75rem);
2729
2750
  padding: var(--hx-space-1, 0.25rem) var(--hx-space-2, 0.5rem);
2730
- border: var(--hx-border-width-thin, 1px) solid var(--hx-color-border-strong, #66787b);
2751
+ border: var(--hx-border-width-thin, 1px) solid
2752
+ var(--hx-color-border-on-dark-strong, rgba(255, 255, 255, 0.7));
2731
2753
  border-radius: var(--hx-border-radius-sm, 0.25rem);
2732
2754
  /* Copy button sits on the always-dark block snippet surface; uses inverse family for contrast on the terminal background. */
2733
2755
  background-color: var(--hx-color-surface-inverse, #0d1825);
@@ -2752,8 +2774,14 @@
2752
2774
  }
2753
2775
 
2754
2776
  .code-snippet__copy-button:focus-visible {
2755
- outline: var(--hx-focus-ring-width, 2px) solid
2756
- var(--hx-focus-ring-color, var(--hx-color-primary-600, #0f7078));
2777
+ /* Always-dark terminal surface — uses primary-400 (#6AB1B1, 7.27:1 on #0d1825)
2778
+ instead of the light-mode --hx-focus-ring-color (primary-600, 3.07:1 — razor
2779
+ above the 3:1 UI floor with no headroom). Deliberate primitive-tier consumption:
2780
+ there is no semantic focus-ring-on-dark alias today — the dark.color.focus-ring
2781
+ override at tokens.json only fires under theme=dark, but this surface is dark in
2782
+ every theme. Tracked for promotion to a semantic alias in a future token-cascade
2783
+ follow-up. */
2784
+ outline: var(--hx-focus-ring-width, 2px) solid var(--hx-color-primary-400, #6ab1b1);
2757
2785
  outline-offset: var(--hx-focus-ring-offset, 2px);
2758
2786
  }
2759
2787
 
@@ -2772,7 +2800,8 @@
2772
2800
  min-height: var(--hx-touch-target-min, 2.75rem);
2773
2801
  padding: var(--hx-space-2, 0.5rem) var(--hx-space-4, 1rem);
2774
2802
  border: none;
2775
- border-top: var(--hx-border-width-thin, 1px) solid var(--hx-color-border-strong, #66787b);
2803
+ border-top: var(--hx-border-width-thin, 1px) solid
2804
+ var(--hx-color-border-on-dark-strong, rgba(255, 255, 255, 0.7));
2776
2805
  /* Expand button is attached to the always-dark block snippet — inverse family maintains the terminal aesthetic. */
2777
2806
  background-color: var(--hx-color-surface-inverse, #0d1825);
2778
2807
  color: var(--hx-color-text-inverse, #ffffff);
@@ -2793,8 +2822,14 @@
2793
2822
  }
2794
2823
 
2795
2824
  .code-snippet__expand-button:focus-visible {
2796
- outline: var(--hx-focus-ring-width, 2px) solid
2797
- var(--hx-focus-ring-color, var(--hx-color-primary-600, #0f7078));
2825
+ /* Always-dark terminal surface — uses primary-400 (#6AB1B1, 7.27:1 on #0d1825)
2826
+ instead of the light-mode --hx-focus-ring-color (primary-600, 3.07:1 — razor
2827
+ above the 3:1 UI floor with no headroom). Deliberate primitive-tier consumption:
2828
+ there is no semantic focus-ring-on-dark alias today — the dark.color.focus-ring
2829
+ override at tokens.json only fires under theme=dark, but this surface is dark in
2830
+ every theme. Tracked for promotion to a semantic alias in a future token-cascade
2831
+ follow-up. */
2832
+ outline: var(--hx-focus-ring-width, 2px) solid var(--hx-color-primary-400, #6ab1b1);
2798
2833
  outline-offset: var(--hx-focus-ring-offset, 2px);
2799
2834
  }
2800
2835
 
@@ -3182,17 +3217,11 @@
3182
3217
  box-shadow var(--hx-transition-fast, 150ms ease);
3183
3218
  }
3184
3219
  .field__input-wrapper:focus-within {
3185
- border-color: var(
3186
- --hx-combobox-focus-ring-color,
3187
- var(--hx-focus-ring-color, var(--hx-color-primary-600, #0f7078))
3188
- );
3220
+ border-color: var(--hx-combobox-focus-ring-color, var(--hx-focus-ring-color, #0f7078));
3189
3221
  box-shadow: 0 0 0 var(--hx-focus-ring-width, 2px)
3190
3222
  color-mix(
3191
3223
  in srgb,
3192
- var(
3193
- --hx-combobox-focus-ring-color,
3194
- var(--hx-focus-ring-color, var(--hx-color-primary-600, #0f7078))
3195
- )
3224
+ var(--hx-combobox-focus-ring-color, var(--hx-focus-ring-color, #0f7078))
3196
3225
  calc(var(--hx-focus-ring-opacity, 0.25) * 100%),
3197
3226
  transparent
3198
3227
  );
@@ -4128,17 +4157,11 @@
4128
4157
  }
4129
4158
 
4130
4159
  .field__input-wrapper:focus-within {
4131
- border-color: var(
4132
- --hx-date-picker-focus-ring-color,
4133
- var(--hx-focus-ring-color, var(--hx-color-primary-600, #0f7078))
4134
- );
4160
+ border-color: var(--hx-date-picker-focus-ring-color, var(--hx-focus-ring-color, #0f7078));
4135
4161
  box-shadow: 0 0 0 var(--hx-focus-ring-width, 2px)
4136
4162
  color-mix(
4137
4163
  in srgb,
4138
- var(
4139
- --hx-date-picker-focus-ring-color,
4140
- var(--hx-focus-ring-color, var(--hx-color-primary-600, #0f7078))
4141
- )
4164
+ var(--hx-date-picker-focus-ring-color, var(--hx-focus-ring-color, #0f7078))
4142
4165
  calc(var(--hx-focus-ring-opacity, 0.25) * 100%),
4143
4166
  transparent
4144
4167
  );
@@ -4207,17 +4230,10 @@
4207
4230
  }
4208
4231
 
4209
4232
  .field__trigger:focus-visible {
4210
- color: var(
4211
- --hx-date-picker-focus-ring-color,
4212
- var(--hx-focus-ring-color, var(--hx-color-primary-600, #0f7078))
4213
- );
4233
+ color: var(--hx-date-picker-focus-ring-color, var(--hx-focus-ring-color, #0f7078));
4214
4234
  background-color: color-mix(
4215
4235
  in srgb,
4216
- var(
4217
- --hx-date-picker-focus-ring-color,
4218
- var(--hx-focus-ring-color, var(--hx-color-primary-600, #0f7078))
4219
- )
4220
- 8%,
4236
+ var(--hx-date-picker-focus-ring-color, var(--hx-focus-ring-color, #0f7078)) 8%,
4221
4237
  transparent
4222
4238
  );
4223
4239
  }
@@ -4314,10 +4330,7 @@
4314
4330
 
4315
4331
  :is(.calendar__nav-btn, .calendar__day):focus-visible {
4316
4332
  box-shadow: 0 0 0 var(--hx-focus-ring-width, 2px)
4317
- var(
4318
- --hx-date-picker-focus-ring-color,
4319
- var(--hx-focus-ring-color, var(--hx-color-primary-600, #0f7078))
4320
- );
4333
+ var(--hx-date-picker-focus-ring-color, var(--hx-focus-ring-color, #0f7078));
4321
4334
  z-index: 1;
4322
4335
  }
4323
4336
 
@@ -6106,10 +6119,7 @@ export const helixGridItemStyles = css`
6106
6119
 
6107
6120
  .link:focus-visible {
6108
6121
  outline: var(--hx-focus-ring-width, 2px) solid
6109
- var(
6110
- --hx-link-focus-ring-color,
6111
- var(--hx-focus-ring-color, var(--hx-color-primary-600, #0f7078))
6112
- );
6122
+ var(--hx-link-focus-ring-color, var(--hx-focus-ring-color, #0f7078));
6113
6123
  outline-offset: var(--hx-focus-ring-offset, 2px);
6114
6124
  border-radius: var(--hx-border-radius-sm, 0.25rem);
6115
6125
  }
@@ -8191,8 +8201,7 @@ export const helixGridItemStyles = css`
8191
8201
  }
8192
8202
 
8193
8203
  .symbol:focus-visible {
8194
- outline: var(--hx-focus-ring-width, 2px) solid
8195
- var(--hx-focus-ring-color, var(--hx-color-primary-600, #0f7078));
8204
+ outline: var(--hx-focus-ring-width, 2px) solid var(--hx-focus-ring-color, #0f7078);
8196
8205
  outline-offset: var(--hx-focus-ring-offset, 2px);
8197
8206
  border-radius: var(--hx-border-radius-sm, 0.25rem);
8198
8207
  }
@@ -8306,10 +8315,7 @@ export const helixGridItemStyles = css`
8306
8315
  --_border-radius: var(--hx-select-border-radius, var(--hx-border-radius-md, 0.375rem));
8307
8316
 
8308
8317
  /* Focus ring */
8309
- --_focus-ring-color: var(
8310
- --hx-select-focus-ring-color,
8311
- var(--hx-focus-ring-color, var(--hx-color-primary-600, #0f7078))
8312
- );
8318
+ --_focus-ring-color: var(--hx-select-focus-ring-color, var(--hx-focus-ring-color, #0f7078));
8313
8319
 
8314
8320
  /* Error */
8315
8321
  --_error-color: var(--hx-select-error-color, var(--hx-color-error-500, #e5493e));
@@ -8691,7 +8697,10 @@ export const helixGridItemStyles = css`
8691
8697
  transition: width var(--hx-transition-normal, 300ms) ease;
8692
8698
  overflow: hidden;
8693
8699
  border-inline-end: var(--hx-border-width-thin, 1px) solid
8694
- var(--hx-side-nav-border-color, var(--hx-color-border-strong, #66787b));
8700
+ var(
8701
+ --hx-side-nav-border-color,
8702
+ var(--hx-color-border-on-dark-strong, rgba(255, 255, 255, 0.7))
8703
+ );
8695
8704
  }
8696
8705
 
8697
8706
  /* ─── Collapsed State ─── */
@@ -8709,7 +8718,10 @@ export const helixGridItemStyles = css`
8709
8718
  flex-shrink: 0;
8710
8719
  min-height: var(--hx-space-14, 3.5rem);
8711
8720
  border-bottom: var(--hx-border-width-thin, 1px) solid
8712
- var(--hx-side-nav-border-color, var(--hx-color-border-strong, #66787b));
8721
+ var(
8722
+ --hx-side-nav-border-color,
8723
+ var(--hx-color-border-on-dark-strong, rgba(255, 255, 255, 0.7))
8724
+ );
8713
8725
  overflow: hidden;
8714
8726
  }
8715
8727
 
@@ -8736,7 +8748,10 @@ export const helixGridItemStyles = css`
8736
8748
  flex-shrink: 0;
8737
8749
  min-height: var(--hx-space-14, 3.5rem);
8738
8750
  border-top: var(--hx-border-width-thin, 1px) solid
8739
- var(--hx-side-nav-border-color, var(--hx-color-border-strong, #66787b));
8751
+ var(
8752
+ --hx-side-nav-border-color,
8753
+ var(--hx-color-border-on-dark-strong, rgba(255, 255, 255, 0.7))
8754
+ );
8740
8755
  overflow: hidden;
8741
8756
  }
8742
8757
 
@@ -8767,16 +8782,28 @@ export const helixGridItemStyles = css`
8767
8782
  }
8768
8783
 
8769
8784
  .side-nav__toggle:hover {
8785
+ /* Read both deprecated --hx-color-border-on-dark-subtle (3.2.0/3.2.1 API)
8786
+ and canonical --hx-color-surface-on-dark-overlay-subtle so consumer
8787
+ overrides on either name reach paint. Deprecated removal: 4.0.0.
8788
+ Hex fallback for browsers without color-mix(). */
8770
8789
  background-color: var(
8771
8790
  --hx-color-border-on-dark-subtle,
8772
- rgba(255, 255, 255, 0.1)
8773
- ); /* fallback for browsers without color-mix() */
8791
+ var(--hx-color-surface-on-dark-overlay-subtle, rgba(255, 255, 255, 0.1))
8792
+ );
8774
8793
  color: var(--hx-side-nav-toggle-hover-color, var(--hx-color-text-inverse, #ffffff));
8775
8794
  }
8776
8795
 
8777
8796
  @supports (color: color-mix(in srgb, red 50%, blue)) {
8797
+ /* Fold color-mix() into the same deprecated-first chain so consumer
8798
+ overrides on either token reach paint on the modern path too. */
8778
8799
  .side-nav__toggle:hover {
8779
- background-color: color-mix(in srgb, currentColor 15%, transparent);
8800
+ background-color: var(
8801
+ --hx-color-border-on-dark-subtle,
8802
+ var(
8803
+ --hx-color-surface-on-dark-overlay-subtle,
8804
+ color-mix(in srgb, currentColor 15%, transparent)
8805
+ )
8806
+ );
8780
8807
  }
8781
8808
  }
8782
8809
 
@@ -9140,10 +9167,7 @@ export const helixGridItemStyles = css`
9140
9167
  .slider__input:focus-visible ~ .slider__thumb-visual {
9141
9168
  box-shadow:
9142
9169
  0 0 0 var(--hx-focus-ring-width, 2px)
9143
- var(
9144
- --hx-slider-focus-ring-color,
9145
- var(--hx-focus-ring-color, var(--hx-color-primary-600, #0f7078))
9146
- ),
9170
+ var(--hx-slider-focus-ring-color, var(--hx-focus-ring-color, #0f7078)),
9147
9171
  var(--hx-slider-thumb-shadow, var(--hx-shadow-sm, 0 1px 2px 0 rgb(0 0 0 / 0.05)));
9148
9172
  }
9149
9173
 
@@ -9412,10 +9436,7 @@ export const helixGridItemStyles = css`
9412
9436
 
9413
9437
  .split-button__primary:focus-visible {
9414
9438
  outline: var(--hx-focus-ring-width, 2px) solid
9415
- var(
9416
- --hx-split-button-focus-ring-color,
9417
- var(--hx-focus-ring-color, var(--hx-color-primary-600, #0f7078))
9418
- );
9439
+ var(--hx-split-button-focus-ring-color, var(--hx-focus-ring-color, #0f7078));
9419
9440
  outline-offset: var(--hx-focus-ring-offset, 2px);
9420
9441
  z-index: 1;
9421
9442
  position: relative;
@@ -9457,10 +9478,7 @@ export const helixGridItemStyles = css`
9457
9478
 
9458
9479
  .split-button__trigger:focus-visible {
9459
9480
  outline: var(--hx-focus-ring-width, 2px) solid
9460
- var(
9461
- --hx-split-button-focus-ring-color,
9462
- var(--hx-focus-ring-color, var(--hx-color-primary-600, #0f7078))
9463
- );
9481
+ var(--hx-split-button-focus-ring-color, var(--hx-focus-ring-color, #0f7078));
9464
9482
  outline-offset: var(--hx-focus-ring-offset, 2px);
9465
9483
  z-index: 1;
9466
9484
  position: relative;
@@ -10528,10 +10546,7 @@ export const helixStructuredListRowStyles = css`
10528
10546
 
10529
10547
  .switch__track:focus-visible {
10530
10548
  outline: var(--hx-focus-ring-width, 2px) solid
10531
- var(
10532
- --hx-switch-focus-ring-color,
10533
- var(--hx-focus-ring-color, var(--hx-color-primary-600, #0f7078))
10534
- );
10549
+ var(--hx-switch-focus-ring-color, var(--hx-focus-ring-color, #0f7078));
10535
10550
  outline-offset: var(--hx-focus-ring-offset, 2px);
10536
10551
  }
10537
10552
 
@@ -11310,10 +11325,7 @@ export const helixTableSectionBaseStyles = css`
11310
11325
  );
11311
11326
  --_text-input-border-color-focus: var(
11312
11327
  --hx-text-input-border-color-focus,
11313
- var(
11314
- --hx-input-focus-ring-color,
11315
- var(--hx-focus-ring-color, var(--hx-color-primary-600, #0f7078))
11316
- )
11328
+ var(--hx-input-focus-ring-color, var(--hx-focus-ring-color, #0f7078))
11317
11329
  );
11318
11330
  --_text-input-border-color-invalid: var(
11319
11331
  --hx-text-input-border-color-invalid,
@@ -11339,10 +11351,7 @@ export const helixTableSectionBaseStyles = css`
11339
11351
  /* Focus ring */
11340
11352
  --_text-input-focus-ring-color: var(
11341
11353
  --hx-text-input-focus-ring-color,
11342
- var(
11343
- --hx-input-focus-ring-color,
11344
- var(--hx-focus-ring-color, var(--hx-color-primary-600, #0f7078))
11345
- )
11354
+ var(--hx-input-focus-ring-color, var(--hx-focus-ring-color, #0f7078))
11346
11355
  );
11347
11356
  --_text-input-focus-ring-width: var(
11348
11357
  --hx-text-input-focus-ring-width,
@@ -11652,10 +11661,7 @@ export const helixTableSectionBaseStyles = css`
11652
11661
  );
11653
11662
  --_textarea-border-color-focus: var(
11654
11663
  --hx-textarea-border-color-focus,
11655
- var(
11656
- --hx-input-focus-ring-color,
11657
- var(--hx-focus-ring-color, var(--hx-color-primary-600, #0f7078))
11658
- )
11664
+ var(--hx-input-focus-ring-color, var(--hx-focus-ring-color, #0f7078))
11659
11665
  );
11660
11666
  --_textarea-border-color-invalid: var(
11661
11667
  --hx-textarea-border-color-invalid,
@@ -12479,10 +12485,7 @@ export const helixToastStackStyles = css`
12479
12485
 
12480
12486
  .button:focus-visible {
12481
12487
  outline: var(--hx-focus-ring-width, 2px) solid
12482
- var(
12483
- --hx-toggle-button-focus-ring-color,
12484
- var(--hx-focus-ring-color, var(--hx-color-primary-600, #0f7078))
12485
- );
12488
+ var(--hx-toggle-button-focus-ring-color, var(--hx-focus-ring-color, #0f7078));
12486
12489
  outline-offset: var(--hx-focus-ring-offset, 2px);
12487
12490
  }
12488
12491
 
@@ -13006,8 +13009,7 @@ export const helixToastStackStyles = css`
13006
13009
  }
13007
13010
 
13008
13011
  .tree:focus-visible {
13009
- outline: var(--hx-focus-ring-width, 2px) solid
13010
- var(--hx-focus-ring-color, var(--hx-color-primary-600, #0f7078));
13012
+ outline: var(--hx-focus-ring-width, 2px) solid var(--hx-focus-ring-color, #0f7078);
13011
13013
  outline-offset: var(--hx-focus-ring-offset, 2px);
13012
13014
  border-radius: var(--hx-border-radius-sm, 0.25rem);
13013
13015
  }
@@ -578,15 +578,16 @@
578
578
 
579
579
  /* ─── Inverted Mode ─── */
580
580
 
581
- /* Inline-fallback contract for --hx-color-border-on-dark-* in this section:
581
+ /* Inline-fallback contract for the on-dark-* tokens in this section:
582
582
  the literal rgba(255, 255, 255, 0.X) arms are a LIGHT-MODE-only last
583
583
  resort (cold-start, CSS-not-loaded). At runtime, hx-theme injects
584
- dark.color.border.on-dark-* as overlay-black-* so dark-mode inverted
585
- buttons stay visible on the now-light surface.inverse (#EBEEE9). The
586
- inline white overlays would render invisible (≈1.1:1) on a light surface,
587
- but they never paint when the theme is mounted. If a future change moves
588
- these into a context where hx-theme is not guaranteed, replace with
589
- mode-aware tokens. */
584
+ the dark.* override (overlay-black-* for the strong border and the
585
+ surface.on-dark-overlay-* fills) so dark-mode inverted buttons stay
586
+ visible on the now-light surface.inverse (#EBEEE9). The inline white
587
+ overlays would render invisible (≈1.1:1) on a light surface, but
588
+ they never paint when the theme is mounted. If a future change
589
+ moves these into a context where hx-theme is not guaranteed,
590
+ replace with mode-aware tokens. */
590
591
 
591
592
  /* Override text color and filter-based hover/active for all variants */
592
593
  :host([inverted]) .button {
@@ -604,8 +605,12 @@
604
605
 
605
606
  :host([inverted]) .button:focus-visible {
606
607
  /* WCAG 1.4.11: focus indicator needs ≥3:1 against adjacent colors.
607
- border-on-dark-default (overlay-white-30) ≈ 2.7:1 on neutral-900 — fails.
608
- border-on-dark-strong (overlay-white-70) 5:1 passes. */
608
+ border-on-dark-strong (overlay-white-70) ≈ 5:1 on neutral-900 — passes.
609
+ The lower-alpha siblings used to live in border.* but were sub-3:1
610
+ against any plausible surface and could not honour a border contract;
611
+ they're now surface.on-dark-overlay-{default,subtle} (translucent
612
+ fills, not borders) and used elsewhere in this file. See
613
+ tokens.json color.surface.on-dark-overlay-* for canonical ratios. */
609
614
  outline-color: var(
610
615
  --hx-button-inverted-focus-ring-color,
611
616
  var(--hx-color-border-on-dark-strong, rgba(255, 255, 255, 0.7))
@@ -616,8 +621,16 @@
616
621
  so dark mode can flip the fill to primary-600. surface.inverse becomes light
617
622
  (#EBEEE9) in dark mode; primary-500 on #EBEEE9 = 2.94:1 (sub-3:1 UI floor
618
623
  fail for the inverted-button boundary). primary-600 on #EBEEE9 = 4.97:1
619
- (AA pass). Light mode tracks action.primary.bg (primary-500, 5.20:1 on
620
- dark surface.inverse). */
624
+ (AA pass). Light mode tracks action.primary.bg-inverted-rest's base value
625
+ (primary-500, 5.20:1 on dark surface.inverse).
626
+
627
+ Override path note (codex round-11): this binds --hx-button-bg directly,
628
+ matching the cascade convention every other .button--{variant} rule uses
629
+ (light primary at line 89, danger at 120, secondary, tertiary, ghost). The
630
+ consumer override path for inverted-primary rest is
631
+ --hx-color-action-primary-bg-inverted-rest, NOT --hx-button-bg — the same
632
+ pattern as light primary (consumers override --hx-color-action-primary-bg).
633
+ Pinned by dark-mode-resolution.test.ts:185-197 across both modes. */
621
634
  :host([inverted]) .button--primary {
622
635
  --hx-button-bg: var(--hx-color-action-primary-bg-inverted-rest, #429797);
623
636
  }
@@ -669,20 +682,34 @@
669
682
  --hx-button-border-color: var(--hx-color-border-on-dark-strong, rgba(255, 255, 255, 0.7));
670
683
  }
671
684
 
685
+ /* Inverted overlay fills read both names so consumer overrides reach paint
686
+ regardless of which token they target: the deprecated --hx-color-border-on-dark-*
687
+ names (3.2.0/3.2.1 public API, scheduled for removal in 4.0.0) and the canonical
688
+ --hx-color-surface-on-dark-overlay-* names (round-8 rename). Deprecated name
689
+ wins when set; otherwise resolves through the canonical alias chain. */
672
690
  :host([inverted]) .button--secondary:hover {
673
- --hx-button-bg: var(--hx-color-border-on-dark-default, rgba(255, 255, 255, 0.3));
691
+ --hx-button-bg: var(
692
+ --hx-color-border-on-dark-default,
693
+ var(--hx-color-surface-on-dark-overlay-default, rgba(255, 255, 255, 0.3))
694
+ );
674
695
  }
675
696
 
676
- /* Tertiary inverted — resting at subtle (10%) lifts to default (30%) on hover
677
- so the runtime hover delta is visually distinct, not collapsed onto a
678
- single token. */
697
+ /* Tertiary inverted — resting at the subtle overlay (10%) lifts to the default
698
+ overlay (30%) on hover so the runtime hover delta is visually distinct, not
699
+ collapsed onto a single token. */
679
700
  :host([inverted]) .button--tertiary {
680
- --hx-button-bg: var(--hx-color-border-on-dark-subtle, rgba(255, 255, 255, 0.1));
701
+ --hx-button-bg: var(
702
+ --hx-color-border-on-dark-subtle,
703
+ var(--hx-color-surface-on-dark-overlay-subtle, rgba(255, 255, 255, 0.1))
704
+ );
681
705
  --hx-button-border-color: transparent;
682
706
  }
683
707
 
684
708
  :host([inverted]) .button--tertiary:hover {
685
- --hx-button-bg: var(--hx-color-border-on-dark-default, rgba(255, 255, 255, 0.3));
709
+ --hx-button-bg: var(
710
+ --hx-color-border-on-dark-default,
711
+ var(--hx-color-surface-on-dark-overlay-default, rgba(255, 255, 255, 0.3))
712
+ );
686
713
  }
687
714
 
688
715
  /* Ghost inverted — transparent base, translucent hover bg */
@@ -694,7 +721,10 @@
694
721
  :host([inverted]) .button--ghost:hover {
695
722
  --hx-button-bg: var(
696
723
  --hx-button-inverted-ghost-hover-bg,
697
- var(--hx-color-border-on-dark-default, rgba(255, 255, 255, 0.3))
724
+ var(
725
+ --hx-color-border-on-dark-default,
726
+ var(--hx-color-surface-on-dark-overlay-default, rgba(255, 255, 255, 0.3))
727
+ )
698
728
  );
699
729
  }
700
730
 
@@ -704,7 +734,10 @@
704
734
  }
705
735
 
706
736
  :host([inverted]) .button--outline:hover {
707
- --hx-button-bg: var(--hx-color-border-on-dark-default, rgba(255, 255, 255, 0.3));
737
+ --hx-button-bg: var(
738
+ --hx-color-border-on-dark-default,
739
+ var(--hx-color-surface-on-dark-overlay-default, rgba(255, 255, 255, 0.3))
740
+ );
708
741
  }
709
742
 
710
743
  /* ─── Prefix / Suffix / Label ─── */
@@ -1519,10 +1552,7 @@
1519
1552
 
1520
1553
  .link:focus-visible {
1521
1554
  outline: var(--hx-focus-ring-width, 2px) solid
1522
- var(
1523
- --hx-link-focus-ring-color,
1524
- var(--hx-focus-ring-color, var(--hx-color-primary-600, #0f7078))
1525
- );
1555
+ var(--hx-link-focus-ring-color, var(--hx-focus-ring-color, #0f7078));
1526
1556
  outline-offset: var(--hx-focus-ring-offset, 2px);
1527
1557
  border-radius: var(--hx-border-radius-sm, 0.25rem);
1528
1558
  }