@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.
@@ -847,7 +847,7 @@ const STYLES = `
847
847
  }
848
848
  .ps-tryon-sizing-product-img { opacity: 1; transition: opacity 0.5s cubic-bezier(0.4, 0, 0.2, 1); }
849
849
  .ps-tryon-sizing-product-img.ps-tryon-img-hidden { opacity: 0.08; }
850
- .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; }
850
+ .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; }
851
851
  .ps-tryon-sizing-measure-img.ps-tryon-img-visible { opacity: 1; }
852
852
  .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; }
853
853
  .ps-tryon-sizing-height-img.ps-tryon-img-visible { opacity: 1; }
@@ -1153,8 +1153,8 @@ const STYLES = `
1153
1153
  min-height: 5vw; padding: 0.4vw; max-height: 8vw;
1154
1154
  }
1155
1155
  .ps-tryon-sr-cards-stack .ps-tryon-sec-bigcard-bg {
1156
- max-height: 8vw; width: 100%;
1157
- object-fit: cover; object-position: center top;
1156
+ max-height: 8vw; width: 100%; height: 100%;
1157
+ object-fit: contain; object-position: center center;
1158
1158
  }
1159
1159
  .ps-tryon-sr-cards-stack .ps-tryon-sec-bigcard-overlay {
1160
1160
  height: 100%;
@@ -2398,8 +2398,8 @@ const STYLES = `
2398
2398
 
2399
2399
  /* Image */
2400
2400
  .ps-tryon-sec-bigcard-bg {
2401
- width: 100%; max-height: 20vw; display: block;
2402
- object-fit: cover; object-position: center top;
2401
+ width: 100%; height: 100%; max-height: 20vw; display: block;
2402
+ object-fit: contain; object-position: center center;
2403
2403
  border-radius: 0.7vw 0.7vw 0 0;
2404
2404
  transition: transform 0.5s cubic-bezier(0.16, 1, 0.3, 1);
2405
2405
  }
@@ -3115,7 +3115,9 @@ const STYLES = `
3115
3115
  display: flex;
3116
3116
  }
3117
3117
  .ps-bp-image-img {
3118
- width: 100%; height: 100%; object-fit: cover; object-position: center top; flex: 1;
3118
+ width: 100%; height: 100%;
3119
+ object-fit: contain; object-position: center center;
3120
+ flex: 1;
3119
3121
  }
3120
3122
  /* Upload zone — same element as .ps-bp-image, dashed border + centered content, full height */
