@primestyleai/tryon 5.5.3 → 5.5.5

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.
@@ -291,29 +291,36 @@ const STYLES = `
291
291
  }
292
292
 
293
293
  .ps-tryon-btn {
294
- display: inline-flex; align-items: center; gap: 0.42vw;
295
- padding: var(--ps-btn-padding, 0.63vw 1.25vw);
294
+ display: inline-flex; align-items: center; gap: clamp(6px, 0.42vw, 8px);
295
+ padding: var(--ps-btn-padding, clamp(10px, 0.63vw, 14px) clamp(16px, 1.25vw, 24px));
296
296
  background: var(--ps-btn-bg, var(--ps-accent)); color: var(--ps-btn-color, #FFFFFF);
297
297
  font-family: var(--ps-btn-font, system-ui, -apple-system, sans-serif);
298
- font-size: var(--ps-btn-font-size, 0.73vw); font-weight: var(--ps-btn-font-weight, 600);
299
- border: var(--ps-btn-border, none); border-radius: var(--ps-btn-radius, 0.42vw);
298
+ font-size: var(--ps-btn-font-size, clamp(13px, 0.73vw, 15px)); font-weight: var(--ps-btn-font-weight, 600);
299
+ border: var(--ps-btn-border, none); border-radius: var(--ps-btn-radius, clamp(6px, 0.42vw, 8px));
300
300
  cursor: pointer; transition: all 0.2s ease;
301
301
  width: var(--ps-btn-width, auto); height: var(--ps-btn-height, auto);
302
302
  box-shadow: var(--ps-btn-shadow, none); line-height: 1; white-space: nowrap;
303
+ box-sizing: border-box;
303
304
  }
304
- .ps-tryon-btn svg { width: var(--ps-btn-icon-size, 0.94vw); height: var(--ps-btn-icon-size, 0.94vw); flex-shrink: 0; }
305
+ .ps-tryon-btn svg { width: var(--ps-btn-icon-size, clamp(16px, 0.94vw, 18px)); height: var(--ps-btn-icon-size, clamp(16px, 0.94vw, 18px)); flex-shrink: 0; }
305
306
  .ps-tryon-btn:hover { background: var(--ps-btn-hover-bg, var(--ps-accent-hover)); transform: translateY(-1px); }
306
307
  .ps-tryon-btn:active { transform: translateY(0); }
307
308
 
308
309
  .ps-tryon-overlay {
309
310
  position: fixed; inset: 0; background: var(--ps-modal-overlay, rgba(0,0,0,0.6));
310
311
  display: flex; align-items: center; justify-content: center;
311
- z-index: 999999;
312
+ z-index: 2147483647;
313
+ isolation: isolate;
314
+ contain: layout style;
312
315
  padding: 0.83vw;
313
316
  padding: max(0.83vw, env(safe-area-inset-top)) max(0.83vw, env(safe-area-inset-right)) max(0.83vw, env(safe-area-inset-bottom)) max(0.83vw, env(safe-area-inset-left));
314
317
  animation: ps-fade-in 0.2s ease;
315
318
  overflow-y: auto; -webkit-overflow-scrolling: touch;
319
+ font-family: system-ui, -apple-system, sans-serif;
320
+ -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale;
321
+ box-sizing: border-box;
316
322
  }
323
+ .ps-tryon-overlay, .ps-tryon-overlay *, .ps-tryon-overlay *::before, .ps-tryon-overlay *::after { box-sizing: border-box; }
317
324
  @keyframes ps-fade-in { from { opacity: 0; } to { opacity: 1; } }
318
325
 
319
326
  .ps-tryon-modal {
@@ -369,21 +376,22 @@ const STYLES = `
369
376
  /* Language switcher */
370
377
  .ps-tryon-lang-wrap { position: relative; z-index: 99999; }
371
378
  .ps-tryon-lang-trigger {
372
- display: flex; align-items: center; gap: 0.36vw;
373
- padding: 0.36vw 0.73vw;
374
- border: 1.5px solid var(--ps-border-color); border-radius: 0.57vw;
379
+ display: flex; align-items: center; gap: clamp(5px, 0.36vw, 6px);
380
+ padding: clamp(6px, 0.36vw, 8px) clamp(10px, 0.73vw, 12px);
381
+ border: 1.5px solid var(--ps-border-color); border-radius: clamp(8px, 0.57vw, 10px);
375
382
  background: transparent; cursor: pointer; color: var(--ps-text-secondary);
376
383
  transition: all 0.25s ease; font-family: inherit; white-space: nowrap;
384
+ min-height: 36px;
377
385
  }
378
386
  .ps-tryon-lang-trigger:hover, .ps-tryon-lang-trigger.ps-active {
379
387
  border-color: var(--ps-accent); color: var(--ps-accent); background: rgba(33,84,239,0.06);
380
388
  }
