dshmarket 1.24.0 → 1.26.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.
package/client/client.js CHANGED
@@ -126,7 +126,12 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
126
126
  updateNow: "立即更新",
127
127
  updateFail: "更新失败",
128
128
  upToDate: "已是最新",
129
- linkedDev: "本地开发链接",
129
+ linkedDev: "本地开发",
130
+ restore: "恢复",
131
+ restoreHint: "会卸载本地版本,重新安装线上版本,并保持更新检测。无法回退,请二次确认。",
132
+ restoreContinue: "继续更新",
133
+ restoreNoCatalog: "精选目录里没有这个插件,无法恢复到线上版本。可以卸载本地版,或继续用本地开发。",
134
+ restoreFail: "恢复失败",
130
135
  exportLog: "导出日志",
131
136
  exportingLog: "导出中…",
132
137
  exportedLog: "日志已导出:dsh-market-log.txt,请将其附在 issue 中",
@@ -425,6 +430,50 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
425
430
  /** Summary-strip tooltip for the order count (before/after rule conflicts). */
426
431
  checkOrderTip: "社区 bundle 加载顺序与插件声明的 before/after 规则冲突",
427
432
  diagOkAll: "一切正常:未发现冲突、依赖或顺序问题",
433
+ presetSection: "插件组合",
434
+ presetHint: "把当前的 bundle 顺序与停用列表保存为组合,随时切换;应用前会做试启动校验并自动创建快照。",
435
+ presetName: "组合名称",
436
+ presetSave: "保存当前状态",
437
+ presetSaving: "保存中…",
438
+ presetSaved: "组合已保存",
439
+ presetApply: "应用",
440
+ presetApplied: "已应用,重启后生效",
441
+ presetDelete: "删除",
442
+ presetDeleted: "组合已删除",
443
+ presetEmpty: "还没有保存过组合",
444
+ presetNameEmpty: "请输入组合名称",
445
+ presetFail: "组合操作失败:",
446
+ presetListFail: "组合列表加载失败:",
447
+ presetBundleCount: "{0} 个 bundle",
448
+ presetPreview: "预览",
449
+ presetPreviewTitle: "应用此组合将:",
450
+ presetReorder: "重排 {0} 个 bundle 的位置",
451
+ presetEnable: "启用 {0} 个插件",
452
+ presetDisable: "停用 {0} 个插件",
453
+ presetNoop: "无变更",
454
+ presetPreviewFail: "预览失败:",
455
+ snapSection: "快照与回滚",
456
+ snapHint: "应用变更前会自动创建快照;也可以手动创建快照,随时回滚到任意状态。",
457
+ snapCreate: "创建快照",
458
+ snapCreating: "创建中…",
459
+ snapCreated: "快照已创建",
460
+ snapEmpty: "还没有快照",
461
+ snapListFail: "快照列表加载失败:",
462
+ snapCreateFail: "创建快照失败:",
463
+ snapRestore: "回滚",
464
+ snapRestoring: "回滚中…",
465
+ snapRestored: "已回滚,重启后生效",
466
+ snapRestoreFail: "回滚失败:",
467
+ snapRestoreConfirm: "确认回滚",
468
+ snapRestoreConfirmText: "回滚会用快照覆盖当前 profile 的 package.json 与配置,且不可撤销(可先创建新快照再回滚)。",
469
+ snapFiles: "包含文件",
470
+ snapDelete: "删除",
471
+ snapDeleting: "删除中…",
472
+ snapDeleted: "快照已删除",
473
+ snapDeleteFail: "删除快照失败:",
474
+ snapDeleteConfirm: "确认删除",
475
+ snapDeleteConfirmText: "删除后该快照将无法恢复。",
476
+ marketNoToggle: "市场自身不能停用",
428
477
  hostDependencyWarning: "插件在 dependencies 中声明了已知的 DSH 共享宿主包,可能遮蔽宿主版本(仅依据清单,未确认运行时重复):",
429
478
  hostDependencyMore: "另有 {0} 条,已省略"
430
479
  };
@@ -521,7 +570,12 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
521
570
  updateNow: "Update now",
522
571
  updateFail: "Update failed",
523
572
  upToDate: "Up to date",
524
- linkedDev: "linked (dev)",
573
+ linkedDev: "local",
574
+ restore: "Restore",
575
+ restoreHint: "This will uninstall the local version, reinstall the catalog version, and keep update checks. This cannot be undone — please confirm again.",
576
+ restoreContinue: "Continue update",
577
+ restoreNoCatalog: "This plugin is not in the curated catalog, so it cannot be restored. Uninstall the local copy, or keep developing it locally.",
578
+ restoreFail: "Restore failed",
525
579
  exportLog: "Export log",
526
580
  exportingLog: "Exporting…",
527
581
  exportedLog: "Log exported: dsh-market-log.txt — please attach it to your issue",
@@ -820,6 +874,50 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
820
874
  /** Summary-strip tooltip for the order count (before/after rule conflicts). */
821
875
  checkOrderTip: "community bundle load order conflicts with declared before/after rules",
822
876
  diagOkAll: "All good: no conflict, dependency or ordering issues found",
877
+ presetSection: "Plugin presets",
878
+ presetHint: "Save the current bundle order and disabled list as a preset and switch anytime; applying runs a trial-start check and creates a snapshot first.",
879
+ presetName: "Preset name",
880
+ presetSave: "Save current state",
881
+ presetSaving: "Saving…",
882
+ presetSaved: "Preset saved",
883
+ presetApply: "Apply",
884
+ presetApplied: "Applied — restart to apply",
885
+ presetDelete: "Delete",
886
+ presetDeleted: "Preset deleted",
887
+ presetEmpty: "No presets saved yet",
888
+ presetNameEmpty: "Enter a preset name",
889
+ presetFail: "Preset operation failed: ",
890
+ presetListFail: "Failed to load presets: ",
891
+ presetBundleCount: "{0} bundles",
892
+ presetPreview: "Preview",
893
+ presetPreviewTitle: "Applying this preset will:",
894
+ presetReorder: "reorder {0} bundles",
895
+ presetEnable: "enable {0} plugins",
896
+ presetDisable: "disable {0} plugins",
897
+ presetNoop: "no changes",
898
+ presetPreviewFail: "Preview failed: ",
899
+ snapSection: "Snapshots & Rollback",
900
+ snapHint: "Snapshots are taken automatically before applying changes; you can also create one manually and roll back anytime.",
901
+ snapCreate: "Create snapshot",
902
+ snapCreating: "Creating…",
903
+ snapCreated: "Snapshot created",
904
+ snapEmpty: "No snapshots yet",
905
+ snapListFail: "Failed to load snapshots: ",
906
+ snapCreateFail: "Failed to create snapshot: ",
907
+ snapRestore: "Restore",
908
+ snapRestoring: "Restoring…",
909
+ snapRestored: "Restored — restart to apply",
910
+ snapRestoreFail: "Failed to restore: ",
911
+ snapRestoreConfirm: "Confirm restore",
912
+ snapRestoreConfirmText: "Restoring overwrites the current profile package.json and configuration from the snapshot; this cannot be undone (create a fresh snapshot first if unsure).",
913
+ snapFiles: "files",
914
+ snapDelete: "Delete",
915
+ snapDeleting: "Deleting…",
916
+ snapDeleted: "Snapshot deleted",
917
+ snapDeleteFail: "Failed to delete snapshot: ",
918
+ snapDeleteConfirm: "Confirm delete",
919
+ snapDeleteConfirmText: "This snapshot cannot be recovered after deletion.",
920
+ marketNoToggle: "The market itself cannot be disabled",
823
921
  hostDependencyWarning: "A plugin lists known shared DSH host packages in dependencies. This may shadow the host version; the check is manifest-only and does not confirm a duplicate runtime instance:",
824
922
  hostDependencyMore: "{0} more finding(s) omitted"
825
923
  };
@@ -1484,7 +1582,7 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
1484
1582
  }
1485
1583
  //#endregion
1486
1584
  //#region \0dsh-css:src/client/Market.module.css.mjs
