@waterwx/dsh-novel-forge 1.7.0 → 1.7.2

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.
Files changed (36) hide show
  1. package/lib/client.js +2537 -1858
  2. package/lib/client.js.map +1 -1
  3. package/lib/index.js +657 -45
  4. package/lib/index.js.map +1 -1
  5. package/lib/types/client/api.d.ts +2 -0
  6. package/lib/types/client/locales.d.ts +0 -1
  7. package/lib/types/client/panel/FlowGuide.d.ts +21 -0
  8. package/lib/types/client/panel/MangaRoleLibrary.d.ts +18 -0
  9. package/lib/types/client/panel/MangaWorkspace.d.ts +2 -2
  10. package/lib/types/client/panel/StoryboardTab.d.ts +5 -1
  11. package/lib/types/engine.d.ts +15 -8
  12. package/lib/types/protocol.d.ts +124 -0
  13. package/package.json +2 -1
  14. package/src/client/api.ts +5 -0
  15. package/src/client/locales.ts +0 -1
  16. package/src/client/panel/AssetsTab.tsx +22 -22
  17. package/src/client/panel/AssistantTab.tsx +3 -3
  18. package/src/client/panel/BookshelfBar.tsx +1 -1
  19. package/src/client/panel/CreateBookView.tsx +10 -10
  20. package/src/client/panel/FlowGuide.tsx +83 -0
  21. package/src/client/panel/MangaRoleLibrary.tsx +810 -0
  22. package/src/client/panel/MangaWorkspace.tsx +359 -297
  23. package/src/client/panel/NovelPanel.tsx +107 -107
  24. package/src/client/panel/ReaderView.tsx +4 -4
  25. package/src/client/panel/RunPanel.tsx +8 -8
  26. package/src/client/panel/SceneLibrary.tsx +68 -67
  27. package/src/client/panel/StoryboardTab.tsx +105 -41
  28. package/src/client/panel/StyleCard.tsx +13 -13
  29. package/src/client/panel/StyleGallery.tsx +2 -2
  30. package/src/client/panel/WorldTab.tsx +5 -5
  31. package/src/client/panel/panel.module.css +861 -510
  32. package/src/client/panel/views.tsx +24 -24
  33. package/src/engine.ts +482 -51
  34. package/src/protocol.ts +125 -0
  35. package/src/routes.ts +203 -0
  36. package/src/client/panel/RoleVisualPanel.tsx +0 -485
