@cyberskill/design 1.1.1 → 1.3.8

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 (481) hide show
  1. package/DESIGN.md +28 -5
  2. package/README.md +23 -22
  3. package/SKILL.md +7 -7
  4. package/THIRD-PARTY-NOTICES.md +35 -0
  5. package/VERSION +1 -1
  6. package/_ds_bundle.js +1495 -1733
  7. package/_ds_manifest.json +1 -1
  8. package/_esm/cs.mjs +18 -4
  9. package/_esm/react.d.ts +2 -0
  10. package/_esm/react.mjs +7 -1
  11. package/_vendor/NOTICE.md +16 -0
  12. package/_vendor/babel/README.md +7 -0
  13. package/_vendor/babel/babel.min.js +4 -0
  14. package/_vendor/react/README.md +3 -0
  15. package/_vendor/react/react-dom.production.min.js +1 -0
  16. package/_vendor/react/react.production.min.js +1 -0
  17. package/assets/aurora-hoa.webp +0 -0
  18. package/assets/aurora-kim.webp +0 -0
  19. package/assets/aurora-moc.webp +0 -0
  20. package/assets/aurora-tho.webp +0 -0
  21. package/assets/aurora-thuy.webp +0 -0
  22. package/base/a11y.css +18 -0
  23. package/base/ai.css +9 -4
  24. package/base/collections.css +18 -7
  25. package/base/components.css +16 -4
  26. package/base/controls.css +116 -66
  27. package/base/data.css +4 -4
  28. package/base/feedback.css +14 -2
  29. package/base/forms.css +10 -4
  30. package/base/glass.css +7 -1
  31. package/base/interaction.css +6 -2
  32. package/base/navigation.css +9 -3
  33. package/base/reset.css +7 -1
  34. package/base/responsive.css +38 -12
  35. package/base/shell.css +15 -3
  36. package/components/_i18n/i18n.js +41 -4
  37. package/components/_i18n/strings.js +89 -22
  38. package/components/ai/ChatMessage.d.ts +2 -0
  39. package/components/ai/ChatMessage.jsx +8 -4
  40. package/components/ai/ConfidenceMeter.d.ts +2 -0
  41. package/components/ai/ConfidenceMeter.jsx +8 -6
  42. package/components/ai/HumanReviewGate.d.ts +2 -0
  43. package/components/ai/PromptInput.d.ts +2 -0
  44. package/components/ai/TypingIndicator.d.ts +2 -0
  45. package/components/ai/ai-conversation.card.html +3 -3
  46. package/components/ai/ai-lumi.card.html +3 -3
  47. package/components/ai/ai.card.html +3 -3
  48. package/components/brand/brand.card.html +3 -3
  49. package/components/button/buttons.card.html +3 -3
  50. package/components/data/Image.jsx +18 -2
  51. package/components/data/Sortable.d.ts +5 -1
  52. package/components/data/Sortable.jsx +42 -9
  53. package/components/data/Sortable.prompt.md +4 -2
  54. package/components/data/Terminal.jsx +3 -2
  55. package/components/data/Tooltip.d.ts +2 -0
  56. package/components/data/Tooltip.jsx +6 -3
  57. package/components/data/Tree.d.ts +2 -1
  58. package/components/data/Tree.jsx +137 -16
  59. package/components/data/Tree.prompt.md +1 -1
  60. package/components/data/Watermark.jsx +11 -3
  61. package/components/data/collections.card.html +3 -3
  62. package/components/data/data.card.html +3 -3
  63. package/components/datatable/DataGrid.jsx +10 -1
  64. package/components/datatable/DataTable.d.ts +24 -1
  65. package/components/datatable/DataTable.jsx +78 -5
  66. package/components/datatable/DataTable.prompt.md +2 -1
  67. package/components/datatable/datatable.card.html +20 -16
  68. package/components/dialog/Dialog.jsx +13 -45
  69. package/components/dialog/dialog.card.html +3 -3
  70. package/components/feedback/Alert.d.ts +2 -0
  71. package/components/feedback/Alert.jsx +8 -2
  72. package/components/feedback/EmptyState.d.ts +2 -0
  73. package/components/feedback/EmptyState.jsx +6 -3
  74. package/components/feedback/ProgressBar.d.ts +2 -0
  75. package/components/feedback/ProgressBar.jsx +9 -4
  76. package/components/feedback/Toast.jsx +15 -1
  77. package/components/feedback/Toast.prompt.md +2 -1
  78. package/components/feedback/feedback-2.card.html +3 -3
  79. package/components/feedback/feedback.card.html +3 -3
  80. package/components/forms/Cascader.jsx +76 -8
  81. package/components/forms/Editor.jsx +37 -2
  82. package/components/forms/FileUpload.d.ts +2 -0
  83. package/components/forms/FileUpload.jsx +22 -8
  84. package/components/forms/Form.d.ts +3 -1
  85. package/components/forms/Form.jsx +9 -1
  86. package/components/forms/Form.prompt.md +1 -1
  87. package/components/forms/Mentions.d.ts +1 -1
  88. package/components/forms/Mentions.jsx +59 -7
  89. package/components/forms/Mentions.prompt.md +3 -1
  90. package/components/forms/Rating.d.ts +3 -2
  91. package/components/forms/Rating.jsx +34 -3
  92. package/components/forms/Rating.prompt.md +1 -1
  93. package/components/forms/Select.d.ts +2 -0
  94. package/components/forms/Select.jsx +6 -2
  95. package/components/forms/Slider.d.ts +2 -0
  96. package/components/forms/Slider.jsx +5 -2
  97. package/components/forms/Switch.d.ts +2 -0
  98. package/components/forms/Switch.jsx +15 -3
  99. package/components/forms/TimePicker.jsx +3 -1
  100. package/components/forms/Toggle.d.ts +2 -0
  101. package/components/forms/Toggle.jsx +14 -2
  102. package/components/forms/forms-2.card.html +3 -3
  103. package/components/forms/forms.card.html +3 -3
  104. package/components/icon/Icon.d.ts +1 -1
  105. package/components/icon/Icon.jsx +1 -0
  106. package/components/icon/Icon.prompt.md +1 -1
  107. package/components/icon/icon.card.html +3 -3
  108. package/components/logo/logo.card.html +3 -3
  109. package/components/navigation/CommandPalette.d.ts +2 -0
  110. package/components/navigation/CommandPalette.jsx +22 -7
  111. package/components/navigation/Menu.d.ts +2 -0
  112. package/components/navigation/Menu.jsx +60 -6
  113. package/components/navigation/Steps.d.ts +2 -0
  114. package/components/navigation/Steps.jsx +6 -3
  115. package/components/navigation/Tabs.d.ts +2 -0
  116. package/components/navigation/Tabs.jsx +6 -3
  117. package/components/navigation/Toolbar.d.ts +3 -2
  118. package/components/navigation/Toolbar.jsx +119 -12
  119. package/components/navigation/Toolbar.prompt.md +1 -1
  120. package/components/navigation/navigation.card.html +3 -3
  121. package/components/navigation/shell.card.html +3 -3
  122. package/components/overlays/AlertDialog.jsx +19 -49
  123. package/components/overlays/ContextMenu.d.ts +2 -0
  124. package/components/overlays/ContextMenu.jsx +6 -3
  125. package/components/overlays/Drawer.d.ts +2 -0
  126. package/components/overlays/Drawer.jsx +24 -20
  127. package/components/overlays/OverlayManager.d.ts +40 -0
  128. package/components/overlays/OverlayManager.jsx +214 -0
  129. package/components/overlays/OverlayManager.prompt.md +12 -0
  130. package/components/overlays/Tour.jsx +14 -7
  131. package/components/overlays/alertdialog.card.html +3 -3
  132. package/components/overlays/overlays.card.html +3 -3
  133. package/components/textfield/textfield.card.html +3 -3
  134. package/dist/styles.min.css +2252 -0
  135. package/docs/benchmark-rubric.md +1 -1
  136. package/docs/ci-cd.md +19 -12
  137. package/docs/consumer-grant.md +3 -0
  138. package/docs/consuming.md +13 -13
  139. package/docs/contrast-report.md +79 -1
  140. package/docs/conventions.md +21 -8
  141. package/docs/decisions.md +45 -7
  142. package/docs/deploy.md +17 -6
  143. package/docs/design-styles.md +2 -2
  144. package/docs/quality-gates.md +35 -15
  145. package/docs/release-notes.md +2 -2
  146. package/docs/release-runbook.md +78 -0
  147. package/docs/sync.md +2 -2
  148. package/docs/vi/benchmark-rubric.md +1 -1
  149. package/docs/vi/ci-cd.md +17 -12
  150. package/docs/vi/consumer-grant.md +3 -0
  151. package/docs/vi/consuming.md +13 -13
  152. package/docs/vi/contrast-report.md +79 -1
  153. package/docs/vi/conventions.md +20 -7
  154. package/docs/vi/decisions.md +43 -6
  155. package/docs/vi/deploy.md +17 -6
  156. package/docs/vi/quality-gates.md +34 -15
  157. package/docs/vi/release-notes.md +2 -2
  158. package/docs/vi/release-runbook.md +78 -0
  159. package/docs/vi/sync.md +2 -2
  160. package/docs/viewer.html +2 -2
  161. package/fonts/OFL.txt +98 -0
  162. package/guidelines/atomic-view.html +13 -9
  163. package/guidelines/brand-imagery.html +1 -1
  164. package/guidelines/elements-variants.html +5 -5
  165. package/guidelines/spacing-breakpoints.html +2 -1
  166. package/guidelines/surfaces-glass.html +1 -1
  167. package/llms.txt +5 -5
  168. package/package.json +38 -10
  169. package/templates/_ds-base.canonical.js +55 -0
  170. package/templates/ai-cluster-demo.html +2 -2
  171. package/templates/app-shell/AppShell.dc.html +7 -5
  172. package/templates/app-shell/content-schema.json +7 -0
  173. package/templates/app-shell/ds-base.js +33 -1
  174. package/templates/app-shell/support.js +13 -20
  175. package/templates/article/Article.dc.html +7 -3
  176. package/templates/article/content-schema.json +7 -0
  177. package/templates/article/ds-base.js +33 -1
  178. package/templates/article/support.js +13 -20
  179. package/templates/auth/Auth.dc.html +33 -12
  180. package/templates/auth/content-schema.json +37 -0
  181. package/templates/auth/ds-base.js +33 -1
  182. package/templates/auth/support.js +13 -20
  183. package/templates/bod-deck/BodDeck.dc.html +11 -10
  184. package/templates/bod-deck/ds-base.js +33 -1
  185. package/templates/bod-deck/support.js +13 -20
  186. package/templates/bod-investor-update/BodInvestorUpdate.dc.html +4 -3
  187. package/templates/bod-investor-update/ds-base.js +33 -1
  188. package/templates/bod-investor-update/support.js +13 -20
  189. package/templates/bod-memo/BodMemo.dc.html +6 -5
  190. package/templates/bod-memo/ds-base.js +33 -1
  191. package/templates/bod-memo/support.js +13 -20
  192. package/templates/bod-minutes/BodMinutes.dc.html +2 -1
  193. package/templates/bod-minutes/ds-base.js +33 -1
  194. package/templates/bod-minutes/support.js +13 -20
  195. package/templates/bod-report/BodReport.dc.html +3 -2
  196. package/templates/bod-report/ds-base.js +33 -1
  197. package/templates/bod-report/support.js +13 -20
  198. package/templates/bod-resolution/BodResolution.dc.html +5 -4
  199. package/templates/bod-resolution/ds-base.js +33 -1
  200. package/templates/bod-resolution/support.js +13 -20
  201. package/templates/culture-event-invite/CultureEventInvite.dc.html +3 -2
  202. package/templates/culture-event-invite/ds-base.js +33 -1
  203. package/templates/culture-event-invite/support.js +13 -20
  204. package/templates/dashboard/Dashboard.dc.html +10 -6
  205. package/templates/dashboard/content-schema.json +7 -0
  206. package/templates/dashboard/ds-base.js +33 -1
  207. package/templates/dashboard/support.js +13 -20
  208. package/templates/delivery-change-note/DeliveryChangeNote.dc.html +4 -3
  209. package/templates/delivery-change-note/ds-base.js +33 -1
  210. package/templates/delivery-change-note/support.js +13 -20
  211. package/templates/delivery-kickoff/DeliveryKickoff.dc.html +3 -2
  212. package/templates/delivery-kickoff/ds-base.js +33 -1
  213. package/templates/delivery-kickoff/support.js +13 -20
  214. package/templates/delivery-qbr-deck/DeliveryQbrDeck.dc.html +6 -5
  215. package/templates/delivery-qbr-deck/ds-base.js +33 -1
  216. package/templates/delivery-qbr-deck/support.js +13 -20
  217. package/templates/delivery-runbook/DeliveryRunbook.dc.html +5 -4
  218. package/templates/delivery-runbook/ds-base.js +33 -1
  219. package/templates/delivery-runbook/support.js +13 -20
  220. package/templates/delivery-status-email/DeliveryStatusEmail.dc.html +3 -2
  221. package/templates/delivery-status-email/ds-base.js +33 -1
  222. package/templates/delivery-status-email/support.js +13 -20
  223. package/templates/doc-style-guide/DocStyleGuide.dc.html +67 -64
  224. package/templates/doc-style-guide/ds-base.js +33 -1
  225. package/templates/doc-style-guide/support.js +13 -20
  226. package/templates/doc-suite-index/DocSuiteIndex.dc.html +46 -45
  227. package/templates/doc-suite-index/ds-base.js +33 -1
  228. package/templates/doc-suite-index/support.js +13 -20
  229. package/templates/doc-templates/DocTemplates.dc.html +42 -41
  230. package/templates/doc-templates/ds-base.js +33 -1
  231. package/templates/doc-templates/support.js +13 -20
  232. package/templates/email/Email.dc.html +3 -2
  233. package/templates/email/ds-base.js +33 -1
  234. package/templates/email/support.js +13 -20
  235. package/templates/email-safe/email-announcement.html +2 -2
  236. package/templates/email-safe/email-dunning.html +2 -2
  237. package/templates/email-safe/email-investor.html +2 -2
  238. package/templates/email-safe/email-launch.html +2 -2
  239. package/templates/email-safe/email-newsletter.html +2 -2
  240. package/templates/email-safe/email-status.html +2 -2
  241. package/templates/email-safe/email-transactional.html +2 -2
  242. package/templates/finance-dunning-email/FinanceDunningEmail.dc.html +6 -5
  243. package/templates/finance-dunning-email/ds-base.js +33 -1
  244. package/templates/finance-dunning-email/support.js +13 -20
  245. package/templates/finance-expense-report/FinanceExpenseReport.dc.html +4 -3
  246. package/templates/finance-expense-report/ds-base.js +33 -1
  247. package/templates/finance-expense-report/support.js +13 -20
  248. package/templates/finance-invoice/FinanceInvoice.dc.html +6 -5
  249. package/templates/finance-invoice/ds-base.js +33 -1
  250. package/templates/finance-invoice/support.js +13 -20
  251. package/templates/finance-quote/FinanceQuote.dc.html +6 -5
  252. package/templates/finance-quote/ds-base.js +33 -1
  253. package/templates/finance-quote/support.js +13 -20
  254. package/templates/hr-announcement/HrAnnouncement.dc.html +5 -4
  255. package/templates/hr-announcement/ds-base.js +33 -1
  256. package/templates/hr-announcement/support.js +13 -20
  257. package/templates/hr-interview-kit/HrInterviewKit.dc.html +5 -4
  258. package/templates/hr-interview-kit/ds-base.js +33 -1
  259. package/templates/hr-interview-kit/support.js +13 -20
  260. package/templates/hr-offboarding/HrOffboarding.dc.html +2 -1
  261. package/templates/hr-offboarding/ds-base.js +33 -1
  262. package/templates/hr-offboarding/support.js +13 -20
  263. package/templates/hr-performance-review/HrPerformanceReview.dc.html +2 -1
  264. package/templates/hr-performance-review/ds-base.js +33 -1
  265. package/templates/hr-performance-review/support.js +13 -20
  266. package/templates/hr-pip/HrPip.dc.html +2 -1
  267. package/templates/hr-pip/ds-base.js +33 -1
  268. package/templates/hr-pip/support.js +13 -20
  269. package/templates/kitchen-sink.html +9 -4
  270. package/templates/legal-msa/LegalMsa.dc.html +2 -1
  271. package/templates/legal-msa/ds-base.js +33 -1
  272. package/templates/legal-msa/support.js +13 -20
  273. package/templates/legal-sow/LegalSow.dc.html +2 -1
  274. package/templates/legal-sow/ds-base.js +33 -1
  275. package/templates/legal-sow/support.js +13 -20
  276. package/templates/marketing-campaign-brief/MarketingCampaignBrief.dc.html +3 -2
  277. package/templates/marketing-campaign-brief/ds-base.js +33 -1
  278. package/templates/marketing-campaign-brief/support.js +13 -20
  279. package/templates/marketing-case-study/MarketingCaseStudy.dc.html +6 -5
  280. package/templates/marketing-case-study/ds-base.js +33 -1
  281. package/templates/marketing-case-study/support.js +13 -20
  282. package/templates/marketing-launch/MarketingLaunch.dc.html +6 -5
  283. package/templates/marketing-launch/ds-base.js +33 -1
  284. package/templates/marketing-launch/support.js +13 -20
  285. package/templates/marketing-newsletter/MarketingNewsletter.dc.html +13 -12
  286. package/templates/marketing-newsletter/ds-base.js +33 -1
  287. package/templates/marketing-newsletter/support.js +13 -20
  288. package/templates/marketing-page/MarketingPage.dc.html +19 -14
  289. package/templates/marketing-page/content-schema.json +1 -0
  290. package/templates/marketing-page/ds-base.js +33 -1
  291. package/templates/marketing-page/support.js +13 -20
  292. package/templates/marketing-press-release/MarketingPressRelease.dc.html +2 -1
  293. package/templates/marketing-press-release/ds-base.js +33 -1
  294. package/templates/marketing-press-release/support.js +13 -20
  295. package/templates/marketing-social-kit/MarketingSocialKit.dc.html +5 -4
  296. package/templates/marketing-social-kit/ds-base.js +33 -1
  297. package/templates/marketing-social-kit/support.js +13 -20
  298. package/templates/sales-one-pager/SalesOnePager.dc.html +5 -4
  299. package/templates/sales-one-pager/ds-base.js +33 -1
  300. package/templates/sales-one-pager/support.js +13 -20
  301. package/templates/sales-proposal-deck/SalesProposalDeck.dc.html +7 -6
  302. package/templates/sales-proposal-deck/ds-base.js +33 -1
  303. package/templates/sales-proposal-deck/support.js +13 -20
  304. package/templates/settings/Settings.dc.html +7 -3
  305. package/templates/settings/content-schema.json +7 -0
  306. package/templates/settings/ds-base.js +33 -1
  307. package/templates/settings/support.js +13 -20
  308. package/templates/slide-deck/SlideDeck.dc.html +5 -4
  309. package/templates/slide-deck/ds-base.js +33 -1
  310. package/templates/slide-deck/support.js +13 -20
  311. package/templates/team-meeting-agenda/TeamMeetingAgenda.dc.html +2 -1
  312. package/templates/team-meeting-agenda/ds-base.js +33 -1
  313. package/templates/team-meeting-agenda/support.js +13 -20
  314. package/templates/tech-incident-report/TechIncidentReport.dc.html +3 -2
  315. package/templates/tech-incident-report/ds-base.js +33 -1
  316. package/templates/tech-incident-report/support.js +13 -20
  317. package/templates/tech-release-notes/TechReleaseNotes.dc.html +6 -5
  318. package/templates/tech-release-notes/ds-base.js +33 -1
  319. package/templates/tech-release-notes/support.js +13 -20
  320. package/templates/tech-retro/TechRetro.dc.html +4 -3
  321. package/templates/tech-retro/ds-base.js +33 -1
  322. package/templates/tech-retro/support.js +13 -20
  323. package/templates/tech-rfc/TechRfc.dc.html +3 -2
  324. package/templates/tech-rfc/ds-base.js +33 -1
  325. package/templates/tech-rfc/support.js +13 -20
  326. package/templates/vn-appointment-transfer/VnAppointmentTransfer.dc.html +36 -35
  327. package/templates/vn-appointment-transfer/ds-base.js +33 -1
  328. package/templates/vn-appointment-transfer/support.js +13 -20
  329. package/templates/vn-certificate-of-employment/VnCertificateOfEmployment.dc.html +27 -26
  330. package/templates/vn-certificate-of-employment/ds-base.js +33 -1
  331. package/templates/vn-certificate-of-employment/support.js +13 -20
  332. package/templates/vn-code-of-conduct/VnCodeOfConduct.dc.html +44 -43
  333. package/templates/vn-code-of-conduct/ds-base.js +33 -1
  334. package/templates/vn-code-of-conduct/support.js +13 -20
  335. package/templates/vn-compensation-regulation/VnCompensationRegulation.dc.html +53 -52
  336. package/templates/vn-compensation-regulation/ds-base.js +33 -1
  337. package/templates/vn-compensation-regulation/support.js +13 -20
  338. package/templates/vn-contract-amendment/VnContractAmendment.dc.html +41 -40
  339. package/templates/vn-contract-amendment/ds-base.js +33 -1
  340. package/templates/vn-contract-amendment/support.js +13 -20
  341. package/templates/vn-contractor-agreement/VnContractorAgreement.dc.html +50 -49
  342. package/templates/vn-contractor-agreement/ds-base.js +33 -1
  343. package/templates/vn-contractor-agreement/support.js +13 -20
  344. package/templates/vn-data-protection-policy/VnDataProtectionPolicy.dc.html +54 -53
  345. package/templates/vn-data-protection-policy/ds-base.js +33 -1
  346. package/templates/vn-data-protection-policy/support.js +13 -20
  347. package/templates/vn-disciplinary-case-file/VnDisciplinaryCaseFile.dc.html +72 -71
  348. package/templates/vn-disciplinary-case-file/ds-base.js +33 -1
  349. package/templates/vn-disciplinary-case-file/support.js +13 -20
  350. package/templates/vn-disciplinary-schedule/VnDisciplinarySchedule.dc.html +21 -20
  351. package/templates/vn-disciplinary-schedule/ds-base.js +33 -1
  352. package/templates/vn-disciplinary-schedule/support.js +13 -20
  353. package/templates/vn-employee-request/VnEmployeeRequest.dc.html +54 -53
  354. package/templates/vn-employee-request/ds-base.js +33 -1
  355. package/templates/vn-employee-request/support.js +13 -20
  356. package/templates/vn-exit-handover/VnExitHandover.dc.html +122 -121
  357. package/templates/vn-exit-handover/ds-base.js +33 -1
  358. package/templates/vn-exit-handover/support.js +13 -20
  359. package/templates/vn-foreign-employee-pack/VnForeignEmployeePack.dc.html +31 -30
  360. package/templates/vn-foreign-employee-pack/ds-base.js +33 -1
  361. package/templates/vn-foreign-employee-pack/support.js +13 -20
  362. package/templates/vn-grassroots-democracy/VnGrassrootsDemocracy.dc.html +54 -53
  363. package/templates/vn-grassroots-democracy/ds-base.js +33 -1
  364. package/templates/vn-grassroots-democracy/support.js +13 -20
  365. package/templates/vn-infosec-policy/VnInfosecPolicy.dc.html +50 -49
  366. package/templates/vn-infosec-policy/ds-base.js +33 -1
  367. package/templates/vn-infosec-policy/support.js +13 -20
  368. package/templates/vn-internal-labor-regulations/VnInternalLaborRegulations.dc.html +84 -83
  369. package/templates/vn-internal-labor-regulations/ds-base.js +33 -1
  370. package/templates/vn-internal-labor-regulations/support.js +13 -20
  371. package/templates/vn-internship-agreement/VnInternshipAgreement.dc.html +44 -43
  372. package/templates/vn-internship-agreement/ds-base.js +33 -1
  373. package/templates/vn-internship-agreement/support.js +13 -20
  374. package/templates/vn-job-description/VnJobDescription.dc.html +28 -27
  375. package/templates/vn-job-description/ds-base.js +33 -1
  376. package/templates/vn-job-description/support.js +13 -20
  377. package/templates/vn-labor-contract/VnLaborContract.dc.html +109 -108
  378. package/templates/vn-labor-contract/ds-base.js +33 -1
  379. package/templates/vn-labor-contract/support.js +13 -20
  380. package/templates/vn-labour-management-book/VnLabourManagementBook.dc.html +32 -31
  381. package/templates/vn-labour-management-book/ds-base.js +33 -1
  382. package/templates/vn-labour-management-book/support.js +13 -20
  383. package/templates/vn-mutual-nda/VnMutualNda.dc.html +45 -44
  384. package/templates/vn-mutual-nda/ds-base.js +33 -1
  385. package/templates/vn-mutual-nda/support.js +13 -20
  386. package/templates/vn-ndnca-ip/VnNdncaIp.dc.html +73 -72
  387. package/templates/vn-ndnca-ip/ds-base.js +33 -1
  388. package/templates/vn-ndnca-ip/support.js +13 -20
  389. package/templates/vn-offer-letter/VnOfferLetter.dc.html +32 -31
  390. package/templates/vn-offer-letter/ds-base.js +33 -1
  391. package/templates/vn-offer-letter/support.js +13 -20
  392. package/templates/vn-onboarding-checklist/VnOnboardingChecklist.dc.html +16 -15
  393. package/templates/vn-onboarding-checklist/ds-base.js +33 -1
  394. package/templates/vn-onboarding-checklist/support.js +13 -20
  395. package/templates/vn-pdpl-consent/VnPdplConsent.dc.html +43 -42
  396. package/templates/vn-pdpl-consent/ds-base.js +33 -1
  397. package/templates/vn-pdpl-consent/support.js +13 -20
  398. package/templates/vn-performance-evaluation-regulation/VnPerformanceEvaluationRegulation.dc.html +65 -64
  399. package/templates/vn-performance-evaluation-regulation/ds-base.js +33 -1
  400. package/templates/vn-performance-evaluation-regulation/support.js +13 -20
  401. package/templates/vn-performance-review-form/VnPerformanceReviewForm.dc.html +49 -48
  402. package/templates/vn-performance-review-form/ds-base.js +33 -1
  403. package/templates/vn-performance-review-form/support.js +13 -20
  404. package/templates/vn-phantom-stock/VnPhantomStock.dc.html +41 -40
  405. package/templates/vn-phantom-stock/ds-base.js +33 -1
  406. package/templates/vn-phantom-stock/support.js +13 -20
  407. package/templates/vn-probation-contract/VnProbationContract.dc.html +56 -55
  408. package/templates/vn-probation-contract/ds-base.js +33 -1
  409. package/templates/vn-probation-contract/support.js +13 -20
  410. package/templates/vn-receipt-acknowledgement/VnReceiptAcknowledgement.dc.html +28 -27
  411. package/templates/vn-receipt-acknowledgement/ds-base.js +33 -1
  412. package/templates/vn-receipt-acknowledgement/support.js +13 -20
  413. package/templates/vn-remote-work-policy/VnRemoteWorkPolicy.dc.html +44 -43
  414. package/templates/vn-remote-work-policy/ds-base.js +33 -1
  415. package/templates/vn-remote-work-policy/support.js +13 -20
  416. package/templates/vn-resignation-letter/VnResignationLetter.dc.html +20 -19
  417. package/templates/vn-resignation-letter/ds-base.js +33 -1
  418. package/templates/vn-resignation-letter/support.js +13 -20
  419. package/templates/vn-salary-scale/VnSalaryScale.dc.html +39 -38
  420. package/templates/vn-salary-scale/ds-base.js +33 -1
  421. package/templates/vn-salary-scale/support.js +13 -20
  422. package/templates/vn-sow-appendix/VnSowAppendix.dc.html +21 -20
  423. package/templates/vn-sow-appendix/ds-base.js +33 -1
  424. package/templates/vn-sow-appendix/support.js +13 -20
  425. package/templates/vn-termination-decision/VnTerminationDecision.dc.html +25 -24
  426. package/templates/vn-termination-decision/ds-base.js +33 -1
  427. package/templates/vn-termination-decision/support.js +13 -20
  428. package/templates/vn-total-rewards-appendix/VnTotalRewardsAppendix.dc.html +63 -62
  429. package/templates/vn-total-rewards-appendix/ds-base.js +33 -1
  430. package/templates/vn-total-rewards-appendix/support.js +13 -20
  431. package/templates/vn-training-commitment/VnTrainingCommitment.dc.html +39 -38
  432. package/templates/vn-training-commitment/ds-base.js +33 -1
  433. package/templates/vn-training-commitment/support.js +13 -20
  434. package/templates/vn-travel-expense-policy/VnTravelExpensePolicy.dc.html +50 -49
  435. package/templates/vn-travel-expense-policy/ds-base.js +33 -1
  436. package/templates/vn-travel-expense-policy/support.js +13 -20
  437. package/tokens/colors.css +19 -1
  438. package/tokens/component-tokens.css +1 -0
  439. package/tokens/element-seeds.json +2 -2
  440. package/tokens/elements.css +228 -21
  441. package/tokens/elevation.css +8 -2
  442. package/tokens/native/CSTokens.kt +37 -2
  443. package/tokens/native/CSTokens.swift +37 -2
  444. package/tokens/native/cs_tokens.dart +37 -2
  445. package/tokens/provenance.json +12 -12
  446. package/tokens/spacing.css +4 -1
  447. package/tokens/tokens.dtcg.json +129 -16
  448. package/tokens/tokens.js +59 -18
  449. package/tokens/tokens.json +58 -17
  450. package/tokens/typography.css +2 -0
  451. package/ui_kits/deck/index.html +4 -0
  452. package/ui_kits/status-hub/StatusHub.jsx +30 -4
  453. package/ui_kits/status-hub/index.html +3 -3
  454. package/ui_kits/status-hub/login.html +55 -9
  455. package/ui_kits/status-hub/project.html +4 -0
  456. package/ui_kits/status-hub/settings.html +35 -13
  457. package/ui_kits/status-hub/status.css +5 -1
  458. package/ui_kits/website/Website.jsx +25 -3
  459. package/ui_kits/website/careers.html +5 -1
  460. package/ui_kits/website/chat.html +5 -3
  461. package/ui_kits/website/index.html +3 -3
  462. package/ui_kits/website/site.css +3 -3
  463. package/ui_kits/website/work.html +5 -1
  464. package/assets/aurora-hoa.png +0 -0
  465. package/assets/aurora-kim.png +0 -0
  466. package/assets/aurora-moc.png +0 -0
  467. package/assets/aurora-thuy.png +0 -0
  468. package/docs/status/assets/favicon.svg +0 -5
  469. package/docs/status/assets/status-legacy.css +0 -399
  470. package/docs/status/assets/status-legacy.js +0 -505
  471. package/docs/status/assets/status.css +0 -644
  472. package/docs/status/assets/status.js +0 -1308
  473. package/docs/status/data/status-feed.json +0 -1
  474. package/docs/status/data/task/TASK-REL-001.js +0 -1
  475. package/docs/status/data/task/TASK-REL-002.js +0 -1
  476. package/docs/status/index.html +0 -42
  477. package/docs/status/roadmap.html +0 -4
  478. package/docs/status/status-legacy.html +0 -117
  479. package/docs/tasks/BACKLOG.md +0 -26
  480. package/docs/tasks/release/TASK-REL-001-launch-1-1-0/spec.md +0 -55
  481. package/docs/tasks/release/TASK-REL-002-republish-1-1-1/spec.md +0 -54
