@primestyleai/tryon 3.14.0 → 3.16.0
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.
|
@@ -302,6 +302,11 @@ const en = {
|
|
|
302
302
|
"Equivalent Sizes": "Equivalent Sizes",
|
|
303
303
|
"Analyzing your size...": "Analyzing your size...",
|
|
304
304
|
"Your size:": "Your size:",
|
|
305
|
+
"Size Chart": "Size Chart",
|
|
306
|
+
"tap to compare": "tap to compare",
|
|
307
|
+
"Comparing size": "Comparing size",
|
|
308
|
+
"Fit Analysis": "Fit Analysis",
|
|
309
|
+
"Show more": "Show more",
|
|
305
310
|
"Done": "Done",
|
|
306
311
|
// ── Try-on result ───────────────────────────────────
|
|
307
312
|
"Try-on result": "Try-on result",
|
package/dist/primestyle-tryon.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { c as createT, A as ApiClient, S as SseClient, i as isValidImageFile, a as compressImage } from "./index-
|
|
2
|
-
import { P, b, T, d, r } from "./index-
|
|
1
|
+
import { c as createT, A as ApiClient, S as SseClient, i as isValidImageFile, a as compressImage } from "./index-DvAzTRFF.js";
|
|
2
|
+
import { P, b, T, d, r } from "./index-DvAzTRFF.js";
|
|
3
3
|
function detectProductImage() {
|
|
4
4
|
const ogImage = document.querySelector(
|
|
5
5
|
'meta[property="og:image"]'
|
package/dist/react/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx, jsxs, Fragment } from "react/jsx-runtime";
|
|
3
3
|
import { useState, useEffect, useMemo, useRef, useCallback } from "react";
|
|
4
|
-
import { c as createT, A as ApiClient, S as SseClient, i as isValidImageFile, a as compressImage, P as PrimeStyleError, L as LOCALE_LABELS, b as SUPPORTED_LOCALES } from "../index-
|
|
4
|
+
import { c as createT, A as ApiClient, S as SseClient, i as isValidImageFile, a as compressImage, P as PrimeStyleError, L as LOCALE_LABELS, b as SUPPORTED_LOCALES } from "../index-DvAzTRFF.js";
|
|
5
5
|
const HEADER_ALIASES = {
|
|
6
6
|
// ── Size label columns (skipped during field derivation) ──
|
|
7
7
|
size: "__size__",
|
|
@@ -406,20 +406,6 @@ const FALLBACK_FIELDS_MALE = [
|
|
|
406
406
|
{ key: "inseam", label: "Inseam", required: false, unit: "cm", placeholder: "e.g. 81", category: "body" },
|
|
407
407
|
{ key: "footLengthCm", label: "Foot length", required: false, unit: "cm", placeholder: "e.g. 27", category: "shoe" }
|
|
408
408
|
];
|
|
409
|
-
const SIZING_COUNTRIES = [
|
|
410
|
-
{ code: "US", label: "United States" },
|
|
411
|
-
{ code: "UK", label: "United Kingdom" },
|
|
412
|
-
{ code: "EU", label: "Europe (EU)" },
|
|
413
|
-
{ code: "FR", label: "France" },
|
|
414
|
-
{ code: "IT", label: "Italy" },
|
|
415
|
-
{ code: "DE", label: "Germany" },
|
|
416
|
-
{ code: "ES", label: "Spain" },
|
|
417
|
-
{ code: "JP", label: "Japan" },
|
|
418
|
-
{ code: "CN", label: "China" },
|
|
419
|
-
{ code: "KR", label: "South Korea" },
|
|
420
|
-
{ code: "AU", label: "Australia" },
|
|
421
|
-
{ code: "BR", label: "Brazil" }
|
|
422
|
-
];
|
|
423
409
|
const STEP_LABELS = ["", "Welcome", "Size", "Your Fit", "Try On"];
|
|
424
410
|
const TOTAL_STEPS = 4;
|
|
425
411
|
function detectLocale() {
|
|
@@ -438,6 +424,9 @@ function detectLocale() {
|
|
|
438
424
|
function isImperial(locale) {
|
|
439
425
|
return locale === "US" || locale === "UK";
|
|
440
426
|
}
|
|
427
|
+
function cmToIn(cm) {
|
|
428
|
+
return +(cm / 2.54).toFixed(1);
|
|
429
|
+
}
|
|
441
430
|
function inToCm(inches) {
|
|
442
431
|
return +(inches * 2.54).toFixed(1);
|
|
443
432
|
}
|
|
@@ -837,7 +826,107 @@ function PrimeStyleTryonInner({
|
|
|
837
826
|
}
|
|
838
827
|
return formGender === "female" ? FALLBACK_FIELDS_FEMALE : FALLBACK_FIELDS_MALE;
|
|
839
828
|
}, [sizeGuide, formGender]);
|
|
829
|
+
const computeSizingLocally = useCallback(() => {
|
|
830
|
+
if (sizingMethod !== "exact" || !sizeGuide?.found || !sizeGuide.headers || !sizeGuide.rows) return null;
|
|
831
|
+
const HEADER_MAP = {
|
|
832
|
+
chest: "chest",
|
|
833
|
+
bust: "bust",
|
|
834
|
+
waist: "waist",
|
|
835
|
+
hips: "hips",
|
|
836
|
+
hip: "hips",
|
|
837
|
+
shoulder: "shoulderWidth",
|
|
838
|
+
shoulders: "shoulderWidth",
|
|
839
|
+
"shoulder width": "shoulderWidth",
|
|
840
|
+
sleeve: "sleeveLength",
|
|
841
|
+
"sleeve length": "sleeveLength",
|
|
842
|
+
inseam: "inseam",
|
|
843
|
+
neck: "neckCircumference",
|
|
844
|
+
foot: "footLengthCm",
|
|
845
|
+
"foot length": "footLengthCm"
|
|
846
|
+
};
|
|
847
|
+
const INTL = /* @__PURE__ */ new Set(["eu", "us", "uk", "it", "fr", "de", "jp", "cn", "kr", "au", "br", "eur"]);
|
|
848
|
+
const userMeas = {};
|
|
849
|
+
for (const f of dynamicFields) {
|
|
850
|
+
if (f.unit === "size" || ["shoeEU", "shoeUS", "shoeUK"].includes(f.key)) continue;
|
|
851
|
+
const raw = formRef.current[f.key];
|
|
852
|
+
if (!raw) continue;
|
|
853
|
+
const v = parseFloat(raw);
|
|
854
|
+
if (isNaN(v)) continue;
|
|
855
|
+
userMeas[f.key] = sizingUnit === "in" ? inToCm(v) : v;
|
|
856
|
+
}
|
|
857
|
+
for (const k of ["chest", "bust", "waist", "hips", "shoulderWidth", "sleeveLength", "inseam", "neckCircumference", "footLengthCm"]) {
|
|
858
|
+
if (userMeas[k] || !formRef.current[k]) continue;
|
|
859
|
+
const v = parseFloat(formRef.current[k]);
|
|
860
|
+
if (!isNaN(v)) userMeas[k] = sizingUnit === "in" ? inToCm(v) : v;
|
|
861
|
+
}
|
|
862
|
+
if (Object.keys(userMeas).length === 0) return null;
|
|
863
|
+
const sizeColIdx = sizeGuide.headers.findIndex((h) => /^size$/i.test(h.trim()));
|
|
864
|
+
const idx = sizeColIdx >= 0 ? sizeColIdx : 0;
|
|
865
|
+
const colMap = [];
|
|
866
|
+
const intlCols = [];
|
|
867
|
+
sizeGuide.headers.forEach((h, i) => {
|
|
868
|
+
if (i === idx) return;
|
|
869
|
+
const lower = h.toLowerCase().trim().replace(/\s*\(.*\)/, "");
|
|
870
|
+
const clean = lower.replace(/\s*size\s*/gi, "").trim();
|
|
871
|
+
if (INTL.has(clean)) {
|
|
872
|
+
intlCols.push({ hi: i, code: clean.toUpperCase() });
|
|
873
|
+
return;
|
|
874
|
+
}
|
|
875
|
+
const fk = HEADER_MAP[clean];
|
|
876
|
+
if (fk && userMeas[fk] !== void 0) colMap.push({ hi: i, formKey: fk, label: h.trim() });
|
|
877
|
+
});
|
|
878
|
+
if (colMap.length === 0) return null;
|
|
879
|
+
const parseRange = (cell) => {
|
|
880
|
+
const nums = cell.replace(/[^\d.\-–]/g, " ").trim().split(/[\s\-–]+/).filter(Boolean).map(Number).filter((n) => !isNaN(n));
|
|
881
|
+
if (nums.length === 0) return null;
|
|
882
|
+
return { min: Math.min(...nums), max: Math.max(...nums) };
|
|
883
|
+
};
|
|
884
|
+
const scores = [];
|
|
885
|
+
for (const row of sizeGuide.rows) {
|
|
886
|
+
const label = row[idx] || "";
|
|
887
|
+
let fitting = 0;
|
|
888
|
+
let total = 0;
|
|
889
|
+
let dist = 0;
|
|
890
|
+
const details = [];
|
|
891
|
+
for (const col of colMap) {
|
|
892
|
+
const range = parseRange(row[col.hi] || "");
|
|
893
|
+
if (!range) continue;
|
|
894
|
+
total++;
|
|
895
|
+
const uv = userMeas[col.formKey];
|
|
896
|
+
const fit = uv >= range.min && uv <= range.max ? "good" : uv < range.min ? "tight" : "loose";
|
|
897
|
+
if (fit === "good") fitting++;
|
|
898
|
+
dist += Math.abs(uv - (range.min + range.max) / 2);
|
|
899
|
+
const dispVal = sizingUnit === "in" ? `${cmToIn(uv)} in` : `${Math.round(uv)} cm`;
|
|
900
|
+
const dispRange = sizingUnit === "in" ? `${cmToIn(range.min)}–${cmToIn(range.max)} in` : `${Math.round(range.min)}–${Math.round(range.max)} cm`;
|
|
901
|
+
details.push({ measurement: col.label, userValue: dispVal, chartRange: dispRange, fit });
|
|
902
|
+
}
|
|
903
|
+
if (total === 0) continue;
|
|
904
|
+
const intl = {};
|
|
905
|
+
for (const ic of intlCols) {
|
|
906
|
+
if (row[ic.hi]) intl[ic.code] = row[ic.hi];
|
|
907
|
+
}
|
|
908
|
+
scores.push({ label, fitting, total, dist, details, intl, row });
|
|
909
|
+
}
|
|
910
|
+
if (scores.length === 0) return null;
|
|
911
|
+
scores.sort((a, b) => b.fitting - a.fitting || a.dist - b.dist);
|
|
912
|
+
const best = scores[0];
|
|
913
|
+
const conf = best.fitting === best.total ? "high" : best.fitting >= best.total * 0.6 ? "medium" : "low";
|
|
914
|
+
return {
|
|
915
|
+
recommendedSize: best.label,
|
|
916
|
+
confidence: conf,
|
|
917
|
+
reasoning: `Based on your measurements, size ${best.label} is the best fit.`,
|
|
918
|
+
internationalSizes: best.intl,
|
|
919
|
+
matchDetails: best.details,
|
|
920
|
+
method: "deterministic"
|
|
921
|
+
};
|
|
922
|
+
}, [sizingMethod, sizeGuide, dynamicFields, sizingUnit]);
|
|
840
923
|
const submitSizing = useCallback(async () => {
|
|
924
|
+
const localResult = computeSizingLocally();
|
|
925
|
+
if (localResult) {
|
|
926
|
+
setSizingResult(localResult);
|
|
927
|
+
setSizingLoading(false);
|
|
928
|
+
return;
|
|
929
|
+
}
|
|
841
930
|
if (!apiRef.current) return;
|
|
842
931
|
const baseUrl = getApiUrl(apiUrl);
|
|
843
932
|
const key = getApiKey();
|
|
@@ -896,7 +985,7 @@ function PrimeStyleTryonInner({
|
|
|
896
985
|
} finally {
|
|
897
986
|
setSizingLoading(false);
|
|
898
987
|
}
|
|
899
|
-
}, [apiUrl, sizingMethod, sizingCountry, heightUnit, weightUnit, sizingUnit, sizeGuide, productTitle, dynamicFields]);
|
|
988
|
+
}, [apiUrl, sizingMethod, sizingCountry, heightUnit, weightUnit, sizingUnit, sizeGuide, productTitle, dynamicFields, computeSizingLocally]);
|
|
900
989
|
const handleTryOnSubmit = useCallback(async () => {
|
|
901
990
|
if (!selectedFile || !apiRef.current || !sseRef.current) {
|
|
902
991
|
const msg = !apiRef.current ? t("SDK not configured. Please provide an API key.") : t("Something went wrong");
|
|
@@ -1336,10 +1425,6 @@ function PrimeStyleTryonInner({
|
|
|
1336
1425
|
")"
|
|
1337
1426
|
] }, p.id))
|
|
1338
1427
|
] }) }),
|
|
1339
|
-
/* @__PURE__ */ jsxs("div", { className: "ps-tryon-input-row", children: [
|
|
1340
|
-
/* @__PURE__ */ jsx("label", { children: t("Sizing region") }),
|
|
1341
|
-
/* @__PURE__ */ jsx("select", { className: "ps-tryon-country-select", value: sizingCountry, onChange: (e) => setSizingCountry(e.target.value), children: SIZING_COUNTRIES.map((c) => /* @__PURE__ */ jsx("option", { value: c.code, children: t(c.label) }, c.code)) })
|
|
1342
|
-
] }),
|
|
1343
1428
|
sizingMethod === "exact" && /* @__PURE__ */ jsxs("div", { className: "ps-tryon-unit-tabs", children: [
|
|
1344
1429
|
/* @__PURE__ */ jsx("button", { className: `ps-tryon-unit-tab${isCm ? " ps-active" : ""}`, onClick: () => {
|
|
1345
1430
|
setSizingUnit("cm");
|
|
@@ -1489,63 +1574,208 @@ function PrimeStyleTryonInner({
|
|
|
1489
1574
|
] }, `form-${formGender}-${sizingUnit}-${heightUnit}-${sizingCountry}-${formKey}`);
|
|
1490
1575
|
}
|
|
1491
1576
|
function SizeResultView() {
|
|
1492
|
-
const [
|
|
1493
|
-
const
|
|
1494
|
-
|
|
1495
|
-
|
|
1577
|
+
const [activeSize, setActiveSize] = useState(sizingResult?.recommendedSize || "");
|
|
1578
|
+
const [editedValues, setEditedValues] = useState({});
|
|
1579
|
+
const isCmResult = sizingUnit === "cm";
|
|
1580
|
+
const chartData = useMemo(() => {
|
|
1581
|
+
if (!sizeGuide?.found || !sizeGuide.headers || !sizeGuide.rows) return null;
|
|
1582
|
+
const INTL = /* @__PURE__ */ new Set(["eu", "us", "uk", "it", "fr", "de", "jp", "cn", "kr", "au", "br", "eur"]);
|
|
1583
|
+
const MEAS_MAP = {
|
|
1584
|
+
chest: "chest",
|
|
1585
|
+
bust: "bust",
|
|
1586
|
+
waist: "waist",
|
|
1587
|
+
hips: "hips",
|
|
1588
|
+
hip: "hips",
|
|
1589
|
+
shoulder: "shoulderWidth",
|
|
1590
|
+
shoulders: "shoulderWidth",
|
|
1591
|
+
"shoulder width": "shoulderWidth",
|
|
1592
|
+
sleeve: "sleeveLength",
|
|
1593
|
+
"sleeve length": "sleeveLength",
|
|
1594
|
+
inseam: "inseam",
|
|
1595
|
+
neck: "neckCircumference",
|
|
1596
|
+
"neck circumference": "neckCircumference",
|
|
1597
|
+
foot: "footLengthCm",
|
|
1598
|
+
"foot length": "footLengthCm"
|
|
1599
|
+
};
|
|
1600
|
+
const sizeColIdx = sizeGuide.headers.findIndex((h) => /^size$/i.test(h.trim()));
|
|
1601
|
+
const idx = sizeColIdx >= 0 ? sizeColIdx : 0;
|
|
1602
|
+
const measCols = [];
|
|
1603
|
+
const intlCols = [];
|
|
1604
|
+
sizeGuide.headers.forEach((h, i) => {
|
|
1605
|
+
if (i === idx) return;
|
|
1606
|
+
const lower = h.toLowerCase().trim().replace(/\s*\(.*\)/, "");
|
|
1607
|
+
const clean = lower.replace(/\s*size\s*/gi, "").trim();
|
|
1608
|
+
if (INTL.has(clean)) {
|
|
1609
|
+
intlCols.push({ headerIdx: i, code: clean.toUpperCase() });
|
|
1610
|
+
} else if (MEAS_MAP[clean]) {
|
|
1611
|
+
measCols.push({ headerIdx: i, label: h.trim(), formKey: MEAS_MAP[clean] });
|
|
1612
|
+
} else if (lower !== "size") {
|
|
1613
|
+
measCols.push({ headerIdx: i, label: h.trim(), formKey: lower.replace(/\s+/g, "") });
|
|
1614
|
+
}
|
|
1615
|
+
});
|
|
1616
|
+
const sizes = sizeGuide.rows.map((row) => {
|
|
1617
|
+
const label = row[idx] || "";
|
|
1618
|
+
const measurements = {};
|
|
1619
|
+
for (const col of measCols) {
|
|
1620
|
+
const cell = row[col.headerIdx] || "";
|
|
1621
|
+
const nums = cell.replace(/[^\d.\-–]/g, " ").trim().split(/[\s\-–]+/).filter(Boolean).map(Number).filter((n) => !isNaN(n));
|
|
1622
|
+
if (nums.length > 0) {
|
|
1623
|
+
measurements[col.formKey] = { raw: cell, min: Math.min(...nums), max: Math.max(...nums) };
|
|
1624
|
+
}
|
|
1625
|
+
}
|
|
1626
|
+
const intl = {};
|
|
1627
|
+
for (const col of intlCols) {
|
|
1628
|
+
if (row[col.headerIdx]) intl[col.code] = row[col.headerIdx];
|
|
1629
|
+
}
|
|
1630
|
+
return { label, measurements, intl };
|
|
1631
|
+
});
|
|
1632
|
+
return { sizes, measCols, intlCols };
|
|
1633
|
+
}, [sizeGuide]);
|
|
1634
|
+
const getUserVal = useCallback((formKey2) => {
|
|
1635
|
+
const edited = editedValues[formKey2];
|
|
1636
|
+
if (edited !== void 0 && edited !== "") {
|
|
1637
|
+
const v2 = parseFloat(edited);
|
|
1638
|
+
return isNaN(v2) ? null : isCmResult ? v2 : inToCm(v2);
|
|
1639
|
+
}
|
|
1640
|
+
const raw = formRef.current[formKey2];
|
|
1641
|
+
if (!raw) return null;
|
|
1642
|
+
const v = parseFloat(raw);
|
|
1643
|
+
return isNaN(v) ? null : isCmResult ? v : inToCm(v);
|
|
1644
|
+
}, [editedValues, isCmResult]);
|
|
1645
|
+
const activeFit = useMemo(() => {
|
|
1646
|
+
if (!chartData) return null;
|
|
1647
|
+
const sizeRow = chartData.sizes.find((s) => s.label === activeSize);
|
|
1648
|
+
if (!sizeRow) return null;
|
|
1649
|
+
const details = [];
|
|
1650
|
+
for (const col of chartData.measCols) {
|
|
1651
|
+
const range = sizeRow.measurements[col.formKey];
|
|
1652
|
+
if (!range) continue;
|
|
1653
|
+
const userVal = getUserVal(col.formKey);
|
|
1654
|
+
if (userVal === null) continue;
|
|
1655
|
+
const fit = userVal >= range.min && userVal <= range.max ? "good" : userVal < range.min ? "tight" : "loose";
|
|
1656
|
+
details.push({ label: col.label, formKey: col.formKey, userVal, chartMin: range.min, chartMax: range.max, chartRaw: range.raw, fit });
|
|
1657
|
+
}
|
|
1658
|
+
return details;
|
|
1659
|
+
}, [chartData, activeSize, getUserVal]);
|
|
1660
|
+
const activeIntl = useMemo(() => {
|
|
1661
|
+
if (!chartData) return sizingResult?.internationalSizes || {};
|
|
1662
|
+
const sizeRow = chartData.sizes.find((s) => s.label === activeSize);
|
|
1663
|
+
return sizeRow?.intl || sizingResult?.internationalSizes || {};
|
|
1664
|
+
}, [chartData, activeSize, sizingResult]);
|
|
1665
|
+
const fmtRange = (min, max) => {
|
|
1666
|
+
if (isCmResult) return min === max ? `${Math.round(min)}` : `${Math.round(min)}–${Math.round(max)}`;
|
|
1667
|
+
return min === max ? `${cmToIn(min)}` : `${cmToIn(min)}–${cmToIn(max)}`;
|
|
1668
|
+
};
|
|
1669
|
+
const unitLabel = isCmResult ? t("cm") : t("in");
|
|
1670
|
+
const isRecommended = activeSize === sizingResult?.recommendedSize;
|
|
1671
|
+
return /* @__PURE__ */ jsxs("div", { className: "ps-tryon-sr", children: [
|
|
1672
|
+
sizingLoading && !sizingResult && /* @__PURE__ */ jsxs("div", { className: "ps-tryon-sr-loading", children: [
|
|
1496
1673
|
/* @__PURE__ */ jsx("div", { className: "ps-tryon-size-loading-spinner" }),
|
|
1497
|
-
/* @__PURE__ */ jsx("p", {
|
|
1674
|
+
/* @__PURE__ */ jsx("p", { children: t("Analyzing your size...") })
|
|
1498
1675
|
] }),
|
|
1499
1676
|
sizingResult && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1500
|
-
/* @__PURE__ */ jsxs("div", { className: "ps-tryon-
|
|
1501
|
-
/* @__PURE__ */ jsx("
|
|
1502
|
-
/* @__PURE__ */ jsxs("div", { className: "ps-tryon-
|
|
1503
|
-
/* @__PURE__ */ jsx("div", { className: "ps-tryon-
|
|
1504
|
-
/* @__PURE__ */ jsx("
|
|
1505
|
-
] })
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
" ",
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
/* @__PURE__ */ jsx("
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1677
|
+
/* @__PURE__ */ jsxs("div", { className: "ps-tryon-sr-hero", children: [
|
|
1678
|
+
/* @__PURE__ */ jsx("div", { className: "ps-tryon-sr-hero-badge", children: sizingResult.recommendedSize }),
|
|
1679
|
+
/* @__PURE__ */ jsxs("div", { className: "ps-tryon-sr-hero-info", children: [
|
|
1680
|
+
/* @__PURE__ */ jsx("div", { className: "ps-tryon-sr-hero-title", children: t("Your Size") }),
|
|
1681
|
+
/* @__PURE__ */ jsx("div", { className: `ps-tryon-sr-hero-conf ps-conf-${sizingResult.confidence}`, children: sizingResult.confidence === "high" ? t("High Confidence") : sizingResult.confidence === "medium" ? t("Medium Confidence") : t("Low Confidence") })
|
|
1682
|
+
] })
|
|
1683
|
+
] }),
|
|
1684
|
+
Object.keys(activeIntl).length > 0 && (() => {
|
|
1685
|
+
const PRIMARY_CODES = ["US", "UK", "EU", "IT", "FR", "DE"];
|
|
1686
|
+
const primary = PRIMARY_CODES.filter((c) => activeIntl[c]).map((c) => ({ code: c, val: activeIntl[c] }));
|
|
1687
|
+
const rest = Object.entries(activeIntl).filter(([c]) => !PRIMARY_CODES.includes(c)).map(([code, val]) => ({ code, val }));
|
|
1688
|
+
return /* @__PURE__ */ jsxs("div", { className: "ps-tryon-sr-intl", children: [
|
|
1689
|
+
/* @__PURE__ */ jsx("div", { className: "ps-tryon-sr-label", children: t("Equivalent Sizes") }),
|
|
1690
|
+
primary.length > 0 && /* @__PURE__ */ jsx("div", { className: "ps-tryon-sr-intl-primary", children: primary.map((s) => /* @__PURE__ */ jsxs("div", { className: "ps-tryon-sr-intl-card", children: [
|
|
1691
|
+
/* @__PURE__ */ jsx("span", { className: "ps-tryon-sr-intl-card-val", children: s.val }),
|
|
1692
|
+
/* @__PURE__ */ jsx("span", { className: "ps-tryon-sr-intl-card-code", children: s.code })
|
|
1693
|
+
] }, s.code)) }),
|
|
1694
|
+
rest.length > 0 && /* @__PURE__ */ jsxs("details", { className: "ps-tryon-sr-intl-more", children: [
|
|
1695
|
+
/* @__PURE__ */ jsxs("summary", { className: "ps-tryon-sr-intl-more-btn", children: [
|
|
1696
|
+
t("Show more"),
|
|
1697
|
+
" (",
|
|
1698
|
+
rest.length,
|
|
1699
|
+
")"
|
|
1700
|
+
] }),
|
|
1701
|
+
/* @__PURE__ */ jsx("div", { className: "ps-tryon-sr-intl-grid", children: rest.map((s) => /* @__PURE__ */ jsxs("div", { className: "ps-tryon-sr-intl-item", children: [
|
|
1702
|
+
/* @__PURE__ */ jsx("span", { className: "ps-tryon-sr-intl-code", children: s.code }),
|
|
1703
|
+
/* @__PURE__ */ jsx("span", { className: "ps-tryon-sr-intl-val", children: s.val })
|
|
1704
|
+
] }, s.code)) })
|
|
1705
|
+
] })
|
|
1706
|
+
] });
|
|
1707
|
+
})(),
|
|
1708
|
+
chartData && chartData.sizes.length > 0 && /* @__PURE__ */ jsxs("div", { className: "ps-tryon-sr-sizes", children: [
|
|
1709
|
+
/* @__PURE__ */ jsxs("div", { className: "ps-tryon-sr-label", children: [
|
|
1710
|
+
t("Size Chart"),
|
|
1711
|
+
" ",
|
|
1712
|
+
/* @__PURE__ */ jsxs("span", { className: "ps-tryon-sr-label-hint", children: [
|
|
1713
|
+
"— ",
|
|
1714
|
+
t("tap to compare")
|
|
1537
1715
|
] })
|
|
1538
1716
|
] }),
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1717
|
+
/* @__PURE__ */ jsx("div", { className: "ps-tryon-sr-size-row", children: chartData.sizes.map((s) => /* @__PURE__ */ jsxs(
|
|
1718
|
+
"button",
|
|
1719
|
+
{
|
|
1720
|
+
onClick: () => setActiveSize(s.label),
|
|
1721
|
+
className: `ps-tryon-sr-size-chip${s.label === activeSize ? " ps-active" : ""}${s.label === sizingResult.recommendedSize ? " ps-recommended" : ""}`,
|
|
1722
|
+
children: [
|
|
1723
|
+
s.label,
|
|
1724
|
+
s.label === sizingResult.recommendedSize && /* @__PURE__ */ jsx("span", { className: "ps-tryon-sr-rec-dot" })
|
|
1725
|
+
]
|
|
1726
|
+
},
|
|
1727
|
+
s.label
|
|
1728
|
+
)) }),
|
|
1729
|
+
!isRecommended && /* @__PURE__ */ jsxs("div", { className: "ps-tryon-sr-comparing", children: [
|
|
1730
|
+
t("Comparing size"),
|
|
1731
|
+
" ",
|
|
1732
|
+
/* @__PURE__ */ jsx("strong", { children: activeSize })
|
|
1733
|
+
] })
|
|
1547
1734
|
] }),
|
|
1548
|
-
/* @__PURE__ */ jsxs("div", { className: "ps-tryon-
|
|
1735
|
+
activeFit && activeFit.length > 0 && /* @__PURE__ */ jsxs("div", { className: "ps-tryon-sr-fit", children: [
|
|
1736
|
+
/* @__PURE__ */ jsx("div", { className: "ps-tryon-sr-label", children: t("Fit Analysis") }),
|
|
1737
|
+
/* @__PURE__ */ jsxs("div", { className: "ps-tryon-sr-fit-table", children: [
|
|
1738
|
+
/* @__PURE__ */ jsxs("div", { className: "ps-tryon-sr-fit-header", children: [
|
|
1739
|
+
/* @__PURE__ */ jsx("span", { className: "ps-tryon-sr-fit-col-area", children: t("Area") }),
|
|
1740
|
+
/* @__PURE__ */ jsxs("span", { className: "ps-tryon-sr-fit-col-you", children: [
|
|
1741
|
+
t("You"),
|
|
1742
|
+
" (",
|
|
1743
|
+
unitLabel,
|
|
1744
|
+
")"
|
|
1745
|
+
] }),
|
|
1746
|
+
/* @__PURE__ */ jsxs("span", { className: "ps-tryon-sr-fit-col-chart", children: [
|
|
1747
|
+
t("Chart"),
|
|
1748
|
+
" (",
|
|
1749
|
+
unitLabel,
|
|
1750
|
+
")"
|
|
1751
|
+
] }),
|
|
1752
|
+
/* @__PURE__ */ jsx("span", { className: "ps-tryon-sr-fit-col-fit", children: t("Fit") })
|
|
1753
|
+
] }),
|
|
1754
|
+
activeFit.map((row, i) => /* @__PURE__ */ jsxs("div", { className: `ps-tryon-sr-fit-row ps-fit-${row.fit}`, children: [
|
|
1755
|
+
/* @__PURE__ */ jsx("span", { className: "ps-tryon-sr-fit-col-area", children: row.label }),
|
|
1756
|
+
/* @__PURE__ */ jsx("span", { className: "ps-tryon-sr-fit-col-you", children: /* @__PURE__ */ jsx(
|
|
1757
|
+
"input",
|
|
1758
|
+
{
|
|
1759
|
+
type: "number",
|
|
1760
|
+
className: "ps-tryon-sr-fit-input",
|
|
1761
|
+
defaultValue: isCmResult ? Math.round(row.userVal) : cmToIn(row.userVal),
|
|
1762
|
+
onBlur: (e) => {
|
|
1763
|
+
const val = e.target.value;
|
|
1764
|
+
setEditedValues((prev) => ({ ...prev, [row.formKey]: val }));
|
|
1765
|
+
}
|
|
1766
|
+
}
|
|
1767
|
+
) }),
|
|
1768
|
+
/* @__PURE__ */ jsx("span", { className: "ps-tryon-sr-fit-col-chart", children: fmtRange(row.chartMin, row.chartMax) }),
|
|
1769
|
+
/* @__PURE__ */ jsx("span", { className: "ps-tryon-sr-fit-col-fit", children: /* @__PURE__ */ jsxs("span", { className: `ps-tryon-sr-fit-badge ps-fit-${row.fit}`, children: [
|
|
1770
|
+
row.fit === "good" ? "✓" : row.fit === "tight" ? "↑" : "↓",
|
|
1771
|
+
" ",
|
|
1772
|
+
row.fit === "good" ? t("within range") : row.fit === "tight" ? t("may be snug") : t("may be loose")
|
|
1773
|
+
] }) })
|
|
1774
|
+
] }, i))
|
|
1775
|
+
] })
|
|
1776
|
+
] }),
|
|
1777
|
+
(!activeFit || activeFit.length === 0) && sizingResult.reasoning && /* @__PURE__ */ jsx("div", { className: "ps-tryon-sr-reasoning", children: /* @__PURE__ */ jsx("p", { children: sizingResult.reasoning }) }),
|
|
1778
|
+
/* @__PURE__ */ jsxs("div", { className: "ps-tryon-sr-ctas", children: [
|
|
1549
1779
|
/* @__PURE__ */ jsxs("button", { className: "ps-tryon-cta", onClick: () => setView("upload"), children: [
|
|
1550
1780
|
t("See how it looks on you"),
|
|
1551
1781
|
" ",
|
|
@@ -2213,79 +2443,139 @@ const STYLES = `
|
|
|
2213
2443
|
.ps-tryon-btn-retry { background: rgba(255,255,255,0.08); color: #fff; border: 1px solid #333 !important; }
|
|
2214
2444
|
.ps-tryon-btn-retry:hover { background: rgba(255,255,255,0.12); }
|
|
2215
2445
|
|
|
2216
|
-
/* Size
|
|
2217
|
-
.ps-tryon-
|
|
2218
|
-
.ps-tryon-
|
|
2219
|
-
.ps-tryon-
|
|
2220
|
-
display: flex; align-items: center; gap: 0.83vw; padding: 0.83vw 1.04vw;
|
|
2221
|
-
border: 1.5px solid #333; border-radius: 0.73vw; margin-bottom: 0.94vw; background: rgba(255,255,255,0.02);
|
|
2222
|
-
}
|
|
2223
|
-
.ps-tryon-size-badge {
|
|
2224
|
-
display: inline-flex; align-items: center; justify-content: center;
|
|
2225
|
-
min-width: 2.92vw; height: 2.92vw; padding: 0 0.63vw; border-radius: 0.63vw;
|
|
2226
|
-
background: linear-gradient(135deg, #bb945c, #d6ba7d);
|
|
2227
|
-
color: #111; font-size: 1.25vw; font-weight: 800; letter-spacing: -0.02em;
|
|
2228
|
-
}
|
|
2229
|
-
.ps-tryon-size-conf-label { font-size: 0.78vw; font-weight: 600; }
|
|
2230
|
-
.ps-conf-high { color: #4ade80; } .ps-conf-medium { color: #bb945c; } .ps-conf-low { color: #ef4444; }
|
|
2231
|
-
|
|
2232
|
-
.ps-tryon-sizing-loading { text-align: center; padding: 1.04vw 0; }
|
|
2446
|
+
/* ── Size Result (redesigned) ── */
|
|
2447
|
+
.ps-tryon-sr { display: flex; flex-direction: column; gap: 1.1vw; }
|
|
2448
|
+
.ps-tryon-sr-loading { text-align: center; padding: 2vw 0; }
|
|
2449
|
+
.ps-tryon-sr-loading p { font-size: 0.83vw; color: #999; margin-top: 0.5vw; }
|
|
2233
2450
|
.ps-tryon-size-loading-spinner {
|
|
2234
|
-
width:
|
|
2451
|
+
width: 2vw; height: 2vw; border: 3px solid #333;
|
|
2235
2452
|
border-top-color: #bb945c; border-radius: 50%;
|
|
2236
|
-
animation: ps-spin 0.8s linear infinite; margin: 0 auto
|
|
2453
|
+
animation: ps-spin 0.8s linear infinite; margin: 0 auto;
|
|
2237
2454
|
}
|
|
2238
2455
|
@keyframes ps-spin { to { transform: rotate(360deg); } }
|
|
2239
2456
|
|
|
2240
|
-
/*
|
|
2241
|
-
.ps-tryon-
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
.ps-tryon-
|
|
2253
|
-
.ps-tryon-
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
.ps-tryon-
|
|
2259
|
-
.ps-tryon-
|
|
2260
|
-
.ps-tryon-
|
|
2261
|
-
.ps-
|
|
2457
|
+
/* Hero */
|
|
2458
|
+
.ps-tryon-sr-hero {
|
|
2459
|
+
display: flex; align-items: center; gap: 1vw; padding: 1vw 1.2vw;
|
|
2460
|
+
background: linear-gradient(135deg, rgba(187,148,92,0.08), rgba(187,148,92,0.02));
|
|
2461
|
+
border: 1.5px solid rgba(187,148,92,0.25); border-radius: 0.83vw;
|
|
2462
|
+
}
|
|
2463
|
+
.ps-tryon-sr-hero-badge {
|
|
2464
|
+
min-width: 3.5vw; height: 3.5vw; display: flex; align-items: center; justify-content: center;
|
|
2465
|
+
background: linear-gradient(135deg, #bb945c, #d6ba7d); color: #111;
|
|
2466
|
+
font-size: 1.5vw; font-weight: 800; border-radius: 0.73vw; letter-spacing: -0.02em;
|
|
2467
|
+
padding: 0 0.8vw; box-shadow: 0 0.4vw 1.2vw rgba(187,148,92,0.25);
|
|
2468
|
+
}
|
|
2469
|
+
.ps-tryon-sr-hero-info { flex: 1; }
|
|
2470
|
+
.ps-tryon-sr-hero-title { font-size: 1.04vw; font-weight: 700; color: #fff; margin-bottom: 0.15vw; }
|
|
2471
|
+
.ps-tryon-sr-hero-conf { font-size: 0.78vw; font-weight: 600; }
|
|
2472
|
+
.ps-conf-high { color: #4ade80; } .ps-conf-medium { color: #bb945c; } .ps-conf-low { color: #ef4444; }
|
|
2473
|
+
|
|
2474
|
+
/* International sizes */
|
|
2475
|
+
.ps-tryon-sr-intl { }
|
|
2476
|
+
.ps-tryon-sr-label { font-size: 0.78vw; font-weight: 700; color: #999; text-transform: uppercase; letter-spacing: 0.08em; margin-bottom: 0.52vw; }
|
|
2477
|
+
.ps-tryon-sr-label-hint { font-weight: 400; text-transform: none; letter-spacing: 0; color: #666; font-style: italic; }
|
|
2478
|
+
.ps-tryon-sr-intl-primary { display: flex; flex-wrap: wrap; gap: 0.42vw; margin-bottom: 0.52vw; }
|
|
2479
|
+
.ps-tryon-sr-intl-card {
|
|
2480
|
+
flex: 1; min-width: 3.5vw; display: flex; flex-direction: column; align-items: center;
|
|
2481
|
+
padding: 0.57vw 0.42vw; border: 1.5px solid #333; border-radius: 0.63vw;
|
|
2482
|
+
background: #1a1b1a; transition: border-color 0.2s;
|
|
2483
|
+
}
|
|
2484
|
+
.ps-tryon-sr-intl-card:hover { border-color: #555; }
|
|
2485
|
+
.ps-tryon-sr-intl-card-val { font-size: 1.04vw; font-weight: 800; color: #fff; line-height: 1.2; }
|
|
2486
|
+
.ps-tryon-sr-intl-card-code { font-size: 0.57vw; font-weight: 700; color: #666; text-transform: uppercase; letter-spacing: 0.08em; margin-top: 0.1vw; }
|
|
2262
2487
|
|
|
2263
|
-
|
|
2264
|
-
.ps-tryon-
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2488
|
+
.ps-tryon-sr-intl-more { }
|
|
2489
|
+
.ps-tryon-sr-intl-more-btn {
|
|
2490
|
+
font-size: 0.73vw; color: #bb945c; font-weight: 600; cursor: pointer;
|
|
2491
|
+
list-style: none; margin-bottom: 0.42vw; font-family: inherit;
|
|
2492
|
+
}
|
|
2493
|
+
.ps-tryon-sr-intl-more-btn::-webkit-details-marker { display: none; }
|
|
2494
|
+
.ps-tryon-sr-intl-more-btn::before { content: "▸ "; }
|
|
2495
|
+
.ps-tryon-sr-intl-more[open] .ps-tryon-sr-intl-more-btn::before { content: "▾ "; }
|
|
2496
|
+
|
|
2497
|
+
.ps-tryon-sr-intl-grid { display: flex; flex-wrap: wrap; gap: 0.42vw; }
|
|
2498
|
+
.ps-tryon-sr-intl-item {
|
|
2268
2499
|
display: flex; align-items: center; border: 1.5px solid #333; border-radius: 0.52vw; overflow: hidden;
|
|
2269
2500
|
}
|
|
2270
|
-
.ps-tryon-
|
|
2271
|
-
.ps-tryon-
|
|
2501
|
+
.ps-tryon-sr-intl-code { padding: 0.42vw 0.57vw; font-size: 0.68vw; color: #999; font-weight: 700; background: rgba(255,255,255,0.03); letter-spacing: 0.04em; }
|
|
2502
|
+
.ps-tryon-sr-intl-val { padding: 0.42vw 0.68vw; font-size: 0.83vw; color: #fff; font-weight: 700; }
|
|
2272
2503
|
|
|
2273
|
-
/*
|
|
2274
|
-
.ps-tryon-
|
|
2275
|
-
.ps-tryon-
|
|
2276
|
-
.ps-tryon-
|
|
2277
|
-
|
|
2278
|
-
|
|
2504
|
+
/* Size selector */
|
|
2505
|
+
.ps-tryon-sr-sizes { }
|
|
2506
|
+
.ps-tryon-sr-size-row { display: flex; flex-wrap: wrap; gap: 0.36vw; }
|
|
2507
|
+
.ps-tryon-sr-size-chip {
|
|
2508
|
+
position: relative; min-width: 2.6vw; height: 2.4vw; padding: 0 0.73vw;
|
|
2509
|
+
display: flex; align-items: center; justify-content: center;
|
|
2510
|
+
border: 1.5px solid #333; border-radius: 0.52vw; background: transparent;
|
|
2511
|
+
color: #999; font-size: 0.83vw; font-weight: 600; cursor: pointer;
|
|
2512
|
+
transition: all 0.2s; font-family: inherit;
|
|
2513
|
+
}
|
|
2514
|
+
.ps-tryon-sr-size-chip:hover { border-color: #555; color: #ccc; }
|
|
2515
|
+
.ps-tryon-sr-size-chip.ps-active {
|
|
2516
|
+
border-color: #bb945c; background: #bb945c; color: #111;
|
|
2517
|
+
box-shadow: 0 0.2vw 0.8vw rgba(187,148,92,0.2);
|
|
2518
|
+
}
|
|
2519
|
+
.ps-tryon-sr-size-chip.ps-recommended { border-color: rgba(187,148,92,0.4); }
|
|
2520
|
+
.ps-tryon-sr-rec-dot {
|
|
2521
|
+
position: absolute; bottom: -0.26vw; left: 50%; transform: translateX(-50%);
|
|
2522
|
+
width: 0.31vw; height: 0.31vw; border-radius: 50%; background: #bb945c;
|
|
2523
|
+
}
|
|
2524
|
+
.ps-tryon-sr-size-chip.ps-active .ps-tryon-sr-rec-dot { background: #111; }
|
|
2525
|
+
.ps-tryon-sr-comparing { font-size: 0.73vw; color: #bb945c; margin-top: 0.42vw; }
|
|
2526
|
+
.ps-tryon-sr-comparing strong { color: #d6ba7d; }
|
|
2527
|
+
|
|
2528
|
+
/* Fit analysis table */
|
|
2529
|
+
.ps-tryon-sr-fit { }
|
|
2530
|
+
.ps-tryon-sr-fit-table { border: 1.5px solid #333; border-radius: 0.73vw; overflow: hidden; }
|
|
2531
|
+
.ps-tryon-sr-fit-header {
|
|
2532
|
+
display: flex; padding: 0.57vw 0.83vw; background: #1a1b1a; border-bottom: 1px solid #333;
|
|
2533
|
+
}
|
|
2534
|
+
.ps-tryon-sr-fit-header span {
|
|
2535
|
+
font-size: 0.68vw; font-weight: 700; color: #666; text-transform: uppercase; letter-spacing: 0.06em;
|
|
2536
|
+
}
|
|
2537
|
+
.ps-tryon-sr-fit-row {
|
|
2538
|
+
display: flex; align-items: center; padding: 0.57vw 0.83vw;
|
|
2539
|
+
border-bottom: 1px solid #222; transition: background 0.15s;
|
|
2540
|
+
}
|
|
2541
|
+
.ps-tryon-sr-fit-row:last-child { border-bottom: none; }
|
|
2542
|
+
.ps-tryon-sr-fit-row:hover { background: rgba(255,255,255,0.02); }
|
|
2543
|
+
.ps-tryon-sr-fit-row.ps-fit-good { border-left: 3px solid #4ade80; }
|
|
2544
|
+
.ps-tryon-sr-fit-row.ps-fit-tight { border-left: 3px solid #f59e0b; }
|
|
2545
|
+
.ps-tryon-sr-fit-row.ps-fit-loose { border-left: 3px solid #60a5fa; }
|
|
2279
2546
|
|
|
2280
|
-
.ps-tryon-
|
|
2547
|
+
.ps-tryon-sr-fit-col-area { flex: 0 0 28%; font-size: 0.78vw; font-weight: 600; color: #fff; }
|
|
2548
|
+
.ps-tryon-sr-fit-col-you { flex: 0 0 22%; }
|
|
2549
|
+
.ps-tryon-sr-fit-col-chart { flex: 0 0 22%; font-size: 0.78vw; color: #999; font-weight: 500; }
|
|
2550
|
+
.ps-tryon-sr-fit-col-fit { flex: 1; text-align: right; }
|
|
2281
2551
|
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2552
|
+
.ps-tryon-sr-fit-input {
|
|
2553
|
+
width: 3.5vw; padding: 0.26vw 0.42vw; border: 1.5px solid #333; border-radius: 0.36vw;
|
|
2554
|
+
background: #111211; color: #fff; font-size: 0.78vw; font-weight: 600; font-family: inherit;
|
|
2555
|
+
outline: none; text-align: center; -moz-appearance: textfield;
|
|
2556
|
+
}
|
|
2557
|
+
.ps-tryon-sr-fit-input::-webkit-outer-spin-button,
|
|
2558
|
+
.ps-tryon-sr-fit-input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
|
|
2559
|
+
.ps-tryon-sr-fit-input:focus { border-color: #bb945c; }
|
|
2560
|
+
|
|
2561
|
+
.ps-tryon-sr-fit-badge {
|
|
2562
|
+
display: inline-flex; align-items: center; gap: 0.26vw; padding: 0.21vw 0.52vw;
|
|
2563
|
+
border-radius: 0.36vw; font-size: 0.63vw; font-weight: 700; white-space: nowrap;
|
|
2564
|
+
}
|
|
2565
|
+
.ps-tryon-sr-fit-badge.ps-fit-good { background: rgba(74,222,128,0.1); color: #4ade80; }
|
|
2566
|
+
.ps-tryon-sr-fit-badge.ps-fit-tight { background: rgba(245,158,11,0.1); color: #f59e0b; }
|
|
2567
|
+
.ps-tryon-sr-fit-badge.ps-fit-loose { background: rgba(96,165,250,0.1); color: #60a5fa; }
|
|
2568
|
+
|
|
2569
|
+
/* Reasoning fallback */
|
|
2570
|
+
.ps-tryon-sr-reasoning { padding: 0.83vw; border: 1px solid #333; border-radius: 0.63vw; background: #1a1b1a; }
|
|
2571
|
+
.ps-tryon-sr-reasoning p { font-size: 0.78vw; color: #ccc; line-height: 1.6; margin: 0; }
|
|
2572
|
+
|
|
2573
|
+
/* CTAs */
|
|
2574
|
+
.ps-tryon-sr-ctas { display: flex; flex-direction: column; gap: 0.52vw; margin-top: 0.36vw; }
|
|
2285
2575
|
.ps-tryon-btn-secondary {
|
|
2286
2576
|
background: transparent; border: 1.5px solid #444; color: #999; font-size: 0.83vw;
|
|
2287
|
-
font-weight: 600; padding: 0.
|
|
2288
|
-
cursor: pointer; transition: all 0.2s;
|
|
2577
|
+
font-weight: 600; padding: 0.73vw 1.3vw; border-radius: 0.52vw;
|
|
2578
|
+
cursor: pointer; transition: all 0.2s; font-family: inherit;
|
|
2289
2579
|
}
|
|
2290
2580
|
.ps-tryon-btn-secondary:hover { border-color: #666; color: #ccc; }
|
|
2291
2581
|
.ps-tryon-size-compact { padding: 0.5vw 0; }
|