three-slicer 0.2.5 → 0.3.1
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/CHANGELOG.md +134 -0
- package/README.md +13 -8
- package/THIRD-PARTY-NOTICES.md +7 -2
- package/components/dist/SettingsPanel.js +12 -198
- package/data/config-schema-lean.json +1 -0
- package/data/processes.js +1 -1
- package/data/ui-tree-keys.json +1 -0
- package/engine/src/client.js +9 -0
- package/engine/src/data.js +6 -0
- package/engine/src/settings.js +12 -627
- package/engine/src/sla_core.js +14 -8
- package/engine/src/toggle_eval.js +9 -77
- package/package.json +24 -17
- package/types/client.d.ts +3 -0
- package/types/components.d.ts +3 -29
- package/types/settings.d.ts +15 -0
- package/types/toggle.d.ts +2 -22
- package/types/viewer-gcode.d.ts +2 -29
- package/types/viewer-loaders.d.ts +1 -33
- package/types/viewer-toolpath.d.ts +3 -113
- package/types/viewer.d.ts +6 -213
- package/viewer/dist/Viewport.js +9 -6571
- package/viewer/dist/gcode_reexport.js +1 -0
- package/viewer/dist/loaders_reexport.js +1 -0
- package/viewer/dist/toolpath_reexport.js +1 -0
- package/components/README.md +0 -44
- package/components/styles.css +0 -88
- package/engine/src/kernel_setting_keys.js +0 -132
- package/engine/src/preset_file.js +0 -99
- package/types/.omc/state/sessions/02e5ddf5-4378-46e1-8fca-e90412c30804/pre-tool-advisory-throttle.json +0 -10
- package/viewer/README.md +0 -423
- package/viewer/dist/gcode_parse.js +0 -190
- package/viewer/dist/make_worker.js +0 -31
- package/viewer/dist/model_loaders.js +0 -184
- package/viewer/dist/parse_3mf-C2X_W442.js +0 -300
- package/viewer/dist/parse_3mf.worker.js +0 -10
- package/viewer/dist/sl1_encode.worker.js +0 -10
- package/viewer/dist/sl1_write-CtX8cVL7.js +0 -302
- package/viewer/dist/sla_reconstruct-CXkYhux2.js +0 -176
- package/viewer/dist/sla_reconstruct.worker.js +0 -24
- package/viewer/dist/sla_slice.worker.js +0 -74
- package/viewer/dist/toolpath_gpu-4foc4FaU.js +0 -482
- package/viewer/dist/toolpath_gpu.js +0 -13
- package/viewer/styles.css +0 -394
package/viewer/styles.css
DELETED
|
@@ -1,394 +0,0 @@
|
|
|
1
|
-
/* Shadow DOM isolation (shadow_host.jsx) — this file is inlined into the bundle as a string via ?inline
|
|
2
|
-
and injected into the shadow root. Outside resets (*{box-sizing}, …) cannot reach it, so they are spelled out here. */
|
|
3
|
-
:host { display: contents; }
|
|
4
|
-
* { box-sizing: border-box; }
|
|
5
|
-
|
|
6
|
-
/* ===== Stage 27: desktop-style shell (top bar · left rail · center viewport · right sidebar) ===== */
|
|
7
|
-
.app-shell { position: absolute; inset: 0; display: flex; flex-direction: column; background: #0e1216; color: #cdd6dd;
|
|
8
|
-
font: 14px/1.5 -apple-system, "Segoe UI", sans-serif; }
|
|
9
|
-
.app-body { flex: 1 1 auto; display: flex; min-height: 0; }
|
|
10
|
-
|
|
11
|
-
/* S1 top bar */
|
|
12
|
-
.topbar { flex: 0 0 44px; height: 44px; display: flex; align-items: center; padding: 0 12px; gap: 10px;
|
|
13
|
-
background: #161b21; border-bottom: 1px solid #262d35; }
|
|
14
|
-
.topbar .tb-left, .topbar .tb-right { flex: 1 1 0; display: flex; align-items: center; gap: 8px; }
|
|
15
|
-
.topbar .tb-right { justify-content: flex-end; }
|
|
16
|
-
.tb-logo { font-size: 15px; color: #e6edf3; letter-spacing: .01em; }
|
|
17
|
-
.tb-logo b { color: #00ae42; } .tb-re { font-size: 10px; background: #00ae42; color: #fff; padding: 1px 5px; border-radius: 4px; margin-left: 2px; }
|
|
18
|
-
.tb-btn { display: inline-flex; align-items: center; gap: 5px; background: #20272f; border: 1px solid #2c353d;
|
|
19
|
-
color: #cdd6dd; border-radius: 6px; padding: 4px 10px; cursor: pointer; font-size: 12px; }
|
|
20
|
-
.tb-btn img { width: 15px; height: 15px; }
|
|
21
|
-
.tb-btn:hover:not(:disabled) { background: #28313a; }
|
|
22
|
-
.tb-btn:disabled { color: #5a6570; cursor: not-allowed; opacity: .6; }
|
|
23
|
-
/* The button that is mid-export. It is disabled too, so it must override the greyed-out look — the running action
|
|
24
|
-
is the one thing on screen that should not look inert. The animation is CSS so it keeps running while the main
|
|
25
|
-
thread is inside the synchronous half of the write; it stalls only for that stretch, which is the honest signal. */
|
|
26
|
-
.tb-btn.tb-busy:disabled { color: #cdd6dd; opacity: 1; cursor: progress; border-color: #00ae42; animation: tb-pulse 1s ease-in-out infinite; }
|
|
27
|
-
@keyframes tb-pulse { 0%, 100% { background: #20272f; } 50% { background: #23402c; } }
|
|
28
|
-
.tb-tabs { display: flex; border: 1px solid #2c353d; border-radius: 8px; overflow: hidden; flex: 0 0 auto; }
|
|
29
|
-
.tb-tabs button { padding: 6px 24px; border: 0; background: #1a2027; color: #9fb3c0; font-weight: 600; font-size: 13px; cursor: pointer; }
|
|
30
|
-
.tb-tabs button.on { background: #00ae42; color: #fff; }
|
|
31
|
-
.tb-tabs button:disabled { color: #5a6570; cursor: not-allowed; }
|
|
32
|
-
/* Undo/redo. Written while these two were permanent placeholders, so the BASE rule carried the disabled look —
|
|
33
|
-
dim text and cursor:not-allowed — and there was no enabled, hover or pressed state at all. Now that they work,
|
|
34
|
-
the base is the live look and :disabled carries the dim one, the same split .tb-btn above uses. */
|
|
35
|
-
.tb-icon { width: 28px; height: 28px; border: 1px solid #2c353d; background: #20272f; color: #cdd6dd;
|
|
36
|
-
border-radius: 6px; font-size: 15px; cursor: pointer; }
|
|
37
|
-
.tb-icon:hover:not(:disabled) { background: #28313a; color: #fff; border-color: #3a4550; }
|
|
38
|
-
.tb-icon:active:not(:disabled) { background: #171d23; }
|
|
39
|
-
.tb-icon:disabled { color: #5a6570; cursor: not-allowed; opacity: .6; }
|
|
40
|
-
|
|
41
|
-
/* S3 left gizmo rail */
|
|
42
|
-
.left-rail { flex: 0 0 48px; display: flex; flex-direction: column; align-items: center; gap: 6px; padding: 9px 0;
|
|
43
|
-
background: #12171c; border-right: 1px solid #232a31; }
|
|
44
|
-
.left-rail button { width: 36px; height: 36px; border: 1px solid transparent; border-radius: 8px; background: transparent;
|
|
45
|
-
cursor: pointer; display: flex; align-items: center; justify-content: center; padding: 0; }
|
|
46
|
-
.left-rail button img { width: 21px; height: 21px; opacity: .72; }
|
|
47
|
-
.left-rail button:hover { background: #1e252c; }
|
|
48
|
-
.left-rail button.on { background: #00ae42; }
|
|
49
|
-
.left-rail button.on img { opacity: 1; filter: brightness(1.6); }
|
|
50
|
-
.rail-sep { width: 26px; height: 1px; background: #2a323a; margin: 3px 0; }
|
|
51
|
-
|
|
52
|
-
/* Center viewport column */
|
|
53
|
-
.viewport-col { position: relative; flex: 1 1 auto; min-width: 0; background: #161a1e; }
|
|
54
|
-
.vp-top-toolbar { position: absolute; top: 12px; left: 50%; transform: translateX(-50%); display: flex; align-items: center;
|
|
55
|
-
gap: 3px; background: rgba(18,23,28,.85); padding: 4px; border-radius: 9px; border: 1px solid #2a323a; z-index: 3;
|
|
56
|
-
/* Stage 33: more buttons. flex-wrap collapses the shrink-to-fit width of an absolutely positioned box (measured 848 -> 424px),
|
|
57
|
-
folding into two rows even when everything fits. Keep one row and let narrow viewports scroll horizontally instead. */
|
|
58
|
-
max-width: calc(100% - 24px); overflow-x: auto; scrollbar-width: none; }
|
|
59
|
-
.vp-top-toolbar::-webkit-scrollbar { display: none; }
|
|
60
|
-
.vp-top-toolbar > * { flex: 0 0 auto; }
|
|
61
|
-
.vp-top-toolbar button { width: 32px; height: 32px; border: 0; background: transparent; border-radius: 6px; cursor: pointer;
|
|
62
|
-
display: flex; align-items: center; justify-content: center; }
|
|
63
|
-
.vp-top-toolbar button img { width: 18px; height: 18px; opacity: .82; }
|
|
64
|
-
.vp-top-toolbar button:hover:not(:disabled) { background: #2a333c; }
|
|
65
|
-
.vp-top-toolbar button:disabled { opacity: .32; cursor: not-allowed; }
|
|
66
|
-
.vtt-sep { width: 1px; align-self: stretch; background: #333c45; margin: 3px 3px; }
|
|
67
|
-
|
|
68
|
-
/* Stage 29-2: plate tab bar + slice dropdown */
|
|
69
|
-
/* Move scrub — inside the Preview card, directly under the layer slider: the two are the same question's two
|
|
70
|
-
axes (which layers / how far into the top one), so they read as one control rather than a floating overlay. */
|
|
71
|
-
.move-bar { display: flex; align-items: center; gap: 6px; margin-top: 2px; }
|
|
72
|
-
.move-bar input[type=range] { flex: 1; min-width: 60px; }
|
|
73
|
-
.move-label { font-size: 12px; white-space: nowrap; }
|
|
74
|
-
.move-reset { height: 20px; padding: 0 7px; border: 1px solid #2c353d; background: #1a2027; color: #9fb3c0;
|
|
75
|
-
border-radius: 5px; cursor: pointer; font-size: 11px; }
|
|
76
|
-
.move-reset:disabled { opacity: .45; cursor: default; }
|
|
77
|
-
|
|
78
|
-
.plate-bar { position: absolute; right: 14px; bottom: 30px; display: flex; align-items: center; gap: 4px; z-index: 3;
|
|
79
|
-
background: rgba(18,23,28,.85); border: 1px solid #2a323a; border-radius: 9px; padding: 4px; }
|
|
80
|
-
.plate-bar button { min-width: 26px; height: 26px; border: 1px solid #2c353d; background: #1a2027; color: #9fb3c0;
|
|
81
|
-
border-radius: 6px; cursor: pointer; font-size: 12px; font-weight: 600; }
|
|
82
|
-
.plate-tab.on { background: #00ae42; color: #fff; border-color: #00ae42; }
|
|
83
|
-
.plate-add { color: #7ad19a !important; } .plate-del { color: #e08a8a !important; }
|
|
84
|
-
.plate-bar button:disabled { opacity: .4; cursor: not-allowed; }
|
|
85
|
-
/* Per-plate override marker: this plate slices with something other than the global settings. */
|
|
86
|
-
.plate-tab { position: relative; }
|
|
87
|
-
.plate-dot { position: absolute; top: 2px; right: 2px; width: 5px; height: 5px; border-radius: 50%; background: #f0a542; }
|
|
88
|
-
.plate-tab.on .plate-dot { background: #fff; }
|
|
89
|
-
/* An all-plates run: what each plate is doing, independent of which one is selected. */
|
|
90
|
-
.plate-tab.run-queued { border-style: dashed; }
|
|
91
|
-
.plate-tab.run-busy { border-color: #00ae42; animation: tb-pulse 1s ease-in-out infinite; }
|
|
92
|
-
.plate-tab.run-busy.on { animation: none; }
|
|
93
|
-
.plate-tab.run-done { box-shadow: inset 0 -3px 0 #00ae42; }
|
|
94
|
-
.plate-tab.run-failed { border-color: #d9534f; }
|
|
95
|
-
/* Settings-scope toggle in the process card head: writes go to the global map or the selected plate's override. */
|
|
96
|
-
.scope-toggle { margin-left: auto; display: flex; gap: 0; border: 1px solid #d5d8dd; border-radius: 6px; overflow: hidden; }
|
|
97
|
-
.scope-toggle button { border: 0; background: #f3f5f7; color: #5a6472; font-size: 11px; font-weight: 600; padding: 3px 8px; cursor: pointer; }
|
|
98
|
-
.scope-toggle button.on { background: #00ae42; color: #fff; }
|
|
99
|
-
.sc-bed-warn { color: #a86a12; background: #fdf4e3; border-radius: 6px; padding: 5px 8px; font-size: 12px; line-height: 1.4; }
|
|
100
|
-
/* Object-list plate headers: which plate a row's object slices on (same colour language as the PlateBar). */
|
|
101
|
-
.obj-plate-head { display: flex; align-items: center; gap: 6px; padding: 4px 2px 2px; margin-top: 4px; cursor: pointer;
|
|
102
|
-
border-bottom: 1px solid #e6e9ec; font-size: 12px; font-weight: 700; color: #5a6472; list-style: none; }
|
|
103
|
-
.obj-plate-head.on { color: #00913a; border-bottom-color: #9adfb6; }
|
|
104
|
-
.obj-plate-head .obj-plate-tech { background: #6d7ce0; color: #fff; border-radius: 7px; padding: 0 6px; font-size: 10px; font-weight: 700; }
|
|
105
|
-
.obj-plate-head .obj-plate-dot { width: 6px; height: 6px; border-radius: 50%; background: #f0a542; }
|
|
106
|
-
.obj-plate-head .obj-plate-count { margin-left: auto; font-weight: 400; color: #97a1ac; }
|
|
107
|
-
.obj-plate-head .obj-plate-sup { display: inline-flex; align-items: center; gap: 3px; font-weight: 400; font-size: 11px; color: #5a6472; cursor: pointer; }
|
|
108
|
-
.obj-plate-head .obj-plate-sup input { margin: 0; }
|
|
109
|
-
.slice-dd { position: relative; flex: 1.4; }
|
|
110
|
-
.slice-dd .slice-btn { width: 100%; }
|
|
111
|
-
.slice-menu { position: absolute; bottom: calc(100% + 6px); left: 0; right: 0; background: #fff; border: 1px solid #d5d8dd;
|
|
112
|
-
border-radius: 8px; box-shadow: 0 4px 16px rgba(0,0,0,.18); overflow: hidden; z-index: 10; }
|
|
113
|
-
.slice-menu button { display: block; width: 100%; text-align: left; padding: 9px 12px; border: 0; background: #fff;
|
|
114
|
-
color: #24282e; cursor: pointer; font-size: 13px; }
|
|
115
|
-
.slice-menu button:hover { background: #eef7f1; }
|
|
116
|
-
/* The worker-count row inside the menu: a value, not an action, so it is a label with a select. */
|
|
117
|
-
.slice-workers { display: flex; align-items: center; gap: 8px; padding: 7px 12px; font-size: 12px; color: #3b434b;
|
|
118
|
-
border-top: 1px solid #edf0f2; border-bottom: 1px solid #edf0f2; }
|
|
119
|
-
.slice-workers select { flex: 1; font-size: 12px; padding: 2px 4px; }
|
|
120
|
-
.kernel-badge { font-size: 10px; font-weight: 700; padding: 1px 6px; border-radius: 4px; letter-spacing: .04em; text-transform: uppercase; }
|
|
121
|
-
.kernel-badge.mt { background: #e2f5e8; color: #167a3a; }
|
|
122
|
-
.kernel-badge.st { background: #fbeaea; color: #a33b37; }
|
|
123
|
-
/* One entry per plate while an all-plates run is on — same colours as the plate tabs. */
|
|
124
|
-
.slice-plates { flex: 0 0 100%; display: flex; flex-wrap: wrap; gap: 4px 8px; margin: -2px 2px 0; font-size: 11px;
|
|
125
|
-
color: #5a646d; font-variant-numeric: tabular-nums; }
|
|
126
|
-
.slice-plate.busy { color: #167a3a; font-weight: 600; }
|
|
127
|
-
.slice-plate.done { color: #167a3a; }
|
|
128
|
-
.slice-plate.failed { color: #a33b37; }
|
|
129
|
-
|
|
130
|
-
/* Floating painting panel */
|
|
131
|
-
.brush-panel { position: absolute; top: 58px; left: 14px; width: 214px; background: rgba(22,27,33,.95);
|
|
132
|
-
border: 1px solid #2c353d; border-radius: 10px; padding: 10px; z-index: 4; box-shadow: 0 3px 14px rgba(0,0,0,.45); }
|
|
133
|
-
.bp-title { font-weight: 600; margin-bottom: 6px; color: #cdd6dd; }
|
|
134
|
-
.bp-modes { display: flex; gap: 4px; flex-wrap: wrap; }
|
|
135
|
-
.bp-modes button { padding: 3px 9px; border: 1px solid #2c353d; background: #1a2027; color: #cdd6dd; border-radius: 5px; cursor: pointer; font-size: 12px; }
|
|
136
|
-
.bp-modes button.enf.on { background: #2b6cff; color: #fff; border-color: #2b6cff; }
|
|
137
|
-
.bp-modes button.blk.on { background: #e23b3b; color: #fff; border-color: #e23b3b; }
|
|
138
|
-
/* Tool row (brush / smart / bucket / triangle + the brush's cursor shape). Its own selected style rather than
|
|
139
|
-
.bp-chip's white outline: a chip carries the filament colour and needs a border that reads on any of them,
|
|
140
|
-
while a tool button only has to look pressed. */
|
|
141
|
-
.bp-tools { margin-top: 6px; }
|
|
142
|
-
.bp-tool.on { background: #2c353d; color: #fff; border-color: #46525c; }
|
|
143
|
-
.bp-radius { display: block; font-size: 12px; color: #aebcc6; margin-top: 8px; }
|
|
144
|
-
.bp-radius input { width: 100%; }
|
|
145
|
-
.bp-counts { margin-top: 6px; font-size: 11px; }
|
|
146
|
-
/* "On overhangs only" — a checkbox row in a panel whose other rows are buttons, so it borrows the label styling
|
|
147
|
-
of .bp-radius and only adds the inline layout a checkbox needs. */
|
|
148
|
-
.bp-check { display: flex; align-items: center; gap: 6px; font-size: 12px; color: #aebcc6; margin-top: 8px; cursor: pointer; }
|
|
149
|
-
.bp-check input { margin: 0; }
|
|
150
|
-
/* Material brush: the chip IS the filament colour, so its background is inline and only the framing is here.
|
|
151
|
-
The active ring is drawn outside the box (outline, not border) — a border would resize the chip on selection. */
|
|
152
|
-
.bp-chip { min-width: 30px; font-weight: 700; border-color: rgba(0,0,0,.35) !important; }
|
|
153
|
-
.bp-chip.on { outline: 2px solid #fff; outline-offset: 1px; }
|
|
154
|
-
.bp-eraser { background: #1a2027 !important; color: #cdd6dd !important; font-weight: 400; }
|
|
155
|
-
.bp-actions { margin-top: 6px; }
|
|
156
|
-
.bp-note { margin-top: 6px; font-size: 10.5px; line-height: 1.35; color: #8b98a2; }
|
|
157
|
-
|
|
158
|
-
/* Over-bed warning while arranging. Sits where the stats card does in Preview — the two never show at once, so the
|
|
159
|
-
same corner carries "here is the problem" in both modes. Amber rather than red: the model is still slicable. */
|
|
160
|
-
.bed-warn { position: absolute; left: 14px; bottom: 32px; z-index: 2;
|
|
161
|
-
background: rgba(58,42,16,.94); border: 1px solid #7a5a1e; border-radius: 10px;
|
|
162
|
-
padding: 8px 13px; font-size: 12.5px; color: #f0c060; }
|
|
163
|
-
|
|
164
|
-
/* Preview stats card, bottom left */
|
|
165
|
-
.stats-card { position: absolute; left: 14px; bottom: 32px; background: rgba(22,27,33,.93); border: 1px solid #2c353d;
|
|
166
|
-
border-radius: 10px; padding: 10px 14px; font-size: 13px; line-height: 1.7; z-index: 2; color: #cdd6dd; }
|
|
167
|
-
.stats-card b { color: #9fe3bd; }
|
|
168
|
-
/* Per-extruder filament breakdown under the total — indented so it reads as a detail of the line above. */
|
|
169
|
-
.stat-tool { display: flex; align-items: center; gap: 5px; font-size: 12px; margin-left: 10px; }
|
|
170
|
-
.stat-swatch { width: 9px; height: 9px; border-radius: 2px; border: 1px solid rgba(255,255,255,.28); flex: 0 0 auto; }
|
|
171
|
-
/* Purge belongs to no extruder, so it gets hatching rather than a colour that would read as a fifth tool. */
|
|
172
|
-
.stat-swatch-purge { background: repeating-linear-gradient(45deg, #6d7780 0 2px, #39424a 2px 4px); }
|
|
173
|
-
|
|
174
|
-
/* S4 right sidebar (light) */
|
|
175
|
-
.sidebar { flex: 0 0 384px; width: 384px; display: flex; flex-direction: column; background: #eef0f2; color: #24282e;
|
|
176
|
-
border-left: 1px solid #d5d8dd; min-height: 0; }
|
|
177
|
-
.sidebar-scroll { flex: 1 1 auto; overflow-y: auto; padding: 10px; display: flex; flex-direction: column; gap: 10px; }
|
|
178
|
-
.side-card { background: #fff; border: 1px solid #e2e4e8; border-radius: 10px; padding: 10px 12px; }
|
|
179
|
-
.sc-head { font-weight: 700; font-size: 13px; color: #2a2f36; display: flex; align-items: center; gap: 6px; margin-bottom: 7px; }
|
|
180
|
-
.sc-count { background: #00ae42; color: #fff; font-size: 10px; border-radius: 8px; padding: 0 6px; font-weight: 700; }
|
|
181
|
-
.sc-head-btns { margin-left: auto; display: flex; gap: 4px; }
|
|
182
|
-
.sc-head-btns button { width: 22px; height: 22px; border: 1px solid #d3d6db; background: #f6f7f8; border-radius: 5px; cursor: pointer; font-size: 14px; line-height: 1; color: #333; }
|
|
183
|
-
.sc-head-btns button:disabled { opacity: .4; cursor: not-allowed; }
|
|
184
|
-
/* Preset actions carry a label, so they override the 22px square the +/− icon buttons above are sized to. */
|
|
185
|
-
.sc-preset-btns button { width: auto; padding: 0 8px; font-size: 11px; white-space: nowrap; }
|
|
186
|
-
.sc-dirty { color: #c47f00; font-weight: 600; }
|
|
187
|
-
.sc-info { display: flex; justify-content: space-between; font-size: 12px; color: #5a6069; padding: 2px 0; }
|
|
188
|
-
.sc-info b { color: #24282e; }
|
|
189
|
-
.side-warn { margin: 0 2px; font-size: 12px; }
|
|
190
|
-
|
|
191
|
-
.filament-row { display: flex; align-items: center; gap: 8px; padding: 3px 0; }
|
|
192
|
-
.filament-row input[type=color] { width: 28px; height: 22px; border: 1px solid #ccc; border-radius: 5px; padding: 0; cursor: pointer; background: none; }
|
|
193
|
-
/* One row per extruder, and the row is the selector for which extruder the pickers below edit. */
|
|
194
|
-
.filament-row { cursor: pointer; border-radius: 5px; padding-left: 4px; }
|
|
195
|
-
.filament-row.fil-active { background: #eef6f0; box-shadow: inset 2px 0 0 #00ae42; }
|
|
196
|
-
.fil-mat { font-size: 11.5px; color: #5a6069; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
197
|
-
.sc-note { color: #8a9099; font-size: 11px; font-style: italic; }
|
|
198
|
-
.fil-t { font-weight: 700; font-size: 12px; width: 20px; }
|
|
199
|
-
/* The material name is the row's flexible column, so the paint controls are pinned to the right of it. */
|
|
200
|
-
.fil-mat { flex: 1; min-width: 0; } /* min-width:0 is what lets a flex item actually ellipsis instead of overflowing */
|
|
201
|
-
.fil-badge { font-size: 9.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .3px;
|
|
202
|
-
color: #5a6069; background: #eceef1; border-radius: 7px; padding: 1px 5px; white-space: nowrap; }
|
|
203
|
-
.fil-count { font-size: 10px; font-weight: 700; color: #fff; background: #2b6cff; border-radius: 7px; padding: 0 5px; }
|
|
204
|
-
.fil-paint { border: 1px solid #d3d6db; background: #f6f7f8; border-radius: 5px; cursor: pointer;
|
|
205
|
-
font-size: 11px; line-height: 1; padding: 3px 5px; }
|
|
206
|
-
.fil-paint.on { background: #2b6cff; border-color: #2b6cff; }
|
|
207
|
-
|
|
208
|
-
.obj-list2 { list-style: none; margin: 0 0 6px; padding: 0; }
|
|
209
|
-
|
|
210
|
-
.obj-list2 li { display: flex; align-items: center; gap: 6px; padding: 3px 0; font-size: 12px; cursor: pointer; }
|
|
211
|
-
/* A row of the object list that is part of the current selection. The card is light and the row text is near-black
|
|
212
|
-
(.obj-name is #24282e), so the tint has to be a LIGHT green — a dark one swallows the name it is highlighting. */
|
|
213
|
-
.obj-list2 li.obj-selected { background: #e3f6ea; box-shadow: inset 2px 0 0 #00ae42; }
|
|
214
|
-
.obj-list2 li.obj-hidden { opacity: .5; }
|
|
215
|
-
.obj-eye { border: 0; background: none; cursor: pointer; font-size: 13px; padding: 0; }
|
|
216
|
-
.obj-list2 .obj-name { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: #24282e; }
|
|
217
|
-
.obj-list2 .obj-ext { border: 1px solid #d0d3d8; border-radius: 5px; font-size: 11px; padding: 1px 3px; background: #fff; }
|
|
218
|
-
.obj-del { border: 0; background: #fbe9ec; color: #d0435a; border-radius: 5px; cursor: pointer; padding: 0 6px; }
|
|
219
|
-
/* Marks a row whose object carries material paint — the extruder select next to it then covers only the rest of it. */
|
|
220
|
-
.obj-painted { font-size: 10px; line-height: 1; background: #e6efff; border-radius: 6px; padding: 2px 4px; }
|
|
221
|
-
.side-card .slice-support { color: #444; font-size: 12px; margin: 5px 0 0; }
|
|
222
|
-
|
|
223
|
-
/* Process card = embedded settings panel (light, full width) */
|
|
224
|
-
.process-card { padding: 8px; }
|
|
225
|
-
/* Width/border overrides for the embedded SettingsPanel now live in the panel's own shadow rules
|
|
226
|
-
(:host(.sp-embedded), components/styles.css) — they are across the boundary and unreachable from here. */
|
|
227
|
-
|
|
228
|
-
/* Preview control overrides (inside the light card) */
|
|
229
|
-
.side-card .view-type-row { color: #444; }
|
|
230
|
-
.side-card .view-type-row select, .side-card .obj-ext { background: #fff; color: #222; border: 1px solid #ccd0d5; }
|
|
231
|
-
.side-card .slice-layer label { color: #444; font-size: 12px; }
|
|
232
|
-
.side-card .grad-title { color: #333; } .side-card .grad-minmax { color: #666; }
|
|
233
|
-
.side-card .role-legend, .side-card .slice-travel { color: #555; }
|
|
234
|
-
.side-card .layer-ctl button { background: #f1f2f4; color: #333; border: 1px solid #d3d6db; }
|
|
235
|
-
.side-card .layer-ctl button.on { background: #00ae42; color: #fff; border-color: #00ae42; }
|
|
236
|
-
|
|
237
|
-
/* (5) Fixed bottom button bar */
|
|
238
|
-
.side-bottom { flex: 0 0 auto; display: flex; flex-wrap: wrap; gap: 8px; padding: 10px; border-top: 1px solid #dcdfe3; background: #e6e9ec; }
|
|
239
|
-
/* The live slice rate takes a full row of its own (it only exists while slicing). Tabular figures keep the
|
|
240
|
-
digits from changing width as the number moves, which otherwise jitters the line several times a second. */
|
|
241
|
-
.slice-rate { flex: 0 0 100%; margin: -4px 2px 0; text-align: right; font-size: 11px; color: #5a646d;
|
|
242
|
-
font-variant-numeric: tabular-nums; }
|
|
243
|
-
.side-bottom .slice-btn { flex: 1.4; margin: 0; }
|
|
244
|
-
.auto-slice { display: flex; align-items: center; gap: 5px; font-size: 12px; color: #444; cursor: pointer; white-space: nowrap; user-select: none; }
|
|
245
|
-
.auto-slice input { margin: 0; }
|
|
246
|
-
.export-btn { flex: 1; text-align: center; padding: 9px; border-radius: 8px; background: #dfe6ea; color: #1f6feb;
|
|
247
|
-
border: 1px solid #c7d2da; text-decoration: none; font-weight: 600; cursor: pointer; font-size: 13px; }
|
|
248
|
-
.export-btn:hover { background: #d3dee4; }
|
|
249
|
-
.export-btn:disabled { color: #9aa4ad; background: #e9ecef; cursor: not-allowed; }
|
|
250
|
-
|
|
251
|
-
.vp-canvas { position: absolute; inset: 0; }
|
|
252
|
-
.vp-canvas canvas { display: block; }
|
|
253
|
-
/* The 3D view holds focus so Ctrl+Z can be scoped to this component instead of window — the focus itself stays,
|
|
254
|
-
only its ring is dropped. :focus-visible has to go with it: the focus is taken by a script (`focus()` in the
|
|
255
|
-
view's own pointerdown), and a scripted focus matches :focus-visible in Chrome even when the pointer caused it,
|
|
256
|
-
so a plain click drew the ring the :focus rule below was written to prevent. CSS cannot tell that click apart
|
|
257
|
-
from a Tab, so a keyboard user gets no ring here; the gizmo rail and the panels keep theirs. */
|
|
258
|
-
.vp-canvas:focus, .vp-canvas:focus-visible { outline: none; }
|
|
259
|
-
.vp-canvas.fail { display: flex; align-items: center; justify-content: center; }
|
|
260
|
-
.vp-fallback { color: #f0c9a8; padding: 24px; text-align: center; max-width: 560px; line-height: 1.5; }
|
|
261
|
-
.vp-status { position: absolute; bottom: 8px; left: 12px; right: 12px; z-index: 1;
|
|
262
|
-
font-size: 11.5px; color: #9fe3bd; font-family: ui-monospace, monospace;
|
|
263
|
-
text-shadow: 0 1px 2px #000; pointer-events: none; }
|
|
264
|
-
/* ---- Slice status display (viewport overlay) ---- */
|
|
265
|
-
.slice-warn { color: #f0c060; margin: 4px 0; }
|
|
266
|
-
/* Basis line under the print-time estimate — the machine limits the kernel reported using */
|
|
267
|
-
.sc-sub { font-size: 10.5px; opacity: .62; margin: 1px 0 3px; }
|
|
268
|
-
/* Collapsible card section holding an injected settings page (printer motion ability) */
|
|
269
|
-
.sc-fold > summary { display: flex; justify-content: space-between; align-items: center; font-size: 12px;
|
|
270
|
-
color: #5a6069; padding: 2px 0; cursor: pointer; list-style: none; }
|
|
271
|
-
.sc-fold > summary::-webkit-details-marker { display: none; }
|
|
272
|
-
.sc-fold-lbl::before { content: '▸'; display: inline-block; width: 10px; font-size: 9px; opacity: .5; }
|
|
273
|
-
.sc-fold[open] .sc-fold-lbl::before { content: '▾'; }
|
|
274
|
-
.sc-fold > summary b { color: #24282e; }
|
|
275
|
-
.sc-fold[open] > summary { border-bottom: 1px solid #e3e6ea; margin-bottom: 4px; }
|
|
276
|
-
/* The injected page is a full settings form — keep it from stretching the card unboundedly */
|
|
277
|
-
.sc-fold-body { max-height: 320px; overflow-y: auto; }
|
|
278
|
-
.sc-model { max-width: 62%; font-size: 11.5px; padding: 1px 2px; }
|
|
279
|
-
/* Support helpers grouped under the "Generate support" toggle */
|
|
280
|
-
.support-tools { display: flex; align-items: center; justify-content: space-between; gap: 8px;
|
|
281
|
-
margin: 2px 0 2px 16px; padding-left: 6px; border-left: 2px solid #e3e6ea; }
|
|
282
|
-
.sup-style { margin-left: 16px; padding-left: 6px; border-left: 2px solid #e3e6ea; }
|
|
283
|
-
.sup-paint { font-size: 11px; padding: 2px 8px; border: 1px solid #c9ced6; border-radius: 5px;
|
|
284
|
-
background: #fff; color: #24282e; cursor: pointer; white-space: nowrap; }
|
|
285
|
-
.sup-paint.on { background: #2b6cff; border-color: #2b6cff; color: #fff; }
|
|
286
|
-
.sup-paint:disabled { opacity: .45; cursor: not-allowed; }
|
|
287
|
-
/* Sits in the light sidebar, so it cannot borrow .slice-warn's colour (tuned for the dark viewport overlay). */
|
|
288
|
-
.sup-filament-warn { margin: 2px 0 2px 22px; font-size: 11px; line-height: 1.35; color: #a06a00; }
|
|
289
|
-
.slice-btn { width: 100%; margin-top: 6px; padding: 7px; border: 0; border-radius: 7px;
|
|
290
|
-
background: #00ae42; color: #fff; font-weight: 700; cursor: pointer; }
|
|
291
|
-
.slice-btn:disabled { background: #3a4650; color: #8b98a2; cursor: not-allowed; }
|
|
292
|
-
.slice-err { color: #ff8b8b; margin-top: 6px; }
|
|
293
|
-
.slice-stats { margin-top: 8px; line-height: 1.5; }
|
|
294
|
-
.slice-stats b { color: #9fe3bd; }
|
|
295
|
-
.slice-layer { margin-top: 8px; display: flex; flex-direction: column; gap: 4px; }
|
|
296
|
-
.slice-layer input[type=range] { width: 100%; }
|
|
297
|
-
.slice-travel { color: #aebcc6; display: flex; align-items: center; gap: 4px; }
|
|
298
|
-
|
|
299
|
-
/* Stage 25 S6: view type select · dual slider · gradient legend */
|
|
300
|
-
.view-type-row { display: flex; align-items: center; justify-content: space-between; gap: 6px; color: #aebcc6; }
|
|
301
|
-
.view-type-row select { flex: 1; background: #10141a; color: #eee; border: 1px solid #2c353d; border-radius: 4px; padding: 2px 4px; }
|
|
302
|
-
.dual-slider { position: relative; height: 22px; }
|
|
303
|
-
.dual-slider input[type=range] { position: absolute; left: 0; top: 0; width: 100%; margin: 0; pointer-events: none; background: transparent; -webkit-appearance: none; appearance: none; }
|
|
304
|
-
.dual-slider input[type=range]::-webkit-slider-thumb { pointer-events: auto; -webkit-appearance: none; width: 13px; height: 13px; border-radius: 50%; background: #00ae42; border: 2px solid #0c1013; cursor: pointer; }
|
|
305
|
-
.dual-slider input[type=range]::-moz-range-thumb { pointer-events: auto; width: 13px; height: 13px; border-radius: 50%; background: #00ae42; border: 2px solid #0c1013; cursor: pointer; }
|
|
306
|
-
.dual-slider input[type=range]::-webkit-slider-runnable-track { height: 4px; background: #2c353d; border-radius: 2px; }
|
|
307
|
-
.dual-slider input[type=range]:first-child { z-index: 2; }
|
|
308
|
-
.layer-ctl { display: flex; align-items: center; gap: 8px; }
|
|
309
|
-
.layer-ctl button { padding: 2px 8px; border: 1px solid #2c353d; border-radius: 5px; background: #1a2027; color: #cdd6dd; font-size: 11px; cursor: pointer; }
|
|
310
|
-
.layer-ctl button.on { background: #00ae42; color: #fff; border-color: #00ae42; }
|
|
311
|
-
.grad-legend { margin-top: 6px; }
|
|
312
|
-
.grad-title { font-size: 11px; color: #cdd6dd; margin-bottom: 3px; }
|
|
313
|
-
.grad-bar { height: 10px; border-radius: 3px; border: 1px solid #2c353d; }
|
|
314
|
-
.grad-minmax { display: flex; justify-content: space-between; font-size: 10px; color: #aebcc6; margin-top: 2px; }
|
|
315
|
-
.role-legend { display: flex; flex-wrap: wrap; gap: 4px 10px; margin-top: 6px; font-size: 11px; color: #aebcc6; }
|
|
316
|
-
.role-item { display: inline-flex; align-items: center; gap: 4px; }
|
|
317
|
-
.role-item i { width: 10px; height: 6px; border-radius: 2px; display: inline-block; }
|
|
318
|
-
.role-item b { color: #cdd6dd; }
|
|
319
|
-
|
|
320
|
-
/* Stage 26: empty scene hint + drag-and-drop overlay */
|
|
321
|
-
.vp-canvas.drag-over { outline: 3px dashed #00ae42; outline-offset: -6px; }
|
|
322
|
-
.empty-hint { position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center;
|
|
323
|
-
gap: 8px; pointer-events: none; color: #9fb3c0; text-align: center; }
|
|
324
|
-
.empty-hint .eh-icon { font-size: 46px; opacity: .8; }
|
|
325
|
-
.empty-hint .eh-title { font-size: 16px; font-weight: 600; color: #cdd6dd; }
|
|
326
|
-
.empty-hint .eh-sub { font-size: 12px; color: #7d8b96; letter-spacing: .04em; }
|
|
327
|
-
.empty-hint .eh-btn { pointer-events: auto; margin-top: 8px; padding: 7px 18px; border: 0; border-radius: 7px;
|
|
328
|
-
background: #00ae42; color: #fff; font-weight: 600; cursor: pointer; }
|
|
329
|
-
.empty-hint .eh-btn:hover { background: #06c04d; }
|
|
330
|
-
.drop-overlay { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
|
|
331
|
-
background: rgba(0,174,66,.14); color: #d7f7e3; font-size: 18px; font-weight: 700; pointer-events: none;
|
|
332
|
-
border: 3px dashed #00ae42; box-sizing: border-box; }
|
|
333
|
-
|
|
334
|
-
/* Split objects button */
|
|
335
|
-
.obj-split { border: 0; background: transparent; cursor: pointer; padding: 0 3px; line-height: 0; }
|
|
336
|
-
.obj-split img { width: 13px; height: 13px; opacity: .6; }
|
|
337
|
-
.obj-split:hover img { opacity: 1; }
|
|
338
|
-
|
|
339
|
-
/* Right-click context menu */
|
|
340
|
-
.ctx-scrim { position: absolute; inset: 0; z-index: 24; }
|
|
341
|
-
.ctx-menu { position: absolute; z-index: 25; min-width: 168px; padding: 4px;
|
|
342
|
-
background: #1b2027; border: 1px solid #2f3944; border-radius: 8px; box-shadow: 0 8px 24px rgba(0,0,0,.5); }
|
|
343
|
-
.ctx-menu button { display: flex; width: 100%; align-items: center; justify-content: space-between; gap: 16px;
|
|
344
|
-
padding: 6px 10px; border: 0; border-radius: 5px; background: transparent; color: #dfe6ee;
|
|
345
|
-
font-size: 12px; text-align: left; cursor: pointer; }
|
|
346
|
-
.ctx-menu button:hover:not(:disabled) { background: #273140; }
|
|
347
|
-
.ctx-menu button:disabled { color: #64707d; cursor: not-allowed; }
|
|
348
|
-
.ctx-menu button.danger:hover:not(:disabled) { background: #4a2229; color: #ffb3b3; }
|
|
349
|
-
.ctx-menu hr { margin: 4px 6px; border: 0; border-top: 1px solid #2f3944; }
|
|
350
|
-
.ctx-key { color: #7d8b96; font-family: ui-monospace, monospace; font-size: 11px; }
|
|
351
|
-
|
|
352
|
-
/* Keyboard shortcut help overlay ('?') */
|
|
353
|
-
.help-overlay { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
|
|
354
|
-
background: rgba(8,12,16,.72); z-index: 20; }
|
|
355
|
-
.help-card { background: #1b2027; color: #dfe6ee; border: 1px solid #2f3944; border-radius: 10px;
|
|
356
|
-
padding: 18px 22px; max-width: 720px; box-shadow: 0 12px 40px rgba(0,0,0,.5); }
|
|
357
|
-
.help-card h3 { margin: 0 0 12px; font-size: 15px; }
|
|
358
|
-
.help-card h4 { margin: 0 0 6px; font-size: 12px; color: #00ae42; text-transform: uppercase; letter-spacing: .04em; }
|
|
359
|
-
.help-cols { display: flex; gap: 26px; flex-wrap: wrap; }
|
|
360
|
-
.help-card dl { display: grid; grid-template-columns: auto 1fr; gap: 3px 12px; margin: 0; font-size: 12px; }
|
|
361
|
-
.help-card dt { color: #9fb0c2; font-family: ui-monospace, monospace; white-space: nowrap; }
|
|
362
|
-
.help-card dd { margin: 0; }
|
|
363
|
-
|
|
364
|
-
/* Multi-object list / support toggle (stage 3) */
|
|
365
|
-
.slice-support { display: flex; align-items: center; gap: 5px; margin: 6px 0; color: #cdd6dd; font-size: 12px; }
|
|
366
|
-
|
|
367
|
-
.slice-support .muted { font-size: 10px; }
|
|
368
|
-
|
|
369
|
-
/* Printer card — inline editing of bed width x depth */
|
|
370
|
-
.sc-bed { display: inline-flex; align-items: center; gap: 4px; font-weight: 700; color: #222; }
|
|
371
|
-
.sc-bed input { width: 54px; padding: 1px 4px; font-size: 12px; font-weight: 600; text-align: right;
|
|
372
|
-
border: 1px solid #ccd0d5; border-radius: 5px; background: #fff; color: #222; }
|
|
373
|
-
/* Model/Tower breakdown inside a filament row — secondary to the total it qualifies, so it reads as an aside. */
|
|
374
|
-
.stat-split { color: #8b98a2; font-size: 11px; }
|
|
375
|
-
/* Material name next to the tool number in the filament legend — a label, so it sits quieter than the amount. */
|
|
376
|
-
.stat-type { margin-left: 4px; padding: 0 4px; border-radius: 3px; background: #2c353d; color: #aebcc6; font-size: 10.5px; }
|
|
377
|
-
/* Purge matrix: one row/column per filament, so it has to stay legible at 3-4 columns inside a 300px card. */
|
|
378
|
-
.purge-grid { width: 100%; border-collapse: collapse; font-size: 11px; }
|
|
379
|
-
.purge-grid th { font-weight: 600; color: #aebcc6; padding: 2px 3px; white-space: nowrap; }
|
|
380
|
-
.purge-grid th .stat-swatch { margin-right: 3px; vertical-align: middle; }
|
|
381
|
-
.purge-grid td { padding: 1px 2px; text-align: center; }
|
|
382
|
-
.purge-grid input { width: 100%; min-width: 42px; background: #1a2027; border: 1px solid #2c353d; color: #cdd6dd;
|
|
383
|
-
border-radius: 4px; padding: 2px 3px; font-size: 11px; }
|
|
384
|
-
.sc-num input { width: 62px; background: #1a2027; border: 1px solid #2c353d; color: #cdd6dd; border-radius: 4px;
|
|
385
|
-
padding: 2px 5px; font-size: 12px; margin-left: 4px; }
|
|
386
|
-
|
|
387
|
-
/* A panel shown but not editable (panels={{ printerCard: 'readonly' }}). `inert` on the wrapper already blocks
|
|
388
|
-
pointer, keyboard and focus — this only has to make that legible, or the card reads as broken rather than locked. */
|
|
389
|
-
.vp-readonly { opacity: .62; cursor: default; }
|
|
390
|
-
.vp-readonly * { cursor: default !important; }
|
|
391
|
-
|
|
392
|
-
/* The scope toggle's ↺ — drops the plate's whole override (ScopeToggle onReset). */
|
|
393
|
-
.scope-toggle .scope-reset { margin-left: 4px; padding: 0 6px; font-size: 12px; line-height: 18px; border: 1px solid #c9d3de; border-radius: 4px; background: transparent; cursor: pointer; }
|
|
394
|
-
.scope-toggle .scope-reset:hover { background: #eef2f6; }
|