dshmarket 1.23.1 → 1.25.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 中",
@@ -355,6 +360,19 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
355
360
  checkSatisfied: "满足",
356
361
  checkUnsatisfied: "不满足",
357
362
  checkUnknown: "未知",
363
+ checkPeerRisk: "依赖风险",
364
+ checkPeerRiskEmpty: "没有风险级依赖不匹配",
365
+ checkPeerWarning: "依赖警告",
366
+ checkPeerWarningEmpty: "没有警告级依赖不匹配",
367
+ checkPeerInfoTier: "依赖信息",
368
+ checkPeerInfoTierEmpty: "没有信息级依赖条目",
369
+ checkPeerSatisfied: "已满足的依赖",
370
+ checkPeerSatisfiedEmpty: "没有已满足的依赖条目",
371
+ peerRiskBelowMin: "低于声明下界",
372
+ peerRiskAboveMax: "高于显式上界",
373
+ peerWarnOptional: "可选依赖",
374
+ peerWarnAboveMax: "超出声明上界",
375
+ peerInfoUnverified: "未达判定",
358
376
  checkMultiVersion: "核心包多版本",
359
377
  checkMultiEmpty: "没有多版本核心包",
360
378
  checkOverrides: "覆盖关系",
@@ -400,15 +418,40 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
400
418
  aiFixDetect: "【第一步·先判断身份】动手前先判断:当前 Agent 所运行的进程,是否就是这个 profile 对应的 DeepSeek Harness 本机实例(即:诊断出的这套组合,就是你现在运行中的组合)?判断依据:当前工作目录 / $DSH_HOME / 进程命令行是否指向该 profile,或你是否运行在 deepseek-harness 进程内。若无法确定,一律按【是你】处理(更安全)。",
401
419
  aiFixIfSelf: "【是 → 你就是这个 harness】严禁原地改动组合、harness 或核心包:不写 cordis.patch.yml、不动 bundle 顺序/启停、不装/卸/升级插件、不重装依赖、不升级/重启 dsh。三步:① 先只读分析,不改任何东西;② 给出 apply.sh/.bat(本次修复的改动)与 rollback.sh/.bat(完整撤销 apply);两者都幂等——apply 仅在无已有快照时才创建快照(否则不覆盖;已存在说明 apply 跑过,先回滚或确认再重跑),rollback 从这份快照恢复,因此 apply 跑到一半失败也能回滚、重复回滚也安全;③ 让我在外部终端跑 apply,并拷回 stdout/stderr 给你判断。每步先说明理由、等我确认;绝不自行执行。",
402
420
  aiFixScope: "【否 → 保守执行】你要是判定自己并非运行在目标 harness 内(独立进程),才可考虑:修改 dsh.profile.bundles 顺序、停用/启用插件、调整 cordis.patch.yml。注意:官方 bundle 不可移动;动手前先说明计划。",
403
- aiFixConservative: "请保持保守:只修复上面列出的明确错误(启动失败/重复条目/确认不匹配的依赖)。警告和信息级问题(如未确认的依赖范围)仅在它们与明确错误相关时处理。不要做不必要的升级或重新排序;每项改动前说明理由并等待确认。",
421
+ aiFixConservative: "请保持保守:只修复上面列出的明确错误(启动失败/重复条目/风险级依赖不匹配)。警告和信息级问题(如可选依赖、未确认的依赖范围)仅在它们与明确错误相关时处理。不要做不必要的升级或重新排序;每项改动前说明理由并等待确认。",
404
422
  aiFixCopied: "已复制修复提示词,请粘贴到新对话后发送",
405
423
  aiFixFail: "无法访问剪贴板,请手动复制下面的诊断内容",
406
424
  catConflict: "冲突",
407
425
  catDeps: "依赖",
426
+ catRisk: "风险",
427
+ catWarn: "警告",
428
+ catInfo: "信息",
408
429
  catOrder: "顺序",
409
430
  /** Summary-strip tooltip for the order count (before/after rule conflicts). */
410
431
  checkOrderTip: "社区 bundle 加载顺序与插件声明的 before/after 规则冲突",
411
432
  diagOkAll: "一切正常:未发现冲突、依赖或顺序问题",
433
+ snapSection: "快照与回滚",
434
+ snapHint: "应用变更前会自动创建快照;也可以手动创建快照,随时回滚到任意状态。",
435
+ snapCreate: "创建快照",
436
+ snapCreating: "创建中…",
437
+ snapCreated: "快照已创建",
438
+ snapEmpty: "还没有快照",
439
+ snapListFail: "快照列表加载失败:",
440
+ snapCreateFail: "创建快照失败:",
441
+ snapRestore: "回滚",
442
+ snapRestoring: "回滚中…",
443
+ snapRestored: "已回滚,重启后生效",
444
+ snapRestoreFail: "回滚失败:",
445
+ snapRestoreConfirm: "确认回滚",
446
+ snapRestoreConfirmText: "回滚会用快照覆盖当前 profile 的 package.json 与配置,且不可撤销(可先创建新快照再回滚)。",
447
+ snapFiles: "包含文件",
448
+ snapDelete: "删除",
449
+ snapDeleting: "删除中…",
450
+ snapDeleted: "快照已删除",
451
+ snapDeleteFail: "删除快照失败:",
452
+ snapDeleteConfirm: "确认删除",
453
+ snapDeleteConfirmText: "删除后该快照将无法恢复。",
454
+ marketNoToggle: "市场自身不能停用",
412
455
  hostDependencyWarning: "插件在 dependencies 中声明了已知的 DSH 共享宿主包,可能遮蔽宿主版本(仅依据清单,未确认运行时重复):",
413
456
  hostDependencyMore: "另有 {0} 条,已省略"
414
457
  };
@@ -505,7 +548,12 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
505
548
  updateNow: "Update now",
506
549
  updateFail: "Update failed",
507
550
  upToDate: "Up to date",
508
- linkedDev: "linked (dev)",
551
+ linkedDev: "local",
552
+ restore: "Restore",
553
+ restoreHint: "This will uninstall the local version, reinstall the catalog version, and keep update checks. This cannot be undone — please confirm again.",
554
+ restoreContinue: "Continue update",
555
+ restoreNoCatalog: "This plugin is not in the curated catalog, so it cannot be restored. Uninstall the local copy, or keep developing it locally.",
556
+ restoreFail: "Restore failed",
509
557
  exportLog: "Export log",
510
558
  exportingLog: "Exporting…",
511
559
  exportedLog: "Log exported: dsh-market-log.txt — please attach it to your issue",
@@ -734,6 +782,19 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
734
782
  checkSatisfied: "satisfied",
735
783
  checkUnsatisfied: "not satisfied",
736
784
  checkUnknown: "unknown",