1487
- const css = ".eGUBIq_root{min-width:0;height:100%;color:var(--dsw-alias-label-primary,#1f2328);flex-direction:column;display:flex;position:relative;container-type:inline-size}.eGUBIq_head{flex-direction:column;gap:12px;padding:4px 4px 6px;display:flex}.eGUBIq_title{margin:0;font-size:16px;font-weight:500;line-height:24px}.eGUBIq_sub{color:var(--dsw-alias-label-tertiary,#8b93a1);align-items:center;gap:8px;margin:0;font-size:12px;line-height:18px;display:flex}.eGUBIq_submitLink{color:var(--dsw-alias-label-tertiary,#8b93a1);white-space:nowrap;font-size:11px;line-height:18px;text-decoration:none}.eGUBIq_submitLink:hover{color:var(--dsw-alias-brand-primary,#4f6ef7);text-decoration:underline}.eGUBIq_tabs{border-bottom:1px solid var(--dsw-alias-border-l2,#e5e7eb);align-items:flex-end;gap:2px;display:flex}.eGUBIq_tab{font:inherit;color:var(--dsw-alias-label-secondary,#6b7280);cursor:pointer;white-space:nowrap;background:0 0;border:none;border-bottom:2px solid #0000;padding:7px 12px;font-size:13px}.eGUBIq_tab.eGUBIq_on{color:var(--dsw-alias-brand-primary,#4f6ef7);border-bottom-color:var(--dsw-alias-brand-primary,#4f6ef7);font-weight:600}.eGUBIq_subTabs{align-items:flex-end;gap:2px;margin:-4px 0 4px;display:flex}.eGUBIq_banner{background:var(--dsw-alias-bg-layer-2,#fdf3e3);border:1px solid var(--dsw-alias-border-l2,#f3e3c3);border-radius:8px;align-items:center;gap:8px;margin:0;padding:8px 12px;font-size:12px;display:flex}.eGUBIq_bannerIcon{color:var(--dsw-alias-label-secondary,#6b7280);flex-shrink:0}.eGUBIq_bannerHint{color:var(--dsw-alias-label-tertiary,#8b93a1);cursor:help;display:inline-flex}.eGUBIq_body{flex:1;padding:12px 4px 24px;overflow-x:hidden;overflow-y:auto}.eGUBIq_stickyHead{z-index:5;background:var(--dsw-alias-bg-layer-2,#f7f8fa);position:sticky;top:-1px}.eGUBIq_stickyHead:before{content:\"\";background:inherit;pointer-events:none;height:14px;position:absolute;bottom:100%;left:0;right:0}.eGUBIq_cats{margin:0 -4px 2px;padding:12px 4px 4px}.eGUBIq_catsRow{align-items:flex-start;gap:8px;display:flex;position:relative}.eGUBIq_star{color:var(--dsw-alias-label-secondary,#9ca3af);white-space:nowrap;flex:none;font-size:11px}.eGUBIq_top{z-index:20;display:inline-flex;position:absolute;bottom:18px;right:18px}.eGUBIq_topBtn{border-radius:99px;width:38px;height:38px;padding:0}.eGUBIq_tag{border:1px solid var(--dsw-alias-border-l3,#d9dde3);color:var(--dsw-alias-label-secondary,#6b7280);border-radius:4px;flex-shrink:0;padding:1px 6px;font-size:11px;line-height:16px}.eGUBIq_okState{color:var(--dsw-alias-state-success-primary,#16a34a);white-space:nowrap;font-size:12px;font-weight:600}.eGUBIq_catsWrap{flex-wrap:wrap;flex:1;align-items:center;gap:6px;min-width:0;display:flex}.eGUBIq_catsCollapsed{max-height:62px;overflow:hidden}.eGUBIq_catsToggle.eGUBIq_catsToggle{height:26px;min-height:26px;color:var(--dsw-alias-label-secondary,#6b7280);padding:0 6px}.eGUBIq_shots{-webkit-overflow-scrolling:touch;scrollbar-width:thin;gap:8px;margin:6px 0 8px;padding:2px 0 6px;display:flex;overflow-x:auto}.eGUBIq_shot{object-fit:cover;border:1px solid var(--dsw-alias-border-default,#e5e7eb);background:var(--dsw-alias-bg-layer-2,#f3f4f6);cursor:pointer;border-radius:8px;flex:none;width:220px;height:150px}.eGUBIq_cardShots{-webkit-overflow-scrolling:touch;scrollbar-width:thin;gap:6px;margin:0 0 6px;padding:0 0 2px;display:flex;overflow-x:auto}.eGUBIq_cardShot{object-fit:contain;border:1px solid var(--dsw-alias-border-default,#e5e7eb);background:var(--dsw-alias-bg-layer-2,#f3f4f6);cursor:pointer;border-radius:8px;flex:none;width:132px;height:88px;display:block}.eGUBIq_lightbox{z-index:10000;cursor:zoom-out;background:#000000d9;justify-content:center;align-items:center;display:flex;position:fixed;top:0;bottom:0;left:0;right:0}.eGUBIq_lightboxImg{object-fit:contain;cursor:default;border-radius:4px;max-width:90vw;max-height:85vh}.eGUBIq_lightboxClose{color:#fff;cursor:pointer;background:#ffffff1f;border:none;border-radius:99px;place-items:center;width:36px;height:36px;font-size:22px;line-height:1;display:grid;position:absolute;top:16px;right:16px}.eGUBIq_lightboxClose:hover{background:#ffffff38}.eGUBIq_lightboxNav{color:#fff;cursor:pointer;background:#ffffff1f;border:none;border-radius:99px;place-items:center;width:44px;height:44px;display:grid;position:absolute;top:50%;transform:translateY(-50%)}.eGUBIq_lightboxNav:hover{background:#ffffff38}.eGUBIq_lightboxPrev{left:16px}.eGUBIq_lightboxNext{right:16px}.eGUBIq_lightboxDots{gap:8px;display:flex;position:absolute;bottom:20px;left:50%;transform:translate(-50%)}.eGUBIq_lightboxDot{cursor:pointer;background:#fff6;border-radius:99px;width:7px;height:7px}.eGUBIq_lightboxDotOn{background:#fff}.eGUBIq_cmd{background:var(--dsw-alias-bg-layer-2,#f3f4f6);word-break:break-all;border-radius:6px;margin:8px 0 0;padding:8px 10px;font-family:ui-monospace,Menlo,monospace;font-size:11px;line-height:18px}.eGUBIq_warnLine{color:var(--dsw-alias-state-warn-primary,#b45309);flex-wrap:wrap;align-items:center;gap:4px;margin:0;font-size:12px;font-weight:600;line-height:18px;display:flex}.eGUBIq_modalNote{color:var(--dsw-alias-label-tertiary,#8b93a1);align-items:center;gap:4px;margin:12px 0 0;font-size:12px;line-height:18px;display:flex}.eGUBIq_grid{grid-template-columns:repeat(2,minmax(0,1fr));align-items:start;gap:10px;display:grid}.eGUBIq_masonry{align-items:flex-start;gap:10px;display:flex}.eGUBIq_masonryCol{flex-direction:column;flex:1;gap:10px;min-width:0;display:flex}.eGUBIq_masonry>.eGUBIq_masonryCol>*{align-self:stretch;min-width:0}@media (max-width:680px){.eGUBIq_masonry{flex-direction:column}.eGUBIq_masonryCol{width:100%}.eGUBIq_grid{grid-template-columns:minmax(0,1fr)}}.eGUBIq_swatches{border:1px solid var(--dsw-alias-border-l2,#e5e7eb);border-radius:8px;gap:0;height:34px;display:flex;overflow:hidden}.eGUBIq_themesGrid{margin-bottom:12px}.eGUBIq_swatches i{flex:1}.eGUBIq_themeToolbar{grid-template-columns:minmax(0,1fr) auto;align-items:center;gap:8px;padding:0 4px 12px;display:grid}.eGUBIq_themeSearch{box-sizing:border-box;width:100%;min-width:0}.eGUBIq_themeToolbarActions{justify-content:flex-end;align-items:center;gap:8px;display:flex}.eGUBIq_themeFullscreenBtn.eGUBIq_themeFullscreenBtn{width:28px;min-width:28px;padding:0}.eGUBIq_themeResultBar{min-height:24px;color:var(--dsw-alias-label-tertiary,#8b93a1);align-items:center;padding:0 4px 8px;font-size:12px;line-height:18px;display:flex}.eGUBIq_themeGallery{grid-template-columns:repeat(4,minmax(0,1fr));align-items:stretch;gap:10px;display:grid}.eGUBIq_themeCard{border:1px solid var(--dsw-alias-border-l2,#e5e7eb);background:var(--dsw-alias-bg-layer-1,#fff);border-radius:8px;flex-direction:column;min-width:0;transition:border-color .16s cubic-bezier(.16,1,.3,1),box-shadow .16s cubic-bezier(.16,1,.3,1),transform .16s cubic-bezier(.16,1,.3,1);display:flex;overflow:hidden}.eGUBIq_themeCard:hover{border-color:var(--dsw-alias-border-l3,#d9dde3);box-shadow:var(--dsw-shadow-lv1,0 4px 12px #1f232814);transform:translateY(-1px)}.eGUBIq_themeCover{aspect-ratio:16/10;border:0;border-bottom:1px solid var(--dsw-alias-border-l2,#e5e7eb);background:var(--dsw-alias-bg-layer-2,#f3f4f6);width:100%;color:var(--dsw-alias-label-secondary,#6b7280);cursor:zoom-in;border-radius:0;padding:0;display:block;position:relative;overflow:hidden}.eGUBIq_themeCover img{object-fit:contain;background:var(--dsw-alias-bg-layer-2,#f3f4f6);width:100%;height:100%;transition:transform .18s cubic-bezier(.16,1,.3,1);display:block}.eGUBIq_themeCover:hover img{transform:scale(1.012)}.eGUBIq_themeCover:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,#4f6ef7);outline-offset:-3px}.eGUBIq_themeCoverEmpty{cursor:default;color:var(--dsw-alias-label-tertiary,#8b93a1);flex-direction:column;justify-content:center;align-items:center;gap:8px;font-size:12px;line-height:18px;display:flex}.eGUBIq_themePreviewAction,.eGUBIq_themePreviewCount{color:#fff;-webkit-backdrop-filter:blur(8px);background:#14181fc7;border:1px solid #ffffff57;border-radius:4px;align-items:center;height:24px;padding:0 8px;font-size:11px;line-height:16px;display:inline-flex;position:absolute;bottom:8px}.eGUBIq_themePreviewAction{gap:4px;right:8px}.eGUBIq_themePreviewCount{left:8px}.eGUBIq_themeCardBody{flex-direction:column;flex:1;gap:8px;padding:12px;display:flex}.eGUBIq_themeCardHead{align-items:flex-start;gap:8px;min-width:0;display:flex}.eGUBIq_themeIdentity{flex:1;min-width:0}.eGUBIq_themeStatus,.eGUBIq_themeStatusMuted{white-space:nowrap;border-radius:4px;flex:none;align-items:center;min-height:22px;padding:0 8px;font-size:11px;font-weight:600;display:inline-flex}.eGUBIq_themeStatus{background:var(--dsw-alias-state-success-tertiary,#16a34a1a);color:var(--dsw-alias-state-success-primary,#15803d)}.eGUBIq_themeStatusMuted{background:var(--dsw-alias-bg-layer-2,#f3f4f6);color:var(--dsw-alias-label-secondary,#6b7280)}.eGUBIq_themeDescription{min-height:36px;color:var(--dsw-alias-label-tertiary,#8b93a1);-webkit-line-clamp:2;-webkit-box-orient:vertical;margin:0;font-size:12px;line-height:18px;display:-webkit-box;overflow:hidden}.eGUBIq_themeCardFooter{justify-content:space-between;align-items:center;gap:8px;margin-top:auto;padding-top:4px;display:flex}.eGUBIq_themeLifecycle{min-width:0;color:var(--dsw-alias-label-tertiary,#8b93a1);text-overflow:ellipsis;white-space:nowrap;font-size:11px;line-height:18px;overflow:hidden}.eGUBIq_themeActions{flex-wrap:wrap;justify-content:flex-end;align-items:center;gap:8px;margin-left:auto;display:flex}@container (width<=900px){.eGUBIq_themeGallery{grid-template-columns:repeat(3,minmax(0,1fr))}}@container (width<=680px){.eGUBIq_themeGallery{grid-template-columns:repeat(2,minmax(0,1fr))}}@container (width<=460px){.eGUBIq_themeGallery{grid-template-columns:minmax(0,1fr)}}@container (width<=420px){.eGUBIq_sub{grid-template-columns:minmax(0,1fr) auto;align-items:start;gap:2px 8px;display:grid}.eGUBIq_sub>span:first-child{grid-area:1/1}.eGUBIq_sub>.eGUBIq_grow{display:none}.eGUBIq_submitLink{grid-area:2/1}.eGUBIq_exportLogBtn{flex-shrink:0;grid-area:1/2/span 2}.eGUBIq_themeToolbar{grid-template-columns:minmax(0,1fr)}.eGUBIq_themeCardHead{flex-wrap:wrap}.eGUBIq_themeStatus,.eGUBIq_themeStatusMuted{order:3}}@container (width<=280px){.eGUBIq_themeCardFooter{flex-direction:column;align-items:flex-start}.eGUBIq_themeActions{justify-content:flex-start;width:100%;margin-left:0}}@media (max-width:560px){[role=dialog]:has([data-dsh-market-root])>nav{display:none}[role=dialog]:has([data-dsh-market-root])>div{flex:100%;width:100%;min-width:0}}[role=dialog]:has([data-dsh-market-fullscreen=true]){border-radius:0;width:100vw;max-width:none;height:100vh;max-height:none;position:fixed;top:0;bottom:0;left:0;right:0}@media (prefers-reduced-motion:reduce){.eGUBIq_themeCard,.eGUBIq_themeCover img{transition:none}.eGUBIq_themeCard:hover{transform:none}}.eGUBIq_card{background:var(--dsw-alias-bg-layer-1,#fff);border:1px solid var(--dsw-alias-border-l2,#e5e7eb);border-radius:12px;flex-direction:column;align-self:start;gap:12px;padding:12px 14px;display:flex}.eGUBIq_row1{align-items:flex-start;gap:10px;min-width:0;display:flex}.eGUBIq_cardAction{flex-shrink:0;align-items:center;display:inline-flex}.eGUBIq_installBtn.eGUBIq_installBtn{min-width:64px}.eGUBIq_av{color:#fff;object-fit:cover;background:var(--dsw-alias-bg-layer-2,#f3f4f6);border-radius:50%;flex-shrink:0;place-items:center;width:16px;height:16px;font-size:9px;font-weight:700;display:grid}.eGUBIq_nm{text-overflow:ellipsis;white-space:nowrap;font-size:15px;font-weight:600;line-height:22px;overflow:hidden}.eGUBIq_nmLink{color:inherit;text-decoration:none;display:block}.eGUBIq_nmLink:hover{color:var(--dsw-alias-brand-primary,#4f6ef7);text-decoration:underline}.eGUBIq_repoMark{color:var(--dsw-alias-label-tertiary,#8b93a1);vertical-align:-1px;flex-shrink:0;margin-left:5px}.eGUBIq_nmLink:hover .eGUBIq_repoMark{color:var(--dsw-alias-brand-primary,#4f6ef7)}.eGUBIq_byline{flex-wrap:wrap;align-items:center;gap:6px;min-width:0;margin-top:2px;display:flex}.eGUBIq_meta{color:var(--dsw-alias-label-secondary,#9ca3af);margin-top:2px;font-size:11px}.eGUBIq_metaInline{color:var(--dsw-alias-label-secondary,#9ca3af);font-size:11px}.eGUBIq_owner{color:var(--dsw-alias-label-secondary,#9ca3af);text-overflow:ellipsis;white-space:nowrap;flex:0 auto;min-width:44px;font-size:11px;overflow:hidden}.eGUBIq_desc{color:var(--dsw-alias-label-tertiary,#8b93a1);margin:0;font-size:12px;line-height:18px}.eGUBIq_descClamp{-webkit-line-clamp:5;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.eGUBIq_descToggle{width:20px;height:16px;color:var(--dsw-alias-label-tertiary,#8b93a1);cursor:pointer;background:0 0;border:none;justify-content:center;align-items:center;margin-top:2px;padding:0;display:flex}.eGUBIq_descToggle:hover{color:var(--dsw-alias-brand-primary,#4f6ef7)}.eGUBIq_foot{flex-wrap:wrap;align-items:center;gap:8px;display:flex}.eGUBIq_foot .eGUBIq_metaInline,.eGUBIq_foot .eGUBIq_src{white-space:nowrap}.eGUBIq_grow{flex:1}.eGUBIq_titleRow{align-items:center;gap:10px;display:flex}.eGUBIq_version{color:var(--dsw-alias-label-tertiary,#8b93a1);font-variant-numeric:tabular-nums;flex-shrink:0;font-size:12px;line-height:20px}.eGUBIq_repoLink{color:var(--dsw-alias-label-tertiary,#8b93a1);flex-shrink:0;font-size:12px;line-height:20px;text-decoration:none}.eGUBIq_repoLink:hover{color:var(--dsw-alias-brand-primary,#4f6ef7)}.eGUBIq_descTight{min-height:0}.eGUBIq_src{color:var(--dsw-alias-label-secondary,#9ca3af);font-size:11px;text-decoration:none}.eGUBIq_src:hover{color:var(--dsw-alias-brand-primary,#4f6ef7)}.eGUBIq_dot{vertical-align:2px;margin-left:5px}.eGUBIq_act{flex-wrap:wrap;align-items:center;gap:6px;margin-top:6px;font-size:11px;display:flex}.eGUBIq_actLive{color:var(--dsw-alias-state-success-primary,#16a34a);align-items:center;gap:4px;font-weight:600;display:inline-flex}.eGUBIq_actWarn{color:var(--dsw-alias-state-warn-primary,#b45309);align-items:center;gap:4px;font-weight:600;display:inline-flex}.eGUBIq_actBroken{color:var(--dsw-alias-state-error-primary,#dc2626);align-items:center;gap:4px;font-weight:600;display:inline-flex}.eGUBIq_actWhy{color:var(--dsw-alias-label-secondary,#6b7280);margin-top:2px}.eGUBIq_loading{color:var(--dsw-alias-label-secondary,#9ca3af);flex-direction:column;align-items:center;gap:12px;padding:48px;font-size:13px;display:flex}.eGUBIq_spin{color:var(--dsw-alias-brand-primary,#4f6ef7);flex-shrink:0;animation:.8s linear infinite eGUBIq_sp;display:inline-flex}.eGUBIq_logoMark{color:var(--dsw-alias-brand-primary,#4f6ef7);flex-shrink:0;display:inline-flex}.eGUBIq_logoPlug{transform-box:fill-box;transform-origin:50%;animation:1.5s cubic-bezier(.4,0,.2,1) infinite eGUBIq_dshmPlug}@keyframes eGUBIq_dshmPlug{0%,12%{transform:rotate(9deg)}45%,62%{transform:translate(-1.28px,1.27px)rotate(0)}95%,to{transform:rotate(9deg)}}@media (prefers-reduced-motion:reduce){.eGUBIq_logoPlug,.eGUBIq_spin{animation:1.5s ease-in-out infinite eGUBIq_dshmPlugFade}}@keyframes eGUBIq_dshmPlugFade{0%,to{opacity:1}50%{opacity:.35}}@keyframes eGUBIq_sp{to{transform:rotate(360deg)}}.eGUBIq_progress{background:var(--dsw-alias-bg-layer-2,#f3f4f6);border:1px solid var(--dsw-alias-border-l2,#e5e7eb);color:var(--dsw-alias-label-secondary,#6b7280);border-radius:8px;flex-wrap:wrap;align-items:center;gap:9px;margin:0;padding:8px 12px;font-size:12px;display:flex}.eGUBIq_bar{background:var(--dsw-alias-border-l1,#e5e7eb);border-radius:99px;width:100%;height:4px;overflow:hidden}.eGUBIq_barFill{background:var(--dsw-alias-brand-primary,#4f6ef7);border-radius:99px;height:100%;transition:width .6s}.eGUBIq_barWave{width:30%;animation:1.2s ease-in-out infinite eGUBIq_dshmSlide}@keyframes eGUBIq_dshmSlide{0%{margin-left:-30%}to{margin-left:100%}}.eGUBIq_irow .eGUBIq_progress{margin-top:8px}.eGUBIq_progress code{text-overflow:ellipsis;white-space:nowrap;font-family:ui-monospace,Menlo,monospace;font-size:11px;overflow:hidden}.eGUBIq_empty{color:var(--dsw-alias-label-secondary,#9ca3af);text-align:center;padding:32px;font-size:13px}.eGUBIq_err{color:var(--dsw-alias-state-error-primary,#dc2626);white-space:pre-wrap;word-break:break-all;margin:8px 0;font-size:12px}.eGUBIq_cardBlocked{border-color:var(--dsw-alias-state-error-primary,#dc2626)}.eGUBIq_conflictHead{align-items:flex-start;gap:8px;display:flex}.eGUBIq_conflictIcon{color:var(--dsw-alias-state-error-primary,#dc2626);flex-shrink:0;margin-top:1px}.eGUBIq_conflictTitle{color:var(--dsw-alias-state-error-primary,#dc2626);font-size:13px;font-weight:600;line-height:18px}.eGUBIq_conflictBody{margin:0;font-size:12px;line-height:19px}.eGUBIq_roster{background:var(--dsw-alias-border-l2,#e5e7eb);border:1px solid var(--dsw-alias-border-l2,#e5e7eb);border-radius:8px;flex-direction:column;gap:1px;display:flex;overflow:hidden}.eGUBIq_rosterRow{background:var(--dsw-alias-bg-layer-1,#fff);align-items:center;gap:8px;padding:7px 10px;display:flex}.eGUBIq_rosterMain{flex-direction:column;min-width:0;display:flex}.eGUBIq_rosterName{text-overflow:ellipsis;white-space:nowrap;min-width:0;font-size:12px;font-weight:600;overflow:hidden}.eGUBIq_rosterAuthor{color:var(--dsw-alias-label-secondary,#9ca3af);text-overflow:ellipsis;white-space:nowrap;font-size:10.5px;overflow:hidden}.eGUBIq_rosterTag{border-radius:4px;flex-shrink:0;margin-left:auto;padding:1px 6px;font-size:10.5px;font-weight:600}.eGUBIq_rosterTagKeep{color:var(--dsw-alias-state-success-primary,#16a34a);background:#16a34a1f}.eGUBIq_rosterTagDrop{color:var(--dsw-alias-state-error-primary,#dc2626);background:#dc26261f}.eGUBIq_rosterRowOut .eGUBIq_rosterName{text-decoration:line-through}.eGUBIq_rosterRowOut{opacity:.62}.eGUBIq_rosterSplit{background:var(--dsw-alias-border-l2,#e5e7eb);height:1px}.eGUBIq_reassure{color:var(--dsw-alias-label-secondary,#6b7280);align-items:center;gap:5px;margin:0;font-size:11.5px;line-height:17px;display:flex}.eGUBIq_reassureOk{color:var(--dsw-alias-state-success-primary,#16a34a);flex-shrink:0}.eGUBIq_conflictWhy{color:var(--dsw-alias-label-tertiary,#8b93a1);overflow-wrap:anywhere;margin-top:2px;font-family:ui-monospace,Menlo,monospace;font-size:11px;line-height:17px}.eGUBIq_conflictWhyText{margin-top:5px;font-family:-apple-system,BlinkMacSystemFont,PingFang SC,sans-serif}.eGUBIq_choices{flex-direction:column;gap:7px;display:flex}.eGUBIq_choice{text-align:left;font:inherit;cursor:pointer;background:var(--dsw-alias-bg-layer-1,#fff);border:1px solid var(--dsw-alias-border-l3,#d9dde3);border-radius:9px;align-items:flex-start;gap:9px;padding:9px 11px;display:flex}.eGUBIq_choice:has(input:disabled){cursor:default;opacity:.6}.eGUBIq_choiceOn{border-color:var(--dsw-alias-brand-primary,#4f6ef7);background:var(--dsw-alias-bg-layer-2,#f5f7ff)}.eGUBIq_choiceRadio{width:13px;height:13px;accent-color:var(--dsw-alias-brand-primary,#4f6ef7);flex-shrink:0;margin:2px 0 0}.eGUBIq_choiceMain{flex-direction:column;gap:3px;min-width:0;display:flex}.eGUBIq_choiceTitle{font-size:12px;font-weight:600;line-height:17px}.eGUBIq_choiceNote{color:var(--dsw-alias-label-tertiary,#8b93a1);font-size:11px;line-height:16px}.eGUBIq_choiceSafe{color:var(--dsw-alias-state-success-primary,#16a34a)}.eGUBIq_stateTag{white-space:nowrap;background:var(--dsw-alias-bg-layer-2,#f3f4f6);min-height:20px;color:var(--dsw-alias-label-secondary,#6b7280);border-radius:5px;flex-shrink:0;align-items:center;gap:5px;padding:1px 7px;font-size:11px;line-height:16px;display:inline-flex}.eGUBIq_stateTag[data-on=true]{color:var(--dsw-alias-state-success-primary,#16a34a);background:color-mix(in srgb, var(--dsw-alias-state-success-primary,#16a34a) 10%, transparent)}.eGUBIq_stateDot{background:var(--dsw-alias-label-tertiary,#8b93a1);border-radius:999px;flex:none;width:6px;height:6px}.eGUBIq_stateDot[data-on=true]{background:var(--dsw-alias-state-success-primary,#16a34a)}.eGUBIq_metaTag{text-overflow:ellipsis;white-space:nowrap;background:var(--dsw-alias-bg-layer-2,#f3f4f6);min-width:0;max-width:100%;min-height:20px;color:var(--dsw-alias-label-tertiary,#8b93a1);border-radius:5px;flex-shrink:1;padding:1px 7px;font-size:11px;line-height:18px;display:inline-block;overflow:hidden}.eGUBIq_metaTagOk{color:var(--dsw-alias-state-success-primary,#16a34a);background:color-mix(in srgb, var(--dsw-alias-state-success-primary,#16a34a) 10%, transparent)}.eGUBIq_nameLink{color:inherit;text-decoration:none}.eGUBIq_irowName{text-overflow:clip;align-items:baseline;gap:6px;min-width:0;display:flex;overflow:visible}.eGUBIq_irowNameText{text-overflow:ellipsis;white-space:nowrap;min-width:0;overflow:hidden}.eGUBIq_irowName>.eGUBIq_owner{flex:none}.eGUBIq_nameLink:hover{color:var(--dsw-alias-brand-primary,#4f6ef7);text-decoration:underline}.eGUBIq_opWrap{flex-shrink:0;display:inline-flex;position:relative}.eGUBIq_opEntry{font:inherit;cursor:pointer;white-space:nowrap;color:var(--dsw-alias-label-primary,#1f2328);background:var(--dsw-alias-bg-layer-1,#fff);border:1px solid var(--dsw-alias-border-l3,#d9dde3);border-radius:7px;align-items:center;gap:6px;padding:4px 10px;font-size:12px;display:inline-flex;position:relative}.eGUBIq_opEntryQuiet{color:var(--dsw-alias-label-secondary,#6b7280);background:0 0;border-color:#0000}.eGUBIq_opEntryAlert{border-color:var(--dsw-alias-state-error-primary,#dc2626);color:var(--dsw-alias-state-error-primary,#dc2626)}.eGUBIq_opDot{background:var(--dsw-alias-state-error-primary,#dc2626);border-radius:99px;width:8px;height:8px;position:absolute;top:-3px;right:-3px}.eGUBIq_opPanel{z-index:40;background:var(--dsw-alias-bg-layer-1,#fff);border:1px solid var(--dsw-alias-border-l3,#d9dde3);border-radius:12px;width:460px;max-width:86vw;max-height:70vh;position:absolute;top:calc(100% + 6px);right:0;overflow-y:auto;box-shadow:0 20px 52px #00000047}.eGUBIq_opHead{border-bottom:1px solid var(--dsw-alias-border-l2,#e5e7eb);align-items:center;gap:8px;padding:9px 14px;display:flex}.eGUBIq_opPanelTitle{font-size:12.5px;font-weight:600}.eGUBIq_opCloseBtn.eGUBIq_opCloseBtn{min-width:0;color:var(--dsw-alias-label-secondary,#6b7280);padding:0 6px}.eGUBIq_opAggregate{border-bottom:1px solid var(--dsw-alias-border-l2,#e5e7eb);background:var(--dsw-alias-bg-layer-2,#f7f8fa);padding:9px 14px}.eGUBIq_opAggregateTop{font-variant-numeric:tabular-nums;font-size:12px;font-weight:600}.eGUBIq_opAggregateHint{color:var(--dsw-alias-label-tertiary,#8b93a1);margin-top:4px;font-size:10.5px}.eGUBIq_opRow{border-bottom:1px solid var(--dsw-alias-border-l2,#e5e7eb);align-items:flex-start;gap:9px;padding:9px 14px;display:flex}.eGUBIq_opRow:last-child{border-bottom:none}.eGUBIq_opRowAlert{background:#dc26260f}.eGUBIq_opIcon{flex-shrink:0;place-items:center;width:14px;margin-top:1px;display:grid}.eGUBIq_opQueuedIcon{color:var(--dsw-alias-label-tertiary,#8b93a1);font-size:12px}.eGUBIq_opMain{flex-direction:column;flex:1;gap:3px;min-width:0;display:flex}.eGUBIq_opTop{align-items:baseline;gap:6px;min-width:0;display:flex}.eGUBIq_opVerb{color:var(--dsw-alias-label-secondary,#6b7280);flex-shrink:0;font-size:12px}.eGUBIq_opName{text-overflow:ellipsis;white-space:nowrap;font-size:12px;font-weight:600;overflow:hidden}.eGUBIq_opStatus{color:var(--dsw-alias-label-tertiary,#8b93a1);overflow-wrap:anywhere;font-size:10.5px;line-height:16px}.eGUBIq_opStatusBad{color:var(--dsw-alias-state-error-primary,#dc2626)}.eGUBIq_opActions{flex-shrink:0;align-items:center;gap:6px;margin-top:1px;display:flex}.eGUBIq_opDecision{border-top:1px dashed var(--dsw-alias-border-l2,#e5e7eb);flex-direction:column;gap:8px;margin-top:8px;padding-top:8px;display:flex}.eGUBIq_opDecisionFoot{align-items:center;gap:8px;display:flex}.eGUBIq_conflictDetailsToggle{font:inherit;cursor:pointer;color:var(--dsw-alias-label-tertiary,#8b93a1);background:0 0;border:none;align-items:center;gap:4px;padding:2px 0;font-size:11px;display:inline-flex}.eGUBIq_conflictDetailsToggle:hover{color:var(--dsw-alias-label-secondary,#6b7280)}.eGUBIq_opEmpty{text-align:center;color:var(--dsw-alias-label-secondary,#6b7280);padding:30px 14px;font-size:12px}.eGUBIq_opEmptyHint{color:var(--dsw-alias-label-tertiary,#8b93a1);margin-top:4px;font-size:11px}.eGUBIq_cardBlockedMark{font:inherit;cursor:pointer;color:var(--dsw-alias-state-error-primary,#dc2626);border:1px solid var(--dsw-alias-state-error-primary,#dc2626);background:#dc262614;border-radius:7px;align-items:center;gap:5px;padding:4px 9px;font-size:11px;display:inline-flex}.eGUBIq_dangerBtn.eGUBIq_dangerBtn{color:var(--dsw-alias-state-error-primary,#dc2626);border-color:var(--dsw-alias-state-error-primary,#dc2626)}.eGUBIq_dangerBtn.eGUBIq_dangerBtn:hover:not(:disabled){background:var(--dsw-alias-state-error-primary,#dc2626);color:#fff}.eGUBIq_dangerArmed.eGUBIq_dangerArmed{background:var(--dsw-alias-state-error-primary,#dc2626);border-color:var(--dsw-alias-state-error-primary,#dc2626);color:#fff}.eGUBIq_retryBtn{margin-top:4px}.eGUBIq_irow{background:var(--dsw-alias-bg-layer-1,#fff);border:1px solid var(--dsw-alias-border-l2,#e5e7eb);border-radius:10px;flex-direction:column;gap:10px;min-width:0;padding:12px 14px;display:flex}.eGUBIq_irowActions{flex-wrap:wrap;justify-content:flex-start;align-items:center;gap:8px;min-width:0;display:flex}.eGUBIq_irowTrailing{flex-wrap:nowrap;align-items:center;gap:8px;min-width:0;display:inline-flex}.eGUBIq_irowMissing{filter:grayscale();opacity:.5}.eGUBIq_irow>.eGUBIq_src,.eGUBIq_irow>.eGUBIq_owner,.eGUBIq_irow button{white-space:nowrap;flex-shrink:0}.eGUBIq_tabSearchRow{padding:0 4px 6px;display:flex}.eGUBIq_tabSearch{width:100%}.eGUBIq_spec{color:var(--dsw-alias-label-secondary,#9ca3af);overflow-wrap:anywhere;min-width:0;font-family:ui-monospace,Menlo,monospace;font-size:11px}.eGUBIq_specTag{white-space:nowrap;border-radius:4px;flex-shrink:0;align-items:center;height:16px;padding:0 5px;font-size:10px;font-weight:600;display:inline-flex}.eGUBIq_specTagGit{color:#0b7285;background:#12a3c41f}.eGUBIq_specTagFile{color:#b07d1b;background:#f0b42924}.eGUBIq_backupCheckList .eGUBIq_grow{white-space:nowrap;text-overflow:ellipsis;flex:70%;min-width:0;overflow:hidden}.eGUBIq_backupCheckList .eGUBIq_spec{text-align:right;white-space:nowrap;text-overflow:ellipsis;flex:0 30%;max-width:30%;overflow:hidden}.eGUBIq_staleAction{margin-top:8px}.eGUBIq_pct{color:var(--dsw-alias-label-secondary,#6b7280);flex-shrink:0;font-size:11px;font-weight:600}.eGUBIq_pager{flex-wrap:wrap;justify-content:space-between;align-items:center;gap:12px;margin:16px 0 4px;display:flex}.eGUBIq_pagerPages{flex-wrap:wrap;flex:1;justify-content:center;align-items:center;gap:6px;min-width:0;display:flex}.eGUBIq_pageEllipsis{color:var(--dsw-alias-label-secondary,#9ca3af);padding:0 2px;font-size:12px}.eGUBIq_pageInfo{color:var(--dsw-alias-label-secondary,#6b7280);white-space:nowrap;font-size:12px}.eGUBIq_depBadge{border:1px solid var(--dsw-alias-state-warn-primary,#b45309);color:var(--dsw-alias-state-warn-primary,#b45309);white-space:nowrap;border-radius:4px;flex-shrink:0;margin-left:6px;padding:1px 6px;font-size:11px;font-weight:600;line-height:16px}.eGUBIq_deprecate{color:var(--dsw-alias-state-warn-primary,#b45309);background:var(--dsw-alias-bg-layer-2,#fdf3e3);border:1px solid var(--dsw-alias-border-l2,#f3e3c3);border-radius:8px;margin:0;padding:8px 10px;font-size:12px;line-height:18px}.eGUBIq_deprecate a{color:var(--dsw-alias-state-warn-primary,#b45309);text-decoration:underline}.eGUBIq_deprecate .eGUBIq_src{margin-left:8px}.eGUBIq_depLine{flex-wrap:wrap;align-items:center;gap:8px;display:flex}.eGUBIq_switch{border:1px solid var(--dsw-alias-border-l2,#d9dde3);background:var(--dsw-alias-bg-layer-2,#e5e7eb);cursor:pointer;border-radius:99px;flex-shrink:0;width:38px;height:22px;padding:0;transition:background .15s,border-color .15s;position:relative}.eGUBIq_switchOn{background:var(--dsw-alias-state-success-primary,#16a34a);border-color:var(--dsw-alias-state-success-primary,#16a34a)}.eGUBIq_switchMixed{background:var(--dsw-alias-state-warn-primary,#b45309);border-color:var(--dsw-alias-state-warn-primary,#b45309)}.eGUBIq_switchKnob{background:#fff;border-radius:99px;width:16px;height:16px;transition:left .15s;position:absolute;top:2px;left:2px;box-shadow:0 1px 2px #00000040}.eGUBIq_switchOn .eGUBIq_switchKnob,.eGUBIq_switchMixed .eGUBIq_switchKnob{left:18px}.eGUBIq_switch:disabled{opacity:.5;cursor:default}.eGUBIq_viewBar{border:1px solid var(--dsw-alias-border-l2,#e5e7eb);border-radius:8px;align-items:center;gap:2px;width:fit-content;margin-bottom:12px;padding:2px;display:flex}.eGUBIq_viewBtn{font:inherit;color:var(--dsw-alias-label-secondary,#6b7280);cursor:pointer;white-space:nowrap;background:0 0;border:none;border-radius:6px;padding:4px 10px;font-size:12px;line-height:18px}.eGUBIq_viewBtn:hover{color:var(--dsw-alias-brand-primary,#4f6ef7)}.eGUBIq_viewOn{background:var(--dsw-alias-bg-layer-2,#eef0f4);color:var(--dsw-alias-label-primary,#1f2328);font-weight:600}.eGUBIq_groupRow{background:var(--dsw-alias-bg-layer-1,#fff);border:1px solid var(--dsw-alias-border-l2,#e5e7eb);border-radius:12px;margin-bottom:10px;padding:12px 14px}.eGUBIq_groupHead{align-items:center;gap:10px;min-width:0;display:flex}.eGUBIq_groupName{text-overflow:ellipsis;white-space:nowrap;font-size:13px;font-weight:600;line-height:20px;overflow:hidden}.eGUBIq_groupActions{flex-shrink:0;align-items:center;gap:6px;display:flex}.eGUBIq_groupMembers{flex-direction:column;gap:6px;margin-top:10px;display:flex}.eGUBIq_groupMember{background:var(--dsw-alias-bg-layer-2,#f7f8fa);border-radius:8px;align-items:center;gap:8px;padding:6px 8px;font-size:12px;line-height:18px;display:flex}.eGUBIq_groupMember .eGUBIq_nm{flex:1;min-width:0;font-size:12px}.eGUBIq_groupAddPanel{border-top:1px dashed var(--dsw-alias-border-l2,#e5e7eb);flex-direction:column;gap:6px;margin-top:10px;padding-top:10px;display:flex}.eGUBIq_groupCreate{align-items:center;gap:8px;margin-bottom:10px;display:flex}.eGUBIq_inlineInput{flex:1;min-width:120px}.eGUBIq_assignRow{flex-wrap:wrap;align-items:center;gap:8px;display:flex}.eGUBIq_assignSelect{border:1px solid var(--dsw-alias-border-l2,#e5e7eb);background:var(--dsw-alias-bg-layer-1,#fff);color:var(--dsw-alias-label-primary,#1f2328);font:inherit;border-radius:6px;padding:3px 6px;font-size:12px;line-height:18px}.eGUBIq_groupHint{color:var(--dsw-alias-label-tertiary,#8b93a1);font-size:11px}.eGUBIq_sectAction{color:var(--dsw-alias-label-secondary,#6b7280);align-items:center;gap:8px;margin:14px 2px 8px;font-size:12px;font-weight:600;display:flex}.eGUBIq_backupGrid{grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:12px;display:grid}.eGUBIq_backupCard{background:var(--dsw-alias-bg-layer-1,#fff);border:1px solid var(--dsw-alias-border-l2,#e5e7eb);border-radius:12px;flex-direction:column;gap:10px;padding:16px;display:flex}.eGUBIq_backupCard h3{margin:0;font-size:14px}.eGUBIq_backupCard p{color:var(--dsw-alias-label-secondary,#6b7280);margin:0;font-size:12px;line-height:18px}.eGUBIq_backupActions{flex-wrap:wrap;gap:8px;display:flex;position:relative}.eGUBIq_hiddenFile{opacity:0;pointer-events:none;width:1px;height:1px;position:absolute}.eGUBIq_backupInput{box-sizing:border-box;width:100%}.eGUBIq_backupCheck{cursor:pointer;align-items:center;gap:6px;font-size:12px;display:flex}.eGUBIq_backupWarn{margin:0;font-size:12px;line-height:18px;color:var(--dsw-alias-state-warn-primary,#b45309)!important}.eGUBIq_backupMessage{color:var(--dsw-alias-label-secondary,#6b7280);grid-column:1/-1;font-size:12px}.eGUBIq_backupCheckList{flex-direction:column;gap:6px;max-height:260px;margin:10px 0 4px;padding-right:4px;display:flex;overflow-y:auto}.eGUBIq_backupCheckList .eGUBIq_backupCheck{justify-content:space-between;gap:8px}.eGUBIq_diagPage{flex-direction:column;gap:12px;height:100%;min-height:0;display:flex;overflow-y:auto}.eGUBIq_diagSummary{background:var(--dsw-alias-bg-layer-1,#fff);border:1px solid var(--dsw-alias-border-l2,#e5e7eb);border-radius:12px;flex-wrap:wrap;align-items:center;gap:12px;padding:10px 14px;font-size:12px;display:flex}.eGUBIq_diagSummaryItem{color:var(--dsw-alias-label-secondary,#6b7280);white-space:nowrap;align-items:center;gap:6px;display:inline-flex}.eGUBIq_diagSummaryMeta{color:var(--dsw-alias-label-tertiary,#9ca3af);text-overflow:ellipsis;white-space:nowrap;max-width:320px;font-family:ui-monospace,Menlo,monospace;font-size:11px;overflow:hidden}.eGUBIq_diagSection{background:var(--dsw-alias-bg-layer-1,#fff);border:1px solid var(--dsw-alias-border-l2,#e5e7eb);border-radius:12px;flex-direction:column;gap:8px;padding:12px 14px;display:flex}.eGUBIq_diagSection h3{color:var(--dsw-alias-label-primary,#1f2328);margin:0;font-size:13px;font-weight:600}.eGUBIq_diagCount{color:var(--dsw-alias-label-tertiary,#9ca3af);font-size:11px;font-weight:400}.eGUBIq_diagEmpty{color:var(--dsw-alias-label-secondary,#9ca3af);padding:8px 0;font-size:12px}.eGUBIq_diagBundle{border-top:1px solid var(--dsw-alias-border-l2,#f0f1f3);flex-direction:column;gap:6px;padding-top:8px;display:flex}.eGUBIq_diagBundle:first-of-type{border-top:none;padding-top:0}.eGUBIq_diagRow{flex-wrap:wrap;align-items:center;gap:8px;min-width:0;font-size:12px;line-height:18px;display:flex}.eGUBIq_diagMeta{align-items:baseline;gap:8px;min-width:0;font-size:12px;display:flex}.eGUBIq_diagKey{color:var(--dsw-alias-label-tertiary,#9ca3af);flex-shrink:0;min-width:64px;font-size:11px}.eGUBIq_diagVal{color:var(--dsw-alias-label-primary,#1f2328);overflow-wrap:anywhere;min-width:0;font-family:ui-monospace,Menlo,monospace;font-size:12px;font-weight:500}.eGUBIq_diagIndex{background:var(--dsw-alias-bg-layer-2,#f3f4f6);min-width:18px;height:18px;color:var(--dsw-alias-label-secondary,#6b7280);border-radius:9px;flex-shrink:0;justify-content:center;align-items:center;font-size:11px;font-weight:600;display:inline-flex}.eGUBIq_diagArrow{color:var(--dsw-alias-label-tertiary,#9ca3af);flex-shrink:0;font-size:12px}.eGUBIq_diagBadgeOfficial{background:var(--dsw-alias-brand-primary,#4f6ef7);color:#fff;border-radius:9px;flex-shrink:0;align-items:center;height:18px;padding:0 8px;font-size:11px;font-weight:600;display:inline-flex}.eGUBIq_diagBadgeCommunity{background:var(--dsw-alias-bg-layer-2,#f3f4f6);height:18px;color:var(--dsw-alias-label-secondary,#6b7280);border-radius:9px;flex-shrink:0;align-items:center;padding:0 8px;font-size:11px;display:inline-flex}.eGUBIq_diagBadgeShadow{background:var(--dsw-alias-state-error-primary,#dc2626);color:#fff;border-radius:9px;flex-shrink:0;align-items:center;height:18px;padding:0 8px;font-size:11px;font-weight:600;display:inline-flex}.eGUBIq_diagBadgeWarn{background:var(--dsw-alias-state-warn-primary,#b45309);color:#fff;white-space:nowrap;border-radius:9px;flex-shrink:0;align-items:center;height:18px;padding:0 8px;font-size:11px;font-weight:600;display:inline-flex}.eGUBIq_diagBadgeInfo{background:var(--dsw-alias-bg-layer-2,#f3f4f6);height:18px;color:var(--dsw-alias-label-secondary,#6b7280);white-space:nowrap;border-radius:9px;flex-shrink:0;align-items:center;padding:0 8px;font-size:11px;display:inline-flex}.eGUBIq_diagList{flex-direction:column;gap:6px;display:flex}.eGUBIq_sectionOverview{color:var(--dsw-alias-label-tertiary,#8b93a1);text-overflow:ellipsis;white-space:nowrap;max-width:100%;padding:2px 0 6px;font-size:12px;line-height:18px;overflow:hidden}.eGUBIq_diagAlert{color:var(--dsw-alias-state-warn-primary,#b45309)}.eGUBIq_ovRow{background:var(--dsw-alias-bg-layer-2,#f7f8fa);border-radius:8px;flex-wrap:wrap;align-items:center;gap:8px;min-width:0;padding:6px 10px;font-size:12px;line-height:18px;display:flex}.eGUBIq_ovArrow{color:var(--dsw-alias-label-tertiary,#9ca3af);flex-shrink:0;font-size:12px}.eGUBIq_ovByTag{background:var(--dsw-alias-brand-primary,#4f6ef7);color:#fff;text-overflow:ellipsis;white-space:nowrap;border-radius:9px;flex-shrink:0;align-items:center;max-width:260px;height:18px;padding:0 8px;font-size:11px;font-weight:600;display:inline-flex;overflow:hidden}.eGUBIq_ovFrom{color:var(--dsw-alias-label-secondary,#6b7280);text-overflow:ellipsis;white-space:nowrap;min-width:0;font-size:12px;overflow:hidden}.eGUBIq_orphRow{background:var(--dsw-alias-bg-layer-2,#f7f8fa);border-radius:8px;flex-wrap:wrap;align-items:center;gap:8px;min-width:0;padding:6px 10px;font-size:12px;line-height:18px;display:flex}.eGUBIq_orphBadge{background:var(--dsw-alias-state-warn-primary,#b45309);color:#fff;white-space:nowrap;border-radius:9px;flex-shrink:0;align-items:center;height:18px;padding:0 8px;font-size:11px;font-weight:600;display:inline-flex}.eGUBIq_dragHandle{width:20px;height:20px;color:var(--dsw-alias-label-tertiary,#9ca3af);cursor:grab;-webkit-user-select:none;user-select:none;flex-shrink:0;justify-content:center;align-items:center;font-size:12px;line-height:20px;display:inline-flex}.eGUBIq_dragOver{outline:2px dashed var(--dsw-alias-brand-primary,#4f6ef7);outline-offset:2px;background:var(--dsw-alias-bg-layer-2,#f0f2f8);border-radius:8px}.eGUBIq_dragging{opacity:.45;background:var(--dsw-alias-bg-layer-2,#f3f4f6)}.eGUBIq_collapseHead{font:inherit;color:var(--dsw-alias-label-primary,#1f2328);cursor:pointer;text-align:left;background:0 0;border:none;align-items:center;gap:8px;width:100%;padding:0;font-size:13px;font-weight:600;display:flex}.eGUBIq_collapseIcon{color:var(--dsw-alias-label-secondary,#6b7280);flex-shrink:0;display:inline-flex}.eGUBIq_collapseTitle{flex:1;min-width:0}.eGUBIq_collapseBody{border-top:1px solid var(--dsw-alias-border-l2,#f0f1f3);overflow-wrap:anywhere;flex-direction:column;gap:10px;min-width:0;margin-top:8px;padding-top:10px;display:flex}.eGUBIq_panelNote{color:var(--dsw-alias-label-secondary,#6b7280);margin:0;font-size:12px;line-height:18px}.eGUBIq_fixFallback{flex-direction:column;gap:6px;margin:8px 0;display:flex}.eGUBIq_fixFallbackText{box-sizing:border-box;width:100%;color:var(--dsw-alias-label-primary,#1f2328);background:var(--dsw-alias-bg-layer-2,#f3f4f6);border:1px solid var(--dsw-alias-border-l2,#e5e7eb);resize:vertical;white-space:pre-wrap;word-break:break-all;border-radius:6px;padding:8px 10px;font-family:ui-monospace,Menlo,monospace;font-size:11px;line-height:16px}.eGUBIq_setCard{border:1px solid var(--dsw-alias-border-l2,#e5e7eb);background:var(--dsw-alias-bg-layer-3,#fff);border-radius:12px;list-style:none;transition:border-color .16s,background .16s}.eGUBIq_setCard:hover{border-color:var(--dsw-alias-label-dimmed,#c8ccd4)}.eGUBIq_setCardOpen{background:var(--dsw-alias-bg-layer-2,#f7f8fa);border-color:var(--dsw-alias-label-dimmed,#c8ccd4)}.eGUBIq_setHeader{-webkit-appearance:none;appearance:none;width:100%;font:inherit;color:inherit;text-align:left;cursor:pointer;background:0 0;border:0;border-radius:12px;align-items:center;gap:12px;padding:14px 16px;display:flex}.eGUBIq_setHeader:focus-visible{outline:2px solid var(--dsw-alias-brand-primary,#4f6ef7);outline-offset:-2px}.eGUBIq_setHeadText{flex-direction:column;flex:1;gap:4px;min-width:0;display:flex}.eGUBIq_setName{color:var(--dsw-alias-label-primary,#1f2328);font-size:15px;font-weight:600;line-height:1.4}.eGUBIq_setDesc{color:var(--dsw-alias-label-tertiary,#8b93a1);font-size:13px;line-height:1.5}.eGUBIq_setChevron{color:var(--dsw-alias-label-tertiary,#8b93a1);flex:none;transition:transform .16s;display:inline-flex}.eGUBIq_setChevronOpen{transform:rotate(180deg)}.eGUBIq_setBody{border-top:1px solid var(--dsw-alias-border-l2,#e5e7eb);margin:0 16px;padding-bottom:8px}.eGUBIq_setRow{align-items:center;gap:12px;padding:12px 0;display:flex}.eGUBIq_setRow+.eGUBIq_setRow{border-top:1px solid var(--dsw-alias-border-l2,#e5e7eb)}.eGUBIq_setLabelBox{flex-direction:column;flex:1;gap:3px;min-width:0;display:flex}.eGUBIq_setLabel{font-size:13px;line-height:20px}.eGUBIq_setHint{color:var(--dsw-alias-label-tertiary,#8b93a1);font-size:12px;line-height:18px}.eGUBIq_setConfirm{border-top:1px solid var(--dsw-alias-border-l2,#e5e7eb);flex-direction:column;gap:8px;padding:12px 0 4px;display:flex}.eGUBIq_setCheck{cursor:pointer;align-items:center;gap:8px;font-size:12px;line-height:18px;display:flex}.eGUBIq_setActions{border-top:1px solid var(--dsw-alias-border-l2,#e5e7eb);justify-content:flex-end;align-items:center;gap:8px;padding:12px 0 4px;display:flex}.eGUBIq_setDanger{color:var(--dsw-alias-state-error-primary,#dc2626)}.eGUBIq_setSeg{border:1px solid var(--dsw-alias-border-l2,#e5e7eb);border-radius:8px;flex-shrink:0;gap:2px;padding:2px;display:inline-flex}.eGUBIq_setSegBtn{font:inherit;color:var(--dsw-alias-label-secondary,#6b7280);cursor:pointer;background:0 0;border:none;border-radius:6px;padding:3px 10px;font-size:12px;line-height:18px}.eGUBIq_setSegBtn:disabled{cursor:default;opacity:.5}.eGUBIq_setSegOn{background:var(--dsw-alias-bg-layer-2,#eef0f4);color:var(--dsw-alias-label-primary,#1f2328);font-weight:600}.eGUBIq_setBetaTag{background:var(--dsw-alias-bg-module-platform,#eef0f4);color:var(--dsw-alias-label-secondary,#6b7280);border-radius:9px;margin-left:6px;padding:0 6px;font-size:11px;font-weight:600;line-height:17px}";
1585
+ const css = ".eGUBIq_root{min-width:0;height:100%;color:var(--dsw-alias-label-primary,#1f2328);flex-direction:column;display:flex;position:relative;container-type:inline-size}.eGUBIq_head{flex-direction:column;gap:12px;padding:4px 4px 6px;display:flex}.eGUBIq_title{margin:0;font-size:16px;font-weight:500;line-height:24px}.eGUBIq_sub{color:var(--dsw-alias-label-tertiary,#8b93a1);align-items:center;gap:8px;margin:0;font-size:12px;line-height:18px;display:flex}.eGUBIq_submitLink{color:var(--dsw-alias-label-tertiary,#8b93a1);white-space:nowrap;font-size:11px;line-height:18px;text-decoration:none}.eGUBIq_submitLink:hover{color:var(--dsw-alias-brand-primary,#4f6ef7);text-decoration:underline}.eGUBIq_tabs{border-bottom:1px solid var(--dsw-alias-border-l2,#e5e7eb);align-items:flex-end;gap:2px;display:flex}.eGUBIq_tab{font:inherit;color:var(--dsw-alias-label-secondary,#6b7280);cursor:pointer;white-space:nowrap;background:0 0;border:none;border-bottom:2px solid #0000;padding:7px 12px;font-size:13px}.eGUBIq_tab.eGUBIq_on{color:var(--dsw-alias-brand-primary,#4f6ef7);border-bottom-color:var(--dsw-alias-brand-primary,#4f6ef7);font-weight:600}.eGUBIq_subTabs{align-items:flex-end;gap:2px;margin:-4px 0 4px;display:flex}.eGUBIq_banner{background:var(--dsw-alias-bg-layer-2,#fdf3e3);border:1px solid var(--dsw-alias-border-l2,#f3e3c3);border-radius:8px;align-items:center;gap:8px;margin:0;padding:8px 12px;font-size:12px;display:flex}.eGUBIq_bannerIcon{color:var(--dsw-alias-label-secondary,#6b7280);flex-shrink:0}.eGUBIq_bannerHint{color:var(--dsw-alias-label-tertiary,#8b93a1);cursor:help;display:inline-flex}.eGUBIq_body{flex:1;padding:12px 4px 24px;overflow-x:hidden;overflow-y:auto}.eGUBIq_stickyHead{z-index:5;background:var(--dsw-alias-bg-layer-2,#f7f8fa);position:sticky;top:-1px}.eGUBIq_stickyHead:before{content:\"\";background:inherit;pointer-events:none;height:14px;position:absolute;bottom:100%;left:0;right:0}.eGUBIq_cats{margin:0 -4px 2px;padding:12px 4px 4px}.eGUBIq_catsRow{align-items:flex-start;gap:8px;display:flex;position:relative}.eGUBIq_star{color:var(--dsw-alias-label-secondary,#9ca3af);white-space:nowrap;flex:none;font-size:11px}.eGUBIq_top{z-index:20;display:inline-flex;position:absolute;bottom:18px;right:18px}.eGUBIq_topBtn{border-radius:99px;width:38px;height:38px;padding:0}.eGUBIq_tag{border:1px solid var(--dsw-alias-border-l3,#d9dde3);color:var(--dsw-alias-label-secondary,#6b7280);border-radius:4px;flex-shrink:0;padding:1px 6px;font-size:11px;line-height:16px}.eGUBIq_okState{color:var(--dsw-alias-state-success-primary,#16a34a);white-space:nowrap;font-size:12px;font-weight:600}.eGUBIq_catsWrap{flex-wrap:wrap;flex:1;align-items:center;gap:6px;min-width:0;display:flex}.eGUBIq_catsCollapsed{max-height:62px;overflow:hidden}.eGUBIq_catsToggle.eGUBIq_catsToggle{height:26px;min-height:26px;color:var(--dsw-alias-label-secondary,#6b7280);padding:0 6px}.eGUBIq_shots{-webkit-overflow-scrolling:touch;scrollbar-width:thin;gap:8px;margin:6px 0 8px;padding:2px 0 6px;display:flex;overflow-x:auto}.eGUBIq_shot{object-fit:cover;border:1px solid var(--dsw-alias-border-default,#e5e7eb);background:var(--dsw-alias-bg-layer-2,#f3f4f6);cursor:pointer;border-radius:8px;flex:none;width:220px;height:150px}.eGUBIq_cardShots{-webkit-overflow-scrolling:touch;scrollbar-width:thin;gap:6px;margin:0 0 6px;padding:0 0 2px;display:flex;overflow-x:auto}.eGUBIq_cardShot{object-fit:contain;border:1px solid var(--dsw-alias-border-default,#e5e7eb);background:var(--dsw-alias-bg-layer-2,#f3f4f6);cursor:pointer;border-radius:8px;flex:none;width:132px;height:88px;display:block}.eGUBIq_lightbox{z-index:10000;cursor:zoom-out;background:#000000d9;justify-content:center;align-items:center;display:flex;position:fixed;top:0;bottom:0;left:0;right:0}.eGUBIq_lightboxImg{object-fit:contain;cursor:default;border-radius:4px;max-width:90vw;max-height:85vh}.eGUBIq_lightboxClose{color:#fff;cursor:pointer;background:#ffffff1f;border:none;border-radius:99px;place-items:center;width:36px;height:36px;font-size:22px;line-height:1;display:grid;position:absolute;top:16px;right:16px}.eGUBIq_lightboxClose:hover{background:#ffffff38}.eGUBIq_lightboxNav{color:#fff;cursor:pointer;background:#ffffff1f;border:none;border-radius:99px;place-items:center;width:44px;height:44px;display:grid;position:absolute;top:50%;transform:translateY(-50%)}.eGUBIq_lightboxNav:hover{background:#ffffff38}.eGUBIq_lightboxPrev{left:16px}.eGUBIq_lightboxNext{right:16px}.eGUBIq_lightboxDots{gap:8px;display:flex;position:absolute;bottom:20px;left:50%;transform:translate(-50%)}.eGUBIq_lightboxDot{cursor:pointer;background:#fff6;border-radius:99px;width:7px;height:7px}.eGUBIq_lightboxDotOn{background:#fff}.eGUBIq_cmd{background:var(--dsw-alias-bg-layer-2,#f3f4f6);word-break:break-all;border-radius:6px;margin:8px 0 0;padding:8px 10px;font-family:ui-monospace,Menlo,monospace;font-size:11px;line-height:18px}.eGUBIq_warnLine{color:var(--dsw-alias-state-warn-primary,#b45309);flex-wrap:wrap;align-items:center;gap:4px;margin:0;font-size:12px;font-weight:600;line-height:18px;display:flex}.eGUBIq_modalNote{color:var(--dsw-alias-label-tertiary,#8b93a1);align-items:center;gap:4px;margin:12px 0 0;font-size:12px;line-height:18px;display:flex}.eGUBIq_grid{grid-template-columns:repeat(2,minmax(0,1fr));align-items:start;gap:10px;display:grid}.eGUBIq_masonry{align-items:flex-start;gap:10px;display:flex}.eGUBIq_masonryCol{flex-direction:column;flex:1;gap:10px;min-width:0;display:flex}.eGUBIq_masonry>.eGUBIq_masonryCol>*{align-self:stretch;min-width:0}@media (max-width:680px){.eGUBIq_masonry{flex-direction:column}.eGUBIq_masonryCol{width:100%}.eGUBIq_grid{grid-template-columns:minmax(0,1fr)}}.eGUBIq_swatches{border:1px solid var(--dsw-alias-border-l2,#e5e7eb);border-radius:8px;gap:0;height:34px;display:flex;overflow:hidden}.eGUBIq_themesGrid{margin-bottom:12px}.eGUBIq_swatches i{flex:1}.eGUBIq_themeToolbar{grid-template-columns:minmax(0,1fr) auto;align-items:center;gap:8px;padding:0 4px 12px;display:grid}.eGUBIq_themeSearch{box-sizing:border-box;width:100%;min-width:0}.eGUBIq_themeToolbarActions{justify-content:flex-end;align-items:center;gap:8px;display:flex}.eGUBIq_themeFullscreenBtn.eGUBIq_themeFullscreenBtn{width:28px;min-width:28px;padding:0}.eGUBIq_themeResultBar{min-height:24px;color:var(--dsw-alias-label-tertiary,#8b93a1);align-items:center;padding:0 4px 8px;font-size:12px;line-height:18px;display:flex}.eGUBIq_themeGallery{grid-template-columns:repeat(4,minmax(0,1fr));align-items:stretch;gap:10px;display:grid}.eGUBIq_themeCard{border:1px solid var(--dsw-alias-border-l2,#e5e7eb);background:var(--dsw-alias-bg-layer-1,#fff);border-radius:8px;flex-direction:column;min-width:0;transition:border-color .16s cubic-bezier(.16,1,.3,1),box-shadow .16s cubic-bezier(.16,1,.3,1),transform .16s cubic-bezier(.16,1,.3,1);display:flex;overflow:hidden}.eGUBIq_themeCard:hover{border-color:var(--dsw-alias-border-l3,#d9dde3);box-shadow:var(--dsw-shadow-lv1,0 4px 12px #1f232814);transform:translateY(-1px)}.eGUBIq_themeCover{aspect-ratio:16/10;border:0;border-bottom:1px solid var(--dsw-alias-border-l2,#e5e7eb);background:var(--dsw-alias-bg-layer-2,#f3f4f6);width:100%;color:var(--dsw-alias-label-secondary,#6b7280);cursor:zoom-in;border-radius:0;padding:0;display:block;position:relative;overflow:hidden}.eGUBIq_themeCover img{object-fit:contain;background:var(--dsw-alias-bg-layer-2,#f3f4f6);width:100%;height:100%;transition:transform .18s cubic-bezier(.16,1,.3,1);display:block}.eGUBIq_themeCover:hover img{transform:scale(1.012)}.eGUBIq_themeCover:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,#4f6ef7);outline-offset:-3px}.eGUBIq_themeCoverEmpty{cursor:default;color:var(--dsw-alias-label-tertiary,#8b93a1);flex-direction:column;justify-content:center;align-items:center;gap:8px;font-size:12px;line-height:18px;display:flex}.eGUBIq_themePreviewAction,.eGUBIq_themePreviewCount{color:#fff;-webkit-backdrop-filter:blur(8px);background:#14181fc7;border:1px solid #ffffff57;border-radius:4px;align-items:center;height:24px;padding:0 8px;font-size:11px;line-height:16px;display:inline-flex;position:absolute;bottom:8px}.eGUBIq_themePreviewAction{gap:4px;right:8px}.eGUBIq_themePreviewCount{left:8px}.eGUBIq_themeCardBody{flex-direction:column;flex:1;gap:8px;padding:12px;display:flex}.eGUBIq_themeCardHead{align-items:flex-start;gap:8px;min-width:0;display:flex}.eGUBIq_themeIdentity{flex:1;min-width:0}.eGUBIq_themeStatus,.eGUBIq_themeStatusMuted{white-space:nowrap;border-radius:4px;flex:none;align-items:center;min-height:22px;padding:0 8px;font-size:11px;font-weight:600;display:inline-flex}.eGUBIq_themeStatus{background:var(--dsw-alias-state-success-tertiary,#16a34a1a);color:var(--dsw-alias-state-success-primary,#15803d)}.eGUBIq_themeStatusMuted{background:var(--dsw-alias-bg-layer-2,#f3f4f6);color:var(--dsw-alias-label-secondary,#6b7280)}.eGUBIq_themeDescription{min-height:36px;color:var(--dsw-alias-label-tertiary,#8b93a1);-webkit-line-clamp:2;-webkit-box-orient:vertical;margin:0;font-size:12px;line-height:18px;display:-webkit-box;overflow:hidden}.eGUBIq_themeCardFooter{justify-content:space-between;align-items:center;gap:8px;margin-top:auto;padding-top:4px;display:flex}.eGUBIq_themeLifecycle{min-width:0;color:var(--dsw-alias-label-tertiary,#8b93a1);text-overflow:ellipsis;white-space:nowrap;font-size:11px;line-height:18px;overflow:hidden}.eGUBIq_themeActions{flex-wrap:wrap;justify-content:flex-end;align-items:center;gap:8px;margin-left:auto;display:flex}@container (width<=900px){.eGUBIq_themeGallery{grid-template-columns:repeat(3,minmax(0,1fr))}}@container (width<=680px){.eGUBIq_themeGallery{grid-template-columns:repeat(2,minmax(0,1fr))}}@container (width<=460px){.eGUBIq_themeGallery{grid-template-columns:minmax(0,1fr)}}@container (width<=420px){.eGUBIq_sub{grid-template-columns:minmax(0,1fr) auto;align-items:start;gap:2px 8px;display:grid}.eGUBIq_sub>span:first-child{grid-area:1/1}.eGUBIq_sub>.eGUBIq_grow{display:none}.eGUBIq_submitLink{grid-area:2/1}.eGUBIq_exportLogBtn{flex-shrink:0;grid-area:1/2/span 2}.eGUBIq_themeToolbar{grid-template-columns:minmax(0,1fr)}.eGUBIq_themeCardHead{flex-wrap:wrap}.eGUBIq_themeStatus,.eGUBIq_themeStatusMuted{order:3}}@container (width<=280px){.eGUBIq_themeCardFooter{flex-direction:column;align-items:flex-start}.eGUBIq_themeActions{justify-content:flex-start;width:100%;margin-left:0}}@media (max-width:560px){[role=dialog]:has([data-dsh-market-root])>nav{display:none}[role=dialog]:has([data-dsh-market-root])>div{flex:100%;width:100%;min-width:0}}[role=dialog]:has([data-dsh-market-fullscreen=true]){border-radius:0;width:100vw;max-width:none;height:100vh;max-height:none;position:fixed;top:0;bottom:0;left:0;right:0}@media (prefers-reduced-motion:reduce){.eGUBIq_themeCard,.eGUBIq_themeCover img{transition:none}.eGUBIq_themeCard:hover{transform:none}}.eGUBIq_card{background:var(--dsw-alias-bg-layer-1,#fff);border:1px solid var(--dsw-alias-border-l2,#e5e7eb);border-radius:12px;flex-direction:column;align-self:start;gap:12px;padding:12px 14px;display:flex}.eGUBIq_row1{align-items:flex-start;gap:10px;min-width:0;display:flex}.eGUBIq_cardAction{flex-shrink:0;align-items:center;display:inline-flex}.eGUBIq_installBtn.eGUBIq_installBtn{min-width:64px}.eGUBIq_av{color:#fff;object-fit:cover;background:var(--dsw-alias-bg-layer-2,#f3f4f6);border-radius:50%;flex-shrink:0;place-items:center;width:16px;height:16px;font-size:9px;font-weight:700;display:grid}.eGUBIq_nm{text-overflow:ellipsis;white-space:nowrap;font-size:15px;font-weight:600;line-height:22px;overflow:hidden}.eGUBIq_nmLink{color:inherit;text-decoration:none;display:block}.eGUBIq_nmLink:hover{color:var(--dsw-alias-brand-primary,#4f6ef7);text-decoration:underline}.eGUBIq_repoMark{color:var(--dsw-alias-label-tertiary,#8b93a1);vertical-align:-1px;flex-shrink:0;margin-left:5px}.eGUBIq_nmLink:hover .eGUBIq_repoMark{color:var(--dsw-alias-brand-primary,#4f6ef7)}.eGUBIq_byline{flex-wrap:wrap;align-items:center;gap:6px;min-width:0;margin-top:2px;display:flex}.eGUBIq_meta{color:var(--dsw-alias-label-secondary,#9ca3af);margin-top:2px;font-size:11px}.eGUBIq_metaInline{color:var(--dsw-alias-label-secondary,#9ca3af);font-size:11px}.eGUBIq_owner{color:var(--dsw-alias-label-secondary,#9ca3af);text-overflow:ellipsis;white-space:nowrap;flex:0 auto;min-width:44px;font-size:11px;overflow:hidden}.eGUBIq_desc{color:var(--dsw-alias-label-tertiary,#8b93a1);margin:0;font-size:12px;line-height:18px}.eGUBIq_descClamp{-webkit-line-clamp:5;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.eGUBIq_descToggle{width:20px;height:16px;color:var(--dsw-alias-label-tertiary,#8b93a1);cursor:pointer;background:0 0;border:none;justify-content:center;align-items:center;margin-top:2px;padding:0;display:flex}.eGUBIq_descToggle:hover{color:var(--dsw-alias-brand-primary,#4f6ef7)}.eGUBIq_foot{flex-wrap:wrap;align-items:center;gap:8px;display:flex}.eGUBIq_foot .eGUBIq_metaInline,.eGUBIq_foot .eGUBIq_src{white-space:nowrap}.eGUBIq_grow{flex:1}.eGUBIq_titleRow{align-items:center;gap:10px;display:flex}.eGUBIq_version{color:var(--dsw-alias-label-tertiary,#8b93a1);font-variant-numeric:tabular-nums;flex-shrink:0;font-size:12px;line-height:20px}.eGUBIq_repoLink{color:var(--dsw-alias-label-tertiary,#8b93a1);flex-shrink:0;font-size:12px;line-height:20px;text-decoration:none}.eGUBIq_repoLink:hover{color:var(--dsw-alias-brand-primary,#4f6ef7)}.eGUBIq_descTight{min-height:0}.eGUBIq_src{color:var(--dsw-alias-label-secondary,#9ca3af);font-size:11px;text-decoration:none}.eGUBIq_src:hover{color:var(--dsw-alias-brand-primary,#4f6ef7)}.eGUBIq_dot{vertical-align:2px;margin-left:5px}.eGUBIq_act{flex-wrap:wrap;align-items:center;gap:6px;margin-top:6px;font-size:11px;display:flex}.eGUBIq_actLive{color:var(--dsw-alias-state-success-primary,#16a34a);align-items:center;gap:4px;font-weight:600;display:inline-flex}.eGUBIq_actWarn{color:var(--dsw-alias-state-warn-primary,#b45309);align-items:center;gap:4px;font-weight:600;display:inline-flex}.eGUBIq_actBroken{color:var(--dsw-alias-state-error-primary,#dc2626);align-items:center;gap:4px;font-weight:600;display:inline-flex}.eGUBIq_actWhy{color:var(--dsw-alias-label-secondary,#6b7280);margin-top:2px}.eGUBIq_loading{color:var(--dsw-alias-label-secondary,#9ca3af);flex-direction:column;align-items:center;gap:12px;padding:48px;font-size:13px;display:flex}.eGUBIq_spin{color:var(--dsw-alias-brand-primary,#4f6ef7);flex-shrink:0;animation:.8s linear infinite eGUBIq_sp;display:inline-flex}.eGUBIq_logoMark{color:var(--dsw-alias-brand-primary,#4f6ef7);flex-shrink:0;display:inline-flex}.eGUBIq_logoPlug{transform-box:fill-box;transform-origin:50%;animation:1.5s cubic-bezier(.4,0,.2,1) infinite eGUBIq_dshmPlug}@keyframes eGUBIq_dshmPlug{0%,12%{transform:rotate(9deg)}45%,62%{transform:translate(-1.28px,1.27px)rotate(0)}95%,to{transform:rotate(9deg)}}@media (prefers-reduced-motion:reduce){.eGUBIq_logoPlug,.eGUBIq_spin{animation:1.5s ease-in-out infinite eGUBIq_dshmPlugFade}}@keyframes eGUBIq_dshmPlugFade{0%,to{opacity:1}50%{opacity:.35}}@keyframes eGUBIq_sp{to{transform:rotate(360deg)}}.eGUBIq_progress{background:var(--dsw-alias-bg-layer-2,#f3f4f6);border:1px solid var(--dsw-alias-border-l2,#e5e7eb);color:var(--dsw-alias-label-secondary,#6b7280);border-radius:8px;flex-wrap:wrap;align-items:center;gap:9px;margin:0;padding:8px 12px;font-size:12px;display:flex}.eGUBIq_bar{background:var(--dsw-alias-border-l1,#e5e7eb);border-radius:99px;width:100%;height:4px;overflow:hidden}.eGUBIq_barFill{background:var(--dsw-alias-brand-primary,#4f6ef7);border-radius:99px;height:100%;transition:width .6s}.eGUBIq_barWave{width:30%;animation:1.2s ease-in-out infinite eGUBIq_dshmSlide}@keyframes eGUBIq_dshmSlide{0%{margin-left:-30%}to{margin-left:100%}}.eGUBIq_irow .eGUBIq_progress{margin-top:8px}.eGUBIq_progress code{text-overflow:ellipsis;white-space:nowrap;font-family:ui-monospace,Menlo,monospace;font-size:11px;overflow:hidden}.eGUBIq_empty{color:var(--dsw-alias-label-secondary,#9ca3af);text-align:center;padding:32px;font-size:13px}.eGUBIq_err{color:var(--dsw-alias-state-error-primary,#dc2626);white-space:pre-wrap;word-break:break-all;margin:8px 0;font-size:12px}.eGUBIq_cardBlocked{border-color:var(--dsw-alias-state-error-primary,#dc2626)}.eGUBIq_conflictHead{align-items:flex-start;gap:8px;display:flex}.eGUBIq_conflictIcon{color:var(--dsw-alias-state-error-primary,#dc2626);flex-shrink:0;margin-top:1px}.eGUBIq_conflictTitle{color:var(--dsw-alias-state-error-primary,#dc2626);font-size:13px;font-weight:600;line-height:18px}.eGUBIq_conflictBody{margin:0;font-size:12px;line-height:19px}.eGUBIq_roster{background:var(--dsw-alias-border-l2,#e5e7eb);border:1px solid var(--dsw-alias-border-l2,#e5e7eb);border-radius:8px;flex-direction:column;gap:1px;display:flex;overflow:hidden}.eGUBIq_rosterRow{background:var(--dsw-alias-bg-layer-1,#fff);align-items:center;gap:8px;padding:7px 10px;display:flex}.eGUBIq_rosterMain{flex-direction:column;min-width:0;display:flex}.eGUBIq_rosterName{text-overflow:ellipsis;white-space:nowrap;min-width:0;font-size:12px;font-weight:600;overflow:hidden}.eGUBIq_rosterAuthor{color:var(--dsw-alias-label-secondary,#9ca3af);text-overflow:ellipsis;white-space:nowrap;font-size:10.5px;overflow:hidden}.eGUBIq_rosterTag{border-radius:4px;flex-shrink:0;margin-left:auto;padding:1px 6px;font-size:10.5px;font-weight:600}.eGUBIq_rosterTagKeep{color:var(--dsw-alias-state-success-primary,#16a34a);background:#16a34a1f}.eGUBIq_rosterTagDrop{color:var(--dsw-alias-state-error-primary,#dc2626);background:#dc26261f}.eGUBIq_rosterRowOut .eGUBIq_rosterName{text-decoration:line-through}.eGUBIq_rosterRowOut{opacity:.62}.eGUBIq_rosterSplit{background:var(--dsw-alias-border-l2,#e5e7eb);height:1px}.eGUBIq_reassure{color:var(--dsw-alias-label-secondary,#6b7280);align-items:center;gap:5px;margin:0;font-size:11.5px;line-height:17px;display:flex}.eGUBIq_reassureOk{color:var(--dsw-alias-state-success-primary,#16a34a);flex-shrink:0}.eGUBIq_conflictWhy{color:var(--dsw-alias-label-tertiary,#8b93a1);overflow-wrap:anywhere;margin-top:2px;font-family:ui-monospace,Menlo,monospace;font-size:11px;line-height:17px}.eGUBIq_conflictWhyText{margin-top:5px;font-family:-apple-system,BlinkMacSystemFont,PingFang SC,sans-serif}.eGUBIq_choices{flex-direction:column;gap:7px;display:flex}.eGUBIq_choice{text-align:left;font:inherit;cursor:pointer;background:var(--dsw-alias-bg-layer-1,#fff);border:1px solid var(--dsw-alias-border-l3,#d9dde3);border-radius:9px;align-items:flex-start;gap:9px;padding:9px 11px;display:flex}.eGUBIq_choice:has(input:disabled){cursor:default;opacity:.6}.eGUBIq_choiceOn{border-color:var(--dsw-alias-brand-primary,#4f6ef7);background:var(--dsw-alias-bg-layer-2,#f5f7ff)}.eGUBIq_choiceRadio{width:13px;height:13px;accent-color:var(--dsw-alias-brand-primary,#4f6ef7);flex-shrink:0;margin:2px 0 0}.eGUBIq_choiceMain{flex-direction:column;gap:3px;min-width:0;display:flex}.eGUBIq_choiceTitle{font-size:12px;font-weight:600;line-height:17px}.eGUBIq_choiceNote{color:var(--dsw-alias-label-tertiary,#8b93a1);font-size:11px;line-height:16px}.eGUBIq_choiceSafe{color:var(--dsw-alias-state-success-primary,#16a34a)}.eGUBIq_stateTag{white-space:nowrap;background:var(--dsw-alias-bg-layer-2,#f3f4f6);min-height:20px;color:var(--dsw-alias-label-secondary,#6b7280);border-radius:5px;flex-shrink:0;align-items:center;gap:5px;padding:1px 7px;font-size:11px;line-height:16px;display:inline-flex}.eGUBIq_stateTag[data-on=true]{color:var(--dsw-alias-state-success-primary,#16a34a);background:color-mix(in srgb, var(--dsw-alias-state-success-primary,#16a34a) 10%, transparent)}.eGUBIq_stateDot{background:var(--dsw-alias-label-tertiary,#8b93a1);border-radius:999px;flex:none;width:6px;height:6px}.eGUBIq_stateDot[data-on=true]{background:var(--dsw-alias-state-success-primary,#16a34a)}.eGUBIq_metaTag{text-overflow:ellipsis;white-space:nowrap;background:var(--dsw-alias-bg-layer-2,#f3f4f6);min-width:0;max-width:100%;min-height:20px;color:var(--dsw-alias-label-tertiary,#8b93a1);border-radius:5px;flex-shrink:1;padding:1px 7px;font-size:11px;line-height:18px;display:inline-block;overflow:hidden}.eGUBIq_metaTagOk{color:var(--dsw-alias-state-success-primary,#16a34a);background:color-mix(in srgb, var(--dsw-alias-state-success-primary,#16a34a) 10%, transparent)}.eGUBIq_nameLink{color:inherit;text-decoration:none}.eGUBIq_irowName{text-overflow:clip;align-items:baseline;gap:6px;min-width:0;display:flex;overflow:visible}.eGUBIq_irowNameText{text-overflow:ellipsis;white-space:nowrap;min-width:0;overflow:hidden}.eGUBIq_irowName>.eGUBIq_owner{flex:none}.eGUBIq_nameLink:hover{color:var(--dsw-alias-brand-primary,#4f6ef7);text-decoration:underline}.eGUBIq_opWrap{flex-shrink:0;display:inline-flex;position:relative}.eGUBIq_opEntry{font:inherit;cursor:pointer;white-space:nowrap;color:var(--dsw-alias-label-primary,#1f2328);background:var(--dsw-alias-bg-layer-1,#fff);border:1px solid var(--dsw-alias-border-l3,#d9dde3);border-radius:7px;align-items:center;gap:6px;padding:4px 10px;font-size:12px;display:inline-flex;position:relative}.eGUBIq_opEntryQuiet{color:var(--dsw-alias-label-secondary,#6b7280);background:0 0;border-color:#0000}.eGUBIq_opEntryAlert{border-color:var(--dsw-alias-state-error-primary,#dc2626);color:var(--dsw-alias-state-error-primary,#dc2626)}.eGUBIq_opDot{background:var(--dsw-alias-state-error-primary,#dc2626);border-radius:99px;width:8px;height:8px;position:absolute;top:-3px;right:-3px}.eGUBIq_opPanel{z-index:40;background:var(--dsw-alias-bg-layer-1,#fff);border:1px solid var(--dsw-alias-border-l3,#d9dde3);border-radius:12px;width:460px;max-width:86vw;max-height:70vh;position:absolute;top:calc(100% + 6px);right:0;overflow-y:auto;box-shadow:0 20px 52px #00000047}.eGUBIq_opHead{border-bottom:1px solid var(--dsw-alias-border-l2,#e5e7eb);align-items:center;gap:8px;padding:9px 14px;display:flex}.eGUBIq_opPanelTitle{font-size:12.5px;font-weight:600}.eGUBIq_opCloseBtn.eGUBIq_opCloseBtn{min-width:0;color:var(--dsw-alias-label-secondary,#6b7280);padding:0 6px}.eGUBIq_opAggregate{border-bottom:1px solid var(--dsw-alias-border-l2,#e5e7eb);background:var(--dsw-alias-bg-layer-2,#f7f8fa);padding:9px 14px}.eGUBIq_opAggregateTop{font-variant-numeric:tabular-nums;font-size:12px;font-weight:600}.eGUBIq_opAggregateHint{color:var(--dsw-alias-label-tertiary,#8b93a1);margin-top:4px;font-size:10.5px}.eGUBIq_opRow{border-bottom:1px solid var(--dsw-alias-border-l2,#e5e7eb);align-items:flex-start;gap:9px;padding:9px 14px;display:flex}.eGUBIq_opRow:last-child{border-bottom:none}.eGUBIq_opRowAlert{background:#dc26260f}.eGUBIq_opIcon{flex-shrink:0;place-items:center;width:14px;margin-top:1px;display:grid}.eGUBIq_opQueuedIcon{color:var(--dsw-alias-label-tertiary,#8b93a1);font-size:12px}.eGUBIq_opMain{flex-direction:column;flex:1;gap:3px;min-width:0;display:flex}.eGUBIq_opTop{align-items:baseline;gap:6px;min-width:0;display:flex}.eGUBIq_opVerb{color:var(--dsw-alias-label-secondary,#6b7280);flex-shrink:0;font-size:12px}.eGUBIq_opName{text-overflow:ellipsis;white-space:nowrap;font-size:12px;font-weight:600;overflow:hidden}.eGUBIq_opStatus{color:var(--dsw-alias-label-tertiary,#8b93a1);overflow-wrap:anywhere;font-size:10.5px;line-height:16px}.eGUBIq_opStatusBad{color:var(--dsw-alias-state-error-primary,#dc2626)}.eGUBIq_opActions{flex-shrink:0;align-items:center;gap:6px;margin-top:1px;display:flex}.eGUBIq_opDecision{border-top:1px dashed var(--dsw-alias-border-l2,#e5e7eb);flex-direction:column;gap:8px;margin-top:8px;padding-top:8px;display:flex}.eGUBIq_opDecisionFoot{align-items:center;gap:8px;display:flex}.eGUBIq_conflictDetailsToggle{font:inherit;cursor:pointer;color:var(--dsw-alias-label-tertiary,#8b93a1);background:0 0;border:none;align-items:center;gap:4px;padding:2px 0;font-size:11px;display:inline-flex}.eGUBIq_conflictDetailsToggle:hover{color:var(--dsw-alias-label-secondary,#6b7280)}.eGUBIq_opEmpty{text-align:center;color:var(--dsw-alias-label-secondary,#6b7280);padding:30px 14px;font-size:12px}.eGUBIq_opEmptyHint{color:var(--dsw-alias-label-tertiary,#8b93a1);margin-top:4px;font-size:11px}.eGUBIq_cardBlockedMark{font:inherit;cursor:pointer;color:var(--dsw-alias-state-error-primary,#dc2626);border:1px solid var(--dsw-alias-state-error-primary,#dc2626);background:#dc262614;border-radius:7px;align-items:center;gap:5px;padding:4px 9px;font-size:11px;display:inline-flex}.eGUBIq_dangerBtn.eGUBIq_dangerBtn{color:var(--dsw-alias-state-error-primary,#dc2626);border-color:var(--dsw-alias-state-error-primary,#dc2626)}.eGUBIq_dangerBtn.eGUBIq_dangerBtn:hover:not(:disabled){background:var(--dsw-alias-state-error-primary,#dc2626);color:#fff}.eGUBIq_dangerArmed.eGUBIq_dangerArmed{background:var(--dsw-alias-state-error-primary,#dc2626);border-color:var(--dsw-alias-state-error-primary,#dc2626);color:#fff}.eGUBIq_retryBtn{margin-top:4px}.eGUBIq_irow{background:var(--dsw-alias-bg-layer-1,#fff);border:1px solid var(--dsw-alias-border-l2,#e5e7eb);border-radius:10px;flex-direction:column;gap:10px;min-width:0;padding:12px 14px;display:flex}.eGUBIq_irowActions{flex-wrap:wrap;justify-content:flex-start;align-items:center;gap:8px;min-width:0;display:flex}.eGUBIq_irowTrailing{flex-wrap:nowrap;align-items:center;gap:8px;min-width:0;display:inline-flex}.eGUBIq_irowMissing{filter:grayscale();opacity:.5}.eGUBIq_irow>.eGUBIq_src,.eGUBIq_irow>.eGUBIq_owner,.eGUBIq_irow button{white-space:nowrap;flex-shrink:0}.eGUBIq_tabSearchRow{padding:0 4px 6px;display:flex}.eGUBIq_tabSearch{width:100%}.eGUBIq_spec{color:var(--dsw-alias-label-secondary,#9ca3af);overflow-wrap:anywhere;min-width:0;font-family:ui-monospace,Menlo,monospace;font-size:11px}.eGUBIq_specTag{white-space:nowrap;border-radius:4px;flex-shrink:0;align-items:center;height:16px;padding:0 5px;font-size:10px;font-weight:600;display:inline-flex}.eGUBIq_specTagGit{color:#0b7285;background:#12a3c41f}.eGUBIq_specTagFile{color:#b07d1b;background:#f0b42924}.eGUBIq_backupCheckList .eGUBIq_grow{white-space:nowrap;text-overflow:ellipsis;flex:70%;min-width:0;overflow:hidden}.eGUBIq_backupCheckList .eGUBIq_spec{text-align:right;white-space:nowrap;text-overflow:ellipsis;flex:0 30%;max-width:30%;overflow:hidden}.eGUBIq_staleAction{margin-top:8px}.eGUBIq_pct{color:var(--dsw-alias-label-secondary,#6b7280);flex-shrink:0;font-size:11px;font-weight:600}.eGUBIq_pager{flex-wrap:wrap;justify-content:space-between;align-items:center;gap:12px;margin:16px 0 4px;display:flex}.eGUBIq_pagerPages{flex-wrap:wrap;flex:1;justify-content:center;align-items:center;gap:6px;min-width:0;display:flex}.eGUBIq_pageEllipsis{color:var(--dsw-alias-label-secondary,#9ca3af);padding:0 2px;font-size:12px}.eGUBIq_pageInfo{color:var(--dsw-alias-label-secondary,#6b7280);white-space:nowrap;font-size:12px}.eGUBIq_depBadge{border:1px solid var(--dsw-alias-state-warn-primary,#b45309);color:var(--dsw-alias-state-warn-primary,#b45309);white-space:nowrap;border-radius:4px;flex-shrink:0;margin-left:6px;padding:1px 6px;font-size:11px;font-weight:600;line-height:16px}.eGUBIq_deprecate{color:var(--dsw-alias-state-warn-primary,#b45309);background:var(--dsw-alias-bg-layer-2,#fdf3e3);border:1px solid var(--dsw-alias-border-l2,#f3e3c3);border-radius:8px;margin:0;padding:8px 10px;font-size:12px;line-height:18px}.eGUBIq_deprecate a{color:var(--dsw-alias-state-warn-primary,#b45309);text-decoration:underline}.eGUBIq_deprecate .eGUBIq_src{margin-left:8px}.eGUBIq_depLine{flex-wrap:wrap;align-items:center;gap:8px;display:flex}.eGUBIq_switch{border:1px solid var(--dsw-alias-border-l2,#d9dde3);background:var(--dsw-alias-bg-layer-2,#e5e7eb);cursor:pointer;border-radius:99px;flex-shrink:0;width:38px;height:22px;padding:0;transition:background .15s,border-color .15s;position:relative}.eGUBIq_switchOn{background:var(--dsw-alias-state-success-primary,#16a34a);border-color:var(--dsw-alias-state-success-primary,#16a34a)}.eGUBIq_switchMixed{background:var(--dsw-alias-state-warn-primary,#b45309);border-color:var(--dsw-alias-state-warn-primary,#b45309)}.eGUBIq_switchKnob{background:#fff;border-radius:99px;width:16px;height:16px;transition:left .15s;position:absolute;top:2px;left:2px;box-shadow:0 1px 2px #00000040}.eGUBIq_switchOn .eGUBIq_switchKnob,.eGUBIq_switchMixed .eGUBIq_switchKnob{left:18px}.eGUBIq_switch:disabled{opacity:.5;cursor:default}.eGUBIq_viewBar{border:1px solid var(--dsw-alias-border-l2,#e5e7eb);border-radius:8px;align-items:center;gap:2px;width:fit-content;margin-bottom:12px;padding:2px;display:flex}.eGUBIq_viewBtn{font:inherit;color:var(--dsw-alias-label-secondary,#6b7280);cursor:pointer;white-space:nowrap;background:0 0;border:none;border-radius:6px;padding:4px 10px;font-size:12px;line-height:18px}.eGUBIq_viewBtn:hover{color:var(--dsw-alias-brand-primary,#4f6ef7)}.eGUBIq_viewOn{background:var(--dsw-alias-bg-layer-2,#eef0f4);color:var(--dsw-alias-label-primary,#1f2328);font-weight:600}.eGUBIq_groupRow{background:var(--dsw-alias-bg-layer-1,#fff);border:1px solid var(--dsw-alias-border-l2,#e5e7eb);border-radius:12px;margin-bottom:10px;padding:12px 14px}.eGUBIq_groupHead{align-items:center;gap:10px;min-width:0;display:flex}.eGUBIq_groupName{text-overflow:ellipsis;white-space:nowrap;font-size:13px;font-weight:600;line-height:20px;overflow:hidden}.eGUBIq_groupActions{flex-shrink:0;align-items:center;gap:6px;display:flex}.eGUBIq_groupMembers{flex-direction:column;gap:6px;margin-top:10px;display:flex}.eGUBIq_groupMember{background:var(--dsw-alias-bg-layer-2,#f7f8fa);border-radius:8px;align-items:center;gap:8px;padding:6px 8px;font-size:12px;line-height:18px;display:flex}.eGUBIq_groupMember .eGUBIq_nm{flex:1;min-width:0;font-size:12px}.eGUBIq_groupAddPanel{border-top:1px dashed var(--dsw-alias-border-l2,#e5e7eb);flex-direction:column;gap:6px;margin-top:10px;padding-top:10px;display:flex}.eGUBIq_groupCreate{align-items:center;gap:8px;margin-bottom:10px;display:flex}.eGUBIq_inlineInput{flex:1;min-width:120px}.eGUBIq_assignRow{flex-wrap:wrap;align-items:center;gap:8px;display:flex}.eGUBIq_assignSelect{border:1px solid var(--dsw-alias-border-l2,#e5e7eb);background:var(--dsw-alias-bg-layer-1,#fff);color:var(--dsw-alias-label-primary,#1f2328);font:inherit;border-radius:6px;padding:3px 6px;font-size:12px;line-height:18px}.eGUBIq_groupHint{color:var(--dsw-alias-label-tertiary,#8b93a1);font-size:11px}.eGUBIq_sectAction{color:var(--dsw-alias-label-secondary,#6b7280);align-items:center;gap:8px;margin:14px 2px 8px;font-size:12px;font-weight:600;display:flex}.eGUBIq_backupGrid{grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:12px;display:grid}.eGUBIq_backupCard{background:var(--dsw-alias-bg-layer-1,#fff);border:1px solid var(--dsw-alias-border-l2,#e5e7eb);border-radius:12px;flex-direction:column;gap:10px;padding:16px;display:flex}.eGUBIq_backupCard h3{margin:0;font-size:14px}.eGUBIq_backupCard p{color:var(--dsw-alias-label-secondary,#6b7280);margin:0;font-size:12px;line-height:18px}.eGUBIq_backupActions{flex-wrap:wrap;gap:8px;display:flex;position:relative}.eGUBIq_hiddenFile{opacity:0;pointer-events:none;width:1px;height:1px;position:absolute}.eGUBIq_backupInput{box-sizing:border-box;width:100%}.eGUBIq_backupCheck{cursor:pointer;align-items:center;gap:6px;font-size:12px;display:flex}.eGUBIq_backupWarn{margin:0;font-size:12px;line-height:18px;color:var(--dsw-alias-state-warn-primary,#b45309)!important}.eGUBIq_backupMessage{color:var(--dsw-alias-label-secondary,#6b7280);grid-column:1/-1;font-size:12px}.eGUBIq_backupCheckList{flex-direction:column;gap:6px;max-height:260px;margin:10px 0 4px;padding-right:4px;display:flex;overflow-y:auto}.eGUBIq_backupCheckList .eGUBIq_backupCheck{justify-content:space-between;gap:8px}.eGUBIq_diagPage{flex-direction:column;gap:12px;height:100%;min-height:0;display:flex;overflow-y:auto}.eGUBIq_diagSummary{background:var(--dsw-alias-bg-layer-1,#fff);border:1px solid var(--dsw-alias-border-l2,#e5e7eb);border-radius:12px;flex-wrap:wrap;align-items:center;gap:12px;padding:10px 14px;font-size:12px;display:flex}.eGUBIq_diagSummaryItem{color:var(--dsw-alias-label-secondary,#6b7280);white-space:nowrap;align-items:center;gap:6px;display:inline-flex}.eGUBIq_diagSummaryMeta{color:var(--dsw-alias-label-tertiary,#9ca3af);text-overflow:ellipsis;white-space:nowrap;max-width:320px;font-family:ui-monospace,Menlo,monospace;font-size:11px;overflow:hidden}.eGUBIq_diagSection{background:var(--dsw-alias-bg-layer-1,#fff);border:1px solid var(--dsw-alias-border-l2,#e5e7eb);border-radius:12px;flex-direction:column;gap:8px;padding:12px 14px;display:flex}.eGUBIq_diagSection h3{color:var(--dsw-alias-label-primary,#1f2328);margin:0;font-size:13px;font-weight:600}.eGUBIq_diagCount{color:var(--dsw-alias-label-tertiary,#9ca3af);font-size:11px;font-weight:400}.eGUBIq_diagEmpty{color:var(--dsw-alias-label-secondary,#9ca3af);padding:8px 0;font-size:12px}.eGUBIq_diagBundle{border-top:1px solid var(--dsw-alias-border-l2,#f0f1f3);flex-direction:column;gap:6px;padding-top:8px;display:flex}.eGUBIq_diagBundle:first-of-type{border-top:none;padding-top:0}.eGUBIq_diagRow{flex-wrap:wrap;align-items:center;gap:8px;min-width:0;font-size:12px;line-height:18px;display:flex}.eGUBIq_diagMeta{align-items:baseline;gap:8px;min-width:0;font-size:12px;display:flex}.eGUBIq_diagKey{color:var(--dsw-alias-label-tertiary,#9ca3af);flex-shrink:0;min-width:64px;font-size:11px}.eGUBIq_diagVal{color:var(--dsw-alias-label-primary,#1f2328);overflow-wrap:anywhere;min-width:0;font-family:ui-monospace,Menlo,monospace;font-size:12px;font-weight:500}.eGUBIq_diagIndex{background:var(--dsw-alias-bg-layer-2,#f3f4f6);min-width:18px;height:18px;color:var(--dsw-alias-label-secondary,#6b7280);border-radius:9px;flex-shrink:0;justify-content:center;align-items:center;font-size:11px;font-weight:600;display:inline-flex}.eGUBIq_diagArrow{color:var(--dsw-alias-label-tertiary,#9ca3af);flex-shrink:0;font-size:12px}.eGUBIq_diagBadgeOfficial{background:var(--dsw-alias-brand-primary,#4f6ef7);color:#fff;border-radius:9px;flex-shrink:0;align-items:center;height:18px;padding:0 8px;font-size:11px;font-weight:600;display:inline-flex}.eGUBIq_diagBadgeCommunity{background:var(--dsw-alias-bg-layer-2,#f3f4f6);height:18px;color:var(--dsw-alias-label-secondary,#6b7280);border-radius:9px;flex-shrink:0;align-items:center;padding:0 8px;font-size:11px;display:inline-flex}.eGUBIq_diagBadgeShadow{background:var(--dsw-alias-state-error-primary,#dc2626);color:#fff;border-radius:9px;flex-shrink:0;align-items:center;height:18px;padding:0 8px;font-size:11px;font-weight:600;display:inline-flex}.eGUBIq_diagBadgeWarn{background:var(--dsw-alias-state-warn-primary,#b45309);color:#fff;white-space:nowrap;border-radius:9px;flex-shrink:0;align-items:center;height:18px;padding:0 8px;font-size:11px;font-weight:600;display:inline-flex}.eGUBIq_diagBadgeInfo{background:var(--dsw-alias-bg-layer-2,#f3f4f6);height:18px;color:var(--dsw-alias-label-secondary,#6b7280);white-space:nowrap;border-radius:9px;flex-shrink:0;align-items:center;padding:0 8px;font-size:11px;display:inline-flex}.eGUBIq_diagList{flex-direction:column;gap:6px;display:flex}.eGUBIq_sectionOverview{color:var(--dsw-alias-label-tertiary,#8b93a1);text-overflow:ellipsis;white-space:nowrap;max-width:100%;padding:2px 0 6px;font-size:12px;line-height:18px;overflow:hidden}.eGUBIq_diagAlert{color:var(--dsw-alias-state-warn-primary,#b45309)}.eGUBIq_ovRow{background:var(--dsw-alias-bg-layer-2,#f7f8fa);border-radius:8px;flex-wrap:wrap;align-items:center;gap:8px;min-width:0;padding:6px 10px;font-size:12px;line-height:18px;display:flex}.eGUBIq_ovArrow{color:var(--dsw-alias-label-tertiary,#9ca3af);flex-shrink:0;font-size:12px}.eGUBIq_ovByTag{background:var(--dsw-alias-brand-primary,#4f6ef7);color:#fff;text-overflow:ellipsis;white-space:nowrap;border-radius:9px;flex-shrink:0;align-items:center;max-width:260px;height:18px;padding:0 8px;font-size:11px;font-weight:600;display:inline-flex;overflow:hidden}.eGUBIq_ovFrom{color:var(--dsw-alias-label-secondary,#6b7280);text-overflow:ellipsis;white-space:nowrap;min-width:0;font-size:12px;overflow:hidden}.eGUBIq_orphRow{background:var(--dsw-alias-bg-layer-2,#f7f8fa);border-radius:8px;flex-wrap:wrap;align-items:center;gap:8px;min-width:0;padding:6px 10px;font-size:12px;line-height:18px;display:flex}.eGUBIq_orphBadge{background:var(--dsw-alias-state-warn-primary,#b45309);color:#fff;white-space:nowrap;border-radius:9px;flex-shrink:0;align-items:center;height:18px;padding:0 8px;font-size:11px;font-weight:600;display:inline-flex}.eGUBIq_dragHandle{width:20px;height:20px;color:var(--dsw-alias-label-tertiary,#9ca3af);cursor:grab;-webkit-user-select:none;user-select:none;flex-shrink:0;justify-content:center;align-items:center;font-size:12px;line-height:20px;display:inline-flex}.eGUBIq_dragOver{outline:2px dashed var(--dsw-alias-brand-primary,#4f6ef7);outline-offset:2px;background:var(--dsw-alias-bg-layer-2,#f0f2f8);border-radius:8px}.eGUBIq_dragging{opacity:.45;background:var(--dsw-alias-bg-layer-2,#f3f4f6)}.eGUBIq_collapseHead{font:inherit;color:var(--dsw-alias-label-primary,#1f2328);cursor:pointer;text-align:left;background:0 0;border:none;align-items:center;gap:8px;width:100%;padding:0;font-size:13px;font-weight:600;display:flex}.eGUBIq_collapseIcon{color:var(--dsw-alias-label-secondary,#6b7280);flex-shrink:0;display:inline-flex}.eGUBIq_collapseTitle{flex:1;min-width:0}.eGUBIq_collapseBody{border-top:1px solid var(--dsw-alias-border-l2,#f0f1f3);overflow-wrap:anywhere;flex-direction:column;gap:10px;min-width:0;margin-top:8px;padding-top:10px;display:flex}.eGUBIq_orderPanel{flex-direction:column;gap:10px;min-width:0;display:flex}.eGUBIq_panelNote{color:var(--dsw-alias-label-secondary,#6b7280);margin:0;font-size:12px;line-height:18px}.eGUBIq_panelActions{flex-wrap:wrap;align-items:center;gap:8px;display:flex}.eGUBIq_presetList{flex-direction:column;gap:6px;min-width:0;display:flex}.eGUBIq_presetRow{background:var(--dsw-alias-bg-layer-2,#f7f8fa);border-radius:8px;flex-direction:column;align-items:stretch;gap:6px;min-width:0;max-width:100%;padding:8px 10px;font-size:12px;line-height:18px;display:flex}.eGUBIq_presetName{text-overflow:ellipsis;white-space:nowrap;min-width:0;font-size:13px;font-weight:600;overflow:hidden}.eGUBIq_snapList{flex-direction:column;gap:6px;min-width:0;display:flex}.eGUBIq_snapRow{background:var(--dsw-alias-bg-layer-2,#f7f8fa);border-radius:8px;flex-direction:column;align-items:stretch;gap:8px;padding:10px 12px;font-size:12px;line-height:18px;display:flex}.eGUBIq_snapMeta{flex-wrap:wrap;align-items:center;gap:8px;min-width:0;display:flex}.eGUBIq_snapConfirmText{color:var(--dsw-alias-state-warn-primary,#b45309);margin:0;font-size:12px;line-height:18px}.eGUBIq_confirmRow{flex-wrap:wrap;align-items:center;gap:6px;display:inline-flex}.eGUBIq_fixFallback{flex-direction:column;gap:6px;margin:8px 0;display:flex}.eGUBIq_fixFallbackText{box-sizing:border-box;width:100%;color:var(--dsw-alias-label-primary,#1f2328);background:var(--dsw-alias-bg-layer-2,#f3f4f6);border:1px solid var(--dsw-alias-border-l2,#e5e7eb);resize:vertical;white-space:pre-wrap;word-break:break-all;border-radius:6px;padding:8px 10px;font-family:ui-monospace,Menlo,monospace;font-size:11px;line-height:16px}.eGUBIq_setCard{border:1px solid var(--dsw-alias-border-l2,#e5e7eb);background:var(--dsw-alias-bg-layer-3,#fff);border-radius:12px;list-style:none;transition:border-color .16s,background .16s}.eGUBIq_setCard:hover{border-color:var(--dsw-alias-label-dimmed,#c8ccd4)}.eGUBIq_setCardOpen{background:var(--dsw-alias-bg-layer-2,#f7f8fa);border-color:var(--dsw-alias-label-dimmed,#c8ccd4)}.eGUBIq_setHeader{-webkit-appearance:none;appearance:none;width:100%;font:inherit;color:inherit;text-align:left;cursor:pointer;background:0 0;border:0;border-radius:12px;align-items:center;gap:12px;padding:14px 16px;display:flex}.eGUBIq_setHeader:focus-visible{outline:2px solid var(--dsw-alias-brand-primary,#4f6ef7);outline-offset:-2px}.eGUBIq_setHeadText{flex-direction:column;flex:1;gap:4px;min-width:0;display:flex}.eGUBIq_setName{color:var(--dsw-alias-label-primary,#1f2328);font-size:15px;font-weight:600;line-height:1.4}.eGUBIq_setDesc{color:var(--dsw-alias-label-tertiary,#8b93a1);font-size:13px;line-height:1.5}.eGUBIq_setChevron{color:var(--dsw-alias-label-tertiary,#8b93a1);flex:none;transition:transform .16s;display:inline-flex}.eGUBIq_setChevronOpen{transform:rotate(180deg)}.eGUBIq_setBody{border-top:1px solid var(--dsw-alias-border-l2,#e5e7eb);margin:0 16px;padding-bottom:8px}.eGUBIq_setRow{align-items:center;gap:12px;padding:12px 0;display:flex}.eGUBIq_setRow+.eGUBIq_setRow{border-top:1px solid var(--dsw-alias-border-l2,#e5e7eb)}.eGUBIq_setLabelBox{flex-direction:column;flex:1;gap:3px;min-width:0;display:flex}.eGUBIq_setLabel{font-size:13px;line-height:20px}.eGUBIq_setHint{color:var(--dsw-alias-label-tertiary,#8b93a1);font-size:12px;line-height:18px}.eGUBIq_setConfirm{border-top:1px solid var(--dsw-alias-border-l2,#e5e7eb);flex-direction:column;gap:8px;padding:12px 0 4px;display:flex}.eGUBIq_setCheck{cursor:pointer;align-items:center;gap:8px;font-size:12px;line-height:18px;display:flex}.eGUBIq_setActions{border-top:1px solid var(--dsw-alias-border-l2,#e5e7eb);justify-content:flex-end;align-items:center;gap:8px;padding:12px 0 4px;display:flex}.eGUBIq_setDanger{color:var(--dsw-alias-state-error-primary,#dc2626)}.eGUBIq_setSeg{border:1px solid var(--dsw-alias-border-l2,#e5e7eb);border-radius:8px;flex-shrink:0;gap:2px;padding:2px;display:inline-flex}.eGUBIq_setSegBtn{font:inherit;color:var(--dsw-alias-label-secondary,#6b7280);cursor:pointer;background:0 0;border:none;border-radius:6px;padding:3px 10px;font-size:12px;line-height:18px}.eGUBIq_setSegBtn:disabled{cursor:default;opacity:.5}.eGUBIq_setSegOn{background:var(--dsw-alias-bg-layer-2,#eef0f4);color:var(--dsw-alias-label-primary,#1f2328);font-weight:600}.eGUBIq_setBetaTag{background:var(--dsw-alias-bg-module-platform,#eef0f4);color:var(--dsw-alias-label-secondary,#6b7280);border-radius:9px;margin-left:6px;padding:0 6px;font-size:11px;font-weight:600;line-height:17px}";
1488
1586
  const tagId = "dshmarket/Market.module.css";
