@primestyleai/tryon 5.5.9 → 5.5.11

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.
@@ -2940,7 +2940,9 @@ const STYLES = `
2940
2940
  .ps-bpm-root {
2941
2941
  display: flex; flex-direction: column;
2942
2942
  gap: 10px; padding: 8px 4px 0;
2943
+ flex: 1; min-height: 0;
2943
2944
  }
2945
+ .ps-bpm-spacer { flex: 1 1 auto; min-height: 8px; }
2944
2946
  .ps-bpm-header { text-align: center; margin: 4px 0 0; }
2945
2947
  .ps-bpm-title {
2946
2948
  font-size: 18px; font-weight: 700; color: var(--ps-text-primary);
@@ -2969,110 +2971,141 @@ const STYLES = `
2969
2971
  border-bottom-color: var(--ps-accent);
2970
2972
  }
2971
2973
 
2972
- /* Field rows — minimal, compact */
2974
+ /* Slider rows — label top-left, value top-right, then [-] [track] [+] */
2973
2975
  .ps-bpm-fields {
2974
2976
  display: flex; flex-direction: column;
2975
2977
  margin-top: 4px;
2976
2978
  }
2977
2979
  .ps-bpm-row {
2978
- display: flex; align-items: baseline;
2980
+ display: flex; flex-direction: column;
2979
2981
  padding: 14px 4px;
2980
- gap: 14px;
2982
+ gap: 12px;
2981
2983
  border-bottom: 1px solid var(--ps-border-subtle);
2982
2984
  }
2983
2985
  .ps-bpm-row:last-child { border-bottom: none; }
2986
+ .ps-bpm-row-top {
2987
+ display: flex; align-items: center; justify-content: space-between;
2988
+ }
2984
2989
  .ps-bpm-label {
2985
- flex: 0 0 64px;
2986
- font-size: 10px; font-weight: 700;
2987
- letter-spacing: 0.1em; text-transform: uppercase;
2990
+ font-size: 11px; font-weight: 600;
2991
+ letter-spacing: 0.12em; text-transform: uppercase;
2988
2992
  color: var(--ps-text-muted);
2989
2993
  }
