gavl-ui 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,1090 @@
1
+ <!DOCTYPE html>
2
+ <html lang="vi">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>GAVL UI — Component Library v1.1</title>
7
+ <!--
8
+ [FIX] Font stack:
9
+ - Be Vietnam Pro: font tiếng Việt chất lượng cao, đầy đủ dấu thanh,
10
+ thiết kế cho màn hình, weight từ 100-800
11
+ - Nunito: fallback
12
+ - Press Start 2P: CHỈ dùng cho ASCII pixel labels
13
+ -->
14
+ <link href="https://fonts.googleapis.com/css2?family=Be+Vietnam+Pro:wght@400;500;600;700;800&family=Press+Start+2P&family=Nunito:wght@400;600;700;800&display=swap" rel="stylesheet">
15
+ <style>
16
+ /* ============================================================
17
+ GAVL UI v1.1 — Compiled Styles
18
+ Xem gavl-ui.scss để biết chi tiết từng fix
19
+ ============================================================ */
20
+ *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
21
+
22
+ :root {
23
+ --gv-brown-darkest:#1a1008;
24
+ --gv-brown-dark: #2a1f14;
25
+ --gv-brown-mid: #5c3d1e;
26
+ --gv-brown-light: #c8a06e;
27
+ --gv-cream: #f5e9d3;
28
+ --gv-cream-2: #ede0c4;
29
+ --gv-cream-3: #e4d5b0;
30
+ --gv-gold: #e6b44c;
31
+ --gv-gold-dark: #c9952a;
32
+ --gv-gold-light: #f5ce7a;
33
+ --gv-blue: #4a90d9;
34
+ --gv-blue-dark: #2d6baa;
35
+ --gv-blue-light: #7ab8f0;
36
+ --gv-red: #e05252;
37
+ --gv-red-dark: #b83a3a;
38
+ --gv-red-light: #f07878;
39
+ --gv-green: #5ab552;
40
+ --gv-green-dark: #3a8c34;
41
+ --gv-green-light: #82d67a;
42
+ --gv-yellow: #f0c830;
43
+ --gv-purple: #9b72cf;
44
+ --gv-purple-dark: #7450a8; /* [FIX] thêm vào — thiếu trong v1.0 */
45
+ --gv-white: #ffffff;
46
+ --gv-gray-1: #f0f0f0;
47
+ --gv-gray-2: #cccccc;
48
+ --gv-gray-3: #888888;
49
+ --gv-gray-4: #555555;
50
+ --gv-shadow-sm: 2px 2px 0;
51
+ --gv-shadow-md: 3px 3px 0;
52
+ --gv-shadow-lg: 4px 4px 0;
53
+ --gv-shadow-xl: 6px 6px 0;
54
+ --gv-border: 2px solid var(--gv-brown-mid);
55
+ --gv-border-gold: 2px solid var(--gv-gold);
56
+ --gv-border-sm: 1px solid var(--gv-brown-light);
57
+ --gv-radius-sm: 4px;
58
+ --gv-radius-md: 8px;
59
+ --gv-radius-lg: 12px;
60
+ --gv-radius-xl: 16px;
61
+ /* [FIX] Be Vietnam Pro là font body chính để hỗ trợ tiếng Việt */
62
+ --gv-font-pixel: 'Press Start 2P', monospace;
63
+ --gv-font-body: 'Be Vietnam Pro', 'Nunito', 'Segoe UI', system-ui, sans-serif;
64
+ --gv-space-1:4px; --gv-space-2:8px; --gv-space-3:12px;
65
+ --gv-space-4:16px; --gv-space-5:24px; --gv-space-6:32px;
66
+ --gv-transition: all 0.15s ease;
67
+ /* [NEW] Line-height chuẩn cho tiếng Việt */
68
+ --gv-lh-vi: 1.75;
69
+ --gv-lh-vi-tight: 1.5;
70
+ }
71
+
72
+ body {
73
+ font-family: var(--gv-font-body);
74
+ background: var(--gv-brown-dark);
75
+ background-image:
76
+ radial-gradient(circle at 20% 20%, rgba(230,180,76,0.06) 0%, transparent 50%),
77
+ radial-gradient(circle at 80% 80%, rgba(90,181,82,0.03) 0%, transparent 50%);
78
+ min-height: 100vh;
79
+ padding: 32px 16px 64px;
80
+ color: var(--gv-brown-dark);
81
+ /* [FIX] line-height toàn cục phù hợp tiếng Việt */
82
+ line-height: var(--gv-lh-vi);
83
+ }
84
+
85
+ /* === PAGE HEADER === */
86
+ .page-header { text-align:center; margin-bottom:48px; }
87
+ .page-logo { font-family:var(--gv-font-pixel);font-size:clamp(14px,4vw,26px);color:var(--gv-gold);letter-spacing:4px;text-shadow:4px 4px 0 var(--gv-brown-darkest);margin-bottom:12px;line-height:1.8; }
88
+ .page-sub { font-size:13px;color:var(--gv-brown-light);font-weight:600;letter-spacing:0.5px; }
89
+ .page-version { display:inline-block;margin-top:10px;font-family:var(--gv-font-pixel);font-size:7px;color:var(--gv-brown-mid);background:var(--gv-cream-2);border:var(--gv-border);padding:4px 10px;border-radius:var(--gv-radius-sm);box-shadow:2px 2px 0 var(--gv-brown-mid);line-height:2; }
90
+
91
+ /* === SECTION WRAPPER === */
92
+ .section { max-width:1000px;margin:0 auto 40px;background:var(--gv-cream);border:var(--gv-border);border-radius:var(--gv-radius-xl);box-shadow:var(--gv-shadow-xl) var(--gv-brown-darkest);overflow:hidden; }
93
+ .section-head { background:var(--gv-brown-dark);padding:14px 24px;display:flex;align-items:center;gap:10px; }
94
+ .section-head-title { font-family:var(--gv-font-pixel);font-size:9px;color:var(--gv-gold);letter-spacing:1px;line-height:2; }
95
+ .section-head-num { font-family:var(--gv-font-pixel);font-size:7px;color:var(--gv-brown-mid);background:var(--gv-brown-darkest);padding:3px 8px;border-radius:var(--gv-radius-sm);line-height:2; }
96
+ .section-body { padding:28px 24px;display:flex;flex-wrap:wrap;gap:14px;align-items:flex-start; }
97
+ .section-body-col { padding:28px 24px;display:flex;flex-direction:column;gap:16px; }
98
+ .demo-label { font-family:var(--gv-font-pixel);font-size:7px;color:var(--gv-brown-light);letter-spacing:1px;margin-bottom:8px;line-height:2; }
99
+ .demo-group { display:flex;flex-direction:column;gap:6px;width:100%; }
100
+
101
+ /* ============================================================
102
+ GAVL-UI COMPILED STYLES v1.1
103
+ Xem gavl-ui.scss để biết toàn bộ thay đổi
104
+ ============================================================ */
105
+
106
+ /* --- TYPOGRAPHY --- */
107
+ /* [NOTE] gv-display-* CHỈ dùng cho text ASCII. Với tiếng Việt dùng gv-heading-* */
108
+ .gv-display-1 { font-family:var(--gv-font-pixel);font-size:24px;color:var(--gv-brown-dark);line-height:1.8;letter-spacing:2px; }
109
+ .gv-display-2 { font-family:var(--gv-font-pixel);font-size:18px;color:var(--gv-brown-dark);line-height:1.8; }
110
+ .gv-display-3 { font-family:var(--gv-font-pixel);font-size:14px;color:var(--gv-brown-dark);line-height:1.8; }
111
+ .gv-display-4 { font-family:var(--gv-font-pixel);font-size:10px;color:var(--gv-brown-dark);line-height:2; }
112
+ .gv-display-5 { font-family:var(--gv-font-pixel);font-size:8px;color:var(--gv-brown-mid);line-height:2;letter-spacing:1px; }
113
+ .gv-display-6 { font-family:var(--gv-font-pixel);font-size:7px;color:var(--gv-brown-mid);line-height:2;letter-spacing:1px; }
114
+
115
+ /* [NEW] Headings tiếng Việt — Be Vietnam Pro */
116
+ .gv-heading-1 { font-family:var(--gv-font-body);font-size:28px;font-weight:800;color:var(--gv-brown-dark);line-height:var(--gv-lh-vi-tight); }
117
+ .gv-heading-2 { font-family:var(--gv-font-body);font-size:22px;font-weight:800;color:var(--gv-brown-dark);line-height:var(--gv-lh-vi-tight); }
118
+ .gv-heading-3 { font-family:var(--gv-font-body);font-size:18px;font-weight:700;color:var(--gv-brown-dark);line-height:var(--gv-lh-vi-tight); }
119
+ .gv-heading-4 { font-family:var(--gv-font-body);font-size:16px;font-weight:700;color:var(--gv-brown-dark);line-height:var(--gv-lh-vi-tight); }
120
+
121
+ /* [FIX] Body text: line-height tăng cho tiếng Việt */
122
+ .gv-text-xl { font-size:20px;font-weight:700;line-height:var(--gv-lh-vi); }
123
+ .gv-text-lg { font-size:17px;font-weight:600;line-height:var(--gv-lh-vi); }
124
+ .gv-text-md { font-size:15px;font-weight:400;line-height:var(--gv-lh-vi); }
125
+ .gv-text-sm { font-size:13px;font-weight:400;line-height:var(--gv-lh-vi); }
126
+ .gv-text-xs { font-size:11px;font-weight:500;line-height:1.6; }
127
+ .gv-text-2xs { font-size:10px;font-weight:600;line-height:1.6;letter-spacing:.5px; }
128
+ .gv-text-gold { color:var(--gv-gold-dark); }
129
+ .gv-text-brown { color:var(--gv-brown-mid); }
130
+ .gv-text-cream { color:var(--gv-cream); }
131
+ .gv-text-muted { color:var(--gv-gray-3); }
132
+ .gv-text-danger { color:var(--gv-red); }
133
+ .gv-text-success { color:var(--gv-green-dark); }
134
+ .gv-text-info { color:var(--gv-blue-dark); }
135
+ .gv-text-purple { color:var(--gv-purple); }
136
+ /* [NOTE] gv-label: CHỈ ASCII. Dùng gv-vi-label cho tiếng Việt */
137
+ .gv-label { font-family:var(--gv-font-pixel);font-size:8px;color:var(--gv-brown-mid);letter-spacing:1px;text-transform:uppercase;line-height:2; }
138
+ /* [NEW] Label tiếng Việt */
139
+ .gv-vi-label { font-family:var(--gv-font-body);font-size:11px;font-weight:700;color:var(--gv-brown-mid);letter-spacing:.5px;text-transform:uppercase;line-height:1.5; }
140
+ .gv-caption { font-size:11px;color:var(--gv-gray-3);font-weight:600;line-height:1.6; }
141
+ /* [NEW] Utilities tiếng Việt */
142
+ .gv-vi { font-family:var(--gv-font-body);line-height:var(--gv-lh-vi);word-break:keep-all;overflow-wrap:break-word; }
143
+ .gv-vi-tight { font-family:var(--gv-font-body);line-height:var(--gv-lh-vi-tight);word-break:keep-all;overflow-wrap:break-word; }
144
+
145
+ /* --- BUTTONS --- */
146
+ .gv-btn {
147
+ display:inline-flex;align-items:center;justify-content:center;gap:8px;
148
+ font-family:var(--gv-font-body);font-weight:800;border-radius:var(--gv-radius-md);
149
+ border:2px solid transparent;cursor:pointer;text-decoration:none;
150
+ transition:var(--gv-transition);white-space:nowrap;
151
+ /* [FIX] line-height 1.2 thay vì 1 — dấu tiếng Việt không bị cắt */
152
+ line-height:1.2;
153
+ padding:10px 20px;font-size:14px;box-shadow:var(--gv-shadow-sm) var(--gv-brown-mid);
154
+ }
155
+ .gv-btn:hover { transform:translate(-1px,-1px);box-shadow:var(--gv-shadow-md) var(--gv-brown-mid); }
156
+ .gv-btn:active { transform:translate(1px,1px);box-shadow:none; }
157
+ .gv-btn:disabled,.gv-disabled { opacity:.45;cursor:not-allowed;pointer-events:none; }
158
+ .gv-btn-xs { padding:5px 10px;font-size:11px; }
159
+ .gv-btn-sm { padding:7px 14px;font-size:12px; }
160
+ .gv-btn-lg { padding:13px 28px;font-size:16px;box-shadow:var(--gv-shadow-md) var(--gv-brown-mid); }
161
+ .gv-btn-xl { padding:16px 36px;font-size:18px;box-shadow:var(--gv-shadow-lg) var(--gv-brown-mid); }
162
+ .gv-btn-block { width:100%; }
163
+ /* [NOTE] gv-btn-pixel CHỈ dùng cho text ASCII */
164
+ .gv-btn-pixel { font-family:var(--gv-font-pixel);font-size:9px;letter-spacing:1px;padding:12px 20px;line-height:1.8; }
165
+ .gv-btn-primary { background:var(--gv-gold);color:var(--gv-brown-dark);border-color:var(--gv-gold-dark); }
166
+ .gv-btn-primary:hover { background:var(--gv-gold-light); }
167
+ .gv-btn-secondary { background:var(--gv-cream-2);color:var(--gv-brown-dark);border-color:var(--gv-brown-light); }
168
+ .gv-btn-secondary:hover { background:var(--gv-cream-3); }
169
+ .gv-btn-dark { background:var(--gv-brown-dark);color:var(--gv-cream);border-color:var(--gv-brown-darkest);box-shadow:var(--gv-shadow-sm) var(--gv-brown-darkest); }
170
+ .gv-btn-dark:hover { background:var(--gv-brown-mid); }
171
+ .gv-btn-danger { background:var(--gv-red);color:#fff;border-color:var(--gv-red-dark);box-shadow:var(--gv-shadow-sm) var(--gv-red-dark); }
172
+ .gv-btn-danger:hover { background:var(--gv-red-light); }
173
+ .gv-btn-success { background:var(--gv-green);color:#fff;border-color:var(--gv-green-dark);box-shadow:var(--gv-shadow-sm) var(--gv-green-dark); }
174
+ .gv-btn-success:hover { background:var(--gv-green-light); }
175
+ .gv-btn-info { background:var(--gv-blue);color:#fff;border-color:var(--gv-blue-dark);box-shadow:var(--gv-shadow-sm) var(--gv-blue-dark); }
176
+ .gv-btn-info:hover { background:var(--gv-blue-light); }
177
+ /* [NEW] Purple button */
178
+ .gv-btn-purple { background:var(--gv-purple);color:#fff;border-color:var(--gv-purple-dark);box-shadow:var(--gv-shadow-sm) var(--gv-purple-dark); }
179
+ .gv-btn-purple:hover { background:#b08de0; }
180
+ .gv-btn-ghost { background:transparent;color:var(--gv-brown-mid);border-color:var(--gv-brown-light);box-shadow:none; }
181
+ .gv-btn-ghost:hover { background:var(--gv-cream-2);box-shadow:var(--gv-shadow-sm) var(--gv-brown-mid); }
182
+ .gv-btn-link { background:transparent;color:var(--gv-blue-dark);border-color:transparent;box-shadow:none;text-decoration:underline;text-decoration-style:dashed; }
183
+ .gv-btn-link:hover { color:var(--gv-blue);transform:none; }
184
+ .gv-btn-icon { width:40px;height:40px;padding:0;border-radius:var(--gv-radius-md); }
185
+ .gv-btn-icon-sm { width:32px;height:32px;padding:0;border-radius:var(--gv-radius-sm); }
186
+ .gv-btn-icon-lg { width:48px;height:48px;padding:0;border-radius:var(--gv-radius-lg); }
187
+ /* [FIX] thêm display:inline-block — bị thiếu trong v1.0 */
188
+ .gv-btn-loading { pointer-events:none; }
189
+ .gv-btn-loading::after {
190
+ content:'';display:inline-block;width:12px;height:12px;vertical-align:middle;
191
+ border:2px solid currentColor;border-top-color:transparent;
192
+ border-radius:50%;animation:gv-spin .6s linear infinite;margin-left:6px;
193
+ }
194
+ .gv-btn-group { display:inline-flex; }
195
+ .gv-btn-group .gv-btn { border-radius:0; }
196
+ .gv-btn-group .gv-btn:first-child { border-radius:var(--gv-radius-md) 0 0 var(--gv-radius-md); }
197
+ .gv-btn-group .gv-btn:last-child { border-radius:0 var(--gv-radius-md) var(--gv-radius-md) 0; }
198
+ .gv-btn-group .gv-btn:not(:first-child) { border-left:none; }
199
+
200
+ /* --- INPUTS --- */
201
+ /* [FIX] line-height:1.5 để dấu tiếng Việt trong input không bị cắt */
202
+ .gv-input,.gv-textarea,.gv-select {
203
+ font-family:var(--gv-font-body);font-size:14px;font-weight:600;
204
+ color:var(--gv-brown-dark);background:var(--gv-cream);
205
+ border:var(--gv-border);border-radius:var(--gv-radius-md);
206
+ padding:10px 14px;width:100%;transition:var(--gv-transition);
207
+ outline:none;box-shadow:var(--gv-shadow-sm) var(--gv-brown-light);
208
+ appearance:none;-webkit-appearance:none;line-height:1.5;
209
+ }
210
+ .gv-input::placeholder,.gv-textarea::placeholder { color:var(--gv-brown-light);font-weight:500; }
211
+ .gv-input:focus,.gv-textarea:focus,.gv-select:focus {
212
+ border-color:var(--gv-gold-dark);
213
+ box-shadow:var(--gv-shadow-sm) var(--gv-gold-dark),0 0 0 3px rgba(230,180,76,.2);
214
+ }
215
+ .gv-input:disabled { background:var(--gv-gray-1);color:var(--gv-gray-3);cursor:not-allowed;box-shadow:none; }
216
+ .gv-input-error { border-color:var(--gv-red)!important;box-shadow:var(--gv-shadow-sm) var(--gv-red-dark)!important; }
217
+ .gv-input-success{ border-color:var(--gv-green)!important;box-shadow:var(--gv-shadow-sm) var(--gv-green-dark)!important; }
218
+ .gv-input-sm { padding:6px 10px;font-size:12px; }
219
+ .gv-input-lg { padding:13px 18px;font-size:16px; }
220
+ /* [FIX] textarea min-height tăng, line-height đúng tiếng Việt */
221
+ .gv-textarea { resize:vertical;min-height:110px;line-height:var(--gv-lh-vi); }
222
+ .gv-select {
223
+ background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath fill='%235c3d1e' d='M0 0l6 8 6-8z'/%3E%3C/svg%3E");
224
+ background-repeat:no-repeat;background-position:right 14px center;padding-right:38px;cursor:pointer;
225
+ }
226
+ .gv-form-group { display:flex;flex-direction:column;gap:6px;margin-bottom:var(--gv-space-4); }
227
+ /* [NOTE] gv-form-label: CHỈ ASCII. Dùng gv-form-label-vi cho tiếng Việt */
228
+ .gv-form-label { font-family:var(--gv-font-pixel);font-size:8px;color:var(--gv-brown-mid);letter-spacing:1px;line-height:2; }
229
+ /* [NEW] Label tiếng Việt trong form */
230
+ .gv-form-label-vi { font-family:var(--gv-font-body);font-size:12px;font-weight:700;color:var(--gv-brown-mid);letter-spacing:.3px;line-height:1.5; }
231
+ .gv-form-helper { font-size:11px;color:var(--gv-gray-3);font-weight:500;line-height:1.5; }
232
+ .gv-form-error { font-size:11px;color:var(--gv-red);font-weight:600;line-height:1.5; }
233
+ .gv-input-group { position:relative;display:flex;align-items:stretch; }
234
+ .gv-input-addon { display:flex;align-items:center;padding:0 12px;background:var(--gv-cream-2);border:var(--gv-border);color:var(--gv-brown-mid);font-weight:700;font-size:13px;white-space:nowrap; }
235
+ .gv-input-addon-left { border-right:none;border-radius:var(--gv-radius-md) 0 0 var(--gv-radius-md); }
236
+ .gv-input-addon-right { border-left:none;border-radius:0 var(--gv-radius-md) var(--gv-radius-md) 0; }
237
+ .gv-input-group .gv-input:not(:first-child) { border-radius:0 var(--gv-radius-md) var(--gv-radius-md) 0; }
238
+ .gv-input-group .gv-input:not(:last-child) { border-radius:var(--gv-radius-md) 0 0 var(--gv-radius-md); }
239
+ .gv-check-group { display:flex;align-items:center;gap:10px;cursor:pointer;user-select:none; }
240
+ .gv-check-group input { display:none; }
241
+ .gv-check-box { width:20px;height:20px;background:var(--gv-cream);border:var(--gv-border);border-radius:var(--gv-radius-sm);flex-shrink:0;box-shadow:var(--gv-shadow-sm) var(--gv-brown-light);display:flex;align-items:center;justify-content:center;transition:var(--gv-transition); }
242
+ .gv-check-group input:checked + .gv-check-box { background:var(--gv-gold);border-color:var(--gv-gold-dark);box-shadow:var(--gv-shadow-sm) var(--gv-gold-dark);color:var(--gv-brown-dark);font-weight:900;font-size:12px; }
243
+ .gv-radio-box { width:20px;height:20px;background:var(--gv-cream);border:var(--gv-border);border-radius:50%;flex-shrink:0;box-shadow:var(--gv-shadow-sm) var(--gv-brown-light);display:flex;align-items:center;justify-content:center;transition:var(--gv-transition); }
244
+ .gv-radio-dot { width:10px;height:10px;background:var(--gv-gold);border-radius:50%;display:none; }
245
+ .gv-check-group input:checked + .gv-radio-box { border-color:var(--gv-gold-dark);box-shadow:var(--gv-shadow-sm) var(--gv-gold-dark); }
246
+ .gv-check-group input:checked + .gv-radio-box .gv-radio-dot { display:block; }
247
+ /* [FIX] line-height cho label tiếng Việt */
248
+ .gv-check-label { font-size:14px;font-weight:700;color:var(--gv-brown-dark);line-height:var(--gv-lh-vi-tight); }
249
+ .gv-toggle { display:inline-flex;align-items:center;gap:10px;cursor:pointer;user-select:none; }
250
+ .gv-toggle input { display:none; }
251
+ .gv-toggle-track { width:44px;height:24px;background:var(--gv-gray-2);border:var(--gv-border);border-radius:20px;position:relative;transition:var(--gv-transition);box-shadow:var(--gv-shadow-sm) var(--gv-brown-light);flex-shrink:0; }
252
+ .gv-toggle-thumb { position:absolute;left:2px;top:2px;width:16px;height:16px;background:#fff;border-radius:50%;border:2px solid var(--gv-brown-light);transition:var(--gv-transition); }
253
+ .gv-toggle input:checked ~ .gv-toggle-track { background:var(--gv-gold);border-color:var(--gv-gold-dark);box-shadow:var(--gv-shadow-sm) var(--gv-gold-dark); }
254
+ .gv-toggle input:checked ~ .gv-toggle-track .gv-toggle-thumb { left:calc(100% - 18px);border-color:var(--gv-gold-dark); }
255
+ .gv-toggle-label { font-size:14px;font-weight:700;color:var(--gv-brown-dark);line-height:var(--gv-lh-vi-tight); }
256
+ .gv-range { -webkit-appearance:none;appearance:none;width:100%;height:8px;border-radius:var(--gv-radius-sm);background:var(--gv-cream-2);border:var(--gv-border);box-shadow:var(--gv-shadow-sm) var(--gv-brown-light);outline:none;cursor:pointer; }
257
+ .gv-range::-webkit-slider-thumb { -webkit-appearance:none;width:20px;height:20px;border-radius:var(--gv-radius-sm);background:var(--gv-gold);border:var(--gv-border);box-shadow:var(--gv-shadow-sm) var(--gv-brown-mid);cursor:pointer;transition:var(--gv-transition); }
258
+ .gv-range::-moz-range-thumb { width:20px;height:20px;border-radius:var(--gv-radius-sm);background:var(--gv-gold);border:var(--gv-border);cursor:pointer; }
259
+
260
+ /* --- CARDS --- */
261
+ .gv-card { background:var(--gv-cream);border:var(--gv-border);border-radius:var(--gv-radius-lg);box-shadow:var(--gv-shadow-md) var(--gv-brown-mid);overflow:hidden;transition:var(--gv-transition); }
262
+ .gv-card.gv-card-hover:hover { transform:translate(-2px,-2px);box-shadow:var(--gv-shadow-lg) var(--gv-brown-mid); }
263
+ .gv-card-dark { background:linear-gradient(135deg,var(--gv-brown-dark),var(--gv-brown-mid));border-color:var(--gv-brown-darkest);box-shadow:var(--gv-shadow-md) var(--gv-brown-darkest);color:var(--gv-cream); }
264
+ .gv-card-gold { background:linear-gradient(135deg,var(--gv-gold),var(--gv-gold-light));border-color:var(--gv-gold-dark);box-shadow:var(--gv-shadow-md) var(--gv-gold-dark);color:var(--gv-brown-dark); }
265
+ .gv-card-header{ padding:16px 20px;border-bottom:var(--gv-border);background:var(--gv-cream-2);display:flex;align-items:center;justify-content:space-between;gap:10px; }
266
+ .gv-card-body { padding:20px; }
267
+ .gv-card-footer{ padding:14px 20px;border-top:var(--gv-border);background:var(--gv-cream-2); }
268
+ .gv-card-image { width:100%;aspect-ratio:16/9;object-fit:cover;display:block;border-bottom:var(--gv-border); }
269
+ /* [NOTE] gv-card-title: CHỈ ASCII. Dùng gv-card-title-vi cho tiếng Việt */
270
+ .gv-card-title { font-family:var(--gv-font-pixel);font-size:10px;color:var(--gv-brown-dark);line-height:2; }
271
+ /* [NEW] Card title tiếng Việt */
272
+ .gv-card-title-vi { font-family:var(--gv-font-body);font-size:16px;font-weight:800;color:var(--gv-brown-dark);line-height:var(--gv-lh-vi-tight); }
273
+ /* [FIX] line-height cho desc tiếng Việt */
274
+ .gv-card-desc { font-size:13px;color:var(--gv-brown-mid);line-height:var(--gv-lh-vi);margin-top:8px; }
275
+
276
+ /* --- BADGES & TAGS --- */
277
+ .gv-badge { display:inline-flex;align-items:center;gap:4px;padding:3px 9px;border-radius:var(--gv-radius-sm);font-size:11px;font-weight:800;border:2px solid transparent;white-space:nowrap;line-height:1.4; }
278
+ /* [NOTE] gv-badge-pixel CHỈ cho ASCII ngắn (HOT, NEW, LIVE...) */
279
+ .gv-badge-pixel { font-family:var(--gv-font-pixel);font-size:7px;padding:4px 8px;line-height:1.8; }
280
+ .gv-badge-primary { background:var(--gv-gold);color:var(--gv-brown-dark);border-color:var(--gv-gold-dark);box-shadow:2px 2px 0 var(--gv-gold-dark); }
281
+ .gv-badge-dark { background:var(--gv-brown-dark);color:var(--gv-cream);border-color:var(--gv-brown-darkest);box-shadow:2px 2px 0 var(--gv-brown-darkest); }
282
+ .gv-badge-danger { background:var(--gv-red);color:#fff;border-color:var(--gv-red-dark);box-shadow:2px 2px 0 var(--gv-red-dark); }
283
+ .gv-badge-success { background:var(--gv-green);color:#fff;border-color:var(--gv-green-dark);box-shadow:2px 2px 0 var(--gv-green-dark); }
284
+ .gv-badge-info { background:var(--gv-blue);color:#fff;border-color:var(--gv-blue-dark);box-shadow:2px 2px 0 var(--gv-blue-dark); }
285
+ .gv-badge-purple { background:var(--gv-purple);color:#fff;border-color:var(--gv-purple-dark);box-shadow:2px 2px 0 var(--gv-purple-dark); }
286
+ .gv-badge-outline { background:transparent;color:var(--gv-brown-mid);border-color:var(--gv-brown-light);box-shadow:2px 2px 0 var(--gv-brown-light); }
287
+ /* [FIX] gv-tag: không dùng @extend, định nghĩa độc lập để tránh conflict */
288
+ .gv-tag { display:inline-flex;align-items:center;gap:4px;padding:5px 12px;border-radius:var(--gv-radius-sm);font-size:12px;font-weight:700;font-family:var(--gv-font-body);line-height:1.4;border:2px solid var(--gv-brown-light);white-space:nowrap;cursor:pointer;text-decoration:none;transition:var(--gv-transition);background:var(--gv-cream-2);color:var(--gv-brown-mid);box-shadow:var(--gv-shadow-sm) var(--gv-brown-mid); }
289
+ .gv-tag::before { content:'#';opacity:.5; }
290
+ .gv-tag:hover { background:var(--gv-gold);border-color:var(--gv-gold-dark);color:var(--gv-brown-dark);transform:translate(-1px,-1px);box-shadow:var(--gv-shadow-md) var(--gv-brown-mid); }
291
+
292
+ /* --- ALERTS --- */
293
+ /* [FIX] line-height tiếng Việt, alert-title dùng body font */
294
+ .gv-alert { display:flex;align-items:flex-start;gap:12px;padding:14px 18px;border-radius:var(--gv-radius-md);border:var(--gv-border);font-size:13px;font-weight:600;line-height:var(--gv-lh-vi);box-shadow:var(--gv-shadow-sm) var(--gv-brown-light); }
295
+ .gv-alert-icon { flex-shrink:0;margin-top:2px; }
296
+ /* [FIX] alert-title dùng body font thay vì pixel font */
297
+ .gv-alert-title { font-family:var(--gv-font-body);font-size:12px;font-weight:800;letter-spacing:.5px;text-transform:uppercase;margin-bottom:4px;line-height:1.4; }
298
+ .gv-alert-info { background:#ddeeff;border-color:var(--gv-blue);color:var(--gv-blue-dark);box-shadow:var(--gv-shadow-sm) var(--gv-blue-dark); }
299
+ .gv-alert-success { background:#ddf5dd;border-color:var(--gv-green);color:var(--gv-green-dark);box-shadow:var(--gv-shadow-sm) var(--gv-green-dark); }
300
+ .gv-alert-warning { background:#fff8dd;border-color:var(--gv-gold);color:var(--gv-gold-dark);box-shadow:var(--gv-shadow-sm) var(--gv-gold-dark); }
301
+ .gv-alert-danger { background:#ffeeee;border-color:var(--gv-red);color:var(--gv-red-dark);box-shadow:var(--gv-shadow-sm) var(--gv-red-dark); }
302
+
303
+ /* --- PROGRESS --- */
304
+ .gv-progress-wrap { height:16px;background:var(--gv-cream-2);border:var(--gv-border);border-radius:var(--gv-radius-sm);overflow:hidden;box-shadow:var(--gv-shadow-sm) var(--gv-brown-light); }
305
+ .gv-progress-bar { height:100%;background:var(--gv-gold);border-right:2px solid var(--gv-gold-dark);transition:width .4s ease; }
306
+ .gv-progress-bar.gv-progress-striped { background-image:repeating-linear-gradient(45deg,transparent,transparent 6px,rgba(255,255,255,.25) 6px,rgba(255,255,255,.25) 12px); }
307
+ /* [FIX] thêm background-size để animation hoạt động đúng */
308
+ .gv-progress-bar.gv-progress-animated { animation:gv-progress-move 1s linear infinite;background-size:24px 24px; }
309
+ .gv-progress-bar.gv-progress-danger { background:var(--gv-red);border-right-color:var(--gv-red-dark); }
310
+ .gv-progress-bar.gv-progress-success { background:var(--gv-green);border-right-color:var(--gv-green-dark); }
311
+ .gv-progress-bar.gv-progress-info { background:var(--gv-blue);border-right-color:var(--gv-blue-dark); }
312
+ .gv-progress-sm .gv-progress-wrap { height:8px; }
313
+ .gv-progress-lg .gv-progress-wrap { height:24px; }
314
+
315
+ /* --- AVATAR --- */
316
+ .gv-avatar { display:inline-flex;align-items:center;justify-content:center;border-radius:var(--gv-radius-md);border:var(--gv-border);box-shadow:var(--gv-shadow-sm) var(--gv-brown-mid);background:var(--gv-brown-mid);color:var(--gv-cream);font-weight:800;overflow:hidden;flex-shrink:0; }
317
+ .gv-avatar img { width:100%;height:100%;object-fit:cover; }
318
+ .gv-avatar.gv-avatar-circle { border-radius:50%; }
319
+ .gv-avatar.gv-avatar-gold { border-color:var(--gv-gold);box-shadow:var(--gv-shadow-sm) var(--gv-gold-dark); }
320
+ .gv-avatar-xs { width:24px;height:24px;font-size:10px; }
321
+ .gv-avatar-sm { width:32px;height:32px;font-size:12px; }
322
+ .gv-avatar-md { width:48px;height:48px;font-size:16px; }
323
+ .gv-avatar-lg { width:64px;height:64px;font-size:20px; }
324
+ .gv-avatar-xl { width:80px;height:80px;font-size:24px; }
325
+ .gv-avatar-group { display:inline-flex; }
326
+ .gv-avatar-group .gv-avatar { margin-left:-10px;transition:var(--gv-transition); }
327
+ .gv-avatar-group .gv-avatar:first-child { margin-left:0; }
328
+ .gv-avatar-group .gv-avatar:hover { z-index:10;transform:translateY(-3px); }
329
+
330
+ /* --- TOOLTIP --- */
331
+ [data-gv-tooltip] { position:relative;cursor:default; }
332
+ [data-gv-tooltip]::before {
333
+ content:attr(data-gv-tooltip);position:absolute;bottom:calc(100% + 8px);left:50%;
334
+ transform:translateX(-50%);background:var(--gv-brown-dark);color:var(--gv-cream);
335
+ /* [FIX] dùng body font cho tooltip tiếng Việt */
336
+ font-family:var(--gv-font-body);font-size:11px;font-weight:700;
337
+ padding:5px 10px;border-radius:var(--gv-radius-sm);white-space:nowrap;
338
+ border:2px solid var(--gv-brown-mid);box-shadow:var(--gv-shadow-sm) var(--gv-brown-darkest);
339
+ opacity:0;pointer-events:none;transition:opacity .15s;z-index:9999;
340
+ }
341
+ [data-gv-tooltip]::after {
342
+ content:'';position:absolute;bottom:calc(100% + 2px);left:50%;
343
+ transform:translateX(-50%);border:6px solid transparent;
344
+ border-top-color:var(--gv-brown-dark);opacity:0;pointer-events:none;transition:opacity .15s;z-index:9999;
345
+ }
346
+ [data-gv-tooltip]:hover::before,[data-gv-tooltip]:hover::after { opacity:1; }
347
+
348
+ /* --- TABLE --- */
349
+ /* [NEW] overflow-x:auto cho responsive */
350
+ .gv-table-wrap { border:var(--gv-border);border-radius:var(--gv-radius-lg);overflow:hidden;overflow-x:auto;box-shadow:var(--gv-shadow-md) var(--gv-brown-mid); }
351
+ .gv-table { width:100%;border-collapse:collapse;font-size:13px;min-width:480px; }
352
+ /* [FIX] thead th dùng body font để hiển thị tiếng Việt */
353
+ .gv-table thead { background:var(--gv-brown-dark);color:var(--gv-cream); }
354
+ .gv-table thead th { padding:12px 16px;text-align:left;font-family:var(--gv-font-body);font-size:11px;font-weight:800;letter-spacing:.5px;text-transform:uppercase;border-bottom:var(--gv-border);white-space:nowrap; }
355
+ .gv-table tbody tr { background:var(--gv-cream);border-bottom:2px solid var(--gv-cream-2);transition:background .1s; }
356
+ .gv-table tbody tr:nth-child(even) { background:var(--gv-cream-2); }
357
+ .gv-table tbody tr:hover { background:#f0e0c0; }
358
+ .gv-table tbody tr:last-child { border-bottom:none; }
359
+ .gv-table tbody td { padding:11px 16px;color:var(--gv-brown-dark);font-weight:600;line-height:var(--gv-lh-vi-tight); }
360
+
361
+ /* --- TABS --- */
362
+ .gv-tabs { display:flex;flex-direction:column; }
363
+ .gv-tab-list { display:flex;border-bottom:var(--gv-border);gap:2px;overflow-x:auto;scrollbar-width:none; }
364
+ .gv-tab-list::-webkit-scrollbar { display:none; }
365
+ /* [FIX] tab dùng body font để hiển thị tiếng Việt đúng */
366
+ .gv-tab-item { padding:10px 18px;font-family:var(--gv-font-body);font-size:12px;font-weight:800;color:var(--gv-brown-light);cursor:pointer;border:var(--gv-border);border-bottom:none;border-radius:var(--gv-radius-md) var(--gv-radius-md) 0 0;background:var(--gv-cream-2);transition:var(--gv-transition);white-space:nowrap;margin-bottom:-2px;line-height:var(--gv-lh-vi-tight); }
367
+ .gv-tab-item:hover { background:var(--gv-cream);color:var(--gv-brown-mid); }
368
+ .gv-tab-item.gv-tab-active { background:var(--gv-cream);color:var(--gv-brown-dark);border-bottom:2px solid var(--gv-cream);box-shadow:var(--gv-shadow-sm) var(--gv-brown-light); }
369
+ .gv-tab-panel { padding:20px;background:var(--gv-cream);border:var(--gv-border);border-top:none;border-radius:0 var(--gv-radius-md) var(--gv-radius-md) var(--gv-radius-md);display:none; }
370
+ .gv-tab-panel.gv-tab-active { display:block;animation:gv-fade-in .15s ease; }
371
+
372
+ /* --- DIVIDERS --- */
373
+ .gv-divider { border:none;height:3px;background:repeating-linear-gradient(90deg,var(--gv-brown-light) 0,var(--gv-brown-light) 8px,transparent 8px,transparent 16px);margin:24px 0; }
374
+ .gv-divider-solid { border:none;height:2px;background:var(--gv-brown-light);margin:24px 0; }
375
+ .gv-divider-with-text { display:flex;align-items:center;gap:12px;margin:24px 0; }
376
+ .gv-divider-with-text::before,.gv-divider-with-text::after { content:'';flex:1;height:2px;background:var(--gv-brown-light); }
377
+ /* [FIX] dùng body font để tiếng Việt hiển thị đúng trong divider */
378
+ .gv-divider-with-text span { font-family:var(--gv-font-body);font-size:11px;font-weight:700;color:var(--gv-brown-light);white-space:nowrap;text-transform:uppercase;letter-spacing:.5px; }
379
+ .gv-pixel-divider { display:flex;align-items:center;margin:24px 0; }
380
+ .gv-pixel-divider span { display:inline-block;height:4px;flex:1;background:repeating-linear-gradient(90deg,var(--gv-brown-mid) 0,var(--gv-brown-mid) 8px,transparent 8px,transparent 16px); }
381
+ .gv-pixel-divider .gv-diamond { width:12px;height:12px;background:var(--gv-gold);transform:rotate(45deg);flex-shrink:0;margin:0 8px; }
382
+
383
+ /* --- SPINNER --- */
384
+ .gv-spinner { display:inline-block;width:32px;height:32px;border:3px solid var(--gv-brown-light);border-top-color:var(--gv-gold);border-radius:50%;animation:gv-spin .7s linear infinite; }
385
+ .gv-spinner-sm { width:18px;height:18px;border-width:2px; }
386
+ .gv-spinner-lg { width:48px;height:48px;border-width:4px; }
387
+ .gv-loader-pixel { display:inline-flex;gap:5px; }
388
+ .gv-loader-pixel span { display:block;width:10px;height:10px;background:var(--gv-gold);border:2px solid var(--gv-gold-dark);border-radius:var(--gv-radius-sm);animation:gv-bounce .6s ease infinite alternate; }
389
+ .gv-loader-pixel span:nth-child(2) { animation-delay:.15s;background:var(--gv-brown-mid);border-color:var(--gv-brown-dark); }
390
+ .gv-loader-pixel span:nth-child(3) { animation-delay:.3s;background:var(--gv-red);border-color:var(--gv-red-dark); }
391
+
392
+ /* --- TOAST --- */
393
+ /* [FIX] line-height cao hơn cho text tiếng Việt */
394
+ .gv-toast { display:flex;align-items:center;gap:10px;padding:12px 18px;background:var(--gv-brown-dark);color:var(--gv-cream);border:var(--gv-border);border-radius:var(--gv-radius-lg);box-shadow:var(--gv-shadow-md) var(--gv-brown-darkest);font-size:13px;font-weight:700;line-height:var(--gv-lh-vi-tight);min-width:220px;max-width:380px;animation:gv-slide-up .2s ease; }
395
+ .gv-toast-icon { flex-shrink:0;font-size:16px; }
396
+ .gv-toast-success { border-color:var(--gv-green); }
397
+ .gv-toast-danger { border-color:var(--gv-red); }
398
+ .gv-toast-warning { border-color:var(--gv-gold); }
399
+ .gv-toast-info { border-color:var(--gv-blue); }
400
+
401
+ /* --- LIST GROUP --- */
402
+ .gv-list { display:flex;flex-direction:column;border:var(--gv-border);border-radius:var(--gv-radius-lg);overflow:hidden;box-shadow:var(--gv-shadow-sm) var(--gv-brown-light); }
403
+ .gv-list-item { display:flex;align-items:center;gap:12px;padding:12px 16px;background:var(--gv-cream);border-bottom:2px solid var(--gv-cream-2);font-size:14px;font-weight:600;color:var(--gv-brown-dark);transition:background .1s;line-height:var(--gv-lh-vi-tight); }
404
+ .gv-list-item:last-child { border-bottom:none; }
405
+ .gv-list-item.gv-list-item-action { cursor:pointer;text-decoration:none; }
406
+ .gv-list-item.gv-list-item-action:hover { background:var(--gv-cream-2); }
407
+ .gv-list-item.gv-list-item-active { background:var(--gv-gold);color:var(--gv-brown-dark);border-bottom-color:var(--gv-gold-dark); }
408
+
409
+ /* --- BREADCRUMB --- */
410
+ .gv-breadcrumb { display:flex;align-items:center;flex-wrap:wrap;gap:4px;font-size:12px;font-weight:700;line-height:1.5; }
411
+ .gv-breadcrumb-item { display:flex;align-items:center;gap:4px;color:var(--gv-brown-light);text-decoration:none;transition:color .15s; }
412
+ .gv-breadcrumb-item:hover { color:var(--gv-gold-dark); }
413
+ .gv-breadcrumb-item.gv-breadcrumb-active { color:var(--gv-brown-dark);pointer-events:none; }
414
+ /* [FIX] breadcrumb sep dùng body font */
415
+ .gv-breadcrumb-sep { color:var(--gv-brown-light);font-family:var(--gv-font-body);font-size:12px;margin:0 2px;opacity:.6; }
416
+
417
+ /* --- PAGINATION --- */
418
+ .gv-pagination { display:flex;align-items:center;gap:6px;flex-wrap:wrap; }
419
+ .gv-page-item { display:inline-flex;align-items:center;justify-content:center;width:38px;height:38px;border:var(--gv-border);border-radius:var(--gv-radius-md);background:var(--gv-cream);color:var(--gv-brown-mid);font-weight:800;font-size:13px;cursor:pointer;text-decoration:none;transition:var(--gv-transition);box-shadow:var(--gv-shadow-sm) var(--gv-brown-light); }
420
+ .gv-page-item:hover { background:var(--gv-cream-2);transform:translate(-1px,-1px);box-shadow:var(--gv-shadow-md) var(--gv-brown-light); }
421
+ .gv-page-item.gv-page-active { background:var(--gv-gold);border-color:var(--gv-gold-dark);color:var(--gv-brown-dark);box-shadow:var(--gv-shadow-sm) var(--gv-gold-dark); }
422
+ .gv-page-item.gv-page-disabled { opacity:.4;pointer-events:none; }
423
+
424
+ /* --- MODAL --- */
425
+ /* [FIX] mặc định display:none, chỉ hiện khi .active */
426
+ .gv-modal-backdrop { display:none;position:fixed;inset:0;background:rgba(26,16,8,.75);backdrop-filter:blur(2px);-webkit-backdrop-filter:blur(2px);z-index:1000;align-items:center;justify-content:center;padding:16px; }
427
+ .gv-modal-backdrop.active { display:flex;animation:gv-fade-in .15s ease; }
428
+ .gv-modal { background:var(--gv-cream);border:var(--gv-border);border-radius:var(--gv-radius-xl);box-shadow:var(--gv-shadow-xl) var(--gv-brown-dark);width:100%;max-width:520px;max-height:90vh;overflow-y:auto;animation:gv-slide-up .2s ease; }
429
+ .gv-modal-header { padding:18px 24px;border-bottom:var(--gv-border);background:var(--gv-cream-2);border-radius:var(--gv-radius-xl) var(--gv-radius-xl) 0 0;display:flex;align-items:center;justify-content:space-between; }
430
+ /* [FIX] modal title dùng body font để tiếng Việt hiển thị đúng */
431
+ .gv-modal-title { font-family:var(--gv-font-body);font-size:14px;font-weight:800;color:var(--gv-brown-dark);letter-spacing:.3px;line-height:var(--gv-lh-vi-tight); }
432
+ .gv-modal-close { background:none;border:none;cursor:pointer;color:var(--gv-brown-mid);font-size:18px;padding:4px 8px;border-radius:var(--gv-radius-sm);flex-shrink:0; }
433
+ .gv-modal-close:hover { background:var(--gv-cream-3); }
434
+ .gv-modal-body { padding:24px; }
435
+ .gv-modal-footer { padding:16px 24px;border-top:var(--gv-border);background:var(--gv-cream-2);border-radius:0 0 var(--gv-radius-xl) var(--gv-radius-xl);display:flex;justify-content:flex-end;gap:10px; }
436
+
437
+ /* --- LAYOUT UTILS --- */
438
+ .gv-flex { display:flex; }
439
+ .gv-flex-center { display:flex;align-items:center;justify-content:center; }
440
+ .gv-flex-between { display:flex;align-items:center;justify-content:space-between; }
441
+ .gv-flex-col { display:flex;flex-direction:column; }
442
+ .gv-flex-wrap { flex-wrap:wrap; }
443
+ .gv-gap-1{gap:4px}.gv-gap-2{gap:8px}.gv-gap-3{gap:12px}.gv-gap-4{gap:16px}.gv-gap-5{gap:24px}
444
+ .gv-mt-1{margin-top:4px}.gv-mt-2{margin-top:8px}.gv-mt-3{margin-top:12px}.gv-mt-4{margin-top:16px}.gv-mt-5{margin-top:24px}
445
+ .gv-mb-1{margin-bottom:4px}.gv-mb-2{margin-bottom:8px}.gv-mb-3{margin-bottom:12px}.gv-mb-4{margin-bottom:16px}.gv-mb-5{margin-bottom:24px}
446
+ .gv-p-2{padding:8px}.gv-p-3{padding:12px}.gv-p-4{padding:16px}.gv-p-5{padding:24px}
447
+ .gv-grid-2 { display:grid;grid-template-columns:repeat(2,1fr);gap:16px; }
448
+ .gv-grid-3 { display:grid;grid-template-columns:repeat(3,1fr);gap:16px; }
449
+ .gv-grid-4 { display:grid;grid-template-columns:repeat(4,1fr);gap:16px; }
450
+ @media(max-width:768px) { .gv-grid-2,.gv-grid-3,.gv-grid-4 { grid-template-columns:1fr; } }
451
+ @media(min-width:769px) and (max-width:1024px) { .gv-grid-3,.gv-grid-4 { grid-template-columns:repeat(2,1fr); } }
452
+
453
+ /* --- KEYFRAMES --- */
454
+ @keyframes gv-spin { to{transform:rotate(360deg)} }
455
+ @keyframes gv-bounce { from{transform:translateY(0)} to{transform:translateY(-8px)} }
456
+ @keyframes gv-fade-in { from{opacity:0} to{opacity:1} }
457
+ @keyframes gv-slide-up{ from{opacity:0;transform:translateY(16px)} to{opacity:1;transform:translateY(0)} }
458
+ /* [FIX] gv-progress-move hoạt động với background-size */
459
+ @keyframes gv-progress-move { from{background-position:0 0} to{background-position:24px 0} }
460
+ @keyframes gv-pixel-blink { 0%,100%{opacity:1} 50%{opacity:0} }
461
+ </style>
462
+ </head>
463
+ <body>
464
+
465
+ <!-- PAGE HEADER -->
466
+ <header class="page-header">
467
+ <div class="page-logo">⚔ GAVL UI</div>
468
+ <p class="page-sub">Pixel RPG Component Library · Made for GAVL.IO.VN</p>
469
+ <span class="page-version">v1.1.0 · Vietnamese-Ready</span>
470
+ </header>
471
+
472
+ <!-- 00. CHANGELOG -->
473
+ <div class="section">
474
+ <div class="section-head">
475
+ <span class="section-head-num">00</span>
476
+ <span class="section-head-title">CHANGELOG v1.1</span>
477
+ </div>
478
+ <div class="section-body-col">
479
+ <div class="gv-alert gv-alert-info">
480
+ <span style="font-size:18px">ℹ️</span>
481
+ <div>
482
+ <div class="gv-alert-title">Font tiếng Việt</div>
483
+ Đổi font body sang <strong>Be Vietnam Pro</strong> — hỗ trợ đầy đủ dấu thanh tiếng Việt (ộ, ề, ẫ, ứ...). Nunito làm fallback.
484
+ </div>
485
+ </div>
486
+ <div class="gv-alert gv-alert-warning">
487
+ <span style="font-size:18px">⚠️</span>
488
+ <div>
489
+ <div class="gv-alert-title">Press Start 2P — CHỈ dùng cho ASCII</div>
490
+ Font pixel <strong>không có ký tự tiếng Việt</strong>. Các class <code style="background:rgba(0,0,0,.1);padding:1px 5px;border-radius:3px">gv-display-*</code>, <code style="background:rgba(0,0,0,.1);padding:1px 5px;border-radius:3px">gv-btn-pixel</code>, <code style="background:rgba(0,0,0,.1);padding:1px 5px;border-radius:3px">gv-badge-pixel</code>, <code style="background:rgba(0,0,0,.1);padding:1px 5px;border-radius:3px">gv-form-label</code> chỉ dùng cho text ASCII. Dùng <strong>gv-heading-*</strong>, <strong>gv-form-label-vi</strong>, <strong>gv-card-title-vi</strong> cho tiếng Việt.
491
+ </div>
492
+ </div>
493
+ <div class="gv-alert gv-alert-success">
494
+ <span style="font-size:18px">✅</span>
495
+ <div>
496
+ <div class="gv-alert-title">Bugs đã sửa</div>
497
+ line-height tiếng Việt · gv-btn-loading::after display · gv-modal-backdrop ẩn mặc định · gv-progress-animated background-size · gv-purple-dark token · gv-tag độc lập (không @extend) · table/tooltip dùng body font · gv-alert-title dùng body font
498
+ </div>
499
+ </div>
500
+ </div>
501
+ </div>
502
+
503
+ <!-- 01. TYPOGRAPHY -->
504
+ <div class="section">
505
+ <div class="section-head">
506
+ <span class="section-head-num">01</span>
507
+ <span class="section-head-title">TYPOGRAPHY</span>
508
+ </div>
509
+ <div class="section-body-col">
510
+ <div><p class="demo-label">PIXEL DISPLAY (ASCII only)</p>
511
+ <div class="gv-display-1">DISPLAY 1 · 24px</div>
512
+ <div class="gv-display-2 gv-mt-2">Display 2 · 18px</div>
513
+ <div class="gv-display-3 gv-mt-2">Display 3 · 14px</div>
514
+ <div class="gv-display-4 gv-mt-2">Display 4 · 10px</div>
515
+ <div class="gv-display-5 gv-mt-2">Display 5 · 8px label</div>
516
+ </div>
517
+ <hr class="gv-divider-solid">
518
+ <div><p class="demo-label">HEADING TIẾNG VIỆT (gv-heading-*)</p>
519
+ <div class="gv-flex-col gv-gap-2">
520
+ <div class="gv-heading-1">Tin Tức Game Mới Nhất Hôm Nay</div>
521
+ <div class="gv-heading-2">Đánh Giá Elden Ring — Hành Trình Vào Vùng Đất Giữa</div>
522
+ <div class="gv-heading-3">VCT Pacific 2025 — Lịch Thi Đấu & Kết Quả</div>
523
+ <div class="gv-heading-4">Hướng Dẫn Build Nhân Vật Sorcerer Mạnh Nhất</div>
524
+ </div>
525
+ </div>
526
+ <hr class="gv-divider-solid">
527
+ <div><p class="demo-label">BODY TEXT — tiếng Việt</p>
528
+ <div class="gv-flex-col gv-gap-2">
529
+ <span class="gv-text-xl">Tin nổi bật: Elden Ring DLC ra mắt với nội dung khổng lồ</span>
530
+ <span class="gv-text-lg">Game thủ Việt Nam đoạt giải Esports Thế Giới năm 2025</span>
531
+ <span class="gv-text-md">Nội dung bài viết thông thường với các ký tự đặc biệt: ộ, ề, ẫ, ứ, ặ, ỡ, ợ, ử, ữ</span>
532
+ <span class="gv-text-sm">Ghi chú: Cập nhật lúc 22/04/2025 · Tác giả: Biên tập viên GAVL</span>
533
+ <span class="gv-text-xs gv-text-muted">Caption nhỏ · Nguồn: GAVL.IO.VN · Bản quyền thuộc về tác giả</span>
534
+ </div>
535
+ </div>
536
+ <div><p class="demo-label">COLOR MODIFIERS</p>
537
+ <div class="gv-flex gv-flex-wrap gv-gap-3">
538
+ <span class="gv-text-gold gv-text-lg" style="font-weight:800">Vàng Gold</span>
539
+ <span class="gv-text-danger gv-text-lg" style="font-weight:800">Nguy hiểm</span>
540
+ <span class="gv-text-success gv-text-lg" style="font-weight:800">Thành công</span>
541
+ <span class="gv-text-info gv-text-lg" style="font-weight:800">Thông tin</span>
542
+ <span class="gv-text-muted gv-text-lg" style="font-weight:800">Mờ</span>
543
+ <span class="gv-text-purple gv-text-lg" style="font-weight:800">Tím</span>
544
+ </div>
545
+ </div>
546
+ <div><p class="demo-label">LABELS — ASCII vs TIẾNG VIỆT</p>
547
+ <div class="gv-flex gv-flex-wrap gv-gap-3" style="align-items:center">
548
+ <span class="gv-label">PIXEL LABEL (ASCII)</span>
549
+ <span class="gv-vi-label">Nhãn Tiếng Việt</span>
550
+ <span class="gv-caption">Caption phụ · Ngày đăng: 22/04/2025</span>
551
+ </div>
552
+ </div>
553
+ </div>
554
+ </div>
555
+
556
+ <!-- 02. BUTTONS -->
557
+ <div class="section">
558
+ <div class="section-head">
559
+ <span class="section-head-num">02</span>
560
+ <span class="section-head-title">BUTTONS</span>
561
+ </div>
562
+ <div class="section-body-col">
563
+ <div><p class="demo-label">VARIANTS — tiếng Việt trong button</p>
564
+ <div class="gv-flex gv-flex-wrap gv-gap-3">
565
+ <button class="gv-btn gv-btn-primary">Đọc ngay</button>
566
+ <button class="gv-btn gv-btn-secondary">Xem thêm</button>
567
+ <button class="gv-btn gv-btn-dark">Đăng bài</button>
568
+ <button class="gv-btn gv-btn-danger">Xóa bài</button>
569
+ <button class="gv-btn gv-btn-success">Đã lưu</button>
570
+ <button class="gv-btn gv-btn-info">Chia sẻ</button>
571
+ <button class="gv-btn gv-btn-purple">Nâng cấp</button>
572
+ <button class="gv-btn gv-btn-ghost">Hủy bỏ</button>
573
+ <button class="gv-btn gv-btn-link">Xem chi tiết</button>
574
+ </div>
575
+ </div>
576
+ <div><p class="demo-label">SIZES</p>
577
+ <div class="gv-flex gv-flex-wrap gv-gap-3" style="align-items:center">
578
+ <button class="gv-btn gv-btn-primary gv-btn-xs">Cực nhỏ</button>
579
+ <button class="gv-btn gv-btn-primary gv-btn-sm">Nhỏ</button>
580
+ <button class="gv-btn gv-btn-primary">Mặc định</button>
581
+ <button class="gv-btn gv-btn-primary gv-btn-lg">Lớn</button>
582
+ <button class="gv-btn gv-btn-primary gv-btn-xl">Rất lớn</button>
583
+ </div>
584
+ </div>
585
+ <div><p class="demo-label">PIXEL FONT (ASCII only) + STATES + GROUP</p>
586
+ <div class="gv-flex gv-flex-wrap gv-gap-3">
587
+ <button class="gv-btn gv-btn-primary gv-btn-pixel">PLAY NOW</button>
588
+ <button class="gv-btn gv-btn-dark gv-btn-pixel">START GAME</button>
589
+ <button class="gv-btn gv-btn-danger gv-disabled">Vô hiệu hoá</button>
590
+ <button class="gv-btn gv-btn-success gv-btn-loading">Đang tải</button>
591
+ </div>
592
+ <div class="gv-btn-group gv-mt-4">
593
+ <button class="gv-btn gv-btn-secondary">←</button>
594
+ <button class="gv-btn gv-btn-secondary">1</button>
595
+ <button class="gv-btn gv-btn-primary">2</button>
596
+ <button class="gv-btn gv-btn-secondary">3</button>
597
+ <button class="gv-btn gv-btn-secondary">→</button>
598
+ </div>
599
+ </div>
600
+ <div><p class="demo-label">ICON BUTTONS (tooltip tiếng Việt)</p>
601
+ <div class="gv-flex gv-gap-3">
602
+ <button class="gv-btn gv-btn-primary gv-btn-icon" data-gv-tooltip="Yêu thích">♥</button>
603
+ <button class="gv-btn gv-btn-dark gv-btn-icon" data-gv-tooltip="Chia sẻ bài viết">↗</button>
604
+ <button class="gv-btn gv-btn-danger gv-btn-icon" data-gv-tooltip="Xóa vĩnh viễn">✕</button>
605
+ <button class="gv-btn gv-btn-success gv-btn-icon gv-btn-icon-lg" data-gv-tooltip="Xác nhận hành động">✓</button>
606
+ <button class="gv-btn gv-btn-purple gv-btn-icon" data-gv-tooltip="Nâng cấp Premium">★</button>
607
+ </div>
608
+ </div>
609
+ </div>
610
+ </div>
611
+
612
+ <!-- 03. FORM INPUTS -->
613
+ <div class="section">
614
+ <div class="section-head">
615
+ <span class="section-head-num">03</span>
616
+ <span class="section-head-title">FORM INPUTS</span>
617
+ </div>
618
+ <div class="section-body-col">
619
+ <div class="gv-grid-2">
620
+ <div class="gv-form-group">
621
+ <!-- [NOTE] gv-form-label-vi cho label tiếng Việt -->
622
+ <label class="gv-form-label-vi">Tên người dùng</label>
623
+ <input class="gv-input" placeholder="Nhập tên của bạn...">
624
+ </div>
625
+ <div class="gv-form-group">
626
+ <label class="gv-form-label-vi">Địa chỉ email</label>
627
+ <input class="gv-input gv-input-error" value="email-sai@@" placeholder="email@example.com">
628
+ <span class="gv-form-error">⚠ Email không hợp lệ!</span>
629
+ </div>
630
+ <div class="gv-form-group">
631
+ <label class="gv-form-label-vi">Mật khẩu mới</label>
632
+ <input class="gv-input gv-input-success" type="password" value="••••••••">
633
+ <span class="gv-form-helper">Mật khẩu đủ mạnh 💪</span>
634
+ </div>
635
+ <div class="gv-form-group">
636
+ <label class="gv-form-label-vi">Thể loại bài viết</label>
637
+ <select class="gv-select">
638
+ <option>Tin tức Game</option>
639
+ <option>Review & Đánh giá</option>
640
+ <option>Esports</option>
641
+ <option>Hướng dẫn & Tips</option>
642
+ <option>Cộng đồng</option>
643
+ </select>
644
+ </div>
645
+ </div>
646
+ <div class="gv-form-group">
647
+ <label class="gv-form-label-vi">Tìm kiếm bài viết</label>
648
+ <div class="gv-input-group">
649
+ <span class="gv-input-addon gv-input-addon-left">🔍</span>
650
+ <input class="gv-input" placeholder="Nhập tên game, bài viết, tác giả...">
651
+ <span class="gv-input-addon gv-input-addon-right" style="cursor:pointer;background:var(--gv-gold);border-color:var(--gv-gold-dark);color:var(--gv-brown-dark);font-weight:800">Tìm</span>
652
+ </div>
653
+ </div>
654
+ <div class="gv-form-group">
655
+ <label class="gv-form-label-vi">Nội dung bài viết</label>
656
+ <textarea class="gv-textarea" placeholder="Viết gì đó hay ho đi bro... Tiếng Việt hiển thị đúng với Be Vietnam Pro 🎮"></textarea>
657
+ </div>
658
+ <div><p class="demo-label">CHECKBOX · RADIO · TOGGLE · RANGE</p>
659
+ <div class="gv-flex gv-flex-wrap gv-gap-4">
660
+ <label class="gv-check-group">
661
+ <input type="checkbox" checked>
662
+ <div class="gv-check-box">✓</div>
663
+ <span class="gv-check-label">Đồng ý điều khoản sử dụng</span>
664
+ </label>
665
+ <label class="gv-check-group">
666
+ <input type="checkbox">
667
+ <div class="gv-check-box"></div>
668
+ <span class="gv-check-label">Nhận thông báo qua email</span>
669
+ </label>
670
+ <label class="gv-check-group">
671
+ <input type="radio" name="r1" checked>
672
+ <div class="gv-radio-box"><div class="gv-radio-dot"></div></div>
673
+ <span class="gv-check-label">PC / Console</span>
674
+ </label>
675
+ <label class="gv-check-group">
676
+ <input type="radio" name="r1">
677
+ <div class="gv-radio-box"><div class="gv-radio-dot"></div></div>
678
+ <span class="gv-check-label">Mobile Gaming</span>
679
+ </label>
680
+ <label class="gv-toggle">
681
+ <input type="checkbox" checked>
682
+ <div class="gv-toggle-track"><div class="gv-toggle-thumb"></div></div>
683
+ <span class="gv-toggle-label">Chế độ tối</span>
684
+ </label>
685
+ <label class="gv-toggle">
686
+ <input type="checkbox">
687
+ <div class="gv-toggle-track"><div class="gv-toggle-thumb"></div></div>
688
+ <span class="gv-toggle-label">Tự động phát</span>
689
+ </label>
690
+ </div>
691
+ <div class="gv-mt-4">
692
+ <label class="gv-form-label-vi gv-mb-2" style="display:block">Âm lượng hệ thống</label>
693
+ <input type="range" class="gv-range" value="65">
694
+ </div>
695
+ </div>
696
+ </div>
697
+ </div>
698
+
699
+ <!-- 04. CARDS -->
700
+ <div class="section">
701
+ <div class="section-head">
702
+ <span class="section-head-num">04</span>
703
+ <span class="section-head-title">CARDS</span>
704
+ </div>
705
+ <div class="section-body-col">
706
+ <div class="gv-grid-3">
707
+ <!-- Default card — dùng gv-card-title-vi cho tiếng Việt -->
708
+ <div class="gv-card gv-card-hover">
709
+ <img class="gv-card-image" src="https://placehold.co/400x225/5c3d1e/f5e9d3?text=GAME+IMG" alt="">
710
+ <div class="gv-card-body">
711
+ <div class="gv-card-title-vi">Elden Ring DLC Shadow of the Erdtree: Đánh Giá Chi Tiết</div>
712
+ <p class="gv-card-desc">Hành trình vào vùng đất bị nguyền rủa với những thử thách kinh hoàng nhất từ trước đến nay.</p>
713
+ <div class="gv-flex gv-flex-between gv-mt-4" style="align-items:center">
714
+ <span class="gv-badge gv-badge-primary gv-badge-pixel">HOT</span>
715
+ <button class="gv-btn gv-btn-dark gv-btn-sm">Đọc ngay</button>
716
+ </div>
717
+ </div>
718
+ </div>
719
+ <!-- Dark card -->
720
+ <div class="gv-card gv-card-dark gv-card-hover">
721
+ <div class="gv-card-header" style="background:rgba(0,0,0,0.2);border-color:rgba(255,255,255,0.1)">
722
+ <span class="gv-heading-4" style="color:var(--gv-gold)">Esports</span>
723
+ <span class="gv-badge gv-badge-danger gv-badge-pixel">LIVE</span>
724
+ </div>
725
+ <div class="gv-card-body">
726
+ <div class="gv-card-title-vi" style="color:var(--gv-cream)">VCT Pacific 2025 — Tuần Chung Kết</div>
727
+ <p class="gv-card-desc" style="color:var(--gv-brown-light)">Team Flash vs Paper Rex — Trận đấu kinh điển đang diễn ra. Ai sẽ giành chức vô địch?</p>
728
+ <button class="gv-btn gv-btn-primary gv-btn-block gv-mt-4 gv-btn-pixel" style="font-size:8px">▶ XEM NGAY</button>
729
+ </div>
730
+ </div>
731
+ <!-- Gold card -->
732
+ <div class="gv-card gv-card-gold gv-card-hover">
733
+ <div class="gv-card-body" style="text-align:center;padding:32px 20px">
734
+ <div style="font-size:40px;margin-bottom:12px">🏆</div>
735
+ <div class="gv-card-title-vi">Hạng S+ Đạt Được!</div>
736
+ <p class="gv-card-desc">Bạn đã hoàn thành thử thách tháng này! Nhận phần thưởng đặc biệt ngay hôm nay.</p>
737
+ <button class="gv-btn gv-btn-dark gv-btn-block gv-mt-4">Nhận thưởng ngay</button>
738
+ </div>
739
+ </div>
740
+ </div>
741
+ <!-- Card with header/footer -->
742
+ <div class="gv-card">
743
+ <div class="gv-card-header">
744
+ <span class="gv-heading-4">Cài Đặt Tài Khoản</span>
745
+ <span class="gv-badge gv-badge-success">Đã lưu</span>
746
+ </div>
747
+ <div class="gv-card-body">
748
+ <p class="gv-text-sm">Quản lý thông tin cá nhân và tùy chỉnh trải nghiệm của bạn trên GAVL.IO.VN.</p>
749
+ </div>
750
+ <div class="gv-card-footer gv-flex gv-gap-3" style="justify-content:flex-end">
751
+ <button class="gv-btn gv-btn-ghost gv-btn-sm">Hủy thay đổi</button>
752
+ <button class="gv-btn gv-btn-primary gv-btn-sm">Lưu cài đặt</button>
753
+ </div>
754
+ </div>
755
+ </div>
756
+ </div>
757
+
758
+ <!-- 05. BADGES & TAGS -->
759
+ <div class="section">
760
+ <div class="section-head">
761
+ <span class="section-head-num">05</span>
762
+ <span class="section-head-title">BADGES & TAGS</span>
763
+ </div>
764
+ <div class="section-body-col">
765
+ <div><p class="demo-label">BADGES — thường (tiếng Việt OK)</p>
766
+ <div class="gv-flex gv-flex-wrap gv-gap-3">
767
+ <span class="gv-badge gv-badge-primary">Nổi bật</span>
768
+ <span class="gv-badge gv-badge-dark">Tối</span>
769
+ <span class="gv-badge gv-badge-danger">Nguy hiểm</span>
770
+ <span class="gv-badge gv-badge-success">Thành công</span>
771
+ <span class="gv-badge gv-badge-info">Thông tin</span>
772
+ <span class="gv-badge gv-badge-purple">Cao cấp</span>
773
+ <span class="gv-badge gv-badge-outline">Viền</span>
774
+ </div>
775
+ <p class="demo-label gv-mt-4">BADGES PIXEL — CHỈ ASCII</p>
776
+ <div class="gv-flex gv-flex-wrap gv-gap-3">
777
+ <span class="gv-badge gv-badge-primary gv-badge-pixel">HOT</span>
778
+ <span class="gv-badge gv-badge-danger gv-badge-pixel">LIVE</span>
779
+ <span class="gv-badge gv-badge-success gv-badge-pixel">NEW</span>
780
+ <span class="gv-badge gv-badge-dark gv-badge-pixel">TOP 1</span>
781
+ <span class="gv-badge gv-badge-info gv-badge-pixel">BETA</span>
782
+ <span class="gv-badge gv-badge-purple gv-badge-pixel">PRO</span>
783
+ </div>
784
+ </div>
785
+ <div><p class="demo-label">TAGS (clickable — tiếng Việt OK)</p>
786
+ <div class="gv-flex gv-flex-wrap gv-gap-3">
787
+ <a class="gv-tag" href="#">Capcom</a>
788
+ <a class="gv-tag" href="#">Valorant</a>
789
+ <a class="gv-tag" href="#">PS5</a>
790
+ <a class="gv-tag" href="#">PC Gaming</a>
791
+ <a class="gv-tag" href="#">Indie Game</a>
792
+ <a class="gv-tag" href="#">Esports Việt Nam</a>
793
+ <a class="gv-tag" href="#">Tin Nóng</a>
794
+ <a class="gv-tag" href="#">Hướng dẫn</a>
795
+ <a class="gv-tag" href="#">Đánh giá</a>
796
+ </div>
797
+ </div>
798
+ </div>
799
+ </div>
800
+
801
+ <!-- 06. ALERTS -->
802
+ <div class="section">
803
+ <div class="section-head">
804
+ <span class="section-head-num">06</span>
805
+ <span class="section-head-title">ALERTS</span>
806
+ </div>
807
+ <div class="section-body-col">
808
+ <div class="gv-alert gv-alert-info">
809
+ <span style="font-size:18px">ℹ️</span>
810
+ <div>
811
+ <div class="gv-alert-title">Thông báo hệ thống</div>
812
+ Máy chủ sẽ bảo trì lúc 2:00 SA ngày 25/04. Hãy lưu lại công việc trước khi hệ thống offline.
813
+ </div>
814
+ </div>
815
+ <div class="gv-alert gv-alert-success">
816
+ <span style="font-size:18px">✅</span>
817
+ <div>
818
+ <div class="gv-alert-title">Đăng bài thành công</div>
819
+ Bài viết của bạn đã được đăng và đang chờ kiểm duyệt. Cảm ơn bạn đã đóng góp cho cộng đồng GAVL!
820
+ </div>
821
+ </div>
822
+ <div class="gv-alert gv-alert-warning">
823
+ <span style="font-size:18px">⚠️</span>
824
+ <div>
825
+ <div class="gv-alert-title">Tài khoản sắp hết hạn</div>
826
+ Gói Premium của bạn sẽ hết hạn vào ngày 30/04. Gia hạn ngay để không mất quyền lợi đặc biệt.
827
+ </div>
828
+ </div>
829
+ <div class="gv-alert gv-alert-danger">
830
+ <span style="font-size:18px">🚫</span>
831
+ <div>
832
+ <div class="gv-alert-title">Lỗi kết nối</div>
833
+ Không thể kết nối tới máy chủ. Vui lòng kiểm tra kết nối mạng và thử lại sau ít phút.
834
+ </div>
835
+ </div>
836
+ </div>
837
+ </div>
838
+
839
+ <!-- 07. PROGRESS -->
840
+ <div class="section">
841
+ <div class="section-head">
842
+ <span class="section-head-num">07</span>
843
+ <span class="section-head-title">PROGRESS BARS</span>
844
+ </div>
845
+ <div class="section-body-col">
846
+ <div>
847
+ <span class="gv-caption gv-mb-2" style="display:block">Kinh nghiệm nhân vật — 72%</span>
848
+ <div class="gv-progress-wrap"><div class="gv-progress-bar" style="width:72%"></div></div>
849
+ </div>
850
+ <div>
851
+ <span class="gv-caption gv-mb-2" style="display:block">Nhiệm vụ hoàn thành — 55%</span>
852
+ <div class="gv-progress-wrap"><div class="gv-progress-bar gv-progress-success" style="width:55%"></div></div>
853
+ </div>
854
+ <div>
855
+ <span class="gv-caption gv-mb-2" style="display:block">Máu còn lại — 30%</span>
856
+ <div class="gv-progress-wrap"><div class="gv-progress-bar gv-progress-danger" style="width:30%"></div></div>
857
+ </div>
858
+ <div>
859
+ <span class="gv-caption gv-mb-2" style="display:block">Tải xuống — 88% (striped animated) [FIX: background-size]</span>
860
+ <!-- [FIX] gv-progress-animated giờ hoạt động đúng với background-size -->
861
+ <div class="gv-progress-wrap"><div class="gv-progress-bar gv-progress-info gv-progress-striped gv-progress-animated" style="width:88%"></div></div>
862
+ </div>
863
+ <div>
864
+ <span class="gv-caption gv-mb-2" style="display:block">Nhỏ (small)</span>
865
+ <div class="gv-progress-sm"><div class="gv-progress-wrap"><div class="gv-progress-bar" style="width:45%"></div></div></div>
866
+ </div>
867
+ </div>
868
+ </div>
869
+
870
+ <!-- 08. AVATARS -->
871
+ <div class="section">
872
+ <div class="section-head">
873
+ <span class="section-head-num">08</span>
874
+ <span class="section-head-title">AVATARS</span>
875
+ </div>
876
+ <div class="section-body-col">
877
+ <div><p class="demo-label">SIZES</p>
878
+ <div class="gv-flex gv-gap-3" style="align-items:center">
879
+ <div class="gv-avatar gv-avatar-xs">G</div>
880
+ <div class="gv-avatar gv-avatar-sm">GV</div>
881
+ <div class="gv-avatar gv-avatar-md">BOT</div>
882
+ <div class="gv-avatar gv-avatar-lg gv-avatar-gold">PRO</div>
883
+ <div class="gv-avatar gv-avatar-xl">🎮</div>
884
+ </div>
885
+ </div>
886
+ <div><p class="demo-label">CIRCLE + GOLD BORDER</p>
887
+ <div class="gv-flex gv-gap-3" style="align-items:center">
888
+ <div class="gv-avatar gv-avatar-md gv-avatar-circle">A</div>
889
+ <div class="gv-avatar gv-avatar-md gv-avatar-circle gv-avatar-gold">★</div>
890
+ <div class="gv-avatar gv-avatar-lg gv-avatar-circle">🦊</div>
891
+ <div class="gv-avatar gv-avatar-lg gv-avatar-circle gv-avatar-gold">👑</div>
892
+ </div>
893
+ </div>
894
+ <div><p class="demo-label">AVATAR GROUP</p>
895
+ <div class="gv-avatar-group">
896
+ <div class="gv-avatar gv-avatar-sm gv-avatar-circle">A</div>
897
+ <div class="gv-avatar gv-avatar-sm gv-avatar-circle" style="background:var(--gv-red)">B</div>
898
+ <div class="gv-avatar gv-avatar-sm gv-avatar-circle" style="background:var(--gv-blue)">C</div>
899
+ <div class="gv-avatar gv-avatar-sm gv-avatar-circle" style="background:var(--gv-purple)">D</div>
900
+ <div class="gv-avatar gv-avatar-sm gv-avatar-circle gv-avatar-gold" style="background:var(--gv-gold);color:var(--gv-brown-dark)">+9</div>
901
+ </div>
902
+ </div>
903
+ </div>
904
+ </div>
905
+
906
+ <!-- 09. TABS -->
907
+ <div class="section">
908
+ <div class="section-head">
909
+ <span class="section-head-num">09</span>
910
+ <span class="section-head-title">TABS</span>
911
+ </div>
912
+ <div class="section-body-col">
913
+ <!-- [FIX] Tab label tiếng Việt hiển thị đúng với body font -->
914
+ <div class="gv-tabs">
915
+ <div class="gv-tab-list">
916
+ <div class="gv-tab-item gv-tab-active" onclick="switchTab(this,'tab1')">Tin Tức</div>
917
+ <div class="gv-tab-item" onclick="switchTab(this,'tab2')">Đánh Giá</div>
918
+ <div class="gv-tab-item" onclick="switchTab(this,'tab3')">Esports</div>
919
+ <div class="gv-tab-item" onclick="switchTab(this,'tab4')">Hướng Dẫn</div>
920
+ <div class="gv-tab-item" onclick="switchTab(this,'tab5')">Cộng Đồng</div>
921
+ </div>
922
+ <div id="tab1" class="gv-tab-panel gv-tab-active">
923
+ <p class="gv-text-md">📰 <strong>Tin Tức</strong> — Cập nhật tin tức game mới nhất mỗi ngày từ khắp nơi trên thế giới. Đặc biệt chú trọng thị trường Đông Nam Á và Việt Nam.</p>
924
+ </div>
925
+ <div id="tab2" class="gv-tab-panel">
926
+ <p class="gv-text-md">⭐ <strong>Đánh Giá</strong> — Review chi tiết từ các game thủ chuyên nghiệp. Điểm số, ưu nhược điểm, và khuyến nghị cho từng đối tượng người chơi.</p>
927
+ </div>
928
+ <div id="tab3" class="gv-tab-panel">
929
+ <p class="gv-text-md">🏆 <strong>Esports</strong> — Kết quả thi đấu, lịch giải đấu mới nhất. Theo dõi các đội tuyển Việt Nam trên đấu trường quốc tế.</p>
930
+ </div>
931
+ <div id="tab4" class="gv-tab-panel">
932
+ <p class="gv-text-md">📖 <strong>Hướng Dẫn</strong> — Tips, tricks và chiến thuật cho mọi thể loại game. Từ beginner đến hardcore gamer đều có chỗ học.</p>
933
+ </div>
934
+ <div id="tab5" class="gv-tab-panel">
935
+ <p class="gv-text-md">💬 <strong>Cộng Đồng</strong> — Kết nối với hàng nghìn game thủ Việt. Chia sẻ clip, thảo luận, và tổ chức squad cùng nhau.</p>
936
+ </div>
937
+ </div>
938
+ </div>
939
+ </div>
940
+
941
+ <!-- 10. TABLE -->
942
+ <div class="section">
943
+ <div class="section-head">
944
+ <span class="section-head-num">10</span>
945
+ <span class="section-head-title">TABLE</span>
946
+ </div>
947
+ <div class="section-body-col">
948
+ <!-- [FIX] thead th dùng body font, tiếng Việt hiển thị đúng -->
949
+ <div class="gv-table-wrap">
950
+ <table class="gv-table">
951
+ <thead><tr>
952
+ <th>#</th><th>Tên Game</th><th>Thể Loại</th><th>Điểm</th><th>Trạng Thái</th>
953
+ </tr></thead>
954
+ <tbody>
955
+ <tr><td>1</td><td><strong>Elden Ring</strong></td><td>Nhập vai hành động</td><td>9.8</td><td><span class="gv-badge gv-badge-success gv-badge-pixel">HOT</span></td></tr>
956
+ <tr><td>2</td><td><strong>Baldur's Gate 3</strong></td><td>RPG chiến thuật</td><td>9.6</td><td><span class="gv-badge gv-badge-primary gv-badge-pixel">TOP</span></td></tr>
957
+ <tr><td>3</td><td><strong>Hollow Knight</strong></td><td>Metroidvania</td><td>9.5</td><td><span class="gv-badge gv-badge-info gv-badge-pixel">INDIE</span></td></tr>
958
+ <tr><td>4</td><td><strong>Cyberpunk 2077</strong></td><td>RPG thế giới mở</td><td>8.9</td><td><span class="gv-badge gv-badge-outline gv-badge-pixel">UPDATE</span></td></tr>
959
+ </tbody>
960
+ </table>
961
+ </div>
962
+ </div>
963
+ </div>
964
+
965
+ <!-- 11. LIST + BREADCRUMB + PAGINATION -->
966
+ <div class="section">
967
+ <div class="section-head">
968
+ <span class="section-head-num">11</span>
969
+ <span class="section-head-title">LIST · BREADCRUMB · PAGINATION</span>
970
+ </div>
971
+ <div class="section-body-col">
972
+ <div><p class="demo-label">BẢNG XẾP HẠNG</p>
973
+ <div class="gv-list">
974
+ <div class="gv-list-item gv-list-item-active">🏆 Hạng 1 — DragonSlayer · 9,850 điểm</div>
975
+ <a class="gv-list-item gv-list-item-action" href="#">🥈 Hạng 2 — NightWolf · 8,420 điểm</a>
976
+ <a class="gv-list-item gv-list-item-action" href="#">🥉 Hạng 3 — PixelHero · 7,100 điểm</a>
977
+ <a class="gv-list-item gv-list-item-action" href="#" style="color:var(--gv-gray-3)">4 — ShadowBlade · 5,600 điểm</a>
978
+ </div>
979
+ </div>
980
+ <div><p class="demo-label">BREADCRUMB — tiếng Việt</p>
981
+ <!-- [FIX] separator dùng body font, không bị vỡ -->
982
+ <nav class="gv-breadcrumb">
983
+ <a class="gv-breadcrumb-item" href="#">Trang chủ</a>
984
+ <span class="gv-breadcrumb-sep">›</span>
985
+ <a class="gv-breadcrumb-item" href="#">Tin Tức Game</a>
986
+ <span class="gv-breadcrumb-sep">›</span>
987
+ <span class="gv-breadcrumb-item gv-breadcrumb-active">Đánh Giá Elden Ring DLC</span>
988
+ </nav>
989
+ </div>
990
+ <div><p class="demo-label">PHÂN TRANG</p>
991
+ <div class="gv-pagination">
992
+ <a class="gv-page-item gv-page-disabled" href="#">«</a>
993
+ <a class="gv-page-item gv-page-active" href="#">1</a>
994
+ <a class="gv-page-item" href="#">2</a>
995
+ <a class="gv-page-item" href="#">3</a>
996
+ <span class="gv-page-item" style="cursor:default;box-shadow:none;background:transparent;border-color:transparent">…</span>
997
+ <a class="gv-page-item" href="#">12</a>
998
+ <a class="gv-page-item" href="#">»</a>
999
+ </div>
1000
+ </div>
1001
+ </div>
1002
+ </div>
1003
+
1004
+ <!-- 12. DIVIDERS + SPINNERS + TOASTS -->
1005
+ <div class="section">
1006
+ <div class="section-head">
1007
+ <span class="section-head-num">12</span>
1008
+ <span class="section-head-title">DIVIDERS · SPINNERS · TOASTS</span>
1009
+ </div>
1010
+ <div class="section-body-col">
1011
+ <div><p class="demo-label">DIVIDERS — tiếng Việt trong divider-with-text</p>
1012
+ <hr class="gv-divider">
1013
+ <hr class="gv-divider-solid">
1014
+ <!-- [FIX] body font — tiếng Việt hiển thị đúng -->
1015
+ <div class="gv-divider-with-text"><span>Hoặc đăng nhập bằng</span></div>
1016
+ <div class="gv-pixel-divider"><span></span><div class="gv-diamond"></div><span></span><div class="gv-diamond"></div><span></span></div>
1017
+ </div>
1018
+ <div><p class="demo-label">SPINNERS & LOADERS</p>
1019
+ <div class="gv-flex gv-gap-4" style="align-items:center">
1020
+ <div class="gv-spinner gv-spinner-sm"></div>
1021
+ <div class="gv-spinner"></div>
1022
+ <div class="gv-spinner gv-spinner-lg"></div>
1023
+ <div class="gv-loader-pixel">
1024
+ <span></span><span></span><span></span>
1025
+ </div>
1026
+ </div>
1027
+ </div>
1028
+ <div><p class="demo-label">TOASTS — tiếng Việt dài hiển thị đúng</p>
1029
+ <div class="gv-flex-col gv-gap-3">
1030
+ <div class="gv-toast gv-toast-success"><span class="gv-toast-icon">✅</span> Đăng bài thành công! Nội dung đang được kiểm duyệt.</div>
1031
+ <div class="gv-toast gv-toast-danger"><span class="gv-toast-icon">🚫</span> Không thể kết nối. Vui lòng kiểm tra lại.</div>
1032
+ <div class="gv-toast gv-toast-warning"><span class="gv-toast-icon">⚡</span> Bot đang bận, hàng đợi còn 3 yêu cầu.</div>
1033
+ <div class="gv-toast gv-toast-info"><span class="gv-toast-icon">ℹ️</span> Phiên bản mới v2.0 đã sẵn sàng cập nhật.</div>
1034
+ </div>
1035
+ </div>
1036
+ </div>
1037
+ </div>
1038
+
1039
+ <!-- 13. MODAL -->
1040
+ <div class="section">
1041
+ <div class="section-head">
1042
+ <span class="section-head-num">13</span>
1043
+ <span class="section-head-title">MODAL</span>
1044
+ </div>
1045
+ <div class="section-body">
1046
+ <button class="gv-btn gv-btn-primary gv-btn-pixel" onclick="document.getElementById('demoModal').classList.add('active')">
1047
+ ▶ MO MODAL
1048
+ </button>
1049
+ <button class="gv-btn gv-btn-dark" onclick="document.getElementById('demoModal').classList.add('active')">
1050
+ Xem demo modal tiếng Việt
1051
+ </button>
1052
+ </div>
1053
+ </div>
1054
+
1055
+ <!-- MODAL DEMO — [FIX] display:none mặc định, dùng .active để mở -->
1056
+ <div class="gv-modal-backdrop" id="demoModal" onclick="if(event.target===this)this.classList.remove('active')">
1057
+ <div class="gv-modal">
1058
+ <div class="gv-modal-header">
1059
+ <!-- [FIX] modal title dùng body font — tiếng Việt hiển thị đúng -->
1060
+ <span class="gv-modal-title">Xác Nhận Xóa Bài Viết</span>
1061
+ <button class="gv-modal-close" onclick="document.getElementById('demoModal').classList.remove('active')">✕</button>
1062
+ </div>
1063
+ <div class="gv-modal-body">
1064
+ <div class="gv-alert gv-alert-warning gv-mb-4">
1065
+ <span>⚠️</span>
1066
+ <div>Bạn sắp xóa bài viết này vĩnh viễn. Hành động không thể hoàn tác!</div>
1067
+ </div>
1068
+ <div class="gv-form-group">
1069
+ <label class="gv-form-label-vi">Nhập "XÁC NHẬN" để tiếp tục</label>
1070
+ <input class="gv-input" placeholder="Gõ XÁC NHẬN tại đây...">
1071
+ </div>
1072
+ </div>
1073
+ <div class="gv-modal-footer">
1074
+ <button class="gv-btn gv-btn-ghost" onclick="document.getElementById('demoModal').classList.remove('active')">Hủy bỏ</button>
1075
+ <button class="gv-btn gv-btn-danger">🗑 Xóa vĩnh viễn</button>
1076
+ </div>
1077
+ </div>
1078
+ </div>
1079
+
1080
+ <script>
1081
+ function switchTab(el, tabId) {
1082
+ const container = el.closest('.gv-tabs');
1083
+ container.querySelectorAll('.gv-tab-item').forEach(t => t.classList.remove('gv-tab-active'));
1084
+ container.querySelectorAll('.gv-tab-panel').forEach(p => p.classList.remove('gv-tab-active'));
1085
+ el.classList.add('gv-tab-active');
1086
+ document.getElementById(tabId).classList.add('gv-tab-active');
1087
+ }
1088
+ </script>
1089
+ </body>
1090
+ </html>