@cyberskill/design 1.7.0 → 1.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/DESIGN.md CHANGED
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: "CyberSkill Design System"
3
- version: "1.7.0"
3
+ version: "1.7.1"
4
4
  generated: "2026-07-23"
5
5
  generator: "scripts/generate-design-md.mjs (npm run build:design-md)"
6
6
  sources:
package/README.md CHANGED
@@ -6,7 +6,7 @@
6
6
 
7
7
  ## Start here
8
8
 
9
- This is the **entrance document** for the CyberSkill Design System — VERSION **1.7.0** (see `VERSION`). The **product site** is Storybook at **`/`** on `design.cyberskill.world` (host-only; local: `npm run storybook`). Operator documentation is published in the Storybook **Docs** sidebar (and the Documentation Library at `/docs/viewer.html`). Legacy `/dashboard`, `/dashboard.html`, and `/playground/*` redirect to `/`. One sentence: a warm, Vietnamese-first, enterprise-grade system where every surface resolves four independent axes — **Theme** (light · dark · system) × **Element** (Ngũ Hành product identity: Kim · Mộc · Thủy · Hỏa · Thổ, 15 variants) × **Language** (EN · VI) × **Style** (`data-cs-style` — sole pack **liquid-glass**; absent ≡ default).
9
+ This is the **entrance document** for the CyberSkill Design System — VERSION **1.7.1** (see `VERSION`). The **product site** is Storybook at **`/`** on `design.cyberskill.world` (host-only; local: `npm run storybook`). Operator documentation is published in the Storybook **Docs** sidebar (and the Documentation Library at `/docs/viewer.html`). Legacy `/dashboard`, `/dashboard.html`, and `/playground/*` redirect to `/`. One sentence: a warm, Vietnamese-first, enterprise-grade system where every surface resolves four independent axes — **Theme** (light · dark · system) × **Element** (Ngũ Hành product identity: Kim · Mộc · Thủy · Hỏa · Thổ, 15 variants) × **Language** (EN · VI) × **Style** (`data-cs-style` — sole pack **liquid-glass**; absent ≡ default).
10
10
 
11
11
  **Quick start by audience**
12
12
  - **Designers** — open Storybook (**Foundations / Components / Templates / Pages / Docs**). **Templates** lists all 85 starting points (Gallery → Atomic View, plus category stories including the 38-document VN A4 suite (Employment Suite + commercial framework) under **Templates → HR**). Flip Theme × Element × Language × Style live via the Storybook toolbar, Atomic View, and the Elements Geometry specimen.
@@ -15,7 +15,7 @@ This is the **entrance document** for the CyberSkill Design System — VERSION *
15
15
 
16
16
  - **Static / open-spec** (e.g. Google Stitch) — start at **`DESIGN.md`** (generated open-spec) → `llms.txt` → `tokens/tokens.dtcg.json`. Build **static** UI with `styles.css` + `.cs-*` / kitchen-sink / `examples/static-hello/`. **Do not** treat `templates/**/*.dc.html` as source of truth.
17
17
 
18
- - **Implementers** — npm package **`@cyberskill/design@1.7.0`** (see `docs/consuming.md`; grant in `docs/consumer-grant.md` — still UNLICENSED). **Next/SSR:** `import { Button } from "@cyberskill/design"` (peer React). **Browser demo:** **`examples/npm-hello/`** (Lumi · Hỏa · plasma, legacy `_esm/cs.mjs`). Or link **`styles.css`** from a clone/subtree (one file = everything), or copy a `templates/<slug>/` folder and edit one line in its `ds-base.js` (one-line rebind, validated end-to-end Jul 2026). Scope identity with `data-theme` · `data-cs-element` (+`data-cs-variant`) · `lang`. Release signal: tip SHA + `docs/release-notes.md` (VERSION is **1.7.0**; no CHANGELOG).
18
+ - **Implementers** — npm package **`@cyberskill/design@1.7.1`** (see `docs/consuming.md`; grant in `docs/consumer-grant.md` — still UNLICENSED). **Next/SSR:** `import { Button } from "@cyberskill/design"` (peer React). **Browser demo:** **`examples/npm-hello/`** (Lumi · Hỏa · plasma, legacy `_esm/cs.mjs`). Or link **`styles.css`** from a clone/subtree (one file = everything), or copy a `templates/<slug>/` folder and edit one line in its `ds-base.js` (one-line rebind, validated end-to-end Jul 2026). Scope identity with `data-theme` · `data-cs-element` (+`data-cs-variant`) · `lang`. Release signal: tip SHA + `docs/release-notes.md` (VERSION is **1.7.1**; no CHANGELOG).
19
19
 
20
20
  - **Maintainers** — `docs/doctrine.md` (expansion + verification), then `CONTRIBUTING.md` and `docs/quality-gates.md`.
21
21
 
@@ -170,7 +170,7 @@ Copied assets live in `assets/`: `logo-mark.svg` / `logo-mark.png` (official mas
170
170
 
171
171
  Highlights: **Button** — Umber primary; variants primary/secondary/tertiary/ghost/danger/danger-ghost; sizes xs–lg; loading, icon, fullWidth. **TextField / Textarea / Select / NativeSelect** share one `.cs-field` frame (label + description/error; diacritic/IME-safe). **DataTable** — caption, scoped headers, per-column render, idle/loading/error/empty triad. **Card** — warm panel + header/body/footer. **Logo** renders the exact official mark; **Icon** drives the in-repo line-icon set. The **AI-native** family carries the brand's explainability doctrine — disclosure, human review, wish capture, and confidence, all stated in words (never colour alone).
172
172
 
173
- **Install / package name.** This monolith publishes as **`@cyberskill/design`** (live at **1.7.0**; grant in `docs/consumer-grant.md` governs *use* — package remains UNLICENSED). Do **not** install `@cyberskill/react` for this tree — that name is historical marketing-site inventory, not this package.
173
+ **Install / package name.** This monolith publishes as **`@cyberskill/design`** (live at **1.7.1**; grant in `docs/consumer-grant.md` governs *use* — package remains UNLICENSED). Do **not** install `@cyberskill/react` for this tree — that name is historical marketing-site inventory, not this package.
174
174
 
175
175
  **Source inventory vs. extensions.** An earlier CyberSkill surface shipped six primitives — `Button`, `TextField`, `Dialog`, `DataTable`, `AIDisclosureBadge`, `HumanReviewGate` — plus a brand `Logo`. Everything else in **this** package is an **intentional extension** built in the brand's own token vocabulary so consumers have a complete working kit: `Icon` (the marketing site's real in-repo line-icon set), the standard Forms / Feedback / Data / Navigation / Overlays primitives (search, stepper, slider, file upload, list, description list, timeline, accordion, kbd, code block, sidebar, steps, command palette, popover, drawer, and more), added AI-native pieces (`PromptInput`, `ChatMessage`, `ConfidenceMeter`, `PromptSuggestions`, `TypingIndicator`, `CitationList`) that formalise the Lumi wish-flow, and the `LumiAvatar` mascot. None invent new visual language — they reuse the anchors, surfaces, type, and motion already defined.
176
176
 
@@ -283,7 +283,7 @@ Every template resolves to one of six archetypes, framed by `templates/doc-templ
283
283
  ## Index / manifest
284
284
 
285
285
  ```
286
- styles.css ← single entry point (@import manifest only) · VERSION 1.7.0
286
+ styles.css ← single entry point (@import manifest only) · VERSION 1.7.1
287
287
  tokens/ fonts · colors · typography · spacing · elevation · motion · component-tokens · elements (Ngũ Hành packs)
288
288
  base/ reset · typography · components · forms · feedback · data · navigation · ai · controls · collections · shell · glass · interaction · a11y · responsive
289
289
  components/ button · textfield · dialog · datatable · forms · feedback · data · navigation · overlays · ai · logo · icon · brand
package/SKILL.md CHANGED
@@ -17,7 +17,7 @@ If the user invokes this skill without any other guidance, ask them what they wa
17
17
  | **Bundler React (Next/Vite/SSR)** | `docs/consuming.md` | `import { Button } from "@cyberskill/design"` + `styles.css`. React is a peer. |
18
18
  | **Maintainers** | `docs/doctrine.md` | Expansion + verification; Storybook Docs at `design.cyberskill.world`. |
19
19
 
20
- Dual-path detail: `docs/consuming.md`. Release signal: tip SHA + `docs/release-notes.md` (VERSION is **1.7.0**; no CHANGELOG).
20
+ Dual-path detail: `docs/consuming.md`. Release signal: tip SHA + `docs/release-notes.md` (VERSION is **1.7.1**; no CHANGELOG).
21
21
 
22
22
  - **`README.md`** — the entrance + design guide + manifest: anchor immutables, CONTENT FUNDAMENTALS (voice = warm/direct/honest/respectful, Vietnamese-first, the "wish" metaphor), VISUAL FOUNDATIONS, ICONOGRAPHY, and the component/kit index. Read it first.
23
23
 
