@waterwx/dsh-novel-forge 0.1.0 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -63,52 +63,59 @@ body[data-ds-dark-theme] .entry {
63
63
  inset: 0;
64
64
  overflow: auto;
65
65
  color-scheme: light;
66
- /* light palette */
67
- --nf-bg: #fafafc;
68
- --nf-bg-raise: #ffffff;
69
- --nf-bg-inset: #f1f1f5;
70
- --nf-border: rgba(0, 0, 0, 0.1);
71
- --nf-border-strong: rgba(0, 0, 0, 0.22);
72
- --nf-text: #1f1f23;
73
- --nf-text-2: #5b5b66;
74
- --nf-text-3: #8a8a94;
75
- --nf-accent: #4d6bfe;
76
- --nf-accent-hover: #3d5bf0;
77
- --nf-accent-soft: rgba(77, 107, 254, 0.12);
66
+ font-family: -apple-system, BlinkMacSystemFont, 'SF Pro Text', 'SF Pro SC', 'PingFang SC', 'Segoe UI', Roboto, 'Helvetica Neue', sans-serif;
67
+ /* iOS light palette (system colors, frosted translucency) */
68
+ --nf-bg: rgba(242, 242, 247, 0.86);
69
+ --nf-bg-raise: rgba(255, 255, 255, 0.72);
70
+ --nf-bg-inset: rgba(118, 118, 128, 0.12);
71
+ --nf-border: rgba(60, 60, 67, 0.16);
72
+ --nf-border-strong: rgba(60, 60, 67, 0.32);
73
+ --nf-text: #1c1c1e;
74
+ --nf-text-2: #3c3c43;
75
+ --nf-text-2-alpha: rgba(60, 60, 67, 0.68);
76
+ --nf-text-3: #8e8e93;
77
+ --nf-accent: #007aff;
78
+ --nf-accent-hover: #0071e3;
79
+ --nf-accent-soft: rgba(0, 122, 255, 0.12);
78
80
  --nf-accent-fg: #ffffff;
79
- --nf-hover: rgba(0, 0, 0, 0.06);
80
- --nf-success: #16a34a;
81
- --nf-error: #e5484d;
82
- --nf-warn: #d97706;
83
- --nf-info: #7c5cf6;
84
- --nf-shadow: 0 1px 2px rgba(16, 24, 40, 0.05), 0 4px 14px rgba(16, 24, 40, 0.06);
85
- --nf-shadow-lg: 0 4px 10px rgba(16, 24, 40, 0.06), 0 12px 28px rgba(16, 24, 40, 0.1);
81
+ --nf-hover: rgba(0, 0, 0, 0.05);
82
+ --nf-success: #34c759;
83
+ --nf-error: #ff3b30;
84
+ --nf-warn: #ff9500;
85
+ --nf-info: #5856d6;
86
+ --nf-shadow: 0 1px 3px rgba(0, 0, 0, 0.06), 0 12px 32px rgba(0, 0, 0, 0.08);
87
+ --nf-shadow-lg: 0 4px 12px rgba(0, 0, 0, 0.07), 0 20px 48px rgba(0, 0, 0, 0.12);
86
88
  background: var(--nf-bg);
89
+ /* Frosted glass: blur whatever is behind the panel (the chat dialog),
90
+ * so translucency shows a soft blur instead of readable content. */
91
+ -webkit-backdrop-filter: blur(32px) saturate(180%);
92
+ backdrop-filter: blur(32px) saturate(180%);
87
93
  color: var(--nf-text);
88
94
  }
89
95
 
