@primestyleai/tryon 2.0.0 → 2.0.2

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.
@@ -1,12 +1,67 @@
1
1
  "use client";
2
2
  import { jsxs, jsx, Fragment } from "react/jsx-runtime";
3
- import { useState, useRef, useEffect, useCallback } from "react";
3
+ import { useState, useRef, useEffect, useMemo, useCallback } from "react";
4
4
  import { A as ApiClient, S as SseClient, i as isValidImageFile, c as compressImage, P as PrimeStyleError } from "../image-utils-C9bJ1zKO.js";
5
5
  function cx(base, override) {
6
6
  return override ? `${base} ${override}` : base;
7
7
  }
8
- function CameraIcon({ size = 18 }) {
9
- return /* @__PURE__ */ jsxs(
8
+ const LS_PREFIX = "primestyle_";
9
+ function lsGet(key, fallback) {
10
+ try {
11
+ const raw = localStorage.getItem(LS_PREFIX + key);
12
+ return raw ? JSON.parse(raw) : fallback;
13
+ } catch {
14
+ return fallback;
15
+ }
16
+ }
17
+ function lsSet(key, value) {
18
+ try {
19
+ localStorage.setItem(LS_PREFIX + key, JSON.stringify(value));
20
+ } catch {
21
+ }
22
+ }
23
+ const SIZING_COUNTRIES = [
24
+ { code: "US", label: "United States" },
25
+ { code: "UK", label: "United Kingdom" },
26
+ { code: "EU", label: "Europe (EU)" },
27
+ { code: "FR", label: "France" },
28
+ { code: "IT", label: "Italy" },
29
+ { code: "DE", label: "Germany" },
30
+ { code: "ES", label: "Spain" },
31
+ { code: "JP", label: "Japan" },
32
+ { code: "CN", label: "China" },
33
+ { code: "KR", label: "South Korea" },
34
+ { code: "AU", label: "Australia" },
35
+ { code: "BR", label: "Brazil" }
36
+ ];
37
+ const STEP_LABELS = ["", "Welcome", "Photo", "Size", "Generate", "Results"];
38
+ const TOTAL_STEPS = 5;
39
+ function detectLocale() {
40
+ const l = (navigator.language || "en-US").toLowerCase();
41
+ if (l.includes("en-gb") || l.includes("en-au")) return "UK";
42
+ if (l.includes("en")) return "US";
43
+ if (l.includes("fr")) return "FR";
44
+ if (l.includes("it")) return "IT";
45
+ if (l.includes("de") || l.includes("nl")) return "EU";
46
+ if (l.includes("ja")) return "JP";
47
+ if (l.includes("zh")) return "CN";
48
+ if (l.includes("ko")) return "KR";
49
+ return "US";
50
+ }
51
+ function isImperial(locale) {
52
+ return locale === "US" || locale === "UK";
53
+ }
54
+ function inToCm(inches) {
55
+ return +(inches * 2.54).toFixed(1);
56
+ }
57
+ function lbsToKg(lbs) {
58
+ return +(lbs / 2.205).toFixed(1);
59
+ }
60
+ function ftInToCm(ft, inch) {
61
+ return +(ft * 30.48 + inch * 2.54).toFixed(1);
62
+ }
63
+ function SvgIcon({ d, size = 18, strokeWidth = 2 }) {
64
+ return /* @__PURE__ */ jsx(
10
65
  "svg",
11
66
  {
12
67
  width: size,
@@ -14,83 +69,84 @@ function CameraIcon({ size = 18 }) {
14
69
  viewBox: "0 0 24 24",
15
70
  fill: "none",
16
71
  stroke: "currentColor",
17
- strokeWidth: 2,
72
+ strokeWidth,
18
73
  strokeLinecap: "round",
19
74
  strokeLinejoin: "round",
20
- children: [
21
- /* @__PURE__ */ jsx("path", { d: "M23 19a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h4l2-3h6l2 3h4a2 2 0 0 1 2 2z" }),
22
- /* @__PURE__ */ jsx("circle", { cx: "12", cy: "13", r: "4" })
23
- ]
75
+ children: /* @__PURE__ */ jsx("path", { d })
24
76
  }
25
77
  );
26
78
  }
79
+ function CameraIcon({ size = 18 }) {
80
+ return /* @__PURE__ */ jsxs("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round", children: [
81
+ /* @__PURE__ */ jsx("path", { d: "M23 19a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h4l2-3h6l2 3h4a2 2 0 0 1 2 2z" }),
82
+ /* @__PURE__ */ jsx("circle", { cx: "12", cy: "13", r: "4" })
83
+ ] });
84
+ }
27
85
  function UploadIcon({ size = 48 }) {
28
- return /* @__PURE__ */ jsxs(
29
- "svg",
30
- {
31
- width: size,
32
- height: size,
33
- viewBox: "0 0 24 24",
34
- fill: "none",
35
- stroke: "currentColor",
36
- strokeWidth: 1.5,
37
- strokeLinecap: "round",
38
- strokeLinejoin: "round",
39
- children: [
40
- /* @__PURE__ */ jsx("path", { d: "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" }),
41
- /* @__PURE__ */ jsx("polyline", { points: "17 8 12 3 7 8" }),
42
- /* @__PURE__ */ jsx("line", { x1: "12", y1: "3", x2: "12", y2: "15" })
43
- ]
44
- }
45
- );
86
+ return /* @__PURE__ */ jsxs("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 1.5, strokeLinecap: "round", strokeLinejoin: "round", children: [
87
+ /* @__PURE__ */ jsx("path", { d: "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" }),
88
+ /* @__PURE__ */ jsx("polyline", { points: "17 8 12 3 7 8" }),
89
+ /* @__PURE__ */ jsx("line", { x1: "12", y1: "3", x2: "12", y2: "15" })
90
+ ] });
46
91
  }