1489
1587
  if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]") === null) {
1490
1588
  const tag = document.createElement("style");
@@ -1542,6 +1640,7 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
1542
1640
  "collapseHead": "eGUBIq_collapseHead",
1543
1641
  "collapseIcon": "eGUBIq_collapseIcon",
1544
1642
  "collapseTitle": "eGUBIq_collapseTitle",
1643
+ "confirmRow": "eGUBIq_confirmRow",
1545
1644
  "conflictBody": "eGUBIq_conflictBody",
1546
1645
  "conflictDetailsToggle": "eGUBIq_conflictDetailsToggle",
1547
1646
  "conflictHead": "eGUBIq_conflictHead",
@@ -1664,6 +1763,7 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
1664
1763
  "opTop": "eGUBIq_opTop",
1665
1764
  "opVerb": "eGUBIq_opVerb",
1666
1765
  "opWrap": "eGUBIq_opWrap",
1766
+ "orderPanel": "eGUBIq_orderPanel",
1667
1767
  "orphBadge": "eGUBIq_orphBadge",
1668
1768
  "orphRow": "eGUBIq_orphRow",
1669
1769
  "ovArrow": "eGUBIq_ovArrow",
@@ -1675,8 +1775,12 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
1675
1775
  "pageInfo": "eGUBIq_pageInfo",
