dsh-deepseek-style-theme 2.0.86 → 2.0.88

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.
@@ -6,9 +6,7 @@ must be preserved in every redistribution.
6
6
 
7
7
  ---
8
8
 
9
- ## dsh-theme-mineradio — code included
10
-
11
- `lib/client.js` contains a port of the fluid-shader subsystem and the glass
9
+ ## dsh-theme-mineradio — code included`lib/client.js` contains a port of the fluid-shader subsystem and the glass
12
10
  dispersion / specular-parallax subsystem of **dsh-theme-mineradio v2.3.8**:
13
11
 
14
12
  - the three GLSL programs (`VERTEX_SHADER`, `FLOW_SHADER`, `DISPLAY_SHADER`) and
@@ -20,6 +18,16 @@ dispersion / specular-parallax subsystem of **dsh-theme-mineradio v2.3.8**:
20
18
  `supportsSvgBackdropFilter`),
21
19
  - the specular cursor parallax (`startSpecularParallax`).
22
20
 
21
+ One further technique is **re-expressed, not copied** (v2.0.88): the docked bottom bar,
22
+ in which the composer and its stats line become a single glass slab with the backdrop
23
+ blur on the wrapper's `::before`, the inner surfaces transparent, and one hairline at
24
+ the seam. That structure comes from mineradio's "fused" state
25
+ (`[data-dsh-inputbar]:has([data-dsh-stats])`), including two of its recorded lessons:
26
+ `z-index` rather than `isolation` on the wrapper (isolation is also a backdrop root and
27
+ would clip popup frost to the bar) and `backdrop-filter: none` on the inner surfaces so
28
+ their blur cannot double up with the slab's. The declarations here are written against
29
+ this plugin's own tokens (`--dshome-*`), not mineradio's `--dsh-aqua-*`.
30
+
23
31
  Only naming and external dependencies were adapted: plugin-scoped identifiers
24
32
  were renamed to this plugin's `dshome-` prefix, and the upstream settings/theme
25
33
  store and React layer were replaced by function parameters. **The GLSL shader
package/lib/client.js CHANGED
@@ -1109,15 +1109,27 @@ html,body{background-color:transparent!important}
1109
1109
  The invisible-text hazard stays open on purpose. A stuck appearance switch is
1110
1110
  a broken control; near-white text on a near-white page at least still reads
1111
1111
  once the marker agrees. Do not re-add these two rules. */
