From b875332a8ccbeaa469f87a12f2b38e5afcd0a5bc Mon Sep 17 00:00:00 2001 From: kingOfSoySauce <60259156+kingOfSoySauce@users.noreply.github.com> Date: Sat, 15 Aug 2026 12:54:08 +0800 Subject: [PATCH] fix: sync liang skin theme and dark controls --- lib/client.js | 576 ++++++++++++++++++++++++++++++++++++++++++- lib/client.js.map | 4 +- package.json | 1 + src/client/index.tsx | 25 +- src/client/skin.css | 92 ++++++- 5 files changed, 685 insertions(+), 13 deletions(-) diff --git a/lib/client.js b/lib/client.js index 3f331aa..4c3503b 100644 --- a/lib/client.js +++ b/lib/client.js @@ -27,7 +27,562 @@ module.exports = __toCommonJS(index_exports); var import_react = require("react"); // src/client/skin.css -var skin_default = '.liang-skin-backdrop {\n position: fixed;\n z-index: 0;\n inset: 0;\n overflow: hidden;\n pointer-events: none;\n background: var(--liang-page, transparent);\n opacity: 0;\n transition: opacity 220ms ease, background-color 180ms linear;\n}\n\nbody[data-liang-skin="on"] .liang-skin-backdrop {\n opacity: 1;\n}\n\n.liang-skin-backdrop video,\n.liang-skin-backdrop img {\n position: absolute;\n top: 50%;\n right: 0;\n display: block;\n width: min(42vw, 720px);\n height: 100vh;\n object-fit: cover;\n object-position: 50% 42%;\n opacity: var(--liang-portrait-opacity, 0.45);\n transform: translateY(-50%);\n filter: none;\n mask-image: linear-gradient(90deg, transparent 0%, rgb(0 0 0 / 20%) 10%, black 30%, black 100%);\n transition: filter 180ms linear;\n}\n\n.liang-skin-backdrop img {\n display: none;\n}\n\n.liang-skin-backdrop[data-media="sequence"] video,\n.liang-skin-backdrop[data-media="sequence"] .liang-skin-poster {\n display: none;\n}\n\n.liang-skin-backdrop[data-media="sequence"] .liang-skin-sequence-frame {\n display: block;\n opacity: var(--liang-portrait-opacity, 0.82);\n}\n\n.liang-skin-backdrop[data-media="video"] .liang-skin-sequence-frame,\n.liang-skin-backdrop[data-media="video"] .liang-skin-poster {\n display: none;\n}\n\n.liang-skin-backdrop[data-media="poster"] video,\n.liang-skin-backdrop[data-media="poster"] .liang-skin-sequence-frame {\n display: none;\n}\n\n.liang-skin-backdrop[data-media="poster"] .liang-skin-poster {\n display: block;\n}\n\n.liang-skin-backdrop[data-media="color"] video,\n.liang-skin-backdrop[data-media="color"] img {\n display: none;\n}\n\n.liang-skin-backdrop::after {\n position: absolute;\n inset: 0;\n content: "";\n background: linear-gradient(90deg, var(--liang-page, transparent) 0 28%, transparent 57% 100%);\n}\n\nbody[data-liang-skin="on"] {\n --dsw-alias-bg-base: var(--liang-bg-base) !important;\n --dsw-alias-bg-layer-1: var(--liang-layer-1) !important;\n --dsw-alias-bg-layer-2: var(--liang-layer-2) !important;\n --dsw-alias-bg-layer-3: var(--liang-layer-3) !important;\n --dsw-specific-sidebar-fill: var(--liang-sidebar) !important;\n --dsw-alias-label-primary: var(--liang-ink) !important;\n --dsw-alias-label-primary-dimmed: var(--liang-ink) !important;\n --dsw-alias-label-secondary: var(--liang-secondary) !important;\n --dsw-alias-label-tertiary: var(--liang-tertiary) !important;\n --dsw-alias-label-caption: var(--liang-tertiary) !important;\n --dsw-alias-border-l1: var(--liang-border) !important;\n --dsw-alias-border-l2-darkmode-thin: var(--liang-border) !important;\n --dsw-alias-border-l2: var(--liang-border) !important;\n --dsw-alias-border-l3: var(--liang-border) !important;\n --dsw-alias-button-primary-fill: var(--liang-accent) !important;\n --dsw-alias-button-primary-hover: var(--liang-accent-hover) !important;\n --dsw-alias-button-info-fill: var(--liang-accent) !important;\n --dsw-alias-button-info-hover: var(--liang-accent-hover) !important;\n --dsw-alias-state-business-primary: var(--liang-accent) !important;\n --dsw-alias-interactive-bg-hover: var(--liang-hover) !important;\n --dsw-alias-interactive-bg-active: var(--liang-hover) !important;\n --dsw-alias-button-elevated-fill: var(--liang-layer-1) !important;\n --dsw-alias-button-floating-fill: var(--liang-layer-2) !important;\n --dsw-alias-button-floating-hover: var(--liang-layer-3) !important;\n --dsw-alias-interactive-bg-hover-solid: var(--liang-layer-2) !important;\n --dsw-specific-bubble: var(--liang-layer-2) !important;\n --dsw-specific-input-major: var(--liang-layer-1) !important;\n --dsw-specific-menu: var(--liang-layer-3) !important;\n --dsw-specific-selector: var(--liang-layer-2) !important;\n background: var(--liang-page) !important;\n}\n\nbody[data-liang-skin="on"]:is(\n [data-liang-stage="0"],\n [data-liang-stage="1"],\n [data-liang-stage="2"],\n [data-liang-stage="3"]\n) {\n --dsw-alias-brand-primary-new-colorprimary-new-color: rgb(65 118 230) !important;\n --dsw-alias-brand-primary: rgb(15 17 21) !important;\n --dsw-alias-brand-text: rgb(15 17 21) !important;\n --dsw-alias-button-primary-fill: rgb(15 17 21) !important;\n --dsw-alias-button-primary-hover: rgb(53 54 56) !important;\n --dsw-alias-button-info-fill: rgb(65 118 230) !important;\n --dsw-alias-button-info-hover: rgb(103 158 254) !important;\n --dsw-alias-state-business-primary: rgb(65 118 230) !important;\n --dsw-alias-label-primary-inverted: rgb(249 250 251) !important;\n --dsw-alias-button-elevated-fill: rgb(255 255 255) !important;\n --dsw-alias-button-floating-fill: rgb(255 255 255) !important;\n --dsw-alias-button-floating-hover: rgb(241 243 245) !important;\n --dsw-alias-interactive-bg-hover-solid: rgb(241 243 245) !important;\n --dsw-specific-bubble: rgb(237 243 254) !important;\n --dsw-specific-input-major: rgb(255 255 255) !important;\n --dsw-specific-menu: rgb(255 255 255) !important;\n --dsw-specific-selector: rgb(245 246 247) !important;\n}\n\nbody[data-liang-skin="on"][data-liang-stage="5"] {\n --dsw-alias-brand-primary-new-colorprimary-new-color: #c19a49 !important;\n --dsw-alias-brand-primary: #c19a49 !important;\n --dsw-alias-brand-text: #d5b56e !important;\n --dsw-alias-button-info-fill: #c19a49 !important;\n --dsw-alias-button-info-hover: #d5b56e !important;\n --dsw-alias-state-business-primary: #c19a49 !important;\n}\n\n/* Preserve the wordmark badge contrast even when the underlying Harness\n preference is dark while our low-intensity shell is light. */\nbody[data-liang-skin="on"]:is(\n [data-liang-stage="0"],\n [data-liang-stage="1"],\n [data-liang-stage="2"],\n [data-liang-stage="3"]\n) button[aria-label="\u65B0\u5EFA\u4F1A\u8BDD"] svg[viewBox="0 0 182 24"] > rect[width="52"] {\n fill: rgb(15 17 21) !important;\n}\n\nbody[data-liang-skin="on"]:is(\n [data-liang-stage="0"],\n [data-liang-stage="1"],\n [data-liang-stage="2"],\n [data-liang-stage="3"]\n) button[aria-label="\u65B0\u5EFA\u4F1A\u8BDD"] svg[viewBox="0 0 182 24"] > g[clip-path*="badge"] path {\n fill: rgb(249 250 251) !important;\n}\n\nbody[data-liang-skin="on"][data-liang-stage="5"] button[aria-label="\u65B0\u5EFA\u4F1A\u8BDD"] svg[viewBox="0 0 182 24"] > rect[width="52"] {\n fill: #c19a49 !important;\n}\n\nbody[data-liang-skin="on"][data-liang-stage="5"] button[aria-label="\u65B0\u5EFA\u4F1A\u8BDD"] svg[viewBox="0 0 182 24"] > g[clip-path*="badge"] path {\n fill: #171816 !important;\n}\n\nbody[data-liang-skin="on"][data-liang-stage="5"] [aria-label^="\u9009\u62E9\u6A21\u578B"] > span:nth-of-type(2) {\n color: #d5b56e !important;\n}\n\nbody[data-liang-skin="on"][data-liang-stage="5"] [class*="heroGlow"] ellipse {\n fill: #c19a49 !important;\n fill-opacity: 0.16 !important;\n}\n\nbody[data-liang-skin="on"][data-liang-stage="5"] span[class*="_previewBadge"] {\n color: #171816 !important;\n background: #c19a49 !important;\n}\n\nbody[data-liang-skin="on"][data-liang-stage="5"] button[aria-label="\u53D1\u9001\u6D88\u606F"] {\n color: #171816 !important;\n}\n\nbody[data-liang-skin="on"][data-liang-stage="5"] button[aria-label="\u53D1\u9001\u6D88\u606F"]:disabled {\n opacity: 0.62;\n}\n\nbody[data-liang-skin="on"]:is(\n [data-liang-stage="0"],\n [data-liang-stage="1"],\n [data-liang-stage="2"],\n [data-liang-stage="3"]\n) button[aria-label="\u53D1\u9001\u6D88\u606F"] {\n color: #fff !important;\n}\n\nbody[data-liang-skin="on"]:is(\n [data-liang-stage="0"],\n [data-liang-stage="1"],\n [data-liang-stage="2"],\n [data-liang-stage="3"]\n) button[aria-label="\u53D1\u9001\u6D88\u606F"]:disabled {\n color: rgb(255 255 255 / 92%) !important;\n background: rgb(65 118 230 / 42%) !important;\n opacity: 1;\n}\n\nbody[data-liang-skin="on"] > #root {\n position: relative;\n z-index: 1;\n background: transparent !important;\n}\n\nbody[data-liang-skin="on"] button,\nbody[data-liang-skin="on"] input,\nbody[data-liang-skin="on"] textarea {\n transition: color 160ms linear, background-color 160ms linear, border-color 160ms linear;\n}\n\n/* Harness can itself be in dark mode while the low intensity stages are light.\n The composer card has a native theme-mode fill, so explicitly bring only\n those light stages back to the original light surface and readable ink. */\nbody[data-liang-skin="on"]:is(\n [data-liang-stage="0"],\n [data-liang-stage="1"],\n [data-liang-stage="2"],\n [data-liang-stage="3"]\n) [data-composer-card="true"] {\n border-color: var(--liang-border) !important;\n color: var(--liang-ink) !important;\n background: var(--liang-layer-1) !important;\n box-shadow: 0 8px 28px rgb(20 22 20 / 8%);\n}\n\nbody[data-liang-skin="on"]:is(\n [data-liang-stage="0"],\n [data-liang-stage="1"],\n [data-liang-stage="2"],\n [data-liang-stage="3"]\n) [data-composer-card="true"] :is(textarea, button, [data-input-mirror="true"]) {\n color: var(--liang-ink) !important;\n caret-color: var(--liang-accent) !important;\n}\n\nbody[data-liang-skin="on"]:is(\n [data-liang-stage="0"],\n [data-liang-stage="1"],\n [data-liang-stage="2"],\n [data-liang-stage="3"]\n) [data-composer-card="true"] textarea::placeholder {\n color: var(--liang-tertiary) !important;\n opacity: 1;\n}\n\n.liang-effort-control {\n --liang-control-accent: var(--dsw-alias-brand-primary-new-colorprimary-new-color, #4176e6);\n --liang-control-rail: var(--dsw-alias-border-l3, rgb(0 0 0 / 16%));\n position: relative;\n display: flex;\n width: 124px;\n height: 28px;\n align-items: center;\n margin: 0 3px;\n overflow: visible;\n}\n\nbody[data-liang-skin="on"] .liang-effort-control {\n --liang-control-accent: var(--liang-secondary);\n --liang-control-rail: color-mix(in srgb, var(--liang-secondary) 28%, transparent);\n}\n\n.liang-effort-control__ticks {\n position: absolute;\n z-index: 0;\n inset: 0 10px;\n pointer-events: none;\n}\n\n.liang-effort-control__ticks::before {\n position: absolute;\n top: 50%;\n right: 0;\n left: 0;\n height: 1px;\n content: "";\n background: var(--liang-control-rail);\n transform: translateY(-50%);\n}\n\n.liang-effort-control__tooltip {\n position: absolute;\n z-index: 4;\n bottom: calc(100% + 7px);\n left: calc(10px + (100% - 20px) * var(--liang-slider-ratio));\n min-width: max-content;\n padding: 5px 8px;\n border: 1px solid var(--liang-border, rgb(0 0 0 / 12%));\n border-radius: 7px;\n color: var(--liang-ink, #171816);\n background: var(--liang-layer-1, #fff);\n box-shadow: 0 5px 16px rgb(0 0 0 / 16%);\n font-size: 11px;\n font-weight: 600;\n line-height: 16px;\n letter-spacing: 0.01em;\n pointer-events: none;\n transform: translateX(-50%);\n white-space: nowrap;\n}\n\n.liang-effort-control__tooltip::after {\n position: absolute;\n top: 100%;\n left: 50%;\n width: 7px;\n height: 7px;\n content: "";\n background: inherit;\n transform: translate(-50%, -4px) rotate(45deg);\n}\n\n.liang-effort-control__tick {\n position: absolute;\n top: 50%;\n width: 1px;\n height: 7px;\n background: var(--liang-control-accent);\n opacity: 0.42;\n transform: translate(-50%, -50%);\n}\n\n.liang-effort-control__range {\n position: relative;\n z-index: 1;\n width: calc(100% - 7px);\n height: 28px;\n margin: 0 3.5px;\n cursor: ew-resize;\n appearance: none;\n background: transparent;\n touch-action: pan-y;\n}\n\n.liang-effort-control__range:disabled {\n cursor: progress;\n opacity: 0.58;\n}\n\n.liang-effort-control__range::-webkit-slider-runnable-track {\n height: 1px;\n border-radius: 1px;\n background: transparent;\n}\n\n.liang-effort-control__range::-webkit-slider-thumb {\n width: 13px;\n height: 13px;\n margin-top: -6px;\n border: 1.5px solid color-mix(in srgb, var(--liang-control-accent) 72%, transparent);\n border-radius: 50%;\n appearance: none;\n background: radial-gradient(circle, var(--liang-control-accent) 0 2px, color-mix(in srgb, var(--liang-control-accent) 22%, var(--dsw-alias-bg-layer-1, #fff)) 2.5px);\n box-shadow: 0 1px 4px rgb(0 0 0 / 14%);\n}\n\nbody[data-liang-skin="on"] .liang-effort-control__range::-webkit-slider-thumb {\n width: 13px;\n height: 13px;\n margin-top: -6px;\n border-color: color-mix(in srgb, var(--liang-control-accent) 72%, transparent);\n background: radial-gradient(circle, var(--liang-control-accent) 0 2px, color-mix(in srgb, var(--liang-control-accent) 22%, var(--liang-layer-1)) 2.5px);\n}\n\n.liang-effort-control__range::-moz-range-track {\n height: 1px;\n background: transparent;\n}\n\n.liang-effort-control__range::-moz-range-progress {\n height: 1px;\n background: transparent;\n}\n\n.liang-effort-control__range::-moz-range-thumb {\n width: 11px;\n height: 11px;\n border: 1.5px solid color-mix(in srgb, var(--liang-control-accent) 72%, transparent);\n border-radius: 50%;\n background: color-mix(in srgb, var(--liang-control-accent) 24%, var(--dsw-alias-bg-layer-1, #fff));\n}\n\n.liang-effort-control__range:focus-visible {\n outline: none;\n}\n\n.liang-effort-control[data-state="error"] {\n --liang-control-accent: var(--dsw-alias-state-error-primary, #e43c3c);\n}\n\n.liang-settings-row {\n display: flex;\n min-height: 82px;\n align-items: center;\n justify-content: space-between;\n gap: 24px;\n padding: 16px 0;\n border-bottom: 1px solid var(--dsw-alias-border-l1, rgb(0 0 0 / 6%));\n color: var(--dsw-alias-label-primary);\n}\n\n.liang-settings-row__title {\n flex: 0 0 auto;\n font-size: 14px;\n font-weight: 500;\n}\n\n.liang-settings-row__choices {\n display: flex;\n gap: 8px;\n}\n\n.liang-settings-row__choice {\n min-width: 76px;\n height: 40px;\n padding: 0 14px;\n border: 1px solid var(--dsw-alias-border-l2, rgb(0 0 0 / 10%));\n border-radius: 10px;\n color: var(--dsw-alias-label-secondary);\n background: var(--dsw-alias-bg-layer-1);\n cursor: pointer;\n}\n\n.liang-settings-row__choice:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n.liang-settings-row__choice[aria-pressed="true"] {\n border-color: var(--dsw-alias-label-primary);\n color: var(--dsw-alias-label-primary);\n box-shadow: inset 0 0 0 1px var(--dsw-alias-label-primary);\n}\n\n@media (max-width: 760px) {\n .liang-effort-control {\n width: 92px;\n }\n\n .liang-skin-backdrop video,\n .liang-skin-backdrop img {\n right: -18vw;\n width: 92vw;\n opacity: calc(var(--liang-portrait-opacity, 0.45) * 0.72);\n }\n\n .liang-settings-row {\n align-items: flex-start;\n flex-direction: column;\n gap: 12px;\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .liang-skin-backdrop,\n .liang-skin-backdrop video,\n .liang-skin-backdrop img,\n body[data-liang-skin="on"] button,\n body[data-liang-skin="on"] input,\n body[data-liang-skin="on"] textarea {\n transition: none;\n }\n}\n'; +var skin_default = `.liang-skin-backdrop { + position: fixed; + z-index: 0; + inset: 0; + overflow: hidden; + pointer-events: none; + background: var(--liang-page, transparent); + opacity: 0; + transition: opacity 220ms ease, background-color 180ms linear; +} + +body[data-liang-skin="on"] .liang-skin-backdrop { + opacity: 1; +} + +.liang-skin-backdrop video, +.liang-skin-backdrop img { + position: absolute; + top: 50%; + right: 0; + display: block; + width: min(42vw, 720px); + height: 100vh; + object-fit: cover; + object-position: 50% 42%; + opacity: var(--liang-portrait-opacity, 0.45); + transform: translateY(-50%); + filter: none; + mask-image: linear-gradient(90deg, transparent 0%, rgb(0 0 0 / 20%) 10%, black 30%, black 100%); + transition: filter 180ms linear; +} + +.liang-skin-backdrop img { + display: none; +} + +.liang-skin-backdrop[data-media="sequence"] video, +.liang-skin-backdrop[data-media="sequence"] .liang-skin-poster { + display: none; +} + +.liang-skin-backdrop[data-media="sequence"] .liang-skin-sequence-frame { + display: block; + opacity: var(--liang-portrait-opacity, 0.82); +} + +.liang-skin-backdrop[data-media="video"] .liang-skin-sequence-frame, +.liang-skin-backdrop[data-media="video"] .liang-skin-poster { + display: none; +} + +.liang-skin-backdrop[data-media="poster"] video, +.liang-skin-backdrop[data-media="poster"] .liang-skin-sequence-frame { + display: none; +} + +.liang-skin-backdrop[data-media="poster"] .liang-skin-poster { + display: block; +} + +.liang-skin-backdrop[data-media="color"] video, +.liang-skin-backdrop[data-media="color"] img { + display: none; +} + +.liang-skin-backdrop::after { + position: absolute; + inset: 0; + content: ""; + background: linear-gradient(90deg, var(--liang-page, transparent) 0 28%, transparent 57% 100%); +} + +body[data-liang-skin="on"] { + --dsw-alias-bg-base: var(--liang-bg-base) !important; + --dsw-alias-bg-layer-1: var(--liang-layer-1) !important; + --dsw-alias-bg-layer-2: var(--liang-layer-2) !important; + --dsw-alias-bg-layer-3: var(--liang-layer-3) !important; + --dsw-specific-sidebar-fill: var(--liang-sidebar) !important; + --dsw-alias-label-primary: var(--liang-ink) !important; + --dsw-alias-label-primary-dimmed: var(--liang-ink) !important; + --dsw-alias-label-secondary: var(--liang-secondary) !important; + --dsw-alias-label-tertiary: var(--liang-tertiary) !important; + --dsw-alias-label-caption: var(--liang-tertiary) !important; + --dsw-alias-border-l1: var(--liang-border) !important; + --dsw-alias-border-l2-darkmode-thin: var(--liang-border) !important; + --dsw-alias-border-l2: var(--liang-border) !important; + --dsw-alias-border-l3: var(--liang-border) !important; + --dsw-alias-button-primary-fill: var(--liang-accent) !important; + --dsw-alias-button-primary-hover: var(--liang-accent-hover) !important; + --dsw-alias-button-info-fill: var(--liang-accent) !important; + --dsw-alias-button-info-hover: var(--liang-accent-hover) !important; + --dsw-alias-state-business-primary: var(--liang-accent) !important; + --dsw-alias-interactive-bg-hover: var(--liang-hover) !important; + --dsw-alias-interactive-bg-active: var(--liang-hover) !important; + --dsw-alias-button-elevated-fill: var(--liang-layer-1) !important; + --dsw-alias-button-floating-fill: var(--liang-layer-2) !important; + --dsw-alias-button-floating-hover: var(--liang-layer-3) !important; + --dsw-alias-interactive-bg-hover-solid: var(--liang-layer-2) !important; + --dsw-specific-bubble: var(--liang-layer-2) !important; + --dsw-specific-input-major: var(--liang-layer-1) !important; + --dsw-specific-menu: var(--liang-layer-3) !important; + --dsw-specific-selector: var(--liang-layer-2) !important; + --dsw-alias-markdown-citation: var(--liang-layer-2) !important; + --dsw-alias-markdown-code-block-banner: var(--liang-layer-1) !important; + --dsw-alias-markdown-code-block: var(--liang-layer-1) !important; + --dsw-alias-markdown-code-segment-selected: var(--liang-layer-2) !important; + --dsw-alias-markdown-code-segment-unselected: var(--liang-layer-1) !important; + --dsw-alias-markdown-inline-code: var(--liang-layer-2) !important; + --dsw-alias-markdown-placeholder: var(--liang-layer-1) !important; + --dsw-alias-markdown-tag: var(--liang-layer-2) !important; + background: var(--liang-page) !important; +} + +body[data-liang-skin="on"]:is( + [data-liang-stage="0"], + [data-liang-stage="1"], + [data-liang-stage="2"], + [data-liang-stage="3"] +) { + --dsw-alias-brand-primary-new-colorprimary-new-color: rgb(65 118 230) !important; + --dsw-alias-brand-primary: rgb(15 17 21) !important; + --dsw-alias-brand-text: rgb(15 17 21) !important; + --dsw-alias-button-primary-fill: rgb(15 17 21) !important; + --dsw-alias-button-primary-hover: rgb(53 54 56) !important; + --dsw-alias-button-info-fill: rgb(65 118 230) !important; + --dsw-alias-button-info-hover: rgb(103 158 254) !important; + --dsw-alias-state-business-primary: rgb(65 118 230) !important; + --dsw-alias-label-primary-inverted: rgb(249 250 251) !important; + --dsw-alias-button-elevated-fill: rgb(255 255 255) !important; + --dsw-alias-button-floating-fill: rgb(255 255 255) !important; + --dsw-alias-button-floating-hover: rgb(241 243 245) !important; + --dsw-alias-interactive-bg-hover-solid: rgb(241 243 245) !important; + --dsw-specific-bubble: rgb(237 243 254) !important; + --dsw-specific-input-major: rgb(255 255 255) !important; + --dsw-specific-menu: rgb(255 255 255) !important; + --dsw-specific-selector: rgb(245 246 247) !important; +} + +body[data-liang-skin="on"][data-liang-stage="5"] { + --dsw-alias-brand-primary-new-colorprimary-new-color: #c19a49 !important; + --dsw-alias-brand-primary: #c19a49 !important; + --dsw-alias-brand-text: #d5b56e !important; + --dsw-alias-button-info-fill: #c19a49 !important; + --dsw-alias-button-info-hover: #d5b56e !important; + --dsw-alias-state-business-primary: #c19a49 !important; + --dsw-alias-bg-module-platform: var(--liang-layer-3) !important; + --dsw-specific-sidebar-nav-item-active: var(--liang-layer-3) !important; + --dsw-specific-sidebar-nav-item-hover: var(--liang-hover) !important; +} + +/* The low-intensity skin is light by default, but it must not turn a dark + Harness document into a light surface. Keep the skin's portrait progression + while switching the shared UI layers back to a readable charcoal palette. */ +body[data-liang-skin="on"][data-ds-dark-theme]:is( + [data-liang-stage="0"], + [data-liang-stage="1"], + [data-liang-stage="2"], + [data-liang-stage="3"] +) { + --liang-page: rgb(17 17 17) !important; + --liang-bg-base: rgb(17 17 17 / 42%) !important; + --liang-layer-1: rgb(30 27 25 / 94%) !important; + --liang-layer-2: rgb(41 35 30 / 96%) !important; + --liang-layer-3: rgb(41 35 30 / 99%) !important; + --liang-sidebar: rgb(23 20 18 / 96%) !important; + --liang-ink: rgb(244 241 232) !important; + --liang-secondary: rgb(184 180 169) !important; + --liang-tertiary: rgb(137 134 126) !important; + --liang-border: rgb(244 241 232 / 15%) !important; + --liang-hover: rgb(244 241 232 / 9%) !important; + --dsw-alias-brand-primary: var(--liang-accent) !important; + --dsw-alias-brand-text: var(--liang-accent) !important; + --dsw-alias-button-primary-fill: var(--liang-accent) !important; + --dsw-alias-button-primary-hover: var(--liang-accent-hover) !important; + --dsw-alias-button-info-fill: var(--liang-accent) !important; + --dsw-alias-button-info-hover: var(--liang-accent-hover) !important; + --dsw-alias-state-business-primary: var(--liang-accent) !important; + --dsw-alias-button-elevated-fill: var(--liang-layer-1) !important; + --dsw-alias-button-floating-fill: var(--liang-layer-2) !important; + --dsw-alias-button-floating-hover: var(--liang-layer-3) !important; + --dsw-alias-interactive-bg-hover-solid: var(--liang-layer-2) !important; + --dsw-specific-bubble: var(--liang-layer-2) !important; + --dsw-specific-input-major: var(--liang-layer-1) !important; + --dsw-specific-menu: var(--liang-layer-3) !important; + --dsw-specific-selector: var(--liang-layer-2) !important; + background: var(--liang-page) !important; +} + +body[data-liang-skin="on"][data-ds-dark-theme]:is( + [data-liang-stage="0"], + [data-liang-stage="1"], + [data-liang-stage="2"], + [data-liang-stage="3"] +) .liang-skin-backdrop { + background: var(--liang-page) !important; +} + +body[data-liang-skin="on"][data-ds-dark-theme]:is( + [data-liang-stage="0"], + [data-liang-stage="1"], + [data-liang-stage="2"], + [data-liang-stage="3"] +) .liang-skin-backdrop::after { + background: linear-gradient(90deg, var(--liang-page) 0 28%, transparent 57% 100%); +} + +/* The host's running-turn label uses a transparent blue shimmer. In the + custom dark skin it is a semantic status accent, so keep both the label + and its elapsed clock gold without changing the original light theme. */ +body[data-liang-skin="on"][data-liang-stage="5"] [class*="_turnStatus"] { + color: #c19a49 !important; + background: #c19a49 !important; + background-clip: initial !important; + -webkit-background-clip: initial !important; + -webkit-text-fill-color: #c19a49 !important; + animation: none !important; +} + +body[data-liang-skin="on"][data-liang-stage="5"] [class*="_turnStatusClock"] { + color: #c19a49 !important; + -webkit-text-fill-color: #c19a49 !important; +} + +/* Preserve the wordmark badge contrast in the low-intensity shell. */ +body[data-liang-skin="on"]:is( + [data-liang-stage="0"], + [data-liang-stage="1"], + [data-liang-stage="2"], + [data-liang-stage="3"] +) button[aria-label="\u65B0\u5EFA\u4F1A\u8BDD"] svg[viewBox="0 0 182 24"] > rect[width="52"] { + fill: rgb(15 17 21) !important; +} + +body[data-liang-skin="on"]:is( + [data-liang-stage="0"], + [data-liang-stage="1"], + [data-liang-stage="2"], + [data-liang-stage="3"] +) button[aria-label="\u65B0\u5EFA\u4F1A\u8BDD"] svg[viewBox="0 0 182 24"] > g[clip-path*="badge"] path { + fill: rgb(249 250 251) !important; +} + +body[data-liang-skin="on"][data-liang-stage="5"] button[aria-label="\u65B0\u5EFA\u4F1A\u8BDD"] svg[viewBox="0 0 182 24"] > rect[width="52"] { + fill: #c19a49 !important; +} + +body[data-liang-skin="on"][data-liang-stage="5"] button[aria-label="\u65B0\u5EFA\u4F1A\u8BDD"] svg[viewBox="0 0 182 24"] > g[clip-path*="badge"] path { + fill: #171816 !important; +} + +body[data-liang-skin="on"][data-liang-stage="5"] [aria-label^="\u9009\u62E9\u6A21\u578B"] > span:nth-of-type(2) { + color: #d5b56e !important; +} + +body[data-liang-skin="on"][data-liang-stage="5"] [class*="heroGlow"] ellipse { + fill: #c19a49 !important; + fill-opacity: 0.16 !important; +} + +body[data-liang-skin="on"][data-liang-stage="5"] span[class*="_previewBadge"] { + color: #171816 !important; + background: #c19a49 !important; +} + +body[data-liang-skin="on"][data-liang-stage="5"] button[aria-label="\u53D1\u9001\u6D88\u606F"] { + color: #171816 !important; +} + +body[data-liang-skin="on"][data-liang-stage="5"] button[aria-label="\u53D1\u9001\u6D88\u606F"]:disabled { + opacity: 0.62; +} + +body[data-liang-skin="on"]:is( + [data-liang-stage="0"], + [data-liang-stage="1"], + [data-liang-stage="2"], + [data-liang-stage="3"] +) button[aria-label="\u53D1\u9001\u6D88\u606F"] { + color: #fff !important; +} + +body[data-liang-skin="on"]:is( + [data-liang-stage="0"], + [data-liang-stage="1"], + [data-liang-stage="2"], + [data-liang-stage="3"] +) button[aria-label="\u53D1\u9001\u6D88\u606F"]:disabled { + color: rgb(255 255 255 / 92%) !important; + background: rgb(65 118 230 / 42%) !important; + opacity: 1; +} + +body[data-liang-skin="on"] > #root { + position: relative; + z-index: 1; + background: transparent !important; +} + +body[data-liang-skin="on"] button, +body[data-liang-skin="on"] input, +body[data-liang-skin="on"] textarea { + transition: color 160ms linear, background-color 160ms linear, border-color 160ms linear; +} + +/* The composer card has a native theme-mode fill, so keep its surface and + readable ink aligned with the active Liang palette. */ +body[data-liang-skin="on"]:is( + [data-liang-stage="0"], + [data-liang-stage="1"], + [data-liang-stage="2"], + [data-liang-stage="3"] +) [data-composer-card="true"] { + border-color: var(--liang-border) !important; + color: var(--liang-ink) !important; + background: var(--liang-layer-1) !important; + box-shadow: 0 8px 28px rgb(20 22 20 / 8%); +} + +body[data-liang-skin="on"]:is( + [data-liang-stage="0"], + [data-liang-stage="1"], + [data-liang-stage="2"], + [data-liang-stage="3"] +) [data-composer-card="true"] :is(textarea, button, [data-input-mirror="true"]) { + color: var(--liang-ink) !important; + caret-color: var(--liang-accent) !important; +} + +body[data-liang-skin="on"]:is( + [data-liang-stage="0"], + [data-liang-stage="1"], + [data-liang-stage="2"], + [data-liang-stage="3"] +) [data-composer-card="true"] textarea::placeholder { + color: var(--liang-tertiary) !important; + opacity: 1; +} + +.liang-effort-control { + --liang-control-accent: var(--dsw-alias-brand-primary-new-colorprimary-new-color, #4176e6); + --liang-control-rail: var(--dsw-alias-border-l3, rgb(0 0 0 / 16%)); + position: relative; + display: flex; + width: 124px; + height: 28px; + align-items: center; + margin: 0 3px; + overflow: visible; +} + +body[data-liang-skin="on"] .liang-effort-control { + --liang-control-accent: var(--liang-secondary); + --liang-control-rail: color-mix(in srgb, var(--liang-secondary) 28%, transparent); +} + +.liang-effort-control__ticks { + position: absolute; + z-index: 0; + inset: 0 10px; + pointer-events: none; +} + +.liang-effort-control__ticks::before { + position: absolute; + top: 50%; + right: 0; + left: 0; + height: 1px; + content: ""; + background: var(--liang-control-rail); + transform: translateY(-50%); +} + +.liang-effort-control__tooltip { + position: absolute; + z-index: 4; + bottom: calc(100% + 7px); + left: calc(10px + (100% - 20px) * var(--liang-slider-ratio)); + min-width: max-content; + padding: 5px 8px; + border: 1px solid var(--liang-border, rgb(0 0 0 / 12%)); + border-radius: 7px; + color: var(--liang-ink, #171816); + background: var(--liang-layer-1, #fff); + box-shadow: 0 5px 16px rgb(0 0 0 / 16%); + font-size: 11px; + font-weight: 600; + line-height: 16px; + letter-spacing: 0.01em; + pointer-events: none; + transform: translateX(-50%); + white-space: nowrap; +} + +.liang-effort-control__tooltip::after { + position: absolute; + top: 100%; + left: 50%; + width: 7px; + height: 7px; + content: ""; + background: inherit; + transform: translate(-50%, -4px) rotate(45deg); +} + +.liang-effort-control__tick { + position: absolute; + top: 50%; + width: 1px; + height: 7px; + background: var(--liang-control-accent); + opacity: 0.42; + transform: translate(-50%, -50%); +} + +.liang-effort-control__range { + position: relative; + z-index: 1; + width: calc(100% - 7px); + height: 28px; + margin: 0 3.5px; + cursor: ew-resize; + appearance: none; + background: transparent; + touch-action: pan-y; +} + +.liang-effort-control__range:disabled { + cursor: progress; + opacity: 0.58; +} + +.liang-effort-control__range::-webkit-slider-runnable-track { + height: 1px; + border-radius: 1px; + background: transparent; +} + +.liang-effort-control__range::-webkit-slider-thumb { + width: 13px; + height: 13px; + margin-top: -6px; + border: 1.5px solid color-mix(in srgb, var(--liang-control-accent) 72%, transparent); + border-radius: 50%; + appearance: none; + background: radial-gradient(circle, var(--liang-control-accent) 0 2px, color-mix(in srgb, var(--liang-control-accent) 22%, var(--dsw-alias-bg-layer-1, #fff)) 2.5px); + box-shadow: 0 1px 4px rgb(0 0 0 / 14%); +} + +body[data-liang-skin="on"] .liang-effort-control__range::-webkit-slider-thumb { + width: 13px; + height: 13px; + margin-top: -6px; + border-color: color-mix(in srgb, var(--liang-control-accent) 72%, transparent); + background: radial-gradient(circle, var(--liang-control-accent) 0 2px, color-mix(in srgb, var(--liang-control-accent) 22%, var(--liang-layer-1)) 2.5px); +} + +.liang-effort-control__range::-moz-range-track { + height: 1px; + background: transparent; +} + +.liang-effort-control__range::-moz-range-progress { + height: 1px; + background: transparent; +} + +.liang-effort-control__range::-moz-range-thumb { + width: 11px; + height: 11px; + border: 1.5px solid color-mix(in srgb, var(--liang-control-accent) 72%, transparent); + border-radius: 50%; + background: color-mix(in srgb, var(--liang-control-accent) 24%, var(--dsw-alias-bg-layer-1, #fff)); +} + +.liang-effort-control__range:focus-visible { + outline: none; +} + +.liang-effort-control[data-state="error"] { + --liang-control-accent: var(--dsw-alias-state-error-primary, #e43c3c); +} + +.liang-settings-row { + display: flex; + min-height: 82px; + align-items: center; + justify-content: space-between; + gap: 24px; + padding: 16px 0; + border-bottom: 1px solid var(--dsw-alias-border-l1, rgb(0 0 0 / 6%)); + color: var(--dsw-alias-label-primary); +} + +.liang-settings-row__title { + flex: 0 0 auto; + font-size: 14px; + font-weight: 500; +} + +.liang-settings-row__choices { + display: flex; + gap: 8px; +} + +.liang-settings-row__choice { + min-width: 76px; + height: 40px; + padding: 0 14px; + border: 1px solid var(--dsw-alias-border-l2, rgb(0 0 0 / 10%)); + border-radius: 10px; + color: var(--dsw-alias-label-secondary); + background: var(--dsw-alias-bg-layer-1); + cursor: pointer; +} + +.liang-settings-row__choice:hover { + background: var(--dsw-alias-interactive-bg-hover); +} + +.liang-settings-row__choice[aria-pressed="true"] { + border-color: var(--dsw-alias-label-primary); + color: var(--dsw-alias-label-primary); + box-shadow: inset 0 0 0 1px var(--dsw-alias-label-primary); +} + +@media (max-width: 760px) { + .liang-effort-control { + width: 92px; + } + + .liang-skin-backdrop video, + .liang-skin-backdrop img { + right: -18vw; + width: 92vw; + opacity: calc(var(--liang-portrait-opacity, 0.45) * 0.72); + } + + .liang-settings-row { + align-items: flex-start; + flex-direction: column; + gap: 12px; + } +} + +@media (prefers-reduced-motion: reduce) { + .liang-skin-backdrop, + .liang-skin-backdrop video, + .liang-skin-backdrop img, + body[data-liang-skin="on"] button, + body[data-liang-skin="on"] input, + body[data-liang-skin="on"] textarea { + transition: none; + } +} +`; // src/client/logic.ts var PREVIEW_MAX_FRAME = 240; @@ -200,6 +755,7 @@ var cssVariables = [ ]; var SkinPresenter = class { scope; + theme; root; video; poster; @@ -211,8 +767,9 @@ var SkinPresenter = class { raf = 0; disposed = false; unsubscribe; - constructor(scope) { + constructor(scope, theme) { this.scope = scope; + this.theme = theme; this.root = document.createElement("div"); this.root.className = "liang-skin-backdrop"; this.root.dataset.plugin = PACKAGE_ID; @@ -297,6 +854,7 @@ var SkinPresenter = class { applyFrame() { const palette = paletteForFrame(this.frame); const body = document.body; + this.syncNativeTheme(palette.stage === 5 ? "dark" : "light"); body.dataset.liangStage = String(palette.stage); body.style.setProperty("--liang-strength", String(palette.strength)); body.style.setProperty("--liang-page", palette.page); @@ -316,6 +874,10 @@ var SkinPresenter = class { this.updatePortrait(palette.level); this.seek(this.frame); } + syncNativeTheme(theme = paletteForFrame(this.frame).stage === 5 ? "dark" : "light") { + if (!this.enabled || this.theme.getTheme().preference === theme) return; + this.theme.setTheme(theme); + } updatePortrait(level) { const { lowerIndex, upperIndex, mix: mix2 } = portraitBlendForLevel( level, @@ -557,7 +1119,8 @@ var inject = [ "slots", "sessions", "modelDirectories", - "locale" + "locale", + "theme" ]; function createPreferenceStore() { let snapshot = { @@ -598,8 +1161,13 @@ function apply(ctx) { ctx.effect(() => () => style.remove(), "liang-intensity-skin: scoped styles"); const scope = createPreferenceStore(); ctx.effect(() => () => scope.dispose(), "liang-intensity-skin: appearance preference"); - const presenter = new SkinPresenter(scope); + const theme = ctx.get("theme"); + const presenter = new SkinPresenter(scope, theme); ctx.effect(() => () => presenter.dispose(), "liang-intensity-skin: backdrop presenter"); + ctx.effect( + () => ctx.on("theme/change", () => presenter.syncNativeTheme()), + "liang-intensity-skin: native theme synchronization" + ); ctx.effect(() => ctx.locale.register(LOCALE_NAMESPACE, { zh: { "appearance.title": "\u5916\u89C2\u76AE\u80A4", diff --git a/lib/client.js.map b/lib/client.js.map index e1182c5..b1a34c4 100644 --- a/lib/client.js.map +++ b/lib/client.js.map @@ -1,7 +1,7 @@ { "version": 3, "sources": ["../src/client/index.tsx", "../src/client/skin.css", "../src/client/logic.ts"], - "sourcesContent": ["import {\n useEffect,\n useMemo,\n useRef,\n useState,\n useSyncExternalStore,\n} from \"react\";\nimport type { ClientContext, SnapshotStore } from \"@deepseek-ai/dsh-client-runtime/client\";\nimport type {} from \"@deepseek-ai/dsh-client-ui-conversation/client\";\nimport type {} from \"@deepseek-ai/dsh-client-ui-settings/client\";\nimport type {} from \"@deepseek-ai/dsh-client-ui-model-selection/client\";\nimport styles from \"./skin.css\";\nimport {\n PREVIEW_MAX_FRAME,\n frameForEffort,\n indicatorLabel,\n nearestEffortIndex,\n paletteForFrame,\n portraitBlendForLevel,\n selectedEffortIndex,\n type EffortLike,\n} from \"./logic\";\n\nconst PACKAGE_ID = \"dsh-client-liang-intensity-skin\";\nconst LOCALE_NAMESPACE = \"liang.skin\";\nconst ASSET_PREFIX = `/plugins/${PACKAGE_ID}/assets`;\nconst VIDEO_DURATION = 8.033;\nconst PREFERENCE_KEY = \"dsh-liang-intensity-skin.enabled\";\n\nconst PORTRAIT_ANCHORS = [\n { level: 0, file: \"stage-00.png\" },\n { level: 1, file: \"level-01.png\" },\n { level: 3, file: \"level-03.png\" },\n { level: 4, file: \"level-04.png\" },\n { level: 6, file: \"stage-06.png\" },\n { level: 7, file: \"level-07.png\" },\n { level: 9, file: \"level-09.png\" },\n { level: 10, file: \"level-10.png\" },\n { level: 12, file: \"stage-12.png\" },\n { level: 13, file: \"level-13.png\" },\n { level: 14, file: \"level-14.png\" },\n { level: 15, file: \"bridge-15.png\" },\n { level: 16, file: \"level-16.png\" },\n { level: 17, file: \"level-17.png\" },\n { level: 18, file: \"stage-18.png\" },\n { level: 19, file: \"level-19.png\" },\n { level: 21, file: \"level-21.png\" },\n { level: 22, file: \"level-22.png\" },\n { level: 24, file: \"stage-24.png\" },\n { level: 25, file: \"level-25.png\" },\n { level: 27, file: \"bridge-27.png\" },\n { level: 28, file: \"level-28.png\" },\n { level: 29, file: \"level-29.png\" },\n { level: 30, file: \"stage-30.png\" },\n] as const;\n\ninterface SkinSettings {\n enabled: boolean;\n}\n\ninterface PreferenceStore {\n getSnapshot(): SkinSettings;\n subscribe(listener: () => void): () => void;\n set(enabled: boolean): Promise;\n dispose(): void;\n}\n\ninterface ModelSelection {\n provider: string;\n model: string;\n reasoningEffort?: string;\n}\n\ninterface CatalogModel {\n id: string;\n reasoning?: {\n efforts: EffortLike[];\n defaultEffort?: string;\n };\n}\n\ninterface ModelDirectoryState {\n current: ModelSelection | null;\n groups: readonly { id: string; models: CatalogModel[] }[];\n status: \"idle\" | \"loading\" | \"ready\" | \"selecting\" | \"error\";\n error: string | null;\n}\n\ninterface ModelDirectory {\n store: SnapshotStore;\n load(): Promise;\n select(selection: ModelSelection): Promise;\n}\n\ninterface SliderProps {\n directory: SnapshotStore;\n load: () => void;\n select: (selection: ModelSelection) => Promise;\n presenter: SkinPresenter;\n scope: PreferenceStore;\n}\n\ninterface SettingsRowProps {\n scope: PreferenceStore;\n presenter: SkinPresenter;\n t: (key: string) => string;\n}\n\nconst cssVariables = [\n \"--liang-strength\",\n \"--liang-page\",\n \"--liang-bg-base\",\n \"--liang-layer-1\",\n \"--liang-layer-2\",\n \"--liang-layer-3\",\n \"--liang-sidebar\",\n \"--liang-ink\",\n \"--liang-secondary\",\n \"--liang-tertiary\",\n \"--liang-border\",\n \"--liang-accent\",\n \"--liang-accent-hover\",\n \"--liang-hover\",\n \"--liang-portrait-opacity\",\n] as const;\n\nclass SkinPresenter {\n private readonly scope: PreferenceStore;\n private readonly root: HTMLDivElement;\n private readonly video: HTMLVideoElement;\n private readonly poster: HTMLImageElement;\n private readonly portrait: HTMLImageElement;\n private readonly preloads: HTMLImageElement[];\n private enabled = true;\n private frame = 0;\n private pendingFrame = 0;\n private raf = 0;\n private disposed = false;\n private unsubscribe: () => void;\n\n constructor(scope: PreferenceStore) {\n this.scope = scope;\n this.root = document.createElement(\"div\");\n this.root.className = \"liang-skin-backdrop\";\n this.root.dataset.plugin = PACKAGE_ID;\n this.root.dataset.media = \"sequence\";\n this.root.setAttribute(\"aria-hidden\", \"true\");\n\n this.video = document.createElement(\"video\");\n this.video.muted = true;\n this.video.playsInline = true;\n this.video.preload = \"auto\";\n // A video poster stays painted while a paused video is scrubbed in some\n // browsers, which would make every effort show the same portrait. Keep the\n // separate image element as the true load-error fallback instead.\n const webm = document.createElement(\"source\");\n webm.src = `${ASSET_PREFIX}/liang-evolution.webm`;\n webm.type = \"video/webm\";\n const mp4 = document.createElement(\"source\");\n mp4.src = `${ASSET_PREFIX}/liang-evolution.mp4`;\n mp4.type = \"video/mp4\";\n this.video.append(webm, mp4);\n\n this.poster = document.createElement(\"img\");\n this.poster.className = \"liang-skin-poster\";\n this.poster.src = `${ASSET_PREFIX}/liang-poster.png`;\n this.poster.alt = \"\";\n\n this.portrait = document.createElement(\"img\");\n this.portrait.className = \"liang-skin-sequence-frame\";\n this.portrait.alt = \"\";\n this.portrait.draggable = false;\n this.portrait.addEventListener(\"error\", this.handleSequenceError);\n\n this.preloads = PORTRAIT_ANCHORS.map(({ file }) => {\n const image = new Image();\n image.src = `${ASSET_PREFIX}/portrait-source-v2/${file}`;\n return image;\n });\n\n this.root.append(this.video, this.portrait, this.poster);\n document.body.prepend(this.root);\n\n this.video.addEventListener(\"loadedmetadata\", this.handleMetadata);\n this.video.addEventListener(\"error\", this.handleVideoError);\n this.poster.addEventListener(\"error\", this.handlePosterError);\n this.video.load();\n this.unsubscribe = scope.subscribe(() => this.syncSettings());\n this.syncSettings();\n }\n\n private readonly handleMetadata = () => {\n this.seek(this.frame);\n };\n\n private readonly handleVideoError = () => {\n this.root.dataset.media = \"poster\";\n };\n\n private readonly handleSequenceError = () => {\n this.root.dataset.media = \"video\";\n };\n\n private readonly handlePosterError = () => {\n this.root.dataset.media = \"color\";\n };\n\n private syncSettings() {\n this.setEnabled(this.scope.getSnapshot().enabled);\n }\n\n isEnabled() {\n return this.enabled;\n }\n\n setEnabled(enabled: boolean) {\n this.enabled = enabled;\n if (enabled) {\n if (!this.root.isConnected) document.body.prepend(this.root);\n document.body.dataset.liangSkin = \"on\";\n this.applyFrame();\n } else {\n this.root.remove();\n delete document.body.dataset.liangSkin;\n delete document.body.dataset.liangStage;\n for (const name of cssVariables) document.body.style.removeProperty(name);\n }\n }\n\n setFrame(frame: number) {\n this.pendingFrame = Math.min(PREVIEW_MAX_FRAME, Math.max(0, Math.round(frame)));\n this.frame = this.pendingFrame;\n if (!this.enabled) return;\n if (this.raf !== 0) return;\n this.raf = requestAnimationFrame(() => {\n this.raf = 0;\n this.frame = this.pendingFrame;\n this.applyFrame();\n });\n }\n\n private applyFrame() {\n const palette = paletteForFrame(this.frame);\n const body = document.body;\n body.dataset.liangStage = String(palette.stage);\n body.style.setProperty(\"--liang-strength\", String(palette.strength));\n body.style.setProperty(\"--liang-page\", palette.page);\n body.style.setProperty(\"--liang-bg-base\", palette.base);\n body.style.setProperty(\"--liang-layer-1\", palette.layer1);\n body.style.setProperty(\"--liang-layer-2\", palette.layer2);\n body.style.setProperty(\"--liang-layer-3\", palette.layer3);\n body.style.setProperty(\"--liang-sidebar\", palette.sidebar);\n body.style.setProperty(\"--liang-ink\", palette.ink);\n body.style.setProperty(\"--liang-secondary\", palette.secondary);\n body.style.setProperty(\"--liang-tertiary\", palette.tertiary);\n body.style.setProperty(\"--liang-border\", palette.border);\n body.style.setProperty(\"--liang-accent\", palette.accent);\n body.style.setProperty(\"--liang-accent-hover\", palette.accentHover);\n body.style.setProperty(\"--liang-hover\", palette.hover);\n body.style.setProperty(\"--liang-portrait-opacity\", palette.portraitOpacity);\n this.updatePortrait(palette.level);\n this.seek(this.frame);\n }\n\n private updatePortrait(level: number) {\n const { lowerIndex, upperIndex, mix } = portraitBlendForLevel(\n level,\n PORTRAIT_ANCHORS.map((anchor) => anchor.level),\n );\n const lower = PORTRAIT_ANCHORS[lowerIndex];\n const upper = PORTRAIT_ANCHORS[upperIndex];\n const selected = mix >= 0.5 ? upper : lower;\n const source = `${ASSET_PREFIX}/portrait-source-v2/${selected.file}`;\n if (this.portrait.getAttribute(\"src\") !== source) this.portrait.src = source;\n }\n\n private seek(frame: number) {\n if (this.video.readyState < 1 || this.video.duration === 0) return;\n const duration = Number.isFinite(this.video.duration) ? this.video.duration : VIDEO_DURATION;\n const target = Math.min(Math.max(0, duration - 0.001), (frame / PREVIEW_MAX_FRAME) * duration);\n if (Math.abs(this.video.currentTime - target) > 0.025) this.video.currentTime = target;\n }\n\n async choose(enabled: boolean) {\n this.setEnabled(enabled);\n try {\n await this.scope.set(enabled);\n } catch (error) {\n this.syncSettings();\n throw error;\n }\n }\n\n dispose() {\n if (this.disposed) return;\n this.disposed = true;\n this.unsubscribe();\n if (this.raf !== 0) cancelAnimationFrame(this.raf);\n this.video.pause();\n this.video.removeEventListener(\"loadedmetadata\", this.handleMetadata);\n this.video.removeEventListener(\"error\", this.handleVideoError);\n this.portrait.removeEventListener(\"error\", this.handleSequenceError);\n this.poster.removeEventListener(\"error\", this.handlePosterError);\n for (const image of this.preloads) image.src = \"\";\n this.root.remove();\n document.body.removeAttribute(\"data-liang-skin\");\n delete document.body.dataset.liangStage;\n for (const name of cssVariables) document.body.style.removeProperty(name);\n }\n}\n\nfunction modelReasoning(state: ModelDirectoryState) {\n const current = state.current;\n if (current === null) return null;\n const group = state.groups.find((item) => item.id === current.provider);\n const model = group?.models.find((item) => item.id === current.model);\n if (model?.reasoning === undefined) return null;\n return {\n selection: current,\n efforts: model.reasoning.efforts,\n defaultEffort: model.reasoning.defaultEffort,\n };\n}\n\nfunction LiangEffortSlider({ directory, load, select, presenter, scope }: SliderProps) {\n const state = useSyncExternalStore(\n (listener) => directory.subscribe(listener),\n () => directory.getSnapshot(),\n );\n const skin = useSyncExternalStore(\n (listener) => scope.subscribe(listener),\n () => scope.getSnapshot(),\n );\n const reasoning = useMemo(() => modelReasoning(state), [state]);\n const efforts = reasoning?.efforts ?? [];\n const committedIndex = selectedEffortIndex(\n efforts,\n reasoning?.selection.reasoningEffort,\n reasoning?.defaultEffort,\n );\n const committedFrame = committedIndex < 0\n ? 0\n : frameForEffort(committedIndex, efforts.length);\n const [frame, setFrame] = useState(committedFrame);\n const [pending, setPending] = useState(false);\n const [failed, setFailed] = useState(false);\n const [interacting, setInteracting] = useState(false);\n const dragging = useRef(false);\n const enabled = skin.enabled;\n\n useEffect(() => {\n if (enabled) load();\n }, [enabled, load]);\n\n useEffect(() => {\n if (dragging.current || pending) return;\n setFrame(committedFrame);\n presenter.setFrame(committedFrame);\n }, [committedFrame, pending, presenter]);\n\n if (!enabled) return null;\n if (reasoning === null || efforts.length < 2) return null;\n\n const previewIndex = nearestEffortIndex(frame, efforts);\n const previewEffort = efforts[previewIndex];\n const progressRatio = frame / PREVIEW_MAX_FRAME;\n\n const commit = async (rawFrame: number) => {\n const targetIndex = nearestEffortIndex(rawFrame, efforts);\n const target = efforts[targetIndex];\n if (target === undefined) return;\n const targetFrame = frameForEffort(targetIndex, efforts.length);\n dragging.current = false;\n setFrame(targetFrame);\n presenter.setFrame(targetFrame);\n if (targetIndex === committedIndex || pending) return;\n setPending(true);\n setFailed(false);\n const accepted = await select({\n provider: reasoning.selection.provider,\n model: reasoning.selection.model,\n reasoningEffort: target.id,\n });\n setPending(false);\n if (!accepted) {\n setFailed(true);\n setFrame(committedFrame);\n presenter.setFrame(committedFrame);\n }\n };\n\n return (\n \n {interacting && (\n \n {indicatorLabel(frame, efforts)}\n \n )}\n
\n {efforts.map((effort, index) => (\n \n ))}\n
\n {\n dragging.current = true;\n setInteracting(true);\n }}\n onInput={(event) => {\n dragging.current = true;\n const next = Number(event.currentTarget.value);\n setFrame(next);\n presenter.setFrame(next);\n }}\n onPointerUp={(event) => {\n setInteracting(false);\n void commit(Number(event.currentTarget.value));\n }}\n onPointerCancel={() => {\n setInteracting(false);\n dragging.current = false;\n setFrame(committedFrame);\n presenter.setFrame(committedFrame);\n }}\n onKeyUp={(event) => {\n setInteracting(false);\n if (event.key !== \"Escape\") void commit(Number(event.currentTarget.value));\n }}\n onBlur={(event) => {\n setInteracting(false);\n if (dragging.current) void commit(Number(event.currentTarget.value));\n }}\n onKeyDown={(event) => {\n setInteracting(true);\n if (event.key === \"Escape\" && !pending) {\n setInteracting(false);\n dragging.current = false;\n setFrame(committedFrame);\n presenter.setFrame(committedFrame);\n }\n }}\n />\n \n );\n}\n\nfunction AppearanceSkinRow({ scope, presenter, t }: SettingsRowProps) {\n const snapshot = useSyncExternalStore(\n (listener) => scope.subscribe(listener),\n () => scope.getSnapshot(),\n );\n const enabled = snapshot.enabled;\n const [pending, setPending] = useState(false);\n\n const choose = async (next: boolean) => {\n if (next === enabled || pending) return;\n setPending(true);\n try {\n await presenter.choose(next);\n } finally {\n setPending(false);\n }\n };\n\n return (\n
\n {t(\"appearance.title\")}\n
\n void choose(false)}\n >\n {t(\"appearance.native\")}\n \n void choose(true)}\n >\n {t(\"appearance.liang\")}\n \n
\n
\n );\n}\n\nexport const inject = [\n \"slots\",\n \"sessions\",\n \"modelDirectories\",\n \"locale\",\n];\n\nfunction createPreferenceStore(): PreferenceStore {\n let snapshot: SkinSettings = {\n enabled: localStorage.getItem(PREFERENCE_KEY) !== \"0\",\n };\n const listeners = new Set<() => void>();\n const onStorage = (event: StorageEvent) => {\n if (event.key !== PREFERENCE_KEY) return;\n const enabled = event.newValue !== \"0\";\n if (enabled === snapshot.enabled) return;\n snapshot = { enabled };\n for (const listener of listeners) listener();\n };\n window.addEventListener(\"storage\", onStorage);\n return {\n getSnapshot: () => snapshot,\n subscribe(listener) {\n listeners.add(listener);\n return () => listeners.delete(listener);\n },\n async set(enabled) {\n if (enabled === snapshot.enabled) return;\n localStorage.setItem(PREFERENCE_KEY, enabled ? \"1\" : \"0\");\n snapshot = { enabled };\n for (const listener of listeners) listener();\n },\n dispose() {\n window.removeEventListener(\"storage\", onStorage);\n listeners.clear();\n },\n };\n}\n\nexport function apply(ctx: ClientContext) {\n const style = document.createElement(\"style\");\n style.dataset.plugin = PACKAGE_ID;\n style.textContent = styles;\n document.head.append(style);\n ctx.effect(() => () => style.remove(), \"liang-intensity-skin: scoped styles\");\n\n const scope = createPreferenceStore();\n ctx.effect(() => () => scope.dispose(), \"liang-intensity-skin: appearance preference\");\n const presenter = new SkinPresenter(scope);\n ctx.effect(() => () => presenter.dispose(), \"liang-intensity-skin: backdrop presenter\");\n\n ctx.effect(() => ctx.locale.register(LOCALE_NAMESPACE, {\n zh: {\n \"appearance.title\": \"\u5916\u89C2\u76AE\u80A4\",\n \"appearance.native\": \"\u539F\u751F\",\n \"appearance.liang\": \"\u6ED1\u52A8\u53D8\u7956\",\n },\n en: {\n \"appearance.title\": \"Visual skin\",\n \"appearance.native\": \"Native\",\n \"appearance.liang\": \"Slider\",\n },\n }), \"liang-intensity-skin: settings locale\");\n\n ctx.slots.inject(\"settings.general.item\", () => ctx.slots.register({\n name: \"settings.general.item\",\n id: \"liang-intensity-appearance\",\n order: 11,\n locale: LOCALE_NAMESPACE,\n inject: () => ({ scope, presenter }),\n }, AppearanceSkinRow));\n\n ctx.slots.inject(\"conversation.input.right\", () => ctx.slots.register({\n name: \"conversation.input.right\",\n id: \"liang-intensity-control\",\n order: 10,\n inject: (sessionId: string) => {\n const available = ctx.sessions.subagentAddress(sessionId) === undefined;\n const directory = ctx.modelDirectories.directoryFor(sessionId) as ModelDirectory;\n return {\n directory: directory.store,\n presenter,\n scope,\n load: () => {\n if (available) void directory.load().catch(() => undefined);\n },\n select: (selection: ModelSelection) => available\n ? directory.select(selection).then(() => true, () => false)\n : Promise.resolve(false),\n };\n },\n }, LiangEffortSlider));\n}\n", ".liang-skin-backdrop {\n position: fixed;\n z-index: 0;\n inset: 0;\n overflow: hidden;\n pointer-events: none;\n background: var(--liang-page, transparent);\n opacity: 0;\n transition: opacity 220ms ease, background-color 180ms linear;\n}\n\nbody[data-liang-skin=\"on\"] .liang-skin-backdrop {\n opacity: 1;\n}\n\n.liang-skin-backdrop video,\n.liang-skin-backdrop img {\n position: absolute;\n top: 50%;\n right: 0;\n display: block;\n width: min(42vw, 720px);\n height: 100vh;\n object-fit: cover;\n object-position: 50% 42%;\n opacity: var(--liang-portrait-opacity, 0.45);\n transform: translateY(-50%);\n filter: none;\n mask-image: linear-gradient(90deg, transparent 0%, rgb(0 0 0 / 20%) 10%, black 30%, black 100%);\n transition: filter 180ms linear;\n}\n\n.liang-skin-backdrop img {\n display: none;\n}\n\n.liang-skin-backdrop[data-media=\"sequence\"] video,\n.liang-skin-backdrop[data-media=\"sequence\"] .liang-skin-poster {\n display: none;\n}\n\n.liang-skin-backdrop[data-media=\"sequence\"] .liang-skin-sequence-frame {\n display: block;\n opacity: var(--liang-portrait-opacity, 0.82);\n}\n\n.liang-skin-backdrop[data-media=\"video\"] .liang-skin-sequence-frame,\n.liang-skin-backdrop[data-media=\"video\"] .liang-skin-poster {\n display: none;\n}\n\n.liang-skin-backdrop[data-media=\"poster\"] video,\n.liang-skin-backdrop[data-media=\"poster\"] .liang-skin-sequence-frame {\n display: none;\n}\n\n.liang-skin-backdrop[data-media=\"poster\"] .liang-skin-poster {\n display: block;\n}\n\n.liang-skin-backdrop[data-media=\"color\"] video,\n.liang-skin-backdrop[data-media=\"color\"] img {\n display: none;\n}\n\n.liang-skin-backdrop::after {\n position: absolute;\n inset: 0;\n content: \"\";\n background: linear-gradient(90deg, var(--liang-page, transparent) 0 28%, transparent 57% 100%);\n}\n\nbody[data-liang-skin=\"on\"] {\n --dsw-alias-bg-base: var(--liang-bg-base) !important;\n --dsw-alias-bg-layer-1: var(--liang-layer-1) !important;\n --dsw-alias-bg-layer-2: var(--liang-layer-2) !important;\n --dsw-alias-bg-layer-3: var(--liang-layer-3) !important;\n --dsw-specific-sidebar-fill: var(--liang-sidebar) !important;\n --dsw-alias-label-primary: var(--liang-ink) !important;\n --dsw-alias-label-primary-dimmed: var(--liang-ink) !important;\n --dsw-alias-label-secondary: var(--liang-secondary) !important;\n --dsw-alias-label-tertiary: var(--liang-tertiary) !important;\n --dsw-alias-label-caption: var(--liang-tertiary) !important;\n --dsw-alias-border-l1: var(--liang-border) !important;\n --dsw-alias-border-l2-darkmode-thin: var(--liang-border) !important;\n --dsw-alias-border-l2: var(--liang-border) !important;\n --dsw-alias-border-l3: var(--liang-border) !important;\n --dsw-alias-button-primary-fill: var(--liang-accent) !important;\n --dsw-alias-button-primary-hover: var(--liang-accent-hover) !important;\n --dsw-alias-button-info-fill: var(--liang-accent) !important;\n --dsw-alias-button-info-hover: var(--liang-accent-hover) !important;\n --dsw-alias-state-business-primary: var(--liang-accent) !important;\n --dsw-alias-interactive-bg-hover: var(--liang-hover) !important;\n --dsw-alias-interactive-bg-active: var(--liang-hover) !important;\n --dsw-alias-button-elevated-fill: var(--liang-layer-1) !important;\n --dsw-alias-button-floating-fill: var(--liang-layer-2) !important;\n --dsw-alias-button-floating-hover: var(--liang-layer-3) !important;\n --dsw-alias-interactive-bg-hover-solid: var(--liang-layer-2) !important;\n --dsw-specific-bubble: var(--liang-layer-2) !important;\n --dsw-specific-input-major: var(--liang-layer-1) !important;\n --dsw-specific-menu: var(--liang-layer-3) !important;\n --dsw-specific-selector: var(--liang-layer-2) !important;\n background: var(--liang-page) !important;\n}\n\nbody[data-liang-skin=\"on\"]:is(\n [data-liang-stage=\"0\"],\n [data-liang-stage=\"1\"],\n [data-liang-stage=\"2\"],\n [data-liang-stage=\"3\"]\n) {\n --dsw-alias-brand-primary-new-colorprimary-new-color: rgb(65 118 230) !important;\n --dsw-alias-brand-primary: rgb(15 17 21) !important;\n --dsw-alias-brand-text: rgb(15 17 21) !important;\n --dsw-alias-button-primary-fill: rgb(15 17 21) !important;\n --dsw-alias-button-primary-hover: rgb(53 54 56) !important;\n --dsw-alias-button-info-fill: rgb(65 118 230) !important;\n --dsw-alias-button-info-hover: rgb(103 158 254) !important;\n --dsw-alias-state-business-primary: rgb(65 118 230) !important;\n --dsw-alias-label-primary-inverted: rgb(249 250 251) !important;\n --dsw-alias-button-elevated-fill: rgb(255 255 255) !important;\n --dsw-alias-button-floating-fill: rgb(255 255 255) !important;\n --dsw-alias-button-floating-hover: rgb(241 243 245) !important;\n --dsw-alias-interactive-bg-hover-solid: rgb(241 243 245) !important;\n --dsw-specific-bubble: rgb(237 243 254) !important;\n --dsw-specific-input-major: rgb(255 255 255) !important;\n --dsw-specific-menu: rgb(255 255 255) !important;\n --dsw-specific-selector: rgb(245 246 247) !important;\n}\n\nbody[data-liang-skin=\"on\"][data-liang-stage=\"5\"] {\n --dsw-alias-brand-primary-new-colorprimary-new-color: #c19a49 !important;\n --dsw-alias-brand-primary: #c19a49 !important;\n --dsw-alias-brand-text: #d5b56e !important;\n --dsw-alias-button-info-fill: #c19a49 !important;\n --dsw-alias-button-info-hover: #d5b56e !important;\n --dsw-alias-state-business-primary: #c19a49 !important;\n}\n\n/* Preserve the wordmark badge contrast even when the underlying Harness\n preference is dark while our low-intensity shell is light. */\nbody[data-liang-skin=\"on\"]:is(\n [data-liang-stage=\"0\"],\n [data-liang-stage=\"1\"],\n [data-liang-stage=\"2\"],\n [data-liang-stage=\"3\"]\n) button[aria-label=\"\u65B0\u5EFA\u4F1A\u8BDD\"] svg[viewBox=\"0 0 182 24\"] > rect[width=\"52\"] {\n fill: rgb(15 17 21) !important;\n}\n\nbody[data-liang-skin=\"on\"]:is(\n [data-liang-stage=\"0\"],\n [data-liang-stage=\"1\"],\n [data-liang-stage=\"2\"],\n [data-liang-stage=\"3\"]\n) button[aria-label=\"\u65B0\u5EFA\u4F1A\u8BDD\"] svg[viewBox=\"0 0 182 24\"] > g[clip-path*=\"badge\"] path {\n fill: rgb(249 250 251) !important;\n}\n\nbody[data-liang-skin=\"on\"][data-liang-stage=\"5\"] button[aria-label=\"\u65B0\u5EFA\u4F1A\u8BDD\"] svg[viewBox=\"0 0 182 24\"] > rect[width=\"52\"] {\n fill: #c19a49 !important;\n}\n\nbody[data-liang-skin=\"on\"][data-liang-stage=\"5\"] button[aria-label=\"\u65B0\u5EFA\u4F1A\u8BDD\"] svg[viewBox=\"0 0 182 24\"] > g[clip-path*=\"badge\"] path {\n fill: #171816 !important;\n}\n\nbody[data-liang-skin=\"on\"][data-liang-stage=\"5\"] [aria-label^=\"\u9009\u62E9\u6A21\u578B\"] > span:nth-of-type(2) {\n color: #d5b56e !important;\n}\n\nbody[data-liang-skin=\"on\"][data-liang-stage=\"5\"] [class*=\"heroGlow\"] ellipse {\n fill: #c19a49 !important;\n fill-opacity: 0.16 !important;\n}\n\nbody[data-liang-skin=\"on\"][data-liang-stage=\"5\"] span[class*=\"_previewBadge\"] {\n color: #171816 !important;\n background: #c19a49 !important;\n}\n\nbody[data-liang-skin=\"on\"][data-liang-stage=\"5\"] button[aria-label=\"\u53D1\u9001\u6D88\u606F\"] {\n color: #171816 !important;\n}\n\nbody[data-liang-skin=\"on\"][data-liang-stage=\"5\"] button[aria-label=\"\u53D1\u9001\u6D88\u606F\"]:disabled {\n opacity: 0.62;\n}\n\nbody[data-liang-skin=\"on\"]:is(\n [data-liang-stage=\"0\"],\n [data-liang-stage=\"1\"],\n [data-liang-stage=\"2\"],\n [data-liang-stage=\"3\"]\n) button[aria-label=\"\u53D1\u9001\u6D88\u606F\"] {\n color: #fff !important;\n}\n\nbody[data-liang-skin=\"on\"]:is(\n [data-liang-stage=\"0\"],\n [data-liang-stage=\"1\"],\n [data-liang-stage=\"2\"],\n [data-liang-stage=\"3\"]\n) button[aria-label=\"\u53D1\u9001\u6D88\u606F\"]:disabled {\n color: rgb(255 255 255 / 92%) !important;\n background: rgb(65 118 230 / 42%) !important;\n opacity: 1;\n}\n\nbody[data-liang-skin=\"on\"] > #root {\n position: relative;\n z-index: 1;\n background: transparent !important;\n}\n\nbody[data-liang-skin=\"on\"] button,\nbody[data-liang-skin=\"on\"] input,\nbody[data-liang-skin=\"on\"] textarea {\n transition: color 160ms linear, background-color 160ms linear, border-color 160ms linear;\n}\n\n/* Harness can itself be in dark mode while the low intensity stages are light.\n The composer card has a native theme-mode fill, so explicitly bring only\n those light stages back to the original light surface and readable ink. */\nbody[data-liang-skin=\"on\"]:is(\n [data-liang-stage=\"0\"],\n [data-liang-stage=\"1\"],\n [data-liang-stage=\"2\"],\n [data-liang-stage=\"3\"]\n) [data-composer-card=\"true\"] {\n border-color: var(--liang-border) !important;\n color: var(--liang-ink) !important;\n background: var(--liang-layer-1) !important;\n box-shadow: 0 8px 28px rgb(20 22 20 / 8%);\n}\n\nbody[data-liang-skin=\"on\"]:is(\n [data-liang-stage=\"0\"],\n [data-liang-stage=\"1\"],\n [data-liang-stage=\"2\"],\n [data-liang-stage=\"3\"]\n) [data-composer-card=\"true\"] :is(textarea, button, [data-input-mirror=\"true\"]) {\n color: var(--liang-ink) !important;\n caret-color: var(--liang-accent) !important;\n}\n\nbody[data-liang-skin=\"on\"]:is(\n [data-liang-stage=\"0\"],\n [data-liang-stage=\"1\"],\n [data-liang-stage=\"2\"],\n [data-liang-stage=\"3\"]\n) [data-composer-card=\"true\"] textarea::placeholder {\n color: var(--liang-tertiary) !important;\n opacity: 1;\n}\n\n.liang-effort-control {\n --liang-control-accent: var(--dsw-alias-brand-primary-new-colorprimary-new-color, #4176e6);\n --liang-control-rail: var(--dsw-alias-border-l3, rgb(0 0 0 / 16%));\n position: relative;\n display: flex;\n width: 124px;\n height: 28px;\n align-items: center;\n margin: 0 3px;\n overflow: visible;\n}\n\nbody[data-liang-skin=\"on\"] .liang-effort-control {\n --liang-control-accent: var(--liang-secondary);\n --liang-control-rail: color-mix(in srgb, var(--liang-secondary) 28%, transparent);\n}\n\n.liang-effort-control__ticks {\n position: absolute;\n z-index: 0;\n inset: 0 10px;\n pointer-events: none;\n}\n\n.liang-effort-control__ticks::before {\n position: absolute;\n top: 50%;\n right: 0;\n left: 0;\n height: 1px;\n content: \"\";\n background: var(--liang-control-rail);\n transform: translateY(-50%);\n}\n\n.liang-effort-control__tooltip {\n position: absolute;\n z-index: 4;\n bottom: calc(100% + 7px);\n left: calc(10px + (100% - 20px) * var(--liang-slider-ratio));\n min-width: max-content;\n padding: 5px 8px;\n border: 1px solid var(--liang-border, rgb(0 0 0 / 12%));\n border-radius: 7px;\n color: var(--liang-ink, #171816);\n background: var(--liang-layer-1, #fff);\n box-shadow: 0 5px 16px rgb(0 0 0 / 16%);\n font-size: 11px;\n font-weight: 600;\n line-height: 16px;\n letter-spacing: 0.01em;\n pointer-events: none;\n transform: translateX(-50%);\n white-space: nowrap;\n}\n\n.liang-effort-control__tooltip::after {\n position: absolute;\n top: 100%;\n left: 50%;\n width: 7px;\n height: 7px;\n content: \"\";\n background: inherit;\n transform: translate(-50%, -4px) rotate(45deg);\n}\n\n.liang-effort-control__tick {\n position: absolute;\n top: 50%;\n width: 1px;\n height: 7px;\n background: var(--liang-control-accent);\n opacity: 0.42;\n transform: translate(-50%, -50%);\n}\n\n.liang-effort-control__range {\n position: relative;\n z-index: 1;\n width: calc(100% - 7px);\n height: 28px;\n margin: 0 3.5px;\n cursor: ew-resize;\n appearance: none;\n background: transparent;\n touch-action: pan-y;\n}\n\n.liang-effort-control__range:disabled {\n cursor: progress;\n opacity: 0.58;\n}\n\n.liang-effort-control__range::-webkit-slider-runnable-track {\n height: 1px;\n border-radius: 1px;\n background: transparent;\n}\n\n.liang-effort-control__range::-webkit-slider-thumb {\n width: 13px;\n height: 13px;\n margin-top: -6px;\n border: 1.5px solid color-mix(in srgb, var(--liang-control-accent) 72%, transparent);\n border-radius: 50%;\n appearance: none;\n background: radial-gradient(circle, var(--liang-control-accent) 0 2px, color-mix(in srgb, var(--liang-control-accent) 22%, var(--dsw-alias-bg-layer-1, #fff)) 2.5px);\n box-shadow: 0 1px 4px rgb(0 0 0 / 14%);\n}\n\nbody[data-liang-skin=\"on\"] .liang-effort-control__range::-webkit-slider-thumb {\n width: 13px;\n height: 13px;\n margin-top: -6px;\n border-color: color-mix(in srgb, var(--liang-control-accent) 72%, transparent);\n background: radial-gradient(circle, var(--liang-control-accent) 0 2px, color-mix(in srgb, var(--liang-control-accent) 22%, var(--liang-layer-1)) 2.5px);\n}\n\n.liang-effort-control__range::-moz-range-track {\n height: 1px;\n background: transparent;\n}\n\n.liang-effort-control__range::-moz-range-progress {\n height: 1px;\n background: transparent;\n}\n\n.liang-effort-control__range::-moz-range-thumb {\n width: 11px;\n height: 11px;\n border: 1.5px solid color-mix(in srgb, var(--liang-control-accent) 72%, transparent);\n border-radius: 50%;\n background: color-mix(in srgb, var(--liang-control-accent) 24%, var(--dsw-alias-bg-layer-1, #fff));\n}\n\n.liang-effort-control__range:focus-visible {\n outline: none;\n}\n\n.liang-effort-control[data-state=\"error\"] {\n --liang-control-accent: var(--dsw-alias-state-error-primary, #e43c3c);\n}\n\n.liang-settings-row {\n display: flex;\n min-height: 82px;\n align-items: center;\n justify-content: space-between;\n gap: 24px;\n padding: 16px 0;\n border-bottom: 1px solid var(--dsw-alias-border-l1, rgb(0 0 0 / 6%));\n color: var(--dsw-alias-label-primary);\n}\n\n.liang-settings-row__title {\n flex: 0 0 auto;\n font-size: 14px;\n font-weight: 500;\n}\n\n.liang-settings-row__choices {\n display: flex;\n gap: 8px;\n}\n\n.liang-settings-row__choice {\n min-width: 76px;\n height: 40px;\n padding: 0 14px;\n border: 1px solid var(--dsw-alias-border-l2, rgb(0 0 0 / 10%));\n border-radius: 10px;\n color: var(--dsw-alias-label-secondary);\n background: var(--dsw-alias-bg-layer-1);\n cursor: pointer;\n}\n\n.liang-settings-row__choice:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n.liang-settings-row__choice[aria-pressed=\"true\"] {\n border-color: var(--dsw-alias-label-primary);\n color: var(--dsw-alias-label-primary);\n box-shadow: inset 0 0 0 1px var(--dsw-alias-label-primary);\n}\n\n@media (max-width: 760px) {\n .liang-effort-control {\n width: 92px;\n }\n\n .liang-skin-backdrop video,\n .liang-skin-backdrop img {\n right: -18vw;\n width: 92vw;\n opacity: calc(var(--liang-portrait-opacity, 0.45) * 0.72);\n }\n\n .liang-settings-row {\n align-items: flex-start;\n flex-direction: column;\n gap: 12px;\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .liang-skin-backdrop,\n .liang-skin-backdrop video,\n .liang-skin-backdrop img,\n body[data-liang-skin=\"on\"] button,\n body[data-liang-skin=\"on\"] input,\n body[data-liang-skin=\"on\"] textarea {\n transition: none;\n }\n}\n", "export const PREVIEW_MAX_FRAME = 240;\nexport const MAX_LEVEL = 30;\n\nconst LIANG_RANKS = [\"\u5C0F\u96BE\u6881\", \"\u7262\u6881\", \"\u6881\u5B50\", \"\u6881\u5723\", \"\u6881\u795E\", \"\u6881\u7956\"] as const;\n\nexport interface EffortLike {\n id: string;\n name: string;\n description?: string;\n}\n\nexport interface Palette {\n level: number;\n stage: number;\n strength: number;\n page: string;\n base: string;\n layer1: string;\n layer2: string;\n layer3: string;\n sidebar: string;\n ink: string;\n secondary: string;\n tertiary: string;\n border: string;\n accent: string;\n accentHover: string;\n hover: string;\n portraitOpacity: string;\n}\n\ntype Rgb = readonly [number, number, number];\n\ninterface PaletteStop {\n at: number;\n page: Rgb;\n surface: Rgb;\n surface2: Rgb;\n ink: Rgb;\n secondary: Rgb;\n accent: Rgb;\n portraitOpacity: number;\n}\n\n// These are the original calibrator's six stage anchors: pale neutral at the\n// low end, progressively smoked surfaces, then charcoal and antique gold.\nconst STOPS: readonly PaletteStop[] = [\n { at: 0, page: [232, 233, 229], surface: [248, 248, 245], surface2: [238, 239, 235], ink: [23, 24, 22], secondary: [112, 116, 111], accent: [181, 43, 36], portraitOpacity: 0.92 },\n { at: 6, page: [211, 211, 206], surface: [239, 239, 234], surface2: [224, 224, 218], ink: [26, 26, 24], secondary: [101, 101, 96], accent: [181, 43, 36], portraitOpacity: 0.93 },\n { at: 12, page: [171, 168, 162], surface: [211, 208, 201], surface2: [190, 186, 179], ink: [27, 26, 24], secondary: [83, 79, 74], accent: [166, 54, 42], portraitOpacity: 0.94 },\n { at: 18, page: [117, 112, 106], surface: [154, 148, 140], surface2: [128, 122, 115], ink: [24, 22, 20], secondary: [65, 61, 56], accent: [154, 56, 42], portraitOpacity: 0.94 },\n { at: 24, page: [43, 39, 37], surface: [48, 43, 40], surface2: [58, 51, 46], ink: [244, 241, 232], secondary: [184, 180, 169], accent: [181, 92, 54], portraitOpacity: 0.94 },\n { at: 30, page: [17, 17, 17], surface: [30, 27, 25], surface2: [41, 35, 30], ink: [244, 241, 232], secondary: [184, 180, 169], accent: [193, 154, 73], portraitOpacity: 0.94 },\n];\n\nexport function clampFrame(value: number): number {\n if (!Number.isFinite(value)) return 0;\n return Math.min(PREVIEW_MAX_FRAME, Math.max(0, Math.round(value)));\n}\n\nexport function frameForEffort(index: number, count: number): number {\n if (count <= 1 || !Number.isFinite(index)) return 0;\n const safe = Math.min(count - 1, Math.max(0, Math.round(index)));\n return Math.round((safe / (count - 1)) * PREVIEW_MAX_FRAME);\n}\n\nexport function nearestEffortIndex(frame: number, efforts: readonly EffortLike[]): number {\n if (efforts.length === 0) return -1;\n const safe = clampFrame(frame);\n let best = 0;\n let distance = Math.abs(safe - frameForEffort(0, efforts.length));\n for (let index = 1; index < efforts.length; index += 1) {\n const next = Math.abs(safe - frameForEffort(index, efforts.length));\n if (next < distance) {\n best = index;\n distance = next;\n }\n }\n return best;\n}\n\nexport function selectedEffortIndex(\n efforts: readonly EffortLike[],\n selectedId?: string,\n defaultId?: string,\n): number {\n const id = selectedId ?? defaultId;\n return id === undefined ? -1 : efforts.findIndex((effort) => effort.id === id);\n}\n\nexport function portraitBlendForLevel(level: number, anchors: readonly number[]) {\n if (anchors.length === 0) return { lowerIndex: -1, upperIndex: -1, mix: 0 };\n const safeLevel = Number.isFinite(level)\n ? Math.min(anchors[anchors.length - 1], Math.max(anchors[0], level))\n : anchors[0];\n let upperIndex = anchors.findIndex((anchor) => anchor >= safeLevel);\n if (upperIndex < 0) upperIndex = anchors.length - 1;\n const lowerIndex = Math.max(0, upperIndex - (anchors[upperIndex] > safeLevel ? 1 : 0));\n const span = anchors[upperIndex] - anchors[lowerIndex];\n return {\n lowerIndex,\n upperIndex,\n mix: span === 0 ? 0 : (safeLevel - anchors[lowerIndex]) / span,\n };\n}\n\nexport function liangRankForFrame(rawFrame: number): string {\n const level = (clampFrame(rawFrame) / PREVIEW_MAX_FRAME) * MAX_LEVEL;\n const index = level >= MAX_LEVEL ? LIANG_RANKS.length - 1 : Math.floor(level / 6);\n return LIANG_RANKS[Math.min(LIANG_RANKS.length - 1, Math.max(0, index))];\n}\n\nexport function indicatorLabel(rawFrame: number, efforts: readonly EffortLike[]): string {\n const effort = efforts[nearestEffortIndex(rawFrame, efforts)];\n return effort === undefined\n ? liangRankForFrame(rawFrame)\n : `${liangRankForFrame(rawFrame)} \u00B7 ${effort.name}`;\n}\n\nfunction lerp(a: number, b: number, amount: number): number {\n return a + (b - a) * amount;\n}\n\nfunction mix(a: Rgb, b: Rgb, amount: number): Rgb {\n return [\n Math.round(lerp(a[0], b[0], amount)),\n Math.round(lerp(a[1], b[1], amount)),\n Math.round(lerp(a[2], b[2], amount)),\n ];\n}\n\nfunction rgb(value: Rgb, alpha = 1): string {\n return alpha === 1\n ? `rgb(${value[0]} ${value[1]} ${value[2]})`\n : `rgb(${value[0]} ${value[1]} ${value[2]} / ${alpha})`;\n}\n\nexport function paletteForFrame(rawFrame: number): Palette {\n const frame = clampFrame(rawFrame);\n const level = (frame / PREVIEW_MAX_FRAME) * MAX_LEVEL;\n const portraitStage = Math.min(5, Math.floor(level / 6));\n const portraitFrom = STOPS[portraitStage];\n const portraitTo = STOPS[Math.min(5, portraitStage + 1)];\n const portraitAmount = portraitFrom === portraitTo\n ? 0\n : (level - portraitFrom.at) / (portraitTo.at - portraitFrom.at);\n\n // The UI itself is intentionally binary: levels 0\u201323 keep the native light\n // shell; entering the original \u6881\u795E/\u6881\u7956 region at level 24 switches black/gold.\n const dark = level >= 24;\n const stage = dark ? 5 : 0;\n const ui = dark ? STOPS[5] : STOPS[0];\n const page = ui.page;\n const surface = ui.surface;\n const surface2 = ui.surface2;\n const sidebar = mix(page, surface2, 0.25);\n const ink = ui.ink;\n const secondary = ui.secondary;\n // Keep Harness' native blue in the light shell. The original calibrator's\n // antique gold only becomes the product accent once the dark region begins.\n const accent: Rgb = dark ? [193, 154, 73] : [65, 118, 230];\n const accentHover = mix(accent, ink, 0.13);\n\n return {\n level,\n stage,\n strength: level / MAX_LEVEL,\n page: rgb(page),\n // Keep the shell readable while allowing the right-side portrait to remain\n // visibly present. Dense controls use the opaque layer tokens below.\n base: rgb(page, dark ? 0.42 : 0.28),\n layer1: rgb(surface, 0.94),\n layer2: rgb(surface2, 0.96),\n layer3: rgb(surface2, 0.99),\n sidebar: rgb(sidebar, 0.96),\n ink: rgb(ink),\n secondary: rgb(secondary),\n tertiary: rgb(mix(secondary, page, 0.28)),\n border: rgb(ink, dark ? 0.15 : 0.12),\n accent: rgb(accent),\n accentHover: rgb(accentHover),\n hover: rgb(ink, dark ? 0.09 : 0.07),\n portraitOpacity: String(lerp(\n portraitFrom.portraitOpacity,\n portraitTo.portraitOpacity,\n portraitAmount,\n )),\n };\n}\n"], - "mappings": "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", + "sourcesContent": ["import {\n useEffect,\n useMemo,\n useRef,\n useState,\n useSyncExternalStore,\n} from \"react\";\nimport type { ClientContext, SnapshotStore } from \"@deepseek-ai/dsh-client-runtime/client\";\nimport type {} from \"@deepseek-ai/dsh-client-ui-conversation/client\";\nimport type {} from \"@deepseek-ai/dsh-client-ui-settings/client\";\nimport type {} from \"@deepseek-ai/dsh-client-ui-model-selection/client\";\nimport styles from \"./skin.css\";\nimport {\n PREVIEW_MAX_FRAME,\n frameForEffort,\n indicatorLabel,\n nearestEffortIndex,\n paletteForFrame,\n portraitBlendForLevel,\n selectedEffortIndex,\n type EffortLike,\n} from \"./logic\";\n\nconst PACKAGE_ID = \"dsh-client-liang-intensity-skin\";\nconst LOCALE_NAMESPACE = \"liang.skin\";\nconst ASSET_PREFIX = `/plugins/${PACKAGE_ID}/assets`;\nconst VIDEO_DURATION = 8.033;\nconst PREFERENCE_KEY = \"dsh-liang-intensity-skin.enabled\";\n\nconst PORTRAIT_ANCHORS = [\n { level: 0, file: \"stage-00.png\" },\n { level: 1, file: \"level-01.png\" },\n { level: 3, file: \"level-03.png\" },\n { level: 4, file: \"level-04.png\" },\n { level: 6, file: \"stage-06.png\" },\n { level: 7, file: \"level-07.png\" },\n { level: 9, file: \"level-09.png\" },\n { level: 10, file: \"level-10.png\" },\n { level: 12, file: \"stage-12.png\" },\n { level: 13, file: \"level-13.png\" },\n { level: 14, file: \"level-14.png\" },\n { level: 15, file: \"bridge-15.png\" },\n { level: 16, file: \"level-16.png\" },\n { level: 17, file: \"level-17.png\" },\n { level: 18, file: \"stage-18.png\" },\n { level: 19, file: \"level-19.png\" },\n { level: 21, file: \"level-21.png\" },\n { level: 22, file: \"level-22.png\" },\n { level: 24, file: \"stage-24.png\" },\n { level: 25, file: \"level-25.png\" },\n { level: 27, file: \"bridge-27.png\" },\n { level: 28, file: \"level-28.png\" },\n { level: 29, file: \"level-29.png\" },\n { level: 30, file: \"stage-30.png\" },\n] as const;\n\ninterface SkinSettings {\n enabled: boolean;\n}\n\ninterface PreferenceStore {\n getSnapshot(): SkinSettings;\n subscribe(listener: () => void): () => void;\n set(enabled: boolean): Promise;\n dispose(): void;\n}\n\ntype NativeThemeId = \"light\" | \"dark\";\n\ninterface ThemeService {\n getTheme(): { preference: string };\n setTheme(id: NativeThemeId): void;\n}\n\ninterface ModelSelection {\n provider: string;\n model: string;\n reasoningEffort?: string;\n}\n\ninterface CatalogModel {\n id: string;\n reasoning?: {\n efforts: EffortLike[];\n defaultEffort?: string;\n };\n}\n\ninterface ModelDirectoryState {\n current: ModelSelection | null;\n groups: readonly { id: string; models: CatalogModel[] }[];\n status: \"idle\" | \"loading\" | \"ready\" | \"selecting\" | \"error\";\n error: string | null;\n}\n\ninterface ModelDirectory {\n store: SnapshotStore;\n load(): Promise;\n select(selection: ModelSelection): Promise;\n}\n\ninterface SliderProps {\n directory: SnapshotStore;\n load: () => void;\n select: (selection: ModelSelection) => Promise;\n presenter: SkinPresenter;\n scope: PreferenceStore;\n}\n\ninterface SettingsRowProps {\n scope: PreferenceStore;\n presenter: SkinPresenter;\n t: (key: string) => string;\n}\n\nconst cssVariables = [\n \"--liang-strength\",\n \"--liang-page\",\n \"--liang-bg-base\",\n \"--liang-layer-1\",\n \"--liang-layer-2\",\n \"--liang-layer-3\",\n \"--liang-sidebar\",\n \"--liang-ink\",\n \"--liang-secondary\",\n \"--liang-tertiary\",\n \"--liang-border\",\n \"--liang-accent\",\n \"--liang-accent-hover\",\n \"--liang-hover\",\n \"--liang-portrait-opacity\",\n] as const;\n\nclass SkinPresenter {\n private readonly scope: PreferenceStore;\n private readonly theme: ThemeService;\n private readonly root: HTMLDivElement;\n private readonly video: HTMLVideoElement;\n private readonly poster: HTMLImageElement;\n private readonly portrait: HTMLImageElement;\n private readonly preloads: HTMLImageElement[];\n private enabled = true;\n private frame = 0;\n private pendingFrame = 0;\n private raf = 0;\n private disposed = false;\n private unsubscribe: () => void;\n\n constructor(scope: PreferenceStore, theme: ThemeService) {\n this.scope = scope;\n this.theme = theme;\n this.root = document.createElement(\"div\");\n this.root.className = \"liang-skin-backdrop\";\n this.root.dataset.plugin = PACKAGE_ID;\n this.root.dataset.media = \"sequence\";\n this.root.setAttribute(\"aria-hidden\", \"true\");\n\n this.video = document.createElement(\"video\");\n this.video.muted = true;\n this.video.playsInline = true;\n this.video.preload = \"auto\";\n // A video poster stays painted while a paused video is scrubbed in some\n // browsers, which would make every effort show the same portrait. Keep the\n // separate image element as the true load-error fallback instead.\n const webm = document.createElement(\"source\");\n webm.src = `${ASSET_PREFIX}/liang-evolution.webm`;\n webm.type = \"video/webm\";\n const mp4 = document.createElement(\"source\");\n mp4.src = `${ASSET_PREFIX}/liang-evolution.mp4`;\n mp4.type = \"video/mp4\";\n this.video.append(webm, mp4);\n\n this.poster = document.createElement(\"img\");\n this.poster.className = \"liang-skin-poster\";\n this.poster.src = `${ASSET_PREFIX}/liang-poster.png`;\n this.poster.alt = \"\";\n\n this.portrait = document.createElement(\"img\");\n this.portrait.className = \"liang-skin-sequence-frame\";\n this.portrait.alt = \"\";\n this.portrait.draggable = false;\n this.portrait.addEventListener(\"error\", this.handleSequenceError);\n\n this.preloads = PORTRAIT_ANCHORS.map(({ file }) => {\n const image = new Image();\n image.src = `${ASSET_PREFIX}/portrait-source-v2/${file}`;\n return image;\n });\n\n this.root.append(this.video, this.portrait, this.poster);\n document.body.prepend(this.root);\n\n this.video.addEventListener(\"loadedmetadata\", this.handleMetadata);\n this.video.addEventListener(\"error\", this.handleVideoError);\n this.poster.addEventListener(\"error\", this.handlePosterError);\n this.video.load();\n this.unsubscribe = scope.subscribe(() => this.syncSettings());\n this.syncSettings();\n }\n\n private readonly handleMetadata = () => {\n this.seek(this.frame);\n };\n\n private readonly handleVideoError = () => {\n this.root.dataset.media = \"poster\";\n };\n\n private readonly handleSequenceError = () => {\n this.root.dataset.media = \"video\";\n };\n\n private readonly handlePosterError = () => {\n this.root.dataset.media = \"color\";\n };\n\n private syncSettings() {\n this.setEnabled(this.scope.getSnapshot().enabled);\n }\n\n isEnabled() {\n return this.enabled;\n }\n\n setEnabled(enabled: boolean) {\n this.enabled = enabled;\n if (enabled) {\n if (!this.root.isConnected) document.body.prepend(this.root);\n document.body.dataset.liangSkin = \"on\";\n this.applyFrame();\n } else {\n this.root.remove();\n delete document.body.dataset.liangSkin;\n delete document.body.dataset.liangStage;\n for (const name of cssVariables) document.body.style.removeProperty(name);\n }\n }\n\n setFrame(frame: number) {\n this.pendingFrame = Math.min(PREVIEW_MAX_FRAME, Math.max(0, Math.round(frame)));\n this.frame = this.pendingFrame;\n if (!this.enabled) return;\n if (this.raf !== 0) return;\n this.raf = requestAnimationFrame(() => {\n this.raf = 0;\n this.frame = this.pendingFrame;\n this.applyFrame();\n });\n }\n\n private applyFrame() {\n const palette = paletteForFrame(this.frame);\n const body = document.body;\n this.syncNativeTheme(palette.stage === 5 ? \"dark\" : \"light\");\n body.dataset.liangStage = String(palette.stage);\n body.style.setProperty(\"--liang-strength\", String(palette.strength));\n body.style.setProperty(\"--liang-page\", palette.page);\n body.style.setProperty(\"--liang-bg-base\", palette.base);\n body.style.setProperty(\"--liang-layer-1\", palette.layer1);\n body.style.setProperty(\"--liang-layer-2\", palette.layer2);\n body.style.setProperty(\"--liang-layer-3\", palette.layer3);\n body.style.setProperty(\"--liang-sidebar\", palette.sidebar);\n body.style.setProperty(\"--liang-ink\", palette.ink);\n body.style.setProperty(\"--liang-secondary\", palette.secondary);\n body.style.setProperty(\"--liang-tertiary\", palette.tertiary);\n body.style.setProperty(\"--liang-border\", palette.border);\n body.style.setProperty(\"--liang-accent\", palette.accent);\n body.style.setProperty(\"--liang-accent-hover\", palette.accentHover);\n body.style.setProperty(\"--liang-hover\", palette.hover);\n body.style.setProperty(\"--liang-portrait-opacity\", palette.portraitOpacity);\n this.updatePortrait(palette.level);\n this.seek(this.frame);\n }\n\n syncNativeTheme(theme: NativeThemeId = paletteForFrame(this.frame).stage === 5 ? \"dark\" : \"light\") {\n if (!this.enabled || this.theme.getTheme().preference === theme) return;\n this.theme.setTheme(theme);\n }\n\n private updatePortrait(level: number) {\n const { lowerIndex, upperIndex, mix } = portraitBlendForLevel(\n level,\n PORTRAIT_ANCHORS.map((anchor) => anchor.level),\n );\n const lower = PORTRAIT_ANCHORS[lowerIndex];\n const upper = PORTRAIT_ANCHORS[upperIndex];\n const selected = mix >= 0.5 ? upper : lower;\n const source = `${ASSET_PREFIX}/portrait-source-v2/${selected.file}`;\n if (this.portrait.getAttribute(\"src\") !== source) this.portrait.src = source;\n }\n\n private seek(frame: number) {\n if (this.video.readyState < 1 || this.video.duration === 0) return;\n const duration = Number.isFinite(this.video.duration) ? this.video.duration : VIDEO_DURATION;\n const target = Math.min(Math.max(0, duration - 0.001), (frame / PREVIEW_MAX_FRAME) * duration);\n if (Math.abs(this.video.currentTime - target) > 0.025) this.video.currentTime = target;\n }\n\n async choose(enabled: boolean) {\n this.setEnabled(enabled);\n try {\n await this.scope.set(enabled);\n } catch (error) {\n this.syncSettings();\n throw error;\n }\n }\n\n dispose() {\n if (this.disposed) return;\n this.disposed = true;\n this.unsubscribe();\n if (this.raf !== 0) cancelAnimationFrame(this.raf);\n this.video.pause();\n this.video.removeEventListener(\"loadedmetadata\", this.handleMetadata);\n this.video.removeEventListener(\"error\", this.handleVideoError);\n this.portrait.removeEventListener(\"error\", this.handleSequenceError);\n this.poster.removeEventListener(\"error\", this.handlePosterError);\n for (const image of this.preloads) image.src = \"\";\n this.root.remove();\n document.body.removeAttribute(\"data-liang-skin\");\n delete document.body.dataset.liangStage;\n for (const name of cssVariables) document.body.style.removeProperty(name);\n }\n}\n\nfunction modelReasoning(state: ModelDirectoryState) {\n const current = state.current;\n if (current === null) return null;\n const group = state.groups.find((item) => item.id === current.provider);\n const model = group?.models.find((item) => item.id === current.model);\n if (model?.reasoning === undefined) return null;\n return {\n selection: current,\n efforts: model.reasoning.efforts,\n defaultEffort: model.reasoning.defaultEffort,\n };\n}\n\nfunction LiangEffortSlider({ directory, load, select, presenter, scope }: SliderProps) {\n const state = useSyncExternalStore(\n (listener) => directory.subscribe(listener),\n () => directory.getSnapshot(),\n );\n const skin = useSyncExternalStore(\n (listener) => scope.subscribe(listener),\n () => scope.getSnapshot(),\n );\n const reasoning = useMemo(() => modelReasoning(state), [state]);\n const efforts = reasoning?.efforts ?? [];\n const committedIndex = selectedEffortIndex(\n efforts,\n reasoning?.selection.reasoningEffort,\n reasoning?.defaultEffort,\n );\n const committedFrame = committedIndex < 0\n ? 0\n : frameForEffort(committedIndex, efforts.length);\n const [frame, setFrame] = useState(committedFrame);\n const [pending, setPending] = useState(false);\n const [failed, setFailed] = useState(false);\n const [interacting, setInteracting] = useState(false);\n const dragging = useRef(false);\n const enabled = skin.enabled;\n\n useEffect(() => {\n if (enabled) load();\n }, [enabled, load]);\n\n useEffect(() => {\n if (dragging.current || pending) return;\n setFrame(committedFrame);\n presenter.setFrame(committedFrame);\n }, [committedFrame, pending, presenter]);\n\n if (!enabled) return null;\n if (reasoning === null || efforts.length < 2) return null;\n\n const previewIndex = nearestEffortIndex(frame, efforts);\n const previewEffort = efforts[previewIndex];\n const progressRatio = frame / PREVIEW_MAX_FRAME;\n\n const commit = async (rawFrame: number) => {\n const targetIndex = nearestEffortIndex(rawFrame, efforts);\n const target = efforts[targetIndex];\n if (target === undefined) return;\n const targetFrame = frameForEffort(targetIndex, efforts.length);\n dragging.current = false;\n setFrame(targetFrame);\n presenter.setFrame(targetFrame);\n if (targetIndex === committedIndex || pending) return;\n setPending(true);\n setFailed(false);\n const accepted = await select({\n provider: reasoning.selection.provider,\n model: reasoning.selection.model,\n reasoningEffort: target.id,\n });\n setPending(false);\n if (!accepted) {\n setFailed(true);\n setFrame(committedFrame);\n presenter.setFrame(committedFrame);\n }\n };\n\n return (\n \n {interacting && (\n \n {indicatorLabel(frame, efforts)}\n \n )}\n
\n {efforts.map((effort, index) => (\n \n ))}\n
\n {\n dragging.current = true;\n setInteracting(true);\n }}\n onInput={(event) => {\n dragging.current = true;\n const next = Number(event.currentTarget.value);\n setFrame(next);\n presenter.setFrame(next);\n }}\n onPointerUp={(event) => {\n setInteracting(false);\n void commit(Number(event.currentTarget.value));\n }}\n onPointerCancel={() => {\n setInteracting(false);\n dragging.current = false;\n setFrame(committedFrame);\n presenter.setFrame(committedFrame);\n }}\n onKeyUp={(event) => {\n setInteracting(false);\n if (event.key !== \"Escape\") void commit(Number(event.currentTarget.value));\n }}\n onBlur={(event) => {\n setInteracting(false);\n if (dragging.current) void commit(Number(event.currentTarget.value));\n }}\n onKeyDown={(event) => {\n setInteracting(true);\n if (event.key === \"Escape\" && !pending) {\n setInteracting(false);\n dragging.current = false;\n setFrame(committedFrame);\n presenter.setFrame(committedFrame);\n }\n }}\n />\n \n );\n}\n\nfunction AppearanceSkinRow({ scope, presenter, t }: SettingsRowProps) {\n const snapshot = useSyncExternalStore(\n (listener) => scope.subscribe(listener),\n () => scope.getSnapshot(),\n );\n const enabled = snapshot.enabled;\n const [pending, setPending] = useState(false);\n\n const choose = async (next: boolean) => {\n if (next === enabled || pending) return;\n setPending(true);\n try {\n await presenter.choose(next);\n } finally {\n setPending(false);\n }\n };\n\n return (\n
\n {t(\"appearance.title\")}\n
\n void choose(false)}\n >\n {t(\"appearance.native\")}\n \n void choose(true)}\n >\n {t(\"appearance.liang\")}\n \n
\n
\n );\n}\n\nexport const inject = [\n \"slots\",\n \"sessions\",\n \"modelDirectories\",\n \"locale\",\n \"theme\",\n];\n\nfunction createPreferenceStore(): PreferenceStore {\n let snapshot: SkinSettings = {\n enabled: localStorage.getItem(PREFERENCE_KEY) !== \"0\",\n };\n const listeners = new Set<() => void>();\n const onStorage = (event: StorageEvent) => {\n if (event.key !== PREFERENCE_KEY) return;\n const enabled = event.newValue !== \"0\";\n if (enabled === snapshot.enabled) return;\n snapshot = { enabled };\n for (const listener of listeners) listener();\n };\n window.addEventListener(\"storage\", onStorage);\n return {\n getSnapshot: () => snapshot,\n subscribe(listener) {\n listeners.add(listener);\n return () => listeners.delete(listener);\n },\n async set(enabled) {\n if (enabled === snapshot.enabled) return;\n localStorage.setItem(PREFERENCE_KEY, enabled ? \"1\" : \"0\");\n snapshot = { enabled };\n for (const listener of listeners) listener();\n },\n dispose() {\n window.removeEventListener(\"storage\", onStorage);\n listeners.clear();\n },\n };\n}\n\nexport function apply(ctx: ClientContext) {\n const style = document.createElement(\"style\");\n style.dataset.plugin = PACKAGE_ID;\n style.textContent = styles;\n document.head.append(style);\n ctx.effect(() => () => style.remove(), \"liang-intensity-skin: scoped styles\");\n\n const scope = createPreferenceStore();\n ctx.effect(() => () => scope.dispose(), \"liang-intensity-skin: appearance preference\");\n const theme = ctx.get(\"theme\") as ThemeService;\n const presenter = new SkinPresenter(scope, theme);\n ctx.effect(() => () => presenter.dispose(), \"liang-intensity-skin: backdrop presenter\");\n ctx.effect(\n () => ctx.on(\"theme/change\", () => presenter.syncNativeTheme()),\n \"liang-intensity-skin: native theme synchronization\",\n );\n\n ctx.effect(() => ctx.locale.register(LOCALE_NAMESPACE, {\n zh: {\n \"appearance.title\": \"\u5916\u89C2\u76AE\u80A4\",\n \"appearance.native\": \"\u539F\u751F\",\n \"appearance.liang\": \"\u6ED1\u52A8\u53D8\u7956\",\n },\n en: {\n \"appearance.title\": \"Visual skin\",\n \"appearance.native\": \"Native\",\n \"appearance.liang\": \"Slider\",\n },\n }), \"liang-intensity-skin: settings locale\");\n\n ctx.slots.inject(\"settings.general.item\", () => ctx.slots.register({\n name: \"settings.general.item\",\n id: \"liang-intensity-appearance\",\n order: 11,\n locale: LOCALE_NAMESPACE,\n inject: () => ({ scope, presenter }),\n }, AppearanceSkinRow));\n\n ctx.slots.inject(\"conversation.input.right\", () => ctx.slots.register({\n name: \"conversation.input.right\",\n id: \"liang-intensity-control\",\n order: 10,\n inject: (sessionId: string) => {\n const available = ctx.sessions.subagentAddress(sessionId) === undefined;\n const directory = ctx.modelDirectories.directoryFor(sessionId) as ModelDirectory;\n return {\n directory: directory.store,\n presenter,\n scope,\n load: () => {\n if (available) void directory.load().catch(() => undefined);\n },\n select: (selection: ModelSelection) => available\n ? directory.select(selection).then(() => true, () => false)\n : Promise.resolve(false),\n };\n },\n }, LiangEffortSlider));\n}\n", ".liang-skin-backdrop {\n position: fixed;\n z-index: 0;\n inset: 0;\n overflow: hidden;\n pointer-events: none;\n background: var(--liang-page, transparent);\n opacity: 0;\n transition: opacity 220ms ease, background-color 180ms linear;\n}\n\nbody[data-liang-skin=\"on\"] .liang-skin-backdrop {\n opacity: 1;\n}\n\n.liang-skin-backdrop video,\n.liang-skin-backdrop img {\n position: absolute;\n top: 50%;\n right: 0;\n display: block;\n width: min(42vw, 720px);\n height: 100vh;\n object-fit: cover;\n object-position: 50% 42%;\n opacity: var(--liang-portrait-opacity, 0.45);\n transform: translateY(-50%);\n filter: none;\n mask-image: linear-gradient(90deg, transparent 0%, rgb(0 0 0 / 20%) 10%, black 30%, black 100%);\n transition: filter 180ms linear;\n}\n\n.liang-skin-backdrop img {\n display: none;\n}\n\n.liang-skin-backdrop[data-media=\"sequence\"] video,\n.liang-skin-backdrop[data-media=\"sequence\"] .liang-skin-poster {\n display: none;\n}\n\n.liang-skin-backdrop[data-media=\"sequence\"] .liang-skin-sequence-frame {\n display: block;\n opacity: var(--liang-portrait-opacity, 0.82);\n}\n\n.liang-skin-backdrop[data-media=\"video\"] .liang-skin-sequence-frame,\n.liang-skin-backdrop[data-media=\"video\"] .liang-skin-poster {\n display: none;\n}\n\n.liang-skin-backdrop[data-media=\"poster\"] video,\n.liang-skin-backdrop[data-media=\"poster\"] .liang-skin-sequence-frame {\n display: none;\n}\n\n.liang-skin-backdrop[data-media=\"poster\"] .liang-skin-poster {\n display: block;\n}\n\n.liang-skin-backdrop[data-media=\"color\"] video,\n.liang-skin-backdrop[data-media=\"color\"] img {\n display: none;\n}\n\n.liang-skin-backdrop::after {\n position: absolute;\n inset: 0;\n content: \"\";\n background: linear-gradient(90deg, var(--liang-page, transparent) 0 28%, transparent 57% 100%);\n}\n\nbody[data-liang-skin=\"on\"] {\n --dsw-alias-bg-base: var(--liang-bg-base) !important;\n --dsw-alias-bg-layer-1: var(--liang-layer-1) !important;\n --dsw-alias-bg-layer-2: var(--liang-layer-2) !important;\n --dsw-alias-bg-layer-3: var(--liang-layer-3) !important;\n --dsw-specific-sidebar-fill: var(--liang-sidebar) !important;\n --dsw-alias-label-primary: var(--liang-ink) !important;\n --dsw-alias-label-primary-dimmed: var(--liang-ink) !important;\n --dsw-alias-label-secondary: var(--liang-secondary) !important;\n --dsw-alias-label-tertiary: var(--liang-tertiary) !important;\n --dsw-alias-label-caption: var(--liang-tertiary) !important;\n --dsw-alias-border-l1: var(--liang-border) !important;\n --dsw-alias-border-l2-darkmode-thin: var(--liang-border) !important;\n --dsw-alias-border-l2: var(--liang-border) !important;\n --dsw-alias-border-l3: var(--liang-border) !important;\n --dsw-alias-button-primary-fill: var(--liang-accent) !important;\n --dsw-alias-button-primary-hover: var(--liang-accent-hover) !important;\n --dsw-alias-button-info-fill: var(--liang-accent) !important;\n --dsw-alias-button-info-hover: var(--liang-accent-hover) !important;\n --dsw-alias-state-business-primary: var(--liang-accent) !important;\n --dsw-alias-interactive-bg-hover: var(--liang-hover) !important;\n --dsw-alias-interactive-bg-active: var(--liang-hover) !important;\n --dsw-alias-button-elevated-fill: var(--liang-layer-1) !important;\n --dsw-alias-button-floating-fill: var(--liang-layer-2) !important;\n --dsw-alias-button-floating-hover: var(--liang-layer-3) !important;\n --dsw-alias-interactive-bg-hover-solid: var(--liang-layer-2) !important;\n --dsw-specific-bubble: var(--liang-layer-2) !important;\n --dsw-specific-input-major: var(--liang-layer-1) !important;\n --dsw-specific-menu: var(--liang-layer-3) !important;\n --dsw-specific-selector: var(--liang-layer-2) !important;\n --dsw-alias-markdown-citation: var(--liang-layer-2) !important;\n --dsw-alias-markdown-code-block-banner: var(--liang-layer-1) !important;\n --dsw-alias-markdown-code-block: var(--liang-layer-1) !important;\n --dsw-alias-markdown-code-segment-selected: var(--liang-layer-2) !important;\n --dsw-alias-markdown-code-segment-unselected: var(--liang-layer-1) !important;\n --dsw-alias-markdown-inline-code: var(--liang-layer-2) !important;\n --dsw-alias-markdown-placeholder: var(--liang-layer-1) !important;\n --dsw-alias-markdown-tag: var(--liang-layer-2) !important;\n background: var(--liang-page) !important;\n}\n\nbody[data-liang-skin=\"on\"]:is(\n [data-liang-stage=\"0\"],\n [data-liang-stage=\"1\"],\n [data-liang-stage=\"2\"],\n [data-liang-stage=\"3\"]\n) {\n --dsw-alias-brand-primary-new-colorprimary-new-color: rgb(65 118 230) !important;\n --dsw-alias-brand-primary: rgb(15 17 21) !important;\n --dsw-alias-brand-text: rgb(15 17 21) !important;\n --dsw-alias-button-primary-fill: rgb(15 17 21) !important;\n --dsw-alias-button-primary-hover: rgb(53 54 56) !important;\n --dsw-alias-button-info-fill: rgb(65 118 230) !important;\n --dsw-alias-button-info-hover: rgb(103 158 254) !important;\n --dsw-alias-state-business-primary: rgb(65 118 230) !important;\n --dsw-alias-label-primary-inverted: rgb(249 250 251) !important;\n --dsw-alias-button-elevated-fill: rgb(255 255 255) !important;\n --dsw-alias-button-floating-fill: rgb(255 255 255) !important;\n --dsw-alias-button-floating-hover: rgb(241 243 245) !important;\n --dsw-alias-interactive-bg-hover-solid: rgb(241 243 245) !important;\n --dsw-specific-bubble: rgb(237 243 254) !important;\n --dsw-specific-input-major: rgb(255 255 255) !important;\n --dsw-specific-menu: rgb(255 255 255) !important;\n --dsw-specific-selector: rgb(245 246 247) !important;\n}\n\nbody[data-liang-skin=\"on\"][data-liang-stage=\"5\"] {\n --dsw-alias-brand-primary-new-colorprimary-new-color: #c19a49 !important;\n --dsw-alias-brand-primary: #c19a49 !important;\n --dsw-alias-brand-text: #d5b56e !important;\n --dsw-alias-button-info-fill: #c19a49 !important;\n --dsw-alias-button-info-hover: #d5b56e !important;\n --dsw-alias-state-business-primary: #c19a49 !important;\n --dsw-alias-bg-module-platform: var(--liang-layer-3) !important;\n --dsw-specific-sidebar-nav-item-active: var(--liang-layer-3) !important;\n --dsw-specific-sidebar-nav-item-hover: var(--liang-hover) !important;\n}\n\n/* The low-intensity skin is light by default, but it must not turn a dark\n Harness document into a light surface. Keep the skin's portrait progression\n while switching the shared UI layers back to a readable charcoal palette. */\nbody[data-liang-skin=\"on\"][data-ds-dark-theme]:is(\n [data-liang-stage=\"0\"],\n [data-liang-stage=\"1\"],\n [data-liang-stage=\"2\"],\n [data-liang-stage=\"3\"]\n) {\n --liang-page: rgb(17 17 17) !important;\n --liang-bg-base: rgb(17 17 17 / 42%) !important;\n --liang-layer-1: rgb(30 27 25 / 94%) !important;\n --liang-layer-2: rgb(41 35 30 / 96%) !important;\n --liang-layer-3: rgb(41 35 30 / 99%) !important;\n --liang-sidebar: rgb(23 20 18 / 96%) !important;\n --liang-ink: rgb(244 241 232) !important;\n --liang-secondary: rgb(184 180 169) !important;\n --liang-tertiary: rgb(137 134 126) !important;\n --liang-border: rgb(244 241 232 / 15%) !important;\n --liang-hover: rgb(244 241 232 / 9%) !important;\n --dsw-alias-brand-primary: var(--liang-accent) !important;\n --dsw-alias-brand-text: var(--liang-accent) !important;\n --dsw-alias-button-primary-fill: var(--liang-accent) !important;\n --dsw-alias-button-primary-hover: var(--liang-accent-hover) !important;\n --dsw-alias-button-info-fill: var(--liang-accent) !important;\n --dsw-alias-button-info-hover: var(--liang-accent-hover) !important;\n --dsw-alias-state-business-primary: var(--liang-accent) !important;\n --dsw-alias-button-elevated-fill: var(--liang-layer-1) !important;\n --dsw-alias-button-floating-fill: var(--liang-layer-2) !important;\n --dsw-alias-button-floating-hover: var(--liang-layer-3) !important;\n --dsw-alias-interactive-bg-hover-solid: var(--liang-layer-2) !important;\n --dsw-specific-bubble: var(--liang-layer-2) !important;\n --dsw-specific-input-major: var(--liang-layer-1) !important;\n --dsw-specific-menu: var(--liang-layer-3) !important;\n --dsw-specific-selector: var(--liang-layer-2) !important;\n background: var(--liang-page) !important;\n}\n\nbody[data-liang-skin=\"on\"][data-ds-dark-theme]:is(\n [data-liang-stage=\"0\"],\n [data-liang-stage=\"1\"],\n [data-liang-stage=\"2\"],\n [data-liang-stage=\"3\"]\n) .liang-skin-backdrop {\n background: var(--liang-page) !important;\n}\n\nbody[data-liang-skin=\"on\"][data-ds-dark-theme]:is(\n [data-liang-stage=\"0\"],\n [data-liang-stage=\"1\"],\n [data-liang-stage=\"2\"],\n [data-liang-stage=\"3\"]\n) .liang-skin-backdrop::after {\n background: linear-gradient(90deg, var(--liang-page) 0 28%, transparent 57% 100%);\n}\n\n/* The host's running-turn label uses a transparent blue shimmer. In the\n custom dark skin it is a semantic status accent, so keep both the label\n and its elapsed clock gold without changing the original light theme. */\nbody[data-liang-skin=\"on\"][data-liang-stage=\"5\"] [class*=\"_turnStatus\"] {\n color: #c19a49 !important;\n background: #c19a49 !important;\n background-clip: initial !important;\n -webkit-background-clip: initial !important;\n -webkit-text-fill-color: #c19a49 !important;\n animation: none !important;\n}\n\nbody[data-liang-skin=\"on\"][data-liang-stage=\"5\"] [class*=\"_turnStatusClock\"] {\n color: #c19a49 !important;\n -webkit-text-fill-color: #c19a49 !important;\n}\n\n/* Preserve the wordmark badge contrast in the low-intensity shell. */\nbody[data-liang-skin=\"on\"]:is(\n [data-liang-stage=\"0\"],\n [data-liang-stage=\"1\"],\n [data-liang-stage=\"2\"],\n [data-liang-stage=\"3\"]\n) button[aria-label=\"\u65B0\u5EFA\u4F1A\u8BDD\"] svg[viewBox=\"0 0 182 24\"] > rect[width=\"52\"] {\n fill: rgb(15 17 21) !important;\n}\n\nbody[data-liang-skin=\"on\"]:is(\n [data-liang-stage=\"0\"],\n [data-liang-stage=\"1\"],\n [data-liang-stage=\"2\"],\n [data-liang-stage=\"3\"]\n) button[aria-label=\"\u65B0\u5EFA\u4F1A\u8BDD\"] svg[viewBox=\"0 0 182 24\"] > g[clip-path*=\"badge\"] path {\n fill: rgb(249 250 251) !important;\n}\n\nbody[data-liang-skin=\"on\"][data-liang-stage=\"5\"] button[aria-label=\"\u65B0\u5EFA\u4F1A\u8BDD\"] svg[viewBox=\"0 0 182 24\"] > rect[width=\"52\"] {\n fill: #c19a49 !important;\n}\n\nbody[data-liang-skin=\"on\"][data-liang-stage=\"5\"] button[aria-label=\"\u65B0\u5EFA\u4F1A\u8BDD\"] svg[viewBox=\"0 0 182 24\"] > g[clip-path*=\"badge\"] path {\n fill: #171816 !important;\n}\n\nbody[data-liang-skin=\"on\"][data-liang-stage=\"5\"] [aria-label^=\"\u9009\u62E9\u6A21\u578B\"] > span:nth-of-type(2) {\n color: #d5b56e !important;\n}\n\nbody[data-liang-skin=\"on\"][data-liang-stage=\"5\"] [class*=\"heroGlow\"] ellipse {\n fill: #c19a49 !important;\n fill-opacity: 0.16 !important;\n}\n\nbody[data-liang-skin=\"on\"][data-liang-stage=\"5\"] span[class*=\"_previewBadge\"] {\n color: #171816 !important;\n background: #c19a49 !important;\n}\n\nbody[data-liang-skin=\"on\"][data-liang-stage=\"5\"] button[aria-label=\"\u53D1\u9001\u6D88\u606F\"] {\n color: #171816 !important;\n}\n\nbody[data-liang-skin=\"on\"][data-liang-stage=\"5\"] button[aria-label=\"\u53D1\u9001\u6D88\u606F\"]:disabled {\n opacity: 0.62;\n}\n\nbody[data-liang-skin=\"on\"]:is(\n [data-liang-stage=\"0\"],\n [data-liang-stage=\"1\"],\n [data-liang-stage=\"2\"],\n [data-liang-stage=\"3\"]\n) button[aria-label=\"\u53D1\u9001\u6D88\u606F\"] {\n color: #fff !important;\n}\n\nbody[data-liang-skin=\"on\"]:is(\n [data-liang-stage=\"0\"],\n [data-liang-stage=\"1\"],\n [data-liang-stage=\"2\"],\n [data-liang-stage=\"3\"]\n) button[aria-label=\"\u53D1\u9001\u6D88\u606F\"]:disabled {\n color: rgb(255 255 255 / 92%) !important;\n background: rgb(65 118 230 / 42%) !important;\n opacity: 1;\n}\n\nbody[data-liang-skin=\"on\"] > #root {\n position: relative;\n z-index: 1;\n background: transparent !important;\n}\n\nbody[data-liang-skin=\"on\"] button,\nbody[data-liang-skin=\"on\"] input,\nbody[data-liang-skin=\"on\"] textarea {\n transition: color 160ms linear, background-color 160ms linear, border-color 160ms linear;\n}\n\n/* The composer card has a native theme-mode fill, so keep its surface and\n readable ink aligned with the active Liang palette. */\nbody[data-liang-skin=\"on\"]:is(\n [data-liang-stage=\"0\"],\n [data-liang-stage=\"1\"],\n [data-liang-stage=\"2\"],\n [data-liang-stage=\"3\"]\n) [data-composer-card=\"true\"] {\n border-color: var(--liang-border) !important;\n color: var(--liang-ink) !important;\n background: var(--liang-layer-1) !important;\n box-shadow: 0 8px 28px rgb(20 22 20 / 8%);\n}\n\nbody[data-liang-skin=\"on\"]:is(\n [data-liang-stage=\"0\"],\n [data-liang-stage=\"1\"],\n [data-liang-stage=\"2\"],\n [data-liang-stage=\"3\"]\n) [data-composer-card=\"true\"] :is(textarea, button, [data-input-mirror=\"true\"]) {\n color: var(--liang-ink) !important;\n caret-color: var(--liang-accent) !important;\n}\n\nbody[data-liang-skin=\"on\"]:is(\n [data-liang-stage=\"0\"],\n [data-liang-stage=\"1\"],\n [data-liang-stage=\"2\"],\n [data-liang-stage=\"3\"]\n) [data-composer-card=\"true\"] textarea::placeholder {\n color: var(--liang-tertiary) !important;\n opacity: 1;\n}\n\n.liang-effort-control {\n --liang-control-accent: var(--dsw-alias-brand-primary-new-colorprimary-new-color, #4176e6);\n --liang-control-rail: var(--dsw-alias-border-l3, rgb(0 0 0 / 16%));\n position: relative;\n display: flex;\n width: 124px;\n height: 28px;\n align-items: center;\n margin: 0 3px;\n overflow: visible;\n}\n\nbody[data-liang-skin=\"on\"] .liang-effort-control {\n --liang-control-accent: var(--liang-secondary);\n --liang-control-rail: color-mix(in srgb, var(--liang-secondary) 28%, transparent);\n}\n\n.liang-effort-control__ticks {\n position: absolute;\n z-index: 0;\n inset: 0 10px;\n pointer-events: none;\n}\n\n.liang-effort-control__ticks::before {\n position: absolute;\n top: 50%;\n right: 0;\n left: 0;\n height: 1px;\n content: \"\";\n background: var(--liang-control-rail);\n transform: translateY(-50%);\n}\n\n.liang-effort-control__tooltip {\n position: absolute;\n z-index: 4;\n bottom: calc(100% + 7px);\n left: calc(10px + (100% - 20px) * var(--liang-slider-ratio));\n min-width: max-content;\n padding: 5px 8px;\n border: 1px solid var(--liang-border, rgb(0 0 0 / 12%));\n border-radius: 7px;\n color: var(--liang-ink, #171816);\n background: var(--liang-layer-1, #fff);\n box-shadow: 0 5px 16px rgb(0 0 0 / 16%);\n font-size: 11px;\n font-weight: 600;\n line-height: 16px;\n letter-spacing: 0.01em;\n pointer-events: none;\n transform: translateX(-50%);\n white-space: nowrap;\n}\n\n.liang-effort-control__tooltip::after {\n position: absolute;\n top: 100%;\n left: 50%;\n width: 7px;\n height: 7px;\n content: \"\";\n background: inherit;\n transform: translate(-50%, -4px) rotate(45deg);\n}\n\n.liang-effort-control__tick {\n position: absolute;\n top: 50%;\n width: 1px;\n height: 7px;\n background: var(--liang-control-accent);\n opacity: 0.42;\n transform: translate(-50%, -50%);\n}\n\n.liang-effort-control__range {\n position: relative;\n z-index: 1;\n width: calc(100% - 7px);\n height: 28px;\n margin: 0 3.5px;\n cursor: ew-resize;\n appearance: none;\n background: transparent;\n touch-action: pan-y;\n}\n\n.liang-effort-control__range:disabled {\n cursor: progress;\n opacity: 0.58;\n}\n\n.liang-effort-control__range::-webkit-slider-runnable-track {\n height: 1px;\n border-radius: 1px;\n background: transparent;\n}\n\n.liang-effort-control__range::-webkit-slider-thumb {\n width: 13px;\n height: 13px;\n margin-top: -6px;\n border: 1.5px solid color-mix(in srgb, var(--liang-control-accent) 72%, transparent);\n border-radius: 50%;\n appearance: none;\n background: radial-gradient(circle, var(--liang-control-accent) 0 2px, color-mix(in srgb, var(--liang-control-accent) 22%, var(--dsw-alias-bg-layer-1, #fff)) 2.5px);\n box-shadow: 0 1px 4px rgb(0 0 0 / 14%);\n}\n\nbody[data-liang-skin=\"on\"] .liang-effort-control__range::-webkit-slider-thumb {\n width: 13px;\n height: 13px;\n margin-top: -6px;\n border-color: color-mix(in srgb, var(--liang-control-accent) 72%, transparent);\n background: radial-gradient(circle, var(--liang-control-accent) 0 2px, color-mix(in srgb, var(--liang-control-accent) 22%, var(--liang-layer-1)) 2.5px);\n}\n\n.liang-effort-control__range::-moz-range-track {\n height: 1px;\n background: transparent;\n}\n\n.liang-effort-control__range::-moz-range-progress {\n height: 1px;\n background: transparent;\n}\n\n.liang-effort-control__range::-moz-range-thumb {\n width: 11px;\n height: 11px;\n border: 1.5px solid color-mix(in srgb, var(--liang-control-accent) 72%, transparent);\n border-radius: 50%;\n background: color-mix(in srgb, var(--liang-control-accent) 24%, var(--dsw-alias-bg-layer-1, #fff));\n}\n\n.liang-effort-control__range:focus-visible {\n outline: none;\n}\n\n.liang-effort-control[data-state=\"error\"] {\n --liang-control-accent: var(--dsw-alias-state-error-primary, #e43c3c);\n}\n\n.liang-settings-row {\n display: flex;\n min-height: 82px;\n align-items: center;\n justify-content: space-between;\n gap: 24px;\n padding: 16px 0;\n border-bottom: 1px solid var(--dsw-alias-border-l1, rgb(0 0 0 / 6%));\n color: var(--dsw-alias-label-primary);\n}\n\n.liang-settings-row__title {\n flex: 0 0 auto;\n font-size: 14px;\n font-weight: 500;\n}\n\n.liang-settings-row__choices {\n display: flex;\n gap: 8px;\n}\n\n.liang-settings-row__choice {\n min-width: 76px;\n height: 40px;\n padding: 0 14px;\n border: 1px solid var(--dsw-alias-border-l2, rgb(0 0 0 / 10%));\n border-radius: 10px;\n color: var(--dsw-alias-label-secondary);\n background: var(--dsw-alias-bg-layer-1);\n cursor: pointer;\n}\n\n.liang-settings-row__choice:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n.liang-settings-row__choice[aria-pressed=\"true\"] {\n border-color: var(--dsw-alias-label-primary);\n color: var(--dsw-alias-label-primary);\n box-shadow: inset 0 0 0 1px var(--dsw-alias-label-primary);\n}\n\n@media (max-width: 760px) {\n .liang-effort-control {\n width: 92px;\n }\n\n .liang-skin-backdrop video,\n .liang-skin-backdrop img {\n right: -18vw;\n width: 92vw;\n opacity: calc(var(--liang-portrait-opacity, 0.45) * 0.72);\n }\n\n .liang-settings-row {\n align-items: flex-start;\n flex-direction: column;\n gap: 12px;\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .liang-skin-backdrop,\n .liang-skin-backdrop video,\n .liang-skin-backdrop img,\n body[data-liang-skin=\"on\"] button,\n body[data-liang-skin=\"on\"] input,\n body[data-liang-skin=\"on\"] textarea {\n transition: none;\n }\n}\n", "export const PREVIEW_MAX_FRAME = 240;\nexport const MAX_LEVEL = 30;\n\nconst LIANG_RANKS = [\"\u5C0F\u96BE\u6881\", \"\u7262\u6881\", \"\u6881\u5B50\", \"\u6881\u5723\", \"\u6881\u795E\", \"\u6881\u7956\"] as const;\n\nexport interface EffortLike {\n id: string;\n name: string;\n description?: string;\n}\n\nexport interface Palette {\n level: number;\n stage: number;\n strength: number;\n page: string;\n base: string;\n layer1: string;\n layer2: string;\n layer3: string;\n sidebar: string;\n ink: string;\n secondary: string;\n tertiary: string;\n border: string;\n accent: string;\n accentHover: string;\n hover: string;\n portraitOpacity: string;\n}\n\ntype Rgb = readonly [number, number, number];\n\ninterface PaletteStop {\n at: number;\n page: Rgb;\n surface: Rgb;\n surface2: Rgb;\n ink: Rgb;\n secondary: Rgb;\n accent: Rgb;\n portraitOpacity: number;\n}\n\n// These are the original calibrator's six stage anchors: pale neutral at the\n// low end, progressively smoked surfaces, then charcoal and antique gold.\nconst STOPS: readonly PaletteStop[] = [\n { at: 0, page: [232, 233, 229], surface: [248, 248, 245], surface2: [238, 239, 235], ink: [23, 24, 22], secondary: [112, 116, 111], accent: [181, 43, 36], portraitOpacity: 0.92 },\n { at: 6, page: [211, 211, 206], surface: [239, 239, 234], surface2: [224, 224, 218], ink: [26, 26, 24], secondary: [101, 101, 96], accent: [181, 43, 36], portraitOpacity: 0.93 },\n { at: 12, page: [171, 168, 162], surface: [211, 208, 201], surface2: [190, 186, 179], ink: [27, 26, 24], secondary: [83, 79, 74], accent: [166, 54, 42], portraitOpacity: 0.94 },\n { at: 18, page: [117, 112, 106], surface: [154, 148, 140], surface2: [128, 122, 115], ink: [24, 22, 20], secondary: [65, 61, 56], accent: [154, 56, 42], portraitOpacity: 0.94 },\n { at: 24, page: [43, 39, 37], surface: [48, 43, 40], surface2: [58, 51, 46], ink: [244, 241, 232], secondary: [184, 180, 169], accent: [181, 92, 54], portraitOpacity: 0.94 },\n { at: 30, page: [17, 17, 17], surface: [30, 27, 25], surface2: [41, 35, 30], ink: [244, 241, 232], secondary: [184, 180, 169], accent: [193, 154, 73], portraitOpacity: 0.94 },\n];\n\nexport function clampFrame(value: number): number {\n if (!Number.isFinite(value)) return 0;\n return Math.min(PREVIEW_MAX_FRAME, Math.max(0, Math.round(value)));\n}\n\nexport function frameForEffort(index: number, count: number): number {\n if (count <= 1 || !Number.isFinite(index)) return 0;\n const safe = Math.min(count - 1, Math.max(0, Math.round(index)));\n return Math.round((safe / (count - 1)) * PREVIEW_MAX_FRAME);\n}\n\nexport function nearestEffortIndex(frame: number, efforts: readonly EffortLike[]): number {\n if (efforts.length === 0) return -1;\n const safe = clampFrame(frame);\n let best = 0;\n let distance = Math.abs(safe - frameForEffort(0, efforts.length));\n for (let index = 1; index < efforts.length; index += 1) {\n const next = Math.abs(safe - frameForEffort(index, efforts.length));\n if (next < distance) {\n best = index;\n distance = next;\n }\n }\n return best;\n}\n\nexport function selectedEffortIndex(\n efforts: readonly EffortLike[],\n selectedId?: string,\n defaultId?: string,\n): number {\n const id = selectedId ?? defaultId;\n return id === undefined ? -1 : efforts.findIndex((effort) => effort.id === id);\n}\n\nexport function portraitBlendForLevel(level: number, anchors: readonly number[]) {\n if (anchors.length === 0) return { lowerIndex: -1, upperIndex: -1, mix: 0 };\n const safeLevel = Number.isFinite(level)\n ? Math.min(anchors[anchors.length - 1], Math.max(anchors[0], level))\n : anchors[0];\n let upperIndex = anchors.findIndex((anchor) => anchor >= safeLevel);\n if (upperIndex < 0) upperIndex = anchors.length - 1;\n const lowerIndex = Math.max(0, upperIndex - (anchors[upperIndex] > safeLevel ? 1 : 0));\n const span = anchors[upperIndex] - anchors[lowerIndex];\n return {\n lowerIndex,\n upperIndex,\n mix: span === 0 ? 0 : (safeLevel - anchors[lowerIndex]) / span,\n };\n}\n\nexport function liangRankForFrame(rawFrame: number): string {\n const level = (clampFrame(rawFrame) / PREVIEW_MAX_FRAME) * MAX_LEVEL;\n const index = level >= MAX_LEVEL ? LIANG_RANKS.length - 1 : Math.floor(level / 6);\n return LIANG_RANKS[Math.min(LIANG_RANKS.length - 1, Math.max(0, index))];\n}\n\nexport function indicatorLabel(rawFrame: number, efforts: readonly EffortLike[]): string {\n const effort = efforts[nearestEffortIndex(rawFrame, efforts)];\n return effort === undefined\n ? liangRankForFrame(rawFrame)\n : `${liangRankForFrame(rawFrame)} \u00B7 ${effort.name}`;\n}\n\nfunction lerp(a: number, b: number, amount: number): number {\n return a + (b - a) * amount;\n}\n\nfunction mix(a: Rgb, b: Rgb, amount: number): Rgb {\n return [\n Math.round(lerp(a[0], b[0], amount)),\n Math.round(lerp(a[1], b[1], amount)),\n Math.round(lerp(a[2], b[2], amount)),\n ];\n}\n\nfunction rgb(value: Rgb, alpha = 1): string {\n return alpha === 1\n ? `rgb(${value[0]} ${value[1]} ${value[2]})`\n : `rgb(${value[0]} ${value[1]} ${value[2]} / ${alpha})`;\n}\n\nexport function paletteForFrame(rawFrame: number): Palette {\n const frame = clampFrame(rawFrame);\n const level = (frame / PREVIEW_MAX_FRAME) * MAX_LEVEL;\n const portraitStage = Math.min(5, Math.floor(level / 6));\n const portraitFrom = STOPS[portraitStage];\n const portraitTo = STOPS[Math.min(5, portraitStage + 1)];\n const portraitAmount = portraitFrom === portraitTo\n ? 0\n : (level - portraitFrom.at) / (portraitTo.at - portraitFrom.at);\n\n // The UI itself is intentionally binary: levels 0\u201323 keep the native light\n // shell; entering the original \u6881\u795E/\u6881\u7956 region at level 24 switches black/gold.\n const dark = level >= 24;\n const stage = dark ? 5 : 0;\n const ui = dark ? STOPS[5] : STOPS[0];\n const page = ui.page;\n const surface = ui.surface;\n const surface2 = ui.surface2;\n const sidebar = mix(page, surface2, 0.25);\n const ink = ui.ink;\n const secondary = ui.secondary;\n // Keep Harness' native blue in the light shell. The original calibrator's\n // antique gold only becomes the product accent once the dark region begins.\n const accent: Rgb = dark ? [193, 154, 73] : [65, 118, 230];\n const accentHover = mix(accent, ink, 0.13);\n\n return {\n level,\n stage,\n strength: level / MAX_LEVEL,\n page: rgb(page),\n // Keep the shell readable while allowing the right-side portrait to remain\n // visibly present. Dense controls use the opaque layer tokens below.\n base: rgb(page, dark ? 0.42 : 0.28),\n layer1: rgb(surface, 0.94),\n layer2: rgb(surface2, 0.96),\n layer3: rgb(surface2, 0.99),\n sidebar: rgb(sidebar, 0.96),\n ink: rgb(ink),\n secondary: rgb(secondary),\n tertiary: rgb(mix(secondary, page, 0.28)),\n border: rgb(ink, dark ? 0.15 : 0.12),\n accent: rgb(accent),\n accentHover: rgb(accentHover),\n hover: rgb(ink, dark ? 0.09 : 0.07),\n portraitOpacity: String(lerp(\n portraitFrom.portraitOpacity,\n portraitTo.portraitOpacity,\n portraitAmount,\n )),\n };\n}\n"], + "mappings": ";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAMO;;;ACNP;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA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", "names": ["mix"] } diff --git a/package.json b/package.json index 35f129f..e34c241 100644 --- a/package.json +++ b/package.json @@ -65,6 +65,7 @@ "@deepseek-ai/dsh-client-ui-conversation", "@deepseek-ai/dsh-client-ui-model-selection", "@deepseek-ai/dsh-client-ui-settings", + "@deepseek-ai/dsh-client-ui-theme", "@deepseek-ai/dsh-client-ui-settings-general", "@deepseek-ai/dsh-client-locale", "@deepseek-ai/dsh-api-remotes" diff --git a/src/client/index.tsx b/src/client/index.tsx index 0f36cb7..935ef91 100644 --- a/src/client/index.tsx +++ b/src/client/index.tsx @@ -65,6 +65,13 @@ interface PreferenceStore { dispose(): void; } +type NativeThemeId = "light" | "dark"; + +interface ThemeService { + getTheme(): { preference: string }; + setTheme(id: NativeThemeId): void; +} + interface ModelSelection { provider: string; model: string; @@ -126,6 +133,7 @@ const cssVariables = [ class SkinPresenter { private readonly scope: PreferenceStore; + private readonly theme: ThemeService; private readonly root: HTMLDivElement; private readonly video: HTMLVideoElement; private readonly poster: HTMLImageElement; @@ -138,8 +146,9 @@ class SkinPresenter { private disposed = false; private unsubscribe: () => void; - constructor(scope: PreferenceStore) { + constructor(scope: PreferenceStore, theme: ThemeService) { this.scope = scope; + this.theme = theme; this.root = document.createElement("div"); this.root.className = "liang-skin-backdrop"; this.root.dataset.plugin = PACKAGE_ID; @@ -242,6 +251,7 @@ class SkinPresenter { private applyFrame() { const palette = paletteForFrame(this.frame); const body = document.body; + this.syncNativeTheme(palette.stage === 5 ? "dark" : "light"); body.dataset.liangStage = String(palette.stage); body.style.setProperty("--liang-strength", String(palette.strength)); body.style.setProperty("--liang-page", palette.page); @@ -262,6 +272,11 @@ class SkinPresenter { this.seek(this.frame); } + syncNativeTheme(theme: NativeThemeId = paletteForFrame(this.frame).stage === 5 ? "dark" : "light") { + if (!this.enabled || this.theme.getTheme().preference === theme) return; + this.theme.setTheme(theme); + } + private updatePortrait(level: number) { const { lowerIndex, upperIndex, mix } = portraitBlendForLevel( level, @@ -515,6 +530,7 @@ export const inject = [ "sessions", "modelDirectories", "locale", + "theme", ]; function createPreferenceStore(): PreferenceStore { @@ -558,8 +574,13 @@ export function apply(ctx: ClientContext) { const scope = createPreferenceStore(); ctx.effect(() => () => scope.dispose(), "liang-intensity-skin: appearance preference"); - const presenter = new SkinPresenter(scope); + const theme = ctx.get("theme") as ThemeService; + const presenter = new SkinPresenter(scope, theme); ctx.effect(() => () => presenter.dispose(), "liang-intensity-skin: backdrop presenter"); + ctx.effect( + () => ctx.on("theme/change", () => presenter.syncNativeTheme()), + "liang-intensity-skin: native theme synchronization", + ); ctx.effect(() => ctx.locale.register(LOCALE_NAMESPACE, { zh: { diff --git a/src/client/skin.css b/src/client/skin.css index 0838b41..341df40 100644 --- a/src/client/skin.css +++ b/src/client/skin.css @@ -100,6 +100,14 @@ body[data-liang-skin="on"] { --dsw-specific-input-major: var(--liang-layer-1) !important; --dsw-specific-menu: var(--liang-layer-3) !important; --dsw-specific-selector: var(--liang-layer-2) !important; + --dsw-alias-markdown-citation: var(--liang-layer-2) !important; + --dsw-alias-markdown-code-block-banner: var(--liang-layer-1) !important; + --dsw-alias-markdown-code-block: var(--liang-layer-1) !important; + --dsw-alias-markdown-code-segment-selected: var(--liang-layer-2) !important; + --dsw-alias-markdown-code-segment-unselected: var(--liang-layer-1) !important; + --dsw-alias-markdown-inline-code: var(--liang-layer-2) !important; + --dsw-alias-markdown-placeholder: var(--liang-layer-1) !important; + --dsw-alias-markdown-tag: var(--liang-layer-2) !important; background: var(--liang-page) !important; } @@ -135,10 +143,85 @@ body[data-liang-skin="on"][data-liang-stage="5"] { --dsw-alias-button-info-fill: #c19a49 !important; --dsw-alias-button-info-hover: #d5b56e !important; --dsw-alias-state-business-primary: #c19a49 !important; + --dsw-alias-bg-module-platform: var(--liang-layer-3) !important; + --dsw-specific-sidebar-nav-item-active: var(--liang-layer-3) !important; + --dsw-specific-sidebar-nav-item-hover: var(--liang-hover) !important; } -/* Preserve the wordmark badge contrast even when the underlying Harness - preference is dark while our low-intensity shell is light. */ +/* The low-intensity skin is light by default, but it must not turn a dark + Harness document into a light surface. Keep the skin's portrait progression + while switching the shared UI layers back to a readable charcoal palette. */ +body[data-liang-skin="on"][data-ds-dark-theme]:is( + [data-liang-stage="0"], + [data-liang-stage="1"], + [data-liang-stage="2"], + [data-liang-stage="3"] +) { + --liang-page: rgb(17 17 17) !important; + --liang-bg-base: rgb(17 17 17 / 42%) !important; + --liang-layer-1: rgb(30 27 25 / 94%) !important; + --liang-layer-2: rgb(41 35 30 / 96%) !important; + --liang-layer-3: rgb(41 35 30 / 99%) !important; + --liang-sidebar: rgb(23 20 18 / 96%) !important; + --liang-ink: rgb(244 241 232) !important; + --liang-secondary: rgb(184 180 169) !important; + --liang-tertiary: rgb(137 134 126) !important; + --liang-border: rgb(244 241 232 / 15%) !important; + --liang-hover: rgb(244 241 232 / 9%) !important; + --dsw-alias-brand-primary: var(--liang-accent) !important; + --dsw-alias-brand-text: var(--liang-accent) !important; + --dsw-alias-button-primary-fill: var(--liang-accent) !important; + --dsw-alias-button-primary-hover: var(--liang-accent-hover) !important; + --dsw-alias-button-info-fill: var(--liang-accent) !important; + --dsw-alias-button-info-hover: var(--liang-accent-hover) !important; + --dsw-alias-state-business-primary: var(--liang-accent) !important; + --dsw-alias-button-elevated-fill: var(--liang-layer-1) !important; + --dsw-alias-button-floating-fill: var(--liang-layer-2) !important; + --dsw-alias-button-floating-hover: var(--liang-layer-3) !important; + --dsw-alias-interactive-bg-hover-solid: var(--liang-layer-2) !important; + --dsw-specific-bubble: var(--liang-layer-2) !important; + --dsw-specific-input-major: var(--liang-layer-1) !important; + --dsw-specific-menu: var(--liang-layer-3) !important; + --dsw-specific-selector: var(--liang-layer-2) !important; + background: var(--liang-page) !important; +} + +body[data-liang-skin="on"][data-ds-dark-theme]:is( + [data-liang-stage="0"], + [data-liang-stage="1"], + [data-liang-stage="2"], + [data-liang-stage="3"] +) .liang-skin-backdrop { + background: var(--liang-page) !important; +} + +body[data-liang-skin="on"][data-ds-dark-theme]:is( + [data-liang-stage="0"], + [data-liang-stage="1"], + [data-liang-stage="2"], + [data-liang-stage="3"] +) .liang-skin-backdrop::after { + background: linear-gradient(90deg, var(--liang-page) 0 28%, transparent 57% 100%); +} + +/* The host's running-turn label uses a transparent blue shimmer. In the + custom dark skin it is a semantic status accent, so keep both the label + and its elapsed clock gold without changing the original light theme. */ +body[data-liang-skin="on"][data-liang-stage="5"] [class*="_turnStatus"] { + color: #c19a49 !important; + background: #c19a49 !important; + background-clip: initial !important; + -webkit-background-clip: initial !important; + -webkit-text-fill-color: #c19a49 !important; + animation: none !important; +} + +body[data-liang-skin="on"][data-liang-stage="5"] [class*="_turnStatusClock"] { + color: #c19a49 !important; + -webkit-text-fill-color: #c19a49 !important; +} + +/* Preserve the wordmark badge contrast in the low-intensity shell. */ body[data-liang-skin="on"]:is( [data-liang-stage="0"], [data-liang-stage="1"], @@ -219,9 +302,8 @@ body[data-liang-skin="on"] textarea { transition: color 160ms linear, background-color 160ms linear, border-color 160ms linear; } -/* Harness can itself be in dark mode while the low intensity stages are light. - The composer card has a native theme-mode fill, so explicitly bring only - those light stages back to the original light surface and readable ink. */ +/* The composer card has a native theme-mode fill, so keep its surface and + readable ink aligned with the active Liang palette. */ body[data-liang-skin="on"]:is( [data-liang-stage="0"], [data-liang-stage="1"],