@waterwx/dsh-novel-forge 1.7.2 → 1.7.3

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.
package/lib/client.js CHANGED
@@ -12,12 +12,6 @@ window.__ModuleLoader__.load({
12
12
  let react_jsx_runtime = require("react/jsx-runtime");
13
13
  let react_dom = require("react-dom");
14
14
  //#region src/protocol.ts
15
- /**
16
- * dsh-novel-forge — shared protocol between the host half (Node) and the
17
- * browser half (web GUI). Route paths, request/response shapes, the project
18
- * state file format, and the NDJSON generation stream frames all live here so
19
- * both halves spell exactly one vocabulary.
20
- */
21
15
  /** The /api/dsh-novel-forge route family (same-origin, loopback-fenced). */
22
16
  const NOVEL_API = {
23
17
  status: "/api/dsh-novel-forge/status",
@@ -35237,298 +35231,298 @@ window.__ModuleLoader__.load({
35237
35231
  document.head.appendChild(tag);
35238
35232
  }
35239
35233
  var panel_module_css_default = {
35240
- "createBookView": "zE6uZW_createBookView",
35241
- "buttonDanger": "zE6uZW_buttonDanger",
35242
- "wsColumns": "zE6uZW_wsColumns",
35243
- "toolLive": "zE6uZW_toolLive",
35244
- "buttonSmall": "zE6uZW_buttonSmall",
35245
- "spaceBetween": "zE6uZW_spaceBetween",
35246
- "wsSelected": "zE6uZW_wsSelected",
35247
- "progressLineError": "zE6uZW_progressLineError",
35248
- "bookCard": "zE6uZW_bookCard",
35249
- "diffChange": "zE6uZW_diffChange",
35250
- "dashHeroSparkle": "zE6uZW_dashHeroSparkle",
35234
+ "helpTipText": "zE6uZW_helpTipText",
35235
+ "dropzone": "zE6uZW_dropzone",
35236
+ "workflowDotDone": "zE6uZW_workflowDotDone",
35237
+ "statCardDIconRed": "zE6uZW_statCardDIconRed",
35238
+ "navTitleLogo": "zE6uZW_navTitleLogo",
35239
+ "badgePending": "zE6uZW_badgePending",
35240
+ "toolStep": "zE6uZW_toolStep",
35241
+ "importHint": "zE6uZW_importHint",
35242
+ "bookAddIcon": "zE6uZW_bookAddIcon",
35243
+ "statCardDUnit": "zE6uZW_statCardDUnit",
35244
+ "wsPageHeader": "zE6uZW_wsPageHeader",
35245
+ "navTitle": "zE6uZW_navTitle",
35246
+ "todoText": "zE6uZW_todoText",
35247
+ "readerItemBadge": "zE6uZW_readerItemBadge",
35248
+ "assetGrid": "zE6uZW_assetGrid",
35249
+ "coverPreview": "zE6uZW_coverPreview",
35250
+ "bookAdd": "zE6uZW_bookAdd",
35251
+ "chapterBeats": "zE6uZW_chapterBeats",
35252
+ "readerMain": "zE6uZW_readerMain",
35253
+ "meta": "zE6uZW_meta",
35254
+ "readerLoading": "zE6uZW_readerLoading",
35255
+ "view": "zE6uZW_view",
35256
+ "createBookTitle": "zE6uZW_createBookTitle",
35251
35257
  "readerTitle": "zE6uZW_readerTitle",
35252
- "diffTagNew": "zE6uZW_diffTagNew",
35253
- "bookshelf": "zE6uZW_bookshelf",
35254
- "entryIcon": "zE6uZW_entryIcon",
35255
- "diffSame": "zE6uZW_diffSame",
35256
- "bookSwitchMeta": "zE6uZW_bookSwitchMeta",
35257
- "todoDanger": "zE6uZW_todoDanger",
35258
- "navActionBtn": "zE6uZW_navActionBtn",
35258
+ "dashFact": "zE6uZW_dashFact",
35259
+ "wsPreview": "zE6uZW_wsPreview",
35260
+ "bookshelfList": "zE6uZW_bookshelfList",
35261
+ "readerItemActive": "zE6uZW_readerItemActive",
35262
+ "chapterFocus": "zE6uZW_chapterFocus",
35263
+ "fieldLabel": "zE6uZW_fieldLabel",
35264
+ "bookCardActions": "zE6uZW_bookCardActions",
35265
+ "shelfStat": "zE6uZW_shelfStat",
35266
+ "buttonDanger": "zE6uZW_buttonDanger",
35259
35267
  "badgeWritten": "zE6uZW_badgeWritten",
35268
+ "assistantStatusBusy": "zE6uZW_assistantStatusBusy",
35260
35269
  "toolStepIcon": "zE6uZW_toolStepIcon",
35261
- "bookChipName": "zE6uZW_bookChipName",
35262
- "legendNew": "zE6uZW_legendNew",
35263
- "dashHeroArrow": "zE6uZW_dashHeroArrow",
35264
- "dashJourney": "zE6uZW_dashJourney",
35265
- "helpTipText": "zE6uZW_helpTipText",
35266
- "progressLineLive": "zE6uZW_progressLineLive",
35267
- "workflowRow": "zE6uZW_workflowRow",
35268
35270
  "dashFacts": "zE6uZW_dashFacts",
35269
- "volumeGroup": "zE6uZW_volumeGroup",
35270
- "diffList": "zE6uZW_diffList",
35271
- "bookshelfLabel": "zE6uZW_bookshelfLabel",
35272
- "diffDel": "zE6uZW_diffDel",
35273
- "dashHeroActionTitle": "zE6uZW_dashHeroActionTitle",
35274
- "readerItemActive": "zE6uZW_readerItemActive",
35275
- "tlSegCurrent": "zE6uZW_tlSegCurrent",
35276
- "assistantStatus": "zE6uZW_assistantStatus",
35277
- "bigProgressBarFill": "zE6uZW_bigProgressBarFill",
35278
- "chatScroll": "zE6uZW_chatScroll",
35279
- "dashGrid": "zE6uZW_dashGrid",
35280
- "panel": "zE6uZW_panel",
35281
- "statCardDLabel": "zE6uZW_statCardDLabel",
35282
- "coverPreview": "zE6uZW_coverPreview",
35271
+ "outlineReadonly": "zE6uZW_outlineReadonly",
35272
+ "assetStatDetail": "zE6uZW_assetStatDetail",
35273
+ "readerItemNo": "zE6uZW_readerItemNo",
35274
+ "readerGroupArrow": "zE6uZW_readerGroupArrow",
35275
+ "entry": "zE6uZW_entry",
35276
+ "navTab": "zE6uZW_navTab",
35277
+ "bookCreateCard": "zE6uZW_bookCreateCard",
35278
+ "chapterNum": "zE6uZW_chapterNum",
35279
+ "reviewBox": "zE6uZW_reviewBox",
35280
+ "bookCardName": "zE6uZW_bookCardName",
35281
+ "bookSwitchName": "zE6uZW_bookSwitchName",
35282
+ "chapterList": "zE6uZW_chapterList",
35283
+ "toolStepError": "zE6uZW_toolStepError",
35284
+ "dashJourney": "zE6uZW_dashJourney",
35285
+ "busyRow": "zE6uZW_busyRow",
35286
+ "navTabBadge": "zE6uZW_navTabBadge",
35287
+ "tlBar": "zE6uZW_tlBar",
35283
35288
  "tlSegDone": "zE6uZW_tlSegDone",
35284
- "ideaCard": "zE6uZW_ideaCard",
35285
- "readerHeader": "zE6uZW_readerHeader",
35286
- "ideaCandidate": "zE6uZW_ideaCandidate",
35287
- "chapterTitle": "zE6uZW_chapterTitle",
35288
- "workflowDot": "zE6uZW_workflowDot",
35289
- "createBookCard": "zE6uZW_createBookCard",
35290
- "toolSteps": "zE6uZW_toolSteps",
35291
- "bookChipRemove": "zE6uZW_bookChipRemove",
35289
+ "todoDanger": "zE6uZW_todoDanger",
35290
+ "navActions": "zE6uZW_navActions",
35291
+ "toolStepDetail": "zE6uZW_toolStepDetail",
35292
+ "bookCardCoverTitle": "zE6uZW_bookCardCoverTitle",
35293
+ "panelNav": "zE6uZW_panelNav",
35294
+ "onlyChanges": "zE6uZW_onlyChanges",
35295
+ "card": "zE6uZW_card",
35296
+ "dashJourneyFill": "zE6uZW_dashJourneyFill",
35297
+ "navAboutUpdate": "zE6uZW_navAboutUpdate",
35298
+ "wsSelectedText": "zE6uZW_wsSelectedText",
35292
35299
  "wsPreviewText": "zE6uZW_wsPreviewText",
35293
- "chapterNum": "zE6uZW_chapterNum",
35300
+ "progressLineDone": "zE6uZW_progressLineDone",
35301
+ "iconButton": "zE6uZW_iconButton",
35302
+ "readerFoot": "zE6uZW_readerFoot",
35303
+ "importModalActions": "zE6uZW_importModalActions",
35304
+ "badgeRejected": "zE6uZW_badgeRejected",
35305
+ "chatRole": "zE6uZW_chatRole",
35306
+ "navAbout": "zE6uZW_navAbout",
35307
+ "navTabLabel": "zE6uZW_navTabLabel",
35308
+ "dropzoneActive": "zE6uZW_dropzoneActive",
35309
+ "shelfEmptyTitle": "zE6uZW_shelfEmptyTitle",
35310
+ "importModalOverlay": "zE6uZW_importModalOverlay",
35311
+ "spaceBetween": "zE6uZW_spaceBetween",
35312
+ "volumeGroup": "zE6uZW_volumeGroup",
35313
+ "bookChipActive": "zE6uZW_bookChipActive",
35314
+ "workflowDotActive": "zE6uZW_workflowDotActive",
35315
+ "importError": "zE6uZW_importError",
35316
+ "ideaCard": "zE6uZW_ideaCard",
35317
+ "statCardDDown": "zE6uZW_statCardDDown",
35318
+ "shelfToolbar": "zE6uZW_shelfToolbar",
35319
+ "bookChip": "zE6uZW_bookChip",
35320
+ "navTabBadgeDone": "zE6uZW_navTabBadgeDone",
35321
+ "readerArticle": "zE6uZW_readerArticle",
35322
+ "importModal": "zE6uZW_importModal",
35323
+ "badgeDone": "zE6uZW_badgeDone",
35324
+ "dashHeroActionTitle": "zE6uZW_dashHeroActionTitle",
35325
+ "diffSame": "zE6uZW_diffSame",
35326
+ "bookCardProgressFill": "zE6uZW_bookCardProgressFill",
35327
+ "bookCardBody": "zE6uZW_bookCardBody",
35294
35328
  "panelNavCollapsed": "zE6uZW_panelNavCollapsed",
35295
- "navAboutRow": "zE6uZW_navAboutRow",
35296
- "bookCreateOutline": "zE6uZW_bookCreateOutline",
35297
- "tabBar": "zE6uZW_tabBar",
35298
- "navTabBadge": "zE6uZW_navTabBadge",
35329
+ "input": "zE6uZW_input",
35330
+ "workflowDot": "zE6uZW_workflowDot",
35331
+ "workflowBody": "zE6uZW_workflowBody",
35332
+ "navBadgePulse": "zE6uZW_navBadgePulse",
35333
+ "importResult": "zE6uZW_importResult",
35334
+ "bookAddCard": "zE6uZW_bookAddCard",
35335
+ "dashGrid": "zE6uZW_dashGrid",
35299
35336
  "assistantResize": "zE6uZW_assistantResize",
35300
- "navTitleName": "zE6uZW_navTitleName",
35301
- "chapterActions": "zE6uZW_chapterActions",
35302
- "statCardDIconRed": "zE6uZW_statCardDIconRed",
35303
- "wsPreview": "zE6uZW_wsPreview",
35304
- "createBookTop": "zE6uZW_createBookTop",
35305
- "meta": "zE6uZW_meta",
35306
- "workflowLabel": "zE6uZW_workflowLabel",
35307
- "createBookTitle": "zE6uZW_createBookTitle",
35308
- "outlineReadonly": "zE6uZW_outlineReadonly",
35309
- "panelBody": "zE6uZW_panelBody",
35310
- "dashJourneyFill": "zE6uZW_dashJourneyFill",
35337
+ "diffText": "zE6uZW_diffText",
35338
+ "bookCard": "zE6uZW_bookCard",
35339
+ "progressLineLive": "zE6uZW_progressLineLive",
35340
+ "readerError": "zE6uZW_readerError",
35341
+ "diffColumn": "zE6uZW_diffColumn",
35342
+ "shelfSearch": "zE6uZW_shelfSearch",
35343
+ "chatBubbleAssistant": "zE6uZW_chatBubbleAssistant",
35344
+ "readerSidebar": "zE6uZW_readerSidebar",
35345
+ "statCardDValue": "zE6uZW_statCardDValue",
35346
+ "navTabBadgeWarn": "zE6uZW_navTabBadgeWarn",
35347
+ "progress": "zE6uZW_progress",
35348
+ "switchOn": "zE6uZW_switchOn",
35349
+ "chapterPreview": "zE6uZW_chapterPreview",
35350
+ "cardTitle": "zE6uZW_cardTitle",
35351
+ "badgeError": "zE6uZW_badgeError",
35352
+ "tabBar": "zE6uZW_tabBar",
35353
+ "dashHero": "zE6uZW_dashHero",
35354
+ "dropzoneIcon": "zE6uZW_dropzoneIcon",
35355
+ "importModalHead": "zE6uZW_importModalHead",
35356
+ "wsSelected": "zE6uZW_wsSelected",
35357
+ "bookCardTitleRow": "zE6uZW_bookCardTitleRow",
35311
35358
  "bookCardProgressBar": "zE6uZW_bookCardProgressBar",
35312
- "dropzoneActive": "zE6uZW_dropzoneActive",
35359
+ "coverPlaceholder": "zE6uZW_coverPlaceholder",
35360
+ "dashHeroAction": "zE6uZW_dashHeroAction",
35361
+ "chapterFocusPulse": "zE6uZW_chapterFocusPulse",
35362
+ "wsEditor": "zE6uZW_wsEditor",
35363
+ "diffList": "zE6uZW_diffList",
35364
+ "workflowLabel": "zE6uZW_workflowLabel",
35365
+ "workflowHint": "zE6uZW_workflowHint",
35313
35366
  "field": "zE6uZW_field",
35314
- "bigProgressBar": "zE6uZW_bigProgressBar",
35367
+ "panelContent": "zE6uZW_panelContent",
35368
+ "navGroupLabel": "zE6uZW_navGroupLabel",
35369
+ "shelfHeader": "zE6uZW_shelfHeader",
35370
+ "readerPara": "zE6uZW_readerPara",
35371
+ "assistantStatus": "zE6uZW_assistantStatus",
35372
+ "bookSwitchCover": "zE6uZW_bookSwitchCover",
35373
+ "bookChipRemove": "zE6uZW_bookChipRemove",
35374
+ "shelfEmpty": "zE6uZW_shelfEmpty",
35375
+ "chapter": "zE6uZW_chapter",
35376
+ "bookSwitchMeta": "zE6uZW_bookSwitchMeta",
35377
+ "dashStageDone": "zE6uZW_dashStageDone",
35315
35378
  "legendOld": "zE6uZW_legendOld",
35316
- "progressLineDone": "zE6uZW_progressLineDone",
35317
- "diffNew": "zE6uZW_diffNew",
35318
- "bookChip": "zE6uZW_bookChip",
35319
- "shelfView": "zE6uZW_shelfView",
35320
- "readerChapterTitle": "zE6uZW_readerChapterTitle",
35321
- "readerSegBtn": "zE6uZW_readerSegBtn",
35322
- "settingsCard": "zE6uZW_settingsCard",
35323
- "statCardDDetail": "zE6uZW_statCardDDetail",
35324
- "fieldLabel": "zE6uZW_fieldLabel",
35325
- "readerText": "zE6uZW_readerText",
35326
- "todoWarning": "zE6uZW_todoWarning",
35327
35379
  "progressBar": "zE6uZW_progressBar",
35328
- "navTabIcon": "zE6uZW_navTabIcon",
35329
- "volumeGroupToggle": "zE6uZW_volumeGroupToggle",
35330
- "chapterMain": "zE6uZW_chapterMain",
35331
- "navTab": "zE6uZW_navTab",
35332
- "coverPlaceholder": "zE6uZW_coverPlaceholder",
35333
- "assetStatLabel": "zE6uZW_assetStatLabel",
35334
- "shelfToolbar": "zE6uZW_shelfToolbar",
35380
+ "bookCardCoverFallback": "zE6uZW_bookCardCoverFallback",
35381
+ "diffTagNew": "zE6uZW_diffTagNew",
35382
+ "bookSwitch": "zE6uZW_bookSwitch",
35335
35383
  "readerGroup": "zE6uZW_readerGroup",
35336
- "wsPageHeader": "zE6uZW_wsPageHeader",
35337
- "dashStageDot": "zE6uZW_dashStageDot",
35338
- "todoInfo": "zE6uZW_todoInfo",
35339
- "createBookIcon": "zE6uZW_createBookIcon",
35340
- "assistantFloatBody": "zE6uZW_assistantFloatBody",
35341
- "readerGroupArrow": "zE6uZW_readerGroupArrow",
35342
- "dashJourneyBar": "zE6uZW_dashJourneyBar",
35343
- "view": "zE6uZW_view",
35344
- "statCardDDown": "zE6uZW_statCardDDown",
35345
- "bookCreateCard": "zE6uZW_bookCreateCard",
35346
- "wsEditor": "zE6uZW_wsEditor",
35347
- "readerBody": "zE6uZW_readerBody",
35348
- "assistantFloat": "zE6uZW_assistantFloat",
35349
- "panelContent": "zE6uZW_panelContent",
35350
- "shelfStats": "zE6uZW_shelfStats",
35384
+ "bookCardActive": "zE6uZW_bookCardActive",
35351
35385
  "volumeGroupHeader": "zE6uZW_volumeGroupHeader",
35352
- "dropzone": "zE6uZW_dropzone",
35353
- "progress": "zE6uZW_progress",
35354
- "navGroupSep": "zE6uZW_navGroupSep",
35355
- "badgeDone": "zE6uZW_badgeDone",
35356
- "todoItem": "zE6uZW_todoItem",
35357
- "entry": "zE6uZW_entry",
35358
- "bookAddCard": "zE6uZW_bookAddCard",
35359
- "tlBar": "zE6uZW_tlBar",
35360
- "workflowDotDone": "zE6uZW_workflowDotDone",
35361
- "navTabBadgeLive": "zE6uZW_navTabBadgeLive",
35362
- "card": "zE6uZW_card",
35363
- "fadeIn": "zE6uZW_fadeIn",
35364
- "readerItemBadge": "zE6uZW_readerItemBadge",
35386
+ "toolStepName": "zE6uZW_toolStepName",
35387
+ "tab": "zE6uZW_tab",
35388
+ "shelfView": "zE6uZW_shelfView",
35389
+ "genreDesc": "zE6uZW_genreDesc",
35390
+ "readerText": "zE6uZW_readerText",
35391
+ "helpTip": "zE6uZW_helpTip",
35392
+ "switchKnob": "zE6uZW_switchKnob",
35365
35393
  "wsPage": "zE6uZW_wsPage",
35366
- "bookCardActions": "zE6uZW_bookCardActions",
35367
- "bookshelfList": "zE6uZW_bookshelfList",
35368
- "toolStepDetail": "zE6uZW_toolStepDetail",
35369
- "buttonPrimary": "zE6uZW_buttonPrimary",
35370
- "readerMain": "zE6uZW_readerMain",
35371
- "navTabLabel": "zE6uZW_navTabLabel",
35394
+ "diffTagOld": "zE6uZW_diffTagOld",
35395
+ "statRowD": "zE6uZW_statRowD",
35396
+ "navActionBtn": "zE6uZW_navActionBtn",
35372
35397
  "progressLine": "zE6uZW_progressLine",
35373
- "busyRow": "zE6uZW_busyRow",
35374
- "readerFoot": "zE6uZW_readerFoot",
35375
- "bookAdd": "zE6uZW_bookAdd",
35376
- "readerArticle": "zE6uZW_readerArticle",
35377
- "chapterPreview": "zE6uZW_chapterPreview",
35378
- "importModalHead": "zE6uZW_importModalHead",
35398
+ "navTitleBook": "zE6uZW_navTitleBook",
35399
+ "navGroup": "zE6uZW_navGroup",
35400
+ "todoWarning": "zE6uZW_todoWarning",
35401
+ "readerChapterTitle": "zE6uZW_readerChapterTitle",
35402
+ "importPreviewList": "zE6uZW_importPreviewList",
35403
+ "row": "zE6uZW_row",
35404
+ "bookCardCover": "zE6uZW_bookCardCover",
35405
+ "assetStatValue": "zE6uZW_assetStatValue",
35406
+ "bookChipName": "zE6uZW_bookChipName",
35407
+ "toolStepStatus": "zE6uZW_toolStepStatus",
35408
+ "diffDel": "zE6uZW_diffDel",
35409
+ "workflowRow": "zE6uZW_workflowRow",
35410
+ "buttonSmall": "zE6uZW_buttonSmall",
35411
+ "diffAdd": "zE6uZW_diffAdd",
35412
+ "assetStat": "zE6uZW_assetStat",
35413
+ "todoItem": "zE6uZW_todoItem",
35379
35414
  "bookCardMetaRow": "zE6uZW_bookCardMetaRow",
35380
- "navGroupLabel": "zE6uZW_navGroupLabel",
35381
- "importModalBody": "zE6uZW_importModalBody",
35382
- "switch": "zE6uZW_switch",
35383
- "navTitleLogo": "zE6uZW_navTitleLogo",
35415
+ "importField": "zE6uZW_importField",
35416
+ "settingsCard": "zE6uZW_settingsCard",
35417
+ "entryIcon": "zE6uZW_entryIcon",
35418
+ "wsAppliedBanner": "zE6uZW_wsAppliedBanner",
35419
+ "bookshelfLabel": "zE6uZW_bookshelfLabel",
35420
+ "chatScroll": "zE6uZW_chatScroll",
35421
+ "dashStage": "zE6uZW_dashStage",
35422
+ "shelfFilters": "zE6uZW_shelfFilters",
35423
+ "bookCreateForm": "zE6uZW_bookCreateForm",
35424
+ "progressLineError": "zE6uZW_progressLineError",
35425
+ "dashHeroActionBody": "zE6uZW_dashHeroActionBody",
35426
+ "chapterActions": "zE6uZW_chapterActions",
35427
+ "navTabBadgeDanger": "zE6uZW_navTabBadgeDanger",
35428
+ "dashHeroEyebrow": "zE6uZW_dashHeroEyebrow",
35429
+ "shelfTitleRow": "zE6uZW_shelfTitleRow",
35430
+ "pulse": "zE6uZW_pulse",
35431
+ "bigProgressBar": "zE6uZW_bigProgressBar",
35432
+ "progressBarFill": "zE6uZW_progressBarFill",
35433
+ "readerSeg": "zE6uZW_readerSeg",
35434
+ "diffSameBody": "zE6uZW_diffSameBody",
35435
+ "statCardD": "zE6uZW_statCardD",
35436
+ "bookshelf": "zE6uZW_bookshelf",
35384
35437
  "diffOld": "zE6uZW_diffOld",
35385
- "navTitle": "zE6uZW_navTitle",
35386
- "shelfEmptyTitle": "zE6uZW_shelfEmptyTitle",
35387
- "bookChipMeta": "zE6uZW_bookChipMeta",
35388
- "badge": "zE6uZW_badge",
35389
- "bookSwitch": "zE6uZW_bookSwitch",
35390
- "assistantStatusBusy": "zE6uZW_assistantStatusBusy",
35438
+ "bookSwitchArrow": "zE6uZW_bookSwitchArrow",
35439
+ "readerSegActive": "zE6uZW_readerSegActive",
35440
+ "readerHeader": "zE6uZW_readerHeader",
35441
+ "todoInfo": "zE6uZW_todoInfo",
35442
+ "button": "zE6uZW_button",
35391
35443
  "liveText": "zE6uZW_liveText",
35392
- "workflowBody": "zE6uZW_workflowBody",
35393
- "bookCardProgressFill": "zE6uZW_bookCardProgressFill",
35394
- "switchOn": "zE6uZW_switchOn",
35395
35444
  "panelTitle": "zE6uZW_panelTitle",
35396
- "shelfTitleRow": "zE6uZW_shelfTitleRow",
35397
- "assetStatDetail": "zE6uZW_assetStatDetail",
35398
- "readerPara": "zE6uZW_readerPara",
35399
- "badgeRejected": "zE6uZW_badgeRejected",
35400
- "importError": "zE6uZW_importError",
35401
- "shelfStatActive": "zE6uZW_shelfStatActive",
35402
- "statRowD": "zE6uZW_statRowD",
35403
- "bookAddIcon": "zE6uZW_bookAddIcon",
35404
- "dashHeroAction": "zE6uZW_dashHeroAction",
35405
- "chatRole": "zE6uZW_chatRole",
35406
- "bookCardBody": "zE6uZW_bookCardBody",
35407
- "shelfSearch": "zE6uZW_shelfSearch",
35408
- "workflowHint": "zE6uZW_workflowHint",
35409
- "readerGroupCount": "zE6uZW_readerGroupCount",
35410
- "diffTagOld": "zE6uZW_diffTagOld",
35411
- "dashFact": "zE6uZW_dashFact",
35412
- "entryLabel": "zE6uZW_entryLabel",
35413
- "readerGroupTitle": "zE6uZW_readerGroupTitle",
35414
- "workflowDotActive": "zE6uZW_workflowDotActive",
35415
- "bookChipActive": "zE6uZW_bookChipActive",
35416
- "helpTip": "zE6uZW_helpTip",
35417
- "importHint": "zE6uZW_importHint",
35418
- "chapterFocusPulse": "zE6uZW_chapterFocusPulse",
35419
- "badgePending": "zE6uZW_badgePending",
35420
- "statCardD": "zE6uZW_statCardD",
35421
- "diffText": "zE6uZW_diffText",
35445
+ "navTabBadgeLive": "zE6uZW_navTabBadgeLive",
35446
+ "shelfEmptyIcon": "zE6uZW_shelfEmptyIcon",
35447
+ "shelfHero": "zE6uZW_shelfHero",
35448
+ "navTabIcon": "zE6uZW_navTabIcon",
35449
+ "fadeIn": "zE6uZW_fadeIn",
35422
35450
  "tlSegTodo": "zE6uZW_tlSegTodo",
35423
- "textarea": "zE6uZW_textarea",
35424
- "chapterBeats": "zE6uZW_chapterBeats",
35425
- "dashStage": "zE6uZW_dashStage",
35426
- "dashHeroActionBody": "zE6uZW_dashHeroActionBody",
35427
- "dashStageCurrent": "zE6uZW_dashStageCurrent",
35428
- "assetStat": "zE6uZW_assetStat",
35429
- "shelfGrid": "zE6uZW_shelfGrid",
35430
- "importPreviewList": "zE6uZW_importPreviewList",
35431
- "button": "zE6uZW_button",
35432
- "navTabBadgeWarn": "zE6uZW_navTabBadgeWarn",
35433
- "navBadgePulse": "zE6uZW_navBadgePulse",
35434
- "wsColumn": "zE6uZW_wsColumn",
35435
- "toolStep": "zE6uZW_toolStep",
35436
- "importModalOverlay": "zE6uZW_importModalOverlay",
35437
- "navActions": "zE6uZW_navActions",
35438
- "dashHero": "zE6uZW_dashHero",
35439
- "bookSwitchCover": "zE6uZW_bookSwitchCover",
35440
- "diffSameBody": "zE6uZW_diffSameBody",
35451
+ "tlSegTrack": "zE6uZW_tlSegTrack",
35452
+ "dashHeroBook": "zE6uZW_dashHeroBook",
35453
+ "readerItemTitle": "zE6uZW_readerItemTitle",
35454
+ "shelfFilter": "zE6uZW_shelfFilter",
35455
+ "navAboutRow": "zE6uZW_navAboutRow",
35441
35456
  "fileList": "zE6uZW_fileList",
35442
- "ideaToggle": "zE6uZW_ideaToggle",
35457
+ "volumeGroupToggle": "zE6uZW_volumeGroupToggle",
35458
+ "dashStageCurrent": "zE6uZW_dashStageCurrent",
35459
+ "createBookCard": "zE6uZW_createBookCard",
35443
35460
  "readerView": "zE6uZW_readerView",
35444
- "readerItemNo": "zE6uZW_readerItemNo",
35445
- "iconButton": "zE6uZW_iconButton",
35446
- "navAbout": "zE6uZW_navAbout",
35447
- "row": "zE6uZW_row",
35448
- "assistantFloatHeader": "zE6uZW_assistantFloatHeader",
35449
- "importFileInfo": "zE6uZW_importFileInfo",
35450
- "diffLegend": "zE6uZW_diffLegend",
35451
- "shelfHero": "zE6uZW_shelfHero",
35452
- "diffAdd": "zE6uZW_diffAdd",
35453
- "bookCardCoverTitle": "zE6uZW_bookCardCoverTitle",
35454
- "genreDesc": "zE6uZW_genreDesc",
35455
- "chatBubbleAssistant": "zE6uZW_chatBubbleAssistant",
35456
- "wsAppliedBanner": "zE6uZW_wsAppliedBanner",
35457
- "assetGrid": "zE6uZW_assetGrid",
35458
- "bookCardTitleRow": "zE6uZW_bookCardTitleRow",
35459
- "switchKnob": "zE6uZW_switchKnob",
35460
- "progressBarFill": "zE6uZW_progressBarFill",
35461
- "chapter": "zE6uZW_chapter",
35462
- "navTabBadgeDanger": "zE6uZW_navTabBadgeDanger",
35461
+ "buttonPrimary": "zE6uZW_buttonPrimary",
35463
35462
  "tlSegFill": "zE6uZW_tlSegFill",
35464
- "shelfStat": "zE6uZW_shelfStat",
35465
- "toolStepName": "zE6uZW_toolStepName",
35466
- "shelfFilterActive": "zE6uZW_shelfFilterActive",
35467
- "pulse": "zE6uZW_pulse",
35468
- "shelfEmpty": "zE6uZW_shelfEmpty",
35469
- "toolStepError": "zE6uZW_toolStepError",
35470
- "bookCardCover": "zE6uZW_bookCardCover",
35471
- "readerLoading": "zE6uZW_readerLoading",
35472
- "reviewBox": "zE6uZW_reviewBox",
35473
- "dashJourneyStages": "zE6uZW_dashJourneyStages",
35463
+ "importPreview": "zE6uZW_importPreview",
35464
+ "dashHeroArrow": "zE6uZW_dashHeroArrow",
35465
+ "textarea": "zE6uZW_textarea",
35466
+ "diffNew": "zE6uZW_diffNew",
35467
+ "bookCardBlurb": "zE6uZW_bookCardBlurb",
35468
+ "toolStepActive": "zE6uZW_toolStepActive",
35469
+ "chatBubbleUser": "zE6uZW_chatBubbleUser",
35470
+ "switch": "zE6uZW_switch",
35471
+ "chapterMain": "zE6uZW_chapterMain",
35472
+ "readerChapterMeta": "zE6uZW_readerChapterMeta",
35473
+ "shelfFilterCount": "zE6uZW_shelfFilterCount",
35474
+ "navTitleName": "zE6uZW_navTitleName",
35475
+ "assistantFloatBody": "zE6uZW_assistantFloatBody",
35476
+ "navGroupSep": "zE6uZW_navGroupSep",
35477
+ "ideaToggle": "zE6uZW_ideaToggle",
35478
+ "entryLabel": "zE6uZW_entryLabel",
35479
+ "statCardDDetail": "zE6uZW_statCardDDetail",
35480
+ "toolLive": "zE6uZW_toolLive",
35481
+ "wsColumns": "zE6uZW_wsColumns",
35474
35482
  "tlSeg": "zE6uZW_tlSeg",
35475
- "badgeError": "zE6uZW_badgeError",
35476
- "statCardDValue": "zE6uZW_statCardDValue",
35483
+ "importFileInfo": "zE6uZW_importFileInfo",
35484
+ "shelfStatActive": "zE6uZW_shelfStatActive",
35485
+ "badgeGenerating": "zE6uZW_badgeGenerating",
35486
+ "bigProgressBarFill": "zE6uZW_bigProgressBarFill",
35487
+ "bookCreateOutline": "zE6uZW_bookCreateOutline",
35488
+ "shelfStats": "zE6uZW_shelfStats",
35477
35489
  "workflowList": "zE6uZW_workflowList",
35478
- "dashHeroBook": "zE6uZW_dashHeroBook",
35479
- "wsSelectedText": "zE6uZW_wsSelectedText",
35490
+ "legendNew": "zE6uZW_legendNew",
35491
+ "readerBody": "zE6uZW_readerBody",
35492
+ "readerGroupTitle": "zE6uZW_readerGroupTitle",
35493
+ "dashJourneyStages": "zE6uZW_dashJourneyStages",
35494
+ "panel": "zE6uZW_panel",
35495
+ "wsColumn": "zE6uZW_wsColumn",
35496
+ "tlSegLabel": "zE6uZW_tlSegLabel",
35497
+ "shelfGrid": "zE6uZW_shelfGrid",
35498
+ "navSpacer": "zE6uZW_navSpacer",
35499
+ "chapterTitle": "zE6uZW_chapterTitle",
35500
+ "ideaCandidate": "zE6uZW_ideaCandidate",
35501
+ "readerGroupCount": "zE6uZW_readerGroupCount",
35502
+ "readerSegBtn": "zE6uZW_readerSegBtn",
35480
35503
  "importModalTabs": "zE6uZW_importModalTabs",
35481
- "shelfFilter": "zE6uZW_shelfFilter",
35482
- "bookCardActive": "zE6uZW_bookCardActive",
35483
- "importModalActions": "zE6uZW_importModalActions",
35484
- "cardTitle": "zE6uZW_cardTitle",
35485
- "tlSegTrack": "zE6uZW_tlSegTrack",
35486
- "readerSeg": "zE6uZW_readerSeg",
35487
- "todoText": "zE6uZW_todoText",
35488
- "shelfHeader": "zE6uZW_shelfHeader",
35489
- "onlyChanges": "zE6uZW_onlyChanges",
35490
- "tab": "zE6uZW_tab",
35491
- "readerItemTitle": "zE6uZW_readerItemTitle",
35492
- "importResult": "zE6uZW_importResult",
35493
- "chapterList": "zE6uZW_chapterList",
35494
- "readerChapterMeta": "zE6uZW_readerChapterMeta",
35495
- "shelfEmptyIcon": "zE6uZW_shelfEmptyIcon",
35496
- "shelfFilters": "zE6uZW_shelfFilters",
35497
- "readerError": "zE6uZW_readerError",
35498
- "dashHeroEyebrow": "zE6uZW_dashHeroEyebrow",
35504
+ "importModalBody": "zE6uZW_importModalBody",
35505
+ "statCardDLabel": "zE6uZW_statCardDLabel",
35506
+ "bookChipMeta": "zE6uZW_bookChipMeta",
35507
+ "assetStatLabel": "zE6uZW_assetStatLabel",
35508
+ "dashJourneyBar": "zE6uZW_dashJourneyBar",
35499
35509
  "readerItem": "zE6uZW_readerItem",
35500
- "dashStageDone": "zE6uZW_dashStageDone",
35501
- "importModal": "zE6uZW_importModal",
35502
- "bookCardBlurb": "zE6uZW_bookCardBlurb",
35503
- "chatBubbleUser": "zE6uZW_chatBubbleUser",
35504
- "bookSwitchName": "zE6uZW_bookSwitchName",
35505
- "diffColumn": "zE6uZW_diffColumn",
35506
- "readerSegActive": "zE6uZW_readerSegActive",
35507
- "readerSidebar": "zE6uZW_readerSidebar",
35508
- "input": "zE6uZW_input",
35510
+ "toolSteps": "zE6uZW_toolSteps",
35511
+ "dashHeroSparkle": "zE6uZW_dashHeroSparkle",
35512
+ "assistantFloatHeader": "zE6uZW_assistantFloatHeader",
35513
+ "diffLegend": "zE6uZW_diffLegend",
35514
+ "diffChange": "zE6uZW_diffChange",
35515
+ "createBookView": "zE6uZW_createBookView",
35516
+ "badge": "zE6uZW_badge",
35517
+ "shelfFilterActive": "zE6uZW_shelfFilterActive",
35518
+ "createBookTop": "zE6uZW_createBookTop",
35519
+ "panelBody": "zE6uZW_panelBody",
35520
+ "tlSegCurrent": "zE6uZW_tlSegCurrent",
35521
+ "dashStageDot": "zE6uZW_dashStageDot",
35509
35522
  "statCardDIcon": "zE6uZW_statCardDIcon",
35510
- "bookCreateForm": "zE6uZW_bookCreateForm",
35511
- "toolStepActive": "zE6uZW_toolStepActive",
35512
- "dashHeroTitle": "zE6uZW_dashHeroTitle",
35513
- "navSpacer": "zE6uZW_navSpacer",
35514
- "tlSegLabel": "zE6uZW_tlSegLabel",
35515
- "assetStatValue": "zE6uZW_assetStatValue",
35516
- "chapterFocus": "zE6uZW_chapterFocus",
35517
- "importPreview": "zE6uZW_importPreview",
35518
- "bookCardName": "zE6uZW_bookCardName",
35519
- "panelNav": "zE6uZW_panelNav",
35520
- "navAboutUpdate": "zE6uZW_navAboutUpdate",
35521
- "bookCardCoverFallback": "zE6uZW_bookCardCoverFallback",
35522
- "dropzoneIcon": "zE6uZW_dropzoneIcon",
35523
- "bookSwitchArrow": "zE6uZW_bookSwitchArrow",
35524
- "toolStepStatus": "zE6uZW_toolStepStatus",
35525
- "shelfFilterCount": "zE6uZW_shelfFilterCount",
35526
- "importField": "zE6uZW_importField",
35527
- "navTabBadgeDone": "zE6uZW_navTabBadgeDone",
35528
- "badgeGenerating": "zE6uZW_badgeGenerating",
35529
- "navTitleBook": "zE6uZW_navTitleBook",
35530
- "statCardDUnit": "zE6uZW_statCardDUnit",
35531
- "navGroup": "zE6uZW_navGroup"
35523
+ "assistantFloat": "zE6uZW_assistantFloat",
35524
+ "createBookIcon": "zE6uZW_createBookIcon",
35525
+ "dashHeroTitle": "zE6uZW_dashHeroTitle"
35532
35526
  };
35533
35527
  //#endregion
35534
35528
  //#region src/client/panel/AssistantTab.tsx
@@ -37082,6 +37076,15 @@ window.__ModuleLoader__.load({
37082
37076
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
37083
37077
  className: `${panel_module_css_default.bookCard} ${panel_module_css_default.bookAddCard}`,
37084
37078
  onClick: onAddBook,
37079
+ role: "button",
37080
+ tabIndex: 0,
37081
+ "aria-label": "开一本新书",
37082
+ onKeyDown: (e) => {
37083
+ if (e.key === "Enter" || e.key === " ") {
37084
+ e.preventDefault();
37085
+ onAddBook();
37086
+ }
37087
+ },
37085
37088
  children: [
37086
37089
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
37087
37090
  className: panel_module_css_default.bookAddIcon,
@@ -37097,6 +37100,15 @@ window.__ModuleLoader__.load({
37097
37100
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
37098
37101
  className: `${panel_module_css_default.bookCard} ${panel_module_css_default.bookAddCard}`,
37099
37102
  onClick: onImportBook,
37103
+ role: "button",
37104
+ tabIndex: 0,
37105
+ "aria-label": "导入已有小说",
37106
+ onKeyDown: (e) => {
37107
+ if (e.key === "Enter" || e.key === " ") {
37108
+ e.preventDefault();
37109
+ onImportBook();
37110
+ }
37111
+ },
37100
37112
  children: [
37101
37113
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
37102
37114
  className: panel_module_css_default.bookAddIcon,
@@ -37860,15 +37872,15 @@ window.__ModuleLoader__.load({
37860
37872
  className: panel_module_css_default.meta,
37861
37873
  children: [
37862
37874
  "新生成 ",
37863
- run.stats.generated,
37875
+ run.stats?.generated ?? 0,
37864
37876
  " · 修订通过 ",
37865
- run.stats.revised,
37877
+ run.stats?.revised ?? 0,
37866
37878
  " · 豁免 ",
37867
- run.stats.exempted,
37879
+ run.stats?.exempted ?? 0,
37868
37880
  " · 重生成 ",
37869
- run.stats.regenerated,
37881
+ run.stats?.regenerated ?? 0,
37870
37882
  " · 失败 ",
37871
- run.stats.error
37883
+ run.stats?.error ?? 0
37872
37884
  ]
37873
37885
  })]
37874
37886
  }),
@@ -38669,9 +38681,18 @@ window.__ModuleLoader__.load({
38669
38681
  }),
38670
38682
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
38671
38683
  className: `${panel_module_css_default.dropzone} ${dragActive ? panel_module_css_default.dropzoneActive : ""}`,
38684
+ role: "button",
38685
+ tabIndex: 0,
38686
+ "aria-label": "选择或拖入 docx 大纲文件",
38672
38687
  onClick: () => {
38673
38688
  outlineFileRef.current?.click();
38674
38689
  },
38690
+ onKeyDown: (e) => {
38691
+ if (e.key === "Enter" || e.key === " ") {
38692
+ e.preventDefault();
38693
+ outlineFileRef.current?.click();
38694
+ }
38695
+ },
38675
38696
  onDragOver: (e) => {
38676
38697
  e.preventDefault();
38677
38698
  setDragActive(true);
@@ -39030,8 +39051,20 @@ window.__ModuleLoader__.load({
39030
39051
  setResult(null);
39031
39052
  setPreview(null);
39032
39053
  };
39054
+ (0, react.useEffect)(() => {
39055
+ const onKey = (e) => {
39056
+ if (e.key === "Escape") onClose();
39057
+ };
39058
+ window.addEventListener("keydown", onKey);
39059
+ return () => {
39060
+ window.removeEventListener("keydown", onKey);
39061
+ };
39062
+ }, [onClose]);
39033
39063
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
39034
39064
  className: panel_module_css_default.importModalOverlay,
39065
+ role: "dialog",
39066
+ "aria-modal": "true",
39067
+ "aria-label": "导入小说",
39035
39068
  onClick: (e) => {
39036
39069
  if (e.target === e.currentTarget) onClose();
39037
39070
  },
@@ -39958,11 +39991,577 @@ window.__ModuleLoader__.load({
39958
39991
  });
39959
39992
  }
39960
39993
  //#endregion
39994
+ //#region src/shot-language.ts
39995
+ const SHOT_SIZES = [
39996
+ {
39997
+ id: "extreme_wide",
39998
+ zh: "大远景",
39999
+ en: "extreme wide shot",
40000
+ hint: "环境为主,人物很小"
40001
+ },
40002
+ {
40003
+ id: "wide",
40004
+ zh: "远景",
40005
+ en: "wide shot",
40006
+ hint: "人在景中,交代环境"
40007
+ },
40008
+ {
40009
+ id: "full",
40010
+ zh: "全景",
40011
+ en: "full shot",
40012
+ hint: "全身』人物整体"
40013
+ },
40014
+ {
40015
+ id: "medium",
40016
+ zh: "中景",
40017
+ en: "medium shot",
40018
+ hint: "膝部以上,叙事主力"
40019
+ },
40020
+ {
40021
+ id: "medium_close",
40022
+ zh: "中近景",
40023
+ en: "medium close-up",
40024
+ hint: "胸以上,表情+动作"
40025
+ },
40026
+ {
40027
+ id: "close",
40028
+ zh: "近景",
40029
+ en: "close-up",
40030
+ hint: "肩以上,突出表情"
40031
+ },
40032
+ {
40033
+ id: "extreme_close",
40034
+ zh: "特写",
40035
+ en: "extreme close-up",
40036
+ hint: "脸/物细节"
40037
+ },
40038
+ {
40039
+ id: "big_extreme_close",
40040
+ zh: "大特写",
40041
+ en: "big close-up",
40042
+ hint: "局部(眼/手/标志物)"
40043
+ }
40044
+ ];
40045
+ const CAMERA_MOVES = [
40046
+ {
40047
+ id: "static",
40048
+ zh: "固定机位",
40049
+ en: "static camera",
40050
+ hint: "机位不动"
40051
+ },
40052
+ {
40053
+ id: "dolly_in",
40054
+ zh: "推近",
40055
+ en: "dolly in",
40056
+ hint: "镜头向主体逼近"
40057
+ },
40058
+ {
40059
+ id: "dolly_out",
40060
+ zh: "拉远",
40061
+ en: "dolly out",
40062
+ hint: "镜头远离主体"
40063
+ },
40064
+ {
40065
+ id: "pan_left",
40066
+ zh: "左摇",
40067
+ en: "pan left",
40068
+ hint: "机位不动,镜头左转"
40069
+ },
40070
+ {
40071
+ id: "pan_right",
40072
+ zh: "右摇",
40073
+ en: "pan right",
40074
+ hint: "机位不动,镜头右转"
40075
+ },
40076
+ {
40077
+ id: "track_left",
40078
+ zh: "左横移",
40079
+ en: "track left",
40080
+ hint: "机位随主体左移"
40081
+ },
40082
+ {
40083
+ id: "track_right",
40084
+ zh: "右横移",
40085
+ en: "track right",
40086
+ hint: "机位随主体右移"
40087
+ },
40088
+ {
40089
+ id: "follow",
40090
+ zh: "跟随",
40091
+ en: "follow shot",
40092
+ hint: "镜头跟着主体运动"
40093
+ },
40094
+ {
40095
+ id: "pedestal_up",
40096
+ zh: "升镜",
40097
+ en: "pedestal up",
40098
+ hint: "机位抬高"
40099
+ },
40100
+ {
40101
+ id: "pedestal_down",
40102
+ zh: "降镜",
40103
+ en: "pedestal down",
40104
+ hint: "机位降低"
40105
+ },
40106
+ {
40107
+ id: "orbit",
40108
+ zh: "环绕",
40109
+ en: "orbit shot",
40110
+ hint: "镜头绕主体转"
40111
+ },
40112
+ {
40113
+ id: "handheld",
40114
+ zh: "手持晃动",
40115
+ en: "handheld",
40116
+ hint: "真实感/紧张感"
40117
+ },
40118
+ {
40119
+ id: "low_angle",
40120
+ zh: "低机位仰拍",
40121
+ en: "low angle",
40122
+ hint: "突出威严/压迫"
40123
+ },
40124
+ {
40125
+ id: "high_angle",
40126
+ zh: "高机位俯拍",
40127
+ en: "high angle",
40128
+ hint: "突出渺小/全知"
40129
+ },
40130
+ {
40131
+ id: "over_shoulder",
40132
+ zh: "过肩镜头",
40133
+ en: "over-the-shoulder",
40134
+ hint: "对话常用"
40135
+ }
40136
+ ];
40137
+ const COMPOSITIONS = [
40138
+ {
40139
+ id: "rule_of_thirds",
40140
+ zh: "三分法",
40141
+ en: "rule of thirds",
40142
+ hint: "主体偏三分之一处"
40143
+ },
40144
+ {
40145
+ id: "center",
40146
+ zh: "中心对称",
40147
+ en: "centered",
40148
+ hint: "主体居中"
40149
+ },
40150
+ {
40151
+ id: "leading_line",
40152
+ zh: "引导线",
40153
+ en: "leading lines",
40154
+ hint: "视线沿线条引向主体"
40155
+ },
40156
+ {
40157
+ id: "foreground",
40158
+ zh: "前景遮挡",
40159
+ en: "foreground framing",
40160
+ hint: "前景物框住主体"
40161
+ },
40162
+ {
40163
+ id: "low",
40164
+ zh: "低机位",
40165
+ en: "low camera",
40166
+ hint: "低于视线"
40167
+ },
40168
+ {
40169
+ id: "overhead",
40170
+ zh: "俯拍",
40171
+ en: "overhead",
40172
+ hint: "从上方俯视"
40173
+ },
40174
+ {
40175
+ id: "symmetry",
40176
+ zh: "对称构图",
40177
+ en: "symmetrical",
40178
+ hint: "左右镜像"
40179
+ }
40180
+ ];
40181
+ const LIGHTINGS = [
40182
+ {
40183
+ id: "front",
40184
+ zh: "顺光",
40185
+ en: "front light",
40186
+ hint: "正面均匀照明"
40187
+ },
40188
+ {
40189
+ id: "side",
40190
+ zh: "侧光",
40191
+ en: "side light",
40192
+ hint: "明暗对比强"
40193
+ },
40194
+ {
40195
+ id: "back",
40196
+ zh: "逆光",
40197
+ en: "back light",
40198
+ hint: "轮廓光/剪影"
40199
+ },
40200
+ {
40201
+ id: "top",
40202
+ zh: "顶光",
40203
+ en: "top light",
40204
+ hint: "俯照硬朗"
40205
+ },
40206
+ {
40207
+ id: "rembrandt",
40208
+ zh: "伦勃朗光",
40209
+ en: "rembrandt lighting",
40210
+ hint: "侧逆光,经典人像"
40211
+ },
40212
+ {
40213
+ id: "neon",
40214
+ zh: "霓虹光",
40215
+ en: "neon lighting",
40216
+ hint: "赛博/夜景"
40217
+ },
40218
+ {
40219
+ id: "hard",
40220
+ zh: "硬光",
40221
+ en: "hard light",
40222
+ hint: "犀利阴影"
40223
+ },
40224
+ {
40225
+ id: "soft",
40226
+ zh: "柔光",
40227
+ en: "soft light",
40228
+ hint: "柔和过渡"
40229
+ },
40230
+ {
40231
+ id: "mood",
40232
+ zh: "氛围光",
40233
+ en: "mood lighting",
40234
+ hint: "情绪化色温"
40235
+ },
40236
+ {
40237
+ id: "contrast",
40238
+ zh: "高反差",
40239
+ en: "high contrast",
40240
+ hint: "黑白/强明暗"
40241
+ }
40242
+ ];
40243
+ /** 从中文文本归一化到景别(处理旧数据/LLM 口语)。未知回退 medium。 */
40244
+ function normalizeShotSize(text) {
40245
+ if (text === void 0 || text === "") return "medium";
40246
+ const t = text.trim();
40247
+ if (t.includes("大远景")) return "extreme_wide";
40248
+ if (t.includes("远景")) return "wide";
40249
+ if (t.includes("全景")) return "full";
40250
+ if (t.includes("中近景") || t.includes("中景")) return "medium";
40251
+ if (t.includes("近景") || t.includes("胸")) return "close";
40252
+ if (t.includes("大特写")) return "big_extreme_close";
40253
+ if (t.includes("特写")) return "extreme_close";
40254
+ return "medium";
40255
+ }
40256
+ /** 从中文文本归一化到运镜列表。 */
40257
+ function normalizeCameras(text) {
40258
+ if (text === void 0 || text === "") return ["static"];
40259
+ const t = text.trim();
40260
+ const out = [];
40261
+ const push = (id) => {
40262
+ if (!out.includes(id)) out.push(id);
40263
+ };
40264
+ if (t.includes("推近") || t.includes("推进")) push("dolly_in");
40265
+ if (t.includes("拉远") || t.includes("拉出")) push("dolly_out");
40266
+ if (t.includes("左摇")) push("pan_left");
40267
+ if (t.includes("右摇")) push("pan_right");
40268
+ if (t.includes("横移")) push(t.includes("左") ? "track_left" : "track_right");
40269
+ if (t.includes("跟随") || t.includes("跟拍")) push("follow");
40270
+ if (t.includes("升降") || t.includes("升") || t.includes("降")) push("pedestal_up");
40271
+ if (t.includes("环绕")) push("orbit");
40272
+ if (t.includes("手持") || t.includes("晃动")) push("handheld");
40273
+ if (t.includes("低机位") || t.includes("仰拍") || t.includes("仰")) push("low_angle");
40274
+ if (t.includes("高机位") || t.includes("俯拍") || t.includes("俯")) push("high_angle");
40275
+ if (t.includes("过肩")) push("over_shoulder");
40276
+ if (out.length === 0) push("static");
40277
+ return out;
40278
+ }
40279
+ /** 从中文文本归一化到构图(可选)。 */
40280
+ function normalizeComposition(text) {
40281
+ if (text === void 0 || text === "") return void 0;
40282
+ const t = text.trim();
40283
+ if (t.includes("三分")) return "rule_of_thirds";
40284
+ if (t.includes("中心") || t.includes("居中")) return "center";
40285
+ if (t.includes("引导")) return "leading_line";
40286
+ if (t.includes("前景")) return "foreground";
40287
+ if (t.includes("低机位")) return "low";
40288
+ if (t.includes("俯拍") || t.includes("俯视")) return "overhead";
40289
+ if (t.includes("对称")) return "symmetry";
40290
+ }
40291
+ /** 从中文文本归一化到光效列表。 */
40292
+ function normalizeLightings(text) {
40293
+ if (text === void 0 || text === "") return ["soft"];
40294
+ const t = text.trim();
40295
+ const out = [];
40296
+ const push = (id) => {
40297
+ if (!out.includes(id)) out.push(id);
40298
+ };
40299
+ if (t.includes("顺光")) push("front");
40300
+ if (t.includes("侧光") || t.includes("伦勃朗")) push(t.includes("伦勃朗") ? "rembrandt" : "side");
40301
+ if (t.includes("逆光")) push("back");
40302
+ if (t.includes("顶光")) push("top");
40303
+ if (t.includes("霓虹")) push("neon");
40304
+ if (t.includes("硬光")) push("hard");
40305
+ if (t.includes("柔光")) push("soft");
40306
+ if (t.includes("氛围") || t.includes("情绪")) push("mood");
40307
+ if (t.includes("高反差")) push("contrast");
40308
+ if (out.length === 0) push("soft");
40309
+ return out;
40310
+ }
40311
+ /** 取词条中文(ZHs 合并句子)。 */
40312
+ function sizeZh(id) {
40313
+ return SHOT_SIZES.find((e) => e.id === id)?.zh ?? "中景";
40314
+ }
40315
+ function cameraZh(ids) {
40316
+ if (ids === void 0 || ids.length === 0) return "固定机位";
40317
+ return CAMERA_MOVES.filter((e) => ids.includes(e.id)).map((e) => e.zh).join(" + ");
40318
+ }
40319
+ function compoZh(id) {
40320
+ return COMPOSITIONS.find((e) => e.id === id)?.zh ?? "";
40321
+ }
40322
+ function lightZh(ids) {
40323
+ if (ids === void 0 || ids.length === 0) return "柔光";
40324
+ return LIGHTINGS.filter((e) => ids.includes(e.id)).map((e) => e.zh).join(" + ");
40325
+ }
40326
+ //#endregion
40327
+ //#region src/story-beat-language.ts
40328
+ /** 叙事功能词表。 */
40329
+ const STORY_FUNCTIONS = [
40330
+ {
40331
+ id: "exposition",
40332
+ zh: "铺垫",
40333
+ en: "exposition",
40334
+ hint: "介绍背景/人物/悬念"
40335
+ },
40336
+ {
40337
+ id: "conflict",
40338
+ zh: "冲突",
40339
+ en: "conflict",
40340
+ hint: "矛盾显现/加剧"
40341
+ },
40342
+ {
40343
+ id: "turn",
40344
+ zh: "转折",
40345
+ en: "turning point",
40346
+ hint: "剧情反转/方向改变"
40347
+ },
40348
+ {
40349
+ id: "climax",
40350
+ zh: "高潮",
40351
+ en: "climax",
40352
+ hint: "冲突顶峰/揭示"
40353
+ },
40354
+ {
40355
+ id: "resolve",
40356
+ zh: "收束",
40357
+ en: "resolution",
40358
+ hint: "矛盾化解/结果"
40359
+ },
40360
+ {
40361
+ id: "foreshadow",
40362
+ zh: "伏笔",
40363
+ en: "foreshadowing",
40364
+ hint: "埋下后续线索"
40365
+ },
40366
+ {
40367
+ id: "character",
40368
+ zh: "人物塑造",
40369
+ en: "characterization",
40370
+ hint: "展现人物特质/转变"
40371
+ }
40372
+ ];
40373
+ /** 情绪词表(按能量/阶段排序)。 */
40374
+ const EMOTIONS = [
40375
+ {
40376
+ id: "calm",
40377
+ zh: "平静",
40378
+ en: "calm",
40379
+ hint: "无波澜"
40380
+ },
40381
+ {
40382
+ id: "indifferent",
40383
+ zh: "淡然",
40384
+ en: "indifferent",
40385
+ hint: "不在乎"
40386
+ },
40387
+ {
40388
+ id: "expectant",
40389
+ zh: "期待",
40390
+ en: "expectant",
40391
+ hint: "有所期盼"
40392
+ },
40393
+ {
40394
+ id: "curious",
40395
+ zh: "好奇",
40396
+ en: "curious",
40397
+ hint: "想要探究"
40398
+ },
40399
+ {
40400
+ id: "alert",
40401
+ zh: "警觉",
40402
+ en: "alert",
40403
+ hint: "察觉到异样"
40404
+ },
40405
+ {
40406
+ id: "suppressed",
40407
+ zh: "压抑",
40408
+ en: "suppressed",
40409
+ hint: "情绪被压制"
40410
+ },
40411
+ {
40412
+ id: "enduring",
40413
+ zh: "隐忍",
40414
+ en: "enduring",
40415
+ hint: "强忍着"
40416
+ },
40417
+ {
40418
+ id: "worried",
40419
+ zh: "担忧",
40420
+ en: "worried",
40421
+ hint: "担心后果"
40422
+ },
40423
+ {
40424
+ id: "irritable",
40425
+ zh: "焦躁",
40426
+ en: "irritable",
40427
+ hint: "烦躁不耐"
40428
+ },
40429
+ {
40430
+ id: "uneasy",
40431
+ zh: "不安",
40432
+ en: "uneasy",
40433
+ hint: "心里没底"
40434
+ },
40435
+ {
40436
+ id: "terrified",
40437
+ zh: "惊惧",
40438
+ en: "terrified",
40439
+ hint: "极度恐惧"
40440
+ },
40441
+ {
40442
+ id: "angry",
40443
+ zh: "愤怒",
40444
+ en: "angry",
40445
+ hint: "强烈不满"
40446
+ },
40447
+ {
40448
+ id: "collapsing",
40449
+ zh: "崩溃",
40450
+ en: "collapsing",
40451
+ hint: "情绪失控"
40452
+ },
40453
+ {
40454
+ id: "resolute",
40455
+ zh: "决绝",
40456
+ en: "resolute",
40457
+ hint: "下定狠心"
40458
+ },
40459
+ {
40460
+ id: "grieved",
40461
+ zh: "痛心",
40462
+ en: "grieved",
40463
+ hint: "悲伤心痛"
40464
+ },
40465
+ {
40466
+ id: "relieved",
40467
+ zh: "释然",
40468
+ en: "relieved",
40469
+ hint: "放下包袱"
40470
+ },
40471
+ {
40472
+ id: "bittersweet",
40473
+ zh: "悲凉",
40474
+ en: "bittersweet",
40475
+ hint: "苦涩无奈"
40476
+ },
40477
+ {
40478
+ id: "triumphant",
40479
+ zh: "得意",
40480
+ en: "triumphant",
40481
+ hint: "占据上风"
40482
+ },
40483
+ {
40484
+ id: "reborn",
40485
+ zh: "重生",
40486
+ en: "reborn",
40487
+ hint: "脱胎换骨"
40488
+ },
40489
+ {
40490
+ id: "numb",
40491
+ zh: "麻木",
40492
+ en: "numb",
40493
+ hint: "失去感知"
40494
+ }
40495
+ ];
40496
+ /** 从中文归一化叙事功能(未知回退 exposition)。 */
40497
+ function normalizeStoryFunction(text) {
40498
+ if (text === void 0 || text === "") return "exposition";
40499
+ const t = text.trim();
40500
+ if (t.includes("铺垫")) return "exposition";
40501
+ if (t.includes("冲突")) return "conflict";
40502
+ if (t.includes("转折")) return "turn";
40503
+ if (t.includes("高潮")) return "climax";
40504
+ if (t.includes("收束")) return "resolve";
40505
+ if (t.includes("伏笔")) return "foreshadow";
40506
+ if (t.includes("人物塑造")) return "character";
40507
+ return "exposition";
40508
+ }
40509
+ /** 从中文文本归一化情绪词列表(可含→箭头链)。 */
40510
+ function normalizeEmotions(text) {
40511
+ if (text === void 0 || text === "") return ["calm"];
40512
+ const t = text.trim();
40513
+ const out = [];
40514
+ const push = (id) => {
40515
+ if (!out.includes(id)) out.push(id);
40516
+ };
40517
+ if (t.includes("平静")) push("calm");
40518
+ if (t.includes("淡然")) push("indifferent");
40519
+ if (t.includes("期待")) push("expectant");
40520
+ if (t.includes("好奇")) push("curious");
40521
+ if (t.includes("警觉")) push("alert");
40522
+ if (t.includes("压抑")) push("suppressed");
40523
+ if (t.includes("隐忍")) push("enduring");
40524
+ if (t.includes("担忧")) push("worried");
40525
+ if (t.includes("焦躁")) push("irritable");
40526
+ if (t.includes("不安")) push("uneasy");
40527
+ if (t.includes("惊惧")) push("terrified");
40528
+ if (t.includes("愤怒")) push("angry");
40529
+ if (t.includes("崩溃")) push("collapsing");
40530
+ if (t.includes("决绝")) push("resolute");
40531
+ if (t.includes("痛心")) push("grieved");
40532
+ if (t.includes("释然")) push("relieved");
40533
+ if (t.includes("悲凉")) push("bittersweet");
40534
+ if (t.includes("得意")) push("triumphant");
40535
+ if (t.includes("重生")) push("reborn");
40536
+ if (t.includes("麻木")) push("numb");
40537
+ if (out.length === 0) push("calm");
40538
+ return out;
40539
+ }
40540
+ /** 叙事功能中文。 */
40541
+ function functionZh(id) {
40542
+ return STORY_FUNCTIONS.find((e) => e.id === id)?.zh ?? "铺垫";
40543
+ }
40544
+ /** 情绪中文(箭头连接)。 */
40545
+ function emotionZh(ids) {
40546
+ if (ids === void 0 || ids.length === 0) return "平静";
40547
+ return EMOTIONS.filter((e) => ids.includes(e.id)).map((e) => e.zh).join("→");
40548
+ }
40549
+ //#endregion
39961
40550
  //#region src/client/panel/StoryboardTab.tsx
39962
40551
  /**
39963
40552
  * 分镜工作台:① 编剧级剧情骨架 → ② 导演级分镜表(镜头级)→ ③ 视频提示词(后续版本)。
39964
40553
  * 定位:辅助人工——每级可重新生成、可复制,产出可导出。
39965
40554
  */
40555
+ /** 归一化旧分镜数据:把自由文本 shot/camera/light/composition 转成词库枚举。 */
40556
+ function normalizeStoryboardShot(s) {
40557
+ return {
40558
+ ...s,
40559
+ shot: normalizeShotSize(typeof s.shot === "string" ? s.shot : void 0),
40560
+ camera: normalizeCameras(typeof s.camera === "string" ? s.camera : void 0),
40561
+ composition: typeof s.composition === "string" ? normalizeComposition(s.composition) : s.composition,
40562
+ light: normalizeLightings(typeof s.light === "string" ? s.light : void 0)
40563
+ };
40564
+ }
39966
40565
  function StoryboardTab({ api, project, chapters, onProjectChanged, styleId, filterId, mode, onGoStep, onProgress }) {
39967
40566
  const written = (0, react.useMemo)(() => chapters.filter((c) => c.status !== "pending" && c.status !== "generating" && c.status !== "error").sort((a, b) => a.no - b.no), [chapters]);
39968
40567
  /** 漫剧卡 id → 卡名/参考图(定妆绑定展示)。 */
@@ -40006,8 +40605,26 @@ window.__ModuleLoader__.load({
40006
40605
  if (chapterNo === null) return;
40007
40606
  if (suppressRestoreRef.current === true) return;
40008
40607
  const entry = (project?.storyboards ?? []).find((e) => e.chapterNo === chapterNo);
40009
- setSkeleton((prev) => prev ?? entry?.skeleton ?? null);
40010
- setTable((prev) => prev ?? entry?.table ?? null);
40608
+ setSkeleton((prev) => {
40609
+ if (prev !== null) return prev;
40610
+ if (entry?.skeleton === void 0) return null;
40611
+ return {
40612
+ ...entry.skeleton,
40613
+ beats: (entry.skeleton.beats ?? []).map((b) => ({
40614
+ ...b,
40615
+ function: normalizeStoryFunction(typeof b.function === "string" ? b.function : void 0),
40616
+ emotion: normalizeEmotions(typeof b.emotion === "string" ? b.emotion : b.emotion?.join("→"))
40617
+ }))
40618
+ };
40619
+ });
40620
+ setTable((prev) => {
40621
+ if (prev !== null) return prev;
40622
+ if (entry?.table === void 0) return null;
40623
+ return {
40624
+ ...entry.table,
40625
+ shots: (entry.table.shots ?? []).map(normalizeStoryboardShot)
40626
+ };
40627
+ });
40011
40628
  setPrompts((prev) => prev ?? entry?.prompts ?? null);
40012
40629
  }, [chapterNo, project?.storyboards]);
40013
40630
  const generate = async (chain) => {
@@ -40279,12 +40896,12 @@ window.__ModuleLoader__.load({
40279
40896
  children: [
40280
40897
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("b", { children: ["节拍 ", i + 1] }),
40281
40898
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
40282
- className: `${panel_module_css_default.badge} ${b.function === "高潮" ? panel_module_css_default.badgeDone : b.function === "转折" ? panel_module_css_default.badgeWritten : panel_module_css_default.badgePending}`,
40283
- children: b.function
40899
+ className: `${panel_module_css_default.badge} ${b.function === "climax" ? panel_module_css_default.badgeDone : b.function === "turn" ? panel_module_css_default.badgeWritten : panel_module_css_default.badgePending}`,
40900
+ children: functionZh(b.function)
40284
40901
  }),
40285
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
40902
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
40286
40903
  className: panel_module_css_default.meta,
40287
- children: b.emotion
40904
+ children: ["💭 ", emotionZh(b.emotion)]
40288
40905
  })
40289
40906
  ]
40290
40907
  }),
@@ -40302,7 +40919,7 @@ window.__ModuleLoader__.load({
40302
40919
  type: "button",
40303
40920
  className: `${panel_module_css_default.button} ${panel_module_css_default.buttonSmall}`,
40304
40921
  onClick: () => {
40305
- const text = `第${skeleton.chapterNo}章 弧线:${skeleton.arc}\n出场角色:${skeleton.characters !== void 0 && skeleton.characters.length > 0 ? skeleton.characters.join("、") : "(未标注)"}\n\n` + skeleton.beats.map((b, i) => `${i + 1}. [${b.function}] ${b.event}(情绪:${b.emotion})${b.cause !== void 0 ? `[承接:${b.cause}]` : ""}`).join("\n");
40922
+ const text = `第${skeleton.chapterNo}章 弧线:${skeleton.arc}\n出场角色:${skeleton.characters !== void 0 && skeleton.characters.length > 0 ? skeleton.characters.join("、") : "(未标注)"}\n\n` + skeleton.beats.map((b, i) => `${i + 1}. [${functionZh(b.function)}] ${b.event}(情绪:${emotionZh(b.emotion)})${b.cause !== void 0 ? `[承接:${b.cause}]` : ""}`).join("\n");
40306
40923
  navigator.clipboard?.writeText(text);
40307
40924
  },
40308
40925
  children: "📋 复制骨架"
@@ -40362,7 +40979,7 @@ window.__ModuleLoader__.load({
40362
40979
  onClick: () => {
40363
40980
  const text = table.shots.map((s) => {
40364
40981
  const beat = skeleton?.beats.find((b) => b.id === s.beatId);
40365
- return `镜头 ${s.id}(节拍 ${beat?.id ?? s.beatId} · ${s.shot} · ${s.camera} · ${s.duration}s)\n出场:${s.characters !== void 0 && s.characters.length > 0 ? s.characters.join("、") : "(未标注)"}\n定妆:${s.mangaRoleIds !== void 0 && s.mangaRoleIds.length > 0 ? bindingNames(s.mangaRoleIds) : "(未绑定漫剧卡)"}\n画面:${s.visual}\n台词:${s.line !== "" ? s.line : "(无)"}\n音效:${s.sound !== "" ? s.sound : "(无)"}\n光效:${s.light !== "" ? s.light : "(无)"}\n承接:${s.prevState} → ${s.nextState}`;
40982
+ return `镜头 ${s.id}(节拍 ${beat?.id ?? s.beatId} · ${sizeZh(s.shot)} · ${cameraZh(s.camera)} · ${s.duration}s)\n出场:${s.characters !== void 0 && s.characters.length > 0 ? s.characters.join("、") : "(未标注)"}\n定妆:${s.mangaRoleIds !== void 0 && s.mangaRoleIds.length > 0 ? bindingNames(s.mangaRoleIds) : "(未绑定漫剧卡)"}\n画面:${s.visual}\n台词:${s.line !== "" ? s.line : "(无)"}\n音效:${s.sound !== "" ? s.sound : "(无)"}\n光效:${lightZh(s.light) !== "" ? lightZh(s.light) : "(无)"}\n承接:${s.prevState} → ${s.nextState}`;
40366
40983
  }).join("\n\n");
40367
40984
  navigator.clipboard?.writeText(`第${table.chapterNo}章分镜表\n\n` + text);
40368
40985
  },
@@ -40422,12 +41039,13 @@ window.__ModuleLoader__.load({
40422
41039
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("b", { children: ["镜头 ", s.id] }),
40423
41040
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
40424
41041
  className: panel_module_css_default.badge,
40425
- children: s.shot
41042
+ children: sizeZh(s.shot)
40426
41043
  }),
40427
41044
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
40428
41045
  className: panel_module_css_default.meta,
40429
41046
  children: [
40430
- s.camera,
41047
+ cameraZh(s.camera),
41048
+ compoZh(s.composition) !== "" ? " · " + compoZh(s.composition) : "",
40431
41049
  " · ",
40432
41050
  s.duration,
40433
41051
  "s"
@@ -40439,7 +41057,7 @@ window.__ModuleLoader__.load({
40439
41057
  "节拍 ",
40440
41058
  beat.id,
40441
41059
  "「",
40442
- beat.function,
41060
+ functionZh(beat.function),
40443
41061
  "」"
40444
41062
  ]
40445
41063
  }),
@@ -40468,7 +41086,7 @@ window.__ModuleLoader__.load({
40468
41086
  }),
40469
41087
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
40470
41088
  className: panel_module_css_default.meta,
40471
- children: ["💡 ", s.light !== "" ? s.light : "(无光效)"]
41089
+ children: ["💡 ", lightZh(s.light) !== "" ? lightZh(s.light) : "(无光效)"]
40472
41090
  })
40473
41091
  ]
40474
41092
  }),
@@ -42508,6 +43126,15 @@ window.__ModuleLoader__.load({
42508
43126
  onClick: () => {
42509
43127
  openDetail(s.name);
42510
43128
  },
43129
+ role: "button",
43130
+ tabIndex: 0,
43131
+ "aria-label": `打开场景 ${s.name}`,
43132
+ onKeyDown: (e) => {
43133
+ if (e.key === "Enter" || e.key === " ") {
43134
+ e.preventDefault();
43135
+ openDetail(s.name);
43136
+ }
43137
+ },
42511
43138
  style: {
42512
43139
  cursor: "pointer",
42513
43140
  border: "1px solid var(--nf-border)",
@@ -44417,7 +45044,7 @@ window.__ModuleLoader__.load({
44417
45044
  icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(import_lucide_react.Sparkles, { size: 16 })
44418
45045
  }
44419
45046
  ];
44420
- const PLUGIN_VERSION = "1.7.2";
45047
+ const PLUGIN_VERSION = "1.7.3";
44421
45048
  /** GitHub 仓库地址(关于区块点击跳转)。 */
44422
45049
  const REPO_URL = "https://github.com/watersxya/dsh-novel-forge";
44423
45050
  /** Whether any chapter is being generated right now. */
@@ -44455,6 +45082,10 @@ window.__ModuleLoader__.load({
44455
45082
  cls: panel_module_css_default.badgeError,
44456
45083
  label: tt("plan.error")
44457
45084
  };
45085
+ default: return {
45086
+ cls: panel_module_css_default.badgeError,
45087
+ label: tt("plan.error")
45088
+ };
44458
45089
  }
44459
45090
  }
44460
45091
  /** One review issue line (severity-colored, theme-aware). */