1676
1776
  "pager": "eGUBIq_pager",
1677
1777
  "pagerPages": "eGUBIq_pagerPages",
1778
+ "panelActions": "eGUBIq_panelActions",
1678
1779
  "panelNote": "eGUBIq_panelNote",
1679
1780
  "pct": "eGUBIq_pct",
1781
+ "presetList": "eGUBIq_presetList",
1782
+ "presetName": "eGUBIq_presetName",
1783
+ "presetRow": "eGUBIq_presetRow",
1680
1784
  "progress": "eGUBIq_progress",
1681
1785
  "reassure": "eGUBIq_reassure",
1682
1786
  "reassureOk": "eGUBIq_reassureOk",
@@ -1720,6 +1824,10 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
1720
1824
  "setSegOn": "eGUBIq_setSegOn",
1721
1825
  "shot": "eGUBIq_shot",
1722
1826
  "shots": "eGUBIq_shots",
1827
+ "snapConfirmText": "eGUBIq_snapConfirmText",
1828
+ "snapList": "eGUBIq_snapList",
1829
+ "snapMeta": "eGUBIq_snapMeta",
1830
+ "snapRow": "eGUBIq_snapRow",
1723
1831
  "sp": "eGUBIq_sp",
1724
1832
  "spec": "eGUBIq_spec",
