@primestyleai/tryon 5.10.187 → 5.10.189

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.
@@ -275,7 +275,7 @@ var scheduler_production_min = {};
275
275
  * This source code is licensed under the MIT license found in the
276
276
  * LICENSE file in the root directory of this source tree.
277
277
  */
278
- (function(exports$1) {
278
+ (function(exports) {
279
279
  function f2(a, b) {
280
280
  var c = a.length;
281
281
  a.push(b);
@@ -308,12 +308,12 @@ var scheduler_production_min = {};
308
308
  }
309
309
  if ("object" === typeof performance && "function" === typeof performance.now) {
310
310
  var l2 = performance;
311
- exports$1.unstable_now = function() {
311
+ exports.unstable_now = function() {
312
312
  return l2.now();
313
313
  };
314
314
  } else {
315
315
  var p2 = Date, q2 = p2.now();
316
- exports$1.unstable_now = function() {
316
+ exports.unstable_now = function() {
317
317
  return p2.now() - q2;
318
318
  };
319
319
  }
@@ -349,7 +349,7 @@ var scheduler_production_min = {};
349
349
  v2.callback = null;
350
350
  y2 = v2.priorityLevel;
351
351
  var e = d(v2.expirationTime <= b);
352
- b = exports$1.unstable_now();
352
+ b = exports.unstable_now();
353
353
  "function" === typeof e ? v2.callback = e : v2 === h(r2) && k2(r2);
354
354
  G2(b);
355
355
  } else k2(r2);
@@ -368,11 +368,11 @@ var scheduler_production_min = {};
368
368
  }
369
369
  var N2 = false, O2 = null, L2 = -1, P2 = 5, Q2 = -1;
370
370
  function M2() {
371
- return exports$1.unstable_now() - Q2 < P2 ? false : true;
371
+ return exports.unstable_now() - Q2 < P2 ? false : true;
372
372
  }
373
373
  function R2() {
374
374
  if (null !== O2) {
375
- var a = exports$1.unstable_now();
375
+ var a = exports.unstable_now();
376
376
  Q2 = a;
377
377
  var b = true;
378
378
  try {
@@ -401,31 +401,31 @@ var scheduler_production_min = {};
401
401
  }
402
402
  function K2(a, b) {
403
403
  L2 = D2(function() {
404
- a(exports$1.unstable_now());
404
+ a(exports.unstable_now());
405
405
  }, b);
406
406
  }
407
- exports$1.unstable_IdlePriority = 5;
408
- exports$1.unstable_ImmediatePriority = 1;
409
- exports$1.unstable_LowPriority = 4;
410
- exports$1.unstable_NormalPriority = 3;
411
- exports$1.unstable_Profiling = null;
412
- exports$1.unstable_UserBlockingPriority = 2;
413
- exports$1.unstable_cancelCallback = function(a) {
407
+ exports.unstable_IdlePriority = 5;
408
+ exports.unstable_ImmediatePriority = 1;
409
+ exports.unstable_LowPriority = 4;
410
+ exports.unstable_NormalPriority = 3;
411
+ exports.unstable_Profiling = null;
412
+ exports.unstable_UserBlockingPriority = 2;
413
+ exports.unstable_cancelCallback = function(a) {
414
414
  a.callback = null;
415
415
  };
416
- exports$1.unstable_continueExecution = function() {
416
+ exports.unstable_continueExecution = function() {
417
417
  A2 || z2 || (A2 = true, I2(J2));
418
418
  };
419
- exports$1.unstable_forceFrameRate = function(a) {
419
+ exports.unstable_forceFrameRate = function(a) {
420
420
  0 > a || 125 < a ? console.error("forceFrameRate takes a positive int between 0 and 125, forcing frame rates higher than 125 fps is not supported") : P2 = 0 < a ? Math.floor(1e3 / a) : 5;
421
421
  };
422
- exports$1.unstable_getCurrentPriorityLevel = function() {
422
+ exports.unstable_getCurrentPriorityLevel = function() {
423
423
  return y2;
424
424
  };
425
- exports$1.unstable_getFirstCallbackNode = function() {
425
+ exports.unstable_getFirstCallbackNode = function() {
426
426
  return h(r2);
427
427
  };
428
- exports$1.unstable_next = function(a) {
428
+ exports.unstable_next = function(a) {
429
429
  switch (y2) {
430
430
  case 1:
431
431
  case 2:
@@ -443,11 +443,11 @@ var scheduler_production_min = {};
443
443
  y2 = c;
444
444
  }
445
445
  };
446
- exports$1.unstable_pauseExecution = function() {
446
+ exports.unstable_pauseExecution = function() {
447
447
  };
448
- exports$1.unstable_requestPaint = function() {
448
+ exports.unstable_requestPaint = function() {
449
449
  };
450
- exports$1.unstable_runWithPriority = function(a, b) {
450
+ exports.unstable_runWithPriority = function(a, b) {
451
451
  switch (a) {
452
452
  case 1:
453
453
  case 2:
@@ -466,8 +466,8 @@ var scheduler_production_min = {};
466
466
  y2 = c;
467
467
  }
468
468
  };
469
- exports$1.unstable_scheduleCallback = function(a, b, c) {
470
- var d = exports$1.unstable_now();
469
+ exports.unstable_scheduleCallback = function(a, b, c) {
470
+ var d = exports.unstable_now();
471
471
  "object" === typeof c && null !== c ? (c = c.delay, c = "number" === typeof c && 0 < c ? d + c : d) : c = d;
472
472
  switch (a) {
473
473
  case 1:
@@ -490,8 +490,8 @@ var scheduler_production_min = {};
490
490
  c > d ? (a.sortIndex = c, f2(t2, a), null === h(r2) && a === h(t2) && (B2 ? (E2(L2), L2 = -1) : B2 = true, K2(H2, c - d))) : (a.sortIndex = e, f2(r2, a), A2 || z2 || (A2 = true, I2(J2)));
491
491
  return a;
492
492
  };
493
- exports$1.unstable_shouldYield = M2;
494
- exports$1.unstable_wrapCallback = function(a) {
493
+ exports.unstable_shouldYield = M2;
494
+ exports.unstable_wrapCallback = function(a) {
495
495
  var b = y2;
496
496
  return function() {
497
497
  var c = y2;
@@ -6979,7 +6979,7 @@ const es = {
6979
6979
  "Virtual Try-On": "Probador Virtual",
6980
6980
  "Find Your Size & See It On You": "Encuentra tu talla y pruébatelo",
6981
6981
  "See Your Fit": "Ver tu ajuste",
6982
- "Get the perfect fit, then try it on virtually": "Encuentra el ajuste perfecto y pruébatelo virtualmente",
6982
+ "Check your size, then try it on virtually": "Comprueba tu talla y pruébatelo virtualmente",
6983
6983
  "Get Your Size": "Tu talla",
6984
6984
  "Instant fit recommendation": "Recomendación de ajuste instantánea",
6985
6985
  "Try It On": "Pruébatelo",
@@ -7014,8 +7014,9 @@ const es = {
7014
7014
  "Edit measurements": "Editar medidas",
7015
7015
  "Size guide": "Guía de tallas",
7016
7016
  "Your fit": "Tu ajuste",
7017
+ "Your Size Recommendation": "Tu recomendación de talla",
7017
7018
  "Your measure": "Tu medida",
7018
- "perfect fit": "ajuste perfecto",
7019
+ "within range": "dentro del rango",
7019
7020
  "too tight": "demasiado ajustado",
7020
7021
  "tight": "ajustado",
7021
7022
  "a bit tight": "un poco ajustado",
@@ -7118,8 +7119,6 @@ const es = {
7118
7119
  "Loose": "Holgado",
7119
7120
  "Short": "Corto",
7120
7121
  "Long": "Largo",
7121
- "Perfect": "Perfecto",
7122
- "Perfect fit": "Ajuste perfecto",
7123
7122
  "✓ Fit": "✓ Ajuste",
7124
7123
  "too short": "demasiado corto",
7125
7124
  "too long": "demasiado largo",
@@ -7236,7 +7235,7 @@ const fr = {
7236
7235
  "Virtual Try-On": "Essayage Virtuel",
7237
7236
  "Find Your Size & See It On You": "Trouvez votre taille et essayez-le",
7238
7237
  "See Your Fit": "Voir votre ajustement",
7239
- "Get the perfect fit, then try it on virtually": "Trouvez la coupe parfaite, puis essayez-le virtuellement",
7238
+ "Check your size, then try it on virtually": "Vérifiez votre taille, puis essayez-le virtuellement",
7240
7239
  "Get Your Size": "Votre taille",
7241
7240
  "Instant fit recommendation": "Recommandation de coupe instantanée",
7242
7241
  "Try It On": "Essayer",
@@ -7271,8 +7270,9 @@ const fr = {
7271
7270
  "Edit measurements": "Modifier les mesures",
7272
7271
  "Size guide": "Guide des tailles",
7273
7272
  "Your fit": "Votre coupe",
7273
+ "Your Size Recommendation": "Votre recommandation de taille",
7274
7274
  "Your measure": "Votre mesure",
7275
- "perfect fit": "coupe parfaite",
7275
+ "within range": "dans la plage",
7276
7276
  "too tight": "trop serré",
7277
7277
  "tight": "serré",
7278
7278
  "a bit tight": "un peu serré",
@@ -7375,8 +7375,6 @@ const fr = {
7375
7375
  "Loose": "Lâche",
7376
7376
  "Short": "Court",
7377
7377
  "Long": "Long",
7378
- "Perfect": "Parfait",
7379
- "Perfect fit": "Ajustement parfait",
7380
7378
  "✓ Fit": "✓ Ajusté",
7381
7379
  "too short": "trop court",
7382
7380
  "too long": "trop long",
@@ -7493,7 +7491,7 @@ const de = {
7493
7491
  "Virtual Try-On": "Virtuelle Anprobe",
7494
7492
  "Find Your Size & See It On You": "Finden Sie Ihre Größe und probieren Sie es an",
7495
7493
  "See Your Fit": "Ihre Passform ansehen",
7496
- "Get the perfect fit, then try it on virtually": "Finden Sie die perfekte Passform und probieren Sie es virtuell an",
7494
+ "Check your size, then try it on virtually": "Prüfen Sie Ihre Größe und probieren Sie es virtuell an",
7497
7495
  "Get Your Size": "Ihre Größe",
7498
7496
  "Instant fit recommendation": "Sofortige Passformempfehlung",
7499
7497
  "Try It On": "Anprobieren",
@@ -7528,8 +7526,9 @@ const de = {
7528
7526
  "Edit measurements": "Maße bearbeiten",
7529
7527
  "Size guide": "Größentabelle",
7530
7528
  "Your fit": "Ihre Passform",
7529
+ "Your Size Recommendation": "Ihre Größenempfehlung",
7531
7530
  "Your measure": "Ihr Maß",
7532
- "perfect fit": "perfekte Passform",
7531
+ "within range": "im Bereich",
7533
7532
  "too tight": "zu eng",
7534
7533
  "tight": "eng",
7535
7534
  "a bit tight": "etwas eng",
@@ -7632,8 +7631,6 @@ const de = {
7632
7631
  "Loose": "Locker",
7633
7632
  "Short": "Kurz",
7634
7633
  "Long": "Lang",
7635
- "Perfect": "Perfekt",
7636
- "Perfect fit": "Perfekte Passform",
7637
7634
  "✓ Fit": "✓ Passt",
7638
7635
  "too short": "zu kurz",
7639
7636
  "too long": "zu lang",
@@ -7750,7 +7747,7 @@ const it = {
7750
7747
  "Virtual Try-On": "Prova Virtuale",
7751
7748
  "Find Your Size & See It On You": "Trova la tua taglia e provalo",
7752
7749
  "See Your Fit": "Vedi la vestibilità",
7753
- "Get the perfect fit, then try it on virtually": "Trova la vestibilità perfetta, poi provalo virtualmente",
7750
+ "Check your size, then try it on virtually": "Controlla la tua taglia, poi provalo virtualmente",
7754
7751
  "Get Your Size": "La tua taglia",
7755
7752
  "Instant fit recommendation": "Raccomandazione vestibilità istantanea",
7756
7753
  "Try It On": "Provalo",
@@ -7785,8 +7782,9 @@ const it = {
7785
7782
  "Edit measurements": "Modifica misure",
7786
7783
  "Size guide": "Guida alle taglie",
7787
7784
  "Your fit": "La tua vestibilità",
7785
+ "Your Size Recommendation": "La tua taglia consigliata",
7788
7786
  "Your measure": "La tua misura",
7789
- "perfect fit": "vestibilità perfetta",
7787
+ "within range": "entro l'intervallo",
7790
7788
  "too tight": "troppo stretto",
7791
7789
  "tight": "stretto",
7792
7790
  "a bit tight": "un po' stretto",
@@ -7889,8 +7887,6 @@ const it = {
7889
7887
  "Loose": "Largo",
7890
7888
  "Short": "Corto",
7891
7889
  "Long": "Lungo",
7892
- "Perfect": "Perfetto",
7893
- "Perfect fit": "Vestibilità perfetta",
7894
7890
  "✓ Fit": "✓ Adatto",
7895
7891
  "too short": "troppo corto",
7896
7892
  "too long": "troppo lungo",
@@ -8007,7 +8003,7 @@ const pt$1 = {
8007
8003
  "Virtual Try-On": "Provador Virtual",
8008
8004
  "Find Your Size & See It On You": "Encontre seu tamanho e experimente",
8009
8005
  "See Your Fit": "Veja seu ajuste",
8010
- "Get the perfect fit, then try it on virtually": "Encontre o caimento perfeito e experimente virtualmente",
8006
+ "Check your size, then try it on virtually": "Confira seu tamanho e experimente virtualmente",
8011
8007
  "Get Your Size": "Seu tamanho",
8012
8008
  "Instant fit recommendation": "Recomendação de caimento instantânea",
8013
8009
  "Try It On": "Experimentar",
@@ -8042,8 +8038,9 @@ const pt$1 = {
8042
8038
  "Edit measurements": "Editar medidas",
8043
8039
  "Size guide": "Guia de tamanhos",
8044
8040
  "Your fit": "Seu caimento",
8041
+ "Your Size Recommendation": "Sua recomendação de tamanho",
8045
8042
  "Your measure": "Sua medida",
8046
- "perfect fit": "caimento perfeito",
8043
+ "within range": "dentro da faixa",
8047
8044
  "too tight": "muito apertado",
8048
8045
  "tight": "apertado",
8049
8046
  "a bit tight": "um pouco apertado",
@@ -8146,8 +8143,6 @@ const pt$1 = {
8146
8143
  "Loose": "Folgado",
8147
8144
  "Short": "Curto",
8148
8145
  "Long": "Longo",
8149
- "Perfect": "Perfeito",
8150
- "Perfect fit": "Caimento perfeito",
8151
8146
  "✓ Fit": "✓ Caimento",
8152
8147
  "too short": "muito curto",
8153
8148
  "too long": "muito longo",
@@ -8264,7 +8259,7 @@ const ja = {
8264
8259
  "Virtual Try-On": "バーチャル試着",
8265
8260
  "Find Your Size & See It On You": "あなたのサイズを見つけて試着",
8266
8261
  "See Your Fit": "フィット感を見る",
8267
- "Get the perfect fit, then try it on virtually": "最適なフィットを見つけて、バーチャルで試着しましょう",
8262
+ "Check your size, then try it on virtually": "サイズを確認して、バーチャルで試着しましょう",
8268
8263
  "Get Your Size": "サイズを確認",
8269
8264
  "Instant fit recommendation": "瞬時にフィット提案",
8270
8265
  "Try It On": "試着する",
@@ -8299,8 +8294,9 @@ const ja = {
8299
8294
  "Edit measurements": "寸法を編集",
8300
8295
  "Size guide": "サイズガイド",
8301
8296
  "Your fit": "あなたのフィット",
8297
+ "Your Size Recommendation": "サイズのおすすめ",
8302
8298
  "Your measure": "あなたの寸法",
8303
- "perfect fit": "ぴったり",
8299
+ "within range": "範囲内",
8304
8300
  "too tight": "きつすぎる",
8305
8301
  "tight": "きつい",
8306
8302
  "a bit tight": "少しきつい",
@@ -8403,8 +8399,6 @@ const ja = {
8403
8399
  "Loose": "ゆるい",
8404
8400
  "Short": "短い",
8405
8401
  "Long": "長い",
8406
- "Perfect": "ぴったり",
8407
- "Perfect fit": "ぴったりフィット",
8408
8402
  "✓ Fit": "✓ フィット",
8409
8403
  "too short": "短すぎる",
8410
8404
  "too long": "長すぎる",
@@ -8521,7 +8515,7 @@ const zh = {
8521
8515
  "Virtual Try-On": "虚拟试穿",
8522
8516
  "Find Your Size & See It On You": "找到你的尺码并试穿",
8523
8517
  "See Your Fit": "查看合身效果",
8524
- "Get the perfect fit, then try it on virtually": "找到最佳合身度,然后虚拟试穿",
8518
+ "Check your size, then try it on virtually": "确认尺码,然后虚拟试穿",
8525
8519
  "Get Your Size": "获取尺码",
8526
8520
  "Instant fit recommendation": "即时合身推荐",
8527
8521
  "Try It On": "试穿",
@@ -8556,8 +8550,9 @@ const zh = {
8556
8550
  "Edit measurements": "编辑尺寸",
8557
8551
  "Size guide": "尺码指南",
8558
8552
  "Your fit": "你的合身度",
8553
+ "Your Size Recommendation": "你的尺码建议",
8559
8554
  "Your measure": "你的尺寸",
8560
- "perfect fit": "完美合身",
8555
+ "within range": "在范围内",
8561
8556
  "too tight": "太紧",
8562
8557
  "tight": "偏紧",
8563
8558
  "a bit tight": "略紧",
@@ -8660,8 +8655,6 @@ const zh = {
8660
8655
  "Loose": "松",
8661
8656
  "Short": "短",
8662
8657
  "Long": "长",
8663
- "Perfect": "完美",
8664
- "Perfect fit": "完美合身",
8665
8658
  "✓ Fit": "✓ 合身",
8666
8659
  "too short": "太短",
8667
8660
  "too long": "太长",
@@ -8778,7 +8771,7 @@ const ko = {
8778
8771
  "Virtual Try-On": "가상 피팅",
8779
8772
  "Find Your Size & See It On You": "사이즈를 찾고 입어보세요",
8780
8773
  "See Your Fit": "핏 확인하기",
8781
- "Get the perfect fit, then try it on virtually": "완벽한 핏을 찾고 가상으로 입어보세요",
8774
+ "Check your size, then try it on virtually": "사이즈를 확인하고 가상으로 입어보세요",
8782
8775
  "Get Your Size": "사이즈 확인",
8783
8776
  "Instant fit recommendation": "즉시 핏 추천",
8784
8777
  "Try It On": "입어보기",
@@ -8813,8 +8806,9 @@ const ko = {
8813
8806
  "Edit measurements": "치수 수정",
8814
8807
  "Size guide": "사이즈 가이드",
8815
8808
  "Your fit": "나의 핏",
8809
+ "Your Size Recommendation": "사이즈 추천",
8816
8810
  "Your measure": "내 치수",
8817
- "perfect fit": "완벽한 ",
8811
+ "within range": "범위 ",
8818
8812
  "too tight": "너무 타이트",
8819
8813
  "tight": "타이트",
8820
8814
  "a bit tight": "약간 타이트",
@@ -8917,8 +8911,6 @@ const ko = {
8917
8911
  "Loose": "헐렁한",
8918
8912
  "Short": "짧은",
8919
8913
  "Long": "긴",
8920
- "Perfect": "완벽",
8921
- "Perfect fit": "완벽한 핏",
8922
8914
  "✓ Fit": "✓ 적합",
8923
8915
  "too short": "너무 짧음",
8924
8916
  "too long": "너무 김",
@@ -9035,7 +9027,7 @@ const ar = {
9035
9027
  "Virtual Try-On": "تجربة افتراضية",
9036
9028
  "Find Your Size & See It On You": "اعثر على مقاسك وجرّبه",
9037
9029
  "See Your Fit": "شاهد الملاءمة",
9038
- "Get the perfect fit, then try it on virtually": "اعثر على المقاس المثالي ثم جرّبه افتراضياً",
9030
+ "Check your size, then try it on virtually": "تحقق من مقاسك ثم جرّبه افتراضياً",
9039
9031
  "Get Your Size": "مقاسك",
9040
9032
  "Instant fit recommendation": "توصية فورية بالمقاس",
9041
9033
  "Try It On": "جرّبه",
@@ -9070,8 +9062,9 @@ const ar = {
9070
9062
  "Edit measurements": "تعديل القياسات",
9071
9063
  "Size guide": "دليل المقاسات",
9072
9064
  "Your fit": "ملاءمتك",
9065
+ "Your Size Recommendation": "توصية المقاس",
9073
9066
  "Your measure": "قياسك",
9074
- "perfect fit": "مقاس مثالي",
9067
+ "within range": "ضمن النطاق",
9075
9068
  "too tight": "ضيق جداً",
9076
9069
  "tight": "ضيق",
9077
9070
  "a bit tight": "ضيق قليلاً",
@@ -9174,8 +9167,6 @@ const ar = {
9174
9167
  "Loose": "فضفاض",
9175
9168
  "Short": "قصير",
9176
9169
  "Long": "طويل",
9177
- "Perfect": "مثالي",
9178
- "Perfect fit": "مقاس مثالي",
9179
9170
  "✓ Fit": "✓ مناسب",
9180
9171
  "too short": "قصير جداً",
9181
9172
  "too long": "طويل جداً",
@@ -9465,16 +9456,20 @@ class ApiClient {
9465
9456
  if (category && category !== "apparel") body.category = category;
9466
9457
  if (context?.productId) body.productId = context.productId;
9467
9458
  if (context?.productTitle) body.productTitle = context.productTitle;
9459
+ if (context?.productCategory) body.productCategory = context.productCategory;
9460
+ if (context?.productSubcategory) body.productSubcategory = context.productSubcategory;
9468
9461
  if (context?.productFitType) body.productFitType = context.productFitType;
9469
9462
  if (context?.productType) body.productType = context.productType;
9470
9463
  if (context?.productTags?.length) body.productTags = context.productTags;
9471
9464
  if (context?.productDescription) body.productDescription = context.productDescription;
9472
9465
  if (context?.productMaterial) body.productMaterial = context.productMaterial;
9466
+ if (context?.garmentDetailImage && context.garmentDetailImage !== garmentImage) body.garmentDetailImage = context.garmentDetailImage;
9473
9467
  if (context?.silhouetteContext) body.silhouetteContext = context.silhouetteContext;
9474
9468
  if (context?.editFromPrevious) body.editFromPrevious = true;
9475
9469
  console.log("[ps-sdk:api] POST /api/v1/tryon payload", {
9476
9470
  modelImageBytes: modelImage.length,
9477
9471
  garmentImageBytes: garmentImage.length,
9472
+ garmentDetailImageSet: !!body.garmentDetailImage,
9478
9473
  category: category || "apparel",
9479
9474
  fitInfo: fitInfo?.map((f2) => ({
9480
9475
  area: f2.area,
@@ -10280,6 +10275,9 @@ function formatUserMeasurementValue(measurement, value) {
10280
10275
  if (!isUnitlessShoeSizeMeasurement(measurement)) return value;
10281
10276
  return value.replace(/\s*(cm|mm|in|inch|inches)\b/ig, "").trim();
10282
10277
  }
10278
+ function normalizePromptSizeLabel(size) {
10279
+ return String(size || "").trim().replace(/\s+[–—-]\s+(?:UK|US|EU|IT|FR|DE|ES|JP|CN|KR|AU|BR)\s+.+$/i, "").replace(/\s*\((?:UK|US|EU|IT|FR|DE|ES|JP|CN|KR|AU|BR)\s+[^)]*\)\s*$/i, "").trim();
10280
+ }
10283
10281
  function computeFit(userValue, chartRange, unit) {
10284
10282
  const targetUnit = normalizeUnit(unit) || detectUnitFromText(chartRange) || "in";
10285
10283
  const chartUnit = detectUnitFromText(chartRange);
@@ -10340,7 +10338,7 @@ function buildSilhouetteContext(sizingResult, sizeGuide, selectedSizeOverride, u
10340
10338
  if (!sizingResult && !sizeGuide && !userHeight && !userWeight) return void 0;
10341
10339
  const out = {};
10342
10340
  const promptUnit = normalizeUnit(sizingResult?.unit) || detectUnitFromText(sizingResult?.matchDetails?.[0]?.userValue) || detectUnitFromText(Object.values(sizingResult?.sections || {})[0]?.matchDetails?.[0]?.userValue) || "in";
10343
- const baseSize = (selectedSizeOverride || sizingResult?.recommendedSize || "").toString().trim();
10341
+ const baseSize = normalizePromptSizeLabel(selectedSizeOverride || sizingResult?.recommendedSize || "");
10344
10342
  if (userHeight) out.userHeight = userHeight;
10345
10343
  if (userWeight) out.userWeight = userWeight;
10346
10344
  let chartRowLength = null;
@@ -10390,7 +10388,7 @@ function buildSilhouetteContext(sizingResult, sizeGuide, selectedSizeOverride, u
10390
10388
  const labelParts = [];
10391
10389
  const measurementParts = [];
10392
10390
  for (const [secName, secResult] of sectionEntries) {
10393
- const secSize = (secResult?.recommendedSize ?? "").toString().trim();
10391
+ const secSize = normalizePromptSizeLabel(secResult?.recommendedSize ?? "");
10394
10392
  if (!secSize) continue;
10395
10393
  const cleanSec = /\bsize\s*$/i.test(secName) ? secName.replace(/\s*\bsize\s*$/i, "").trim() : secName;
10396
10394
  labelParts.push(`${cleanSec} ${secSize}`);
@@ -10496,6 +10494,24 @@ function lsSet(key, value) {
10496
10494
  } catch {
10497
10495
  }
10498
10496
  }
10497
+ function lsRemove(key) {
10498
+ try {
10499
+ localStorage.removeItem(LS_PREFIX + key);
10500
+ } catch {
10501
+ }
10502
+ }
10503
+ function clearProfileLocalStorage() {
10504
+ lsRemove(PROFILES_KEY);
10505
+ lsRemove(ACTIVE_PROFILE_KEY);
10506
+ lsRemove("profile_completion_draft");
10507
+ try {
10508
+ localStorage.removeItem(PROFILES_KEY);
10509
+ localStorage.removeItem(ACTIVE_PROFILE_KEY);
10510
+ localStorage.removeItem("profile_completion_draft");
10511
+ } catch {
10512
+ }
10513
+ emitStorageChange("profile-clear");
10514
+ }
10499
10515
  function getProfiles() {
10500
10516
  return lsGet(PROFILES_KEY, []);
10501
10517
  }
@@ -10510,19 +10526,6 @@ function setActiveProfileId(id2) {
10510
10526
  lsSet(ACTIVE_PROFILE_KEY, id2);
10511
10527
  emitStorageChange("active-profile");
10512
10528
  }
10513
- function getActiveProfile() {
10514
- const profiles = getProfiles();
10515
- if (profiles.length === 0) return null;
10516
- const activeId = getActiveProfileId();
10517
- if (activeId) {
10518
- const found = profiles.find((p2) => p2.id === activeId);
10519
- if (found) return found;
10520
- }
10521
- const sorted = [...profiles].sort(
10522
- (a, b) => (b.lastUsedAt || b.createdAt || 0) - (a.lastUsedAt || a.createdAt || 0)
10523
- );
10524
- return sorted[0] || null;
10525
- }
10526
10529
  function updateProfile(id2, patch) {
10527
10530
  const profiles = getProfiles();
10528
10531
  const idx = profiles.findIndex((p2) => p2.id === id2);
@@ -10937,6 +10940,188 @@ function getApiUrl(override) {
10937
10940
  }
10938
10941
  return envUrl || "http://localhost:4000";
10939
10942
  }
10943
+ const SESSION_KEY = "primestyle_profile_session";
10944
+ const AUTH_MESSAGE_TYPE = "PRIMESTYLE_SDK_AUTH";
10945
+ const POPUP_TIMEOUT_MS = 12e4;
10946
+ const POLL_INTERVAL_MS = 900;
10947
+ function emitProfileAuthChange(reason) {
10948
+ if (typeof window === "undefined") return;
10949
+ try {
10950
+ window.dispatchEvent(new CustomEvent(PS_STORAGE_CHANGE_EVENT, { detail: { reason } }));
10951
+ } catch {
10952
+ }
10953
+ }
10954
+ function isTrustedAuthOrigin(eventOrigin, expectedOrigin) {
10955
+ if (eventOrigin === expectedOrigin) return true;
10956
+ try {
10957
+ const host = new URL(eventOrigin).hostname;
10958
+ return host === "localhost" || host === "127.0.0.1" || host.endsWith(".primestyleai.com") || host.endsWith(".myaifitting.com");
10959
+ } catch {
10960
+ return false;
10961
+ }
10962
+ }
10963
+ function readStorage() {
10964
+ if (typeof window === "undefined") return null;
10965
+ try {
10966
+ return window.localStorage;
10967
+ } catch {
10968
+ return null;
10969
+ }
10970
+ }
10971
+ function createAuthRequestId() {
10972
+ try {
10973
+ const randomId = window.crypto?.randomUUID?.();
10974
+ if (randomId) return randomId;
10975
+ } catch {
10976
+ }
10977
+ return `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 12)}`;
10978
+ }
10979
+ async function readAuthStatus(statusUrl) {
10980
+ const response = await fetch(statusUrl.toString(), {
10981
+ method: "GET",
10982
+ credentials: "omit",
10983
+ cache: "no-store"
10984
+ });
10985
+ if (!response.ok) return null;
10986
+ const data = await response.json();
10987
+ return data.status === "done" ? data : null;
10988
+ }
10989
+ function getStoredProfileSession() {
10990
+ const storage = readStorage();
10991
+ if (!storage) return null;
10992
+ try {
10993
+ const raw = storage.getItem(SESSION_KEY);
10994
+ if (!raw) return null;
10995
+ const parsed = JSON.parse(raw);
10996
+ return parsed?.accessToken ? parsed : null;
10997
+ } catch {
10998
+ return null;
10999
+ }
11000
+ }
11001
+ function setStoredProfileSession(session) {
11002
+ const storage = readStorage();
11003
+ if (!storage) return;
11004
+ try {
11005
+ storage.setItem(SESSION_KEY, JSON.stringify(session));
11006
+ emitProfileAuthChange("profile-auth-set");
11007
+ } catch {
11008
+ }
11009
+ }
11010
+ function clearStoredProfileSession() {
11011
+ const storage = readStorage();
11012
+ if (!storage) return;
11013
+ try {
11014
+ storage.removeItem(SESSION_KEY);
11015
+ emitProfileAuthChange("profile-auth-clear");
11016
+ } catch {
11017
+ }
11018
+ }
11019
+ function startSocialProfileLogin(provider, apiUrl) {
11020
+ if (typeof window === "undefined") {
11021
+ return Promise.reject(new Error("Social login must run in the browser."));
11022
+ }
11023
+ const baseUrl = getApiUrl(apiUrl);
11024
+ const backendOrigin = new URL(baseUrl).origin;
11025
+ const authRequestId = createAuthRequestId();
11026
+ const startUrl = new URL(`${baseUrl.replace(/\/$/, "")}/api/sdk/v1/auth/${provider}/start`);
11027
+ startUrl.searchParams.set("origin", window.location.origin);
11028
+ startUrl.searchParams.set("requestId", authRequestId);
11029
+ const statusUrl = new URL(`${baseUrl.replace(/\/$/, "")}/api/sdk/v1/auth/${provider}/status`);
11030
+ statusUrl.searchParams.set("origin", window.location.origin);
11031
+ statusUrl.searchParams.set("requestId", authRequestId);
11032
+ const popup = window.open(
11033
+ startUrl.toString(),
11034
+ "primestyle-profile-login",
11035
+ "width=520,height=720"
11036
+ );
11037
+ if (!popup) {
11038
+ return Promise.reject(new Error("Popup was blocked. Please allow popups and try again."));
11039
+ }
11040
+ return new Promise((resolve, reject) => {
11041
+ let settled = false;
11042
+ const cleanup = () => {
11043
+ window.removeEventListener("message", onMessage);
11044
+ window.clearInterval(statusTimer);
11045
+ window.clearTimeout(timeout);
11046
+ };
11047
+ const finish = (fn) => {
11048
+ if (settled) return;
11049
+ settled = true;
11050
+ cleanup();
11051
+ fn();
11052
+ };
11053
+ const onMessage = (event) => {
11054
+ if (!isTrustedAuthOrigin(event.origin, backendOrigin)) return;
11055
+ const data = event.data;
11056
+ if (!data || data.type !== AUTH_MESSAGE_TYPE) return;
11057
+ if (!data.ok || !data.accessToken) {
11058
+ finish(() => reject(new Error(data.error || "Social login failed.")));
11059
+ return;
11060
+ }
11061
+ finish(() => resolve({
11062
+ accessToken: data.accessToken,
11063
+ isNewUser: Boolean(data.isNewUser),
11064
+ signedInAt: Date.now()
11065
+ }));
11066
+ };
11067
+ const handleAuthPayload = (data) => {
11068
+ if (!data.ok || !data.accessToken) {
11069
+ finish(() => reject(new Error(data.error || "Social login failed.")));
11070
+ return;
11071
+ }
11072
+ finish(() => resolve({
11073
+ accessToken: data.accessToken,
11074
+ isNewUser: Boolean(data.isNewUser),
11075
+ signedInAt: Date.now()
11076
+ }));
11077
+ };
11078
+ const statusTimer = window.setInterval(() => {
11079
+ readAuthStatus(statusUrl).then((data) => {
11080
+ if (data) handleAuthPayload(data);
11081
+ }).catch(() => {
11082
+ });
11083
+ }, POLL_INTERVAL_MS);
11084
+ const timeout = window.setTimeout(() => {
11085
+ finish(() => reject(new Error("Login did not finish. Please close the sign-in window and try again.")));
11086
+ }, POPUP_TIMEOUT_MS);
11087
+ window.addEventListener("message", onMessage);
11088
+ });
11089
+ }
11090
+ function endpoint(apiUrl) {
11091
+ return `${getApiUrl(apiUrl).replace(/\/$/, "")}/api/sdk/v1/profiles`;
11092
+ }
11093
+ function normalizeStore(data) {
11094
+ return {
11095
+ profiles: Array.isArray(data.profiles) ? data.profiles : [],
11096
+ activeProfileId: data.activeProfileId ?? null
11097
+ };
11098
+ }
11099
+ async function parseResponse(response) {
11100
+ const data = await response.json().catch(() => ({}));
11101
+ if (!response.ok) {
11102
+ const message = typeof data.message === "string" ? data.message : "Profile sync failed.";
11103
+ throw new Error(message);
11104
+ }
11105
+ return data;
11106
+ }
11107
+ async function fetchRemoteProfiles(apiUrl, accessToken) {
11108
+ const response = await fetch(endpoint(apiUrl), {
11109
+ method: "GET",
11110
+ headers: { Authorization: `Bearer ${accessToken}` }
11111
+ });
11112
+ return normalizeStore(await parseResponse(response));
11113
+ }
11114
+ async function saveRemoteProfiles(apiUrl, accessToken, profiles, activeProfileId) {
11115
+ const response = await fetch(endpoint(apiUrl), {
11116
+ method: "PUT",
11117
+ headers: {
11118
+ Authorization: `Bearer ${accessToken}`,
11119
+ "Content-Type": "application/json"
11120
+ },
11121
+ body: JSON.stringify({ profiles, activeProfileId })
11122
+ });
11123
+ return normalizeStore(await parseResponse(response));
11124
+ }
10940
11125
  let cachedMP = null;
10941
11126
  const MP_CACHE_TTL_MS = 6e4;
10942
11127
  function setCachedMediaPipe(landmarks) {
@@ -10962,9 +11147,26 @@ async function recommendForProduct(input) {
10962
11147
  const t0 = Date.now();
10963
11148
  log("ENTER", { productId: input.productId, apiUrl: input.apiUrl, skipCache: !!input.skipCache });
10964
11149
  const sessionId = getOrCreateSessionId();
10965
- const profile = input.profile ?? getActiveProfile();
11150
+ const apiKey = input.apiKey ?? getApiKey();
11151
+ const apiUrl = (input.apiUrl ?? getApiUrl()).replace(/\/+$/, "");
11152
+ const session = getStoredProfileSession();
11153
+ if (!session) {
11154
+ log("no signed-in profile session — returning null");
11155
+ return null;
11156
+ }
11157
+ let remoteProfiles = [];
11158
+ let activeProfileId = null;
11159
+ try {
11160
+ const remoteStore = await fetchRemoteProfiles(apiUrl, session.accessToken);
11161
+ remoteProfiles = remoteStore.profiles;
11162
+ activeProfileId = remoteStore.activeProfileId;
11163
+ } catch (error) {
11164
+ log("remote profile fetch failed — returning null", error);
11165
+ return null;
11166
+ }
11167
+ const profile = input.profile && input.profile.id === activeProfileId ? input.profile : activeProfileId ? remoteProfiles.find((p2) => p2.id === activeProfileId) ?? null : null;
10966
11168
  if (!profile) {
10967
- log("no active profile — returning null");
11169
+ log("no selected backend profile — returning null");
10968
11170
  return null;
10969
11171
  }
10970
11172
  log("profile resolved", {
@@ -11017,8 +11219,6 @@ async function recommendForProduct(input) {
11017
11219
  }
11018
11220
  }
11019
11221
  log(`cache MISS — calling backend (elapsed in pre-flight: ${Date.now() - t0}ms)`);
11020
- const apiKey = input.apiKey ?? getApiKey();
11021
- const apiUrl = (input.apiUrl ?? getApiUrl()).replace(/\/+$/, "");
11022
11222
  let sizeGuide = null;
11023
11223
  if (input.sizeGuideData != null) {
11024
11224
  const tSg = Date.now();
@@ -11063,6 +11263,34 @@ async function recommendForProduct(input) {
11063
11263
  if (value != null) measurements[key] = value;
11064
11264
  }
11065
11265
  }
11266
+ const legacyKnownMeasurements = {};
11267
+ for (const key of [
11268
+ "chest",
11269
+ "bust",
11270
+ "waist",
11271
+ "hips",
11272
+ "shoulderWidth",
11273
+ "sleeveLength",
11274
+ "inseam",
11275
+ "neckCircumference",
11276
+ "thighCircumference",
11277
+ "wristCircumference",
11278
+ "footLengthCm"
11279
+ ]) {
11280
+ const value = profile[key];
11281
+ if (typeof value === "number" && value > 0) {
11282
+ measurements[key] = value;
11283
+ legacyKnownMeasurements[key] = value;
11284
+ }
11285
+ }
11286
+ if (profile.customMeasurements) {
11287
+ for (const [key, value] of Object.entries(profile.customMeasurements)) {
11288
+ if (typeof value === "number" && value > 0) {
11289
+ measurements[key] = value;
11290
+ legacyKnownMeasurements[key] = value;
11291
+ }
11292
+ }
11293
+ }
11066
11294
  if (profile.height != null) measurements.height = profile.height;
11067
11295
  if (profile.weight != null) measurements.weight = profile.weight;
11068
11296
  if (profile.heightUnit) measurements.heightUnit = profile.heightUnit;
@@ -11099,6 +11327,8 @@ async function recommendForProduct(input) {
11099
11327
  }
11100
11328
  if (profile.knownMeasurements) {
11101
11329
  payload.knownMeasurements = profile.knownMeasurements;
11330
+ } else if (Object.keys(legacyKnownMeasurements).length > 0) {
11331
+ payload.knownMeasurements = legacyKnownMeasurements;
11102
11332
  }
11103
11333
  if (sizeGuide && sizeGuide.found) {
11104
11334
  payload.sizeGuide = sizeGuide;
@@ -11146,7 +11376,7 @@ async function recommendForProduct(input) {
11146
11376
  }
11147
11377
  ])
11148
11378
  ) : void 0;
11149
- addSizeToHistory(profile.id, {
11379
+ const newHistoryEntry = {
11150
11380
  productId: input.productId,
11151
11381
  productTitle: input.productTitle,
11152
11382
  productImage: input.productImage,
@@ -11156,6 +11386,15 @@ async function recommendForProduct(input) {
11156
11386
  sectionsFull,
11157
11387
  recommendedLength: result.recommendedLength || void 0,
11158
11388
  savedAt: Date.now()
11389
+ };
11390
+ const updatedProfiles = remoteProfiles.map((p2) => {
11391
+ if (p2.id !== profile.id) return p2;
11392
+ const history = (p2.sizeHistory || []).filter((h) => h.productId !== input.productId);
11393
+ history.unshift(newHistoryEntry);
11394
+ return { ...p2, sizeHistory: history.slice(0, 50), lastUsedAt: Date.now() };
11395
+ });
11396
+ void saveRemoteProfiles(apiUrl, session.accessToken, updatedProfiles, activeProfileId).catch((error) => {
11397
+ log("remote size-history save failed", error);
11159
11398
  });
11160
11399
  setLastSizeSelection({
11161
11400
  productId: input.productId,
@@ -11345,179 +11584,6 @@ async function pickBestGarmentImage(images) {
11345
11584
  for (const s of scored) console.log(`[ps-sdk:garment-pick] ${s.score.toString().padStart(4, " ")} ${s.url}`);
11346
11585
  return best;
11347
11586
  }
11348
- const SESSION_KEY = "primestyle_profile_session";
11349
- const AUTH_MESSAGE_TYPE = "PRIMESTYLE_SDK_AUTH";
11350
- const POPUP_TIMEOUT_MS = 12e4;
11351
- const POLL_INTERVAL_MS = 900;
11352
- function isTrustedAuthOrigin(eventOrigin, expectedOrigin) {
11353
- if (eventOrigin === expectedOrigin) return true;
11354
- try {
11355
- const host = new URL(eventOrigin).hostname;
11356
- return host === "localhost" || host === "127.0.0.1" || host.endsWith(".primestyleai.com") || host.endsWith(".myaifitting.com");
11357
- } catch {
11358
- return false;
11359
- }
11360
- }
11361
- function readStorage() {
11362
- if (typeof window === "undefined") return null;
11363
- try {
11364
- return window.localStorage;
11365
- } catch {
11366
- return null;
11367
- }
11368
- }
11369
- function createAuthRequestId() {
11370
- try {
11371
- const randomId = window.crypto?.randomUUID?.();
11372
- if (randomId) return randomId;
11373
- } catch {
11374
- }
11375
- return `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 12)}`;
11376
- }
11377
- async function readAuthStatus(statusUrl) {
11378
- const response = await fetch(statusUrl.toString(), {
11379
- method: "GET",
11380
- credentials: "omit",
11381
- cache: "no-store"
11382
- });
11383
- if (!response.ok) return null;
11384
- const data = await response.json();
11385
- return data.status === "done" ? data : null;
11386
- }
11387
- function getStoredProfileSession() {
11388
- const storage = readStorage();
11389
- if (!storage) return null;
11390
- try {
11391
- const raw = storage.getItem(SESSION_KEY);
11392
- if (!raw) return null;
11393
- const parsed = JSON.parse(raw);
11394
- return parsed?.accessToken ? parsed : null;
11395
- } catch {
11396
- return null;
11397
- }
11398
- }
11399
- function setStoredProfileSession(session) {
11400
- const storage = readStorage();
11401
- if (!storage) return;
11402
- try {
11403
- storage.setItem(SESSION_KEY, JSON.stringify(session));
11404
- } catch {
11405
- }
11406
- }
11407
- function clearStoredProfileSession() {
11408
- const storage = readStorage();
11409
- if (!storage) return;
11410
- try {
11411
- storage.removeItem(SESSION_KEY);
11412
- } catch {
11413
- }
11414
- }
11415
- function startSocialProfileLogin(provider, apiUrl) {
11416
- if (typeof window === "undefined") {
11417
- return Promise.reject(new Error("Social login must run in the browser."));
11418
- }
11419
- const baseUrl = getApiUrl(apiUrl);
11420
- const backendOrigin = new URL(baseUrl).origin;
11421
- const authRequestId = createAuthRequestId();
11422
- const startUrl = new URL(`${baseUrl.replace(/\/$/, "")}/api/sdk/v1/auth/${provider}/start`);
11423
- startUrl.searchParams.set("origin", window.location.origin);
11424
- startUrl.searchParams.set("requestId", authRequestId);
11425
- const statusUrl = new URL(`${baseUrl.replace(/\/$/, "")}/api/sdk/v1/auth/${provider}/status`);
11426
- statusUrl.searchParams.set("origin", window.location.origin);
11427
- statusUrl.searchParams.set("requestId", authRequestId);
11428
- const popup = window.open(
11429
- startUrl.toString(),
11430
- "primestyle-profile-login",
11431
- "width=520,height=720"
11432
- );
11433
- if (!popup) {
11434
- return Promise.reject(new Error("Popup was blocked. Please allow popups and try again."));
11435
- }
11436
- return new Promise((resolve, reject) => {
11437
- let settled = false;
11438
- const cleanup = () => {
11439
- window.removeEventListener("message", onMessage);
11440
- window.clearInterval(statusTimer);
11441
- window.clearTimeout(timeout);
11442
- };
11443
- const finish = (fn) => {
11444
- if (settled) return;
11445
- settled = true;
11446
- cleanup();
11447
- fn();
11448
- };
11449
- const onMessage = (event) => {
11450
- if (!isTrustedAuthOrigin(event.origin, backendOrigin)) return;
11451
- const data = event.data;
11452
- if (!data || data.type !== AUTH_MESSAGE_TYPE) return;
11453
- if (!data.ok || !data.accessToken) {
11454
- finish(() => reject(new Error(data.error || "Social login failed.")));
11455
- return;
11456
- }
11457
- finish(() => resolve({
11458
- accessToken: data.accessToken,
11459
- isNewUser: Boolean(data.isNewUser),
11460
- signedInAt: Date.now()
11461
- }));
11462
- };
11463
- const handleAuthPayload = (data) => {
11464
- if (!data.ok || !data.accessToken) {
11465
- finish(() => reject(new Error(data.error || "Social login failed.")));
11466
- return;
11467
- }
11468
- finish(() => resolve({
11469
- accessToken: data.accessToken,
11470
- isNewUser: Boolean(data.isNewUser),
11471
- signedInAt: Date.now()
11472
- }));
11473
- };
11474
- const statusTimer = window.setInterval(() => {
11475
- readAuthStatus(statusUrl).then((data) => {
11476
- if (data) handleAuthPayload(data);
11477
- }).catch(() => {
11478
- });
11479
- }, POLL_INTERVAL_MS);
11480
- const timeout = window.setTimeout(() => {
11481
- finish(() => reject(new Error("Login did not finish. Please close the sign-in window and try again.")));
11482
- }, POPUP_TIMEOUT_MS);
11483
- window.addEventListener("message", onMessage);
11484
- });
11485
- }
11486
- function endpoint(apiUrl) {
11487
- return `${getApiUrl(apiUrl).replace(/\/$/, "")}/api/sdk/v1/profiles`;
11488
- }
11489
- function normalizeStore(data) {
11490
- return {
11491
- profiles: Array.isArray(data.profiles) ? data.profiles : [],
11492
- activeProfileId: data.activeProfileId ?? null
11493
- };
11494
- }
11495
- async function parseResponse(response) {
11496
- const data = await response.json().catch(() => ({}));
11497
- if (!response.ok) {
11498
- const message = typeof data.message === "string" ? data.message : "Profile sync failed.";
11499
- throw new Error(message);
11500
- }
11501
- return data;
11502
- }
11503
- async function fetchRemoteProfiles(apiUrl, accessToken) {
11504
- const response = await fetch(endpoint(apiUrl), {
11505
- method: "GET",
11506
- headers: { Authorization: `Bearer ${accessToken}` }
11507
- });
11508
- return normalizeStore(await parseResponse(response));
11509
- }
11510
- async function saveRemoteProfiles(apiUrl, accessToken, profiles, activeProfileId) {
11511
- const response = await fetch(endpoint(apiUrl), {
11512
- method: "PUT",
11513
- headers: {
11514
- Authorization: `Bearer ${accessToken}`,
11515
- "Content-Type": "application/json"
11516
- },
11517
- body: JSON.stringify({ profiles, activeProfileId })
11518
- });
11519
- return normalizeStore(await parseResponse(response));
11520
- }
11521
11587
  function normalizeProfilePhotoSource(value) {
11522
11588
  if (!value) return null;
11523
11589
  if (/^https?:\/\//i.test(value)) return value;
@@ -12239,8 +12305,9 @@ const STYLES = `
12239
12305
  align-self: stretch;
12240
12306
  height: 100%;
12241
12307
  justify-content: flex-start;
12242
- gap: 0.55vw;
12243
- padding-bottom: clamp(8px, 0.72vw, 14px);
12308
+ gap: clamp(8px, 0.48vw, 12px);
12309
+ padding-bottom: clamp(4px, 0.35vw, 8px);
12310
+ overflow: hidden;
12244
12311
  }
12245
12312
  .ps-tryon-v2-result-panel .ps-tryon-v2-sep {
12246
12313
  margin-bottom: 0;
@@ -12250,16 +12317,17 @@ const STYLES = `
12250
12317
  min-height: 0;
12251
12318
  }
12252
12319
  .ps-tryon-v2-result-panel .ps-tryon-photo-strip {
12253
- flex: 0 0 auto;
12320
+ flex: 1 1 auto;
12254
12321
  min-height: 0;
12255
- margin-top: clamp(10px, 0.75vw, 14px);
12256
- margin-bottom: clamp(8px, 0.7vw, 12px);
12322
+ margin-top: clamp(18px, 1.25vw, 26px);
12323
+ margin-bottom: clamp(4px, 0.35vw, 8px);
12324
+ overflow: hidden;
12257
12325
  }
12258
12326
  .ps-tryon-v2-result-panel .ps-tryon-sr-card-v2 {
12259
- min-height: clamp(140px, 10.5vw, 165px);
12327
+ min-height: clamp(118px, 8.6vw, 142px);
12260
12328
  }
12261
12329
  .ps-tryon-v2-result-panel .ps-tryon-sr-card-v2.ps-full {
12262
- min-height: clamp(140px, 10.5vw, 165px);
12330
+ min-height: clamp(118px, 8.6vw, 142px);
12263
12331
  }
12264
12332
  .ps-tryon-v2-result-panel .ps-tryon-photo-strip-cell {
12265
12333
  aspect-ratio: 1 / 1;
@@ -12270,10 +12338,33 @@ const STYLES = `
12270
12338
  align-items: center;
12271
12339
  justify-content: space-between;
12272
12340
  margin-top: auto;
12273
- padding-top: clamp(8px, 0.65vw, 12px);
12274
- padding-bottom: 0;
12341
+ padding-top: clamp(6px, 0.45vw, 10px);
12342
+ padding-bottom: clamp(2px, 0.25vw, 6px);
12275
12343
  gap: 0.5vw;
12276
12344
  flex-shrink: 0;
12345
+ width: 100%;
12346
+ min-height: clamp(42px, 3.1vw, 52px);
12347
+ box-sizing: border-box;
12348
+ border-top: 1px solid rgba(15,23,42,0.06);
12349
+ }
12350
+ .ps-tryon-v2-result-actions > .ps-tryon-v2-action-group {
12351
+ flex: 0 1 min(26vw, 390px);
12352
+ min-width: 0;
12353
+ max-width: min(100%, 390px);
12354
+ margin-left: auto;
12355
+ }
12356
+ .ps-tryon-v2-result-actions .ps-tryon-v2-cta {
12357
+ flex: 1 1 0;
12358
+ min-width: 0;
12359
+ min-height: clamp(38px, 2.55vw, 44px);
12360
+ padding: 0 clamp(10px, 0.75vw, 14px);
12361
+ }
12362
+ .ps-tryon-v2-result-actions > .ps-tryon-v2-cta {
12363
+ flex: 0 1 min(18vw, 240px);
12364
+ margin-left: auto;
12365
+ }
12366
+ .ps-tryon-v2-result-actions > .ps-tryon-v2-action-group .ps-tryon-v2-cta {
12367
+ flex: 1 1 0;
12277
12368
  }
12278
12369
  @keyframes ps-v2-fade {
12279
12370
  0% { opacity: 0; }
@@ -12417,12 +12508,12 @@ const STYLES = `
12417
12508
 
12418
12509
  /* CTA button */
12419
12510
  .ps-tryon-v2-cta {
12420
- margin-top: 0.8vw; padding: 0.65vw 1.5vw;
12421
- width: auto; min-width: 12vw; display: flex; align-items: center; justify-content: center; gap: 0.4vw;
12511
+ margin-top: 0.8vw; padding: 0.55vw 1.05vw;
12512
+ width: auto; min-width: 9.2vw; min-height: 2.35vw; display: flex; align-items: center; justify-content: center; gap: 0.35vw;
12422
12513
  background: var(--ps-accent); color: #fff;
12423
- border: none; border-radius: 0.35vw;
12424
- font-size: 0.72vw; font-weight: 700; font-family: inherit;
12425
- letter-spacing: 0.12em; text-transform: uppercase;
12514
+ border: none; border-radius: 0.42vw;
12515
+ font-size: clamp(10px, 0.64vw, 12px); font-weight: 750; font-family: inherit;
12516
+ letter-spacing: 0.07em; text-transform: uppercase;
12426
12517
  cursor: pointer; transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
12427
12518
  flex-shrink: 0;
12428
12519
  }
@@ -12433,6 +12524,98 @@ const STYLES = `
12433
12524
  transform: translateY(-1px);
12434
12525
  }
12435
12526
  .ps-tryon-v2-cta svg { width: 0.8vw; height: 0.8vw; stroke: currentColor; }
12527
+ .ps-tryon-v2-action-group {
12528
+ display: flex;
12529
+ align-items: center;
12530
+ justify-content: flex-end;
12531
+ gap: clamp(8px, 0.55vw, 12px);
12532
+ min-width: 0;
12533
+ }
12534
+ .ps-tryon-v2-action-group-history {
12535
+ flex: 0 0 auto !important;
12536
+ width: auto !important;
12537
+ max-width: none !important;
12538
+ }
12539
+ .ps-tryon-v2-cta-compact,
12540
+ .ps-tryon-v2-history-product-cta {
12541
+ flex: 0 0 auto !important;
12542
+ width: auto !important;
12543
+ min-width: 0 !important;
12544
+ min-height: clamp(34px, 2.25vw, 40px) !important;
12545
+ padding: 0 clamp(10px, 0.75vw, 14px) !important;
12546
+ letter-spacing: 0.03em;
12547
+ text-transform: none;
12548
+ font-weight: 750;
12549
+ }
12550
+ .ps-tryon-v2-history-product-cta {
12551
+ justify-content: center;
12552
+ }
12553
+ .ps-tryon-v2-add-bag-cta svg,
12554
+ .ps-tryon-v2-history-product-cta svg {
12555
+ flex: 0 0 auto;
12556
+ width: clamp(16px, 1vw, 18px);
12557
+ height: clamp(16px, 1vw, 18px);
12558
+ stroke-width: 2.1;
12559
+ }
12560
+ .ps-tryon-v2-add-bag-cta.is-added {
12561
+ background: #16a34a;
12562
+ color: #fff;
12563
+ }
12564
+ .ps-tryon-v2-add-bag-cta.is-added:disabled {
12565
+ opacity: 1;
12566
+ cursor: default;
12567
+ }
12568
+ .ps-tryon-v2-add-bag-cta.is-added svg {
12569
+ animation: ps-added-check 0.42s cubic-bezier(0.16, 1, 0.3, 1);
12570
+ }
12571
+ @keyframes ps-added-check {
12572
+ 0% { transform: scale(0.45); opacity: 0; }
12573
+ 55% { transform: scale(1.18); opacity: 1; }
12574
+ 100% { transform: scale(1); opacity: 1; }
12575
+ }
12576
+ .ps-tryon-v2-cta-secondary {
12577
+ background: #FFFFFF;
12578
+ color: var(--ps-accent);
12579
+ border: 1px solid rgba(33,84,239,0.38);
12580
+ box-shadow: none;
12581
+ }
12582
+ .ps-tryon-v2-cta-secondary:hover {
12583
+ background: rgba(33,84,239,0.06);
12584
+ color: var(--ps-accent);
12585
+ border-color: var(--ps-accent);
12586
+ box-shadow: 0 0.25vw 1vw rgba(33,84,239,0.12);
12587
+ }
12588
+ @media (max-width: 768px) {
12589
+ .ps-tryon-v2-action-group {
12590
+ width: 100%;
12591
+ gap: 8px;
12592
+ }
12593
+ .ps-tryon-v2-action-group-history {
12594
+ width: auto !important;
12595
+ margin-left: auto;
12596
+ }
12597
+ .ps-tryon-v2-action-group .ps-tryon-v2-cta,
12598
+ .ps-msr-commerce-row > .ps-tryon-v2-cta {
12599
+ flex: 1 1 0;
12600
+ min-width: 0;
12601
+ padding: 11px 12px;
12602
+ border-radius: 10px;
12603
+ font-size: 11px;
12604
+ letter-spacing: 0.08em;
12605
+ white-space: nowrap;
12606
+ }
12607
+ .ps-tryon-v2-action-group-history .ps-tryon-v2-cta {
12608
+ flex: 0 0 auto !important;
12609
+ width: auto !important;
12610
+ padding: 10px 12px !important;
12611
+ letter-spacing: 0.02em;
12612
+ }
12613
+ .ps-tryon-v2-add-bag-cta svg,
12614
+ .ps-tryon-v2-history-product-cta svg {
12615
+ width: 17px;
12616
+ height: 17px;
12617
+ }
12618
+ }
12436
12619
 
12437
12620
  /* ── Size result card rows (split layout) ── */
12438
12621
  .ps-tryon-sr-cards-stack {
@@ -12515,39 +12698,132 @@ const STYLES = `
12515
12698
  flex: 1 1 45%; max-width: 49%;
12516
12699
  display: flex; flex-direction: column; align-items: center; justify-content: center;
12517
12700
  text-align: center;
12518
- background: rgba(0,0,0,0.02); border: 1px solid rgba(0,0,0,0.06);
12519
- border-radius: 0.6vw; padding: 1vw 0.5vw;
12701
+ background: linear-gradient(180deg, #FFFFFF 0%, #FBFCFF 100%);
12702
+ border: 1px solid rgba(15,23,42,0.08);
12703
+ border-radius: clamp(12px, 0.72vw, 14px); padding: clamp(14px, 0.82vw, 18px);
12520
12704
  cursor: pointer; font-family: inherit;
12521
12705
  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
12522
12706
  animation: ps-card-in 0.4s cubic-bezier(0.16, 1, 0.3, 1) forwards;
12523
12707
  opacity: 0; overflow: hidden; position: relative;
12524
12708
  min-height: 7vw;
12525
12709
  }
12526
- .ps-tryon-sr-card-v2.ps-full { flex: 1 1 100%; max-width: 100%; min-height: 5vw; padding: 0.8vw; }
12710
+ .ps-tryon-sr-card-v2::after {
12711
+ content: "";
12712
+ position: absolute;
12713
+ inset: 0;
12714
+ border-radius: inherit;
12715
+ pointer-events: none;
12716
+ background: radial-gradient(circle at 50% 0%, rgba(33,84,239,0.08), transparent 38%);
12717
+ opacity: 0.6;
12718
+ }
12719
+ .ps-tryon-sr-card-v2.ps-full { flex: 1 1 100%; max-width: 100%; min-height: 5vw; padding: clamp(14px, 0.82vw, 18px); }
12720
+ .ps-tryon-sr-card-v2.ps-summary-card {
12721
+ align-items: stretch;
12722
+ justify-content: center;
12723
+ text-align: left;
12724
+ min-height: clamp(112px, 7.4vw, 132px);
12725
+ padding: clamp(18px, 1.12vw, 24px) clamp(20px, 1.3vw, 28px);
12726
+ }
12527
12727
  .ps-tryon-sr-card-v2:hover {
12528
12728
  border-color: var(--ps-accent);
12529
- background: rgba(33,84,239,0.06);
12729
+ background: linear-gradient(180deg, #FFFFFF 0%, rgba(33,84,239,0.045) 100%);
12530
12730
  transform: translateY(-2px);
12531
- box-shadow: 0 0.4vw 1.5vw rgba(0,0,0,0.08);
12731
+ box-shadow: 0 0.45vw 1.4vw rgba(15,23,42,0.08);
12532
12732
  }
12533
12733
  .ps-tryon-sr-card-v2-text {
12534
- display: flex; flex-direction: column; align-items: center; gap: 0.15vw; z-index: 1;
12734
+ display: flex; flex-direction: column; align-items: center; gap: clamp(5px, 0.22vw, 7px); z-index: 1;
12735
+ }
12736
+ .ps-summary-card-layout {
12737
+ width: 100%;
12738
+ display: grid;
12739
+ grid-template-columns: minmax(0, 1fr) auto;
12740
+ grid-template-areas: "copy action";
12741
+ align-items: center;
12742
+ column-gap: clamp(18px, 1.25vw, 28px);
12743
+ row-gap: 0;
12744
+ }
12745
+ .ps-summary-card-copy {
12746
+ grid-area: copy;
12747
+ display: flex;
12748
+ flex-direction: column;
12749
+ align-items: flex-start;
12750
+ justify-content: center;
12751
+ min-width: 0;
12752
+ gap: clamp(8px, 0.48vw, 12px);
12753
+ }
12754
+ .ps-tryon-sr-card-v2-heading {
12755
+ grid-area: heading;
12756
+ display: flex;
12757
+ align-items: center;
12758
+ gap: clamp(8px, 0.55vw, 12px);
12759
+ min-width: 0;
12760
+ }
12761
+ .ps-tryon-sr-card-v2-main {
12762
+ display: flex;
12763
+ align-items: center;
12764
+ justify-content: flex-start;
12765
+ gap: clamp(9px, 0.6vw, 14px);
12766
+ min-width: 0;
12767
+ }
12768
+ .ps-summary-card-layout .ps-tryon-sr-card-v2-open-pill {
12769
+ grid-area: action;
12770
+ margin-top: 0;
12771
+ white-space: nowrap;
12772
+ }
12773
+ .ps-tryon-sr-card-v2-summary-title {
12774
+ font-size: clamp(11px, 0.66vw, 12px);
12775
+ font-weight: 760;
12776
+ color: rgba(15,23,42,0.56);
12777
+ letter-spacing: 0.06em;
12778
+ text-transform: uppercase;
12779
+ line-height: 1.2;
12780
+ margin-bottom: clamp(2px, 0.08vw, 4px);
12781
+ }
12782
+ .ps-summary-card-layout .ps-tryon-sr-card-v2-summary-title {
12783
+ margin-bottom: 0;
12784
+ white-space: nowrap;
12785
+ color: rgba(15,23,42,0.58);
12786
+ font-size: clamp(11px, 0.66vw, 12px);
12787
+ font-weight: 780;
12788
+ letter-spacing: 0.12em;
12789
+ text-transform: uppercase;
12790
+ }
12791
+ .ps-tryon-sr-card-v2-summary-subtitle {
12792
+ font-size: clamp(10px, 0.56vw, 11px);
12793
+ font-weight: 400;
12794
+ color: rgba(0,0,0,0.32);
12795
+ letter-spacing: 0.02em;
12796
+ line-height: 1.25;
12797
+ text-transform: none;
12798
+ margin-bottom: 0.35vw;
12535
12799
  }
12536
12800
  .ps-tryon-sr-card-v2-label {
12537
- font-size: 0.65vw; font-weight: 600; color: var(--ps-text-secondary);
12538
- text-transform: uppercase; letter-spacing: 0.1em;
12801
+ font-size: clamp(10px, 0.56vw, 11px); font-weight: 650; color: rgba(15,23,42,0.58);
12802
+ text-transform: uppercase; letter-spacing: 0.08em;
12539
12803
  display: inline-flex; align-items: center; gap: 0.5vw;
12540
12804
  }
12805
+ .ps-summary-card-layout .ps-tryon-sr-card-v2-label {
12806
+ min-width: 0;
12807
+ overflow: hidden;
12808
+ text-overflow: ellipsis;
12809
+ white-space: nowrap;
12810
+ }
12541
12811
  .ps-tryon-sr-card-v2-label-icon {
12542
12812
  width: 4.8vw; height: 4.8vw; object-fit: contain;
12543
12813
  opacity: 1;
12544
12814
  }
12545
12815
  .ps-tryon-sr-card-v2-value {
12546
- font-size: 2.2vw; font-weight: 200; color: var(--ps-text-primary);
12816
+ font-size: clamp(30px, 2.18vw, 38px); font-weight: 260; color: var(--ps-text-primary);
12547
12817
  line-height: 1; letter-spacing: -0.02em;
12548
12818
  overflow-wrap: anywhere;
12549
12819
  }
12550
- .ps-tryon-sr-card-v2.ps-full .ps-tryon-sr-card-v2-value { font-size: 1.8vw; }
12820
+ .ps-tryon-sr-card-v2.ps-full .ps-tryon-sr-card-v2-value { font-size: clamp(30px, 2vw, 36px); }
12821
+ .ps-summary-card-layout .ps-tryon-sr-card-v2-value {
12822
+ flex: 0 1 auto;
12823
+ font-size: clamp(38px, 2.55vw, 48px);
12824
+ min-width: 0;
12825
+ text-align: left;
12826
+ }
12551
12827
  /* Long combined labels ("MISSY 12 / Standard", "PLUS 16W / Extra Length")
12552
12828
  overflow the card at 2vw. Drop to ~1.3vw whenever the label is more
12553
12829
  than ~12 chars so the whole thing fits on one line. */
@@ -12566,13 +12842,19 @@ const STYLES = `
12566
12842
  }
12567
12843
  .ps-tryon-sr-card-v2-rec-pill {
12568
12844
  align-self: center;
12569
- font-size: 0.55vw; font-weight: 700; color: var(--ps-accent);
12570
- text-transform: uppercase; letter-spacing: 0.08em;
12845
+ font-size: clamp(9px, 0.52vw, 10px); font-weight: 780; color: var(--ps-accent);
12846
+ text-transform: uppercase; letter-spacing: 0.07em;
12571
12847
  background: rgba(33, 84, 239, 0.10);
12572
12848
  border: 1px solid rgba(33, 84, 239, 0.18);
12573
12849
  border-radius: 2vw;
12574
- padding: 0.18vw 0.6vw;
12575
- margin-top: 0.3vw;
12850
+ padding: clamp(3px, 0.18vw, 4px) clamp(9px, 0.58vw, 12px);
12851
+ margin-top: clamp(2px, 0.12vw, 4px);
12852
+ }
12853
+ .ps-summary-card-layout .ps-tryon-sr-card-v2-rec-pill {
12854
+ align-self: center;
12855
+ margin-top: 0;
12856
+ white-space: nowrap;
12857
+ background: #fff;
12576
12858
  }
12577
12859
  .ps-tryon-sr-card-v2-rec-pill.is-overridden {
12578
12860
  color: #b45309;
@@ -12581,10 +12863,10 @@ const STYLES = `
12581
12863
  }
12582
12864
  .ps-tryon-sr-card-v2-view {
12583
12865
  align-self: center;
12584
- margin-top: 0.4vw;
12585
- font-size: 0.62vw; font-weight: 600;
12866
+ margin-top: clamp(2px, 0.18vw, 5px);
12867
+ font-size: clamp(10px, 0.58vw, 11px); font-weight: 700;
12586
12868
  color: var(--ps-accent);
12587
- text-transform: uppercase; letter-spacing: 0.06em;
12869
+ text-transform: none; letter-spacing: 0.02em;
12588
12870
  display: inline-flex; align-items: center; justify-content: center; gap: 0.2vw;
12589
12871
  transition: gap 0.2s ease;
12590
12872
  }
@@ -12595,6 +12877,60 @@ const STYLES = `
12595
12877
  font-size: 0.85vw; line-height: 1; color: var(--ps-accent);
12596
12878
  transform: translateY(-0.05vw);
12597
12879
  }
12880
+ .ps-tryon-sr-card-v2-open-pill {
12881
+ margin-top: clamp(4px, 0.26vw, 7px);
12882
+ display: inline-flex;
12883
+ align-items: center;
12884
+ justify-content: center;
12885
+ gap: clamp(4px, 0.25vw, 6px);
12886
+ min-height: clamp(26px, 1.65vw, 32px);
12887
+ padding: 0 clamp(10px, 0.68vw, 14px);
12888
+ border-radius: 999px;
12889
+ background: #fff;
12890
+ border: 1px solid rgba(33,84,239,0.22);
12891
+ color: var(--ps-accent);
12892
+ font-size: clamp(10px, 0.58vw, 11px);
12893
+ font-weight: 760;
12894
+ letter-spacing: 0.01em;
12895
+ box-shadow: 0 0.18vw 0.8vw rgba(33,84,239,0.08);
12896
+ transition: transform 0.2s ease, border-color 0.2s ease, box-shadow 0.2s ease;
12897
+ }
12898
+ .ps-tryon-sr-card-v2-open-pill > span[aria-hidden="true"] {
12899
+ font-size: clamp(14px, 0.85vw, 16px);
12900
+ line-height: 1;
12901
+ transform: translateY(-0.03vw);
12902
+ }
12903
+ .ps-tryon-sr-card-v2:hover .ps-tryon-sr-card-v2-open-pill {
12904
+ transform: translateY(-1px);
12905
+ border-color: rgba(33,84,239,0.45);
12906
+ box-shadow: 0 0.24vw 1vw rgba(33,84,239,0.13);
12907
+ }
12908
+ @media (max-width: 768px) {
12909
+ .ps-tryon-sr-card-v2.ps-summary-card {
12910
+ min-height: 104px;
12911
+ padding: 16px;
12912
+ }
12913
+ .ps-summary-card-layout {
12914
+ grid-template-columns: minmax(0, 1fr);
12915
+ grid-template-areas:
12916
+ "copy"
12917
+ "action";
12918
+ row-gap: 12px;
12919
+ align-items: stretch;
12920
+ }
12921
+ .ps-summary-card-layout .ps-tryon-sr-card-v2-main {
12922
+ width: 100%;
12923
+ justify-content: space-between;
12924
+ gap: 12px;
12925
+ }
12926
+ .ps-summary-card-layout .ps-tryon-sr-card-v2-value {
12927
+ font-size: 34px;
12928
+ }
12929
+ .ps-summary-card-layout .ps-tryon-sr-card-v2-open-pill {
12930
+ width: 100%;
12931
+ min-height: 38px;
12932
+ }
12933
+ }
12598
12934
  .ps-tryon-sr-card-v2-img { display: none; }
12599
12935
  .ps-tryon-sr-card-v2-icon {
12600
12936
  position: absolute; bottom: 0.35vw; right: 0.45vw;
@@ -16583,6 +16919,87 @@ const STYLES = `
16583
16919
  }
16584
16920
  .ps-bp-image-remove:hover { background: rgba(0,0,0,0.8); }
16585
16921
 
16922
+ .ps-bp-photo-help-chip {
16923
+ position: absolute;
16924
+ top: clamp(8px, 0.65vw, 12px);
16925
+ left: clamp(8px, 0.65vw, 12px);
16926
+ z-index: 3;
16927
+ display: inline-flex;
16928
+ align-items: center;
16929
+ gap: clamp(5px, 0.35vw, 7px);
16930
+ max-width: calc(100% - clamp(58px, 4.2vw, 78px));
16931
+ padding: clamp(5px, 0.38vw, 7px) clamp(8px, 0.62vw, 12px);
16932
+ border: 1px solid rgba(33, 84, 239, 0.22);
16933
+ border-radius: 999px;
16934
+ background: rgba(255, 255, 255, 0.92);
16935
+ color: var(--ps-accent);
16936
+ box-shadow: 0 8px 20px -16px rgba(17, 24, 39, 0.35);
16937
+ backdrop-filter: blur(8px);
16938
+ -webkit-backdrop-filter: blur(8px);
16939
+ font-family: inherit;
16940
+ font-size: clamp(10px, 0.6vw, 12px);
16941
+ font-weight: 800;
16942
+ letter-spacing: 0.04em;
16943
+ line-height: 1;
16944
+ white-space: nowrap;
16945
+ cursor: pointer;
16946
+ transition: background 0.15s, color 0.15s, border-color 0.15s;
16947
+ }
16948
+ .ps-bp-photo-help-chip.ps-active {
16949
+ background: var(--ps-accent);
16950
+ border-color: var(--ps-accent);
16951
+ color: #FFFFFF;
16952
+ }
16953
+ .ps-bp-photo-help-chip-mark {
16954
+ display: inline-flex;
16955
+ align-items: center;
16956
+ justify-content: center;
16957
+ width: clamp(14px, 0.9vw, 16px);
16958
+ height: clamp(14px, 0.9vw, 16px);
16959
+ flex: 0 0 auto;
16960
+ border-radius: 999px;
16961
+ background: var(--ps-accent);
16962
+ color: #FFFFFF;
16963
+ font-size: clamp(10px, 0.58vw, 11px);
16964
+ font-weight: 900;
16965
+ }
16966
+ .ps-bp-photo-help-chip.ps-active .ps-bp-photo-help-chip-mark {
16967
+ background: #FFFFFF;
16968
+ color: var(--ps-accent);
16969
+ }
16970
+
16971
+ .ps-bp-photo-details-head {
16972
+ display: flex;
16973
+ align-items: center;
16974
+ justify-content: space-between;
16975
+ gap: clamp(10px, 0.8vw, 16px);
16976
+ padding: 0 0 clamp(5px, 0.35vw, 8px);
16977
+ border-bottom: 1px solid var(--ps-border-subtle);
16978
+ }
16979
+ .ps-bp-photo-details-head h3 {
16980
+ margin: 0;
16981
+ color: var(--ps-text-primary);
16982
+ font-size: clamp(13px, 0.82vw, 16px);
16983
+ font-weight: 800;
16984
+ letter-spacing: 0.01em;
16985
+ line-height: 1.1;
16986
+ }
16987
+ .ps-bp-photo-details-head-simple {
16988
+ padding-bottom: clamp(8px, 0.55vw, 12px);
16989
+ }
16990
+ .ps-bp-photo-details-head-simple h3 {
16991
+ font-size: clamp(14px, 0.9vw, 17px);
16992
+ }
16993
+ .ps-bp-system-toggle-compact {
16994
+ margin: 0;
16995
+ gap: clamp(12px, 0.85vw, 18px);
16996
+ flex-shrink: 0;
16997
+ }
16998
+ .ps-bp-system-toggle-compact .ps-bp-system-btn {
16999
+ font-size: clamp(11px, 0.66vw, 13px);
17000
+ padding: 0 0 3px;
17001
+ }
17002
+
16586
17003
  .ps-bp-root {
16587
17004
  flex: 1; min-width: 0;
16588
17005
  display: flex; flex-direction: column; gap: 0.6vw; padding: 0.2vw 0.5vw 0.3vw 0;
@@ -16611,7 +17028,7 @@ const STYLES = `
16611
17028
  to { opacity: 1; }
16612
17029
  }
16613
17030
 
16614
- /* Minimal "Using <profile> · start fresh" hint above the first input */
17031
+ /* Active profile status above body details */
16615
17032
  .ps-bp-profile-hint {
16616
17033
  margin: 0; padding: 0;
16617
17034
  text-align: center;
@@ -16631,6 +17048,98 @@ const STYLES = `
16631
17048
  cursor: pointer; padding: 0;
16632
17049
  }
16633
17050
  .ps-bp-profile-hint-link:hover { color: var(--ps-text-secondary); }
17051
+ .ps-bp-profile-card {
17052
+ display: flex;
17053
+ align-items: center;
17054
+ justify-content: space-between;
17055
+ gap: clamp(8px, 0.65vw, 14px);
17056
+ width: min(100%, 500px);
17057
+ margin: 0 auto clamp(7px, 0.55vw, 12px);
17058
+ padding: clamp(7px, 0.55vw, 11px) clamp(10px, 0.8vw, 16px);
17059
+ border: 1px solid rgba(33, 84, 239, 0.18);
17060
+ border-radius: clamp(8px, 0.7vw, 12px);
17061
+ background: linear-gradient(135deg, rgba(33, 84, 239, 0.08), rgba(255, 255, 255, 0.96));
17062
+ box-shadow: 0 10px 28px -24px rgba(33, 84, 239, 0.55);
17063
+ }
17064
+ .ps-bp-profile-card-copy {
17065
+ display: flex;
17066
+ flex-direction: column;
17067
+ gap: clamp(1px, 0.12vw, 3px);
17068
+ min-width: 0;
17069
+ }
17070
+ .ps-bp-profile-card-eyebrow {
17071
+ font-size: clamp(8px, 0.55vw, 10px);
17072
+ font-weight: 800;
17073
+ letter-spacing: 0.14em;
17074
+ text-transform: uppercase;
17075
+ color: var(--ps-accent);
17076
+ }
17077
+ .ps-bp-profile-card-copy strong {
17078
+ font-size: clamp(12px, 0.85vw, 15px);
17079
+ line-height: 1.1;
17080
+ color: var(--ps-text-primary);
17081
+ overflow: hidden;
17082
+ text-overflow: ellipsis;
17083
+ white-space: nowrap;
17084
+ }
17085
+ .ps-bp-profile-card-copy span:last-child {
17086
+ font-size: clamp(9px, 0.58vw, 11px);
17087
+ line-height: 1.25;
17088
+ color: var(--ps-text-secondary);
17089
+ }
17090
+ .ps-bp-profile-card-action {
17091
+ flex-shrink: 0;
17092
+ border: 1px solid rgba(33, 84, 239, 0.22);
17093
+ background: #FFFFFF;
17094
+ color: var(--ps-accent);
17095
+ border-radius: 999px;
17096
+ padding: clamp(6px, 0.45vw, 8px) clamp(9px, 0.7vw, 14px);
17097
+ font-family: inherit;
17098
+ font-size: clamp(9px, 0.62vw, 11px);
17099
+ font-weight: 800;
17100
+ letter-spacing: 0.08em;
17101
+ text-transform: uppercase;
17102
+ cursor: pointer;
17103
+ transition: border-color 0.15s, background 0.15s, transform 0.15s;
17104
+ }
17105
+ .ps-bp-profile-card-action:hover {
17106
+ border-color: var(--ps-accent);
17107
+ background: rgba(33, 84, 239, 0.06);
17108
+ }
17109
+ .ps-bp-profile-card-action:active { transform: scale(0.98); }
17110
+ .ps-bp-profile-card-compact {
17111
+ margin: 0 auto clamp(3px, 0.32vw, 6px);
17112
+ padding: clamp(4px, 0.34vw, 6px) clamp(8px, 0.62vw, 12px);
17113
+ border-radius: clamp(7px, 0.55vw, 10px);
17114
+ box-shadow: none;
17115
+ }
17116
+ .ps-bp-profile-card-compact .ps-bp-profile-card-copy {
17117
+ display: grid;
17118
+ grid-template-columns: auto minmax(0, 1fr);
17119
+ align-items: baseline;
17120
+ gap: 2px clamp(6px, 0.45vw, 9px);
17121
+ }
17122
+ .ps-bp-profile-card-compact .ps-bp-profile-card-eyebrow {
17123
+ grid-column: 1 / -1;
17124
+ font-size: clamp(7px, 0.46vw, 9px);
17125
+ letter-spacing: 0.16em;
17126
+ line-height: 1;
17127
+ }
17128
+ .ps-bp-profile-card-compact .ps-bp-profile-card-copy strong {
17129
+ font-size: clamp(11px, 0.72vw, 13px);
17130
+ line-height: 1.05;
17131
+ }
17132
+ .ps-bp-profile-card-compact .ps-bp-profile-card-copy span:last-child {
17133
+ font-size: clamp(8px, 0.5vw, 10px);
17134
+ line-height: 1.1;
17135
+ overflow: hidden;
17136
+ text-overflow: ellipsis;
17137
+ white-space: nowrap;
17138
+ }
17139
+ .ps-bp-profile-card-compact .ps-bp-profile-card-action {
17140
+ padding: clamp(4px, 0.3vw, 6px) clamp(7px, 0.55vw, 11px);
17141
+ font-size: clamp(8px, 0.52vw, 10px);
17142
+ }
16634
17143
 
16635
17144
  /* Typography */
16636
17145
  .ps-bp-title {
@@ -17846,6 +18355,16 @@ const STYLES = `
17846
18355
  .ps-msr-bottom-row {
17847
18356
  display: flex; gap: 8px; align-items: stretch; justify-content: flex-end;
17848
18357
  }
18358
+ .ps-msr-bottom-row.ps-msr-commerce-row {
18359
+ width: 100%;
18360
+ }
18361
+ .ps-msr-commerce-row .ps-tryon-v2-action-group {
18362
+ width: 100%;
18363
+ }
18364
+ .ps-msr-commerce-row .ps-tryon-v2-cta {
18365
+ flex: 1 1 0;
18366
+ min-width: 0;
18367
+ }
17849
18368
  .ps-msr-bottom-row .ps-msr-tryon-cta {
17850
18369
  flex: 0 0 auto; min-width: 94px; width: auto;
17851
18370
  padding: 11px 14px; font-size: 12px;
@@ -19259,6 +19778,9 @@ const STYLES = `
19259
19778
  background: var(--ps-bg-primary);
19260
19779
  flex-shrink: 0;
19261
19780
  }
19781
+ .ps-cpw-footer-no-back {
19782
+ justify-content: flex-end;
19783
+ }
19262
19784
  .ps-cpw-back-btn {
19263
19785
  background: none; border: none;
19264
19786
  color: var(--ps-text-secondary);
@@ -19902,6 +20424,7 @@ const STYLES = `
19902
20424
  display: flex; flex-direction: column;
19903
20425
  gap: max(14px, 1.2vw);
19904
20426
  min-width: 0; width: 100%;
20427
+ padding-bottom: clamp(78px, 5.4vw, 104px);
19905
20428
  }
19906
20429
 
19907
20430
  /* Basics list — height / weight / age, inline icon + label + value */
@@ -20137,12 +20660,12 @@ const STYLES = `
20137
20660
  gap: clamp(8px, 0.7vw, 14px);
20138
20661
  position: sticky;
20139
20662
  bottom: 0;
20140
- background: var(--ps-bg-primary);
20663
+ background: color-mix(in srgb, var(--ps-bg-primary) 96%, #FFFFFF);
20141
20664
  border-top: 1px solid var(--ps-border-subtle);
20142
- padding-top: clamp(8px, 0.7vw, 14px);
20143
- padding-bottom: clamp(8px, 0.7vw, 14px);
20144
- z-index: 2;
20665
+ padding: clamp(10px, 0.8vw, 16px) clamp(4px, 0.35vw, 8px) calc(clamp(10px, 0.8vw, 16px) + env(safe-area-inset-bottom, 0px));
20666
+ z-index: 5;
20145
20667
  margin-top: auto;
20668
+ box-shadow: 0 -14px 30px -28px rgba(17, 24, 39, 0.35);
20146
20669
  }
20147
20670
  .ps-pmv-actions-right {
20148
20671
  display: flex; align-items: center;
@@ -20154,7 +20677,7 @@ const STYLES = `
20154
20677
  background: none;
20155
20678
  border: 1px solid var(--ps-border-color);
20156
20679
  border-radius: clamp(4px, 0.35vw, 8px);
20157
- padding: clamp(6px, 0.55vw, 12px) clamp(10px, 0.9vw, 20px);
20680
+ padding: clamp(6px, 0.55vw, 12px) clamp(13px, 1.05vw, 24px);
20158
20681
  font-family: inherit;
20159
20682
  font-size: clamp(9px, 0.65vw, 12px);
20160
20683
  font-weight: 600;
@@ -20176,7 +20699,7 @@ const STYLES = `
20176
20699
  background: var(--ps-accent); color: #FFFFFF;
20177
20700
  border: none;
20178
20701
  border-radius: clamp(4px, 0.35vw, 8px);
20179
- padding: clamp(7px, 0.65vw, 14px) clamp(12px, 1vw, 22px);
20702
+ padding: clamp(7px, 0.65vw, 14px) clamp(15px, 1.15vw, 26px);
20180
20703
  font-family: inherit;
20181
20704
  font-size: clamp(9px, 0.65vw, 12px);
20182
20705
  font-weight: 700;
@@ -20272,6 +20795,14 @@ const STYLES = `
20272
20795
  opacity: 0.6;
20273
20796
  cursor: default;
20274
20797
  }
20798
+ .ps-msd-result-action-group {
20799
+ flex: 1 1 0;
20800
+ justify-content: flex-end;
20801
+ }
20802
+ .ps-msd-result-action-group .ps-tryon-v2-cta {
20803
+ flex: 1 1 0;
20804
+ min-width: 0;
20805
+ }
20275
20806
 
20276
20807
  /* RECOMMENDED SIZE card */
20277
20808
  .ps-msd-card {
@@ -20548,6 +21079,14 @@ const STYLES = `
20548
21079
  display: flex; flex-direction: column; gap: 0.6vw;
20549
21080
  z-index: 5;
20550
21081
  }
21082
+ .ps-bp-photo-help-upload {
21083
+ top: clamp(46px, 3.2vw, 58px);
21084
+ left: clamp(12px, 0.85vw, 16px);
21085
+ right: auto;
21086
+ width: min(360px, calc(100% - clamp(24px, 1.7vw, 32px)));
21087
+ max-height: calc(100% - clamp(64px, 4.5vw, 82px));
21088
+ overflow-y: auto;
21089
+ }
20551
21090
  .ps-bp-photo-help-handle { display: none; }
20552
21091
  .ps-bp-photo-help-header { display: flex; align-items: center; justify-content: space-between; }
20553
21092
  .ps-bp-photo-help-title { font-size: 0.8vw; font-weight: 700; color: var(--ps-text-primary); }
@@ -21299,6 +21838,21 @@ function UserIcon({ size = 16 }) {
21299
21838
  /* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "12", cy: "7", r: "4" })
21300
21839
  ] });
21301
21840
  }
21841
+ function ShoppingBagIcon({ size = 16 }) {
21842
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round", children: [
21843
+ /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M6 7h12l-1 14H7L6 7Z" }),
21844
+ /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M9 7a3 3 0 0 1 6 0" }),
21845
+ /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M12 12v5" }),
21846
+ /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M9.5 14.5h5" })
21847
+ ] });
21848
+ }
21849
+ function ExternalLinkIcon({ size = 16 }) {
21850
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round", children: [
21851
+ /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M14 3h7v7" }),
21852
+ /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M10 14 21 3" }),
21853
+ /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M21 14v5a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5" })
21854
+ ] });
21855
+ }
21302
21856
  function ClockIcon({ size = 16 }) {
21303
21857
  return /* @__PURE__ */ jsxRuntimeExports.jsxs("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round", children: [
21304
21858
  /* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "12", cy: "12", r: "10" }),
@@ -21824,7 +22378,7 @@ function WelcomeView({
21824
22378
  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-tryon-welcome-sparkle", children: /* @__PURE__ */ jsxRuntimeExports.jsx(SparkleIcon, { size: 20 }) })
21825
22379
  ] }),
21826
22380
  /* @__PURE__ */ jsxRuntimeExports.jsx("h2", { className: "ps-tryon-welcome-title", children: t2("See Your Fit") }),
21827
- /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "ps-tryon-welcome-sub", children: t2("Get the perfect fit, then try it on virtually") })
22381
+ /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "ps-tryon-welcome-sub", children: t2("Check your size, then try it on virtually") })
21828
22382
  ] }),
21829
22383
  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-tryon-features", children: [
21830
22384
  { icon: /* @__PURE__ */ jsxRuntimeExports.jsx(RulerIcon$1, { size: 22 }), title: t2("Get Your Size"), desc: t2("Instant fit recommendation") },
@@ -22155,7 +22709,7 @@ function MobileScanningView({
22155
22709
  { title: t2("FINALIZING RESULT"), desc: t2("Almost done — preparing your recommendation."), viewfinderText: t2("FINALIZING") }
22156
22710
  ] : [
22157
22711
  { title: t2("DETECTING POSE"), desc: t2("Identifying body landmarks from your photo."), viewfinderText: t2("DETECTING POSE") },
22158
- { title: t2("SCANNING FRAME"), desc: t2("Our AI is mapping your proportions to calculate the perfect fit."), viewfinderText: t2("SCANNING FRAME") },
22712
+ { title: t2("SCANNING FRAME"), desc: t2("Our AI is mapping your proportions for a size recommendation."), viewfinderText: t2("SCANNING FRAME") },
22159
22713
  { title: t2("ANALYZING BODY"), desc: t2("Measuring shoulders, chest, waist and hips."), viewfinderText: t2("ANALYZING") },
22160
22714
  { title: t2("MATCHING SIZE"), desc: t2("Comparing your measurements to the size guide."), viewfinderText: t2("MATCHING SIZE") },
22161
22715
  { title: t2("FINALIZING RESULT"), desc: t2("Almost done — preparing your recommendation."), viewfinderText: t2("FINALIZING") }
@@ -22325,6 +22879,7 @@ function MultiSectionMobile({
22325
22879
  tryOnDone,
22326
22880
  onTryAgain,
22327
22881
  onClose,
22882
+ resultActionNode,
22328
22883
  overlayNode,
22329
22884
  showLines,
22330
22885
  onToggleLines,
@@ -22400,7 +22955,7 @@ function MultiSectionMobile({
22400
22955
  }) }),
22401
22956
  profileCompletionCta
22402
22957
  ] }),
22403
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-msr-bottom", children: tryOnDone ? /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-msr-bottom-row", children: [
22958
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-msr-bottom", children: resultActionNode ? /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-msr-bottom-row ps-msr-commerce-row", children: resultActionNode }) : tryOnDone ? /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-msr-bottom-row", children: [
22404
22959
  /* @__PURE__ */ jsxRuntimeExports.jsx(
22405
22960
  "button",
22406
22961
  {
@@ -22504,7 +23059,7 @@ function ProfileCompletionCta({
22504
23059
  border: "1px solid rgba(33, 84, 239, 0.16)",
22505
23060
  background: "linear-gradient(135deg, #FFFFFF 0%, rgba(33,84,239,0.055) 100%)",
22506
23061
  borderRadius: isMobile ? 12 : "0.7vw",
22507
- padding: isMobile ? "13px 14px" : isHeader ? "0.7vw 0.9vw" : "0.58vw 0.75vw",
23062
+ padding: isMobile ? "13px 14px" : isHeader ? "clamp(8px, 0.55vw, 10px) clamp(10px, 0.7vw, 14px)" : "0.5vw 0.7vw",
22508
23063
  marginTop: isMobile ? 12 : isHeader ? 0 : "0.48vw",
22509
23064
  cursor: "pointer",
22510
23065
  fontFamily: "inherit",
@@ -22513,18 +23068,18 @@ function ProfileCompletionCta({
22513
23068
  flexDirection: isMobile ? "column" : "row",
22514
23069
  alignItems: isMobile ? "stretch" : "center",
22515
23070
  justifyContent: "space-between",
22516
- gap: isMobile ? 10 : isHeader ? "0.85vw" : "0.8vw",
23071
+ gap: isMobile ? 10 : isHeader ? "0.62vw" : "0.7vw",
22517
23072
  boxShadow: "0 12px 28px -22px rgba(33,84,239,0.52)"
22518
23073
  },
22519
23074
  children: [
22520
- /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { style: { display: "flex", alignItems: "center", gap: isMobile ? 10 : isHeader ? "0.65vw" : "0.6vw", minWidth: 0, width: isMobile || isHeader ? "100%" : "auto" }, children: [
23075
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { style: { display: "flex", alignItems: "center", gap: isMobile ? 10 : isHeader ? "0.5vw" : "0.6vw", minWidth: 0, width: isMobile || isHeader ? "100%" : "auto" }, children: [
22521
23076
  /* @__PURE__ */ jsxRuntimeExports.jsx(
22522
23077
  "span",
22523
23078
  {
22524
23079
  "aria-hidden": "true",
22525
23080
  style: {
22526
- width: isMobile ? 32 : isHeader ? "1.9vw" : "1.65vw",
22527
- height: isMobile ? 32 : isHeader ? "1.9vw" : "1.65vw",
23081
+ width: isMobile ? 32 : isHeader ? "clamp(26px, 1.65vw, 30px)" : "1.55vw",
23082
+ height: isMobile ? 32 : isHeader ? "clamp(26px, 1.65vw, 30px)" : "1.55vw",
22528
23083
  borderRadius: "50%",
22529
23084
  background: "var(--ps-accent)",
22530
23085
  color: "#fff",
@@ -22533,12 +23088,12 @@ function ProfileCompletionCta({
22533
23088
  justifyContent: "center",
22534
23089
  flexShrink: 0
22535
23090
  },
22536
- children: /* @__PURE__ */ jsxRuntimeExports.jsx(SparkleIcon, { size: isMobile ? 16 : isHeader ? 16 : 14 })
23091
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx(UserIcon, { size: isMobile ? 16 : isHeader ? 16 : 14 })
22537
23092
  }
22538
23093
  ),
22539
23094
  /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { style: { minWidth: 0 }, children: [
22540
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { style: { display: "block", color: "var(--ps-text-primary)", fontSize: isMobile ? 14 : isHeader ? "0.78vw" : "0.68vw", fontWeight: 800, lineHeight: 1.2 }, children: title }),
22541
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { style: { display: "block", color: "var(--ps-text-secondary)", fontSize: isMobile ? 12 : isHeader ? "0.58vw" : "0.56vw", lineHeight: 1.32, marginTop: isMobile ? 3 : "0.12vw" }, children: body })
23095
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { style: { display: "block", color: "var(--ps-text-primary)", fontSize: isMobile ? 14 : isHeader ? "clamp(12px, 0.72vw, 14px)" : "0.68vw", fontWeight: 800, lineHeight: 1.15 }, children: title }),
23096
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { style: { display: "block", color: "var(--ps-text-secondary)", fontSize: isMobile ? 12 : isHeader ? "clamp(10px, 0.52vw, 11px)" : "0.56vw", lineHeight: 1.22, marginTop: isMobile ? 3 : "0.1vw" }, children: body })
22542
23097
  ] })
22543
23098
  ] }),
22544
23099
  /* @__PURE__ */ jsxRuntimeExports.jsxs(
@@ -22550,7 +23105,7 @@ function ProfileCompletionCta({
22550
23105
  border: isMobile ? "1px solid rgba(33,84,239,0.14)" : 0,
22551
23106
  borderRadius: isMobile ? 999 : 0,
22552
23107
  padding: isMobile ? "7px 10px" : 0,
22553
- fontSize: isMobile ? 12 : isHeader ? "0.64vw" : "0.62vw",
23108
+ fontSize: isMobile ? 12 : isHeader ? "clamp(10px, 0.56vw, 11px)" : "0.62vw",
22554
23109
  fontWeight: 800,
22555
23110
  whiteSpace: "nowrap",
22556
23111
  flexShrink: 0,
@@ -23168,10 +23723,10 @@ const cellValFn = (row, colIdx, header) => {
23168
23723
  }
23169
23724
  return "";
23170
23725
  };
23171
- const fitLabelFn = (fit, t2) => fit === "good" ? t2("perfect fit") : fit === "too-tight" ? t2("too tight") : fit === "tight" ? t2("tight") : fit === "a-bit-tight" ? t2("a bit tight") : fit === "too-loose" ? t2("too loose") : fit === "loose" ? t2("loose") : t2("a bit loose");
23726
+ const fitLabelFn = (fit, t2) => fit === "good" ? t2("within range") : fit === "too-tight" ? t2("too tight") : fit === "tight" ? t2("tight") : fit === "a-bit-tight" ? t2("a bit tight") : fit === "too-loose" ? t2("too loose") : fit === "loose" ? t2("loose") : t2("a bit loose");
23172
23727
  const accessoryFitLabelFn = (fit, t2) => fit === "good" ? t2("within range") : fitLabelFn(fit, t2);
23173
23728
  const lengthFitLabelFn = (fit, t2) => {
23174
- if (fit === "good") return t2("perfect fit");
23729
+ if (fit === "good") return t2("within range");
23175
23730
  if (fit === "too-short" || fit === "too-tight") return t2("too short");
23176
23731
  if (fit === "short" || fit === "tight") return t2("short");
23177
23732
  if (fit === "a-bit-short" || fit === "a-bit-tight") return t2("a bit short");
@@ -23249,6 +23804,7 @@ function SectionDetailView({
23249
23804
  internationalSizes,
23250
23805
  continueLabel,
23251
23806
  onContinue,
23807
+ resultActionNode,
23252
23808
  renderRaw = false,
23253
23809
  sectionFound,
23254
23810
  allSizes,
@@ -23901,7 +24457,7 @@ function SectionDetailView({
23901
24457
  tryOnProcessing ? `${t2("Generating try-on…")}${tryOnElapsedS > 0 ? ` ${tryOnElapsedS}s` : ""}` : t2("Try It On")
23902
24458
  ]
23903
24459
  }
23904
- ) : /* @__PURE__ */ jsxRuntimeExports.jsxs(
24460
+ ) : resultActionNode ? /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-tryon-v2-action-group ps-msd-result-action-group", children: resultActionNode }) : /* @__PURE__ */ jsxRuntimeExports.jsxs(
23905
24461
  "button",
23906
24462
  {
23907
24463
  type: "button",
@@ -24126,7 +24682,7 @@ function SectionDetailView({
24126
24682
  tryOnProcessing ? `${t2("Generating try-on…")}${tryOnElapsedS > 0 ? ` ${tryOnElapsedS}s` : ""}` : t2("Try It On")
24127
24683
  ]
24128
24684
  }
24129
- ) : /* @__PURE__ */ jsxRuntimeExports.jsxs(
24685
+ ) : resultActionNode ? /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-tryon-v2-action-group", children: resultActionNode }) : /* @__PURE__ */ jsxRuntimeExports.jsxs(
24130
24686
  "button",
24131
24687
  {
24132
24688
  onClick: continueLabel ? onContinue || onBack : onBack,
@@ -24172,6 +24728,12 @@ function SizeResultView({
24172
24728
  setView,
24173
24729
  handleDownload,
24174
24730
  onContinueShopping,
24731
+ isHistoryResult = false,
24732
+ onBackToProductPage,
24733
+ onAddToBag,
24734
+ addToBagLabel,
24735
+ continueShoppingLabel,
24736
+ backToProductPageLabel,
24175
24737
  onTryOnFeedbackSubmit,
24176
24738
  selectedFile,
24177
24739
  previewUrl,
@@ -24203,6 +24765,101 @@ function SizeResultView({
24203
24765
  const shoeUserGender = normalizeShoeGender(sizingResult?.userGender || sizingResult?.detectedGender) || void 0;
24204
24766
  const [editVals, setEditVals] = reactExports.useState({});
24205
24767
  const pRange = pRangeFn;
24768
+ const resolvedContinueShoppingLabel = continueShoppingLabel?.trim() || t2("Continue Shopping");
24769
+ const resolvedAddToBagLabel = addToBagLabel?.trim() || t2("Add to Bag");
24770
+ const resolvedBackToProductPageLabel = backToProductPageLabel?.trim() || t2("Back to product");
24771
+ const handleContinueAction = onContinueShopping || onClose;
24772
+ const handleBackToProductPageAction = onBackToProductPage || handleContinueAction;
24773
+ const canAddToBag = !!onAddToBag && !isHistoryResult && !!sizingResult && sizingResult.found !== false;
24774
+ const [addToBagState, setAddToBagState] = reactExports.useState("idle");
24775
+ reactExports.useEffect(() => {
24776
+ if (addToBagState !== "added") return;
24777
+ const timer = window.setTimeout(() => setAddToBagState("idle"), 1500);
24778
+ return () => window.clearTimeout(timer);
24779
+ }, [addToBagState]);
24780
+ const handleAddToBagClick = reactExports.useCallback(async () => {
24781
+ if (!onAddToBag || addToBagState !== "idle") return;
24782
+ setAddToBagState("adding");
24783
+ try {
24784
+ await onAddToBag();
24785
+ setAddToBagState("added");
24786
+ } catch {
24787
+ setAddToBagState("idle");
24788
+ }
24789
+ }, [addToBagState, onAddToBag]);
24790
+ const renderShoppingCta = reactExports.useCallback((options) => {
24791
+ if (isHistoryResult && handleBackToProductPageAction) {
24792
+ return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-tryon-v2-action-group ps-tryon-v2-action-group-history", children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
24793
+ "button",
24794
+ {
24795
+ className: "ps-tryon-v2-cta ps-tryon-v2-cta-secondary ps-tryon-v2-cta-compact ps-tryon-v2-history-product-cta",
24796
+ style: { marginTop: 0 },
24797
+ onClick: handleBackToProductPageAction,
24798
+ type: "button",
24799
+ children: [
24800
+ /* @__PURE__ */ jsxRuntimeExports.jsx(ExternalLinkIcon, { size: 13 }),
24801
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: resolvedBackToProductPageLabel })
24802
+ ]
24803
+ }
24804
+ ) });
24805
+ }
24806
+ const allowAddToBag = options?.allowAddToBag !== false;
24807
+ if (allowAddToBag && canAddToBag) {
24808
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-tryon-v2-action-group", children: [
24809
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(
24810
+ "button",
24811
+ {
24812
+ className: "ps-tryon-v2-cta ps-tryon-v2-cta-secondary",
24813
+ style: { marginTop: 0 },
24814
+ onClick: handleContinueAction,
24815
+ type: "button",
24816
+ children: [
24817
+ resolvedContinueShoppingLabel,
24818
+ " →"
24819
+ ]
24820
+ }
24821
+ ),
24822
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(
24823
+ "button",
24824
+ {
24825
+ className: `ps-tryon-v2-cta ps-tryon-v2-add-bag-cta${addToBagState === "added" ? " is-added" : ""}`,
24826
+ style: { marginTop: 0 },
24827
+ onClick: handleAddToBagClick,
24828
+ type: "button",
24829
+ disabled: addToBagState !== "idle",
24830
+ children: [
24831
+ addToBagState === "added" ? /* @__PURE__ */ jsxRuntimeExports.jsx(CheckIcon$1, { size: 16 }) : /* @__PURE__ */ jsxRuntimeExports.jsx(ShoppingBagIcon, { size: 17 }),
24832
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: addToBagState === "added" ? t2("Added to bag") : addToBagState === "adding" ? t2("Adding...") : resolvedAddToBagLabel })
24833
+ ]
24834
+ }
24835
+ )
24836
+ ] });
24837
+ }
24838
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs(
24839
+ "button",
24840
+ {
24841
+ className: "ps-tryon-v2-cta",
24842
+ style: { marginTop: 0 },
24843
+ onClick: handleContinueAction,
24844
+ type: "button",
24845
+ children: [
24846
+ resolvedContinueShoppingLabel,
24847
+ " →"
24848
+ ]
24849
+ }
24850
+ );
24851
+ }, [
24852
+ canAddToBag,
24853
+ addToBagState,
24854
+ handleBackToProductPageAction,
24855
+ handleAddToBagClick,
24856
+ handleContinueAction,
24857
+ isHistoryResult,
24858
+ resolvedAddToBagLabel,
24859
+ resolvedBackToProductPageLabel,
24860
+ resolvedContinueShoppingLabel,
24861
+ t2
24862
+ ]);
24206
24863
  const cellVal = reactExports.useCallback((row, colIdx, header) => {
24207
24864
  return cellValFn(row, colIdx, header);
24208
24865
  }, []);
@@ -24691,7 +25348,8 @@ function SizeResultView({
24691
25348
  return lengthEntries.find((le2) => le2.section.headers.some((h) => /height|altezza|estatura|\(cm\)/i.test(h))) || null;
24692
25349
  })(),
24693
25350
  onBack: () => setActiveSection(null),
24694
- onContinue: onContinueShopping || onClose,
25351
+ onContinue: handleContinueAction,
25352
+ resultActionNode: canAddToBag || isHistoryResult || !!resultImageUrl || vtoExcluded ? renderShoppingCta() : void 0,
24695
25353
  internationalSizes: entry.secResult?.internationalSizes,
24696
25354
  productImage: tryOnProcessing && previewUrl ? previewUrl : resultImageUrl || productImage,
24697
25355
  productTitle,
@@ -24791,7 +25449,8 @@ function SizeResultView({
24791
25449
  return lengthEntries.find((le2) => le2.section.headers.some((h) => /height|altezza|estatura|\(cm\)/i.test(h))) || null;
24792
25450
  })(),
24793
25451
  onBack: () => setActiveSection(null),
24794
- onContinue: onContinueShopping || onClose,
25452
+ onContinue: handleContinueAction,
25453
+ resultActionNode: canAddToBag || isHistoryResult || !!resultImageUrl || vtoExcluded ? renderShoppingCta() : void 0,
24795
25454
  internationalSizes: entry.secResult?.internationalSizes,
24796
25455
  tryOnProcessing,
24797
25456
  tryOnStartedAt,
@@ -24834,7 +25493,8 @@ function SizeResultView({
24834
25493
  setGuideFile(selectedFile || null);
24835
25494
  setShowPhotoGuide(true);
24836
25495
  },
24837
- onClose: onContinueShopping || onClose,
25496
+ onClose: handleContinueAction,
25497
+ resultActionNode: canAddToBag || isHistoryResult ? renderShoppingCta() : void 0,
24838
25498
  showLines,
24839
25499
  onToggleLines: suppressFitOverlayActions ? void 0 : () => setShowLines(!showLines),
24840
25500
  onOpenImage: resultImageUrl && !tryOnProcessing ? () => setZoomImageUrl(resultImageUrl) : void 0,
@@ -24929,7 +25589,7 @@ function SizeResultView({
24929
25589
  ] }),
24930
25590
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-tryon-v2-panel ps-tryon-v2-result-panel", children: [
24931
25591
  profileCompletionCta ? /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-tryon-v2-profile-head ps-expanded", children: /* @__PURE__ */ jsxRuntimeExports.jsx(ProfileCompletionCta, { onClick: profileCompletionCta.onClick, placement: "header", t: t2 }) }) : /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-tryon-v2-result-copy", children: [
24932
- /* @__PURE__ */ jsxRuntimeExports.jsx("h3", { className: "ps-tryon-v2-title", children: t2("Your Perfect Fit") }),
25592
+ /* @__PURE__ */ jsxRuntimeExports.jsx("h3", { className: "ps-tryon-v2-title", children: t2("Your Size Recommendation") }),
24933
25593
  /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "ps-tryon-v2-subtitle", children: t2("Tap any section for detailed breakdown") })
24934
25594
  ] }),
24935
25595
  mismatchNotice,
@@ -24978,29 +25638,7 @@ function SizeResultView({
24978
25638
  " ",
24979
25639
  t2("Back")
24980
25640
  ] }),
24981
- resultImageUrl && !tryOnProcessing ? /* @__PURE__ */ jsxRuntimeExports.jsxs(
24982
- "button",
24983
- {
24984
- className: "ps-tryon-v2-cta",
24985
- style: { marginTop: 0 },
24986
- onClick: onContinueShopping || onClose,
24987
- children: [
24988
- t2("Continue Shopping"),
24989
- " →"
24990
- ]
24991
- }
24992
- ) : vtoExcluded ? /* @__PURE__ */ jsxRuntimeExports.jsxs(
24993
- "button",
24994
- {
24995
- className: "ps-tryon-v2-cta",
24996
- style: { marginTop: 0 },
24997
- onClick: onContinueShopping || onClose,
24998
- children: [
24999
- t2("Continue Shopping"),
25000
- " →"
25001
- ]
25002
- }
25003
- ) : /* @__PURE__ */ jsxRuntimeExports.jsxs(
25641
+ canAddToBag || isHistoryResult || resultImageUrl && !tryOnProcessing || vtoExcluded ? renderShoppingCta() : /* @__PURE__ */ jsxRuntimeExports.jsxs(
25004
25642
  "button",
25005
25643
  {
25006
25644
  className: "ps-tryon-v2-cta",
@@ -25064,11 +25702,12 @@ function SizeResultView({
25064
25702
  if (resultImageUrl) onResetTryOn?.();
25065
25703
  setView("body-profile");
25066
25704
  },
25067
- onContinue: onContinueShopping || onClose,
25705
+ onContinue: handleContinueAction,
25068
25706
  backLabel: t2("Back"),
25069
25707
  internationalSizes: singleInternationalSizes,
25070
- onTryOn: resultImageUrl || vtoExcluded ? void 0 : handleSingleTryOn,
25071
- continueLabel: resultImageUrl ? t2("Done") : void 0,
25708
+ onTryOn: canAddToBag || isHistoryResult || resultImageUrl || vtoExcluded ? void 0 : handleSingleTryOn,
25709
+ resultActionNode: canAddToBag || isHistoryResult || !!resultImageUrl || vtoExcluded ? renderShoppingCta() : void 0,
25710
+ continueLabel: resultImageUrl ? resolvedContinueShoppingLabel : void 0,
25072
25711
  tryOnProcessing,
25073
25712
  tryOnStartedAt,
25074
25713
  productImage: resultImageUrl || productImage,
@@ -25158,18 +25797,14 @@ function SizeResultView({
25158
25797
  chartUnit: resultUnit,
25159
25798
  lengthEntry: null,
25160
25799
  onBack: () => {
25161
- if (resultImageUrl) {
25162
- onResetTryOn?.();
25163
- setView("body-profile");
25164
- } else {
25165
- setActiveSection(null);
25166
- }
25800
+ setActiveSection(null);
25167
25801
  },
25168
- onContinue: onContinueShopping || onClose,
25802
+ onContinue: handleContinueAction,
25169
25803
  backLabel: t2("Back"),
25170
25804
  internationalSizes: singleInternationalSizes,
25171
- onTryOn: resultImageUrl || vtoExcluded ? void 0 : handleSingleTryOn,
25172
- continueLabel: resultImageUrl ? t2("Continue Shopping") : void 0,
25805
+ onTryOn: canAddToBag || isHistoryResult || resultImageUrl || vtoExcluded ? void 0 : handleSingleTryOn,
25806
+ resultActionNode: canAddToBag || isHistoryResult || !!resultImageUrl || vtoExcluded ? renderShoppingCta() : void 0,
25807
+ continueLabel: resultImageUrl ? resolvedContinueShoppingLabel : void 0,
25173
25808
  tryOnProcessing,
25174
25809
  tryOnStartedAt,
25175
25810
  onFeedbackSubmit: onTryOnFeedbackSubmit,
@@ -25185,35 +25820,35 @@ function SizeResultView({
25185
25820
  ) : (
25186
25821
  /* CARD VIEW — clickable summary card + gallery strip */
25187
25822
  /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
25188
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-tryon-v2-result-head", children: profileCompletionCta ? /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-tryon-v2-profile-head ps-expanded", children: /* @__PURE__ */ jsxRuntimeExports.jsx(ProfileCompletionCta, { onClick: profileCompletionCta.onClick, placement: "header", t: t2 }) }) : /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-tryon-v2-result-copy", children: [
25189
- /* @__PURE__ */ jsxRuntimeExports.jsx("h3", { className: "ps-tryon-v2-title", children: guideOnlyResult ? t2("Product Size Guide") : t2("Your Perfect Fit") }),
25190
- /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "ps-tryon-v2-subtitle", children: guideOnlyResult ? t2("Tap the card to view product measurements") : t2("Tap the card for detailed breakdown") })
25191
- ] }) }),
25192
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-tryon-v2-sep" }),
25823
+ profileCompletionCta ? /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-tryon-v2-result-head", children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-tryon-v2-profile-head ps-expanded", children: /* @__PURE__ */ jsxRuntimeExports.jsx(ProfileCompletionCta, { onClick: profileCompletionCta.onClick, placement: "header", t: t2 }) }) }) : null,
25824
+ profileCompletionCta ? /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-tryon-v2-sep" }) : null,
25193
25825
  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-tryon-sr-cards-v2", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
25194
25826
  "button",
25195
25827
  {
25196
- className: `ps-tryon-sr-card-v2 ps-full${pendingCustomSizes[sectionName] ? " ps-overridden" : ""}`,
25828
+ className: `ps-tryon-sr-card-v2 ps-summary-card ps-full${pendingCustomSizes[sectionName] ? " ps-overridden" : ""}`,
25197
25829
  onClick: () => setActiveSection(sectionName),
25198
25830
  type: "button",
25199
- children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-tryon-sr-card-v2-text", children: [
25200
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ps-tryon-sr-card-v2-label", children: sectionName }),
25201
- (() => {
25202
- const rawLabelText = pendingCustomSizes[sectionName]?.displayLabel || singleResult.recommendedSize || singleResult.sizeLabel || (guideOnlyResult ? t2("One Size") : "—");
25203
- const labelText = measurementType === "foot" ? formatShoeSizeLabel(rawLabelText, shoeUserGender) : rawLabelText;
25204
- const isLong = labelText.length > 12;
25205
- return /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: `ps-tryon-sr-card-v2-value${isLong ? " ps-long" : ""}`, children: labelText });
25206
- })(),
25207
- /* @__PURE__ */ jsxRuntimeExports.jsx(
25208
- "span",
25209
- {
25210
- className: `ps-tryon-sr-card-v2-rec-pill${pendingCustomSizes[sectionName] ? " is-overridden" : ""}`,
25211
- children: guideOnlyResult ? t2("SIZE GUIDE") : pendingCustomSizes[sectionName] ? t2("YOUR SELECTION") : t2("RECOMMENDED")
25212
- }
25213
- ),
25214
- /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "ps-tryon-sr-card-v2-view", children: [
25215
- t2("VIEW DETAILS"),
25216
- " ",
25831
+ children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-tryon-sr-card-v2-text ps-summary-card-layout", children: [
25832
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "ps-summary-card-copy", children: [
25833
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ps-tryon-sr-card-v2-summary-title", children: guideOnlyResult ? t2("Product Size Guide") : t2("Recommended size") }),
25834
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "ps-tryon-sr-card-v2-main", children: [
25835
+ (() => {
25836
+ const rawLabelText = pendingCustomSizes[sectionName]?.displayLabel || singleResult.recommendedSize || singleResult.sizeLabel || (guideOnlyResult ? t2("One Size") : "—");
25837
+ const labelText = measurementType === "foot" ? formatShoeSizeLabel(rawLabelText, shoeUserGender) : rawLabelText;
25838
+ const isLong = labelText.length > 12;
25839
+ return /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: `ps-tryon-sr-card-v2-value${isLong ? " ps-long" : ""}`, children: labelText });
25840
+ })(),
25841
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
25842
+ "span",
25843
+ {
25844
+ className: `ps-tryon-sr-card-v2-rec-pill${pendingCustomSizes[sectionName] ? " is-overridden" : ""}`,
25845
+ children: guideOnlyResult ? t2("SIZE GUIDE") : pendingCustomSizes[sectionName] ? t2("YOUR SELECTION") : t2("RECOMMENDED")
25846
+ }
25847
+ )
25848
+ ] })
25849
+ ] }),
25850
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "ps-tryon-sr-card-v2-open-pill", children: [
25851
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: guideOnlyResult ? t2("View chart") : t2("View measurements") }),
25217
25852
  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { "aria-hidden": "true", children: "›" })
25218
25853
  ] })
25219
25854
  ] })
@@ -25237,13 +25872,7 @@ function SizeResultView({
25237
25872
  ]
25238
25873
  }
25239
25874
  ),
25240
- resultImageUrl && !tryOnProcessing ? /* @__PURE__ */ jsxRuntimeExports.jsxs("button", { className: "ps-tryon-v2-cta", style: { marginTop: 0 }, onClick: onContinueShopping || onClose, children: [
25241
- t2("Continue Shopping"),
25242
- " →"
25243
- ] }) : vtoExcluded ? /* @__PURE__ */ jsxRuntimeExports.jsxs("button", { className: "ps-tryon-v2-cta", style: { marginTop: 0 }, onClick: onContinueShopping || onClose, children: [
25244
- t2("Continue Shopping"),
25245
- " →"
25246
- ] }) : /* @__PURE__ */ jsxRuntimeExports.jsxs(
25875
+ canAddToBag || isHistoryResult || resultImageUrl && !tryOnProcessing || vtoExcluded ? renderShoppingCta() : /* @__PURE__ */ jsxRuntimeExports.jsxs(
25247
25876
  "button",
25248
25877
  {
25249
25878
  className: "ps-tryon-v2-cta",
@@ -26048,7 +26677,7 @@ function ProcessingView({
26048
26677
  }
26049
26678
  }, []);
26050
26679
  const aiFacts = [
26051
- t2("Our model is analyzing 150+ body landmarks for the perfect fit"),
26680
+ t2("Our model is analyzing 150+ body landmarks for your size recommendation"),
26052
26681
  t2("Calibrating fabric drape against your body proportions"),
26053
26682
  t2("Cross-checking fit against millions of garment patterns"),
26054
26683
  t2("Rendering shadows and highlights to match your photo's lighting")
@@ -26151,20 +26780,22 @@ function ProcessingView({
26151
26780
  function NoChartView({
26152
26781
  productImage,
26153
26782
  productTitle,
26783
+ reason = "no-chart",
26154
26784
  onTryOn,
26155
26785
  onClose,
26156
26786
  t: t2
26157
26787
  }) {
26158
26788
  const isMobile = useIsMobile();
26789
+ const isNoMatch = reason === "no-match";
26159
26790
  const RightColumn = /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-tryon-no-chart-content", children: [
26160
26791
  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-tryon-no-chart-icon", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("svg", { viewBox: "0 0 24 24", width: "44", height: "44", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", children: [
26161
26792
  /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M3 17l6 6 12-12-6-6L3 17z" }),
26162
26793
  /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M14 4l-3 3M16 6l-2 2M18 8l-2 2M11 7l-2 2M13 9l-2 2M15 11l-2 2" })
26163
26794
  ] }) }),
26164
- /* @__PURE__ */ jsxRuntimeExports.jsx("h3", { className: "ps-tryon-no-chart-title", children: t2("No size chart available") }),
26165
- /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "ps-tryon-no-chart-msg", children: t2("The merchant hasn't uploaded sizing data for this product yet. You can still see how it looks on you with a virtual try-on.") }),
26795
+ /* @__PURE__ */ jsxRuntimeExports.jsx("h3", { className: "ps-tryon-no-chart-title", children: isNoMatch ? t2("No matching size available") : t2("No size chart available") }),
26796
+ /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "ps-tryon-no-chart-msg", children: isNoMatch ? t2("This product's size chart doesn't include a reliable fit for your measurements.") : t2("The merchant hasn't uploaded sizing data for this product yet. You can still see how it looks on you with a virtual try-on.") }),
26166
26797
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-tryon-no-chart-actions", children: [
26167
- /* @__PURE__ */ jsxRuntimeExports.jsxs("button", { type: "button", className: "ps-tryon-no-chart-cta", onClick: onTryOn, children: [
26798
+ !isNoMatch && /* @__PURE__ */ jsxRuntimeExports.jsxs("button", { type: "button", className: "ps-tryon-no-chart-cta", onClick: onTryOn, children: [
26168
26799
  t2("See how it looks on you"),
26169
26800
  " →"
26170
26801
  ] }),
@@ -26348,11 +26979,12 @@ function ProgressiveStep({
26348
26979
  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-cpw-card-row", children })
26349
26980
  ] }, stepKey);
26350
26981
  }
26351
- function CreateProfileWizard({ onSave, onCancel, initialMode, initialDraft, apiUrl, apiKey, onPhotoPreview, onEstimate, t: t2 }) {
26982
+ function CreateProfileWizard({ onSave, onCancel, initialMode, initialDraft, directAnalysisFlow = false, apiUrl, apiKey, onPhotoPreview, onEstimate, t: t2 }) {
26352
26983
  const seededUnit = draftUnit(initialDraft);
26353
26984
  const seededHeight = draftHeightParts(initialDraft, seededUnit);
26354
26985
  const seededGender = initialDraft?.gender === "female" ? "female" : "male";
26355
26986
  const seededPhotoRef = reactExports.useRef(initialDraft?.photoBase64 || initialDraft?.photoUrl || null);
26987
+ const seededMeasurements = initialDraft?.measurements && Object.keys(initialDraft.measurements).length > 0 ? initialDraft.measurements : null;
26356
26988
  const [mode, setMode] = reactExports.useState(initialMode ?? null);
26357
26989
  const [manualStep, setManualStep] = reactExports.useState("identity");
26358
26990
  const [imageStep, setImageStep] = reactExports.useState("name-photo");
@@ -26383,6 +27015,7 @@ function CreateProfileWizard({ onSave, onCancel, initialMode, initialDraft, apiU
26383
27015
  const [scanStageIdx, setScanStageIdx] = reactExports.useState(0);
26384
27016
  const [photoHelpOpen, setPhotoHelpOpen] = reactExports.useState(false);
26385
27017
  const [uploadHoverCpw, setUploadHoverCpw] = reactExports.useState(false);
27018
+ const directAutoStartedRef = reactExports.useRef(false);
26386
27019
  reactExports.useEffect(() => {
26387
27020
  if (imageStep !== "calculating" || !photoBase64) return;
26388
27021
  let cancelled = false;
@@ -26571,6 +27204,7 @@ function CreateProfileWizard({ onSave, onCancel, initialMode, initialDraft, apiU
26571
27204
  bandSize: isWomen ? bandSize || void 0 : void 0,
26572
27205
  cupSize: isWomen ? cupSize || void 0 : void 0,
26573
27206
  ...isWomen && bandSize && cupSize ? { braSizeRegion } : {},
27207
+ ...initialDraft?.measurements ? { measurements: initialDraft.measurements, measurementsUnit: initialDraft.measurementsUnit || "cm" } : {},
26574
27208
  ...initialDraft?.customMeasurements ? { customMeasurements: initialDraft.customMeasurements } : {}
26575
27209
  };
26576
27210
  };
@@ -26590,6 +27224,7 @@ function CreateProfileWizard({ onSave, onCancel, initialMode, initialDraft, apiU
26590
27224
  ...isWomen && bandSize ? { bandSize } : {},
26591
27225
  ...isWomen && cupSize ? { cupSize } : {},
26592
27226
  ...isWomen && bandSize && cupSize ? { braSizeRegion } : {},
27227
+ ...initialDraft?.measurements ? { measurements: initialDraft.measurements, measurementsUnit: initialDraft.measurementsUnit || "cm" } : {},
26593
27228
  ...initialDraft?.customMeasurements ? { customMeasurements: initialDraft.customMeasurements } : {},
26594
27229
  photoBase64: photoBase64 || void 0
26595
27230
  };
@@ -26662,13 +27297,14 @@ function CreateProfileWizard({ onSave, onCancel, initialMode, initialDraft, apiU
26662
27297
  setError(t2("Please upload a photo"));
26663
27298
  return;
26664
27299
  }
26665
- if (unit === "in") {
27300
+ const canUseSeededMeasurements = directAnalysisFlow && !!seededMeasurements;
27301
+ if (!canUseSeededMeasurements && unit === "in") {
26666
27302
  const ft = parseFloat(heightFt);
26667
27303
  if (!ft || ft < 3 || ft > 8) {
26668
27304
  setError(t2("Please enter a valid height"));
26669
27305
  return;
26670
27306
  }
26671
- } else {
27307
+ } else if (!canUseSeededMeasurements) {
26672
27308
  const cm = parseFloat(heightVal);
26673
27309
  if (!cm || cm < 100 || cm > 250) {
26674
27310
  setError(t2("Please enter a valid height"));
@@ -26676,12 +27312,12 @@ function CreateProfileWizard({ onSave, onCancel, initialMode, initialDraft, apiU
26676
27312
  }
26677
27313
  }
26678
27314
  const w2 = parseFloat(weightVal);
26679
- if (!w2 || w2 <= 0) {
27315
+ if (!canUseSeededMeasurements && (!w2 || w2 <= 0)) {
26680
27316
  setError(t2("Please enter a valid weight"));
26681
27317
  return;
26682
27318
  }
26683
27319
  const a = parseFloat(ageVal);
26684
- if (isWomen && (!bandSize || !cupSize)) {
27320
+ if (isWomen && !directAnalysisFlow && (!bandSize || !cupSize)) {
26685
27321
  setError(t2("Please select your bra band and cup size"));
26686
27322
  return;
26687
27323
  }
@@ -26690,8 +27326,8 @@ function CreateProfileWizard({ onSave, onCancel, initialMode, initialDraft, apiU
26690
27326
  setEstimating(true);
26691
27327
  const MIN_HOLD_MS = 6e3;
26692
27328
  const minHold = new Promise((r2) => setTimeout(r2, MIN_HOLD_MS));
26693
- let liveEstimates = null;
26694
- if (onEstimate && photoBase64) {
27329
+ let liveEstimates = seededMeasurements;
27330
+ if (!canUseSeededMeasurements && onEstimate && photoBase64) {
26695
27331
  const heightRaw = unit === "in" ? (parseInt(heightFt, 10) || 0) * 12 + (parseInt(heightInch, 10) || 0) : parseFloat(heightVal);
26696
27332
  try {
26697
27333
  const result = await onEstimate({
@@ -26731,6 +27367,16 @@ function CreateProfileWizard({ onSave, onCancel, initialMode, initialDraft, apiU
26731
27367
  }
26732
27368
  onSave(payload);
26733
27369
  };
27370
+ reactExports.useEffect(() => {
27371
+ if (!directAnalysisFlow || directAutoStartedRef.current) return;
27372
+ if (mode !== "image" || imageStep !== "name-photo") return;
27373
+ const hasHeight = unit === "in" ? parseFloat(heightFt) > 0 || parseFloat(heightInch) > 0 : parseFloat(heightVal) > 0;
27374
+ const hasWeight = parseFloat(weightVal) > 0;
27375
+ const canUseSeededMeasurements = directAnalysisFlow && !!seededMeasurements;
27376
+ if (!photoBase64 || !name.trim() || !canUseSeededMeasurements && (!hasHeight || !hasWeight)) return;
27377
+ directAutoStartedRef.current = true;
27378
+ void advanceImage();
27379
+ }, [directAnalysisFlow, mode, imageStep, photoBase64, name, heightFt, heightInch, heightVal, weightVal, unit]);
26734
27380
  const goBackImage = () => {
26735
27381
  setError("");
26736
27382
  if (imageStep === "details") {
@@ -26772,9 +27418,12 @@ function CreateProfileWizard({ onSave, onCancel, initialMode, initialDraft, apiU
26772
27418
  if (photoBase64) pct += 50;
26773
27419
  return pct;
26774
27420
  })();
26775
- const hideGlobalBack = mode === "image" && imageStep === "name-photo";
26776
- return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: `ps-cpw-root${hideGlobalBack ? " ps-cpw-hide-global-back" : ""}`, children: [
26777
- !(mode === "image" && imageStep === "name-photo") && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-cpw-step-head", children: [
27421
+ const hideGlobalBack = mode === "image" && imageStep === "name-photo" && !directAnalysisFlow;
27422
+ const hideStepHeader = directAnalysisFlow && mode === "image";
27423
+ const hideFooter = directAnalysisFlow && mode === "image" && imageStep === "calculating" && estimating;
27424
+ const hideFooterBack = directAnalysisFlow && mode === "image";
27425
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: `ps-cpw-root${hideGlobalBack ? " ps-cpw-hide-global-back" : ""}${directAnalysisFlow ? " ps-cpw-direct-flow" : ""}`, children: [
27426
+ !hideStepHeader && !(mode === "image" && imageStep === "name-photo") && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-cpw-step-head", children: [
26778
27427
  /* @__PURE__ */ jsxRuntimeExports.jsx("h2", { className: "ps-cpw-step-title", children: headerLabel }),
26779
27428
  mode != null && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-cpw-progress", children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-cpw-progress-track", children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-cpw-progress-fill", style: { width: `${progressPct}%` } }) }) })
26780
27429
  ] }),
@@ -27702,7 +28351,7 @@ function CreateProfileWizard({ onSave, onCancel, initialMode, initialDraft, apiU
27702
28351
  mode === "image" && imageStep === "calculating" && (() => {
27703
28352
  const stages = [
27704
28353
  { title: t2("DETECTING POSE"), desc: t2("Identifying body landmarks from your photo.") },
27705
- { title: t2("SCANNING FRAME"), desc: t2("Our AI is mapping your proportions to calculate the perfect fit.") },
28354
+ { title: t2("SCANNING FRAME"), desc: t2("Our AI is mapping your proportions for a size recommendation.") },
27706
28355
  { title: t2("ANALYZING BODY"), desc: t2("Measuring shoulders, chest, waist and hips.") },
27707
28356
  { title: t2("MATCHING SIZE"), desc: t2("Comparing your measurements to the size guide.") },
27708
28357
  { title: t2("FINALIZING RESULT"), desc: t2("Almost done — preparing your recommendation.") }
@@ -27790,13 +28439,13 @@ function CreateProfileWizard({ onSave, onCancel, initialMode, initialDraft, apiU
27790
28439
  ] }) }, "image-calculating");
27791
28440
  })()
27792
28441
  ] }),
27793
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-cpw-footer", children: [
27794
- /* @__PURE__ */ jsxRuntimeExports.jsx("button", { type: "button", className: "ps-cpw-back-btn", onClick: handleBack, children: mode == null ? t2("Cancel") : `← ${t2("Back")}` }),
28442
+ !hideFooter && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: `ps-cpw-footer${hideFooterBack ? " ps-cpw-footer-no-back" : ""}`, children: [
28443
+ !hideFooterBack && /* @__PURE__ */ jsxRuntimeExports.jsx("button", { type: "button", className: "ps-cpw-back-btn", onClick: handleBack, children: mode == null ? t2("Cancel") : `← ${t2("Back")}` }),
27795
28444
  mode === "manual" && !isAutoAdvanceStep && /* @__PURE__ */ jsxRuntimeExports.jsx("button", { type: "button", className: "ps-cpw-next-btn", onClick: advanceManual, children: isLastManualStep ? t2("CALCULATE MY FIT") : t2("Continue") }),
27796
28445
  mode === "image" && imageStep === "name-photo" && (() => {
27797
28446
  const heightOk = unit === "in" ? parseFloat(heightFt) > 0 || parseFloat(heightInch) > 0 : parseFloat(heightVal) > 0;
27798
28447
  const weightOk = parseFloat(weightVal) > 0;
27799
- const braOk = !isWomen || !!bandSize && !!cupSize;
28448
+ const braOk = !isWomen || directAnalysisFlow || !!bandSize && !!cupSize;
27800
28449
  const nameOk = !!name.trim();
27801
28450
  const photoOk = !!photoBase64;
27802
28451
  const analyzing = photoUploading;
@@ -28252,6 +28901,7 @@ function MySizingProfilesView({
28252
28901
  apiKey,
28253
28902
  initialMode: initialCreateDraft ? "image" : void 0,
28254
28903
  initialDraft: initialCreateDraft,
28904
+ directAnalysisFlow: !!initialCreateDraft,
28255
28905
  onSave: (data) => {
28256
28906
  onSaveNewProfile(data);
28257
28907
  onProfileDraftConsumed?.();
@@ -28488,14 +29138,13 @@ function BasicsStepMobile({
28488
29138
  /* @__PURE__ */ jsxRuntimeExports.jsx("h2", { className: "ps-bpm-title", children: t2("Body Measurements") }),
28489
29139
  /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "ps-bpm-subtitle", children: t2("Enter your details for a bespoke size recommendation") })
28490
29140
  ] }),
28491
- activeProfileName && /* @__PURE__ */ jsxRuntimeExports.jsxs("p", { className: "ps-bp-profile-hint", children: [
28492
- t2("Using"),
28493
- " ",
28494
- /* @__PURE__ */ jsxRuntimeExports.jsx("strong", { children: activeProfileName }),
28495
- onStartFresh && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
28496
- " · ",
28497
- /* @__PURE__ */ jsxRuntimeExports.jsx("button", { type: "button", className: "ps-bp-profile-hint-link", onClick: onStartFresh, children: t2("start fresh") })
28498
- ] })
29141
+ activeProfileName && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-bp-profile-card", children: [
29142
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-bp-profile-card-copy", children: [
29143
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ps-bp-profile-card-eyebrow", children: t2("Active Profile") }),
29144
+ /* @__PURE__ */ jsxRuntimeExports.jsx("strong", { children: activeProfileName }),
29145
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: t2("Using saved measurements for this fit.") })
29146
+ ] }),
29147
+ onStartFresh && /* @__PURE__ */ jsxRuntimeExports.jsx("button", { type: "button", className: "ps-bp-profile-card-action", onClick: onStartFresh, children: t2("Start Fresh") })
28499
29148
  ] }),
28500
29149
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-bpm-toggle", children: [
28501
29150
  /* @__PURE__ */ jsxRuntimeExports.jsx(
@@ -28693,6 +29342,7 @@ function PhotoStepMobile({
28693
29342
  photoStatus,
28694
29343
  photoRejection,
28695
29344
  onClearRejection,
29345
+ photoHelpSlot,
28696
29346
  bodyContextSlot,
28697
29347
  hideTabs = false,
28698
29348
  t: t2
@@ -28717,6 +29367,7 @@ function PhotoStepMobile({
28717
29367
  }
28718
29368
  ),
28719
29369
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: `ps-pm-preview${compactAgeGate ? " ps-pm-preview-tall" : ""}`, children: [
29370
+ !hasPhoto && photoHelpSlot,
28720
29371
  hasPhoto ? /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
28721
29372
  /* @__PURE__ */ jsxRuntimeExports.jsx("img", { src: photoPreview, alt: t2("Your photo"), className: "ps-pm-preview-img" }),
28722
29373
  /* @__PURE__ */ jsxRuntimeExports.jsx(
@@ -29273,6 +29924,7 @@ function BodyProfileView({
29273
29924
  basicOnly = false,
29274
29925
  initialStep,
29275
29926
  simplePhotoOnly = false,
29927
+ simpleAccessoryLayout = false,
29276
29928
  simpleQuestionMode = "heightWeight",
29277
29929
  formRef,
29278
29930
  sizingCountry,
@@ -29437,6 +30089,7 @@ function BodyProfileView({
29437
30089
  setPhotoProcessing(true);
29438
30090
  setPhotoStatus(t2("Analyzing photo…"));
29439
30091
  setPhotoFile(file);
30092
+ setPhotoHelpOpen(false);
29440
30093
  const previewUrl = URL.createObjectURL(file);
29441
30094
  setPhotoPreview(previewUrl);
29442
30095
  try {
@@ -29555,6 +30208,9 @@ function BodyProfileView({
29555
30208
  formRef.current.weight = String(weightVal);
29556
30209
  formRef.current.gender = gender;
29557
30210
  if (age) formRef.current.age = age;
30211
+ if (chestProfile) formRef.current.chestProfile = chestProfile;
30212
+ if (midsectionProfile) formRef.current.midsectionProfile = midsectionProfile;
30213
+ if (hipProfile) formRef.current.hipProfile = hipProfile;
29558
30214
  if (bandSize) formRef.current.bandSize = bandSize;
29559
30215
  if (cupSize) formRef.current.cupSize = cupSize;
29560
30216
  if (braSizeRegion) formRef.current.braSizeRegion = braSizeRegion;
@@ -29611,6 +30267,9 @@ function BodyProfileView({
29611
30267
  weightUnit: isShoeReferenceMode ? "kg" : wUnit,
29612
30268
  gender,
29613
30269
  ...ageForSubmit ? { age: ageForSubmit } : {},
30270
+ ...chestProfile ? { chestProfile } : {},
30271
+ ...midsectionProfile ? { midsectionProfile } : {},
30272
+ ...hipProfile ? { hipProfile } : {},
29614
30273
  ...currentShoeReference ? {
29615
30274
  extraMeasurements: {
29616
30275
  referenceShoeBrandId: currentShoeReference.brandId,
@@ -30057,6 +30716,7 @@ function BodyProfileView({
30057
30716
  }
30058
30717
  const analyzeDisabled = analyzeMissing.length > 0;
30059
30718
  const analyzeLabel = analyzeDisabled ? analyzeMissing[0] ?? t2("Analyze My Size") : t2("Analyze My Size");
30719
+ const compactHeightWeightAccessory = simplePhotoOnly && simpleAccessoryLayout && !isShoeReferenceMode;
30060
30720
  if (isMobile) {
30061
30721
  return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-bp-wrapper", children: [
30062
30722
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-bp-scan-progress", children: [
@@ -30074,19 +30734,6 @@ function BodyProfileView({
30074
30734
  ] }),
30075
30735
  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ps-bp-scan-progress-spacer", "aria-hidden": "true" })
30076
30736
  ] }),
30077
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-bp-scan-help-row", children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
30078
- "button",
30079
- {
30080
- type: "button",
30081
- onClick: () => setPhotoHelpOpen((v2) => !v2),
30082
- "aria-label": t2("How to take a good photo"),
30083
- className: `ps-pm-help-pill ps-bp-scan-help-pill${photoHelpOpen ? " ps-active" : ""}`,
30084
- children: [
30085
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ps-pm-help-pill-q", "aria-hidden": "true", children: "?" }),
30086
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: t2("How to take a good photo") })
30087
- ]
30088
- }
30089
- ) }),
30090
30737
  /* @__PURE__ */ jsxRuntimeExports.jsx(
30091
30738
  PhotoStepMobile,
30092
30739
  {
@@ -30111,11 +30758,27 @@ function BodyProfileView({
30111
30758
  photoStatus,
30112
30759
  photoRejection,
30113
30760
  onClearRejection: () => setPhotoRejection(null),
30761
+ photoHelpSlot: /* @__PURE__ */ jsxRuntimeExports.jsxs(
30762
+ "button",
30763
+ {
30764
+ type: "button",
30765
+ onClick: (e) => {
30766
+ e.stopPropagation();
30767
+ setPhotoHelpOpen((v2) => !v2);
30768
+ },
30769
+ "aria-label": t2("How to take a good photo"),
30770
+ className: `ps-bp-photo-help-chip${photoHelpOpen ? " ps-active" : ""}`,
30771
+ children: [
30772
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ps-bp-photo-help-chip-mark", "aria-hidden": "true", children: "?" }),
30773
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: t2("How to take a good photo") })
30774
+ ]
30775
+ }
30776
+ ),
30114
30777
  hideTabs: simplePhotoOnly,
30115
30778
  t: t2
30116
30779
  }
30117
30780
  ),
30118
- photoHelpOpen && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
30781
+ !photoPreview && photoHelpOpen && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
30119
30782
  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-bp-photo-help-backdrop", onClick: () => setPhotoHelpOpen(false), "aria-hidden": "true" }),
30120
30783
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { role: "dialog", "aria-label": t2("How to take the best photo"), className: "ps-bp-photo-help", children: [
30121
30784
  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-bp-photo-help-handle", "aria-hidden": "true" }),
@@ -30175,7 +30838,7 @@ function BodyProfileView({
30175
30838
  ] });
30176
30839
  }
30177
30840
  return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-bp-wrapper", children: [
30178
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { style: { display: "flex", gap: "1.2vw", padding: "1.5vw", width: "100%", height: "100%", minHeight: "20vw", alignItems: "stretch", position: "relative" }, children: [
30841
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { style: { display: "flex", gap: "1.2vw", padding: "1.5vw", width: "100%", flex: "1 1 auto", minHeight: 0, alignItems: "stretch", position: "relative", overflow: "hidden" }, children: [
30179
30842
  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { style: { flex: 1, position: "relative", display: "flex", flexDirection: "column", gap: "0.7vw" }, children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
30180
30843
  "div",
30181
30844
  {
@@ -30233,6 +30896,95 @@ function BodyProfileView({
30233
30896
  overflow: "hidden"
30234
30897
  },
30235
30898
  children: [
30899
+ !photoPreview && /* @__PURE__ */ jsxRuntimeExports.jsxs(
30900
+ "button",
30901
+ {
30902
+ type: "button",
30903
+ onClick: (e) => {
30904
+ e.stopPropagation();
30905
+ setPhotoHelpOpen((v2) => !v2);
30906
+ },
30907
+ "aria-label": t2("How to take a good photo"),
30908
+ title: t2("How to take a good photo"),
30909
+ className: `ps-bp-photo-help-chip${photoHelpOpen ? " ps-active" : ""}`,
30910
+ children: [
30911
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ps-bp-photo-help-chip-mark", "aria-hidden": "true", children: "?" }),
30912
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: t2("How to take a good photo") })
30913
+ ]
30914
+ }
30915
+ ),
30916
+ !photoPreview && photoHelpOpen && /* @__PURE__ */ jsxRuntimeExports.jsxs(
30917
+ "div",
30918
+ {
30919
+ role: "dialog",
30920
+ "aria-label": t2("How to take the best photo"),
30921
+ className: "ps-bp-photo-help ps-bp-photo-help-upload",
30922
+ onClick: (e) => e.stopPropagation(),
30923
+ children: [
30924
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-bp-photo-help-handle", "aria-hidden": "true" }),
30925
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-bp-photo-help-header", children: [
30926
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ps-bp-photo-help-title", children: t2("How to take the best photo") }),
30927
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
30928
+ "button",
30929
+ {
30930
+ type: "button",
30931
+ onClick: () => setPhotoHelpOpen(false),
30932
+ "aria-label": t2("Close"),
30933
+ className: "ps-bp-photo-help-close",
30934
+ children: "×"
30935
+ }
30936
+ )
30937
+ ] }),
30938
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-bp-photo-help-section ps-bp-photo-help-do", children: [
30939
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-bp-photo-help-section-label", children: [
30940
+ "✓ ",
30941
+ t2("Do")
30942
+ ] }),
30943
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-bp-photo-help-section-body", children: [
30944
+ t2("Stand facing the camera with your full body in frame"),
30945
+ /* @__PURE__ */ jsxRuntimeExports.jsx("br", {}),
30946
+ t2("Hold the phone at WAIST height (not eye level)"),
30947
+ /* @__PURE__ */ jsxRuntimeExports.jsx("br", {}),
30948
+ t2("Stand with your HEELS against a wall for best accuracy"),
30949
+ /* @__PURE__ */ jsxRuntimeExports.jsx("br", {}),
30950
+ t2("Use natural or even lighting (e.g. near a window)"),
30951
+ /* @__PURE__ */ jsxRuntimeExports.jsx("br", {}),
30952
+ t2("Wear fitted, simple clothing (e.g. neutral colors)"),
30953
+ /* @__PURE__ */ jsxRuntimeExports.jsx("br", {}),
30954
+ t2("Choose a plain background (a light wall is ideal)"),
30955
+ /* @__PURE__ */ jsxRuntimeExports.jsx("br", {}),
30956
+ t2("Stand straight and still, arms relaxed by your sides")
30957
+ ] })
30958
+ ] }),
30959
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-bp-photo-help-section ps-bp-photo-help-dont", children: [
30960
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-bp-photo-help-section-label", children: [
30961
+ "✗ ",
30962
+ t2("Don't")
30963
+ ] }),
30964
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-bp-photo-help-section-body", children: [
30965
+ t2("Don't wear loose, baggy, or layered clothing"),
30966
+ /* @__PURE__ */ jsxRuntimeExports.jsx("br", {}),
30967
+ t2("Don't sit, pose, or bend your body"),
30968
+ /* @__PURE__ */ jsxRuntimeExports.jsx("br", {}),
30969
+ t2("Don't use strong backlighting"),
30970
+ /* @__PURE__ */ jsxRuntimeExports.jsx("br", {}),
30971
+ t2("Don't take mirror photos or selfies"),
30972
+ /* @__PURE__ */ jsxRuntimeExports.jsx("br", {}),
30973
+ t2("Don't apply filters, effects, or edits")
30974
+ ] })
30975
+ ] }),
30976
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-bp-photo-help-section ps-bp-photo-help-tip", children: [
30977
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("strong", { children: [
30978
+ "💡 ",
30979
+ t2("Quick Tip"),
30980
+ ":"
30981
+ ] }),
30982
+ " ",
30983
+ t2("The simpler your photo is, the more accurate your virtual try-on results will be.")
30984
+ ] })
30985
+ ]
30986
+ }
30987
+ ),
30236
30988
  photoProcessing && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-bp-photo-overlay", onClick: (e) => e.stopPropagation(), children: [
30237
30989
  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-bp-photo-overlay-spinner", "aria-hidden": "true" }),
30238
30990
  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ps-bp-photo-overlay-label", children: photoStatus || t2("Analyzing photo…") })
@@ -30451,71 +31203,30 @@ function BodyProfileView({
30451
31203
  background: "linear-gradient(to bottom, transparent 0%, var(--ps-border-subtle) 18%, var(--ps-border-subtle) 82%, transparent 100%)",
30452
31204
  flexShrink: 0
30453
31205
  } }),
30454
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { style: { flex: 1, display: "flex", flexDirection: "column", justifyContent: "flex-start", position: "relative", gap: "0.8vw" }, children: isShoeReferenceMode ? /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-shoe-ref-desktop", children: renderShoeReferenceFields() }) : /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
30455
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
30456
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { style: { display: "flex", alignItems: "center", justifyContent: "space-between", gap: "0.6vw" }, children: [
30457
- /* @__PURE__ */ jsxRuntimeExports.jsx("h3", { style: { margin: 0, fontSize: "1vw", fontWeight: 700, color: "var(--ps-text-primary)" }, children: t2("Body details") }),
30458
- /* @__PURE__ */ jsxRuntimeExports.jsxs(
30459
- "button",
30460
- {
30461
- type: "button",
30462
- onClick: () => setPhotoHelpOpen((v2) => !v2),
30463
- "aria-label": t2("How to take a good photo"),
30464
- title: t2("How to take a good photo"),
30465
- style: {
30466
- display: "inline-flex",
30467
- alignItems: "center",
30468
- gap: "0.35vw",
30469
- padding: "0.4vw 0.7vw",
30470
- background: photoHelpOpen ? "var(--ps-accent)" : "transparent",
30471
- color: photoHelpOpen ? "#FFFFFF" : "var(--ps-accent)",
30472
- border: `1.5px solid var(--ps-accent)`,
30473
- borderRadius: "999px",
30474
- cursor: "pointer",
30475
- fontFamily: "inherit",
30476
- fontSize: "0.58vw",
30477
- fontWeight: 700,
30478
- letterSpacing: "0.04em",
30479
- whiteSpace: "nowrap",
30480
- transition: "background 0.15s, color 0.15s",
30481
- flexShrink: 0
30482
- },
30483
- children: [
30484
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { style: {
30485
- display: "inline-flex",
30486
- alignItems: "center",
30487
- justifyContent: "center",
30488
- width: "0.95vw",
30489
- height: "0.95vw",
30490
- minWidth: "14px",
30491
- minHeight: "14px",
30492
- borderRadius: "50%",
30493
- background: photoHelpOpen ? "#FFFFFF" : "var(--ps-accent)",
30494
- color: photoHelpOpen ? "var(--ps-accent)" : "#FFFFFF",
30495
- fontSize: "0.65vw",
30496
- fontWeight: 700,
30497
- lineHeight: 1
30498
- }, "aria-hidden": "true", children: "?" }),
30499
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: t2("How to take a good photo") })
30500
- ]
30501
- }
30502
- )
30503
- ] }),
30504
- /* @__PURE__ */ jsxRuntimeExports.jsx("p", { style: { margin: "0.2vw 0 0", fontSize: "0.65vw", color: "var(--ps-text-muted)" }, children: t2("These calibrate the AI — all required.") })
30505
- ] }),
30506
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-bp-system-toggle", style: { alignSelf: "center", marginTop: "1.2vw" }, children: [
30507
- /* @__PURE__ */ jsxRuntimeExports.jsx("button", { className: `ps-bp-system-btn${!isImperialMode ? " ps-bp-system-active" : ""}`, onClick: photoSwitchToMetric, type: "button", children: t2("Metric") }),
30508
- /* @__PURE__ */ jsxRuntimeExports.jsx("button", { className: `ps-bp-system-btn${isImperialMode ? " ps-bp-system-active" : ""}`, onClick: photoSwitchToImperial, type: "button", children: t2("Imperial") })
31206
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { style: {
31207
+ flex: compactHeightWeightAccessory ? "0 1 min(34vw, 360px)" : 1,
31208
+ display: "flex",
31209
+ flexDirection: "column",
31210
+ justifyContent: compactHeightWeightAccessory ? "center" : "flex-start",
31211
+ position: "relative",
31212
+ gap: compactHeightWeightAccessory ? "1.1vw" : "0.8vw",
31213
+ minWidth: compactHeightWeightAccessory ? "280px" : void 0
31214
+ }, children: isShoeReferenceMode ? /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-shoe-ref-desktop", children: renderShoeReferenceFields() }) : /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
31215
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: `ps-bp-photo-details-head${compactHeightWeightAccessory ? " ps-bp-photo-details-head-simple" : ""}`, children: [
31216
+ /* @__PURE__ */ jsxRuntimeExports.jsx("h3", { children: t2("Body details") }),
31217
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-bp-system-toggle ps-bp-system-toggle-compact", children: [
31218
+ /* @__PURE__ */ jsxRuntimeExports.jsx("button", { className: `ps-bp-system-btn${!isImperialMode ? " ps-bp-system-active" : ""}`, onClick: photoSwitchToMetric, type: "button", children: t2("Metric") }),
31219
+ /* @__PURE__ */ jsxRuntimeExports.jsx("button", { className: `ps-bp-system-btn${isImperialMode ? " ps-bp-system-active" : ""}`, onClick: photoSwitchToImperial, type: "button", children: t2("Imperial") })
31220
+ ] })
30509
31221
  ] }),
30510
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { style: { marginTop: "auto", marginBottom: "auto" }, children: [
30511
- activeProfileName && /* @__PURE__ */ jsxRuntimeExports.jsxs("p", { className: "ps-bp-profile-hint", style: { textAlign: "center", margin: "0 0 0.5vw" }, children: [
30512
- t2("Using"),
30513
- " ",
30514
- /* @__PURE__ */ jsxRuntimeExports.jsx("strong", { children: activeProfileName }),
30515
- onStartFresh && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
30516
- " · ",
30517
- /* @__PURE__ */ jsxRuntimeExports.jsx("button", { type: "button", className: "ps-bp-profile-hint-link", onClick: handleClearFromProfile, children: t2("start fresh") })
30518
- ] })
31222
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { style: { marginTop: compactHeightWeightAccessory ? "0.35vw" : "0.15vw", marginBottom: 0, minHeight: 0 }, children: [
31223
+ activeProfileName && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-bp-profile-card ps-bp-profile-card-compact", children: [
31224
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-bp-profile-card-copy", children: [
31225
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ps-bp-profile-card-eyebrow", children: t2("Active Profile") }),
31226
+ /* @__PURE__ */ jsxRuntimeExports.jsx("strong", { children: activeProfileName }),
31227
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: t2("Using saved measurements for this fit.") })
31228
+ ] }),
31229
+ onStartFresh && /* @__PURE__ */ jsxRuntimeExports.jsx("button", { type: "button", className: "ps-bp-profile-card-action", onClick: handleClearFromProfile, children: t2("Start Fresh") })
30519
31230
  ] }),
30520
31231
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-bp-inline-fields", children: [
30521
31232
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-bp-inline-row", children: [
@@ -30593,87 +31304,6 @@ function BodyProfileView({
30593
31304
  ] })
30594
31305
  ] })
30595
31306
  ] })
30596
- ] }),
30597
- photoHelpOpen && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
30598
- /* @__PURE__ */ jsxRuntimeExports.jsx(
30599
- "div",
30600
- {
30601
- className: "ps-bp-photo-help-backdrop",
30602
- onClick: () => setPhotoHelpOpen(false),
30603
- "aria-hidden": "true"
30604
- }
30605
- ),
30606
- /* @__PURE__ */ jsxRuntimeExports.jsxs(
30607
- "div",
30608
- {
30609
- role: "dialog",
30610
- "aria-label": t2("How to take the best photo"),
30611
- className: "ps-bp-photo-help",
30612
- children: [
30613
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-bp-photo-help-handle", "aria-hidden": "true" }),
30614
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-bp-photo-help-header", children: [
30615
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ps-bp-photo-help-title", children: t2("How to take the best photo") }),
30616
- /* @__PURE__ */ jsxRuntimeExports.jsx(
30617
- "button",
30618
- {
30619
- type: "button",
30620
- onClick: () => setPhotoHelpOpen(false),
30621
- "aria-label": t2("Close"),
30622
- className: "ps-bp-photo-help-close",
30623
- children: "×"
30624
- }
30625
- )
30626
- ] }),
30627
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-bp-photo-help-section ps-bp-photo-help-do", children: [
30628
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-bp-photo-help-section-label", children: [
30629
- "✓ ",
30630
- t2("Do")
30631
- ] }),
30632
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-bp-photo-help-section-body", children: [
30633
- t2("Stand facing the camera with your full body in frame"),
30634
- /* @__PURE__ */ jsxRuntimeExports.jsx("br", {}),
30635
- t2("Hold the phone at WAIST height (not eye level)"),
30636
- /* @__PURE__ */ jsxRuntimeExports.jsx("br", {}),
30637
- t2("Stand with your HEELS against a wall for best accuracy"),
30638
- /* @__PURE__ */ jsxRuntimeExports.jsx("br", {}),
30639
- t2("Use natural or even lighting (e.g. near a window)"),
30640
- /* @__PURE__ */ jsxRuntimeExports.jsx("br", {}),
30641
- t2("Wear fitted, simple clothing (e.g. neutral colors)"),
30642
- /* @__PURE__ */ jsxRuntimeExports.jsx("br", {}),
30643
- t2("Choose a plain background (a light wall is ideal)"),
30644
- /* @__PURE__ */ jsxRuntimeExports.jsx("br", {}),
30645
- t2("Stand straight and still, arms relaxed by your sides")
30646
- ] })
30647
- ] }),
30648
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-bp-photo-help-section ps-bp-photo-help-dont", children: [
30649
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-bp-photo-help-section-label", children: [
30650
- "✗ ",
30651
- t2("Don't")
30652
- ] }),
30653
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-bp-photo-help-section-body", children: [
30654
- t2("Don't wear loose, baggy, or layered clothing"),
30655
- /* @__PURE__ */ jsxRuntimeExports.jsx("br", {}),
30656
- t2("Don't sit, pose, or bend your body"),
30657
- /* @__PURE__ */ jsxRuntimeExports.jsx("br", {}),
30658
- t2("Don't use strong backlighting"),
30659
- /* @__PURE__ */ jsxRuntimeExports.jsx("br", {}),
30660
- t2("Don't take mirror photos or selfies"),
30661
- /* @__PURE__ */ jsxRuntimeExports.jsx("br", {}),
30662
- t2("Don't apply filters, effects, or edits")
30663
- ] })
30664
- ] }),
30665
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-bp-photo-help-section ps-bp-photo-help-tip", children: [
30666
- /* @__PURE__ */ jsxRuntimeExports.jsxs("strong", { children: [
30667
- "💡 ",
30668
- t2("Quick Tip"),
30669
- ":"
30670
- ] }),
30671
- " ",
30672
- t2("The simpler your photo is, the more accurate your virtual try-on results will be.")
30673
- ] })
30674
- ]
30675
- }
30676
- )
30677
31307
  ] })