@@ -1,6 +1,7 @@
1
1
  <!DOCTYPE html>
2
- <html>
2
+ <html lang="en">
3
3
  <head>
4
+ <title>Marketing page · CyberSkill</title>
4
5
  <meta charset="utf-8">
5
6
  <meta name="viewport" content="width=device-width, initial-scale=1">
6
7
  <script src="./support.js"></script>
@@ -13,6 +14,8 @@
13
14
  <script src="../../image-slot.js"></script>
14
15
  </helmet>
15
16
  <div data-theme="{{ rootTheme }}" lang="{{ langAttr }}" data-cs-element="{{ elAttr }}" data-cs-variant="{{ vaAttr }}" style="font-family:var(--cs-font-family-ui);color:var(--cs-color-text-primary);background:var(--cs-color-surface-page);min-height:100vh">
17
+ <a class="cs-skip" href="#main" style="position:absolute;left:-999px;top:auto;width:1px;height:1px;overflow:hidden">{{ skipLabel }}</a>
18
+ <main id="main">
16
19
  <header style="position:sticky;top:0;z-index:50;display:flex;align-items:center;flex-wrap:wrap;gap:10px 24px;padding:14px 32px;background:color-mix(in oklab,var(--cs-color-surface-panel) 82%,transparent);backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px);border-bottom:1px solid var(--cs-color-border-default)">