1725
1833
  "specTag": "eGUBIq_specTag",
@@ -2253,21 +2361,568 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
2253
2361
  });
2254
2362
  }
2255
2363
  //#endregion
2364
+ //#region src/client/preset-panel.tsx
2365
+ /**
2366
+ * Diagnostics sub-panel — issue #98 phase 3 (plugin presets).
2367
+ *
2368
+ * Rendered at the bottom of the Diagnostics tab inside a collapsible section
2369
+ * (the parent keeps it mounted and passes `open`, so it lazy-loads on first
2370
+ * expand and keeps its state across collapses). Lists named presets
2371
+ * (GET /dsh-market/presets), saves the current community bundle order as a
2372
+ * new preset (POST /dsh-market/presets {action:'save', name, bundleOrder,
2373
+ * disabled}), applies one (action:'apply' — the host trial-validates and
2374
+ * auto-snapshots before writing; on success the parent refreshes the check
2375
+ * report) and deletes one after an inline double confirmation
2376
+ * (action:'delete').
2377
+ *
2378
+ * The list payload is read defensively (bare array or {presets: [...]}).
2379
+ */
2380
+ async function postJson$1(url, body) {
2381
+ let res;
2382
+ try {
2383
+ res = await fetch(url, {
2384
+ method: "POST",
2385
+ headers: { "content-type": "application/json" },
2386
+ body: JSON.stringify(body)
2387
+ });
2388
+ } catch {
2389
+ return {
2390
+ status: 0,
2391
+ body: null
2392
+ };
2393
+ }
2394
+ let payload = null;
2395
+ try {
2396
+ payload = await res.json();
2397
+ } catch {}
2398
+ return {
2399
+ status: res.status,
2400
+ body: payload
2401
+ };
2402
+ }
2403
+ const errorText = (status, body, fallback) => body !== null && typeof body.error === "string" ? body.error : status === 0 ? fallback + "network error" : fallback + `HTTP ${String(status)}`;
2404
+ function PresetPanel(props) {
2405
+ const { t, open, bundleOrder, onRefresh } = props;
2406
+ const [presets, setPresets] = (0, react.useState)(null);
2407
+ const [error, setError] = (0, react.useState)(null);
2408
+ const [msg, setMsg] = (0, react.useState)(null);
2409
+ const [busy, setBusy] = (0, react.useState)(null);
2410
+ const [name, setName] = (0, react.useState)("");
2411
+ /** Preset name awaiting the second confirm click, or null. */
2412
+ const [confirmDelete, setConfirmDelete] = (0, react.useState)(null);
2413
+ /** Hidden <input type="file"> for the import action. */
2414
+ const loaded = (0, react.useRef)(false);
2415
+ const load = (0, react.useCallback)(() => {
2416
+ fetch("/dsh-market/presets", { cache: "no-store" }).then((res) => res.json()).then((body) => {
2417
+ const list = Array.isArray(body) ? body : Array.isArray(body.presets) ? body.presets : [];
2418
+ setPresets(list.map((item) => {
2419
+ const preset = item ?? {};
2420
+ return {
2421
+ name: String(preset.name ?? ""),
2422
+ bundleOrder: Array.isArray(preset.bundleOrder) ? preset.bundleOrder.map(String) : [],
2423
+ disabled: Array.isArray(preset.disabled) ? preset.disabled.map(String) : []
2424
+ };
2425
+ }));
2426
+ setError(null);
2427
+ loaded.current = true;
2428
+ }).catch(() => setError(t("presetListFail") + "network"));
2429
+ }, [t]);
2430
+ (0, react.useEffect)(() => {
2431
+ if (open && !loaded.current) load();
2432
+ }, [open, load]);
2433
+ (0, react.useCallback)(() => {
2434
+ const presetName = name.trim();
2435
+ if (presetName === "") {
2436
+ setError(t("presetNameEmpty"));
2437
+ return;
2438
+ }
2439
+ if (busy !== null) return;
2440
+ setBusy("save");
2441
+ setMsg(null);
2442
+ setError(null);
2443
+ fetch("/dsh-market/installed", { cache: "no-store" }).then((res) => res.json()).then((installed) => postJson$1("/dsh-market/presets", {
2444
+ action: "save",
2445
+ name: presetName,
2446
+ bundleOrder,
2447
+ disabled: Array.isArray(installed.disabled) ? installed.disabled.map(String) : []
2448
+ })).then(({ status, body }) => {
2449
+ if (status >= 200 && status < 300 && body?.ok === true) {
2450
+ setName("");
2451
+ setMsg(t("presetSaved"));
2452
+ load();
2453
+ } else setError(errorText(status, body, t("presetFail")));
2454
+ }).catch(() => setError(t("presetFail") + "network")).finally(() => setBusy(null));
2455
+ }, [
2456
+ busy,
2457
+ bundleOrder,
2458
+ load,
2459
+ name,
2460
+ t
2461
+ ]);
2462
+ const apply = (0, react.useCallback)((presetName) => {
2463
+ if (busy !== null) return;
2464
+ setBusy("apply");
2465
+ setMsg(null);
2466
+ setError(null);
2467
+ postJson$1("/dsh-market/presets", {
2468
+ action: "apply",
2469
+ name: presetName
2470
+ }).then(({ status, body }) => {
2471
+ if (status >= 200 && status < 300 && body?.ok === true) {
2472
+ setMsg(t("presetApplied"));
2473
+ onRefresh();
2474
+ } else setError(errorText(status, body, t("presetFail")));
2475
+ }).catch(() => setError(t("presetFail") + "network")).finally(() => setBusy(null));
2476
+ }, [
2477
+ busy,
2478
+ onRefresh,
2479
+ t
2480
+ ]);
2481
+ const remove = (0, react.useCallback)((presetName) => {
2482
+ if (busy !== null) return;
2483
+ setBusy("delete");
2484
+ setMsg(null);
2485
+ setError(null);
2486
+ postJson$1("/dsh-market/presets", {
2487
+ action: "delete",
2488
+ name: presetName
2489
+ }).then(({ status, body }) => {
2490
+ if (status >= 200 && status < 300 && body?.ok === true) {
2491
+ setConfirmDelete(null);
2492
+ setMsg(t("presetDeleted"));
2493
+ load();
2494
+ } else setError(errorText(status, body, t("presetFail")));
2495
+ }).catch(() => setError(t("presetFail") + "network")).finally(() => setBusy(null));
2496
+ }, [
2497
+ busy,
2498
+ load,
2499
+ t
2500
+ ]);
2501
+ /** Change preview of one preset: {reordered[], enabled[], disabled[], noop}. */
2502
+ const [previewed, setPreviewed] = (0, react.useState)(null);
2503
+ const preview = (0, react.useCallback)((presetName) => {
2504
+ if (busy !== null) return;
2505
+ setBusy("preview");
2506
+ setMsg(null);
2507
+ setError(null);
2508
+ if (previewed?.name === presetName) {
2509
+ setPreviewed(null);
2510
+ setBusy(null);
2511
+ return;
2512
+ }
2513
+ postJson$1("/dsh-market/presets", {
2514
+ action: "preview",
2515
+ name: presetName
2516
+ }).then(({ status, body }) => {
2517
+ if (status >= 200 && status < 300 && body?.ok === true && body.changes !== null && typeof body.changes === "object") {
2518
+ const changes = body.changes;
2519
+ setPreviewed({
2520
+ name: presetName,
2521
+ changes: {
2522
+ reordered: Array.isArray(changes.reordered) ? changes.reordered.map(String) : [],
2523
+ enabled: Array.isArray(changes.enabled) ? changes.enabled.map(String) : [],
2524
+ disabled: Array.isArray(changes.disabled) ? changes.disabled.map(String) : [],
2525
+ noop: changes.noop === true
2526
+ }
2527
+ });
2528
+ } else setError(errorText(status, body, t("presetPreviewFail")));
2529
+ }).catch(() => setError(t("presetPreviewFail") + "network")).finally(() => setBusy(null));
2530
+ }, [
2531
+ busy,
2532
+ previewed,
2533
+ t
2534
+ ]);
2535
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2536
+ className: Market_module_css_default.orderPanel,
2537
+ children: [
2538
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
2539
+ className: Market_module_css_default.panelNote,
2540
+ children: t("presetHint")
2541
+ }),
2542
+ error !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2543
+ className: Market_module_css_default.err,
2544
+ children: error
2545
+ }),
2546
+ presets === null || presets.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2547
+ className: Market_module_css_default.diagEmpty,
2548
+ children: t("presetEmpty")
2549
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2550
+ className: Market_module_css_default.presetList,
2551
+ children: presets.map((preset) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2552
+ className: Market_module_css_default.presetRow,
2553
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2554
+ className: Market_module_css_default.confirmRow,
2555
+ children: [
2556
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2557
+ className: Market_module_css_default.presetName,
2558
+ children: preset.name
2559
+ }),
2560
+ preset.bundleOrder.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2561
+ className: Market_module_css_default.spec,
2562
+ children: t("presetBundleCount").replace("{0}", String(preset.bundleOrder.length))
2563
+ }),
2564
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: Market_module_css_default.grow }),
2565
+ confirmDelete === preset.name ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
2566
+ className: Market_module_css_default.confirmRow,
2567
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
2568
+ variant: "primary",
2569
+ size: "sm",
2570
+ disabled: busy !== null,
2571
+ onClick: () => remove(preset.name),
2572
+ children: t("presetDelete")
2573
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
2574
+ variant: "ghost",
2575
+ size: "sm",
2576
+ disabled: busy !== null,
2577
+ onClick: () => setConfirmDelete(null),
2578
+ children: t("cancel")
2579
+ })]
2580
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
2581
+ className: Market_module_css_default.confirmRow,
2582
+ children: [
2583
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
2584
+ variant: "outline",
2585
+ size: "sm",
2586
+ disabled: busy !== null,
2587
+ onClick: () => apply(preset.name),
2588
+ children: t("presetApply")
2589
+ }),
2590
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
2591
+ variant: "ghost",
2592
+ size: "sm",
2593
+ disabled: busy !== null,
2594
+ onClick: () => preview(preset.name),
2595
+ children: previewed?.name === preset.name ? t("cancel") : t("presetPreview")
2596
+ }),
2597
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
2598
+ variant: "ghost",
2599
+ size: "sm",
2600
+ disabled: busy !== null,
2601
+ onClick: () => setConfirmDelete(preset.name),
2602
+ children: t("presetDelete")
2603
+ })
2604
+ ]
2605
+ })
2606
+ ]
2607
+ }), previewed?.name === preset.name && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2608
+ className: Market_module_css_default.diagList,
2609
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2610
+ className: Market_module_css_default.diagKey,
2611
+ children: t("presetPreviewTitle")
2612
+ }), previewed.changes.noop ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2613
+ className: Market_module_css_default.spec,
2614
+ children: t("presetNoop")
2615
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2616
+ className: Market_module_css_default.spec,
2617
+ children: [
2618
+ previewed.changes.reordered.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2619
+ className: Market_module_css_default.warnLine,
2620
+ children: [
2621
+ t("presetReorder").replace("{0}", String(previewed.changes.reordered.length)),
2622
+ ": ",
2623
+ previewed.changes.reordered.join(", ")
2624
+ ]
2625
+ }),
2626
+ previewed.changes.enabled.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2627
+ className: Market_module_css_default.warnLine,
2628
+ children: [
2629
+ t("presetEnable").replace("{0}", String(previewed.changes.enabled.length)),
2630
+ ": ",
2631
+ previewed.changes.enabled.join(", ")
2632
+ ]
2633
+ }),
2634
+ previewed.changes.disabled.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2635
+ className: Market_module_css_default.warnLine,
2636
+ children: [
2637
+ t("presetDisable").replace("{0}", String(previewed.changes.disabled.length)),
2638
+ ": ",
2639
+ previewed.changes.disabled.join(", ")
2640
+ ]
2641
+ })
2642
+ ]
2643
+ })]
2644
+ })]
2645
+ }, preset.name))
2646
+ }),
2647
+ msg !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2648
+ className: Market_module_css_default.okState,
2649
+ children: msg
2650
+ })
2651
+ ]
2652
+ });
2653
+ }
2654
+ //#endregion
2655
+ //#region src/client/snapshot-panel.tsx
2656
+ /**
2657
+ * Diagnostics sub-panel — issue #98 phase 3 (snapshots & rollback).
2658
+ *
2659
+ * Rendered at the bottom of the Diagnostics tab inside a collapsible section
2660
+ * (the parent keeps it mounted and passes `open`, so it lazy-loads on first
2661
+ * expand and keeps its state across collapses). Lists profile snapshots
2662
+ * (GET /dsh-market/snapshots), creates one (POST /dsh-market/snapshots) and
2663
+ * restores one after an inline double confirmation
2664
+ * (POST /dsh-market/restore-snapshot {snapshot}).
2665
+ *
2666
+ * The list payload is read defensively (bare array or {snapshots: [...]});
2667
+ * `files` entries are {path, json|lines} objects, from which only `path` is
2668
+ * displayed.
2669
+ */
2670
+ async function postJson(url, body) {
2671
+ let res;
2672
+ try {
2673
+ res = await fetch(url, {
2674
+ method: "POST",
2675
+ headers: { "content-type": "application/json" },
2676
+ body: JSON.stringify(body)
2677
+ });
2678
+ } catch {
2679
+ return {
2680
+ status: 0,
2681
+ body: null
2682
+ };
2683
+ }
2684
+ let payload = null;
2685
+ try {
2686
+ payload = await res.json();
2687
+ } catch {}
2688
+ return {
2689
+ status: res.status,
2690
+ body: payload
2691
+ };
2692
+ }
2693
+ /** Snapshot file entries may be plain names or {path, json|lines} objects. */
2694
+ function fileNames(files) {
2695
+ if (!Array.isArray(files)) return [];
2696
+ const names = [];
2697
+ for (const file of files) if (typeof file === "string") names.push(file);
2698
+ else if (file !== null && typeof file === "object") {
2699
+ const path = file.path;
2700
+ if (typeof path === "string") names.push(path);
2701
+ }
2702
+ return names;
2703
+ }
2704
+ function snapshotOf(value) {
2705
+ if (value === null || typeof value !== "object") return null;
2706
+ const item = value;
2707
+ if (typeof item.id !== "string" && typeof item.id !== "number") return null;
2708
+ return {
2709
+ id: String(item.id),
2710
+ createdAt: typeof item.createdAt === "string" || typeof item.createdAt === "number" ? item.createdAt : 0,
2711
+ files: fileNames(item.files)
2712
+ };
2713
+ }
2714
+ function formatTime(value) {
2715
+ const date = new Date(value);
2716
+ return Number.isNaN(date.getTime()) ? String(value) : date.toLocaleString();
2717
+ }
2718
+ function SnapshotPanel(props) {
2719
+ const { t, open, onRefresh } = props;
2720
+ const [snapshots, setSnapshots] = (0, react.useState)(null);
2721
+ const [error, setError] = (0, react.useState)(null);
2722
+ const [msg, setMsg] = (0, react.useState)(null);
2723
+ const [busy, setBusy] = (0, react.useState)(null);
2724
+ /** Snapshot id awaiting the second confirm click (restore), or null. */
2725
+ const [confirmId, setConfirmId] = (0, react.useState)(null);
2726
+ /** Snapshot id awaiting the second confirm click (delete), or null. */
2727
+ const [confirmDeleteId, setConfirmDeleteId] = (0, react.useState)(null);
2728
+ const loaded = (0, react.useRef)(false);
2729
+ const load = (0, react.useCallback)(() => {
2730
+ fetch("/dsh-market/snapshots", { cache: "no-store" }).then((res) => res.json()).then((body) => {
2731
+ const list = Array.isArray(body) ? body : Array.isArray(body.snapshots) ? body.snapshots : [];
2732
+ setSnapshots(list.map(snapshotOf).filter((snap) => snap !== null));
2733
+ setError(null);
2734
+ loaded.current = true;
2735
+ }).catch(() => setError(t("snapListFail") + "network"));
2736
+ }, [t]);
2737
+ (0, react.useEffect)(() => {
2738
+ if (open && !loaded.current) load();
2739
+ }, [open, load]);
2740
+ const create = (0, react.useCallback)(() => {
2741
+ if (busy !== null) return;
2742
+ setBusy("create");
2743
+ setMsg(null);
2744
+ setError(null);
2745
+ postJson("/dsh-market/snapshots", {}).then(({ status, body }) => {
2746
+ if (status >= 200 && status < 300 && body?.ok === true) {
2747
+ setMsg(t("snapCreated"));
2748
+ load();
2749
+ } else {
2750
+ const detail = body !== null && typeof body.error === "string" ? body.error : status === 0 ? "network error" : `HTTP ${String(status)}`;
2751
+ setError(t("snapCreateFail") + detail);
2752
+ }
2753
+ }).catch(() => setError(t("snapCreateFail") + "network")).finally(() => setBusy(null));
2754
+ }, [
2755
+ busy,
2756
+ load,
2757
+ t
2758
+ ]);
2759
+ const restore = (0, react.useCallback)((id) => {
2760
+ if (busy !== null) return;
2761
+ setBusy("restore");
2762
+ setMsg(null);
2763
+ setError(null);
2764
+ postJson("/dsh-market/restore-snapshot", { snapshot: id }).then(({ status, body }) => {
2765
+ if (status >= 200 && status < 300 && body?.ok === true) {
2766
+ setConfirmId(null);
2767
+ setMsg(t("snapRestored"));
2768
+ onRefresh();
2769
+ } else {
2770
+ const detail = body !== null && typeof body.error === "string" ? body.error : status === 0 ? "network error" : `HTTP ${String(status)}`;
2771
+ setError(t("snapRestoreFail") + detail);
2772
+ }
2773
+ }).catch(() => setError(t("snapRestoreFail") + "network")).finally(() => setBusy(null));
2774
+ }, [
2775
+ busy,
2776
+ onRefresh,
2777
+ t
2778
+ ]);
2779
+ /** Delete one snapshot after inline double confirmation. */
2780
+ const remove = (0, react.useCallback)((id) => {
2781
+ if (busy !== null) return;
2782
+ setBusy("delete");
2783
+ setMsg(null);
2784
+ setError(null);
2785
+ postJson("/dsh-market/delete-snapshot", { snapshot: id }).then(({ status, body }) => {
2786
+ if (status >= 200 && status < 300 && body?.ok === true) {
2787
+ setConfirmDeleteId(null);
2788
+ setMsg(t("snapDeleted"));
2789
+ load();
2790
+ } else {
2791
+ const detail = body !== null && typeof body.error === "string" ? body.error : status === 0 ? "network error" : `HTTP ${String(status)}`;
2792
+ setError(t("snapDeleteFail") + detail);
2793
+ }
2794
+ }).catch(() => setError(t("snapDeleteFail") + "network")).finally(() => setBusy(null));
2795
+ }, [
2796
+ busy,
2797
+ load,
2798
+ t
2799
+ ]);
2800
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2801
+ className: Market_module_css_default.orderPanel,
2802
+ children: [
2803
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
2804
+ className: Market_module_css_default.panelNote,
2805
+ children: t("snapHint")
2806
+ }),
2807
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2808
+ className: Market_module_css_default.panelActions,
2809
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
2810
+ variant: "primary",
2811
+ size: "sm",
2812
+ disabled: busy !== null,
2813
+ onClick: create,
2814
+ children: busy === "create" ? t("snapCreating") : t("snapCreate")
2815
+ })
2816
+ }),
2817
+ error !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2818
+ className: Market_module_css_default.err,
2819
+ children: error
2820
+ }),
2821
+ snapshots === null || snapshots.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2822
+ className: Market_module_css_default.diagEmpty,
2823
+ children: t("snapEmpty")
2824
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2825
+ className: Market_module_css_default.snapList,
2826
+ children: snapshots.map((snap) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2827
+ className: Market_module_css_default.snapRow,
2828
+ children: confirmId === snap.id ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
2829
+ className: Market_module_css_default.snapConfirmText,
2830
+ children: t("snapRestoreConfirmText")
2831
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2832
+ className: Market_module_css_default.confirmRow,
2833
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
2834
+ variant: "primary",
2835
+ size: "sm",
2836
+ disabled: busy !== null,
2837
+ onClick: () => restore(snap.id),
2838
+ children: busy === "restore" ? t("snapRestoring") : t("snapRestoreConfirm")
2839
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
2840
+ variant: "ghost",
2841
+ size: "sm",
2842
+ disabled: busy !== null,
2843
+ onClick: () => setConfirmId(null),
2844
+ children: t("cancel")
2845
+ })]
2846
+ })] }) : confirmDeleteId === snap.id ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
2847
+ className: Market_module_css_default.snapConfirmText,
2848
+ children: t("snapDeleteConfirmText")
2849
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2850
+ className: Market_module_css_default.confirmRow,
2851
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
2852
+ variant: "primary",
2853
+ size: "sm",
2854
+ disabled: busy !== null,
2855
+ onClick: () => remove(snap.id),
2856
+ children: busy === "delete" ? t("snapDeleting") : t("snapDeleteConfirm")
2857
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
2858
+ variant: "ghost",
2859
+ size: "sm",
2860
+ disabled: busy !== null,
2861
+ onClick: () => setConfirmDeleteId(null),
2862
+ children: t("cancel")
2863
+ })]
2864
+ })] }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2865
+ className: Market_module_css_default.snapMeta,
2866
+ children: [
2867
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2868
+ className: Market_module_css_default.diagVal,
2869
+ children: formatTime(snap.createdAt)
2870
+ }),
2871
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2872
+ className: Market_module_css_default.spec,
2873
+ children: snap.id
2874
+ }),
2875
+ snap.files.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
2876
+ className: Market_module_css_default.spec,
2877
+ children: [
2878
+ t("snapFiles"),
2879
+ ": ",
2880
+ snap.files.join(", ")
2881
+ ]
2882
+ })
2883
+ ]
2884
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2885
+ className: Market_module_css_default.confirmRow,
2886
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
2887
+ variant: "outline",
2888
+ size: "sm",
2889
+ disabled: busy !== null,
2890
+ onClick: () => setConfirmId(snap.id),
2891
+ children: t("snapRestore")
2892
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
2893
+ variant: "ghost",
2894
+ size: "sm",
2895
+ disabled: busy !== null,
2896
+ onClick: () => setConfirmDeleteId(snap.id),
2897
+ children: t("snapDelete")
2898
+ })]
2899
+ })] })
2900
+ }, snap.id))
2901
+ }),
2902
+ msg !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2903
+ className: Market_module_css_default.okState,
2904
+ children: msg
2905
+ })
2906
+ ]
2907
+ });
2908
+ }
2909
+ //#endregion
2256
2910
  //#region src/client/Diagnostics.tsx