381
- .ps-tryon-lang-trigger svg { stroke: currentColor; fill: none; flex-shrink: 0; width: 0.8vw; height: 0.8vw; }
389
+ .ps-tryon-lang-trigger svg { stroke: currentColor; fill: none; flex-shrink: 0; width: clamp(13px, 0.8vw, 14px); height: clamp(13px, 0.8vw, 14px); }
382
390
  .ps-tryon-lang-current {
383
- font-size: 0.68vw; font-weight: 500; letter-spacing: 0.01em;
391
+ font-size: clamp(12px, 0.68vw, 13px); font-weight: 500; letter-spacing: 0.01em;
384
392
  }
385
393
  .ps-tryon-lang-arrow {
386
- font-size: 0.57vw; transition: transform 0.25s ease; display: inline-block;
394
+ font-size: clamp(10px, 0.57vw, 11px); transition: transform 0.25s ease; display: inline-block;
387
395
  }
388
396
  .ps-tryon-lang-arrow.ps-open { transform: rotate(180deg); }
389
397
 
@@ -2614,24 +2622,83 @@ const STYLES = `
2614
2622
  .ps-tryon-detail-delete:hover { background: rgba(239,68,68,0.06); border-color: var(--ps-error-color); }
2615
2623
  .ps-tryon-detail-delete svg { stroke: currentColor; fill: none; }
2616
2624
 
2617
- /* Mobile responsive */
2625
+ /* ════════════════════════════════════════════════════════════════
2626
+ Mobile (≤768px) — full-screen drawer, bigger touch targets,
2627
+ px-based sizing (vw becomes sub-pixel and unreadable on phones)
2628
+ ════════════════════════════════════════════════════════════════ */
2618
2629
  @media (max-width: 768px) {
2630
+ /* ── Trigger button: minimum 44px touch target, readable text ── */
2631
+ .ps-tryon-btn {
2632
+ padding: 12px 20px; font-size: 14px; gap: 8px;
2633
+ border-radius: 8px; min-height: 44px;
2634
+ }
2635
+ .ps-tryon-btn svg { width: 18px; height: 18px; }
2636
+
2637
+ /* ── Overlay: full screen, no centering, slide-up drawer feel ── */
2619
2638
  .ps-tryon-overlay {
2620
- padding: 0;
2621
- padding: env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left);
2622
- align-items: stretch; justify-content: stretch;
2639
+ padding: 0 !important;
2640
+ align-items: stretch !important; justify-content: stretch !important;
2641
+ overflow: hidden !important;
2623
2642
  }
2624
- .ps-tryon-modal {
2625
- max-width: 100%; max-height: none; width: 100%;
2626
- border-radius: 0; box-shadow: none;
2627
- min-height: 100%; flex: 1;
2628
- display: flex; flex-direction: column;
2643
+
2644
+ /* ── Modal: occupies entire viewport as a drawer ── */
2645
+ .ps-tryon-modal,
2646
+ .ps-tryon-modal-wide {
2647
+ max-width: 100vw !important; max-width: 100dvw !important;
2648
+ max-height: 100vh !important; max-height: 100dvh !important;
2649
+ width: 100vw !important; width: 100dvw !important;
2650
+ height: 100vh !important; height: 100dvh !important;
2651
+ min-height: 100vh !important; min-height: 100dvh !important;
2652
+ border-radius: 0 !important; box-shadow: none !important;
2653
+ margin: 0 !important;
2654
+ display: flex !important; flex-direction: column !important;
2655
+ overflow: hidden !important;
2656
+ animation: ps-mobile-slide-up 0.32s cubic-bezier(0.32, 0.72, 0, 1);
2657
+ padding-top: env(safe-area-inset-top);
2658
+ padding-bottom: env(safe-area-inset-bottom);
2659
+ padding-left: env(safe-area-inset-left);
2660
+ padding-right: env(safe-area-inset-right);
2661
+ }
2662
+ .ps-tryon-modal > :last-child { flex: 1; min-height: 0; }
2663
+
2664
+ /* ── Header: bigger touch targets, fixed top ── */
2665
+ .ps-tryon-header {
2666
+ border-radius: 0 !important;
2667
+ padding: 10px 14px !important;
2668
+ flex-shrink: 0;
2669
+ background: var(--ps-modal-header-bg, rgba(255,255,255,0.95)) !important;
2670
+ }
2671
+ .ps-tryon-header-icon {
2672
+ width: 40px !important; height: 40px !important;
2673
+ border-radius: 10px !important;
2629
2674
  }
2630
- .ps-tryon-modal-wide { max-width: 100%; width: 100%; height: auto; }
2631
- .ps-tryon-modal > :last-child { flex: 1; }
2632
- .ps-tryon-header { border-radius: 0; }
2675
+ .ps-tryon-header-icon svg { width: 18px !important; height: 18px !important; }
2676
+ .ps-tryon-close { width: 40px !important; height: 40px !important; border-radius: 10px !important; }
2677
+ .ps-tryon-close svg { width: 22px !important; height: 22px !important; }
2678
+
2679
+ /* ── Body: scrollable, comfortable padding, momentum scroll ── */
2680
+ .ps-tryon-body {
2681
+ padding: 16px !important;
2682
+ flex: 1 !important; min-height: 0 !important;
2683
+ overflow-y: auto !important; overflow-x: hidden !important;
2684
+ -webkit-overflow-scrolling: touch;
2685
+ }
2686
+
2687
+ /* ── Back button: bigger, easier to tap ── */
2688
+ .ps-tryon-back-btn {
2689
+ font-size: 14px !important; gap: 6px !important;
2690
+ margin-bottom: 12px !important; padding: 6px 0 !important;
2691
+ }
2692
+ .ps-tryon-back-btn svg { width: 18px !important; height: 12px !important; }
2693
+
2694
+ /* ── Preserve existing previews and modal-wide overrides ── */
2633
2695
  .ps-tryon-preview { height: 320px; }
2634
2696
  }
2697
+
2698
+ @keyframes ps-mobile-slide-up {
2699
+ from { transform: translateY(100%); opacity: 0.4; }
2700
+ to { transform: translateY(0); opacity: 1; }
2701
+ }
2635
2702
  @media (max-width: 720px) {
2636
2703
  .ps-tryon-result-split { flex-direction: column; }
2637
2704
  .ps-tryon-result-image-col { flex: none; }
@@ -2855,6 +2922,84 @@ const STYLES = `
2855
2922
  .ps-bp-photo-cta-done { color: var(--ps-success-color); }
