@cyberskill/design 1.1.1 → 1.2.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 (353) hide show
  1. package/DESIGN.md +25 -3
  2. package/README.md +3 -3
  3. package/SKILL.md +3 -3
  4. package/VERSION +1 -1
  5. package/_ds_bundle.js +819 -416
  6. package/_ds_manifest.json +1 -1
  7. package/_esm/cs.mjs +18 -4
  8. package/_esm/react.d.ts +2 -0
  9. package/_esm/react.mjs +1 -0
  10. package/base/a11y.css +18 -0
  11. package/base/ai.css +2 -2
  12. package/base/collections.css +8 -3
  13. package/base/components.css +11 -2
  14. package/base/controls.css +61 -48
  15. package/base/data.css +3 -3
  16. package/base/feedback.css +5 -0
  17. package/base/forms.css +9 -3
  18. package/base/glass.css +6 -0
  19. package/base/navigation.css +8 -2
  20. package/base/reset.css +1 -1
  21. package/base/responsive.css +25 -0
  22. package/base/shell.css +7 -1
  23. package/components/_i18n/i18n.js +13 -1
  24. package/components/_i18n/strings.js +52 -3
  25. package/components/ai/ConfidenceMeter.jsx +8 -6
  26. package/components/data/Watermark.jsx +11 -3
  27. package/components/datatable/DataGrid.jsx +10 -1
  28. package/components/dialog/Dialog.jsx +13 -45
  29. package/components/feedback/ProgressBar.jsx +4 -2
  30. package/components/forms/Cascader.jsx +69 -6
  31. package/components/forms/Editor.jsx +37 -2
  32. package/components/forms/FileUpload.jsx +22 -8
  33. package/components/forms/Switch.jsx +16 -2
  34. package/components/forms/TimePicker.jsx +3 -1
  35. package/components/icon/Icon.jsx +1 -0
  36. package/components/navigation/CommandPalette.jsx +22 -7
  37. package/components/navigation/Toolbar.jsx +2 -1
  38. package/components/overlays/AlertDialog.jsx +19 -49
  39. package/components/overlays/Drawer.jsx +24 -20
  40. package/components/overlays/OverlayManager.d.ts +40 -0
  41. package/components/overlays/OverlayManager.jsx +214 -0
  42. package/components/overlays/OverlayManager.prompt.md +12 -0
  43. package/components/overlays/Tour.jsx +14 -7
  44. package/dist/styles.min.css +2004 -0
  45. package/docs/benchmark-rubric.md +1 -1
  46. package/docs/ci-cd.md +3 -1
  47. package/docs/consuming.md +6 -6
  48. package/docs/conventions.md +4 -4
  49. package/docs/decisions/container-query-migration.md +18 -0
  50. package/docs/decisions/overlay-manager-design.md +101 -0
  51. package/docs/decisions.md +5 -5
  52. package/docs/design-styles.md +1 -1
  53. package/docs/plans/cyberskill-design-system-audit-and-12-month-evolution-plan.md +1490 -0
  54. package/docs/quality-gates.md +20 -8
  55. package/docs/release-notes.md +2 -2
  56. package/docs/status/data/status-feed.json +1 -1
  57. package/docs/status/index.html +9 -5
  58. package/docs/status/status-legacy.html +12 -7
  59. package/docs/sync.md +1 -1
  60. package/docs/tasks/_state/commit-links.yaml +14 -0
  61. package/docs/vi/benchmark-rubric.md +1 -1
  62. package/docs/vi/ci-cd.md +3 -1
  63. package/docs/vi/consuming.md +6 -6
  64. package/docs/vi/conventions.md +2 -2
  65. package/docs/vi/decisions.md +4 -4
  66. package/docs/vi/quality-gates.md +21 -9
  67. package/docs/vi/release-notes.md +2 -2
  68. package/docs/vi/sync.md +1 -1
  69. package/guidelines/atomic-view.html +11 -7
  70. package/llms.txt +2 -2
  71. package/package.json +14 -6
  72. package/templates/_ds-base.canonical.js +55 -0
  73. package/templates/ai-cluster-demo.html +2 -2
  74. package/templates/app-shell/AppShell.dc.html +5 -3
  75. package/templates/app-shell/ds-base.js +33 -1
  76. package/templates/app-shell/support.js +13 -20
  77. package/templates/article/Article.dc.html +5 -1
  78. package/templates/article/ds-base.js +33 -1
  79. package/templates/article/support.js +13 -20
  80. package/templates/auth/Auth.dc.html +10 -5
  81. package/templates/auth/content-schema.json +12 -0
  82. package/templates/auth/ds-base.js +33 -1
  83. package/templates/auth/support.js +13 -20
  84. package/templates/bod-deck/BodDeck.dc.html +11 -10
  85. package/templates/bod-deck/ds-base.js +33 -1
  86. package/templates/bod-deck/support.js +13 -20
  87. package/templates/bod-investor-update/BodInvestorUpdate.dc.html +4 -3
  88. package/templates/bod-investor-update/ds-base.js +33 -1
  89. package/templates/bod-investor-update/support.js +13 -20
  90. package/templates/bod-memo/BodMemo.dc.html +6 -5
  91. package/templates/bod-memo/ds-base.js +33 -1
  92. package/templates/bod-memo/support.js +13 -20
  93. package/templates/bod-minutes/BodMinutes.dc.html +2 -1
  94. package/templates/bod-minutes/ds-base.js +33 -1
  95. package/templates/bod-minutes/support.js +13 -20
  96. package/templates/bod-report/BodReport.dc.html +3 -2
  97. package/templates/bod-report/ds-base.js +33 -1
  98. package/templates/bod-report/support.js +13 -20
  99. package/templates/bod-resolution/BodResolution.dc.html +5 -4
  100. package/templates/bod-resolution/ds-base.js +33 -1
  101. package/templates/bod-resolution/support.js +13 -20
  102. package/templates/culture-event-invite/CultureEventInvite.dc.html +3 -2
  103. package/templates/culture-event-invite/ds-base.js +33 -1
  104. package/templates/culture-event-invite/support.js +13 -20
  105. package/templates/dashboard/Dashboard.dc.html +7 -3
  106. package/templates/dashboard/ds-base.js +33 -1
  107. package/templates/dashboard/support.js +13 -20
  108. package/templates/delivery-change-note/DeliveryChangeNote.dc.html +2 -1
  109. package/templates/delivery-change-note/ds-base.js +33 -1
  110. package/templates/delivery-change-note/support.js +13 -20
  111. package/templates/delivery-kickoff/DeliveryKickoff.dc.html +3 -2
  112. package/templates/delivery-kickoff/ds-base.js +33 -1
  113. package/templates/delivery-kickoff/support.js +13 -20
  114. package/templates/delivery-qbr-deck/DeliveryQbrDeck.dc.html +6 -5
  115. package/templates/delivery-qbr-deck/ds-base.js +33 -1
  116. package/templates/delivery-qbr-deck/support.js +13 -20
  117. package/templates/delivery-runbook/DeliveryRunbook.dc.html +3 -2
  118. package/templates/delivery-runbook/ds-base.js +33 -1
  119. package/templates/delivery-runbook/support.js +13 -20
  120. package/templates/delivery-status-email/DeliveryStatusEmail.dc.html +3 -2
  121. package/templates/delivery-status-email/ds-base.js +33 -1
  122. package/templates/delivery-status-email/support.js +13 -20
  123. package/templates/doc-style-guide/DocStyleGuide.dc.html +67 -64
  124. package/templates/doc-style-guide/ds-base.js +33 -1
  125. package/templates/doc-style-guide/support.js +13 -20
  126. package/templates/doc-suite-index/DocSuiteIndex.dc.html +46 -45
  127. package/templates/doc-suite-index/ds-base.js +33 -1
  128. package/templates/doc-suite-index/support.js +13 -20
  129. package/templates/doc-templates/DocTemplates.dc.html +42 -41
  130. package/templates/doc-templates/ds-base.js +33 -1
  131. package/templates/doc-templates/support.js +13 -20
  132. package/templates/email/Email.dc.html +3 -2
  133. package/templates/email/ds-base.js +33 -1
  134. package/templates/email/support.js +13 -20
  135. package/templates/finance-dunning-email/FinanceDunningEmail.dc.html +4 -3
  136. package/templates/finance-dunning-email/ds-base.js +33 -1
  137. package/templates/finance-dunning-email/support.js +13 -20
  138. package/templates/finance-expense-report/FinanceExpenseReport.dc.html +4 -3
  139. package/templates/finance-expense-report/ds-base.js +33 -1
  140. package/templates/finance-expense-report/support.js +13 -20
  141. package/templates/finance-invoice/FinanceInvoice.dc.html +4 -3
  142. package/templates/finance-invoice/ds-base.js +33 -1
  143. package/templates/finance-invoice/support.js +13 -20
  144. package/templates/finance-quote/FinanceQuote.dc.html +4 -3
  145. package/templates/finance-quote/ds-base.js +33 -1
  146. package/templates/finance-quote/support.js +13 -20
  147. package/templates/hr-announcement/HrAnnouncement.dc.html +5 -4
  148. package/templates/hr-announcement/ds-base.js +33 -1
  149. package/templates/hr-announcement/support.js +13 -20
  150. package/templates/hr-interview-kit/HrInterviewKit.dc.html +4 -3
  151. package/templates/hr-interview-kit/ds-base.js +33 -1
  152. package/templates/hr-interview-kit/support.js +13 -20
  153. package/templates/hr-offboarding/HrOffboarding.dc.html +2 -1
  154. package/templates/hr-offboarding/ds-base.js +33 -1
  155. package/templates/hr-offboarding/support.js +13 -20
  156. package/templates/hr-performance-review/HrPerformanceReview.dc.html +2 -1
  157. package/templates/hr-performance-review/ds-base.js +33 -1
  158. package/templates/hr-performance-review/support.js +13 -20
  159. package/templates/hr-pip/HrPip.dc.html +2 -1
  160. package/templates/hr-pip/ds-base.js +33 -1
  161. package/templates/hr-pip/support.js +13 -20
  162. package/templates/kitchen-sink.html +9 -4
  163. package/templates/legal-msa/LegalMsa.dc.html +2 -1
  164. package/templates/legal-msa/ds-base.js +33 -1
  165. package/templates/legal-msa/support.js +13 -20
  166. package/templates/legal-sow/LegalSow.dc.html +2 -1
  167. package/templates/legal-sow/ds-base.js +33 -1
  168. package/templates/legal-sow/support.js +13 -20
  169. package/templates/marketing-campaign-brief/MarketingCampaignBrief.dc.html +3 -2
  170. package/templates/marketing-campaign-brief/ds-base.js +33 -1
  171. package/templates/marketing-campaign-brief/support.js +13 -20
  172. package/templates/marketing-case-study/MarketingCaseStudy.dc.html +5 -4
  173. package/templates/marketing-case-study/ds-base.js +33 -1
  174. package/templates/marketing-case-study/support.js +13 -20
  175. package/templates/marketing-launch/MarketingLaunch.dc.html +6 -5
  176. package/templates/marketing-launch/ds-base.js +33 -1
  177. package/templates/marketing-launch/support.js +13 -20
  178. package/templates/marketing-newsletter/MarketingNewsletter.dc.html +13 -12
  179. package/templates/marketing-newsletter/ds-base.js +33 -1
  180. package/templates/marketing-newsletter/support.js +13 -20
  181. package/templates/marketing-page/MarketingPage.dc.html +17 -12
  182. package/templates/marketing-page/ds-base.js +33 -1
  183. package/templates/marketing-page/support.js +13 -20
  184. package/templates/marketing-press-release/MarketingPressRelease.dc.html +2 -1
  185. package/templates/marketing-press-release/ds-base.js +33 -1
  186. package/templates/marketing-press-release/support.js +13 -20
  187. package/templates/marketing-social-kit/MarketingSocialKit.dc.html +5 -4
  188. package/templates/marketing-social-kit/ds-base.js +33 -1
  189. package/templates/marketing-social-kit/support.js +13 -20
  190. package/templates/sales-one-pager/SalesOnePager.dc.html +5 -4
  191. package/templates/sales-one-pager/ds-base.js +33 -1
  192. package/templates/sales-one-pager/support.js +13 -20
  193. package/templates/sales-proposal-deck/SalesProposalDeck.dc.html +7 -6
  194. package/templates/sales-proposal-deck/ds-base.js +33 -1
  195. package/templates/sales-proposal-deck/support.js +13 -20
  196. package/templates/settings/Settings.dc.html +5 -1
  197. package/templates/settings/ds-base.js +33 -1
  198. package/templates/settings/support.js +13 -20
  199. package/templates/slide-deck/SlideDeck.dc.html +5 -4
  200. package/templates/slide-deck/ds-base.js +33 -1
  201. package/templates/slide-deck/support.js +13 -20
  202. package/templates/team-meeting-agenda/TeamMeetingAgenda.dc.html +2 -1
  203. package/templates/team-meeting-agenda/ds-base.js +33 -1
  204. package/templates/team-meeting-agenda/support.js +13 -20
  205. package/templates/tech-incident-report/TechIncidentReport.dc.html +3 -2
  206. package/templates/tech-incident-report/ds-base.js +33 -1
  207. package/templates/tech-incident-report/support.js +13 -20
  208. package/templates/tech-release-notes/TechReleaseNotes.dc.html +6 -5
  209. package/templates/tech-release-notes/ds-base.js +33 -1
  210. package/templates/tech-release-notes/support.js +13 -20
  211. package/templates/tech-retro/TechRetro.dc.html +4 -3
  212. package/templates/tech-retro/ds-base.js +33 -1
  213. package/templates/tech-retro/support.js +13 -20
  214. package/templates/tech-rfc/TechRfc.dc.html +3 -2
  215. package/templates/tech-rfc/ds-base.js +33 -1
  216. package/templates/tech-rfc/support.js +13 -20
  217. package/templates/vn-appointment-transfer/VnAppointmentTransfer.dc.html +36 -35
  218. package/templates/vn-appointment-transfer/ds-base.js +33 -1
  219. package/templates/vn-appointment-transfer/support.js +13 -20
  220. package/templates/vn-certificate-of-employment/VnCertificateOfEmployment.dc.html +27 -26
  221. package/templates/vn-certificate-of-employment/ds-base.js +33 -1
  222. package/templates/vn-certificate-of-employment/support.js +13 -20
  223. package/templates/vn-code-of-conduct/VnCodeOfConduct.dc.html +44 -43
  224. package/templates/vn-code-of-conduct/ds-base.js +33 -1
  225. package/templates/vn-code-of-conduct/support.js +13 -20
  226. package/templates/vn-compensation-regulation/VnCompensationRegulation.dc.html +53 -52
  227. package/templates/vn-compensation-regulation/ds-base.js +33 -1
  228. package/templates/vn-compensation-regulation/support.js +13 -20
  229. package/templates/vn-contract-amendment/VnContractAmendment.dc.html +41 -40
  230. package/templates/vn-contract-amendment/ds-base.js +33 -1
  231. package/templates/vn-contract-amendment/support.js +13 -20
  232. package/templates/vn-contractor-agreement/VnContractorAgreement.dc.html +50 -49
  233. package/templates/vn-contractor-agreement/ds-base.js +33 -1
  234. package/templates/vn-contractor-agreement/support.js +13 -20
  235. package/templates/vn-data-protection-policy/VnDataProtectionPolicy.dc.html +54 -53
  236. package/templates/vn-data-protection-policy/ds-base.js +33 -1
  237. package/templates/vn-data-protection-policy/support.js +13 -20
  238. package/templates/vn-disciplinary-case-file/VnDisciplinaryCaseFile.dc.html +72 -71
  239. package/templates/vn-disciplinary-case-file/ds-base.js +33 -1
  240. package/templates/vn-disciplinary-case-file/support.js +13 -20
  241. package/templates/vn-disciplinary-schedule/VnDisciplinarySchedule.dc.html +21 -20
  242. package/templates/vn-disciplinary-schedule/ds-base.js +33 -1
  243. package/templates/vn-disciplinary-schedule/support.js +13 -20
  244. package/templates/vn-employee-request/VnEmployeeRequest.dc.html +54 -53
  245. package/templates/vn-employee-request/ds-base.js +33 -1
  246. package/templates/vn-employee-request/support.js +13 -20
  247. package/templates/vn-exit-handover/VnExitHandover.dc.html +122 -121
  248. package/templates/vn-exit-handover/ds-base.js +33 -1
  249. package/templates/vn-exit-handover/support.js +13 -20
  250. package/templates/vn-foreign-employee-pack/VnForeignEmployeePack.dc.html +31 -30
  251. package/templates/vn-foreign-employee-pack/ds-base.js +33 -1
  252. package/templates/vn-foreign-employee-pack/support.js +13 -20
  253. package/templates/vn-grassroots-democracy/VnGrassrootsDemocracy.dc.html +54 -53
  254. package/templates/vn-grassroots-democracy/ds-base.js +33 -1
  255. package/templates/vn-grassroots-democracy/support.js +13 -20
  256. package/templates/vn-infosec-policy/VnInfosecPolicy.dc.html +50 -49
  257. package/templates/vn-infosec-policy/ds-base.js +33 -1
  258. package/templates/vn-infosec-policy/support.js +13 -20
  259. package/templates/vn-internal-labor-regulations/VnInternalLaborRegulations.dc.html +84 -83
  260. package/templates/vn-internal-labor-regulations/ds-base.js +33 -1
  261. package/templates/vn-internal-labor-regulations/support.js +13 -20
  262. package/templates/vn-internship-agreement/VnInternshipAgreement.dc.html +44 -43
  263. package/templates/vn-internship-agreement/ds-base.js +33 -1
  264. package/templates/vn-internship-agreement/support.js +13 -20
  265. package/templates/vn-job-description/VnJobDescription.dc.html +28 -27
  266. package/templates/vn-job-description/ds-base.js +33 -1
  267. package/templates/vn-job-description/support.js +13 -20
  268. package/templates/vn-labor-contract/VnLaborContract.dc.html +109 -108
  269. package/templates/vn-labor-contract/ds-base.js +33 -1
  270. package/templates/vn-labor-contract/support.js +13 -20
  271. package/templates/vn-labour-management-book/VnLabourManagementBook.dc.html +32 -31
  272. package/templates/vn-labour-management-book/ds-base.js +33 -1
  273. package/templates/vn-labour-management-book/support.js +13 -20
  274. package/templates/vn-mutual-nda/VnMutualNda.dc.html +45 -44
  275. package/templates/vn-mutual-nda/ds-base.js +33 -1
  276. package/templates/vn-mutual-nda/support.js +13 -20
  277. package/templates/vn-ndnca-ip/VnNdncaIp.dc.html +73 -72
  278. package/templates/vn-ndnca-ip/ds-base.js +33 -1
  279. package/templates/vn-ndnca-ip/support.js +13 -20
  280. package/templates/vn-offer-letter/VnOfferLetter.dc.html +32 -31
  281. package/templates/vn-offer-letter/ds-base.js +33 -1
  282. package/templates/vn-offer-letter/support.js +13 -20
  283. package/templates/vn-onboarding-checklist/VnOnboardingChecklist.dc.html +16 -15
  284. package/templates/vn-onboarding-checklist/ds-base.js +33 -1
  285. package/templates/vn-onboarding-checklist/support.js +13 -20
  286. package/templates/vn-pdpl-consent/VnPdplConsent.dc.html +43 -42
  287. package/templates/vn-pdpl-consent/ds-base.js +33 -1
  288. package/templates/vn-pdpl-consent/support.js +13 -20
  289. package/templates/vn-performance-evaluation-regulation/VnPerformanceEvaluationRegulation.dc.html +65 -64
  290. package/templates/vn-performance-evaluation-regulation/ds-base.js +33 -1
  291. package/templates/vn-performance-evaluation-regulation/support.js +13 -20
  292. package/templates/vn-performance-review-form/VnPerformanceReviewForm.dc.html +49 -48
  293. package/templates/vn-performance-review-form/ds-base.js +33 -1
  294. package/templates/vn-performance-review-form/support.js +13 -20
  295. package/templates/vn-phantom-stock/VnPhantomStock.dc.html +41 -40
  296. package/templates/vn-phantom-stock/ds-base.js +33 -1
  297. package/templates/vn-phantom-stock/support.js +13 -20
  298. package/templates/vn-probation-contract/VnProbationContract.dc.html +56 -55
  299. package/templates/vn-probation-contract/ds-base.js +33 -1
  300. package/templates/vn-probation-contract/support.js +13 -20
  301. package/templates/vn-receipt-acknowledgement/VnReceiptAcknowledgement.dc.html +28 -27
  302. package/templates/vn-receipt-acknowledgement/ds-base.js +33 -1
  303. package/templates/vn-receipt-acknowledgement/support.js +13 -20
  304. package/templates/vn-remote-work-policy/VnRemoteWorkPolicy.dc.html +44 -43
  305. package/templates/vn-remote-work-policy/ds-base.js +33 -1
  306. package/templates/vn-remote-work-policy/support.js +13 -20
  307. package/templates/vn-resignation-letter/VnResignationLetter.dc.html +20 -19
  308. package/templates/vn-resignation-letter/ds-base.js +33 -1
  309. package/templates/vn-resignation-letter/support.js +13 -20
  310. package/templates/vn-salary-scale/VnSalaryScale.dc.html +39 -38
  311. package/templates/vn-salary-scale/ds-base.js +33 -1
  312. package/templates/vn-salary-scale/support.js +13 -20
  313. package/templates/vn-sow-appendix/VnSowAppendix.dc.html +21 -20
  314. package/templates/vn-sow-appendix/ds-base.js +33 -1
  315. package/templates/vn-sow-appendix/support.js +13 -20
  316. package/templates/vn-termination-decision/VnTerminationDecision.dc.html +25 -24
  317. package/templates/vn-termination-decision/ds-base.js +33 -1
  318. package/templates/vn-termination-decision/support.js +13 -20
  319. package/templates/vn-total-rewards-appendix/VnTotalRewardsAppendix.dc.html +63 -62
  320. package/templates/vn-total-rewards-appendix/ds-base.js +33 -1
  321. package/templates/vn-total-rewards-appendix/support.js +13 -20
  322. package/templates/vn-training-commitment/VnTrainingCommitment.dc.html +39 -38
  323. package/templates/vn-training-commitment/ds-base.js +33 -1
  324. package/templates/vn-training-commitment/support.js +13 -20
  325. package/templates/vn-travel-expense-policy/VnTravelExpensePolicy.dc.html +50 -49
  326. package/templates/vn-travel-expense-policy/ds-base.js +33 -1
  327. package/templates/vn-travel-expense-policy/support.js +13 -20
  328. package/tokens/colors.css +19 -1
  329. package/tokens/component-tokens.css +1 -0
  330. package/tokens/elements.css +35 -2
  331. package/tokens/elevation.css +8 -2
  332. package/tokens/native/CSTokens.kt +35 -1
  333. package/tokens/native/CSTokens.swift +35 -1
  334. package/tokens/native/cs_tokens.dart +35 -1
  335. package/tokens/provenance.json +12 -12
  336. package/tokens/spacing.css +2 -0
  337. package/tokens/tokens.dtcg.json +111 -3
  338. package/tokens/tokens.js +46 -6
  339. package/tokens/tokens.json +45 -5
  340. package/tokens/typography.css +2 -0
  341. package/ui_kits/deck/index.html +4 -0
  342. package/ui_kits/status-hub/StatusHub.jsx +30 -4
  343. package/ui_kits/status-hub/index.html +3 -3
  344. package/ui_kits/status-hub/login.html +4 -0
  345. package/ui_kits/status-hub/project.html +4 -0
  346. package/ui_kits/status-hub/settings.html +35 -13
  347. package/ui_kits/status-hub/status.css +5 -1
  348. package/ui_kits/website/Website.jsx +25 -3
  349. package/ui_kits/website/careers.html +4 -0
  350. package/ui_kits/website/chat.html +5 -3
  351. package/ui_kits/website/index.html +3 -3
  352. package/ui_kits/website/site.css +2 -2
  353. package/ui_kits/website/work.html +4 -0