2257
2911
  /**
2258
2912
  * Diagnostics tab — issue #98: renders the profile composition check report
2259
2913
  * served by the host route /dsh-market/check (see src/check.ts). Below the
2260
- * report sits the phase 2 action panel: community-bundle ordering (reorder
2261
- * locally with ↑/↓ or drag, POST to /dsh-market/bundle-order) plus the AI-fix
2262
- * clipboard prompt for HARD issues. The phase 3 snapshots & rollback and
2263
- * plugin presets panels ship in later stacked PRs.
2914
+ * report sit the phase 2/3 action panels: a community-bundle ordering block
2915
+ * (reorder locally with ↑/↓, POST to /dsh-market/bundle-order) and a
2916
+ * snapshots & rollback panel (snapshot-panel.tsx) collapsible, default
2917
+ * collapsed, and lazy-fetching on first expand. The plugin presets panel
2918
+ * ships in a later stacked PR.
2264
2919
  *
2265
2920
  * Read-only view of the loading-layer stack and the conflict surface: bundle
2266
2921
  * order (official vs community), duplicate loader entry ids, peer dependency
2267
2922
  * mismatches, multi-version core packages, overrides and orphan patches. The
2268
- * report shape mirrors the CheckReport interface in src/check.ts; it is
2269
- * re-declared here because the client bundle is built independently of the
2270
- * host tree.
2923
+ * report
2924
+ * shape mirrors the CheckReport interface in src/check.ts; it is re-declared
2925
+ * here because the client bundle is built independently of the host tree.
2271
2926
  */
