update skill ba

This commit is contained in:
Canhchimlac
2026-09-11 23:01:18 +07:00
parent 2c7bcde741
commit d169c85dd4
51 changed files with 4111 additions and 30 deletions

View File

@@ -0,0 +1,58 @@
# FIGMA_US002-003_v1.0 — Gói nhập vào Figma
| | |
|---|---|
| **Sinh bởi** | skill `ba-design`, activity `figma` |
| **US / màn hình** | US-002 (Xem giỏ hàng nhóm theo seller), US-003 (Sửa số lượng / xoá sản phẩm trong giỏ) — cùng `SCR-04` Giỏ hàng |
| **Nguồn** | `../HIFI_US002-003_v1.0.html` (bố cục v1.1, 2026-09-09) · `00-index/DS_e-commerce_v1.0.md` (v1.1, `00-index/ds/tokens.json`) · `03-specification/WF_US002-003_v1.0.md` · `03-specification/SRS_US002-003_v1.0.md` |
| **Vì sao không có file `.fig`** | `.fig` là định dạng nhị phân độc quyền; REST API của Figma không cho tạo node thiết kế. Gói này gồm các định dạng Figma **nhập được** và giữ được layer/text/token. |
| **Độ tin cậy visual** | 🔴 — token trong `tokens.dtcg.json` là placeholder trung tính của template `ba-design` (dự án chưa có brand guideline — SAD §7.0, chưa chọn design system — `OQ-022`). Designer/PO cần chốt trước khi coi các file SVG này là visual cuối cùng |
| **v1.1 (2026-09-09)** | Bổ sung `F01`/`C07` còn thiếu cho dòng "Balo du lịch" ở `SCR-04.desktop.svg`; cập nhật `SCR-04.mobile.svg` theo bố cục mobile mới (nhóm thao tác F01+C07 xuống hàng riêng — theo `ds-components` v1.1, tiện ích `.ds-m-full`); `png/` đã có 8 ảnh (xem bên dưới) |
## Nội dung gói
| File | Định dạng | Nhập vào Figma bằng | Sửa được trong Figma |
|---|---|---|---|
| `SCR-04.desktop.svg` | SVG (1440×900), trạng thái mặc định — đủ `F01`/`C07` cho **mọi** dòng `CartItem` (kể cả "Balo du lịch", bổ sung ở v1.1) | Kéo thả vào canvas, hoặc **File → Place image / Import** | ✅ Layer vector, text, tên layer = `Z1`/`Z2`/`Z3`/`C02`/`C03`/`C04`/`C05`/`C06`/`F01`/`C07`/`C08`/`C09`/`C11` |
| `SCR-04.mobile.svg` | SVG (390×844), trạng thái mặc định — cập nhật v1.1: nhóm thao tác (F01+C07) nằm hàng riêng dưới khối text, khớp `.ds-m-full` trong HIFI | Kéo thả | ✅ Layer vector — `Z3` là footer sticky đáy màn hình (khác desktop: sidebar bên phải) theo `WF` §2 |
| `tokens.dtcg.json` | Design token chuẩn W3C DTCG (bản sao `00-index/ds/tokens.json`) | Plugin **Tokens Studio for Figma** → Import → JSON; hoặc **Variables → Import** nếu tài khoản có API variables | ✅ Thành Figma Variables / Styles |
| `png/` | 8 ảnh chụp `HIFI_US002-003_v1.0.html` bằng Chrome headless (`scripts/render-figma.sh`, chụp 2026-09-09): `SCR-04.{desktop,mobile}.{default,loading,empty-none,error}.png` | Kéo thả | ❌ Chỉ để tham chiếu và đối chiếu pixel — **ảnh mobile chụp từ bản HIFI trước khi sửa lỗi bố cục §"v1.1" ở trên, nên chụp lại** (xem "Việc còn lại") |
| `../HIFI_US002-003_v1.0.html` | HTML tự chứa | Plugin **html.to.design** (divRIOTS) → *Import from file* hoặc *from URL* khi host tạm bằng `python3 -m http.server` | ✅ Layer đầy đủ theo DOM, auto-layout |
## Thứ tự nhập khuyến nghị
1. **Token trước:** nhập `tokens.dtcg.json` bằng Tokens Studio → *Create Styles / Variables* để có bảng màu, chữ, khoảng cách trùng tên `--ds-*`. Vì token còn placeholder (🔴), đặt tên style rõ ràng kiểu "e-commerce/placeholder/…" để không nhầm là bảng màu chính thức.
2. **Component sheet:** nhập `../../00-index/ds/components.html` bằng html.to.design vào page *Components*; hoặc dựng component từ SVG và gán style vừa tạo.
3. **Màn hình:** kéo `SCR-04.desktop.svg` và `SCR-04.mobile.svg` vào page *Screens*, đổi tên frame thành `SCR-04 · Giỏ hàng · desktop` / `SCR-04 · Giỏ hàng · mobile`.
4. **Trạng thái khác** (đang tải, rỗng, lỗi tải — xem `HIFI_US002-003_v1.0.html?scr=SCR-04&state=…`): gói này **chưa có SVG riêng cho từng trạng thái** (chỉ có `default`) — Designer dựng thêm trong Figma dựa trên `HIFI` (mở với `?state=loading`/`empty-none`/`error` để xem) nếu cần, hoặc yêu cầu chạy lại `figma` với các hậu tố trạng thái.
5. **Đối chiếu:** mở `png/` cạnh frame để kiểm tra khoảng cách và màu khớp HIFI — đã có 8 ảnh (2026-09-09); **ảnh mobile nên chụp lại** sau bản HIFI v1.1 (xem "Việc còn lại").
## Lưu ý
- **Font:** SVG ghi font `Segoe UI, Roboto, Helvetica Neue, Arial, sans-serif` (system stack, chưa có font brand); máy không có font ⇒ Figma thay bằng font gần nhất. Không cần cài thêm font đặc biệt ở lần chạy này.
- **Màu trong SVG là mã nguyên văn** từ `tokens.dtcg.json` (Figma không đọc biến CSS); thuộc tính `data-token` ghi tên token để tra ngược. Sửa màu ⇒ sửa `00-index/ds/tokens.json` rồi chạy lại `ds` + `hifi` + `figma`, không sửa tay SVG.
- **Hành vi không nằm trong Figma.** Prototype link trong Figma chỉ mô phỏng điều hướng theo `SRS` §2.A.2; điều kiện, validation, mã lỗi đọc ở `SRS_US002-003_v1.0.md`. Khi Figma và SRS lệch: SRS thắng về tồn tại/hành vi/text, Figma thắng về bố cục (W11) — ghi lệch vào `WF_US002-003_v1.0.md` §5 (đã có 4 dòng chờ PO/Tech Lead quyết, xem đó trước khi sửa SVG theo ý riêng).
- **Không dùng gói này để thay `HIFI`.** `HIFI_US002-003_v1.0.html` là nguồn sự thật về visual đã đề xuất (🔴 chưa duyệt); Figma là bản làm việc của Designer. Designer sửa trong Figma ⇒ báo BA để chạy lại `hifi` + `figma` với `--proto <link Figma>`.
- **Số liệu trong SVG là dữ liệu minh hoạ** (VD "Áo thun basic", "250.000 ₫") để hình dung bố cục thật — không phải dữ liệu SRS quy định (SRS không có ví dụ số cụ thể ngoài `AC_US-002_v1.0.md` §Dữ liệu mẫu, vốn dùng bộ số khác). Không suy ra số liệu nghiệp vụ từ SVG/HIFI.
## Việc còn lại — cần người điều phối (có Bash/Chrome)
| # | Việc | Lệnh |
|---|---|---|
| 1 | Chụp lại PNG mobile sau bản HIFI v1.1 (sửa lỗi bố cục §"v1.1" ở trên) — desktop không đổi cấu trúc DOM, không bắt buộc chụp lại nhưng chụp lại toàn bộ cho đồng bộ cũng được | `.claude/skills/ba-design/scripts/render-figma.sh 03-specification/design/HIFI_US002-003_v1.0.html 03-specification/design/FIGMA_US002-003_v1.0/png` |
| 2 | Chạy lại phép kiểm máy đầy đủ (T1/T2/H1–H5/S1) trên bản HIFI/SVG v1.1 mới nhất — lần chạy 2026-09-09 (chép ở `DSPEC` §6) thực hiện trên bản trước khi sửa mobile | xem lệnh ở `DSPEC_US002-003_v1.0.md` §6 |
## Kiểm tra trước khi giao
```bash
node .claude/skills/ba-design/scripts/design-check.mjs --tokens 00-index/ds/tokens.json --svg-dir 03-specification/design/FIGMA_US002-003_v1.0
```
Kết quả chạy 2026-09-09 (người điều phối, trên bản SVG trước khi bổ sung F01/C07 dòng "Balo du lịch"):
```
✅ S1 SVG: 2 file, màu ⊆ token
✅ S1 SVG phủ desktop+mobile cho 1 SCR
```
Tự kiểm tay bản v1.1 (sau khi bổ sung component còn thiếu): 9 mã màu dùng trong hai SVG đều khớp `tokens.json` (`#F6F7F9`, `#1B1F24`, `#5B6472`, `#FFFFFF`, `#D5DAE1`, `#EEF1F5`, `#767F8C`, `#B42318`, `#2456A6`); tập id `C02, C03, C04, C05, C06, F01, C07, C08, C09, C11` ⊆ tập `data-c`/`data-f` của `HIFI_US002-003_v1.0.html` (14 ID: `C01`…`C13`, `F01`) — **khuyến nghị chạy lại lệnh trên bằng máy để có kết quả chính thức cho bản v1.1**.

