weifuwu 0.58.0 → 0.59.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.
@@ -1,6 +1,49 @@
1
1
  /* weifuwu/layout — 基于 CSS 标准的布局原语 */
2
2
 
3
- /* weifuwu/theme — 设计 Token */
3
+ @layer tokens, base, layout, utilities, components;
4
+
5
+ @layer tokens {
6
+ /* weifuwu/theme — 设计 Token(Primitive + Semantic 双层)
7
+ *
8
+ * 原始层(Primitive):色值/暗色值只定义一次。品牌换色/暗色调校只改这一层。
9
+ * 语义层(Semantic):组件消费这一层。主题切换 = 覆盖语义映射(见 _dark.css)。
10
+ */
11
+
12
+ /* ══ 原始层(Primitive)══ */
13
+ :root {
14
+ /* 品牌(覆盖 --wf-brand-500 即换主题色,全站跟随) */
15
+ --wf-brand-500: #4f6ef7;
16
+ --wf-brand-600: #3b5ae0;
17
+ --wf-brand-50: #eef1ff;
18
+
19
+ /* 语义原始色 */
20
+ --wf-green-500: #22c55e; --wf-green-50: #f0fdf4;
21
+ --wf-amber-500: #f59e0b; --wf-amber-50: #fffbeb;
22
+ --wf-red-500: #ef4444; --wf-red-50: #fef2f2;
23
+ --wf-sky-500: #1677ff; --wf-sky-50: #e6f4ff;
24
+
25
+ /* 中性 */
26
+ --wf-slate-900: #0f172a; --wf-slate-500: #64748b; --wf-slate-400: #94a3b8;
27
+ --wf-slate-300: #cbd5e1; --wf-slate-200: #e2e8f0; --wf-slate-100: #f1f5f9;
28
+ --wf-slate-50: #f8fafc; --wf-white: #ffffff;
29
+
30
+ /* 暗色值(暗色模式只做映射,值定义于此) */
31
+ --wf-dark-brand-500: #6b8aff; --wf-dark-brand-600: #8ba3ff; --wf-dark-brand-50: #1e293b;
32
+ --wf-dark-green-500: #4ade80; --wf-dark-green-50: #14532d;
33
+ --wf-dark-amber-500: #fbbf24; --wf-dark-amber-50: #451a03;
34
+ --wf-dark-red-500: #f87171; --wf-dark-red-50: #451a1a;
35
+ --wf-dark-sky-500: #60a5fa; --wf-dark-sky-50: #172554;
36
+ --wf-dark-slate-900: #f1f5f9; --wf-dark-slate-500: #94a3b8; --wf-dark-slate-400: #64748b;
37
+ --wf-dark-slate-300: #475569; --wf-dark-slate-200: #334155; --wf-dark-slate-100: #1e293b;
38
+ --wf-dark-slate-50: #0f172a; --wf-dark-bg: #0f172a;
39
+ --wf-dark-surface-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
40
+ --wf-dark-shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.2);
41
+ --wf-dark-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
42
+ --wf-dark-shadow-md: 0 4px 12px rgba(0, 0, 0, 0.4);
43
+ --wf-dark-shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.4);
44
+ }
45
+
46
+ /* ══ 语义层(Semantic)— 组件消费 ══ */
4
47
  :root {
5
48
  /* ── 间距 ── */
6
49
  --wf-gap-xs: 4px;
@@ -50,31 +93,31 @@
50
93
  --wf-pop-z: var(--wf-z-popover);
51
94
  --wf-cover-z: var(--wf-z-modal);
52
95
 
53
- /* ── 色彩 — 品牌 ── */
54
- --wf-color-primary: #4f6ef7;
55
- --wf-color-primary-hover: #3b5ae0;
56
- --wf-color-primary-bg: #eef1ff;
96
+ /* ── 色彩 — 品牌(引用原始层) ── */
97
+ --wf-color-primary: var(--wf-brand-500);
98
+ --wf-color-primary-hover: var(--wf-brand-600);
99
+ --wf-color-primary-bg: var(--wf-brand-50);
57
100
 
58
- --wf-color-success: #22c55e;
59
- --wf-color-success-bg: #f0fdf4;
60
- --wf-color-warning: #f59e0b;
61
- --wf-color-warning-bg: #fffbeb;
62
- --wf-color-error: #ef4444;
63
- --wf-color-error-bg: #fef2f2;
101
+ --wf-color-success: var(--wf-green-500);
102
+ --wf-color-success-bg: var(--wf-green-50);
103
+ --wf-color-warning: var(--wf-amber-500);
104
+ --wf-color-warning-bg: var(--wf-amber-50);
105
+ --wf-color-error: var(--wf-red-500);
106
+ --wf-color-error-bg: var(--wf-red-50);
64
107
 
65
- /* ── 色彩 — 中性 ── */
66
- --wf-color-text: #0f172a;
67
- --wf-color-text-secondary: #64748b;
68
- --wf-color-text-tertiary: #94a3b8;
69
- --wf-color-text-disabled: #cbd5e1;
108
+ /* ── 色彩 — 中性(引用原始层) ── */
109
+ --wf-color-text: var(--wf-slate-900);
110
+ --wf-color-text-secondary: var(--wf-slate-500);
111
+ --wf-color-text-tertiary: var(--wf-slate-400);
112
+ --wf-color-text-disabled: var(--wf-slate-300);
70
113
 
71
- --wf-color-bg: #ffffff;
72
- --wf-color-bg-secondary: #f8fafc;
73
- --wf-color-bg-tertiary: #f1f5f9;
114
+ --wf-color-bg: var(--wf-white);
115
+ --wf-color-bg-secondary: var(--wf-slate-50);
116
+ --wf-color-bg-tertiary: var(--wf-slate-100);
74
117
 
75
- --wf-color-border: #e2e8f0;
76
- --wf-color-border-light: #f1f5f9;
77
- --wf-color-border-dark: #cbd5e1;
118
+ --wf-color-border: var(--wf-slate-200);
119
+ --wf-color-border-light: var(--wf-slate-100);
120
+ --wf-color-border-dark: var(--wf-slate-300);
78
121
 
79
122
  /* ── surface 引用色彩 ── */
80
123
  --wf-surface-bg: var(--wf-color-bg);
@@ -106,7 +149,7 @@
106
149
  /* ── 边框宽度 ── */
107
150
  --wf-border-width: 1px;
108
151
 
109
- /* ── 聚焦环 ── */
152
+ /* ── 聚焦环(引用 primary-bg,暗色自动跟随) ── */
110
153
  --wf-focus-ring: 0 0 0 2px var(--wf-color-primary-bg);
111
154
 
112
155
  /* ── 动效 ── */
@@ -115,8 +158,8 @@
115
158
  --wf-transition: var(--wf-transition-duration) var(--wf-transition-timing);
116
159
 
117
160
  /* ── 色彩 — 信息(补充) ── */
118
- --wf-color-info: #1677ff;
119
- --wf-color-info-bg: #e6f4ff;
161
+ --wf-color-info: var(--wf-sky-500);
162
+ --wf-color-info-bg: var(--wf-sky-50);
120
163
 
121
164
  /* ── 表单控件 ── */
122
165
  --wf-accent-color: var(--wf-color-primary);
@@ -132,6 +175,9 @@
132
175
  --wf-bp-lg: 1024px;
133
176
  --wf-bp-xl: 1280px;
134
177
 
178
+ /* ── 应用外壳 ── */
179
+ --wf-sidebar-width: 240px;
180
+
135
181
  /* ── 透明度 ── */
136
182
  --wf-opacity-disabled: 0.5;
137
183
  --wf-opacity-overlay: 0.4;
@@ -141,58 +187,55 @@
141
187
  --wf-letter-spacing-wide: 0.5px;
142
188
  --wf-letter-spacing-wider: 1px;
143
189
  }
190
+ }
144
191
 
