@found-in-space/skykit 0.2.0-alpha.1 → 0.2.0-dev.20260527.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +143 -6
- package/examples/custom-object-layer/custom-object-layer.js +1 -24
- package/examples/xr-free-roam/index.html +62 -4
- package/examples/xr-free-roam/xr-free-roam.css +249 -18
- package/examples/xr-free-roam/xr-free-roam.js +644 -217
- package/package.json +31 -5
- package/src/__tests__/skykit-anchored-images.test.js +32 -4
- package/src/__tests__/skykit-browser.test.js +217 -0
- package/src/__tests__/skykit-data.test.js +131 -0
- package/src/__tests__/skykit-parallax.test.js +4 -4
- package/src/__tests__/skykit-touch-os.test.js +71 -0
- package/src/__tests__/skykit-xr.test.js +123 -2
- package/src/__tests__/skykit.test.js +138 -1
- package/src/anchored-images.js +14 -15
- package/src/browser-addons.d.ts +16 -0
- package/src/browser-addons.js +155 -0
- package/src/browser-constellations.d.ts +13 -0
- package/src/browser-constellations.js +387 -0
- package/src/browser-journey.d.ts +8 -0
- package/src/browser-journey.js +240 -0
- package/src/browser.d.ts +98 -0
- package/src/browser.js +215 -13
- package/src/data.d.ts +133 -0
- package/src/data.js +447 -0
- package/src/embed.d.ts +5 -0
- package/src/embed.js +52 -2
- package/src/hr-diagram.js +23 -5
- package/src/index.d.ts +32 -7
- package/src/plugins.js +87 -43
- package/src/story.d.ts +57 -0
- package/src/story.js +396 -0
- package/src/three-shim.d.ts +32 -0
- package/src/touch-os.d.ts +70 -0
- package/src/touch-os.js +275 -0
- package/src/utils.js +96 -6
- package/src/viewer-entry.d.ts +10 -0
- package/src/viewer-entry.js +4 -0
- package/src/viewer.js +110 -12
- package/src/xr/plugins.js +224 -13
- package/src/xr/session.js +60 -14
- package/src/xr.d.ts +22 -0
- package/src/xr.js +1 -0
package/README.md
CHANGED
|
@@ -20,6 +20,20 @@ strategies. SkyKit passes strategies through to provider sessions; it does not
|
|
|
20
20
|
redefine planning, inspect strategy kinds, or hide loader registries behind
|
|
21
21
|
string names.
|
|
22
22
|
|
|
23
|
+
## Website Use-Cases
|
|
24
|
+
|
|
25
|
+
The beginner website entries are use-case bounded:
|
|
26
|
+
|
|
27
|
+
| Use-case | Website owner says | Public entry |
|
|
28
|
+
| --- | --- | --- |
|
|
29
|
+
| Viewer | "Put stars on my page and let me customize the scene." | `embed.js`, `viewer.js` |
|
|
30
|
+
| Data | "Give me star data so I can render, list, map, or game it myself." | `data.js` |
|
|
31
|
+
| Story | "Let me tell a curated story through space." | `story.js` |
|
|
32
|
+
|
|
33
|
+
`embed.js` is the no-code viewer entry. It is not a separate use-case.
|
|
34
|
+
`viewer.js` is the JavaScript-customizable viewer entry. `data.js` is renderer
|
|
35
|
+
independent. `story.js` is authored chapters plus a viewer.
|
|
36
|
+
|
|
23
37
|
## Paste into a static page or CMS
|
|
24
38
|
|
|
25
39
|
For the beginner path, use the auto-booting embed. Paste this into a static HTML
|
|
@@ -36,7 +50,7 @@ page or a CMS custom HTML block:
|
|
|
36
50
|
|
|
37
51
|
<script
|
|
38
52
|
type="module"
|
|
39
|
-
src="https://esm.sh/@found-in-space/skykit/embed?bundle"
|
|
53
|
+
src="https://esm.sh/@found-in-space/skykit@0.2.0-alpha.2/embed?bundle&deps=three@0.170.0"
|
|
40
54
|
></script>
|
|
41
55
|
```
|
|
42
56
|
|
|
@@ -55,19 +69,64 @@ Optional attributes keep small tweaks HTML-only:
|
|
|
55
69
|
data-skykit-magnitude="7"
|
|
56
70
|
data-skykit-speed="4"
|
|
57
71
|
data-skykit-exposure="2600"
|
|
72
|
+
data-skykit-look-at="ra=4.496h, dec=16.948"
|
|
73
|
+
data-skykit-mouse-mode="strafe"
|
|
58
74
|
style="width: 100%; height: 520px; background: #02040b"
|
|
59
75
|
></div>
|
|
60
76
|
```
|
|
61
77
|
|
|
78
|
+
`data-skykit-look-at` accepts RA/Dec text such as
|
|
79
|
+
`ra=4.496h, dec=16.948`, decimal degrees such as `67.447,16.948`, or a
|
|
80
|
+
parsec-space `x,y,z` target for exact generated coordinates. `data-skykit-mouse-mode`
|
|
81
|
+
defaults to `grab`; use `look` or `strafe` for the first-person mouse-look
|
|
82
|
+
direction, or `none` to disable mouse drag controls.
|
|
83
|
+
|
|
62
84
|
The host dispatches `skykit-browser-ready` with `{ browser, viewer }` in
|
|
63
85
|
`event.detail` after startup, and `skykit-browser-error` if startup fails. The
|
|
64
|
-
embed
|
|
86
|
+
embed also installs a small `Skykit` global for noob-path scripts:
|
|
87
|
+
|
|
88
|
+
```js
|
|
89
|
+
const browser = await Skykit.whenReady();
|
|
90
|
+
```
|
|
65
91
|
|
|
66
|
-
|
|
67
|
-
|
|
92
|
+
Pages can host multiple viewers. Pass a selector or element to choose one:
|
|
93
|
+
|
|
94
|
+
```js
|
|
95
|
+
const browser = await Skykit.whenReady('#orion-viewer');
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Pin the package CDN URL to a released SkyKit version when publishing long-lived
|
|
99
|
+
pages, for example
|
|
68
100
|
`https://esm.sh/@found-in-space/skykit@x.y.z/embed?bundle&deps=three@0.170.0`.
|
|
69
101
|
|
|
70
|
-
|
|
102
|
+
Optional first-party capabilities stay out of the initial browser until they are
|
|
103
|
+
requested. This keeps the one-script noob path while avoiding bundle bloat.
|
|
104
|
+
|
|
105
|
+
```html
|
|
106
|
+
<div
|
|
107
|
+
data-skykit-browser
|
|
108
|
+
data-skykit-constellations="western"
|
|
109
|
+
data-skykit-constellation-art="off"
|
|
110
|
+
style="width:100%;height:520px;background:#02040b"
|
|
111
|
+
></div>
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
For small scripted interactions, use the browser handle:
|
|
115
|
+
|
|
116
|
+
```html
|
|
117
|
+
<script type="module">
|
|
118
|
+
const browser = await Skykit.whenReady();
|
|
119
|
+
|
|
120
|
+
document.querySelector('#orion').addEventListener('click', () => {
|
|
121
|
+
browser.journey.transitionTo({
|
|
122
|
+
lookAt: 'ra=5.919h, dec=7.407',
|
|
123
|
+
durationSecs: 3,
|
|
124
|
+
});
|
|
125
|
+
});
|
|
126
|
+
</script>
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
## Create a Viewer from JavaScript
|
|
71
130
|
|
|
72
131
|
If your site has a module script, npm, or a bundler, call the helper directly:
|
|
73
132
|
|
|
@@ -76,7 +135,7 @@ If your site has a module script, npm, or a bundler, call the helper directly:
|
|
|
76
135
|
<pre id="status">Loading stars...</pre>
|
|
77
136
|
|
|
78
137
|
<script type="module">
|
|
79
|
-
import { createSkykitBrowser } from '
|
|
138
|
+
import { createSkykitBrowser } from 'https://esm.sh/@found-in-space/skykit@0.2.0-alpha.2/viewer?bundle&deps=three@0.170.0';
|
|
80
139
|
|
|
81
140
|
await createSkykitBrowser({
|
|
82
141
|
host: '#viewer',
|
|
@@ -91,10 +150,66 @@ The helper still returns the pieces when a lesson wants to grow:
|
|
|
91
150
|
const sky = await createSkykitBrowser('#viewer');
|
|
92
151
|
|
|
93
152
|
sky.viewer.requestViewState({ observerPc: { x: 4, y: 0, z: -8 } });
|
|
153
|
+
sky.addObject(marker, {
|
|
154
|
+
positionPc: { x: 17.574, y: 42.316, z: 13.963 },
|
|
155
|
+
});
|
|
94
156
|
sky.loop.stop();
|
|
95
157
|
await sky.dispose();
|
|
96
158
|
```
|
|
97
159
|
|
|
160
|
+
For npm or bundlers, use the same beginner entry:
|
|
161
|
+
|
|
162
|
+
```js
|
|
163
|
+
import { THREE, createSkykitBrowser } from '@found-in-space/skykit/viewer';
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
## Use Star Data Without a Viewer
|
|
167
|
+
|
|
168
|
+
Use `data.js` when SkyKit should supply rows and your app should own rendering:
|
|
169
|
+
|
|
170
|
+
```js
|
|
171
|
+
import { loadStarRows } from 'https://esm.sh/@found-in-space/skykit@0.2.0-alpha.2/data?bundle';
|
|
172
|
+
|
|
173
|
+
const stars = await loadStarRows({
|
|
174
|
+
limitingMagnitude: 6.5,
|
|
175
|
+
maxStars: 100,
|
|
176
|
+
sortBy: 'apparentMagnitude',
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
console.table(stars);
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
For games and maps, load a local volume and hand rows to Canvas, PixiJS,
|
|
183
|
+
Phaser, SVG, or your own renderer:
|
|
184
|
+
|
|
185
|
+
```js
|
|
186
|
+
const stars = await loadStarRows({
|
|
187
|
+
centerPc: { x: 0, y: 0, z: 0 },
|
|
188
|
+
radiusPc: 50,
|
|
189
|
+
maxStars: 2000,
|
|
190
|
+
});
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
## Create a Guided Story
|
|
194
|
+
|
|
195
|
+
Use `story.js` when the page is an authored article or tour:
|
|
196
|
+
|
|
197
|
+
```html
|
|
198
|
+
<div data-skykit-story style="height:600px;background:#02040b">
|
|
199
|
+
<section data-skykit-chapter data-title="The Sun" data-target-pc="0,0,0">
|
|
200
|
+
We start at the Sun.
|
|
201
|
+
</section>
|
|
202
|
+
<section data-skykit-chapter data-title="The Hyades" data-target-pc="17.574,42.316,13.963">
|
|
203
|
+
Now jump to the Hyades cluster.
|
|
204
|
+
</section>
|
|
205
|
+
</div>
|
|
206
|
+
|
|
207
|
+
<script
|
|
208
|
+
type="module"
|
|
209
|
+
src="https://esm.sh/@found-in-space/skykit@0.2.0-alpha.2/story?bundle&deps=three@0.170.0"
|
|
210
|
+
></script>
|
|
211
|
+
```
|
|
212
|
+
|
|
98
213
|
Use the lower-level factories when a lesson is teaching composition or replacing
|
|
99
214
|
a part of the stack:
|
|
100
215
|
|
|
@@ -263,6 +378,28 @@ For a slightly more playful example, see `examples/plugin-lab.js`. It builds
|
|
|
263
378
|
app-owned Three objects and action-driven annotations from the same public hooks
|
|
264
379
|
a learner would use.
|
|
265
380
|
|
|
381
|
+
The pasteable browser embed has a smaller add-on convention for noob pages:
|
|
382
|
+
|
|
383
|
+
```js
|
|
384
|
+
Skykit.registerBrowserAddon({
|
|
385
|
+
id: 'lesson:marker',
|
|
386
|
+
install({ browser, THREE }) {
|
|
387
|
+
const marker = new THREE.Mesh(
|
|
388
|
+
new THREE.SphereGeometry(0.02),
|
|
389
|
+
new THREE.MeshBasicMaterial({ color: 0xffcc00 }),
|
|
390
|
+
);
|
|
391
|
+
const handle = browser.addObject(marker, {
|
|
392
|
+
positionPc: { x: 17.574, y: 42.316, z: 13.963 },
|
|
393
|
+
});
|
|
394
|
+
return () => handle.dispose();
|
|
395
|
+
},
|
|
396
|
+
});
|
|
397
|
+
```
|
|
398
|
+
|
|
399
|
+
See `docs/skykit-browser-plugins.md` for the browser add-on spec,
|
|
400
|
+
`Skykit.whenReady()`, first-party constellation support, and the
|
|
401
|
+
`browser.journey` API.
|
|
402
|
+
|
|
266
403
|
Browser lessons:
|
|
267
404
|
|
|
268
405
|
- `examples/free-roam-lesson/` composes streamed stars, keyboard navigation,
|
|
@@ -145,7 +145,7 @@ function createInitialViewState() {
|
|
|
145
145
|
observerPc: { x: 0, y: 0, z: 0 },
|
|
146
146
|
coordinateUnitsPerParsec: UNITS_PER_PARSEC,
|
|
147
147
|
limitingMagnitude: 7.5,
|
|
148
|
-
|
|
148
|
+
lookAt: { targetPc: HYADES_CENTER_PC },
|
|
149
149
|
};
|
|
150
150
|
}
|
|
151
151
|
|
|
@@ -332,29 +332,6 @@ function toRenderPosition(pointPc) {
|
|
|
332
332
|
);
|
|
333
333
|
}
|
|
334
334
|
|
|
335
|
-
function lookAtFromOriginWithNorthUp(targetPc) {
|
|
336
|
-
const forward = new THREE.Vector3(targetPc.x, targetPc.y, targetPc.z).normalize();
|
|
337
|
-
const north = new THREE.Vector3(0, 0, 1);
|
|
338
|
-
let up = north.clone().sub(forward.clone().multiplyScalar(north.dot(forward)));
|
|
339
|
-
if (up.lengthSq() < 1e-8) {
|
|
340
|
-
up = new THREE.Vector3(0, 1, 0);
|
|
341
|
-
}
|
|
342
|
-
up.normalize();
|
|
343
|
-
|
|
344
|
-
const backward = forward.clone().negate();
|
|
345
|
-
const right = up.clone().cross(backward).normalize();
|
|
346
|
-
up = backward.clone().cross(right).normalize();
|
|
347
|
-
|
|
348
|
-
const matrix = new THREE.Matrix4().makeBasis(right, up, backward);
|
|
349
|
-
const quaternion = new THREE.Quaternion().setFromRotationMatrix(matrix);
|
|
350
|
-
return {
|
|
351
|
-
x: quaternion.x,
|
|
352
|
-
y: quaternion.y,
|
|
353
|
-
z: quaternion.z,
|
|
354
|
-
w: quaternion.w,
|
|
355
|
-
};
|
|
356
|
-
}
|
|
357
|
-
|
|
358
335
|
function directionFromRaDec(raDeg, decDeg) {
|
|
359
336
|
const ra = THREE.MathUtils.degToRad(raDeg);
|
|
360
337
|
const dec = THREE.MathUtils.degToRad(decDeg);
|
|
@@ -10,10 +10,68 @@
|
|
|
10
10
|
<body>
|
|
11
11
|
<main class="xr-free-roam-shell">
|
|
12
12
|
<div class="viewer-shell" data-viewer></div>
|
|
13
|
-
<
|
|
14
|
-
<
|
|
15
|
-
|
|
16
|
-
|
|
13
|
+
<section class="xr-preflight" data-preflight aria-labelledby="xr-preflight-title">
|
|
14
|
+
<div class="xr-preflight-copy">
|
|
15
|
+
<p class="xr-kicker">SkyKit XR</p>
|
|
16
|
+
<h1 id="xr-preflight-title">Free Roam Preflight</h1>
|
|
17
|
+
<p>
|
|
18
|
+
Choose the rendering defaults for this headset run, then enter the immersive session.
|
|
19
|
+
</p>
|
|
20
|
+
<dl class="xr-status-list">
|
|
21
|
+
<div>
|
|
22
|
+
<dt>WebXR</dt>
|
|
23
|
+
<dd data-xr-supported>Checking</dd>
|
|
24
|
+
</div>
|
|
25
|
+
<div>
|
|
26
|
+
<dt>Scale</dt>
|
|
27
|
+
<dd data-setting-value="worldScaleLog10">1 m/pc</dd>
|
|
28
|
+
</div>
|
|
29
|
+
<div>
|
|
30
|
+
<dt>Stars</dt>
|
|
31
|
+
<dd data-setting-value="limitingMagnitude">Mag 7.5</dd>
|
|
32
|
+
</div>
|
|
33
|
+
</dl>
|
|
34
|
+
</div>
|
|
35
|
+
|
|
36
|
+
<form class="xr-settings" data-xr-settings>
|
|
37
|
+
<fieldset>
|
|
38
|
+
<legend>Rendering</legend>
|
|
39
|
+
<label>
|
|
40
|
+
<span>Magnitude limit</span>
|
|
41
|
+
<output data-setting-value="limitingMagnitude">7.5</output>
|
|
42
|
+
<input data-setting="limitingMagnitude" type="range" min="4" max="10" step="0.1" value="7.5" />
|
|
43
|
+
</label>
|
|
44
|
+
<label>
|
|
45
|
+
<span>Exposure</span>
|
|
46
|
+
<output data-setting-value="exposureLog10">100,000</output>
|
|
47
|
+
<input data-setting="exposureLog10" type="range" min="3.5" max="5.5" step="0.05" value="5" />
|
|
48
|
+
</label>
|
|
49
|
+
<label>
|
|
50
|
+
<span>World scale</span>
|
|
51
|
+
<output data-setting-value="worldScaleLog10">1 m/pc</output>
|
|
52
|
+
<input data-setting="worldScaleLog10" type="range" min="-3" max="0" step="0.05" value="0" />
|
|
53
|
+
</label>
|
|
54
|
+
</fieldset>
|
|
55
|
+
|
|
56
|
+
<fieldset>
|
|
57
|
+
<legend>Session Flags</legend>
|
|
58
|
+
<label class="xr-toggle">
|
|
59
|
+
<input data-setting="nearFloor" type="checkbox" checked />
|
|
60
|
+
<span>Near-star readability floor</span>
|
|
61
|
+
</label>
|
|
62
|
+
<label class="xr-toggle">
|
|
63
|
+
<input data-setting="constellationArt" type="checkbox" checked />
|
|
64
|
+
<span>Constellation art</span>
|
|
65
|
+
</label>
|
|
66
|
+
</fieldset>
|
|
67
|
+
|
|
68
|
+
<div class="xr-actions" aria-label="XR actions">
|
|
69
|
+
<button class="xr-primary-action" type="button" data-action="enter-xr">Enter VR</button>
|
|
70
|
+
<button type="button" data-action="exit-xr" hidden disabled>Exit VR</button>
|
|
71
|
+
</div>
|
|
72
|
+
<p class="xr-session-status" data-session-status>Idle</p>
|
|
73
|
+
</form>
|
|
74
|
+
</section>
|
|
17
75
|
</main>
|
|
18
76
|
<script type="module" src="./xr-free-roam.js"></script>
|
|
19
77
|
</body>
|
|
@@ -2,9 +2,20 @@ html,
|
|
|
2
2
|
body {
|
|
3
3
|
margin: 0;
|
|
4
4
|
width: 100%;
|
|
5
|
+
min-width: 320px;
|
|
5
6
|
height: 100%;
|
|
6
7
|
overflow: hidden;
|
|
7
|
-
background: #
|
|
8
|
+
background: #05070b;
|
|
9
|
+
color: #f4efe2;
|
|
10
|
+
font: 16px/1.45 "Avenir Next", Avenir, "Segoe UI", sans-serif;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
* {
|
|
14
|
+
box-sizing: border-box;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
[hidden] {
|
|
18
|
+
display: none !important;
|
|
8
19
|
}
|
|
9
20
|
|
|
10
21
|
.xr-free-roam-shell,
|
|
@@ -13,39 +24,259 @@ body {
|
|
|
13
24
|
inset: 0;
|
|
14
25
|
}
|
|
15
26
|
|
|
27
|
+
.xr-free-roam-shell {
|
|
28
|
+
background:
|
|
29
|
+
linear-gradient(90deg, rgba(5, 7, 11, 0.96) 0%, rgba(5, 7, 11, 0.84) 46%, rgba(5, 7, 11, 0.58) 100%),
|
|
30
|
+
#05070b;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
.viewer-shell {
|
|
34
|
+
z-index: 0;
|
|
35
|
+
opacity: 0.34;
|
|
36
|
+
filter: saturate(0.78) contrast(1.08);
|
|
37
|
+
pointer-events: none;
|
|
38
|
+
transition: opacity 0.18s ease, filter 0.18s ease;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
.xr-free-roam-shell.is-presenting .viewer-shell {
|
|
42
|
+
opacity: 1;
|
|
43
|
+
filter: none;
|
|
44
|
+
pointer-events: auto;
|
|
45
|
+
}
|
|
46
|
+
|
|
16
47
|
.viewer-shell canvas {
|
|
17
48
|
display: block;
|
|
18
49
|
width: 100%;
|
|
19
50
|
height: 100%;
|
|
20
|
-
cursor:
|
|
51
|
+
cursor: default;
|
|
21
52
|
touch-action: none;
|
|
22
53
|
user-select: none;
|
|
23
54
|
}
|
|
24
55
|
|
|
25
|
-
.
|
|
26
|
-
|
|
56
|
+
.xr-preflight {
|
|
57
|
+
position: fixed;
|
|
58
|
+
inset: 0;
|
|
59
|
+
z-index: 10;
|
|
60
|
+
display: grid;
|
|
61
|
+
grid-template-columns: minmax(0, 1fr) minmax(320px, 430px);
|
|
62
|
+
gap: clamp(24px, 5vw, 72px);
|
|
63
|
+
align-items: center;
|
|
64
|
+
width: 100%;
|
|
65
|
+
height: 100%;
|
|
66
|
+
padding: clamp(24px, 6vh, 72px) clamp(18px, 7vw, 92px);
|
|
67
|
+
overflow: auto;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
.xr-free-roam-shell.is-presenting .xr-preflight {
|
|
71
|
+
display: none;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
.xr-preflight-copy {
|
|
75
|
+
max-width: 720px;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
.xr-kicker {
|
|
79
|
+
margin: 0 0 10px;
|
|
80
|
+
color: #6fd7c3;
|
|
81
|
+
font-size: 0.82rem;
|
|
82
|
+
font-weight: 700;
|
|
83
|
+
text-transform: uppercase;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
.xr-preflight h1 {
|
|
87
|
+
margin: 0;
|
|
88
|
+
max-width: 11ch;
|
|
89
|
+
color: #fff9e8;
|
|
90
|
+
font-size: clamp(2.6rem, 6vh, 5.6rem);
|
|
91
|
+
line-height: 0.96;
|
|
92
|
+
font-weight: 760;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
.xr-preflight-copy > p:not(.xr-kicker) {
|
|
96
|
+
max-width: 46rem;
|
|
97
|
+
margin: 22px 0 0;
|
|
98
|
+
color: #cfc7b8;
|
|
99
|
+
font-size: 1.08rem;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
.xr-status-list {
|
|
103
|
+
display: grid;
|
|
104
|
+
grid-template-columns: repeat(3, minmax(0, 1fr));
|
|
105
|
+
gap: 1px;
|
|
106
|
+
max-width: 620px;
|
|
107
|
+
margin: 34px 0 0;
|
|
108
|
+
padding: 1px;
|
|
109
|
+
background: rgba(244, 239, 226, 0.14);
|
|
110
|
+
border-radius: 8px;
|
|
111
|
+
overflow: hidden;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
.xr-status-list div {
|
|
115
|
+
min-width: 0;
|
|
116
|
+
padding: 13px 14px;
|
|
117
|
+
background: rgba(15, 18, 18, 0.88);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
.xr-status-list dt {
|
|
121
|
+
color: #a7b2ac;
|
|
122
|
+
font-size: 0.76rem;
|
|
123
|
+
font-weight: 700;
|
|
124
|
+
text-transform: uppercase;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
.xr-status-list dd {
|
|
128
|
+
margin: 4px 0 0;
|
|
129
|
+
color: #fff6dd;
|
|
130
|
+
font-weight: 700;
|
|
131
|
+
overflow-wrap: anywhere;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
.xr-settings {
|
|
135
|
+
display: grid;
|
|
136
|
+
gap: 14px;
|
|
137
|
+
width: min(100%, 430px);
|
|
138
|
+
padding: 18px;
|
|
139
|
+
border: 1px solid rgba(244, 239, 226, 0.18);
|
|
140
|
+
border-radius: 8px;
|
|
141
|
+
background: rgba(14, 17, 16, 0.88);
|
|
142
|
+
box-shadow: 0 24px 80px rgba(0, 0, 0, 0.28);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
.xr-settings fieldset {
|
|
146
|
+
display: grid;
|
|
147
|
+
gap: 14px;
|
|
148
|
+
min-width: 0;
|
|
149
|
+
margin: 0;
|
|
150
|
+
padding: 0 0 16px;
|
|
151
|
+
border: 0;
|
|
152
|
+
border-bottom: 1px solid rgba(244, 239, 226, 0.13);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
.xr-settings fieldset:last-of-type {
|
|
156
|
+
padding-bottom: 2px;
|
|
157
|
+
border-bottom: 0;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
.xr-settings legend {
|
|
161
|
+
padding: 0;
|
|
162
|
+
color: #d9b779;
|
|
163
|
+
font-size: 0.82rem;
|
|
164
|
+
font-weight: 760;
|
|
165
|
+
text-transform: uppercase;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
.xr-settings label:not(.xr-toggle) {
|
|
169
|
+
display: grid;
|
|
170
|
+
grid-template-columns: 1fr auto;
|
|
171
|
+
gap: 8px 14px;
|
|
172
|
+
align-items: center;
|
|
173
|
+
color: #f4efe2;
|
|
174
|
+
font-weight: 650;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
.xr-settings output {
|
|
178
|
+
color: #9ddbd1;
|
|
179
|
+
font-variant-numeric: tabular-nums;
|
|
180
|
+
font-weight: 760;
|
|
181
|
+
text-align: right;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
.xr-settings input[type="range"] {
|
|
185
|
+
grid-column: 1 / -1;
|
|
186
|
+
width: 100%;
|
|
187
|
+
accent-color: #d9b779;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
.xr-toggle {
|
|
191
|
+
display: grid;
|
|
192
|
+
grid-template-columns: 22px 1fr;
|
|
193
|
+
gap: 10px;
|
|
194
|
+
align-items: center;
|
|
195
|
+
min-height: 32px;
|
|
196
|
+
color: #e8dfcf;
|
|
197
|
+
font-weight: 650;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
.xr-toggle input {
|
|
201
|
+
width: 18px;
|
|
202
|
+
height: 18px;
|
|
203
|
+
accent-color: #6fd7c3;
|
|
27
204
|
}
|
|
28
205
|
|
|
29
206
|
.xr-actions {
|
|
30
|
-
position: fixed;
|
|
31
|
-
top: 16px;
|
|
32
|
-
right: 16px;
|
|
33
|
-
z-index: 10;
|
|
34
207
|
display: flex;
|
|
35
|
-
|
|
208
|
+
flex-wrap: wrap;
|
|
209
|
+
gap: 10px;
|
|
36
210
|
}
|
|
37
211
|
|
|
38
212
|
.xr-actions button {
|
|
39
|
-
min-height:
|
|
40
|
-
padding: 0
|
|
41
|
-
border: 1px solid rgba(
|
|
213
|
+
min-height: 42px;
|
|
214
|
+
padding: 0 16px;
|
|
215
|
+
border: 1px solid rgba(244, 239, 226, 0.24);
|
|
42
216
|
border-radius: 8px;
|
|
43
|
-
background: rgba(
|
|
44
|
-
color: #
|
|
45
|
-
font:
|
|
217
|
+
background: rgba(244, 239, 226, 0.08);
|
|
218
|
+
color: #fff9e8;
|
|
219
|
+
font: inherit;
|
|
220
|
+
font-weight: 760;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
.xr-actions button:hover:not(:disabled) {
|
|
224
|
+
border-color: rgba(244, 239, 226, 0.72);
|
|
225
|
+
background: rgba(244, 239, 226, 0.13);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
.xr-actions button:disabled {
|
|
229
|
+
cursor: not-allowed;
|
|
230
|
+
opacity: 0.55;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
.xr-actions .xr-primary-action {
|
|
234
|
+
min-width: 144px;
|
|
235
|
+
border-color: rgba(217, 183, 121, 0.72);
|
|
236
|
+
background: #d9b779;
|
|
237
|
+
color: #101313;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
.xr-actions .xr-primary-action:hover:not(:disabled) {
|
|
241
|
+
border-color: #ffe0a6;
|
|
242
|
+
background: #e8c987;
|
|
46
243
|
}
|
|
47
244
|
|
|
48
|
-
.xr-
|
|
49
|
-
|
|
50
|
-
|
|
245
|
+
.xr-session-status {
|
|
246
|
+
min-height: 1.4em;
|
|
247
|
+
margin: 0;
|
|
248
|
+
color: #a7b2ac;
|
|
249
|
+
font-size: 0.88rem;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
@media (max-width: 820px) {
|
|
253
|
+
.xr-preflight {
|
|
254
|
+
grid-template-columns: 1fr;
|
|
255
|
+
align-content: start;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
.xr-preflight h1 {
|
|
259
|
+
max-width: 13ch;
|
|
260
|
+
font-size: clamp(2.3rem, 12vw, 4.4rem);
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
.xr-status-list {
|
|
264
|
+
grid-template-columns: 1fr;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
.xr-settings {
|
|
268
|
+
width: 100%;
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
@media (max-height: 640px) and (min-width: 821px) {
|
|
273
|
+
.xr-preflight {
|
|
274
|
+
align-items: start;
|
|
275
|
+
padding-top: 28px;
|
|
276
|
+
padding-bottom: 28px;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
.xr-preflight h1 {
|
|
280
|
+
font-size: 3.4rem;
|
|
281
|
+
}
|
|
51
282
|
}
|