View File

@@ -0,0 +1,81 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
SCR-04.desktop.svg — khung Giỏ hàng (US-002/US-003), trạng thái default, khung nhìn desktop (1440×900).
Nguồn: HIFI_US002-003_v1.0.html#SCR-04 · SRS_US002-003_v1.0.md §2.A.3.1/§4.2 · WF_US002-003_v1.0.md §3.1.1/§3.1.2 · 00-index/ds/tokens.json
Màu là mã nguyên văn từ tokens.json (Figma không đọc biến CSS) kèm data-token để tra ngược.
Layer <g id="Zn"> theo WF §3.1.1; <g id="Cnn"> theo SRS §2.A.3.1. Text nguyên văn SRS §4.2 (số liệu minh hoạ không phải một phần khoá i18n).
Độ tin cậy visual: 🔴 (DS_e-commerce §0 — token placeholder trung tính, chưa có brand/design system, OQ-022).
v1.1 (2026-09-09): bổ sung F01/C07 còn thiếu cho dòng "Balo du lịch" (Shop B) — theo ghi chú người duyệt, SVG phải phản chiếu đủ C-id của HIFI cho mỗi dòng hiển thị.
-->
<svg xmlns="http://www.w3.org/2000/svg" width="1440" height="900" viewBox="0 0 1440 900" font-family="Segoe UI, Roboto, Helvetica Neue, Arial, sans-serif" font-size="14" data-scr="SCR-04" data-view="desktop" data-state="default" data-source="HIFI_US002-003_v1.0.html#SCR-04">
<title>SCR-04 · Giỏ hàng · desktop · default</title>
<rect id="canvas" width="1440" height="900" fill="#F6F7F9" data-token="color.bg.canvas"/>
<g id="Z1" data-name="Header màn hình" transform="translate(120 48)">
<text x="0" y="28" font-size="24" font-weight="600" fill="#1B1F24" data-token="color.text.primary" data-key="cart.title">Giỏ hàng của bạn</text>
<text x="230" y="28" font-size="16" fill="#5B6472" data-token="color.text.secondary" data-key="cart.itemCount">(5 sản phẩm — minh hoạ)</text>
</g>
<g id="Z2" data-name="Danh sách nhóm seller" transform="translate(120 104)">
<!-- Nhóm seller Shop A -->
<g data-name="Card nhóm seller">
<rect width="800" height="164" rx="8" fill="#FFFFFF" stroke="#D5DAE1" data-token="color.border.default"/>
<g id="C02"><text x="16" y="30" font-size="16" font-weight="600" fill="#1B1F24" data-token="color.text.primary">Shop A</text></g>
<g data-name="CartItem 1" transform="translate(16 44)">
<g id="C03"><rect width="64" height="64" rx="4" fill="#EEF1F5" stroke="#D5DAE1" data-token="color.bg.subtle"/></g>
<g transform="translate(76 4)">
<text id="C04" y="16" fill="#1B1F24" data-token="color.text.primary">Áo thun basic</text>
<text id="C05" y="36" font-size="12" fill="#5B6472" data-token="color.text.secondary">Size M, Đỏ</text>
<text id="C06" y="54" font-size="12" fill="#5B6472" data-token="color.text.secondary">100.000 ₫</text>
</g>
<g id="F01" transform="translate(560 12)">
<rect width="112" height="36" rx="4" fill="#FFFFFF" stroke="#767F8C" data-token="color.border.strong"/>
<text x="20" y="23" fill="#1B1F24" data-token="color.text.primary">− 2 +</text>
</g>
<g id="C07" transform="translate(690 12)">
<rect width="80" height="36" rx="4" fill="#B42318" data-token="color.status.danger"/>
<text x="40" y="23" text-anchor="middle" font-weight="600" fill="#FFFFFF" data-token="color.text.inverse" data-key="btn.delete">Xoá</text>
</g>
</g>
<g id="C08" transform="translate(600 132)"><text text-anchor="end" x="184" fill="#1B1F24" data-token="color.text.primary">Tạm tính: 250.000 ₫</text></g>
</g>
<!-- Nhóm seller Shop B -->
<g transform="translate(0 180)" data-name="Card nhóm seller">
<rect width="800" height="164" rx="8" fill="#FFFFFF" stroke="#D5DAE1" data-token="color.border.default"/>
<g id="C02"><text x="16" y="30" font-size="16" font-weight="600" fill="#1B1F24" data-token="color.text.primary">Shop B</text></g>
<g data-name="CartItem 2" transform="translate(16 44)">
<g id="C03"><rect width="64" height="64" rx="4" fill="#EEF1F5" stroke="#D5DAE1" data-token="color.bg.subtle"/></g>
<g transform="translate(76 4)">
<text id="C04" y="16" fill="#1B1F24" data-token="color.text.primary">Balo du lịch</text>
<text id="C05" y="36" font-size="12" fill="#5B6472" data-token="color.text.secondary">Đen</text>
<text id="C06" y="54" font-size="12" fill="#5B6472" data-token="color.text.secondary">200.000 ₫</text>
</g>
<g id="F01" transform="translate(560 12)">
<rect width="112" height="36" rx="4" fill="#FFFFFF" stroke="#767F8C" data-token="color.border.strong"/>
<text x="20" y="23" fill="#1B1F24" data-token="color.text.primary">− 1 +</text>
</g>
<g id="C07" transform="translate(690 12)">
<rect width="80" height="36" rx="4" fill="#B42318" data-token="color.status.danger"/>
<text x="40" y="23" text-anchor="middle" font-weight="600" fill="#FFFFFF" data-token="color.text.inverse" data-key="btn.delete">Xoá</text>
</g>
</g>
<g id="C08" transform="translate(600 132)"><text text-anchor="end" x="184" fill="#1B1F24" data-token="color.text.primary">Tạm tính: 260.000 ₫</text></g>
</g>
</g>
<g id="Z3" data-name="Tổng kết (sidebar desktop / footer mobile)" transform="translate(960 104)">
<rect width="360" height="120" rx="8" fill="#FFFFFF" stroke="#D5DAE1" data-token="color.border.default"/>
<g id="C09"><text x="16" y="36" font-size="20" font-weight="600" fill="#1B1F24" data-token="color.text.primary">Tổng cộng: 510.000 ₫</text></g>
<g id="C11" transform="translate(16 56)">
<rect width="328" height="36" rx="4" fill="#2456A6" data-token="color.brand.primary"/>
<text x="164" y="23" text-anchor="middle" font-weight="600" fill="#FFFFFF" data-token="color.text.inverse" data-key="btn.checkout">Tiến hành Checkout</text>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.7 KiB