17
20
  <div style="display:flex;align-items:center;gap:10px;font-weight:800;font-size:18px;color:var(--cs-color-text-primary);letter-spacing:-0.01em">
18
21
  <x-import component-from-global-scope="CyberSkillDS.Logo" size="32" hint-size="32px,32px"></x-import>
@@ -28,17 +31,17 @@
28
31
  </div>
29
32
  </header>
30
33
 
31
- <section style="position:relative;overflow:hidden;background:var(--cs-accent-strong);color:#fff;padding:84px 32px 96px">
34
+ <section style="position:relative;overflow:hidden;background:var(--cs-color-brand-umber);color:#FFFDF8;padding:84px 32px 96px">
32
35
  <image-slot id="cs-mktg-hero" shape="rect" placeholder="Drop a hero image (optional)" style="position:absolute;inset:0"></image-slot>
33
36
  <div class="cs-aurora-wash" style="position:absolute;inset:0;opacity:0.55;pointer-events:none"></div>
34
37
  <div style="position:absolute;inset:0;pointer-events:none;background:linear-gradient(180deg,rgba(42,26,13,0.62),rgba(42,26,13,0.42))"></div>
35
38
  <div style="position:relative;z-index:1;max-width:1080px;margin:0 auto">
36
- <div class="cs-rise-in" style="font-size:12px;font-weight:700;text-transform:uppercase;letter-spacing:0.12em;color:#fff">{{ heroKicker }}</div>
39
+ <div class="cs-rise-in" style="font-size:12px;font-weight:700;text-transform:uppercase;letter-spacing:0.12em;color:#FFFDF8">{{ heroKicker }}</div>
37
40
  <h1 class="cs-rise-in cs-rise-in--2" style="font-size:clamp(40px,6vw,64px);font-weight:800;letter-spacing:-0.02em;line-height:1.05;color:var(--cs-accent-bright);margin:14px 0 4px">{{ heroH }}</h1>