785
+ checkPeerRisk: "Dependency risks",
786
+ checkPeerRiskEmpty: "No risk-level dependency mismatches",
787
+ checkPeerWarning: "Dependency warnings",
788
+ checkPeerWarningEmpty: "No warning-level dependency mismatches",
789
+ checkPeerInfoTier: "Dependency info",
790
+ checkPeerInfoTierEmpty: "No informational dependency entries",
791
+ checkPeerSatisfied: "Satisfied dependencies",
792
+ checkPeerSatisfiedEmpty: "No satisfied dependency entries",
793
+ peerRiskBelowMin: "below declared minimum",
794
+ peerRiskAboveMax: "above explicit maximum",
795
+ peerWarnOptional: "optional peer",
796
+ peerWarnAboveMax: "above declared upper bound",
797
+ peerInfoUnverified: "unverified",
737
798
  checkMultiVersion: "Multi-version core packages",
738
799
  checkMultiEmpty: "No multi-version core packages",
739
800
  checkOverrides: "Overrides",
@@ -779,15 +840,40 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
779
840
  aiFixDetect: "Step 1 — identify yourself first. Before touching anything, determine whether the process you are running in IS the DeepSeek Harness instance this profile belongs to (i.e. this diagnosed composition is the one you are running in right now). Check whether the cwd / $DSH_HOME / command line points at this profile, or whether you are running inside a deepseek-harness process. If you cannot tell, assume the answer is \"yes\" (the safe choice).",
780
841
  aiFixIfSelf: "If YES — you are this harness: never change the live composition, the harness or core packages in place (don't edit cordis.patch.yml, don't reorder/enable/disable bundles, don't install/remove/upgrade a plugin, don't reinstall deps, don't upgrade/restart dsh). Three steps: 1) read-only analysis only, change nothing; 2) produce apply.sh/.bat (this fix's changes) and rollback.sh/.bat (fully reverts it); both are idempotent — apply snapshots only when none exists yet and never overwrites an existing snapshot (an existing one means apply already ran, so roll back or confirm before re-running), while rollback restores from that snapshot, so a half-run apply can still be rolled back and repeated rollback is safe; 3) have me run apply in an external terminal and paste the stdout/stderr back to you. State the reason and wait for my confirmation at each step — never run these yourself.",
781
842
  aiFixScope: "If NO — you are a process outside the target harness: you may then consider reordering dsh.profile.bundles, disabling / enabling plugins, or adjusting cordis.patch.yml. Note: official bundles are fixed; state your plan before changing anything.",
782
- aiFixConservative: "Be conservative: only fix the clear errors listed above (boot failures / duplicate entries / confirmed dependency mismatches). Treat warnings and informational entries (e.g. unconfirmed peer ranges) only when they relate to a clear error. Do not perform unnecessary upgrades or reordering; explain each change and wait for confirmation.",
843
+ aiFixConservative: "Be conservative: only fix the clear errors listed above (boot failures / duplicate entries / risk-level dependency mismatches). Treat warnings and informational entries (e.g. optional or unconfirmed peer ranges) only when they relate to a clear error. Do not perform unnecessary upgrades or reordering; explain each change and wait for confirmation.",
783
844
  aiFixCopied: "Fix prompt copied — paste it into a new conversation and send when ready",
784
845
  aiFixFail: "Clipboard unavailable — copy the diagnostics below manually",
785
846
  catConflict: "Conflicts",
786
847
  catDeps: "Dependencies",
848
+ catRisk: "Risk",
849
+ catWarn: "Warning",
850
+ catInfo: "Info",
787
851
  catOrder: "Order",
788
852
  /** Summary-strip tooltip for the order count (before/after rule conflicts). */
789
853
  checkOrderTip: "community bundle load order conflicts with declared before/after rules",
790
854
  diagOkAll: "All good: no conflict, dependency or ordering issues found",
855
+ snapSection: "Snapshots & Rollback",
856
+ snapHint: "Snapshots are taken automatically before applying changes; you can also create one manually and roll back anytime.",
857
+ snapCreate: "Create snapshot",
858
+ snapCreating: "Creating…",
859
+ snapCreated: "Snapshot created",
860
+ snapEmpty: "No snapshots yet",
861
+ snapListFail: "Failed to load snapshots: ",
862
+ snapCreateFail: "Failed to create snapshot: ",
863
+ snapRestore: "Restore",
864
+ snapRestoring: "Restoring…",
865
+ snapRestored: "Restored — restart to apply",
866
+ snapRestoreFail: "Failed to restore: ",
867
+ snapRestoreConfirm: "Confirm restore",
868
+ snapRestoreConfirmText: "Restoring overwrites the current profile package.json and configuration from the snapshot; this cannot be undone (create a fresh snapshot first if unsure).",
869
+ snapFiles: "files",
870
+ snapDelete: "Delete",
871
+ snapDeleting: "Deleting…",
872
+ snapDeleted: "Snapshot deleted",
873
+ snapDeleteFail: "Failed to delete snapshot: ",
874
+ snapDeleteConfirm: "Confirm delete",
875
+ snapDeleteConfirmText: "This snapshot cannot be recovered after deletion.",
876
+ marketNoToggle: "The market itself cannot be disabled",
791
877
  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:",
792
878
  hostDependencyMore: "{0} more finding(s) omitted"
793
879
  };
@@ -1452,7 +1538,7 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
1452
1538
  }
1453
1539
  //#endregion
1454
1540
  //#region \0dsh-css:src/client/Market.module.css.mjs
1455
- 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_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}";
1541
+ 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_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}";
1456
1542
  const tagId = "dshmarket/Market.module.css";
1457
1543
  if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]") === null) {
1458
1544
  const tag = document.createElement("style");
@@ -1510,6 +1596,7 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
1510
1596
  "collapseHead": "eGUBIq_collapseHead",
1511
1597
  "collapseIcon": "eGUBIq_collapseIcon",
1512
1598
  "collapseTitle": "eGUBIq_collapseTitle",
1599
+ "confirmRow": "eGUBIq_confirmRow",
1513
1600
  "conflictBody": "eGUBIq_conflictBody",
1514
1601
  "conflictDetailsToggle": "eGUBIq_conflictDetailsToggle",
1515
1602
  "conflictHead": "eGUBIq_conflictHead",
@@ -1529,8 +1616,10 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
1529
1616
  "diagAlert": "eGUBIq_diagAlert",
1530
1617
  "diagArrow": "eGUBIq_diagArrow",
1531
1618
  "diagBadgeCommunity": "eGUBIq_diagBadgeCommunity",
1619
+ "diagBadgeInfo": "eGUBIq_diagBadgeInfo",
1532
1620
  "diagBadgeOfficial": "eGUBIq_diagBadgeOfficial",
1533
1621
  "diagBadgeShadow": "eGUBIq_diagBadgeShadow",
1622
+ "diagBadgeWarn": "eGUBIq_diagBadgeWarn",
1534
1623
  "diagBundle": "eGUBIq_diagBundle",
1535
1624
  "diagCount": "eGUBIq_diagCount",
