@primestyleai/tryon 5.8.20 → 5.8.22

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.
@@ -10271,7 +10271,7 @@ const STYLES$1 = `
10271
10271
  }
10272
10272
  .ps-tryon-sizing-product-img { opacity: 1; transition: opacity 0.5s cubic-bezier(0.4, 0, 0.2, 1); }
10273
10273
  .ps-tryon-sizing-product-img.ps-tryon-img-hidden { opacity: 0.08; }
10274
- .ps-tryon-sizing-measure-img { position: absolute; inset: 0; object-fit: cover; object-position: top center; opacity: 0; transition: opacity 0.5s cubic-bezier(0.4, 0, 0.2, 1); z-index: 2; will-change: opacity; }
10274
+ .ps-tryon-sizing-measure-img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain; object-position: center center; opacity: 0; transition: opacity 0.5s cubic-bezier(0.4, 0, 0.2, 1); z-index: 2; will-change: opacity; }
10275
10275
  .ps-tryon-sizing-measure-img.ps-tryon-img-visible { opacity: 1; }
10276
10276
  .ps-tryon-sizing-height-img { position: absolute; inset: 0; object-fit: contain !important; background: #f5f5f5; opacity: 0; transition: opacity 0.5s cubic-bezier(0.4, 0, 0.2, 1); z-index: 2; will-change: opacity; }
10277
10277
  .ps-tryon-sizing-height-img.ps-tryon-img-visible { opacity: 1; }
@@ -10577,8 +10577,8 @@ const STYLES$1 = `
10577
10577
  min-height: 5vw; padding: 0.4vw; max-height: 8vw;
10578
10578
  }
10579
10579
  .ps-tryon-sr-cards-stack .ps-tryon-sec-bigcard-bg {
10580
- max-height: 8vw; width: 100%;
10581
- object-fit: cover; object-position: center top;
10580
+ max-height: 8vw; width: 100%; height: 100%;
10581
+ object-fit: contain; object-position: center center;
10582
10582
  }
10583
10583
  .ps-tryon-sr-cards-stack .ps-tryon-sec-bigcard-overlay {
10584
10584
  height: 100%;
@@ -11822,8 +11822,8 @@ const STYLES$1 = `
11822
11822
 
11823
11823
  /* Image */
11824
11824
  .ps-tryon-sec-bigcard-bg {
11825
- width: 100%; max-height: 20vw; display: block;
11826
- object-fit: cover; object-position: center top;
11825
+ width: 100%; height: 100%; max-height: 20vw; display: block;
11826
+ object-fit: contain; object-position: center center;
11827
11827
  border-radius: 0.7vw 0.7vw 0 0;
11828
11828
  transition: transform 0.5s cubic-bezier(0.16, 1, 0.3, 1);
11829
11829
  }
@@ -12539,7 +12539,9 @@ const STYLES$1 = `
12539
12539
  display: flex;
12540
12540
  }
12541
12541
  .ps-bp-image-img {
12542
- width: 100%; height: 100%; object-fit: cover; object-position: center top; flex: 1;
12542
+ width: 100%; height: 100%;
12543
+ object-fit: contain; object-position: center center;
12544
+ flex: 1;
12543
12545
  }
12544
12546
  /* Upload zone — same element as .ps-bp-image, dashed border + centered content, full height */
