cadcode 0.1.0 → 0.3.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/LICENSE +21 -0
- package/README.md +22 -9
- package/client/favicon.svg +17 -0
- package/client/index.html +48 -32
- package/client/render-worker.js +333 -0
- package/client/scene.js +166 -0
- package/client/viewer.css +423 -109
- package/client/viewer.js +144 -153
- package/package.json +9 -3
- package/src/core/evaluate.js +59 -0
- package/src/core/program.js +4 -44
- package/src/dev/server.js +26 -3
- package/src/dev/worker.js +25 -15
- package/src/export/stl.js +9 -7
package/client/viewer.css
CHANGED
|
@@ -1,14 +1,30 @@
|
|
|
1
|
+
/* The dev viewer as the playground's photo studio, without the code sheet: the model
|
|
2
|
+
stands on a soft, seamless backdrop that fills the window, and the controls float
|
|
3
|
+
on it in small groups, one per corner. Top left says what is on screen (the file,
|
|
4
|
+
the part), top right takes it away (PNG, STL), bottom left measures it, bottom
|
|
5
|
+
right changes how it is drawn. One accent, filament yellow, for the primary action
|
|
6
|
+
and the current selection; red only for faults. */
|
|
1
7
|
:root {
|
|
2
|
-
--
|
|
3
|
-
--
|
|
4
|
-
--
|
|
5
|
-
--
|
|
6
|
-
--
|
|
7
|
-
--
|
|
8
|
-
--
|
|
9
|
-
--
|
|
10
|
-
|
|
11
|
-
|
|
8
|
+
--stage-light: #ffffff;
|
|
9
|
+
--stage-mid: #f2f3f5;
|
|
10
|
+
--stage-edge: #e2e5e9;
|
|
11
|
+
--ink: #1f2833;
|
|
12
|
+
--ink-soft: #77818d;
|
|
13
|
+
--glass: rgba(255, 255, 255, 0.72);
|
|
14
|
+
--hairline: rgba(31, 40, 51, 0.08);
|
|
15
|
+
--lift: 0 1px 2px rgba(31, 40, 51, 0.06), 0 8px 24px -8px rgba(31, 40, 51, 0.14);
|
|
16
|
+
--pop: 0 2px 6px rgba(31, 40, 51, 0.06), 0 18px 48px -12px rgba(31, 40, 51, 0.28);
|
|
17
|
+
--filament: #f2c14e;
|
|
18
|
+
--filament-deep: #dcaa2c;
|
|
19
|
+
--selected: #fdf6e3;
|
|
20
|
+
--fault: #c2412d;
|
|
21
|
+
--ok: #3f9a62;
|
|
22
|
+
--gap: 20px;
|
|
23
|
+
--ui: 'Instrument Sans', ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif;
|
|
24
|
+
--mono: 'JetBrains Mono', ui-monospace, 'SF Mono', Menlo, monospace;
|
|
25
|
+
font: 14px/1.45 var(--ui);
|
|
26
|
+
color: var(--ink);
|
|
27
|
+
accent-color: var(--ink);
|
|
12
28
|
}
|
|
13
29
|
|
|
14
30
|
* {
|
|
@@ -20,118 +36,241 @@ body {
|
|
|
20
36
|
margin: 0;
|
|
21
37
|
height: 100%;
|
|
22
38
|
overflow: hidden;
|
|
23
|
-
background: var(--
|
|
39
|
+
background: var(--stage-mid);
|
|
24
40
|
}
|
|
25
41
|
|
|
26
|
-
|
|
42
|
+
[hidden] {
|
|
43
|
+
display: none !important;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
:focus-visible {
|
|
47
|
+
outline: 2px solid var(--ink);
|
|
48
|
+
outline-offset: 2px;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
button {
|
|
52
|
+
font: inherit;
|
|
53
|
+
color: inherit;
|
|
54
|
+
cursor: pointer;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
button:disabled {
|
|
58
|
+
cursor: progress;
|
|
59
|
+
opacity: 0.5;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
p {
|
|
63
|
+
margin: 0;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/* --- Stage ------------------------------------------------------------------ */
|
|
67
|
+
|
|
68
|
+
/* The canvas is transparent; the backdrop is a light sweep, brightest where the
|
|
69
|
+
model stands, a little above the middle. */
|
|
70
|
+
.stage {
|
|
27
71
|
position: fixed;
|
|
28
72
|
inset: 0;
|
|
73
|
+
background: radial-gradient(ellipse 70% 80% at 50% 42%, var(--stage-light) 0%, var(--stage-mid) 55%, var(--stage-edge) 100%);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
#view {
|
|
77
|
+
position: absolute;
|
|
78
|
+
inset: 0;
|
|
29
79
|
width: 100%;
|
|
30
80
|
height: 100%;
|
|
31
81
|
display: block;
|
|
82
|
+
transition: opacity 0.25s ease, filter 0.25s ease;
|
|
32
83
|
}
|
|
33
84
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
top: 12px;
|
|
38
|
-
left: 12px;
|
|
39
|
-
right: 12px;
|
|
85
|
+
.corner {
|
|
86
|
+
position: absolute;
|
|
87
|
+
z-index: 2;
|
|
40
88
|
display: flex;
|
|
41
|
-
|
|
89
|
+
align-items: center;
|
|
90
|
+
gap: 10px;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
.top-left {
|
|
94
|
+
top: var(--gap);
|
|
95
|
+
left: var(--gap);
|
|
96
|
+
/* Leaves room for the export pills; a long path gives way first. */
|
|
97
|
+
right: calc(var(--gap) + 260px);
|
|
98
|
+
pointer-events: none;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
.top-left > * {
|
|
102
|
+
pointer-events: auto;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
.top-right {
|
|
106
|
+
top: var(--gap);
|
|
107
|
+
right: var(--gap);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
.bottom-left {
|
|
111
|
+
left: var(--gap);
|
|
112
|
+
bottom: var(--gap);
|
|
113
|
+
right: calc(var(--gap) + 240px);
|
|
114
|
+
flex-direction: column;
|
|
42
115
|
align-items: flex-start;
|
|
43
|
-
gap:
|
|
116
|
+
gap: 14px;
|
|
44
117
|
pointer-events: none;
|
|
45
118
|
}
|
|
46
119
|
|
|
47
|
-
.
|
|
120
|
+
.bottom-left > * {
|
|
48
121
|
pointer-events: auto;
|
|
49
122
|
}
|
|
50
123
|
|
|
51
|
-
.
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
124
|
+
.bottom-right {
|
|
125
|
+
right: var(--gap);
|
|
126
|
+
bottom: var(--gap);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/* --- Floating controls -------------------------------------------------------- */
|
|
130
|
+
|
|
131
|
+
.brand {
|
|
132
|
+
flex-shrink: 0;
|
|
133
|
+
display: inline-flex;
|
|
55
134
|
align-items: center;
|
|
56
|
-
gap:
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
border-radius: 10px;
|
|
62
|
-
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.06);
|
|
135
|
+
gap: 9px;
|
|
136
|
+
margin-right: 8px;
|
|
137
|
+
font-weight: 600;
|
|
138
|
+
font-size: 17px;
|
|
139
|
+
letter-spacing: -0.01em;
|
|
63
140
|
}
|
|
64
141
|
|
|
65
|
-
.
|
|
142
|
+
.pill {
|
|
66
143
|
flex-shrink: 0;
|
|
144
|
+
display: inline-flex;
|
|
145
|
+
align-items: center;
|
|
146
|
+
gap: 8px;
|
|
147
|
+
height: 36px;
|
|
148
|
+
padding: 0 14px;
|
|
149
|
+
background: var(--glass);
|
|
150
|
+
-webkit-backdrop-filter: blur(12px) saturate(1.4);
|
|
151
|
+
backdrop-filter: blur(12px) saturate(1.4);
|
|
152
|
+
border: 1px solid var(--hairline);
|
|
153
|
+
border-radius: 999px;
|
|
154
|
+
box-shadow: var(--lift);
|
|
155
|
+
font-weight: 500;
|
|
156
|
+
white-space: nowrap;
|
|
157
|
+
transition: background 0.15s ease;
|
|
67
158
|
}
|
|
68
159
|
|
|
69
|
-
.
|
|
70
|
-
|
|
71
|
-
letter-spacing: 0.02em;
|
|
160
|
+
button.pill:hover {
|
|
161
|
+
background: #fff;
|
|
72
162
|
}
|
|
73
163
|
|
|
164
|
+
.pill.primary {
|
|
165
|
+
background: var(--filament);
|
|
166
|
+
border-color: var(--filament-deep);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
.pill.primary:hover {
|
|
170
|
+
background: var(--filament-deep);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
.pill[aria-pressed='true'] {
|
|
174
|
+
background: var(--ink);
|
|
175
|
+
border-color: var(--ink);
|
|
176
|
+
color: #fff;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
.pill[aria-pressed='true']:hover {
|
|
180
|
+
background: var(--ink);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
.pill.round {
|
|
184
|
+
justify-content: center;
|
|
185
|
+
width: 40px;
|
|
186
|
+
height: 40px;
|
|
187
|
+
padding: 0;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/* The program being watched: its folder quietly, its name plainly. A long path
|
|
191
|
+
gives up its folder first; the name always stays. */
|
|
74
192
|
.file {
|
|
75
|
-
|
|
193
|
+
flex-shrink: 1;
|
|
76
194
|
min-width: 0;
|
|
77
|
-
|
|
78
|
-
font-family:
|
|
79
|
-
font-size:
|
|
80
|
-
|
|
195
|
+
gap: 0;
|
|
196
|
+
font-family: var(--mono);
|
|
197
|
+
font-size: 12.5px;
|
|
198
|
+
font-weight: 400;
|
|
199
|
+
overflow: hidden;
|
|
81
200
|
}
|
|
82
201
|
|
|
83
|
-
/* A long path gives up its directory first; the file name always stays. */
|
|
84
202
|
.file .dir {
|
|
85
203
|
min-width: 0;
|
|
86
204
|
overflow: hidden;
|
|
87
205
|
text-overflow: ellipsis;
|
|
206
|
+
color: var(--ink-soft);
|
|
88
207
|
}
|
|
89
208
|
|
|
90
209
|
.file .name {
|
|
91
210
|
flex-shrink: 0;
|
|
211
|
+
font-weight: 500;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
.field {
|
|
215
|
+
color: var(--ink-soft);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
.field strong {
|
|
219
|
+
font-weight: 600;
|
|
220
|
+
color: var(--ink);
|
|
92
221
|
}
|
|
93
222
|
|
|
94
|
-
.
|
|
223
|
+
.field svg {
|
|
224
|
+
margin-left: -2px;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
.tools {
|
|
95
228
|
display: flex;
|
|
96
|
-
|
|
97
|
-
gap: 6px;
|
|
98
|
-
color: var(--muted);
|
|
229
|
+
gap: 8px;
|
|
99
230
|
}
|
|
100
231
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
232
|
+
/* --- The readout: the model's size, set large ----------------------------------- */
|
|
233
|
+
|
|
234
|
+
.readout .size {
|
|
235
|
+
font-size: clamp(28px, 3.4vw, 44px);
|
|
236
|
+
font-weight: 400;
|
|
237
|
+
line-height: 1.05;
|
|
238
|
+
letter-spacing: -0.03em;
|
|
239
|
+
font-variant-numeric: tabular-nums;
|
|
109
240
|
}
|
|
110
241
|
|
|
111
|
-
|
|
112
|
-
|
|
242
|
+
.readout .size small {
|
|
243
|
+
margin-left: 0.2em;
|
|
244
|
+
font-size: 0.42em;
|
|
245
|
+
letter-spacing: 0;
|
|
246
|
+
color: var(--ink-soft);
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
.readout .meta {
|
|
250
|
+
display: flex;
|
|
251
|
+
flex-wrap: wrap;
|
|
252
|
+
column-gap: 16px;
|
|
253
|
+
margin-top: 8px;
|
|
254
|
+
color: var(--ink-soft);
|
|
255
|
+
font-variant-numeric: tabular-nums;
|
|
113
256
|
}
|
|
114
257
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
border-color: rgba(20, 30, 40, 0.28);
|
|
258
|
+
.readout .meta span:empty {
|
|
259
|
+
display: none;
|
|
118
260
|
}
|
|
119
261
|
|
|
120
262
|
.status {
|
|
121
263
|
display: inline-flex;
|
|
122
264
|
align-items: center;
|
|
123
|
-
gap:
|
|
124
|
-
color: var(--muted);
|
|
125
|
-
white-space: nowrap;
|
|
126
|
-
font-variant-numeric: tabular-nums;
|
|
265
|
+
gap: 7px;
|
|
127
266
|
}
|
|
128
267
|
|
|
129
268
|
.status::before {
|
|
130
269
|
content: '';
|
|
131
|
-
width:
|
|
132
|
-
height:
|
|
270
|
+
width: 7px;
|
|
271
|
+
height: 7px;
|
|
133
272
|
border-radius: 50%;
|
|
134
|
-
background: var(--
|
|
273
|
+
background: var(--ink-soft);
|
|
135
274
|
}
|
|
136
275
|
|
|
137
276
|
.status[data-state='ready']::before {
|
|
@@ -140,77 +279,252 @@ select:hover {
|
|
|
140
279
|
|
|
141
280
|
.status[data-state='building']::before,
|
|
142
281
|
.status[data-state='evaluating']::before {
|
|
143
|
-
background: var(--
|
|
282
|
+
background: var(--filament-deep);
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
.status[data-state='error'],
|
|
286
|
+
.status[data-state='disconnected'] {
|
|
287
|
+
color: var(--fault);
|
|
288
|
+
font-weight: 500;
|
|
144
289
|
}
|
|
145
290
|
|
|
146
291
|
.status[data-state='error']::before,
|
|
147
292
|
.status[data-state='disconnected']::before {
|
|
148
|
-
background: var(--
|
|
293
|
+
background: var(--fault);
|
|
149
294
|
}
|
|
150
295
|
|
|
151
|
-
.
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
bottom: 40px;
|
|
156
|
-
max-height: 45vh;
|
|
157
|
-
overflow: auto;
|
|
158
|
-
background: #fff6f5;
|
|
159
|
-
border: 1px solid rgba(200, 55, 45, 0.35);
|
|
160
|
-
border-left: 4px solid var(--bad);
|
|
161
|
-
border-radius: 8px;
|
|
162
|
-
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.08);
|
|
296
|
+
.hint {
|
|
297
|
+
font-size: 12.5px;
|
|
298
|
+
color: var(--ink-soft);
|
|
299
|
+
pointer-events: none !important;
|
|
163
300
|
}
|
|
164
301
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
302
|
+
/* --- Cards: logs and errors ----------------------------------------------------- */
|
|
303
|
+
|
|
304
|
+
.card {
|
|
305
|
+
background: rgba(255, 255, 255, 0.9);
|
|
306
|
+
-webkit-backdrop-filter: blur(12px);
|
|
307
|
+
backdrop-filter: blur(12px);
|
|
308
|
+
border: 1px solid var(--hairline);
|
|
309
|
+
border-radius: 14px;
|
|
310
|
+
box-shadow: var(--lift);
|
|
171
311
|
}
|
|
172
312
|
|
|
313
|
+
/* The program's console output, hanging under the file it came from. */
|
|
173
314
|
.logs {
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
315
|
+
position: absolute;
|
|
316
|
+
z-index: 2;
|
|
317
|
+
top: calc(var(--gap) + 56px);
|
|
318
|
+
left: var(--gap);
|
|
319
|
+
max-width: min(480px, calc(100% - 2 * var(--gap)));
|
|
320
|
+
max-height: 35%;
|
|
178
321
|
overflow: auto;
|
|
179
|
-
padding:
|
|
180
|
-
|
|
181
|
-
border: 1px solid var(--border);
|
|
182
|
-
border-radius: 10px;
|
|
183
|
-
font: 12px/1.5 ui-monospace, 'SF Mono', Menlo, monospace;
|
|
322
|
+
padding: 10px 14px;
|
|
323
|
+
font: 12px/1.55 var(--mono);
|
|
184
324
|
white-space: pre-wrap;
|
|
185
325
|
}
|
|
186
326
|
|
|
187
327
|
.logs .log-warn {
|
|
188
|
-
color:
|
|
328
|
+
color: #a8730b;
|
|
189
329
|
}
|
|
190
330
|
|
|
191
331
|
.logs .log-error {
|
|
192
|
-
color: var(--
|
|
332
|
+
color: var(--fault);
|
|
193
333
|
}
|
|
194
334
|
|
|
195
|
-
.
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
335
|
+
.error {
|
|
336
|
+
max-width: min(720px, 100%);
|
|
337
|
+
max-height: 42vh;
|
|
338
|
+
overflow: auto;
|
|
339
|
+
border-left: 3px solid var(--fault);
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
.error pre {
|
|
343
|
+
margin: 0;
|
|
344
|
+
padding: 12px 16px;
|
|
345
|
+
font: 12.5px/1.55 var(--mono);
|
|
346
|
+
white-space: pre-wrap;
|
|
347
|
+
color: #8a2a1c;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
/* --- Busy ------------------------------------------------------------------------ */
|
|
351
|
+
/* While the program rebuilds: a line runs along the top and the model on screen
|
|
352
|
+
steps back. With no model yet, a line of text in the middle instead. Both wait a
|
|
353
|
+
moment, so a quick rebuild does not flicker. A lost connection steps the model
|
|
354
|
+
back the same way, without the running line. */
|
|
355
|
+
|
|
356
|
+
.progress {
|
|
357
|
+
position: absolute;
|
|
358
|
+
z-index: 3;
|
|
359
|
+
top: 0;
|
|
360
|
+
left: 0;
|
|
361
|
+
right: 0;
|
|
362
|
+
height: 2px;
|
|
363
|
+
overflow: hidden;
|
|
364
|
+
opacity: 0;
|
|
365
|
+
transition: opacity 0.2s ease;
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
.progress::before {
|
|
369
|
+
content: '';
|
|
370
|
+
position: absolute;
|
|
371
|
+
inset: 0 auto 0 0;
|
|
372
|
+
width: 35%;
|
|
373
|
+
background: linear-gradient(90deg, transparent, var(--filament-deep), transparent);
|
|
374
|
+
animation: run 1.1s ease-in-out infinite;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
@keyframes run {
|
|
378
|
+
from {
|
|
379
|
+
translate: -100% 0;
|
|
380
|
+
}
|
|
381
|
+
to {
|
|
382
|
+
translate: 300% 0;
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
.empty {
|
|
387
|
+
position: absolute;
|
|
388
|
+
top: 50%;
|
|
389
|
+
left: 50%;
|
|
390
|
+
translate: -50% -50%;
|
|
391
|
+
color: var(--ink-soft);
|
|
392
|
+
font-size: 15px;
|
|
393
|
+
opacity: 0;
|
|
201
394
|
pointer-events: none;
|
|
395
|
+
transition: opacity 0.2s ease;
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
.stage[data-busy] .progress {
|
|
399
|
+
opacity: 1;
|
|
400
|
+
transition-delay: 0.15s;
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
.stage[data-busy] #view,
|
|
404
|
+
.stage[data-offline] #view {
|
|
405
|
+
opacity: 0.45;
|
|
406
|
+
filter: saturate(0.4);
|
|
407
|
+
transition-delay: 0.15s;
|
|
202
408
|
}
|
|
203
409
|
|
|
410
|
+
.stage[data-empty]:is([data-busy], [data-offline]) .empty {
|
|
411
|
+
opacity: 1;
|
|
412
|
+
transition-delay: 0.15s;
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
/* --- Part menu ------------------------------------------------------------------ */
|
|
416
|
+
/* A list of the program's parts hanging under the Part pill. */
|
|
417
|
+
|
|
418
|
+
.menu {
|
|
419
|
+
position: fixed;
|
|
420
|
+
inset: auto;
|
|
421
|
+
min-width: 180px;
|
|
422
|
+
max-height: min(420px, calc(100dvh - 84px));
|
|
423
|
+
margin: 0;
|
|
424
|
+
padding: 6px;
|
|
425
|
+
display: none;
|
|
426
|
+
flex-direction: column;
|
|
427
|
+
gap: 2px;
|
|
428
|
+
overflow-y: auto;
|
|
429
|
+
background: #fff;
|
|
430
|
+
color: var(--ink);
|
|
431
|
+
border: 1px solid var(--hairline);
|
|
432
|
+
border-radius: 14px;
|
|
433
|
+
box-shadow: var(--pop);
|
|
434
|
+
transform-origin: 24px 0;
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
.menu:popover-open {
|
|
438
|
+
display: flex;
|
|
439
|
+
animation: drop 0.14s ease-out;
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
@keyframes drop {
|
|
443
|
+
from {
|
|
444
|
+
opacity: 0;
|
|
445
|
+
scale: 0.97;
|
|
446
|
+
translate: 0 -4px;
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
.menu button {
|
|
451
|
+
display: flex;
|
|
452
|
+
align-items: center;
|
|
453
|
+
justify-content: space-between;
|
|
454
|
+
gap: 16px;
|
|
455
|
+
padding: 7px 12px;
|
|
456
|
+
text-align: left;
|
|
457
|
+
font-weight: 500;
|
|
458
|
+
white-space: nowrap;
|
|
459
|
+
background: transparent;
|
|
460
|
+
border: 0;
|
|
461
|
+
border-radius: 9px;
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
.menu button:hover,
|
|
465
|
+
.menu button:focus-visible {
|
|
466
|
+
background: var(--stage-mid);
|
|
467
|
+
outline: none;
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
.menu button[aria-checked='true'] {
|
|
471
|
+
background: var(--selected);
|
|
472
|
+
font-weight: 600;
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
.menu button[aria-checked='true']::after {
|
|
476
|
+
content: '';
|
|
477
|
+
width: 7px;
|
|
478
|
+
height: 7px;
|
|
479
|
+
border-radius: 50%;
|
|
480
|
+
background: var(--filament-deep);
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
@media (prefers-reduced-motion: reduce) {
|
|
484
|
+
.progress::before {
|
|
485
|
+
animation: none;
|
|
486
|
+
width: 100%;
|
|
487
|
+
opacity: 0.6;
|
|
488
|
+
}
|
|
489
|
+
#view,
|
|
490
|
+
.progress,
|
|
491
|
+
.empty {
|
|
492
|
+
transition: none !important;
|
|
493
|
+
}
|
|
494
|
+
.menu:popover-open {
|
|
495
|
+
animation: none;
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
/* Phones: the brand keeps only its mark, the path goes, and the readout
|
|
500
|
+
rises above the display tools. */
|
|
204
501
|
@media (max-width: 720px) {
|
|
502
|
+
.stage {
|
|
503
|
+
--gap: 12px;
|
|
504
|
+
}
|
|
505
|
+
.brand {
|
|
506
|
+
font-size: 0;
|
|
507
|
+
gap: 0;
|
|
508
|
+
margin-right: 0;
|
|
509
|
+
}
|
|
510
|
+
.top-left {
|
|
511
|
+
right: calc(var(--gap) + 170px);
|
|
512
|
+
gap: 8px;
|
|
513
|
+
}
|
|
514
|
+
.top-right {
|
|
515
|
+
gap: 6px;
|
|
516
|
+
}
|
|
205
517
|
.file,
|
|
518
|
+
.wide,
|
|
206
519
|
.hint {
|
|
207
520
|
display: none;
|
|
208
521
|
}
|
|
209
|
-
.
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
522
|
+
.bottom-left {
|
|
523
|
+
right: var(--gap);
|
|
524
|
+
bottom: calc(var(--gap) + 56px);
|
|
525
|
+
gap: 10px;
|
|
526
|
+
}
|
|
527
|
+
.readout .size {
|
|
528
|
+
font-size: 26px;
|
|
215
529
|
}
|
|
216
530
|
}
|