30678
31308
  ] }) })
30679
31309
  ] }),
@@ -30817,14 +31447,13 @@ function BodyProfileView({
30817
31447
  }
30818
31448
  return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-bp-step ps-bp-step-enter", children: [
30819
31449
  /* @__PURE__ */ jsxRuntimeExports.jsx("h2", { className: "ps-bp-title", children: basicOnly || simplePhotoOnly ? t2("Your Details") : t2("Body Measurements") }),
30820
- activeProfileName && /* @__PURE__ */ jsxRuntimeExports.jsxs("p", { className: "ps-bp-profile-hint", style: { textAlign: "center", margin: "0 0 0.5vw" }, children: [
30821
- t2("Using"),
30822
- " ",
30823
- /* @__PURE__ */ jsxRuntimeExports.jsx("strong", { children: activeProfileName }),
30824
- onStartFresh && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
30825
- " · ",
30826
- /* @__PURE__ */ jsxRuntimeExports.jsx("button", { type: "button", className: "ps-bp-profile-hint-link", onClick: handleClearFromProfile, children: t2("start fresh") })
30827
- ] })
31450
+ activeProfileName && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-bp-profile-card", children: [
31451
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-bp-profile-card-copy", children: [
31452
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ps-bp-profile-card-eyebrow", children: t2("Active Profile") }),
31453
+ /* @__PURE__ */ jsxRuntimeExports.jsx("strong", { children: activeProfileName }),
31454
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: t2("Using saved measurements for this fit.") })
31455
+ ] }),
31456
+ onStartFresh && /* @__PURE__ */ jsxRuntimeExports.jsx("button", { type: "button", className: "ps-bp-profile-card-action", onClick: handleClearFromProfile, children: t2("Start Fresh") })
30828
31457
  ] }),