12545
12547
  .ps-bp-image.ps-bp-upload-zone {
@@ -14164,6 +14166,141 @@ const STYLES$1 = `
14164
14166
  .ps-cpw-footer { flex-direction: column-reverse; gap: 10px; align-items: stretch; }
14165
14167
  .ps-cpw-next-btn { width: 100%; padding: 14px; }
14166
14168
  .ps-cpw-back-btn { text-align: center; }
14169
+ .ps-cpw-method-grid { grid-template-columns: 1fr; }
14170
+ .ps-cpw-method-card { padding: 22px 18px; }
14171
+ .ps-cpw-photo-frame { max-width: 100%; height: 320px; }
14172
+ }
14173
+
14174
+ /* ── Progressive (one-question-at-a-time) flow ── */
14175
+ .ps-cpw-progressive {
14176
+ display: flex; flex-direction: column; gap: 16px;
14177
+ padding: 8px 0;
14178
+ }
14179
+ .ps-cpw-fade-in {
14180
+ animation: ps-cpw-fade-up 0.35s cubic-bezier(0.16, 1, 0.3, 1);
14181
+ }
14182
+ @keyframes ps-cpw-fade-up {
14183
+ from { opacity: 0; transform: translateY(12px); }
14184
+ to { opacity: 1; transform: translateY(0); }
14185
+ }
14186
+
14187
+ /* ── Method picker (initial step) ── */
14188
+ .ps-cpw-method-picker {
14189
+ display: flex; flex-direction: column; align-items: center;
14190
+ gap: 24px; padding: 16px 0;
14191
+ }
14192
+ .ps-cpw-method-intro {
14193
+ font-size: 14px; color: var(--ps-text-muted);
14194
+ text-align: center; margin: 0;
14195
+ max-width: 480px;
14196
+ }
14197
+ .ps-cpw-method-grid {
14198
+ display: grid;
14199
+ grid-template-columns: 1fr 1fr;
14200
+ gap: 16px;
14201
+ width: 100%;
14202
+ }
14203
+ .ps-cpw-method-card {
14204
+ display: flex; flex-direction: column; align-items: flex-start;
14205
+ gap: 14px;
14206
+ padding: 28px 24px;
14207
+ background: var(--ps-bg-primary);
14208
+ border: 2px solid var(--ps-border-subtle);
14209
+ border-radius: 14px;
14210
+ cursor: pointer; font-family: inherit; text-align: left;
14211
+ transition: border-color 0.18s, transform 0.18s, box-shadow 0.18s;
14212
+ }
14213
+ .ps-cpw-method-card:hover {
14214
+ border-color: var(--ps-accent);
14215
+ transform: translateY(-2px);
14216
+ box-shadow: 0 10px 30px rgba(33, 84, 239, 0.12);
14217
+ }
14218
+ .ps-cpw-method-icon {
14219
+ width: 56px; height: 56px;
14220
+ border-radius: 14px;
14221
+ display: flex; align-items: center; justify-content: center;
14222
+ background: rgba(33, 84, 239, 0.08);
14223
+ color: var(--ps-accent);
14224
+ }
14225
+ .ps-cpw-method-title {
14226
+ font-size: 16px; font-weight: 700;
14227
+ color: var(--ps-text-primary);
14228
+ letter-spacing: -0.01em;
14229
+ }
14230
+ .ps-cpw-method-desc {
14231
+ font-size: 12.5px; line-height: 1.55;
14232
+ color: var(--ps-text-muted);
14233
+ }
14234
+
14235
+ /* ── Image-path photo step ── */
14236
+ .ps-cpw-photo-step {
14237
+ display: flex; flex-direction: column; align-items: stretch;
14238
+ gap: 16px; padding: 8px 0 24px;
14239
+ }
14240
+ .ps-cpw-photo-step-title {
14241
+ font-size: 18px; font-weight: 700; margin: 0;
14242
+ color: var(--ps-text-primary);
14243
+ }
14244
+ .ps-cpw-photo-step-sub {
14245
+ font-size: 13px; line-height: 1.6;
14246
+ color: var(--ps-text-muted); margin: 0;
14247
+ }
14248
+ .ps-cpw-photo-dropzone {
14249
+ display: flex; flex-direction: column; align-items: center; justify-content: center;
14250
+ gap: 10px;
14251
+ width: 100%;
14252
+ min-height: 360px;
14253
+ padding: 24px;
14254
+ border: 2px dashed var(--ps-border-color);
14255
+ border-radius: 14px;
14256
+ background: var(--ps-bg-secondary);
14257
+ color: var(--ps-text-muted);
14258
+ cursor: pointer; font-family: inherit;
14259
+ transition: border-color 0.18s, background 0.18s;
14260
+ }
14261
+ .ps-cpw-photo-dropzone:hover { border-color: var(--ps-accent); background: rgba(33, 84, 239, 0.04); }
14262
+ .ps-cpw-photo-dropzone:disabled { opacity: 0.6; cursor: default; }
14263
+ .ps-cpw-photo-dropzone-title {
14264
+ font-size: 14px; font-weight: 600; color: var(--ps-text-primary);
14265
+ }
14266
+ .ps-cpw-photo-dropzone-hint {
14267
+ font-size: 11px; color: var(--ps-text-muted);
14268
+ }
14269
+ .ps-cpw-photo-frame {
14270
+ position: relative;
14271
+ width: 100%;
14272
+ height: 480px;
14273
+ background: var(--ps-bg-secondary);
14274
+ border-radius: 14px;
14275
+ overflow: hidden;
14276
+ border: 1px solid var(--ps-border-subtle);
14277
+ }
14278
+ .ps-cpw-photo-frame-img {
14279
+ width: 100%; height: 100%;
14280
+ object-fit: contain;
14281
+ display: block;
14282
+ }
14283
+ .ps-cpw-photo-retake {
14284
+ align-self: center;
14285
+ padding: 12px 24px;
14286
+ border-radius: 999px;
14287
+ background: transparent;
14288
+ color: var(--ps-accent);
14289
+ border: 2px solid var(--ps-accent);
14290
+ font-weight: 700; font-size: 12px;
14291
+ text-transform: uppercase; letter-spacing: 0.08em;
14292
+ cursor: pointer; font-family: inherit;
14293
+ transition: background 0.18s;
14294
+ }
14295
+ .ps-cpw-photo-retake:hover { background: rgba(33, 84, 239, 0.08); }
14296
+ .ps-cpw-hint {
14297
+ font-size: 12.5px; line-height: 1.6;
14298
+ color: var(--ps-text-muted);
14299
+ margin: 8px 0 0;
14300
+ padding: 12px 14px;
14301
+ background: rgba(33, 84, 239, 0.05);
14302
+ border-left: 3px solid var(--ps-accent);
14303
+ border-radius: 6px;
14167
14304
  }
14168
14305
 
14169
14306
  /* ════════════════════════════════════════════════════════════════
@@ -17861,25 +17998,28 @@ function ShapeCard({
17861
17998
  }
17862
17999
  );
17863
18000
  }
17864
- function ShapeSection({
18001
+ function ProgressiveStep({
18002
+ stepKey,
17865
18003
  title,
17866
18004
  subtitle,
17867
18005
  children
17868
18006
  }) {
17869
- return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-cpw-section", children: [
18007
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-cpw-progressive ps-cpw-fade-in", children: [
17870
18008
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-cpw-section-head", children: [
17871
18009
  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-cpw-section-title", children: title }),
17872
18010
  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-cpw-section-sub", children: subtitle })
17873
18011
  ] }),
17874
18012
  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-cpw-card-row", children })
17875
- ] });
18013
+ ] }, stepKey);
17876
18014
  }
17877
18015
  function CreateProfileWizard({ onSave, onCancel, t: t2 }) {
17878
- const [step, setStep] = reactExports.useState(1);
18016
+ const [mode, setMode] = reactExports.useState(null);
18017
+ const [manualStep, setManualStep] = reactExports.useState("identity");
18018
+ const [imageStep, setImageStep] = reactExports.useState("name");
17879
18019
  const bodyScrollRef = reactExports.useRef(null);
17880
18020
  reactExports.useEffect(() => {
17881
18021
  if (bodyScrollRef.current) bodyScrollRef.current.scrollTop = 0;
17882
- }, [step]);
18022
+ }, [mode, manualStep, imageStep]);
17883
18023
  const [name, setName] = reactExports.useState("");
17884
18024
  const [gender, setGender] = reactExports.useState("male");
17885
18025
  const [unit, setUnit] = reactExports.useState("cm");
@@ -17926,7 +18066,11 @@ function CreateProfileWizard({ onSave, onCancel, t: t2 }) {
17926
18066
  const CUP_OPTIONS_US = ["AA", "A", "B", "C", "D", "DD/E", "DDD/F", "G", "H", "I", "J"];
17927
18067
  const isWomen = gender === "female";
17928
18068
  const imgs = isWomen ? BODY_IMAGES.female : BODY_IMAGES.male;
17929
- const validateStep1 = () => {
18069
+ const manualStepOrder = isWomen ? ["identity", "stomach", "seat", "hips", "bra"] : ["identity", "chest", "stomach", "seat"];
18070
+ const manualStepIdx = manualStepOrder.indexOf(manualStep);
18071
+ const manualStepCount = manualStepOrder.length;
18072
+ const isLastManualStep = manualStepIdx === manualStepCount - 1;
18073
+ const validateIdentity = () => {
17930
18074
  if (!name.trim()) {
17931
18075
  setError(t2("Please enter a profile name"));
17932
18076
  return false;
@@ -17949,52 +18093,141 @@ function CreateProfileWizard({ onSave, onCancel, t: t2 }) {
17949
18093
  setError("");
17950
18094
  return true;
17951
18095
  };
17952
- const handleContinue = () => {
17953
- if (step === 1) {
17954
- if (!validateStep1()) return;
17955
- setStep(2);
17956
- return;
18096
+ const validateNameOnly = () => {
18097
+ if (!name.trim()) {
18098
+ setError(t2("Please enter a profile name"));
18099
+ return false;
17957
18100
  }
17958
- const data = {
18101
+ setError("");
18102
+ return true;
18103
+ };
18104
+ const buildManualPayload = () => ({
18105
+ name: name.trim(),
18106
+ gender,
18107
+ sizingUnit: unit,
18108
+ heightUnit: unit,
18109
+ weightUnit: unit === "in" ? "lbs" : "kg",
18110
+ heightCm: parseFloat(heightVal),
18111
+ weightKg: parseFloat(weightVal),
18112
+ height: parseFloat(heightVal),
18113
+ weight: parseFloat(weightVal),
18114
+ age: parseFloat(ageVal),
18115
+ chestProfile: chestProfile || void 0,
18116
+ midsectionProfile: midsectionProfile || void 0,
18117
+ hipProfile: isWomen ? hipProfile || void 0 : seatProfile || void 0,
18118
+ bandSize: isWomen ? bandSize || void 0 : void 0,
18119
+ cupSize: isWomen ? cupSize || void 0 : void 0
18120
+ });
18121
+ const buildImagePayload = () => {
18122
+ const h = parseFloat(heightVal);
18123
+ const w2 = parseFloat(weightVal);
18124
+ const a = parseFloat(ageVal);
18125
+ return {
17959
18126
  name: name.trim(),
17960
18127
  gender,
17961
18128
  sizingUnit: unit,
17962
18129
  heightUnit: unit,
17963
18130
  weightUnit: unit === "in" ? "lbs" : "kg",
17964
- // Legacy keys (kept for backward compat with the existing storage)
17965
- heightCm: parseFloat(heightVal),
17966
- weightKg: parseFloat(weightVal),
17967
- // New canonical keys
17968
- height: parseFloat(heightVal),
17969
- weight: parseFloat(weightVal),
17970
- age: parseFloat(ageVal),
17971
- chestProfile: chestProfile || void 0,
17972
- midsectionProfile: midsectionProfile || void 0,
17973
- hipProfile: isWomen ? hipProfile || void 0 : seatProfile || void 0,
17974
- bandSize: isWomen ? bandSize || void 0 : void 0,
17975
- cupSize: isWomen ? cupSize || void 0 : void 0,
18131
+ ...h > 0 ? { heightCm: h, height: h } : {},
18132
+ ...w2 > 0 ? { weightKg: w2, weight: w2 } : {},
18133
+ ...a > 0 ? { age: a } : {},
17976
18134
  photoBase64: photoBase64 || void 0
17977
18135
  };
17978
- onSave(data);
18136
+ };
18137
+ const advanceManual = () => {
18138
+ if (manualStep === "identity") {
18139
+ if (!validateIdentity()) return;
18140
+ }
18141
+ if (manualStep === "chest" && !chestProfile) {
18142
+ setError(t2("Please pick an option"));
18143
+ return;
18144
+ }
18145
+ if (manualStep === "stomach" && !midsectionProfile) {
18146
+ setError(t2("Please pick an option"));
18147
+ return;
18148
+ }
18149
+ if (manualStep === "seat" && !seatProfile) {
18150
+ setError(t2("Please pick an option"));
18151
+ return;
18152
+ }
18153
+ if (manualStep === "hips" && !hipProfile) {
18154
+ setError(t2("Please pick an option"));
18155
+ return;
18156
+ }
18157
+ if (manualStep === "bra" && (!bandSize || !cupSize)) {
18158
+ setError(t2("Please pick band and cup size"));
18159
+ return;
18160
+ }
18161
+ setError("");
18162
+ if (isLastManualStep) {
18163
+ onSave(buildManualPayload());
18164
+ return;
18165
+ }
18166
+ setManualStep(manualStepOrder[manualStepIdx + 1]);
18167
+ };
18168
+ const goBackManual = () => {
18169
+ setError("");
18170
+ if (manualStep === "identity") {
18171
+ setMode(null);
18172
+ return;
18173
+ }
18174
+ setManualStep(manualStepOrder[Math.max(0, manualStepIdx - 1)]);
18175
+ };
18176
+ const advanceImage = () => {
18177
+ if (imageStep === "name") {
18178
+ if (!validateNameOnly()) return;
18179
+ setImageStep("photo");
18180
+ return;
18181
+ }
18182
+ if (!photoBase64) {
18183
+ setError(t2("Please upload a photo"));
18184
+ return;
18185
+ }
18186
+ setError("");
18187
+ onSave(buildImagePayload());
18188
+ };
18189
+ const goBackImage = () => {
18190
+ setError("");
18191
+ if (imageStep === "name") {
18192
+ setMode(null);
18193
+ return;
18194
+ }
18195
+ setImageStep("name");
17979
18196
  };
17980
18197
  const handleBack = () => {
17981
- if (step === 2) setStep(1);
17982
- else onCancel();
18198
+ if (mode === "manual") return goBackManual();
18199
+ if (mode === "image") return goBackImage();
18200
+ onCancel();
17983
18201
  };
17984
- const progressPct = step === 1 ? 50 : 100;
18202
+ const headerLabel = (() => {
18203
+ if (mode == null) return t2("CHOOSE A METHOD");
18204
+ if (mode === "manual") {
18205
+ const labels = {
18206
+ identity: t2("Identity"),
18207
+ chest: t2("Chest Profile"),
18208
+ stomach: t2("Stomach Profile"),
18209
+ seat: t2("Back & Seat"),
18210
+ hips: t2("Hip Profile"),
18211
+ bra: t2("Bra Size")
18212
+ };
18213
+ return `${t2("Step")} ${String(manualStepIdx + 1).padStart(2, "0")} — ${labels[manualStep]}`;
18214
+ }
18215
+ const idx = imageStep === "name" ? 1 : 2;
18216
+ const label = imageStep === "name" ? t2("Profile") : t2("Upload Photo");
18217
+ return `${t2("Step")} ${String(idx).padStart(2, "0")} — ${label}`;
18218
+ })();
18219
+ const progressPct = (() => {
18220
+ if (mode == null) return 0;
18221
+ if (mode === "manual") return Math.round((manualStepIdx + 1) / manualStepCount * 100);
18222
+ return imageStep === "name" ? 50 : 100;
18223
+ })();
17985
18224
  return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-cpw-root", children: [
17986
18225
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-cpw-step-head", children: [
17987
18226
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
17988
18227
  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-cpw-eyebrow", children: t2("CREATE PROFILE") }),
17989
- /* @__PURE__ */ jsxRuntimeExports.jsxs("h2", { className: "ps-cpw-step-title", children: [
17990
- t2("Step"),
17991
- " ",
17992
- String(step).padStart(2, "0"),
17993
- " — ",
17994
- step === 1 ? t2("Identity") : t2("Silhouette")
17995
- ] })
18228
+ /* @__PURE__ */ jsxRuntimeExports.jsx("h2", { className: "ps-cpw-step-title", children: headerLabel })
17996
18229
  ] }),
17997
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-cpw-progress", children: [
18230
+ mode != null && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-cpw-progress", children: [
17998
18231
  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-cpw-progress-track", children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-cpw-progress-fill", style: { width: `${progressPct}%` } }) }),
17999
18232
  /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "ps-cpw-progress-label", children: [
18000
18233
  progressPct,
@@ -18003,197 +18236,236 @@ function CreateProfileWizard({ onSave, onCancel, t: t2 }) {
18003
18236
  ] })
18004
18237
  ] })
18005
18238
  ] }),
18006
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-cpw-body", ref: bodyScrollRef, children: step === 1 ? /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-cpw-identity", children: [
18007
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-cpw-pill-row", children: [
18008
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-cpw-pill-group", children: [
18009
- /* @__PURE__ */ jsxRuntimeExports.jsx("button", { type: "button", className: `ps-cpw-pill${gender === "male" ? " ps-active" : ""}`, onClick: () => setGender("male"), children: t2("Male") }),
18010
- /* @__PURE__ */ jsxRuntimeExports.jsx("button", { type: "button", className: `ps-cpw-pill${gender === "female" ? " ps-active" : ""}`, onClick: () => setGender("female"), children: t2("Female") })
18011
- ] }),
18012
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-cpw-pill-group", children: [
18013
- /* @__PURE__ */ jsxRuntimeExports.jsx("button", { type: "button", className: `ps-cpw-pill${unit === "cm" ? " ps-active" : ""}`, onClick: () => setUnit("cm"), children: "cm" }),
18014
- /* @__PURE__ */ jsxRuntimeExports.jsx("button", { type: "button", className: `ps-cpw-pill${unit === "in" ? " ps-active" : ""}`, onClick: () => setUnit("in"), children: "in" })
18015
- ] })
18016
- ] }),
18017
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-cpw-field", children: [
18018
- /* @__PURE__ */ jsxRuntimeExports.jsx("label", { className: "ps-cpw-field-label", children: t2("PROFILE NAME") }),
18019
- /* @__PURE__ */ jsxRuntimeExports.jsx(
18020
- "input",
18021
- {
18022
- type: "text",
18023
- className: "ps-cpw-input",
18024
- value: name,
18025
- placeholder: t2("e.g. My Measurements"),
18026
- onChange: (e) => {
18027
- setName(e.target.value);
18028
- setError("");
18239
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-cpw-body", ref: bodyScrollRef, children: [
18240
+ mode == null && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-cpw-method-picker ps-cpw-fade-in", children: [
18241
+ /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "ps-cpw-method-intro", children: t2("How would you like us to find your size?") }),
18242
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-cpw-method-grid", children: [
18243
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(
18244
+ "button",
18245
+ {
18246
+ type: "button",
18247
+ className: "ps-cpw-method-card",
18248
+ onClick: () => {
18249
+ setMode("manual");
18250
+ setManualStep("identity");
18251
+ },
18252
+ children: [
18253
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-cpw-method-icon", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", width: "32", height: "32", children: [
18254
+ /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M3 7h18M3 12h18M3 17h18" }),
18255
+ /* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "6", cy: "7", r: "1", fill: "currentColor" }),
18256
+ /* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "14", cy: "12", r: "1", fill: "currentColor" }),
18257
+ /* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "9", cy: "17", r: "1", fill: "currentColor" })
18258
+ ] }) }),
18259
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-cpw-method-title", children: t2("Measure manually") }),
18260
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-cpw-method-desc", children: t2("Enter height, weight and answer a few quick body shape questions.") })
18261
+ ]
18029
18262
  }
18030
- }
18031
- )
18032
- ] }),
18033
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-cpw-split", children: [
18034
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-cpw-split-left", children: [
18035
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-cpw-field", children: [
18036
- /* @__PURE__ */ jsxRuntimeExports.jsxs("label", { className: "ps-cpw-field-label", children: [
18037
- t2("HEIGHT"),
18038
- " (",
18039
- unit,
18040
- ")"
18041
- ] }),
18042
- /* @__PURE__ */ jsxRuntimeExports.jsx(
18043
- "input",
18044
- {
18045
- type: "number",
18046
- inputMode: "numeric",
18047
- className: "ps-cpw-input",
18048
- value: heightVal,
18049
- placeholder: unit === "cm" ? t2("e.g. 173") : t2("e.g. 68 in"),
18050
- onChange: (e) => {
18051
- setHeightVal(e.target.value);
18052
- setError("");
18053
- }
18054
- }
18055
- )
18263
+ ),
18264
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(
18265
+ "button",
18266
+ {
18267
+ type: "button",
18268
+ className: "ps-cpw-method-card",
18269
+ onClick: () => {
18270
+ setMode("image");
18271
+ setImageStep("name");
18272
+ },
18273
+ children: [
18274
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-cpw-method-icon", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", width: "32", height: "32", children: [
18275
+ /* @__PURE__ */ jsxRuntimeExports.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" }),
18276
+ /* @__PURE__ */ jsxRuntimeExports.jsx("circle", { cx: "12", cy: "13", r: "4" })
18277
+ ] }) }),
18278
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-cpw-method-title", children: t2("Analyze by photo") }),
18279
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-cpw-method-desc", children: t2("Upload a full-body photo and our AI will calculate every measurement automatically.") })
18280
+ ]
18281
+ }
18282
+ )
18283
+ ] })
18284
+ ] }, "method-picker"),
18285
+ mode === "manual" && manualStep === "identity" && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-cpw-identity ps-cpw-fade-in", children: [
18286
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-cpw-pill-row", children: [
18287
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-cpw-pill-group", children: [
18288
+ /* @__PURE__ */ jsxRuntimeExports.jsx("button", { type: "button", className: `ps-cpw-pill${gender === "male" ? " ps-active" : ""}`, onClick: () => setGender("male"), children: t2("Male") }),
18289
+ /* @__PURE__ */ jsxRuntimeExports.jsx("button", { type: "button", className: `ps-cpw-pill${gender === "female" ? " ps-active" : ""}`, onClick: () => setGender("female"), children: t2("Female") })
18056
18290
  ] }),
18057
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-cpw-field", children: [
18058
- /* @__PURE__ */ jsxRuntimeExports.jsxs("label", { className: "ps-cpw-field-label", children: [
18059
- t2("WEIGHT"),
18060
- " (",
18061
- unit === "in" ? "lbs" : "kg",
18062
- ")"
18063
- ] }),
18064
- /* @__PURE__ */ jsxRuntimeExports.jsx(
18065
- "input",
18066
- {
18067
- type: "number",
18068
- inputMode: "numeric",
18069
- className: "ps-cpw-input",
18070
- value: weightVal,
18071
- placeholder: unit === "in" ? t2("e.g. 154") : t2("e.g. 70"),
18072
- onChange: (e) => {
18073
- setWeightVal(e.target.value);
18074
- setError("");
18075
- }
18291
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-cpw-pill-group", children: [
18292
+ /* @__PURE__ */ jsxRuntimeExports.jsx("button", { type: "button", className: `ps-cpw-pill${unit === "cm" ? " ps-active" : ""}`, onClick: () => setUnit("cm"), children: "cm" }),
18293
+ /* @__PURE__ */ jsxRuntimeExports.jsx("button", { type: "button", className: `ps-cpw-pill${unit === "in" ? " ps-active" : ""}`, onClick: () => setUnit("in"), children: "in" })
18294
+ ] })
18295
+ ] }),
18296
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-cpw-field", children: [
18297
+ /* @__PURE__ */ jsxRuntimeExports.jsx("label", { className: "ps-cpw-field-label", children: t2("PROFILE NAME") }),
18298
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
18299
+ "input",
18300
+ {
18301
+ type: "text",
18302
+ className: "ps-cpw-input",
18303
+ value: name,
18304
+ placeholder: t2("e.g. My Measurements"),
18305
+ onChange: (e) => {
18306
+ setName(e.target.value);
18307
+ setError("");
18076
18308
  }
18077
- )
18309
+ }
18310
+ )
18311
+ ] }),
18312
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-cpw-field", children: [
18313
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("label", { className: "ps-cpw-field-label", children: [
18314
+ t2("HEIGHT"),
18315
+ " (",
18316
+ unit,
18317
+ ")"
18078
18318
  ] }),
18079
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-cpw-field", children: [
18080
- /* @__PURE__ */ jsxRuntimeExports.jsxs("label", { className: "ps-cpw-field-label", children: [
18081
- t2("AGE"),
18082
- " (",
18083
- t2("years"),
18084
- ")"
18085
- ] }),
18086
- /* @__PURE__ */ jsxRuntimeExports.jsx(
18087
- "input",
18088
- {
18089
- type: "number",
18090
- inputMode: "numeric",
18091
- className: "ps-cpw-input",
18092
- value: ageVal,
18093
- placeholder: t2("e.g. 30"),
18094
- onChange: (e) => {
18095
- setAgeVal(e.target.value);
18096
- setError("");
18097
- }
18319
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
18320
+ "input",
18321
+ {
18322
+ type: "number",
18323
+ inputMode: "numeric",
18324
+ className: "ps-cpw-input",
18325
+ value: heightVal,
18326
+ placeholder: unit === "cm" ? t2("e.g. 173") : t2("e.g. 68 in"),
18327
+ onChange: (e) => {
18328
+ setHeightVal(e.target.value);
18329
+ setError("");
18098
18330
  }
18099
- )
18100
- ] })
18331
+ }
18332
+ )
18101
18333
  ] }),
18102
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-cpw-split-right", children: [
18103
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-cpw-field-label", children: t2("PROFILE PHOTO (OPTIONAL)") }),
18334
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-cpw-field", children: [
18335
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("label", { className: "ps-cpw-field-label", children: [
18336
+ t2("WEIGHT"),
18337
+ " (",
18338
+ unit === "in" ? "lbs" : "kg",
18339
+ ")"
18340
+ ] }),
18104
18341
  /* @__PURE__ */ jsxRuntimeExports.jsx(
18105
18342
  "input",
18106
18343
  {
18107
- ref: photoInputRef,
18108
- type: "file",
18109
- accept: "image/*",
18110
- onChange: handlePhotoSelect,
18111
- style: { display: "none" }
18112
- }
18113
- ),
18114
- photoBase64 ? /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-cpw-photo-preview", children: [
18115
- /* @__PURE__ */ jsxRuntimeExports.jsx("img", { src: photoBase64, alt: t2("Profile photo") }),
18116
- /* @__PURE__ */ jsxRuntimeExports.jsx(
18117
- "button",
18118
- {
18119
- type: "button",
18120
- className: "ps-cpw-photo-remove",
18121
- onClick: handleRemovePhoto,
18122
- "aria-label": t2("Remove photo"),
18123
- children: "×"
18344
+ type: "number",
18345
+ inputMode: "numeric",
18346
+ className: "ps-cpw-input",
18347
+ value: weightVal,
18348
+ placeholder: unit === "in" ? t2("e.g. 154") : t2("e.g. 70"),
18349
+ onChange: (e) => {
18350
+ setWeightVal(e.target.value);
18351
+ setError("");
18124
18352
  }
18125
- )
18126
- ] }) : /* @__PURE__ */ jsxRuntimeExports.jsxs(
18127
- "button",
18353
+ }
18354
+ )
18355
+ ] }),
18356
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-cpw-field", children: [
18357
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("label", { className: "ps-cpw-field-label", children: [
18358
+ t2("AGE"),
18359
+ " (",
18360
+ t2("years"),
18361
+ ")"
18362
+ ] }),
18363
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
18364
+ "input",
18128
18365
  {
18129
- type: "button",
18130
- className: "ps-cpw-photo-upload",
18131
- onClick: () => photoInputRef.current?.click(),
18132
- disabled: photoUploading,
18133
- children: [
18134
- /* @__PURE__ */ jsxRuntimeExports.jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", width: "22", height: "22", children: [
18135
- /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" }),
18136
- /* @__PURE__ */ jsxRuntimeExports.jsx("polyline", { points: "17 8 12 3 7 8" }),
18137
- /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "12", y1: "3", x2: "12", y2: "15" })
18138
- ] }),
18139
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ps-cpw-photo-upload-title", children: photoUploading ? t2("Uploading...") : t2("Upload a photo") }),
18140
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ps-cpw-photo-upload-hint", children: t2("Helps refine your AI sizing — JPEG, PNG up to 10MB") })
18141
- ]
18366
+ type: "number",
18367
+ inputMode: "numeric",
18368
+ className: "ps-cpw-input",
18369
+ value: ageVal,
18370
+ placeholder: t2("e.g. 30"),
18371
+ onChange: (e) => {
18372
+ setAgeVal(e.target.value);
18373
+ setError("");
18374
+ }
18142
18375
  }
18143
18376
  )
18144
- ] })
18145
- ] }),
18146
- error && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-cpw-error", children: error })
18147
- ] }) : /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-cpw-silhouette", children: [
18148
- !isWomen && /* @__PURE__ */ jsxRuntimeExports.jsxs(
18149
- ShapeSection,
18377
+ ] }),
18378
+ error && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-cpw-error", children: error })
18379
+ ] }, "manual-identity"),
18380
+ mode === "manual" && manualStep === "chest" && !isWomen && /* @__PURE__ */ jsxRuntimeExports.jsxs(
18381
+ ProgressiveStep,
18150
18382
  {
18383
+ stepKey: "chest",
18151
18384
  title: t2("CHEST PROFILE"),
18152
18385
  subtitle: t2("Select the profile that best matches your chest breadth"),
18153
18386
  children: [
18154
- /* @__PURE__ */ jsxRuntimeExports.jsx(ShapeCard, { img: imgs.chest?.narrow ?? null, label: t2("NARROW"), selected: chestProfile === "narrow", onSelect: () => setChestProfile("narrow") }),
18155
- /* @__PURE__ */ jsxRuntimeExports.jsx(ShapeCard, { img: imgs.chest?.average ?? null, label: t2("AVERAGE"), selected: chestProfile === "average", onSelect: () => setChestProfile("average") }),
18156
- /* @__PURE__ */ jsxRuntimeExports.jsx(ShapeCard, { img: imgs.chest?.broad ?? null, label: t2("BROAD"), selected: chestProfile === "broad", onSelect: () => setChestProfile("broad") })
18387
+ /* @__PURE__ */ jsxRuntimeExports.jsx(ShapeCard, { img: imgs.chest?.narrow ?? null, label: t2("NARROW"), selected: chestProfile === "narrow", onSelect: () => {
18388
+ setChestProfile("narrow");
18389
+ setError("");
18390
+ } }),
18391
+ /* @__PURE__ */ jsxRuntimeExports.jsx(ShapeCard, { img: imgs.chest?.average ?? null, label: t2("AVERAGE"), selected: chestProfile === "average", onSelect: () => {
18392
+ setChestProfile("average");
18393
+ setError("");
18394
+ } }),
18395
+ /* @__PURE__ */ jsxRuntimeExports.jsx(ShapeCard, { img: imgs.chest?.broad ?? null, label: t2("BROAD"), selected: chestProfile === "broad", onSelect: () => {
18396
+ setChestProfile("broad");
18397
+ setError("");
18398
+ } })
18157
18399
  ]
18158
18400
  }
18159
18401
  ),
18160
- /* @__PURE__ */ jsxRuntimeExports.jsxs(
18161
- ShapeSection,
18402
+ mode === "manual" && manualStep === "stomach" && /* @__PURE__ */ jsxRuntimeExports.jsxs(
18403
+ ProgressiveStep,
18162
18404
  {
18405
+ stepKey: "stomach",
18163
18406
  title: t2("STOMACH PROFILE"),
18164
18407
  subtitle: t2("Describe your mid-section silhouette"),
18165
18408
  children: [
18166
- /* @__PURE__ */ jsxRuntimeExports.jsx(ShapeCard, { img: imgs.stomach?.flat ?? null, label: t2("FLAT"), selected: midsectionProfile === "flat", onSelect: () => setMidsectionProfile("flat") }),
18167
- /* @__PURE__ */ jsxRuntimeExports.jsx(ShapeCard, { img: imgs.stomach?.average ?? null, label: t2("AVERAGE"), selected: midsectionProfile === "average", onSelect: () => setMidsectionProfile("average") }),
18168
- /* @__PURE__ */ jsxRuntimeExports.jsx(ShapeCard, { img: imgs.stomach?.round ?? null, label: t2("ROUND"), selected: midsectionProfile === "round", onSelect: () => setMidsectionProfile("round") })
18409
+ /* @__PURE__ */ jsxRuntimeExports.jsx(ShapeCard, { img: imgs.stomach?.flat ?? null, label: t2("FLAT"), selected: midsectionProfile === "flat", onSelect: () => {
18410
+ setMidsectionProfile("flat");
18411
+ setError("");
18412
+ } }),
18413
+ /* @__PURE__ */ jsxRuntimeExports.jsx(ShapeCard, { img: imgs.stomach?.average ?? null, label: t2("AVERAGE"), selected: midsectionProfile === "average", onSelect: () => {
18414
+ setMidsectionProfile("average");
18415
+ setError("");
18416
+ } }),
18417
+ /* @__PURE__ */ jsxRuntimeExports.jsx(ShapeCard, { img: imgs.stomach?.round ?? null, label: t2("ROUND"), selected: midsectionProfile === "round", onSelect: () => {
18418
+ setMidsectionProfile("round");
18419
+ setError("");
18420
+ } })
18169
18421
  ]
18170
18422
  }
18171
18423
  ),
18172
- /* @__PURE__ */ jsxRuntimeExports.jsxs(
18173
- ShapeSection,
18424
+ mode === "manual" && manualStep === "seat" && /* @__PURE__ */ jsxRuntimeExports.jsxs(
18425
+ ProgressiveStep,
18174
18426
  {
18427
+ stepKey: "seat",
18175
18428
  title: t2("BACK & SEAT"),
18176
18429
  subtitle: t2("The curvature of your lower spine and seat profile"),
18177
18430
  children: [
18178
- /* @__PURE__ */ jsxRuntimeExports.jsx(ShapeCard, { img: imgs.seat?.narrow ?? null, label: t2("STRAIGHT"), selected: seatProfile === "narrow", onSelect: () => setSeatProfile("narrow") }),
18179
- /* @__PURE__ */ jsxRuntimeExports.jsx(ShapeCard, { img: imgs.seat?.average ?? null, label: t2("CURVED"), selected: seatProfile === "average", onSelect: () => setSeatProfile("average") }),
18180
- /* @__PURE__ */ jsxRuntimeExports.jsx(ShapeCard, { img: imgs.seat?.full ?? null, label: t2("DEEP"), selected: seatProfile === "full", onSelect: () => setSeatProfile("full") })
18431
+ /* @__PURE__ */ jsxRuntimeExports.jsx(ShapeCard, { img: imgs.seat?.narrow ?? null, label: t2("STRAIGHT"), selected: seatProfile === "narrow", onSelect: () => {
18432
+ setSeatProfile("narrow");
18433
+ setError("");
18434
+ } }),
18435
+ /* @__PURE__ */ jsxRuntimeExports.jsx(ShapeCard, { img: imgs.seat?.average ?? null, label: t2("CURVED"), selected: seatProfile === "average", onSelect: () => {
18436
+ setSeatProfile("average");
18437
+ setError("");
18438
+ } }),
18439
+ /* @__PURE__ */ jsxRuntimeExports.jsx(ShapeCard, { img: imgs.seat?.full ?? null, label: t2("DEEP"), selected: seatProfile === "full", onSelect: () => {
18440
+ setSeatProfile("full");
18441
+ setError("");
18442
+ } })
18181
18443
  ]
18182
18444
  }
18183
18445
  ),
18184
- isWomen && imgs.hips && /* @__PURE__ */ jsxRuntimeExports.jsxs(
18185
- ShapeSection,
18446
+ mode === "manual" && manualStep === "hips" && isWomen && imgs.hips && /* @__PURE__ */ jsxRuntimeExports.jsxs(
18447
+ ProgressiveStep,
18186
18448
  {
18449
+ stepKey: "hips",
18187
18450
  title: t2("HIP PROFILE"),
18188
18451
  subtitle: t2("The curvature of your hips and thighs"),
18189
18452
  children: [
18190
- /* @__PURE__ */ jsxRuntimeExports.jsx(ShapeCard, { img: imgs.hips.narrow ?? null, label: t2("NARROW"), selected: hipProfile === "narrow", onSelect: () => setHipProfile("narrow") }),
18191
- /* @__PURE__ */ jsxRuntimeExports.jsx(ShapeCard, { img: imgs.hips.average ?? null, label: t2("AVERAGE"), selected: hipProfile === "average", onSelect: () => setHipProfile("average") }),
18192
- /* @__PURE__ */ jsxRuntimeExports.jsx(ShapeCard, { img: imgs.hips.full ?? null, label: t2("FULL"), selected: hipProfile === "full", onSelect: () => setHipProfile("full") })
18453
+ /* @__PURE__ */ jsxRuntimeExports.jsx(ShapeCard, { img: imgs.hips.narrow ?? null, label: t2("NARROW"), selected: hipProfile === "narrow", onSelect: () => {
18454
+ setHipProfile("narrow");
18455
+ setError("");
18456
+ } }),
18457
+ /* @__PURE__ */ jsxRuntimeExports.jsx(ShapeCard, { img: imgs.hips.average ?? null, label: t2("AVERAGE"), selected: hipProfile === "average", onSelect: () => {
18458
+ setHipProfile("average");
18459
+ setError("");
18460
+ } }),
18461
+ /* @__PURE__ */ jsxRuntimeExports.jsx(ShapeCard, { img: imgs.hips.full ?? null, label: t2("FULL"), selected: hipProfile === "full", onSelect: () => {
18462
+ setHipProfile("full");
18463
+ setError("");
18464
+ } })
18193
18465
  ]
18194
18466
  }
18195
18467
  ),
18196
- isWomen && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-cpw-section", children: [
18468
+ mode === "manual" && manualStep === "bra" && isWomen && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-cpw-progressive ps-cpw-fade-in", children: [
18197
18469
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-cpw-section-head", children: [
18198
18470
  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-cpw-section-title", children: t2("BRA SIZE") }),
18199
18471
  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-cpw-section-sub", children: t2("Helps us refine bust measurements for tops and dresses") })
@@ -18206,7 +18478,10 @@ function CreateProfileWizard({ onSave, onCancel, t: t2 }) {
18206
18478
  {
18207
18479
  className: "ps-cpw-input",
18208
18480
  value: bandSize ?? "",
18209
- onChange: (e) => setBandSize(e.target.value || null),
18481
+ onChange: (e) => {
18482
+ setBandSize(e.target.value || null);
18483
+ setError("");
18484
+ },
18210
18485
  children: [
18211
18486
  /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "", children: t2("Select") }),
18212
18487
  BAND_OPTIONS_US.map((b) => /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: b, children: b }, b))
@@ -18221,7 +18496,10 @@ function CreateProfileWizard({ onSave, onCancel, t: t2 }) {
18221
18496
  {
18222
18497
  className: "ps-cpw-input",
18223
18498
  value: cupSize ?? "",
18224
- onChange: (e) => setCupSize(e.target.value || null),
18499
+ onChange: (e) => {
18500
+ setCupSize(e.target.value || null);
18501
+ setError("");
18502
+ },
18225
18503
  children: [
18226
18504
  /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "", children: t2("Select") }),
18227
18505
  CUP_OPTIONS_US.map((c) => /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: c, children: c }, c))
@@ -18230,11 +18508,92 @@ function CreateProfileWizard({ onSave, onCancel, t: t2 }) {
18230
18508
  )
18231
18509
  ] })
18232
18510
  ] })
18233
- ] })
18234
- ] }) }),
18511
+ ] }, "bra"),
18512
+ mode === "manual" && error && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-cpw-error", children: error }),
18513
+ mode === "image" && imageStep === "name" && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-cpw-identity ps-cpw-fade-in", children: [
18514
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-cpw-pill-row", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-cpw-pill-group", children: [
18515
+ /* @__PURE__ */ jsxRuntimeExports.jsx("button", { type: "button", className: `ps-cpw-pill${gender === "male" ? " ps-active" : ""}`, onClick: () => setGender("male"), children: t2("Male") }),
18516
+ /* @__PURE__ */ jsxRuntimeExports.jsx("button", { type: "button", className: `ps-cpw-pill${gender === "female" ? " ps-active" : ""}`, onClick: () => setGender("female"), children: t2("Female") })
18517
+ ] }) }),
18518
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-cpw-field", children: [
18519
+ /* @__PURE__ */ jsxRuntimeExports.jsx("label", { className: "ps-cpw-field-label", children: t2("PROFILE NAME") }),
18520
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
18521
+ "input",
18522
+ {
18523
+ type: "text",
18524
+ className: "ps-cpw-input",
18525
+ value: name,
18526
+ placeholder: t2("e.g. My Photo Profile"),
18527
+ onChange: (e) => {
18528
+ setName(e.target.value);
18529
+ setError("");
18530
+ }
18531
+ }
18532
+ )
18533
+ ] }),
18534
+ /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "ps-cpw-hint", children: t2("Next, upload a full-body photo. Our AI will analyze it and compute every measurement (chest, waist, hips, sleeve, inseam, etc.) automatically.") }),
18535
+ error && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-cpw-error", children: error })
18536
+ ] }, "image-name"),
18537
+ mode === "image" && imageStep === "photo" && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-cpw-photo-step ps-cpw-fade-in", children: [
18538
+ /* @__PURE__ */ jsxRuntimeExports.jsx("h3", { className: "ps-cpw-photo-step-title", children: t2("Upload your photo") }),
18539
+ /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "ps-cpw-photo-step-sub", children: t2("Stand straight, full body in frame, neutral lighting. Form-fitting clothes give the most accurate result.") }),
18540
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
18541
+ "input",
18542
+ {
18543
+ ref: photoInputRef,
18544
+ type: "file",
18545
+ accept: "image/jpeg,image/png,image/webp",
18546
+ style: { display: "none" },
18547
+ onChange: handlePhotoSelect
18548
+ }
18549
+ ),
18550
+ photoBase64 ? /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-cpw-photo-frame", children: [
18551
+ /* @__PURE__ */ jsxRuntimeExports.jsx("img", { src: photoBase64, alt: t2("Profile photo"), className: "ps-cpw-photo-frame-img" }),
18552
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
18553
+ "button",
18554
+ {
18555
+ type: "button",
18556
+ className: "ps-cpw-photo-remove",
18557
+ onClick: handleRemovePhoto,
18558
+ "aria-label": t2("Remove photo"),
18559
+ children: "×"
18560
+ }
18561
+ )
18562
+ ] }) : /* @__PURE__ */ jsxRuntimeExports.jsxs(
18563
+ "button",
18564
+ {
18565
+ type: "button",
18566
+ className: "ps-cpw-photo-dropzone",
18567
+ onClick: () => photoInputRef.current?.click(),
18568
+ disabled: photoUploading,
18569
+ children: [
18570
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", width: "48", height: "48", children: [
18571
+ /* @__PURE__ */ jsxRuntimeExports.jsx("path", { d: "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" }),
18572
+ /* @__PURE__ */ jsxRuntimeExports.jsx("polyline", { points: "17 8 12 3 7 8" }),
18573
+ /* @__PURE__ */ jsxRuntimeExports.jsx("line", { x1: "12", y1: "3", x2: "12", y2: "15" })
18574
+ ] }),
18575
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ps-cpw-photo-dropzone-title", children: photoUploading ? t2("Processing...") : t2("Tap to upload a photo") }),
18576
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "ps-cpw-photo-dropzone-hint", children: t2("JPEG, PNG up to 10MB") })
18577
+ ]
18578
+ }
18579
+ ),
18580
+ photoBase64 && /* @__PURE__ */ jsxRuntimeExports.jsx(
18581
+ "button",
18582
+ {
18583
+ type: "button",
18584
+ className: "ps-cpw-photo-retake",
18585
+ onClick: () => photoInputRef.current?.click(),
18586
+ disabled: photoUploading,
18587
+ children: t2("RETAKE PHOTO")
18588
+ }
18589
+ ),
18590
+ error && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ps-cpw-error", children: error })
18591
+ ] }, "image-photo")
18592
+ ] }),
18235
18593
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "ps-cpw-footer", children: [
18236
- /* @__PURE__ */ jsxRuntimeExports.jsx("button", { type: "button", className: "ps-cpw-back-btn", onClick: handleBack, children: step === 1 ? t2("Cancel") : `← ${t2("Back to Identity")}` }),
18237
- /* @__PURE__ */ jsxRuntimeExports.jsx("button", { type: "button", className: "ps-cpw-next-btn", onClick: handleContinue, children: step === 1 ? t2("Continue") : t2("CALCULATE MY FIT") })
18594
+ /* @__PURE__ */ jsxRuntimeExports.jsx("button", { type: "button", className: "ps-cpw-back-btn", onClick: handleBack, children: mode == null ? t2("Cancel") : `← ${t2("Back")}` }),
18595
+ mode === "manual" && /* @__PURE__ */ jsxRuntimeExports.jsx("button", { type: "button", className: "ps-cpw-next-btn", onClick: advanceManual, children: isLastManualStep ? t2("CALCULATE MY FIT") : t2("Continue") }),
18596
+ mode === "image" && /* @__PURE__ */ jsxRuntimeExports.jsx("button", { type: "button", className: "ps-cpw-next-btn", onClick: advanceImage, disabled: imageStep === "photo" && !photoBase64, children: imageStep === "name" ? t2("Continue") : t2("ANALYZE BY IMAGE") })
18238
18597
  ] })
18239
18598
  ] });
18240
18599
  }
@@ -20540,18 +20899,23 @@ function PrimeStyleTryonInner({
20540
20899
  setBodyLandmarks(null);
20541
20900
  detectMeasurementLines(objUrl).then((lines) => {
20542
20901
  modelPoseRef.current = lines;
20543
- }).catch(() => {
20544
- });
20545
- detectBodyLandmarks(objUrl).then((lm) => {
20902
+ return lines;
20903
+ }).catch(() => null);
20904
+ const landmarksPromise = detectBodyLandmarks(objUrl).then((lm) => {
20546
20905
  setBodyLandmarks(lm);
20547
- }).catch(() => {
20548
- });
20906
+ return lm;
20907
+ }).catch(() => null);
20908
+ const landmarks = await landmarksPromise;
20549
20909
  const payload = {
20550
20910
  method: "photo",
20551
20911
  locale: sizingCountry,
20552
20912
  sizingUnit,
20553
20913
  product: { title: productTitle, description: "", variants: [] },
20554
20914
  bodyImage: data.photoBase64,
20915
+ // BlazePose landmarks (normalized 0–1 coordinates). The backend uses
20916
+ // these to compute exact pixel distances and feed them to Gemini as
20917
+ // anchors instead of asking it to estimate visually.
20918
+ bodyLandmarks: landmarks || void 0,
20555
20919
  measurements: {
20556
20920
  gender: data.gender,
20557
20921
  height: data.height,