@godxjp/ui 31.31.8 → 32.0.1

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 (732) hide show
  1. package/README.md +102 -121
  2. package/agent/START-HERE.md +10 -10
  3. package/agent/components/Accordion.json +2 -2
  4. package/agent/components/AccountChip.json +1 -1
  5. package/agent/components/Actions.json +1 -1
  6. package/agent/components/Activity.json +2 -2
  7. package/agent/components/Affix.json +1 -1
  8. package/agent/components/Alert.json +22 -6
  9. package/agent/components/AlertDialog.json +8 -1
  10. package/agent/components/Anchor.json +4 -3
  11. package/agent/components/AppLauncher.json +2 -2
  12. package/agent/components/AppProvider.json +19 -11
  13. package/agent/components/AppSettingPicker.json +18 -2
  14. package/agent/components/AppShell.json +4 -5
  15. package/agent/components/AreaChart.json +0 -1
  16. package/agent/components/AspectRatio.json +2 -2
  17. package/agent/components/Attachments.json +3 -3
  18. package/agent/components/AuthAccountSummary.json +1 -1
  19. package/agent/components/AuthDivider.json +1 -1
  20. package/agent/components/AuthExpiryProvider.json +0 -1
  21. package/agent/components/AuthFooter.json +2 -2
  22. package/agent/components/AuthIdentity.json +3 -3
  23. package/agent/components/AuthStack.json +1 -1
  24. package/agent/components/Avatar.json +2 -12
  25. package/agent/components/Badge.json +1 -1
  26. package/agent/components/BarChart.json +0 -1
  27. package/agent/components/BranchScopePicker.json +1 -1
  28. package/agent/components/Breadcrumb.json +1 -1
  29. package/agent/components/Button.json +3 -3
  30. package/agent/components/Calendar.json +1 -1
  31. package/agent/components/Card.json +2 -2
  32. package/agent/components/CardBar.json +0 -1
  33. package/agent/components/CardContent.json +0 -1
  34. package/agent/components/Carousel.json +4 -3
  35. package/agent/components/Cascader.json +1 -1
  36. package/agent/components/CenteredShell.json +78 -17
  37. package/agent/components/ChatBubble.json +3 -3
  38. package/agent/components/ChatBubbleList.json +3 -3
  39. package/agent/components/ChatComposer.json +3 -3
  40. package/agent/components/ChatSuggestion.json +3 -3
  41. package/agent/components/Checkbox.json +1 -1
  42. package/agent/components/CheckboxGroup.json +0 -1
  43. package/agent/components/CodeBlock.json +1 -1
  44. package/agent/components/Collapsible.json +4 -4
  45. package/agent/components/ColorPicker.json +1 -1
  46. package/agent/components/Command.json +5 -5
  47. package/agent/components/CommandPalette.json +1 -1
  48. package/agent/components/CompactBarTrend.json +1 -1
  49. package/agent/components/Conversations.json +3 -3
  50. package/agent/components/CredentialReveal.json +1 -1
  51. package/agent/components/DataState.json +2 -2
  52. package/agent/components/DataTable.json +1 -1
  53. package/agent/components/DatePicker.json +1 -1
  54. package/agent/components/Descriptions.json +1 -1
  55. package/agent/components/Dialog.json +2 -2
  56. package/agent/components/DraggablePanel.json +5 -4
  57. package/agent/components/DropdownMenu.json +1 -1
  58. package/agent/components/EmojiPicker.json +3 -2
  59. package/agent/components/EmptyState.json +1 -1
  60. package/agent/components/ErrorSurface.json +3 -3
  61. package/agent/components/FeatureList.json +1 -1
  62. package/agent/components/Field.json +0 -1
  63. package/agent/components/Flex.json +34 -4
  64. package/agent/components/FloatButton.json +6 -5
  65. package/agent/components/Form.json +1 -1
  66. package/agent/components/FormErrors.json +0 -1
  67. package/agent/components/FormField.json +6 -6
  68. package/agent/components/FormFieldArray.json +0 -1
  69. package/agent/components/FormFieldControl.json +0 -1
  70. package/agent/components/FormRoot.json +1 -1
  71. package/agent/components/Heading.json +3 -0
  72. package/agent/components/Icon.json +1 -1
  73. package/agent/components/Image.json +7 -4
  74. package/agent/components/InfiniteQueryState.json +1 -1
  75. package/agent/components/Input.json +1 -1
  76. package/agent/components/InputOTP.json +2 -2
  77. package/agent/components/Label.json +3 -3
  78. package/agent/components/LegalDocumentShell.json +5 -4
  79. package/agent/components/Legend.json +1 -1
  80. package/agent/components/LineChart.json +0 -1
  81. package/agent/components/Link.json +0 -1
  82. package/agent/components/ListRow.json +1 -1
  83. package/agent/components/Logo.json +5 -4
  84. package/agent/components/Marquee.json +4 -3
  85. package/agent/components/Masonry.json +4 -3
  86. package/agent/components/MasterDetail.json +1 -1
  87. package/agent/components/MegaMenu.json +4 -3
  88. package/agent/components/MobileShell.json +4 -4
  89. package/agent/components/NavList.json +1 -1
  90. package/agent/components/NumberInput.json +1 -1
  91. package/agent/components/OrgChart.json +4 -3
  92. package/agent/components/OrgSwitcher.json +1 -1
  93. package/agent/components/OverlayPortalProvider.json +0 -1
  94. package/agent/components/PageContainer.json +3 -3
  95. package/agent/components/PageCover.json +3 -2
  96. package/agent/components/Pagination.json +1 -1
  97. package/agent/components/PasswordInput.json +1 -1
  98. package/agent/components/PasswordStrength.json +1 -1
  99. package/agent/components/PermissionMatrix.json +1 -1
  100. package/agent/components/PieChart.json +0 -1
  101. package/agent/components/Popover.json +31 -6
  102. package/agent/components/PrefetchLink.json +1 -1
  103. package/agent/components/Progress.json +1 -1
  104. package/agent/components/Prose.json +1 -1
  105. package/agent/components/QrCode.json +1 -1
  106. package/agent/components/Radio.json +0 -1
  107. package/agent/components/RadioGroup.json +2 -2
  108. package/agent/components/RangeTimeline.json +2 -1
  109. package/agent/components/Rating.json +1 -1
  110. package/agent/components/RecordPicker.json +1 -1
  111. package/agent/components/ResizablePanel.json +1 -1
  112. package/agent/components/ResponsiveGrid.json +2 -2
  113. package/agent/components/Reveal.json +3 -3
  114. package/agent/components/ScrollArea.json +2 -2
  115. package/agent/components/SearchInput.json +1 -1
  116. package/agent/components/Segmented.json +1 -1
  117. package/agent/components/Select.json +7 -5
  118. package/agent/components/Separator.json +1 -1
  119. package/agent/components/ServiceCatalogCta.json +0 -1
  120. package/agent/components/ServiceLauncherCard.json +1 -1
  121. package/agent/components/ServiceRolePanel.json +1 -1
  122. package/agent/components/Sheet.json +5 -5
  123. package/agent/components/Sidebar.json +1 -1
  124. package/agent/components/Skeleton.json +26 -12
  125. package/agent/components/Slider.json +2 -2
  126. package/agent/components/SortableList.json +3 -2
  127. package/agent/components/SplitPane.json +1 -1
  128. package/agent/components/StatCard.json +1 -1
  129. package/agent/components/Steps.json +1 -1
  130. package/agent/components/Swatch.json +1 -1
  131. package/agent/components/Switch.json +1 -1
  132. package/agent/components/Table.json +1 -1
  133. package/agent/components/Tabs.json +3 -3
  134. package/agent/components/Text.json +5 -1
  135. package/agent/components/TextDiff.json +5 -4
  136. package/agent/components/Textarea.json +1 -1
  137. package/agent/components/ThemeScope.json +1 -1
  138. package/agent/components/ThoughtChain.json +3 -3
  139. package/agent/components/TimePicker.json +1 -1
  140. package/agent/components/Timeline.json +1 -1
  141. package/agent/components/TimelineGrid.json +5 -4
  142. package/agent/components/Toaster.json +0 -1
  143. package/agent/components/Toggle.json +3 -3
  144. package/agent/components/ToggleGroup.json +1 -1
  145. package/agent/components/Toolbar.json +10 -3
  146. package/agent/components/Tooltip.json +9 -9
  147. package/agent/components/Topbar.json +1 -1
  148. package/agent/components/TopbarItem.json +1 -1
  149. package/agent/components/Transfer.json +2 -2
  150. package/agent/components/Tree.json +1 -1
  151. package/agent/components/TreeSelect.json +1 -1
  152. package/agent/components/TwoFactorSetup.json +1 -1
  153. package/agent/components/Upload.json +1 -1
  154. package/agent/components/UploadCropDialog.json +1 -1
  155. package/agent/components/Welcome.json +3 -3
  156. package/agent/components/formatDate.json +2 -2
  157. package/agent/components/inertiaUpload.json +0 -1
  158. package/agent/components/useZodForm.json +0 -1
  159. package/agent/components-index.json +80 -154
  160. package/agent/components.json +541 -1737
  161. package/agent/index.json +10 -10
  162. package/agent/llms.txt +9 -9
  163. package/agent/patterns/account-recovery-settings.json +1 -1
  164. package/agent/patterns/auth-recovery-panels.json +2 -2
  165. package/agent/patterns/error-pages.json +1 -1
  166. package/agent/patterns/pricing-plans.json +17 -0
  167. package/agent/patterns-index.json +17 -1
  168. package/agent/patterns.json +21 -4
  169. package/agent/rules.json +30 -65
  170. package/agent/tokens.json +27 -57
  171. package/agent/vocabulary.json +3 -3
  172. package/dist/app/app-provider.d.ts +5 -3
  173. package/dist/app/app-provider.js +47 -12
  174. package/dist/app/date-format-labels.d.ts +3 -1
  175. package/dist/app/date-format-labels.js +2 -4
  176. package/dist/app/date-formats.d.ts +21 -2
  177. package/dist/app/date-formats.js +51 -2
  178. package/dist/app/index.d.ts +3 -1
  179. package/dist/app/index.js +5 -0
  180. package/dist/app/locales.d.ts +58 -3
  181. package/dist/app/locales.js +134 -8
  182. package/dist/app/preset.d.ts +25 -0
  183. package/dist/app/preset.js +10 -0
  184. package/dist/app/request-headers.d.ts +3 -3
  185. package/dist/app/request-headers.js +19 -10
  186. package/dist/app/settings-scope.d.ts +54 -0
  187. package/dist/app/settings-scope.js +46 -0
  188. package/dist/app/tenant-theme.js +8 -3
  189. package/dist/app/time-format-labels.d.ts +4 -1
  190. package/dist/app/time-format-labels.js +7 -1
  191. package/dist/app/types.d.ts +10 -2
  192. package/dist/app/use-formatting.d.ts +1 -1
  193. package/dist/components/admin/index.d.ts +1 -1
  194. package/dist/components/admin/index.js +1 -1
  195. package/dist/components/data-display/accordion.d.ts +51 -1
  196. package/dist/components/data-display/accordion.js +247 -1
  197. package/dist/components/data-display/avatar.d.ts +16 -1
  198. package/dist/components/data-display/avatar.js +109 -1
  199. package/dist/components/data-display/credential-reveal.d.ts +9 -2
  200. package/dist/components/data-display/credential-reveal.js +156 -1
  201. package/dist/components/data-display/image.js +5 -3
  202. package/dist/components/data-display/index.d.ts +0 -21
  203. package/dist/components/data-display/index.js +1 -43
  204. package/dist/components/data-display/popover.d.ts +15 -3
  205. package/dist/components/data-display/popover.js +168 -2
  206. package/dist/components/data-entry/branch-scope-picker.d.ts +1 -1
  207. package/dist/components/data-entry/index.d.ts +5 -12
  208. package/dist/components/data-entry/index.js +11 -12
  209. package/dist/components/data-entry/input-otp.d.ts +48 -2
  210. package/dist/components/data-entry/input-otp.js +94 -1
  211. package/dist/components/data-entry/number-input.d.ts +1 -1
  212. package/dist/components/data-entry/password-input.d.ts +38 -2
  213. package/dist/components/data-entry/password-input.js +56 -1
  214. package/dist/components/data-entry/rating.d.ts +38 -2
  215. package/dist/components/data-entry/rating.js +127 -1
  216. package/dist/components/data-entry/segmented.d.ts +94 -2
  217. package/dist/components/data-entry/segmented.js +104 -1
  218. package/dist/components/{ui/tag-input.d.ts → data-entry/select-tags-inline.d.ts} +7 -4
  219. package/dist/components/{ui/tag-input.js → data-entry/select-tags-inline.js} +4 -4
  220. package/dist/components/data-entry/select.js +4 -0
  221. package/dist/components/data-entry/toggle-group.d.ts +108 -2
  222. package/dist/components/data-entry/toggle-group.js +189 -1
  223. package/dist/components/data-entry/toggle.d.ts +86 -2
  224. package/dist/components/data-entry/toggle.js +153 -2
  225. package/dist/components/feedback/alert.d.ts +5 -3
  226. package/dist/components/feedback/alert.js +14 -2
  227. package/dist/components/feedback/index.d.ts +2 -6
  228. package/dist/components/feedback/index.js +1 -13
  229. package/dist/components/feedback/skeleton.d.ts +4 -17
  230. package/dist/components/feedback/skeleton.js +3 -40
  231. package/dist/components/general/index.d.ts +2 -4
  232. package/dist/components/general/index.js +1 -6
  233. package/dist/components/general/typography.d.ts +4 -58
  234. package/dist/components/general/typography.js +7 -141
  235. package/dist/components/layout/aspect-ratio.d.ts +24 -1
  236. package/dist/components/layout/aspect-ratio.js +18 -1
  237. package/dist/components/layout/auth-divider.js +1 -1
  238. package/dist/components/layout/auth-identity.js +6 -2
  239. package/dist/components/layout/centered-shell.d.ts +13 -8
  240. package/dist/components/layout/centered-shell.js +43 -1
  241. package/dist/components/layout/flex.d.ts +1 -1
  242. package/dist/components/layout/flex.js +73 -1
  243. package/dist/components/layout/index.d.ts +1 -13
  244. package/dist/components/layout/index.js +0 -12
  245. package/dist/components/layout/separator.d.ts +25 -2
  246. package/dist/components/layout/separator.js +71 -1
  247. package/dist/components/navigation/{app-setting-toggle.d.ts → app-setting-cycle.d.ts} +3 -4
  248. package/dist/components/navigation/{app-setting-toggle.js → app-setting-cycle.js} +3 -3
  249. package/dist/components/navigation/app-setting-picker.d.ts +6 -2
  250. package/dist/components/navigation/app-setting-picker.js +20 -2
  251. package/dist/components/navigation/index.d.ts +3 -11
  252. package/dist/components/navigation/index.js +1 -9
  253. package/dist/components/navigation/tabs.js +1 -1
  254. package/dist/components/ui/carousel.d.ts +1 -1
  255. package/dist/components/ui/carousel.js +1 -1
  256. package/dist/components/ui/index.d.ts +11 -5
  257. package/dist/components/ui/index.js +5 -5
  258. package/dist/contracts/measurement.json +2 -2
  259. package/dist/email/brand-mark.d.ts +3 -2
  260. package/dist/email/brand-mark.js +1 -1
  261. package/dist/email/color.d.ts +7 -0
  262. package/dist/email/color.js +14 -1
  263. package/dist/email/index.d.ts +10 -2
  264. package/dist/email/index.js +23 -2
  265. package/dist/email/tokens.generated.d.ts +120 -2
  266. package/dist/email/tokens.generated.js +119 -1
  267. package/dist/i18n/locale-tags.d.ts +25 -0
  268. package/dist/i18n/locale-tags.js +59 -0
  269. package/dist/i18n/translate.d.ts +20 -3
  270. package/dist/i18n/translate.js +25 -14
  271. package/dist/i18n/use-translation.d.ts +3 -3
  272. package/dist/i18n/use-translation.js +4 -2
  273. package/dist/{components/navigation → lab}/anchor.d.ts +2 -2
  274. package/dist/{components/navigation → lab}/anchor.js +5 -5
  275. package/dist/{components/data-display → lab}/carousel.js +2 -2
  276. package/dist/{components/layout → lab}/draggable-panel.d.ts +8 -8
  277. package/dist/{components/layout → lab}/draggable-panel.js +2 -2
  278. package/dist/{components/data-entry → lab}/emoji-picker.d.ts +2 -2
  279. package/dist/{components/data-entry → lab}/emoji-picker.js +6 -6
  280. package/dist/{components/general → lab}/float-button.d.ts +8 -8
  281. package/dist/{components/general → lab}/float-button.js +7 -7
  282. package/dist/lab/index.d.ts +39 -0
  283. package/dist/lab/index.js +48 -0
  284. package/dist/{components/layout → lab}/legal-document-shell.d.ts +2 -2
  285. package/dist/{components/layout → lab}/legal-document-shell.js +4 -4
  286. package/dist/{components/data-display → lab}/marquee.d.ts +5 -5
  287. package/dist/{components/data-display → lab}/marquee.js +5 -5
  288. package/dist/{components/layout → lab}/masonry.d.ts +2 -2
  289. package/dist/{components/layout → lab}/masonry.js +3 -3
  290. package/dist/{components/navigation → lab}/mega-menu.d.ts +4 -4
  291. package/dist/{components/navigation → lab}/mega-menu.js +2 -2
  292. package/dist/{components/data-display → lab}/org-chart.d.ts +2 -2
  293. package/dist/{components/data-display → lab}/org-chart.js +4 -4
  294. package/dist/{components/layout → lab}/page-cover.d.ts +2 -2
  295. package/dist/{components/layout → lab}/page-cover.js +2 -2
  296. package/dist/{components/data-display → lab}/range-timeline.d.ts +1 -1
  297. package/dist/{components/data-display → lab}/range-timeline.js +6 -6
  298. package/dist/{components/data-entry → lab}/sortable-list.d.ts +2 -2
  299. package/dist/{components/data-entry → lab}/sortable-list.js +3 -3
  300. package/dist/{components/data-display → lab}/text-diff.d.ts +3 -3
  301. package/dist/{components/data-display → lab}/text-diff.js +4 -4
  302. package/dist/{components/data-display → lab}/timeline-grid.d.ts +2 -2
  303. package/dist/{components/data-display → lab}/timeline-grid.js +1 -1
  304. package/dist/lib/control-styles.js +1 -1
  305. package/dist/lib/datetime/format.js +20 -6
  306. package/dist/lib/datetime/sync.d.ts +6 -2
  307. package/dist/lib/datetime/sync.js +14 -18
  308. package/dist/lib/platform.d.ts +1 -1
  309. package/dist/props/components/app.prop.d.ts +28 -13
  310. package/dist/props/components/data-display.prop.d.ts +19 -29
  311. package/dist/props/components/feedback.prop.d.ts +15 -44
  312. package/dist/props/components/general.prop.d.ts +2 -64
  313. package/dist/props/components/index.d.ts +9 -1
  314. package/dist/props/components/layout.prop.d.ts +41 -57
  315. package/dist/props/registry.d.ts +48 -101
  316. package/dist/props/registry.js +45 -129
  317. package/dist/props/vocabulary/index.d.ts +1 -1
  318. package/dist/props/vocabulary/interaction.prop.d.ts +3 -12
  319. package/dist/styles/alert-layout.css +0 -29
  320. package/dist/styles/data-display-layout.css +14 -22
  321. package/dist/styles/fonts/OFL.txt +93 -0
  322. package/dist/styles/form-layout.css +4 -0
  323. package/dist/styles/index.css +0 -2
  324. package/dist/styles/layers.json +44 -179
  325. package/dist/styles/text-layout.css +0 -15
  326. package/dist/styles.css +2 -0
  327. package/dist/themes/godx-tokens.css +41 -0
  328. package/dist/themes/godx.css +3 -0
  329. package/dist/themes/godx.d.ts +16 -0
  330. package/dist/themes/godx.js +12 -0
  331. package/dist/tokens/components/feedback.css +0 -6
  332. package/dist/tokens/derived.css +23 -22
  333. package/dist/tokens/foundation.css +4 -6
  334. package/docs/COMPOSITION-VS-COMPONENT.md +58 -33
  335. package/docs/CONSUMER-RULES.md +1 -1
  336. package/docs/CUSTOMER-THEMING.md +17 -53
  337. package/docs/migrations/v32.md +105 -0
  338. package/package.json +59 -19
  339. package/scripts/_agent-setup.mjs +54 -3
  340. package/scripts/brand-accent.generated.mjs +15 -2
  341. package/scripts/cli.mjs +36 -11
  342. package/scripts/codemod.mjs +542 -0
  343. package/scripts/consumer-rule.md +21 -43
  344. package/scripts/postinstall.mjs +10 -47
  345. package/scripts/prune-css.mjs +1 -1
  346. package/scripts/ui-audit.mjs +5 -2
  347. package/dist/components/data-display/chat-bubble.d.ts +0 -30
  348. package/dist/components/data-display/chat-bubble.js +0 -229
  349. package/dist/components/data-display/hover-card.d.ts +0 -1
  350. package/dist/components/data-display/hover-card.js +0 -7
  351. package/dist/components/data-display/thought-chain.d.ts +0 -42
  352. package/dist/components/data-display/thought-chain.js +0 -177
  353. package/dist/components/data-display/thumbnail.d.ts +0 -37
  354. package/dist/components/data-display/thumbnail.js +0 -20
  355. package/dist/components/data-display/welcome.d.ts +0 -26
  356. package/dist/components/data-display/welcome.js +0 -37
  357. package/dist/components/data-entry/attachments.d.ts +0 -19
  358. package/dist/components/data-entry/attachments.js +0 -366
  359. package/dist/components/data-entry/chat-composer.d.ts +0 -51
  360. package/dist/components/data-entry/chat-composer.js +0 -200
  361. package/dist/components/data-entry/chat-suggestion.d.ts +0 -28
  362. package/dist/components/data-entry/chat-suggestion.js +0 -309
  363. package/dist/components/data-entry/tag-input.d.ts +0 -2
  364. package/dist/components/data-entry/tag-input.js +0 -5
  365. package/dist/components/feedback/banner.d.ts +0 -21
  366. package/dist/components/feedback/banner.js +0 -19
  367. package/dist/components/feedback/callout.d.ts +0 -23
  368. package/dist/components/feedback/callout.js +0 -42
  369. package/dist/components/layout/auth-shell.d.ts +0 -10
  370. package/dist/components/layout/auth-shell.js +0 -42
  371. package/dist/components/layout/space-compact.d.ts +0 -65
  372. package/dist/components/layout/space-compact.js +0 -52
  373. package/dist/components/navigation/conversations.d.ts +0 -39
  374. package/dist/components/navigation/conversations.js +0 -371
  375. package/dist/components/ui/accordion.d.ts +0 -51
  376. package/dist/components/ui/accordion.js +0 -254
  377. package/dist/components/ui/aspect-ratio.d.ts +0 -24
  378. package/dist/components/ui/aspect-ratio.js +0 -21
  379. package/dist/components/ui/avatar.d.ts +0 -16
  380. package/dist/components/ui/avatar.js +0 -115
  381. package/dist/components/ui/credential-reveal.d.ts +0 -9
  382. package/dist/components/ui/credential-reveal.js +0 -160
  383. package/dist/components/ui/hover-card.d.ts +0 -47
  384. package/dist/components/ui/hover-card.js +0 -205
  385. package/dist/components/ui/input-otp.d.ts +0 -48
  386. package/dist/components/ui/input-otp.js +0 -101
  387. package/dist/components/ui/password-input.d.ts +0 -38
  388. package/dist/components/ui/password-input.js +0 -60
  389. package/dist/components/ui/rating.d.ts +0 -38
  390. package/dist/components/ui/rating.js +0 -131
  391. package/dist/components/ui/segmented.d.ts +0 -94
  392. package/dist/components/ui/segmented.js +0 -108
  393. package/dist/components/ui/separator.d.ts +0 -25
  394. package/dist/components/ui/separator.js +0 -74
  395. package/dist/components/ui/toggle-group.d.ts +0 -108
  396. package/dist/components/ui/toggle-group.js +0 -194
  397. package/dist/components/ui/toggle.d.ts +0 -86
  398. package/dist/components/ui/toggle.js +0 -156
  399. package/docs/CANONICAL-CONTRACTS.md +0 -206
  400. package/docs/COMPONENTS.md +0 -163
  401. package/docs/DATETIME.md +0 -78
  402. package/docs/DEVELOPMENT.md +0 -269
  403. package/docs/FRAME-A11Y-CI.md +0 -287
  404. package/docs/FRAME-COVERAGE-LEDGER.md +0 -123
  405. package/docs/FRAME-COVERAGE-REPORT.md +0 -228
  406. package/docs/FRAME-COVERAGE-STANDARD.md +0 -65
  407. package/docs/FRAME-COVERAGE.md +0 -29
  408. package/docs/MEASUREMENT-CONTRACT.md +0 -109
  409. package/docs/PROPS-REGISTRY.md +0 -61
  410. package/docs/PROPS-VOCABULARY.md +0 -100
  411. package/docs/REGISTRY.md +0 -70
  412. package/docs/TESTING.md +0 -107
  413. package/docs/THEME-API-COVERAGE.md +0 -538
  414. package/docs/WHAT-BELONGS-HERE.md +0 -179
  415. package/docs/asset-modules.d.ts +0 -53
  416. package/docs/assets/cover-terrain.svg +0 -6
  417. package/docs/assets/portrait-amber.svg +0 -5
  418. package/docs/assets/portrait-clay.svg +0 -5
  419. package/docs/assets/portrait-indigo.svg +0 -5
  420. package/docs/assets/portrait-iris.svg +0 -5
  421. package/docs/assets/portrait-moss.svg +0 -5
  422. package/docs/assets/portrait-plum.svg +0 -5
  423. package/docs/assets/portrait-slate.svg +0 -5
  424. package/docs/assets/service-mark-rose.svg +0 -6
  425. package/docs/assets/service-mark-teal.svg +0 -5
  426. package/docs/assets/shot-landscape.svg +0 -12
  427. package/docs/assets/shot-portrait.svg +0 -10
  428. package/docs/assets/tcgm/card-1.svg +0 -1
  429. package/docs/assets/tcgm/card-2.svg +0 -1
  430. package/docs/assets/tcgm/card-3.svg +0 -1
  431. package/docs/assets/tcgm/card-4.svg +0 -1
  432. package/docs/assets/tcgm/card-5.svg +0 -1
  433. package/docs/assets/tcgm/card-6.svg +0 -1
  434. package/docs/assets/tcgm/hero-prism.svg +0 -1
  435. package/docs/assets/tcgm/scene-1.svg +0 -1
  436. package/docs/assets/tcgm/scene-2.svg +0 -1
  437. package/docs/assets/tcgm/scene-3.svg +0 -1
  438. package/docs/assets/tcgm/scene-4.svg +0 -1
  439. package/docs/assets/tcgm/scene-5.svg +0 -1
  440. package/docs/assets/tcgm/tcgm-lockup-color.svg +0 -1
  441. package/docs/assets/tcgm/tcgm-symbol-color.svg +0 -1
  442. package/docs/charts/cjk-category-axis.tsx +0 -81
  443. package/docs/charts/compact-bar-trend.tsx +0 -327
  444. package/docs/charts/size-tiers.tsx +0 -192
  445. package/docs/data-display/accordion.tsx +0 -99
  446. package/docs/data-display/avatar.tsx +0 -502
  447. package/docs/data-display/badge.tsx +0 -335
  448. package/docs/data-display/card/examples/detail-panel.tsx +0 -106
  449. package/docs/data-display/card/examples/tab-list.tsx +0 -97
  450. package/docs/data-display/card/index.md +0 -3
  451. package/docs/data-display/card/index.tsx +0 -390
  452. package/docs/data-display/carousel.tsx +0 -160
  453. package/docs/data-display/charts.tsx +0 -278
  454. package/docs/data-display/chat-bubble.tsx +0 -397
  455. package/docs/data-display/code-block.tsx +0 -188
  456. package/docs/data-display/collapsible.tsx +0 -162
  457. package/docs/data-display/credential-reveal.tsx +0 -148
  458. package/docs/data-display/data-table/examples/antd-parity.tsx +0 -257
  459. package/docs/data-display/data-table/examples/approval-queue.tsx +0 -212
  460. package/docs/data-display/data-table/examples/grid-features.tsx +0 -158
  461. package/docs/data-display/data-table/examples/list-page.tsx +0 -175
  462. package/docs/data-display/data-table/examples/selectable-inbox.tsx +0 -113
  463. package/docs/data-display/data-table/examples/server-paged.tsx +0 -179
  464. package/docs/data-display/data-table/examples/striped-list.tsx +0 -173
  465. package/docs/data-display/data-table/index.md +0 -9
  466. package/docs/data-display/data-table/index.tsx +0 -407
  467. package/docs/data-display/descriptions.tsx +0 -263
  468. package/docs/data-display/empty-state.tsx +0 -164
  469. package/docs/data-display/feature-list.tsx +0 -159
  470. package/docs/data-display/hover-card.tsx +0 -181
  471. package/docs/data-display/image.tsx +0 -170
  472. package/docs/data-display/legend.tsx +0 -158
  473. package/docs/data-display/list-row.tsx +0 -441
  474. package/docs/data-display/markdown.tsx +0 -86
  475. package/docs/data-display/marquee.tsx +0 -254
  476. package/docs/data-display/org-chart.tsx +0 -165
  477. package/docs/data-display/permission-matrix.tsx +0 -188
  478. package/docs/data-display/popover-touch.tsx +0 -27
  479. package/docs/data-display/popover.tsx +0 -331
  480. package/docs/data-display/progress.tsx +0 -162
  481. package/docs/data-display/prose.tsx +0 -169
  482. package/docs/data-display/qr-code.tsx +0 -68
  483. package/docs/data-display/scroll-area.tsx +0 -420
  484. package/docs/data-display/service-launcher-card.tsx +0 -445
  485. package/docs/data-display/stat-card.tsx +0 -354
  486. package/docs/data-display/swatch.tsx +0 -107
  487. package/docs/data-display/table.tsx +0 -362
  488. package/docs/data-display/text-diff.tsx +0 -89
  489. package/docs/data-display/thought-chain.tsx +0 -176
  490. package/docs/data-display/thumbnail.tsx +0 -128
  491. package/docs/data-display/timeline-grid.tsx +0 -119
  492. package/docs/data-display/timeline.tsx +0 -671
  493. package/docs/data-display/touch-actions.tsx +0 -36
  494. package/docs/data-display/tree.tsx +0 -724
  495. package/docs/data-display/welcome.tsx +0 -115
  496. package/docs/data-entry/attachments.tsx +0 -160
  497. package/docs/data-entry/block-editor.tsx +0 -105
  498. package/docs/data-entry/branch-scope-picker.tsx +0 -128
  499. package/docs/data-entry/calendar.tsx +0 -226
  500. package/docs/data-entry/cascader.tsx +0 -380
  501. package/docs/data-entry/chat-composer.tsx +0 -619
  502. package/docs/data-entry/chat-suggestion.tsx +0 -301
  503. package/docs/data-entry/checkbox.tsx +0 -256
  504. package/docs/data-entry/color-picker.tsx +0 -189
  505. package/docs/data-entry/command-palette.tsx +0 -179
  506. package/docs/data-entry/command.tsx +0 -341
  507. package/docs/data-entry/country-picker-recipe.tsx +0 -175
  508. package/docs/data-entry/date-picker.tsx +0 -452
  509. package/docs/data-entry/emoji-picker.tsx +0 -35
  510. package/docs/data-entry/form/examples/employee-settings.tsx +0 -267
  511. package/docs/data-entry/form/examples/invoice-form.tsx +0 -387
  512. package/docs/data-entry/form-dynamic-fields.tsx +0 -199
  513. package/docs/data-entry/form-field/examples/a11y-contract.tsx +0 -242
  514. package/docs/data-entry/form-field/examples/create-form.tsx +0 -107
  515. package/docs/data-entry/form-field/index.md +0 -8
  516. package/docs/data-entry/form-field/index.tsx +0 -337
  517. package/docs/data-entry/form-inertia.tsx +0 -80
  518. package/docs/data-entry/form-root.tsx +0 -112
  519. package/docs/data-entry/form.tsx +0 -1498
  520. package/docs/data-entry/input-otp.tsx +0 -258
  521. package/docs/data-entry/input.tsx +0 -796
  522. package/docs/data-entry/label.tsx +0 -102
  523. package/docs/data-entry/markdown-editor.tsx +0 -69
  524. package/docs/data-entry/number-input.tsx +0 -279
  525. package/docs/data-entry/password-input.tsx +0 -102
  526. package/docs/data-entry/password-strength.tsx +0 -99
  527. package/docs/data-entry/radio-group.tsx +0 -316
  528. package/docs/data-entry/rating.tsx +0 -91
  529. package/docs/data-entry/record-picker.tsx +0 -209
  530. package/docs/data-entry/search-input.tsx +0 -121
  531. package/docs/data-entry/segmented-in-filter-row.tsx +0 -60
  532. package/docs/data-entry/segmented.tsx +0 -300
  533. package/docs/data-entry/select-async-contracts.tsx +0 -108
  534. package/docs/data-entry/select-matrix.tsx +0 -209
  535. package/docs/data-entry/select.tsx +0 -547
  536. package/docs/data-entry/slider.tsx +0 -212
  537. package/docs/data-entry/sortable-list.tsx +0 -76
  538. package/docs/data-entry/switch.tsx +0 -314
  539. package/docs/data-entry/tag-input.tsx +0 -145
  540. package/docs/data-entry/textarea.tsx +0 -249
  541. package/docs/data-entry/time-picker.tsx +0 -187
  542. package/docs/data-entry/time-range-picker.tsx +0 -55
  543. package/docs/data-entry/toggle-count.tsx +0 -348
  544. package/docs/data-entry/toggle-group.tsx +0 -438
  545. package/docs/data-entry/toggle.tsx +0 -217
  546. package/docs/data-entry/transfer.tsx +0 -115
  547. package/docs/data-entry/tree-select.tsx +0 -204
  548. package/docs/data-entry/upload-crop-dialog.tsx +0 -109
  549. package/docs/data-entry/upload.tsx +0 -310
  550. package/docs/feedback/alert-dialog.tsx +0 -270
  551. package/docs/feedback/alert.tsx +0 -248
  552. package/docs/feedback/auth-expiry.tsx +0 -104
  553. package/docs/feedback/banner.tsx +0 -183
  554. package/docs/feedback/callout.tsx +0 -220
  555. package/docs/feedback/danger-confirm.tsx +0 -91
  556. package/docs/feedback/dialog-touch.tsx +0 -24
  557. package/docs/feedback/dialog.tsx +0 -373
  558. package/docs/feedback/sheet.tsx +0 -510
  559. package/docs/feedback/skeleton.tsx +0 -168
  560. package/docs/feedback/toast.tsx +0 -135
  561. package/docs/feedback/tooltip.tsx +0 -171
  562. package/docs/feedback/two-factor-setup.tsx +0 -68
  563. package/docs/foundation/_email-specimen.ts +0 -274
  564. package/docs/foundation/_theme-editor-scope.ts +0 -222
  565. package/docs/foundation/colors.tsx +0 -207
  566. package/docs/foundation/density.tsx +0 -242
  567. package/docs/foundation/email-tokens.tsx +0 -323
  568. package/docs/foundation/radius-shadow.tsx +0 -154
  569. package/docs/foundation/spacing.tsx +0 -216
  570. package/docs/foundation/theme-editor.tsx +0 -654
  571. package/docs/foundation/typography.tsx +0 -147
  572. package/docs/general/actions.tsx +0 -175
  573. package/docs/general/activity.tsx +0 -289
  574. package/docs/general/button/examples/destructive-confirm.tsx +0 -90
  575. package/docs/general/button/examples/form-actions.tsx +0 -87
  576. package/docs/general/button/examples/toolbar.tsx +0 -160
  577. package/docs/general/button/index.md +0 -16
  578. package/docs/general/button/index.tsx +0 -236
  579. package/docs/general/float-button.tsx +0 -133
  580. package/docs/general/icon.tsx +0 -217
  581. package/docs/general/logo.tsx +0 -194
  582. package/docs/general/reveal.tsx +0 -309
  583. package/docs/general/typography.tsx +0 -542
  584. package/docs/i18n/messages/en.json +0 -1715
  585. package/docs/i18n/messages/ja.json +0 -1708
  586. package/docs/i18n/messages/vi.json +0 -1708
  587. package/docs/layout/account-chip.tsx +0 -72
  588. package/docs/layout/admin-collection.tsx +0 -122
  589. package/docs/layout/affix.tsx +0 -209
  590. package/docs/layout/app-launcher.tsx +0 -211
  591. package/docs/layout/app-shell-arrangements.tsx +0 -225
  592. package/docs/layout/app-shell-narrow-bar.tsx +0 -205
  593. package/docs/layout/app-shell-states.tsx +0 -171
  594. package/docs/layout/app-shell.tsx +0 -395
  595. package/docs/layout/aspect-ratio.tsx +0 -135
  596. package/docs/layout/auth-account-summary.tsx +0 -103
  597. package/docs/layout/auth-divider.tsx +0 -28
  598. package/docs/layout/auth-footer.tsx +0 -37
  599. package/docs/layout/auth-identity.tsx +0 -70
  600. package/docs/layout/auth-recovery/examples/mfa-challenge.md +0 -41
  601. package/docs/layout/auth-recovery/examples/mfa-challenge.tsx +0 -254
  602. package/docs/layout/auth-recovery/examples/mobile-390.md +0 -25
  603. package/docs/layout/auth-recovery/examples/mobile-390.tsx +0 -82
  604. package/docs/layout/auth-recovery/examples/password-recovery.md +0 -24
  605. package/docs/layout/auth-recovery/examples/password-recovery.tsx +0 -197
  606. package/docs/layout/auth-recovery/examples/wrapping-ja-en-vi.md +0 -27
  607. package/docs/layout/auth-recovery/examples/wrapping-ja-en-vi.tsx +0 -156
  608. package/docs/layout/auth-recovery/index.md +0 -140
  609. package/docs/layout/auth-recovery/index.tsx +0 -96
  610. package/docs/layout/auth-shell-context.tsx +0 -103
  611. package/docs/layout/auth-shell-device.tsx +0 -112
  612. package/docs/layout/auth-shell-registration.tsx +0 -338
  613. package/docs/layout/auth-shell-variants.tsx +0 -143
  614. package/docs/layout/auth-shell.tsx +0 -59
  615. package/docs/layout/auth-stack.tsx +0 -40
  616. package/docs/layout/centered-shell.tsx +0 -102
  617. package/docs/layout/draggable-panel.tsx +0 -127
  618. package/docs/layout/error-surface/examples/application-403.tsx +0 -84
  619. package/docs/layout/error-surface/examples/application-404.tsx +0 -77
  620. package/docs/layout/error-surface/examples/system-500.tsx +0 -47
  621. package/docs/layout/error-surface/examples/system-503.tsx +0 -48
  622. package/docs/layout/error-surface/index.md +0 -153
  623. package/docs/layout/error-surface/index.tsx +0 -239
  624. package/docs/layout/flex.tsx +0 -444
  625. package/docs/layout/legal-document-shell/_data.ts +0 -110
  626. package/docs/layout/legal-document-shell/examples/desktop-1440.md +0 -12
  627. package/docs/layout/legal-document-shell/examples/desktop-1440.tsx +0 -83
  628. package/docs/layout/legal-document-shell/examples/mobile-390.md +0 -22
  629. package/docs/layout/legal-document-shell/examples/mobile-390.tsx +0 -70
  630. package/docs/layout/legal-document-shell/examples/tablet-1024.md +0 -3
  631. package/docs/layout/legal-document-shell/examples/tablet-1024.tsx +0 -84
  632. package/docs/layout/legal-document-shell/examples/wrapping-ja-en-vi.md +0 -18
  633. package/docs/layout/legal-document-shell/examples/wrapping-ja-en-vi.tsx +0 -61
  634. package/docs/layout/legal-document-shell/index.md +0 -51
  635. package/docs/layout/legal-document-shell/index.tsx +0 -101
  636. package/docs/layout/masonry.tsx +0 -291
  637. package/docs/layout/master-detail.tsx +0 -390
  638. package/docs/layout/mobile-shell.tsx +0 -106
  639. package/docs/layout/nav-list.tsx +0 -584
  640. package/docs/layout/org-switcher.tsx +0 -131
  641. package/docs/layout/page-container.tsx +0 -1020
  642. package/docs/layout/page-cover.tsx +0 -56
  643. package/docs/layout/resizable-panel.tsx +0 -419
  644. package/docs/layout/responsive-grid.tsx +0 -403
  645. package/docs/layout/separator.tsx +0 -327
  646. package/docs/layout/service-role-panel.tsx +0 -144
  647. package/docs/layout/sidebar.tsx +0 -689
  648. package/docs/layout/space-compact.tsx +0 -202
  649. package/docs/layout/split-pane.tsx +0 -532
  650. package/docs/layout/topbar-item.tsx +0 -233
  651. package/docs/layout/topbar.tsx +0 -360
  652. package/docs/navigation/anchor.tsx +0 -295
  653. package/docs/navigation/app-setting-picker.tsx +0 -178
  654. package/docs/navigation/app-setting-toggle.tsx +0 -111
  655. package/docs/navigation/breadcrumb.tsx +0 -207
  656. package/docs/navigation/card-tabs.tsx +0 -344
  657. package/docs/navigation/conversations.tsx +0 -176
  658. package/docs/navigation/dropdown-menu.tsx +0 -345
  659. package/docs/navigation/filter-bar.tsx +0 -247
  660. package/docs/navigation/mega-menu-panel.tsx +0 -86
  661. package/docs/navigation/mega-menu.tsx +0 -254
  662. package/docs/navigation/pagination.tsx +0 -293
  663. package/docs/navigation/steps.tsx +0 -315
  664. package/docs/navigation/tabs-rtl.tsx +0 -28
  665. package/docs/navigation/tabs.tsx +0 -755
  666. package/docs/navigation/toolbar.tsx +0 -347
  667. package/docs/providers/app-provider.tsx +0 -191
  668. package/docs/providers/format-date.tsx +0 -230
  669. package/docs/providers/theme-scope.tsx +0 -186
  670. package/docs/query/button-refetch.tsx +0 -161
  671. package/docs/query/data-state.tsx +0 -262
  672. package/docs/query/infinite-query-state.tsx +0 -97
  673. package/docs/query/mutation-feedback.tsx +0 -128
  674. package/docs/query/touch-actions.tsx +0 -68
  675. package/docs/react-router/prefetch-link.tsx +0 -262
  676. package/docs/roadmap/ai-chat-components.md +0 -206
  677. package/docs/roadmap/antd-parity.md +0 -155
  678. package/docs/roadmap/badge-tag-chip-count.md +0 -172
  679. package/docs/roadmap/list-masonry.md +0 -159
  680. package/docs/roadmap/parity-audit-data-display-feedback.md +0 -567
  681. package/docs/roadmap/parity-audit-data-entry.md +0 -368
  682. package/docs/roadmap/parity-audit-layout-navigation-general.md +0 -459
  683. package/docs/roadmap/parity-backlog.md +0 -77
  684. package/docs/roadmap/tree-components.md +0 -151
  685. package/docs/roadmap/website-components.md +0 -813
  686. package/docs/showcase/acme-portal.tsx +0 -461
  687. package/docs/showcase/acme-website.tsx +0 -499
  688. package/docs/showcase/caimono-price-comparison.tsx +0 -919
  689. package/docs/showcase/case1-warehouse-dashboard.tsx +0 -358
  690. package/docs/showcase/case2-employee-me.tsx +0 -438
  691. package/docs/showcase/case3-approval-workflow.tsx +0 -531
  692. package/docs/showcase/case4-login.tsx +0 -312
  693. package/docs/showcase/case5-shift-calendar.tsx +0 -702
  694. package/docs/showcase/case6-agency-handy.tsx +0 -1120
  695. package/docs/showcase/futurelastic-web.tsx +0 -441
  696. package/docs/showcase/marketing-page.tsx +0 -895
  697. package/docs/showcase/org-switcher.tsx +0 -320
  698. package/docs/showcase/permission-matrix.tsx +0 -354
  699. package/docs/showcase/public-landing.tsx +0 -210
  700. package/docs/showcase/settings-account-sections.tsx +0 -559
  701. package/docs/showcase/settings-security-mfa.tsx +0 -145
  702. package/docs/showcase/table-approval-queue.tsx +0 -199
  703. package/docs/showcase/table-bulk-actions.tsx +0 -468
  704. package/docs/showcase/table-compact-kintone.tsx +0 -438
  705. package/docs/showcase/table-conditional-format.tsx +0 -367
  706. package/docs/showcase/table-crud-list.tsx +0 -544
  707. package/docs/showcase/table-density.tsx +0 -349
  708. package/docs/showcase/table-expandable-rows.tsx +0 -496
  709. package/docs/showcase/table-filter-chips.tsx +0 -468
  710. package/docs/showcase/table-footer-totals.tsx +0 -328
  711. package/docs/showcase/table-grouped-subtotals.tsx +0 -398
  712. package/docs/showcase/table-master-detail.tsx +0 -482
  713. package/docs/showcase/table-pagination.tsx +0 -409
  714. package/docs/showcase/table-states.tsx +0 -371
  715. package/docs/showcase/table-sticky-columns.tsx +0 -377
  716. package/docs/showcase/table-tree-rows.tsx +0 -451
  717. package/docs/showcase/table-view-tabs.tsx +0 -488
  718. package/docs/showcase/tcgm-website.tsx +0 -1047
  719. package/docs/showcase/tenant-brand-color.tsx +0 -338
  720. package/docs/showcase/theme-customization.tsx +0 -1292
  721. package/docs/showcase/theme-lab.tsx +0 -2125
  722. package/docs/themes/flat.css +0 -466
  723. package/docs/themes/glassmorphism.css +0 -960
  724. package/docs/themes/index.ts +0 -219
  725. package/docs/themes/neubrutalism.css +0 -481
  726. /package/dist/components/navigation/{filter-bar.d.ts → toolbar.d.ts} +0 -0
  727. /package/dist/components/navigation/{filter-bar.js → toolbar.js} +0 -0
  728. /package/dist/{components/data-display → lab}/carousel.d.ts +0 -0
  729. /package/dist/{components/data-entry → lab}/emoji-data.d.ts +0 -0
  730. /package/dist/{components/data-entry → lab}/emoji-data.js +0 -0
  731. /package/dist/{components/data-display → lab}/marquee-reveal.d.ts +0 -0
  732. /package/dist/{components/data-display → lab}/marquee-reveal.js +0 -0