@@ -63,7 +63,7 @@ Every artifact exports, all paths preserving Vietnamese Unicode (see `docs/conve
63
63
 
64
64
  - Voice stays warm/direct/honest/respectful — never fun/playful/edgy. Products are "wishes" that Lumi helps grant.
65
65
 
66
- - Expansion rule: when any set grows (element/variant, icon, component, language), update every deliverable in the same change — tokens, cards + related guidelines, contract trio, all template enums, Storybook toolbar / Atomic View, docs incl. every related document/README — and grep the old list to prove it. Full text: `docs/doctrine.md`. VERSION **1.7.0** (auto-bumps on `main`; owner may still force a bump; no changelog).
66
+ - Expansion rule: when any set grows (element/variant, icon, component, language), update every deliverable in the same change — tokens, cards + related guidelines, contract trio, all template enums, Storybook toolbar / Atomic View, docs incl. every related document/README — and grep the old list to prove it. Full text: `docs/doctrine.md`. VERSION **1.7.1** (auto-bumps on `main`; owner may still force a bump; no changelog).
67
67
 
68
68
  - **Stitch / non-DC tools must not consume `*.dc.html` as source of truth.** Those files need the Design Components compiler (tweaks, `x-import`, `__dcSetProps`). Generate static UI from `DESIGN.md` / DTCG / `styles.css` + `.cs-*` / kitchen-sink / `examples/static-hello/` instead. DC authoring requires a compiler session (Claude Design, or a full clone with the compiler).
69
69
 
package/VERSION CHANGED
@@ -1 +1 @@
1
- 1.7.0
1
+ 1.7.1
package/_ds_bundle.js CHANGED
@@ -1,4 +1,4 @@
1
- /* @ds-bundle: {"format":4,"namespace":"CyberSkillDesignSystem_847b3c","components":[{"name":"AIDisclosureBadge","sourcePath":"components/ai/AIDisclosureBadge.jsx"},{"name":"ChatMessage","sourcePath":"components/ai/ChatMessage.jsx"},{"name":"CitationList","sourcePath":"components/ai/CitationList.jsx"},{"name":"ConfidenceMeter","sourcePath":"components/ai/ConfidenceMeter.jsx"},{"name":"HumanReviewGate","sourcePath":"components/ai/HumanReviewGate.jsx"},{"name":"PromptInput","sourcePath":"components/ai/PromptInput.jsx"},{"name":"PromptSuggestions","sourcePath":"components/ai/PromptSuggestions.jsx"},{"name":"TypingIndicator","sourcePath":"components/ai/TypingIndicator.jsx"},{"name":"LumiAvatar","sourcePath":"components/brand/LumiAvatar.jsx"},{"name":"Button","sourcePath":"components/button/Button.jsx"},{"name":"ButtonGroup","sourcePath":"components/button/ButtonGroup.jsx"},{"name":"FloatingActionButton","sourcePath":"components/button/FloatingActionButton.jsx"},{"name":"Accordion","sourcePath":"components/data/Accordion.jsx"},{"name":"AspectRatio","sourcePath":"components/data/AspectRatio.jsx"},{"name":"Avatar","sourcePath":"components/data/Avatar.jsx"},{"name":"AvatarGroup","sourcePath":"components/data/Avatar.jsx"},{"name":"Card","sourcePath":"components/data/Card.jsx"},{"name":"CardHeader","sourcePath":"components/data/Card.jsx"},{"name":"CardBody","sourcePath":"components/data/Card.jsx"},{"name":"CardFooter","sourcePath":"components/data/Card.jsx"},{"name":"Carousel","sourcePath":"components/data/Carousel.jsx"},{"name":"Chart","sourcePath":"components/data/Chart.jsx"},{"name":"CodeBlock","sourcePath":"components/data/CodeBlock.jsx"},{"name":"Collapsible","sourcePath":"components/data/Collapsible.jsx"},{"name":"Comment","sourcePath":"components/data/Comment.jsx"},{"name":"DescriptionList","sourcePath":"components/data/DescriptionList.jsx"},{"name":"Divider","sourcePath":"components/data/Divider.jsx"},{"name":"Image","sourcePath":"components/data/Image.jsx"},{"name":"Item","sourcePath":"components/data/Item.jsx"},{"name":"Kbd","sourcePath":"components/data/Kbd.jsx"},{"name":"List","sourcePath":"components/data/List.jsx"},{"name":"ListItem","sourcePath":"components/data/List.jsx"},{"name":"Masonry","sourcePath":"components/data/Masonry.jsx"},{"name":"QRCode","sourcePath":"components/data/QRCode.jsx"},{"name":"ScrollArea","sourcePath":"components/data/ScrollArea.jsx"},{"name":"Sortable","sourcePath":"components/data/Sortable.jsx"},{"name":"Splitter","sourcePath":"components/data/Splitter.jsx"},{"name":"Stat","sourcePath":"components/data/Stat.jsx"},{"name":"Terminal","sourcePath":"components/data/Terminal.jsx"},{"name":"Timeline","sourcePath":"components/data/Timeline.jsx"},{"name":"Tooltip","sourcePath":"components/data/Tooltip.jsx"},{"name":"Tree","sourcePath":"components/data/Tree.jsx"},{"name":"Watermark","sourcePath":"components/data/Watermark.jsx"},{"name":"DataGrid","sourcePath":"components/datatable/DataGrid.jsx"},{"name":"DataTable","sourcePath":"components/datatable/DataTable.jsx"},{"name":"TreeTable","sourcePath":"components/datatable/TreeTable.jsx"},{"name":"Dialog","sourcePath":"components/dialog/Dialog.jsx"},{"name":"Alert","sourcePath":"components/feedback/Alert.jsx"},{"name":"Badge","sourcePath":"components/feedback/Badge.jsx"},{"name":"EmptyState","sourcePath":"components/feedback/EmptyState.jsx"},{"name":"ProgressBar","sourcePath":"components/feedback/ProgressBar.jsx"},{"name":"Result","sourcePath":"components/feedback/Result.jsx"},{"name":"Skeleton","sourcePath":"components/feedback/Skeleton.jsx"},{"name":"Spinner","sourcePath":"components/feedback/Spinner.jsx"},{"name":"StatusIndicator","sourcePath":"components/feedback/StatusIndicator.jsx"},{"name":"Tag","sourcePath":"components/feedback/Tag.jsx"},{"name":"ToastStack","sourcePath":"components/feedback/Toast.jsx"},{"name":"Toast","sourcePath":"components/feedback/Toast.jsx"},{"name":"Calendar","sourcePath":"components/forms/Calendar.jsx"},{"name":"Cascader","sourcePath":"components/forms/Cascader.jsx"},{"name":"Checkbox","sourcePath":"components/forms/Checkbox.jsx"},{"name":"ColorPicker","sourcePath":"components/forms/ColorPicker.jsx"},{"name":"Combobox","sourcePath":"components/forms/Combobox.jsx"},{"name":"DatePicker","sourcePath":"components/forms/DatePicker.jsx"},{"name":"Editor","sourcePath":"components/forms/Editor.jsx"},{"name":"FileUpload","sourcePath":"components/forms/FileUpload.jsx"},{"name":"Form","sourcePath":"components/forms/Form.jsx"},{"name":"FormField","sourcePath":"components/forms/Form.jsx"},{"name":"FormFieldArray","sourcePath":"components/forms/Form.jsx"},{"name":"FormWizard","sourcePath":"components/forms/Form.jsx"},{"name":"InlineEdit","sourcePath":"components/forms/InlineEdit.jsx"},{"name":"InputGroup","sourcePath":"components/forms/InputGroup.jsx"},{"name":"InputOTP","sourcePath":"components/forms/InputOTP.jsx"},{"name":"Mentions","sourcePath":"components/forms/Mentions.jsx"},{"name":"NativeSelect","sourcePath":"components/forms/NativeSelect.jsx"},{"name":"NumberField","sourcePath":"components/forms/NumberField.jsx"},{"name":"Radio","sourcePath":"components/forms/RadioGroup.jsx"},{"name":"RadioGroup","sourcePath":"components/forms/RadioGroup.jsx"},{"name":"Rating","sourcePath":"components/forms/Rating.jsx"},{"name":"SearchField","sourcePath":"components/forms/SearchField.jsx"},{"name":"SegmentedControl","sourcePath":"components/forms/SegmentedControl.jsx"},{"name":"Select","sourcePath":"components/forms/Select.jsx"},{"name":"Slider","sourcePath":"components/forms/Slider.jsx"},{"name":"Switch","sourcePath":"components/forms/Switch.jsx"},{"name":"TagInput","sourcePath":"components/forms/TagInput.jsx"},{"name":"Textarea","sourcePath":"components/forms/Textarea.jsx"},{"name":"TimePicker","sourcePath":"components/forms/TimePicker.jsx"},{"name":"Toggle","sourcePath":"components/forms/Toggle.jsx"},{"name":"Transfer","sourcePath":"components/forms/Transfer.jsx"},{"name":"TreeSelect","sourcePath":"components/forms/TreeSelect.jsx"},{"name":"CS_ICONS","sourcePath":"components/icon/Icon.jsx"},{"name":"Icon","sourcePath":"components/icon/Icon.jsx"},{"name":"Logo","sourcePath":"components/logo/Logo.jsx"},{"name":"CS_LOGO_VIEWBOX","sourcePath":"components/logo/logo-data.js"},{"name":"CS_LOGO_MARK_INNER","sourcePath":"components/logo/logo-data.js"},{"name":"Anchor","sourcePath":"components/navigation/Anchor.jsx"},{"name":"BackTop","sourcePath":"components/navigation/BackTop.jsx"},{"name":"Breadcrumb","sourcePath":"components/navigation/Breadcrumb.jsx"},{"name":"CommandPalette","sourcePath":"components/navigation/CommandPalette.jsx"},{"name":"Dock","sourcePath":"components/navigation/Dock.jsx"},{"name":"HotKeys","sourcePath":"components/navigation/HotKeys.jsx"},{"name":"Link","sourcePath":"components/navigation/Link.jsx"},{"name":"Menu","sourcePath":"components/navigation/Menu.jsx"},{"name":"MenuItem","sourcePath":"components/navigation/Menu.jsx"},{"name":"Menubar","sourcePath":"components/navigation/Menubar.jsx"},{"name":"NavigationMenu","sourcePath":"components/navigation/NavigationMenu.jsx"},{"name":"Pagination","sourcePath":"components/navigation/Pagination.jsx"},{"name":"Sidebar","sourcePath":"components/navigation/Sidebar.jsx"},{"name":"NavItem","sourcePath":"components/navigation/Sidebar.jsx"},{"name":"Steps","sourcePath":"components/navigation/Steps.jsx"},{"name":"Tabs","sourcePath":"components/navigation/Tabs.jsx"},{"name":"Tab","sourcePath":"components/navigation/Tabs.jsx"},{"name":"Toolbar","sourcePath":"components/navigation/Toolbar.jsx"},{"name":"AlertDialog","sourcePath":"components/overlays/AlertDialog.jsx"},{"name":"ContextMenu","sourcePath":"components/overlays/ContextMenu.jsx"},{"name":"Drawer","sourcePath":"components/overlays/Drawer.jsx"},{"name":"HoverCard","sourcePath":"components/overlays/HoverCard.jsx"},{"name":"OverlayProvider","sourcePath":"components/overlays/OverlayManager.jsx"},{"name":"Popconfirm","sourcePath":"components/overlays/Popconfirm.jsx"},{"name":"Popover","sourcePath":"components/overlays/Popover.jsx"},{"name":"Tour","sourcePath":"components/overlays/Tour.jsx"},{"name":"TextField","sourcePath":"components/textfield/TextField.jsx"}],"sourceHashes":{"components/_i18n/i18n.js":"c8fc9f74a4c0","components/_i18n/strings.js":"0e63dc7515d8","components/_utils/cx.js":"ad6a747ea116","components/ai/AIDisclosureBadge.jsx":"4c8954aa2d79","components/ai/ChatMessage.jsx":"344e9c13fcfe","components/ai/CitationList.jsx":"4d12ef868ff3","components/ai/ConfidenceMeter.jsx":"68cf2bba3a9e","components/ai/HumanReviewGate.jsx":"922b278dca5c","components/ai/PromptInput.jsx":"7634643dafa5","components/ai/PromptSuggestions.jsx":"02d64117ecfa","components/ai/TypingIndicator.jsx":"149e3a0c7ef8","components/brand/LumiAvatar.jsx":"b6444360cf80","components/button/Button.jsx":"6d902a925eed","components/button/ButtonGroup.jsx":"1a1481f6fb93","components/button/FloatingActionButton.jsx":"ce49fe4129a3","components/data/Accordion.jsx":"fed81278cefd","components/data/AspectRatio.jsx":"6c1e8703891e","components/data/Avatar.jsx":"88c8f59334e6","components/data/Card.jsx":"96e1f9ef44a9","components/data/Carousel.jsx":"caf09a766c42","components/data/Chart.jsx":"1953e9fef120","components/data/CodeBlock.jsx":"04e0bd2507e2","components/data/Collapsible.jsx":"3d961fef83f8","components/data/Comment.jsx":"81469a910d80","components/data/DescriptionList.jsx":"ce50d72546bb","components/data/Divider.jsx":"2d08b4a7b18e","components/data/Image.jsx":"0ea06cfe1532","components/data/Item.jsx":"7e1ac68c4e96","components/data/Kbd.jsx":"3b3d867cbdd8","components/data/List.jsx":"5c221b19efe0","components/data/Masonry.jsx":"a65508731d79","components/data/QRCode.jsx":"6acaf577a7fc","components/data/ScrollArea.jsx":"c2e2ec304b1e","components/data/Sortable.jsx":"ed7615a9469a","components/data/Splitter.jsx":"d231064601e9","components/data/Stat.jsx":"35734a801a71","components/data/Terminal.jsx":"9d419686bea8","components/data/Timeline.jsx":"22058a781a98","components/data/Tooltip.jsx":"3f30c6b1bf1d","components/data/Tree.jsx":"a1d33dec0451","components/data/Watermark.jsx":"66b7b71488d8","components/data/qr-encode.js":"14e8de77df5f","components/datatable/DataGrid.jsx":"c84fe5d5b8cc","components/datatable/DataTable.jsx":"2a7c3bda5142","components/datatable/TreeTable.jsx":"597c35135ebb","components/dialog/Dialog.jsx":"8ef7722c37c4","components/feedback/Alert.jsx":"4dbf685af3e1","components/feedback/Badge.jsx":"e691ae1634f8","components/feedback/EmptyState.jsx":"5ba1437e6d81","components/feedback/ProgressBar.jsx":"c63a431e9eed","components/feedback/Result.jsx":"c168f8dcb009","components/feedback/Skeleton.jsx":"86ee345cb412","components/feedback/Spinner.jsx":"cad2ed4008a6","components/feedback/StatusIndicator.jsx":"d27a5fc3db2a","components/feedback/Tag.jsx":"13d288da9f38","components/feedback/Toast.jsx":"6a7832751669","components/forms/Calendar.jsx":"8a66cbe766af","components/forms/Cascader.jsx":"63f35db7101d","components/forms/Checkbox.jsx":"2badb7b3b72b","components/forms/ColorPicker.jsx":"d04db0ee7678","components/forms/Combobox.jsx":"3f2fb4d28922","components/forms/DatePicker.jsx":"7a6c18e1e635","components/forms/Editor.jsx":"194484fb9dc4","components/forms/FileUpload.jsx":"509dfaff8bea","components/forms/Form.jsx":"6945025a205f","components/forms/InlineEdit.jsx":"5ffb40598769","components/forms/InputGroup.jsx":"06d6c22420d0","components/forms/InputOTP.jsx":"c3a5d02ffebc","components/forms/Mentions.jsx":"3924619137f3","components/forms/NativeSelect.jsx":"d6f6d300f75d","components/forms/NumberField.jsx":"44975fd25721","components/forms/RadioGroup.jsx":"1a64f7600e01","components/forms/Rating.jsx":"bd5c94741d63","components/forms/SearchField.jsx":"2a12c65900ec","components/forms/SegmentedControl.jsx":"1f143c62fb56","components/forms/Select.jsx":"009495d18845","components/forms/Slider.jsx":"213b7b9edec9","components/forms/Switch.jsx":"3cdf185f757c","components/forms/TagInput.jsx":"2d1554422097","components/forms/Textarea.jsx":"cf244fee0e37","components/forms/TimePicker.jsx":"abd6e54b2983","components/forms/Toggle.jsx":"a5378fd66713","components/forms/Transfer.jsx":"dd0c02d1014e","components/forms/TreeSelect.jsx":"a5b1b91d1d6a","components/icon/Icon.jsx":"280fba8477db","components/logo/Logo.jsx":"445c5f5fbd40","components/logo/logo-data.js":"f1a251a50c8f","components/navigation/Anchor.jsx":"491fb330e718","components/navigation/BackTop.jsx":"5cac0081fc20","components/navigation/Breadcrumb.jsx":"45636f3b0a51","components/navigation/CommandPalette.jsx":"51c25b8416eb","components/navigation/Dock.jsx":"3073e2870c65","components/navigation/HotKeys.jsx":"f0f707a3335d","components/navigation/Link.jsx":"d4fe3fcffd2c","components/navigation/Menu.jsx":"999e1659f8b3","components/navigation/Menubar.jsx":"1aa64f59891e","components/navigation/NavigationMenu.jsx":"020279fd7f79","components/navigation/Pagination.jsx":"a1fc19bfd104","components/navigation/Sidebar.jsx":"d578b013ad33","components/navigation/Steps.jsx":"e26c4a18cdfc","components/navigation/Tabs.jsx":"16964d61f349","components/navigation/Toolbar.jsx":"0f1f25d9e0c5","components/overlays/AlertDialog.jsx":"dcfbb7f61506","components/overlays/ContextMenu.jsx":"e3fb63e7b74f","components/overlays/Drawer.jsx":"a1c719da3f62","components/overlays/HoverCard.jsx":"5cfabde80960","components/overlays/OverlayManager.jsx":"6b58c4dad9da","components/overlays/Popconfirm.jsx":"55f08dba5f38","components/overlays/Popover.jsx":"1582f7fa5533","components/overlays/Tour.jsx":"707cd7464f0c","components/textfield/TextField.jsx":"c06bd9729f20","tokens/tokens.js":"ed1c735bcda9"},"inlinedExternals":[],"unexposedExports":[{"name":"attachFocusTrap","sourcePath":"components/overlays/OverlayManager.jsx"},{"name":"cx","sourcePath":"components/_utils/cx.js"},{"name":"focusableSelector","sourcePath":"components/overlays/OverlayManager.jsx"},{"name":"formatCurrency","sourcePath":"components/_i18n/i18n.js"},{"name":"formatDate","sourcePath":"components/_i18n/i18n.js"},{"name":"formatNumber","sourcePath":"components/_i18n/i18n.js"},{"name":"getOverlayManager","sourcePath":"components/overlays/OverlayManager.jsx"},{"name":"getPath","sourcePath":"components/forms/Form.jsx"},{"name":"makeT","sourcePath":"components/_i18n/i18n.js"},{"name":"monthName","sourcePath":"components/_i18n/i18n.js"},{"name":"qrMatrix","sourcePath":"components/data/qr-encode.js"},{"name":"reorderItems","sourcePath":"components/data/Sortable.jsx"},{"name":"resolveLang","sourcePath":"components/_i18n/i18n.js"},{"name":"setPath","sourcePath":"components/forms/Form.jsx"},{"name":"strings","sourcePath":"components/_i18n/strings.js"},{"name":"tokens","sourcePath":"tokens/tokens.js"},{"name":"tr","sourcePath":"components/_i18n/i18n.js"},{"name":"useLang","sourcePath":"components/_i18n/i18n.js"},{"name":"useOverlayLayer","sourcePath":"components/overlays/OverlayManager.jsx"}]} */
1
+ /* @ds-bundle: {"format":4,"namespace":"CyberSkillDesignSystem_847b3c","components":[{"name":"AIDisclosureBadge","sourcePath":"components/ai/AIDisclosureBadge.jsx"},{"name":"ChatMessage","sourcePath":"components/ai/ChatMessage.jsx"},{"name":"CitationList","sourcePath":"components/ai/CitationList.jsx"},{"name":"ConfidenceMeter","sourcePath":"components/ai/ConfidenceMeter.jsx"},{"name":"HumanReviewGate","sourcePath":"components/ai/HumanReviewGate.jsx"},{"name":"PromptInput","sourcePath":"components/ai/PromptInput.jsx"},{"name":"PromptSuggestions","sourcePath":"components/ai/PromptSuggestions.jsx"},{"name":"TypingIndicator","sourcePath":"components/ai/TypingIndicator.jsx"},{"name":"LumiAvatar","sourcePath":"components/brand/LumiAvatar.jsx"},{"name":"Button","sourcePath":"components/button/Button.jsx"},{"name":"ButtonGroup","sourcePath":"components/button/ButtonGroup.jsx"},{"name":"FloatingActionButton","sourcePath":"components/button/FloatingActionButton.jsx"},{"name":"Accordion","sourcePath":"components/data/Accordion.jsx"},{"name":"AspectRatio","sourcePath":"components/data/AspectRatio.jsx"},{"name":"Avatar","sourcePath":"components/data/Avatar.jsx"},{"name":"AvatarGroup","sourcePath":"components/data/Avatar.jsx"},{"name":"Card","sourcePath":"components/data/Card.jsx"},{"name":"CardHeader","sourcePath":"components/data/Card.jsx"},{"name":"CardBody","sourcePath":"components/data/Card.jsx"},{"name":"CardFooter","sourcePath":"components/data/Card.jsx"},{"name":"Carousel","sourcePath":"components/data/Carousel.jsx"},{"name":"Chart","sourcePath":"components/data/Chart.jsx"},{"name":"CodeBlock","sourcePath":"components/data/CodeBlock.jsx"},{"name":"Collapsible","sourcePath":"components/data/Collapsible.jsx"},{"name":"Comment","sourcePath":"components/data/Comment.jsx"},{"name":"DescriptionList","sourcePath":"components/data/DescriptionList.jsx"},{"name":"Divider","sourcePath":"components/data/Divider.jsx"},{"name":"Image","sourcePath":"components/data/Image.jsx"},{"name":"Item","sourcePath":"components/data/Item.jsx"},{"name":"Kbd","sourcePath":"components/data/Kbd.jsx"},{"name":"List","sourcePath":"components/data/List.jsx"},{"name":"ListItem","sourcePath":"components/data/List.jsx"},{"name":"Masonry","sourcePath":"components/data/Masonry.jsx"},{"name":"QRCode","sourcePath":"components/data/QRCode.jsx"},{"name":"ScrollArea","sourcePath":"components/data/ScrollArea.jsx"},{"name":"Sortable","sourcePath":"components/data/Sortable.jsx"},{"name":"Splitter","sourcePath":"components/data/Splitter.jsx"},{"name":"Stat","sourcePath":"components/data/Stat.jsx"},{"name":"Terminal","sourcePath":"components/data/Terminal.jsx"},{"name":"Timeline","sourcePath":"components/data/Timeline.jsx"},{"name":"Tooltip","sourcePath":"components/data/Tooltip.jsx"},{"name":"Tree","sourcePath":"components/data/Tree.jsx"},{"name":"Watermark","sourcePath":"components/data/Watermark.jsx"},{"name":"DataGrid","sourcePath":"components/datatable/DataGrid.jsx"},{"name":"DataTable","sourcePath":"components/datatable/DataTable.jsx"},{"name":"TreeTable","sourcePath":"components/datatable/TreeTable.jsx"},{"name":"Dialog","sourcePath":"components/dialog/Dialog.jsx"},{"name":"Alert","sourcePath":"components/feedback/Alert.jsx"},{"name":"Badge","sourcePath":"components/feedback/Badge.jsx"},{"name":"EmptyState","sourcePath":"components/feedback/EmptyState.jsx"},{"name":"ProgressBar","sourcePath":"components/feedback/ProgressBar.jsx"},{"name":"Result","sourcePath":"components/feedback/Result.jsx"},{"name":"Skeleton","sourcePath":"components/feedback/Skeleton.jsx"},{"name":"Spinner","sourcePath":"components/feedback/Spinner.jsx"},{"name":"StatusIndicator","sourcePath":"components/feedback/StatusIndicator.jsx"},{"name":"Tag","sourcePath":"components/feedback/Tag.jsx"},{"name":"ToastStack","sourcePath":"components/feedback/Toast.jsx"},{"name":"Toast","sourcePath":"components/feedback/Toast.jsx"},{"name":"Calendar","sourcePath":"components/forms/Calendar.jsx"},{"name":"Cascader","sourcePath":"components/forms/Cascader.jsx"},{"name":"Checkbox","sourcePath":"components/forms/Checkbox.jsx"},{"name":"ColorPicker","sourcePath":"components/forms/ColorPicker.jsx"},{"name":"Combobox","sourcePath":"components/forms/Combobox.jsx"},{"name":"DatePicker","sourcePath":"components/forms/DatePicker.jsx"},{"name":"Editor","sourcePath":"components/forms/Editor.jsx"},{"name":"FileUpload","sourcePath":"components/forms/FileUpload.jsx"},{"name":"Form","sourcePath":"components/forms/Form.jsx"},{"name":"FormField","sourcePath":"components/forms/Form.jsx"},{"name":"FormFieldArray","sourcePath":"components/forms/Form.jsx"},{"name":"FormWizard","sourcePath":"components/forms/Form.jsx"},{"name":"InlineEdit","sourcePath":"components/forms/InlineEdit.jsx"},{"name":"InputGroup","sourcePath":"components/forms/InputGroup.jsx"},{"name":"InputOTP","sourcePath":"components/forms/InputOTP.jsx"},{"name":"Mentions","sourcePath":"components/forms/Mentions.jsx"},{"name":"NativeSelect","sourcePath":"components/forms/NativeSelect.jsx"},{"name":"NumberField","sourcePath":"components/forms/NumberField.jsx"},{"name":"Radio","sourcePath":"components/forms/RadioGroup.jsx"},{"name":"RadioGroup","sourcePath":"components/forms/RadioGroup.jsx"},{"name":"Rating","sourcePath":"components/forms/Rating.jsx"},{"name":"SearchField","sourcePath":"components/forms/SearchField.jsx"},{"name":"SegmentedControl","sourcePath":"components/forms/SegmentedControl.jsx"},{"name":"Select","sourcePath":"components/forms/Select.jsx"},{"name":"Slider","sourcePath":"components/forms/Slider.jsx"},{"name":"Switch","sourcePath":"components/forms/Switch.jsx"},{"name":"TagInput","sourcePath":"components/forms/TagInput.jsx"},{"name":"Textarea","sourcePath":"components/forms/Textarea.jsx"},{"name":"TimePicker","sourcePath":"components/forms/TimePicker.jsx"},{"name":"Toggle","sourcePath":"components/forms/Toggle.jsx"},{"name":"Transfer","sourcePath":"components/forms/Transfer.jsx"},{"name":"TreeSelect","sourcePath":"components/forms/TreeSelect.jsx"},{"name":"CS_ICONS","sourcePath":"components/icon/Icon.jsx"},{"name":"Icon","sourcePath":"components/icon/Icon.jsx"},{"name":"Logo","sourcePath":"components/logo/Logo.jsx"},{"name":"CS_LOGO_VIEWBOX","sourcePath":"components/logo/logo-data.js"},{"name":"CS_LOGO_MARK_INNER","sourcePath":"components/logo/logo-data.js"},{"name":"Anchor","sourcePath":"components/navigation/Anchor.jsx"},{"name":"BackTop","sourcePath":"components/navigation/BackTop.jsx"},{"name":"Breadcrumb","sourcePath":"components/navigation/Breadcrumb.jsx"},{"name":"CommandPalette","sourcePath":"components/navigation/CommandPalette.jsx"},{"name":"Dock","sourcePath":"components/navigation/Dock.jsx"},{"name":"HotKeys","sourcePath":"components/navigation/HotKeys.jsx"},{"name":"Link","sourcePath":"components/navigation/Link.jsx"},{"name":"Menu","sourcePath":"components/navigation/Menu.jsx"},{"name":"MenuItem","sourcePath":"components/navigation/Menu.jsx"},{"name":"Menubar","sourcePath":"components/navigation/Menubar.jsx"},{"name":"NavigationMenu","sourcePath":"components/navigation/NavigationMenu.jsx"},{"name":"Pagination","sourcePath":"components/navigation/Pagination.jsx"},{"name":"Sidebar","sourcePath":"components/navigation/Sidebar.jsx"},{"name":"NavItem","sourcePath":"components/navigation/Sidebar.jsx"},{"name":"Steps","sourcePath":"components/navigation/Steps.jsx"},{"name":"Tabs","sourcePath":"components/navigation/Tabs.jsx"},{"name":"Tab","sourcePath":"components/navigation/Tabs.jsx"},{"name":"Toolbar","sourcePath":"components/navigation/Toolbar.jsx"},{"name":"AlertDialog","sourcePath":"components/overlays/AlertDialog.jsx"},{"name":"ContextMenu","sourcePath":"components/overlays/ContextMenu.jsx"},{"name":"Drawer","sourcePath":"components/overlays/Drawer.jsx"},{"name":"HoverCard","sourcePath":"components/overlays/HoverCard.jsx"},{"name":"OverlayProvider","sourcePath":"components/overlays/OverlayManager.jsx"},{"name":"Popconfirm","sourcePath":"components/overlays/Popconfirm.jsx"},{"name":"Popover","sourcePath":"components/overlays/Popover.jsx"},{"name":"Tour","sourcePath":"components/overlays/Tour.jsx"},{"name":"TextField","sourcePath":"components/textfield/TextField.jsx"}],"sourceHashes":{"components/_i18n/i18n.js":"c8fc9f74a4c0","components/_i18n/strings.js":"0e63dc7515d8","components/_utils/cx.js":"ad6a747ea116","components/ai/AIDisclosureBadge.jsx":"4c8954aa2d79","components/ai/ChatMessage.jsx":"344e9c13fcfe","components/ai/CitationList.jsx":"4d12ef868ff3","components/ai/ConfidenceMeter.jsx":"68cf2bba3a9e","components/ai/HumanReviewGate.jsx":"922b278dca5c","components/ai/PromptInput.jsx":"7634643dafa5","components/ai/PromptSuggestions.jsx":"02d64117ecfa","components/ai/TypingIndicator.jsx":"149e3a0c7ef8","components/brand/LumiAvatar.jsx":"b6444360cf80","components/button/Button.jsx":"6d902a925eed","components/button/ButtonGroup.jsx":"1a1481f6fb93","components/button/FloatingActionButton.jsx":"ce49fe4129a3","components/data/Accordion.jsx":"fed81278cefd","components/data/AspectRatio.jsx":"6c1e8703891e","components/data/Avatar.jsx":"88c8f59334e6","components/data/Card.jsx":"96e1f9ef44a9","components/data/Carousel.jsx":"caf09a766c42","components/data/Chart.jsx":"1953e9fef120","components/data/CodeBlock.jsx":"04e0bd2507e2","components/data/Collapsible.jsx":"3d961fef83f8","components/data/Comment.jsx":"81469a910d80","components/data/DescriptionList.jsx":"ce50d72546bb","components/data/Divider.jsx":"2d08b4a7b18e","components/data/Image.jsx":"0ea06cfe1532","components/data/Item.jsx":"7e1ac68c4e96","components/data/Kbd.jsx":"3b3d867cbdd8","components/data/List.jsx":"5c221b19efe0","components/data/Masonry.jsx":"a65508731d79","components/data/QRCode.jsx":"6acaf577a7fc","components/data/ScrollArea.jsx":"c2e2ec304b1e","components/data/Sortable.jsx":"ed7615a9469a","components/data/Splitter.jsx":"d231064601e9","components/data/Stat.jsx":"35734a801a71","components/data/Terminal.jsx":"9d419686bea8","components/data/Timeline.jsx":"22058a781a98","components/data/Tooltip.jsx":"3f30c6b1bf1d","components/data/Tree.jsx":"a1d33dec0451","components/data/Watermark.jsx":"66b7b71488d8","components/data/qr-encode.js":"14e8de77df5f","components/datatable/DataGrid.jsx":"c84fe5d5b8cc","components/datatable/DataTable.jsx":"2a7c3bda5142","components/datatable/TreeTable.jsx":"597c35135ebb","components/dialog/Dialog.jsx":"8ef7722c37c4","components/feedback/Alert.jsx":"4dbf685af3e1","components/feedback/Badge.jsx":"e691ae1634f8","components/feedback/EmptyState.jsx":"5ba1437e6d81","components/feedback/ProgressBar.jsx":"c63a431e9eed","components/feedback/Result.jsx":"c168f8dcb009","components/feedback/Skeleton.jsx":"86ee345cb412","components/feedback/Spinner.jsx":"cad2ed4008a6","components/feedback/StatusIndicator.jsx":"d27a5fc3db2a","components/feedback/Tag.jsx":"13d288da9f38","components/feedback/Toast.jsx":"6a7832751669","components/forms/Calendar.jsx":"8a66cbe766af","components/forms/Cascader.jsx":"63f35db7101d","components/forms/Checkbox.jsx":"2badb7b3b72b","components/forms/ColorPicker.jsx":"d04db0ee7678","components/forms/Combobox.jsx":"3f2fb4d28922","components/forms/DatePicker.jsx":"7a6c18e1e635","components/forms/Editor.jsx":"194484fb9dc4","components/forms/FileUpload.jsx":"509dfaff8bea","components/forms/Form.jsx":"6945025a205f","components/forms/InlineEdit.jsx":"5ffb40598769","components/forms/InputGroup.jsx":"06d6c22420d0","components/forms/InputOTP.jsx":"c3a5d02ffebc","components/forms/Mentions.jsx":"3924619137f3","components/forms/NativeSelect.jsx":"d6f6d300f75d","components/forms/NumberField.jsx":"44975fd25721","components/forms/RadioGroup.jsx":"1a64f7600e01","components/forms/Rating.jsx":"bd5c94741d63","components/forms/SearchField.jsx":"2a12c65900ec","components/forms/SegmentedControl.jsx":"1f143c62fb56","components/forms/Select.jsx":"009495d18845","components/forms/Slider.jsx":"213b7b9edec9","components/forms/Switch.jsx":"3cdf185f757c","components/forms/TagInput.jsx":"2d1554422097","components/forms/Textarea.jsx":"cf244fee0e37","components/forms/TimePicker.jsx":"abd6e54b2983","components/forms/Toggle.jsx":"a5378fd66713","components/forms/Transfer.jsx":"dd0c02d1014e","components/forms/TreeSelect.jsx":"a5b1b91d1d6a","components/icon/Icon.jsx":"280fba8477db","components/logo/Logo.jsx":"445c5f5fbd40","components/logo/logo-data.js":"f1a251a50c8f","components/navigation/Anchor.jsx":"491fb330e718","components/navigation/BackTop.jsx":"5cac0081fc20","components/navigation/Breadcrumb.jsx":"45636f3b0a51","components/navigation/CommandPalette.jsx":"51c25b8416eb","components/navigation/Dock.jsx":"3073e2870c65","components/navigation/HotKeys.jsx":"f0f707a3335d","components/navigation/Link.jsx":"d4fe3fcffd2c","components/navigation/Menu.jsx":"999e1659f8b3","components/navigation/Menubar.jsx":"1aa64f59891e","components/navigation/NavigationMenu.jsx":"020279fd7f79","components/navigation/Pagination.jsx":"a1fc19bfd104","components/navigation/Sidebar.jsx":"d578b013ad33","components/navigation/Steps.jsx":"e26c4a18cdfc","components/navigation/Tabs.jsx":"16964d61f349","components/navigation/Toolbar.jsx":"0f1f25d9e0c5","components/overlays/AlertDialog.jsx":"dcfbb7f61506","components/overlays/ContextMenu.jsx":"e3fb63e7b74f","components/overlays/Drawer.jsx":"a1c719da3f62","components/overlays/HoverCard.jsx":"5cfabde80960","components/overlays/OverlayManager.jsx":"6b58c4dad9da","components/overlays/Popconfirm.jsx":"55f08dba5f38","components/overlays/Popover.jsx":"1582f7fa5533","components/overlays/Tour.jsx":"707cd7464f0c","components/textfield/TextField.jsx":"c06bd9729f20","tokens/tokens.js":"c2ea96348d98"},"inlinedExternals":[],"unexposedExports":[{"name":"attachFocusTrap","sourcePath":"components/overlays/OverlayManager.jsx"},{"name":"cx","sourcePath":"components/_utils/cx.js"},{"name":"focusableSelector","sourcePath":"components/overlays/OverlayManager.jsx"},{"name":"formatCurrency","sourcePath":"components/_i18n/i18n.js"},{"name":"formatDate","sourcePath":"components/_i18n/i18n.js"},{"name":"formatNumber","sourcePath":"components/_i18n/i18n.js"},{"name":"getOverlayManager","sourcePath":"components/overlays/OverlayManager.jsx"},{"name":"getPath","sourcePath":"components/forms/Form.jsx"},{"name":"makeT","sourcePath":"components/_i18n/i18n.js"},{"name":"monthName","sourcePath":"components/_i18n/i18n.js"},{"name":"qrMatrix","sourcePath":"components/data/qr-encode.js"},{"name":"reorderItems","sourcePath":"components/data/Sortable.jsx"},{"name":"resolveLang","sourcePath":"components/_i18n/i18n.js"},{"name":"setPath","sourcePath":"components/forms/Form.jsx"},{"name":"strings","sourcePath":"components/_i18n/strings.js"},{"name":"tokens","sourcePath":"tokens/tokens.js"},{"name":"tr","sourcePath":"components/_i18n/i18n.js"},{"name":"useLang","sourcePath":"components/_i18n/i18n.js"},{"name":"useOverlayLayer","sourcePath":"components/overlays/OverlayManager.jsx"}]} */
2
2
 
3
3
  (() => {
4
4
 
@@ -4874,7 +4874,7 @@ try { (() => {
4874
4874
  const tokens = {
4875
4875
  "$meta": {
4876
4876
  "system": "CyberSkill Design System",
4877
- "version": "1.7.0",
4877
+ "version": "1.7.1",
4878
4878
  "generated": "2026-07-23",
4879
4879
  "note": "Generated from tokens/*.css. Root grouped by category; theme/element scopes carry overrides only. Regenerate after any token change (see docs/conventions.md)."
4880
4880
  },
package/_esm/cs.mjs CHANGED
@@ -1,4 +1,4 @@
1
- // CyberSkill Design System — ESM entry point (GENERATED from _ds_manifest.json at v1.7.0).
1
+ // CyberSkill Design System — ESM entry point (GENERATED from _ds_manifest.json at v1.7.1).
2
2
  // No build step: import this module directly in a browser. It ensures React 19.2.8 via umd-react
3
3
  // (official React 19 dropped UMD; pinned + SRI; skipped when window.React already exists), side-loads
4
4
  // ../_ds_bundle.js once, resolves the compiler-assigned namespace BY PREFIX (never a hardcoded suffix),
@@ -32,7 +32,7 @@ if (!found()) await ensureScript("../_ds_bundle.js");
32
32
  export const CS = g[found()];
33
33
  if (!CS) throw new Error("cs.js: bundle loaded but no CyberSkillDesignSystem_* namespace found");
34
34
  export default CS;
35
- export const VERSION = "1.7.0";
35
+ export const VERSION = "1.7.1";
36
36
  export const AIDisclosureBadge = CS.AIDisclosureBadge;
37
37
  export const Accordion = CS.Accordion;
38
38
  export const Alert = CS.Alert;
@@ -1,6 +1,6 @@
1
1
  # Contrast report — elemental pairings (APCA)
2
2
 
3
- Generated · sweep at VERSION 1.7.0.
3
+ Generated · sweep at VERSION 1.7.1.
4
4
 
5
5
  Published on Storybook **Docs** at `design.cyberskill.world`.
6
6
 
@@ -38,7 +38,7 @@ Style’s sole pack today is **liquid-glass**. Immutable under all axes: Umber/O
38
38
 
39
39
  **New element variant** — stay inside the element's oklch envelope; set the 10 `--cs-accent-*` contract tokens (incl. `--cs-accent-on-strong` ≥4.5:1 on `-strong`) plus `--cs-color-text-accent`/`--cs-color-link` (APCA-check both); the aurora wash inherits from the element via `.cs-aurora-wash` (override the class rule only if the variant truly needs its own image); gradient partner (`grad-b`) must follow Tương sinh.
40
40
 
41
- **Ship check** — run the compiler check until clean, then run `_audit/docs-consistency.html` **and** `_audit/namespace-portability.html` (both must be green). VERSION **1.7.0** (auto-bumps on `main`).
41
+ **Ship check** — run the compiler check until clean, then run `_audit/docs-consistency.html` **and** `_audit/namespace-portability.html` (both must be green). VERSION **1.7.1** (auto-bumps on `main`).
42
42
 
43
43
  ## Decision log (owner-approved)
44
44
 
@@ -64,7 +64,7 @@ Every template exports; the right path depends on the archetype. All paths prese
64
64
  | Archetype | Path | Notes |
65
65
  |---|---|---|
66
66
  | Deck (`*-deck`, `slide-deck`) | **PPTX (editable)** | `gen_pptx` at 960×540; force VN per-slide with `showJs: __dcSetProps(__dcRootName(),{language:'Tiếng Việt'})`. Text exports as native runs; only the Logo is an image. |
67
- | Document (any with `@page{size:…}` / `<meta name="omelette-owns-print">`) | **PDF + editable DOCX** | One **Tải / Download** control (`data-omelette-chrome`, print-stripped) from `templates/_vendor/doc-export.js` via `ds-base.js`, with a PDF \| DOCX menu. Both formats are built from the live `.cs-sheet` so the file matches the HTML preview. **PDF** = raster of the rendered sheet (JPEG pages, fallback: print a same-origin sheet clone — not the Storybook URL); CI still uses Playwright `page.pdf`. **DOCX** = editable OOXML walked from that same sheet (tables, bilingual cell paras, umber headings, VN Unicode; running header is the short brand line, not a duplicated lockup); ZIP via `CompressionStream` — no CDN. Decks stay PPTX. |
67
+ | Document (any with `@page{size:…}` / `<meta name="omelette-owns-print">`) | **PDF + editable DOCX** | One **Tải / Download** control (`data-omelette-chrome`, print-stripped) from `templates/_vendor/doc-export.js` via `ds-base.js`, with a PDF \| DOCX menu. Both formats are built from the live `.cs-sheet` so the file matches the HTML preview. **PDF** = one JPEG page of the rendered sheet (MediaBox aspect = the card — do not slice to A4 or stretch leftover slices); fallback: print a same-origin sheet clone — not the Storybook URL. CI still uses Playwright `page.pdf` for the print path. **DOCX** = editable OOXML walked from that same sheet (tables + colspan, yellow `--cs-doc-fill` blanks, bilingual cell paras, umber headings, VN Unicode; Word header/footer stay empty so the sheet lockup is not duplicated); ZIP via `CompressionStream` — no CDN. Decks stay PPTX. |
68
68
  | Email / product page / any DC | **Standalone offline HTML** | The DC loads CSS + bundle dynamically via `ds-base.js`, which `super_inline_html` can't see. To bundle: make a `*-standalone.html` copy **in the same folder** (keeps `./support.js` relative) with **static** `<link rel="stylesheet" href="../../styles.css">` + `<script src="../../_ds_bundle.js">` in the raw `<head>` (both inlinable) instead of `ds-base.js`, plus a `<template id="__bundler_thumbnail">`. Bake the target language into the props default. Then `super_inline_html`. |
69
69
  | Any | **Editor-native + Claude Code handoff** | The whole project is dev-handoff-ready (compiled bundle + `.d.ts` + `prompt.md` per component); generate the package on request via the handoff skill. |
70
70
 
@@ -52,7 +52,7 @@ Benchmark principles (WCAG · APCA · OKLCH · DTCG · CDS doctrine + style expa
52
52
  | Axe smoke | `_audit/axe-smoke.html` + `_audit/lib/axe-fixtures.js` | axe-core 4.10.0 (vendored at `_audit/vendor/axe.min.js`) serious/critical WCAG 2 A/AA rules on every public primary (inventory-locked fixtures; bilingual EN·VI) — Dialog, AlertDialog, Drawer, Tour, CommandPalette, and Menu mount open, and Cascader / TreeSelect / Menubar / Combobox surfaces are expanded before the scan; gate-equivalent Storybook a11y enforcement (no separate test-runner) | 0 serious/critical findings (`__axesmoke`) | Hard | Fast board CI |
53
53
  | Print smoke | `_audit/print-smoke.html` | **Every** `omelette-owns-print` document declares print-ownership meta and A4/Letter `@page` hooks the PDF/DOCX export path relies on | ≥60 print docs, 0 missing hooks (`__printsmoke`) | Hard | Fast board CI |
54
54
  | Support no-eval (Node) | `_audit/ci/test-support-no-eval.mjs` | Canonical `templates/_vendor/support.js` + all template copies are identical and contain no Function-constructor / `eval(` call sites (CSP-safe inline-script runtime) | Exit 0 | Hard | Unit test |
55
- | Doc export (Node+PW) | `_audit/ci/test-doc-export.mjs` | Every print template under site CSP: no EvalError, one Download menu (PDF\|DOCX), PDF `%PDF` + A4/Letter MediaBox, DOCX ZIP + `word/document.xml` + VN diacritics + ≥70% sheet-text overlap | Exit 0 | Hard | Unit test |
55
+ | Doc export (Node+PW) | `_audit/ci/test-doc-export.mjs` | Every print template under site CSP: no EvalError, one Download menu (PDF\|DOCX), Playwright PDF `%PDF` + A4/Letter MediaBox, downloaded `buildPdfBlob` is one unstretched page of the live sheet (framework), DOCX ZIP + `word/document.xml` + VN diacritics + ≥70% sheet-text overlap + yellow fills/colspan on framework | Exit 0 | Hard | Unit test |
56
56
  | DOCX source parity (Node) | `_audit/ci/test-docx-source-parity.mjs` | DC text vs committed fixtures under `_audit/fixtures/hr-suite-docx-text/` for every mapped HR instrument | ≥85% phrase overlap; exit 0 | Hard | Unit test |
57
57
  | Pixel CI | `_audit/pixel-ci.html` + `_audit/ci/pixel-diff.mjs` | 15 curated baselines exist; Playwright capture script performs real % pixel compare; last report must be clean (`drifted[]` empty) | Contract + clean compare (`__pixelci.pass`); drift or missing report fails | Hard | Fast board CI (compare step feeds the row) + `pixel-diff` job |
58
58
 
@@ -1,6 +1,6 @@
1
1
  # Release Notes
2
2
 
3
- Curated product highlights for operators. This is **not** a git log and **not** a `CHANGELOG.md` — the design system does not maintain a changelog file. VERSION **1.7.0** (auto-bumps on push to `main` from Conventional Commits; owner may still force a bump). Technical continuity is the repo tip; product-facing continuity is this page (mirrored in Storybook **Release Notes**). Published on Storybook **Docs** at `design.cyberskill.world`.
3
+ Curated product highlights for operators. This is **not** a git log and **not** a `CHANGELOG.md` — the design system does not maintain a changelog file. VERSION **1.7.1** (auto-bumps on push to `main` from Conventional Commits; owner may still force a bump). Technical continuity is the repo tip; product-facing continuity is this page (mirrored in Storybook **Release Notes**). Published on Storybook **Docs** at `design.cyberskill.world`.
4
4
 
5
5
  ## Release — `@cyberskill/design@1.3.10`
6
6
 
@@ -1,6 +1,6 @@
1
1
  # Báo cáo contrast — cặp elemental (APCA)
2
2
 
3
- Tạo · quét tại VERSION 1.7.0.
3
+ Tạo · quét tại VERSION 1.7.1.
4
4
 
5
5
  Xuất bản trên Storybook **Docs** tại `design.cyberskill.world`.
6
6
 
@@ -38,7 +38,7 @@ Pack Style duy nhất hiện nay là **liquid-glass**. Bất biến dưới mọ
38
38
 
39
39
  **Element variant mới** — ở trong envelope oklch của element; đặt 10 token hợp đồng `--cs-accent-*` (gồm `--cs-accent-on-strong` ≥4.5:1 trên `-strong`) cộng `--cs-color-text-accent`/`--cs-color-link` (APCA-check cả hai); aurora wash kế thừa từ element qua `.cs-aurora-wash` (chỉ override class rule nếu variant thật sự cần ảnh riêng); đối tác gradient (`grad-b`) phải theo Tương sinh.
40
40
 
41
- **Ship check** — chạy compiler check đến sạch, rồi chạy `_audit/docs-consistency.html` **và** `_audit/namespace-portability.html` (cả hai phải xanh). VERSION **1.7.0** (auto-bump trên `main`).
41
+ **Ship check** — chạy compiler check đến sạch, rồi chạy `_audit/docs-consistency.html` **và** `_audit/namespace-portability.html` (cả hai phải xanh). VERSION **1.7.1** (auto-bump trên `main`).
42
42
 
43
43
  ## Decision log (owner duyệt)
44
44
 
@@ -64,7 +64,7 @@ Mọi template export; đường đúng phụ thuộc archetype. Mọi đường
64
64
  | Archetype | Đường | Ghi chú |
65
65
  |---|---|---|
66
66
  | Deck (`*-deck`, `slide-deck`) | **PPTX (editable)** | `gen_pptx` ở 960×540; ép VN từng slide với `showJs: __dcSetProps(__dcRootName(),{language:'Tiếng Việt'})`. Text export như native runs; chỉ Logo là ảnh. |
67
- | Document (mọi cái có `@page{size:…}` / `<meta name="omelette-owns-print">`) | **PDF + DOCX chỉnh sửa được** | Một nút **Tải / Download** (`data-omelette-chrome`, ẩn khi in) từ `templates/_vendor/doc-export.js` qua `ds-base.js`, menu PDF \| DOCX. Cả hai format dựng từ `.cs-sheet` sống để file khớp preview HTML. **PDF** = raster sheet đã render (trang JPEG; fallback: in bản clone same-origin — không phải URL Storybook); CI vẫn dùng Playwright `page.pdf`. **DOCX** = OOXML editable walk từ cùng sheet (bảng, đoạn bilingual trong ô, heading umber, Unicode VN; header Word là dòng brand ngắn, không nhân đôi lockup); ZIP qua `CompressionStream` — không CDN. Deck vẫn PPTX. |
67
+ | Document (mọi cái có `@page{size:…}` / `<meta name="omelette-owns-print">`) | **PDF + DOCX chỉnh sửa được** | Một nút **Tải / Download** (`data-omelette-chrome`, ẩn khi in) từ `templates/_vendor/doc-export.js` qua `ds-base.js`, menu PDF \| DOCX. Cả hai format dựng từ `.cs-sheet` sống để file khớp preview HTML. **PDF** = một trang JPEG của sheet đã render (tỉ lệ MediaBox = thẻ — không cắt A4 hay kéo dãn lát cuối); fallback: in bản clone same-origin — không phải URL Storybook. CI vẫn dùng Playwright `page.pdf` cho đường in. **DOCX** = OOXML editable walk từ cùng sheet (bảng + colspan, ô vàng `--cs-doc-fill`, đoạn bilingual trong ô, heading umber, Unicode VN; header/footer Word để trống để không nhân đôi lockup); ZIP qua `CompressionStream` — không CDN. Deck vẫn PPTX. |
68
68
  | Email / product page / mọi DC | **Standalone offline HTML** | DC load CSS + bundle động qua `ds-base.js`, mà `super_inline_html` không thấy. Để bundle: tạo bản `*-standalone.html` **cùng thư mục** (giữ `./support.js` relative) với `<link rel="stylesheet" href="../../styles.css">` + `<script src="../../_ds_bundle.js">` **static** trong raw `<head>` (cả hai inline được) thay `ds-base.js`, cộng `<template id="__bundler_thumbnail">`. Nướng ngôn ngữ đích vào props default. Rồi `super_inline_html`. |
69
69
  | Bất kỳ | **Editor-native + Claude Code handoff** | Cả project sẵn sàng handoff-dev (compiled bundle + `.d.ts` + `prompt.md` mỗi component); generate package theo request qua handoff skill. |
70
70
 
@@ -52,7 +52,7 @@ Nguyên tắc benchmark (WCAG · APCA · OKLCH · DTCG · doctrine CDS + mở r
52
52
  | Axe smoke | `_audit/axe-smoke.html` + `_audit/lib/axe-fixtures.js` | Rule serious/critical WCAG 2 A/AA của axe-core 4.10.0 (vendored tại `_audit/vendor/axe.min.js`) trên mọi public primary (fixture khoá inventory; bilingual EN·VI) — Dialog, AlertDialog, Drawer, Tour, CommandPalette và Menu mount mở, còn Cascader / TreeSelect / Menubar / Combobox được bung trước khi quét; tương đương enforcement a11y Storybook (không test-runner riêng) | 0 finding serious/critical (`__axesmoke`) | Hard | Fast board CI |
53
53
  | Print smoke | `_audit/print-smoke.html` | **Every** `omelette-owns-print` document declares print-ownership meta and A4/Letter `@page` hooks the PDF/DOCX export path relies on | ≥60 print docs, 0 missing hooks (`__printsmoke`) | Hard | Fast board CI |
54
54
  | Support no-eval (Node) | `_audit/ci/test-support-no-eval.mjs` | Canonical `templates/_vendor/support.js` + all template copies are identical and contain no Function-constructor / `eval(` call sites (CSP-safe inline-script runtime) | Exit 0 | Hard | Unit test |
55
- | Doc export (Node+PW) | `_audit/ci/test-doc-export.mjs` | Every print template under site CSP: no EvalError, one Download menu (PDF\|DOCX), PDF `%PDF` + A4/Letter MediaBox, DOCX ZIP + `word/document.xml` + VN diacritics + ≥70% sheet-text overlap | Exit 0 | Hard | Unit test |
55
+ | Doc export (Node+PW) | `_audit/ci/test-doc-export.mjs` | Mọi template in dưới CSP site: không EvalError, một menu Download (PDF\|DOCX), PDF Playwright `%PDF` + MediaBox A4/Letter, `buildPdfBlob` tải về là một trang không méo của sheet sống (framework), DOCX ZIP + `word/document.xml` + dấu VN + ≥70% chồng text sheet + fill vàng/colspan trên framework | Exit 0 | Hard | Unit test |
56
56
  | DOCX source parity (Node) | `_audit/ci/test-docx-source-parity.mjs` | DC text vs committed fixtures under `_audit/fixtures/hr-suite-docx-text/` for every mapped HR instrument | ≥85% phrase overlap; exit 0 | Hard | Unit test |
57
57
  | Pixel CI | `_audit/pixel-ci.html` + `_audit/ci/pixel-diff.mjs` | 15 baseline curated tồn tại; script Playwright capture so sánh % pixel thật; report gần nhất phải sạch (`drifted[]` rỗng) | Hợp đồng + compare sạch (`__pixelci.pass`); drift hoặc thiếu report → fail | Hard | Fast board CI (bước compare nuôi hàng) + job `pixel-diff` |
58
58
 
@@ -1,6 +1,6 @@
1
1
  # Ghi chú phát hành
2
2
 
3
- Điểm nổi bật sản phẩm cho operator — **không** phải git log và **không** phải `CHANGELOG.md`. Hệ thống thiết kế không maintain file changelog. VERSION **1.7.0** (auto-bump khi push lên `main` từ Conventional Commits; owner vẫn có thể force bump). Chân lý kỹ thuật là tip repo; chân lý hướng sản phẩm là trang này (đồng bộ Storybook **Release Notes**). Xuất bản trên Storybook **Docs** tại `design.cyberskill.world`.
3
+ Điểm nổi bật sản phẩm cho operator — **không** phải git log và **không** phải `CHANGELOG.md`. Hệ thống thiết kế không maintain file changelog. VERSION **1.7.1** (auto-bump khi push lên `main` từ Conventional Commits; owner vẫn có thể force bump). Chân lý kỹ thuật là tip repo; chân lý hướng sản phẩm là trang này (đồng bộ Storybook **Release Notes**). Xuất bản trên Storybook **Docs** tại `design.cyberskill.world`.
4
4
 
5
5
  ## Release — `@cyberskill/design@1.3.10`
6
6
 
package/llms.txt CHANGED
@@ -1,6 +1,6 @@
1
1
  # CyberSkill Design System
2
2
 
3
- > HTML-first, Vietnamese-first design system, VERSION **1.7.0**. Immutable anchors: Umber #45210E · Ochre #F4BA17. Four independent axes — Theme (light · dark · system) × Element (Ngũ Hành, 15 variants) × Language (EN · VI) × Style (`data-cs-style` — sole pack **liquid-glass**; absent ≡ default). It ships 106 components / 122 exports, 85 copyable templates (EN·VN for emails + team/legal/finance; client/media collateral EN-first), and tokens in CSS + JSON + ESM + W3C DTCG + native mirrors. This file is the agent/tool front door: it maps each **capability** to the format it should consume. npm package name is **`@cyberskill/design`** (not `@cyberskill/react`). Release signal: tip SHA + [docs/release-notes.md](docs/release-notes.md) — VERSION **1.7.0**, no CHANGELOG.
3
+ > HTML-first, Vietnamese-first design system, VERSION **1.7.1**. Immutable anchors: Umber #45210E · Ochre #F4BA17. Four independent axes — Theme (light · dark · system) × Element (Ngũ Hành, 15 variants) × Language (EN · VI) × Style (`data-cs-style` — sole pack **liquid-glass**; absent ≡ default). It ships 106 components / 122 exports, 85 copyable templates (EN·VN for emails + team/legal/finance; client/media collateral EN-first), and tokens in CSS + JSON + ESM + W3C DTCG + native mirrors. This file is the agent/tool front door: it maps each **capability** to the format it should consume. npm package name is **`@cyberskill/design`** (not `@cyberskill/react`). Release signal: tip SHA + [docs/release-notes.md](docs/release-notes.md) — VERSION **1.7.1**, no CHANGELOG.
4
4
 
5
5
  The portable contract covers browser and bundler entry points: `styles.css` · `_esm/cs.mjs` legacy · `_ds_bundle.js` · tokens work without a build step; `_esm/react.mjs` is bundler-native JSX (Next/Vite must transpile — not a bare-browser import). The DC layer (`templates/**/*.dc.html`) needs a **Design Components compiler**. **Google Stitch must not treat `*.dc.html` as source of truth** — use `DESIGN.md`, DTCG, `styles.css`, kitchen-sink, and `.cs-*` static HTML instead. Dual path: [docs/consuming.md](docs/consuming.md). The full non-negotiables list lives in `CONTRIBUTING.md` and `docs/doctrine.md`. Operator docs are published on the Storybook **Docs** sidebar at `design.cyberskill.world`.
6
6
 
@@ -31,7 +31,7 @@ The portable contract covers browser and bundler entry points: `styles.css` · `
31
31
  - [templates/](templates/): 85 copyable starting points (`.dc.html`); `email-safe/` send-ready emails; `kitchen-sink.html`; `playground.html`
32
32
  - [guidelines/](guidelines/): specimen cards + `atomic-view.html` (portable component grid) — host product surface is Storybook at `/`
33
33
  - [examples/static-hello/](examples/static-hello/): zero-install static consumer (Stitch / plain HTML)
34
- - [examples/npm-hello/](examples/npm-hello/): first registry **browser** consumer — `@cyberskill/design@1.7.0` legacy entry (Lumi · Hỏa · plasma); Status Hub teams swap to `thuy`; Next/SSR apps use default `@cyberskill/design` React entry instead
34
+ - [examples/npm-hello/](examples/npm-hello/): first registry **browser** consumer — `@cyberskill/design@1.7.1` legacy entry (Lumi · Hỏa · plasma); Status Hub teams swap to `thuy`; Next/SSR apps use default `@cyberskill/design` React entry instead
35
35
  - [examples/native/](examples/native/): SwiftUI / Compose / Flutter sample apps + store scaffolds — Compose is **Android Studio**-first (no committed `gradlew`; see `examples/native/README.md`)
36
36
  - [ui_kits/](ui_kits/): product recreations — status-hub · website · deck
37
37
  - [fonts/](fonts/): self-hosted Be Vietnam Pro (UI) + Space Grotesk (opt-in display, `--cs-font-family-display`) + JetBrains Mono woff2
@@ -48,7 +48,7 @@ The portable contract covers browser and bundler entry points: `styles.css` · `
48
48
  Published on Storybook **Docs** (`design.cyberskill.world`) and in [docs/viewer.html](docs/viewer.html) (EN|VI).
49
49
 
50
50
  - [docs/consuming.md](docs/consuming.md): adopting & upgrading, DC-capable vs static dual path, package name `@cyberskill/design`; first registry install at [examples/npm-hello/](examples/npm-hello/) (Lumi · Hỏa · plasma); native mirrors at [examples/native/](examples/native/) (SwiftUI / Compose / Flutter samples)
51
- - [docs/release-notes.md](docs/release-notes.md): curated product highlights (not a changelog) — includes `@cyberskill/design@1.7.0` Trusted Publishing / grant pointer
51
+ - [docs/release-notes.md](docs/release-notes.md): curated product highlights (not a changelog) — includes `@cyberskill/design@1.7.1` Trusted Publishing / grant pointer
52
52
  - [docs/consumer-grant.md](docs/consumer-grant.md): written npm grant (CyberSkill portfolio; UNLICENSED)
53
53
  - [docs/conventions.md](docs/conventions.md): authoring rules (naming grammar, the four axes)
54
54
  - [docs/design-styles.md](docs/design-styles.md): the live styling axes and the fixed liquid-glass treatment
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cyberskill/design",
3
- "version": "1.7.0",
3
+ "version": "1.7.1",
4
4
  "private": false,
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -6,6 +6,7 @@
6
6
  */
7
7
  (() => {
8
8
  const UMBER = '45210E';
9
+ const DOC_FILL = 'FDE68A';
9
10
  const A4 = { w: 11906, h: 16838, name: 'A4', ptW: 595.28, ptH: 841.89 };
10
11
  const LETTER = { w: 12240, h: 15840, name: 'Letter', ptW: 612, ptH: 792 };
11
12
  function pageSizeFromCss() {
@@ -123,17 +124,21 @@
123
124
  return el.getAttribute && el.getAttribute('data-omelette-chrome') != null;
124
125
  }
125
126
 
127
+ function isDocFillColor(bg) {
128
+ return bg && /rgb\(\s*253\s*,\s*230\s*,\s*138\s*\)/i.test(bg);
129
+ }
130
+
126
131
  function textRuns(el) {
127
132
  const parts = [];
128
- const walk = (node, italic, bold, color) => {
133
+ const walk = (node, italic, bold, color, fill) => {
129
134
  if (node.nodeType === 3) {
130
135
  const raw = node.textContent || '';
131
136
  if (!raw) return;
132
137
  if (!raw.replace(/\s+/g, '').length) {
133
- if (parts.length) parts.push({ t: ' ', italic, bold, color });
138
+ if (parts.length) parts.push({ t: ' ', italic, bold, color, fill });
134
139
  return;
135
140
  }
136
- parts.push({ t: raw.replace(/\s+/g, ' '), italic, bold, color });
141
+ parts.push({ t: raw.replace(/\s+/g, ' '), italic, bold, color, fill });
137
142
  return;
138
143
  }
139
144
  if (node.nodeType !== 1) return;
@@ -152,9 +157,22 @@
152
157
  if (/^h[1-6]$/.test(tag) || (st.color && /rgb\(\s*69\s*,\s*33\s*,\s*14\s*\)/.test(st.color))) {
153
158
  nextColor = UMBER;
154
159
  }
155
- for (const c of node.childNodes) walk(c, nextItalic, nextBold, nextColor);
160
+ const nextFill = fill || (isDocFillColor(st.backgroundColor) ? DOC_FILL : null);
161
+ const kids = [...node.childNodes];
162
+ for (let i = 0; i < kids.length; i++) {
163
+ const before = parts.length;
164
+ walk(kids[i], nextItalic, nextBold, nextColor, nextFill);
165
+ const nxt = kids[i + 1];
166
+ if (parts.length > before && nxt) {
167
+ const last = parts[parts.length - 1];
168
+ const nextRaw = nxt.textContent || '';
169
+ if (last && last.t && !/\s$/.test(last.t) && nextRaw.replace(/\s+/g, '') && !/^\s/.test(nextRaw)) {
170
+ parts.push({ t: ' ', italic: nextItalic, bold: nextBold, color: nextColor, fill: nextFill });
171
+ }
172
+ }
173
+ }
156
174
  };
157
- walk(el, false, false, null);
175
+ walk(el, false, false, null, null);
158
176
  const merged = [];
159
177
  for (const r of parts) {
160
178
  const prev = merged[merged.length - 1];
@@ -162,7 +180,8 @@
162
180
  prev &&
163
181
  prev.italic === r.italic &&
164
182
  prev.bold === r.bold &&
165
- prev.color === r.color
183
+ prev.color === r.color &&
184
+ prev.fill === r.fill
166
185
  ) {
167
186
  prev.t += r.t;
168
187
  } else {
@@ -182,6 +201,7 @@
182
201
  if (r.bold) rPr.push('<w:b/>');
183
202
  if (r.italic) rPr.push('<w:i/>');
184
203
  if (r.color) rPr.push(`<w:color w:val="${r.color}"/>`);
204
+ if (r.fill) rPr.push(`<w:shd w:val="clear" w:fill="${r.fill}"/><w:highlight w:val="yellow"/>`);
185
205
  rPr.push('<w:rFonts w:ascii="Arial" w:hAnsi="Arial" w:cs="Arial"/>');
186
206
  const pr = rPr.length ? `<w:rPr>${rPr.join('')}</w:rPr>` : '';
187
207
  return `<w:r>${pr}<w:t xml:space="preserve">${xmlEscape(r.t)}</w:t></w:r>`;
@@ -189,11 +209,21 @@
189
209
  .join('');
190
210
  }
191
211
 
212
+ function pPrXml(el, style) {
213
+ const bits = [];
214
+ if (style) bits.push(`<w:pStyle w:val="${style}"/>`);
215
+ if (el) {
216
+ const ta = window.getComputedStyle(el).textAlign;
217
+ if (ta === 'center') bits.push('<w:jc w:val="center"/>');
218
+ else if (ta === 'right' || ta === 'end') bits.push('<w:jc w:val="right"/>');
219
+ }
220
+ return bits.length ? `<w:pPr>${bits.join('')}</w:pPr>` : '';
221
+ }
222
+
192
223
  function paraXml(el, style) {
193
224
  const runs = textRuns(el);
194
225
  if (!runs.length && !el.querySelector?.('br')) return '';
195
- const pPr = style ? `<w:pPr><w:pStyle w:val="${style}"/></w:pPr>` : '';
196
- return `<w:p>${pPr}${runsToXml(runs)}</w:p>`;
226
+ return `<w:p>${pPrXml(el, style)}${runsToXml(runs)}</w:p>`;
197
227
  }
198
228
 
199
229
  function cellInnerXml(cell, fillWhite) {
@@ -214,11 +244,20 @@
214
244
  return `<w:p>${runsToXml(paint(textRuns(cell)))}</w:p>`;
215
245
  }
216
246
 
247
+ function cellColSpan(cell) {
248
+ return Math.max(1, Number(cell.getAttribute('colspan')) || 1);
249
+ }
250
+
251
+ function rowColCount(tr) {
252
+ return [...tr.children].reduce((n, c) => n + cellColSpan(c), 0);
253
+ }
254
+
217
255
  function tableXml(table) {
218
256
  const rows = [...table.querySelectorAll(':scope > tbody > tr, :scope > thead > tr, :scope > tr')];
219
257
  if (!rows.length) return '';
220
- const gridCols = Math.max(...rows.map((r) => r.children.length), 1);
258
+ const gridCols = Math.max(...rows.map(rowColCount), 1);
221
259
  const colW = Math.floor(9000 / gridCols);
260
+ const gridColsXml = Array.from({ length: gridCols }, () => `<w:gridCol w:w="${colW}"/>`).join('');
222
261
  let xml = `<w:tbl><w:tblPr><w:tblW w:w="5000" w:type="pct"/><w:tblBorders>
223
262
  <w:top w:val="single" w:sz="4" w:color="C9B8A8"/>
224
263
  <w:left w:val="single" w:sz="4" w:color="C9B8A8"/>
@@ -226,16 +265,21 @@
226
265
  <w:right w:val="single" w:sz="4" w:color="C9B8A8"/>
227
266
  <w:insideH w:val="single" w:sz="4" w:color="C9B8A8"/>
228
267
  <w:insideV w:val="single" w:sz="4" w:color="C9B8A8"/>
229
- </w:tblBorders></w:tblPr><w:tblGrid>${'<w:gridCol w:w="' + colW + '"/>'.repeat(gridCols)}</w:tblGrid>`;
268
+ </w:tblBorders></w:tblPr><w:tblGrid>${gridColsXml}</w:tblGrid>`;
230
269
  for (const tr of rows) {
231
270
  xml += '<w:tr>';
232
271
  for (const cell of tr.children) {
233
272
  const bg = window.getComputedStyle(cell).backgroundColor;
234
273
  const umberFill = bg && /rgb\(\s*69\s*,\s*33\s*,\s*14\s*\)/.test(bg);
235
- const shade = umberFill
236
- ? `<w:tcPr><w:shd w:val="clear" w:fill="${UMBER}"/><w:tcW w:w="${colW}" w:type="dxa"/></w:tcPr>`
237
- : `<w:tcPr><w:tcW w:w="${colW}" w:type="dxa"/></w:tcPr>`;
238
- xml += `<w:tc>${shade}${cellInnerXml(cell, umberFill)}</w:tc>`;
274
+ const yellowFill = isDocFillColor(bg);
275
+ const span = cellColSpan(cell);
276
+ const spanXml = span > 1 ? `<w:gridSpan w:val="${span}"/>` : '';
277
+ const fillXml = umberFill
278
+ ? `<w:shd w:val="clear" w:fill="${UMBER}"/>`
279
+ : yellowFill
280
+ ? `<w:shd w:val="clear" w:fill="${DOC_FILL}"/>`
281
+ : '';
282
+ xml += `<w:tc><w:tcPr>${fillXml}${spanXml}<w:tcW w:w="${colW * span}" w:type="dxa"/></w:tcPr>${cellInnerXml(cell, umberFill)}</w:tc>`;
239
283
  }
240
284
  xml += '</w:tr>';
241
285
  }
@@ -257,10 +301,11 @@
257
301
  const kids = [...el.children].filter((c) => c.nodeType === 1 && !isChrome(c));
258
302
  if (kids.length < 2) return '';
259
303
  const colW = Math.floor(9000 / cols);
304
+ const gridColsXml = Array.from({ length: cols }, () => `<w:gridCol w:w="${colW}"/>`).join('');
260
305
  let xml = `<w:tbl><w:tblPr><w:tblW w:w="5000" w:type="pct"/><w:tblBorders>
261
306
  <w:top w:val="nil"/><w:left w:val="nil"/><w:bottom w:val="nil"/><w:right w:val="nil"/>
262
307
  <w:insideH w:val="nil"/><w:insideV w:val="nil"/>
263
- </w:tblBorders></w:tblPr><w:tblGrid>${'<w:gridCol w:w="' + colW + '"/>'.repeat(cols)}</w:tblGrid>`;
308
+ </w:tblBorders></w:tblPr><w:tblGrid>${gridColsXml}</w:tblGrid>`;
264
309
  for (let i = 0; i < kids.length; i += cols) {
265
310
  xml += '<w:tr>';
266
311
  for (let c = 0; c < cols; c++) {
@@ -286,7 +331,7 @@
286
331
  continue;
287
332
  }
288
333
  if (/^h[1-6]$/.test(tag)) {
289
- blocks.push(paraXml(el, 'Heading1'));
334
+ blocks.push(paraXml(el, tag === 'h1' ? 'Heading1' : 'Heading2'));
290
335
  continue;
291
336
  }
292
337
  const gridXml = gridAsTable(el);
@@ -318,10 +363,9 @@
318
363
  }
319
364
 
320
365
  function headerFooterText() {
321
- return {
322
- header: 'CyberSkill · Hiện Thực Hoá Ý Chí',
323
- footer: 'CyberSkill · MST 0316475200 · info@cyberskill.world',
324
- };
366
+ // Sheet already carries lockup + footer. Word chrome stays empty so the
367
+ // file does not duplicate the card into header/footer.
368
+ return { header: '', footer: '' };
325
369
  }
326
370
 
327
371
  async function buildDocxBlob(sheet) {
@@ -362,25 +406,20 @@
362
406
  <w:name w:val="heading 1"/><w:basedOn w:val="Normal"/><w:qFormat/>
363
407
  <w:rPr><w:b/><w:color w:val="${UMBER}"/><w:sz w:val="28"/></w:rPr>
364
408
  </w:style>
409
+ <w:style w:type="paragraph" w:styleId="Heading2">
410
+ <w:name w:val="heading 2"/><w:basedOn w:val="Normal"/><w:qFormat/>
411
+ <w:rPr><w:b/><w:color w:val="${UMBER}"/><w:sz w:val="24"/></w:rPr>
412
+ </w:style>
365
413
  </w:styles>`;
366
414
 
367
415
  const headerXml = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
368
416
  <w:hdr xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
369
- <w:p><w:pPr><w:pBdr><w:bottom w:val="single" w:sz="6" w:color="C9B8A8"/></w:pBdr></w:pPr>
370
- <w:r><w:rPr><w:b/><w:color w:val="${UMBER}"/><w:sz w:val="18"/></w:rPr>
371
- <w:t xml:space="preserve">${xmlEscape(header)}</w:t></w:r>
372
- </w:p>
417
+ <w:p>${header ? `<w:r><w:t xml:space="preserve">${xmlEscape(header)}</w:t></w:r>` : ''}</w:p>
373
418
  </w:hdr>`;
374
419
 
375
420
  const footerXml = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
376
421
  <w:ftr xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
377
- <w:p>
378
- <w:r><w:rPr><w:sz w:val="16"/><w:color w:val="6B5D4F"/></w:rPr>
379
- <w:t xml:space="preserve">${xmlEscape(footer)} · </w:t></w:r>
380
- <w:r><w:fldChar w:fldCharType="begin"/></w:r>
381
- <w:r><w:instrText xml:space="preserve"> PAGE </w:instrText></w:r>
382
- <w:r><w:fldChar w:fldCharType="end"/></w:r>
383
- </w:p>
422
+ <w:p>${footer ? `<w:r><w:t xml:space="preserve">${xmlEscape(footer)}</w:t></w:r>` : ''}</w:p>
384
423
  </w:ftr>`;
385
424
 
386
425
  const documentXml = `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
@@ -650,28 +689,12 @@
650
689
  ink = true;
651
690
  }
652
691
  if (!ink) throw new Error('blank-raster');
653
- const pageH = Math.round(width * (page.h / page.w) * scale);
654
- const pages = [];
655
- let y = 0;
656
- while (y < canvas.height - 1) {
657
- const ch = Math.min(pageH, canvas.height - y);
658
- const slice = document.createElement('canvas');
659
- slice.width = canvas.width;
660
- slice.height = Math.max(1, ch);
661
- const sctx = slice.getContext('2d');
662
- sctx.fillStyle = '#ffffff';
663
- sctx.fillRect(0, 0, slice.width, slice.height);
664
- sctx.drawImage(canvas, 0, y, canvas.width, ch, 0, 0, canvas.width, ch);
665
- pages.push({
666
- jpeg: dataUrlToBytes(slice.toDataURL('image/jpeg', 0.92)),
667
- w: slice.width,
668
- h: slice.height,
669
- });
670
- y += pageH;
671
- if (pages.length > 40) break;
672
- }
673
- if (!pages.length) throw new Error('no-pages');
674
- return jpegPagesToPdf(pages, page.ptW, page.ptH);
692
+ // One PDF page = the whole card. Slicing to A4 cut tables mid-row and
693
+ // stretched the leftover slice to full page height (squashed last page).
694
+ const jpeg = dataUrlToBytes(canvas.toDataURL('image/jpeg', 0.95));
695
+ const ptW = page.ptW;
696
+ const ptH = ptW * (canvas.height / canvas.width);
697
+ return jpegPagesToPdf([{ jpeg, w: canvas.width, h: canvas.height }], ptW, ptH);
675
698
  }
676
699
 
677
700
  async function buildPdfBlob(sheet) {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$meta": {
3
3
  "system": "CyberSkill Design System",
4
- "version": "1.7.0",
4
+ "version": "1.7.1",
5
5
  "note": "OKLCH seed contract for the 15 element packs × light/dark (30 sets). SoT for scripts/generate-element-packs.mjs — do not hand-edit tokens/elements.css. Owner bar (Jul 2026): soft/middle/deep clearly distinct; middle intensity synced across elements; harmonious role palettes; light↔dark same-hue identity. Public variant names unchanged."
6
6
  },
7
7
  "intensity": {
@@ -1,6 +1,6 @@
1
1
  // CyberSkill Design System — native design tokens.
2
2
  // GENERATED from tokens/tokens.dtcg.json — do not hand-edit; regenerate on token change.
3
- // release v1.7.0 · source sha256 c1e69d03df03c124…
3
+ // release v1.7.1 · source sha256 d067c6f894cc8314…
4
4
  // conversions: rem→px at 16 · em→…Em relative doubles · rgba alpha→ARGB byte (round(a*255)) · durations in ms
5
5
  // dark element packs: see $extensions.overrides.elementsDark
6
6
  // provenance: tokens/provenance.json · parity gate: _audit/token-pipeline-test.html
@@ -1,6 +1,6 @@
1
1
  // CyberSkill Design System — native design tokens.
2
2
  // GENERATED from tokens/tokens.dtcg.json — do not hand-edit; regenerate on token change.
3
- // release v1.7.0 · source sha256 c1e69d03df03c124…
3
+ // release v1.7.1 · source sha256 d067c6f894cc8314…
4
4
  // conversions: rem→px at 16 · em→…Em relative doubles · rgba alpha→ARGB byte (round(a*255)) · durations in ms
5
5
  // dark element packs: see $extensions.overrides.elementsDark
6
6
  // provenance: tokens/provenance.json · parity gate: _audit/token-pipeline-test.html
@@ -1,6 +1,6 @@
1
1
  // CyberSkill Design System — native design tokens.
2
2
  // GENERATED from tokens/tokens.dtcg.json — do not hand-edit; regenerate on token change.
3
- // release v1.7.0 · source sha256 c1e69d03df03c124…
3
+ // release v1.7.1 · source sha256 d067c6f894cc8314…
4
4
  // conversions: rem→px at 16 · em→…Em relative doubles · rgba alpha→ARGB byte (round(a*255)) · durations in ms
5
5
  // dark element packs: see $extensions.overrides.elementsDark
6
6
  // provenance: tokens/provenance.json · parity gate: _audit/token-pipeline-test.html
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "system": "CyberSkill Design System",
3
- "release": "1.7.0",
3
+ "release": "1.7.1",
4
4
  "source": "tokens/tokens.dtcg.json",
5
- "sourceSha256": "c1e69d03df03c12412835e06ba087c8a73a3c418007d9f47cdbcea85c5dadf53",
5
+ "sourceSha256": "d067c6f894cc83141be9b3afd469934b1292fb2f4dc0c200af385f44f7d36752",
6
6
  "dtcgStamp": {
7
- "version": "1.7.0",
7
+ "version": "1.7.1",
8
8
  "generated": "2026-07-23"
9
9
  },
10
10
  "conversions": {
@@ -36,17 +36,17 @@
36
36
  {
37
37
  "file": "tokens/native/CSTokens.swift",
38
38
  "lang": "swift",
39
- "sha256": "ca83e3cf8b01f7acc8c06ca1aded61b64350818c91426ff026e576eec2bfd788"
39
+ "sha256": "55daba84d5acdf3b0f995962219edb72676b92092c94a28abf74740058168f27"
40
40
  },
41
41
  {
42
42
  "file": "tokens/native/CSTokens.kt",
43
43
  "lang": "kotlin",
44
- "sha256": "bceb1925ac096d02637e24a78efdf8b18527fa95fdc76a5395de2d734b451256"
44
+ "sha256": "59812e3e8773573cbb79962672536caf64a2abfb3361a161cbb4838e016d213f"
45
45
  },
46
46
  {
47
47
  "file": "tokens/native/cs_tokens.dart",
48
48
  "lang": "dart",
49
- "sha256": "4c0702c11721596654f91aba4f8dc0d85dcf7027a50449ab94f9bf992f0ee69d"
49
+ "sha256": "44729f83b8ba64becf79faad0a55916b35347ee42041d61e91132be565e18239"
50
50
  }
51
51
  ]
52
52
  }
@@ -3,7 +3,7 @@
3
3
  "$extensions": {
4
4
  "com.cyberskill": {
5
5
  "system": "CyberSkill Design System",
6
- "version": "1.7.0",
6
+ "version": "1.7.1",
7
7
  "generated": "2026-07-23",
8
8
  "source": "tokens/tokens.json",
9
9
  "note": "Scope overrides (dark/system theme · 15 element×variant packs) are carried under $extensions.overrides keyed by CSS selector — apply the matching selector on :root/ancestor to activate.",
package/tokens/tokens.js CHANGED
@@ -1,8 +1,8 @@
1
- // CyberSkill design tokens — generated from tokens/*.css (v1.7.0). Do not edit by hand.
1
+ // CyberSkill design tokens — generated from tokens/*.css (v1.7.1). Do not edit by hand.
2
2
  export const tokens = {
3
3
  "$meta": {
4
4
  "system": "CyberSkill Design System",
5
- "version": "1.7.0",
5
+ "version": "1.7.1",
6
6
  "generated": "2026-07-23",
7
7
  "note": "Generated from tokens/*.css. Root grouped by category; theme/element scopes carry overrides only. Regenerate after any token change (see docs/conventions.md)."
8
8
  },
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$meta": {
3
3
  "system": "CyberSkill Design System",
4
- "version": "1.7.0",
4
+ "version": "1.7.1",
5
5
  "generated": "2026-07-23",
6
6
  "note": "Generated from tokens/*.css. Root grouped by category; theme/element scopes carry overrides only. Regenerate after any token change (see docs/conventions.md)."
7
7
  },