2272
2927
  /**
2273
2928
  * A collapsible report section: header shows title + count + chevron; the
@@ -2329,8 +2984,9 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
2329
2984
  });
2330
2985
  }
2331
2986
  /** A collapsible section that KEEPS its children mounted (hidden via CSS when
2332
- * collapsed) so the ordering panel below retains its loaded data and
2333
- * in-progress edits across collapses.
2987
+ * collapsed) so the phase 3 panels below retain their loaded data and
2988
+ * in-progress edits across collapses. Children mount from the start, but the
2989
+ * panels only fetch when `open` first becomes true.
2334
2990
  */
2335
2991
  function CollapsibleSection(props) {
2336
2992
  const { title, count, open, onToggle, children } = props;
@@ -2389,7 +3045,7 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
2389
3045
  /**
2390
3046
  * Fetch and render the profile check report. Refetches on every mount, so
2391
3047
  * switching tabs away and back re-runs the (cheap, read-only) analysis; the
2392
- * ordering panel calls `refresh()` after applying an order.
3048
+ * phase 3 panels below call `refresh()` after applying changes.
2393
3049
  */
2394
3050
  function Diagnostics(props) {
2395
3051
  const { t } = props;
@@ -2397,11 +3053,13 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
2397
3053
  const [error, setError] = (0, react.useState)(null);
2398
3054
  const [orderOpen, setOrderOpen] = (0, react.useState)(false);
2399
3055
  const [explainOpen, setExplainOpen] = (0, react.useState)(false);
3056
+ const [snapOpen, setSnapOpen] = (0, react.useState)(false);
3057
+ const [presetOpen, setPresetOpen] = (0, react.useState)(false);
2400
3058
  const [fixMsg, setFixMsg] = (0, react.useState)(null);
2401
3059
  /** The built AI-fix prompt when the clipboard path failed — rendered as a
2402
3060
  * selectable text block so the user can still copy it manually. */
2403
3061
  const [fixFallback, setFixFallback] = (0, react.useState)(null);
2404
- /** Bump to re-run the /dsh-market/check fetch after an order apply. */
3062
+ /** Bump to re-run the /dsh-market/check fetch after an order/snapshot-restore apply. */
2405
3063
  const [version, setVersion] = (0, react.useState)(0);
2406
3064
  const refresh = (0, react.useCallback)(() => setVersion((v) => v + 1), []);
2407
3065
  /** Community bundle names from the report, in declared order. */
@@ -2419,8 +3077,8 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
2419
3077
  * refresh() refetch returns a NEW array even when the order is unchanged,
2420
3078
  * so a naive `setOrder(communityNames)` effect would wipe the user's
2421
3079
  * in-progress drag/↑↓ edits on every unrelated re-check. Only resync when
2422
- * the report's community order actually CHANGED (apply order) an
2423
- * identical refetch keeps the draft (review M2).
3080
+ * the report's community order actually CHANGED (apply order / snapshot
3081
+ * restore) — an identical refetch keeps the draft (review M2).
2424
3082
  */
2425
3083
  const syncedOrderRef = (0, react.useRef)(null);
2426
3084
  (0, react.useEffect)(() => {
@@ -3337,6 +3995,27 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
3337
3995
  }, name))