38
41
  <div class="cs-rise-in cs-rise-in--3" style="font-size:20px;font-weight:600;opacity:0.9;margin-bottom:18px">{{ heroSub }}</div>
39
42
  <p class="cs-rise-in cs-rise-in--4" style="font-size:18px;line-height:1.55;max-width:600px;opacity:0.95">{{ heroP }}</p>
40
43
  <div style="max-width:600px;margin-top:26px">
41
- <x-import component-from-global-scope="CyberSkillDS.PromptInput" placeholder="{{ promptPh }}" send-label="{{ promptSend }}" hint-size="100%,120px"></x-import>
44
+ <x-import component-from-global-scope="CyberSkillDS.PromptInput" placeholder="{{ promptPh }}" send-label="{{ promptSend }}" lang="{{ langAttr }}" hint-size="100%,120px"></x-import>
42
45
  </div>
43
46
  </div>
44
47
  </section>
@@ -66,7 +69,7 @@
66
69
  </section>
67
70
 
68
71
  <section id="process" style="padding:0 32px 80px">
69
- <div style="max-width:1080px;margin:0 auto;display:flex;align-items:center;justify-content:space-between;gap:28px;flex-wrap:wrap;background:linear-gradient(120deg,var(--cs-accent-strong) 35%,color-mix(in oklab,var(--cs-accent-grad-b) 26%,var(--cs-accent-strong)));color:#fff;border-radius:var(--cs-radius-lg);padding:40px 36px">
72
+ <div style="max-width:1080px;margin:0 auto;display:flex;align-items:center;justify-content:space-between;gap:28px;flex-wrap:wrap;background:linear-gradient(120deg,var(--cs-accent-strong) 35%,color-mix(in oklab,var(--cs-accent-grad-b) 26%,var(--cs-accent-strong)));color:var(--cs-accent-on-strong);border-radius:var(--cs-radius-lg);padding:40px 36px">
70
73
  <div>
71
74
  <h2 style="color:var(--cs-accent-bright);font-size:28px;font-weight:800;margin:0 0 6px;letter-spacing:-0.01em">{{ ctaH }}</h2>
72
75
  <p style="margin:0;opacity:0.9;max-width:520px">{{ ctaP }}</p>
@@ -77,9 +80,9 @@
77
80
  </div>
78
81
  </section>
79
82
 
80
- <footer style="background:var(--cs-accent-strong);color:rgba(255,255,255,0.82);padding:40px 32px">
83
+ <footer style="background:var(--cs-color-brand-umber);color:#FFFDF8;padding:40px 32px">
81
84
  <div style="max-width:1080px;margin:0 auto;display:flex;justify-content:space-between;gap:24px;flex-wrap:wrap;align-items:center">
82
- <div style="display:flex;align-items:center;gap:10px;color:#fff;font-weight:800">
85
+ <div style="display:flex;align-items:center;gap:10px;color:#FFFDF8;font-weight:800">
83
86
  <x-import component-from-global-scope="CyberSkillDS.Logo" size="28" decorative="{{ true }}" hint-size="28px,28px"></x-import>
84
87
  CyberSkill
85
88
  </div>
@@ -88,13 +91,13 @@
88
91
  </footer>
89
92
 
90
93
  <sc-if value="{{ showLauncher }}" hint-placeholder-val="{{ true }}">
91
- <button onClick="{{ openChat }}" style="position:fixed;right:22px;bottom:22px;z-index:200;background:var(--cs-accent-strong);color:var(--cs-accent-on);border:0;border-radius:var(--cs-radius-full);height:54px;padding:0 22px;font-family:var(--cs-font-family-ui);font-weight:700;font-size:15px;cursor:pointer;box-shadow:var(--cs-shadow-lg)">✦ {{ talkBtn }}</button>
94
+ <button onClick="{{ openChat }}" style="position:fixed;right:22px;bottom:22px;z-index:200;background:var(--cs-accent-strong);color:var(--cs-accent-on-strong);border:0;border-radius:var(--cs-radius-full);height:54px;padding:0 22px;font-family:var(--cs-font-family-ui);font-weight:700;font-size:15px;cursor:pointer;box-shadow:var(--cs-shadow-lg)">✦ {{ talkBtn }}</button>
92
95
  </sc-if>
93
96
 
94
97
  <sc-if value="{{ chatOpen }}">
95
98
  <div style="position:fixed;right:22px;bottom:22px;z-index:201;width:360px;max-width:calc(100vw - 44px);border-radius:var(--cs-radius-lg);overflow:hidden;box-shadow:var(--cs-shadow-xl);display:flex;flex-direction:column;max-height:min(560px,84vh)">