192
+ @layer tokens {
145
193
  /* weifuwu/theme — 暗色模式
146
194
  *
147
195
  * 两种激活方式(优先级:显式 data-theme > 系统偏好):
148
196
  * 1. 手动:<html data-theme="dark">(或 data-theme="light" 强制亮色)
149
197
  * 2. 自动:系统偏好 prefers-color-scheme: dark,无显式覆盖时生效
150
198
  *
151
- * ⚠️ 两段暗色覆盖值必须保持一致(静态 CSS 无法共享选择器列表,改动需同步)。
152
- * 每段末尾都设置 color-scheme: dark,让原生控件/滚动条跟随。
199
+ * 值全部定义在 _tokens.css 原始层的 --wf-dark-*,此处只做语义映射——
200
+ * 两段代码完全一致,且不含任何硬编码色值(改暗色调校只动原始层)。
153
201
  */
154
202
 
155
203
  /* ── 激活方式一:手动 data-theme="dark" ── */
156
- /* color-scheme 用 :root[data-theme] 提升优先级,压过 _base.css 的 :root 定义(导入顺序在后者) */
157
204
  :root[data-theme="dark"] {
158
205
  color-scheme: dark;
159
206
 
160
- --wf-color-primary: #6b8aff;
161
- --wf-color-primary-hover: #8ba3ff;
162
- --wf-color-primary-bg: #1e293b;
163
-
164
- --wf-color-success: #4ade80;
165
- --wf-color-success-bg: #14532d;
166
- --wf-color-warning: #fbbf24;
167
- --wf-color-warning-bg: #451a03;
168
- --wf-color-error: #f87171;
169
- --wf-color-error-bg: #451a1a;
170
-
171
- --wf-color-info: #60a5fa;
172
- --wf-color-info-bg: #172554;
207
+ --wf-color-primary: var(--wf-dark-brand-500);
208
+ --wf-color-primary-hover: var(--wf-dark-brand-600);
209
+ --wf-color-primary-bg: var(--wf-dark-brand-50);
173
210
 
174
- --wf-color-text: #f1f5f9;
175
- --wf-color-text-secondary: #94a3b8;
176
- --wf-color-text-tertiary: #64748b;
177
- --wf-color-text-disabled: #475569;
211
+ --wf-color-success: var(--wf-dark-green-500);
212
+ --wf-color-success-bg: var(--wf-dark-green-50);
213
+ --wf-color-warning: var(--wf-dark-amber-500);
214
+ --wf-color-warning-bg: var(--wf-dark-amber-50);
215
+ --wf-color-error: var(--wf-dark-red-500);
216
+ --wf-color-error-bg: var(--wf-dark-red-50);
217
+ --wf-color-info: var(--wf-dark-sky-500);
218
+ --wf-color-info-bg: var(--wf-dark-sky-50);
178
219
 
179
- --wf-color-bg: #0f172a;
180
- --wf-color-bg-secondary: #1e293b;
181
- --wf-color-bg-tertiary: #334155;
220
+ --wf-color-text: var(--wf-dark-slate-900);
221
+ --wf-color-text-secondary: var(--wf-dark-slate-500);
222
+ --wf-color-text-tertiary: var(--wf-dark-slate-400);
223
+ --wf-color-text-disabled: var(--wf-dark-slate-300);
182
224
 
183
- --wf-color-border: #334155;
184
- --wf-color-border-light: #1e293b;
185
- --wf-color-border-dark: #475569;
225
+ --wf-color-bg: var(--wf-dark-bg);
226
+ --wf-color-bg-secondary: var(--wf-dark-slate-100);
227
+ --wf-color-bg-tertiary: var(--wf-dark-slate-200);
186
228
 
187
- --wf-surface-shadow: 0 1px 3px rgba(0,0,0,0.3);
188
- --wf-shadow-sm: 0 1px 2px rgba(0,0,0,0.2);
189
- --wf-shadow: 0 1px 3px rgba(0,0,0,0.3);
190
- --wf-shadow-md: 0 4px 12px rgba(0,0,0,0.4);
191
- --wf-shadow-lg: 0 10px 15px -3px rgba(0,0,0,0.4);
192
-
193
- --wf-focus-ring: 0 0 0 2px var(--wf-color-primary-bg);
229
+ --wf-color-border: var(--wf-dark-slate-200);
230
+ --wf-color-border-light: var(--wf-dark-slate-100);
231
+ --wf-color-border-dark: var(--wf-dark-slate-300);
194
232
 
195
233
  --wf-surface-bg: var(--wf-color-bg);
234
+ --wf-surface-shadow: var(--wf-dark-surface-shadow);
235
+ --wf-shadow-sm: var(--wf-dark-shadow-sm);
236
+ --wf-shadow: var(--wf-dark-shadow);
237
+ --wf-shadow-md: var(--wf-dark-shadow-md);
238
+ --wf-shadow-lg: var(--wf-dark-shadow-lg);
196
239
  }
197
240
 
198
241
  /* ── 激活方式二:系统暗色偏好(data-theme="light" 可强制亮色) ── */
@@ -200,45 +243,43 @@
200
243
  :root:not([data-theme="light"]) {
201
244
  color-scheme: dark;
202
245
 
203
- --wf-color-primary: #6b8aff;
204
- --wf-color-primary-hover: #8ba3ff;
205
- --wf-color-primary-bg: #1e293b;
206
-
207
- --wf-color-success: #4ade80;
208
- --wf-color-success-bg: #14532d;
209
- --wf-color-warning: #fbbf24;
210
- --wf-color-warning-bg: #451a03;
211
- --wf-color-error: #f87171;
212
- --wf-color-error-bg: #451a1a;
246
+ --wf-color-primary: var(--wf-dark-brand-500);
247
+ --wf-color-primary-hover: var(--wf-dark-brand-600);
248
+ --wf-color-primary-bg: var(--wf-dark-brand-50);
213
249
 
214
- --wf-color-info: #60a5fa;
215
- --wf-color-info-bg: #172554;
250
+ --wf-color-success: var(--wf-dark-green-500);
251
+ --wf-color-success-bg: var(--wf-dark-green-50);
252
+ --wf-color-warning: var(--wf-dark-amber-500);
253
+ --wf-color-warning-bg: var(--wf-dark-amber-50);
254
+ --wf-color-error: var(--wf-dark-red-500);
255
+ --wf-color-error-bg: var(--wf-dark-red-50);
256
+ --wf-color-info: var(--wf-dark-sky-500);
257
+ --wf-color-info-bg: var(--wf-dark-sky-50);
216
258
 
217
- --wf-color-text: #f1f5f9;
218
- --wf-color-text-secondary: #94a3b8;
219
- --wf-color-text-tertiary: #64748b;
220
- --wf-color-text-disabled: #475569;
259
+ --wf-color-text: var(--wf-dark-slate-900);
260
+ --wf-color-text-secondary: var(--wf-dark-slate-500);
261
+ --wf-color-text-tertiary: var(--wf-dark-slate-400);
262
+ --wf-color-text-disabled: var(--wf-dark-slate-300);
221
263
 
222
- --wf-color-bg: #0f172a;
223
- --wf-color-bg-secondary: #1e293b;
224
- --wf-color-bg-tertiary: #334155;
264
+ --wf-color-bg: var(--wf-dark-bg);
265
+ --wf-color-bg-secondary: var(--wf-dark-slate-100);
266
+ --wf-color-bg-tertiary: var(--wf-dark-slate-200);
225
267
 
226
- --wf-color-border: #334155;
227
- --wf-color-border-light: #1e293b;
228
- --wf-color-border-dark: #475569;
229
-
230
- --wf-surface-shadow: 0 1px 3px rgba(0,0,0,0.3);
231
- --wf-shadow-sm: 0 1px 2px rgba(0,0,0,0.2);
232
- --wf-shadow: 0 1px 3px rgba(0,0,0,0.3);
233
- --wf-shadow-md: 0 4px 12px rgba(0,0,0,0.4);
234
- --wf-shadow-lg: 0 10px 15px -3px rgba(0,0,0,0.4);
235
-
236
- --wf-focus-ring: 0 0 0 2px var(--wf-color-primary-bg);
268
+ --wf-color-border: var(--wf-dark-slate-200);
269
+ --wf-color-border-light: var(--wf-dark-slate-100);
270
+ --wf-color-border-dark: var(--wf-dark-slate-300);
237
271
 
238
272
  --wf-surface-bg: var(--wf-color-bg);
273
+ --wf-surface-shadow: var(--wf-dark-surface-shadow);
274
+ --wf-shadow-sm: var(--wf-dark-shadow-sm);
275
+ --wf-shadow: var(--wf-dark-shadow);
276
+ --wf-shadow-md: var(--wf-dark-shadow-md);
277
+ --wf-shadow-lg: var(--wf-dark-shadow-lg);
239
278
  }
240
279
  }
280
+ }
241
281
 