@@ -0,0 +1,55 @@
1
+ // Loads this design system into the template. In a consuming project, point
2
+ // base at the bound DS folder relative to this file (e.g. '_ds/<folder>' at
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.
5
+ (() => {
6
+ const base = '../..';
7
+ for (const p of ['dist/styles.min.css']) {
8
+ const l = document.createElement('link');
9
+ l.rel = 'stylesheet'; l.href = base + '/' + p;
10
+ document.head.appendChild(l);
11
+ }
12
+ const s = document.createElement('script');
13
+ s.src = base + '/_ds_bundle.js';
14
+ s.onload = () => {
15
+ // Expose a STABLE, project-id-independent alias. The compiler names the bundle
16
+ // global CyberSkillDesignSystem_<6-hex-project-id>, which changes whenever this
17
+ // system is re-imported into another project. Templates/cards read window.CyberSkillDS
18
+ // so no file ever has to be rewritten on re-import.
19
+ const k = Object.keys(window).find((k) => /^CyberSkillDesignSystem_[0-9a-f]{6}$/.test(k));
20
+ if (k) window.CyberSkillDS = window[k];
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');
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
+ }
55
+ })();
@@ -8,8 +8,8 @@
8
8
  h1{font-size:18px;margin:0 0 8px} .sub{color:var(--cs-color-text-muted);font-size:13px;line-height:1.5;margin:0 0 18px}
