1in-ui 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,2116 @@
1
+ /**
2
+ * 1in UI - 轻量级前端组件库
3
+ * 完全基于实际项目样式提取
4
+ * Version: 1.1.0
5
+ */
6
+
7
+ /* ========================================
8
+ CSS Variables / 设计令牌
9
+ ======================================== */
10
+ :root {
11
+ /* 主色调 */
12
+ --ui-primary: #6366f1;
13
+ --ui-primary-hover: #4f46e5;
14
+
15
+ /* 功能色 */
16
+ --ui-success: #10b981;
17
+ --ui-error: #ef4444;
18
+ --ui-warning: #f59e0b;
19
+
20
+ /* 中性色 - 亮色模式 */
21
+ --ui-bg: #f1f5f9; /* slate-100 */
22
+ --ui-bg-card: #ffffff;
23
+ --ui-bg-input: #f8fafc; /* slate-50 */
24
+ --ui-border: #f1f5f9; /* slate-100 */
25
+ --ui-border-dark: #e2e8f0; /* slate-200 */
26
+ --ui-text: #475569; /* slate-600 */
27
+ --ui-text-dark: #1e293b; /* slate-800 */
28
+ --ui-text-light: #94a3b8; /* slate-400 */
29
+ --ui-text-muted: #64748b; /* slate-500 */
30
+
31
+ /* 字体 */
32
+ --ui-font: 'Nunito', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
33
+
34
+ /* 阴影 */
35
+ --ui-shadow-card: 0 4px 6px -1px rgba(0, 0, 0, 0.02), 0 2px 4px -1px rgba(0, 0, 0, 0.02);
36
+ --ui-shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.08), 0 4px 6px -4px rgba(0, 0, 0, 0.05);
37
+
38
+ /* 过渡 */
39
+ --ui-transition: all 0.2s ease;
40
+ --ui-transition-colors: color 0.3s, background-color 0.3s, border-color 0.3s;
41
+ }
42
+
43
+ /* 暗色模式 */
44
+ .dark {
45
+ --ui-bg: #0f172a; /* slate-900 */
46
+ --ui-bg-card: #1e293b; /* slate-800 */
47
+ --ui-bg-input: #0f172a; /* slate-900 */
48
+ --ui-border: #334155; /* slate-700 */
49
+ --ui-border-dark: #334155;
50
+ --ui-text: #cbd5e1; /* slate-300 */
51
+ --ui-text-dark: #ffffff;
52
+ --ui-text-light: #64748b; /* slate-500 */
53
+ --ui-text-muted: #94a3b8; /* slate-400 */
54
+ }
55
+
56
+ /* ========================================
57
+ Base / 基础样式
58
+ ======================================== */
59
+ *, *::before, *::after {
60
+ box-sizing: border-box;
61
+ }
62
+
63
+ /* 滚动条 - Discord 风格 */
64
+ ::-webkit-scrollbar {
65
+ width: 8px;
66
+ height: 8px;
67
+ }
68
+
69
+ ::-webkit-scrollbar-track {
70
+ background: transparent;
71
+ }
72
+
73
+ ::-webkit-scrollbar-thumb {
74
+ background: #c4c9ce;
75
+ border-radius: 4px;
76
+ }
77
+
78
+ ::-webkit-scrollbar-thumb:hover {
79
+ background: #a8adb3;
80
+ }
81
+
82
+ .dark ::-webkit-scrollbar-thumb {
83
+ background: #1a1b1e;
84
+ }
85
+
86
+ .dark ::-webkit-scrollbar-thumb:hover {
87
+ background: #232428;
88
+ }
89
+
90
+ /* Firefox 滚动条 */
91
+ * {
92
+ scrollbar-width: thin;
93
+ scrollbar-color: #c4c9ce transparent;
94
+ }
95
+
96
+ .dark * {
97
+ scrollbar-color: #1a1b1e transparent;
98
+ }
99
+
100
+ .ui-base {
101
+ font-family: var(--ui-font);
102
+ color: var(--ui-text);
103
+ background-color: var(--ui-bg);
104
+ -webkit-font-smoothing: antialiased;
105
+ -moz-osx-font-smoothing: grayscale;
106
+ min-height: 100vh;
107
+ }
108
+
109
+ /* ========================================
110
+ Navbar / 导航栏
111
+ 完全匹配: fixed top-0 bg-white/80 backdrop-blur-md border-b h-16
112
+ ======================================== */
113
+ .ui-navbar {
114
+ position: fixed;
115
+ top: 0;
116
+ left: 0;
117
+ right: 0;
118
+ z-index: 50;
119
+ height: 4rem;
120
+ background: rgba(255, 255, 255, 0.8);
121
+ backdrop-filter: blur(12px);
122
+ -webkit-backdrop-filter: blur(12px);
123
+ border-bottom: 1px solid var(--ui-border);
124
+ transition: var(--ui-transition-colors);
125
+ }
126
+
127
+ .dark .ui-navbar {
128
+ background: rgba(15, 23, 42, 0.8);
129
+ border-color: #1e293b;
130
+ }
131
+
132
+ .ui-navbar-inner {
133
+ max-width: 80rem;
134
+ margin: 0 auto;
135
+ padding: 0 1rem;
136
+ height: 100%;
137
+ display: flex;
138
+ justify-content: space-between;
139
+ align-items: center;
140
+ }
141
+
142
+ /* Logo: flex items-center space-x-2 */
143
+ .ui-navbar-brand {
144
+ display: flex;
145
+ align-items: center;
146
+ gap: 0.5rem;
147
+ text-decoration: none;
148
+ cursor: pointer;
149
+ }
150
+
151
+ .ui-navbar-brand img {
152
+ width: 2rem;
153
+ height: 2rem;
154
+ border-radius: 0.5rem;
155
+ box-shadow: var(--ui-shadow-lg);
156
+ }
157
+
158
+ .ui-navbar-brand span {
159
+ font-weight: 800;
160
+ font-size: 1.125rem;
161
+ color: var(--ui-text-dark);
162
+ letter-spacing: -0.025em;
163
+ }
164
+
165
+ /* 导航链接组: bg-slate-100/50 p-1 rounded-full */
166
+ .ui-nav-pills {
167
+ display: flex;
168
+ align-items: center;
169
+ gap: 0.25rem;
170
+ background: rgba(241, 245, 249, 0.5);
171
+ padding: 0.25rem;
172
+ border-radius: 9999px;
173
+ }
174
+
175
+ .dark .ui-nav-pills {
176
+ background: rgba(30, 41, 59, 0.5);
177
+ }
178
+
179
+ /* 导航链接: px-5 py-1.5 rounded-full text-sm font-bold */
180
+ .ui-nav-link {
181
+ padding: 0.375rem 1.25rem;
182
+ border-radius: 9999px;
183
+ font-size: 0.875rem;
184
+ font-weight: 700;
185
+ color: var(--ui-text-muted);
186
+ text-decoration: none;
187
+ transition: var(--ui-transition);
188
+ }
189
+
190
+ .ui-nav-link:hover {
191
+ color: var(--ui-primary);
192
+ }
193
+
194
+ /* 激活状态: bg-white text-primary shadow-sm */
195
+ .ui-nav-link.active {
196
+ background: var(--ui-bg-card);
197
+ color: var(--ui-primary);
198
+ box-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05);
199
+ }
200
+
201
+ .dark .ui-nav-link.active {
202
+ background: #334155;
203
+ }
204
+
205
+ /* 分隔线: w-px h-6 bg-slate-200/70 mx-1 */
206
+ .ui-divider-v {
207
+ width: 1px;
208
+ height: 1.5rem;
209
+ background: rgba(226, 232, 240, 0.7);
210
+ margin: 0 0.25rem;
211
+ }
212
+
213
+ .dark .ui-divider-v {
214
+ background: #334155;
215
+ }
216
+
217
+
218
+ /* ========================================
219
+ Buttons / 按钮
220
+ 完全匹配: px-3 py-2 rounded-lg text-sm font-bold transition-colors
221
+ ======================================== */
222
+
223
+ /* 基础按钮 */
224
+ .ui-btn {
225
+ display: inline-flex;
226
+ align-items: center;
227
+ justify-content: center;
228
+ gap: 0.5rem;
229
+ padding: 0.5rem 0.75rem;
230
+ font-size: 0.875rem;
231
+ font-weight: 700;
232
+ border-radius: 0.5rem;
233
+ border: none;
234
+ cursor: pointer;
235
+ transition: all 0.15s ease;
236
+ text-decoration: none;
237
+ white-space: nowrap;
238
+ font-family: var(--ui-font);
239
+ }
240
+
241
+ .ui-btn:hover:not(:disabled) {
242
+ transform: translateY(-1px);
243
+ }
244
+
245
+ .ui-btn:active:not(:disabled) {
246
+ transform: translateY(0) scale(0.98);
247
+ }
248
+
249
+ .ui-btn:disabled {
250
+ opacity: 0.5;
251
+ cursor: not-allowed;
252
+ }
253
+
254
+ /* 主要按钮: bg-primary text-white hover:bg-primary-hover */
255
+ .ui-btn-primary {
256
+ background: var(--ui-primary);
257
+ color: white;
258
+ box-shadow: 0 2px 0 rgba(0,0,0,0.1);
259
+ }
260
+
261
+ .ui-btn-primary:hover:not(:disabled) {
262
+ background: var(--ui-primary-hover);
263
+ box-shadow: 0 4px 12px rgba(99, 102, 241, 0.4);
264
+ }
265
+
266
+ /* 次要按钮: bg-slate-100 text-slate-700 hover:bg-slate-200 */
267
+ .ui-btn-secondary {
268
+ background: #f1f5f9;
269
+ color: #334155;
270
+ }
271
+
272
+ .dark .ui-btn-secondary {
273
+ background: #334155;
274
+ color: #f1f5f9;
275
+ }
276
+
277
+ .ui-btn-secondary:hover:not(:disabled) {
278
+ background: #e2e8f0;
279
+ }
280
+
281
+ .dark .ui-btn-secondary:hover:not(:disabled) {
282
+ background: #475569;
283
+ }
284
+
285
+ /* 幽灵按钮: text-slate-600 hover:bg-slate-100 */
286
+ .ui-btn-ghost {
287
+ background: transparent;
288
+ color: var(--ui-text);
289
+ }
290
+
291
+ .ui-btn-ghost:hover:not(:disabled) {
292
+ background: #f1f5f9;
293
+ }
294
+
295
+ .dark .ui-btn-ghost:hover:not(:disabled) {
296
+ background: #1e293b;
297
+ }
298
+
299
+ /* 危险按钮: bg-red-500 text-white hover:bg-red-600 */
300
+ .ui-btn-danger {
301
+ background: #ef4444;
302
+ color: white;
303
+ box-shadow: 0 2px 0 rgba(0,0,0,0.1);
304
+ }
305
+
306
+ .ui-btn-danger:hover:not(:disabled) {
307
+ background: #dc2626;
308
+ box-shadow: 0 4px 12px rgba(239, 68, 68, 0.4);
309
+ }
310
+
311
+ /* 成功按钮: bg-green-500 */
312
+ .ui-btn-success {
313
+ background: #22c55e;
314
+ color: white;
315
+ box-shadow: 0 2px 0 rgba(0,0,0,0.1);
316
+ }
317
+
318
+ .ui-btn-success:hover:not(:disabled) {
319
+ background: #16a34a;
320
+ box-shadow: 0 4px 12px rgba(34, 197, 94, 0.4);
321
+ }
322
+
323
+ /* 大按钮 (提交按钮): w-full py-4 rounded-xl text-lg shadow-lg hover:-translate-y-0.5 */
324
+ .ui-btn-lg {
325
+ width: 100%;
326
+ padding: 1rem;
327
+ font-size: 1.125rem;
328
+ border-radius: 0.75rem;
329
+ box-shadow: var(--ui-shadow-lg);
330
+ }
331
+
332
+ .ui-btn-lg:hover:not(:disabled) {
333
+ transform: translateY(-2px);
334
+ }
335
+
336
+ .ui-btn-lg:active:not(:disabled) {
337
+ transform: translateY(0);
338
+ }
339
+
340
+ /* 图标按钮: w-9 h-9 rounded-full bg-slate-50 */
341
+ .ui-btn-icon {
342
+ width: 2.25rem;
343
+ height: 2.25rem;
344
+ padding: 0;
345
+ border-radius: 9999px;
346
+ background: #f8fafc;
347
+ color: var(--ui-text-light);
348
+ border: none;
349
+ cursor: pointer;
350
+ transition: all 0.15s ease;
351
+ display: inline-flex;
352
+ align-items: center;
353
+ justify-content: center;
354
+ }
355
+
356
+ .ui-btn-icon svg {
357
+ width: 1.125rem;
358
+ height: 1.125rem;
359
+ }
360
+
361
+ .dark .ui-btn-icon {
362
+ background: #1e293b;
363
+ }
364
+
365
+ .ui-btn-icon:hover:not(:disabled) {
366
+ background: #e2e8f0;
367
+ color: var(--ui-text-dark);
368
+ }
369
+
370
+ .dark .ui-btn-icon:hover:not(:disabled) {
371
+ background: #334155;
372
+ color: #f1f5f9;
373
+ }
374
+
375
+ /* ========================================
376
+ Cards / 卡片
377
+ 完全匹配: bg-white p-8 rounded-[2rem] border border-slate-100 shadow-card
378
+ ======================================== */
379
+ .ui-card {
380
+ background: var(--ui-bg-card);
381
+ padding: 2rem;
382
+ border-radius: 2rem;
383
+ border: 1px solid var(--ui-border);
384
+ box-shadow: var(--ui-shadow-card);
385
+ transition: all 0.2s ease;
386
+ }
387
+
388
+ .ui-card:hover {
389
+ box-shadow: 0 8px 24px -4px rgba(0, 0, 0, 0.08);
390
+ }
391
+
392
+ .dark .ui-card:hover {
393
+ box-shadow: 0 8px 24px -4px rgba(0, 0, 0, 0.3);
394
+ }
395
+
396
+ /* 小卡片: p-4 rounded-2xl */
397
+ .ui-card-sm {
398
+ padding: 1rem;
399
+ border-radius: 1rem;
400
+ }
401
+
402
+ /* 毛玻璃卡片: bg-white/80 backdrop-blur-md */
403
+ .ui-card-blur {
404
+ background: rgba(255, 255, 255, 0.8);
405
+ backdrop-filter: blur(12px);
406
+ -webkit-backdrop-filter: blur(12px);
407
+ }
408
+
409
+ .dark .ui-card-blur {
410
+ background: rgba(30, 41, 59, 0.6);
411
+ }
412
+
413
+ /* 卡片标题: text-2xl font-extrabold text-slate-800 mb-2 */
414
+ .ui-card-title {
415
+ font-size: 1.5rem;
416
+ font-weight: 800;
417
+ color: var(--ui-text-dark);
418
+ margin: 0 0 0.5rem 0;
419
+ }
420
+
421
+ /* 卡片副标题: text-sm font-medium text-slate-500 mb-6 */
422
+ .ui-card-subtitle {
423
+ font-size: 0.875rem;
424
+ font-weight: 500;
425
+ color: var(--ui-text-muted);
426
+ margin: 0 0 1.5rem 0;
427
+ }
428
+
429
+ /* 信息卡片图标: w-9 h-9 rounded-xl bg-primary/10 text-primary */
430
+ .ui-card-icon {
431
+ width: 2.25rem;
432
+ height: 2.25rem;
433
+ border-radius: 0.75rem;
434
+ background: rgba(99, 102, 241, 0.1);
435
+ color: var(--ui-primary);
436
+ display: flex;
437
+ align-items: center;
438
+ justify-content: center;
439
+ font-weight: 900;
440
+ flex-shrink: 0;
441
+ }
442
+
443
+
444
+ /* ========================================
445
+ Form / 表单
446
+ 完全匹配实际样式
447
+ ======================================== */
448
+
449
+ /* 标签: text-xs font-bold text-slate-400 uppercase tracking-wide mb-2 ml-1 */
450
+ .ui-label {
451
+ display: block;
452
+ font-size: 0.75rem;
453
+ font-weight: 700;
454
+ color: var(--ui-text-light);
455
+ text-transform: uppercase;
456
+ letter-spacing: 0.05em;
457
+ margin-bottom: 0.5rem;
458
+ margin-left: 0.25rem;
459
+ }
460
+
461
+ /* 输入框: bg-slate-50 border-2 border-transparent focus:bg-white focus:border-primary focus:ring-4 focus:ring-primary/10 rounded-xl px-4 py-3 font-bold */
462
+ .ui-input {
463
+ width: 100%;
464
+ box-sizing: border-box;
465
+ background: var(--ui-bg-input);
466
+ border: 2px solid transparent;
467
+ border-radius: 0.75rem;
468
+ padding: 0.75rem 1rem;
469
+ font-size: 0.875rem;
470
+ font-weight: 700;
471
+ font-family: var(--ui-font);
472
+ color: var(--ui-text-dark);
473
+ outline: none;
474
+ transition: var(--ui-transition);
475
+ }
476
+
477
+ .ui-input::placeholder {
478
+ color: var(--ui-text-light);
479
+ }
480
+
481
+ .dark .ui-input::placeholder {
482
+ color: #475569;
483
+ }
484
+
485
+ .ui-input:focus {
486
+ background: var(--ui-bg-card);
487
+ border-color: var(--ui-primary);
488
+ box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.25);
489
+ }
490
+
491
+ /* 带图标的输入框容器 */
492
+ .ui-input-group {
493
+ position: relative;
494
+ }
495
+
496
+ /* 输入框图标: absolute left-0 pl-4 text-slate-400 */
497
+ .ui-input-icon {
498
+ position: absolute;
499
+ left: 0;
500
+ top: 0;
501
+ bottom: 0;
502
+ padding-left: 1rem;
503
+ display: flex;
504
+ align-items: center;
505
+ pointer-events: none;
506
+ color: var(--ui-text-light);
507
+ }
508
+
509
+ .ui-input-icon svg {
510
+ width: 1.25rem;
511
+ height: 1.25rem;
512
+ }
513
+
514
+ /* 带图标时输入框左内边距: pl-11 */
515
+ .ui-input-group .ui-input {
516
+ padding-left: 2.75rem;
517
+ }
518
+
519
+ /* 文本域 */
520
+ .ui-textarea {
521
+ min-height: 6rem;
522
+ resize: vertical;
523
+ }
524
+
525
+ /* 复选框: inline-flex items-center gap-2 */
526
+ .ui-checkbox {
527
+ display: inline-flex;
528
+ align-items: center;
529
+ gap: 0.5rem;
530
+ cursor: pointer;
531
+ font-size: 0.875rem;
532
+ font-weight: 700;
533
+ color: var(--ui-text);
534
+ }
535
+
536
+ .ui-checkbox input {
537
+ width: 1rem;
538
+ height: 1rem;
539
+ accent-color: var(--ui-primary);
540
+ cursor: pointer;
541
+ }
542
+
543
+ /* 表单间距: space-y-5 */
544
+ .ui-form-group {
545
+ margin-bottom: 1.25rem;
546
+ }
547
+
548
+ /* ========================================
549
+ Alert / 提示框
550
+ 完全匹配: p-4 rounded-xl text-sm font-bold shadow-sm
551
+ ======================================== */
552
+ .ui-alert {
553
+ padding: 1rem;
554
+ border-radius: 0.75rem;
555
+ font-size: 0.875rem;
556
+ font-weight: 700;
557
+ box-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05);
558
+ }
559
+
560
+ /* 成功: bg-emerald-50 text-emerald-700 */
561
+ .ui-alert-success {
562
+ background: #ecfdf5;
563
+ color: #047857;
564
+ }
565
+
566
+ .dark .ui-alert-success {
567
+ background: rgba(16, 185, 129, 0.2);
568
+ color: #34d399;
569
+ }
570
+
571
+ /* 错误: bg-red-50 text-red-700 */
572
+ .ui-alert-error {
573
+ background: #fef2f2;
574
+ color: #b91c1c;
575
+ }
576
+
577
+ .dark .ui-alert-error {
578
+ background: rgba(239, 68, 68, 0.2);
579
+ color: #f87171;
580
+ }
581
+
582
+ /* 警告 */
583
+ .ui-alert-warning {
584
+ background: #fffbeb;
585
+ color: #b45309;
586
+ }
587
+
588
+ .dark .ui-alert-warning {
589
+ background: rgba(245, 158, 11, 0.2);
590
+ color: #fbbf24;
591
+ }
592
+
593
+ /* 信息: bg-primary/10 */
594
+ .ui-alert-info {
595
+ background: rgba(99, 102, 241, 0.1);
596
+ color: #4338ca;
597
+ }
598
+
599
+ .dark .ui-alert-info {
600
+ background: rgba(99, 102, 241, 0.2);
601
+ color: #a5b4fc;
602
+ }
603
+
604
+ /* 提示框内容布局: flex items-start */
605
+ .ui-alert-content {
606
+ display: flex;
607
+ align-items: flex-start;
608
+ gap: 0.75rem;
609
+ }
610
+
611
+ .ui-alert-icon {
612
+ flex-shrink: 0;
613
+ width: 1.25rem;
614
+ height: 1.25rem;
615
+ }
616
+
617
+ .ui-alert-title {
618
+ font-size: 1rem;
619
+ font-weight: 900;
620
+ margin: 0 0 0.25rem 0;
621
+ }
622
+
623
+ .ui-alert-text {
624
+ font-size: 0.75rem;
625
+ opacity: 0.9;
626
+ margin: 0;
627
+ }
628
+
629
+
630
+ /* ========================================
631
+ Badge / 徽章
632
+ 完全匹配: px-3 py-1 rounded-full text-xs font-bold
633
+ ======================================== */
634
+ .ui-badge {
635
+ display: inline-flex;
636
+ align-items: center;
637
+ padding: 0.25rem 0.75rem;
638
+ font-size: 0.75rem;
639
+ font-weight: 700;
640
+ border-radius: 9999px;
641
+ white-space: nowrap;
642
+ }
643
+
644
+ /* bg-primary/10 text-primary */
645
+ .ui-badge-primary {
646
+ background: rgba(99, 102, 241, 0.1);
647
+ color: var(--ui-primary);
648
+ }
649
+
650
+ /* bg-slate-100 text-slate-600 */
651
+ .ui-badge-secondary {
652
+ background: #f1f5f9;
653
+ color: #475569;
654
+ }
655
+
656
+ .dark .ui-badge-secondary {
657
+ background: #334155;
658
+ color: #cbd5e1;
659
+ }
660
+
661
+ /* bg-emerald-50 text-emerald-600 */
662
+ .ui-badge-success {
663
+ background: #ecfdf5;
664
+ color: #059669;
665
+ }
666
+
667
+ .dark .ui-badge-success {
668
+ background: rgba(16, 185, 129, 0.2);
669
+ color: #34d399;
670
+ }
671
+
672
+ /* bg-red-50 text-red-600 */
673
+ .ui-badge-error {
674
+ background: #fef2f2;
675
+ color: #dc2626;
676
+ }
677
+
678
+ .dark .ui-badge-error {
679
+ background: rgba(239, 68, 68, 0.2);
680
+ color: #f87171;
681
+ }
682
+
683
+ /* ========================================
684
+ Stat Card / 统计卡片
685
+ 完全匹配: bg-slate-50 p-3 rounded-xl
686
+ ======================================== */
687
+ .ui-stat {
688
+ background: #f8fafc;
689
+ padding: 0.75rem;
690
+ border-radius: 0.75rem;
691
+ text-align: center;
692
+ }
693
+
694
+ .dark .ui-stat {
695
+ background: rgba(15, 23, 42, 0.5);
696
+ }
697
+
698
+ /* text-3xl font-black */
699
+ .ui-stat-value {
700
+ font-size: 1.875rem;
701
+ font-weight: 900;
702
+ color: var(--ui-text-dark);
703
+ }
704
+
705
+ .ui-stat-value.primary { color: var(--ui-primary); }
706
+ .ui-stat-value.success { color: #10b981; }
707
+ .ui-stat-value.error { color: #ef4444; }
708
+
709
+ /* text-xs font-bold text-slate-400 uppercase */
710
+ .ui-stat-label {
711
+ font-size: 0.75rem;
712
+ font-weight: 700;
713
+ color: var(--ui-text-light);
714
+ text-transform: uppercase;
715
+ }
716
+
717
+ /* ========================================
718
+ Progress / 进度条
719
+ 完全匹配: h-2.5 bg-slate-100 rounded-full
720
+ ======================================== */
721
+ .ui-progress {
722
+ height: 0.625rem;
723
+ background: #f1f5f9;
724
+ border-radius: 9999px;
725
+ overflow: hidden;
726
+ }
727
+
728
+ .dark .ui-progress {
729
+ background: #334155;
730
+ }
731
+
732
+ .ui-progress-bar {
733
+ height: 100%;
734
+ border-radius: 9999px;
735
+ background: var(--ui-primary);
736
+ transition: width 1s ease-out;
737
+ position: relative;
738
+ }
739
+
740
+ /* 渐变高光效果 */
741
+ .ui-progress-bar::after {
742
+ content: '';
743
+ position: absolute;
744
+ inset: 0;
745
+ background: linear-gradient(to bottom, rgba(255,255,255,0.2), transparent);
746
+ }
747
+
748
+ .ui-progress-bar.success { background: #10b981; }
749
+ .ui-progress-bar.warning { background: #f59e0b; }
750
+ .ui-progress-bar.error { background: #ef4444; }
751
+
752
+ /* ========================================
753
+ Pagination / 分页
754
+ 完全匹配: w-10 h-10 rounded-xl border-2
755
+ ======================================== */
756
+ .ui-pagination {
757
+ display: flex;
758
+ align-items: center;
759
+ justify-content: center;
760
+ gap: 0.5rem;
761
+ }
762
+
763
+ .ui-page-btn {
764
+ width: 2.5rem;
765
+ height: 2.5rem;
766
+ border-radius: 0.75rem;
767
+ background: var(--ui-bg-card);
768
+ border: 2px solid #e2e8f0;
769
+ color: var(--ui-text-muted);
770
+ font-weight: 700;
771
+ font-size: 0.875rem;
772
+ cursor: pointer;
773
+ display: flex;
774
+ align-items: center;
775
+ justify-content: center;
776
+ transition: var(--ui-transition);
777
+ font-family: var(--ui-font);
778
+ }
779
+
780
+ .dark .ui-page-btn {
781
+ border-color: #334155;
782
+ }
783
+
784
+ .ui-page-btn:hover:not(:disabled):not(.active) {
785
+ border-color: var(--ui-primary);
786
+ color: var(--ui-primary);
787
+ transform: translateY(-1px);
788
+ }
789
+
790
+ /* 激活状态: bg-primary text-white border-primary */
791
+ .ui-page-btn.active {
792
+ background: var(--ui-primary);
793
+ border-color: var(--ui-primary);
794
+ color: white;
795
+ box-shadow: 0 2px 8px rgba(99, 102, 241, 0.35);
796
+ }
797
+
798
+ .ui-page-btn:disabled {
799
+ opacity: 0.3;
800
+ cursor: not-allowed;
801
+ }
802
+
803
+ /* 省略号: text-slate-400 font-bold px-2 */
804
+ .ui-page-ellipsis {
805
+ color: var(--ui-text-light);
806
+ font-weight: 700;
807
+ padding: 0 0.5rem;
808
+ }
809
+
810
+
811
+ /* ========================================
812
+ Modal / 模态框
813
+ 完全匹配: fixed inset-0 bg-black/50 backdrop-blur-sm z-50 flex items-center justify-center p-4
814
+ ======================================== */
815
+ .ui-modal-overlay {
816
+ position: fixed;
817
+ inset: 0;
818
+ background: rgba(0, 0, 0, 0.5);
819
+ backdrop-filter: blur(4px);
820
+ -webkit-backdrop-filter: blur(4px);
821
+ z-index: 50;
822
+ display: flex;
823
+ align-items: center;
824
+ justify-content: center;
825
+ padding: 1rem;
826
+ }
827
+
828
+ /* 模态框: bg-white rounded-[2rem] shadow-2xl max-w-sm w-full p-8 relative */
829
+ .ui-modal {
830
+ background: var(--ui-bg-card);
831
+ border-radius: 2rem;
832
+ box-shadow: 0 25px 50px -12px rgb(0 0 0 / 0.25);
833
+ width: 100%;
834
+ max-width: 24rem;
835
+ padding: 2rem;
836
+ position: relative;
837
+ transition: var(--ui-transition-colors);
838
+ animation: modalSlideIn 0.3s ease-out;
839
+ }
840
+
841
+ @keyframes modalSlideIn {
842
+ from {
843
+ opacity: 0;
844
+ transform: translateY(-20px);
845
+ }
846
+ to {
847
+ opacity: 1;
848
+ transform: translateY(0);
849
+ }
850
+ }
851
+
852
+ .ui-modal-lg { max-width: 28rem; } /* max-w-md */
853
+ .ui-modal-xl { max-width: 32rem; } /* max-w-lg */
854
+
855
+ /* 模态框图标: w-16 h-16 rounded-full bg-red-50 flex items-center justify-center mx-auto mb-4 */
856
+ .ui-modal-icon {
857
+ width: 4rem;
858
+ height: 4rem;
859
+ border-radius: 9999px;
860
+ display: flex;
861
+ align-items: center;
862
+ justify-content: center;
863
+ margin: 0 auto 1rem;
864
+ }
865
+
866
+ .ui-modal-icon svg {
867
+ width: 2rem;
868
+ height: 2rem;
869
+ }
870
+
871
+ .ui-modal-icon.danger {
872
+ background: #fef2f2;
873
+ color: #ef4444;
874
+ }
875
+
876
+ .dark .ui-modal-icon.danger {
877
+ background: rgba(239, 68, 68, 0.3);
878
+ }
879
+
880
+ .ui-modal-icon.warning {
881
+ background: #fffbeb;
882
+ color: #f59e0b;
883
+ }
884
+
885
+ .dark .ui-modal-icon.warning {
886
+ background: rgba(245, 158, 11, 0.3);
887
+ }
888
+
889
+ .ui-modal-icon.success {
890
+ background: #ecfdf5;
891
+ color: #10b981;
892
+ }
893
+
894
+ .dark .ui-modal-icon.success {
895
+ background: rgba(16, 185, 129, 0.3);
896
+ }
897
+
898
+ /* 模态框标题: text-xl font-black text-slate-800 mb-2 text-center */
899
+ .ui-modal-title {
900
+ font-size: 1.25rem;
901
+ font-weight: 900;
902
+ color: var(--ui-text-dark);
903
+ text-align: center;
904
+ margin: 0 0 0.5rem 0;
905
+ }
906
+
907
+ /* 模态框描述: text-slate-500 text-center mb-6 */
908
+ .ui-modal-desc {
909
+ color: var(--ui-text-muted);
910
+ text-align: center;
911
+ margin: 0 0 1.5rem 0;
912
+ font-size: 0.875rem;
913
+ }
914
+
915
+ /* 模态框按钮组: flex gap-3 */
916
+ .ui-modal-actions {
917
+ display: flex;
918
+ gap: 0.75rem;
919
+ }
920
+
921
+ /* 取消按钮: flex-1 py-3 rounded-xl border-2 border-slate-100 text-slate-500 font-bold */
922
+ .ui-modal-btn-cancel {
923
+ flex: 1;
924
+ padding: 0.75rem;
925
+ border-radius: 0.75rem;
926
+ border: 2px solid #f1f5f9;
927
+ background: transparent;
928
+ color: var(--ui-text-muted);
929
+ font-weight: 700;
930
+ font-family: var(--ui-font);
931
+ cursor: pointer;
932
+ transition: var(--ui-transition);
933
+ }
934
+
935
+ .dark .ui-modal-btn-cancel {
936
+ border-color: #334155;
937
+ }
938
+
939
+ .ui-modal-btn-cancel:hover {
940
+ background: #f8fafc;
941
+ }
942
+
943
+ .dark .ui-modal-btn-cancel:hover {
944
+ background: #334155;
945
+ }
946
+
947
+ /* 确认按钮: flex-1 py-3 rounded-xl bg-red-500 text-white font-bold */
948
+ .ui-modal-btn-confirm {
949
+ flex: 1;
950
+ padding: 0.75rem;
951
+ border-radius: 0.75rem;
952
+ border: none;
953
+ background: var(--ui-primary);
954
+ color: white;
955
+ font-weight: 700;
956
+ font-family: var(--ui-font);
957
+ cursor: pointer;
958
+ transition: var(--ui-transition);
959
+ }
960
+
961
+ .ui-modal-btn-confirm:hover {
962
+ background: var(--ui-primary-hover);
963
+ box-shadow: 0 4px 12px rgba(99, 102, 241, 0.35);
964
+ }
965
+
966
+ .ui-modal-btn-confirm.danger {
967
+ background: #ef4444;
968
+ }
969
+
970
+ .ui-modal-btn-confirm.danger:hover {
971
+ background: #dc2626;
972
+ box-shadow: 0 4px 12px rgba(239, 68, 68, 0.35);
973
+ }
974
+
975
+ .ui-modal-btn-confirm:disabled {
976
+ opacity: 0.5;
977
+ cursor: not-allowed;
978
+ }
979
+
980
+ /* 关闭按钮: absolute top-6 right-6 w-8 h-8 rounded-full bg-slate-50 */
981
+ .ui-modal-close {
982
+ position: absolute;
983
+ top: 1.5rem;
984
+ right: 1.5rem;
985
+ width: 2rem;
986
+ height: 2rem;
987
+ border-radius: 9999px;
988
+ background: #f8fafc;
989
+ border: none;
990
+ cursor: pointer;
991
+ display: flex;
992
+ align-items: center;
993
+ justify-content: center;
994
+ color: var(--ui-text-light);
995
+ transition: var(--ui-transition);
996
+ }
997
+
998
+ .dark .ui-modal-close {
999
+ background: #334155;
1000
+ }
1001
+
1002
+ .ui-modal-close:hover {
1003
+ background: #f1f5f9;
1004
+ }
1005
+
1006
+ .dark .ui-modal-close:hover {
1007
+ background: #475569;
1008
+ }
1009
+
1010
+ .ui-modal-close svg {
1011
+ width: 1rem;
1012
+ height: 1rem;
1013
+ }
1014
+
1015
+ /* ========================================
1016
+ Sidebar / 侧边栏
1017
+ 完全匹配: fixed top-0 right-0 bottom-0 w-64 bg-white shadow-2xl
1018
+ ======================================== */
1019
+ .ui-sidebar-overlay {
1020
+ position: fixed;
1021
+ inset: 0;
1022
+ background: rgba(0, 0, 0, 0.5);
1023
+ backdrop-filter: blur(4px);
1024
+ -webkit-backdrop-filter: blur(4px);
1025
+ z-index: 50;
1026
+ opacity: 0;
1027
+ visibility: hidden;
1028
+ transition: var(--ui-transition);
1029
+ }
1030
+
1031
+ .ui-sidebar-overlay.open {
1032
+ opacity: 1;
1033
+ visibility: visible;
1034
+ }
1035
+
1036
+ .ui-sidebar {
1037
+ position: fixed;
1038
+ top: 0;
1039
+ right: 0;
1040
+ bottom: 0;
1041
+ width: 16rem;
1042
+ background: var(--ui-bg-card);
1043
+ box-shadow: 0 25px 50px -12px rgb(0 0 0 / 0.25);
1044
+ z-index: 51;
1045
+ transform: translateX(100%);
1046
+ transition: transform 0.3s ease;
1047
+ }
1048
+
1049
+ .ui-sidebar.open {
1050
+ transform: translateX(0);
1051
+ }
1052
+
1053
+ /* 侧边栏头部: h-16 border-b flex items-center justify-between px-4 */
1054
+ .ui-sidebar-header {
1055
+ height: 4rem;
1056
+ border-bottom: 1px solid var(--ui-border);
1057
+ display: flex;
1058
+ align-items: center;
1059
+ justify-content: space-between;
1060
+ padding: 0 1rem;
1061
+ }
1062
+
1063
+ .ui-sidebar-title {
1064
+ font-weight: 700;
1065
+ color: var(--ui-text-dark);
1066
+ }
1067
+
1068
+ /* 侧边栏导航: p-4 space-y-2 */
1069
+ .ui-sidebar-nav {
1070
+ padding: 1rem;
1071
+ display: flex;
1072
+ flex-direction: column;
1073
+ gap: 0.5rem;
1074
+ }
1075
+
1076
+ /* 侧边栏链接: flex items-center space-x-3 px-4 py-3 rounded-xl font-bold */
1077
+ .ui-sidebar-link {
1078
+ display: flex;
1079
+ align-items: center;
1080
+ gap: 0.75rem;
1081
+ padding: 0.75rem 1rem;
1082
+ border-radius: 0.75rem;
1083
+ font-weight: 700;
1084
+ color: var(--ui-text);
1085
+ text-decoration: none;
1086
+ transition: var(--ui-transition);
1087
+ }
1088
+
1089
+ .ui-sidebar-link:hover {
1090
+ background: #f8fafc;
1091
+ }
1092
+
1093
+ .dark .ui-sidebar-link:hover {
1094
+ background: #334155;
1095
+ }
1096
+
1097
+ /* 激活状态: bg-primary/10 text-primary */
1098
+ .ui-sidebar-link.active {
1099
+ background: rgba(99, 102, 241, 0.1);
1100
+ color: var(--ui-primary);
1101
+ }
1102
+
1103
+ .dark .ui-sidebar-link.active {
1104
+ background: rgba(99, 102, 241, 0.2);
1105
+ }
1106
+
1107
+
1108
+ /* ========================================
1109
+ Option / 选项卡片(答题用)
1110
+ 完全匹配: p-4 rounded-2xl border-2 transition-all
1111
+ ======================================== */
1112
+ .ui-option {
1113
+ width: 100%;
1114
+ text-align: left;
1115
+ padding: 1rem;
1116
+ border-radius: 1rem;
1117
+ border: 2px solid var(--ui-border-dark);
1118
+ background: var(--ui-bg-card);
1119
+ cursor: pointer;
1120
+ display: flex;
1121
+ align-items: center;
1122
+ gap: 1rem;
1123
+ transition: var(--ui-transition);
1124
+ font-family: var(--ui-font);
1125
+ }
1126
+
1127
+ .ui-option:hover:not(:disabled):not(.selected):not(.correct):not(.wrong) {
1128
+ border-color: var(--ui-primary);
1129
+ background: rgba(99, 102, 241, 0.02);
1130
+ transform: translateX(4px);
1131
+ }
1132
+
1133
+ /* 选中状态 */
1134
+ .ui-option.selected {
1135
+ border-color: var(--ui-primary);
1136
+ background: rgba(99, 102, 241, 0.05);
1137
+ }
1138
+
1139
+ /* 正确: border-green-500 bg-green-50 */
1140
+ .ui-option.correct {
1141
+ border-color: #22c55e;
1142
+ background: #f0fdf4;
1143
+ }
1144
+
1145
+ .dark .ui-option.correct {
1146
+ background: rgba(34, 197, 94, 0.15);
1147
+ }
1148
+
1149
+ /* 错误: border-red-500 bg-red-50 */
1150
+ .ui-option.wrong {
1151
+ border-color: #ef4444;
1152
+ background: #fef2f2;
1153
+ }
1154
+
1155
+ .dark .ui-option.wrong {
1156
+ background: rgba(239, 68, 68, 0.15);
1157
+ }
1158
+
1159
+ /* 选项键: w-10 h-10 rounded-xl bg-slate-100 font-bold text-lg */
1160
+ .ui-option-key {
1161
+ width: 2.5rem;
1162
+ height: 2.5rem;
1163
+ border-radius: 0.75rem;
1164
+ background: #f1f5f9;
1165
+ color: var(--ui-text-light);
1166
+ display: flex;
1167
+ align-items: center;
1168
+ justify-content: center;
1169
+ font-weight: 700;
1170
+ font-size: 1rem;
1171
+ flex-shrink: 0;
1172
+ transition: var(--ui-transition);
1173
+ }
1174
+
1175
+ .dark .ui-option-key {
1176
+ background: #334155;
1177
+ }
1178
+
1179
+ .ui-option.selected .ui-option-key,
1180
+ .ui-option:hover:not(:disabled) .ui-option-key {
1181
+ background: var(--ui-primary);
1182
+ color: white;
1183
+ }
1184
+
1185
+ .ui-option-text {
1186
+ font-weight: 700;
1187
+ color: var(--ui-text-dark);
1188
+ }
1189
+
1190
+ /* ========================================
1191
+ Tabs / 标签页
1192
+ 完全匹配: flex bg-slate-200 p-1 rounded-lg
1193
+ ======================================== */
1194
+ .ui-tabs {
1195
+ display: flex;
1196
+ background: #e2e8f0;
1197
+ padding: 0.25rem;
1198
+ border-radius: 0.5rem;
1199
+ gap: 0.25rem;
1200
+ }
1201
+
1202
+ .dark .ui-tabs {
1203
+ background: #334155;
1204
+ }
1205
+
1206
+ /* px-4 py-1 text-sm font-bold rounded-md */
1207
+ .ui-tab {
1208
+ flex: 1;
1209
+ padding: 0.25rem 1rem;
1210
+ font-size: 0.875rem;
1211
+ font-weight: 700;
1212
+ color: var(--ui-text-muted);
1213
+ background: none;
1214
+ border: none;
1215
+ border-radius: 0.375rem;
1216
+ cursor: pointer;
1217
+ transition: var(--ui-transition);
1218
+ font-family: var(--ui-font);
1219
+ }
1220
+
1221
+ .ui-tab:hover:not(.active) {
1222
+ color: var(--ui-text-dark);
1223
+ }
1224
+
1225
+ /* 激活: bg-white shadow */
1226
+ .ui-tab.active {
1227
+ background: var(--ui-bg-card);
1228
+ color: var(--ui-text-dark);
1229
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.08);
1230
+ }
1231
+
1232
+ .ui-tab:active:not(.active) {
1233
+ transform: scale(0.97);
1234
+ }
1235
+
1236
+ /* ========================================
1237
+ Dropdown / 下拉菜单
1238
+ 完全匹配: absolute mt-2 bg-white border rounded-xl shadow-lg
1239
+ ======================================== */
1240
+ .ui-dropdown {
1241
+ position: relative;
1242
+ display: inline-block;
1243
+ }
1244
+
1245
+ .ui-dropdown-menu {
1246
+ position: absolute;
1247
+ top: 100%;
1248
+ left: 0;
1249
+ right: 0;
1250
+ margin-top: 0.5rem;
1251
+ background: var(--ui-bg-card);
1252
+ border: 1px solid var(--ui-border);
1253
+ border-radius: 0.75rem;
1254
+ box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
1255
+ overflow: hidden;
1256
+ z-index: 20;
1257
+ opacity: 0;
1258
+ visibility: hidden;
1259
+ transform: translateY(-5px);
1260
+ transition: var(--ui-transition);
1261
+ }
1262
+
1263
+ .ui-dropdown.open .ui-dropdown-menu {
1264
+ opacity: 1;
1265
+ visibility: visible;
1266
+ transform: translateY(0);
1267
+ }
1268
+
1269
+ /* px-4 py-2.5 text-sm font-bold hover:bg-primary/5 */
1270
+ .ui-dropdown-item {
1271
+ display: block;
1272
+ width: 100%;
1273
+ padding: 0.625rem 1rem;
1274
+ font-size: 0.875rem;
1275
+ font-weight: 700;
1276
+ color: var(--ui-text);
1277
+ text-align: left;
1278
+ background: none;
1279
+ border: none;
1280
+ cursor: pointer;
1281
+ transition: var(--ui-transition);
1282
+ font-family: var(--ui-font);
1283
+ }
1284
+
1285
+ .ui-dropdown-item:hover {
1286
+ background: rgba(99, 102, 241, 0.08);
1287
+ color: var(--ui-primary);
1288
+ padding-left: 1.25rem;
1289
+ }
1290
+
1291
+ .dark .ui-dropdown-item:hover {
1292
+ background: #334155;
1293
+ }
1294
+
1295
+ /* ========================================
1296
+ Loading / 加载状态
1297
+ 完全匹配: w-12 h-12 border-4 border-primary/30 border-t-primary rounded-full animate-spin
1298
+ ======================================== */
1299
+ .ui-spinner {
1300
+ width: 3rem;
1301
+ height: 3rem;
1302
+ border: 4px solid rgba(99, 102, 241, 0.3);
1303
+ border-top-color: var(--ui-primary);
1304
+ border-radius: 9999px;
1305
+ animation: spin 0.8s linear infinite;
1306
+ }
1307
+
1308
+ .ui-spinner-sm {
1309
+ width: 1.25rem;
1310
+ height: 1.25rem;
1311
+ border-width: 2px;
1312
+ }
1313
+
1314
+ @keyframes spin {
1315
+ to { transform: rotate(360deg); }
1316
+ }
1317
+
1318
+ /* 骨架屏 - Discord 风格 */
1319
+ .ui-skeleton {
1320
+ background: #e3e5e8;
1321
+ border-radius: 0.25rem;
1322
+ animation: skeleton-pulse 1.5s ease-in-out infinite;
1323
+ }
1324
+
1325
+ .dark .ui-skeleton {
1326
+ background: #3f4147;
1327
+ }
1328
+
1329
+ @keyframes skeleton-pulse {
1330
+ 0%, 100% { opacity: 1; }
1331
+ 50% { opacity: 0.4; }
1332
+ }
1333
+
1334
+ /* 骨架屏变体 */
1335
+ .ui-skeleton-text {
1336
+ height: 1rem;
1337
+ margin-bottom: 0.5rem;
1338
+ }
1339
+
1340
+ .ui-skeleton-text:last-child {
1341
+ width: 60%;
1342
+ }
1343
+
1344
+ .ui-skeleton-avatar {
1345
+ width: 2.5rem;
1346
+ height: 2.5rem;
1347
+ border-radius: 9999px;
1348
+ }
1349
+
1350
+ .ui-skeleton-btn {
1351
+ height: 2.25rem;
1352
+ width: 5rem;
1353
+ border-radius: 0.25rem;
1354
+ }
1355
+
1356
+ /* ========================================
1357
+ Empty State / 空状态
1358
+ 完全匹配: text-center p-12
1359
+ ======================================== */
1360
+ .ui-empty {
1361
+ text-align: center;
1362
+ padding: 3rem 2rem;
1363
+ }
1364
+
1365
+ /* w-24 h-24 bg-slate-100 rounded-full mx-auto mb-6 */
1366
+ .ui-empty-icon {
1367
+ width: 6rem;
1368
+ height: 6rem;
1369
+ margin: 0 auto 1.5rem;
1370
+ background: #f1f5f9;
1371
+ border-radius: 9999px;
1372
+ display: flex;
1373
+ align-items: center;
1374
+ justify-content: center;
1375
+ color: var(--ui-text-light);
1376
+ font-size: 3rem;
1377
+ }
1378
+
1379
+ .dark .ui-empty-icon {
1380
+ background: #334155;
1381
+ }
1382
+
1383
+ /* text-xl font-bold mb-2 */
1384
+ .ui-empty-title {
1385
+ font-size: 1.25rem;
1386
+ font-weight: 700;
1387
+ color: var(--ui-text-dark);
1388
+ margin: 0 0 0.5rem 0;
1389
+ }
1390
+
1391
+ /* text-slate-500 mb-8 max-w-sm mx-auto */
1392
+ .ui-empty-text {
1393
+ color: var(--ui-text-muted);
1394
+ margin: 0 auto 2rem;
1395
+ max-width: 20rem;
1396
+ }
1397
+
1398
+ /* ========================================
1399
+ Utilities / 工具类
1400
+ ======================================== */
1401
+ .ui-text-primary { color: var(--ui-primary) !important; }
1402
+ .ui-text-success { color: #10b981 !important; }
1403
+ .ui-text-error { color: #ef4444 !important; }
1404
+ .ui-text-warning { color: #f59e0b !important; }
1405
+ .ui-text-muted { color: var(--ui-text-muted) !important; }
1406
+
1407
+ .ui-font-bold { font-weight: 700; }
1408
+ .ui-font-black { font-weight: 900; }
1409
+
1410
+ .ui-flex { display: flex; }
1411
+ .ui-flex-col { flex-direction: column; }
1412
+ .ui-items-center { align-items: center; }
1413
+ .ui-items-start { align-items: flex-start; }
1414
+ .ui-justify-center { justify-content: center; }
1415
+ .ui-justify-between { justify-content: space-between; }
1416
+ .ui-gap-2 { gap: 0.5rem; }
1417
+ .ui-gap-3 { gap: 0.75rem; }
1418
+ .ui-gap-4 { gap: 1rem; }
1419
+ .ui-gap-6 { gap: 1.5rem; }
1420
+
1421
+ .ui-w-full { width: 100%; }
1422
+ .ui-text-center { text-align: center; }
1423
+ .ui-text-sm { font-size: 0.875rem; }
1424
+ .ui-text-xs { font-size: 0.75rem; }
1425
+
1426
+ .ui-mt-4 { margin-top: 1rem; }
1427
+ .ui-mt-6 { margin-top: 1.5rem; }
1428
+ .ui-mb-4 { margin-bottom: 1rem; }
1429
+ .ui-mb-6 { margin-bottom: 1.5rem; }
1430
+
1431
+ .ui-space-y-4 > * + * { margin-top: 1rem; }
1432
+ .ui-space-y-5 > * + * { margin-top: 1.25rem; }
1433
+ .ui-space-y-6 > * + * { margin-top: 1.5rem; }
1434
+
1435
+ .ui-hidden { display: none; }
1436
+
1437
+ @media (max-width: 768px) {
1438
+ .ui-hide-mobile { display: none !important; }
1439
+ }
1440
+
1441
+ @media (min-width: 769px) {
1442
+ .ui-hide-desktop { display: none !important; }
1443
+ }
1444
+
1445
+ /* ========================================
1446
+ Avatar / 头像
1447
+ ======================================== */
1448
+ .ui-avatar {
1449
+ display: inline-flex;
1450
+ align-items: center;
1451
+ justify-content: center;
1452
+ border-radius: 9999px;
1453
+ background: var(--ui-primary);
1454
+ color: white;
1455
+ font-weight: 700;
1456
+ overflow: hidden;
1457
+ flex-shrink: 0;
1458
+ }
1459
+
1460
+ .ui-avatar img {
1461
+ width: 100%;
1462
+ height: 100%;
1463
+ object-fit: cover;
1464
+ }
1465
+
1466
+ .ui-avatar-xs { width: 1.5rem; height: 1.5rem; font-size: 0.625rem; }
1467
+ .ui-avatar-sm { width: 2rem; height: 2rem; font-size: 0.75rem; }
1468
+ .ui-avatar-md { width: 2.5rem; height: 2.5rem; font-size: 0.875rem; }
1469
+ .ui-avatar-lg { width: 3rem; height: 3rem; font-size: 1rem; }
1470
+ .ui-avatar-xl { width: 4rem; height: 4rem; font-size: 1.25rem; }
1471
+
1472
+ .ui-avatar-group {
1473
+ display: flex;
1474
+ }
1475
+
1476
+ .ui-avatar-group .ui-avatar {
1477
+ border: 2px solid var(--ui-bg-card);
1478
+ margin-left: -0.5rem;
1479
+ }
1480
+
1481
+ .ui-avatar-group .ui-avatar:first-child {
1482
+ margin-left: 0;
1483
+ }
1484
+
1485
+ /* 在线状态 */
1486
+ .ui-avatar-wrapper {
1487
+ position: relative;
1488
+ display: inline-block;
1489
+ }
1490
+
1491
+ .ui-avatar-status {
1492
+ position: absolute;
1493
+ bottom: 0;
1494
+ right: 0;
1495
+ width: 0.75rem;
1496
+ height: 0.75rem;
1497
+ border-radius: 9999px;
1498
+ border: 2px solid var(--ui-bg-card);
1499
+ }
1500
+
1501
+ .ui-avatar-status.online { background: #22c55e; }
1502
+ .ui-avatar-status.offline { background: #94a3b8; }
1503
+ .ui-avatar-status.busy { background: #ef4444; }
1504
+ .ui-avatar-status.away { background: #f59e0b; }
1505
+
1506
+ /* ========================================
1507
+ Switch / 开关
1508
+ ======================================== */
1509
+ .ui-switch {
1510
+ position: relative;
1511
+ display: inline-flex;
1512
+ align-items: center;
1513
+ gap: 0.5rem;
1514
+ cursor: pointer;
1515
+ }
1516
+
1517
+ .ui-switch input {
1518
+ position: absolute;
1519
+ opacity: 0;
1520
+ width: 0;
1521
+ height: 0;
1522
+ }
1523
+
1524
+ .ui-switch-track {
1525
+ width: 2.75rem;
1526
+ height: 1.5rem;
1527
+ background: #e2e8f0;
1528
+ border-radius: 9999px;
1529
+ transition: all 0.2s ease;
1530
+ position: relative;
1531
+ }
1532
+
1533
+ .dark .ui-switch-track {
1534
+ background: #475569;
1535
+ }
1536
+
1537
+ .ui-switch-thumb {
1538
+ position: absolute;
1539
+ top: 0.125rem;
1540
+ left: 0.125rem;
1541
+ width: 1.25rem;
1542
+ height: 1.25rem;
1543
+ background: white;
1544
+ border-radius: 9999px;
1545
+ box-shadow: 0 1px 3px rgba(0,0,0,0.2);
1546
+ transition: all 0.2s ease;
1547
+ }
1548
+
1549
+ .ui-switch input:checked + .ui-switch-track {
1550
+ background: var(--ui-primary);
1551
+ }
1552
+
1553
+ .ui-switch input:checked + .ui-switch-track .ui-switch-thumb {
1554
+ transform: translateX(1.25rem);
1555
+ }
1556
+
1557
+ .ui-switch input:focus + .ui-switch-track {
1558
+ box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.25);
1559
+ }
1560
+
1561
+ .ui-switch-label {
1562
+ font-size: 0.875rem;
1563
+ font-weight: 600;
1564
+ color: var(--ui-text);
1565
+ }
1566
+
1567
+ /* ========================================
1568
+ Radio / 单选按钮组
1569
+ ======================================== */
1570
+ .ui-radio-group {
1571
+ display: flex;
1572
+ flex-direction: column;
1573
+ gap: 0.5rem;
1574
+ }
1575
+
1576
+ .ui-radio-group.horizontal {
1577
+ flex-direction: row;
1578
+ gap: 1rem;
1579
+ }
1580
+
1581
+ .ui-radio {
1582
+ display: inline-flex;
1583
+ align-items: center;
1584
+ gap: 0.5rem;
1585
+ cursor: pointer;
1586
+ font-size: 0.875rem;
1587
+ font-weight: 600;
1588
+ color: var(--ui-text);
1589
+ }
1590
+
1591
+ .ui-radio input {
1592
+ position: absolute;
1593
+ opacity: 0;
1594
+ }
1595
+
1596
+ .ui-radio-mark {
1597
+ width: 1.25rem;
1598
+ height: 1.25rem;
1599
+ border: 2px solid #cbd5e1;
1600
+ border-radius: 9999px;
1601
+ display: flex;
1602
+ align-items: center;
1603
+ justify-content: center;
1604
+ transition: all 0.15s ease;
1605
+ }
1606
+
1607
+ .dark .ui-radio-mark {
1608
+ border-color: #475569;
1609
+ }
1610
+
1611
+ .ui-radio-mark::after {
1612
+ content: '';
1613
+ width: 0.5rem;
1614
+ height: 0.5rem;
1615
+ background: var(--ui-primary);
1616
+ border-radius: 9999px;
1617
+ transform: scale(0);
1618
+ transition: transform 0.15s ease;
1619
+ }
1620
+
1621
+ .ui-radio input:checked + .ui-radio-mark {
1622
+ border-color: var(--ui-primary);
1623
+ }
1624
+
1625
+ .ui-radio input:checked + .ui-radio-mark::after {
1626
+ transform: scale(1);
1627
+ }
1628
+
1629
+ .ui-radio input:focus + .ui-radio-mark {
1630
+ box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.25);
1631
+ }
1632
+
1633
+ /* ========================================
1634
+ Select 已移除,使用 Dropdown 替代
1635
+ ======================================== */
1636
+
1637
+ /* ========================================
1638
+ Table / 表格
1639
+ ======================================== */
1640
+ .ui-table-wrapper {
1641
+ overflow-x: auto;
1642
+ border-radius: 1rem;
1643
+ border: 1px solid var(--ui-border);
1644
+ }
1645
+
1646
+ .ui-table {
1647
+ width: 100%;
1648
+ border-collapse: collapse;
1649
+ font-size: 0.875rem;
1650
+ }
1651
+
1652
+ .ui-table th {
1653
+ background: var(--ui-bg-input);
1654
+ padding: 0.75rem 1rem;
1655
+ text-align: left;
1656
+ font-weight: 700;
1657
+ font-size: 0.75rem;
1658
+ text-transform: uppercase;
1659
+ letter-spacing: 0.05em;
1660
+ color: var(--ui-text-light);
1661
+ border-bottom: 1px solid var(--ui-border);
1662
+ }
1663
+
1664
+ .ui-table td {
1665
+ padding: 0.75rem 1rem;
1666
+ color: var(--ui-text);
1667
+ border-bottom: 1px solid var(--ui-border);
1668
+ }
1669
+
1670
+ .ui-table tr:last-child td {
1671
+ border-bottom: none;
1672
+ }
1673
+
1674
+ .ui-table tbody tr {
1675
+ transition: background 0.15s ease;
1676
+ }
1677
+
1678
+ .ui-table tbody tr:hover {
1679
+ background: rgba(99, 102, 241, 0.04);
1680
+ }
1681
+
1682
+ .dark .ui-table tbody tr:hover {
1683
+ background: rgba(99, 102, 241, 0.1);
1684
+ }
1685
+
1686
+ .ui-table-striped tbody tr:nth-child(even) {
1687
+ background: var(--ui-bg-input);
1688
+ }
1689
+
1690
+ /* ========================================
1691
+ List / 列表
1692
+ ======================================== */
1693
+ .ui-list {
1694
+ list-style: none;
1695
+ padding: 0;
1696
+ margin: 0;
1697
+ }
1698
+
1699
+ .ui-list-item {
1700
+ display: flex;
1701
+ align-items: center;
1702
+ gap: 0.75rem;
1703
+ padding: 0.75rem 1rem;
1704
+ border-bottom: 1px solid var(--ui-border);
1705
+ transition: background 0.15s ease;
1706
+ }
1707
+
1708
+ .ui-list-item:last-child {
1709
+ border-bottom: none;
1710
+ }
1711
+
1712
+ .ui-list-item:hover {
1713
+ background: rgba(99, 102, 241, 0.04);
1714
+ }
1715
+
1716
+ .ui-list-item-icon {
1717
+ width: 1.25rem;
1718
+ height: 1.25rem;
1719
+ color: var(--ui-text-light);
1720
+ flex-shrink: 0;
1721
+ }
1722
+
1723
+ .ui-list-item-content {
1724
+ flex: 1;
1725
+ min-width: 0;
1726
+ }
1727
+
1728
+ .ui-list-item-title {
1729
+ font-weight: 700;
1730
+ color: var(--ui-text-dark);
1731
+ font-size: 0.875rem;
1732
+ }
1733
+
1734
+ .ui-list-item-desc {
1735
+ font-size: 0.75rem;
1736
+ color: var(--ui-text-muted);
1737
+ margin-top: 0.125rem;
1738
+ }
1739
+
1740
+ .ui-list-item-action {
1741
+ flex-shrink: 0;
1742
+ }
1743
+
1744
+ /* ========================================
1745
+ Divider / 分隔线
1746
+ ======================================== */
1747
+ .ui-divider {
1748
+ height: 1px;
1749
+ background: var(--ui-border);
1750
+ margin: 1rem 0;
1751
+ }
1752
+
1753
+ .ui-divider-text {
1754
+ display: flex;
1755
+ align-items: center;
1756
+ gap: 1rem;
1757
+ color: var(--ui-text-light);
1758
+ font-size: 0.75rem;
1759
+ font-weight: 700;
1760
+ text-transform: uppercase;
1761
+ }
1762
+
1763
+ .ui-divider-text::before,
1764
+ .ui-divider-text::after {
1765
+ content: '';
1766
+ flex: 1;
1767
+ height: 1px;
1768
+ background: var(--ui-border);
1769
+ }
1770
+
1771
+ /* ========================================
1772
+ Tag / 可关闭标签
1773
+ ======================================== */
1774
+ .ui-tag {
1775
+ display: inline-flex;
1776
+ align-items: center;
1777
+ gap: 0.375rem;
1778
+ padding: 0.25rem 0.625rem;
1779
+ font-size: 0.75rem;
1780
+ font-weight: 600;
1781
+ border-radius: 0.375rem;
1782
+ background: var(--ui-bg-input);
1783
+ color: var(--ui-text);
1784
+ }
1785
+
1786
+ .ui-tag-close {
1787
+ width: 1rem;
1788
+ height: 1rem;
1789
+ display: flex;
1790
+ align-items: center;
1791
+ justify-content: center;
1792
+ border-radius: 0.25rem;
1793
+ cursor: pointer;
1794
+ opacity: 0.6;
1795
+ transition: all 0.15s ease;
1796
+ }
1797
+
1798
+ .ui-tag-close:hover {
1799
+ opacity: 1;
1800
+ background: rgba(0,0,0,0.1);
1801
+ }
1802
+
1803
+ .ui-tag-primary { background: rgba(99, 102, 241, 0.1); color: var(--ui-primary); }
1804
+ .ui-tag-success { background: rgba(16, 185, 129, 0.1); color: #059669; }
1805
+ .ui-tag-error { background: rgba(239, 68, 68, 0.1); color: #dc2626; }
1806
+ .ui-tag-warning { background: rgba(245, 158, 11, 0.1); color: #d97706; }
1807
+
1808
+ /* ========================================
1809
+ Breadcrumb / 面包屑
1810
+ ======================================== */
1811
+ .ui-breadcrumb {
1812
+ display: flex;
1813
+ align-items: center;
1814
+ gap: 0.5rem;
1815
+ font-size: 0.875rem;
1816
+ }
1817
+
1818
+ .ui-breadcrumb-item {
1819
+ display: flex;
1820
+ align-items: center;
1821
+ gap: 0.5rem;
1822
+ color: var(--ui-text-muted);
1823
+ text-decoration: none;
1824
+ font-weight: 600;
1825
+ transition: color 0.15s ease;
1826
+ }
1827
+
1828
+ .ui-breadcrumb-item:hover {
1829
+ color: var(--ui-primary);
1830
+ }
1831
+
1832
+ .ui-breadcrumb-item.active {
1833
+ color: var(--ui-text-dark);
1834
+ pointer-events: none;
1835
+ }
1836
+
1837
+ .ui-breadcrumb-sep {
1838
+ color: var(--ui-text-light);
1839
+ }
1840
+
1841
+ /* ========================================
1842
+ Accordion / 手风琴
1843
+ ======================================== */
1844
+ .ui-accordion {
1845
+ border: 1px solid var(--ui-border);
1846
+ border-radius: 0.75rem;
1847
+ overflow: hidden;
1848
+ }
1849
+
1850
+ .ui-accordion-item {
1851
+ border-bottom: 1px solid var(--ui-border);
1852
+ }
1853
+
1854
+ .ui-accordion-item:last-child {
1855
+ border-bottom: none;
1856
+ }
1857
+
1858
+ .ui-accordion-header {
1859
+ width: 100%;
1860
+ display: flex;
1861
+ align-items: center;
1862
+ justify-content: space-between;
1863
+ padding: 1rem;
1864
+ background: none;
1865
+ border: none;
1866
+ cursor: pointer;
1867
+ font-family: var(--ui-font);
1868
+ font-size: 0.875rem;
1869
+ font-weight: 700;
1870
+ color: var(--ui-text-dark);
1871
+ text-align: left;
1872
+ transition: background 0.15s ease;
1873
+ }
1874
+
1875
+ .ui-accordion-header:hover {
1876
+ background: var(--ui-bg-input);
1877
+ }
1878
+
1879
+ .ui-accordion-icon {
1880
+ width: 1.25rem;
1881
+ height: 1.25rem;
1882
+ color: var(--ui-text-light);
1883
+ transition: transform 0.2s ease;
1884
+ }
1885
+
1886
+ .ui-accordion-item.open .ui-accordion-icon {
1887
+ transform: rotate(180deg);
1888
+ }
1889
+
1890
+ .ui-accordion-content {
1891
+ max-height: 0;
1892
+ overflow: hidden;
1893
+ transition: max-height 0.3s ease;
1894
+ }
1895
+
1896
+ .ui-accordion-item.open .ui-accordion-content {
1897
+ max-height: 500px;
1898
+ }
1899
+
1900
+ .ui-accordion-body {
1901
+ padding: 0 1rem 1rem;
1902
+ font-size: 0.875rem;
1903
+ color: var(--ui-text-muted);
1904
+ }
1905
+
1906
+ /* ========================================
1907
+ Tooltip / 工具提示
1908
+ ======================================== */
1909
+ .ui-tooltip {
1910
+ position: relative;
1911
+ display: inline-block;
1912
+ }
1913
+
1914
+ .ui-tooltip-content {
1915
+ position: absolute;
1916
+ bottom: 100%;
1917
+ left: 50%;
1918
+ transform: translateX(-50%) translateY(-0.5rem);
1919
+ padding: 0.5rem 0.75rem;
1920
+ background: #1e293b;
1921
+ color: white;
1922
+ font-size: 0.75rem;
1923
+ font-weight: 600;
1924
+ border-radius: 0.5rem;
1925
+ white-space: nowrap;
1926
+ opacity: 0;
1927
+ visibility: hidden;
1928
+ transition: all 0.15s ease;
1929
+ z-index: 100;
1930
+ }
1931
+
1932
+ .ui-tooltip-content::after {
1933
+ content: '';
1934
+ position: absolute;
1935
+ top: 100%;
1936
+ left: 50%;
1937
+ transform: translateX(-50%);
1938
+ border: 6px solid transparent;
1939
+ border-top-color: #1e293b;
1940
+ }
1941
+
1942
+ .ui-tooltip:hover .ui-tooltip-content {
1943
+ opacity: 1;
1944
+ visibility: visible;
1945
+ transform: translateX(-50%) translateY(-0.75rem);
1946
+ }
1947
+
1948
+ /* 位置变体 */
1949
+ .ui-tooltip-bottom .ui-tooltip-content {
1950
+ bottom: auto;
1951
+ top: 100%;
1952
+ transform: translateX(-50%) translateY(0.5rem);
1953
+ }
1954
+
1955
+ .ui-tooltip-bottom .ui-tooltip-content::after {
1956
+ top: auto;
1957
+ bottom: 100%;
1958
+ border-top-color: transparent;
1959
+ border-bottom-color: #1e293b;
1960
+ }
1961
+
1962
+ .ui-tooltip-bottom:hover .ui-tooltip-content {
1963
+ transform: translateX(-50%) translateY(0.75rem);
1964
+ }
1965
+
1966
+ /* ========================================
1967
+ Notification Dot / 通知点
1968
+ ======================================== */
1969
+ .ui-dot {
1970
+ position: relative;
1971
+ display: inline-block;
1972
+ }
1973
+
1974
+ .ui-dot::after {
1975
+ content: '';
1976
+ position: absolute;
1977
+ top: -2px;
1978
+ right: -2px;
1979
+ width: 0.5rem;
1980
+ height: 0.5rem;
1981
+ background: #ef4444;
1982
+ border-radius: 9999px;
1983
+ border: 2px solid var(--ui-bg-card);
1984
+ }
1985
+
1986
+ .ui-dot-count {
1987
+ position: absolute;
1988
+ top: -0.5rem;
1989
+ right: -0.5rem;
1990
+ min-width: 1.25rem;
1991
+ height: 1.25rem;
1992
+ padding: 0 0.375rem;
1993
+ background: #ef4444;
1994
+ color: white;
1995
+ font-size: 0.625rem;
1996
+ font-weight: 700;
1997
+ border-radius: 9999px;
1998
+ display: flex;
1999
+ align-items: center;
2000
+ justify-content: center;
2001
+ border: 2px solid var(--ui-bg-card);
2002
+ }
2003
+
2004
+ /* ========================================
2005
+ Kbd / 键盘按键
2006
+ ======================================== */
2007
+ .ui-kbd {
2008
+ display: inline-flex;
2009
+ align-items: center;
2010
+ justify-content: center;
2011
+ min-width: 1.5rem;
2012
+ height: 1.5rem;
2013
+ padding: 0 0.375rem;
2014
+ background: var(--ui-bg-input);
2015
+ border: 1px solid var(--ui-border-dark);
2016
+ border-radius: 0.25rem;
2017
+ font-family: monospace;
2018
+ font-size: 0.75rem;
2019
+ font-weight: 600;
2020
+ color: var(--ui-text-muted);
2021
+ box-shadow: 0 2px 0 var(--ui-border-dark);
2022
+ }
2023
+
2024
+ /* ========================================
2025
+ Code / 代码块
2026
+ ======================================== */
2027
+ .ui-code {
2028
+ display: inline;
2029
+ padding: 0.125rem 0.375rem;
2030
+ background: var(--ui-bg-input);
2031
+ border-radius: 0.25rem;
2032
+ font-family: 'Fira Code', 'Consolas', monospace;
2033
+ font-size: 0.8125rem;
2034
+ color: #e879f9;
2035
+ }
2036
+
2037
+ .dark .ui-code {
2038
+ background: #0f172a;
2039
+ }
2040
+
2041
+ .ui-code-block {
2042
+ display: block;
2043
+ padding: 1rem;
2044
+ background: #1e293b;
2045
+ border-radius: 0.75rem;
2046
+ font-family: 'Fira Code', 'Consolas', monospace;
2047
+ font-size: 0.8125rem;
2048
+ color: #e2e8f0;
2049
+ overflow-x: auto;
2050
+ line-height: 1.6;
2051
+ }
2052
+
2053
+ /* ========================================
2054
+ Callout / 提示块 - Discord 风格
2055
+ ======================================== */
2056
+ .ui-callout {
2057
+ display: flex;
2058
+ gap: 0.75rem;
2059
+ padding: 1rem;
2060
+ border-radius: 0.5rem;
2061
+ background: #f2f3f5;
2062
+ }
2063
+
2064
+ .dark .ui-callout {
2065
+ background: #2b2d31;
2066
+ }
2067
+
2068
+ .ui-callout-icon {
2069
+ flex-shrink: 0;
2070
+ width: 1.25rem;
2071
+ height: 1.25rem;
2072
+ color: #5865f2;
2073
+ }
2074
+
2075
+ .ui-callout-content {
2076
+ flex: 1;
2077
+ font-size: 0.875rem;
2078
+ color: var(--ui-text);
2079
+ line-height: 1.5;
2080
+ }
2081
+
2082
+ .ui-callout-title {
2083
+ font-weight: 700;
2084
+ color: var(--ui-text-dark);
2085
+ margin-bottom: 0.25rem;
2086
+ }
2087
+
2088
+ .ui-callout-warning {
2089
+ background: rgba(250, 166, 26, 0.1);
2090
+ }
2091
+
2092
+ .dark .ui-callout-warning {
2093
+ background: rgba(250, 166, 26, 0.15);
2094
+ }
2095
+
2096
+ .ui-callout-warning .ui-callout-icon { color: #faa61a; }
2097
+
2098
+ .ui-callout-error {
2099
+ background: rgba(237, 66, 69, 0.1);
2100
+ }
2101
+
2102
+ .dark .ui-callout-error {
2103
+ background: rgba(237, 66, 69, 0.15);
2104
+ }
2105
+
2106
+ .ui-callout-error .ui-callout-icon { color: #ed4245; }
2107
+
2108
+ .ui-callout-success {
2109
+ background: rgba(59, 165, 92, 0.1);
2110
+ }
2111
+
2112
+ .dark .ui-callout-success {
2113
+ background: rgba(59, 165, 92, 0.15);
2114
+ }
2115
+
2116
+ .ui-callout-success .ui-callout-icon { color: #3ba55c; }