282
+ @layer base {
242
283
  /* weifuwu/theme — 基础元素默认样式 */
243
284
  *,
244
285
  *::before,
@@ -429,7 +470,9 @@ code {
429
470
  scroll-behavior: auto !important;
430
471
  }
431
472
  }
473
+ }
432
474
 
475
+ @layer layout {
433
476
  /* stack — 纵向堆叠 */
434
477
  .wf-stack {
435
478
  display: flex;
@@ -449,7 +492,9 @@ code {
449
492
  @media (min-width: 640px) { .wf-stack-reverse\@sm { flex-direction: row-reverse; align-items: var(--wf-align, center); } }
450
493
  @media (min-width: 768px) { .wf-stack-reverse\@md { flex-direction: row-reverse; align-items: var(--wf-align, center); } }
451
494
  @media (min-width: 1024px) { .wf-stack-reverse\@lg { flex-direction: row-reverse; align-items: var(--wf-align, center); } }
495
+ }
452
496
 
497
+ @layer layout {
453
498
  /* row — 横向排列 */
454
499
  .wf-row {
455
500
  display: flex;
@@ -472,7 +517,9 @@ code {
472
517
  @media (min-width: 640px) { .wf-row-reverse\@sm { flex-direction: row-reverse; flex-wrap: wrap; } }
473
518
  @media (min-width: 768px) { .wf-row-reverse\@md { flex-direction: row-reverse; flex-wrap: wrap; } }
474
519
  @media (min-width: 1024px) { .wf-row-reverse\@lg { flex-direction: row-reverse; flex-wrap: wrap; } }
520
+ }
475
521
 
522
+ @layer layout {
476
523
  /* split — 两端展开 */
477
524
  .wf-split {
478
525
  display: flex;
@@ -483,7 +530,9 @@ code {
483
530
  .wf-split > :last-child {
484
531
  flex-shrink: 0;
485
532
  }
533
+ }
486
534
 
535
+ @layer layout {
487
536
  /* center — 居中 */
488
537
  .wf-center {
489
538
  display: flex;
@@ -491,7 +540,9 @@ code {
491
540
  align-items: center;
492
541
  justify-content: center;
493
542
  }
543
+ }
494
544
 
545
+ @layer layout {
495
546
  /* right — 靠右对齐 */
496
547
  .wf-right {
497
548
  display: flex;
@@ -499,28 +550,36 @@ code {
499
550
  align-items: var(--wf-align, center);
500
551
  gap: var(--wf-gap, var(--wf-gap-md));
501
552
  }
553
+ }
502
554
 
555
+ @layer layout {
503
556
  /* top — 顶部对齐 */
504
557
  .wf-top {
505
558
  display: flex;
506
559
  align-items: flex-start;
507
560
  gap: var(--wf-gap, var(--wf-gap-md));
508
561
  }
562
+ }
509
563
 
564
+ @layer layout {
510
565
  /* bottom — 底部对齐 */
511
566
  .wf-bottom {
512
567
  display: flex;
513
568
  align-items: flex-end;
514
569
  gap: var(--wf-gap, var(--wf-gap-md));
515
570
  }
571
+ }
516
572
 
573
+ @layer layout {
517
574
  /* stretch — 拉伸对齐 */
518
575
  .wf-stretch {
519
576
  display: flex;
520
577
  align-items: stretch;
521
578
  gap: var(--wf-gap, var(--wf-gap-md));
522
579
  }
580
+ }
523
581
 
582
+ @layer layout {
524
583
  /* around — 均匀环绕分布 */
525
584
  .wf-around {
526
585
  display: flex;
@@ -528,7 +587,9 @@ code {
528
587
  align-items: var(--wf-align, center);
529
588
  gap: var(--wf-gap, var(--wf-gap-md));
530
589
  }
590
+ }
531
591
 
592
+ @layer layout {
532
593
  /* evenly — 均匀分布 */
533
594
  .wf-evenly {
534
595
  display: flex;
@@ -536,26 +597,34 @@ code {
536
597
  align-items: var(--wf-align, center);
537
598
  gap: var(--wf-gap, var(--wf-gap-md));
538
599
  }
600
+ }
539
601
 
602
+ @layer layout {
540
603
  /* fill — 撑满剩余空间 */
541
604
  .wf-fill {
542
605
  flex: 1;
543
606
  min-width: 0;
544
607
  min-height: 0;
545
608
  }
609
+ }
546
610
 
611
+ @layer layout {
547
612
  /* fixed — 固定不伸缩 */
548
613
  .wf-fixed {
549
614
  flex: none;
550
615
  }
616
+ }
551
617
 
618
+ @layer layout {
552
619
  /* auto — 按内容撑满 */
553
620
  .wf-auto {
554
621
  flex: auto;
555
622
  min-width: 0;
556
623
  min-height: 0;
557
624
  }
625
+ }
558
626
 
627
+ @layer layout {
559
628
  /* cover — 全屏覆盖 */
560
629
  .wf-cover {
561
630
  position: fixed;
@@ -565,38 +634,99 @@ code {
565
634
  justify-content: center;
566
635
  z-index: var(--wf-z, var(--wf-cover-z));
567
636
  }
637
+ }
568
638
 
639
+ @layer layout {
569
640
  /* pop — 浮动层 */
570
641
  .wf-pop {
571
642
  position: absolute;
572
643
  z-index: var(--wf-z, var(--wf-pop-z));
573
644
  }
645
+ }
574
646
 
647
+ @layer layout {
575
648
  /* anchor — 定位锚点容器 */
576
649
  .wf-anchor {
577
650
  position: relative;
578
651
  }
652
+ }
579
653
 
654
+ @layer layout {
580
655
  /* sticky — 粘性定位 */
581
656
  .wf-sticky {
582
657
  position: sticky;
583
658
  top: var(--wf-offset, 0);
584
659
  }
660
+ }
661
+
662
+ @layer utilities {
663
+ /* surface — 基础面 + 面工具类(背景色/气泡/胶囊) */
585
664
 
586
- /* surface — 基础面 */
587
665
  .wf-surface {
588
666
  border-radius: var(--wf-surface-radius);
589
667
  box-shadow: var(--wf-surface-shadow);
590
668
  background: var(--wf-surface-bg);
591
669
  }
592
670
 
671
+ /* ── 背景色工具 — 引用语义 Token,免自定义 CSS ── */
672
+ .wf-bg-secondary { background: var(--wf-color-bg-secondary); }
673
+ .wf-bg-tertiary { background: var(--wf-color-bg-tertiary); }
674
+ .wf-bg-brand { background: var(--wf-color-primary-bg); } /* 兼容别名 → wf-bg-primary */
675
+ .wf-bg-primary { background: var(--wf-color-primary-bg); }
676
+ .wf-bg-success { background: var(--wf-color-success-bg); }
677
+ .wf-bg-warning { background: var(--wf-color-warning-bg); }
678
+ .wf-bg-error { background: var(--wf-color-error-bg); }
679
+ .wf-bg-info { background: var(--wf-color-info-bg); }
680
+
681
+ /* ── 胶囊圆角(状态徽章/标签/色块) ── */
682
+ .wf-pill { border-radius: 999px; }
683
+
684
+ /* ── 圆角工具 — 引用圆角 Token ── */
685
+ .wf-rounded-sm { border-radius: var(--wf-radius-sm); }
686
+ .wf-rounded { border-radius: var(--wf-radius); }
687
+ .wf-rounded-md { border-radius: var(--wf-radius-md); }
688
+ .wf-rounded-lg { border-radius: var(--wf-radius-lg); }
689
+
690
+ /* ── 聊天气泡 ──
691
+ * 用法:wf-bubble(对方/AI)+ wf-bubble--own(自己)
692
+ * 行布局用 wf-row + wf-gap/wf-mb 覆盖;文字用 wf-pre-wrap 已内建
693
+ */
694
+ .wf-bubble {
695
+ display: inline-block;
696
+ max-width: 70%;
697
+ padding: var(--wf-space-sm) var(--wf-space-md);
698
+ border-radius: var(--wf-radius-md);
699
+ background: var(--wf-color-bg-secondary);
700
+ color: var(--wf-color-text);
701
+ font-size: var(--wf-font-size-base);
702
+ line-height: var(--wf-line-height);
703
+ white-space: pre-wrap;
704
+ word-break: break-word;
705
+ }
706
+
707
+ .wf-bubble--own {
708
+ background: var(--wf-color-primary);
709
+ color: #fff;
710
+ border-bottom-right-radius: var(--wf-radius-sm);
711
+ }
712
+
713
+ .wf-bubble--ai {
714
+ background: var(--wf-color-primary-bg);
715
+ border: var(--wf-border-width) solid var(--wf-color-border-light);
716
+ border-bottom-left-radius: var(--wf-radius-sm);
717
+ }
718
+ }
719
+
720
+ @layer layout {
593
721
  /* grid — 二维网格 */
594
722
  .wf-grid {
595
723
  display: grid;
596
724
  grid-template-columns: var(--wf-cols, repeat(auto-fill, minmax(280px, 1fr)));
597
725
  gap: var(--wf-gap, var(--wf-gap-lg));
598
726
  }
727
+ }
599
728
 
729
+ @layer layout {
600
730
  /* cluster — 换行簇 */
601
731
  .wf-cluster {
602
732
  display: flex;
@@ -605,17 +735,23 @@ code {
605
735
  justify-content: var(--wf-justify, center);
606
736
  align-items: var(--wf-align, center);
607
737
  }
738
+ }
608
739
 
740
+ @layer layout {
609
741
  /* scroll — 可滚动容器 */
610
742
  .wf-scroll {
611
743
  overflow: auto;
612
744
  }
745
+ }
613
746
 
747
+ @layer layout {
614
748
  /* clip — 裁剪溢出 */
615
749
  .wf-clip {
616
750
  overflow: hidden;
617
751
  }
752
+ }
618
753
 
754
+ @layer utilities {
619
755
  /* hidden — 隐藏元素 */
620
756
  .wf-hidden {
621
757
  display: none;
@@ -624,6 +760,23 @@ code {
624
760
  @media (min-width: 768px) { .wf-hidden\@md { display: none; } }
625
761
  @media (min-width: 1024px) { .wf-hidden\@lg { display: none; } }
626
762
 
763
+ /* dim — 视觉淡化(运行中/历史态/次要操作) */
764
+ .wf-dim {
765
+ opacity: 0.7;
766
+ }
767
+
768
+ /* cursor — 交互指针 */
769
+ .wf-pointer { cursor: pointer; }
770
+ .wf-not-allowed { cursor: not-allowed; }
771
+
772
+ /* 打印工具 — 导出 PDF 时隐藏工具区 / 恢复块级 */
773
+ @media print {
774
+ .wf-print-hidden { display: none !important; }
775
+ .wf-print-block { display: block !important; }
776
+ }
777
+ }
778
+
779
+ @layer layout {
627
780
  /* block — 块级显示 */
628
781
  .wf-block {
629
782
  display: block;
@@ -631,35 +784,47 @@ code {
631
784
  @media (min-width: 640px) { .wf-block\@sm { display: block; } }
632
785
  @media (min-width: 768px) { .wf-block\@md { display: block; } }
633
786
  @media (min-width: 1024px) { .wf-block\@lg { display: block; } }
787
+ }
634
788
 
789
+ @layer layout {
635
790
  /* inline — 行内显示 */
636
791
  .wf-inline {
637
792
  display: inline;
638
793
  }
794
+ }
639
795
 
796
+ @layer layout {
640
797
  /* inline-block — 行内块 */
641
798
  .wf-inline-block {
642
799
  display: inline-block;
643
800
  }
801
+ }
644
802
 
803
+ @layer layout {
645
804
  /* container — 内容宽度约束居中 */
646
805
  .wf-container {
647
806
  max-width: var(--wf-max, 1200px);
648
807
  margin: 0 auto;
649
808
  padding: 0 var(--wf-gap, var(--wf-gap-lg));
650
809
  }
810
+ }
651
811
 
812
+ @layer layout {
652
813
  /* contents — 容器抹除(子元素直接参与上层布局) */
653
814
  .wf-contents {
654
815
  display: contents;
655
816
  }
817
+ }
656
818
 
819
+ @layer layout {
657
820
  /* layer — 层级控制 */
658
821
  .wf-layer {
659
822
  position: relative;
660
823
  z-index: var(--wf-z, 1);
661
824
  }
825
+ }
662
826
 
827
+ @layer layout {
663
828
  /* nowrap — 不换行 */
664
829
  .wf-nowrap {
665
830
  display: flex;
@@ -667,13 +832,244 @@ code {
667
832
  gap: var(--wf-gap, var(--wf-gap-md));
668
833
  align-items: var(--wf-align, center);
669
834
  }
835
+ }
670
836
 
837
+ @layer layout {
671
838
  /* min — flex 子项可收缩约束 */
672
839
  .wf-shrink {
673
840
  min-width: 0;
674
841
  min-height: 0;
675
842
  }
843
+ }
844
+
845
+ @layer utilities {
846
+ /* 间距/尺寸工具类 — 全部引用 --wf-* Token,无硬编码
847
+ *
848
+ * 命名:wf-p(adding)/wf-m(argin)[x|y|t|b] + 刻度(xs sm md lg xl 2xl)
849
+ * 与 flex 原语协作:wf-gap-* 设置 --wf-gap 变量(stack/row/split 等读取)
850
+ */
851
+
852
+ /* ── padding ── */
853
+ .wf-p-xs { padding: var(--wf-space-xs); }
854
+ .wf-p-sm { padding: var(--wf-space-sm); }
855
+ .wf-p-md { padding: var(--wf-space-md); }
856
+ .wf-p-lg { padding: var(--wf-space-lg); }
857
+ .wf-p-xl { padding: var(--wf-space-xl); }
858
+ .wf-p-2xl { padding: var(--wf-space-2xl); }
859
+
860
+ /* ── padding: 水平/垂直 ── */
861
+ .wf-px-xs { padding-left: var(--wf-space-xs); padding-right: var(--wf-space-xs); }
862
+ .wf-px-sm { padding-left: var(--wf-space-sm); padding-right: var(--wf-space-sm); }
863
+ .wf-px-md { padding-left: var(--wf-space-md); padding-right: var(--wf-space-md); }
864
+ .wf-px-lg { padding-left: var(--wf-space-lg); padding-right: var(--wf-space-lg); }
865
+ .wf-px-xl { padding-left: var(--wf-space-xl); padding-right: var(--wf-space-xl); }
866
+ .wf-px-2xl { padding-left: var(--wf-space-2xl); padding-right: var(--wf-space-2xl); }
867
+
868
+ .wf-py-xs { padding-top: var(--wf-space-xs); padding-bottom: var(--wf-space-xs); }
869
+ .wf-py-sm { padding-top: var(--wf-space-sm); padding-bottom: var(--wf-space-sm); }
870
+ .wf-py-md { padding-top: var(--wf-space-md); padding-bottom: var(--wf-space-md); }
871
+ .wf-py-lg { padding-top: var(--wf-space-lg); padding-bottom: var(--wf-space-lg); }
872
+ .wf-py-xl { padding-top: var(--wf-space-xl); padding-bottom: var(--wf-space-xl); }
873
+ .wf-py-2xl { padding-top: var(--wf-space-2xl); padding-bottom: var(--wf-space-2xl); }
874
+
875
+ /* ── margin:重置 ── */
876
+ .wf-m-0 { margin: 0; }
877
+ .wf-p-0 { padding: 0; }
878
+
879
+ /* ── margin(高频方向:top / bottom / 垂直) ── */
880
+ .wf-mt-xs { margin-top: var(--wf-space-xs); }
881
+ .wf-mt-sm { margin-top: var(--wf-space-sm); }
882
+ .wf-mt-md { margin-top: var(--wf-space-md); }
883
+ .wf-mt-lg { margin-top: var(--wf-space-lg); }
884
+ .wf-mt-xl { margin-top: var(--wf-space-xl); }
885
+ .wf-mt-2xl { margin-top: var(--wf-space-2xl); }
886
+
887
+ .wf-mb-xs { margin-bottom: var(--wf-space-xs); }
888
+ .wf-mb-sm { margin-bottom: var(--wf-space-sm); }
889
+ .wf-mb-md { margin-bottom: var(--wf-space-md); }
890
+ .wf-mb-lg { margin-bottom: var(--wf-space-lg); }
891
+ .wf-mb-xl { margin-bottom: var(--wf-space-xl); }
892
+ .wf-mb-2xl { margin-bottom: var(--wf-space-2xl); }
893
+
894
+ .wf-my-xs { margin-top: var(--wf-space-xs); margin-bottom: var(--wf-space-xs); }
895
+ .wf-my-sm { margin-top: var(--wf-space-sm); margin-bottom: var(--wf-space-sm); }
896
+ .wf-my-md { margin-top: var(--wf-space-md); margin-bottom: var(--wf-space-md); }
897
+ .wf-my-lg { margin-top: var(--wf-space-lg); margin-bottom: var(--wf-space-lg); }
898
+ .wf-my-xl { margin-top: var(--wf-space-xl); margin-bottom: var(--wf-space-xl); }
899
+ .wf-my-2xl { margin-top: var(--wf-space-2xl); margin-bottom: var(--wf-space-2xl); }
900
+
901
+ /* ── margin: auto(居中) ── */
902
+ .wf-mx-auto { margin-left: auto; margin-right: auto; }
903
+ .wf-my-auto { margin-top: auto; margin-bottom: auto; }
904
+
905
+ /* ── gap:为 flex/grid 原语设置间距变量 ── */
906
+ .wf-gap-none { --wf-gap: 0; }
907
+ .wf-gap-xs { --wf-gap: var(--wf-gap-xs); }
908
+ .wf-gap-sm { --wf-gap: var(--wf-gap-sm); }
909
+ .wf-gap-md { --wf-gap: var(--wf-gap-md); }
910
+ .wf-gap-lg { --wf-gap: var(--wf-gap-lg); }
911
+ .wf-gap-xl { --wf-gap: var(--wf-gap-xl); }
912
+ .wf-gap-2xl { --wf-gap: var(--wf-gap-2xl); }
913
+
914
+ /* ── 尺寸 ── */
915
+ .wf-w-full { width: 100%; }
916
+ .wf-h-full { height: 100%; }
917
+ .wf-w-auto { width: auto; }
918
+ }
919
+
920
+ @layer layout {
921
+ /* 应用外壳 — 侧边栏 + 主内容区
922
+ *
923
+ * 结构约定(应用层 AppLayout 组件使用):
924
+ * wf-app-shell > [wf-sidebar, wf-main]
925
+ * wf-sidebar > [wf-sidebar-header(品牌), wf-sidebar-body(wf-nav), wf-sidebar-footer(用户区)]
926
+ * wf-nav > wf-nav-group(分组标题) / wf-nav-item(链接,--active 激活)
927
+ *
928
+ * 移动端(<768px)降级:侧边栏堆叠到顶部、静态定位、主区占满。
929
+ * 交互式折叠抽屉属应用层职责(需 JS 开关),layout 只提供静态外壳。
930
+ */
931
+
932
+ .wf-app-shell {
933
+ display: grid;
934
+ grid-template-columns: var(--wf-sidebar-width, 240px) minmax(0, 1fr);
935
+ min-height: 100vh;
936
+ }
937
+
938
+ /* ── 侧边栏 ── */
939
+ .wf-sidebar {
940
+ display: flex;
941
+ flex-direction: column;
942
+ position: sticky;
943
+ top: 0;
944
+ height: 100vh;
945
+ overflow-y: auto;
946
+ background: var(--wf-color-bg-secondary);
947
+ border-right: var(--wf-border-width) solid var(--wf-color-border);
948
+ }
949
+
950
+ .wf-sidebar-header {
951
+ display: flex;
952
+ align-items: center;
953
+ gap: var(--wf-gap-sm);
954
+ padding: var(--wf-space-md);
955
+ border-bottom: var(--wf-border-width) solid var(--wf-color-border-light);
956
+ flex-shrink: 0;
957
+ }
958
+
959
+ .wf-sidebar-body {
960
+ flex: 1;
961
+ padding: var(--wf-space-sm);
962
+ overflow-y: auto;
963
+ }
964
+
965
+ .wf-sidebar-footer {
966
+ padding: var(--wf-space-sm);
967
+ border-top: var(--wf-border-width) solid var(--wf-color-border-light);
968
+ flex-shrink: 0;
969
+ }
970
+
971
+ /* ── 导航 ── */
972
+ .wf-nav {
973
+ display: flex;
974
+ flex-direction: column;
975
+ gap: 2px;
976
+ }
977
+
978
+ .wf-nav-group {
979
+ font-size: var(--wf-font-size-xs);
980
+ font-weight: var(--wf-font-weight-medium);
981
+ color: var(--wf-color-text-tertiary);
982
+ text-transform: uppercase;
983
+ letter-spacing: 0.5px;
984
+ padding: var(--wf-space-md) var(--wf-space-sm) var(--wf-space-xs);
985
+ }
676
986
 
987
+ .wf-nav-item {
988
+ display: flex;
989
+ align-items: center;
990
+ gap: var(--wf-gap-sm);
991
+ padding: var(--wf-space-sm) var(--wf-space);
992
+ border-radius: var(--wf-radius);
993
+ color: var(--wf-color-text-secondary);
994
+ font-size: var(--wf-font-size-base);
995
+ text-decoration: none;
996
+ cursor: pointer;
997
+ border: none;
998
+ background: none;
999
+ width: 100%;
1000
+ text-align: left;
1001
+ font-family: inherit;
1002
+ transition: background var(--wf-transition), color var(--wf-transition);
1003
+ }
1004
+
1005
+ .wf-nav-item:hover {
1006
+ background: var(--wf-color-bg-tertiary);
1007
+ color: var(--wf-color-text);
1008
+ text-decoration: none;
1009
+ }
1010
+
1011
+ .wf-nav-item:focus-visible {
1012
+ outline: none;
1013
+ box-shadow: var(--wf-focus-ring);
1014
+ }
1015
+
1016
+ .wf-nav-item--active {
1017
+ background: var(--wf-color-primary-bg);
1018
+ color: var(--wf-color-primary);
1019
+ font-weight: var(--wf-font-weight-medium);
1020
+ }
1021
+
1022
+ .wf-nav-item--active:hover {
1023
+ background: var(--wf-color-primary-bg);
1024
+ color: var(--wf-color-primary);
1025
+ }
1026
+
1027
+ .wf-nav-icon {
1028
+ flex-shrink: 0;
1029
+ display: inline-flex;
1030
+ }
1031
+
1032
+ /* ── 主内容区 ── */
1033
+ .wf-main {
1034
+ padding: var(--wf-space-lg);
1035
+ min-width: 0;
1036
+ background: var(--wf-color-bg);
1037
+ }
1038
+
1039
+ /* ── 触屏:导航项 44px 命中区 ── */
1040
+ @media (pointer: coarse) {
1041
+ .wf-nav-item {
1042
+ min-height: 44px;
1043
+ }
1044
+ }
1045
+
1046
+ /* ── 移动端:堆叠降级 ── */
1047
+ @media (max-width: 767.98px) {
1048
+ .wf-app-shell {
1049
+ grid-template-columns: 1fr;
1050
+ }
1051
+ .wf-sidebar {
1052
+ position: static;
1053
+ height: auto;
1054
+ border-right: none;
1055
+ border-bottom: var(--wf-border-width) solid var(--wf-color-border);
1056
+ }
1057
+ .wf-main {
1058
+ padding: var(--wf-space-md);
1059
+ }
1060
+ }
1061
+ }
1062
+
1063
+ @layer utilities {
1064
+ /* 边框工具类 — 全部引用 --wf-border-width / --wf-color-border */
1065
+ .wf-border { border: var(--wf-border-width) solid var(--wf-color-border); }
1066
+ .wf-border-t { border-top: var(--wf-border-width) solid var(--wf-color-border); }
1067
+ .wf-border-b { border-bottom: var(--wf-border-width) solid var(--wf-color-border); }
1068
+ .wf-border-l { border-left: var(--wf-border-width) solid var(--wf-color-border); }
1069
+ .wf-border-r { border-right: var(--wf-border-width) solid var(--wf-color-border); }
1070
+ }
1071
+
1072
+ @layer utilities {
677
1073
  /* 排版工具类 — 字号 / 色阶 / 字重 / 截断(零 CSS 用户自排版) */
678
1074
 
679
1075
  /* ── text-align ── */
@@ -707,7 +1103,12 @@ code {
707
1103
  .wf-text-secondary { color: var(--wf-color-text-secondary); }
708
1104
  .wf-text-tertiary { color: var(--wf-color-text-tertiary); }
709
1105
  .wf-text-disabled { color: var(--wf-color-text-disabled); }
710
- .wf-text-brand { color: var(--wf-color-primary); }
1106
+ .wf-text-brand { color: var(--wf-color-primary); } /* 兼容别名 → wf-text-primary */
1107
+ .wf-text-primary { color: var(--wf-color-primary); }
1108
+ .wf-text-success { color: var(--wf-color-success); }
1109
+ .wf-text-warning { color: var(--wf-color-warning); }
1110
+ .wf-text-error { color: var(--wf-color-error); }
1111
+ .wf-text-info { color: var(--wf-color-info); }
711
1112
 
712
1113
  /* ── 字重 ── */
713
1114
 
@@ -715,6 +1116,40 @@ code {
715
1116
  .wf-text-semibold { font-weight: var(--wf-font-weight-semibold); }
716
1117
  .wf-text-bold { font-weight: var(--wf-font-weight-bold); }
717
1118
 
1119
+ /* ── 行高 ── */
1120
+
1121
+ .wf-leading-tight { line-height: var(--wf-line-height-tight); }
1122
+ .wf-leading-base { line-height: var(--wf-line-height); }
1123
+ .wf-leading-relaxed { line-height: var(--wf-line-height-relaxed); }
1124
+
1125
+ /* ── 字距 ── */
1126
+
1127
+ .wf-tracking-normal { letter-spacing: var(--wf-letter-spacing); }
1128
+ .wf-tracking-wide { letter-spacing: var(--wf-letter-spacing-wide); }
1129
+ .wf-tracking-wider { letter-spacing: var(--wf-letter-spacing-wider); }
1130
+
1131
+ /* ── 文本变换 ── */
1132
+
1133
+ .wf-uppercase { text-transform: uppercase; }
1134
+ .wf-lowercase { text-transform: lowercase; }
1135
+ .wf-capitalize { text-transform: capitalize; }
1136
+
1137
+ /* ── 换行/折行 ── */
1138
+
1139
+ .wf-pre-wrap {
1140
+ white-space: pre-wrap;
1141
+ word-break: break-word;
1142
+ }
1143
+
1144
+ .wf-break-word {
1145
+ overflow-wrap: break-word;
1146
+ word-break: break-word;
1147
+ }
1148
+
1149
+ .wf-text-nowrap {
1150
+ white-space: nowrap;
1151
+ }
1152
+
718
1153
  /* ── 截断 ── */
719
1154
 
720
1155
  .wf-truncate {
@@ -736,7 +1171,118 @@ code {
736
1171
  -webkit-box-orient: vertical;
737
1172
  overflow: hidden;
738
1173
  }
1174
+ }
1175
+
1176
+ @layer utilities {
1177
+ /* prose — 富文本正文排版(文章/博客/文档渲染,一个类包全部)
1178
+ *
1179
+ * 用法:<article class="wf-prose">…markdown/富文本 HTML…</article>
1180
+ * 覆盖:h2-h4 / p / ul / ol / li / blockquote / pre / code / a / img / table / hr / strong
1181
+ */
1182
+
1183
+ .wf-prose {
1184
+ font-size: var(--wf-font-size-base);
1185
+ line-height: var(--wf-line-height-relaxed);
1186
+ color: var(--wf-color-text);
1187
+ }
1188
+
1189
+ .wf-prose h2 {
1190
+ font-size: var(--wf-font-size-2xl);
1191
+ font-weight: var(--wf-font-weight-semibold);
1192
+ line-height: var(--wf-line-height-tight);
1193
+ margin: var(--wf-space-xl) 0 var(--wf-space-md);
1194
+ }
1195
+
1196
+ .wf-prose h3 {
1197
+ font-size: var(--wf-font-size-xl);
1198
+ font-weight: var(--wf-font-weight-semibold);
1199
+ line-height: var(--wf-line-height-tight);
1200
+ margin: var(--wf-space-lg) 0 var(--wf-space-sm);
1201
+ }
739
1202
 
1203
+ .wf-prose h4 {
1204
+ font-size: var(--wf-font-size-base);
1205
+ font-weight: var(--wf-font-weight-semibold);
1206
+ margin: var(--wf-space-md) 0 var(--wf-space-sm);
1207
+ }
1208
+
1209
+ .wf-prose p {
1210
+ margin: 0 0 var(--wf-space-md);
1211
+ line-height: var(--wf-line-height-relaxed);
1212
+ }
1213
+
1214
+ .wf-prose ul,
1215
+ .wf-prose ol {
1216
+ margin: 0 0 var(--wf-space-md);
1217
+ padding-left: var(--wf-space-lg);
1218
+ }
1219
+
1220
+ .wf-prose li {
1221
+ margin: var(--wf-space-xs) 0;
1222
+ line-height: var(--wf-line-height-relaxed);
1223
+ }
1224
+
1225
+ .wf-prose blockquote {
1226
+ margin: 0 0 var(--wf-space-md);
1227
+ padding: var(--wf-space-xs) var(--wf-space-md);
1228
+ border-left: 3px solid var(--wf-color-primary);
1229
+ background: var(--wf-color-primary-bg);
1230
+ border-radius: var(--wf-radius);
1231
+ color: var(--wf-color-text-secondary);
1232
+ }
1233
+
1234
+ .wf-prose pre {
1235
+ margin: 0 0 var(--wf-space-md);
1236
+ padding: var(--wf-space-md);
1237
+ background: var(--wf-color-bg-tertiary);
1238
+ border: var(--wf-border-width) solid var(--wf-color-border);
1239
+ border-radius: var(--wf-radius);
1240
+ overflow-x: auto;
1241
+ white-space: pre;
1242
+ }
1243
+
1244
+ .wf-prose code {
1245
+ background: var(--wf-color-bg-tertiary);
1246
+ padding: 2px 6px;
1247
+ border-radius: var(--wf-radius-sm);
1248
+ }
1249
+
1250
+ .wf-prose pre code {
1251
+ background: none;
1252
+ padding: 0;
1253
+ }
1254
+
1255
+ .wf-prose a {
1256
+ color: var(--wf-color-primary);
1257
+ text-decoration: none;
1258
+ }
1259
+
1260
+ .wf-prose a:hover {
1261
+ text-decoration: underline;
1262
+ }
1263
+
1264
+ .wf-prose img {
1265
+ max-width: 100%;
1266
+ border-radius: var(--wf-radius-md);
1267
+ }
1268
+
1269
+ .wf-prose hr {
1270
+ margin: var(--wf-space-lg) 0;
1271
+ }
1272
+
1273
+ .wf-prose strong {
1274
+ font-weight: var(--wf-font-weight-semibold);
1275
+ }
1276
+
1277
+ .wf-prose > :first-child {
1278
+ margin-top: 0;
1279
+ }
1280
+
1281
+ .wf-prose > :last-child {
1282
+ margin-bottom: 0;
1283
+ }
1284
+ }
1285
+ @layer components {
740
1286
  /* weifuwu/components — Button */
741
1287
  /* 所有颜色/间距/字号引用 layout 的 --wf-* 变量,不硬编码 */
742
1288
 
@@ -748,9 +1294,9 @@ code {
748
1294
  font-family: var(--wf-font-sans);
749
1295
  font-size: var(--wf-font-size-sm);
750
1296
  font-weight: var(--wf-font-weight-medium);
751
- padding: var(--wf-control-pad-y) var(--wf-space-md);
1297
+ padding: var(--wf-btn-pad-y, var(--wf-control-pad-y)) var(--wf-btn-pad-x, var(--wf-space-md));
752
1298
  min-height: var(--wf-control-height);
753
- border-radius: var(--wf-radius);
1299
+ border-radius: var(--wf-btn-radius, var(--wf-radius));
754
1300
  border: var(--wf-border-width) solid transparent;
755
1301
  cursor: pointer;
756
1302
  transition: all var(--wf-transition);
@@ -803,9 +1349,10 @@ code {
803
1349
  .wf-input {
804
1350
  font-family: var(--wf-font-sans);
805
1351
  font-size: var(--wf-font-size-sm);
1352
+ min-height: var(--wf-field-height, var(--wf-control-height));
806
1353
  padding: var(--wf-control-pad-y) var(--wf-space);
807
1354
  border: var(--wf-border-width) solid var(--wf-color-border);
808
- border-radius: var(--wf-radius);
1355
+ border-radius: var(--wf-field-radius, var(--wf-radius));
809
1356
  background: var(--wf-color-bg);
810
1357
  color: var(--wf-color-text);
811
1358
  outline: none;
@@ -823,6 +1370,25 @@ code {
823
1370
  cursor: not-allowed;
824
1371
  }
825
1372
 
1373
+ /* borderless — 可编辑标题/内联编辑(hover/focus 才显现边框) */
1374
+ .wf-input--borderless {
1375
+ border-color: transparent;
1376
+ background: transparent;
1377
+ box-shadow: none;
1378
+ padding-left: var(--wf-space-xs);
1379
+ padding-right: var(--wf-space-xs);
1380
+ }
1381
+
1382
+ .wf-input--borderless:hover {
1383
+ border-color: var(--wf-color-border);
1384
+ background: var(--wf-color-bg);
1385
+ }
1386
+
1387
+ .wf-input--borderless:focus {
1388
+ border-color: var(--wf-color-primary);
1389
+ background: var(--wf-color-bg);
1390
+ }
1391
+
826
1392
  .wf-input::placeholder {
827
1393
  color: var(--wf-color-text-tertiary);
828
1394
  }
@@ -934,9 +1500,10 @@ code {
934
1500
  .wf-textarea {
935
1501
  font-family: var(--wf-font-sans);
936
1502
  font-size: var(--wf-font-size-sm);
1503
+ min-height: var(--wf-field-height, var(--wf-control-height));
937
1504
  padding: var(--wf-control-pad-y) var(--wf-space);
938
1505
  border: var(--wf-border-width) solid var(--wf-color-border);
939
- border-radius: var(--wf-radius);
1506
+ border-radius: var(--wf-field-radius, var(--wf-radius));
940
1507
  background: var(--wf-color-bg);
941
1508
  color: var(--wf-color-text);
942
1509
  outline: none;
@@ -970,6 +1537,19 @@ code {
970
1537
  color: var(--wf-color-text-tertiary);
971
1538
  }
972
1539
 
1540
+ /* 字数统计 */
1541
+ .wf-textarea-count {
1542
+ font-size: var(--wf-font-size-xs);
1543
+ color: var(--wf-color-text-tertiary);
1544
+ text-align: right;
1545
+ line-height: 1;
1546
+ margin-top: -2px;
1547
+ }
1548
+
1549
+ .wf-textarea-count--over {
1550
+ color: var(--wf-color-error);
1551
+ }
1552
+
973
1553
  .wf-textarea--err .wf-textarea {
974
1554
  border-color: var(--wf-color-error);
975
1555
  }
@@ -999,9 +1579,10 @@ code {
999
1579
  .wf-select {
1000
1580
  font-family: var(--wf-font-sans);
1001
1581
  font-size: var(--wf-font-size-sm);
1582
+ min-height: var(--wf-field-height, var(--wf-control-height));
1002
1583
  padding: var(--wf-control-pad-y) var(--wf-space);
1003
1584
  border: var(--wf-border-width) solid var(--wf-color-border);
1004
- border-radius: var(--wf-radius);
1585
+ border-radius: var(--wf-field-radius, var(--wf-radius));
1005
1586
  background: var(--wf-color-bg);
1006
1587
  color: var(--wf-color-text);
1007
1588
  outline: none;
@@ -1038,7 +1619,7 @@ code {
1038
1619
 
1039
1620
  .wf-select-search-trigger {
1040
1621
  border: var(--wf-border-width) solid var(--wf-color-border);
1041
- border-radius: var(--wf-radius);
1622
+ border-radius: var(--wf-field-radius, var(--wf-radius));
1042
1623
  background: var(--wf-color-bg);
1043
1624
  cursor: pointer;
1044
1625
  transition: all var(--wf-transition);
@@ -1063,6 +1644,7 @@ code {
1063
1644
  font-family: var(--wf-font-sans);
1064
1645
  font-size: var(--wf-font-size-sm);
1065
1646
  color: var(--wf-color-text);
1647
+ min-height: var(--wf-field-height, var(--wf-control-height));
1066
1648
  padding: var(--wf-control-pad-y) var(--wf-space);
1067
1649
  cursor: pointer;
1068
1650
  box-sizing: border-box;
@@ -1079,7 +1661,7 @@ code {
1079
1661
  margin-top: 2px;
1080
1662
  background: var(--wf-color-bg);
1081
1663
  border: var(--wf-border-width) solid var(--wf-color-border);
1082
- border-radius: var(--wf-radius);
1664
+ border-radius: var(--wf-field-radius, var(--wf-radius));
1083
1665
  box-shadow: var(--wf-shadow-md);
1084
1666
  max-height: 240px;
1085
1667
  overflow-y: auto;
@@ -1193,7 +1775,7 @@ code {
1193
1775
  width: 36px;
1194
1776
  height: 20px;
1195
1777
  background: var(--wf-color-border-dark);
1196
- border-radius: 10px;
1778
+ border-radius: var(--wf-switch-radius, 10px);
1197
1779
  transition: background var(--wf-transition);
1198
1780
  flex-shrink: 0;
1199
1781
  }
@@ -1397,9 +1979,9 @@ code {
1397
1979
 
1398
1980
  .wf-modal-content {
1399
1981
  background: var(--wf-color-bg);
1400
- border-radius: var(--wf-radius-md);
1401
- box-shadow: var(--wf-shadow-lg);
1402
- min-width: 400px;
1982
+ border-radius: var(--wf-modal-radius, var(--wf-radius-md));
1983
+ box-shadow: var(--wf-modal-shadow, var(--wf-shadow-lg));
1984
+ min-width: var(--wf-modal-width, 400px);
1403
1985
  max-width: 90vw;
1404
1986
  max-height: 80vh;
1405
1987
  display: flex;
@@ -1467,11 +2049,11 @@ code {
1467
2049
  align-items: center;
1468
2050
  gap: var(--wf-gap-sm);
1469
2051
  padding: var(--wf-space) var(--wf-space-md);
1470
- border-radius: var(--wf-radius);
2052
+ border-radius: var(--wf-toast-radius, var(--wf-radius));
1471
2053
  box-shadow: var(--wf-shadow-md);
1472
2054
  font-family: var(--wf-font-sans);
1473
2055
  font-size: var(--wf-font-size-sm);
1474
- min-width: 260px;
2056
+ min-width: var(--wf-toast-width, 260px);
1475
2057
  max-width: 400px;
1476
2058
  cursor: pointer;
1477
2059
  pointer-events: auto;
@@ -1524,7 +2106,7 @@ code {
1524
2106
  align-items: flex-start;
1525
2107
  gap: var(--wf-gap-sm);
1526
2108
  padding: var(--wf-space) var(--wf-space-md);
1527
- border-radius: var(--wf-radius);
2109
+ border-radius: var(--wf-alert-radius, var(--wf-radius));
1528
2110
  font-family: var(--wf-font-sans);
1529
2111
  font-size: var(--wf-font-size-sm);
1530
2112
  line-height: var(--wf-line-height);
@@ -1675,7 +2257,7 @@ code {
1675
2257
 
1676
2258
  .wf-dropdown-menu {
1677
2259
  position: fixed;
1678
- min-width: 140px;
2260
+ min-width: var(--wf-dropdown-min-width, 140px);
1679
2261
  background: var(--wf-color-bg);
1680
2262
  border: var(--wf-border-width) solid var(--wf-color-border);
1681
2263
  border-radius: var(--wf-radius);
@@ -1776,13 +2358,13 @@ code {
1776
2358
  /* weifuwu/components — Card */
1777
2359
 
1778
2360
  .wf-card {
1779
- border-radius: var(--wf-surface-radius);
2361
+ border-radius: var(--wf-card-radius, var(--wf-surface-radius));
1780
2362
  background: var(--wf-surface-bg);
1781
2363
  font-family: var(--wf-font-sans);
1782
2364
  }
1783
2365
 
1784
2366
  .wf-card--default {
1785
- box-shadow: var(--wf-surface-shadow);
2367
+ box-shadow: var(--wf-card-shadow, var(--wf-surface-shadow));
1786
2368
  }
1787
2369
 
1788
2370
  .wf-card--outlined {
@@ -1807,13 +2389,29 @@ code {
1807
2389
  box-shadow: var(--wf-shadow-md), var(--wf-focus-ring);
1808
2390
  }
1809
2391
 
2392
+ /* hover 抬升变体 — 阴影 + 上移(悬停卡片/列表卡片) */
2393
+ .wf-card--hover {
2394
+ transition: box-shadow var(--wf-transition), transform var(--wf-transition);
2395
+ }
2396
+
2397
+ .wf-card--hover:hover {
2398
+ box-shadow: var(--wf-shadow-md);
2399
+ transform: translateY(-2px);
2400
+ }
2401
+
2402
+ /* 选中态 — 选择卡片(类型选择/模板选择) */
2403
+ .wf-card--active {
2404
+ border: var(--wf-border-width) solid var(--wf-color-primary);
2405
+ background: var(--wf-color-primary-bg);
2406
+ }
2407
+
1810
2408
  /* weifuwu/components — Badge */
1811
2409
 
1812
2410
  .wf-badge {
1813
2411
  display: inline-flex;
1814
2412
  align-items: center;
1815
2413
  padding: 2px var(--wf-space-sm);
1816
- border-radius: 10px;
2414
+ border-radius: var(--wf-badge-radius, 10px);
1817
2415
  font-family: var(--wf-font-sans);
1818
2416
  font-size: var(--wf-font-size-xs);
1819
2417
  font-weight: var(--wf-font-weight-medium);
@@ -1869,7 +2467,7 @@ code {
1869
2467
  align-items: center;
1870
2468
  gap: var(--wf-gap-xs);
1871
2469
  padding: 2px var(--wf-space-sm);
1872
- border-radius: var(--wf-radius-sm);
2470
+ border-radius: var(--wf-tag-radius, var(--wf-radius-sm));
1873
2471
  font-family: var(--wf-font-sans);
1874
2472
  font-size: var(--wf-font-size-xs);
1875
2473
  line-height: 1.5;
@@ -1940,6 +2538,22 @@ code {
1940
2538
  font-weight: var(--wf-font-weight-bold);
1941
2539
  }
1942
2540
 
2541
+ /* 可点击指标卡 */
2542
+ .wf-stat--clickable {
2543
+ cursor: pointer;
2544
+ transition: box-shadow var(--wf-transition), transform var(--wf-transition);
2545
+ }
2546
+
2547
+ .wf-stat--clickable:hover {
2548
+ box-shadow: var(--wf-shadow-md);
2549
+ transform: translateY(-2px);
2550
+ }
2551
+
2552
+ .wf-stat--clickable:focus-visible {
2553
+ outline: none;
2554
+ box-shadow: var(--wf-shadow-md), var(--wf-focus-ring);
2555
+ }
2556
+
1943
2557
  /* weifuwu/components — Steps */
1944
2558
 
1945
2559
  .wf-steps {
@@ -2161,6 +2775,82 @@ code {
2161
2775
  color: var(--wf-color-text);
2162
2776
  }
2163
2777
 
2778
+ /* weifuwu/components — SegmentedControl */
2779
+
2780
+ .wf-segmented {
2781
+ display: inline-flex;
2782
+ align-items: center;
2783
+ gap: 2px;
2784
+ padding: 2px;
2785
+ border-radius: var(--wf-radius);
2786
+ background: var(--wf-color-bg-tertiary);
2787
+ font-family: var(--wf-font-sans);
2788
+ }
2789
+
2790
+ .wf-segmented--block {
2791
+ display: flex;
2792
+ width: 100%;
2793
+ }
2794
+
2795
+ .wf-segmented--block .wf-segmented-option {
2796
+ flex: 1;
2797
+ justify-content: center;
2798
+ }
2799
+
2800
+ .wf-segmented-option {
2801
+ display: inline-flex;
2802
+ align-items: center;
2803
+ gap: var(--wf-gap-xs);
2804
+ border: none;
2805
+ background: none;
2806
+ cursor: pointer;
2807
+ padding: var(--wf-space-xs) var(--wf-space-md);
2808
+ border-radius: calc(var(--wf-radius) - 1px);
2809
+ font-family: inherit;
2810
+ font-size: var(--wf-font-size-sm);
2811
+ font-weight: var(--wf-font-weight-medium);
2812
+ line-height: var(--wf-line-height);
2813
+ color: var(--wf-color-text-secondary);
2814
+ white-space: nowrap;
2815
+ transition: background var(--wf-transition), color var(--wf-transition), box-shadow var(--wf-transition);
2816
+ }
2817
+
2818
+ .wf-segmented-option:hover {
2819
+ color: var(--wf-color-text);
2820
+ }
2821
+
2822
+ .wf-segmented-option--active {
2823
+ background: var(--wf-surface-bg);
2824
+ color: var(--wf-color-primary);
2825
+ box-shadow: var(--wf-shadow-sm);
2826
+ }
2827
+
2828
+ .wf-segmented-option--active:hover {
2829
+ color: var(--wf-color-primary);
2830
+ }
2831
+
2832
+ .wf-segmented-option:focus-visible {
2833
+ outline: none;
2834
+ box-shadow: var(--wf-focus-ring);
2835
+ }
2836
+
2837
+ .wf-segmented-option:disabled {
2838
+ opacity: var(--wf-opacity-disabled);
2839
+ cursor: not-allowed;
2840
+ }
2841
+
2842
+ .wf-segmented--sm .wf-segmented-option {
2843
+ padding: 2px var(--wf-space-sm);
2844
+ font-size: var(--wf-font-size-xs);
2845
+ }
2846
+
2847
+ /* 触屏:44px 命中区 */
2848
+ @media (pointer: coarse) {
2849
+ .wf-segmented-option {
2850
+ min-height: 44px;
2851
+ }
2852
+ }
2853
+
2164
2854
  /* weifuwu/components — ProgressBar */
2165
2855
 
2166
2856
  .wf-progress-wrap {
@@ -2500,7 +3190,7 @@ code {
2500
3190
  font-family: var(--wf-font-sans);
2501
3191
  font-size: var(--wf-font-size-xs);
2502
3192
  padding: var(--wf-space-xs) var(--wf-space-sm);
2503
- border-radius: var(--wf-radius-sm);
3193
+ border-radius: var(--wf-tooltip-radius, var(--wf-radius-sm));
2504
3194
  white-space: nowrap;
2505
3195
  pointer-events: none;
2506
3196
  max-width: 240px;
@@ -2623,7 +3313,7 @@ code {
2623
3313
  position: relative;
2624
3314
  display: flex;
2625
3315
  flex-direction: column;
2626
- width: 360px;
3316
+ width: var(--wf-drawer-width, 360px);
2627
3317
  max-width: 100vw;
2628
3318
  height: 100%;
2629
3319
  background: var(--wf-color-bg);
@@ -2736,10 +3426,10 @@ code {
2736
3426
  z-index: var(--wf-z-popover);
2737
3427
  background: var(--wf-color-bg);
2738
3428
  border: var(--wf-border-width) solid var(--wf-color-border);
2739
- border-radius: var(--wf-radius-md);
3429
+ border-radius: var(--wf-popover-radius, var(--wf-radius-md));
2740
3430
  box-shadow: var(--wf-shadow-md);
2741
3431
  padding: var(--wf-space);
2742
- min-width: 160px;
3432
+ min-width: var(--wf-popover-width, 160px);
2743
3433
  max-width: 320px;
2744
3434
  }
2745
3435
 
@@ -2954,7 +3644,7 @@ code {
2954
3644
  border-radius: var(--wf-radius-md);
2955
3645
  box-shadow: var(--wf-shadow-md);
2956
3646
  padding: var(--wf-space);
2957
- min-width: 260px;
3647
+ min-width: var(--wf-datepicker-width, 260px);
2958
3648
  user-select: none;
2959
3649
  }
2960
3650
 
@@ -3067,7 +3757,7 @@ code {
3067
3757
  }
3068
3758
 
3069
3759
  .wf-datepicker-range-panel {
3070
- min-width: 240px;
3760
+ min-width: var(--wf-datepicker-time-width, 240px);
3071
3761
  }
3072
3762
 
3073
3763
  /* ── 时间选择 ── */
@@ -3080,7 +3770,7 @@ code {
3080
3770
  border-radius: var(--wf-radius-md);
3081
3771
  box-shadow: var(--wf-shadow-md);
3082
3772
  padding: var(--wf-space);
3083
- min-width: 200px;
3773
+ min-width: var(--wf-datepicker-range-width, 200px);
3084
3774
  user-select: none;
3085
3775
  }
3086
3776
 
@@ -3755,3 +4445,4 @@ code {
3755
4445
  color: var(--wf-color-text-secondary);
3756
4446
  }
3757
4447
 
4448
+ }