9
9
  #root{display:grid;gap:14px}
10
10
  </style>
11
- <script src="https://unpkg.com/umd-react@19.2.8/dist/react.development.js" crossorigin="anonymous"></script>
12
- <script src="https://unpkg.com/umd-react@19.2.8/dist/react-dom.development.js" crossorigin="anonymous"></script>
11
+ <script src="../_vendor/react/react.production.min.js"></script>
12
+ <script src="../_vendor/react/react-dom.production.min.js"></script>
13
13
  <script src="../_ds_bundle.js"></script>
14
14
  </head><body data-cs-element="tho" data-cs-style="liquid-glass">
15
15
  <h1>AI cluster demo</h1>
@@ -1,6 +1,7 @@
1
1
  <!DOCTYPE html>
2
- <html>
2
+ <html lang="en">
3
3
  <head>
4
+ <title>App shell · 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>
@@ -12,7 +13,8 @@
12
13
  <script src="./ds-base.js"></script>
13
14
  </helmet>
14
15
  <div data-theme="{{ rootTheme }}" lang="{{ langAttr }}" data-cs-element="{{ elAttr }}" data-cs-variant="{{ vaAttr }}" style="display:grid;grid-template-columns:248px 1fr;min-height:100vh;font-family:var(--cs-font-family-ui);color:var(--cs-color-text-primary);background:var(--cs-color-surface-page)">
