index.css had a hand-written reset (`*, *::before, *::after { margin: 0;
padding: 0; box-sizing: border-box; }`) left over from before Tailwind was
added, sitting outside any `@layer` block. Per the CSS Cascade Layers spec,
unlayered rules always beat layered rules regardless of selector
specificity — since every Tailwind utility class lives inside `@layer
utilities`, this one `*`-selector rule was silently overriding every
single margin/padding utility (p-*, m-*, mx-auto, etc.) across the entire
app. Other properties (colors, borders, gap) weren't affected, which is
why this went unnoticed through the whole Tailwind migration — only
spacing/centering was silently broken, not colors or general layout.
Tailwind's own preflight (already loaded via `@import "tailwindcss"`,
correctly placed inside `@layer base`) provides the identical reset, so
the duplicate unlayered copy was simply deleted.
Also fixed two smaller, related issues found while investigating: an
inline `style={{ maxWidth: '100vw' }}` on Login/Register's auth-card
overrode its CSS class's `max-width: 400px`, stretching it to near full
viewport width on screens wider than ~400px (invisible on mobile, obvious
on laptop/desktop — probably what originally looked like "responsive
wasn't fixed"). And BacktestPage.tsx, unlike every other page, rendered
its `mx-auto`-centered container as a direct child of #root (which has
`display: flex; flex-direction: column`), so flexbox's default
align-items: stretch overrode the centering; wrapped it in the same
min-h-screen container pattern every other page already uses.
Verified via direct getComputedStyle()/getBoundingClientRect() measurement
(screenshots in this environment don't reliably reflect true layout) —
margin-inline resolved to 0px before the fix, 183px (correctly centered)
after. Frontend build clean, 170 backend tests unaffected (CSS-only change).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
> **Cập nhật v1-v8:** xem các file `theo_doi_trading-portal_v1.md`…`v8.md`
> **Cập nhật v9 (lần này):** 2026-07-04 — sửa 1 bug CSS toàn cục nghiêm trọng khiến **toàn bộ class margin/padding của Tailwind trên cả app bị vô hiệu hóa âm thầm**, cộng 2 bug nhỏ hơn liên quan (login/register card giãn to trên desktop, BacktestPage không canh giữa)
> **Người thực hiện:** Claude (Sonnet 5), theo yêu cầu của tien.a.le@accenture.com
> **Quy ước đặt tên:** Mỗi lần có thay đổi lớn → tạo bản mới `theo_doi_trading-portal_v10.md`, ... giữ nguyên các bản cũ làm lịch sử.
---
## 1. Tổng quan dự án
(Không đổi — xem [theo_doi_trading-portal_v2.md](theo_doi_trading-portal_v2.md) mục 1.)
---
## 2. Bối cảnh
Người dùng phản ánh: "giao diện trên laptop to quá chừng" — nghi ngờ việc rà soát responsive ở v6 (mục 3, task #34) chưa thực sự đầy đủ. Kiểm tra trực tiếp bằng trình duyệt ở độ phân giải laptop thực tế (1366×768) thay vì chỉ dựa vào ảnh chụp màn hình, phát hiện **3 vấn đề riêng biệt**, xếp theo mức độ nghiêm trọng tăng dần khi đào sâu:
### 2.1 Bug nhỏ: `LoginPage`/`RegisterPage` có inline style thừa
`<div className="auth-card" style={{ maxWidth: '100vw', boxSizing: 'border-box' }}>` — inline style luôn thắng CSS class, nên `max-width: 100vw` đè lên `max-width: 400px` của class `.auth-card`, khiến khung đăng nhập giãn gần hết chiều rộng màn hình ở độ phân giải lớn (ẩn ở mobile vì 100vw ở đó vốn đã nhỏ, nên không ai để ý). `box-sizing: border-box` trong cùng inline style cũng thừa (đã có reset toàn cục). **Đã xóa cả 2 inline style** ở cả `LoginPage.tsx` và `RegisterPage.tsx`.
### 2.2 Bug nhỏ: `BacktestPage.tsx` không canh giữa
Trang này là trang **duy nhất** trong số các trang dùng pattern `mx-auto max-w-[Npx]` mà không có div bọc ngoài (không giống `AnalyticsPage`/`ProfilePage`/`AdminPage`/`AuditLogPage` đều có nav bar + wrapper `min-h-screen` bên ngoài). Vì `#root` có `display:flex; flex-direction:column`, div `mx-auto` trở thành flex item trực tiếp của `#root`, và `align-items` mặc định (`normal`→`stretch`) làm nó giãn full-width thay vì canh giữa. **Đã bọc thêm 1 div `min-h-screen bg-bg-primary` bên ngoài**, đúng theo pattern các trang khác.
### 2.3 Bug lớn — nghiêm trọng nhất: CSS reset viết tay đè lên toàn bộ Tailwind margin/padding utilities
Khi đào sâu tìm hiểu tại sao `mx-auto` "không hoạt động" ngay cả sau khi đã bọc div đúng cách ở mục 2.2, phát hiện: `index.css` có đoạn reset viết tay từ trước khi thêm Tailwind:
```css
*,*::before,*::after{
box-sizing:border-box;
margin:0;
padding:0;
}
```
Đoạn này nằm **ngoài mọi `@layer`** của Tailwind (không nằm trong `@layer base/components/utilities`). Theo đặc tả CSS Cascade Layers: **style không thuộc layer nào luôn thắng mọi style thuộc layer nào đó, bất kể độ đặc hiệu (specificity) selector**. Vì TOÀN BỘ utility class của Tailwind (`.p-5`, `.mx-auto`, `.mb-5`, `.px-4`, v.v.) đều nằm trong `@layer utilities`, đoạn reset viết tay này (dù chỉ dùng selector `*` — độ đặc hiệu thấp nhất có thể) vẫn **đè lên và vô hiệu hóa TẤT CẢ margin/padding utility của Tailwind trên toàn bộ ứng dụng**.
**Vì sao không ai nhận ra ngay:** các thuộc tính khác (màu nền, viền, `gap` giữa các phần tử flex/grid, font, border-radius...) không bị ảnh hưởng (không phải margin/padding), nên giao diện vẫn "trông tạm ổn" ở cái nhìn thoáng qua — chỉ khi kiểm tra kỹ khoảng cách/canh giữa mới lộ ra. Đây chính xác là loại lỗi tạo cảm giác "giao diện to quá, không đúng chỗ" mà người dùng mô tả — hàng trăm chỗ dùng `p-*`/`m-*` xuyên suốt 14 file đã chuyển sang Tailwind đều bị ảnh hưởng.
**Cách sửa:** Tailwind v4's preflight (bên trong `@layer base`, tự động có sẵn từ `@import "tailwindcss"`) **đã cung cấp sẵn đúng loại reset y hệt** (`box-sizing:border-box; margin:0; padding:0` cho `*, ::before, ::after`), chỉ khác là nó nằm ĐÚNG trong layer, nên các utility trong `@layer utilities` (khai báo sau `base` trong thứ tự layer) mới override đúng theo thiết kế. → **Xóa hẳn đoạn reset viết tay trùng lặp** trong `index.css`, để Tailwind's preflight tự lo, không cần viết lại.
### 2.4 Kiểm chứng
Đo trực tiếp trong trình duyệt (không chỉ dựa vào ảnh chụp — ảnh chụp của công cụ preview trong phiên làm việc này không phản ánh chính xác layout thật, đã xác nhận qua đối chiếu với `getBoundingClientRect()`/`getComputedStyle()`):
| Trước khi sửa | Sau khi sửa |
|---|---|
| `.mx-auto` (BacktestPage): `margin-left/right: 0px`, giãn full 1366px | `margin-left/right: 183px`, đúng 1000px canh giữa |
| `.auth-card` (Login, sau fix 2.1): full width ~1268px | đúng 400px, canh giữa cả ngang lẫn dọc |
Build frontend sạch, 170 test backend vẫn pass (thay đổi chỉ ở CSS, không đụng logic).
---
## 3. Toàn bộ nhược điểm & rủi ro — bổ sung mới trong v9
| # | Vấn đề | Trạng thái |
|---|---|---|
| ee | (mới) Inline style `maxWidth:'100vw'` đè `.auth-card`'s `max-width:400px` trên Login/Register | ✅ Đã sửa (mục 2.1) |
| ff | (mới) `BacktestPage.tsx` thiếu wrapper, bị flex-stretch của `#root` làm mất canh giữa | ✅ Đã sửa (mục 2.2) |
| gg | (mới, **nghiêm trọng**) CSS reset viết tay không nằm trong `@layer`, vô hiệu hóa toàn bộ margin/padding utility của Tailwind app-wide | ✅ Đã sửa (mục 2.3) |
**Bài học quy trình:** việc rà soát responsive ở v6 (mục "Review UI end-to-end", task #34) dựa nhiều vào ảnh chụp màn hình ở kích thước mobile/tablet — bug này chỉ lộ rõ ở kích thước **laptop/desktop** (1280px+) và cần đo trực tiếp `getComputedStyle()`/`getBoundingClientRect()` mới phát hiện được, vì ảnh chụp không đáng tin cậy để kiểm tra chính xác khoảng cách/kích thước (đúng như mô tả của chính công cụ preview_screenshot). Từ nay nếu nghi ngờ vấn đề layout tinh vi, nên ưu tiên `preview_eval` + `getComputedStyle` thay vì chỉ nhìn ảnh chụp.
| v8 | 2026-07-04 | Wire ADX/regime vào bộ lọc tín hiệu dùng chung, hợp nhất 2 hệ thống regime. 170 test pass. |
| v9 | 2026-07-04 | Sửa bug CSS toàn cục: reset viết tay không nằm trong `@layer` vô hiệu hóa toàn bộ margin/padding utility Tailwind app-wide (gg) — nguyên nhân chính khiến giao diện "to quá" trên laptop. Kèm 2 bug nhỏ: inline style đè max-width trên Login/Register (ee), BacktestPage thiếu wrapper mất canh giữa (ff). Build sạch, 170 test pass (không đổi logic). |
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.