@@ -10,16 +10,17 @@
10
10
  .entry {
11
11
  display: flex;
12
12
  align-items: center;
13
- gap: 8px;
13
+ gap: var(--nf-space-8, 8px);
14
14
  width: 100%;
15
- padding: 8px 12px;
15
+ padding: var(--nf-space-8, 8px) var(--nf-space-12, 12px);
16
16
  border: none;
17
17
  background: transparent;
18
18
  color: var(--dsw-alias-label-primary, #1f1f23);
19
19
  cursor: pointer;
20
- font-size: 13px;
20
+ /* 入口行在 .view 外,令牌不可达,用字面值对齐统一档(主文本 14px) */
21
+ font-size: 14px;
21
22
  text-align: left;
22
- border-radius: 6px;
23
+ border-radius: var(--nf-radius-6, 6px);
23
24
  transition: background 0.15s ease;
24
25
  }
25
26
 
@@ -90,24 +91,102 @@ body[data-ds-dark-theme] .entry {
90
91
  --nf-shadow-lg: 0 4px 12px rgba(0, 0, 0, 0.07), 0 20px 48px rgba(0, 0, 0, 0.12);
91
92
  --nf-card-shadow: 0 2px 6px rgba(0, 0, 0, 0.06), 0 14px 38px rgba(0, 0, 0, 0.14);
92
93
  --nf-card-shadow-hover: 0 4px 10px rgba(0, 0, 0, 0.08), 0 22px 52px rgba(0, 0, 0, 0.20);
93
- /* Liquid Glass: vertical glass face + soft top-left core + sheen border */
94
- --nf-glass-face: linear-gradient(180deg, #f6f7f9 0%, #f0f2f5 26%, #e9ebef 52%, #e0e3e8 78%, #d6d9df 100%);
95
- --nf-glass-core: radial-gradient(30% 24% at 36% 28%, rgba(255, 255, 255, 0.5) 0%, rgba(255, 255, 255, 0.22) 45%, rgba(255, 255, 255, 0) 78%);
94
+ /* Liquid Glass: 薄透玻璃面(透明度以文字清晰为先,保留壁纸透色但不干扰阅读)+ 顶部高光 + 淡描边 */
95
+ --nf-glass-face: linear-gradient(180deg, rgba(255, 255, 255, 0.40) 0%, rgba(255, 255, 255, 0.30) 26%, rgba(255, 255, 255, 0.24) 52%, rgba(255, 255, 255, 0.20) 78%, rgba(255, 255, 255, 0.18) 100%);
96
+ --nf-glass-core: radial-gradient(60% 40% at 30% 0%, rgba(255, 255, 255, 0.60) 0%, rgba(255, 255, 255, 0.20) 42%, rgba(255, 255, 255, 0) 78%);
96
97
  --nf-glass-sheen: rgba(255, 255, 255, 0.55);
97
- --nf-glass-border: rgba(255, 255, 255, 0.65);
98
- --nf-glass-inset: rgba(255, 255, 255, 0.55);
99
- --nf-glass-orb-a: rgba(0, 184, 92, 0.18);
100
- --nf-glass-orb-b: rgba(120, 160, 255, 0.13);
98
+ --nf-glass-border: rgba(255, 255, 255, 0.5);
99
+ --nf-glass-inset: rgba(255, 255, 255, 0.4);
100
+ --nf-glass-orb-a: rgba(0, 184, 92, 0.24);
101
+ --nf-glass-orb-b: rgba(120, 160, 255, 0.20);
101
102
  --nf-glass-noise: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.8' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23n)'/%3E%3C/svg%3E");
103
+ /* 容器形态(主题可覆盖,用于区分 液态玻璃/毛玻璃 等):液态=适圆角+薄玻璃+彩色流光 */
104
+ --nf-card-radius: 20px;
105
+ --nf-card-blur: 26px;
106
+ --nf-card-saturate: 170%;
107
+ --nf-card-brightness: 1.04;
108
+ --nf-card-sheen: rgba(255, 255, 255, 0.5);
109
+ --nf-card-border: 1px solid rgba(255, 255, 255, 0.35);
110
+ /* 控件形态(液态:圆润 + 玻璃底 + 强内高光 + 绿色箭头) */
111
+ --nf-ctrl-radius: 14px;
112
+ --nf-ctrl-bg: var(--nf-bg-raise);
113
+ --nf-ctrl-border: 1px solid rgba(255, 255, 255, 0.7);
114
+ --nf-ctrl-sheen: rgba(255, 255, 255, 0.5);
115
+ --nf-ctrl-caret: var(--nf-accent);
116
+ /* 液态:绿→蓝 流光壁纸底 */
117
+ --nf-glass-bg-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='1600' height='1000'%3E%3Cdefs%3E%3Cfilter id='b' x='-20%25' y='-20%25' width='140%25' height='140%25'%3E%3CfeGaussianBlur stdDeviation='110'/%3E%3C/filter%3E%3C/defs%3E%3Cg filter='url(%23b)'%3E%3Ccircle cx='300' cy='180' r='420' fill='%2335d07a' fill-opacity='0.62'/%3E%3Ccircle cx='1240' cy='260' r='470' fill='%233aa7ff' fill-opacity='0.58'/%3E%3Ccircle cx='900' cy='860' r='470' fill='%2340cfc0' fill-opacity='0.5'/%3E%3Ccircle cx='1500' cy='820' r='330' fill='%23ff9fb0' fill-opacity='0.4'/%3E%3Ccircle cx='600' cy='620' r='260' fill='%23b06ef0' fill-opacity='0.42'/%3E%3Ccircle cx='180' cy='600' r='220' fill='%23ffd166' fill-opacity='0.36'/%3E%3C/g%3E%3C/svg%3E");
102
118
  background: var(--nf-bg);
103
119
  /* Frosted glass: blur whatever is behind the panel (the chat dialog),
104
120
  * so translucency shows a soft blur instead of readable content. */
105
- -webkit-backdrop-filter: blur(32px) saturate(180%);
106
- backdrop-filter: blur(32px) saturate(180%);
121
+ -webkit-backdrop-filter: blur(30px) saturate(170%) brightness(1.04);
122
+ backdrop-filter: blur(30px) saturate(170%) brightness(1.04);
107
123
  color: var(--nf-text);
108
- }
109
-
110
- body[data-ds-dark-theme] .view {
124
+ /* ------------------------------------------------------------------
125
+ * Unified size tokens (单一尺寸来源).
126
+ * 约定:主题(data-nf-theme/data-nf-mode)只改颜色/质感,永不覆盖这些
127
+ * 尺寸令牌;界面密度(data-nf-density)是唯一允许重定义尺寸的开关。
128
+ * ------------------------------------------------------------------ */
129
+ /* 字号档:12=次要文本 / 14=主文本 / 16+ = 标题与大数字 */
130
+ --nf-fs-10: 10px;
131
+ --nf-fs-12: 12px;
132
+ --nf-fs-14: 14px;
133
+ --nf-fs-16: 16px;
134
+ --nf-fs-18: 18px;
135
+ --nf-fs-20: 20px;
136
+ --nf-fs-22: 22px;
137
+ --nf-fs-24: 24px;
138
+ --nf-fs-34: 34px;
139
+ --nf-fs-42: 42px;
140
+ /* 图标尺寸档 */
141
+ --nf-icon-s: 14px;
142
+ --nf-icon-m: 16px;
143
+ --nf-icon-l: 18px;
144
+ --nf-icon-xl: 22px;
145
+ /* 间距档 */
146
+ --nf-space-2: 2px;
147
+ --nf-space-4: 4px;
148
+ --nf-space-6: 6px;
149
+ --nf-space-8: 8px;
150
+ --nf-space-10: 10px;
151
+ --nf-space-12: 12px;
152
+ --nf-space-14: 14px;
153
+ --nf-space-16: 16px;
154
+ --nf-space-18: 18px;
155
+ --nf-space-20: 20px;
156
+ --nf-space-24: 24px;
157
+ --nf-space-28: 28px;
158
+ --nf-space-32: 32px;
159
+ /* 圆角档 */
160
+ --nf-radius-2: 2px;
161
+ --nf-radius-4: 4px;
162
+ --nf-radius-6: 6px;
163
+ --nf-radius-8: 8px;
164
+ --nf-radius-10: 10px;
165
+ --nf-radius-12: 12px;
166
+ --nf-radius-14: 14px;
167
+ --nf-radius-16: 16px;
168
+ --nf-radius-20: 20px;
169
+ --nf-radius-22: 22px;
170
+ --nf-radius-999: 999px;
171
+ /* 控件高度档 */
172
+ --nf-ctrl-s: 28px;
173
+ --nf-ctrl-m: 32px;
174
+ --nf-ctrl-l: 38px;
175
+ /* 页面主容器(以设置页为基准)与卡片 */
176
+ --nf-container-pad: 20px 22px;
177
+ --nf-container-gap: var(--nf-space-14, 14px);
178
+ --nf-card-pad: 20px 22px;
179
+ --nf-nav-pad: 16px 12px 14px;
180
+ }
181
+
182
+ /* 深色基准:由面板显示模式驱动(强制 dark / system 跟随宿主深色)。
183
+ * 注意 .view 是 .panel 的父容器,承载 background 与 color-scheme,必须同步设深色变量,
184
+ * 否则 .panel 设了深色也无法回传给父级 .view → 面板背景永远浅色。
185
+ * :has() 用于让 .view 跟随显式强制 dark/light(宿主深色时排除强制 light)。 */
186
+ .panel[data-nf-mode='dark'],
187
+ body[data-ds-dark-theme] .panel:not([data-nf-mode]),
188
+ .view:has(> .panel[data-nf-mode='dark']),
189
+ body[data-ds-dark-theme] .view:not(:has(> .panel[data-nf-mode='light'])) {
111
190
  color-scheme: dark;
112
191
  /* iOS dark palette — near-black canvas with green Liquid-Glass accents */
113
192
  --nf-bg: rgba(10, 11, 13, 0.86);
@@ -132,15 +211,30 @@ body[data-ds-dark-theme] .view {
132
211
  --nf-shadow-lg: 0 4px 12px rgba(0, 0, 0, 0.4), 0 20px 48px rgba(0, 0, 0, 0.55);
133
212
  --nf-card-shadow: 0 2px 6px rgba(0, 0, 0, 0.35), 0 14px 38px rgba(0, 0, 0, 0.45);
134
213
  --nf-card-shadow-hover: 0 4px 10px rgba(0, 0, 0, 0.4), 0 22px 52px rgba(0, 0, 0, 0.55);
135
- /* Liquid Glass (dark): translucent charcoal glass face + soft bright core */
136
- --nf-glass-face: linear-gradient(180deg, rgba(112, 116, 122, 0.42) 0%, rgba(96, 100, 106, 0.42) 26%, rgba(82, 85, 90, 0.42) 52%, rgba(68, 71, 76, 0.42) 78%, rgba(56, 58, 63, 0.42) 100%);
137
- --nf-glass-core: radial-gradient(30% 24% at 36% 28%, rgba(255, 255, 255, 0.26) 0%, rgba(255, 255, 255, 0.10) 45%, rgba(255, 255, 255, 0) 78%);
138
- --nf-glass-sheen: rgba(255, 255, 255, 0.26);
214
+ /* Liquid Glass (dark): 薄透玻璃面(透明度以文字清晰为先)+ 顶部高光 + 淡描边 */
215
+ --nf-glass-face: linear-gradient(180deg, rgba(62, 66, 74, 0.52) 0%, rgba(54, 58, 66, 0.46) 26%, rgba(48, 52, 60, 0.40) 52%, rgba(42, 46, 54, 0.36) 78%, rgba(38, 42, 50, 0.34) 100%);
216
+ --nf-glass-core: radial-gradient(60% 40% at 30% 0%, rgba(255, 255, 255, 0.22) 0%, rgba(255, 255, 255, 0.08) 42%, rgba(255, 255, 255, 0) 78%);
217
+ --nf-glass-sheen: rgba(255, 255, 255, 0.24);
139
218
  --nf-glass-border: rgba(255, 255, 255, 0.14);
140
- --nf-glass-inset: rgba(255, 255, 255, 0.07);
141
- --nf-glass-orb-a: rgba(0, 202, 82, 0.28);
142
- --nf-glass-orb-b: rgba(190, 200, 215, 0.10);
219
+ --nf-glass-inset: rgba(255, 255, 255, 0.08);
220
+ --nf-glass-orb-a: rgba(0, 202, 82, 0.36);
221
+ --nf-glass-orb-b: rgba(120, 160, 255, 0.28);
143
222
  --nf-glass-noise: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.8' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23n)'/%3E%3C/svg%3E");
223
+ /* 深色液态容器形态 */
224
+ --nf-card-radius: 20px;
225
+ --nf-card-blur: 28px;
226
+ --nf-card-saturate: 165%;
227
+ --nf-card-brightness: 1;
228
+ --nf-card-border: 1px solid rgba(255, 255, 255, 0.14);
229
+ --nf-card-sheen: rgba(255, 255, 255, 0.22);
230
+ /* 深色液态专用壁纸:压暗浓郁光斑(仅默认液态,macos/neumorph 在各自块覆盖) */
231
+ --nf-glass-bg-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='1600' height='1000'%3E%3Cdefs%3E%3Cfilter id='b' x='-20%25' y='-20%25' width='140%25' height='140%25'%3E%3CfeGaussianBlur stdDeviation='110'/%3E%3C/filter%3E%3C/defs%3E%3Cg filter='url(%23b)'%3E%3Ccircle cx='300' cy='180' r='420' fill='%231a9f4d' fill-opacity='0.44'/%3E%3Ccircle cx='1240' cy='260' r='470' fill='%23268bd6' fill-opacity='0.40'/%3E%3Ccircle cx='900' cy='860' r='470' fill='%232a9e94' fill-opacity='0.36'/%3E%3Ccircle cx='1500' cy='820' r='330' fill='%23e07a94' fill-opacity='0.30'/%3E%3Ccircle cx='600' cy='620' r='260' fill='%238c5bd6' fill-opacity='0.32'/%3E%3C/g%3E%3C/svg%3E");
232
+ /* 深色液态控件 */
233
+ --nf-ctrl-radius: 14px;
234
+ --nf-ctrl-bg: var(--nf-bg-raise);
235
+ --nf-ctrl-border: 1px solid rgba(255, 255, 255, 0.18);
236
+ --nf-ctrl-sheen: rgba(255, 255, 255, 0.2);
237
+ --nf-ctrl-caret: var(--nf-accent);
144
238
  }
145
239
 
146
240
  html[data-dsh-novelforge-active]:not([data-dsh-taskboard-active]):not([data-dsh-ssh-active]) .view {
@@ -149,45 +243,132 @@ html[data-dsh-novelforge-active]:not([data-dsh-taskboard-active]):not([data-dsh-
149
243
 
150
244
  /* ------------------------------------------------------------ themes
151
245
  * 'liquid' (default): iOS Liquid Glass, green accent — set on .view above.
152
- * 'classic': original frosted iOS look, blue accent — overrides below.
246
+ * 'macos' / 'neumorph' override below.
153
247
  */
154
- .panel[data-nf-theme='classic'] {
248
+
249
+ /* ------------------------------------------------------------
250
+ * 'macos': macOS 玻璃(浅色默认 / 深色亮蓝),强调色随外观自动切换 #007aff / #0a84ff。
251
+ * 第二个选择器:深色系统下强制「浅色」显示模式时也能覆盖宿主的深色规则。
252
+ * ------------------------------------------------------------ */
253
+ .panel[data-nf-theme='macos'],
254
+ body[data-ds-dark-theme] .panel[data-nf-mode='light'][data-nf-theme='macos'] {
255
+ --nf-bg: rgba(245, 246, 248, 0.92);
256
+ --nf-bg-raise: rgba(255, 255, 255, 0.78);
257
+ --nf-bg-inset: rgba(118, 118, 128, 0.1);
258
+ --nf-border: rgba(60, 60, 67, 0.14);
259
+ --nf-border-strong: rgba(60, 60, 67, 0.3);
260
+ --nf-text: #1d1d1f;
261
+ --nf-text-2: #3a3a3c;
262
+ --nf-text-2-alpha: rgba(58, 58, 60, 0.7);
263
+ --nf-text-3: #86868b;
155
264
  --nf-accent: #007aff;
156
265
  --nf-accent-hover: #0071e3;
157
266
  --nf-accent-soft: rgba(0, 122, 255, 0.12);
158
267
  --nf-accent-fg: #ffffff;
268
+ --nf-hover: rgba(0, 0, 0, 0.04);
159
269
  --nf-info: #5856d6;
160
- --nf-glass-face: var(--nf-bg-raise);
270
+ --nf-shadow: 0 1px 3px rgba(0, 0, 0, 0.05), 0 10px 28px rgba(0, 0, 0, 0.07);
271
+ --nf-shadow-lg: 0 4px 12px rgba(0, 0, 0, 0.06), 0 18px 44px rgba(0, 0, 0, 0.11);
272
+ --nf-card-shadow: 0 2px 6px rgba(0, 0, 0, 0.05), 0 12px 34px rgba(0, 0, 0, 0.09);
273
+ --nf-card-shadow-hover: 0 4px 10px rgba(0, 0, 0, 0.07), 0 20px 48px rgba(0, 0, 0, 0.14);
274
+ --nf-glass-face: rgba(255, 255, 255, 0.7);
161
275
  --nf-glass-core: transparent;
162
- --nf-glass-sheen: rgba(255, 255, 255, 0);
163
- --nf-glass-border: var(--nf-border);
164
- --nf-glass-inset: var(--nf-bg-inset);
165
- --nf-glass-orb-a: transparent;
166
- --nf-glass-orb-b: transparent;
276
+ --nf-glass-sheen: rgba(255, 255, 255, 0.8);
277
+ --nf-glass-border: rgba(255, 255, 255, 0.9);
278
+ --nf-glass-inset: rgba(255, 255, 255, 0.6);
279
+ --nf-glass-orb-a: rgba(0, 122, 255, 0.08);
280
+ --nf-glass-orb-b: rgba(88, 86, 214, 0.07);
167
281
  --nf-glass-noise: none;
168
- }
169
-
170
- body[data-ds-dark-theme] .panel[data-nf-theme='classic'] {
282
+ /* macOS 容器:小圆角 + 高模糊低饱和 + 冷描边,玻璃面板质感 */
283
+ --nf-card-radius: 12px;
284
+ --nf-card-blur: 42px;
285
+ --nf-card-saturate: 150%;
286
+ --nf-card-border: 1px solid var(--nf-border);
287
+ --nf-card-sheen: rgba(255, 255, 255, 0.35);
288
+ /* macOS 控件:小圆角 + 玻璃底 + 冷描边 + 蓝色箭头(focus 蓝环见特写) */
289
+ --nf-ctrl-radius: 8px;
290
+ --nf-ctrl-bg: var(--nf-bg-raise);
291
+ --nf-ctrl-border: 1px solid var(--nf-border-strong);
292
+ --nf-ctrl-sheen: rgba(255, 255, 255, 0.35);
293
+ --nf-ctrl-caret: var(--nf-accent);
294
+ }
295
+
296
+ .panel[data-nf-mode='dark'][data-nf-theme='macos'],
297
+ body[data-ds-dark-theme] .panel[data-nf-theme='macos']:not([data-nf-mode]) {
298
+ --nf-bg: rgba(28, 28, 30, 0.9);
299
+ --nf-bg-raise: rgba(44, 44, 46, 0.82);
300
+ --nf-bg-inset: rgba(118, 118, 128, 0.18);
301
+ --nf-border: rgba(255, 255, 255, 0.12);
302
+ --nf-border-strong: rgba(255, 255, 255, 0.26);
303
+ --nf-text: #f5f5f7;
304
+ --nf-text-2: #d1d1d6;
305
+ --nf-text-2-alpha: rgba(209, 209, 214, 0.7);
306
+ --nf-text-3: #98989d;
171
307
  --nf-accent: #0a84ff;
172
308
  --nf-accent-hover: #3a9bff;
173
309
  --nf-accent-soft: rgba(10, 132, 255, 0.2);
174
310
  --nf-accent-fg: #ffffff;
311
+ --nf-hover: rgba(255, 255, 255, 0.06);
175
312
  --nf-info: #bf5af2;
176
- --nf-glass-face: var(--nf-bg-raise);
313
+ --nf-shadow: 0 1px 2px rgba(0, 0, 0, 0.4), 0 10px 30px rgba(0, 0, 0, 0.45);
314
+ --nf-shadow-lg: 0 4px 12px rgba(0, 0, 0, 0.45), 0 18px 44px rgba(0, 0, 0, 0.6);
315
+ --nf-card-shadow: 0 2px 6px rgba(0, 0, 0, 0.4), 0 14px 38px rgba(0, 0, 0, 0.5);
316
+ --nf-card-shadow-hover: 0 4px 10px rgba(0, 0, 0, 0.45), 0 22px 52px rgba(0, 0, 0, 0.6);
317
+ --nf-glass-face: rgba(44, 44, 46, 0.85);
177
318
  --nf-glass-core: transparent;
178
- --nf-glass-sheen: rgba(255, 255, 255, 0);
179
- --nf-glass-border: var(--nf-border);
180
- --nf-glass-inset: var(--nf-bg-inset);
181
- --nf-glass-orb-a: transparent;
182
- --nf-glass-orb-b: transparent;
319
+ --nf-glass-sheen: rgba(255, 255, 255, 0.2);
320
+ --nf-glass-border: rgba(255, 255, 255, 0.18);
321
+ --nf-glass-inset: rgba(255, 255, 255, 0.06);
322
+ --nf-glass-orb-a: rgba(10, 132, 255, 0.16);
323
+ --nf-glass-orb-b: rgba(191, 90, 242, 0.08);
183
324
  --nf-glass-noise: none;
184
325
  }
185
326
 
327
+ /* macOS 按钮 / 输入框玻璃化(圆角由基础 .button/.input 引用 --nf-ctrl-radius 形态令牌提供) */
328
+ .panel[data-nf-theme='macos'] .button {
329
+ border: 1px solid var(--nf-border-strong);
330
+ background: color-mix(in srgb, var(--nf-bg-raise) 82%, #fff);
331
+ box-shadow: 0 1px 1px rgba(0, 0, 0, 0.04), inset 0 1px 0 rgba(255, 255, 255, 0.6);
332
+ }
333
+ .panel[data-nf-theme='macos'] .buttonPrimary {
334
+ background: linear-gradient(180deg, color-mix(in srgb, var(--nf-accent) 90%, #fff), var(--nf-accent));
335
+ border-color: transparent;
336
+ color: var(--nf-accent-fg);
337
+ box-shadow: 0 1px 3px color-mix(in srgb, var(--nf-accent) 45%, transparent), inset 0 1px 0 rgba(255, 255, 255, 0.35);
338
+ }
339
+ .panel[data-nf-theme='macos'] .input,
340
+ .panel[data-nf-theme='macos'] .textarea {
341
+ border: 1px solid var(--nf-border-strong);
342
+ background: var(--nf-bg-raise);
343
+ }
344
+ .panel[data-nf-theme='macos'] .input:focus,
345
+ .panel[data-nf-theme='macos'] .textarea:focus {
346
+ border-color: var(--nf-accent);
347
+ box-shadow: 0 0 0 3px var(--nf-accent-soft);
348
+ }
349
+
186
350
  /* ------------------------------------------------------------
187
351
  * 'neumorph': Neumorphism (dual-shadow soft UI).
188
352
  * Light variant in light mode; a dark dual-shadow variant in dark
189
353
  * mode so switching always has a visible effect.
190
354
  * ------------------------------------------------------------ */
355
+ /* 新拟物容器:实色无模糊、较大圆角、无内高光(不依赖深浅,任何模式一致) */
356
+ .panel[data-nf-theme='neumorph'] {
357
+ --nf-card-radius: 20px;
358
+ --nf-card-blur: 0px;
359
+ --nf-card-saturate: 100%;
360
+ --nf-card-border: none;
361
+ --nf-card-sheen: rgba(255, 255, 255, 0);
362
+ /* 新拟物控件:实色无模糊 + 较大圆角 + 无内高光(深浅一致) */
363
+ --nf-ctrl-radius: 10px;
364
+ --nf-ctrl-bg: var(--nf-bg-inset);
365
+ --nf-ctrl-border: none;
366
+ --nf-ctrl-sheen: rgba(255, 255, 255, 0);
367
+ --nf-ctrl-caret: var(--nf-text-3);
368
+ /* 新拟物:实色,无玻璃底图 */
369
+ --nf-glass-bg-image: none;
370
+ }
371
+
191
372
  body:not([data-ds-dark-theme]) .panel[data-nf-theme='neumorph'] {
192
373
  --nf-bg: #e4e9f2;
193
374
  --nf-bg-raise: #e4e9f2;
@@ -213,7 +394,8 @@ body:not([data-ds-dark-theme]) .panel[data-nf-theme='neumorph'] {
213
394
  --nf-glass-noise: none;
214
395
  }
215
396
 
216
- body[data-ds-dark-theme] .panel[data-nf-theme='neumorph'] {
397
+ .panel[data-nf-mode='dark'][data-nf-theme='neumorph'],
398
+ body[data-ds-dark-theme] .panel[data-nf-theme='neumorph']:not([data-nf-mode]) {
217
399
  --nf-bg: #2b2f36;
218
400
  --nf-bg-raise: #2b2f36;
219
401
  --nf-bg-inset: #25292f;
@@ -237,6 +419,153 @@ body[data-ds-dark-theme] .panel[data-nf-theme='neumorph'] {
237
419
  --nf-glass-orb-b: transparent;
238
420
  --nf-glass-noise: none;
239
421
  }
422
+ /* ------------------------------------------------------------
423
+ * 'clay': Claymorphism(粘土拟态)—— 柔软圆润、同色系软阴影、奶油底色。
424
+ * 实心(无 backdrop 模糊)、大圆角、双阴影制造"黏土鼓起"感。
425
+ * ------------------------------------------------------------ */
426
+ /* 粘土形态(深浅一致):大圆角、无模糊、奶油高光描边、软阴影 */
427
+ .panel[data-nf-theme='clay'] {
428
+ /* 容器:大圆角 + 实心(关闭玻璃模糊)+ 顶部奶油高光 */
429
+ --nf-card-radius: 28px;
430
+ --nf-card-blur: 0px;
431
+ --nf-card-saturate: 100%;
432
+ --nf-card-brightness: 1;
433
+ --nf-card-border: 1px solid rgba(255, 255, 255, 0.6);
434
+ --nf-card-sheen: rgba(255, 255, 255, 0.85);
435
+ /* 控件:圆润 + 同色系软阴影 + 顶部高光 */
436
+ --nf-ctrl-radius: 16px;
437
+ --nf-ctrl-bg: var(--nf-bg-raise);
438
+ --nf-ctrl-border: 1px solid rgba(255, 255, 255, 0.55);
439
+ --nf-ctrl-sheen: rgba(255, 255, 255, 0.7);
440
+ --nf-ctrl-caret: var(--nf-accent);
441
+ /* 粘土为实心:无玻璃壁纸 */
442
+ --nf-glass-bg-image: none;
443
+ }
444
+
445
+ /* 浅色粘土(默认浅色系统 / 强制浅色) */
446
+ body:not([data-ds-dark-theme]) .panel[data-nf-theme='clay'],
447
+ .panel[data-nf-mode='light'][data-nf-theme='clay'] {
448
+ --nf-bg: #f2eae0;
449
+ --nf-bg-raise: #efe4d6;
450
+ --nf-bg-inset: #e6d8c6;
451
+ --nf-border: rgba(120, 96, 72, 0.16);
452
+ --nf-border-strong: rgba(120, 96, 72, 0.28);
453
+ --nf-text: #3a3330;
454
+ --nf-text-2: #5a4f48;
455
+ --nf-text-2-alpha: rgba(90, 79, 72, 0.7);
456
+ --nf-text-3: #9a8c80;
457
+ --nf-accent: #e08a5c;
458
+ --nf-accent-hover: #d67a4a;
459
+ --nf-accent-soft: rgba(224, 138, 92, 0.16);
460
+ --nf-accent-fg: #ffffff;
461
+ --nf-hover: rgba(120, 96, 72, 0.08);
462
+ --nf-success: #7fae6a;
463
+ --nf-error: #c96b63;
464
+ --nf-warn: #d9a660;
465
+ --nf-info: #e08a5c;
466
+ --nf-shadow: 0 8px 16px -6px rgba(90, 70, 50, 0.28), inset 0 6px 10px rgba(255, 255, 255, 0.55), inset 0 -6px 10px rgba(120, 96, 72, 0.12);
467
+ --nf-shadow-lg: 0 16px 28px -10px rgba(90, 70, 50, 0.34), inset 0 6px 10px rgba(255, 255, 255, 0.55), inset 0 -6px 10px rgba(120, 96, 72, 0.14);
468
+ --nf-card-shadow: 0 16px 28px -10px rgba(90, 70, 50, 0.34), inset 0 -8px 12px rgba(120, 96, 72, 0.14), inset 0 8px 12px rgba(255, 255, 255, 0.6);
469
+ --nf-card-shadow-hover: 0 22px 36px -12px rgba(90, 70, 50, 0.38), inset 0 -8px 12px rgba(120, 96, 72, 0.16), inset 0 8px 12px rgba(255, 255, 255, 0.7);
470
+ --nf-glass-face: #efe4d6;
471
+ --nf-glass-core: transparent;
472
+ --nf-glass-sheen: rgba(255, 255, 255, 0.85);
473
+ --nf-glass-border: rgba(255, 255, 255, 0.6);
474
+ --nf-glass-inset: #e6d8c6;
475
+ --nf-glass-orb-a: transparent;
476
+ --nf-glass-orb-b: transparent;
477
+ --nf-glass-noise: none;
478
+ }
479
+
480
+ /* 深色粘土(强制深色 / system 深色系统) */
481
+ .panel[data-nf-mode='dark'][data-nf-theme='clay'],
482
+ body[data-ds-dark-theme] .panel[data-nf-theme='clay']:not([data-nf-mode]) {
483
+ --nf-bg: #2a2522;
484
+ --nf-bg-raise: #37302b;
485
+ --nf-bg-inset: #2f2925;
486
+ --nf-border: rgba(255, 255, 255, 0.08);
487
+ --nf-border-strong: rgba(255, 255, 255, 0.18);
488
+ --nf-text: #efe9e3;
489
+ --nf-text-2: #c7beb5;
490
+ --nf-text-2-alpha: rgba(199, 190, 181, 0.7);
491
+ --nf-text-3: #8a8078;
492
+ --nf-accent: #e69a6c;
493
+ --nf-accent-hover: #f0ac82;
494
+ --nf-accent-soft: rgba(230, 154, 108, 0.2);
495
+ --nf-accent-fg: #241b16;
496
+ --nf-hover: rgba(255, 255, 255, 0.06);
497
+ --nf-success: #9cba82;
498
+ --nf-error: #d98f86;
499
+ --nf-warn: #d9a660;
500
+ --nf-info: #e69a6c;
501
+ --nf-shadow: 0 8px 16px -6px rgba(0, 0, 0, 0.55), inset 0 6px 10px rgba(255, 255, 255, 0.12), inset 0 -6px 10px rgba(0, 0, 0, 0.35);
502
+ --nf-shadow-lg: 0 16px 28px -10px rgba(0, 0, 0, 0.62), inset 0 6px 10px rgba(255, 255, 255, 0.12), inset 0 -6px 10px rgba(0, 0, 0, 0.4);
503
+ --nf-card-shadow: 0 16px 28px -10px rgba(0, 0, 0, 0.62), inset 0 -8px 12px rgba(0, 0, 0, 0.4), inset 0 8px 12px rgba(255, 255, 255, 0.14);
504
+ --nf-card-shadow-hover: 0 22px 36px -12px rgba(0, 0, 0, 0.68), inset 0 -8px 12px rgba(0, 0, 0, 0.44), inset 0 8px 12px rgba(255, 255, 255, 0.18);
505
+ --nf-glass-face: #37302b;
506
+ --nf-glass-core: transparent;
507
+ --nf-glass-sheen: rgba(255, 255, 255, 0.16);
508
+ --nf-glass-border: rgba(255, 255, 255, 0.16);
509
+ --nf-glass-inset: #2f2925;
510
+ --nf-glass-orb-a: transparent;
511
+ --nf-glass-orb-b: transparent;
512
+ --nf-glass-noise: none;
513
+ }
514
+
515
+ /* 粘土输入框:凹陷黏土内阴影(深浅一致,深色下另覆盖) */
516
+ .panel[data-nf-theme='clay'] .input,
517
+ .panel[data-nf-theme='clay'] .textarea {
518
+ background: var(--nf-bg-inset);
519
+ border-color: var(--nf-border-strong);
520
+ box-shadow: inset 3px 3px 7px rgba(120, 96, 72, 0.14), inset -3px -3px 7px rgba(255, 255, 255, 0.5);
521
+ }
522
+
523
+ /* 粘土按钮:柔和的"黏土凸起"——外围软投影 + 顶部奶油高光 + 底部厚影 */
524
+ body:not([data-ds-dark-theme]) .panel[data-nf-theme='clay'] .button {
525
+ border-color: rgba(255, 255, 255, 0.6);
526
+ background: linear-gradient(180deg, #f6ecdf, #eee0cf);
527
+ box-shadow: 0 8px 16px -6px rgba(90, 70, 50, 0.35), inset 0 3px 4px rgba(255, 255, 255, 0.8), inset 0 -3px 5px rgba(120, 96, 72, 0.2);
528
+ }
529
+
530
+ body:not([data-ds-dark-theme]) .panel[data-nf-theme='clay'] .button:hover:not([disabled]) {
531
+ box-shadow: 0 12px 22px -8px rgba(90, 70, 50, 0.42), inset 0 3px 4px rgba(255, 255, 255, 0.85), inset 0 -3px 5px rgba(120, 96, 72, 0.22);
532
+ }
533
+
534
+ body:not([data-ds-dark-theme]) .panel[data-nf-theme='clay'] .buttonPrimary {
535
+ background: linear-gradient(180deg, #eda178, #e08a5c);
536
+ border-color: transparent;
537
+ color: var(--nf-accent-fg);
538
+ box-shadow: 0 8px 16px -6px rgba(224, 138, 92, 0.55), inset 0 3px 4px rgba(255, 255, 255, 0.5), inset 0 -3px 5px rgba(150, 70, 40, 0.3);
539
+ }
540
+
541
+ /* 深色粘土按钮 */
542
+ .panel[data-nf-mode='dark'][data-nf-theme='clay'] .button,
543
+ body[data-ds-dark-theme] .panel[data-nf-theme='clay']:not([data-nf-mode]) .button {
544
+ border-color: rgba(255, 255, 255, 0.16);
545
+ background: linear-gradient(180deg, #403731, #332c27);
546
+ box-shadow: 0 8px 16px -6px rgba(0, 0, 0, 0.55), inset 0 3px 4px rgba(255, 255, 255, 0.14), inset 0 -3px 5px rgba(0, 0, 0, 0.4);
547
+ }
548
+
549
+ .panel[data-nf-mode='dark'][data-nf-theme='clay'] .button:hover:not([disabled]),
550
+ body[data-ds-dark-theme] .panel[data-nf-theme='clay']:not([data-nf-mode]) .button:hover:not([disabled]) {
551
+ box-shadow: 0 12px 22px -8px rgba(0, 0, 0, 0.6), inset 0 3px 4px rgba(255, 255, 255, 0.16), inset 0 -3px 5px rgba(0, 0, 0, 0.44);
552
+ }
553
+
554
+ .panel[data-nf-mode='dark'][data-nf-theme='clay'] .buttonPrimary,
555
+ body[data-ds-dark-theme] .panel[data-nf-theme='clay']:not([data-nf-mode]) .buttonPrimary {
556
+ background: linear-gradient(180deg, #f0ac82, #d67a4a);
557
+ border-color: transparent;
558
+ color: var(--nf-accent-fg);
559
+ box-shadow: 0 8px 16px -6px rgba(230, 154, 108, 0.5), inset 0 3px 4px rgba(255, 255, 255, 0.4), inset 0 -3px 5px rgba(120, 50, 20, 0.3);
560
+ }
561
+
562
+ .panel[data-nf-mode='dark'][data-nf-theme='clay'] .input,
563
+ .panel[data-nf-mode='dark'][data-nf-theme='clay'] .textarea,
564
+ body[data-ds-dark-theme] .panel[data-nf-theme='clay']:not([data-nf-mode]) .input,
565
+ body[data-ds-dark-theme] .panel[data-nf-theme='clay']:not([data-nf-mode]) .textarea {
566
+ box-shadow: inset 3px 3px 7px rgba(0, 0, 0, 0.45), inset -3px -3px 7px rgba(255, 255, 255, 0.08);
567
+ }
568
+
240
569
 
241
570
  /* Neumorphic inset inputs (sunken). */
242
571
  body:not([data-ds-dark-theme]) .panel[data-nf-theme='neumorph'] .input,
@@ -315,13 +644,13 @@ body[data-ds-dark-theme] .panel[data-nf-theme='neumorph'] .buttonPrimary {
315
644
  flex-direction: column;
316
645
  height: 100%;
317
646
  min-width: 0;
318
- font-size: 14px;
647
+ font-size: var(--nf-fs-14, 14px);
319
648
  line-height: 1.6;
320
649
  position: relative;
321
650
  overflow: hidden;
322
651
  }
323
652
 
324
- /* Liquid-Glass backdrop: colored orbs + vignette behind the frosted cards. */
653
+ /* Liquid-Glass backdrop: themed abstract image + colored orbs + vignette behind the frosted cards. */
325
654
  .panel::before {
326
655
  content: '';
327
656
  position: absolute;
@@ -329,26 +658,32 @@ body[data-ds-dark-theme] .panel[data-nf-theme='neumorph'] .buttonPrimary {
329
658
  z-index: 0;
330
659
  pointer-events: none;
331
660
  background:
661
+ var(--nf-glass-bg-image, none) center / cover no-repeat,
332
662
  radial-gradient(46% 36% at 18% 12%, var(--nf-glass-orb-a), transparent 70%),
333
663
  radial-gradient(52% 42% at 88% 22%, var(--nf-glass-orb-b), transparent 72%),
334
664
  radial-gradient(120% 95% at 50% 42%, transparent 55%, rgba(2, 2, 3, 0.10) 100%);
335
665
  }
336
666
 
667
+ /* --- 玻璃主题背后的「抽象壁纸」底图(每主题一种色调,供卡片 blur 出真实玻璃感) --- */
668
+ .panel[data-nf-theme='macos'] {
669
+ --nf-glass-bg-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='1600' height='1000'%3E%3Cdefs%3E%3Cfilter id='b' x='-20%25' y='-20%25' width='140%25' height='140%25'%3E%3CfeGaussianBlur stdDeviation='140'/%3E%3C/filter%3E%3C/defs%3E%3Cg filter='url(%23b)'%3E%3Ccircle cx='320' cy='220' r='320' fill='%230a84ff' fill-opacity='0.34'/%3E%3Ccircle cx='1180' cy='320' r='360' fill='%237f5af0' fill-opacity='0.30'/%3E%3Ccircle cx='920' cy='820' r='380' fill='%2340cfc0' fill-opacity='0.26'/%3E%3Ccircle cx='1460' cy='820' r='260' fill='%23ff9fb0' fill-opacity='0.18'/%3E%3C/g%3E%3C/svg%3E");
670
+ }
671
+
337
672
  .panelTitle {
338
673
  margin: 0;
339
- font-size: 16px;
674
+ font-size: var(--nf-fs-16, 16px);
340
675
  font-weight: 700;
341
676
  letter-spacing: 0.2px;
342
677
  display: flex;
343
678
  align-items: center;
344
- gap: 8px;
679
+ gap: var(--nf-space-8, 8px);
345
680
  }
346
681
 
347
682
  .panelTitle::before {
348
683
  content: '';
349
684
  width: 4px;
350
685
  height: 16px;
351
- border-radius: 2px;
686
+ border-radius: var(--nf-radius-2, 2px);
352
687
  background: linear-gradient(180deg, var(--nf-accent), var(--nf-info));
353
688
  }
354
689
 
@@ -356,10 +691,10 @@ body[data-ds-dark-theme] .panel[data-nf-theme='neumorph'] .buttonPrimary {
356
691
  border: none;
357
692
  background: transparent;
358
693
  cursor: pointer;
359
- font-size: 16px;
694
+ font-size: var(--nf-fs-16, 16px);
360
695
  color: var(--nf-text-2);
361
- padding: 4px 9px;
362
- border-radius: 9px;
696
+ padding: var(--nf-space-4, 4px) var(--nf-space-10, 9px);
697
+ border-radius: var(--nf-radius-10, 9px);
363
698
  transition: background 0.15s ease, color 0.15s ease, transform 0.1s ease;
364
699
  }
365
700
 
@@ -373,8 +708,8 @@ body[data-ds-dark-theme] .panel[data-nf-theme='neumorph'] .buttonPrimary {
373
708
 
374
709
  .tabBar {
375
710
  display: flex;
376
- gap: 2px;
377
- padding: 8px 14px 0;
711
+ gap: var(--nf-space-2, 2px);
712
+ padding: var(--nf-space-8, 8px) var(--nf-space-14, 14px) 0;
378
713
  border-bottom: 1px solid var(--nf-border);
379
714
  flex-shrink: 0;
380
715
  background: var(--nf-bg-raise);
@@ -386,10 +721,10 @@ body[data-ds-dark-theme] .panel[data-nf-theme='neumorph'] .buttonPrimary {
386
721
  .tab {
387
722
  border: none;
388
723
  background: transparent;
389
- padding: 7px 13px;
724
+ padding: var(--nf-space-8, 7px) var(--nf-space-14, 13px);
390
725
  cursor: pointer;
391
- border-radius: 8px 8px 0 0;
392
- font-size: 13.5px;
726
+ border-radius: var(--nf-radius-8, 8px) var(--nf-radius-8, 8px) 0 0;
727
+ font-size: var(--nf-fs-14, 13.5px);
393
728
  color: var(--nf-text-2);
394
729
  transition: color 0.15s ease, background 0.15s ease;
395
730
  position: relative;
@@ -413,17 +748,17 @@ body[data-ds-dark-theme] .panel[data-nf-theme='neumorph'] .buttonPrimary {
413
748
  right: 10px;
414
749
  bottom: -1px;
415
750
  height: 2.5px;
416
- border-radius: 2px 2px 0 0;
751
+ border-radius: var(--nf-radius-2, 2px) var(--nf-radius-2, 2px) 0 0;
417
752
  background: var(--nf-accent);
418
753
  }
419
754
 
420
755
  .panelContent {
421
756
  flex: 1;
422
757
  overflow: auto;
423
- padding: var(--nf-density-pad, 16px 18px 20px);
758
+ padding: var(--nf-container-pad, 20px 22px);
424
759
  display: flex;
425
760
  flex-direction: column;
426
- gap: var(--nf-density-gap, 14px);
761
+ gap: var(--nf-container-gap, 14px);
427
762
  position: relative;
428
763
  z-index: 1;
429
764
  }
@@ -444,11 +779,11 @@ body[data-ds-dark-theme] .panel[data-nf-theme='neumorph'] .buttonPrimary {
444
779
  width: 216px;
445
780
  display: flex;
446
781
  flex-direction: column;
447
- gap: 6px;
782
+ gap: var(--nf-space-6, 6px);
448
783
  margin: 10px 0 10px 12px;
449
- padding: var(--nf-density-nav, 16px 12px 14px);
784
+ padding: var(--nf-nav-pad, 16px 12px 14px);
450
785
  border: 1px solid var(--nf-glass-border);
451
- border-radius: 18px;
786
+ border-radius: var(--nf-radius-16, 18px);
452
787
  background: var(--nf-glass-face);
453
788
  box-shadow: var(--nf-shadow), inset 0 1px 0 var(--nf-glass-sheen);
454
789
  -webkit-backdrop-filter: blur(28px) saturate(175%);
@@ -459,22 +794,22 @@ body[data-ds-dark-theme] .panel[data-nf-theme='neumorph'] .buttonPrimary {
459
794
 
460
795
  .panelNavCollapsed {
461
796
  width: 52px;
462
- padding: 10px 6px;
797
+ padding: var(--nf-space-10, 10px) var(--nf-space-6, 6px);
463
798
  }
464
799
 
465
800
  .navGroup {
466
801
  display: flex;
467
802
  flex-direction: column;
468
- gap: 6px;
803
+ gap: var(--nf-space-6, 6px);
469
804
  }
470
805
 
471
806
  .navGroupLabel {
472
- font-size: 12px;
807
+ font-size: var(--nf-fs-12, 12px);
473
808
  font-weight: 600;
474
809
  letter-spacing: 0.8px;
475
810
  text-transform: uppercase;
476
811
  color: var(--nf-text-3);
477
- padding: 12px 10px 6px;
812
+ padding: var(--nf-space-12, 12px) var(--nf-space-10, 10px) var(--nf-space-6, 6px);
478
813
  user-select: none;
479
814
  }
480
815
 
@@ -495,8 +830,8 @@ body[data-ds-dark-theme] .panel[data-nf-theme='neumorph'] .buttonPrimary {
495
830
  flex: none;
496
831
  display: flex;
497
832
  flex-direction: column;
498
- gap: 4px;
499
- padding: 8px 6px 4px;
833
+ gap: var(--nf-space-4, 4px);
834
+ padding: var(--nf-space-8, 8px) var(--nf-space-6, 6px) var(--nf-space-4, 4px);
500
835
  border-top: 1px solid var(--nf-border);
501
836
  margin-top: 4px;
502
837
  }
@@ -505,14 +840,14 @@ body[data-ds-dark-theme] .panel[data-nf-theme='neumorph'] .buttonPrimary {
505
840
  display: flex;
506
841
  align-items: center;
507
842
  justify-content: space-between;
508
- gap: 4px;
843
+ gap: var(--nf-space-4, 4px);
509
844
  border: none;
510
845
  background: transparent;
511
846
  cursor: pointer;
512
- font-size: 11px;
847
+ font-size: var(--nf-fs-12, 11px);
513
848
  color: var(--nf-text-3);
514
- padding: 4px 6px;
515
- border-radius: 8px;
849
+ padding: var(--nf-space-4, 4px) var(--nf-space-6, 6px);
850
+ border-radius: var(--nf-radius-8, 8px);
516
851
  transition: color 0.15s ease, background 0.15s ease;
517
852
  text-align: left;
518
853
  white-space: nowrap;
@@ -528,10 +863,10 @@ body[data-ds-dark-theme] .panel[data-nf-theme='neumorph'] .buttonPrimary {
528
863
  background: var(--nf-accent-soft);
529
864
  color: var(--nf-accent);
530
865
  cursor: pointer;
531
- font-size: 10.5px;
866
+ font-size: var(--nf-fs-12, 10.5px);
532
867
  font-weight: 600;
533
- padding: 4px 6px;
534
- border-radius: 8px;
868
+ padding: var(--nf-space-4, 4px) var(--nf-space-6, 6px);
869
+ border-radius: var(--nf-radius-8, 8px);
535
870
  text-align: left;
536
871
  white-space: nowrap;
537
872
  }
@@ -541,13 +876,13 @@ body[data-ds-dark-theme] .panel[data-nf-theme='neumorph'] .buttonPrimary {
541
876
  }
542
877
 
543
878
  .panelNavCollapsed .navAbout {
544
- padding: 6px 2px 2px;
879
+ padding: var(--nf-space-6, 6px) var(--nf-space-2, 2px) var(--nf-space-2, 2px);
545
880
  align-items: center;
546
881
  }
547
882
 
548
883
  .panelNavCollapsed .navAboutRow {
549
884
  justify-content: center;
550
- padding: 4px 0;
885
+ padding: var(--nf-space-4, 4px) 0;
551
886
  width: 100%;
552
887
  }
553
888
 
@@ -556,11 +891,11 @@ body[data-ds-dark-theme] .panel[data-nf-theme='neumorph'] .buttonPrimary {
556
891
  flex: none;
557
892
  min-width: 18px;
558
893
  height: 18px;
559
- padding: 0 5px;
560
- border-radius: 999px;
894
+ padding: 0 var(--nf-space-6, 5px);
895
+ border-radius: var(--nf-radius-999, 999px);
561
896
  background: var(--nf-accent);
562
897
  color: #fff;
563
- font-size: 10.5px;
898
+ font-size: var(--nf-fs-12, 10.5px);
564
899
  font-weight: 700;
565
900
  line-height: 18px;
566
901
  text-align: center;
@@ -571,11 +906,12 @@ body[data-ds-dark-theme] .panel[data-nf-theme='neumorph'] .buttonPrimary {
571
906
  position: absolute;
572
907
  top: 2px;
573
908
  right: 2px;
574
- min-width: 14px;
575
- height: 14px;
576
- line-height: 14px;
577
- font-size: 9px;
578
- padding: 0 3px;
909
+ /* 字号统一为 12px 后,徽标容器同步放大到 18px 避免溢出 */
910
+ min-width: 18px;
911
+ height: 18px;
912
+ line-height: 18px;
913
+ font-size: var(--nf-fs-12, 9px);
914
+ padding: 0 var(--nf-space-6, 5px);
579
915
  }
580
916
 
581
917
  .navTabBadgeDanger {
@@ -604,14 +940,14 @@ body[data-ds-dark-theme] .panel[data-nf-theme='neumorph'] .buttonPrimary {
604
940
  .navTab {
605
941
  display: flex;
606
942
  align-items: center;
607
- gap: 10px;
943
+ gap: var(--nf-space-10, 10px);
608
944
  width: 100%;
609
945
  border: 1px solid transparent;
610
946
  background: transparent;
611
947
  cursor: pointer;
612
- border-radius: 10px;
613
- padding: 11px 12px;
614
- font-size: 14px;
948
+ border-radius: var(--nf-radius-10, 10px);
949
+ padding: var(--nf-space-12, 11px) var(--nf-space-12, 12px);
950
+ font-size: var(--nf-fs-14, 14px);
615
951
  color: var(--nf-text-2-alpha, var(--nf-text-2));
616
952
  font-weight: 500;
617
953
  transition: color 0.15s ease, background 0.15s ease, border-color 0.15s ease, box-shadow 0.15s ease;
@@ -622,7 +958,7 @@ body[data-ds-dark-theme] .panel[data-nf-theme='neumorph'] .buttonPrimary {
622
958
 
623
959
  .panelNavCollapsed .navTab {
624
960
  justify-content: center;
625
- padding: 8px 0;
961
+ padding: var(--nf-space-8, 8px) 0;
626
962
  }
627
963
 
628
964
  .navTab:hover {
@@ -646,7 +982,7 @@ body[data-ds-dark-theme] .panel[data-nf-theme='neumorph'] .buttonPrimary {
646
982
  flex: none;
647
983
  width: 22px;
648
984
  text-align: center;
649
- font-size: 17px;
985
+ font-size: var(--nf-fs-16, 17px);
650
986
  line-height: 1;
651
987
  }
652
988
 
@@ -659,8 +995,8 @@ body[data-ds-dark-theme] .panel[data-nf-theme='neumorph'] .buttonPrimary {
659
995
  .navTitle {
660
996
  display: flex;
661
997
  align-items: center;
662
- gap: 10px;
663
- padding: 2px 6px 12px;
998
+ gap: var(--nf-space-10, 10px);
999
+ padding: var(--nf-space-2, 2px) var(--nf-space-6, 6px) var(--nf-space-12, 12px);
664
1000
  border-bottom: 1px solid var(--nf-border);
665
1001
  margin-bottom: 6px;
666
1002
  flex: none;
@@ -670,11 +1006,11 @@ body[data-ds-dark-theme] .panel[data-nf-theme='neumorph'] .buttonPrimary {
670
1006
  .navTitleLogo {
671
1007
  width: 34px;
672
1008
  height: 34px;
673
- border-radius: 10px;
1009
+ border-radius: var(--nf-radius-10, 10px);
674
1010
  background: linear-gradient(145deg, var(--nf-accent), var(--nf-accent-hover));
675
1011
  color: var(--nf-accent-fg);
676
1012
  font-weight: 800;
677
- font-size: 15px;
1013
+ font-size: var(--nf-fs-14, 15px);
678
1014
  display: flex;
679
1015
  align-items: center;
680
1016
  justify-content: center;
@@ -684,7 +1020,7 @@ body[data-ds-dark-theme] .panel[data-nf-theme='neumorph'] .buttonPrimary {
684
1020
 
685
1021
  .navTitleName {
686
1022
  font-weight: 700;
687
- font-size: 15px;
1023
+ font-size: var(--nf-fs-14, 15px);
688
1024
  letter-spacing: 0.2px;
689
1025
  white-space: nowrap;
690
1026
  overflow: hidden;
@@ -692,7 +1028,7 @@ body[data-ds-dark-theme] .panel[data-nf-theme='neumorph'] .buttonPrimary {
692
1028
  }
693
1029
 
694
1030
  .navTitleBook {
695
- font-size: 11px;
1031
+ font-size: var(--nf-fs-12, 11px);
696
1032
  color: var(--nf-text-3);
697
1033
  white-space: nowrap;
698
1034
  overflow: hidden;
@@ -701,21 +1037,21 @@ body[data-ds-dark-theme] .panel[data-nf-theme='neumorph'] .buttonPrimary {
701
1037
 
702
1038
  .panelNavCollapsed .navTitle {
703
1039
  justify-content: center;
704
- padding: 2px 0 10px;
1040
+ padding: var(--nf-space-2, 2px) 0 var(--nf-space-10, 10px);
705
1041
  }
706
1042
 
707
1043
  .panelNavCollapsed .navTitleLogo {
708
1044
  width: 32px;
709
- height: 32px;
1045
+ height: var(--nf-ctrl-m, 32px);
710
1046
  }
711
1047
 
712
1048
  /* 操作行:收起导航 / 关闭面板 */
713
1049
  .navActions {
714
1050
  flex: none;
715
1051
  display: flex;
716
- gap: 6px;
1052
+ gap: var(--nf-space-6, 6px);
717
1053
  margin-top: 8px;
718
- padding-top: 8px;
1054
+ padding-top: var(--nf-space-8, 8px);
719
1055
  border-top: 1px solid var(--nf-border);
720
1056
  }
721
1057
 
@@ -725,9 +1061,9 @@ body[data-ds-dark-theme] .panel[data-nf-theme='neumorph'] .buttonPrimary {
725
1061
  background: rgba(0, 0, 0, 0);
726
1062
  color: var(--nf-text-2);
727
1063
  cursor: pointer;
728
- border-radius: 10px;
729
- height: 32px;
730
- font-size: 14px;
1064
+ border-radius: var(--nf-radius-10, 10px);
1065
+ height: var(--nf-ctrl-m, 32px);
1066
+ font-size: var(--nf-fs-14, 14px);
731
1067
  line-height: 1;
732
1068
  display: inline-flex;
733
1069
  align-items: center;
@@ -751,10 +1087,10 @@ body[data-ds-dark-theme] .panel[data-nf-theme='neumorph'] .buttonPrimary {
751
1087
  flex: none;
752
1088
  display: flex;
753
1089
  align-items: center;
754
- gap: 8px;
1090
+ gap: var(--nf-space-8, 8px);
755
1091
  margin-top: 4px;
756
- padding: 9px;
757
- border-radius: 12px;
1092
+ padding: var(--nf-space-10, 9px);
1093
+ border-radius: var(--nf-radius-12, 12px);
758
1094
  background: var(--nf-bg-inset);
759
1095
  border: 1px solid var(--nf-border);
760
1096
  cursor: pointer;
@@ -773,19 +1109,19 @@ body[data-ds-dark-theme] .panel[data-nf-theme='neumorph'] .buttonPrimary {
773
1109
  .bookSwitchCover {
774
1110
  width: 26px;
775
1111
  height: 34px;
776
- border-radius: 5px;
1112
+ border-radius: var(--nf-radius-6, 5px);
777
1113
  background: linear-gradient(160deg, var(--nf-accent), color-mix(in srgb, var(--nf-accent) 45%, #000));
778
1114
  color: var(--nf-accent-fg);
779
1115
  display: flex;
780
1116
  align-items: center;
781
1117
  justify-content: center;
782
- font-size: 11px;
1118
+ font-size: var(--nf-fs-12, 11px);
783
1119
  font-weight: 700;
784
1120
  flex: none;
785
1121
  }
786
1122
 
787
1123
  .bookSwitchName {
788
- font-size: 12.5px;
1124
+ font-size: var(--nf-fs-12, 12.5px);
789
1125
  font-weight: 600;
790
1126
  overflow: hidden;
791
1127
  text-overflow: ellipsis;
@@ -793,7 +1129,7 @@ body[data-ds-dark-theme] .panel[data-nf-theme='neumorph'] .buttonPrimary {
793
1129
  }
794
1130
 
795
1131
  .bookSwitchMeta {
796
- font-size: 11px;
1132
+ font-size: var(--nf-fs-12, 11px);
797
1133
  color: var(--nf-text-3);
798
1134
  overflow: hidden;
799
1135
  text-overflow: ellipsis;
@@ -803,31 +1139,31 @@ body[data-ds-dark-theme] .panel[data-nf-theme='neumorph'] .buttonPrimary {
803
1139
  .bookSwitchArrow {
804
1140
  margin-left: auto;
805
1141
  color: var(--nf-text-3);
806
- font-size: 12px;
1142
+ font-size: var(--nf-fs-12, 12px);
807
1143
  flex: none;
808
1144
  }
809
1145
 
810
1146
  /* demo 风格统计卡(今日待写 / 写作中 / 已通过 / 待审稿) */
811
- .statRowD { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 12px; }
812
- .statCardD { display: flex; align-items: flex-start; justify-content: space-between; gap: 10px; padding: 14px 16px; border-radius: 16px; background: var(--nf-bg-inset); border: 1px solid var(--nf-border); min-width: 0; }
813
- .statCardDLabel { font-size: 12px; color: var(--nf-text-3); }
814
- .statCardDValue { font-size: 22px; font-weight: 700; margin-top: 2px; color: var(--nf-text); }
815
- .statCardDUnit { font-size: 12px; color: var(--nf-text-3); font-weight: 400; }
816
- .statCardDDetail { font-size: 11.5px; color: var(--nf-text-3); margin-top: 2px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
1147
+ .statRowD { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: var(--nf-space-12, 12px); }
1148
+ .statCardD { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--nf-space-10, 10px); padding: var(--nf-space-14, 14px) var(--nf-space-16, 16px); border-radius: var(--nf-radius-16, 16px); background: var(--nf-bg-inset); border: 1px solid var(--nf-border); min-width: 0; }
1149
+ .statCardDLabel { font-size: var(--nf-fs-12, 12px); color: var(--nf-text-3); }
1150
+ .statCardDValue { font-size: var(--nf-fs-22, 22px); font-weight: 700; margin-top: 2px; color: var(--nf-text); }
1151
+ .statCardDUnit { font-size: var(--nf-fs-12, 12px); color: var(--nf-text-3); font-weight: 400; }
1152
+ .statCardDDetail { font-size: var(--nf-fs-12, 11.5px); color: var(--nf-text-3); margin-top: 2px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
817
1153
  .statCardDDown { color: var(--nf-error); }
818
- .statCardDIcon { width: 38px; height: 38px; border-radius: 12px; display: flex; align-items: center; justify-content: center; font-size: 18px; flex: none; background: var(--nf-accent-soft); }
1154
+ .statCardDIcon { width: 38px; height: var(--nf-ctrl-l, 38px); border-radius: var(--nf-radius-12, 12px); display: flex; align-items: center; justify-content: center; font-size: var(--nf-fs-18, 18px); flex: none; background: var(--nf-accent-soft); }
819
1155
  .statCardDIconRed { background: color-mix(in srgb, var(--nf-error) 13%, transparent); }
820
1156
 
821
1157
  /* demo 风格创作时间线(6 阶段分段条,点击跳转对应 tab) */
822
- .tlBar { display: flex; gap: 6px; margin-top: 8px; }
823
- .tlSeg { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 4px; border: none; background: transparent; padding: 0; cursor: pointer; font: inherit; }
824
- .tlSegTrack { height: 8px; border-radius: 999px; background: var(--nf-hover); border: 1px solid var(--nf-border); overflow: hidden; }
825
- .tlSegFill { display: block; height: 100%; width: 100%; border-radius: 999px; background: var(--nf-accent); }
1158
+ .tlBar { display: flex; gap: var(--nf-space-6, 6px); margin-top: 8px; }
1159
+ .tlSeg { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: var(--nf-space-4, 4px); border: none; background: transparent; padding: 0; cursor: pointer; font: inherit; }
1160
+ .tlSegTrack { height: 8px; border-radius: var(--nf-radius-999, 999px); background: var(--nf-hover); border: 1px solid var(--nf-border); overflow: hidden; }
1161
+ .tlSegFill { display: block; height: 100%; width: 100%; border-radius: var(--nf-radius-999, 999px); background: var(--nf-accent); }
826
1162
  .tlSegTodo .tlSegFill { opacity: 0; }
827
1163
  .tlSegTodo .tlSegTrack { background: transparent; }
828
1164
  .tlSegCurrent .tlSegTrack { border-color: var(--nf-accent); box-shadow: 0 0 0 2px var(--nf-accent-soft); }
829
1165
  .tlSegCurrent .tlSegFill { opacity: 0.45; }
830
- .tlSegLabel { font-size: 10.5px; color: var(--nf-text-3); text-align: center; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
1166
+ .tlSegLabel { font-size: var(--nf-fs-12, 10.5px); color: var(--nf-text-3); text-align: center; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
831
1167
  .tlSegDone .tlSegLabel { color: var(--nf-accent); font-weight: 600; }
832
1168
  .tlSeg:hover .tlSegTrack { border-color: var(--nf-border-strong); }
833
1169
 
@@ -836,19 +1172,19 @@ body[data-ds-dark-theme] .panel[data-nf-theme='neumorph'] .buttonPrimary {
836
1172
 
837
1173
  .card {
838
1174
  position: relative;
839
- border: 1px solid var(--nf-glass-border);
840
- border-radius: 22px;
841
- padding: var(--nf-density-card, 16px 18px);
1175
+ border: var(--nf-card-border, 1px solid var(--nf-glass-border));
1176
+ border-radius: var(--nf-card-radius, 22px);
1177
+ padding: var(--nf-card-pad, 20px 22px);
842
1178
  display: flex;
843
1179
  flex-direction: column;
844
- gap: 10px;
1180
+ gap: var(--nf-space-10, 10px);
845
1181
  background: var(--nf-glass-face);
846
1182
  box-shadow:
847
1183
  var(--nf-card-shadow),
848
- inset 0 1.5px 0 var(--nf-glass-sheen),
849
- inset 0 -1px 0 rgba(255, 255, 255, 0.25);
850
- -webkit-backdrop-filter: blur(30px) saturate(180%);
851
- backdrop-filter: blur(30px) saturate(180%);
1184
+ inset 0 1.5px 0 var(--nf-card-sheen, var(--nf-glass-sheen)),
1185
+ inset 0 -1px 0 rgba(255, 255, 255, 0.10);
1186
+ -webkit-backdrop-filter: blur(var(--nf-card-blur, 30px)) saturate(var(--nf-card-saturate, 180%)) brightness(var(--nf-card-brightness, 1.06));
1187
+ backdrop-filter: blur(var(--nf-card-blur, 30px)) saturate(var(--nf-card-saturate, 180%)) brightness(var(--nf-card-brightness, 1.06));
852
1188
  transition: transform 0.22s ease, box-shadow 0.22s ease;
853
1189
  }
854
1190
 
@@ -861,7 +1197,7 @@ body[data-ds-dark-theme] .panel[data-nf-theme='neumorph'] .buttonPrimary {
861
1197
  pointer-events: none;
862
1198
  background:
863
1199
  var(--nf-glass-core),
864
- linear-gradient(90deg, transparent, var(--nf-glass-sheen), transparent) no-repeat 10% 0 / 80% 1px,
1200
+ linear-gradient(90deg, transparent, var(--nf-card-sheen, var(--nf-glass-sheen)), transparent) no-repeat 10% 0 / 80% 1px,
865
1201
  linear-gradient(156deg, rgba(255, 255, 255, 0.26) 0%, rgba(255, 255, 255, 0) 55%);
866
1202
  z-index: 0;
867
1203
  }
@@ -882,7 +1218,7 @@ body[data-ds-dark-theme] .panel[data-nf-theme='neumorph'] .buttonPrimary {
882
1218
  transform: translateY(-3px);
883
1219
  box-shadow:
884
1220
  var(--nf-card-shadow-hover),
885
- inset 0 1.5px 0 var(--nf-glass-sheen),
1221
+ inset 0 1.5px 0 var(--nf-card-sheen, var(--nf-glass-sheen)),
886
1222
  inset 0 -1px 0 rgba(255, 255, 255, 0.25);
887
1223
  }
888
1224
 
@@ -893,26 +1229,27 @@ body[data-ds-dark-theme] .panel[data-nf-theme='neumorph'] .buttonPrimary {
893
1229
 
894
1230
  .cardTitle {
895
1231
  margin: 0;
896
- font-size: 14px;
1232
+ font-size: var(--nf-fs-14, 14px);
897
1233
  font-weight: 650;
898
1234
  color: var(--nf-text);
899
1235
  display: flex;
900
1236
  align-items: center;
901
- gap: 8px;
1237
+ gap: var(--nf-space-8, 8px);
902
1238
  }
903
1239
 
904
1240
  /* ------------------------------------------------------------ buttons */
905
1241
 
906
1242
  .button {
907
- border: 1px solid var(--nf-border-strong);
908
- background: var(--nf-bg-inset);
1243
+ /* 控件形态令牌:按钮与 input/textarea 一致,随主题(液态/粘土/macOS/新拟物)走形状 */
1244
+ border: 1px solid var(--nf-ctrl-border, var(--nf-border-strong));
1245
+ background: var(--nf-ctrl-bg, var(--nf-bg-inset));
909
1246
  color: var(--nf-text);
910
- padding: 7px 15px;
911
- border-radius: 9px;
1247
+ padding: var(--nf-space-8, 7px) var(--nf-space-16, 15px);
1248
+ border-radius: var(--nf-ctrl-radius, 10px);
912
1249
  cursor: pointer;
913
- font-size: 13px;
1250
+ font-size: var(--nf-fs-14, 13px);
914
1251
  font-weight: 500;
915
- box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.09);
1252
+ box-shadow: inset 0 1px 0 var(--nf-ctrl-sheen, rgba(255, 255, 255, 0.09));
916
1253
  transition: background 0.15s ease, border-color 0.15s ease, transform 0.1s ease, box-shadow 0.15s ease;
917
1254
  white-space: nowrap;
918
1255
  }
@@ -936,7 +1273,7 @@ body[data-ds-dark-theme] .panel[data-nf-theme='neumorph'] .buttonPrimary {
936
1273
  border-color: transparent;
937
1274
  background: linear-gradient(180deg, color-mix(in srgb, var(--nf-accent) 88%, #ffffff), var(--nf-accent));
938
1275
  color: var(--nf-accent-fg);
939
- border-radius: 10px;
1276
+ border-radius: var(--nf-radius-10, 10px);
940
1277
  box-shadow: 0 2px 10px color-mix(in srgb, var(--nf-accent) 45%, transparent), 0 0 0 0.5px color-mix(in srgb, var(--nf-accent) 30%, transparent), inset 0 1px 0 rgba(255, 255, 255, 0.45);
941
1278
  }
942
1279
 
@@ -957,9 +1294,10 @@ body[data-ds-dark-theme] .panel[data-nf-theme='neumorph'] .buttonPrimary {
957
1294
  }
958
1295
 
959
1296
  .buttonSmall {
960
- padding: 4px 10px;
961
- font-size: 12px;
962
- border-radius: 8px;
1297
+ padding: var(--nf-space-4, 4px) var(--nf-space-10, 10px);
1298
+ font-size: var(--nf-fs-12, 12px);
1299
+ /* 与常规按钮同一控件形态令牌,保证主题一致 */
1300
+ border-radius: var(--nf-ctrl-radius, 8px);
963
1301
  }
964
1302
 
965
1303
  /* ------------------------------------------------------------ forms */
@@ -967,25 +1305,26 @@ body[data-ds-dark-theme] .panel[data-nf-theme='neumorph'] .buttonPrimary {
967
1305
  .field {
968
1306
  display: flex;
969
1307
  flex-direction: column;
970
- gap: 5px;
1308
+ gap: var(--nf-space-6, 5px);
971
1309
  }
972
1310
 
973
1311
  .fieldLabel {
974
- font-size: 12px;
1312
+ font-size: var(--nf-fs-12, 12px);
975
1313
  color: var(--nf-text-2);
976
1314
  font-weight: 500;
977
1315
  }
978
1316
 
979
1317
  .input {
980
- border: 1px solid var(--nf-border-strong);
981
- background: var(--nf-bg-inset);
1318
+ border: var(--nf-ctrl-border, 1px solid var(--nf-border-strong));
1319
+ background: var(--nf-ctrl-bg, var(--nf-bg-inset));
982
1320
  color: var(--nf-text);
983
1321
  color-scheme: light;
984
- border-radius: 12px;
985
- padding: 7px 11px;
986
- font-size: 13px;
1322
+ border-radius: var(--nf-ctrl-radius, 12px);
1323
+ padding: var(--nf-space-8, 7px) var(--nf-space-12, 11px);
1324
+ font-size: var(--nf-fs-14, 13px);
987
1325
  width: 100%;
988
1326
  box-sizing: border-box;
1327
+ box-shadow: inset 0 1px 0 var(--nf-ctrl-sheen, rgba(255, 255, 255, 0.09));
989
1328
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
990
1329
  }
991
1330
 
@@ -1004,11 +1343,21 @@ body:not([data-ds-dark-theme]) .panel[data-nf-theme='neumorph'] .input {
1004
1343
  }
1005
1344
  select.input {
1006
1345
  cursor: pointer;
1346
+ appearance: none;
1347
+ -webkit-appearance: none;
1348
+ /* 自绘下拉箭头(跟随主题色),去掉浏览器默认黑色 caret */
1349
+ background-image:
1350
+ linear-gradient(45deg, transparent 50%, var(--nf-ctrl-caret, var(--nf-text-3)) 50%),
1351
+ linear-gradient(135deg, var(--nf-ctrl-caret, var(--nf-text-3)) 50%, transparent 50%);
1352
+ background-position: calc(100% - 18px) 50%, calc(100% - 12px) 50%;
1353
+ background-size: 6px 6px, 6px 6px;
1354
+ background-repeat: no-repeat;
1355
+ padding-right: 30px;
1007
1356
  }
1008
1357
  .input option {
1009
1358
  color: var(--nf-text);
1010
1359
  background: var(--nf-bg-raise);
1011
- font-size: 15px;
1360
+ font-size: var(--nf-fs-14, 15px);
1012
1361
  }
1013
1362
 
1014
1363
  .input:focus,
@@ -1024,12 +1373,12 @@ select.input {
1024
1373
  }
1025
1374
 
1026
1375
  .textarea {
1027
- border: 1px solid var(--nf-border-strong);
1028
- background: var(--nf-bg-inset);
1376
+ border: var(--nf-ctrl-border, 1px solid var(--nf-border-strong));
1377
+ background: var(--nf-ctrl-bg, var(--nf-bg-inset));
1029
1378
  color: var(--nf-text);
1030
- border-radius: 12px;
1031
- padding: 9px 11px;
1032
- font-size: 13px;
1379
+ border-radius: var(--nf-ctrl-radius, 12px);
1380
+ padding: var(--nf-space-10, 9px) var(--nf-space-12, 11px);
1381
+ font-size: var(--nf-fs-14, 13px);
1033
1382
  width: 100%;
1034
1383
  box-sizing: border-box;
1035
1384
  min-height: 200px;
@@ -1042,7 +1391,7 @@ select.input {
1042
1391
  .row {
1043
1392
  display: flex;
1044
1393
  align-items: center;
1045
- gap: 8px;
1394
+ gap: var(--nf-space-8, 8px);
1046
1395
  flex-wrap: wrap;
1047
1396
  }
1048
1397
 
@@ -1055,27 +1404,27 @@ select.input {
1055
1404
  .chapterList {
1056
1405
  display: flex;
1057
1406
  flex-direction: column;
1058
- gap: 8px;
1407
+ gap: var(--nf-space-8, 8px);
1059
1408
  }
1060
1409
 
1061
1410
  /* 章节按卷分组 */
1062
1411
  .volumeGroup {
1063
1412
  display: flex;
1064
1413
  flex-direction: column;
1065
- gap: 6px;
1414
+ gap: var(--nf-space-6, 6px);
1066
1415
  }
1067
1416
 
1068
1417
  .volumeGroupHeader {
1069
1418
  display: flex;
1070
1419
  align-items: center;
1071
- gap: 8px;
1072
- padding: 6px 10px;
1073
- border-radius: 10px;
1420
+ gap: var(--nf-space-8, 8px);
1421
+ padding: var(--nf-space-6, 6px) var(--nf-space-10, 10px);
1422
+ border-radius: var(--nf-radius-10, 10px);
1074
1423
  background: var(--nf-bg-inset);
1075
1424
  border: 1px solid var(--nf-border);
1076
1425
  cursor: pointer;
1077
1426
  user-select: none;
1078
- font-size: 13px;
1427
+ font-size: var(--nf-fs-14, 13px);
1079
1428
  transition: border-color 0.15s ease;
1080
1429
  }
1081
1430
 
@@ -1085,17 +1434,17 @@ select.input {
1085
1434
 
1086
1435
  .volumeGroupToggle {
1087
1436
  flex: none;
1088
- font-size: 11px;
1437
+ font-size: var(--nf-fs-12, 11px);
1089
1438
  color: var(--nf-text-2);
1090
1439
  }
1091
1440
 
1092
1441
  .chapter {
1093
1442
  display: flex;
1094
1443
  align-items: center;
1095
- gap: 10px;
1096
- padding: 9px 12px;
1444
+ gap: var(--nf-space-10, 10px);
1445
+ padding: var(--nf-space-10, 9px) var(--nf-space-12, 12px);
1097
1446
  border: 1px solid var(--nf-border);
1098
- border-radius: 10px;
1447
+ border-radius: var(--nf-radius-10, 10px);
1099
1448
  background: var(--nf-bg);
1100
1449
  transition: border-color 0.15s ease, box-shadow 0.15s ease, transform 0.1s ease;
1101
1450
  }
@@ -1122,12 +1471,12 @@ select.input {
1122
1471
  align-items: center;
1123
1472
  justify-content: center;
1124
1473
  min-width: 28px;
1125
- height: 28px;
1126
- padding: 0 8px;
1127
- border-radius: 8px;
1474
+ height: var(--nf-ctrl-s, 28px);
1475
+ padding: 0 var(--nf-space-8, 8px);
1476
+ border-radius: var(--nf-radius-8, 8px);
1128
1477
  background: var(--nf-bg-inset);
1129
1478
  border: 1px solid var(--nf-border);
1130
- font-size: 12px;
1479
+ font-size: var(--nf-fs-12, 12px);
1131
1480
  font-weight: 700;
1132
1481
  color: var(--nf-text-2);
1133
1482
  flex-shrink: 0;
@@ -1140,15 +1489,15 @@ select.input {
1140
1489
 
1141
1490
  .chapterTitle {
1142
1491
  font-weight: 600;
1143
- font-size: 13px;
1492
+ font-size: var(--nf-fs-14, 13px);
1144
1493
  display: flex;
1145
1494
  align-items: center;
1146
- gap: 8px;
1495
+ gap: var(--nf-space-8, 8px);
1147
1496
  color: var(--nf-text);
1148
1497
  }
1149
1498
 
1150
1499
  .chapterBeats {
1151
- font-size: 12px;
1500
+ font-size: var(--nf-fs-12, 12px);
1152
1501
  color: var(--nf-text-2);
1153
1502
  opacity: 0.85;
1154
1503
  overflow: hidden;
@@ -1158,7 +1507,7 @@ select.input {
1158
1507
 
1159
1508
  .chapterActions {
1160
1509
  display: flex;
1161
- gap: 4px;
1510
+ gap: var(--nf-space-4, 4px);
1162
1511
  flex-shrink: 0;
1163
1512
  opacity: 0.85;
1164
1513
  transition: opacity 0.15s ease;
@@ -1171,9 +1520,9 @@ select.input {
1171
1520
  /* ------------------------------------------------------------ badges */
1172
1521
 
1173
1522
  .badge {
1174
- font-size: 11px;
1175
- padding: 2px 9px;
1176
- border-radius: 999px;
1523
+ font-size: var(--nf-fs-12, 11px);
1524
+ padding: var(--nf-space-2, 2px) var(--nf-space-10, 9px);
1525
+ border-radius: var(--nf-radius-999, 999px);
1177
1526
  border: 1px solid;
1178
1527
  white-space: nowrap;
1179
1528
  font-weight: 600;
@@ -1221,13 +1570,13 @@ select.input {
1221
1570
 
1222
1571
  .reviewBox {
1223
1572
  border: 1px solid var(--nf-border);
1224
- border-radius: 10px;
1225
- padding: 10px 12px;
1573
+ border-radius: var(--nf-radius-10, 10px);
1574
+ padding: var(--nf-space-10, 10px) var(--nf-space-12, 12px);
1226
1575
  background: var(--nf-bg-inset);
1227
1576
  display: flex;
1228
1577
  flex-direction: column;
1229
- gap: 6px;
1230
- font-size: 12.5px;
1578
+ gap: var(--nf-space-6, 6px);
1579
+ font-size: var(--nf-fs-12, 12.5px);
1231
1580
  }
1232
1581
 
1233
1582
  .chapterPreview {
@@ -1235,14 +1584,14 @@ select.input {
1235
1584
  overflow: auto;
1236
1585
  white-space: pre-wrap;
1237
1586
  word-break: break-all;
1238
- font-size: 12.5px;
1587
+ font-size: var(--nf-fs-12, 12.5px);
1239
1588
  line-height: 1.8;
1240
1589
  font-family: inherit;
1241
1590
  color: var(--nf-text);
1242
1591
  background: var(--nf-bg-inset);
1243
1592
  border: 1px solid var(--nf-border);
1244
- border-radius: 10px;
1245
- padding: 10px 12px;
1593
+ border-radius: var(--nf-radius-10, 10px);
1594
+ padding: var(--nf-space-10, 10px) var(--nf-space-12, 12px);
1246
1595
  margin: 0;
1247
1596
  }
1248
1597
 
@@ -1255,10 +1604,10 @@ select.input {
1255
1604
  overflow-y: auto;
1256
1605
  display: flex;
1257
1606
  flex-direction: column;
1258
- gap: 10px;
1259
- padding: 14px;
1607
+ gap: var(--nf-space-10, 10px);
1608
+ padding: var(--nf-space-14, 14px);
1260
1609
  border: 1px solid var(--nf-border);
1261
- border-radius: 12px;
1610
+ border-radius: var(--nf-radius-12, 12px);
1262
1611
  background: var(--nf-bg-inset);
1263
1612
  }
1264
1613
 
@@ -1267,9 +1616,9 @@ select.input {
1267
1616
  max-width: 90%;
1268
1617
  background: linear-gradient(180deg, var(--nf-accent), var(--nf-accent-hover));
1269
1618
  color: var(--nf-accent-fg);
1270
- border-radius: 14px 14px 4px 14px;
1271
- padding: 9px 14px;
1272
- font-size: 13px;
1619
+ border-radius: var(--nf-radius-14, 14px) var(--nf-radius-14, 14px) var(--nf-radius-4, 4px) var(--nf-radius-14, 14px);
1620
+ padding: var(--nf-space-10, 9px) var(--nf-space-14, 14px);
1621
+ font-size: var(--nf-fs-14, 13px);
1273
1622
  box-shadow: 0 2px 6px rgba(77, 107, 254, 0.2);
1274
1623
  }
1275
1624
 
@@ -1279,14 +1628,14 @@ select.input {
1279
1628
  background: var(--nf-bg-raise);
1280
1629
  color: var(--nf-text);
1281
1630
  border: 1px solid var(--nf-border);
1282
- border-radius: 14px 14px 14px 4px;
1283
- padding: 9px 14px;
1284
- font-size: 13px;
1631
+ border-radius: var(--nf-radius-14, 14px) var(--nf-radius-14, 14px) var(--nf-radius-14, 14px) var(--nf-radius-4, 4px);
1632
+ padding: var(--nf-space-10, 9px) var(--nf-space-14, 14px);
1633
+ font-size: var(--nf-fs-14, 13px);
1285
1634
  box-shadow: var(--nf-shadow);
1286
1635
  }
1287
1636
 
1288
1637
  .chatRole {
1289
- font-size: 11px;
1638
+ font-size: var(--nf-fs-12, 11px);
1290
1639
  color: var(--nf-text-3);
1291
1640
  margin-bottom: 3px;
1292
1641
  font-weight: 600;
@@ -1295,11 +1644,11 @@ select.input {
1295
1644
  /* Live tool output (text streaming while a chapter is generated/rewritten). */
1296
1645
  .toolLive {
1297
1646
  margin-top: 6px;
1298
- padding: 8px 10px;
1299
- border-radius: 8px;
1647
+ padding: var(--nf-space-8, 8px) var(--nf-space-10, 10px);
1648
+ border-radius: var(--nf-radius-8, 8px);
1300
1649
  background: var(--nf-bg-inset);
1301
1650
  border: 1px dashed var(--nf-border-strong);
1302
- font-size: 12px;
1651
+ font-size: var(--nf-fs-12, 12px);
1303
1652
  line-height: 1.7;
1304
1653
  white-space: pre-wrap;
1305
1654
  word-break: break-all;
@@ -1312,15 +1661,15 @@ select.input {
1312
1661
  .assistantStatus {
1313
1662
  flex: none;
1314
1663
  margin-top: 6px;
1315
- padding: 6px 12px;
1316
- border-radius: 999px;
1317
- font-size: 12px;
1664
+ padding: var(--nf-space-6, 6px) var(--nf-space-12, 12px);
1665
+ border-radius: var(--nf-radius-999, 999px);
1666
+ font-size: var(--nf-fs-12, 12px);
1318
1667
  color: var(--nf-text-2);
1319
1668
  background: var(--nf-bg-inset);
1320
1669
  border: 1px solid var(--nf-border);
1321
1670
  display: flex;
1322
1671
  align-items: center;
1323
- gap: 6px;
1672
+ gap: var(--nf-space-6, 6px);
1324
1673
  }
1325
1674
 
1326
1675
  .assistantStatusBusy {
@@ -1334,17 +1683,17 @@ select.input {
1334
1683
  .toolSteps {
1335
1684
  display: flex;
1336
1685
  flex-direction: column;
1337
- gap: 4px;
1686
+ gap: var(--nf-space-4, 4px);
1338
1687
  margin-top: 6px;
1339
1688
  }
1340
1689
 
1341
1690
  .toolStep {
1342
1691
  display: flex;
1343
1692
  align-items: center;
1344
- gap: 8px;
1345
- padding: 5px 10px;
1346
- border-radius: 8px;
1347
- font-size: 12px;
1693
+ gap: var(--nf-space-8, 8px);
1694
+ padding: var(--nf-space-6, 5px) var(--nf-space-10, 10px);
1695
+ border-radius: var(--nf-radius-8, 8px);
1696
+ font-size: var(--nf-fs-12, 12px);
1348
1697
  background: var(--nf-bg-inset);
1349
1698
  border: 1px solid var(--nf-border);
1350
1699
  }
@@ -1361,7 +1710,7 @@ select.input {
1361
1710
 
1362
1711
  .toolStepIcon {
1363
1712
  flex: none;
1364
- font-size: 13px;
1713
+ font-size: var(--nf-fs-14, 13px);
1365
1714
  }
1366
1715
 
1367
1716
  .toolStepName {
@@ -1376,7 +1725,7 @@ select.input {
1376
1725
  .toolStepStatus {
1377
1726
  flex: none;
1378
1727
  color: var(--nf-text-2);
1379
- font-size: 11px;
1728
+ font-size: var(--nf-fs-12, 11px);
1380
1729
  }
1381
1730
 
1382
1731
  .toolStepActive .toolStepStatus {
@@ -1390,7 +1739,7 @@ select.input {
1390
1739
  .toolStepDetail {
1391
1740
  width: 100%;
1392
1741
  color: var(--nf-error);
1393
- font-size: 11px;
1742
+ font-size: var(--nf-fs-12, 11px);
1394
1743
  word-break: break-all;
1395
1744
  }
1396
1745
 
@@ -1398,9 +1747,9 @@ select.input {
1398
1747
 
1399
1748
  .progress {
1400
1749
  border: 1px solid var(--nf-border);
1401
- border-radius: 10px;
1402
- padding: 10px 14px;
1403
- font-size: 12px;
1750
+ border-radius: var(--nf-radius-10, 10px);
1751
+ padding: var(--nf-space-10, 10px) var(--nf-space-14, 14px);
1752
+ font-size: var(--nf-fs-12, 12px);
1404
1753
  min-height: 60px;
1405
1754
  max-height: 220px;
1406
1755
  overflow: auto;
@@ -1422,7 +1771,7 @@ select.input {
1422
1771
  font-weight: 600;
1423
1772
  display: flex;
1424
1773
  align-items: center;
1425
- gap: 8px;
1774
+ gap: var(--nf-space-8, 8px);
1426
1775
  }
1427
1776
 
1428
1777
  .progressBar {
@@ -1430,7 +1779,7 @@ select.input {
1430
1779
  flex: none;
1431
1780
  width: 110px;
1432
1781
  height: 6px;
1433
- border-radius: 999px;
1782
+ border-radius: var(--nf-radius-999, 999px);
1434
1783
  background: var(--nf-border);
1435
1784
  overflow: hidden;
1436
1785
  }
@@ -1438,7 +1787,7 @@ select.input {
1438
1787
  .progressBarFill {
1439
1788
  display: block;
1440
1789
  height: 100%;
1441
- border-radius: 3px;
1790
+ border-radius: var(--nf-radius-4, 3px);
1442
1791
  background: var(--nf-accent);
1443
1792
  transition: width 0.3s ease;
1444
1793
  }
@@ -1448,12 +1797,12 @@ select.input {
1448
1797
  display: flex;
1449
1798
  align-items: center;
1450
1799
  justify-content: space-between;
1451
- gap: 12px;
1800
+ gap: var(--nf-space-12, 12px);
1452
1801
  flex-wrap: wrap;
1453
1802
  }
1454
1803
 
1455
1804
  .liveText {
1456
- font-size: 12px;
1805
+ font-size: var(--nf-fs-12, 12px);
1457
1806
  font-variant-numeric: tabular-nums;
1458
1807
  color: var(--nf-text-2);
1459
1808
  }
@@ -1461,7 +1810,7 @@ select.input {
1461
1810
  .bigProgressBar {
1462
1811
  margin-top: 10px;
1463
1812
  height: 8px;
1464
- border-radius: 999px;
1813
+ border-radius: var(--nf-radius-999, 999px);
1465
1814
  background: var(--nf-border);
1466
1815
  overflow: hidden;
1467
1816
  }
@@ -1469,7 +1818,7 @@ select.input {
1469
1818
  .bigProgressBarFill {
1470
1819
  display: block;
1471
1820
  height: 100%;
1472
- border-radius: 999px;
1821
+ border-radius: var(--nf-radius-999, 999px);
1473
1822
  background: linear-gradient(90deg, var(--nf-accent), var(--nf-accent-2, var(--nf-accent)));
1474
1823
  transition: width 0.3s ease;
1475
1824
  }
@@ -1478,10 +1827,10 @@ select.input {
1478
1827
  .diffLegend {
1479
1828
  display: flex;
1480
1829
  align-items: center;
1481
- gap: 14px;
1830
+ gap: var(--nf-space-14, 14px);
1482
1831
  flex-wrap: wrap;
1483
1832
  margin: 6px 0 8px;
1484
- font-size: 12px;
1833
+ font-size: var(--nf-fs-12, 12px);
1485
1834
  }
1486
1835
 
1487
1836
  .legendOld {
@@ -1497,7 +1846,7 @@ select.input {
1497
1846
  .onlyChanges {
1498
1847
  display: inline-flex;
1499
1848
  align-items: center;
1500
- gap: 4px;
1849
+ gap: var(--nf-space-4, 4px);
1501
1850
  color: var(--nf-text-2);
1502
1851
  cursor: pointer;
1503
1852
  margin-left: auto;
@@ -1508,27 +1857,27 @@ select.input {
1508
1857
  min-height: 0;
1509
1858
  overflow-y: auto;
1510
1859
  border: 1px solid var(--nf-border);
1511
- border-radius: 8px;
1860
+ border-radius: var(--nf-radius-8, 8px);
1512
1861
  background: var(--nf-bg-inset);
1513
- padding: 10px 12px;
1862
+ padding: var(--nf-space-10, 10px) var(--nf-space-12, 12px);
1514
1863
  display: flex;
1515
1864
  flex-direction: column;
1516
- gap: 8px;
1517
- font-size: 13px;
1865
+ gap: var(--nf-space-8, 8px);
1866
+ font-size: var(--nf-fs-14, 13px);
1518
1867
  line-height: 1.7;
1519
1868
  }
1520
1869
 
1521
1870
  .diffSame {
1522
1871
  border: 1px dashed var(--nf-border);
1523
- border-radius: 6px;
1524
- padding: 6px 10px;
1872
+ border-radius: var(--nf-radius-6, 6px);
1873
+ padding: var(--nf-space-6, 6px) var(--nf-space-10, 10px);
1525
1874
  color: var(--nf-text-2);
1526
1875
  opacity: 0.85;
1527
1876
  }
1528
1877
 
1529
1878
  .diffSame summary {
1530
1879
  cursor: pointer;
1531
- font-size: 12px;
1880
+ font-size: var(--nf-fs-12, 12px);
1532
1881
  user-select: none;
1533
1882
  }
1534
1883
 
@@ -1542,16 +1891,16 @@ select.input {
1542
1891
  display: grid;
1543
1892
  grid-template-columns: 1fr 1fr;
1544
1893
  border: 1px solid var(--nf-border);
1545
- border-radius: 8px;
1894
+ border-radius: var(--nf-radius-8, 8px);
1546
1895
  overflow: hidden;
1547
1896
  }
1548
1897
 
1549
1898
  .diffColumn {
1550
1899
  display: flex;
1551
1900
  flex-direction: column;
1552
- gap: 6px;
1901
+ gap: var(--nf-space-6, 6px);
1553
1902
  min-width: 0;
1554
- padding: 8px 10px;
1903
+ padding: var(--nf-space-8, 8px) var(--nf-space-10, 10px);
1555
1904
  }
1556
1905
 
1557
1906
  .diffColumn:first-child {
@@ -1562,10 +1911,10 @@ select.input {
1562
1911
  .diffTagNew {
1563
1912
  align-self: flex-start;
1564
1913
  flex: none;
1565
- font-size: 11px;
1914
+ font-size: var(--nf-fs-12, 11px);
1566
1915
  font-weight: 700;
1567
- border-radius: 4px;
1568
- padding: 1px 7px;
1916
+ border-radius: var(--nf-radius-4, 4px);
1917
+ padding: var(--nf-space-2, 1px) var(--nf-space-8, 7px);
1569
1918
  letter-spacing: 0.5px;
1570
1919
  }
1571
1920
 
@@ -1597,9 +1946,9 @@ select.input {
1597
1946
  .diffDel {
1598
1947
  display: flex;
1599
1948
  flex-direction: column;
1600
- gap: 4px;
1601
- padding: 6px 10px;
1602
- border-radius: 6px;
1949
+ gap: var(--nf-space-4, 4px);
1950
+ padding: var(--nf-space-6, 6px) var(--nf-space-10, 10px);
1951
+ border-radius: var(--nf-radius-6, 6px);
1603
1952
  border: 1px solid color-mix(in srgb, var(--nf-error) 35%, transparent);
1604
1953
  background: color-mix(in srgb, var(--nf-error) 7%, transparent);
1605
1954
  }
@@ -1607,9 +1956,9 @@ select.input {
1607
1956
  .diffAdd {
1608
1957
  display: flex;
1609
1958
  flex-direction: column;
1610
- gap: 4px;
1611
- padding: 6px 10px;
1612
- border-radius: 6px;
1959
+ gap: var(--nf-space-4, 4px);
1960
+ padding: var(--nf-space-6, 6px) var(--nf-space-10, 10px);
1961
+ border-radius: var(--nf-radius-6, 6px);
1613
1962
  border: 1px solid color-mix(in srgb, var(--nf-success) 35%, transparent);
1614
1963
  background: color-mix(in srgb, var(--nf-success) 7%, transparent);
1615
1964
  }
@@ -1634,13 +1983,13 @@ select.input {
1634
1983
  flex-direction: column;
1635
1984
  flex: 1;
1636
1985
  min-height: 0;
1637
- gap: 10px;
1986
+ gap: var(--nf-space-10, 10px);
1638
1987
  }
1639
1988
 
1640
1989
  .wsPageHeader {
1641
1990
  display: flex;
1642
1991
  align-items: center;
1643
- gap: 8px;
1992
+ gap: var(--nf-space-8, 8px);
1644
1993
  flex: none;
1645
1994
  flex-wrap: wrap;
1646
1995
  }
@@ -1650,20 +1999,20 @@ select.input {
1650
1999
  flex: none;
1651
2000
  display: flex;
1652
2001
  align-items: center;
1653
- gap: 8px;
2002
+ gap: var(--nf-space-8, 8px);
1654
2003
  flex-wrap: wrap;
1655
- padding: 8px 12px;
2004
+ padding: var(--nf-space-8, 8px) var(--nf-space-12, 12px);
1656
2005
  border: 1px solid var(--nf-success);
1657
- border-radius: 10px;
2006
+ border-radius: var(--nf-radius-10, 10px);
1658
2007
  background: color-mix(in srgb, var(--nf-success) 8%, transparent);
1659
- font-size: 12px;
2008
+ font-size: var(--nf-fs-12, 12px);
1660
2009
  font-weight: 600;
1661
2010
  }
1662
2011
 
1663
2012
  .wsColumns {
1664
2013
  display: grid;
1665
2014
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
1666
- gap: 14px;
2015
+ gap: var(--nf-space-14, 14px);
1667
2016
  flex: 1;
1668
2017
  min-height: 0;
1669
2018
  }
@@ -1671,7 +2020,7 @@ select.input {
1671
2020
  .wsColumn {
1672
2021
  display: flex;
1673
2022
  flex-direction: column;
1674
- gap: 8px;
2023
+ gap: var(--nf-space-8, 8px);
1675
2024
  min-width: 0;
1676
2025
  min-height: 0;
1677
2026
  }
@@ -1681,15 +2030,15 @@ select.input {
1681
2030
  min-height: 0;
1682
2031
  resize: vertical;
1683
2032
  font-family: var(--nf-font);
1684
- font-size: 13px;
2033
+ font-size: var(--nf-fs-14, 13px);
1685
2034
  line-height: 1.75;
1686
2035
  white-space: pre-wrap;
1687
2036
  }
1688
2037
 
1689
2038
  .wsSelected {
1690
2039
  border: 1px solid var(--nf-accent);
1691
- border-radius: 6px;
1692
- padding: 6px 10px;
2040
+ border-radius: var(--nf-radius-6, 6px);
2041
+ padding: var(--nf-space-6, 6px) var(--nf-space-10, 10px);
1693
2042
  background: color-mix(in srgb, var(--nf-accent) 8%, transparent);
1694
2043
  max-height: 120px;
1695
2044
  overflow: auto;
@@ -1697,18 +2046,18 @@ select.input {
1697
2046
 
1698
2047
  .wsSelectedText {
1699
2048
  margin-top: 4px;
1700
- font-size: 12px;
2049
+ font-size: var(--nf-fs-12, 12px);
1701
2050
  color: var(--nf-text-2);
1702
2051
  white-space: pre-wrap;
1703
2052
  }
1704
2053
 
1705
2054
  .wsPreview {
1706
2055
  border: 1px solid var(--nf-border);
1707
- border-radius: 8px;
1708
- padding: 8px 10px;
2056
+ border-radius: var(--nf-radius-8, 8px);
2057
+ padding: var(--nf-space-8, 8px) var(--nf-space-10, 10px);
1709
2058
  display: flex;
1710
2059
  flex-direction: column;
1711
- gap: 8px;
2060
+ gap: var(--nf-space-8, 8px);
1712
2061
  background: var(--nf-bg-inset);
1713
2062
  }
1714
2063
 
@@ -1717,7 +2066,7 @@ select.input {
1717
2066
  flex: 1;
1718
2067
  min-height: 0;
1719
2068
  overflow: auto;
1720
- font-size: 13px;
2069
+ font-size: var(--nf-fs-14, 13px);
1721
2070
  line-height: 1.7;
1722
2071
  white-space: pre-wrap;
1723
2072
  color: var(--nf-text);
@@ -1727,16 +2076,16 @@ select.input {
1727
2076
  .assetGrid {
1728
2077
  display: grid;
1729
2078
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
1730
- gap: 10px;
2079
+ gap: var(--nf-space-10, 10px);
1731
2080
  }
1732
2081
 
1733
2082
  .assetStat {
1734
2083
  border: 1px solid var(--nf-glass-border);
1735
- border-radius: 14px;
1736
- padding: 10px 12px;
2084
+ border-radius: var(--nf-radius-14, 14px);
2085
+ padding: var(--nf-space-10, 10px) var(--nf-space-12, 12px);
1737
2086
  display: flex;
1738
2087
  flex-direction: column;
1739
- gap: 4px;
2088
+ gap: var(--nf-space-4, 4px);
1740
2089
  background: var(--nf-glass-face);
1741
2090
  box-shadow: var(--nf-card-shadow), inset 0 1px 0 var(--nf-glass-sheen);
1742
2091
  -webkit-backdrop-filter: blur(30px) saturate(180%);
@@ -1750,20 +2099,20 @@ select.input {
1750
2099
  }
1751
2100
 
1752
2101
  .assetStatLabel {
1753
- font-size: 11px;
2102
+ font-size: var(--nf-fs-12, 11px);
1754
2103
  color: var(--nf-text-2);
1755
2104
  opacity: 0.9;
1756
2105
  }
1757
2106
 
1758
2107
  .assetStatValue {
1759
- font-size: 15px;
2108
+ font-size: var(--nf-fs-14, 15px);
1760
2109
  font-weight: 700;
1761
2110
  line-height: 1.2;
1762
2111
  color: var(--nf-text);
1763
2112
  }
1764
2113
 
1765
2114
  .assetStatDetail {
1766
- font-size: 11px;
2115
+ font-size: var(--nf-fs-12, 11px);
1767
2116
  color: var(--nf-text-2);
1768
2117
  opacity: 0.85;
1769
2118
  overflow: hidden;
@@ -1776,8 +2125,9 @@ select.input {
1776
2125
  .dashHero {
1777
2126
  position: relative;
1778
2127
  border: 1px solid var(--nf-glass-border);
1779
- border-radius: 22px;
1780
- padding: 18px 20px;
2128
+ border-radius: var(--nf-radius-22, 22px);
2129
+ /* 主容器统一:与设置页卡片同一 --nf-card-pad */
2130
+ padding: var(--nf-card-pad, 20px 22px);
1781
2131
  background: var(--nf-glass-face);
1782
2132
  box-shadow:
1783
2133
  var(--nf-card-shadow),
@@ -1787,7 +2137,7 @@ select.input {
1787
2137
  backdrop-filter: blur(30px) saturate(180%);
1788
2138
  display: flex;
1789
2139
  flex-direction: column;
1790
- gap: 14px;
2140
+ gap: var(--nf-space-14, 14px);
1791
2141
  transition: transform 0.22s ease, box-shadow 0.22s ease;
1792
2142
  }
1793
2143
 
@@ -1833,25 +2183,25 @@ select.input {
1833
2183
  .dashHeroEyebrow {
1834
2184
  display: inline-flex;
1835
2185
  align-items: center;
1836
- gap: 6px;
1837
- font-size: 13px;
2186
+ gap: var(--nf-space-6, 6px);
2187
+ font-size: var(--nf-fs-14, 13px);
1838
2188
  font-weight: 600;
1839
2189
  color: var(--nf-accent);
1840
2190
  }
1841
2191
 
1842
2192
  .dashHeroSparkle {
1843
- font-size: 14px;
2193
+ font-size: var(--nf-fs-14, 14px);
1844
2194
  }
1845
2195
 
1846
2196
  .dashHeroTitle {
1847
2197
  display: flex;
1848
2198
  flex-direction: column;
1849
- gap: 2px;
2199
+ gap: var(--nf-space-2, 2px);
1850
2200
  }
1851
2201
 
1852
2202
  .dashHeroBook {
1853
2203
  margin: 0;
1854
- font-size: 24px;
2204
+ font-size: var(--nf-fs-24, 24px);
1855
2205
  font-weight: 700;
1856
2206
  letter-spacing: -0.3px;
1857
2207
  line-height: 1.25;
@@ -1860,25 +2210,25 @@ select.input {
1860
2210
  .dashHeroAction {
1861
2211
  display: flex;
1862
2212
  align-items: center;
1863
- gap: 12px;
2213
+ gap: var(--nf-space-12, 12px);
1864
2214
  border: 1px solid var(--nf-glass-border);
1865
- border-radius: 14px;
2215
+ border-radius: var(--nf-radius-14, 14px);
1866
2216
  background: var(--nf-glass-inset);
1867
2217
  box-shadow: inset 0 1px 0 var(--nf-glass-sheen);
1868
- padding: 10px 14px;
2218
+ padding: var(--nf-space-10, 10px) var(--nf-space-14, 14px);
1869
2219
  }
1870
2220
 
1871
2221
  .dashHeroArrow {
1872
2222
  flex: none;
1873
2223
  width: 28px;
1874
- height: 28px;
2224
+ height: var(--nf-ctrl-s, 28px);
1875
2225
  border-radius: 50%;
1876
2226
  background: var(--nf-accent);
1877
2227
  color: #fff;
1878
2228
  display: inline-flex;
1879
2229
  align-items: center;
1880
2230
  justify-content: center;
1881
- font-size: 14px;
2231
+ font-size: var(--nf-fs-14, 14px);
1882
2232
  }
1883
2233
 
1884
2234
  .dashHeroActionBody {
@@ -1886,23 +2236,23 @@ select.input {
1886
2236
  min-width: 0;
1887
2237
  display: flex;
1888
2238
  flex-direction: column;
1889
- gap: 2px;
2239
+ gap: var(--nf-space-2, 2px);
1890
2240
  }
1891
2241
 
1892
2242
  .dashHeroActionTitle {
1893
- font-size: 14px;
2243
+ font-size: var(--nf-fs-14, 14px);
1894
2244
  font-weight: 600;
1895
2245
  }
1896
2246
 
1897
2247
  .dashJourney {
1898
2248
  display: flex;
1899
2249
  flex-direction: column;
1900
- gap: 6px;
2250
+ gap: var(--nf-space-6, 6px);
1901
2251
  }
1902
2252
 
1903
2253
  .dashJourneyBar {
1904
2254
  height: 6px;
1905
- border-radius: 999px;
2255
+ border-radius: var(--nf-radius-999, 999px);
1906
2256
  background: var(--nf-border);
1907
2257
  overflow: hidden;
1908
2258
  }
@@ -1910,7 +2260,7 @@ select.input {
1910
2260
  .dashJourneyFill {
1911
2261
  display: block;
1912
2262
  height: 100%;
1913
- border-radius: 999px;
2263
+ border-radius: var(--nf-radius-999, 999px);
1914
2264
  background: linear-gradient(90deg, var(--nf-info), var(--nf-accent));
1915
2265
  transition: width 0.4s ease;
1916
2266
  }
@@ -1918,15 +2268,15 @@ select.input {
1918
2268
  .dashJourneyStages {
1919
2269
  display: grid;
1920
2270
  grid-template-columns: repeat(6, minmax(0, 1fr));
1921
- gap: 4px;
2271
+ gap: var(--nf-space-4, 4px);
1922
2272
  }
1923
2273
 
1924
2274
  .dashStage {
1925
2275
  display: flex;
1926
2276
  flex-direction: column;
1927
2277
  align-items: center;
1928
- gap: 3px;
1929
- font-size: 11px;
2278
+ gap: var(--nf-space-4, 3px);
2279
+ font-size: var(--nf-fs-12, 11px);
1930
2280
  color: var(--nf-text-3);
1931
2281
  text-align: center;
1932
2282
  white-space: nowrap;
@@ -1940,7 +2290,7 @@ select.input {
1940
2290
  display: inline-flex;
1941
2291
  align-items: center;
1942
2292
  justify-content: center;
1943
- font-size: 10px;
2293
+ font-size: var(--nf-fs-12, 10px);
1944
2294
  background: var(--nf-bg-base);
1945
2295
  }
1946
2296
 
@@ -1968,20 +2318,20 @@ select.input {
1968
2318
  .dashFacts {
1969
2319
  display: grid;
1970
2320
  grid-template-columns: repeat(4, minmax(0, 1fr));
1971
- gap: 8px;
2321
+ gap: var(--nf-space-8, 8px);
1972
2322
  border-top: 1px solid var(--nf-border);
1973
- padding-top: 12px;
2323
+ padding-top: var(--nf-space-12, 12px);
1974
2324
  }
1975
2325
 
1976
2326
  .dashFact {
1977
2327
  display: flex;
1978
2328
  flex-direction: column;
1979
- gap: 2px;
2329
+ gap: var(--nf-space-2, 2px);
1980
2330
  min-width: 0;
1981
2331
  }
1982
2332
 
1983
2333
  .dashFact b {
1984
- font-size: 13px;
2334
+ font-size: var(--nf-fs-14, 13px);
1985
2335
  white-space: nowrap;
1986
2336
  overflow: hidden;
1987
2337
  text-overflow: ellipsis;
@@ -1990,17 +2340,17 @@ select.input {
1990
2340
  .dashGrid {
1991
2341
  display: grid;
1992
2342
  grid-template-columns: minmax(0, 3fr) minmax(0, 2fr);
1993
- gap: 14px;
2343
+ gap: var(--nf-space-14, 14px);
1994
2344
  align-items: start;
1995
2345
  }
1996
2346
 
1997
2347
  .todoItem {
1998
2348
  display: flex;
1999
2349
  align-items: center;
2000
- gap: 10px;
2001
- border-radius: 8px;
2002
- padding: 8px 12px;
2003
- font-size: 12.5px;
2350
+ gap: var(--nf-space-10, 10px);
2351
+ border-radius: var(--nf-radius-8, 8px);
2352
+ padding: var(--nf-space-8, 8px) var(--nf-space-12, 12px);
2353
+ font-size: var(--nf-fs-12, 12.5px);
2004
2354
  border: 1px solid var(--nf-border);
2005
2355
  }
2006
2356
 
@@ -2024,17 +2374,17 @@ select.input {
2024
2374
  min-width: 0;
2025
2375
  display: flex;
2026
2376
  flex-direction: column;
2027
- gap: 2px;
2377
+ gap: var(--nf-space-2, 2px);
2028
2378
  }
2029
2379
 
2030
2380
  /* 只读大纲(开书后的出生证明) */
2031
2381
  .outlineReadonly {
2032
2382
  margin: 0;
2033
- padding: 12px 14px;
2383
+ padding: var(--nf-space-12, 12px) var(--nf-space-14, 14px);
2034
2384
  border: 1px solid var(--nf-border);
2035
- border-radius: 12px;
2385
+ border-radius: var(--nf-radius-12, 12px);
2036
2386
  background: var(--nf-bg-inset);
2037
- font-size: 12.5px;
2387
+ font-size: var(--nf-fs-12, 12.5px);
2038
2388
  line-height: 1.8;
2039
2389
  white-space: pre-wrap;
2040
2390
  max-height: 480px;
@@ -2046,7 +2396,7 @@ select.input {
2046
2396
  .bookCreateOutline {
2047
2397
  display: flex;
2048
2398
  flex-direction: column;
2049
- gap: 6px;
2399
+ gap: var(--nf-space-6, 6px);
2050
2400
  align-items: flex-start;
2051
2401
  }
2052
2402
 
@@ -2057,7 +2407,7 @@ select.input {
2057
2407
  display: flex;
2058
2408
  flex-direction: column;
2059
2409
  border: 1px solid var(--nf-border);
2060
- border-radius: 16px;
2410
+ border-radius: var(--nf-radius-16, 16px);
2061
2411
  background: var(--nf-bg-raise);
2062
2412
  -webkit-backdrop-filter: blur(24px) saturate(180%);
2063
2413
  backdrop-filter: blur(24px) saturate(180%);
@@ -2072,11 +2422,11 @@ select.input {
2072
2422
  display: flex;
2073
2423
  align-items: center;
2074
2424
  justify-content: space-between;
2075
- gap: 8px;
2076
- padding: 8px 10px 8px 14px;
2425
+ gap: var(--nf-space-8, 8px);
2426
+ padding: var(--nf-space-8, 8px) var(--nf-space-10, 10px) var(--nf-space-8, 8px) var(--nf-space-14, 14px);
2077
2427
  cursor: grab;
2078
2428
  user-select: none;
2079
- font-size: 13px;
2429
+ font-size: var(--nf-fs-14, 13px);
2080
2430
  font-weight: 600;
2081
2431
  border-bottom: 1px solid var(--nf-border);
2082
2432
  background: var(--nf-bg-inset);
@@ -2091,7 +2441,7 @@ select.input {
2091
2441
  min-height: 0;
2092
2442
  overflow: hidden;
2093
2443
  display: flex;
2094
- padding: 10px;
2444
+ padding: var(--nf-space-10, 10px);
2095
2445
  }
2096
2446
 
2097
2447
  .assistantFloatBody > * {
@@ -2116,7 +2466,7 @@ select.input {
2116
2466
  width: 150px;
2117
2467
  height: 200px;
2118
2468
  border: 1px solid var(--nf-border);
2119
- border-radius: 12px;
2469
+ border-radius: var(--nf-radius-12, 12px);
2120
2470
  overflow: hidden;
2121
2471
  background: var(--nf-bg-inset);
2122
2472
  display: flex;
@@ -2132,7 +2482,7 @@ select.input {
2132
2482
  }
2133
2483
 
2134
2484
  .coverPlaceholder {
2135
- font-size: 12px;
2485
+ font-size: var(--nf-fs-12, 12px);
2136
2486
  color: var(--nf-text-3);
2137
2487
  }
2138
2488
 
@@ -2142,32 +2492,32 @@ select.input {
2142
2492
  flex: 1;
2143
2493
  min-height: 0;
2144
2494
  overflow: auto;
2145
- padding: var(--nf-density-pad, 18px);
2495
+ padding: var(--nf-container-pad, 20px 22px);
2146
2496
  display: flex;
2147
2497
  flex-direction: column;
2148
- gap: var(--nf-density-gap, 16px);
2498
+ gap: var(--nf-container-gap, 14px);
2149
2499
  }
2150
2500
 
2151
2501
  .shelfHeader {
2152
2502
  display: flex;
2153
2503
  flex-direction: column;
2154
- gap: 10px;
2504
+ gap: var(--nf-space-10, 10px);
2155
2505
  }
2156
2506
 
2157
2507
  /* 书架顶部主容器:加高玻璃卡 */
2158
2508
  .shelfHero {
2159
2509
  display: flex;
2160
2510
  flex-direction: column;
2161
- gap: 14px;
2162
- padding: var(--nf-density-card, 22px 24px);
2511
+ gap: var(--nf-space-14, 14px);
2512
+ padding: var(--nf-card-pad, 20px 22px);
2163
2513
  border: 1px solid var(--nf-glass-border);
2164
- border-radius: 22px;
2514
+ border-radius: var(--nf-radius-22, 22px);
2165
2515
  background: var(--nf-glass-face);
2166
2516
  box-shadow: var(--nf-shadow), inset 0 1.5px 0 var(--nf-glass-sheen);
2167
2517
  }
2168
2518
 
2169
2519
  .shelfHero .panelTitle {
2170
- font-size: 22px;
2520
+ font-size: var(--nf-fs-22, 22px);
2171
2521
  letter-spacing: 0.3px;
2172
2522
  }
2173
2523
 
@@ -2175,14 +2525,14 @@ select.input {
2175
2525
  display: flex;
2176
2526
  align-items: center;
2177
2527
  justify-content: space-between;
2178
- gap: 10px;
2528
+ gap: var(--nf-space-10, 10px);
2179
2529
  flex-wrap: wrap;
2180
2530
  }
2181
2531
 
2182
2532
  .shelfToolbar {
2183
2533
  display: flex;
2184
2534
  align-items: center;
2185
- gap: 10px;
2535
+ gap: var(--nf-space-10, 10px);
2186
2536
  flex-wrap: wrap;
2187
2537
  }
2188
2538
 
@@ -2195,17 +2545,17 @@ select.input {
2195
2545
  .shelfStats {
2196
2546
  display: grid;
2197
2547
  grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
2198
- gap: 10px;
2548
+ gap: var(--nf-space-10, 10px);
2199
2549
  }
2200
2550
 
2201
2551
  .shelfStat {
2202
2552
  display: flex;
2203
2553
  align-items: baseline;
2204
2554
  justify-content: space-between;
2205
- gap: 8px;
2206
- padding: 10px 14px;
2555
+ gap: var(--nf-space-8, 8px);
2556
+ padding: var(--nf-space-10, 10px) var(--nf-space-14, 14px);
2207
2557
  border: 1px solid var(--nf-glass-border);
2208
- border-radius: 14px;
2558
+ border-radius: var(--nf-radius-14, 14px);
2209
2559
  background: var(--nf-glass-face);
2210
2560
  box-shadow: var(--nf-shadow), inset 0 1px 0 var(--nf-glass-sheen);
2211
2561
  cursor: pointer;
@@ -2225,23 +2575,23 @@ select.input {
2225
2575
  }
2226
2576
 
2227
2577
  .shelfStat b {
2228
- font-size: 20px;
2578
+ font-size: var(--nf-fs-20, 20px);
2229
2579
  font-weight: 800;
2230
2580
  color: var(--nf-accent);
2231
2581
  }
2232
2582
 
2233
2583
  .shelfStat span {
2234
- font-size: 12px;
2584
+ font-size: var(--nf-fs-12, 12px);
2235
2585
  color: var(--nf-text-2);
2236
2586
  }
2237
2587
 
2238
2588
  /* 筛选:胶囊分段控件 */
2239
2589
  .shelfFilters {
2240
2590
  display: inline-flex;
2241
- gap: 2px;
2242
- padding: 3px;
2591
+ gap: var(--nf-space-2, 2px);
2592
+ padding: var(--nf-space-4, 3px);
2243
2593
  border: 1px solid var(--nf-border);
2244
- border-radius: 999px;
2594
+ border-radius: var(--nf-radius-999, 999px);
2245
2595
  background: var(--nf-bg-inset);
2246
2596
  }
2247
2597
 
@@ -2249,14 +2599,14 @@ select.input {
2249
2599
  border: none;
2250
2600
  background: transparent;
2251
2601
  color: var(--nf-text-2);
2252
- font-size: 12.5px;
2602
+ font-size: var(--nf-fs-12, 12.5px);
2253
2603
  font-weight: 600;
2254
- padding: 5px 12px;
2255
- border-radius: 999px;
2604
+ padding: var(--nf-space-6, 5px) var(--nf-space-12, 12px);
2605
+ border-radius: var(--nf-radius-999, 999px);
2256
2606
  cursor: pointer;
2257
2607
  display: inline-flex;
2258
2608
  align-items: center;
2259
- gap: 5px;
2609
+ gap: var(--nf-space-6, 5px);
2260
2610
  white-space: nowrap;
2261
2611
  transition: background 0.15s ease, color 0.15s ease, box-shadow 0.15s ease;
2262
2612
  }
@@ -2272,11 +2622,11 @@ select.input {
2272
2622
  }
2273
2623
 
2274
2624
  .shelfFilterCount {
2275
- font-size: 10.5px;
2625
+ font-size: var(--nf-fs-12, 10.5px);
2276
2626
  opacity: 0.8;
2277
2627
  background: color-mix(in srgb, currentColor 14%, transparent);
2278
- border-radius: 999px;
2279
- padding: 0 6px;
2628
+ border-radius: var(--nf-radius-999, 999px);
2629
+ padding: 0 var(--nf-space-6, 6px);
2280
2630
  }
2281
2631
 
2282
2632
  /* 书架空态 / 无结果引导卡 */
@@ -2286,10 +2636,10 @@ select.input {
2286
2636
  flex-direction: column;
2287
2637
  align-items: center;
2288
2638
  justify-content: center;
2289
- gap: 10px;
2290
- padding: 40px 20px;
2639
+ gap: var(--nf-space-10, 10px);
2640
+ padding: var(--nf-space-40, 40px) var(--nf-space-20, 20px);
2291
2641
  border: 1px dashed var(--nf-border-strong);
2292
- border-radius: 16px;
2642
+ border-radius: var(--nf-radius-16, 16px);
2293
2643
  background: var(--nf-bg-raise);
2294
2644
  -webkit-backdrop-filter: blur(24px) saturate(180%);
2295
2645
  backdrop-filter: blur(24px) saturate(180%);
@@ -2297,43 +2647,45 @@ select.input {
2297
2647
  }
2298
2648
 
2299
2649
  .shelfEmptyIcon {
2300
- font-size: 42px;
2650
+ font-size: var(--nf-fs-42, 42px);
2301
2651
  }
2302
2652
 
2303
2653
  .shelfEmptyTitle {
2304
- font-size: 16px;
2654
+ font-size: var(--nf-fs-16, 16px);
2305
2655
  font-weight: 700;
2306
2656
  }
2307
2657
 
2308
2658
  .shelfGrid {
2309
2659
  display: grid;
2310
2660
  grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
2311
- gap: var(--nf-density-gap, 14px);
2661
+ gap: var(--nf-container-gap, 14px);
2312
2662
  align-content: start;
2313
2663
  }
2314
2664
 
2315
2665
  /* ------------------------------------------------------------
2316
2666
  * 外观设置扩展:强制显示模式 + 界面密度 + 主题暗色覆盖
2317
2667
  * ------------------------------------------------------------ */
2668
+ /* 界面密度:唯一允许重定义尺寸的开关(主题永不触碰这些令牌)。
2669
+ * comfort = 设置页主容器基准;compact/spacious 只缩放令牌,不改组件。 */
2318
2670
  .panel {
2319
- --nf-density-card: 16px 18px;
2320
- --nf-density-gap: 14px;
2321
- --nf-density-pad: 16px 18px 20px;
2322
- --nf-density-nav: 16px 12px 14px;
2671
+ --nf-container-pad: 20px 22px;
2672
+ --nf-container-gap: var(--nf-space-14, 14px);
2673
+ --nf-card-pad: 20px 22px;
2674
+ --nf-nav-pad: 16px 12px 14px;
2323
2675
  }
2324
2676
 
2325
2677
  .panel[data-nf-density='compact'] {
2326
- --nf-density-card: 12px 14px;
2327
- --nf-density-gap: 8px;
2328
- --nf-density-pad: 12px 14px;
2329
- --nf-density-nav: 8px 8px;
2678
+ --nf-container-pad: 12px 14px;
2679
+ --nf-container-gap: var(--nf-space-8, 8px);
2680
+ --nf-card-pad: 12px 14px;
2681
+ --nf-nav-pad: 8px 8px;
2330
2682
  }
2331
2683
 
2332
2684
  .panel[data-nf-density='spacious'] {
2333
- --nf-density-card: 22px 26px;
2334
- --nf-density-gap: 18px;
2335
- --nf-density-pad: 22px 24px;
2336
- --nf-density-nav: 18px 14px;
2685
+ --nf-container-pad: 24px 28px;
2686
+ --nf-container-gap: var(--nf-space-18, 18px);
2687
+ --nf-card-pad: 22px 26px;
2688
+ --nf-nav-pad: 18px 14px;
2337
2689
  }
2338
2690
 
2339
2691
  /* 强制浅色(不跟随系统时覆盖 .view 的明暗变量) */
@@ -2404,20 +2756,35 @@ select.input {
2404
2756
  --nf-glass-orb-b: rgba(190, 200, 215, 0.10);
2405
2757
  }
2406
2758
 
2407
- /* 强制深色时:经典毛玻璃 / 新拟物 的暗色变体 */
2408
- .panel[data-nf-mode='dark'][data-nf-theme='classic'] {
2759
+ /* 强制深色时:新拟物 的暗色变体 */
2760
+
2761
+ .panel[data-nf-mode='dark'][data-nf-theme='macos'] {
2762
+ --nf-bg: rgba(28, 28, 30, 0.9);
2763
+ --nf-bg-raise: rgba(44, 44, 46, 0.82);
2764
+ --nf-bg-inset: rgba(118, 118, 128, 0.18);
2765
+ --nf-border: rgba(255, 255, 255, 0.12);
2766
+ --nf-border-strong: rgba(255, 255, 255, 0.26);
2767
+ --nf-text: #f5f5f7;
2768
+ --nf-text-2: #d1d1d6;
2769
+ --nf-text-2-alpha: rgba(209, 209, 214, 0.7);
2770
+ --nf-text-3: #98989d;
2409
2771
  --nf-accent: #0a84ff;
2410
2772
  --nf-accent-hover: #3a9bff;
2411
2773
  --nf-accent-soft: rgba(10, 132, 255, 0.2);
2412
2774
  --nf-accent-fg: #ffffff;
2775
+ --nf-hover: rgba(255, 255, 255, 0.06);
2413
2776
  --nf-info: #bf5af2;
2414
- --nf-glass-face: var(--nf-bg-raise);
2777
+ --nf-shadow: 0 1px 2px rgba(0, 0, 0, 0.4), 0 10px 30px rgba(0, 0, 0, 0.45);
2778
+ --nf-shadow-lg: 0 4px 12px rgba(0, 0, 0, 0.45), 0 18px 44px rgba(0, 0, 0, 0.6);
2779
+ --nf-card-shadow: 0 2px 6px rgba(0, 0, 0, 0.4), 0 14px 38px rgba(0, 0, 0, 0.5);
2780
+ --nf-card-shadow-hover: 0 4px 10px rgba(0, 0, 0, 0.45), 0 22px 52px rgba(0, 0, 0, 0.6);
2781
+ --nf-glass-face: rgba(44, 44, 46, 0.85);
2415
2782
  --nf-glass-core: transparent;
2416
- --nf-glass-sheen: rgba(255, 255, 255, 0);
2417
- --nf-glass-border: var(--nf-border);
2418
- --nf-glass-inset: var(--nf-bg-inset);
2419
- --nf-glass-orb-a: transparent;
2420
- --nf-glass-orb-b: transparent;
2783
+ --nf-glass-sheen: rgba(255, 255, 255, 0.2);
2784
+ --nf-glass-border: rgba(255, 255, 255, 0.18);
2785
+ --nf-glass-inset: rgba(255, 255, 255, 0.06);
2786
+ --nf-glass-orb-a: rgba(10, 132, 255, 0.16);
2787
+ --nf-glass-orb-b: rgba(191, 90, 242, 0.08);
2421
2788
  --nf-glass-noise: none;
2422
2789
  }
2423
2790
 
@@ -2476,10 +2843,10 @@ select.input {
2476
2843
  .bookCard {
2477
2844
  display: flex;
2478
2845
  flex-direction: column;
2479
- gap: 8px;
2846
+ gap: var(--nf-space-8, 8px);
2480
2847
  border: 1px solid var(--nf-border);
2481
- border-radius: 16px;
2482
- padding: 12px;
2848
+ border-radius: var(--nf-radius-16, 16px);
2849
+ padding: var(--nf-space-12, 12px);
2483
2850
  background: var(--nf-bg-raise);
2484
2851
  -webkit-backdrop-filter: blur(24px) saturate(180%);
2485
2852
  backdrop-filter: blur(24px) saturate(180%);
@@ -2502,7 +2869,7 @@ select.input {
2502
2869
  .bookCardCover {
2503
2870
  flex: none;
2504
2871
  aspect-ratio: 3 / 4;
2505
- border-radius: 12px;
2872
+ border-radius: var(--nf-radius-12, 12px);
2506
2873
  overflow: hidden;
2507
2874
  background: var(--nf-bg-inset);
2508
2875
  border: 1px solid var(--nf-border);
@@ -2545,7 +2912,7 @@ select.input {
2545
2912
  flex-direction: column;
2546
2913
  align-items: center;
2547
2914
  justify-content: center;
2548
- gap: 6px;
2915
+ gap: var(--nf-space-6, 6px);
2549
2916
  width: 100%;
2550
2917
  height: 100%;
2551
2918
  background:
@@ -2554,7 +2921,7 @@ select.input {
2554
2921
  }
2555
2922
 
2556
2923
  .bookCardCoverTitle {
2557
- font-size: 22px;
2924
+ font-size: var(--nf-fs-22, 22px);
2558
2925
  font-weight: 800;
2559
2926
  color: var(--nf-accent);
2560
2927
  letter-spacing: 2px;
@@ -2563,7 +2930,7 @@ select.input {
2563
2930
  .bookCardBody {
2564
2931
  display: flex;
2565
2932
  flex-direction: column;
2566
- gap: 5px;
2933
+ gap: var(--nf-space-6, 5px);
2567
2934
  min-width: 0;
2568
2935
  flex: 1;
2569
2936
  }
@@ -2572,12 +2939,12 @@ select.input {
2572
2939
  display: flex;
2573
2940
  align-items: center;
2574
2941
  justify-content: space-between;
2575
- gap: 6px;
2942
+ gap: var(--nf-space-6, 6px);
2576
2943
  }
2577
2944
 
2578
2945
  .bookCardName {
2579
2946
  font-weight: 700;
2580
- font-size: 13.5px;
2947
+ font-size: var(--nf-fs-14, 13.5px);
2581
2948
  overflow: hidden;
2582
2949
  text-overflow: ellipsis;
2583
2950
  white-space: nowrap;
@@ -2595,13 +2962,13 @@ select.input {
2595
2962
  display: flex;
2596
2963
  align-items: center;
2597
2964
  justify-content: space-between;
2598
- gap: 6px;
2965
+ gap: var(--nf-space-6, 6px);
2599
2966
  flex-wrap: wrap;
2600
2967
  }
2601
2968
 
2602
2969
  .bookCardProgressBar {
2603
2970
  height: 6px;
2604
- border-radius: 999px;
2971
+ border-radius: var(--nf-radius-999, 999px);
2605
2972
  background: var(--nf-border);
2606
2973
  overflow: hidden;
2607
2974
  box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.12);
@@ -2610,7 +2977,7 @@ select.input {
2610
2977
  .bookCardProgressFill {
2611
2978
  display: block;
2612
2979
  height: 100%;
2613
- border-radius: 999px;
2980
+ border-radius: var(--nf-radius-999, 999px);
2614
2981
  background: linear-gradient(90deg, var(--nf-info), var(--nf-accent));
2615
2982
  transition: width 0.3s ease;
2616
2983
  }
@@ -2618,7 +2985,7 @@ select.input {
2618
2985
  .bookAddCard {
2619
2986
  align-items: center;
2620
2987
  justify-content: center;
2621
- gap: 8px;
2988
+ gap: var(--nf-space-8, 8px);
2622
2989
  text-align: center;
2623
2990
  border-style: dashed;
2624
2991
  color: var(--nf-text-2);
@@ -2634,7 +3001,7 @@ select.input {
2634
3001
  }
2635
3002
 
2636
3003
  .bookAddIcon {
2637
- font-size: 34px;
3004
+ font-size: var(--nf-fs-34, 34px);
2638
3005
  line-height: 1;
2639
3006
  color: var(--nf-accent);
2640
3007
  transition: transform 0.15s ease;
@@ -2655,10 +3022,11 @@ select.input {
2655
3022
  flex: 1;
2656
3023
  min-height: 0;
2657
3024
  overflow: auto;
2658
- padding: 14px 18px 24px;
3025
+ /* 主容器统一:与工作台/书架/设置页同一令牌 */
3026
+ padding: var(--nf-container-pad, 20px 22px);
2659
3027
  display: flex;
2660
3028
  flex-direction: column;
2661
- gap: 14px;
3029
+ gap: var(--nf-container-gap, 14px);
2662
3030
  }
2663
3031
 
2664
3032
  .createBookTop {
@@ -2671,10 +3039,11 @@ select.input {
2671
3039
  width: min(520px, 100%);
2672
3040
  display: flex;
2673
3041
  flex-direction: column;
2674
- gap: 12px;
3042
+ gap: var(--nf-space-12, 12px);
2675
3043
  border: 1px solid var(--nf-border);
2676
- border-radius: 20px;
2677
- padding: 26px 28px;
3044
+ border-radius: var(--nf-radius-20, 20px);
3045
+ /* 主容器统一:与设置页卡片同一 --nf-card-pad */
3046
+ padding: var(--nf-card-pad, 20px 22px);
2678
3047
  background: var(--nf-bg-raise);
2679
3048
  -webkit-backdrop-filter: blur(24px) saturate(180%);
2680
3049
  backdrop-filter: blur(24px) saturate(180%);
@@ -2682,13 +3051,13 @@ select.input {
2682
3051
  }
2683
3052
 
2684
3053
  .createBookIcon {
2685
- font-size: 34px;
3054
+ font-size: var(--nf-fs-34, 34px);
2686
3055
  line-height: 1;
2687
3056
  }
2688
3057
 
2689
3058
  .createBookTitle {
2690
3059
  margin: 0;
2691
- font-size: 22px;
3060
+ font-size: var(--nf-fs-22, 22px);
2692
3061
  font-weight: 800;
2693
3062
  letter-spacing: -0.3px;
2694
3063
  }
@@ -2697,21 +3066,21 @@ select.input {
2697
3066
  .ideaCard {
2698
3067
  display: flex;
2699
3068
  flex-direction: column;
2700
- gap: 8px;
3069
+ gap: var(--nf-space-8, 8px);
2701
3070
  border: 1px dashed var(--nf-border-strong);
2702
- border-radius: 14px;
2703
- padding: 10px 12px;
3071
+ border-radius: var(--nf-radius-14, 14px);
3072
+ padding: var(--nf-space-10, 10px) var(--nf-space-12, 12px);
2704
3073
  background: color-mix(in srgb, var(--nf-accent) 3%, transparent);
2705
3074
  }
2706
3075
 
2707
3076
  .ideaToggle {
2708
3077
  display: flex;
2709
3078
  align-items: center;
2710
- gap: 6px;
3079
+ gap: var(--nf-space-6, 6px);
2711
3080
  border: none;
2712
3081
  background: none;
2713
3082
  color: var(--nf-accent);
2714
- font-size: 13px;
3083
+ font-size: var(--nf-fs-14, 13px);
2715
3084
  font-weight: 700;
2716
3085
  cursor: pointer;
2717
3086
  text-align: left;
@@ -2721,10 +3090,10 @@ select.input {
2721
3090
  .ideaCandidate {
2722
3091
  display: flex;
2723
3092
  flex-direction: column;
2724
- gap: 6px;
3093
+ gap: var(--nf-space-6, 6px);
2725
3094
  border: 1px solid var(--nf-border);
2726
- border-radius: 12px;
2727
- padding: 10px 12px;
3095
+ border-radius: var(--nf-radius-12, 12px);
3096
+ padding: var(--nf-space-10, 10px) var(--nf-space-12, 12px);
2728
3097
  background: var(--nf-bg);
2729
3098
  }
2730
3099
 
@@ -2741,7 +3110,7 @@ select.input {
2741
3110
  /* ------------------------------------------------------------ misc */
2742
3111
 
2743
3112
  .meta {
2744
- font-size: 12px;
3113
+ font-size: var(--nf-fs-12, 12px);
2745
3114
  color: var(--nf-text-2);
2746
3115
  opacity: 0.9;
2747
3116
  }
@@ -2758,8 +3127,8 @@ select.input {
2758
3127
  .fileList {
2759
3128
  display: flex;
2760
3129
  flex-direction: column;
2761
- gap: 3px;
2762
- font-size: 12px;
3130
+ gap: var(--nf-space-4, 3px);
3131
+ font-size: var(--nf-fs-12, 12px);
2763
3132
  color: var(--nf-text-2);
2764
3133
  opacity: 0.9;
2765
3134
  word-break: break-all;
@@ -2781,7 +3150,7 @@ select.input {
2781
3150
  .progress::-webkit-scrollbar-thumb,
2782
3151
  .toolLive::-webkit-scrollbar-thumb {
2783
3152
  background: var(--nf-border-strong);
2784
- border-radius: 4px;
3153
+ border-radius: var(--nf-radius-4, 4px);
2785
3154
  }
2786
3155
 
2787
3156
  .panelContent::-webkit-scrollbar-thumb:hover,
@@ -2802,8 +3171,8 @@ select.input {
2802
3171
  .workflowRow {
2803
3172
  display: flex;
2804
3173
  align-items: flex-start;
2805
- gap: 12px;
2806
- padding: 8px 4px;
3174
+ gap: var(--nf-space-12, 12px);
3175
+ padding: var(--nf-space-8, 8px) var(--nf-space-4, 4px);
2807
3176
  position: relative;
2808
3177
  }
2809
3178
 
@@ -2823,12 +3192,12 @@ select.input {
2823
3192
 
2824
3193
  .workflowDot {
2825
3194
  width: 28px;
2826
- height: 28px;
3195
+ height: var(--nf-ctrl-s, 28px);
2827
3196
  border-radius: 50%;
2828
3197
  display: inline-flex;
2829
3198
  align-items: center;
2830
3199
  justify-content: center;
2831
- font-size: 12px;
3200
+ font-size: var(--nf-fs-12, 12px);
2832
3201
  font-weight: 700;
2833
3202
  flex-shrink: 0;
2834
3203
  border: 2px solid var(--nf-border-strong);
@@ -2855,18 +3224,18 @@ select.input {
2855
3224
  min-width: 0;
2856
3225
  display: flex;
2857
3226
  flex-direction: column;
2858
- gap: 4px;
2859
- padding-top: 2px;
3227
+ gap: var(--nf-space-4, 4px);
3228
+ padding-top: var(--nf-space-2, 2px);
2860
3229
  }
2861
3230
 
2862
3231
  .workflowLabel {
2863
- font-size: 13px;
3232
+ font-size: var(--nf-fs-14, 13px);
2864
3233
  font-weight: 600;
2865
3234
  color: var(--nf-text);
2866
3235
  }
2867
3236
 
2868
3237
  .workflowHint {
2869
- font-size: 12px;
3238
+ font-size: var(--nf-fs-12, 12px);
2870
3239
  color: var(--nf-text-2);
2871
3240
  }
2872
3241
 
@@ -2889,11 +3258,11 @@ select.input {
2889
3258
  .bookshelf {
2890
3259
  display: flex;
2891
3260
  align-items: center;
2892
- gap: 10px;
3261
+ gap: var(--nf-space-10, 10px);
2893
3262
  margin: 10px 12px 0;
2894
- padding: 8px 14px;
3263
+ padding: var(--nf-space-8, 8px) var(--nf-space-14, 14px);
2895
3264
  border: 1px solid var(--nf-glass-border);
2896
- border-radius: 16px;
3265
+ border-radius: var(--nf-radius-16, 16px);
2897
3266
  background: var(--nf-glass-face);
2898
3267
  box-shadow: var(--nf-shadow), inset 0 1px 0 var(--nf-glass-sheen);
2899
3268
  -webkit-backdrop-filter: blur(26px) saturate(175%);
@@ -2905,7 +3274,7 @@ select.input {
2905
3274
  }
2906
3275
 
2907
3276
  .bookshelfLabel {
2908
- font-size: 12px;
3277
+ font-size: var(--nf-fs-12, 12px);
2909
3278
  font-weight: 700;
2910
3279
  color: var(--nf-text-3);
2911
3280
  letter-spacing: 1px;
@@ -2915,7 +3284,7 @@ select.input {
2915
3284
  .bookshelfList {
2916
3285
  display: flex;
2917
3286
  align-items: center;
2918
- gap: 6px;
3287
+ gap: var(--nf-space-6, 6px);
2919
3288
  flex-wrap: wrap;
2920
3289
  flex: 1;
2921
3290
  min-width: 0;
@@ -2924,13 +3293,13 @@ select.input {
2924
3293
  .bookChip {
2925
3294
  display: flex;
2926
3295
  align-items: center;
2927
- gap: 6px;
2928
- padding: 4px 8px 4px 10px;
3296
+ gap: var(--nf-space-6, 6px);
3297
+ padding: var(--nf-space-4, 4px) var(--nf-space-8, 8px) var(--nf-space-4, 4px) var(--nf-space-10, 10px);
2929
3298
  border: 1px solid var(--nf-border);
2930
- border-radius: 999px;
3299
+ border-radius: var(--nf-radius-999, 999px);
2931
3300
  background: var(--nf-bg-inset);
2932
3301
  cursor: pointer;
2933
- font-size: 12px;
3302
+ font-size: var(--nf-fs-12, 12px);
2934
3303
  transition: border-color 0.15s ease, background 0.15s ease;
2935
3304
  max-width: 220px;
2936
3305
  }
@@ -2953,7 +3322,7 @@ select.input {
2953
3322
  }
2954
3323
 
2955
3324
  .bookChipMeta {
2956
- font-size: 11px;
3325
+ font-size: var(--nf-fs-12, 11px);
2957
3326
  opacity: 0.7;
2958
3327
  white-space: nowrap;
2959
3328
  }
@@ -2963,10 +3332,10 @@ select.input {
2963
3332
  background: transparent;
2964
3333
  color: var(--nf-text-3);
2965
3334
  cursor: pointer;
2966
- font-size: 13px;
3335
+ font-size: var(--nf-fs-14, 13px);
2967
3336
  line-height: 1;
2968
- padding: 0 2px;
2969
- border-radius: 4px;
3337
+ padding: 0 var(--nf-space-2, 2px);
3338
+ border-radius: var(--nf-radius-4, 4px);
2970
3339
  }
2971
3340
 
2972
3341
  .bookChipRemove:hover {
@@ -2978,9 +3347,9 @@ select.input {
2978
3347
  background: transparent;
2979
3348
  color: var(--nf-text-2);
2980
3349
  cursor: pointer;
2981
- font-size: 12px;
2982
- padding: 4px 12px;
2983
- border-radius: 999px;
3350
+ font-size: var(--nf-fs-12, 12px);
3351
+ padding: var(--nf-space-4, 4px) var(--nf-space-12, 12px);
3352
+ border-radius: var(--nf-radius-999, 999px);
2984
3353
  transition: border-color 0.15s ease, color 0.15s ease;
2985
3354
  }
2986
3355
 
@@ -2992,24 +3361,24 @@ select.input {
2992
3361
  .bookCreateForm {
2993
3362
  display: flex;
2994
3363
  align-items: center;
2995
- gap: 6px;
3364
+ gap: var(--nf-space-6, 6px);
2996
3365
  }
2997
3366
 
2998
3367
  /* ------------------------------------------------------------ dropzone */
2999
3368
 
3000
3369
  .dropzone {
3001
3370
  border: 2px dashed var(--nf-border-strong);
3002
- border-radius: 10px;
3003
- padding: 18px 14px;
3371
+ border-radius: var(--nf-radius-10, 10px);
3372
+ padding: var(--nf-space-18, 18px) var(--nf-space-14, 14px);
3004
3373
  text-align: center;
3005
- font-size: 13px;
3374
+ font-size: var(--nf-fs-14, 13px);
3006
3375
  color: var(--nf-text-2);
3007
3376
  cursor: pointer;
3008
3377
  transition: border-color 0.15s ease, background 0.15s ease;
3009
3378
  display: flex;
3010
3379
  flex-direction: column;
3011
3380
  align-items: center;
3012
- gap: 6px;
3381
+ gap: var(--nf-space-6, 6px);
3013
3382
  }
3014
3383
 
3015
3384
  .dropzone:hover,
@@ -3020,7 +3389,7 @@ select.input {
3020
3389
  }
3021
3390
 
3022
3391
  .dropzoneIcon {
3023
- font-size: 22px;
3392
+ font-size: var(--nf-fs-22, 22px);
3024
3393
  line-height: 1;
3025
3394
  }
3026
3395
 
@@ -3029,9 +3398,9 @@ select.input {
3029
3398
  .bookCardActions {
3030
3399
  display: flex;
3031
3400
  align-items: center;
3032
- gap: 6px;
3401
+ gap: var(--nf-space-6, 6px);
3033
3402
  margin-top: auto;
3034
- padding-top: 8px;
3403
+ padding-top: var(--nf-space-8, 8px);
3035
3404
  }
3036
3405
 
3037
3406
  .bookCardActions .button {
@@ -3054,31 +3423,31 @@ select.input {
3054
3423
  flex: none;
3055
3424
  display: flex;
3056
3425
  align-items: center;
3057
- gap: 8px;
3058
- padding: 8px 12px;
3426
+ gap: var(--nf-space-8, 8px);
3427
+ padding: var(--nf-space-8, 8px) var(--nf-space-12, 12px);
3059
3428
  border-bottom: 1px solid;
3060
3429
  flex-wrap: wrap;
3061
3430
  }
3062
3431
 
3063
3432
  .readerTitle {
3064
3433
  font-weight: 700;
3065
- font-size: 14px;
3434
+ font-size: var(--nf-fs-14, 14px);
3066
3435
  }
3067
3436
 
3068
3437
  .readerSeg {
3069
3438
  display: flex;
3070
3439
  align-items: center;
3071
- gap: 2px;
3072
- border-radius: 8px;
3440
+ gap: var(--nf-space-2, 2px);
3441
+ border-radius: var(--nf-radius-8, 8px);
3073
3442
  overflow: hidden;
3074
3443
  }
3075
3444
 
3076
3445
  .readerSegBtn {
3077
3446
  border: none;
3078
3447
  background: transparent;
3079
- font-size: 12px;
3080
- padding: 3px 8px;
3081
- border-radius: 6px;
3448
+ font-size: var(--nf-fs-12, 12px);
3449
+ padding: var(--nf-space-4, 3px) var(--nf-space-8, 8px);
3450
+ border-radius: var(--nf-radius-6, 6px);
3082
3451
  cursor: pointer;
3083
3452
  opacity: 0.75;
3084
3453
  }
@@ -3103,34 +3472,34 @@ select.input {
3103
3472
  width: 220px;
3104
3473
  min-width: 220px;
3105
3474
  overflow-y: auto;
3106
- padding: 8px 6px 24px;
3475
+ padding: var(--nf-space-8, 8px) var(--nf-space-6, 6px) var(--nf-space-24, 24px);
3107
3476
  border-right: 1px solid;
3108
3477
  scrollbar-width: thin;
3109
3478
  display: flex;
3110
3479
  flex-direction: column;
3111
- gap: 10px;
3480
+ gap: var(--nf-space-10, 10px);
3112
3481
  }
3113
3482
 
3114
3483
  .readerGroup {
3115
3484
  display: flex;
3116
3485
  flex-direction: column;
3117
- gap: 1px;
3486
+ gap: var(--nf-space-2, 1px);
3118
3487
  }
3119
3488
 
3120
3489
  .readerGroupTitle {
3121
3490
  display: flex;
3122
3491
  align-items: center;
3123
- gap: 6px;
3492
+ gap: var(--nf-space-6, 6px);
3124
3493
  width: 100%;
3125
3494
  border: none;
3126
3495
  background: transparent;
3127
- font-size: 12px;
3496
+ font-size: var(--nf-fs-12, 12px);
3128
3497
  font-weight: 700;
3129
- padding: 6px 8px 4px;
3498
+ padding: var(--nf-space-6, 6px) var(--nf-space-8, 8px) var(--nf-space-4, 4px);
3130
3499
  opacity: 0.9;
3131
3500
  cursor: pointer;
3132
3501
  text-align: left;
3133
- border-radius: 6px;
3502
+ border-radius: var(--nf-radius-6, 6px);
3134
3503
  }
3135
3504
 
3136
3505
  .readerGroupTitle:hover {
@@ -3140,30 +3509,30 @@ select.input {
3140
3509
 
3141
3510
  .readerGroupArrow {
3142
3511
  flex: none;
3143
- font-size: 10px;
3512
+ font-size: var(--nf-fs-12, 10px);
3144
3513
  width: 12px;
3145
3514
  text-align: center;
3146
3515
  }
3147
3516
 
3148
3517
  .readerGroupCount {
3149
3518
  flex: none;
3150
- font-size: 11px;
3519
+ font-size: var(--nf-fs-12, 11px);
3151
3520
  font-weight: 400;
3152
3521
  opacity: 0.6;
3153
3522
  margin-left: auto;
3154
- padding-right: 2px;
3523
+ padding-right: var(--nf-space-2, 2px);
3155
3524
  }
3156
3525
 
3157
3526
  .readerItem {
3158
3527
  display: flex;
3159
3528
  align-items: center;
3160
- gap: 6px;
3529
+ gap: var(--nf-space-6, 6px);
3161
3530
  border: 1px solid;
3162
- border-radius: 8px;
3531
+ border-radius: var(--nf-radius-8, 8px);
3163
3532
  background: transparent;
3164
- font-size: 12px;
3533
+ font-size: var(--nf-fs-12, 12px);
3165
3534
  text-align: left;
3166
- padding: 4px 8px;
3535
+ padding: var(--nf-space-4, 4px) var(--nf-space-8, 8px);
3167
3536
  cursor: pointer;
3168
3537
  opacity: 0.8;
3169
3538
  transition: opacity 0.15s ease, background 0.15s ease;
@@ -3197,14 +3566,14 @@ select.input {
3197
3566
 
3198
3567
  .readerItemBadge {
3199
3568
  flex: none;
3200
- font-size: 11px;
3569
+ font-size: var(--nf-fs-12, 11px);
3201
3570
  }
3202
3571
 
3203
3572
  .readerMain {
3204
3573
  flex: 1;
3205
3574
  min-height: 0;
3206
3575
  overflow-y: auto;
3207
- padding: 20px 16px 48px;
3576
+ padding: var(--nf-space-20, 20px) var(--nf-space-16, 16px) var(--nf-space-48, 48px);
3208
3577
  display: flex;
3209
3578
  justify-content: center;
3210
3579
  scrollbar-width: thin;
@@ -3214,12 +3583,12 @@ select.input {
3214
3583
  width: 100%;
3215
3584
  display: flex;
3216
3585
  flex-direction: column;
3217
- gap: 12px;
3586
+ gap: var(--nf-space-12, 12px);
3218
3587
  }
3219
3588
 
3220
3589
  .readerChapterTitle {
3221
3590
  margin: 0;
3222
- font-size: 24px;
3591
+ font-size: var(--nf-fs-24, 24px);
3223
3592
  font-weight: 800;
3224
3593
  letter-spacing: 1px;
3225
3594
  }
@@ -3227,8 +3596,8 @@ select.input {
3227
3596
  .readerChapterMeta {
3228
3597
  display: flex;
3229
3598
  align-items: center;
3230
- gap: 8px;
3231
- font-size: 12px;
3599
+ gap: var(--nf-space-8, 8px);
3600
+ font-size: var(--nf-fs-12, 12px);
3232
3601
  }
3233
3602
 
3234
3603
  .readerText {
@@ -3245,17 +3614,17 @@ select.input {
3245
3614
  display: flex;
3246
3615
  align-items: center;
3247
3616
  justify-content: space-between;
3248
- gap: 8px;
3617
+ gap: var(--nf-space-8, 8px);
3249
3618
  margin-top: 12px;
3250
- padding-top: 12px;
3619
+ padding-top: var(--nf-space-12, 12px);
3251
3620
  border-top: 1px dashed;
3252
3621
  }
3253
3622
 
3254
3623
  .readerLoading,
3255
3624
  .readerError {
3256
3625
  align-self: center;
3257
- padding: 32px 0;
3258
- font-size: 13px;
3626
+ padding: var(--nf-space-32, 32px) 0;
3627
+ font-size: var(--nf-fs-14, 13px);
3259
3628
  opacity: 0.7;
3260
3629
  }
3261
3630
 
@@ -3275,7 +3644,7 @@ select.input {
3275
3644
  background: rgba(0, 0, 0, 0.45);
3276
3645
  -webkit-backdrop-filter: blur(4px);
3277
3646
  backdrop-filter: blur(4px);
3278
- padding: 24px;
3647
+ padding: var(--nf-space-24, 24px);
3279
3648
  }
3280
3649
 
3281
3650
  .importModal {
@@ -3284,10 +3653,11 @@ select.input {
3284
3653
  overflow: auto;
3285
3654
  display: flex;
3286
3655
  flex-direction: column;
3287
- gap: 12px;
3656
+ gap: var(--nf-space-12, 12px);
3288
3657
  border: 1px solid var(--nf-border-strong);
3289
- border-radius: 16px;
3290
- padding: 16px;
3658
+ border-radius: var(--nf-radius-16, 16px);
3659
+ /* 主容器统一:与设置页卡片同一 --nf-card-pad */
3660
+ padding: var(--nf-card-pad, 20px 22px);
3291
3661
  background: var(--nf-bg-raise);
3292
3662
  -webkit-backdrop-filter: blur(28px) saturate(180%);
3293
3663
  backdrop-filter: blur(28px) saturate(180%);
@@ -3298,12 +3668,12 @@ select.input {
3298
3668
  display: flex;
3299
3669
  align-items: center;
3300
3670
  justify-content: space-between;
3301
- gap: 10px;
3671
+ gap: var(--nf-space-10, 10px);
3302
3672
  }
3303
3673
 
3304
3674
  .importModalTabs {
3305
3675
  display: flex;
3306
- gap: 8px;
3676
+ gap: var(--nf-space-8, 8px);
3307
3677
  }
3308
3678
 
3309
3679
  .importModalTabs .button {
@@ -3313,28 +3683,28 @@ select.input {
3313
3683
  .importModalBody {
3314
3684
  display: flex;
3315
3685
  flex-direction: column;
3316
- gap: 10px;
3686
+ gap: var(--nf-space-10, 10px);
3317
3687
  }
3318
3688
 
3319
3689
  .importField {
3320
3690
  display: flex;
3321
3691
  flex-direction: column;
3322
- gap: 5px;
3323
- font-size: 13px;
3692
+ gap: var(--nf-space-6, 5px);
3693
+ font-size: var(--nf-fs-14, 13px);
3324
3694
  color: var(--nf-text-2);
3325
3695
  }
3326
3696
 
3327
3697
  .importHint {
3328
- font-size: 12px;
3698
+ font-size: var(--nf-fs-12, 12px);
3329
3699
  color: var(--nf-text-3);
3330
3700
  line-height: 1.5;
3331
3701
  }
3332
3702
 
3333
3703
  .importError {
3334
3704
  border: 1px solid color-mix(in srgb, var(--nf-danger, #e5484d) 55%, transparent);
3335
- border-radius: 10px;
3336
- padding: 8px 10px;
3337
- font-size: 12.5px;
3705
+ border-radius: var(--nf-radius-10, 10px);
3706
+ padding: var(--nf-space-8, 8px) var(--nf-space-10, 10px);
3707
+ font-size: var(--nf-fs-12, 12.5px);
3338
3708
  color: var(--nf-danger, #e5484d);
3339
3709
  background: color-mix(in srgb, var(--nf-danger, #e5484d) 10%, transparent);
3340
3710
  white-space: pre-wrap;
@@ -3344,11 +3714,11 @@ select.input {
3344
3714
  .importResult {
3345
3715
  display: flex;
3346
3716
  flex-direction: column;
3347
- gap: 4px;
3717
+ gap: var(--nf-space-4, 4px);
3348
3718
  border: 1px solid color-mix(in srgb, var(--nf-ok, #46a758) 45%, transparent);
3349
- border-radius: 10px;
3350
- padding: 10px 12px;
3351
- font-size: 13px;
3719
+ border-radius: var(--nf-radius-10, 10px);
3720
+ padding: var(--nf-space-10, 10px) var(--nf-space-12, 12px);
3721
+ font-size: var(--nf-fs-14, 13px);
3352
3722
  background: color-mix(in srgb, var(--nf-ok, #46a758) 9%, transparent);
3353
3723
  word-break: break-all;
3354
3724
  }
@@ -3356,14 +3726,14 @@ select.input {
3356
3726
  .importModalActions {
3357
3727
  display: flex;
3358
3728
  justify-content: flex-end;
3359
- gap: 8px;
3729
+ gap: var(--nf-space-8, 8px);
3360
3730
  }
3361
3731
 
3362
3732
  .importFileInfo {
3363
3733
  display: flex;
3364
3734
  align-items: center;
3365
- gap: 8px;
3366
- font-size: 13px;
3735
+ gap: var(--nf-space-8, 8px);
3736
+ font-size: var(--nf-fs-14, 13px);
3367
3737
  color: var(--nf-text-1);
3368
3738
  flex-wrap: wrap;
3369
3739
  }
@@ -3371,21 +3741,21 @@ select.input {
3371
3741
  .importPreview {
3372
3742
  display: flex;
3373
3743
  flex-direction: column;
3374
- gap: 4px;
3744
+ gap: var(--nf-space-4, 4px);
3375
3745
  border: 1px solid var(--nf-border-strong);
3376
- border-radius: 10px;
3377
- padding: 10px 12px;
3378
- font-size: 13px;
3746
+ border-radius: var(--nf-radius-10, 10px);
3747
+ padding: var(--nf-space-10, 10px) var(--nf-space-12, 12px);
3748
+ font-size: var(--nf-fs-14, 13px);
3379
3749
  background: var(--nf-bg-inset);
3380
3750
  }
3381
3751
 
3382
3752
  .importPreviewList {
3383
3753
  margin: 0;
3384
- padding-left: 18px;
3754
+ padding-left: var(--nf-space-18, 18px);
3385
3755
  display: flex;
3386
3756
  flex-direction: column;
3387
- gap: 2px;
3388
- font-size: 12.5px;
3757
+ gap: var(--nf-space-2, 2px);
3758
+ font-size: var(--nf-fs-12, 12.5px);
3389
3759
  color: var(--nf-text-2);
3390
3760
  max-height: 140px;
3391
3761
  overflow: auto;
@@ -3415,12 +3785,12 @@ select.input {
3415
3785
  transform: translateX(-50%);
3416
3786
  width: 280px;
3417
3787
  max-width: 70vw;
3418
- padding: 10px 12px;
3419
- border-radius: 10px;
3788
+ padding: var(--nf-space-10, 10px) var(--nf-space-12, 12px);
3789
+ border-radius: var(--nf-radius-10, 10px);
3420
3790
  background: var(--nf-bg-raise);
3421
3791
  border: 1px solid var(--nf-border-strong);
3422
3792
  box-shadow: var(--nf-shadow-lg);
3423
- font-size: 12px;
3793
+ font-size: var(--nf-fs-12, 12px);
3424
3794
  font-weight: 400;
3425
3795
  line-height: 1.7;
3426
3796
  color: var(--nf-text-2);
@@ -3436,36 +3806,19 @@ select.input {
3436
3806
  display: block;
3437
3807
  }
3438
3808
 
3439
- /* 设置页字号放大(标题明显大于正文) */
3440
- .settingsCard {
3441
- font-size: 15px;
3442
- }
3443
- .settingsCard .fieldLabel {
3444
- font-size: 14px;
3445
- }
3446
- .settingsCard .input {
3447
- font-size: 15.5px;
3448
- }
3449
- .settingsCard .meta {
3450
- font-size: 13px;
3451
- }
3452
- .settingsCard .cardTitle {
3453
- font-size: 20px;
3454
- }
3455
- .settingsCard .input {
3456
- padding: 12px 16px;
3457
- border-radius: 10px;
3458
- }
3809
+ /* 设置页:字号已统一为全局档(次要 12 / 主 14 / 标题 16+),不再放大;
3810
+ * 主容器由 .card 的 --nf-card-pad 统一提供(舒适 20px 22px)。 */
3459
3811
  .settingsCard + .settingsCard {
3460
3812
  flex: 1;
3461
3813
  min-height: 0;
3814
+ }
3462
3815
 
3463
3816
  /* 设置页开关(滑块) */
3464
3817
  .switch {
3465
3818
  position: relative;
3466
3819
  width: 42px;
3467
3820
  height: 24px;
3468
- border-radius: 999px;
3821
+ border-radius: var(--nf-radius-999, 999px);
3469
3822
  border: 1px solid var(--nf-border-strong);
3470
3823
  background: var(--nf-bg-inset);
3471
3824
  cursor: pointer;
@@ -3494,5 +3847,3 @@ select.input {
3494
3847
  .switchOn .switchKnob {
3495
3848
  transform: translateX(18px);
3496
3849
  }
3497
-
3498
- }