@repobit/dex-system-design 0.25.11 → 0.26.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.
Files changed (336) hide show
  1. package/CHANGELOG.md +195 -0
  2. package/README.md +131 -8
  3. package/package.json +95 -13
  4. package/schemas/component-manifest.json +3294 -405
  5. package/schemas/manifest-omissions.json +173 -0
  6. package/src/blog/src/breakpoints.js +6 -6
  7. package/src/blog/src/content/blog-atoms-showcase.js +1 -1
  8. package/src/blog/src/content/blog-page-layout.js +2 -2
  9. package/src/blog/src/lib/article-toc.js +7 -7
  10. package/src/blog/src/shell/blog-shell.js +1 -1
  11. package/src/blog/src/tokens/blog.js +2 -2
  12. package/src/blog/src/tokens/core.js +34 -35
  13. package/src/blog/src/tokens/legacy.js +0 -9
  14. package/src/blog/tokens/blog.js +2 -2
  15. package/src/blog/tokens/core.js +34 -35
  16. package/src/blog/tokens/legacy.js +0 -9
  17. package/src/blog/tokens.css +36 -46
  18. package/src/components/accordion/accordion-bg.css.js +83 -59
  19. package/src/components/accordion/accordion-bg.js +29 -10
  20. package/src/components/accordion/accordion-bg.stories.js +67 -67
  21. package/src/components/accordion/accordion-keyboard.js +80 -0
  22. package/src/components/accordion/accordion.css.js +142 -80
  23. package/src/components/accordion/accordion.js +37 -10
  24. package/src/components/accordion/accordion.stories.js +7 -7
  25. package/src/components/agent-endpoints/agent-endpoints.css.js +36 -39
  26. package/src/components/agent-endpoints/agent-endpoints.js +30 -20
  27. package/src/components/agent-endpoints/agent-endpoints.stories.js +1 -1
  28. package/src/components/ai-guardian-demo.stories.js +91 -91
  29. package/src/components/alert/alert.css.js +198 -0
  30. package/src/components/alert/alert.js +103 -0
  31. package/src/components/alert/alert.stories.js +206 -0
  32. package/src/components/anchor/anchor-nav.css.js +213 -101
  33. package/src/components/anchor/anchor-nav.js +26 -40
  34. package/src/components/anchor/anchor.stories.js +22 -12
  35. package/src/components/annotation/annotation.css.js +58 -0
  36. package/src/components/annotation/annotation.js +67 -0
  37. package/src/components/annotation/annotation.stories.js +63 -0
  38. package/src/components/architecture.stories.js +285 -0
  39. package/src/components/atoms.stories.js +342 -0
  40. package/src/components/avatar/avatar.css.js +67 -0
  41. package/src/components/avatar/avatar.js +42 -0
  42. package/src/components/avatar/avatar.stories.js +95 -0
  43. package/src/components/awards/awards-flex.css.js +209 -23
  44. package/src/components/awards/awards-flex.js +66 -7
  45. package/src/components/awards/awards-flex.stories.js +1 -1
  46. package/src/components/awards/{awards-light.stories.js → awards-summary.stories.js} +54 -64
  47. package/src/components/awards/awards.css.js +116 -58
  48. package/src/components/awards/awards.js +102 -28
  49. package/src/components/awards/awards.stories.js +1 -1
  50. package/src/components/back/back.css.js +51 -22
  51. package/src/components/back/back.js +28 -7
  52. package/src/components/back/back.stories.js +9 -3
  53. package/src/components/badge/badge.css.js +158 -46
  54. package/src/components/badge/badge.js +62 -74
  55. package/src/components/badge/badge.stories.js +176 -248
  56. package/src/components/bento-grid/bento-grid.css.js +21 -16
  57. package/src/components/bento-grid/bento-grid.js +16 -4
  58. package/src/components/bento-grid/bento-grid.stories.js +19 -18
  59. package/src/components/bento-grid/bento-item.css.js +52 -28
  60. package/src/components/bento-grid/bento-item.js +2 -2
  61. package/src/components/blockquote/blockquote.css.js +47 -0
  62. package/src/components/blockquote/blockquote.js +29 -0
  63. package/src/components/blockquote/blockquote.stories.js +62 -0
  64. package/src/components/breadcrumb/breadcrumb.css.js +92 -22
  65. package/src/components/breadcrumb/breadcrumb.js +56 -11
  66. package/src/components/button/button.css.js +531 -161
  67. package/src/components/button/button.js +206 -214
  68. package/src/components/button/button.stories.js +322 -174
  69. package/src/components/caption/caption.css.js +21 -0
  70. package/src/components/caption/caption.js +31 -0
  71. package/src/components/caption/caption.stories.js +62 -0
  72. package/src/components/card-features/card-features.css.js +14 -22
  73. package/src/components/card-features/card-features.js +68 -9
  74. package/src/components/card-features/card-features.stories.js +11 -11
  75. package/src/components/cards/card.css.js +60 -81
  76. package/src/components/cards/card.js +56 -25
  77. package/src/components/cards/card.stories.js +39 -39
  78. package/src/components/carousel/carousel.css.js +93 -99
  79. package/src/components/carousel/carousel.js +32 -4
  80. package/src/components/checkbox/checkbox.css.js +111 -93
  81. package/src/components/checkbox/checkbox.js +64 -90
  82. package/src/components/checkbox/checkbox.stories.js +96 -29
  83. package/src/components/code/code.css.js +70 -0
  84. package/src/components/code/code.js +40 -0
  85. package/src/components/code/code.stories.js +73 -0
  86. package/src/components/compare/compare.css.js +179 -43
  87. package/src/components/compare/compare.js +52 -25
  88. package/src/components/compare/compare.stories.js +61 -4
  89. package/src/components/comparison-panel/comparison-panel.css.js +38 -51
  90. package/src/components/comparison-panel/comparison-panel.js +5 -4
  91. package/src/components/comparison-panel/comparison-panel.stories.js +1 -1
  92. package/src/components/compatibility-table/compatibility-table.css.js +180 -80
  93. package/src/components/compatibility-table/compatibility-table.js +37 -9
  94. package/src/components/control-alignment.stories.js +393 -0
  95. package/src/components/cta-banner/cta-banner.css.js +41 -13
  96. package/src/components/cta-banner/cta-banner.js +6 -5
  97. package/src/components/cta-banner/cta-banner.stories.js +43 -98
  98. package/src/components/display/display.css.js +25 -1
  99. package/src/components/display/display.js +46 -13
  100. package/src/components/display/display.stories.js +270 -40
  101. package/src/components/divider/divider-horizontal.js +21 -5
  102. package/src/components/divider/divider-vertical.js +15 -7
  103. package/src/components/divider/divider.css.js +2 -2
  104. package/src/components/divider/divider.stories.js +38 -34
  105. package/src/components/dropdown/dropdown.css.js +93 -126
  106. package/src/components/dropdown/dropdown.js +114 -34
  107. package/src/components/dropdown/dropdown.stories.js +56 -24
  108. package/src/components/features/features.css.js +24 -11
  109. package/src/components/features/features.js +7 -3
  110. package/src/components/features/features.stories.js +37 -37
  111. package/src/components/features-tab/features-tab.css.js +19 -8
  112. package/src/components/features-tab/features-tab.js +6 -5
  113. package/src/components/features-tab/features-tab.stories.js +23 -23
  114. package/src/components/fieldset/fieldset.css.js +30 -0
  115. package/src/components/fieldset/fieldset.js +28 -0
  116. package/src/components/fieldset/fieldset.stories.js +84 -0
  117. package/src/components/footer/footer-links-group.css.js +10 -14
  118. package/src/components/footer/footer-links-group.js +4 -3
  119. package/src/components/footer/footer-lp.css.js +59 -30
  120. package/src/components/footer/footer-lp.js +17 -12
  121. package/src/components/footer/footer-lp.stories.js +63 -75
  122. package/src/components/footer/footer-nav-menu.css.js +26 -4
  123. package/src/components/footer/footer-nav-menu.js +3 -2
  124. package/src/components/footer/footer.css.js +146 -264
  125. package/src/components/footer/footer.js +176 -106
  126. package/src/components/footer/footer.stories.js +9 -9
  127. package/src/components/footer/localeMap.js +1 -1
  128. package/src/components/grid/grid.css.js +1 -1
  129. package/src/components/grid/grid.js +49 -7
  130. package/src/components/grid/grid.stories.js +111 -0
  131. package/src/components/header/header-code.css.js +61 -51
  132. package/src/components/header/header-code.js +28 -14
  133. package/src/components/header/header-code.stories.js +5 -5
  134. package/src/components/header/header.css.js +655 -176
  135. package/src/components/header/header.js +269 -36
  136. package/src/components/header/header.stories.js +841 -18
  137. package/src/components/heading/heading.css.js +14 -17
  138. package/src/components/heading/heading.js +48 -33
  139. package/src/components/heading/heading.stories.js +27 -25
  140. package/src/components/help-text/help-text.css.js +21 -0
  141. package/src/components/help-text/help-text.js +25 -0
  142. package/src/components/help-text/help-text.stories.js +66 -0
  143. package/src/components/highlight/highlight.css.js +86 -64
  144. package/src/components/highlight/highlight.js +18 -27
  145. package/src/components/highlight/highlight.stories.js +14 -3
  146. package/src/components/icons/analysis-icon.js +6 -16
  147. package/src/components/icons/arrow-down-icon.js +6 -19
  148. package/src/components/icons/arrow-icon.js +44 -0
  149. package/src/components/icons/arrow-right-icon.js +30 -23
  150. package/src/components/icons/arrow-up-icon.js +19 -18
  151. package/src/components/icons/bd-ai-icon.js +1 -1
  152. package/src/components/icons/brand-marks.stories.js +279 -0
  153. package/src/components/icons/brand-signature-icon.js +42 -0
  154. package/src/components/icons/check-icon.js +27 -0
  155. package/src/components/icons/circle-info-icon.js +33 -0
  156. package/src/components/icons/close-icon.js +6 -18
  157. package/src/components/icons/family-icon.js +8 -20
  158. package/src/components/icons/globe-icon.js +6 -18
  159. package/src/components/icons/guide-icon.js +6 -18
  160. package/src/components/icons/icon-element.js +99 -0
  161. package/src/components/icons/icons.js +36 -0
  162. package/src/components/icons/icons.stories.js +184 -52
  163. package/src/components/icons/individual-icon.js +6 -18
  164. package/src/components/icons/laurel-icon.js +9 -19
  165. package/src/components/icons/machine-learning-icon.js +6 -17
  166. package/src/components/icons/marks.js +41 -0
  167. package/src/components/icons/minus-icon.js +7 -21
  168. package/src/components/icons/missing-icon.js +52 -0
  169. package/src/components/icons/plus-icon.js +7 -21
  170. package/src/components/icons/quote-icon.js +19 -19
  171. package/src/components/image/image.css.js +72 -25
  172. package/src/components/image/image.js +11 -6
  173. package/src/components/image/image.stories.js +2 -2
  174. package/src/components/input/custom-form.stories.js +214 -62
  175. package/src/components/input/input-clipboard.css.js +51 -144
  176. package/src/components/input/input-clipboard.js +31 -15
  177. package/src/components/input/input.css.js +8 -146
  178. package/src/components/input/input.js +93 -38
  179. package/src/components/install-options/install-options.css.js +84 -77
  180. package/src/components/install-options/install-options.js +33 -30
  181. package/src/components/install-options/install-options.stories.js +3 -3
  182. package/src/components/label/label.css.js +35 -0
  183. package/src/components/label/label.js +38 -0
  184. package/src/components/label/label.stories.js +82 -0
  185. package/src/components/light-carousel/light-carousel.css.js +111 -63
  186. package/src/components/light-carousel/light-carousel.js +85 -11
  187. package/src/components/light-carousel/light-carousel.stories.js +126 -82
  188. package/src/components/link/link.css.js +150 -99
  189. package/src/components/link/link.js +86 -11
  190. package/src/components/link/link.stories.js +124 -30
  191. package/src/components/list/list-item/list-item.css.js +74 -22
  192. package/src/components/list/list-item/list-item.js +32 -10
  193. package/src/components/list/list-item/list-item.stories.js +23 -23
  194. package/src/components/list/list.css.js +8 -2
  195. package/src/components/list/list.js +3 -2
  196. package/src/components/list/list.stories.js +222 -0
  197. package/src/components/modal/modal.css.js +114 -24
  198. package/src/components/modal/modal.js +83 -7
  199. package/src/components/modal/modal.stories.js +9 -9
  200. package/src/components/overview/overview.css.js +19 -14
  201. package/src/components/overview/overview.js +6 -5
  202. package/src/components/overview/overview.stories.js +10 -10
  203. package/src/components/page-switcher/page-switcher.css.js +97 -40
  204. package/src/components/page-switcher/page-switcher.js +28 -5
  205. package/src/components/page-switcher/page-switcher.stories.js +95 -0
  206. package/src/components/paragraph/paragraph.css.js +15 -10
  207. package/src/components/paragraph/paragraph.js +41 -44
  208. package/src/components/paragraph/paragraph.stories.js +56 -21
  209. package/src/components/picture/picture.css.js +103 -44
  210. package/src/components/picture/picture.js +100 -30
  211. package/src/components/picture/picture.stories.js +1 -1
  212. package/src/components/pricing-cards/new-pricing-card.js +3 -3
  213. package/src/components/pricing-cards/new-pricing.css.js +24 -15
  214. package/src/components/pricing-cards/pricing-card-actions.css.js +1 -1
  215. package/src/components/pricing-cards/pricing-card-actions.js +3 -4
  216. package/src/components/pricing-cards/pricing-card-container.css.js +3 -3
  217. package/src/components/pricing-cards/pricing-card-container.js +3 -2
  218. package/src/components/pricing-cards/pricing-card-header.css.js +10 -8
  219. package/src/components/pricing-cards/pricing-card-header.js +6 -7
  220. package/src/components/pricing-cards/pricing-card-pricing.css.js +16 -9
  221. package/src/components/pricing-cards/pricing-card-pricing.js +8 -6
  222. package/src/components/pricing-cards/pricing-card-show-more.css.js +11 -3
  223. package/src/components/pricing-cards/pricing-card-show-more.js +8 -3
  224. package/src/components/pricing-cards/pricing-card.css.js +244 -190
  225. package/src/components/pricing-cards/pricing-card.js +54 -70
  226. package/src/components/pricing-cards/pricing-feature-item.css.js +25 -8
  227. package/src/components/pricing-cards/pricing-feature-item.js +8 -3
  228. package/src/components/process-steps/process-steps.css.js +26 -14
  229. package/src/components/process-steps/process-steps.js +23 -6
  230. package/src/components/process-steps/process-steps.stories.js +1 -1
  231. package/src/components/progress/progress.css.js +80 -0
  232. package/src/components/progress/progress.js +42 -0
  233. package/src/components/progress/progress.stories.js +79 -0
  234. package/src/components/quick-answer/quick-answer.css.js +75 -13
  235. package/src/components/quick-answer/quick-answer.js +8 -3
  236. package/src/components/radio/radio.css.js +92 -128
  237. package/src/components/radio/radio.js +106 -127
  238. package/src/components/radio/radio.stories.js +54 -19
  239. package/src/components/review/review-grid.css.js +5 -6
  240. package/src/components/review/review-grid.js +14 -11
  241. package/src/components/review/review.css.js +11 -6
  242. package/src/components/review/review.js +3 -8
  243. package/src/components/shared/ensemble.css.js +93 -0
  244. package/src/components/shared/form-field.css.js +206 -0
  245. package/src/components/shared/prop-vocabulary.js +48 -0
  246. package/src/components/shared/token-scales.js +306 -0
  247. package/src/components/skeleton/skeleton.css.js +34 -0
  248. package/src/components/skeleton/skeleton.js +32 -0
  249. package/src/components/skeleton/skeleton.stories.js +70 -0
  250. package/src/components/spinner/spinner.css.js +62 -0
  251. package/src/components/spinner/spinner.js +38 -0
  252. package/src/components/spinner/spinner.stories.js +92 -0
  253. package/src/components/spotlight-section/spotlight-section.css.js +14 -13
  254. package/src/components/spotlight-section/spotlight-section.js +42 -39
  255. package/src/components/switch/switch.css.js +103 -0
  256. package/src/components/switch/switch.js +44 -0
  257. package/src/components/switch/switch.stories.js +86 -0
  258. package/src/components/tab-list/content-switcher.stories.js +189 -0
  259. package/src/components/tab-list/tab-list.css.js +250 -0
  260. package/src/components/tab-list/tab-list.js +184 -0
  261. package/src/components/tab-list/tab-list.stories.js +221 -0
  262. package/src/components/tabs/tabs.css.js +14 -123
  263. package/src/components/tabs/tabs.js +16 -19
  264. package/src/components/tabs/tabs.stories.js +95 -95
  265. package/src/components/tag/tag.css.js +54 -0
  266. package/src/components/tag/tag.js +32 -0
  267. package/src/components/tag/tag.stories.js +126 -0
  268. package/src/components/terminal/terminal-message.css.js +164 -60
  269. package/src/components/terminal/terminal-message.js +5 -5
  270. package/src/components/terminal/terminal-message.stories.js +70 -1
  271. package/src/components/termsOfUse/terms.css.js +25 -20
  272. package/src/components/termsOfUse/terms.js +13 -9
  273. package/src/components/termsOfUse/terms.stories.js +1 -1
  274. package/src/components/textarea/textarea.css.js +51 -0
  275. package/src/components/textarea/textarea.js +136 -0
  276. package/src/components/textarea/textarea.stories.js +191 -0
  277. package/src/components/tooltip/tooltip.css.js +75 -0
  278. package/src/components/tooltip/tooltip.js +156 -0
  279. package/src/components/tooltip/tooltip.stories.js +161 -0
  280. package/src/components/trust-panel/trust-panel.css.js +85 -33
  281. package/src/components/trust-panel/trust-panel.js +18 -10
  282. package/src/components/trust-panel/trust-panel.stories.js +1 -1
  283. package/src/components/ultimate-security-demo.stories.js +431 -0
  284. package/src/components/video/video.css.js +17 -0
  285. package/src/components/video/video.js +40 -0
  286. package/src/components/video/video.stories.js +106 -0
  287. package/src/components/video-player/video-player.css.js +67 -11
  288. package/src/components/video-player/video-player.js +35 -4
  289. package/src/components/video-player/video-player.stories.js +1 -1
  290. package/src/components/visual-alignment.stories.js +411 -0
  291. package/src/components/visually-hidden/visually-hidden.css.js +24 -0
  292. package/src/components/visually-hidden/visually-hidden.js +16 -0
  293. package/src/components/visually-hidden/visually-hidden.stories.js +56 -0
  294. package/src/stories/Button.stories.js +17 -17
  295. package/src/stories/Header.stories.js +10 -10
  296. package/src/stories/Page.js +1 -1
  297. package/src/stories/Page.stories.js +6 -6
  298. package/src/tokens/borders.stories.js +339 -0
  299. package/src/tokens/color-responsibilities.stories.js +227 -0
  300. package/src/tokens/dark-derivation.js +309 -0
  301. package/src/tokens/dark-findings.js +197 -0
  302. package/src/tokens/dark-mode.stories.js +207 -0
  303. package/src/tokens/dimension.stories.js +251 -0
  304. package/src/tokens/elevation.stories.js +143 -0
  305. package/src/tokens/focus.stories.js +276 -0
  306. package/src/tokens/fonts.css +20 -20
  307. package/src/tokens/fonts.stories.js +354 -374
  308. package/src/tokens/layout.css +25 -11
  309. package/src/tokens/motion.stories.js +231 -0
  310. package/src/tokens/shape.stories.js +272 -0
  311. package/src/tokens/spacing-rhythm.stories.js +359 -0
  312. package/src/tokens/spacing.stories.js +208 -703
  313. package/src/tokens/story-chrome.js +503 -0
  314. package/src/tokens/surfaces.stories.js +224 -0
  315. package/src/tokens/text-on-surface.stories.js +164 -0
  316. package/src/tokens/token-map.js +220 -0
  317. package/src/tokens/token-map.stories.js +257 -0
  318. package/src/tokens/token-purposes.js +266 -0
  319. package/src/tokens/tokens-grid.stories.js +388 -900
  320. package/src/tokens/tokens.css +1633 -1045
  321. package/src/tokens/tokens.js +1130 -492
  322. package/src/tokens/tokens.stories.js +137 -47
  323. package/src/tokens/type-ceiling-words.js +299 -0
  324. package/src/tokens/typography.stories.js +1003 -965
  325. package/src/tokens/vertical-rhythm.stories.js +224 -0
  326. package/src/components/awards/awards-icon.js +0 -56
  327. package/src/components/awards/awards-light.js +0 -240
  328. package/src/components/banner/banner.js +0 -60
  329. package/src/components/banner/banner.stories.js +0 -51
  330. package/src/components/button/icons.js +0 -24
  331. package/src/components/input/index.js +0 -0
  332. package/src/components/light-carousel/light-carousel-simple.css.js +0 -183
  333. package/src/components/light-carousel/light-carousel-simple.js +0 -74
  334. package/src/tokens/colors.js +0 -121
  335. package/src/tokens/typography.css.js +0 -207
  336. package/src/tokens/typography.js +0 -0
