dsh-plugin-ekko-skin-manager 0.3.0 → 0.3.1

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/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Ekko 皮肤管理器 · 旧版兼容入口
2
2
 
3
- **主题管理功能已整合到新版主题中。** 新用户请直接安装 [初音未来与玫瑰女王主题套装](https://github.com/cjjchina3088191870-sudo/dsh-plugin-miku-theme),主题内已包含管理界面、手机导航、外观设置和启动视频功能。
3
+ **主题管理功能已整合到新版主题中。** 新用户请直接安装 [玫瑰女王、初音未来与丝柯克主题套装](https://github.com/cjjchina3088191870-sudo/dsh-plugin-miku-theme),主题内已包含管理界面、手机导航、外观设置和启动视频功能。
4
4
 
5
5
  本仓库保留旧版兼容与迁移说明。新版主题可独立使用,安装其他兼容主题后,会自动纳入同一管理界面。
6
6
 
@@ -14,7 +14,7 @@ dsh plugin --profile web add dsh-plugin-miku-theme
14
14
 
15
15
  重启 DSH 并刷新网页,进入 **账号菜单 → 设置 → Ekko 皮肤** 即可使用。
16
16
 
17
- 电脑与手机可以分别上传启动视频,支持 MP4 / WebM、预览、声音控制与不同画面比例。完整介绍和主题预览请查看 [初音未来与玫瑰女王主题套装仓库](https://github.com/cjjchina3088191870-sudo/dsh-plugin-miku-theme#readme)。
17
+ 电脑与手机可以分别上传启动视频,支持 MP4 / WebM、预览、声音控制与不同画面比例。完整介绍和主题预览请查看 [玫瑰女王、初音未来与丝柯克主题套装仓库](https://github.com/cjjchina3088191870-sudo/dsh-plugin-miku-theme#readme)。
18
18
 
19
19
  ## 已安装独立管理器的用户
20
20
 
@@ -27,7 +27,9 @@ dsh plugin --profile web add dsh-plugin-miku-theme
27
27
 
28
28
  完成后重启 DSH 并刷新网页。主题偏好和已保存的视频会保留;使用其他 profile 时,将 `web` 替换为对应名称。
29
29
 
30
- 独立管理器 0.3.x 与新版主题套装可以共用管理界面,但日常使用只安装主题即可。
30
+ 独立管理器 **0.3.1 及以上**与新版三主题套装可以共用管理界面,支持丝柯克、三个主题分别保存的外观设置与电脑/手机启动视频。日常使用只安装主题即可。
31
+
32
+ 保留独立管理器时,请一起升级到当前版本;0.3.0 及更早版本不支持丝柯克。
31
33
 
32
34
  ## 许可
33
35
 
package/design-qa.md CHANGED
@@ -52,3 +52,13 @@ H.264 1280×720 MP4 与 270×480 WebM 已在 Chromium 桌面及 393×760 手机
52
52
  ### 2026-11-07 · 启动片段的备用编码
53
53
 
54
54
  内置片段增加 VP8/Opus WebM,与原 MP4 保持同一内容;上传相同文件时通过内容哈希匹配备用编码。浏览器可以选择可用编码,媒体加载失败会尝试另一源,预览不再自动跳到 0.8 秒。核心 22 项通过;通过 HTTPS 网关访问已保存的视频,桌面和手机模拟视口均确认时间前进及可见动画,并验证屏蔽 WebM 后 MP4 回退仍正常。尚未在用户出现故障的实际设备上复现其原始错误。
55
+
56
+ ## 2026-11-13 — third-theme compatibility release 0.3.1
57
+
58
+ The legacy compatibility entry and the integrated bundle share the same root-scoped `client-v2` and `host-v2` leases. The first loaded entry owns the manager. Version0.3.0 only knew Rose/Miku and rejected a Skirk provider if it loaded before the new bundle.
59
+
60
+ The standalone core now mirrors the bundle's three-theme controller, UI, catalog/assets/preview routes, startup-video store/player and theme preferences. Its own package identity, migration command and shared lease entries remain. README now requires compatibility entry0.3.1+ for the three-theme suite; new users still install only the theme bundle.
61
+
62
+ Regression evidence: test/skirk-compat.test.mjs evaluates both independently built client bundles in one DOM, loads the standalone manager first, then registers all three theme providers. It verifies exactly one shared client, selected Skirk, continued service after the first lease is removed, and release after the last lease. An HTTP test verifies all three bundled themes, Skirk artwork/font/preview routes and independent Skirk mobile fit settings. These are contract/JSDOM/HTTP checks, not a full DSH browser install.
63
+
64
+ Full manager suite:22 passed,0 failed,2 existing native-runtime tests skipped because DSH_MODULES was not supplied. Log: work/rose-queen-release/manager-compat-tests.log.
package/lib/client.js CHANGED
@@ -27,7 +27,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
27
27
  ));
28
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
29
 
30
- // src/client-entry.mjs
30
+ // work/rose-queen-release/manager-publish/src/client-entry.mjs
31
31
  var client_entry_exports = {};
32
32
  __export(client_entry_exports, {
33
33
  acquireClient: () => acquireClient,
@@ -36,13 +36,13 @@ __export(client_entry_exports, {
36
36
  });
37
37
  module.exports = __toCommonJS(client_entry_exports);
38
38
 
39
- // src/client.jsx
39
+ // work/rose-queen-release/manager-publish/src/client.jsx
40
40
  var import_react2 = __toESM(require("react"), 1);
41
41
 
42
- // src/video-settings.jsx
42
+ // work/rose-queen-release/manager-publish/src/video-settings.jsx
43
43
  var import_react = __toESM(require("react"), 1);
44
44
 
45
- // src/boot-player.mjs
45
+ // work/rose-queen-release/manager-publish/src/boot-player.mjs
46
46
  var BOOT_CSS = `
47
47
  .ekko-boot{position:fixed;inset:0;z-index:2147483000;display:grid;place-items:center;background:#10171e;color:#fff;opacity:1;isolation:isolate;font:14px/1.5 system-ui,sans-serif}
48
48
  .ekko-boot[data-skin="rose"]{background:#241a20;--boot-accent:#f3b3c6}.ekko-boot[data-skin="miku"]{--boot-accent:#81eff0}
@@ -255,7 +255,7 @@ function playBoot(skin, options, { preview = false } = {}) {
255
255
  return done;
256
256
  }
257
257
 
258
- // src/video-settings.jsx
258
+ // work/rose-queen-release/manager-publish/src/video-settings.jsx
259
259
  var API = "./api/ekko-skins/";
260
260
  var LIMIT = 96 * 1024 * 1024;
261
261
  var fields = (entry) => Object.fromEntries(["enabled", "sound", "volume", "fit", "maxSeconds"].map((k) => [k, entry[k]]));
@@ -379,7 +379,7 @@ function VideoSettings({ skin }) {
379
379
  };
380
380
  if (!data || !draft) return /* @__PURE__ */ import_react.default.createElement("section", { className: "ekko-skin-options ekko-video-settings", "data-testid": "ekko-video-settings" }, /* @__PURE__ */ import_react.default.createElement("h3", null, "\u542F\u52A8\u89C6\u9891"), /* @__PURE__ */ import_react.default.createElement("p", { role: "status" }, message || "\u6B63\u5728\u8BFB\u53D6\u89C6\u9891\u8BBE\u7F6E\u2026"), /* @__PURE__ */ import_react.default.createElement("button", { type: "button", className: "ekko-skin-button", onClick: load }, "\u91CD\u8BD5"));
381
381
  const update = (patch) => setDraft({ ...draft, ...patch }), fitKey = device === "mobile" ? "mobileFit" : "fit";
382
- return /* @__PURE__ */ import_react.default.createElement("section", { className: "ekko-skin-options ekko-video-settings", "data-testid": "ekko-video-settings", "data-device": device }, /* @__PURE__ */ import_react.default.createElement("div", { className: "ekko-skin-toolbar" }, /* @__PURE__ */ import_react.default.createElement("h3", null, skin === "miku" ? "\u521D\u97F3\u672A\u6765" : "\u73AB\u7470\u5973\u738B", " \xB7 \u542F\u52A8\u89C6\u9891"), /* @__PURE__ */ import_react.default.createElement("span", { className: "ekko-skin-version" }, "\u6BCF\u6B3E\u4E3B\u9898\u5206\u522B\u4FDD\u5B58")), /* @__PURE__ */ import_react.default.createElement("div", { className: "ekko-video-controls" }, /* @__PURE__ */ import_react.default.createElement("label", { className: "ekko-skin-option" }, /* @__PURE__ */ import_react.default.createElement("span", null, "\u542F\u7528\u542F\u52A8\u89C6\u9891", /* @__PURE__ */ import_react.default.createElement("small", null, "\u9875\u9762\u542F\u52A8\u65F6\u64AD\u653E\uFF0C\u53EF\u968F\u65F6\u8DF3\u8FC7")), /* @__PURE__ */ import_react.default.createElement("input", { type: "checkbox", checked: draft.enabled, disabled: busy, onChange: (e) => update({ enabled: e.target.checked }) })), /* @__PURE__ */ import_react.default.createElement("label", { className: "ekko-skin-option" }, /* @__PURE__ */ import_react.default.createElement("span", null, "\u64AD\u653E\u58F0\u97F3", /* @__PURE__ */ import_react.default.createElement("small", null, "\u6D4F\u89C8\u5668\u9650\u5236\u81EA\u52A8\u64AD\u653E\u65F6\u5148\u9759\u97F3\uFF0C\u70B9\u51FB\u53EF\u5F00\u542F\u58F0\u97F3")), /* @__PURE__ */ import_react.default.createElement("input", { type: "checkbox", checked: draft.sound, disabled: busy, onChange: (e) => update({ sound: e.target.checked }) })), /* @__PURE__ */ import_react.default.createElement("label", { className: "ekko-skin-option" }, /* @__PURE__ */ import_react.default.createElement("span", null, "\u97F3\u91CF", /* @__PURE__ */ import_react.default.createElement("small", null, Math.round(draft.volume * 100), "%")), /* @__PURE__ */ import_react.default.createElement("input", { type: "range", min: "0", max: "100", value: Math.round(draft.volume * 100), disabled: busy, onChange: (e) => update({ volume: Number(e.target.value) / 100 }) })), /* @__PURE__ */ import_react.default.createElement("label", { className: "ekko-skin-option" }, /* @__PURE__ */ import_react.default.createElement("span", null, "\u6700\u957F\u64AD\u653E\u65F6\u95F4", /* @__PURE__ */ import_react.default.createElement("small", null, "5\u201360 \u79D2\uFF0C\u5230\u65F6\u81EA\u52A8\u8FDB\u5165\u754C\u9762")), /* @__PURE__ */ import_react.default.createElement("input", { className: "ekko-video-seconds", type: "number", min: "5", max: "60", value: draft.maxSeconds, disabled: busy, onChange: (e) => update({ maxSeconds: Number(e.target.value) }) }))), /* @__PURE__ */ import_react.default.createElement("div", { className: "ekko-video-device-tabs", role: "tablist", "aria-label": "\u542F\u52A8\u89C6\u9891\u5C4F\u5E55\u7C7B\u578B" }, ["desktop", "mobile"].map((value) => /* @__PURE__ */ import_react.default.createElement("button", { key: value, type: "button", role: "tab", id: "ekko-video-tab-" + skin + "-" + value, "aria-selected": device === value, "aria-controls": "ekko-video-panel-" + skin, disabled: busy, className: "ekko-skin-button", "data-active": device === value, onClick: () => {
382
+ return /* @__PURE__ */ import_react.default.createElement("section", { className: "ekko-skin-options ekko-video-settings", "data-testid": "ekko-video-settings", "data-device": device }, /* @__PURE__ */ import_react.default.createElement("div", { className: "ekko-skin-toolbar" }, /* @__PURE__ */ import_react.default.createElement("h3", null, skin === "skirk" ? "\u4E1D\u67EF\u514B \xB7 \u78F7\u661F\u73AF\u8F68" : skin === "miku" ? "\u521D\u97F3\u672A\u6765" : "\u73AB\u7470\u5973\u738B", " \xB7 \u542F\u52A8\u89C6\u9891"), /* @__PURE__ */ import_react.default.createElement("span", { className: "ekko-skin-version" }, "\u6BCF\u6B3E\u4E3B\u9898\u5206\u522B\u4FDD\u5B58")), /* @__PURE__ */ import_react.default.createElement("div", { className: "ekko-video-controls" }, /* @__PURE__ */ import_react.default.createElement("label", { className: "ekko-skin-option" }, /* @__PURE__ */ import_react.default.createElement("span", null, "\u542F\u7528\u542F\u52A8\u89C6\u9891", /* @__PURE__ */ import_react.default.createElement("small", null, "\u9875\u9762\u542F\u52A8\u65F6\u64AD\u653E\uFF0C\u53EF\u968F\u65F6\u8DF3\u8FC7")), /* @__PURE__ */ import_react.default.createElement("input", { type: "checkbox", checked: draft.enabled, disabled: busy, onChange: (e) => update({ enabled: e.target.checked }) })), /* @__PURE__ */ import_react.default.createElement("label", { className: "ekko-skin-option" }, /* @__PURE__ */ import_react.default.createElement("span", null, "\u64AD\u653E\u58F0\u97F3", /* @__PURE__ */ import_react.default.createElement("small", null, "\u6D4F\u89C8\u5668\u9650\u5236\u81EA\u52A8\u64AD\u653E\u65F6\u5148\u9759\u97F3\uFF0C\u70B9\u51FB\u53EF\u5F00\u542F\u58F0\u97F3")), /* @__PURE__ */ import_react.default.createElement("input", { type: "checkbox", checked: draft.sound, disabled: busy, onChange: (e) => update({ sound: e.target.checked }) })), /* @__PURE__ */ import_react.default.createElement("label", { className: "ekko-skin-option" }, /* @__PURE__ */ import_react.default.createElement("span", null, "\u97F3\u91CF", /* @__PURE__ */ import_react.default.createElement("small", null, Math.round(draft.volume * 100), "%")), /* @__PURE__ */ import_react.default.createElement("input", { type: "range", min: "0", max: "100", value: Math.round(draft.volume * 100), disabled: busy, onChange: (e) => update({ volume: Number(e.target.value) / 100 }) })), /* @__PURE__ */ import_react.default.createElement("label", { className: "ekko-skin-option" }, /* @__PURE__ */ import_react.default.createElement("span", null, "\u6700\u957F\u64AD\u653E\u65F6\u95F4", /* @__PURE__ */ import_react.default.createElement("small", null, "5\u201360 \u79D2\uFF0C\u5230\u65F6\u81EA\u52A8\u8FDB\u5165\u754C\u9762")), /* @__PURE__ */ import_react.default.createElement("input", { className: "ekko-video-seconds", type: "number", min: "5", max: "60", value: draft.maxSeconds, disabled: busy, onChange: (e) => update({ maxSeconds: Number(e.target.value) }) }))), /* @__PURE__ */ import_react.default.createElement("div", { className: "ekko-video-device-tabs", role: "tablist", "aria-label": "\u542F\u52A8\u89C6\u9891\u5C4F\u5E55\u7C7B\u578B" }, ["desktop", "mobile"].map((value) => /* @__PURE__ */ import_react.default.createElement("button", { key: value, type: "button", role: "tab", id: "ekko-video-tab-" + skin + "-" + value, "aria-selected": device === value, "aria-controls": "ekko-video-panel-" + skin, disabled: busy, className: "ekko-skin-button", "data-active": device === value, onClick: () => {
383
383
  setDevice(value);
384
384
  setMessage("");
385
385
  } }, value === "mobile" ? "\u624B\u673A\u7AEF\u89C6\u9891" : "\u7535\u8111\u7AEF\u89C6\u9891"))), /* @__PURE__ */ import_react.default.createElement("div", { className: "ekko-video-device-panel", role: "tabpanel", id: "ekko-video-panel-" + skin, "aria-labelledby": "ekko-video-tab-" + skin + "-" + device }, /* @__PURE__ */ import_react.default.createElement("p", { className: "ekko-skin-version" }, device === "mobile" ? "\u624B\u673A\u53CA\u7A84\u5C4F\u81EA\u52A8\u4F7F\u7528\u6B64\u89C6\u9891\uFF0C\u63A8\u8350 9:16 \u7AD6\u5C4F\uFF1B\u672A\u4E0A\u4F20\u65F6\u6CBF\u7528\u7535\u8111\u7AEF\u89C6\u9891\u3002" : "\u7535\u8111\u53CA\u5BBD\u5C4F\u4F7F\u7528\u6B64\u89C6\u9891\uFF0C\u63A8\u8350 16:9 \u6A2A\u5C4F\u3002", "\u652F\u6301\u5176\u4ED6\u5206\u8FA8\u7387\u4E0E\u6BD4\u4F8B\u3002"), /* @__PURE__ */ import_react.default.createElement("label", { className: "ekko-skin-option" }, /* @__PURE__ */ import_react.default.createElement("span", null, device === "mobile" ? "\u624B\u673A\u7AEF" : "\u7535\u8111\u7AEF", "\u753B\u9762\u663E\u793A"), /* @__PURE__ */ import_react.default.createElement("select", { "aria-label": (device === "mobile" ? "\u624B\u673A\u7AEF" : "\u7535\u8111\u7AEF") + "\u753B\u9762\u663E\u793A", value: draft[fitKey], disabled: busy, onChange: (e) => update({ [fitKey]: e.target.value }) }, /* @__PURE__ */ import_react.default.createElement("option", { value: "cover" }, "\u94FA\u6EE1\u5C4F\u5E55"), /* @__PURE__ */ import_react.default.createElement("option", { value: "contain" }, "\u5B8C\u6574\u663E\u793A"))), /* @__PURE__ */ import_react.default.createElement("video", { key: device + source, ref: preview, className: "ekko-video-preview", "data-device": device, muted: !draft.sound, controls: true, playsInline: true, preload: "metadata", onLoadedMetadata: () => setMediaError(""), onError: (e) => {
@@ -390,9 +390,9 @@ function VideoSettings({ skin }) {
390
390
  }, src: source, "aria-label": (device === "mobile" ? "\u624B\u673A\u7AEF" : "\u7535\u8111\u7AEF") + "\u542F\u52A8\u89C6\u9891\u9884\u89C8" }), /* @__PURE__ */ import_react.default.createElement("p", { className: "ekko-video-name" }, entry.source === "upload" ? entry.name : entry.source === "fallback" ? "\u6CBF\u7528\u7535\u8111\u7AEF\u89C6\u9891" + (base.name ? " \xB7 " + base.name : "") : "\u9ED8\u8BA4\u542F\u52A8\u89C6\u9891"), mediaError && /* @__PURE__ */ import_react.default.createElement("p", { className: "ekko-video-message", role: "status" }, mediaError)), /* @__PURE__ */ import_react.default.createElement("p", { className: "ekko-skin-version" }, "\u652F\u6301 MP4 / WebM\uFF0C\u6BCF\u4E2A\u89C6\u9891\u6700\u5927 96 MiB\u3002\u7535\u8111\u7AEF\u4E0E\u624B\u673A\u7AEF\u5206\u522B\u4FDD\u5B58\uFF0C\u53EF\u5728\u5F53\u524D DSH \u7684\u5176\u4ED6\u8BBE\u5907\u4E0A\u4F7F\u7528\u3002"), /* @__PURE__ */ import_react.default.createElement("input", { ref: input, className: "ekko-video-file", tabIndex: "-1", type: "file", accept: "video/mp4,video/webm,.mp4,.webm", disabled: busy, "aria-label": "\u4E0A\u4F20" + (device === "mobile" ? "\u624B\u673A\u7AEF" : "\u7535\u8111\u7AEF") + "\u542F\u52A8\u89C6\u9891", onChange: (e) => void upload(e.target.files?.[0]) }), progress !== null && /* @__PURE__ */ import_react.default.createElement("div", { role: "status" }, /* @__PURE__ */ import_react.default.createElement("progress", { max: "100", value: progress }), /* @__PURE__ */ import_react.default.createElement("span", null, " \u4E0A\u4F20 ", progress, "%"), /* @__PURE__ */ import_react.default.createElement("button", { type: "button", className: "ekko-skin-button", onClick: () => operation.current?.abort() }, "\u53D6\u6D88\u4E0A\u4F20")), /* @__PURE__ */ import_react.default.createElement("div", { className: "ekko-video-actions" }, /* @__PURE__ */ import_react.default.createElement("button", { type: "button", className: "ekko-skin-button", disabled: busy, onClick: () => input.current?.click() }, "\u4E0A\u4F20", device === "mobile" ? "\u624B\u673A\u7AEF" : "\u7535\u8111\u7AEF", "\u89C6\u9891"), /* @__PURE__ */ import_react.default.createElement("button", { type: "button", className: "ekko-skin-button", disabled: busy, onClick: () => void playBoot(skin, { ...entry, ...fields(draft), fit: draft[fitKey] }, { preview: true }) }, "\u9884\u89C8\u542F\u52A8\u6548\u679C"), /* @__PURE__ */ import_react.default.createElement("button", { type: "button", className: "ekko-skin-button", disabled: busy || entry.source !== "upload", onClick: () => void save(true) }, device === "mobile" ? "\u6CBF\u7528\u7535\u8111\u7AEF\u89C6\u9891" : "\u6062\u590D\u9ED8\u8BA4\u89C6\u9891"), /* @__PURE__ */ import_react.default.createElement("button", { type: "button", className: "ekko-skin-button", "data-active": "true", disabled: busy, onClick: () => void save() }, "\u4FDD\u5B58\u542F\u52A8\u8BBE\u7F6E")), /* @__PURE__ */ import_react.default.createElement("p", { role: "status", className: "ekko-video-message" }, message));
391
391
  }
392
392
 
393
- // src/controller.mjs
393
+ // work/rose-queen-release/manager-publish/src/controller.mjs
394
394
  var SELECTION_KEY = "dsh:ekko-skins:selection:v1";
395
- var SKIN_IDS = ["default", "rose", "miku"];
395
+ var SKIN_IDS = ["default", "rose", "miku", "skirk"];
396
396
  function readSelection(storage, fallback = "rose") {
397
397
  try {
398
398
  const value = JSON.parse(storage.getItem(SELECTION_KEY));
@@ -474,10 +474,7 @@ function createController({ storage, mount, prepare = async () => {
474
474
  return () => listeners.delete(fn);
475
475
  },
476
476
  register(provider) {
477
- if (!["rose", "miku"].includes(provider.id) || typeof provider.plugin?.apply !== "function") throw new TypeError("Unknown Ekko skin provider");
478
- const existing = providers.get(provider.id);
479
- if (existing && (existing.priority || 0) > (provider.priority || 0)) return () => {
480
- };
477
+ if (!["rose", "miku", "skirk"].includes(provider.id) || typeof provider.plugin?.apply !== "function") throw new TypeError("Unknown Ekko skin provider");
481
478
  providers.set(provider.id, provider);
482
479
  publish({});
483
480
  if (initialized && provider.id === wanted) void reconcile();
@@ -517,10 +514,10 @@ function createController({ storage, mount, prepare = async () => {
517
514
  };
518
515
  }
519
516
 
520
- // src/generated.mjs
521
- var STYLES = ".ekko-skins{display:grid;gap:18px;color:var(--dsw-alias-label-primary);font:14px/1.6 var(--ds-font-family,system-ui);}\n.ekko-skins h2,.ekko-skins h3,.ekko-skins p{margin:0;}.ekko-skins h2{font-size:20px;line-height:1.5;}.ekko-skins h3{font-size:15px;}\n.ekko-skins-intro{display:grid;gap:5px;}.ekko-skins-intro p,.ekko-skin-version,.ekko-skin-option small{color:var(--dsw-alias-label-secondary);font-size:12px;}\n.ekko-skin-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:14px;}\n.ekko-skin-card{min-width:0;overflow:hidden;border:1px solid var(--dsw-alias-border-l2);border-radius:16px;background:var(--dsw-alias-bg-layer-1);box-shadow:0 4px 12px #234c6510;}\n.ekko-skin-card[data-active='true']{border-color:var(--dsw-alias-brand-primary);box-shadow:0 0 0 2px color-mix(in srgb,var(--dsw-alias-brand-primary) 18%,transparent);}\n.ekko-skin-cover{display:block;width:100%;aspect-ratio:1400/787;object-fit:cover;border-bottom:1px solid var(--dsw-alias-border-l3);}\n.ekko-skin-description{display:grid;gap:10px;padding:13px;}.ekko-skin-title{display:flex;align-items:center;justify-content:space-between;gap:8px;}.ekko-skin-state{color:var(--dsw-alias-brand-text);font-size:11px;white-space:nowrap;}\n.ekko-skin-button{border:1px solid var(--dsw-alias-border-l2);border-radius:9px;padding:7px 12px;background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-primary);font:inherit;cursor:pointer;}\n.ekko-skin-button:disabled{opacity:.65;cursor:default;}.ekko-skin-button:focus-visible,.ekko-skins input:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:3px;}\n.ekko-skin-button[data-active='true']{background:var(--dsw-alias-brand-primary);border-color:var(--dsw-alias-brand-primary);color:var(--dsw-alias-brand-primary-invert);}\n.ekko-skin-option select{min-height:40px;max-width:52%;padding:6px 9px;border:1px solid var(--dsw-alias-border-l2);border-radius:9px;background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-primary);font:inherit;}\n.ekko-skin-option select:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:3px;}\n.ekko-skin-toolbar{display:flex;align-items:center;justify-content:space-between;gap:12px;}.ekko-skin-options{padding:15px;border:1px solid var(--dsw-alias-border-l2);border-radius:14px;background:var(--dsw-alias-bg-layer-1);}\n.ekko-skin-option{display:flex;align-items:center;justify-content:space-between;gap:18px;min-height:40px;padding:8px 0;border-bottom:1px solid var(--dsw-alias-border-l3);}.ekko-skin-option:last-child{border:0;}.ekko-skin-option span{display:grid;gap:2px;}.ekko-skin-option input{accent-color:var(--dsw-alias-brand-primary);}.ekko-skin-option input[type='range']{width:130px;max-width:40%;}.ekko-skin-error{padding:10px 12px;border:1px solid var(--dsw-alias-border-l2);border-radius:10px;color:var(--dsw-alias-state-danger,#c43d3d);font-size:13px;}\n@media(max-width:640px){.ekko-skin-grid{grid-template-columns:1fr;}.ekko-skins h2{font-size:18px;}.ekko-skin-toolbar{align-items:flex-start;}.ekko-skin-description{padding:12px;}}\n/* Keep the native settings shell usable on phones: tabs above the content. */\n@media(max-width:640px){\n [role='dialog']:has(>[class*='_nav']>[class*='_navList']){flex-direction:column;width:calc(100vw - 24px);max-width:calc(100vw - 24px);height:min(800px,calc(100dvh - 48px));}\n [role='dialog']:has(>[class*='_nav']>[class*='_navList'])>[class*='_nav']{width:100%;padding:15px 12px 0;gap:12px;}\n [role='dialog']:has(>[class*='_nav']>[class*='_navList']) [class*='_navTitle']{padding-inline:5px;}\n [role='dialog']:has(>[class*='_nav']>[class*='_navList']) [class*='_navList']{flex-direction:row;gap:4px;overflow:auto;padding-bottom:5px;}\n [role='dialog']:has(>[class*='_nav']>[class*='_navList']) [class*='_navCell']{flex:none;width:max-content;height:36px;padding:7px 10px;font-size:13px;}\n [role='dialog']:has(>[class*='_nav']>[class*='_navList'])>[class*='_content']{min-height:0;width:100%;}\n [role='dialog']:has(>[class*='_nav']>[class*='_navList'])>[class*='_content']>[class*='_header']{position:absolute;top:10px;right:10px;height:auto;padding:0;}\n [role='dialog']:has(>[class*='_nav']>[class*='_navList'])>[class*='_content']>[class*='_header'] button{white-space:nowrap;flex-shrink:0;}\n [role='dialog']:has(>[class*='_nav']>[class*='_navList']) [class*='_options']{padding:12px 12px 18px;min-width:0;}\n .ekko-skins{gap:13px;width:100%;min-width:0;}\n .ekko-skin-grid{grid-template-columns:repeat(2,minmax(0,1fr));gap:10px;}\n .ekko-skin-description{padding:9px;gap:7px;min-width:0;}.ekko-skin-title{gap:4px;flex-wrap:wrap;}.ekko-skin-title h3{font-size:13px;}.ekko-skin-state{font-size:10px;}\n .ekko-skin-button{font-size:12px;padding:6px;min-height:36px;max-width:100%;overflow-wrap:anywhere;}\n .ekko-skin-toolbar{flex-wrap:wrap;min-width:0;}.ekko-skin-options{min-width:0;padding:11px;}.ekko-skin-options .ekko-skin-toolbar h3{font-size:13px;}\n}\n\n.ekko-video-settings{display:grid;gap:10px;min-width:0}.ekko-video-settings .ekko-skin-option{margin:0}.ekko-video-preview{display:block;width:100%;max-height:160px;border:1px solid var(--dsw-alias-border-l2);border-radius:12px;background:#101820;object-fit:contain}.ekko-video-name{font-weight:500;overflow-wrap:anywhere}.ekko-video-file{position:absolute;width:1px;height:1px;opacity:0;overflow:hidden;pointer-events:none}.ekko-video-file::file-selector-button{font:inherit;padding:8px 12px;border:1px solid var(--dsw-alias-border-l2);border-radius:8px;background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-primary);margin-right:8px}.ekko-video-actions{display:flex;gap:8px;flex-wrap:wrap}.ekko-video-seconds{width:72px;padding:7px;border-radius:8px;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-base);color:inherit;font:inherit}.ekko-video-settings progress{max-width:100%;accent-color:var(--dsw-alias-brand-primary)}.ekko-video-message{font-size:12px;overflow-wrap:anywhere}\n\n.ekko-video-controls{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:0 18px;min-width:0}.ekko-video-controls .ekko-skin-option{min-width:0;gap:10px}.ekko-video-controls .ekko-skin-option:last-child{grid-column:1/-1}.ekko-video-controls .ekko-skin-option span{min-width:0}.ekko-video-controls input[type=range]{width:100px}.ekko-video-actions .ekko-skin-button{min-height:40px}.ekko-video-settings{scroll-margin-top:12px}\n@media(max-width:640px){.ekko-video-controls{grid-template-columns:1fr}.ekko-video-preview{max-height:140px}.ekko-video-actions{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:8px}.ekko-video-actions .ekko-skin-button{width:100%;min-height:42px}.ekko-video-settings .ekko-skin-option small{font-size:11px}}\n\n.ekko-video-device-tabs{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:6px;padding:5px;border:1px solid var(--dsw-alias-border-l3);border-radius:13px;background:var(--dsw-alias-bg-layer-2)}\n.ekko-video-device-tabs .ekko-skin-button{min-height:40px;box-shadow:none;background:transparent;border-color:transparent}\n.ekko-video-device-tabs .ekko-skin-button[data-active='true']{background:var(--dsw-alias-brand-primary);border-color:var(--dsw-alias-brand-primary)}\n.ekko-video-device-panel{display:grid;gap:8px;min-width:0}\n.ekko-video-preview[data-device='mobile']{width:100%;height:210px;max-height:210px;object-fit:contain}\n.ekko-video-device-tabs .ekko-skin-button:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:1px}\n.ekko-video-controls .ekko-skin-option:last-child{grid-column:auto}\n@media(max-width:640px){.ekko-video-preview[data-device='mobile']{height:200px;max-height:200px}.ekko-video-device-tabs{gap:4px;padding:4px}.ekko-video-device-tabs .ekko-skin-button{min-height:40px}}\n\n/* Both phone modes use the active skin's existing artwork and jewellery tokens. */\n.ekko-mobile-navigation{display:none;}\n@media(max-width:700px) and (orientation:portrait){\n body[data-ekko-mobile-nav] .ekko-mobile-navigation{position:fixed;z-index:65;display:flex;box-sizing:border-box;align-items:center;color:var(--dsw-alias-brand-primary);}\n body[data-ekko-mobile-nav] .ekko-mobile-brand,\n body[data-ekko-mobile-nav] .ekko-mobile-action{position:relative;display:flex;flex:none;align-items:center;justify-content:center;box-sizing:border-box;width:44px;height:44px;min-height:44px;padding:8px;border:1px solid var(--ekko-rim-soft);border-radius:14px;background:var(--ekko-panel);box-shadow:inset 0 1px 0 var(--ekko-shine),0 3px 8px var(--ekko-shadow);color:inherit;cursor:pointer;}\n body[data-ekko-mobile-nav] .ekko-mobile-brand{padding:6px;border-color:var(--ekko-rim);}\n body[data-ekko-mobile-nav] .ekko-mobile-brand img{display:block;width:31px;height:31px;object-fit:contain;}\n body[data-ekko-mobile-nav] .ekko-mobile-action :is(svg,img){width:21px;height:21px;flex:none;}\n body[data-ekko-mobile-nav] .ekko-mobile-action[data-ekko-mobile-action='new']{margin-top:4px;border-color:var(--ekko-rim);box-shadow:inset 0 0 0 2px var(--ekko-shine),0 3px 8px var(--ekko-shadow);}\n body[data-ekko-mobile-nav] .ekko-mobile-action[aria-current]{background:var(--ekko-tint);border-color:var(--ekko-rim);}\n body[data-ekko-mobile-nav] .ekko-mobile-action:disabled{opacity:.45;cursor:default;}\n body[data-ekko-mobile-nav] .ekko-mobile-navigation button:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:2px;}\n body[data-ekko-mobile-nav] .ekko-mobile-navigation button:active{box-shadow:inset 1px 2px 5px var(--ekko-shadow);}\n body[data-ekko-mobile-nav='corner'] .ekko-mobile-navigation{top:calc(env(safe-area-inset-top,0px) + 7px);left:9px;}\n body[data-ekko-mobile-nav='corner'] :is(.ekko-mobile-actions,.ekko-mobile-footer){display:none;}\n /* Set clearance on the content column so native drawer/platform frame rules cannot override it. */\n body[data-ekko-mobile-nav='corner'] [data-ekko-mobile-frame] [data-ekko-mobile-center]{--dsh-frame-leading-clearance:62px;}\n body[data-ekko-mobile-nav='corner'] :is(.miku-welcome-brand,.rose-welcome-brand){padding-left:48px;}\n body[data-ekko-mobile-nav='corner'] :is(.miku-mark,.rose-mark){display:none;}\n body[data-ekko-mobile-nav='rail'] .ekko-mobile-navigation{inset:0 auto 0 0;width:60px;flex-direction:column;gap:10px;padding:calc(env(safe-area-inset-top,0px) + 13px) 7px max(10px,env(safe-area-inset-bottom,0px));background:var(--ekko-panel);border-right:1px solid var(--ekko-rim);box-shadow:inset -2px 0 0 var(--ekko-shine),inset -4px 0 0 var(--ekko-rim-soft);}\n body[data-ekko-mobile-nav='rail'] .ekko-mobile-actions{display:flex;flex:1;min-height:0;flex-direction:column;gap:10px;padding:0 0 4px;overflow:auto;scrollbar-width:none;}\n body[data-ekko-mobile-nav='rail'] .ekko-mobile-footer{display:flex;flex:none;padding-top:5px;border-top:1px solid var(--ekko-rim-soft);}\n body[data-ekko-mobile-nav='rail'] [data-ekko-mobile-frame] [data-ekko-mobile-center]{margin-inline-start:60px;--dsh-frame-leading-clearance:0px;}\n /* The native drawer stays inert while closed. Only our launchers remain visible. */\n body[data-ekko-mobile-nav] [data-ekko-mobile-frame] [data-shell-leading]{display:none;}\n body[data-ekko-mobile-nav] [data-ekko-mobile-frame] [data-ekko-mobile-drawer]{z-index:80;background:var(--ekko-panel);box-shadow:12px 0 30px var(--ekko-shadow);}\n body[data-ekko-mobile-nav][data-ekko-mobile-drawer-open='true'] .ekko-mobile-navigation{visibility:hidden;pointer-events:none;}\n}\n\n/* Keep phone controls aligned when the icon rail reduces the editor width. */\n@media(max-width:700px) and (orientation:portrait){\n body[data-ekko-mobile-nav] [data-ekko-mobile-center] :is([data-miku-editor-root],[data-rose-editor-root]){width:calc(100% + 8px);margin-inline-start:-4px;}\n body[data-ekko-mobile-nav] [data-ekko-mobile-center] [data-composer-card]{container:ekko-composer / inline-size;gap:6px;padding-top:14px;}\n body[data-ekko-mobile-nav] [data-ekko-mobile-center] :is([data-miku-editor-root],[data-rose-editor-root]) [data-composer-card]{min-height:140px;}\n body[data-ekko-mobile-nav] [data-ekko-mobile-center] [data-composer-card]>[class*='_scroll']{flex:1;min-height:56px;margin-right:0;}\n body[data-ekko-mobile-nav] [data-ekko-mobile-center] [data-composer-card] [contenteditable]{padding-inline:12px;}\n body[data-ekko-mobile-nav] [data-ekko-mobile-center] [data-composer-card] button[class*='_primary']{align-self:center;transform:none;}\n}\n@container ekko-composer (max-width:350px){\n body[data-ekko-mobile-nav] [data-ekko-mobile-center] [data-composer-card]>[class*='_row']{display:grid;grid-template-columns:auto minmax(0,1fr) 30px 34px;grid-template-areas:'extras extras extras extras' 'tools model activity send';gap:4px 6px;padding:4px 7px 6px;align-items:center;}\n body[data-ekko-mobile-nav] [data-ekko-mobile-center] [data-composer-card]>[class*='_row']:not(:has([data-slot='conversation.input.right']:not(:empty))){grid-template-areas:'tools model activity send';}\n body[data-ekko-mobile-nav] [data-ekko-mobile-center] [data-composer-card] [class*='_tools']{grid-area:tools;gap:5px;align-items:center;}\n body[data-ekko-mobile-nav] [data-ekko-mobile-center] [data-composer-card] :is([class*='_trailing'],[class*='_standardControls'],[class*='_modes']){display:contents;}\n body[data-ekko-mobile-nav] [data-ekko-mobile-center] [data-composer-card] :is([class*='_tools'],[class*='_standardControls'])[hidden]{display:none!important;}\n body[data-ekko-mobile-nav] [data-ekko-mobile-center] [data-composer-card] [class*='_trailing']>[class*='_activity']{display:contents;}\n body[data-ekko-mobile-nav] [data-ekko-mobile-center] [data-slot='conversation.input.right']{grid-area:extras;display:flex!important;align-items:center;justify-content:flex-start;gap:8px;min-width:0;max-width:100%;overflow-x:auto;scrollbar-width:thin;}\n body[data-ekko-mobile-nav] [data-ekko-mobile-center] [data-slot='conversation.input.right']:empty{display:none!important;}\n body[data-ekko-mobile-nav] [data-ekko-mobile-center] [data-slot='conversation.input.right']>*{flex:none;}\n body[data-ekko-mobile-nav] [data-ekko-mobile-center] [data-slot='conversation.input.model']{grid-area:model;display:flex!important;min-width:0;justify-content:flex-end;align-items:center;}\n body[data-ekko-mobile-nav] [data-ekko-mobile-center] [data-slot='conversation.input.model']>div{min-width:0;max-width:100%;}\n body[data-ekko-mobile-nav] [data-ekko-mobile-center] [data-slot='conversation.input.model'] button{min-width:0;max-width:100%;height:34px;padding-inline:4px;}\n body[data-ekko-mobile-nav] [data-ekko-mobile-center] [data-slot='conversation.input.model'] :is([class*='_triggerLabel'],[class*='_triggerEffort']){display:none;}\n body[data-ekko-mobile-nav] [data-ekko-mobile-center] [data-slot='conversation.input.model'] button>svg:first-child{display:block;flex:none;width:18px;height:18px;}\n body[data-ekko-mobile-nav] [data-ekko-mobile-center] [data-slot='conversation.input.activity']{grid-area:activity;display:flex!important;align-items:center;justify-content:center;}\n body[data-ekko-mobile-nav] [data-ekko-mobile-center] [data-composer-card] button[class*='_primary']{grid-area:send;justify-self:end;}\n body[data-ekko-mobile-nav] [data-ekko-mobile-center] [data-composer-card] button:is([aria-label^='\u8BBF\u95EE\u6A21\u5F0F'],[aria-label^='Access mode']){padding-inline:6px;}\n}\n";
517
+ // work/rose-queen-release/manager-publish/src/generated.mjs
518
+ var STYLES = ".ekko-skins{display:grid;gap:18px;color:var(--dsw-alias-label-primary);font:14px/1.6 var(--ds-font-family,system-ui);}\n.ekko-skins h2,.ekko-skins h3,.ekko-skins p{margin:0;}.ekko-skins h2{font-size:20px;line-height:1.5;}.ekko-skins h3{font-size:15px;}\n.ekko-skins-intro{display:grid;gap:5px;}.ekko-skins-intro p,.ekko-skin-version,.ekko-skin-option small{color:var(--dsw-alias-label-secondary);font-size:12px;}\n.ekko-skin-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,220px),1fr));gap:14px;}\n.ekko-skin-card{min-width:0;overflow:hidden;border:1px solid var(--dsw-alias-border-l2);border-radius:16px;background:var(--dsw-alias-bg-layer-1);box-shadow:0 4px 12px #234c6510;}\n.ekko-skin-card[data-active='true']{border-color:var(--dsw-alias-brand-primary);box-shadow:0 0 0 2px color-mix(in srgb,var(--dsw-alias-brand-primary) 18%,transparent);}\n.ekko-skin-cover{display:block;width:100%;aspect-ratio:1400/787;object-fit:cover;border-bottom:1px solid var(--dsw-alias-border-l3);}\n.ekko-skin-description{display:grid;gap:10px;padding:13px;}.ekko-skin-title{display:flex;align-items:center;justify-content:space-between;gap:8px;}.ekko-skin-state{color:var(--dsw-alias-brand-text);font-size:11px;white-space:nowrap;}\n.ekko-skin-button{border:1px solid var(--dsw-alias-border-l2);border-radius:9px;padding:7px 12px;background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-primary);font:inherit;cursor:pointer;}\n.ekko-skin-button:disabled{opacity:.65;cursor:default;}.ekko-skin-button:focus-visible,.ekko-skins input:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:3px;}\n.ekko-skin-button[data-active='true']{background:var(--dsw-alias-brand-primary);border-color:var(--dsw-alias-brand-primary);color:var(--dsw-alias-brand-primary-invert);}\n.ekko-skin-option select{min-height:40px;max-width:52%;padding:6px 9px;border:1px solid var(--dsw-alias-border-l2);border-radius:9px;background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-primary);font:inherit;}\n.ekko-skin-option select:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:3px;}\n.ekko-skin-toolbar{display:flex;align-items:center;justify-content:space-between;gap:12px;}.ekko-skin-options{padding:15px;border:1px solid var(--dsw-alias-border-l2);border-radius:14px;background:var(--dsw-alias-bg-layer-1);}\n.ekko-skin-option{display:flex;align-items:center;justify-content:space-between;gap:18px;min-height:40px;padding:8px 0;border-bottom:1px solid var(--dsw-alias-border-l3);}.ekko-skin-option:last-child{border:0;}.ekko-skin-option span{display:grid;gap:2px;}.ekko-skin-option input{accent-color:var(--dsw-alias-brand-primary);}.ekko-skin-option input[type='range']{width:130px;max-width:40%;}.ekko-skin-error{padding:10px 12px;border:1px solid var(--dsw-alias-border-l2);border-radius:10px;color:var(--dsw-alias-state-danger,#c43d3d);font-size:13px;}\n@media(max-width:640px){.ekko-skin-grid{grid-template-columns:1fr;}.ekko-skins h2{font-size:18px;}.ekko-skin-toolbar{align-items:flex-start;}.ekko-skin-description{padding:12px;}}\n/* Keep the native settings shell usable on phones: tabs above the content. */\n@media(max-width:640px){\n [role='dialog']:has(>[class*='_nav']>[class*='_navList']){flex-direction:column;width:calc(100vw - 24px);max-width:calc(100vw - 24px);height:min(800px,calc(100dvh - 48px));}\n [role='dialog']:has(>[class*='_nav']>[class*='_navList'])>[class*='_nav']{width:100%;padding:15px 12px 0;gap:12px;}\n [role='dialog']:has(>[class*='_nav']>[class*='_navList']) [class*='_navTitle']{padding-inline:5px;}\n [role='dialog']:has(>[class*='_nav']>[class*='_navList']) [class*='_navList']{flex-direction:row;gap:4px;overflow:auto;padding-bottom:5px;}\n [role='dialog']:has(>[class*='_nav']>[class*='_navList']) [class*='_navCell']{flex:none;width:max-content;height:36px;padding:7px 10px;font-size:13px;}\n [role='dialog']:has(>[class*='_nav']>[class*='_navList'])>[class*='_content']{min-height:0;width:100%;}\n [role='dialog']:has(>[class*='_nav']>[class*='_navList'])>[class*='_content']>[class*='_header']{position:absolute;top:10px;right:10px;height:auto;padding:0;}\n [role='dialog']:has(>[class*='_nav']>[class*='_navList'])>[class*='_content']>[class*='_header'] button{white-space:nowrap;flex-shrink:0;}\n [role='dialog']:has(>[class*='_nav']>[class*='_navList']) [class*='_options']{padding:12px 12px 18px;min-width:0;}\n .ekko-skins{gap:13px;width:100%;min-width:0;}\n .ekko-skin-grid{grid-template-columns:repeat(auto-fit,minmax(min(100%,220px),1fr));gap:10px;}\n .ekko-skin-description{padding:9px;gap:7px;min-width:0;}.ekko-skin-title{gap:4px;flex-wrap:wrap;}.ekko-skin-title h3{font-size:13px;}.ekko-skin-state{font-size:10px;}\n .ekko-skin-button{font-size:12px;padding:6px;min-height:36px;max-width:100%;overflow-wrap:anywhere;}\n .ekko-skin-toolbar{flex-wrap:wrap;min-width:0;}.ekko-skin-options{min-width:0;padding:11px;}.ekko-skin-options .ekko-skin-toolbar h3{font-size:13px;}\n}\n\n.ekko-video-settings{display:grid;gap:10px;min-width:0}.ekko-video-settings .ekko-skin-option{margin:0}.ekko-video-preview{display:block;width:100%;max-height:160px;border:1px solid var(--dsw-alias-border-l2);border-radius:12px;background:#101820;object-fit:contain}.ekko-video-name{font-weight:500;overflow-wrap:anywhere}.ekko-video-file{position:absolute;width:1px;height:1px;opacity:0;overflow:hidden;pointer-events:none}.ekko-video-file::file-selector-button{font:inherit;padding:8px 12px;border:1px solid var(--dsw-alias-border-l2);border-radius:8px;background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-primary);margin-right:8px}.ekko-video-actions{display:flex;gap:8px;flex-wrap:wrap}.ekko-video-seconds{width:72px;padding:7px;border-radius:8px;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-base);color:inherit;font:inherit}.ekko-video-settings progress{max-width:100%;accent-color:var(--dsw-alias-brand-primary)}.ekko-video-message{font-size:12px;overflow-wrap:anywhere}\n\n.ekko-video-controls{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,220px),1fr));gap:0 18px;min-width:0}.ekko-video-controls .ekko-skin-option{min-width:0;gap:10px}.ekko-video-controls .ekko-skin-option:last-child{grid-column:1/-1}.ekko-video-controls .ekko-skin-option span{min-width:0}.ekko-video-controls input[type=range]{width:100px}.ekko-video-actions .ekko-skin-button{min-height:40px}.ekko-video-settings{scroll-margin-top:12px}\n@media(max-width:640px){.ekko-video-controls{grid-template-columns:1fr}.ekko-video-preview{max-height:140px}.ekko-video-actions{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,220px),1fr));gap:8px}.ekko-video-actions .ekko-skin-button{width:100%;min-height:42px}.ekko-video-settings .ekko-skin-option small{font-size:11px}}\n\n.ekko-video-device-tabs{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,220px),1fr));gap:6px;padding:5px;border:1px solid var(--dsw-alias-border-l3);border-radius:13px;background:var(--dsw-alias-bg-layer-2)}\n.ekko-video-device-tabs .ekko-skin-button{min-height:40px;box-shadow:none;background:transparent;border-color:transparent}\n.ekko-video-device-tabs .ekko-skin-button[data-active='true']{background:var(--dsw-alias-brand-primary);border-color:var(--dsw-alias-brand-primary)}\n.ekko-video-device-panel{display:grid;gap:8px;min-width:0}\n.ekko-video-preview[data-device='mobile']{width:100%;height:210px;max-height:210px;object-fit:contain}\n.ekko-video-device-tabs .ekko-skin-button:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:1px}\n.ekko-video-controls .ekko-skin-option:last-child{grid-column:auto}\n@media(max-width:640px){.ekko-video-preview[data-device='mobile']{height:200px;max-height:200px}.ekko-video-device-tabs{gap:4px;padding:4px}.ekko-video-device-tabs .ekko-skin-button{min-height:40px}}\n\n/* Both phone modes use the active skin's existing artwork and jewellery tokens. */\n.ekko-mobile-navigation{display:none;}\n@media(max-width:700px) and (orientation:portrait){\n body[data-ekko-mobile-nav] .ekko-mobile-navigation{position:fixed;z-index:65;display:flex;box-sizing:border-box;align-items:center;color:var(--dsw-alias-brand-primary);}\n body[data-ekko-mobile-nav] .ekko-mobile-brand,\n body[data-ekko-mobile-nav] .ekko-mobile-action{position:relative;display:flex;flex:none;align-items:center;justify-content:center;box-sizing:border-box;width:44px;height:44px;min-height:44px;padding:8px;border:1px solid var(--ekko-rim-soft);border-radius:14px;background:var(--ekko-panel);box-shadow:inset 0 1px 0 var(--ekko-shine),0 3px 8px var(--ekko-shadow);color:inherit;cursor:pointer;}\n body[data-ekko-mobile-nav] .ekko-mobile-brand{padding:6px;border-color:var(--ekko-rim);}\n body[data-ekko-mobile-nav] .ekko-mobile-brand img{display:block;width:31px;height:31px;object-fit:contain;}\n body[data-ekko-mobile-nav] .ekko-mobile-action :is(svg,img){width:21px;height:21px;flex:none;}\n body[data-ekko-mobile-nav] .ekko-mobile-action[data-ekko-mobile-action='new']{margin-top:4px;border-color:var(--ekko-rim);box-shadow:inset 0 0 0 2px var(--ekko-shine),0 3px 8px var(--ekko-shadow);}\n body[data-ekko-mobile-nav] .ekko-mobile-action[aria-current]{background:var(--ekko-tint);border-color:var(--ekko-rim);}\n body[data-ekko-mobile-nav] .ekko-mobile-action:disabled{opacity:.45;cursor:default;}\n body[data-ekko-mobile-nav] .ekko-mobile-navigation button:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:2px;}\n body[data-ekko-mobile-nav] .ekko-mobile-navigation button:active{box-shadow:inset 1px 2px 5px var(--ekko-shadow);}\n body[data-ekko-mobile-nav='corner'] .ekko-mobile-navigation{top:calc(env(safe-area-inset-top,0px) + 7px);left:9px;}\n body[data-ekko-mobile-nav='corner'] :is(.ekko-mobile-actions,.ekko-mobile-footer){display:none;}\n /* Set clearance on the content column so native drawer/platform frame rules cannot override it. */\n body[data-ekko-mobile-nav='corner'] [data-ekko-mobile-frame] [data-ekko-mobile-center]{--dsh-frame-leading-clearance:62px;}\n body[data-ekko-mobile-nav='corner'] :is(.miku-welcome-brand,.rose-welcome-brand){padding-left:48px;}\n body[data-ekko-mobile-nav='corner'] :is(.miku-mark,.rose-mark){display:none;}\n body[data-ekko-mobile-nav='rail'] .ekko-mobile-navigation{inset:0 auto 0 0;width:60px;flex-direction:column;gap:10px;padding:calc(env(safe-area-inset-top,0px) + 13px) 7px max(10px,env(safe-area-inset-bottom,0px));background:var(--ekko-panel);border-right:1px solid var(--ekko-rim);box-shadow:inset -2px 0 0 var(--ekko-shine),inset -4px 0 0 var(--ekko-rim-soft);}\n body[data-ekko-mobile-nav='rail'] .ekko-mobile-actions{display:flex;flex:1;min-height:0;flex-direction:column;gap:10px;padding:0 0 4px;overflow:auto;scrollbar-width:none;}\n body[data-ekko-mobile-nav='rail'] .ekko-mobile-footer{display:flex;flex:none;padding-top:5px;border-top:1px solid var(--ekko-rim-soft);}\n body[data-ekko-mobile-nav='rail'] [data-ekko-mobile-frame] [data-ekko-mobile-center]{margin-inline-start:60px;--dsh-frame-leading-clearance:0px;}\n /* The native drawer stays inert while closed. Only our launchers remain visible. */\n body[data-ekko-mobile-nav] [data-ekko-mobile-frame] [data-shell-leading]{display:none;}\n body[data-ekko-mobile-nav] [data-ekko-mobile-frame] [data-ekko-mobile-drawer]{z-index:80;background:var(--ekko-panel);box-shadow:12px 0 30px var(--ekko-shadow);}\n body[data-ekko-mobile-nav][data-ekko-mobile-drawer-open='true'] .ekko-mobile-navigation{visibility:hidden;pointer-events:none;}\n}\n\n/* Keep phone controls aligned when the icon rail reduces the editor width. */\n@media(max-width:700px) and (orientation:portrait){\n body[data-ekko-mobile-nav] [data-ekko-mobile-center] :is([data-miku-editor-root],[data-rose-editor-root]){width:calc(100% + 8px);margin-inline-start:-4px;}\n body[data-ekko-mobile-nav] [data-ekko-mobile-center] [data-composer-card]{container:ekko-composer / inline-size;gap:6px;padding-top:14px;}\n body[data-ekko-mobile-nav] [data-ekko-mobile-center] :is([data-miku-editor-root],[data-rose-editor-root]) [data-composer-card]{min-height:140px;}\n body[data-ekko-mobile-nav] [data-ekko-mobile-center] [data-composer-card]>[class*='_scroll']{flex:1;min-height:56px;margin-right:0;}\n body[data-ekko-mobile-nav] [data-ekko-mobile-center] [data-composer-card] [contenteditable]{padding-inline:12px;}\n body[data-ekko-mobile-nav] [data-ekko-mobile-center] [data-composer-card] button[class*='_primary']{align-self:center;transform:none;}\n}\n@container ekko-composer (max-width:350px){\n body[data-ekko-mobile-nav] [data-ekko-mobile-center] [data-composer-card]>[class*='_row']{display:grid;grid-template-columns:auto minmax(0,1fr) 30px 34px;grid-template-areas:'extras extras extras extras' 'tools model activity send';gap:4px 6px;padding:4px 7px 6px;align-items:center;}\n body[data-ekko-mobile-nav] [data-ekko-mobile-center] [data-composer-card]>[class*='_row']:not(:has([data-slot='conversation.input.right']:not(:empty))){grid-template-areas:'tools model activity send';}\n body[data-ekko-mobile-nav] [data-ekko-mobile-center] [data-composer-card] [class*='_tools']{grid-area:tools;gap:5px;align-items:center;}\n body[data-ekko-mobile-nav] [data-ekko-mobile-center] [data-composer-card] :is([class*='_trailing'],[class*='_standardControls'],[class*='_modes']){display:contents;}\n body[data-ekko-mobile-nav] [data-ekko-mobile-center] [data-composer-card] :is([class*='_tools'],[class*='_standardControls'])[hidden]{display:none!important;}\n body[data-ekko-mobile-nav] [data-ekko-mobile-center] [data-composer-card] [class*='_trailing']>[class*='_activity']{display:contents;}\n body[data-ekko-mobile-nav] [data-ekko-mobile-center] [data-slot='conversation.input.right']{grid-area:extras;display:flex!important;align-items:center;justify-content:flex-start;gap:8px;min-width:0;max-width:100%;overflow-x:auto;scrollbar-width:thin;}\n body[data-ekko-mobile-nav] [data-ekko-mobile-center] [data-slot='conversation.input.right']:empty{display:none!important;}\n body[data-ekko-mobile-nav] [data-ekko-mobile-center] [data-slot='conversation.input.right']>*{flex:none;}\n body[data-ekko-mobile-nav] [data-ekko-mobile-center] [data-slot='conversation.input.model']{grid-area:model;display:flex!important;min-width:0;justify-content:flex-end;align-items:center;}\n body[data-ekko-mobile-nav] [data-ekko-mobile-center] [data-slot='conversation.input.model']>div{min-width:0;max-width:100%;}\n body[data-ekko-mobile-nav] [data-ekko-mobile-center] [data-slot='conversation.input.model'] button{min-width:0;max-width:100%;height:34px;padding-inline:4px;}\n body[data-ekko-mobile-nav] [data-ekko-mobile-center] [data-slot='conversation.input.model'] :is([class*='_triggerLabel'],[class*='_triggerEffort']){display:none;}\n body[data-ekko-mobile-nav] [data-ekko-mobile-center] [data-slot='conversation.input.model'] button>svg:first-child{display:block;flex:none;width:18px;height:18px;}\n body[data-ekko-mobile-nav] [data-ekko-mobile-center] [data-slot='conversation.input.activity']{grid-area:activity;display:flex!important;align-items:center;justify-content:center;}\n body[data-ekko-mobile-nav] [data-ekko-mobile-center] [data-composer-card] button[class*='_primary']{grid-area:send;justify-self:end;}\n body[data-ekko-mobile-nav] [data-ekko-mobile-center] [data-composer-card] button:is([aria-label^='\u8BBF\u95EE\u6A21\u5F0F'],[aria-label^='Access mode']){padding-inline:6px;}\n}\n";
522
519
 
523
- // src/mobile-navigation.mjs
520
+ // work/rose-queen-release/manager-publish/src/mobile-navigation.mjs
524
521
  function createMobileNavigation({ layout, document: doc = document }) {
525
522
  const view = doc.defaultView, body = doc.body;
526
523
  let current = null, nav, brand, actions, footer, frame, sidebar, center, raf = 0, disposed = false;
@@ -706,12 +703,12 @@ function createMobileNavigation({ layout, document: doc = document }) {
706
703
  };
707
704
  }
708
705
 
709
- // src/client.jsx
706
+ // work/rose-queen-release/manager-publish/src/client.jsx
710
707
  var inject = ["slots", "theme", "layout"];
711
- var NAMES = { rose: { zh: "\u73AB\u7470\u5973\u738B", en: "Rose Queen" }, miku: { zh: "\u521D\u97F3\u672A\u6765", en: "Hatsune Miku" } };
708
+ var NAMES = { rose: { zh: "\u73AB\u7470\u5973\u738B", en: "Rose Queen" }, miku: { zh: "\u521D\u97F3\u672A\u6765", en: "Hatsune Miku" }, skirk: { zh: "\u4E1D\u67EF\u514B \xB7 \u78F7\u661F\u73AF\u8F68", en: "Skirk \xB7 Stellar Orbit" } };
712
709
  var COPY = {
713
- zh: { nav: "Ekko \u76AE\u80A4", title: "\u73AB\u7470\u4E0E\u521D\u97F3", intro: "\u9009\u62E9\u4F60\u7684\u521B\u4F5C\u7A7A\u95F4\uFF1B\u6BCF\u4E2A\u4E3B\u9898\u7684\u88C5\u9970\u504F\u597D\u5206\u522B\u4FDD\u7559\u3002", use: "\u4F7F\u7528", active: "\u5F53\u524D\u4F7F\u7528", switching: "\u6B63\u5728\u5207\u6362\u2026", native: "\u539F\u751F\u754C\u9762", options: "\u4E3B\u9898\u88C5\u9970", artwork: "\u6B22\u8FCE\u9875\u88C5\u9970", companion: "\u5BF9\u8BDD\u4EBA\u7269\u80CC\u666F", polaroid: "\u53F3\u4E0B\u89D2\u7167\u7247", opacity: "\u5BF9\u8BDD\u80CC\u666F\u6D53\u5EA6", reset: "\u6062\u590D\u6B64\u4E3B\u9898\u9ED8\u8BA4", loading: "\u6B63\u5728\u52A0\u8F7D\u4E3B\u9898\u2026", unavailable: "\u53EF\u9009\u4E3B\u9898\uFF0C\u5C1A\u672A\u5B89\u88C5", retry: "\u91CD\u8BD5", loadFailed: "\u76AE\u80A4\u7BA1\u7406\u5668\u6682\u65F6\u65E0\u6CD5\u52A0\u8F7D\uFF0C\u8BF7\u91CD\u8BD5\u3002", materialFailed: "\u4E3B\u9898\u7D20\u6750\u672A\u80FD\u52A0\u8F7D\uFF0C\u8BF7\u91CD\u8BD5\u3002" },
714
- en: { nav: "Ekko skins", title: "Rose & Miku", intro: "Choose your creative space. Each skin keeps its own appearance preferences.", use: "Use", active: "In use", switching: "Switching\u2026", native: "Native appearance", options: "Artwork preferences", artwork: "Welcome artwork", companion: "Chat character background", polaroid: "Corner photo", opacity: "Chat background opacity", reset: "Reset this skin", loading: "Loading skins\u2026", unavailable: "Optional skin, not installed", retry: "Retry", loadFailed: "Unable to load the skin manager. Please retry.", materialFailed: "Unable to load the skin artwork. Please retry." }
710
+ zh: { nav: "Ekko \u76AE\u80A4", title: "Ekko \u521B\u4F5C\u7A7A\u95F4", intro: "\u9009\u62E9\u4F60\u7684\u521B\u4F5C\u7A7A\u95F4\uFF1B\u6BCF\u4E2A\u4E3B\u9898\u7684\u88C5\u9970\u504F\u597D\u5206\u522B\u4FDD\u7559\u3002", use: "\u4F7F\u7528", active: "\u5F53\u524D\u4F7F\u7528", switching: "\u6B63\u5728\u5207\u6362\u2026", native: "\u539F\u751F\u754C\u9762", options: "\u4E3B\u9898\u88C5\u9970", artwork: "\u6B22\u8FCE\u9875\u88C5\u9970", companion: "\u5BF9\u8BDD\u4EBA\u7269\u80CC\u666F", polaroid: "\u53F3\u4E0B\u89D2\u7167\u7247", opacity: "\u5BF9\u8BDD\u80CC\u666F\u6D53\u5EA6", reset: "\u6062\u590D\u6B64\u4E3B\u9898\u9ED8\u8BA4", loading: "\u6B63\u5728\u52A0\u8F7D\u4E3B\u9898\u2026", unavailable: "\u53EF\u9009\u4E3B\u9898\uFF0C\u5C1A\u672A\u5B89\u88C5", retry: "\u91CD\u8BD5", loadFailed: "\u76AE\u80A4\u7BA1\u7406\u5668\u6682\u65F6\u65E0\u6CD5\u52A0\u8F7D\uFF0C\u8BF7\u91CD\u8BD5\u3002", materialFailed: "\u4E3B\u9898\u7D20\u6750\u672A\u80FD\u52A0\u8F7D\uFF0C\u8BF7\u91CD\u8BD5\u3002" },
711
+ en: { nav: "Ekko skins", title: "Ekko creative spaces", intro: "Choose your creative space. Each skin keeps its own appearance preferences.", use: "Use", active: "In use", switching: "Switching\u2026", native: "Native appearance", options: "Artwork preferences", artwork: "Welcome artwork", companion: "Chat character background", polaroid: "Corner photo", opacity: "Chat background opacity", reset: "Reset this skin", loading: "Loading skins\u2026", unavailable: "Optional skin, not installed", retry: "Retry", loadFailed: "Unable to load the skin manager. Please retry.", materialFailed: "Unable to load the skin artwork. Please retry." }
715
712
  };
716
713
  var language = () => /^zh/i.test(document.documentElement.lang || navigator.language) ? "zh" : "en";
717
714
  function apply(ctx) {
@@ -811,10 +808,10 @@ function apply(ctx) {
811
808
  const choose = (target) => {
812
809
  void controller.choose(target);
813
810
  };
814
- return /* @__PURE__ */ import_react2.default.createElement("section", { className: "ekko-skins", "data-ekko-skin-manager": "", "aria-label": c.nav }, /* @__PURE__ */ import_react2.default.createElement("header", { className: "ekko-skins-intro" }, /* @__PURE__ */ import_react2.default.createElement("h2", null, c.title), /* @__PURE__ */ import_react2.default.createElement("p", null, c.intro)), state.error && /* @__PURE__ */ import_react2.default.createElement("div", { className: "ekko-skin-error", role: "alert" }, state.error, " ", /* @__PURE__ */ import_react2.default.createElement("button", { type: "button", className: "ekko-skin-button", onClick: load }, c.retry)), !state.catalog && !state.error && /* @__PURE__ */ import_react2.default.createElement("p", { role: "status" }, c.loading), /* @__PURE__ */ import_react2.default.createElement("div", { className: "ekko-skin-grid" }, ["rose", "miku"].map((skin) => {
811
+ return /* @__PURE__ */ import_react2.default.createElement("section", { className: "ekko-skins", "data-ekko-skin-manager": "", "aria-label": c.nav }, /* @__PURE__ */ import_react2.default.createElement("header", { className: "ekko-skins-intro" }, /* @__PURE__ */ import_react2.default.createElement("h2", null, c.title), /* @__PURE__ */ import_react2.default.createElement("p", null, c.intro)), state.error && /* @__PURE__ */ import_react2.default.createElement("div", { className: "ekko-skin-error", role: "alert" }, state.error, " ", /* @__PURE__ */ import_react2.default.createElement("button", { type: "button", className: "ekko-skin-button", onClick: load }, c.retry)), !state.catalog && !state.error && /* @__PURE__ */ import_react2.default.createElement("p", { role: "status" }, c.loading), /* @__PURE__ */ import_react2.default.createElement("div", { className: "ekko-skin-grid" }, ["rose", "miku", "skirk"].map((skin) => {
815
812
  const entry = state.catalog?.skins.find((s) => s.id === skin), name = NAMES[skin][lang], active = id === skin, available = entry?.available && p.available.includes(skin);
816
813
  return /* @__PURE__ */ import_react2.default.createElement("article", { key: skin, className: "ekko-skin-card", "data-active": active }, entry?.preview && /* @__PURE__ */ import_react2.default.createElement("img", { className: "ekko-skin-cover", src: entry.preview[document.body.hasAttribute("data-ds-dark-theme") ? "dark" : "light"], alt: name, loading: "lazy" }), /* @__PURE__ */ import_react2.default.createElement("div", { className: "ekko-skin-description" }, /* @__PURE__ */ import_react2.default.createElement("div", { className: "ekko-skin-title" }, /* @__PURE__ */ import_react2.default.createElement("h3", null, name), active && /* @__PURE__ */ import_react2.default.createElement("span", { className: "ekko-skin-state" }, c.active)), /* @__PURE__ */ import_react2.default.createElement("span", { className: "ekko-skin-version" }, entry?.version ? "v" + entry.version : c.unavailable), /* @__PURE__ */ import_react2.default.createElement("button", { type: "button", className: "ekko-skin-button", "data-active": active, disabled: !available || active || p.busy, onClick: () => choose(skin) }, p.busy && p.desired === skin ? c.switching : active ? c.active : c.use + " " + name)));
817
- })), /* @__PURE__ */ import_react2.default.createElement("div", { className: "ekko-skin-toolbar" }, /* @__PURE__ */ import_react2.default.createElement("span", null, p.busy ? c.switching : id === "default" ? c.native : NAMES[id]?.[lang]), /* @__PURE__ */ import_react2.default.createElement("button", { type: "button", className: "ekko-skin-button", disabled: id === "default" || p.busy, onClick: () => choose("default") }, c.native)), p.error && /* @__PURE__ */ import_react2.default.createElement("div", { className: "ekko-skin-error", role: "alert" }, p.error, /* @__PURE__ */ import_react2.default.createElement("button", { type: "button", className: "ekko-skin-button", onClick: () => choose(p.desired) }, c.retry)), prefs && /* @__PURE__ */ import_react2.default.createElement("div", { className: "ekko-skin-options" }, /* @__PURE__ */ import_react2.default.createElement("div", { className: "ekko-skin-toolbar" }, /* @__PURE__ */ import_react2.default.createElement("h3", null, NAMES[id][lang], " \xB7 ", c.options), /* @__PURE__ */ import_react2.default.createElement("button", { type: "button", className: "ekko-skin-button", disabled: p.busy, onClick: () => setPreference(id, { artwork: true, companion: true, polaroid: true, opacity: 0.12, mobileNav: "corner" }) }, c.reset)), /* @__PURE__ */ import_react2.default.createElement("label", { className: "ekko-skin-option" }, /* @__PURE__ */ import_react2.default.createElement("span", null, lang === "zh" ? "\u624B\u673A\u5BFC\u822A\u65B9\u5F0F" : "Phone navigation", /* @__PURE__ */ import_react2.default.createElement("small", null, lang === "zh" ? "\u7AD6\u5C4F\u624B\u673A\u751F\u6548\uFF0C\u4E24\u4E2A\u4E3B\u9898\u5206\u522B\u4FDD\u5B58" : "Portrait phones; saved separately for each skin")), /* @__PURE__ */ import_react2.default.createElement("select", { "aria-label": lang === "zh" ? "\u624B\u673A\u5BFC\u822A\u65B9\u5F0F" : "Phone navigation", value: prefs.mobileNav || "corner", disabled: p.busy, onChange: (e) => setPreference(id, { mobileNav: e.target.value }) }, /* @__PURE__ */ import_react2.default.createElement("option", { value: "corner" }, lang === "zh" ? "\u5DE6\u4E0A\u89D2\u6309\u94AE + \u62BD\u5C49" : "Corner button + drawer"), /* @__PURE__ */ import_react2.default.createElement("option", { value: "rail" }, lang === "zh" ? "\u5DE6\u4FA7\u7EB5\u5411\u56FE\u6807\u680F" : "Vertical icon rail"))), ["artwork", "companion", "polaroid"].map((key) => /* @__PURE__ */ import_react2.default.createElement("label", { className: "ekko-skin-option", key }, /* @__PURE__ */ import_react2.default.createElement("span", null, c[key]), /* @__PURE__ */ import_react2.default.createElement("input", { type: "checkbox", checked: prefs[key], disabled: p.busy, onChange: (e) => setPreference(id, { [key]: e.target.checked }) }))), /* @__PURE__ */ import_react2.default.createElement("label", { className: "ekko-skin-option" }, /* @__PURE__ */ import_react2.default.createElement("span", null, c.opacity, /* @__PURE__ */ import_react2.default.createElement("small", null, Math.round(prefs.opacity * 100), "%")), /* @__PURE__ */ import_react2.default.createElement("input", { type: "range", min: ".04", max: ".24", step: ".01", value: prefs.opacity, disabled: p.busy, onChange: (e) => setPreference(id, { opacity: Number(e.target.value) }) }))), prefs && /* @__PURE__ */ import_react2.default.createElement(VideoSettings, { key: id, skin: id }));
814
+ })), /* @__PURE__ */ import_react2.default.createElement("div", { className: "ekko-skin-toolbar" }, /* @__PURE__ */ import_react2.default.createElement("span", null, p.busy ? c.switching : id === "default" ? c.native : NAMES[id]?.[lang]), /* @__PURE__ */ import_react2.default.createElement("button", { type: "button", className: "ekko-skin-button", disabled: id === "default" || p.busy, onClick: () => choose("default") }, c.native)), p.error && /* @__PURE__ */ import_react2.default.createElement("div", { className: "ekko-skin-error", role: "alert" }, p.error, /* @__PURE__ */ import_react2.default.createElement("button", { type: "button", className: "ekko-skin-button", onClick: () => choose(p.desired) }, c.retry)), prefs && /* @__PURE__ */ import_react2.default.createElement("div", { className: "ekko-skin-options" }, /* @__PURE__ */ import_react2.default.createElement("div", { className: "ekko-skin-toolbar" }, /* @__PURE__ */ import_react2.default.createElement("h3", null, NAMES[id][lang], " \xB7 ", c.options), /* @__PURE__ */ import_react2.default.createElement("button", { type: "button", className: "ekko-skin-button", disabled: p.busy, onClick: () => setPreference(id, provider.defaults || { artwork: true, companion: true, polaroid: true, opacity: 0.12, mobileNav: "corner" }) }, c.reset)), /* @__PURE__ */ import_react2.default.createElement("label", { className: "ekko-skin-option" }, /* @__PURE__ */ import_react2.default.createElement("span", null, lang === "zh" ? "\u624B\u673A\u5BFC\u822A\u65B9\u5F0F" : "Phone navigation", /* @__PURE__ */ import_react2.default.createElement("small", null, lang === "zh" ? "\u7AD6\u5C4F\u624B\u673A\u751F\u6548\uFF0C\u5404\u4E3B\u9898\u5206\u522B\u4FDD\u5B58" : "Portrait phones; saved separately for each skin")), /* @__PURE__ */ import_react2.default.createElement("select", { "aria-label": lang === "zh" ? "\u624B\u673A\u5BFC\u822A\u65B9\u5F0F" : "Phone navigation", value: prefs.mobileNav || "corner", disabled: p.busy, onChange: (e) => setPreference(id, { mobileNav: e.target.value }) }, /* @__PURE__ */ import_react2.default.createElement("option", { value: "corner" }, lang === "zh" ? "\u5DE6\u4E0A\u89D2\u6309\u94AE + \u62BD\u5C49" : "Corner button + drawer"), /* @__PURE__ */ import_react2.default.createElement("option", { value: "rail" }, lang === "zh" ? "\u5DE6\u4FA7\u7EB5\u5411\u56FE\u6807\u680F" : "Vertical icon rail"))), ["artwork", "companion", ...id === "skirk" ? [] : ["polaroid"]].map((key) => /* @__PURE__ */ import_react2.default.createElement("label", { className: "ekko-skin-option", key }, /* @__PURE__ */ import_react2.default.createElement("span", null, c[key]), /* @__PURE__ */ import_react2.default.createElement("input", { type: "checkbox", checked: prefs[key], disabled: p.busy, onChange: (e) => setPreference(id, { [key]: e.target.checked }) }))), /* @__PURE__ */ import_react2.default.createElement("label", { className: "ekko-skin-option" }, /* @__PURE__ */ import_react2.default.createElement("span", null, c.opacity, /* @__PURE__ */ import_react2.default.createElement("small", null, Math.round(prefs.opacity * 100), "%")), /* @__PURE__ */ import_react2.default.createElement("input", { type: "range", min: ".04", max: ".24", step: ".01", value: prefs.opacity, disabled: p.busy, onChange: (e) => setPreference(id, { opacity: Number(e.target.value) }) }))), prefs && /* @__PURE__ */ import_react2.default.createElement(VideoSettings, { key: id, skin: id }));
818
815
  }
819
816
  function registerSection() {
820
817
  return ctx.slots.inject("settings.section", () => ctx.slots.register({ name: "settings.section", id: "ekko-skins", order: 115, label: () => COPY[language()].nav }, Panel));
@@ -863,7 +860,7 @@ function apply(ctx) {
863
860
  }, "ekko-skins: controller, section and presentation cleanup");
864
861
  }
865
862
 
866
- // src/shared-lease.mjs
863
+ // work/rose-queen-release/manager-publish/src/shared-lease.mjs
867
864
  function acquireShared(ctx, key, plugin, config = {}) {
868
865
  const symbol = /* @__PURE__ */ Symbol.for("dsh.ekko-skins.leases." + key);
869
866
  const leases = globalThis[symbol] ??= /* @__PURE__ */ new WeakMap(), root = ctx.root;
@@ -892,7 +889,7 @@ function acquireShared(ctx, key, plugin, config = {}) {
892
889
  return state.fiber;
893
890
  }
894
891
 
895
- // src/client-entry.mjs
892
+ // work/rose-queen-release/manager-publish/src/client-entry.mjs
896
893
  var manager = { name: "ekko-skins-shared-client-v2", inject, apply };
897
894
  function acquireClient(ctx) {
898
895
  return acquireShared(ctx, "client-v2", manager);
package/lib/index.js CHANGED
@@ -1,19 +1,19 @@
1
- // src/index.mjs
2
- import { readFile as readFile2 } from "node:fs/promises";
1
+ // work/rose-queen-release/manager-publish/src/index.mjs
3
2
  import { existsSync as existsSync2 } from "node:fs";
3
+ import { readFile as readFile2 } from "node:fs/promises";
4
4
  import { createRequire } from "node:module";
5
5
  import { createHash as createHash2 } from "node:crypto";
6
6
  import { dirname, join as join2 } from "node:path";
7
7
  import { pathToFileURL } from "node:url";
8
8
 
9
- // src/boot-media.mjs
9
+ // work/rose-queen-release/manager-publish/src/boot-media.mjs
10
10
  import { mkdir, readFile, writeFile, rename, unlink, readdir, stat, open } from "node:fs/promises";
11
11
  import { createReadStream, existsSync } from "node:fs";
12
12
  import { Readable } from "node:stream";
13
13
  import { join, basename } from "node:path";
14
14
  import { createHash, randomBytes } from "node:crypto";
15
15
 
16
- // src/vendor/video-route.mjs
16
+ // work/rose-queen-release/manager-publish/src/vendor/video-route.mjs
17
17
  function parseRange(header, size) {
18
18
  if (header === void 0 || header === null || header === "") return null;
19
19
  if (typeof header !== "string") return null;
@@ -42,10 +42,10 @@ function toInlineJson(value) {
42
42
  return JSON.stringify(value).replace(/</gu, "\\u003c").replace(/\u2028/gu, "\\u2028").replace(/\u2029/gu, "\\u2029");
43
43
  }
44
44
 
45
- // src/boot-media.mjs
45
+ // work/rose-queen-release/manager-publish/src/boot-media.mjs
46
46
  var MAX_VIDEO = 96 * 1024 * 1024;
47
47
  var CHUNK_SIZE = 512 * 1024;
48
- var IDS = ["rose", "miku"];
48
+ var IDS = ["rose", "miku", "skirk"];
49
49
  var DEVICES = ["desktop", "mobile"];
50
50
  var defaults = { enabled: true, sound: true, volume: 0.65, fit: "cover", maxSeconds: 30, file: null, name: null };
51
51
  var mediaName = /^[a-f0-9]{64}\.(mp4|webm)$/;
@@ -324,13 +324,13 @@ async function createMediaStore({ directory, resolvePackage }) {
324
324
  } };
325
325
  }
326
326
 
327
- // src/boot-generated.mjs
328
- var BOOT_SCRIPT = '(()=>{var D=`\n.ekko-boot{position:fixed;inset:0;z-index:2147483000;display:grid;place-items:center;background:#10171e;color:#fff;opacity:1;isolation:isolate;font:14px/1.5 system-ui,sans-serif}\n.ekko-boot[data-skin="rose"]{background:#241a20;--boot-accent:#f3b3c6}.ekko-boot[data-skin="miku"]{--boot-accent:#81eff0}\n.ekko-boot video{display:block;width:100%;height:100%;position:absolute;inset:0;object-fit:cover}\n.ekko-boot:after{content:"";position:absolute;inset:0;pointer-events:none;box-shadow:inset 0 0 0 2px var(--boot-accent),inset 0 -100px 100px -75px #000b}\n.ekko-boot button{position:relative;z-index:2;cursor:pointer;border:1px solid #fff8;background:#101820b8;color:white;border-radius:999px;min-height:44px;padding:9px 16px;font:inherit;backdrop-filter:blur(8px)}\n.ekko-boot button:focus-visible{outline:3px solid var(--boot-accent);outline-offset:3px}\n.ekko-boot-skip{position:absolute!important;right:max(18px,env(safe-area-inset-right));top:max(18px,env(safe-area-inset-top))}\n.ekko-boot-footer{position:absolute;bottom:max(20px,env(safe-area-inset-bottom));left:max(20px,env(safe-area-inset-left));right:max(20px,env(safe-area-inset-right));display:grid;gap:10px;z-index:2;text-shadow:0 1px 8px #000}\n.ekko-boot-toolbar{display:flex;gap:12px;align-items:center;flex-wrap:wrap}.ekko-boot-toolbar span{margin-left:auto}.ekko-boot progress{width:100%;height:4px;accent-color:var(--boot-accent)}\n@media(prefers-reduced-motion:reduce){.ekko-boot{scroll-behavior:auto}}\n`,N=()=>/^zh/i.test(document.documentElement.lang||navigator.language)?{skip:"\\u8DF3\\u8FC7\\u89C6\\u9891",sound:"\\u5F00\\u542F\\u58F0\\u97F3",mute:"\\u9759\\u97F3",play:"\\u64AD\\u653E\\u89C6\\u9891",loading:"\\u6B63\\u5728\\u52A0\\u8F7D\\u542F\\u52A8\\u89C6\\u9891\\u2026",hint:"\\u70B9\\u51FB\\u753B\\u9762\\u6216\\u6309 Esc \\u8DF3\\u8FC7",title:"\\u4E3B\\u9898\\u542F\\u52A8\\u89C6\\u9891"}:{skip:"Skip video",sound:"Enable sound",mute:"Mute",play:"Play video",loading:"Loading startup video\\u2026",hint:"Click the picture or press Esc to skip",title:"Theme startup video"},R="(max-width: 768px), (hover: none) and (pointer: coarse) and (max-height: 768px)";function j(a,n=!1){return a&&(n&&a.mobile?{...a,...a.mobile,device:"mobile"}:{...a,device:n?"mobile":"desktop"})}function q(a,n){let i=a?.url,t=a?.fallbackUrl;return[...new Set((n?[t,i]:[i,t]).filter(Boolean))]}function U(a,n,{preview:i=!1}={}){if(!n?.url||n.available===!1||!i&&!n.enabled||!i&&window.matchMedia?.("(prefers-reduced-motion: reduce)").matches||document.querySelector(".ekko-boot"))return Promise.resolve();let t=N(),r=document.createElement("section"),e=document.createElement("video");r.className="ekko-boot",r.dataset.skin=a,r.dataset.device=n.device||"desktop",r.setAttribute("role","dialog"),r.setAttribute("aria-modal","true"),r.setAttribute("aria-label",t.title);let h=document.createElement("style");h.dataset.ekkoBoot="",h.textContent=D,document.head.append(h),e.playsInline=!0,e.preload="auto",e.muted=!n.sound,e.volume=n.volume??.65,e.style.objectFit=n.fit||"cover";let w=q(n,!!e.canPlayType(\'video/webm; codecs="vp8, opus"\')),E=0;e.src=w[E];let T=(o,l)=>{let u=document.createElement("button");return u.type="button",u.textContent=o,u.className=l||"",u},f=T(t.skip,"ekko-boot-skip"),d=T(e.muted?t.sound:t.mute),s=T(t.play);s.hidden=!0;let _=document.createElement("div");_.className="ekko-boot-footer";let O=document.createElement("div");O.className="ekko-boot-toolbar";let g=document.createElement("span");g.textContent=t.loading;let m=document.createElement("progress");m.max=1,m.value=0,m.setAttribute("aria-label",t.title),O.append(d,s,g),_.append(O,m),r.append(e,f,_),document.body.append(r);let C=document.activeElement,k=document.getElementById("root"),K=k?.inert;k&&(k.inert=!0),f.focus();let A=new MutationObserver(()=>{t=N(),f.textContent=t.skip,d.textContent=e.muted?t.sound:t.mute,s.textContent=t.play,g.textContent=e.currentTime>0?t.hint:t.loading,r.setAttribute("aria-label",t.title),m.setAttribute("aria-label",t.title)});A.observe(document.documentElement,{attributes:!0,attributeFilter:["lang"]});let v=!1,p=!1,y=0,x,b,P,z=new Promise(o=>P=o);function B(){p||(p=!0,clearTimeout(b),clearTimeout(x),cancelAnimationFrame(y),A.disconnect(),document.removeEventListener("keydown",F,!0),e.pause(),e.removeAttribute("src"),e.load(),r.remove(),h.remove(),k&&(k.inert=K),C?.isConnected&&C!==document.body&&C.focus({preventScroll:!0}),P())}function c(o=800){if(v)return;v=!0,clearTimeout(b),clearTimeout(x),cancelAnimationFrame(y);let l=performance.now(),u=e.volume,L=()=>{if(p)return;let S=Math.min(1,(performance.now()-l)/o);r.style.opacity=String(1-S),e.volume=u*(1-S),S===1?B():y=requestAnimationFrame(L)};y=requestAnimationFrame(L),x=setTimeout(B,o+150)}function F(o){if(o.key==="Escape"&&(o.preventDefault(),o.stopPropagation(),c(250)),o.key==="Tab"){let l=[f,d,...s.hidden?[]:[s]],u=l.indexOf(document.activeElement);o.preventDefault(),l[(u+(o.shiftKey?-1:1)+l.length)%l.length].focus()}}document.addEventListener("keydown",F,!0),f.onclick=o=>{o.stopPropagation(),c(250)},r.onclick=o=>{o.target.closest("button")||c(250)},d.onclick=async o=>{o.stopPropagation(),e.muted=!e.muted;try{await e.play()}catch{s.hidden=!1}d.textContent=e.muted?t.sound:t.mute},s.onclick=async o=>{o.stopPropagation();try{await e.play(),s.hidden=!0}catch{e.muted=!0,d.textContent=t.sound;try{await e.play(),s.hidden=!0}catch{c(200)}}},e.addEventListener("ended",()=>c()),e.addEventListener("error",()=>{p||v||(E+1<w.length?(clearTimeout(b),b=setTimeout(()=>c(200),12e3),e.src=w[++E],e.load(),M()):c(200))}),e.addEventListener("playing",()=>{clearTimeout(b),s.hidden=!0,x||(x=setTimeout(()=>c(),Math.max(5,Math.min(60,n.maxSeconds||30))*1e3)),g.textContent=t.hint}),e.addEventListener("timeupdate",()=>{Number.isFinite(e.duration)&&e.duration>0&&(m.value=Math.min(1,e.currentTime/e.duration))}),b=setTimeout(()=>c(200),12e3);async function M(){try{await e.play()}catch{if(p||v)return;e.muted=!0,d.textContent=t.sound;try{await e.play()}catch{!p&&!v&&(s.hidden=!1)}}}return M(),z}function I({defaultSkin:a="miku"}={}){if(window.__EKKO_BOOT_STARTED__)return;window.__EKKO_BOOT_STARTED__=!0;let n=a;try{let i=JSON.parse(localStorage.getItem("dsh:ekko-skins:selection:v1"));i?.version===1&&["rose","miku","default"].includes(i.skin)&&(n=i.skin)}catch{}["rose","miku"].includes(n)&&(async()=>{try{let i=await fetch("./api/ekko-skins/boot",{credentials:"same-origin",signal:AbortSignal.timeout(3e3)});if(!i.ok)return;let t=await i.json();await U(n,j(t.skins?.[n],!!window.matchMedia?.(R).matches))}catch{}})()}try{I(globalThis.__EKKO_STARTUP_CONFIG__||{})}catch{}})();\n';
327
+ // work/rose-queen-release/manager-publish/src/boot-generated.mjs
328
+ var BOOT_SCRIPT = '(()=>{var D=`\n.ekko-boot{position:fixed;inset:0;z-index:2147483000;display:grid;place-items:center;background:#10171e;color:#fff;opacity:1;isolation:isolate;font:14px/1.5 system-ui,sans-serif}\n.ekko-boot[data-skin="rose"]{background:#241a20;--boot-accent:#f3b3c6}.ekko-boot[data-skin="miku"]{--boot-accent:#81eff0}\n.ekko-boot video{display:block;width:100%;height:100%;position:absolute;inset:0;object-fit:cover}\n.ekko-boot:after{content:"";position:absolute;inset:0;pointer-events:none;box-shadow:inset 0 0 0 2px var(--boot-accent),inset 0 -100px 100px -75px #000b}\n.ekko-boot button{position:relative;z-index:2;cursor:pointer;border:1px solid #fff8;background:#101820b8;color:white;border-radius:999px;min-height:44px;padding:9px 16px;font:inherit;backdrop-filter:blur(8px)}\n.ekko-boot button:focus-visible{outline:3px solid var(--boot-accent);outline-offset:3px}\n.ekko-boot-skip{position:absolute!important;right:max(18px,env(safe-area-inset-right));top:max(18px,env(safe-area-inset-top))}\n.ekko-boot-footer{position:absolute;bottom:max(20px,env(safe-area-inset-bottom));left:max(20px,env(safe-area-inset-left));right:max(20px,env(safe-area-inset-right));display:grid;gap:10px;z-index:2;text-shadow:0 1px 8px #000}\n.ekko-boot-toolbar{display:flex;gap:12px;align-items:center;flex-wrap:wrap}.ekko-boot-toolbar span{margin-left:auto}.ekko-boot progress{width:100%;height:4px;accent-color:var(--boot-accent)}\n@media(prefers-reduced-motion:reduce){.ekko-boot{scroll-behavior:auto}}\n`,N=()=>/^zh/i.test(document.documentElement.lang||navigator.language)?{skip:"\\u8DF3\\u8FC7\\u89C6\\u9891",sound:"\\u5F00\\u542F\\u58F0\\u97F3",mute:"\\u9759\\u97F3",play:"\\u64AD\\u653E\\u89C6\\u9891",loading:"\\u6B63\\u5728\\u52A0\\u8F7D\\u542F\\u52A8\\u89C6\\u9891\\u2026",hint:"\\u70B9\\u51FB\\u753B\\u9762\\u6216\\u6309 Esc \\u8DF3\\u8FC7",title:"\\u4E3B\\u9898\\u542F\\u52A8\\u89C6\\u9891"}:{skip:"Skip video",sound:"Enable sound",mute:"Mute",play:"Play video",loading:"Loading startup video\\u2026",hint:"Click the picture or press Esc to skip",title:"Theme startup video"},R="(max-width: 768px), (hover: none) and (pointer: coarse) and (max-height: 768px)";function j(a,n=!1){return a&&(n&&a.mobile?{...a,...a.mobile,device:"mobile"}:{...a,device:n?"mobile":"desktop"})}function q(a,n){let i=a?.url,t=a?.fallbackUrl;return[...new Set((n?[t,i]:[i,t]).filter(Boolean))]}function U(a,n,{preview:i=!1}={}){if(!n?.url||n.available===!1||!i&&!n.enabled||!i&&window.matchMedia?.("(prefers-reduced-motion: reduce)").matches||document.querySelector(".ekko-boot"))return Promise.resolve();let t=N(),r=document.createElement("section"),e=document.createElement("video");r.className="ekko-boot",r.dataset.skin=a,r.dataset.device=n.device||"desktop",r.setAttribute("role","dialog"),r.setAttribute("aria-modal","true"),r.setAttribute("aria-label",t.title);let h=document.createElement("style");h.dataset.ekkoBoot="",h.textContent=D,document.head.append(h),e.playsInline=!0,e.preload="auto",e.muted=!n.sound,e.volume=n.volume??.65,e.style.objectFit=n.fit||"cover";let w=q(n,!!e.canPlayType(\'video/webm; codecs="vp8, opus"\')),E=0;e.src=w[E];let T=(o,l)=>{let u=document.createElement("button");return u.type="button",u.textContent=o,u.className=l||"",u},f=T(t.skip,"ekko-boot-skip"),d=T(e.muted?t.sound:t.mute),s=T(t.play);s.hidden=!0;let _=document.createElement("div");_.className="ekko-boot-footer";let O=document.createElement("div");O.className="ekko-boot-toolbar";let g=document.createElement("span");g.textContent=t.loading;let m=document.createElement("progress");m.max=1,m.value=0,m.setAttribute("aria-label",t.title),O.append(d,s,g),_.append(O,m),r.append(e,f,_),document.body.append(r);let C=document.activeElement,k=document.getElementById("root"),K=k?.inert;k&&(k.inert=!0),f.focus();let A=new MutationObserver(()=>{t=N(),f.textContent=t.skip,d.textContent=e.muted?t.sound:t.mute,s.textContent=t.play,g.textContent=e.currentTime>0?t.hint:t.loading,r.setAttribute("aria-label",t.title),m.setAttribute("aria-label",t.title)});A.observe(document.documentElement,{attributes:!0,attributeFilter:["lang"]});let v=!1,p=!1,y=0,x,b,P,z=new Promise(o=>P=o);function B(){p||(p=!0,clearTimeout(b),clearTimeout(x),cancelAnimationFrame(y),A.disconnect(),document.removeEventListener("keydown",F,!0),e.pause(),e.removeAttribute("src"),e.load(),r.remove(),h.remove(),k&&(k.inert=K),C?.isConnected&&C!==document.body&&C.focus({preventScroll:!0}),P())}function c(o=800){if(v)return;v=!0,clearTimeout(b),clearTimeout(x),cancelAnimationFrame(y);let l=performance.now(),u=e.volume,L=()=>{if(p)return;let S=Math.min(1,(performance.now()-l)/o);r.style.opacity=String(1-S),e.volume=u*(1-S),S===1?B():y=requestAnimationFrame(L)};y=requestAnimationFrame(L),x=setTimeout(B,o+150)}function F(o){if(o.key==="Escape"&&(o.preventDefault(),o.stopPropagation(),c(250)),o.key==="Tab"){let l=[f,d,...s.hidden?[]:[s]],u=l.indexOf(document.activeElement);o.preventDefault(),l[(u+(o.shiftKey?-1:1)+l.length)%l.length].focus()}}document.addEventListener("keydown",F,!0),f.onclick=o=>{o.stopPropagation(),c(250)},r.onclick=o=>{o.target.closest("button")||c(250)},d.onclick=async o=>{o.stopPropagation(),e.muted=!e.muted;try{await e.play()}catch{s.hidden=!1}d.textContent=e.muted?t.sound:t.mute},s.onclick=async o=>{o.stopPropagation();try{await e.play(),s.hidden=!0}catch{e.muted=!0,d.textContent=t.sound;try{await e.play(),s.hidden=!0}catch{c(200)}}},e.addEventListener("ended",()=>c()),e.addEventListener("error",()=>{p||v||(E+1<w.length?(clearTimeout(b),b=setTimeout(()=>c(200),12e3),e.src=w[++E],e.load(),M()):c(200))}),e.addEventListener("playing",()=>{clearTimeout(b),s.hidden=!0,x||(x=setTimeout(()=>c(),Math.max(5,Math.min(60,n.maxSeconds||30))*1e3)),g.textContent=t.hint}),e.addEventListener("timeupdate",()=>{Number.isFinite(e.duration)&&e.duration>0&&(m.value=Math.min(1,e.currentTime/e.duration))}),b=setTimeout(()=>c(200),12e3);async function M(){try{await e.play()}catch{if(p||v)return;e.muted=!0,d.textContent=t.sound;try{await e.play()}catch{!p&&!v&&(s.hidden=!1)}}}return M(),z}function I({defaultSkin:a="miku"}={}){if(window.__EKKO_BOOT_STARTED__)return;window.__EKKO_BOOT_STARTED__=!0;let n=a;try{let i=JSON.parse(localStorage.getItem("dsh:ekko-skins:selection:v1"));i?.version===1&&["rose","miku","skirk","default"].includes(i.skin)&&(n=i.skin)}catch{}["rose","miku","skirk"].includes(n)&&(async()=>{try{let i=await fetch("./api/ekko-skins/boot",{credentials:"same-origin",signal:AbortSignal.timeout(3e3)});if(!i.ok)return;let t=await i.json();await U(n,j(t.skins?.[n],!!window.matchMedia?.(R).matches))}catch{}})()}try{I(globalThis.__EKKO_STARTUP_CONFIG__||{})}catch{}})();\n';
329
329
 
330
- // src/index.mjs
330
+ // work/rose-queen-release/manager-publish/src/index.mjs
331
331
  var require2 = createRequire(import.meta.url);
332
332
  var PREFIX = "/ekko-skins";
333
- var PACKAGES = { rose: "dsh-plugin-rose-theme", miku: "dsh-plugin-miku-theme" };
333
+ var PACKAGES = { rose: "dsh-plugin-rose-theme", miku: "dsh-plugin-miku-theme", skirk: "dsh-plugin-miku-theme" };
334
334
  function resolveSkinPackage(resolvePackage, id) {
335
335
  if (id === "rose") try {
336
336
  const bundled = join2(resolvePackage(PACKAGES.miku), "themes/rose");
@@ -345,15 +345,15 @@ function createHandler({ resolvePackage = (name) => dirname(require2.resolve(nam
345
345
  for (const [id, pkg] of Object.entries(PACKAGES)) {
346
346
  try {
347
347
  const root = resolveSkinPackage(resolvePackage, id), meta = JSON.parse(await readFile2(join2(root, "package.json"), "utf8"));
348
- skins.push({ id, version: meta.version, available: meta.dsh?.ekkoSkinProvider === 1, preview: { light: "./ekko-skins/preview/" + id + "/light.webp", dark: "./ekko-skins/preview/" + id + "/dark.webp" } });
348
+ skins.push({ id, version: meta.version, available: meta.dsh?.ekkoSkinProvider === 1 && (id !== "skirk" || Array.isArray(meta.dsh?.ekkoSkins) && meta.dsh.ekkoSkins.includes("skirk")), preview: { light: "./ekko-skins/preview/" + id + "/light.webp", dark: "./ekko-skins/preview/" + id + "/dark.webp" } });
349
349
  } catch {
350
350
  skins.push({ id, available: false });
351
351
  }
352
352
  }
353
353
  const installed = skins.filter((s) => s.available).map((s) => s.id);
354
- const preferred = ["rose", "miku", "default"].includes(defaultSkin) ? defaultSkin : "miku";
354
+ const preferred = ["rose", "miku", "skirk", "default"].includes(defaultSkin) ? defaultSkin : "miku";
355
355
  const selected = preferred === "default" || installed.includes(preferred) ? preferred : installed[0] || "default";
356
- return { version: "0.3.0", defaultSkin: selected, skins };
356
+ return { version: "0.3.1", defaultSkin: selected, skins };
357
357
  }
358
358
  return async (req, res) => {
359
359
  if (!["GET", "HEAD"].includes(req.method)) {
@@ -367,7 +367,7 @@ function createHandler({ resolvePackage = (name) => dirname(require2.resolve(nam
367
367
  res.end(req.method === "HEAD" ? void 0 : bytes2);
368
368
  return;
369
369
  }
370
- const match = /^\/ekko-skins\/(assets|preview)\/(rose|miku)\/([a-z0-9.-]+)$/.exec(pathname);
370
+ const match = /^\/ekko-skins\/(assets|preview)\/(rose|miku|skirk)\/([a-z0-9.-]+)$/.exec(pathname);
371
371
  if (!match) {
372
372
  res.writeHead(404).end();
373
373
  return;
@@ -381,18 +381,18 @@ function createHandler({ resolvePackage = (name) => dirname(require2.resolve(nam
381
381
  res.writeHead(404).end();
382
382
  return;
383
383
  }
384
- const manifest = JSON.parse(await readFile2(join2(root, "assets/manifest.json"), "utf8"));
384
+ const manifest = JSON.parse(await readFile2(join2(root, id === "skirk" ? "assets/skirk/manifest.json" : "assets/manifest.json"), "utf8"));
385
385
  if (!Object.values(manifest).includes(file)) {
386
386
  res.writeHead(404).end();
387
387
  return;
388
388
  }
389
- bytes = await readFile2(join2(root, "assets/runtime", file));
389
+ bytes = await readFile2(join2(root, id === "skirk" ? "assets/skirk/runtime" : "assets/runtime", file));
390
390
  } else {
391
391
  if (!["light.webp", "dark.webp"].includes(file)) {
392
392
  res.writeHead(404).end();
393
393
  return;
394
394
  }
395
- bytes = await readFile2(join2(root, "preview", file));
395
+ bytes = await readFile2(join2(root, id === "skirk" ? "preview/skirk" : "preview", file));
396
396
  }
397
397
  } catch {
398
398
  res.writeHead(404).end();
@@ -414,7 +414,7 @@ function apply(ctx, config = {}) {
414
414
  ctx.inject(["webServer", "profileContext", "connection"], async (child) => {
415
415
  const profile = child.get("profileContext"), resolver = createRequire(pathToFileURL(join2(profile.dir, "package.json")));
416
416
  const resolvePackage = (name) => dirname(resolver.resolve(name + "/package.json"));
417
- const media = await createMediaStore({ directory: join2(profile.dir, "ekko-skins-media"), resolvePackage: (id) => resolveSkinPackage(resolvePackage, id) });
417
+ const media = await createMediaStore({ directory: join2(profile.dir, "ekko-skins-media"), resolvePackage: (id) => id === "skirk" ? join2(resolveSkinPackage(resolvePackage, id), "assets/skirk") : resolveSkinPackage(resolvePackage, id) });
418
418
  child.effect(() => () => media.close(), "ekko-skins: private media store");
419
419
  child.effect(() => child.get("webServer").register({ kind: "prefix", path: PREFIX, handler: createHandler({ defaultSkin: config.defaultSkin, resolvePackage }) }));
420
420
  for (const [path, methods, fetch, requestBody] of [
@@ -426,7 +426,7 @@ function apply(ctx, config = {}) {
426
426
  });
427
427
  }
428
428
 
429
- // src/shared-lease.mjs
429
+ // work/rose-queen-release/manager-publish/src/shared-lease.mjs
430
430
  function acquireShared(ctx, key, plugin, config = {}) {
431
431
  const symbol = /* @__PURE__ */ Symbol.for("dsh.ekko-skins.leases." + key);
432
432
  const leases = globalThis[symbol] ??= /* @__PURE__ */ new WeakMap(), root = ctx.root;
@@ -455,7 +455,7 @@ function acquireShared(ctx, key, plugin, config = {}) {
455
455
  return state.fiber;
456
456
  }
457
457
 
458
- // src/host-entry.mjs
458
+ // work/rose-queen-release/manager-publish/src/host-entry.mjs
459
459
  var host = { name: "ekko-skins-shared-host-v2", apply };
460
460
  function acquireHost(ctx, config = {}) {
461
461
  return acquireShared(ctx, "host-v2", host, config);