@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.
- package/DESIGN.md +25 -3
- package/README.md +3 -3
- package/SKILL.md +3 -3
- package/VERSION +1 -1
- package/_ds_bundle.js +819 -416
- package/_ds_manifest.json +1 -1
- package/_esm/cs.mjs +18 -4
- package/_esm/react.d.ts +2 -0
- package/_esm/react.mjs +1 -0
- package/base/a11y.css +18 -0
- package/base/ai.css +2 -2
- package/base/collections.css +8 -3
- package/base/components.css +11 -2
- package/base/controls.css +61 -48
- package/base/data.css +3 -3
- package/base/feedback.css +5 -0
- package/base/forms.css +9 -3
- package/base/glass.css +6 -0
- package/base/navigation.css +8 -2
- package/base/reset.css +1 -1
- package/base/responsive.css +25 -0
- package/base/shell.css +7 -1
- package/components/_i18n/i18n.js +13 -1
- package/components/_i18n/strings.js +52 -3
- package/components/ai/ConfidenceMeter.jsx +8 -6
- package/components/data/Watermark.jsx +11 -3
- package/components/datatable/DataGrid.jsx +10 -1
- package/components/dialog/Dialog.jsx +13 -45
- package/components/feedback/ProgressBar.jsx +4 -2
- package/components/forms/Cascader.jsx +69 -6
- package/components/forms/Editor.jsx +37 -2
- package/components/forms/FileUpload.jsx +22 -8
- package/components/forms/Switch.jsx +16 -2
- package/components/forms/TimePicker.jsx +3 -1
- package/components/icon/Icon.jsx +1 -0
- package/components/navigation/CommandPalette.jsx +22 -7
- package/components/navigation/Toolbar.jsx +2 -1
- package/components/overlays/AlertDialog.jsx +19 -49
- package/components/overlays/Drawer.jsx +24 -20
- package/components/overlays/OverlayManager.d.ts +40 -0
- package/components/overlays/OverlayManager.jsx +214 -0
- package/components/overlays/OverlayManager.prompt.md +12 -0
- package/components/overlays/Tour.jsx +14 -7
- package/dist/styles.min.css +2004 -0
- package/docs/benchmark-rubric.md +1 -1
- package/docs/ci-cd.md +3 -1
- package/docs/consuming.md +6 -6
- package/docs/conventions.md +4 -4
- package/docs/decisions/container-query-migration.md +18 -0
- package/docs/decisions/overlay-manager-design.md +101 -0
- package/docs/decisions.md +5 -5
- package/docs/design-styles.md +1 -1
- package/docs/plans/cyberskill-design-system-audit-and-12-month-evolution-plan.md +1490 -0
- package/docs/quality-gates.md +20 -8
- package/docs/release-notes.md +2 -2
- package/docs/status/data/status-feed.json +1 -1
- package/docs/status/index.html +9 -5
- package/docs/status/status-legacy.html +12 -7
- package/docs/sync.md +1 -1
- package/docs/tasks/_state/commit-links.yaml +14 -0
- package/docs/vi/benchmark-rubric.md +1 -1
- package/docs/vi/ci-cd.md +3 -1
- package/docs/vi/consuming.md +6 -6
- package/docs/vi/conventions.md +2 -2
- package/docs/vi/decisions.md +4 -4
- package/docs/vi/quality-gates.md +21 -9
- package/docs/vi/release-notes.md +2 -2
- package/docs/vi/sync.md +1 -1
- package/guidelines/atomic-view.html +11 -7
- package/llms.txt +2 -2
- package/package.json +14 -6
- package/templates/_ds-base.canonical.js +55 -0
- package/templates/ai-cluster-demo.html +2 -2
- package/templates/app-shell/AppShell.dc.html +5 -3
- package/templates/app-shell/ds-base.js +33 -1
- package/templates/app-shell/support.js +13 -20
- package/templates/article/Article.dc.html +5 -1
- package/templates/article/ds-base.js +33 -1
- package/templates/article/support.js +13 -20
- package/templates/auth/Auth.dc.html +10 -5
- package/templates/auth/content-schema.json +12 -0
- package/templates/auth/ds-base.js +33 -1
- package/templates/auth/support.js +13 -20
- package/templates/bod-deck/BodDeck.dc.html +11 -10
- package/templates/bod-deck/ds-base.js +33 -1
- package/templates/bod-deck/support.js +13 -20
- package/templates/bod-investor-update/BodInvestorUpdate.dc.html +4 -3
- package/templates/bod-investor-update/ds-base.js +33 -1
- package/templates/bod-investor-update/support.js +13 -20
- package/templates/bod-memo/BodMemo.dc.html +6 -5
- package/templates/bod-memo/ds-base.js +33 -1
- package/templates/bod-memo/support.js +13 -20
- package/templates/bod-minutes/BodMinutes.dc.html +2 -1
- package/templates/bod-minutes/ds-base.js +33 -1
- package/templates/bod-minutes/support.js +13 -20
- package/templates/bod-report/BodReport.dc.html +3 -2
- package/templates/bod-report/ds-base.js +33 -1
- package/templates/bod-report/support.js +13 -20
- package/templates/bod-resolution/BodResolution.dc.html +5 -4
- package/templates/bod-resolution/ds-base.js +33 -1
- package/templates/bod-resolution/support.js +13 -20
- package/templates/culture-event-invite/CultureEventInvite.dc.html +3 -2
- package/templates/culture-event-invite/ds-base.js +33 -1
- package/templates/culture-event-invite/support.js +13 -20
- package/templates/dashboard/Dashboard.dc.html +7 -3
- package/templates/dashboard/ds-base.js +33 -1
- package/templates/dashboard/support.js +13 -20
- package/templates/delivery-change-note/DeliveryChangeNote.dc.html +2 -1
- package/templates/delivery-change-note/ds-base.js +33 -1
- package/templates/delivery-change-note/support.js +13 -20
- package/templates/delivery-kickoff/DeliveryKickoff.dc.html +3 -2
- package/templates/delivery-kickoff/ds-base.js +33 -1
- package/templates/delivery-kickoff/support.js +13 -20
- package/templates/delivery-qbr-deck/DeliveryQbrDeck.dc.html +6 -5
- package/templates/delivery-qbr-deck/ds-base.js +33 -1
- package/templates/delivery-qbr-deck/support.js +13 -20
- package/templates/delivery-runbook/DeliveryRunbook.dc.html +3 -2
- package/templates/delivery-runbook/ds-base.js +33 -1
- package/templates/delivery-runbook/support.js +13 -20
- package/templates/delivery-status-email/DeliveryStatusEmail.dc.html +3 -2
- package/templates/delivery-status-email/ds-base.js +33 -1
- package/templates/delivery-status-email/support.js +13 -20
- package/templates/doc-style-guide/DocStyleGuide.dc.html +67 -64
- package/templates/doc-style-guide/ds-base.js +33 -1
- package/templates/doc-style-guide/support.js +13 -20
- package/templates/doc-suite-index/DocSuiteIndex.dc.html +46 -45
- package/templates/doc-suite-index/ds-base.js +33 -1
- package/templates/doc-suite-index/support.js +13 -20
- package/templates/doc-templates/DocTemplates.dc.html +42 -41
- package/templates/doc-templates/ds-base.js +33 -1
- package/templates/doc-templates/support.js +13 -20
- package/templates/email/Email.dc.html +3 -2
- package/templates/email/ds-base.js +33 -1
- package/templates/email/support.js +13 -20
- package/templates/finance-dunning-email/FinanceDunningEmail.dc.html +4 -3
- package/templates/finance-dunning-email/ds-base.js +33 -1
- package/templates/finance-dunning-email/support.js +13 -20
- package/templates/finance-expense-report/FinanceExpenseReport.dc.html +4 -3
- package/templates/finance-expense-report/ds-base.js +33 -1
- package/templates/finance-expense-report/support.js +13 -20
- package/templates/finance-invoice/FinanceInvoice.dc.html +4 -3
- package/templates/finance-invoice/ds-base.js +33 -1
- package/templates/finance-invoice/support.js +13 -20
- package/templates/finance-quote/FinanceQuote.dc.html +4 -3
- package/templates/finance-quote/ds-base.js +33 -1
- package/templates/finance-quote/support.js +13 -20
- package/templates/hr-announcement/HrAnnouncement.dc.html +5 -4
- package/templates/hr-announcement/ds-base.js +33 -1
- package/templates/hr-announcement/support.js +13 -20
- package/templates/hr-interview-kit/HrInterviewKit.dc.html +4 -3
- package/templates/hr-interview-kit/ds-base.js +33 -1
- package/templates/hr-interview-kit/support.js +13 -20
- package/templates/hr-offboarding/HrOffboarding.dc.html +2 -1
- package/templates/hr-offboarding/ds-base.js +33 -1
- package/templates/hr-offboarding/support.js +13 -20
- package/templates/hr-performance-review/HrPerformanceReview.dc.html +2 -1
- package/templates/hr-performance-review/ds-base.js +33 -1
- package/templates/hr-performance-review/support.js +13 -20
- package/templates/hr-pip/HrPip.dc.html +2 -1
- package/templates/hr-pip/ds-base.js +33 -1
- package/templates/hr-pip/support.js +13 -20
- package/templates/kitchen-sink.html +9 -4
- package/templates/legal-msa/LegalMsa.dc.html +2 -1
- package/templates/legal-msa/ds-base.js +33 -1
- package/templates/legal-msa/support.js +13 -20
- package/templates/legal-sow/LegalSow.dc.html +2 -1
- package/templates/legal-sow/ds-base.js +33 -1
- package/templates/legal-sow/support.js +13 -20
- package/templates/marketing-campaign-brief/MarketingCampaignBrief.dc.html +3 -2
- package/templates/marketing-campaign-brief/ds-base.js +33 -1
- package/templates/marketing-campaign-brief/support.js +13 -20
- package/templates/marketing-case-study/MarketingCaseStudy.dc.html +5 -4
- package/templates/marketing-case-study/ds-base.js +33 -1
- package/templates/marketing-case-study/support.js +13 -20
- package/templates/marketing-launch/MarketingLaunch.dc.html +6 -5
- package/templates/marketing-launch/ds-base.js +33 -1
- package/templates/marketing-launch/support.js +13 -20
- package/templates/marketing-newsletter/MarketingNewsletter.dc.html +13 -12
- package/templates/marketing-newsletter/ds-base.js +33 -1
- package/templates/marketing-newsletter/support.js +13 -20
- package/templates/marketing-page/MarketingPage.dc.html +17 -12
- package/templates/marketing-page/ds-base.js +33 -1
- package/templates/marketing-page/support.js +13 -20
- package/templates/marketing-press-release/MarketingPressRelease.dc.html +2 -1
- package/templates/marketing-press-release/ds-base.js +33 -1
- package/templates/marketing-press-release/support.js +13 -20
- package/templates/marketing-social-kit/MarketingSocialKit.dc.html +5 -4
- package/templates/marketing-social-kit/ds-base.js +33 -1
- package/templates/marketing-social-kit/support.js +13 -20
- package/templates/sales-one-pager/SalesOnePager.dc.html +5 -4
- package/templates/sales-one-pager/ds-base.js +33 -1
- package/templates/sales-one-pager/support.js +13 -20
- package/templates/sales-proposal-deck/SalesProposalDeck.dc.html +7 -6
- package/templates/sales-proposal-deck/ds-base.js +33 -1
- package/templates/sales-proposal-deck/support.js +13 -20
- package/templates/settings/Settings.dc.html +5 -1
- package/templates/settings/ds-base.js +33 -1
- package/templates/settings/support.js +13 -20
- package/templates/slide-deck/SlideDeck.dc.html +5 -4
- package/templates/slide-deck/ds-base.js +33 -1
- package/templates/slide-deck/support.js +13 -20
- package/templates/team-meeting-agenda/TeamMeetingAgenda.dc.html +2 -1
- package/templates/team-meeting-agenda/ds-base.js +33 -1
- package/templates/team-meeting-agenda/support.js +13 -20
- package/templates/tech-incident-report/TechIncidentReport.dc.html +3 -2
- package/templates/tech-incident-report/ds-base.js +33 -1
- package/templates/tech-incident-report/support.js +13 -20
- package/templates/tech-release-notes/TechReleaseNotes.dc.html +6 -5
- package/templates/tech-release-notes/ds-base.js +33 -1
- package/templates/tech-release-notes/support.js +13 -20
- package/templates/tech-retro/TechRetro.dc.html +4 -3
- package/templates/tech-retro/ds-base.js +33 -1
- package/templates/tech-retro/support.js +13 -20
- package/templates/tech-rfc/TechRfc.dc.html +3 -2
- package/templates/tech-rfc/ds-base.js +33 -1
- package/templates/tech-rfc/support.js +13 -20
- package/templates/vn-appointment-transfer/VnAppointmentTransfer.dc.html +36 -35
- package/templates/vn-appointment-transfer/ds-base.js +33 -1
- package/templates/vn-appointment-transfer/support.js +13 -20
- package/templates/vn-certificate-of-employment/VnCertificateOfEmployment.dc.html +27 -26
- package/templates/vn-certificate-of-employment/ds-base.js +33 -1
- package/templates/vn-certificate-of-employment/support.js +13 -20
- package/templates/vn-code-of-conduct/VnCodeOfConduct.dc.html +44 -43
- package/templates/vn-code-of-conduct/ds-base.js +33 -1
- package/templates/vn-code-of-conduct/support.js +13 -20
- package/templates/vn-compensation-regulation/VnCompensationRegulation.dc.html +53 -52
- package/templates/vn-compensation-regulation/ds-base.js +33 -1
- package/templates/vn-compensation-regulation/support.js +13 -20
- package/templates/vn-contract-amendment/VnContractAmendment.dc.html +41 -40
- package/templates/vn-contract-amendment/ds-base.js +33 -1
- package/templates/vn-contract-amendment/support.js +13 -20
- package/templates/vn-contractor-agreement/VnContractorAgreement.dc.html +50 -49
- package/templates/vn-contractor-agreement/ds-base.js +33 -1
- package/templates/vn-contractor-agreement/support.js +13 -20
- package/templates/vn-data-protection-policy/VnDataProtectionPolicy.dc.html +54 -53
- package/templates/vn-data-protection-policy/ds-base.js +33 -1
- package/templates/vn-data-protection-policy/support.js +13 -20
- package/templates/vn-disciplinary-case-file/VnDisciplinaryCaseFile.dc.html +72 -71
- package/templates/vn-disciplinary-case-file/ds-base.js +33 -1
- package/templates/vn-disciplinary-case-file/support.js +13 -20
- package/templates/vn-disciplinary-schedule/VnDisciplinarySchedule.dc.html +21 -20
- package/templates/vn-disciplinary-schedule/ds-base.js +33 -1
- package/templates/vn-disciplinary-schedule/support.js +13 -20
- package/templates/vn-employee-request/VnEmployeeRequest.dc.html +54 -53
- package/templates/vn-employee-request/ds-base.js +33 -1
- package/templates/vn-employee-request/support.js +13 -20
- package/templates/vn-exit-handover/VnExitHandover.dc.html +122 -121
- package/templates/vn-exit-handover/ds-base.js +33 -1
- package/templates/vn-exit-handover/support.js +13 -20
- package/templates/vn-foreign-employee-pack/VnForeignEmployeePack.dc.html +31 -30
- package/templates/vn-foreign-employee-pack/ds-base.js +33 -1
- package/templates/vn-foreign-employee-pack/support.js +13 -20
- package/templates/vn-grassroots-democracy/VnGrassrootsDemocracy.dc.html +54 -53
- package/templates/vn-grassroots-democracy/ds-base.js +33 -1
- package/templates/vn-grassroots-democracy/support.js +13 -20
- package/templates/vn-infosec-policy/VnInfosecPolicy.dc.html +50 -49
- package/templates/vn-infosec-policy/ds-base.js +33 -1
- package/templates/vn-infosec-policy/support.js +13 -20
- package/templates/vn-internal-labor-regulations/VnInternalLaborRegulations.dc.html +84 -83
- package/templates/vn-internal-labor-regulations/ds-base.js +33 -1
- package/templates/vn-internal-labor-regulations/support.js +13 -20
- package/templates/vn-internship-agreement/VnInternshipAgreement.dc.html +44 -43
- package/templates/vn-internship-agreement/ds-base.js +33 -1
- package/templates/vn-internship-agreement/support.js +13 -20
- package/templates/vn-job-description/VnJobDescription.dc.html +28 -27
- package/templates/vn-job-description/ds-base.js +33 -1
- package/templates/vn-job-description/support.js +13 -20
- package/templates/vn-labor-contract/VnLaborContract.dc.html +109 -108
- package/templates/vn-labor-contract/ds-base.js +33 -1
- package/templates/vn-labor-contract/support.js +13 -20
- package/templates/vn-labour-management-book/VnLabourManagementBook.dc.html +32 -31
- package/templates/vn-labour-management-book/ds-base.js +33 -1
- package/templates/vn-labour-management-book/support.js +13 -20
- package/templates/vn-mutual-nda/VnMutualNda.dc.html +45 -44
- package/templates/vn-mutual-nda/ds-base.js +33 -1
- package/templates/vn-mutual-nda/support.js +13 -20
- package/templates/vn-ndnca-ip/VnNdncaIp.dc.html +73 -72
- package/templates/vn-ndnca-ip/ds-base.js +33 -1
- package/templates/vn-ndnca-ip/support.js +13 -20
- package/templates/vn-offer-letter/VnOfferLetter.dc.html +32 -31
- package/templates/vn-offer-letter/ds-base.js +33 -1
- package/templates/vn-offer-letter/support.js +13 -20
- package/templates/vn-onboarding-checklist/VnOnboardingChecklist.dc.html +16 -15
- package/templates/vn-onboarding-checklist/ds-base.js +33 -1
- package/templates/vn-onboarding-checklist/support.js +13 -20
- package/templates/vn-pdpl-consent/VnPdplConsent.dc.html +43 -42
- package/templates/vn-pdpl-consent/ds-base.js +33 -1
- package/templates/vn-pdpl-consent/support.js +13 -20
- package/templates/vn-performance-evaluation-regulation/VnPerformanceEvaluationRegulation.dc.html +65 -64
- package/templates/vn-performance-evaluation-regulation/ds-base.js +33 -1
- package/templates/vn-performance-evaluation-regulation/support.js +13 -20
- package/templates/vn-performance-review-form/VnPerformanceReviewForm.dc.html +49 -48
- package/templates/vn-performance-review-form/ds-base.js +33 -1
- package/templates/vn-performance-review-form/support.js +13 -20
- package/templates/vn-phantom-stock/VnPhantomStock.dc.html +41 -40
- package/templates/vn-phantom-stock/ds-base.js +33 -1
- package/templates/vn-phantom-stock/support.js +13 -20
- package/templates/vn-probation-contract/VnProbationContract.dc.html +56 -55
- package/templates/vn-probation-contract/ds-base.js +33 -1
- package/templates/vn-probation-contract/support.js +13 -20
- package/templates/vn-receipt-acknowledgement/VnReceiptAcknowledgement.dc.html +28 -27
- package/templates/vn-receipt-acknowledgement/ds-base.js +33 -1
- package/templates/vn-receipt-acknowledgement/support.js +13 -20
- package/templates/vn-remote-work-policy/VnRemoteWorkPolicy.dc.html +44 -43
- package/templates/vn-remote-work-policy/ds-base.js +33 -1
- package/templates/vn-remote-work-policy/support.js +13 -20
- package/templates/vn-resignation-letter/VnResignationLetter.dc.html +20 -19
- package/templates/vn-resignation-letter/ds-base.js +33 -1
- package/templates/vn-resignation-letter/support.js +13 -20
- package/templates/vn-salary-scale/VnSalaryScale.dc.html +39 -38
- package/templates/vn-salary-scale/ds-base.js +33 -1
- package/templates/vn-salary-scale/support.js +13 -20
- package/templates/vn-sow-appendix/VnSowAppendix.dc.html +21 -20
- package/templates/vn-sow-appendix/ds-base.js +33 -1
- package/templates/vn-sow-appendix/support.js +13 -20
- package/templates/vn-termination-decision/VnTerminationDecision.dc.html +25 -24
- package/templates/vn-termination-decision/ds-base.js +33 -1
- package/templates/vn-termination-decision/support.js +13 -20
- package/templates/vn-total-rewards-appendix/VnTotalRewardsAppendix.dc.html +63 -62
- package/templates/vn-total-rewards-appendix/ds-base.js +33 -1
- package/templates/vn-total-rewards-appendix/support.js +13 -20
- package/templates/vn-training-commitment/VnTrainingCommitment.dc.html +39 -38
- package/templates/vn-training-commitment/ds-base.js +33 -1
- package/templates/vn-training-commitment/support.js +13 -20
- package/templates/vn-travel-expense-policy/VnTravelExpensePolicy.dc.html +50 -49
- package/templates/vn-travel-expense-policy/ds-base.js +33 -1
- package/templates/vn-travel-expense-policy/support.js +13 -20
- package/tokens/colors.css +19 -1
- package/tokens/component-tokens.css +1 -0
- package/tokens/elements.css +35 -2
- package/tokens/elevation.css +8 -2
- package/tokens/native/CSTokens.kt +35 -1
- package/tokens/native/CSTokens.swift +35 -1
- package/tokens/native/cs_tokens.dart +35 -1
- package/tokens/provenance.json +12 -12
- package/tokens/spacing.css +2 -0
- package/tokens/tokens.dtcg.json +111 -3
- package/tokens/tokens.js +46 -6
- package/tokens/tokens.json +45 -5
- package/tokens/typography.css +2 -0
- package/ui_kits/deck/index.html +4 -0
- package/ui_kits/status-hub/StatusHub.jsx +30 -4
- package/ui_kits/status-hub/index.html +3 -3
- package/ui_kits/status-hub/login.html +4 -0
- package/ui_kits/status-hub/project.html +4 -0
- package/ui_kits/status-hub/settings.html +35 -13
- package/ui_kits/status-hub/status.css +5 -1
- package/ui_kits/website/Website.jsx +25 -3
- package/ui_kits/website/careers.html +4 -0
- package/ui_kits/website/chat.html +5 -3
- package/ui_kits/website/index.html +3 -3
- package/ui_kits/website/site.css +2 -2
- package/ui_kits/website/work.html +4 -0
|
@@ -1070,16 +1070,15 @@
|
|
|
1070
1070
|
}
|
|
1071
1071
|
|
|
1072
1072
|
// src/cdn.ts
|
|
1073
|
-
var
|
|
1074
|
-
var
|
|
1075
|
-
var
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
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[
|
|
1082
|
-
return typeof v === "string" && v ?
|
|
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
|
|
1108
|
+
const src = localScriptFor(BABEL_LOCAL);
|
|
1110
1109
|
babelLoading = new Promise((res, rej) => {
|
|
1111
1110
|
const s = document.createElement("script");
|
|
1112
|
-
s.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(
|
|
1775
|
-
loadScript(
|
|
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 · Launch announcement · 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,10 +14,10 @@
|
|
|
13
14
|
</helmet>
|
|
14
15
|
<div data-theme="{{ rootTheme }}" lang="{{ langAttr }}" data-cs-element="{{ elAttr }}" data-cs-variant="{{ vaAttr }}" style="background:#efe6d8;padding:32px 16px;font-family:var(--cs-font-family-ui);color:var(--cs-color-text-primary);min-height:100vh">
|
|
15
16
|
<div style="max-width:640px;margin:0 auto;background:var(--cs-color-surface-panel);border-radius:16px;overflow:hidden;box-shadow:var(--cs-shadow-sm)">
|
|
16
|
-
<div style="position:relative;overflow:hidden;background:var(--cs-
|
|
17
|
+
<div style="position:relative;overflow:hidden;background:var(--cs-color-brand-umber);text-align:center;padding:44px 32px 40px">
|
|
17
18
|
<div class="cs-aurora-wash" style="position:absolute;inset:0;opacity:0.5"></div>
|
|
18
19
|
<div style="position:absolute;inset:0;background:linear-gradient(180deg,rgba(26,17,8,0.25),rgba(26,17,8,0.82))"></div>
|
|
19
|
-
<div style="position:relative;z-index:1;color:#
|
|
20
|
+
<div style="position:relative;z-index:1;color:#FFFDF8">
|
|
20
21
|
<div style="display:inline-flex;align-items:center;gap:10px;margin-bottom:20px"><x-import component-from-global-scope="CyberSkillDS.Logo" size="30" hint-size="30px,30px"></x-import><span style="font-weight:800;font-size:16px">CyberSkill</span></div>
|
|
21
22
|
<sc-if value="{{ isEN }}" hint-placeholder-val="{{ true }}">
|
|
22
23
|
<div style="font-size:12px;font-weight:700;text-transform:uppercase;letter-spacing:0.14em;color:var(--cs-accent-bright)">Now live</div>
|
|
@@ -39,7 +40,7 @@
|
|
|
39
40
|
<div style="display:flex;gap:14px;align-items:flex-start"><span style="flex:none;width:38px;height:38px;border-radius:10px;background:var(--cs-accent-tint);color:var(--cs-color-text-accent);display:grid;place-items:center;font-weight:800">✓</span><div><div style="font-weight:700;font-size:16px">Handed to real people</div><div style="font-size:14px;color:var(--cs-color-text-muted);line-height:1.5">A clear wish goes to the team — human in the loop.</div></div></div>
|
|
40
41
|
</div>
|
|
41
42
|
<div style="text-align:center;margin-bottom:24px">
|
|
42
|
-
<a href="#" style="display:inline-block;background:var(--cs-accent-strong);color:var(--cs-accent-on);font-weight:700;font-size:16px;text-decoration:none;padding:15px 32px;border-radius:var(--cs-radius-full)">Talk to Lumi →</a>
|
|
43
|
+
<a href="#" style="display:inline-block;background:var(--cs-accent-strong);color:var(--cs-accent-on-strong);font-weight:700;font-size:16px;text-decoration:none;padding:15px 32px;border-radius:var(--cs-radius-full)">Talk to Lumi →</a>
|
|
43
44
|
</div>
|
|
44
45
|
<blockquote style="margin:0;background:var(--cs-color-surface-raised);border-left:4px solid var(--cs-accent);border-radius:var(--cs-radius-md);padding:16px 20px;font-size:15px;line-height:1.6;font-style:italic">“We described a checkout in two sentences. Two weeks later it shipped.”<br /><span style="font-style:normal;font-size:13px;color:var(--cs-color-text-muted)">— Product lead, Retailer A</span></blockquote>
|
|
45
46
|
</sc-if>
|
|
@@ -51,7 +52,7 @@
|
|
|
51
52
|
<div style="display:flex;gap:14px;align-items:flex-start"><span style="flex:none;width:38px;height:38px;border-radius:10px;background:var(--cs-accent-tint);color:var(--cs-color-text-accent);display:grid;place-items:center;font-weight:800">✓</span><div><div style="font-weight:700;font-size:16px">Trao cho người thật</div><div style="font-size:14px;color:var(--cs-color-text-muted);line-height:1.6">Điều ước rõ ràng đến tay đội ngũ — luôn có con người trong vòng lặp.</div></div></div>
|
|
52
53
|
</div>
|
|
53
54
|
<div style="text-align:center;margin-bottom:24px">
|
|
54
|
-
<a href="#" style="display:inline-block;background:var(--cs-accent-strong);color:var(--cs-accent-on);font-weight:700;font-size:16px;text-decoration:none;padding:15px 32px;border-radius:var(--cs-radius-full)">Trò chuyện với Lumi →</a>
|
|
55
|
+
<a href="#" style="display:inline-block;background:var(--cs-accent-strong);color:var(--cs-accent-on-strong);font-weight:700;font-size:16px;text-decoration:none;padding:15px 32px;border-radius:var(--cs-radius-full)">Trò chuyện với Lumi →</a>
|
|
55
56
|
</div>
|
|
56
57
|
<blockquote style="margin:0;background:var(--cs-color-surface-raised);border-left:4px solid var(--cs-accent);border-radius:var(--cs-radius-md);padding:16px 20px;font-size:15px;line-height:1.65;font-style:italic">“Chúng tôi mô tả trang thanh toán trong hai câu. Hai tuần sau nó đã chạy.”<br /><span style="font-style:normal;font-size:13px;color:var(--cs-color-text-muted)">— Trưởng sản phẩm, Retailer A</span></blockquote>
|
|
57
58
|
</div></sc-if>
|
|
@@ -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
|
|
1074
|
-
var
|
|
1075
|
-
var
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
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[
|
|
1082
|
-
return typeof v === "string" && v ?
|
|
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
|
|
1108
|
+
const src = localScriptFor(BABEL_LOCAL);
|
|
1110
1109
|
babelLoading = new Promise((res, rej) => {
|
|
1111
1110
|
const s = document.createElement("script");
|
|
1112
|
-
s.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(
|
|
1775
|
-
loadScript(
|
|
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 · Newsletter · 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,15 +14,15 @@
|
|
|
13
14
|
</helmet>
|
|
14
15
|
<div data-theme="{{ rootTheme }}" lang="{{ langAttr }}" data-cs-element="{{ elAttr }}" data-cs-variant="{{ vaAttr }}" style="background:#efe6d8;padding:32px 16px;font-family:var(--cs-font-family-ui);color:var(--cs-color-text-primary);min-height:100vh">
|
|
15
16
|
<div style="max-width:640px;margin:0 auto;background:var(--cs-color-surface-panel);border-radius:16px;overflow:hidden;box-shadow:var(--cs-shadow-sm)">
|
|
16
|
-
<div style="background:var(--cs-
|
|
17
|
+
<div style="background:var(--cs-color-brand-umber);padding:22px 32px;display:flex;align-items:center;gap:12px">
|
|
17
18
|
<x-import component-from-global-scope="CyberSkillDS.Logo" size="28" hint-size="28px,28px"></x-import>
|
|
18
|
-
<span style="color:#
|
|
19
|
-
<span style="margin-left:auto;text-align:right;color:#
|
|
19
|
+
<span style="color:#FFFDF8;font-weight:800;font-size:16px">The Lamp</span>
|
|
20
|
+
<span style="margin-left:auto;text-align:right;color:#FFFDF8;font-size:13px;font-family:var(--cs-font-family-mono)"><sc-if value="{{ isEN }}" hint-placeholder-val="{{ true }}"><span style="display:block">Issue 12 · July 2026</span></sc-if><sc-if value="{{ isVN }}"><span lang="vi" style="display:block">Số 12 · Tháng 7 2026</span></sc-if></span>
|
|
20
21
|
</div>
|
|
21
|
-
<div style="position:relative;overflow:hidden;background:var(--cs-
|
|
22
|
+
<div style="position:relative;overflow:hidden;background:var(--cs-color-brand-umber)">
|
|
22
23
|
<div class="cs-aurora-wash" style="position:absolute;inset:0;opacity:0.5"></div>
|
|
23
24
|
<div style="position:absolute;inset:0;background:linear-gradient(180deg,rgba(26,17,8,0.25),rgba(26,17,8,0.8))"></div>
|
|
24
|
-
<div style="position:relative;z-index:1;padding:32px;color:#
|
|
25
|
+
<div style="position:relative;z-index:1;padding:32px;color:#FFFDF8">
|
|
25
26
|
<sc-if value="{{ isEN }}" hint-placeholder-val="{{ true }}">
|
|
26
27
|
<div style="font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:0.12em;color:var(--cs-accent-bright)">This month</div>
|
|
27
28
|
<h1 style="font-size:26px;font-weight:800;letter-spacing:-0.02em;line-height:1.2;margin:8px 0 8px">Liquid Glass, now in every build</h1>
|
|
@@ -37,7 +38,7 @@
|
|
|
37
38
|
</div>
|
|
38
39
|
<div style="padding:28px 32px">
|
|
39
40
|
<sc-if value="{{ isEN }}" hint-placeholder-val="{{ true }}">
|
|
40
|
-
<a href="#" style="display:inline-block;background:var(--cs-
|
|
41
|
+
<a href="#" style="display:inline-block;background:var(--cs-color-brand-umber);color:#FFFDF8;font-weight:700;font-size:15px;text-decoration:none;padding:12px 22px;border-radius:var(--cs-radius-full);margin-bottom:26px">Read the story →</a>
|
|
41
42
|
<div style="border-top:1px solid var(--cs-color-border-default);padding-top:20px;margin-bottom:20px">
|
|
42
43
|
<div style="font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:0.1em;color:var(--cs-color-text-accent);margin-bottom:6px">Field notes</div>
|
|
43
44
|
<h2 style="font-size:19px;font-weight:700;margin:0 0 6px">How we grant a wish in four steps</h2>
|
|
@@ -53,7 +54,7 @@
|
|
|
53
54
|
</sc-if>
|
|
54
55
|
<sc-if value="{{ isVN }}"><div lang="vi" style="display:contents">
|
|
55
56
|
<sc-if value="{{ isBoth }}"><div style="border-top:1px solid var(--cs-color-border-default);margin:0 0 20px"></div></sc-if>
|
|
56
|
-
<a href="#" style="display:inline-block;background:var(--cs-
|
|
57
|
+
<a href="#" style="display:inline-block;background:var(--cs-color-brand-umber);color:#FFFDF8;font-weight:700;font-size:15px;text-decoration:none;padding:12px 22px;border-radius:var(--cs-radius-full);margin-bottom:26px">Đọc câu chuyện →</a>
|
|
57
58
|
<div style="border-top:1px solid var(--cs-color-border-default);padding-top:20px;margin-bottom:20px">
|
|
58
59
|
<div style="font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:0.1em;color:var(--cs-color-text-accent);margin-bottom:6px">Ghi chú thực địa</div>
|
|
59
60
|
<h2 style="font-size:19px;font-weight:700;margin:0 0 6px">Cách chúng tôi thực hiện một điều ước trong bốn bước</h2>
|
|
@@ -68,17 +69,17 @@
|
|
|
68
69
|
</div>
|
|
69
70
|
</div></sc-if>
|
|
70
71
|
</div>
|
|
71
|
-
<div style="background:var(--cs-
|
|
72
|
+
<div style="background:var(--cs-color-brand-umber);color:#FFFDF8;padding:24px 32px;text-align:center">
|
|
72
73
|
<sc-if value="{{ isEN }}" hint-placeholder-val="{{ true }}">
|
|
73
|
-
<div style="font-size:17px;font-weight:700;color
|
|
74
|
+
<div style="font-size:17px;font-weight:700;color:#FFFDF8;margin-bottom:4px">Have a wish of your own?</div>
|
|
74
75
|
<p style="font-size:14px;opacity:0.85;margin:0 0 14px">Tell us the outcome in a sentence. We reply within one business day.</p>
|
|
75
|
-
<a href="#" style="display:inline-block;background:var(--cs-
|
|
76
|
+
<a href="#" style="display:inline-block;background:var(--cs-color-brand-umber);color:#FFFDF8;font-weight:700;font-size:14px;text-decoration:none;padding:11px 22px;border-radius:var(--cs-radius-full)">Make a wish</a>
|
|
76
77
|
</sc-if>
|
|
77
78
|
<sc-if value="{{ isVN }}"><div lang="vi" style="display:contents">
|
|
78
79
|
<sc-if value="{{ isBoth }}"><div style="height:1px;background:rgba(255,255,255,0.18);margin:0 auto 16px;max-width:200px"></div></sc-if>
|
|
79
80
|
<div style="font-size:17px;font-weight:700;color:var(--cs-accent-bright);margin-bottom:4px">Bạn có điều ước của riêng mình?</div>
|
|
80
81
|
<p style="font-size:14px;opacity:0.85;margin:0 0 14px">Kể cho chúng tôi kết quả bạn muốn trong một câu. Chúng tôi trả lời trong vòng một ngày làm việc.</p>
|
|
81
|
-
<a href="#" style="display:inline-block;background:var(--cs-
|
|
82
|
+
<a href="#" style="display:inline-block;background:var(--cs-color-brand-umber);color:#FFFDF8;font-weight:700;font-size:14px;text-decoration:none;padding:11px 22px;border-radius:var(--cs-radius-full)">Gửi điều ước</a>
|
|
82
83
|
</div></sc-if>
|
|
83
84
|
</div>
|
|
84
85
|
<div style="padding:16px 32px;background:var(--cs-color-surface-raised);font-size:12px;color:var(--cs-color-text-muted);text-align:center">
|
|
@@ -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
|
|
1074
|
-
var
|
|
1075
|
-
var
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
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[
|
|
1082
|
-
return typeof v === "string" && v ?
|
|
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
|
|
1108
|
+
const src = localScriptFor(BABEL_LOCAL);
|
|
1110
1109
|
babelLoading = new Promise((res, rej) => {
|
|
1111
1110
|
const s = document.createElement("script");
|
|
1112
|
-
s.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(
|
|
1775
|
-
loadScript(
|
|
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 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">Skip to content</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-
|
|
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:#
|
|
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
|
|
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-
|
|
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:#
|
|
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
|
|
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="{
|
|
@@ -123,7 +127,8 @@ const vn = this.props.language === "Tiếng Việt";
|
|
|
123
127
|
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
128
|
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" };
|
|
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
|
-
|
|
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
|
}
|
|
@@ -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
|
|
1074
|
-
var
|
|
1075
|
-
var
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
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[
|
|
1082
|
-
return typeof v === "string" && v ?
|
|
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
|
|
1108
|
+
const src = localScriptFor(BABEL_LOCAL);
|
|
1110
1109
|
babelLoading = new Promise((res, rej) => {
|
|
1111
1110
|
const s = document.createElement("script");
|
|
1112
|
-
s.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(
|
|
1775
|
-
loadScript(
|
|
1767
|
+
loadScript(localScriptFor(REACT_LOCAL)),
|
|
1768
|
+
loadScript(localScriptFor(REACT_DOM_LOCAL))
|
|
1776
1769
|
]).then(() => void 0);
|
|
1777
1770
|
}
|
|
1778
1771
|
function init() {
|