1112
- body:not([data-dshome-bg=custom]){background:radial-gradient(1200px 700px at 12% -10%,color-mix(in srgb,var(--ds-brand) 14%,transparent),transparent 60%),radial-gradient(1000px 600px at 105% 12%,color-mix(in srgb,var(--ds-brand-light) 16%,transparent),transparent 55%),radial-gradient(900px 700px at 50% 115%,color-mix(in srgb,var(--ds-brand) 10%,transparent),transparent 60%),linear-gradient(180deg,#fbfbfd 0%,#f5f6fa 100%);background-attachment:fixed}
1112
+ /* The themed background lives on a FIXED PSEUDO-ELEMENT, not on the body with
1113
+ background-attachment: fixed. Two reasons, and the second is the one the user hit:
1114
+ a fixed-attachment background is painted in its own phase, so Chromium's
1115
+ backdrop-filter does not sample it -- every glass pane over the page wash ended up
1116
+ blurring "nothing" and read as plain translucency ("现在的效果是半透明,没有背景模糊
1117
+ 效果"). A position:fixed layer is ordinary painted content and is part of the
1118
+ backdrop. The visual is the same (the wash stays put), and z-index:-2 keeps it under
1119
+ the fluid canvas (-1), which is what the glass should blur next. No backticks in this
1120
+ comment: it lives inside a template literal and a pair of them ends it. */
1121
+ body:not([data-dshome-bg=custom])::before{content:"";position:fixed;inset:0;z-index:-2;pointer-events:none;background:radial-gradient(1200px 700px at 12% -10%,color-mix(in srgb,var(--ds-brand) 14%,transparent),transparent 60%),radial-gradient(1000px 600px at 105% 12%,color-mix(in srgb,var(--ds-brand-light) 16%,transparent),transparent 55%),radial-gradient(900px 700px at 50% 115%,color-mix(in srgb,var(--ds-brand) 10%,transparent),transparent 60%),linear-gradient(180deg,#fbfbfd 0%,#f5f6fa 100%)}
1113
1122
  body[data-dshome-color=red]{--ds-brand:#F5222D;--ds-brand-deep:#CF1322;--ds-brand-mid:#FF4D4F;--ds-brand-light:#FF7875}
1114
1123
  body[data-dshome-color=blue]{--ds-brand:#4D6BFE;--ds-brand-deep:#3A65C2;--ds-brand-mid:#4176E6;--ds-brand-light:#73A3D2}
1115
1124
  body[data-dshome-dark]{--ds-brand:#10B981;--ds-brand-deep:#059669;--ds-brand-mid:#34D399;--ds-brand-light:#6EE7B7}
1116
- body[data-dshome-dark]:not([data-dshome-bg=custom]){background:radial-gradient(1100px 650px at 8% -8%,#0a3a28 0,transparent 62%),radial-gradient(950px 600px at 104% 10%,#0d4d35 0,transparent 58%),radial-gradient(800px 600px at 50% 118%,#06291c 0,transparent 60%),linear-gradient(180deg,#081b14 0%,#0a241a 55%,#081b14 100%);background-attachment:fixed}
1125
+ body[data-dshome-dark]:not([data-dshome-bg=custom])::before{background:radial-gradient(1100px 650px at 8% -8%,#0a3a28 0,transparent 62%),radial-gradient(950px 600px at 104% 10%,#0d4d35 0,transparent 58%),radial-gradient(800px 600px at 50% 118%,#06291c 0,transparent 60%),linear-gradient(180deg,#081b14 0%,#0a241a 55%,#081b14 100%)}
1117
1126
  body[data-dshome-dark][data-dshome-color=red]{--ds-brand:#FF4D4F;--ds-brand-deep:#F5222D;--ds-brand-mid:#FF7875;--ds-brand-light:#FFA39E}
1118
- body[data-dshome-dark][data-dshome-color=red]:not([data-dshome-bg=custom]){background:radial-gradient(1100px 650px at 8% -8%,#5c0f14 0,transparent 62%),radial-gradient(950px 600px at 104% 10%,#7d1a20 0,transparent 58%),radial-gradient(800px 600px at 50% 118%,#3f0a0e 0,transparent 60%),linear-gradient(180deg,#260709 0%,#330a0d 55%,#260709 100%);background-attachment:fixed}
1127
+ body[data-dshome-dark][data-dshome-color=red]:not([data-dshome-bg=custom])::before{background:radial-gradient(1100px 650px at 8% -8%,#5c0f14 0,transparent 62%),radial-gradient(950px 600px at 104% 10%,#7d1a20 0,transparent 58%),radial-gradient(800px 600px at 50% 118%,#3f0a0e 0,transparent 60%),linear-gradient(180deg,#260709 0%,#330a0d 55%,#260709 100%)}
1119
1128
  body[data-dshome-dark][data-dshome-color=blue]{--ds-brand:#5D79FF;--ds-brand-deep:#4D6BFE;--ds-brand-mid:#7A96FF;--ds-brand-light:#9DB9FF}
1120
- body[data-dshome-dark][data-dshome-color=blue]:not([data-dshome-bg=custom]){background:radial-gradient(1100px 650px at 8% -8%,#1a3870 0,transparent 62%),radial-gradient(950px 600px at 104% 10%,#2d5f9e 0,transparent 58%),radial-gradient(800px 600px at 50% 118%,#0d1f4a 0,transparent 60%),linear-gradient(180deg,#0a1a3a 0%,#0d1f4a 55%,#0a1a3a 100%);background-attachment:fixed}
1129
+ body[data-dshome-dark][data-dshome-color=blue]:not([data-dshome-bg=custom])::before{background:radial-gradient(1100px 650px at 8% -8%,#1a3870 0,transparent 62%),radial-gradient(950px 600px at 104% 10%,#2d5f9e 0,transparent 58%),radial-gradient(800px 600px at 50% 118%,#0d1f4a 0,transparent 60%),linear-gradient(180deg,#0a1a3a 0%,#0d1f4a 55%,#0a1a3a 100%)}
1130
+ /* The body itself must NOT paint a background: any opaque page background sits
1131
+ below the pseudo-element and would be what the glass samples. */
1132
+ body:not([data-dshome-bg=custom]){background:none!important}
1121
1133
  /* ── background recipe: 自选背景 ─────────────────────────────────────────
1122
1134
  The custom value never enters this sheet. It arrives as the custom property
1123
1135
  --dshome-custom-bg on <body>, and only after the client's CSS.supports()
@@ -1493,6 +1505,47 @@ body[data-dshome-dark] :is([class*="_headline"]){background:linear-gradient(120d
1493
1505
  { anchor: ".wSkVaW_scrollBody", css: `
1494
1506
  :is(${USER_BUBBLE}){background:rgba(255,255,255,.6)!important;-webkit-backdrop-filter:blur(16px);backdrop-filter:blur(16px);border:1px solid rgba(0,0,0,.05);box-shadow:0 4px 16px rgba(13,30,60,.06)}
1495
1507
  body[data-dshome-dark] :is(${USER_BUBBLE}){background:rgba(21,42,86,.65)!important;border:1px solid rgba(255,255,255,.1);box-shadow:0 4px 16px rgba(0,0,0,.25)}
1508
+ ` },
1509
+ // The line under the composer: round/step/token stats ([data-dsh-stats]) and
1510
+ // the whole input bar ([data-dsh-inputbar]) -- both product markup that has
1511
+ // never been renamed.
1512
+ //
1513
+ // Two things happen here.
1514
+ //
1515
+ // 1. The DOCKED BOTTOM BAR, borrowed from dsh-theme-mineradio's fused state
1516
+ // (MIT, @dhicoc): once the stats line exists, the WHOLE input bar becomes
1517
+ // one glass slab -- a single border, radius, fill and shadow on the
1518
+ // wrapper, with the backdrop blur on its ::before -- and the card and the
1519
+ // stats turn transparent inside it, leaving one hairline at the seam. The
1520
+ // two surfaces can then never drift apart tonally, and the composer reads
1521
+ // as one designed bar instead of a card with loose text under it.
1522
+ // `:has()` is what makes this safe to attempt at all: when the product
1523
+ // does not render a stats line, none of it applies and the card keeps its
1524
+ // own glass.
1525
+ // Two details are load-bearing and inherited from mineradio's notes:
1526
+ // z-index (not isolation) on the wrapper -- isolation is also a backdrop
1527
+ // root and would clip popup frost to the bar -- and `backdrop-filter:
1528
+ // none` on the inner surfaces, whose own blur would otherwise double up
1529
+ // with the slab's.
1530
+ //
1531
+ // 2. The LENS touch the user asked for ("对对话窗下方文字进行放大(模拟液体放大)"):
1532
+ // a real lens magnifies what is behind the glass, which a backdrop filter
1533
+ // cannot do, so the text is scaled a touch instead -- and a touch further
1534
+ // while the pane leans (html[data-dshome-leaning], written by
1535
+ // startComposerTilt). `transform-origin: left center` keeps a
1536
+ // left-aligned line growing inwards instead of spilling past the slab's
1537
+ // right edge.
1538
+ { anchor: "[data-dsh-stats]", css: `
1539
+ [data-dsh-inputbar]:has([data-dsh-stats]){position:relative;z-index:8;padding:0;border:1.5px solid rgba(255,255,255,.55);border-radius:24px;background:rgba(255,255,255,.42);box-shadow:0 8px 32px rgba(13,30,60,.1),inset 0 1px 1px hsla(0,0%,100%,.8)}
1540
+ [data-dsh-inputbar]:has([data-dsh-stats])::before{content:"";position:absolute;inset:0;border-radius:inherit;pointer-events:none;z-index:-1;-webkit-backdrop-filter:blur(28px) saturate(1.42) brightness(1.02);backdrop-filter:blur(28px) saturate(1.42) brightness(1.02)}
1541
+ [data-dsh-inputbar]:has([data-dsh-stats]) [data-composer-card]{border:none!important;border-radius:0!important;background:transparent!important;background-image:none!important;box-shadow:none!important;-webkit-backdrop-filter:none!important;backdrop-filter:none!important}
1542
+ [data-dsh-inputbar]:has([data-dsh-stats]) [data-composer-card]::before,[data-dsh-inputbar]:has([data-dsh-stats]) [data-composer-card]::after{display:none!important}
1543
+ [data-dsh-inputbar]:has([data-dsh-stats]) [data-dsh-stats]{display:block;width:100%;max-width:none;box-sizing:border-box;margin:auto 0 0;min-height:24px;padding:2px 16px;border:none;border-top:1px solid rgba(0,0,0,.06);border-radius:0;background:transparent;box-shadow:none;-webkit-backdrop-filter:none;backdrop-filter:none;transform-origin:left center;transition:transform .24s cubic-bezier(.2,.8,.2,1)}
1544
+ [data-dsh-stats]{transform:scale(1.04)}
1545
+ html[data-dshome-leaning] [data-dsh-inputbar]:has([data-dsh-stats]) [data-dsh-stats]{transform:scale(1.08)}
1546
+ body[data-dshome-dark] [data-dsh-inputbar]:has([data-dsh-stats]){border-color:rgba(255,255,255,.16);background:rgba(13,30,60,.55);box-shadow:0 10px 40px rgba(0,0,0,.35),inset 0 1px 1px rgba(255,255,255,.06)}
1547
+ body[data-dshome-dark] [data-dsh-inputbar]:has([data-dsh-stats]) [data-dsh-stats]{border-top-color:rgba(255,255,255,.1)}
1548
+ @media (prefers-reduced-motion:reduce){[data-dsh-inputbar]:has([data-dsh-stats]) [data-dsh-stats]{transition:none}}
1496
1549
  ` },
1497
1550
  // Trajectory view bar.
1498
1551
  { anchor: ".fV0t5q_root", css: `
@@ -1790,10 +1843,14 @@ html[data-dshome-glass="liquid"] :is(${USER_BUBBLE}){
1790
1843
  /* The composer leans under the cursor (see startComposerTilt). The transition
1791
1844
  is what turns the release into a settle rather than a snap: the ported
1792
1845
  routine writes the neutral transform back and only drops the inline
1793
- properties 240ms later. */
1846
+ properties 240ms later.
1847
+ will-change: transform used to sit here as a perf hint and is deliberately
1848
+ GONE: promoting the pane to its own layer is the other half of "no blur" --
1849
+ Chromium's backdrop sampling is unreliable on a will-changed element, and the
1850
+ compositor already promotes a transformed element while it is actually being
1851
+ transformed. The hint cost the effect it was meant to smooth. */
1794
1852
  html[data-dshome-glass="liquid"] [data-composer-card]{
1795
1853
  transition:transform .24s cubic-bezier(.2,.8,.2,1),background-color .18s ease,box-shadow .18s ease!important;
1796
- will-change:transform;
1797
1854
  }
1798
1855
  html[data-dshome-glass="liquid"] :is(${USER_BUBBLE}):hover{
1799
1856
  background-color:rgb(255 255 255 / .18)!important;
@@ -1859,8 +1916,11 @@ html[data-dshome-dispersion][data-dshome-glass="liquid"][data-dshome-composer="o
1859
1916
  actually behind it, so the fade shows up as a lighter band above 设置 (the
1860
1917
  user's red box). The pane itself already separates the list from the
1861
1918
  conversation, so the fade is dropped. Scoped to the sidebar and to the
1862
- product's own <hash>_fade naming so nothing else is touched. */
1863
- html[data-dshome-glass="liquid"] body .hHd-Xa_root [class*="_fade" i]{
1919
+ product's own <hash>_fade naming so nothing else is touched.
1920
+ NOT gated on the liquid recipe: it was, and the user sent a screenshot of the
1921
+ same light band in 白磨砂 ("白磨砂,有这个渐变") — the frosted pane is translucent
1922
+ too, so its end stop mismatches just the same. Both recipes drop it. */
1923
+ body .hHd-Xa_root [class*="_fade" i]{
1864
1924
  background-image:none!important;
1865
1925
  }
1866
1926
  /* The sidebar's own, heavier blur. Written after the two rules above because it
@@ -2421,6 +2481,9 @@ html[data-dshome-blur="off"] body{
2421
2481
  // `spots` (0 means the composer no longer matches TILT_SELECTOR), and the
2422
2482
  // reduced-motion case logs one info line instead of vanishing.
2423
2483
  const TILT_SELECTOR = '[data-composer-card],.uV2eYG_card';
2484
+ /** On <html> while the composer leans; the lens touch on the line under the
2485
+ * composer reads it (see the [data-dsh-stats] patch block). */
2486
+ const LEAN_ATTR = 'data-dshome-leaning';
2424
2487
  // 0.0175 rad was upstream's conservative lean, and after 2.0.85 finally made
2425
2488
  // the effect reachable the verdict was "倾斜效果很微弱" -- fair, at ~4 degrees
2426
2489
  // end to end over a pane this wide it reads as a wobble, not as depth. Raised
@@ -2493,6 +2556,7 @@ html[data-dshome-blur="off"] body{
2493
2556
  if (!tilted.has(spot)) return;
2494
2557
  releasedAt = performance.now();
2495
2558
  tilted.delete(spot);
2559
+ document.documentElement.removeAttribute(LEAN_ATTR);
2496
2560
  spot.style.transform = 'perspective(' + TILT_PERSPECTIVE + 'px) rotateX(0rad) rotateY(0rad) scale(1)';
2497
2561
  const handle = window.setTimeout(() => {
2498
2562
  settle.delete(spot);
@@ -2519,6 +2583,11 @@ html[data-dshome-blur="off"] body{
2519
2583
  + ' scale(' + TILT_SCALE + ')';
2520
2584
  if (!tilted.has(spot)) engagements += 1;
2521
2585
  tilted.add(spot);
2586
+ // The marker the lens touch reads (see the composer-stats block in
2587
+ // PATCH_BLOCKS): while the pane leans, the line under it is scaled a
2588
+ // little further, which is the closest thing to a lens without
2589
+ // touching the backdrop.
2590
+ if (!document.documentElement.hasAttribute(LEAN_ATTR)) document.documentElement.setAttribute(LEAN_ATTR, '');
2522
2591
  });
2523
2592
  };
2524
2593
  /**
@@ -2633,6 +2702,7 @@ html[data-dshome-blur="off"] body{
2633
2702
  spot.style.removeProperty('transform-origin');
2634
2703
  spot.style.removeProperty('transition');
2635
2704
  }
2705
+ document.documentElement.removeAttribute(LEAN_ATTR);
2636
2706
  current = null;
2637
2707
  };
2638
2708
  }
@@ -2651,7 +2721,7 @@ html[data-dshome-blur="off"] body{
2651
2721
  if (!supportsWebgl2()) return startParticles();
2652
2722
  // Which build is running, readable from the page (see README). One line in
2653
2723
  // the console answers "is the bundle I just installed actually live?".
2654
- try { window.__dshomeBuild = '2.0.86 glass-on noise-fix'; } catch (error) {}
2724
+ try { window.__dshomeBuild = '2.0.88 fused-bar'; } catch (error) {}
2655
2725
  const canvas = document.createElement('canvas');
2656
2726
  canvas.setAttribute('data-dsh-deepseek-canvas', '');
2657
2727
  const style = canvas.style;
@@ -2782,6 +2852,33 @@ html[data-dshome-blur="off"] body{
2782
2852
  recipe: dsttGetGlass()
2783
2853
  });
2784
2854
  } catch (error) {}
2855
+ /**
2856
+ * "Why is there no blur" answered in one call: the computed backdrop chain of
2857
+ * every glass surface, the two things that can silently stop Chromium from
2858
+ * sampling a backdrop (a fixed-attachment body background and a will-changed
2859
+ * pane), and the setting that turns the radii off on purpose.
2860
+ */
2861
+ try {
2862
+ window.__dshomeGlassProbe = () => {
2863
+ const card = document.querySelector(TILT_SELECTOR);
2864
+ const chain = (selector, pseudo) => {
2865
+ const node = document.querySelector(selector);
2866
+ if (node === null) return null;
2867
+ try { return getComputedStyle(node, pseudo === undefined ? null : pseudo).backdropFilter; } catch (error) { return 'ERR'; }
2868
+ };
2869
+ return {
2870
+ recipe: dsttGetGlass(),
2871
+ backdropBlurSetting: dsttState.blur,
2872
+ bodyBackgroundAttachment: getComputedStyle(document.body).backgroundAttachment,
2873
+ bodyBackgroundImage: getComputedStyle(document.body).backgroundImage.slice(0, 32),
2874
+ washLayer: getComputedStyle(document.body, '::before').position,
2875
+ tiltCard: card === null ? null : getComputedStyle(card).backdropFilter,
2876
+ tiltCardWillChange: card === null ? null : (getComputedStyle(card).willChange || 'auto'),
2877
+ sidebar: chain('.hHd-Xa_root', '::before'),
2878
+ bubble: chain(USER_BUBBLE)
2879
+ };
2880
+ };
2881
+ } catch (error) {}
2785
2882
  // Both recipes share one filter pair, so the recipe selects the scale:
2786
2883
  // 104 for liquid (visible edge refraction) and the untouched 60 for
2787
2884
  // frosted, which is what the pane has always used.
@@ -2815,7 +2912,7 @@ html[data-dshome-blur="off"] body{
2815
2912
  }
2816
2913
 
2817
2914
  function startParticles() {
2818
- try { window.__dshomeBuild = '2.0.86 glass-on noise-fix'; } catch (error) {}
2915
+ try { window.__dshomeBuild = '2.0.88 fused-bar'; } catch (error) {}
2819
2916
  const canvas = document.createElement('canvas');
2820
2917
  canvas.setAttribute('data-dsh-deepseek-canvas', '');
2821
2918
  const style = canvas.style;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "dsh-deepseek-style-theme",
3
3
  "description": "DeepSeek official-home style theme: WebGL fluid-flow background, liquid glass with SVG edge refraction, glass sidebar and composer, frosted header, running-subagent progress panel, and DeepSeek brand link for the dsh web GUI",
4
- "version": "2.0.86",
4
+ "version": "2.0.88",
5
5
  "type": "module",
6
6
  "keywords": [
7
7
  "deepseek",