2990
- .ps-bpm-value-group {
2991
- flex: 1; display: flex; align-items: baseline; gap: 4px;
2992
- justify-content: flex-start;
2993
- }
2994
- .ps-bpm-input {
2995
- background: transparent; border: none; outline: none;
2996
- font-family: inherit;
2997
- font-size: 20px; font-weight: 600;
2994
+ .ps-bpm-value-display {
2995
+ font-size: 14px; font-weight: 700;
2998
2996
  color: var(--ps-text-primary);
2999
- padding: 0; margin: 0;
3000
- width: auto; min-width: 0;
3001
- field-sizing: content;
3002
- max-width: 4ch;
3003
- }
3004
- .ps-bpm-input::-webkit-outer-spin-button,
3005
- .ps-bpm-input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
3006
- .ps-bpm-input[type="number"] { -moz-appearance: textfield; }
3007
- .ps-bpm-input::placeholder { color: var(--ps-border-color); }
3008
- .ps-bpm-input:focus { outline: none; }
3009
- .ps-bpm-unit {
3010
- font-size: 11px; font-weight: 500;
3011
- color: var(--ps-text-muted);
3012
- margin-left: 1px; flex-shrink: 0;
2997
+ font-feature-settings: "tnum" 1;
3013
2998
  }
3014
2999
 
3015
- /* RECOMMENDED upload card compact */
3016
- .ps-bpm-photo-card {
3000
+ /* Slider row container: [-] [track] [+] */
3001
+ .ps-bpm-slider-row {
3017
3002
  display: flex; align-items: center; gap: 12px;
3018
- background: #1C1D1E; color: #FFFFFF;
3019
- border: none; border-radius: 10px;
3020
- padding: 10px 14px; margin-top: 6px;
3021
- cursor: pointer; font-family: inherit;
3022
- text-align: left; width: 100%;
3023
- transition: transform 0.15s ease;
3024
3003
  }
3025
- .ps-bpm-photo-card:active { transform: scale(0.98); }
3026
- .ps-bpm-photo-card-icon {
3004
+ .ps-bpm-step-btn {
3027
3005
  flex-shrink: 0;
3028
- width: 32px; height: 32px; border-radius: 7px;
3029
- background: rgba(255,255,255,0.08);
3006
+ width: 34px; height: 34px; border-radius: 50%;
3007
+ background: var(--ps-bg-tertiary); border: none;
3030
3008
  display: flex; align-items: center; justify-content: center;
3031
- color: #FFFFFF;
3032
- }
3033
- .ps-bpm-photo-card-icon svg { width: 16px; height: 16px; }
3034
- .ps-bpm-photo-card-content {
3035
- flex: 1; display: flex; flex-direction: column; gap: 2px; min-width: 0;
3009
+ cursor: pointer;
3010
+ color: var(--ps-text-secondary);
3011
+ transition: background 0.15s, transform 0.1s;
3036
3012
  }
3037
- .ps-bpm-photo-card-badge {
3038
- font-size: 9px; font-weight: 700; letter-spacing: 0.12em;
3039
- color: rgba(255,255,255,0.55);
3013
+ .ps-bpm-step-btn:hover { background: var(--ps-border-color); }
3014
+ .ps-bpm-step-btn:active { transform: scale(0.92); }
3015
+
3016
+ /* The slider — thicker track, dark navy thumb, monochrome */
3017
+ .ps-bpm-slider {
3018
+ -webkit-appearance: none; appearance: none;
3019
+ flex: 1; min-width: 0;
3020
+ height: 4px; outline: none;
3021
+ background: linear-gradient(
3022
+ to right,
3023
+ var(--ps-text-primary) 0%,
3024
+ var(--ps-text-primary) var(--ps-pct, 0%),
3025
+ var(--ps-border-color) var(--ps-pct, 0%),
3026
+ var(--ps-border-color) 100%
3027
+ );
3028
+ border-radius: 999px; cursor: pointer;
3029
+ margin: 0;
3030
+ }
3031
+ .ps-bpm-slider::-webkit-slider-thumb {
3032
+ -webkit-appearance: none; appearance: none;
3033
+ width: 18px; height: 18px; border-radius: 50%;
3034
+ background: var(--ps-text-primary); border: none;
3035
+ cursor: grab; transition: transform 0.15s ease;
3036
+ box-shadow: 0 1px 3px rgba(0,0,0,0.18);
3037
+ }
3038
+ .ps-bpm-slider::-webkit-slider-thumb:active { cursor: grabbing; transform: scale(1.1); }
3039
+ .ps-bpm-slider::-moz-range-thumb {
3040
+ width: 18px; height: 18px; border-radius: 50%;
3041
+ background: var(--ps-text-primary); border: none; cursor: grab;
3042
+ box-shadow: 0 1px 3px rgba(0,0,0,0.18);
3043
+ }
3044
+ .ps-bpm-slider::-moz-range-track { background: transparent; height: 4px; }
3045
+
3046
+ /* "or" divider — flanked by hairlines */
3047
+ .ps-bpm-or {
3048
+ display: flex; align-items: center; gap: 12px;
3049
+ margin: 14px 4px 4px;
3040
3050
  }
3041
- .ps-bpm-photo-card-text {
3042
- font-size: 13px; font-weight: 500; color: #FFFFFF;
3051
+ .ps-bpm-or::before, .ps-bpm-or::after {
3052
+ content: ""; flex: 1; height: 1px;
3053
+ background: var(--ps-border-subtle);
3043
3054
  }
3044
- .ps-bpm-photo-card-arrow {
3045
- flex-shrink: 0; color: rgba(255,255,255,0.6);
3046
- display: flex; align-items: center;
3055
+ .ps-bpm-or span {
3056
+ font-size: 10px; font-weight: 600;
3057
+ text-transform: uppercase; letter-spacing: 0.16em;
3058
+ color: var(--ps-text-muted);
3047
3059
  }
3048
- .ps-bpm-photo-card-arrow svg { width: 16px; height: 16px; }
3049
3060
 
3050
- /* Helper hint */
3051
- .ps-bpm-hint {
3052
- font-size: 10px; color: var(--ps-text-muted);
3053
- text-align: center; margin: 2px 8px 0; line-height: 1.5;
3054
- font-style: italic;
3061
+ /* Minimal upload link — no card, no background, just text + icons */
3062
+ .ps-bpm-upload-link {
3063
+ display: flex; align-items: center; justify-content: center; gap: 10px;
3064
+ background: none; border: none;
3065
+ padding: 8px 4px; margin: 0;
3066
+ cursor: pointer; font-family: inherit;
3067
+ color: var(--ps-text-primary); font-size: 13px; font-weight: 500;
3068
+ width: 100%;
3069
+ transition: opacity 0.15s;
3055
3070
  }
3071
+ .ps-bpm-upload-link:hover { opacity: 0.7; }
3072
+ .ps-bpm-upload-link svg { color: var(--ps-text-secondary); flex-shrink: 0; }
3073
+
3056
3074
  .ps-bpm-error {
3057
3075
  font-size: 11px; color: var(--ps-error-color);
3058
3076
  text-align: center; margin: 4px 0 0;
3059
3077
  }
3060
3078
 
3061
- /* Bottom mode tabs (MANUAL FIT / AI SCAN) sticky to the bottom of
3062
- the modal body. Border-top separator, equal-width buttons, active
3063
- state uses the accent color. Sits above the existing .ps-bp-nav
3064
- CALCULATE BEST FIT button. */
3079
+ /* Bottom action area Next button + tab bar grouped together,
3080
+ pushed to the bottom of the modal body by .ps-bpm-spacer above. */
3081
+ .ps-bpm-bottom {
3082
+ display: flex; flex-direction: column;
3083
+ margin: 0 -16px;
3084
+ border-top: 1px solid var(--ps-border-subtle);
3085
+ background: var(--ps-bg-primary);
3086
+ flex-shrink: 0;
3087
+ padding-bottom: env(safe-area-inset-bottom);
3088
+ }
3089
+ .ps-bpm-next-btn {
3090
+ margin: 14px 16px 12px;
3091
+ padding: 14px 18px;
3092
+ background: var(--ps-accent); color: #FFFFFF;
3093
+ border: none; border-radius: 10px;
3094
+ font-family: inherit; font-size: 14px; font-weight: 700;
3095
+ cursor: pointer; transition: opacity 0.15s, transform 0.15s;
3096
+ letter-spacing: 0.02em;
3097
+ }
3098
+ .ps-bpm-next-btn:active { transform: scale(0.98); }
3099
+ .ps-bpm-next-btn:disabled { opacity: 0.4; cursor: not-allowed; }
3065
3100
  .ps-bpm-bottom-tabs {
3066
3101
  display: flex; align-items: stretch;
3067
- margin: 14px -16px 0;
3068
3102
  border-top: 1px solid var(--ps-border-subtle);
3069
3103
  background: var(--ps-bg-primary);
3070
- position: sticky; bottom: 0;
3071
3104
  }
3072
3105
  .ps-bpm-bottom-tab {
3073
3106
  flex: 1; background: none; border: none;
3074
- padding: 16px 8px 14px;
3075
- font-family: inherit; font-size: 11px; font-weight: 700;
3107
+ padding: 14px 8px 12px;
3108
+ font-family: inherit; font-size: 10px; font-weight: 700;
3076
3109
  letter-spacing: 0.12em; text-transform: uppercase;
3077
3110
  color: var(--ps-text-muted); cursor: pointer;
3078
3111
  border-bottom: 2px solid transparent;
@@ -3083,7 +3116,7 @@ const STYLES = `
3083
3116
  color: var(--ps-accent);
3084
3117
  border-bottom-color: var(--ps-accent);
3085
3118
  }
3086
- .ps-bpm-bottom-tab svg { width: 14px; height: 14px; flex-shrink: 0; }
3119
+ .ps-bpm-bottom-tab svg { width: 13px; height: 13px; flex-shrink: 0; }
3087
3120
 
3088
3121
  .ps-bp-optional { font-weight: 400; color: var(--ps-text-muted); }
3089
3122
 
@@ -3358,10 +3391,21 @@ const STYLES = `
3358
3391
  @media (max-width: 768px) {
3359
3392
  .ps-bp-layout { flex-direction: column; height: auto; gap: 0; overflow: visible; }
3360
3393
  /* Desktop layout's product image — hidden on mobile because BasicsStepMobile
3361
- renders its own .ps-bpm-image. The other steps (chest/midsection/hips) don't
3394
+ has its own minimal layout. The other steps (chest/midsection/hips) don't
3362
3395
  need the giant left-column image on a phone either. */
3363
3396
  .ps-bp-image { display: none !important; }
3364
- .ps-bp-wrapper { overflow-y: auto; -webkit-overflow-scrolling: touch; }
3397
+ .ps-bp-wrapper { overflow-y: auto; -webkit-overflow-scrolling: touch; flex: 1; min-height: 0; display: flex; flex-direction: column; }
3398
+ .ps-bp-layout { flex: 1; min-height: 0; }
3399
+ /* Override desktop justify-content:center so BasicsStepMobile can
3400
+ stretch to the bottom of the modal — its bottom action bar (Next +
3401
+ tabs) needs to land at the bottom edge, not floating in the middle. */
3402
+ .ps-bp-root {
3403
+ justify-content: stretch !important;
3404
+ height: auto !important;
3405
+ max-height: none !important;
3406
+ overflow: visible !important;
3407
+ flex: 1 !important;
3408
+ }
3365
3409
  .ps-bp-upload-placeholder svg { width: 32px; height: 32px; }
3366
3410
  .ps-bp-upload-text { font-size: 14px; }
3367
3411
  .ps-bp-upload-hint { font-size: 11px; }
@@ -3458,7 +3502,7 @@ function ClockIcon({ size = 16 }) {
3458
3502
  /* @__PURE__ */ jsx("polyline", { points: "12 6 12 12 16 14" })
3459
3503
  ] });
3460
3504
  }
3461
- function RulerIcon({ size = 18 }) {
3505
+ function RulerIcon$1({ size = 18 }) {
3462
3506
  return /* @__PURE__ */ jsxs("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round", children: [
3463
3507
  /* @__PURE__ */ jsx("path", { d: "M21.3 15.3a2.4 2.4 0 0 1 0 3.4l-2.6 2.6a2.4 2.4 0 0 1-3.4 0L2.7 8.7a2.41 2.41 0 0 1 0-3.4l2.6-2.6a2.41 2.41 0 0 1 3.4 0Z" }),
3464
3508
  /* @__PURE__ */ jsx("path", { d: "m14.5 12.5 2-2" }),
@@ -3476,7 +3520,7 @@ function TrashIcon({ size = 14 }) {
3476
3520
  /* @__PURE__ */ jsx("path", { d: "M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2" })
3477
3521
  ] });
3478
3522
  }
3479
- function ChevronRightIcon$1() {
3523
+ function ChevronRightIcon() {
3480
3524
  return /* @__PURE__ */ jsx("svg", { width: 16, height: 16, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx("path", { d: "M9 18l6-6-6-6" }) });
3481
3525
  }
3482
3526
  function CheckIcon({ size = 14 }) {
@@ -3806,7 +3850,7 @@ function DrawerPanel({
3806
3850
  p.heightCm ? ` · ${Math.round(p.heightCm)}${t("cm")}` : ""
3807
3851
  ] })
3808
3852
  ] }),
3809
- /* @__PURE__ */ jsx(ChevronRightIcon$1, {})
3853
+ /* @__PURE__ */ jsx(ChevronRightIcon, {})
3810
3854
  ] }, p.id))
3811
3855
  ] }) : /* @__PURE__ */ jsx(Fragment, { children: history.length === 0 ? /* @__PURE__ */ jsx("div", { className: "ps-tryon-drawer-empty", children: t("No history yet.") }) : /* @__PURE__ */ jsxs(Fragment, { children: [
3812
3856
  history.map((entry, idx) => /* @__PURE__ */ jsxs("div", { className: "ps-tryon-history-item ps-tryon-history-clickable", onClick: () => restoreHistory(entry), children: [
@@ -3918,7 +3962,7 @@ function WelcomeView({
3918
3962
  /* @__PURE__ */ jsx("p", { className: "ps-tryon-welcome-sub", children: t("Get the perfect fit, then try it on virtually") })
3919
3963
  ] }),
3920
3964
  /* @__PURE__ */ jsx("div", { className: "ps-tryon-features", children: [
3921
- { icon: /* @__PURE__ */ jsx(RulerIcon, { size: 22 }), title: t("Get Your Size"), desc: t("Instant fit recommendation") },
3965
+ { icon: /* @__PURE__ */ jsx(RulerIcon$1, { size: 22 }), title: t("Get Your Size"), desc: t("Instant fit recommendation") },
3922
3966
  { icon: /* @__PURE__ */ jsx(CameraIcon, { size: 22 }), title: t("Try It On"), desc: t("See how it looks on you") }
3923
3967
  ].map((f, i) => /* @__PURE__ */ jsxs("div", { className: "ps-tryon-feature", children: [
3924
3968
  /* @__PURE__ */ jsx("div", { className: "ps-tryon-feature-icon", children: f.icon }),
@@ -5358,25 +5402,62 @@ function useIsMobile() {
5358
5402
  }, []);
5359
5403
  return isMobile;
5360
5404
  }
5361
- function CameraSmallIcon({ size = 18 }) {
5405
+ function RulerIcon() {
5406
+ return /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", width: "13", height: "13", children: [
5407
+ /* @__PURE__ */ jsx("path", { d: "M3 17l6 6 12-12-6-6z" }),
5408
+ /* @__PURE__ */ jsx("path", { d: "M9 11l2 2M11 9l2 2M13 7l2 2M7 13l2 2" })
5409
+ ] });
5410
+ }
5411
+ function ScanIcon() {
5412
+ return /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", width: "13", height: "13", children: [
5413
+ /* @__PURE__ */ jsx("path", { d: "M3 7V5a2 2 0 0 1 2-2h2M17 3h2a2 2 0 0 1 2 2v2M21 17v2a2 2 0 0 1-2 2h-2M7 21H5a2 2 0 0 1-2-2v-2" }),
5414
+ /* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "3" })
5415
+ ] });
5416
+ }
5417
+ function MobileBottomTabs({ mode, onSwitchToManual, onSwitchToScan, t }) {
5418
+ return /* @__PURE__ */ jsxs("div", { className: "ps-bpm-bottom-tabs", children: [
5419
+ /* @__PURE__ */ jsxs(
5420
+ "button",
5421
+ {
5422
+ type: "button",
5423
+ className: `ps-bpm-bottom-tab${mode === "manual" ? " ps-active" : ""}`,
5424
+ onClick: onSwitchToManual,
5425
+ children: [
5426
+ /* @__PURE__ */ jsx(RulerIcon, {}),
5427
+ t("MANUAL FIT")
5428
+ ]
5429
+ }
5430
+ ),
5431
+ /* @__PURE__ */ jsxs(
5432
+ "button",
5433
+ {
5434
+ type: "button",
5435
+ className: `ps-bpm-bottom-tab${mode === "scan" ? " ps-active" : ""}`,
5436
+ onClick: onSwitchToScan,
5437
+ children: [
5438
+ /* @__PURE__ */ jsx(ScanIcon, {}),
5439
+ t("AI SCAN")
5440
+ ]
5441
+ }
5442
+ )
5443
+ ] });
5444
+ }
5445
+ function CameraSmallIcon({ size = 16 }) {
5362
5446
  return /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.6", strokeLinecap: "round", strokeLinejoin: "round", width: size, height: size, children: [
5363
5447
  /* @__PURE__ */ jsx("path", { d: "M23 19a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h4l2-3h6l2 3h4a2 2 0 0 1 2 2z" }),
5364
5448
  /* @__PURE__ */ jsx("circle", { cx: "12", cy: "13", r: "4" })
5365
5449
  ] });
5366
5450
  }
5367
- function ChevronRightIcon() {
5368
- return /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", width: "18", height: "18", children: /* @__PURE__ */ jsx("polyline", { points: "9 18 15 12 9 6" }) });
5451
+ function ChevronRight() {
5452
+ return /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", width: "14", height: "14", children: /* @__PURE__ */ jsx("polyline", { points: "9 18 15 12 9 6" }) });
5369
5453
  }
5370
- function RulerIconSmall() {
5371
- return /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", width: "14", height: "14", children: [
5372
- /* @__PURE__ */ jsx("path", { d: "M3 17l6 6 12-12-6-6z" }),
5373
- /* @__PURE__ */ jsx("path", { d: "M9 11l2 2M11 9l2 2M13 7l2 2M7 13l2 2" })
5374
- ] });
5454
+ function MinusIcon() {
5455
+ return /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", width: "14", height: "14", children: /* @__PURE__ */ jsx("line", { x1: "5", y1: "12", x2: "19", y2: "12" }) });
5375
5456
  }
5376
- function ScanIconSmall() {
5377
- return /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", width: "14", height: "14", children: [
5378
- /* @__PURE__ */ jsx("path", { d: "M3 7V5a2 2 0 0 1 2-2h2M17 3h2a2 2 0 0 1 2 2v2M21 17v2a2 2 0 0 1-2 2h-2M7 21H5a2 2 0 0 1-2-2v-2" }),
5379
- /* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "3" })
5457
+ function PlusIcon() {
5458
+ return /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", width: "14", height: "14", children: [
5459
+ /* @__PURE__ */ jsx("line", { x1: "5", y1: "12", x2: "19", y2: "12" }),
5460
+ /* @__PURE__ */ jsx("line", { x1: "12", y1: "5", x2: "12", y2: "19" })
5380
5461
  ] });
5381
5462
  }
5382
5463
  function BasicsStepMobile({
@@ -5397,9 +5478,43 @@ function BasicsStepMobile({
5397
5478
  switchToImperial,
5398
5479
  onUploadPhoto,
5399
5480
  onSwitchToScan,
5481
+ onNext,
5482
+ canProceed,
5400
5483
  error,
5401
5484
  t
5402
5485
  }) {
5486
+ const heightCm = parseFloat(height) || 173;
5487
+ const heightInTotal = (parseFloat(heightFeet) || 5) * 12 + (parseFloat(heightInches) || 8);
5488
+ const ftDisplay = Math.floor(heightInTotal / 12);
5489
+ const inDisplay = heightInTotal % 12;
5490
+ const weightNum = parseFloat(weight) || (wUnit === "kg" ? 70 : 154);
5491
+ const ageNum = parseFloat(age) || 30;
5492
+ const wMinFix = wUnit === "kg" ? 30 : 66;
5493
+ const wMax = wUnit === "kg" ? 200 : 440;
5494
+ const hCmMin = 120, hCmMax = 220;
5495
+ const hInMin = 48, hInMax = 84;
5496
+ const ageMin = 13, ageMax = 100;
5497
+ const pctHCm = (heightCm - hCmMin) / (hCmMax - hCmMin) * 100;
5498
+ const pctHIn = (heightInTotal - hInMin) / (hInMax - hInMin) * 100;
5499
+ const pctW = (weightNum - wMinFix) / (wMax - wMinFix) * 100;
5500
+ const pctA = (ageNum - ageMin) / (ageMax - ageMin) * 100;
5501
+ const setHeightTotalIn = (totalIn) => {
5502
+ const v = Math.max(hInMin, Math.min(hInMax, totalIn));
5503
+ setHeightFeet(String(Math.floor(v / 12)));
5504
+ setHeightInches(String(v % 12));
5505
+ };
5506
+ const incHeight = () => {
5507
+ if (hUnit === "in") setHeightTotalIn(heightInTotal + 1);
5508
+ else setHeight(String(Math.min(hCmMax, heightCm + 1)));
5509
+ };
5510
+ const decHeight = () => {
5511
+ if (hUnit === "in") setHeightTotalIn(heightInTotal - 1);
5512
+ else setHeight(String(Math.max(hCmMin, heightCm - 1)));
5513
+ };
5514
+ const incWeight = () => setWeight(String(Math.min(wMax, weightNum + 1)));
5515
+ const decWeight = () => setWeight(String(Math.max(wMinFix, weightNum - 1)));
5516
+ const incAge = () => setAge(String(Math.min(ageMax, ageNum + 1)));
5517
+ const decAge = () => setAge(String(Math.max(ageMin, ageNum - 1)));
5403
5518
  return /* @__PURE__ */ jsxs("div", { className: "ps-bpm-root", children: [
5404
5519
  /* @__PURE__ */ jsxs("div", { className: "ps-bpm-header", children: [
5405
5520
  /* @__PURE__ */ jsx("h2", { className: "ps-bpm-title", children: t("Let's find your best fit") }),
@@ -5427,134 +5542,130 @@ function BasicsStepMobile({
5427
5542
  ] }),
5428
5543
  /* @__PURE__ */ jsxs("div", { className: "ps-bpm-fields", children: [
5429
5544
  /* @__PURE__ */ jsxs("div", { className: "ps-bpm-row", children: [
5430
- /* @__PURE__ */ jsx("span", { className: "ps-bpm-label", children: t("HEIGHT") }),
5431
- hUnit === "in" ? /* @__PURE__ */ jsxs("div", { className: "ps-bpm-value-group", children: [
5432
- /* @__PURE__ */ jsx(
5433
- "input",
5434
- {
5435
- type: "number",
5436
- inputMode: "numeric",
5437
- className: "ps-bpm-input",
5438
- value: heightFeet,
5439
- onChange: (e) => setHeightFeet(e.target.value),
5440
- min: 3,
5441
- max: 8,
5442
- placeholder: "5"
5443
- }
5444
- ),
5445
- /* @__PURE__ */ jsx("span", { className: "ps-bpm-unit", children: "ft" }),
5446
- /* @__PURE__ */ jsx(
5545
+ /* @__PURE__ */ jsxs("div", { className: "ps-bpm-row-top", children: [
5546
+ /* @__PURE__ */ jsx("span", { className: "ps-bpm-label", children: t("HEIGHT") }),
5547
+ /* @__PURE__ */ jsx("span", { className: "ps-bpm-value-display", children: hUnit === "in" ? `${ftDisplay}ft ${inDisplay}in` : `${Math.round(heightCm)} cm` })
5548
+ ] }),
5549
+ /* @__PURE__ */ jsxs("div", { className: "ps-bpm-slider-row", children: [
5550
+ /* @__PURE__ */ jsx("button", { type: "button", className: "ps-bpm-step-btn", onClick: decHeight, "aria-label": t("Decrease"), children: /* @__PURE__ */ jsx(MinusIcon, {}) }),
5551
+ hUnit === "in" ? /* @__PURE__ */ jsx(
5447
5552
  "input",
5448
5553
  {
5449
- type: "number",
5450
- inputMode: "numeric",
5451
- className: "ps-bpm-input",
5452
- value: heightInches,
5453
- onChange: (e) => setHeightInches(e.target.value),
5454
- min: 0,
5455
- max: 11,
5456
- placeholder: "8"
5554
+ type: "range",
5555
+ className: "ps-bpm-slider",
5556
+ min: hInMin,
5557
+ max: hInMax,
5558
+ step: 1,
5559
+ value: heightInTotal,
5560
+ onChange: (e) => setHeightTotalIn(parseInt(e.target.value, 10)),
5561
+ style: { ["--ps-pct"]: `${pctHIn}%` }
5457
5562
  }
5458
- ),
5459
- /* @__PURE__ */ jsx("span", { className: "ps-bpm-unit", children: "in" })
5460
- ] }) : /* @__PURE__ */ jsxs("div", { className: "ps-bpm-value-group", children: [
5461
- /* @__PURE__ */ jsx(
5563
+ ) : /* @__PURE__ */ jsx(
5462
5564
  "input",
5463
5565
  {
5464
- type: "number",
5465
- inputMode: "numeric",
5466
- className: "ps-bpm-input",
5467
- value: height,
5566
+ type: "range",
5567
+ className: "ps-bpm-slider",
5568
+ min: hCmMin,
5569
+ max: hCmMax,
5570
+ step: 1,
5571
+ value: heightCm,
5468
5572
  onChange: (e) => setHeight(e.target.value),
5469
- min: 100,
5470
- max: 250,
5471
- placeholder: "173"
5573
+ style: { ["--ps-pct"]: `${pctHCm}%` }
5472
5574
  }
5473
5575
  ),
5474
- /* @__PURE__ */ jsx("span", { className: "ps-bpm-unit", children: "cm" })
5576
+ /* @__PURE__ */ jsx("button", { type: "button", className: "ps-bpm-step-btn", onClick: incHeight, "aria-label": t("Increase"), children: /* @__PURE__ */ jsx(PlusIcon, {}) })
5475
5577
  ] })
5476
5578
  ] }),
5477
5579
  /* @__PURE__ */ jsxs("div", { className: "ps-bpm-row", children: [
5478
- /* @__PURE__ */ jsx("span", { className: "ps-bpm-label", children: t("WEIGHT") }),
5479
- /* @__PURE__ */ jsxs("div", { className: "ps-bpm-value-group", children: [
5580
+ /* @__PURE__ */ jsxs("div", { className: "ps-bpm-row-top", children: [
5581
+ /* @__PURE__ */ jsx("span", { className: "ps-bpm-label", children: t("WEIGHT") }),
5582
+ /* @__PURE__ */ jsxs("span", { className: "ps-bpm-value-display", children: [
5583
+ Math.round(weightNum),
5584
+ " ",
5585
+ wUnit.toUpperCase()
5586
+ ] })
5587
+ ] }),
5588
+ /* @__PURE__ */ jsxs("div", { className: "ps-bpm-slider-row", children: [
5589
+ /* @__PURE__ */ jsx("button", { type: "button", className: "ps-bpm-step-btn", onClick: decWeight, "aria-label": t("Decrease"), children: /* @__PURE__ */ jsx(MinusIcon, {}) }),
5480
5590
  /* @__PURE__ */ jsx(
5481
5591
  "input",
5482
5592
  {
5483
- type: "number",
5484
- inputMode: "numeric",
5485
- className: "ps-bpm-input",
5486
- value: weight,
5593
+ type: "range",
5594
+ className: "ps-bpm-slider",
5595
+ min: wMinFix,
5596
+ max: wMax,
5597
+ step: 1,
5598
+ value: weightNum,
5487
5599
  onChange: (e) => setWeight(e.target.value),
5488
- min: wUnit === "kg" ? 30 : 66,
5489
- max: wUnit === "kg" ? 300 : 660,
5490
- placeholder: wUnit === "kg" ? "70" : "154"
5600
+ style: { ["--ps-pct"]: `${pctW}%` }
5491
5601
  }
5492
5602
  ),
5493
- /* @__PURE__ */ jsx("span", { className: "ps-bpm-unit", children: wUnit })
5603
+ /* @__PURE__ */ jsx("button", { type: "button", className: "ps-bpm-step-btn", onClick: incWeight, "aria-label": t("Increase"), children: /* @__PURE__ */ jsx(PlusIcon, {}) })
5494
5604
  ] })
5495
5605
  ] }),
5496
5606
  /* @__PURE__ */ jsxs("div", { className: "ps-bpm-row", children: [
5497
- /* @__PURE__ */ jsx("span", { className: "ps-bpm-label", children: t("AGE") }),
5498
- /* @__PURE__ */ jsxs("div", { className: "ps-bpm-value-group", children: [
5607
+ /* @__PURE__ */ jsxs("div", { className: "ps-bpm-row-top", children: [
5608
+ /* @__PURE__ */ jsx("span", { className: "ps-bpm-label", children: t("AGE") }),
5609
+ /* @__PURE__ */ jsxs("span", { className: "ps-bpm-value-display", children: [
5610
+ Math.round(ageNum),
5611
+ " ",
5612
+ t("YEARS")
5613
+ ] })
5614
+ ] }),
5615
+ /* @__PURE__ */ jsxs("div", { className: "ps-bpm-slider-row", children: [
5616
+ /* @__PURE__ */ jsx("button", { type: "button", className: "ps-bpm-step-btn", onClick: decAge, "aria-label": t("Decrease"), children: /* @__PURE__ */ jsx(MinusIcon, {}) }),
5499
5617
  /* @__PURE__ */ jsx(
5500
5618
  "input",
5501
5619
  {
5502
- type: "number",
5503
- inputMode: "numeric",
5504
- className: "ps-bpm-input",
5505
- value: age,
5620
+ type: "range",
5621
+ className: "ps-bpm-slider",
5622
+ min: ageMin,
5623
+ max: ageMax,
5624
+ step: 1,
5625
+ value: ageNum,
5506
5626
  onChange: (e) => setAge(e.target.value),
5507
- min: 13,
5508
- max: 100,
5509
- placeholder: "30"
5627
+ style: { ["--ps-pct"]: `${pctA}%` }
5510
5628
  }
5511
5629
  ),
5512
- /* @__PURE__ */ jsx("span", { className: "ps-bpm-unit", children: t("years") })
5630
+ /* @__PURE__ */ jsx("button", { type: "button", className: "ps-bpm-step-btn", onClick: incAge, "aria-label": t("Increase"), children: /* @__PURE__ */ jsx(PlusIcon, {}) })
5513
5631
  ] })
5514
5632
  ] })
5515
5633
  ] }),
5634
+ /* @__PURE__ */ jsx("div", { className: "ps-bpm-or", children: /* @__PURE__ */ jsx("span", { children: t("or") }) }),
5516
5635
  /* @__PURE__ */ jsxs(
5517
5636
  "button",
5518
5637
  {
5519
5638
  type: "button",
5520
- className: "ps-bpm-photo-card",
5639
+ className: "ps-bpm-upload-link",
5521
5640
  onClick: onUploadPhoto,
5522
5641
  children: [
5523
- /* @__PURE__ */ jsx("span", { className: "ps-bpm-photo-card-icon", children: /* @__PURE__ */ jsx(CameraSmallIcon, { size: 20 }) }),
5524
- /* @__PURE__ */ jsxs("div", { className: "ps-bpm-photo-card-content", children: [
5525
- /* @__PURE__ */ jsx("span", { className: "ps-bpm-photo-card-badge", children: t("RECOMMENDED") }),
5526
- /* @__PURE__ */ jsx("span", { className: "ps-bpm-photo-card-text", children: t("Upload a photo for AI sizing") })
5527
- ] }),
5528
- /* @__PURE__ */ jsx("span", { className: "ps-bpm-photo-card-arrow", children: /* @__PURE__ */ jsx(ChevronRightIcon, {}) })
5642
+ /* @__PURE__ */ jsx(CameraSmallIcon, {}),
5643
+ /* @__PURE__ */ jsx("span", { children: t("Upload a photo for AI sizing") }),
5644
+ /* @__PURE__ */ jsx(ChevronRight, {})
5529
5645
  ]
5530
5646
  }
5531
5647
  ),
5532
- /* @__PURE__ */ jsx("p", { className: "ps-bpm-hint", children: t("Enter accurate height for better fit recommendations") }),
5533
5648
  error && /* @__PURE__ */ jsx("p", { className: "ps-bpm-error", children: error }),
5534
- /* @__PURE__ */ jsxs("div", { className: "ps-bpm-bottom-tabs", children: [
5535
- /* @__PURE__ */ jsxs(
5649
+ /* @__PURE__ */ jsx("div", { className: "ps-bpm-spacer" }),
5650
+ /* @__PURE__ */ jsxs("div", { className: "ps-bpm-bottom", children: [
5651
+ /* @__PURE__ */ jsx(
5536
5652
  "button",
5537
5653
  {
5538
5654
  type: "button",
5539
- className: "ps-bpm-bottom-tab ps-active",
5540
- onClick: () => {
5541
- },
5542
- children: [
5543
- /* @__PURE__ */ jsx(RulerIconSmall, {}),
5544
- t("MANUAL FIT")
5545
- ]
5655
+ className: "ps-bpm-next-btn",
5656
+ onClick: onNext,
5657
+ disabled: !canProceed,
5658
+ children: t("Next")
5546
5659
  }
5547
5660
  ),
5548
- /* @__PURE__ */ jsxs(
5549
- "button",
5661
+ /* @__PURE__ */ jsx(
5662
+ MobileBottomTabs,
5550
5663
  {
5551
- type: "button",
5552
- className: "ps-bpm-bottom-tab",
5553
- onClick: onSwitchToScan,
5554
- children: [
5555
- /* @__PURE__ */ jsx(ScanIconSmall, {}),
5556
- t("AI SCAN")
5557
- ]
5664
+ mode: "manual",
5665
+ onSwitchToManual: () => {
5666
+ },
5667
+ onSwitchToScan,
5668
+ t
5558
5669
  }
5559
5670
  )
5560
5671
  ] })
@@ -6002,7 +6113,31 @@ function BodyProfileView({
6002
6113
  ] })
6003
6114
  ] }),
6004
6115
  /* @__PURE__ */ jsx("input", { ref: fileInputRef, type: "file", accept: "image/*", onChange: handlePhotoSelect, style: { display: "none" } }),
6005
- /* @__PURE__ */ jsxs("div", { className: "ps-bp-nav", children: [
6116
+ isMobile ? /* @__PURE__ */ jsxs(Fragment, { children: [
6117
+ /* @__PURE__ */ jsx("div", { className: "ps-bpm-spacer" }),
6118
+ /* @__PURE__ */ jsxs("div", { className: "ps-bpm-bottom", children: [
6119
+ /* @__PURE__ */ jsx(
6120
+ "button",
6121
+ {
6122
+ type: "button",
6123
+ className: "ps-bpm-next-btn",
6124
+ onClick: handleNext,
6125
+ disabled: !photoPreview,
6126
+ children: t("Analyze My Size")
6127
+ }
6128
+ ),
6129
+ /* @__PURE__ */ jsx(
6130
+ MobileBottomTabs,
6131
+ {
6132
+ mode: "scan",
6133
+ onSwitchToManual: () => setStep("basics"),
6134
+ onSwitchToScan: () => {
6135
+ },
6136
+ t
6137
+ }
6138
+ )
6139
+ ] })
6140
+ ] }) : /* @__PURE__ */ jsxs("div", { className: "ps-bp-nav", children: [
6006
6141
  /* @__PURE__ */ jsxs("button", { className: "ps-bp-back-btn", onClick: handleBackStep, type: "button", children: [
6007
6142
  /* @__PURE__ */ jsx("span", { className: "ps-bp-back-arrow", children: "←" }),
6008
6143
  " ",
@@ -6085,6 +6220,8 @@ function BodyProfileView({
6085
6220
  switchToImperial,
6086
6221
  onUploadPhoto: () => setStep("photo"),
6087
6222
  onSwitchToScan: () => setStep("photo"),
6223
+ onNext: handleNext,
6224
+ canProceed: true,
6088
6225
  error,
6089
6226
  t
6090
6227
  },
@@ -6262,7 +6399,7 @@ function BodyProfileView({
6262
6399
  })(),
6263
6400
  error && /* @__PURE__ */ jsx("p", { className: "ps-bp-error", children: error })
6264
6401
  ] }, "step-bra"),
6265
- /* @__PURE__ */ jsxs("div", { className: "ps-bp-nav", children: [
6402
+ !(isMobile && step === "basics") && /* @__PURE__ */ jsxs("div", { className: "ps-bp-nav", children: [
6266
6403
  step !== "basics" ? /* @__PURE__ */ jsxs("button", { className: "ps-bp-back-btn", onClick: handleBackStep, type: "button", children: [
6267
6404
  /* @__PURE__ */ jsx("span", { className: "ps-bp-back-arrow", children: "←" }),
6268
6405
  " ",