96
- <div style="background:var(--cs-accent-strong);color:#fff;padding:14px 16px;display:flex;align-items:center;gap:10px">
97
- <span style="width:30px;height:30px;border-radius:50%;background:var(--cs-accent-strong);color:var(--cs-accent-on);display:grid;place-items:center;font-weight:800">✦</span>
99
+ <div style="background:var(--cs-accent-strong);color:var(--cs-accent-on-strong);padding:14px 16px;display:flex;align-items:center;gap:10px">
100
+ <span style="width:30px;height:30px;border-radius:50%;background:var(--cs-accent-strong);color:var(--cs-accent-on-strong);display:grid;place-items:center;font-weight:800">✦</span>
98
101
  <b style="font-size:14px">Lumi · {{ genieLabel }}</b>
99
102
  <button onClick="{{ closeChat }}" aria-label="Close" style="margin-left:auto;background:transparent;border:0;color:rgba(255,255,255,0.8);cursor:pointer;font-size:18px">✕</button>
100
103
  </div>
@@ -102,10 +105,11 @@
102
105
  <x-import component-from-global-scope="CyberSkillDS.ChatMessage" role="lumi" hint-size="100%,60px">{{ chatHello }}</x-import>
103
106
  </div>
104
107
  <div style="background:var(--cs-color-surface-panel);padding:0 12px 12px">
105
- <x-import component-from-global-scope="CyberSkillDS.PromptInput" placeholder="{{ chatPh }}" send-label="{{ chatSend }}" hint-size="100%,110px"></x-import>
108
+ <x-import component-from-global-scope="CyberSkillDS.PromptInput" placeholder="{{ chatPh }}" send-label="{{ chatSend }}" lang="{{ langAttr }}" hint-size="100%,110px"></x-import>
106
109
  </div>
107
110
  </div>
108
111
  </sc-if>
112
+ </main>
109
113
  </div>
110
114
  </x-dc>
111
115
  <script type="text/x-dc" data-dc-script data-props="{
@@ -120,10 +124,11 @@ class Component extends DCLogic {
120
124
  const EL = {"Thổ · studio":["tho",""],"Thổ · clay":["tho","clay"],"Thổ · sand":["tho","sand"],"Hỏa · ember":["hoa",""],"Hỏa · lava":["hoa","lava"],"Hỏa · plasma":["hoa","plasma"],"Thủy · river":["thuy",""],"Thủy · ocean":["thuy","ocean"],"Thủy · mist":["thuy","mist"],"Mộc · leaf":["moc",""],"Mộc · bamboo":["moc","bamboo"],"Mộc · forest":["moc","forest"],"Kim · champagne":["kim",""],"Kim · steel":["kim","steel"],"Kim · titanium":["kim","titanium"]};
121
125
  const [elAttr, vaAttr] = EL[this.props.element] || EL["Thổ · studio"];
122
126
  const vn = this.props.language === "Tiếng Việt";
123
- const en = { navServices:"Services", navProcess:"Process", navContact:"Contact", talkBtn:"Talk to Lumi", heroKicker:"A Saigon studio · since 2020", heroH:"Turn Your Will Into Real", heroSub:"Hiện Thực Hoá Ý Chí", heroP:"Tell us a wish in a sentence. Lumi shares plain advice, then hands it to a real team who build software your people actually run — built to ship, built to last.", promptPh:"Make a wish… a faster checkout, an app, a tool", promptSend:"Make a wish", svcKicker:"Services", svcH:"What we build", svcP:"Three focused practices. One team that answers for the result.", c1h:"Web & mobile apps", c1p:"Product apps your customers reach for — fast, accessible, bilingual by default.", c2h:"Internal systems & automation", c2p:"The tools your team runs on: dashboards, workflows, and the automation behind them.", c3h:"Built to last", c3p:"Shipped software that keeps running — tested, documented, handed over cleanly.", ctaH:"Ready to make a wish?", ctaP:"Send a short note. We reply within one business day.", chatHello:"Hello, I’m Lumi. Tell me a wish, and I’ll share plain advice before asking for anything.", chatPh:"Type your wish…", chatSend:"Send", footer:"© 2026 CyberSkill · Saigon · Turn Your Will Into Real", genieLabel:"golden genie" };
124
- const vi = { navServices:"Dịch vụ", navProcess:"Quy trình", navContact:"Liên hệ", talkBtn:"Trò chuyện với Lumi", heroKicker:"Studio Sài Gòn · từ 2020", heroH:"Hiện Thực Hoá Ý Chí", heroSub:"Turn Your Will Into Real", heroP:"Kể cho chúng tôi một điều ước trong một câu. Lumi chia sẻ lời khuyên thẳng thắn, rồi trao cho một đội ngũ thật xây phần mềm mà người của bạn thực sự vận hành — làm để chạy được, làm để bền lâu.", promptPh:"Gửi điều ước… thanh toán nhanh hơn, một app, một công cụ", promptSend:"Gửi điều ước", svcKicker:"Dịch vụ", svcH:"Chúng tôi xây gì", svcP:"Ba mảng tập trung. Một đội ngũ chịu trách nhiệm về kết quả.", c1h:"Ứng dụng web & di động", c1p:"Sản phẩm khách hàng muốn dùng — nhanh, dễ tiếp cận, song ngữ mặc định.", c2h:"Hệ thống nội bộ & tự động hoá", c2p:"Công cụ đội bạn vận hành: dashboard, luồng công việc, và tự động hoá phía sau.", c3h:"Làm để bền lâu", c3p:"Phần mềm đã ra mắt vẫn chạy đều — kiểm thử, tài liệu, bàn giao gọn gàng.", ctaH:"Sẵn sàng gửi điều ước?", ctaP:"Gửi một ghi chú ngắn. Chúng tôi phản hồi trong một ngày làm việc.", chatHello:"Xin chào, tôi là Lumi. Kể cho tôi một điều ước, tôi sẽ chia sẻ lời khuyên thẳng thắn trước khi hỏi bất cứ điều gì.", chatPh:"Nhập điều ước của bạn…", chatSend:"Gửi", footer:"© 2026 CyberSkill · Sài Gòn · Hiện Thực Hoá Ý Chí", genieLabel:"thần đèn vàng" };
127
+ const en = { skipLabel:"Skip to content", navServices:"Services", navProcess:"Process", navContact:"Contact", talkBtn:"Talk to Lumi", heroKicker:"A Saigon studio · since 2020", heroH:"Turn Your Will Into Real", heroSub:"Hiện Thực Hoá Ý Chí", heroP:"Tell us a wish in a sentence. Lumi shares plain advice, then hands it to a real team who build software your people actually run — built to ship, built to last.", promptPh:"Make a wish… a faster checkout, an app, a tool", promptSend:"Make a wish", svcKicker:"Services", svcH:"What we build", svcP:"Three focused practices. One team that answers for the result.", c1h:"Web & mobile apps", c1p:"Product apps your customers reach for — fast, accessible, bilingual by default.", c2h:"Internal systems & automation", c2p:"The tools your team runs on: dashboards, workflows, and the automation behind them.", c3h:"Built to last", c3p:"Shipped software that keeps running — tested, documented, handed over cleanly.", ctaH:"Ready to make a wish?", ctaP:"Send a short note. We reply within one business day.", chatHello:"Hello, I’m Lumi. Tell me a wish, and I’ll share plain advice before asking for anything.", chatPh:"Type your wish…", chatSend:"Send", footer:"© 2026 CyberSkill · Saigon · Turn Your Will Into Real", genieLabel:"golden genie" };
128
+ const vi = { skipLabel:"Bỏ qua nội dung", navServices:"Dịch vụ", navProcess:"Quy trình", navContact:"Liên hệ", talkBtn:"Trò chuyện với Lumi", heroKicker:"Studio Sài Gòn · từ 2020", heroH:"Hiện Thực Hoá Ý Chí", heroSub:"Turn Your Will Into Real", heroP:"Kể cho chúng tôi một điều ước trong một câu. Lumi chia sẻ lời khuyên thẳng thắn, rồi trao cho một đội ngũ thật xây phần mềm mà người của bạn thực sự vận hành — làm để chạy được, làm để bền lâu.", promptPh:"Gửi điều ước… thanh toán nhanh hơn, một app, một công cụ", promptSend:"Gửi điều ước", svcKicker:"Dịch vụ", svcH:"Chúng tôi xây gì", svcP:"Ba mảng tập trung. Một đội ngũ chịu trách nhiệm về kết quả.", c1h:"Ứng dụng web & di động", c1p:"Sản phẩm khách hàng muốn dùng — nhanh, dễ tiếp cận, song ngữ mặc định.", c2h:"Hệ thống nội bộ & tự động hoá", c2p:"Công cụ đội bạn vận hành: dashboard, luồng công việc, và tự động hoá phía sau.", c3h:"Làm để bền lâu", c3p:"Phần mềm đã ra mắt vẫn chạy đều — kiểm thử, tài liệu, bàn giao gọn gàng.", ctaH:"Sẵn sàng gửi điều ước?", ctaP:"Gửi một ghi chú ngắn. Chúng tôi phản hồi trong một ngày làm việc.", chatHello:"Xin chào, tôi là Lumi. Kể cho tôi một điều ước, tôi sẽ chia sẻ lời khuyên thẳng thắn trước khi hỏi bất cứ điều gì.", chatPh:"Nhập điều ước của bạn…", chatSend:"Gửi", footer:"© 2026 CyberSkill · Sài Gòn · Hiện Thực Hoá Ý Chí", genieLabel:"thần đèn vàng" };
125
129
  return Object.assign({ langAttr: (this.props.language ?? "English") === "Tiếng Việt" ? "vi" : "en", elAttr, vaAttr, rootTheme: this.props.theme === "dark" ? "dark" : "",
126
- showLauncher: (this.props.showChat ?? true) && !this.state.chatOpen, chatOpen: this.state.chatOpen,
130
+ /* FAB omitted — header Talk to Lumi is the single secondary CTA (UX-016). */
131
+ showLauncher: false, chatOpen: this.state.chatOpen,
127
132
  openChat: () => this.setState({ chatOpen: true }), closeChat: () => this.setState({ chatOpen: false })}, vn ? vi : en);
128
133
  }
