@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
@@ -55,7 +55,7 @@ prin \`ResizeObserver\` — fără a fi necesară setarea manuală a \`max-width
55
55
 
56
56
  <bd-button-link
57
57
  slot="cta"
58
- kind="danger"
58
+ variant="accent"
59
59
  size="md"
60
60
  href="https://www.bitdefender.com/buy"
61
61
  label="Cumpără acum"
@@ -111,6 +111,18 @@ nu-i o valoare universală, depinde de conținutul acelui header.
111
111
  ### Slot \`cta\`
112
112
  Orice element cu \`slot="cta"\` înlocuiește butonul CTA fallback.
113
113
  Pe mobile devine automat full-width prin \`::slotted([slot="cta"])\`.
114
+
115
+ ---
116
+
117
+ ### Accesibilitate
118
+ Este **navigație**, nu un set de tab-uri: linkurile duc la secțiuni care există
119
+ deja în pagină. De aceea folosește \`<nav>\` + linkuri + \`aria-current="true"\`
120
+ pe cel activ — nu \`role="tablist"\` / \`aria-selected\`, care înseamnă
121
+ "panoul afișat acum". Pentru un strip de tab-uri reale vezi **Components/Tab List**.
122
+
123
+ Pe mobile, lista devine un **disclosure** (APG Disclosure Navigation Menu):
124
+ butonul poartă \`aria-expanded\` + \`aria-controls\`, iar panoul conține un
125
+ \`<ul>\` de linkuri reale. \`Escape\` închide panoul și readuce focusul pe buton.
114
126
  `
115
127
  }
116
128
  }