@@ -1,45 +1,90 @@
1
1
  import { css } from "lit";
2
2
 
3
+ /**
4
+ * Styled entirely from src/tokens/tokens.js — see CLAUDE.md, "The foundation
5
+ * rule". Every measurement was matched to the token that already carries the
6
+ * ds-button value; nothing was copied across as a literal.
7
+ *
8
+ * The --button-* properties below are component-local semantic aliases, not
9
+ * design tokens. Declaring them on :host is deliberate: outer-tree rules beat
10
+ * :host, so a page can still theme a button with
11
+ * `bd-button { --bd-button-primary-bg: … }`.
12
+ */
3
13
  export default css`
4
14
  :host {
5
15
  display: inline-flex;
6
- --button-background-primary: var(--color-blue-500);
7
- --button-background-primary-hover: var(--color-blue-600);
8
- --button-background-primary-focus: var(--color-blue-700);
9
16
 
10
- --button-background-secondary: var(--color-neutral-950);
11
- --button-background-secondary-hover: var(--color-neutral-900);
12
- --button-background-secondary-focus: var(--color-neutral-800);
13
-
14
- --button-background-danger: var(--color-red-600);
15
- --button-background-danger-hover: var(--color-red-700);
16
- --button-background-danger-focus: var(--color-red-800);
17
-
18
- --color-button-background-outline: var(--color-neutral-950);
19
- --border-button-background-outline: var(--color-neutral-950);
20
- --button-background-outline-hover: var(--color-neutral-50);
21
- --border-button-background-outline-hover: var(--color-neutral-950);
22
- --button-background-outline-focus: var(--color-neutral-800);
23
-
24
- --color-button-background-primary-outline: var(--color-blue-500);
25
- --border-button-background-primary-outline: var(--color-blue-500);
26
- --button-background-primary-outline-hover: var(--color-blue-50);
27
- --border-button-background-primary-outline-hover: var(--color-blue-500);
28
- --button-background-primary-outline-focus: var(--color-blue-500);
29
- --bd-accesibility-focus: var(--color-blue-500);
30
-
31
- --button-arrow-size: 1.1em;
32
- --button-arrow-shift: 0.65em;
33
- --button-arrow-inset: 0.65em;
34
- --button-arrow-offset: -0.4em;
35
-
36
- --button-radius-rounded: var(--spacing-30);
17
+ /* Component-local aliases, not design tokens. Each defaults to the
18
+ --button-* token that carries the system-wide answer, so there are two
19
+ places to change a button and they do different jobs: set the token on
20
+ :root to move every button in the document, or set the alias on the
21
+ bd-button element to move one.
22
+
23
+ The alias is also what surface="dark" switches further down, which is
24
+ why it stays even now that the tokens behind it are live. */
25
+
26
+ /* ---- primary: blue fill ------------------------------------------- */
27
+ --bd-button-primary-bg: var(--button-primary-background-default);
28
+ --bd-button-primary-bg-hover: var(--button-primary-background-hover);
29
+ --bd-button-primary-bg-active: var(--button-primary-background-active);
30
+ --bd-button-primary-text: var(--button-primary-text-default);
31
+
32
+ /* ---- secondary: near-black fill ----------------------------------- */
33
+ --bd-button-secondary-bg: var(--button-secondary-background-default);
34
+ --bd-button-secondary-bg-hover: var(--button-secondary-background-hover);
35
+ --bd-button-secondary-bg-active: var(--button-secondary-background-active);
36
+ --bd-button-secondary-text: var(--button-secondary-text-default);
37
+
38
+ /* ---- tertiary: blue outline --------------------------------------- */
39
+ --bd-button-tertiary-text: var(--button-tertiary-text-default);
40
+ --bd-button-tertiary-border: var(--button-tertiary-border-default);
41
+ --bd-button-tertiary-bg-hover: var(--button-tertiary-background-hover);
42
+ --bd-button-tertiary-text-hover: var(--button-tertiary-text-hover);
43
+ --bd-button-tertiary-border-hover: var(--button-tertiary-border-hover);
44
+ --bd-button-tertiary-bg-active: var(--button-tertiary-background-active);
45
+ --bd-button-tertiary-text-active: var(--button-tertiary-text-active);
46
+
47
+ /* ---- ghost: dark outline ------------------------------------------ */
48
+ --bd-button-ghost-text: var(--button-ghost-text-default);
49
+ --bd-button-ghost-border: var(--button-ghost-border-default);
50
+ --bd-button-ghost-bg-hover: var(--button-ghost-background-hover);
51
+ --bd-button-ghost-text-hover: var(--button-ghost-text-hover);
52
+ --bd-button-ghost-bg-active: var(--button-ghost-background-active);
53
+ --bd-button-ghost-text-active: var(--button-ghost-text-active);
54
+
55
+ /* ---- accent: red fill --------------------------------------------- */
56
+ --bd-button-accent-bg: var(--button-accent-background-default);
57
+ --bd-button-accent-bg-hover: var(--button-accent-background-hover);
58
+ --bd-button-accent-bg-active: var(--button-accent-background-active);
59
+ --bd-button-accent-text: var(--button-accent-text-default);
60
+
61
+ /* ---- white and outline-white: fixed presets for a coloured banner --
62
+ They ignore surface on purpose; see the note on VARIANTS in button.js. */
63
+ --bd-button-white-bg: var(--button-white-background-default);
64
+ --bd-button-white-bg-hover: var(--button-white-background-hover);
65
+ --bd-button-white-bg-active: var(--button-white-background-active);
66
+ --bd-button-white-text: var(--button-white-text-default);
67
+
68
+ --bd-button-outline-white-text: var(--button-outline-white-text-default);
69
+ --bd-button-outline-white-border: var(--button-outline-white-border-default);
70
+ --bd-button-outline-white-bg-hover: var(--button-outline-white-background-hover);
71
+ --bd-button-outline-white-bg-active: var(--button-outline-white-background-active);
72
+
73
+ /* ---- disabled, shared across every variant ----------------------- */
74
+ --bd-button-disabled-bg: var(--button-disabled-backgroundColor);
75
+ --bd-button-disabled-text: var(--button-disabled-color);
76
+ --bd-button-disabled-border: var(--button-disabled-borderColor);
77
+
78
+ /* accent carries no ring on a light page; on a dark one it needs a
79
+ boundary, so the value is switched rather than the rule */
80
+ --bd-button-accent-ring: var(--button-accent-ring-default);
81
+
82
+ --bd-button-border-width: var(--border-width-2);
37
83
  }
38
84
 
39
85
  /* ============================================
40
- ALIGNMENT SUPPORT
86
+ ALIGNMENT
41
87
  ============================================ */
42
-
43
88
  :host([align="center"]) {
44
89
  display: flex;
45
90
  justify-content: center;
@@ -72,28 +117,49 @@ export default css`
72
117
  display: flex;