15
- <nav class="cs-sidebar">
16
+ <a class="cs-skip" href="#main" style="position:absolute;left:-999px;top:auto;width:1px;height:1px;overflow:hidden">Skip to content</a>
17
+ <nav class="cs-sidebar" aria-label="{{ navLabel }}">
16
18
  <div style="display:flex;align-items:center;gap:10px;font-weight:800;font-size:17px;color:var(--cs-color-text-primary);padding:6px 12px 14px">
17
19
  <x-import component-from-global-scope="CyberSkillDS.Logo" size="28" hint-size="28px,28px"></x-import>CyberSkill
18
20
  </div>
@@ -34,7 +36,7 @@
34
36
  <x-import component-from-global-scope="CyberSkillDS.Avatar" name="An Le" hint-size="40px,40px"></x-import>
35
37
  </header>
36
38
 
37
- <main style="padding:28px;display:grid;gap:24px">
39
+ <main id="main" style="padding:28px;display:grid;gap:24px">
38
40
  <div>
39
41
  <h1 style="font-size:26px;font-weight:800;letter-spacing:-0.02em;margin:0 0 4px">{{ h1 }}</h1>
40
42
  <p style="color:var(--cs-color-text-muted);margin:0">{{ sub }}</p>
@@ -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>Article · 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>
@@ -12,6 +13,8 @@
12
13
  <script src="./ds-base.js"></script>