90
96
  body[data-ds-dark-theme] .view {
91
97
  color-scheme: dark;
92
- /* dark palette */
93
- --nf-bg: #121216;
94
- --nf-bg-raise: #1a1a20;
95
- --nf-bg-inset: #232329;
96
- --nf-border: rgba(255, 255, 255, 0.1);
97
- --nf-border-strong: rgba(255, 255, 255, 0.24);
98
- --nf-text: #ececf1;
99
- --nf-text-2: #b0b0ba;
100
- --nf-text-3: #7d7d88;
101
- --nf-accent: #5b7cff;
102
- --nf-accent-hover: #7390ff;
103
- --nf-accent-soft: rgba(91, 124, 255, 0.18);
98
+ /* iOS dark palette */
99
+ --nf-bg: rgba(0, 0, 0, 0.72);
100
+ --nf-bg-raise: rgba(28, 28, 30, 0.78);
101
+ --nf-bg-inset: rgba(118, 118, 128, 0.18);
102
+ --nf-border: rgba(255, 255, 255, 0.12);
103
+ --nf-border-strong: rgba(255, 255, 255, 0.28);
104
+ --nf-text: #f2f2f7;
105
+ --nf-text-2: #d1d1d6;
106
+ --nf-text-2-alpha: rgba(209, 209, 214, 0.72);
107
+ --nf-text-3: #8e8e93;
108
+ --nf-accent: #0a84ff;
109
+ --nf-accent-hover: #3a9bff;
110
+ --nf-accent-soft: rgba(10, 132, 255, 0.2);
104
111
  --nf-accent-fg: #ffffff;
105
- --nf-hover: rgba(255, 255, 255, 0.08);
106
- --nf-success: #4ade80;
107
- --nf-error: #f87171;
108
- --nf-warn: #fbbf24;
109
- --nf-info: #a78bfa;
110
- --nf-shadow: 0 1px 2px rgba(0, 0, 0, 0.4), 0 4px 14px rgba(0, 0, 0, 0.35);
111
- --nf-shadow-lg: 0 4px 10px rgba(0, 0, 0, 0.4), 0 12px 28px rgba(0, 0, 0, 0.5);
112
+ --nf-hover: rgba(255, 255, 255, 0.09);
113
+ --nf-success: #30d158;
114
+ --nf-error: #ff453a;
115
+ --nf-warn: #ff9f0a;
116
+ --nf-info: #bf5af2;
117
+ --nf-shadow: 0 1px 2px rgba(0, 0, 0, 0.35), 0 10px 30px rgba(0, 0, 0, 0.4);
118
+ --nf-shadow-lg: 0 4px 12px rgba(0, 0, 0, 0.4), 0 20px 48px rgba(0, 0, 0, 0.55);
112
119
  }
113
120
 