1536
1625
  "diagEmpty": "eGUBIq_diagEmpty",
@@ -1630,6 +1719,7 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
1630
1719
  "opTop": "eGUBIq_opTop",
1631
1720
  "opVerb": "eGUBIq_opVerb",
1632
1721
  "opWrap": "eGUBIq_opWrap",
1722
+ "orderPanel": "eGUBIq_orderPanel",
1633
1723
  "orphBadge": "eGUBIq_orphBadge",
1634
1724
  "orphRow": "eGUBIq_orphRow",
1635
1725
  "ovArrow": "eGUBIq_ovArrow",
@@ -1641,6 +1731,7 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
1641
1731
  "pageInfo": "eGUBIq_pageInfo",
1642
1732
  "pager": "eGUBIq_pager",
1643
1733
  "pagerPages": "eGUBIq_pagerPages",
1734
+ "panelActions": "eGUBIq_panelActions",
1644
1735
  "panelNote": "eGUBIq_panelNote",
1645
1736
  "pct": "eGUBIq_pct",
1646
1737
  "progress": "eGUBIq_progress",
@@ -1686,6 +1777,10 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
1686
1777
  "setSegOn": "eGUBIq_setSegOn",
1687
1778
  "shot": "eGUBIq_shot",
1688
1779
  "shots": "eGUBIq_shots",
1780
+ "snapConfirmText": "eGUBIq_snapConfirmText",
1781
+ "snapList": "eGUBIq_snapList",
1782
+ "snapMeta": "eGUBIq_snapMeta",
1783
+ "snapRow": "eGUBIq_snapRow",
1689
1784
  "sp": "eGUBIq_sp",
1690
1785
  "spec": "eGUBIq_spec",
1691
1786
  "specTag": "eGUBIq_specTag",
@@ -2219,21 +2314,277 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
2219
2314
  });
2220
2315
  }
2221
2316
  //#endregion