13
14
  </helmet>
14
15
  <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">
16
+ <a class="cs-skip" href="#main" style="position:absolute;left:-999px;top:auto;width:1px;height:1px;overflow:hidden">Skip to content</a>
17
+ <main id="main">
15
18
  <article style="max-width:720px;margin:0 auto;padding:56px 28px 80px">
16
19
  <div style="font-size:12px;font-weight:700;text-transform:uppercase;letter-spacing:0.12em;color:var(--cs-color-text-accent)">{{ eyebrow }}</div>
17
20
  <h1 style="font-size:clamp(32px,5vw,46px);font-weight:800;letter-spacing:-0.02em;line-height:1.14;margin:12px 0 16px">{{ h1 }}</h1>
@@ -32,6 +35,7 @@
32
35
  </div>
33
36
  <p style="font-size:17px;line-height:1.7;margin:0 0 18px">{{ p3 }}</p>
34
37
  </article>
38
+ </main>
35
39
  </div>
36
40
  </x-dc>
37
41
  <script type="text/x-dc" data-dc-script data-props="{
@@ -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>Sign in · 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,7 +14,7 @@
13
14
  </helmet>
14
15
  <style>
15
16
  .cs-auth-shell{display:grid;grid-template-columns:minmax(0,1.05fr) minmax(0,1fr);min-height:100vh;font-family:var(--cs-font-family-ui);color:var(--cs-color-text-primary);background:var(--cs-color-surface-page)}