View File

@@ -0,0 +1,78 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
SCR-04.mobile.svg — khung Giỏ hàng (US-002/US-003), trạng thái default, khung nhìn mobile (390×844).
Z3 (Tổng kết) hiển thị dạng footer sticky đáy màn hình theo WF §2/§3.1.1 (khác desktop: sidebar bên phải).
Nguồn/quy tắc màu — xem SCR-04.desktop.svg. Độ tin cậy visual: 🔴 (OQ-022).
v1.1 (2026-09-09): bổ sung F01/C07 còn thiếu cho dòng "Balo du lịch" (Shop B), đặt ở hàng riêng dưới khối text
(khớp bản sửa lỗi bố cục mobile của HIFI — ds-components v1.1, .ds-m-full — xem DSPEC §2.1).
-->
<svg xmlns="http://www.w3.org/2000/svg" width="390" height="844" viewBox="0 0 390 844" font-family="Segoe UI, Roboto, Helvetica Neue, Arial, sans-serif" font-size="13" data-scr="SCR-04" data-view="mobile" data-state="default" data-source="HIFI_US002-003_v1.0.html#SCR-04">
<title>SCR-04 · Giỏ hàng · mobile · default</title>
<rect id="canvas" width="390" height="844" fill="#F6F7F9" data-token="color.bg.canvas"/>
<g id="Z1" data-name="Header màn hình" transform="translate(16 20)">
<text x="0" y="24" font-size="18" font-weight="600" fill="#1B1F24" data-token="color.text.primary" data-key="cart.title">Giỏ hàng của bạn</text>
<text x="0" y="42" font-size="12" fill="#5B6472" data-token="color.text.secondary" data-key="cart.itemCount">(5 sản phẩm — minh hoạ)</text>
</g>
<g id="Z2" data-name="Danh sách nhóm seller" transform="translate(16 76)">
<g data-name="Card nhóm seller">
<rect width="358" height="164" rx="8" fill="#FFFFFF" stroke="#D5DAE1" data-token="color.border.default"/>
<g id="C02"><text x="12" y="26" font-size="14" font-weight="600" fill="#1B1F24" data-token="color.text.primary">Shop A</text></g>
<g data-name="CartItem 1" transform="translate(12 38)">
<g id="C03"><rect width="56" height="56" rx="4" fill="#EEF1F5" stroke="#D5DAE1" data-token="color.bg.subtle"/></g>
<g transform="translate(64 2)">
<text id="C04" y="14" fill="#1B1F24" data-token="color.text.primary">Áo thun basic</text>
<text id="C05" y="32" font-size="11" fill="#5B6472" data-token="color.text.secondary">Size M, Đỏ</text>
<text id="C06" y="48" font-size="11" fill="#5B6472" data-token="color.text.secondary">100.000 ₫</text>
</g>
</g>
<g id="F01" transform="translate(12 104)">
<rect width="100" height="44" rx="4" fill="#FFFFFF" stroke="#767F8C" data-token="color.border.strong"/>
<text x="18" y="27" fill="#1B1F24" data-token="color.text.primary">− 2 +</text>
</g>
<g id="C07" transform="translate(246 104)">
<rect width="100" height="44" rx="4" fill="#B42318" data-token="color.status.danger"/>
<text x="50" y="27" text-anchor="middle" font-weight="600" fill="#FFFFFF" data-token="color.text.inverse" data-key="btn.delete">Xoá</text>
</g>
</g>
<g id="C08" transform="translate(174 250)"><text text-anchor="end" x="184" fill="#1B1F24" data-token="color.text.primary">Tạm tính: 250.000 ₫</text></g>
<g transform="translate(0 280)" data-name="Card nhóm seller">
<rect width="358" height="164" rx="8" fill="#FFFFFF" stroke="#D5DAE1" data-token="color.border.default"/>
<g id="C02"><text x="12" y="26" font-size="14" font-weight="600" fill="#1B1F24" data-token="color.text.primary">Shop B</text></g>
<g data-name="CartItem 2" transform="translate(12 38)">
<g id="C03"><rect width="56" height="56" rx="4" fill="#EEF1F5" stroke="#D5DAE1" data-token="color.bg.subtle"/></g>
<g transform="translate(64 2)">
<text id="C04" y="14" fill="#1B1F24" data-token="color.text.primary">Balo du lịch</text>
<text id="C05" y="32" font-size="11" fill="#5B6472" data-token="color.text.secondary">Đen</text>
<text id="C06" y="48" font-size="11" fill="#5B6472" data-token="color.text.secondary">200.000 ₫</text>
</g>
</g>
<g id="F01" transform="translate(12 104)">
<rect width="100" height="44" rx="4" fill="#FFFFFF" stroke="#767F8C" data-token="color.border.strong"/>
<text x="18" y="27" fill="#1B1F24" data-token="color.text.primary">− 1 +</text>
</g>
<g id="C07" transform="translate(246 104)">
<rect width="100" height="44" rx="4" fill="#B42318" data-token="color.status.danger"/>
<text x="50" y="27" text-anchor="middle" font-weight="600" fill="#FFFFFF" data-token="color.text.inverse" data-key="btn.delete">Xoá</text>
</g>
</g>
<g id="C08" transform="translate(174 530)"><text text-anchor="end" x="184" fill="#1B1F24" data-token="color.text.primary">Tạm tính: 260.000 ₫</text></g>
</g>
<!-- Z3 — footer sticky đáy màn hình (mobile khác desktop: nằm dưới thay vì sidebar phải) -->
<g id="Z3" data-name="Tổng kết (footer mobile)" transform="translate(0 764)">
<rect width="390" height="80" fill="#FFFFFF" data-token="color.bg.surface"/>
<line x1="0" y1="0.5" x2="390" y2="0.5" stroke="#D5DAE1" data-token="color.border.default"/>
<g id="C09"><text x="16" y="30" font-size="16" font-weight="600" fill="#1B1F24" data-token="color.text.primary">Tổng cộng: 510.000 ₫</text></g>
<g id="C11" transform="translate(16 40)">
<rect width="358" height="30" rx="4" fill="#2456A6" data-token="color.brand.primary"/>
<text x="179" y="20" text-anchor="middle" font-weight="600" fill="#FFFFFF" data-token="color.text.inverse" data-key="btn.checkout">Tiến hành Checkout</text>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 117 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 101 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 106 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