2317
+ //#region src/client/snapshot-panel.tsx
2318
+ /**
2319
+ * Diagnostics sub-panel — issue #98 phase 3 (snapshots & rollback).
2320
+ *
2321
+ * Rendered at the bottom of the Diagnostics tab inside a collapsible section
2322
+ * (the parent keeps it mounted and passes `open`, so it lazy-loads on first
2323
+ * expand and keeps its state across collapses). Lists profile snapshots
2324
+ * (GET /dsh-market/snapshots), creates one (POST /dsh-market/snapshots) and
2325
+ * restores one after an inline double confirmation
2326
+ * (POST /dsh-market/restore-snapshot {snapshot}).
2327
+ *
2328
+ * The list payload is read defensively (bare array or {snapshots: [...]});
2329
+ * `files` entries are {path, json|lines} objects, from which only `path` is
2330
+ * displayed.
2331
+ */
2332
+ async function postJson(url, body) {
2333
+ let res;
2334
+ try {
2335
+ res = await fetch(url, {
2336
+ method: "POST",
2337
+ headers: { "content-type": "application/json" },
2338
+ body: JSON.stringify(body)
2339
+ });
2340
+ } catch {
2341
+ return {
2342
+ status: 0,
2343
+ body: null
2344
+ };
2345
+ }
2346
+ let payload = null;
2347
+ try {
2348
+ payload = await res.json();
2349
+ } catch {}
2350
+ return {
2351
+ status: res.status,
2352
+ body: payload
2353
+ };
2354
+ }
2355
+ /** Snapshot file entries may be plain names or {path, json|lines} objects. */
2356
+ function fileNames(files) {
2357
+ if (!Array.isArray(files)) return [];
2358
+ const names = [];
2359
+ for (const file of files) if (typeof file === "string") names.push(file);
2360
+ else if (file !== null && typeof file === "object") {
2361
+ const path = file.path;
2362
+ if (typeof path === "string") names.push(path);
2363
+ }
2364
+ return names;
2365
+ }
2366
+ function snapshotOf(value) {
2367
+ if (value === null || typeof value !== "object") return null;
2368
+ const item = value;
2369
+ if (typeof item.id !== "string" && typeof item.id !== "number") return null;
2370
+ return {
2371
+ id: String(item.id),
2372
+ createdAt: typeof item.createdAt === "string" || typeof item.createdAt === "number" ? item.createdAt : 0,
2373
+ files: fileNames(item.files)
2374
+ };
2375
+ }
2376
+ function formatTime(value) {
2377
+ const date = new Date(value);
2378
+ return Number.isNaN(date.getTime()) ? String(value) : date.toLocaleString();
2379
+ }
2380
+ function SnapshotPanel(props) {
2381
+ const { t, open, onRefresh } = props;
2382
+ const [snapshots, setSnapshots] = (0, react.useState)(null);
2383
+ const [error, setError] = (0, react.useState)(null);
2384
+ const [msg, setMsg] = (0, react.useState)(null);
2385
+ const [busy, setBusy] = (0, react.useState)(null);
2386
+ /** Snapshot id awaiting the second confirm click (restore), or null. */
2387
+ const [confirmId, setConfirmId] = (0, react.useState)(null);
2388
+ /** Snapshot id awaiting the second confirm click (delete), or null. */
2389
+ const [confirmDeleteId, setConfirmDeleteId] = (0, react.useState)(null);
2390
+ const loaded = (0, react.useRef)(false);
2391
+ const load = (0, react.useCallback)(() => {
2392
+ fetch("/dsh-market/snapshots", { cache: "no-store" }).then((res) => res.json()).then((body) => {
2393
+ const list = Array.isArray(body) ? body : Array.isArray(body.snapshots) ? body.snapshots : [];
2394
+ setSnapshots(list.map(snapshotOf).filter((snap) => snap !== null));
2395
+ setError(null);
2396
+ loaded.current = true;
2397
+ }).catch(() => setError(t("snapListFail") + "network"));
2398
+ }, [t]);
2399
+ (0, react.useEffect)(() => {
2400
+ if (open && !loaded.current) load();
2401
+ }, [open, load]);
2402
+ const create = (0, react.useCallback)(() => {
2403
+ if (busy !== null) return;
2404
+ setBusy("create");
2405
+ setMsg(null);
2406
+ setError(null);
2407
+ postJson("/dsh-market/snapshots", {}).then(({ status, body }) => {
2408
+ if (status >= 200 && status < 300 && body?.ok === true) {
2409
+ setMsg(t("snapCreated"));
2410
+ load();
2411
+ } else {
2412
+ const detail = body !== null && typeof body.error === "string" ? body.error : status === 0 ? "network error" : `HTTP ${String(status)}`;
2413
+ setError(t("snapCreateFail") + detail);
2414
+ }
2415
+ }).catch(() => setError(t("snapCreateFail") + "network")).finally(() => setBusy(null));
2416
+ }, [
2417
+ busy,
2418
+ load,
2419
+ t
2420
+ ]);
2421
+ const restore = (0, react.useCallback)((id) => {
2422
+ if (busy !== null) return;
2423
+ setBusy("restore");
2424
+ setMsg(null);
2425
+ setError(null);
2426
+ postJson("/dsh-market/restore-snapshot", { snapshot: id }).then(({ status, body }) => {
2427
+ if (status >= 200 && status < 300 && body?.ok === true) {
2428
+ setConfirmId(null);
2429
+ setMsg(t("snapRestored"));
2430
+ onRefresh();
2431
+ } else {
2432
+ const detail = body !== null && typeof body.error === "string" ? body.error : status === 0 ? "network error" : `HTTP ${String(status)}`;
2433
+ setError(t("snapRestoreFail") + detail);
2434
+ }
2435
+ }).catch(() => setError(t("snapRestoreFail") + "network")).finally(() => setBusy(null));
2436
+ }, [
2437
+ busy,
2438
+ onRefresh,
2439
+ t
2440
+ ]);
2441
+ /** Delete one snapshot after inline double confirmation. */
2442
+ const remove = (0, react.useCallback)((id) => {
2443
+ if (busy !== null) return;
2444
+ setBusy("delete");
2445
+ setMsg(null);
2446
+ setError(null);
2447
+ postJson("/dsh-market/delete-snapshot", { snapshot: id }).then(({ status, body }) => {
2448
+ if (status >= 200 && status < 300 && body?.ok === true) {
2449
+ setConfirmDeleteId(null);
2450
+ setMsg(t("snapDeleted"));
2451
+ load();
2452
+ } else {
2453
+ const detail = body !== null && typeof body.error === "string" ? body.error : status === 0 ? "network error" : `HTTP ${String(status)}`;
2454
+ setError(t("snapDeleteFail") + detail);
2455
+ }
2456
+ }).catch(() => setError(t("snapDeleteFail") + "network")).finally(() => setBusy(null));
2457
+ }, [
2458
+ busy,
2459
+ load,
2460
+ t
2461
+ ]);
2462
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2463
+ className: Market_module_css_default.orderPanel,
2464
+ children: [
2465
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
2466
+ className: Market_module_css_default.panelNote,
2467
+ children: t("snapHint")
2468
+ }),
2469
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2470
+ className: Market_module_css_default.panelActions,
2471
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
2472
+ variant: "primary",
2473
+ size: "sm",
2474
+ disabled: busy !== null,
2475
+ onClick: create,
2476
+ children: busy === "create" ? t("snapCreating") : t("snapCreate")
2477
+ })
2478
+ }),
2479
+ error !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2480
+ className: Market_module_css_default.err,
2481
+ children: error
2482
+ }),
2483
+ snapshots === null || snapshots.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2484
+ className: Market_module_css_default.diagEmpty,
2485
+ children: t("snapEmpty")
2486
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2487
+ className: Market_module_css_default.snapList,
2488
+ children: snapshots.map((snap) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2489
+ className: Market_module_css_default.snapRow,
2490
+ children: confirmId === snap.id ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
2491
+ className: Market_module_css_default.snapConfirmText,
2492
+ children: t("snapRestoreConfirmText")
2493
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2494
+ className: Market_module_css_default.confirmRow,
2495
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
2496
+ variant: "primary",
2497
+ size: "sm",
2498
+ disabled: busy !== null,
2499
+ onClick: () => restore(snap.id),
2500
+ children: busy === "restore" ? t("snapRestoring") : t("snapRestoreConfirm")
2501
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
2502
+ variant: "ghost",
2503
+ size: "sm",
2504
+ disabled: busy !== null,
2505
+ onClick: () => setConfirmId(null),
2506
+ children: t("cancel")
2507
+ })]
2508
+ })] }) : confirmDeleteId === snap.id ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
2509
+ className: Market_module_css_default.snapConfirmText,
2510
+ children: t("snapDeleteConfirmText")
2511
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2512
+ className: Market_module_css_default.confirmRow,
2513
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
2514
+ variant: "primary",
2515
+ size: "sm",
2516
+ disabled: busy !== null,
2517
+ onClick: () => remove(snap.id),
2518
+ children: busy === "delete" ? t("snapDeleting") : t("snapDeleteConfirm")
2519
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
2520
+ variant: "ghost",
2521
+ size: "sm",
2522
+ disabled: busy !== null,
2523
+ onClick: () => setConfirmDeleteId(null),
2524
+ children: t("cancel")
2525
+ })]
2526
+ })] }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2527
+ className: Market_module_css_default.snapMeta,
2528
+ children: [
2529
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2530
+ className: Market_module_css_default.diagVal,
2531
+ children: formatTime(snap.createdAt)
2532
+ }),
2533
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2534
+ className: Market_module_css_default.spec,
2535
+ children: snap.id
2536
+ }),
2537
+ snap.files.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
2538
+ className: Market_module_css_default.spec,
2539
+ children: [
2540
+ t("snapFiles"),
2541
+ ": ",
2542
+ snap.files.join(", ")
2543
+ ]
2544
+ })
2545
+ ]
2546
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2547
+ className: Market_module_css_default.confirmRow,
2548
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
2549
+ variant: "outline",
2550
+ size: "sm",
2551
+ disabled: busy !== null,
2552
+ onClick: () => setConfirmId(snap.id),
2553
+ children: t("snapRestore")
2554
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
2555
+ variant: "ghost",
2556
+ size: "sm",
2557
+ disabled: busy !== null,
2558
+ onClick: () => setConfirmDeleteId(snap.id),
2559
+ children: t("snapDelete")
2560
+ })]
2561
+ })] })
2562
+ }, snap.id))
2563
+ }),
2564
+ msg !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2565
+ className: Market_module_css_default.okState,
2566
+ children: msg
2567
+ })
2568
+ ]
2569
+ });
2570
+ }
2571
+ //#endregion
2222
2572
  //#region src/client/Diagnostics.tsx
2223
2573
  /**
2224
2574
  * Diagnostics tab — issue #98: renders the profile composition check report
2225
2575
  * served by the host route /dsh-market/check (see src/check.ts). Below the
2226
- * report sits the phase 2 action panel: community-bundle ordering (reorder
2227
- * locally with ↑/↓ or drag, POST to /dsh-market/bundle-order) plus the AI-fix
2228
- * clipboard prompt for HARD issues. The phase 3 snapshots & rollback and
2229
- * plugin presets panels ship in later stacked PRs.
2576
+ * report sit the phase 2/3 action panels: a community-bundle ordering block
2577
+ * (reorder locally with ↑/↓, POST to /dsh-market/bundle-order) and a
2578
+ * snapshots & rollback panel (snapshot-panel.tsx) collapsible, default
2579
+ * collapsed, and lazy-fetching on first expand. The plugin presets panel
2580
+ * ships in a later stacked PR.
2230
2581
  *
2231
2582
  * Read-only view of the loading-layer stack and the conflict surface: bundle
2232
2583
  * order (official vs community), duplicate loader entry ids, peer dependency
2233
2584
  * mismatches, multi-version core packages, overrides and orphan patches. The
2234
- * report shape mirrors the CheckReport interface in src/check.ts; it is
2235
- * re-declared here because the client bundle is built independently of the
2236
- * host tree.
2585
+ * report
2586
+ * shape mirrors the CheckReport interface in src/check.ts; it is re-declared
2587
+ * here because the client bundle is built independently of the host tree.
2237
2588
  */