3121
3123
  .ps-bp-image.ps-bp-upload-zone {
@@ -4740,6 +4742,141 @@ const STYLES = `
4740
4742
  .ps-cpw-footer { flex-direction: column-reverse; gap: 10px; align-items: stretch; }
4741
4743
  .ps-cpw-next-btn { width: 100%; padding: 14px; }
4742
4744
  .ps-cpw-back-btn { text-align: center; }
4745
+ .ps-cpw-method-grid { grid-template-columns: 1fr; }
4746
+ .ps-cpw-method-card { padding: 22px 18px; }
4747
+ .ps-cpw-photo-frame { max-width: 100%; height: 320px; }
4748
+ }
4749
+
4750
+ /* ── Progressive (one-question-at-a-time) flow ── */
4751
+ .ps-cpw-progressive {
4752
+ display: flex; flex-direction: column; gap: 16px;
4753
+ padding: 8px 0;
4754
+ }
4755
+ .ps-cpw-fade-in {
4756
+ animation: ps-cpw-fade-up 0.35s cubic-bezier(0.16, 1, 0.3, 1);
4757
+ }
4758
+ @keyframes ps-cpw-fade-up {
4759
+ from { opacity: 0; transform: translateY(12px); }
4760
+ to { opacity: 1; transform: translateY(0); }
4761
+ }
4762
+
4763
+ /* ── Method picker (initial step) ── */
4764
+ .ps-cpw-method-picker {
4765
+ display: flex; flex-direction: column; align-items: center;
4766
+ gap: 24px; padding: 16px 0;
4767
+ }
4768
+ .ps-cpw-method-intro {
4769
+ font-size: 14px; color: var(--ps-text-muted);
4770
+ text-align: center; margin: 0;
4771
+ max-width: 480px;
4772
+ }
4773
+ .ps-cpw-method-grid {
4774
+ display: grid;
4775
+ grid-template-columns: 1fr 1fr;
4776
+ gap: 16px;
4777
+ width: 100%;
4778
+ }
4779
+ .ps-cpw-method-card {
4780
+ display: flex; flex-direction: column; align-items: flex-start;
4781
+ gap: 14px;
4782
+ padding: 28px 24px;
4783
+ background: var(--ps-bg-primary);
4784
+ border: 2px solid var(--ps-border-subtle);
4785
+ border-radius: 14px;
4786
+ cursor: pointer; font-family: inherit; text-align: left;
4787
+ transition: border-color 0.18s, transform 0.18s, box-shadow 0.18s;
4788
+ }
4789
+ .ps-cpw-method-card:hover {
4790
+ border-color: var(--ps-accent);
4791
+ transform: translateY(-2px);
4792
+ box-shadow: 0 10px 30px rgba(33, 84, 239, 0.12);
4793
+ }
4794
+ .ps-cpw-method-icon {
4795
+ width: 56px; height: 56px;
4796
+ border-radius: 14px;
4797
+ display: flex; align-items: center; justify-content: center;
4798
+ background: rgba(33, 84, 239, 0.08);
4799
+ color: var(--ps-accent);
4800
+ }
4801
+ .ps-cpw-method-title {
4802
+ font-size: 16px; font-weight: 700;
4803
+ color: var(--ps-text-primary);
4804
+ letter-spacing: -0.01em;
4805
+ }
4806
+ .ps-cpw-method-desc {
4807
+ font-size: 12.5px; line-height: 1.55;
4808
+ color: var(--ps-text-muted);
4809
+ }
4810
+
4811
+ /* ── Image-path photo step ── */
4812
+ .ps-cpw-photo-step {
4813
+ display: flex; flex-direction: column; align-items: stretch;
4814
+ gap: 16px; padding: 8px 0 24px;
4815
+ }
4816
+ .ps-cpw-photo-step-title {
4817
+ font-size: 18px; font-weight: 700; margin: 0;
4818
+ color: var(--ps-text-primary);
4819
+ }
4820
+ .ps-cpw-photo-step-sub {
4821
+ font-size: 13px; line-height: 1.6;
4822
+ color: var(--ps-text-muted); margin: 0;
4823
+ }
4824
+ .ps-cpw-photo-dropzone {
4825
+ display: flex; flex-direction: column; align-items: center; justify-content: center;
4826
+ gap: 10px;
4827
+ width: 100%;
4828
+ min-height: 360px;
4829
+ padding: 24px;
4830
+ border: 2px dashed var(--ps-border-color);
4831
+ border-radius: 14px;
4832
+ background: var(--ps-bg-secondary);
4833
+ color: var(--ps-text-muted);
4834
+ cursor: pointer; font-family: inherit;
4835
+ transition: border-color 0.18s, background 0.18s;
4836
+ }
4837
+ .ps-cpw-photo-dropzone:hover { border-color: var(--ps-accent); background: rgba(33, 84, 239, 0.04); }
4838
+ .ps-cpw-photo-dropzone:disabled { opacity: 0.6; cursor: default; }
4839
+ .ps-cpw-photo-dropzone-title {
4840
+ font-size: 14px; font-weight: 600; color: var(--ps-text-primary);
4841
+ }
4842
+ .ps-cpw-photo-dropzone-hint {
4843
+ font-size: 11px; color: var(--ps-text-muted);
4844
+ }
4845
+ .ps-cpw-photo-frame {
4846
+ position: relative;
4847
+ width: 100%;
4848
+ height: 480px;
4849
+ background: var(--ps-bg-secondary);
4850
+ border-radius: 14px;
4851
+ overflow: hidden;
4852
+ border: 1px solid var(--ps-border-subtle);
4853
+ }
4854
+ .ps-cpw-photo-frame-img {
4855
+ width: 100%; height: 100%;
4856
+ object-fit: contain;
4857
+ display: block;
4858
+ }
4859
+ .ps-cpw-photo-retake {
4860
+ align-self: center;
4861
+ padding: 12px 24px;
4862
+ border-radius: 999px;
4863
+ background: transparent;
4864
+ color: var(--ps-accent);
4865
+ border: 2px solid var(--ps-accent);
4866
+ font-weight: 700; font-size: 12px;
4867
+ text-transform: uppercase; letter-spacing: 0.08em;
4868
+ cursor: pointer; font-family: inherit;
4869
+ transition: background 0.18s;
4870
+ }
4871
+ .ps-cpw-photo-retake:hover { background: rgba(33, 84, 239, 0.08); }
4872
+ .ps-cpw-hint {
4873
+ font-size: 12.5px; line-height: 1.6;
4874
+ color: var(--ps-text-muted);
4875
+ margin: 8px 0 0;
4876
+ padding: 12px 14px;
4877
+ background: rgba(33, 84, 239, 0.05);
4878
+ border-left: 3px solid var(--ps-accent);
4879
+ border-radius: 6px;
4743
4880
  }
4744
4881
 
4745
4882
  /* ════════════════════════════════════════════════════════════════
@@ -8437,25 +8574,28 @@ function ShapeCard({
8437
8574
  }
8438
8575
  );
8439
8576
  }
8440
- function ShapeSection({
8577
+ function ProgressiveStep({
8578
+ stepKey,
8441
8579
  title,
8442
8580
  subtitle,
8443
8581
  children
8444
8582
  }) {
8445
- return /* @__PURE__ */ jsxs("div", { className: "ps-cpw-section", children: [
8583
+ return /* @__PURE__ */ jsxs("div", { className: "ps-cpw-progressive ps-cpw-fade-in", children: [
8446
8584
  /* @__PURE__ */ jsxs("div", { className: "ps-cpw-section-head", children: [
8447
8585
  /* @__PURE__ */ jsx("div", { className: "ps-cpw-section-title", children: title }),
8448
8586
  /* @__PURE__ */ jsx("div", { className: "ps-cpw-section-sub", children: subtitle })
8449
8587
  ] }),
8450
8588
  /* @__PURE__ */ jsx("div", { className: "ps-cpw-card-row", children })
8451
- ] });
8589
+ ] }, stepKey);
8452
8590
  }
8453
8591
  function CreateProfileWizard({ onSave, onCancel, t }) {
8454
- const [step, setStep] = useState(1);
8592
+ const [mode, setMode] = useState(null);
8593
+ const [manualStep, setManualStep] = useState("identity");
8594
+ const [imageStep, setImageStep] = useState("name");
8455
8595
  const bodyScrollRef = useRef(null);
8456
8596
  useEffect(() => {
8457
8597
  if (bodyScrollRef.current) bodyScrollRef.current.scrollTop = 0;
8458
- }, [step]);
8598
+ }, [mode, manualStep, imageStep]);
8459
8599
  const [name, setName] = useState("");
8460
8600
  const [gender, setGender] = useState("male");
8461
8601
  const [unit, setUnit] = useState("cm");
@@ -8502,7 +8642,11 @@ function CreateProfileWizard({ onSave, onCancel, t }) {
8502
8642
  const CUP_OPTIONS_US = ["AA", "A", "B", "C", "D", "DD/E", "DDD/F", "G", "H", "I", "J"];
8503
8643
  const isWomen = gender === "female";
8504
8644
  const imgs = isWomen ? BODY_IMAGES.female : BODY_IMAGES.male;
8505
- const validateStep1 = () => {
8645
+ const manualStepOrder = isWomen ? ["identity", "stomach", "seat", "hips", "bra"] : ["identity", "chest", "stomach", "seat"];
8646
+ const manualStepIdx = manualStepOrder.indexOf(manualStep);
8647
+ const manualStepCount = manualStepOrder.length;
8648
+ const isLastManualStep = manualStepIdx === manualStepCount - 1;
8649
+ const validateIdentity = () => {
8506
8650
  if (!name.trim()) {
8507
8651
  setError(t("Please enter a profile name"));
8508
8652
  return false;
@@ -8525,52 +8669,141 @@ function CreateProfileWizard({ onSave, onCancel, t }) {
8525
8669
  setError("");
8526
8670
  return true;
8527
8671
  };
8528
- const handleContinue = () => {
8529
- if (step === 1) {
8530
- if (!validateStep1()) return;
8531
- setStep(2);
8532
- return;
8672
+ const validateNameOnly = () => {
8673
+ if (!name.trim()) {
8674
+ setError(t("Please enter a profile name"));
8675
+ return false;
8533
8676
  }
8534
- const data = {
8677
+ setError("");
8678
+ return true;
8679
+ };
8680
+ const buildManualPayload = () => ({
8681
+ name: name.trim(),
8682
+ gender,
8683
+ sizingUnit: unit,
8684
+ heightUnit: unit,
8685
+ weightUnit: unit === "in" ? "lbs" : "kg",
8686
+ heightCm: parseFloat(heightVal),
8687
+ weightKg: parseFloat(weightVal),
8688
+ height: parseFloat(heightVal),
8689
+ weight: parseFloat(weightVal),
8690
+ age: parseFloat(ageVal),
8691
+ chestProfile: chestProfile || void 0,
8692
+ midsectionProfile: midsectionProfile || void 0,
8693
+ hipProfile: isWomen ? hipProfile || void 0 : seatProfile || void 0,
8694
+ bandSize: isWomen ? bandSize || void 0 : void 0,
8695
+ cupSize: isWomen ? cupSize || void 0 : void 0
8696
+ });
8697
+ const buildImagePayload = () => {
8698
+ const h = parseFloat(heightVal);
8699
+ const w = parseFloat(weightVal);
8700
+ const a = parseFloat(ageVal);
8701
+ return {
8535
8702
  name: name.trim(),
8536
8703
  gender,
8537
8704
  sizingUnit: unit,
8538
8705
  heightUnit: unit,
8539
8706
  weightUnit: unit === "in" ? "lbs" : "kg",
8540
- // Legacy keys (kept for backward compat with the existing storage)
8541
- heightCm: parseFloat(heightVal),
8542
- weightKg: parseFloat(weightVal),
8543
- // New canonical keys
8544
- height: parseFloat(heightVal),
8545
- weight: parseFloat(weightVal),
8546
- age: parseFloat(ageVal),
8547
- chestProfile: chestProfile || void 0,
8548
- midsectionProfile: midsectionProfile || void 0,
8549
- hipProfile: isWomen ? hipProfile || void 0 : seatProfile || void 0,
8550
- bandSize: isWomen ? bandSize || void 0 : void 0,
8551
- cupSize: isWomen ? cupSize || void 0 : void 0,
8707
+ ...h > 0 ? { heightCm: h, height: h } : {},
8708
+ ...w > 0 ? { weightKg: w, weight: w } : {},
8709
+ ...a > 0 ? { age: a } : {},
8552
8710
  photoBase64: photoBase64 || void 0
8553
8711
  };
8554
- onSave(data);
8712
+ };
8713
+ const advanceManual = () => {
8714
+ if (manualStep === "identity") {
8715
+ if (!validateIdentity()) return;
8716
+ }
8717
+ if (manualStep === "chest" && !chestProfile) {
8718
+ setError(t("Please pick an option"));
8719
+ return;
8720
+ }
8721
+ if (manualStep === "stomach" && !midsectionProfile) {
8722
+ setError(t("Please pick an option"));
8723
+ return;
8724
+ }
8725
+ if (manualStep === "seat" && !seatProfile) {
8726
+ setError(t("Please pick an option"));
8727
+ return;
8728
+ }
8729
+ if (manualStep === "hips" && !hipProfile) {
8730
+ setError(t("Please pick an option"));
8731
+ return;
8732
+ }
8733
+ if (manualStep === "bra" && (!bandSize || !cupSize)) {
8734
+ setError(t("Please pick band and cup size"));
8735
+ return;
8736
+ }
8737
+ setError("");
8738
+ if (isLastManualStep) {
8739
+ onSave(buildManualPayload());
8740
+ return;
8741
+ }
8742
+ setManualStep(manualStepOrder[manualStepIdx + 1]);
8743
+ };
8744
+ const goBackManual = () => {
8745
+ setError("");
8746
+ if (manualStep === "identity") {
8747
+ setMode(null);
8748
+ return;
8749
+ }
8750
+ setManualStep(manualStepOrder[Math.max(0, manualStepIdx - 1)]);
8751
+ };
8752
+ const advanceImage = () => {
8753
+ if (imageStep === "name") {
8754
+ if (!validateNameOnly()) return;
8755
+ setImageStep("photo");
8756
+ return;
8757
+ }
8758
+ if (!photoBase64) {
8759
+ setError(t("Please upload a photo"));
8760
+ return;
8761
+ }
8762
+ setError("");
8763
+ onSave(buildImagePayload());
8764
+ };
8765
+ const goBackImage = () => {
8766
+ setError("");
8767
+ if (imageStep === "name") {
8768
+ setMode(null);
8769
+ return;
8770
+ }
8771
+ setImageStep("name");
8555
8772
  };
8556
8773
  const handleBack = () => {
8557
- if (step === 2) setStep(1);
8558
- else onCancel();
8774
+ if (mode === "manual") return goBackManual();
8775
+ if (mode === "image") return goBackImage();
8776
+ onCancel();
8559
8777
  };
8560
- const progressPct = step === 1 ? 50 : 100;
8778
+ const headerLabel = (() => {
8779
+ if (mode == null) return t("CHOOSE A METHOD");
8780
+ if (mode === "manual") {
8781
+ const labels = {
8782
+ identity: t("Identity"),
8783
+ chest: t("Chest Profile"),
8784
+ stomach: t("Stomach Profile"),
8785
+ seat: t("Back & Seat"),
8786
+ hips: t("Hip Profile"),
8787
+ bra: t("Bra Size")
8788
+ };
8789
+ return `${t("Step")} ${String(manualStepIdx + 1).padStart(2, "0")} — ${labels[manualStep]}`;
8790
+ }
8791
+ const idx = imageStep === "name" ? 1 : 2;
8792
+ const label = imageStep === "name" ? t("Profile") : t("Upload Photo");
8793
+ return `${t("Step")} ${String(idx).padStart(2, "0")} — ${label}`;
8794
+ })();
8795
+ const progressPct = (() => {
8796
+ if (mode == null) return 0;
8797
+ if (mode === "manual") return Math.round((manualStepIdx + 1) / manualStepCount * 100);
8798
+ return imageStep === "name" ? 50 : 100;
8799
+ })();
8561
8800
  return /* @__PURE__ */ jsxs("div", { className: "ps-cpw-root", children: [
8562
8801
  /* @__PURE__ */ jsxs("div", { className: "ps-cpw-step-head", children: [
8563
8802
  /* @__PURE__ */ jsxs("div", { children: [
8564
8803
  /* @__PURE__ */ jsx("div", { className: "ps-cpw-eyebrow", children: t("CREATE PROFILE") }),
8565
- /* @__PURE__ */ jsxs("h2", { className: "ps-cpw-step-title", children: [
8566
- t("Step"),
8567
- " ",
8568
- String(step).padStart(2, "0"),
8569
- " — ",
8570
- step === 1 ? t("Identity") : t("Silhouette")
8571
- ] })
8804
+ /* @__PURE__ */ jsx("h2", { className: "ps-cpw-step-title", children: headerLabel })
8572
8805
  ] }),
8573
- /* @__PURE__ */ jsxs("div", { className: "ps-cpw-progress", children: [
8806
+ mode != null && /* @__PURE__ */ jsxs("div", { className: "ps-cpw-progress", children: [
8574
8807
  /* @__PURE__ */ jsx("div", { className: "ps-cpw-progress-track", children: /* @__PURE__ */ jsx("div", { className: "ps-cpw-progress-fill", style: { width: `${progressPct}%` } }) }),
8575
8808
  /* @__PURE__ */ jsxs("span", { className: "ps-cpw-progress-label", children: [
8576
8809
  progressPct,
@@ -8579,197 +8812,236 @@ function CreateProfileWizard({ onSave, onCancel, t }) {
8579
8812
  ] })
8580
8813
  ] })
8581
8814
  ] }),
8582
- /* @__PURE__ */ jsx("div", { className: "ps-cpw-body", ref: bodyScrollRef, children: step === 1 ? /* @__PURE__ */ jsxs("div", { className: "ps-cpw-identity", children: [
8583
- /* @__PURE__ */ jsxs("div", { className: "ps-cpw-pill-row", children: [
8584
- /* @__PURE__ */ jsxs("div", { className: "ps-cpw-pill-group", children: [
8585
- /* @__PURE__ */ jsx("button", { type: "button", className: `ps-cpw-pill${gender === "male" ? " ps-active" : ""}`, onClick: () => setGender("male"), children: t("Male") }),
8586
- /* @__PURE__ */ jsx("button", { type: "button", className: `ps-cpw-pill${gender === "female" ? " ps-active" : ""}`, onClick: () => setGender("female"), children: t("Female") })
8587
- ] }),
8588
- /* @__PURE__ */ jsxs("div", { className: "ps-cpw-pill-group", children: [
8589
- /* @__PURE__ */ jsx("button", { type: "button", className: `ps-cpw-pill${unit === "cm" ? " ps-active" : ""}`, onClick: () => setUnit("cm"), children: "cm" }),
8590
- /* @__PURE__ */ jsx("button", { type: "button", className: `ps-cpw-pill${unit === "in" ? " ps-active" : ""}`, onClick: () => setUnit("in"), children: "in" })
8591
- ] })
8592
- ] }),
8593
- /* @__PURE__ */ jsxs("div", { className: "ps-cpw-field", children: [
8594
- /* @__PURE__ */ jsx("label", { className: "ps-cpw-field-label", children: t("PROFILE NAME") }),
8595
- /* @__PURE__ */ jsx(
8596
- "input",
8597
- {
8598
- type: "text",
8599
- className: "ps-cpw-input",
8600
- value: name,
8601
- placeholder: t("e.g. My Measurements"),
8602
- onChange: (e) => {
8603
- setName(e.target.value);
8604
- setError("");
8815
+ /* @__PURE__ */ jsxs("div", { className: "ps-cpw-body", ref: bodyScrollRef, children: [
8816
+ mode == null && /* @__PURE__ */ jsxs("div", { className: "ps-cpw-method-picker ps-cpw-fade-in", children: [
8817
+ /* @__PURE__ */ jsx("p", { className: "ps-cpw-method-intro", children: t("How would you like us to find your size?") }),
8818
+ /* @__PURE__ */ jsxs("div", { className: "ps-cpw-method-grid", children: [
8819
+ /* @__PURE__ */ jsxs(
8820
+ "button",
8821
+ {
8822
+ type: "button",
8823
+ className: "ps-cpw-method-card",
8824
+ onClick: () => {
8825
+ setMode("manual");
8826
+ setManualStep("identity");
8827
+ },
8828
+ children: [
8829
+ /* @__PURE__ */ jsx("div", { className: "ps-cpw-method-icon", children: /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", width: "32", height: "32", children: [
8830
+ /* @__PURE__ */ jsx("path", { d: "M3 7h18M3 12h18M3 17h18" }),
8831
+ /* @__PURE__ */ jsx("circle", { cx: "6", cy: "7", r: "1", fill: "currentColor" }),
8832
+ /* @__PURE__ */ jsx("circle", { cx: "14", cy: "12", r: "1", fill: "currentColor" }),
8833
+ /* @__PURE__ */ jsx("circle", { cx: "9", cy: "17", r: "1", fill: "currentColor" })
8834
+ ] }) }),
8835
+ /* @__PURE__ */ jsx("div", { className: "ps-cpw-method-title", children: t("Measure manually") }),
8836
+ /* @__PURE__ */ jsx("div", { className: "ps-cpw-method-desc", children: t("Enter height, weight and answer a few quick body shape questions.") })
8837
+ ]
8605
8838
  }
8606
- }
8607
- )
8608
- ] }),
8609
- /* @__PURE__ */ jsxs("div", { className: "ps-cpw-split", children: [
8610
- /* @__PURE__ */ jsxs("div", { className: "ps-cpw-split-left", children: [
8611
- /* @__PURE__ */ jsxs("div", { className: "ps-cpw-field", children: [
8612
- /* @__PURE__ */ jsxs("label", { className: "ps-cpw-field-label", children: [
8613
- t("HEIGHT"),
8614
- " (",
8615
- unit,
8616
- ")"
8617
- ] }),
8618
- /* @__PURE__ */ jsx(
8619
- "input",
8620
- {
8621
- type: "number",
8622
- inputMode: "numeric",
8623
- className: "ps-cpw-input",
8624
- value: heightVal,
8625
- placeholder: unit === "cm" ? t("e.g. 173") : t("e.g. 68 in"),
8626
- onChange: (e) => {
8627
- setHeightVal(e.target.value);
8628
- setError("");
8629
- }
8630
- }
8631
- )
8839
+ ),
8840
+ /* @__PURE__ */ jsxs(
8841
+ "button",
8842
+ {
8843
+ type: "button",
8844
+ className: "ps-cpw-method-card",
8845
+ onClick: () => {
8846
+ setMode("image");
8847
+ setImageStep("name");
8848
+ },
8849
+ children: [
8850
+ /* @__PURE__ */ jsx("div", { className: "ps-cpw-method-icon", children: /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", width: "32", height: "32", children: [
8851
+ /* @__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" }),
8852
+ /* @__PURE__ */ jsx("circle", { cx: "12", cy: "13", r: "4" })
8853
+ ] }) }),
8854
+ /* @__PURE__ */ jsx("div", { className: "ps-cpw-method-title", children: t("Analyze by photo") }),
8855
+ /* @__PURE__ */ jsx("div", { className: "ps-cpw-method-desc", children: t("Upload a full-body photo and our AI will calculate every measurement automatically.") })
8856
+ ]
8857
+ }
8858
+ )
8859
+ ] })
8860
+ ] }, "method-picker"),
8861
+ mode === "manual" && manualStep === "identity" && /* @__PURE__ */ jsxs("div", { className: "ps-cpw-identity ps-cpw-fade-in", children: [
8862
+ /* @__PURE__ */ jsxs("div", { className: "ps-cpw-pill-row", children: [
8863
+ /* @__PURE__ */ jsxs("div", { className: "ps-cpw-pill-group", children: [
8864
+ /* @__PURE__ */ jsx("button", { type: "button", className: `ps-cpw-pill${gender === "male" ? " ps-active" : ""}`, onClick: () => setGender("male"), children: t("Male") }),
8865
+ /* @__PURE__ */ jsx("button", { type: "button", className: `ps-cpw-pill${gender === "female" ? " ps-active" : ""}`, onClick: () => setGender("female"), children: t("Female") })
8632
8866
  ] }),
8633
- /* @__PURE__ */ jsxs("div", { className: "ps-cpw-field", children: [
8634
- /* @__PURE__ */ jsxs("label", { className: "ps-cpw-field-label", children: [
8635
- t("WEIGHT"),
8636
- " (",
8637
- unit === "in" ? "lbs" : "kg",
8638
- ")"
8639
- ] }),
8640
- /* @__PURE__ */ jsx(
8641
- "input",
8642
- {
8643
- type: "number",
8644
- inputMode: "numeric",
8645
- className: "ps-cpw-input",
8646
- value: weightVal,
8647
- placeholder: unit === "in" ? t("e.g. 154") : t("e.g. 70"),
8648
- onChange: (e) => {
8649
- setWeightVal(e.target.value);
8650
- setError("");
8651
- }
8867
+ /* @__PURE__ */ jsxs("div", { className: "ps-cpw-pill-group", children: [
8868
+ /* @__PURE__ */ jsx("button", { type: "button", className: `ps-cpw-pill${unit === "cm" ? " ps-active" : ""}`, onClick: () => setUnit("cm"), children: "cm" }),
8869
+ /* @__PURE__ */ jsx("button", { type: "button", className: `ps-cpw-pill${unit === "in" ? " ps-active" : ""}`, onClick: () => setUnit("in"), children: "in" })
8870
+ ] })
8871
+ ] }),
8872
+ /* @__PURE__ */ jsxs("div", { className: "ps-cpw-field", children: [
8873
+ /* @__PURE__ */ jsx("label", { className: "ps-cpw-field-label", children: t("PROFILE NAME") }),
8874
+ /* @__PURE__ */ jsx(
8875
+ "input",
8876
+ {
8877
+ type: "text",
8878
+ className: "ps-cpw-input",
8879
+ value: name,
8880
+ placeholder: t("e.g. My Measurements"),
8881
+ onChange: (e) => {
8882
+ setName(e.target.value);
8883
+ setError("");
8652
8884
  }
8653
- )
8885
+ }
8886
+ )
8887
+ ] }),
8888
+ /* @__PURE__ */ jsxs("div", { className: "ps-cpw-field", children: [
8889
+ /* @__PURE__ */ jsxs("label", { className: "ps-cpw-field-label", children: [
8890
+ t("HEIGHT"),
8891
+ " (",
8892
+ unit,
8893
+ ")"
8654
8894
  ] }),
8655
- /* @__PURE__ */ jsxs("div", { className: "ps-cpw-field", children: [
8656
- /* @__PURE__ */ jsxs("label", { className: "ps-cpw-field-label", children: [
8657
- t("AGE"),
8658
- " (",
8659
- t("years"),
8660
- ")"
8661
- ] }),
8662
- /* @__PURE__ */ jsx(
8663
- "input",
8664
- {
8665
- type: "number",
8666
- inputMode: "numeric",
8667
- className: "ps-cpw-input",
8668
- value: ageVal,
8669
- placeholder: t("e.g. 30"),
8670
- onChange: (e) => {
8671
- setAgeVal(e.target.value);
8672
- setError("");
8673
- }
8895
+ /* @__PURE__ */ jsx(
8896
+ "input",
8897
+ {
8898
+ type: "number",
8899
+ inputMode: "numeric",
8900
+ className: "ps-cpw-input",
8901
+ value: heightVal,
8902
+ placeholder: unit === "cm" ? t("e.g. 173") : t("e.g. 68 in"),
8903
+ onChange: (e) => {
8904
+ setHeightVal(e.target.value);
8905
+ setError("");
8674
8906
  }
8675
- )
8676
- ] })
8907
+ }
8908
+ )
8677
8909
  ] }),
8678
- /* @__PURE__ */ jsxs("div", { className: "ps-cpw-split-right", children: [
8679
- /* @__PURE__ */ jsx("div", { className: "ps-cpw-field-label", children: t("PROFILE PHOTO (OPTIONAL)") }),
8910
+ /* @__PURE__ */ jsxs("div", { className: "ps-cpw-field", children: [
8911
+ /* @__PURE__ */ jsxs("label", { className: "ps-cpw-field-label", children: [
8912
+ t("WEIGHT"),
8913
+ " (",
8914
+ unit === "in" ? "lbs" : "kg",
8915
+ ")"
8916
+ ] }),
8680
8917
  /* @__PURE__ */ jsx(
8681
8918
  "input",
8682
8919
  {
8683
- ref: photoInputRef,
8684
- type: "file",
8685
- accept: "image/*",
8686
- onChange: handlePhotoSelect,
8687
- style: { display: "none" }
8688
- }
8689
- ),
8690
- photoBase64 ? /* @__PURE__ */ jsxs("div", { className: "ps-cpw-photo-preview", children: [
8691
- /* @__PURE__ */ jsx("img", { src: photoBase64, alt: t("Profile photo") }),
8692
- /* @__PURE__ */ jsx(
8693
- "button",
8694
- {
8695
- type: "button",
8696
- className: "ps-cpw-photo-remove",
8697
- onClick: handleRemovePhoto,
8698
- "aria-label": t("Remove photo"),
8699
- children: "×"
8920
+ type: "number",
8921
+ inputMode: "numeric",
8922
+ className: "ps-cpw-input",
8923
+ value: weightVal,
8924
+ placeholder: unit === "in" ? t("e.g. 154") : t("e.g. 70"),
8925
+ onChange: (e) => {
8926
+ setWeightVal(e.target.value);
8927
+ setError("");
8700
8928
  }
8701
- )
8702
- ] }) : /* @__PURE__ */ jsxs(
8703
- "button",
8929
+ }
8930
+ )
8931
+ ] }),
8932
+ /* @__PURE__ */ jsxs("div", { className: "ps-cpw-field", children: [
8933
+ /* @__PURE__ */ jsxs("label", { className: "ps-cpw-field-label", children: [
8934
+ t("AGE"),
8935
+ " (",
8936
+ t("years"),
8937
+ ")"
8938
+ ] }),
8939
+ /* @__PURE__ */ jsx(
8940
+ "input",
8704
8941
  {
8705
- type: "button",
8706
- className: "ps-cpw-photo-upload",
8707
- onClick: () => photoInputRef.current?.click(),
8708
- disabled: photoUploading,
8709
- children: [
8710
- /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", width: "22", height: "22", children: [
8711
- /* @__PURE__ */ jsx("path", { d: "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" }),
8712
- /* @__PURE__ */ jsx("polyline", { points: "17 8 12 3 7 8" }),
8713
- /* @__PURE__ */ jsx("line", { x1: "12", y1: "3", x2: "12", y2: "15" })
8714
- ] }),
8715
- /* @__PURE__ */ jsx("span", { className: "ps-cpw-photo-upload-title", children: photoUploading ? t("Uploading...") : t("Upload a photo") }),
8716
- /* @__PURE__ */ jsx("span", { className: "ps-cpw-photo-upload-hint", children: t("Helps refine your AI sizing — JPEG, PNG up to 10MB") })
8717
- ]
8942
+ type: "number",
8943
+ inputMode: "numeric",
8944
+ className: "ps-cpw-input",
8945
+ value: ageVal,
8946
+ placeholder: t("e.g. 30"),
8947
+ onChange: (e) => {
8948
+ setAgeVal(e.target.value);
8949
+ setError("");
8950
+ }
8718
8951
  }
8719
8952
  )
8720
- ] })
8721
- ] }),
8722
- error && /* @__PURE__ */ jsx("div", { className: "ps-cpw-error", children: error })
8723
- ] }) : /* @__PURE__ */ jsxs("div", { className: "ps-cpw-silhouette", children: [
8724
- !isWomen && /* @__PURE__ */ jsxs(
8725
- ShapeSection,
8953
+ ] }),
8954
+ error && /* @__PURE__ */ jsx("div", { className: "ps-cpw-error", children: error })
8955
+ ] }, "manual-identity"),
8956
+ mode === "manual" && manualStep === "chest" && !isWomen && /* @__PURE__ */ jsxs(
8957
+ ProgressiveStep,
8726
8958
  {
8959
+ stepKey: "chest",
8727
8960
  title: t("CHEST PROFILE"),
8728
8961
  subtitle: t("Select the profile that best matches your chest breadth"),
8729
8962
  children: [
8730
- /* @__PURE__ */ jsx(ShapeCard, { img: imgs.chest?.narrow ?? null, label: t("NARROW"), selected: chestProfile === "narrow", onSelect: () => setChestProfile("narrow") }),
8731
- /* @__PURE__ */ jsx(ShapeCard, { img: imgs.chest?.average ?? null, label: t("AVERAGE"), selected: chestProfile === "average", onSelect: () => setChestProfile("average") }),
8732
- /* @__PURE__ */ jsx(ShapeCard, { img: imgs.chest?.broad ?? null, label: t("BROAD"), selected: chestProfile === "broad", onSelect: () => setChestProfile("broad") })
8963
+ /* @__PURE__ */ jsx(ShapeCard, { img: imgs.chest?.narrow ?? null, label: t("NARROW"), selected: chestProfile === "narrow", onSelect: () => {
8964
+ setChestProfile("narrow");
8965
+ setError("");
8966
+ } }),
8967
+ /* @__PURE__ */ jsx(ShapeCard, { img: imgs.chest?.average ?? null, label: t("AVERAGE"), selected: chestProfile === "average", onSelect: () => {
8968
+ setChestProfile("average");
8969
+ setError("");
8970
+ } }),
8971
+ /* @__PURE__ */ jsx(ShapeCard, { img: imgs.chest?.broad ?? null, label: t("BROAD"), selected: chestProfile === "broad", onSelect: () => {
8972
+ setChestProfile("broad");
8973
+ setError("");
8974
+ } })
8733
8975
  ]
8734
8976
  }
8735
8977
  ),
8736
- /* @__PURE__ */ jsxs(
8737
- ShapeSection,
8978
+ mode === "manual" && manualStep === "stomach" && /* @__PURE__ */ jsxs(
8979
+ ProgressiveStep,
8738
8980
  {
8981
+ stepKey: "stomach",
8739
8982
  title: t("STOMACH PROFILE"),
8740
8983
  subtitle: t("Describe your mid-section silhouette"),
8741
8984
  children: [
8742
- /* @__PURE__ */ jsx(ShapeCard, { img: imgs.stomach?.flat ?? null, label: t("FLAT"), selected: midsectionProfile === "flat", onSelect: () => setMidsectionProfile("flat") }),
8743
- /* @__PURE__ */ jsx(ShapeCard, { img: imgs.stomach?.average ?? null, label: t("AVERAGE"), selected: midsectionProfile === "average", onSelect: () => setMidsectionProfile("average") }),
8744
- /* @__PURE__ */ jsx(ShapeCard, { img: imgs.stomach?.round ?? null, label: t("ROUND"), selected: midsectionProfile === "round", onSelect: () => setMidsectionProfile("round") })
8985
+ /* @__PURE__ */ jsx(ShapeCard, { img: imgs.stomach?.flat ?? null, label: t("FLAT"), selected: midsectionProfile === "flat", onSelect: () => {
8986
+ setMidsectionProfile("flat");
8987
+ setError("");
8988
+ } }),
8989
+ /* @__PURE__ */ jsx(ShapeCard, { img: imgs.stomach?.average ?? null, label: t("AVERAGE"), selected: midsectionProfile === "average", onSelect: () => {
8990
+ setMidsectionProfile("average");
8991
+ setError("");
8992
+ } }),
8993
+ /* @__PURE__ */ jsx(ShapeCard, { img: imgs.stomach?.round ?? null, label: t("ROUND"), selected: midsectionProfile === "round", onSelect: () => {
8994
+ setMidsectionProfile("round");
8995
+ setError("");
8996
+ } })
8745
8997
  ]
8746
8998
  }
8747
8999
  ),
8748
- /* @__PURE__ */ jsxs(
8749
- ShapeSection,
9000
+ mode === "manual" && manualStep === "seat" && /* @__PURE__ */ jsxs(
9001
+ ProgressiveStep,
8750
9002
  {
9003
+ stepKey: "seat",
8751
9004
  title: t("BACK & SEAT"),
8752
9005
  subtitle: t("The curvature of your lower spine and seat profile"),
8753
9006
  children: [
8754
- /* @__PURE__ */ jsx(ShapeCard, { img: imgs.seat?.narrow ?? null, label: t("STRAIGHT"), selected: seatProfile === "narrow", onSelect: () => setSeatProfile("narrow") }),
8755
- /* @__PURE__ */ jsx(ShapeCard, { img: imgs.seat?.average ?? null, label: t("CURVED"), selected: seatProfile === "average", onSelect: () => setSeatProfile("average") }),
8756
- /* @__PURE__ */ jsx(ShapeCard, { img: imgs.seat?.full ?? null, label: t("DEEP"), selected: seatProfile === "full", onSelect: () => setSeatProfile("full") })
9007
+ /* @__PURE__ */ jsx(ShapeCard, { img: imgs.seat?.narrow ?? null, label: t("STRAIGHT"), selected: seatProfile === "narrow", onSelect: () => {
9008
+ setSeatProfile("narrow");
9009
+ setError("");
9010
+ } }),
9011
+ /* @__PURE__ */ jsx(ShapeCard, { img: imgs.seat?.average ?? null, label: t("CURVED"), selected: seatProfile === "average", onSelect: () => {
9012
+ setSeatProfile("average");
9013
+ setError("");
9014
+ } }),
9015
+ /* @__PURE__ */ jsx(ShapeCard, { img: imgs.seat?.full ?? null, label: t("DEEP"), selected: seatProfile === "full", onSelect: () => {
9016
+ setSeatProfile("full");
9017
+ setError("");
9018
+ } })
8757
9019
  ]
8758
9020
  }
8759
9021
  ),
8760
- isWomen && imgs.hips && /* @__PURE__ */ jsxs(
8761
- ShapeSection,
9022
+ mode === "manual" && manualStep === "hips" && isWomen && imgs.hips && /* @__PURE__ */ jsxs(
9023
+ ProgressiveStep,
8762
9024
  {
9025
+ stepKey: "hips",
8763
9026
  title: t("HIP PROFILE"),
8764
9027
  subtitle: t("The curvature of your hips and thighs"),
8765
9028
  children: [
8766
- /* @__PURE__ */ jsx(ShapeCard, { img: imgs.hips.narrow ?? null, label: t("NARROW"), selected: hipProfile === "narrow", onSelect: () => setHipProfile("narrow") }),
8767
- /* @__PURE__ */ jsx(ShapeCard, { img: imgs.hips.average ?? null, label: t("AVERAGE"), selected: hipProfile === "average", onSelect: () => setHipProfile("average") }),
8768
- /* @__PURE__ */ jsx(ShapeCard, { img: imgs.hips.full ?? null, label: t("FULL"), selected: hipProfile === "full", onSelect: () => setHipProfile("full") })
9029
+ /* @__PURE__ */ jsx(ShapeCard, { img: imgs.hips.narrow ?? null, label: t("NARROW"), selected: hipProfile === "narrow", onSelect: () => {
9030
+ setHipProfile("narrow");
9031
+ setError("");
9032
+ } }),
9033
+ /* @__PURE__ */ jsx(ShapeCard, { img: imgs.hips.average ?? null, label: t("AVERAGE"), selected: hipProfile === "average", onSelect: () => {
9034
+ setHipProfile("average");
9035
+ setError("");
9036
+ } }),
9037
+ /* @__PURE__ */ jsx(ShapeCard, { img: imgs.hips.full ?? null, label: t("FULL"), selected: hipProfile === "full", onSelect: () => {
9038
+ setHipProfile("full");
9039
+ setError("");
9040
+ } })
8769
9041
  ]
8770
9042
  }
8771
9043
  ),
8772
- isWomen && /* @__PURE__ */ jsxs("div", { className: "ps-cpw-section", children: [
9044
+ mode === "manual" && manualStep === "bra" && isWomen && /* @__PURE__ */ jsxs("div", { className: "ps-cpw-progressive ps-cpw-fade-in", children: [
8773
9045
  /* @__PURE__ */ jsxs("div", { className: "ps-cpw-section-head", children: [
8774
9046
  /* @__PURE__ */ jsx("div", { className: "ps-cpw-section-title", children: t("BRA SIZE") }),
8775
9047
  /* @__PURE__ */ jsx("div", { className: "ps-cpw-section-sub", children: t("Helps us refine bust measurements for tops and dresses") })
@@ -8782,7 +9054,10 @@ function CreateProfileWizard({ onSave, onCancel, t }) {
8782
9054
  {
8783
9055
  className: "ps-cpw-input",
8784
9056
  value: bandSize ?? "",
8785
- onChange: (e) => setBandSize(e.target.value || null),
9057
+ onChange: (e) => {
9058
+ setBandSize(e.target.value || null);
9059
+ setError("");
9060
+ },
8786
9061
  children: [
8787
9062
  /* @__PURE__ */ jsx("option", { value: "", children: t("Select") }),
8788
9063
  BAND_OPTIONS_US.map((b) => /* @__PURE__ */ jsx("option", { value: b, children: b }, b))
@@ -8797,7 +9072,10 @@ function CreateProfileWizard({ onSave, onCancel, t }) {
8797
9072
  {
8798
9073
  className: "ps-cpw-input",
8799
9074
  value: cupSize ?? "",
8800
- onChange: (e) => setCupSize(e.target.value || null),
9075
+ onChange: (e) => {
9076
+ setCupSize(e.target.value || null);
9077
+ setError("");
9078
+ },
8801
9079
  children: [
8802
9080
  /* @__PURE__ */ jsx("option", { value: "", children: t("Select") }),
8803
9081
  CUP_OPTIONS_US.map((c) => /* @__PURE__ */ jsx("option", { value: c, children: c }, c))
@@ -8806,11 +9084,92 @@ function CreateProfileWizard({ onSave, onCancel, t }) {
8806
9084
  )
8807
9085
  ] })
8808
9086
  ] })
8809
- ] })
8810
- ] }) }),
9087
+ ] }, "bra"),
9088
+ mode === "manual" && error && /* @__PURE__ */ jsx("div", { className: "ps-cpw-error", children: error }),
9089
+ mode === "image" && imageStep === "name" && /* @__PURE__ */ jsxs("div", { className: "ps-cpw-identity ps-cpw-fade-in", children: [
9090
+ /* @__PURE__ */ jsx("div", { className: "ps-cpw-pill-row", children: /* @__PURE__ */ jsxs("div", { className: "ps-cpw-pill-group", children: [
9091
+ /* @__PURE__ */ jsx("button", { type: "button", className: `ps-cpw-pill${gender === "male" ? " ps-active" : ""}`, onClick: () => setGender("male"), children: t("Male") }),
9092
+ /* @__PURE__ */ jsx("button", { type: "button", className: `ps-cpw-pill${gender === "female" ? " ps-active" : ""}`, onClick: () => setGender("female"), children: t("Female") })
9093
+ ] }) }),
9094
+ /* @__PURE__ */ jsxs("div", { className: "ps-cpw-field", children: [
9095
+ /* @__PURE__ */ jsx("label", { className: "ps-cpw-field-label", children: t("PROFILE NAME") }),
9096
+ /* @__PURE__ */ jsx(
9097
+ "input",
9098
+ {
9099
+ type: "text",
9100
+ className: "ps-cpw-input",
9101
+ value: name,
9102
+ placeholder: t("e.g. My Photo Profile"),
9103
+ onChange: (e) => {
9104
+ setName(e.target.value);
9105
+ setError("");
9106
+ }
9107
+ }
9108
+ )
9109
+ ] }),
9110
+ /* @__PURE__ */ jsx("p", { className: "ps-cpw-hint", children: t("Next, upload a full-body photo. Our AI will analyze it and compute every measurement (chest, waist, hips, sleeve, inseam, etc.) automatically.") }),
9111
+ error && /* @__PURE__ */ jsx("div", { className: "ps-cpw-error", children: error })
9112
+ ] }, "image-name"),
9113
+ mode === "image" && imageStep === "photo" && /* @__PURE__ */ jsxs("div", { className: "ps-cpw-photo-step ps-cpw-fade-in", children: [
9114
+ /* @__PURE__ */ jsx("h3", { className: "ps-cpw-photo-step-title", children: t("Upload your photo") }),
9115
+ /* @__PURE__ */ jsx("p", { className: "ps-cpw-photo-step-sub", children: t("Stand straight, full body in frame, neutral lighting. Form-fitting clothes give the most accurate result.") }),
9116
+ /* @__PURE__ */ jsx(
9117
+ "input",
9118
+ {
9119
+ ref: photoInputRef,
9120
+ type: "file",
9121
+ accept: "image/jpeg,image/png,image/webp",
9122
+ style: { display: "none" },
9123
+ onChange: handlePhotoSelect
9124
+ }
9125
+ ),
9126
+ photoBase64 ? /* @__PURE__ */ jsxs("div", { className: "ps-cpw-photo-frame", children: [
9127
+ /* @__PURE__ */ jsx("img", { src: photoBase64, alt: t("Profile photo"), className: "ps-cpw-photo-frame-img" }),
9128
+ /* @__PURE__ */ jsx(
9129
+ "button",
9130
+ {
9131
+ type: "button",
9132
+ className: "ps-cpw-photo-remove",
9133
+ onClick: handleRemovePhoto,
9134
+ "aria-label": t("Remove photo"),
9135
+ children: "×"
9136
+ }
9137
+ )
9138
+ ] }) : /* @__PURE__ */ jsxs(
9139
+ "button",
9140
+ {
9141
+ type: "button",
9142
+ className: "ps-cpw-photo-dropzone",
9143
+ onClick: () => photoInputRef.current?.click(),
9144
+ disabled: photoUploading,
9145
+ children: [
9146
+ /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", width: "48", height: "48", children: [
9147
+ /* @__PURE__ */ jsx("path", { d: "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" }),
9148
+ /* @__PURE__ */ jsx("polyline", { points: "17 8 12 3 7 8" }),
9149
+ /* @__PURE__ */ jsx("line", { x1: "12", y1: "3", x2: "12", y2: "15" })
9150
+ ] }),
9151
+ /* @__PURE__ */ jsx("span", { className: "ps-cpw-photo-dropzone-title", children: photoUploading ? t("Processing...") : t("Tap to upload a photo") }),
9152
+ /* @__PURE__ */ jsx("span", { className: "ps-cpw-photo-dropzone-hint", children: t("JPEG, PNG up to 10MB") })
9153
+ ]
9154
+ }
9155
+ ),
9156
+ photoBase64 && /* @__PURE__ */ jsx(
9157
+ "button",
9158
+ {
9159
+ type: "button",
9160
+ className: "ps-cpw-photo-retake",
9161
+ onClick: () => photoInputRef.current?.click(),
9162
+ disabled: photoUploading,
9163
+ children: t("RETAKE PHOTO")
9164
+ }
9165
+ ),
9166
+ error && /* @__PURE__ */ jsx("div", { className: "ps-cpw-error", children: error })
9167
+ ] }, "image-photo")
9168
+ ] }),
8811
9169
  /* @__PURE__ */ jsxs("div", { className: "ps-cpw-footer", children: [
8812
- /* @__PURE__ */ jsx("button", { type: "button", className: "ps-cpw-back-btn", onClick: handleBack, children: step === 1 ? t("Cancel") : `← ${t("Back to Identity")}` }),
8813
- /* @__PURE__ */ jsx("button", { type: "button", className: "ps-cpw-next-btn", onClick: handleContinue, children: step === 1 ? t("Continue") : t("CALCULATE MY FIT") })
9170
+ /* @__PURE__ */ jsx("button", { type: "button", className: "ps-cpw-back-btn", onClick: handleBack, children: mode == null ? t("Cancel") : `← ${t("Back")}` }),
9171
+ mode === "manual" && /* @__PURE__ */ jsx("button", { type: "button", className: "ps-cpw-next-btn", onClick: advanceManual, children: isLastManualStep ? t("CALCULATE MY FIT") : t("Continue") }),
9172
+ mode === "image" && /* @__PURE__ */ jsx("button", { type: "button", className: "ps-cpw-next-btn", onClick: advanceImage, disabled: imageStep === "photo" && !photoBase64, children: imageStep === "name" ? t("Continue") : t("ANALYZE BY IMAGE") })
8814
9173
  ] })
8815
9174
  ] });
8816
9175
  }
@@ -11116,18 +11475,23 @@ function PrimeStyleTryonInner({
11116
11475
  setBodyLandmarks(null);
11117
11476
  detectMeasurementLines(objUrl).then((lines) => {
11118
11477
  modelPoseRef.current = lines;
11119
- }).catch(() => {
11120
- });
11121
- detectBodyLandmarks(objUrl).then((lm) => {
11478
+ return lines;
11479
+ }).catch(() => null);
11480
+ const landmarksPromise = detectBodyLandmarks(objUrl).then((lm) => {
11122
11481
  setBodyLandmarks(lm);
11123
- }).catch(() => {
11124
- });
11482
+ return lm;
11483
+ }).catch(() => null);
11484
+ const landmarks = await landmarksPromise;
11125
11485
  const payload = {
11126
11486
  method: "photo",
11127
11487
  locale: sizingCountry,
11128
11488
  sizingUnit,
11129
11489
  product: { title: productTitle, description: "", variants: [] },
11130
11490
  bodyImage: data.photoBase64,
11491
+ // BlazePose landmarks (normalized 0–1 coordinates). The backend uses
11492
+ // these to compute exact pixel distances and feed them to Gemini as
11493
+ // anchors instead of asking it to estimate visually.
11494
+ bodyLandmarks: landmarks || void 0,
11131
11495
  measurements: {
11132
11496
  gender: data.gender,
11133
11497
  height: data.height,