114
121
  html[data-dsh-novelforge-active]:not([data-dsh-taskboard-active]):not([data-dsh-ssh-active]) .view {
@@ -124,6 +131,7 @@ html[data-dsh-novelforge-active]:not([data-dsh-taskboard-active]):not([data-dsh-
124
131
  min-width: 0;
125
132
  font-size: 14px;
126
133
  line-height: 1.6;
134
+ position: relative;
127
135
  }
128
136
 
129
137
  .panelHeader {
@@ -134,6 +142,8 @@ html[data-dsh-novelforge-active]:not([data-dsh-taskboard-active]):not([data-dsh-
134
142
  border-bottom: 1px solid var(--nf-border);
135
143
  flex-shrink: 0;
136
144
  background: var(--nf-bg-raise);
145
+ -webkit-backdrop-filter: blur(24px) saturate(180%);
146
+ backdrop-filter: blur(24px) saturate(180%);
137
147
  position: sticky;
138
148
  top: 0;
139
149
  z-index: 5;
@@ -230,17 +240,199 @@ html[data-dsh-novelforge-active]:not([data-dsh-taskboard-active]):not([data-dsh-
230
240
  gap: 14px;
231
241
  }
232
242
 
243
+ /* ------------------------------------------- body: left nav + content */
244
+
245
+ .panelBody {
246
+ flex: 1;
247
+ min-height: 0;
248
+ display: flex;
249
+ }
250
+
251
+ .panelNav {
252
+ flex: none;
253
+ width: 142px;
254
+ display: flex;
255
+ flex-direction: column;
256
+ gap: 2px;
257
+ padding: 10px 8px;
258
+ border-right: 1px solid var(--nf-border);
259
+ background: var(--nf-bg-raise);
260
+ -webkit-backdrop-filter: blur(24px) saturate(180%);
261
+ backdrop-filter: blur(24px) saturate(180%);
262
+ overflow-y: auto;
263
+ transition: width 0.18s ease;
264
+ }
265
+
266
+ .panelNavCollapsed {
267
+ width: 52px;
268
+ padding: 10px 6px;
269
+ }
270
+
271
+ .navGroup {
272
+ display: flex;
273
+ flex-direction: column;
274
+ gap: 2px;
275
+ }
276
+
277
+ .navGroupLabel {
278
+ font-size: 10.5px;
279
+ font-weight: 600;
280
+ letter-spacing: 0.6px;
281
+ text-transform: uppercase;
282
+ color: var(--nf-text-3);
283
+ padding: 6px 10px 2px;
284
+ user-select: none;
285
+ }
286
+
287
+ .navGroupSep {
288
+ height: 1px;
289
+ margin: 6px 8px 4px;
290
+ background: var(--nf-border);
291
+ }
292
+
293
+ .navSpacer {
294
+ flex: 1;
295
+ min-height: 8px;
296
+ }
297
+
298
+ .navTabBadge {
299
+ margin-left: auto;
300
+ flex: none;
301
+ min-width: 18px;
302
+ height: 18px;
303
+ padding: 0 5px;
304
+ border-radius: 999px;
305
+ background: var(--nf-accent);
306
+ color: #fff;
307
+ font-size: 10.5px;
308
+ font-weight: 700;
309
+ line-height: 18px;
310
+ text-align: center;
311
+ display: inline-block;
312
+ }
313
+
314
+ .panelNavCollapsed .navTabBadge {
315
+ position: absolute;
316
+ top: 2px;
317
+ right: 2px;
318
+ min-width: 14px;
319
+ height: 14px;
320
+ line-height: 14px;
321
+ font-size: 9px;
322
+ padding: 0 3px;
323
+ }
324
+
325
+ .navTabBadgeDanger {
326
+ background: var(--nf-error);
327
+ }
328
+
329
+ .navTabBadgeWarn {
330
+ background: var(--nf-warn);
331
+ }
332
+
333
+ .navTabBadgeDone {
334
+ background: var(--nf-success);
335
+ }
336
+
337
+ .navTab {
338
+ display: flex;
339
+ align-items: center;
340
+ gap: 8px;
341
+ width: 100%;
342
+ border: none;
343
+ background: transparent;
344
+ cursor: pointer;
345
+ border-radius: 12px;
346
+ padding: 8px 10px;
347
+ font-size: 13px;
348
+ color: var(--nf-text-2-alpha, var(--nf-text-2));
349
+ font-weight: 500;
350
+ transition: color 0.15s ease, background 0.15s ease;
351
+ position: relative;
352
+ text-align: left;
353
+ white-space: nowrap;
354
+ }
355
+
356
+ .panelNavCollapsed .navTab {
357
+ justify-content: center;
358
+ padding: 8px 0;
359
+ }
360
+
361
+ .navTab:hover {
362
+ color: var(--nf-text);
363
+ background: var(--nf-hover);
364
+ }
365
+
366
+ .navTab[data-active] {
367
+ color: var(--nf-accent);
368
+ font-weight: 600;
369
+ background: var(--nf-accent-soft);
370
+ }
371
+
372
+ .navTab[data-active]::before {
373
+ content: '';
374
+ position: absolute;
375
+ left: -8px;
376
+ top: 20%;
377
+ bottom: 20%;
378
+ width: 3px;
379
+ border-radius: 999px;
380
+ background: var(--nf-accent);
381
+ }
382
+
383
+ .panelNavCollapsed .navTab[data-active]::before {
384
+ left: -6px;
385
+ }
386
+
387
+ .navTabIcon {
388
+ flex: none;
389
+ font-size: 15px;
390
+ line-height: 1;
391
+ }
392
+
393
+ .navTabLabel {
394
+ overflow: hidden;
395
+ text-overflow: ellipsis;
396
+ }
397
+
398
+ /* 顶栏进度摘要 */
399
+ .headerProgress {
400
+ font-size: 12px;
401
+ font-weight: 400;
402
+ color: var(--nf-text-2);
403
+ display: inline-flex;
404
+ align-items: center;
405
+ gap: 6px;
406
+ margin-left: 4px;
407
+ white-space: nowrap;
408
+ }
409
+
410
+ .headerProgress b {
411
+ color: var(--nf-accent);
412
+ font-weight: 700;
413
+ }
414
+
415
+ .headerProgressDot {
416
+ width: 3px;
417
+ height: 3px;
418
+ border-radius: 50%;
419
+ background: var(--nf-border-strong, var(--nf-text-3));
420
+ display: inline-block;
421
+ }
422
+
233
423
  /* ------------------------------------------------------------ cards */
234
424
 
235
425
  .card {
236
426
  border: 1px solid var(--nf-border);
237
- border-radius: 12px;
238
- padding: 14px 16px;
427
+ border-radius: 20px;
428
+ padding: 16px 18px;
239
429
  display: flex;
240
430
  flex-direction: column;
241
431
  gap: 10px;
242
432
  background: var(--nf-bg-raise);
243
433
  box-shadow: var(--nf-shadow);
434
+ -webkit-backdrop-filter: blur(24px) saturate(180%);
435
+ backdrop-filter: blur(24px) saturate(180%);
244
436
  transition: border-color 0.2s ease, box-shadow 0.2s ease;
245
437
  }
246
438
 
@@ -261,7 +453,7 @@ html[data-dsh-novelforge-active]:not([data-dsh-taskboard-active]):not([data-dsh-
261
453
  background: var(--nf-bg-inset);
262
454
  color: var(--nf-text);
263
455
  padding: 6px 14px;
264
- border-radius: 8px;
456
+ border-radius: 12px;
265
457
  cursor: pointer;
266
458
  font-size: 13px;
267
459
  font-weight: 500;
@@ -275,7 +467,7 @@ html[data-dsh-novelforge-active]:not([data-dsh-taskboard-active]):not([data-dsh-
275
467
  }
276
468
 
277
469
  .button:active:not([disabled]) {
278
- transform: translateY(1px);
470
+ transform: scale(0.96);
279
471
  }
280
472
 
281
473
  .button[disabled] {
@@ -284,15 +476,15 @@ html[data-dsh-novelforge-active]:not([data-dsh-taskboard-active]):not([data-dsh-
284
476
  }
285
477
 
286
478
  .buttonPrimary {
287
- border-color: var(--nf-accent);
288
- background: linear-gradient(180deg, var(--nf-accent), var(--nf-accent-hover));
479
+ border-color: transparent;
480
+ background: linear-gradient(180deg, color-mix(in srgb, var(--nf-accent) 88%, #ffffff), var(--nf-accent));
289
481
  color: var(--nf-accent-fg);
290
- box-shadow: 0 1px 3px rgba(77, 107, 254, 0.25);
482
+ box-shadow: 0 2px 8px color-mix(in srgb, var(--nf-accent) 35%, transparent);
291
483
  }
292
484
 
293
485
  .buttonPrimary:hover:not([disabled]) {
294
- background: linear-gradient(180deg, var(--nf-accent-hover), var(--nf-accent));
295
- border-color: var(--nf-accent-hover);
486
+ background: linear-gradient(180deg, var(--nf-accent-hover), color-mix(in srgb, var(--nf-accent-hover) 85%, #000000));
487
+ border-color: transparent;
296
488
  }
297
489
 
298
490
  .buttonDanger {
@@ -301,13 +493,13 @@ html[data-dsh-novelforge-active]:not([data-dsh-taskboard-active]):not([data-dsh-
301
493
  }
302
494
 
303
495
  .buttonDanger:hover:not([disabled]) {
304
- background: rgba(229, 72, 77, 0.1);
496
+ background: rgba(255, 59, 48, 0.1);
305
497
  }
306
498
 
307
499
  .buttonSmall {
308
500
  padding: 3px 10px;
309
501
  font-size: 12px;
310
- border-radius: 6px;
502
+ border-radius: 9px;
311
503
  }
312
504
 
313
505
  /* ------------------------------------------------------------ forms */
@@ -328,7 +520,7 @@ html[data-dsh-novelforge-active]:not([data-dsh-taskboard-active]):not([data-dsh-
328
520
  border: 1px solid var(--nf-border-strong);
329
521
  background: var(--nf-bg-inset);
330
522
  color: var(--nf-text);
331
- border-radius: 8px;
523
+ border-radius: 12px;
332
524
  padding: 7px 11px;
333
525
  font-size: 13px;
334
526
  width: 100%;
@@ -352,7 +544,7 @@ html[data-dsh-novelforge-active]:not([data-dsh-taskboard-active]):not([data-dsh-
352
544
  border: 1px solid var(--nf-border-strong);
353
545
  background: var(--nf-bg-inset);
354
546
  color: var(--nf-text);
355
- border-radius: 8px;
547
+ border-radius: 12px;
356
548
  padding: 9px 11px;
357
549
  font-size: 13px;
358
550
  width: 100%;
@@ -613,22 +805,634 @@ html[data-dsh-novelforge-active]:not([data-dsh-taskboard-active]):not([data-dsh-
613
805
  opacity: 0.9;
614
806
  }
615
807
 
616
- .progressLineDone {
617
- color: var(--nf-success);
808
+ .progressLineLive {
809
+ color: var(--nf-accent);
618
810
  font-weight: 600;
811
+ display: flex;
812
+ align-items: center;
813
+ gap: 8px;
619
814
  }
620
815
 
621
- .progressLineError {
622
- color: var(--nf-error);
623
- font-weight: 600;
816
+ .progressBar {
817
+ display: inline-block;
818
+ flex: none;
819
+ width: 110px;
820
+ height: 6px;
821
+ border-radius: 999px;
822
+ background: var(--nf-border);
823
+ overflow: hidden;
624
824
  }
625
825
 
626
- /* ------------------------------------------------------------ misc */
826
+ .progressBarFill {
827
+ display: block;
828
+ height: 100%;
829
+ border-radius: 3px;
830
+ background: var(--nf-accent);
831
+ transition: width 0.3s ease;
832
+ }
627
833
 
628
- .meta {
834
+ /* Prominent top-of-panel generation progress (visible on every tab). */
835
+ .busyRow {
836
+ display: flex;
837
+ align-items: center;
838
+ justify-content: space-between;
839
+ gap: 12px;
840
+ flex-wrap: wrap;
841
+ }
842
+
843
+ .liveText {
629
844
  font-size: 12px;
845
+ font-variant-numeric: tabular-nums;
630
846
  color: var(--nf-text-2);
631
- opacity: 0.9;
847
+ }
848
+
849
+ .bigProgressBar {
850
+ margin-top: 10px;
851
+ height: 8px;
852
+ border-radius: 999px;
853
+ background: var(--nf-border);
854
+ overflow: hidden;
855
+ }
856
+
857
+ .bigProgressBarFill {
858
+ display: block;
859
+ height: 100%;
860
+ border-radius: 999px;
861
+ background: linear-gradient(90deg, var(--nf-accent), var(--nf-accent-2, var(--nf-accent)));
862
+ transition: width 0.3s ease;
863
+ }
864
+
865
+ /* Draft-vs-original diff view (polish / rewrite comparison). */
866
+ .diffLegend {
867
+ display: flex;
868
+ align-items: center;
869
+ gap: 14px;
870
+ flex-wrap: wrap;
871
+ margin: 6px 0 8px;
872
+ font-size: 12px;
873
+ }
874
+
875
+ .legendOld {
876
+ color: var(--nf-error);
877
+ font-weight: 700;
878
+ }
879
+
880
+ .legendNew {
881
+ color: var(--nf-success);
882
+ font-weight: 700;
883
+ }
884
+
885
+ .onlyChanges {
886
+ display: inline-flex;
887
+ align-items: center;
888
+ gap: 4px;
889
+ color: var(--nf-text-2);
890
+ cursor: pointer;
891
+ margin-left: auto;
892
+ }
893
+
894
+ .diffList {
895
+ max-height: 460px;
896
+ overflow-y: auto;
897
+ border: 1px solid var(--nf-border);
898
+ border-radius: 8px;
899
+ background: var(--nf-bg-inset);
900
+ padding: 10px 12px;
901
+ display: flex;
902
+ flex-direction: column;
903
+ gap: 8px;
904
+ font-size: 13px;
905
+ line-height: 1.7;
906
+ }
907
+
908
+ .diffSame {
909
+ border: 1px dashed var(--nf-border);
910
+ border-radius: 6px;
911
+ padding: 6px 10px;
912
+ color: var(--nf-text-2);
913
+ opacity: 0.85;
914
+ }
915
+
916
+ .diffSame summary {
917
+ cursor: pointer;
918
+ font-size: 12px;
919
+ user-select: none;
920
+ }
921
+
922
+ .diffSameBody {
923
+ margin-top: 6px;
924
+ white-space: pre-wrap;
925
+ }
926
+
927
+ /* change 块:左右两栏(左原稿 / 右新稿),带标签徽标 */
928
+ .diffChange {
929
+ display: grid;
930
+ grid-template-columns: 1fr 1fr;
931
+ border: 1px solid var(--nf-border);
932
+ border-radius: 8px;
933
+ overflow: hidden;
934
+ }
935
+
936
+ .diffColumn {
937
+ display: flex;
938
+ flex-direction: column;
939
+ gap: 6px;
940
+ min-width: 0;
941
+ padding: 8px 10px;
942
+ }
943
+
944
+ .diffColumn:first-child {
945
+ border-right: 1px solid var(--nf-border);
946
+ }
947
+
948
+ .diffTagOld,
949
+ .diffTagNew {
950
+ align-self: flex-start;
951
+ flex: none;
952
+ font-size: 11px;
953
+ font-weight: 700;
954
+ border-radius: 4px;
955
+ padding: 1px 7px;
956
+ letter-spacing: 0.5px;
957
+ }
958
+
959
+ .diffTagOld {
960
+ color: var(--nf-error);
961
+ background: color-mix(in srgb, var(--nf-error) 16%, transparent);
962
+ border: 1px solid color-mix(in srgb, var(--nf-error) 45%, transparent);
963
+ }
964
+
965
+ .diffTagNew {
966
+ color: var(--nf-success);
967
+ background: color-mix(in srgb, var(--nf-success) 16%, transparent);
968
+ border: 1px solid color-mix(in srgb, var(--nf-success) 45%, transparent);
969
+ }
970
+
971
+ .diffOld {
972
+ color: var(--nf-error);
973
+ white-space: pre-wrap;
974
+ text-decoration: line-through;
975
+ text-decoration-color: color-mix(in srgb, var(--nf-error) 55%, transparent);
976
+ }
977
+
978
+ .diffNew {
979
+ color: var(--nf-success);
980
+ white-space: pre-wrap;
981
+ font-weight: 500;
982
+ }
983
+
984
+ .diffDel {
985
+ display: flex;
986
+ flex-direction: column;
987
+ gap: 4px;
988
+ padding: 6px 10px;
989
+ border-radius: 6px;
990
+ border: 1px solid color-mix(in srgb, var(--nf-error) 35%, transparent);
991
+ background: color-mix(in srgb, var(--nf-error) 7%, transparent);
992
+ }
993
+
994
+ .diffAdd {
995
+ display: flex;
996
+ flex-direction: column;
997
+ gap: 4px;
998
+ padding: 6px 10px;
999
+ border-radius: 6px;
1000
+ border: 1px solid color-mix(in srgb, var(--nf-success) 35%, transparent);
1001
+ background: color-mix(in srgb, var(--nf-success) 7%, transparent);
1002
+ }
1003
+
1004
+ .diffText {
1005
+ white-space: pre-wrap;
1006
+ }
1007
+
1008
+ .diffDel .diffText {
1009
+ color: var(--nf-error);
1010
+ text-decoration: line-through;
1011
+ text-decoration-color: color-mix(in srgb, var(--nf-error) 50%, transparent);
1012
+ }
1013
+
1014
+ .diffAdd .diffText {
1015
+ color: var(--nf-success);
1016
+ }
1017
+
1018
+ /* Revision workspace: left original editor + right instruction/preview. */
1019
+ .wsColumns {
1020
+ display: grid;
1021
+ grid-template-columns: minmax(0, 3fr) minmax(0, 2fr);
1022
+ gap: 14px;
1023
+ }
1024
+
1025
+ .wsColumn {
1026
+ display: flex;
1027
+ flex-direction: column;
1028
+ gap: 8px;
1029
+ min-width: 0;
1030
+ }
1031
+
1032
+ .wsEditor {
1033
+ flex: 1;
1034
+ min-height: 340px;
1035
+ resize: vertical;
1036
+ font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
1037
+ font-size: 13px;
1038
+ line-height: 1.75;
1039
+ white-space: pre-wrap;
1040
+ }
1041
+
1042
+ .wsSelected {
1043
+ border: 1px solid var(--nf-accent);
1044
+ border-radius: 6px;
1045
+ padding: 6px 10px;
1046
+ background: color-mix(in srgb, var(--nf-accent) 8%, transparent);
1047
+ max-height: 120px;
1048
+ overflow: auto;
1049
+ }
1050
+
1051
+ .wsSelectedText {
1052
+ margin-top: 4px;
1053
+ font-size: 12px;
1054
+ color: var(--nf-text-2);
1055
+ white-space: pre-wrap;
1056
+ }
1057
+
1058
+ .wsPreview {
1059
+ border: 1px solid var(--nf-border);
1060
+ border-radius: 8px;
1061
+ padding: 8px 10px;
1062
+ display: flex;
1063
+ flex-direction: column;
1064
+ gap: 8px;
1065
+ background: var(--nf-bg-inset);
1066
+ }
1067
+
1068
+ .wsPreviewText {
1069
+ margin: 0;
1070
+ max-height: 320px;
1071
+ overflow: auto;
1072
+ font-size: 13px;
1073
+ line-height: 1.7;
1074
+ white-space: pre-wrap;
1075
+ color: var(--nf-text);
1076
+ }
1077
+
1078
+ /* Assets overview status grid (AI-Novel-Writing-Assistant AssetLibraryStatusGrid). */
1079
+ .assetGrid {
1080
+ display: grid;
1081
+ grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
1082
+ gap: 10px;
1083
+ }
1084
+
1085
+ .assetStat {
1086
+ border: 1px solid var(--nf-border);
1087
+ border-radius: 10px;
1088
+ padding: 10px 12px;
1089
+ display: flex;
1090
+ flex-direction: column;
1091
+ gap: 4px;
1092
+ background: var(--nf-bg-inset);
1093
+ }
1094
+
1095
+ .assetStatLabel {
1096
+ font-size: 11px;
1097
+ color: var(--nf-text-2);
1098
+ opacity: 0.9;
1099
+ }
1100
+
1101
+ .assetStatValue {
1102
+ font-size: 15px;
1103
+ font-weight: 700;
1104
+ line-height: 1.2;
1105
+ color: var(--nf-text);
1106
+ }
1107
+
1108
+ .assetStatDetail {
1109
+ font-size: 11px;
1110
+ color: var(--nf-text-2);
1111
+ opacity: 0.85;
1112
+ overflow: hidden;
1113
+ text-overflow: ellipsis;
1114
+ white-space: nowrap;
1115
+ }
1116
+
1117
+ /* ------------------------------------------------ dashboard (workflow tab) */
1118
+
1119
+ .dashHero {
1120
+ border: 1px solid var(--nf-border);
1121
+ border-radius: 16px;
1122
+ padding: 18px 20px;
1123
+ background:
1124
+ radial-gradient(1200px 400px at 110% -60%, color-mix(in srgb, var(--nf-accent) 16%, transparent), transparent 60%),
1125
+ linear-gradient(135deg, var(--nf-bg-raise), color-mix(in srgb, var(--nf-accent) 5%, var(--nf-bg-raise)));
1126
+ box-shadow: var(--nf-shadow);
1127
+ display: flex;
1128
+ flex-direction: column;
1129
+ gap: 14px;
1130
+ }
1131
+
1132
+ .dashHeroEyebrow {
1133
+ display: inline-flex;
1134
+ align-items: center;
1135
+ gap: 6px;
1136
+ font-size: 13px;
1137
+ font-weight: 600;
1138
+ color: var(--nf-accent);
1139
+ }
1140
+
1141
+ .dashHeroSparkle {
1142
+ font-size: 14px;
1143
+ }
1144
+
1145
+ .dashHeroTitle {
1146
+ display: flex;
1147
+ flex-direction: column;
1148
+ gap: 2px;
1149
+ }
1150
+
1151
+ .dashHeroBook {
1152
+ margin: 0;
1153
+ font-size: 24px;
1154
+ font-weight: 700;
1155
+ letter-spacing: -0.3px;
1156
+ line-height: 1.25;
1157
+ }
1158
+
1159
+ .dashHeroAction {
1160
+ display: flex;
1161
+ align-items: center;
1162
+ gap: 12px;
1163
+ border: 1px solid var(--nf-border);
1164
+ border-radius: 12px;
1165
+ background: color-mix(in srgb, var(--nf-bg-base) 65%, transparent);
1166
+ padding: 10px 14px;
1167
+ }
1168
+
1169
+ .dashHeroArrow {
1170
+ flex: none;
1171
+ width: 28px;
1172
+ height: 28px;
1173
+ border-radius: 50%;
1174
+ background: var(--nf-accent);
1175
+ color: #fff;
1176
+ display: inline-flex;
1177
+ align-items: center;
1178
+ justify-content: center;
1179
+ font-size: 14px;
1180
+ }
1181
+
1182
+ .dashHeroActionBody {
1183
+ flex: 1;
1184
+ min-width: 0;
1185
+ display: flex;
1186
+ flex-direction: column;
1187
+ gap: 2px;
1188
+ }
1189
+
1190
+ .dashHeroActionTitle {
1191
+ font-size: 14px;
1192
+ font-weight: 600;
1193
+ }
1194
+
1195
+ .dashJourney {
1196
+ display: flex;
1197
+ flex-direction: column;
1198
+ gap: 6px;
1199
+ }
1200
+
1201
+ .dashJourneyBar {
1202
+ height: 6px;
1203
+ border-radius: 999px;
1204
+ background: var(--nf-border);
1205
+ overflow: hidden;
1206
+ }
1207
+
1208
+ .dashJourneyFill {
1209
+ display: block;
1210
+ height: 100%;
1211
+ border-radius: 999px;
1212
+ background: linear-gradient(90deg, var(--nf-info), var(--nf-accent));
1213
+ transition: width 0.4s ease;
1214
+ }
1215
+
1216
+ .dashJourneyStages {
1217
+ display: grid;
1218
+ grid-template-columns: repeat(6, minmax(0, 1fr));
1219
+ gap: 4px;
1220
+ }
1221
+
1222
+ .dashStage {
1223
+ display: flex;
1224
+ flex-direction: column;
1225
+ align-items: center;
1226
+ gap: 3px;
1227
+ font-size: 11px;
1228
+ color: var(--nf-text-3);
1229
+ text-align: center;
1230
+ white-space: nowrap;
1231
+ }
1232
+
1233
+ .dashStageDot {
1234
+ width: 18px;
1235
+ height: 18px;
1236
+ border-radius: 50%;
1237
+ border: 1px solid var(--nf-border-strong, var(--nf-text-3));
1238
+ display: inline-flex;
1239
+ align-items: center;
1240
+ justify-content: center;
1241
+ font-size: 10px;
1242
+ background: var(--nf-bg-base);
1243
+ }
1244
+
1245
+ .dashStageDone {
1246
+ color: var(--nf-text-2);
1247
+ }
1248
+
1249
+ .dashStageDone .dashStageDot {
1250
+ background: var(--nf-success);
1251
+ border-color: var(--nf-success);
1252
+ color: #fff;
1253
+ }
1254
+
1255
+ .dashStageCurrent {
1256
+ color: var(--nf-accent);
1257
+ font-weight: 600;
1258
+ }
1259
+
1260
+ .dashStageCurrent .dashStageDot {
1261
+ border-color: var(--nf-accent);
1262
+ color: var(--nf-accent);
1263
+ box-shadow: 0 0 0 3px color-mix(in srgb, var(--nf-accent) 18%, transparent);
1264
+ }
1265
+
1266
+ .dashFacts {
1267
+ display: grid;
1268
+ grid-template-columns: repeat(4, minmax(0, 1fr));
1269
+ gap: 8px;
1270
+ border-top: 1px solid var(--nf-border);
1271
+ padding-top: 12px;
1272
+ }
1273
+
1274
+ .dashFact {
1275
+ display: flex;
1276
+ flex-direction: column;
1277
+ gap: 2px;
1278
+ min-width: 0;
1279
+ }
1280
+
1281
+ .dashFact b {
1282
+ font-size: 13px;
1283
+ white-space: nowrap;
1284
+ overflow: hidden;
1285
+ text-overflow: ellipsis;
1286
+ }
1287
+
1288
+ .dashGrid {
1289
+ display: grid;
1290
+ grid-template-columns: minmax(0, 3fr) minmax(0, 2fr);
1291
+ gap: 14px;
1292
+ align-items: start;
1293
+ }
1294
+
1295
+ .todoItem {
1296
+ display: flex;
1297
+ align-items: center;
1298
+ gap: 10px;
1299
+ border-radius: 8px;
1300
+ padding: 8px 12px;
1301
+ font-size: 12.5px;
1302
+ border: 1px solid var(--nf-border);
1303
+ }
1304
+
1305
+ .todoDanger {
1306
+ border-color: color-mix(in srgb, var(--nf-error) 40%, transparent);
1307
+ background: color-mix(in srgb, var(--nf-error) 8%, transparent);
1308
+ }
1309
+
1310
+ .todoWarning {
1311
+ border-color: color-mix(in srgb, var(--nf-warn) 40%, transparent);
1312
+ background: color-mix(in srgb, var(--nf-warn) 8%, transparent);
1313
+ }
1314
+
1315
+ .todoInfo {
1316
+ border-color: color-mix(in srgb, var(--nf-info) 40%, transparent);
1317
+ background: color-mix(in srgb, var(--nf-info) 7%, transparent);
1318
+ }
1319
+
1320
+ .todoText {
1321
+ flex: 1;
1322
+ min-width: 0;
1323
+ display: flex;
1324
+ flex-direction: column;
1325
+ gap: 2px;
1326
+ }
1327
+
1328
+ /* 只读大纲(开书后的出生证明) */
1329
+ .outlineReadonly {
1330
+ margin: 0;
1331
+ padding: 12px 14px;
1332
+ border: 1px solid var(--nf-border);
1333
+ border-radius: 12px;
1334
+ background: var(--nf-bg-inset);
1335
+ font-size: 12.5px;
1336
+ line-height: 1.8;
1337
+ white-space: pre-wrap;
1338
+ max-height: 480px;
1339
+ overflow: auto;
1340
+ user-select: text;
1341
+ }
1342
+
1343
+ /* 开书向导表单 */
1344
+ .bookCreateOutline {
1345
+ display: flex;
1346
+ flex-direction: column;
1347
+ gap: 6px;
1348
+ align-items: flex-start;
1349
+ }
1350
+
1351
+ /* AI 助手悬浮窗:可拖动移动 + 右下角拉大小 */
1352
+ .assistantFloat {
1353
+ position: absolute;
1354
+ z-index: 80;
1355
+ display: flex;
1356
+ flex-direction: column;
1357
+ border: 1px solid var(--nf-border);
1358
+ border-radius: 16px;
1359
+ background: var(--nf-bg-raise);
1360
+ -webkit-backdrop-filter: blur(24px) saturate(180%);
1361
+ backdrop-filter: blur(24px) saturate(180%);
1362
+ box-shadow: var(--nf-shadow-lg);
1363
+ overflow: hidden;
1364
+ min-width: 320px;
1365
+ min-height: 220px;
1366
+ }
1367
+
1368
+ .assistantFloatHeader {
1369
+ flex: none;
1370
+ display: flex;
1371
+ align-items: center;
1372
+ justify-content: space-between;
1373
+ gap: 8px;
1374
+ padding: 8px 10px 8px 14px;
1375
+ cursor: grab;
1376
+ user-select: none;
1377
+ font-size: 13px;
1378
+ font-weight: 600;
1379
+ border-bottom: 1px solid var(--nf-border);
1380
+ background: var(--nf-bg-inset);
1381
+ }
1382
+
1383
+ .assistantFloatHeader:active {
1384
+ cursor: grabbing;
1385
+ }
1386
+
1387
+ .assistantFloatBody {
1388
+ flex: 1;
1389
+ min-height: 0;
1390
+ overflow: hidden;
1391
+ display: flex;
1392
+ padding: 10px;
1393
+ }
1394
+
1395
+ .assistantFloatBody > * {
1396
+ flex: 1;
1397
+ min-width: 0;
1398
+ }
1399
+
1400
+ .assistantResize {
1401
+ position: absolute;
1402
+ right: 0;
1403
+ bottom: 0;
1404
+ width: 20px;
1405
+ height: 20px;
1406
+ cursor: nwse-resize;
1407
+ background:
1408
+ linear-gradient(135deg, transparent 0 55%, var(--nf-border-strong) 55% 62%, transparent 62%) no-repeat 4px 4px / 12px 12px;
1409
+ }
1410
+
1411
+ .progressLineDone {
1412
+ color: var(--nf-success);
1413
+ font-weight: 600;
1414
+ }
1415
+
1416
+ .progressLineError {
1417
+ color: var(--nf-error);
1418
+ font-weight: 600;
1419
+ }
1420
+
1421
+ /* ------------------------------------------------------------ misc */
1422
+
1423
+ .meta {
1424
+ font-size: 12px;
1425
+ color: var(--nf-text-2);
1426
+ opacity: 0.9;
1427
+ }
1428
+
1429
+ /* 题材基底:描述两行截断(悬停 title 看全文),保持列表紧凑自然展开 */
1430
+ .genreDesc {
1431
+ display: -webkit-box;
1432
+ -webkit-line-clamp: 2;
1433
+ -webkit-box-orient: vertical;
1434
+ overflow: hidden;
1435
+ max-width: 560px;
632
1436
  }
633
1437
 
634
1438
  .fileList {