Dọn màu play.conan.school về token: 08.09.2026
Site thứ tư về 0, sau www, admin và tokyo. 270 → 0.
play khác phần còn lại của repo: một trò chơi quiz thời gian thực, frontend Vite riêng, backend Durable Object. Nhưng vấn đề màu thì cùng một hình dạng, một màu nhấn không phải màu thương hiệu, lặp lại 48 lần.
#ea580c: màu nhấn thứ ba của repo
play dùng #ea580c (cam) làm màu chính: nút, viền, nền nhấn, cả bóng đổ. Đây là màu thứ ba đóng vai primary trong repo, sau #f26625 của admin và #d94f2b của hệ thiết kế. Không màu nào trong hai màu kia là #d94f2b.
Khác admin ở một điểm quan trọng: play có @import theme.css, và khối @theme của nó chỉ khai token chuyển động (--animate-lobby-bounce…) chứ không khai lại màu. Nghĩa là token thương hiệu vẫn ở đó, sẵn sàng, chỉ là không ai dùng. Đủ để thấy: nạp hệ thiết kế là điều kiện cần, không phải điều kiện đủ.
Hex có alpha: #ea580c10
Hơn 30 lớp dùng hex 8 ký tự, sáu chữ màu cộng hai chữ độ mờ: bg-[#ea580c10], bg-[#11111108], text-[#66666690]. Quy đổi phải tách hai phần và đổi alpha sang phần trăm:
| hex | alpha | token |
|---|---|---|
#ea580c05 | 05 → 2% | bg-primary/2 |
#ea580c10 | 10 → 6% | bg-primary/8 (làm tròn lên bậc dễ đọc) |
#ea580c30 | 30 → 19% | bg-primary/20 |
#11111108 | 08 → 3% | bg-foreground/5 |
Làm tròn về một thang bậc quen (2, 5, 8, 10, 15, 20, 25, 30…) thay vì giữ con số lẻ, sai lệch dưới 2% mắt không thấy, còn bảng độ mờ nhất quán thì người sửa sau đọc được.
Lỗi tôi tự gây ra: thang xám ĐẢO NGƯỢC trên nền tối
Đây là bài học lớn nhất của lượt này.
HostHistory.tsx là một trang nền tối dựng bằng slate-900 / 800 / 750 / 700 / 600. Bộ quy đổi xám của tôi giả định trang nền sáng, 900 là chữ, 200 là viền, 50 là nền:
| lớp gốc | vai trò thật (nền tối) | quy đổi máy móc | hậu quả |
|---|---|---|---|
bg-slate-900 | nền trang | bg-foreground (#111) | ✅ tình cờ đúng |
bg-slate-800 | thẻ, sáng hơn nền | bg-foreground (#111) | thẻ biến mất, trùng nền |
bg-slate-700 | nút, sáng hơn nữa | bg-border (#f2f2f2) | nút trắng, kèm text-white → không đọc được |
border-slate-700 | viền mờ | border-border (#f2f2f2) | viền trắng chói trên nền đen |
Trên nền tối, thang xám chạy ngược: số càng nhỏ thì càng sáng, tức càng nổi lên trên nền. Ánh xạ từng bậc sang token của nền sáng là sai về ngữ nghĩa, và sai theo kiểu build vẫn xanh, gác màu vẫn xanh, vì mọi lớp đều là token hợp lệ.
Cách đúng là dùng cặp token bề mặt nghịch đảo mà hệ thiết kế đã có sẵn, và diễn đạt các bậc trung gian bằng độ mờ của màu chữ nghịch đảo:
bg-slate-900 → bg-surface-inverse (nền)
bg-slate-800 → bg-surface-inverse-foreground/5 (thẻ nổi nhẹ)
bg-slate-700 → bg-surface-inverse-foreground/10 (nút)
border-* → border-surface-inverse-foreground/15
text-slate-400→ text-surface-inverse-foreground/60
text-white → text-surface-inverse-foregroundTrước khi quy đổi xám, phải xác định trang đó nền sáng hay nền tối. Dấu hiệu rẻ nhất: text-white trong cùng khối, hoặc bg-*-900 ở phần tử bao ngoài cùng.
Ba thứ chết đã gỡ
src/App.css(184 dòng), không file nàoimportnó, kể cảmain.tsx. Tàn dư của mẫu Vite.tailwind.config.js, cấu hình kiểu Tailwind v3. Dự án dùng v4, và v4 chỉ đọc file này khi có chỉ thị@configtrong CSS, không có. File chết, nhưng đọc như đang có hiệu lực.- Ba alias
--color-conan-red/sand/espressotrongindex.css, trỏ về token dùng chung nhưng không nơi nào dùng.
Bẫy khi kiểm: dev server nói dối, bản dựng nói thật
Sau khi sửa HostHistory.tsx, dev server hiện trang nền sáng, .bg-surface-inverse có trong DOM nhưng getComputedStyle trả rgba(0,0,0,0), và stylesheet của trang chỉ có 95 rule, không có utility đó. Suýt kết luận là token hỏng.
Bản dựng production thì đúng:
.bg-surface-inverse{background-color:var(--color-surface-inverse)}
--color-surface-inverse:#111Nguyên nhân là cách khởi động dev server (chạy vite từ ngoài thư mục dự án bằng --prefix), không phải mã. Nhưng bài học giữ nguyên: khi dev và bản dựng bất đồng, tin bản dựng, đó mới là thứ được deploy. Đã xem lại bằng vite preview trên chính dist/: nền rgb(17,17,17), chữ trắng, thẻ nổi 5%, CTA đất nung.
Kiểm chứng
tsc -b0 lỗi ·npm run buildxanh · cả bảy gác ở gốc repo xanh.- 66 lớp token dùng trong mã, 0 lớp không sinh CSS.
- CSS đã dựng không còn
#ea580c,#b03a2a,#666666,#f4f4f5. - Ba trang xem bằng mắt trên bản dựng: trang vào phòng, bảng điều khiển chủ phòng, lịch sử ván (nền tối), đều đúng.
Còn mở với play
- Không có job kiểm nào trên PR.
ci-checks.ymlkhông dựngplay; jobguardscó soi nó (gác màu, gác gói UI) nhưng không cótschayvite build. Lỗi biên dịch củaplaychỉ lộ ra ở lượt deploy. - Thiếu hai phần ba bộ ba UI: không
motion, không shadcn (src/components/ui/không tồn tại, 0 gói@radix-ui). Là nợ, không phải ngoại lệ,CLAUDE.mdkhông miễn trừplay.
Hậu kiểm sau khi merge: người dùng CHƯA thấy bản mới
deploy-play xanh cả hai job, deployment đúng nội dung, nhưng https://play.conan.school vẫn trả bản dựng cũ (--color-primary:#ea580c, không có .bg-surface-inverse), trong khi main.kahoot-frontend.pages.dev trả bản mới (#d94f2b, có utility). Không phải cache (cf-cache-status: BYPASS).
Domain không trỏ vào deployment production của project kahoot-frontend. Đây là lỗi hạ tầng có sẵn, không do lượt dọn màu, nhưng chỉ lộ ra vì lượt này có một thay đổi nhìn thấy được để đối chiếu. Nghĩa là mọi lượt deploy play trước đó cũng chưa tới người dùng, và không ai biết.
Sửa chỗ gắn domain phải làm trên dashboard Cloudflare. Chi tiết và cách kiểm: known-risks.
Trạng thái
293 chỗ tồn đọng toàn repo, từ 3.445 đầu ngày. Bốn site khoá ở 0: www, admin, com, play. Còn: mam 175 · mentors 53 · packages 32 (DebugFooter, cố ý) · docs 12 · video 11 · api 10.