@@ -1,895 +0,0 @@
1
- /**
2
- * Showcase · Marketing page — the composition doctrine's own deliverable (gh#833).
3
- *
4
- * `docs/COMPOSITION-VS-COMPONENT.md` §3 judges Hero, Navbar, Footer, PricingTable, testimonial,
5
- * logo wall, feature grid and CTA band to be COMPOSITIONS: layout + content + token configuration
6
- * over real components, expressible today. The doctrine's remedy for a composition is a `docs/`
7
- * showcase, not a component. Until this page existed that was an assertion. This is the
8
- * demonstration, and its claim is a MEASUREMENT, not a promise:
9
- *
10
- * this page acme-website futurelastic-web
11
- * `<style>` blocks ................ 0 1 1
12
- * page-local class SELECTORS ...... 0 17 28
13
- * bespoke classes ON elements ..... 0 16 25
14
- * non-`ui-*` classes on elements .. 0 38 45
15
- * raw px/rem/em/vw literals ....... 0 29 40
16
- *
17
- * Counted with comments stripped (so a docblock quoting a class or a length is not counted):
18
- * selectors are `/(^|[\s,>+~])\.([a-zA-Z_][\w-]*)\s*(?=[{,.:[]|\s)/m`, classes are every token
19
- * inside a `className`, literals are `/(?<![\w.$}#-])(\d*\.?\d+)(px|rem|em|ch|pt|v\w+)\b/`. The two
20
- * siblings also RE-THEME, which is half of what their stylesheets carry; this page uses the shipped
21
- * theme, so everything it could not express is a framework gap rather than a brand decision.
22
- * `public-landing.tsx` also measures 0/0 and is not a counter-example: it is a narrow
23
- * `CenteredShell preset="public-landing"` page with no full-bleed band, no display type, no
24
- * pricing and no logo wall, i.e. none of the shapes that produced the classes above.
25
- *
26
- * Every LENGTH here is a token reference: `var(--space-section-band)`, `var(--space-section-hero)`,
27
- * `var(--page-measure-wide)`, `var(--band-height-3xl)`, `var(--space-6)`, `var(--space-2)`,
28
- * `var(--overlay-z-index)`. The only class written anywhere below is `.ui-brand-glow`, which the
29
- * package ships (`src/styles/layout.css`).
30
- *
31
- * ── WHAT IS STILL HAND-WRITTEN, AND WHY (the finding this page exists to produce) ───────────────
32
- *
33
- * Zero classes and zero literals did NOT mean zero CSS. Six things below WERE inline `style`
34
- * objects because no PROP reached them. Each one is a named gap, in the order a reader meets them;
35
- * gh#839 closed the first two:
36
- *
37
- * 1. THE SECTION BAND — was `paddingBlock: var(--space-section-band | --space-section-hero)`.
38
- * CLOSED by gh#839: the numeric `GapProp` ladder reaches the two band steps, so
39
- * `pad={{ block: 20 }}` (80px) and `pad={{ block: 24 }}` (96px) state the rhythm through the
40
- * public API, and every band below now does. Neither step has a compact variant and gh#839
41
- * decided it should not: `--space-section-hero` measures 96px at 1440 AND at 320, which is
42
- * deliberate — Tailwind UI's own marketing sections are `py-24 sm:py-32`, i.e. 96px is the
43
- * NARROW rung of the industry pair and the desktop one is the step above. A numeric `pad`
44
- * step is a VALUE (`pad={3}` is 12px everywhere); making one of them responsive would break
45
- * that contract for the whole ladder. `--centered-shell-landing-main-padding-block-compact`
46
- * is not the counter-example it looks like: 40px → 24px is a SHELL's main padding, not a
47
- * marketing band, and it switches inside `.ui-centered-shell`'s own scope, which a plain
48
- * `<section>` has no equivalent of.
49
- * 2. THE CENTRED COLUMN — was `marginInline: auto` + `inlineSize: 100%` +
50
- * `maxInlineSize: var(--page-measure-wide)` + `paddingInline: var(--space-6)`, repeated at
51
- * every band. CLOSED by gh#839 as `Flex measure="wide"` + `pad={{ inline: 6 }}`. gh#831 minted
52
- * `--page-measure-wide` and deliberately did not add `PageContainer measure="wide"`, reasoning
53
- * that a marketing page is full-bleed sections with a centred inner column and `PageContainer`
54
- * owns neither. That reasoning still holds and was not reopened — the prop went to `Flex`, the
55
- * primitive a full-bleed `<section>` can actually put inside itself, where it has seven call
56
- * sites on this page. `measure` adds NO gutter: `pad` owns that, and one band with two padding
57
- * owners is how a measure and its inset drift apart.
58
- * 3. THE STICKY BAR — `position: sticky` + `insetBlockStart` + `zIndex`. `Affix` has since
59
- * shipped (28.8.0, with the measured placeholder that removes the 62px page jump) and this
60
- * page has not yet been moved onto it; `Topbar` still has no `sticky` prop.
61
- * 4. THE GLASS — `--topbar-background-alpha` / `--topbar-backdrop-blur-size` as inline custom
62
- * properties. They are `initial` by design, so a call site MUST set them, and that is correct.
63
- * This used to read `--space-2`, borrowing a token that means something else, because the
64
- * library had no blur SCALE at all. gh#837 closed that: `--blur-sm|md|lg` now exists in
65
- * `foundation.css`, deliberately NOT `--scaling`-multiplied, because a backdrop blur is an
66
- * optical effect and compact density does not mean thinner glass. Measured: `blur(8px)`.
67
- * 5. THE HALO — `position: relative` / `overflow: hidden` on the band and `position: absolute` /
68
- * `inset: 0` on the `.ui-brand-glow` layer. This is the package's own idiom (both siblings
69
- * write `className="ui-brand-glow absolute inset-0"`), spelled as logical inline style so
70
- * `check:rtl` never has to grant an exception.
71
- * 6. THE DISPLAY RAMP IS NOT RESPONSIVE, and this is the one that changed the page. gh#826 gave
72
- * `Heading size` / `Text size` the display steps, and `size` takes a single scalar: there is
73
- * no responsive object form, the way `Flex direction` and `ResponsiveGrid columns` both take
74
- * one. `--font-size-5xl` is `--font-size-display` = 54px at 1440 and 54px at 320. Measured
75
- * with a headline of ordinary marketing length (99 characters): 6 lines at 1280, 10 at 375,
76
- * 12 at 320, i.e. a phone hero five screens tall. The headline in `en`/`ja`/`vi` was cut to
77
- * what 54px can carry (2 lines at 1280, 4 at 375) and the long-copy edge case moved to the
78
- * feature grid, where `features.auditTitle` runs several lines beside `features.ssoTitle` =
79
- * "SSO". NO page-local `clamp()` was written: both siblings wrote one, and writing a third is
80
- * how a framework gap becomes folklore. The package already knows the answer for exactly one
81
- * preset (`--centered-shell-landing-heading-size-compact`, read only by
82
- * `CenteredShell preset="public-landing"`); a composition cannot reach it.
83
- *
84
- * MegaMenu is deliberately ABSENT, and the absence is measured, not an oversight. A site nav and
85
- * this sticky glass bar are mutually exclusive today. `docs/navigation/mega-menu.tsx` records that
86
- * MegaMenu must not go in a `Topbar` slot: `topbar-center` is `display: none` below ~1280px, and
87
- * `topbar-start` is `overflow: clip` with a nowrap row, which put 58 elements outside the viewport
88
- * at 375px. Meanwhile `.ui-topbar` is the ONLY selector that reads the gh#831 glass knobs, and
89
- * turning the blur on makes the bar a backdrop root, i.e. the containing block for its own fixed
90
- * descendants, which is exactly how MegaMenu positions its panel. So the bar carries plain anchors
91
- * at desktop and the narrow answer is the `Sheet`, which is what the MegaMenu doc prescribes.
92
- *
93
- * ── REACHING THE EDGES, AND THE TWO THINGS IT BROKE ─────────────────────────────────────────────
94
- *
95
- * Tidy data is why a docs site's examples never break. On purpose here: a 71-character identifier
96
- * with no break opportunity in it, in three places; CJK beside Latin in one sentence, one plan row
97
- * and one quote; a feature card with NO description beside five that have one; a testimonial with
98
- * NO rating beside two that have one; a plan with NO badge and NO figure beside one carrying three
99
- * badges; a footer column with one link beside one with six; a brand lockup long enough to outgrow
100
- * the bar. Two of those broke the page, and both fixes are documented at the call site:
101
- *
102
- * • The id held the document open at 457px on every phone width. `Text whitespace="pre-wrap"`
103
- * gives `overflow-wrap: break-word`, which does NOT reduce a box's MIN-CONTENT size, and a
104
- * flex item keeps `min-width: auto` — so in the footer row it wrapped nothing. `Flex fill`
105
- * (`flex: 1 1 0` + `min-inline-size: 0`) is what makes the break fire.
106
- * • The lockup measured 222px against the 85px `topbar-start` had left at 375, and was clipped.
107
- * `Logo` has no `truncate`; the package's own answer, in `public-landing.tsx`, is to drop the
108
- * wordmark at phone width.
109
- *
110
- * Measured in Chromium after both, at 320 / 375 / 390 / 768 / 1024 / 1280 / 1440:
111
- * `document.documentElement.scrollWidth` equals the viewport at every one, and zero unclipped
112
- * elements cross the inline edge. The two boxes that do scroll are the `Marquee` viewport and the
113
- * `Carousel` viewport, which is what both components are.
114
- *
115
- * Every string and every `aria-label` comes from `t()` (`docs/i18n/messages/{en,ja,vi}.json`,
116
- * namespace `marketingShowcase` — demo copy the preview registers at startup, never shipped to a
117
- * consumer; gh#858), and the locale picker in the bar switches all three live. Money
118
- * is `Intl.NumberFormat` with the ACTIVE locale and an ISO 4217 code that lives in data, never a
119
- * symbol in the copy. The year is `Intl.DateTimeFormat`. Domains are RFC 2606 reserved
120
- * (`*.example.jp`), the company is fictional, and every wordmark in the logo wall is invented.
121
- */
122
- import { useMemo, useState, type CSSProperties } from "react";
123
- import {
124
- ArrowRight,
125
- CalendarClock,
126
- CircleCheck,
127
- FileSearch,
128
- Globe2,
129
- KeyRound,
130
- Menu,
131
- Route,
132
- Webhook,
133
- } from "lucide-react";
134
-
135
- import {
136
- Avatar,
137
- AvatarFallback,
138
- Badge,
139
- Card,
140
- CardContent,
141
- Carousel,
142
- CarouselContent,
143
- CarouselDots,
144
- CarouselItem,
145
- CarouselNext,
146
- CarouselPrevious,
147
- FeatureList,
148
- Marquee,
149
- StatCard,
150
- } from "@godxjp/ui/data-display";
151
- import { Rating, Segmented } from "@godxjp/ui/data-entry";
152
- import {
153
- Sheet,
154
- SheetBody,
155
- SheetClose,
156
- SheetContent,
157
- SheetDescription,
158
- SheetHeader,
159
- SheetTitle,
160
- SheetTrigger,
161
- } from "@godxjp/ui/feedback";
162
- import { Button, Heading, Icon, Logo, Reveal, Text } from "@godxjp/ui/general";
163
- import { useTranslation } from "@godxjp/ui/i18n";
164
- import { Flex, ResponsiveGrid, Separator, Topbar } from "@godxjp/ui/layout";
165
- import { AppSettingPicker } from "@godxjp/ui/navigation";
166
-
167
- /* ── The inline-style constants named in the docblock. Every value is a token reference; no number
168
- with a unit appears anywhere in this file. Gaps 1 and 2 no longer have one: `Flex measure` and
169
- `Flex pad` state the band through props (gh#839). ──────────────────────────────────────────── */
170
-
171
- /** (5) The halo host and the halo layer. */
172
- const GLOW_HOST: CSSProperties = { position: "relative", overflow: "hidden" };
173
- const GLOW_LAYER: CSSProperties = { position: "absolute", inset: 0 };
174
- const ABOVE_GLOW: CSSProperties = { position: "relative" };
175
-
176
- /** (3) The sticky bar region. `Affix` does not exist; `Topbar` has no `sticky`. */
177
- const STICKY_HEADER: CSSProperties = {
178
- position: "sticky",
179
- insetBlockStart: 0,
180
- zIndex: "var(--overlay-z-index)",
181
- };
182
-
183
- /** (4) gh#831's glass knobs plus the bar geometry its own docstring recommends. */
184
- const GLASS_BAR: CSSProperties = {
185
- "--topbar-height": "var(--band-height-3xl)",
186
- /* Full-bleed glass, content on the shell measure: the same `max(gutter, half the slack)` the
187
- package writes for CenteredShell's landing preset, so no page-local media query. */
188
- "--topbar-inset": "max(var(--space-6), calc((100% - var(--page-measure-wide)) / 2))",
189
- "--topbar-background-alpha": "85%",
190
- "--topbar-backdrop-blur-size": "var(--blur-md)",
191
- } as CSSProperties;
192
-
193
- /** Per-instance halo shaping — the four `--brand-glow-*` knobs, at the call site. */
194
- const HERO_GLOW: CSSProperties = {
195
- "--brand-glow-size": "55% 60%",
196
- "--brand-glow-position": "82% -8%",
197
- "--brand-glow-alpha": "0.20",
198
- } as CSSProperties;
199
-
200
- const CTA_GLOW: CSSProperties = {
201
- "--brand-glow-size": "70% 90%",
202
- "--brand-glow-position": "50% 110%",
203
- "--brand-glow-alpha": "0.16",
204
- } as CSSProperties;
205
-
206
- /* ── Data. RFC 2606 reserved domains, a fictional company, invented customer wordmarks. ──────── */
207
-
208
- const SITE = "works.example.jp";
209
-
210
- /**
211
- * 71 characters, and not one of them is a break opportunity: no hyphen, no underscore, no slash.
212
- * It is in the hero panel AND in a feature card so the failure has two chances to show itself.
213
- */
214
- const ENDPOINT_ID = "whsec0f3a8c1d2e4b5a697c8d0e1f2a3b4c5d6e7f8091a2b3c4d5e6f708192a3b4c5d6e";
215
-
216
- const NAV_KEYS = ["product", "solutions", "pricing", "docs"] as const;
217
-
218
- /** Invented wordmarks. CJK, Latin and Vietnamese diacritics in one row, plus a very long one. */
219
- const CUSTOMERS = [
220
- { glyph: "A", name: "Aoba Foods" },
221
- { glyph: "北", name: "北陸精密工業" },
222
- { glyph: "M", name: "Meridian Health" },
223
- { glyph: "T", name: "Trường An" },
224
- { glyph: "K", name: "Kita Logistics and Warehousing" },
225
- { glyph: "Ö", name: "Örebro Verkstad" },
226
- { glyph: "海", name: "海運サービス" },
227
- ];
228
-
229
- /** The currency lives in DATA, so nothing in the page hard-codes a symbol or an ISO 4217 code. */
230
- const CURRENCY = "JPY";
231
-
232
- type Plan = {
233
- key: "starter" | "team" | "enterprise";
234
- /** `null` = quoted: the empty slot beside two filled ones. */
235
- monthly: number | null;
236
- yearlyMonthly: number | null;
237
- accent: boolean;
238
- badges: Array<"popular" | "saving" | "fresh">;
239
- features: Array<{ state: "included" | "limited" | "excluded"; key: string; limitKey?: string }>;
240
- };
241
-
242
- const PLANS: Plan[] = [
243
- {
244
- key: "starter",
245
- monthly: 4800,
246
- yearlyMonthly: 4000,
247
- accent: false,
248
- badges: [],
249
- features: [
250
- { state: "limited", key: "featChains", limitKey: "limitedChains" },
251
- { state: "included", key: "featExport" },
252
- { state: "excluded", key: "featDelegation" },
253
- { state: "excluded", key: "featSso" },
254
- { state: "excluded", key: "featResidency" },
255
- { state: "limited", key: "featSupport", limitKey: "limitedSupport" },
256
- ],
257
- },
258
- {
259
- key: "team",
260
- monthly: 9600,
261
- yearlyMonthly: 8000,
262
- accent: true,
263
- badges: ["popular", "saving", "fresh"],
264
- features: [
265
- { state: "included", key: "featChains" },
266
- { state: "included", key: "featExport" },
267
- { state: "included", key: "featDelegation" },
268
- { state: "included", key: "featSso" },
269
- { state: "excluded", key: "featResidency" },
270
- { state: "limited", key: "featSupport", limitKey: "limitedSupport" },
271
- ],
272
- },
273
- {
274
- key: "enterprise",
275
- monthly: null,
276
- yearlyMonthly: null,
277
- accent: false,
278
- badges: [],
279
- features: [
280
- { state: "included", key: "featChains" },
281
- { state: "included", key: "featExport" },
282
- { state: "included", key: "featDelegation" },
283
- { state: "included", key: "featSso" },
284
- { state: "included", key: "featResidency" },
285
- { state: "included", key: "featSupport" },
286
- ],
287
- },
288
- ];
289
-
290
- const FEATURES = [
291
- { key: "routing", icon: Route, hasBody: true, long: false },
292
- /* The long title with NO body: an empty slot beside five filled ones. */
293
- { key: "audit", icon: FileSearch, hasBody: false, long: true },
294
- { key: "evidence", icon: CircleCheck, hasBody: true, long: false },
295
- { key: "webhook", icon: Webhook, hasBody: true, long: false },
296
- { key: "residency", icon: Globe2, hasBody: true, long: false },
297
- { key: "sso", icon: KeyRound, hasBody: true, long: false },
298
- ];
299
-
300
- const QUOTES = [
301
- { key: "1", rating: 5 },
302
- /* Two words, and no rating: the second empty slot. */
303
- { key: "2", rating: null },
304
- { key: "3", rating: 4 },
305
- ] as const;
306
-
307
- const FOOTER_COLUMNS = [
308
- { key: "product", links: ["featuresLink", "pricingLink", "changelog", "status"] },
309
- { key: "company", links: ["about", "careers"] },
310
- {
311
- key: "legal",
312
- links: ["terms", "privacy", "security", "subprocessors", "accessibility", "status"],
313
- },
314
- /* One link beside six. */
315
- { key: "contact", links: ["salesLine"] },
316
- ];
317
-
318
- export default function MarketingPage() {
319
- const { t, locale } = useTranslation();
320
- const [cycle, setCycle] = useState("monthly");
321
- const [navOpen, setNavOpen] = useState(false);
322
-
323
- const money = useMemo(
324
- () =>
325
- new Intl.NumberFormat(locale, {
326
- style: "currency",
327
- currency: CURRENCY,
328
- maximumFractionDigits: 0,
329
- }),
330
- [locale],
331
- );
332
- const count = useMemo(() => new Intl.NumberFormat(locale), [locale]);
333
- const year = useMemo(
334
- () => new Intl.DateTimeFormat(locale, { year: "numeric" }).format(new Date()),
335
- [locale],
336
- );
337
-
338
- return (
339
- <Flex as="div" direction="col" gap="none">
340
- {/* ── NAVBAR ─────────────────────────────────────────────────────────────────────────── */}
341
- <header style={STICKY_HEADER}>
342
- <Topbar
343
- style={GLASS_BAR}
344
- start={
345
- <Flex align="center" gap="lg">
346
- {/* The lockup measures 222px, and at 375 the start slot has 85px after the end
347
- cluster takes its natural width — so `topbar-start` clipped it (measured: 93 in
348
- 85). The bar's shrink contract says a long brand string should truncate rather
349
- than spill, and `Logo` has no `truncate`; the package's own answer, in
350
- `public-landing.tsx`, is to drop the wordmark at phone width. The mark alone
351
- identifies the product there, and the full name is the first thing in the Sheet. */}
352
- <Flex hideBelow="sm" align="center" gap="none">
353
- <Logo
354
- glyph="E"
355
- wordmark={t("marketingShowcase.brand.name")}
356
- productSuffix={t("marketingShowcase.brand.suffix")}
357
- />
358
- </Flex>
359
- <Flex hideFrom="sm" align="center" gap="none">
360
- <Logo glyph="E" label={t("marketingShowcase.brand.name")} />
361
- </Flex>
362
- <Flex
363
- as="div"
364
- hideBelow="lg"
365
- align="center"
366
- gap="xs"
367
- role="navigation"
368
- aria-label={t("marketingShowcase.nav.label")}
369
- >
370
- {NAV_KEYS.map((key, index) => (
371
- <Button key={key} variant="ghost" size="sm" asChild>
372
- <a href={`#${key}`} aria-current={index === 0 ? "page" : undefined}>
373
- {t(`marketingShowcase.nav.${key}`)}
374
- </a>
375
- </Button>
376
- ))}
377
- </Flex>
378
- </Flex>
379
- }
380
- end={
381
- <Flex align="center" gap="sm">
382
- <AppSettingPicker kind="locale" />
383
- <Flex hideBelow="sm" align="center" gap="sm">
384
- <Button variant="ghost" size="sm" asChild>
385
- <a href="#start">{t("marketingShowcase.nav.signIn")}</a>
386
- </Button>
387
- </Flex>
388
- <Button size="sm" asChild>
389
- <a href="#start">{t("marketingShowcase.nav.getStarted")}</a>
390
- </Button>
391
- {/* The narrow answer the MegaMenu doc prescribes. Nothing in the bar is unreachable
392
- at 375px: every destination hidden above is inside this Sheet. */}
393
- <Flex hideFrom="lg" align="center" gap="none">
394
- <Sheet open={navOpen} onOpenChange={setNavOpen}>
395
- <SheetTrigger asChild>
396
- <Button
397
- variant="ghost"
398
- size="icon-sm"
399
- aria-label={t("marketingShowcase.nav.open")}
400
- >
401
- <Icon as={Menu} size="sm" />
402
- </Button>
403
- </SheetTrigger>
404
- <SheetContent side="right">
405
- <SheetHeader>
406
- <SheetTitle>{t("marketingShowcase.nav.title")}</SheetTitle>
407
- <SheetDescription>{t("marketingShowcase.nav.description")}</SheetDescription>
408
- </SheetHeader>
409
- <SheetBody>
410
- <Flex
411
- direction="col"
412
- gap="xs"
413
- role="navigation"
414
- aria-label={t("marketingShowcase.nav.label")}
415
- >
416
- {NAV_KEYS.map((key) => (
417
- <SheetClose key={key} asChild>
418
- <Button variant="ghost" size="sm" align="start" fullWidth asChild>
419
- <a href={`#${key}`}>{t(`marketingShowcase.nav.${key}`)}</a>
420
- </Button>
421
- </SheetClose>
422
- ))}
423
- <Separator space="sm" />
424
- <SheetClose asChild>
425
- <Button variant="ghost" size="sm" align="start" fullWidth asChild>
426
- <a href="#start">{t("marketingShowcase.nav.signIn")}</a>
427
- </Button>
428
- </SheetClose>
429
- </Flex>
430
- </SheetBody>
431
- </SheetContent>
432
- </Sheet>
433
- </Flex>
434
- </Flex>
435
- }
436
- />
437
- </header>
438
-
439
- <main>
440
- {/* ── HERO ─────────────────────────────────────────────────────────────────────────── */}
441
- <section id="product" style={GLOW_HOST}>
442
- <div
443
- aria-hidden="true"
444
- className="ui-brand-glow"
445
- style={{ ...GLOW_LAYER, ...HERO_GLOW }}
446
- />
447
- <Flex
448
- direction="col"
449
- gap="none"
450
- measure="wide"
451
- pad={{ inline: 6, block: 24 }}
452
- style={ABOVE_GLOW}
453
- >
454
- <ResponsiveGrid columns={{ base: 1, lg: 2 }} gap="xl" align="start">
455
- <Reveal>
456
- <Flex direction="col" gap="lg">
457
- <Flex align="center" gap="sm" wrap>
458
- <Badge tone="primary" shape="pill">
459
- {t("marketingShowcase.hero.eyebrow")}
460
- </Badge>
461
- </Flex>
462
- {/* A real <h1> at the display tier — gh#826's `size` beside `level`, instead of
463
- the `.tx-display` class with a raw font-size both siblings used to carry. */}
464
- <Heading level={1} size="5xl" weight="bold">
465
- {t("marketingShowcase.hero.title")}
466
- </Heading>
467
- <Text size="xl" tone="muted">
468
- {t("marketingShowcase.hero.lead")}
469
- </Text>
470
- <Flex align="center" gap="sm" wrap>
471
- <Button size="lg" asChild>
472
- <a href="#start">
473
- {t("marketingShowcase.hero.primary")}
474
- <Icon as={ArrowRight} size="sm" tone="inherit" />
475
- </a>
476
- </Button>
477
- <Button size="lg" variant="outline" asChild>
478
- <a href="#start">
479
- <Icon as={CalendarClock} size="sm" tone="inherit" />
480
- {t("marketingShowcase.hero.secondary")}
481
- </a>
482
- </Button>
483
- </Flex>
484
- <Text size="xs" tone="muted">
485
- {t("marketingShowcase.hero.trust")}
486
- </Text>
487
- </Flex>
488
- </Reveal>
489
-
490
- <Reveal delay={2}>
491
- <Card variant="outline">
492
- <CardContent solo>
493
- <Flex direction="col" gap="md">
494
- <Flex direction="col" gap="none">
495
- <Heading level={2} size="md">
496
- {t("marketingShowcase.hero.panelTitle")}
497
- </Heading>
498
- <Text size="xs" tone="muted">
499
- {t("marketingShowcase.hero.panelNote")}
500
- </Text>
501
- </Flex>
502
- <ResponsiveGrid columns={{ base: 1, sm: 3 }} gap="sm">
503
- <StatCard
504
- label={t("marketingShowcase.hero.pending")}
505
- value={count.format(18)}
506
- accent="attention"
507
- />
508
- <StatCard
509
- label={t("marketingShowcase.hero.cleared")}
510
- value={count.format(146)}
511
- delta="+12"
512
- />
513
- <StatCard
514
- label={t("marketingShowcase.hero.median")}
515
- value={t("marketingShowcase.hero.medianValue")}
516
- />
517
- </ResponsiveGrid>
518
- <Separator space="xs" />
519
- <Flex direction="col" gap="xs">
520
- <Text size="xs" weight="medium" tone="muted">
521
- {t("marketingShowcase.hero.endpointLabel")}
522
- </Text>
523
- {/* 71 characters with nowhere to break. `whitespace="pre-wrap"` is the
524
- public prop for this (`overflow-wrap: break-word`) and it is enough
525
- HERE, because a column flex item has a definite inline size to break
526
- against. In the footer row it was not; see the note there. */}
527
- <Text as="code" chip size="2xs" whitespace="pre-wrap">
528
- {ENDPOINT_ID}
529
- </Text>
530
- <Text size="2xs" tone="muted">
531
- {t("marketingShowcase.hero.endpointNote")}
532
- </Text>
533
- </Flex>
534
- </Flex>
535
- </CardContent>
536
- </Card>
537
- </Reveal>
538
- </ResponsiveGrid>
539
- </Flex>
540
- </section>
541
-
542
- {/* ── LOGO WALL ────────────────────────────────────────────────────────────────────── */}
543
- <section aria-labelledby="logos-title">
544
- <Flex direction="col" gap="none" measure="wide" pad={{ inline: 6, block: 20 }}>
545
- <Flex direction="col" gap="lg">
546
- <Flex direction="col" gap="xs">
547
- <Heading level={2} size="lg" id="logos-title">
548
- {t("marketingShowcase.logos.title")}
549
- </Heading>
550
- <Text size="sm" tone="muted">
551
- {t("marketingShowcase.logos.caption")}
552
- </Text>
553
- </Flex>
554
- {/* `defaultPlay={false}` is the recommended posture; the pause/play control is
555
- Marquee's own real Button, in the tab order, with a localized name. */}
556
- <Marquee
557
- defaultPlay={false}
558
- speed="slow"
559
- gap="xl"
560
- fade
561
- pauseOnHover
562
- label={t("marketingShowcase.logos.marqueeLabel")}
563
- >
564
- {CUSTOMERS.map((customer) => (
565
- <Logo
566
- key={customer.name}
567
- glyph={customer.glyph}
568
- size="sm"
569
- wordmark={customer.name}
570
- />
571
- ))}
572
- </Marquee>
573
- </Flex>
574
- </Flex>
575
- </section>
576
-
577
- {/* ── FEATURE GRID ─────────────────────────────────────────────────────────────────── */}
578
- <section id="solutions" aria-labelledby="features-title">
579
- <Flex as="div" direction="col" gap="none" surface="muted">
580
- <Flex direction="col" gap="none" measure="wide" pad={{ inline: 6, block: 20 }}>
581
- <Flex direction="col" gap="xl">
582
- <Flex direction="col" gap="xs">
583
- <Heading level={2} size="3xl" weight="bold" id="features-title">
584
- {t("marketingShowcase.features.title")}
585
- </Heading>
586
- <Text size="lg" tone="muted">
587
- {t("marketingShowcase.features.lead")}
588
- </Text>
589
- </Flex>
590
- <ResponsiveGrid columns={{ base: 1, sm: 2, lg: 3 }} gap="md" align="stretch">
591
- {FEATURES.map((feature) => (
592
- <Card key={feature.key} hoverable>
593
- <CardContent solo>
594
- <Flex direction="col" gap="sm">
595
- {/* The doctrine's "icon medallion": Avatar square + a Lucide glyph. */}
596
- <Avatar shape="square" appearance="tinted" size="md">
597
- <AvatarFallback>
598
- <Icon as={feature.icon} size="sm" tone="primary" />
599
- </AvatarFallback>
600
- </Avatar>
601
- <Heading level={3} size="md">
602
- {t(`marketingShowcase.features.${feature.key}Title`)}
603
- </Heading>
604
- {feature.hasBody ? (
605
- <Text size="sm" tone="muted">
606
- {t(`marketingShowcase.features.${feature.key}Body`)}
607
- </Text>
608
- ) : null}
609
- {feature.key === "webhook" ? (
610
- <Text as="code" chip size="2xs" whitespace="pre-wrap">
611
- {ENDPOINT_ID}
612
- </Text>
613
- ) : null}
614
- </Flex>
615
- </CardContent>
616
- </Card>
617
- ))}
618
- </ResponsiveGrid>
619
- </Flex>
620
- </Flex>
621
- </Flex>
622
- </section>
623
-
624
- {/* ── TESTIMONIALS ─────────────────────────────────────────────────────────────────── */}
625
- <section aria-labelledby="quotes-title">
626
- <Flex direction="col" gap="none" measure="wide" pad={{ inline: 6, block: 20 }}>
627
- <Flex direction="col" gap="lg">
628
- <Heading level={2} size="3xl" weight="bold" id="quotes-title">
629
- {t("marketingShowcase.testimonials.title")}
630
- </Heading>
631
- <Carousel opts={{ align: "start", loop: true }}>
632
- <CarouselContent>
633
- {QUOTES.map((quote) => (
634
- <CarouselItem key={quote.key}>
635
- <Card variant="outline">
636
- <CardContent solo>
637
- <Flex direction="col" gap="md">
638
- {quote.rating === null ? null : (
639
- <Rating
640
- readOnly
641
- value={quote.rating}
642
- name={`quote-${quote.key}`}
643
- aria-label={t("marketingShowcase.testimonials.ratingLabel")}
644
- />
645
- )}
646
- <Text size="lg">
647
- {t(`marketingShowcase.testimonials.q${quote.key}`)}
648
- </Text>
649
- <Flex align="center" gap="sm">
650
- <Avatar size="sm">
651
- <AvatarFallback>
652
- {t(`marketingShowcase.testimonials.a${quote.key}`).slice(0, 1)}
653
- </AvatarFallback>
654
- </Avatar>
655
- <Flex direction="col" gap="none">
656
- <Text size="sm" weight="medium">
657
- {t(`marketingShowcase.testimonials.a${quote.key}`)}
658
- </Text>
659
- <Text size="xs" tone="muted">
660
- {t(`marketingShowcase.testimonials.r${quote.key}`)}
661
- </Text>
662
- </Flex>
663
- </Flex>
664
- </Flex>
665
- </CardContent>
666
- </Card>
667
- </CarouselItem>
668
- ))}
669
- </CarouselContent>
670
- {/* The three controls are DIRECT children of Carousel because the component
671
- places them itself: `.ui-carousel-previous` / `-next` are `position: absolute`
672
- against `.ui-carousel`, and `.ui-carousel-dots` carries its own block padding.
673
- Wrapping them in a Flex row produced an empty flex item and moved nothing.
674
- Their accessible names are the component's own (`dataDisplay.carousel.*`). */}
675
- <CarouselPrevious />
676
- <CarouselNext />
677
- <CarouselDots />
678
- </Carousel>
679
- </Flex>
680
- </Flex>
681
- </section>
682
-
683
- {/* ── PRICING ──────────────────────────────────────────────────────────────────────── */}
684
- <section id="pricing" aria-labelledby="pricing-title">
685
- <Flex as="div" direction="col" gap="none" surface="muted">
686
- <Flex direction="col" gap="none" measure="wide" pad={{ inline: 6, block: 20 }}>
687
- <Flex direction="col" gap="xl">
688
- <Flex direction="col" gap="md">
689
- <Heading level={2} size="3xl" weight="bold" id="pricing-title">
690
- {t("marketingShowcase.pricing.title")}
691
- </Heading>
692
- <Text size="lg" tone="muted">
693
- {t("marketingShowcase.pricing.lead")}
694
- </Text>
695
- {/* FeatureList + Card accent + Segmented. The plan said pricing needs nothing
696
- new, and it needed nothing new. */}
697
- <Segmented
698
- value={cycle}
699
- onValueChange={setCycle}
700
- aria-label={t("marketingShowcase.pricing.cycleLabel")}
701
- options={[
702
- { value: "monthly", label: t("marketingShowcase.pricing.monthly") },
703
- {
704
- value: "yearly",
705
- label: t("marketingShowcase.pricing.yearly"),
706
- count: 2,
707
- countLabel: t("marketingShowcase.pricing.saving"),
708
- },
709
- ]}
710
- />
711
- </Flex>
712
- <ResponsiveGrid columns={{ base: 1, md: 3 }} gap="md" align="stretch">
713
- {PLANS.map((plan) => {
714
- const amount = cycle === "yearly" ? plan.yearlyMonthly : plan.monthly;
715
- return (
716
- <Card
717
- key={plan.key}
718
- accent={plan.accent ? "primary" : undefined}
719
- accentPlacement={plan.accent ? "perimeter" : undefined}
720
- >
721
- <CardContent solo>
722
- <Flex direction="col" gap="md">
723
- <Flex align="center" gap="xs" wrap>
724
- <Heading level={3} size="lg">
725
- {t(`marketingShowcase.pricing.${plan.key}Name`)}
726
- </Heading>
727
- {plan.badges.map((badge) => (
728
- <Badge
729
- key={badge}
730
- as="span"
731
- shape="pill"
732
- tone={badge === "popular" ? "primary" : "muted"}
733
- variant={badge === "fresh" ? "outline" : "default"}
734
- >
735
- {t(`marketingShowcase.pricing.${badge}`)}
736
- </Badge>
737
- ))}
738
- </Flex>
739
- <Flex direction="col" gap="none">
740
- {/* The quoted plan has NO figure: an empty slot beside two full
741
- ones, in the row where a missing number usually collapses. */}
742
- <Text size="4xl" weight="bold" tabular>
743
- {amount === null
744
- ? t("marketingShowcase.pricing.quoted")
745
- : money.format(amount)}
746
- </Text>
747
- <Text size="xs" tone="muted">
748
- {amount === null
749
- ? t("marketingShowcase.pricing.quotedNote")
750
- : cycle === "yearly"
751
- ? t("marketingShowcase.pricing.billedYearly")
752
- : t("marketingShowcase.pricing.perMonth")}
753
- </Text>
754
- </Flex>
755
- <Text size="sm" tone="muted">
756
- {t(`marketingShowcase.pricing.${plan.key}Note`)}
757
- </Text>
758
- <FeatureList
759
- items={plan.features.map((feature) => ({
760
- state: feature.state,
761
- label: t(`marketingShowcase.pricing.${feature.key}`),
762
- description: feature.limitKey
763
- ? t(`marketingShowcase.pricing.${feature.limitKey}`)
764
- : undefined,
765
- }))}
766
- />
767
- <Button fullWidth variant={plan.accent ? "default" : "outline"} asChild>
768
- <a href="#start">
769
- {amount === null
770
- ? t("marketingShowcase.pricing.ctaQuote")
771
- : t("marketingShowcase.pricing.cta")}
772
- </a>
773
- </Button>
774
- </Flex>
775
- </CardContent>
776
- </Card>
777
- );
778
- })}
779
- </ResponsiveGrid>
780
- </Flex>
781
- </Flex>
782
- </Flex>
783
- </section>
784
-
785
- {/* ── CTA BAND ─────────────────────────────────────────────────────────────────────── */}
786
- <section id="start" style={GLOW_HOST} aria-labelledby="cta-title">
787
- <div
788
- aria-hidden="true"
789
- className="ui-brand-glow"
790
- style={{ ...GLOW_LAYER, ...CTA_GLOW }}
791
- />
792
- <Flex
793
- direction="col"
794
- gap="none"
795
- measure="wide"
796
- pad={{ inline: 6, block: 20 }}
797
- style={ABOVE_GLOW}
798
- >
799
- <Reveal on="view">
800
- <Flex direction="col" gap="md" align="center">
801
- <Heading level={2} size="4xl" weight="bold" align="center" id="cta-title">
802
- {t("marketingShowcase.cta.title")}
803
- </Heading>
804
- <Text size="lg" tone="muted" align="center">
805
- {t("marketingShowcase.cta.lead")}
806
- </Text>
807
- <Flex align="center" gap="sm" wrap justify="center">
808
- <Button size="lg" asChild>
809
- <a href={`https://${SITE}`}>
810
- {t("marketingShowcase.cta.primary")}
811
- <Icon as={ArrowRight} size="sm" tone="inherit" />
812
- </a>
813
- </Button>
814
- <Button size="lg" variant="outline" asChild>
815
- <a href={`https://${SITE}`}>{t("marketingShowcase.cta.secondary")}</a>
816
- </Button>
817
- </Flex>
818
- <Text size="xs" tone="muted" align="center">
819
- {t("marketingShowcase.cta.note")}
820
- </Text>
821
- </Flex>
822
- </Reveal>
823
- </Flex>
824
- </section>
825
- </main>
826
-
827
- {/* ── FOOTER ───────────────────────────────────────────────────────────────────────── */}
828
- <footer>
829
- <Flex as="div" direction="col" gap="none" surface="muted">
830
- <Flex direction="col" gap="none" measure="wide" pad={{ inline: 6, block: 20 }}>
831
- <Flex direction="col" gap="lg">
832
- {/* ResponsiveGrid.Item span — the asymmetric footer both siblings hand-wrote a
833
- `grid-template-columns: 1.4fr 1fr 1fr 1fr` for. It has shipped the whole time. */}
834
- <ResponsiveGrid columns={12} gap="lg">
835
- <ResponsiveGrid.Item span={{ base: 12, sm: 12, md: 4, lg: 4 }}>
836
- <Flex direction="col" gap="sm">
837
- <Logo
838
- glyph="E"
839
- wordmark={t("marketingShowcase.brand.name")}
840
- productSuffix={t("marketingShowcase.brand.suffix")}
841
- />
842
- <Text size="sm" tone="muted">
843
- {t("marketingShowcase.footer.addressLabel")} ·{" "}
844
- {t("marketingShowcase.footer.address")}
845
- </Text>
846
- <Text size="sm" tone="muted">
847
- {t("marketingShowcase.footer.salesLine")} · sales@{SITE}
848
- </Text>
849
- </Flex>
850
- </ResponsiveGrid.Item>
851
- {FOOTER_COLUMNS.map((column) => (
852
- <ResponsiveGrid.Item key={column.key} span={{ base: 12, sm: 6, md: 2, lg: 2 }}>
853
- <Flex
854
- direction="col"
855
- gap="xs"
856
- align="start"
857
- role="navigation"
858
- aria-label={t(`marketingShowcase.footer.${column.key}`)}
859
- >
860
- <Text size="xs" weight="medium" tone="muted">
861
- {t(`marketingShowcase.footer.${column.key}`)}
862
- </Text>
863
- {column.links.map((link) => (
864
- <Button key={link} variant="link" size="sm" asChild>
865
- <a href={`https://${SITE}`}>{t(`marketingShowcase.footer.${link}`)}</a>
866
- </Button>
867
- ))}
868
- </Flex>
869
- </ResponsiveGrid.Item>
870
- ))}
871
- </ResponsiveGrid>
872
- <Separator space="sm" />
873
- <Flex align="center" justify="between" gap="sm" wrap>
874
- <Text size="xs" tone="muted">
875
- {year} · {t("marketingShowcase.footer.rights")}
876
- </Text>
877
- {/* The hostile case, and the one that actually broke: `whitespace="pre-wrap"`
878
- gives `overflow-wrap: break-word`, which does NOT reduce a box's MIN-CONTENT
879
- size, and a flex item keeps `min-width: auto`. So in this row the 71-character
880
- id held the whole line open and the DOCUMENT scrolled: 457px at 390, 375 and
881
- 320 alike. `Flex fill` is the documented answer (`flex: 1 1 0` +
882
- `min-inline-size: 0`, layout.css:167) and it is what makes the break fire. */}
883
- <Flex fill direction="col" gap="none">
884
- <Text size="2xs" tone="muted" whitespace="pre-wrap" align="end">
885
- {ENDPOINT_ID}
886
- </Text>
887
- </Flex>
888
- </Flex>
889
- </Flex>
890
- </Flex>
891
- </Flex>
892
- </footer>
893
- </Flex>
894
- );
895
- }