2856
2923
  .ps-bp-photo-cta-done:hover { color: var(--ps-text-muted); }
2857
2924
 
2925
+ /* ── Subtitle under the basics title ── */
2926
+ .ps-bp-subtitle {
2927
+ font-size: clamp(12px, 0.68vw, 13px); color: var(--ps-text-muted);
2928
+ text-align: center; margin: 4px 0 0; font-weight: 400; line-height: 1.4;
2929
+ }
2930
+
2931
+ /* ════════════════════════════════════════════════════════════════
2932
+ Range slider rows for height / weight / age (basics step)
2933
+ Big displayed value + thin track + circular thumb. Track fill
2934
+ uses the inline --ps-pct CSS variable so we don't need JS to
2935
+ repaint the gradient.
2936
+ ════════════════════════════════════════════════════════════════ */
2937
+ .ps-bp-sliders {
2938
+ display: flex; flex-direction: column; gap: clamp(18px, 1.4vw, 22px);
2939
+ flex: 1; justify-content: center; padding: clamp(8px, 0.6vw, 12px) 0;
2940
+ }
2941
+ .ps-bp-slider-row {
2942
+ display: grid;
2943
+ grid-template-columns: clamp(70px, 6vw, 90px) 1fr;
2944
+ grid-template-rows: auto auto;
2945
+ column-gap: clamp(14px, 1vw, 20px); row-gap: 8px;
2946
+ align-items: center;
2947
+ }
2948
+ .ps-bp-slider-label {
2949
+ grid-column: 1; grid-row: 1 / span 2;
2950
+ font-size: clamp(11px, 0.68vw, 12px); font-weight: 700;
2951
+ color: var(--ps-text-muted); letter-spacing: 0.1em;
2952
+ text-transform: uppercase;
2953
+ align-self: center;
2954
+ }
2955
+ .ps-bp-slider-value-wrap {
2956
+ grid-column: 2; grid-row: 1;
2957
+ display: flex; align-items: baseline; gap: 6px;
2958
+ color: var(--ps-text-primary);
2959
+ }
2960
+ .ps-bp-slider-value {
2961
+ font-size: clamp(28px, 1.6vw, 32px); font-weight: 600;
2962
+ line-height: 1; font-feature-settings: "tnum" 1;
2963
+ }
2964
+ .ps-bp-slider-value-sm { margin-left: 4px; }
2965
+ .ps-bp-slider-unit {
2966
+ font-size: clamp(13px, 0.78vw, 15px); color: var(--ps-text-muted);
2967
+ font-weight: 500;
2968
+ }
2969
+
2970
+ /* The slider itself — fully reset, custom track + thumb */
2971
+ .ps-bp-slider {
2972
+ grid-column: 2; grid-row: 2;
2973
+ -webkit-appearance: none; appearance: none;
2974
+ width: 100%; height: 4px; outline: none;
2975
+ background: linear-gradient(
2976
+ to right,
2977
+ var(--ps-accent) 0%,
2978
+ var(--ps-accent) var(--ps-pct, 0%),
2979
+ var(--ps-border-color) var(--ps-pct, 0%),
2980
+ var(--ps-border-color) 100%
2981
+ );
2982
+ border-radius: 999px; cursor: grab;
2983
+ transition: background 0.05s linear;
2984
+ }
2985
+ .ps-bp-slider:active { cursor: grabbing; }
2986
+ .ps-bp-slider::-webkit-slider-thumb {
2987
+ -webkit-appearance: none; appearance: none;
2988
+ width: 22px; height: 22px; border-radius: 50%;
2989
+ background: #FFFFFF; border: 2px solid var(--ps-accent);
2990
+ box-shadow: 0 2px 6px rgba(0,0,0,0.12);
2991
+ cursor: grab; transition: transform 0.15s ease;
2992
+ }
2993
+ .ps-bp-slider::-webkit-slider-thumb:hover { transform: scale(1.08); }
2994
+ .ps-bp-slider::-webkit-slider-thumb:active { cursor: grabbing; transform: scale(1.04); }
2995
+ .ps-bp-slider::-moz-range-thumb {
2996
+ width: 22px; height: 22px; border-radius: 50%;
2997
+ background: #FFFFFF; border: 2px solid var(--ps-accent);
2998
+ box-shadow: 0 2px 6px rgba(0,0,0,0.12);
2999
+ cursor: grab;
3000
+ }
3001
+ .ps-bp-slider::-moz-range-track { background: transparent; height: 4px; }
3002
+
2858
3003
  .ps-bp-optional { font-weight: 400; color: var(--ps-text-muted); }
