@womp/mcp-ui 0.1.6 → 0.1.8

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.
@@ -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(--color-text-primary, #e8e8e8);
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(--font-text-sm-size, 13px);
73
+ font-size: var(--fs-sm);
37
74
  font-weight: 600;
38
75
  }
39
- .size {
40
- font-size: var(--font-text-xs-size, 11px);
41
- color: var(--color-text-secondary, rgba(232, 232, 232, 0.6));
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
- /* The configurator: three labelled controls in a row. Hidden entirely in
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 76px 64px;
85
+ grid-template-columns: minmax(0, 1fr);
52
86
  gap: 8px;
53
87
  }
54
- .controls[hidden] { display: none; }
55
- .field {
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
- gap: 3px;
58
- font-size: 10px;
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
- .field select,
62
- .field input {
63
- font: inherit;
64
- font-size: var(--font-text-xs-size, 12px);
65
- color: var(--color-text-primary, #e8e8e8);
66
- background: var(--color-background-tertiary, #2a2a2e);
67
- border: 1px solid var(--color-border-primary, rgba(255, 255, 255, 0.1));
68
- border-radius: var(--border-radius-md, 8px);
69
- padding: 6px 8px;
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;
71
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);
72
222
  }
73
- .field select:focus-visible,
74
- .field input:focus-visible {
75
- outline: 2px solid var(--color-ring-primary, #7aa2ff);
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;
308
+ box-sizing: border-box;
309
+ }
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
- margin-top: 12px;
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
- transition: opacity 120ms ease;
509
+ flex-wrap: wrap;
85
510
  }
86
- .price:empty { display: none; }
87
511
  .amount {
88
- font-size: 24px;
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(--font-text-xs-size, 12px);
94
- color: var(--color-text-secondary, rgba(232, 232, 232, 0.6));
518
+ font-size: var(--fs-xs);
519
+ color: var(--fg2);
95
520
  text-decoration: line-through;
521
+ font-variant-numeric: tabular-nums;
522
+ }
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);
96
529
  }
97
- .per {
98
- font-size: var(--font-text-xs-size, 11px);
99
- color: var(--color-text-secondary, rgba(232, 232, 232, 0.6));
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
- .rows {
103
- margin-top: 6px;
104
- font-size: var(--font-text-xs-size, 11px);
105
- color: var(--color-text-secondary, rgba(232, 232, 232, 0.6));
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: 2px;
108
- transition: opacity 120ms ease;
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
- /* Re-quoting: dim the numbers that are about to change, keep the layout. */
113
- .quoting .price,
114
- .quoting .rows { opacity: 0.35; }
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,88 +602,174 @@
122
602
  gap: 6px;
123
603
  border: 0;
124
604
  cursor: pointer;
125
- font: inherit;
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: var(--border-radius-full, 999px);
608
+ border-radius: 999px;
130
609
  color: #fff;
131
- background: var(--color-background-accent, #5867dd);
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(--color-text-secondary, rgba(232, 232, 232, 0.5));
634
+ color: var(--fg2);
635
+ line-height: 1.4;
143
636
  }
144
- .note[hidden] { display: none; }
145
-
146
637
  .status {
147
- margin-top: 8px;
148
- font-size: var(--font-text-xs-size, 11px);
149
- color: var(--color-text-secondary, rgba(232, 232, 232, 0.6));
150
- }
151
- .status:empty { display: none; }
152
- .status.error { color: var(--color-text-danger, #ff8888); }
153
- .material-row {
154
- display: inline-flex;
155
- align-items: center;
156
- gap: 6px;
157
- }
158
- /* Small, and it disappears entirely when the catalog has no swatch for the
159
- selection — an empty box next to a picker reads as a broken image. */
160
- .swatch {
161
- width: 28px;
162
- height: 20px;
163
- object-fit: cover;
164
- border-radius: 4px;
165
- flex: none;
166
- }
167
- </style>
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);
647
+ }
648
+ </style>
168
649
  </head>
169
650
  <body>
170
651
  <div class="card" id="card">
171
652
  <div class="head">
172
653
  <div class="title">3D print</div>
173
- <div class="size" id="size"></div>
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>
174
743
  </div>
175
744
 
176
- <div class="controls" id="controls" hidden>
177
- <label class="field">
178
- material
179
- <span class="material-row">
180
- <select id="material"></select>
181
- <img id="swatch" class="swatch" alt="" hidden />
182
- </span>
183
- </label>
184
- <label class="field">
185
- size (cm)
186
- <input id="longest" type="number" min="2" max="60" step="0.5" />
187
- </label>
188
- <label class="field">
189
- qty
190
- <input id="quantity" type="number" min="1" max="100" step="1" />
191
- </label>
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">&minus;</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>
192
761
  </div>
193
762
 
194
- <div class="price" id="price"></div>
195
- <div class="rows" id="rows"></div>
196
-
197
- <button class="cta" id="order" hidden>
198
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round">
199
- <path d="M7 17 17 7M9 7h8v8" />
200
- </svg>
201
- <span id="order-label">Add to cart</span>
202
- </button>
203
- <div class="note" id="note" hidden>
204
- 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&hellip;</div>
205
772
  </div>
206
- <div class="status" id="status">Connecting&hellip;</div>
207
773
  </div>
208
774
  <script type="module" src="./main.ts"></script>
209
775
  </body>