73
118
  }
74
119
 
75
- :host([data-bd-button-focus]) {
76
- outline: var(--spacing-2) solid var(--bd-accesibility-focus);
77
- outline-offset: var(--spacing-2);
78
- border-radius: var(--radius-md);
120
+ /* ============================================
121
+ FOCUS
122
+ The design specifies no focus state, but 2.4.7 requires one.
123
+
124
+ This used to be driven from JavaScript: two requestAnimationFrame hops
125
+ checked :focus-visible and set a data attribute the CSS then styled.
126
+ :focus-visible does that natively, so the detection is gone and the ring
127
+ is the shared one from Foundations/Focus — a two-colour ring whose white
128
+ inner band keeps it visible on a coloured hero, which the old
129
+ single-colour outline could not do. It is composed with
130
+ --bd-button-edge rather than replacing it, so an outlined variant keeps
131
+ its own boundary while focused; see the note on that property.
132
+ ============================================ */
133
+ button:focus,
134
+ a:focus {
135
+ outline: none;
79
136
  }
80
137
 
81
- :host([shape="rounded"][data-bd-button-focus]) {
82
- border-radius: var(--button-radius-rounded);
138
+ .button:focus-visible {
139
+ outline: none;
140
+ box-shadow: var(--focus-outline-primary), var(--bd-button-edge);
83
141
  }
84
142
 
85
- button:focus,
86
- button:focus-visible,
87
- a:focus,
88
- a:focus-visible {
89
- outline: none;
90
- box-shadow: none;
143
+ /* A white control needs the ring the other way up. --focus-outline-primary
144
+ puts its WHITE band against the control, which is what keeps it visible on
145
+ a coloured hero -- and is exactly wrong when the control is itself white:
146
+ measured on Button — White / Outline-White, the inner band was 1.00:1
147
+ against the button's own fill and the blue band 2.38:1 against the hero
148
+ (1.75:1 at the gradient's light end), so neither reached the 3:1 WCAG
149
+ 2.4.11 asks. outline-white is here too because restoring its boundary
150
+ above puts a white border where the white band used to sit on the hero. */
151
+ .button--white:focus-visible,
152
+ .button--outline-white:focus-visible {
153
+ box-shadow: var(--focus-outline-inverse), var(--bd-button-edge);
91
154
  }
92
155
 
93
156
  a.button {
94
157
  text-decoration: none;
95
158
  }
96
159
 
160
+ /* ============================================
161
+ SHARED
162
+ ============================================ */
97
163
  .button,
98
164
  .bd-contact-btn {
99
165
  display: inline-flex;
@@ -101,67 +167,131 @@ export default css`
101
167
  align-items: center;
102
168
  text-align: center;
103
169
  text-decoration: none;
104
- color: var(--color-neutral-0);
105
170
  border: none;
106
171
  cursor: pointer;
107
- transition: background-color var(--transition-duration-normal) var(--transition-easing-smooth),
108
- transform var(--transition-duration-normal) var(--transition-easing-smooth),
109
- box-shadow var(--transition-duration-normal) var(--transition-easing-smooth),
110
- color var(--transition-duration-normal) var(--transition-easing-smooth);
111
- gap: var(--spacing-10);
172
+ font-family: var(--typography-fontFamily-sans);
173
+ font-weight: var(--typography-control-label-large-fontWeight);
174
+ line-height: var(--typography-control-label-large-lineHeight);
112
175
  vertical-align: middle;
113
- line-height: 1;
114
176
  box-sizing: border-box;
115
- }
116
-
117
- .button__label {
118
- display: inline-block;
119
- }
120
177
 
121
- .button--primary {
122
- background-color: var(--button-background-primary);
123
- color: var(--color-neutral-0);
124
- }
125
-
126
- .button--primary:hover {
127
- background-color: var(--button-background-primary-hover);
128
- }
129
-
130
- .button--primary:active {
131
- background-color: var(--button-background-primary-focus);
132
- }
178
+ /* The variant's own boundary, held in a custom property so the focus ring
179
+ can COMPOSE with it. box-shadow is a single list, not additive, and
180
+ .button:focus-visible (0,2,0) outranks .button--ghost (0,1,0) -- so a
181
+ focus rule that declared box-shadow directly erased the border of every
182
+ outlined variant. A focused ghost button lost its dark outline and wore
183
+ a blue ring instead, which read as a tertiary button. The default is a
184
+ zero-spread transparent shadow rather than the keyword none, so the value
185
+ a valid shadow the focus rule can append to. */
186
+ --bd-button-edge: 0 0 0 0 transparent;
187
+ box-shadow: var(--bd-button-edge);
133
188
 
134
- .button--secondary {
135
- background-color: var(--button-background-secondary);
136
- color: var(--color-neutral-0);
189
+ transition: background-color var(--transition-duration-normal) var(--transition-easing-smooth),
190
+ box-shadow var(--transition-duration-normal) var(--transition-easing-smooth),
191
+ color var(--transition-duration-normal) var(--transition-easing-smooth);
137
192
  }
138
193
 
139
- .button--secondary:hover {
140
- background-color: var(--button-background-secondary-hover);
194
+ /* bd-contact-button has no variant, so it would inherit no colour at all */
195
+ .button.bd-contact-btn {
196
+ background-color: transparent;
197
+ color: var(--color-text-brand);
198
+ gap: var(--spacing-8);
199
+
200
+ /* Same inset bd-back carries, and for the same reason. Without it this
201
+ control was a bare line box measuring 159x20 -- a 20px tall target
202
+ against the 24x24 WCAG 2.5.8 asks of anything that is not inline in a
203
+ sentence, so 4px short, and a standalone CTA has no exception to claim.
204
+ It also left the focus ring sitting on the glyphs' ascenders.
205
+
206
+ bd-back is the same shape of control -- text, a trailing mark, no fill --
207
+ and already answers this with 12px 16px, which takes a 16px line to about
208
+ 44px: the same height bd-button reaches through its own padding. Reading
209
+ the inset off the sibling rather than picking a number is what keeps the
210
+ two text CTAs in step. */
211
+ padding: var(--spacing-12) var(--spacing-16);
212
+
213
+ /* This control takes no size class -- it is a text CTA with a trailing
214
+ arrow, not a filled button -- so it arrived with no radius at all, and
215
+ the shared ring drew SQUARE corners around a bare line box while every
216
+ other button's ring followed a curve.
217
+
218
+ --button-medium-borderRadius, not --focus-outline-radius. The focus
219
+ token is the documented default for an element with NO radius, and that
220
+ is what this rule used first -- but with the inset above the control is
221
+ now a 44px box standing next to bd-button at the same height, and the
222
+ focus token is --radius-sm where medium buttons are --radius-md. Four
223
+ pixels against six is small, and it is visible when they sit in a row.
224
+ Matching the size band this control actually occupies is the better
225
+ answer than matching the rule for controls that occupy none.
226
+
227
+ Declared unconditionally rather than under :focus-visible because the
228
+ control draws no background and no border at rest, so the radius is
229
+ invisible until the ring needs it. */
230
+ border-radius: var(--button-medium-borderRadius);
141
231
  }
142
232
 
143
- .button--secondary:active {
144
- background-color: var(--button-background-secondary-focus);
233
+ /* ============================================
234
+ SIZE
235
+ Height is left to padding and line-height rather than pinned with a
236
+ min-height, which lands within half a pixel of the design: 33.5 / 44 /
237
+ 54.5 against 34 / 45 / 55. The previous rules also carried hardcoded
238
+ min-widths (115px, 150px) that the design does not ask for at all.
239
+
240
+ The radius comes from --button-*-borderRadius rather than --radius-*
241
+ directly. Same values, so nothing moves here — but a button and a field
242
+ of the same size sit in the same form row, and reading both from their
243
+ own size-matched alias is what keeps them in step. Spelled as raw scale
244
+ steps on one side and aliases on the other, they had drifted a step apart
245
+ at sm and md without either side looking wrong on its own.
246
+ ============================================ */
247
+ .button--small {
248
+ padding: var(--button-small-padding);
249
+ font-size: var(--button-small-fontSize);
250
+ border-radius: var(--button-small-borderRadius);
251
+ gap: var(--button-small-gap);
145
252
  }
146
253
 
147
- .button--danger {
148
- background-color: var(--button-background-danger);
149
- color: var(--color-neutral-0);
254
+ .button--medium {
255
+ padding: var(--button-medium-padding);
256
+ font-size: var(--button-medium-fontSize);
257
+ border-radius: var(--button-medium-borderRadius);
258
+ gap: var(--button-medium-gap);
150
259
  }
151
260
 
152
- // .button--danger:hover {
153
- // background-color: var(--button-background-danger-hover);
154
- // }
155
-
156
- .button--danger:active {
157
- background-color: var(--button-background-danger-focus);
261
+ .button--large {
262
+ padding: var(--button-large-padding);
263
+ font-size: var(--button-large-fontSize);
264
+ border-radius: var(--button-large-borderRadius);
265
+ gap: var(--button-large-gap);
266
+ }
267
+
268
+ .button--bold {
269
+ /* no role: the class is the semantic. .button--bold says what this
270
+ declaration does, so a role naming it would only restate the class --
271
+ there is no text-content type here for a role to describe, just an
272
+ emphasis the caller asked for by name. The same holds for a weight
273
+ driven by an active or selected state: that is a UI state, the category
274
+ CLAUDE.md keeps apart from type when it says a focus ring is never
275
+ expressed by swapping a border colour. This is the argument for every
276
+ "no role: state or modifier" marker in the package -- the others point
277
+ here rather than restating it. */
278
+ font-weight: var(--typography-fontWeight-semibold);
279
+ }
280
+
281
+ /* shape="rounded". After the size rules on purpose: same specificity, so
282
+ source order is what lets the shape replace the size band's corner. */
283
+ .button--rounded {
284
+ border-radius: var(--radius-3xl);
158
285
  }
159
286
 
160
287
  /* ============================================
161
- HOVER CU SĂGEATĂ (implicit pentru kind="danger")
162
- Lățimea butonului rămâne fixă: textul se translatează
163
- spre stânga, iar săgeata (poziționată absolut) apare în dreapta.
288
+ HOVER ARROW — accent, unless no-arrow
289
+ The button keeps its width: the label slides left and the arrow,
290
+ absolutely positioned, fades in where the label was.
164
291
  ============================================ */
292
+ .button__label {
293
+ display: inline-block;
294
+ }
165
295
 
166
296
  .button--with-arrow {
167
297
  position: relative;
@@ -175,115 +305,334 @@ export default css`
175
305
  .button--with-arrow .button__arrow {
176
306
  position: absolute;
177
307
  top: 50%;
178
- right: var(--button-arrow-inset);
179
- width: var(--button-arrow-size);
180
- height: var(--button-arrow-size);
181
- display: inline-flex;
308
+ right: var(--spacing-12);
182
309
  opacity: 0;
183
- transform: translate(var(--button-arrow-offset), -50%);
184
- transition: opacity var(--transition-duration-normal) var(--transition-easing-smooth),
310
+ transform: translate(calc(-1 * var(--spacing-8)), -50%);
311
+ transition:
312
+ opacity var(--transition-duration-normal) var(--transition-easing-smooth),
185
313
  transform var(--transition-duration-normal) var(--transition-easing-smooth);
186
314
  pointer-events: none;
187
315
  }
188
316
 
189
317
  .button--with-arrow:hover .button__label,
190
318
  .button--with-arrow:focus-visible .button__label {
191
- transform: translateX(calc(var(--button-arrow-shift) * -1));
319
+ transform: translateX(calc(-1 * var(--spacing-12)));
192
320
  }
193
321
 
194
322
  .button--with-arrow:hover .button__arrow,
195
323
  .button--with-arrow:focus-visible .button__arrow {
196
324
  opacity: 1;
197
- transform: translate(0, -50%);
325
+ transform: translate(var(--spacing-0), -50%);
198
326
  }
199
327
 
200
- /* Pe touch nu există hover real — nu lăsăm săgeata „blocată” după tap */
328
+ /* A touch screen has no real hover; do not leave the arrow stuck after a tap. */
201
329
  @media (hover: none) {
202
330
  .button--with-arrow:hover .button__label {
203
331
  transform: none;
204
332
  }
333
+
205
334
  .button--with-arrow:hover .button__arrow {
206
335
  opacity: 0;
207
336
  }
208
337
  }
209
-
210
- .button--outline {
211
- background-color: transparent;
212
- border: var(--border-width-2) solid var(--border-button-background-outline);
213
- color: var(--color-button-background-outline);
338
+
339
+ /* ============================================
340
+ SHAPE — icon-only
341
+ A circle around one icon. The diameter is not pinned, for the same reason
342
+ the labelled height is not: equal padding on every side plus the icon step
343
+ gives 8+16+8 = 32, 12+20+12 = 44 and 16+24+16 = 56. Only md sits level
344
+ with a labelled button beside it: the labelled heights are 33.5, 44 and
345
+ 54.5, so sm is 1.5px shorter and lg 1.5px taller. Both differences come
346
+ from the label's line box, which an icon does not have, and closing them
347
+ would need an off-scale padding. sm is below the 44px target, exactly as
348
+ the labelled sm is.
349
+
350
+ The padding stays on the spacing scale, which is rem, while the icon is on
351
+ the icon scale, which is px. So when a reader enlarges their text the
352
+ circle grows and the glyph does not -- the target gets bigger for the
353
+ reader a bigger target helps, and the shape stays round because the
354
+ padding is equal on both axes.
355
+
356
+ The compound selectors outrank the size classes whatever the source
357
+ order, and they carry the radius too, so a size class can never put
358
+ its own corner back. The slotted rule sizes a caller's icon to the step
359
+ even if it was given a size of its own: a 20px glyph in a 56px circle
360
+ reads as the wrong control, not as a choice.
361
+ ============================================ */
362
+ .button--icon-only {
363
+ line-height: var(--typography-lineHeight-none);
364
+ }
365
+ .button--icon-only.button--small {
366
+ --bd-button-icon-size: var(--icon-sm-size);
367
+ padding: var(--spacing-8);
368
+ border-radius: var(--radius-full);
369
+ }
370
+ .button--icon-only.button--medium {
371
+ --bd-button-icon-size: var(--icon-md-size);
372
+ padding: var(--spacing-12);
373
+ border-radius: var(--radius-full);
374
+ }
375
+ .button--icon-only.button--large {
376
+ --bd-button-icon-size: var(--icon-lg-size);
377
+ padding: var(--spacing-16);
378
+ border-radius: var(--radius-full);
379
+ }
380
+ .button--icon-only > ::slotted(*) {
381
+ height: var(--bd-button-icon-size);
382
+ }
383
+ /* loading swaps the icon for the spinner, so the spinner takes the icon's
384
+ box rather than its em size, and the circle does not shrink while busy */
385
+ .button--icon-only .spinner {
386
+ width: var(--bd-button-icon-size);
387
+ height: var(--bd-button-icon-size);
388
+ }
389
+
390
+ /* ============================================
391
+ VARIANT — primary
392
+ ============================================ */
393
+ .button--primary {
394
+ background-color: var(--bd-button-primary-bg);
395
+ color: var(--bd-button-primary-text);
396
+ }
397
+ .button--primary:hover {
398
+ background-color: var(--bd-button-primary-bg-hover);
399
+ }
400
+ .button--primary:active {
401
+ background-color: var(--bd-button-primary-bg-active);
214
402
  }
215
403
 
216
- .button--outline:hover {
217
- background-color: var(--button-background-outline-hover);
218
- border: var(--border-width-2) solid var(--border-button-background-outline-hover);
404
+ /* ============================================
405
+ VARIANT — secondary
406
+ ============================================ */
407
+ .button--secondary {
408
+ background-color: var(--bd-button-secondary-bg);
409
+ color: var(--bd-button-secondary-text);
410
+ }
411
+ .button--secondary:hover {
412
+ background-color: var(--bd-button-secondary-bg-hover);
413
+ }
414
+ .button--secondary:active {
415
+ background-color: var(--bd-button-secondary-bg-active);
219
416
  }
220
417
 
221
- .button--outline:active {
222
- background-color: var(--button-background-outline-focus);
223
- color: var(--color-neutral-0);
418
+ /* ============================================
419
+ VARIANT — tertiary (blue outline)
420
+ ============================================ */
421
+ .button--tertiary {
422
+ background-color: transparent;
423
+ --bd-button-edge: inset 0 0 0 var(--bd-button-border-width) var(--bd-button-tertiary-border);
424
+ color: var(--bd-button-tertiary-text);
425
+ }
426
+ .button--tertiary:hover {
427
+ background-color: var(--bd-button-tertiary-bg-hover);
428
+ --bd-button-edge: inset 0 0 0 var(--bd-button-border-width) var(--bd-button-tertiary-border-hover);
429
+ color: var(--bd-button-tertiary-text-hover);
430
+ }
431
+ .button--tertiary:active {
432
+ background-color: var(--bd-button-tertiary-bg-active);
433
+ --bd-button-edge: inset 0 0 0 var(--bd-button-border-width) var(--bd-button-tertiary-bg-active);
434
+ color: var(--bd-button-tertiary-text-active);
224
435
  }
225
436
 
226
- .button--primary--outline {
437
+ /* ============================================
438
+ VARIANT — ghost (dark outline)
439
+ ============================================ */
440
+ .button--ghost {
227
441
  background-color: transparent;
228
- border: var(--border-width-2) solid var(--border-button-background-primary-outline);
229
- color: var(--color-button-background-primary-outline);
442
+ --bd-button-edge: inset 0 0 0 var(--bd-button-border-width) var(--bd-button-ghost-border);
443
+ color: var(--bd-button-ghost-text);
444
+ }
445
+ .button--ghost:hover {
446
+ background-color: var(--bd-button-ghost-bg-hover);
447
+ color: var(--bd-button-ghost-text-hover);
448
+ }
449
+ .button--ghost:active {
450
+ background-color: var(--bd-button-ghost-bg-active);
451
+ --bd-button-edge: inset 0 0 0 var(--bd-button-border-width) var(--bd-button-ghost-bg-active);
452
+ color: var(--bd-button-ghost-text-active);
230
453
  }
231
454
 
232
- .button--primary--outline:hover {
233
- background-color: var(--button-background-primary-outline-hover);
234
- border: var(--border-width-2) solid var(--border-button-background-primary-outline-hover);
455
+ /* ============================================
456
+ VARIANT — accent
457
+ ============================================ */
458
+ .button--accent {
459
+ background-color: var(--bd-button-accent-bg);
460
+ color: var(--bd-button-accent-text);
461
+ --bd-button-edge: inset 0 0 0 var(--bd-button-border-width) var(--bd-button-accent-ring);
462
+ }
463
+ .button--accent:hover {
464
+ background-color: var(--bd-button-accent-bg-hover);
465
+ }
466
+ .button--accent:active {
467
+ background-color: var(--bd-button-accent-bg-active);
235
468
  }
236
469
 
237
- .button--primary--outline:active {
238
- background-color: var(--button-background-primary-outline-focus);
239
- color: var(--color-neutral-0);
470
+ /* ============================================
471
+ SURFACE — dark
472
+
473
+ For a hero or any panel with a full background colour. On a light page
474
+ every variant passes; on a coloured one 21 of 25 variant/surface pairings
475
+ failed, because tertiary and ghost put their ink straight onto the page
476
+ and primary is literally the same colour as a blue-500 hero (1.00:1).
477
+
478
+ The design carries no on-dark set — its axes are Size, Variant and State
479
+ only — so these values are derived from our own palette rather than read
480
+ off a spec, and every one is measured against blue-500, blue-600,
481
+ blue-700, neutral-900 and neutral-950. They need a designer's sign-off.
482
+
483
+ Two notes on what changed shape rather than just colour: ghost drops its
484
+ ring here, because a white ring would make it identical to tertiary, and
485
+ dropping it is what "ghost" conventionally means anyway. accent keeps its
486
+ red so the conversion signal survives, and gains a white ring to give it
487
+ a boundary against blue.
488
+
489
+ WHY THE INK IS A ROLE AND THE GROUNDS ARE NOT, which is what the inline
490
+ no role: markers below point at. check:color-coverage gained sight of
491
+ these declarations on 2026-09-15 and classified twenty-three of them; a
492
+ role of the right CATEGORY exists at the value for nineteen, and exactly
493
+ nine survive the second question, which is whether the role's JOB is this
494
+ declaration's job.
495
+
496
+ The nine that do are all ink, and each one matches a role's own words.
497
+ tertiary and ghost put their label straight onto the hero, and
498
+ --color-text-inverse is defined as the high-emphasis ink on an inverse
499
+ ground. Once a variant inverts and the label sits on the button's own
500
+ light fill, it is ordinary ink again -- --color-text-primary -- or brand
501
+ ink, --color-text-brand. disabled's label is a control the user cannot
502
+ operate, which is --color-text-disabled's whole definition rather than a
503
+ step on the hierarchy. Every one is value-identical, so nothing here
504
+ renders differently.
505
+
506
+ The grounds and hairlines have no role, and the reason is not scarcity.
507
+ --color-surface-default carries this exact white, and its own theme
508
+ clause in Foundations/Surfaces reads "On dark it is the dark ground, not
509
+ white" -- so adopting it here would assert the opposite of what the
510
+ declaration means. surface-subtle is a wash behind a group, not a press
511
+ fill. surface-muted is a state surface and would fit primary's pressed
512
+ step on value and nearly on job, but these three values are one ramp
513
+ measured against the hero rather than three independent choices, and
514
+ binding its last step to a role that can move on its own would break the
515
+ relationship the measurement established. At neutral-700 and neutral-600
516
+ there is no surface or border role at all, and there is no solid white
517
+ border role anywhere: --color-border-container-inverse is white at 12%.
518
+
519
+ So the missing vocabulary is nameable, and it is two entries: a control
520
+ fill on an inverse ground, and a solid hairline on an inverse ground.
521
+ Adding either is a vocabulary decision for the same designer pass this
522
+ block is already waiting on, and token-scales.js is explicit that one
523
+ consumer is not enough to name a role. Recorded, not taken.
524
+ ============================================ */
525
+ :host([surface='dark']) {
526
+ /* white fill, brand label — the strongest thing on a coloured hero */
527
+ --bd-button-primary-bg: var(--color-neutral-0); /* no role: on-dark ground; see the block note */
528
+ --bd-button-primary-bg-hover: var(--color-neutral-50); /* no role: on-dark ground; see the block note */
529
+ --bd-button-primary-bg-active: var(--color-neutral-100); /* no role: on-dark ground; see the block note */
530
+ --bd-button-primary-text: var(--color-text-brand);
531
+
532
+ /* neutral-100 rather than a lighter step: it is the lightest fill that
533
+ still clears 3:1 against a blue-500 hero while staying distinguishable
534
+ from primary's pure white */
535
+ --bd-button-secondary-bg: var(--color-neutral-100); /* no role: on-dark ground; see the block note */
536
+ --bd-button-secondary-bg-hover: var(--color-neutral-50); /* no role: on-dark ground; see the block note */
537
+ --bd-button-secondary-bg-active: var(--color-neutral-0); /* no role: on-dark ground; see the block note */
538
+ --bd-button-secondary-text: var(--color-text-primary);
539
+
540
+ /* the outlined one: white ring, white label, inverting on hover */
541
+ --bd-button-tertiary-text: var(--color-text-inverse);
542
+ --bd-button-tertiary-border: var(--color-neutral-0); /* no role: on-dark hairline; see the block note */
543
+ --bd-button-tertiary-bg-hover: var(--color-neutral-0); /* no role: on-dark ground; see the block note */
544
+ --bd-button-tertiary-text-hover: var(--color-text-brand);
545
+ --bd-button-tertiary-border-hover: var(--color-neutral-0); /* no role: on-dark hairline; see the block note */
546
+ --bd-button-tertiary-bg-active: var(--color-neutral-50); /* no role: on-dark ground; see the block note */
547
+ --bd-button-tertiary-text-active: var(--color-text-brand);
548
+
549
+ /* no ring at all, so it stays distinct from tertiary */
550
+ --bd-button-ghost-text: var(--color-text-inverse);
551
+ --bd-button-ghost-border: transparent;
552
+ --bd-button-ghost-bg-hover: var(--color-neutral-0); /* no role: on-dark ground; see the block note */
553
+ --bd-button-ghost-text-hover: var(--color-text-primary);
554
+ --bd-button-ghost-bg-active: var(--color-neutral-50); /* no role: on-dark ground; see the block note */
555
+ --bd-button-ghost-text-active: var(--color-text-primary);
556
+
557
+ /* unchanged red, plus a boundary against the hero */
558
+ --bd-button-accent-ring: var(--color-neutral-0);
559
+
560
+ /* muted downward instead of upward: a neutral-100 fill would read as an
561
+ active control on a dark hero. Exempt from contrast under WCAG 1.4.3. */
562
+ --bd-button-disabled-bg: var(--color-neutral-700); /* no role: on-dark ground; see the block note */
563
+ --bd-button-disabled-text: var(--color-text-disabled);
564
+ --bd-button-disabled-border: var(--color-neutral-600); /* no role: on-dark hairline; see the block note */
565
+
240
566
  }
241
567
 
242
- .button--small {
243
- padding: var(--spacing-8) var(--spacing-16);
244
- font-size: var(--spacing-14);
245
- font-weight: var(--typography-fontWeight-normal);
246
- font-family: var(--typography-fontFamily-sans);
247
- border-radius: var(--radius-md);
248
- min-height: var(--dimension-34px);
249
- min-width: 115px;
568
+ /* ============================================
569
+ STATE — disabled
570
+ Filled variants go grey; outlined ones keep a transparent fill and take
571
+ the subtle border. Contrast is exempt here under WCAG 1.4.3.
572
+ ============================================ */
573
+ .button:disabled,
574
+ .button[aria-disabled="true"] {
575
+ cursor: not-allowed;
576
+ pointer-events: none;
577
+ background-color: var(--bd-button-disabled-bg);
578
+ --bd-button-edge: 0 0 0 0 transparent;
579
+ color: var(--bd-button-disabled-text);
250
580
  }
251
581
 
252
- .button--medium {
253
- padding: var(--spacing-12) var(--spacing-20);
254
- font-size: var(--spacing-16);
255
- font-weight: var(--typography-fontWeight-normal);
256
- font-family: var(--typography-fontFamily-sans);
257
- border-radius: var(--radius-lg);
258
- min-height: var(--dimension-45px);
259
- min-width: 150px;
582
+ .button--tertiary:disabled,
583
+ .button--ghost:disabled,
584
+ .button--tertiary[aria-disabled="true"],
585
+ .button--ghost[aria-disabled="true"] {
586
+ background-color: transparent;
587
+ --bd-button-edge: inset 0 0 0 var(--bd-button-border-width) var(--bd-button-disabled-border);
588
+ color: var(--bd-button-disabled-text);
260
589
  }
261
590
 
262
- .button--large {
263
- padding: var(--spacing-16) var(--spacing-24);
264
- font-size: var(--spacing-18);
265
- font-weight: var(--typography-fontWeight-normal);
266
- font-family: var(--typography-fontFamily-sans);
267
- border-radius: var(--radius-lg);
268
- min-height: var(--dimension-55px);
269
- min-width: 150px;
591
+ /* ============================================
592
+ STATE — loading
593
+ The variant keeps its own colours, so the spinner is drawn in
594
+ currentColor and sized in em to track the type scale — which is what the
595
+ design's loading widths imply (they exceed the default by exactly one
596
+ font-size plus the gap).
597
+ ============================================ */
598
+ .button--loading {
599
+ cursor: progress;
600
+ pointer-events: none;
270
601
  }
271
602
 
272
- .button--rounded {
273
- border-radius: var(--radius-3xl);
603
+ .spinner {
604
+ width: 1em;
605
+ height: 1em;
606
+ flex: none;
607
+ box-sizing: border-box;
608
+ border: var(--border-width-2) solid currentColor;
609
+ border-top-color: transparent;
610
+ border-radius: var(--radius-full);
611
+ animation: bd-button-spin var(--transition-duration-slower)
612
+ var(--transition-easing-linear) infinite;
274
613
  }
275
614
 
276
- .button--bold {
277
- font: normal normal var(--typography-fontWeight-medium) var(--typography-fontSize-lg) / var(--dimension-24px) Roboto, sans-serif;
615
+ @keyframes bd-button-spin {
616
+ to { transform: rotate(360deg); }
278
617
  }
279
618
 
280
- /* slot-ul nu mai e copil direct al .button (e în .button__label) */
281
- .button ::slotted(*) {
619
+ /* The slot sits inside .button__label now, not directly in .button. */
620
+ .button__label > ::slotted(*) {
282
621
  display: inline-block;
283
- width: 100%;
284
622
  text-align: center;
285
623
  }
286
624
 
625
+ /* box-shadow is not rendered in forced-colors mode, which would leave the
626
+ outlined variants with no visible boundary at all, so a real border comes
627
+ back there. It costs 4px of height, which does not matter when the user
628
+ agent is repainting everything anyway. */
629
+ @media (forced-colors: active) {
630
+ .button--tertiary,
631
+ .button--ghost {
632
+ border: var(--bd-button-border-width) solid currentColor;
633
+ }
634
+ }
635
+
287
636
  @media (prefers-reduced-motion: reduce) {
288
637
  .button,
289
638
  .bd-contact-btn,
@@ -291,32 +640,53 @@ export default css`
291
640
  .button__arrow {
292
641
  transition: none !important;
293
642
  }
294
- }
295
643
 
644
+ /* a spinner that cannot spin should still read as busy, so it pulses
645
+ rather than freezing into a static broken ring */
646
+ .spinner {
647
+ animation: bd-button-pulse var(--transition-duration-slower)
648
+ var(--transition-easing-smooth) infinite alternate;
649
+ border-top-color: currentColor;
650
+ }
651
+
652
+ @keyframes bd-button-pulse {
653
+ to { opacity: var(--opacity-pulse); }
654
+ }
655
+ }
656
+ /* ============================================
657
+ VARIANT — white and outline-white
658
+
659
+ Fixed presets for a solid-colour banner, where even a surface="dark"
660
+ primary would sit too close in tone. They ignore surface on purpose —
661
+ see the note on VARIANTS in button.js.
662
+
663
+ These two were appended below the stylesheet's last rule and unindented,
664
+ and they hardcoded their colours instead of going through the aliases
665
+ every other variant uses: 1.5px against the 2px border width the docs
666
+ describe, #ffffff8c, and two rgba() whites. None of it could be rethemed
667
+ and none of it was visible to the lint, which does not read 8-digit hex
668
+ or rgba().
669
+ ============================================ */
296
670
  .button--white {
297
- background-color: var(--color-neutral-0);
298
- color: var(--color-blue-500);
671
+ background-color: var(--bd-button-white-bg);
672
+ color: var(--bd-button-white-text);
299
673
  }
300
-
301
674
  .button--white:hover {
302
- background-color: var(--color-blue-50);
675
+ background-color: var(--bd-button-white-bg-hover);
303
676
  }
304
-
305
677
  .button--white:active {
306
- background-color: var(--color-blue-100);
678
+ background-color: var(--bd-button-white-bg-active);
307
679
  }
308
680
 
309
681
  .button--outline-white {
310
682
  background-color: transparent;
311
- box-shadow: inset 0 0 0 1.5px #ffffff8c;
312
- color: var(--color-neutral-0);
683
+ --bd-button-edge: inset 0 0 0 var(--bd-button-border-width) var(--bd-button-outline-white-border);
684
+ color: var(--bd-button-outline-white-text);
313
685
  }
314
-
315
686
  .button--outline-white:hover {
316
- background-color: rgba(255, 255, 255, 0.1);
687
+ background-color: var(--bd-button-outline-white-bg-hover);
317
688
  }
318
-
319
689
  .button--outline-white:active {
320
- background-color: rgba(255, 255, 255, 0.2);
690
+ background-color: var(--bd-button-outline-white-bg-active);
321
691
  }
322
- `;
692
+ `;