2238
2589
  /**
2239
2590
  * A collapsible report section: header shows title + count + chevron; the
@@ -2295,8 +2646,9 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
2295
2646
  });
2296
2647
  }
2297
2648
  /** A collapsible section that KEEPS its children mounted (hidden via CSS when
2298
- * collapsed) so the ordering panel below retains its loaded data and
2299
- * in-progress edits across collapses.
2649
+ * collapsed) so the phase 3 panels below retain their loaded data and
2650
+ * in-progress edits across collapses. Children mount from the start, but the
2651
+ * panels only fetch when `open` first becomes true.
2300
2652
  */
2301
2653
  function CollapsibleSection(props) {
2302
2654
  const { title, count, open, onToggle, children } = props;
@@ -2343,10 +2695,19 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
2343
2695
  if (reason.startsWith("name mismatch")) return "orphanNameMismatch";
2344
2696
  return "orphanReasonOther";
2345
2697
  }
2698
+ /** Badge label for one risk-tier peer row (#201). */
2699
+ function peerRiskLabel(peer, t) {
2700
+ return peer.verdict?.kind === "risk" && peer.verdict.risk.direction === "aboveMax" ? t("peerRiskAboveMax") : t("peerRiskBelowMin");
2701
+ }
2702
+ /** Badge label for one warning-tier peer row (optional / aboveMax / legacy). */
2703
+ function peerWarningLabel(peer, t) {
2704
+ if (peer.verdict?.kind !== "warning") return t("checkUnsatisfied");
2705
+ return peer.verdict.warning.reason === "optional" ? t("peerWarnOptional") : t("peerWarnAboveMax");
2706
+ }
2346
2707
  /**
2347
2708
  * Fetch and render the profile check report. Refetches on every mount, so
2348
2709
  * switching tabs away and back re-runs the (cheap, read-only) analysis; the
2349
- * ordering panel calls `refresh()` after applying an order.
2710
+ * phase 3 panels below call `refresh()` after applying changes.
2350
2711
  */
2351
2712
  function Diagnostics(props) {
2352
2713
  const { t } = props;
@@ -2354,12 +2715,12 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
2354
2715
  const [error, setError] = (0, react.useState)(null);
2355
2716
  const [orderOpen, setOrderOpen] = (0, react.useState)(false);
2356
2717
  const [explainOpen, setExplainOpen] = (0, react.useState)(false);
2357
- const [peerInfoOpen, setPeerInfoOpen] = (0, react.useState)(false);
2718
+ const [snapOpen, setSnapOpen] = (0, react.useState)(false);
2358
2719
  const [fixMsg, setFixMsg] = (0, react.useState)(null);
2359
2720
  /** The built AI-fix prompt when the clipboard path failed — rendered as a
2360
2721
  * selectable text block so the user can still copy it manually. */
2361
2722
  const [fixFallback, setFixFallback] = (0, react.useState)(null);
2362
- /** Bump to re-run the /dsh-market/check fetch after an order apply. */
2723
+ /** Bump to re-run the /dsh-market/check fetch after an order/snapshot-restore apply. */
2363
2724
  const [version, setVersion] = (0, react.useState)(0);
2364
2725
  const refresh = (0, react.useCallback)(() => setVersion((v) => v + 1), []);
2365
2726
  /** Community bundle names from the report, in declared order. */
@@ -2377,8 +2738,8 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
2377
2738
  * refresh() refetch returns a NEW array even when the order is unchanged,
2378
2739
  * so a naive `setOrder(communityNames)` effect would wipe the user's
2379
2740
  * in-progress drag/↑↓ edits on every unrelated re-check. Only resync when
2380
- * the report's community order actually CHANGED (apply order) an
2381
- * identical refetch keeps the draft (review M2).
2741
+ * the report's community order actually CHANGED (apply order / snapshot
2742
+ * restore) — an identical refetch keeps the draft (review M2).
2382
2743
  */
2383
2744
  const syncedOrderRef = (0, react.useRef)(null);
2384
2745
  (0, react.useEffect)(() => {
@@ -2496,17 +2857,23 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
2496
2857
  });
2497
2858
  const summary = report.summary;
2498
2859
  const suggested = report.suggestedOrder ?? null;
2499
- const peerConfirmed = report.peerMismatches.filter((peer) => peer.satisfied === false);
2500
- const peerInfo = report.peerMismatches.filter((peer) => peer.satisfied !== false);
2860
+ const peerRisk = report.peerMismatches.filter((peer) => peer.satisfied === false && peer.verdict?.kind === "risk");
2861
+ const peerWarning = report.peerMismatches.filter((peer) => peer.satisfied === false && (peer.verdict === void 0 || peer.verdict.kind === "warning"));
2862
+ const peerInfo = report.peerMismatches.filter((peer) => peer.satisfied === false && peer.verdict?.kind === "none" || peer.satisfied === null);
2863
+ const peerSatisfied = report.peerMismatches.filter((peer) => peer.satisfied === true);
2501
2864
  const catConflict = report.duplicates.length;
2502
- const catDeps = report.peerMismatches.length + report.multiVersion.length;
2865
+ const catRisk = peerRisk.length;
2866
+ const catWarn = peerWarning.length;
2867
+ const catInfo = peerInfo.length;
2868
+ const catMulti = report.multiVersion.length;
2503
2869
  const catOrder = report.orderConflicts?.length ?? 0;
2504
- const anyIssue = catConflict + catDeps + catOrder > 0;
2505
- const hasHardIssues = summary.errors.length > 0 || report.duplicates.length > 0 || report.peerMismatches.some((peer) => peer.satisfied === false);
2870
+ const anyIssue = catConflict + catRisk + catWarn + catInfo + catMulti + catOrder > 0;
2871
+ const hasHardIssues = summary.errors.length > 0 || report.duplicates.length > 0 || catRisk > 0;
2506
2872
  /**
2507
- * Build the AI-fix prompt (errors/warnings/order conflicts + scope) and
2508
- * copy it to the clipboard. The user pastes it into a new conversation
2509
- * and decides whether to send — the agent never runs automatically.
2873
+ * Build the AI-fix prompt (structured errors / duplicates / peer risks /
2874
+ * order conflicts + scope) and copy it to the clipboard. The user pastes it
2875
+ * into a new conversation and decides whether to send — the agent never runs
2876
+ * automatically.
2510
2877
  * (A previous auto-open/prefill attempt was dropped: it was unreliable
2511
2878
  * across host versions, so plain copy + toast is the contract.)
2512
2879
  */
