@t3q-ui/design-system 0.0.0-stage → 1.56.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,2014 @@
1
+ @source "./**/*.js";
2
+ /* TDS (T3Q Design System) - Design Tokens */
3
+ /* Tailwind v4 CSS-first Configuration */
4
+ /* Note: @import 'tailwindcss'는 소비 프로젝트에서 해야 함 */
5
+
6
+ @theme {
7
+ /* ---------------------------------- Animation --------------------------------- */
8
+ @keyframes fade-in {
9
+ 0% { opacity: 0; }
10
+ 100% { opacity: 1; }
11
+ }
12
+
13
+ @keyframes fade-out {
14
+ 0% { opacity: 1; }
15
+ 100% { opacity: 0; }
16
+ }
17
+
18
+ @keyframes zoom-in {
19
+ 0% { transform: scale(0.95); }
20
+ 100% { transform: scale(1); }
21
+ }
22
+
23
+ @keyframes zoom-out {
24
+ 0% { transform: scale(1); }
25
+ 100% { transform: scale(0.95); }
26
+ }
27
+
28
+ @keyframes slide-in-top {
29
+ from { transform: translateY(-2px); }
30
+ to { transform: translateY(0); }
31
+ }
32
+
33
+ @keyframes slide-in-bottom {
34
+ from { transform: translateY(2px); }
35
+ to { transform: translateY(0); }
36
+ }
37
+
38
+ @keyframes slide-in-left {
39
+ from { transform: translateX(-2px); }
40
+ to { transform: translateX(0); }
41
+ }
42
+
43
+ @keyframes slide-in-right {
44
+ from { transform: translateX(2px); }
45
+ to { transform: translateX(0); }
46
+ }
47
+
48
+ @keyframes slide_in_from_top {
49
+ from { transform: translateY(-100%); }
50
+ to { transform: translateY(0); }
51
+ }
52
+
53
+ @keyframes slide_out_to_top {
54
+ from { transform: translateY(0); }
55
+ to { transform: translateY(-100%); }
56
+ }
57
+
58
+ @keyframes slide_in_from_bottom {
59
+ from { transform: translateY(100%); }
60
+ to { transform: translateY(0); }
61
+ }
62
+
63
+ @keyframes slide_out_to_bottom {
64
+ from { transform: translateY(0); }
65
+ to { transform: translateY(100%); }
66
+ }
67
+
68
+ @keyframes slide_in_from_left {
69
+ from { transform: translateX(-100%); }
70
+ to { transform: translateX(0); }
71
+ }
72
+
73
+ @keyframes slide_out_to_left {
74
+ from { transform: translateX(0); }
75
+ to { transform: translateX(-100%); }
76
+ }
77
+
78
+ @keyframes slide_in_from_right {
79
+ from { transform: translateX(100%); }
80
+ to { transform: translateX(0); }
81
+ }
82
+
83
+ @keyframes slide_out_to_right {
84
+ from { transform: translateX(0); }
85
+ to { transform: translateX(100%); }
86
+ }
87
+
88
+ @keyframes skeleton-gradient {
89
+ 0% { background-color: rgba(165, 165, 165, 0.1); }
90
+ 50% { background-color: rgba(165, 165, 165, 0.2); }
91
+ 100% { background-color: rgba(165, 165, 165, 0.1); }
92
+ }
93
+
94
+ @keyframes accordion-down {
95
+ from { height: 0; }
96
+ to { height: var(--radix-accordion-content-height); }
97
+ }
98
+
99
+ @keyframes accordion-up {
100
+ from { height: var(--radix-accordion-content-height); }
101
+ to { height: 0; }
102
+ }
103
+
104
+ /* Animation Variables */
105
+ --animate-fade-in: fade-in 0.5s ease-in-out;
106
+ --animate-fade-out: fade-out 0.5s ease-in-out;
107
+ --animate-zoom-in: zoom-in 0.3s ease-in-out;
108
+ --animate-zoom-out: zoom-out 0.3s ease-in-out;
109
+ --animate-slide-in-from-top: slide_in_from_top 0.3s ease-in-out;
110
+ --animate-slide-out-to-top: slide_out_to_top 0.3s ease-in-out;
111
+ --animate-slide-in-from-bottom: slide_in_from_bottom 0.3s ease-in-out;
112
+ --animate-slide-out-to-bottom: slide_out_to_bottom 0.3s ease-in-out;
113
+ --animate-slide-in-from-left: slide_in_from_left 0.3s ease-in-out;
114
+ --animate-slide-out-to-left: slide_out_to_left 0.3s ease-in-out;
115
+ --animate-slide-in-from-right: slide_in_from_right 0.3s ease-in-out;
116
+ --animate-slide-out-to-right: slide_out_to_right 0.3s ease-in-out;
117
+ --animate-skeleton-gradient: skeleton-gradient 1.5s ease-in-out infinite;
118
+ --animate-accordion-down: accordion-down 0.2s ease-out;
119
+ --animate-accordion-up: accordion-up 0.2s ease-out;
120
+
121
+ /* --------------------------------- Shadow --------------------------------- */
122
+ --shadow-primary-small: 0 2px 4px var(--color-primary-o10);
123
+ --shadow-primary-medium: 0 4px 8px var(--color-primary-o20);
124
+ --shadow-primary-large: 0 6px 12px var(--color-primary-o30);
125
+ --shadow-secondary-small: 0 2px 4px var(--color-secondary-o10);
126
+ --shadow-secondary-medium: 0 4px 8px var(--color-secondary-o20);
127
+ --shadow-secondary-large: 0 6px 12px var(--color-secondary-o30);
128
+ --shadow-danger-small: 0 2px 4px var(--color-danger-o10);
129
+ --shadow-danger-medium: 0 4px 8px var(--color-red-o20);
130
+ --shadow-danger-large: 0 6px 12px var(--color-danger-o30);
131
+ --shadow-gray-small: 0 3px 12px var(--color-grayscale-s10);
132
+ --shadow-gray-medium: 0 4px 16px var(--color-grayscale-s30);
133
+ --shadow-gray-large: 0 4px 16px var(--color-grayscale-s40);
134
+ --shadow-success-small: 0 2px 4px var(--color-success-o10);
135
+ --shadow-success-medium: 0 4px 8px var(--color-success-o20);
136
+ --shadow-success-large: 0 6px 12px var(--color-success-o30);
137
+ --shadow-warning-small: 0 2px 4px var(--color-warning-o10);
138
+ --shadow-warning-medium: 0 4px 8px var(--color-warning-o20);
139
+ --shadow-warning-large: 0 6px 12px var(--color-warning-o30);
140
+ --shadow-info-small: 0 2px 4px var(--color-info-o10);
141
+ --shadow-info-medium: 0 4px 8px var(--color-info-o20);
142
+ --shadow-info-large: 0 6px 12px var(--color-info-o30);
143
+
144
+ /* --------------------------------- Radius --------------------------------- */
145
+ --radius-none: 0px;
146
+ --radius-xsmall: 4px;
147
+ --radius-small: 6px;
148
+ --radius-medium: 8px;
149
+ --radius-large: 12px;
150
+ --radius-xlarge: 18px;
151
+ --radius-full: 9999px;
152
+
153
+ /* --------------------------------- Sizing - Form ---------------------------------
154
+ * Form 내 input 류(TextField, TextArea, Select, MultiSelect, DatePicker, TimePicker, IconSelect) 의
155
+ * wrapper(FormControl) 가 기본으로 적용하는 max-width.
156
+ * 가독성 근거: Baymard line-length research 권장 580–720px upper bound,
157
+ * NN/g F-pattern 600px 권고. 720 이 optimal upper bound.
158
+ */
159
+ --max-w-form-control: 720px;
160
+ --max-w-form-control-narrow: 480px;
161
+ /* 폼 페이지 내용 폭(2026-10-26 22차): 폼 열 720 + 간격 24 + 검토 패널 408. FormPage 가 헤더 내용과 본문을 이 폭 안에 가운데 둔다 —
162
+ * 전폭 왼쪽 정렬에서는 긴 폼 옆 짧은 패널 아래가 "unused space" 로 감점됐고(21차 폼 진단, CSS 주입 4 변형 중 이것만 layout 3.5 → 4.0),
163
+ * 기준선 폼들이 쓰는 max-w-6xl(1152)과 같은 값 */
164
+ --max-w-page-content: 1152px;
165
+
166
+ /* ------------------------------- Typography ------------------------------ */
167
+ /* Font Family */
168
+ --font-sans:
169
+ 'Pretendard Variable',
170
+ Pretendard,
171
+ -apple-system,
172
+ BlinkMacSystemFont,
173
+ system-ui,
174
+ 'Segoe UI',
175
+ sans-serif;
176
+
177
+ --font-weight-regular: 400;
178
+ --font-weight-medium: 500;
179
+ --font-weight-semibold: 600;
180
+ --font-weight-bold: 700;
181
+ --font-weight-thin: 100;
182
+ --font-weight-extralight: 200;
183
+ --font-weight-light: 300;
184
+ --font-weight-extrabold: 800;
185
+ --font-weight-black: 900;
186
+
187
+ --text-h1: 48px;
188
+ --text-h1--line-height: 1;
189
+ --text-h1--font-weight: var(--font-weight-bold);
190
+ --text-h2: 32px;
191
+ --text-h2--line-height: 1.25;
192
+ --text-h2--font-weight: var(--font-weight-bold);
193
+ --text-h3: 24px;
194
+ --text-h3--line-height: 32px;
195
+ --text-h3--font-weight: var(--font-weight-bold);
196
+ --text-h4: 20px;
197
+ --text-h4--line-height: 1.2;
198
+ --text-h4--font-weight: var(--font-weight-bold);
199
+ --text-h5: 16px;
200
+ --text-h5--line-height: 1.5;
201
+ --text-h5--font-weight: var(--font-weight-bold);
202
+ --text-h6: 14px;
203
+ --text-h6--line-height: 24px;
204
+ --text-h6--font-weight: var(--font-weight-bold);
205
+ --text-base-semibold: 14px;
206
+ --text-base-semibold--line-height: 24px;
207
+ --text-base-semibold--font-weight: var(--font-weight-semibold);
208
+ --text-base-medium: 14px;
209
+ --text-base-medium--line-height: 24px;
210
+ --text-base-medium--font-weight: var(--font-weight-medium);
211
+ --text-base-regular: 14px;
212
+ --text-base-regular--line-height: 24px;
213
+ --text-base-regular--font-weight: var(--font-weight-regular);
214
+ --text-large-medium: 16px;
215
+ --text-large-medium--line-height: 24px;
216
+ --text-large-medium--font-weight: var(--font-weight-medium);
217
+ --text-large-semibold: 16px;
218
+ --text-large-semibold--line-height: 24px;
219
+ --text-large-semibold--font-weight: var(--font-weight-semibold);
220
+ --text-small-bold: 12px;
221
+ --text-small-bold--line-height: 16px;
222
+ --text-small-bold--font-weight: var(--font-weight-bold);
223
+ --text-small-medium: 12px;
224
+ --text-small-medium--line-height: 16px;
225
+ --text-small-medium--font-weight: var(--font-weight-medium);
226
+ --text-small-regular: 12px;
227
+ --text-small-regular--line-height: 16px;
228
+ --text-small-regular--font-weight: var(--font-weight-regular);
229
+ --text-small-bold-h: 12px;
230
+ --text-small-bold-h--line-height: 20px;
231
+ --text-small-bold-h--font-weight: var(--font-weight-bold);
232
+ --text-small-medium-h: 12px;
233
+ --text-small-medium-h--line-height: 20px;
234
+ --text-small-medium-h--font-weight: var(--font-weight-medium);
235
+ --text-small-regular-h: 12px;
236
+ --text-small-regular-h--line-height: 20px;
237
+ --text-small-regular-h--font-weight: var(--font-weight-regular);
238
+ --text-xsmall-bold: 10px;
239
+ --text-xsmall-bold--line-height: 1.6;
240
+ --text-xsmall-bold--font-weight: var(--font-weight-bold);
241
+ --text-xsmall-medium: 10px;
242
+ --text-xsmall-medium--line-height: 1.6;
243
+ --text-xsmall-medium--font-weight: var(--font-weight-medium);
244
+ --text-xsmall-regular: 10px;
245
+ --text-xsmall-regular--line-height: 1.6;
246
+ --text-xsmall-regular--font-weight: var(--font-weight-regular);
247
+
248
+ /* ---------------------------------- Color - Primitive --------------------------------- */
249
+ /* 10단계(light) — 2026-10-17 이슈 47 5차: 여섯 색을 OKLCH 같은 밝기·채도(L 0.93·C 0.045, yellow L 0.95·cyan L 0.94 — 40단계 글자 대비 4.5:1 이상)로 재조정. 원문 심판이 "채도 높은 초록·시안 뱃지" 를 반복 감점. 이전: blue #c7deff red #ffadad green #97ffcd yellow #ffe8ad cyan #adf5ff violet #e9ccff */
250
+ --color-blue10: #d5eaff;
251
+ --color-blue20: #70acff;
252
+ --color-blue30: #006aff;
253
+ --color-blue40: #0051c2;
254
+ --color-blue50: #00337a;
255
+ --color-blue-o10: rgba(112, 172, 255, 0.16);
256
+ --color-blue-o20: rgba(112, 172, 255, 0.33);
257
+ --color-blue-o30: rgba(112, 172, 255, 0.5);
258
+ --color-blue-o40: rgba(112, 172, 255, 0.67);
259
+ --color-blue-o50: rgba(112, 172, 255, 0.84);
260
+
261
+ --color-grayscale10: #ffffff;
262
+ --color-grayscale20: #eeeff2;
263
+ --color-grayscale30: #d6d9e0;
264
+ --color-grayscale40: #a8adbd;
265
+ --color-grayscale50: #7d849c;
266
+ --color-grayscale60: #636b82;
267
+ --color-grayscale70: #4d5365;
268
+ --color-grayscale80: #373b48;
269
+ --color-grayscale90: #21242b;
270
+ --color-grayscale-o10: rgba(197, 201, 211, 0.16);
271
+ --color-grayscale-o20: rgba(197, 201, 211, 0.33);
272
+ --color-grayscale-o30: rgba(197, 201, 211, 0.5);
273
+ --color-grayscale-o40: rgba(197, 201, 211, 0.67);
274
+ --color-grayscale-o50: rgba(197, 201, 211, 0.84);
275
+ --color-grayscale-s10: rgba(77, 83, 101, 0.1);
276
+ --color-grayscale-s20: rgba(77, 83, 101, 0.2);
277
+ --color-grayscale-s30: rgba(77, 83, 101, 0.3);
278
+ --color-grayscale-s40: rgba(77, 83, 101, 0.4);
279
+ --color-grayscale-s50: rgba(77, 83, 101, 0.5);
280
+
281
+ /* Secondary Shadow - grayscale-s alias */
282
+ --color-secondary-s10: var(--color-grayscale-s10);
283
+ --color-secondary-s20: var(--color-grayscale-s20);
284
+ --color-secondary-s30: var(--color-grayscale-s30);
285
+ --color-secondary-s40: var(--color-grayscale-s40);
286
+ --color-secondary-s50: var(--color-grayscale-s50);
287
+
288
+ --color-red10: #ffdddc;
289
+ --color-red20: #ff5757;
290
+ --color-red30: #cc0000;
291
+ --color-red40: #a30000;
292
+ --color-red50: #520000;
293
+ --color-red-o10: rgba(255, 87, 87, 0.16);
294
+ --color-red-o20: rgba(255, 87, 87, 0.33);
295
+ --color-red-o30: rgba(255, 87, 87, 0.5);
296
+ --color-red-o40: rgba(255, 87, 87, 0.67);
297
+ --color-red-o50: rgba(255, 87, 87, 0.84);
298
+
299
+ --color-green10: #cef2df;
300
+ --color-green20: #00dc72;
301
+ --color-green30: #008847;
302
+ --color-green40: #004d28;
303
+ --color-green50: #002e18;
304
+ --color-green-o10: rgba(0, 220, 114, 0.16);
305
+ --color-green-o20: rgba(0, 220, 114, 0.33);
306
+ --color-green-o30: rgba(0, 220, 114, 0.5);
307
+ --color-green-o40: rgba(0, 220, 114, 0.67);
308
+ --color-green-o50: rgba(0, 220, 114, 0.84);
309
+
310
+ --color-yellow10: #fbeecd;
311
+ --color-yellow20: #ffcf57;
312
+ --color-yellow30: #ffb700;
313
+ --color-yellow40: #8a6300;
314
+ --color-yellow50: #523b00;
315
+ --color-yellow-o10: rgba(255, 207, 87, 0.16);
316
+ --color-yellow-o20: rgba(255, 207, 87, 0.33);
317
+ --color-yellow-o30: rgba(255, 207, 87, 0.5);
318
+ --color-yellow-o40: rgba(255, 207, 87, 0.67);
319
+ --color-yellow-o50: rgba(255, 207, 87, 0.84);
320
+
321
+ --color-orange10: #ffd5ad;
322
+ --color-orange20: #ffa857;
323
+ --color-orange30: #ff7b00;
324
+ --color-orange40: #bd5b00;
325
+ --color-orange50: #522700;
326
+ --color-orange-o10: rgba(255, 168, 87, 0.16);
327
+ --color-orange-o20: rgba(255, 168, 87, 0.33);
328
+ --color-orange-o30: rgba(255, 168, 87, 0.5);
329
+ --color-orange-o40: rgba(255, 168, 87, 0.67);
330
+ --color-orange-o50: rgba(255, 168, 87, 0.84);
331
+
332
+ --color-cyan10: #c9f4fa;
333
+ --color-cyan20: #57ebff;
334
+ --color-cyan30: #00e1ff;
335
+ --color-cyan40: #007483;
336
+ --color-cyan50: #004852;
337
+ --color-cyan-o10: rgba(87, 235, 255, 0.16);
338
+ --color-cyan-o20: rgba(87, 235, 255, 0.33);
339
+ --color-cyan-o30: rgba(87, 235, 255, 0.5);
340
+ --color-cyan-o40: rgba(87, 235, 255, 0.67);
341
+ --color-cyan-o50: rgba(87, 235, 255, 0.84);
342
+
343
+ --color-violet10: #f1e0ff;
344
+ --color-violet20: #c57aff;
345
+ --color-violet30: #8f00ff;
346
+ --color-violet40: #5e00a8;
347
+ --color-violet50: #2e0052;
348
+ --color-violet-o10: rgba(197, 122, 255, 0.16);
349
+ --color-violet-o20: rgba(197, 122, 255, 0.33);
350
+ --color-violet-o30: rgba(197, 122, 255, 0.5);
351
+ --color-violet-o40: rgba(197, 122, 255, 0.67);
352
+ --color-violet-o50: rgba(197, 122, 255, 0.84);
353
+
354
+ /* -------------------------------- Color - Semantic -------------------------------- */
355
+ --color-primary10: var(--color-blue10);
356
+ --color-primary20: var(--color-blue20);
357
+ --color-primary30: var(--color-blue30);
358
+ --color-primary40: var(--color-blue40);
359
+ --color-primary50: var(--color-blue50);
360
+ --color-primary-o10: var(--color-blue-o10);
361
+ --color-primary-o20: var(--color-blue-o20);
362
+ --color-primary-o30: var(--color-blue-o30);
363
+ --color-primary-o40: var(--color-blue-o40);
364
+ --color-primary-o50: var(--color-blue-o50);
365
+
366
+ --color-secondary10: var(--color-grayscale10);
367
+ --color-secondary20: var(--color-grayscale20);
368
+ --color-secondary30: var(--color-grayscale30);
369
+ --color-secondary40: var(--color-grayscale40);
370
+ --color-secondary50: var(--color-grayscale50);
371
+ --color-secondary60: var(--color-grayscale60);
372
+ --color-secondary70: var(--color-grayscale70);
373
+ --color-secondary80: var(--color-grayscale80);
374
+ --color-secondary90: var(--color-grayscale90);
375
+ --color-secondary-o10: var(--color-grayscale-o10);
376
+ --color-secondary-o20: var(--color-grayscale-o20);
377
+ --color-secondary-o30: var(--color-grayscale-o30);
378
+ --color-secondary-o40: var(--color-grayscale-o40);
379
+ --color-secondary-o50: var(--color-grayscale-o50);
380
+
381
+ --color-danger10: var(--color-red10);
382
+ --color-danger20: var(--color-red20);
383
+ --color-danger30: var(--color-red30);
384
+ --color-danger40: var(--color-red40);
385
+ --color-danger50: var(--color-red50);
386
+ --color-danger-o10: var(--color-red-o10);
387
+ --color-danger-o20: var(--color-red-o20);
388
+ --color-danger-o30: var(--color-red-o30);
389
+ --color-danger-o40: var(--color-red-o40);
390
+ --color-danger-o50: var(--color-red-o50);
391
+
392
+ --color-success10: var(--color-green10);
393
+ --color-success20: var(--color-green20);
394
+ --color-success30: var(--color-green30);
395
+ --color-success40: var(--color-green40);
396
+ --color-success50: var(--color-green50);
397
+ --color-success-o10: var(--color-green-o10);
398
+ --color-success-o20: var(--color-green-o20);
399
+ --color-success-o30: var(--color-green-o30);
400
+ --color-success-o40: var(--color-green-o40);
401
+ --color-success-o50: var(--color-green-o50);
402
+
403
+ --color-warning10: var(--color-yellow10);
404
+ --color-warning20: var(--color-yellow20);
405
+ --color-warning30: var(--color-yellow30);
406
+ --color-warning40: var(--color-yellow40);
407
+ --color-warning50: var(--color-yellow50);
408
+ --color-warning-o10: var(--color-yellow-o10);
409
+ --color-warning-o20: var(--color-yellow-o20);
410
+ --color-warning-o30: var(--color-yellow-o30);
411
+ --color-warning-o40: var(--color-yellow-o40);
412
+ --color-warning-o50: var(--color-yellow-o50);
413
+
414
+ --color-critical10: var(--color-orange10);
415
+ --color-critical20: var(--color-orange20);
416
+ --color-critical30: var(--color-orange30);
417
+ --color-critical40: var(--color-orange40);
418
+ --color-critical50: var(--color-orange50);
419
+ --color-critical-o10: var(--color-orange-o10);
420
+ --color-critical-o20: var(--color-orange-o20);
421
+ --color-critical-o30: var(--color-orange-o30);
422
+ --color-critical-o40: var(--color-orange-o40);
423
+ --color-critical-o50: var(--color-orange-o50);
424
+
425
+ --color-info10: var(--color-cyan10);
426
+ --color-info20: var(--color-cyan20);
427
+ --color-info30: var(--color-cyan30);
428
+ --color-info40: var(--color-cyan40);
429
+ --color-info50: var(--color-cyan50);
430
+ --color-info-o10: var(--color-cyan-o10);
431
+ --color-info-o20: var(--color-cyan-o20);
432
+ --color-info-o30: var(--color-cyan-o30);
433
+ --color-info-o40: var(--color-cyan-o40);
434
+ --color-info-o50: var(--color-cyan-o50);
435
+
436
+ --color-etc10: var(--color-violet10);
437
+ --color-etc20: var(--color-violet20);
438
+ --color-etc30: var(--color-violet30);
439
+ --color-etc40: var(--color-violet40);
440
+ --color-etc50: var(--color-violet50);
441
+ --color-etc-o10: var(--color-violet-o10);
442
+ --color-etc-o20: var(--color-violet-o20);
443
+ --color-etc-o30: var(--color-violet-o30);
444
+ --color-etc-o40: var(--color-violet-o40);
445
+ --color-etc-o50: var(--color-violet-o50);
446
+
447
+ /* --------------------------------- Color - System --------------------------------- */
448
+ /* text */
449
+ --color-sys-text-main: var(--color-secondary80);
450
+ --color-sys-text-normal: var(--color-secondary80);
451
+ --color-sys-text-subtle: var(--color-secondary70);
452
+ --color-sys-text-subtler: var(--color-secondary60);
453
+ --color-sys-text-subtlest: var(--color-secondary40);
454
+ /* 비활성 글자 (2026-10-26 23차): 반투명 secondary-o50 은 흰 바탕에서 ≈1.6:1 — 라디오·체크박스 카드의 비활성 옵션 설명("왜 못 고르는지")이
455
+ * 안 읽혔다(홀드아웃 10 볼륨 생성 폼 3/3 "disabled options very faint"). secondary50(#7d849c, 3.72:1)로. WCAG 는 비활성을 예외로 두지만 읽혀야 하는 글자다 */
456
+ --color-sys-text-disabled: var(--color-secondary50);
457
+ /* placeholder·플로팅 라벨 텍스트. secondary50 은 흰 배경에서 3.7:1 로 WCAG AA 미달 → secondary60 (5.3:1). 다크는 이미 60 */
458
+ --color-sys-text-placeholder: var(--color-secondary60);
459
+
460
+ /* divider */
461
+ --color-sys-divider-main: var(--color-secondary40);
462
+ --color-sys-divider-subtle: var(--color-secondary30);
463
+ --color-sys-divider-subtler: var(--color-secondary20);
464
+
465
+ /* background */
466
+ --color-sys-background: var(--color-secondary10);
467
+ --color-sys-background-hover: var(--color-secondary20);
468
+ --color-sys-background-press: var(--color-secondary30);
469
+ --color-sys-background-subtle: var(--color-secondary10);
470
+ --color-sys-background-subtle-hover: var(--color-secondary20);
471
+ --color-sys-background-subtle-press: var(--color-secondary30);
472
+ /* PageHeader 바탕 — Figma 시안(node 9017:60912)의 위→아래 그라데이션(흰색 → rgb(245,249,255)), dl-ui-v3 와 같은 값. 배경 이미지로 쓴다(`bg-[image:…]`).
473
+ * 2026-10-30 사용자 결정으로 되돌림 — 2026-10-16~10-29 에는 평면 연한 파랑(이슈 47 평가 지적 대응)이었다. 헤더 아래 1px 구분선은 유지 */
474
+ --color-page-header-bg: linear-gradient(180deg, rgb(255, 255, 255) 0%, rgb(245, 249, 255) 100%);
475
+
476
+ /* foreground */
477
+ --color-sys-foreground: var(--color-secondary90);
478
+ --color-sys-foreground-hover: var(--color-secondary80);
479
+ --color-sys-foreground-press: var(--color-secondary70);
480
+ --color-sys-foreground-subtle: var(--color-secondary80);
481
+ --color-sys-foreground-subtle-hover: var(--color-secondary70);
482
+ --color-sys-foreground-subtle-press: var(--color-secondary60);
483
+
484
+ /* border */
485
+ --color-sys-border: var(--color-secondary30);
486
+ --color-sys-border-hover: var(--color-secondary40);
487
+ --color-sys-border-press: var(--color-secondary50);
488
+ --color-sys-border-subtle: var(--color-secondary20);
489
+ --color-sys-border-subtle-hover: var(--color-secondary30);
490
+ --color-sys-border-subtle-press: var(--color-secondary40);
491
+
492
+ /* focus ring */
493
+ --color-sys-focus-ring-main: var(--color-primary20);
494
+ --color-sys-focus-ring-bold: var(--color-primary30);
495
+
496
+ /* blanket */
497
+ --color-sys-blanket: var(--color-grayscale-s50);
498
+
499
+ /* scroll bar */
500
+ --color-sys-scroll-bar: var(--color-secondary-o40);
501
+
502
+ /* table */
503
+ /* 표 헤더 — 아주 연한 회색(o10): 띠가 아니라 행과 같은 면에 살짝 얹힌 정도, 경계는 1px 선이 맡는다 (2026-10-17 이슈 47 4차, 사용자 의견) */
504
+ --color-sys-table-header-background: var(--color-secondary-o10);
505
+ --color-sys-table-header-text: var(--color-secondary70);
506
+ --color-sys-table-align-button-disabled: var(--color-secondary30);
507
+ --color-sys-table-hover: var(--color-grayscale-o10);
508
+ --color-sys-table-press: var(--color-secondary-o20);
509
+ --color-sys-table-select: var(--color-primary-o10);
510
+ --color-sys-table-row-background: var(--color-secondary10);
511
+ --color-sys-table-row-background-hover: var(--color-secondary20);
512
+ --color-sys-table-row-focused-row: var(--color-secondary30);
513
+ --color-sys-table-row-border: var(--color-secondary20);
514
+
515
+ /* GNB */
516
+ --color-sys-gnb-text: var(--color-sys-text-main);
517
+ --color-sys-gnb-selected-text: var(--color-grayscale10);
518
+ --color-sys-gnb-selected-background-start: var(--color-primary30);
519
+ --color-sys-gnb-selected-background-end: var(--color-primary10);
520
+
521
+ /* badge */
522
+ --color-sys-badge-primary-text: var(--color-primary40);
523
+ --color-sys-badge-primary-background: var(--color-primary10);
524
+ --color-sys-badge-secondary-text: var(--color-sys-text-main);
525
+ --color-sys-badge-secondary-background: var(--color-secondary30);
526
+ --color-sys-badge-danger-text: var(--color-danger40);
527
+ --color-sys-badge-danger-background: var(--color-danger10);
528
+ --color-sys-badge-warning-text: var(--color-warning40);
529
+ --color-sys-badge-warning-background: var(--color-warning10);
530
+ --color-sys-badge-info-text: var(--color-info40);
531
+ --color-sys-badge-info-background: var(--color-info10);
532
+ --color-sys-badge-success-text: var(--color-success40);
533
+ --color-sys-badge-success-background: var(--color-success10);
534
+ --color-sys-badge-etc-text: var(--color-etc40);
535
+ --color-sys-badge-etc-background: var(--color-etc10);
536
+
537
+ /* alert */
538
+ --color-sys-alert-primary-text: var(--color-primary50);
539
+ --color-sys-alert-primary-background: var(--color-primary-o10);
540
+ --color-sys-alert-primary-icon: var(--color-primary40);
541
+ --color-sys-alert-info-text: var(--color-info50);
542
+ --color-sys-alert-info-background: var(--color-info-o10);
543
+ --color-sys-alert-info-icon: var(--color-info40);
544
+ --color-sys-alert-success-text: var(--color-success50);
545
+ --color-sys-alert-success-background: var(--color-success-o10);
546
+ --color-sys-alert-success-icon: var(--color-success40);
547
+ --color-sys-alert-warning-text: var(--color-critical50);
548
+ --color-sys-alert-warning-background: var(--color-warning-o10);
549
+ --color-sys-alert-warning-icon: var(--color-warning40);
550
+ --color-sys-alert-danger-text: var(--color-danger50);
551
+ --color-sys-alert-danger-background: var(--color-danger-o10);
552
+ --color-sys-alert-danger-icon: var(--color-danger40);
553
+
554
+ /* button - bold */
555
+ --color-sys-button-primary-text: var(--color-sys-background);
556
+ --color-sys-button-primary-background: var(--color-primary30);
557
+ --color-sys-button-primary-background-hover: var(--color-primary40);
558
+ --color-sys-button-primary-background-press: var(--color-primary50);
559
+ --color-sys-button-primary-border: var(--color-primary30);
560
+ --color-sys-button-primary-border-hover: var(--color-primary40);
561
+ --color-sys-button-primary-border-press: var(--color-primary50);
562
+ --color-sys-button-secondary-text: var(--color-sys-background);
563
+ --color-sys-button-secondary-background: var(--color-secondary60);
564
+ --color-sys-button-secondary-background-hover: var(--color-secondary70);
565
+ --color-sys-button-secondary-background-press: var(--color-secondary80);
566
+ --color-sys-button-secondary-border: var(--color-secondary60);
567
+ --color-sys-button-secondary-border-hover: var(--color-secondary70);
568
+ --color-sys-button-secondary-border-press: var(--color-secondary80);
569
+ --color-sys-button-danger-text: var(--color-sys-background);
570
+ --color-sys-button-danger-background: var(--color-danger30);
571
+ --color-sys-button-danger-background-hover: var(--color-danger40);
572
+ --color-sys-button-danger-background-press: var(--color-danger50);
573
+ --color-sys-button-danger-border: var(--color-danger30);
574
+ --color-sys-button-warning-text: var(--color-sys-text-main);
575
+ --color-sys-button-warning-background: var(--color-warning20);
576
+ --color-sys-button-warning-background-hover: var(--color-warning30);
577
+ --color-sys-button-warning-background-press: var(--color-warning40);
578
+
579
+ /* button - link */
580
+ --color-sys-button-primary-link-text: var(--color-primary30);
581
+ --color-sys-button-primary-link-text-hover: var(--color-primary40);
582
+ --color-sys-button-primary-link-text-press: var(--color-primary50);
583
+ --color-sys-button-secondary-link-text: var(--color-secondary60);
584
+ --color-sys-button-secondary-link-text-hover: var(--color-secondary70);
585
+ --color-sys-button-secondary-link-text-press: var(--color-secondary80);
586
+ --color-sys-button-danger-link-text: var(--color-danger30);
587
+ --color-sys-button-danger-link-text-hover: var(--color-danger40);
588
+ --color-sys-button-danger-link-text-press: var(--color-danger50);
589
+ --color-sys-button-warning-link-text: var(--color-warning40);
590
+ --color-sys-button-warning-link-text-hover: var(--color-warning50);
591
+ --color-sys-button-warning-link-text-press: var(--color-sys-text-main);
592
+
593
+ /* button - subtle */
594
+ --color-sys-button-primary-subtle-text: var(--color-primary40);
595
+ --color-sys-button-primary-subtle-background: var(--color-primary-o10);
596
+ --color-sys-button-primary-subtle-background-hover: var(--color-primary-o20);
597
+ --color-sys-button-primary-subtle-background-press: var(--color-primary-o30);
598
+ --color-sys-button-secondary-subtle-text: var(--color-sys-text-main);
599
+ --color-sys-button-secondary-subtle-background: var(--color-secondary-o10);
600
+ --color-sys-button-secondary-subtle-background-hover: var(--color-secondary-o20);
601
+ --color-sys-button-secondary-subtle-background-press: var(--color-secondary-o30);
602
+ --color-sys-button-danger-subtle-text: var(--color-danger30);
603
+ --color-sys-button-danger-subtle-background: var(--color-danger-o10);
604
+ --color-sys-button-danger-subtle-background-hover: var(--color-danger-o20);
605
+ --color-sys-button-danger-subtle-background-press: var(--color-danger-o30);
606
+ --color-sys-button-warning-subtle-text: var(--color-warning40);
607
+ --color-sys-button-warning-subtle-background: var(--color-warning-o10);
608
+ --color-sys-button-warning-subtle-background-hover: var(--color-warning-o20);
609
+ --color-sys-button-warning-subtle-background-press: var(--color-warning-o30);
610
+
611
+ /* button - outline */
612
+ --color-sys-button-primary-outline-text: var(--color-primary40);
613
+ --color-sys-button-primary-outline-border: var(--color-primary20);
614
+ --color-sys-button-primary-outline-background-hover: var(--color-primary-o10);
615
+ --color-sys-button-primary-outline-background-press: var(--color-primary-o20);
616
+ --color-sys-button-secondary-outline-text: var(--color-sys-text-main);
617
+ --color-sys-button-secondary-outline-border: var(--color-secondary30);
618
+ --color-sys-button-secondary-outline-background-hover: var(--color-secondary-o10);
619
+ --color-sys-button-secondary-outline-background-press: var(--color-secondary-o20);
620
+ --color-sys-button-danger-outline-text: var(--color-danger30);
621
+ --color-sys-button-danger-outline-border: var(--color-danger20);
622
+ --color-sys-button-danger-outline-background-hover: var(--color-danger-o10);
623
+ --color-sys-button-danger-outline-background-press: var(--color-danger-o20);
624
+ --color-sys-button-warning-outline-text: var(--color-warning40);
625
+ --color-sys-button-warning-outline-border: var(--color-warning20);
626
+ --color-sys-button-warning-outline-background-hover: var(--color-warning-o10);
627
+ --color-sys-button-warning-outline-background-press: var(--color-warning-o20);
628
+
629
+ /* button - disabled */
630
+ --color-sys-button-disabled-text: var(--color-secondary60); /* 2026-10-12: o40 은 흰 바탕 대비 1.4:1 로 버튼이 있는지도 안 보였다 → sys-text-subtler 와 같은 값 */
631
+ --color-sys-button-disabled-background: var(--color-grayscale-o10);
632
+ --color-sys-button-disabled-outline: var(--color-secondary-o30);
633
+ }
634
+
635
+ /* Overlay z-index: popover, dialog, drawer 등 overlay 컴포넌트의 기본 z-index */
636
+ :root {
637
+ --root-z-index: 1001;
638
+ }
639
+
640
+ /* dark: prefix를 [data-theme='dark']와 연결 */
641
+ @variant dark ([data-theme='dark'] &);
642
+
643
+ /* ============================================================================
644
+ Dark Mode
645
+ ============================================================================ */
646
+ [data-theme='dark'] {
647
+ /* -------------------------------- Base Colors (반전) -------------------------------- */
648
+ /* Secondary (Grayscale) - 반전 */
649
+ --color-secondary10: #21242b;
650
+ --color-secondary20: #373b48;
651
+ --color-secondary30: #4d5365;
652
+ --color-secondary40: #636b82;
653
+ --color-secondary50: #7d849c;
654
+ --color-secondary60: #a8adbd;
655
+ --color-secondary70: #d6d9e0;
656
+ --color-secondary80: #eeeff2;
657
+ --color-secondary90: #ffffff;
658
+
659
+ /* -------------------------------- Primitive Colors (Dark Mode) -------------------------------- */
660
+ /* Blue - Dark Mode 값 */
661
+ --color-blue10: #d1e2fa;
662
+ --color-blue20: #9ec2f5;
663
+ --color-blue30: #75a8f0;
664
+ --color-blue40: #307de9;
665
+ --color-blue50: #0f428a;
666
+ --color-blue-o10: rgba(48, 125, 233, 0.16);
667
+ --color-blue-o20: rgba(48, 125, 233, 0.33);
668
+ --color-blue-o30: rgba(48, 125, 233, 0.5);
669
+ --color-blue-o40: rgba(48, 125, 233, 0.67);
670
+ --color-blue-o50: rgba(48, 125, 233, 0.84);
671
+
672
+ /* Red - Dark Mode 값 */
673
+ --color-red10: #fbdada;
674
+ --color-red20: #f5a3a3;
675
+ --color-red30: #ff8080;
676
+ --color-red40: #b71515;
677
+ --color-red50: #5c0a0a;
678
+ --color-red-o10: rgba(183, 21, 21, 0.16);
679
+ --color-red-o20: rgba(183, 21, 21, 0.33);
680
+ --color-red-o30: rgba(183, 21, 21, 0.5);
681
+ --color-red-o40: rgba(183, 21, 21, 0.67);
682
+ --color-red-o50: rgba(183, 21, 21, 0.84);
683
+
684
+ /* Green - Dark Mode 값 */
685
+ --color-green10: #d6f5e6;
686
+ --color-green20: #a1e8c6;
687
+ --color-green30: #4bd291;
688
+ --color-green40: #289f66;
689
+ --color-green50: #145234;
690
+ --color-green-o10: rgba(40, 159, 102, 0.16);
691
+ --color-green-o20: rgba(40, 159, 102, 0.33);
692
+ --color-green-o30: rgba(40, 159, 102, 0.5);
693
+ --color-green-o40: rgba(40, 159, 102, 0.67);
694
+ --color-green-o50: rgba(40, 159, 102, 0.84);
695
+
696
+ /* Yellow - Dark Mode 값 */
697
+ --color-yellow10: #fcf1cf;
698
+ --color-yellow20: #f9e19a;
699
+ --color-yellow30: #f4cd56;
700
+ --color-yellow40: #f0b80f;
701
+ --color-yellow50: #785c08;
702
+ --color-yellow-o10: rgba(240, 184, 15, 0.16);
703
+ --color-yellow-o20: rgba(240, 184, 15, 0.33);
704
+ --color-yellow-o30: rgba(240, 184, 15, 0.5);
705
+ --color-yellow-o40: rgba(240, 184, 15, 0.67);
706
+ --color-yellow-o50: rgba(240, 184, 15, 0.84);
707
+
708
+ /* Orange - Dark Mode 값 */
709
+ --color-orange10: #f9e5d2;
710
+ --color-orange20: #f1c398;
711
+ --color-orange30: #e6964b;
712
+ --color-orange40: #b36419;
713
+ --color-orange50: #5a320c;
714
+ --color-orange-o10: rgba(179, 100, 25, 0.16);
715
+ --color-orange-o20: rgba(179, 100, 25, 0.33);
716
+ --color-orange-o30: rgba(179, 100, 25, 0.5);
717
+ --color-orange-o40: rgba(179, 100, 25, 0.67);
718
+ --color-orange-o50: rgba(179, 100, 25, 0.84);
719
+
720
+ /* Cyan - Dark Mode 값 */
721
+ --color-cyan10: #bbebf1;
722
+ --color-cyan20: #73d5e2;
723
+ --color-cyan30: #2bbfd4;
724
+ --color-cyan40: #1d7e8c;
725
+ --color-cyan50: #0e3d44;
726
+ --color-cyan-o10: rgba(29, 126, 140, 0.16);
727
+ --color-cyan-o20: rgba(29, 126, 140, 0.33);
728
+ --color-cyan-o30: rgba(29, 126, 140, 0.5);
729
+ --color-cyan-o40: rgba(29, 126, 140, 0.67);
730
+ --color-cyan-o50: rgba(29, 126, 140, 0.84);
731
+
732
+ /* Violet - Dark Mode 값 */
733
+ --color-violet10: #e8daf6;
734
+ --color-violet20: #c9a9ea;
735
+ --color-violet30: #b16ff4;
736
+ --color-violet40: #8c46d2;
737
+ --color-violet50: #4c1e7b;
738
+ --color-violet-o10: rgba(140, 70, 210, 0.16);
739
+ --color-violet-o20: rgba(140, 70, 210, 0.33);
740
+ --color-violet-o30: rgba(140, 70, 210, 0.5);
741
+ --color-violet-o40: rgba(140, 70, 210, 0.67);
742
+ --color-violet-o50: rgba(140, 70, 210, 0.84);
743
+
744
+ /* -------------------------------- Semantic Colors (Dark Mode) -------------------------------- */
745
+ /* Primary = Blue (반전: 10↔50, 20↔40) */
746
+ --color-primary10: var(--color-blue50);
747
+ --color-primary20: var(--color-blue40);
748
+ --color-primary30: var(--color-blue30);
749
+ --color-primary40: var(--color-blue20);
750
+ --color-primary50: var(--color-blue10);
751
+ --color-primary-o10: var(--color-blue-o10);
752
+ --color-primary-o20: var(--color-blue-o20);
753
+ --color-primary-o30: var(--color-blue-o30);
754
+ --color-primary-o40: var(--color-blue-o40);
755
+ --color-primary-o50: var(--color-blue-o50);
756
+
757
+ /* Danger = Red (반전) */
758
+ --color-danger10: var(--color-red50);
759
+ --color-danger20: var(--color-red40);
760
+ --color-danger30: var(--color-red30);
761
+ --color-danger40: var(--color-red20);
762
+ --color-danger50: var(--color-red10);
763
+ --color-danger-o10: var(--color-red-o10);
764
+ --color-danger-o20: var(--color-red-o20);
765
+ --color-danger-o30: var(--color-red-o30);
766
+ --color-danger-o40: var(--color-red-o40);
767
+ --color-danger-o50: var(--color-red-o50);
768
+
769
+ /* Success = Green (반전) */
770
+ --color-success10: var(--color-green50);
771
+ --color-success20: var(--color-green40);
772
+ --color-success30: var(--color-green30);
773
+ --color-success40: var(--color-green20);
774
+ --color-success50: var(--color-green10);
775
+ --color-success-o10: var(--color-green-o10);
776
+ --color-success-o20: var(--color-green-o20);
777
+ --color-success-o30: var(--color-green-o30);
778
+ --color-success-o40: var(--color-green-o40);
779
+ --color-success-o50: var(--color-green-o50);
780
+
781
+ /* Warning = Yellow (반전) */
782
+ --color-warning10: var(--color-yellow50);
783
+ --color-warning20: var(--color-yellow40);
784
+ --color-warning30: var(--color-yellow30);
785
+ --color-warning40: var(--color-yellow20);
786
+ --color-warning50: var(--color-yellow10);
787
+ --color-warning-o10: var(--color-yellow-o10);
788
+ --color-warning-o20: var(--color-yellow-o20);
789
+ --color-warning-o30: var(--color-yellow-o30);
790
+ --color-warning-o40: var(--color-yellow-o40);
791
+ --color-warning-o50: var(--color-yellow-o50);
792
+
793
+ /* Critical = Orange (반전) */
794
+ --color-critical10: var(--color-orange50);
795
+ --color-critical20: var(--color-orange40);
796
+ --color-critical30: var(--color-orange30);
797
+ --color-critical40: var(--color-orange20);
798
+ --color-critical50: var(--color-orange10);
799
+ --color-critical-o10: var(--color-orange-o10);
800
+ --color-critical-o20: var(--color-orange-o20);
801
+ --color-critical-o30: var(--color-orange-o30);
802
+ --color-critical-o40: var(--color-orange-o40);
803
+ --color-critical-o50: var(--color-orange-o50);
804
+
805
+ /* Info = Cyan (반전) */
806
+ --color-info10: var(--color-cyan50);
807
+ --color-info20: var(--color-cyan40);
808
+ --color-info30: var(--color-cyan30);
809
+ --color-info40: var(--color-cyan20);
810
+ --color-info50: var(--color-cyan10);
811
+ --color-info-o10: var(--color-cyan-o10);
812
+ --color-info-o20: var(--color-cyan-o20);
813
+ --color-info-o30: var(--color-cyan-o30);
814
+ --color-info-o40: var(--color-cyan-o40);
815
+ --color-info-o50: var(--color-cyan-o50);
816
+
817
+ /* Etc = Violet (반전) */
818
+ --color-etc10: var(--color-violet50);
819
+ --color-etc20: var(--color-violet40);
820
+ --color-etc30: var(--color-violet30);
821
+ --color-etc40: var(--color-violet20);
822
+ --color-etc50: var(--color-violet10);
823
+ --color-etc-o10: var(--color-violet-o10);
824
+ --color-etc-o20: var(--color-violet-o20);
825
+ --color-etc-o30: var(--color-violet-o30);
826
+ --color-etc-o40: var(--color-violet-o40);
827
+ --color-etc-o50: var(--color-violet-o50);
828
+
829
+ /* Shadow용 색상 - 검정 기반 (Figma Dark Grayscale.S) */
830
+ --color-grayscale-s10: rgba(0, 0, 0, 0.1);
831
+ --color-grayscale-s20: rgba(0, 0, 0, 0.2);
832
+ --color-grayscale-s30: rgba(0, 0, 0, 0.3);
833
+ --color-grayscale-s40: rgba(0, 0, 0, 0.4);
834
+ --color-grayscale-s50: rgba(0, 0, 0, 0.5);
835
+
836
+ /* Overlay용 색상 (Figma Dark Grayscale.O) */
837
+ --color-grayscale-o10: rgba(139, 146, 167, 0.16);
838
+ --color-grayscale-o20: rgba(139, 146, 167, 0.33);
839
+ --color-grayscale-o30: rgba(139, 146, 167, 0.5);
840
+ --color-grayscale-o40: rgba(139, 146, 167, 0.67);
841
+ --color-grayscale-o50: rgba(139, 146, 167, 0.84);
842
+
843
+ /* Secondary Overlay - grayscale과 동일하게 설정 */
844
+ --color-secondary-o10: rgba(139, 146, 167, 0.16);
845
+ --color-secondary-o20: rgba(139, 146, 167, 0.33);
846
+ --color-secondary-o30: rgba(139, 146, 167, 0.5);
847
+ --color-secondary-o40: rgba(139, 146, 167, 0.67);
848
+ --color-secondary-o50: rgba(139, 146, 167, 0.84);
849
+
850
+ /* Secondary Shadow - grayscale-s와 동일 */
851
+ --color-secondary-s10: var(--color-grayscale-s10);
852
+ --color-secondary-s20: var(--color-grayscale-s20);
853
+ --color-secondary-s30: var(--color-grayscale-s30);
854
+ --color-secondary-s40: var(--color-grayscale-s40);
855
+ --color-secondary-s50: var(--color-grayscale-s50);
856
+
857
+ /* -------------------------------- System Colors -------------------------------- */
858
+ /* text */
859
+ --color-sys-text-main: var(--color-secondary80);
860
+ --color-sys-text-normal: var(--color-secondary80);
861
+ --color-sys-text-subtle: var(--color-secondary70);
862
+ --color-sys-text-subtler: var(--color-secondary60);
863
+ --color-sys-text-subtlest: var(--color-secondary40);
864
+ --color-sys-text-disabled: var(--color-secondary50); /* 라이트와 같은 단계(23차) — 어두운 바탕에서 #7d849c 약 4:1 */
865
+ --color-sys-text-placeholder: var(--color-secondary60);
866
+
867
+ /* divider */
868
+ --color-sys-divider-main: var(--color-secondary40);
869
+ --color-sys-divider-subtle: var(--color-secondary30);
870
+ --color-sys-divider-subtler: var(--color-secondary30);
871
+
872
+ /* background */
873
+ --color-sys-background: var(--color-secondary10);
874
+ --color-sys-background-hover: var(--color-secondary30);
875
+ --color-sys-background-press: var(--color-secondary40);
876
+ --color-sys-background-subtle: var(--color-secondary10);
877
+ --color-sys-background-subtle-hover: var(--color-secondary20);
878
+ --color-sys-background-subtle-press: var(--color-secondary30);
879
+ /* PageHeader 바탕(다크) — 시안 그라데이션, dl-ui-v3 와 같은 값(2026-10-30 되돌림) */
880
+ --color-page-header-bg: linear-gradient(180deg, rgb(33, 36, 43) 0%, rgb(34, 42, 56) 100%);
881
+
882
+ /* foreground */
883
+ --color-sys-foreground: var(--color-secondary90);
884
+ --color-sys-foreground-hover: var(--color-secondary80);
885
+ --color-sys-foreground-press: var(--color-secondary70);
886
+ --color-sys-foreground-subtle: var(--color-secondary80);
887
+ --color-sys-foreground-subtle-hover: var(--color-secondary70);
888
+ --color-sys-foreground-subtle-press: var(--color-secondary60);
889
+
890
+ /* border */
891
+ --color-sys-border: var(--color-secondary30);
892
+ --color-sys-border-hover: var(--color-secondary40);
893
+ --color-sys-border-press: var(--color-secondary50);
894
+ --color-sys-border-subtle: var(--color-secondary20);
895
+ --color-sys-border-subtle-hover: var(--color-secondary30);
896
+ --color-sys-border-subtle-press: var(--color-secondary40);
897
+
898
+ /* focus ring */
899
+ --color-sys-focus-ring-main: var(--color-primary20);
900
+ --color-sys-focus-ring-bold: var(--color-primary30);
901
+
902
+ /* blanket */
903
+ --color-sys-blanket: var(--color-grayscale-s50);
904
+
905
+ /* scroll bar */
906
+ --color-sys-scroll-bar: var(--color-secondary-o40);
907
+
908
+ /* table */
909
+ /* 표 헤더 — 아주 연한 회색(o10): 띠가 아니라 행과 같은 면에 살짝 얹힌 정도, 경계는 1px 선이 맡는다 (2026-10-17 이슈 47 4차, 사용자 의견) */
910
+ --color-sys-table-header-background: var(--color-secondary-o10);
911
+ --color-sys-table-header-text: var(--color-secondary80);
912
+ --color-sys-table-align-button-disabled: var(--color-secondary40);
913
+ --color-sys-table-hover: var(--color-secondary-o10);
914
+ --color-sys-table-press: var(--color-secondary-o20);
915
+ --color-sys-table-select: var(--color-primary-o10);
916
+ --color-sys-table-row-background: var(--color-secondary20);
917
+ --color-sys-table-row-background-hover: var(--color-secondary30);
918
+ --color-sys-table-row-focused-row: var(--color-secondary40);
919
+ --color-sys-table-row-border: var(--color-secondary30);
920
+
921
+ /* badge */
922
+ --color-sys-badge-primary-text: var(--color-primary40);
923
+ --color-sys-badge-primary-background: var(--color-primary10);
924
+ --color-sys-badge-secondary-text: var(--color-secondary80);
925
+ --color-sys-badge-secondary-background: var(--color-secondary30);
926
+ --color-sys-badge-danger-text: var(--color-danger40);
927
+ --color-sys-badge-danger-background: var(--color-danger10);
928
+ --color-sys-badge-warning-text: var(--color-warning40);
929
+ --color-sys-badge-warning-background: var(--color-warning10);
930
+ --color-sys-badge-info-text: var(--color-info40);
931
+ --color-sys-badge-info-background: var(--color-info10);
932
+ --color-sys-badge-success-text: var(--color-success40);
933
+ --color-sys-badge-success-background: var(--color-success10);
934
+ --color-sys-badge-etc-text: var(--color-etc40);
935
+ --color-sys-badge-etc-background: var(--color-etc10);
936
+
937
+ /* alert */
938
+ --color-sys-alert-primary-text: var(--color-primary50);
939
+ --color-sys-alert-primary-background: var(--color-primary-o10);
940
+ --color-sys-alert-primary-icon: var(--color-primary40);
941
+ --color-sys-alert-info-text: var(--color-info40);
942
+ --color-sys-alert-info-background: var(--color-info-o10);
943
+ --color-sys-alert-info-icon: var(--color-info40);
944
+ --color-sys-alert-success-text: var(--color-success40);
945
+ --color-sys-alert-success-background: var(--color-success-o10);
946
+ --color-sys-alert-success-icon: var(--color-success40);
947
+ --color-sys-alert-warning-text: var(--color-warning40);
948
+ --color-sys-alert-warning-background: var(--color-warning-o10);
949
+ --color-sys-alert-warning-icon: var(--color-warning40);
950
+ --color-sys-alert-danger-text: var(--color-danger40);
951
+ --color-sys-alert-danger-background: var(--color-danger-o10);
952
+ --color-sys-alert-danger-icon: var(--color-danger40);
953
+
954
+ /* button - bold */
955
+ --color-sys-button-primary-text: var(--color-sys-background);
956
+ --color-sys-button-primary-background: var(--color-primary30);
957
+ --color-sys-button-primary-background-hover: var(--color-primary40);
958
+ --color-sys-button-primary-background-press: var(--color-primary50);
959
+ --color-sys-button-primary-border: var(--color-primary30);
960
+ --color-sys-button-primary-border-hover: var(--color-primary40);
961
+ --color-sys-button-primary-border-press: var(--color-primary50);
962
+ --color-sys-button-secondary-text: var(--color-sys-background);
963
+ --color-sys-button-secondary-background: var(--color-secondary60);
964
+ --color-sys-button-secondary-background-hover: var(--color-secondary70);
965
+ --color-sys-button-secondary-background-press: var(--color-secondary80);
966
+ --color-sys-button-secondary-border: var(--color-secondary60);
967
+ --color-sys-button-secondary-border-hover: var(--color-secondary70);
968
+ --color-sys-button-secondary-border-press: var(--color-secondary80);
969
+ --color-sys-button-danger-text: var(--color-sys-background);
970
+ --color-sys-button-danger-background: var(--color-danger30);
971
+ --color-sys-button-danger-background-hover: var(--color-danger40);
972
+ --color-sys-button-danger-background-press: var(--color-danger50);
973
+ --color-sys-button-danger-border: var(--color-danger30);
974
+ --color-sys-button-warning-text: var(--color-sys-text-main);
975
+ --color-sys-button-warning-background: var(--color-warning20);
976
+ --color-sys-button-warning-background-hover: var(--color-warning30);
977
+ --color-sys-button-warning-background-press: var(--color-warning40);
978
+
979
+ /* button - link */
980
+ --color-sys-button-primary-link-text: var(--color-primary30);
981
+ --color-sys-button-primary-link-text-hover: var(--color-primary40);
982
+ --color-sys-button-primary-link-text-press: var(--color-primary50);
983
+ --color-sys-button-secondary-link-text: var(--color-secondary60);
984
+ --color-sys-button-secondary-link-text-hover: var(--color-secondary70);
985
+ --color-sys-button-secondary-link-text-press: var(--color-secondary80);
986
+ --color-sys-button-danger-link-text: var(--color-danger30);
987
+ --color-sys-button-danger-link-text-hover: var(--color-danger40);
988
+ --color-sys-button-danger-link-text-press: var(--color-danger50);
989
+ --color-sys-button-warning-link-text: var(--color-warning40);
990
+ --color-sys-button-warning-link-text-hover: var(--color-warning50);
991
+ --color-sys-button-warning-link-text-press: var(--color-sys-text-main);
992
+
993
+ /* button - subtle */
994
+ --color-sys-button-primary-subtle-text: var(--color-primary40);
995
+ --color-sys-button-primary-subtle-background: var(--color-primary-o10);
996
+ --color-sys-button-primary-subtle-background-hover: var(--color-primary-o20);
997
+ --color-sys-button-primary-subtle-background-press: var(--color-primary-o30);
998
+ --color-sys-button-secondary-subtle-text: var(--color-sys-text-main);
999
+ --color-sys-button-secondary-subtle-background: var(--color-secondary-o10);
1000
+ --color-sys-button-secondary-subtle-background-hover: var(--color-secondary-o20);
1001
+ --color-sys-button-secondary-subtle-background-press: var(--color-secondary-o30);
1002
+ --color-sys-button-danger-subtle-text: var(--color-danger40);
1003
+ --color-sys-button-danger-subtle-background: var(--color-danger-o10);
1004
+ --color-sys-button-danger-subtle-background-hover: var(--color-danger-o20);
1005
+ --color-sys-button-danger-subtle-background-press: var(--color-danger-o30);
1006
+ --color-sys-button-warning-subtle-text: var(--color-warning40);
1007
+ --color-sys-button-warning-subtle-background: var(--color-warning-o10);
1008
+ --color-sys-button-warning-subtle-background-hover: var(--color-warning-o20);
1009
+ --color-sys-button-warning-subtle-background-press: var(--color-warning-o30);
1010
+
1011
+ /* button - outline */
1012
+ --color-sys-button-primary-outline-text: var(--color-primary40);
1013
+ --color-sys-button-primary-outline-border: var(--color-primary20);
1014
+ --color-sys-button-primary-outline-background-hover: var(--color-primary-o10);
1015
+ --color-sys-button-primary-outline-background-press: var(--color-primary-o20);
1016
+ --color-sys-button-secondary-outline-text: var(--color-sys-text-main);
1017
+ --color-sys-button-secondary-outline-border: var(--color-secondary40);
1018
+ --color-sys-button-secondary-outline-background-hover: var(--color-secondary-o10);
1019
+ --color-sys-button-secondary-outline-background-press: var(--color-secondary-o20);
1020
+ --color-sys-button-danger-outline-text: var(--color-danger40);
1021
+ --color-sys-button-danger-outline-border: var(--color-danger20);
1022
+ --color-sys-button-danger-outline-background-hover: var(--color-danger-o10);
1023
+ --color-sys-button-danger-outline-background-press: var(--color-danger-o20);
1024
+ --color-sys-button-warning-outline-text: var(--color-warning40);
1025
+ --color-sys-button-warning-outline-border: var(--color-warning20);
1026
+ --color-sys-button-warning-outline-background-hover: var(--color-warning-o10);
1027
+ --color-sys-button-warning-outline-background-press: var(--color-warning-o20);
1028
+
1029
+ /* button - disabled */
1030
+ --color-sys-button-disabled-text: var(--color-secondary60); /* 2026-10-12: o40 은 흰 바탕 대비 1.4:1 로 버튼이 있는지도 안 보였다 → sys-text-subtler 와 같은 값 */
1031
+ --color-sys-button-disabled-background: var(--color-grayscale-o10);
1032
+ --color-sys-button-disabled-outline: var(--color-secondary-o30);
1033
+ }
1034
+ /* TDS Utility Classes */
1035
+ /* Tailwind v4가 @theme 블록의 커스텀 색상에 대한 유틸리티 클래스를 자동 생성하지 않아서 직접 정의 */
1036
+
1037
+ /* ============================================================================
1038
+ System Colors - Background
1039
+ ============================================================================ */
1040
+
1041
+ /* Background */
1042
+ @utility bg-sys-background { background-color: var(--color-sys-background); }
1043
+
1044
+ /* Button - Primary */
1045
+ @utility bg-sys-button-primary-background { background-color: var(--color-sys-button-primary-background); }
1046
+ @utility bg-sys-button-primary-background-hover { background-color: var(--color-sys-button-primary-background-hover); }
1047
+ @utility bg-sys-button-primary-background-press { background-color: var(--color-sys-button-primary-background-press); }
1048
+
1049
+ /* Button - Secondary */
1050
+ @utility bg-sys-button-secondary-background { background-color: var(--color-sys-button-secondary-background); }
1051
+ @utility bg-sys-button-secondary-background-hover { background-color: var(--color-sys-button-secondary-background-hover); }
1052
+ @utility bg-sys-button-secondary-background-press { background-color: var(--color-sys-button-secondary-background-press); }
1053
+
1054
+ /* Button - Danger */
1055
+ @utility bg-sys-button-danger-background { background-color: var(--color-sys-button-danger-background); }
1056
+ @utility bg-sys-button-danger-background-hover { background-color: var(--color-sys-button-danger-background-hover); }
1057
+ @utility bg-sys-button-danger-background-press { background-color: var(--color-sys-button-danger-background-press); }
1058
+
1059
+ /* Button - Warning */
1060
+ @utility bg-sys-button-warning-background { background-color: var(--color-sys-button-warning-background); }
1061
+ @utility bg-sys-button-warning-background-hover { background-color: var(--color-sys-button-warning-background-hover); }
1062
+ @utility bg-sys-button-warning-background-press { background-color: var(--color-sys-button-warning-background-press); }
1063
+
1064
+ /* Button - Disabled */
1065
+ @utility bg-sys-button-disabled-background { background-color: var(--color-sys-button-disabled-background); }
1066
+
1067
+ /* Button - Primary Subtle */
1068
+ @utility bg-sys-button-primary-subtle-background { background-color: var(--color-sys-button-primary-subtle-background); }
1069
+ @utility bg-sys-button-primary-subtle-background-hover { background-color: var(--color-sys-button-primary-subtle-background-hover); }
1070
+ @utility bg-sys-button-primary-subtle-background-press { background-color: var(--color-sys-button-primary-subtle-background-press); }
1071
+
1072
+ /* Button - Secondary Subtle */
1073
+ @utility bg-sys-button-secondary-subtle-background { background-color: var(--color-sys-button-secondary-subtle-background); }
1074
+ @utility bg-sys-button-secondary-subtle-background-hover { background-color: var(--color-sys-button-secondary-subtle-background-hover); }
1075
+ @utility bg-sys-button-secondary-subtle-background-press { background-color: var(--color-sys-button-secondary-subtle-background-press); }
1076
+
1077
+ /* Button - Danger Subtle */
1078
+ @utility bg-sys-button-danger-subtle-background { background-color: var(--color-sys-button-danger-subtle-background); }
1079
+ @utility bg-sys-button-danger-subtle-background-hover { background-color: var(--color-sys-button-danger-subtle-background-hover); }
1080
+ @utility bg-sys-button-danger-subtle-background-press { background-color: var(--color-sys-button-danger-subtle-background-press); }
1081
+
1082
+ /* Button - Warning Subtle */
1083
+ @utility bg-sys-button-warning-subtle-background { background-color: var(--color-sys-button-warning-subtle-background); }
1084
+ @utility bg-sys-button-warning-subtle-background-hover { background-color: var(--color-sys-button-warning-subtle-background-hover); }
1085
+ @utility bg-sys-button-warning-subtle-background-press { background-color: var(--color-sys-button-warning-subtle-background-press); }
1086
+
1087
+ /* Badge */
1088
+ @utility bg-sys-badge-primary-background { background-color: var(--color-sys-badge-primary-background); }
1089
+ @utility bg-sys-badge-secondary-background { background-color: var(--color-sys-badge-secondary-background); }
1090
+ @utility bg-sys-badge-danger-background { background-color: var(--color-sys-badge-danger-background); }
1091
+ @utility bg-sys-badge-warning-background { background-color: var(--color-sys-badge-warning-background); }
1092
+ @utility bg-sys-badge-info-background { background-color: var(--color-sys-badge-info-background); }
1093
+ @utility bg-sys-badge-success-background { background-color: var(--color-sys-badge-success-background); }
1094
+ @utility bg-sys-badge-etc-background { background-color: var(--color-sys-badge-etc-background); }
1095
+
1096
+ /* Alert */
1097
+ @utility bg-sys-alert-primary-background { background-color: var(--color-sys-alert-primary-background); }
1098
+ @utility bg-sys-alert-info-background { background-color: var(--color-sys-alert-info-background); }
1099
+ @utility bg-sys-alert-success-background { background-color: var(--color-sys-alert-success-background); }
1100
+ @utility bg-sys-alert-warning-background { background-color: var(--color-sys-alert-warning-background); }
1101
+ @utility bg-sys-alert-danger-background { background-color: var(--color-sys-alert-danger-background); }
1102
+
1103
+ /* Divider */
1104
+ @utility bg-sys-divider-main { background-color: var(--color-sys-divider-main); }
1105
+ @utility bg-sys-divider-subtle { background-color: var(--color-sys-divider-subtle); }
1106
+ @utility bg-sys-divider-subtler { background-color: var(--color-sys-divider-subtler); }
1107
+
1108
+ /* Table */
1109
+ @utility bg-sys-table-header-background { background-color: var(--color-sys-table-header-background); }
1110
+ @utility bg-sys-table-hover { background-color: var(--color-sys-table-hover); }
1111
+ @utility bg-sys-table-press { background-color: var(--color-sys-table-press); }
1112
+ @utility bg-sys-table-select { background-color: var(--color-sys-table-select); }
1113
+
1114
+ /* Blanket */
1115
+ @utility bg-sys-blanket { background-color: var(--color-sys-blanket); }
1116
+
1117
+ /* ============================================================================
1118
+ System Colors - Text
1119
+ ============================================================================ */
1120
+
1121
+ /* Text */
1122
+ @utility text-sys-text-main { color: var(--color-sys-text-main); }
1123
+ @utility text-sys-text-normal { color: var(--color-sys-text-normal); }
1124
+ @utility text-sys-text-subtle { color: var(--color-sys-text-subtle); }
1125
+ @utility text-sys-text-subtler { color: var(--color-sys-text-subtler); }
1126
+ @utility text-sys-text-subtlest { color: var(--color-sys-text-subtlest); }
1127
+ @utility text-sys-text-disabled { color: var(--color-sys-text-disabled); }
1128
+ @utility text-sys-text-placeholder { color: var(--color-sys-text-placeholder); }
1129
+
1130
+ /* Button Text - Primary */
1131
+ @utility text-sys-button-primary-text { color: var(--color-sys-button-primary-text); }
1132
+ @utility text-sys-button-primary-link-text { color: var(--color-sys-button-primary-link-text); }
1133
+ @utility text-sys-button-primary-link-text-hover { color: var(--color-sys-button-primary-link-text-hover); }
1134
+ @utility text-sys-button-primary-link-text-press { color: var(--color-sys-button-primary-link-text-press); }
1135
+ @utility text-sys-button-primary-subtle-text { color: var(--color-sys-button-primary-subtle-text); }
1136
+
1137
+ /* Button Text - Secondary */
1138
+ @utility text-sys-button-secondary-text { color: var(--color-sys-button-secondary-text); }
1139
+ @utility text-sys-button-secondary-link-text { color: var(--color-sys-button-secondary-link-text); }
1140
+ @utility text-sys-button-secondary-link-text-hover { color: var(--color-sys-button-secondary-link-text-hover); }
1141
+ @utility text-sys-button-secondary-link-text-press { color: var(--color-sys-button-secondary-link-text-press); }
1142
+ @utility text-sys-button-secondary-subtle-text { color: var(--color-sys-button-secondary-subtle-text); }
1143
+
1144
+ /* Button Text - Danger */
1145
+ @utility text-sys-button-danger-text { color: var(--color-sys-button-danger-text); }
1146
+ @utility text-sys-button-danger-link-text { color: var(--color-sys-button-danger-link-text); }
1147
+ @utility text-sys-button-danger-link-text-hover { color: var(--color-sys-button-danger-link-text-hover); }
1148
+ @utility text-sys-button-danger-link-text-press { color: var(--color-sys-button-danger-link-text-press); }
1149
+ @utility text-sys-button-danger-subtle-text { color: var(--color-sys-button-danger-subtle-text); }
1150
+
1151
+ /* Button Text - Warning */
1152
+ @utility text-sys-button-warning-text { color: var(--color-sys-button-warning-text); }
1153
+ @utility text-sys-button-warning-link-text { color: var(--color-sys-button-warning-link-text); }
1154
+ @utility text-sys-button-warning-link-text-hover { color: var(--color-sys-button-warning-link-text-hover); }
1155
+ @utility text-sys-button-warning-link-text-press { color: var(--color-sys-button-warning-link-text-press); }
1156
+ @utility text-sys-button-warning-subtle-text { color: var(--color-sys-button-warning-subtle-text); }
1157
+
1158
+ /* Button Text - Disabled */
1159
+ @utility text-sys-button-disabled-text { color: var(--color-sys-button-disabled-text); }
1160
+
1161
+ /* Badge Text */
1162
+ @utility text-sys-badge-primary-text { color: var(--color-sys-badge-primary-text); }
1163
+ @utility text-sys-badge-secondary-text { color: var(--color-sys-badge-secondary-text); }
1164
+ @utility text-sys-badge-danger-text { color: var(--color-sys-badge-danger-text); }
1165
+ @utility text-sys-badge-warning-text { color: var(--color-sys-badge-warning-text); }
1166
+ @utility text-sys-badge-info-text { color: var(--color-sys-badge-info-text); }
1167
+ @utility text-sys-badge-success-text { color: var(--color-sys-badge-success-text); }
1168
+ @utility text-sys-badge-etc-text { color: var(--color-sys-badge-etc-text); }
1169
+
1170
+ /* Alert Text & Icon */
1171
+ @utility text-sys-alert-primary-text { color: var(--color-sys-alert-primary-text); }
1172
+ @utility text-sys-alert-primary-icon { color: var(--color-sys-alert-primary-icon); }
1173
+ @utility text-sys-alert-info-text { color: var(--color-sys-alert-info-text); }
1174
+ @utility text-sys-alert-info-icon { color: var(--color-sys-alert-info-icon); }
1175
+ @utility text-sys-alert-success-text { color: var(--color-sys-alert-success-text); }
1176
+ @utility text-sys-alert-success-icon { color: var(--color-sys-alert-success-icon); }
1177
+ @utility text-sys-alert-warning-text { color: var(--color-sys-alert-warning-text); }
1178
+ @utility text-sys-alert-warning-icon { color: var(--color-sys-alert-warning-icon); }
1179
+ @utility text-sys-alert-danger-text { color: var(--color-sys-alert-danger-text); }
1180
+ @utility text-sys-alert-danger-icon { color: var(--color-sys-alert-danger-icon); }
1181
+
1182
+ /* Background as text */
1183
+ @utility text-sys-background { color: var(--color-sys-background); }
1184
+
1185
+ /* ============================================================================
1186
+ System Colors - Border
1187
+ ============================================================================ */
1188
+
1189
+ @utility border-sys-divider-main { border-color: var(--color-sys-divider-main); }
1190
+ @utility border-sys-divider-subtle { border-color: var(--color-sys-divider-subtle); }
1191
+ @utility border-sys-divider-subtler { border-color: var(--color-sys-divider-subtler); }
1192
+ @utility border-sys-focus-ring-main { border-color: var(--color-sys-focus-ring-main); }
1193
+ @utility border-sys-focus-ring-bold { border-color: var(--color-sys-focus-ring-bold); }
1194
+
1195
+ /* ============================================================================
1196
+ Semantic Colors - Background
1197
+ ============================================================================ */
1198
+
1199
+ /* Primary */
1200
+ @utility bg-primary { background-color: var(--color-primary30); }
1201
+ @utility bg-primary10 { background-color: var(--color-primary10); }
1202
+ @utility bg-primary20 { background-color: var(--color-primary20); }
1203
+ @utility bg-primary30 { background-color: var(--color-primary30); }
1204
+ @utility bg-primary40 { background-color: var(--color-primary40); }
1205
+ @utility bg-primary50 { background-color: var(--color-primary50); }
1206
+ @utility bg-primary-o10 { background-color: var(--color-primary-o10); }
1207
+ @utility bg-primary-o20 { background-color: var(--color-primary-o20); }
1208
+ @utility bg-primary-o30 { background-color: var(--color-primary-o30); }
1209
+
1210
+ /* Secondary */
1211
+ @utility bg-secondary { background-color: var(--color-secondary60); }
1212
+ @utility bg-secondary10 { background-color: var(--color-secondary10); }
1213
+ @utility bg-secondary20 { background-color: var(--color-secondary20); }
1214
+ @utility bg-secondary30 { background-color: var(--color-secondary30); }
1215
+ @utility bg-secondary40 { background-color: var(--color-secondary40); }
1216
+ @utility bg-secondary50 { background-color: var(--color-secondary50); }
1217
+ @utility bg-secondary60 { background-color: var(--color-secondary60); }
1218
+ @utility bg-secondary70 { background-color: var(--color-secondary70); }
1219
+ @utility bg-secondary80 { background-color: var(--color-secondary80); }
1220
+ @utility bg-secondary90 { background-color: var(--color-secondary90); }
1221
+ @utility bg-secondary-o10 { background-color: var(--color-secondary-o10); }
1222
+ @utility bg-secondary-o20 { background-color: var(--color-secondary-o20); }
1223
+ @utility bg-secondary-o30 { background-color: var(--color-secondary-o30); }
1224
+
1225
+ /* Grayscale Shadow (semi-transparent) */
1226
+ @utility bg-grayscale-s10 { background-color: var(--color-grayscale-s10); }
1227
+ @utility bg-grayscale-s20 { background-color: var(--color-grayscale-s20); }
1228
+ @utility bg-grayscale-s30 { background-color: var(--color-grayscale-s30); }
1229
+ @utility bg-grayscale-s40 { background-color: var(--color-grayscale-s40); }
1230
+ @utility bg-grayscale-s50 { background-color: var(--color-grayscale-s50); }
1231
+
1232
+ /* Sidebar blur background */
1233
+ @utility bg-sys-background-blur { background-color: color-mix(in srgb, var(--color-sys-background) 50%, transparent); }
1234
+ @utility bg-secondary-o10-blur { background-color: color-mix(in srgb, var(--color-sys-background) 50%, var(--color-secondary-o10)); }
1235
+
1236
+ /* Danger */
1237
+ @utility bg-danger10 { background-color: var(--color-danger10); }
1238
+ @utility bg-danger20 { background-color: var(--color-danger20); }
1239
+ @utility bg-danger30 { background-color: var(--color-danger30); }
1240
+ @utility bg-danger40 { background-color: var(--color-danger40); }
1241
+ @utility bg-danger50 { background-color: var(--color-danger50); }
1242
+ @utility bg-danger-o10 { background-color: var(--color-danger-o10); }
1243
+ @utility bg-danger-o20 { background-color: var(--color-danger-o20); }
1244
+ @utility bg-danger-o30 { background-color: var(--color-danger-o30); }
1245
+
1246
+ /* Success */
1247
+ @utility bg-success10 { background-color: var(--color-success10); }
1248
+ @utility bg-success20 { background-color: var(--color-success20); }
1249
+ @utility bg-success30 { background-color: var(--color-success30); }
1250
+ @utility bg-success40 { background-color: var(--color-success40); }
1251
+ @utility bg-success50 { background-color: var(--color-success50); }
1252
+ @utility bg-success-o10 { background-color: var(--color-success-o10); }
1253
+ @utility bg-success-o20 { background-color: var(--color-success-o20); }
1254
+ @utility bg-success-o30 { background-color: var(--color-success-o30); }
1255
+
1256
+ /* Warning */
1257
+ @utility bg-warning10 { background-color: var(--color-warning10); }
1258
+ @utility bg-warning20 { background-color: var(--color-warning20); }
1259
+ @utility bg-warning30 { background-color: var(--color-warning30); }
1260
+ @utility bg-warning40 { background-color: var(--color-warning40); }
1261
+ @utility bg-warning50 { background-color: var(--color-warning50); }
1262
+ @utility bg-warning-o10 { background-color: var(--color-warning-o10); }
1263
+ @utility bg-warning-o20 { background-color: var(--color-warning-o20); }
1264
+ @utility bg-warning-o30 { background-color: var(--color-warning-o30); }
1265
+
1266
+ /* Info */
1267
+ @utility bg-info10 { background-color: var(--color-info10); }
1268
+ @utility bg-info20 { background-color: var(--color-info20); }
1269
+ @utility bg-info30 { background-color: var(--color-info30); }
1270
+ @utility bg-info40 { background-color: var(--color-info40); }
1271
+ @utility bg-info50 { background-color: var(--color-info50); }
1272
+ @utility bg-info-o10 { background-color: var(--color-info-o10); }
1273
+ @utility bg-info-o20 { background-color: var(--color-info-o20); }
1274
+ @utility bg-info-o30 { background-color: var(--color-info-o30); }
1275
+
1276
+ /* Critical */
1277
+ @utility bg-critical10 { background-color: var(--color-critical10); }
1278
+ @utility bg-critical20 { background-color: var(--color-critical20); }
1279
+ @utility bg-critical30 { background-color: var(--color-critical30); }
1280
+ @utility bg-critical40 { background-color: var(--color-critical40); }
1281
+ @utility bg-critical50 { background-color: var(--color-critical50); }
1282
+ @utility bg-critical-o10 { background-color: var(--color-critical-o10); }
1283
+ @utility bg-critical-o20 { background-color: var(--color-critical-o20); }
1284
+ @utility bg-critical-o30 { background-color: var(--color-critical-o30); }
1285
+
1286
+ /* Etc */
1287
+ @utility bg-etc10 { background-color: var(--color-etc10); }
1288
+ @utility bg-etc20 { background-color: var(--color-etc20); }
1289
+ @utility bg-etc30 { background-color: var(--color-etc30); }
1290
+ @utility bg-etc40 { background-color: var(--color-etc40); }
1291
+ @utility bg-etc50 { background-color: var(--color-etc50); }
1292
+ @utility bg-etc-o10 { background-color: var(--color-etc-o10); }
1293
+ @utility bg-etc-o20 { background-color: var(--color-etc-o20); }
1294
+ @utility bg-etc-o30 { background-color: var(--color-etc-o30); }
1295
+
1296
+ /* ============================================================================
1297
+ Semantic Colors - Text
1298
+ ============================================================================ */
1299
+
1300
+ /* Primary */
1301
+ @utility text-primary10 { color: var(--color-primary10); }
1302
+ @utility text-primary20 { color: var(--color-primary20); }
1303
+ @utility text-primary30 { color: var(--color-primary30); }
1304
+ @utility text-primary40 { color: var(--color-primary40); }
1305
+ @utility text-primary50 { color: var(--color-primary50); }
1306
+
1307
+ /* Secondary */
1308
+ @utility text-secondary10 { color: var(--color-secondary10); }
1309
+ @utility text-secondary20 { color: var(--color-secondary20); }
1310
+ @utility text-secondary30 { color: var(--color-secondary30); }
1311
+ @utility text-secondary40 { color: var(--color-secondary40); }
1312
+ @utility text-secondary50 { color: var(--color-secondary50); }
1313
+ @utility text-secondary60 { color: var(--color-secondary60); }
1314
+ @utility text-secondary70 { color: var(--color-secondary70); }
1315
+ @utility text-secondary80 { color: var(--color-secondary80); }
1316
+ @utility text-secondary90 { color: var(--color-secondary90); }
1317
+
1318
+ /* Danger */
1319
+ @utility text-danger10 { color: var(--color-danger10); }
1320
+ @utility text-danger20 { color: var(--color-danger20); }
1321
+ @utility text-danger30 { color: var(--color-danger30); }
1322
+ @utility text-danger40 { color: var(--color-danger40); }
1323
+ @utility text-danger50 { color: var(--color-danger50); }
1324
+
1325
+ /* Success */
1326
+ @utility text-success10 { color: var(--color-success10); }
1327
+ @utility text-success20 { color: var(--color-success20); }
1328
+ @utility text-success30 { color: var(--color-success30); }
1329
+ @utility text-success40 { color: var(--color-success40); }
1330
+ @utility text-success50 { color: var(--color-success50); }
1331
+
1332
+ /* Warning */
1333
+ @utility text-warning10 { color: var(--color-warning10); }
1334
+ @utility text-warning20 { color: var(--color-warning20); }
1335
+ @utility text-warning30 { color: var(--color-warning30); }
1336
+ @utility text-warning40 { color: var(--color-warning40); }
1337
+ @utility text-warning50 { color: var(--color-warning50); }
1338
+
1339
+ /* Info */
1340
+ @utility text-info10 { color: var(--color-info10); }
1341
+ @utility text-info20 { color: var(--color-info20); }
1342
+ @utility text-info30 { color: var(--color-info30); }
1343
+ @utility text-info40 { color: var(--color-info40); }
1344
+ @utility text-info50 { color: var(--color-info50); }
1345
+
1346
+ /* Critical */
1347
+ @utility text-critical10 { color: var(--color-critical10); }
1348
+ @utility text-critical20 { color: var(--color-critical20); }
1349
+ @utility text-critical30 { color: var(--color-critical30); }
1350
+ @utility text-critical40 { color: var(--color-critical40); }
1351
+ @utility text-critical50 { color: var(--color-critical50); }
1352
+
1353
+ /* Etc */
1354
+ @utility text-etc10 { color: var(--color-etc10); }
1355
+ @utility text-etc20 { color: var(--color-etc20); }
1356
+ @utility text-etc30 { color: var(--color-etc30); }
1357
+ @utility text-etc40 { color: var(--color-etc40); }
1358
+ @utility text-etc50 { color: var(--color-etc50); }
1359
+
1360
+ /* ============================================================================
1361
+ Semantic Colors - Border
1362
+ ============================================================================ */
1363
+
1364
+ /* Primary */
1365
+ @utility border-primary10 { border-color: var(--color-primary10); }
1366
+ @utility border-primary20 { border-color: var(--color-primary20); }
1367
+ @utility border-primary30 { border-color: var(--color-primary30); }
1368
+ @utility border-primary40 { border-color: var(--color-primary40); }
1369
+ @utility border-primary50 { border-color: var(--color-primary50); }
1370
+ @utility border-primary-o10 { border-color: var(--color-primary-o10); }
1371
+ @utility border-primary-o20 { border-color: var(--color-primary-o20); }
1372
+ @utility border-primary-o30 { border-color: var(--color-primary-o30); }
1373
+ @utility border-primary-o40 { border-color: var(--color-primary-o40); }
1374
+ @utility border-primary-o50 { border-color: var(--color-primary-o50); }
1375
+
1376
+ /* Secondary */
1377
+ @utility border-secondary { border-color: var(--color-secondary30); }
1378
+ @utility border-secondary10 { border-color: var(--color-secondary10); }
1379
+ @utility border-secondary20 { border-color: var(--color-secondary20); }
1380
+ @utility border-secondary30 { border-color: var(--color-secondary30); }
1381
+ @utility border-secondary40 { border-color: var(--color-secondary40); }
1382
+ @utility border-secondary50 { border-color: var(--color-secondary50); }
1383
+ @utility border-secondary60 { border-color: var(--color-secondary60); }
1384
+ @utility border-secondary70 { border-color: var(--color-secondary70); }
1385
+ @utility border-secondary80 { border-color: var(--color-secondary80); }
1386
+ @utility border-secondary90 { border-color: var(--color-secondary90); }
1387
+
1388
+ /* Danger */
1389
+ @utility border-danger10 { border-color: var(--color-danger10); }
1390
+ @utility border-danger20 { border-color: var(--color-danger20); }
1391
+ @utility border-danger30 { border-color: var(--color-danger30); }
1392
+ @utility border-danger40 { border-color: var(--color-danger40); }
1393
+ @utility border-danger50 { border-color: var(--color-danger50); }
1394
+
1395
+ /* Success */
1396
+ @utility border-success10 { border-color: var(--color-success10); }
1397
+ @utility border-success20 { border-color: var(--color-success20); }
1398
+ @utility border-success30 { border-color: var(--color-success30); }
1399
+ @utility border-success40 { border-color: var(--color-success40); }
1400
+ @utility border-success50 { border-color: var(--color-success50); }
1401
+
1402
+ /* Warning */
1403
+ @utility border-warning10 { border-color: var(--color-warning10); }
1404
+ @utility border-warning20 { border-color: var(--color-warning20); }
1405
+ @utility border-warning30 { border-color: var(--color-warning30); }
1406
+ @utility border-warning40 { border-color: var(--color-warning40); }
1407
+ @utility border-warning50 { border-color: var(--color-warning50); }
1408
+
1409
+ /* Info */
1410
+ @utility border-info10 { border-color: var(--color-info10); }
1411
+ @utility border-info20 { border-color: var(--color-info20); }
1412
+ @utility border-info30 { border-color: var(--color-info30); }
1413
+ @utility border-info40 { border-color: var(--color-info40); }
1414
+ @utility border-info50 { border-color: var(--color-info50); }
1415
+
1416
+ /* ============================================================================
1417
+ Ring Colors (Focus)
1418
+ ============================================================================ */
1419
+
1420
+ @utility ring-sys-focus-ring-main { --tw-ring-color: var(--color-sys-focus-ring-main); }
1421
+ @utility ring-sys-focus-ring-bold { --tw-ring-color: var(--color-sys-focus-ring-bold); }
1422
+ @utility ring-primary20 { --tw-ring-color: var(--color-primary20); }
1423
+ @utility ring-primary30 { --tw-ring-color: var(--color-primary30); }
1424
+
1425
+ /* ============================================================================
1426
+ Typography
1427
+ ============================================================================ */
1428
+
1429
+ @utility text-h1 { font-size: var(--text-h1); line-height: var(--text-h1--line-height); font-weight: var(--text-h1--font-weight); }
1430
+ @utility text-h2 { font-size: var(--text-h2); line-height: var(--text-h2--line-height); font-weight: var(--text-h2--font-weight); }
1431
+ @utility text-h3 { font-size: var(--text-h3); line-height: var(--text-h3--line-height); font-weight: var(--text-h3--font-weight); }
1432
+ @utility text-h4 { font-size: var(--text-h4); line-height: var(--text-h4--line-height); font-weight: var(--text-h4--font-weight); }
1433
+ @utility text-h5 { font-size: var(--text-h5); line-height: var(--text-h5--line-height); font-weight: var(--text-h5--font-weight); }
1434
+ @utility text-h6 { font-size: var(--text-h6); line-height: var(--text-h6--line-height); font-weight: var(--text-h6--font-weight); }
1435
+ @utility text-base-semibold { font-size: var(--text-base-semibold); line-height: var(--text-base-semibold--line-height); font-weight: var(--text-base-semibold--font-weight); }
1436
+ @utility text-base-medium { font-size: var(--text-base-medium); line-height: var(--text-base-medium--line-height); font-weight: var(--text-base-medium--font-weight); }
1437
+ @utility text-base-regular { font-size: var(--text-base-regular); line-height: var(--text-base-regular--line-height); font-weight: var(--text-base-regular--font-weight); }
1438
+ @utility text-large-medium { font-size: var(--text-large-medium); line-height: var(--text-large-medium--line-height); font-weight: var(--text-large-medium--font-weight); }
1439
+ @utility text-large-semibold { font-size: var(--text-large-semibold); line-height: var(--text-large-semibold--line-height); font-weight: var(--text-large-semibold--font-weight); }
1440
+ @utility text-small-bold { font-size: var(--text-small-bold); line-height: var(--text-small-bold--line-height); font-weight: var(--text-small-bold--font-weight); }
1441
+ @utility text-small-medium { font-size: var(--text-small-medium); line-height: var(--text-small-medium--line-height); font-weight: var(--text-small-medium--font-weight); }
1442
+ @utility text-small-regular { font-size: var(--text-small-regular); line-height: var(--text-small-regular--line-height); font-weight: var(--text-small-regular--font-weight); }
1443
+ @utility text-small-bold-h { font-size: var(--text-small-bold-h); line-height: var(--text-small-bold-h--line-height); font-weight: var(--text-small-bold-h--font-weight); }
1444
+ @utility text-small-medium-h { font-size: var(--text-small-medium-h); line-height: var(--text-small-medium-h--line-height); font-weight: var(--text-small-medium-h--font-weight); }
1445
+ @utility text-small-regular-h { font-size: var(--text-small-regular-h); line-height: var(--text-small-regular-h--line-height); font-weight: var(--text-small-regular-h--font-weight); }
1446
+ @utility text-xsmall-bold { font-size: var(--text-xsmall-bold); line-height: var(--text-xsmall-bold--line-height); font-weight: var(--text-xsmall-bold--font-weight); }
1447
+ @utility text-xsmall-medium { font-size: var(--text-xsmall-medium); line-height: var(--text-xsmall-medium--line-height); font-weight: var(--text-xsmall-medium--font-weight); }
1448
+ @utility text-xsmall-regular { font-size: var(--text-xsmall-regular); line-height: var(--text-xsmall-regular--line-height); font-weight: var(--text-xsmall-regular--font-weight); }
1449
+
1450
+ /* ============================================================================
1451
+ Radius
1452
+ ============================================================================ */
1453
+
1454
+ @utility rounded-none { border-radius: var(--radius-none); }
1455
+ @utility rounded-xsmall { border-radius: var(--radius-xsmall); }
1456
+ @utility rounded-small { border-radius: var(--radius-small); }
1457
+ @utility rounded-medium { border-radius: var(--radius-medium); }
1458
+ @utility rounded-large { border-radius: var(--radius-large); }
1459
+ @utility rounded-xlarge { border-radius: var(--radius-xlarge); }
1460
+
1461
+ /* ============================================================================
1462
+ Shadow
1463
+ ============================================================================ */
1464
+
1465
+ @utility shadow-primary-small { box-shadow: var(--shadow-primary-small); }
1466
+ @utility shadow-primary-medium { box-shadow: var(--shadow-primary-medium); }
1467
+ @utility shadow-primary-large { box-shadow: var(--shadow-primary-large); }
1468
+ @utility shadow-secondary-small { box-shadow: var(--shadow-secondary-small); }
1469
+ @utility shadow-secondary-medium { box-shadow: var(--shadow-secondary-medium); }
1470
+ @utility shadow-secondary-large { box-shadow: var(--shadow-secondary-large); }
1471
+ @utility shadow-danger-small { box-shadow: var(--shadow-danger-small); }
1472
+ @utility shadow-danger-medium { box-shadow: var(--shadow-danger-medium); }
1473
+ @utility shadow-danger-large { box-shadow: var(--shadow-danger-large); }
1474
+ @utility shadow-gray-small { box-shadow: var(--shadow-gray-small); }
1475
+ @utility shadow-gray-medium { box-shadow: var(--shadow-gray-medium); }
1476
+ @utility shadow-gray-large { box-shadow: var(--shadow-gray-large); }
1477
+ @utility shadow-success-small { box-shadow: var(--shadow-success-small); }
1478
+ @utility shadow-success-medium { box-shadow: var(--shadow-success-medium); }
1479
+ @utility shadow-success-large { box-shadow: var(--shadow-success-large); }
1480
+ @utility shadow-warning-small { box-shadow: var(--shadow-warning-small); }
1481
+ @utility shadow-warning-medium { box-shadow: var(--shadow-warning-medium); }
1482
+ @utility shadow-warning-large { box-shadow: var(--shadow-warning-large); }
1483
+ @utility shadow-info-small { box-shadow: var(--shadow-info-small); }
1484
+ @utility shadow-info-medium { box-shadow: var(--shadow-info-medium); }
1485
+ @utility shadow-info-large { box-shadow: var(--shadow-info-large); }
1486
+
1487
+ /* ============================================================================
1488
+ Animation
1489
+ ============================================================================ */
1490
+
1491
+ @utility animate-fade-in { animation: var(--animate-fade-in); }
1492
+ @utility animate-fade-out { animation: var(--animate-fade-out); }
1493
+ @utility animate-zoom-in { animation: var(--animate-zoom-in); }
1494
+ @utility animate-zoom-out { animation: var(--animate-zoom-out); }
1495
+ @utility animate-slide-in-from-top { animation: var(--animate-slide-in-from-top); }
1496
+ @utility animate-slide-out-to-top { animation: var(--animate-slide-out-to-top); }
1497
+ @utility animate-slide-in-from-bottom { animation: var(--animate-slide-in-from-bottom); }
1498
+ @utility animate-slide-out-to-bottom { animation: var(--animate-slide-out-to-bottom); }
1499
+ @utility animate-slide-in-from-left { animation: var(--animate-slide-in-from-left); }
1500
+ @utility animate-slide-out-to-left { animation: var(--animate-slide-out-to-left); }
1501
+ @utility animate-slide-in-from-right { animation: var(--animate-slide-in-from-right); }
1502
+ @utility animate-slide-out-to-right { animation: var(--animate-slide-out-to-right); }
1503
+ @utility animate-skeleton-gradient { animation: var(--animate-skeleton-gradient); }
1504
+
1505
+ /* ============================================================================
1506
+ Scrollbar
1507
+ ============================================================================ */
1508
+
1509
+ @utility scrollbar-gutter-stable { scrollbar-gutter: stable; }
1510
+ .ag-grid-container {
1511
+ width: 100%;
1512
+ height: 100%;
1513
+ }
1514
+
1515
+ /*
1516
+ AG Grid legacy base rule `[class*="ag-theme-"]` has higher specificity than
1517
+ v33 `:where(.ag-theme-params-*)` rules in some environments.
1518
+ Re-apply core table tokens here with stronger specificity.
1519
+ */
1520
+ .ag-grid-container [class*='ag-theme-'] {
1521
+ --ag-font-family: var(--font-sans);
1522
+ --ag-header-background-color: var(--color-sys-table-header-background);
1523
+ /* 선 하나의 규칙(2026-10-17 이슈 47 4차): 바깥 둥근 테두리·헤더 아래 선·행 선이 모두 같은 1px sys-divider-subtle.
1524
+ 원문 심판이 "채운 헤더 띠 vs 테두리 없는 행", "헤더에만 있는 열 구분선" 을 감점했고, 사용자가 표를 감싸는 둥근 테두리를 요청 */
1525
+ --ag-border-color: var(--color-sys-divider-subtle);
1526
+ --ag-wrapper-border: solid 1px var(--color-sys-divider-subtle);
1527
+ --ag-wrapper-border-radius: var(--radius-medium);
1528
+ --ag-header-row-border: solid 1px var(--color-sys-divider-subtle);
1529
+ --ag-row-border: solid 1px var(--color-sys-divider-subtle);
1530
+
1531
+ --ag-header-column-border: none;
1532
+ --ag-spacing: 8px;
1533
+ --ag-cell-horizontal-padding: calc(
1534
+ var(--ag-spacing) * 2 * var(--ag-cell-horizontal-padding-scale)
1535
+ );
1536
+
1537
+ /*
1538
+ themeQuartz.withParams()는 CSS var() 레퍼런스를 색상으로 파싱하지 못해 기본값으로 폴백.
1539
+ CSS 오버라이드 방식으로 브라우저가 var()를 해석하도록 강제.
1540
+ */
1541
+ --ag-foreground-color: var(--color-sys-text-normal);
1542
+ --ag-background-color: var(--color-sys-background);
1543
+ --ag-header-foreground-color: var(--color-sys-table-header-text);
1544
+ --ag-row-hover-color: var(--color-sys-table-hover);
1545
+ --ag-selected-row-background-color: var(--color-sys-table-select);
1546
+
1547
+ /* 헤더 컬럼 resize handle: CSS 변수로 다크모드 대응. 평소엔 숨기고 헤더 셀 hover 때만 보인다(아래) */
1548
+ --ag-header-column-resize-handle-color: var(--color-sys-border);
1549
+ --ag-header-column-resize-handle-height: 30%;
1550
+ --ag-header-column-resize-handle-width: 2px;
1551
+ }
1552
+
1553
+ /* 둥근 테두리 안에서 헤더 모서리가 잘리도록. 테두리 자체는 --ag-wrapper-border 가 그린다 */
1554
+ .ag-grid-container .ag-root-wrapper {
1555
+ overflow: hidden;
1556
+ }
1557
+
1558
+ /* 리사이즈 핸들은 hover 때만 — 늘 보이면 헤더에만 세로선이 있는 것처럼 읽힌다 */
1559
+ .ag-grid-container .ag-header-cell-resize::after {
1560
+ opacity: 0;
1561
+ transition: opacity 120ms ease;
1562
+ }
1563
+ .ag-grid-container .ag-header-cell:hover .ag-header-cell-resize::after {
1564
+ opacity: 1;
1565
+ }
1566
+
1567
+ /* 마지막 행의 선은 바깥 테두리와 겹쳐 2px 가 되므로 지운다 */
1568
+ .ag-grid-container .ag-row.ag-row-last {
1569
+ border-bottom: none;
1570
+ }
1571
+
1572
+ /* ============================================================================
1573
+ agGridTable/index.tsx에서 마이그레이션된 스타일
1574
+ ============================================================================ */
1575
+
1576
+ /* onRowClicked 옵션 사용 시 마우스 커서 변경 */
1577
+ .ag-grid-container .ag-row-clickable {
1578
+ cursor: pointer;
1579
+ }
1580
+
1581
+ /* 열 타입 'primary' (AgGridTable columnTypes): 주 식별자 열. 위계는 굵기로(본문 색, dl-ui-v3 목록의 이름 열과 같음),
1582
+ 클릭 가능하다는 표시는 행 hover 배경 + 이름 밑줄로. 파란 링크색은 쓰지 않는다 — 행 전체가 눌리는 표에서
1583
+ "이름만 링크" 로 읽히기 때문 (2026-10-09 결정) */
1584
+ .ag-grid-container .ag-cell-primary {
1585
+ color: var(--color-sys-text-main);
1586
+ font-weight: var(--font-weight-semibold);
1587
+ }
1588
+ /* hover 밑줄은 이름 글자에만 — 두 줄 셀(TwoLineCellRenderer)에서는 보조 줄까지 밑줄이 번지지 않게 첫 줄([data-slot='cell-primary'])만
1589
+ (2026-10-18 13차 ⑥). text-decoration 은 자손에게 전파되어 자손이 끌 수 없으므로 :has 로 대상을 나눈다 */
1590
+ .ag-grid-container .ag-row-clickable:hover .ag-cell-primary:not(:has([data-slot='cell-primary'])),
1591
+ .ag-grid-container .ag-row-clickable:hover .ag-cell-primary [data-slot='cell-primary'] {
1592
+ text-decoration: underline;
1593
+ }
1594
+
1595
+ /* 셀 말줄임 (2026-10-18 13차): defaultColDef.cellStyle 이 display:flex 라 .ag-cell-value 가 flex 자식이 되고, flex 자식은 min-width:auto 라
1596
+ 줄어들지 않아 ag-grid 의 말줄임(overflow:hidden; text-overflow:ellipsis)이 죽는다 — 글자가 셀 끝에서 뚝 잘렸다
1597
+ (한 줄 판 12차 목록 9쌍 중 7쌍 "clipped mid-word with no ellipsis"). min-width:0 을 주면 줄어들며 말줄임표가 산다.
1598
+ wrapText 를 켠 열(.ag-cell-wrap-text)과 ag-allow-overflow 는 건드리지 않는다 */
1599
+ .ag-grid-container .ag-cell,
1600
+ .ag-grid-container .ag-cell-wrapper,
1601
+ .ag-grid-container .ag-cell-value {
1602
+ min-width: 0;
1603
+ }
1604
+ .ag-grid-container .ag-cell:not(.ag-cell-wrap-text) .ag-cell-value:not(.ag-allow-overflow) {
1605
+ overflow: hidden;
1606
+ text-overflow: ellipsis;
1607
+ white-space: nowrap;
1608
+ }
1609
+
1610
+ /* 평문 셀 말줄임 (2026-10-26 22차): 체크박스·행 끌기 열이 없는 표에서 ag-grid 는 .ag-cell-wrapper 를 만들지 않고 .ag-cell 자체에
1611
+ ag-cell-value 를 붙인다(toggleCss("ag-cell-value", !usingWrapper)). valueFormatter 만 쓴 평문 열은 그 안이 글자 노드 하나인데
1612
+ defaultColDef.cellStyle 의 인라인 display:flex 가 들어가 글자가 익명 flex 항목이 되고 ellipsis 가 그려지지 않는다 — 위 규칙은 자손
1613
+ 선택자라 같은 요소에 닿지 않는다(21차 1-B: 'a100-prod-cluste' 뚝 잘림, 두 줄 판 알림 규칙 목록 2/3 run). 자식 요소가 없는 값 셀만
1614
+ block 으로 되돌린다(인라인 스타일을 이기려면 !important). 세로 가운데는 align-content. renderer 가 있는 셀(flex 정렬이 필요)·
1615
+ 숫자 열(.ag-right-aligned-cell, justify-content:flex-end 유지)·wrapText 열은 그대로 */
1616
+ .ag-grid-container
1617
+ .ag-cell.ag-cell-value:not(:has(> *)):not(.ag-right-aligned-cell):not(.ag-cell-wrap-text) {
1618
+ display: block !important;
1619
+ align-content: center;
1620
+ }
1621
+
1622
+ /* 열 타입 'number' (AgGridTable columnTypes): 숫자 열. defaultColDef.cellStyle 이 display:flex 라 ag-grid 의 text-align:right 가
1623
+ 먹지 않으므로 justify-content 로 오른쪽 정렬. 제목은 글자를 오른쪽, 정렬 아이콘을 왼쪽에(row-reverse). 숫자 폭은 고정(tabular-nums)
1624
+ — 원문 심판이 "숫자 열이 왼쪽 정렬" 을 51쌍에서 20회 감점 (2026-10-16 이슈 47) */
1625
+ .ag-grid-container .ag-cell.ag-right-aligned-cell {
1626
+ justify-content: flex-end;
1627
+ text-align: right;
1628
+ font-variant-numeric: tabular-nums;
1629
+ }
1630
+ .ag-grid-container .ag-header-cell.ag-right-aligned-header .ag-header-cell-label {
1631
+ /* 글자만 오른쪽으로, 정렬 아이콘은 다른 열처럼 글자 뒤. ag-grid 기본 테마가 숫자 열 헤더에 row-reverse 를 걸어 아이콘이 왼쪽으로 가므로
1632
+ 명시적으로 되돌린다 (2026-10-17 5차: "아이콘 자리가 다르다" 감점) */
1633
+ flex-direction: row;
1634
+ justify-content: flex-end;
1635
+ }
1636
+ /* 정렬 아이콘이 늘 보이는 숫자 열(withSortIconOffset): 위 제목은 글자 뒤에 아이콘(간격 --ag-spacing + 아이콘 --ag-icon-size)이 있어 글자가
1637
+ 값보다 그만큼 왼쪽에서 끝난다. 값 셀의 오른쪽 여백을 같은 폭만큼 늘려 제목 글자 끝 = 값 끝으로 맞춘다
1638
+ (2026-10-30 홀드아웃 17 세트 2: "right-aligned numeric values under left-aligned column headers") */
1639
+ .ag-grid-container .ag-cell.ag-right-aligned-cell.ag-cell-sort-offset {
1640
+ /* ag-grid 셀 여백 식(셀 테두리 1px 를 뺀 값)에 아이콘 폭을 더한다 — 1px 를 빼지 않으면 값이 제목보다 1px 안쪽(2026-10-30 실측) */
1641
+ padding-right: calc(
1642
+ var(--ag-cell-horizontal-padding) - 1px + var(--ag-spacing) + var(--ag-icon-size)
1643
+ );
1644
+ }
1645
+
1646
+ /* 상세가 열린 행 (ListPage activeRowId → rowClassRules 'ag-row-active'). 선택 행과 같은 색 */
1647
+ .ag-grid-container .ag-row.ag-row-active {
1648
+ background-color: var(--color-sys-table-select);
1649
+ }
1650
+
1651
+ /*
1652
+ domLayout: 'autoHeight' 일 때 기본 높이 제거 (단, 데이터가 없는 경우 기본 높이 유지)
1653
+ https://www.ag-grid.com/react-data-grid/grid-size/#min-height-with-auto-height
1654
+ */
1655
+ .ag-grid-container[data-is-empty='false'] .ag-center-cols-viewport {
1656
+ min-height: unset !important;
1657
+ }
1658
+
1659
+ /* 헤더는 바깥 둥근 테두리가 모서리를 맡으므로 자체 라운드 없음 */
1660
+ .ag-grid-container .ag-header {
1661
+ position: relative;
1662
+ z-index: 1;
1663
+ }
1664
+
1665
+ /* 마지막 컬럼 크기 조절 버튼 숨김 */
1666
+ .ag-grid-container .ag-column-last .ag-header-cell-resize {
1667
+ display: none;
1668
+ }
1669
+
1670
+ /* cellClass 옵션에 추가 시 cell width 100%으로 적용 */
1671
+ .ag-grid-container .width_full .ag-cell-wrapper {
1672
+ width: 100%;
1673
+ }
1674
+
1675
+ .ag-grid-container .width_full .ag-cell-value {
1676
+ width: 100%;
1677
+ }
1678
+
1679
+ .ag-grid-container .width_full.ag-cell {
1680
+ width: 100%;
1681
+ }
1682
+
1683
+ .ag-grid-container .ag-column-first {
1684
+ display: flex;
1685
+ align-items: center;
1686
+ }
1687
+
1688
+ /* 체크박스 크기 복원 (v33 Theming API에서 기본으로 작아짐 방지) */
1689
+ .ag-checkbox-input-wrapper,
1690
+ .ag-radio-button-input-wrapper {
1691
+ transform: scale(1.3);
1692
+ }
1693
+
1694
+ /* focus 시 보여지는 border-color 초기화 */
1695
+ .ag-cell-focus:not(.ag-cell-range-selected):focus-within,
1696
+ .ag-cell-range-single-cell,
1697
+ .ag-cell-range-single-cell.ag-cell-range-handle,
1698
+ .ag-context-menu-open .ag-cell-focus:not(.ag-cell-range-selected),
1699
+ .ag-full-width-row.ag-row-focus:focus .ag-cell-wrapper.ag-row-group {
1700
+ border-color: transparent;
1701
+ }
1702
+
1703
+ /* AG Grid v33: 마우스 클릭 시 focus-within 없이 ag-cell-focus만 붙는 케이스 대응 */
1704
+ .ag-grid-container .ag-cell-focus:not(.ag-cell-range-selected) {
1705
+ border-color: transparent !important;
1706
+ }
1707
+
1708
+ /* 빈 상태 오버레이 지원 */
1709
+ .ag-overlay-no-rows-wrapper {
1710
+ position: absolute;
1711
+ top: 40px;
1712
+ height: calc(100% - 40px);
1713
+ background-color: var(--color-sys-background);
1714
+ display: flex;
1715
+ align-items: center;
1716
+ justify-content: center;
1717
+ }
1718
+
1719
+ .ag-overlay-no-rows-center {
1720
+ background-color: var(--color-sys-background);
1721
+ color: var(--color-sys-text-subtle);
1722
+ }
1723
+
1724
+ /* 로딩 오버레이 지원 */
1725
+ .ag-overlay-loading-wrapper {
1726
+ background-color: var(--color-sys-background);
1727
+ }
1728
+
1729
+ .ag-overlay-loading-center {
1730
+ background-color: var(--color-sys-background);
1731
+ color: var(--color-sys-text-normal);
1732
+ }
1733
+
1734
+ /* 행 클릭 시 눌림 효과 */
1735
+ .ag-grid-container .ag-row:active {
1736
+ background-color: var(--color-sys-table-press) !important;
1737
+ }
1738
+
1739
+ /* 선택된 행 hover 상태 */
1740
+ .ag-grid-container .ag-row-selected.ag-row-hover {
1741
+ background-color: var(--color-sys-table-press);
1742
+ }
1743
+
1744
+ /* Checkbox Column Fix: Remove padding to allow full cell click area */
1745
+ .checkbox-column-cell {
1746
+ padding: 0 !important;
1747
+ display: flex !important;
1748
+ justify-content: center !important;
1749
+ align-items: center !important;
1750
+ }
1751
+
1752
+ .checkbox-column-cell .ag-react-container {
1753
+ width: 100%;
1754
+ height: 100%;
1755
+ }
1756
+
1757
+ /* ============================================================================
1758
+ 다크모드 AG Grid 오버라이드
1759
+ AG Grid 팝업(ag-popup, ag-menu)은 body 포털로 렌더링되므로
1760
+ .ag-grid-container 스코프 없이 [data-theme='dark']로만 처리
1761
+ ============================================================================ */
1762
+
1763
+ /* 팝업 / 메뉴 / 필터 배경 */
1764
+ [data-theme='dark'] .ag-popup,
1765
+ [data-theme='dark'] .ag-menu,
1766
+ [data-theme='dark'] .ag-filter {
1767
+ background-color: var(--color-sys-background);
1768
+ border: 1px solid var(--color-sys-divider-subtler);
1769
+ }
1770
+
1771
+ [data-theme='dark'] .ag-filter-toolpanel-header,
1772
+ [data-theme='dark'] .ag-filter-air-mode,
1773
+ [data-theme='dark'] .ag-filter-list-panel,
1774
+ [data-theme='dark'] .ag-filter-apply-panel {
1775
+ background-color: var(--color-sys-background);
1776
+ }
1777
+
1778
+ /* 텍스트 입력창 (Search) */
1779
+ [data-theme='dark'] .ag-input-field-input {
1780
+ background-color: var(--color-sys-background);
1781
+ color: var(--color-sys-text-main);
1782
+ border: 1px solid var(--color-sys-divider-main);
1783
+ border-radius: 6px;
1784
+ height: 36px;
1785
+ }
1786
+
1787
+ [data-theme='dark'] .ag-input-field-input:focus {
1788
+ outline: 2px solid var(--color-sys-focus-ring-bold);
1789
+ border-color: var(--color-sys-focus-ring-bold);
1790
+ }
1791
+
1792
+ [data-theme='dark'] .ag-input-field-input::placeholder {
1793
+ color: var(--color-sys-text-subtler);
1794
+ }
1795
+
1796
+ [data-theme='dark'] .ag-input-wrapper::before,
1797
+ [data-theme='dark'] .ag-input-wrapper::after,
1798
+ [data-theme='dark'] .ag-picker-field-icon .ag-icon::before,
1799
+ [data-theme='dark'] .ag-picker-field-icon .ag-icon::after {
1800
+ background-color: var(--color-sys-text-subtle) !important;
1801
+ color: var(--color-sys-text-subtle) !important;
1802
+ }
1803
+
1804
+ [data-theme='dark'] .ag-picker-field-icon {
1805
+ background-color: transparent !important;
1806
+ color: var(--color-sys-text-subtle) !important;
1807
+ }
1808
+
1809
+ [data-theme='dark'] .ag-icon {
1810
+ color: var(--color-sys-text-subtle) !important;
1811
+ }
1812
+
1813
+ /* 셀렉트 박스 */
1814
+ [data-theme='dark'] .ag-picker-field-wrapper {
1815
+ background-color: var(--color-sys-background);
1816
+ border: 1px solid var(--color-sys-divider-main);
1817
+ border-radius: 6px;
1818
+ min-height: 36px;
1819
+ }
1820
+
1821
+ [data-theme='dark'] .ag-picker-field-display {
1822
+ color: var(--color-sys-text-main);
1823
+ margin-left: 4px;
1824
+ }
1825
+
1826
+ [data-theme='dark'] .ag-rich-select-list,
1827
+ [data-theme='dark'] .ag-select-list,
1828
+ [data-theme='dark'] .ag-picker-field-wrapper .ag-picker-expanded {
1829
+ background-color: var(--color-sys-background);
1830
+ border: 1px solid var(--color-sys-divider-subtler);
1831
+ box-shadow: 0 4px 16px var(--color-grayscale-s30);
1832
+ }
1833
+
1834
+ [data-theme='dark'] .ag-rich-select-row,
1835
+ [data-theme='dark'] .ag-select-list-item {
1836
+ color: var(--color-sys-text-normal);
1837
+ }
1838
+
1839
+ [data-theme='dark'] .ag-rich-select-row.ag-rich-select-row-selected,
1840
+ [data-theme='dark'] .ag-select-list-item:hover,
1841
+ [data-theme='dark'] .ag-select-list-item.ag-select-list-item-highlighted {
1842
+ background-color: var(--color-sys-table-select);
1843
+ }
1844
+
1845
+ /* 체크박스: 글로우/배경 제거 */
1846
+ [data-theme='dark'] .ag-checkbox-input-wrapper {
1847
+ background-color: transparent !important;
1848
+ box-shadow: none !important;
1849
+ transform: scale(1.3);
1850
+ }
1851
+
1852
+ [data-theme='dark'] .ag-checkbox-input-wrapper::after {
1853
+ color: white;
1854
+ }
1855
+
1856
+ /* 라디오 버튼: Masked Donut 전략 */
1857
+ [data-theme='dark'] .ag-radio-button .ag-radio-button-input-wrapper {
1858
+ background-color: transparent;
1859
+ border: 1.5px solid var(--color-sys-divider-main);
1860
+ border-radius: 50%;
1861
+ box-sizing: border-box;
1862
+ transition: all 0.1s ease;
1863
+ background-image: none !important;
1864
+ mask-image: none !important;
1865
+ }
1866
+
1867
+ [data-theme='dark'] .ag-radio-button:not(.ag-checked) .ag-radio-button-input-wrapper {
1868
+ border-color: var(--color-sys-divider-main);
1869
+ }
1870
+
1871
+ [data-theme='dark'] .ag-radio-button:not(.ag-checked) .ag-radio-button-input-wrapper::after {
1872
+ content: none;
1873
+ }
1874
+
1875
+ [data-theme='dark'] .ag-radio-button .ag-radio-button-input-wrapper.ag-checked {
1876
+ background-color: var(--color-primary30);
1877
+ border-color: var(--color-primary30);
1878
+ border-width: 0px;
1879
+ background-image: none !important;
1880
+ mask-image: none !important;
1881
+ }
1882
+
1883
+ [data-theme='dark'] .ag-radio-button .ag-radio-button-input-wrapper.ag-checked::after {
1884
+ content: '';
1885
+ display: block;
1886
+ width: 100%;
1887
+ height: 100%;
1888
+ background-color: var(--color-sys-background) !important;
1889
+ border-radius: 50%;
1890
+ transform: scale(0.4);
1891
+ background-image: none !important;
1892
+ mask-image: none !important;
1893
+ box-shadow: none !important;
1894
+ border: none !important;
1895
+ }
1896
+
1897
+ /* 체크박스 / 라디오 레이블 */
1898
+ [data-theme='dark'] .ag-checkbox-label,
1899
+ [data-theme='dark'] .ag-radio-button-label {
1900
+ color: var(--color-sys-text-main);
1901
+ }
1902
+ /* Parameter Table — Google Sheets 스타일 셀 모드 시각 스타일.
1903
+ active/selected/editing 상태는 ParameterTableRow 에서 data-* 속성으로 표시.
1904
+
1905
+ 편집 input 은 단일 floating input 으로 root 안에 absolute positioning. 활성 cell
1906
+ 위에 띄워서 cell 위치를 따라간다 — IME composition 중 input element 가
1907
+ unmount/remount 되지 않으므로 한국어 자모 분리 문제가 발생하지 않는다. */
1908
+
1909
+ .t3q-parameter-table {
1910
+ width: 100%;
1911
+ position: relative; /* floating input absolute 기준점 */
1912
+ }
1913
+
1914
+ /* 셀 기본. text 선택 차단 + cursor-cell (셀 선택 UX 힌트). */
1915
+ .t3q-pt-cell {
1916
+ user-select: none;
1917
+ position: relative;
1918
+ vertical-align: middle;
1919
+ border-bottom: 1px solid var(--color-sys-divider-subtle); /* Table 행 선과 같은 토큰 (2026-10-17 이슈 47 4차) */
1920
+ }
1921
+
1922
+ /* 마지막 행의 선은 Table 의 둥근 바깥 테두리와 겹치지 않게 지운다 */
1923
+ tr:last-child > .t3q-pt-cell {
1924
+ border-bottom: none;
1925
+ }
1926
+
1927
+ /* 외부 검증 실패 셀. layout 영향 없이 연한 빨강 배경으로 강조.
1928
+ sys-alert-danger-background 와 동일 토큰(danger-o10) — opacity 기반이라 hover/selection
1929
+ tint 위에서도 자연스럽게 합성된다. 아래 .t3q-pt-cell--selected / --editing 이 CSS
1930
+ cascade 에서 뒤에 정의돼 사용자 인터랙션 중인 셀은 selection/editing 배경이 우선. */
1931
+ .t3q-pt-cell--error {
1932
+ background-color: var(--color-danger-o10);
1933
+ }
1934
+
1935
+ /* 선택 범위 안의 셀. 배경에 옅은 primary tint. */
1936
+ .t3q-pt-cell--selected {
1937
+ background-color: var(--color-sys-table-select);
1938
+ }
1939
+
1940
+ /* 편집 중 셀. 흰 배경 + 활성 outline. CSS 변수 fallback 안전한 outline 색. */
1941
+ .t3q-pt-cell--editing {
1942
+ background-color: var(--color-sys-background);
1943
+ outline: 2px solid var(--color-sys-focus-ring-bold);
1944
+ outline-offset: -2px;
1945
+ z-index: 1;
1946
+ }
1947
+
1948
+ /* 비편집 상태의 셀 display 영역. 셀 안 텍스트 유무와 무관하게 행 높이가 동일하도록
1949
+ 고정 height + 명시적 line-height. min-height 가 floor 일 뿐이라 inline content 의
1950
+ font line box 가 박스 높이를 미세하게 변경시키는 문제를 차단. */
1951
+ .t3q-pt-cell-display {
1952
+ height: 28px;
1953
+ line-height: 1.4;
1954
+ display: flex;
1955
+ align-items: center;
1956
+ }
1957
+
1958
+ /* 편집 중인 셀의 display 영역은 floating input 이 그 위를 덮으므로 visually hidden.
1959
+ 레이아웃은 유지해 (text node 그대로 둠) cell 의 line-height/height 측정에 영향 X. */
1960
+ .t3q-pt-cell-display--editing {
1961
+ visibility: hidden;
1962
+ }
1963
+
1964
+ /* compact spacing 보정. */
1965
+ .t3q-parameter-table--compact .t3q-pt-cell-display {
1966
+ height: 24px;
1967
+ font-size: 13px;
1968
+ }
1969
+
1970
+ .t3q-parameter-table--normal .t3q-pt-cell-display {
1971
+ height: 32px;
1972
+ }
1973
+
1974
+ /* disabled. */
1975
+ .t3q-parameter-table--disabled .t3q-pt-cell {
1976
+ cursor: default;
1977
+ }
1978
+
1979
+ /* 단일 floating input — 활성 cell 위에 absolute positioning. 비편집 모드에서는
1980
+ off-screen 아니라 활성 cell 위에 두지만 opacity:0 + pointer-events:none 으로 숨김.
1981
+ focus 는 항상 이 input 에 있어 한국어/일본어/중국어 IME 가 자연스럽게 composition
1982
+ 을 받는다. cell 별로 input 을 mount/unmount 하지 않으므로 composition 이
1983
+ 끊기지 않는다.
1984
+
1985
+ background: transparent — 셀의 outline / background / selected tint 같은 모든 시각
1986
+ 단서는 cell 이 표현하고, floating input 은 단지 caret + text + selection 만 그 위에
1987
+ 덧그리는 invisible layer 역할. 불투명 background 였을 때는 cell editing 의 outline
1988
+ (outline-offset -2px 로 셀 안쪽에 그려짐) 이 가려져 안 보이는 문제가 있었다. */
1989
+ .t3q-pt-floating-input {
1990
+ position: absolute;
1991
+ margin: 0;
1992
+ border: 0;
1993
+ padding: 6px 12px;
1994
+ background: transparent;
1995
+ color: var(--color-sys-text-main);
1996
+ font: inherit;
1997
+ line-height: 1.4;
1998
+ outline: none;
1999
+ /* default: cell 위치에 두지만 안 보이고 mouse interaction 안 받음 */
2000
+ opacity: 0;
2001
+ pointer-events: none;
2002
+ z-index: 2;
2003
+ }
2004
+
2005
+ /* compact spacing — cell display 와 동일한 폰트 크기 */
2006
+ .t3q-parameter-table--compact .t3q-pt-floating-input {
2007
+ font-size: 13px;
2008
+ }
2009
+
2010
+ /* 편집 모드: 셀 위에 visible. */
2011
+ .t3q-pt-floating-input--editing {
2012
+ opacity: 1;
2013
+ pointer-events: auto;
2014
+ }