129
134
  }
@@ -2,6 +2,7 @@
2
2
  "$schemaVersion": "2.0",
3
3
  "template": "marketing-page",
4
4
  "slots": [
5
+ { "id": "skipLabel", "type": "text", "label": "Skip-to-content link label", "maxLength": 40, "required": true },
5
6
  { "id": "heroKicker", "type": "text", "label": "Hero eyebrow", "maxLength": 40, "i18n": {"en": "Eyebrow above the headline", "vi": "Nhãn nhỏ phía trên tiêu đề"} },
6
7
  { "id": "heroH", "type": "text", "label": "Hero headline", "maxLength": 70, "required": true },
7
8
  { "id": "heroSub", "type": "text", "label": "Hero subhead", "maxLength": 90 },
@@ -1,9 +1,10 @@
1
1
  // Loads this design system into the template. In a consuming project, point
2
2
  // base at the bound DS folder relative to this file (e.g. '_ds/<folder>' at
3
3
  // the project root, '../_ds/<folder>' one level down) — one line to edit.
4
+ // Artifact head standard (UX-002 / B1): ensure <html lang> + <title> from @template.
4
5
  (() => {
5
6
  const base = '../..';
6
- for (const p of ['styles.css']) {
7
+ for (const p of ['dist/styles.min.css']) {
7
8
  const l = document.createElement('link');
8
9
  l.rel = 'stylesheet'; l.href = base + '/' + p;
9
10
  document.head.appendChild(l);
@@ -20,4 +21,35 @@
20
21
  };
21
22
  s.onerror = () => console.error('ds-base.js: failed to load ' + s.src + ' — if this is a consuming project, point the base line in ds-base.js at the bound _ds/<folder> tree relative to this page (e.g. _ds/<folder> at the project root, ../_ds/<folder> one level down); in a fresh design system this can just mean the bundle is not compiled yet');
22
23
  document.head.appendChild(s);
24
+
25
+ const syncLang = () => {
26
+ try {
27
+ const a = document.querySelector('[lang]');
28
+ const v = a && a.getAttribute('lang');
29
+ // Ignore unresolved DC holes like {{ langAttr }}
30
+ if (v && v.indexOf('{{') === -1) document.documentElement.setAttribute('lang', v);
31
+ else if (!document.documentElement.getAttribute('lang')) document.documentElement.setAttribute('lang', 'en');
32
+ } catch (e) { /* authoring host may sandbox */ }
33
+ };
34
+ const ensureHead = () => {
35
+ try {
36
+ if (!document.title || !document.title.trim()) {
37
+ const src = document.documentElement.innerHTML;
38
+ const m = src.match(/@template\s+name="([^"]+)"/);
39
+ if (m) document.title = m[1] + ' · CyberSkill';
40
+ }
41
+ syncLang();
42
+ const obs = new MutationObserver(syncLang);
43
+ obs.observe(document.body || document.documentElement, {
44
+ attributes: true,
45
+ attributeFilter: ['lang'],
46
+ subtree: true,
47
+ });
48
+ } catch (e) { /* authoring host may sandbox */ }
49
+ };
50
+ if (document.readyState === 'loading') {
51
+ document.addEventListener('DOMContentLoaded', ensureHead);
52
+ } else {
53
+ ensureHead();
54
+ }
23
55
  })();
@@ -1070,16 +1070,15 @@
1070
1070
  }
1071
1071
 
1072
1072
  // src/cdn.ts