@@ -2518,14 +2885,23 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
2518
2885
  lines.push("");
2519
2886
  lines.push(t("aiFixIfSelf"));
2520
2887
  lines.push("");
2521
- if (summary.errors.length > 0) {
2888
+ const errorLines = summary.errors.filter((line) => !line.startsWith("duplicate loader entry id"));
2889
+ if (errorLines.length > 0) {
2522
2890
  lines.push(`${t("checkErrors")}:`);
2523
- for (const e of summary.errors) lines.push(`- ${e}`);
2891
+ for (const e of errorLines) lines.push(`- ${e}`);
2524
2892
  lines.push("");
2525
2893
  }
2526
- if (summary.warnings.length > 0) {
2527
- lines.push(`${t("checkWarnings")}:`);
2528
- for (const w of summary.warnings) lines.push(`- ${w}`);
2894
+ if (report.duplicates.length > 0) {
2895
+ lines.push(`${t("checkDuplicates")}:`);
2896
+ for (const dup of report.duplicates) lines.push(`- ${dup.id} × ${dup.count} (${dup.layers.join(" / ")})`);
2897
+ lines.push("");
2898
+ }
2899
+ if (peerRisk.length > 0) {
2900
+ lines.push(`${t("checkPeerRisk")}:`);
2901
+ for (const peer of peerRisk) {
2902
+ const direction = peer.verdict?.kind === "risk" && peer.verdict.risk.direction === "aboveMax" ? t("peerRiskAboveMax") : t("peerRiskBelowMin");
2903
+ lines.push(`- ${peer.plugin} → ${peer.name}@${peer.range} (${t("checkResolved")}: ${peer.resolved ?? "—"}, ${direction})`);
2904
+ }
2529
2905
  lines.push("");
2530
2906
  }
2531
2907
  if ((report.orderConflicts ?? []).length > 0) {
@@ -2571,15 +2947,54 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
2571
2947
  }),
2572
2948
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
2573
2949
  className: Market_module_css_default.diagSummaryItem,
2574
- title: t("checkPeerMismatches"),
2950
+ title: t("checkPeerRisk"),
2951
+ children: [
2952
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.StateDot, {
2953
+ state: "error",
2954
+ size: 8
2955
+ }),
2956
+ t("catRisk"),
2957
+ ": ",
2958
+ catRisk
2959
+ ]
2960
+ }),
2961
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
2962
+ className: Market_module_css_default.diagSummaryItem,
2963
+ title: t("checkPeerWarning"),
2575
2964
  children: [
2576
2965
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.StateDot, {
2577
2966
  state: "warning",
2578
2967
  size: 8
2579
2968
  }),
2580
- t("catDeps"),
2969
+ t("catWarn"),
2581
2970
  ": ",
2582
- catDeps
2971
+ catWarn
2972
+ ]
2973
+ }),
2974
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
2975
+ className: Market_module_css_default.diagSummaryItem,
2976
+ title: t("checkPeerInfoTier"),
2977
+ children: [
2978
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.StateDot, {
2979
+ state: "ongoing",
2980
+ size: 8
2981
+ }),
2982
+ t("catInfo"),
2983
+ ": ",
2984
+ catInfo
2985
+ ]
2986
+ }),
2987
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
2988
+ className: Market_module_css_default.diagSummaryItem,
2989
+ title: t("checkMultiVersion"),
2990
+ children: [
2991
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.StateDot, {
2992
+ state: "warning",
2993
+ size: 8
2994
+ }),
2995
+ t("checkMultiVersion"),
2996
+ ": ",
2997
+ catMulti
2583
2998
  ]
2584
2999
  }),
2585
3000
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
@@ -2824,18 +3239,14 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
2824
3239
  }, dup.id))
2825
3240
  })
2826
3241
  }),
2827
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(Section, {
2828
- title: t("checkPeerMismatches"),
2829
- count: peerConfirmed.length,
2830
- empty: t("checkPeerEmpty"),
2831
- overview: report.peerMismatches.length > 0 ? t("checkPeerOverview").replace("{0}", String(peerConfirmed.length)).replace("{1}", String(peerInfo.length)) : void 0,
2832
- alwaysShowBody: peerInfo.length > 0,
2833
- children: [peerConfirmed.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2834
- className: Market_module_css_default.diagEmpty,
2835
- children: t("checkPeerEmpty")
2836
- }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
3242
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Section, {
3243
+ title: t("checkPeerRisk"),
3244
+ count: peerRisk.length,
3245
+ empty: t("checkPeerRiskEmpty"),
3246
+ overview: peerRisk.length > 0 ? `${peerRisk[0].plugin} → ${peerRisk[0].name}@${peerRisk[0].range}(${t("checkResolved")}: ${peerRisk[0].resolved ?? "—"})` : void 0,
3247
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2837
3248
  className: Market_module_css_default.diagList,
2838
- children: peerConfirmed.map((peer, i) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3249
+ children: peerRisk.map((peer, i) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2839
3250
  className: Market_module_css_default.diagRow,
2840
3251
  children: [
2841
3252
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("code", {
@@ -2864,56 +3275,142 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
2864
3275
  }),
2865
3276
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2866
3277
  className: Market_module_css_default.diagBadgeShadow,
2867
- children: t("checkUnsatisfied")
3278
+ children: peerRiskLabel(peer, t)
2868
3279
  })
2869
3280
  ]
2870
3281
  }, i))