47
92
  function XIcon({ size = 20 }) {
48
- return /* @__PURE__ */ jsxs(
49
- "svg",
50
- {
51
- width: size,
52
- height: size,
53
- viewBox: "0 0 24 24",
54
- fill: "none",
55
- stroke: "currentColor",
56
- strokeWidth: 2,
57
- strokeLinecap: "round",
58
- strokeLinejoin: "round",
59
- children: [
60
- /* @__PURE__ */ jsx("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
61
- /* @__PURE__ */ jsx("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
62
- ]
63
- }
64
- );
93
+ return /* @__PURE__ */ jsxs("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round", children: [
94
+ /* @__PURE__ */ jsx("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
95
+ /* @__PURE__ */ jsx("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
96
+ ] });
65
97
  }
66
98
  function AlertIcon({ size = 48 }) {
67
- return /* @__PURE__ */ jsxs(
68
- "svg",
69
- {
70
- width: size,
71
- height: size,
72
- viewBox: "0 0 24 24",
73
- fill: "none",
74
- stroke: "currentColor",
75
- strokeWidth: 1.5,
76
- strokeLinecap: "round",
77
- strokeLinejoin: "round",
78
- children: [
79
- /* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "10" }),
80
- /* @__PURE__ */ jsx("line", { x1: "12", y1: "8", x2: "12", y2: "12" }),
81
- /* @__PURE__ */ jsx("line", { x1: "12", y1: "16", x2: "12.01", y2: "16" })
82
- ]
83
- }
84
- );
99
+ return /* @__PURE__ */ jsxs("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 1.5, strokeLinecap: "round", strokeLinejoin: "round", children: [
100
+ /* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "10" }),
101
+ /* @__PURE__ */ jsx("line", { x1: "12", y1: "8", x2: "12", y2: "12" }),
102
+ /* @__PURE__ */ jsx("line", { x1: "12", y1: "16", x2: "12.01", y2: "16" })
103
+ ] });
104
+ }
105
+ function ArrowLeftIcon() {
106
+ return /* @__PURE__ */ jsx("svg", { width: 18, height: 18, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx("path", { d: "M15 18l-6-6 6-6" }) });
107
+ }
108
+ function ArrowRightIcon() {
109
+ return /* @__PURE__ */ jsx("svg", { width: 16, height: 16, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx("path", { d: "M5 12h14M12 5l7 7-7 7" }) });
110
+ }
111
+ function UserIcon({ size = 16 }) {
112
+ return /* @__PURE__ */ jsxs("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round", children: [
113
+ /* @__PURE__ */ jsx("path", { d: "M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2" }),
114
+ /* @__PURE__ */ jsx("circle", { cx: "12", cy: "7", r: "4" })
115
+ ] });
116
+ }
117
+ function ClockIcon({ size = 16 }) {
118
+ return /* @__PURE__ */ jsxs("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round", children: [
119
+ /* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "10" }),
120
+ /* @__PURE__ */ jsx("polyline", { points: "12 6 12 12 16 14" })
121
+ ] });
122
+ }
123
+ function RulerIcon({ size = 18 }) {
124
+ return /* @__PURE__ */ jsxs("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round", children: [
125
+ /* @__PURE__ */ jsx("path", { d: "M21.3 15.3a2.4 2.4 0 0 1 0 3.4l-2.6 2.6a2.4 2.4 0 0 1-3.4 0L2.7 8.7a2.41 2.41 0 0 1 0-3.4l2.6-2.6a2.41 2.41 0 0 1 3.4 0Z" }),
126
+ /* @__PURE__ */ jsx("path", { d: "m14.5 12.5 2-2" }),
127
+ /* @__PURE__ */ jsx("path", { d: "m11.5 9.5 2-2" }),
128
+ /* @__PURE__ */ jsx("path", { d: "m8.5 6.5 2-2" }),
129
+ /* @__PURE__ */ jsx("path", { d: "m17.5 15.5 2-2" })
130
+ ] });
131
+ }
132
+ function SparkleIcon({ size = 18 }) {
133
+ return /* @__PURE__ */ jsx("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx("path", { d: "m12 3-1.912 5.813a2 2 0 0 1-1.275 1.275L3 12l5.813 1.912a2 2 0 0 1 1.275 1.275L12 21l1.912-5.813a2 2 0 0 1 1.275-1.275L21 12l-5.813-1.912a2 2 0 0 1-1.275-1.275L12 3Z" }) });
134
+ }
135
+ function TrashIcon({ size = 14 }) {
136
+ return /* @__PURE__ */ jsxs("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round", children: [
137
+ /* @__PURE__ */ jsx("polyline", { points: "3 6 5 6 21 6" }),
138
+ /* @__PURE__ */ jsx("path", { d: "M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2" })
139
+ ] });
140
+ }
141
+ function ChevronRightIcon() {
142
+ return /* @__PURE__ */ jsx("svg", { width: 16, height: 16, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx("path", { d: "M9 18l6-6-6-6" }) });
143
+ }
144
+ function CheckIcon({ size = 14 }) {
145
+ return /* @__PURE__ */ jsx("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 3, strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx("polyline", { points: "20 6 9 17 4 12" }) });
85
146
  }
86
147
  function getApiKey() {
87
148
  const key = process.env.NEXT_PUBLIC_PRIMESTYLE_API_KEY ?? "";
88
- if (!key) {
89
- throw new PrimeStyleError(
90
- "Missing NEXT_PUBLIC_PRIMESTYLE_API_KEY in environment variables",
91
- "MISSING_API_KEY"
92
- );
93
- }
149
+ if (!key) throw new PrimeStyleError("Missing NEXT_PUBLIC_PRIMESTYLE_API_KEY", "MISSING_API_KEY");
94
150
  return key;
95
151
  }
96
152
  function getApiUrl(override) {
@@ -98,6 +154,7 @@ function getApiUrl(override) {
98
154
  }
99
155
  function PrimeStyleTryon({
100
156
  productImage,
157
+ productTitle = "Product",
101
158
  buttonText = "Virtual Try-On",
102
159
  apiUrl,
103
160
  showPoweredBy = true,
@@ -119,12 +176,31 @@ function PrimeStyleTryon({
119
176
  const [resultImageUrl, setResultImageUrl] = useState(null);
120
177
  const [errorMessage, setErrorMessage] = useState(null);
121
178
  const [dragOver, setDragOver] = useState(false);
122
- const [countdown, setCountdown] = useState(20);
179
+ const countdownRef = useRef(25);
180
+ const countdownElRef = useRef(null);
181
+ const countdownCircleRef = useRef(null);
182
+ const [sizingMethod, setSizingMethod] = useState(null);
183
+ const [sizingResult, setSizingResult] = useState(null);
184
+ const [sizeGuide, setSizeGuide] = useState(null);
185
+ const [sizingCountry, setSizingCountry] = useState(detectLocale);
186
+ const imperial = isImperial(sizingCountry);
187
+ const [sizingUnit, setSizingUnit] = useState(imperial ? "in" : "cm");
188
+ const [heightUnit, setHeightUnit] = useState(imperial ? "ft" : "cm");
189
+ const [weightUnit, setWeightUnit] = useState(imperial ? "lbs" : "kg");
190
+ const [formData, setFormData] = useState({});
191
+ const [profiles, setProfiles] = useState(() => lsGet("profiles", []));
192
+ const [history, setHistory] = useState(() => lsGet("history", []));
193
+ const [activeProfileId, setActiveProfileId] = useState(null);
194
+ const [profileSaved, setProfileSaved] = useState(false);
195
+ const [drawer, setDrawer] = useState(null);
196
+ const [profileDetail, setProfileDetail] = useState(null);
123
197
  const fileInputRef = useRef(null);
124
198
  const apiRef = useRef(null);
125
199
  const sseRef = useRef(null);
126
200
  const unsubRef = useRef(null);
127
201
  const pollingRef = useRef(null);
202
+ const completedRef = useRef(false);
203
+ const bodyRef = useRef(null);
128
204
  useEffect(() => {
129
205
  try {
130
206
  const key = getApiKey();
@@ -141,15 +217,12 @@ function PrimeStyleTryon({
141
217
  }, [apiUrl]);
142
218
  useEffect(() => {
143
219
  if (view === "processing") {
144
- setCountdown(25);
220
+ countdownRef.current = 25;
145
221
  const interval = setInterval(() => {
146
- setCountdown((prev) => {
147
- if (prev <= 1) {
148
- clearInterval(interval);
149
- return 0;
150
- }
151
- return prev - 1;
152
- });
222
+ countdownRef.current -= 1;
223
+ if (countdownElRef.current) countdownElRef.current.textContent = String(Math.max(countdownRef.current, 0));
224
+ if (countdownCircleRef.current) countdownCircleRef.current.style.strokeDashoffset = `${Math.max(countdownRef.current, 0) / 25 * 326.73}`;
225
+ if (countdownRef.current <= 0) clearInterval(interval);
153
226
  }, 1e3);
154
227
  return () => clearInterval(interval);
155
228
  }
@@ -177,17 +250,47 @@ function PrimeStyleTryon({
177
250
  };
178
251
  }
179
252
  }, [view]);
253
+ useEffect(() => {
254
+ lsSet("profiles", profiles);
255
+ }, [profiles]);
256
+ useEffect(() => {
257
+ lsSet("history", history);
258
+ }, [history]);
259
+ const stepIndex = useMemo(() => {
260
+ switch (view) {
261
+ case "welcome":
262
+ return 1;
263
+ case "upload":
264
+ return 2;
265
+ case "sizing-choice":
266
+ case "sizing-form":
267
+ return 3;
268
+ case "processing":
269
+ return 4;
270
+ case "result":
271
+ return 5;
272
+ default:
273
+ return 1;
274
+ }
275
+ }, [view]);
180
276
  const handleOpen = useCallback(() => {
181
- setView("upload");
277
+ setView("welcome");
182
278
  onOpen?.();
183
279
  }, [onOpen]);
184
280
  const handleClose = useCallback(() => {
185
281
  setView("idle");
186
282
  setSelectedFile(null);
283
+ setDrawer(null);
284
+ setProfileDetail(null);
187
285
  if (previewUrl) URL.revokeObjectURL(previewUrl);
188
286
  setPreviewUrl(null);
189
287
  setResultImageUrl(null);
190
288
  setErrorMessage(null);
289
+ setSizingMethod(null);
290
+ setSizingResult(null);
291
+ setSizeGuide(null);
292
+ setProfileSaved(false);
293
+ setFormData({});
191
294
  unsubRef.current?.();
192
295
  unsubRef.current = null;
193
296
  if (pollingRef.current) {
@@ -196,32 +299,28 @@ function PrimeStyleTryon({
196
299
  }
197
300
  onClose?.();
198
301
  }, [onClose, previewUrl]);
199
- const handleFileSelect = useCallback(
200
- (file) => {
201
- if (!isValidImageFile(file)) {
202
- setErrorMessage("Please upload a JPEG, PNG, or WebP image.");
203
- setView("error");
204
- onError?.({ message: "Invalid file type", code: "INVALID_FILE" });
205
- return;
206
- }
207
- if (file.size > 10 * 1024 * 1024) {
208
- setErrorMessage("Image must be under 10MB.");
209
- setView("error");
210
- onError?.({ message: "File too large", code: "FILE_TOO_LARGE" });
211
- return;
212
- }
213
- setSelectedFile(file);
214
- setPreviewUrl(URL.createObjectURL(file));
215
- onUpload?.(file);
216
- },
217
- [onUpload, onError]
218
- );
302
+ const handleFileSelect = useCallback((file) => {
303
+ if (!isValidImageFile(file)) {
304
+ setErrorMessage("Please upload a JPEG, PNG, or WebP image.");
305
+ setView("error");
306
+ onError?.({ message: "Invalid file type", code: "INVALID_FILE" });
307
+ return;
308
+ }
309
+ if (file.size > 10 * 1024 * 1024) {
310
+ setErrorMessage("Image must be under 10MB.");
311
+ setView("error");
312
+ onError?.({ message: "File too large", code: "FILE_TOO_LARGE" });
313
+ return;
314
+ }
315
+ setSelectedFile(file);
316
+ setPreviewUrl(URL.createObjectURL(file));
317
+ onUpload?.(file);
318
+ }, [onUpload, onError]);
219
319
  const handleRemovePreview = useCallback(() => {
220
320
  setSelectedFile(null);
221
321
  if (previewUrl) URL.revokeObjectURL(previewUrl);
222
322
  setPreviewUrl(null);
223
323
  }, [previewUrl]);
224
- const completedRef = useRef(false);
225
324
  const cleanupJob = useCallback(() => {
226
325
  if (pollingRef.current) {
227
326
  clearInterval(pollingRef.current);
@@ -230,36 +329,76 @@ function PrimeStyleTryon({
230
329
  unsubRef.current?.();
231
330
  unsubRef.current = null;
232
331
  }, []);
233
- const handleVtoUpdate = useCallback(
234
- (update) => {
235
- if (update.status === "completed" && update.imageUrl) {
236
- setResultImageUrl((prev) => {
237
- if (!prev || prev.startsWith("data:")) return update.imageUrl;
238
- if (!update.imageUrl.startsWith("data:")) return update.imageUrl;
239
- return prev;
240
- });
241
- if (!completedRef.current) {
242
- completedRef.current = true;
243
- cleanupJob();
244
- setView("result");
245
- onComplete?.({ jobId: update.galleryId, imageUrl: update.imageUrl });
246
- }
247
- } else if (update.status === "failed") {
248
- if (!completedRef.current) {
249
- completedRef.current = true;
250
- cleanupJob();
251
- const msg = update.error || "Try-on generation failed";
252
- setErrorMessage(msg);
253
- setView("error");
254
- onError?.({ message: msg });
255
- }
332
+ const handleVtoUpdate = useCallback((update) => {
333
+ if (update.status === "completed" && update.imageUrl) {
334
+ setResultImageUrl((prev) => {
335
+ if (!prev || prev.startsWith("data:")) return update.imageUrl;
336
+ if (!update.imageUrl.startsWith("data:")) return update.imageUrl;
337
+ return prev;
338
+ });
339
+ if (!completedRef.current) {
340
+ completedRef.current = true;
341
+ cleanupJob();
342
+ setView("result");
343
+ onComplete?.({ jobId: update.galleryId, imageUrl: update.imageUrl });
256
344
  }
257
- },
258
- [onComplete, onError, cleanupJob]
259
- );
345
+ } else if (update.status === "failed") {
346
+ if (!completedRef.current) {
347
+ completedRef.current = true;
348
+ cleanupJob();
349
+ const msg = update.error || "Try-on generation failed";
350
+ setErrorMessage(msg);
351
+ setView("error");
352
+ onError?.({ message: msg });
353
+ }
354
+ }
355
+ }, [onComplete, onError, cleanupJob]);
356
+ const submitSizing = useCallback(async () => {
357
+ if (!apiRef.current) return;
358
+ const baseUrl = getApiUrl(apiUrl);
359
+ const key = getApiKey();
360
+ const payload = {
361
+ method: sizingMethod,
362
+ locale: sizingCountry,
363
+ product: { title: productTitle, variants: [] }
364
+ };
365
+ if (sizeGuide?.found) payload.sizeGuide = sizeGuide;
366
+ if (sizingMethod === "exact") {
367
+ const m = { gender: formData.gender || "male" };
368
+ if (formData.height) m.heightCm = heightUnit === "ft" ? ftInToCm(parseFloat(formData.heightFeet || "0"), parseFloat(formData.heightInches || "0")) : parseFloat(formData.height);
369
+ if (formData.weight) m.weightKg = weightUnit === "lbs" ? lbsToKg(parseFloat(formData.weight)) : parseFloat(formData.weight);
370
+ const keys = ["chest", "bust", "waist", "hips", "shoulderWidth", "sleeveLength", "inseam", "neckCircumference", "footLengthCm"];
371
+ for (const k of keys) {
372
+ if (formData[k]) m[k] = sizingUnit === "in" ? inToCm(parseFloat(formData[k])) : parseFloat(formData[k]);
373
+ }
374
+ if (formData.shoeEU) m.shoeEU = formData.shoeEU;
375
+ if (formData.shoeUS) m.shoeUS = formData.shoeUS;
376
+ if (formData.shoeUK) m.shoeUK = formData.shoeUK;
377
+ if (formData.fitPreference) m.fitPreference = formData.fitPreference;
378
+ payload.measurements = m;
379
+ } else {
380
+ payload.quickEstimate = {
381
+ heightCm: heightUnit === "ft" ? ftInToCm(parseFloat(formData.heightFeet || "0"), parseFloat(formData.heightInches || "0")) : parseFloat(formData.height || "0"),
382
+ weightKg: weightUnit === "lbs" ? lbsToKg(parseFloat(formData.weight || "0")) : parseFloat(formData.weight || "0"),
383
+ gender: formData.gender || "male"
384
+ };
385
+ }
386
+ try {
387
+ const res = await fetch(`${baseUrl}/api/v1/sizing/recommend`, {
388
+ method: "POST",
389
+ headers: { "Content-Type": "application/json", Authorization: `Bearer ${key}` },
390
+ body: JSON.stringify(payload)
391
+ });
392
+ if (res.ok) {
393
+ const data = await res.json();
394
+ setSizingResult(data);
395
+ }
396
+ } catch {
397
+ }
398
+ }, [apiUrl, sizingMethod, sizingCountry, formData, heightUnit, weightUnit, sizingUnit, sizeGuide, productTitle]);
260
399
  const handleSubmit = useCallback(async () => {
261
400
  if (!selectedFile || !apiRef.current || !sseRef.current) {
262
- const msg = !apiRef.current ? "Missing NEXT_PUBLIC_PRIMESTYLE_API_KEY in environment variables" : "No file selected";
401
+ const msg = !apiRef.current ? "Missing NEXT_PUBLIC_PRIMESTYLE_API_KEY" : "No file selected";
263
402
  setErrorMessage(msg);
264
403
  setView("error");
265
404
  onError?.({ message: msg, code: "SDK_NOT_CONFIGURED" });
@@ -267,17 +406,12 @@ function PrimeStyleTryon({
267
406
  }
268
407
  completedRef.current = false;
269
408
  setView("processing");
409
+ if (sizingMethod) submitSizing();
270
410
  try {
271
411
  const modelImage = await compressImage(selectedFile);
272
- const response = await apiRef.current.submitTryOn(
273
- modelImage,
274
- productImage
275
- );
412
+ const response = await apiRef.current.submitTryOn(modelImage, productImage);
276
413
  onProcessing?.(response.jobId);
277
- unsubRef.current = sseRef.current.onJob(
278
- response.jobId,
279
- (update) => handleVtoUpdate(update)
280
- );
414
+ unsubRef.current = sseRef.current.onJob(response.jobId, handleVtoUpdate);
281
415
  let attempts = 0;
282
416
  pollingRef.current = setInterval(async () => {
283
417
  if (completedRef.current) {
@@ -294,13 +428,7 @@ function PrimeStyleTryon({
294
428
  try {
295
429
  const status = await apiRef.current.getStatus(response.jobId);
296
430
  if (status.status === "completed" || status.status === "failed") {
297
- handleVtoUpdate({
298
- galleryId: response.jobId,
299
- status: status.status,
300
- imageUrl: status.imageUrl,
301
- error: status.status === "failed" ? status.message : null,
302
- timestamp: Date.now()
303
- });
431
+ handleVtoUpdate({ galleryId: response.jobId, status: status.status, imageUrl: status.imageUrl, error: status.status === "failed" ? status.message : null, timestamp: Date.now() });
304
432
  }
305
433
  } catch {
306
434
  }
@@ -312,7 +440,7 @@ function PrimeStyleTryon({
312
440
  setView("error");
313
441
  onError?.({ message, code });
314
442
  }
315
- }, [selectedFile, productImage, onProcessing, onError, handleVtoUpdate]);
443
+ }, [selectedFile, productImage, onProcessing, onError, handleVtoUpdate, sizingMethod, submitSizing]);
316
444
  const handleDownload = useCallback(() => {
317
445
  if (!resultImageUrl) return;
318
446
  if (resultImageUrl.startsWith("data:")) {
@@ -339,8 +467,103 @@ function PrimeStyleTryon({
339
467
  setPreviewUrl(null);
340
468
  setResultImageUrl(null);
341
469
  setErrorMessage(null);
470
+ setSizingMethod(null);
471
+ setSizingResult(null);
472
+ setProfileSaved(false);
342
473
  setView("upload");
343
474
  }, [previewUrl, cleanupJob]);
475
+ const applyProfile = useCallback((id) => {
476
+ const p = profiles.find((pr) => pr.id === id);
477
+ if (!p) return;
478
+ setActiveProfileId(id);
479
+ const fd = { gender: p.gender || "male" };
480
+ if (p.heightCm) fd.height = String(p.heightCm);
481
+ if (p.weightKg) fd.weight = String(p.weightKg);
482
+ if (p.chest) fd.chest = String(p.chest);
483
+ if (p.bust) fd.bust = String(p.bust);
484
+ if (p.waist) fd.waist = String(p.waist);
485
+ if (p.hips) fd.hips = String(p.hips);
486
+ if (p.shoulderWidth) fd.shoulderWidth = String(p.shoulderWidth);
487
+ if (p.sleeveLength) fd.sleeveLength = String(p.sleeveLength);
488
+ if (p.inseam) fd.inseam = String(p.inseam);
489
+ if (p.neckCircumference) fd.neckCircumference = String(p.neckCircumference);
490
+ if (p.footLengthCm) fd.footLengthCm = String(p.footLengthCm);
491
+ if (p.shoeEU) fd.shoeEU = p.shoeEU;
492
+ if (p.shoeUS) fd.shoeUS = p.shoeUS;
493
+ if (p.shoeUK) fd.shoeUK = p.shoeUK;
494
+ if (p.fitPreference) fd.fitPreference = p.fitPreference;
495
+ setFormData(fd);
496
+ }, [profiles]);
497
+ const saveProfile = useCallback((name) => {
498
+ const id = activeProfileId || `p_${Date.now()}`;
499
+ const p = {
500
+ id,
501
+ name,
502
+ gender: formData.gender || "male",
503
+ heightCm: formData.height ? parseFloat(formData.height) : void 0,
504
+ weightKg: formData.weight ? parseFloat(formData.weight) : void 0,
505
+ chest: formData.chest ? parseFloat(formData.chest) : void 0,
506
+ bust: formData.bust ? parseFloat(formData.bust) : void 0,
507
+ waist: formData.waist ? parseFloat(formData.waist) : void 0,
508
+ hips: formData.hips ? parseFloat(formData.hips) : void 0,
509
+ shoulderWidth: formData.shoulderWidth ? parseFloat(formData.shoulderWidth) : void 0,
510
+ sleeveLength: formData.sleeveLength ? parseFloat(formData.sleeveLength) : void 0,
511
+ inseam: formData.inseam ? parseFloat(formData.inseam) : void 0,
512
+ neckCircumference: formData.neckCircumference ? parseFloat(formData.neckCircumference) : void 0,
513
+ footLengthCm: formData.footLengthCm ? parseFloat(formData.footLengthCm) : void 0,
514
+ shoeEU: formData.shoeEU,
515
+ shoeUS: formData.shoeUS,
516
+ shoeUK: formData.shoeUK,
517
+ fitPreference: formData.fitPreference,
518
+ createdAt: Date.now()
519
+ };
520
+ setProfiles((prev) => {
521
+ const idx = prev.findIndex((x) => x.id === id);
522
+ if (idx >= 0) {
523
+ const next = [...prev];
524
+ next[idx] = p;
525
+ return next;
526
+ }
527
+ return [...prev, p].slice(-50);
528
+ });
529
+ setActiveProfileId(id);
530
+ setProfileSaved(true);
531
+ }, [activeProfileId, formData]);
532
+ const saveHistoryEntry = useCallback(() => {
533
+ const entry = {
534
+ id: `h_${Date.now()}`,
535
+ productTitle,
536
+ productImage,
537
+ resultImageUrl: resultImageUrl || void 0,
538
+ recommendedSize: sizingResult?.recommendedSize,
539
+ confidence: sizingResult?.confidence,
540
+ reasoning: sizingResult?.reasoning,
541
+ internationalSizes: sizingResult?.internationalSizes,
542
+ matchDetails: sizingResult?.matchDetails,
543
+ date: Date.now()
544
+ };
545
+ if (activeProfileId) {
546
+ const p = profiles.find((x) => x.id === activeProfileId);
547
+ if (p) entry.profileName = p.name;
548
+ }
549
+ setHistory((prev) => [entry, ...prev].slice(0, 50));
550
+ }, [productTitle, productImage, resultImageUrl, sizingResult, activeProfileId, profiles]);
551
+ useEffect(() => {
552
+ if (view === "result" && (resultImageUrl || sizingResult)) {
553
+ saveHistoryEntry();
554
+ }
555
+ }, [view]);
556
+ const updateField = useCallback((key, val) => {
557
+ setFormData((prev) => ({ ...prev, [key]: val }));
558
+ }, []);
559
+ const shoeField = useMemo(() => {
560
+ const map = {
561
+ US: { key: "shoeUS", label: "Shoe size (US)", ph: "e.g. 10" },
562
+ UK: { key: "shoeUK", label: "Shoe size (UK)", ph: "e.g. 9" },
563
+ AU: { key: "shoeUK", label: "Shoe size (UK)", ph: "e.g. 9" }
564
+ };
565
+ return map[sizingCountry] || { key: "shoeEU", label: "Shoe size (EU)", ph: "e.g. 43" };
566
+ }, [sizingCountry]);
344
567
  const rootVars = {
345
568
  "--ps-btn-bg": btnS.backgroundColor,
346
569
  "--ps-btn-color": btnS.textColor,
@@ -377,520 +600,864 @@ function PrimeStyleTryon({
377
600
  "--ps-loader": mdlS.loaderColor,
378
601
  "--ps-result-radius": mdlS.resultBorderRadius
379
602
  };
380
- const cssVars = Object.fromEntries(
381
- Object.entries(rootVars).filter(([, v]) => v !== void 0)
382
- );
383
- return /* @__PURE__ */ jsxs(
384
- "div",
385
- {
386
- className: cx("ps-tryon-root", cn.root || className),
387
- style: { ...cssVars, ...style },
388
- "data-ps-tryon": true,
389
- children: [
390
- /* @__PURE__ */ jsxs("button", { onClick: handleOpen, className: cx("ps-tryon-btn", cn.button), children: [
391
- /* @__PURE__ */ jsx(CameraIcon, { size: parseInt(btnS.iconSize || "18") }),
392
- /* @__PURE__ */ jsx("span", { children: buttonText })
603
+ const cssVars = Object.fromEntries(Object.entries(rootVars).filter(([, v]) => v !== void 0));
604
+ function Stepper() {
605
+ if (view === "error" || view === "idle") return null;
606
+ return /* @__PURE__ */ jsx("div", { className: "ps-tryon-stepper", children: /* @__PURE__ */ jsx("div", { className: "ps-tryon-stepper-track", children: Array.from({ length: TOTAL_STEPS }, (_, i) => i + 1).map((i) => /* @__PURE__ */ jsxs("div", { className: "ps-tryon-stepper-fragment", children: [
607
+ i > 1 && /* @__PURE__ */ jsx("div", { className: `ps-tryon-stepper-line${i <= stepIndex ? " ps-done" : ""}` }),
608
+ /* @__PURE__ */ jsxs("div", { className: `ps-tryon-stepper-step${i < stepIndex ? " ps-done" : i === stepIndex ? " ps-active" : ""}`, children: [
609
+ /* @__PURE__ */ jsx("div", { className: "ps-tryon-stepper-circle", children: i < stepIndex ? /* @__PURE__ */ jsx(CheckIcon, {}) : i }),
610
+ /* @__PURE__ */ jsx("div", { className: "ps-tryon-stepper-label", children: STEP_LABELS[i] })
611
+ ] })
612
+ ] }, i)) }) });
613
+ }
614
+ function InputRow({ label, fieldKey, placeholder, type = "text", unit }) {
615
+ return /* @__PURE__ */ jsxs("div", { className: "ps-tryon-input-row", children: [
616
+ /* @__PURE__ */ jsx("label", { children: label }),
617
+ /* @__PURE__ */ jsx(
618
+ "input",
619
+ {
620
+ type,
621
+ placeholder,
622
+ value: formData[fieldKey] || "",
623
+ onChange: (e) => updateField(fieldKey, e.target.value)
624
+ }
625
+ ),
626
+ unit && /* @__PURE__ */ jsx("span", { className: "ps-tryon-input-unit", children: unit })
627
+ ] });
628
+ }
629
+ function UnitToggle({ options, value, onChange }) {
630
+ return /* @__PURE__ */ jsx("div", { className: "ps-tryon-unit-toggle", children: options.map((o) => /* @__PURE__ */ jsx("button", { className: `ps-tryon-unit-btn${value === o.value ? " ps-active" : ""}`, onClick: () => onChange(o.value), children: o.label }, o.value)) });
631
+ }
632
+ function WelcomeView() {
633
+ return /* @__PURE__ */ jsxs("div", { className: "ps-tryon-welcome", children: [
634
+ /* @__PURE__ */ jsxs("div", { className: "ps-tryon-welcome-hero", children: [
635
+ productImage && /* @__PURE__ */ jsxs("div", { className: "ps-tryon-welcome-img-wrap", children: [
636
+ /* @__PURE__ */ jsx("img", { src: productImage, alt: "Product", className: "ps-tryon-welcome-product" }),
637
+ /* @__PURE__ */ jsx("div", { className: "ps-tryon-welcome-sparkle", children: /* @__PURE__ */ jsx(SparkleIcon, { size: 20 }) })
393
638
  ] }),
394
- view !== "idle" && /* @__PURE__ */ jsx(
395
- "div",
396
- {
397
- className: cx("ps-tryon-overlay", cn.overlay),
398
- onClick: (e) => {
399
- if (e.target === e.currentTarget) handleClose();
400
- },
401
- children: /* @__PURE__ */ jsxs(
402
- "div",
639
+ /* @__PURE__ */ jsx("h2", { className: "ps-tryon-welcome-title", children: "See How It Looks On You" }),
640
+ /* @__PURE__ */ jsx("p", { className: "ps-tryon-welcome-sub", children: "Virtual try-on + AI size recommendation" })
641
+ ] }),
642
+ /* @__PURE__ */ jsx("div", { className: "ps-tryon-features", children: [
643
+ { icon: /* @__PURE__ */ jsx(CameraIcon, {}), title: "Upload Photo", desc: "Share a photo of yourself" },
644
+ { icon: /* @__PURE__ */ jsx(RulerIcon, {}), title: "Find Your Size", desc: "AI-powered fit analysis" },
645
+ { icon: /* @__PURE__ */ jsx(SparkleIcon, {}), title: "See Results", desc: "Try-on in seconds" }
646
+ ].map((f, i) => /* @__PURE__ */ jsxs("div", { className: "ps-tryon-feature", children: [
647
+ /* @__PURE__ */ jsx("div", { className: "ps-tryon-feature-icon", children: f.icon }),
648
+ /* @__PURE__ */ jsx("div", { className: "ps-tryon-feature-title", children: f.title }),
649
+ /* @__PURE__ */ jsx("div", { className: "ps-tryon-feature-desc", children: f.desc })
650
+ ] }, i)) }),
651
+ /* @__PURE__ */ jsxs("button", { className: "ps-tryon-cta", onClick: () => setView("upload"), children: [
652
+ "Let’s Get Started ",
653
+ /* @__PURE__ */ jsx(ArrowRightIcon, {})
654
+ ] }),
655
+ /* @__PURE__ */ jsx("div", { className: "ps-tryon-welcome-note", children: "Takes less than a minute" })
656
+ ] });
657
+ }
658
+ function UploadView() {
659
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
660
+ profiles.length > 0 && /* @__PURE__ */ jsx("div", { className: "ps-tryon-profile-bar", children: /* @__PURE__ */ jsxs("select", { className: "ps-tryon-profile-select", value: activeProfileId || "", onChange: (e) => {
661
+ if (e.target.value) applyProfile(e.target.value);
662
+ }, children: [
663
+ /* @__PURE__ */ jsx("option", { value: "", children: "Auto-fill from saved profile..." }),
664
+ profiles.map((p) => /* @__PURE__ */ jsxs("option", { value: p.id, children: [
665
+ p.name,
666
+ " (",
667
+ p.gender === "female" ? "Women's" : "Men's",
668
+ ")"
669
+ ] }, p.id))
670
+ ] }) }),
671
+ selectedFile && previewUrl ? /* @__PURE__ */ jsxs(Fragment, { children: [
672
+ /* @__PURE__ */ jsxs("div", { className: cx("ps-tryon-preview", cn.preview), children: [
673
+ /* @__PURE__ */ jsx("img", { src: previewUrl, alt: "Your photo", className: cn.previewImage }),
674
+ /* @__PURE__ */ jsx("button", { onClick: handleRemovePreview, className: cx("ps-tryon-preview-remove", cn.removeButton), children: "×" })
675
+ ] }),
676
+ /* @__PURE__ */ jsxs("button", { onClick: () => setView("sizing-choice"), className: cx("ps-tryon-submit", cn.submitButton), children: [
677
+ "Continue to Sizing ",
678
+ /* @__PURE__ */ jsx(ArrowRightIcon, {})
679
+ ] })
680
+ ] }) : /* @__PURE__ */ jsxs(
681
+ "div",
682
+ {
683
+ className: cx(`ps-tryon-upload${dragOver ? " ps-tryon-drag-over" : ""}`, cn.uploadZone),
684
+ onClick: () => fileInputRef.current?.click(),
685
+ onDragOver: (e) => {
686
+ e.preventDefault();
687
+ setDragOver(true);
688
+ },
689
+ onDragLeave: () => setDragOver(false),
690
+ onDrop: (e) => {
691
+ e.preventDefault();
692
+ setDragOver(false);
693
+ const f = e.dataTransfer?.files?.[0];
694
+ if (f) handleFileSelect(f);
695
+ },
696
+ children: [
697
+ /* @__PURE__ */ jsx(
698
+ "input",
403
699
  {
404
- className: cx("ps-tryon-modal", cn.modal),
405
- onClick: (e) => e.stopPropagation(),
406
- children: [
407
- /* @__PURE__ */ jsxs("div", { className: cx("ps-tryon-header", cn.header), children: [
408
- /* @__PURE__ */ jsx("span", { className: cx("ps-tryon-title", cn.title), children: "Virtual Try-On" }),
409
- /* @__PURE__ */ jsx(
410
- "button",
411
- {
412
- onClick: handleClose,
413
- className: cx("ps-tryon-close", cn.closeButton),
414
- children: /* @__PURE__ */ jsx(XIcon, {})
415
- }
416
- )
417
- ] }),
418
- /* @__PURE__ */ jsxs("div", { className: cx("ps-tryon-body", cn.body), children: [
419
- view === "upload" && /* @__PURE__ */ jsx(Fragment, { children: selectedFile && previewUrl ? /* @__PURE__ */ jsxs(Fragment, { children: [
420
- /* @__PURE__ */ jsxs("div", { className: cx("ps-tryon-preview", cn.preview), children: [
421
- /* @__PURE__ */ jsx(
422
- "img",
423
- {
424
- src: previewUrl,
425
- alt: "Your photo",
426
- className: cn.previewImage
427
- }
428
- ),
429
- /* @__PURE__ */ jsx(
430
- "button",
431
- {
432
- onClick: handleRemovePreview,
433
- className: cx(
434
- "ps-tryon-preview-remove",
435
- cn.removeButton
436
- ),
437
- children: "×"
438
- }
439
- )
440
- ] }),
441
- /* @__PURE__ */ jsx(
442
- "button",
443
- {
444
- onClick: handleSubmit,
445
- className: cx("ps-tryon-submit", cn.submitButton),
446
- children: "Try It On"
447
- }
448
- )
449
- ] }) : /* @__PURE__ */ jsxs(
450
- "div",
451
- {
452
- className: cx(
453
- `ps-tryon-upload${dragOver ? " ps-tryon-drag-over" : ""}`,
454
- cn.uploadZone
455
- ),
456
- onClick: () => fileInputRef.current?.click(),
457
- onDragOver: (e) => {
458
- e.preventDefault();
459
- setDragOver(true);
460
- },
461
- onDragLeave: () => setDragOver(false),
462
- onDrop: (e) => {
463
- e.preventDefault();
464
- setDragOver(false);
465
- const file = e.dataTransfer?.files?.[0];
466
- if (file) handleFileSelect(file);
467
- },
468
- children: [
469
- /* @__PURE__ */ jsx(
470
- "input",
471
- {
472
- ref: fileInputRef,
473
- type: "file",
474
- accept: "image/jpeg,image/png,image/webp",
475
- style: { display: "none" },
476
- onChange: (e) => {
477
- const file = e.target.files?.[0];
478
- if (file) handleFileSelect(file);
479
- }
480
- }
481
- ),
482
- /* @__PURE__ */ jsx(UploadIcon, {}),
483
- /* @__PURE__ */ jsx("p", { className: cx("ps-tryon-upload-text", cn.uploadText), children: "Drop or upload your full body photo!" }),
484
- /* @__PURE__ */ jsx("p", { className: cx("ps-tryon-upload-hint", cn.uploadHint), children: "JPEG, PNG or WebP (max 10MB)" })
485
- ]
486
- }
487
- ) }),
488
- view === "processing" && /* @__PURE__ */ jsxs("div", { className: "ps-tryon-processing", children: [
489
- countdown > 0 ? /* @__PURE__ */ jsxs("div", { className: "ps-tryon-countdown-ring", children: [
490
- /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 120 120", children: [
491
- /* @__PURE__ */ jsx(
492
- "circle",
493
- {
494
- className: "ps-tryon-countdown-track",
495
- cx: "60",
496
- cy: "60",
497
- r: "52"
498
- }
499
- ),
500
- /* @__PURE__ */ jsx(
501
- "circle",
502
- {
503
- className: "ps-tryon-countdown-progress",
504
- cx: "60",
505
- cy: "60",
506
- r: "52",
507
- style: {
508
- strokeDashoffset: `${countdown / 25 * 326.73}`
509
- }
510
- }
511
- )
512
- ] }),
513
- /* @__PURE__ */ jsx("span", { className: "ps-tryon-countdown-number", children: countdown })
514
- ] }) : /* @__PURE__ */ jsx("div", { className: "ps-tryon-done-pulse", children: /* @__PURE__ */ jsx("div", { className: cx("ps-tryon-spinner", cn.spinner) }) }),
515
- /* @__PURE__ */ jsx(
516
- "p",
517
- {
518
- className: cx(
519
- "ps-tryon-processing-text",
520
- cn.processingText
521
- ),
522
- children: countdown > 0 ? "Generating your try-on..." : "Almost there..."
523
- }
524
- ),
525
- /* @__PURE__ */ jsx(
526
- "p",
527
- {
528
- className: cx(
529
- "ps-tryon-processing-sub",
530
- cn.processingSubText
531
- ),
532
- children: countdown > 0 ? "This usually takes 15-25 seconds" : "Finishing up your look"
533
- }
534
- )
535
- ] }),
536
- view === "result" && resultImageUrl && /* @__PURE__ */ jsxs("div", { className: cx("ps-tryon-result", cn.result), children: [
537
- /* @__PURE__ */ jsx(
538
- "img",
539
- {
540
- src: resultImageUrl,
541
- alt: "Try-on result",
542
- className: cn.resultImage
543
- }
544
- ),
545
- /* @__PURE__ */ jsxs(
546
- "div",
547
- {
548
- className: cx(
549
- "ps-tryon-result-actions",
550
- cn.resultActions
551
- ),
552
- children: [
553
- /* @__PURE__ */ jsx(
554
- "button",
555
- {
556
- onClick: handleDownload,
557
- className: cx("ps-tryon-btn-download", cn.downloadButton),
558
- children: "Download"
559
- }
560
- ),
561
- /* @__PURE__ */ jsx(
562
- "button",
563
- {
564
- onClick: handleRetry,
565
- className: cx("ps-tryon-btn-retry", cn.retryButton),
566
- children: "Try Another"
567
- }
568
- )
569
- ]
570
- }
571
- )
572
- ] }),
573
- view === "error" && /* @__PURE__ */ jsxs("div", { className: cx("ps-tryon-error", cn.error), children: [
574
- /* @__PURE__ */ jsx(AlertIcon, {}),
575
- /* @__PURE__ */ jsx("p", { className: cx("ps-tryon-error-text", cn.errorText), children: errorMessage || "Something went wrong" }),
576
- /* @__PURE__ */ jsx(
577
- "button",
578
- {
579
- onClick: handleRetry,
580
- className: cx("ps-tryon-submit", cn.submitButton),
581
- children: "Try Again"
582
- }
583
- )
584
- ] })
585
- ] }),
586
- showPoweredBy && /* @__PURE__ */ jsxs("div", { className: cx("ps-tryon-powered", cn.poweredBy), children: [
587
- "Powered by",
588
- " ",
589
- /* @__PURE__ */ jsx(
590
- "a",
591
- {
592
- href: "https://myaifitting.com",
593
- target: "_blank",
594
- rel: "noopener noreferrer",
595
- children: "PrimeStyle AI"
596
- }
597
- )
598
- ] })
599
- ]
700
+ ref: fileInputRef,
701
+ type: "file",
702
+ accept: "image/jpeg,image/png,image/webp",
703
+ style: { display: "none" },
704
+ onChange: (e) => {
705
+ const f = e.target.files?.[0];
706
+ if (f) handleFileSelect(f);
707
+ }
600
708
  }
601
- )
602
- }
603
- ),
604
- /* @__PURE__ */ jsx("style", { children: `
605
- .ps-tryon-root {
606
- display: inline-block;
709
+ ),
710
+ /* @__PURE__ */ jsx(UploadIcon, {}),
711
+ /* @__PURE__ */ jsx("p", { className: cx("ps-tryon-upload-text", cn.uploadText), children: "Drop or upload your full body photo!" }),
712
+ /* @__PURE__ */ jsx("p", { className: cx("ps-tryon-upload-hint", cn.uploadHint), children: "JPEG, PNG or WebP (max 10MB)" })
713
+ ]
607
714
  }
715
+ )
716
+ ] });
717
+ }
718
+ function SizingChoiceView() {
719
+ return /* @__PURE__ */ jsxs("div", { className: "ps-tryon-sizing-choice", children: [
720
+ /* @__PURE__ */ jsx("h3", { className: "ps-tryon-section-title", children: "How would you like to find your size?" }),
721
+ /* @__PURE__ */ jsxs("div", { className: "ps-tryon-choice-cards", children: [
722
+ /* @__PURE__ */ jsxs("button", { className: "ps-tryon-choice-card", onClick: () => {
723
+ setSizingMethod("exact");
724
+ setView("sizing-form");
725
+ }, children: [
726
+ /* @__PURE__ */ jsx("div", { className: "ps-tryon-choice-icon", children: /* @__PURE__ */ jsx(RulerIcon, { size: 24 }) }),
727
+ /* @__PURE__ */ jsxs("div", { className: "ps-tryon-choice-info", children: [
728
+ /* @__PURE__ */ jsx("div", { className: "ps-tryon-choice-title", children: "Enter my measurements" }),
729
+ /* @__PURE__ */ jsx("div", { className: "ps-tryon-choice-desc", children: "Chest, waist, hips, shoes & more" })
730
+ ] }),
731
+ /* @__PURE__ */ jsx("span", { className: "ps-tryon-choice-badge", children: "Best accuracy" })
732
+ ] }),
733
+ /* @__PURE__ */ jsxs("button", { className: "ps-tryon-choice-card", onClick: () => {
734
+ setSizingMethod("quick");
735
+ setView("sizing-form");
736
+ }, children: [
737
+ /* @__PURE__ */ jsx("div", { className: "ps-tryon-choice-icon", children: /* @__PURE__ */ jsx(SparkleIcon, { size: 24 }) }),
738
+ /* @__PURE__ */ jsxs("div", { className: "ps-tryon-choice-info", children: [
739
+ /* @__PURE__ */ jsx("div", { className: "ps-tryon-choice-title", children: "Just height & weight" }),
740
+ /* @__PURE__ */ jsx("div", { className: "ps-tryon-choice-desc", children: "Quick estimate in seconds" })
741
+ ] })
742
+ ] }),
743
+ /* @__PURE__ */ jsxs("button", { className: "ps-tryon-choice-card", onClick: () => {
744
+ setSizingMethod(null);
745
+ handleSubmit();
746
+ }, children: [
747
+ /* @__PURE__ */ jsx("div", { className: "ps-tryon-choice-icon", children: /* @__PURE__ */ jsx(SvgIcon, { d: "M13 5H1M13 9H1M13 13H1M5 17l4 4 8-8", size: 24, strokeWidth: 1.5 }) }),
748
+ /* @__PURE__ */ jsxs("div", { className: "ps-tryon-choice-info", children: [
749
+ /* @__PURE__ */ jsx("div", { className: "ps-tryon-choice-title", children: "Skip sizing" }),
750
+ /* @__PURE__ */ jsx("div", { className: "ps-tryon-choice-desc", children: "Just show me the try-on" })
751
+ ] })
752
+ ] })
753
+ ] })
754
+ ] });
755
+ }
756
+ function SizingFormView() {
757
+ const isFemale = formData.gender === "female";
758
+ return /* @__PURE__ */ jsxs("div", { className: "ps-tryon-sizing-form", children: [
759
+ /* @__PURE__ */ jsxs("div", { className: "ps-tryon-input-row", children: [
760
+ /* @__PURE__ */ jsx("label", { children: "Sizing region" }),
761
+ /* @__PURE__ */ jsx("select", { className: "ps-tryon-country-select", value: sizingCountry, onChange: (e) => setSizingCountry(e.target.value), children: SIZING_COUNTRIES.map((c) => /* @__PURE__ */ jsx("option", { value: c.code, children: c.label }, c.code)) })
762
+ ] }),
763
+ /* @__PURE__ */ jsxs("div", { className: "ps-tryon-input-row", children: [
764
+ /* @__PURE__ */ jsx("label", { children: "Gender" }),
765
+ /* @__PURE__ */ jsxs("div", { className: "ps-tryon-unit-toggle", children: [
766
+ /* @__PURE__ */ jsx("button", { className: `ps-tryon-unit-btn${formData.gender !== "female" ? " ps-active" : ""}`, onClick: () => updateField("gender", "male"), children: "Men's" }),
767
+ /* @__PURE__ */ jsx("button", { className: `ps-tryon-unit-btn${formData.gender === "female" ? " ps-active" : ""}`, onClick: () => updateField("gender", "female"), children: "Women's" })
768
+ ] })
769
+ ] }),
770
+ /* @__PURE__ */ jsxs("div", { className: "ps-tryon-input-row", children: [
771
+ /* @__PURE__ */ jsx("label", { children: "Height" }),
772
+ heightUnit === "ft" ? /* @__PURE__ */ jsxs("div", { className: "ps-tryon-height-ft", children: [
773
+ /* @__PURE__ */ jsx("input", { type: "number", placeholder: "5", value: formData.heightFeet || "", onChange: (e) => updateField("heightFeet", e.target.value) }),
774
+ /* @__PURE__ */ jsx("span", { children: "ft" }),
775
+ /* @__PURE__ */ jsx("input", { type: "number", placeholder: "4", value: formData.heightInches || "", onChange: (e) => updateField("heightInches", e.target.value) }),
776
+ /* @__PURE__ */ jsx("span", { children: "in" })
777
+ ] }) : /* @__PURE__ */ jsx("input", { type: "number", placeholder: "e.g. 175", value: formData.height || "", onChange: (e) => updateField("height", e.target.value) }),
778
+ /* @__PURE__ */ jsx(UnitToggle, { options: [{ label: "cm", value: "cm" }, { label: "ft", value: "ft" }], value: heightUnit, onChange: setHeightUnit })
779
+ ] }),
780
+ /* @__PURE__ */ jsxs("div", { className: "ps-tryon-input-row", children: [
781
+ /* @__PURE__ */ jsx("label", { children: "Weight" }),
782
+ /* @__PURE__ */ jsx("input", { type: "number", placeholder: weightUnit === "lbs" ? "e.g. 170" : "e.g. 75", value: formData.weight || "", onChange: (e) => updateField("weight", e.target.value) }),
783
+ /* @__PURE__ */ jsx(UnitToggle, { options: [{ label: "kg", value: "kg" }, { label: "lbs", value: "lbs" }], value: weightUnit, onChange: setWeightUnit })
784
+ ] }),
785
+ sizingMethod === "exact" && /* @__PURE__ */ jsxs(Fragment, { children: [
786
+ /* @__PURE__ */ jsxs("div", { className: "ps-tryon-input-row", children: [
787
+ /* @__PURE__ */ jsx("label", { children: "Measurements" }),
788
+ /* @__PURE__ */ jsx(UnitToggle, { options: [{ label: "cm", value: "cm" }, { label: "in", value: "in" }], value: sizingUnit, onChange: setSizingUnit })
789
+ ] }),
790
+ isFemale ? /* @__PURE__ */ jsxs(Fragment, { children: [
791
+ /* @__PURE__ */ jsx(InputRow, { label: "Bust", fieldKey: "bust", placeholder: "e.g. 90", type: "number", unit: sizingUnit }),
792
+ /* @__PURE__ */ jsx(InputRow, { label: "Waist", fieldKey: "waist", placeholder: "e.g. 70", type: "number", unit: sizingUnit }),
793
+ /* @__PURE__ */ jsx(InputRow, { label: "Hips", fieldKey: "hips", placeholder: "e.g. 95", type: "number", unit: sizingUnit })
794
+ ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
795
+ /* @__PURE__ */ jsx(InputRow, { label: "Chest", fieldKey: "chest", placeholder: "e.g. 100", type: "number", unit: sizingUnit }),
796
+ /* @__PURE__ */ jsx(InputRow, { label: "Waist", fieldKey: "waist", placeholder: "e.g. 82", type: "number", unit: sizingUnit }),
797
+ /* @__PURE__ */ jsx(InputRow, { label: "Hips", fieldKey: "hips", placeholder: "e.g. 98", type: "number", unit: sizingUnit })
798
+ ] }),
799
+ /* @__PURE__ */ jsx(InputRow, { label: "Shoulder Width", fieldKey: "shoulderWidth", placeholder: "e.g. 45", type: "number", unit: sizingUnit }),
800
+ /* @__PURE__ */ jsx(InputRow, { label: "Sleeve Length", fieldKey: "sleeveLength", placeholder: "e.g. 65", type: "number", unit: sizingUnit }),
801
+ /* @__PURE__ */ jsx(InputRow, { label: "Inseam", fieldKey: "inseam", placeholder: "e.g. 80", type: "number", unit: sizingUnit }),
802
+ isFemale && /* @__PURE__ */ jsxs("div", { className: "ps-tryon-input-row", children: [
803
+ /* @__PURE__ */ jsx("label", { children: "Fit preference" }),
804
+ /* @__PURE__ */ jsx("div", { className: "ps-tryon-unit-toggle", children: ["petite", "standard", "tall", "plus"].map((fp) => /* @__PURE__ */ jsx(
805
+ "button",
806
+ {
807
+ className: `ps-tryon-unit-btn${(formData.fitPreference || "standard") === fp ? " ps-active" : ""}`,
808
+ onClick: () => updateField("fitPreference", fp),
809
+ children: fp.charAt(0).toUpperCase() + fp.slice(1)
810
+ },
811
+ fp
812
+ )) })
813
+ ] }),
814
+ /* @__PURE__ */ jsxs("div", { className: "ps-tryon-shoe-section", children: [
815
+ /* @__PURE__ */ jsx("div", { className: "ps-tryon-shoe-title", children: "Shoe sizing (optional)" }),
816
+ /* @__PURE__ */ jsx(InputRow, { label: "Foot length", fieldKey: "footLengthCm", placeholder: sizingUnit === "in" ? "e.g. 10.5" : "e.g. 27", type: "number", unit: sizingUnit }),
817
+ /* @__PURE__ */ jsx(InputRow, { label: shoeField.label, fieldKey: shoeField.key, placeholder: shoeField.ph })
818
+ ] })
819
+ ] }),
820
+ /* @__PURE__ */ jsx("p", { className: "ps-tryon-disclaimer", children: "Fill in what you know — more measurements = better accuracy." }),
821
+ /* @__PURE__ */ jsxs("button", { className: "ps-tryon-submit", onClick: handleSubmit, children: [
822
+ "Get My Size & Try On ",
823
+ /* @__PURE__ */ jsx(ArrowRightIcon, {})
824
+ ] })
825
+ ] });
826
+ }
827
+ function ProcessingView() {
828
+ return /* @__PURE__ */ jsxs("div", { className: "ps-tryon-processing", children: [
829
+ /* @__PURE__ */ jsxs("div", { className: "ps-tryon-countdown-ring", children: [
830
+ /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 120 120", children: [
831
+ /* @__PURE__ */ jsx("circle", { className: "ps-tryon-countdown-track", cx: "60", cy: "60", r: "52" }),
832
+ /* @__PURE__ */ jsx("circle", { ref: countdownCircleRef, className: "ps-tryon-countdown-progress", cx: "60", cy: "60", r: "52", style: { strokeDashoffset: `${25 / 25 * 326.73}` } })
833
+ ] }),
834
+ /* @__PURE__ */ jsx("span", { ref: countdownElRef, className: "ps-tryon-countdown-number", children: "25" })
835
+ ] }),
836
+ /* @__PURE__ */ jsx("p", { className: cx("ps-tryon-processing-text", cn.processingText), children: "Generating your try-on..." }),
837
+ /* @__PURE__ */ jsx("p", { className: cx("ps-tryon-processing-sub", cn.processingSubText), children: "This usually takes 15-25 seconds" })
838
+ ] });
839
+ }
840
+ function ResultView() {
841
+ const hasBoth = !!resultImageUrl && !!sizingResult;
842
+ const [profileName, setProfileName] = useState("");
843
+ return /* @__PURE__ */ jsxs("div", { className: `ps-tryon-result-layout${hasBoth ? " ps-tryon-result-split" : ""}`, children: [
844
+ resultImageUrl && /* @__PURE__ */ jsx("div", { className: "ps-tryon-result-image-col", children: /* @__PURE__ */ jsx("img", { src: resultImageUrl, alt: "Try-on result", className: cn.resultImage }) }),
845
+ /* @__PURE__ */ jsxs("div", { className: "ps-tryon-result-info-col", children: [
846
+ sizingResult && /* @__PURE__ */ jsxs("div", { className: "ps-tryon-size-recommend", children: [
847
+ /* @__PURE__ */ jsx("div", { className: "ps-tryon-size-badge", children: sizingResult.recommendedSize }),
848
+ /* @__PURE__ */ jsxs("div", { className: "ps-tryon-size-confidence", children: [
849
+ "Confidence: ",
850
+ /* @__PURE__ */ jsx("span", { className: `ps-conf-${sizingResult.confidence}`, children: sizingResult.confidence })
851
+ ] }),
852
+ /* @__PURE__ */ jsx("p", { className: "ps-tryon-size-reasoning", children: sizingResult.reasoning }),
853
+ sizingResult.internationalSizes && /* @__PURE__ */ jsx("div", { className: "ps-tryon-intl-sizes", children: Object.entries(sizingResult.internationalSizes).map(([k, v]) => /* @__PURE__ */ jsxs("span", { className: "ps-tryon-intl-chip", children: [
854
+ k,
855
+ ": ",
856
+ v
857
+ ] }, k)) }),
858
+ sizingResult.matchDetails && sizingResult.matchDetails.length > 0 && /* @__PURE__ */ jsxs("details", { className: "ps-tryon-match-details", children: [
859
+ /* @__PURE__ */ jsx("summary", { children: "Measurement breakdown" }),
860
+ /* @__PURE__ */ jsxs("table", { children: [
861
+ /* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsxs("tr", { children: [
862
+ /* @__PURE__ */ jsx("th", { children: "Area" }),
863
+ /* @__PURE__ */ jsx("th", { children: "You" }),
864
+ /* @__PURE__ */ jsx("th", { children: "Chart" }),
865
+ /* @__PURE__ */ jsx("th", { children: "Fit" })
866
+ ] }) }),
867
+ /* @__PURE__ */ jsx("tbody", { children: sizingResult.matchDetails.map((m, i) => /* @__PURE__ */ jsxs("tr", { children: [
868
+ /* @__PURE__ */ jsx("td", { children: m.measurement }),
869
+ /* @__PURE__ */ jsx("td", { children: m.userValue }),
870
+ /* @__PURE__ */ jsx("td", { children: m.chartRange }),
871
+ /* @__PURE__ */ jsx("td", { className: `ps-fit-${m.fit}`, children: m.fit })
872
+ ] }, i)) })
873
+ ] })
874
+ ] })
875
+ ] }),
876
+ /* @__PURE__ */ jsxs("div", { className: cx("ps-tryon-result-actions", cn.resultActions), children: [
877
+ /* @__PURE__ */ jsx("button", { onClick: handleDownload, className: cx("ps-tryon-btn-download", cn.downloadButton), children: "Download" }),
878
+ /* @__PURE__ */ jsx("button", { onClick: handleRetry, className: cx("ps-tryon-btn-retry", cn.retryButton), children: "Try Another" })
879
+ ] }),
880
+ sizingMethod && !profileSaved && /* @__PURE__ */ jsxs("div", { className: "ps-tryon-save-prompt", children: [
881
+ /* @__PURE__ */ jsx("div", { className: "ps-tryon-save-label", children: "Save your measurements for next time" }),
882
+ /* @__PURE__ */ jsxs("div", { className: "ps-tryon-save-row", children: [
883
+ /* @__PURE__ */ jsx("input", { type: "text", placeholder: "Name this profile (e.g. John, Sarah)", value: profileName, onChange: (e) => setProfileName(e.target.value) }),
884
+ /* @__PURE__ */ jsx("button", { onClick: () => {
885
+ if (profileName.trim()) saveProfile(profileName.trim());
886
+ }, children: "Save" })
887
+ ] })
888
+ ] }),
889
+ profileSaved && /* @__PURE__ */ jsxs("div", { className: "ps-tryon-save-done", children: [
890
+ /* @__PURE__ */ jsx(CheckIcon, {}),
891
+ " Measurements saved to profile"
892
+ ] })
893
+ ] })
894
+ ] });
895
+ }
896
+ function ErrorView() {
897
+ return /* @__PURE__ */ jsxs("div", { className: cx("ps-tryon-error", cn.error), children: [
898
+ /* @__PURE__ */ jsx(AlertIcon, {}),
899
+ /* @__PURE__ */ jsx("p", { className: cx("ps-tryon-error-text", cn.errorText), children: errorMessage || "Something went wrong" }),
900
+ /* @__PURE__ */ jsx("button", { onClick: handleRetry, className: cx("ps-tryon-submit", cn.submitButton), children: "Try Again" })
901
+ ] });
902
+ }
903
+ function DrawerPanel() {
904
+ if (!drawer) return null;
905
+ return /* @__PURE__ */ jsxs("div", { className: `ps-tryon-drawer${drawer ? " ps-tryon-drawer-open" : ""}`, children: [
906
+ /* @__PURE__ */ jsxs("div", { className: "ps-tryon-drawer-header", children: [
907
+ /* @__PURE__ */ jsx("button", { className: "ps-tryon-drawer-back", onClick: () => setDrawer(null), children: /* @__PURE__ */ jsx(ArrowLeftIcon, {}) }),
908
+ /* @__PURE__ */ jsx("span", { className: "ps-tryon-drawer-title", children: drawer === "profiles" ? "My Profiles" : "History" })
909
+ ] }),
910
+ /* @__PURE__ */ jsx("div", { className: "ps-tryon-drawer-list", children: drawer === "profiles" ? profiles.length === 0 ? /* @__PURE__ */ jsx("div", { className: "ps-tryon-drawer-empty", children: "No saved profiles yet." }) : profiles.map((p) => /* @__PURE__ */ jsxs("div", { className: "ps-tryon-profile-item", onClick: () => {
911
+ setProfileDetail(p);
912
+ setDrawer(null);
913
+ }, children: [
914
+ /* @__PURE__ */ jsx("div", { className: "ps-tryon-profile-avatar", children: /* @__PURE__ */ jsx(UserIcon, { size: 20 }) }),
915
+ /* @__PURE__ */ jsxs("div", { className: "ps-tryon-profile-info", children: [
916
+ /* @__PURE__ */ jsx("div", { className: "ps-tryon-profile-name", children: p.name }),
917
+ /* @__PURE__ */ jsxs("div", { className: "ps-tryon-profile-detail", children: [
918
+ p.gender === "female" ? "Women's" : "Men's",
919
+ p.heightCm ? ` · ${Math.round(p.heightCm)}cm` : ""
920
+ ] })
921
+ ] }),
922
+ /* @__PURE__ */ jsx(ChevronRightIcon, {})
923
+ ] }, p.id)) : history.length === 0 ? /* @__PURE__ */ jsx("div", { className: "ps-tryon-drawer-empty", children: "No history yet." }) : history.map((entry, idx) => /* @__PURE__ */ jsxs("div", { className: "ps-tryon-history-item", children: [
924
+ entry.productImage && /* @__PURE__ */ jsx("img", { src: entry.productImage, alt: "", className: "ps-tryon-history-thumb" }),
925
+ /* @__PURE__ */ jsxs("div", { className: "ps-tryon-history-info", children: [
926
+ /* @__PURE__ */ jsx("div", { className: "ps-tryon-history-product", children: entry.productTitle || "Product" }),
927
+ /* @__PURE__ */ jsxs("div", { className: "ps-tryon-history-meta", children: [
928
+ entry.profileName ? `${entry.profileName} · ` : "",
929
+ new Date(entry.date).toLocaleDateString()
930
+ ] }),
931
+ entry.recommendedSize && /* @__PURE__ */ jsx("div", { className: "ps-tryon-history-sizing", children: /* @__PURE__ */ jsx("span", { className: "ps-tryon-history-size-badge", children: entry.recommendedSize }) })
932
+ ] }),
933
+ entry.resultImageUrl && /* @__PURE__ */ jsx("img", { src: entry.resultImageUrl, alt: "", className: "ps-tryon-history-result-img" }),
934
+ /* @__PURE__ */ jsx("button", { className: "ps-tryon-history-delete", onClick: (e) => {
935
+ e.stopPropagation();
936
+ setHistory((prev) => prev.filter((_, i) => i !== idx));
937
+ }, children: /* @__PURE__ */ jsx(TrashIcon, {}) })
938
+ ] }, entry.id)) })
939
+ ] });
940
+ }
941
+ function ProfileDetailModal() {
942
+ if (!profileDetail) return null;
943
+ const p = profileDetail;
944
+ const measurements = [
945
+ { label: "Height", value: p.heightCm, unit: "cm" },
946
+ { label: "Weight", value: p.weightKg, unit: "kg" },
947
+ { label: "Chest", value: p.chest, unit: "cm" },
948
+ { label: "Bust", value: p.bust, unit: "cm" },
949
+ { label: "Waist", value: p.waist, unit: "cm" },
950
+ { label: "Hips", value: p.hips, unit: "cm" },
951
+ { label: "Shoulders", value: p.shoulderWidth, unit: "cm" },
952
+ { label: "Sleeve", value: p.sleeveLength, unit: "cm" },
953
+ { label: "Inseam", value: p.inseam, unit: "cm" },
954
+ { label: "Neck", value: p.neckCircumference, unit: "cm" },
955
+ { label: "Foot", value: p.footLengthCm, unit: "cm" },
956
+ { label: "Shoe EU", value: p.shoeEU ? Number(p.shoeEU) : void 0, unit: "" },
957
+ { label: "Shoe US", value: p.shoeUS ? Number(p.shoeUS) : void 0, unit: "" },
958
+ { label: "Shoe UK", value: p.shoeUK ? Number(p.shoeUK) : void 0, unit: "" }
959
+ ].filter((m) => m.value);
960
+ return /* @__PURE__ */ jsx("div", { className: "ps-tryon-detail-overlay", onClick: (e) => {
961
+ if (e.target === e.currentTarget) setProfileDetail(null);
962
+ }, children: /* @__PURE__ */ jsxs("div", { className: "ps-tryon-detail-modal", children: [
963
+ /* @__PURE__ */ jsxs("div", { className: "ps-tryon-detail-header", children: [
964
+ /* @__PURE__ */ jsx("span", { children: p.name }),
965
+ /* @__PURE__ */ jsx("button", { onClick: () => setProfileDetail(null), children: /* @__PURE__ */ jsx(XIcon, { size: 18 }) })
966
+ ] }),
967
+ /* @__PURE__ */ jsxs("div", { className: "ps-tryon-detail-body", children: [
968
+ /* @__PURE__ */ jsxs("div", { className: "ps-tryon-detail-gender", children: [
969
+ /* @__PURE__ */ jsx(UserIcon, { size: 18 }),
970
+ " ",
971
+ p.gender === "female" ? "Women's" : "Men's",
972
+ " Profile"
973
+ ] }),
974
+ measurements.length > 0 && /* @__PURE__ */ jsx("div", { className: "ps-tryon-detail-grid", children: measurements.map((m) => /* @__PURE__ */ jsxs("div", { className: "ps-tryon-detail-cell", children: [
975
+ /* @__PURE__ */ jsx("div", { className: "ps-tryon-detail-cell-label", children: m.label }),
976
+ /* @__PURE__ */ jsxs("div", { className: "ps-tryon-detail-cell-value", children: [
977
+ Math.round(m.value),
978
+ m.unit ? ` ${m.unit}` : ""
979
+ ] })
980
+ ] }, m.label)) }),
981
+ p.createdAt && /* @__PURE__ */ jsxs("div", { className: "ps-tryon-detail-date", children: [
982
+ "Saved ",
983
+ new Date(p.createdAt).toLocaleDateString()
984
+ ] }),
985
+ /* @__PURE__ */ jsxs("button", { className: "ps-tryon-detail-delete", onClick: () => {
986
+ setProfiles((prev) => prev.filter((x) => x.id !== p.id));
987
+ if (activeProfileId === p.id) setActiveProfileId(null);
988
+ setProfileDetail(null);
989
+ }, children: [
990
+ /* @__PURE__ */ jsx(TrashIcon, {}),
991
+ " Delete Profile"
992
+ ] })
993
+ ] })
994
+ ] }) });
995
+ }
996
+ function renderBody() {
997
+ switch (view) {
998
+ case "welcome":
999
+ return /* @__PURE__ */ jsx(WelcomeView, {});
1000
+ case "upload":
1001
+ return /* @__PURE__ */ jsx(UploadView, {});
1002
+ case "sizing-choice":
1003
+ return /* @__PURE__ */ jsx(SizingChoiceView, {});
1004
+ case "sizing-form":
1005
+ return /* @__PURE__ */ jsx(SizingFormView, {});
1006
+ case "processing":
1007
+ return /* @__PURE__ */ jsx(ProcessingView, {});
1008
+ case "result":
1009
+ return /* @__PURE__ */ jsx(ResultView, {});
1010
+ case "error":
1011
+ return /* @__PURE__ */ jsx(ErrorView, {});
1012
+ default:
1013
+ return null;
1014
+ }
1015
+ }
1016
+ return /* @__PURE__ */ jsxs("div", { className: cx("ps-tryon-root", cn.root || className), style: { ...cssVars, ...style }, "data-ps-tryon": true, children: [
1017
+ /* @__PURE__ */ jsxs("button", { onClick: handleOpen, className: cx("ps-tryon-btn", cn.button), children: [
1018
+ /* @__PURE__ */ jsx(CameraIcon, { size: parseInt(btnS.iconSize || "18") }),
1019
+ /* @__PURE__ */ jsx("span", { children: buttonText })
1020
+ ] }),
1021
+ view !== "idle" && /* @__PURE__ */ jsx("div", { className: cx("ps-tryon-overlay", cn.overlay), onClick: (e) => {
1022
+ if (e.target === e.currentTarget) handleClose();
1023
+ }, children: /* @__PURE__ */ jsxs("div", { className: cx(`ps-tryon-modal${view === "result" && resultImageUrl && sizingResult ? " ps-tryon-modal-wide" : ""}`, cn.modal), onClick: (e) => e.stopPropagation(), children: [
1024
+ /* @__PURE__ */ jsxs("div", { className: cx("ps-tryon-header", cn.header), children: [
1025
+ /* @__PURE__ */ jsx("span", { className: cx("ps-tryon-title", cn.title), children: "Virtual Try-On" }),
1026
+ /* @__PURE__ */ jsxs("div", { className: "ps-tryon-header-actions", children: [
1027
+ profiles.length > 0 && /* @__PURE__ */ jsx("button", { className: "ps-tryon-header-icon", title: "Profiles", onClick: () => setDrawer(drawer === "profiles" ? null : "profiles"), children: /* @__PURE__ */ jsx(UserIcon, {}) }),
1028
+ history.length > 0 && /* @__PURE__ */ jsx("button", { className: "ps-tryon-header-icon", title: "History", onClick: () => setDrawer(drawer === "history" ? null : "history"), children: /* @__PURE__ */ jsx(ClockIcon, {}) }),
1029
+ /* @__PURE__ */ jsx("button", { onClick: handleClose, className: cx("ps-tryon-close", cn.closeButton), children: /* @__PURE__ */ jsx(XIcon, {}) })
1030
+ ] })
1031
+ ] }),
1032
+ /* @__PURE__ */ jsx(Stepper, {}),
1033
+ /* @__PURE__ */ jsxs("div", { ref: bodyRef, className: cx("ps-tryon-body", cn.body), style: { position: "relative", overflow: drawer ? "hidden" : void 0 }, children: [
1034
+ renderBody(),
1035
+ /* @__PURE__ */ jsx(DrawerPanel, {})
1036
+ ] }),
1037
+ showPoweredBy && /* @__PURE__ */ jsxs("div", { className: cx("ps-tryon-powered", cn.poweredBy), children: [
1038
+ "Powered by",
1039
+ " ",
1040
+ /* @__PURE__ */ jsx("a", { href: "https://myaifitting.com", target: "_blank", rel: "noopener noreferrer", children: "PrimeStyle AI" })
1041
+ ] })
1042
+ ] }) }),
1043
+ /* @__PURE__ */ jsx(ProfileDetailModal, {}),
1044
+ /* @__PURE__ */ jsx("style", { children: STYLES })
1045
+ ] });
1046
+ }
1047
+ const STYLES = `
1048
+ .ps-tryon-root { display: inline-block; }
608
1049
 
609
- .ps-tryon-btn {
610
- display: inline-flex;
611
- align-items: center;
612
- gap: 8px;
613
- padding: var(--ps-btn-padding, 12px 24px);
614
- background: var(--ps-btn-bg, #bb945c);
615
- color: var(--ps-btn-color, #111211);
616
- font-family: var(--ps-btn-font, system-ui, -apple-system, sans-serif);
617
- font-size: var(--ps-btn-font-size, 14px);
618
- font-weight: var(--ps-btn-font-weight, 600);
619
- border: var(--ps-btn-border, none);
620
- border-radius: var(--ps-btn-radius, 8px);
621
- cursor: pointer;
622
- transition: all 0.2s ease;
623
- width: var(--ps-btn-width, auto);
624
- height: var(--ps-btn-height, auto);
625
- box-shadow: var(--ps-btn-shadow, none);
626
- line-height: 1;
627
- white-space: nowrap;
628
- }
629
- .ps-tryon-btn:hover {
630
- background: var(--ps-btn-hover-bg, #a07d4e);
631
- color: var(--ps-btn-hover-color, var(--ps-btn-color, #111211));
632
- transform: translateY(-1px);
633
- }
634
- .ps-tryon-btn:active { transform: translateY(0); }
1050
+ .ps-tryon-btn {
1051
+ display: inline-flex; align-items: center; gap: 8px;
1052
+ padding: var(--ps-btn-padding, 12px 24px);
1053
+ background: var(--ps-btn-bg, #bb945c); color: var(--ps-btn-color, #111211);
1054
+ font-family: var(--ps-btn-font, system-ui, -apple-system, sans-serif);
1055
+ font-size: var(--ps-btn-font-size, 14px); font-weight: var(--ps-btn-font-weight, 600);
1056
+ border: var(--ps-btn-border, none); border-radius: var(--ps-btn-radius, 8px);
1057
+ cursor: pointer; transition: all 0.2s ease;
1058
+ width: var(--ps-btn-width, auto); height: var(--ps-btn-height, auto);
1059
+ box-shadow: var(--ps-btn-shadow, none); line-height: 1; white-space: nowrap;
1060
+ }
1061
+ .ps-tryon-btn:hover { background: var(--ps-btn-hover-bg, #a07d4e); transform: translateY(-1px); }
1062
+ .ps-tryon-btn:active { transform: translateY(0); }
635
1063
 
636
- .ps-tryon-overlay {
637
- position: fixed;
638
- inset: 0;
639
- background: var(--ps-modal-overlay, rgba(0,0,0,0.6));
640
- display: flex;
641
- align-items: center;
642
- justify-content: center;
643
- z-index: 999999;
644
- padding: 16px;
645
- animation: ps-fade-in 0.2s ease;
646
- }
647
- @keyframes ps-fade-in {
648
- from { opacity: 0; }
649
- to { opacity: 1; }
650
- }
1064
+ .ps-tryon-overlay {
1065
+ position: fixed; inset: 0; background: var(--ps-modal-overlay, rgba(0,0,0,0.6));
1066
+ display: flex; align-items: center; justify-content: center;
1067
+ z-index: 999999; padding: 16px; animation: ps-fade-in 0.2s ease;
1068
+ }
1069
+ @keyframes ps-fade-in { from { opacity: 0; } to { opacity: 1; } }
651
1070
 
652
- .ps-tryon-modal {
653
- background: var(--ps-modal-bg, #111211);
654
- color: var(--ps-modal-color, #ffffff);
655
- border-radius: var(--ps-modal-radius, 12px);
656
- width: var(--ps-modal-width, 100%);
657
- max-width: var(--ps-modal-max-width, 480px);
658
- max-height: 90vh;
659
- overflow-y: auto;
660
- font-family: var(--ps-modal-font, system-ui, -apple-system, sans-serif);
661
- box-shadow: 0 25px 50px rgba(0,0,0,0.4);
662
- animation: ps-slide-up 0.25s ease;
663
- }
664
- @keyframes ps-slide-up {
665
- from { transform: translateY(20px) scale(0.97); opacity: 0; }
666
- to { transform: translateY(0) scale(1); opacity: 1; }
667
- }
1071
+ .ps-tryon-modal {
1072
+ background: var(--ps-modal-bg, #111211); color: var(--ps-modal-color, #fff);
1073
+ border-radius: var(--ps-modal-radius, 16px); width: var(--ps-modal-width, 100%);
1074
+ max-width: var(--ps-modal-max-width, 520px); max-height: 92vh; overflow-y: auto;
1075
+ font-family: var(--ps-modal-font, system-ui, -apple-system, sans-serif);
1076
+ box-shadow: 0 25px 50px rgba(0,0,0,0.4); animation: ps-slide-up 0.3s ease;
1077
+ scrollbar-width: thin; scrollbar-color: #333 transparent;
1078
+ }
1079
+ .ps-tryon-modal-wide { max-width: 920px; }
1080
+ @keyframes ps-slide-up { from { transform: translateY(20px) scale(0.97); opacity: 0; } to { transform: translateY(0) scale(1); opacity: 1; } }
668
1081
 
669
- .ps-tryon-header {
670
- display: flex;
671
- align-items: center;
672
- justify-content: space-between;
673
- padding: 20px 24px;
674
- background: var(--ps-modal-header-bg, #1a1b1a);
675
- border-bottom: 1px solid #333;
676
- border-radius: var(--ps-modal-radius, 12px) var(--ps-modal-radius, 12px) 0 0;
677
- }
678
- .ps-tryon-title {
679
- font-size: 16px;
680
- font-weight: 600;
681
- color: var(--ps-modal-header-color, #fff);
682
- }
683
- .ps-tryon-close {
684
- width: 32px;
685
- height: 32px;
686
- display: flex;
687
- align-items: center;
688
- justify-content: center;
689
- background: none;
690
- border: none;
691
- color: var(--ps-modal-close-color, #999);
692
- cursor: pointer;
693
- border-radius: 6px;
694
- transition: background 0.15s;
695
- }
696
- .ps-tryon-close:hover { background: rgba(255,255,255,0.1); }
1082
+ /* Header */
1083
+ .ps-tryon-header {
1084
+ display: flex; align-items: center; justify-content: space-between;
1085
+ padding: 18px 24px; background: var(--ps-modal-header-bg, #1a1b1a);
1086
+ border-bottom: 1px solid #333;
1087
+ border-radius: var(--ps-modal-radius, 16px) var(--ps-modal-radius, 16px) 0 0;
1088
+ }
1089
+ .ps-tryon-title { font-size: 15px; font-weight: 600; color: var(--ps-modal-header-color, #fff); }
1090
+ .ps-tryon-header-actions { display: flex; align-items: center; gap: 8px; }
1091
+ .ps-tryon-header-icon {
1092
+ width: 34px; height: 34px; display: flex; align-items: center; justify-content: center;
1093
+ border: 1.5px solid #333; border-radius: 10px; background: transparent;
1094
+ cursor: pointer; color: #999; transition: all 0.2s;
1095
+ }
1096
+ .ps-tryon-header-icon:hover { border-color: #bb945c; color: #bb945c; }
1097
+ .ps-tryon-header-icon svg { stroke: currentColor; fill: none; }
1098
+ .ps-tryon-close {
1099
+ width: 32px; height: 32px; display: flex; align-items: center; justify-content: center;
1100
+ background: none; border: none; color: var(--ps-modal-close-color, #999);
1101
+ cursor: pointer; border-radius: 6px; transition: background 0.15s;
1102
+ }
1103
+ .ps-tryon-close:hover { background: rgba(255,255,255,0.1); }
697
1104
 
698
- .ps-tryon-body { padding: 24px; }
1105
+ /* Stepper */
1106
+ .ps-tryon-stepper { padding: 20px 24px 12px; }
1107
+ .ps-tryon-stepper-track { display: flex; align-items: flex-start; }
1108
+ .ps-tryon-stepper-fragment { display: flex; align-items: flex-start; flex: 1; }
1109
+ .ps-tryon-stepper-fragment:first-child { flex: 0 0 auto; }
1110
+ .ps-tryon-stepper-line { flex: 1; height: 2px; background: #333; margin-top: 14px; transition: background 0.4s; }
1111
+ .ps-tryon-stepper-line.ps-done { background: #bb945c; }
1112
+ .ps-tryon-stepper-step { display: flex; flex-direction: column; align-items: center; }
1113
+ .ps-tryon-stepper-circle {
1114
+ width: 28px; height: 28px; border-radius: 50%;
1115
+ display: flex; align-items: center; justify-content: center;
1116
+ border: 2px solid #333; font-size: 12px; font-weight: 600; color: #666;
1117
+ transition: all 0.3s;
1118
+ }
1119
+ .ps-tryon-stepper-step.ps-done .ps-tryon-stepper-circle { background: #bb945c; border-color: #bb945c; color: #111; }
1120
+ .ps-tryon-stepper-step.ps-done .ps-tryon-stepper-circle svg { stroke: #111; }
1121
+ .ps-tryon-stepper-step.ps-active .ps-tryon-stepper-circle { border-color: #bb945c; color: #bb945c; box-shadow: 0 0 0 4px rgba(187,148,92,0.15); }
1122
+ .ps-tryon-stepper-label { font-size: 10px; margin-top: 5px; color: #666; font-weight: 500; text-align: center; white-space: nowrap; }
1123
+ .ps-tryon-stepper-step.ps-done .ps-tryon-stepper-label { color: #bb945c; }
1124
+ .ps-tryon-stepper-step.ps-active .ps-tryon-stepper-label { color: #bb945c; font-weight: 700; }
699
1125
 
700
- .ps-tryon-upload {
701
- border: 2px dashed var(--ps-upload-border, #333);
702
- border-radius: 12px;
703
- padding: 40px 24px;
704
- text-align: center;
705
- cursor: pointer;
706
- transition: all 0.2s;
707
- background: var(--ps-upload-bg, transparent);
708
- display: flex;
709
- flex-direction: column;
710
- align-items: center;
711
- }
712
- .ps-tryon-upload:hover, .ps-tryon-drag-over {
713
- border-color: #bb945c;
714
- background: rgba(187,148,92,0.05);
715
- }
716
- .ps-tryon-upload svg {
717
- color: var(--ps-upload-icon-color, #bb945c);
718
- margin-bottom: 12px;
719
- }
720
- .ps-tryon-upload-text {
721
- font-size: 14px;
722
- color: var(--ps-upload-color, #fff);
723
- margin: 0 0 4px;
724
- }
725
- .ps-tryon-upload-hint {
726
- font-size: 12px;
727
- color: #999;
728
- margin: 0;
729
- }
1126
+ /* Body */
1127
+ .ps-tryon-body { padding: 24px; min-height: 300px; }
1128
+ .ps-tryon-body > * { animation: ps-fade-up 0.35s ease both; }
1129
+ @keyframes ps-fade-up { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: translateY(0); } }
730
1130
 
731
- .ps-tryon-preview {
732
- position: relative;
733
- margin-bottom: 4px;
734
- }
735
- .ps-tryon-preview img {
736
- width: 100%;
737
- border-radius: 12px;
738
- display: block;
739
- }
740
- .ps-tryon-preview-remove {
741
- position: absolute;
742
- top: 8px;
743
- right: 8px;
744
- width: 28px;
745
- height: 28px;
746
- border-radius: 50%;
747
- background: rgba(0,0,0,0.6);
748
- border: none;
749
- color: white;
750
- cursor: pointer;
751
- display: flex;
752
- align-items: center;
753
- justify-content: center;
754
- font-size: 16px;
755
- transition: background 0.15s;
756
- }
757
- .ps-tryon-preview-remove:hover { background: rgba(0,0,0,0.8); }
1131
+ /* Welcome */
1132
+ .ps-tryon-welcome { text-align: center; }
1133
+ .ps-tryon-welcome-hero { margin-bottom: 20px; }
1134
+ .ps-tryon-welcome-img-wrap { position: relative; display: inline-block; }
1135
+ .ps-tryon-welcome-product { width: 120px; height: 140px; object-fit: cover; border-radius: 14px; border: 2px solid #333; }
1136
+ .ps-tryon-welcome-sparkle { position: absolute; top: -8px; right: -8px; width: 28px; height: 28px; background: #bb945c; border-radius: 50%; display: flex; align-items: center; justify-content: center; animation: ps-float 3s ease-in-out infinite; }
1137
+ .ps-tryon-welcome-sparkle svg { stroke: #111; width: 14px; height: 14px; }
1138
+ @keyframes ps-float { 0%,100% { transform: translateY(0); } 50% { transform: translateY(-6px); } }
1139
+ .ps-tryon-welcome-title { font-size: 20px; font-weight: 700; color: #fff; margin: 14px 0 4px; }
1140
+ .ps-tryon-welcome-sub { font-size: 13px; color: #999; margin: 0; }
1141
+ .ps-tryon-features { display: flex; gap: 10px; margin: 20px 0; }
1142
+ .ps-tryon-feature { flex: 1; padding: 14px 10px; border: 1px solid #333; border-radius: 12px; text-align: center; }
1143
+ .ps-tryon-feature-icon { margin-bottom: 6px; color: #bb945c; display: flex; justify-content: center; }
1144
+ .ps-tryon-feature-icon svg { stroke: currentColor; fill: none; }
1145
+ .ps-tryon-feature-title { font-size: 12px; font-weight: 600; color: #fff; margin-bottom: 2px; }
1146
+ .ps-tryon-feature-desc { font-size: 10px; color: #999; }
1147
+ .ps-tryon-cta {
1148
+ width: 100%; padding: 14px; background: #bb945c; color: #111; border: none;
1149
+ border-radius: 12px; font-size: 15px; font-weight: 700; cursor: pointer;
1150
+ display: flex; align-items: center; justify-content: center; gap: 8px; transition: all 0.2s;
1151
+ font-family: var(--ps-modal-font, system-ui, sans-serif);
1152
+ }
1153
+ .ps-tryon-cta:hover { background: #a07d4e; transform: translateY(-1px); }
1154
+ .ps-tryon-cta svg { stroke: #111; }
1155
+ .ps-tryon-welcome-note { font-size: 11px; color: #666; margin-top: 12px; }
758
1156
 
759
- .ps-tryon-submit {
760
- width: 100%;
761
- padding: 14px;
762
- margin-top: 20px;
763
- background: var(--ps-modal-primary-bg, #bb945c);
764
- color: var(--ps-modal-primary-color, #111211);
765
- font-family: var(--ps-modal-font, system-ui, sans-serif);
766
- font-size: 14px;
767
- font-weight: 600;
768
- border: none;
769
- border-radius: var(--ps-modal-primary-radius, 8px);
770
- cursor: pointer;
771
- transition: all 0.2s;
772
- display: flex;
773
- align-items: center;
774
- justify-content: center;
775
- gap: 8px;
776
- }
777
- .ps-tryon-submit:hover { opacity: 0.9; transform: translateY(-1px); }
778
- .ps-tryon-submit:disabled { opacity: 0.5; cursor: not-allowed; }
1157
+ /* Upload */
1158
+ .ps-tryon-upload {
1159
+ border: 2px dashed var(--ps-upload-border, #333); border-radius: 12px;
1160
+ padding: 40px 24px; text-align: center; cursor: pointer; transition: all 0.2s;
1161
+ background: var(--ps-upload-bg, transparent); display: flex; flex-direction: column; align-items: center;
1162
+ }
1163
+ .ps-tryon-upload:hover, .ps-tryon-drag-over { border-color: #bb945c; background: rgba(187,148,92,0.05); }
1164
+ .ps-tryon-upload svg { color: var(--ps-upload-icon-color, #bb945c); margin-bottom: 12px; }
1165
+ .ps-tryon-upload-text { font-size: 14px; color: var(--ps-upload-color, #fff); margin: 0 0 4px; }
1166
+ .ps-tryon-upload-hint { font-size: 12px; color: #999; margin: 0; }
1167
+ .ps-tryon-preview { position: relative; margin-bottom: 4px; }
1168
+ .ps-tryon-preview img { width: 100%; border-radius: 12px; display: block; }
1169
+ .ps-tryon-preview-remove {
1170
+ position: absolute; top: 8px; right: 8px; width: 28px; height: 28px;
1171
+ border-radius: 50%; background: rgba(0,0,0,0.6); border: none; color: white;
1172
+ cursor: pointer; display: flex; align-items: center; justify-content: center;
1173
+ font-size: 16px; transition: background 0.15s;
1174
+ }
1175
+ .ps-tryon-preview-remove:hover { background: rgba(0,0,0,0.8); }
1176
+ .ps-tryon-submit {
1177
+ width: 100%; padding: 14px; margin-top: 16px;
1178
+ background: var(--ps-modal-primary-bg, #bb945c); color: var(--ps-modal-primary-color, #111);
1179
+ font-family: var(--ps-modal-font, system-ui, sans-serif);
1180
+ font-size: 14px; font-weight: 600; border: none;
1181
+ border-radius: var(--ps-modal-primary-radius, 10px);
1182
+ cursor: pointer; transition: all 0.2s;
1183
+ display: flex; align-items: center; justify-content: center; gap: 8px;
1184
+ }
1185
+ .ps-tryon-submit:hover { opacity: 0.9; transform: translateY(-1px); }
1186
+ .ps-tryon-submit svg { stroke: currentColor; }
779
1187
 
780
- .ps-tryon-processing {
781
- text-align: center;
782
- padding: 40px 24px;
783
- }
784
- .ps-tryon-spinner {
785
- width: 48px;
786
- height: 48px;
787
- border: 3px solid #333;
788
- border-top-color: var(--ps-loader, #bb945c);
789
- border-radius: 50%;
790
- animation: ps-spin 0.8s linear infinite;
791
- margin: 0 auto 16px;
792
- }
793
- @keyframes ps-spin { to { transform: rotate(360deg); } }
1188
+ /* Profile bar */
1189
+ .ps-tryon-profile-bar { margin-bottom: 16px; }
1190
+ .ps-tryon-profile-select {
1191
+ width: 100%; padding: 10px 36px 10px 14px; border: 1.5px solid #333; border-radius: 10px;
1192
+ background: #1a1b1a; color: #fff; font-size: 13px; font-family: inherit;
1193
+ appearance: none; -webkit-appearance: none; cursor: pointer; outline: none;
1194
+ background-image: url("data:image/svg+xml,%3Csvg width='12' height='12' viewBox='0 0 12 12' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M2.5 4.5L6 8L9.5 4.5' stroke='%23999' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
1195
+ background-repeat: no-repeat; background-position: right 14px center;
1196
+ }
1197
+ .ps-tryon-profile-select:focus { border-color: #bb945c; }
794
1198
 
795
- .ps-tryon-countdown-ring {
796
- position: relative;
797
- width: 100px;
798
- height: 100px;
799
- margin: 0 auto 20px;
800
- }
801
- .ps-tryon-countdown-ring svg {
802
- width: 100%;
803
- height: 100%;
804
- transform: rotate(-90deg);
805
- }
806
- .ps-tryon-countdown-track {
807
- fill: none;
808
- stroke: #333;
809
- stroke-width: 4;
810
- }
811
- .ps-tryon-countdown-progress {
812
- fill: none;
813
- stroke: var(--ps-loader, #bb945c);
814
- stroke-width: 4;
815
- stroke-linecap: round;
816
- stroke-dasharray: 326.73;
817
- transition: stroke-dashoffset 1s linear;
818
- }
819
- .ps-tryon-countdown-number {
820
- position: absolute;
821
- inset: 0;
822
- display: flex;
823
- align-items: center;
824
- justify-content: center;
825
- font-size: 28px;
826
- font-weight: 700;
827
- color: #fff;
828
- font-variant-numeric: tabular-nums;
829
- }
1199
+ /* Sizing choice */
1200
+ .ps-tryon-sizing-choice { text-align: center; }
1201
+ .ps-tryon-section-title { font-size: 16px; font-weight: 600; color: #fff; margin: 0 0 16px; }
1202
+ .ps-tryon-choice-cards { display: flex; flex-direction: column; gap: 10px; }
1203
+ .ps-tryon-choice-card {
1204
+ display: flex; align-items: center; gap: 14px; padding: 16px;
1205
+ border: 1.5px solid #333; border-radius: 12px;
1206
+ background: #1a1b1a; cursor: pointer; transition: all 0.25s; text-align: left;
1207
+ width: 100%; font-family: inherit; position: relative; overflow: hidden;
1208
+ }
1209
+ .ps-tryon-choice-card:hover { border-color: #bb945c; transform: translateY(-1px); box-shadow: 0 6px 20px rgba(187,148,92,0.08); }
1210
+ .ps-tryon-choice-card:hover::before { content: ''; position: absolute; left: 0; top: 0; bottom: 0; width: 3px; background: #bb945c; }
1211
+ .ps-tryon-choice-icon { color: #bb945c; flex-shrink: 0; }
1212
+ .ps-tryon-choice-icon svg { stroke: currentColor; fill: none; }
1213
+ .ps-tryon-choice-info { flex: 1; min-width: 0; }
1214
+ .ps-tryon-choice-title { font-size: 14px; font-weight: 600; color: #fff; }
1215
+ .ps-tryon-choice-desc { font-size: 12px; color: #999; margin-top: 2px; }
1216
+ .ps-tryon-choice-badge {
1217
+ padding: 3px 10px; border-radius: 20px; flex-shrink: 0;
1218
+ background: rgba(187,148,92,0.12); color: #bb945c; font-size: 10px; font-weight: 600;
1219
+ }
830
1220
 
831
- .ps-tryon-done-pulse {
832
- animation: ps-fade-scale-in 0.4s ease both;
833
- margin-bottom: 4px;
834
- }
835
- @keyframes ps-fade-scale-in {
836
- from { opacity: 0; transform: scale(0.8); }
837
- to { opacity: 1; transform: scale(1); }
838
- }
1221
+ /* Sizing form */
1222
+ .ps-tryon-sizing-form { display: flex; flex-direction: column; gap: 12px; }
1223
+ .ps-tryon-input-row { display: flex; align-items: center; gap: 10px; }
1224
+ .ps-tryon-input-row label { font-size: 13px; font-weight: 500; color: #ccc; min-width: 90px; flex-shrink: 0; }
1225
+ .ps-tryon-input-row input {
1226
+ flex: 1; padding: 10px 14px; border: 1.5px solid #333; border-radius: 10px;
1227
+ background: #1a1b1a; color: #fff; font-size: 14px; font-family: inherit; outline: none;
1228
+ transition: border-color 0.2s; -moz-appearance: textfield;
1229
+ }
1230
+ .ps-tryon-input-row input::-webkit-outer-spin-button,
1231
+ .ps-tryon-input-row input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
1232
+ .ps-tryon-input-row input:focus { border-color: #bb945c; }
1233
+ .ps-tryon-input-unit { font-size: 12px; color: #666; flex-shrink: 0; }
1234
+ .ps-tryon-height-ft { display: flex; align-items: center; gap: 6px; flex: 1; }
1235
+ .ps-tryon-height-ft input { width: 60px; padding: 10px 10px; border: 1.5px solid #333; border-radius: 10px; background: #1a1b1a; color: #fff; font-size: 14px; font-family: inherit; outline: none; text-align: center; -moz-appearance: textfield; }
1236
+ .ps-tryon-height-ft input::-webkit-outer-spin-button, .ps-tryon-height-ft input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
1237
+ .ps-tryon-height-ft input:focus { border-color: #bb945c; }
1238
+ .ps-tryon-height-ft span { font-size: 12px; color: #666; }
1239
+ .ps-tryon-country-select {
1240
+ flex: 1; padding: 10px 36px 10px 14px; border: 1.5px solid #333; border-radius: 10px;
1241
+ background: #1a1b1a; color: #fff; font-size: 13px; font-family: inherit;
1242
+ appearance: none; -webkit-appearance: none; cursor: pointer; outline: none;
1243
+ background-image: url("data:image/svg+xml,%3Csvg width='12' height='12' viewBox='0 0 12 12' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M2.5 4.5L6 8L9.5 4.5' stroke='%23999' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
1244
+ background-repeat: no-repeat; background-position: right 14px center;
1245
+ }
1246
+ .ps-tryon-country-select:focus { border-color: #bb945c; }
1247
+ .ps-tryon-unit-toggle { display: flex; gap: 0; border: 1.5px solid #333; border-radius: 8px; overflow: hidden; }
1248
+ .ps-tryon-unit-btn {
1249
+ padding: 6px 14px; background: transparent; border: none; color: #999;
1250
+ font-size: 12px; font-weight: 600; cursor: pointer; transition: all 0.2s; font-family: inherit;
1251
+ }
1252
+ .ps-tryon-unit-btn.ps-active { background: #bb945c; color: #111; }
1253
+ .ps-tryon-shoe-section { border-top: 1px solid #333; padding-top: 14px; margin-top: 6px; display: flex; flex-direction: column; gap: 10px; }
1254
+ .ps-tryon-shoe-title { font-size: 13px; font-weight: 600; color: #999; }
1255
+ .ps-tryon-disclaimer { font-size: 11px; color: #666; margin: 4px 0 0; }
839
1256
 
840
- .ps-tryon-processing-text { font-size: 14px; color: #fff; margin: 0 0 4px; }
841
- .ps-tryon-processing-sub { font-size: 12px; color: #999; margin: 0; }
1257
+ /* Processing */
1258
+ .ps-tryon-processing { text-align: center; padding: 40px 24px; }
1259
+ .ps-tryon-spinner {
1260
+ width: 48px; height: 48px; border: 3px solid #333;
1261
+ border-top-color: var(--ps-loader, #bb945c); border-radius: 50%;
1262
+ animation: ps-spin 0.8s linear infinite; margin: 0 auto 16px;
1263
+ }
1264
+ @keyframes ps-spin { to { transform: rotate(360deg); } }
1265
+ .ps-tryon-countdown-ring { position: relative; width: 100px; height: 100px; margin: 0 auto 20px; }
1266
+ .ps-tryon-countdown-ring svg { width: 100%; height: 100%; transform: rotate(-90deg); }
1267
+ .ps-tryon-countdown-track { fill: none; stroke: #333; stroke-width: 4; }
1268
+ .ps-tryon-countdown-progress { fill: none; stroke: var(--ps-loader, #bb945c); stroke-width: 4; stroke-linecap: round; stroke-dasharray: 326.73; transition: stroke-dashoffset 1s linear; }
1269
+ .ps-tryon-countdown-number { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; font-size: 28px; font-weight: 700; color: #fff; font-variant-numeric: tabular-nums; }
1270
+ .ps-tryon-done-pulse { animation: ps-scale-in 0.4s ease both; }
1271
+ @keyframes ps-scale-in { from { opacity: 0; transform: scale(0.8); } to { opacity: 1; transform: scale(1); } }
1272
+ .ps-tryon-processing-text { font-size: 14px; color: #fff; margin: 0 0 4px; }
1273
+ .ps-tryon-processing-sub { font-size: 12px; color: #999; margin: 0; }
842
1274
 
843
- .ps-tryon-result { text-align: center; }
844
- .ps-tryon-result img {
845
- width: 100%;
846
- border-radius: var(--ps-result-radius, 12px);
847
- display: block;
848
- margin-bottom: 16px;
849
- }
850
- .ps-tryon-result-actions { display: flex; gap: 8px; }
851
- .ps-tryon-result-actions button {
852
- flex: 1;
853
- padding: 12px;
854
- font-family: var(--ps-modal-font, system-ui, sans-serif);
855
- font-size: 13px;
856
- font-weight: 600;
857
- border-radius: 8px;
858
- cursor: pointer;
859
- transition: all 0.2s;
860
- border: none;
861
- }
862
- .ps-tryon-btn-download { background: #bb945c; color: #111211; }
863
- .ps-tryon-btn-download:hover { opacity: 0.9; }
864
- .ps-tryon-btn-retry {
865
- background: rgba(255,255,255,0.1);
866
- color: #fff;
867
- border: 1px solid #333 !important;
868
- }
869
- .ps-tryon-btn-retry:hover { background: rgba(255,255,255,0.15); }
1275
+ /* Result */
1276
+ .ps-tryon-result-layout { text-align: center; }
1277
+ .ps-tryon-result-split { display: flex; gap: 24px; text-align: left; align-items: stretch; }
1278
+ .ps-tryon-result-image-col { flex: 0 0 45%; min-width: 0; display: flex; align-items: center; justify-content: center; }
1279
+ .ps-tryon-result-image-col img { width: 100%; max-height: 400px; object-fit: contain; border-radius: 14px; box-shadow: 0 8px 32px rgba(0,0,0,0.2); animation: ps-scale-in 0.5s ease both; }
1280
+ .ps-tryon-result-info-col { flex: 1; min-width: 0; }
1281
+ .ps-tryon-result-layout:not(.ps-tryon-result-split) img { width: 100%; border-radius: 12px; margin-bottom: 16px; }
1282
+ .ps-tryon-result-actions { display: flex; gap: 8px; margin-top: 16px; }
1283
+ .ps-tryon-result-actions button {
1284
+ flex: 1; padding: 12px; font-family: var(--ps-modal-font, system-ui, sans-serif);
1285
+ font-size: 13px; font-weight: 600; border-radius: 10px; cursor: pointer; transition: all 0.2s; border: none;
1286
+ }
1287
+ .ps-tryon-btn-download { background: #bb945c; color: #111; }
1288
+ .ps-tryon-btn-download:hover { opacity: 0.9; }
1289
+ .ps-tryon-btn-retry { background: rgba(255,255,255,0.08); color: #fff; border: 1px solid #333 !important; }
1290
+ .ps-tryon-btn-retry:hover { background: rgba(255,255,255,0.12); }
870
1291
 
871
- .ps-tryon-error {
872
- text-align: center;
873
- padding: 24px;
874
- display: flex;
875
- flex-direction: column;
876
- align-items: center;
877
- }
878
- .ps-tryon-error svg { color: #ef4444; margin-bottom: 12px; }
879
- .ps-tryon-error-text { font-size: 14px; color: #ef4444; margin: 0 0 16px; }
1292
+ /* Size recommendation */
1293
+ .ps-tryon-size-recommend { margin-bottom: 16px; }
1294
+ .ps-tryon-size-badge {
1295
+ display: inline-flex; align-items: center; justify-content: center;
1296
+ width: 56px; height: 56px; border-radius: 50%;
1297
+ background: linear-gradient(135deg, #bb945c, #d6ba7d);
1298
+ color: #111; font-size: 20px; font-weight: 700; margin-bottom: 10px;
1299
+ }
1300
+ .ps-tryon-size-confidence { font-size: 12px; color: #999; margin-bottom: 8px; }
1301
+ .ps-conf-high { color: #4ade80; } .ps-conf-medium { color: #bb945c; } .ps-conf-low { color: #ef4444; }
1302
+ .ps-tryon-size-reasoning { font-size: 13px; color: #ccc; line-height: 1.5; margin-bottom: 12px; }
1303
+ .ps-tryon-intl-sizes { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 12px; }
1304
+ .ps-tryon-intl-chip { padding: 4px 10px; border: 1px solid #333; border-radius: 8px; font-size: 11px; color: #ccc; font-weight: 500; }
1305
+ .ps-tryon-match-details { margin-top: 12px; }
1306
+ .ps-tryon-match-details summary { font-size: 12px; color: #bb945c; cursor: pointer; font-weight: 600; }
1307
+ .ps-tryon-match-details table { width: 100%; border-collapse: collapse; margin-top: 8px; font-size: 12px; }
1308
+ .ps-tryon-match-details th { text-align: left; padding: 6px 8px; border-bottom: 1px solid #333; color: #999; font-weight: 600; }
1309
+ .ps-tryon-match-details td { padding: 6px 8px; border-bottom: 1px solid #222; color: #ccc; }
1310
+ .ps-fit-good { color: #4ade80; } .ps-fit-tight { color: #f59e0b; } .ps-fit-loose { color: #60a5fa; }
880
1311
 
881
- .ps-tryon-powered {
882
- text-align: center;
883
- padding: 12px 24px 16px;
884
- font-size: 11px;
885
- color: #999;
886
- }
887
- .ps-tryon-powered a { color: #bb945c; text-decoration: none; }
888
- .ps-tryon-powered a:hover { text-decoration: underline; }
889
- ` })
890
- ]
891
- }
892
- );
893
- }
1312
+ /* Save profile prompt */
1313
+ .ps-tryon-save-prompt { margin-top: 14px; padding: 14px; border: 1px solid #333; border-radius: 12px; background: #1a1b1a; }
1314
+ .ps-tryon-save-label { font-size: 12px; color: #999; margin-bottom: 10px; }
1315
+ .ps-tryon-save-row { display: flex; gap: 8px; }
1316
+ .ps-tryon-save-row input {
1317
+ flex: 1; padding: 10px 14px; border: 1.5px solid #333; border-radius: 10px;
1318
+ background: #111211; color: #fff; font-size: 13px; font-family: inherit; outline: none;
1319
+ }
1320
+ .ps-tryon-save-row input:focus { border-color: #bb945c; }
1321
+ .ps-tryon-save-row button {
1322
+ padding: 10px 20px; background: #bb945c; color: #111; border: none; border-radius: 10px;
1323
+ font-size: 13px; font-weight: 600; cursor: pointer; transition: opacity 0.2s; font-family: inherit;
1324
+ }
1325
+ .ps-tryon-save-row button:hover { opacity: 0.9; }
1326
+ .ps-tryon-save-done { font-size: 12px; color: #4ade80; margin-top: 10px; display: flex; align-items: center; gap: 6px; justify-content: center; }
1327
+ .ps-tryon-save-done svg { stroke: currentColor; }
1328
+
1329
+ /* Error */
1330
+ .ps-tryon-error { text-align: center; padding: 24px; display: flex; flex-direction: column; align-items: center; }
1331
+ .ps-tryon-error svg { color: #ef4444; margin-bottom: 12px; }
1332
+ .ps-tryon-error-text { font-size: 14px; color: #ef4444; margin: 0 0 16px; }
1333
+
1334
+ /* Footer */
1335
+ .ps-tryon-powered { text-align: center; padding: 12px 24px 16px; font-size: 11px; color: #666; }
1336
+ .ps-tryon-powered a { color: #bb945c; text-decoration: none; }
1337
+ .ps-tryon-powered a:hover { text-decoration: underline; }
1338
+
1339
+ /* Drawer */
1340
+ .ps-tryon-drawer {
1341
+ position: absolute; inset: 0; z-index: 20; background: var(--ps-modal-bg, #111211);
1342
+ overflow-y: auto; scrollbar-width: thin; padding: 20px 24px;
1343
+ transform: translateX(100%); transition: transform 0.25s cubic-bezier(0.4,0,0.2,1);
1344
+ }
1345
+ .ps-tryon-drawer-open { transform: translateX(0); }
1346
+ .ps-tryon-drawer-header { display: flex; align-items: center; gap: 10px; padding-bottom: 14px; margin-bottom: 14px; border-bottom: 1px solid #333; }
1347
+ .ps-tryon-drawer-back {
1348
+ width: 32px; height: 32px; display: flex; align-items: center; justify-content: center;
1349
+ border: 1.5px solid #333; border-radius: 10px; background: transparent;
1350
+ cursor: pointer; color: #999; transition: all 0.2s; flex-shrink: 0;
1351
+ }
1352
+ .ps-tryon-drawer-back:hover { border-color: #bb945c; color: #bb945c; }
1353
+ .ps-tryon-drawer-title { font-size: 16px; font-weight: 600; color: #fff; }
1354
+ .ps-tryon-drawer-list { display: flex; flex-direction: column; gap: 8px; }
1355
+ .ps-tryon-drawer-empty { text-align: center; padding: 32px 16px; color: #666; font-size: 14px; }
1356
+
1357
+ /* Profile items */
1358
+ .ps-tryon-profile-item {
1359
+ display: flex; align-items: center; gap: 12px; padding: 14px;
1360
+ border: 1px solid #333; border-radius: 12px; cursor: pointer; transition: all 0.2s;
1361
+ }
1362
+ .ps-tryon-profile-item:hover { border-color: #bb945c; }
1363
+ .ps-tryon-profile-avatar {
1364
+ width: 40px; height: 40px; border-radius: 50%;
1365
+ display: flex; align-items: center; justify-content: center;
1366
+ background: rgba(187,148,92,0.1); flex-shrink: 0;
1367
+ }
1368
+ .ps-tryon-profile-avatar svg { stroke: #bb945c; fill: none; }
1369
+ .ps-tryon-profile-info { flex: 1; min-width: 0; }
1370
+ .ps-tryon-profile-name { font-size: 14px; font-weight: 600; color: #fff; }
1371
+ .ps-tryon-profile-detail { font-size: 11px; color: #999; margin-top: 2px; }
1372
+ .ps-tryon-profile-item > svg:last-child { color: #666; flex-shrink: 0; transition: color 0.2s; }
1373
+ .ps-tryon-profile-item:hover > svg:last-child { color: #bb945c; }
1374
+
1375
+ /* History items */
1376
+ .ps-tryon-history-item {
1377
+ display: flex; gap: 10px; padding: 12px;
1378
+ border: 1px solid #333; border-radius: 12px; align-items: center; transition: all 0.2s;
1379
+ }
1380
+ .ps-tryon-history-item:hover { border-color: #bb945c; }
1381
+ .ps-tryon-history-thumb { width: 48px; height: 60px; border-radius: 8px; object-fit: cover; flex-shrink: 0; }
1382
+ .ps-tryon-history-info { flex: 1; min-width: 0; }
1383
+ .ps-tryon-history-product { font-size: 13px; font-weight: 600; color: #fff; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
1384
+ .ps-tryon-history-meta { font-size: 11px; color: #666; margin-top: 3px; }
1385
+ .ps-tryon-history-sizing { display: flex; align-items: center; gap: 6px; margin-top: 6px; }
1386
+ .ps-tryon-history-size-badge {
1387
+ width: 28px; height: 28px; border-radius: 50%;
1388
+ display: flex; align-items: center; justify-content: center;
1389
+ background: linear-gradient(135deg, #bb945c, #d6ba7d);
1390
+ color: #111; font-size: 11px; font-weight: 700; flex-shrink: 0;
1391
+ }
1392
+ .ps-tryon-history-result-img { width: 48px; height: 60px; border-radius: 8px; object-fit: cover; flex-shrink: 0; border: 1.5px solid #bb945c; }
1393
+ .ps-tryon-history-delete {
1394
+ width: 28px; height: 28px; display: flex; align-items: center; justify-content: center;
1395
+ border: none; background: transparent; cursor: pointer; color: #666; border-radius: 6px; transition: all 0.2s; flex-shrink: 0;
1396
+ }
1397
+ .ps-tryon-history-delete:hover { background: rgba(239,68,68,0.1); color: #ef4444; }
1398
+ .ps-tryon-history-delete svg { stroke: currentColor; fill: none; }
1399
+
1400
+ /* Profile detail modal */
1401
+ .ps-tryon-detail-overlay {
1402
+ position: fixed; inset: 0; background: rgba(0,0,0,0.55);
1403
+ display: flex; align-items: center; justify-content: center;
1404
+ z-index: 9999999; padding: 16px; animation: ps-fade-in 0.2s ease;
1405
+ }
1406
+ .ps-tryon-detail-modal {
1407
+ background: #111211; border-radius: 16px; width: 100%; max-width: 440px; max-height: 85vh;
1408
+ overflow-y: auto; box-shadow: 0 32px 64px rgba(0,0,0,0.3); animation: ps-slide-up 0.25s ease;
1409
+ font-family: var(--ps-modal-font, system-ui, sans-serif); color: #fff;
1410
+ }
1411
+ .ps-tryon-detail-header {
1412
+ display: flex; align-items: center; justify-content: space-between;
1413
+ padding: 18px 24px; border-bottom: 1px solid #333;
1414
+ }
1415
+ .ps-tryon-detail-header span { font-size: 15px; font-weight: 600; }
1416
+ .ps-tryon-detail-header button { background: none; border: none; color: #999; cursor: pointer; display: flex; align-items: center; border-radius: 6px; padding: 4px; transition: background 0.15s; }
1417
+ .ps-tryon-detail-header button:hover { background: rgba(255,255,255,0.1); }
1418
+ .ps-tryon-detail-body { padding: 20px 24px; }
1419
+ .ps-tryon-detail-gender { display: flex; align-items: center; gap: 8px; font-size: 14px; font-weight: 600; padding-bottom: 14px; border-bottom: 1px solid #333; margin-bottom: 14px; }
1420
+ .ps-tryon-detail-gender svg { stroke: #bb945c; fill: none; }
1421
+ .ps-tryon-detail-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin-bottom: 16px; }
1422
+ .ps-tryon-detail-cell { background: #1a1b1a; border-radius: 10px; padding: 12px 14px; }
1423
+ .ps-tryon-detail-cell-label { font-size: 11px; color: #999; text-transform: uppercase; letter-spacing: 0.04em; margin-bottom: 4px; }
1424
+ .ps-tryon-detail-cell-value { font-size: 16px; font-weight: 600; color: #fff; }
1425
+ .ps-tryon-detail-date { font-size: 11px; color: #666; text-align: center; margin-top: 8px; }
1426
+ .ps-tryon-detail-delete {
1427
+ width: 100%; display: flex; align-items: center; justify-content: center; gap: 6px;
1428
+ padding: 12px; border: 1px solid #333; border-radius: 10px; background: none;
1429
+ color: #ef4444; font-size: 13px; font-weight: 500; cursor: pointer; transition: all 0.2s;
1430
+ font-family: inherit; margin-top: 16px;
1431
+ }
1432
+ .ps-tryon-detail-delete:hover { background: rgba(239,68,68,0.06); border-color: #ef4444; }
1433
+ .ps-tryon-detail-delete svg { stroke: currentColor; fill: none; }
1434
+
1435
+ /* Mobile responsive */
1436
+ @media (max-width: 720px) {
1437
+ .ps-tryon-result-split { flex-direction: column; }
1438
+ .ps-tryon-result-image-col { flex: none; }
1439
+ .ps-tryon-modal-wide { max-width: 520px; }
1440
+ }
1441
+ @media (max-width: 480px) {
1442
+ .ps-tryon-modal { max-height: 100vh; border-radius: 14px; }
1443
+ .ps-tryon-body { padding: 18px; }
1444
+ .ps-tryon-header { padding: 14px 18px; }
1445
+ .ps-tryon-stepper { padding: 14px 18px 8px; }
1446
+ .ps-tryon-stepper-circle { width: 24px; height: 24px; font-size: 10px; }
1447
+ .ps-tryon-stepper-label { font-size: 9px; }
1448
+ .ps-tryon-features { flex-direction: column; gap: 8px; }
1449
+ .ps-tryon-feature { flex-direction: row; gap: 10px; text-align: left; }
1450
+ .ps-tryon-feature-icon { margin-bottom: 0; }
1451
+ .ps-tryon-input-row { flex-wrap: wrap; }
1452
+ .ps-tryon-input-row label { min-width: 100%; margin-bottom: -4px; }
1453
+ .ps-tryon-drawer { padding: 16px; }
1454
+ .ps-tryon-detail-grid { gap: 8px; }
1455
+ .ps-tryon-detail-cell { padding: 10px 12px; }
1456
+ .ps-tryon-detail-cell-value { font-size: 14px; }
1457
+ .ps-tryon-detail-modal { max-width: 100%; }
1458
+ .ps-tryon-header-icon { width: 30px; height: 30px; border-radius: 8px; }
1459
+ }
1460
+ `;
894
1461
  export {
895
1462
  PrimeStyleTryon
896
1463
  };