diff --git a/src/features/ecommerce/EcommercePage.tsx b/src/features/ecommerce/EcommercePage.tsx index f878bdd..aaf32f7 100644 --- a/src/features/ecommerce/EcommercePage.tsx +++ b/src/features/ecommerce/EcommercePage.tsx @@ -41,35 +41,6 @@ import EcommerceTryOnPanel from "./panels/EcommerceTryOnPanel"; import EcommerceClonePanel from "./panels/EcommerceClonePanel"; import { ecommerceOssScopes, saveUnifiedEcommerceGenerationRecord, deleteEcommerceGenerationRecord } from "./ecommerceGenerationPersistence"; import { downloadResultAsset } from "../workbench/workbenchDownload"; -import { - formatRatioDisplayValue, - getQuickSetRatioValue, - getRatioDisplayParts, - normalizeRatioForApi, - normalizeRatioToken, - parseRatioToAspectCss, - quickSetRatioOptions, -} from "./utils/ratioUtils"; -import { - defaultCloneOutput, - defaultEcommercePlatform, - defaultProductSetOutput, - formatUploadedImageRatio, - getPlatformDefaultLanguage, - getPlatformDefaultRatio, - getPlatformLanguageOptions, - getPlatformRatioOptions, - getUniqueRatioOptions, - marketLanguageOptions, - marketOptions, - normalizeLanguageForPlatform, - normalizeMarket, - normalizePlatform, - normalizeRatioForPlatform, - platformOptions, - type CloneOutputKey, - type ProductSetOutputKey, -} from "./utils/platformRules"; const smartCutoutColorPresets = [ "#ffffff", @@ -295,11 +266,13 @@ import { interface ProductClonePageProps { - onWorkspaceChromeChange?: (state: { isToolPage: boolean }) => void; [key: string]: unknown; } type ProductCloneStatus = "idle" | "ready" | "generating" | "done" | "failed"; +type ProductSetOutputKey = "set" | "detail" | "model" | "video"; +type CloneOutputKey = ProductSetOutputKey | "hot"; +type CommerceScenarioKey = "popular" | "poster" | "mainImage" | "scene" | "festival" | "model" | "background" | "retouch" | "salesVideo"; type CloneSetCountKey = "selling" | "white" | "scene"; type CloneModelPanelTab = "scene" | "model"; type CloneVideoQualityKey = "standard" | "high" | "ultra"; @@ -316,6 +289,12 @@ type CloneTemplateAsset = { prompt: string; mediaUrl: string; }; +interface CommerceScenarioTemplate extends CloneTemplateAsset { + scenario: Exclude; + output: ProductSetOutputKey; + desc: string; + badge: string; +} type TryOnModelSource = "ai" | "library"; type TryOnStatus = "idle" | "modeling" | "ready" | "generating" | "done" | "failed"; type DetailStatus = "idle" | "ready" | "generating" | "done" | "failed"; @@ -457,6 +436,13 @@ interface EcommerceImagePromptOptions { detailModules?: string[]; } +type PlatformRatioModeKey = ProductSetOutputKey | "hot"; + +interface PlatformRatioGroup { + ratios: string[]; + defaultRatio: string; +} + const sideTools: Array<{ key: ProductKitToolKey; label: string; icon: ReactNode }> = [ { key: "set", label: "商品套图", icon: }, { key: "detail", label: "A+详情", icon: }, @@ -464,6 +450,324 @@ const sideTools: Array<{ key: ProductKitToolKey; label: string; icon: ReactNode { key: "clone", label: "电商AI作图", icon: }, ]; +const platformSpecOptions: Array<{ + label: string; + ratios: string[]; + defaultRatio: string; + ratioGroups?: Partial>; + specs: string[]; + tip?: string; + aliases?: string[]; +}> = [ + { + label: "淘宝/天猫", + ratios: ["淘宝主图 / SKU 图 800×800px", "详情页宽 750px", "详情页宽 790px"], + defaultRatio: "淘宝主图 / SKU 图 800×800px", + ratioGroups: { + set: { + ratios: ["1000×1000px\u00a0\u00a0\u00a01:1", "800×800px\u00a0\u00a0\u00a01:1"], + defaultRatio: "1000×1000px\u00a0\u00a0\u00a01:1", + }, + detail: { + ratios: [ + "750×1000px\u00a0\u00a0\u00a03:4", + "790×1053px\u00a0\u00a0\u00a03:4", + "750×1125px\u00a0\u00a0\u00a02:3", + "790×1185px\u00a0\u00a0\u00a02:3", + ], + defaultRatio: "750×1000px\u00a0\u00a0\u00a03:4", + }, + model: { + ratios: ["750×1000px\u00a0\u00a0\u00a03:4"], + defaultRatio: "750×1000px\u00a0\u00a0\u00a03:4", + }, + video: { + ratios: ["1080×1920px\u00a0\u00a0\u00a09:16", "1080×1440px\u00a0\u00a0\u00a03:4", "1080×1080px\u00a0\u00a0\u00a01:1"], + defaultRatio: "1080×1920px\u00a0\u00a0\u00a09:16", + }, + hot: { + ratios: ["800×800px\u00a0\u00a0\u00a01:1"], + defaultRatio: "800×800px\u00a0\u00a0\u00a01:1", + }, + }, + specs: ["主图 / SKU 图 800×800px,≤3MB", "详情页宽 750px 或 790px,单张高度≤1546px"], + tip: "建议主图 200-400KB JPG,超过 500KB 会影响加载速度。", + }, + { + label: "京东", + ratios: ["京东主图 / SKU 图 800×800px", "详情页宽 750px", "首图主体占比 ≥80%"], + defaultRatio: "京东主图 / SKU 图 800×800px", + ratioGroups: { + set: { + ratios: ["1000×1000px\u00a0\u00a0\u00a01:1"], + defaultRatio: "1000×1000px\u00a0\u00a0\u00a01:1", + }, + detail: { + ratios: [ + "750×1000px\u00a0\u00a0\u00a03:4", + "990×1320px\u00a0\u00a0\u00a03:4", + "750×1125px\u00a0\u00a0\u00a02:3", + "990×1485px\u00a0\u00a0\u00a02:3", + ], + defaultRatio: "750×1000px\u00a0\u00a0\u00a03:4", + }, + model: { + ratios: ["750×1125px\u00a0\u00a0\u00a02:3", "990×1485px\u00a0\u00a0\u00a02:3"], + defaultRatio: "750×1125px\u00a0\u00a0\u00a02:3", + }, + video: { + ratios: ["1080×1920px\u00a0\u00a0\u00a09:16", "1920×1080px\u00a0\u00a0\u00a016:9"], + defaultRatio: "1080×1920px\u00a0\u00a0\u00a09:16", + }, + hot: { + ratios: ["800×800px\u00a0\u00a0\u00a01:1"], + defaultRatio: "800×800px\u00a0\u00a0\u00a01:1", + }, + }, + specs: ["主图 / SKU 图 800×800px,白底,≤3MB", "详情页宽 750px,首图主体占比 ≥80%"], + }, + { + label: "拼多多", + ratios: ["主图 750×352px", "主图 800×800px", "详情页宽 750px"], + defaultRatio: "主图 750×352px", + ratioGroups: { + set: { + ratios: ["800×800px\u00a0\u00a0\u00a01:1", "750×1000px\u00a0\u00a0\u00a03:4"], + defaultRatio: "800×800px\u00a0\u00a0\u00a01:1", + }, + detail: { + ratios: ["750×1000px\u00a0\u00a0\u00a03:4", "750×1125px\u00a0\u00a0\u00a02:3"], + defaultRatio: "750×1000px\u00a0\u00a0\u00a03:4", + }, + model: { + ratios: ["750×1000px\u00a0\u00a0\u00a03:4"], + defaultRatio: "750×1000px\u00a0\u00a0\u00a03:4", + }, + video: { + ratios: ["1080×1920px\u00a0\u00a0\u00a09:16"], + defaultRatio: "1080×1920px\u00a0\u00a0\u00a09:16", + }, + hot: { + ratios: ["800×800px\u00a0\u00a0\u00a01:1"], + defaultRatio: "800×800px\u00a0\u00a0\u00a01:1", + }, + }, + specs: ["主图 750×352px 或 800×800px,≤1MB", "详情页宽 750px,要求纯白底、无水印、无拼接"], + }, + { + label: "抖音电商", + ratios: ["短视频1080×1920px"], + defaultRatio: "短视频1080×1920px", + ratioGroups: { + video: { + ratios: ["1080×1920px\u00a0\u00a0\u00a09:16"], + defaultRatio: "1080×1920px\u00a0\u00a0\u00a09:16", + }, + hot: { + ratios: ["800×800px\u00a0\u00a0\u00a01:1"], + defaultRatio: "800×800px\u00a0\u00a0\u00a01:1", + }, + }, + specs: ["短视频 1080×1920px,9:16", "30s 内最佳"], + }, + { + label: "亚马逊 Amazon", + ratios: ["主图 ≥1600×1600px", "建议 2000×2000px+", "最小 500×500px"], + defaultRatio: "主图 ≥1600×1600px", + ratioGroups: { + set: { + ratios: ["1600×1600px\u00a0\u00a0\u00a01:1"], + defaultRatio: "1600×1600px\u00a0\u00a0\u00a01:1", + }, + detail: { + ratios: ["1600×1600px\u00a0\u00a0\u00a01:1", "1200×1800px\u00a0\u00a0\u00a02:3", "1200×1600px\u00a0\u00a0\u00a03:4"], + defaultRatio: "1200×1800px\u00a0\u00a0\u00a02:3", + }, + model: { + ratios: ["1200×1800px\u00a0\u00a0\u00a02:3"], + defaultRatio: "1200×1800px\u00a0\u00a0\u00a02:3", + }, + video: { + ratios: ["1920×1080px\u00a0\u00a0\u00a016:9"], + defaultRatio: "1920×1080px\u00a0\u00a0\u00a016:9", + }, + hot: { + ratios: ["1600×1600px\u00a0\u00a0\u00a01:1"], + defaultRatio: "1600×1600px\u00a0\u00a0\u00a01:1", + }, + }, + specs: ["主图 1600×1600px+,纯白底,≤10MB", "最小 500×500px,建议 2000px+ 以支持缩放"], + aliases: ["亚马逊"], + }, + { + label: "Shopee", + ratios: ["商品主图 1024×1024px", "基础主图 800×800px"], + defaultRatio: "商品主图 1024×1024px", + ratioGroups: { + set: { + ratios: ["800×800px\u00a0\u00a0\u00a01:1"], + defaultRatio: "800×800px\u00a0\u00a0\u00a01:1", + }, + detail: { + ratios: ["750×1000px\u00a0\u00a0\u00a03:4", "750×1125px\u00a0\u00a0\u00a02:3"], + defaultRatio: "750×1000px\u00a0\u00a0\u00a03:4", + }, + model: { + ratios: ["750×1000px\u00a0\u00a0\u00a03:4"], + defaultRatio: "750×1000px\u00a0\u00a0\u00a03:4", + }, + video: { + ratios: ["1080×1920px\u00a0\u00a0\u00a09:16"], + defaultRatio: "1080×1920px\u00a0\u00a0\u00a09:16", + }, + hot: { + ratios: ["800×800px\u00a0\u00a0\u00a01:1"], + defaultRatio: "800×800px\u00a0\u00a0\u00a01:1", + }, + }, + specs: ["商品主图推荐 1024×1024px,基础 800×800px", "≤2MB,白底或浅色底"], + aliases: ["虾皮 Shopee/Lazada", "虾皮"], + }, + { + label: "Lazada", + ratios: ["商品主图 800×800px"], + defaultRatio: "商品主图 800×800px", + ratioGroups: { + set: { + ratios: ["800×800px\u00a0\u00a0\u00a01:1"], + defaultRatio: "800×800px\u00a0\u00a0\u00a01:1", + }, + detail: { + ratios: ["750×1000px\u00a0\u00a0\u00a03:4", "750×1125px\u00a0\u00a0\u00a02:3"], + defaultRatio: "750×1000px\u00a0\u00a0\u00a03:4", + }, + model: { + ratios: ["750×1000px\u00a0\u00a0\u00a03:4"], + defaultRatio: "750×1000px\u00a0\u00a0\u00a03:4", + }, + video: { + ratios: ["1080×1920px\u00a0\u00a0\u00a09:16"], + defaultRatio: "1080×1920px\u00a0\u00a0\u00a09:16", + }, + hot: { + ratios: ["800×800px\u00a0\u00a0\u00a01:1"], + defaultRatio: "800×800px\u00a0\u00a0\u00a01:1", + }, + }, + specs: ["商品主图 800×800px,1:1"], + }, + { + label: "Instagram", + ratios: ["帖子 1080×1350px", "帖子 1080×1080px", "Stories / Reels 1080×1920px", "头像 320×320px"], + defaultRatio: "帖子 1080×1350px", + ratioGroups: { + set: { + ratios: ["1080×1080px\u00a0\u00a0\u00a01:1", "1080×1350px\u00a0\u00a0\u00a04:5"], + defaultRatio: "1080×1080px\u00a0\u00a0\u00a01:1", + }, + detail: { + ratios: ["1080×1350px\u00a0\u00a0\u00a04:5"], + defaultRatio: "1080×1350px\u00a0\u00a0\u00a04:5", + }, + model: { + ratios: ["1080×1350px\u00a0\u00a0\u00a04:5"], + defaultRatio: "1080×1350px\u00a0\u00a0\u00a04:5", + }, + video: { + ratios: ["1080×1920px\u00a0\u00a0\u00a09:16", "1080×1350px\u00a0\u00a0\u00a04:5"], + defaultRatio: "1080×1920px\u00a0\u00a0\u00a09:16", + }, + }, + specs: ["帖子 1080×1350px 或 1080×1080px", "Stories / Reels 封面 1080×1920px,头像 320×320px"], + tip: "建议 ≤8MB JPG。", + aliases: ["Instagram Reels"], + }, + { + label: "速卖通", + ratios: ["主图 800×800px", "主图 1000×1000px+"], + defaultRatio: "主图 800×800px", + ratioGroups: { + set: { + ratios: ["1000×1000px\u00a0\u00a0\u00a01:1"], + defaultRatio: "1000×1000px\u00a0\u00a0\u00a01:1", + }, + detail: { + ratios: ["750×1125px\u00a0\u00a0\u00a02:3", "750×1000px\u00a0\u00a0\u00a03:4"], + defaultRatio: "750×1125px\u00a0\u00a0\u00a02:3", + }, + model: { + ratios: ["750×1125px\u00a0\u00a0\u00a02:3"], + defaultRatio: "750×1125px\u00a0\u00a0\u00a02:3", + }, + video: { + ratios: ["1080×1920px\u00a0\u00a0\u00a09:16", "1920×1080px\u00a0\u00a0\u00a016:9"], + defaultRatio: "1080×1920px\u00a0\u00a0\u00a09:16", + }, + hot: { + ratios: ["800×800px\u00a0\u00a0\u00a01:1"], + defaultRatio: "800×800px\u00a0\u00a0\u00a01:1", + }, + }, + specs: ["主图建议 800×800px 或更高,1:1", "适合跨境电商主图、SKU 图和场景图"], + }, + { + label: "eBay", + ratios: ["商品图1:1", "白底多角度展示图 1:1"], + defaultRatio: "商品图1:1", + ratioGroups: { + set: { + ratios: ["1600×1600px\u00a0\u00a0\u00a01:1"], + defaultRatio: "1600×1600px\u00a0\u00a0\u00a01:1", + }, + detail: { + ratios: ["1000×1500px\u00a0\u00a0\u00a02:3", "1200×1600px\u00a0\u00a0\u00a03:4"], + defaultRatio: "1000×1500px\u00a0\u00a0\u00a02:3", + }, + model: { + ratios: ["1000×1500px\u00a0\u00a0\u00a02:3"], + defaultRatio: "1000×1500px\u00a0\u00a0\u00a02:3", + }, + video: { + ratios: ["1920×1080px\u00a0\u00a0\u00a016:9", "1080×1920px\u00a0\u00a0\u00a09:16"], + defaultRatio: "1920×1080px\u00a0\u00a0\u00a016:9", + }, + hot: { + ratios: ["1600×1600px\u00a0\u00a0\u00a01:1"], + defaultRatio: "1600×1600px\u00a0\u00a0\u00a01:1", + }, + }, + specs: ["商品图建议 1:1,主体清晰居中", "适合白底主图和多角度展示图"], + }, + { + label: "TikTok Shop", + ratios: ["商品主图 1:1", "短视频/ 竖版封面 9:16"], + defaultRatio: "商品主图 1:1", + ratioGroups: { + set: { + ratios: ["1280×1280px\u00a0\u00a0\u00a01:1"], + defaultRatio: "1280×1280px\u00a0\u00a0\u00a01:1", + }, + detail: { + ratios: ["1080×1350px\u00a0\u00a0\u00a04:5"], + defaultRatio: "1080×1350px\u00a0\u00a0\u00a04:5", + }, + model: { + ratios: ["1080×1350px\u00a0\u00a0\u00a04:5"], + defaultRatio: "1080×1350px\u00a0\u00a0\u00a04:5", + }, + video: { + ratios: ["1080×1920px\u00a0\u00a0\u00a09:16"], + defaultRatio: "1080×1920px\u00a0\u00a0\u00a09:16", + }, + hot: { + ratios: ["800×800px\u00a0\u00a0\u00a01:1"], + defaultRatio: "800×800px\u00a0\u00a0\u00a01:1", + }, + }, + specs: ["商品主图建议 1:1", "短视频竖版封面建议 9:16"], + }, +]; +const platformOptions = platformSpecOptions.map((option) => option.label); const getPlatformLogoText = (value: string) => { const normalized = value.toLowerCase(); if (value.includes("淘宝") || value.includes("天猫")) return "淘"; @@ -514,6 +818,223 @@ const renderPlatformLogo = (value: string) => { ); }; +const marketLanguageOptions: Array<{ country: string; languages: string[] }> = [ + { country: "中国", languages: ["中文"] }, + { country: "美国", languages: ["英文"] }, + { country: "加拿大", languages: ["英文", "法文"] }, + { country: "英国", languages: ["英文"] }, + { country: "德国", languages: ["德文"] }, + { country: "法国", languages: ["法文"] }, + { country: "意大利", languages: ["意大利语"] }, + { country: "西班牙", languages: ["西班牙语"] }, + { country: "日本", languages: ["日文"] }, + { country: "韩国", languages: ["韩文"] }, + { country: "澳大利亚", languages: ["英文"] }, + { country: "新加坡", languages: ["英文", "中文"] }, + { country: "马来西亚", languages: ["马来语", "英文", "中文"] }, + { country: "印尼", languages: ["印度尼西亚语", "英文"] }, + { country: "越南", languages: ["越南语", "英文"] }, + { country: "泰国", languages: ["泰语", "英文"] }, + { country: "菲律宾", languages: ["菲律宾语(他加禄语)", "英文"] }, + { country: "巴西", languages: ["葡萄牙语"] }, + { country: "墨西哥", languages: ["西班牙语"] }, + { country: "智利", languages: ["西班牙语"] }, + { country: "哥伦比亚", languages: ["西班牙语"] }, + { country: "阿联酋", languages: ["阿拉伯语", "英文"] }, + { country: "沙特阿拉伯", languages: ["阿拉伯语", "英文"] }, + { country: "俄罗斯", languages: ["俄语"] }, + { country: "波兰", languages: ["波兰语"] }, +]; +const marketOptions = marketLanguageOptions.map((option) => option.country); +const languageOptions = Array.from(new Set(marketLanguageOptions.flatMap((option) => option.languages))); +const languageAliases: Record = { + "英文": "英文", + "中文": "中文", + "英语": "英文", + "日语": "日文", + "日文": "日文", + "德语": "德文", + "德文": "德文", + "法语": "法文", + "法文": "法文", + "韩语": "韩文", + "韩文": "韩文", + "西文": "西班牙语", + "西班牙语": "西班牙语", + "葡文": "葡萄牙语", + "葡萄牙语": "葡萄牙语", + "印尼语": "印度尼西亚语", + "印度尼西亚语": "印度尼西亚语", + "菲律宾语": "菲律宾语(他加禄语)", + "菲律宾语(他加禄语)": "菲律宾语(他加禄语)", +}; +const defaultPlatformSpec = platformSpecOptions[0]!; +const getPlatformSpec = (value: string) => + platformSpecOptions.find((option) => option.label === value || option.aliases?.includes(value)) ?? defaultPlatformSpec; +const legacyPlatformAliases: Record = { + "淘宝/天猫": "淘宝/天猫", + "京东": "京东", + "拼多多": "拼多多", + "抖音电商": "抖音电商", + "亚马逊Amazon": "亚马逊 Amazon", + "速卖通": "速卖通", +}; +const normalizePlatform = (value: string) => getPlatformSpec(legacyPlatformAliases[value] ?? value).label; +const domesticPlatformLabels = new Set(["淘宝/天猫", "京东", "拼多多", "抖音电商"]); +const domesticPlatformLanguages = ["中文"]; +const isDomesticPlatform = (platformValue: string) => domesticPlatformLabels.has(normalizePlatform(platformValue)); +const getPlatformRatioGroup = (value: string, mode?: PlatformRatioModeKey): PlatformRatioGroup => { + const platformSpec = getPlatformSpec(value); + return (mode ? platformSpec.ratioGroups?.[mode] : null) ?? { + ratios: platformSpec.ratios, + defaultRatio: platformSpec.defaultRatio, + }; +}; +const getPlatformRatioOptions = (value: string, mode?: PlatformRatioModeKey) => getPlatformRatioGroup(value, mode).ratios; +const getPlatformDefaultRatio = (value: string, mode?: PlatformRatioModeKey) => getPlatformRatioGroup(value, mode).defaultRatio; +const getUniqueRatioOptions = (ratios: string[]) => Array.from(new Set(ratios)); +const normalizeRatioToken = (value: string) => + value + .replaceAll("\u00a0", " ") + .replaceAll("脳", "×") + .replaceAll("*", "×") + .replaceAll(":", ":") + .replace(/锛\?/g, ":") + .replace(/\s+/g, " ") + .trim(); +const normalizeRatioForPlatform = (platformValue: string, ratioValue: string, mode?: PlatformRatioModeKey) => { + const platformRatios = getPlatformRatioOptions(platformValue, mode); + if (platformRatios.includes(ratioValue)) return ratioValue; + const normalizedRatio = normalizeRatioToken(ratioValue); + const matchedRatio = platformRatios.find((option) => normalizeRatioToken(option).includes(normalizedRatio)); + return matchedRatio ?? getPlatformDefaultRatio(platformValue, mode); +}; +const quickSetRatioOptions = ["1:1", "3:4", "4:3", "9:16", "16:9"]; +const getQuickSetRatioValue = (value: string) => { + const normalizedValue = normalizeRatioToken(value); + if (quickSetRatioOptions.includes(normalizedValue)) return normalizedValue; + const sizeMatch = normalizedValue.match(/(\d+)\s*[×xX]\s*(\d+)/u); + if (sizeMatch) { + const width = Number(sizeMatch[1]); + const height = Number(sizeMatch[2]); + if (Number.isFinite(width) && Number.isFinite(height) && width > 0 && height > 0) { + const aspect = formatAspectRatio(width, height); + if (quickSetRatioOptions.includes(aspect)) return aspect; + } + } + const ratioMatch = normalizedValue.match(/(\d+)\s*[::]\s*(\d+)/u); + if (ratioMatch) { + const aspect = `${Number(ratioMatch[1])}:${Number(ratioMatch[2])}`; + if (quickSetRatioOptions.includes(aspect)) return aspect; + } + return quickSetRatioOptions[0]!; +}; +const formatRatioDisplayValue = (value: string) => { + const normalizedValue = normalizeRatioToken(value); + const sizeMatch = normalizedValue.match(/(\d+)\s*[×xX]\s*(\d+)\s*px?/u); + if (sizeMatch) { + const width = Number(sizeMatch[1]); + const height = Number(sizeMatch[2]); + return `${width}×${height}px\u00a0\u00a0\u00a0${formatAspectRatio(width, height)}`; + } + return normalizedValue + .replace("淘宝主图 / SKU 图 ", "淘宝主图 / SKU 图 ") + .replace("京东主图 / SKU 图 ", "京东主图 / SKU 图 ") + .replace("详情页宽", "详情页宽") + .replace("短视频", "短视频") + .replace("主图", "主图") + .replace("商品主图", "商品主图") + .replace("鍟嗗搧鍥?", "商品图") + .replace(/\s+:/g, ":") + .replace(/:\s+/g, ":"); +}; +const getRatioDisplayParts = (value: string) => { + const display = formatRatioDisplayValue(value).replace(/\u00a0/g, " ").replace(/\s+/g, " ").trim(); + const aspectMatch = display.match(/(\d+\s*[::]\s*\d+)(?!.*\d+\s*[::]\s*\d+)/u); + const aspect = aspectMatch?.[1]?.replace(/\s+/g, "") ?? "自适应"; + const size = aspectMatch ? display.replace(aspectMatch[0], "").trim() : display; + return { + size: size || "原图比例", + aspect, + }; +}; +/** Extract CSS aspect-ratio from a ratio string like "1000x1000px 1:1" -> "1 / 1" */ +const parseRatioToAspectCss = (ratioStr: string): string => { + const match = ratioStr.match(/(\d+)\D+(\d+)/u); + if (!match) return "1 / 1"; + return `${match[1]} / ${match[2]}`; +}; +const supportedImageApiRatios = ["1:1", "3:4", "4:3", "9:16", "16:9"] as const; +type SupportedImageApiRatio = typeof supportedImageApiRatios[number]; + +const toSupportedImageApiRatio = (width: number, height: number): SupportedImageApiRatio => { + if (!Number.isFinite(width) || !Number.isFinite(height) || width <= 0 || height <= 0) return "1:1"; + let bestRatio: SupportedImageApiRatio = "1:1"; + let bestScore = Number.POSITIVE_INFINITY; + const target = Math.log(width / height); + for (const ratio of supportedImageApiRatios) { + const [left, right] = ratio.split(":").map(Number); + const score = Math.abs(target - Math.log(left / right)); + if (score < bestScore) { + bestRatio = ratio; + bestScore = score; + } + } + return bestRatio; +}; + +/** Normalize ratio display string ("1000×1000px 1:1") to an image API aspect ratio ("1:1"). */ +const normalizeRatioForApi = (ratioStr: string): string => { + const normalizedValue = normalizeRatioToken(ratioStr); + const explicitRatios = Array.from(normalizedValue.matchAll(/(\d+(?:\.\d+)?)\s*:\s*(\d+(?:\.\d+)?)/g)); + const explicitRatio = explicitRatios.at(-1); + if (explicitRatio) { + return toSupportedImageApiRatio(Number(explicitRatio[1]), Number(explicitRatio[2])); + } + + const sizeMatch = normalizedValue.match(/(\d+(?:\.\d+)?)\s*[×xX*]\s*(\d+(?:\.\d+)?)/u); + if (!sizeMatch) return "1:1"; + return toSupportedImageApiRatio(Number(sizeMatch[1]), Number(sizeMatch[2])); +}; +const greatestCommonDivisor = (left: number, right: number): number => { + let a = Math.abs(left); + let b = Math.abs(right); + while (b) { + [a, b] = [b, a % b]; + } + return a || 1; +}; +const formatAspectRatio = (width: number, height: number) => { + const divisor = greatestCommonDivisor(width, height); + return `${Math.round(width / divisor)}:${Math.round(height / divisor)}`; +}; +const formatUploadedImageRatio = (image?: CloneImageItem) => { + if (!image) return null; + const format = image.format ? `\u00a0\u00a0\u00a0${image.format}` : ""; + if (!image.width || !image.height) return `上传图片\u00a0\u00a0\u00a0原图比例${format}`; + return `上传图片 ${image.width}×${image.height}px\u00a0\u00a0\u00a0${formatAspectRatio(image.width, image.height)}${format}`; +}; +const defaultMarketLanguageOption = marketLanguageOptions[0]!; +const normalizeMarket = (value: string) => + marketLanguageOptions.some((option) => option.country === value) ? value : defaultMarketLanguageOption.country; +const normalizeLanguage = (value: string) => languageAliases[value] ?? value; +const uniqueLanguages = (languages: string[]) => Array.from(new Set(languages)); +const appendEnglish = (languages: string[]) => Array.from(new Set([...languages, "英文"])); +const getMarketLanguageOptions = (marketValue: string) => + appendEnglish((marketLanguageOptions.find((option) => option.country === marketValue) ?? defaultMarketLanguageOption).languages); +const getPlatformLanguageOptions = (platformValue: string, marketValue: string) => { + const marketLanguages = getMarketLanguageOptions(marketValue); + if (!isDomesticPlatform(platformValue)) return marketLanguages; + const localLanguages = marketLanguages.filter((item) => item !== "英文"); + return uniqueLanguages([...localLanguages, ...domesticPlatformLanguages, "英文"]); +}; +const getPlatformDefaultLanguage = (platformValue: string, marketValue: string) => + isDomesticPlatform(platformValue) ? "中文" : (getPlatformLanguageOptions(platformValue, marketValue)[0] ?? languageOptions[0] ?? "英文"); +const normalizeLanguageForPlatform = (platformValue: string, marketValue: string, languageValue: string) => { + const normalizedLanguage = normalizeLanguage(languageValue); + const platformLanguages = getPlatformLanguageOptions(platformValue, marketValue); + return platformLanguages.includes(normalizedLanguage) ? normalizedLanguage : getPlatformDefaultLanguage(platformValue, marketValue); +}; const productSetOutputOptions: Array<{ key: ProductSetOutputKey; label: string; desc: string; icon: ReactNode }> = [ { key: "set", label: "套图", desc: "主图/卖点/场景", icon: }, { key: "detail", label: "详情图", desc: "长图模块化生成", icon: }, @@ -523,112 +1044,193 @@ const productSetOutputOptions: Array<{ key: ProductSetOutputKey; label: string; const cloneOutputOptions: Array<{ key: ProductSetOutputKey; label: string; desc: string; icon: ReactNode }> = [ ...productSetOutputOptions, ]; -const cloneTemplateCards: Record, CloneTemplateAsset[]> = { - set: [ - { - id: "set-main", - title: "商品套图主图", - prompt: "生成一组统一风格的商品套图,包含主图、卖点图、场景图和细节图,主体清晰,色调统一,符合电商平台展示规范。", - mediaUrl: ossAssets.ecommerce.productSet.main, - }, - { - id: "set-scene", - title: "商品套图场景", - prompt: "生成生活化场景商品套图,突出商品在真实环境中的使用感、氛围感和转化卖点。", - mediaUrl: ossAssets.ecommerce.productSet.scene, - }, - { - id: "set-detail", - title: "商品套图细节", - prompt: "生成突出材质、工艺和边缘细节的商品套图,画面干净,信息聚焦,适合电商详情展示。", - mediaUrl: ossAssets.ecommerce.productSet.detail, - }, - { - id: "set-selling", - title: "商品套图卖点", - prompt: "生成强调核心卖点和对比优势的商品套图,信息层级清晰,适合列表页和转化场景。", - mediaUrl: ossAssets.ecommerce.productSet.selling, - }, - ], - detail: [ - { - id: "detail-hero", - title: "详情图头图", - prompt: "生成适用于 A+ 详情页的头图模块,突出品牌感、主卖点和视觉中心,版式清晰高级。", - mediaUrl: ossAssets.ecommerce.detail.longPage, - }, - { - id: "detail-grid-a", - title: "详情图模块 A", - prompt: "生成模块化详情长图,重点展示产品卖点、功能说明和适用场景,适合滚动阅读。", - mediaUrl: ossAssets.ecommerce.detail.gridA, - }, - { - id: "detail-grid-b", - title: "详情图模块 B", - prompt: "生成模块化详情长图,强化材质、规格和使用说明,视觉简洁,信息明确。", - mediaUrl: ossAssets.ecommerce.detail.gridB, - }, - { - id: "detail-grid-c", - title: "详情图模块 C", - prompt: "生成模块化详情页内容,突出品牌叙事、细节拆解和购买理由,保持统一排版。", - mediaUrl: ossAssets.ecommerce.detail.gridC, - }, - ], - model: [ - { - id: "model-dress-a", - title: "模特图穿搭 A", - prompt: "生成真人模特穿搭展示图,突出服装版型、上身效果和整体气质,姿态自然。", - mediaUrl: ossAssets.ecommerce.tryOn.dressA, - }, - { - id: "model-dress-b", - title: "模特图穿搭 B", - prompt: "生成适合商品展示的模特图,强调衣型、垂感和真实穿着效果,画面干净。", - mediaUrl: ossAssets.ecommerce.tryOn.dressB, - }, - { - id: "model-woman", - title: "模特图女模", - prompt: "生成自然站姿的女模特展示图,适合服饰、配件和穿搭类商品展示。", - mediaUrl: ossAssets.ecommerce.tryOn.modelWoman, - }, - { - id: "model-man", - title: "模特图男模", - prompt: "生成真实感更强的男模特展示图,突出上身效果、轮廓和场景氛围。", - mediaUrl: ossAssets.ecommerce.tryOn.modelMan, - }, - ], - video: [ - { - id: "video-hook", - title: "短视频开场", - prompt: "生成适合电商短视频的开场镜头,节奏明确,第一秒就突出产品和核心看点。", - mediaUrl: ossAssets.ecommerce.inspiration.tiktokPreference, - }, - { - id: "video-scene", - title: "短视频场景", - prompt: "生成生活化使用场景的短视频分镜,画面连贯,围绕商品使用过程展开。", - mediaUrl: ossAssets.ecommerce.inspiration.officeStyleSet, - }, - { - id: "video-review", - title: "短视频口播", - prompt: "生成适合口播讲解的电商短视频结构,包含产品亮点、卖点说明和收尾引导。", - mediaUrl: ossAssets.ecommerce.inspiration.asinListing, - }, - { - id: "video-conversion", - title: "短视频转化", - prompt: "生成以转化为目标的短视频分镜,强化开头钩子、卖点展示和行动引导。", - mediaUrl: ossAssets.ecommerce.inspiration.competitorListing, - }, - ], +const commerceScenarioOptions: Array<{ key: CommerceScenarioKey; label: string; desc: string; icon: ReactNode }> = [ + { key: "popular", label: "热门", desc: "高频模板", icon: }, + { key: "poster", label: "海报生成", desc: "活动视觉", icon: }, + { key: "mainImage", label: "商品主图", desc: "主图转化", icon: }, + { key: "scene", label: "场景图", desc: "生活氛围", icon: }, + { key: "festival", label: "节日风格图", desc: "节点营销", icon: }, + { key: "model", label: "模特图", desc: "真人展示", icon: }, + { key: "background", label: "更换背景", desc: "背景重构", icon: }, + { key: "retouch", label: "无痕改图", desc: "精修优化", icon: }, + { key: "salesVideo", label: "带货视频", desc: "短视频脚本", icon: }, +]; +const commerceScenarioOutputMap: Record, ProductSetOutputKey> = { + poster: "set", + mainImage: "set", + scene: "set", + festival: "set", + model: "model", + background: "set", + retouch: "set", + salesVideo: "video", }; +const commerceScenarioTemplates: CommerceScenarioTemplate[] = [ + { + id: "poster-campaign-clean", + scenario: "poster", + output: "set", + title: "新品活动海报", + desc: "适合首发、上新、促销专题的主视觉", + badge: "高频推荐", + prompt: "帮我生成一张电商新品活动海报,突出产品主体、核心卖点和促销氛围,画面干净高级,适合店铺首页和广告投放。", + mediaUrl: ossAssets.ecommerce.detail.longPage, + }, + { + id: "poster-social-drop", + scenario: "poster", + output: "set", + title: "社媒种草海报", + desc: "更适合小红书、朋友圈、站外广告", + badge: "热门模板", + prompt: "生成一张社媒种草风格商品海报,突出产品质感、生活方式和一句清晰卖点,画面轻盈、有品牌感。", + mediaUrl: ossAssets.ecommerce.inspiration.officeStyleSet, + }, + { + id: "main-clean-product", + scenario: "mainImage", + output: "set", + title: "高转化商品主图", + desc: "白底/浅场景,主体清楚,卖点明确", + badge: "高频推荐", + prompt: "生成一张高转化商品主图,产品主体居中清晰,背景简洁,突出核心卖点和材质细节,适合电商搜索列表展示。", + mediaUrl: ossAssets.ecommerce.productSet.main, + }, + { + id: "main-selling-point", + scenario: "mainImage", + output: "set", + title: "卖点强化主图", + desc: "适合列表点击率优化", + badge: "点击率优先", + prompt: "生成一张卖点强化商品主图,保留产品真实质感,加入清晰卖点表达和轻量信息层级,适合提升列表点击率。", + mediaUrl: ossAssets.ecommerce.productSet.selling, + }, + { + id: "scene-lifestyle", + scenario: "scene", + output: "set", + title: "生活方式场景图", + desc: "把商品放进真实使用环境", + badge: "高频推荐", + prompt: "生成生活方式商品场景图,把产品自然放入真实使用环境,突出使用感、氛围和购买理由,画面真实且商业化。", + mediaUrl: ossAssets.ecommerce.productSet.scene, + }, + { + id: "scene-premium", + scenario: "scene", + output: "set", + title: "高级质感场景", + desc: "适合品牌调性和详情页氛围图", + badge: "品牌感", + prompt: "生成高级质感商品场景图,背景克制、光影柔和,突出产品材质、轮廓和品牌调性,适合详情页和广告素材。", + mediaUrl: ossAssets.ecommerce.detail.gridA, + }, + { + id: "festival-seasonal", + scenario: "festival", + output: "set", + title: "节日营销图", + desc: "适合大促、节庆、节点活动", + badge: "节点营销", + prompt: "生成节日营销风格商品图,结合节日氛围和促销视觉,但保持产品主体清晰、信息不过载,适合电商活动投放。", + mediaUrl: ossAssets.ecommerce.detail.gridB, + }, + { + id: "festival-gift", + scenario: "festival", + output: "set", + title: "礼赠氛围图", + desc: "适合礼盒、礼品、节日送礼场景", + badge: "热门模板", + prompt: "生成礼赠氛围商品图,突出节日送礼感、包装质感和温暖情绪,画面高级克制,适合活动页与社媒投放。", + mediaUrl: ossAssets.ecommerce.detail.gridC, + }, + { + id: "model-natural-fit", + scenario: "model", + output: "model", + title: "自然穿搭模特图", + desc: "突出上身效果、版型和真实穿着", + badge: "高频推荐", + prompt: "生成自然穿搭模特图,突出服饰上身效果、版型和整体气质,模特姿态自然,适合服饰电商详情与主图展示。", + mediaUrl: ossAssets.ecommerce.tryOn.dressA, + }, + { + id: "model-street", + scenario: "model", + output: "model", + title: "街拍模特场景", + desc: "更适合年轻化、生活方式品牌", + badge: "风格推荐", + prompt: "生成街拍风格模特图,模特自然展示商品,背景有生活气息,突出穿搭氛围、比例和品牌调性。", + mediaUrl: ossAssets.ecommerce.tryOn.modelWoman, + }, + { + id: "background-clean", + scenario: "background", + output: "set", + title: "商品换浅色背景", + desc: "保留主体,重构干净商业背景", + badge: "高频推荐", + prompt: "为商品更换干净浅色商业背景,保留产品主体、边缘和材质细节,整体画面适合电商主图和广告素材。", + mediaUrl: ossAssets.ecommerce.productSet.detail, + }, + { + id: "background-scene", + scenario: "background", + output: "set", + title: "商品换场景背景", + desc: "从普通拍摄变成真实使用场景", + badge: "场景增强", + prompt: "为商品更换真实使用场景背景,保持主体比例和边缘自然,增强生活化氛围和商业转化感。", + mediaUrl: ossAssets.ecommerce.productSet.scene, + }, + { + id: "retouch-clean", + scenario: "retouch", + output: "set", + title: "白底精修图", + desc: "修正瑕疵、增强质感和边缘细节", + badge: "高频推荐", + prompt: "对商品图进行无痕精修,清理瑕疵、优化光影和边缘细节,保持商品真实结构,输出干净高级的电商图。", + mediaUrl: ossAssets.ecommerce.productSet.main, + }, + { + id: "retouch-premium", + scenario: "retouch", + output: "set", + title: "质感增强图", + desc: "强化材质、反光和商品高级感", + badge: "精修模板", + prompt: "对商品图进行质感增强,强化材质、光泽、纹理和立体感,画面自然不过度修饰,适合商业广告素材。", + mediaUrl: ossAssets.ecommerce.productSet.selling, + }, + { + id: "sales-video-hook", + scenario: "salesVideo", + output: "video", + title: "带货视频开场", + desc: "第一秒抓住注意力,快速进入卖点", + badge: "高频推荐", + prompt: "生成电商带货短视频脚本和分镜,第一秒突出产品和痛点,随后展示核心卖点、使用场景和行动引导。", + mediaUrl: ossAssets.ecommerce.inspiration.tiktokPreference, + }, + { + id: "sales-video-demo", + scenario: "salesVideo", + output: "video", + title: "使用演示视频", + desc: "适合讲解型、种草型短视频", + badge: "转化优先", + prompt: "生成商品使用演示短视频分镜,围绕使用过程、关键卖点和效果对比展开,节奏清晰,适合带货转化。", + mediaUrl: ossAssets.ecommerce.inspiration.asinListing, + }, +]; +const popularCommerceScenarioTemplates = commerceScenarioOptions + .filter((option): option is { key: Exclude; label: string; desc: string; icon: ReactNode } => option.key !== "popular") + .map((option) => commerceScenarioTemplates.find((template) => template.scenario === option.key)) + .filter((template): template is CommerceScenarioTemplate => Boolean(template)); const cloneSetCountOptions: Array<{ key: CloneSetCountKey; title: string; @@ -650,6 +1252,9 @@ const maxCloneProductImages = 20; const maxCloneReferenceImages = 20; const cloneVideoDurationMin = 5; const cloneVideoDurationMax = 45; +const defaultEcommercePlatform = "淘宝/天猫"; +const defaultProductSetOutput: ProductSetOutputKey = "set"; +const defaultCloneOutput: CloneOutputKey = "set"; const cloneLatestSettingStorageKey = "omniai.clone-ai.latest-setting"; const ecommerceHistoryStorageKey = "omniai.ecommerce.history.records"; const cloneVideoQualityOptions: Array<{ key: CloneVideoQualityKey; label: string; desc: string }> = [ @@ -1077,7 +1682,6 @@ function ProductClonePage(_props: ProductClonePageProps = {}) { const countHoldTimeoutRef = useRef(null); const countHoldIntervalRef = useRef(null); const isAuthenticated = Boolean((_props as Record).isAuthenticated); - const onWorkspaceChromeChange = _props.onWorkspaceChromeChange; const requestLogin = () => { const handler = (_props as Record).onRequireLogin; if (typeof handler === "function") handler(); @@ -1109,16 +1713,6 @@ function ProductClonePage(_props: ProductClonePageProps = {}) { const [showHostingModal, setShowHostingModal] = useState(false); const [productImages, setProductImages] = useState([]); const [activeQuickTool, setActiveQuickTool] = useState<"cutout" | "detail" | "watermark" | "image-edit" | "translate" | "hot" | null>(null); - useEffect(() => { - const handleWorkspaceHome = () => { - setActiveTool("clone"); - setActiveQuickTool(null); - setActiveHistoryRecordId(null); - }; - - window.addEventListener("ecommerce-workspace-home", handleWorkspaceHome); - return () => window.removeEventListener("ecommerce-workspace-home", handleWorkspaceHome); - }, []); const [smartCutoutImage, setSmartCutoutImage] = useState(null); const [smartCutoutBatchImages, setSmartCutoutBatchImages] = useState([]); const [smartCutoutBackgroundColor, setSmartCutoutBackgroundColor] = useState("#ffffff"); @@ -1154,8 +1748,9 @@ function ProductClonePage(_props: ProductClonePageProps = {}) { const [imageWorkbenchResultUrl, setImageWorkbenchResultUrl] = useState(null); const [imageWorkbenchProgress, setImageWorkbenchProgress] = useState(0); const [isProductUploadDragging, setIsProductUploadDragging] = useState(false); + const [activeCommerceScenario, setActiveCommerceScenario] = useState("popular"); const [cloneOutput, setCloneOutput] = useState(defaultCloneOutput); - const [isCloneTemplateStripVisible, setIsCloneTemplateStripVisible] = useState(false); + const [isCloneTemplateStripVisible, setIsCloneTemplateStripVisible] = useState(true); const [videoHistoryVisible, setVideoHistoryVisible] = useState(false); const [isVideoWorkspaceVisible, setIsVideoWorkspaceVisible] = useState(false); const [videoPlanTrigger, setVideoPlanTrigger] = useState(0); @@ -1659,7 +2254,9 @@ function ProductClonePage(_props: ProductClonePageProps = {}) { const selectedProductSetOutput = productSetOutputOptions.find((option) => option.key === productSetOutput) ?? productSetOutputOptions[0]!; const selectedCloneOutput = cloneOutputOptions.find((option) => option.key === cloneOutput) ?? cloneOutputOptions[1]!; - const activeCloneTemplateCards = cloneTemplateCards[cloneOutput === "hot" ? "set" : cloneOutput]; + const activeCommerceScenarioTemplates = activeCommerceScenario === "popular" + ? popularCommerceScenarioTemplates + : commerceScenarioTemplates.filter((template) => template.scenario === activeCommerceScenario); const cloneRequirementPlaceholder = cloneOutput === "model" ? "建议包含以下信息:产品名称、核心卖点、期望场景、模特外貌描述(如小麦色皮肤、齐刘海、眼角有泪痣)、具体参数" @@ -3053,13 +3650,18 @@ function ProductClonePage(_props: ProductClonePageProps = {}) { ); }; - const handleCloneModeTabClick = (nextOutput: CloneOutputKey) => { - if (nextOutput === cloneOutput) { + const handleCommerceScenarioClick = (nextScenario: CommerceScenarioKey) => { + if (nextScenario === activeCommerceScenario) { setIsCloneTemplateStripVisible((visible) => !visible); + setComposerMenu(null); return; } - handleCloneOutputChange(nextOutput); + setActiveCommerceScenario(nextScenario); + setIsCloneTemplateStripVisible(true); setComposerMenu(null); + if (nextScenario === "popular") return; + const mappedOutput = commerceScenarioOutputMap[nextScenario]; + if (mappedOutput !== cloneOutput) handleCloneOutputChange(mappedOutput); }; const handleCloneMarketChange = (nextMarket: string) => { @@ -5102,6 +5704,12 @@ function ProductClonePage(_props: ProductClonePageProps = {}) { textarea.setSelectionRange(nextValue.length, nextValue.length); textarea.scrollIntoView({ behavior: "smooth", block: "center" }); } + window.setTimeout(() => { + const latestTextarea = requirementTextareaRef.current; + if (!latestTextarea) return; + latestTextarea.focus(); + latestTextarea.setSelectionRange(nextValue.length, nextValue.length); + }, 80); }); }; @@ -5137,7 +5745,10 @@ function ProductClonePage(_props: ProductClonePageProps = {}) { } }; - const handleCloneTemplateCardClick = (card: CloneTemplateAsset) => { + const handleCloneTemplateCardClick = (card: CommerceScenarioTemplate) => { + if (card.output !== cloneOutput) handleCloneOutputChange(card.output); + setIsCloneTemplateStripVisible(true); + setComposerMenu(null); void addTemplateImageToComposer(card); applyComposerPrompt(card.prompt); }; @@ -5474,19 +6085,23 @@ function ProductClonePage(_props: ProductClonePageProps = {}) { onChange={handleSmartCutoutUpload} aria-label="上传智能抠图素材" /> -
- {cloneOutputOptions.map((option) => ( +
+ {commerceScenarioOptions.map((option) => ( ))}
+
{productImages.length ? (
@@ -5580,8 +6195,8 @@ function ProductClonePage(_props: ProductClonePageProps = {}) { {renderComposerMenu()}
{(status === "idle" || status === "ready") && !showMainVideoWorkspace && isCloneTemplateStripVisible ? ( -
- {activeCloneTemplateCards.map((card) => ( +
+ {activeCommerceScenarioTemplates.map((card) => ( ))}
@@ -7210,20 +7832,6 @@ function ProductClonePage(_props: ProductClonePageProps = {}) { const isRecordDetailWorkspace = isMainCloneWorkspace && Boolean(activeHistoryRecordId); const currentResultCount = canvasNodes.reduce((count, node) => count + node.results.length, 0); const activeHistoryRecord = activeHistoryRecordId ? ecommerceHistoryRecords.find((record) => record.id === activeHistoryRecordId) : null; - const isFocusedToolPage = - isRecordDetailWorkspace || isSmartCutoutTool || isQuickDetailTool || isWatermarkTool || isTranslateTool || isImageEditTool || isHotCloneTool; - - useEffect(() => { - onWorkspaceChromeChange?.({ - isToolPage: isFocusedToolPage, - }); - - return () => { - onWorkspaceChromeChange?.({ - isToolPage: false, - }); - }; - }, [isFocusedToolPage, onWorkspaceChromeChange]); const activeConversationTurns = activeHistoryRecord ? activeHistoryRecord.turns?.length ? activeHistoryRecord.turns diff --git a/src/styles/ecommerce-standalone.css b/src/styles/ecommerce-standalone.css index 0c3d15f..b7a9817 100644 --- a/src/styles/ecommerce-standalone.css +++ b/src/styles/ecommerce-standalone.css @@ -12,7 +12,9 @@ } .ecommerce-standalone__topbar { - position: relative; + position: fixed; + inset: 0 0 auto; + z-index: 80; display: flex; align-items: center; justify-content: space-between; @@ -20,7 +22,8 @@ min-height: 64px; padding: 10px clamp(16px, 3vw, 32px); border-bottom: 1px solid rgba(255, 255, 255, 0.08); - background: transparent; + background: rgba(8, 12, 10, 0.78); + backdrop-filter: blur(18px); } .ecommerce-standalone__brand, @@ -63,6 +66,7 @@ .ecommerce-standalone__content { height: 100vh; + padding-top: 64px; } /* 工作台与个人中心常驻同层,用 hidden 切换以保活生成任务状态。 @@ -226,6 +230,7 @@ } .ecommerce-standalone__content { + padding-top: 58px; } } @@ -244,7 +249,8 @@ .ecommerce-standalone__topbar { border-bottom-color: rgba(126, 235, 255, 0.22); - background: transparent; + background: + linear-gradient(90deg, rgba(7, 72, 121, 0.94), rgba(4, 37, 75, 0.92)); } .ecommerce-standalone__brand::before { @@ -312,7 +318,7 @@ .ecommerce-standalone__topbar { border-bottom-color: rgba(30, 189, 219, 0.16) !important; - background: transparent !important; + background: #f8f9fa !important; } .ecommerce-standalone__brand::before { @@ -12257,12 +12263,26 @@ html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[d /* #/imageWorkbench detail popover and topbar blend: no inner scrollbar, no hard header split. */ html body #root .ecommerce-standalone.web-shell .ecommerce-standalone__topbar { border-bottom-color: transparent !important; - background: transparent !important; + background: + radial-gradient(48rem 14rem at 50% 100%, rgba(30, 189, 219, 0.09), transparent 72%), + radial-gradient(28rem 12rem at 12% 100%, rgba(16, 115, 204, 0.045), transparent 68%), + linear-gradient(180deg, #fbfdfe 0%, #f8fbfc 100%) !important; box-shadow: none !important; backdrop-filter: none !important; -webkit-backdrop-filter: none !important; } +html body #root .ecommerce-standalone.web-shell .ecommerce-standalone__topbar::after { + position: absolute !important; + right: 0 !important; + bottom: -1px !important; + left: 0 !important; + height: 1px !important; + background: linear-gradient(90deg, transparent, rgba(30, 189, 219, 0.08), transparent) !important; + content: "" !important; + pointer-events: none !important; +} + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .clone-ai-input-wrapper.ecom-command-composer > .ecom-command-popover.ecom-command-popover--settings-detail { width: min(468px, calc(100vw - 48px)) !important; max-width: min(468px, calc(100vw - 48px)) !important; @@ -17414,520 +17434,357 @@ html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[d } } -/* Hide the topbar banner background while keeping brand and account in place. */ -html body #root div.ecommerce-standalone.web-shell[data-view="ecommerce"] .ecommerce-standalone__topbar { - border-bottom: none !important; +/* Ecommerce home scenario templates */ +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"]:not(.is-history-detail) .ecom-command-scenario-tabs.ecom-command-mode-tabs { + display: flex !important; + align-items: stretch !important; + justify-content: center !important; + gap: 9px !important; + width: min(100%, 1180px) !important; + margin: 0 auto 10px !important; + padding: 5px 0 !important; + overflow-x: auto !important; + scrollbar-width: none !important; + scroll-snap-type: x proximity !important; + border: 0 !important; + border-radius: 0 !important; background: transparent !important; - background-color: transparent !important; - background-image: none !important; box-shadow: none !important; - backdrop-filter: none !important; - -webkit-backdrop-filter: none !important; } -html body #root div.ecommerce-standalone.web-shell[data-view="ecommerce"] .ecommerce-standalone__topbar::before, -html body #root div.ecommerce-standalone.web-shell[data-view="ecommerce"] .ecommerce-standalone__topbar::after { - content: none !important; +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"]:not(.is-history-detail) .ecom-command-scenario-tabs.ecom-command-mode-tabs::-webkit-scrollbar { display: none !important; } -/* Keep topbar transparent and remove any background/border from inner controls. */ -html body #root div.ecommerce-standalone.web-shell[data-view="ecommerce"] .ecommerce-standalone__brand, -html body #root div.ecommerce-standalone.web-shell[data-view="ecommerce"] .ecommerce-standalone__brand strong, -html body #root div.ecommerce-standalone.web-shell[data-view="ecommerce"] .ecommerce-standalone__credits, -html body #root div.ecommerce-standalone.web-shell[data-view="ecommerce"] .ecommerce-standalone__account button:not(.ecommerce-standalone__login-button):not(.ecommerce-profile-menu__trigger) { - color: #10202c !important; - background: transparent !important; - background-color: transparent !important; - background-image: none !important; - border: none !important; - border-color: transparent !important; - box-shadow: none !important; - backdrop-filter: none !important; - -webkit-backdrop-filter: none !important; +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"]:not(.is-history-detail) .ecom-command-scenario-tabs.ecom-command-mode-tabs button { + --mode-accent: #1073cc; + position: relative !important; + display: grid !important; + grid-template-columns: 24px minmax(0, 1fr) !important; + grid-template-rows: auto !important; + align-items: center !important; + justify-items: start !important; + gap: 8px !important; + flex: 0 0 auto !important; + width: auto !important; + min-width: 104px !important; + min-height: 40px !important; + padding: 7px 12px !important; + scroll-snap-align: start !important; + border: 1px solid rgba(16, 32, 44, 0.07) !important; + border-radius: 20px !important; + background: rgba(255, 255, 255, 0.6) !important; + color: rgba(16, 32, 44, 0.68) !important; + box-shadow: + 0 2px 6px rgba(16, 32, 44, 0.03), + inset 0 1px 0 rgba(255, 255, 255, 0.92) !important; + text-align: left !important; + cursor: pointer !important; + transition: + background 180ms ease, + border-color 180ms ease, + color 180ms ease, + box-shadow 180ms ease, + transform 180ms ease !important; } -html body #root div.ecommerce-standalone.web-shell[data-view="ecommerce"] .ecommerce-standalone__brand:hover, -html body #root div.ecommerce-standalone.web-shell[data-view="ecommerce"] .ecommerce-standalone__account button:not(.ecommerce-standalone__login-button):not(.ecommerce-profile-menu__trigger):hover { - background: transparent !important; - background-color: transparent !important; - background-image: none !important; - box-shadow: none !important; +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"]:not(.is-history-detail) .ecom-command-scenario-tabs.ecom-command-mode-tabs button:hover { + background: rgba(255, 255, 255, 0.86) !important; + border-color: color-mix(in srgb, var(--mode-accent) 22%, transparent) !important; + color: rgba(16, 32, 44, 0.86) !important; + box-shadow: + 0 8px 18px color-mix(in srgb, var(--mode-accent) 10%, transparent), + inset 0 1px 0 rgba(255, 255, 255, 0.95) !important; + transform: translateY(-1px) !important; } -html body #root div.ecommerce-standalone.web-shell[data-view="ecommerce"] .ecommerce-standalone__credits { - color: #3a5a6a !important; +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"]:not(.is-history-detail) .ecom-command-scenario-tabs.ecom-command-mode-tabs button.is-active { + background: + radial-gradient(circle at 24% 16%, color-mix(in srgb, var(--mode-accent) 14%, transparent), transparent 54%), + rgba(255, 255, 255, 0.98) !important; + border-color: color-mix(in srgb, var(--mode-accent) 35%, transparent) !important; + color: rgba(16, 32, 44, 0.96) !important; + box-shadow: + 0 10px 24px color-mix(in srgb, var(--mode-accent) 14%, transparent), + inset 0 1px 0 rgba(255, 255, 255, 0.98) !important; + transform: translateY(-1px) !important; } -/* Topbar composition: quiet brand chip + single account capsule. */ -html body #root div.ecommerce-standalone.web-shell[data-view="ecommerce"] .ecommerce-standalone__topbar { - padding: 14px clamp(18px, 2.5vw, 30px) !important; +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"]:not(.is-history-detail) .ecom-command-scenario-tabs.ecom-command-mode-tabs button.is-open { + background: + radial-gradient(circle at 24% 16%, color-mix(in srgb, var(--mode-accent) 18%, transparent), transparent 50%), + rgba(255, 255, 255, 1) !important; + border-color: color-mix(in srgb, var(--mode-accent) 45%, transparent) !important; + box-shadow: + 0 12px 28px color-mix(in srgb, var(--mode-accent) 16%, transparent), + inset 0 1px 0 rgba(255, 255, 255, 1) !important; } -html body #root div.ecommerce-standalone.web-shell[data-view="ecommerce"] { - --ecommerce-workspace-top-offset: 50px; +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"]:not(.is-history-detail) .ecom-command-scenario-tabs.ecom-command-mode-tabs button:focus-visible { + outline: 2px solid color-mix(in srgb, var(--mode-accent) 45%, transparent) !important; + outline-offset: 2px !important; } -html body #root div.ecommerce-standalone.web-shell[data-view="ecommerce"] .ecommerce-standalone__brand { - gap: 10px !important; - min-height: 42px !important; - padding: 5px 12px 5px 6px !important; - border: 1px solid rgba(30, 189, 219, 0.16) !important; - border-radius: 999px !important; - background: rgba(255, 255, 255, 0.62) !important; - box-shadow: 0 12px 34px rgba(16, 115, 204, 0.07) !important; - backdrop-filter: blur(18px) saturate(1.08) !important; - -webkit-backdrop-filter: blur(18px) saturate(1.08) !important; - transition: border-color 180ms ease, box-shadow 180ms ease, transform 180ms ease, background 180ms ease !important; - will-change: opacity, transform, filter !important; -} - -html body #root div.ecommerce-standalone.web-shell[data-view="ecommerce"] .ecommerce-standalone__brand:hover { - border-color: rgba(30, 189, 219, 0.28) !important; - background: rgba(255, 255, 255, 0.78) !important; - box-shadow: 0 16px 42px rgba(16, 115, 204, 0.1) !important; - transform: translateY(-1px); -} - -html body #root div.ecommerce-standalone.web-shell[data-view="ecommerce"] .ecommerce-standalone__logo { - width: 34px !important; - height: 34px !important; - border-radius: 12px !important; - box-shadow: 0 8px 18px rgba(16, 115, 204, 0.16) !important; -} - -html body #root div.ecommerce-standalone.web-shell[data-view="ecommerce"] .ecommerce-standalone__brand strong { - max-width: 168px !important; - overflow: hidden !important; - color: #10202c !important; +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"]:not(.is-history-detail) .ecom-command-scenario-tabs .ecom-command-mode-icon { + grid-row: auto !important; + display: inline-grid !important; + width: 24px !important; + min-width: 24px !important; + height: 24px !important; + place-items: center !important; + border: 0 !important; + border-radius: 8px !important; + background: color-mix(in srgb, var(--mode-accent) 10%, rgba(255, 255, 255, 0.9)) !important; + color: var(--mode-accent) !important; + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.8) !important; font-size: 13px !important; - font-weight: 800 !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"]:not(.is-history-detail) .ecom-command-scenario-tabs button.is-active .ecom-command-mode-icon, +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"]:not(.is-history-detail) .ecom-command-scenario-tabs button.is-open .ecom-command-mode-icon { + background: color-mix(in srgb, var(--mode-accent) 16%, rgba(255, 255, 255, 0.95)) !important; + box-shadow: + inset 0 1px 0 rgba(255, 255, 255, 0.9), + 0 2px 6px color-mix(in srgb, var(--mode-accent) 12%, transparent) !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"]:not(.is-history-detail) .ecom-command-scenario-tabs strong { + min-width: 0 !important; + max-width: 88px !important; + overflow: hidden !important; + color: rgba(16, 32, 44, 0.82) !important; + font-size: 12.5px !important; + font-weight: 760 !important; + letter-spacing: -0.01em !important; line-height: 1 !important; text-overflow: ellipsis !important; white-space: nowrap !important; } -html body #root div.ecommerce-standalone.web-shell[data-view="ecommerce"] .ecommerce-profile-menu { +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"]:not(.is-history-detail) .ecom-command-scenario-tabs button.is-active strong, +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"]:not(.is-history-detail) .ecom-command-scenario-tabs button.is-open strong { + color: rgba(16, 32, 44, 0.95) !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"]:not(.is-history-detail) .ecom-command-scenario-tabs .ecom-command-scenario-close { + position: absolute !important; + top: 4px !important; + right: 4px !important; + display: inline-flex !important; + align-items: center !important; + justify-content: center !important; + width: 15px !important; + height: 15px !important; + border-radius: 50% !important; + background: rgba(16, 32, 44, 0.05) !important; + color: rgba(16, 32, 44, 0.42) !important; + font-size: 9px !important; + transition: + background 160ms ease, + color 160ms ease, + transform 160ms ease !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"]:not(.is-history-detail) .ecom-command-scenario-tabs .ecom-command-scenario-close:hover { + background: rgba(16, 32, 44, 0.1) !important; + color: rgba(16, 32, 44, 0.7) !important; + transform: scale(1.08) !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"]:not(.is-history-detail) .ecom-command-scenario-scroll-hint { + display: none !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"]:not(.is-history-detail) .ecom-command-scenario-tabs .ecom-command-scenario-close .anticon { + display: inline-flex !important; + align-items: center !important; + justify-content: center !important; + line-height: 1 !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"]:not(.is-history-detail) .ecom-command-scenario-tabs button:has(.ecom-command-mode-icon--popular) { + --mode-accent: #c04468; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"]:not(.is-history-detail) .ecom-command-scenario-tabs button:has(.ecom-command-mode-icon--poster), +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"]:not(.is-history-detail) .ecom-command-scenario-tabs button:has(.ecom-command-mode-icon--festival) { + --mode-accent: #cc6b14; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"]:not(.is-history-detail) .ecom-command-scenario-tabs button:has(.ecom-command-mode-icon--mainImage), +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"]:not(.is-history-detail) .ecom-command-scenario-tabs button:has(.ecom-command-mode-icon--scene), +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"]:not(.is-history-detail) .ecom-command-scenario-tabs button:has(.ecom-command-mode-icon--background) { + --mode-accent: #0f8f72; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"]:not(.is-history-detail) .ecom-command-scenario-tabs button:has(.ecom-command-mode-icon--model), +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"]:not(.is-history-detail) .ecom-command-scenario-tabs button:has(.ecom-command-mode-icon--retouch), +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"]:not(.is-history-detail) .ecom-command-scenario-tabs button:has(.ecom-command-mode-icon--salesVideo) { + --mode-accent: #1073cc; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"]:not(.is-history-detail) .ecom-command-template-strip { + grid-template-columns: repeat(4, minmax(0, 1fr)) !important; + gap: 12px !important; + width: min(100%, 1180px) !important; + margin: 16px auto 10px !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"]:not(.is-history-detail) .ecom-command-template-card { + display: grid !important; + grid-template-columns: 94px minmax(0, 1fr) !important; + align-items: stretch !important; + gap: 12px !important; + aspect-ratio: auto !important; + min-height: 132px !important; + padding: 10px !important; + border-radius: 18px !important; + text-align: left !important; + background: + radial-gradient(circle at 20% 0%, rgba(30, 189, 219, 0.08), transparent 46%), + linear-gradient(180deg, rgba(255, 255, 255, 0.98), rgba(247, 252, 254, 0.94)) !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"]:not(.is-history-detail) .ecom-command-template-card__media { position: relative !important; - gap: 0 !important; -} - -html body #root div.ecommerce-standalone.web-shell[data-view="ecommerce"] .ecommerce-profile-menu__trigger { - gap: 10px !important; - min-height: 46px !important; - padding: 4px 6px 4px 14px !important; - border: 1px solid rgba(30, 189, 219, 0.16) !important; - border-radius: 999px !important; - background: rgba(255, 255, 255, 0.66) !important; - box-shadow: 0 12px 34px rgba(16, 115, 204, 0.08) !important; - backdrop-filter: blur(18px) saturate(1.08) !important; - -webkit-backdrop-filter: blur(18px) saturate(1.08) !important; - transition: border-color 180ms ease, box-shadow 180ms ease, transform 180ms ease, background 180ms ease !important; - will-change: opacity, transform, filter !important; -} - -html body #root div.ecommerce-standalone.web-shell[data-view="ecommerce"] .ecommerce-standalone__topbar[data-scroll-hidden="true"] .ecommerce-standalone__brand, -html body #root div.ecommerce-standalone.web-shell[data-view="ecommerce"] .ecommerce-standalone__topbar[data-scroll-hidden="true"] .ecommerce-profile-menu__trigger, -html body #root div.ecommerce-standalone.web-shell[data-view="ecommerce"] .ecommerce-standalone__topbar[data-scroll-hidden="true"] .ecommerce-standalone__login-button { - opacity: 0 !important; - pointer-events: none !important; - filter: blur(4px) saturate(0.96) !important; - transform: translateY(-14px) scale(0.96) !important; - transition: - opacity 160ms ease, - transform 190ms cubic-bezier(0.4, 0, 1, 1), - filter 160ms ease !important; -} - -html body #root div.ecommerce-standalone.web-shell[data-view="ecommerce"] .ecommerce-standalone__topbar[data-scroll-hidden="false"] .ecommerce-standalone__brand, -html body #root div.ecommerce-standalone.web-shell[data-view="ecommerce"] .ecommerce-standalone__topbar[data-scroll-hidden="false"] .ecommerce-profile-menu__trigger, -html body #root div.ecommerce-standalone.web-shell[data-view="ecommerce"] .ecommerce-standalone__topbar[data-scroll-hidden="false"] .ecommerce-standalone__login-button { - opacity: 1 !important; - filter: blur(0) saturate(1) !important; - transform: translateY(0) scale(1) !important; - transition: - opacity 260ms ease 40ms, - transform 360ms cubic-bezier(0.16, 1, 0.3, 1) 40ms, - filter 260ms ease 40ms, - border-color 180ms ease, - box-shadow 180ms ease, - background 180ms ease !important; -} - -html body #root div.ecommerce-standalone.web-shell[data-view="ecommerce"] .ecommerce-profile-menu__trigger:hover, -html body #root div.ecommerce-standalone.web-shell[data-view="ecommerce"] .ecommerce-profile-menu__trigger[aria-expanded="true"] { - border-color: rgba(30, 189, 219, 0.3) !important; - background: rgba(255, 255, 255, 0.82) !important; - box-shadow: 0 16px 42px rgba(16, 115, 204, 0.12) !important; - transform: translateY(-1px); -} - -html body #root div.ecommerce-standalone.web-shell[data-view="ecommerce"] .ecommerce-profile-menu__trigger .ecommerce-standalone__credits { - min-height: auto !important; - padding: 0 !important; - border: 0 !important; - border-radius: 0 !important; - color: #3a5a6a !important; - background: transparent !important; - box-shadow: none !important; - font-size: 12px !important; - font-weight: 800 !important; - letter-spacing: 0 !important; -} - -html body #root div.ecommerce-standalone.web-shell[data-view="ecommerce"] .ecommerce-profile-menu__name { - max-width: 82px !important; + display: block !important; + width: 94px !important; + min-width: 94px !important; + height: 112px !important; overflow: hidden !important; - color: #10202c !important; - font-size: 13px !important; - font-weight: 800 !important; + border: 1px solid rgba(30, 189, 219, 0.14) !important; + border-radius: 14px !important; + background: rgba(232, 249, 253, 0.6) !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"]:not(.is-history-detail) .ecom-command-template-card__media img { + display: block !important; + width: 100% !important; + height: 100% !important; + object-fit: cover !important; + transition: transform 220ms ease !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"]:not(.is-history-detail) .ecom-command-template-card:hover .ecom-command-template-card__media img { + transform: scale(1.035) !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"]:not(.is-history-detail) .ecom-command-template-card__body { + display: grid !important; + align-content: center !important; + gap: 7px !important; + min-width: 0 !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"]:not(.is-history-detail) .ecom-command-template-card__badge { + justify-self: start !important; + max-width: 100% !important; + padding: 4px 8px !important; + overflow: hidden !important; + border-radius: 999px !important; + background: rgba(232, 249, 253, 0.9) !important; + color: #0f829b !important; + font-size: 10px !important; + font-weight: 760 !important; + line-height: 1 !important; text-overflow: ellipsis !important; white-space: nowrap !important; } -html body #root div.ecommerce-standalone.web-shell[data-view="ecommerce"] .ecommerce-profile-menu__trigger .local-user-avatar--sm { - width: 34px !important; - height: 34px !important; - border: 2px solid rgba(255, 255, 255, 0.86) !important; - border-radius: 999px !important; - box-shadow: - 0 0 0 1px rgba(30, 189, 219, 0.22), - 0 8px 18px rgba(16, 115, 204, 0.16) !important; +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"]:not(.is-history-detail) .ecom-command-template-card__body strong { + min-width: 0 !important; + overflow: hidden !important; + color: #10202c !important; + font-size: 15px !important; + font-weight: 820 !important; + line-height: 1.25 !important; + text-overflow: ellipsis !important; + white-space: nowrap !important; } -@media (max-width: 720px) { - html body #root div.ecommerce-standalone.web-shell[data-view="ecommerce"] .ecommerce-standalone__brand strong, - html body #root div.ecommerce-standalone.web-shell[data-view="ecommerce"] .ecommerce-profile-menu__name { +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"]:not(.is-history-detail) .ecom-command-template-card__body em { + display: -webkit-box !important; + min-width: 0 !important; + overflow: hidden !important; + color: rgba(85, 111, 126, 0.78) !important; + font-size: 12px !important; + font-style: normal !important; + font-weight: 620 !important; + line-height: 1.45 !important; + -webkit-line-clamp: 2 !important; + -webkit-box-orient: vertical !important; +} + +@media (max-width: 1024px) { + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"]:not(.is-history-detail) .ecom-command-template-strip { + grid-template-columns: repeat(2, minmax(0, 1fr)) !important; + } +} + +@media (max-width: 900px) { + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"]:not(.is-history-detail) .ecom-command-scenario-tabs.ecom-command-mode-tabs { + justify-content: flex-start !important; + } + + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"]:not(.is-history-detail) .ecom-command-scenario-scroll-hint { + display: block !important; + width: min(100%, 1180px) !important; + margin: -4px auto 6px !important; + text-align: center !important; + font-size: 11px !important; + font-weight: 480 !important; + line-height: 1 !important; + color: rgba(16, 32, 44, 0.36) !important; + } +} + +@media (max-width: 640px) { + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"]:not(.is-history-detail) .ecom-command-scenario-tabs.ecom-command-mode-tabs { + width: 100% !important; + margin-bottom: 8px !important; + } + + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"]:not(.is-history-detail) .ecom-command-scenario-tabs.ecom-command-mode-tabs button { + min-width: 112px !important; + min-height: 44px !important; + padding: 7px 10px !important; + } + + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"]:not(.is-history-detail) .ecom-command-scenario-tabs .ecom-command-mode-icon { + width: 24px !important; + min-width: 24px !important; + height: 24px !important; + font-size: 13px !important; + } + + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"]:not(.is-history-detail) .ecom-command-scenario-tabs strong { + font-size: 12px !important; + } + + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"]:not(.is-history-detail) .ecom-command-template-strip { + display: flex !important; + gap: 10px !important; + width: 100% !important; + margin-top: 12px !important; + overflow-x: auto !important; + scrollbar-width: none !important; + scroll-snap-type: x mandatory !important; + } + + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"]:not(.is-history-detail) .ecom-command-template-strip::-webkit-scrollbar { display: none !important; } - html body #root div.ecommerce-standalone.web-shell[data-view="ecommerce"] .ecommerce-profile-menu__trigger { - padding-left: 12px !important; - } -} - -html body #root div.ecommerce-standalone.web-shell[data-view="ecommerce"] .ecommerce-standalone__account button.ecommerce-standalone__login-button { - pointer-events: auto !important; - min-height: 40px !important; - padding: 0 16px !important; - border: 1px solid rgba(30, 189, 219, 0.22) !important; - border-radius: 999px !important; - color: #10202c !important; - background: - linear-gradient(180deg, rgba(255, 255, 255, 0.88), rgba(241, 250, 252, 0.82)) !important; - box-shadow: - 0 10px 26px rgba(16, 115, 204, 0.08), - inset 0 1px 0 rgba(255, 255, 255, 0.92) !important; - font-weight: 700 !important; -} - -html body #root div.ecommerce-standalone.web-shell[data-view="ecommerce"] .ecommerce-standalone__account button.ecommerce-standalone__login-button:hover { - border-color: rgba(30, 189, 219, 0.38) !important; - background: - linear-gradient(180deg, rgba(255, 255, 255, 0.96), rgba(232, 250, 253, 0.9)) !important; - box-shadow: - 0 14px 32px rgba(30, 189, 219, 0.14), - inset 0 1px 0 rgba(255, 255, 255, 0.96) !important; - transform: translateY(-1px); -} - -/* Let the workspace surface paint behind the transparent fixed topbar. */ -html body #root div.ecommerce-standalone.web-shell[data-view="ecommerce"] .ecommerce-standalone__content { - box-sizing: border-box !important; - height: 100dvh !important; - padding-top: 0 !important; -} - -html body #root div.ecommerce-standalone.web-shell[data-view="ecommerce"] .ecommerce-standalone__page--profile { - box-sizing: border-box !important; - height: 100dvh !important; - padding-top: var(--ecommerce-topbar-height) !important; -} - -html body #root div.ecommerce-standalone.web-shell[data-view="ecommerce"] .ecommerce-standalone__page--workspace, -html body #root div.ecommerce-standalone.web-shell[data-view="ecommerce"] .ecommerce-standalone__page--workspace .product-clone-page, -html body #root div.ecommerce-standalone.web-shell[data-view="ecommerce"] .ecommerce-standalone__page--workspace .product-clone-shell, -html body #root div.ecommerce-standalone.web-shell[data-view="ecommerce"] .ecommerce-standalone__page--workspace .product-clone-preview.clone-ai-preview { - height: 100% !important; -} - -html body #root div.ecommerce-standalone.web-shell[data-view="ecommerce"] .ecommerce-standalone__page--workspace .product-clone-page[data-tool="clone"][data-tool="clone"] .clone-ai-preview.clone-ai-preview:has(.ecom-inspiration-lab) { - padding-top: calc(var(--ecommerce-topbar-height) + var(--ecommerce-workspace-top-offset, 50px) + clamp(18px, 2.5vh, 30px)) !important; -} - -html body #root div.ecommerce-standalone.web-shell[data-view="ecommerce"] .ecommerce-standalone__page--workspace .product-clone-page[data-tool="clone"][data-tool="clone"].is-history-collapsed .ecom-command-history__toggle.ecom-command-history__toggle { - top: calc(var(--ecommerce-topbar-height) + 12px) !important; -} - -html body #root div.ecommerce-standalone.web-shell[data-view="ecommerce"] .ecommerce-standalone__page--workspace .product-clone-page[data-tool="clone"][data-tool="clone"].is-history-collapsed .ecom-command-history__toggle.ecom-command-history__toggle:hover { - transform: translateY(-2px) scale(1.035) !important; -} - -html body #root div.ecommerce-standalone.web-shell[data-view="ecommerce"] .ecommerce-standalone__page--workspace .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-history.ecom-command-history { - top: calc(var(--ecommerce-topbar-height) + 18px) !important; - right: 18px !important; - bottom: auto !important; - height: calc(100dvh - var(--ecommerce-topbar-height) - 42px) !important; - width: min(316px, calc(100vw - 72px)) !important; - overflow: hidden !important; - border: 1px solid rgba(30, 189, 219, 0.2) !important; - border-radius: 24px !important; - background: - linear-gradient(180deg, rgba(255, 255, 255, 0.88), rgba(238, 250, 253, 0.82)) !important; - box-shadow: - 0 24px 68px rgba(16, 115, 204, 0.16), - inset 0 1px 0 rgba(255, 255, 255, 0.9) !important; - backdrop-filter: blur(22px) saturate(1.12) !important; - -webkit-backdrop-filter: blur(22px) saturate(1.12) !important; -} - -html body #root div.ecommerce-standalone.web-shell[data-view="ecommerce"] .ecommerce-standalone__page--workspace .product-clone-page[data-tool="clone"][data-tool="clone"].is-history-collapsed .ecom-command-history.ecom-command-history { - top: calc(var(--ecommerce-topbar-height) + 12px) !important; - right: 18px !important; - bottom: auto !important; - width: 42px !important; - height: 42px !important; - overflow: visible !important; - border: 0 !important; - border-radius: 15px !important; - background: transparent !important; - box-shadow: none !important; - transform: none !important; - backdrop-filter: none !important; - -webkit-backdrop-filter: none !important; -} - -html body #root div.ecommerce-standalone.web-shell[data-view="ecommerce"] .ecommerce-standalone__page--workspace .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-history__tools { - padding: 14px 14px 10px !important; -} - -html body #root div.ecommerce-standalone.web-shell[data-view="ecommerce"] .ecommerce-standalone__page--workspace .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-history__heading { - padding-inline: 16px !important; -} - -html body #root div.ecommerce-standalone.web-shell[data-view="ecommerce"] .ecommerce-standalone__page--workspace .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-history__list { - padding: 10px 12px 16px !important; - overflow: hidden auto !important; -} - -html body #root div.ecommerce-standalone.web-shell[data-view="ecommerce"] .ecommerce-standalone__page--workspace .product-clone-page[data-tool="clone"][data-tool="clone"].is-history-collapsed .ecom-command-history__toggle.ecom-command-history__toggle { - position: relative !important; - top: auto !important; - right: auto !important; - left: auto !important; - z-index: 130 !important; - width: 42px !important; - height: 42px !important; - min-height: 42px !important; - transform: none !important; -} - -html body #root div.ecommerce-standalone.web-shell[data-view="ecommerce"] .ecommerce-standalone__page--workspace .product-clone-page[data-tool="clone"][data-tool="clone"].is-history-collapsed .ecom-command-history__tools { - display: block !important; - width: 42px !important; - height: 42px !important; - padding: 0 !important; -} - -/* History overlay final behavior: panel floats above the workspace and never reserves layout space. */ -html body #root div.ecommerce-standalone.web-shell[data-view="ecommerce"] .ecommerce-standalone__page--workspace .product-clone-page[data-tool="clone"][data-tool="clone"] { - --ecom-history-offset: 0px !important; - --ecom-history-panel-width: 0px !important; - --history-detail-workspace-width: 100vw !important; - padding-right: 0 !important; -} - -html body #root div.ecommerce-standalone.web-shell[data-view="ecommerce"] .ecommerce-standalone__page--workspace .product-clone-page[data-tool="clone"][data-tool="clone"] > .product-clone-shell.product-clone-shell { - width: 100% !important; - max-width: none !important; - padding-right: 0 !important; - filter: none !important; - opacity: 1 !important; - transform: none !important; - pointer-events: auto !important; - user-select: auto !important; -} - -html body #root div.ecommerce-standalone.web-shell[data-view="ecommerce"] .ecommerce-standalone__page--workspace .product-clone-page[data-tool="clone"][data-tool="clone"] .product-clone-preview.clone-ai-preview { - width: 100% !important; - max-width: none !important; -} - -html body #root div.ecommerce-standalone.web-shell[data-view="ecommerce"] .ecommerce-standalone__page--workspace .product-clone-page[data-tool="clone"][data-tool="clone"].is-history-detail .ecom-command-composer-wrap.has-generated.is-compact { - left: 50vw !important; - width: min(760px, calc(100vw - clamp(48px, 8vw, 96px))) !important; -} - -html body #root div.ecommerce-standalone.web-shell[data-view="ecommerce"] .ecommerce-standalone__page--workspace .product-clone-page[data-tool="clone"][data-tool="clone"].is-history-detail .clone-ai-canvas-node:not(.is-generating) { - max-width: min(860px, calc(100vw - 80px)) !important; -} - -html body #root div.ecommerce-standalone.web-shell[data-view="ecommerce"] .ecommerce-standalone__page--workspace .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-history__backdrop { - background: rgba(16, 38, 56, 0.08) !important; - backdrop-filter: none !important; - -webkit-backdrop-filter: none !important; - animation: ecommerce-soft-scrim-in 180ms ease-out both !important; -} - -html body #root div.ecommerce-standalone.web-shell[data-view="ecommerce"] .ecommerce-standalone__page--workspace .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-history.ecom-command-history { - position: fixed !important; - z-index: 130 !important; - opacity: 1 !important; - transform: translateX(0) scale(1) !important; - transform-origin: top right !important; - transition: - opacity 240ms ease, - top 360ms cubic-bezier(0.22, 0.61, 0.36, 1), - width 360ms cubic-bezier(0.22, 0.61, 0.36, 1), - height 360ms cubic-bezier(0.22, 0.61, 0.36, 1), - border-radius 360ms cubic-bezier(0.22, 0.61, 0.36, 1), - border-color 220ms ease, - background 220ms ease, - transform 360ms cubic-bezier(0.22, 0.61, 0.36, 1), - box-shadow 260ms ease !important; - will-change: opacity, transform !important; - animation: none !important; -} - -html body #root div.ecommerce-standalone.web-shell[data-view="ecommerce"] .ecommerce-standalone__page--workspace .product-clone-page[data-tool="clone"][data-tool="clone"].is-history-collapsed .ecom-command-history.ecom-command-history { - opacity: 1 !important; - transform: translateX(0) scale(1) !important; - animation: none !important; -} - -html body #root div.ecommerce-standalone.web-shell[data-view="ecommerce"] .ecommerce-standalone__page--workspace .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-history__tools, -html body #root div.ecommerce-standalone.web-shell[data-view="ecommerce"] .ecommerce-standalone__page--workspace .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-history__new, -html body #root div.ecommerce-standalone.web-shell[data-view="ecommerce"] .ecommerce-standalone__page--workspace .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-history__refresh, -html body #root div.ecommerce-standalone.web-shell[data-view="ecommerce"] .ecommerce-standalone__page--workspace .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-history__heading, -html body #root div.ecommerce-standalone.web-shell[data-view="ecommerce"] .ecommerce-standalone__page--workspace .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-history__refresh-note, -html body #root div.ecommerce-standalone.web-shell[data-view="ecommerce"] .ecommerce-standalone__page--workspace .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-history__list { - transition: - opacity 220ms ease, - transform 360ms cubic-bezier(0.34, 0, 0.22, 1), - visibility 0s linear 220ms !important; -} - -html body #root div.ecommerce-standalone.web-shell[data-view="ecommerce"] .ecommerce-standalone__page--workspace .product-clone-page[data-tool="clone"][data-tool="clone"]:not(.is-history-collapsed) .ecom-command-history__tools, -html body #root div.ecommerce-standalone.web-shell[data-view="ecommerce"] .ecommerce-standalone__page--workspace .product-clone-page[data-tool="clone"][data-tool="clone"]:not(.is-history-collapsed) .ecom-command-history__new, -html body #root div.ecommerce-standalone.web-shell[data-view="ecommerce"] .ecommerce-standalone__page--workspace .product-clone-page[data-tool="clone"][data-tool="clone"]:not(.is-history-collapsed) .ecom-command-history__refresh, -html body #root div.ecommerce-standalone.web-shell[data-view="ecommerce"] .ecommerce-standalone__page--workspace .product-clone-page[data-tool="clone"][data-tool="clone"]:not(.is-history-collapsed) .ecom-command-history__heading, -html body #root div.ecommerce-standalone.web-shell[data-view="ecommerce"] .ecommerce-standalone__page--workspace .product-clone-page[data-tool="clone"][data-tool="clone"]:not(.is-history-collapsed) .ecom-command-history__refresh-note, -html body #root div.ecommerce-standalone.web-shell[data-view="ecommerce"] .ecommerce-standalone__page--workspace .product-clone-page[data-tool="clone"][data-tool="clone"]:not(.is-history-collapsed) .ecom-command-history__list { - opacity: 1 !important; - visibility: visible !important; - transform: translateY(0) !important; - transition: - opacity 180ms ease 90ms, - transform 280ms cubic-bezier(0.22, 0.61, 0.36, 1) 70ms, - visibility 0s linear 0s !important; -} - -html body #root div.ecommerce-standalone.web-shell[data-view="ecommerce"] .ecommerce-standalone__page--workspace .product-clone-page[data-tool="clone"][data-tool="clone"].is-history-collapsed .ecom-command-history__new, -html body #root div.ecommerce-standalone.web-shell[data-view="ecommerce"] .ecommerce-standalone__page--workspace .product-clone-page[data-tool="clone"][data-tool="clone"].is-history-collapsed .ecom-command-history__refresh, -html body #root div.ecommerce-standalone.web-shell[data-view="ecommerce"] .ecommerce-standalone__page--workspace .product-clone-page[data-tool="clone"][data-tool="clone"].is-history-collapsed .ecom-command-history__heading, -html body #root div.ecommerce-standalone.web-shell[data-view="ecommerce"] .ecommerce-standalone__page--workspace .product-clone-page[data-tool="clone"][data-tool="clone"].is-history-collapsed .ecom-command-history__refresh-note, -html body #root div.ecommerce-standalone.web-shell[data-view="ecommerce"] .ecommerce-standalone__page--workspace .product-clone-page[data-tool="clone"][data-tool="clone"].is-history-collapsed .ecom-command-history__list { - opacity: 0 !important; - visibility: hidden !important; - transform: translateY(6px) !important; - transition: - opacity 160ms ease, - transform 220ms ease, - visibility 0s linear 160ms !important; -} - -@keyframes ecom-history-panel-enter { - from { - opacity: 0; - transform: translateX(26px) scale(0.975); + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"]:not(.is-history-detail) .ecom-command-template-card { + grid-template-columns: 84px minmax(0, 1fr) !important; + flex: 0 0 min(86vw, 360px) !important; + min-height: 118px !important; + scroll-snap-align: start !important; } - to { - opacity: 1; - transform: translateX(0) scale(1); + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"]:not(.is-history-detail) .ecom-command-template-card__media { + width: 84px !important; + min-width: 84px !important; + height: 98px !important; } } - -/* Focused tool page sample: the inner tool header owns navigation, so the global brand steps away. */ -html body #root div.ecommerce-standalone.web-shell[data-view="ecommerce"][data-workspace-tool-page="true"] .ecommerce-standalone__brand { - opacity: 0 !important; - pointer-events: none !important; - filter: blur(4px) saturate(0.96) !important; - transform: translateY(-10px) scale(0.96) !important; -} - -html body #root div.ecommerce-standalone.web-shell[data-view="ecommerce"][data-workspace-tool-page="true"] .ecommerce-standalone__topbar[data-scroll-hidden] .ecommerce-standalone__brand { - opacity: 0 !important; - pointer-events: none !important; - filter: blur(4px) saturate(0.96) !important; - transform: translateY(-10px) scale(0.96) !important; -} - -html body #root div.ecommerce-standalone.web-shell[data-view="ecommerce"][data-workspace-tool-page="true"] .ecommerce-standalone__topbar { - padding-inline: clamp(16px, 2vw, 24px) !important; -} - -html body #root div.ecommerce-standalone.web-shell[data-view="ecommerce"][data-workspace-tool-page="true"] .ecommerce-standalone__page--workspace .product-clone-page[data-tool="clone"].is-quick-set-page .ecom-quick-set-page, -html body #root div.ecommerce-standalone.web-shell[data-view="ecommerce"][data-workspace-tool-page="true"] .ecommerce-standalone__page--workspace .product-clone-page[data-tool="clone"].is-hot-clone-page .ecom-quick-set-page, -html body #root div.ecommerce-standalone.web-shell[data-view="ecommerce"][data-workspace-tool-page="true"] .ecommerce-standalone__page--workspace .product-clone-page[data-tool="clone"].is-image-workbench-page .ecom-image-workbench-page, -html body #root div.ecommerce-standalone.web-shell[data-view="ecommerce"][data-workspace-tool-page="true"] .ecommerce-standalone__page--workspace .product-clone-page[data-tool="clone"].is-watermark-page .ecom-watermark-page, -html body #root div.ecommerce-standalone.web-shell[data-view="ecommerce"][data-workspace-tool-page="true"] .ecommerce-standalone__page--workspace .product-clone-page[data-tool="clone"].is-translate-page .ecom-translate-page { - padding-top: 14px !important; -} - -html body #root div.ecommerce-standalone.web-shell[data-view="ecommerce"][data-workspace-tool-page="true"] .ecommerce-standalone__page--workspace .ecom-quick-set-panel, -html body #root div.ecommerce-standalone.web-shell[data-view="ecommerce"][data-workspace-tool-page="true"] .ecommerce-standalone__page--workspace .ecom-image-workbench-side, -html body #root div.ecommerce-standalone.web-shell[data-view="ecommerce"][data-workspace-tool-page="true"] .ecommerce-standalone__page--workspace .ecom-watermark-side, -html body #root div.ecommerce-standalone.web-shell[data-view="ecommerce"][data-workspace-tool-page="true"] .ecommerce-standalone__page--workspace .ecom-translate-side { - border-radius: 18px !important; -} - -html body #root div.ecommerce-standalone.web-shell[data-view="ecommerce"][data-workspace-tool-page="true"] .ecommerce-standalone__page--workspace .ecom-quick-set-panel-head, -html body #root div.ecommerce-standalone.web-shell[data-view="ecommerce"][data-workspace-tool-page="true"] .ecommerce-standalone__page--workspace .ecom-image-workbench-panel-head { - display: grid !important; - grid-template-columns: minmax(0, 1fr) auto auto !important; - align-items: center !important; - gap: 8px !important; - min-height: 48px !important; - margin: -18px -16px 10px !important; - padding: 12px 12px 10px 16px !important; - border-bottom: 1px solid rgba(16, 115, 204, 0.08) !important; - background: - linear-gradient(180deg, rgba(255, 255, 255, 0.96), rgba(248, 252, 254, 0.9)) !important; - box-shadow: 0 10px 28px rgba(16, 115, 204, 0.05) !important; - backdrop-filter: blur(18px) saturate(1.08) !important; - -webkit-backdrop-filter: blur(18px) saturate(1.08) !important; -} - -html body #root div.ecommerce-standalone.web-shell[data-view="ecommerce"][data-workspace-tool-page="true"] .ecommerce-standalone__page--workspace .ecom-quick-set-page-title { - min-width: 0 !important; - margin: 0 !important; - overflow: hidden !important; - color: #10202c !important; - font-size: 18px !important; - font-weight: 950 !important; - line-height: 1.1 !important; - text-overflow: ellipsis !important; - white-space: nowrap !important; -} - -html body #root div.ecommerce-standalone.web-shell[data-view="ecommerce"][data-workspace-tool-page="true"] .ecommerce-standalone__page--workspace .ecom-quick-set-back { - min-width: 58px !important; - min-height: 32px !important; - padding: 0 12px !important; - border: 1px solid rgba(16, 115, 204, 0.12) !important; - border-radius: 999px !important; - color: #526474 !important; - background: rgba(255, 255, 255, 0.78) !important; - box-shadow: none !important; - font-size: 13px !important; - font-weight: 850 !important; - letter-spacing: 0 !important; -} - -html body #root div.ecommerce-standalone.web-shell[data-view="ecommerce"][data-workspace-tool-page="true"] .ecommerce-standalone__page--workspace .ecom-quick-set-back:hover { - border-color: rgba(30, 189, 219, 0.34) !important; - color: #1073cc !important; - background: rgba(232, 249, 253, 0.92) !important; - transform: translateY(-1px) !important; -}