16
- .cs-auth-brand{position:relative;overflow:hidden;background:var(--cs-accent-strong);color:#fff;padding:56px 60px;display:flex;flex-direction:column;min-width:0}
17
+ .cs-auth-brand{position:relative;overflow:hidden;background:var(--cs-color-brand-umber);color:#FFFDF8;padding:56px 60px;display:flex;flex-direction:column;min-width:0}
17
18
  .cs-auth-form{display:grid;place-items:center;padding:40px 24px;min-width:0}
18
19
  .cs-auth-form-inner{width:min(400px,100%);max-width:100%;box-sizing:border-box}
19
20
  @media (max-width:820px){
@@ -24,6 +25,8 @@
24
25
  }
25
26
  </style>
26
27
  <div class="cs-auth-shell" data-theme="{{ rootTheme }}" lang="{{ langAttr }}" data-cs-element="{{ elAttr }}" data-cs-variant="{{ vaAttr }}">
28
+ <a class="cs-skip" href="#main" style="position:absolute;left:-999px;top:auto;width:1px;height:1px;overflow:hidden">Skip to content</a>
29
+ <main id="main">
27
30
  <sc-if value="{{ showBrand }}" hint-placeholder-val="{{ true }}">
28
31
  <div class="cs-auth-brand">
29
32
  <div class="cs-aurora-wash" style="position:absolute;inset:0;opacity:0.4"></div>
@@ -42,13 +45,15 @@
42
45
  <div style="display:grid;gap:16px">
43
46
  <x-import component-from-global-scope="CyberSkillDS.TextField" label="{{ emailL }}" type="email" placeholder="you@cyberskill.world" hint-size="100%,74px"></x-import>
44
47
  <x-import component-from-global-scope="CyberSkillDS.TextField" label="{{ pwL }}" type="password" placeholder="••••••••" hint-size="100%,74px"></x-import>
45
- <x-import component-from-global-scope="CyberSkillDS.Switch" label="{{ rememberL }}" hint-size="140px,26px"></x-import>
48
+ <x-import component-from-global-scope="CyberSkillDS.Switch" label="{{ rememberL }}" checked="{{ false }}" hint-size="140px,26px"></x-import>
46
49
  <x-import component-from-global-scope="CyberSkillDS.Button" variant="primary" full-width="{{ true }}" hint-size="100%,44px">{{ signInBtn }}</x-import>
47
50
  <x-import component-from-global-scope="CyberSkillDS.Button" variant="ghost" full-width="{{ true }}" hint-size="100%,44px">{{ lumiBtn }}</x-import>
48
51
  </div>
49
52
  <p style="text-align:center;font-size:13px;color:var(--cs-color-text-muted);margin-top:16px">{{ newHere }} <a href="#">{{ askAccess }}</a></p>
53
+ <p style="text-align:center;font-size:12px;color:var(--cs-color-text-muted);margin-top:8px">{{ resetHint }} <a href="mailto:admin@cyberskill.world?subject=Password%20reset">{{ resetLink }}</a></p>
50
54
  </div>
51
55
  </div>
56
+ </main>
52
57
  </div>
53
58
  </x-dc>
54
59
  <script type="text/x-dc" data-dc-script data-props="{
@@ -62,8 +67,8 @@ class Component extends DCLogic {
62
67
  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"]};
63
68
  const [elAttr, vaAttr] = EL[this.props.element] || EL["Thổ · studio"];
64
69
  const vn = this.props.language === "Tiếng Việt";
65
- const en = { brandH:"Turn Your Will Into Real", brandP:"Sign in to your workspace — one page, three lenses across every wish in flight.", title:"Sign in", sub:"Welcome back. Đăng nhập để tiếp tục.", emailL:"Work email", pwL:"Password", rememberL:"Remember me", signInBtn:"Sign in", lumiBtn:"✦ Talk to Lumi instead", newHere:"New here?", askAccess:"Ask for access" };
66
- const vi = { brandH:"Hiện Thực Hoá Ý Chí", brandP:"Đăng nhập vào không gian làm việc — một trang, ba lăng kính cho mọi điều ước đang chạy.", title:"Đăng nhập", sub:"Chào bạn trở lại. Sign in to continue.", emailL:"Email công việc", pwL:"Mật khẩu", rememberL:"Ghi nhớ đăng nhập", signInBtn:"Đăng nhập", lumiBtn:"✦ Trò chuyện với Lumi", newHere:"Lần đầu?", askAccess:"Xin quyền truy cập" };
70
+ const en = { brandH:"Turn Your Will Into Real", brandP:"Sign in to your workspace — one page, three lenses across every wish in flight.", title:"Sign in", sub:"Welcome back. Sign in to continue.", emailL:"Work email", pwL:"Password", rememberL:"Remember me", signInBtn:"Sign in", lumiBtn:"✦ Talk to Lumi instead", newHere:"New here?", askAccess:"Ask for access", resetHint:"Forgot password?", resetLink:"Email your workspace admin to reset." };
71
+ const vi = { brandH:"Hiện Thực Hoá Ý Chí", brandP:"Đăng nhập vào không gian làm việc — một trang, ba lăng kính cho mọi điều ước đang chạy.", title:"Đăng nhập", sub:"Mừng bạn quay lại. Đăng nhập để tiếp tục.", emailL:"Email công việc", pwL:"Mật khẩu", rememberL:"Ghi nhớ đăng nhập", signInBtn:"Đăng nhập", lumiBtn:"✦ Trò chuyện với Lumi", newHere:"Lần đầu?", askAccess:"Xin quyền truy cập", resetHint:"Quên mật khẩu?", resetLink:"Gửi email cho quản trị không gian làm việc để đặt lại." };
67
72
  return Object.assign({ langAttr: (this.props.language ?? "English") === "Tiếng Việt" ? "vi" : "en", elAttr, vaAttr, rootTheme: this.props.theme === "dark" ? "dark" : "", showBrand: this.props.showBrandPanel ?? true }, vn ? vi : en);
68
73
  }
69
74
  }
@@ -69,6 +69,18 @@
69
69
  "type": "text",
70
70
  "label": "Ask-for-access link label",
71
71
  "maxLength": 24
72
+ },
73
+ {
74
+ "id": "resetHint",
75
+ "type": "text",
76
+ "label": "Password-reset hint",
77
+ "maxLength": 40
78
+ },
79
+ {
80
+ "id": "resetLink",
81
+ "type": "text",
82
+ "label": "Password-reset action link",
83
+ "maxLength": 64
72
84
  }
