@womp/mcp-ui 0.1.5 → 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.
- package/README.md +54 -2
- package/dist/index.js +7 -7
- package/dist/print/index.html +698 -115
- package/package.json +1 -1
- package/src/print/index.html +681 -98
- package/src/print/main.ts +750 -167
- package/src/print/pantone-coated.ts +5 -0
- package/src/print/pantone.ts +224 -0
package/src/print/index.html
CHANGED
|
@@ -6,24 +6,61 @@
|
|
|
6
6
|
<style>
|
|
7
7
|
/* Same var()-with-fallback discipline as the other cards: host style
|
|
8
8
|
variables arrive over the bridge after the handshake, not as CSS
|
|
9
|
-
custom properties, so the card must look right without them.
|
|
9
|
+
custom properties, so the card must look right without them. The
|
|
10
|
+
shorthands below re-resolve when the host variables land on :root.
|
|
11
|
+
|
|
12
|
+
The layout follows the web print panel's flow — Size, Material (with
|
|
13
|
+
its finish / colour controls inside the selection), Print style, then a
|
|
14
|
+
review row with quantity and price — compressed into a 360px card. */
|
|
10
15
|
:root {
|
|
11
16
|
color-scheme: light dark;
|
|
17
|
+
--bg: var(--color-background-secondary, #1b1b1d);
|
|
18
|
+
--bg2: var(--color-background-tertiary, #27272b);
|
|
19
|
+
--fg: var(--color-text-primary, #ececec);
|
|
20
|
+
--fg2: var(--color-text-secondary, rgba(236, 236, 236, 0.62));
|
|
21
|
+
--line: var(--color-border-primary, rgba(255, 255, 255, 0.1));
|
|
22
|
+
--accent: var(--color-background-accent, #5867dd);
|
|
23
|
+
--ring: var(--color-ring-primary, #7aa2ff);
|
|
24
|
+
--danger: var(--color-text-danger, #ff8080);
|
|
25
|
+
--ok: #4fbf7a;
|
|
26
|
+
--warn: #e0a83a;
|
|
27
|
+
--pro: #f0c453;
|
|
28
|
+
--r-md: var(--border-radius-md, 10px);
|
|
29
|
+
--r-lg: var(--border-radius-lg, 14px);
|
|
30
|
+
--fs-xs: var(--font-text-xs-size, 11px);
|
|
31
|
+
--fs-sm: var(--font-text-sm-size, 13px);
|
|
12
32
|
}
|
|
13
33
|
body {
|
|
14
34
|
margin: 0;
|
|
15
35
|
font-family: var(--font-sans, system-ui, -apple-system, "Segoe UI", sans-serif);
|
|
16
|
-
color: var(--
|
|
36
|
+
color: var(--fg);
|
|
37
|
+
}
|
|
38
|
+
button {
|
|
39
|
+
font: inherit;
|
|
40
|
+
color: inherit;
|
|
41
|
+
}
|
|
42
|
+
[hidden] {
|
|
43
|
+
display: none !important;
|
|
17
44
|
}
|
|
18
45
|
|
|
19
46
|
.card {
|
|
20
47
|
max-width: 360px;
|
|
21
|
-
border-radius: var(--border-radius-lg, 14px);
|
|
22
|
-
overflow: hidden;
|
|
23
|
-
background: var(--color-background-secondary, #1b1b1d);
|
|
24
|
-
border: 1px solid var(--color-border-primary, rgba(255, 255, 255, 0.08));
|
|
25
48
|
padding: 14px;
|
|
49
|
+
border-radius: var(--r-lg);
|
|
50
|
+
background: var(--bg);
|
|
51
|
+
border: 1px solid var(--line);
|
|
26
52
|
box-sizing: border-box;
|
|
53
|
+
display: grid;
|
|
54
|
+
/* minmax(0, 1fr), not the implicit auto track: an auto track grows to
|
|
55
|
+
its items' min-content, and a bare <input type="number"> has an
|
|
56
|
+
intrinsic width of ~150px, so three of them widened every row past
|
|
57
|
+
the card's edge while the card itself stayed 360px. */
|
|
58
|
+
grid-template-columns: minmax(0, 1fr);
|
|
59
|
+
gap: 14px;
|
|
60
|
+
}
|
|
61
|
+
:root[data-display-mode="fullscreen"] .card {
|
|
62
|
+
max-width: 560px;
|
|
63
|
+
margin: 16px auto;
|
|
27
64
|
}
|
|
28
65
|
|
|
29
66
|
.head {
|
|
@@ -33,88 +70,531 @@
|
|
|
33
70
|
gap: 8px;
|
|
34
71
|
}
|
|
35
72
|
.title {
|
|
36
|
-
font-size: var(--
|
|
73
|
+
font-size: var(--fs-sm);
|
|
37
74
|
font-weight: 600;
|
|
38
75
|
}
|
|
39
|
-
.
|
|
40
|
-
font-size: var(--
|
|
41
|
-
color: var(--
|
|
76
|
+
.dims {
|
|
77
|
+
font-size: var(--fs-xs);
|
|
78
|
+
color: var(--fg2);
|
|
42
79
|
white-space: nowrap;
|
|
80
|
+
font-variant-numeric: tabular-nums;
|
|
43
81
|
}
|
|
44
|
-
.size:empty { display: none; }
|
|
45
82
|
|
|
46
|
-
|
|
47
|
-
static mode (a prepare_print result rendered by a model call). */
|
|
48
|
-
.controls {
|
|
49
|
-
margin-top: 10px;
|
|
83
|
+
.section {
|
|
50
84
|
display: grid;
|
|
51
|
-
grid-template-columns: 1fr
|
|
85
|
+
grid-template-columns: minmax(0, 1fr);
|
|
52
86
|
gap: 8px;
|
|
53
87
|
}
|
|
54
|
-
.
|
|
55
|
-
|
|
88
|
+
.label-row {
|
|
89
|
+
display: flex;
|
|
90
|
+
align-items: center;
|
|
91
|
+
justify-content: space-between;
|
|
92
|
+
gap: 8px;
|
|
93
|
+
min-height: 22px;
|
|
94
|
+
}
|
|
95
|
+
.label {
|
|
96
|
+
font-size: var(--fs-xs);
|
|
97
|
+
font-weight: 500;
|
|
98
|
+
color: var(--fg2);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/* --- Size: W / H / D in the chosen unit; editing one axis rescales the
|
|
102
|
+
others, because MCP prints scale uniformly. */
|
|
103
|
+
.dim-grid {
|
|
56
104
|
display: grid;
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
color: var(--color-text-secondary, rgba(232, 232, 232, 0.6));
|
|
105
|
+
grid-template-columns: repeat(3, 1fr);
|
|
106
|
+
gap: 8px;
|
|
60
107
|
}
|
|
61
|
-
.
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
border:
|
|
68
|
-
|
|
69
|
-
|
|
108
|
+
.dim {
|
|
109
|
+
display: flex;
|
|
110
|
+
align-items: center;
|
|
111
|
+
gap: 6px;
|
|
112
|
+
height: 30px;
|
|
113
|
+
padding: 0 8px;
|
|
114
|
+
border-radius: var(--r-md);
|
|
115
|
+
background: var(--bg2);
|
|
116
|
+
border: 1px solid var(--line);
|
|
117
|
+
font-size: var(--fs-xs);
|
|
118
|
+
box-sizing: border-box;
|
|
119
|
+
}
|
|
120
|
+
.dim:focus-within {
|
|
121
|
+
outline: 2px solid var(--ring);
|
|
122
|
+
outline-offset: 1px;
|
|
123
|
+
}
|
|
124
|
+
.dim > span {
|
|
125
|
+
color: var(--fg2);
|
|
126
|
+
width: 10px;
|
|
127
|
+
}
|
|
128
|
+
.dim input {
|
|
129
|
+
flex: 1 1 0;
|
|
130
|
+
width: 0; /* the flex basis, not the intrinsic ~150px — see .card */
|
|
70
131
|
min-width: 0;
|
|
132
|
+
border: 0;
|
|
133
|
+
background: none;
|
|
134
|
+
color: var(--fg);
|
|
135
|
+
font: inherit;
|
|
136
|
+
font-variant-numeric: tabular-nums;
|
|
137
|
+
text-align: right;
|
|
138
|
+
outline: none;
|
|
139
|
+
-moz-appearance: textfield;
|
|
140
|
+
appearance: textfield;
|
|
141
|
+
}
|
|
142
|
+
.dim input::-webkit-outer-spin-button,
|
|
143
|
+
.dim input::-webkit-inner-spin-button {
|
|
144
|
+
-webkit-appearance: none;
|
|
145
|
+
margin: 0;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
.segmented {
|
|
149
|
+
display: inline-flex;
|
|
150
|
+
padding: 2px;
|
|
151
|
+
border-radius: 999px;
|
|
152
|
+
background: var(--bg2);
|
|
153
|
+
border: 1px solid var(--line);
|
|
154
|
+
}
|
|
155
|
+
.segmented button {
|
|
156
|
+
border: 0;
|
|
157
|
+
background: none;
|
|
158
|
+
color: var(--fg2);
|
|
159
|
+
font-size: var(--fs-xs);
|
|
160
|
+
padding: 3px 10px;
|
|
161
|
+
border-radius: 999px;
|
|
162
|
+
cursor: pointer;
|
|
163
|
+
line-height: 1.3;
|
|
164
|
+
}
|
|
165
|
+
.segmented button[aria-checked="true"] {
|
|
166
|
+
background: var(--bg);
|
|
167
|
+
color: var(--fg);
|
|
168
|
+
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.25);
|
|
169
|
+
}
|
|
170
|
+
.segmented button:focus-visible {
|
|
171
|
+
outline: 2px solid var(--ring);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/* --- Material tiles: swatch image + label, the panel's cards at a
|
|
175
|
+
quarter of the size. Selection is a neutral ring, as there. */
|
|
176
|
+
.tiles {
|
|
177
|
+
display: grid;
|
|
178
|
+
grid-template-columns: repeat(auto-fill, minmax(74px, 1fr));
|
|
179
|
+
gap: 8px;
|
|
180
|
+
}
|
|
181
|
+
.tile {
|
|
182
|
+
position: relative;
|
|
183
|
+
display: grid;
|
|
184
|
+
gap: 5px;
|
|
185
|
+
padding: 0;
|
|
186
|
+
border: 0;
|
|
187
|
+
background: none;
|
|
188
|
+
cursor: pointer;
|
|
189
|
+
text-align: left;
|
|
190
|
+
border-radius: var(--r-md);
|
|
191
|
+
}
|
|
192
|
+
.tile-img {
|
|
193
|
+
width: 100%;
|
|
194
|
+
aspect-ratio: 4 / 3;
|
|
195
|
+
object-fit: cover;
|
|
196
|
+
border-radius: var(--r-md);
|
|
197
|
+
background: var(--bg2);
|
|
198
|
+
border: 1px solid var(--line);
|
|
199
|
+
display: grid;
|
|
200
|
+
place-items: center;
|
|
201
|
+
box-sizing: border-box;
|
|
202
|
+
color: var(--fg2);
|
|
203
|
+
font-size: var(--fs-sm);
|
|
204
|
+
font-weight: 600;
|
|
205
|
+
transition: box-shadow 120ms ease;
|
|
206
|
+
}
|
|
207
|
+
.tile[aria-checked="true"] .tile-img {
|
|
208
|
+
box-shadow: 0 0 0 2px var(--fg);
|
|
209
|
+
border-color: transparent;
|
|
210
|
+
}
|
|
211
|
+
.tile:focus-visible {
|
|
212
|
+
outline: 2px solid var(--ring);
|
|
213
|
+
outline-offset: 2px;
|
|
214
|
+
}
|
|
215
|
+
.tile-label {
|
|
216
|
+
font-size: var(--fs-xs);
|
|
217
|
+
line-height: 1.25;
|
|
218
|
+
color: var(--fg);
|
|
219
|
+
}
|
|
220
|
+
.tile[aria-disabled="true"] .tile-label {
|
|
221
|
+
color: var(--fg2);
|
|
222
|
+
}
|
|
223
|
+
.crown {
|
|
224
|
+
position: absolute;
|
|
225
|
+
top: 4px;
|
|
226
|
+
right: 4px;
|
|
227
|
+
width: 16px;
|
|
228
|
+
height: 16px;
|
|
229
|
+
border-radius: 999px;
|
|
230
|
+
background: rgba(0, 0, 0, 0.55);
|
|
231
|
+
color: var(--pro);
|
|
232
|
+
display: grid;
|
|
233
|
+
place-items: center;
|
|
234
|
+
}
|
|
235
|
+
.crown svg {
|
|
236
|
+
width: 10px;
|
|
237
|
+
height: 10px;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
.disclosure {
|
|
241
|
+
display: flex;
|
|
242
|
+
align-items: center;
|
|
243
|
+
gap: 6px;
|
|
244
|
+
background: none;
|
|
245
|
+
border: 0;
|
|
246
|
+
padding: 2px 0;
|
|
247
|
+
color: var(--fg2);
|
|
248
|
+
font-size: var(--fs-xs);
|
|
249
|
+
cursor: pointer;
|
|
250
|
+
justify-self: start;
|
|
251
|
+
}
|
|
252
|
+
.disclosure svg {
|
|
253
|
+
width: 12px;
|
|
254
|
+
height: 12px;
|
|
255
|
+
transition: transform 150ms ease;
|
|
256
|
+
}
|
|
257
|
+
.disclosure[aria-expanded="true"] svg {
|
|
258
|
+
transform: rotate(90deg);
|
|
259
|
+
}
|
|
260
|
+
.disclosure:focus-visible {
|
|
261
|
+
outline: 2px solid var(--ring);
|
|
262
|
+
outline-offset: 2px;
|
|
263
|
+
border-radius: 4px;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/* --- The selected material's own controls (finish, colour), boxed the
|
|
267
|
+
way the panel boxes them under the selected card. */
|
|
268
|
+
.sub {
|
|
269
|
+
display: grid;
|
|
270
|
+
grid-template-columns: minmax(0, 1fr);
|
|
271
|
+
gap: 10px;
|
|
272
|
+
padding: 10px;
|
|
273
|
+
border: 1px solid var(--line);
|
|
274
|
+
border-radius: var(--r-md);
|
|
275
|
+
}
|
|
276
|
+
.sub-row {
|
|
277
|
+
display: flex;
|
|
278
|
+
align-items: center;
|
|
279
|
+
justify-content: space-between;
|
|
280
|
+
gap: 8px;
|
|
281
|
+
}
|
|
282
|
+
.sub-label {
|
|
283
|
+
font-size: var(--fs-xs);
|
|
284
|
+
color: var(--fg2);
|
|
285
|
+
display: flex;
|
|
286
|
+
align-items: center;
|
|
287
|
+
gap: 6px;
|
|
288
|
+
}
|
|
289
|
+
.sub-label svg {
|
|
290
|
+
width: 13px;
|
|
291
|
+
height: 13px;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
.color-controls {
|
|
295
|
+
display: flex;
|
|
296
|
+
align-items: center;
|
|
297
|
+
gap: 8px;
|
|
298
|
+
}
|
|
299
|
+
.color-dot {
|
|
300
|
+
position: relative;
|
|
301
|
+
width: 30px;
|
|
302
|
+
height: 30px;
|
|
303
|
+
border-radius: 999px;
|
|
304
|
+
border: 1px solid var(--line);
|
|
305
|
+
box-shadow: inset 0 0 0 2px var(--bg);
|
|
306
|
+
cursor: pointer;
|
|
307
|
+
flex: none;
|
|
71
308
|
box-sizing: border-box;
|
|
72
309
|
}
|
|
73
|
-
.
|
|
74
|
-
|
|
75
|
-
|
|
310
|
+
.color-dot input {
|
|
311
|
+
position: absolute;
|
|
312
|
+
inset: 0;
|
|
313
|
+
width: 100%;
|
|
314
|
+
height: 100%;
|
|
315
|
+
opacity: 0;
|
|
316
|
+
cursor: pointer;
|
|
317
|
+
}
|
|
318
|
+
.color-dot:focus-within {
|
|
319
|
+
outline: 2px solid var(--ring);
|
|
76
320
|
outline-offset: 1px;
|
|
77
321
|
}
|
|
322
|
+
.hex {
|
|
323
|
+
display: flex;
|
|
324
|
+
align-items: center;
|
|
325
|
+
gap: 1px;
|
|
326
|
+
padding: 0 8px;
|
|
327
|
+
height: 30px;
|
|
328
|
+
border-radius: var(--r-md);
|
|
329
|
+
background: var(--bg2);
|
|
330
|
+
border: 1px solid var(--line);
|
|
331
|
+
font-size: var(--fs-xs);
|
|
332
|
+
font-variant-numeric: tabular-nums;
|
|
333
|
+
box-sizing: border-box;
|
|
334
|
+
}
|
|
335
|
+
.hex:focus-within {
|
|
336
|
+
outline: 2px solid var(--ring);
|
|
337
|
+
outline-offset: 1px;
|
|
338
|
+
}
|
|
339
|
+
.hash {
|
|
340
|
+
color: var(--fg2);
|
|
341
|
+
}
|
|
342
|
+
.hex input {
|
|
343
|
+
width: 62px;
|
|
344
|
+
border: 0;
|
|
345
|
+
background: none;
|
|
346
|
+
color: var(--fg);
|
|
347
|
+
font: inherit;
|
|
348
|
+
text-transform: uppercase;
|
|
349
|
+
letter-spacing: 0.05em;
|
|
350
|
+
outline: none;
|
|
351
|
+
}
|
|
352
|
+
.pantone {
|
|
353
|
+
margin-left: auto;
|
|
354
|
+
display: flex;
|
|
355
|
+
align-items: center;
|
|
356
|
+
gap: 6px;
|
|
357
|
+
font-size: var(--fs-xs);
|
|
358
|
+
color: var(--fg2);
|
|
359
|
+
white-space: nowrap;
|
|
360
|
+
}
|
|
361
|
+
.pantone i {
|
|
362
|
+
width: 14px;
|
|
363
|
+
height: 14px;
|
|
364
|
+
border-radius: 999px;
|
|
365
|
+
border: 1px solid var(--line);
|
|
366
|
+
display: inline-block;
|
|
367
|
+
flex: none;
|
|
368
|
+
}
|
|
369
|
+
.chips {
|
|
370
|
+
display: grid;
|
|
371
|
+
grid-template-columns: repeat(12, 1fr);
|
|
372
|
+
gap: 5px;
|
|
373
|
+
}
|
|
374
|
+
.chip {
|
|
375
|
+
aspect-ratio: 1;
|
|
376
|
+
width: 100%;
|
|
377
|
+
border-radius: 999px;
|
|
378
|
+
border: 1px solid rgba(0, 0, 0, 0.18);
|
|
379
|
+
padding: 0;
|
|
380
|
+
cursor: pointer;
|
|
381
|
+
box-sizing: border-box;
|
|
382
|
+
}
|
|
383
|
+
.chip[aria-selected="true"] {
|
|
384
|
+
box-shadow:
|
|
385
|
+
0 0 0 2px var(--bg),
|
|
386
|
+
0 0 0 4px var(--fg);
|
|
387
|
+
}
|
|
388
|
+
.chip:focus-visible {
|
|
389
|
+
outline: 2px solid var(--ring);
|
|
390
|
+
outline-offset: 2px;
|
|
391
|
+
}
|
|
392
|
+
.fineprint {
|
|
393
|
+
font-size: 10px;
|
|
394
|
+
line-height: 1.4;
|
|
395
|
+
color: var(--fg2);
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
/* --- Print style: Solid / Hollow, each with its own price, as the
|
|
399
|
+
panel's two cards. Hollow carries the Pro crown. */
|
|
400
|
+
.styles {
|
|
401
|
+
display: grid;
|
|
402
|
+
grid-template-columns: 1fr 1fr;
|
|
403
|
+
gap: 8px;
|
|
404
|
+
}
|
|
405
|
+
.style {
|
|
406
|
+
display: grid;
|
|
407
|
+
gap: 2px;
|
|
408
|
+
text-align: left;
|
|
409
|
+
padding: 8px 10px;
|
|
410
|
+
border-radius: var(--r-md);
|
|
411
|
+
border: 1px solid var(--line);
|
|
412
|
+
background: var(--bg2);
|
|
413
|
+
cursor: pointer;
|
|
414
|
+
transition: box-shadow 120ms ease;
|
|
415
|
+
}
|
|
416
|
+
.style[aria-checked="true"] {
|
|
417
|
+
box-shadow: 0 0 0 2px var(--fg);
|
|
418
|
+
border-color: transparent;
|
|
419
|
+
}
|
|
420
|
+
.style:focus-visible {
|
|
421
|
+
outline: 2px solid var(--ring);
|
|
422
|
+
outline-offset: 2px;
|
|
423
|
+
}
|
|
424
|
+
.style-name {
|
|
425
|
+
font-size: var(--fs-xs);
|
|
426
|
+
font-weight: 600;
|
|
427
|
+
display: flex;
|
|
428
|
+
align-items: center;
|
|
429
|
+
gap: 5px;
|
|
430
|
+
}
|
|
431
|
+
.style-price {
|
|
432
|
+
font-size: var(--fs-xs);
|
|
433
|
+
color: var(--fg2);
|
|
434
|
+
font-variant-numeric: tabular-nums;
|
|
435
|
+
transition: opacity 120ms ease;
|
|
436
|
+
}
|
|
437
|
+
.pro {
|
|
438
|
+
font-size: 9px;
|
|
439
|
+
font-weight: 700;
|
|
440
|
+
letter-spacing: 0.04em;
|
|
441
|
+
padding: 1px 5px;
|
|
442
|
+
border-radius: 999px;
|
|
443
|
+
background: rgba(240, 196, 83, 0.18);
|
|
444
|
+
color: var(--pro);
|
|
445
|
+
}
|
|
78
446
|
|
|
447
|
+
/* --- Review row: quantity on the left, the price for it on the right. */
|
|
448
|
+
.review {
|
|
449
|
+
display: flex;
|
|
450
|
+
align-items: center;
|
|
451
|
+
justify-content: space-between;
|
|
452
|
+
gap: 10px;
|
|
453
|
+
}
|
|
454
|
+
.stepper {
|
|
455
|
+
display: inline-flex;
|
|
456
|
+
align-items: center;
|
|
457
|
+
height: 30px;
|
|
458
|
+
border-radius: 999px;
|
|
459
|
+
background: var(--bg2);
|
|
460
|
+
border: 1px solid var(--line);
|
|
461
|
+
box-sizing: border-box;
|
|
462
|
+
}
|
|
463
|
+
.stepper button {
|
|
464
|
+
width: 30px;
|
|
465
|
+
height: 28px;
|
|
466
|
+
border: 0;
|
|
467
|
+
background: none;
|
|
468
|
+
font-size: 15px;
|
|
469
|
+
line-height: 1;
|
|
470
|
+
cursor: pointer;
|
|
471
|
+
border-radius: 999px;
|
|
472
|
+
}
|
|
473
|
+
.stepper button:disabled {
|
|
474
|
+
color: var(--fg2);
|
|
475
|
+
cursor: default;
|
|
476
|
+
}
|
|
477
|
+
.stepper button:focus-visible {
|
|
478
|
+
outline: 2px solid var(--ring);
|
|
479
|
+
}
|
|
480
|
+
.stepper input {
|
|
481
|
+
width: 32px;
|
|
482
|
+
text-align: center;
|
|
483
|
+
border: 0;
|
|
484
|
+
background: none;
|
|
485
|
+
color: var(--fg);
|
|
486
|
+
font: inherit;
|
|
487
|
+
font-size: var(--fs-sm);
|
|
488
|
+
font-variant-numeric: tabular-nums;
|
|
489
|
+
outline: none;
|
|
490
|
+
-moz-appearance: textfield;
|
|
491
|
+
appearance: textfield;
|
|
492
|
+
}
|
|
493
|
+
.stepper input::-webkit-outer-spin-button,
|
|
494
|
+
.stepper input::-webkit-inner-spin-button {
|
|
495
|
+
-webkit-appearance: none;
|
|
496
|
+
margin: 0;
|
|
497
|
+
}
|
|
79
498
|
.price {
|
|
80
|
-
|
|
499
|
+
text-align: right;
|
|
500
|
+
display: grid;
|
|
501
|
+
gap: 1px;
|
|
502
|
+
transition: opacity 120ms ease;
|
|
503
|
+
}
|
|
504
|
+
.price-main {
|
|
81
505
|
display: flex;
|
|
82
506
|
align-items: baseline;
|
|
507
|
+
justify-content: flex-end;
|
|
83
508
|
gap: 8px;
|
|
84
|
-
|
|
509
|
+
flex-wrap: wrap;
|
|
85
510
|
}
|
|
86
|
-
.price:empty { display: none; }
|
|
87
511
|
.amount {
|
|
88
|
-
font-size:
|
|
512
|
+
font-size: 22px;
|
|
89
513
|
font-weight: 700;
|
|
90
514
|
letter-spacing: -0.02em;
|
|
515
|
+
font-variant-numeric: tabular-nums;
|
|
91
516
|
}
|
|
92
517
|
.was {
|
|
93
|
-
font-size: var(--
|
|
94
|
-
color: var(--
|
|
518
|
+
font-size: var(--fs-xs);
|
|
519
|
+
color: var(--fg2);
|
|
95
520
|
text-decoration: line-through;
|
|
521
|
+
font-variant-numeric: tabular-nums;
|
|
96
522
|
}
|
|
97
|
-
.
|
|
98
|
-
font-size:
|
|
99
|
-
|
|
523
|
+
.pill {
|
|
524
|
+
font-size: 10px;
|
|
525
|
+
padding: 2px 7px;
|
|
526
|
+
border-radius: 999px;
|
|
527
|
+
background: rgba(79, 191, 122, 0.16);
|
|
528
|
+
color: var(--ok);
|
|
529
|
+
}
|
|
530
|
+
.price-sub {
|
|
531
|
+
font-size: var(--fs-xs);
|
|
532
|
+
color: var(--fg2);
|
|
533
|
+
display: flex;
|
|
534
|
+
justify-content: flex-end;
|
|
535
|
+
align-items: center;
|
|
536
|
+
gap: 6px;
|
|
537
|
+
flex-wrap: wrap;
|
|
538
|
+
}
|
|
539
|
+
.quoting .price,
|
|
540
|
+
.quoting .style-price {
|
|
541
|
+
opacity: 0.35;
|
|
100
542
|
}
|
|
101
543
|
|
|
102
|
-
.
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
544
|
+
/* --- Callouts: mesh repair, size bounds, Enterprise, hollow hand-off. */
|
|
545
|
+
.callouts:empty {
|
|
546
|
+
display: none;
|
|
547
|
+
}
|
|
548
|
+
.callouts {
|
|
106
549
|
display: grid;
|
|
107
|
-
gap:
|
|
108
|
-
|
|
550
|
+
gap: 8px;
|
|
551
|
+
}
|
|
552
|
+
.callout {
|
|
553
|
+
display: flex;
|
|
554
|
+
gap: 8px;
|
|
555
|
+
align-items: flex-start;
|
|
556
|
+
padding: 8px 10px;
|
|
557
|
+
border-radius: var(--r-md);
|
|
558
|
+
border: 1px solid var(--line);
|
|
559
|
+
font-size: var(--fs-xs);
|
|
560
|
+
line-height: 1.45;
|
|
561
|
+
}
|
|
562
|
+
.callout svg {
|
|
563
|
+
width: 14px;
|
|
564
|
+
height: 14px;
|
|
565
|
+
flex: none;
|
|
566
|
+
margin-top: 1px;
|
|
567
|
+
color: var(--fg2);
|
|
568
|
+
}
|
|
569
|
+
.callout.warn {
|
|
570
|
+
border-color: rgba(224, 168, 58, 0.45);
|
|
571
|
+
}
|
|
572
|
+
.callout.warn svg {
|
|
573
|
+
color: var(--warn);
|
|
574
|
+
}
|
|
575
|
+
.callout.danger {
|
|
576
|
+
border-color: rgba(255, 128, 128, 0.45);
|
|
577
|
+
}
|
|
578
|
+
.callout.danger svg {
|
|
579
|
+
color: var(--danger);
|
|
580
|
+
}
|
|
581
|
+
.callout a,
|
|
582
|
+
.callout button.link {
|
|
583
|
+
color: inherit;
|
|
584
|
+
text-decoration: underline;
|
|
585
|
+
cursor: pointer;
|
|
586
|
+
background: none;
|
|
587
|
+
border: 0;
|
|
588
|
+
padding: 0;
|
|
589
|
+
font: inherit;
|
|
109
590
|
}
|
|
110
|
-
.rows:empty { display: none; }
|
|
111
591
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
592
|
+
.summary {
|
|
593
|
+
font-size: var(--fs-xs);
|
|
594
|
+
color: var(--fg2);
|
|
595
|
+
}
|
|
115
596
|
|
|
116
597
|
.cta {
|
|
117
|
-
margin-top: 12px;
|
|
118
598
|
display: flex;
|
|
119
599
|
width: 100%;
|
|
120
600
|
align-items: center;
|
|
@@ -122,71 +602,174 @@
|
|
|
122
602
|
gap: 6px;
|
|
123
603
|
border: 0;
|
|
124
604
|
cursor: pointer;
|
|
125
|
-
font:
|
|
126
|
-
font-size: var(--font-text-sm-size, 13px);
|
|
605
|
+
font-size: var(--fs-sm);
|
|
127
606
|
font-weight: 600;
|
|
128
607
|
padding: 9px 12px;
|
|
129
|
-
border-radius:
|
|
608
|
+
border-radius: 999px;
|
|
130
609
|
color: #fff;
|
|
131
|
-
background: var(--
|
|
610
|
+
background: var(--accent);
|
|
611
|
+
}
|
|
612
|
+
.cta:hover:not(:disabled) {
|
|
613
|
+
filter: brightness(1.1);
|
|
614
|
+
}
|
|
615
|
+
.cta:focus-visible {
|
|
616
|
+
outline: 2px solid var(--ring);
|
|
617
|
+
outline-offset: 1px;
|
|
618
|
+
}
|
|
619
|
+
.cta:disabled {
|
|
620
|
+
opacity: 0.55;
|
|
621
|
+
cursor: default;
|
|
622
|
+
}
|
|
623
|
+
.cta svg {
|
|
624
|
+
width: 14px;
|
|
625
|
+
height: 14px;
|
|
626
|
+
display: block;
|
|
627
|
+
}
|
|
628
|
+
.foot {
|
|
629
|
+
display: grid;
|
|
630
|
+
gap: 6px;
|
|
132
631
|
}
|
|
133
|
-
.cta:hover:not(:disabled) { filter: brightness(1.1); }
|
|
134
|
-
.cta:focus-visible { outline: 2px solid var(--color-ring-primary, #7aa2ff); outline-offset: 1px; }
|
|
135
|
-
.cta[hidden] { display: none; }
|
|
136
|
-
.cta:disabled { opacity: 0.55; cursor: default; }
|
|
137
|
-
.cta svg { width: 14px; height: 14px; display: block; }
|
|
138
|
-
|
|
139
632
|
.note {
|
|
140
|
-
margin-top: 8px;
|
|
141
633
|
font-size: 10px;
|
|
142
|
-
color: var(--
|
|
634
|
+
color: var(--fg2);
|
|
635
|
+
line-height: 1.4;
|
|
143
636
|
}
|
|
144
|
-
.note[hidden] { display: none; }
|
|
145
|
-
|
|
146
637
|
.status {
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
638
|
+
font-size: var(--fs-xs);
|
|
639
|
+
color: var(--fg2);
|
|
640
|
+
line-height: 1.4;
|
|
641
|
+
}
|
|
642
|
+
.status:empty {
|
|
643
|
+
display: none;
|
|
644
|
+
}
|
|
645
|
+
.status.error {
|
|
646
|
+
color: var(--danger);
|
|
150
647
|
}
|
|
151
|
-
.status:empty { display: none; }
|
|
152
|
-
.status.error { color: var(--color-text-danger, #ff8888); }
|
|
153
648
|
</style>
|
|
154
649
|
</head>
|
|
155
650
|
<body>
|
|
156
651
|
<div class="card" id="card">
|
|
157
652
|
<div class="head">
|
|
158
653
|
<div class="title">3D print</div>
|
|
159
|
-
<div class="
|
|
654
|
+
<div class="dims" id="dims"></div>
|
|
655
|
+
</div>
|
|
656
|
+
|
|
657
|
+
<div class="callouts" id="mesh-callouts"></div>
|
|
658
|
+
|
|
659
|
+
<div class="summary" id="summary" hidden></div>
|
|
660
|
+
|
|
661
|
+
<div class="section" id="size-section" hidden>
|
|
662
|
+
<div class="label-row">
|
|
663
|
+
<span class="label">Size</span>
|
|
664
|
+
<div class="segmented" id="unit" role="radiogroup" aria-label="Unit">
|
|
665
|
+
<button type="button" role="radio" data-unit="cm" aria-checked="true">cm</button>
|
|
666
|
+
<button type="button" role="radio" data-unit="in" aria-checked="false">in</button>
|
|
667
|
+
</div>
|
|
668
|
+
</div>
|
|
669
|
+
<div class="dim-grid">
|
|
670
|
+
<label class="dim"><span>W</span><input id="dim-width" type="number" inputmode="decimal" step="any" min="0" /></label>
|
|
671
|
+
<label class="dim"><span>H</span><input id="dim-height" type="number" inputmode="decimal" step="any" min="0" /></label>
|
|
672
|
+
<label class="dim"><span>D</span><input id="dim-depth" type="number" inputmode="decimal" step="any" min="0" /></label>
|
|
673
|
+
</div>
|
|
674
|
+
<div class="callouts" id="size-callouts"></div>
|
|
675
|
+
</div>
|
|
676
|
+
|
|
677
|
+
<div class="section" id="material-section" hidden>
|
|
678
|
+
<div class="label-row"><span class="label">Material</span></div>
|
|
679
|
+
<div class="tiles" id="tiles-standard" role="radiogroup" aria-label="Material"></div>
|
|
680
|
+
<button class="disclosure" id="enterprise-toggle" type="button" aria-expanded="false" hidden>
|
|
681
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><path d="m9 6 6 6-6 6" /></svg>
|
|
682
|
+
<span id="enterprise-label">Enterprise materials</span>
|
|
683
|
+
</button>
|
|
684
|
+
<div class="tiles" id="tiles-enterprise" role="radiogroup" aria-label="Enterprise materials" hidden></div>
|
|
685
|
+
<div class="callouts" id="material-callouts"></div>
|
|
686
|
+
|
|
687
|
+
<div class="sub" id="sub" hidden>
|
|
688
|
+
<div class="sub-row" id="finish-row" hidden>
|
|
689
|
+
<span class="sub-label">
|
|
690
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M3 6a3 3 0 0 1 3-3h12a3 3 0 0 1 3 3v12a3 3 0 0 1-3 3H6a3 3 0 0 1-3-3Z" /><path d="M3 12h18M12 3v18" /></svg>
|
|
691
|
+
Finish
|
|
692
|
+
</span>
|
|
693
|
+
<div class="segmented" id="finish" role="radiogroup" aria-label="Finish"></div>
|
|
694
|
+
</div>
|
|
695
|
+
<div class="sub-row" id="color-mode-row" hidden>
|
|
696
|
+
<span class="sub-label">Color mode</span>
|
|
697
|
+
<div class="segmented" id="color-mode" role="radiogroup" aria-label="Color mode">
|
|
698
|
+
<button type="button" role="radio" data-mode="original" aria-checked="true">Original</button>
|
|
699
|
+
<button type="button" role="radio" data-mode="custom" aria-checked="false">Custom</button>
|
|
700
|
+
</div>
|
|
701
|
+
</div>
|
|
702
|
+
<div id="color-block" hidden style="display: grid; gap: 8px">
|
|
703
|
+
<div class="sub-row">
|
|
704
|
+
<span class="sub-label">
|
|
705
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="m19 11-8-8-8.6 8.6a2 2 0 0 0 0 2.8l5.2 5.2c.8.8 2 .8 2.8 0L19 11Z" /><path d="m5 2 5 5" /><path d="M2 13h15" /><path d="M22 20a2 2 0 1 1-4 0c0-1.6 1.7-2.4 2-4 .3 1.6 2 2.4 2 4Z" /></svg>
|
|
706
|
+
Color
|
|
707
|
+
</span>
|
|
708
|
+
<span class="pantone" id="pantone"></span>
|
|
709
|
+
</div>
|
|
710
|
+
<div class="color-controls">
|
|
711
|
+
<label class="color-dot" id="color-dot" title="Pick any color">
|
|
712
|
+
<input type="color" id="color-native" aria-label="Pick any color" />
|
|
713
|
+
</label>
|
|
714
|
+
<div class="hex">
|
|
715
|
+
<span class="hash">#</span>
|
|
716
|
+
<input id="color-hex" maxlength="6" spellcheck="false" autocomplete="off" aria-label="Hex color" />
|
|
717
|
+
</div>
|
|
718
|
+
</div>
|
|
719
|
+
<div class="chips" id="chips" role="listbox" aria-label="Pantone colors"></div>
|
|
720
|
+
<div class="fineprint">
|
|
721
|
+
Matched to the nearest Pantone shade. Printed colors come out lighter and less saturated than on screen.
|
|
722
|
+
</div>
|
|
723
|
+
</div>
|
|
724
|
+
</div>
|
|
725
|
+
</div>
|
|
726
|
+
|
|
727
|
+
<div class="section" id="style-section" hidden>
|
|
728
|
+
<div class="label-row"><span class="label">Print style</span></div>
|
|
729
|
+
<div class="styles" role="radiogroup" aria-label="Print style">
|
|
730
|
+
<button class="style" type="button" role="radio" data-style="solid" aria-checked="true">
|
|
731
|
+
<span class="style-name">Solid</span>
|
|
732
|
+
<span class="style-price" id="price-solid"></span>
|
|
733
|
+
</button>
|
|
734
|
+
<button class="style" type="button" role="radio" data-style="hollow" aria-checked="false">
|
|
735
|
+
<span class="style-name">
|
|
736
|
+
Hollow
|
|
737
|
+
<span class="pro" id="hollow-pro">Pro</span>
|
|
738
|
+
</span>
|
|
739
|
+
<span class="style-price" id="price-hollow"></span>
|
|
740
|
+
</button>
|
|
741
|
+
</div>
|
|
742
|
+
<div class="callouts" id="style-callouts"></div>
|
|
160
743
|
</div>
|
|
161
744
|
|
|
162
|
-
<div class="
|
|
163
|
-
<
|
|
164
|
-
|
|
165
|
-
<
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
<
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
<
|
|
174
|
-
|
|
745
|
+
<div class="review" id="review" hidden>
|
|
746
|
+
<div class="stepper" aria-label="Quantity">
|
|
747
|
+
<button type="button" id="qty-dec" aria-label="Fewer copies">−</button>
|
|
748
|
+
<input id="qty" type="number" inputmode="numeric" min="1" max="100" aria-label="Quantity" />
|
|
749
|
+
<button type="button" id="qty-inc" aria-label="More copies">+</button>
|
|
750
|
+
</div>
|
|
751
|
+
<div class="price" id="price">
|
|
752
|
+
<div class="price-main">
|
|
753
|
+
<span class="amount" id="amount"></span>
|
|
754
|
+
<span class="was" id="was" hidden></span>
|
|
755
|
+
</div>
|
|
756
|
+
<div class="price-sub">
|
|
757
|
+
<span class="pill" id="pill" hidden></span>
|
|
758
|
+
<span id="price-sub"></span>
|
|
759
|
+
</div>
|
|
760
|
+
</div>
|
|
175
761
|
</div>
|
|
176
762
|
|
|
177
|
-
<div class="
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
<
|
|
183
|
-
</
|
|
184
|
-
<
|
|
185
|
-
|
|
186
|
-
<div class="note" id="note" hidden>
|
|
187
|
-
Shipping is added at checkout; the final price is confirmed before printing.
|
|
763
|
+
<div class="foot">
|
|
764
|
+
<button class="cta" id="cta" hidden>
|
|
765
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round">
|
|
766
|
+
<path d="M7 17 17 7M9 7h8v8" />
|
|
767
|
+
</svg>
|
|
768
|
+
<span id="cta-label">Add to cart</span>
|
|
769
|
+
</button>
|
|
770
|
+
<div class="note" id="note" hidden>Shipping is added at checkout. The final price is confirmed before printing.</div>
|
|
771
|
+
<div class="status" id="status">Connecting…</div>
|
|
188
772
|
</div>
|
|
189
|
-
<div class="status" id="status">Connecting…</div>
|
|
190
773
|
</div>
|
|
191
774
|
<script type="module" src="./main.ts"></script>
|
|
192
775
|
</body>
|