@cyberskill/design 1.0.0 → 1.1.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 (264) hide show
  1. package/DESIGN.md +10 -9
  2. package/README.md +31 -28
  3. package/SKILL.md +13 -9
  4. package/VERSION +1 -1
  5. package/_ds_bundle.js +660 -202
  6. package/_ds_manifest.json +1 -1
  7. package/_esm/cs.mjs +14 -8
  8. package/_esm/react.d.ts +216 -0
  9. package/_esm/react.mjs +114 -0
  10. package/base/collections.css +31 -0
  11. package/base/components.css +3 -0
  12. package/base/data.css +33 -0
  13. package/base/forms.css +8 -0
  14. package/base/interaction.css +1 -0
  15. package/base/typography.css +6 -0
  16. package/components/_i18n/strings.js +8 -4
  17. package/components/ai/ai-conversation.card.html +2 -2
  18. package/components/ai/ai-lumi.card.html +2 -2
  19. package/components/ai/ai.card.html +2 -2
  20. package/components/brand/brand.card.html +2 -2
  21. package/components/button/buttons.card.html +2 -2
  22. package/components/data/AspectRatio.d.ts +16 -0
  23. package/components/data/AspectRatio.figma.tsx +12 -0
  24. package/components/data/AspectRatio.jsx +16 -0
  25. package/components/data/AspectRatio.prompt.md +7 -0
  26. package/components/data/Collapsible.d.ts +21 -0
  27. package/components/data/Collapsible.figma.tsx +12 -0
  28. package/components/data/Collapsible.jsx +49 -0
  29. package/components/data/Collapsible.prompt.md +7 -0
  30. package/components/data/Image.d.ts +4 -0
  31. package/components/data/Image.prompt.md +2 -2
  32. package/components/data/Item.d.ts +26 -0
  33. package/components/data/Item.figma.tsx +12 -0
  34. package/components/data/Item.jsx +63 -0
  35. package/components/data/Item.prompt.md +10 -0
  36. package/components/data/ScrollArea.d.ts +16 -0
  37. package/components/data/ScrollArea.figma.tsx +12 -0
  38. package/components/data/ScrollArea.jsx +25 -0
  39. package/components/data/ScrollArea.prompt.md +7 -0
  40. package/components/data/collections.card.html +15 -4
  41. package/components/data/data.card.html +15 -4
  42. package/components/datatable/datatable.card.html +2 -2
  43. package/components/dialog/dialog.card.html +2 -2
  44. package/components/feedback/feedback-2.card.html +2 -2
  45. package/components/feedback/feedback.card.html +2 -2
  46. package/components/forms/Cascader.jsx +5 -3
  47. package/components/forms/Editor.prompt.md +1 -1
  48. package/components/forms/InputGroup.d.ts +4 -0
  49. package/components/forms/InputGroup.jsx +38 -8
  50. package/components/forms/InputGroup.prompt.md +3 -3
  51. package/components/forms/NativeSelect.d.ts +22 -0
  52. package/components/forms/NativeSelect.figma.tsx +12 -0
  53. package/components/forms/NativeSelect.jsx +56 -0
  54. package/components/forms/NativeSelect.prompt.md +10 -0
  55. package/components/forms/NumberField.d.ts +5 -0
  56. package/components/forms/NumberField.jsx +51 -7
  57. package/components/forms/NumberField.prompt.md +2 -2
  58. package/components/forms/SegmentedControl.jsx +1 -1
  59. package/components/forms/TagInput.d.ts +3 -0
  60. package/components/forms/TagInput.jsx +62 -20
  61. package/components/forms/TagInput.prompt.md +2 -2
  62. package/components/forms/forms-2.card.html +2 -2
  63. package/components/forms/forms.card.html +5 -4
  64. package/components/icon/Icon.prompt.md +1 -1
  65. package/components/icon/icon.card.html +2 -2
  66. package/components/logo/Logo.jsx +2 -1
  67. package/components/logo/logo.card.html +2 -2
  68. package/components/navigation/Menu.jsx +14 -1
  69. package/components/navigation/navigation.card.html +2 -2
  70. package/components/navigation/shell.card.html +2 -2
  71. package/components/overlays/AlertDialog.d.ts +29 -0
  72. package/components/overlays/AlertDialog.figma.tsx +12 -0
  73. package/components/overlays/AlertDialog.jsx +142 -0
  74. package/components/overlays/AlertDialog.prompt.md +12 -0
  75. package/components/overlays/Drawer.jsx +1 -1
  76. package/components/overlays/Popconfirm.jsx +14 -1
  77. package/components/overlays/Popover.jsx +14 -1
  78. package/components/overlays/alertdialog.card.html +42 -0
  79. package/components/overlays/overlays.card.html +2 -2
  80. package/components/textfield/textfield.card.html +2 -2
  81. package/docs/benchmark-rubric.md +46 -0
  82. package/docs/ci-cd.md +17 -11
  83. package/docs/consumer-grant.md +37 -0
  84. package/docs/consuming.md +45 -16
  85. package/docs/contrast-report.md +91 -103
  86. package/docs/conventions.md +12 -9
  87. package/docs/decisions.md +33 -10
  88. package/docs/deploy.md +1 -1
  89. package/docs/design-styles.md +26 -8
  90. package/docs/figma.md +3 -3
  91. package/docs/live-hub.md +5 -3
  92. package/docs/products.md +13 -11
  93. package/docs/quality-gates.md +35 -21
  94. package/docs/release-notes.md +13 -3
  95. package/docs/status/assets/favicon.svg +5 -0
  96. package/docs/status/assets/status-legacy.css +399 -0
  97. package/docs/status/assets/status-legacy.js +505 -0
  98. package/docs/status/assets/status.css +644 -0
  99. package/docs/status/assets/status.js +1308 -0
  100. package/docs/status/data/status-feed.json +1 -0
  101. package/docs/status/data/task/TASK-REL-001.js +1 -0
  102. package/docs/status/index.html +45 -0
  103. package/docs/status/roadmap.html +4 -0
  104. package/docs/status/status-legacy.html +121 -0
  105. package/docs/storybook.md +5 -4
  106. package/docs/sync.md +3 -2
  107. package/docs/tasks/BACKLOG.md +25 -0
  108. package/docs/tasks/release/TASK-REL-001-launch-1-1-0/spec.md +55 -0
  109. package/docs/template-schema-v2.md +15 -3
  110. package/docs/vi/benchmark-rubric.md +46 -0
  111. package/docs/vi/ci-cd.md +17 -11
  112. package/docs/vi/consumer-grant.md +37 -0
  113. package/docs/vi/consuming.md +45 -16
  114. package/docs/vi/contrast-report.md +94 -106
  115. package/docs/vi/conventions.md +12 -9
  116. package/docs/vi/decisions.md +33 -10
  117. package/docs/vi/deploy.md +1 -1
  118. package/docs/vi/design-styles.md +26 -8
  119. package/docs/vi/figma.md +3 -3
  120. package/docs/vi/live-hub.md +5 -3
  121. package/docs/vi/products.md +13 -11
  122. package/docs/vi/quality-gates.md +35 -21
  123. package/docs/vi/release-notes.md +18 -8
  124. package/docs/vi/storybook.md +5 -4
  125. package/docs/vi/sync.md +3 -2
  126. package/docs/vi/template-schema-v2.md +15 -3
  127. package/docs/viewer.html +2 -2
  128. package/fonts/spacegrotesk-var-latin-ext.woff2 +0 -0
  129. package/fonts/spacegrotesk-var-latin.woff2 +0 -0
  130. package/fonts/spacegrotesk-var-vietnamese.woff2 +0 -0
  131. package/guidelines/atomic-view.html +40 -27
  132. package/guidelines/elements-geometry.html +69 -0
  133. package/guidelines/elements-variants.html +17 -17
  134. package/guidelines/type-families.html +16 -10
  135. package/llms.txt +17 -11
  136. package/package.json +38 -16
  137. package/styles.css +1 -0
  138. package/templates/ai-cluster-demo.html +29 -14
  139. package/templates/app-shell/support.js +4 -4
  140. package/templates/article/content-schema.json +6 -0
  141. package/templates/article/support.js +4 -4
  142. package/templates/auth/support.js +4 -4
  143. package/templates/bod-deck/support.js +4 -4
  144. package/templates/bod-investor-update/support.js +4 -4
  145. package/templates/bod-memo/support.js +4 -4
  146. package/templates/bod-minutes/content-schema.json +12 -0
  147. package/templates/bod-minutes/support.js +4 -4
  148. package/templates/bod-report/support.js +4 -4
  149. package/templates/bod-resolution/support.js +4 -4
  150. package/templates/culture-event-invite/support.js +4 -4
  151. package/templates/dashboard/support.js +4 -4
  152. package/templates/delivery-change-note/support.js +4 -4
  153. package/templates/delivery-kickoff/support.js +4 -4
  154. package/templates/delivery-qbr-deck/support.js +4 -4
  155. package/templates/delivery-runbook/content-schema.json +6 -0
  156. package/templates/delivery-runbook/support.js +4 -4
  157. package/templates/delivery-status-email/support.js +4 -4
  158. package/templates/doc-style-guide/DocStyleGuide.dc.html +2 -2
  159. package/templates/doc-style-guide/support.js +4 -4
  160. package/templates/doc-suite-index/support.js +4 -4
  161. package/templates/doc-templates/DocTemplates.dc.html +1 -1
  162. package/templates/doc-templates/support.js +4 -4
  163. package/templates/email/support.js +4 -4
  164. package/templates/email-safe/README.md +17 -4
  165. package/templates/email-safe/email-launch.html +3 -3
  166. package/templates/email-safe/email-newsletter.html +1 -1
  167. package/templates/finance-dunning-email/support.js +4 -4
  168. package/templates/finance-expense-report/support.js +4 -4
  169. package/templates/finance-invoice/support.js +4 -4
  170. package/templates/finance-quote/support.js +4 -4
  171. package/templates/hr-announcement/support.js +4 -4
  172. package/templates/hr-interview-kit/content-schema.json +12 -0
  173. package/templates/hr-interview-kit/support.js +4 -4
  174. package/templates/hr-offboarding/content-schema.json +12 -0
  175. package/templates/hr-offboarding/support.js +4 -4
  176. package/templates/hr-performance-review/content-schema.json +12 -0
  177. package/templates/hr-performance-review/support.js +4 -4
  178. package/templates/hr-pip/content-schema.json +12 -0
  179. package/templates/hr-pip/support.js +4 -4
  180. package/templates/legal-msa/content-schema.json +16 -0
  181. package/templates/legal-msa/support.js +4 -4
  182. package/templates/legal-sow/support.js +4 -4
  183. package/templates/marketing-campaign-brief/support.js +4 -4
  184. package/templates/marketing-case-study/support.js +4 -4
  185. package/templates/marketing-launch/support.js +4 -4
  186. package/templates/marketing-newsletter/support.js +4 -4
  187. package/templates/marketing-page/content-schema.json +0 -1
  188. package/templates/marketing-page/support.js +4 -4
  189. package/templates/marketing-press-release/support.js +4 -4
  190. package/templates/marketing-social-kit/support.js +4 -4
  191. package/templates/playground.html +8 -4
  192. package/templates/sales-one-pager/support.js +4 -4
  193. package/templates/sales-proposal-deck/support.js +4 -4
  194. package/templates/settings/Settings.dc.html +26 -14
  195. package/templates/settings/content-schema.json +36 -0
  196. package/templates/settings/support.js +4 -4
  197. package/templates/slide-deck/support.js +4 -4
  198. package/templates/team-meeting-agenda/content-schema.json +16 -0
  199. package/templates/team-meeting-agenda/support.js +4 -4
  200. package/templates/tech-incident-report/support.js +4 -4
  201. package/templates/tech-release-notes/support.js +4 -4
  202. package/templates/tech-retro/content-schema.json +12 -0
  203. package/templates/tech-retro/support.js +4 -4
  204. package/templates/tech-rfc/content-schema.json +6 -0
  205. package/templates/tech-rfc/support.js +4 -4
  206. package/templates/vn-appointment-transfer/support.js +4 -4
  207. package/templates/vn-certificate-of-employment/support.js +4 -4
  208. package/templates/vn-code-of-conduct/support.js +4 -4
  209. package/templates/vn-compensation-regulation/support.js +4 -4
  210. package/templates/vn-contract-amendment/support.js +4 -4
  211. package/templates/vn-contractor-agreement/support.js +4 -4
  212. package/templates/vn-data-protection-policy/support.js +4 -4
  213. package/templates/vn-disciplinary-case-file/support.js +4 -4
  214. package/templates/vn-disciplinary-schedule/content-schema.json +15 -0
  215. package/templates/vn-disciplinary-schedule/support.js +4 -4
  216. package/templates/vn-employee-request/support.js +4 -4
  217. package/templates/vn-exit-handover/support.js +4 -4
  218. package/templates/vn-foreign-employee-pack/support.js +4 -4
  219. package/templates/vn-grassroots-democracy/support.js +4 -4
  220. package/templates/vn-infosec-policy/support.js +4 -4
  221. package/templates/vn-internal-labor-regulations/support.js +4 -4
  222. package/templates/vn-internship-agreement/support.js +4 -4
  223. package/templates/vn-job-description/support.js +4 -4
  224. package/templates/vn-labor-contract/support.js +4 -4
  225. package/templates/vn-labour-management-book/content-schema.json +15 -0
  226. package/templates/vn-labour-management-book/support.js +4 -4
  227. package/templates/vn-mutual-nda/support.js +4 -4
  228. package/templates/vn-ndnca-ip/support.js +4 -4
  229. package/templates/vn-offer-letter/support.js +4 -4
  230. package/templates/vn-onboarding-checklist/support.js +4 -4
  231. package/templates/vn-pdpl-consent/support.js +4 -4
  232. package/templates/vn-performance-evaluation-regulation/support.js +4 -4
  233. package/templates/vn-performance-review-form/support.js +4 -4
  234. package/templates/vn-phantom-stock/support.js +4 -4
  235. package/templates/vn-probation-contract/support.js +4 -4
  236. package/templates/vn-receipt-acknowledgement/content-schema.json +15 -0
  237. package/templates/vn-receipt-acknowledgement/support.js +4 -4
  238. package/templates/vn-remote-work-policy/support.js +4 -4
  239. package/templates/vn-resignation-letter/support.js +4 -4
  240. package/templates/vn-salary-scale/content-schema.json +15 -0
  241. package/templates/vn-salary-scale/support.js +4 -4
  242. package/templates/vn-sow-appendix/support.js +4 -4
  243. package/templates/vn-termination-decision/support.js +4 -4
  244. package/templates/vn-total-rewards-appendix/support.js +4 -4
  245. package/templates/vn-training-commitment/support.js +4 -4
  246. package/templates/vn-travel-expense-policy/support.js +4 -4
  247. package/tokens/element-seeds.json +112 -0
  248. package/tokens/elements.css +274 -187
  249. package/tokens/fonts.css +12 -3
  250. package/tokens/native/CSTokens.kt +84 -68
  251. package/tokens/native/CSTokens.swift +84 -68
  252. package/tokens/native/cs_tokens.dart +84 -68
  253. package/tokens/provenance.json +9 -9
  254. package/tokens/styles.css +15 -0
  255. package/tokens/tokens.dtcg.json +258 -233
  256. package/tokens/tokens.js +168 -167
  257. package/tokens/tokens.json +167 -166
  258. package/tokens/typography.css +9 -1
  259. package/ui_kits/status-hub/README.md +1 -2
  260. package/ui_kits/status-hub/index.html +2 -2
  261. package/ui_kits/status-hub/settings.html +6 -3
  262. package/ui_kits/website/chat.html +2 -2
  263. package/ui_kits/website/index.html +2 -2
  264. package/ui_kits/status-hub/identity-lab.html +0 -134
