dsh-skin-galactic-opera 0.1.6 → 0.1.7

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.
Files changed (3) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/lib/client.js +192 -43
  3. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -2,6 +2,18 @@
2
2
 
3
3
  All notable changes to this package will be documented in this file.
4
4
 
5
+ ## 0.1.7 - 2026-09-03
6
+
7
+ ### Changed
8
+
9
+ - Moves the decorative visual layer into Shadow DOM to isolate scanner, planet, pulse, and black-hole geometry from DSH host style regressions.
10
+ - Keeps the input-mode black hole visually stable while still reducing high-motion distraction elsewhere.
11
+ - Aligns the hyperspace burst effect to the black-hole center after Shadow DOM isolation.
12
+
13
+ ### Fixed
14
+
15
+ - Prevents Shadow DOM container nesting from shifting the scanner disk, planet, satellite orbit, and other decorative elements toward the viewport edges.
16
+
5
17
  ## 0.1.6 - 2026-08-28
6
18
 
7
19
  ### Changed
package/lib/client.js CHANGED
@@ -10,6 +10,7 @@ window.__ModuleLoader__.load({
10
10
  const THEME_LABEL = "Galactic Opera";
11
11
  const STYLE_ID = "dsh-skin-galactic-opera-style";
12
12
  const DECOR_ID = "dsh-skin-galactic-opera-decor";
13
+ const DECOR_HOST_CLASS = "dsh-skin-galactic-opera-decor-host";
13
14
  const CSS_TAG_ID = `${PLUGIN_ID}/global.css`;
14
15
 
15
16
  const TOKENS = Object.freeze({
@@ -160,17 +161,13 @@ body.dsh-skin-galactic-opera.dsh-skin-galactic-opera-input-active #root::before
160
161
  will-change: auto;
161
162
  }
162
163
 
163
- body.dsh-skin-galactic-opera.dsh-skin-galactic-opera-input-active .dsh-skin-galactic-opera-decor {
164
- opacity: 0.28;
165
- }
166
-
167
- body.dsh-skin-galactic-opera.dsh-skin-galactic-opera-input-active :is(.dsh-skin-nebula-core, .dsh-skin-energy, .dsh-skin-comet, .dsh-skin-starfighter, .dsh-skin-mission-crawl, .dsh-skin-scanner, .dsh-skin-route-map),
164
+ body.dsh-skin-galactic-opera.dsh-skin-galactic-opera-input-active :is(.dsh-skin-energy, .dsh-skin-comet, .dsh-skin-starfighter, .dsh-skin-mission-crawl, .dsh-skin-scanner, .dsh-skin-route-map),
168
165
  body.dsh-skin-galactic-opera.dsh-skin-galactic-opera-input-active .dsh-skin-scanner::after {
169
166
  animation-play-state: paused !important;
170
167
  }
171
168
 
172
- body.dsh-skin-galactic-opera.dsh-skin-galactic-opera-input-active :is(.dsh-skin-nebula-core, .dsh-skin-energy, .dsh-skin-comet, .dsh-skin-starfighter, .dsh-skin-mission-crawl) {
173
- opacity: 0.08 !important;
169
+ body.dsh-skin-galactic-opera.dsh-skin-galactic-opera-input-active :is(.dsh-skin-energy, .dsh-skin-comet, .dsh-skin-starfighter, .dsh-skin-mission-crawl) {
170
+ opacity: 0.16 !important;
174
171
  }
175
172
 
176
173
  body.dsh-skin-galactic-opera #root > *,
@@ -197,6 +194,7 @@ body.dsh-skin-galactic-opera [class*="Sidebar"] {
197
194
  0 0 40px rgba(125, 227, 255, 0.12) !important;
198
195
  }
199
196
 
197
+ body.dsh-skin-galactic-opera .dsh-skin-galactic-opera-decor-host,
200
198
  body.dsh-skin-galactic-opera .dsh-skin-galactic-opera-decor {
201
199
  position: fixed;
202
200
  inset: -2vmax;
@@ -206,16 +204,28 @@ body.dsh-skin-galactic-opera .dsh-skin-galactic-opera-decor {
206
204
  mix-blend-mode: screen;
207
205
  }
208
206
 
207
+ body.dsh-skin-galactic-opera .dsh-skin-galactic-opera-decor-host {
208
+ display: block;
209
+ width: auto;
210
+ height: auto;
211
+ border: 0 !important;
212
+ border-radius: 0 !important;
213
+ background: transparent !important;
214
+ }
215
+
209
216
  body.dsh-skin-galactic-opera .dsh-skin-galactic-opera-decor::before {
210
217
  content: "";
211
218
  position: absolute;
212
- inset: -12vmax;
219
+ left: 48%;
220
+ top: 50%;
221
+ width: 140vmax;
222
+ height: 140vmax;
213
223
  opacity: 0;
214
224
  pointer-events: none;
215
225
  background:
216
226
  repeating-conic-gradient(from 0deg at 50% 50%, transparent 0deg 5deg, rgba(125,227,255,0.72) 5.4deg 6deg, transparent 6.4deg 12deg),
217
227
  radial-gradient(circle at 50% 50%, rgba(255,255,255,0.82), transparent 8vmin, rgba(255,207,92,0.26) 12vmin, transparent 36vmin);
218
- transform: scale(0.5);
228
+ transform: translate(-50%, -50%) scale(0.5);
219
229
  filter: blur(0.2px);
220
230
  }
221
231
 
@@ -223,6 +233,23 @@ body.dsh-skin-galactic-opera.dsh-skin-galactic-opera-hyperspace .dsh-skin-galact
223
233
  animation: dsh-skin-galactic-opera-hyperspace-burst 880ms cubic-bezier(.16,.8,.25,1) both;
224
234
  }
225
235
 
236
+ body.dsh-skin-galactic-opera .dsh-skin-galactic-opera-decor,
237
+ body.dsh-skin-galactic-opera .dsh-skin-galactic-opera-decor *,
238
+ body.dsh-skin-galactic-opera .dsh-skin-galactic-opera-decor *::before,
239
+ body.dsh-skin-galactic-opera .dsh-skin-galactic-opera-decor *::after {
240
+ box-sizing: border-box;
241
+ min-width: 0;
242
+ min-height: 0;
243
+ max-width: none;
244
+ max-height: none;
245
+ margin: 0;
246
+ padding: 0;
247
+ font: inherit;
248
+ line-height: 1;
249
+ text-decoration: none;
250
+ background-clip: border-box;
251
+ }
252
+
226
253
  body.dsh-skin-galactic-opera .dsh-skin-galactic-opera-decor span {
227
254
  position: absolute;
228
255
  display: block;
@@ -584,6 +611,32 @@ body.dsh-skin-galactic-opera .dsh-skin-mission-crawl::before {
584
611
  text-shadow: 0 0 14px rgba(255,207,92,0.46);
585
612
  }
586
613
 
614
+ body.dsh-skin-galactic-opera :is(.dsh-skin-twinkle, .dsh-skin-nebula-core, .dsh-skin-orb, .dsh-skin-scanner, .dsh-skin-scanner-target, .dsh-skin-pulse),
615
+ body.dsh-skin-galactic-opera .dsh-skin-satellite::before,
616
+ body.dsh-skin-galactic-opera .dsh-skin-satellite-orbit::before,
617
+ body.dsh-skin-galactic-opera .dsh-skin-satellite-orbit-front::before,
618
+ body.dsh-skin-galactic-opera #dsh-skin-galactic-opera-decor :is(.dsh-skin-twinkle, .dsh-skin-nebula-core, .dsh-skin-orb, .dsh-skin-scanner, .dsh-skin-scanner-target, .dsh-skin-pulse),
619
+ body.dsh-skin-galactic-opera #dsh-skin-galactic-opera-decor .dsh-skin-satellite::before,
620
+ body.dsh-skin-galactic-opera #dsh-skin-galactic-opera-decor .dsh-skin-satellite-orbit::before,
621
+ body.dsh-skin-galactic-opera #dsh-skin-galactic-opera-decor .dsh-skin-satellite-orbit-front::before {
622
+ border-radius: 50% !important;
623
+ border-top-left-radius: 50% !important;
624
+ border-top-right-radius: 50% !important;
625
+ border-bottom-right-radius: 50% !important;
626
+ border-bottom-left-radius: 50% !important;
627
+ }
628
+
629
+ body.dsh-skin-galactic-opera :is(.dsh-skin-energy, .dsh-skin-comet),
630
+ body.dsh-skin-galactic-opera .dsh-skin-scanner::after,
631
+ body.dsh-skin-galactic-opera #dsh-skin-galactic-opera-decor :is(.dsh-skin-energy, .dsh-skin-comet),
632
+ body.dsh-skin-galactic-opera #dsh-skin-galactic-opera-decor .dsh-skin-scanner::after {
633
+ border-radius: 999px !important;
634
+ border-top-left-radius: 999px !important;
635
+ border-top-right-radius: 999px !important;
636
+ border-bottom-right-radius: 999px !important;
637
+ border-bottom-left-radius: 999px !important;
638
+ }
639
+
587
640
  body.dsh-skin-galactic-opera .dsh-skin-pulse {
588
641
  position: fixed;
589
642
  left: var(--dsh-skin-pulse-x);
@@ -925,9 +978,9 @@ body.dsh-skin-galactic-opera .dsh-skin-telemetry-value-full {
925
978
  }
926
979
 
927
980
  @keyframes dsh-skin-galactic-opera-hyperspace-burst {
928
- 0% { opacity: 0; transform: scale(0.32) rotate(0deg); }
981
+ 0% { opacity: 0; transform: translate(-50%, -50%) scale(0.32) rotate(0deg); }
929
982
  15% { opacity: 0.9; }
930
- 100% { opacity: 0; transform: scale(1.45) rotate(10deg); }
983
+ 100% { opacity: 0; transform: translate(-50%, -50%) scale(1.45) rotate(10deg); }
931
984
  }
932
985
 
933
986
  @keyframes dsh-skin-route-pulse {
@@ -1009,42 +1062,133 @@ body.dsh-skin-galactic-opera .dsh-skin-telemetry-value-full {
1009
1062
  return tag;
1010
1063
  }
1011
1064
 
1065
+ const DECOR_MARKUP = [
1066
+ "<span class=\"dsh-skin-nebula-core\"></span>",
1067
+ "<span class=\"dsh-skin-twinkle dsh-skin-twinkle-a\"></span>",
1068
+ "<span class=\"dsh-skin-twinkle dsh-skin-twinkle-b\"></span>",
1069
+ "<span class=\"dsh-skin-twinkle dsh-skin-twinkle-c\"></span>",
1070
+ "<span class=\"dsh-skin-orb dsh-skin-orb-primary\"></span>",
1071
+ "<span class=\"dsh-skin-orb dsh-skin-orb-moon-a\"></span>",
1072
+ "<span class=\"dsh-skin-satellite-orbit\"></span>",
1073
+ "<span class=\"dsh-skin-satellite-orbit-front\"></span>",
1074
+ "<span class=\"dsh-skin-satellite\"></span>",
1075
+ "<span class=\"dsh-skin-scanner\"></span>",
1076
+ "<span class=\"dsh-skin-scanner-target\"></span>",
1077
+ "<span class=\"dsh-skin-route-map\"></span>",
1078
+ "<span class=\"dsh-skin-energy dsh-skin-energy-cyan\"></span>",
1079
+ "<span class=\"dsh-skin-energy dsh-skin-energy-red\"></span>",
1080
+ "<span class=\"dsh-skin-energy dsh-skin-energy-gold\"></span>",
1081
+ "<span class=\"dsh-skin-starfighter dsh-skin-starfighter-1\"></span>",
1082
+ "<span class=\"dsh-skin-starfighter dsh-skin-starfighter-2\"></span>",
1083
+ "<span class=\"dsh-skin-starfighter dsh-skin-starfighter-3\"></span>",
1084
+ "<span class=\"dsh-skin-mission-crawl\"></span>",
1085
+ "<span class=\"dsh-skin-comet dsh-skin-comet-1\"></span>",
1086
+ "<span class=\"dsh-skin-comet dsh-skin-comet-2\"></span>",
1087
+ "<span class=\"dsh-skin-comet dsh-skin-comet-3\"></span>",
1088
+ "<span class=\"dsh-skin-comet dsh-skin-comet-4\"></span>",
1089
+ "<span class=\"dsh-skin-comet dsh-skin-comet-5\"></span>",
1090
+ "<span class=\"dsh-skin-comet dsh-skin-comet-6\"></span>"
1091
+ ].join("");
1092
+
1093
+ function getDecorShadowCss() {
1094
+ return `${CSS
1095
+ .replace(/body\.dsh-skin-galactic-opera\.dsh-skin-galactic-opera-input-active\s+/g, ":host-context(body.dsh-skin-galactic-opera.dsh-skin-galactic-opera-input-active) ")
1096
+ .replace(/body\.dsh-skin-galactic-opera\.dsh-skin-galactic-opera-hyperspace\s+/g, ":host-context(body.dsh-skin-galactic-opera.dsh-skin-galactic-opera-hyperspace) ")
1097
+ .replace(/body\.dsh-skin-galactic-opera\s+/g, "")}
1098
+
1099
+ .dsh-skin-galactic-opera-decor {
1100
+ position: absolute !important;
1101
+ inset: 0 !important;
1102
+ width: auto !important;
1103
+ height: auto !important;
1104
+ z-index: auto !important;
1105
+ }
1106
+ `;
1107
+ }
1108
+
1109
+ function setImportantStyle(element, name, value) {
1110
+ if (element instanceof HTMLElement) element.style.setProperty(name, value, "important");
1111
+ }
1112
+
1113
+ function hardenDecorHost(decor) {
1114
+ setImportantStyle(decor, "position", "fixed");
1115
+ setImportantStyle(decor, "inset", "-2vmax");
1116
+ setImportantStyle(decor, "z-index", "2147483645");
1117
+ setImportantStyle(decor, "pointer-events", "none");
1118
+ setImportantStyle(decor, "overflow", "hidden");
1119
+ setImportantStyle(decor, "mix-blend-mode", "screen");
1120
+ setImportantStyle(decor, "display", "block");
1121
+ setImportantStyle(decor, "width", "auto");
1122
+ setImportantStyle(decor, "height", "auto");
1123
+ setImportantStyle(decor, "border", "0");
1124
+ setImportantStyle(decor, "border-radius", "0");
1125
+ setImportantStyle(decor, "border-top-left-radius", "0");
1126
+ setImportantStyle(decor, "border-top-right-radius", "0");
1127
+ setImportantStyle(decor, "border-bottom-right-radius", "0");
1128
+ setImportantStyle(decor, "border-bottom-left-radius", "0");
1129
+ setImportantStyle(decor, "background", "transparent");
1130
+ }
1131
+
1132
+ function getDecorRoot(decor) {
1133
+ return decor?.shadowRoot ?? decor;
1134
+ }
1135
+
1136
+ function getDecorLayer(decor) {
1137
+ const root = getDecorRoot(decor);
1138
+ return root?.querySelector?.(".dsh-skin-galactic-opera-decor") ?? root;
1139
+ }
1140
+
1141
+ function hardenDecorGeometry(decor) {
1142
+ const root = getDecorRoot(decor);
1143
+ if (root === undefined || root === null) return;
1144
+ const roundSelector = ".dsh-skin-twinkle, .dsh-skin-nebula-core, .dsh-skin-orb, .dsh-skin-scanner, .dsh-skin-scanner-target";
1145
+ for (const element of root.querySelectorAll(roundSelector)) {
1146
+ setImportantStyle(element, "border-radius", "50%");
1147
+ setImportantStyle(element, "overflow", "visible");
1148
+ setImportantStyle(element, "box-sizing", "border-box");
1149
+ }
1150
+ for (const element of root.querySelectorAll(".dsh-skin-energy, .dsh-skin-comet")) {
1151
+ setImportantStyle(element, "border-radius", "999px");
1152
+ setImportantStyle(element, "overflow", "visible");
1153
+ setImportantStyle(element, "box-sizing", "border-box");
1154
+ }
1155
+ }
1156
+
1157
+ function populateDecor(decor) {
1158
+ if (typeof decor.attachShadow === "function") {
1159
+ const shadow = decor.shadowRoot ?? decor.attachShadow({ mode: "open" });
1160
+ shadow.replaceChildren();
1161
+ decor.replaceChildren();
1162
+ const style = document.createElement("style");
1163
+ style.textContent = getDecorShadowCss();
1164
+ const layer = document.createElement("div");
1165
+ layer.className = "dsh-skin-galactic-opera-decor";
1166
+ layer.innerHTML = DECOR_MARKUP;
1167
+ shadow.append(style, layer);
1168
+ } else {
1169
+ decor.innerHTML = DECOR_MARKUP;
1170
+ }
1171
+ hardenDecorGeometry(decor);
1172
+ }
1173
+
1012
1174
  function ensureDecor() {
1013
1175
  if (typeof document === "undefined") return undefined;
1014
1176
  let decor = document.getElementById(DECOR_ID);
1015
- if (decor instanceof HTMLDivElement) return decor;
1177
+ if (decor instanceof HTMLDivElement) {
1178
+ decor.className = DECOR_HOST_CLASS;
1179
+ decor.setAttribute("aria-hidden", "true");
1180
+ decor.dataset.plugin = PLUGIN_ID;
1181
+ hardenDecorHost(decor);
1182
+ populateDecor(decor);
1183
+ return decor;
1184
+ }
1016
1185
  decor = document.createElement("div");
1017
1186
  decor.id = DECOR_ID;
1018
- decor.className = "dsh-skin-galactic-opera-decor";
1187
+ decor.className = DECOR_HOST_CLASS;
1019
1188
  decor.setAttribute("aria-hidden", "true");
1020
1189
  decor.dataset.plugin = PLUGIN_ID;
1021
- decor.innerHTML = [
1022
- "<span class=\"dsh-skin-nebula-core\"></span>",
1023
- "<span class=\"dsh-skin-twinkle dsh-skin-twinkle-a\"></span>",
1024
- "<span class=\"dsh-skin-twinkle dsh-skin-twinkle-b\"></span>",
1025
- "<span class=\"dsh-skin-twinkle dsh-skin-twinkle-c\"></span>",
1026
- "<span class=\"dsh-skin-orb dsh-skin-orb-primary\"></span>",
1027
- "<span class=\"dsh-skin-orb dsh-skin-orb-moon-a\"></span>",
1028
- "<span class=\"dsh-skin-satellite-orbit\"></span>",
1029
- "<span class=\"dsh-skin-satellite-orbit-front\"></span>",
1030
- "<span class=\"dsh-skin-satellite\"></span>",
1031
- "<span class=\"dsh-skin-scanner\"></span>",
1032
- "<span class=\"dsh-skin-scanner-target\"></span>",
1033
- "<span class=\"dsh-skin-route-map\"></span>",
1034
- "<span class=\"dsh-skin-energy dsh-skin-energy-cyan\"></span>",
1035
- "<span class=\"dsh-skin-energy dsh-skin-energy-red\"></span>",
1036
- "<span class=\"dsh-skin-energy dsh-skin-energy-gold\"></span>",
1037
- "<span class=\"dsh-skin-starfighter dsh-skin-starfighter-1\"></span>",
1038
- "<span class=\"dsh-skin-starfighter dsh-skin-starfighter-2\"></span>",
1039
- "<span class=\"dsh-skin-starfighter dsh-skin-starfighter-3\"></span>",
1040
- "<span class=\"dsh-skin-mission-crawl\"></span>",
1041
- "<span class=\"dsh-skin-comet dsh-skin-comet-1\"></span>",
1042
- "<span class=\"dsh-skin-comet dsh-skin-comet-2\"></span>",
1043
- "<span class=\"dsh-skin-comet dsh-skin-comet-3\"></span>",
1044
- "<span class=\"dsh-skin-comet dsh-skin-comet-4\"></span>",
1045
- "<span class=\"dsh-skin-comet dsh-skin-comet-5\"></span>",
1046
- "<span class=\"dsh-skin-comet dsh-skin-comet-6\"></span>"
1047
- ].join("");
1190
+ hardenDecorHost(decor);
1191
+ populateDecor(decor);
1048
1192
  document.body.appendChild(decor);
1049
1193
  return decor;
1050
1194
  }
@@ -1110,8 +1254,10 @@ body.dsh-skin-galactic-opera .dsh-skin-telemetry-value-full {
1110
1254
  let inputFocusTimer;
1111
1255
  let scannerPingTimer;
1112
1256
  let lastHyperspaceAt = 0;
1113
- const scanner = decor.querySelector(".dsh-skin-scanner");
1114
- const scannerTarget = decor.querySelector(".dsh-skin-scanner-target");
1257
+ const decorRoot = getDecorRoot(decor);
1258
+ const decorLayer = getDecorLayer(decor);
1259
+ const scanner = decorRoot?.querySelector?.(".dsh-skin-scanner");
1260
+ const scannerTarget = decorRoot?.querySelector?.(".dsh-skin-scanner-target");
1115
1261
  const pulseColors = ["rgba(125,227,255,0.94)", "rgba(255,207,92,0.92)", "rgba(255,71,120,0.88)"];
1116
1262
  const updatePointer = () => {
1117
1263
  frame = 0;
@@ -1190,11 +1336,14 @@ body.dsh-skin-galactic-opera .dsh-skin-telemetry-value-full {
1190
1336
  if (isReducedMotion() || isEditableTarget(event.target)) return;
1191
1337
  const pulse = document.createElement("span");
1192
1338
  pulse.className = "dsh-skin-pulse";
1339
+ setImportantStyle(pulse, "border-radius", "50%");
1340
+ setImportantStyle(pulse, "box-sizing", "border-box");
1193
1341
  pulse.style.setProperty("--dsh-skin-pulse-x", `${event.clientX}px`);
1194
1342
  pulse.style.setProperty("--dsh-skin-pulse-y", `${event.clientY}px`);
1195
1343
  pulse.style.setProperty("--dsh-skin-pulse-color", pulseColors[pulseIndex % pulseColors.length]);
1196
1344
  pulseIndex += 1;
1197
- decor.appendChild(pulse);
1345
+ if (decorLayer instanceof Element) decorLayer.appendChild(pulse);
1346
+ else decor.appendChild(pulse);
1198
1347
  const remove = () => { pulse.remove(); };
1199
1348
  pulse.addEventListener("animationend", remove, { once: true });
1200
1349
  window.setTimeout(remove, 900);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-skin-galactic-opera",
3
- "version": "0.1.6",
3
+ "version": "0.1.7",
4
4
  "description": "Unofficial cinematic space-opera dark skin bundle for the DSH Web GUI.",
5
5
  "repository": {
6
6
  "type": "git",