2871
- }), peerInfo.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.DisclosureRow, {
2872
- icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronDownOutline14, { size: 14 }),
2873
- title: `${t("checkPeerInfo").replace("{0}", String(peerInfo.length))} (${peerInfo.length})`,
2874
- expandable: true,
2875
- open: peerInfoOpen,
2876
- onToggle: () => setPeerInfoOpen((o) => !o),
2877
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2878
- className: Market_module_css_default.diagList,
2879
- children: peerInfo.map((peer, i) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2880
- className: Market_module_css_default.diagRow,
2881
- children: [
2882
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("code", {
2883
- className: Market_module_css_default.diagVal,
2884
- children: peer.name
2885
- }),
2886
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2887
- className: Market_module_css_default.nm,
2888
- children: peer.plugin
2889
- }),
2890
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
2891
- className: Market_module_css_default.spec,
2892
- children: [
2893
- t("checkRange"),
2894
- ": ",
2895
- peer.range
2896
- ]
2897
- }),
2898
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
2899
- className: Market_module_css_default.spec,
2900
- children: [
2901
- t("checkResolved"),
2902
- ": ",
2903
- peer.resolved ?? "—"
2904
- ]
2905
- }),
2906
- peer.satisfied === true ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2907
- className: Market_module_css_default.okState,
2908
- children: t("checkSatisfied")
2909
- }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
2910
- className: Market_module_css_default.spec,
2911
- children: t("checkUnknown")
2912
- })
2913
- ]
2914
- }, i))
2915
- })
2916
- })]
3282
+ })
3283
+ }),
3284
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Section, {
3285
+ title: t("checkPeerWarning"),
3286
+ count: peerWarning.length,
3287
+ empty: t("checkPeerWarningEmpty"),
3288
+ overview: peerWarning.length > 0 ? `${peerWarning[0].plugin} → ${peerWarning[0].name}@${peerWarning[0].range}(${peerWarningLabel(peerWarning[0], t)})` : void 0,
3289
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
3290
+ className: Market_module_css_default.diagList,
3291
+ children: peerWarning.map((peer, i) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3292
+ className: Market_module_css_default.diagRow,
3293
+ children: [
3294
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("code", {
3295
+ className: Market_module_css_default.diagVal,
3296
+ children: peer.name
3297
+ }),
3298
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3299
+ className: Market_module_css_default.nm,
3300
+ children: peer.plugin
3301
+ }),
3302
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
3303
+ className: Market_module_css_default.spec,
3304
+ children: [
3305
+ t("checkRange"),
3306
+ ": ",
3307
+ peer.range
3308
+ ]
3309
+ }),
3310
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
3311
+ className: Market_module_css_default.spec,
3312
+ children: [
3313
+ t("checkResolved"),
3314
+ ": ",
3315
+ peer.resolved ?? "—"
3316
+ ]
3317
+ }),
3318
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3319
+ className: Market_module_css_default.diagBadgeWarn,
3320
+ children: peerWarningLabel(peer, t)
3321
+ })
3322
+ ]
3323
+ }, i))
3324
+ })
3325
+ }),
3326
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Section, {
3327
+ title: t("checkPeerInfoTier"),
3328
+ count: peerInfo.length,
3329
+ empty: t("checkPeerInfoTierEmpty"),
3330
+ problem: false,
3331
+ overview: peerInfo.length > 0 ? `${peerInfo[0].plugin} → ${peerInfo[0].name}@${peerInfo[0].range}` : void 0,
3332
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
3333
+ className: Market_module_css_default.diagList,
3334
+ children: peerInfo.map((peer, i) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3335
+ className: Market_module_css_default.diagRow,
3336
+ children: [
3337
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("code", {
3338
+ className: Market_module_css_default.diagVal,
3339
+ children: peer.name
3340
+ }),
3341
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3342
+ className: Market_module_css_default.nm,
3343
+ children: peer.plugin
3344
+ }),
3345
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
3346
+ className: Market_module_css_default.spec,
3347
+ children: [
3348
+ t("checkRange"),
3349
+ ": ",
3350
+ peer.range
3351
+ ]
3352
+ }),
3353
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
3354
+ className: Market_module_css_default.spec,
3355
+ children: [
3356
+ t("checkResolved"),
3357
+ ": ",
3358
+ peer.resolved ?? "—"
3359
+ ]
3360
+ }),
3361
+ peer.satisfied === null ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3362
+ className: Market_module_css_default.diagBadgeInfo,
3363
+ children: t("checkUnknown")
3364
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3365
+ className: Market_module_css_default.diagBadgeInfo,
3366
+ children: t("peerInfoUnverified")
3367
+ })
3368
+ ]
3369
+ }, i))
3370
+ })
3371
+ }),
3372
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Section, {
3373
+ title: t("checkPeerSatisfied"),
3374
+ count: peerSatisfied.length,
3375
+ empty: t("checkPeerSatisfiedEmpty"),
3376
+ problem: false,
3377
+ overview: peerSatisfied.length > 0 ? `${peerSatisfied[0].plugin} → ${peerSatisfied[0].name}@${peerSatisfied[0].range}` : void 0,
3378
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
3379
+ className: Market_module_css_default.diagList,
3380
+ children: peerSatisfied.map((peer, i) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3381
+ className: Market_module_css_default.diagRow,
3382
+ children: [
3383
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("code", {
3384
+ className: Market_module_css_default.diagVal,
3385
+ children: peer.name
3386
+ }),
3387
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3388
+ className: Market_module_css_default.nm,
3389
+ children: peer.plugin
3390
+ }),
3391
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
3392
+ className: Market_module_css_default.spec,
3393
+ children: [
3394
+ t("checkRange"),
3395
+ ": ",
3396
+ peer.range
3397
+ ]
3398
+ }),
3399
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
3400
+ className: Market_module_css_default.spec,
3401
+ children: [
3402
+ t("checkResolved"),
3403
+ ": ",
3404
+ peer.resolved ?? "—"
3405
+ ]
3406
+ }),
3407
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3408
+ className: Market_module_css_default.okState,
3409
+ children: t("checkSatisfied")
3410
+ })
3411
+ ]
3412
+ }, i))
3413
+ })
2917
3414
  }),
2918
3415
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Section, {
2919
3416
  title: t("checkMultiVersion"),
@@ -3159,6 +3656,16 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
3159
3656
  }, name))
3160
3657
  })
3161
3658
  ]
3659
+ }),
3660
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CollapsibleSection, {
3661
+ title: t("snapSection"),
3662
+ open: snapOpen,
3663
+ onToggle: () => setSnapOpen((o) => !o),
3664
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SnapshotPanel, {
3665
+ t,
3666
+ open: snapOpen,
3667
+ onRefresh: refresh
3668
+ })
3162
3669
  })
3163
3670
  ]
3164
3671
  });
@@ -4249,6 +4756,7 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
4249
4756
  const [updates, setUpdates] = (0, react.useState)({});
4250
4757
  const [updatingName, setUpdatingName] = (0, react.useState)(null);
4251
4758
  const [staleName, setStaleName] = (0, react.useState)(null);
4759
+ const [restoreName, setRestoreName] = (0, react.useState)(null);
4252
4760
  /** Determinate percent parsed from pnpm's Progress line, when available. */
4253
4761
  const [progressPct, setProgressPct] = (0, react.useState)(null);