@@ -1,4 +1,4 @@
1
- <!-- @dsCard group="Atomic View" viewport="1280x820" name="Atomic View" subtitle="Storybook-style browser — every component + variants, live across Theme × Element × Language" -->
1
+ <!-- @dsCard group="Atomic View" viewport="1280x820" name="Atomic View" subtitle="Storybook-style browser — every component + variants, live across Theme × Element × Language × Style" -->
2
2
  <!DOCTYPE html>
3
3
  <html lang="en">
4
4
  <head>
@@ -77,8 +77,8 @@
77
77
  @media (max-width:820px){.app{grid-template-columns:1fr}.nav{display:none}.grid2{grid-template-columns:1fr}}
78
78
  </style>
79
79
  <script src="nav-model.cjs"></script>
80
- <script src="https://unpkg.com/react@18.3.1/umd/react.development.js" integrity="sha384-hD6/rw4ppMLGNu3tX5cjIb+uRZ7UkRJ6BPkLpg4hAu/6onKUg4lLsHAs9EBPT82L" crossorigin="anonymous"></script>
81
- <script src="https://unpkg.com/react-dom@18.3.1/umd/react-dom.development.js" integrity="sha384-u6aeetuaXnQ38mYT8rp6sbXaQe3NL9t+IBXmnYxwkUI2Hw4bsp2Wvmx4yRQF1uAm" crossorigin="anonymous"></script>
80
+ <script src="https://unpkg.com/umd-react@19.2.8/dist/react.development.js" integrity="sha384-r22tQd8qRIHDPIkmdXZcVtvPi1Tj2x1QaW2tmFQHEvHscATUnHQ5siTyxWw5PMUs" crossorigin="anonymous"></script>
81
+ <script src="https://unpkg.com/umd-react@19.2.8/dist/react-dom.development.js" integrity="sha384-gJZYmumEmwqVmX3JVsLZq+4QrxoPGh/BW47Rk7SqNPCPFpTGnRtvmeRPJ7//ZDPk" crossorigin="anonymous"></script>
82
82
  <script src="https://unpkg.com/@babel/standalone@7.29.0/babel.min.js" integrity="sha384-m08KidiNqLdpJqLq95G/LEi8Qvjl/xUYll3QILypMoQ65QorJ9Lvtp2RXYGBFj1y" crossorigin="anonymous"></script>
83
83
  <script src="../_ds_bundle.js"></script>
84
84
  </head>
@@ -89,10 +89,10 @@ const { useState, useEffect, useRef } = React;
89
89
  const NS = window[Object.keys(window).find(k=>/^CyberSkillDesignSystem_[0-9a-f]{6}$/.test(k))] || {};
