@primestyleai/tryon 4.2.1 → 4.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/react/index.js +292 -322
  2. package/package.json +2 -2
@@ -426,7 +426,6 @@ const SIZE_CONVERSIONS = {
426
426
  "48": { US: "XXXL", UK: "20", EU: "48", IT: "52", FR: "48", DE: "48", JP: "19", KR: "105", AU: "20" },
427
427
  "50": { US: "XXXL", UK: "22", EU: "50", IT: "54", FR: "50", DE: "50", JP: "21", KR: "110", AU: "22" }
428
428
  };
429
- const STEP_LABELS = ["", "Welcome", "Size", "Your Fit", "Try On"];
430
429
  const TOTAL_STEPS = 4;
431
430
  function detectLocale() {
432
431
  if (typeof window === "undefined") return "US";
@@ -1162,31 +1161,7 @@ function PrimeStyleTryonInner({
1162
1161
  const cssVars = Object.fromEntries(Object.entries(rootVars).filter(([, v]) => v !== void 0));
1163
1162
  function Stepper() {
1164
1163
  if (view === "error" || view === "idle") return null;
1165
- 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: [
1166
- i > 1 && /* @__PURE__ */ jsx("div", { className: `ps-tryon-stepper-line${i <= stepIndex ? " ps-done" : ""}` }),
1167
- /* @__PURE__ */ jsxs("div", { className: `ps-tryon-stepper-step${i < stepIndex ? " ps-done" : i === stepIndex ? " ps-active" : ""}`, children: [
1168
- /* @__PURE__ */ jsx("div", { className: "ps-tryon-stepper-circle", children: i < stepIndex ? /* @__PURE__ */ jsx(CheckIcon, {}) : i }),
1169
- /* @__PURE__ */ jsx("div", { className: "ps-tryon-stepper-label", children: t(STEP_LABELS[i]) })
1170
- ] })
1171
- ] }, i)) }) });
1172
- }
1173
- function InputRow({ label, fieldKey, placeholder, type = "text", unit }) {
1174
- return /* @__PURE__ */ jsxs("div", { className: "ps-tryon-input-row", children: [
1175
- /* @__PURE__ */ jsx("label", { children: label }),
1176
- /* @__PURE__ */ jsx(
1177
- "input",
1178
- {
1179
- type,
1180
- placeholder,
1181
- defaultValue: formRef.current[fieldKey] || "",
1182
- onInput: (e) => updateField(fieldKey, e.target.value)
1183
- }
1184
- ),
1185
- unit && /* @__PURE__ */ jsx("span", { className: "ps-tryon-input-unit", children: unit })
1186
- ] });
1187
- }
1188
- function UnitToggle({ options, value, onChange }) {
1189
- 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)) });
1164
+ return /* @__PURE__ */ jsx("div", { className: "ps-tryon-dots", children: Array.from({ length: TOTAL_STEPS }, (_, i) => i + 1).map((i) => /* @__PURE__ */ jsx("div", { className: `ps-tryon-dot${i < stepIndex ? " ps-done" : i === stepIndex ? " ps-active" : ""}` }, i)) });
1190
1165
  }