View File

@@ -0,0 +1,106 @@
{
"$schema": "https://tr.designtokens.org/format/",
"$description": "DS_e-commerce — design token theo chuẩn W3C DTCG. Nguồn sự thật duy nhất về màu/chữ/khoảng cách; tokens.css và khối :root trong HIFI_*.html phải sinh từ file này (kiểm bằng scripts/design-check.mjs). Giá trị bên dưới là PLACEHOLDER trung tính của template ba-design — dự án chưa có brand guideline (SAD §7.0: 'không có brand guideline cố định') và chưa chọn design system tham chiếu (OQ-022). KHÔNG coi đây là đề xuất nhận diện đã duyệt — xem DS_e-commerce_v1.0.md §0.",
"color": {
"bg": {
"canvas": { "$type": "color", "$value": "#F6F7F9", "$description": "Nền trang" },
"surface": { "$type": "color", "$value": "#FFFFFF", "$description": "Nền card/bảng/modal" },
"subtle": { "$type": "color", "$value": "#EEF1F5", "$description": "Header bảng, vùng phụ" }
},
"border": {
"default": { "$type": "color", "$value": "#D5DAE1" },
"strong": { "$type": "color", "$value": "#767F8C" }
},
"text": {
"primary": { "$type": "color", "$value": "#1B1F24" },
"secondary": { "$type": "color", "$value": "#5B6472" },
"disabled": { "$type": "color", "$value": "#9AA3AF", "$description": "Miễn kiểm tương phản (WCAG 1.4.3 loại trừ thành phần vô hiệu)" },
"inverse": { "$type": "color", "$value": "#FFFFFF" }
},
"brand": {
"primary": { "$type": "color", "$value": "#2456A6", "$description": "Nút chính, liên kết, focus ring — placeholder trung tính, chưa có brand guideline (OQ-022)" },
"primary-hover": { "$type": "color", "$value": "#1C468A" },
"primary-subtle": { "$type": "color", "$value": "#E7EEF9", "$description": "Nền badge/hàng được chọn" }
},
"status": {
"danger": { "$type": "color", "$value": "#B42318" },
"danger-subtle": { "$type": "color", "$value": "#FDECEA" },
"success": { "$type": "color", "$value": "#1E7B45" },
"success-subtle": { "$type": "color", "$value": "#E6F4EC" },
"warning": { "$type": "color", "$value": "#B7791F" },
"warning-subtle": { "$type": "color", "$value": "#FFF4DE" }
},
"focus": { "ring": { "$type": "color", "$value": "#2456A6" } }
},
"font": {
"family": {
"base": { "$type": "fontFamily", "$value": ["Segoe UI", "Roboto", "Helvetica Neue", "Arial", "sans-serif"], "$description": "PLACEHOLDER — system stack giữ nguyên theo chỉ đạo (không có font brand); ZH/KO/JA cần rà lại fallback font khi có bản dịch (OQ-023)" },
"mono": { "$type": "fontFamily", "$value": ["SFMono-Regular", "Consolas", "Menlo", "monospace"] }
},
"size": {
"xs": { "$type": "dimension", "$value": "12px" },
"sm": { "$type": "dimension", "$value": "14px" },
"md": { "$type": "dimension", "$value": "16px" },
"lg": { "$type": "dimension", "$value": "20px" },
"xl": { "$type": "dimension", "$value": "24px" },
"2xl": { "$type": "dimension", "$value": "32px" }
},
"weight": {
"regular": { "$type": "fontWeight", "$value": 400 },
"semibold": { "$type": "fontWeight", "$value": 600 }
},
"line-height": {
"tight": { "$type": "number", "$value": 1.25 },
"normal": { "$type": "number", "$value": 1.5 }
}
},
"space": {
"1": { "$type": "dimension", "$value": "4px" },
"2": { "$type": "dimension", "$value": "8px" },
"3": { "$type": "dimension", "$value": "12px" },
"4": { "$type": "dimension", "$value": "16px" },
"6": { "$type": "dimension", "$value": "24px" },
"8": { "$type": "dimension", "$value": "32px" },
"12": { "$type": "dimension", "$value": "48px" }
},
"radius": {
"sm": { "$type": "dimension", "$value": "4px" },
"md": { "$type": "dimension", "$value": "8px" },
"pill": { "$type": "dimension", "$value": "999px" }
},
"shadow": {
"sm": { "$type": "shadow", "$value": { "color": "#1B1F2414", "offsetX": "0px", "offsetY": "1px", "blur": "2px", "spread": "0px" } },
"md": { "$type": "shadow", "$value": { "color": "#1B1F2426", "offsetX": "0px", "offsetY": "4px", "blur": "12px", "spread": "0px" } }
},
"size": {
"control": {
"desktop": { "$type": "dimension", "$value": "36px", "$description": "Chiều cao nút/ô nhập desktop" },
"touch": { "$type": "dimension", "$value": "44px", "$description": "Chiều cao tối thiểu trên mobile (hit target ≥ 44px)" }
},
"icon": { "$type": "dimension", "$value": "20px" },
"content-max": { "$type": "dimension", "$value": "1200px", "$description": "PLACEHOLDER — UICONV §1 chưa chốt max-width thật (OQ-018), giữ giá trị template" }
},
"breakpoint": {
"tablet": { "$type": "dimension", "$value": "768px", "$description": "PLACEHOLDER — UICONV §1 chưa chốt ngưỡng thật (OQ-018), giữ giá trị template" },
"desktop": { "$type": "dimension", "$value": "1024px", "$description": "PLACEHOLDER — UICONV §1 chưa chốt ngưỡng thật (OQ-018), giữ giá trị template" }
},
"$extensions": {
"ba": {
"project": "e-commerce",
"version": "1.0",
"source": "UICONV_e-commerce_v1.0.md v1.1 §0/§1/§8/§11 (chưa chốt design system — OQ-022; chưa chốt breakpoint/grid — OQ-018) · brand guideline: chưa có (SAD §7.0) — placeholder trung tính của templates/tokens.json",
"contrastPairs": [
{ "fg": "color.text.primary", "bg": "color.bg.surface", "min": 4.5, "use": "Chữ thường trên nền card (VD tên sản phẩm C04, biến thể C05)" },
{ "fg": "color.text.primary", "bg": "color.bg.canvas", "min": 4.5, "use": "Chữ thường trên nền trang" },
{ "fg": "color.text.secondary", "bg": "color.bg.surface", "min": 4.5, "use": "Hint, tên gian hàng phụ" },
{ "fg": "color.text.inverse", "bg": "color.brand.primary", "min": 4.5, "use": "Nhãn nút chính (C11 Tiến hành Checkout)" },
{ "fg": "color.text.inverse", "bg": "color.status.danger", "min": 4.5, "use": "Nhãn nút nguy hiểm (C07 Xoá)" },
{ "fg": "color.brand.primary", "bg": "color.bg.surface", "min": 4.5, "use": "Liên kết" },
{ "fg": "color.status.danger", "bg": "color.bg.surface", "min": 4.5, "use": "Message lỗi dưới field (E-CART-0002)" },
{ "fg": "color.status.danger", "bg": "color.status.danger-subtle", "min": 4.5, "use": "Banner lỗi tải/cập nhật (C12, E-CART-0003/0006)" },
{ "fg": "color.text.primary", "bg": "color.brand.primary-subtle", "min": 4.5, "use": "Chữ trên badge/hàng chọn" },
{ "fg": "color.border.strong", "bg": "color.bg.surface", "min": 3.0, "use": "Viền ô nhập / bộ đếm F01 (WCAG 1.4.11 non-text)" }
]
}
}
}