1073
- var REACT_URL = "https://unpkg.com/umd-react@19.2.8/dist/react.production.min.js";
1074
- var REACT_SRI = "sha384-/nh8CKeV7Pk42Gpda6L4DM1JtZ2bwPOi+eh9O7+a1Y22UkGs8+mw3aW1shQ9FV30";
1075
- var REACT_DOM_URL = "https://unpkg.com/umd-react@19.2.8/dist/react-dom.production.min.js";
1076
- var REACT_DOM_SRI = "sha384-rhLCB72qrpcezgY2QW0panvW9IeO32m94nvuDVRD/iEGHXoUbjtijL6Xi/Z5/mzu";
1077
- var BABEL_URL = "https://unpkg.com/@babel/standalone@7.29.0/babel.min.js";
1078
- var BABEL_SRI = "sha384-m08KidiNqLdpJqLq95G/LEi8Qvjl/xUYll3QILypMoQ65QorJ9Lvtp2RXYGBFj1y";
1079
- function cdnScriptFor(url, sri) {
1073
+ var REACT_LOCAL = "../../_vendor/react/react.production.min.js";
1074
+ var REACT_DOM_LOCAL = "../../_vendor/react/react-dom.production.min.js";
1075
+ var BABEL_LOCAL = "../../_vendor/babel/babel.min.js";
1076
+ // Product surfaces are offline-first (UX-026 / D4): no third-party script origins.
1077
+ // Host editors may still remap via window.__resources[localPath].
1078
+ function localScriptFor(path) {
1080
1079
  const res = window.__resources;
1081
- const v = res ? res[url] : void 0;
1082
- return typeof v === "string" && v ? { src: v } : { src: url, integrity: sri };
1080
+ const v = res ? res[path] : void 0;
1081
+ return typeof v === "string" && v ? v : path;
1083
1082
  }
1084
1083
 
1085
1084
  // src/external.ts
@@ -1106,16 +1105,12 @@
1106
1105
  function ensureBabel() {
1107
1106
  if (window.Babel) return Promise.resolve();
1108
1107
  if (babelLoading) return babelLoading;
1109
- const babel = cdnScriptFor(BABEL_URL, BABEL_SRI);
1108
+ const src = localScriptFor(BABEL_LOCAL);
1110
1109
  babelLoading = new Promise((res, rej) => {
1111
1110
  const s = document.createElement("script");
1112
- s.src = babel.src;
1113
- if (babel.integrity) {
1114
- s.integrity = babel.integrity;
1115
- s.crossOrigin = "anonymous";
1116
- }
1111
+ s.src = src;
1117
1112
  s.onload = () => res();
1118
- s.onerror = rej;
1113
+ s.onerror = () => rej(new Error("failed to load local Babel: " + src));
1119
1114
  document.head.appendChild(s);
1120
1115
  });
1121
1116
  return babelLoading;
@@ -1768,11 +1763,9 @@
1768
1763
  function loadReactUmd() {
1769
1764
  const w = window;
1770
1765
  if (w.React && w.ReactDOM) return Promise.resolve();
1771
- const react = cdnScriptFor(REACT_URL, REACT_SRI);
1772
- const reactDom = cdnScriptFor(REACT_DOM_URL, REACT_DOM_SRI);
1773
1766
  return Promise.all([
1774
- loadScript(react.src, react.integrity),
1775
- loadScript(reactDom.src, reactDom.integrity)
1767
+ loadScript(localScriptFor(REACT_LOCAL)),
1768
+ loadScript(localScriptFor(REACT_DOM_LOCAL))
1776
1769
  ]).then(() => void 0);
1777
1770
  }
1778
1771
  function init() {
@@ -1,6 +1,7 @@
1
1
  <!DOCTYPE html>
2
- <html>
2
+ <html lang="en">
3
3
  <head>
4
+ <title>Marketing · Press release · CyberSkill</title>
4
5
  <meta charset="utf-8">
5
6
  <meta name="viewport" content="width=device-width, initial-scale=1">
6
7
  <meta name="omelette-owns-print" content="1">
@@ -1,9 +1,10 @@
1
1
  // Loads this design system into the template. In a consuming project, point
2
2
  // base at the bound DS folder relative to this file (e.g. '_ds/<folder>' at
3
3
  // the project root, '../_ds/<folder>' one level down) — one line to edit.
4
+ // Artifact head standard (UX-002 / B1): ensure <html lang> + <title> from @template.
4
5
  (() => {
5
6
  const base = '../..';
6
- for (const p of ['styles.css']) {
7
+ for (const p of ['dist/styles.min.css']) {
7
8
  const l = document.createElement('link');
8
9
  l.rel = 'stylesheet'; l.href = base + '/' + p;
9
10
  document.head.appendChild(l);
@@ -20,4 +21,35 @@
20
21
  };
21
22
  s.onerror = () => console.error('ds-base.js: failed to load ' + s.src + ' — if this is a consuming project, point the base line in ds-base.js at the bound _ds/<folder> tree relative to this page (e.g. _ds/<folder> at the project root, ../_ds/<folder> one level down); in a fresh design system this can just mean the bundle is not compiled yet');
22
23
  document.head.appendChild(s);
24
+
25
+ const syncLang = () => {
26
+ try {
27
+ const a = document.querySelector('[lang]');
28
+ const v = a && a.getAttribute('lang');
29
+ // Ignore unresolved DC holes like {{ langAttr }}
30
+ if (v && v.indexOf('{{') === -1) document.documentElement.setAttribute('lang', v);
31
+ else if (!document.documentElement.getAttribute('lang')) document.documentElement.setAttribute('lang', 'en');
32
+ } catch (e) { /* authoring host may sandbox */ }
33
+ };
34
+ const ensureHead = () => {
35
+ try {
36
+ if (!document.title || !document.title.trim()) {
37
+ const src = document.documentElement.innerHTML;
38
+ const m = src.match(/@template\s+name="([^"]+)"/);
39
+ if (m) document.title = m[1] + ' · CyberSkill';
40
+ }
41
+ syncLang();
42
+ const obs = new MutationObserver(syncLang);
43
+ obs.observe(document.body || document.documentElement, {
44
+ attributes: true,
45
+ attributeFilter: ['lang'],
46
+ subtree: true,
47
+ });
48
+ } catch (e) { /* authoring host may sandbox */ }
49
+ };
50
+ if (document.readyState === 'loading') {
51
+ document.addEventListener('DOMContentLoaded', ensureHead);
52
+ } else {
53
+ ensureHead();
54
+ }
23
55
  })();
@@ -1070,16 +1070,15 @@
1070
1070
  }
1071
1071
 
1072
1072
  // src/cdn.ts
1073
- var REACT_URL = "https://unpkg.com/umd-react@19.2.8/dist/react.production.min.js";
1074
- var REACT_SRI = "sha384-/nh8CKeV7Pk42Gpda6L4DM1JtZ2bwPOi+eh9O7+a1Y22UkGs8+mw3aW1shQ9FV30";
1075
- var REACT_DOM_URL = "https://unpkg.com/umd-react@19.2.8/dist/react-dom.production.min.js";
1076
- var REACT_DOM_SRI = "sha384-rhLCB72qrpcezgY2QW0panvW9IeO32m94nvuDVRD/iEGHXoUbjtijL6Xi/Z5/mzu";
1077
- var BABEL_URL = "https://unpkg.com/@babel/standalone@7.29.0/babel.min.js";
1078
- var BABEL_SRI = "sha384-m08KidiNqLdpJqLq95G/LEi8Qvjl/xUYll3QILypMoQ65QorJ9Lvtp2RXYGBFj1y";
1079
- function cdnScriptFor(url, sri) {
1073
+ var REACT_LOCAL = "../../_vendor/react/react.production.min.js";
1074
+ var REACT_DOM_LOCAL = "../../_vendor/react/react-dom.production.min.js";
1075
+ var BABEL_LOCAL = "../../_vendor/babel/babel.min.js";
1076
+ // Product surfaces are offline-first (UX-026 / D4): no third-party script origins.
1077
+ // Host editors may still remap via window.__resources[localPath].
1078
+ function localScriptFor(path) {
1080
1079
  const res = window.__resources;
1081
- const v = res ? res[url] : void 0;
1082
- return typeof v === "string" && v ? { src: v } : { src: url, integrity: sri };
1080
+ const v = res ? res[path] : void 0;
1081
+ return typeof v === "string" && v ? v : path;
1083
1082
  }
1084
1083
 
1085
1084
  // src/external.ts
@@ -1106,16 +1105,12 @@
1106
1105
  function ensureBabel() {
1107
1106
  if (window.Babel) return Promise.resolve();
1108
1107
  if (babelLoading) return babelLoading;
1109
- const babel = cdnScriptFor(BABEL_URL, BABEL_SRI);
1108
+ const src = localScriptFor(BABEL_LOCAL);
1110
1109
  babelLoading = new Promise((res, rej) => {
1111
1110
  const s = document.createElement("script");
1112
- s.src = babel.src;
1113
- if (babel.integrity) {
1114
- s.integrity = babel.integrity;
1115
- s.crossOrigin = "anonymous";
1116
- }
1111
+ s.src = src;
1117
1112
  s.onload = () => res();
1118
- s.onerror = rej;
1113
+ s.onerror = () => rej(new Error("failed to load local Babel: " + src));
1119
1114
  document.head.appendChild(s);
1120
1115
  });
1121
1116
  return babelLoading;
@@ -1768,11 +1763,9 @@
1768
1763
  function loadReactUmd() {
1769
1764
  const w = window;
1770
1765
  if (w.React && w.ReactDOM) return Promise.resolve();
1771
- const react = cdnScriptFor(REACT_URL, REACT_SRI);
1772
- const reactDom = cdnScriptFor(REACT_DOM_URL, REACT_DOM_SRI);
1773
1766
  return Promise.all([
1774
- loadScript(react.src, react.integrity),
1775
- loadScript(reactDom.src, reactDom.integrity)
1767
+ loadScript(localScriptFor(REACT_LOCAL)),
1768
+ loadScript(localScriptFor(REACT_DOM_LOCAL))
1776
1769
  ]).then(() => void 0);
1777
1770
  }
1778
1771
  function init() {
@@ -1,6 +1,7 @@
1
1
  <!DOCTYPE html>
2
- <html>
2
+ <html lang="en">
3
3
  <head>
4
+ <title>Marketing · Social post kit · CyberSkill</title>
4
5
  <meta charset="utf-8">
5
6
  <meta name="viewport" content="width=device-width, initial-scale=1">
6
7
  <script src="./support.js"></script>
@@ -14,7 +15,7 @@
14
15
  </helmet>
15
16
  <div lang="{{ langAttr }}" data-cs-element="{{ elAttr }}" data-cs-variant="{{ vaAttr }}" class="cs-canvas-desk" style="background:#2a1a0d;padding:28px;font-family:var(--cs-font-family-ui);display:grid;gap:28px;justify-items:center">
16
17
 
17
- <div id="square" style="width:1080px;height:1080px;position:relative;overflow:hidden;background:var(--cs-accent-strong);color:#fff;display:flex;flex-direction:column;justify-content:center;padding:0 96px;box-sizing:border-box;box-shadow:var(--cs-shadow-xl)">
18
+ <div id="square" style="width:1080px;height:1080px;position:relative;overflow:hidden;background:var(--cs-color-brand-umber);color:#FFFDF8;display:flex;flex-direction:column;justify-content:center;padding:0 96px;box-sizing:border-box;box-shadow:var(--cs-shadow-xl)">
18
19
  <image-slot id="cs-social-square" shape="rect" placeholder="Drop a brand image" style="position:absolute;inset:0"></image-slot>
19
20
  <div class="cs-aurora-wash" style="position:absolute;inset:0;opacity:0.55;pointer-events:none"></div>
20
21
  <div style="position:absolute;inset:0;pointer-events:none;background:linear-gradient(180deg,rgba(42,26,13,0.58),rgba(42,26,13,0.44))"></div>
@@ -28,7 +29,7 @@
28
29
  <div style="position:relative;margin-top:52px"><span style="display:inline-block;background:var(--cs-accent-bright);color:var(--cs-accent-on);font-weight:700;font-size:26px;padding:20px 40px;border-radius:var(--cs-radius-full)">cyberskill.world</span></div>
29
30
  </div>
30
31
 
31
- <div id="linkcard" style="width:1200px;height:630px;position:relative;overflow:hidden;background:var(--cs-accent-strong);color:#fff;display:flex;align-items:center;box-sizing:border-box;box-shadow:var(--cs-shadow-xl)">
32
+ <div id="linkcard" style="width:1200px;height:630px;position:relative;overflow:hidden;background:var(--cs-color-brand-umber);color:#FFFDF8;display:flex;align-items:center;box-sizing:border-box;box-shadow:var(--cs-shadow-xl)">
32
33
  <image-slot id="cs-social-link" shape="rect" placeholder="Drop a brand image" style="position:absolute;inset:0"></image-slot>
33
34
  <div class="cs-aurora-wash" style="position:absolute;inset:0;opacity:0.5;pointer-events:none"></div>
34
35
  <div style="position:absolute;inset:0;pointer-events:none;background:linear-gradient(90deg,rgba(42,26,13,0.72),rgba(42,26,13,0.4))"></div>
@@ -42,7 +43,7 @@
42
43
  </div>
43
44
  </div>
44
45
 
45
- <div id="story" style="width:1080px;height:1920px;position:relative;overflow:hidden;background:var(--cs-accent-strong);color:#fff;display:flex;flex-direction:column;justify-content:center;padding:0 100px;box-sizing:border-box;box-shadow:var(--cs-shadow-xl)">
46
+ <div id="story" style="width:1080px;height:1920px;position:relative;overflow:hidden;background:var(--cs-color-brand-umber);color:#FFFDF8;display:flex;flex-direction:column;justify-content:center;padding:0 100px;box-sizing:border-box;box-shadow:var(--cs-shadow-xl)">
46
47
  <image-slot id="cs-social-story" shape="rect" placeholder="Drop a brand image" style="position:absolute;inset:0"></image-slot>
47
48
  <div class="cs-aurora-wash" style="position:absolute;inset:0;opacity:0.55;pointer-events:none"></div>
48
49
  <div style="position:absolute;inset:0;pointer-events:none;background:linear-gradient(180deg,rgba(42,26,13,0.58),rgba(42,26,13,0.46))"></div>
@@ -1,9 +1,10 @@
1
1
  // Loads this design system into the template. In a consuming project, point
2
2
  // base at the bound DS folder relative to this file (e.g. '_ds/<folder>' at
3
3
  // the project root, '../_ds/<folder>' one level down) — one line to edit.
4
+ // Artifact head standard (UX-002 / B1): ensure <html lang> + <title> from @template.
4
5
  (() => {
5
6
  const base = '../..';
6
- for (const p of ['styles.css']) {
7
+ for (const p of ['dist/styles.min.css']) {
7
8
  const l = document.createElement('link');
8
9
  l.rel = 'stylesheet'; l.href = base + '/' + p;
9
10
  document.head.appendChild(l);
@@ -20,4 +21,35 @@
20
21
  };
21
22
  s.onerror = () => console.error('ds-base.js: failed to load ' + s.src + ' — if this is a consuming project, point the base line in ds-base.js at the bound _ds/<folder> tree relative to this page (e.g. _ds/<folder> at the project root, ../_ds/<folder> one level down); in a fresh design system this can just mean the bundle is not compiled yet');
22
23
  document.head.appendChild(s);
24
+
25
+ const syncLang = () => {
26
+ try {
27
+ const a = document.querySelector('[lang]');
28
+ const v = a && a.getAttribute('lang');
29
+ // Ignore unresolved DC holes like {{ langAttr }}
30
+ if (v && v.indexOf('{{') === -1) document.documentElement.setAttribute('lang', v);
31
+ else if (!document.documentElement.getAttribute('lang')) document.documentElement.setAttribute('lang', 'en');
32
+ } catch (e) { /* authoring host may sandbox */ }
33
+ };
34
+ const ensureHead = () => {
35
+ try {
36
+ if (!document.title || !document.title.trim()) {
37
+ const src = document.documentElement.innerHTML;
38
+ const m = src.match(/@template\s+name="([^"]+)"/);
39
+ if (m) document.title = m[1] + ' · CyberSkill';
40
+ }
41
+ syncLang();
42
+ const obs = new MutationObserver(syncLang);
43
+ obs.observe(document.body || document.documentElement, {
44
+ attributes: true,
45
+ attributeFilter: ['lang'],
46
+ subtree: true,
47
+ });
48
+ } catch (e) { /* authoring host may sandbox */ }
49
+ };
50
+ if (document.readyState === 'loading') {
51
+ document.addEventListener('DOMContentLoaded', ensureHead);
52
+ } else {
53
+ ensureHead();
54
+ }
23
55
  })();
@@ -1070,16 +1070,15 @@
1070
1070
  }
1071
1071
 
1072
1072
  // src/cdn.ts
1073
- var REACT_URL = "https://unpkg.com/umd-react@19.2.8/dist/react.production.min.js";
1074
- var REACT_SRI = "sha384-/nh8CKeV7Pk42Gpda6L4DM1JtZ2bwPOi+eh9O7+a1Y22UkGs8+mw3aW1shQ9FV30";
1075
- var REACT_DOM_URL = "https://unpkg.com/umd-react@19.2.8/dist/react-dom.production.min.js";
1076
- var REACT_DOM_SRI = "sha384-rhLCB72qrpcezgY2QW0panvW9IeO32m94nvuDVRD/iEGHXoUbjtijL6Xi/Z5/mzu";
1077
- var BABEL_URL = "https://unpkg.com/@babel/standalone@7.29.0/babel.min.js";
1078
- var BABEL_SRI = "sha384-m08KidiNqLdpJqLq95G/LEi8Qvjl/xUYll3QILypMoQ65QorJ9Lvtp2RXYGBFj1y";
1079
- function cdnScriptFor(url, sri) {
1073
+ var REACT_LOCAL = "../../_vendor/react/react.production.min.js";
1074
+ var REACT_DOM_LOCAL = "../../_vendor/react/react-dom.production.min.js";
1075
+ var BABEL_LOCAL = "../../_vendor/babel/babel.min.js";
1076
+ // Product surfaces are offline-first (UX-026 / D4): no third-party script origins.
1077
+ // Host editors may still remap via window.__resources[localPath].
1078
+ function localScriptFor(path) {
1080
1079
  const res = window.__resources;
1081
- const v = res ? res[url] : void 0;
1082
- return typeof v === "string" && v ? { src: v } : { src: url, integrity: sri };
1080
+ const v = res ? res[path] : void 0;
1081
+ return typeof v === "string" && v ? v : path;
1083
1082
  }
1084
1083
 
1085
1084
  // src/external.ts
@@ -1106,16 +1105,12 @@
1106
1105
  function ensureBabel() {
1107
1106
  if (window.Babel) return Promise.resolve();
1108
1107
  if (babelLoading) return babelLoading;
1109
- const babel = cdnScriptFor(BABEL_URL, BABEL_SRI);
1108
+ const src = localScriptFor(BABEL_LOCAL);
1110
1109
  babelLoading = new Promise((res, rej) => {
1111
1110
  const s = document.createElement("script");
1112
- s.src = babel.src;
1113
- if (babel.integrity) {
1114
- s.integrity = babel.integrity;
1115
- s.crossOrigin = "anonymous";
1116
- }
1111
+ s.src = src;
1117
1112
  s.onload = () => res();
1118
- s.onerror = rej;
1113
+ s.onerror = () => rej(new Error("failed to load local Babel: " + src));
1119
1114
  document.head.appendChild(s);
1120
1115
  });
1121
1116
  return babelLoading;
@@ -1768,11 +1763,9 @@
1768
1763
  function loadReactUmd() {
1769
1764
  const w = window;
1770
1765
  if (w.React && w.ReactDOM) return Promise.resolve();
1771
- const react = cdnScriptFor(REACT_URL, REACT_SRI);
1772
- const reactDom = cdnScriptFor(REACT_DOM_URL, REACT_DOM_SRI);
1773
1766
  return Promise.all([
1774
- loadScript(react.src, react.integrity),
1775
- loadScript(reactDom.src, reactDom.integrity)
1767
+ loadScript(localScriptFor(REACT_LOCAL)),
1768
+ loadScript(localScriptFor(REACT_DOM_LOCAL))
1776
1769
  ]).then(() => void 0);
1777
1770
  }
1778
1771
  function init() {
@@ -1,6 +1,7 @@
1
1
  <!DOCTYPE html>
2
- <html>
2
+ <html lang="en">
3
3
  <head>
4
+ <title>Sales · One-pager · CyberSkill</title>
4
5
  <meta charset="utf-8">
5
6
  <meta name="viewport" content="width=device-width, initial-scale=1">
6
7
  <meta name="omelette-owns-print" content="1">
@@ -15,7 +16,7 @@
15
16
  </helmet>
16
17
  <div lang="{{ langAttr }}" data-cs-element="{{ elAttr }}" data-cs-variant="{{ vaAttr }}" class="cs-desk" style="background:#efe6d8;min-height:100vh;padding:40px 16px;font-family:var(--cs-font-family-ui);color:var(--cs-color-text-primary)">
17
18
  <div class="cs-sheet" style="max-width:816px;margin:0 auto;background:#fff;border:1px solid var(--cs-color-border-default);border-radius:12px;box-shadow:var(--cs-shadow-md);overflow:hidden">
18
- <div style="background:var(--cs-accent-strong);color:#fff;padding:44px 56px 40px;position:relative;overflow:hidden">
19
+ <div style="background:var(--cs-color-brand-umber);color:#FFFDF8;padding:44px 56px 40px;position:relative;overflow:hidden">
19
20
  <div style="position:absolute;inset:0;background:radial-gradient(120% 90% at 88% -10%, color-mix(in srgb, var(--cs-accent-glow) 56%, transparent), transparent 60%);pointer-events:none"></div>
20
21
  <div style="position:relative;display:flex;align-items:center;gap:12px;margin-bottom:26px">
21
22
  <x-import component-from-global-scope="CyberSkillDS.Logo" size="40" hint-size="40px,40px"></x-import>
@@ -66,8 +67,8 @@
66
67
  </div></sc-if>
67
68
  </div>
68
69
  </div>
69
- <div class="cs-avoid" style="display:flex;align-items:center;justify-content:space-between;gap:20px;background:var(--cs-accent-strong);color:#fff;padding:22px 56px;margin-top:6px">
70
- <div><div style="font-size:11px;text-transform:uppercase;letter-spacing:0.1em;color:var(--cs-accent-bright);font-weight:700">{{ ctaKicker }}</div><div style="font-size:15px;margin-top:2px">hello@cyberskill.world · cyberskill.world · {{ ctaPlace }}</div></div>
70
+ <div class="cs-avoid" style="display:flex;align-items:center;justify-content:space-between;gap:20px;background:var(--cs-color-brand-umber);color:#FFFDF8;padding:22px 56px;margin-top:6px">
71
+ <div><div style="font-size:11px;text-transform:uppercase;letter-spacing:0.1em;color:#FFFDF8;font-weight:700">{{ ctaKicker }}</div><div style="font-size:15px;margin-top:2px">hello@cyberskill.world · cyberskill.world · {{ ctaPlace }}</div></div>
71
72
  <span style="display:inline-block;background:var(--cs-accent-bright);color:var(--cs-accent-on);font-weight:700;font-size:14px;padding:12px 24px;border-radius:var(--cs-radius-full);white-space:nowrap">{{ ctaBtn }}</span>
72
73
  </div>
73
74
  </div>
@@ -1,9 +1,10 @@
1
1
  // Loads this design system into the template. In a consuming project, point
2
2
  // base at the bound DS folder relative to this file (e.g. '_ds/<folder>' at
3
3
  // the project root, '../_ds/<folder>' one level down) — one line to edit.
4
+ // Artifact head standard (UX-002 / B1): ensure <html lang> + <title> from @template.
4
5
  (() => {
5
6
  const base = '../..';
6
- for (const p of ['styles.css']) {
7
+ for (const p of ['dist/styles.min.css']) {
7
8
  const l = document.createElement('link');
8
9
  l.rel = 'stylesheet'; l.href = base + '/' + p;
9
10
  document.head.appendChild(l);
@@ -20,4 +21,35 @@
20
21
  };
21
22
  s.onerror = () => console.error('ds-base.js: failed to load ' + s.src + ' — if this is a consuming project, point the base line in ds-base.js at the bound _ds/<folder> tree relative to this page (e.g. _ds/<folder> at the project root, ../_ds/<folder> one level down); in a fresh design system this can just mean the bundle is not compiled yet');
22
23
  document.head.appendChild(s);
24
+
25
+ const syncLang = () => {
26
+ try {
27
+ const a = document.querySelector('[lang]');
28
+ const v = a && a.getAttribute('lang');
29
+ // Ignore unresolved DC holes like {{ langAttr }}
30
+ if (v && v.indexOf('{{') === -1) document.documentElement.setAttribute('lang', v);
31
+ else if (!document.documentElement.getAttribute('lang')) document.documentElement.setAttribute('lang', 'en');
32
+ } catch (e) { /* authoring host may sandbox */ }
33
+ };
34
+ const ensureHead = () => {
35
+ try {
36
+ if (!document.title || !document.title.trim()) {
37
+ const src = document.documentElement.innerHTML;
38
+ const m = src.match(/@template\s+name="([^"]+)"/);
39
+ if (m) document.title = m[1] + ' · CyberSkill';
40
+ }
41
+ syncLang();
42
+ const obs = new MutationObserver(syncLang);
43
+ obs.observe(document.body || document.documentElement, {
44
+ attributes: true,
45
+ attributeFilter: ['lang'],
46
+ subtree: true,
47
+ });
48
+ } catch (e) { /* authoring host may sandbox */ }
49
+ };
50
+ if (document.readyState === 'loading') {
51
+ document.addEventListener('DOMContentLoaded', ensureHead);
52
+ } else {
53
+ ensureHead();
54
+ }
23
55
  })();