2859
3004
 
2860
3005
  /* Bra size step — vertically centered */
@@ -3127,7 +3272,29 @@ const STYLES = `
3127
3272
  /* ── Mobile responsive ── */
3128
3273
  @media (max-width: 768px) {
3129
3274
  .ps-bp-layout { flex-direction: column; height: auto; gap: 0; overflow: visible; }
3130
- .ps-bp-image { flex: none; height: 200px; border-radius: 10px; }
3275
+ /* Hide the giant product/body photo on mobile — gives the form full vertical room */
3276
+ .ps-bp-image { display: none !important; }
3277
+ .ps-bp-wrapper { overflow-y: auto; -webkit-overflow-scrolling: touch; }
3278
+
3279
+ /* ── Mobile slider rows: bigger labels, bigger values, taller sliders ── */
3280
+ .ps-bp-sliders { gap: 22px; padding: 8px 0; }
3281
+ .ps-bp-slider-row {
3282
+ grid-template-columns: 80px 1fr;
3283
+ column-gap: 16px; row-gap: 10px;
3284
+ }
3285
+ .ps-bp-slider-label { font-size: 12px !important; letter-spacing: 0.1em; }
3286
+ .ps-bp-slider-value { font-size: 30px !important; font-weight: 600; }
3287
+ .ps-bp-slider-unit { font-size: 14px !important; }
3288
+ .ps-bp-slider {
3289
+ height: 5px;
3290
+ }
3291
+ .ps-bp-slider::-webkit-slider-thumb { width: 26px; height: 26px; }
3292
+ .ps-bp-slider::-moz-range-thumb { width: 26px; height: 26px; }
3293
+
3294
+ /* Subtitle below title */
3295
+ .ps-bp-subtitle { font-size: 13px !important; margin-top: 6px !important; }
3296
+
3297
+ .ps-bp-image-fallback { flex: none; height: 200px; border-radius: 10px; }
3131
3298
  .ps-bp-upload-placeholder svg { width: 32px; height: 32px; }
3132
3299
  .ps-bp-upload-text { font-size: 14px; }
3133
3300
  .ps-bp-upload-hint { font-size: 11px; }
@@ -5271,11 +5438,11 @@ function BodyProfileView({
5271
5438
  const [step, setStep] = useState("basics");
5272
5439
  step === "photo" ? 0 : steps.indexOf(step);
5273
5440
  const imperial = isImperial(sizingCountry);
5274
- const [height, setHeight] = useState(formRef.current.height || "");
5275
- const [heightFeet, setHeightFeet] = useState(formRef.current.heightFeet || "");
5276
- const [heightInches, setHeightInches] = useState(formRef.current.heightInches || "");
5277
- const [weight, setWeight] = useState(formRef.current.weight || "");
5278
- const [age, setAge] = useState(formRef.current.age || "");
5441
+ const [height, setHeight] = useState(formRef.current.height || "173");
5442
+ const [heightFeet, setHeightFeet] = useState(formRef.current.heightFeet || "5");
5443
+ const [heightInches, setHeightInches] = useState(formRef.current.heightInches || "8");
5444
+ const [weight, setWeight] = useState(formRef.current.weight || (imperial ? "154" : "70"));
5445
+ const [age, setAge] = useState(formRef.current.age || "30");
5279
5446
  const [hUnit, setHUnit] = useState(
5280
5447
  heightUnit === "ft" ? "in" : heightUnit || (imperial ? "in" : "cm")
5281
5448
  );
@@ -5584,59 +5751,147 @@ function BodyProfileView({
5584
5751
  }
5585
5752
  ),
5586
5753
  /* @__PURE__ */ jsxs("div", { className: "ps-bp-root", children: [
5587
- step === "basics" && /* @__PURE__ */ jsxs("div", { className: "ps-bp-step ps-bp-step-enter", children: [
5588
- /* @__PURE__ */ jsx("h2", { className: "ps-bp-title", children: t("Let's find your best fit") }),
5589
- /* @__PURE__ */ jsxs("div", { className: "ps-bp-system-toggle", children: [
5590
- /* @__PURE__ */ jsx("button", { className: `ps-bp-system-btn${!isImperialMode ? " ps-bp-system-active" : ""}`, onClick: () => {
5591
- setHUnit("cm");
5592
- setWUnit("kg");
5593
- setHeightUnit("cm");
5594
- setWeightUnit("kg");
5595
- setSizingUnit?.("cm");
5596
- }, type: "button", children: t("Metric") }),
5597
- /* @__PURE__ */ jsx("button", { className: `ps-bp-system-btn${isImperialMode ? " ps-bp-system-active" : ""}`, onClick: () => {
5598
- setHUnit("in");
5599
- setWUnit("lbs");
5600
- setHeightUnit("in");
5601
- setWeightUnit("lbs");
5602
- setSizingUnit?.("in");
5603
- }, type: "button", children: t("Imperial") })
5604
- ] }),
5605
- /* @__PURE__ */ jsxs("div", { className: "ps-bp-inline-fields", children: [
5606
- /* @__PURE__ */ jsxs("div", { className: "ps-bp-inline-row", children: [
5607
- /* @__PURE__ */ jsx("span", { className: "ps-bp-inline-label", children: t("HEIGHT") }),
5608
- hUnit === "in" ? /* @__PURE__ */ jsxs("div", { className: "ps-bp-inline-input-group", children: [
5609
- /* @__PURE__ */ jsx("input", { type: "number", className: "ps-bp-inline-input", placeholder: "5", value: heightFeet, onChange: (e) => setHeightFeet(e.target.value), min: 3, max: 8 }),
5610
- /* @__PURE__ */ jsx("span", { className: "ps-bp-inline-unit", children: "ft" }),
5611
- /* @__PURE__ */ jsx("input", { type: "number", className: "ps-bp-inline-input", placeholder: "10", value: heightInches, onChange: (e) => setHeightInches(e.target.value), min: 0, max: 11 }),
5612
- /* @__PURE__ */ jsx("span", { className: "ps-bp-inline-unit", children: "in" })
5613
- ] }) : /* @__PURE__ */ jsxs("div", { className: "ps-bp-inline-input-group", children: [
5614
- /* @__PURE__ */ jsx("input", { type: "number", className: "ps-bp-inline-input", placeholder: "173", value: height, onChange: (e) => setHeight(e.target.value), min: 100, max: 250 }),
5615
- /* @__PURE__ */ jsx("span", { className: "ps-bp-inline-unit", children: "cm" })
5616
- ] })
5754
+ step === "basics" && (() => {
5755
+ const heightCm = parseFloat(height) || 173;
5756
+ const heightInTotal = (parseFloat(heightFeet) || 5) * 12 + (parseFloat(heightInches) || 8);
5757
+ const ftDisplay = Math.floor(heightInTotal / 12);
5758
+ const inDisplay = heightInTotal % 12;
5759
+ const weightNum = parseFloat(weight) || (wUnit === "kg" ? 70 : 154);
5760
+ const ageNum = parseFloat(age) || 30;
5761
+ const wMin = wUnit === "kg" ? 30 : 66;
5762
+ const wMax = wUnit === "kg" ? 200 : 440;
5763
+ const hCmPct = (heightCm - 120) / (220 - 120) * 100;
5764
+ const hInPct = (heightInTotal - 48) / (84 - 48) * 100;
5765
+ const wPct = (weightNum - wMin) / (wMax - wMin) * 100;
5766
+ const aPct = (ageNum - 13) / (100 - 13) * 100;
5767
+ const switchToMetric = () => {
5768
+ if (hUnit === "in") {
5769
+ const totalIn = (parseFloat(heightFeet) || 5) * 12 + (parseFloat(heightInches) || 8);
5770
+ setHeight(String(Math.round(totalIn * 2.54)));
5771
+ }
5772
+ if (wUnit === "lbs" && weight) {
5773
+ setWeight(String(Math.round(parseFloat(weight) / 2.205)));
5774
+ }
5775
+ setHUnit("cm");
5776
+ setWUnit("kg");
5777
+ setHeightUnit("cm");
5778
+ setWeightUnit("kg");
5779
+ setSizingUnit?.("cm");
5780
+ };
5781
+ const switchToImperial = () => {
5782
+ if (hUnit === "cm") {
5783
+ const cmVal = parseFloat(height) || 173;
5784
+ const totalIn = Math.round(cmVal / 2.54);
5785
+ setHeightFeet(String(Math.floor(totalIn / 12)));
5786
+ setHeightInches(String(totalIn % 12));
5787
+ }
5788
+ if (wUnit === "kg" && weight) {
5789
+ setWeight(String(Math.round(parseFloat(weight) * 2.205)));
5790
+ }
5791
+ setHUnit("in");
5792
+ setWUnit("lbs");
5793
+ setHeightUnit("in");
5794
+ setWeightUnit("lbs");
5795
+ setSizingUnit?.("in");
5796
+ };
5797
+ return /* @__PURE__ */ jsxs("div", { className: "ps-bp-step ps-bp-step-enter", children: [
5798
+ /* @__PURE__ */ jsx("h2", { className: "ps-bp-title", children: t("Let's find your best fit") }),
5799
+ /* @__PURE__ */ jsx("p", { className: "ps-bp-subtitle", children: t("Drag the sliders for a bespoke size recommendation") }),
5800
+ /* @__PURE__ */ jsxs("div", { className: "ps-bp-system-toggle", children: [
5801
+ /* @__PURE__ */ jsx("button", { className: `ps-bp-system-btn${!isImperialMode ? " ps-bp-system-active" : ""}`, onClick: switchToMetric, type: "button", children: t("Metric") }),
5802
+ /* @__PURE__ */ jsx("button", { className: `ps-bp-system-btn${isImperialMode ? " ps-bp-system-active" : ""}`, onClick: switchToImperial, type: "button", children: t("Imperial") })
5617
5803
  ] }),
5618
- /* @__PURE__ */ jsxs("div", { className: "ps-bp-inline-row", children: [
5619
- /* @__PURE__ */ jsx("span", { className: "ps-bp-inline-label", children: t("WEIGHT") }),
5620
- /* @__PURE__ */ jsxs("div", { className: "ps-bp-inline-input-group", children: [
5621
- /* @__PURE__ */ jsx("input", { type: "number", className: "ps-bp-inline-input", placeholder: wUnit === "kg" ? "75" : "165", value: weight, onChange: (e) => setWeight(e.target.value), min: wUnit === "kg" ? 30 : 66, max: wUnit === "kg" ? 300 : 660 }),
5622
- /* @__PURE__ */ jsx("span", { className: "ps-bp-inline-unit", children: wUnit })
5804
+ /* @__PURE__ */ jsxs("div", { className: "ps-bp-sliders", children: [
5805
+ /* @__PURE__ */ jsxs("div", { className: "ps-bp-slider-row", children: [
5806
+ /* @__PURE__ */ jsx("span", { className: "ps-bp-slider-label", children: t("HEIGHT") }),
5807
+ /* @__PURE__ */ jsx("div", { className: "ps-bp-slider-value-wrap", children: hUnit === "in" ? /* @__PURE__ */ jsxs(Fragment, { children: [
5808
+ /* @__PURE__ */ jsx("span", { className: "ps-bp-slider-value", children: ftDisplay }),
5809
+ /* @__PURE__ */ jsx("span", { className: "ps-bp-slider-unit", children: "ft" }),
5810
+ /* @__PURE__ */ jsx("span", { className: "ps-bp-slider-value ps-bp-slider-value-sm", children: inDisplay }),
5811
+ /* @__PURE__ */ jsx("span", { className: "ps-bp-slider-unit", children: "in" })
5812
+ ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
5813
+ /* @__PURE__ */ jsx("span", { className: "ps-bp-slider-value", children: Math.round(heightCm) }),
5814
+ /* @__PURE__ */ jsx("span", { className: "ps-bp-slider-unit", children: "cm" })
5815
+ ] }) }),
5816
+ hUnit === "in" ? /* @__PURE__ */ jsx(
5817
+ "input",
5818
+ {
5819
+ type: "range",
5820
+ className: "ps-bp-slider",
5821
+ min: 48,
5822
+ max: 84,
5823
+ step: 1,
5824
+ value: heightInTotal,
5825
+ onChange: (e) => {
5826
+ const v = parseInt(e.target.value, 10);
5827
+ setHeightFeet(String(Math.floor(v / 12)));
5828
+ setHeightInches(String(v % 12));
5829
+ },
5830
+ style: { ["--ps-pct"]: `${hInPct}%` }
5831
+ }
5832
+ ) : /* @__PURE__ */ jsx(
5833
+ "input",
5834
+ {
5835
+ type: "range",
5836
+ className: "ps-bp-slider",
5837
+ min: 120,
5838
+ max: 220,
5839
+ step: 1,
5840
+ value: heightCm,
5841
+ onChange: (e) => setHeight(e.target.value),
5842
+ style: { ["--ps-pct"]: `${hCmPct}%` }
5843
+ }
5844
+ )
5845
+ ] }),
5846
+ /* @__PURE__ */ jsxs("div", { className: "ps-bp-slider-row", children: [
5847
+ /* @__PURE__ */ jsx("span", { className: "ps-bp-slider-label", children: t("WEIGHT") }),
5848
+ /* @__PURE__ */ jsxs("div", { className: "ps-bp-slider-value-wrap", children: [
5849
+ /* @__PURE__ */ jsx("span", { className: "ps-bp-slider-value", children: Math.round(weightNum) }),
5850
+ /* @__PURE__ */ jsx("span", { className: "ps-bp-slider-unit", children: wUnit })
5851
+ ] }),
5852
+ /* @__PURE__ */ jsx(
5853
+ "input",
5854
+ {
5855
+ type: "range",
5856
+ className: "ps-bp-slider",
5857
+ min: wMin,
5858
+ max: wMax,
5859
+ step: 1,
5860
+ value: weightNum,
5861
+ onChange: (e) => setWeight(e.target.value),
5862
+ style: { ["--ps-pct"]: `${wPct}%` }
5863
+ }
5864
+ )
5865
+ ] }),
5866
+ /* @__PURE__ */ jsxs("div", { className: "ps-bp-slider-row", children: [
5867
+ /* @__PURE__ */ jsx("span", { className: "ps-bp-slider-label", children: t("AGE") }),
5868
+ /* @__PURE__ */ jsxs("div", { className: "ps-bp-slider-value-wrap", children: [
5869
+ /* @__PURE__ */ jsx("span", { className: "ps-bp-slider-value", children: Math.round(ageNum) }),
5870
+ /* @__PURE__ */ jsx("span", { className: "ps-bp-slider-unit", children: t("years") })
5871
+ ] }),
5872
+ /* @__PURE__ */ jsx(
5873
+ "input",
5874
+ {
5875
+ type: "range",
5876
+ className: "ps-bp-slider",
5877
+ min: 13,
5878
+ max: 100,
5879
+ step: 1,
5880
+ value: ageNum,
5881
+ onChange: (e) => setAge(e.target.value),
5882
+ style: { ["--ps-pct"]: `${aPct}%` }
5883
+ }
5884
+ )
5623
5885
  ] })
5624
5886
  ] }),
5625
- /* @__PURE__ */ jsxs("div", { className: "ps-bp-inline-row", children: [
5626
- /* @__PURE__ */ jsx("span", { className: "ps-bp-inline-label", children: t("AGE") }),
5627
- /* @__PURE__ */ jsxs("div", { className: "ps-bp-inline-input-group", children: [
5628
- /* @__PURE__ */ jsx("input", { type: "number", className: "ps-bp-inline-input", placeholder: "30", value: age, onChange: (e) => setAge(e.target.value), min: 13, max: 100 }),
5629
- /* @__PURE__ */ jsx("span", { className: "ps-bp-inline-unit", children: t("years") })
5630
- ] })
5631
- ] })
5632
- ] }),
5633
- /* @__PURE__ */ jsxs("button", { className: "ps-bp-photo-cta", onClick: () => setStep("photo"), type: "button", children: [
5634
- /* @__PURE__ */ jsx(CameraUploadIcon, {}),
5635
- /* @__PURE__ */ jsx("span", { children: t("Or upload a photo for AI sizing") }),
5636
- /* @__PURE__ */ jsx("span", { className: "ps-bp-photo-cta-arrow", children: "→" })
5637
- ] }),
5638
- error && /* @__PURE__ */ jsx("p", { className: "ps-bp-error", children: error })
5639
- ] }, "step-basics"),
5887
+ /* @__PURE__ */ jsxs("button", { className: "ps-bp-photo-cta", onClick: () => setStep("photo"), type: "button", children: [
5888
+ /* @__PURE__ */ jsx(CameraUploadIcon, {}),
5889
+ /* @__PURE__ */ jsx("span", { children: t("Or upload a photo for AI sizing") }),
5890
+ /* @__PURE__ */ jsx("span", { className: "ps-bp-photo-cta-arrow", children: "" })
5891
+ ] }),
5892
+ error && /* @__PURE__ */ jsx("p", { className: "ps-bp-error", children: error })
5893
+ ] }, "step-basics");
5894
+ })(),
5640
5895
  step === "chest" && !isWomen && /* @__PURE__ */ jsxs("div", { className: "ps-bp-step ps-bp-step-enter ps-bp-single-q", children: [
5641
5896
  /* @__PURE__ */ jsx("h2", { className: "ps-bp-title", children: t("Which best describes your chest?") }),
5642
5897
  /* @__PURE__ */ jsxs("div", { className: "ps-bp-shape-row ps-bp-shape-row-full", children: [
@@ -6898,39 +7153,42 @@ function PrimeStyleTryonInner({
6898
7153
  showIcon !== false && (buttonIcon || /* @__PURE__ */ jsx(CameraIcon, {})),
6899
7154
  /* @__PURE__ */ jsx("span", { children: resolvedButtonText })
6900
7155
  ] }),
6901
- view !== "idle" && /* @__PURE__ */ jsx("div", { className: cx("ps-tryon-overlay", cn.overlay), children: /* @__PURE__ */ jsxs("div", { className: cx(`ps-tryon-modal${view === "result" && resultImageUrl && sizingResult || view === "size-result" || view === "estimation-review" || view === "body-profile" ? " ps-tryon-modal-wide" : ""}`, cn.modal), onClick: (e) => e.stopPropagation(), children: [
6902
- /* @__PURE__ */ jsxs("div", { className: cx("ps-tryon-header ps-tryon-header-minimal", cn.header), children: [
6903
- /* @__PURE__ */ jsx(LangSwitcher, { activeLocale, onSelect: setActiveLocale }),
6904
- /* @__PURE__ */ jsx("button", { className: "ps-tryon-header-icon", title: t("Profiles"), onClick: () => setDrawer(drawer === "profiles" ? null : "profiles"), children: /* @__PURE__ */ jsx(UserIcon, {}) }),
6905
- /* @__PURE__ */ jsx("button", { className: "ps-tryon-header-icon", title: t("History"), onClick: () => setDrawer(drawer === "history" ? null : "history"), children: /* @__PURE__ */ jsx(ClockIcon, {}) }),
6906
- /* @__PURE__ */ jsx("button", { onClick: handleClose, className: cx("ps-tryon-close", cn.closeButton), children: /* @__PURE__ */ jsx(XIcon, {}) })
6907
- ] }),
6908
- view !== "body-profile" && view !== "processing" && !(view === "size-result" && sizeGuide?.sections && Object.keys(sizeGuide.sections).length > 1) && /* @__PURE__ */ jsx(Stepper, { view, stepIndex }),
6909
- /* @__PURE__ */ jsxs("div", { ref: bodyRef, className: cx("ps-tryon-body", cn.body), style: { position: "relative", overflow: drawer ? "hidden" : void 0 }, children: [
6910
- showBackButton && /* @__PURE__ */ jsxs("button", { className: "ps-tryon-back-btn", onClick: handleBack, children: [
6911
- /* @__PURE__ */ jsxs("svg", { width: "18", height: "12", viewBox: "0 0 18 12", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", children: [
6912
- /* @__PURE__ */ jsx("line", { x1: "17", y1: "6", x2: "1", y2: "6" }),
6913
- /* @__PURE__ */ jsx("polyline", { points: "5 1 1 6 5 11" })
6914
- ] }),
6915
- t("Back")
7156
+ view !== "idle" && typeof document !== "undefined" && createPortal(
7157
+ /* @__PURE__ */ jsx("div", { className: cx("ps-tryon-overlay", cn.overlay), style: cssVars, "data-ps-tryon-portal": true, children: /* @__PURE__ */ jsxs("div", { className: cx(`ps-tryon-modal${view === "result" && resultImageUrl && sizingResult || view === "size-result" || view === "estimation-review" || view === "body-profile" ? " ps-tryon-modal-wide" : ""}`, cn.modal), onClick: (e) => e.stopPropagation(), children: [
7158
+ /* @__PURE__ */ jsxs("div", { className: cx("ps-tryon-header ps-tryon-header-minimal", cn.header), children: [
7159
+ /* @__PURE__ */ jsx(LangSwitcher, { activeLocale, onSelect: setActiveLocale }),
7160
+ /* @__PURE__ */ jsx("button", { className: "ps-tryon-header-icon", title: t("Profiles"), onClick: () => setDrawer(drawer === "profiles" ? null : "profiles"), children: /* @__PURE__ */ jsx(UserIcon, {}) }),
7161
+ /* @__PURE__ */ jsx("button", { className: "ps-tryon-header-icon", title: t("History"), onClick: () => setDrawer(drawer === "history" ? null : "history"), children: /* @__PURE__ */ jsx(ClockIcon, {}) }),
7162
+ /* @__PURE__ */ jsx("button", { onClick: handleClose, className: cx("ps-tryon-close", cn.closeButton), children: /* @__PURE__ */ jsx(XIcon, {}) })
6916
7163
  ] }),
6917
- renderBody(),
6918
- /* @__PURE__ */ jsx(
6919
- DrawerPanel,
6920
- {
6921
- drawer,
6922
- setDrawer,
6923
- profiles,
6924
- setProfiles,
6925
- history,
6926
- setHistory,
6927
- setProfileDetail,
6928
- restoreHistory,
6929
- t
6930
- }
6931
- )
6932
- ] })
6933
- ] }) }),
7164
+ view !== "body-profile" && view !== "processing" && !(view === "size-result" && sizeGuide?.sections && Object.keys(sizeGuide.sections).length > 1) && /* @__PURE__ */ jsx(Stepper, { view, stepIndex }),
7165
+ /* @__PURE__ */ jsxs("div", { ref: bodyRef, className: cx("ps-tryon-body", cn.body), style: { position: "relative", overflow: drawer ? "hidden" : void 0 }, children: [
7166
+ showBackButton && /* @__PURE__ */ jsxs("button", { className: "ps-tryon-back-btn", onClick: handleBack, children: [
7167
+ /* @__PURE__ */ jsxs("svg", { width: "18", height: "12", viewBox: "0 0 18 12", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", children: [
7168
+ /* @__PURE__ */ jsx("line", { x1: "17", y1: "6", x2: "1", y2: "6" }),
7169
+ /* @__PURE__ */ jsx("polyline", { points: "5 1 1 6 5 11" })
7170
+ ] }),
7171
+ t("Back")
7172
+ ] }),
7173
+ renderBody(),
7174
+ /* @__PURE__ */ jsx(
7175
+ DrawerPanel,
7176
+ {
7177
+ drawer,
7178
+ setDrawer,
7179
+ profiles,
7180
+ setProfiles,
7181
+ history,
7182
+ setHistory,
7183
+ setProfileDetail,
7184
+ restoreHistory,
7185
+ t
7186
+ }
7187
+ )
7188
+ ] })
7189
+ ] }) }),
7190
+ document.body
7191
+ ),
6934
7192
  /* @__PURE__ */ jsx(
6935
7193
  ProfileDetailModal,
6936
7194
  {