90
90
  const {
91
91
  Button, Icon, Badge, Tag, Alert, Toast, ToastStack, Spinner, ProgressBar, Skeleton, StatusIndicator, EmptyState,
92
- TextField, Select, Checkbox, RadioGroup, Switch, Textarea, SearchField, NumberField, Slider, FileUpload, SegmentedControl,
92
+ TextField, Select, NativeSelect, Checkbox, RadioGroup, Switch, Textarea, SearchField, NumberField, Slider, FileUpload, SegmentedControl,
93
93
  Tabs, Breadcrumb, Pagination, Menu, MenuItem, Sidebar, NavItem, Steps, CommandPalette,
94
- DataTable, Card, CardHeader, CardBody, CardFooter, Stat, Avatar, AvatarGroup, Tooltip, Divider,
95
- List, ListItem, DescriptionList, Timeline, Accordion, Kbd, CodeBlock, Dialog, Drawer, Popover,
94
+ DataTable, Card, CardHeader, CardBody, CardFooter, Stat, Avatar, AvatarGroup, Tooltip, Divider, ScrollArea, AspectRatio, Item,
95
+ List, ListItem, DescriptionList, Timeline, Accordion, Collapsible, Kbd, CodeBlock, Dialog, Drawer, Popover, AlertDialog,
96
96
  PromptInput, ChatMessage, ConfidenceMeter, AIDisclosureBadge, HumanReviewGate, PromptSuggestions, TypingIndicator, CitationList,
97
97
  LumiAvatar, Logo, Toggle, Rating, InputOTP, ButtonGroup, Combobox, InputGroup, TagInput, Calendar, DatePicker, TimePicker,
98
98
  HoverCard, Popconfirm, ContextMenu, FloatingActionButton, Result, InlineEdit, Link, Anchor, Image, Toolbar,
@@ -125,13 +125,14 @@ function Controlled({spec}){
125
125
  function TabsD({L}){ const [v,setV]=useState("board"); const V=L==="vi"; return has(Tabs)?<Tabs value={v} onChange={setV} tabs={[{value:"board",label:V?"Bảng công việc":"Board"},{value:"table",label:V?"Bảng dữ liệu":"Table",count:6},{value:"rel",label:V?"Phát hành":"Releases"}]}/>:<Miss n="Tabs"/>; }
126
126
  function PaginationD(){ const [p,setP]=useState(3); return has(Pagination)?<Pagination page={p} pageCount={12} onChange={setP}/>:<Miss n="Pagination"/>; }
127
127
  function SegmentedD({L}){ const [v,setV]=useState("board"); const V=L==="vi"; return has(SegmentedControl)?<SegmentedControl value={v} onChange={setV} options={[{value:"board",label:V?"Bảng công việc":"Board"},{value:"table",label:V?"Bảng dữ liệu":"Table"},{value:"rel",label:V?"Phát hành":"Releases"}]}/>:<Miss n="SegmentedControl"/>; }
128
- function SliderD(){ const [v,setV]=useState(60); return has(Slider)?<div style={{flex:1,minWidth:200}}><Slider min={0} max={100} value={v} onChange={(e)=>setV(+e.target.value)}/></div>:<Miss n="Slider"/>; }
128
+ function SliderD({L}){ const [v,setV]=useState(60); return has(Slider)?<div style={{flex:1,minWidth:200}}><Slider min={0} max={100} value={v} onChange={(e)=>setV(+e.target.value)} aria-label={L==="vi"?"Tiến độ":"Progress"}/></div>:<Miss n="Slider"/>; }
129
129
  function SearchD({L}){ const [q,setQ]=useState("Design System"); return has(SearchField)?<div style={{flex:1,minWidth:240}}><SearchField value={q} onChange={setQ} placeholder={L==="vi"?"Tìm dự án…":"Search projects…"}/></div>:<Miss n="SearchField"/>; }
130
- function NumberD(){ const [n,setN]=useState(3); return has(NumberField)?<NumberField value={n} onChange={setN} min={1} max={20}/>:<Miss n="NumberField"/>; }
130
+ function NumberD({L}){ const [n,setN]=useState(3); return has(NumberField)?<NumberField label={L==="vi"?"Số lượng":"Quantity"} value={n} onChange={setN} min={1} max={20}/>:<Miss n="NumberField"/>; }
131
131
  function DateD({L}){ const [d,setD]=useState(()=>new Date(2026,6,18)); const [tm,setTm]=useState("09:30"); return <div className="srow" style={{alignItems:"flex-start",minHeight:400}}>{has(DatePicker)?<DatePicker value={d} onChange={setD}/>:<Miss n="DatePicker"/>}{has(TimePicker)?<TimePicker value={tm} onChange={setTm} step={15}/>:<Miss n="TimePicker"/>}</div>; }
132
132
  function CalD({L}){ const [d,setD]=useState(()=>new Date(2026,6,18)); return has(Calendar)?<Calendar value={d} onChange={setD}/>:<Miss n="Calendar"/>; }
133
133
  function ColorD({L}){ const [c,setC]=useState("#F4BA17"); return has(ColorPicker)?<div style={{minHeight:210}}><ColorPicker value={c} onChange={setC}/></div>:<Miss n="ColorPicker"/>; }
134
134
  function TourD({L}){ const [on,setOn]=useState(false); return has(Tour,Button)?<div><Button size="sm" variant="secondary" onClick={()=>setOn(true)}>{L==="vi"?"Bắt đầu hướng dẫn":"Start tour"}</Button><Tour open={on} onClose={()=>setOn(false)} steps={L==="vi"?[{target:"#toggle",title:"Toggle",body:"Nút bật/tắt đứng độc lập."},{target:"#rating",title:"Rating",body:"Đánh giá sao màu Ochre."}]:[{target:"#toggle",title:"Toggle",body:"A standalone pressable button."},{target:"#rating",title:"Rating",body:"Ochre star rating."}]}/></div>:<Miss n="Tour"/>; }
135
+ function AlertDialogD({L}){ const [on,setOn]=useState(false); const V=L==="vi"; return has(AlertDialog,Button)?<div><Button variant="danger-ghost" size="sm" onClick={()=>setOn(true)}>{V?"Xoá không gian":"Delete workspace"}</Button><AlertDialog open={on} onOpenChange={setOn} title={V?"Xoá không gian làm việc?":"Delete workspace?"} description={V?"Xoá mọi dự án. Không thể hoàn tác.":"Removes every project. This cannot be undone."} tone="destructive" onConfirm={()=>{}}/></div>:<Miss n="AlertDialog"/>; }
135
136
  function GridD({L}){ const [sel,setSel]=useState(["CDS"]); const V=L==="vi"; return has(DataGrid)?<DataGrid selectable selected={sel} onSelect={setSel} rowKey="key" height={220} columns={[{key:"key",header:V?"Mã":"Key",sortable:true},{key:"name",header:V?"Dự án":"Project",sortable:true},{key:"pct",header:V?"Tiến độ":"Progress",sortable:true,render:(r)=>r.pct+"%"}]} rows={[{key:"CDS",name:"Design System",pct:72},{key:"GENIE",name:"Lumi Genie",pct:58},{key:"SITE",name:"cyberskill.world",pct:84}]}/>:<Miss n="DataGrid"/>; }
136
137
  function SortD({L}){ const [it,setIt]=useState(L==="vi"?[{key:"a",label:"Ước một điều"},{key:"b",label:"Định hình"},{key:"c",label:"Xây để ra mắt"}]:[{key:"a",label:"Make a wish"},{key:"b",label:"Shape it"},{key:"c",label:"Build to ship"}]); return has(Sortable)?<Sortable items={it} onChange={setIt}/>:<Miss n="Sortable"/>; }
137
138
  function TreeSelD({L}){ const [k,setK]=useState("ds"); return has(TreeSelect)?<TreeSelect value={k} onChange={setK} nodes={L==="vi"?[{key:"p",label:"Nền tảng",children:[{key:"ds",label:"Design System"},{key:"tok",label:"Token Pipeline"}]},{key:"ai",label:"AI",children:[{key:"lumi",label:"Lumi Genie"}]}]:[{key:"p",label:"Platform",children:[{key:"ds",label:"Design System"},{key:"tok",label:"Token Pipeline"}]},{key:"ai",label:"AI",children:[{key:"lumi",label:"Lumi Genie"}]}]}/>:<Miss n="TreeSelect"/>; }
@@ -167,21 +168,24 @@ const STORIES = [
167
168
  { tier:"Atom", name:"Spinner · ProgressBar · Skeleton", grp:"Feedback", controls:[{k:"value",type:"range",min:0,max:100,step:1,def:72},{k:"label",type:"text",def:"v1.6 progress"}], renderC:(v)=> has(ProgressBar)?<div style={{maxWidth:320}}><ProgressBar value={v.value} label={v.label}/></div>:<Miss n="ProgressBar"/>, render:()=> has(Spinner,ProgressBar,Skeleton)?<div className="srow"><Spinner size={24}/><div style={{flex:"1 1 200px"}}><ProgressBar value={72} label="v1.6 progress"/></div><div style={{flex:"1 1 160px"}}><Skeleton lines={2}/></div></div>:<Miss n="Spinner/ProgressBar/Skeleton"/> },
168
169
  { tier:"Atom", name:"Avatar", grp:"Data", controls:[{k:"name",type:"text",def:"Nguyễn Vũ"},{k:"size",type:"select",options:["sm","md","lg"],def:"lg"}], renderC:(v)=> has(Avatar)?<Avatar name={v.name} size={v.size}/>:<Miss n="Avatar"/>, render:()=> has(Avatar,AvatarGroup)?<div className="srow"><Avatar name="Nguyễn Vũ" size="lg"/><Avatar name="An Le" size="md"/><Avatar name="Bao Vu" size="sm"/><AvatarGroup><Avatar name="An Le" size="sm"/><Avatar name="Bao Vu" size="sm"/><Avatar name="Chi Tran" size="sm"/></AvatarGroup></div>:<Miss n="Avatar"/> },
169
170
  { tier:"Atom", name:"Divider", grp:"Data", render:()=> has(Divider)?<div style={{maxWidth:360}}><Divider/><Divider label="team"/></div>:<Miss n="Divider"/> },
171
+ { tier:"Atom", name:"AspectRatio", grp:"Data", controls:[{k:"ratio",type:"select",options:["16 / 9","1","4 / 3","9 / 16"],def:"16 / 9"}], renderC:(v)=> has(AspectRatio)?<div style={{maxWidth:280}}><AspectRatio ratio={v.ratio}><img src="../assets/aurora-gold.jpg" alt="Aurora"/></AspectRatio></div>:<Miss n="AspectRatio"/>, render:(L)=> has(AspectRatio)?<div style={{maxWidth:280}}><AspectRatio ratio="16 / 9"><img src="../assets/aurora-gold.jpg" alt={L==="vi"?"Aurora vàng":"Aurora gold"}/></AspectRatio></div>:<Miss n="AspectRatio"/> },
172
+ { tier:"Atom", name:"Item", grp:"Data", controls:[{k:"selected",type:"toggle",def:false},{k:"disabled",type:"toggle",def:false}], renderC:(v)=> has(Item)?<div style={{maxWidth:420}}><Item title="Release notes" description="Bilingual digest" selected={v.selected} disabled={v.disabled} trailing={has(Switch)?<Switch defaultChecked aria-label="Release notes"/>:null}/></div>:<Miss n="Item"/>, render:(L)=> has(Item)?<div style={{maxWidth:420,display:"grid",gap:8}}><Item title={L==="vi"?"Ghi chú phát hành":"Release notes"} description={L==="vi"?"Tóm tắt song ngữ":"Bilingual digest"} trailing={has(Switch)?<Switch defaultChecked aria-label={L==="vi"?"Ghi chú phát hành":"Release notes"}/>:null}/><Item title={L==="vi"?"Hồ sơ":"Profile"} href="#profile" selected/></div>:<Miss n="Item"/> },
170
173
  { tier:"Atom", name:"Kbd", grp:"Data", render:()=> has(Kbd)?<span>Press <Kbd>⌘</Kbd> <Kbd>K</Kbd> to search</span>:<Miss n="Kbd"/> },
171
174
  { tier:"Atom", name:"Logo", grp:"Brand", render:()=> has(Logo)?<div className="srow" style={{gap:24}}><Logo size={56}/><Logo size={40}/><Logo size={28}/><span style={{display:"flex",alignItems:"center",gap:10}}><Logo size={40}/><b style={{fontSize:22,letterSpacing:"-.01em",color:"var(--cs-color-text-primary)"}}>CyberSkill</b></span></div>:<Miss n="Logo"/> },
172
175
  { tier:"Atom", name:"LumiAvatar", grp:"Brand", controls:[{k:"size",type:"select",options:["sm","md","lg"],def:"lg"},{k:"ring",type:"toggle",def:true}], renderC:(v)=> has(LumiAvatar)?<LumiAvatar src="../assets/lumi-poster.webp" size={v.size} ring={v.ring}/>:<Miss n="LumiAvatar"/>, render:()=> has(LumiAvatar)?<div className="srow" style={{gap:22}}><LumiAvatar src="../assets/lumi-poster.webp" size="lg" ring/><LumiAvatar src="../assets/lumi-poster.webp" size="md"/><LumiAvatar size="md"/><LumiAvatar size="sm"/></div>:<Miss n="LumiAvatar"/> },
173
176
 
174
177
  // ============ MOLECULES ============
175
178
  { tier:"Molecule", name:"TextField", grp:"Forms", controls:[{k:"label",type:"text",def:"Work email"},{k:"error",type:"text",def:""},{k:"disabled",type:"toggle",def:false}], renderC:(v)=> has(TextField)?<div style={{maxWidth:360}}><TextField label={v.label} error={v.error||undefined} disabled={v.disabled} placeholder="you@company.com"/></div>:<Miss n="TextField"/>, render:()=> has(TextField)?<div className="grid2"><TextField label="Work email" type="email" placeholder="you@company.com"/><TextField label="Tên của bạn" description="Diacritics preserved" defaultValue="Nguyễn Hoàng Vũ"/><TextField label="Company" placeholder="Optional"/><TextField label="Email" error="Enter a valid email address." defaultValue="not-an-email"/></div>:<Miss n="TextField"/> },
176
- { tier:"Molecule", name:"Select · Radio · Checkbox · Switch · Textarea", grp:"Forms", controls:[{k:"label",type:"text",def:"Dark theme"},{k:"disabled",type:"toggle",def:false}], renderC:(v)=> has(Switch)?<Switch label={v.label} disabled={v.disabled} defaultChecked/>:<Miss n="Switch"/>, render:()=> has(Select,RadioGroup,Checkbox,Switch,Textarea)?<div className="grid2">
179
+ { tier:"Molecule", name:"Select · NativeSelect · Radio · Checkbox · Switch · Textarea", grp:"Forms", controls:[{k:"label",type:"text",def:"Squad"},{k:"disabled",type:"toggle",def:false}], renderC:(v)=> has(Select,Checkbox,RadioGroup,Switch)?<div className="scol" style={{maxWidth:360,gap:12}}><Select label={v.label} disabled={v.disabled} options={[{value:"plat",label:"Platform"},{value:"ai",label:"AI"}]} defaultValue="ai"/><Checkbox label="Email me release notes" disabled={v.disabled} defaultChecked/><RadioGroup legend="Billing" options={[{value:"mo",label:"Monthly"},{value:"yr",label:"Annual"}]} defaultValue="yr"/><Switch label="Dark theme" disabled={v.disabled} defaultChecked/></div>:<Miss n="Select"/>, render:()=> has(Select,NativeSelect,RadioGroup,Checkbox,Switch,Textarea)?<div className="grid2">
177
180
  <Select label="Squad" options={[{value:"plat",label:"Platform"},{value:"ai",label:"AI"},{value:"growth",label:"Growth"}]} defaultValue="ai"/>
181
+ <NativeSelect label="Interface" size="sm" options={[{value:"en",label:"English"},{value:"vi",label:"Tiếng Việt"}]} defaultValue="en"/>
178
182
  <RadioGroup legend="Billing" defaultValue="yr" options={[{value:"mo",label:"Monthly"},{value:"yr",label:"Annual",description:"Two months free"}]}/>
179
183
  <div className="scol"><Checkbox label="Email me release notes" defaultChecked/><Checkbox label="Bilingual export" description="Ship EN + VN together"/><Switch label="Dark theme" defaultChecked/></div>
180
184
  <Textarea label="Tell us your wish" description="A sentence or two is plenty." rows={3} defaultValue="A faster checkout for our shop."/>
181
185
  </div>:<Miss n="Form controls"/> },
182
- { tier:"Molecule", name:"Search · Number · Slider · Segmented · FileUpload", grp:"Forms", render:(L)=> <div className="scol">
186
+ { tier:"Molecule", name:"Search · Number · Slider · Segmented · FileUpload", grp:"Forms", controls:[{k:"query",type:"text",def:"design system"},{k:"qty",type:"range",min:0,max:20,step:1,def:3},{k:"level",type:"range",min:0,max:100,step:1,def:60}], renderC:(v)=> has(SearchField,NumberField,Slider,SegmentedControl,FileUpload)?<div className="scol" style={{maxWidth:420}}><SearchField value={v.query} onChange={()=>{}}/><NumberField label="Qty" value={+v.qty} onChange={()=>{}} lang="en"/><Slider aria-label="Level" value={+v.level} onChange={()=>{}}/><SegmentedControl value="board" onChange={()=>{}} options={[{value:"board",label:"Board"},{value:"list",label:"List"}]}/><FileUpload title="Drop files"/></div>:<Miss n="SearchField"/>, render:(L)=> <div className="scol">
183
187
  <div className="srow"><SearchD L={L}/></div>
184
- <div className="srow"><NumberD/><SliderD/></div>
188
+ <div className="srow"><NumberD L={L}/><SliderD L={L}/></div>
185
189
  <div className="srow"><SegmentedD L={L}/></div>
186
190
  {has(FileUpload)?<FileUpload/>:<Miss n="FileUpload"/>}
187
191
  </div> },
@@ -189,19 +193,21 @@ const STORIES = [
189
193
  { tier:"Molecule", name:"InputOTP", grp:"Forms", render:()=> has(InputOTP)?<InputOTP length={6} onComplete={()=>{}}/>:<Miss n="InputOTP"/> },
190
194
  { tier:"Molecule", name:"ButtonGroup", grp:"Core", render:(L)=> has(ButtonGroup,Button)?<ButtonGroup label="View"><Button variant="secondary" size="sm">{L==="vi"?"Bảng công việc":"Board"}</Button><Button variant="secondary" size="sm">{L==="vi"?"Danh sách":"List"}</Button><Button variant="secondary" size="sm">{L==="vi"?"Dòng thời gian":"Timeline"}</Button></ButtonGroup>:<Miss n="ButtonGroup"/> },
191
195
  { tier:"Molecule", name:"Combobox", grp:"Forms", render:(L)=> <div style={{minHeight:230}}><ComboD L={L}/></div> },
192
- { tier:"Molecule", name:"InputGroup", grp:"Forms", render:(L)=> has(InputGroup)?<div className="scol" style={{maxWidth:360}}><InputGroup prefix="https://" suffix=".world" defaultValue="cyberskill" clearable/><InputGroup password defaultValue="hunter2" placeholder={L==="vi"?"Mật khẩu":"Password"}/></div>:<Miss n="InputGroup"/> },
193
- { tier:"Molecule", name:"TagInput", grp:"Forms", render:(L)=> has(TagInput)?<div style={{maxWidth:420}}><TagInput defaultValue={L==="vi"?["Ứng dụng web","Song ngữ"]:["Web apps","Bilingual"]}/></div>:<Miss n="TagInput"/> },
194
- { tier:"Molecule", name:"HoverCard", grp:"Overlays", render:(L)=> has(HoverCard)?<div style={{minHeight:150}}><HoverCard trigger={<a href="#" onClick={(e)=>e.preventDefault()}>@anle</a>}><b>An Lê</b><br/>{L==="vi"?"Trưởng nhóm Nền tảng · Sài Gòn":"Platform lead · Saigon"}</HoverCard></div>:<Miss n="HoverCard"/> },
196
+ { tier:"Molecule", name:"InputGroup", grp:"Forms", render:(L)=> has(InputGroup)?<div className="scol" style={{maxWidth:360}}><InputGroup label={L==="vi"?"Máy chủ":"Host"} prefix="https://" suffix=".world" defaultValue="cyberskill" clearable/><InputGroup label={L==="vi"?"Mật khẩu":"Password"} password defaultValue="hunter2" placeholder={L==="vi"?"Mật khẩu":"Password"}/></div>:<Miss n="InputGroup"/> },
197
+ { tier:"Molecule", name:"TagInput", grp:"Forms", render:(L)=> has(TagInput)?<div style={{maxWidth:420}}><TagInput label={L==="vi"?"Thẻ":"Tags"} defaultValue={L==="vi"?["Ứng dụng web","Song ngữ"]:["Web apps","Bilingual"]}/></div>:<Miss n="TagInput"/> },
198
+ { tier:"Molecule", name:"HoverCard", grp:"Overlays", controls:[{k:"openDelay",type:"range",min:0,max:400,step:50,def:0}], renderC:(v)=> has(HoverCard)?<div style={{minHeight:150}}><HoverCard openDelay={+v.openDelay} closeDelay={99999} trigger={<button type="button" className="cs-button cs-button--ghost">@anle</button>}><b>An Lê</b><br/>Platform lead · Saigon</HoverCard></div>:<Miss n="HoverCard"/>, render:(L)=> has(HoverCard)?<div style={{minHeight:150}}><HoverCard trigger={<a href="#" onClick={(e)=>e.preventDefault()}>@anle</a>}><b>An Lê</b><br/>{L==="vi"?"Trưởng nhóm Nền tảng · Sài Gòn":"Platform lead · Saigon"}</HoverCard></div>:<Miss n="HoverCard"/> },
195
199
  { tier:"Molecule", name:"Popconfirm", grp:"Overlays", render:(L)=> has(Popconfirm,Button)?<div style={{minHeight:170}}><Popconfirm title={L==="vi"?"Xóa bản nháp này?":"Delete this draft?"} onConfirm={()=>{}} trigger={<Button variant="danger-ghost" size="sm">{L==="vi"?"Xóa":"Delete"}</Button>}/></div>:<Miss n="Popconfirm"/> },
196
200
  { tier:"Molecule", name:"ContextMenu", grp:"Overlays", render:(L)=> has(ContextMenu)?<ContextMenu items={L==="vi"?[{label:"Nhân bản"},{label:"Đổi tên"},"-",{label:"Xóa",danger:true}]:[{label:"Duplicate"},{label:"Rename"},"-",{label:"Delete",danger:true}]}><div style={{border:"1px dashed var(--cs-color-border-default)",borderRadius:"var(--cs-radius-md)",padding:"26px 18px",color:"var(--cs-color-text-muted)",fontSize:14,minHeight:120}}>{L==="vi"?"Nhấp chuột phải vào vùng này":"Right-click this zone"}</div></ContextMenu>:<Miss n="ContextMenu"/> },
197
201
  { tier:"Molecule", name:"FloatingActionButton", grp:"Core", render:(L)=> has(FloatingActionButton,Icon)?<FloatingActionButton position="static" icon={<Icon name="sparkle"/>} label={L==="vi"?"Ước một điều":"Make a wish"} actions={[{icon:<Icon name="chat" size="sm"/>,label:L==="vi"?"Trò chuyện với Lumi":"Talk to Lumi"},{icon:<Icon name="plus" size="sm"/>,label:L==="vi"?"Dự án mới":"New project"}]}/>:<Miss n="FloatingActionButton"/> },
198
202
  { tier:"Molecule", name:"InlineEdit", grp:"Forms", render:(L)=> has(InlineEdit)?<InlineEdit defaultValue="Design System v1.6" label={L==="vi"?"Tên dự án":"Project name"}/>:<Miss n="InlineEdit"/> },
199
203
  { tier:"Molecule", name:"Toolbar", grp:"Navigation", render:(L)=> has(Toolbar,Icon)?<Toolbar label="Editor" overflowAfter={3} items={L==="vi"?[{icon:<Icon name="edit" size="sm"/>,label:"Sửa"},{icon:<Icon name="copy" size="sm"/>,label:"Nhân bản"},"-",{icon:<Icon name="download" size="sm"/>,label:"Xuất"},{label:"Lưu trữ"},{label:"Xóa"}]:[{icon:<Icon name="edit" size="sm"/>,label:"Edit"},{icon:<Icon name="copy" size="sm"/>,label:"Duplicate"},"-",{icon:<Icon name="download" size="sm"/>,label:"Export"},{label:"Archive"},{label:"Delete"}]}/>:<Miss n="Toolbar"/> },
200
204
  { tier:"Molecule", name:"Image", grp:"Data", render:(L)=> has(Image)?<div className="srow"><Image src="../assets/aurora-gold.jpg" alt="Aurora" ratio="16/9" preview style={{width:260}}/><Image src="/broken.png" alt="" ratio="16/9" style={{width:180}}/></div>:<Miss n="Image"/> },
205
+ { tier:"Molecule", name:"ScrollArea", grp:"Data", controls:[{k:"maxHeight",type:"range",min:80,max:280,step:20,def:140}], renderC:(v)=> has(ScrollArea)?<ScrollArea maxHeight={v.maxHeight} aria-label="Notes" style={{border:"1px solid var(--cs-color-border-default)",maxWidth:360,padding:"8px 12px",fontSize:13,color:"var(--cs-color-text-muted)"}}><p>Release notes arrive bilingual.</p><p>Blocked alerts only when asked.</p><p>Weekly velocity every Monday.</p><p>Quiet by default.</p></ScrollArea>:<Miss n="ScrollArea"/>, render:(L)=> has(ScrollArea)?<ScrollArea maxHeight={140} aria-label={L==="vi"?"Ghi chú":"Notes"} style={{border:"1px solid var(--cs-color-border-default)",maxWidth:360,padding:"8px 12px",fontSize:13,color:"var(--cs-color-text-muted)"}}><p>{L==="vi"?"Ghi chú phát hành song ngữ.":"Release notes arrive bilingual."}</p><p>{L==="vi"?"Cảnh báo chỉ khi bạn yêu cầu.":"Blocked alerts only when asked."}</p><p>{L==="vi"?"Tóm tắt tốc độ mỗi thứ Hai.":"Weekly velocity every Monday."}</p><p>{L==="vi"?"Yên tĩnh theo mặc định.":"Quiet by default."}</p></ScrollArea>:<Miss n="ScrollArea"/> },
206
+ { tier:"Molecule", name:"Collapsible", grp:"Data", controls:[{k:"defaultOpen",type:"toggle",def:false}], renderC:(v)=> has(Collapsible)?<div style={{maxWidth:420}}><Collapsible title="Advanced preferences" defaultOpen={v.defaultOpen}><p style={{margin:0}}>Quiet by default — only what you opt into.</p></Collapsible></div>:<Miss n="Collapsible"/>, render:(L)=> has(Collapsible)?<div style={{maxWidth:420}}><Collapsible title={L==="vi"?"Tuỳ chọn nâng cao":"Advanced preferences"} defaultOpen={false}><p style={{margin:0}}>{L==="vi"?"Yên tĩnh theo mặc định — chỉ những gì bạn chọn.":"Quiet by default — only what you opt into."}</p></Collapsible></div>:<Miss n="Collapsible"/> },
201
207
  { tier:"Molecule", name:"Anchor", grp:"Navigation", render:(L)=> has(Anchor)?<Anchor title={L==="vi"?"Trên trang này":"On this page"} items={L==="vi"?[{id:"atoms",label:"Nguyên tử"},{id:"molecules",label:"Phân tử"},{id:"organisms",label:"Cơ quan"}]:[{id:"atoms",label:"Atoms"},{id:"molecules",label:"Molecules"},{id:"organisms",label:"Organisms"}]}/>:<Miss n="Anchor"/> },
202
- { tier:"Molecule", name:"Tabs", grp:"Navigation", render:(L)=> <TabsD L={L}/> },
208
+ { tier:"Molecule", name:"Tabs", grp:"Navigation", controls:[{k:"value",type:"select",options:["a","b","c"],def:"a"}], renderC:(v)=> has(Tabs)?<Tabs value={v.value} onChange={()=>{}} tabs={[{label:"Overview",value:"a"},{label:"Releases",value:"b"},{label:"Settings",value:"c"}]}/>:<Miss n="Tabs"/>, render:(L)=> <TabsD L={L}/> },
203
209
  { tier:"Molecule", name:"Breadcrumb", grp:"Navigation", render:(L)=> has(Breadcrumb)?<Breadcrumb items={L==="vi"?[{label:"Trung tâm",href:"#"},{label:"Nền tảng",href:"#"},{label:"Design System v1.6"}]:[{label:"Status Hub",href:"#"},{label:"Platform",href:"#"},{label:"Design System v1.6"}]}/>:<Miss n="Breadcrumb"/> },
204
- { tier:"Molecule", name:"Pagination", grp:"Navigation", render:()=> <PaginationD/> },
210
+ { tier:"Molecule", name:"Pagination", grp:"Navigation", controls:[{k:"page",type:"range",min:1,max:8,step:1,def:3}], renderC:(v)=> has(Pagination)?<Pagination page={+v.page} pageCount={8} onChange={()=>{}}/>:<Miss n="Pagination"/>, render:()=> <PaginationD/> },
205
211
  { tier:"Molecule", name:"Menu", grp:"Navigation", render:(L)=> has(Menu,MenuItem)?<Menu trigger={<button className="cs-button cs-button--secondary cs-button--sm">{L==="vi"?"Hành động ▾":"Actions ▾"}</button>}><MenuItem>{L==="vi"?"Nhân bản":"Duplicate"}</MenuItem><MenuItem>{L==="vi"?"Xuất EN + VN":"Export EN + VN"}</MenuItem><div className="cs-menu__sep"/><MenuItem danger>{L==="vi"?"Xóa":"Delete"}</MenuItem></Menu>:<Miss n="Menu"/> },
206
212
  { tier:"Molecule", name:"Stat", grp:"Data", controls:[{k:"label",type:"text",def:"Avg progress"},{k:"value",type:"text",def:"70%"},{k:"delta",type:"text",def:"+6"},{k:"trend",type:"select",options:["up","down","flat"],def:"up"}], renderC:(v)=> has(Stat)?<Stat label={v.label} value={v.value} delta={v.delta||undefined} trend={v.trend}/>:<Miss n="Stat"/>, render:(L)=> has(Stat)?<div className="srow" style={{gap:32}}><Stat label={L==="vi"?"Dự án":"Projects"} value="6"/><Stat label={L==="vi"?"Tiến độ TB":"Avg progress"} value="70%" delta="+6" trend="up"/><Stat label={L==="vi"?"Bị chặn":"Blocked"} value="1" delta="-1" trend="down"/></div>:<Miss n="Stat"/> },
207
213
  { tier:"Molecule", name:"Card", grp:"Data", controls:[{k:"title",type:"text",def:"Design System v1.6"},{k:"subtitle",type:"text",def:"Platform squad"},{k:"body",type:"text",def:"Liquid Glass bindings + 15 element packs."}], renderC:(v)=> has(Card,CardHeader,CardBody)?<div style={{maxWidth:360}}><Card><CardHeader title={v.title} subtitle={v.subtitle}/><CardBody>{v.body}</CardBody></Card></div>:<Miss n="Card"/>, render:(L)=> has(Card,CardHeader,CardBody,CardFooter)?<div style={{maxWidth:360}}><Card><CardHeader title="Design System v1.6" subtitle={L==="vi"?"Nhóm Nền tảng":"Platform squad"}/><CardBody>{L==="vi"?"Liên kết Liquid Glass + 15 gói Ngũ Hành, đã kiểm chứng.":"Liquid Glass bindings + 15 element packs, verified."}</CardBody><CardFooter>{has(Badge)&&<Badge variant="ochre">{L==="vi"?"Đang làm":"Now"}</Badge>}{has(AvatarGroup,Avatar)&&<AvatarGroup><Avatar name="An Le" size="sm"/><Avatar name="Bao Vu" size="sm"/></AvatarGroup>}</CardFooter></Card></div>:<Miss n="Card"/> },
@@ -267,7 +273,7 @@ const STORIES = [
267
273
  { tier:"Organism", name:"Tree", grp:"Data", render:(L)=> has(Tree)?<div style={{maxWidth:340}}><Tree defaultOpen nodes={L==="vi"?[{key:"p",label:"Nền tảng",children:[{key:"ds",label:"Design System"},{key:"tok",label:"Token Pipeline"}]},{key:"ai",label:"AI",children:[{key:"lumi",label:"Lumi Genie"}]}]:[{key:"p",label:"Platform",children:[{key:"ds",label:"Design System"},{key:"tok",label:"Token Pipeline"}]},{key:"ai",label:"AI",children:[{key:"lumi",label:"Lumi Genie"}]}]}/></div>:<Miss n="Tree"/> },
268
274
  { tier:"Molecule", name:"Watermark", grp:"Data", render:(L)=> has(Watermark)?<Watermark text={L==="vi"?"BẢN NHÁP":"DRAFT"}><div style={{border:"1px solid var(--cs-color-border-default)",borderRadius:"var(--cs-radius-md)",padding:"30px 22px",maxWidth:420}}>{L==="vi"?"Nội dung tài liệu được đánh dấu bản nháp.":"Document content marked as a draft."}</div></Watermark>:<Miss n="Watermark"/> },
269
275
  { tier:"Molecule", name:"BackTop", grp:"Navigation", render:(L)=> has(BackTop)?<div style={{fontSize:13,color:"var(--cs-color-text-muted)"}}>{L==="vi"?"Cuộn trang để thấy nút ở góc phải dưới.":"Scroll the page — the button appears bottom-right."}<BackTop threshold={300}/></div>:<Miss n="BackTop"/> },
270
- { tier:"Organism", name:"Menubar", grp:"Navigation", render:(L)=> has(Menubar)?<div style={{minHeight:180}}><Menubar menus={L==="vi"?[{label:"Tệp",items:[{label:"Mới"},{label:"Mở…"},"-",{label:"Xuất EN + VN"}]},{label:"Sửa",items:[{label:"Hoàn tác"},{label:"Làm lại"}]}]:[{label:"File",items:[{label:"New"},{label:"Open…"},"-",{label:"Export EN + VN"}]},{label:"Edit",items:[{label:"Undo"},{label:"Redo"}]}]}/></div>:<Miss n="Menubar"/> },
276
+ { tier:"Organism", name:"Menubar", grp:"Navigation", controls:[{k:"fileLabel",type:"text",def:"File"}], renderC:(v)=> has(Menubar)?<div style={{minHeight:180}}><Menubar menus={[{label:v.fileLabel,items:[{label:"New"},{label:"Open…"},"-",{label:"Export"}]},{label:"Edit",items:[{label:"Undo"},{label:"Redo"}]}]}/></div>:<Miss n="Menubar"/>, render:(L)=> has(Menubar)?<div style={{minHeight:180}}><Menubar menus={L==="vi"?[{label:"Tệp",items:[{label:"Mới"},{label:"Mở…"},"-",{label:"Xuất EN + VN"}]},{label:"Sửa",items:[{label:"Hoàn tác"},{label:"Làm lại"}]}]:[{label:"File",items:[{label:"New"},{label:"Open…"},"-",{label:"Export EN + VN"}]},{label:"Edit",items:[{label:"Undo"},{label:"Redo"}]}]}/></div>:<Miss n="Menubar"/> },
271
277
  { tier:"Organism", name:"NavigationMenu", grp:"Navigation", render:(L)=> has(NavigationMenu)?<div style={{minHeight:220}}><NavigationMenu items={L==="vi"?[{label:"Dịch vụ",panel:[{label:"Ứng dụng web & di động",desc:"Sản phẩm khách hàng dùng hằng ngày",href:"#"},{label:"Hệ thống nội bộ",desc:"Công cụ đội ngũ vận hành",href:"#"}]},{label:"Dự án",href:"#"},{label:"Tuyển dụng",href:"#"}]:[{label:"Services",panel:[{label:"Web & mobile apps",desc:"Products your customers reach for",href:"#"},{label:"Internal systems",desc:"The tools your team runs on",href:"#"}]},{label:"Work",href:"#"},{label:"Careers",href:"#"}]}/></div>:<Miss n="NavigationMenu"/> },
272
278
  { tier:"Organism", name:"Carousel", grp:"Data", render:(L)=> has(Carousel)?<div style={{maxWidth:460}}><Carousel label={L==="vi"?"Dự án":"Cases"}>{[1,2,3].map(n=><div key={n} style={{padding:"44px 24px",textAlign:"center",fontWeight:700}}>{(L==="vi"?"Trang ":"Slide ")+n}</div>)}</Carousel></div>:<Miss n="Carousel"/> },
273
279
  { tier:"Organism", name:"Comment", grp:"Data", render:(L)=> has(Comment,Avatar)?<div style={{maxWidth:460}}><Comment avatar={<Avatar name="An Le" size="sm"/>} author="An Lê" meta={L==="vi"?"2 giờ trước":"2h ago"} replies={<Comment avatar={<Avatar name="Bao Vu" size="sm"/>} author="Bảo Vũ" meta={L==="vi"?"1 giờ trước":"1h ago"}>{L==="vi"?"Đồng ý, giao tuần này.":"Agreed — shipping this week."}</Comment>}>{L==="vi"?"Trông ổn rồi — giao thôi.":"Looks good — ship it."}</Comment></div>:<Miss n="Comment"/> },
@@ -277,9 +283,10 @@ const STORIES = [
277
283
  { tier:"Organism", name:"Accordion", grp:"Data", controls:[{k:"allowMultiple",type:"toggle",def:false}], renderC:(v)=> has(Accordion)?<div style={{maxWidth:460}}><Accordion allowMultiple={v.allowMultiple} items={[{title:"What is a wish?",content:"A clear outcome stated in a sentence or two."},{title:"How fast do you reply?",content:"Within one business day."},{title:"Do you ship bilingual?",content:"Every deliverable ships EN + VN."}]}/></div>:<Miss n="Accordion"/>, render:(L)=> has(Accordion)?<div style={{maxWidth:460}}><Accordion items={L==="vi"?[{title:"Điều ước là gì?",content:"Một kết quả rõ ràng, nói trong một hai câu."},{title:"Bao lâu thì trả lời?",content:"Trong một ngày làm việc."},{title:"Có giao song ngữ không?",content:"Mọi sản phẩm đều giao EN + VN."}]:[{title:"What is a wish?",content:"A clear outcome stated in a sentence or two."},{title:"How fast do you reply?",content:"Within one business day."},{title:"Do you ship bilingual?",content:"Every deliverable ships EN + VN."}]}/></div>:<Miss n="Accordion"/> },
278
284
  { tier:"Organism", name:"Timeline", grp:"Data", render:(L)=> has(Timeline)?<div style={{maxWidth:420}}><Timeline items={L==="vi"?[{title:"v1.6.0",meta:"Tuần này",state:"now",body:"Liên kết Glass"},{title:"v1.5.1",meta:"04/07/2026",body:"15 gói Ngũ Hành"},{title:"v1.4.0",meta:"13/06/2026",body:"Liquid Glass trong mã"}]:[{title:"v1.6.0",meta:"This week",state:"now",body:"Glass bindings"},{title:"v1.5.1",meta:"04 Jul 2026",body:"15 element packs"},{title:"v1.4.0",meta:"13 Jun 2026",body:"Liquid Glass in code"}]}/></div>:<Miss n="Timeline"/> },
279
285
  { tier:"Organism", name:"EmptyState", grp:"Feedback", controls:[{k:"title",type:"text",def:"No projects yet"},{k:"body",type:"text",def:"Start by telling Lumi what you'd like to build."}], renderC:(v)=> has(EmptyState)?<div style={{border:"1px solid var(--cs-color-border-default)",borderRadius:"var(--cs-radius-lg)"}}><EmptyState title={v.title}>{v.body}</EmptyState></div>:<Miss n="EmptyState"/>, render:(L)=> has(EmptyState)?<div style={{border:"1px solid var(--cs-color-border-default)",borderRadius:"var(--cs-radius-lg)"}}><EmptyState title={L==="vi"?"Chưa có dự án nào":"No projects yet"} actions={has(Button)?<Button size="sm">{L==="vi"?"✦ Ước một điều":"✦ Make a wish"}</Button>:null}>{L==="vi"?"Hãy bắt đầu bằng cách nói với Lumi bạn muốn xây gì.":"Start by telling Lumi what you'd like to build."}</EmptyState></div>:<Miss n="EmptyState"/> },
280
- { tier:"Organism", name:"Dialog", grp:"Overlays", framed:true, render:()=> has(Dialog,Button)?<Dialog open={true} title="Send your wish?" onClose={()=>{}} actions={<><Button variant="secondary">Not now</Button><Button>Send wish</Button></>}>A real person on the team replies within one business day.</Dialog>:<Miss n="Dialog"/> },
281
- { tier:"Organism", name:"Drawer", grp:"Overlays", framed:true, render:(L)=> has(Drawer)?<Drawer open={true} onClose={()=>{}} title="Design System v1.6" actions={has(Button)?<Button size="sm">{L==="vi"?"Mở dự án":"Open project"}</Button>:null}>{has(Badge)&&<Badge variant="ochre">{L==="vi"?"Đang làm":"In progress"}</Badge>}<p style={{color:"var(--cs-color-text-muted)",fontSize:13}}>{L==="vi"?"Liên kết component Liquid Glass + 15 gói Ngũ Hành.":"Liquid Glass component bindings + 15 element packs."}</p>{has(DescriptionList)&&<DescriptionList items={L==="vi"?[{term:"Phụ trách",value:"An Lê"},{term:"Nhóm",value:"Nền tảng"}]:[{term:"Owner",value:"An Le"},{term:"Squad",value:"Platform"}]}/>}</Drawer>:<Miss n="Drawer"/> },
282
- { tier:"Organism", name:"Popover", grp:"Overlays", framed:true, render:(L)=> has(Popover,Button,RadioGroup)?<div style={{padding:16}}><Popover open={true} onOpenChange={()=>{}} trigger={<Button variant="secondary" size="sm">{L==="vi"?"Lọc ▾":"Filter ▾"}</Button>}><RadioGroup legend={L==="vi"?"Trạng thái":"Status"} defaultValue="active" options={L==="vi"?[{value:"active",label:"Đang làm"},{value:"done",label:"Đã ra mắt"},{value:"hold",label:"Bị chặn"}]:[{value:"active",label:"In progress"},{value:"done",label:"Shipped"},{value:"hold",label:"Blocked"}]}/></Popover></div>:<Miss n="Popover"/> },
286
+ { tier:"Organism", name:"Dialog", grp:"Overlays", framed:true, controls:[{k:"title",type:"text",def:"Send your wish?"}], renderC:(v)=> has(Dialog,Button)?<Dialog open={true} title={v.title} onClose={()=>{}} actions={<><Button variant="secondary">Not now</Button><Button>Send wish</Button></>}>A real person on the team replies within one business day.</Dialog>:<Miss n="Dialog"/>, render:()=> has(Dialog,Button)?<Dialog open={true} title="Send your wish?" onClose={()=>{}} actions={<><Button variant="secondary">Not now</Button><Button>Send wish</Button></>}>A real person on the team replies within one business day.</Dialog>:<Miss n="Dialog"/> },
287
+ { tier:"Organism", name:"AlertDialog", grp:"Overlays", controls:[{k:"tone",type:"select",options:["default","destructive"],def:"destructive"}], renderC:(v)=> has(AlertDialog)?<div style={{minHeight:200}}><AlertDialog open title="Delete workspace?" description="Removes every project. This cannot be undone." tone={v.tone} onOpenChange={()=>{}}/></div>:<Miss n="AlertDialog"/>, render:(L)=> <div style={{minHeight:120}}><AlertDialogD L={L}/></div> },
288
+ { tier:"Organism", name:"Drawer", grp:"Overlays", framed:true, controls:[{k:"title",type:"text",def:"Design System v1.6"}], renderC:(v)=> has(Drawer,Button)?<Drawer open={true} onClose={()=>{}} title={v.title} actions={<Button size="sm">Open project</Button>}><p style={{color:"var(--cs-color-text-muted)",fontSize:13}}>Liquid Glass component bindings + 15 element packs.</p></Drawer>:<Miss n="Drawer"/>, render:(L)=> has(Drawer)?<Drawer open={true} onClose={()=>{}} title="Design System v1.6" actions={has(Button)?<Button size="sm">{L==="vi"?"Mở dự án":"Open project"}</Button>:null}>{has(Badge)&&<Badge variant="ochre">{L==="vi"?"Đang làm":"In progress"}</Badge>}<p style={{color:"var(--cs-color-text-muted)",fontSize:13}}>{L==="vi"?"Liên kết component Liquid Glass + 15 gói Ngũ Hành.":"Liquid Glass component bindings + 15 element packs."}</p>{has(DescriptionList)&&<DescriptionList items={L==="vi"?[{term:"Phụ trách",value:"An Lê"},{term:"Nhóm",value:"Nền tảng"}]:[{term:"Owner",value:"An Le"},{term:"Squad",value:"Platform"}]}/>}</Drawer>:<Miss n="Drawer"/> },
289
+ { tier:"Organism", name:"Popover", grp:"Overlays", framed:true, controls:[{k:"trigger",type:"text",def:"Filter ▾"}], renderC:(v)=> has(Popover,Button,RadioGroup)?<div style={{padding:16}}><Popover open={true} onOpenChange={()=>{}} trigger={<Button variant="secondary" size="sm">{v.trigger}</Button>}><RadioGroup legend="Status" defaultValue="active" options={[{value:"active",label:"In progress"},{value:"done",label:"Shipped"}]}/></Popover></div>:<Miss n="Popover"/>, render:(L)=> has(Popover,Button,RadioGroup)?<div style={{padding:16}}><Popover open={true} onOpenChange={()=>{}} trigger={<Button variant="secondary" size="sm">{L==="vi"?"Lọc ▾":"Filter ▾"}</Button>}><RadioGroup legend={L==="vi"?"Trạng thái":"Status"} defaultValue="active" options={L==="vi"?[{value:"active",label:"Đang làm"},{value:"done",label:"Đã ra mắt"},{value:"hold",label:"Bị chặn"}]:[{value:"active",label:"In progress"},{value:"done",label:"Shipped"},{value:"hold",label:"Blocked"}]}/></Popover></div>:<Miss n="Popover"/> },
283
290
  { tier:"Organism", name:"Conversation (PromptInput + ChatMessage)", grp:"AI-native", render:(L)=> has(ChatMessage)?<div style={{maxWidth:520}}><div className="cs-chat" style={{marginBottom:12}}><ChatMessage role="lumi">{L==="vi"?"Xin chào, mình là Lumi. Hãy nói điều ước của bạn — mình sẽ tư vấn thẳng thắn trước khi hỏi bất kỳ điều gì.":"Hello, I'm Lumi. Tell me a wish, and I'll share plain advice before asking for anything."}</ChatMessage><ChatMessage role="user">{L==="vi"?"Một trang thanh toán nhanh hơn.":"A faster checkout."}</ChatMessage><ChatMessage role="lumi">{L==="vi"?"Một điều ước đáng thực hiện — mình nên gọi bạn là gì?":"A wish worth granting — what should I call you?"}</ChatMessage></div><PromptD L={L}/></div>:<Miss n="ChatMessage"/> },
284
291
  { tier:"Organism", name:"HumanReviewGate", grp:"AI-native", controls:[{k:"risk",type:"text",def:"High-stakes · billing change"},{k:"summary",type:"text",def:"Move client to annual + prorated credit."},{k:"reviewer",type:"text",def:"Ops on call"}], renderC:(v)=> has(HumanReviewGate)?<div style={{maxWidth:520}}><HumanReviewGate risk={v.risk} summary={v.summary} reviewer={v.reviewer}/></div>:<Miss n="HumanReviewGate"/>, render:()=> has(HumanReviewGate)?<div style={{maxWidth:520}}><HumanReviewGate risk="High-stakes · billing change" summary="Lumi proposes moving this client to the annual plan and issuing a prorated credit." reviewer="Ops on call"/></div>:<Miss n="HumanReviewGate"/> },
285
292
  ];
@@ -290,11 +297,11 @@ const TIERS = [
290
297
  { id:"Organism", label:"Organisms", sub:"Composite, self-contained sections." },
291
298
  ];
292
299
  const ELEMENTS = [
293
- ["tho|","Thổ · studio"],["tho|clay","Thổ · clay"],["tho|sand","Thổ · sand"],
294
- ["hoa|","Hỏa · ember"],["hoa|lava","Hỏa · lava"],["hoa|plasma","Hỏa · plasma"],
295
- ["thuy|","Thủy · river"],["thuy|ocean","Thủy · ocean"],["thuy|mist","Thủy · mist"],
296
- ["moc|","Mộc · leaf"],["moc|bamboo","Mộc · bamboo"],["moc|forest","Mộc · forest"],
297
- ["kim|","Kim · champagne"],["kim|steel","Kim · steel"],["kim|titanium","Kim · titanium"],
300
+ ["tho|","Thổ · studio (middle)"],["tho|sand","Thổ · sand (soft)"],["tho|clay","Thổ · clay (deep)"],
301
+ ["hoa|","Hỏa · ember (middle)"],["hoa|plasma","Hỏa · plasma (soft)"],["hoa|lava","Hỏa · lava (deep)"],
302
+ ["thuy|","Thủy · river (middle)"],["thuy|mist","Thủy · mist (soft)"],["thuy|ocean","Thủy · ocean (deep)"],
303
+ ["moc|","Mộc · leaf (middle)"],["moc|bamboo","Mộc · bamboo (soft)"],["moc|forest","Mộc · forest (deep)"],
304
+ ["kim|","Kim · champagne (middle)"],["kim|titanium","Kim · titanium (soft)"],["kim|steel","Kim · steel (deep)"],
298
305
  ];
299
306
  const LANGS = [["","Default"],["en","English"],["vi","Tiếng Việt"]];
300
307
  const PAGES = [
@@ -308,6 +315,7 @@ function applyAxis(ifr, ax){
308
315
  try{
309
316
  const d=ifr.contentDocument, h=d&&d.documentElement; if(!h) return;
310
317
  (ax.theme&&ax.theme!=="light")?h.setAttribute("data-theme",ax.theme):h.removeAttribute("data-theme");
318
+ if(ax.style) h.setAttribute("data-cs-style",ax.style); else h.setAttribute("data-cs-style","liquid-glass");
311
319
  ax.elm?h.setAttribute("data-cs-element",ax.elm):h.removeAttribute("data-cs-element");
312
320
  ax.elv?h.setAttribute("data-cs-variant",ax.elv):h.removeAttribute("data-cs-variant");
313
321
  if(ax.lang) h.setAttribute("lang", ax.lang);
@@ -350,6 +358,7 @@ const NM = window.__csNavModel || {};
350
358
 
351
359
  function App(){
352
360
  const [theme,setTheme]=useState("light");
361
+ const [style,setStyle]=useState("liquid-glass");
353
362
  const [el,setEl]=useState("tho|");
354
363
  const [lang,setLang]=useState("");
355
364
  const [collapsed,setCollapsed]=useState({Atom:false,Molecule:false,Organism:false,found:false,tpl:true,pages:true});
@@ -365,10 +374,11 @@ function App(){
365
374
  const [elm,elv]=el.split("|");
366
375
  const axis={};
367
376
  if(theme!=="light") axis["data-theme"]=theme;
377
+ if(style) axis["data-cs-style"]=style;
368
378
  if(elm) axis["data-cs-element"]=elm;
369
379
  if(elv) axis["data-cs-variant"]=elv;
370
380
  if(lang) axis.lang=lang;
371
- const artifactAx={theme,elm,elv,lang};
381
+ const artifactAx={theme,style,elm,elv,lang};
372
382
  const shownTpls=tpls.filter(t=>!nq||t.name.toLowerCase().includes(nq)||(NM.classifyTemplate&&NM.classifyTemplate(t.name).toLowerCase().includes(nq)));
373
383
  const tplGroups=(NM.groupTemplates||((xs)=>[{category:"All",items:xs}]))(shownTpls);
374
384
  const shownPages=PAGES.filter(t=>!nq||t.name.toLowerCase().includes(nq));
@@ -440,11 +450,14 @@ function App(){
440
450
  <div className="toolbar" data-chrome="atomic-toolbar">
441
451
  <h1>CyberSkill · Components</h1>
442
452
  <label className="ctl">Theme
443
- <select value={theme} onChange={(e)=>setTheme(e.target.value)}><option value="light">Light</option><option value="dark">Dark</option></select>
453
+ <select value={theme} onChange={(e)=>setTheme(e.target.value)}><option value="light">Light</option><option value="dark">Dark</option><option value="system">System</option></select>
444
454
  </label>
445
455
  <label className="ctl">Element
446
456
  <select value={el} onChange={(e)=>setEl(e.target.value)}>{ELEMENTS.map(([v,l])=><option key={v} value={v}>{l}</option>)}</select>
447
457
  </label>
458
+ <label className="ctl">Style
459
+ <select value={style} onChange={(e)=>setStyle(e.target.value)}><option value="liquid-glass">Liquid glass</option></select>
460
+ </label>
448
461
  <label className="ctl">Language
449
462
  <select value={lang} onChange={(e)=>setLang(e.target.value)}>{LANGS.map(([v,l])=><option key={v} value={v}>{l}</option>)}</select>
450
463
  </label>
@@ -0,0 +1,69 @@
1
+ <!-- @dsCard group="Elements" viewport="1280x720" name="Geometry · 30 sets" subtitle="Soft / middle / deep × light/dark — shared intensity · hue-locked themes" -->
2
+ <!DOCTYPE html>
3
+ <html lang="en"><head><meta charset="utf-8">
4
+ <link rel="stylesheet" href="../styles.css">
5
+ <style>
6
+ body{margin:0;background:var(--cs-color-surface-page);width:1280px;height:720px;overflow:hidden;box-sizing:border-box;padding:22px 28px;font-family:var(--cs-font-family-ui);color:var(--cs-color-text-primary)}
7
+ h1{font-size:18px;margin:0 0 4px;font-weight:800;letter-spacing:-0.01em}
8
+ .sub{font-size:12px;color:var(--cs-color-text-muted);margin:0 0 14px}
9
+ .grid{display:grid;grid-template-columns:repeat(5,1fr);gap:10px}
10
+ .el{font-weight:800;font-size:12px;margin-bottom:6px}
11
+ .card{border:1px solid var(--cs-color-border-default);border-radius:10px;overflow:hidden;background:var(--cs-color-surface-panel)}
12
+ .row{display:grid;grid-template-columns:1fr 1fr;min-height:88px}
13
+ .cell{padding:8px 10px;display:flex;flex-direction:column;justify-content:space-between;gap:6px}
14
+ .cell.dark{background:#221710;color:#f5ead9}
15
+ .slot{font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:0.06em;opacity:0.75}
16
+ .sw{height:18px;border-radius:6px;box-shadow:inset 0 0 0 1px rgba(0,0,0,0.08)}
17
+ .meta{font-size:10px;font-family:var(--cs-font-family-mono);opacity:0.85}
18
+ .cta{display:inline-flex;align-items:center;justify-content:center;min-height:26px;padding:0 10px;border-radius:6px;font-size:11px;font-weight:700}
19
+ footer{margin-top:12px;font-size:11px;color:var(--cs-color-text-muted)}
20
+ </style></head>
21
+ <body>
22
+ <h1>Element geometry — 30 colour sets</h1>
23
+ <p class="sub">Thirty default colour sets (5 × soft/middle/deep × light/dark) — whole-set specimen, not a spot check. Soft is a washed pastel, middle the synced default, deep a clearly darker sibling in the same hue family; role ramps stay harmonious; theme flip keeps hue identity. Seeds: <code>tokens/element-seeds.json</code> · gate: <code>_audit/element-geometry.html</code>.</p>
24
+ <div class="grid" id="grid"></div>
25
+ <footer>Gate: <code>_audit/element-geometry.html</code> · Generate: <code>npm run tokens:elements</code> · Text never on mid-tone <code>-accent</code></footer>
26
+ <script type="module">
27
+ const ORDER = [
28
+ ['tho','Thổ',[['sand','soft'],[null,'middle'],['clay','deep']]],
29
+ ['hoa','Hỏa',[['plasma','soft'],[null,'middle'],['lava','deep']]],
30
+ ['thuy','Thủy',[['mist','soft'],[null,'middle'],['ocean','deep']]],
31
+ ['moc','Mộc',[['bamboo','soft'],[null,'middle'],['forest','deep']]],
32
+ ['kim','Kim',[['titanium','soft'],[null,'middle'],['steel','deep']]],
33
+ ];
34
+ const grid = document.getElementById('grid');
35
+ for (const [el, label, slots] of ORDER) {
36
+ const col = document.createElement('div');
37
+ col.innerHTML = `<div class="el">${label}</div>`;
38
+ for (const [va, slot] of slots) {
39
+ const card = document.createElement('div');
40
+ card.className = 'card';
41
+ card.style.marginBottom = '8px';
42
+ const mk = (dark) => {
43
+ const wrap = document.createElement('div');
44
+ wrap.className = 'cell' + (dark ? ' dark' : '');
45
+ if (el) wrap.setAttribute('data-cs-element', el);
46
+ if (va) wrap.setAttribute('data-cs-variant', va);
47
+ if (dark) wrap.setAttribute('data-theme', 'dark');
48
+ wrap.innerHTML = `
49
+ <div>
50
+ <div class="slot">${slot} · ${dark ? 'dark' : 'light'}${va ? ' · ' + va : ' · default'}</div>
51
+ <div class="sw" style="background:var(--cs-accent);margin-top:6px"></div>
52
+ </div>
53
+ <div style="display:flex;gap:6px;align-items:center;justify-content:space-between">
54
+ <span class="cta" style="background:var(--cs-accent-strong);color:var(--cs-accent-on)">CTA</span>
55
+ <span class="meta" style="color:var(--cs-color-text-accent)">Aa</span>
56
+ </div>`;
57
+ return wrap;
58
+ };
59
+ const row = document.createElement('div');
60
+ row.className = 'row';
61
+ row.appendChild(mk(false));
62
+ row.appendChild(mk(true));
63
+ card.appendChild(row);
64
+ col.appendChild(card);
65
+ }
66
+ grid.appendChild(col);
67
+ }
68
+ </script>
69
+ </body></html>
@@ -1,4 +1,4 @@
1
- <!-- @dsCard group="Elements" viewport="1280x560" name="Variants & washes" subtitle="12 variants inside 5 oklch envelopes · each element's aurora wash · Lumi stays golden in every element" -->
1
+ <!-- @dsCard group="Elements" viewport="1280x560" name="Variants & washes" subtitle="Soft / middle / deep names · aurora washes · live packs from element-seeds (see Geometry · 30 sets)" -->
2
2
  <!DOCTYPE html>
3
3
  <html lang="en"><head><meta charset="utf-8">
4
4
  <link rel="stylesheet" href="../styles.css">
@@ -18,25 +18,25 @@ a{color:var(--cs-color-link)}a:hover{color:var(--cs-color-link-hover)}
18
18
  <body>
19
19
  <div style="display:grid;grid-template-columns:repeat(5,1fr);gap:14px;margin-bottom:16px">
20
20
  <div class="col"><div class="el">Mộc · Wood</div>
21
- <div class="v"><span class="sw" style="background:#7A9B57"></span><div><div class="vn">leaf ·default</div><div class="vx">#7A9B57</div></div></div>
22
- <div class="v"><span class="sw" style="background:#A9C177"></span><div><div class="vn">bamboo</div><div class="vx">#A9C177</div></div></div>
23
- <div class="v"><span class="sw" style="background:#3E5A2E"></span><div><div class="vn">forest</div><div class="vx">#3E5A2E</div></div></div></div>
21
+ <div class="v"><span class="sw" style="background:#ADD386"></span><div><div class="vn">leaf ·middle</div><div class="vx">#ADD386</div></div></div>
22
+ <div class="v"><span class="sw" style="background:#C7E2AC"></span><div><div class="vn">bamboo</div><div class="vx">#C7E2AC</div></div></div>
23
+ <div class="v"><span class="sw" style="background:#668643"></span><div><div class="vn">forest</div><div class="vx">#668643</div></div></div></div>
24
24
  <div class="col"><div class="el">Hỏa · Fire</div>
25
- <div class="v"><span class="sw" style="background:#E0632B"></span><div><div class="vn">ember ·default</div><div class="vx">#E0632B</div></div></div>
26
- <div class="v"><span class="sw" style="background:#C43D1F"></span><div><div class="vn">lava</div><div class="vx">#C43D1F</div></div></div>
27
- <div class="v"><span class="sw" style="background:#E8506E"></span><div><div class="vn">plasma</div><div class="vx">#E8506E</div></div></div></div>
25
+ <div class="v"><span class="sw" style="background:#FFAD8E"></span><div><div class="vn">ember ·middle</div><div class="vx">#FFAD8E</div></div></div>
26
+ <div class="v"><span class="sw" style="background:#BB5A32"></span><div><div class="vn">lava</div><div class="vx">#BB5A32</div></div></div>
27
+ <div class="v"><span class="sw" style="background:#FFC7CC"></span><div><div class="vn">plasma</div><div class="vx">#FFC7CC</div></div></div></div>
28
28
  <div class="col" style="outline:2px solid var(--cs-color-brand-ochre);outline-offset:2px"><div class="el">Thổ · Earth</div>
29
- <div class="v"><span class="sw" style="background:#F4BA17"></span><div><div class="vn">ochre ·studio</div><div class="vx">#F4BA17</div></div></div>
30
- <div class="v"><span class="sw" style="background:#C77B4A"></span><div><div class="vn">clay</div><div class="vx">#C77B4A</div></div></div>
31
- <div class="v"><span class="sw" style="background:#E4C98F"></span><div><div class="vn">sand</div><div class="vx">#E4C98F</div></div></div></div>
29
+ <div class="v"><span class="sw" style="background:#F4BA17"></span><div><div class="vn">ochre ·middle</div><div class="vx">#F4BA17</div></div></div>
30
+ <div class="v"><span class="sw" style="background:#98741A"></span><div><div class="vn">clay</div><div class="vx">#98741A</div></div></div>
31
+ <div class="v"><span class="sw" style="background:#F6D389"></span><div><div class="vn">sand</div><div class="vx">#F6D389</div></div></div></div>
32
32
  <div class="col"><div class="el">Kim · Metal</div>
33
- <div class="v"><span class="sw" style="background:#BFB29B"></span><div><div class="vn">champagne ·default</div><div class="vx">#BFB29B</div></div></div>
34
- <div class="v"><span class="sw" style="background:#9FA3A3"></span><div><div class="vn">steel</div><div class="vx">#9FA3A3</div></div></div>
35
- <div class="v"><span class="sw" style="background:#8A7F72"></span><div><div class="vn">titanium</div><div class="vx">#8A7F72</div></div></div></div>
33
+ <div class="v"><span class="sw" style="background:#D1C2A8"></span><div><div class="vn">champagne ·middle</div><div class="vx">#D1C2A8</div></div></div>
34
+ <div class="v"><span class="sw" style="background:#707D7E"></span><div><div class="vn">steel</div><div class="vx">#707D7E</div></div></div>
35
+ <div class="v"><span class="sw" style="background:#E1D6C3"></span><div><div class="vn">titanium</div><div class="vx">#E1D6C3</div></div></div></div>
36
36
  <div class="col"><div class="el">Thủy · Water</div>
37
- <div class="v"><span class="sw" style="background:#4E8E9B"></span><div><div class="vn">river ·default</div><div class="vx">#4E8E9B</div></div></div>
38
- <div class="v"><span class="sw" style="background:#2E5E7E"></span><div><div class="vn">ocean</div><div class="vx">#2E5E7E</div></div></div>
39
- <div class="v"><span class="sw" style="background:#A7C4C9"></span><div><div class="vn">mist</div><div class="vx">#A7C4C9</div></div></div></div>
37
+ <div class="v"><span class="sw" style="background:#87D2E1"></span><div><div class="vn">river ·middle</div><div class="vx">#87D2E1</div></div></div>
38
+ <div class="v"><span class="sw" style="background:#428693"></span><div><div class="vn">ocean</div><div class="vx">#428693</div></div></div>
39
+ <div class="v"><span class="sw" style="background:#AEE2ED"></span><div><div class="vn">mist</div><div class="vx">#AEE2ED</div></div></div></div>
40
40
  </div>
41
41
  <div style="display:grid;grid-template-columns:repeat(5,1fr);gap:14px">
42
42
  <div class="wash"><img src="../assets/aurora-moc.png" alt="Mộc aurora wash"><span class="wl">Mộc</span></div>
@@ -45,5 +45,5 @@ a{color:var(--cs-color-link)}a:hover{color:var(--cs-color-link-hover)}
45
45
  <div class="wash"><img src="../assets/aurora-kim.png" alt="Kim aurora wash"><span class="wl">Kim</span></div>
46
46
  <div class="wash"><img src="../assets/aurora-thuy.png" alt="Thủy aurora wash"><span class="wl">Thủy</span></div>
47
47
  </div>
48
- <footer style="display:flex;gap:16px;margin-top:14px;font-size:12px;color:var(--cs-color-text-muted);align-items:center"><b style="color:var(--cs-color-text-primary)">Rules</b><span>A variant is a point inside its element's oklch envelope — same 9-token contract</span><span>·</span><span>Washes apply via .cs-aurora-wash</span><span>·</span><span><b style="color:var(--cs-color-text-primary)">Lumi stays golden</b> — only the environment re-tints</span></footer>
48
+ <footer style="display:flex;gap:16px;margin-top:14px;font-size:12px;color:var(--cs-color-text-muted);align-items:center"><b style="color:var(--cs-color-text-primary)">Rules</b><span>Slots soft · middle · deep share intensity across elements — same 9-token contract (generated)</span><span>·</span><span>Washes apply via .cs-aurora-wash</span><span>·</span><span><b style="color:var(--cs-color-text-primary)">Lumi stays golden</b> — only the environment re-tints</span></footer>
49
49
  </body></html>
@@ -1,4 +1,4 @@
1
- <!-- @dsCard group="Type" viewport="700x230" name="Typefaces" subtitle="Be Vietnam Pro (UI) · JetBrains Mono (code)" -->
1
+ <!-- @dsCard group="Type" viewport="700x330" name="Typefaces" subtitle="Be Vietnam Pro (UI) · Space Grotesk (display) · JetBrains Mono (code)" -->
2
2
  <!DOCTYPE html>
3
3
  <html lang="en"><head><meta charset="utf-8" />
4
4
  <link rel="stylesheet" href="../styles.css" />
@@ -7,19 +7,25 @@
7
7
  .fam { margin-bottom: 18px; }
8
8
  .k { font: 600 11px/1 var(--cs-font-family-ui); text-transform: uppercase; letter-spacing: .09em; color: var(--cs-color-text-muted); margin-bottom: 6px; }
9
9
  .ui { font-family: var(--cs-font-family-ui); }
10
- .mono { font-family: var(--cs-font-family-mono); }
11
- .big { font-size: 30px; font-weight: 700; letter-spacing: -.01em; }
12
- .set { font-size: 15px; color: var(--cs-color-text-muted); margin-top: 2px; }
10
+ .cs-type-display { font-family: var(--cs-font-family-display); }
11
+ .cs-type-mono { font-family: var(--cs-font-family-mono); }
12
+ .cs-type-big { font-size: 30px; font-weight: 700; letter-spacing: -.01em; }
13
+ .cs-type-set { font-size: 15px; color: var(--cs-color-text-muted); margin-top: 2px; }
13
14
  </style></head>
14
15
  <body>
15
16
  <div class="fam">
16
- <div class="k">Be Vietnam Pro — UI / display</div>
17
- <div class="ui big">Turn Your Will Into Real</div>
18
- <div class="ui set">Hiện Thực Hoá Ý Chí · 300 400 500 600 700 800 · full Vietnamese diacritics</div>
17
+ <div class="k">Be Vietnam Pro — UI (--cs-font-family-ui)</div>
18
+ <div class="ui cs-type-big">Turn Your Will Into Real</div>
19
+ <div class="ui cs-type-set">Hiện Thực Hoá Ý Chí · 300 400 500 600 700 800 · full Vietnamese diacritics</div>
20
+ </div>
21
+ <div class="fam">
22
+ <div class="k">Space Grotesk — display / headline (--cs-font-family-display)</div>
23
+ <div class="cs-type-display cs-type-big">Turn Your Will Into Real</div>
24
+ <div class="cs-type-display cs-type-set">Hiện Thực Hoá Ý Chí · variable 300–700 · Vietnamese subset · opt-in via <span class="cs-type-mono">.cs-display-face</span></div>
19
25
  </div>
20
26
  <div class="fam" style="margin-bottom:0">
21
- <div class="k">JetBrains Mono — code / data</div>
22
- <div class="mono big" style="font-size:24px">--cs-color-brand-ochre</div>
23
- <div class="mono set">0123456789 · v1.5.1 · {} =&gt; () · 400 500 700</div>
27
+ <div class="k">JetBrains Mono — code / data (--cs-font-family-mono)</div>
28
+ <div class="cs-type-mono cs-type-big" style="font-size:24px">--cs-color-brand-ochre</div>
29
+ <div class="cs-type-mono cs-type-set">0123456789 · v1.5.1 · {} =&gt; () · 400 500 700</div>
24
30
  </div>
25
31
  </body></html>
package/llms.txt CHANGED
@@ -1,15 +1,16 @@
1
1
  # CyberSkill Design System
2
2
 
3
- > HTML-first, Vietnamese-first design system, pinned **v1.0.0**. Immutable anchors: Umber #45210E · Ochre #F4BA17. Three independent axes — Theme (light · dark) × Element (Ngũ Hành, 15 variants) × Language (EN · VI); surface treatment is liquid-glass (fixed). It ships 99 components / 115 exports, 84 copyable templates (EN·VN for emails + team/legal/finance; client/media collateral EN-first), and tokens in CSS + JSON + ESM + W3C DTCG + native mirrors. This file is the agent/tool front door: it maps each audience to the format it should consume. npm package name is **`@cyberskill/design`** (not `@cyberskill/react`). Release signal: tip SHA + [docs/release-notes.md](docs/release-notes.md) — no CHANGELOG.
3
+ > HTML-first, Vietnamese-first design system, LAUNCHED **v1.1.0**. Immutable anchors: Umber #45210E · Ochre #F4BA17. Four independent axes — Theme (light · dark · system) × Element (Ngũ Hành, 15 variants) × Language (EN · VI) × Style (`data-cs-style` — sole pack **liquid-glass**; absent ≡ default). It ships 105 components / 121 exports, 84 copyable templates (EN·VN for emails + team/legal/finance; client/media collateral EN-first), and tokens in CSS + JSON + ESM + W3C DTCG + native mirrors. This file is the agent/tool front door: it maps each audience to the format it should consume. npm package name is **`@cyberskill/design`** (not `@cyberskill/react`). Release signal: tip SHA + [docs/release-notes.md](docs/release-notes.md) — no CHANGELOG.
4
4
 
5
- The portable contract (styles.css · `_esm/cs.mjs` · bundle · tokens) works everywhere; the DC layer (`templates/**/*.dc.html`) is **Claude Design / authoring-environment-only**. **Google Stitch must not treat `*.dc.html` as source of truth** — use `DESIGN.md`, DTCG, `styles.css`, kitchen-sink, and `.cs-*` static HTML instead. Dual path: [docs/consuming.md](docs/consuming.md). The full non-negotiables list lives in `CONTRIBUTING.md` and `docs/conventions.md`.
5
+ The portable contract covers browser and bundler entry points: `styles.css` · `_esm/cs.mjs` legacy · `_ds_bundle.js` · tokens work without a build step; `_esm/react.mjs` is bundler-native JSX (Next/Vite must transpile — not a bare-browser import). The DC layer (`templates/**/*.dc.html`) is **Claude Design / authoring-environment-only**. **Google Stitch must not treat `*.dc.html` as source of truth** — use `DESIGN.md`, DTCG, `styles.css`, kitchen-sink, and `.cs-*` static HTML instead. Dual path: [docs/consuming.md](docs/consuming.md). The full non-negotiables list lives in `CONTRIBUTING.md` and `docs/conventions.md`.
6
6
 
7
7
  ## Consume by audience
8
8
 
9
- - **Claude Code** → [SKILL.md](SKILL.md) first, then [README.md](README.md): compose with `styles.css` + `_esm/cs.mjs` / `_ds_bundle.js` (prefix resolve). Optional DC templates only when the session has the compiler. Gates/`_audit/` need a full clone.
9
+ - **Claude Code** → [SKILL.md](SKILL.md) first, then [README.md](README.md): compose with `styles.css` + bundler `_esm/react.mjs` / legacy `_esm/cs.mjs` / `_ds_bundle.js` (prefix resolve). Optional DC templates only when the session has the compiler. Gates/`_audit/` need a full clone.
10
10
  - **Google Stitch** → [DESIGN.md](DESIGN.md) first, then this file + [tokens/tokens.dtcg.json](tokens/tokens.dtcg.json): generate **static** UI. Do **not** open or rewrite `templates/**/*.dc.html` as if they were plain HTML.
11
11
  - [styles.css](styles.css): any web / framework / email (Vue, Svelte, plain HTML, React) — link this one file for every `--cs-*` token, the `.cs-*` component classes, and the Liquid Glass surfaces. Framework-agnostic, no build step.
12
- - [_esm/cs.mjs](_esm/cs.mjs): ESM React entry — `import { Button, … } from "./_esm/cs.mjs"` (still link `styles.css`).
12
+ - [_esm/react.mjs](_esm/react.mjs): **default** npm entry — `import { Button, … } from "@cyberskill/design"` (React peer; Next/Vite transpile). Also `@cyberskill/design/react`.
13
+ - [_esm/cs.mjs](_esm/cs.mjs): browser / no-build legacy — `import { Button, … } from "@cyberskill/design/legacy"` (self-ensures React; still link `styles.css`). **Not for Next/SSR.**
13
14
  - [_ds_bundle.js](_ds_bundle.js): React (production) — `styles.css` + `<script src="_ds_bundle.js">`, then resolve the bundle global by prefix (its `_<projectId>` suffix is compiler-assigned and changes on re-import): `const CS = window[Object.keys(window).find(k => /^CyberSkillDesignSystem_/.test(k))]; const { Button, … } = CS`. Proven green by `_audit/consumer-smoke-test.html`. (Templates load via `ds-base.js`, which publishes a stable `window.CyberSkillDS` alias for the same reason.)
14
15
  - [tokens/tokens.json](tokens/tokens.json): design tools / native / token pipelines / other agents (Figma, Google Stitch, Style Dictionary) — every token grouped by category, plus theme/element override maps; also [tokens/tokens.js](tokens/tokens.js) (ESM) and [tokens/tokens.dtcg.json](tokens/tokens.dtcg.json) (**W3C DTCG** format for Tokens Studio for Figma / Style Dictionary). This is the canonical cross-tool contract.
15
16
  - [DESIGN.md](DESIGN.md): agents/tools that read a root DESIGN.md (Google Stitch open-spec style) — **this repo's** generated file with the brand doctrine, every token value (light + dark), and the component/template inventory. Generated from the DTCG source by `npm run build:design-md`; the `design-md-parity` gate pins it — do not hand-edit.
@@ -19,26 +20,31 @@ The portable contract (styles.css · `_esm/cs.mjs` · bundle · tokens) works ev
19
20
 
20
21
  - [dashboard.html](dashboard.html): legacy redirect stub → `/` (product site is Storybook)
21
22
  - [styles.css](styles.css): single entry point (`@import`s `tokens/` then `base/`)
22
- - [_esm/cs.mjs](_esm/cs.mjs): ESM entry (imports every component, no build)
23
+ - [_esm/react.mjs](_esm/react.mjs): bundler-native React entry (default package export; React peer)
24
+ - [_esm/cs.mjs](_esm/cs.mjs): browser / no-build legacy ESM entry (`@cyberskill/design/legacy`)
23
25
  - [tokens/](tokens/): design tokens as CSS custom properties + `tokens.json` / `tokens.js` / `tokens.dtcg.json` (W3C DTCG) + `viewer.html` (table + raw modes) + `native/` (SwiftUI/Compose/Flutter)
24
26
  - [base/](base/): reset, component classes (`.cs-*`), a11y, responsive, glass
25
- - [components/](components/): 99 components / 115 exports — every primary ships `.jsx` + `.d.ts` + `.prompt.md` + a `@dsCard` card; co-exports are documented in their parent's files
27
+ - [components/](components/): 105 components / 121 exports — every primary ships `.jsx` + `.d.ts` + `.prompt.md` + a `@dsCard` card; co-exports are documented in their parent's files
26
28
  - [templates/](templates/): 84 copyable starting points (`.dc.html`); `email-safe/` send-ready emails; `kitchen-sink.html`; `playground.html`
27
29
  - [guidelines/](guidelines/): specimen cards + `atomic-view.html` (portable component grid) — host product surface is Storybook at `/`
30
+ - [examples/static-hello/](examples/static-hello/): zero-install static consumer (Stitch / plain HTML)
31
+ - [examples/npm-hello/](examples/npm-hello/): first registry **browser** consumer — `@cyberskill/design@1.1.0` legacy entry (Lumi · Hỏa · plasma); Status Hub teams swap to `thuy`; Next/SSR apps use default `@cyberskill/design` React entry instead
32
+ - [examples/native/](examples/native/): SwiftUI / Compose / Flutter sample apps + store scaffolds — Compose is **Android Studio**-first (no committed `gradlew`; see `examples/native/README.md`)
28
33
  - [ui_kits/](ui_kits/): product recreations — status-hub · website · deck
29
- - [fonts/](fonts/): self-hosted Be Vietnam Pro + JetBrains Mono woff2
34
+ - [fonts/](fonts/): self-hosted Be Vietnam Pro (UI) + Space Grotesk (opt-in display, `--cs-font-family-display`) + JetBrains Mono woff2
30
35
  - [assets/](assets/): official logo mark (never recreate) · favicon · aurora washes · Lumi mascot
31
36
  - [README.md](README.md): the entrance document — voice, visual foundations, components, templates, index
32
37
  - [DESIGN.md](DESIGN.md): generated open-spec surface (doctrine + tokens + inventory) for Stitch-style consumers — pinned to DTCG by the design-md-parity gate
33
38
  - [SKILL.md](SKILL.md): agent entry — hard rules + fast orientation
34
39
  - [CONTRIBUTING.md](CONTRIBUTING.md): one-page onboarding for extending the system
35
- - [VERSION](VERSION): pinned 1.0.0 (matches [package.json](package.json))
40
+ - [VERSION](VERSION): pinned 1.1.0 (matches [package.json](package.json))
36
41
 
37
42
  ## Docs — consumers
38
43
 
39
- - [docs/consuming.md](docs/consuming.md): adopting & upgrading, Claude Code vs Stitch dual path, package name `@cyberskill/design`
40
- - [docs/release-notes.md](docs/release-notes.md): curated product highlights (not a changelog)
41
- - [docs/conventions.md](docs/conventions.md): authoring rules (naming grammar, the three axes)
44
+ - [docs/consuming.md](docs/consuming.md): adopting & upgrading, Claude Code vs Stitch dual path, package name `@cyberskill/design`; first registry install at [examples/npm-hello/](examples/npm-hello/) (Lumi · Hỏa · plasma); native mirrors at [examples/native/](examples/native/) (SwiftUI / Compose / Flutter samples)
45
+ - [docs/release-notes.md](docs/release-notes.md): curated product highlights (not a changelog) — includes `@cyberskill/design@1.1.0` Trusted Publishing / grant pointer
46
+ - [docs/consumer-grant.md](docs/consumer-grant.md): written npm grant (CyberSkill portfolio; UNLICENSED)
47
+ - [docs/conventions.md](docs/conventions.md): authoring rules (naming grammar, the four axes)
42
48
  - [docs/design-styles.md](docs/design-styles.md): the live styling axes and the fixed liquid-glass treatment
43
49
  - [docs/products.md](docs/products.md): product → element registry (**locked**)
44
50
  - [docs/contrast-report.md](docs/contrast-report.md): generated APCA elemental sweep — 0 failures at its Lc ≥ 60 UI-label floor (body text authors to Lc ≥ 75)