4254
4762
  /**
@@ -4934,10 +5442,11 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
4934
5442
  body: "{}"
4935
5443
  }).catch(() => {});
4936
5444
  }, []);
4937
- const doUpdate = (0, react.useCallback)((name, force = false) => {
5445
+ const doUpdate = (0, react.useCallback)((name, force = false, restore = false) => {
4938
5446
  setInstallError(null);
4939
5447
  setActivationWarnings([]);
4940
5448
  setStaleName((prev) => prev === name ? null : prev);
5449
+ setRestoreName((prev) => prev === name ? null : prev);
4941
5450
  setUpdatingName(name);
4942
5451
  updateIdleStrikes.current = 0;
4943
5452
  sessionStorage.setItem("dshm-updating", JSON.stringify({ name }));
@@ -4951,10 +5460,11 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
4951
5460
  return fetch("/dsh-market/update", {
4952
5461
  method: "POST",
4953
5462
  headers: { "content-type": "application/json" },
4954
- body: JSON.stringify(force ? {
5463
+ body: JSON.stringify({
4955
5464
  name,
4956
- force: true
4957
- } : { name })
5465
+ ...force ? { force: true } : {},
5466
+ ...restore ? { restore: true } : {}
5467
+ })
4958
5468
  }).then((res) => res.json().then((body) => ({
4959
5469
  status: res.status,
4960
5470
  body
@@ -4997,7 +5507,8 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
4997
5507
  if (body.stale === true) setStaleName(name);
4998
5508
  if (Array.isArray(body.ignoredBuilds) && body.ignoredBuilds.length > 0) setBuildsSkipped({
4999
5509
  updateName: name,
5000
- names: body.ignoredBuilds.map(String)
5510
+ names: body.ignoredBuilds.map(String),
5511
+ restore
5001
5512
  });
5002
5513
  const text = (v) => typeof v === "string" ? v : v && typeof v.text === "string" ? v.text : v == null ? "" : JSON.stringify(v);
5003
5514
  const detail = text(body.error) || humanOutput([text(body.stderr), text(body.stdout)].filter(Boolean).join("\n")) || "exit " + body.exitCode;
@@ -5005,10 +5516,28 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
5005
5516
  state: "failed",
5006
5517
  reason: detail.trim().slice(-600)
5007
5518
  }));
5008
- setInstallError(t("updateFail") + ": " + name + " — " + detail.trim().slice(-600));
5519
+ setInstallError((restore ? t("restoreFail") : t("updateFail")) + ": " + name + " — " + detail.trim().slice(-600));
5009
5520
  }
5010
5521
  }).catch(() => {});
5011
5522
  }, [refreshInstalled, t]);
5523
+ const askRestore = (0, react.useCallback)((name) => {
5524
+ const spec = installed[name];
5525
+ const entry = data === null || spec === void 0 ? void 0 : entryForDep(data.plugins, name, String(spec), repoIdentities[name], repoHints[name]);
5526
+ setStaleName(null);
5527
+ if (entry === void 0) {
5528
+ setRestoreName(null);
5529
+ setInstallError(t("restoreNoCatalog"));
5530
+ return;
5531
+ }
5532
+ setRestoreName(name);
5533
+ setInstallError(t("restoreHint"));
5534
+ }, [
5535
+ data,
5536
+ installed,
5537
+ repoHints,
5538
+ repoIdentities,
5539
+ t
5540
+ ]);
5012
5541
  const doUseSkin = (0, react.useCallback)((name) => {
5013
5542
  setInstallError(null);
5014
5543
  fetch("/dsh-market/use-skin", {
@@ -6269,7 +6798,7 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
6269
6798
  size: "sm",
6270
6799
  disabled: busyUrl !== null,
6271
6800
  onClick: () => {
6272
- const { plugin, updateName, names } = buildsSkipped;
6801
+ const { plugin, updateName, names, restore } = buildsSkipped;
6273
6802
  setBuildsSkipped(null);
6274
6803
  fetch("/dsh-market/approve-builds", {
6275
6804
  method: "POST",
@@ -6278,7 +6807,7 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
6278
6807
  }).then((res) => res.json()).then((body) => {
6279
6808
  if (!body.ok) setInstallError(String(body.error || "approve failed"));
6280
6809
  else if (plugin !== void 0) doInstall(plugin);
6281
- else if (updateName !== void 0) doUpdate(updateName);
6810
+ else if (updateName !== void 0) doUpdate(updateName, false, restore === true);
6282
6811
  }).catch((error) => setInstallError(String(error)));
6283
6812
  },
6284
6813
  children: t("approveBuilds")
@@ -6329,18 +6858,26 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
6329
6858
  className: Market_module_css_default.err,
6330
6859
  children: [installError, /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6331
6860
  className: Market_module_css_default.staleAction,
6332
- children: [staleName !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
6333
- size: "sm",
6334
- onClick: () => doUpdate(staleName, true),
6335
- children: t("updateNow")
6336
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
6337
- size: "sm",
6338
- variant: "outline",
6339
- icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconDownloadOutline16, { size: 14 }),
6340
- disabled: exportState === "busy",
6341
- onClick: doExportLog,
6342
- children: exportState === "busy" ? t("exportingLog") : t("exportLog")
6343
- })]
6861
+ children: [
6862
+ staleName !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
6863
+ size: "sm",
6864
+ onClick: () => doUpdate(staleName, true),
6865
+ children: t("updateNow")
6866
+ }),
6867
+ restoreName !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
6868
+ size: "sm",
6869
+ onClick: () => doUpdate(restoreName, false, true),
6870
+ children: t("restoreContinue")
6871
+ }),
6872
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
6873
+ size: "sm",
6874
+ variant: "outline",
6875
+ icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconDownloadOutline16, { size: 14 }),
6876
+ disabled: exportState === "busy",
6877
+ onClick: doExportLog,
6878
+ children: exportState === "busy" ? t("exportingLog") : t("exportLog")
6879
+ })
6880
+ ]
6344
6881
  })]
6345
6882
  }),
6346
6883
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
@@ -7095,6 +7632,7 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
7095
7632
  const missing = pendingBackup !== null && !installedFiles.includes(name);
7096
7633
  const entry = data === null ? void 0 : entryForDep(data.plugins, name, String(spec), repoIdentities[name], repoHints[name]);
7097
7634
  const status = updates[name];
7635
+ const localDev = /^(?:link|file):/i.test(String(spec)) || status?.kind === "linked";
7098
7636
  const act = activations[name];
7099
7637
  const meta = act !== void 0 ? activationMeta(act.state, t) : null;
7100
7638
  const version = status && status.version ? "v" + status.version : "";
@@ -7276,7 +7814,7 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
7276
7814
  disabled: updatingName !== null,
7277
7815
  onClick: () => doUpdate(name),
7278
7816
  children: t("update")
7279
- }) : status && status.kind === "linked" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
7817
+ }) : localDev ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
7280
7818
  className: Market_module_css_default.metaTag,
7281
7819
  title: t("linkedDev"),
7282
7820
  children: t("linkedDev")
@@ -7290,14 +7828,20 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
7290
7828
  className: Market_module_css_default.dangerBtn,
7291
7829
  disabled: true,
7292
7830
  children: t("uninstalling")
7293
- }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
7831
+ }) : /* @__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, {
7832
+ variant: "outline",
7833
+ size: "sm",
7834
+ disabled: removingName !== null || busyUrl !== null || updatingName !== null,
7835
+ onClick: () => askRestore(name),
7836
+ children: t("restore")
7837
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
7294
7838
  variant: "outline",
7295
7839
  size: "sm",
7296
7840
  className: Market_module_css_default.dangerBtn,
7297
7841
  disabled: removingName !== null || busyUrl !== null || updatingName !== null,
7298
7842
  onClick: () => setRemoveConfirm(name),
7299
7843
  children: t("uninstall")
7300
- }))]
7844
+ })] }))]
7301
7845
  })
7302
7846
  ]
7303
7847
  })]