@linxin666/dsh-client-ui-skin-center 0.3.19 → 0.3.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/contracts/semantic-attrs-v1.md +11 -3
- package/lib/client.js +97 -33
- package/lib/client.js.map +1 -1
- package/lib/index.js +22 -16
- package/package.json +11 -11
- package/skins/blue-fantasy/patches.css +369 -0
package/lib/index.js
CHANGED
|
@@ -717,6 +717,11 @@ const REVIEWED_SKIN_HOOKS = {
|
|
|
717
717
|
manifestSha256: "b22cc82145e1f90f4257af1411724e34a99513761290980fb5f8d25727809808",
|
|
718
718
|
hooksSha256: "21ac2ad4d4423acf31e3391bfba18ce2d9eec7b192f7a0ba47e8a0c843ff15a5"
|
|
719
719
|
},
|
|
720
|
+
"blueprint": {
|
|
721
|
+
entry: "hooks.mjs",
|
|
722
|
+
manifestSha256: "e36d9d53aae73c4693e36fc2e130bca2996cda6dcd8f80917627897774232a3e",
|
|
723
|
+
hooksSha256: "4f6c7db598e72469920d1dbafd5c20cec39f435f225220ffc860636523ed70bb"
|
|
724
|
+
},
|
|
720
725
|
"cyber-night": {
|
|
721
726
|
entry: "hooks.mjs",
|
|
722
727
|
manifestSha256: "38de22962a80602c22910324e7c5fec171342363760972b7421debeb628d8508",
|
|
@@ -744,8 +749,8 @@ const REVIEWED_SKIN_HOOKS = {
|
|
|
744
749
|
},
|
|
745
750
|
"maid-atelier": {
|
|
746
751
|
entry: "hooks.mjs",
|
|
747
|
-
manifestSha256: "
|
|
748
|
-
hooksSha256: "
|
|
752
|
+
manifestSha256: "7596a704bce65006381d27417d4c12bb09d7e5ede038a6f486cfa58e62314aa5",
|
|
753
|
+
hooksSha256: "c4668f9cee8192fe3c25e6a01b779bc9ec9ab1980061106e749551a7bafa4153"
|
|
749
754
|
},
|
|
750
755
|
"matrix": {
|
|
751
756
|
entry: "hooks.mjs",
|
|
@@ -805,7 +810,7 @@ const REVIEWED_SKIN_HOOKS = {
|
|
|
805
810
|
"xp": {
|
|
806
811
|
entry: "hooks.mjs",
|
|
807
812
|
manifestSha256: "8bceb95c45b400b67ceb80a7f063b6c2086c0e9f9907a7b72a592d33017623eb",
|
|
808
|
-
hooksSha256: "
|
|
813
|
+
hooksSha256: "1574d30f271f481a681feddc0608b04b0aec684e323fec0b00481f08450e4eb3"
|
|
809
814
|
}
|
|
810
815
|
};
|
|
811
816
|
//#endregion
|
|
@@ -5484,6 +5489,7 @@ function buildSceneManifestVia(access, token, projectOverride) {
|
|
|
5484
5489
|
const width = typeof projW === "number" && Number.isFinite(projW) && projW > 0 ? Math.floor(projW) : 3840;
|
|
5485
5490
|
const height = typeof projH === "number" && Number.isFinite(projH) && projH > 0 ? Math.floor(projH) : 2160;
|
|
5486
5491
|
const resourceBase = "/api/skin-center/we/scene-resource/" + token + "/";
|
|
5492
|
+
const resourceUrl = (pkgPath) => resourceBase + pkgPath.split("/").map(encodeURIComponent).join("/");
|
|
5487
5493
|
const manifest = {
|
|
5488
5494
|
width,
|
|
5489
5495
|
height,
|
|
@@ -5724,7 +5730,7 @@ function buildSceneManifestVia(access, token, projectOverride) {
|
|
|
5724
5730
|
uv2B64: m.uv2 ? Buffer$1.from(m.uv2.buffer, m.uv2.byteOffset, m.uv2.byteLength).toString("base64") : void 0,
|
|
5725
5731
|
indicesB64: Buffer$1.from(m.indices.buffer, m.indices.byteOffset, m.indices.byteLength).toString("base64"),
|
|
5726
5732
|
idx32: m.indices instanceof Uint32Array || void 0,
|
|
5727
|
-
texUrl: subTex ?
|
|
5733
|
+
texUrl: subTex ? resourceUrl(subTex) : void 0,
|
|
5728
5734
|
repeatBase: m.uv.some((value) => value < 0 || value > 1) || void 0,
|
|
5729
5735
|
materialPath: m.materialPath,
|
|
5730
5736
|
shader,
|
|
@@ -5733,8 +5739,8 @@ function buildSceneManifestVia(access, token, projectOverride) {
|
|
|
5733
5739
|
noDepthWrite,
|
|
5734
5740
|
tint,
|
|
5735
5741
|
tint2,
|
|
5736
|
-
texUrl2: texPath2 ?
|
|
5737
|
-
lightmapUrl: lightmapPath ?
|
|
5742
|
+
texUrl2: texPath2 ? resourceUrl(texPath2) : void 0,
|
|
5743
|
+
lightmapUrl: lightmapPath ? resourceUrl(lightmapPath) : void 0,
|
|
5738
5744
|
translucent,
|
|
5739
5745
|
gradFade,
|
|
5740
5746
|
userColors,
|
|
@@ -5796,7 +5802,7 @@ function buildSceneManifestVia(access, token, projectOverride) {
|
|
|
5796
5802
|
manifest.bgLayers.push({
|
|
5797
5803
|
name: typeof obj.name === "string" ? obj.name : "fullscreen",
|
|
5798
5804
|
shader: typeof pass0.shader === "string" ? pass0.shader : void 0,
|
|
5799
|
-
texUrl: texPath ?
|
|
5805
|
+
texUrl: texPath ? resourceUrl(texPath) : void 0,
|
|
5800
5806
|
userColors: Object.keys(userColors).length > 0 ? userColors : void 0,
|
|
5801
5807
|
userNums: Object.keys(userNums).length > 0 ? userNums : void 0
|
|
5802
5808
|
});
|
|
@@ -5819,7 +5825,7 @@ function buildSceneManifestVia(access, token, projectOverride) {
|
|
|
5819
5825
|
manifest.sprites = manifest.sprites ?? [];
|
|
5820
5826
|
manifest.sprites.push({
|
|
5821
5827
|
name: typeof obj.name === "string" ? obj.name : "sprite",
|
|
5822
|
-
texUrl: texPath ?
|
|
5828
|
+
texUrl: texPath ? resourceUrl(texPath) : void 0,
|
|
5823
5829
|
origin: parseVec3(obj.origin, [
|
|
5824
5830
|
0,
|
|
5825
5831
|
0,
|
|
@@ -5869,7 +5875,7 @@ function buildSceneManifestVia(access, token, projectOverride) {
|
|
|
5869
5875
|
manifest.particles3d = manifest.particles3d ?? [];
|
|
5870
5876
|
manifest.particles3d.push({
|
|
5871
5877
|
name: typeof obj.name === "string" ? obj.name : "particles",
|
|
5872
|
-
texUrl: texPath ?
|
|
5878
|
+
texUrl: texPath ? resourceUrl(texPath) : void 0,
|
|
5873
5879
|
origin: [
|
|
5874
5880
|
objOrigin[0] + emitterOrigin[0],
|
|
5875
5881
|
objOrigin[1] + emitterOrigin[1],
|
|
@@ -5914,9 +5920,9 @@ function buildSceneManifestVia(access, token, projectOverride) {
|
|
|
5914
5920
|
if (nameLower.includes("fireflies") || nameLower.includes("motes") || nameLower.includes("dust")) manifest.hasFireflies = true;
|
|
5915
5921
|
}
|
|
5916
5922
|
const meteorTexPath = allTex.find((p) => p.toLowerCase().includes("shootingstar") || p.toLowerCase().includes("meteor"));
|
|
5917
|
-
if (meteorTexPath) manifest.meteorTex =
|
|
5923
|
+
if (meteorTexPath) manifest.meteorTex = resourceUrl(meteorTexPath);
|
|
5918
5924
|
const sparkleTexPath = allTex.find((p) => p.toLowerCase().includes("sparkle") || p.toLowerCase().includes("halo") || p.toLowerCase().includes("star"));
|
|
5919
|
-
if (sparkleTexPath) manifest.sparkleTex =
|
|
5925
|
+
if (sparkleTexPath) manifest.sparkleTex = resourceUrl(sparkleTexPath);
|
|
5920
5926
|
const sceneObjects = scene.objects;
|
|
5921
5927
|
const resolveObjectTransform = (obj) => {
|
|
5922
5928
|
const chain = [obj];
|
|
@@ -5987,7 +5993,7 @@ function buildSceneManifestVia(access, token, projectOverride) {
|
|
|
5987
5993
|
if (reflTex) manifest.layers.push({
|
|
5988
5994
|
name: "Reflection",
|
|
5989
5995
|
isReflection: true,
|
|
5990
|
-
texUrl:
|
|
5996
|
+
texUrl: resourceUrl(reflTex),
|
|
5991
5997
|
x: width / 2,
|
|
5992
5998
|
y: height / 2,
|
|
5993
5999
|
w: width,
|
|
@@ -6095,7 +6101,7 @@ function buildSceneManifestVia(access, token, projectOverride) {
|
|
|
6095
6101
|
const alpha = typeof obj.alpha === "number" && Number.isFinite(obj.alpha) ? Math.min(1, Math.max(0, obj.alpha)) : 1;
|
|
6096
6102
|
let videoUrl;
|
|
6097
6103
|
try {
|
|
6098
|
-
if (parseTexInternal(file.bytes).isVideoMp4) videoUrl =
|
|
6104
|
+
if (parseTexInternal(file.bytes).isVideoMp4) videoUrl = resourceUrl(texPath);
|
|
6099
6105
|
} catch {}
|
|
6100
6106
|
let uvCrop;
|
|
6101
6107
|
if (decoded && typeof modelJson.width === "number" && typeof modelJson.height === "number") {
|
|
@@ -6118,7 +6124,7 @@ function buildSceneManifestVia(access, token, projectOverride) {
|
|
|
6118
6124
|
if (reflTex) manifest.layers.push({
|
|
6119
6125
|
name: "Reflection",
|
|
6120
6126
|
isReflection: true,
|
|
6121
|
-
texUrl:
|
|
6127
|
+
texUrl: resourceUrl(reflTex),
|
|
6122
6128
|
x: layerX,
|
|
6123
6129
|
y: layerY,
|
|
6124
6130
|
w: lw,
|
|
@@ -6128,7 +6134,7 @@ function buildSceneManifestVia(access, token, projectOverride) {
|
|
|
6128
6134
|
}
|
|
6129
6135
|
manifest.layers.push({
|
|
6130
6136
|
name: typeof obj.name === "string" ? obj.name : "layer",
|
|
6131
|
-
texUrl:
|
|
6137
|
+
texUrl: resourceUrl(texPath),
|
|
6132
6138
|
x: layerX,
|
|
6133
6139
|
y: layerY,
|
|
6134
6140
|
w: lw,
|
|
@@ -6137,7 +6143,7 @@ function buildSceneManifestVia(access, token, projectOverride) {
|
|
|
6137
6143
|
angle: objAngles[2] || 0,
|
|
6138
6144
|
uvCrop,
|
|
6139
6145
|
shader: layerShader,
|
|
6140
|
-
texUrls: texPaths.length > 1 ? texPaths.map((p) =>
|
|
6146
|
+
texUrls: texPaths.length > 1 ? texPaths.map((p) => resourceUrl(p)) : void 0,
|
|
6141
6147
|
userColors: layerUserColors,
|
|
6142
6148
|
nums: Object.keys(nums).length > 0 ? nums : void 0,
|
|
6143
6149
|
isGround,
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@linxin666/dsh-client-ui-skin-center",
|
|
3
3
|
"description": "In-GUI skin center for the dsh web GUI — the single skin package: skins are pure asset directories (built-in plus $DSH_HOME/skins) loaded and rendered only by the skin center; live try-on and one-click apply switch atomically in the page (no reload, no cordis.patch.yml rewrite, no restart)",
|
|
4
|
-
"version": "0.3.
|
|
4
|
+
"version": "0.3.21",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "lib/index.js",
|
|
7
7
|
"exports": {
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
},
|
|
13
13
|
"dsh": {
|
|
14
14
|
"engines": {
|
|
15
|
-
"dsh": ">=0.1.
|
|
15
|
+
"dsh": ">=0.1.5-rc.1"
|
|
16
16
|
},
|
|
17
17
|
"bundle": {
|
|
18
18
|
"patch": "./cordis.patch.yml"
|
|
@@ -39,15 +39,15 @@
|
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
41
|
"@deepseek-ai/cordis": "^4.0.2",
|
|
42
|
-
"@deepseek-ai/dsh-api-remotes": "^0.1.
|
|
43
|
-
"@deepseek-ai/dsh-api-workspace-controller": "^0.1.
|
|
44
|
-
"@deepseek-ai/dsh-client-locale": "^0.1.
|
|
45
|
-
"@deepseek-ai/dsh-client-ui-renderer": "^0.1.
|
|
46
|
-
"@deepseek-ai/dsh-client-ui-settings": "^0.1.
|
|
47
|
-
"@deepseek-ai/dsh-client-ui-slots": "^0.1.
|
|
48
|
-
"@deepseek-ai/dsh-client-ui-theme": "^0.1.
|
|
49
|
-
"@deepseek-ai/dsh-host-webserver": "^0.1.
|
|
50
|
-
"@deepseek-ai/dsh-settings": "^0.1.
|
|
42
|
+
"@deepseek-ai/dsh-api-remotes": "^0.1.5-rc.1",
|
|
43
|
+
"@deepseek-ai/dsh-api-workspace-controller": "^0.1.5-rc.1",
|
|
44
|
+
"@deepseek-ai/dsh-client-locale": "^0.1.5-rc.1",
|
|
45
|
+
"@deepseek-ai/dsh-client-ui-renderer": "^0.1.5-rc.1",
|
|
46
|
+
"@deepseek-ai/dsh-client-ui-settings": "^0.1.5-rc.1",
|
|
47
|
+
"@deepseek-ai/dsh-client-ui-slots": "^0.1.5-rc.1",
|
|
48
|
+
"@deepseek-ai/dsh-client-ui-theme": "^0.1.5-rc.1",
|
|
49
|
+
"@deepseek-ai/dsh-host-webserver": "^0.1.5-rc.1",
|
|
50
|
+
"@deepseek-ai/dsh-settings": "^0.1.5-rc.1",
|
|
51
51
|
"@types/jpeg-js": "^0.3.7",
|
|
52
52
|
"@types/node": "^22.20.0",
|
|
53
53
|
"@types/react": "^18.3.0",
|
|
@@ -260,3 +260,372 @@ body[data-ds-dark-theme] [data-phase="active"] [class*="composerSeat"]:before {
|
|
|
260
260
|
backdrop-filter: blur(6px);
|
|
261
261
|
background: linear-gradient(#0000 0, #101624d1 36px);
|
|
262
262
|
}
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* Blue Fantasy — text readability layer (L3).
|
|
266
|
+
*
|
|
267
|
+
* The whale illustration sits directly behind the conversation, so body text,
|
|
268
|
+
* tool output and the turn-tail controls lose contrast against the art. This
|
|
269
|
+
* layer paints a translucent frosted plate *behind the text only* (shrink to
|
|
270
|
+
* fit on block elements), leaving the illustration visible everywhere else.
|
|
271
|
+
*
|
|
272
|
+
* - Markdown blocks, lists, code and tables: one plate per block.
|
|
273
|
+
* - Disclosure rows (think / bash / context injection / system prompt):
|
|
274
|
+
* one plate per row, clipped to the content width.
|
|
275
|
+
* - The shimmering turn-status line keeps its gradient — the plate is painted
|
|
276
|
+
* by a ::before layer instead of the element's own background.
|
|
277
|
+
* - Expanded bodies (command output / reasoning / injected context) stay
|
|
278
|
+
* full-width so long output keeps its measure.
|
|
279
|
+
* - Turn-tail controls (copy / feedback / regenerate) sit on a plate so the
|
|
280
|
+
* icons stay legible where the art is busy.
|
|
281
|
+
* - Tool-call rows (bash / custom renderers) plate their outermost wrapper and
|
|
282
|
+
* reset the two layers nested inside it, so a row is one plate and not three.
|
|
283
|
+
* - The user's own message bubble keeps its accent colour and gains a
|
|
284
|
+
* translucent frosted body whose density rides the same slider.
|
|
285
|
+
*
|
|
286
|
+
* Both knobs come from the skin-center Background card and are read as optional
|
|
287
|
+
* variables with fallbacks: the blur is var(--dsh-skin-bubble-blur, 10px), and
|
|
288
|
+
* every text plate alpha rides var(--dsh-skin-bubble-alpha, .5). Each plate keeps
|
|
289
|
+
* its own ratio so the default 50% reproduces the values this layer first shipped
|
|
290
|
+
* with. The "Bubble opacity" slider therefore drives everything painted *behind
|
|
291
|
+
* text* -- markdown blocks, tool output, the turn-process row -- and nothing else.
|
|
292
|
+
* The window chrome (header, right sidebar) is deliberately not on that slider:
|
|
293
|
+
* it is frame, not bubble, and it keeps a fixed density.
|
|
294
|
+
*
|
|
295
|
+
* The light base is the left pane's measured rgb(242 245 250) (dark:
|
|
296
|
+
* rgb(16 22 42)) instead of pure white, so the plates sit in the same colour
|
|
297
|
+
* family as the panels around them.
|
|
298
|
+
*/
|
|
299
|
+
|
|
300
|
+
/* --- markdown: one plate per block ---------------------------------------- */
|
|
301
|
+
|
|
302
|
+
[class*="markdown"] > p,
|
|
303
|
+
[class*="markdown"] > :where(h1, h2, h3, h4, h5, h6),
|
|
304
|
+
[class*="markdown"] > blockquote {
|
|
305
|
+
background: rgb(242 245 250 / calc(var(--dsh-skin-bubble-alpha, .5) * 1));
|
|
306
|
+
-webkit-backdrop-filter: blur(var(--dsh-skin-bubble-blur, 10px)) saturate(1.3);
|
|
307
|
+
backdrop-filter: blur(var(--dsh-skin-bubble-blur, 10px)) saturate(1.3);
|
|
308
|
+
border-radius: 6px;
|
|
309
|
+
padding: 2px 7px;
|
|
310
|
+
width: fit-content;
|
|
311
|
+
max-width: 100%;
|
|
312
|
+
box-decoration-break: clone;
|
|
313
|
+
-webkit-box-decoration-break: clone;
|
|
314
|
+
box-shadow: 0 1px 3px rgba(28, 37, 70, 0.08);
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
/* One plate for the whole list: the markers sit outside the ul/ol box, and a
|
|
318
|
+
plate per item would leave the markers on the bare illustration. */
|
|
319
|
+
[class*="markdown"] > :where(ul, ol) {
|
|
320
|
+
background: rgb(242 245 250 / calc(var(--dsh-skin-bubble-alpha, .5) * 1));
|
|
321
|
+
-webkit-backdrop-filter: blur(var(--dsh-skin-bubble-blur, 10px)) saturate(1.3);
|
|
322
|
+
backdrop-filter: blur(var(--dsh-skin-bubble-blur, 10px)) saturate(1.3);
|
|
323
|
+
border-radius: 8px;
|
|
324
|
+
padding: 6px 12px 6px 26px;
|
|
325
|
+
width: fit-content;
|
|
326
|
+
max-width: 100%;
|
|
327
|
+
box-shadow: 0 1px 3px rgba(28, 37, 70, 0.08);
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
[class*="markdown"] > pre {
|
|
331
|
+
background: rgb(242 245 250 / calc(var(--dsh-skin-bubble-alpha, .5) * 1));
|
|
332
|
+
-webkit-backdrop-filter: blur(var(--dsh-skin-bubble-blur, 10px)) saturate(1.3);
|
|
333
|
+
backdrop-filter: blur(var(--dsh-skin-bubble-blur, 10px)) saturate(1.3);
|
|
334
|
+
border-radius: 6px;
|
|
335
|
+
padding: 3px 7px;
|
|
336
|
+
box-shadow: 0 1px 3px rgba(28, 37, 70, 0.08);
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
/* A table renders inside a scroll wrapper, so it is not a direct child of the
|
|
340
|
+
markdown box; plate the wrapper to frost the table as a whole.
|
|
341
|
+
|
|
342
|
+
The wrapper is a block and stretches to the column by default, so a table
|
|
343
|
+
narrower than the column leaves the plate hanging ~300px past the last cell --
|
|
344
|
+
a slab of empty glass next to prose plates that all hug their text. Shrink the
|
|
345
|
+
plate to its table (still capped at the column) and centre it. Wide tables are
|
|
346
|
+
unaffected: max-width keeps the plate inside the column and the wrapper's own
|
|
347
|
+
overflow-x:auto still scrolls the table itself. */
|
|
348
|
+
[class*="markdown"] [class*="tableScroll"] {
|
|
349
|
+
background: rgb(242 245 250 / calc(var(--dsh-skin-bubble-alpha, .5) * 1.1));
|
|
350
|
+
-webkit-backdrop-filter: blur(var(--dsh-skin-bubble-blur, 10px)) saturate(1.3);
|
|
351
|
+
backdrop-filter: blur(var(--dsh-skin-bubble-blur, 10px)) saturate(1.3);
|
|
352
|
+
border-radius: 10px;
|
|
353
|
+
padding: 8px 10px;
|
|
354
|
+
box-shadow: 0 1px 4px rgba(28, 37, 70, 0.08);
|
|
355
|
+
width: fit-content;
|
|
356
|
+
max-width: 100%;
|
|
357
|
+
margin-left: auto;
|
|
358
|
+
margin-right: auto;
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
/* The shell ships two table shapes: the default hugs its content
|
|
362
|
+
(`.tableScroll table { width: max-content }`) and a fill variant stretches to
|
|
363
|
+
the column (`.tableFill table { width: 100% }`). Tables here were landing on
|
|
364
|
+
the fill variant, so a four-column table spanned the whole column while every
|
|
365
|
+
prose plate above it hugged its text -- the layer contradicted itself, and a
|
|
366
|
+
short table read as a slab of empty plate.
|
|
367
|
+
|
|
368
|
+
Put the fill variant back on the content-hugging shape. Wide tables still
|
|
369
|
+
behave: the wrapper keeps max-width:100% and overflow-x:auto, so an
|
|
370
|
+
over-long table scrolls instead of overflowing. */
|
|
371
|
+
[class*="markdown"] [class*="tableFill"] table {
|
|
372
|
+
width: max-content;
|
|
373
|
+
max-width: 100%;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
body[data-ds-dark-theme] [class*="markdown"] > p,
|
|
377
|
+
body[data-ds-dark-theme] [class*="markdown"] > :where(h1, h2, h3, h4, h5, h6),
|
|
378
|
+
body[data-ds-dark-theme] [class*="markdown"] > blockquote,
|
|
379
|
+
body[data-ds-dark-theme] [class*="markdown"] > :where(ul, ol),
|
|
380
|
+
body[data-ds-dark-theme] [class*="markdown"] > pre {
|
|
381
|
+
background: rgb(16 22 42 / calc(var(--dsh-skin-bubble-alpha, .5) * .8));
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
body[data-ds-dark-theme] [class*="markdown"] [class*="tableScroll"] {
|
|
385
|
+
background: rgb(16 22 42 / calc(var(--dsh-skin-bubble-alpha, .5) * .9));
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
/* --- disclosure rows: one plate per row, clipped to the text -------------- */
|
|
389
|
+
|
|
390
|
+
[data-slot="conversation.session"] [data-disclosure-row] {
|
|
391
|
+
background: rgb(242 245 250 / calc(var(--dsh-skin-bubble-alpha, .5) * 1));
|
|
392
|
+
-webkit-backdrop-filter: blur(var(--dsh-skin-bubble-blur, 10px)) saturate(1.3);
|
|
393
|
+
backdrop-filter: blur(var(--dsh-skin-bubble-blur, 10px)) saturate(1.3);
|
|
394
|
+
border-radius: 8px;
|
|
395
|
+
padding: 1px 8px;
|
|
396
|
+
width: fit-content;
|
|
397
|
+
max-width: 100%;
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
body[data-ds-dark-theme] [data-slot="conversation.session"] [data-disclosure-row] {
|
|
401
|
+
background: rgb(16 22 42 / calc(var(--dsh-skin-bubble-alpha, .5) * .8));
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
/* --- turn status: keep the shimmer, plate behind the text ----------------- */
|
|
405
|
+
|
|
406
|
+
/* The status line paints its own background with background-clip: text, so it
|
|
407
|
+
cannot take a plate directly; a ::before layer frosts the art underneath
|
|
408
|
+
while the gradient stays on the text. The turn-status clock chip embeds the
|
|
409
|
+
same substring, hence the explicit exclusion. */
|
|
410
|
+
[class*="turnStatus"]:not([class*="turnStatusClock"]) {
|
|
411
|
+
position: relative;
|
|
412
|
+
border-radius: 8px;
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
[class*="turnStatus"]:not([class*="turnStatusClock"])::before {
|
|
416
|
+
content: "";
|
|
417
|
+
position: absolute;
|
|
418
|
+
inset: -5px -10px;
|
|
419
|
+
z-index: -1;
|
|
420
|
+
background: rgb(242 245 250 / calc(var(--dsh-skin-bubble-alpha, .5) * 1.1));
|
|
421
|
+
-webkit-backdrop-filter: blur(var(--dsh-skin-bubble-blur, 10px)) saturate(1.3);
|
|
422
|
+
backdrop-filter: blur(var(--dsh-skin-bubble-blur, 10px)) saturate(1.3);
|
|
423
|
+
border-radius: 8px;
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
body[data-ds-dark-theme] [class*="turnStatus"]:not([class*="turnStatusClock"])::before {
|
|
427
|
+
background: rgb(16 22 42 / calc(var(--dsh-skin-bubble-alpha, .5) * 1));
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
/* --- turn-tail controls: copy / feedback / regenerate --------------------- */
|
|
431
|
+
|
|
432
|
+
[data-turn-tail] [class*="actions"],
|
|
433
|
+
[data-chat-flow-kind="user"] [class*="actions"],
|
|
434
|
+
[data-chat-flow-kind="steering"] [class*="actions"] {
|
|
435
|
+
background: rgb(242 245 250 / calc(var(--dsh-skin-bubble-alpha, .5) * 1));
|
|
436
|
+
-webkit-backdrop-filter: blur(var(--dsh-skin-bubble-blur, 10px)) saturate(1.3);
|
|
437
|
+
backdrop-filter: blur(var(--dsh-skin-bubble-blur, 10px)) saturate(1.3);
|
|
438
|
+
border-radius: 10px;
|
|
439
|
+
padding: 0 8px;
|
|
440
|
+
width: fit-content;
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
body[data-ds-dark-theme] [data-turn-tail] [class*="actions"],
|
|
444
|
+
body[data-ds-dark-theme] [data-chat-flow-kind="user"] [class*="actions"],
|
|
445
|
+
body[data-ds-dark-theme] [data-chat-flow-kind="steering"] [class*="actions"] {
|
|
446
|
+
background: rgb(16 22 42 / calc(var(--dsh-skin-bubble-alpha, .5) * .8));
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
/* --- expanded bodies: full width, plate only ----------------------------- */
|
|
450
|
+
|
|
451
|
+
[class*="_5OnbHa_body"],
|
|
452
|
+
[class*="lcKema_thinkBody"],
|
|
453
|
+
[class*="XrJvXW_body"],
|
|
454
|
+
[data-context-injection-body],
|
|
455
|
+
[data-system-prompt-body] {
|
|
456
|
+
background: rgb(242 245 250 / calc(var(--dsh-skin-bubble-alpha, .5) * 1));
|
|
457
|
+
-webkit-backdrop-filter: blur(var(--dsh-skin-bubble-blur, 10px)) saturate(1.3);
|
|
458
|
+
backdrop-filter: blur(var(--dsh-skin-bubble-blur, 10px)) saturate(1.3);
|
|
459
|
+
border-radius: 8px;
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
body[data-ds-dark-theme] [class*="_5OnbHa_body"],
|
|
463
|
+
body[data-ds-dark-theme] [class*="lcKema_thinkBody"],
|
|
464
|
+
body[data-ds-dark-theme] [class*="XrJvXW_body"],
|
|
465
|
+
body[data-ds-dark-theme] [data-context-injection-body],
|
|
466
|
+
body[data-ds-dark-theme] [data-system-prompt-body] {
|
|
467
|
+
background: rgb(16 22 42 / calc(var(--dsh-skin-bubble-alpha, .5) * .8));
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
/* --- fenced code: the shell paints a plate but no frosting ---------------- */
|
|
471
|
+
|
|
472
|
+
/* A fenced block renders through the shell as a <div class="md-code-block">, not
|
|
473
|
+
a <pre>, so the markdown block rule above never reached it. It already carries
|
|
474
|
+
the shell's own plate (rgba(243 245 251 / .58) light, and its banner + <pre>
|
|
475
|
+
rows repeat it), but with no backdrop-filter the art stays sharp underneath
|
|
476
|
+
and the block reads flatter than the prose around it. Frost it and leave the
|
|
477
|
+
shell's fill alone. */
|
|
478
|
+
[class*="markdown"] [class*="md-code-block"] {
|
|
479
|
+
-webkit-backdrop-filter: blur(var(--dsh-skin-bubble-blur, 10px)) saturate(1.3);
|
|
480
|
+
backdrop-filter: blur(var(--dsh-skin-bubble-blur, 10px)) saturate(1.3);
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
|
|
484
|
+
/* --- turn-process row: one plate, and only one ---------------------------- */
|
|
485
|
+
|
|
486
|
+
/* The "N tool calls . M messages" row is one module whose three slots share a
|
|
487
|
+
single class prefix: the button, its label span and its chevron. Painting the
|
|
488
|
+
prefix lands on all three, the .5 plates stack, and the row reads as a double
|
|
489
|
+
background. The button carries a stable semantic attribute (data-turn-process,
|
|
490
|
+
stamped by TurnProcessNodeView with its turn number), so target that: an
|
|
491
|
+
attribute selector matches the name exactly and leaves the -member / -hidden /
|
|
492
|
+
-answer / -inline siblings alone.
|
|
493
|
+
|
|
494
|
+
Upstream that row is a separator (height 33px, padding 0 0 8px, a .5px bottom
|
|
495
|
+
border). Inside a plate the 8px reads as dead space with a stray line across
|
|
496
|
+
the rounded corner, so square it up with the tool rows and hand the separator
|
|
497
|
+
back only while expanded. */
|
|
498
|
+
[data-slot="main.conversation"] [data-turn-process] {
|
|
499
|
+
background: rgb(242 245 250 / calc(var(--dsh-skin-bubble-alpha, .5) * 1));
|
|
500
|
+
-webkit-backdrop-filter: blur(var(--dsh-skin-bubble-blur, 10px)) saturate(1.3);
|
|
501
|
+
backdrop-filter: blur(var(--dsh-skin-bubble-blur, 10px)) saturate(1.3);
|
|
502
|
+
border-radius: 8px;
|
|
503
|
+
height: auto;
|
|
504
|
+
padding: 1px 8px;
|
|
505
|
+
border-bottom: none;
|
|
506
|
+
width: fit-content;
|
|
507
|
+
max-width: 100%;
|
|
508
|
+
margin-left: auto;
|
|
509
|
+
margin-right: auto;
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
body[data-ds-dark-theme] [data-slot="main.conversation"] [data-turn-process] {
|
|
513
|
+
background: rgb(16 22 42 / calc(var(--dsh-skin-bubble-alpha, .5) * .8));
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
[data-slot="main.conversation"] [data-turn-process][data-open] {
|
|
517
|
+
border-bottom: .5px solid var(--dsw-alias-border-l2);
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
/* --- chrome: the top bar and the right sidebar ---------------------------- */
|
|
521
|
+
|
|
522
|
+
/* The three columns only read as one surface if they share a base, so the
|
|
523
|
+
conversation header and the right sidebar reuse the left pane's measured
|
|
524
|
+
rgb(242 245 250) at the same density instead of plain white. The density is
|
|
525
|
+
fixed rather than tied to --dsh-skin-bubble-alpha: this is window chrome, and
|
|
526
|
+
dragging the Bubble opacity slider should fade bubbles, not the frame.
|
|
527
|
+
|
|
528
|
+
The right sidebar renders as [class*="rightbarCol"] > [data-slot="rightbar"]
|
|
529
|
+
> [data-slot="rightbar.session"] > [class*="panel"]. The two slot hosts are
|
|
530
|
+
display:contents and measure 0x0, so a background on them paints nothing --
|
|
531
|
+
the plate has to land on .panel.
|
|
532
|
+
|
|
533
|
+
The items inside the header (session name, mode picker, the tabs) stay
|
|
534
|
+
background-free on purpose: plates under those labels read as smudges and
|
|
535
|
+
fight the official underline indicator. */
|
|
536
|
+
[data-slot="main.conversation"] header,
|
|
537
|
+
[data-slot="rightbar.session"] > *,
|
|
538
|
+
[class*="rightbarCol"] [class*="panel"] {
|
|
539
|
+
background: rgba(242, 245, 250, 0.75);
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
[data-slot="main.conversation"] header {
|
|
543
|
+
border-bottom: 1px solid rgba(28, 37, 70, 0.08);
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
body[data-ds-dark-theme] [data-slot="main.conversation"] header,
|
|
547
|
+
body[data-ds-dark-theme] [data-slot="rightbar.session"] > *,
|
|
548
|
+
body[data-ds-dark-theme] [class*="rightbarCol"] [class*="panel"] {
|
|
549
|
+
background: rgba(16, 22, 42, 0.75);
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
body[data-ds-dark-theme] [data-slot="main.conversation"] header {
|
|
553
|
+
border-bottom-color: rgba(160, 180, 230, 0.12);
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
|
|
557
|
+
/* --- tool-call rows: one plate per row ------------------------------------ */
|
|
558
|
+
|
|
559
|
+
/* A tool call renders as a wrapper with two near-identical layers inside it
|
|
560
|
+
(the row body and its disclosure header). Plating all three stacks the same
|
|
561
|
+
translucent fill three times and the row reads as a doubled background, so
|
|
562
|
+
plate the wrapper only and reset what is nested inside it. The wrapper
|
|
563
|
+
carries a stable callRow suffix; the inner reset is scoped to the row and
|
|
564
|
+
repeats the dark-theme prefix so it outranks the dark disclosure rule. */
|
|
565
|
+
[data-slot="main.conversation"] [class*="callRow"] {
|
|
566
|
+
background: rgb(242 245 250 / calc(var(--dsh-skin-bubble-alpha, .5) * 1));
|
|
567
|
+
-webkit-backdrop-filter: blur(var(--dsh-skin-bubble-blur, 10px)) saturate(1.3);
|
|
568
|
+
backdrop-filter: blur(var(--dsh-skin-bubble-blur, 10px)) saturate(1.3);
|
|
569
|
+
border-radius: 8px;
|
|
570
|
+
padding: 1px 8px;
|
|
571
|
+
width: fit-content;
|
|
572
|
+
max-width: 100%;
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
body[data-ds-dark-theme] [data-slot="main.conversation"] [class*="callRow"] {
|
|
576
|
+
background: rgb(16 22 42 / calc(var(--dsh-skin-bubble-alpha, .5) * .8));
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
[data-slot="conversation.session"] [class*="callRow"] [class*="o3BgMG_root"],
|
|
580
|
+
[data-slot="conversation.session"] [class*="callRow"] [class*="o3BgMG_summary"],
|
|
581
|
+
[data-slot="conversation.session"] [class*="callRow"] [data-disclosure-row],
|
|
582
|
+
body[data-ds-dark-theme] [data-slot="conversation.session"] [class*="callRow"] [class*="o3BgMG_root"],
|
|
583
|
+
body[data-ds-dark-theme] [data-slot="conversation.session"] [class*="callRow"] [class*="o3BgMG_summary"],
|
|
584
|
+
body[data-ds-dark-theme] [data-slot="conversation.session"] [class*="callRow"] [data-disclosure-row] {
|
|
585
|
+
background: none;
|
|
586
|
+
-webkit-backdrop-filter: none;
|
|
587
|
+
backdrop-filter: none;
|
|
588
|
+
border-radius: 0;
|
|
589
|
+
box-shadow: none;
|
|
590
|
+
padding: 0;
|
|
591
|
+
margin: 0;
|
|
592
|
+
width: auto;
|
|
593
|
+
max-width: none;
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
/* --- the user's own message bubble ---------------------------------------- */
|
|
597
|
+
|
|
598
|
+
/* Keep the accent fill the skin already assigns, add translucency to it and
|
|
599
|
+
frost what shows through. The compound selector matters: a bare
|
|
600
|
+
[class*="bubble"] would also catch unrelated bubbles elsewhere in the shell. */
|
|
601
|
+
[data-slot="main.conversation"] [class*="userStack"] [class*="bubble"] {
|
|
602
|
+
/* 120% of the slider reproduces the 60% body this layer shipped with. */
|
|
603
|
+
background: color-mix(in srgb, var(--dsw-specific-bubble) calc(var(--dsh-skin-bubble-alpha, .5) * 120%), transparent);
|
|
604
|
+
-webkit-backdrop-filter: blur(var(--dsh-skin-bubble-blur, 12px)) saturate(1.3);
|
|
605
|
+
backdrop-filter: blur(var(--dsh-skin-bubble-blur, 12px)) saturate(1.3);
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
/* --- deliverables row (this turn's produced files) ------------------------ */
|
|
609
|
+
|
|
610
|
+
/* Sits in the turn tail and had no plate at all.
|
|
611
|
+
|
|
612
|
+
The width cannot come from a bare fit-content: the row's parent is a
|
|
613
|
+
display:contents slot host that measures 0, and fit-content plus max-width
|
|
614
|
+
then crushes the file chips onto three lines. Making the row an inline-level
|
|
615
|
+
shrink-to-fit box keeps it independent of the parent's width, and align-self
|
|
616
|
+
stops a flex parent from stretching it. */
|
|
617
|
+
[data-slot="main.conversation"] [class*="producedRow"] {
|
|
618
|
+
display: inline-flex;
|
|
619
|
+
align-self: flex-start;
|
|
620
|
+
width: fit-content;
|
|
621
|
+
max-width: 100%;
|
|
622
|
+
background: rgb(242 245 250 / calc(var(--dsh-skin-bubble-alpha, .5) * 1));
|
|
623
|
+
-webkit-backdrop-filter: blur(var(--dsh-skin-bubble-blur, 10px)) saturate(1.3);
|
|
624
|
+
backdrop-filter: blur(var(--dsh-skin-bubble-blur, 10px)) saturate(1.3);
|
|
625
|
+
border-radius: 8px;
|
|
626
|
+
padding: 4px 10px;
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
body[data-ds-dark-theme] [data-slot="main.conversation"] [class*="producedRow"] {
|
|
630
|
+
background: rgb(16 22 42 / calc(var(--dsh-skin-bubble-alpha, .5) * .8));
|
|
631
|
+
}
|