30829
31458
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-bp-system-toggle", children: [
30830
31459
  /* @__PURE__ */ jsxRuntimeExports.jsx("button", { className: `ps-bp-system-btn${!isImperialMode ? " ps-bp-system-active" : ""}`, onClick: switchToMetric, type: "button", children: t2("Metric") }),
@@ -32351,6 +32980,31 @@ function validMidsectionProfile(value) {
32351
32980
  function validHipProfile(value) {
32352
32981
  return value === "narrow" || value === "average" || value === "full" ? value : void 0;
32353
32982
  }
32983
+ async function profilePhotoFromFile(file) {
32984
+ try {
32985
+ return await compressImage(file, { maxDimension: 1280, quality: 0.92 });
32986
+ } catch {
32987
+ return new Promise((resolve) => {
32988
+ try {
32989
+ const reader = new FileReader();
32990
+ reader.onload = () => resolve(typeof reader.result === "string" ? reader.result : null);
32991
+ reader.onerror = () => resolve(null);
32992
+ reader.readAsDataURL(file);
32993
+ } catch {
32994
+ resolve(null);
32995
+ }
32996
+ });
32997
+ }
32998
+ }
32999
+ function cleanProfileMeasurements(value) {
33000
+ if (!value || typeof value !== "object") return void 0;
33001
+ const measurements = {};
33002
+ for (const [key, raw] of Object.entries(value)) {
33003
+ const n2 = positiveNumber(raw);
33004
+ if (n2 != null) measurements[key] = n2;
33005
+ }
33006
+ return Object.keys(measurements).length > 0 ? measurements : void 0;
33007
+ }
32354
33008
  function durableHistoryImageUrl(url) {
32355
33009
  if (!url) return void 0;
32356
33010
  const clean = url.trim();
@@ -32441,6 +33095,7 @@ function PrimeStyleTryonInner({
32441
33095
  productImages,
32442
33096
  productCarouselItems,
32443
33097
  garmentReferenceImage,
33098
+ garmentDetailImage,
32444
33099
  productTitle = "Product",
32445
33100
  productUrl,
32446
33101
  productId,
@@ -32472,6 +33127,10 @@ function PrimeStyleTryonInner({
32472
33127
  onProcessing,
32473
33128
  onComplete,
32474
33129
  onError,
33130
+ onAddToBag,
33131
+ addToBagLabel,
33132
+ continueShoppingLabel,
33133
+ backToProductPageLabel,
32475
33134
  sizeGuideData,
32476
33135
  initialView,
32477
33136
  initialBodyProfileStep
@@ -32600,6 +33259,7 @@ function PrimeStyleTryonInner({
32600
33259
  setCssReady(true);
32601
33260
  }, []);
32602
33261
  const [view, setView] = reactExports.useState(initialView ?? "idle");
33262
+ const [noSizeReason, setNoSizeReason] = reactExports.useState("no-chart");
32603
33263
  const [selectedFile, setSelectedFile] = reactExports.useState(null);
32604
33264
  const [previewUrl, setPreviewUrl] = reactExports.useState(null);
32605
33265
  const [resultImageUrl, setResultImageUrl] = reactExports.useState(null);
@@ -32679,7 +33339,11 @@ function PrimeStyleTryonInner({
32679
33339
  const [estimationLoading, setEstimationLoading] = reactExports.useState(false);
32680
33340
  const [profiles, setProfiles] = reactExports.useState(() => lsGet("profiles", []));
32681
33341
  const [profileSession, setProfileSession] = reactExports.useState(() => getStoredProfileSession());
32682
- const [profileCompletionDraft, setProfileCompletionDraft] = reactExports.useState(() => lsGet(PROFILE_COMPLETION_DRAFT_KEY, null));
33342
+ const profileSessionRef = reactExports.useRef(profileSession);
33343
+ const suppressNextProfilePersistRef = reactExports.useRef(false);
33344
+ const [profileCompletionDraft, setProfileCompletionDraft] = reactExports.useState(
33345
+ () => lsGet(PROFILE_COMPLETION_DRAFT_KEY, null)
33346
+ );
32683
33347
  const [profileAuthError, setProfileAuthError] = reactExports.useState(null);
32684
33348
  const [profileAuthLoadingProvider, setProfileAuthLoadingProvider] = reactExports.useState(null);
32685
33349
  const [history, setHistory] = reactExports.useState(() => lsGet("history", []).map(normalizeHistoryEntry));
@@ -32693,13 +33357,17 @@ function PrimeStyleTryonInner({
32693
33357
  const [restoredProductCarouselItems, setRestoredProductCarouselItems] = reactExports.useState(null);
32694
33358
  const [restoredProductTitle, setRestoredProductTitle] = reactExports.useState(null);
32695
33359
  const [restoredProductUrl, setRestoredProductUrl] = reactExports.useState(null);
33360
+ const [restoredHistoryEntryId, setRestoredHistoryEntryId] = reactExports.useState(null);
32696
33361
  const [activeProfileId, setActiveProfileIdState] = reactExports.useState(() => getActiveProfileId());
32697
33362
  const [estimatingProfileIds, setEstimatingProfileIds] = reactExports.useState(() => /* @__PURE__ */ new Set());
32698
33363
  const [deleteConfirmId, setDeleteConfirmId] = reactExports.useState(null);
32699
33364
  const setActiveProfileId$1 = reactExports.useCallback((id2) => {
32700
33365
  setActiveProfileIdState(id2);
32701
- setActiveProfileId(id2);
33366
+ if (!profileSessionRef.current) setActiveProfileId(id2);
32702
33367
  }, []);
33368
+ reactExports.useEffect(() => {
33369
+ profileSessionRef.current = profileSession;
33370
+ }, [profileSession]);
32703
33371
  const [profileSaved, setProfileSaved] = reactExports.useState(false);
32704
33372
  const [drawer, setDrawer] = reactExports.useState(null);
32705
33373
  const [profileDetail, setProfileDetail] = reactExports.useState(null);
@@ -32715,28 +33383,38 @@ function PrimeStyleTryonInner({
32715
33383
  profilesGoBackRef.current = goBack;
32716
33384
  }, []);
32717
33385
  const clearProfileCompletionDraft = reactExports.useCallback(() => {
32718
- lsSet(PROFILE_COMPLETION_DRAFT_KEY, null);
33386
+ lsRemove(PROFILE_COMPLETION_DRAFT_KEY);
32719
33387
  setProfileCompletionDraft(null);
32720
33388
  }, []);
32721
- const handleCompleteProfileFromResult = reactExports.useCallback(() => {
33389
+ const buildProfileCompletionDraft = reactExports.useCallback((photoBase64) => {
32722
33390
  const f2 = formRef.current || {};
32723
33391
  const active = profiles.find((p2) => p2.id === activeProfileId) || null;
32724
33392
  const gender = f2.gender === "female" || active?.gender === "female" ? "female" : "male";
32725
- const profilePhoto = f2.photoBase64 || f2.bodyImage || active?.photoBase64 || active?.photoUrl;
32726
- const normalizedProfilePhoto = profilePhoto ? normalizeProfilePhotoSource(profilePhoto) : null;
32727
33393
  const customMeasurements = {};
32728
33394
  const wristCircumference = positiveNumber(f2.wristCircumference);
32729
33395
  if (wristCircumference != null) customMeasurements.wristCircumference = wristCircumference;
32730
- const draft = {
33396
+ const resultMeasurements = cleanProfileMeasurements(sizingResult?.estimates);
33397
+ const resultMeasurementsUnit = sizingResult?.estimatesUnit === "in" ? "in" : "cm";
33398
+ const formHeight = positiveNumber(f2.height);
33399
+ const activeHeight = positiveNumber(active?.height ?? active?.heightCm);
33400
+ const estimateHeight = positiveNumber(resultMeasurements?.height);
33401
+ const formWeight = positiveNumber(f2.weight);
33402
+ const activeWeight = positiveNumber(active?.weight ?? active?.weightKg);
33403
+ const estimateWeight = positiveNumber(resultMeasurements?.weight);
33404
+ const height = formHeight ?? activeHeight ?? estimateHeight;
33405
+ const weight = formWeight ?? activeWeight ?? estimateWeight;
33406
+ const heightUnitForDraft = formHeight != null ? f2.heightUnit || active?.heightUnit || heightUnit : activeHeight != null ? active?.heightUnit || heightUnit : estimateHeight != null ? resultMeasurementsUnit : f2.heightUnit || active?.heightUnit || heightUnit;
33407
+ const weightUnitForDraft = formWeight != null ? f2.weightUnit || active?.weightUnit || weightUnit : activeWeight != null ? active?.weightUnit || weightUnit : estimateWeight != null ? resultMeasurementsUnit : f2.weightUnit || active?.weightUnit || weightUnit;
33408
+ return {
32731
33409
  source: "size-result",
32732
33410
  createdAt: Date.now(),
32733
33411
  productId: effectiveProductId,
32734
33412
  productTitle,
32735
33413
  gender,
32736
- height: positiveNumber(f2.height) ?? positiveNumber(active?.height ?? active?.heightCm),
32737
- weight: positiveNumber(f2.weight) ?? positiveNumber(active?.weight ?? active?.weightKg),
32738
- heightUnit: f2.heightUnit || active?.heightUnit || heightUnit,
32739
- weightUnit: f2.weightUnit || active?.weightUnit || weightUnit,
33414
+ ...height != null ? { height } : {},
33415
+ ...weight != null ? { weight } : {},
33416
+ heightUnit: heightUnitForDraft,
33417
+ weightUnit: weightUnitForDraft,
32740
33418
  sizingUnit: active?.sizingUnit || sizingUnit,
32741
33419
  age: positiveNumber(f2.age) ?? positiveNumber(active?.age),
32742
33420
  chestProfile: validChestProfile(f2.chestProfile || active?.chestProfile),
@@ -32745,34 +33423,44 @@ function PrimeStyleTryonInner({
32745
33423
  bandSize: f2.bandSize || active?.bandSize,
32746
33424
  cupSize: f2.cupSize || active?.cupSize,
32747
33425
  braSizeRegion: f2.braSizeRegion || active?.braSizeRegion || "US",
32748
- ...normalizedProfilePhoto ? { photoBase64: normalizedProfilePhoto } : {},
33426
+ ...photoBase64 ? { photoBase64 } : {},
33427
+ ...resultMeasurements ? { measurements: resultMeasurements, measurementsUnit: resultMeasurementsUnit } : {},
32749
33428
  ...Object.keys(customMeasurements).length > 0 ? { customMeasurements } : {}
32750
33429
  };
33430
+ }, [activeProfileId, effectiveProductId, heightUnit, productTitle, profiles, sizingResult, sizingUnit, weightUnit]);
33431
+ const handleCompleteProfileFromResult = reactExports.useCallback(async () => {
33432
+ const f2 = formRef.current || {};
33433
+ const active = profiles.find((p2) => p2.id === activeProfileId) || null;
33434
+ const file = selectedFile || selectedFileRef.current;
33435
+ const profilePhoto = f2.photoBase64 || f2.bodyImage || (file ? await profilePhotoFromFile(file) : null) || active?.photoBase64 || active?.photoUrl;
33436
+ const normalizedProfilePhoto = profilePhoto ? normalizeProfilePhotoSource(profilePhoto) : null;
33437
+ const draft = buildProfileCompletionDraft(normalizedProfilePhoto);
32751
33438
  lsSet(PROFILE_COMPLETION_DRAFT_KEY, draft);
32752
33439
  setProfileCompletionDraft(draft);
32753
33440
  setProfileAuthError(null);
32754
33441
  setView("profiles");
32755
- }, [activeProfileId, effectiveProductId, heightUnit, productTitle, profiles, sizingUnit, weightUnit]);
32756
- const applyProfileStore = reactExports.useCallback((nextProfiles, nextActiveProfileId) => {
32757
- saveProfiles(nextProfiles);
33442
+ }, [activeProfileId, buildProfileCompletionDraft, profiles, selectedFile]);
33443
+ const applyProfileStore = reactExports.useCallback((nextProfiles, nextActiveProfileId, persistLocal = !profileSessionRef.current) => {
33444
+ if (persistLocal) saveProfiles(nextProfiles);
32758
33445
  setProfiles(nextProfiles);
32759
- setActiveProfileId$1(nextActiveProfileId);
33446
+ setActiveProfileIdState(nextActiveProfileId);
33447
+ if (persistLocal) setActiveProfileId(nextActiveProfileId);
32760
33448
  profileSyncSnapshotRef.current = JSON.stringify({ profiles: nextProfiles, activeProfileId: nextActiveProfileId });
32761
- }, [setActiveProfileId$1]);
33449
+ }, []);
32762
33450
  const hydrateProfileStore = reactExports.useCallback(async (session, seedProfiles, seedActiveProfileId) => {
32763
33451
  profileSyncHydratingRef.current = true;
32764
33452
  try {
32765
33453
  const remoteStore = await fetchRemoteProfiles(apiUrl, session.accessToken);
32766
33454
  if (remoteStore.profiles.length > 0) {
32767
- applyProfileStore(remoteStore.profiles, remoteStore.activeProfileId);
33455
+ applyProfileStore(remoteStore.profiles, remoteStore.activeProfileId, false);
32768
33456
  return;
32769
33457
  }
32770
33458
  if (seedProfiles.length > 0) {
32771
33459
  const savedStore = await saveRemoteProfiles(apiUrl, session.accessToken, seedProfiles, seedActiveProfileId);
32772
- applyProfileStore(savedStore.profiles, savedStore.activeProfileId);
33460
+ applyProfileStore(savedStore.profiles, savedStore.activeProfileId, false);
32773
33461
  return;
32774
33462
  }
32775
- applyProfileStore([], null);
33463
+ applyProfileStore([], null, false);
32776
33464
  } finally {
32777
33465
  profileSyncHydratingRef.current = false;
32778
33466
  }
@@ -32783,8 +33471,12 @@ function PrimeStyleTryonInner({
32783
33471
  try {
32784
33472
  const session = await startSocialProfileLogin(provider, apiUrl);
32785
33473
  setStoredProfileSession(session);
33474
+ profileSessionRef.current = session;
32786
33475
  setProfileSession(session);
32787
33476
  await hydrateProfileStore(session, profiles, activeProfileId);
33477
+ setProfileCompletionDraft(
33478
+ (current) => current ?? lsGet(PROFILE_COMPLETION_DRAFT_KEY, null)
33479
+ );
32788
33480
  } catch (error) {
32789
33481
  setProfileAuthError(error instanceof Error ? error.message : t2("Social login failed. Please try again."));
32790
33482
  } finally {
@@ -32793,10 +33485,28 @@ function PrimeStyleTryonInner({
32793
33485
  }, [activeProfileId, apiUrl, hydrateProfileStore, profiles, t2]);
32794
33486
  const handleProfileLogout = reactExports.useCallback(() => {
32795
33487
  clearStoredProfileSession();
33488
+ clearProfileLocalStorage();
33489
+ suppressNextProfilePersistRef.current = true;
33490
+ profileSessionRef.current = null;
32796
33491
  setProfileSession(null);
33492
+ setProfiles([]);
33493
+ setActiveProfileIdState(null);
33494
+ setProfileCompletionDraft(null);
33495
+ setProfileSaved(false);
33496
+ setProfileDetail(null);
33497
+ formRef.current = {};
33498
+ setFormKey((k2) => k2 + 1);
33499
+ if (previewUrl) URL.revokeObjectURL(previewUrl);
33500
+ setSelectedFile(null);
33501
+ selectedFileRef.current = null;
33502
+ setPreviewUrl(null);
33503
+ setBodyLandmarks(null);
33504
+ setFaceLandmarks(null);
33505
+ setEstimatedValues(null);
33506
+ setEstimatingProfileIds(/* @__PURE__ */ new Set());
32797
33507
  setProfileAuthError(null);
32798
33508
  setProfileAuthLoadingProvider(null);
32799
- }, []);
33509
+ }, [previewUrl]);
32800
33510
  const fileInputRef = reactExports.useRef(null);
32801
33511
  const apiRef = reactExports.useRef(null);
32802
33512
  const sseRef = reactExports.useRef(null);
@@ -32811,6 +33521,7 @@ function PrimeStyleTryonInner({
32811
33521
  const modelImageIdRef = reactExports.useRef(null);
32812
33522
  const autoTryOnFiredRef = reactExports.useRef(false);
32813
33523
  const bestGarmentImageRef = reactExports.useRef(null);
33524
+ const bestGarmentDetailImageRef = reactExports.useRef(null);
32814
33525
  reactExports.useEffect(() => {
32815
33526
  try {
32816
33527
  const key = getApiKey();
@@ -32850,6 +33561,7 @@ function PrimeStyleTryonInner({
32850
33561
  productTitle
32851
33562
  });
32852
33563
  bestGarmentImageRef.current = null;
33564
+ bestGarmentDetailImageRef.current = garmentDetailImage || null;
32853
33565
  if (garmentReferenceImage) {
32854
33566
  bestGarmentImageRef.current = garmentReferenceImage;
32855
33567
  console.log(`[ps-sdk:pick] #${fireN} early-return — using prop override`);
@@ -32875,8 +33587,9 @@ function PrimeStyleTryonInner({
32875
33587
  signal: ctrl.signal
32876
33588
  }).then((r2) => r2.ok ? r2.json() : null).then((j) => {
32877
33589
  if (j?.bestUrl) {
32878
- bestGarmentImageRef.current = j.bestUrl;
32879
- console.log(`[ps-sdk:pick] #${fireN} OK in ${Date.now() - t0}ms → ${j.bestUrl}`);
33590
+ bestGarmentImageRef.current = j.modelUrl || j.bestUrl;
33591
+ bestGarmentDetailImageRef.current = garmentDetailImage || j.detailUrl || null;
33592
+ console.log(`[ps-sdk:pick] #${fireN} ← OK in ${Date.now() - t0}ms → worn=${bestGarmentImageRef.current} detail=${bestGarmentDetailImageRef.current || "none"}`);
32880
33593
  } else {
32881
33594
  console.log(`[ps-sdk:pick] #${fireN} ← no bestUrl in response (${Date.now() - t0}ms)`);
32882
33595
  }
@@ -32887,7 +33600,7 @@ function PrimeStyleTryonInner({
32887
33600
  ctrl.abort();
32888
33601
  console.log(`[ps-sdk:pick] #${fireN} cleanup — aborted in-flight fetch`);
32889
33602
  };
32890
- }, [effectiveProductImages, garmentReferenceImage, apiUrl, productTitle, toBackendFetchableImageUrl]);
33603
+ }, [effectiveProductImages, garmentReferenceImage, garmentDetailImage, apiUrl, productTitle, toBackendFetchableImageUrl]);
32891
33604
  function summarizeSizeGuideForGender(value) {
32892
33605
  if (!value || typeof value !== "object") return void 0;
32893
33606
  const obj = value;
@@ -33079,6 +33792,11 @@ function PrimeStyleTryonInner({
33079
33792
  };
33080
33793
  }, [history]);
33081
33794
  reactExports.useEffect(() => {
33795
+ if (suppressNextProfilePersistRef.current) {
33796
+ suppressNextProfilePersistRef.current = false;
33797
+ return;
33798
+ }
33799
+ if (profileSessionRef.current) return;
33082
33800
  lsSet("profiles", profiles);
33083
33801
  }, [profiles]);
33084
33802
  reactExports.useEffect(() => {
@@ -33107,7 +33825,10 @@ function PrimeStyleTryonInner({
33107
33825
  };
33108
33826
  }, [activeProfileId, apiUrl, applyProfileStore, profileSession, profiles, t2]);
33109
33827
  reactExports.useEffect(() => {
33110
- const handler = () => setProfiles(lsGet("profiles", []));
33828
+ const handler = () => {
33829
+ if (profileSessionRef.current) return;
33830
+ setProfiles(lsGet("profiles", []));
33831
+ };
33111
33832
  window.addEventListener(PS_STORAGE_CHANGE_EVENT, handler);
33112
33833
  return () => window.removeEventListener(PS_STORAGE_CHANGE_EVENT, handler);
33113
33834
  }, []);
@@ -33155,6 +33876,14 @@ function PrimeStyleTryonInner({
33155
33876
  return 1;
33156
33877
  }
33157
33878
  }, [view]);
33879
+ const updateProfilesForCurrentSession = reactExports.useCallback((updater) => {
33880
+ setProfiles((prev) => {
33881
+ const source = profileSessionRef.current ? prev : lsGet("profiles", prev);
33882
+ const next = updater(source);
33883
+ if (!profileSessionRef.current) saveProfiles(next);
33884
+ return next;
33885
+ });
33886
+ }, []);
33158
33887
  const persistResultToProfile = reactExports.useCallback(
33159
33888
  (formData, recommendation, options) => {
33160
33889
  let targetId = activeProfileId;
@@ -33164,27 +33893,63 @@ function PrimeStyleTryonInner({
33164
33893
  return;
33165
33894
  }
33166
33895
  if (targetId && formData.gender === "female" && (formData.bandSize || formData.cupSize || formData.braSizeRegion)) {
33167
- updateProfile(targetId, {
33896
+ const patch = {
33168
33897
  ...formData.bandSize ? { bandSize: formData.bandSize } : {},
33169
33898
  ...formData.cupSize ? { cupSize: formData.cupSize } : {},
33170
33899
  ...formData.braSizeRegion ? { braSizeRegion: formData.braSizeRegion } : {}
33171
- });
33172
- setProfiles(lsGet("profiles", []));
33900
+ };
33901
+ if (profileSessionRef.current) {
33902
+ updateProfilesForCurrentSession((list) => list.map((p2) => p2.id === targetId ? { ...p2, ...patch, lastEditedAt: Date.now() } : p2));
33903
+ } else {
33904
+ updateProfile(targetId, patch);
33905
+ setProfiles(lsGet("profiles", []));
33906
+ }
33173
33907
  }
33908
+ const persistMeasurements = (est, unit) => {
33909
+ if (!targetId) return;
33910
+ if (profileSessionRef.current) {
33911
+ updateProfilesForCurrentSession((list) => list.map((p2) => p2.id === targetId ? {
33912
+ ...p2,
33913
+ measurements: est,
33914
+ measurementsUnit: unit,
33915
+ lastEditedAt: Date.now()
33916
+ } : p2));
33917
+ } else {
33918
+ updateProfileMeasurements(targetId, est, unit);
33919
+ setProfiles(lsGet("profiles", []));
33920
+ }
33921
+ };
33922
+ const persistSizeHistory = (entry) => {
33923
+ if (!targetId) return;
33924
+ if (profileSessionRef.current) {
33925
+ updateProfilesForCurrentSession((list) => list.map((p2) => {
33926
+ if (p2.id !== targetId) return p2;
33927
+ const sizeHistory = (p2.sizeHistory || []).filter((h) => h.productId !== entry.productId);
33928
+ sizeHistory.unshift(entry);
33929
+ return {
33930
+ ...p2,
33931
+ sizeHistory: sizeHistory.slice(0, 50),
33932
+ lastUsedAt: Date.now()
33933
+ };
33934
+ }));
33935
+ } else {
33936
+ addSizeToHistory(targetId, entry);
33937
+ setProfiles(lsGet("profiles", []));
33938
+ }
33939
+ };
33174
33940
  if (options?.skipBodyEstimate) {
33175
33941
  console.log("[ps-sdk:persist] skipping body estimates — face/head flow (no body context)");
33176
33942
  } else if (targetId && recommendation?.estimates) {
33177
33943
  const est = recommendation.estimates;
33178
33944
  const unit = recommendation.estimatesUnit || "cm";
33179
- updateProfileMeasurements(targetId, est, unit);
33180
- setProfiles(lsGet("profiles", []));
33945
+ persistMeasurements(est, unit);
33181
33946
  }
33182
33947
  setEstimationDone(true);
33183
33948
  if (recommendation?.recommendedSize && targetId) {
33184
33949
  const sectionsMap = recommendation.sections ? Object.fromEntries(
33185
33950
  Object.entries(recommendation.sections).map(([name, sec]) => [name, sec.recommendedSize])
33186
33951
  ) : void 0;
33187
- addSizeToHistory(targetId, {
33952
+ persistSizeHistory({
33188
33953
  productId: effectiveProductId,
33189
33954
  productTitle,
33190
33955
  productImage,
@@ -33193,10 +33958,9 @@ function PrimeStyleTryonInner({
33193
33958
  sections: sectionsMap,
33194
33959
  savedAt: Date.now()
33195
33960
  });
33196
- setProfiles(lsGet("profiles", []));
33197
33961
  }
33198
33962
  },
33199
- [activeProfileId, profiles, productImage, productTitle, effectiveProductId]
33963
+ [activeProfileId, profiles, productImage, productTitle, effectiveProductId, updateProfilesForCurrentSession]
33200
33964
  );
33201
33965
  const snapSubmitRef = reactExports.useRef(null);
33202
33966
  const [confirmProfile, setConfirmProfile] = reactExports.useState(null);
@@ -33205,7 +33969,7 @@ function PrimeStyleTryonInner({
33205
33969
  const profileWeight = p2.weight ?? p2.weightKg ?? 0;
33206
33970
  const hasStored = !!p2.measurements && Object.keys(p2.measurements).length > 0;
33207
33971
  const storedPhoto = p2.photoUrl || p2.photoBase64;
33208
- if (!hasStored && storedPhoto && profileHeight > 0 && snapSubmitRef.current) {
33972
+ if (storedPhoto && profileHeight > 0 && snapSubmitRef.current) {
33209
33973
  try {
33210
33974
  const dataUrl = await profilePhotoToDataUrl(storedPhoto);
33211
33975
  const blob = await fetch(dataUrl).then((r2) => r2.blob());
@@ -33219,6 +33983,7 @@ function PrimeStyleTryonInner({
33219
33983
  weightUnit: p2.weightUnit || "kg",
33220
33984
  gender: p2.gender,
33221
33985
  age: p2.age,
33986
+ ...hasStored && p2.measurements ? { knownMeasurements: p2.measurements } : {},
33222
33987
  ...snapBraFields({
33223
33988
  gender: p2.gender,
33224
33989
  bandSize: p2.bandSize,
@@ -33240,6 +34005,7 @@ function PrimeStyleTryonInner({
33240
34005
  setRestoredProductCarouselItems(null);
33241
34006
  setRestoredProductTitle(null);
33242
34007
  setRestoredProductUrl(null);
34008
+ setRestoredHistoryEntryId(null);
33243
34009
  setRestoredProductUrl(null);
33244
34010
  setSizingLoading(true);
33245
34011
  setEstimationDone(hasStored);
@@ -33262,6 +34028,7 @@ function PrimeStyleTryonInner({
33262
34028
  }
33263
34029
  }
33264
34030
  setView("size-result");
34031
+ const minVisible = new Promise((resolve) => setTimeout(resolve, 6e3));
33265
34032
  recommendForProduct({
33266
34033
  productId: effectiveProductId,
33267
34034
  productTitle,
@@ -33280,7 +34047,9 @@ function PrimeStyleTryonInner({
33280
34047
  if (res?.raw) setSizingResult(res.raw);
33281
34048
  setEstimationDone(true);
33282
34049
  }).catch(() => {
33283
- }).finally(() => setSizingLoading(false));
34050
+ }).finally(() => {
34051
+ void minVisible.then(() => setSizingLoading(false));
34052
+ });
33284
34053
  }, [effectiveProductId, productTitle, productImage, productCategory, productSubcategory, resolvedProductFitType, productType, productTagsList, productDescription, sizeGuideData, apiUrl, previewUrl]);
33285
34054
  const handleUseActiveProfile = reactExports.useCallback(async () => {
33286
34055
  const p2 = profiles.find((x2) => x2.id === activeProfileId);
@@ -33333,6 +34102,7 @@ function PrimeStyleTryonInner({
33333
34102
  setRestoredProductCarouselItems(null);
33334
34103
  setRestoredProductTitle(null);
33335
34104
  setRestoredProductUrl(null);
34105
+ setRestoredHistoryEntryId(null);
33336
34106
  if (!tryOnInFlight) {
33337
34107
  setResultImageUrl(null);
33338
34108
  setSizingResult(null);
@@ -33502,6 +34272,8 @@ function PrimeStyleTryonInner({
33502
34272
  }, [sizeGuide, formGender]);
33503
34273
  const submitSizing = reactExports.useCallback(async (methodOverride) => {
33504
34274
  if (!apiRef.current) return;
34275
+ setActiveSection(null);
34276
+ noFitFoundRef.current = false;
33505
34277
  const method = methodOverride || sizingMethod;
33506
34278
  const baseUrl = getApiUrl(apiUrl);
33507
34279
  const key = getApiKey();
@@ -33562,6 +34334,12 @@ function PrimeStyleTryonInner({
33562
34334
  if (resp.ok) {
33563
34335
  const data = await resp.json();
33564
34336
  await minVisible;
34337
+ if (data?.found === false) {
34338
+ setNoSizeReason(data?.reasoning === "NO_SIZE_CHART" ? "no-chart" : "no-match");
34339
+ setView("no-chart");
34340
+ setEstimationDone(true);
34341
+ return;
34342
+ }
33565
34343
  setSizingResult(data);
33566
34344
  onComplete?.(data);
33567
34345
  } else {
@@ -33623,6 +34401,10 @@ function PrimeStyleTryonInner({
33623
34401
  if (formRef.current.shoeUS) m2.shoeUS = formRef.current.shoeUS;
33624
34402
  if (formRef.current.shoeUK) m2.shoeUK = formRef.current.shoeUK;
33625
34403
  if (formRef.current.fitPreference) m2.fitPreference = formRef.current.fitPreference;
34404
+ if (formRef.current.bodyType) m2.bodyType = formRef.current.bodyType;
34405
+ if (formRef.current.chestProfile) m2.chestProfile = formRef.current.chestProfile;
34406
+ if (formRef.current.midsectionProfile) m2.midsectionProfile = formRef.current.midsectionProfile;
34407
+ if (formRef.current.hipProfile) m2.hipProfile = formRef.current.hipProfile;
33626
34408
  payload.measurements = m2;
33627
34409
  console.log("[PS-SDK] FINAL measurements:", JSON.stringify(m2));
33628
34410
  } else {
@@ -33661,7 +34443,8 @@ function PrimeStyleTryonInner({
33661
34443
  if (res.ok) {
33662
34444
  const data = await res.json();
33663
34445
  console.log("[PS-SDK] Sizing recommend RESULT:", JSON.stringify(data));
33664
- if (data?.found === false && data?.reasoning === "NO_SIZE_CHART") {
34446
+ if (data?.found === false) {
34447
+ setNoSizeReason(data?.reasoning === "NO_SIZE_CHART" ? "no-chart" : "no-match");
33665
34448
  setView("no-chart");
33666
34449
  setEstimationDone(true);
33667
34450
  return;
@@ -33750,6 +34533,7 @@ function PrimeStyleTryonInner({
33750
34533
  setFaceLandmarks(null);
33751
34534
  setSizingMethod("quick");
33752
34535
  setSizingLoading(true);
34536
+ setActiveSection(null);
33753
34537
  setView("size-result");
33754
34538
  submitSizing("quick");
33755
34539
  return;
@@ -33768,11 +34552,13 @@ function PrimeStyleTryonInner({
33768
34552
  setResultImageUrl(null);
33769
34553
  currentHistoryEntryIdRef.current = null;
33770
34554
  currentTryOnJobIdRef.current = null;
34555
+ setActiveSection(null);
33771
34556
  setRestoredProductImage(null);
33772
34557
  setRestoredProductImages(null);
33773
34558
  setRestoredProductCarouselItems(null);
33774
34559
  setRestoredProductTitle(null);
33775
34560
  setRestoredProductUrl(null);
34561
+ setRestoredHistoryEntryId(null);
33776
34562
  if (previewUrl) URL.revokeObjectURL(previewUrl);
33777
34563
  setSelectedFile(null);
33778
34564
  selectedFileRef.current = null;
@@ -33834,6 +34620,7 @@ function PrimeStyleTryonInner({
33834
34620
  setRestoredProductImages(null);
33835
34621
  setRestoredProductCarouselItems(null);
33836
34622
  setRestoredProductTitle(null);
34623
+ setRestoredHistoryEntryId(null);
33837
34624
  completedRef.current = false;
33838
34625
  modelImageIdRef.current = null;
33839
34626
  noFitFoundRef.current = false;
@@ -33845,12 +34632,14 @@ function PrimeStyleTryonInner({
33845
34632
  historyTryonSavedRef.current = false;
33846
34633
  currentHistoryEntryIdRef.current = null;
33847
34634
  currentTryOnJobIdRef.current = null;
34635
+ setActiveSection(null);
33848
34636
  setSizingLoading(true);
33849
34637
  setEstimationDone(false);
33850
34638
  setView("size-result");
33851
34639
  if (measurementType === "face" || measurementType === "head") {
33852
34640
  setFaceLandmarks(null);
33853
34641
  const minVisible2 = new Promise((r2) => setTimeout(r2, 4500));
34642
+ let landmarksVisibleMin = null;
33854
34643
  try {
33855
34644
  const faceResult = await detectFaceMeasurements(objUrl);
33856
34645
  if (!faceResult) {
@@ -33863,7 +34652,10 @@ function PrimeStyleTryonInner({
33863
34652
  setSizingLoading(false);
33864
34653
  return;
33865
34654
  }
33866
- if (faceResult) setFaceLandmarks(faceResult.landmarks);
34655
+ if (faceResult) {
34656
+ setFaceLandmarks(faceResult.landmarks);
34657
+ landmarksVisibleMin = new Promise((r2) => setTimeout(r2, 1200));
34658
+ }
33867
34659
  const facePayload = {
33868
34660
  product: productContext,
33869
34661
  sizeGuide: sizeGuide ?? { found: false },
@@ -33891,6 +34683,14 @@ function PrimeStyleTryonInner({
33891
34683
  });
33892
34684
  if (recRes.ok) {
33893
34685
  const recData = await recRes.json();
34686
+ if (recData?.found === false) {
34687
+ await Promise.all([minVisible2, landmarksVisibleMin || Promise.resolve()]);
34688
+ setNoSizeReason(recData?.reasoning === "NO_SIZE_CHART" ? "no-chart" : "no-match");
34689
+ setView("no-chart");
34690
+ setEstimationDone(true);
34691
+ setSizingLoading(false);
34692
+ return;
34693
+ }
33894
34694
  setSizingResult(recData);
33895
34695
  onComplete?.(recData);
33896
34696
  persistResultToProfile(
@@ -33908,7 +34708,7 @@ function PrimeStyleTryonInner({
33908
34708
  { skipBodyEstimate: true }
33909
34709
  );
33910
34710
  } else {
33911
- await minVisible2;
34711
+ await Promise.all([minVisible2, landmarksVisibleMin || Promise.resolve()]);
33912
34712
  const errBody = await recRes.text().catch(() => "");
33913
34713
  console.error("[ps-sdk] face-recommend failed:", recRes.status, errBody);
33914
34714
  setErrorMessage(t2("Unable to get size recommendation. Please try manual measurements."));
@@ -33919,14 +34719,14 @@ function PrimeStyleTryonInner({
33919
34719
  }
33920
34720
  } catch (err) {
33921
34721
  console.error("[ps-sdk] face-recommend failed:", err);
33922
- await minVisible2;
34722
+ await Promise.all([minVisible2, landmarksVisibleMin || Promise.resolve()]);
33923
34723
  setErrorMessage(t2("Unable to get size recommendation. Please try manual measurements."));
33924
34724
  setEstimationDone(true);
33925
34725
  setSizingLoading(false);
33926
34726
  setView("error");
33927
34727
  return;
33928
34728
  }
33929
- await minVisible2;
34729
+ await Promise.all([minVisible2, landmarksVisibleMin || Promise.resolve()]);
33930
34730
  setSizingLoading(false);
33931
34731
  return;
33932
34732
  }
@@ -34010,6 +34810,7 @@ function PrimeStyleTryonInner({
34010
34810
  if (recRes.ok) {
34011
34811
  const recData = await recRes.json();
34012
34812
  if (recData?.found === false && recData?.reasoning === "NO_SIZE_CHART") {
34813
+ setNoSizeReason("no-chart");
34013
34814
  setView("no-chart");
34014
34815
  setEstimationDone(true);
34015
34816
  setSizingLoading(false);
@@ -34023,8 +34824,13 @@ function PrimeStyleTryonInner({
34023
34824
  noFitFoundRef.current = true;
34024
34825
  setTryOnProcessing(false);
34025
34826
  setTryOnStartedAt(null);
34827
+ setNoSizeReason("no-match");
34026
34828
  setSizingResult({ ...recData, found: false });
34027
34829
  onComplete?.({ ...recData, found: false });
34830
+ setView("no-chart");
34831
+ setEstimationDone(true);
34832
+ setSizingLoading(false);
34833
+ return;
34028
34834
  } else {
34029
34835
  setSizingResult(recData);
34030
34836
  onComplete?.(recData);
@@ -34165,6 +34971,7 @@ function PrimeStyleTryonInner({
34165
34971
  }
34166
34972
  console.log("[ps-sdk:tryon] fitInfo built", { count: fitInfo?.length || 0, areas: fitInfo?.map((f2) => `${f2.area}(${f2.fit})`) });
34167
34973
  let garmentImage = productImage;
34974
+ let detailImage = garmentDetailImage || bestGarmentDetailImageRef.current || null;
34168
34975
  if (garmentReferenceImage) {
34169
34976
  garmentImage = garmentReferenceImage;
34170
34977
  } else if (bestGarmentImageRef.current) {
@@ -34177,6 +34984,9 @@ function PrimeStyleTryonInner({
34177
34984
  garmentImage = best;
34178
34985
  }
34179
34986
  }
34987
+ if (!detailImage && effectiveProductImages?.length) {
34988
+ detailImage = effectiveProductImages.find((img) => img && img !== garmentImage) || null;
34989
+ }
34180
34990
  const response = await apiRef.current.submitTryOn(
34181
34991
  modelImage,
34182
34992
  garmentImage,
@@ -34185,11 +34995,14 @@ function PrimeStyleTryonInner({
34185
34995
  {
34186
34996
  productId: effectiveProductId,
34187
34997
  productTitle,
34998
+ productCategory,
34999
+ productSubcategory,
34188
35000
  productFitType: resolvedProductFitType,
34189
35001
  productType,
34190
35002
  productTags: productTagsList,
34191
35003
  productDescription,
34192
35004
  productMaterial,
35005
+ ...detailImage && detailImage !== garmentImage ? { garmentDetailImage: detailImage } : {},
34193
35006
  silhouetteContext: buildSilhouetteContext(
34194
35007
  sizingResult,
34195
35008
  sizeGuide,
@@ -34253,7 +35066,7 @@ function PrimeStyleTryonInner({
34253
35066
  setView("error");
34254
35067
  onError?.({ message, code });
34255
35068
  }
34256
- }, [selectedFile, productImage, effectiveProductImages, garmentReferenceImage, productTitle, resolvedProductFitType, productType, productTagsList, productDescription, productMaterial, measurementType, sizingResult, sizeGuide, apiUrl, onProcessing, onError, handleVtoUpdate]);
35069
+ }, [selectedFile, productImage, effectiveProductImages, garmentReferenceImage, garmentDetailImage, productTitle, productCategory, productSubcategory, resolvedProductFitType, productType, productTagsList, productDescription, productMaterial, measurementType, sizingResult, sizeGuide, apiUrl, onProcessing, onError, handleVtoUpdate]);
34257
35070
  reactExports.useEffect(() => {
34258
35071
  if (view !== "size-result") {
34259
35072
  autoTryOnFiredRef.current = false;
@@ -34286,17 +35099,86 @@ function PrimeStyleTryonInner({
34286
35099
  }).catch(() => window.open(resultImageUrl, "_blank"));
34287
35100
  }
34288
35101
  }, [resultImageUrl]);
34289
- const handleContinueShopping = reactExports.useCallback(() => {
34290
- const historyUrl = restoredProductUrl || "";
34291
- if (historyUrl && typeof window !== "undefined") {
35102
+ const openProductPageUrl = reactExports.useCallback((url) => {
35103
+ if (url && typeof window !== "undefined") {
34292
35104
  try {
34293
- window.open(new URL(historyUrl, window.location.origin).href, "_blank", "noopener,noreferrer");
35105
+ window.open(new URL(url, window.location.origin).href, "_blank", "noopener,noreferrer");
34294
35106
  } catch {
34295
- window.open(historyUrl, "_blank", "noopener,noreferrer");
35107
+ window.open(url, "_blank", "noopener,noreferrer");
34296
35108
  }
34297
35109
  }
35110
+ }, []);
35111
+ const handleContinueShopping = reactExports.useCallback(() => {
35112
+ handleClose();
35113
+ }, [handleClose]);
35114
+ const handleBackToProductPage = reactExports.useCallback(() => {
35115
+ const targetUrl = restoredProductUrl || effectiveProductUrl || "";
35116
+ if (targetUrl) {
35117
+ openProductPageUrl(targetUrl);
35118
+ return;
35119
+ }
34298
35120
  handleClose();
34299
- }, [handleClose, restoredProductUrl]);
35121
+ }, [effectiveProductUrl, handleClose, openProductPageUrl, restoredProductUrl]);
35122
+ const buildAddToBagSelectedSizes = reactExports.useCallback(() => {
35123
+ const overrides = Object.values(pendingCustomSizesRef.current);
35124
+ if (overrides.length) {
35125
+ return overrides.map((override) => ({
35126
+ sectionName: override.sectionName,
35127
+ selectedSize: override.selectedSize,
35128
+ selectedLength: override.selectedLength,
35129
+ displayLabel: override.displayLabel,
35130
+ isOverride: true
35131
+ }));
35132
+ }
35133
+ const sections = sizingResult?.sections;
35134
+ if (sections && typeof sections === "object") {
35135
+ const selected = Object.entries(sections).map(([sectionName, sectionResult]) => {
35136
+ const result = sectionResult;
35137
+ const selectedSize = result.size || result.recommendedSize || "";
35138
+ if (!selectedSize) return null;
35139
+ const displayLabel = [selectedSize, result.length].filter(Boolean).join(" / ");
35140
+ return {
35141
+ sectionName,
35142
+ selectedSize,
35143
+ selectedLength: result.length,
35144
+ displayLabel,
35145
+ isOverride: false
35146
+ };
35147
+ }).filter(Boolean);
35148
+ return selected.length ? selected : void 0;
35149
+ }
35150
+ const recommendedSize = sizingResult?.recommendedSize || "";
35151
+ if (!recommendedSize) return void 0;
35152
+ return [{
35153
+ sectionName: "Your Fit",
35154
+ selectedSize: recommendedSize,
35155
+ displayLabel: recommendedSize,
35156
+ isOverride: false
35157
+ }];
35158
+ }, [sizingResult]);
35159
+ const handleAddToBag = reactExports.useCallback(async () => {
35160
+ if (!onAddToBag || !sizingResult) return;
35161
+ await onAddToBag({
35162
+ productId,
35163
+ productTitle: restoredProductTitle || productTitle,
35164
+ productUrl: restoredProductUrl || effectiveProductUrl,
35165
+ recommendedSize: sizingResult.recommendedSize,
35166
+ sizingResult,
35167
+ resultImageUrl: resultImageUrlRef.current || resultImageUrl,
35168
+ historyEntryId: currentHistoryEntryIdRef.current ?? void 0,
35169
+ selectedSizes: buildAddToBagSelectedSizes()
35170
+ });
35171
+ }, [
35172
+ buildAddToBagSelectedSizes,
35173
+ effectiveProductUrl,
35174
+ onAddToBag,
35175
+ productId,
35176
+ productTitle,
35177
+ restoredProductTitle,
35178
+ restoredProductUrl,
35179
+ resultImageUrl,
35180
+ sizingResult
35181
+ ]);
34300
35182
  const handleTryOnFeedbackSubmit = reactExports.useCallback(async ({ rating, note }) => {
34301
35183
  const profileLoggedIn = Boolean(profileSession);
34302
35184
  const activeProfile = profileLoggedIn ? profiles.find((profile) => profile.id === activeProfileId) : null;
@@ -34355,6 +35237,7 @@ function PrimeStyleTryonInner({
34355
35237
  setRestoredProductCarouselItems(null);
34356
35238
  setRestoredProductTitle(null);
34357
35239
  setRestoredProductUrl(null);
35240
+ setRestoredHistoryEntryId(null);
34358
35241
  setErrorMessage(null);
34359
35242
  setSizingMethod(null);
34360
35243
  setSizingResult(null);
@@ -34487,6 +35370,7 @@ function PrimeStyleTryonInner({
34487
35370
  }));
34488
35371
  const latestResultImageUrl = resultImageUrlRef.current;
34489
35372
  const durableResultUrl = durableHistoryImageUrl(latestResultImageUrl);
35373
+ const profileDraftSnapshot = buildProfileCompletionDraft(null);
34490
35374
  const entry = {
34491
35375
  id: id2,
34492
35376
  productId,
@@ -34511,6 +35395,7 @@ function PrimeStyleTryonInner({
34511
35395
  sections: sizeGuide.sections,
34512
35396
  sectionImages: sizeGuide.sectionImages
34513
35397
  } : void 0,
35398
+ profileCompletionDraft: profileDraftSnapshot,
34514
35399
  date: Date.now(),
34515
35400
  hasPhoto: hasPhoto || void 0,
34516
35401
  hasResult: latestResultImageUrl ? true : void 0,
@@ -34527,7 +35412,7 @@ function PrimeStyleTryonInner({
34527
35412
  return next;
34528
35413
  });
34529
35414
  return id2;
34530
- }, [productId, productTitle, effectiveProductUrl, productImage, effectiveProductImages, effectiveProductCarouselItems, resultImageUrl, sizingResult, sizeGuide, activeProfileId, profiles, selectedFile]);
35415
+ }, [productId, productTitle, effectiveProductUrl, productImage, effectiveProductImages, effectiveProductCarouselItems, resultImageUrl, sizingResult, sizeGuide, activeProfileId, profiles, selectedFile, buildProfileCompletionDraft]);
34531
35416
  const persistHistoryResult = reactExports.useCallback((entryId, imageUrl, cleanupWhenIdle) => {
34532
35417
  void (async () => {
34533
35418
  const durableResultUrl = durableHistoryImageUrl(imageUrl);
@@ -34642,6 +35527,33 @@ function PrimeStyleTryonInner({
34642
35527
  );
34643
35528
  setRestoredProductTitle(entry.productTitle || null);
34644
35529
  setRestoredProductUrl(entry.productUrl || null);
35530
+ setRestoredHistoryEntryId(entry.id);
35531
+ if (entry.profileCompletionDraft) {
35532
+ const draft = entry.profileCompletionDraft;
35533
+ const restoredForm = { ...formRef.current };
35534
+ if (draft.gender) restoredForm.gender = draft.gender;
35535
+ if (draft.height != null) restoredForm.height = String(draft.height);
35536
+ if (draft.weight != null) restoredForm.weight = String(draft.weight);
35537
+ if (draft.heightUnit) restoredForm.heightUnit = String(draft.heightUnit);
35538
+ if (draft.weightUnit) restoredForm.weightUnit = String(draft.weightUnit);
35539
+ if (draft.age != null) restoredForm.age = String(draft.age);
35540
+ if (draft.chestProfile) restoredForm.chestProfile = draft.chestProfile;
35541
+ if (draft.midsectionProfile) restoredForm.midsectionProfile = draft.midsectionProfile;
35542
+ if (draft.hipProfile) restoredForm.hipProfile = draft.hipProfile;
35543
+ if (draft.bandSize) restoredForm.bandSize = draft.bandSize;
35544
+ if (draft.cupSize) restoredForm.cupSize = draft.cupSize;
35545
+ if (draft.braSizeRegion) restoredForm.braSizeRegion = draft.braSizeRegion;
35546
+ if (draft.customMeasurements) {
35547
+ for (const [key, value] of Object.entries(draft.customMeasurements)) {
35548
+ restoredForm[key] = String(value);
35549
+ }
35550
+ }
35551
+ formRef.current = restoredForm;
35552
+ setFormGender(restoredForm.gender || "male");
35553
+ if (draft.heightUnit) setHeightUnit(String(draft.heightUnit));
35554
+ if (draft.weightUnit) setWeightUnit(String(draft.weightUnit));
35555
+ if (draft.sizingUnit) setSizingUnit(String(draft.sizingUnit));
35556
+ }
34645
35557
  if (entry.sizingResult) {
34646
35558
  setSizingResult(entry.sizingResult);
34647
35559
  } else if (entry.recommendedSize) {
@@ -34799,6 +35711,7 @@ function PrimeStyleTryonInner({
34799
35711
  basicOnly: false,
34800
35712
  initialStep: bodyProfileInitialStep === "basics" ? "basics" : void 0,
34801
35713
  simplePhotoOnly,
35714
+ simpleAccessoryLayout: measurementType === "body-basic",
34802
35715
  simpleQuestionMode: measurementType === "foot" ? "shoeReference" : "heightWeight",
34803
35716
  formRef,
34804
35717
  sizingCountry,
@@ -34901,6 +35814,12 @@ function PrimeStyleTryonInner({
34901
35814
  setView,
34902
35815
  handleDownload,
34903
35816
  onContinueShopping: handleContinueShopping,
35817
+ isHistoryResult: !!restoredHistoryEntryId,
35818
+ onBackToProductPage: handleBackToProductPage,
35819
+ onAddToBag: onAddToBag ? handleAddToBag : void 0,
35820
+ addToBagLabel,
35821
+ continueShoppingLabel,
35822
+ backToProductPageLabel,
34904
35823
  onTryOnFeedbackSubmit: handleTryOnFeedbackSubmit,
34905
35824
  selectedFile,
34906
35825
  previewUrl,
@@ -35000,12 +35919,31 @@ function PrimeStyleTryonInner({
35000
35919
  setView("body-profile");
35001
35920
  },
35002
35921
  onSaveProfileMeasurements: (id2, measurements, unit) => {
35003
- updateProfileMeasurements(id2, measurements, unit ?? profiles.find((x2) => x2.id === id2)?.measurementsUnit ?? "cm");
35004
- setProfiles(lsGet("profiles", []));
35922
+ const nextUnit = unit ?? profiles.find((x2) => x2.id === id2)?.measurementsUnit ?? "cm";
35923
+ if (profileSessionRef.current) {
35924
+ updateProfilesForCurrentSession((list) => list.map((p2) => p2.id === id2 ? {
35925
+ ...p2,
35926
+ measurements,
35927
+ measurementsUnit: nextUnit,
35928
+ lastEditedAt: Date.now()
35929
+ } : p2));
35930
+ } else {
35931
+ updateProfileMeasurements(id2, measurements, nextUnit);
35932
+ setProfiles(lsGet("profiles", []));
35933
+ }
35005
35934
  },
35006
35935
  onSaveBraSize: (id2, bandSize, cupSize) => {
35007
- updateProfile(id2, { bandSize, cupSize });
35008
- setProfiles(lsGet("profiles", []));
35936
+ if (profileSessionRef.current) {
35937
+ updateProfilesForCurrentSession((list) => list.map((p2) => p2.id === id2 ? {
35938
+ ...p2,
35939
+ bandSize,
35940
+ cupSize,
35941
+ lastEditedAt: Date.now()
35942
+ } : p2));
35943
+ } else {
35944
+ updateProfile(id2, { bandSize, cupSize });
35945
+ setProfiles(lsGet("profiles", []));
35946
+ }
35009
35947
  },
35010
35948
  onEditProfile: (p2) => {
35011
35949
  setProfileDetail(p2);
@@ -35078,13 +36016,24 @@ function PrimeStyleTryonInner({
35078
36016
  bodyLandmarks: landmarks ?? void 0
35079
36017
  })).then((est) => {
35080
36018
  if (est) {
35081
- updateProfileMeasurements(newProfile.id, est.estimates, est.unit);
36019
+ if (profileSessionRef.current) {
36020
+ updateProfilesForCurrentSession((list) => list.map((p2) => p2.id === newProfile.id ? {
36021
+ ...p2,
36022
+ measurements: est.estimates,
36023
+ measurementsUnit: est.unit,
36024
+ lastEditedAt: Date.now()
36025
+ } : p2));
36026
+ } else {
36027
+ updateProfileMeasurements(newProfile.id, est.estimates, est.unit);
36028
+ }
35082
36029
  if (est.userEstimates) {
35083
- const all = lsGet("profiles", []);
35084
- const idx = all.findIndex((p2) => p2.id === newProfile.id);
35085
- if (idx >= 0) {
36030
+ const userEstimates = est.userEstimates;
36031
+ updateProfilesForCurrentSession((list) => {
36032
+ const idx = list.findIndex((p2) => p2.id === newProfile.id);
36033
+ if (idx < 0) return list;
36034
+ const all = [...list];
35086
36035
  const target = all[idx];
35087
- const u2 = est.userEstimates;
36036
+ const u2 = userEstimates;
35088
36037
  const patched = { ...target };
35089
36038
  if (u2.height && !(target.height || target.heightCm)) {
35090
36039
  patched.height = u2.height;
@@ -35100,10 +36049,10 @@ function PrimeStyleTryonInner({
35100
36049
  patched.age = u2.age;
35101
36050
  }
35102
36051
  all[idx] = patched;
35103
- lsSet("profiles", all);
35104
- }
36052
+ return all;
36053
+ });
35105
36054
  }
35106
- setProfiles(lsGet("profiles", []));
36055
+ if (!profileSessionRef.current) setProfiles(lsGet("profiles", []));
35107
36056
  }
35108
36057
  }).catch(() => {
35109
36058
  }).finally(() => {
@@ -35116,9 +36065,8 @@ function PrimeStyleTryonInner({
35116
36065
  }
35117
36066
  },
35118
36067
  onDeleteProfile: (id2) => {
35119
- setProfiles((prev) => prev.filter((p2) => p2.id !== id2));
36068
+ updateProfilesForCurrentSession((prev) => prev.filter((p2) => p2.id !== id2));
35120
36069
  if (activeProfileId === id2) setActiveProfileId$1(null);
35121
- lsSet("profiles", lsGet("profiles", []).filter((p2) => p2.id !== id2));
35122
36070
  },
35123
36071
  onRequestDelete: (id2) => setDeleteConfirmId(id2),
35124
36072
  onLogout: handleProfileLogout,
@@ -35152,6 +36100,7 @@ function PrimeStyleTryonInner({
35152
36100
  {
35153
36101
  productImage,
35154
36102
  productTitle,
36103
+ reason: noSizeReason,
35155
36104
  onTryOn: () => setView("photo-guide"),
35156
36105
  onClose: onClose ?? (() => {
35157
36106
  }),
@@ -35378,9 +36327,7 @@ function PrimeStyleTryonInner({
35378
36327
  {
35379
36328
  onConfirm: () => {
35380
36329
  const id2 = deleteConfirmId;
35381
- const updated = lsGet("profiles", []).filter((p2) => p2.id !== id2);
35382
- lsSet("profiles", updated);
35383
- setProfiles(updated);
36330
+ updateProfilesForCurrentSession((prev) => prev.filter((p2) => p2.id !== id2));
35384
36331
  if (activeProfileId === id2) setActiveProfileId$1(null);
35385
36332
  setDeleteConfirmId(null);
35386
36333
  },