3338
3996
  })
3339
3997
  ]
3998
+ }),
3999
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CollapsibleSection, {
4000
+ title: t("presetSection"),
4001
+ open: presetOpen,
4002
+ onToggle: () => setPresetOpen((o) => !o),
4003
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PresetPanel, {
4004
+ t,
4005
+ open: presetOpen,
4006
+ bundleOrder: order,
4007
+ onRefresh: refresh
4008
+ })
4009
+ }),
4010
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CollapsibleSection, {
4011
+ title: t("snapSection"),
4012
+ open: snapOpen,
4013
+ onToggle: () => setSnapOpen((o) => !o),
4014
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SnapshotPanel, {
4015
+ t,
4016
+ open: snapOpen,
4017
+ onRefresh: refresh
4018
+ })
3340
4019
  })
3341
4020
  ]
3342
4021
  });
@@ -4427,6 +5106,7 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
4427
5106
  const [updates, setUpdates] = (0, react.useState)({});
4428
5107
  const [updatingName, setUpdatingName] = (0, react.useState)(null);
4429
5108
  const [staleName, setStaleName] = (0, react.useState)(null);
5109
+ const [restoreName, setRestoreName] = (0, react.useState)(null);
4430
5110
  /** Determinate percent parsed from pnpm's Progress line, when available. */
4431
5111
  const [progressPct, setProgressPct] = (0, react.useState)(null);
4432
5112
  /**
@@ -5112,10 +5792,11 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
5112
5792
  body: "{}"
5113
5793
  }).catch(() => {});
5114
5794
  }, []);
5115
- const doUpdate = (0, react.useCallback)((name, force = false) => {
5795
+ const doUpdate = (0, react.useCallback)((name, force = false, restore = false) => {
5116
5796
  setInstallError(null);
5117
5797
  setActivationWarnings([]);
5118
5798
  setStaleName((prev) => prev === name ? null : prev);
5799
+ setRestoreName((prev) => prev === name ? null : prev);
5119
5800
  setUpdatingName(name);
5120
5801
  updateIdleStrikes.current = 0;
5121
5802
  sessionStorage.setItem("dshm-updating", JSON.stringify({ name }));
@@ -5129,10 +5810,11 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
5129
5810
  return fetch("/dsh-market/update", {
5130
5811
  method: "POST",
5131
5812
  headers: { "content-type": "application/json" },
5132
- body: JSON.stringify(force ? {
5813
+ body: JSON.stringify({
5133
5814
  name,
5134
- force: true
5135
- } : { name })
5815
+ ...force ? { force: true } : {},
5816
+ ...restore ? { restore: true } : {}
5817
+ })
5136
5818
  }).then((res) => res.json().then((body) => ({
5137
5819
  status: res.status,
5138
5820
  body
@@ -5175,7 +5857,8 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
5175
5857
  if (body.stale === true) setStaleName(name);
5176
5858
  if (Array.isArray(body.ignoredBuilds) && body.ignoredBuilds.length > 0) setBuildsSkipped({
5177
5859
  updateName: name,
5178
- names: body.ignoredBuilds.map(String)
5860
+ names: body.ignoredBuilds.map(String),
5861
+ restore
5179
5862
  });
5180
5863
  const text = (v) => typeof v === "string" ? v : v && typeof v.text === "string" ? v.text : v == null ? "" : JSON.stringify(v);
5181
5864
  const detail = text(body.error) || humanOutput([text(body.stderr), text(body.stdout)].filter(Boolean).join("\n")) || "exit " + body.exitCode;
@@ -5183,10 +5866,28 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
5183
5866
  state: "failed",
5184
5867
  reason: detail.trim().slice(-600)
5185
5868
  }));
5186
- setInstallError(t("updateFail") + ": " + name + " — " + detail.trim().slice(-600));
5869
+ setInstallError((restore ? t("restoreFail") : t("updateFail")) + ": " + name + " — " + detail.trim().slice(-600));
5187
5870
  }
5188
5871
  }).catch(() => {});
5189
5872
  }, [refreshInstalled, t]);
5873
+ const askRestore = (0, react.useCallback)((name) => {
5874
+ const spec = installed[name];
5875
+ const entry = data === null || spec === void 0 ? void 0 : entryForDep(data.plugins, name, String(spec), repoIdentities[name], repoHints[name]);
5876
+ setStaleName(null);
5877
+ if (entry === void 0) {
5878
+ setRestoreName(null);
5879
+ setInstallError(t("restoreNoCatalog"));
5880
+ return;
5881
+ }
5882
+ setRestoreName(name);
5883
+ setInstallError(t("restoreHint"));
5884
+ }, [
5885
+ data,
5886
+ installed,
5887
+ repoHints,
5888
+ repoIdentities,
5889
+ t
5890
+ ]);
5190
5891
  const doUseSkin = (0, react.useCallback)((name) => {
5191
5892
  setInstallError(null);
5192
5893
  fetch("/dsh-market/use-skin", {
@@ -6447,7 +7148,7 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
6447
7148
  size: "sm",
6448
7149
  disabled: busyUrl !== null,
6449
7150
  onClick: () => {
6450
- const { plugin, updateName, names } = buildsSkipped;
7151
+ const { plugin, updateName, names, restore } = buildsSkipped;
6451
7152
  setBuildsSkipped(null);
6452
7153
  fetch("/dsh-market/approve-builds", {
6453
7154
  method: "POST",
@@ -6456,7 +7157,7 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
6456
7157
  }).then((res) => res.json()).then((body) => {
6457
7158
  if (!body.ok) setInstallError(String(body.error || "approve failed"));
6458
7159
  else if (plugin !== void 0) doInstall(plugin);
6459
- else if (updateName !== void 0) doUpdate(updateName);
7160
+ else if (updateName !== void 0) doUpdate(updateName, false, restore === true);
6460
7161
  }).catch((error) => setInstallError(String(error)));
6461
7162
  },
6462
7163
  children: t("approveBuilds")
@@ -6507,18 +7208,26 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
6507
7208
  className: Market_module_css_default.err,
6508
7209
  children: [installError, /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6509
7210
  className: Market_module_css_default.staleAction,
6510
- children: [staleName !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
6511
- size: "sm",
6512
- onClick: () => doUpdate(staleName, true),
6513
- children: t("updateNow")
6514
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
6515
- size: "sm",
6516
- variant: "outline",
6517
- icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconDownloadOutline16, { size: 14 }),
6518
- disabled: exportState === "busy",
6519
- onClick: doExportLog,
6520
- children: exportState === "busy" ? t("exportingLog") : t("exportLog")
6521
- })]
7211
+ children: [
7212
+ staleName !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
7213
+ size: "sm",
7214
+ onClick: () => doUpdate(staleName, true),
7215
+ children: t("updateNow")
7216
+ }),
7217
+ restoreName !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
7218
+ size: "sm",
7219
+ onClick: () => doUpdate(restoreName, false, true),
7220
+ children: t("restoreContinue")
7221
+ }),
7222
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
7223
+ size: "sm",
7224
+ variant: "outline",
7225
+ icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconDownloadOutline16, { size: 14 }),
7226
+ disabled: exportState === "busy",
7227
+ onClick: doExportLog,
7228
+ children: exportState === "busy" ? t("exportingLog") : t("exportLog")
7229
+ })
7230
+ ]
6522
7231
  })]
6523
7232
  }),
6524
7233
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
@@ -7273,6 +7982,7 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
7273
7982
  const missing = pendingBackup !== null && !installedFiles.includes(name);
7274
7983
  const entry = data === null ? void 0 : entryForDep(data.plugins, name, String(spec), repoIdentities[name], repoHints[name]);
7275
7984
  const status = updates[name];
7985
+ const localDev = /^(?:link|file):/i.test(String(spec)) || status?.kind === "linked";
7276
7986
  const act = activations[name];
7277
7987
  const meta = act !== void 0 ? activationMeta(act.state, t) : null;
7278
7988
  const version = status && status.version ? "v" + status.version : "";
@@ -7454,7 +8164,7 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
7454
8164
  disabled: updatingName !== null,
7455
8165
  onClick: () => doUpdate(name),
7456
8166
  children: t("update")
7457
- }) : status && status.kind === "linked" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
8167
+ }) : localDev ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
7458
8168
  className: Market_module_css_default.metaTag,
7459
8169
  title: t("linkedDev"),
7460
8170
  children: t("linkedDev")
@@ -7468,14 +8178,20 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
7468
8178
  className: Market_module_css_default.dangerBtn,
7469
8179
  disabled: true,
7470
8180
  children: t("uninstalling")
7471
- }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
8181
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [localDev && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
8182
+ variant: "outline",
8183
+ size: "sm",
8184
+ disabled: removingName !== null || busyUrl !== null || updatingName !== null,
8185
+ onClick: () => askRestore(name),
8186
+ children: t("restore")
8187
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
7472
8188
  variant: "outline",
7473
8189
  size: "sm",
7474
8190
  className: Market_module_css_default.dangerBtn,
7475
8191
  disabled: removingName !== null || busyUrl !== null || updatingName !== null,
7476
8192
  onClick: () => setRemoveConfirm(name),
7477
8193
  children: t("uninstall")
7478
- }))]
8194
+ })] }))]
7479
8195
  })
7480
8196
  ]
7481
8197
  })]