1191
1166
  function WelcomeView() {
1192
1167
  return /* @__PURE__ */ jsxs("div", { className: "ps-tryon-welcome", children: [
@@ -1264,233 +1239,152 @@ function PrimeStyleTryonInner({
1264
1239
  ) });
1265
1240
  }
1266
1241
  function SizingChoiceView() {
1242
+ const [mode, setMode] = useState("exact");
1243
+ const [saveToggle, setSaveToggle] = useState(false);
1244
+ const [saveFormName, setSaveFormName] = useState("");
1245
+ const isCm = sizingUnit === "cm";
1267
1246
  const sgAvailable = sizeGuide?.found === true;
1268
1247
  const sgChecked = !sizeGuideFetching && sizeGuide !== null;
1269
- if (sizeGuideFetching) {
1270
- return /* @__PURE__ */ jsx("div", { className: "ps-tryon-sizing-choice", children: /* @__PURE__ */ jsxs("div", { className: "ps-tryon-sg-checking", children: [
1271
- /* @__PURE__ */ jsx("div", { className: "ps-tryon-sg-checking-icon", children: /* @__PURE__ */ jsx(RulerIcon, { size: 32 }) }),
1272
- /* @__PURE__ */ jsx("div", { className: "ps-tryon-sg-checking-bar-wrap", children: /* @__PURE__ */ jsx("div", { className: "ps-tryon-sg-checking-bar" }) }),
1273
- /* @__PURE__ */ jsx("h3", { className: "ps-tryon-section-title", children: t("Checking size guide...") }),
1274
- /* @__PURE__ */ jsx("p", { className: "ps-tryon-sg-checking-sub", children: t("Looking for size chart data for this product") })
1275
- ] }) });
1276
- }
1277
- return /* @__PURE__ */ jsxs("div", { className: "ps-tryon-sizing-choice", children: [
1278
- /* @__PURE__ */ jsx("h3", { className: "ps-tryon-section-title", children: t("How would you like to find your size?") }),
1279
- sgChecked && !sgAvailable && /* @__PURE__ */ jsxs("div", { className: "ps-tryon-sg-notice", children: [
1280
- t("This product doesn't have a size guide you can still see how it looks on you!"),
1281
- /* @__PURE__ */ jsxs("button", { className: "ps-tryon-sg-notice-cta", onClick: () => {
1282
- setSizingMethod(null);
1283
- setView("upload");
1284
- }, children: [
1285
- t("Try It On"),
1286
- " ",
1287
- /* @__PURE__ */ jsx(ArrowRightIcon, {})
1288
- ] })
1248
+ const exactAvailable = sgChecked ? sgAvailable : true;
1249
+ const handleSubmit = async () => {
1250
+ if (saveToggle && saveFormName.trim()) {
1251
+ saveProfile(saveFormName.trim());
1252
+ }
1253
+ setSizingMethod(mode);
1254
+ setSizingLoading(true);
1255
+ setView("size-result");
1256
+ await submitSizing();
1257
+ };
1258
+ const renderQuickFields = () => /* @__PURE__ */ jsxs(Fragment, { children: [
1259
+ /* @__PURE__ */ jsxs("div", { className: "ps-tryon-sf-row", children: [
1260
+ /* @__PURE__ */ jsx("label", { className: "ps-tryon-sf-label", children: t("HEIGHT") }),
1261
+ /* @__PURE__ */ jsx("div", { className: "ps-tryon-sf-input-wrap", children: heightUnit === "ft" ? /* @__PURE__ */ jsxs("div", { className: "ps-tryon-sf-ft-group", children: [
1262
+ /* @__PURE__ */ jsx("input", { type: "number", placeholder: "5", className: "ps-tryon-sf-input", defaultValue: formRef.current.heightFeet || "", onInput: (e) => updateField("heightFeet", e.target.value) }),
1263
+ /* @__PURE__ */ jsx("span", { className: "ps-tryon-sf-unit", children: t("feet") }),
1264
+ /* @__PURE__ */ jsx("input", { type: "number", placeholder: "10", className: "ps-tryon-sf-input", defaultValue: formRef.current.heightInches || "", onInput: (e) => updateField("heightInches", e.target.value) }),
1265
+ /* @__PURE__ */ jsx("span", { className: "ps-tryon-sf-unit", children: t("inches") })
1266
+ ] }) : /* @__PURE__ */ jsxs("div", { className: "ps-tryon-sf-inline", children: [
1267
+ /* @__PURE__ */ jsx("input", { type: "number", placeholder: "175", className: "ps-tryon-sf-input", defaultValue: formRef.current.height || "", onInput: (e) => updateField("height", e.target.value) }),
1268
+ /* @__PURE__ */ jsx("span", { className: "ps-tryon-sf-unit", children: t("cm") })
1269
+ ] }) })
1289
1270
  ] }),
1290
- /* @__PURE__ */ jsxs("div", { className: "ps-tryon-choice-cards", children: [
1291
- /* @__PURE__ */ jsxs("button", { className: "ps-tryon-choice-card", onClick: () => {
1292
- setSizingMethod("exact");
1293
- setView("sizing-form");
1294
- }, children: [
1295
- /* @__PURE__ */ jsx("div", { className: "ps-tryon-choice-icon", children: /* @__PURE__ */ jsx(RulerIcon, { size: 24 }) }),
1296
- /* @__PURE__ */ jsxs("div", { className: "ps-tryon-choice-info", children: [
1297
- /* @__PURE__ */ jsx("div", { className: "ps-tryon-choice-title", children: t("Enter my measurements") }),
1298
- /* @__PURE__ */ jsx("div", { className: "ps-tryon-choice-desc", children: sizeGuide?.requiredFields?.length ? sizeGuide.requiredFields.filter((f) => f.required).slice(0, 3).map((f) => t(f.label)).join(", ") + (sizeGuide.requiredFields.length > 3 ? ` ${t("& more")}` : "") : t("Chest, waist, hips, shoes & more") })
1299
- ] }),
1300
- /* @__PURE__ */ jsx("span", { className: "ps-tryon-choice-badge", children: t("Best accuracy") })
1301
- ] }),
1302
- /* @__PURE__ */ jsxs("button", { className: "ps-tryon-choice-card", onClick: () => {
1303
- setSizingMethod("quick");
1304
- setView("sizing-form");
1305
- }, children: [
1306
- /* @__PURE__ */ jsx("div", { className: "ps-tryon-choice-icon", children: /* @__PURE__ */ jsx(SparkleIcon, { size: 24 }) }),
1307
- /* @__PURE__ */ jsxs("div", { className: "ps-tryon-choice-info", children: [
1308
- /* @__PURE__ */ jsx("div", { className: "ps-tryon-choice-title", children: t("Just height & weight") }),
1309
- /* @__PURE__ */ jsx("div", { className: "ps-tryon-choice-desc", children: t("Quick estimate in seconds") })
1310
- ] })
1311
- ] }),
1312
- /* @__PURE__ */ jsxs("button", { className: "ps-tryon-choice-card", onClick: () => {
1313
- setSizingMethod(null);
1314
- setView("upload");
1315
- }, children: [
1316
- /* @__PURE__ */ jsx("div", { className: "ps-tryon-choice-icon", children: /* @__PURE__ */ jsx(CameraIcon, { size: 24 }) }),
1317
- /* @__PURE__ */ jsxs("div", { className: "ps-tryon-choice-info", children: [
1318
- /* @__PURE__ */ jsx("div", { className: "ps-tryon-choice-title", children: t("Skip, just try it on") }),
1319
- /* @__PURE__ */ jsx("div", { className: "ps-tryon-choice-desc", children: t("Upload a photo to see how it looks") })
1320
- ] })
1271
+ /* @__PURE__ */ jsxs("div", { className: "ps-tryon-sf-row", children: [
1272
+ /* @__PURE__ */ jsx("label", { className: "ps-tryon-sf-label", children: t("WEIGHT") }),
1273
+ /* @__PURE__ */ jsxs("div", { className: "ps-tryon-sf-inline", children: [
1274
+ /* @__PURE__ */ jsx("input", { type: "number", placeholder: weightUnit === "lbs" ? "170" : "75", className: "ps-tryon-sf-input", defaultValue: formRef.current.weight || "", onInput: (e) => updateField("weight", e.target.value) }),
1275
+ /* @__PURE__ */ jsx("span", { className: "ps-tryon-sf-unit", children: weightUnit })
1321
1276
  ] })
1322
1277
  ] })
1323
1278
  ] });
1324
- }
1325
- function SizingFormView() {
1326
- const isFemale = formGender === "female";
1327
- const isCm = sizingUnit === "cm";
1328
- const [saveToggle, setSaveToggle] = useState(false);
1329
- const [saveFormName, setSaveFormName] = useState("");
1330
- return /* @__PURE__ */ jsxs("div", { className: "ps-tryon-sizing-form", children: [
1331
- /* @__PURE__ */ jsxs("button", { className: "ps-tryon-back", onClick: () => setView("sizing-choice"), children: [
1332
- /* @__PURE__ */ jsx(ArrowLeftIcon, {}),
1333
- " ",
1334
- t("Back")
1335
- ] }),
1336
- sizingMethod === "exact" && profiles.length > 0 && /* @__PURE__ */ jsx("div", { className: "ps-tryon-profile-bar", children: /* @__PURE__ */ jsxs("select", { className: "ps-tryon-profile-select", value: activeProfileId || "", onChange: (e) => {
1337
- if (e.target.value) applyProfile(e.target.value);
1338
- }, children: [
1339
- /* @__PURE__ */ jsx("option", { value: "", children: t("Auto-fill from saved profile...") }),
1340
- profiles.map((p) => /* @__PURE__ */ jsxs("option", { value: p.id, children: [
1341
- p.name,
1342
- " (",
1343
- p.gender === "female" ? t("Women's") : t("Men's"),
1344
- ")"
1345
- ] }, p.id))
1346
- ] }) }),
1347
- sizingMethod === "exact" && /* @__PURE__ */ jsxs("div", { className: "ps-tryon-unit-tabs", children: [
1348
- /* @__PURE__ */ jsx("button", { className: `ps-tryon-unit-tab${isCm ? " ps-active" : ""}`, onClick: () => {
1349
- setSizingUnit("cm");
1350
- setHeightUnit("cm");
1351
- setWeightUnit("kg");
1352
- }, children: "CM" }),
1353
- /* @__PURE__ */ jsx("button", { className: `ps-tryon-unit-tab${!isCm ? " ps-active" : ""}`, onClick: () => {
1354
- setSizingUnit("in");
1355
- setHeightUnit("ft");
1356
- setWeightUnit("lbs");
1357
- }, children: "Inches" })
1358
- ] }),
1359
- sizingMethod === "exact" ? /* @__PURE__ */ jsx(Fragment, { children: (() => {
1360
- const reqFields = dynamicFields.filter((f) => f.required);
1361
- const optFields = dynamicFields.filter((f) => !f.required);
1362
- const isShoeProduct = reqFields.some((f) => f.category === "shoe");
1363
- const isClothingProduct = reqFields.some((f) => f.category === "body");
1364
- const renderField = (field) => {
1365
- if (["shoeEU", "shoeUS", "shoeUK"].includes(field.key)) {
1366
- const regionField = shoeField;
1367
- const key = regionField.key;
1368
- const showOriginal = field.key !== key;
1369
- return /* @__PURE__ */ jsxs("span", { children: [
1370
- /* @__PURE__ */ jsx(InputRow, { label: `${regionField.label}${field.required ? " *" : ""}`, fieldKey: key, placeholder: regionField.ph }),
1371
- showOriginal && /* @__PURE__ */ jsx(InputRow, { label: t(field.label), fieldKey: field.key, placeholder: field.placeholder })
1372
- ] }, field.key);
1373
- }
1374
- const phNum = parseFloat(field.placeholder?.replace(/[^0-9.]/g, "") || "");
1375
- const phIn = !isNaN(phNum) && phNum > 0 && field.unit === "cm" ? String(Math.round(phNum / 2.54)) : "";
1376
- const placeholder = isCm ? field.placeholder || "" : phIn ? `e.g. ${phIn}` : field.placeholder || "";
1377
- return /* @__PURE__ */ jsx(
1378
- InputRow,
1379
- {
1380
- label: `${t(field.label)}${field.required ? " *" : ""}`,
1381
- fieldKey: field.key,
1382
- placeholder,
1383
- type: "number",
1384
- unit: field.unit === "cm" ? sizingUnit : void 0
1385
- },
1386
- field.key
1387
- );
1388
- };
1389
- const profileExtras = [];
1390
- if (isShoeProduct && !dynamicFields.some((f) => f.category === "body")) {
1391
- const bodyFields = isFemale ? FALLBACK_FIELDS_FEMALE : FALLBACK_FIELDS_MALE;
1392
- for (const f of bodyFields) {
1393
- if (!dynamicFields.some((d) => d.key === f.key)) {
1394
- profileExtras.push({ ...f, required: false });
1395
- }
1396
- }
1397
- }
1398
- if (isClothingProduct && !dynamicFields.some((f) => f.category === "shoe")) {
1399
- profileExtras.push({ key: "footLengthCm", label: "Foot length", required: false, unit: "cm", placeholder: "e.g. 27", category: "shoe" });
1400
- profileExtras.push({ key: shoeField.key, label: shoeField.label, required: false, unit: "size", placeholder: shoeField.ph, category: "shoe" });
1279
+ const renderExactFields = () => {
1280
+ const reqFields = dynamicFields.filter((f) => f.required);
1281
+ const optFields = dynamicFields.filter((f) => !f.required);
1282
+ const renderField = (field) => {
1283
+ if (["shoeEU", "shoeUS", "shoeUK"].includes(field.key)) {
1284
+ const regionField = shoeField;
1285
+ return /* @__PURE__ */ jsxs("div", { className: "ps-tryon-sf-row", children: [
1286
+ /* @__PURE__ */ jsxs("label", { className: "ps-tryon-sf-label", children: [
1287
+ regionField.label.toUpperCase(),
1288
+ field.required ? " *" : ""
1289
+ ] }),
1290
+ /* @__PURE__ */ jsx("div", { className: "ps-tryon-sf-inline", children: /* @__PURE__ */ jsx("input", { type: "text", placeholder: regionField.ph, className: "ps-tryon-sf-input", defaultValue: formRef.current[regionField.key] || "", onInput: (e) => updateField(regionField.key, e.target.value) }) })
1291
+ ] }, field.key);
1401
1292
  }
1402
- const allOptFields = [...optFields, ...profileExtras];
1403
- return /* @__PURE__ */ jsxs(Fragment, { children: [
1404
- reqFields.length > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
1405
- /* @__PURE__ */ jsx("div", { className: "ps-tryon-section-label", children: t("Required for this product") }),
1406
- reqFields.map(renderField)
1293
+ const phNum = parseFloat(field.placeholder?.replace(/[^0-9.]/g, "") || "");
1294
+ const phIn = !isNaN(phNum) && phNum > 0 && field.unit === "cm" ? String(Math.round(phNum / 2.54)) : "";
1295
+ const placeholder = isCm ? field.placeholder?.replace("e.g. ", "") || "" : phIn || field.placeholder?.replace("e.g. ", "") || "";
1296
+ return /* @__PURE__ */ jsxs("div", { className: "ps-tryon-sf-row", children: [
1297
+ /* @__PURE__ */ jsxs("label", { className: "ps-tryon-sf-label", children: [
1298
+ t(field.label).toUpperCase(),
1299
+ field.required ? " *" : ""
1407
1300
  ] }),
1408
- isFemale && /* @__PURE__ */ jsxs("div", { className: "ps-tryon-input-row", children: [
1409
- /* @__PURE__ */ jsx("label", { children: t("Fit type") }),
1410
- /* @__PURE__ */ jsx("div", { className: "ps-tryon-unit-toggle", children: ["petite", "standard", "tall", "plus"].map((fp) => /* @__PURE__ */ jsx(
1411
- "button",
1412
- {
1413
- className: `ps-tryon-unit-btn${(formRef.current.fitPreference || "standard") === fp ? " ps-active" : ""}`,
1414
- onClick: (e) => {
1415
- updateField("fitPreference", fp);
1416
- const btns = e.target.parentElement.querySelectorAll(".ps-tryon-unit-btn");
1417
- btns.forEach((b) => b.classList.toggle("ps-active", b.dataset.fp === fp));
1418
- },
1419
- "data-fp": fp,
1420
- children: t(fp.charAt(0).toUpperCase() + fp.slice(1))
1421
- },
1422
- fp
1423
- )) })
1424
- ] }),
1425
- allOptFields.length > 0 && /* @__PURE__ */ jsxs("div", { className: "ps-tryon-optional-section", children: [
1426
- /* @__PURE__ */ jsxs("button", { className: "ps-tryon-optional-toggle", onClick: (e) => {
1427
- const wrap = e.target.closest(".ps-tryon-optional-section").querySelector(".ps-tryon-optional-fields");
1428
- const arrow = e.target.closest(".ps-tryon-optional-toggle").querySelector(".ps-tryon-chevron");
1429
- if (wrap) {
1430
- const open = wrap.style.display !== "none";
1431
- wrap.style.display = open ? "none" : "flex";
1432
- if (arrow) arrow.style.transform = open ? "rotate(0deg)" : "rotate(180deg)";
1433
- }
1434
- }, children: [
1435
- /* @__PURE__ */ jsx("span", { children: t("Optional — improve accuracy & save to profile") }),
1436
- /* @__PURE__ */ jsx("span", { className: "ps-tryon-chevron", children: "▾" })
1437
- ] }),
1438
- /* @__PURE__ */ jsx("div", { className: "ps-tryon-optional-fields", style: { display: "none" }, children: allOptFields.map(renderField) })
1301
+ /* @__PURE__ */ jsxs("div", { className: "ps-tryon-sf-inline", children: [
1302
+ /* @__PURE__ */ jsx("input", { type: "number", placeholder, className: "ps-tryon-sf-input", defaultValue: formRef.current[field.key] || "", onInput: (e) => updateField(field.key, e.target.value) }),
1303
+ field.unit === "cm" && /* @__PURE__ */ jsx("span", { className: "ps-tryon-sf-unit", children: sizingUnit })
1439
1304
  ] })
1440
- ] });
1441
- })() }) : /* @__PURE__ */ jsxs(Fragment, { children: [
1442
- /* @__PURE__ */ jsxs("div", { className: "ps-tryon-input-row", children: [
1443
- /* @__PURE__ */ jsxs("label", { children: [
1444
- t("Height"),
1445
- " *"
1446
- ] }),
1447
- heightUnit === "ft" ? /* @__PURE__ */ jsxs("div", { className: "ps-tryon-height-ft", children: [
1448
- /* @__PURE__ */ jsx("input", { type: "number", placeholder: "5", defaultValue: formRef.current.heightFeet || "", onInput: (e) => updateField("heightFeet", e.target.value) }),
1449
- /* @__PURE__ */ jsx("span", { children: t("ft") }),
1450
- /* @__PURE__ */ jsx("input", { type: "number", placeholder: "4", defaultValue: formRef.current.heightInches || "", onInput: (e) => updateField("heightInches", e.target.value) }),
1451
- /* @__PURE__ */ jsx("span", { children: t("in") })
1452
- ] }) : /* @__PURE__ */ jsx("input", { type: "number", placeholder: "e.g. 175", defaultValue: formRef.current.height || "", onInput: (e) => updateField("height", e.target.value) }),
1453
- /* @__PURE__ */ jsx(UnitToggle, { options: [{ label: t("cm"), value: "cm" }, { label: t("ft"), value: "ft" }], value: heightUnit, onChange: setHeightUnit })
1305
+ ] }, field.key);
1306
+ };
1307
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
1308
+ reqFields.map(renderField),
1309
+ optFields.length > 0 && /* @__PURE__ */ jsxs("details", { className: "ps-tryon-sf-optional", children: [
1310
+ /* @__PURE__ */ jsx("summary", { className: "ps-tryon-sf-optional-toggle", children: t("Optional fields") }),
1311
+ /* @__PURE__ */ jsx("div", { className: "ps-tryon-sf-optional-fields", children: optFields.map(renderField) })
1312
+ ] })
1313
+ ] });
1314
+ };
1315
+ return /* @__PURE__ */ jsxs("div", { className: "ps-tryon-sizing-split", children: [
1316
+ /* @__PURE__ */ jsx("div", { className: "ps-tryon-sizing-img-col", children: /* @__PURE__ */ jsx("img", { src: productImage, alt: productTitle, className: "ps-tryon-sizing-product-img" }) }),
1317
+ /* @__PURE__ */ jsxs("div", { className: "ps-tryon-sizing-form-col", children: [
1318
+ /* @__PURE__ */ jsx("h3", { className: "ps-tryon-sf-title", children: t("Let's find your best fit") }),
1319
+ /* @__PURE__ */ jsxs("div", { className: "ps-tryon-sf-unit-tabs", children: [
1320
+ /* @__PURE__ */ jsx(
1321
+ "button",
1322
+ {
1323
+ className: `ps-tryon-sf-unit-tab${(isCm || heightUnit === "cm") && mode !== "exact" ? " ps-active" : ""} ${mode === "exact" && isCm ? " ps-active" : ""}`,
1324
+ onClick: () => {
1325
+ setSizingUnit("cm");
1326
+ setHeightUnit("cm");
1327
+ setWeightUnit("kg");
1328
+ },
1329
+ children: t("Metric")
1330
+ }
1331
+ ),
1332
+ /* @__PURE__ */ jsx(
1333
+ "button",
1334
+ {
1335
+ className: `ps-tryon-sf-unit-tab${(!isCm || heightUnit === "ft") && mode !== "exact" ? " ps-active" : ""} ${mode === "exact" && !isCm ? " ps-active" : ""}`,
1336
+ onClick: () => {
1337
+ setSizingUnit("in");
1338
+ setHeightUnit("ft");
1339
+ setWeightUnit("lbs");
1340
+ },
1341
+ children: t("Imperial")
1342
+ }
1343
+ )
1454
1344
  ] }),
1455
- /* @__PURE__ */ jsxs("div", { className: "ps-tryon-input-row", children: [
1456
- /* @__PURE__ */ jsxs("label", { children: [
1457
- t("Weight"),
1458
- " *"
1345
+ mode === "exact" && profiles.length > 0 && /* @__PURE__ */ jsx("div", { className: "ps-tryon-sf-profile-bar", children: /* @__PURE__ */ jsxs("select", { className: "ps-tryon-sf-profile-select", value: activeProfileId || "", onChange: (e) => {
1346
+ if (e.target.value) applyProfile(e.target.value);
1347
+ }, children: [
1348
+ /* @__PURE__ */ jsx("option", { value: "", children: t("Load saved profile...") }),
1349
+ profiles.map((p) => /* @__PURE__ */ jsx("option", { value: p.id, children: p.name }, p.id))
1350
+ ] }) }),
1351
+ /* @__PURE__ */ jsx("div", { className: "ps-tryon-sf-fields", children: mode === "quick" ? renderQuickFields() : renderExactFields() }),
1352
+ /* @__PURE__ */ jsx("div", { className: "ps-tryon-sf-switch", children: mode === "quick" && exactAvailable ? /* @__PURE__ */ jsxs("button", { className: "ps-tryon-sf-switch-btn", onClick: () => {
1353
+ setMode("exact");
1354
+ setSizingMethod("exact");
1355
+ }, children: [
1356
+ t("I know my measurements"),
1357
+ " ",
1358
+ /* @__PURE__ */ jsx(ArrowRightIcon, {})
1359
+ ] }) : mode === "exact" ? /* @__PURE__ */ jsx("button", { className: "ps-tryon-sf-switch-btn", onClick: () => {
1360
+ setMode("quick");
1361
+ setSizingMethod("quick");
1362
+ }, children: t("Not sure? Use height & weight instead") }) : null }),
1363
+ /* @__PURE__ */ jsxs("div", { className: "ps-tryon-sf-save", children: [
1364
+ /* @__PURE__ */ jsxs("label", { className: "ps-tryon-sf-save-check", children: [
1365
+ /* @__PURE__ */ jsx("input", { type: "checkbox", checked: saveToggle, onChange: (e) => setSaveToggle(e.target.checked) }),
1366
+ /* @__PURE__ */ jsx("span", { children: t("Save as profile") })
1459
1367
  ] }),
1460
- /* @__PURE__ */ jsx("input", { type: "number", placeholder: weightUnit === "lbs" ? "e.g. 170" : "e.g. 75", defaultValue: formRef.current.weight || "", onInput: (e) => updateField("weight", e.target.value) }),
1461
- /* @__PURE__ */ jsx(UnitToggle, { options: [{ label: t("kg"), value: "kg" }, { label: t("lbs"), value: "lbs" }], value: weightUnit, onChange: setWeightUnit })
1462
- ] })
1463
- ] }),
1464
- /* @__PURE__ */ jsx("p", { className: "ps-tryon-disclaimer", children: t("Fill in what you know — more measurements = better accuracy.") }),
1465
- /* @__PURE__ */ jsxs("div", { className: "ps-tryon-form-save-toggle", children: [
1466
- /* @__PURE__ */ jsxs("label", { className: "ps-tryon-form-save-check", children: [
1467
- /* @__PURE__ */ jsx("input", { type: "checkbox", checked: saveToggle, onChange: (e) => setSaveToggle(e.target.checked) }),
1468
- /* @__PURE__ */ jsx("span", { children: t("Save as profile") })
1368
+ saveToggle && /* @__PURE__ */ jsx(
1369
+ "input",
1370
+ {
1371
+ type: "text",
1372
+ className: "ps-tryon-sf-save-name",
1373
+ placeholder: t("Profile name (e.g. John, Sarah)"),
1374
+ value: saveFormName,
1375
+ onChange: (e) => setSaveFormName(e.target.value)
1376
+ }
1377
+ )
1469
1378
  ] }),
1470
- saveToggle && /* @__PURE__ */ jsx(
1471
- "input",
1472
- {
1473
- type: "text",
1474
- className: "ps-tryon-form-save-name",
1475
- placeholder: t("Profile name (e.g. John, Sarah)"),
1476
- value: saveFormName,
1477
- onChange: (e) => setSaveFormName(e.target.value)
1478
- }
1479
- )
1480
- ] }),
1481
- /* @__PURE__ */ jsxs("button", { className: "ps-tryon-submit", onClick: async () => {
1482
- if (saveToggle && saveFormName.trim()) {
1483
- saveProfile(saveFormName.trim());
1484
- }
1485
- setSizingLoading(true);
1486
- setView("size-result");
1487
- await submitSizing();
1488
- }, children: [
1489
- t("Get My Size"),
1490
- " ",
1491
- /* @__PURE__ */ jsx(ArrowRightIcon, {})
1379
+ /* @__PURE__ */ jsx("button", { className: "ps-tryon-sf-next", onClick: handleSubmit, children: t("Next") })
1492
1380
  ] })
1493
- ] }, `form-${formGender}-${sizingUnit}-${heightUnit}-${sizingCountry}-${formKey}`);
1381
+ ] });
1382
+ }
1383
+ function SizingFormView() {
1384
+ useEffect(() => {
1385
+ setView("sizing-choice");
1386
+ }, []);
1387
+ return null;
1494
1388
  }
1495
1389
  function SizeResultView() {
1496
1390
  const unitLbl = sizingUnit === "cm" ? t("cm") : t("in");
@@ -1871,7 +1765,7 @@ function PrimeStyleTryonInner({
1871
1765
  ] }),
1872
1766
  view !== "idle" && /* @__PURE__ */ jsx("div", { className: cx("ps-tryon-overlay", cn.overlay), onClick: (e) => {
1873
1767
  if (e.target === e.currentTarget) handleClose();
1874
- }, children: /* @__PURE__ */ jsxs("div", { className: cx(`ps-tryon-modal${view === "result" && resultImageUrl && sizingResult || view === "size-result" ? " ps-tryon-modal-wide" : ""}`, cn.modal), onClick: (e) => e.stopPropagation(), children: [
1768
+ }, children: /* @__PURE__ */ jsxs("div", { className: cx(`ps-tryon-modal${view === "result" && resultImageUrl && sizingResult || view === "size-result" || view === "sizing-choice" ? " ps-tryon-modal-wide" : ""}`, cn.modal), onClick: (e) => e.stopPropagation(), children: [
1875
1769
  /* @__PURE__ */ jsxs("div", { className: cx("ps-tryon-header", cn.header), children: [
1876
1770
  /* @__PURE__ */ jsx("span", { className: cx("ps-tryon-title", cn.title), children: t("Virtual Try-On") }),
1877
1771
  /* @__PURE__ */ jsxs("div", { className: "ps-tryon-header-actions", children: [
@@ -1927,13 +1821,13 @@ const STYLES = `
1927
1821
  .ps-tryon-modal {
1928
1822
  background: var(--ps-modal-bg, #111211); color: var(--ps-modal-color, #fff);
1929
1823
  border-radius: var(--ps-modal-radius, 0.83vw); width: var(--ps-modal-width, 100%);
1930
- max-width: var(--ps-modal-max-width, 32vw); max-height: 92vh; overflow-y: auto;
1824
+ max-width: var(--ps-modal-max-width, 36vw); max-height: 92vh; overflow-y: auto;
1931
1825
  font-family: var(--ps-modal-font, system-ui, -apple-system, sans-serif);
1932
1826
  box-shadow: 0 1.3vw 2.6vw rgba(0,0,0,0.4); animation: ps-slide-up 0.3s ease;
1933
1827
  scrollbar-width: thin; scrollbar-color: #333 transparent;
1934
1828
  flex-shrink: 0;
1935
1829
  }
1936
- .ps-tryon-modal-wide { max-width: 48vw; }
1830
+ .ps-tryon-modal-wide { max-width: 52vw; }
1937
1831
  .ps-tryon-modal:has(.ps-tryon-drawer-open) { overflow: hidden; }
1938
1832
  @keyframes ps-slide-up { from { transform: translateY(1.04vw) scale(0.97); opacity: 0; } to { transform: translateY(0) scale(1); opacity: 1; } }
1939
1833
 
@@ -2020,25 +1914,14 @@ const STYLES = `
2020
1914
  .ps-tryon-lang-check { color: #bb945c; display: flex; align-items: center; }
2021
1915
 
2022
1916
  /* Stepper */
2023
- .ps-tryon-stepper { padding: 1.04vw 1.25vw 0.63vw; }
2024
- .ps-tryon-stepper-track { display: flex; align-items: flex-start; }
2025
- .ps-tryon-stepper-fragment { display: flex; align-items: flex-start; flex: 1; }
2026
- .ps-tryon-stepper-fragment:first-child { flex: 0 0 auto; }
2027
- .ps-tryon-stepper-line { flex: 1; height: 2px; background: #333; margin-top: 0.73vw; transition: background 0.4s; }
2028
- .ps-tryon-stepper-line.ps-done { background: #bb945c; }
2029
- .ps-tryon-stepper-step { display: flex; flex-direction: column; align-items: center; }
2030
- .ps-tryon-stepper-circle {
2031
- width: 1.46vw; height: 1.46vw; border-radius: 50%;
2032
- display: flex; align-items: center; justify-content: center;
2033
- border: 2px solid #333; font-size: 0.63vw; font-weight: 600; color: #666;
2034
- transition: all 0.3s;
2035
- }
2036
- .ps-tryon-stepper-step.ps-done .ps-tryon-stepper-circle { background: #bb945c; border-color: #bb945c; color: #111; }
2037
- .ps-tryon-stepper-step.ps-done .ps-tryon-stepper-circle svg { stroke: #111; }
2038
- .ps-tryon-stepper-step.ps-active .ps-tryon-stepper-circle { border-color: #bb945c; color: #bb945c; box-shadow: 0 0 0 0.21vw rgba(187,148,92,0.15); }
2039
- .ps-tryon-stepper-label { font-size: 0.52vw; margin-top: 0.26vw; color: #666; font-weight: 500; text-align: center; white-space: nowrap; }
2040
- .ps-tryon-stepper-step.ps-done .ps-tryon-stepper-label { color: #bb945c; }
2041
- .ps-tryon-stepper-step.ps-active .ps-tryon-stepper-label { color: #bb945c; font-weight: 700; }
1917
+ /* Dots progress */
1918
+ .ps-tryon-dots { display: flex; align-items: center; gap: 0.42vw; padding: 0.83vw 1.25vw; }
1919
+ .ps-tryon-dot {
1920
+ width: 0.47vw; height: 0.47vw; border-radius: 50%; background: #333;
1921
+ transition: all 0.3s ease;
1922
+ }
1923
+ .ps-tryon-dot.ps-done { background: #666; }
1924
+ .ps-tryon-dot.ps-active { background: #fff; width: 0.57vw; height: 0.57vw; }
2042
1925
 
2043
1926
  /* Body */
2044
1927
  .ps-tryon-body { padding: 1.25vw; min-height: 15.6vw; }
@@ -2046,31 +1929,31 @@ const STYLES = `
2046
1929
  .ps-tryon-view-enter { animation: ps-fade-up 0.35s ease both; }
2047
1930
 
2048
1931
  /* Welcome */
2049
- .ps-tryon-welcome { text-align: center; padding: clamp(8px, 0.5vw, 12px) 0; }
2050
- .ps-tryon-welcome-hero { margin-bottom: clamp(16px, 1.3vw, 24px); }
1932
+ .ps-tryon-welcome { text-align: center; padding: 0.5vw 0; }
1933
+ .ps-tryon-welcome-hero { margin-bottom: 1.3vw; }
2051
1934
  .ps-tryon-welcome-img-wrap { position: relative; display: inline-block; }
2052
- .ps-tryon-welcome-product { width: clamp(100px, 9vw, 160px); height: clamp(120px, 10.5vw, 190px); object-fit: cover; border-radius: clamp(10px, 0.9vw, 16px); border: 2px solid #333; box-shadow: 0 8px 30px rgba(0,0,0,0.4); }
2053
- .ps-tryon-welcome-sparkle { position: absolute; top: clamp(-6px, -0.5vw, -4px); right: clamp(-6px, -0.5vw, -4px); width: clamp(22px, 1.8vw, 30px); height: clamp(22px, 1.8vw, 30px); background: #bb945c; border-radius: 50%; display: flex; align-items: center; justify-content: center; animation: ps-float 3s ease-in-out infinite; }
2054
- .ps-tryon-welcome-sparkle svg { stroke: #111; width: clamp(10px, 0.9vw, 14px); height: clamp(10px, 0.9vw, 14px); }
1935
+ .ps-tryon-welcome-product { width: 9vw; height: 10.5vw; object-fit: cover; border-radius: 0.9vw; border: 2px solid #333; box-shadow: 0 8px 30px rgba(0,0,0,0.4); }
1936
+ .ps-tryon-welcome-sparkle { position: absolute; top: -0.5vw; right: -0.5vw; width: 1.8vw; height: 1.8vw; background: #bb945c; border-radius: 50%; display: flex; align-items: center; justify-content: center; animation: ps-float 3s ease-in-out infinite; }
1937
+ .ps-tryon-welcome-sparkle svg { stroke: #111; width: 0.9vw; height: 0.9vw; }
2055
1938
  @keyframes ps-float { 0%,100% { transform: translateY(0); } 50% { transform: translateY(-4px); } }
2056
- .ps-tryon-welcome-title { font-size: clamp(18px, 1.4vw, 24px); font-weight: 700; color: #fff; margin: clamp(12px, 1vw, 18px) 0 clamp(4px, 0.3vw, 6px); letter-spacing: -0.01em; }
2057
- .ps-tryon-welcome-sub { font-size: clamp(13px, 0.9vw, 16px); color: #999; margin: 0; }
2058
- .ps-tryon-features { display: flex; gap: clamp(8px, 0.7vw, 12px); margin: clamp(16px, 1.3vw, 24px) 0; }
2059
- .ps-tryon-feature { flex: 1; padding: clamp(14px, 1vw, 18px) clamp(10px, 0.7vw, 14px); border: 1px solid #333; border-radius: clamp(10px, 0.8vw, 14px); text-align: center; transition: border-color 0.2s; }
1939
+ .ps-tryon-welcome-title { font-size: 1.4vw; font-weight: 700; color: #fff; margin: 1vw 0 0.3vw; letter-spacing: -0.01em; }
1940
+ .ps-tryon-welcome-sub { font-size: 0.9vw; color: #999; margin: 0; }
1941
+ .ps-tryon-features { display: flex; gap: 0.7vw; margin: 1.3vw 0; }
1942
+ .ps-tryon-feature { flex: 1; padding: 1vw 0.7vw; border: 1px solid #333; border-radius: 0.8vw; text-align: center; transition: border-color 0.2s; }
2060
1943
  .ps-tryon-feature:hover { border-color: #555; }
2061
- .ps-tryon-feature-icon { margin-bottom: clamp(6px, 0.4vw, 8px); color: #bb945c; display: flex; justify-content: center; }
2062
- .ps-tryon-feature-icon svg { stroke: currentColor; fill: none; width: clamp(18px, 1.2vw, 22px); height: clamp(18px, 1.2vw, 22px); }
2063
- .ps-tryon-feature-title { font-size: clamp(13px, 0.85vw, 15px); font-weight: 600; color: #fff; margin-bottom: 2px; }
2064
- .ps-tryon-feature-desc { font-size: clamp(11px, 0.7vw, 13px); color: #999; }
1944
+ .ps-tryon-feature-icon { margin-bottom: 0.4vw; color: #bb945c; display: flex; justify-content: center; }
1945
+ .ps-tryon-feature-icon svg { stroke: currentColor; fill: none; width: 1.2vw; height: 1.2vw; }
1946
+ .ps-tryon-feature-title { font-size: 0.85vw; font-weight: 600; color: #fff; margin-bottom: 2px; }
1947
+ .ps-tryon-feature-desc { font-size: 0.7vw; color: #999; }
2065
1948
  .ps-tryon-cta {
2066
- width: 100%; padding: clamp(14px, 1vw, 18px); background: #bb945c; color: #111; border: none;
2067
- border-radius: clamp(10px, 0.8vw, 14px); font-size: clamp(14px, 1vw, 17px); font-weight: 700; cursor: pointer;
2068
- display: flex; align-items: center; justify-content: center; gap: clamp(6px, 0.5vw, 10px); transition: all 0.2s;
1949
+ width: 100%; padding: 1vw; background: #bb945c; color: #111; border: none;
1950
+ border-radius: 0.8vw; font-size: 1vw; font-weight: 700; cursor: pointer;
1951
+ display: flex; align-items: center; justify-content: center; gap: 0.5vw; transition: all 0.2s;
2069
1952
  font-family: var(--ps-modal-font, system-ui, sans-serif);
2070
1953
  }
2071
1954
  .ps-tryon-cta:hover { background: #a07d4e; transform: translateY(-1px); }
2072
1955
  .ps-tryon-cta svg { stroke: #111; }
2073
- .ps-tryon-welcome-note { font-size: clamp(11px, 0.7vw, 13px); color: #666; margin-top: clamp(10px, 0.7vw, 14px); }
1956
+ .ps-tryon-welcome-note { font-size: 0.7vw; color: #666; margin-top: 0.7vw; }
2074
1957
 
2075
1958
  /* Upload */
2076
1959
  .ps-tryon-upload {
@@ -2122,59 +2005,146 @@ const STYLES = `
2122
2005
  }
2123
2006
  .ps-tryon-profile-select:focus { border-color: #bb945c; }
2124
2007
 
2125
- /* Sizing choice */
2126
- .ps-tryon-sizing-choice { text-align: center; }
2127
- .ps-tryon-section-title { font-size: 0.83vw; font-weight: 600; color: #fff; margin: 0 0 0.83vw; }
2128
- .ps-tryon-choice-cards { display: flex; flex-direction: column; gap: 0.52vw; }
2129
- .ps-tryon-choice-card {
2130
- display: flex; align-items: center; gap: 0.73vw; padding: 0.83vw;
2131
- border: 1.5px solid #333; border-radius: 0.63vw;
2132
- background: #1a1b1a; cursor: pointer; transition: all 0.25s; text-align: left;
2133
- width: 100%; font-family: inherit; position: relative; overflow: hidden;
2134
- }
2135
- .ps-tryon-choice-card:hover { border-color: #bb945c; transform: translateY(-1px); box-shadow: 0 0.31vw 1.04vw rgba(187,148,92,0.08); }
2136
- .ps-tryon-choice-card:hover::before { content: ''; position: absolute; left: 0; top: 0; bottom: 0; width: 3px; background: #bb945c; }
2137
- .ps-tryon-choice-icon { color: #bb945c; flex-shrink: 0; }
2138
- .ps-tryon-choice-icon svg { stroke: currentColor; fill: none; }
2139
- .ps-tryon-choice-info { flex: 1; min-width: 0; }
2140
- .ps-tryon-choice-title { font-size: 0.73vw; font-weight: 600; color: #fff; }
2141
- .ps-tryon-choice-desc { font-size: 0.63vw; color: #999; margin-top: 2px; }
2142
- .ps-tryon-choice-badge {
2143
- padding: 0.16vw 0.52vw; border-radius: 1.04vw; flex-shrink: 0;
2144
- background: rgba(187,148,92,0.12); color: #bb945c; font-size: 0.52vw; font-weight: 600;
2145
- }
2146
- .ps-tryon-sg-notice {
2147
- font-size: 0.68vw; color: #999; text-align: center; padding: 0.73vw 0.83vw;
2148
- margin-bottom: 0.73vw; border: 1px solid #333; border-radius: 0.63vw; background: #1a1b1a;
2149
- display: flex; flex-direction: column; align-items: center; gap: 0.57vw;
2150
- }
2151
- .ps-tryon-sg-notice-cta {
2152
- display: inline-flex; align-items: center; gap: 0.31vw;
2153
- padding: 0.42vw 1vw;
2154
- background: #bb945c; color: #111; border: none; border-radius: 0.42vw;
2155
- font-size: 0.68vw; font-weight: 700; cursor: pointer;
2156
- transition: all 0.2s; font-family: inherit;
2008
+ /* Sizing split layout (product image left, form right) */
2009
+ .ps-tryon-sizing-split {
2010
+ display: grid; grid-template-columns: 1fr 1.2fr; gap: 1.5vw;
2011
+ min-height: 22vw;
2012
+ }
2013
+ .ps-tryon-sizing-img-col {
2014
+ display: flex; align-items: stretch; justify-content: center;
2015
+ background: #0e0e0f; border-radius: 0.8vw; overflow: hidden;
2016
+ }
2017
+ .ps-tryon-sizing-product-img {
2018
+ width: 100%; height: 100%; object-fit: cover; object-position: top;
2019
+ }
2020
+ .ps-tryon-sizing-form-col {
2021
+ display: flex; flex-direction: column; justify-content: center;
2022
+ padding: 0.5vw 0;
2023
+ }
2024
+ .ps-tryon-sf-title {
2025
+ font-size: 1.3vw; font-weight: 700; color: #fff;
2026
+ margin: 0 0 1vw; letter-spacing: -0.01em;
2027
+ }
2028
+ .ps-tryon-sf-unit-tabs {
2029
+ display: flex; border-bottom: 1.5px solid #333; margin-bottom: 1vw;
2030
+ }
2031
+ .ps-tryon-sf-unit-tab {
2032
+ background: none; border: none; padding: 0.4vw 0.8vw;
2033
+ font-size: 0.8vw; font-weight: 600; color: #666; cursor: pointer;
2034
+ font-family: inherit; transition: all 0.2s; border-bottom: 2px solid transparent;
2035
+ margin-bottom: -1.5px;
2157
2036
  }
2158
- .ps-tryon-sg-notice-cta:hover { background: #a07d4e; }
2159
- .ps-tryon-sg-notice-cta svg { stroke: #111; }
2160
- .ps-tryon-sg-found svg { stroke: #4ade80; }
2161
- .ps-tryon-sg-checking { display: flex; flex-direction: column; align-items: center; padding: 2.08vw 1.04vw; text-align: center; }
2162
- .ps-tryon-sg-checking-icon { color: #bb945c; margin-bottom: 0.83vw; animation: ps-pulse-ruler 1.5s ease-in-out infinite; }
2037
+ .ps-tryon-sf-unit-tab:hover { color: #999; }
2038
+ .ps-tryon-sf-unit-tab.ps-active { color: #fff; border-bottom-color: #bb945c; }
2039
+
2040
+ .ps-tryon-sf-profile-bar { margin-bottom: 0.7vw; }
2041
+ .ps-tryon-sf-profile-select {
2042
+ width: 100%; padding: 0.4vw; background: #1a1b1a; color: #ccc;
2043
+ border: 1px solid #333; border-radius: 0.4vw;
2044
+ font-size: 0.75vw; font-family: inherit; cursor: pointer;
2045
+ }
2046
+
2047
+ .ps-tryon-sf-fields {
2048
+ display: flex; flex-direction: column; gap: 1.1vw;
2049
+ flex: 1;
2050
+ }
2051
+ .ps-tryon-sf-row {
2052
+ display: flex; align-items: center; justify-content: space-between;
2053
+ border-bottom: 1px solid #2a2a2a; padding-bottom: 0.7vw;
2054
+ }
2055
+ .ps-tryon-sf-label {
2056
+ font-size: 0.85vw; font-weight: 600; color: #ccc;
2057
+ letter-spacing: 0.04em; flex-shrink: 0;
2058
+ }
2059
+ .ps-tryon-sf-input-wrap { flex: 1; display: flex; justify-content: flex-end; }
2060
+ .ps-tryon-sf-inline { display: flex; align-items: center; gap: 0.4vw; }
2061
+ .ps-tryon-sf-ft-group { display: flex; align-items: center; gap: 0.3vw; }
2062
+ .ps-tryon-sf-input {
2063
+ background: transparent; border: none; border-bottom: 1.5px solid #444;
2064
+ color: #fff; font-size: 1vw; font-family: inherit;
2065
+ padding: 0.3vw 0; width: 4vw;
2066
+ text-align: center; outline: none; transition: border-color 0.2s;
2067
+ }
2068
+ .ps-tryon-sf-input:focus { border-bottom-color: #bb945c; }
2069
+ .ps-tryon-sf-input::placeholder { color: #555; }
2070
+ .ps-tryon-sf-input::-webkit-outer-spin-button,
2071
+ .ps-tryon-sf-input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
2072
+ .ps-tryon-sf-unit {
2073
+ font-size: 0.75vw; color: #666; font-weight: 500;
2074
+ }
2075
+
2076
+ .ps-tryon-sf-optional { margin-top: 0.3vw; }
2077
+ .ps-tryon-sf-optional { border-top: 1px solid #282828; margin-top: 0.42vw; padding-top: 0.42vw; }
2078
+ .ps-tryon-sf-optional-fields {
2079
+ display: flex; flex-direction: column; gap: 0.52vw; padding-top: 0.52vw;
2080
+ animation: ps-fade-up 0.3s ease both;
2081
+ }
2082
+ .ps-tryon-sf-optional-toggle {
2083
+ font-size: 0.75vw; color: #666; cursor: pointer;
2084
+ font-family: inherit; list-style: none;
2085
+ }
2086
+ .ps-tryon-sf-optional-toggle:hover { color: #999; }
2087
+ .ps-tryon-sf-optional-toggle::-webkit-details-marker { display: none; }
2088
+ .ps-tryon-sf-optional-fields { display: flex; flex-direction: column; gap: 0.8vw; padding-top: 0.7vw; }
2089
+
2090
+ .ps-tryon-sf-switch { margin-top: 0.8vw; text-align: center; }
2091
+ .ps-tryon-sf-switch-btn {
2092
+ background: none; border: none; color: #bb945c; font-size: 0.8vw;
2093
+ font-weight: 600; cursor: pointer; font-family: inherit;
2094
+ display: inline-flex; align-items: center; gap: 0.3vw;
2095
+ transition: color 0.2s;
2096
+ }
2097
+ .ps-tryon-sf-switch-btn:hover { color: #d6ba7d; }
2098
+ .ps-tryon-sf-switch-btn svg { stroke: currentColor; width: 0.8vw; height: 0.8vw; }
2099
+
2100
+ /* Save profile */
2101
+ .ps-tryon-sf-save { margin-top: 0.42vw; display: flex; flex-direction: column; gap: 0.36vw; }
2102
+ .ps-tryon-sf-save-check {
2103
+ display: flex; align-items: center; gap: 0.42vw; font-size: 0.73vw; color: #999; cursor: pointer; user-select: none;
2104
+ }
2105
+ .ps-tryon-sf-save-check input[type="checkbox"] { width: 0.83vw; height: 0.83vw; accent-color: #bb945c; cursor: pointer; }
2106
+ .ps-tryon-sf-save-name {
2107
+ padding: 0.42vw 0.63vw; border: 1.5px solid #333; border-radius: 0.42vw;
2108
+ background: #111; color: #fff; font-size: 0.73vw; font-family: inherit; outline: none;
2109
+ transition: border-color 0.2s; animation: ps-fade-up 0.2s ease both;
2110
+ }
2111
+ .ps-tryon-sf-save-name:focus { border-color: #bb945c; }
2112
+
2113
+ .ps-tryon-sf-next {
2114
+ margin-top: 1vw; align-self: flex-end;
2115
+ padding: 0.7vw 2vw;
2116
+ background: #bb945c; color: #111; border: none;
2117
+ border-radius: 0.6vw; font-size: 0.95vw;
2118
+ font-weight: 700; cursor: pointer; transition: all 0.2s; font-family: inherit;
2119
+ }
2120
+ .ps-tryon-sf-next:hover { background: #a07d4e; transform: translateY(-1px); }
2121
+
2122
+ /* Mobile: stack vertically */
2123
+ @media (max-width: 600px) {
2124
+ .ps-tryon-sizing-split { grid-template-columns: 1fr; }
2125
+ .ps-tryon-sizing-img-col { max-height: 200px; }
2126
+ .ps-tryon-sf-next { width: 100%; text-align: center; display: flex; justify-content: center; }
2127
+ }
2128
+
2129
+ /* Keep old class names for backwards compat */
2130
+ .ps-tryon-section-title { font-size: 0.95vw; font-weight: 600; color: #fff; margin: 0 0 0.8vw; }
2131
+ .ps-tryon-sg-checking { display: flex; flex-direction: column; align-items: center; padding: 2.5vw 1vw; text-align: center; }
2132
+ .ps-tryon-sg-checking-icon { color: #bb945c; margin-bottom: 0.8vw; animation: ps-pulse-ruler 1.5s ease-in-out infinite; }
2163
2133
  .ps-tryon-sg-checking-icon svg { stroke: currentColor; fill: none; }
2164
2134
  @keyframes ps-pulse-ruler { 0%, 100% { transform: scale(1); opacity: 0.7; } 50% { transform: scale(1.15); opacity: 1; } }
2165
- .ps-tryon-sg-checking-bar-wrap { width: 9.4vw; height: 4px; background: #333; border-radius: 2px; overflow: hidden; margin-bottom: 1.04vw; }
2135
+ .ps-tryon-sg-checking-bar-wrap { width: 9vw; height: 4px; background: #333; border-radius: 2px; overflow: hidden; margin-bottom: 1vw; }
2166
2136
  .ps-tryon-sg-checking-bar { height: 100%; width: 40%; background: linear-gradient(90deg, #bb945c, #d6ba7d); border-radius: 2px; animation: ps-sg-bar 1.5s ease-in-out infinite; }
2167
2137
  @keyframes ps-sg-bar { 0% { transform: translateX(-100%); } 100% { transform: translateX(350%); } }
2168
- .ps-tryon-sg-checking .ps-tryon-section-title { margin-bottom: 0.31vw; }
2169
- .ps-tryon-sg-checking-sub { font-size: 0.68vw; color: #999; margin: 0; }
2138
+ .ps-tryon-sg-checking .ps-tryon-section-title { margin-bottom: 0.3vw; }
2139
+ .ps-tryon-sg-checking-sub { font-size: 0.75vw; color: #999; margin: 0; }
2170
2140
 
2171
2141
  /* Back button */
2172
- .ps-tryon-back { display: flex; align-items: center; gap: 0.31vw; background: none; border: none; color: #999; font-size: 0.68vw; cursor: pointer; padding: 0; margin-bottom: 0.63vw; font-family: inherit; transition: color 0.2s; }
2142
+ .ps-tryon-back { display: flex; align-items: center; gap: 0.3vw; background: none; border: none; color: #999; font-size: 0.8vw; cursor: pointer; padding: 0; margin-bottom: 0.7vw; font-family: inherit; transition: color 0.2s; }
2173
2143
  .ps-tryon-back:hover { color: #fff; }
2174
2144
  .ps-tryon-back svg { stroke: currentColor; fill: none; }
2175
2145
 
2176
- /* Sizing form */
2177
- .ps-tryon-sizing-form { display: flex; flex-direction: column; gap: 0.63vw; }
2146
+ /* Sizing form (legacy — redirect to split view) */
2147
+ .ps-tryon-sizing-form { display: flex; flex-direction: column; gap: 0.7vw; }
2178
2148
  .ps-tryon-input-row { display: flex; align-items: center; gap: 0.52vw; }
2179
2149
  .ps-tryon-input-row label { font-size: 0.68vw; font-weight: 500; color: #ccc; min-width: 4.7vw; flex-shrink: 0; }
2180
2150
  .ps-tryon-input-row input {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@primestyleai/tryon",
3
- "version": "4.2.1",
3
+ "version": "4.3.0",
4
4
  "description": "PrimeStyle Virtual Try-On SDK — React component & Web Component",
5
5
  "type": "module",
6
6
  "main": "dist/primestyle-tryon.js",
@@ -55,6 +55,6 @@
55
55
  "vite": "^5.4.0"
56
56
  },
57
57
  "dependencies": {
58
- "@primestyleai/tryon": "^4.1.2"
58
+ "@primestyleai/tryon": "^4.2.2"
59
59
  }
60
60
  }