73
85
  ]
74
86
  }
@@ -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>Board · Meeting deck · 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
  <div data-theme="{{ rootTheme }}" 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)">
15
16
  <div style="display:grid;gap:28px;max-width:1280px;margin:0 auto">
16
17
 
17
- <section style="position:relative;width:100%;aspect-ratio:16/9;background:var(--cs-accent-strong);color:#fff;border-radius:var(--cs-radius-lg);overflow:hidden;box-shadow:var(--cs-shadow-xl);display:flex;flex-direction:column;justify-content:center;padding:0 88px">
18
+ <section style="position:relative;width:100%;aspect-ratio:16/9;background:var(--cs-color-brand-umber);color:#FFFDF8;border-radius:var(--cs-radius-lg);overflow:hidden;box-shadow:var(--cs-shadow-xl);display:flex;flex-direction:column;justify-content:center;padding:0 88px">
18
19
  <div style="display:flex;align-items:center;gap:14px;margin-bottom:26px">
19
20
  <x-import component-from-global-scope="CyberSkillDS.Logo" size="46" hint-size="46px,46px"></x-import>
20
21
  <span style="font-weight:800;font-size:22px;letter-spacing:-0.01em">CyberSkill</span>
@@ -30,10 +31,10 @@
30
31
  <div style="font-size:14px;font-weight:700;text-transform:uppercase;letter-spacing:0.12em;color:var(--cs-color-text-accent)">{{ s2kicker }}</div>
31
32
  <h2 style="font-size:44px;font-weight:800;letter-spacing:-0.02em;margin:10px 0 40px">{{ s2h }}</h2>
32
33
  <div style="display:grid;grid-template-columns:repeat(4,1fr);gap:40px">