@@ -161,12 +173,11 @@ const renderWithSlotCta = (labels, ctaLabel = "Cumpără acum", ctaHref = "#sect
161
173
  ${navItems(labels)}
162
174
  <bd-button-link
163
175
  slot="cta"
164
- kind="danger"
176
+ variant="accent"
165
177
  size="md"
166
178
  href=${ctaHref}
167
179
  label=${ctaLabel}
168
- font-size="16px"
169
- font-weight="600"
180
+ font-size="base"
170
181
  buyLink
171
182
  >${ctaLabel}</bd-button-link>
172
183
  </bd-anchor-nav>
@@ -193,7 +204,7 @@ const withSiblingContent = (navTemplate) => html`
193
204
  border-radius: 8px;
194
205
  text-align: center;
195
206
  color: #1e40af;
196
- font-family: sans-serif;
207
+ font-family: var(--typography-fontFamily-sans);
197
208
  ">
198
209
  <strong>Sibling content — 900px max-width</strong><br>
199
210
  <span style="font-size: 0.875rem; opacity: 0.8;">
@@ -237,12 +248,11 @@ export const WithSlotCtaOutline = {
237
248
  ${navItems(["Overview", "Features", "Pricing"])}
238
249
  <bd-button-link
239
250
  slot="cta"
240
- kind="outline"
251
+ variant="ghost"
241
252
  size="md"
242
253
  href="https://www.bitdefender.com/buy"
243
254
  label="Cumpără acum"
244
- font-size="16px"
245
- font-weight="600"
255
+ font-size="base"
246
256
  >Cumpără acum</bd-button-link>
247
257
  </bd-anchor-nav>
248
258
  `,
@@ -383,7 +393,7 @@ export const WithScrollTargets = {
383
393
  background: #EDF9FF; border-bottom: 1px solid #e2e8f0;
384
394
  ">
385
395
  <bd-h as="h2">Overview Section</bd-h>
386
- <bd-p kind="regular">
396
+ <bd-p variant="regular">
387
397
  Navul de mai sus se aliniază automat la lățimea acestui container (800px).
388
398
  Scroll în jos pentru a vedea sticky și scroll spy în acțiune.
389
399
  </bd-p>
@@ -394,7 +404,7 @@ export const WithScrollTargets = {
394
404
  background: #fff; border-bottom: 1px solid #e2e8f0;
395
405
  ">
396
406
  <bd-h as="h2">Features Section</bd-h>
397
- <bd-p kind="regular">Conținut Features. Link-ul din nav devine activ când ajungi aici.</bd-p>
407
+ <bd-p variant="regular">Conținut Features. Link-ul din nav devine activ când ajungi aici.</bd-p>
398
408
  </div>
399
409
 
400
410
  <div id="anchor-3-section" style="
@@ -402,14 +412,14 @@ export const WithScrollTargets = {
402
412
  background: #EDF9FF; border-bottom: 1px solid #e2e8f0;
403
413
  ">
404
414
  <bd-h as="h2">Pricing Section</bd-h>
405
- <bd-p kind="regular">Conținut Pricing.</bd-p>
415
+ <bd-p variant="regular">Conținut Pricing.</bd-p>
406
416
  </div>
407
417
 
408
418
  <div id="section-pricing" style="
409
419
  min-height: 40vh; padding: 80px 24px; background: #fff;
410
420
  ">
411
421
  <bd-h as="h2">Buy Now Target</bd-h>
412
- <bd-p kind="regular">Butonul CTA scrollează până aici.</bd-p>
422
+ <bd-p variant="regular">Butonul CTA scrollează până aici.</bd-p>
413
423
  </div>
414
424
 
415
425
  </div>
@@ -0,0 +1,58 @@
1
+ import { css } from 'lit';
2
+
3
+ /** Styled entirely from design tokens — see npm run lint:tokens. */
4
+ export const annotationCSS = css`
5
+ :host { display: inline; }
6
+
7
+ .footnote {
8
+ font-size: var(--footnote-reference-fontSize);
9
+ font-weight: var(--footnote-reference-fontWeight);
10
+ line-height: var(--footnote-reference-lineHeight);
11
+ vertical-align: var(--footnote-reference-verticalAlign);
12
+ color: var(--footnote-reference-color);
13
+ margin-left: var(--footnote-reference-marginLeft);
14
+ margin-right: var(--footnote-reference-marginRight);
15
+ text-decoration: none;
16
+ }
17
+
18
+ .citation {
19
+ font-size: var(--citation-reference-fontSize);
20
+ font-weight: var(--citation-reference-fontWeight);
21
+ line-height: var(--citation-reference-lineHeight);
22
+ color: var(--citation-reference-color);
23
+ text-decoration: var(--citation-reference-textDecoration);
24
+ }
25
+
26
+ .citation:hover {
27
+ color: var(--citation-reference-hover-color);
28
+ text-decoration: var(--citation-reference-hover-textDecoration);
29
+ }
30
+
31
+ .citation:focus-visible,
32
+ .footnote:focus-visible {
33
+ /* the one focus ring — see Foundations/Focus. A two-colour ring whose
34
+ white inner band keeps it visible on a coloured or dark surface, which
35
+ a single-colour outline cannot do. */
36
+ outline: none;
37
+ box-shadow: var(--focus-outline-primary);
38
+ border-radius: var(--focus-outline-radius);
39
+ }
40
+
41
+ .sup {
42
+ font-size: var(--math-superscript-fontSize);
43
+ font-weight: var(--math-superscript-fontWeight);
44
+ line-height: var(--math-superscript-lineHeight);
45
+ vertical-align: var(--math-superscript-verticalAlign);
46
+ margin-left: var(--math-superscript-marginLeft);
47
+ }
48
+
49
+ .sub {
50
+ font-size: var(--math-subscript-fontSize);
51
+ font-weight: var(--math-subscript-fontWeight);
52
+ line-height: var(--math-subscript-lineHeight);
53
+ vertical-align: var(--math-subscript-verticalAlign);
54
+ margin-left: var(--math-subscript-marginLeft);
55
+ }
56
+ `;
57
+
58
+ export default annotationCSS;
@@ -0,0 +1,67 @@
1
+ import { LitElement, html, nothing } from 'lit';
2
+ // Installs the design tokens into document scope; see src/tokens/tokens.js
3
+ import '../../tokens/tokens.js';
4
+ import { annotationCSS } from './annotation.css.js';
5
+
6
+ export class BdFootnote extends LitElement {
7
+ static styles = [annotationCSS];
8
+
9
+ static properties = {
10
+ href: { type: String }
11
+ };
12
+
13
+ constructor() {
14
+ super();
15
+ this.href = '';
16
+ }
17
+
18
+ render() {
19
+ return html`
20
+ <a class="footnote" href=${this.href || nothing}><slot></slot></a>
21
+ `;
22
+ }
23
+ }
24
+
25
+ export class BdCitation extends LitElement {
26
+ static styles = [annotationCSS];
27
+
28
+ static properties = {
29
+ href: { type: String }
30
+ };
31
+
32
+ constructor() {
33
+ super();
34
+ this.href = '';
35
+ }
36
+
37
+ render() {
38
+ return html`
39
+ <a class="citation" href=${this.href || nothing}><slot></slot></a>
40
+ `;
41
+ }
42
+ }
43
+
44
+ export class BdSup extends LitElement {
45
+ static styles = [annotationCSS];
46
+
47
+ render() {
48
+ return html`
49
+ <sup class="sup"><slot></slot></sup>
50
+ `;
51
+ }
52
+ }
53
+
54
+ export class BdSub extends LitElement {
55
+ static styles = [annotationCSS];
56
+
57
+ render() {
58
+ return html`
59
+ <sub class="sub"><slot></slot></sub>
60
+ `;
61
+ }
62
+ }
63
+
64
+ customElements.define('bd-footnote', BdFootnote);
65
+ customElements.define('bd-citation', BdCitation);
66
+ customElements.define('bd-sup', BdSup);
67
+ customElements.define('bd-sub', BdSub);
@@ -0,0 +1,63 @@
1
+ import { html } from 'lit';
2
+ import './annotation.js';
3
+
4
+ export default {
5
+ title : 'Atoms/Annotation',
6
+ tags : ['autodocs'],
7
+ parameters: {
8
+ docs: {
9
+ description: {
10
+ component: `
11
+ Four small elements for references and maths inside prose.
12
+
13
+ - \`<bd-footnote>\` — a superscript reference marker, optionally linked
14
+ - \`<bd-citation>\` — a source reference, optionally linked
15
+ - \`<bd-sup>\` / \`<bd-sub>\` — superscript and subscript that do **not** disturb
16
+ the line box
17
+
18
+ ### Usage
19
+ \`\`\`html
20
+ Detections rose sharply<bd-footnote href="#n1">1</bd-footnote> last quarter.
21
+
22
+ <bd-citation href="https://example.com/report">Threat Landscape 2026</bd-citation>
23
+
24
+ The formula is CO<bd-sub>2</bd-sub> and the unit is m<bd-sup>3</bd-sup>.
25
+ \`\`\`
26
+
27
+ ### Props
28
+ | Prop | Applies to | Default |
29
+ |---|---|---|
30
+ | \`href\` | \`bd-footnote\` and \`bd-citation\`. Omit to render unlinked. | \`''\` |
31
+
32
+ \`bd-sup\` and \`bd-sub\` take no props. All four take their content from the
33
+ default slot.
34
+
35
+ ### Why not plain sup and sub
36
+ The browser's own \`sup\` and \`sub\` shift text with \`vertical-align\`, which grows
37
+ the line box — an annotated line then sits further from its neighbours than the
38
+ rest of the paragraph. These set their own font size and use a relative offset
39
+ instead, so leading stays even down the column.
40
+ `
41
+ }
42
+ }
43
+ },
44
+ argTypes: {
45
+ href: {
46
+ control : 'text',
47
+ description: 'Destination for bd-footnote and bd-citation. Omit to render unlinked.',
48
+ table : { type: { summary: 'string' }, defaultValue: { summary: "" }, category: 'Navigation' }
49
+ }
50
+ }
51
+ };
52
+
53
+ export const Footnote = () => html`
54
+ Blocks 99.8% of threats<bd-footnote href="#n1">1</bd-footnote>
55
+ `;
56
+
57
+ export const Citation = () => html`
58
+ See the <bd-citation href="#">2026 Threat Report</bd-citation>.
59
+ `;
60
+
61
+ export const Maths = () => html`
62
+ E = mc<bd-sup>2</bd-sup> · H<bd-sub>2</bd-sub>O
63
+ `;
@@ -0,0 +1,285 @@
1
+ import { html } from 'lit';
2
+ import { docsPage, refSection } from '../tokens/story-chrome.js';
3
+
4
+ /**
5
+ * The canonical layer model, written so it can be read without knowing the
6
+ * P5/P6 remediation history.
7
+ *
8
+ * Documentation only: this file renders no product component and owns no
9
+ * contract. It is filed under its own group rather than under `Atoms/` or
10
+ * `Components/` on purpose -- `lint:tokens` reads the atom tier from a story's
11
+ * `title`, and `verify:typography` builds its population from the same two
12
+ * prefixes, so a documentation page filed under either would either claim to
13
+ * be vocabulary or add itself to a contract gate.
14
+ */
15
+ export default {
16
+ title: 'Foundations/Layer Model',
17
+ tags : ['autodocs']
18
+ };
19
+
20
+ const LAYERS = [
21
+ {
22
+ layer: 'Foundations',
23
+ owns : 'Design tokens, the scales they are read through, semantic roles, and the governance that keeps them honest.',
24
+ is : 'Values and the rules for choosing between them. Nothing here renders product UI.',
25
+ isNot: 'A place for components. A token is not a component with one property.',
26
+ here : '--color-*, --spacing-* / --dimension-*, --status-*, --focus-*, --indicator-*, the typography roles, ' +
27
+ 'token-scales.js, and the Design Tokens pages that document them.',
28
+ rule: 'Never a literal where a token exists; never a token from the wrong category; never a fallback for a design token.'
29
+ },
30
+ {
31
+ layer: 'Atoms',
32
+ owns : 'Published single-responsibility UI vocabulary, each with its own semantic and accessibility contract.',
33
+ is : 'One responsibility, documentable on its own, meaningful to a consumer outside this repository. ' +
34
+ 'An atom may own behaviour -- a checkbox has state, bd-back navigates -- as long as the behaviour is its ' +
35
+ 'own responsibility rather than the orchestration of other UI objects.',
36
+ isNot: 'Anything that is merely small. Anything whose job is to arrange other objects.',
37
+ here : 'bd-h, bd-p, bd-link, bd-button, bd-badge, bd-divider-*, bd-img, the icon family, the form controls, ' +
38
+ 'bd-alert, bd-progress, bd-tooltip, bd-back, bd-visually-hidden.',
39
+ rule: 'In-repo reuse is NOT a requirement. See "Zero consumers" below.'
40
+ },
41
+ {
42
+ layer: 'Components',
43
+ owns : 'Reusable composed UI objects: several responsibilities together, or real behaviour and state, ' +
44
+ 'still meaningful outside any one page section.',
45
+ is : 'A UI object a page can use more than once, in more than one place.',
46
+ isNot: 'Something classified here merely because it contains another custom element. Containment is not composition.',
47
+ here : 'bd-accordion, bd-tabs, bd-tab-list, bd-modal, bd-carousel, bd-video-player, bd-breadcrumb, ' +
48
+ 'bd-page-switcher, bd-anchor-nav, bd-compatibility-table, bd-quick-answer, bd-card-item, bd-terminal-message.',
49
+ rule: 'A component is not required to be built only from atoms. Local implementation is often correct.'
50
+ },
51
+ {
52
+ layer: 'Modules',
53
+ owns : 'Page-level compositions whose responsibility is a meaningful content or marketing section.',
54
+ is : 'A section of a page: usually one instance per page, with a title, a description and a body it owns.',
55
+ isNot: 'A reusable primitive. Do not split a module into invented components to improve a composition metric.',
56
+ here : 'bd-trust-panel, bd-process-steps, bd-overview, bd-cta-banner, bd-comparison-panel, bd-agent-endpoints, ' +
57
+ 'bd-awards-section (and its two variants), bd-terms-section, bd-bento-grid, bd-card-features-section.',
58
+ rule: 'Modules MAY compose atoms directly. They do so today and it is correct -- see "Modules and atoms" below.'
59
+ },
60
+ {
61
+ layer: 'Layout',
62
+ owns : 'Reusable layout responsibility, where one genuinely exists.',
63
+ is : 'An API that expresses arrangement -- columns, gap, alignment -- and carries no content semantics.',
64
+ isNot: 'A wrapper around display:flex. A section that happens to use a grid internally is a Module, not Layout.',
65
+ here : 'bd-grid, and today nothing else. bd-bento-grid is a Module: it takes eyebrow, title and description, ' +
66
+ 'so it arranges content it also owns.',
67
+ rule: 'Layout stays local CSS unless a stable arrangement responsibility is demonstrated with evidence.'
68
+ },
69
+ {
70
+ layer: 'Internal primitives',
71
+ owns : 'Reusable implementation mechanisms that are deliberately NOT public UI vocabulary.',
72
+ is : 'A keyboard map, a resolver, a derived formula, a base class, a shared stylesheet fragment.',
73
+ isNot: 'An atom. These have no element, no story and no public contract, and that is the point.',
74
+ here : 'shared/form-field.css.js (control height = padding·2 + fontSize × lineHeight), shared/token-scales.js, ' +
75
+ 'shared/prop-vocabulary.js (size · variant · tone), accordion/accordion-keyboard.js, ' +
76
+ 'icons/icon-element.js (BdIconElement).',
77
+ rule: 'Prefer this over a public atom when the shared thing is a mechanism rather than a UI object. ' +
78
+ 'It is the layer with the best record here: five primitives, all healthy, no public surface.'
79
+ }
80
+ ];
81
+
82
+ const layerTable = () => html`
83
+ <table class="ref">
84
+ <thead>
85
+ <tr><th>Layer</th><th>Owns</th><th>What belongs</th><th>What does not</th></tr>
86
+ </thead>
87
+ <tbody>
88
+ ${LAYERS.map(l => html`
89
+ <tr>
90
+ <td><strong>${l.layer}</strong></td>
91
+ <td>${l.owns}</td>
92
+ <td>${l.is}<br><em>${l.here}</em></td>
93
+ <td>${l.isNot}<br><strong>Rule:</strong> ${l.rule}</td>
94
+ </tr>
95
+ `)}
96
+ </tbody>
97
+ </table>
98
+ `;
99
+
100
+ const COMPOSITION = [
101
+ ['An existing atom MUST be used',
102
+ 'Heading or body copy (bd-h / bd-p -- already used by 22 and 21 components), an inline navigational link, ' +
103
+ 'a tintable interface icon that already exists in icons/, or a form control.'],
104
+ ['Local implementation is correct',
105
+ 'Layout. Chrome controls that carry no variant contract -- a modal close, a footer nav toggle. ' +
106
+ 'Marks a control owns, like a checkbox tick or a play triangle. Decorative artwork. Anything the ' +
107
+ 'component’s own behaviour owns.'],
108
+ ['Repeated responsibility triggers an atom review',
109
+ 'When the same responsibility -- not the same markup -- appears in THREE independent non-frozen components ' +
110
+ 'and they agree on semantics and accessibility. Three, not two: at two, this library has consistently been ' +
111
+ 'better off leaving it local.'],
112
+ ['Shared behaviour belongs in an internal primitive',
113
+ 'When the shared thing is a mechanism rather than a UI object. accordion-keyboard.js is the model: two item ' +
114
+ 'classes share one keyboard contract with no element and no public API.'],
115
+ ['Modules may compose atoms directly',
116
+ 'Yes. Do not invent a wrapper component so a section only ever touches components.'],
117
+ ['Layout stays CSS, or becomes vocabulary',
118
+ 'It stays CSS unless it encodes a stable arrangement responsibility with a token behind it. ' +
119
+ '165 flex and 187 gap declarations across 52 files are shorthand, not a responsibility.'],
120
+ ['Evidence required for a new Atom',
121
+ 'A clear single responsibility; coherent accessibility ownership; an API that can stay small; ' +
122
+ 'parents that do not need extensive overrides to reproduce today’s behaviour; and it must remove ' +
123
+ 'duplicated behaviour or semantics rather than duplicated markup.'],
124
+ ['Evidence required for a new Component',
125
+ 'Two or more genuinely distinct uses, behaviour or composition beyond a single atom responsibility, ' +
126
+ 'and meaning outside one page section.'],
127
+ ['Evidence required for a new Module',
128
+ 'A real page section with content it owns. Modules are written, not abstracted.'],
129
+ ['PRODUCT_FROZEN',
130
+ 'pricing-cards is frozen by product decision. Report findings there; change nothing. It is the largest local ' +
131
+ 'reimplementer in the library and none of it is actionable.']
132
+ ];
133
+
134
+ const A11Y = [
135
+ ['role', 'The atom, wherever an atom exists. bd-alert owns alert/status, bd-progress owns progressbar, bd-tooltip owns tooltip.'],
136
+ ['accessible name', 'The atom that renders the control. Where a label can be empty, the host forwards aria-label to the real control -- bd-back is the worked example.'],
137
+ ['keyboard behaviour', 'The component. Shared keyboard contracts live in an internal primitive, not an atom.'],
138
+ ['focus behaviour', 'The component. The visual focus owner and the DOM focus owner may differ deliberately: the accordion paints the ring on the whole item while the button stays the focus target.'],
139
+ ['ARIA value semantics', 'Whoever genuinely has a value. A component whose geometry is not proportional to its value should not claim a value role -- see below.'],
140
+ ['live regions', 'The atom that owns the message. Two components independently implementing the same live-region rule is duplication, not defence.']
141
+ ];
142
+
143
+ export const LayerModel = () =>
144
+ docsPage({
145
+ title: 'Layer model',
146
+ lede : 'Foundations, Atoms, Components, Modules, Layout, and internal primitives — what each one owns in ' +
147
+ 'this repository, with the rules for adding to them. Derived from the library as it stands, not from a ' +
148
+ 'textbook hierarchy.',
149
+ note: html`This page is documentation. It is filed under its own group because
150
+ <code>lint:tokens</code> reads the atom tier from a story&rsquo;s <code>title</code>, and
151
+ <code>verify:typography</code> builds its population from the <code>Atoms/</code> and
152
+ <code>Components/</code> prefixes — so where a page is filed changes what the gates believe.`,
153
+ children: html`
154
+ ${refSection({ name: 'The six layers', meta: 'what belongs where', children: layerTable() })}
155
+
156
+ ${refSection({
157
+ name : 'Composition contract',
158
+ meta : 'when to reach for an atom, and when not to',
159
+ children: html`
160
+ <table class="ref">
161
+ <thead><tr><th>Question</th><th>Answer</th></tr></thead>
162
+ <tbody>${COMPOSITION.map(([q, a]) => html`<tr><td><strong>${q}</strong></td><td>${a}</td></tr>`)}</tbody>
163
+ </table>
164
+ <p><strong>One rule this system deliberately does NOT have:</strong> &ldquo;components must be composed only
165
+ from atoms&rdquo;. The evidence does not support it. The median component here composes two atoms and
166
+ implements the rest locally, and that is usually the right answer rather than a defect.</p>
167
+ `
168
+ })}
169
+
170
+ ${refSection({
171
+ name : 'Accessibility ownership',
172
+ meta : 'who owns which contract',
173
+ children: html`
174
+ <table class="ref">
175
+ <thead><tr><th>Responsibility</th><th>Owner</th></tr></thead>
176
+ <tbody>${A11Y.map(([r, o]) => html`<tr><td><strong>${r}</strong></td><td>${o}</td></tr>`)}</tbody>
177
+ </table>
178
+ <p>Used as a test: <strong>an abstraction that cannot clearly own its accessibility responsibility is
179
+ probably not an atom.</strong></p>
180
+ `
181
+ })}
182
+
183
+ ${refSection({
184
+ name : 'Misleading visual similarity',
185
+ meta : 'the negative example, kept on purpose',
186
+ children: html`
187
+ <p><code>bd-progress</code> and <code>compare-bar</code> both draw a coloured horizontal bar in a rounded
188
+ track with a label. They share no responsibility, and the measurement is what proves it.</p>
189
+ <table class="ref">
190
+ <thead><tr><th></th><th>bd-progress</th><th>compare-bar</th></tr></thead>
191
+ <tbody>
192
+ <tr><td>fill width vs value</td><td>64 &rarr; 64.0%, 30 &rarr; 30.0%, 100 &rarr; 100.0% — <strong>width is the value</strong></td>
193
+ <td>5.59 &rarr; 86.3%, <strong>5.89 &rarr; 71.4%</strong> — <strong>not even monotonic</strong></td></tr>
194
+ <tr><td>why</td><td>value / max, linear</td>
195
+ <td>per-card reference score through a gamma-shaped stretch; <code>variant="primary"</code> is pinned at 100%</td></tr>
196
+ <tr><td>ARIA</td><td><code>role="progressbar"</code> with <code>aria-valuenow/min/max</code></td>
197
+ <td>no role; the value reaches the tree only as a sentence on a generic node</td></tr>
198
+ <tr><td>track</td><td>8px, label above it</td><td>48px row, label and score inside the fill</td></tr>
199
+ <tr><td>colour</td><td><code>--status-*-accent</code> — tone carries meaning</td>
200
+ <td><code>--cs-bar-primary-bg</code> — brand and theme identity</td></tr>
201
+ </tbody>
202
+ </table>
203
+ <p>The compare section says so in its own visible copy: <em>&ldquo;Bar lengths are scaled for visibility
204
+ between brands.&rdquo;</em> One is a measurement; the other is deliberately not. A shared
205
+ &ldquo;track + fill&rdquo; primitive would have to make them agree about the only thing that matters, and it
206
+ could not own value semantics for both. <strong>So there is no shared primitive, and this pair is the standing
207
+ reminder that appearance does not establish responsibility.</strong></p>
208
+ `
209
+ })}
210
+
211
+ ${refSection({
212
+ name : 'Zero consumers does not mean dead',
213
+ meta : 'why the atom tier looks unused',
214
+ children: html`
215
+ <p>33 of the 65 elements filed under <code>Atoms/</code> have <strong>no consumer inside this
216
+ repository</strong>. None of them is dead: 62 of 65 are reachable from the package&rsquo;s public exports, and
217
+ the consumers of this library are external pages.</p>
218
+ <p>The <code>Atoms/</code> tier is a <strong>published vocabulary and documentation layer</strong> before it is
219
+ an internal composition layer. Every form atom sits in this group — coherently, because this package ships
220
+ forms while its own marketing components contain none.</p>
221
+ <p><strong>Do not delete or demote an atom on consumer count.</strong> The question is whether it owns a
222
+ coherent responsibility and contract, not whether anything here happens to call it.</p>
223
+ `
224
+ })}
225
+
226
+ ${refSection({
227
+ name : 'Where classification lives',
228
+ meta : 'and why it is not the Storybook title',
229
+ children: html`
230
+ <p>A unit&rsquo;s layer is recorded in <code>scripts/architecture.json</code>, keyed on its
231
+ <strong>source path</strong>. Both governance gates read it from there: <code>lint:tokens</code> asks which
232
+ files are atom-tier, and <code>verify:typography</code> asks which stories are a typography contract.</p>
233
+ <table class="ref">
234
+ <thead><tr><th>Rule</th><th>Why</th></tr></thead>
235
+ <tbody>
236
+ <tr><td><strong>Architecture layer &ne; Storybook navigation path</strong></td>
237
+ <td>Both gates used to read the layer out of the title. Filing the module stories under
238
+ <code>Modules/</code> would have taken the typography population from 572 stories to 479 with the
239
+ gate still green. A presentation name must never decide what gets enforced.</td></tr>
240
+ <tr><td><strong>Architecture layer &ne; gate participation</strong></td>
241
+ <td>Two separate fields. <code>src/components/atoms.stories.js</code> is <code>FOUNDATION</code> and
242
+ <code>typography: true</code>: documentation by responsibility, but it renders real atoms at real
243
+ sizes, so it is still a typography contract.</td></tr>
244
+ <tr><td><strong>A Module is not an exemption</strong></td>
245
+ <td>Every <code>MODULE</code> unit is <code>typography: true</code>. Page-level composition still has
246
+ headings and body copy with real leading.</td></tr>
247
+ <tr><td><strong>A new Atom or Component</strong></td>
248
+ <td>Add one entry for its directory. Until then <code>check:architecture</code> fails with
249
+ <em>unclassified</em> — there is deliberately no fallback entry for <code>src/components</code>,
250
+ because a fallback would silently classify the next thing somebody adds.</td></tr>
251
+ <tr><td><strong>When a Storybook title changes</strong></td>
252
+ <td>Nothing happens to enforcement, and that has now been done rather than argued.
253
+ P6D.3 moved 35 titles into this taxonomy — <code>bd-tab-list</code> from
254
+ <code>Atoms/</code> to <code>Components/</code>, <code>bd-grid</code> to <code>Layout/</code>,
255
+ thirteen page-level sections to <code>Modules/</code> — and the typography population stayed at
256
+ 572 stories, the same 572, with atom-tier enforcement unchanged at 132 files.</td></tr>
257
+ <tr><td><strong>Stale and missing entries</strong></td>
258
+ <td>Checked both ways, like <code>breakpoint-exceptions.json</code>: an entry whose path has gone
259
+ fails as <em>stale</em>, a shipped file with no entry fails as <em>unclassified</em>, and an invalid
260
+ layer or a non-boolean flag fails too. <code>check:architecture --negative-control</code> proves each
261
+ one still fails.</td></tr>
262
+ <tr><td><strong>The population floor</strong></td>
263
+ <td><code>typographyPopulationFloor</code> records how many stories the gate must cover. It fails
264
+ below and reports above, so a gate can no longer quietly check less — a reduction has to be argued
265
+ for in a diff.</td></tr>
266
+ </tbody>
267
+ </table>
268
+ `
269
+ })}
270
+
271
+ ${refSection({
272
+ name : 'Modules and atoms',
273
+ meta : 'already true, not a proposal',
274
+ children: html`
275
+ <p>The AI Guardian landing demo composes atoms directly and heavily: <code>bd-p</code> 19 times,
276
+ <code>bd-link</code> 18, <code>bd-button-link</code> 6, <code>bd-divider-vertical</code> 4, plus the icon
277
+ family — alongside modules such as <code>bd-trust-panel</code>, <code>bd-process-steps</code> and
278
+ <code>bd-cta-banner</code>.</p>
279
+ <p>A page-level composition reaching for a heading or a link is not a layering violation. Requiring modules to
280
+ go through components would add wrappers that carry no responsibility.</p>
281
+ `
282
+ })}
283
+ `
284
+ });
285
+ LayerModel.storyName = 'Layer model';