33
- <div><div style="font-size:60px;font-weight:800;color:var(--cs-accent-bright);line-height:1;letter-spacing:-0.02em">+18%</div><div style="font-size:19px;color:var(--cs-color-text-muted);margin-top:10px">{{ n1 }}</div></div>
34
- <div><div style="font-size:60px;font-weight:800;color:var(--cs-accent-bright);line-height:1;letter-spacing:-0.02em">14</div><div style="font-size:19px;color:var(--cs-color-text-muted);margin-top:10px">{{ n2 }}</div></div>
35
- <div><div style="font-size:60px;font-weight:800;color:var(--cs-accent-bright);line-height:1;letter-spacing:-0.02em">{{ runway }}</div><div style="font-size:19px;color:var(--cs-color-text-muted);margin-top:10px">{{ n3 }}</div></div>
36
- <div><div style="font-size:60px;font-weight:800;color:var(--cs-accent-bright);line-height:1;letter-spacing:-0.02em">38</div><div style="font-size:19px;color:var(--cs-color-text-muted);margin-top:10px">{{ n4 }}</div></div>
34
+ <div><div style="font-size:60px;font-weight:800;color:var(--cs-accent-strong);line-height:1;letter-spacing:-0.02em">+18%</div><div style="font-size:19px;color:var(--cs-color-text-muted);margin-top:10px">{{ n1 }}</div></div>
35
+ <div><div style="font-size:60px;font-weight:800;color:var(--cs-accent-strong);line-height:1;letter-spacing:-0.02em">14</div><div style="font-size:19px;color:var(--cs-color-text-muted);margin-top:10px">{{ n2 }}</div></div>
36
+ <div><div style="font-size:60px;font-weight:800;color:var(--cs-accent-strong);line-height:1;letter-spacing:-0.02em">{{ runway }}</div><div style="font-size:19px;color:var(--cs-color-text-muted);margin-top:10px">{{ n3 }}</div></div>
37
+ <div><div style="font-size:60px;font-weight:800;color:var(--cs-accent-strong);line-height:1;letter-spacing:-0.02em">38</div><div style="font-size:19px;color:var(--cs-color-text-muted);margin-top:10px">{{ n4 }}</div></div>
37
38
  </div>
38
39
  <sc-if value="{{ showNumbers }}"><div style="position:absolute;bottom:40px;right:88px;font-family:var(--cs-font-family-mono);font-size:14px;color:var(--cs-color-text-muted)">02 / 05</div></sc-if>
39
40
  </section>
@@ -49,17 +50,17 @@
49
50
  <sc-if value="{{ showNumbers }}"><div style="position:absolute;bottom:40px;right:88px;font-family:var(--cs-font-family-mono);font-size:14px;color:var(--cs-color-text-muted)">03 / 05</div></sc-if>
50
51
  </section>
51
52
 
52
- <section style="position:relative;width:100%;aspect-ratio:16/9;background:var(--cs-accent-strong);color:#fff;border-radius:var(--cs-radius-lg);overflow:hidden;box-shadow:var(--cs-shadow-xl);padding:64px 88px;display:flex;flex-direction:column;justify-content:center">
53
+ <section style="position:relative;width:100%;aspect-ratio:16/9;background:var(--cs-color-brand-umber);color:#FFFDF8;border-radius:var(--cs-radius-lg);overflow:hidden;box-shadow:var(--cs-shadow-xl);padding:64px 88px;display:flex;flex-direction:column;justify-content:center">
53
54
  <div style="font-size:14px;font-weight:700;text-transform:uppercase;letter-spacing:0.14em;color:var(--cs-accent-bright)">{{ s4kicker }}</div>
54
55
  <h2 style="font-size:44px;font-weight:800;letter-spacing:-0.02em;color:var(--cs-accent-bright);margin:10px 0 34px">{{ s4h }}</h2>
55
56
  <div style="display:grid;gap:22px;font-size:24px;line-height:1.4;max-width:1000px">
56
- <div style="display:flex;gap:16px"><span style="color:var(--cs-accent-bright);font-weight:800">1.</span><div><b>{{ r1b }}</b> <span style="opacity:0.85">{{ r1t }}</span></div></div>
57
- <div style="display:flex;gap:16px"><span style="color:var(--cs-accent-bright);font-weight:800">2.</span><div><b>{{ r2b }}</b> <span style="opacity:0.85">{{ r2t }}</span></div></div>
57
+ <div style="display:flex;gap:16px"><span style="color:var(--cs-accent-strong);font-weight:800">1.</span><div><b>{{ r1b }}</b> <span style="opacity:0.85">{{ r1t }}</span></div></div>
58
+ <div style="display:flex;gap:16px"><span style="color:var(--cs-accent-strong);font-weight:800">2.</span><div><b>{{ r2b }}</b> <span style="opacity:0.85">{{ r2t }}</span></div></div>
58
59
  </div>
59
60
  <sc-if value="{{ showNumbers }}"><div style="position:absolute;bottom:40px;right:88px;font-family:var(--cs-font-family-mono);font-size:14px;color:var(--cs-accent-bright)">04 / 05</div></sc-if>
60
61
  </section>
61
62
 
62
- <section style="position:relative;width:100%;aspect-ratio:16/9;background:var(--cs-accent-strong);color:#fff;border-radius:var(--cs-radius-lg);overflow:hidden;box-shadow:var(--cs-shadow-xl);display:flex;flex-direction:column;justify-content:center;align-items:center;text-align:center;padding:0 88px">
63
+ <section style="position:relative;width:100%;aspect-ratio:16/9;background:var(--cs-color-brand-umber);color:#FFFDF8;border-radius:var(--cs-radius-lg);overflow:hidden;box-shadow:var(--cs-shadow-xl);display:flex;flex-direction:column;justify-content:center;align-items:center;text-align:center;padding:0 88px">
63
64
  <x-import component-from-global-scope="CyberSkillDS.Logo" size="72" hint-size="72px,72px"></x-import>
64
65
  <h2 style="font-size:56px;font-weight:800;letter-spacing:-0.02em;color:var(--cs-accent-bright);margin:24px 0 10px">{{ closeH }}</h2>
65
66
  <p style="font-size:22px;opacity:0.9;margin:0">{{ closeP }}</p>