diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100644 index 0000000..2312dc5 --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1 @@ +npx lint-staged diff --git a/.husky/pre-push b/.husky/pre-push new file mode 100644 index 0000000..0f84d2b --- /dev/null +++ b/.husky/pre-push @@ -0,0 +1 @@ +npm run css:audit diff --git a/lint-staged.config.mjs b/lint-staged.config.mjs new file mode 100644 index 0000000..aa0ab61 --- /dev/null +++ b/lint-staged.config.mjs @@ -0,0 +1,10 @@ +// lint-staged 配置 —— 配合 husky pre-commit 使用 +// +// 当前只运行 tsc 全量类型检查(tsc 不接受单文件增量检查), +// 未来可扩展 ESLint / Prettier / stylelint 等按文件的检查。 +// +// 函数语法返回原始命令字符串,lint-staged 不会追加文件名。 + +export default { + "*.{ts,tsx}": () => "tsc --noEmit", +}; diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..b4bb84b --- /dev/null +++ b/package-lock.json @@ -0,0 +1,3459 @@ +{ + "name": "omniai-web-preview", + "version": "0.1.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "omniai-web-preview", + "version": "0.1.0", + "dependencies": { + "@ant-design/icons": "5.3.0", + "react": "18.2.0", + "react-dom": "18.2.0", + "scheduler": "0.23.0", + "zustand": "5.0.13" + }, + "devDependencies": { + "@types/react": "18.2.55", + "@types/react-dom": "18.2.18", + "@vitejs/plugin-react": "4.2.1", + "@vitest/coverage-v8": "^1.6.0", + "husky": "^9.1.7", + "lint-staged": "^17.0.7", + "typescript": "5.3.3", + "vite": "5.1.0", + "vite-plugin-compression2": "2.5.3", + "vitest": "^1.6.0" + } + }, + "node_modules/@ampproject/remapping": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@ant-design/colors": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/@ant-design/colors/-/colors-7.2.1.tgz", + "integrity": "sha512-lCHDcEzieu4GA3n8ELeZ5VQ8pKQAWcGGLRTQ50aQM2iqPpq2evTxER84jfdPvsPAtEcZ7m44NI45edFMo8oOYQ==", + "license": "MIT", + "dependencies": { + "@ant-design/fast-color": "^2.0.6" + } + }, + "node_modules/@ant-design/fast-color": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@ant-design/fast-color/-/fast-color-2.0.6.tgz", + "integrity": "sha512-y2217gk4NqL35giHl72o6Zzqji9O7vHh9YmhUVkPtAOpoTCH4uWxo/pr4VE8t0+ChEPs0qo4eJRC5Q1eXWo3vA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.24.7" + }, + "engines": { + "node": ">=8.x" + } + }, + "node_modules/@ant-design/icons": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/@ant-design/icons/-/icons-5.3.0.tgz", + "integrity": "sha512-69FgBsIkeCjw72ZU3fJpqjhmLCPrzKGEllbrAZK7MUdt1BrKsyG6A8YDCBPKea27UQ0tRXi33PcjR4tp/tEXMg==", + "license": "MIT", + "dependencies": { + "@ant-design/colors": "^7.0.0", + "@ant-design/icons-svg": "^4.4.0", + "@babel/runtime": "^7.11.2", + "classnames": "^2.2.6", + "rc-util": "^5.31.1" + }, + "engines": { + "node": ">=8" + }, + "peerDependencies": { + "react": ">=16.0.0", + "react-dom": ">=16.0.0" + } + }, + "node_modules/@ant-design/icons-svg": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/@ant-design/icons-svg/-/icons-svg-4.4.2.tgz", + "integrity": "sha512-vHbT+zJEVzllwP+CM+ul7reTEfBR0vgxFe7+lREAsAA7YGsYpboiq2sQNeQeRvh09GfQgs/GyFEvZpJ9cLXpXA==", + "license": "MIT" + }, + "node_modules/@babel/code-frame": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.7.tgz", + "integrity": "sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.29.7", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.7.tgz", + "integrity": "sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.7.tgz", + "integrity": "sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/code-frame": "^7.29.7", + "@babel/generator": "^7.29.7", + "@babel/helper-compilation-targets": "^7.29.7", + "@babel/helper-module-transforms": "^7.29.7", + "@babel/helpers": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/template": "^7.29.7", + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7", + "@jridgewell/remapping": "^2.3.5", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/generator": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.7.tgz", + "integrity": "sha512-DkXD5OJQaAQIdZ1bt3UZdEnHAn9Imd3IVBdX03UFe+ony9Ojw5pzr9YVKGDY1jt+Gcn/FnGkNf8r+Vj5NOJWtQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.7", + "@babel/types": "^7.29.7", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.29.7.tgz", + "integrity": "sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.29.7", + "@babel/helper-validator-option": "^7.29.7", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-globals": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.29.7.tgz", + "integrity": "sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.29.7.tgz", + "integrity": "sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.29.7.tgz", + "integrity": "sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7", + "@babel/traverse": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.29.7.tgz", + "integrity": "sha512-G7sHYigPY17oO5SYWnfD/0MTBwVR781S/JI643e/JhUYgVgWE/61SoW3NH9KWUKyKq5LVh3npif99Wkt6j86Jw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz", + "integrity": "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz", + "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.29.7.tgz", + "integrity": "sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.7.tgz", + "integrity": "sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.29.7", + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.7.tgz", + "integrity": "sha512-hnORnjP/1P/zFEndoeX+n+t1RwWRJiJpM/jO7FW32Kn9r5+sJB2JWOdYo4L6k78j15eCwY3Gm/7364B1EMwtNg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.7" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-self": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.29.7.tgz", + "integrity": "sha512-TL0hMc9xzy86VD31nUiwzd5otRAcyEPcsegCxolO0PvcXuH1v0kECe/UIznYFihpkvU5wg/jk4v0TTEFfm53fw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-source": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.29.7.tgz", + "integrity": "sha512-06IyK09H3wi4cGbhDBwp5gUGo0IKtnYa8tyTiephirPCK6fbobVGiXMMI5zLQ4aKEYP3wZ3ArU44o+8KMrSG/Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/runtime": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.29.7.tgz", + "integrity": "sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/template": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.29.7.tgz", + "integrity": "sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.7.tgz", + "integrity": "sha512-EhlfNQtZ+NK22w5BM61ciuiq1m58ed33Wr1Xan//ZRTy6hgjnwyCffRYwzsGXdASJSUJ1guZILsErh1eQcl+zw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.7", + "@babel/generator": "^7.29.7", + "@babel/helper-globals": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/template": "^7.29.7", + "@babel/types": "^7.29.7", + "debug": "^4.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.7.tgz", + "integrity": "sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.19.12.tgz", + "integrity": "sha512-bmoCYyWdEL3wDQIVbcyzRyeKLgk2WtWLTWz1ZIAZF/EGbNOwSA6ew3PftJ1PqMiOOGu0OyFMzG53L0zqIpPeNA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.12.tgz", + "integrity": "sha512-qg/Lj1mu3CdQlDEEiWrlC4eaPZ1KztwGJ9B6J+/6G+/4ewxJg7gqj8eVYWvao1bXrqGiW2rsBZFSX3q2lcW05w==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.19.12.tgz", + "integrity": "sha512-P0UVNGIienjZv3f5zq0DP3Nt2IE/3plFzuaS96vihvD0Hd6H/q4WXUGpCxD/E8YrSXfNyRPbpTq+T8ZQioSuPA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.19.12.tgz", + "integrity": "sha512-3k7ZoUW6Q6YqhdhIaq/WZ7HwBpnFBlW905Fa4s4qWJyiNOgT1dOqDiVAQFwBH7gBRZr17gLrlFCRzF6jFh7Kew==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.12.tgz", + "integrity": "sha512-B6IeSgZgtEzGC42jsI+YYu9Z3HKRxp8ZT3cqhvliEHovq8HSX2YX8lNocDn79gCKJXOSaEot9MVYky7AKjCs8g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.19.12.tgz", + "integrity": "sha512-hKoVkKzFiToTgn+41qGhsUJXFlIjxI/jSYeZf3ugemDYZldIXIxhvwN6erJGlX4t5h417iFuheZ7l+YVn05N3A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.12.tgz", + "integrity": "sha512-4aRvFIXmwAcDBw9AueDQ2YnGmz5L6obe5kmPT8Vd+/+x/JMVKCgdcRwH6APrbpNXsPz+K653Qg8HB/oXvXVukA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.19.12.tgz", + "integrity": "sha512-EYoXZ4d8xtBoVN7CEwWY2IN4ho76xjYXqSXMNccFSx2lgqOG/1TBPW0yPx1bJZk94qu3tX0fycJeeQsKovA8gg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.19.12.tgz", + "integrity": "sha512-J5jPms//KhSNv+LO1S1TX1UWp1ucM6N6XuL6ITdKWElCu8wXP72l9MM0zDTzzeikVyqFE6U8YAV9/tFyj0ti+w==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.12.tgz", + "integrity": "sha512-EoTjyYyLuVPfdPLsGVVVC8a0p1BFFvtpQDB/YLEhaXyf/5bczaGeN15QkR+O4S5LeJ92Tqotve7i1jn35qwvdA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.19.12.tgz", + "integrity": "sha512-Thsa42rrP1+UIGaWz47uydHSBOgTUnwBwNq59khgIwktK6x60Hivfbux9iNR0eHCHzOLjLMLfUMLCypBkZXMHA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.19.12.tgz", + "integrity": "sha512-LiXdXA0s3IqRRjm6rV6XaWATScKAXjI4R4LoDlvO7+yQqFdlr1Bax62sRwkVvRIrwXxvtYEHHI4dm50jAXkuAA==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.19.12.tgz", + "integrity": "sha512-fEnAuj5VGTanfJ07ff0gOA6IPsvrVHLVb6Lyd1g2/ed67oU1eFzL0r9WL7ZzscD+/N6i3dWumGE1Un4f7Amf+w==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.19.12.tgz", + "integrity": "sha512-nYJA2/QPimDQOh1rKWedNOe3Gfc8PabU7HT3iXWtNUbRzXS9+vgB0Fjaqr//XNbd82mCxHzik2qotuI89cfixg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.19.12.tgz", + "integrity": "sha512-2MueBrlPQCw5dVJJpQdUYgeqIzDQgw3QtiAHUC4RBz9FXPrskyyU3VI1hw7C0BSKB9OduwSJ79FTCqtGMWqJHg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.19.12.tgz", + "integrity": "sha512-+Pil1Nv3Umes4m3AZKqA2anfhJiVmNCYkPchwFJNEJN5QxmTs1uzyy4TvmDrCRNT2ApwSari7ZIgrPeUx4UZDg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.12.tgz", + "integrity": "sha512-B71g1QpxfwBvNrfyJdVDexenDIt1CiDN1TIXLbhOw0KhJzE78KIFGX6OJ9MrtC0oOqMWf+0xop4qEU8JrJTwCg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.19.12.tgz", + "integrity": "sha512-3ltjQ7n1owJgFbuC61Oj++XhtzmymoCihNFgT84UAmJnxJfm4sYCiSLTXZtE00VWYpPMYc+ZQmB6xbSdVh0JWA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.19.12.tgz", + "integrity": "sha512-RbrfTB9SWsr0kWmb9srfF+L933uMDdu9BIzdA7os2t0TXhCRjrQyCeOt6wVxr79CKD4c+p+YhCj31HBkYcXebw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.19.12.tgz", + "integrity": "sha512-HKjJwRrW8uWtCQnQOz9qcU3mUZhTUQvi56Q8DPTLLB+DawoiQdjsYq+j+D3s9I8VFtDr+F9CjgXKKC4ss89IeA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.19.12.tgz", + "integrity": "sha512-URgtR1dJnmGvX864pn1B2YUYNzjmXkuJOIqG2HdU62MVS4EHpU2946OZoTMnRUHklGtJdJZ33QfzdjGACXhn1A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.19.12.tgz", + "integrity": "sha512-+ZOE6pUkMOJfmxmBZElNOx72NKpIa/HFOMGzu8fqzQJ5kgf6aTGrcJaFsNiVMH4JKpMipyK+7k0n2UXN7a8YKQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.19.12.tgz", + "integrity": "sha512-T1QyPSDCyMXaO3pzBkF96E8xMkiRYbUEZADd29SyPGabqxMViNoii+NcK7eWJAEoU6RZyEm5lVSIjTmcdoB9HA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@istanbuljs/schema": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.6.tgz", + "integrity": "sha512-+Sg6GCR/wy1oSmQDFq4LQDAhm3ETKnorxN+y5nbLULOR3P0c14f2Wurzj3/xqPXtasLFfHd5iRFQ7AJt4KH2cw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@rollup/pluginutils": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.4.0.tgz", + "integrity": "sha512-MfPp06CjRLfXQ3wY0R8vJDYBy/MvVcc9OulEfR0B8Iv9ko+GCNaRZ+EpJYFl27LhKsZK0o420sYCRHCjfCgeUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "estree-walker": "^2.0.2", + "picomatch": "^4.0.2" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.62.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.62.0.tgz", + "integrity": "sha512-IPIQ55ythEHkfEd9jMEi32OQ7SxURsGA43JI22lj01OLZNt2NUbJX8YUHxkVWyQ6daHPNn0truF5nSj3DQp6YQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.62.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.62.0.tgz", + "integrity": "sha512-M6s9cr10MibETyo8JsOkq+Lo1+lU6hcvb1MApnUql5qte/5hMEgzlN8/ReIKNfRV8rrqX50W1BX9zoUhC192RA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.62.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.62.0.tgz", + "integrity": "sha512-BqCoMoIbn0keKys+dEAdBa70EtOwV1bEsQCUgU9FdiZmmMge/Zk7LlkYGqbrdHR+Frnt0E1FOanly+rlwvvQzw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.62.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.62.0.tgz", + "integrity": "sha512-SIMzST3VFNXDAbeIWDWiFCNM5qncUBDWaEV7NfE7oZbDt2mgfW4MvbKdbYiGOLoM32gbTv608UMd0XktEYSD7w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.62.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.62.0.tgz", + "integrity": "sha512-ezjfSQMP7ArdUsbBwbQIfwAlhE84I2iVnzQNCFSveqV42q+BmKlzVpf7mxv5EchLcoWU4y6/heFzVg1F+hodUQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.62.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.62.0.tgz", + "integrity": "sha512-9+qTWGW9AZRhnUgwtTwzNwcPlL87ngkeN0LA+q1bADvmY9aNvWaF2TFW8BZgnQPYxpDI7+rMVLivcd4V737TAQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.62.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.62.0.tgz", + "integrity": "sha512-T1dMEQhXA/jkJ/jyMIw9IovK8bSUq7A8kLIlvZTb/6YIVsp2zLavr4F3oyllHWo7eIVJRyE5n3tUjQJEbE1IuQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.62.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.62.0.tgz", + "integrity": "sha512-2as0LgT7qQpyceQq6VUJYnumUMUrgGQCWIiDIN9DE0/tglsk6o66uCB4f3djRawAltvfCNLyZZrsqbPA6inCsA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.62.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.62.0.tgz", + "integrity": "sha512-bVURMg+6eNN9C/yc0aVjooZcwTTtYF4YW3xta5pP0//r3o1V8gXEHXWCndj47w/HhwsFroZrFhR+6uQP5T0n0g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.62.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.62.0.tgz", + "integrity": "sha512-Ful8pM/2yYI83PViWdFdpZhdI8HJ5qsXANe5atypbHDf+KIBBDsZsbyy8hbXnULVvW9NsTh5DHwbcBftyLTfiw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.62.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.62.0.tgz", + "integrity": "sha512-9Gp/DgrkzfUBmNPVTyPTvay+4xEP7M/clXpj3efXBcm6uTIVIgDg4rqUpqKXvLEuFRVuEpSAOkhgNeecvaZ4Cg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-musl": { + "version": "4.62.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.62.0.tgz", + "integrity": "sha512-m9tsJz54LUXkSYM8+8PG81B9IKK5r+2T0clMq4QrS16xFosufU7firBDAZEsDheDs7wTlP7h3++S7lMsU955HA==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.62.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.62.0.tgz", + "integrity": "sha512-3UvJ5PNVU16aJf6M3tFI24pWzAl2/ynfbyRN3ICyQajK1lSkrnVYNnLz3v04J32qKa0FczJc22zeToc0lr2A3w==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-musl": { + "version": "4.62.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.62.0.tgz", + "integrity": "sha512-vRWUAbYLGHBZS6Q8Msb2sfnf1fvJf+47t8l/TwOerM2qArzy+IeNMTHrYLHXh95h8MoatPHI5hhSZNs+mGXKPg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.62.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.62.0.tgz", + "integrity": "sha512-c00T5SYENHAt86cfW47URaP3Us5vLC/4QO7GYud1G5VNRffCwwCuBspwqYrriuJB+5m0WFzClCn9wed0FBjKvg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.62.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.62.0.tgz", + "integrity": "sha512-krrCDilhXOwFkSkO3Wm9I/f9H0L92XHHwy2fwxjukxIbh0dem8gZqOW5Y8BsHrpJv5qwlRBV+Wl4ZFyRWhUpwg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.62.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.62.0.tgz", + "integrity": "sha512-7pfYFSTc4/rUC/FtAI0Qp6QthDBCIi6/AuP1xYqFk5vanI6KnL5dWKP60OM/05LOsbwTmIcvr6eXC4CJuJ75IA==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.62.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.62.0.tgz", + "integrity": "sha512-7SDIalKeIpG0Ifogbbdn58HmSotYMlf23K3dCJEmiVd9Fg36Vmni82iPQec27N3wY4Bvbxftkxz6vSx9OcouTg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.62.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.62.0.tgz", + "integrity": "sha512-eRZevouTH2i1HeAVLqJuLnt256krQkGY0TN6WsTmsIhuzbh457HuWDMakKwmi0Cjadux983CoSr8Lim2QhUIFw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-openbsd-x64": { + "version": "4.62.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.62.0.tgz", + "integrity": "sha512-3oVS7FLGa4U1qcvao9ylGxrjXZyUQqR8UwxEcnUEyPX53O/C/mKDZegNXTdHCP+h3e6ta/f1EN38Yif1mmZHYg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.62.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.62.0.tgz", + "integrity": "sha512-yTB9TgfWj5wHe5QgktAgXTLLot1gvEjl1NiPPAUiCs4oPrIWFl5V4nC3GrkNdj9LaAU4s94nVrGbGOCqUpyWsg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.62.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.62.0.tgz", + "integrity": "sha512-5LOhoaesY3doG1c+ac/2JtgREpKoJr5bUHH8tKY0V8di7+uSV6BwLs2PlR0/yzefGOkR+wE7ZolZphHCsyG5Rw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.62.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.62.0.tgz", + "integrity": "sha512-yYkWHhmbhRTWTnWos5HC4GcPQfjlzzCNbM9e/+GXrLuaBXYA3qSDR9f0Vgufd5S8yX81U8jPKp7ZnAjZFMtRnw==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.62.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.62.0.tgz", + "integrity": "sha512-SoTb6lPg25xZlA2ibwQ++ahCCnH+FP0qmEuafMJ4gznZKOlXioKEAeJLgCrqjM98ACziXM9V1amFjICVL4IFoA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.62.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.62.0.tgz", + "integrity": "sha512-5L+T1fMX4RIEBoZzT0+sQ0PhTS36NULFmMXtl1TZo44TMAROIMHbZufSOjVWt/Y622BtxgxtaNOokbTDvfsrZA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@sinclair/typebox": { + "version": "0.27.10", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.10.tgz", + "integrity": "sha512-MTBk/3jGLNB2tVxv6uLlFh1iu64iYOQ2PbdOSK3NW8JZsmlaOh2q6sdtKowBhfw8QFLmYNzTW4/oK4uATIi6ZA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz", + "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz", + "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.28.2" + } + }, + "node_modules/@types/estree": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", + "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/prop-types": { + "version": "15.7.15", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.15.tgz", + "integrity": "sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/@types/react": { + "version": "18.2.55", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.55.tgz", + "integrity": "sha512-Y2Tz5P4yz23brwm2d7jNon39qoAtMMmalOQv6+fEFt1mT+FcM3D841wDpoUvFXhaYenuROCy3FZYqdTjM7qVyA==", + "devOptional": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@types/prop-types": "*", + "@types/scheduler": "*", + "csstype": "^3.0.2" + } + }, + "node_modules/@types/react-dom": { + "version": "18.2.18", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.18.tgz", + "integrity": "sha512-TJxDm6OfAX2KJWJdMEVTwWke5Sc/E/RlnPGvGfS0W7+6ocy2xhDVQVh/KvC2Uf7kACs+gDytdusDSdWfWkaNzw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/react": "*" + } + }, + "node_modules/@types/scheduler": { + "version": "0.26.0", + "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.26.0.tgz", + "integrity": "sha512-WFHp9YUJQ6CKshqoC37iOlHnQSmxNc795UhB26CyBBttrN9svdIrUjl/NjnNmfcwtncN0h/0PPAFWv9ovP8mLA==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/@vitejs/plugin-react": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.2.1.tgz", + "integrity": "sha512-oojO9IDc4nCUUi8qIR11KoQm0XFFLIwsRBwHRR4d/88IWghn1y6ckz/bJ8GHDCsYEJee8mDzqtJxh15/cisJNQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.23.5", + "@babel/plugin-transform-react-jsx-self": "^7.23.3", + "@babel/plugin-transform-react-jsx-source": "^7.23.3", + "@types/babel__core": "^7.20.5", + "react-refresh": "^0.14.0" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "peerDependencies": { + "vite": "^4.2.0 || ^5.0.0" + } + }, + "node_modules/@vitest/coverage-v8": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-1.6.1.tgz", + "integrity": "sha512-6YeRZwuO4oTGKxD3bijok756oktHSIm3eczVVzNe3scqzuhLwltIF3S9ZL/vwOVIpURmU6SnZhziXXAfw8/Qlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@ampproject/remapping": "^2.2.1", + "@bcoe/v8-coverage": "^0.2.3", + "debug": "^4.3.4", + "istanbul-lib-coverage": "^3.2.2", + "istanbul-lib-report": "^3.0.1", + "istanbul-lib-source-maps": "^5.0.4", + "istanbul-reports": "^3.1.6", + "magic-string": "^0.30.5", + "magicast": "^0.3.3", + "picocolors": "^1.0.0", + "std-env": "^3.5.0", + "strip-literal": "^2.0.0", + "test-exclude": "^6.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "vitest": "1.6.1" + } + }, + "node_modules/@vitest/expect": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-1.6.1.tgz", + "integrity": "sha512-jXL+9+ZNIJKruofqXuuTClf44eSpcHlgj3CiuNihUF3Ioujtmc0zIa3UJOW5RjDK1YLBJZnWBlPuqhYycLioog==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/spy": "1.6.1", + "@vitest/utils": "1.6.1", + "chai": "^4.3.10" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/runner": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-1.6.1.tgz", + "integrity": "sha512-3nSnYXkVkf3mXFfE7vVyPmi3Sazhb/2cfZGGs0JRzFsPFvAMBEcrweV1V1GsrstdXeKCTXlJbvnQwGWgEIHmOA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/utils": "1.6.1", + "p-limit": "^5.0.0", + "pathe": "^1.1.1" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/snapshot": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-1.6.1.tgz", + "integrity": "sha512-WvidQuWAzU2p95u8GAKlRMqMyN1yOJkGHnx3M1PL9Raf7AQ1kwLKg04ADlCa3+OXUZE7BceOhVZiuWAbzCKcUQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "magic-string": "^0.30.5", + "pathe": "^1.1.1", + "pretty-format": "^29.7.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/spy": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-1.6.1.tgz", + "integrity": "sha512-MGcMmpGkZebsMZhbQKkAf9CX5zGvjkBTqf8Zx3ApYWXr3wG+QvEu2eXWfnIIWYSJExIp4V9FCKDEeygzkYrXMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "tinyspy": "^2.2.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/utils": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-1.6.1.tgz", + "integrity": "sha512-jOrrUvXM4Av9ZWiG1EajNto0u96kWAhJ1LmPmJhXXQx/32MecEKd10pOLYgS2BQx1TgkGhloPU1ArDW2vvaY6g==", + "dev": true, + "license": "MIT", + "dependencies": { + "diff-sequences": "^29.6.3", + "estree-walker": "^3.0.3", + "loupe": "^2.3.7", + "pretty-format": "^29.7.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/utils/node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0" + } + }, + "node_modules/acorn": { + "version": "8.17.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.17.0.tgz", + "integrity": "sha512-xRQbDb9BnwDafYNn6Vwl839DYVjqXYb1XVGtWAZ1kcDc6iwAL4hg3B1dZlRiuENFeO2H53gFG3in621AdERVAg==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.3.5", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.5.tgz", + "integrity": "sha512-HEHNfbars9v4pgpW6SO1KSPkfoS0xVOM/9UzkJltjlsHZmJasxg8aXkuZa7SMf8vKGIBhpUsPluQSqhJFCqebw==", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.11.0" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/ansi-escapes": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.3.0.tgz", + "integrity": "sha512-BvU8nYgGQBxcmMuEeUEmNTvrMVjJNSH7RgW24vXexN4Ven6qCvy4TntnvlnwnMLTVlcRQQdbRY8NKnaIoeWDNg==", + "dev": true, + "license": "MIT", + "dependencies": { + "environment": "^1.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/assertion-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/baseline-browser-mapping": { + "version": "2.10.37", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.37.tgz", + "integrity": "sha512-girxaJ7WZssDOFhzCGZTDKoTa1gk6A1TbflaYTpykLJ4UU9Fz9kx1aREM8JCuoVHbL8X8T/mJg7w2oYSq72Oig==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.cjs" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", + "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/browserslist": { + "version": "4.28.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.2.tgz", + "integrity": "sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "peer": true, + "dependencies": { + "baseline-browser-mapping": "^2.10.12", + "caniuse-lite": "^1.0.30001782", + "electron-to-chromium": "^1.5.328", + "node-releases": "^2.0.36", + "update-browserslist-db": "^1.2.3" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/cac": { + "version": "6.7.14", + "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", + "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001799", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001799.tgz", + "integrity": "sha512-hG1bReV+OUU+MOqK4t/ZWI0tZOyz3rqS9XuhOUz1cIcbwBKjOyJEJuw9ER5JuNyqxNk8u/JUVbGibBOL1yrjFw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/chai": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.5.0.tgz", + "integrity": "sha512-RITGBfijLkBddZvnn8jdqoTypxvqbOLYQkGGxXzeFjVHvudaPw0HNFD9x928/eUwYWd2dPCugVqspGALTZZQKw==", + "dev": true, + "license": "MIT", + "dependencies": { + "assertion-error": "^1.1.0", + "check-error": "^1.0.3", + "deep-eql": "^4.1.3", + "get-func-name": "^2.0.2", + "loupe": "^2.3.6", + "pathval": "^1.1.1", + "type-detect": "^4.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/check-error": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz", + "integrity": "sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-func-name": "^2.0.2" + }, + "engines": { + "node": "*" + } + }, + "node_modules/classnames": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.5.1.tgz", + "integrity": "sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==", + "license": "MIT" + }, + "node_modules/cli-cursor": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz", + "integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==", + "dev": true, + "license": "MIT", + "dependencies": { + "restore-cursor": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-truncate": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-5.2.0.tgz", + "integrity": "sha512-xRwvIOMGrfOAnM1JYtqQImuaNtDEv9v6oIYAs4LIHwTiKee8uwvIi363igssOC0O5U04i4AlENs79LQLu9tEMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "slice-ansi": "^8.0.0", + "string-width": "^8.2.0" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "license": "MIT" + }, + "node_modules/confbox": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.1.8.tgz", + "integrity": "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==", + "dev": true, + "license": "MIT" + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/csstype": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/deep-eql": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.4.tgz", + "integrity": "sha512-SUwdGfqdKOwxCPeVYjwSyRpJ7Z+fhpwIAtmCUdZIWZ/YP5R9WAsyuSgpLVDi9bjWoN2LXHNss/dk3urXtdQxGg==", + "dev": true, + "license": "MIT", + "dependencies": { + "type-detect": "^4.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/diff-sequences": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.5.372", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.372.tgz", + "integrity": "sha512-M3yhbAlilnwqC8D21t28UCDGHyitShTmmLRU/H+b74P6Ski16Nb9HONYEaVpMj/pwC7BEo5B95FpjODLCWbtfA==", + "dev": true, + "license": "ISC" + }, + "node_modules/emoji-regex": { + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", + "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", + "dev": true, + "license": "MIT" + }, + "node_modules/environment": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/environment/-/environment-1.1.0.tgz", + "integrity": "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/esbuild": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.12.tgz", + "integrity": "sha512-aARqgq8roFBj054KvQr5f1sFu0D65G+miZRCuJyJ0G13Zwx7vRar5Zhn2tkQNzIXcBrNVsv/8stehpj+GAjgbg==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.19.12", + "@esbuild/android-arm": "0.19.12", + "@esbuild/android-arm64": "0.19.12", + "@esbuild/android-x64": "0.19.12", + "@esbuild/darwin-arm64": "0.19.12", + "@esbuild/darwin-x64": "0.19.12", + "@esbuild/freebsd-arm64": "0.19.12", + "@esbuild/freebsd-x64": "0.19.12", + "@esbuild/linux-arm": "0.19.12", + "@esbuild/linux-arm64": "0.19.12", + "@esbuild/linux-ia32": "0.19.12", + "@esbuild/linux-loong64": "0.19.12", + "@esbuild/linux-mips64el": "0.19.12", + "@esbuild/linux-ppc64": "0.19.12", + "@esbuild/linux-riscv64": "0.19.12", + "@esbuild/linux-s390x": "0.19.12", + "@esbuild/linux-x64": "0.19.12", + "@esbuild/netbsd-x64": "0.19.12", + "@esbuild/openbsd-x64": "0.19.12", + "@esbuild/sunos-x64": "0.19.12", + "@esbuild/win32-arm64": "0.19.12", + "@esbuild/win32-ia32": "0.19.12", + "@esbuild/win32-x64": "0.19.12" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "dev": true, + "license": "MIT" + }, + "node_modules/eventemitter3": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.4.tgz", + "integrity": "sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==", + "dev": true, + "license": "MIT" + }, + "node_modules/execa": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", + "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^8.0.1", + "human-signals": "^5.0.0", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^4.1.0", + "strip-final-newline": "^3.0.0" + }, + "engines": { + "node": ">=16.17" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true, + "license": "ISC" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-east-asian-width": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.6.0.tgz", + "integrity": "sha512-QRbvDIbx6YklUe6RxeTeleMR0yv3cYH6PsPZHcnVn7xv7zO1BHN8r0XETu8n6Ye3Q+ahtSarc3WgtNWmehIBfA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-func-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", + "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/get-stream": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", + "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true, + "license": "MIT" + }, + "node_modules/human-signals": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", + "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=16.17.0" + } + }, + "node_modules/husky": { + "version": "9.1.7", + "resolved": "https://registry.npmjs.org/husky/-/husky-9.1.7.tgz", + "integrity": "sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==", + "dev": true, + "license": "MIT", + "bin": { + "husky": "bin.js" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/typicode" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dev": true, + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/is-fullwidth-code-point": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.1.0.tgz", + "integrity": "sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-east-asian-width": "^1.3.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-source-maps": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-5.0.6.tgz", + "integrity": "sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.23", + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-reports": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.2.0.tgz", + "integrity": "sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "license": "MIT" + }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "dev": true, + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/lint-staged": { + "version": "17.0.7", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-17.0.7.tgz", + "integrity": "sha512-JrSobt+tW3rH8IOMi8tDZd3foorM5yPEkLD/V2NxobgHrFfHWGee4MOLVuZeScgxftEwbHrPHIFA/ZL+nUJeuA==", + "dev": true, + "license": "MIT", + "dependencies": { + "listr2": "^10.2.1", + "picomatch": "^4.0.4", + "string-argv": "^0.3.2", + "tinyexec": "^1.2.4" + }, + "bin": { + "lint-staged": "bin/lint-staged.js" + }, + "engines": { + "node": ">=22.22.1" + }, + "funding": { + "url": "https://opencollective.com/lint-staged" + }, + "optionalDependencies": { + "yaml": "^2.9.0" + } + }, + "node_modules/listr2": { + "version": "10.2.1", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-10.2.1.tgz", + "integrity": "sha512-7I5knELsJKTUjXG+A6BkKAiGkW1i25fNa/xlUl9hFtk15WbE9jndA89xu5FzQKrY5llajE1hfZZFMILXkDHk/Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "cli-truncate": "^5.2.0", + "eventemitter3": "^5.0.4", + "log-update": "^6.1.0", + "rfdc": "^1.4.1", + "wrap-ansi": "^10.0.0" + }, + "engines": { + "node": ">=22.13.0" + } + }, + "node_modules/local-pkg": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-0.5.1.tgz", + "integrity": "sha512-9rrA30MRRP3gBD3HTGnC6cDFpaE1kVDWxWgqWJUN0RvDNAo+Nz/9GxB+nHOH0ifbVFy0hSA1V6vFDvnx54lTEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "mlly": "^1.7.3", + "pkg-types": "^1.2.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/log-update": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-6.1.0.tgz", + "integrity": "sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-escapes": "^7.0.0", + "cli-cursor": "^5.0.0", + "slice-ansi": "^7.1.0", + "strip-ansi": "^7.1.0", + "wrap-ansi": "^9.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/log-update/node_modules/slice-ansi": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.2.tgz", + "integrity": "sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.2.1", + "is-fullwidth-code-point": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/log-update/node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/wrap-ansi": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz", + "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "license": "MIT", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/loupe": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz", + "integrity": "sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-func-name": "^2.0.1" + } + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/magicast": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/magicast/-/magicast-0.3.5.tgz", + "integrity": "sha512-L0WhttDl+2BOsybvEOLK7fW3UA0OQ0IQ2d6Zl2x/a6vVRs3bAY0ECOSHHeL5jD+SbOpOCUEi0y1DgHEn9Qn1AQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.25.4", + "@babel/types": "^7.25.4", + "source-map-js": "^1.2.0" + } + }, + "node_modules/make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-dir/node_modules/semver": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.4.tgz", + "integrity": "sha512-rUCObTnP32Q08R2uuIrt7r9PlEonuTmtuXYcW6s5kjdlj3xbnwe+21yXptAUYcMAABLkYYTtnmzb3w3EDZfueA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true, + "license": "MIT" + }, + "node_modules/mimic-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mimic-function": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz", + "integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/mlly": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.8.2.tgz", + "integrity": "sha512-d+ObxMQFmbt10sretNDytwt85VrbkhhUA/JBGm1MPaWJ65Cl4wOgLaB1NYvJSZ0Ef03MMEU/0xpPMXUIQ29UfA==", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.16.0", + "pathe": "^2.0.3", + "pkg-types": "^1.3.1", + "ufo": "^1.6.3" + } + }, + "node_modules/mlly/node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "dev": true, + "license": "MIT" + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/nanoid": { + "version": "3.3.12", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.12.tgz", + "integrity": "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/node-releases": { + "version": "2.0.47", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.47.tgz", + "integrity": "sha512-Uzmd6LXpouKo8EUK68IjH4+E01w/hXyV3R3g/geCJo+rXLNfh1xucB+LOzYEOQPSiUK3h/xZf0cQGcSsmyL2Og==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/npm-run-path": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", + "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm-run-path/node_modules/path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-fn": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-limit": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-5.0.0.tgz", + "integrity": "sha512-/Eaoq+QyLSiXQ4lyYV23f14mZRQcXnxfHrN0vCai+ak9G0pp9iEQukIIZq5NccEvwRB8PUnZT0KsOoDCINS1qQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^1.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/pathe": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz", + "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/pathval": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", + "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pkg-types": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.3.1.tgz", + "integrity": "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "confbox": "^0.1.8", + "mlly": "^1.7.4", + "pathe": "^2.0.1" + } + }, + "node_modules/pkg-types/node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "dev": true, + "license": "MIT" + }, + "node_modules/postcss": { + "version": "8.5.15", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.15.tgz", + "integrity": "sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.12", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/rc-util": { + "version": "5.44.4", + "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-5.44.4.tgz", + "integrity": "sha512-resueRJzmHG9Q6rI/DfK6Kdv9/Lfls05vzMs1Sk3M2P+3cJa+MakaZyWY8IPfehVuhPJFKrIY1IK4GqbiaiY5w==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.3", + "react-is": "^18.2.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/react": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", + "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", + "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==", + "license": "MIT", + "peer": true, + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.0" + }, + "peerDependencies": { + "react": "^18.2.0" + } + }, + "node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "license": "MIT" + }, + "node_modules/react-refresh": { + "version": "0.14.2", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz", + "integrity": "sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/restore-cursor": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz", + "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==", + "dev": true, + "license": "MIT", + "dependencies": { + "onetime": "^7.0.0", + "signal-exit": "^4.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/restore-cursor/node_modules/onetime": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz", + "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-function": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/rfdc": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", + "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", + "dev": true, + "license": "MIT" + }, + "node_modules/rollup": { + "version": "4.62.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.62.0.tgz", + "integrity": "sha512-nc72Wgq62I7rtDV4izT5/aaS0zxy3kttkinf9586ApknY3jZO9NYsmtc24fUckA0X7Q2v+ML4a15pdUlV5V/jA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@types/estree": "1.0.9" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.62.0", + "@rollup/rollup-android-arm64": "4.62.0", + "@rollup/rollup-darwin-arm64": "4.62.0", + "@rollup/rollup-darwin-x64": "4.62.0", + "@rollup/rollup-freebsd-arm64": "4.62.0", + "@rollup/rollup-freebsd-x64": "4.62.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.62.0", + "@rollup/rollup-linux-arm-musleabihf": "4.62.0", + "@rollup/rollup-linux-arm64-gnu": "4.62.0", + "@rollup/rollup-linux-arm64-musl": "4.62.0", + "@rollup/rollup-linux-loong64-gnu": "4.62.0", + "@rollup/rollup-linux-loong64-musl": "4.62.0", + "@rollup/rollup-linux-ppc64-gnu": "4.62.0", + "@rollup/rollup-linux-ppc64-musl": "4.62.0", + "@rollup/rollup-linux-riscv64-gnu": "4.62.0", + "@rollup/rollup-linux-riscv64-musl": "4.62.0", + "@rollup/rollup-linux-s390x-gnu": "4.62.0", + "@rollup/rollup-linux-x64-gnu": "4.62.0", + "@rollup/rollup-linux-x64-musl": "4.62.0", + "@rollup/rollup-openbsd-x64": "4.62.0", + "@rollup/rollup-openharmony-arm64": "4.62.0", + "@rollup/rollup-win32-arm64-msvc": "4.62.0", + "@rollup/rollup-win32-ia32-msvc": "4.62.0", + "@rollup/rollup-win32-x64-gnu": "4.62.0", + "@rollup/rollup-win32-x64-msvc": "4.62.0", + "fsevents": "~2.3.2" + } + }, + "node_modules/scheduler": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz", + "integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0" + } + }, + "node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/siginfo": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", + "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", + "dev": true, + "license": "ISC" + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/slice-ansi": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-8.0.0.tgz", + "integrity": "sha512-stxByr12oeeOyY2BlviTNQlYV5xOj47GirPr4yA1hE9JCtxfQN0+tVbkxwCtYDQWhEKWFHsEK48ORg5jrouCAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.2.3", + "is-fullwidth-code-point": "^5.1.0" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/slice-ansi/node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/stackback": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", + "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", + "dev": true, + "license": "MIT" + }, + "node_modules/std-env": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.10.0.tgz", + "integrity": "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==", + "dev": true, + "license": "MIT" + }, + "node_modules/string-argv": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz", + "integrity": "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.6.19" + } + }, + "node_modules/string-width": { + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-8.2.1.tgz", + "integrity": "sha512-IIaP0g3iy9Cyy18w3M9YcaDudujEAVHKt3a3QJg1+sr/oX96TbaGUubG0hJyCjCBThFH+tFpcIyoUHUn1ogaLA==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-east-asian-width": "^1.5.0", + "strip-ansi": "^7.1.2" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/strip-ansi": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", + "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.2.2" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/strip-final-newline": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/strip-literal": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-2.1.1.tgz", + "integrity": "sha512-631UJ6O00eNGfMiWG78ck80dfBab8X6IVFB51jZK5Icd7XAs60Z5y7QdSd/wGIklnWvRbUNloVzhOKKmutxQ6Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "js-tokens": "^9.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/strip-literal/node_modules/js-tokens": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-9.0.1.tgz", + "integrity": "sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/tar-mini": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/tar-mini/-/tar-mini-0.2.0.tgz", + "integrity": "sha512-+qfUHz700DWnRutdUsxRRVZ38G1Qr27OetwaMYTdg8hcPxf46U0S1Zf76dQMWRBmusOt2ZCK5kbIaiLkoGO7WQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "dev": true, + "license": "ISC", + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/tinybench": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", + "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/tinyexec": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.2.4.tgz", + "integrity": "sha512-SHf/r48b7vOrjve9PxJo3MN5v5yuyjHvdUcrQffT3WXMUfnGmHDVbC4k3sHJaJTgZCwpUplIaAo5ANtMyp3YHg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/tinypool": { + "version": "0.8.4", + "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-0.8.4.tgz", + "integrity": "sha512-i11VH5gS6IFeLY3gMBQ00/MmLncVP7JLXOw1vlgkytLmJK7QnEr7NXf0LBdxfmNPAeyetukOk0bOYrJrFGjYJQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tinyspy": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-2.2.1.tgz", + "integrity": "sha512-KYad6Vy5VDWV4GH3fjpseMQ/XU2BhIYP7Vzd0LG44qRWm/Yt2WCOTicFdvmgo6gWaqooMQCawTtILVQJupKu7A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/type-detect": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.1.0.tgz", + "integrity": "sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/typescript": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", + "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/ufo": { + "version": "1.6.4", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.6.4.tgz", + "integrity": "sha512-JFNbkD1Svwe0KvGi8GOeLcP4kAWQ609twvCdcHxq1oSL8svv39ZuSvajcD8B+5D0eL4+s1Is2D/O6KN3qcTeRA==", + "dev": true, + "license": "MIT" + }, + "node_modules/update-browserslist-db": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", + "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/vite": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.1.0.tgz", + "integrity": "sha512-STmSFzhY4ljuhz14bg9LkMTk3d98IO6DIArnTY6MeBwiD1Za2StcQtz7fzOUnRCqrHSD5+OS2reg4HOz1eoLnw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "esbuild": "^0.19.3", + "postcss": "^8.4.35", + "rollup": "^4.2.0" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || >=20.0.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } + } + }, + "node_modules/vite-node": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-1.6.1.tgz", + "integrity": "sha512-YAXkfvGtuTzwWbDSACdJSg4A4DZiAqckWe90Zapc/sEX3XvHcw1NdurM/6od8J207tSDqNbSsgdCacBgvJKFuA==", + "dev": true, + "license": "MIT", + "dependencies": { + "cac": "^6.7.14", + "debug": "^4.3.4", + "pathe": "^1.1.1", + "picocolors": "^1.0.0", + "vite": "^5.0.0" + }, + "bin": { + "vite-node": "vite-node.mjs" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/vite-plugin-compression2": { + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/vite-plugin-compression2/-/vite-plugin-compression2-2.5.3.tgz", + "integrity": "sha512-ItPgqQWkcnBbVw7is9OKwiZ8v6+ju9rYROl5Lp6QfQDEx/d55AwJQb/KLpsQqsU9HoigYBsZ8tK6I02UwJNvEw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rollup/pluginutils": "^5.1.0", + "tar-mini": "^0.2.0" + } + }, + "node_modules/vitest": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-1.6.1.tgz", + "integrity": "sha512-Ljb1cnSJSivGN0LqXd/zmDbWEM0RNNg2t1QW/XUhYl/qPqyu7CsqeWtqQXHVaJsecLPuDoak2oJcZN2QoRIOag==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@vitest/expect": "1.6.1", + "@vitest/runner": "1.6.1", + "@vitest/snapshot": "1.6.1", + "@vitest/spy": "1.6.1", + "@vitest/utils": "1.6.1", + "acorn-walk": "^8.3.2", + "chai": "^4.3.10", + "debug": "^4.3.4", + "execa": "^8.0.1", + "local-pkg": "^0.5.0", + "magic-string": "^0.30.5", + "pathe": "^1.1.1", + "picocolors": "^1.0.0", + "std-env": "^3.5.0", + "strip-literal": "^2.0.0", + "tinybench": "^2.5.1", + "tinypool": "^0.8.3", + "vite": "^5.0.0", + "vite-node": "1.6.1", + "why-is-node-running": "^2.2.2" + }, + "bin": { + "vitest": "vitest.mjs" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@edge-runtime/vm": "*", + "@types/node": "^18.0.0 || >=20.0.0", + "@vitest/browser": "1.6.1", + "@vitest/ui": "1.6.1", + "happy-dom": "*", + "jsdom": "*" + }, + "peerDependenciesMeta": { + "@edge-runtime/vm": { + "optional": true + }, + "@types/node": { + "optional": true + }, + "@vitest/browser": { + "optional": true + }, + "@vitest/ui": { + "optional": true + }, + "happy-dom": { + "optional": true + }, + "jsdom": { + "optional": true + } + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/why-is-node-running": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", + "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", + "dev": true, + "license": "MIT", + "dependencies": { + "siginfo": "^2.0.0", + "stackback": "0.0.2" + }, + "bin": { + "why-is-node-running": "cli.js" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-10.0.0.tgz", + "integrity": "sha512-SGcvg80f0wUy2/fXES19feHMz8E0JoXv2uNgHOu4Dgi2OrCy1lqwFYEJz1BLbDI0exjPMe/ZdzZ/YpGECBG/aQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.2.3", + "string-width": "^8.2.0", + "strip-ansi": "^7.1.2" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true, + "license": "ISC" + }, + "node_modules/yaml": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.9.0.tgz", + "integrity": "sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA==", + "dev": true, + "license": "ISC", + "optional": true, + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14.6" + }, + "funding": { + "url": "https://github.com/sponsors/eemeli" + } + }, + "node_modules/yocto-queue": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.2.2.tgz", + "integrity": "sha512-4LCcse/U2MHZ63HAJVE+v71o7yOdIe4cZ70Wpf8D/IyjDKYQLV5GD46B+hSTjJsvV5PztjvHoU580EftxjDZFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/zustand": { + "version": "5.0.13", + "resolved": "https://registry.npmjs.org/zustand/-/zustand-5.0.13.tgz", + "integrity": "sha512-efI2tVaVQPqtOh114loML/Z80Y4NP3yc+Ff0fYiZJPauNeWZeIp/bRFD7I9bfmCOYBh/PHxlglQ9+wvlwnPikQ==", + "license": "MIT", + "engines": { + "node": ">=12.20.0" + }, + "peerDependencies": { + "@types/react": ">=18.0.0", + "immer": ">=9.0.6", + "react": ">=18.0.0", + "use-sync-external-store": ">=1.2.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "immer": { + "optional": true + }, + "react": { + "optional": true + }, + "use-sync-external-store": { + "optional": true + } + } + } + } +} diff --git a/package.json b/package.json index 3b24b5a..b2897cc 100644 --- a/package.json +++ b/package.json @@ -7,20 +7,30 @@ "dev": "vite --host 127.0.0.1", "build": "vite build", "preview": "vite preview --host 127.0.0.1", - "type-check": "tsc -p tsconfig.json --noEmit" + "type-check": "tsc -p tsconfig.json --noEmit", + "test": "vitest", + "test:run": "vitest run", + "test:coverage": "vitest run --coverage", + "css:audit": "node scripts/css-audit.mjs", + "prepare": "husky" }, "dependencies": { "@ant-design/icons": "5.3.0", "react": "18.2.0", "react-dom": "18.2.0", + "scheduler": "0.23.0", "zustand": "5.0.13" }, "devDependencies": { - "@types/react": "18.2.0", - "@types/react-dom": "18.2.0", + "@types/react": "18.2.55", + "@types/react-dom": "18.2.18", "@vitejs/plugin-react": "4.2.1", + "@vitest/coverage-v8": "^1.6.0", + "husky": "^9.1.7", + "lint-staged": "^17.0.7", "typescript": "5.3.3", "vite": "5.1.0", - "vite-plugin-compression2": "2.5.3" + "vite-plugin-compression2": "2.5.3", + "vitest": "^1.6.0" } } diff --git a/scripts/css-audit.mjs b/scripts/css-audit.mjs new file mode 100644 index 0000000..20ff14c --- /dev/null +++ b/scripts/css-audit.mjs @@ -0,0 +1,87 @@ +// CSS 健康度审计脚本。 +// 用法: npm run css:audit +// 输出每个 CSS 文件的行数、选择器数、!important 数、@media 数, +// 以及 !important 密度(每 100 行的 !important 数)。 +// 用于建立基线、跟踪 CSS 瘦身进度、防止 !important 回潮。 + +import { readFileSync, readdirSync, statSync } from "node:fs"; +import { fileURLToPath } from "node:url"; +import { dirname, join, relative } from "node:path"; + +const ROOT = join(dirname(fileURLToPath(import.meta.url)), "..", "src", "styles"); +const REPORT = []; + +function scanCssFile(filePath) { + const content = readFileSync(filePath, "utf-8"); + const lines = content.split(/\r?\n/).length; + const selectors = (content.match(/\{/g) || []).length; + const important = (content.match(/!important/g) || []).length; + const media = (content.match(/@media/g) || []).length; + const density = lines > 0 ? ((important / lines) * 100).toFixed(1) : "0"; + return { lines, selectors, important, media, density }; +} + +function walk(dir) { + for (const entry of readdirSync(dir)) { + const full = join(dir, entry); + const st = statSync(full); + if (st.isDirectory()) { + walk(full); + } else if (entry.endsWith(".css")) { + const rel = relative(ROOT, full).replace(/\\/g, "/"); + REPORT.push({ file: rel, ...scanCssFile(full) }); + } + } +} + +walk(ROOT); + +// Sort by !important count descending to surface the worst offenders. +REPORT.sort((a, b) => b.important - a.important); + +const totals = REPORT.reduce( + (acc, r) => { + acc.lines += r.lines; + acc.selectors += r.selectors; + acc.important += r.important; + acc.media += r.media; + return acc; + }, + { lines: 0, selectors: 0, important: 0, media: 0 }, +); + +const pad = (s, n) => String(s).padEnd(n); +const num = (s, n) => String(s).padStart(n); + +console.log("\nCSS Audit Report — src/styles/\n"); +console.log( + `${pad("File", 52)} ${num("Lines", 7)} ${num("Sel", 6)} ${num("!imp", 7)} ${num("@media", 7)} imp/100ln`, +); +console.log("-".repeat(92)); +for (const r of REPORT) { + console.log( + `${pad(r.file, 52)} ${num(r.lines, 7)} ${num(r.selectors, 6)} ${num(r.important, 7)} ${num(r.media, 7)} ${r.density}`, + ); +} +console.log("-".repeat(92)); +console.log( + `${pad("TOTAL", 52)} ${num(totals.lines, 7)} ${num(totals.selectors, 6)} ${num(totals.important, 7)} ${num(totals.media, 7)} ${((totals.important / totals.lines) * 100).toFixed(1)}`, +); +console.log(""); + +// Exit non-zero if total !important exceeds a budget threshold. +// Current baseline: ~7795. Set budget slightly above to allow incremental work +// while preventing uncontrolled growth. +const IMPORTANT_BUDGET = 7820; +if (totals.important > IMPORTANT_BUDGET) { + console.error( + `FAIL: !important count ${totals.important} exceeds budget ${IMPORTANT_BUDGET}. ` + + `Run with --no-important-check to bypass (not recommended).`, + ); + process.exit(1); +} else { + console.log( + `OK: !important count ${totals.important} within budget ${IMPORTANT_BUDGET} ` + + `(headroom ${IMPORTANT_BUDGET - totals.important}).`, + ); +} diff --git a/src/api/aiGenerationClient.ts b/src/api/aiGenerationClient.ts index db00e1f..bfdc128 100644 --- a/src/api/aiGenerationClient.ts +++ b/src/api/aiGenerationClient.ts @@ -1,12 +1,18 @@ import { buildApiUrl, buildAuthHeaders, - isRecord, readJsonResponse, serverRequest, throwResponseError, } from "./serverConnection"; import { isOptionalApiRouteMissing } from "./apiErrorUtils"; +import { + parseAiTaskStatus, + parseAiTaskStatusList, + parseImageTaskCreateResponse, + parseSseTaskFrame, + parseTaskCreateResponse, +} from "./dtoParsers"; import type { WebGenerationPreviewTask } from "../types"; export interface ImageGenInput { @@ -190,13 +196,6 @@ function parseContentDispositionFilename(value: string | null): string | undefin return plainMatch?.[1]?.trim() || undefined; } -function extractTaskList(payload: unknown): AiTaskStatus[] { - if (Array.isArray(payload)) return payload as AiTaskStatus[]; - if (!isRecord(payload)) return []; - const rows = payload.tasks ?? payload.items; - return Array.isArray(rows) ? (rows as AiTaskStatus[]) : []; -} - function getStoredSessionRole(): string { try { if (typeof window === "undefined") return ""; @@ -251,67 +250,73 @@ export const aiGenerationClient = { projectId: input.projectId, conversationId: input.conversationId, }); - const payload = await serverRequest("ai/image", { + const payload = await serverRequest("ai/image", { method: "POST", body: input, timeoutMs: TASK_SUBMIT_TIMEOUT_MS, maxRetries: NON_RETRYING_REQUEST.maxRetries, fallbackMessage: "Image generation request failed", }); - if (payload.providerDebug) { - emitImageRouteDebug("[ai/image-provider-debug]", payload.providerDebug as Record); + const parsed = parseImageTaskCreateResponse(payload); + if (parsed.providerDebug) { + emitImageRouteDebug("[ai/image-provider-debug]", parsed.providerDebug as Record); } - return payload; + return parsed; }, async createVideoTask(input: VideoGenInput): Promise<{ taskId: string }> { - return serverRequest<{ taskId: string }>("ai/video", { + const payload = await serverRequest("ai/video", { method: "POST", body: input, timeoutMs: TASK_SUBMIT_TIMEOUT_MS, maxRetries: NON_RETRYING_REQUEST.maxRetries, fallbackMessage: "Video generation request failed", }); + return parseTaskCreateResponse(payload); }, async createVideoSuperResolveTask(input: VideoSuperResolveInput): Promise<{ taskId: string }> { - return serverRequest<{ taskId: string }>("ai/video/super-resolve", { + const payload = await serverRequest("ai/video/super-resolve", { method: "POST", body: input, timeoutMs: TASK_SUBMIT_TIMEOUT_MS, maxRetries: NON_RETRYING_REQUEST.maxRetries, fallbackMessage: "Video super-resolution request failed", }); + return parseTaskCreateResponse(payload); }, async createEraseSubtitlesTask(input: EraseSubtitlesInput): Promise<{ taskId: string }> { - return serverRequest<{ taskId: string }>("ai/video/erase-subtitles", { + const payload = await serverRequest("ai/video/erase-subtitles", { method: "POST", body: input, timeoutMs: TASK_SUBMIT_TIMEOUT_MS, maxRetries: NON_RETRYING_REQUEST.maxRetries, fallbackMessage: "Subtitle removal request failed", }); + return parseTaskCreateResponse(payload); }, async createImageSuperResolveTask(input: ImageSuperResolveInput): Promise<{ taskId: string }> { - return serverRequest<{ taskId: string }>("ai/image/super-resolve", { + const payload = await serverRequest("ai/image/super-resolve", { method: "POST", body: input, timeoutMs: TASK_SUBMIT_TIMEOUT_MS, maxRetries: NON_RETRYING_REQUEST.maxRetries, fallbackMessage: "Image super-resolution request failed", }); + return parseTaskCreateResponse(payload); }, async createImageEditTask(input: ImageEditInput): Promise<{ taskId: string }> { - return serverRequest<{ taskId: string }>("ai/image/edit", { + const payload = await serverRequest("ai/image/edit", { method: "POST", body: input, timeoutMs: TASK_SUBMIT_TIMEOUT_MS, maxRetries: NON_RETRYING_REQUEST.maxRetries, fallbackMessage: "Image edit request failed", }); + return parseTaskCreateResponse(payload); }, async cancelTask(taskId: string): Promise { @@ -328,10 +333,11 @@ export const aiGenerationClient = { }, async getTaskStatus(taskId: string): Promise { - return serverRequest(`ai/tasks/${taskId}`, { + const payload = await serverRequest(`ai/tasks/${taskId}`, { timeoutMs: TASK_STATUS_TIMEOUT_MS, fallbackMessage: "Task status request failed", }); + return parseAiTaskStatus(payload); }, async downloadTaskResult(taskId: string): Promise<{ blob: Blob; filename?: string; contentType?: string }> { @@ -361,7 +367,7 @@ export const aiGenerationClient = { const payload = await serverRequest(`ai/tasks${search.toString() ? `?${search}` : ""}`, { fallbackMessage: "Task history request failed", }); - return extractTaskList(payload).map(toPreviewTask); + return parseAiTaskStatusList(payload).map(toPreviewTask); } catch (error) { if (isOptionalApiRouteMissing(error)) { taskHistoryRouteMissing = true; @@ -451,7 +457,7 @@ export const aiGenerationClient = { if (!line.startsWith("data: ")) continue; try { const data = JSON.parse(line.slice(6)); - onUpdate(data); + onUpdate(parseSseTaskFrame(data)); } catch { /* ignore */ } } } diff --git a/src/api/dtoParsers.test.ts b/src/api/dtoParsers.test.ts new file mode 100644 index 0000000..6d406eb --- /dev/null +++ b/src/api/dtoParsers.test.ts @@ -0,0 +1,184 @@ +import { describe, it, expect } from "vitest"; +import { + parseAiTaskStatus, + parseTaskCreateResponse, + parseImageTaskCreateResponse, + parseAiTaskStatusList, + parseSseTaskFrame, +} from "./dtoParsers"; + +describe("parseAiTaskStatus", () => { + it("parses a well-formed camelCase DTO", () => { + const result = parseAiTaskStatus({ + taskId: "task-1", + type: "video", + status: "running", + progress: 42, + resultUrl: "https://example.com/r.mp4", + error: null, + createdAt: "2026-01-01T00:00:00Z", + updatedAt: "2026-01-01T00:01:00Z", + }); + expect(result.taskId).toBe("task-1"); + expect(result.type).toBe("video"); + expect(result.status).toBe("running"); + expect(result.progress).toBe(42); + expect(result.resultUrl).toBe("https://example.com/r.mp4"); + }); + + it("tolerates snake_case field names", () => { + const result = parseAiTaskStatus({ + task_id: "task-2", + result_url: "https://example.com/x.png", + created_at: "2026-01-01T00:00:00Z", + updated_at: "2026-01-01T00:00:00Z", + }); + expect(result.taskId).toBe("task-2"); + expect(result.resultUrl).toBe("https://example.com/x.png"); + }); + + it("falls back to safe defaults for missing fields", () => { + const result = parseAiTaskStatus({}); + expect(result.taskId).toBe(""); + expect(result.type).toBe("image"); + expect(result.status).toBe("failed"); + expect(result.progress).toBe(0); + expect(result.resultUrl).toBeNull(); + expect(result.error).toBeNull(); + }); + + it("rejects unknown status/type values", () => { + const result = parseAiTaskStatus({ status: "weird", type: "audio" }); + expect(result.status).toBe("failed"); + expect(result.type).toBe("image"); + }); + + it("clamps progress to [0, 100]", () => { + expect(parseAiTaskStatus({ progress: 150 }).progress).toBe(100); + expect(parseAiTaskStatus({ progress: -10 }).progress).toBe(0); + expect(parseAiTaskStatus({ progress: "not-a-number" }).progress).toBe(0); + }); + + it("preserves numeric conversationId and nulls others", () => { + expect(parseAiTaskStatus({ conversationId: 7 }).conversationId).toBe(7); + expect(parseAiTaskStatus({ conversation_id: 9 }).conversationId).toBe(9); + expect(parseAiTaskStatus({ conversationId: "nope" }).conversationId).toBeNull(); + expect(parseAiTaskStatus({}).conversationId).toBeNull(); + }); + + it("returns empty string for a non-record payload", () => { + const result = parseAiTaskStatus("garbage"); + expect(result.taskId).toBe(""); + expect(result.status).toBe("failed"); + }); +}); + +describe("parseTaskCreateResponse", () => { + it("extracts taskId from a create response", () => { + expect(parseTaskCreateResponse({ taskId: "abc" }).taskId).toBe("abc"); + expect(parseTaskCreateResponse({ task_id: "def" }).taskId).toBe("def"); + expect(parseTaskCreateResponse({ id: "ghi" }).taskId).toBe("ghi"); + }); + + it("throws when taskId is missing", () => { + expect(() => parseTaskCreateResponse({})).toThrow(); + expect(() => parseTaskCreateResponse({ taskId: "" })).toThrow(); + expect(() => parseTaskCreateResponse({ taskId: " " })).toThrow(); + }); +}); + +describe("parseImageTaskCreateResponse", () => { + it("includes providerDebug when present", () => { + const result = parseImageTaskCreateResponse({ + taskId: "img-1", + providerDebug: { + requestedModel: "gpt-image", + effectiveModel: "dall-e-3", + route: ["primary", "fallback"], + candidates: [{ provider: "openai", model: "dall-e-3" }], + }, + }); + expect(result.taskId).toBe("img-1"); + expect(result.providerDebug?.effectiveModel).toBe("dall-e-3"); + expect(result.providerDebug?.route).toEqual(["primary", "fallback"]); + expect(result.providerDebug?.candidates?.[0]?.model).toBe("dall-e-3"); + }); + + it("omits providerDebug when absent", () => { + const result = parseImageTaskCreateResponse({ taskId: "img-2" }); + expect(result.taskId).toBe("img-2"); + expect(result.providerDebug).toBeUndefined(); + }); + + it("tolerates snake_case providerDebug fields", () => { + const result = parseImageTaskCreateResponse({ + taskId: "img-3", + provider_debug: { requested_model: "x", primary_provider: "openai" }, + }); + expect(result.providerDebug?.requestedModel).toBe("x"); + expect(result.providerDebug?.primaryProvider).toBe("openai"); + }); + + it("throws when taskId missing even if providerDebug present", () => { + expect(() => parseImageTaskCreateResponse({ providerDebug: {} })).toThrow(); + }); +}); + +describe("parseAiTaskStatusList", () => { + it("parses a bare array", () => { + const result = parseAiTaskStatusList([{ taskId: "a" }, { taskId: "b" }]); + expect(result).toHaveLength(2); + expect(result[0].taskId).toBe("a"); + }); + + it("parses an envelope { tasks: [...] }", () => { + const result = parseAiTaskStatusList({ tasks: [{ taskId: "a" }, { task_id: "b" }] }); + expect(result).toHaveLength(2); + expect(result[1].taskId).toBe("b"); + }); + + it("parses an envelope { items: [...] }", () => { + const result = parseAiTaskStatusList({ items: [{ taskId: "a" }] }); + expect(result).toHaveLength(1); + }); + + it("drops rows with no taskId rather than crashing", () => { + const result = parseAiTaskStatusList([{ taskId: "keep" }, { status: "running" }, {}]); + expect(result).toHaveLength(1); + expect(result[0].taskId).toBe("keep"); + }); + + it("returns empty array for non-array non-record payload", () => { + expect(parseAiTaskStatusList(null)).toEqual([]); + expect(parseAiTaskStatusList("nope")).toEqual([]); + expect(parseAiTaskStatusList({})).toEqual([]); + }); +}); + +describe("parseSseTaskFrame", () => { + it("parses a well-formed SSE frame", () => { + const frame = parseSseTaskFrame({ + taskId: "sse-1", + status: "completed", + progress: 100, + resultUrl: "https://example.com/done.png", + }); + expect(frame.taskId).toBe("sse-1"); + expect(frame.status).toBe("completed"); + expect(frame.progress).toBe(100); + expect(frame.resultUrl).toBe("https://example.com/done.png"); + }); + + it("clamps progress and rejects unknown status", () => { + const frame = parseSseTaskFrame({ taskId: "sse-2", status: "oops", progress: 999 }); + expect(frame.status).toBe("failed"); + expect(frame.progress).toBe(100); + }); + + it("handles a non-object payload", () => { + const frame = parseSseTaskFrame("garbage"); + expect(frame.taskId).toBe(""); + expect(frame.status).toBe("failed"); + expect(frame.progress).toBe(0); + }); +}); diff --git a/src/api/dtoParsers.ts b/src/api/dtoParsers.ts new file mode 100644 index 0000000..66d3a03 --- /dev/null +++ b/src/api/dtoParsers.ts @@ -0,0 +1,173 @@ +// DTO 解析层:把后端返回的 unknown 安全地解析成强类型 view model。 +// 所有从 serverRequest / SSE / localStorage 进入前端状态的 DTO 都应经过这里的 parser, +// 避免 as unknown as / as T 这类静默断言在后端变形时把 undefined/错误类型传到 UI。 +// +// helper 与 keyServerClient 里的 toNumber/toStringValue 同构,为避免改动 keyServerClient +// 暂在此自带一份;后续可统一到共享 dtoHelpers 模块。 + +import { isRecord } from "./serverConnection"; +import type { AiTaskStatus, ImageTaskCreateResponse, ImageProviderDebug } from "./aiGenerationClient"; + +function toNumber(value: unknown, fallback = 0): number { + const numberValue = typeof value === "number" ? value : Number(value); + return Number.isFinite(numberValue) ? numberValue : fallback; +} + +function toNullableString(value: unknown): string | null { + if (typeof value !== "string") return null; + const trimmed = value.trim(); + return trimmed || null; +} + +const TASK_STATUS_VALUES: ReadonlySet = new Set(["pending", "running", "completed", "failed", "cancelled"]); +const TASK_TYPE_VALUES: ReadonlySet = new Set(["image", "video"]); + +function normalizeTaskStatusValue(value: unknown): AiTaskStatus["status"] { + return typeof value === "string" && TASK_STATUS_VALUES.has(value) + ? (value as AiTaskStatus["status"]) + : "failed"; +} + +function normalizeTaskTypeValue(value: unknown): AiTaskStatus["type"] { + return typeof value === "string" && TASK_TYPE_VALUES.has(value) ? (value as AiTaskStatus["type"]) : "image"; +} + +interface ProviderDebugCandidate { + provider?: string; + transport?: string; + model?: string; + requestedModel?: string; + billingProvider?: string; + fallbackOf?: string; +} + +function normalizeProviderDebugCandidate(raw: unknown): ProviderDebugCandidate { + if (!isRecord(raw)) return {}; + return { + provider: toNullableString(raw.provider) ?? undefined, + transport: toNullableString(raw.transport) ?? undefined, + model: toNullableString(raw.model) ?? undefined, + requestedModel: toNullableString(raw.requestedModel ?? raw.requested_model) ?? undefined, + billingProvider: toNullableString(raw.billingProvider ?? raw.billing_provider) ?? undefined, + fallbackOf: toNullableString(raw.fallbackOf ?? raw.fallback_of) ?? undefined, + }; +} + +function toStringArray(raw: unknown): string[] | undefined { + if (!Array.isArray(raw)) return undefined; + return (raw as unknown[]) + .map((item) => toNullableString(item)) + .filter((item): item is string => item !== null); +} + +function normalizeProviderDebug(raw: unknown): ImageProviderDebug | undefined { + if (!isRecord(raw)) return undefined; + const hasAny = + (raw.requestedModel ?? raw.requested_model) !== undefined || + (raw.effectiveModel ?? raw.effective_model) !== undefined || + (raw.primaryProvider ?? raw.primary_provider) !== undefined || + (raw.fallbackProviders ?? raw.fallback_providers) !== undefined || + raw.route !== undefined || + raw.candidates !== undefined; + if (!hasAny) return undefined; + const fallbackProviders = toStringArray(raw.fallbackProviders ?? raw.fallback_providers); + const route = toStringArray(raw.route); + const candidates = Array.isArray(raw.candidates) + ? (raw.candidates as unknown[]).map(normalizeProviderDebugCandidate) + : undefined; + return { + requestedModel: toNullableString(raw.requestedModel ?? raw.requested_model) ?? undefined, + effectiveModel: toNullableString(raw.effectiveModel ?? raw.effective_model) ?? undefined, + primaryProvider: toNullableString(raw.primaryProvider ?? raw.primary_provider) ?? undefined, + fallbackProviders, + route, + candidates, + }; +} + +/** + * Parse a single task status DTO. Returns a well-formed AiTaskStatus with safe + * defaults for any missing/malformed field, so downstream code never sees + * undefined where it expects a value. + */ +export function parseAiTaskStatus(payload: unknown): AiTaskStatus { + const task = isRecord(payload) ? payload : {}; + return { + taskId: toNullableString(task.taskId ?? task.task_id ?? task.id) ?? "", + projectId: toNullableString(task.projectId ?? task.project_id) ?? undefined, + conversationId: typeof task.conversationId === "number" || typeof task.conversation_id === "number" + ? ((task.conversationId ?? task.conversation_id) as number) + : null, + clientQueueId: toNullableString(task.clientQueueId ?? task.client_queue_id), + type: normalizeTaskTypeValue(task.type), + status: normalizeTaskStatusValue(task.status), + progress: Math.max(0, Math.min(100, toNumber(task.progress))), + resultUrl: toNullableString(task.resultUrl ?? task.result_url), + error: toNullableString(task.error), + params: isRecord(task.params) ? task.params : undefined, + createdAt: toNullableString(task.createdAt ?? task.created_at) ?? "", + updatedAt: toNullableString(task.updatedAt ?? task.updated_at) ?? "", + completedAt: toNullableString(task.completedAt ?? task.completed_at), + }; +} + +/** + * Parse a task-create response ({ taskId }). Throws if taskId is missing, + * rather than silently returning { taskId: undefined }. + */ +export function parseTaskCreateResponse(payload: unknown): { taskId: string } { + const body = isRecord(payload) ? payload : {}; + const taskId = toNullableString(body.taskId ?? body.task_id ?? body.id); + if (!taskId) { + throw new Error("任务创建失败:服务端未返回任务 ID"); + } + return { taskId }; +} + +/** + * Parse an image task-create response, including optional provider debug info. + */ +export function parseImageTaskCreateResponse(payload: unknown): ImageTaskCreateResponse { + const base = parseTaskCreateResponse(payload); + const body = isRecord(payload) ? payload : {}; + const providerDebug = normalizeProviderDebug(body.providerDebug ?? body.provider_debug); + return providerDebug ? { ...base, providerDebug } : base; +} + +/** + * Parse a task list payload that may be a bare array or an envelope + * ({ tasks | items: [...] }). Malformed elements are dropped, not coerced, + * because a single bad row should not corrupt the whole history list. + */ +export function parseAiTaskStatusList(payload: unknown): AiTaskStatus[] { + let rows: unknown[]; + if (Array.isArray(payload)) { + rows = payload; + } else if (isRecord(payload)) { + const nested = payload.tasks ?? payload.items; + rows = Array.isArray(nested) ? nested : []; + } else { + rows = []; + } + // Keep only rows that have a non-empty taskId — empty-id rows are useless + // to the UI and indicate a malformed DTO. + return rows.map(parseAiTaskStatus).filter((task) => task.taskId); +} + +/** + * Parse an SSE task frame. SSE data is untyped JSON from the server stream; + * this validates the subset of fields that subscribeTaskStatus forwards. + */ +export function parseSseTaskFrame(payload: unknown): Pick< + AiTaskStatus, + "taskId" | "status" | "progress" | "resultUrl" | "error" +> { + const frame = isRecord(payload) ? payload : {}; + return { + taskId: toNullableString(frame.taskId ?? frame.task_id) ?? "", + status: normalizeTaskStatusValue(frame.status), + progress: Math.max(0, Math.min(100, toNumber(frame.progress))), + resultUrl: toNullableString(frame.resultUrl ?? frame.result_url), + error: toNullableString(frame.error), + }; +} diff --git a/src/api/serverConnection.ts b/src/api/serverConnection.ts index 2316f72..78f5650 100644 --- a/src/api/serverConnection.ts +++ b/src/api/serverConnection.ts @@ -82,9 +82,19 @@ function parseStoredSession(raw: string | null): WebUserSession | null { try { const parsed = JSON.parse(raw) as unknown; - return isRecord(parsed) && typeof parsed.token === "string" && isRecord(parsed.user) - ? (parsed as unknown as WebUserSession) - : null; + // Require token + a user object with at least an id, so a malformed/partial + // cached session does not get cast wholesale into WebUserSession and then + // crash UI code that reads user.id / user.username. + if (!isRecord(parsed) || typeof parsed.token !== "string" || !isRecord(parsed.user)) { + return null; + } + const user = parsed.user; + const userId = user.id ?? user.userId ?? user.user_id; + const username = user.username ?? user.name; + if (userId === undefined || typeof username !== "string" || !username.trim()) { + return null; + } + return parsed as unknown as WebUserSession; } catch { return null; } diff --git a/src/features/ecommerce/EcommerceVideoWorkspace.tsx b/src/features/ecommerce/EcommerceVideoWorkspace.tsx index 16b6510..bb4b914 100644 --- a/src/features/ecommerce/EcommerceVideoWorkspace.tsx +++ b/src/features/ecommerce/EcommerceVideoWorkspace.tsx @@ -1,4 +1,4 @@ -import { Fragment, useCallback, useEffect, useMemo, useRef, useState } from "react"; +import { Fragment, useCallback, useEffect, useMemo, useRef, useState } from "react"; import "../../styles/pages/ecommerce-video.css"; import { CloseOutlined, @@ -13,8 +13,6 @@ import { } from "@ant-design/icons"; import { runVideoPlan, - renderSceneImage, - renderScene, buildSceneTasks, saveVideoHistory, buildComplianceFailureMessage, @@ -29,7 +27,6 @@ import { type PlanStep, } from "./ecommerceVideoTypes"; import type { AdVideoUserConfig } from "../../api/adVideoPlanClient"; -import { ServerRequestError } from "../../api/serverConnection"; import { saveToolResultToLocal, addToolResultToAssetLibrary } from "../workbench/toolResultActions"; import { useAppStore } from "../../stores"; import { useGenerationTasks } from "../../hooks/useGenerationTasks"; @@ -39,6 +36,7 @@ import { clearEcommerceVideoState, } from "./ecommerceVideoKeepalive"; import { saveUnifiedEcommerceGenerationRecord } from "./ecommerceGenerationPersistence"; +import { useVideoSceneRunner } from "./useVideoSceneRunner"; interface EcommerceVideoWorkspaceProps { isAuthenticated: boolean; @@ -137,8 +135,6 @@ export default function EcommerceVideoWorkspace({ const [actionNotice, setActionNotice] = useState(null); const [previewMedia, setPreviewMedia] = useState<{ url: string; type: "image" | "video" } | null>(null); const [flowZoom, setFlowZoom] = useState(1); - const abortControllerRef = useRef(null); - const renderAbortRef = useRef({ current: false }); const actionNoticeTimerRef = useRef(null); const setView = useAppStore((s) => s.setView); const keepaliveRestoredFingerprintRef = useRef(null); @@ -150,6 +146,28 @@ export default function EcommerceVideoWorkspace({ [productImageDataUrls, requirement, platform, aspectRatio, durationSeconds, resolution], ); + const { + abortControllerRef, + renderAbortRef, + runImagePhase, + runVideoPhase, + resumePolling, + cancel, + retryScene, + } = useVideoSceneRunner({ + inputFingerprint, + planResult, + completedSteps, + sourceImageUrls, + aspectRatio, + resolution, + generation: generation as unknown as Parameters[0]["generation"], + sceneStoreIdMap, + onScenesChange: setScenes, + onStageChange: setStage, + onError: setError, + }); + // ── Keep-alive: restore saved state on mount ───────────── useEffect(() => { if (keepaliveRestoredFingerprintRef.current === inputFingerprint) return; @@ -180,11 +198,11 @@ export default function EcommerceVideoWorkspace({ setError(buildComplianceFailureMessage(planResult.compliance)); return; } - const timer = setTimeout(() => { void handleGenerateImages(); }, delay); + const timer = setTimeout(() => { void runImagePhase(scenes); }, delay); return () => clearTimeout(timer); } if (stage === "imaged" && scenes.every((s) => s.imageUrl)) { - const timer = setTimeout(() => { void handleRenderVideos(); }, delay); + const timer = setTimeout(() => { void runVideoPhase(scenes); }, delay); return () => clearTimeout(timer); } }, [stage, scenes, planResult]); @@ -301,82 +319,11 @@ export default function EcommerceVideoWorkspace({ useEffect(() => { if (keepalivePollingStartedRef.current) return; if (!scenes.length || stage === "idle" || stage === "cancelled" || stage === "completed") return; - const hasRunningScenes = scenes.some((s) => s.status === "running" || s.status === "pending"); if (!hasRunningScenes) return; keepalivePollingStartedRef.current = true; - - // Resume polling for image generation tasks - if (stage === "imaging") { - renderAbortRef.current = { current: false }; - void (async () => { - for (const scene of scenes) { - if (renderAbortRef.current.current) break; - if (scene.status !== "running" && scene.status !== "pending") continue; - if (!scene.imageTaskId) continue; - try { - const { waitForTask } = await import("../../api/taskSubscription"); - const resultUrl = await waitForTask(scene.imageTaskId, { - abortRef: renderAbortRef.current, - onProgress: (e) => - setScenes((prev) => prev.map((s) => (s.sceneId === scene.sceneId ? { ...s, progress: e.progress } : s))), - }); - if (resultUrl) { - setScenes((prev) => - prev.map((s) => (s.sceneId === scene.sceneId ? { ...s, status: "idle", progress: 100, imageUrl: resultUrl } : s)), - ); - } - } catch { - setScenes((prev) => - prev.map((s) => (s.sceneId === scene.sceneId ? { ...s, status: "idle", error: "恢复任务失败" } : s)), - ); - } - } - setScenes((current) => { - const allImaged = current.every((s) => s.imageUrl); - if (allImaged) setStage("imaged"); - return current; - }); - })(); - } - - // Resume polling for video rendering tasks - if (stage === "rendering") { - renderAbortRef.current = { current: false }; - void (async () => { - for (const scene of scenes) { - if (renderAbortRef.current.current) break; - if (scene.status !== "running" && scene.status !== "pending") continue; - if (!scene.taskId) continue; - try { - const { waitForTask } = await import("../../api/taskSubscription"); - const resultUrl = await waitForTask(scene.taskId, { - abortRef: renderAbortRef.current, - onProgress: (e) => - setScenes((prev) => prev.map((s) => (s.sceneId === scene.sceneId ? { ...s, progress: e.progress } : s))), - }); - if (resultUrl) { - setScenes((prev) => - prev.map((s) => - s.sceneId === scene.sceneId ? { ...s, status: "completed", progress: 100, resultUrl: resultUrl } : s, - ), - ); - } - } catch { - setScenes((prev) => - prev.map((s) => (s.sceneId === scene.sceneId ? { ...s, status: "failed", error: "恢复任务失败" } : s)), - ); - } - } - setScenes((current) => { - const hasFailed = current.some((s) => s.status === "failed"); - const allDone = current.every((s) => s.status === "completed" || s.status === "failed"); - if (allDone) setStage(hasFailed ? "partial_failed" : "completed"); - return current; - }); - })(); - } - }, [scenes, stage]); + void resumePolling(stage, scenes); + }, [scenes, stage, resumePolling]); // Note: keep-alive is NOT cleared on completion — results persist across page switches. // Only cleared when user explicitly starts a new plan via handlePlan. @@ -559,157 +506,9 @@ export default function EcommerceVideoWorkspace({ await runPlanFlow(planProgress); }; - // ── Phase 2: Image generation per scene ────────────────────── - const handleGenerateImages = async () => { - if (!planResult || !scenes.length) return; - if (!planAllowsVideoGeneration(planResult)) { - setError(buildComplianceFailureMessage(planResult.compliance)); - return; - } - setStage("imaging"); setError(null); - renderAbortRef.current = { current: false }; - const ratio = aspectRatio.includes("9:16") || aspectRatio.includes("9:16") ? "9:16" - : aspectRatio.includes("16:9") || aspectRatio.includes("16:9") ? "16:9" - : "1:1"; - let currentScenes = [...scenes]; - const persistScenes = (next: EcommerceVideoSceneTask[]) => { - currentScenes = next; - setScenes(next); - saveEcommerceVideoState({ inputFingerprint, stage: "imaging", completedSteps, planResult, scenes: next, sourceImageUrls }); - }; - // Only redo scenes missing imageUrl — preserves successfully generated images on partial retry - const scenesToProcess = currentScenes.filter((s) => !s.imageUrl); - if (!scenesToProcess.length) { - setStage("imaged"); - saveEcommerceVideoState({ inputFingerprint, stage: "imaged", completedSteps, planResult, scenes: currentScenes, sourceImageUrls }); - return; - } - for (const scene of scenesToProcess) { - if (renderAbortRef.current.current) break; - persistScenes(currentScenes.map((s) => s.sceneId === scene.sceneId ? { ...s, status: "pending", error: undefined } : s)); - try { - await renderSceneImage( - { sceneId: scene.sceneId, prompt: scene.prompt, aspectRatio: ratio, productImageUrls: sourceImageUrls }, - { - onSceneImageSubmitted: (id, taskId) => { - persistScenes(currentScenes.map((s) => s.sceneId === id ? { ...s, imageTaskId: taskId, status: "running" } : s)); - const storeId = generation.submitTask({ title: `分镜${id}图片`, type: "image", status: "running", progress: 0, prompt: scene.prompt, sourceView: "ecommerce", taskId, params: { sceneId: id, phase: "imaging" } }); - sceneStoreIdMap.current.set(id, storeId); - }, - onSceneImageProgress: (id, progress) => persistScenes(currentScenes.map((s) => s.sceneId === id ? { ...s, progress } : s)), - onSceneImageCompleted: (id, url) => { - persistScenes(currentScenes.map((s) => s.sceneId === id ? { ...s, status: "idle", progress: 100, imageUrl: url } : s)); - const sid = sceneStoreIdMap.current.get(id); - if (sid) generation.markCompleted(sid, url); - }, - onSceneImageFailed: (id, err2) => { - persistScenes(currentScenes.map((s) => s.sceneId === id ? { ...s, status: "idle", error: err2 } : s)); - const sid = sceneStoreIdMap.current.get(id); - if (sid) generation.markFailed(sid, err2); - }, - }, - renderAbortRef.current, - ); - } catch (err) { - const message = err instanceof Error ? err.message : "图片生成失败"; - persistScenes(currentScenes.map((s) => s.sceneId === scene.sceneId ? { ...s, status: "idle", error: message } : s)); - } - } - const allHaveImages = currentScenes.every((s) => s.imageUrl); - const finalStage = allHaveImages ? "imaged" as const : "partial_failed" as const; - setStage(finalStage); - saveEcommerceVideoState({ inputFingerprint, stage: finalStage, completedSteps, planResult, scenes: currentScenes, sourceImageUrls }); - }; - // ── Phase 3: Video rendering from generated images ────────── - const handleRenderVideos = async () => { - if (!scenes.length) return; - if (!planAllowsVideoGeneration(planResult)) { - setError(planResult ? buildComplianceFailureMessage(planResult.compliance) : "合规检查未通过,已停止生成。"); - return; - } - if (!scenes.some((s) => s.imageUrl)) { setError("请先生成分镜图片"); return; } - setStage("rendering"); setError(null); - renderAbortRef.current = { current: false }; - const quality = mapResolutionToQuality(resolution); - let currentScenes = [...scenes]; - const persistScenes = (next: EcommerceVideoSceneTask[]) => { - currentScenes = next; - setScenes(next); - saveEcommerceVideoState({ inputFingerprint, stage: "rendering", completedSteps, planResult, scenes: next, sourceImageUrls }); - }; - // Only render scenes that haven't completed yet — preserves successful videos on partial retry - const scenesToProcess = currentScenes.filter((s) => s.imageUrl && s.status !== "completed"); - if (!scenesToProcess.length) { - const finalStage = currentScenes.every((s) => s.status === "completed") ? "completed" as const : "partial_failed" as const; - setStage(finalStage); - saveEcommerceVideoState({ inputFingerprint, stage: finalStage, completedSteps, planResult, scenes: currentScenes, sourceImageUrls }); - return; - } - for (const scene of scenesToProcess) { - if (renderAbortRef.current.current) break; - if (!scene.imageUrl) continue; - persistScenes(currentScenes.map((s) => s.sceneId === scene.sceneId ? { ...s, status: "pending", error: undefined } : s)); - try { - await renderScene( - { sceneId: scene.sceneId, prompt: scene.prompt, durationSeconds: scene.durationSeconds, imageUrl: scene.imageUrl, productImageUrls: sourceImageUrls, aspectRatio, resolution: quality }, - { - onSceneSubmitted: (id, taskId) => { - persistScenes(currentScenes.map((s) => s.sceneId === id ? { ...s, taskId, status: "running" } : s)); - const storeId = generation.submitTask({ title: `分镜${id}视频`, type: "video", status: "running", progress: 0, prompt: scene.prompt, sourceView: "ecommerce", taskId, params: { sceneId: id, phase: "rendering" } }); - sceneStoreIdMap.current.set(id, storeId); - }, - onSceneProgress: (id, progress) => persistScenes(currentScenes.map((s) => s.sceneId === id ? { ...s, progress } : s)), - onSceneCompleted: (id, url) => { - persistScenes(currentScenes.map((s) => s.sceneId === id ? { ...s, status: "completed", progress: 100, resultUrl: url } : s)); - const sid = sceneStoreIdMap.current.get(id); - if (sid) generation.markCompleted(sid, url); - }, - onSceneFailed: (id, err2) => { - persistScenes(currentScenes.map((s) => s.sceneId === id ? { ...s, status: "failed", error: err2 } : s)); - const sid = sceneStoreIdMap.current.get(id); - if (sid) generation.markFailed(sid, err2); - }, - }, - renderAbortRef.current, - ); - } catch (err) { - const msg = err instanceof Error ? err.message : "生成失败"; - const isPayment = err instanceof ServerRequestError && err.status === 402; - persistScenes(currentScenes.map((s) => s.sceneId === scene.sceneId ? { ...s, status: "failed", error: isPayment ? "余额不足,请充值后继续" : msg } : s)); - if (isPayment) { setError("余额不足,请充值后再生成视频"); renderAbortRef.current.current = true; break; } - } - } - const hasFailed = currentScenes.some((s) => s.status === "failed"); - const allDone = currentScenes.every((s) => s.status === "completed" || s.status === "failed"); - const finalStage = allDone ? (hasFailed ? "partial_failed" as const : "completed" as const) : "rendering" as const; - setScenes(currentScenes); - setStage(finalStage); - saveEcommerceVideoState({ inputFingerprint, stage: finalStage, completedSteps, planResult, scenes: currentScenes, sourceImageUrls }); - }; - - const handleCancel = () => { abortControllerRef.current?.abort(); renderAbortRef.current.current = true; setStage("cancelled"); }; - - const handleRetryScene = async (scene: EcommerceVideoSceneTask) => { - if (!scene.imageUrl) return; - setScenes((prev) => prev.map((s) => s.sceneId === scene.sceneId ? { ...s, status: "pending", error: undefined } : s)); - try { - await renderScene( - { sceneId: scene.sceneId, prompt: scene.prompt, durationSeconds: scene.durationSeconds, imageUrl: scene.imageUrl!, productImageUrls: sourceImageUrls, aspectRatio, resolution: mapResolutionToQuality(resolution) }, - { - onSceneSubmitted: (id, taskId) => setScenes((prev) => prev.map((s) => s.sceneId === id ? { ...s, taskId, status: "running" } : s)), - onSceneProgress: (id, progress) => setScenes((prev) => prev.map((s) => s.sceneId === id ? { ...s, progress } : s)), - onSceneCompleted: (id, url) => setScenes((prev) => prev.map((s) => s.sceneId === id ? { ...s, status: "completed", progress: 100, resultUrl: url } : s)), - onSceneFailed: (id, err2) => setScenes((prev) => prev.map((s) => s.sceneId === id ? { ...s, status: "failed", error: err2 } : s)), - }, - renderAbortRef.current, - ); - } catch (err) { - setScenes((prev) => prev.map((s) => s.sceneId === scene.sceneId ? { ...s, status: "failed", error: (err as Error).message } : s)); - } - }; // ── Derived state ─────────────────────────────────────────── @@ -759,13 +558,13 @@ export default function EcommerceVideoWorkspace({ ) : null} {stage === "planned" || stage === "imaged" ? ( ) : null} {stage === "imaged" || (stage === "partial_failed" && imagedScenes.length > 0) ? ( ) : null} @@ -779,7 +578,7 @@ export default function EcommerceVideoWorkspace({ 生成视频中 ) : null} {stage === "planning" || stage === "imaging" || stage === "rendering" ? ( - ) : null} @@ -868,7 +667,7 @@ export default function EcommerceVideoWorkspace({ 分镜视频{scene.sceneId} {vidFailed ? ( diff --git a/src/features/ecommerce/ecommerceImageValidation.test.ts b/src/features/ecommerce/ecommerceImageValidation.test.ts new file mode 100644 index 0000000..6ce66f7 --- /dev/null +++ b/src/features/ecommerce/ecommerceImageValidation.test.ts @@ -0,0 +1,90 @@ +import { describe, it, expect } from "vitest"; +import { + validateEcommerceImageFiles, + summarizeRejectedImages, + normalizeEcommerceImageMime, + ECOMMERCE_MAX_IMAGE_BYTES, +} from "./ecommerceImageValidation"; + +function makeFile(name: string, type: string, size: number): File { + return new File([new Uint8Array(size)], name, { type }); +} + +describe("validateEcommerceImageFiles", () => { + it("accepts supported types under the size limit", () => { + const result = validateEcommerceImageFiles([ + makeFile("a.png", "image/png", 1024), + makeFile("b.jpg", "image/jpeg", 1024), + makeFile("c.webp", "image/webp", 1024), + makeFile("d.gif", "image/gif", 1024), + ]); + expect(result.accepted).toHaveLength(4); + expect(result.rejected).toHaveLength(0); + }); + + it("rejects unsupported mime types", () => { + const result = validateEcommerceImageFiles([makeFile("x.bmp", "image/bmp", 1024)]); + expect(result.accepted).toHaveLength(0); + expect(result.rejected[0]).toMatchObject({ name: "x.bmp", reason: "不支持的图片格式" }); + }); + + it("rejects files over 10MB", () => { + const result = validateEcommerceImageFiles([ + makeFile("big.png", "image/png", ECOMMERCE_MAX_IMAGE_BYTES + 1), + ]); + expect(result.accepted).toHaveLength(0); + expect(result.rejected[0]).toMatchObject({ name: "big.png", reason: "图片超过 10MB" }); + }); + + it("accepts exactly 10MB (boundary)", () => { + const result = validateEcommerceImageFiles([ + makeFile("edge.png", "image/png", ECOMMERCE_MAX_IMAGE_BYTES), + ]); + expect(result.accepted).toHaveLength(1); + }); + + it("partitions a mixed batch", () => { + const result = validateEcommerceImageFiles([ + makeFile("ok.png", "image/png", 100), + makeFile("bad.bmp", "image/bmp", 100), + makeFile("huge.jpg", "image/jpeg", ECOMMERCE_MAX_IMAGE_BYTES + 1), + ]); + expect(result.accepted).toHaveLength(1); + expect(result.rejected).toHaveLength(2); + }); +}); + +describe("summarizeRejectedImages", () => { + it("returns empty string for no rejections", () => { + expect(summarizeRejectedImages([])).toBe(""); + }); + + it("summarizes a single rejection", () => { + expect(summarizeRejectedImages([{ name: "a.bmp", reason: "不支持的图片格式" }])).toBe( + "a.bmp 已跳过:不支持的图片格式", + ); + }); + + it("appends count suffix for multiple rejections", () => { + const summary = summarizeRejectedImages([ + { name: "a.bmp", reason: "不支持的图片格式" }, + { name: "b.bmp", reason: "不支持的图片格式" }, + ]); + expect(summary).toBe("a.bmp 等 2 个文件 已跳过:不支持的图片格式"); + }); +}); + +describe("normalizeEcommerceImageMime", () => { + it("passes through supported types", () => { + expect(normalizeEcommerceImageMime("image/png")).toBe("image/png"); + expect(normalizeEcommerceImageMime("image/jpeg")).toBe("image/jpeg"); + expect(normalizeEcommerceImageMime("image/webp")).toBe("image/webp"); + expect(normalizeEcommerceImageMime("image/gif")).toBe("image/gif"); + }); + + it("falls back to image/png for unsupported or empty types", () => { + expect(normalizeEcommerceImageMime("image/bmp")).toBe("image/png"); + expect(normalizeEcommerceImageMime("")).toBe("image/png"); + expect(normalizeEcommerceImageMime("application/octet-stream")).toBe("image/png"); + }); +}); diff --git a/src/features/ecommerce/useVideoSceneRunner.ts b/src/features/ecommerce/useVideoSceneRunner.ts new file mode 100644 index 0000000..0f4b6ba --- /dev/null +++ b/src/features/ecommerce/useVideoSceneRunner.ts @@ -0,0 +1,480 @@ +// 视频场景任务编排 hook。 +// 从 EcommerceVideoWorkspace.tsx 抽出,封装"分镜图片生成 / 视频渲染 / 恢复轮询 / 取消" +// 四类场景任务的执行逻辑,消除组件内 persistScenes 闭包的重复。 +// +// 运行时行为与原组件逻辑等价(setScenes/setStage/saveEcommerceVideoState 的调用顺序和参数不变); +// 抽离目的是建立逻辑边界,让 resume 与正常执行共享同一套遍历。 + +import { useCallback, useRef } from "react"; +import type { MutableRefObject } from "react"; +import { + renderSceneImage, + renderScene, +} from "./ecommerceVideoService"; +import { waitForTask } from "../../api/taskSubscription"; +import { ServerRequestError } from "../../api/serverConnection"; +import { ENTERPRISE_DEFAULT_VIDEO_MODEL } from "../../utils/enterpriseVideoPolicy"; +import { resolveVideoRequestModel } from "../../utils/resolveVideoModel"; +import { + saveEcommerceVideoState, +} from "./ecommerceVideoKeepalive"; +import type { + EcommerceVideoSceneTask, + EcommerceVideoStage, + EcommerceVideoPlanResult, + PlanStep, +} from "./ecommerceVideoTypes"; + +type SetStateAction = T | ((prev: T) => T); + +export interface VideoSceneRunnerContext { + inputFingerprint: string; + planResult: EcommerceVideoPlanResult | null; + completedSteps: PlanStep[]; + sourceImageUrls: string[]; + aspectRatio: string; + resolution: string; + /** useGenerationTasks 实例,用于 submitTask/markCompleted/markFailed */ + generation: { + submitTask: (task: Record & { taskId: string }) => string; + markCompleted: (id: string, resultUrl?: string) => void; + markFailed: (id: string, error?: string) => void; + }; + sceneStoreIdMap: MutableRefObject>; + onScenesChange: (updater: SetStateAction) => void; + onStageChange: (stage: EcommerceVideoStage) => void; + onError?: (message: string) => void; +} + +function mapResolutionToQuality(res: string): "720P" | "1080P" { + return res.includes("720") ? "720P" : "1080P"; +} + +function deriveAspectRatioToken(aspectRatio: string): string { + if (aspectRatio.includes("9:16") || aspectRatio.includes("9:16")) return "9:16"; + if (aspectRatio.includes("16:9") || aspectRatio.includes("16:9")) return "16:9"; + return "1:1"; +} + +export function useVideoSceneRunner(context: VideoSceneRunnerContext) { + const { + inputFingerprint, + planResult, + completedSteps, + sourceImageUrls, + aspectRatio, + resolution, + generation, + sceneStoreIdMap, + onScenesChange, + onStageChange, + onError, + } = context; + + const abortControllerRef = useRef(null); + const renderAbortRef = useRef({ current: false }); + + // ── Image phase: generate per-scene images ────────────────── + const runImagePhase = useCallback( + async (scenes: EcommerceVideoSceneTask[]): Promise => { + if (!planResult || !scenes.length) return; + const ratio = deriveAspectRatioToken(aspectRatio); + let currentScenes = [...scenes]; + + const persistScenes = (next: EcommerceVideoSceneTask[]) => { + currentScenes = next; + onScenesChange(next); + saveEcommerceVideoState({ + inputFingerprint, + stage: "imaging", + completedSteps, + planResult, + scenes: next, + sourceImageUrls, + }); + }; + + const scenesToProcess = currentScenes.filter((s) => !s.imageUrl); + if (!scenesToProcess.length) { + onStageChange("imaged"); + saveEcommerceVideoState({ + inputFingerprint, + stage: "imaged", + completedSteps, + planResult, + scenes: currentScenes, + sourceImageUrls, + }); + return; + } + + for (const scene of scenesToProcess) { + if (renderAbortRef.current.current) break; + persistScenes( + currentScenes.map((s) => + s.sceneId === scene.sceneId ? { ...s, status: "pending", error: undefined } : s, + ), + ); + try { + await renderSceneImage( + { + sceneId: scene.sceneId, + prompt: scene.prompt, + aspectRatio: ratio, + productImageUrls: sourceImageUrls, + }, + { + onSceneImageSubmitted: (id, taskId) => { + persistScenes( + currentScenes.map((s) => (s.sceneId === id ? { ...s, imageTaskId: taskId, status: "running" } : s)), + ); + const storeId = generation.submitTask({ + title: `分镜${id}图片`, + type: "image", + status: "running", + progress: 0, + prompt: scene.prompt, + sourceView: "ecommerce", + taskId, + params: { sceneId: id, phase: "imaging" }, + }); + sceneStoreIdMap.current.set(id, storeId); + }, + onSceneImageProgress: (id, progress) => + persistScenes(currentScenes.map((s) => (s.sceneId === id ? { ...s, progress } : s))), + onSceneImageCompleted: (id, url) => { + persistScenes( + currentScenes.map((s) => (s.sceneId === id ? { ...s, status: "idle", progress: 100, imageUrl: url } : s)), + ); + const sid = sceneStoreIdMap.current.get(id); + if (sid) generation.markCompleted(sid, url); + }, + onSceneImageFailed: (id, err2) => { + persistScenes( + currentScenes.map((s) => (s.sceneId === id ? { ...s, status: "idle", error: err2 } : s)), + ); + const sid = sceneStoreIdMap.current.get(id); + if (sid) generation.markFailed(sid, err2); + }, + }, + renderAbortRef.current, + ); + } catch (err) { + const message = err instanceof Error ? err.message : "图片生成失败"; + persistScenes( + currentScenes.map((s) => (s.sceneId === scene.sceneId ? { ...s, status: "idle", error: message } : s)), + ); + } + } + + const allHaveImages = currentScenes.every((s) => s.imageUrl); + const finalStage: EcommerceVideoStage = allHaveImages ? "imaged" : "partial_failed"; + onStageChange(finalStage); + saveEcommerceVideoState({ + inputFingerprint, + stage: finalStage, + completedSteps, + planResult, + scenes: currentScenes, + sourceImageUrls, + }); + }, + [ + planResult, + aspectRatio, + inputFingerprint, + completedSteps, + sourceImageUrls, + generation, + sceneStoreIdMap, + onScenesChange, + onStageChange, + ], + ); + + // ── Video phase: render per-scene videos ──────────────────── + const runVideoPhase = useCallback( + async (scenes: EcommerceVideoSceneTask[]): Promise => { + if (!scenes.length) return; + const quality = mapResolutionToQuality(resolution); + let currentScenes = [...scenes]; + + const persistScenes = (next: EcommerceVideoSceneTask[]) => { + currentScenes = next; + onScenesChange(next); + saveEcommerceVideoState({ + inputFingerprint, + stage: "rendering", + completedSteps, + planResult, + scenes: next, + sourceImageUrls, + }); + }; + + const scenesToProcess = currentScenes.filter((s) => s.imageUrl && s.status !== "completed"); + if (!scenesToProcess.length) { + const finalStage: EcommerceVideoStage = currentScenes.every((s) => s.status === "completed") + ? "completed" + : "partial_failed"; + onStageChange(finalStage); + saveEcommerceVideoState({ + inputFingerprint, + stage: finalStage, + completedSteps, + planResult, + scenes: currentScenes, + sourceImageUrls, + }); + return; + } + + for (const scene of scenesToProcess) { + if (renderAbortRef.current.current) break; + if (!scene.imageUrl) continue; + persistScenes( + currentScenes.map((s) => + s.sceneId === scene.sceneId ? { ...s, status: "pending", error: undefined } : s, + ), + ); + try { + await renderScene( + { + sceneId: scene.sceneId, + prompt: scene.prompt, + durationSeconds: scene.durationSeconds, + imageUrl: scene.imageUrl, + productImageUrls: sourceImageUrls, + aspectRatio, + resolution: quality, + }, + { + onSceneSubmitted: (id, taskId) => { + persistScenes( + currentScenes.map((s) => (s.sceneId === id ? { ...s, taskId, status: "running" } : s)), + ); + const storeId = generation.submitTask({ + title: `分镜${id}视频`, + type: "video", + status: "running", + progress: 0, + prompt: scene.prompt, + sourceView: "ecommerce", + taskId, + params: { sceneId: id, phase: "rendering" }, + }); + sceneStoreIdMap.current.set(id, storeId); + }, + onSceneProgress: (id, progress) => + persistScenes(currentScenes.map((s) => (s.sceneId === id ? { ...s, progress } : s))), + onSceneCompleted: (id, url) => { + persistScenes( + currentScenes.map((s) => + s.sceneId === id ? { ...s, status: "completed", progress: 100, resultUrl: url } : s, + ), + ); + const sid = sceneStoreIdMap.current.get(id); + if (sid) generation.markCompleted(sid, url); + }, + onSceneFailed: (id, err2) => { + persistScenes( + currentScenes.map((s) => (s.sceneId === id ? { ...s, status: "failed", error: err2 } : s)), + ); + const sid = sceneStoreIdMap.current.get(id); + if (sid) generation.markFailed(sid, err2); + }, + }, + renderAbortRef.current, + ); + } catch (err) { + const msg = err instanceof Error ? err.message : "生成失败"; + const isPayment = err instanceof ServerRequestError && err.status === 402; + persistScenes( + currentScenes.map((s) => + s.sceneId === scene.sceneId + ? { ...s, status: "failed", error: isPayment ? "余额不足,请充值后继续" : msg } + : s, + ), + ); + if (isPayment) { + onError?.("余额不足,请充值后再生成视频"); + renderAbortRef.current.current = true; + break; + } + } + } + + const hasFailed = currentScenes.some((s) => s.status === "failed"); + const allDone = currentScenes.every((s) => s.status === "completed" || s.status === "failed"); + const finalStage: EcommerceVideoStage = allDone + ? hasFailed + ? "partial_failed" + : "completed" + : "rendering"; + onScenesChange(currentScenes); + onStageChange(finalStage); + saveEcommerceVideoState({ + inputFingerprint, + stage: finalStage, + completedSteps, + planResult, + scenes: currentScenes, + sourceImageUrls, + }); + }, + [ + resolution, + inputFingerprint, + completedSteps, + planResult, + sourceImageUrls, + aspectRatio, + generation, + sceneStoreIdMap, + onScenesChange, + onStageChange, + onError, + ], + ); + + // ── Resume polling: re-attach waitForTask to running scenes ─ + // Used when the page is restored from keep-alive. Differs from runImagePhase/runVideoPhase + // in that it does NOT create new tasks — it only polls existing imageTaskId/taskId. + const resumePolling = useCallback( + async (stage: EcommerceVideoStage, scenes: EcommerceVideoSceneTask[]): Promise => { + renderAbortRef.current = { current: false }; + + if (stage === "imaging") { + for (const scene of scenes) { + if (renderAbortRef.current.current) break; + if (scene.status !== "running" && scene.status !== "pending") continue; + if (!scene.imageTaskId) continue; + try { + const resultUrl = await waitForTask(scene.imageTaskId, { + abortRef: renderAbortRef.current, + onProgress: (e) => + onScenesChange((prev) => + prev.map((s) => (s.sceneId === scene.sceneId ? { ...s, progress: e.progress } : s)), + ), + }); + if (resultUrl) { + onScenesChange((prev) => + prev.map((s) => + s.sceneId === scene.sceneId ? { ...s, status: "idle", progress: 100, imageUrl: resultUrl } : s, + ), + ); + } + } catch { + onScenesChange((prev) => + prev.map((s) => (s.sceneId === scene.sceneId ? { ...s, status: "idle", error: "恢复任务失败" } : s)), + ); + } + } + onScenesChange((current) => { + const allImaged = current.every((s) => s.imageUrl); + if (allImaged) onStageChange("imaged"); + return current; + }); + } + + if (stage === "rendering") { + for (const scene of scenes) { + if (renderAbortRef.current.current) break; + if (scene.status !== "running" && scene.status !== "pending") continue; + if (!scene.taskId) continue; + try { + const resultUrl = await waitForTask(scene.taskId, { + abortRef: renderAbortRef.current, + onProgress: (e) => + onScenesChange((prev) => + prev.map((s) => (s.sceneId === scene.sceneId ? { ...s, progress: e.progress } : s)), + ), + }); + if (resultUrl) { + onScenesChange((prev) => + prev.map((s) => + s.sceneId === scene.sceneId + ? { ...s, status: "completed", progress: 100, resultUrl: resultUrl } + : s, + ), + ); + } + } catch { + onScenesChange((prev) => + prev.map((s) => (s.sceneId === scene.sceneId ? { ...s, status: "failed", error: "恢复任务失败" } : s)), + ); + } + } + onScenesChange((current) => { + const hasFailed = current.some((s) => s.status === "failed"); + const allDone = current.every((s) => s.status === "completed" || s.status === "failed"); + if (allDone) onStageChange(hasFailed ? "partial_failed" : "completed"); + return current; + }); + } + }, + [onScenesChange, onStageChange], + ); + + // ── Cancel: abort planning + scene rendering ──────────────── + const cancel = useCallback(() => { + abortControllerRef.current?.abort(); + renderAbortRef.current.current = true; + onStageChange("cancelled"); + }, [onStageChange]); + + // ── Retry a single scene's video ──────────────────────────── + const retryScene = useCallback( + async (scene: EcommerceVideoSceneTask): Promise => { + if (!scene.imageUrl) return; + onScenesChange((prev) => + prev.map((s) => (s.sceneId === scene.sceneId ? { ...s, status: "pending", error: undefined } : s)), + ); + try { + await renderScene( + { + sceneId: scene.sceneId, + prompt: scene.prompt, + durationSeconds: scene.durationSeconds, + imageUrl: scene.imageUrl, + productImageUrls: sourceImageUrls, + aspectRatio, + resolution: mapResolutionToQuality(resolution), + }, + { + onSceneSubmitted: (id, taskId) => + onScenesChange((prev) => prev.map((s) => (s.sceneId === id ? { ...s, taskId, status: "running" } : s))), + onSceneProgress: (id, progress) => + onScenesChange((prev) => prev.map((s) => (s.sceneId === id ? { ...s, progress } : s))), + onSceneCompleted: (id, url) => + onScenesChange((prev) => + prev.map((s) => (s.sceneId === id ? { ...s, status: "completed", progress: 100, resultUrl: url } : s)), + ), + onSceneFailed: (id, err2) => + onScenesChange((prev) => + prev.map((s) => (s.sceneId === id ? { ...s, status: "failed", error: err2 } : s)), + ), + }, + renderAbortRef.current, + ); + } catch (err) { + onScenesChange((prev) => + prev.map((s) => + s.sceneId === scene.sceneId ? { ...s, status: "failed", error: (err as Error).message } : s, + ), + ); + } + }, + [sourceImageUrls, aspectRatio, resolution, onScenesChange], + ); + + return { + abortControllerRef, + renderAbortRef, + runImagePhase, + runVideoPhase, + resumePolling, + cancel, + retryScene, + }; +} diff --git a/src/features/ecommerce/utils/clonePersistence.ts b/src/features/ecommerce/utils/clonePersistence.ts new file mode 100644 index 0000000..0c55638 --- /dev/null +++ b/src/features/ecommerce/utils/clonePersistence.ts @@ -0,0 +1,212 @@ +// 克隆 / 电商历史的本地持久化模块。 +// 从 EcommercePage.tsx 抽出,逻辑零改动。 +// 把 localStorage 读写 + 字段校验 + 默认值收口在此,页面只调用 read/write。 +// +// 领域类型(CloneImageItem / CloneResult / CloneSavedSetting / EcommerceHistoryRecord +// 及其依赖的 type alias)也定义在此并 export,因为它们本质上是"持久化数据契约"; +// EcommercePage 从这里 re-import,避免循环依赖(类型 import 编译期擦除)。 + +import type { CloneOutputKey } from "./platformRules"; + +export type CloneSetCountKey = "selling" | "white" | "scene"; +export type CloneModelPanelTab = "scene" | "model"; +export type CloneVideoQualityKey = "standard" | "high" | "ultra"; +export type CloneReplicateLevelKey = "style" | "high"; +export type CloneReferenceMode = "upload" | "link"; + +export interface CloneImageItem { + id: string; + src: string; + name: string; + file?: File; + width?: number; + height?: number; + format?: string; + mimeType?: string; + ossKey?: string; +} + +export interface CloneResult { + id: string; + src: string; + label: string; + type?: "image" | "video"; +} + +export interface CloneSavedSetting { + id: string; + name: string; + savedAt: string; + output: CloneOutputKey; + platform: string; + market: string; + language: string; + ratio: string; + setCounts: Record; + detailModules: string[]; + modelPanelTab: CloneModelPanelTab; + modelScenes: string[]; + modelCustomScene: string; + modelGender: string; + modelAge: string; + modelEthnicity: string; + modelBody: string; + modelAppearance: string; + videoQuality: CloneVideoQualityKey; + videoDurationSeconds: number; + videoSmart: boolean; + referenceMode?: CloneReferenceMode; + replicateLevel?: CloneReplicateLevelKey; + requirement: string; +} + +export interface EcommerceHistoryRecord { + id: string; + title: string; + createdAt: number; + output: CloneOutputKey; + platform: string; + market: string; + language: string; + ratio: string; + requirement: string; + productImages: CloneImageItem[]; + results: CloneResult[]; + setResultImages: string[]; + setCounts: Record; + detailModules: string[]; + modelScenes: string[]; + referenceImages: CloneImageItem[]; + replicateLevel: CloneReplicateLevelKey; +} + +export const cloneLatestSettingStorageKey = "omniai.clone-ai.latest-setting"; +export const ecommerceHistoryStorageKey = "omniai.ecommerce.history.records"; + +export const defaultCloneSetCounts: Record = { + selling: 3, + white: 1, + scene: 3, +}; + +export const defaultCloneDetailModuleIds = ["hero", "selling", "usage", "angle", "scene", "detail"]; + +export function isCloneImageItem(item: unknown): item is CloneImageItem { + const candidate = item as Partial; + return typeof candidate.id === "string" && typeof candidate.src === "string" && typeof candidate.name === "string"; +} + +export function isCloneResult(item: unknown): item is CloneResult { + const candidate = item as Partial; + return typeof candidate.id === "string" && typeof candidate.src === "string" && typeof candidate.label === "string"; +} + +export function isEcommerceHistoryRecord(item: unknown): item is EcommerceHistoryRecord { + const candidate = item as Partial; + return ( + typeof candidate.id === "string" && + typeof candidate.title === "string" && + typeof candidate.createdAt === "number" && + typeof candidate.output === "string" && + typeof candidate.platform === "string" && + typeof candidate.market === "string" && + typeof candidate.language === "string" && + typeof candidate.ratio === "string" && + typeof candidate.requirement === "string" && + Array.isArray(candidate.productImages) && + candidate.productImages.every(isCloneImageItem) && + Array.isArray(candidate.results) && + candidate.results.every(isCloneResult) + ); +} + +export function isCloneSavedSetting(item: unknown): item is CloneSavedSetting { + const candidate = item as Partial; + return ( + typeof candidate.id === "string" && + typeof candidate.name === "string" && + typeof candidate.savedAt === "string" && + typeof candidate.output === "string" && + typeof candidate.platform === "string" && + typeof candidate.market === "string" && + typeof candidate.language === "string" && + typeof candidate.ratio === "string" && + typeof candidate.videoDurationSeconds === "number" + ); +} + +export function removeFilePayloadFromImages(images: CloneImageItem[]): CloneImageItem[] { + return images.map(({ id, src, name, width, height, format, mimeType, ossKey }) => ({ + id, + src, + name, + width, + height, + format, + mimeType, + ossKey, + })); +} + +export function normalizeEcommerceHistoryRecord(record: EcommerceHistoryRecord): EcommerceHistoryRecord { + return { + ...record, + productImages: removeFilePayloadFromImages(record.productImages), + referenceImages: removeFilePayloadFromImages(record.referenceImages ?? []), + results: record.results ?? [], + setResultImages: record.setResultImages ?? [], + setCounts: record.setCounts ?? defaultCloneSetCounts, + detailModules: record.detailModules ?? defaultCloneDetailModuleIds, + modelScenes: record.modelScenes ?? [], + replicateLevel: record.replicateLevel ?? "high", + }; +} + +export function readCloneLatestSetting(): CloneSavedSetting | null { + if (typeof window === "undefined") return null; + try { + const rawValue = window.localStorage.getItem(cloneLatestSettingStorageKey); + if (rawValue) { + const parsedValue: unknown = JSON.parse(rawValue); + if (isCloneSavedSetting(parsedValue)) return parsedValue; + } + } catch { + return null; + } + return null; +} + +export function writeCloneLatestSetting(setting: CloneSavedSetting): void { + if (typeof window === "undefined") return; + window.localStorage.setItem(cloneLatestSettingStorageKey, JSON.stringify(setting)); +} + +export function clearCloneLatestSetting(): void { + if (typeof window === "undefined") return; + window.localStorage.removeItem(cloneLatestSettingStorageKey); +} + +export function readEcommerceHistoryRecords(): EcommerceHistoryRecord[] { + if (typeof window === "undefined") return []; + try { + const rawValue = window.localStorage.getItem(ecommerceHistoryStorageKey); + if (!rawValue) return []; + const parsedValue: unknown = JSON.parse(rawValue); + if (!Array.isArray(parsedValue)) return []; + return parsedValue + .filter(isEcommerceHistoryRecord) + .map(normalizeEcommerceHistoryRecord) + .sort((a, b) => b.createdAt - a.createdAt) + .slice(0, 30); + } catch { + return []; + } +} + +export function writeEcommerceHistoryRecords(records: EcommerceHistoryRecord[]): void { + if (typeof window === "undefined") return; + window.localStorage.setItem( + ecommerceHistoryStorageKey, + JSON.stringify(records.map(normalizeEcommerceHistoryRecord).slice(0, 30)), + ); +} diff --git a/src/features/ecommerce/utils/colorUtils.test.ts b/src/features/ecommerce/utils/colorUtils.test.ts new file mode 100644 index 0000000..a8af8b3 --- /dev/null +++ b/src/features/ecommerce/utils/colorUtils.test.ts @@ -0,0 +1,122 @@ +import { describe, it, expect } from "vitest"; +import { + clampNumber, + normalizeHexColor, + hexToRgb, + rgbToHex, + parseSmartCutoutAspect, + parseSmartCutoutPercent, + hsvToRgb, + hexToHsv, +} from "./colorUtils"; + +describe("clampNumber", () => { + it("clamps below min", () => { + expect(clampNumber(-5, 0, 100)).toBe(0); + }); + it("clamps above max", () => { + expect(clampNumber(200, 0, 100)).toBe(100); + }); + it("passes through values in range", () => { + expect(clampNumber(50, 0, 100)).toBe(50); + }); +}); + +describe("normalizeHexColor", () => { + it("normalizes a valid hex", () => { + expect(normalizeHexColor("#FF8800")).toBe("#ff8800"); + }); + it("accepts hex without leading #", () => { + expect(normalizeHexColor("ff8800")).toBe("#ff8800"); + }); + it("returns null for invalid hex", () => { + expect(normalizeHexColor("#fff")).toBeNull(); + expect(normalizeHexColor("ggghhh")).toBeNull(); + expect(normalizeHexColor("")).toBeNull(); + }); +}); + +describe("hex <-> rgb round-trip", () => { + const cases: Array<[string, { r: number; g: number; b: number }]> = [ + ["#000000", { r: 0, g: 0, b: 0 }], + ["#ffffff", { r: 255, g: 255, b: 255 }], + ["#ff8800", { r: 255, g: 136, b: 0 }], + ["#2dd4bf", { r: 45, g: 212, b: 191 }], + ]; + for (const [hex, rgb] of cases) { + it(`hexToRgb(${hex}) -> rgb`, () => { + expect(hexToRgb(hex)).toEqual(rgb); + }); + it(`rgbToHex(${rgb.r},${rgb.g},${rgb.b}) -> ${hex}`, () => { + expect(rgbToHex(rgb.r, rgb.g, rgb.b)).toBe(hex); + }); + } + + it("hexToRgb returns null for invalid", () => { + expect(hexToRgb("nope")).toBeNull(); + }); + + it("rgbToHex clamps out-of-range channels", () => { + expect(rgbToHex(300, -5, 128)).toBe(rgbToHex(255, 0, 128)); + }); +}); + +describe("parseSmartCutoutAspect", () => { + it("parses a W / H aspect string", () => { + expect(parseSmartCutoutAspect("295 / 413")).toBeCloseTo(295 / 413, 5); + }); + it("handles decimals", () => { + expect(parseSmartCutoutAspect("1.5 / 2")).toBeCloseTo(0.75, 5); + }); + it("returns null when no ratio pattern is present", () => { + expect(parseSmartCutoutAspect("not-a-ratio")).toBeNull(); + expect(parseSmartCutoutAspect("")).toBeNull(); + }); + it("returns null for zero dimensions", () => { + expect(parseSmartCutoutAspect("0 / 100")).toBeNull(); + expect(parseSmartCutoutAspect("100 / 0")).toBeNull(); + }); + it("ignores leading sign (regex only matches digits)", () => { + // The regex \d+ does not match '-', so "-1 / 2" parses as 1/2. + expect(parseSmartCutoutAspect("-1 / 2")).toBeCloseTo(0.5, 5); + }); +}); + +describe("parseSmartCutoutPercent", () => { + it("parses a percentage", () => { + expect(parseSmartCutoutPercent("82%", 0.5)).toBeCloseTo(0.82, 5); + }); + it("clamps to [0.05, 1]", () => { + expect(parseSmartCutoutPercent("150%", 0.5)).toBe(1); + expect(parseSmartCutoutPercent("1%", 0.5)).toBe(0.05); + }); + it("returns fallback for non-numeric", () => { + expect(parseSmartCutoutPercent("abc", 0.5)).toBe(0.5); + }); +}); + +describe("hsv <-> rgb", () => { + it("hsvToRgb of pure red", () => { + expect(hsvToRgb(0, 100, 100)).toEqual({ r: 255, g: 0, b: 0 }); + }); + it("hsvToRgb of pure green", () => { + expect(hsvToRgb(120, 100, 100)).toEqual({ r: 0, g: 255, b: 0 }); + }); + it("hsvToRgb of white (saturation 0)", () => { + expect(hsvToRgb(0, 0, 100)).toEqual({ r: 255, g: 255, b: 255 }); + }); + + it("hexToHsv then hsvToRgb round-trips within ±2 (rounding)", () => { + const hex = "#2dd4bf"; + const hsv = hexToHsv(hex); + const rgb = hsvToRgb(hsv.h, hsv.s, hsv.v); + const original = hexToRgb(hex)!; + expect(Math.abs(rgb.r - original.r)).toBeLessThanOrEqual(2); + expect(Math.abs(rgb.g - original.g)).toBeLessThanOrEqual(2); + expect(Math.abs(rgb.b - original.b)).toBeLessThanOrEqual(2); + }); + + it("hexToHsv of white", () => { + expect(hexToHsv("#ffffff")).toEqual({ h: 0, s: 0, v: 100 }); + }); +}); diff --git a/src/features/ecommerce/utils/colorUtils.ts b/src/features/ecommerce/utils/colorUtils.ts new file mode 100644 index 0000000..a6b643c --- /dev/null +++ b/src/features/ecommerce/utils/colorUtils.ts @@ -0,0 +1,88 @@ +// 智能抠图 / 调色板用到的纯数值与颜色转换工具。 +// 从 EcommercePage.tsx 抽出,逻辑零改动,仅加 export 以便单测。 + +export const clampNumber = (value: number, min: number, max: number) => Math.min(max, Math.max(min, value)); + +export const normalizeHexColor = (value: string) => { + const clean = value.trim().replace(/^#/, ""); + if (!/^[0-9a-fA-F]{6}$/.test(clean)) return null; + return `#${clean.toLowerCase()}`; +}; + +export const hexToRgb = (value: string) => { + const normalized = normalizeHexColor(value); + if (!normalized) return null; + const numeric = Number.parseInt(normalized.slice(1), 16); + return { + r: (numeric >> 16) & 255, + g: (numeric >> 8) & 255, + b: numeric & 255, + }; +}; + +export const rgbToHex = (r: number, g: number, b: number) => + `#${[r, g, b].map((item) => clampNumber(Math.round(item), 0, 255).toString(16).padStart(2, "0")).join("")}`; + +export const parseSmartCutoutAspect = (aspect: string) => { + const match = aspect.match(/(\d+(?:\.\d+)?)\s*\/\s*(\d+(?:\.\d+)?)/); + if (!match) return null; + const width = Number(match[1]); + const height = Number(match[2]); + if (!Number.isFinite(width) || !Number.isFinite(height) || width <= 0 || height <= 0) return null; + return width / height; +}; + +export const parseSmartCutoutPercent = (value: string, fallback: number) => { + const numeric = Number(value.replace("%", "")); + if (!Number.isFinite(numeric)) return fallback; + return clampNumber(numeric / 100, 0.05, 1); +}; + +export const hsvToRgb = (h: number, s: number, v: number) => { + const hue = ((h % 360) + 360) % 360; + const saturation = clampNumber(s, 0, 100) / 100; + const value = clampNumber(v, 0, 100) / 100; + const chroma = value * saturation; + const x = chroma * (1 - Math.abs(((hue / 60) % 2) - 1)); + const match = value - chroma; + const [red, green, blue] = + hue < 60 + ? [chroma, x, 0] + : hue < 120 + ? [x, chroma, 0] + : hue < 180 + ? [0, chroma, x] + : hue < 240 + ? [0, x, chroma] + : hue < 300 + ? [x, 0, chroma] + : [chroma, 0, x]; + return { + r: (red + match) * 255, + g: (green + match) * 255, + b: (blue + match) * 255, + }; +}; + +export const hexToHsv = (value: string) => { + const rgb = hexToRgb(value) ?? { r: 255, g: 255, b: 255 }; + const red = rgb.r / 255; + const green = rgb.g / 255; + const blue = rgb.b / 255; + const max = Math.max(red, green, blue); + const min = Math.min(red, green, blue); + const delta = max - min; + const hue = + delta === 0 + ? 0 + : max === red + ? 60 * (((green - blue) / delta) % 6) + : max === green + ? 60 * ((blue - red) / delta + 2) + : 60 * ((red - green) / delta + 4); + return { + h: Math.round((hue + 360) % 360), + s: max === 0 ? 0 : Math.round((delta / max) * 100), + v: Math.round(max * 100), + }; +}; diff --git a/src/features/ecommerce/utils/platformRules.test.ts b/src/features/ecommerce/utils/platformRules.test.ts new file mode 100644 index 0000000..a702bce --- /dev/null +++ b/src/features/ecommerce/utils/platformRules.test.ts @@ -0,0 +1,95 @@ +import { describe, expect, it } from "vitest"; +import { + defaultCloneOutput, + defaultEcommercePlatform, + defaultProductSetOutput, + formatUploadedImageRatio, + getPlatformDefaultLanguage, + getPlatformDefaultRatio, + getPlatformLanguageOptions, + getPlatformRatioOptions, + getUniqueRatioOptions, + normalizeLanguageForPlatform, + normalizeMarket, + normalizePlatform, + normalizeRatioForPlatform, + platformOptions, +} from "./platformRules"; + +describe("platform defaults", () => { + it("exposes the default ecommerce platform and outputs", () => { + expect(defaultEcommercePlatform).toBe("淘宝/天猫"); + expect(defaultProductSetOutput).toBe("set"); + expect(defaultCloneOutput).toBe("set"); + }); + + it("lists platform labels for UI selectors", () => { + expect(platformOptions).toContain("淘宝/天猫"); + expect(platformOptions).toContain("亚马逊 Amazon"); + expect(platformOptions).toContain("TikTok Shop"); + }); +}); + +describe("normalizePlatform", () => { + it("normalizes legacy labels", () => { + expect(normalizePlatform("亚马逊Amazon")).toBe("亚马逊 Amazon"); + expect(normalizePlatform("亚马逊")).toBe("亚马逊 Amazon"); + }); + + it("falls back to the default platform for unknown labels", () => { + expect(normalizePlatform("unknown")).toBe("淘宝/天猫"); + }); +}); + +describe("platform ratios", () => { + it("returns mode-specific ratios", () => { + expect(getPlatformRatioOptions("淘宝/天猫", "set")).toContain("1000×1000px\u00a0\u00a0\u00a01:1"); + expect(getPlatformDefaultRatio("淘宝/天猫", "video")).toBe("1080×1920px\u00a0\u00a0\u00a09:16"); + }); + + it("normalizes an existing or partially matching ratio for a platform", () => { + expect(normalizeRatioForPlatform("淘宝/天猫", "1000×1000px\u00a0\u00a0\u00a01:1", "set")).toBe("1000×1000px\u00a0\u00a0\u00a01:1"); + expect(normalizeRatioForPlatform("淘宝/天猫", "1000×1000px", "set")).toBe("1000×1000px\u00a0\u00a0\u00a01:1"); + }); + + it("falls back to the mode default when no ratio matches", () => { + expect(normalizeRatioForPlatform("淘宝/天猫", "nope", "set")).toBe("1000×1000px\u00a0\u00a0\u00a01:1"); + }); + + it("deduplicates ratio lists without changing order", () => { + expect(getUniqueRatioOptions(["1:1", "3:4", "1:1"])).toEqual(["1:1", "3:4"]); + }); +}); + +describe("market and language rules", () => { + it("normalizes unknown markets to the default country", () => { + expect(normalizeMarket("火星")).toBe("中国"); + }); + + it("uses Chinese by default for domestic platforms", () => { + expect(getPlatformDefaultLanguage("淘宝/天猫", "美国")).toBe("中文"); + }); + + it("includes English for domestic platforms while preserving local languages", () => { + expect(getPlatformLanguageOptions("淘宝/天猫", "美国")).toEqual(["中文", "英文"]); + }); + + it("uses market languages for cross-border platforms", () => { + expect(getPlatformDefaultLanguage("亚马逊 Amazon", "日本")).toBe("日文"); + }); + + it("normalizes language aliases and falls back when not available", () => { + expect(normalizeLanguageForPlatform("亚马逊 Amazon", "日本", "日语")).toBe("日文"); + expect(normalizeLanguageForPlatform("亚马逊 Amazon", "日本", "德语")).toBe("日文"); + }); +}); + +describe("formatUploadedImageRatio", () => { + it("formats dimensions and aspect ratio", () => { + expect(formatUploadedImageRatio({ width: 750, height: 1000, format: "PNG" })).toBe("上传图片 750×1000px\u00a0\u00a0\u00a03:4\u00a0\u00a0\u00a0PNG"); + }); + + it("falls back to original ratio when dimensions are missing", () => { + expect(formatUploadedImageRatio({ format: "JPG" })).toBe("上传图片\u00a0\u00a0\u00a0原图比例\u00a0\u00a0\u00a0JPG"); + }); +}); diff --git a/src/features/ecommerce/utils/platformRules.ts b/src/features/ecommerce/utils/platformRules.ts new file mode 100644 index 0000000..4e48447 --- /dev/null +++ b/src/features/ecommerce/utils/platformRules.ts @@ -0,0 +1,479 @@ +import { formatAspectRatio, normalizeRatioToken } from "./ratioUtils"; + +export type ProductSetOutputKey = "set" | "detail" | "model" | "video"; +export type CloneOutputKey = ProductSetOutputKey | "hot"; +export type PlatformRatioModeKey = ProductSetOutputKey | "hot"; + +export interface PlatformRatioGroup { + ratios: string[]; + defaultRatio: string; +} + +export interface EcommercePlatformSpec { + label: string; + ratios: string[]; + defaultRatio: string; + ratioGroups?: Partial>; + specs: string[]; + tip?: string; + aliases?: string[]; +} +export const platformSpecOptions: EcommercePlatformSpec[] = [ + { + 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"], + }, +]; +export const platformOptions = platformSpecOptions.map((option) => option.label); +const getPlatformLogoText = (value: string) => { + const normalized = value.toLowerCase(); + if (value.includes("淘宝") || value.includes("天猫")) return "淘"; + if (value.includes("京东")) return "京"; + if (value.includes("拼多多") || value.includes("鎷煎澶")) return "拼"; + if (value.includes("抖音")) return "抖"; + if (normalized.includes("amazon")) return "a"; + if (normalized.includes("shopee")) return "S"; + if (normalized.includes("lazada")) return "L"; + if (normalized.includes("instagram")) return "IG"; + if (value.includes("速卖通") || value.includes("閫熷崠閫")) return "AE"; + if (normalized.includes("ebay")) return "eB"; + if (normalized.includes("tiktok")) return "♪"; + return value.trim().slice(0, 1).toUpperCase() || "商"; +}; +const getPlatformLogoVariant = (value: string) => { + const normalized = value.toLowerCase(); + if (value.includes("淘宝") || value.includes("天猫")) return "taobao"; + if (value.includes("京东")) return "jd"; + if (value.includes("拼多多") || value.includes("鎷煎澶")) return "pdd"; + if (value.includes("抖音")) return "douyin"; + if (normalized.includes("amazon")) return "amazon"; + if (normalized.includes("shopee")) return "shopee"; + if (normalized.includes("lazada")) return "lazada"; + if (normalized.includes("instagram")) return "instagram"; + if (value.includes("速卖通") || value.includes("閫熷崠閫")) return "aliexpress"; + if (normalized.includes("ebay")) return "ebay"; + if (normalized.includes("tiktok")) return "tiktok"; + return "default"; +}; +const getPlatformLogoMarks = (value: string) => { + if (value.includes("淘宝") || value.includes("天猫")) return ["淘", "猫"]; + return [getPlatformLogoText(value)]; +}; +export 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: ["波兰语"] }, +]; +export const marketOptions = marketLanguageOptions.map((option) => option.country); +export const languageOptions = Array.from(new Set(marketLanguageOptions.flatMap((option) => option.languages))); +export const languageAliases: Record = { + "英文": "英文", + "中文": "中文", + "英语": "英文", + "日语": "日文", + "日文": "日文", + "德语": "德文", + "德文": "德文", + "法语": "法文", + "法文": "法文", + "韩语": "韩文", + "韩文": "韩文", + "西文": "西班牙语", + "西班牙语": "西班牙语", + "葡文": "葡萄牙语", + "葡萄牙语": "葡萄牙语", + "印尼语": "印度尼西亚语", + "印度尼西亚语": "印度尼西亚语", + "菲律宾语": "菲律宾语(他加禄语)", + "菲律宾语(他加禄语)": "菲律宾语(他加禄语)", +}; +export const defaultPlatformSpec = platformSpecOptions[0]!; +export const getPlatformSpec = (value: string) => + platformSpecOptions.find((option) => option.label === value || option.aliases?.includes(value)) ?? defaultPlatformSpec; +export const legacyPlatformAliases: Record = { + "淘宝/天猫": "淘宝/天猫", + "京东": "京东", + "拼多多": "拼多多", + "抖音电商": "抖音电商", + "亚马逊Amazon": "亚马逊 Amazon", + "速卖通": "速卖通", +}; +export const normalizePlatform = (value: string) => getPlatformSpec(legacyPlatformAliases[value] ?? value).label; +export const domesticPlatformLabels = new Set(["淘宝/天猫", "京东", "拼多多", "抖音电商"]); +export const domesticPlatformLanguages = ["中文"]; +export const isDomesticPlatform = (platformValue: string) => domesticPlatformLabels.has(normalizePlatform(platformValue)); +export const getPlatformRatioGroup = (value: string, mode?: PlatformRatioModeKey): PlatformRatioGroup => { + const platformSpec = getPlatformSpec(value); + return (mode ? platformSpec.ratioGroups?.[mode] : null) ?? { + ratios: platformSpec.ratios, + defaultRatio: platformSpec.defaultRatio, + }; +}; +export const getPlatformRatioOptions = (value: string, mode?: PlatformRatioModeKey) => getPlatformRatioGroup(value, mode).ratios; +export const getPlatformDefaultRatio = (value: string, mode?: PlatformRatioModeKey) => getPlatformRatioGroup(value, mode).defaultRatio; +export const getUniqueRatioOptions = (ratios: string[]) => Array.from(new Set(ratios)); +export 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); +}; + +export const defaultMarketLanguageOption = marketLanguageOptions[0]!; +export const normalizeMarket = (value: string) => + marketLanguageOptions.some((option) => option.country === value) ? value : defaultMarketLanguageOption.country; +export const normalizeLanguage = (value: string) => languageAliases[value] ?? value; +export const uniqueLanguages = (languages: string[]) => Array.from(new Set(languages)); +export const appendEnglish = (languages: string[]) => Array.from(new Set([...languages, "英文"])); +export const getMarketLanguageOptions = (marketValue: string) => + appendEnglish((marketLanguageOptions.find((option) => option.country === marketValue) ?? defaultMarketLanguageOption).languages); +export 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, "英文"]); +}; +export const getPlatformDefaultLanguage = (platformValue: string, marketValue: string) => + isDomesticPlatform(platformValue) ? "中文" : (getPlatformLanguageOptions(platformValue, marketValue)[0] ?? languageOptions[0] ?? "英文"); +export 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); +}; + +export const defaultEcommercePlatform = "淘宝/天猫"; +export const defaultProductSetOutput: ProductSetOutputKey = "set"; +export const defaultCloneOutput: CloneOutputKey = "set"; + +export const formatUploadedImageRatio = (image?: { width?: number; height?: number; format?: string }) => { + 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}`; +}; diff --git a/src/features/ecommerce/utils/promptBuilder.test.ts b/src/features/ecommerce/utils/promptBuilder.test.ts new file mode 100644 index 0000000..715afd2 --- /dev/null +++ b/src/features/ecommerce/utils/promptBuilder.test.ts @@ -0,0 +1,83 @@ +import { describe, expect, it } from "vitest"; +import { + buildDetailModulePrompt, + buildEcommerceImagePrompt, + buildSetSubPrompt, + setCountLabels, + type EcommercePromptDetailModule, +} from "./promptBuilder"; + +const detailModules: EcommercePromptDetailModule[] = [ + { id: "hero", title: "首页焦点图", desc: "集中呈现核心利益点" }, + { id: "usage", title: "使用情境图", desc: "还原实际使用画面" }, + { id: "spec", title: "参数信息表", desc: "整理商品关键数据" }, +]; + +describe("buildDetailModulePrompt", () => { + it("uses the complete-detail prompt when no modules are selected", () => { + expect(buildDetailModulePrompt([], detailModules)).toContain("complete A+ detail layout"); + }); + + it("includes only selected modules", () => { + const prompt = buildDetailModulePrompt(["hero", "spec"], detailModules); + expect(prompt).toContain("首页焦点图: 集中呈现核心利益点"); + expect(prompt).toContain("参数信息表: 整理商品关键数据"); + expect(prompt).not.toContain("使用情境图"); + }); + + it("returns an empty prompt for unknown selected ids", () => { + expect(buildDetailModulePrompt(["missing"], detailModules)).toBe(""); + }); +}); + +describe("buildSetSubPrompt", () => { + it("builds white-background prompts with strict background guidance", () => { + const prompt = buildSetSubPrompt("white", 0, 1, "淘宝/天猫", "1:1", "中文", "中国"); + expect(prompt).toContain(setCountLabels.white.label); + expect(prompt).toContain("clean white-background product image"); + expect(prompt).toContain("Platform: 淘宝/天猫. Aspect ratio: 1:1. Language/copy: 中文. Market: 中国."); + }); + + it("adds variant guidance when generating multiple images", () => { + expect(buildSetSubPrompt("scene", 1, 3, "Amazon", "3:4", "英文", "美国")).toContain("variant 2 of 3"); + }); +}); + +describe("buildEcommerceImagePrompt", () => { + it("builds detail prompts with selected A+ modules", () => { + const prompt = buildEcommerceImagePrompt( + "detail", + "突出轻量化", + "京东", + "3:4", + "中文", + "中国", + { detailModules: ["usage"] }, + detailModules, + ); + expect(prompt).toContain("professional A+ detail page"); + expect(prompt).toContain("使用情境图: 还原实际使用画面"); + expect(prompt).toContain("Additional user requirements: 突出轻量化"); + }); + + it("builds model prompts with model attributes and scenes", () => { + const prompt = buildEcommerceImagePrompt( + "model", + "", + "Shopee", + "3:4", + "英文", + "美国", + { gender: "女", age: "青年", ethnicity: "亚洲人", body: "标准", appearance: "短发", scenes: ["都市街头"], smartScene: true }, + ); + expect(prompt).toContain("Model gender: 女."); + expect(prompt).toContain("Background scenes: 都市街头."); + expect(prompt).toContain("Use smart scene matching"); + }); + + it("builds hot-replication prompts", () => { + const prompt = buildEcommerceImagePrompt("hot", "", "TikTok Shop", "9:16", "英文", "美国"); + expect(prompt).toContain("closely replicates the style"); + expect(prompt).toContain("TikTok Shop marketplace standards"); + }); +}); diff --git a/src/features/ecommerce/utils/promptBuilder.ts b/src/features/ecommerce/utils/promptBuilder.ts new file mode 100644 index 0000000..c716420 --- /dev/null +++ b/src/features/ecommerce/utils/promptBuilder.ts @@ -0,0 +1,113 @@ +import type { CloneOutputKey } from "./platformRules"; + +export type EcommerceSetCountKey = "selling" | "white" | "scene"; + +export interface EcommercePromptDetailModule { + id: string; + title: string; + desc: string; +} + +export interface EcommerceImagePromptOptions { + gender?: string; + age?: string; + ethnicity?: string; + body?: string; + appearance?: string; + scenes?: string[]; + customScene?: string; + smartScene?: boolean; + detailModules?: string[]; +} + +export const setCountLabels: Record = { + selling: { label: "卖点图", promptDesc: "selling-point infographic image highlighting core product advantages and detail close-ups" }, + white: { label: "白底图", promptDesc: "clean white-background product photo showing the item from its best angle, studio lighting, no props" }, + scene: { label: "场景图", promptDesc: "lifestyle scene image showing the product in a realistic usage environment with natural surroundings" }, +}; + +export const buildDetailModulePrompt = (moduleIds: string[], modules: EcommercePromptDetailModule[]): string => { + if (!moduleIds.length) { + return "Generate a complete A+ detail layout with hero, selling points, usage scene, product detail, and specification modules."; + } + + const selectedModules = modules.filter((module) => moduleIds.includes(module.id)); + if (!selectedModules.length) return ""; + + const moduleList = selectedModules.map((module) => `${module.title}: ${module.desc}`).join("; "); + return `Only generate these selected A+ detail modules, no extra modules: ${moduleList}. Keep the output focused even if only one or two modules are selected.`; +}; + +export const buildSetSubPrompt = ( + countKey: EcommerceSetCountKey, + index: number, + totalCount: number, + platform: string, + ratio: string, + language: string, + market: string, +): string => { + const info = setCountLabels[countKey]; + const parts: string[] = []; + parts.push(`Generate an e-commerce ${info.label.toLowerCase()} for a product listing.`); + parts.push(info.promptDesc); + if (countKey === "white") { + parts.push("The output must be a clean white-background product image. Do not use lifestyle backgrounds, props, text overlays, or people."); + } + if (countKey === "scene") { + parts.push("The output must be a realistic usage scene image. Keep the product clearly visible and preserve its shape, color, and key details."); + } + if (countKey === "selling") { + parts.push("The output must be a selling-point graphic with clear hierarchy, concise copy, and product detail callouts."); + } + if (totalCount > 1) { + parts.push(`This is variant ${index + 1} of ${totalCount} —vary the angle, composition, or emphasis to make each distinct.`); + } + parts.push(`Platform: ${platform}. Aspect ratio: ${ratio}. Language/copy: ${language}. Market: ${market}.`); + parts.push("Must comply with platform image guidelines —proper margins, no watermark, professional quality."); + return parts.join(" "); +}; + +export const buildEcommerceImagePrompt = ( + outputKey: CloneOutputKey, + userText: string, + platform: string, + ratio: string, + language: string, + market: string, + options?: EcommerceImagePromptOptions, + detailModules: EcommercePromptDetailModule[] = [], +): string => { + const parts: string[] = []; + if (outputKey === "detail") { + parts.push("Generate a professional A+ detail page hero image for an e-commerce product listing."); + parts.push("Create a high-impact first-screen visual that combines the product photo with key selling points, usage scenes, and detailed specifications in a cohesive layout."); + parts.push(`Platform: ${platform}. Aspect ratio: ${ratio}. Language/copy: ${language}. Market: ${market}.`); + if (options?.detailModules) parts.push(buildDetailModulePrompt(options.detailModules, detailModules)); + parts.push("Follow platform A+ page best practices —clear hierarchy, professional typography, high visual impact."); + } else if (outputKey === "model") { + parts.push("Generate model/try-on lifestyle images for an e-commerce product listing."); + parts.push("Show the product being used or worn by a model in attractive lifestyle settings."); + parts.push(`Platform: ${platform}. Aspect ratio: ${ratio}. Language/copy: ${language}. Market: ${market}.`); + if (options) { + if (options.gender) parts.push(`Model gender: ${options.gender}.`); + if (options.age) parts.push(`Model age: ${options.age}.`); + if (options.ethnicity) parts.push(`Model ethnicity: ${options.ethnicity}.`); + if (options.body) parts.push(`Model body type: ${options.body}.`); + if (options.appearance) parts.push(`Model appearance details: ${options.appearance}.`); + if (options.scenes?.length) parts.push(`Background scenes: ${options.scenes.join(", ")}.`); + if (options.customScene) parts.push(`Custom background scene: ${options.customScene}.`); + if (options.smartScene) parts.push("Use smart scene matching to select the best background context."); + } + parts.push("Model should appear natural and appealing. Background should complement the product. Image must meet platform standards."); + } else if (outputKey === "hot") { + parts.push("Generate a high-conversion e-commerce product image that closely replicates the style and composition of the reference image while adapting it to the target platform."); + parts.push(`Replicate the visual style, color palette, and layout feel of the source product image, then adapt it for ${platform} marketplace standards.`); + parts.push(`Platform: ${platform}. Aspect ratio: ${ratio}. Language/copy: ${language}. Market: ${market}.`); + parts.push("The result must look professional and optimized for high click-through rate and conversion on the specified platform."); + } + if (userText.trim()) { + parts.push(`Additional user requirements: ${userText.trim()}`); + } + return parts.join(" "); +}; diff --git a/src/features/ecommerce/utils/ratioUtils.test.ts b/src/features/ecommerce/utils/ratioUtils.test.ts new file mode 100644 index 0000000..11b022b --- /dev/null +++ b/src/features/ecommerce/utils/ratioUtils.test.ts @@ -0,0 +1,170 @@ +import { describe, it, expect } from "vitest"; +import { + normalizeRatioToken, + greatestCommonDivisor, + formatAspectRatio, + getQuickSetRatioValue, + formatRatioDisplayValue, + getRatioDisplayParts, + parseRatioToAspectCss, + toSupportedImageApiRatio, + normalizeRatioForApi, +} from "./ratioUtils"; + +describe("normalizeRatioToken", () => { + it("normalizes non-breaking spaces", () => { + expect(normalizeRatioToken("800\u00a0\u00a0px")).toBe("800 px"); + }); + + it("replaces plain separators with the normal multiplication sign", () => { + expect(normalizeRatioToken("800*800")).toBe("800×800"); + }); + + it("replaces legacy mojibake multiply signs", () => { + expect(normalizeRatioToken("800\u8133800")).toBe("800×800"); + }); + + it("replaces fullwidth and legacy mojibake colons", () => { + expect(normalizeRatioToken("1:1")).toBe("1:1"); + expect(normalizeRatioToken("1\u951b?1")).toBe("1:1"); + }); + + it("collapses whitespace and trims", () => { + expect(normalizeRatioToken(" 1 : 1 ")).toBe("1 : 1"); + }); +}); + +describe("greatestCommonDivisor", () => { + it("computes GCD", () => { + expect(greatestCommonDivisor(12, 8)).toBe(4); + expect(greatestCommonDivisor(1920, 1080)).toBe(120); + }); + + it("handles zero with fallback to 1", () => { + expect(greatestCommonDivisor(0, 5)).toBe(5); + expect(greatestCommonDivisor(0, 0)).toBe(1); + }); + + it("handles negatives via abs", () => { + expect(greatestCommonDivisor(-12, 8)).toBe(4); + }); +}); + +describe("formatAspectRatio", () => { + it("reduces 1920x1080 to 16:9", () => { + expect(formatAspectRatio(1920, 1080)).toBe("16:9"); + }); + + it("reduces 750x1000 to 3:4", () => { + expect(formatAspectRatio(750, 1000)).toBe("3:4"); + }); + + it("reduces 800x800 to 1:1", () => { + expect(formatAspectRatio(800, 800)).toBe("1:1"); + }); +}); + +describe("getQuickSetRatioValue", () => { + it("passes through a canonical quick-set value", () => { + expect(getQuickSetRatioValue("1:1")).toBe("1:1"); + }); + + it("derives from a WxH size string", () => { + expect(getQuickSetRatioValue("1920×1080px")).toBe("16:9"); + expect(getQuickSetRatioValue("750×1000px")).toBe("3:4"); + }); + + it("derives from a raw ratio string", () => { + expect(getQuickSetRatioValue("9:16")).toBe("9:16"); + }); + + it("falls back to 1:1 for unparseable input", () => { + expect(getQuickSetRatioValue("unknown")).toBe("1:1"); + }); +}); + +describe("formatRatioDisplayValue", () => { + it("formats a WxHpx string with aspect suffix", () => { + expect(formatRatioDisplayValue("1000×1000px 1:1")).toBe("1000×1000px\u00a0\u00a0\u00a01:1"); + }); + + it("reformats 800x800px without explicit aspect", () => { + expect(formatRatioDisplayValue("800x800px")).toBe("800×800px\u00a0\u00a0\u00a01:1"); + }); + + it("replaces legacy mojibake product image labels", () => { + expect(formatRatioDisplayValue("\u935f\u55d7\u6427\u9365?")).toBe("商品图"); + }); +}); + +describe("getRatioDisplayParts", () => { + it("splits size and aspect", () => { + expect(getRatioDisplayParts("1000×1000px 1:1")).toEqual({ + size: "1000×1000px", + aspect: "1:1", + }); + }); + + it("uses 自适应 when no aspect present", () => { + const parts = getRatioDisplayParts("原图"); + expect(parts.aspect).toBe("自适应"); + }); +}); + +describe("parseRatioToAspectCss", () => { + it("extracts CSS aspect-ratio", () => { + expect(parseRatioToAspectCss("1000×1000px 1:1")).toBe("1000 / 1000"); + }); + + it("falls back to 1 / 1", () => { + expect(parseRatioToAspectCss("no numbers")).toBe("1 / 1"); + }); +}); + +describe("toSupportedImageApiRatio", () => { + it("snaps square to 1:1", () => { + expect(toSupportedImageApiRatio(800, 800)).toBe("1:1"); + }); + + it("snaps 750x1000 to 3:4", () => { + expect(toSupportedImageApiRatio(750, 1000)).toBe("3:4"); + }); + + it("snaps 1920x1080 to 16:9", () => { + expect(toSupportedImageApiRatio(1920, 1080)).toBe("16:9"); + }); + + it("snaps 1080x1920 to 9:16", () => { + expect(toSupportedImageApiRatio(1080, 1920)).toBe("9:16"); + }); + + it("snaps 800x600 to 4:3", () => { + expect(toSupportedImageApiRatio(800, 600)).toBe("4:3"); + }); + + it("returns 1:1 for non-finite or non-positive", () => { + expect(toSupportedImageApiRatio(NaN, 100)).toBe("1:1"); + expect(toSupportedImageApiRatio(0, 100)).toBe("1:1"); + expect(toSupportedImageApiRatio(-1, 100)).toBe("1:1"); + }); +}); + +describe("normalizeRatioForApi", () => { + it("extracts the explicit ratio from a display string", () => { + expect(normalizeRatioForApi("1000×1000px 1:1")).toBe("1:1"); + expect(normalizeRatioForApi("750×1000px 3:4")).toBe("3:4"); + }); + + it("derives ratio from a bare size string", () => { + expect(normalizeRatioForApi("1920×1080px")).toBe("16:9"); + }); + + it("returns 1:1 for unparseable input", () => { + expect(normalizeRatioForApi("")).toBe("1:1"); + expect(normalizeRatioForApi("无尺寸信息")).toBe("1:1"); + }); + + it("uses the last explicit ratio when multiple present", () => { + expect(normalizeRatioForApi("4:3 16:9")).toBe("16:9"); + }); +}); diff --git a/src/features/ecommerce/utils/ratioUtils.ts b/src/features/ecommerce/utils/ratioUtils.ts new file mode 100644 index 0000000..8340718 --- /dev/null +++ b/src/features/ecommerce/utils/ratioUtils.ts @@ -0,0 +1,125 @@ +// Ratio and dimension formatting helpers. +// Keep compatibility with a few legacy mojibake tokens, but never emit them. +// normalizeRatioForPlatform / formatUploadedImageRatio 因依赖平台规格表与 CloneImageItem, +// 暂留在 EcommercePage.tsx,后续随 platformSpec 一起整理。 + +const LEGACY_MULTIPLY_SIGN = "\u8133"; +const LEGACY_FULLWIDTH_COLON = "\u951b?"; +const LEGACY_PRODUCT_IMAGE_LABEL = "\u935f\u55d7\u6427\u9365?"; + +export const normalizeRatioToken = (value: string) => + value + .replaceAll("\u00a0", " ") + .replaceAll(LEGACY_MULTIPLY_SIGN, "×") + .replaceAll("*", "×") + .replaceAll(":", ":") + .replaceAll(LEGACY_FULLWIDTH_COLON, ":") + .replace(/\s+/g, " ") + .trim(); + +export const quickSetRatioOptions = ["1:1", "3:4", "4:3", "9:16", "16:9"]; + +export 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; +}; + +export const formatAspectRatio = (width: number, height: number) => { + const divisor = greatestCommonDivisor(width, height); + return `${Math.round(width / divisor)}:${Math.round(height / divisor)}`; +}; + +export 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]!; +}; + +export 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(LEGACY_PRODUCT_IMAGE_LABEL, "商品图") + .replace(/\s+:/g, ":") + .replace(/:\s+/g, ":"); +}; + +export 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" */ +export const parseRatioToAspectCss = (ratioStr: string): string => { + const match = ratioStr.match(/(\d+)\D+(\d+)/u); + if (!match) return "1 / 1"; + return `${match[1]} / ${match[2]}`; +}; + +export const supportedImageApiRatios = ["1:1", "3:4", "4:3", "9:16", "16:9"] as const; +export type SupportedImageApiRatio = typeof supportedImageApiRatios[number]; + +export 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"). */ +export 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])); +}; diff --git a/src/styles/standalone/base.css b/src/styles/standalone/base.css new file mode 100644 index 0000000..e9ecde1 --- /dev/null +++ b/src/styles/standalone/base.css @@ -0,0 +1,10461 @@ +.ecommerce-standalone-body { + overflow: hidden; + background: #0d0f10; +} + +.ecommerce-standalone { + min-height: 100vh; + color: #f7faf8; + background: + radial-gradient(circle at 18% 0%, rgba(34, 197, 94, 0.16), transparent 32rem), + linear-gradient(135deg, #0b0f0d 0%, #111616 42%, #101412 100%); +} + +.ecommerce-standalone__topbar { + position: fixed; + inset: 0 0 auto; + z-index: 80; + display: flex; + align-items: center; + justify-content: space-between; + gap: 16px; + min-height: 64px; + padding: 10px clamp(16px, 3vw, 32px); + border-bottom: 1px solid rgba(255, 255, 255, 0.08); + background: rgba(8, 12, 10, 0.78); + backdrop-filter: blur(18px); +} + +.ecommerce-standalone__brand, +.ecommerce-standalone__account { + display: flex; + align-items: center; + gap: 12px; +} + +.ecommerce-standalone__brand strong { + font-size: 16px; + font-weight: 800; +} + +.ecommerce-standalone__brand span, +.ecommerce-standalone__credits, +.ecommerce-standalone__user { + color: rgba(247, 250, 248, 0.66); + font-size: 13px; +} + +.ecommerce-standalone__account button { + display: inline-flex; + align-items: center; + justify-content: center; + gap: 8px; + min-height: 36px; + padding: 0 13px; + border: 1px solid rgba(255, 255, 255, 0.14); + border-radius: 8px; + color: #f7faf8; + background: rgba(255, 255, 255, 0.08); + cursor: pointer; +} + +.ecommerce-standalone__account button:hover { + border-color: rgba(59, 232, 139, 0.58); + background: rgba(59, 232, 139, 0.14); +} + +.ecommerce-standalone__content { + height: 100vh; + padding-top: 64px; +} + +/* 工作台与个人中心常驻同层,用 hidden 切换以保活生成任务状态。 + wrapper 需要撑满内容区,让内部 .product-clone-page/.local-profile-page 的 height:100% 生效。 */ +.ecommerce-standalone__page { + height: 100%; + min-height: 0; +} + +.ecommerce-standalone__page[hidden] { + display: none !important; +} + +.ecommerce-standalone__content > .error-boundary, +.ecommerce-standalone__content .product-clone-page { + height: 100%; +} + +.ecommerce-standalone__content .page-loading-center { + background: #f8f9fa; +} + +.ecommerce-standalone__content .page-loading-center__text { + color: rgba(16, 32, 44, 0.55); +} + +.ecommerce-standalone__content .page-loading-spinner { + border-color: rgba(16, 115, 204, 0.16); + border-top-color: #1073cc; +} + +.ecommerce-auth-modal { + position: fixed; + inset: 0; + z-index: 200; + display: grid; + place-items: center; + padding: 20px; +} + +.ecommerce-auth-modal__scrim { + position: absolute; + inset: 0; + border: 0; + background: rgba(0, 0, 0, 0.62); +} + +.ecommerce-auth-modal__panel { + position: relative; + z-index: 1; + width: min(420px, 100%); + padding: 24px; + border: 1px solid rgba(255, 255, 255, 0.12); + border-radius: 8px; + background: rgba(15, 22, 18, 0.96); + box-shadow: 0 24px 80px rgba(0, 0, 0, 0.42); +} + +.ecommerce-auth-modal__close { + position: absolute; + top: 12px; + right: 12px; + width: 34px; + height: 34px; + border: 1px solid rgba(255, 255, 255, 0.12); + border-radius: 8px; + color: #f7faf8; + background: rgba(255, 255, 255, 0.06); + cursor: pointer; +} + +.ecommerce-auth-modal__eyebrow { + color: #52f49f; + font-size: 12px; + font-weight: 800; +} + +.ecommerce-auth-modal h2 { + margin: 8px 0 18px; + font-size: 24px; +} + +.ecommerce-auth-modal label { + display: grid; + gap: 7px; + margin-top: 12px; + color: rgba(247, 250, 248, 0.72); + font-size: 13px; +} + +.ecommerce-auth-modal input { + width: 100%; + min-height: 42px; + border: 1px solid rgba(255, 255, 255, 0.12); + border-radius: 8px; + padding: 0 12px; + color: #f7faf8; + background: rgba(255, 255, 255, 0.07); + outline: none; +} + +.ecommerce-auth-modal input:focus { + border-color: rgba(59, 232, 139, 0.68); + box-shadow: 0 0 0 3px rgba(59, 232, 139, 0.14); +} + +.ecommerce-auth-modal__notice, +.ecommerce-auth-modal__error { + margin: 0 0 10px; + font-size: 13px; + line-height: 1.6; +} + +.ecommerce-auth-modal__notice { + color: rgba(247, 250, 248, 0.72); +} + +.ecommerce-auth-modal__error { + color: #ff9a9a; +} + +.ecommerce-auth-modal__submit, +.ecommerce-auth-modal__switch { + width: 100%; + min-height: 42px; + margin-top: 16px; + border-radius: 8px; + cursor: pointer; +} + +.ecommerce-auth-modal__submit { + display: inline-flex; + align-items: center; + justify-content: center; + gap: 8px; + border: 0; + color: #062012; + background: #52f49f; + font-weight: 800; +} + +.ecommerce-auth-modal__submit:disabled { + opacity: 0.7; + cursor: wait; +} + +.ecommerce-auth-modal__switch { + border: 0; + color: rgba(247, 250, 248, 0.78); + background: transparent; +} + +@media (max-width: 720px) { + .ecommerce-standalone__topbar { + min-height: 58px; + } + + .ecommerce-standalone__brand span, + .ecommerce-standalone__credits { + display: none; + } + + .ecommerce-standalone__content { + padding-top: 58px; + } +} + +/* Standalone ecommerce blue/white theme overrides. */ +.ecommerce-standalone-body { + background: #05233f; +} + +.ecommerce-standalone { + color: #f5fbff; + background: + radial-gradient(circle at 13% 0%, rgba(22, 200, 223, 0.42), transparent 31rem), + radial-gradient(circle at 80% 10%, rgba(8, 118, 216, 0.36), transparent 34rem), + linear-gradient(135deg, #083c67 0%, #062a4e 45%, #051f3d 100%); +} + +.ecommerce-standalone__topbar { + border-bottom-color: rgba(126, 235, 255, 0.22); + background: + linear-gradient(90deg, rgba(7, 72, 121, 0.94), rgba(4, 37, 75, 0.92)); +} + +.ecommerce-standalone__brand::before { + width: 34px; + height: 34px; + flex: 0 0 auto; + border-radius: 10px; + background: + linear-gradient(135deg, #16c8df 0 46%, transparent 46% 54%, #31d7f0 54% 100%), + linear-gradient(45deg, #0876d8, #16c8df); + box-shadow: 0 10px 26px rgba(22, 200, 223, 0.34); + content: ""; + transform: rotate(45deg); +} + +.ecommerce-standalone__brand strong { + color: #f7fbff; +} + +.ecommerce-standalone__brand span, +.ecommerce-standalone__credits, +.ecommerce-standalone__user { + color: rgba(226, 242, 255, 0.62); +} + +.ecommerce-standalone__account button { + border-color: rgba(126, 235, 255, 0.22); + color: #f5fbff; + background: rgba(3, 35, 68, 0.5); +} + +.ecommerce-standalone__account button:hover { + border-color: rgba(22, 200, 223, 0.66); + background: rgba(22, 200, 223, 0.18); +} + +.ecommerce-auth-modal__panel { + border-color: rgba(126, 235, 255, 0.24); + background: linear-gradient(180deg, rgba(6, 54, 94, 0.98), rgba(4, 35, 68, 0.98)); +} + +.ecommerce-auth-modal__eyebrow { + color: #16c8df; +} + +.ecommerce-auth-modal input:focus { + border-color: rgba(22, 200, 223, 0.7); + box-shadow: 0 0 0 3px rgba(22, 200, 223, 0.16); +} + +.ecommerce-auth-modal__submit { + color: #021b2e; + background: linear-gradient(135deg, #16c8df, #18a7ff); +} + +/* Standalone ecommerce: final white theme with #1ebddb accent. */ +.ecommerce-standalone-body { + background: #f8f9fa !important; +} + +.ecommerce-standalone { + color: #10202c !important; + background: #f8f9fa !important; +} + +.ecommerce-standalone__topbar { + border-bottom-color: rgba(30, 189, 219, 0.16) !important; + background: #f8f9fa !important; +} + +.ecommerce-standalone__brand::before { + content: none !important; +} + +.ecommerce-standalone__logo { + position: relative; + display: inline-block; + width: 36px; + height: 36px; + flex: 0 0 36px; + overflow: hidden; + border-radius: 10px; +} + +.ecommerce-standalone__logo i { + position: absolute; + width: 22px; + height: 22px; + border-radius: 8px; +} + +.ecommerce-standalone__logo i:nth-child(1) { + left: 1px; + top: 1px; + background: linear-gradient(135deg, #1f86df 0%, #1974c7 100%); +} + +.ecommerce-standalone__logo i:nth-child(2) { + right: 1px; + top: 1px; + background: linear-gradient(135deg, #24c9ee 0%, #16a7d8 100%); +} + +.ecommerce-standalone__logo i:nth-child(3) { + left: 1px; + bottom: 1px; + background: linear-gradient(135deg, #26c8e9 0%, #17addb 100%); +} + +.ecommerce-standalone__logo i:nth-child(4) { + right: 1px; + bottom: 1px; + background: linear-gradient(135deg, #1778ca 0%, #116abd 100%); +} + +.ecommerce-standalone__logo::before { + position: absolute; + inset: 8px; + z-index: 2; + background: #f8f9fa; + content: ""; + transform: rotate(45deg); +} + +.ecommerce-standalone__logo::after { + position: absolute; + inset: 0; + z-index: 3; + border-radius: inherit; + box-shadow: inset 0 0 0 1px rgba(16, 32, 44, 0.03); + content: ""; + pointer-events: none; +} + +.ecommerce-standalone__brand strong { + color: #10202c !important; +} + +.ecommerce-standalone__brand span, +.ecommerce-standalone__credits, +.ecommerce-standalone__user { + color: #6b7c88 !important; +} + +.ecommerce-standalone__account button { + border-color: rgba(30, 189, 219, 0.22) !important; + color: #10202c !important; + background: #fbfdfe !important; +} + +.ecommerce-standalone__account button:hover { + border-color: #1ebddb !important; + background: rgba(30, 189, 219, 0.1) !important; +} + +.ecommerce-auth-modal__panel { + border-color: rgba(30, 189, 219, 0.22) !important; + background: #fbfdfe !important; +} + +.ecommerce-auth-modal__eyebrow { + color: #1ebddb !important; +} + +.ecommerce-auth-modal h2, +.ecommerce-auth-modal label { + color: #10202c !important; +} + +.ecommerce-auth-modal input { + color: #10202c !important; + background: #f7fbfc !important; + border-color: rgba(30, 189, 219, 0.2) !important; +} + +.ecommerce-auth-modal input:focus { + border-color: #1ebddb !important; + box-shadow: 0 0 0 3px rgba(30, 189, 219, 0.14) !important; +} + +.ecommerce-auth-modal__submit { + color: #ffffff !important; + background: #1ebddb !important; +} + +/* Auth modal: dark OmniAI commerce sign-in/register experience. */ +.ecommerce-auth-modal { + place-items: start center !important; + overflow: auto; + padding: clamp(28px, 7vh, 58px) 18px 34px !important; +} + +.ecommerce-auth-modal__scrim { + background: rgba(12, 15, 17, 0.78) !important; + backdrop-filter: blur(8px); +} + +.ecommerce-auth-modal__panel { + width: min(560px, 100%) !important; + padding: 28px clamp(24px, 5vw, 48px) 30px !important; + border-color: rgba(255, 255, 255, 0.08) !important; + border-radius: 0 !important; + color: #f6fbff !important; + background: linear-gradient(180deg, #171b1d 0%, #15191b 100%) !important; + box-shadow: 0 24px 80px rgba(0, 0, 0, 0.42) !important; +} + +.ecommerce-auth-modal__close { + border-color: rgba(255, 255, 255, 0.1) !important; + color: #aab5bb !important; + background: rgba(255, 255, 255, 0.04) !important; +} + +.ecommerce-auth-modal__logo { + position: relative; + display: grid; + place-items: center; + width: 58px; + height: 58px; + margin: 0 auto 14px; + overflow: visible; + border-radius: 0; + background: transparent; + box-shadow: none; +} + +.ecommerce-auth-modal__logo img { + display: block; + width: 58px; + height: 58px; + object-fit: contain; +} + +.ecommerce-auth-modal__logo i, +.ecommerce-auth-modal__logo::before { + content: none !important; + display: none !important; +} + +.ecommerce-auth-modal__logo i:nth-child(1) { + left: 1px; + top: 1px; + background: linear-gradient(135deg, #2289e6, #176fc2); +} + +.ecommerce-auth-modal__logo i:nth-child(2) { + right: 1px; + top: 1px; + background: linear-gradient(135deg, #29d2ee, #18a9d8); +} + +.ecommerce-auth-modal__logo i:nth-child(3) { + left: 1px; + bottom: 1px; + background: linear-gradient(135deg, #2ed1ea, #17acd8); +} + +.ecommerce-auth-modal__logo i:nth-child(4) { + right: 1px; + bottom: 1px; + background: linear-gradient(135deg, #1879ca, #1268b9); +} + +.ecommerce-auth-modal__logo::before { + position: absolute; + inset: 13px; + z-index: 2; + background: #171b1d; + content: ""; + transform: rotate(45deg); +} + +.ecommerce-auth-modal h2 { + margin: 0 !important; + color: #f7fbff !important; + font-size: 30px !important; + font-weight: 900; + line-height: 1.15; + text-align: center; +} + +.ecommerce-auth-modal__subtitle { + margin: 8px 0 24px; + color: #95a3aa; + font-size: 15px; + text-align: center; +} + +.ecommerce-auth-modal__tabs, +.ecommerce-auth-modal__methods { + display: grid; + gap: 8px; +} + +.ecommerce-auth-modal__tabs { + grid-template-columns: repeat(2, minmax(0, 1fr)); + margin-bottom: 22px; + padding: 4px; + border: 1px solid rgba(255, 255, 255, 0.1); + border-radius: 10px; +} + +.ecommerce-auth-modal__methods { + grid-template-columns: repeat(3, minmax(0, 1fr)); + margin-bottom: 18px; +} + +.ecommerce-auth-modal__tabs button, +.ecommerce-auth-modal__methods button { + min-height: 46px; + border: 1px solid transparent; + border-radius: 9px; + color: #d4dde2; + background: transparent; + font-size: 15px; + font-weight: 900; + cursor: pointer; +} + +.ecommerce-auth-modal__methods button { + border-color: rgba(255, 255, 255, 0.1); + background: rgba(255, 255, 255, 0.025); +} + +.ecommerce-auth-modal__tabs button.is-active, +.ecommerce-auth-modal__methods button.is-active { + border-color: rgba(30, 189, 219, 0.74); + color: #0df7a8; + background: rgba(15, 235, 154, 0.18); +} + +.ecommerce-auth-field { + display: grid !important; + gap: 8px !important; + margin-top: 14px !important; + color: #d9e5e9 !important; + font-size: 14px !important; + font-weight: 900; +} + +.ecommerce-auth-field > span { + display: inline-flex; + align-items: center; + gap: 7px; +} + +.ecommerce-auth-modal input, +.ecommerce-auth-phone-row, +.ecommerce-auth-code-row { + min-height: 50px; +} + +.ecommerce-auth-modal input { + width: 100%; + border: 1px solid rgba(255, 255, 255, 0.1) !important; + border-radius: 10px !important; + padding: 0 14px !important; + color: #eaf6f8 !important; + background: rgba(255, 255, 255, 0.035) !important; + font-size: 16px; +} + +.ecommerce-auth-modal input::placeholder { + color: #82919a; +} + +.ecommerce-auth-modal input:focus { + border-color: #1ebddb !important; + box-shadow: 0 0 0 3px rgba(30, 189, 219, 0.2) !important; +} + +.ecommerce-auth-phone-row, +.ecommerce-auth-code-row { + display: grid; + align-items: center; + gap: 12px; +} + +.ecommerce-auth-phone-row { + grid-template-columns: 58px minmax(0, 1fr); +} + +.ecommerce-auth-phone-row b { + display: grid; + place-items: center; + min-height: 50px; + border-right: 1px solid rgba(255, 255, 255, 0.08); + color: #dce8ec; + background: rgba(255, 255, 255, 0.035); + border-radius: 10px 0 0 10px; +} + +.ecommerce-auth-phone-row input { + border-radius: 0 10px 10px 0 !important; +} + +.ecommerce-auth-code-row { + grid-template-columns: minmax(0, 1fr) 112px; +} + +.ecommerce-auth-code-row button { + min-height: 50px; + border: 1px solid rgba(255, 255, 255, 0.1); + border-radius: 10px; + color: #8f9da5; + background: rgba(255, 255, 255, 0.035); + font-weight: 900; +} + +.ecommerce-auth-modal__forgot { + display: block; + margin: 12px 0 0 auto; + border: 0; + color: #0df7a8; + background: transparent; + font-weight: 900; + cursor: pointer; +} + +.ecommerce-auth-modal__error { + margin: 10px 0 0 !important; + color: #ff6b74 !important; +} + +.ecommerce-auth-modal__submit { + min-height: 52px !important; + margin-top: 18px !important; + border: 0 !important; + border-radius: 10px !important; + color: #061817 !important; + background: linear-gradient(135deg, #0df7a8, #00f089) !important; + font-size: 17px; + font-weight: 950; +} + +.ecommerce-auth-modal__agreement { + margin: 16px 0 20px; + color: #83919a; + font-size: 12px; + text-align: center; +} + +.ecommerce-auth-modal__agreement a { + color: #0df7a8; + font-weight: 900; + text-decoration: none; +} + +.ecommerce-auth-modal__divider { + display: grid; + grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr); + align-items: center; + gap: 12px; + color: #737f86; + font-size: 13px; +} + +.ecommerce-auth-modal__divider::before, +.ecommerce-auth-modal__divider::after { + height: 1px; + background: rgba(255, 255, 255, 0.08); + content: ""; +} + +.ecommerce-auth-modal__mobile-alt { + display: grid; + place-items: center; + width: 48px; + height: 48px; + margin: 14px auto 0; + border: 1px solid rgba(255, 255, 255, 0.1); + border-radius: 999px; + color: #d2dde2; + background: rgba(255, 255, 255, 0.035); + font-size: 20px; + cursor: pointer; +} + +@media (max-width: 620px) { + .ecommerce-auth-modal__panel { + padding: 24px 18px 28px !important; + } + + .ecommerce-auth-modal__methods, + .ecommerce-auth-code-row { + grid-template-columns: minmax(0, 1fr); + } +} + +/* Auth modal localized to the ecommerce blue/white UI. */ +.ecommerce-auth-modal { + min-height: 100dvh; + place-items: center !important; + overflow: auto; + padding: clamp(18px, 4vh, 42px) 18px !important; +} + +.ecommerce-auth-modal__scrim { + background: + radial-gradient(circle at 50% 42%, rgba(29, 190, 219, 0.18), transparent 34rem), + rgba(248, 249, 250, 0.72) !important; + animation: ecommerce-auth-scrim-in 180ms ease both; +} + +.ecommerce-auth-modal__panel { + border-color: rgba(16, 115, 204, 0.14) !important; + color: #10202c !important; + background: #feffff !important; + box-shadow: 0 28px 90px rgba(16, 115, 204, 0.16), 0 12px 34px rgba(20, 80, 100, 0.08) !important; + animation: ecommerce-auth-panel-in 220ms cubic-bezier(0.22, 1, 0.36, 1) both; +} + +.ecommerce-auth-modal__close, +.ecommerce-auth-modal__mobile-alt, +.ecommerce-auth-code-row button { + border-color: rgba(16, 115, 204, 0.14) !important; + color: #566b78 !important; + background: #f8fbfc !important; +} + +.ecommerce-auth-modal__logo::before { + background: #feffff !important; +} + +.ecommerce-auth-modal h2 { + color: #10202c !important; +} + +.ecommerce-auth-modal__subtitle, +.ecommerce-auth-modal__agreement, +.ecommerce-auth-modal__divider { + color: #6b7c88 !important; +} + +.ecommerce-auth-modal__tabs { + border-color: rgba(16, 115, 204, 0.14) !important; + background: #f3f8fa; +} + +.ecommerce-auth-modal__tabs button, +.ecommerce-auth-modal__methods button { + color: #425765 !important; +} + +.ecommerce-auth-modal__methods button { + border-color: rgba(16, 115, 204, 0.14) !important; + background: #feffff !important; +} + +.ecommerce-auth-modal__tabs button.is-active, +.ecommerce-auth-modal__methods button.is-active { + border-color: rgba(29, 190, 219, 0.66) !important; + color: #1073cc !important; + background: rgba(29, 190, 219, 0.12) !important; + box-shadow: inset 0 0 0 1px rgba(16, 115, 204, 0.08); +} + +.ecommerce-auth-field { + color: #10202c !important; +} + +.ecommerce-auth-modal input { + border-color: rgba(16, 115, 204, 0.14) !important; + color: #10202c !important; + background: #f8fbfc !important; +} + +.ecommerce-auth-modal input::placeholder { + color: #8da0ab !important; +} + +.ecommerce-auth-modal input:focus { + border-color: #1dbedb !important; + box-shadow: 0 0 0 3px rgba(29, 190, 219, 0.16) !important; +} + +.ecommerce-auth-phone-row b { + border-right-color: rgba(16, 115, 204, 0.14) !important; + color: #1073cc !important; + background: #f3f8fa !important; +} + +.ecommerce-auth-modal__forgot, +.ecommerce-auth-modal__agreement a { + color: #1073cc !important; +} + +.ecommerce-auth-modal__submit { + color: #ffffff !important; + background: linear-gradient(135deg, #1073cc, #1dbedb) !important; + box-shadow: 0 16px 34px rgba(29, 190, 219, 0.24); +} + +.ecommerce-auth-modal__divider::before, +.ecommerce-auth-modal__divider::after { + background: rgba(16, 115, 204, 0.12) !important; +} + +@keyframes ecommerce-auth-scrim-in { + from { opacity: 0; } + to { opacity: 1; } +} + +@keyframes ecommerce-auth-panel-in { + from { + opacity: 0; + transform: translateY(14px) scale(0.985); + } + to { + opacity: 1; + transform: translateY(0) scale(1); + } +} + +@media (prefers-reduced-motion: reduce) { + .ecommerce-auth-modal__scrim, + .ecommerce-auth-modal__panel { + animation: none !important; + } +} + +/* Local auth UI typography and rounder modal controls. */ +.ecommerce-standalone, +.ecommerce-standalone button, +.ecommerce-standalone input, +.ecommerce-auth-modal, +.ecommerce-auth-modal button, +.ecommerce-auth-modal input { + font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif !important; +} + +.ecommerce-auth-modal { + color: #10202c; + font-weight: 500; +} + +.ecommerce-auth-modal__panel { + border-radius: 30px !important; +} + +.ecommerce-auth-modal h2 { + color: #10202c !important; + font-weight: 900 !important; +} + +.ecommerce-auth-modal__eyebrow, +.ecommerce-auth-modal__subtitle, +.ecommerce-auth-modal__agreement, +.ecommerce-auth-modal__divider, +.ecommerce-auth-field, +.ecommerce-auth-modal input { + font-weight: 500 !important; +} + +.ecommerce-auth-modal__tabs button, +.ecommerce-auth-modal__methods button, +.ecommerce-auth-code-row button, +.ecommerce-auth-modal__forgot, +.ecommerce-auth-modal__submit, +.ecommerce-auth-modal__switch, +.ecommerce-auth-modal__mobile-alt { + font-weight: 600 !important; +} + +.ecommerce-auth-modal__close, +.ecommerce-auth-modal__tabs, +.ecommerce-auth-modal__methods, +.ecommerce-auth-modal__tabs button, +.ecommerce-auth-modal__methods button, +.ecommerce-auth-modal input, +.ecommerce-auth-code-row button, +.ecommerce-auth-modal__submit { + border-radius: 16px !important; +} + +.ecommerce-auth-phone-row b { + font-weight: 600 !important; + border-radius: 16px 0 0 16px !important; +} + +.ecommerce-auth-phone-row input { + border-radius: 0 16px 16px 0 !important; +} + +/* Logged-in profile menu and standalone profile page. */ +.ecommerce-standalone__brand { + border: 0; + color: inherit; + background: transparent; + cursor: pointer; +} + +.ecommerce-profile-menu { + position: relative; + display: flex; + align-items: center; + gap: 12px; +} + +.ecommerce-profile-menu__trigger { + min-height: 42px !important; + padding: 0 14px 0 6px !important; + border-radius: 16px !important; + color: #10202c !important; + background: #feffff !important; + box-shadow: 0 10px 28px rgba(16, 115, 204, 0.08); +} + +.local-user-avatar { + display: inline-grid; + flex: 0 0 auto; + place-items: center; + overflow: hidden; + border: 2px solid rgba(30, 189, 219, 0.62); + border-radius: 14px; + color: #fff; + background: linear-gradient(135deg, #1073cc, #1dbedb); + font-weight: 800; +} + +.local-user-avatar img { + width: 100%; + height: 100%; + object-fit: cover; +} + +.local-user-avatar--sm { + width: 34px; + height: 34px; +} + +.local-user-avatar--md { + width: 52px; + height: 52px; +} + +.local-user-avatar--lg { + width: 96px; + height: 96px; + border-radius: 28px; +} + +.ecommerce-profile-popover { + position: absolute; + top: calc(100% + 12px); + right: 0; + z-index: 120; + width: 336px; + padding: 20px; + border: 1px solid rgba(16, 115, 204, 0.14); + border-radius: 24px; + color: #10202c; + background: rgba(254, 255, 255, 0.98); + box-shadow: 0 28px 80px rgba(16, 115, 204, 0.18); + animation: ecommerce-auth-panel-in 180ms cubic-bezier(0.22, 1, 0.36, 1) both; +} + +.ecommerce-profile-popover__head { + display: flex; + align-items: center; + gap: 14px; + padding-bottom: 16px; + border-bottom: 1px solid rgba(16, 115, 204, 0.12); +} + +.ecommerce-profile-popover__head strong { + display: block; + color: #10202c; + font-size: 18px; + font-weight: 900; +} + +.ecommerce-profile-popover__head span { + display: block; + margin-top: 2px; + color: #526675; + font-weight: 500; +} + +.ecommerce-profile-popover__stats { + display: grid; + gap: 9px; + margin: 16px 0; + padding-bottom: 16px; + border-bottom: 1px solid rgba(16, 115, 204, 0.12); +} + +.ecommerce-profile-popover__stats div { + display: flex; + align-items: center; + justify-content: space-between; + gap: 12px; +} + +.ecommerce-profile-popover__stats dt, +.ecommerce-profile-popover__stats dd { + margin: 0; +} + +.ecommerce-profile-popover__stats dt { + display: inline-flex; + align-items: center; + gap: 8px; + color: #526675; + font-weight: 500; +} + +.ecommerce-profile-popover__stats dd { + color: #10202c; + font-weight: 700; +} + +.ecommerce-profile-popover__actions { + display: grid; + gap: 12px; +} + +.ecommerce-profile-popover__actions button, +.local-profile-card button, +.local-profile-page__back { + display: inline-flex; + align-items: center; + justify-content: center; + gap: 8px; + min-height: 42px; + border: 1px solid rgba(16, 115, 204, 0.14); + border-radius: 15px; + color: #10202c; + background: #f8fbfc; + font-weight: 600; + cursor: pointer; +} + +.ecommerce-profile-popover__actions button.is-primary, +.local-profile-card__primary { + border-color: rgba(29, 190, 219, 0.45) !important; + color: #fff !important; + background: linear-gradient(135deg, #1073cc, #1dbedb) !important; +} + +.ecommerce-profile-popover__actions button.is-danger, +.local-profile-card__danger { + color: #d04444 !important; +} + +.local-profile-page { + height: 100%; + overflow: auto; + color: #10202c; + background: + radial-gradient(42rem 18rem at 48% 7%, rgba(29, 190, 219, 0.18), transparent 72%), + linear-gradient(180deg, #f8f9fa 0%, #eef9fc 46%, #f8f9fa 100%); +} + +.local-profile-page__hero { + position: relative; + min-height: 210px; + background: + linear-gradient(180deg, rgba(16, 115, 204, 0.2), rgba(248, 249, 250, 0.92)), + radial-gradient(36rem 15rem at 34% 8%, rgba(16, 115, 204, 0.34), transparent 70%), + radial-gradient(32rem 14rem at 66% 18%, rgba(29, 190, 219, 0.28), transparent 72%); +} + +.local-profile-page__back { + position: absolute; + top: 24px; + right: 32px; + background: rgba(254, 255, 255, 0.84); + backdrop-filter: blur(14px); +} + +.local-profile-page__body { + display: grid; + grid-template-columns: 342px minmax(0, 1fr); + gap: 30px; + width: min(1380px, calc(100% - 56px)); + margin: -72px auto 48px; +} + +.local-profile-card, +.local-profile-tabs, +.local-profile-works { + border: 1px solid rgba(16, 115, 204, 0.12); + border-radius: 24px; + background: rgba(254, 255, 255, 0.94); + box-shadow: 0 24px 70px rgba(16, 115, 204, 0.1); +} + +.local-profile-card { + position: sticky; + top: 84px; + align-self: start; + padding: 24px; +} + +.local-profile-card__head { + display: grid; + justify-items: center; + gap: 10px; + text-align: center; +} + +.local-profile-card__avatar-wrap { + position: relative; +} + +.local-profile-card__avatar-wrap > .anticon { + position: absolute; + right: -2px; + bottom: 6px; + color: #1dbedb; + background: #feffff; + border-radius: 999px; + font-size: 20px; +} + +.local-profile-card__head strong { + font-size: 24px; + font-weight: 900; +} + +.local-profile-card__uid { + width: 100%; + padding: 10px 12px; + border: 1px solid rgba(16, 115, 204, 0.12); + border-radius: 999px; + color: #526675; +} + +.local-profile-card__stats, +.local-profile-card__credits, +.local-profile-card__meta { + display: grid; + gap: 10px; + margin-top: 18px; +} + +.local-profile-card__stats { + grid-template-columns: repeat(3, minmax(0, 1fr)); +} + +.local-profile-card__stats span, +.local-profile-card__credits span, +.local-profile-card__meta span { + display: grid; + gap: 4px; + padding: 14px; + border: 1px solid rgba(16, 115, 204, 0.12); + border-radius: 16px; + background: #f8fbfc; +} + +.local-profile-card strong { + color: #10202c; +} + +.local-profile-card em { + color: #637889; + font-style: normal; + font-weight: 500; +} + +.local-profile-card__credits { + grid-template-columns: 1fr 1fr; +} + +.local-profile-card__credits span:first-child { + grid-column: span 2; + color: #1073cc; + background: rgba(29, 190, 219, 0.1); +} + +.local-profile-card__credits strong, +.local-profile-card__meta strong { + font-size: 18px; +} + +.local-profile-card__primary, +.local-profile-card__secondary, +.local-profile-card__danger { + width: 100%; + margin-top: 12px; +} + +.local-profile-main { + display: grid; + gap: 18px; + min-width: 0; +} + +.local-profile-tabs { + display: grid; + grid-template-columns: repeat(4, minmax(0, 1fr)); + gap: 8px; + padding: 8px; +} + +.local-profile-tabs button { + min-height: 44px; + border: 1px solid rgba(16, 115, 204, 0.12); + border-radius: 16px; + color: #526675; + background: #f8fbfc; + font-weight: 700; +} + +.local-profile-tabs button.is-active { + border-color: rgba(29, 190, 219, 0.5); + color: #1073cc; + background: rgba(29, 190, 219, 0.12); +} + +.local-profile-works { + padding: 24px; +} + +.local-profile-works header { + display: flex; + align-items: center; + justify-content: space-between; + gap: 16px; + margin-bottom: 18px; +} + +.local-profile-works header strong { + display: block; + font-size: 22px; + font-weight: 900; +} + +.local-profile-works header span, +.local-profile-works header em { + color: #637889; + font-style: normal; + font-weight: 500; +} + +.local-profile-works header em { + padding: 7px 14px; + border: 1px solid rgba(29, 190, 219, 0.32); + border-radius: 999px; + color: #1073cc; + background: rgba(29, 190, 219, 0.08); +} + +.local-profile-work-grid { + display: grid; + grid-template-columns: repeat(3, minmax(220px, 1fr)); + gap: 14px; +} + +.local-profile-work-card { + display: grid; + grid-template-columns: 106px minmax(0, 1fr); + gap: 14px; + min-height: 132px; + padding: 14px; + border: 1px solid rgba(16, 115, 204, 0.12); + border-radius: 18px; + background: #f8fbfc; +} + +.local-profile-work-card img { + width: 106px; + height: 106px; + border-radius: 14px; + object-fit: cover; +} + +.local-profile-work-card span { + display: inline-flex; + width: max-content; + margin-bottom: 5px; + padding: 3px 9px; + border-radius: 999px; + color: #1073cc; + background: rgba(29, 190, 219, 0.12); + font-size: 12px; + font-weight: 700; +} + +.local-profile-work-card strong { + display: block; + overflow: hidden; + color: #10202c; + font-weight: 900; + text-overflow: ellipsis; + white-space: nowrap; +} + +.local-profile-work-card p { + display: -webkit-box; + overflow: hidden; + margin: 6px 0 10px; + color: #526675; + font-weight: 500; + -webkit-box-orient: vertical; + -webkit-line-clamp: 2; +} + +.local-profile-work-card em { + color: #7b8e9a; + font-style: normal; + font-weight: 500; +} + +.local-profile-work-grid--empty { + display: block; +} + +.local-profile-empty { + display: grid; + min-height: 220px; + place-items: center; + gap: 8px; + padding: 36px 20px; + border: 1px dashed rgba(30, 189, 219, 0.22); + border-radius: 18px; + color: #6c7d88; + text-align: center; + background: #f8fbfc; +} + +.local-profile-empty strong { + color: #10202c; + font-size: 15px; +} + +.local-profile-empty span { + max-width: 360px; + font-size: 13px; + line-height: 1.6; +} + +@media (max-width: 980px) { + .local-profile-page__body { + grid-template-columns: minmax(0, 1fr); + } + + .local-profile-card { + position: static; + } + + .local-profile-work-grid { + grid-template-columns: repeat(2, minmax(0, 1fr)); + } +} + +@media (max-width: 640px) { + .ecommerce-profile-popover { + right: -8px; + width: min(336px, calc(100vw - 24px)); + } + + .local-profile-page__body { + width: calc(100% - 24px); + } + + .local-profile-tabs, + .local-profile-work-grid { + grid-template-columns: minmax(0, 1fr); + } +} + +/* Final account popover corrections: independent modal, compact metric rows. */ +.ecommerce-standalone .ecommerce-profile-menu { + position: static !important; +} + +.ecommerce-standalone .ecommerce-profile-menu__trigger { + display: inline-flex !important; + align-items: center !important; + justify-content: center !important; + gap: 9px !important; + min-height: 44px !important; + padding: 0 15px 0 7px !important; + border-radius: 16px !important; +} + +.ecommerce-standalone .ecommerce-standalone__credits { + display: inline-flex !important; + align-items: center !important; + justify-content: center !important; + min-height: 40px !important; + padding: 0 14px !important; + border: 1px solid rgba(30, 189, 219, 0.14) !important; + border-radius: 15px !important; + color: #10202c !important; + background: #f8f9fa !important; + box-shadow: 0 10px 26px rgba(16, 115, 204, 0.06) !important; + font-size: 13px !important; + font-weight: 600 !important; + line-height: 1 !important; + white-space: nowrap !important; +} + +.ecommerce-standalone .ecommerce-profile-popover__backdrop { + position: fixed !important; + inset: 0 !important; + z-index: 118 !important; + min-height: 0 !important; + padding: 0 !important; + border: 0 !important; + border-radius: 0 !important; + background: transparent !important; + box-shadow: none !important; +} + +.ecommerce-standalone .ecommerce-profile-popover { + position: fixed !important; + top: 62px !important; + right: 22px !important; + z-index: 130 !important; + display: block !important; + width: min(338px, calc(100vw - 28px)) !important; + max-height: calc(100vh - 82px); + overflow: auto; + padding: 20px !important; + border: 1px solid rgba(16, 115, 204, 0.16) !important; + border-radius: 20px !important; + color: #10202c !important; + background: rgba(254, 255, 255, 0.98) !important; + box-shadow: 0 28px 80px rgba(16, 115, 204, 0.18) !important; +} + +.ecommerce-standalone .ecommerce-profile-popover__stats { + display: grid !important; + grid-template-columns: minmax(0, 1fr) !important; + gap: 10px !important; + margin: 16px 0 !important; + padding: 0 0 16px !important; +} + +.ecommerce-standalone .ecommerce-profile-popover__stats div { + display: flex !important; + flex-direction: row !important; + align-items: center !important; + justify-content: space-between !important; + gap: 16px !important; + min-height: 24px !important; +} + +.ecommerce-standalone .ecommerce-profile-popover__stats dt, +.ecommerce-standalone .ecommerce-profile-popover__stats dd { + display: inline-flex !important; + align-items: center !important; + margin: 0 !important; + white-space: nowrap !important; +} + +.ecommerce-standalone .ecommerce-profile-popover__stats dt { + gap: 7px !important; + min-width: 72px !important; +} + +.ecommerce-standalone .ecommerce-profile-popover__stats dd { + justify-content: flex-end !important; + flex: 1 1 auto !important; + text-align: right !important; + font-weight: 800 !important; +} + +.ecommerce-standalone .ecommerce-profile-popover__actions { + display: grid !important; + grid-template-columns: minmax(0, 1fr) !important; + gap: 11px !important; +} + +.ecommerce-standalone .ecommerce-profile-popover__actions button { + width: 100% !important; + min-height: 40px !important; + padding: 0 14px !important; +} + +/* Profile page tabs should be a compact segmented control, not tall cards. */ +.ecommerce-standalone .local-profile-main { + align-content: start !important; +} + +.ecommerce-standalone .local-profile-tabs { + display: grid !important; + grid-template-columns: repeat(4, minmax(0, 1fr)) !important; + align-items: center !important; + gap: 8px !important; + height: auto !important; + min-height: 60px !important; + padding: 8px !important; + border-radius: 18px !important; + background: rgba(254, 255, 255, 0.94) !important; +} + +.ecommerce-standalone .local-profile-tabs button { + display: inline-flex !important; + align-items: center !important; + justify-content: center !important; + width: 100% !important; + height: 44px !important; + min-height: 44px !important; + padding: 0 14px !important; + border-radius: 13px !important; + color: #526675 !important; + line-height: 1 !important; + white-space: nowrap !important; + background: #f8fbfc !important; +} + +.ecommerce-standalone .local-profile-tabs button.is-active { + color: #1073cc !important; + background: rgba(29, 190, 219, 0.12) !important; +} + +/* Keep the profile dashboard evenly inset on both sides. */ +.ecommerce-standalone .local-profile-page { + overflow-x: hidden !important; +} + +.ecommerce-standalone .local-profile-page__body { + box-sizing: border-box !important; + grid-template-columns: minmax(280px, 342px) minmax(0, 1fr) !important; + width: 100% !important; + max-width: 1380px !important; + padding: 0 clamp(24px, 4vw, 56px) !important; + margin-right: auto !important; + margin-left: auto !important; +} + +.ecommerce-standalone .local-profile-main, +.ecommerce-standalone .local-profile-tabs, +.ecommerce-standalone .local-profile-works { + box-sizing: border-box !important; + min-width: 0 !important; + max-width: 100% !important; +} + +.ecommerce-standalone .local-profile-tabs { + overflow: hidden !important; +} + +.ecommerce-standalone .local-profile-page__back { + right: clamp(24px, 4vw, 56px) !important; +} + +/* Final ecommerce header, inline uploads, and compact setting buttons. */ +.ecommerce-standalone .ecommerce-standalone__brand { + gap: 10px !important; +} + +.ecommerce-standalone .ecommerce-standalone__brand strong { + font-weight: 900 !important; + letter-spacing: 0 !important; +} + +.ecommerce-standalone .ecommerce-standalone__logo { + position: relative !important; + width: 40px !important; + height: 40px !important; + flex-basis: 40px !important; + border-radius: 8px !important; + background: #101820 !important; + box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.04) !important; +} + +.ecommerce-standalone .ecommerce-standalone__logo i { + position: absolute !important; + width: 25px !important; + height: 25px !important; + border-radius: 7px !important; + transform: rotate(45deg) !important; +} + +.ecommerce-standalone .ecommerce-standalone__logo i:nth-child(1) { + left: 3px !important; + top: 3px !important; + background: linear-gradient(135deg, #1c86df, #126dc4) !important; +} + +.ecommerce-standalone .ecommerce-standalone__logo i:nth-child(2) { + right: 3px !important; + top: 3px !important; + background: linear-gradient(135deg, #25d1ef, #1697d5) !important; +} + +.ecommerce-standalone .ecommerce-standalone__logo i:nth-child(3) { + left: 3px !important; + bottom: 3px !important; + background: linear-gradient(135deg, #19c6e4, #12a4d9) !important; +} + +.ecommerce-standalone .ecommerce-standalone__logo i:nth-child(4) { + right: 3px !important; + bottom: 3px !important; + background: linear-gradient(135deg, #1a7fd5, #1265b4) !important; +} + +.ecommerce-standalone .ecommerce-standalone__logo::before { + position: absolute !important; + inset: 11px !important; + z-index: 3 !important; + border-radius: 3px !important; + background: #101820 !important; + content: "" !important; + transform: rotate(45deg) !important; +} + +.ecommerce-standalone .ecommerce-standalone__logo::after { + content: none !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .clone-ai-input-wrapper.ecom-command-composer { + grid-template-columns: minmax(0, 1fr) !important; + grid-template-rows: auto minmax(64px, auto) auto !important; + row-gap: 12px !important; + min-height: 0 !important; + padding: 18px 20px 16px !important; + overflow: visible !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-reference { + position: absolute !important; + left: 18px !important; + bottom: 15px !important; + z-index: 8 !important; + display: inline-grid !important; + grid-auto-flow: column !important; + place-items: center !important; + gap: 8px !important; + width: auto !important; + min-width: 42px !important; + height: 40px !important; + min-height: 40px !important; + margin: 0 !important; + padding: 0 10px !important; + border: 0 !important; + border-radius: 12px !important; + background: transparent !important; + transform: none !important; + pointer-events: auto !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-reference span { + font-size: 28px !important; + line-height: 1 !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-reference strong { + display: none !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-asset-popover { + position: static !important; + grid-column: 1 !important; + grid-row: 1 !important; + display: flex !important; + align-items: center !important; + justify-content: flex-start !important; + gap: 10px !important; + width: 100% !important; + max-width: 100% !important; + min-height: 70px !important; + padding: 12px 14px !important; + border: 0 !important; + border-bottom: 1px solid rgba(16, 115, 204, 0.08) !important; + border-radius: 22px 22px 0 0 !important; + background: + radial-gradient(circle at 30% 0%, rgba(30, 189, 219, 0.08), transparent 18rem), + linear-gradient(90deg, rgba(16, 115, 204, 0.035), rgba(30, 189, 219, 0.045), rgba(255, 225, 180, 0.04)) !important; + box-shadow: none !important; + animation: none !important; + transform: none !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-asset-thumb { + width: 78px !important; + height: 78px !important; + border-radius: 14px !important; + overflow: visible !important; + background: #f2f6f8 !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-asset-thumb img, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-asset-thumb video { + border-radius: 14px !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-asset-thumb > button { + top: -7px !important; + right: -7px !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-asset-add { + width: 44px !important; + height: 44px !important; + border: 0 !important; + border-radius: 12px !important; + background: #f3f8fa !important; + font-size: 28px !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-composer textarea { + grid-column: 1 !important; + grid-row: 2 !important; + min-height: 56px !important; + padding: 8px 0 !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-toolbar { + grid-column: 1 !important; + grid-row: 3 !important; + align-items: center !important; + justify-content: space-between !important; + gap: 12px !important; + padding-top: 8px !important; + padding-left: 52px !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-option-row { + flex: 0 1 auto !important; + flex-wrap: wrap !important; + gap: 6px !important; + padding-left: 0 !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-option-row button { + flex: 0 0 auto !important; + width: auto !important; + max-width: 148px !important; + min-width: 0 !important; + min-height: 34px !important; + padding: 0 9px !important; + gap: 4px !important; + border-radius: 11px !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-option-row button span { + max-width: none !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-submit-row { + flex: 0 0 auto !important; +} + +/* Remove oversized blanks in composer popovers and keep the logo on white. */ +.ecommerce-standalone .ecommerce-standalone__logo { + background: #ffffff !important; + box-shadow: none !important; +} + +.ecommerce-standalone .ecommerce-standalone__logo::before { + background: #ffffff !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover { + right: auto !important; + width: max-content !important; + min-width: min(360px, calc(100vw - 56px)) !important; + max-width: min(760px, calc(100vw - 56px)) !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover--grid, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover--list, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover--languages, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-module-grid, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-module-grid--detail, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-module-grid--model, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-module-grid--video { + display: flex !important; + flex-wrap: wrap !important; + align-items: flex-start !important; + justify-content: flex-start !important; + grid-template-columns: none !important; + gap: 8px !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover button, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-module-grid button, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-module-grid--detail button, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-module-grid--model button, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-module-grid--video button { + flex: 0 0 auto !important; + width: auto !important; + min-width: 84px !important; + max-width: 190px !important; + min-height: 38px !important; + padding: 8px 13px !important; + white-space: nowrap !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover--settings { + width: max-content !important; + max-width: 100% !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover--split { + display: flex !important; + flex-wrap: wrap !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover--split > div { + width: max-content !important; + min-width: 0 !important; + max-width: 100% !important; +} + +/* All command popovers: three columns, two visible rows, scroll for the rest. */ +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover { + width: min(620px, calc(100vw - 56px)) !important; + min-width: 0 !important; + max-width: min(620px, calc(100vw - 56px)) !important; + max-height: 178px !important; + overflow-x: hidden !important; + overflow-y: auto !important; + scrollbar-gutter: stable; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover--grid, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover--list, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover--languages { + display: grid !important; + grid-template-columns: repeat(3, minmax(0, 1fr)) !important; + align-items: start !important; + gap: 8px !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover--settings { + display: grid !important; + grid-template-columns: repeat(3, minmax(0, 1fr)) !important; + align-items: start !important; + gap: 10px !important; + max-height: 214px !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover header, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover-note, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-range, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-hot-layout { + grid-column: 1 / -1 !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-module-grid, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-module-grid--detail, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-module-grid--model, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-module-grid--video, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-hot-levels { + grid-column: 1 / -1 !important; + display: grid !important; + grid-template-columns: repeat(3, minmax(0, 1fr)) !important; + gap: 8px !important; + max-height: 104px !important; + overflow-x: hidden !important; + overflow-y: auto !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover button, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-module-grid button, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-hot-levels button { + width: 100% !important; + min-width: 0 !important; + max-width: none !important; + min-height: 44px !important; + padding: 8px 12px !important; + white-space: nowrap !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-count-row { + display: grid !important; + grid-template-columns: minmax(0, 1fr) auto !important; + min-width: 0 !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover--settings > .ecom-command-count-row { + grid-column: span 1 !important; + min-height: 72px !important; +} + +/* Settings exceptions: counters and hot-replicate layout should not be crushed. */ +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover--settings { + max-height: 260px !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover--settings > .ecom-command-count-row { + min-height: 86px !important; + padding: 12px !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover--settings:has(> .ecom-command-count-row) { + width: min(720px, calc(100vw - 56px)) !important; + max-width: min(720px, calc(100vw - 56px)) !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover--settings:has(> .ecom-command-count-row) { + grid-template-columns: repeat(3, minmax(190px, 1fr)) !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-count-row > span { + min-width: 0 !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-count-row > span strong, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-count-row > span em { + display: block !important; + overflow: hidden !important; + text-overflow: ellipsis !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-count-row > div { + display: inline-flex !important; + align-items: center !important; + gap: 6px !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-count-row > div button { + width: 28px !important; + min-width: 28px !important; + max-width: 28px !important; + height: 28px !important; + min-height: 28px !important; + padding: 0 !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-hot-layout { + display: grid !important; + grid-template-columns: minmax(220px, 1fr) minmax(160px, 0.62fr) !important; + gap: 12px !important; + max-height: none !important; + overflow: visible !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-hot-layout .ecom-command-hot-upload { + min-height: 156px !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-hot-levels { + grid-column: auto !important; + display: grid !important; + grid-template-columns: minmax(0, 1fr) !important; + grid-template-rows: repeat(2, minmax(0, 1fr)) !important; + gap: 10px !important; + max-height: none !important; + overflow: visible !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-hot-levels button { + min-height: 72px !important; + white-space: normal !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-hot-thumb-grid { + display: grid !important; + grid-template-columns: repeat(3, 54px) !important; + gap: 8px !important; + max-height: 118px !important; + overflow-x: visible !important; + overflow-y: auto !important; + padding: 2px 4px 2px 2px !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-hot-thumb { + position: relative !important; + display: block !important; + width: 54px !important; + height: 54px !important; + border-radius: 10px !important; + background: #eef6f8 !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-hot-thumb > img { + display: block !important; + width: 100% !important; + height: 100% !important; + border-radius: inherit !important; + object-fit: cover !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-hot-zoom { + position: absolute !important; + left: calc(100% + 12px) !important; + top: 50% !important; + z-index: 200 !important; + display: none !important; + width: min(320px, 70vw) !important; + max-height: min(360px, 70vh) !important; + padding: 8px !important; + border: 1px solid rgba(30, 189, 219, 0.28) !important; + border-radius: 16px !important; + background: #feffff !important; + box-shadow: 0 18px 46px rgba(20, 80, 100, 0.18) !important; + pointer-events: none !important; + transform: translateY(-50%) !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-hot-thumb:hover .ecom-command-hot-zoom { + display: block !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-hot-zoom img { + display: block !important; + width: 100% !important; + height: auto !important; + max-height: calc(min(360px, 70vh) - 16px) !important; + border-radius: 10px !important; + object-fit: contain !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover.ecom-command-popover--grid, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover.ecom-command-popover--list, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover.ecom-command-popover--languages { + display: grid !important; + grid-template-columns: repeat(3, minmax(0, 1fr)) !important; + grid-auto-rows: minmax(44px, auto) !important; + max-height: 122px !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover.ecom-command-popover--grid button, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover.ecom-command-popover--list button, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover.ecom-command-popover--languages button { + width: 100% !important; + min-width: 0 !important; + max-width: none !important; +} + +/* Make the upload entry obvious and keep it out of the text input area. */ +.ecommerce-standalone .product-clone-page[data-tool="clone"] .clone-ai-input-wrapper.ecom-command-composer { + padding-bottom: 18px !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-reference { + left: 20px !important; + bottom: 18px !important; + width: auto !important; + min-width: 76px !important; + height: 44px !important; + min-height: 44px !important; + padding: 0 15px !important; + border: 1px solid rgba(16, 115, 204, 0.12) !important; + border-radius: 999px !important; + color: #10202c !important; + background: #feffff !important; + box-shadow: 0 8px 18px rgba(16, 115, 204, 0.08) !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-reference span { + display: inline-block !important; + color: #10202c !important; + font-size: 32px !important; + font-weight: 300 !important; + line-height: 1 !important; + transform: translateY(-1px); +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-reference strong { + display: inline !important; + max-width: none !important; + color: #10202c !important; + font-size: 15px !important; + font-weight: 600 !important; + line-height: 1 !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-reference:hover, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-reference.has-images, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-reference.is-dragging { + border-color: rgba(30, 189, 219, 0.55) !important; + color: #1073cc !important; + background: rgba(30, 189, 219, 0.08) !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-composer textarea { + grid-row: 1 / 3 !important; + min-height: 96px !important; + padding: 10px 0 58px !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-asset-popover + textarea, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-asset-popover ~ textarea { + grid-row: 2 !important; + min-height: 58px !important; + padding: 18px 0 12px !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-toolbar { + position: relative !important; + z-index: 6 !important; + padding-left: 104px !important; +} + +/* Ratio popover: no oversized blank space from long size labels. */ +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover--ratio { + width: min(520px, calc(100vw - 56px)) !important; + max-width: min(520px, calc(100vw - 56px)) !important; + grid-template-columns: repeat(3, minmax(0, 1fr)) !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover--ratio button { + display: block !important; + overflow: hidden !important; + min-width: 0 !important; + width: 100% !important; + max-width: none !important; + text-align: left !important; + text-overflow: ellipsis !important; + white-space: nowrap !important; +} + +/* Right history panel should sit flush with the content top. */ +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-history { + top: 0 !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-history__tools { + padding-top: 12px !important; +} + +/* Prevent long option labels from overflowing their buttons. */ +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover *, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-option-row, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-option-row * { + box-sizing: border-box !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover button, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-option-row button { + overflow: hidden !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-button-text, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover button > strong, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover button > span, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-option-row button > span { + display: block !important; + min-width: 0 !important; + max-width: 100% !important; + overflow: hidden !important; + text-overflow: ellipsis !important; + white-space: nowrap !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover--ratio { + width: min(480px, calc(100vw - 56px)) !important; + max-width: min(480px, calc(100vw - 56px)) !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover--ratio button { + min-width: 0 !important; + padding-right: 10px !important; + padding-left: 10px !important; +} + +/* Final composer sizing pass: buttons use their content width and keep full labels visible. */ +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-toolbar { + padding-left: 0 !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-option-row { + display: flex !important; + flex: 1 1 auto !important; + flex-wrap: wrap !important; + align-items: center !important; + justify-content: flex-start !important; + gap: 6px !important; + min-width: 0 !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-option-row button { + flex: 0 0 auto !important; + width: max-content !important; + min-width: 0 !important; + max-width: none !important; + height: 34px !important; + min-height: 34px !important; + padding: 0 10px !important; + gap: 5px !important; + white-space: nowrap !important; + overflow: visible !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-option-row button > span { + display: inline !important; + flex: 0 0 auto !important; + width: auto !important; + min-width: 0 !important; + max-width: none !important; + overflow: visible !important; + text-overflow: clip !important; + white-space: nowrap !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-option-row button > .ecom-command-option-icon { + display: inline-flex !important; + align-items: center !important; + justify-content: center !important; + flex: 0 0 16px !important; + width: 16px !important; + height: 16px !important; + min-width: 16px !important; + color: #4d7184 !important; + font-size: 15px !important; + line-height: 1 !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-option-row button.is-active > .ecom-command-option-icon, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-option-row button:hover > .ecom-command-option-icon { + color: #1073cc !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-reference { + position: absolute !important; + grid-column: 1 !important; + grid-row: 3 !important; + left: 20px !important; + top: 8px !important; + bottom: auto !important; + z-index: 8 !important; + display: inline-flex !important; + align-items: center !important; + justify-content: center !important; + gap: 4px !important; + width: auto !important; + min-width: 78px !important; + max-width: none !important; + height: 34px !important; + min-height: 34px !important; + padding: 0 11px !important; + border-radius: 11px !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-reference span { + font-size: 20px !important; + line-height: 1 !important; + transform: none !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-reference strong { + display: inline !important; + font-size: 13px !important; + line-height: 1 !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover.ecom-command-popover--grid { + width: max-content !important; + min-width: 0 !important; + max-width: min(620px, calc(100vw - 56px)) !important; + display: flex !important; + flex-wrap: wrap !important; + align-items: flex-start !important; + justify-content: flex-start !important; + gap: 8px !important; + max-height: 122px !important; + overflow-x: hidden !important; + overflow-y: auto !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover.ecom-command-popover--grid button { + flex: 0 0 auto !important; + width: max-content !important; + min-width: 0 !important; + max-width: none !important; + padding: 8px 15px !important; + overflow: visible !important; + white-space: nowrap !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover.ecom-command-popover--list:not(.ecom-command-popover--ratio), +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover.ecom-command-popover--languages { + grid-template-columns: repeat(3, max-content) !important; + width: max-content !important; + min-width: 0 !important; + max-width: min(680px, calc(100vw - 56px)) !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover.ecom-command-popover--list:not(.ecom-command-popover--ratio) button, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover.ecom-command-popover--languages button { + width: max-content !important; + min-width: 0 !important; + max-width: none !important; + overflow: visible !important; + white-space: nowrap !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover--ratio { + grid-template-columns: repeat(3, max-content) !important; + width: max-content !important; + min-width: 0 !important; + max-width: min(860px, calc(100vw - 56px)) !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover--ratio button { + display: inline-flex !important; + width: max-content !important; + min-width: 0 !important; + max-width: none !important; + overflow: visible !important; + text-align: left !important; + text-overflow: clip !important; + white-space: nowrap !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-button-text { + display: inline !important; + max-width: none !important; + overflow: visible !important; + text-overflow: clip !important; + white-space: nowrap !important; +} + +/* Keep command popovers visually attached to the composer. */ +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover { + bottom: -2px !important; +} + +/* Softer popover and side-panel motion. */ +@keyframes ecommerce-soft-popover-in { + 0% { + opacity: 0; + filter: blur(2px); + transform: translate3d(0, 12px, 0) scale(0.972); + } + 58% { + opacity: 1; + filter: blur(0); + transform: translate3d(0, -2px, 0) scale(1.004); + } + 100% { + opacity: 1; + filter: blur(0); + transform: translate3d(0, 0, 0) scale(1); + } +} + +@keyframes ecommerce-soft-drop-in { + 0% { + opacity: 0; + filter: blur(2px); + transform: translate3d(0, -10px, 0) scale(0.976); + } + 62% { + opacity: 1; + filter: blur(0); + transform: translate3d(0, 2px, 0) scale(1.003); + } + 100% { + opacity: 1; + filter: blur(0); + transform: translate3d(0, 0, 0) scale(1); + } +} + +@keyframes ecommerce-soft-scrim-in { + from { + opacity: 0; + } + to { + opacity: 1; + } +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover, +.ecommerce-standalone .ecommerce-profile-popover, +.ecommerce-standalone .product-set-preview-modal { + transform-origin: top left !important; + will-change: opacity, transform, filter !important; + animation: ecommerce-soft-popover-in 420ms cubic-bezier(0.16, 1, 0.3, 1) both !important; +} + +.ecommerce-standalone .ecommerce-auth-modal__panel { + transform-origin: center !important; + will-change: opacity, transform, filter !important; + animation: ecommerce-soft-popover-in 460ms cubic-bezier(0.16, 1, 0.3, 1) both !important; +} + +.ecommerce-standalone .ecommerce-auth-modal__scrim, +.ecommerce-standalone .ecommerce-profile-popover__backdrop, +.ecommerce-standalone .product-set-preview-backdrop { + animation: ecommerce-soft-scrim-in 300ms ease-out both !important; +} + +.ecommerce-standalone .ecom-command-asset-popover { + transform-origin: top left !important; + will-change: opacity, transform, filter !important; + animation: ecommerce-soft-drop-in 380ms cubic-bezier(0.16, 1, 0.3, 1) both !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-history { + transition: + transform 440ms cubic-bezier(0.16, 1, 0.3, 1), + opacity 300ms ease, + box-shadow 320ms ease, + border-color 320ms ease !important; + will-change: transform, opacity !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-history__tools, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-history__list { + transition: + opacity 260ms ease, + transform 360ms cubic-bezier(0.16, 1, 0.3, 1) !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"].is-history-collapsed .ecom-command-history__tools, +.ecommerce-standalone .product-clone-page[data-tool="clone"].is-history-collapsed .ecom-command-history__list { + opacity: 0.96 !important; +} + +@media (prefers-reduced-motion: reduce) { + .ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover, + .ecommerce-standalone .ecommerce-profile-popover, + .ecommerce-standalone .product-set-preview-modal, + .ecommerce-standalone .ecommerce-auth-modal__panel, + .ecommerce-standalone .ecommerce-auth-modal__scrim, + .ecommerce-standalone .ecommerce-profile-popover__backdrop, + .ecommerce-standalone .product-set-preview-backdrop, + .ecommerce-standalone .ecom-command-asset-popover, + .ecommerce-standalone .ecom-tool-page-enter, + .ecommerce-standalone .ecom-tool-page-enter .ecom-quick-page-sidebar, + .ecommerce-standalone .ecom-tool-page-enter .ecom-quick-set-panel, + .ecommerce-standalone .ecom-tool-page-enter .ecom-watermark-side, + .ecommerce-standalone .ecom-tool-page-enter .ecom-image-workbench-side, + .ecommerce-standalone .ecom-tool-page-enter .ecom-smart-cutout-nav, + .ecommerce-standalone .ecom-tool-page-enter .ecom-quick-set-stage, + .ecommerce-standalone .ecom-tool-page-enter .ecom-watermark-workspace, + .ecommerce-standalone .ecom-tool-page-enter .ecom-image-workbench-stage, + .ecommerce-standalone .ecom-tool-page-enter .ecom-smart-cutout-upload, + .ecommerce-standalone .ecom-tool-page-enter .ecom-smart-editor, + .ecommerce-standalone .ecom-tool-page-enter .ecom-quick-set-panel > section, + .ecommerce-standalone .ecom-tool-page-enter .ecom-watermark-panel, + .ecommerce-standalone .ecom-tool-page-enter .ecom-image-workbench-panel { + animation: none !important; + } + + .ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-history, + .ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-history__tools, + .ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-history__list { + transition: none !important; + } +} + +/* Align the upload action with the command pill buttons. */ +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-composer > .ecom-command-reference:not(.ecom-command-reference--inline) { + display: none !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-reference { + box-sizing: border-box !important; + position: static !important; + grid-column: auto !important; + grid-row: auto !important; + inset: auto !important; + z-index: auto !important; + flex: 0 0 auto !important; + display: inline-flex !important; + align-items: center !important; + justify-content: center !important; + gap: 5px !important; + width: max-content !important; + min-width: 0 !important; + max-width: none !important; + height: 34px !important; + min-height: 34px !important; + padding: 0 10px !important; + border: 1px solid rgba(30, 189, 219, 0.22) !important; + border-radius: 11px !important; + color: #10202c !important; + background: #f3f8fa !important; + box-shadow: none !important; + font-size: 13px !important; + font-weight: 500 !important; + line-height: 1 !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-reference span { + display: inline !important; + color: inherit !important; + font-size: 13px !important; + font-weight: 500 !important; + line-height: 1 !important; + transform: none !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-reference strong { + display: inline !important; + color: inherit !important; + font-size: 13px !important; + font-weight: 500 !important; + line-height: 1 !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-reference.has-images, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-reference.is-dragging, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-reference:hover { + border-color: rgba(30, 189, 219, 0.42) !important; + color: #1073cc !important; + background: linear-gradient(180deg, rgba(254, 255, 255, 0.96), rgba(234, 250, 254, 0.9)) !important; +} + +/* Match the official OmniAI logo lockup on the local soft-white surface. */ +.ecommerce-standalone .ecommerce-standalone__brand { + gap: 10px !important; + min-height: 36px !important; + padding: 0 6px !important; + border-radius: 12px !important; + color: #10202c !important; + background: #f8f9fa !important; + box-shadow: inset 0 0 0 1px rgba(30, 189, 219, 0.08) !important; +} + +.ecommerce-standalone .ecommerce-standalone__brand strong { + color: #10202c !important; + font-size: 15px !important; + font-weight: 700 !important; + line-height: 1 !important; +} + +.ecommerce-standalone .ecommerce-standalone__logo { + position: relative !important; + display: inline-flex !important; + flex: 0 0 28px !important; + align-items: center !important; + justify-content: center !important; + width: 28px !important; + height: 28px !important; + border-radius: 8px !important; + background: #f8f9fa !important; + box-shadow: none !important; +} + +.ecommerce-standalone .ecommerce-standalone__logo img { + display: block !important; + width: 28px !important; + height: 28px !important; + object-fit: contain !important; +} + +.ecommerce-standalone .ecommerce-standalone__logo i, +.ecommerce-standalone .ecommerce-standalone__logo::before, +.ecommerce-standalone .ecommerce-standalone__logo::after { + content: none !important; + display: none !important; +} + +/* Language popover only: restore the compact inline language style. */ +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover.ecom-command-popover--languages { + display: grid !important; + grid-template-columns: repeat(3, max-content) !important; + align-items: start !important; + gap: 8px !important; + width: max-content !important; + min-width: 0 !important; + max-width: min(680px, calc(100vw - 56px)) !important; + max-height: 122px !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover.ecom-command-popover--languages button { + display: inline-flex !important; + align-items: center !important; + justify-content: flex-start !important; + gap: 5px !important; + width: max-content !important; + min-width: 0 !important; + max-width: none !important; + min-height: 34px !important; + padding: 0 12px !important; + white-space: nowrap !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover.ecom-command-popover--languages button strong, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover.ecom-command-popover--languages button span { + display: inline !important; + width: auto !important; + min-width: 0 !important; + max-width: none !important; + overflow: visible !important; + line-height: 1 !important; + text-overflow: clip !important; + white-space: nowrap !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover.ecom-command-popover--languages button strong { + color: #10202c !important; + font-size: 13px !important; + font-weight: 600 !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover.ecom-command-popover--languages button span { + color: #6b7c88 !important; + font-size: 12px !important; + font-weight: 500 !important; +} + +/* Settings popover: center non-set-mode option text only. */ +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover--settings .ecom-command-module-grid button, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover--settings .ecom-command-hot-levels button, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover--settings .ecom-command-hot-upload { + align-items: center !important; + justify-content: center !important; + justify-items: center !important; + text-align: center !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover--settings .ecom-command-module-grid button > strong, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover--settings .ecom-command-module-grid button > span, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover--settings .ecom-command-hot-levels button > strong, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover--settings .ecom-command-hot-levels button > span, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover--settings .ecom-command-hot-upload > strong, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover--settings .ecom-command-hot-upload > span { + width: 100% !important; + text-align: center !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover--settings > .ecom-command-count-row, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover--settings > .ecom-command-count-row * { + text-align: initial !important; +} + +/* Uploaded asset strip: no tinted background or divider line. */ +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-asset-popover { + border-bottom: 0 !important; + background: transparent !important; +} + +/* Command popovers must open below the composer; animation transforms should not control placement. */ +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover { + top: calc(100% + 2px) !important; + bottom: auto !important; +} + +/* Generated workspace: compact composer, textured canvas, mouse-centered zoom and middle-button panning. */ +.ecommerce-standalone .product-clone-page[data-tool="clone"] .clone-ai-preview { + grid-template-rows: auto minmax(0, 1fr) !important; + align-content: stretch !important; + gap: 14px !important; + overflow: auto !important; + cursor: default !important; + background: + radial-gradient(circle at 18% 18%, rgba(30, 189, 219, 0.08), transparent 24rem), + radial-gradient(circle at 82% 28%, rgba(16, 115, 204, 0.06), transparent 22rem), + linear-gradient(rgba(16, 115, 204, 0.035) 1px, transparent 1px), + linear-gradient(90deg, rgba(16, 115, 204, 0.035) 1px, transparent 1px), + #f8f9fa !important; + background-size: auto, auto, 28px 28px, 28px 28px, auto !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .clone-ai-preview.is-middle-panning { + cursor: grabbing !important; + user-select: none !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .clone-ai-preview-zoom-wrap { + width: max-content !important; + min-width: 100% !important; + transform-origin: 0 0 !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .clone-ai-preview-showcase, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .clone-ai-flow-pipeline, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .clone-ai-empty-state { + position: relative !important; + grid-row: 2 !important; + margin-top: 0 !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-composer-wrap.is-compact { + gap: 0 !important; + cursor: text !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-composer-wrap.is-compact .ecom-command-title { + display: none !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-composer-wrap.is-compact .clone-ai-input-wrapper.ecom-command-composer { + grid-template-rows: auto auto !important; + row-gap: 8px !important; + min-height: 92px !important; + padding: 12px 16px !important; + border-radius: 22px !important; + box-shadow: 0 14px 36px rgba(16, 115, 204, 0.1) !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-composer-wrap.is-compact .ecom-command-asset-popover { + max-height: 42px !important; + overflow: hidden !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-composer-wrap.is-compact .ecom-command-composer textarea { + min-height: 34px !important; + max-height: 38px !important; + padding-top: 4px !important; + padding-bottom: 0 !important; + overflow: hidden !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-composer-wrap.is-compact .ecom-command-toolbar { + padding-top: 4px !important; + border-top: 0 !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-history__list button.is-active, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-history__item.is-active .ecom-command-history__item-main { + border-color: rgba(30, 189, 219, 0.42) !important; + background: rgba(30, 189, 219, 0.12) !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-history__empty { + margin: 10px 8px 0 !important; + padding: 18px 12px !important; + border: 1px dashed rgba(30, 189, 219, 0.22) !important; + border-radius: 14px !important; + color: #7a8c98 !important; + background: rgba(248, 249, 250, 0.72) !important; + font-size: 13px !important; + font-weight: 500 !important; + text-align: center !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] { + padding-left: 0 !important; +} + +/* Final canvas alignment: keep the composer centered in the generation area and make middle-button panning visible. */ +.ecommerce-standalone .product-clone-page[data-tool="clone"] .clone-ai-preview { + position: relative !important; + overflow: hidden !important; + padding-right: 0 !important; + padding-left: 0 !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-composer-wrap { + position: absolute !important; + left: 50% !important; + z-index: 12 !important; + width: min(1036px, calc(100% - 56px)) !important; + margin-right: 0 !important; + margin-left: 0 !important; +; + transition: top 520ms cubic-bezier(0.16, 1, 0.3, 1), + transform 520ms cubic-bezier(0.16, 1, 0.3, 1), + width 520ms cubic-bezier(0.16, 1, 0.3, 1) !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-composer-wrap.is-before-generate { + top: calc(50% - clamp(24px, 3.5vh, 36px)) !important; + transform: translate(-50%, -50%) !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-composer-wrap.has-generated { + top: 48px !important; + transform: translateX(-50%) !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .clone-ai-preview[data-status="done"] { + padding-top: 156px !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .clone-ai-preview[data-status="done"]:has(.ecom-command-composer-wrap:not(.is-compact)) { + padding-top: 360px !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .clone-ai-preview-zoom-wrap { + display: inline-flex !important; + align-items: flex-start !important; + justify-content: center !important; + width: auto !important; + min-width: 100% !important; + transform-origin: 0 0 !important; + will-change: transform !important; + transition: transform 120ms ease-out !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .clone-ai-preview.is-middle-panning .clone-ai-preview-zoom-wrap { + transition: none !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .clone-ai-preview-showcase { + width: min(1120px, calc(100vw - 420px)) !important; + min-width: 980px !important; + margin-right: auto !important; + margin-left: auto !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .clone-ai-canvas-nodes { + position: relative; + width: max-content; + min-width: min(1120px, calc(100vw - 420px)); + min-height: 200px; + padding: 24px; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .clone-ai-canvas-node { + position: absolute; + top: 24px; + left: 24px; + display: flex; + align-items: center; + gap: 16px; + padding: 20px 24px; + padding-top: 36px; + border-radius: 18px; + border: 1px solid rgba(30, 189, 219, 0.18); + background: rgba(255, 255, 255, 0.96); + box-shadow: 0 4px 20px rgba(16, 115, 204, 0.08); + transition: box-shadow 200ms ease; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .clone-ai-canvas-node:hover { + box-shadow: 0 8px 32px rgba(16, 115, 204, 0.14); +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .clone-ai-node-drag-handle { + position: absolute; + top: 0; + left: 0; + right: 0; + height: 32px; + display: flex; + align-items: center; + justify-content: flex-end; + padding: 0 12px; + border-radius: 18px 18px 0 0; + cursor: grab; + user-select: none; + touch-action: none; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .clone-ai-node-drag-handle:active { + cursor: grabbing; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .clone-ai-canvas-node .clone-ai-main-result { + flex: 0 0 auto; + width: 150px; + border-radius: 12px; + overflow: hidden; + border: 1px solid rgba(30, 189, 219, 0.12); + cursor: pointer; + background: #f4f8fa; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .clone-ai-canvas-node .clone-ai-main-result img { + width: 100%; + height: auto; + display: block; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .clone-ai-canvas-node .clone-ai-main-result span { + display: block; + text-align: center; + font-size: 11px; + color: #68818f; + padding: 4px; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .clone-ai-canvas-node .clone-ai-source-stack { + position: relative; + flex: 0 0 auto; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .clone-ai-canvas-node .clone-ai-result-grid { + display: flex; + gap: 12px; + flex-wrap: wrap; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .clone-ai-canvas-node .clone-ai-result-stack { + position: relative; + flex: 0 0 auto; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .clone-ai-canvas-node .clone-ai-source-corner-action { + position: absolute; + top: -6px; + left: 50%; + z-index: 5; + display: inline-flex; + align-items: center; + justify-content: center; + min-height: 24px; + padding: 4px 9px; + border: 1px solid rgba(30, 189, 219, 0.22); + border-radius: 999px; + background: rgba(255, 255, 255, 0.96); + box-shadow: 0 6px 18px rgba(16, 115, 204, 0.12); + color: #188ba7; + font-size: 11px; + font-weight: 700; + line-height: 1; + white-space: nowrap; + cursor: pointer; + transform: translate(-50%, -100%); +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .clone-ai-canvas-node .clone-ai-source-corner-action:hover { + border-color: rgba(30, 189, 219, 0.45); + color: #0f7895; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .clone-ai-canvas-node .clone-ai-result-grid button { + width: 140px; + border-radius: 12px; + overflow: hidden; + border: 1px solid rgba(30, 189, 219, 0.12); + background: #f4f8fa; + cursor: pointer; + transition: border-color 200ms; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .clone-ai-canvas-node .clone-ai-result-grid button:hover { + border-color: rgba(30, 189, 219, 0.4); +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .clone-ai-canvas-node .clone-ai-result-grid img { + width: 100%; + height: auto; + display: block; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .clone-ai-canvas-node .clone-ai-result-grid span { + display: block; + text-align: center; + font-size: 11px; + color: #68818f; + padding: 4px; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .clone-ai-node-label { + font-size: 11px; + font-weight: 600; + color: rgba(30, 189, 219, 0.8); + background: rgba(30, 189, 219, 0.08); + padding: 2px 8px; + border-radius: 8px; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .clone-ai-result-stack > .clone-ai-node-label { + position: absolute; + top: -6px; + left: 50%; + z-index: 5; + transform: translate(-50%, -100%); + white-space: nowrap; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .clone-ai-canvas-node.is-generating { + justify-content: center; + min-width: 200px; + min-height: 120px; + color: #68818f; + font-size: 14px; + gap: 10px; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .clone-ai-preview { + cursor: grab; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .clone-ai-preview.is-middle-panning { + cursor: grabbing; +} + +/* History sidebar is an overlay drawer; do NOT shift the underlying content. */ +.ecommerce-standalone .product-clone-page[data-tool="clone"] .clone-ai-empty-state, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .clone-ai-flow-pipeline { + transform: none !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .clone-ai-preview-zoom-wrap { + margin-left: 0 !important; +} + +/* Header polish: remove the logo frame trace and match credit/user pill surfaces. */ +.ecommerce-standalone .ecommerce-standalone__brand { + background: transparent !important; + box-shadow: none !important; +} + +.ecommerce-standalone .ecommerce-standalone__logo { + overflow: visible !important; + border: 0 !important; + border-radius: 0 !important; + background: transparent !important; + box-shadow: none !important; +} + +.ecommerce-standalone .ecommerce-standalone__logo img { + border: 0 !important; + border-radius: 0 !important; + background: transparent !important; + box-shadow: none !important; +} + +.ecommerce-standalone .ecommerce-standalone__credits, +.ecommerce-standalone .ecommerce-profile-menu__trigger { + min-height: 42px !important; + border: 1px solid rgba(30, 189, 219, 0.18) !important; + border-radius: 15px !important; + color: #10202c !important; + background: #fbfdfe !important; + box-shadow: 0 10px 26px rgba(16, 115, 204, 0.06) !important; +} + +.ecommerce-standalone .ecommerce-standalone__credits { + padding: 0 14px !important; +} + +.ecommerce-standalone .ecommerce-profile-menu__trigger { + padding: 0 15px 0 7px !important; +} + +/* Compact generated composer: keep uploaded thumbnails visible and collapse the text band. */ +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-composer-wrap.is-compact .clone-ai-input-wrapper.ecom-command-composer { + grid-template-rows: auto 24px auto !important; + row-gap: 6px !important; + min-height: 124px !important; + padding: 10px 16px 12px !important; + overflow: visible !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-composer-wrap.is-compact .ecom-command-asset-popover { + min-height: 56px !important; + max-height: 56px !important; + padding: 7px 12px 5px !important; + overflow: visible !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-composer-wrap.is-compact .ecom-command-asset-thumb { + width: 44px !important; + height: 44px !important; + border-radius: 10px !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-composer-wrap.is-compact .ecom-command-asset-thumb img, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-composer-wrap.is-compact .ecom-command-asset-thumb video { + border-radius: 10px !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-composer-wrap.is-compact .ecom-command-asset-thumb > button { + top: -4px !important; + right: -4px !important; + width: 18px !important; + height: 18px !important; + min-height: 18px !important; + font-size: 12px !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-composer-wrap.is-compact .ecom-command-asset-add { + width: 42px !important; + height: 42px !important; + min-height: 42px !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-composer-wrap.is-compact .ecom-command-composer textarea { + min-height: 22px !important; + max-height: 24px !important; + padding: 0 !important; + font-size: 14px !important; + line-height: 22px !important; + white-space: nowrap !important; + text-overflow: ellipsis !important; +} + +/* Composer final pass: viewport-centered position, icon-only upload, platform marks, and language-only sizing. */ +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-composer-wrap { + position: fixed !important; + left: 50vw !important; + right: auto !important; + width: min(1036px, calc(100vw - 56px)) !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-composer-wrap.is-before-generate { + top: calc(50vh + 32px) !important; + transform: translate(-50%, -50%) !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-composer-wrap.has-generated { + top: 88px !important; + transform: translateX(-50%) !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-reference--inline { + width: 34px !important; + min-width: 34px !important; + max-width: 34px !important; + padding: 0 !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-reference--inline strong { + display: none !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-reference--inline span { + font-size: 20px !important; + font-weight: 600 !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-platform-logo-mark { + display: inline-flex !important; + align-items: center !important; + justify-content: center !important; + flex: 0 0 20px !important; + width: 20px !important; + height: 20px !important; + padding: 0 !important; + overflow: hidden !important; + border-radius: 6px !important; + color: inherit !important; + background: transparent !important; + box-shadow: none !important; + font-size: 0 !important; + font-style: normal !important; + font-weight: 800 !important; + line-height: 1 !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-platform-logo-mark--duo { + flex-basis: 42px !important; + width: 42px !important; + gap: 2px !important; + overflow: visible !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-platform-logo-mark img { + display: block !important; + width: 20px !important; + height: 20px !important; + flex: 0 0 20px !important; + object-fit: contain !important; + border-radius: 5px !important; + background: transparent !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover--platform button, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-option-row button:has(.ecom-platform-logo-mark) { + display: inline-flex !important; + align-items: center !important; + gap: 6px !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-platform-name { + display: inline !important; + width: auto !important; + max-width: none !important; + overflow: visible !important; + color: inherit !important; + text-overflow: clip !important; + white-space: nowrap !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover.ecom-command-popover--languages { + grid-template-columns: repeat(3, minmax(118px, 1fr)) !important; + width: min(520px, calc(100vw - 56px)) !important; + min-width: 0 !important; + max-width: min(520px, calc(100vw - 56px)) !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover.ecom-command-popover--languages button { + display: grid !important; + grid-template-columns: minmax(0, 1fr) !important; + align-content: center !important; + justify-items: center !important; + gap: 4px !important; + width: 100% !important; + min-width: 0 !important; + max-width: none !important; + min-height: 52px !important; + padding: 8px 10px !important; + text-align: center !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover.ecom-command-popover--languages button strong, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover.ecom-command-popover--languages button span { + width: 100% !important; + min-width: 0 !important; + max-width: 100% !important; + overflow: hidden !important; + text-align: center !important; + text-overflow: ellipsis !important; + white-space: nowrap !important; +} + +/* Restore composer scale: only center dynamically, do not enlarge the input or upload strip. */ +.ecommerce-standalone .product-clone-page[data-tool="clone"] { + --ecom-history-offset: 0px; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"].is-history-collapsed { + --ecom-history-offset: 0px; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-composer-wrap { + position: absolute !important; + left: calc(50% + var(--ecom-history-offset)) !important; + right: auto !important; + bottom: auto !important; + height: auto !important; + width: min(1036px, calc(100% - 56px)) !important; + align-content: start !important; + grid-template-rows: auto auto !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-composer-wrap.is-before-generate { + top: calc(50% - clamp(24px, 3.5vh, 36px)) !important; + transform: translate(-50%, -50%) !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-composer-wrap.has-generated { + top: 24px !important; + transform: translateX(-50%) !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-title { + font-size: clamp(28px, 2.7vw, 40px) !important; + line-height: 1.12 !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .clone-ai-input-wrapper.ecom-command-composer { + grid-template-rows: auto minmax(40px, auto) auto !important; + row-gap: 8px !important; + min-height: 184px !important; + padding: 14px 20px 14px !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-asset-popover { + min-height: 54px !important; + max-height: 62px !important; + padding: 6px 12px !important; + overflow: visible !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-asset-thumb { + width: 48px !important; + height: 48px !important; + border-radius: 10px !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-asset-thumb img, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-asset-thumb video { + border-radius: 10px !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-asset-thumb > button { + top: -5px !important; + right: -5px !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-asset-add { + width: 42px !important; + height: 42px !important; + min-height: 42px !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-asset-popover + textarea, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-asset-popover ~ textarea, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-composer textarea { + min-height: 42px !important; + max-height: 62px !important; + padding: 8px 0 6px !important; + font-size: 16px !important; + line-height: 24px !important; +} + +/* Size rollback: keep the previous compact composer proportions while preserving dynamic centering. */ +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-composer-wrap { + gap: 18px !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-title { + max-width: 100% !important; + font-size: clamp(24px, 2.2vw, 32px) !important; + line-height: 1.15 !important; + white-space: nowrap !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .clone-ai-input-wrapper.ecom-command-composer { + grid-template-rows: 54px 32px auto !important; + row-gap: 6px !important; + min-height: 164px !important; + padding: 12px 18px !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-asset-popover { + min-height: 54px !important; + max-height: 54px !important; + padding: 5px 10px !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-asset-thumb { + width: 44px !important; + height: 44px !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-asset-add { + width: 40px !important; + height: 40px !important; + min-height: 40px !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-asset-popover + textarea, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-asset-popover ~ textarea { + min-height: 32px !important; + max-height: 32px !important; + padding: 3px 0 0 !important; + line-height: 24px !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-toolbar { + min-height: 42px !important; + padding-top: 4px !important; +} + +/* Hidden utility nodes must not create rows in the composer grid. */ +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-hidden-file { + position: absolute !important; + width: 1px !important; + height: 1px !important; + min-height: 0 !important; + overflow: hidden !important; + opacity: 0 !important; + pointer-events: none !important; + transform: translate(-9999px, -9999px) !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .clone-ai-char-count { + position: absolute !important; + right: 10px !important; + bottom: -18px !important; + height: auto !important; + margin: 0 !important; + line-height: 1 !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-title { + height: auto !important; + min-height: 0 !important; + max-height: 38px !important; + overflow: hidden !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .clone-ai-input-wrapper.ecom-command-composer { + height: auto !important; + max-height: 190px !important; + align-content: start !important; +} + +/* Horizontal centering only: keep the original vertical placement and visual scale. */ +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-composer-wrap.is-before-generate { + top: clamp(44px, 4.6vh, 58px) !important; + transform: translateX(-50%) !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-title { + height: auto !important; + max-height: none !important; + overflow: visible !important; + font-size: clamp(30px, 3.3vw, 46px) !important; + line-height: 1.1 !important; + white-space: normal !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .clone-ai-input-wrapper.ecom-command-composer { + grid-template-rows: minmax(92px, auto) auto !important; + min-height: 206px !important; + max-height: none !important; + padding: 18px 20px !important; + row-gap: 16px !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-quick-board { + display: grid !important; + grid-template-columns: repeat(6, minmax(0, 1fr)) !important; + width: min(1036px, 100%) !important; + min-height: 148px !important; + overflow: hidden !important; + border: 1px solid rgba(30, 189, 219, 0.13) !important; + border-radius: 18px !important; + background: rgba(254, 255, 255, 0.92) !important; + box-shadow: 0 18px 42px rgba(16, 115, 204, 0.08) !important; + backdrop-filter: blur(14px) !important; + -webkit-backdrop-filter: blur(14px) !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-quick-board button { + position: relative !important; + display: flex !important; + align-items: center !important; + justify-content: center !important; + gap: 9px !important; + min-width: 0 !important; + min-height: 74px !important; + padding: 14px 12px !important; + border: 0 !important; + border-radius: 0 !important; + color: #172636 !important; + background: transparent !important; + font-family: "PingFang SC", "Microsoft YaHei", sans-serif !important; + cursor: default !important; + transition: background 0.22s ease, color 0.22s ease !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-quick-board button:not(:nth-child(6n + 1))::before { + position: absolute !important; + top: 14px !important; + bottom: 14px !important; + left: 0 !important; + width: 1px !important; + content: "" !important; + background: rgba(30, 189, 219, 0.12) !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-quick-board button:nth-child(n + 7)::after { + position: absolute !important; + top: 0 !important; + left: 16px !important; + right: 16px !important; + height: 1px !important; + content: "" !important; + background: rgba(30, 189, 219, 0.12) !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-quick-board button:hover { + color: #1073cc !important; + background: rgba(30, 189, 219, 0.09) !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-quick-board button span { + display: inline-flex !important; + align-items: center !important; + justify-content: center !important; + flex: 0 0 auto !important; + width: 20px !important; + height: 20px !important; + color: currentColor !important; + font-size: 18px !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-quick-board button strong { + overflow: hidden !important; + color: currentColor !important; + font-size: 13px !important; + font-weight: 600 !important; + line-height: 1.2 !important; + text-overflow: ellipsis !important; + white-space: nowrap !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-composer-wrap.has-generated .ecom-command-quick-board, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-composer-wrap.is-compact .ecom-command-quick-board { + display: none !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-composer textarea { + grid-row: 1 / 3 !important; + min-height: 96px !important; + max-height: 183px !important; + padding: 10px 0 58px !important; + font-size: 14px !important; + line-height: 1.55 !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-toolbar { + min-height: auto !important; + padding-top: 8px !important; +} + +/* Match the target top spacing. */ +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-composer-wrap.is-before-generate { + top: clamp(-28px, -1.6vh, -12px) !important; + transform: translateX(-50%) !important; +} + +/* Set-mode settings should read as a vertical category list. */ +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover--settings-set { + grid-template-columns: minmax(0, 1fr) !important; + width: min(420px, calc(100vw - 56px)) !important; + max-width: min(420px, calc(100vw - 56px)) !important; + max-height: 360px !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover.ecom-command-popover--settings.ecom-command-popover--settings-set:has(> .ecom-command-count-row) { + grid-template-columns: minmax(0, 1fr) !important; + width: min(420px, calc(100vw - 56px)) !important; + max-width: min(420px, calc(100vw - 56px)) !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover--settings-set > .ecom-command-count-row { + grid-column: 1 !important; + min-height: 64px !important; + padding: 10px 12px !important; +} + +/* Upload action: keep only a larger plus sign. */ +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-reference.ecom-command-reference--inline { + width: 28px !important; + min-width: 28px !important; + max-width: 28px !important; + height: 34px !important; + min-height: 34px !important; + padding: 0 !important; + border: 0 !important; + border-radius: 0 !important; + color: #10202c !important; + background: transparent !important; + box-shadow: none !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-reference.ecom-command-reference--inline:hover, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-reference.ecom-command-reference--inline.has-images, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-reference.ecom-command-reference--inline.is-dragging { + border: 0 !important; + color: #1073cc !important; + background: transparent !important; + box-shadow: none !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-reference.ecom-command-reference--inline span { + font-size: 28px !important; + font-weight: 500 !important; + line-height: 1 !important; +} + +/* Platform popover: center short labels while allowing long labels to keep their natural width. */ +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover--platform button { + justify-content: center !important; + gap: 4px !important; + text-align: center !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover--platform .ecom-platform-name { + text-align: center !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover--platform .ecom-platform-logo-mark--duo { + flex-basis: 28px !important; + width: 28px !important; + gap: 0 !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover--platform .ecom-platform-logo-mark--duo img + img { + margin-left: -12px !important; +} + +/* Uploaded state: place thumbnails at the upper-left and move the prompt below them. */ +.ecommerce-standalone .product-clone-page[data-tool="clone"] .clone-ai-input-wrapper.ecom-command-composer:has(.ecom-command-asset-popover) { + grid-template-rows: 99px minmax(44px, auto) auto !important; + row-gap: 8px !important; + min-height: 276px !important; + padding: 32px 20px 16px !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .clone-ai-input-wrapper.ecom-command-composer:has(.ecom-command-asset-popover) .ecom-command-asset-popover { + grid-row: 1 !important; + align-self: start !important; + display: flex !important; + align-items: flex-start !important; + justify-content: flex-start !important; + gap: 10px !important; + width: max-content !important; + max-width: 100% !important; + min-height: 82px !important; + max-height: 86px !important; + padding: 0 0 0 14px !important; + overflow: visible !important; + border: 0 !important; + background: transparent !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .clone-ai-input-wrapper.ecom-command-composer:has(.ecom-command-asset-popover) .ecom-command-asset-thumb { + flex: 0 0 78px !important; + width: 78px !important; + height: 78px !important; + border-radius: 12px !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .clone-ai-input-wrapper.ecom-command-composer:has(.ecom-command-asset-popover) .ecom-command-asset-thumb img, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .clone-ai-input-wrapper.ecom-command-composer:has(.ecom-command-asset-popover) .ecom-command-asset-thumb video { + border-radius: 12px !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .clone-ai-input-wrapper.ecom-command-composer:has(.ecom-command-asset-popover) .ecom-command-asset-add { + flex: 0 0 44px !important; + width: 44px !important; + height: 44px !important; + min-height: 44px !important; + margin-top: 18px !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .clone-ai-input-wrapper.ecom-command-composer:has(.ecom-command-asset-popover) > textarea { + grid-row: 2 !important; + min-height: 44px !important; + max-height: 72px !important; + padding: 6px 0 0 !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .clone-ai-input-wrapper.ecom-command-composer:has(.ecom-command-asset-popover) .ecom-command-toolbar { + grid-row: 3 !important; + min-height: 42px !important; + padding-top: 8px !important; +} + +/* Generated-state final guard: fixed positioning so the composer never goes behind the topbar. */ +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-composer-wrap.has-generated { + position: fixed !important; + top: calc(var(--ecommerce-topbar-height, 64px) + 10px) !important; + left: calc(50vw + var(--ecom-history-offset, 0px)) !important; + transform: translateX(-50%) !important; + z-index: 90 !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-composer-wrap.has-generated.is-compact { + gap: 0 !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-composer-wrap.has-generated.is-compact .ecom-command-title { + display: none !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-composer-wrap.has-generated.is-compact .clone-ai-input-wrapper.ecom-command-composer, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-composer-wrap.has-generated.is-compact .clone-ai-input-wrapper.ecom-command-composer:has(.ecom-command-asset-popover) { + grid-template-rows: 44px 22px 34px !important; + row-gap: 4px !important; + min-height: 118px !important; + max-height: 126px !important; + padding: 10px 18px 10px !important; + overflow: visible !important; + border-radius: 22px !important; + border: 1px solid rgba(30, 189, 219, 0.14) !important; + background: rgba(254, 255, 255, 0.94) !important; + box-shadow: + 0 8px 32px rgba(16, 115, 204, 0.07), + 0 2px 8px rgba(16, 115, 204, 0.04) !important; + backdrop-filter: blur(16px) !important; + -webkit-backdrop-filter: blur(16px) !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-composer-wrap.has-generated.is-compact .ecom-command-asset-popover, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-composer-wrap.has-generated.is-compact .clone-ai-input-wrapper.ecom-command-composer:has(.ecom-command-asset-popover) .ecom-command-asset-popover { + grid-row: 1 !important; + min-height: 44px !important; + max-height: 44px !important; + padding: 0 !important; + overflow: visible !important; + background: transparent !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-composer-wrap.has-generated.is-compact .ecom-command-asset-thumb, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-composer-wrap.has-generated.is-compact .clone-ai-input-wrapper.ecom-command-composer:has(.ecom-command-asset-popover) .ecom-command-asset-thumb { + flex: 0 0 44px !important; + width: 44px !important; + height: 44px !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-composer-wrap.has-generated.is-compact .ecom-command-asset-add, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-composer-wrap.has-generated.is-compact .clone-ai-input-wrapper.ecom-command-composer:has(.ecom-command-asset-popover) .ecom-command-asset-add { + flex: 0 0 34px !important; + width: 34px !important; + height: 34px !important; + min-height: 34px !important; + margin-top: 5px !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-composer-wrap.has-generated.is-compact .ecom-command-composer textarea, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-composer-wrap.has-generated.is-compact .clone-ai-input-wrapper.ecom-command-composer:has(.ecom-command-asset-popover) > textarea { + grid-row: 2 !important; + min-height: 22px !important; + max-height: 22px !important; + padding: 0 !important; + overflow: hidden !important; + font-size: 14px !important; + line-height: 22px !important; + white-space: nowrap !important; + text-overflow: ellipsis !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-composer-wrap.has-generated.is-compact .ecom-command-toolbar, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-composer-wrap.has-generated.is-compact .clone-ai-input-wrapper.ecom-command-composer:has(.ecom-command-asset-popover) .ecom-command-toolbar { + grid-row: 3 !important; + min-height: 34px !important; + padding-top: 2px !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .clone-ai-preview[data-status="done"] { + padding-top: 138px !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .clone-ai-preview[data-status="done"]:has(.ecom-command-composer-wrap:not(.is-compact)) { + padding-top: 320px !important; +} + +/* Generated composer top alignment: compensate preview padding so the box sits below the topbar. */ +.ecommerce-standalone .product-clone-page[data-tool="clone"] .clone-ai-preview[data-status="done"] .ecom-command-composer-wrap.has-generated { + top: calc(var(--ecommerce-topbar-height, 64px) + 10px) !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .clone-ai-preview[data-status="done"]:has(.ecom-command-composer-wrap:not(.is-compact)) .ecom-command-composer-wrap.has-generated { + top: calc(var(--ecommerce-topbar-height, 64px) + 10px) !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-history { + z-index: 80 !important; + pointer-events: auto !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-history__tools, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-history__tools button, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-history__list, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-history__list button { + pointer-events: auto !important; +} + +/* Right generation history: explicit functional panel with a visible collapsed handle. */ +.ecommerce-standalone .product-clone-page[data-tool="clone"] { + --ecom-history-panel-width: 292px; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-history { + position: fixed !important; + top: 0 !important; + right: 0 !important; + bottom: 0 !important; + z-index: 90 !important; + display: grid !important; + grid-template-rows: auto auto auto minmax(0, 1fr) !important; + width: var(--ecom-history-panel-width) !important; + overflow: visible !important; + border-left: 1px solid rgba(30, 189, 219, 0.18) !important; + background: rgba(254, 255, 255, 0.96) !important; + box-shadow: -18px 0 42px rgba(16, 115, 204, 0.08) !important; + backdrop-filter: blur(18px) !important; + -webkit-backdrop-filter: blur(18px) !important; + transform: translateX(0) !important; + transition: + transform 520ms cubic-bezier(0.16, 1, 0.3, 1), + box-shadow 360ms ease, + border-color 360ms ease !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"].is-history-collapsed .ecom-command-history { + transform: translateX(100%) !important; + box-shadow: none !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-history__backdrop { + position: fixed !important; + inset: 0 !important; + z-index: 85 !important; + background: rgba(16, 38, 56, 0.28) !important; + backdrop-filter: blur(2px) !important; + -webkit-backdrop-filter: blur(2px) !important; + animation: ecommerce-soft-scrim-in 240ms ease-out both !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-history__tools { + display: grid !important; + grid-template-columns: 40px minmax(0, 1fr) 40px !important; + align-items: center !important; + gap: 8px !important; + padding: 12px 12px 10px !important; + border-bottom: 0 !important; + background: transparent !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-history__tools button { + display: inline-flex !important; + align-items: center !important; + justify-content: center !important; + min-width: 0 !important; + min-height: 38px !important; + height: 38px !important; + border: 1px solid rgba(30, 189, 219, 0.22) !important; + border-radius: 13px !important; + color: #10202c !important; + background: #f3f8fa !important; + box-shadow: none !important; + font-size: 14px !important; + font-weight: 600 !important; + cursor: pointer !important; + transition: + transform 180ms ease, + border-color 220ms ease, + background 220ms ease, + color 220ms ease !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-history__tools button:hover { + border-color: rgba(30, 189, 219, 0.5) !important; + color: #1073cc !important; + background: rgba(30, 189, 219, 0.1) !important; + transform: translateY(-1px) !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-history__toggle { + position: static !important; + width: 40px !important; + min-width: 40px !important; + padding: 0 !important; + font-size: 25px !important; + line-height: 1 !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"].is-history-collapsed .ecom-command-history__toggle { + position: absolute !important; + top: 50% !important; + left: -52px !important; + right: auto !important; + z-index: 100 !important; + width: 42px !important; + height: 42px !important; + min-height: 42px !important; + border-radius: 15px !important; + background: #feffff !important; + box-shadow: 0 16px 34px rgba(16, 115, 204, 0.14) !important; + transform: translateY(-50%) !important; + pointer-events: auto !important; + visibility: visible !important; + opacity: 1 !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"].is-history-collapsed .ecom-command-history__new, +.ecommerce-standalone .product-clone-page[data-tool="clone"].is-history-collapsed .ecom-command-history__refresh, +.ecommerce-standalone .product-clone-page[data-tool="clone"].is-history-collapsed .ecom-command-history__heading, +.ecommerce-standalone .product-clone-page[data-tool="clone"].is-history-collapsed .ecom-command-history__refresh-note, +.ecommerce-standalone .product-clone-page[data-tool="clone"].is-history-collapsed .ecom-command-history__list { + opacity: 0 !important; + visibility: hidden !important; + pointer-events: none !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-history__new { + border-color: rgba(30, 189, 219, 0.46) !important; + color: #0f6678 !important; + background: rgba(30, 189, 219, 0.12) !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-history__refresh { + font-size: 18px !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-history__refresh.is-refreshing { + color: #1073cc !important; + background: rgba(30, 189, 219, 0.14) !important; + animation: ecom-history-refresh-spin 680ms linear infinite !important; + cursor: wait !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-history__refresh:disabled { + opacity: 0.78 !important; +} + +@keyframes ecom-history-refresh-spin { + from { + transform: rotate(0deg); + } + to { + transform: rotate(360deg); + } +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-history__heading { + display: flex !important; + align-items: center !important; + justify-content: space-between !important; + gap: 12px !important; + margin: 2px 12px 10px !important; + padding: 12px 12px !important; + border: 1px solid rgba(30, 189, 219, 0.14) !important; + border-radius: 14px !important; + background: #f8f9fa !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-history__heading strong { + color: #10202c !important; + font-size: 14px !important; + font-weight: 700 !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-history__heading span { + color: #68818f !important; + font-size: 12px !important; + font-weight: 500 !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-history__refresh-note { + margin: -2px 12px 10px !important; + padding: 8px 10px !important; + border: 1px solid rgba(30, 189, 219, 0.18) !important; + border-radius: 12px !important; + color: #0f6678 !important; + background: rgba(30, 189, 219, 0.08) !important; + font-size: 12px !important; + font-weight: 500 !important; + text-align: center !important; + animation: ecommerce-soft-drop-in 260ms ease-out both !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-history__list { + display: grid !important; + align-content: start !important; + gap: 8px !important; + min-height: 0 !important; + overflow: auto !important; + padding: 0 12px 18px !important; + background: transparent !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-history__list button { + display: grid !important; + gap: 6px !important; + min-height: 66px !important; + padding: 12px 12px !important; + border: 1px solid rgba(30, 189, 219, 0.12) !important; + border-radius: 14px !important; + color: #10202c !important; + background: #feffff !important; + box-shadow: 0 8px 20px rgba(16, 115, 204, 0.045) !important; + text-align: left !important; + cursor: pointer !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-history__list button:hover, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-history__list button.is-active { + border-color: rgba(30, 189, 219, 0.38) !important; + background: rgba(30, 189, 219, 0.1) !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-history__item { + position: relative !important; + display: grid !important; + grid-template-columns: 1fr auto !important; + align-items: stretch !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-history__item .ecom-command-history__item-main { + grid-column: 1 / -1 !important; + grid-row: 1 !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-history__item .ecom-command-history__item-delete { + grid-column: 2 !important; + grid-row: 1 !important; + z-index: 2 !important; + align-self: center !important; + width: 28px !important; + height: 28px !important; + min-height: 28px !important; + margin-right: 6px !important; + padding: 0 !important; + border: none !important; + border-radius: 6px !important; + color: #99a8b2 !important; + background: rgba(255, 255, 255, 0.92) !important; + box-shadow: 0 1px 4px rgba(0, 0, 0, 0.08) !important; + font-size: 13px !important; + cursor: pointer !important; + opacity: 0 !important; + transition: opacity 160ms ease, color 120ms ease, background 120ms ease !important; + pointer-events: none !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-history__item:hover .ecom-command-history__item-delete { + opacity: 1 !important; + pointer-events: auto !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-history__item .ecom-command-history__item-delete:hover { + color: #ff4d4f !important; + background: rgba(255, 77, 79, 0.1) !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-history__item.is-active .ecom-command-history__item-main { + border-color: rgba(30, 189, 219, 0.42) !important; + background: rgba(30, 189, 219, 0.12) !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-history__list strong { + display: block !important; + overflow: hidden !important; + color: #10202c !important; + font-size: 14px !important; + font-weight: 700 !important; + line-height: 1.35 !important; + text-overflow: ellipsis !important; + white-space: nowrap !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-history__list span { + overflow: hidden !important; + color: #68818f !important; + font-size: 12px !important; + font-weight: 500 !important; + text-overflow: ellipsis !important; + white-space: nowrap !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-history__empty { + margin: 0 !important; + padding: 26px 12px !important; + border: 1px dashed rgba(30, 189, 219, 0.24) !important; + border-radius: 14px !important; + color: #68818f !important; + background: #f8f9fa !important; + font-size: 13px !important; + font-weight: 500 !important; + text-align: center !important; +} + +/* Platform menu: logos only appear in the popover, and the list opens fully without scrollbars. */ +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover.ecom-command-popover--platform { + grid-template-columns: repeat(4, 132px) !important; + align-items: start !important; + justify-items: stretch !important; + gap: 10px !important; + width: max-content !important; + min-width: 0 !important; + max-width: calc(100vw - 96px) !important; + max-height: none !important; + overflow: visible !important; + overflow-x: visible !important; + overflow-y: visible !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover.ecom-command-popover--platform button { + width: 100% !important; + min-width: 0 !important; + max-width: none !important; + overflow: hidden !important; + justify-content: flex-start !important; + gap: 8px !important; + padding: 8px 10px !important; + white-space: nowrap !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover.ecom-command-popover--platform .ecom-platform-logo-mark { + position: relative !important; + display: inline-flex !important; + align-items: center !important; + justify-content: center !important; + flex: 0 0 30px !important; + width: 30px !important; + height: 30px !important; + padding: 0 !important; + border-radius: 9px !important; + overflow: visible !important; + color: #fff !important; + background: transparent !important; + box-shadow: 0 8px 18px rgba(16, 32, 44, 0.12) !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover.ecom-command-popover--platform .ecom-platform-logo-mark--duo { + flex-basis: 45px !important; + width: 45px !important; + gap: 3px !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover.ecom-command-popover--platform .ecom-platform-logo-mark__tile { + position: relative !important; + display: inline-grid !important; + place-items: center !important; + width: 30px !important; + height: 30px !important; + border-radius: 9px !important; + color: #fff !important; + font-size: 14px !important; + font-weight: 900 !important; + line-height: 1 !important; + letter-spacing: 0 !important; + text-shadow: 0 1px 2px rgba(0, 0, 0, 0.18) !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover.ecom-command-popover--platform .ecom-platform-logo-mark--duo .ecom-platform-logo-mark__tile { + width: 21px !important; + height: 30px !important; + border-radius: 8px !important; + font-size: 13px !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover.ecom-command-popover--platform .ecom-platform-logo-mark__tile--wide { + font-size: 11px !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover.ecom-command-popover--platform .ecom-platform-logo-mark--taobao .ecom-platform-logo-mark__tile:first-child { + background: linear-gradient(135deg, #ff8a00, #ff4d00) !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover.ecom-command-popover--platform .ecom-platform-logo-mark--taobao .ecom-platform-logo-mark__tile:last-child { + background: linear-gradient(135deg, #ff3d5f, #c9002b) !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover.ecom-command-popover--platform .ecom-platform-logo-mark--jd .ecom-platform-logo-mark__tile { + background: linear-gradient(135deg, #f22735, #bd0016) !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover.ecom-command-popover--platform .ecom-platform-logo-mark--pdd .ecom-platform-logo-mark__tile { + background: linear-gradient(135deg, #ff5b35, #e60012) !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover.ecom-command-popover--platform .ecom-platform-logo-mark--douyin .ecom-platform-logo-mark__tile, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover.ecom-command-popover--platform .ecom-platform-logo-mark--tiktok .ecom-platform-logo-mark__tile { + background: #111318 !important; + text-shadow: -1px 0 #25f4ee, 1px 0 #fe2c55 !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover.ecom-command-popover--platform .ecom-platform-logo-mark--amazon .ecom-platform-logo-mark__tile { + align-items: start !important; + padding-top: 5px !important; + background: #18202a !important; + font-family: Arial, Helvetica, sans-serif !important; + font-size: 19px !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover.ecom-command-popover--platform .ecom-platform-logo-mark--amazon::after { + content: "" !important; + position: absolute !important; + left: 8px !important; + right: 7px !important; + bottom: 7px !important; + height: 5px !important; + border-bottom: 2px solid #ff9900 !important; + border-radius: 0 0 999px 999px !important; + transform: rotate(-8deg) !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover.ecom-command-popover--platform .ecom-platform-logo-mark--shopee .ecom-platform-logo-mark__tile { + background: linear-gradient(135deg, #ff7043, #ee4d2d) !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover.ecom-command-popover--platform .ecom-platform-logo-mark--shopee::before { + content: "" !important; + position: absolute !important; + top: 5px !important; + left: 9px !important; + width: 12px !important; + height: 8px !important; + border: 2px solid rgba(255, 255, 255, 0.9) !important; + border-bottom: 0 !important; + border-radius: 999px 999px 0 0 !important; + z-index: 2 !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover.ecom-command-popover--platform .ecom-platform-logo-mark--lazada .ecom-platform-logo-mark__tile { + background: linear-gradient(135deg, #2335d6, #8b2cff 48%, #ff7a00) !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover.ecom-command-popover--platform .ecom-platform-logo-mark--instagram .ecom-platform-logo-mark__tile { + background: radial-gradient(circle at 28% 92%, #ffd86b 0 22%, transparent 23%), linear-gradient(135deg, #405de6, #833ab4 38%, #e1306c 68%, #fd1d1d 84%, #fcb045) !important; + font-size: 10px !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover.ecom-command-popover--platform .ecom-platform-logo-mark--aliexpress .ecom-platform-logo-mark__tile { + background: linear-gradient(135deg, #ff4f1f, #d71920) !important; + font-size: 10px !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover.ecom-command-popover--platform .ecom-platform-logo-mark--ebay .ecom-platform-logo-mark__tile { + background: #fff !important; + color: #1d60b8 !important; + text-shadow: 1px 0 #e53238, 2px 0 #f5af02, 3px 0 #86b817 !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover.ecom-command-popover--platform .ecom-platform-logo-mark--default .ecom-platform-logo-mark__tile { + background: linear-gradient(135deg, #18b7d6, #1073cc) !important; +} + +/* Language menu: show all rows directly, no inner scrollbar. */ +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover.ecom-command-popover--languages { + max-height: none !important; + overflow: visible !important; + overflow-x: visible !important; + overflow-y: visible !important; + scrollbar-gutter: auto !important; +} + +/* Command menus: every option panel expands fully instead of using inner scrollbars. */ +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover.ecom-command-popover--grid, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover.ecom-command-popover--list, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover.ecom-command-popover--ratio, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover.ecom-command-popover--languages, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover.ecom-command-popover--platform, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover.ecom-command-popover--settings, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover--settings, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover--settings-set, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover.ecom-command-popover--settings-set, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-module-grid, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-module-grid--detail, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-module-grid--model, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-module-grid--video, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-hot-levels, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-hot-thumb-grid { + max-height: none !important; + overflow: visible !important; + overflow-x: visible !important; + overflow-y: visible !important; + scrollbar-gutter: auto !important; +} + +/* Soft premium motion: brand halo, credit shimmer, and active-tag glints. */ +.ecommerce-standalone .ecommerce-standalone__logo { + position: relative !important; + overflow: visible !important; + isolation: isolate !important; +} + +.ecommerce-standalone .ecommerce-standalone__logo::before { + position: absolute !important; + inset: -7px !important; + z-index: -1 !important; + display: block !important; + border-radius: 999px !important; + content: "" !important; + background: + radial-gradient(circle, rgba(30, 189, 219, 0.28), rgba(16, 115, 204, 0.12) 44%, transparent 70%) !important; + filter: blur(2px) !important; + opacity: 0.52 !important; + transform: scale(0.92) !important; + animation: ecom-brand-halo-breathe 4.8s ease-in-out infinite !important; +} + +.ecommerce-standalone .ecommerce-standalone__credits { + position: relative !important; + overflow: hidden !important; + isolation: isolate !important; +} + +.ecommerce-standalone .ecommerce-standalone__credits::after { + position: absolute !important; + top: -38% !important; + bottom: -38% !important; + left: -42% !important; + z-index: 1 !important; + width: 34% !important; + pointer-events: none !important; + content: "" !important; + background: linear-gradient(105deg, transparent 0%, rgba(255, 255, 255, 0.74) 48%, transparent 100%) !important; + transform: translateX(-160%) skewX(-18deg) !important; + animation: ecom-credit-shimmer 7.2s ease-in-out infinite !important; +} + +.ecommerce-standalone .ecommerce-standalone__credits > * { + position: relative !important; + z-index: 2 !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-option-row button.is-active, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover button.is-active, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-history__list button.is-active, +.ecommerce-standalone .product-clone-rail button.is-active, +.ecommerce-standalone .clone-ai-tag-group button.is-active, +.ecommerce-standalone .ecommerce-auth-modal__tabs button.is-active, +.ecommerce-standalone .ecommerce-auth-modal__methods button.is-active, +.ecommerce-standalone .local-profile-tabs button.is-active { + position: relative !important; + overflow: hidden !important; + isolation: isolate !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-option-row button.is-active::after, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover button.is-active::after, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-history__list button.is-active::after, +.ecommerce-standalone .product-clone-rail button.is-active::after, +.ecommerce-standalone .clone-ai-tag-group button.is-active::after, +.ecommerce-standalone .ecommerce-auth-modal__tabs button.is-active::after, +.ecommerce-standalone .ecommerce-auth-modal__methods button.is-active::after, +.ecommerce-standalone .local-profile-tabs button.is-active::after { + position: absolute !important; + top: -45% !important; + bottom: -45% !important; + left: -46% !important; + z-index: 1 !important; + width: 28% !important; + pointer-events: none !important; + content: "" !important; + background: linear-gradient(105deg, transparent 0%, rgba(255, 255, 255, 0.72) 48%, transparent 100%) !important; + transform: translateX(-170%) skewX(-18deg) !important; + animation: ecom-active-tag-glint 5.6s ease-in-out infinite !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-option-row button.is-active > *, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover button.is-active > *, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-history__list button.is-active > *, +.ecommerce-standalone .product-clone-rail button.is-active > *, +.ecommerce-standalone .clone-ai-tag-group button.is-active > *, +.ecommerce-standalone .ecommerce-auth-modal__tabs button.is-active > *, +.ecommerce-standalone .ecommerce-auth-modal__methods button.is-active > *, +.ecommerce-standalone .local-profile-tabs button.is-active > * { + position: relative !important; + z-index: 2 !important; +} + +@keyframes ecom-brand-halo-breathe { + 0%, + 100% { + opacity: 0.42; + transform: scale(0.9); + } + 50% { + opacity: 0.78; + transform: scale(1.16); + } +} + +@keyframes ecom-credit-shimmer { + 0%, + 62% { + transform: translateX(-180%) skewX(-18deg); + } + 76%, + 100% { + transform: translateX(460%) skewX(-18deg); + } +} + +@keyframes ecom-active-tag-glint { + 0%, + 56% { + transform: translateX(-180%) skewX(-18deg); + } + 72%, + 100% { + transform: translateX(480%) skewX(-18deg); + } +} + +/* Model settings: expose model appearance controls inside the command popover. */ +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover--settings-model { + grid-template-columns: repeat(3, minmax(138px, 1fr)) !important; + width: min(720px, calc(100vw - 56px)) !important; + max-width: min(720px, calc(100vw - 56px)) !important; + margin-left: -128px !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover--settings-model header, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover--settings-model .ecom-command-module-grid--model, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-model-profile, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-model-text { + grid-column: 1 / -1 !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover--settings-model header { + order: 0 !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-model-profile { + order: 1 !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover--settings-model .ecom-command-module-grid--model { + order: 2 !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-model-profile { + display: grid !important; + grid-template-columns: 1fr !important; + gap: 8px !important; + padding: 0 !important; + border: 0 !important; + border-radius: 0 !important; + background: transparent !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-model-profile__title { + grid-column: 1 / -1 !important; + color: #10202c !important; + font-size: 13px !important; + font-weight: 700 !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-model-profile section { + display: grid !important; + grid-template-columns: 52px minmax(0, 1fr) !important; + align-items: center !important; + gap: 8px !important; + min-width: 0 !important; + padding: 0 !important; + border: 0 !important; + border-radius: 0 !important; + background: transparent !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-model-profile section > strong, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-model-text > strong { + color: #526f7e !important; + font-size: 12px !important; + font-weight: 700 !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-model-profile section > div { + display: flex !important; + flex-wrap: wrap !important; + gap: 6px !important; + min-width: 0 !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-model-profile button { + width: auto !important; + min-width: 0 !important; + min-height: 32px !important; + padding: 6px 12px !important; + font-size: 12px !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-model-text { + display: grid !important; + gap: 7px !important; + padding: 0 !important; + border: 0 !important; + border-radius: 0 !important; + background: transparent !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-model-text > strong { + order: 0 !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-model-text > textarea { + order: 1 !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-model-text textarea { + min-height: 58px !important; + resize: vertical !important; + border: 1px solid rgba(30, 189, 219, 0.22) !important; + border-radius: 13px !important; + padding: 10px 12px !important; + color: #122534 !important; + background: #f3f8fa !important; + font-family: "PingFang SC", "Microsoft YaHei", sans-serif !important; + font-size: 13px !important; + font-weight: 500 !important; + line-height: 1.45 !important; +} + +/* Smart cutout quick tool: standalone upload and editor flow. */ +.ecommerce-standalone .product-clone-page[data-tool="clone"].is-smart-cutout-page { + display: block !important; + width: 100% !important; + min-width: 100% !important; + height: 100% !important; + min-height: calc(100vh - 58px) !important; + overflow: hidden !important; + background: #feffff !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"].is-smart-cutout-page .product-clone-shell { + display: block !important; + width: 100% !important; + min-width: 100% !important; + height: 100% !important; + min-height: calc(100vh - 58px) !important; + padding: 0 !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"].is-smart-cutout-page .product-clone-rail, +.ecommerce-standalone .product-clone-page[data-tool="clone"].is-smart-cutout-page .product-clone-panel, +.ecommerce-standalone .product-clone-page[data-tool="clone"].is-smart-cutout-page .clone-ai-settings-toggle, +.ecommerce-standalone .product-clone-page[data-tool="clone"].is-smart-cutout-page .ecom-command-history { + display: none !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"].is-smart-cutout-page .ecom-command-hidden-file { + position: absolute !important; + width: 1px !important; + height: 1px !important; + overflow: hidden !important; + opacity: 0 !important; + pointer-events: none !important; +} + +/* Product set quick tool: standalone task page. */ +.ecommerce-standalone .product-clone-page[data-tool="clone"].is-quick-set-page { + display: block !important; + overflow: hidden !important; + background: #f3f5f8 !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"].is-quick-set-page .product-clone-shell { + display: block !important; + width: 100% !important; + height: 100% !important; + padding: 0 !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"].is-quick-set-page .product-clone-rail, +.ecommerce-standalone .product-clone-page[data-tool="clone"].is-quick-set-page .product-clone-panel, +.ecommerce-standalone .product-clone-page[data-tool="clone"].is-quick-set-page .clone-ai-settings-toggle, +.ecommerce-standalone .product-clone-page[data-tool="clone"].is-quick-set-page .ecom-command-history { + display: none !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"].is-watermark-page { + display: block !important; + height: 100% !important; + min-height: calc(100vh - 58px) !important; + overflow: hidden !important; + background: #f8f9fa !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"].is-watermark-page .product-clone-shell { + display: block !important; + width: 100% !important; + height: 100% !important; + min-height: calc(100vh - 58px) !important; + padding: 0 !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"].is-watermark-page .product-clone-rail, +.ecommerce-standalone .product-clone-page[data-tool="clone"].is-watermark-page .product-clone-panel, +.ecommerce-standalone .product-clone-page[data-tool="clone"].is-watermark-page .clone-ai-settings-toggle, +.ecommerce-standalone .product-clone-page[data-tool="clone"].is-watermark-page .ecom-command-history { + display: none !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"].is-image-workbench-page { + display: block !important; + height: 100% !important; + min-height: calc(100vh - 58px) !important; + overflow: hidden !important; + background: #f8f9fa !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"].is-image-workbench-page .product-clone-shell { + display: block !important; + width: 100% !important; + height: 100% !important; + min-height: calc(100vh - 58px) !important; + padding: 0 !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"].is-image-workbench-page .product-clone-rail, +.ecommerce-standalone .product-clone-page[data-tool="clone"].is-image-workbench-page .product-clone-panel, +.ecommerce-standalone .product-clone-page[data-tool="clone"].is-image-workbench-page .clone-ai-settings-toggle, +.ecommerce-standalone .product-clone-page[data-tool="clone"].is-image-workbench-page .ecom-command-history { + display: none !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"].is-watermark-page .ecom-command-hidden-file { + position: absolute !important; + width: 1px !important; + height: 1px !important; + overflow: hidden !important; + opacity: 0 !important; + pointer-events: none !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"].is-translate-page { + display: block !important; + height: 100% !important; + min-height: calc(100vh - 58px) !important; + overflow: hidden !important; + background: #f8f9fa !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"].is-translate-page .product-clone-shell { + display: block !important; + width: 100% !important; + height: 100% !important; + min-height: calc(100vh - 58px) !important; + padding: 0 !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"].is-translate-page .product-clone-rail, +.ecommerce-standalone .product-clone-page[data-tool="clone"].is-translate-page .product-clone-panel, +.ecommerce-standalone .product-clone-page[data-tool="clone"].is-translate-page .clone-ai-settings-toggle, +.ecommerce-standalone .product-clone-page[data-tool="clone"].is-translate-page .ecom-command-history { + display: none !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"].is-translate-page .ecom-command-hidden-file { + position: absolute !important; + width: 1px !important; + height: 1px !important; + overflow: hidden !important; + opacity: 0 !important; + pointer-events: none !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"].is-image-workbench-page .ecom-command-hidden-file { + position: absolute !important; + width: 1px !important; + height: 1px !important; + overflow: hidden !important; + opacity: 0 !important; + pointer-events: none !important; +} + + +/* ── Quick Page Sidebar — shared left nav for set / detail ── */ +.ecommerce-standalone .ecom-quick-page-wrap { + position: absolute !important; + inset: 0 !important; + display: flex !important; + min-height: 0 !important; +} + +.ecommerce-standalone .ecom-quick-page-sidebar { + display: flex !important; + flex-direction: column !important; + align-items: center !important; + gap: 4px !important; + flex: 0 0 88px !important; + width: 88px !important; + padding: 20px 10px !important; + border-right: 1px solid rgba(30, 189, 219, 0.1) !important; + background: + linear-gradient(180deg, + rgba(255, 255, 255, 0.96) 0%, + rgba(248, 250, 252, 0.94) 50%, + rgba(243, 247, 250, 0.92) 100%) !important; + backdrop-filter: blur(20px) !important; + -webkit-backdrop-filter: blur(20px) !important; +} + +.ecommerce-standalone .ecom-quick-page-sidebar button { + position: relative !important; + display: flex !important; + flex-direction: column !important; + align-items: center !important; + justify-content: center !important; + gap: 4px !important; + width: 100% !important; + min-height: 66px !important; + padding: 10px 6px !important; + border: 0 !important; + border-radius: 12px !important; + background: transparent !important; + color: #7c8a96 !important; + font-size: 10px !important; + font-family: "PingFang SC", "Microsoft YaHei", sans-serif !important; + font-weight: 500 !important; + letter-spacing: 0.01em !important; + line-height: 1.2 !important; + cursor: pointer !important; + transition: + background 0.22s cubic-bezier(0.16, 1, 0.3, 1), + color 0.22s cubic-bezier(0.16, 1, 0.3, 1), + transform 0.22s cubic-bezier(0.16, 1, 0.3, 1), + box-shadow 0.22s cubic-bezier(0.16, 1, 0.3, 1) !important; +} + +.ecommerce-standalone .ecom-quick-page-sidebar button .anticon { + font-size: 22px !important; + transition: transform 0.22s cubic-bezier(0.16, 1, 0.3, 1) !important; +} + +.ecommerce-standalone .ecom-quick-page-sidebar button span:last-child { + display: block !important; + font-size: 10px !important; + font-weight: 500 !important; + letter-spacing: 0.02em !important; + line-height: 1.2 !important; + white-space: nowrap !important; +} + +.ecommerce-standalone .ecom-quick-page-sidebar button:hover { + background: rgba(30, 189, 219, 0.07) !important; + color: #0d6bb8 !important; + transform: translateY(-1px) !important; + box-shadow: 0 4px 12px rgba(16, 115, 204, 0.08) !important; +} + +.ecommerce-standalone .ecom-quick-page-sidebar button:hover .anticon { + transform: scale(1.08) !important; +} + +.ecommerce-standalone .ecom-quick-page-sidebar button:active { + transform: translateY(0) !important; + box-shadow: none !important; +} + +.ecommerce-standalone .ecom-quick-page-sidebar button.is-active { + background: + linear-gradient(135deg, + rgba(16, 115, 204, 0.12) 0%, + rgba(30, 189, 219, 0.08) 100%) !important; + color: #0d6bb8 !important; + font-weight: 700 !important; + box-shadow: + 0 2px 8px rgba(16, 115, 204, 0.1), + inset 0 1px 0 rgba(255, 255, 255, 0.6) !important; +} + +.ecommerce-standalone .ecom-quick-page-sidebar button.is-active::before { + content: "" !important; + position: absolute !important; + left: 0 !important; + top: 14px !important; + bottom: 14px !important; + width: 3px !important; + border-radius: 0 3px 3px 0 !important; + background: + linear-gradient(180deg, + #1073cc 0%, + #1ebddb 100%) !important; +} + +.ecommerce-standalone .ecom-quick-page-sidebar button.is-active .anticon { + color: #1073cc !important; +} + +.ecommerce-standalone .ecom-quick-page-wrap > :not(.ecom-quick-page-sidebar) { + flex: 1 1 0% !important; + min-width: 0 !important; + min-height: 0 !important; +} + + +.ecommerce-standalone .ecom-image-workbench-page { + position: relative !important; + display: grid !important; + grid-template-columns: 350px minmax(0, 1fr) !important; + gap: 18px !important; + align-items: stretch !important; + width: 100% !important; + height: 100% !important; + min-height: calc(100vh - 58px) !important; + box-sizing: border-box !important; + padding: 18px !important; + color: #172636 !important; + background: + radial-gradient(circle at 54% 48%, rgba(30, 189, 219, 0.07), transparent 28rem), + #f8f9fa !important; + font-family: "PingFang SC", "Microsoft YaHei", sans-serif !important; + animation: ecom-smart-page-enter 440ms cubic-bezier(0.16, 1, 0.3, 1) both !important; +} + +.ecommerce-standalone .ecom-image-workbench-nav { + display: none !important; +} + +.ecommerce-standalone .ecom-image-workbench-nav button, +.ecommerce-standalone .ecom-image-workbench-url-row button { + display: inline-flex !important; + align-items: center !important; + justify-content: center !important; + gap: 7px !important; + border: 1px solid rgba(16, 115, 204, 0.14) !important; + border-radius: 10px !important; + color: #1073cc !important; + background: #ffffff !important; + box-shadow: 0 8px 20px rgba(16, 115, 204, 0.06) !important; + font-weight: 850 !important; + cursor: pointer !important; + transition: transform 180ms ease, color 180ms ease, background 180ms ease, box-shadow 180ms ease !important; +} + +.ecommerce-standalone .ecom-image-workbench-nav button { + min-height: 32px !important; + padding: 0 14px !important; + font-size: 13px !important; +} + +.ecommerce-standalone .ecom-image-workbench-nav button:hover, +.ecommerce-standalone .ecom-image-workbench-url-row button:hover { + color: #ffffff !important; + background: #1073cc !important; + box-shadow: 0 12px 26px rgba(16, 115, 204, 0.18) !important; + transform: translateY(-1px) !important; +} + +.ecommerce-standalone .ecom-image-workbench-side { + display: flex !important; + flex-direction: column !important; + gap: 12px !important; + height: 100% !important; + min-height: 0 !important; + padding: 18px 16px !important; + overflow: auto !important; + border: 1px solid rgba(16, 115, 204, 0.14) !important; + border-radius: 14px !important; + background: + linear-gradient(180deg, rgba(16, 115, 204, 0.055), transparent 180px), + #ffffff !important; + box-shadow: 0 14px 34px rgba(16, 115, 204, 0.08) !important; +} + +.ecommerce-standalone .ecom-image-workbench-panel-head { + flex: 0 0 auto !important; + margin-bottom: 4px !important; +} + +.ecommerce-standalone .ecom-image-workbench-intro { + margin: -2px 2px 2px !important; + color: #66798a !important; + font-size: 12px !important; + font-weight: 750 !important; + line-height: 1.65 !important; +} + +.ecommerce-standalone .ecom-image-workbench-heading { + display: grid !important; + gap: 7px !important; + padding: 2px 2px 6px !important; +} + +.ecommerce-standalone .ecom-image-workbench-heading span { + width: fit-content !important; + padding: 3px 9px !important; + border-radius: 999px !important; + color: #1073cc !important; + background: #edf8ff !important; + font-size: 11px !important; + font-weight: 850 !important; +} + +.ecommerce-standalone .ecom-image-workbench-heading strong { + color: #172636 !important; + font-size: 22px !important; + font-weight: 950 !important; +} + +.ecommerce-standalone .ecom-image-workbench-heading p { + max-width: 286px !important; + margin: 0 !important; + color: #66798a !important; + font-size: 12px !important; + font-weight: 750 !important; + line-height: 1.7 !important; +} + +.ecommerce-standalone .ecom-image-workbench-panel { + display: grid !important; + gap: 12px !important; + padding: 14px !important; + border: 1px solid rgba(16, 115, 204, 0.14) !important; + border-radius: 12px !important; + background: + linear-gradient(180deg, rgba(255, 255, 255, 0.5), transparent), + #ffffff !important; + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.75), 0 10px 28px rgba(16, 115, 204, 0.035) !important; +} + +.ecommerce-standalone .ecom-image-workbench-panel header { + display: flex !important; + align-items: center !important; + justify-content: space-between !important; +} + +.ecommerce-standalone .ecom-image-workbench-panel strong, +.ecommerce-standalone .ecom-image-workbench-upload strong { + color: #132435 !important; + font-size: 13px !important; + font-weight: 950 !important; +} + +.ecommerce-standalone .ecom-image-workbench-panel header span { + padding: 3px 9px !important; + border-radius: 999px !important; + color: #1073cc !important; + background: #edf8ff !important; + font-size: 11px !important; + font-weight: 850 !important; +} + +.ecommerce-standalone .ecom-image-workbench-upload { + position: relative !important; + display: grid !important; + grid-template-columns: 74px minmax(0, 1fr) !important; + align-items: center !important; + gap: 12px !important; + min-height: 104px !important; + padding: 12px !important; + border: 1px dashed rgba(30, 189, 219, 0.5) !important; + border-radius: 12px !important; + color: #607485 !important; + background: #fbfdff !important; + cursor: pointer !important; + transition: border-color 180ms ease, background 180ms ease, box-shadow 180ms ease !important; +} + +.ecommerce-standalone .ecom-image-workbench-upload:not(.has-image) { + grid-template-columns: 1fr !important; + justify-items: center !important; + text-align: center !important; +} + +.ecommerce-standalone .ecom-image-workbench-upload.is-dragging, +.ecommerce-standalone .ecom-image-workbench-upload:hover { + border-color: #1ebddb !important; + background: #f6fcff !important; + box-shadow: 0 12px 28px rgba(16, 115, 204, 0.12) !important; +} + +.ecommerce-standalone .ecom-image-workbench-upload > .anticon { + color: #1ebddb !important; + font-size: 30px !important; +} + +.ecommerce-standalone .ecom-image-workbench-upload figure { + width: 74px !important; + height: 74px !important; + margin: 0 !important; + overflow: hidden !important; + border: 1px solid rgba(16, 115, 204, 0.12) !important; + border-radius: 10px !important; + background: #f8f9fa !important; +} + +.ecommerce-standalone .ecom-image-workbench-upload img { + width: 100% !important; + height: 100% !important; + object-fit: cover !important; +} + +.ecommerce-standalone .ecom-image-workbench-upload div { + display: grid !important; + gap: 8px !important; + min-width: 0 !important; +} + +.ecommerce-standalone .ecom-image-workbench-upload div strong { + overflow: hidden !important; + text-overflow: ellipsis !important; + white-space: nowrap !important; +} + +.ecommerce-standalone .ecom-image-workbench-upload span { + color: #627485 !important; + font-size: 12px !important; + font-weight: 750 !important; +} + +.ecommerce-standalone .ecom-image-workbench-remove { + position: absolute !important; + top: 8px !important; + right: 8px !important; + z-index: 2 !important; + display: inline-grid !important; + place-items: center !important; + width: 24px !important; + height: 24px !important; + border: 1px solid rgba(16, 115, 204, 0.14) !important; + border-radius: 50% !important; + color: #526474 !important; + background: rgba(255, 255, 255, 0.92) !important; + box-shadow: 0 6px 14px rgba(16, 115, 204, 0.12) !important; + font-size: 16px !important; + font-weight: 850 !important; + line-height: 1 !important; + cursor: pointer !important; +} + +.ecommerce-standalone .ecom-image-workbench-url-row { + display: grid !important; + grid-template-columns: minmax(0, 1fr) 58px !important; + gap: 8px !important; +} + +.ecommerce-standalone .ecom-image-workbench-url-row input, +.ecommerce-standalone .ecom-image-workbench-panel textarea { + width: 100% !important; + border: 1px solid rgba(16, 115, 204, 0.12) !important; + border-radius: 9px !important; + color: #172636 !important; + background: #f8fafc !important; + outline: none !important; + font-size: 12px !important; + font-weight: 800 !important; +} + +.ecommerce-standalone .ecom-image-workbench-url-row input { + min-height: 36px !important; + padding: 0 12px !important; +} + +.ecommerce-standalone .ecom-image-workbench-url-row button { + min-height: 36px !important; + padding: 0 12px !important; + font-size: 12px !important; +} + +.ecommerce-standalone .ecom-image-workbench-panel textarea { + min-height: 112px !important; + padding: 12px !important; + resize: vertical !important; + line-height: 1.7 !important; +} + +.ecommerce-standalone .ecom-image-workbench-slider { + display: grid !important; + grid-template-columns: 44px minmax(0, 1fr) 44px !important; + align-items: center !important; + gap: 10px !important; + color: #526474 !important; + font-size: 12px !important; + font-weight: 850 !important; +} + +.ecommerce-standalone .ecom-image-workbench-slider input { + accent-color: #1ebddb !important; +} + +.ecommerce-standalone .ecom-image-workbench-slider em { + color: #738392 !important; + font-style: normal !important; + text-align: right !important; +} + +.ecommerce-standalone .ecom-image-workbench-clear { + min-height: 34px !important; + border: 1px solid rgba(16, 115, 204, 0.12) !important; + border-radius: 9px !important; + color: #1073cc !important; + background: #edf8ff !important; + font-size: 12px !important; + font-weight: 900 !important; + cursor: pointer !important; +} + +.ecommerce-standalone .ecom-image-workbench-clear:disabled { + color: #9badba !important; + background: #f1f4f6 !important; + cursor: not-allowed !important; +} + +.ecommerce-standalone .ecom-image-workbench-ratios { + display: grid !important; + grid-template-columns: repeat(5, minmax(0, 1fr)) !important; + gap: 6px !important; + padding: 4px !important; + border: 1px solid rgba(16, 115, 204, 0.1) !important; + border-radius: 10px !important; + background: #f8fafc !important; +} + +.ecommerce-standalone .ecom-image-workbench-ratios button { + min-height: 30px !important; + border: 0 !important; + border-radius: 7px !important; + color: #526474 !important; + background: transparent !important; + font-size: 12px !important; + font-weight: 900 !important; +} + +.ecommerce-standalone .ecom-image-workbench-ratios button.is-active { + color: #1073cc !important; + background: #edf8ff !important; + box-shadow: inset 0 0 0 1px rgba(30, 189, 219, 0.22) !important; +} + +.ecommerce-standalone .ecom-image-workbench-primary { + display: inline-flex !important; + align-items: center !important; + justify-content: center !important; + gap: 9px !important; + min-height: 48px !important; + width: 100% !important; + margin-top: 2px !important; + border: 0 !important; + border-radius: 13px !important; + color: #ffffff !important; + background: linear-gradient(135deg, #1073cc, #1ebddb) !important; + box-shadow: 0 18px 38px rgba(16, 115, 204, 0.24) !important; + font-size: 15px !important; + font-weight: 950 !important; +} + +.ecommerce-standalone .ecom-image-workbench-primary:disabled { + color: #8ea0ad !important; + background: #edf1f4 !important; + box-shadow: none !important; +} + +.ecommerce-standalone .ecom-image-workbench-stage { + display: grid !important; + place-items: stretch !important; + min-width: 0 !important; + min-height: 0 !important; + height: 100% !important; + padding: 0 !important; + overflow: hidden !important; + border: none !important; + border-radius: 0 !important; + background: #f8f9fa !important; + box-shadow: none !important; +} + +.ecommerce-standalone .ecom-image-workbench-canvas { + position: relative !important; + display: grid !important; + place-items: center !important; + width: 100% !important; + height: 100% !important; + min-height: 0 !important; + overflow: hidden !important; + border: 1px dashed rgba(30, 189, 219, 0.42) !important; + border-radius: 0 !important; + background: + radial-gradient(circle, rgba(30, 189, 219, 0.18) 1px, transparent 1px), + linear-gradient(90deg, rgba(30, 189, 219, 0.04), rgba(16, 115, 204, 0.02)) !important; + background-color: #fbfdff !important; + background-size: 18px 18px, 100% 100% !important; + cursor: pointer !important; +} + +.ecommerce-standalone .ecom-image-workbench-canvas.is-dragging, +.ecommerce-standalone .ecom-image-workbench-canvas:hover { + border-color: rgba(30, 189, 219, 0.58) !important; +} + +.ecommerce-standalone .ecom-image-workbench-empty { + display: grid !important; + place-items: center !important; + gap: 12px !important; + max-width: 460px !important; + text-align: center !important; +} + +.ecommerce-standalone .ecom-image-workbench-empty .anticon { + display: inline-grid !important; + place-items: center !important; + width: 56px !important; + height: 56px !important; + border-radius: 16px !important; + color: #1073cc !important; + background: #edf8ff !important; + font-size: 26px !important; +} + +.ecommerce-standalone .ecom-image-workbench-empty strong { + color: #172636 !important; + font-size: 18px !important; + font-weight: 950 !important; +} + +.ecommerce-standalone .ecom-image-workbench-empty span { + color: #66798a !important; + font-size: 12px !important; + font-weight: 750 !important; +} + +.ecommerce-standalone .ecom-image-workbench-preview { + position: relative !important; + display: grid !important; + place-items: center !important; + width: min(72%, 760px) !important; + max-height: 78vh !important; + padding: 18px !important; + border: 1px solid rgba(16, 115, 204, 0.1) !important; + border-radius: 16px !important; + background: #ffffff !important; + box-shadow: 0 16px 44px rgba(16, 115, 204, 0.08) !important; +} + +.ecommerce-standalone .ecom-image-workbench-image-frame { + position: relative !important; + display: block !important; + justify-self: center !important; + width: fit-content !important; + height: fit-content !important; + max-width: 100% !important; + max-height: 68vh !important; + overflow: hidden !important; + border-radius: 12px !important; + cursor: crosshair !important; + line-height: 0 !important; + touch-action: none !important; + user-select: none !important; +} + +.ecommerce-standalone .ecom-image-workbench-image-frame img { + display: block !important; + max-width: 100% !important; + max-height: 68vh !important; + border-radius: 12px !important; + object-fit: contain !important; + user-select: none !important; + pointer-events: none !important; + -webkit-user-drag: none !important; +} + +.ecommerce-standalone .ecom-image-workbench-preview em { + position: absolute !important; + left: 18px !important; + top: 18px !important; + padding: 5px 11px !important; + border-radius: 999px !important; + color: #1073cc !important; + background: rgba(237, 248, 255, 0.92) !important; + font-size: 12px !important; + font-style: normal !important; + font-weight: 950 !important; +} + +.ecommerce-standalone .ecom-image-workbench-brush { + position: absolute !important; + z-index: 4 !important; + display: none !important; + border: 2px solid rgba(30, 189, 219, 0.72) !important; + border-radius: 50% !important; + background: rgba(30, 189, 219, 0.16) !important; + box-shadow: 0 0 0 6px rgba(30, 189, 219, 0.08) !important; + transform: translate(-50%, -50%) !important; + pointer-events: none !important; +} + +.ecommerce-standalone .ecom-image-workbench-mask-layer { + position: absolute !important; + inset: 0 !important; + z-index: 3 !important; + width: 100% !important; + height: 100% !important; + overflow: hidden !important; + border-radius: 12px !important; + pointer-events: none !important; +} + +.ecommerce-standalone .ecom-image-workbench-result { + display: grid !important; + place-items: center !important; + gap: 16px !important; + width: 100% !important; +} + +.ecommerce-standalone .ecom-image-workbench-result img { + display: block !important; + max-width: 100% !important; + max-height: 60vh !important; + border-radius: 12px !important; + object-fit: contain !important; +} + +.ecommerce-standalone .ecom-image-workbench-generating { + position: relative !important; + display: grid !important; + place-items: center !important; + width: 100% !important; +} + +.ecommerce-standalone .ecom-watermark-page { + position: relative !important; + display: grid !important; + grid-template-columns: 350px minmax(0, 1fr) !important; + gap: 0 !important; + align-items: stretch !important; + width: 100% !important; + height: 100% !important; + min-height: calc(100vh - 58px) !important; + box-sizing: border-box !important; + padding: 0 !important; + color: #172636 !important; + background: #f8f9fa !important; + font-family: "PingFang SC", "Microsoft YaHei", sans-serif !important; + animation: ecom-smart-page-enter 440ms cubic-bezier(0.16, 1, 0.3, 1) both !important; +} + +.ecommerce-standalone .ecom-watermark-nav { + display: none !important; +} + +.ecommerce-standalone .ecom-watermark-nav button, +.ecommerce-standalone .ecom-watermark-url-row button, +.ecommerce-standalone .ecom-watermark-actions button { + display: inline-flex !important; + align-items: center !important; + justify-content: center !important; + gap: 7px !important; + border: 1px solid rgba(16, 115, 204, 0.14) !important; + border-radius: 10px !important; + color: #1073cc !important; + background: #ffffff !important; + box-shadow: 0 8px 20px rgba(16, 115, 204, 0.06) !important; + font-weight: 850 !important; + cursor: pointer !important; + transition: transform 180ms ease, color 180ms ease, background 180ms ease, box-shadow 180ms ease !important; +} + +.ecommerce-standalone .ecom-watermark-nav button { + min-height: 32px !important; + padding: 0 14px !important; + font-size: 13px !important; +} + +.ecommerce-standalone .ecom-watermark-nav button:hover, +.ecommerce-standalone .ecom-watermark-url-row button:hover, +.ecommerce-standalone .ecom-watermark-actions button:hover:not(:disabled) { + color: #ffffff !important; + background: #1073cc !important; + box-shadow: 0 12px 26px rgba(16, 115, 204, 0.18) !important; + transform: translateY(-1px) !important; +} + +.ecommerce-standalone .ecom-watermark-side { + display: flex !important; + flex-direction: column !important; + gap: 10px !important; + height: 100% !important; + min-height: 0 !important; + padding: 14px 16px !important; + overflow: auto !important; + border: none !important; + border-right: 1px solid rgba(16, 115, 204, 0.1) !important; + border-radius: 0 !important; + background: #ffffff !important; + box-shadow: none !important; +} + +.ecommerce-standalone .ecom-watermark-panel-head { + flex: 0 0 auto !important; + margin-bottom: 0 !important; +} + +.ecommerce-standalone .ecom-watermark-intro { + margin: 0 2px 0 !important; + color: #66798a !important; + font-size: 12px !important; + font-weight: 750 !important; + line-height: 1.65 !important; +} + +.ecommerce-standalone .ecom-watermark-heading { + display: grid !important; + gap: 7px !important; + padding: 2px 2px 6px !important; +} + +.ecommerce-standalone .ecom-watermark-heading span { + width: fit-content !important; + padding: 3px 9px !important; + border-radius: 999px !important; + color: #1073cc !important; + background: #edf8ff !important; + font-size: 11px !important; + font-weight: 850 !important; +} + +.ecommerce-standalone .ecom-watermark-heading strong { + color: #172636 !important; + font-size: 22px !important; + font-weight: 950 !important; + letter-spacing: 0 !important; +} + +.ecommerce-standalone .ecom-watermark-heading p { + max-width: 280px !important; + margin: 0 !important; + color: #66798a !important; + font-size: 12px !important; + font-weight: 750 !important; + line-height: 1.7 !important; +} + +.ecommerce-standalone .ecom-watermark-panel { + display: grid !important; + gap: 10px !important; + padding: 12px !important; + border: 1px solid rgba(16, 115, 204, 0.1) !important; + border-radius: 12px !important; + background: rgba(248, 252, 255, 0.6) !important; + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.75) !important; +} + +.ecommerce-standalone .ecom-watermark-panel header { + display: flex !important; + align-items: center !important; + justify-content: space-between !important; +} + +.ecommerce-standalone .ecom-watermark-panel strong, +.ecommerce-standalone .ecom-watermark-upload-card strong { + color: #132435 !important; + font-size: 13px !important; + font-weight: 950 !important; +} + +.ecommerce-standalone .ecom-watermark-panel header span { + padding: 3px 9px !important; + border-radius: 999px !important; + color: #1073cc !important; + background: #edf8ff !important; + font-size: 11px !important; + font-weight: 850 !important; +} + +.ecommerce-standalone .ecom-watermark-upload-card { + position: relative !important; + display: grid !important; + grid-template-columns: 68px minmax(0, 1fr) !important; + align-items: center !important; + gap: 12px !important; + min-height: 92px !important; + padding: 10px 12px !important; + border: 1px dashed rgba(30, 189, 219, 0.45) !important; + border-radius: 12px !important; + color: #607485 !important; + background: #fbfdff !important; + cursor: pointer !important; + transition: border-color 180ms ease, background 180ms ease, box-shadow 180ms ease !important; +} + +.ecommerce-standalone .ecom-watermark-remove { + position: absolute !important; + top: 8px !important; + right: 8px !important; + z-index: 2 !important; + display: inline-grid !important; + place-items: center !important; + width: 24px !important; + height: 24px !important; + border: 1px solid rgba(16, 115, 204, 0.14) !important; + border-radius: 50% !important; + color: #526474 !important; + background: rgba(255, 255, 255, 0.92) !important; + box-shadow: 0 6px 14px rgba(16, 115, 204, 0.12) !important; + font-size: 16px !important; + font-weight: 850 !important; + line-height: 1 !important; + cursor: pointer !important; + transition: color 160ms ease, border-color 160ms ease, background 160ms ease, transform 160ms ease !important; +} + +.ecommerce-standalone .ecom-watermark-remove:hover { + border-color: rgba(16, 115, 204, 0.38) !important; + color: #1073cc !important; + background: #edf8ff !important; + transform: scale(1.04) !important; +} + +.ecommerce-standalone .ecom-watermark-upload-card:not(.has-image) { + grid-template-columns: 1fr !important; + justify-items: center !important; + text-align: center !important; +} + +.ecommerce-standalone .ecom-watermark-upload-card.is-dragging, +.ecommerce-standalone .ecom-watermark-upload-card:hover { + border-color: #1ebddb !important; + background: #f6fcff !important; + box-shadow: 0 12px 28px rgba(16, 115, 204, 0.12) !important; +} + +.ecommerce-standalone .ecom-watermark-upload-card > .anticon { + color: #1ebddb !important; + font-size: 30px !important; +} + +.ecommerce-standalone .ecom-watermark-upload-card figure { + width: 68px !important; + height: 68px !important; + margin: 0 !important; + overflow: hidden !important; + border: 1px solid rgba(16, 115, 204, 0.12) !important; + border-radius: 10px !important; + background: #f8f9fa !important; +} + +.ecommerce-standalone .ecom-watermark-upload-card img { + width: 100% !important; + height: 100% !important; + object-fit: cover !important; +} + +.ecommerce-standalone .ecom-watermark-upload-card div { + display: grid !important; + gap: 10px !important; + min-width: 0 !important; +} + +.ecommerce-standalone .ecom-watermark-upload-card span, +.ecommerce-standalone .ecom-watermark-panel p { + margin: 0 !important; + color: #627485 !important; + font-size: 12px !important; + font-weight: 750 !important; + line-height: 1.65 !important; +} + +.ecommerce-standalone .ecom-watermark-upload-card div strong { + overflow: hidden !important; + text-overflow: ellipsis !important; + white-space: nowrap !important; +} + +.ecommerce-standalone .ecom-watermark-url-row { + display: grid !important; + grid-template-columns: minmax(0, 1fr) 58px !important; + gap: 8px !important; +} + +.ecommerce-standalone .ecom-watermark-url-row input { + min-height: 36px !important; + padding: 0 12px !important; + border: 1px solid rgba(16, 115, 204, 0.12) !important; + border-radius: 9px !important; + color: #172636 !important; + background: #f8fafc !important; + outline: none !important; + font-size: 12px !important; + font-weight: 800 !important; +} + +.ecommerce-standalone .ecom-watermark-url-row button { + min-height: 36px !important; + padding: 0 12px !important; + font-size: 12px !important; +} + +.ecommerce-standalone .ecom-watermark-primary { + display: inline-flex !important; + align-items: center !important; + justify-content: center !important; + gap: 9px !important; + min-height: 44px !important; + width: 100% !important; + margin-top: auto !important; + border: 0 !important; + border-radius: 12px !important; + color: #ffffff !important; + background: linear-gradient(135deg, #1073cc, #1ebddb) !important; + box-shadow: 0 12px 28px rgba(16, 115, 204, 0.2) !important; + font-size: 14px !important; + font-weight: 950 !important; + cursor: pointer !important; + transition: box-shadow 180ms ease, transform 180ms ease !important; +} + +.ecommerce-standalone .ecom-watermark-primary:hover:not(:disabled) { + box-shadow: 0 16px 36px rgba(16, 115, 204, 0.28) !important; + transform: translateY(-1px) !important; +} + +.ecommerce-standalone .ecom-watermark-primary:disabled { + color: #8ea0ad !important; + background: #edf1f4 !important; + box-shadow: none !important; +} + +.ecommerce-standalone .ecom-watermark-workspace { + display: grid !important; + place-items: stretch !important; + min-width: 0 !important; + min-height: 0 !important; + height: 100% !important; + padding: 0 !important; + overflow: hidden !important; + border: none !important; + border-radius: 0 !important; + background: #f8f9fa !important; + box-shadow: none !important; +} + +.ecommerce-standalone .ecom-watermark-dropzone { + display: grid !important; + place-items: center !important; + align-content: center !important; + gap: 12px !important; + width: 100% !important; + height: 100% !important; + min-height: 0 !important; + border: 1px dashed rgba(30, 189, 219, 0.42) !important; + border-radius: 0 !important; + color: #657686 !important; + background: #fbfdff !important; + text-align: center !important; + cursor: pointer !important; + transition: border-color 180ms ease, background 180ms ease, color 180ms ease !important; +} + +.ecommerce-standalone .ecom-watermark-dropzone:hover, +.ecommerce-standalone .ecom-watermark-dropzone.is-dragging { + border-color: rgba(30, 189, 219, 0.72) !important; + color: #1073cc !important; + background: #f6fcff !important; +} + +.ecommerce-standalone .ecom-watermark-dropzone .anticon { + display: inline-grid !important; + place-items: center !important; + width: 50px !important; + height: 50px !important; + border-radius: 14px !important; + color: #1073cc !important; + background: #edf8ff !important; + font-size: 24px !important; +} + +.ecommerce-standalone .ecom-watermark-dropzone strong { + color: #172636 !important; + font-size: 15px !important; + font-weight: 950 !important; +} + +.ecommerce-standalone .ecom-watermark-dropzone span { + max-width: 360px !important; + color: #71818e !important; + font-size: 12px !important; + font-weight: 750 !important; + line-height: 1.6 !important; +} + +.ecommerce-standalone .ecom-watermark-grid { + display: grid !important; + grid-template-columns: repeat(2, minmax(0, 1fr)) !important; + gap: 0 !important; + width: 100% !important; + height: 100% !important; + overflow: hidden !important; + border: 1px solid rgba(16, 115, 204, 0.1) !important; + border-radius: 0 !important; + background: #ffffff !important; + box-shadow: none !important; +} + +.ecommerce-standalone .ecom-watermark-preview-card { + position: relative !important; + display: grid !important; + grid-template-rows: minmax(0, 1fr) auto !important; + align-items: center !important; + justify-items: center !important; + min-width: 0 !important; + min-height: 0 !important; + padding: 24px !important; + overflow: hidden !important; + border: 0 !important; + border-radius: 0 !important; + background: #ffffff !important; + box-shadow: none !important; +} + +.ecommerce-standalone .ecom-watermark-preview-card:first-child { + border-right: 1px solid rgba(16, 115, 204, 0.1) !important; +} + +.ecommerce-standalone .ecom-watermark-preview-card > span { + position: absolute !important; + top: 14px !important; + left: 14px !important; + z-index: 2 !important; + padding: 4px 10px !important; + border-radius: 999px !important; + color: #1073cc !important; + background: #edf8ff !important; + font-size: 12px !important; + font-weight: 950 !important; +} + +.ecommerce-standalone .ecom-watermark-preview-card > img { + display: block !important; + max-width: 100% !important; + max-height: 70vh !important; + object-fit: contain !important; + border-radius: 10px !important; + box-shadow: 0 12px 30px rgba(16, 115, 204, 0.1) !important; +} + +.ecommerce-standalone .ecom-watermark-preview-card .ecom-image-workbench-image-frame { + position: relative !important; + display: block !important; + width: fit-content !important; + max-width: 100% !important; + max-height: 70vh !important; + overflow: hidden !important; + border-radius: 10px !important; + box-shadow: 0 12px 30px rgba(16, 115, 204, 0.1) !important; + cursor: crosshair !important; + touch-action: none !important; + user-select: none !important; + line-height: 0 !important; +} + +.ecommerce-standalone .ecom-watermark-preview-card .ecom-image-workbench-image-frame img { + display: block !important; + max-width: 100% !important; + max-height: 70vh !important; + object-fit: contain !important; + border-radius: 10px !important; + user-select: none !important; + pointer-events: none !important; + -webkit-user-drag: none !important; +} + +.ecommerce-standalone .ecom-watermark-preview-card .ecom-image-workbench-mask-layer { + position: absolute !important; + inset: 0 !important; + z-index: 3 !important; + width: 100% !important; + height: 100% !important; + overflow: hidden !important; + border-radius: 10px !important; + pointer-events: none !important; +} + +.ecommerce-standalone .ecom-watermark-preview-card .ecom-image-workbench-brush { + position: absolute !important; + z-index: 4 !important; + border: 2px solid rgba(30, 189, 219, 0.72) !important; + border-radius: 50% !important; + background: rgba(30, 189, 219, 0.16) !important; + box-shadow: 0 0 0 6px rgba(30, 189, 219, 0.08) !important; + transform: translate(-50%, -50%) !important; + pointer-events: none !important; +} + +.ecommerce-standalone .ecom-watermark-empty, +.ecommerce-standalone .ecom-watermark-processing { + display: grid !important; + place-items: center !important; + gap: 10px !important; + width: min(360px, 80%) !important; + min-height: 190px !important; + padding: 24px !important; + border: 1px dashed rgba(16, 115, 204, 0.16) !important; + border-radius: 16px !important; + color: #6b7e8d !important; + background: #fbfdff !important; + text-align: center !important; +} + +.ecommerce-standalone .ecom-watermark-empty .anticon, +.ecommerce-standalone .ecom-watermark-processing .anticon { + color: #1ebddb !important; + font-size: 30px !important; +} + +.ecommerce-standalone .ecom-watermark-empty strong, +.ecommerce-standalone .ecom-watermark-processing strong { + color: #172636 !important; + font-size: 16px !important; + font-weight: 950 !important; +} + +.ecommerce-standalone .ecom-watermark-empty em, +.ecommerce-standalone .ecom-watermark-processing em { + color: #71818e !important; + font-size: 12px !important; + font-style: normal !important; + font-weight: 750 !important; +} + +.ecommerce-standalone .ecom-watermark-zoom { + position: absolute !important; + top: 14px !important; + right: 14px !important; + display: inline-grid !important; + place-items: center !important; + width: 34px !important; + height: 34px !important; + border: 0 !important; + border-radius: 50% !important; + color: #1073cc !important; + background: #edf8ff !important; + font-size: 17px !important; +} + +.ecommerce-standalone .ecom-watermark-actions { + display: flex !important; + justify-content: center !important; + gap: 14px !important; + width: 100% !important; + padding-top: 16px !important; +} + +.ecommerce-standalone .ecom-watermark-actions button { + min-width: 138px !important; + min-height: 44px !important; + padding: 0 18px !important; + color: #172636 !important; + font-size: 13px !important; +} + +.ecommerce-standalone .ecom-watermark-actions button:disabled { + opacity: 0.45 !important; + cursor: not-allowed !important; + transform: none !important; +} + +.ecommerce-standalone .ecom-translate-lang-panel header { + margin-bottom: 8px !important; +} + +.ecommerce-standalone .ecom-translate-lang-select { + display: block !important; + width: 100% !important; + height: 38px !important; + padding: 0 12px !important; + border: 1px solid #e0e6ed !important; + border-radius: 10px !important; + color: #172636 !important; + background: #ffffff !important; + font-size: 13px !important; + font-weight: 600 !important; + font-family: inherit !important; + cursor: pointer !important; + transition: border-color 180ms ease, box-shadow 180ms ease !important; + appearance: none !important; + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath d='M3 5l3 3 3-3' fill='none' stroke='%23596775' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") !important; + background-repeat: no-repeat !important; + background-position: right 12px center !important; +} + +.ecommerce-standalone .ecom-translate-lang-select:focus { + border-color: #1073cc !important; + box-shadow: 0 0 0 3px rgba(16, 115, 204, 0.1) !important; + outline: none !important; +} + +.ecommerce-standalone .ecom-translate-lang-select:hover { + border-color: #1073cc !important; +} + +.ecommerce-standalone .ecom-quick-set-page { + position: relative !important; + display: grid !important; + grid-template-rows: 42px minmax(0, 1fr) !important; + width: 100% !important; + height: 100% !important; + min-height: 720px !important; + color: #111827 !important; + background: #f3f5f8 !important; + font-family: "PingFang SC", "Microsoft YaHei", sans-serif !important; +} + +.ecommerce-standalone .ecom-quick-set-topbar { + display: flex !important; + align-items: center !important; + justify-content: space-between !important; + gap: 18px !important; + padding: 0 16px !important; + border-bottom: 1px solid rgba(15, 23, 42, 0.06) !important; + background: rgba(255, 255, 255, 0.92) !important; +} + +.ecommerce-standalone .ecom-quick-set-brand, +.ecommerce-standalone .ecom-quick-set-actions { + display: flex !important; + align-items: center !important; + gap: 8px !important; +} + +.ecommerce-standalone .ecom-quick-set-brand > span { + display: inline-grid !important; + place-items: center !important; + width: 22px !important; + height: 22px !important; + border-radius: 7px !important; + color: #ffffff !important; + background: linear-gradient(135deg, #ff3366, #1ebddb 55%, #111827) !important; + font-size: 13px !important; +} + +.ecommerce-standalone .ecom-quick-set-brand strong { + font-size: 14px !important; + font-weight: 900 !important; +} + +.ecommerce-standalone .ecom-quick-set-brand button, +.ecommerce-standalone .ecom-quick-set-actions button, +.ecommerce-standalone .ecom-quick-set-actions span { + min-height: 26px !important; + padding: 0 10px !important; + border: 0 !important; + border-radius: 7px !important; + color: #26323f !important; + background: #f4f6f8 !important; + font-size: 12px !important; + font-weight: 800 !important; +} + +.ecommerce-standalone .ecom-quick-set-actions button:first-child { + color: #9a5623 !important; + background: #ffe0c7 !important; +} + +.ecommerce-standalone .ecom-quick-set-actions i { + width: 26px !important; + height: 26px !important; + border-radius: 50% !important; + background: #d7dde4 !important; +} + +.ecommerce-standalone .ecom-quick-set-body { + display: grid !important; + grid-template-columns: 54px 322px minmax(0, 1fr) !important; + min-height: 0 !important; +} + +.ecommerce-standalone .ecom-quick-set-rail { + display: grid !important; + align-content: start !important; + gap: 16px !important; + padding: 14px 8px !important; + border-right: 1px solid rgba(15, 23, 42, 0.06) !important; + background: #ffffff !important; +} + +.ecommerce-standalone .ecom-quick-set-rail button { + display: grid !important; + justify-items: center !important; + gap: 5px !important; + min-height: 48px !important; + border: 0 !important; + border-radius: 9px !important; + color: #2c3642 !important; + background: transparent !important; + font-size: 11px !important; + font-weight: 800 !important; +} + +.ecommerce-standalone .ecom-quick-set-rail button.is-active { + color: #1073cc !important; + background: #eef8ff !important; +} + +.ecommerce-standalone .ecom-quick-set-panel { + position: relative !important; + display: grid !important; + grid-template-rows: auto auto auto auto auto minmax(0, 1fr) !important; + gap: 14px !important; + padding: 18px 16px 70px !important; + border-right: 1px solid rgba(15, 23, 42, 0.06) !important; + background: #ffffff !important; + overflow-y: auto !important; +} + +.ecommerce-standalone .ecom-quick-set-panel section { + display: grid !important; + gap: 10px !important; +} + +.ecommerce-standalone .ecom-quick-set-panel strong, +.ecommerce-standalone .ecom-quick-set-section-head strong { + font-size: 13px !important; + font-weight: 900 !important; +} + +.ecommerce-standalone .ecom-quick-set-upload { + display: grid !important; + place-items: center !important; + gap: 8px !important; + min-height: 84px !important; + border: 1px dashed rgba(16, 115, 204, 0.22) !important; + border-radius: 10px !important; + color: #5f6f7c !important; + background: #fbfdff !important; +} + +.ecommerce-standalone .ecom-quick-set-upload span { + padding: 7px 14px !important; + border-radius: 8px !important; + color: #344250 !important; + background: #f3f5f8 !important; + font-size: 13px !important; + font-weight: 900 !important; +} + +.ecommerce-standalone .ecom-quick-set-upload em { + color: #a0a9b2 !important; + font-style: normal !important; + font-size: 12px !important; + font-weight: 700 !important; +} + +.ecommerce-standalone .ecom-quick-set-selects { + display: grid !important; + grid-template-columns: 1fr 1fr !important; + gap: 8px !important; +} + +.ecommerce-standalone .ecom-quick-set-selects button { + display: flex !important; + align-items: center !important; + justify-content: space-between !important; + min-height: 34px !important; + padding: 0 10px !important; + border: 0 !important; + border-radius: 8px !important; + background: #f3f5f8 !important; + font-size: 13px !important; + font-weight: 800 !important; +} + +.ecommerce-standalone .ecom-quick-set-section-head { + display: flex !important; + align-items: center !important; + justify-content: space-between !important; + gap: 10px !important; +} + +.ecommerce-standalone .ecom-quick-set-section-head button { + min-height: 26px !important; + padding: 0 10px !important; + border: 1px solid rgba(16, 115, 204, 0.12) !important; + border-radius: 999px !important; + color: #3386ef !important; + background: #f6fbff !important; + font-size: 12px !important; + font-weight: 900 !important; +} + +.ecommerce-standalone .ecom-quick-set-panel textarea { + min-height: 102px !important; + resize: none !important; + padding: 12px !important; + border: 1px solid rgba(15, 23, 42, 0.08) !important; + border-radius: 10px !important; + color: #253443 !important; + background: #ffffff !important; + font-size: 12px !important; + font-weight: 700 !important; + line-height: 1.65 !important; + outline: none !important; +} + +.ecommerce-standalone .ecom-quick-set-config { + display: grid !important; + gap: 8px !important; +} + +.ecommerce-standalone .ecom-quick-set-config button { + display: grid !important; + grid-template-columns: minmax(0, 1fr) 18px !important; + gap: 4px 10px !important; + min-height: 58px !important; + padding: 12px !important; + border: 1px solid rgba(15, 23, 42, 0.08) !important; + border-radius: 10px !important; + color: #253443 !important; + background: #ffffff !important; + text-align: left !important; +} + +.ecommerce-standalone .ecom-quick-set-config button::after { + grid-row: 1 / span 2 !important; + grid-column: 2 !important; + align-self: center !important; + width: 14px !important; + height: 14px !important; + border: 1px solid #c9d3dc !important; + border-radius: 4px !important; + content: "" !important; +} + +.ecommerce-standalone .ecom-quick-set-config button.is-active::after { + border-color: #3386ef !important; + background: #3386ef !important; + box-shadow: inset 0 0 0 3px #ffffff !important; +} + +.ecommerce-standalone .ecom-quick-set-config button strong, +.ecommerce-standalone .ecom-quick-set-config button span { + grid-column: 1 !important; +} + +.ecommerce-standalone .ecom-quick-set-config button span { + color: #909aa5 !important; + font-size: 12px !important; + font-weight: 700 !important; +} + +.ecommerce-standalone .ecom-quick-set-analysis { + min-height: 34px !important; + border: 0 !important; + border-radius: 8px !important; + color: #7aa9f8 !important; + background: #f3f5f8 !important; + font-weight: 900 !important; +} + +.ecommerce-standalone .ecom-quick-set-panel footer { + position: absolute !important; + left: 16px !important; + right: 16px !important; + bottom: 16px !important; +} + +.ecommerce-standalone .ecom-quick-set-panel footer button { + width: 100% !important; + min-height: 38px !important; + border: 0 !important; + border-radius: 8px !important; + color: #ffffff !important; + background: #b8b8b8 !important; + font-size: 13px !important; + font-weight: 900 !important; +} + +.ecommerce-standalone .ecom-quick-set-stage { + display: grid !important; + place-items: center !important; + padding: 42px 48px !important; + overflow: auto !important; +} + +.ecommerce-standalone .ecom-quick-set-hero { + display: grid !important; + justify-items: center !important; + gap: 22px !important; + width: min(720px, 100%) !important; +} + +.ecommerce-standalone .ecom-quick-set-hero h1 { + margin: 0 !important; + font-size: 30px !important; + font-weight: 950 !important; + letter-spacing: 0 !important; +} + +.ecommerce-standalone .ecom-quick-set-hero p { + margin: -8px 0 16px !important; + color: #6b7684 !important; + font-size: 14px !important; + font-weight: 700 !important; +} + +.ecommerce-standalone .ecom-quick-set-hero p span { + color: #3386ef !important; +} + +.ecommerce-standalone .ecom-quick-set-preview-card { + display: grid !important; + grid-template-columns: 1.2fr 40px 1fr !important; + align-items: center !important; + gap: 18px !important; + width: 100% !important; + min-height: 300px !important; + padding: 22px !important; + border-radius: 18px !important; + background: #ffffff !important; + box-shadow: 0 20px 60px rgba(23, 31, 44, 0.08) !important; +} + +.ecommerce-standalone .ecom-quick-set-preview-card figure { + position: relative !important; + margin: 0 !important; + overflow: hidden !important; + border-radius: 12px !important; + background: #f3f5f8 !important; +} + +.ecommerce-standalone .ecom-quick-set-preview-card figure span { + position: absolute !important; + top: 9px !important; + left: 10px !important; + z-index: 1 !important; + padding: 4px 9px !important; + border-radius: 999px !important; + color: #536171 !important; + background: rgba(255, 255, 255, 0.86) !important; + font-size: 11px !important; + font-weight: 900 !important; +} + +.ecommerce-standalone .ecom-quick-set-preview-card img { + display: block !important; + width: 100% !important; + height: 100% !important; + object-fit: cover !important; +} + +.ecommerce-standalone .ecom-quick-set-preview-main { + height: 250px !important; +} + +.ecommerce-standalone .ecom-quick-set-preview-arrow { + display: grid !important; + place-items: center !important; + width: 40px !important; + height: 40px !important; + border-radius: 50% !important; + color: #c8d1db !important; + font-size: 42px !important; + font-weight: 700 !important; +} + +.ecommerce-standalone .ecom-quick-set-preview-grid { + display: grid !important; + grid-template-columns: 1fr 1fr !important; + gap: 10px !important; +} + +.ecommerce-standalone .ecom-quick-set-preview-grid figure { + height: 120px !important; +} + +.ecommerce-standalone .ecom-quick-set-help { + position: absolute !important; + right: 18px !important; + bottom: 18px !important; + width: 38px !important; + height: 38px !important; + border: 1px solid rgba(15, 23, 42, 0.08) !important; + border-radius: 50% !important; + color: #6b7280 !important; + background: #ffffff !important; + box-shadow: 0 8px 22px rgba(15, 23, 42, 0.08) !important; + font-size: 20px !important; + font-weight: 900 !important; +} + +/* Localized product set workbench layout. */ +.ecommerce-standalone .ecom-quick-set-page { + grid-template-rows: minmax(0, 1fr) !important; + min-height: 100% !important; + color: #172636 !important; + background: #f8f9fa !important; +} + +.ecommerce-standalone .ecom-quick-set-body { + grid-template-columns: 440px minmax(0, 1fr) !important; + min-height: 0 !important; + transition: grid-template-columns 680ms cubic-bezier(0.22, 1, 0.36, 1) !important; +} + +.ecommerce-standalone .ecom-quick-set-page.is-panel-collapsed .ecom-quick-set-body { + grid-template-columns: 0 minmax(0, 1fr) !important; +} + +.ecommerce-standalone .ecom-quick-set-panel { + display: flex !important; + flex-direction: column !important; + gap: 14px !important; + padding: 16px 14px 86px !important; + border-right: 1px solid rgba(16, 115, 204, 0.08) !important; + background: #feffff !important; + box-shadow: 18px 0 46px rgba(16, 115, 204, 0.04) !important; + overflow-y: auto !important; + scrollbar-width: none !important; + -ms-overflow-style: none !important; + transform: translateX(0) !important; + opacity: 1 !important; + clip-path: inset(0 0 0 0 round 0) !important; + will-change: transform, opacity, clip-path !important; + transition: + transform 680ms cubic-bezier(0.22, 1, 0.36, 1), + opacity 360ms ease, + clip-path 680ms cubic-bezier(0.22, 1, 0.36, 1), + box-shadow 460ms ease, + border-color 460ms ease !important; +} + +.ecommerce-standalone .ecom-quick-set-panel > * { + transform: translateX(0) !important; + opacity: 1 !important; + transition: + transform 520ms cubic-bezier(0.22, 1, 0.36, 1), + opacity 300ms ease !important; +} + +.ecommerce-standalone .ecom-quick-set-page.is-panel-collapsed .ecom-quick-set-panel { + pointer-events: none !important; + opacity: 0 !important; + transform: translateX(-26px) scaleX(0.96) !important; + clip-path: inset(0 100% 0 0 round 0) !important; + box-shadow: none !important; + border-color: transparent !important; +} + +.ecommerce-standalone .ecom-quick-set-page.is-panel-collapsed .ecom-quick-set-panel > * { + transform: translateX(-18px) !important; + opacity: 0 !important; +} + +.ecommerce-standalone .ecom-quick-set-panel::-webkit-scrollbar { + width: 0 !important; + height: 0 !important; + display: none !important; +} + +.ecommerce-standalone .ecom-quick-set-panel-head { + display: flex !important; + align-items: center !important; + gap: 10px !important; + min-height: 34px !important; +} + +.ecommerce-standalone .ecom-quick-set-back { + display: inline-flex !important; + align-items: center !important; + justify-content: center !important; + min-width: 70px !important; + min-height: 32px !important; + padding: 0 13px !important; + border: 1px solid rgba(16, 115, 204, 0.14) !important; + border-radius: 11px !important; + color: #1073cc !important; + background: #ffffff !important; + box-shadow: 0 8px 18px rgba(16, 115, 204, 0.08) !important; + font-size: 13px !important; + font-weight: 700 !important; + white-space: nowrap !important; + cursor: pointer !important; + transition: color 180ms ease, background 180ms ease, box-shadow 180ms ease !important; +} + +.ecommerce-standalone .ecom-quick-set-back:hover { + color: #ffffff !important; + background: #1073cc !important; + box-shadow: 0 8px 18px rgba(16, 115, 204, 0.18) !important; +} + +.ecommerce-standalone .ecom-quick-set-panel-head span { + display: inline-grid !important; + place-items: center !important; + width: 25px !important; + height: 25px !important; + border-radius: 8px !important; + color: #ffffff !important; + background: linear-gradient(135deg, #1073cc, #1ebddb) !important; + font-size: 12px !important; + font-weight: 950 !important; +} + +.ecommerce-standalone .ecom-quick-set-page-title { + margin-right: auto !important; + color: #10202c !important; + font-size: 17px !important; + font-weight: 950 !important; + letter-spacing: 0.02em !important; +} + +.ecommerce-standalone .ecom-quick-set-panel-head strong { + color: #132435 !important; + font-size: 15px !important; + font-weight: 950 !important; +} + +.ecommerce-standalone .ecom-quick-set-panel section { + position: relative !important; + gap: 9px !important; + padding: 12px !important; + border: 1px solid rgba(16, 115, 204, 0.09) !important; + border-radius: 12px !important; + background: #ffffff !important; + box-shadow: 0 10px 26px rgba(16, 115, 204, 0.035) !important; +} + +.ecommerce-standalone .ecom-quick-set-panel section > strong { + display: inline-flex !important; + align-items: center !important; + gap: 7px !important; + color: #172636 !important; + font-size: 13px !important; + font-weight: 950 !important; +} + +.ecommerce-standalone .ecom-quick-set-basic-section { + z-index: 12 !important; + overflow: visible !important; +} + +.ecommerce-standalone .ecom-quick-set-select-anchor { + position: relative !important; + z-index: 12 !important; + overflow: visible !important; +} + +.ecommerce-standalone .ecom-quick-set-upload { + display: grid !important; + place-items: center !important; + gap: 10px !important; + min-height: 126px !important; + padding: 18px 14px !important; + border: 1px dashed rgba(30, 189, 219, 0.42) !important; + border-radius: 0 !important; + color: #172636 !important; + background: #ffffff !important; + outline: none !important; + cursor: pointer !important; + box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.02) !important; + transition: border-color 180ms ease, box-shadow 180ms ease, background 180ms ease !important; +} + +.ecommerce-standalone .ecom-quick-set-upload.has-images { + min-height: 158px !important; + padding: 14px !important; +} + +.ecommerce-standalone .ecom-quick-set-upload:hover, +.ecommerce-standalone .ecom-quick-set-upload:focus-visible { + border-color: rgba(30, 189, 219, 0.76) !important; + background: #ffffff !important; + box-shadow: 0 0 0 3px rgba(30, 189, 219, 0.1), 0 14px 34px rgba(16, 115, 204, 0.12) !important; +} + +.ecommerce-standalone .ecom-quick-set-upload > .anticon { + color: #1ebddb !important; + font-size: 24px !important; +} + +.ecommerce-standalone .ecom-quick-set-upload > span { + color: #253544 !important; + background: transparent !important; + font-size: 15px !important; + font-weight: 950 !important; +} + +.ecommerce-standalone .ecom-quick-set-upload b { + display: inline-flex !important; + align-items: center !important; + justify-content: center !important; + min-height: 46px !important; + padding: 0 34px !important; + border-radius: 12px !important; + color: #ffffff !important; + background: linear-gradient(135deg, #1073cc, #1ebddb) !important; + box-shadow: 0 18px 42px rgba(16, 115, 204, 0.22) !important; + font-size: 16px !important; + font-weight: 950 !important; +} + +.ecommerce-standalone .ecom-quick-set-upload em { + color: #71818e !important; + font-size: 13px !important; + font-style: normal !important; + font-weight: 850 !important; +} + +.ecommerce-standalone .ecom-quick-upload-thumbs { + position: relative !important; + display: flex !important; + flex-wrap: wrap !important; + justify-content: center !important; + gap: 8px !important; + width: 100% !important; + max-width: 100% !important; +} + +.ecommerce-standalone .ecom-quick-upload-thumbs figure { + position: relative !important; + width: 48px !important; + height: 48px !important; + margin: 0 !important; + overflow: visible !important; + border: 1px solid rgba(16, 115, 204, 0.14) !important; + border-radius: 10px !important; + background: #f8f9fa !important; + box-shadow: 0 8px 18px rgba(16, 115, 204, 0.08) !important; +} + +.ecommerce-standalone .ecom-quick-upload-thumbs figure > img { + width: 100% !important; + height: 100% !important; + display: block !important; + object-fit: cover !important; + border-radius: 9px !important; +} + +.ecommerce-standalone .ecom-quick-upload-thumbs button { + position: absolute !important; + top: -7px !important; + right: -7px !important; + z-index: 4 !important; + width: 18px !important; + height: 18px !important; + display: inline-flex !important; + align-items: center !important; + justify-content: center !important; + padding: 0 !important; + border: 1px solid rgba(16, 115, 204, 0.12) !important; + border-radius: 999px !important; + color: #344250 !important; + background: #ffffff !important; + box-shadow: 0 8px 18px rgba(15, 23, 42, 0.16) !important; + font-size: 13px !important; + font-weight: 950 !important; + line-height: 1 !important; + cursor: pointer !important; +} + +.ecommerce-standalone .ecom-quick-upload-zoom { + position: absolute !important; + left: calc(100% + 12px) !important; + top: 50% !important; + z-index: 80 !important; + width: 184px !important; + height: 184px !important; + display: block !important; + padding: 0 !important; + overflow: hidden !important; + border: 1px solid rgba(16, 115, 204, 0.16) !important; + border-radius: 14px !important; + background: #ffffff !important; + box-shadow: 0 22px 54px rgba(15, 23, 42, 0.22) !important; + opacity: 0 !important; + pointer-events: none !important; + transform: translate3d(8px, -50%, 0) scale(0.94) !important; + transition: opacity 180ms ease, transform 180ms ease !important; +} + +.ecommerce-standalone .ecom-quick-upload-zoom img { + width: 100% !important; + height: 100% !important; + display: block !important; + object-fit: contain !important; + background: #ffffff !important; +} + +.ecommerce-standalone .ecom-quick-upload-thumbs figure:hover .ecom-quick-upload-zoom { + opacity: 1 !important; + transform: translate3d(0, -50%, 0) scale(1) !important; +} + +.ecommerce-standalone .ecom-quick-upload-thumbs .ecom-command-asset-zoom { + position: absolute !important; + top: 50% !important; + left: calc(100% + 12px) !important; + z-index: 90 !important; + display: none !important; + width: min(320px, calc(100vw - 48px)) !important; + height: auto !important; + padding: 8px !important; + overflow: visible !important; + border: 1px solid rgba(30, 189, 219, 0.28) !important; + border-radius: 10px !important; + background: #feffff !important; + box-shadow: 0 18px 46px rgba(20, 80, 100, 0.18) !important; + opacity: 1 !important; + pointer-events: none !important; + transform: translateY(-50%) !important; +} + +.ecommerce-standalone .ecom-quick-upload-thumbs .ecom-command-asset-thumb:hover .ecom-command-asset-zoom, +.ecommerce-standalone .ecom-quick-upload-thumbs .ecom-command-asset-thumb:focus-within .ecom-command-asset-zoom { + display: block !important; + animation: ecom-zoom-preview-in 150ms ease-out both !important; +} + +.ecommerce-standalone .ecom-quick-upload-thumbs .ecom-command-asset-zoom img { + display: block !important; + width: 100% !important; + height: auto !important; + max-height: 360px !important; + border-radius: 6px !important; + object-fit: contain !important; + background: transparent !important; +} + +.ecommerce-standalone .ecom-quick-set-label { + color: #6c7b88 !important; + font-size: 12px !important; + font-weight: 850 !important; +} + +.ecommerce-standalone .ecom-quick-set-modes { + display: grid !important; + grid-template-columns: repeat(3, minmax(0, 1fr)) !important; + gap: 8px !important; +} + +.ecommerce-standalone .ecom-quick-set-modes button { + min-height: 33px !important; + border: 1px solid rgba(16, 115, 204, 0.12) !important; + border-radius: 9px !important; + color: #253544 !important; + background: #f8f9fa !important; + font-size: 13px !important; + font-weight: 900 !important; +} + +.ecommerce-standalone .ecom-quick-set-modes button.is-active { + border-color: #1073cc !important; + color: #1073cc !important; + background: #edf8ff !important; + box-shadow: 0 0 0 3px rgba(30, 189, 219, 0.12) !important; +} + +.ecommerce-standalone .ecom-quick-set-selects { + display: grid !important; + grid-template-columns: repeat(2, minmax(0, 1fr)) !important; + gap: 8px !important; +} + +.ecommerce-standalone .ecom-quick-set-selects button { + display: grid !important; + grid-template-columns: minmax(0, 1fr) 16px !important; + grid-template-rows: auto auto !important; + align-items: center !important; + justify-content: initial !important; + column-gap: 6px !important; + row-gap: 3px !important; + min-height: 58px !important; + padding: 9px 10px !important; + border: 1px solid rgba(16, 115, 204, 0.08) !important; + border-radius: 9px !important; + background: #f8f9fa !important; + text-align: left !important; +} + +.ecommerce-standalone .ecom-quick-set-selects button span { + display: block !important; + grid-column: 1 !important; + grid-row: 1 !important; + min-width: 0 !important; + color: #71818e !important; + font-size: 11px !important; + font-weight: 800 !important; + white-space: nowrap !important; +} + +.ecommerce-standalone .ecom-quick-set-selects button strong { + display: block !important; + grid-column: 1 !important; + grid-row: 2 !important; + min-width: 0 !important; + margin-top: 0 !important; + overflow: hidden !important; + color: #172636 !important; + font-size: 13px !important; + font-weight: 950 !important; + line-height: 1.25 !important; + text-overflow: ellipsis !important; + white-space: nowrap !important; +} + +.ecommerce-standalone .ecom-quick-set-selects button em { + align-self: center !important; + grid-column: 2 !important; + grid-row: 1 / 3 !important; + justify-self: end !important; + color: #82919e !important; + font-style: normal !important; + font-size: 12px !important; +} + +.ecommerce-standalone .ecom-quick-set-selects button.is-active { + border-color: rgba(16, 115, 204, 0.36) !important; + background: #edf8ff !important; + box-shadow: 0 0 0 3px rgba(30, 189, 219, 0.12) !important; +} + +.ecommerce-standalone .ecom-quick-set-dropdown { + position: absolute !important; + top: 66px !important; + left: 0 !important; + right: 0 !important; + z-index: 20 !important; + display: grid !important; + grid-template-columns: repeat(2, minmax(0, 1fr)) !important; + gap: 8px !important; + padding: 10px !important; + border: 1px solid rgba(16, 115, 204, 0.1) !important; + border-radius: 12px !important; + background: #feffff !important; + box-shadow: 0 16px 36px rgba(16, 115, 204, 0.12) !important; + transform-origin: top left !important; + will-change: opacity, transform, filter !important; + animation: ecomQuickDropdownIn 300ms cubic-bezier(0.16, 1, 0.3, 1) both !important; +} + +.ecommerce-standalone .ecom-quick-set-dropdown--language, +.ecommerce-standalone .ecom-quick-set-dropdown--ratio { + top: 132px !important; +} + +.ecommerce-standalone .ecom-quick-set-dropdown.is-closing { + pointer-events: none !important; + animation: ecomQuickDropdownOut 420ms cubic-bezier(0.4, 0, 0.2, 1) both !important; +} + +.ecommerce-standalone .ecom-quick-set-dropdown button { + min-height: 32px !important; + padding: 0 10px !important; + border: 1px solid rgba(16, 115, 204, 0.1) !important; + border-radius: 8px !important; + color: #273849 !important; + background: #f8f9fa !important; + font-size: 12px !important; + font-weight: 850 !important; +} + +.ecommerce-standalone .ecom-quick-set-dropdown button.is-active { + border-color: #1073cc !important; + color: #1073cc !important; + background: #edf8ff !important; + font-weight: 950 !important; +} + +.ecommerce-standalone .ecom-quick-detail-types { + display: grid !important; + grid-template-columns: repeat(2, minmax(0, 1fr)) !important; + gap: 8px !important; +} + +.ecommerce-standalone .ecom-quick-detail-types button { + min-height: 34px !important; + border: 1px solid rgba(16, 115, 204, 0.12) !important; + border-radius: 9px !important; + color: #253544 !important; + background: #f8f9fa !important; + font-size: 13px !important; + font-weight: 900 !important; +} + +.ecommerce-standalone .ecom-quick-detail-types button.is-active { + border-color: #1073cc !important; + color: #1073cc !important; + background: #edf8ff !important; + box-shadow: 0 0 0 3px rgba(30, 189, 219, 0.12) !important; +} + +.ecommerce-standalone .ecom-quick-detail-thumbs { + display: grid !important; + grid-template-columns: repeat(3, minmax(0, 1fr)) !important; + gap: 8px !important; +} + +.ecommerce-standalone .ecom-quick-detail-thumbs figure { + aspect-ratio: 1 / 1 !important; + margin: 0 !important; + overflow: hidden !important; + border: 1px solid rgba(16, 115, 204, 0.12) !important; + border-radius: 9px !important; + background: #f8f9fa !important; +} + +.ecommerce-standalone .ecom-quick-detail-thumbs img { + width: 100% !important; + height: 100% !important; + object-fit: cover !important; +} + +.ecommerce-standalone .ecom-quick-detail-modules { + display: grid !important; + grid-template-columns: repeat(2, minmax(0, 1fr)) !important; + gap: 8px !important; + max-height: 430px !important; + overflow-y: auto !important; + padding-right: 4px !important; + scrollbar-width: thin !important; + scrollbar-color: rgba(16, 115, 204, 0.34) transparent !important; +} + +.ecommerce-standalone .ecom-quick-detail-modules::-webkit-scrollbar { + width: 6px !important; +} + +.ecommerce-standalone .ecom-quick-detail-modules::-webkit-scrollbar-track { + background: transparent !important; +} + +.ecommerce-standalone .ecom-quick-detail-modules::-webkit-scrollbar-thumb { + border-radius: 999px !important; + background: rgba(16, 115, 204, 0.28) !important; +} + +.ecommerce-standalone .ecom-quick-detail-page .ecom-quick-set-panel { + overflow-y: auto !important; + padding-bottom: 16px !important; + scrollbar-width: auto !important; + scrollbar-color: rgba(16, 115, 204, 0.56) rgba(16, 115, 204, 0.08) !important; +} + +.ecommerce-standalone .ecom-quick-detail-page .ecom-quick-set-panel::-webkit-scrollbar { + display: block !important; + width: 14px !important; + height: 14px !important; +} + +.ecommerce-standalone .ecom-quick-detail-page .ecom-quick-set-panel::-webkit-scrollbar-track { + border-radius: 999px !important; + background: rgba(16, 115, 204, 0.08) !important; +} + +.ecommerce-standalone .ecom-quick-detail-page .ecom-quick-set-panel::-webkit-scrollbar-thumb { + border: 3px solid rgba(248, 249, 250, 0.95) !important; + border-radius: 999px !important; + background: rgba(16, 115, 204, 0.56) !important; +} + +.ecommerce-standalone .ecom-quick-detail-page .ecom-quick-set-panel::-webkit-scrollbar-thumb:hover { + background: rgba(16, 115, 204, 0.72) !important; +} + +.ecommerce-standalone .ecom-quick-detail-page .ecom-quick-detail-modules { + max-height: none !important; + overflow: visible !important; + padding-right: 0 !important; + scrollbar-width: auto !important; +} + +.ecommerce-standalone .ecom-quick-detail-modules button { + display: grid !important; + gap: 4px !important; + min-height: 58px !important; + padding: 9px 10px !important; + border: 1px solid rgba(16, 115, 204, 0.1) !important; + border-radius: 10px !important; + color: #172636 !important; + background: #f8f9fa !important; + text-align: left !important; +} + +.ecommerce-standalone .ecom-quick-detail-modules button.is-active { + border-color: rgba(16, 115, 204, 0.48) !important; + background: #edf8ff !important; + box-shadow: inset 0 0 0 1px rgba(30, 189, 219, 0.08), 0 8px 18px rgba(16, 115, 204, 0.08) !important; +} + +.ecommerce-standalone .ecom-quick-detail-modules strong { + color: #172636 !important; + font-size: 13px !important; + font-weight: 950 !important; +} + +.ecommerce-standalone .ecom-quick-detail-modules span { + color: #738392 !important; + font-size: 11px !important; + font-weight: 750 !important; +} + +@keyframes ecomPopoverIn { + from { + opacity: 0; + transform: translateY(-6px) scale(0.98); + } + to { + opacity: 1; + transform: translateY(0) scale(1); + } +} + +@keyframes ecomQuickDropdownIn { + from { + opacity: 0; + filter: blur(5px); + transform: translateY(-8px) scale(0.96); + } + 60% { + opacity: 1; + filter: blur(0); + transform: translateY(2px) scale(1.01); + } + to { + opacity: 1; + filter: blur(0); + transform: translateY(0) scale(1); + } +} + +@keyframes ecomQuickDropdownOut { + from { + opacity: 1; + filter: blur(0); + transform: translateY(0) scale(1); + } + to { + opacity: 0; + filter: blur(4px); + transform: translateY(-8px) scale(0.96); + } +} + +.ecommerce-standalone .ecom-quick-set-counts { + display: grid !important; + gap: 9px !important; +} + +.ecommerce-standalone .ecom-quick-set-counts article { + display: grid !important; + grid-template-columns: minmax(0, 1fr) auto !important; + align-items: center !important; + gap: 12px !important; + min-height: 58px !important; + padding: 10px !important; + border: 1px solid rgba(16, 115, 204, 0.08) !important; + border-radius: 10px !important; + background: #f8f9fa !important; +} + +.ecommerce-standalone .ecom-quick-set-counts article strong { + color: #172636 !important; + font-size: 13px !important; + font-weight: 950 !important; +} + +.ecommerce-standalone .ecom-quick-set-counts article span { + display: block !important; + margin-top: 4px !important; + color: #738392 !important; + font-size: 12px !important; + font-weight: 750 !important; +} + +.ecommerce-standalone .ecom-quick-set-counts p { + display: inline-grid !important; + grid-template-columns: 26px 28px 26px !important; + align-items: center !important; + margin: 0 !important; + border: 1px solid rgba(16, 115, 204, 0.12) !important; + border-radius: 9px !important; + background: #ffffff !important; +} + +.ecommerce-standalone .ecom-quick-set-counts p button, +.ecommerce-standalone .ecom-quick-set-counts p b { + display: inline-grid !important; + place-items: center !important; + min-height: 28px !important; + border: 0 !important; + color: #1073cc !important; + background: transparent !important; + font-size: 13px !important; + font-weight: 950 !important; +} + +.ecommerce-standalone .ecom-quick-set-primary { + position: absolute !important; + left: 14px !important; + right: 14px !important; + bottom: 14px !important; + min-height: 54px !important; + border: 0 !important; + border-radius: 13px !important; + color: #ffffff !important; + background: linear-gradient(135deg, #1073cc, #1ebddb) !important; + box-shadow: 0 16px 36px rgba(16, 115, 204, 0.2) !important; + font-size: 17px !important; + font-weight: 950 !important; +} + +.ecommerce-standalone .ecom-quick-set-primary--cancel { + display: block !important; + position: static !important; + left: auto !important; + right: auto !important; + bottom: auto !important; + width: 100% !important; + margin-top: 8px !important; + min-height: 40px !important; + color: #ff4d4f !important; + background: rgba(255, 77, 79, 0.06) !important; + border: 1px solid rgba(255, 77, 79, 0.18) !important; + border-radius: 12px !important; + box-shadow: none !important; + font-size: 14px !important; + font-weight: 700 !important; + cursor: pointer !important; + transition: background 180ms ease, color 180ms ease, border-color 180ms ease !important; +} + +.ecommerce-standalone .ecom-quick-set-primary--cancel:hover { + color: #ffffff !important; + background: #ff4d4f !important; + border-color: #ff4d4f !important; +} + +.ecommerce-standalone .ecom-quick-set-primary:disabled { + color: #8fa1af !important; + background: #eef2f5 !important; + box-shadow: none !important; +} + +.ecommerce-standalone .ecom-quick-set-page .ecom-quick-set-primary { + position: static !important; + left: auto !important; + right: auto !important; + bottom: auto !important; + width: 100% !important; + margin-top: auto !important; + flex: 0 0 auto !important; +} + +.ecommerce-standalone .ecom-quick-set-page .ecom-quick-set-panel { + overflow-y: auto !important; + padding-bottom: 16px !important; + scrollbar-width: auto !important; + scrollbar-color: rgba(16, 115, 204, 0.56) rgba(16, 115, 204, 0.08) !important; +} + +.ecommerce-standalone .ecom-quick-set-page .ecom-quick-set-panel::-webkit-scrollbar { + display: block !important; + width: 14px !important; + height: 14px !important; +} + +.ecommerce-standalone .ecom-quick-set-page .ecom-quick-set-panel::-webkit-scrollbar-track { + border-radius: 999px !important; + background: rgba(16, 115, 204, 0.08) !important; +} + +.ecommerce-standalone .ecom-quick-set-page .ecom-quick-set-panel::-webkit-scrollbar-thumb { + border: 3px solid rgba(248, 249, 250, 0.95) !important; + border-radius: 999px !important; + background: rgba(16, 115, 204, 0.56) !important; +} + +.ecommerce-standalone .ecom-quick-set-page .ecom-quick-set-panel::-webkit-scrollbar-thumb:hover { + background: rgba(16, 115, 204, 0.72) !important; +} + +.ecommerce-standalone .ecom-quick-detail-page .ecom-quick-set-primary { + position: static !important; + left: auto !important; + right: auto !important; + bottom: auto !important; + width: 100% !important; + margin-top: 2px !important; + flex: 0 0 auto !important; +} + +.ecommerce-standalone .ecom-quick-set-stage { + position: relative !important; + display: grid !important; + grid-template-rows: auto minmax(0, 1fr) auto !important; + gap: 18px !important; + place-items: stretch !important; + padding: 24px 34px !important; + background: + radial-gradient(circle at 52% 46%, rgba(30, 189, 219, 0.07), transparent 26rem), + #f8f9fa !important; +} + +.ecommerce-standalone .ecom-quick-set-preview-head { + display: grid !important; + gap: 8px !important; + justify-items: start !important; + padding-bottom: 18px !important; + border-bottom: 1px solid rgba(16, 115, 204, 0.08) !important; +} + +.ecommerce-standalone .ecom-quick-set-preview-head h1 { + margin: 0 !important; + color: #172636 !important; + font-size: 21px !important; + font-weight: 950 !important; +} + +.ecommerce-standalone .ecom-quick-set-preview-head p { + margin: 0 !important; + color: #657686 !important; + font-size: 13px !important; + font-weight: 750 !important; +} + +.ecommerce-standalone .ecom-quick-set-preview-head p span { + color: #1073cc !important; + font-weight: 950 !important; +} + +.ecommerce-standalone .ecom-quick-set-preview-head div { + display: inline-flex !important; + align-items: center !important; + gap: 8px !important; +} + +.ecommerce-standalone .ecom-quick-set-preview-head div button { + width: 24px !important; + height: 24px !important; + border: 0 !important; + border-radius: 7px !important; + color: #1073cc !important; + background: #edf8ff !important; + font-weight: 950 !important; +} + +.ecommerce-standalone .ecom-quick-set-canvas { + display: grid !important; + place-items: center !important; + min-height: 340px !important; +} + +.ecommerce-standalone .ecom-quick-set-empty { + display: grid !important; + place-items: center !important; + gap: 12px !important; + width: min(480px, 76%) !important; + min-height: 200px !important; + padding: 28px !important; + border: 1px solid rgba(16, 115, 204, 0.1) !important; + border-radius: 18px !important; + color: #738392 !important; + background: #ffffff !important; + box-shadow: 0 18px 48px rgba(16, 115, 204, 0.06) !important; + text-align: center !important; +} + +.ecommerce-standalone .ecom-quick-set-empty .anticon { + display: inline-grid !important; + place-items: center !important; + width: 58px !important; + height: 58px !important; + border-radius: 50% !important; + color: #1073cc !important; + background: #edf8ff !important; + font-size: 26px !important; +} + +.ecommerce-standalone .ecom-quick-set-empty strong { + color: #172636 !important; + font-size: 19px !important; + font-weight: 950 !important; +} + +.ecommerce-standalone .ecom-quick-set-generating, +.ecommerce-standalone .ecom-quick-set-failed { + display: grid !important; + place-items: center !important; + gap: 12px !important; + width: min(480px, 76%) !important; + min-height: 200px !important; + padding: 28px !important; + border: 1px solid rgba(16, 115, 204, 0.1) !important; + border-radius: 18px !important; + color: #738392 !important; + background: #ffffff !important; + box-shadow: 0 18px 48px rgba(16, 115, 204, 0.06) !important; + text-align: center !important; +} + +.ecommerce-standalone .ecom-quick-set-generating .anticon { + display: inline-grid !important; + place-items: center !important; + width: 58px !important; + height: 58px !important; + border-radius: 50% !important; + color: #1073cc !important; + background: #edf8ff !important; + font-size: 26px !important; + animation: spin 1s linear infinite !important; +} + +.ecommerce-standalone .ecom-quick-set-generating strong { + color: #172636 !important; + font-size: 19px !important; + font-weight: 950 !important; +} + +.ecommerce-standalone .ecom-quick-set-generating span { + color: #738392 !important; + font-size: 13px !important; + line-height: 1.5 !important; +} + +.ecommerce-standalone .ecom-quick-set-progress { + width: 100% !important; + max-width: 320px !important; + height: 6px !important; + border-radius: 3px !important; + background: #e8eef4 !important; + overflow: hidden !important; +} + +.ecommerce-standalone .ecom-quick-set-progress-bar { + height: 100% !important; + border-radius: 3px !important; + background: linear-gradient(90deg, #1073cc, #38bdf8) !important; + transition: width 500ms ease !important; +} + +.ecommerce-standalone .ecom-quick-set-progress-text { + color: #1073cc !important; + font-size: 13px !important; + font-weight: 700 !important; + font-style: normal !important; +} + +.ecommerce-standalone .ecom-quick-set-failed .anticon { + display: inline-grid !important; + place-items: center !important; + width: 58px !important; + height: 58px !important; + border-radius: 50% !important; + color: #e04545 !important; + background: #fff0f0 !important; + font-size: 26px !important; +} + +.ecommerce-standalone .ecom-quick-set-failed strong { + color: #172636 !important; + font-size: 19px !important; + font-weight: 950 !important; +} + +.ecommerce-standalone .ecom-quick-set-failed span { + color: #738392 !important; + font-size: 13px !important; + line-height: 1.5 !important; +} + +.ecommerce-standalone .ecom-quick-set-failed button { + min-height: 36px !important; + padding: 0 20px !important; + border: 1px solid rgba(16, 115, 204, 0.14) !important; + border-radius: 10px !important; + color: #1073cc !important; + background: #ffffff !important; + font-size: 13px !important; + font-weight: 700 !important; + cursor: pointer !important; + transition: background 180ms ease, color 180ms ease !important; +} + +.ecommerce-standalone .ecom-quick-set-failed button:hover:not(:disabled) { + color: #ffffff !important; + background: #1073cc !important; +} + +.ecommerce-standalone .ecom-quick-set-failed button:disabled { + opacity: 0.45 !important; + cursor: not-allowed !important; +} + +@keyframes spin { + from { transform: rotate(0deg); } + to { transform: rotate(360deg); } +} + +.ecommerce-standalone .ecom-quick-set-result-card { + display: grid !important; + grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr) !important; + gap: 16px !important; + width: min(760px, 92%) !important; + padding: 18px !important; + border: 1px solid rgba(16, 115, 204, 0.08) !important; + border-radius: 18px !important; + background: #ffffff !important; + box-shadow: 0 20px 56px rgba(16, 115, 204, 0.08) !important; + transform-origin: center !important; +} + +.ecommerce-standalone .ecom-quick-set-result-card figure { + position: relative !important; + margin: 0 !important; + overflow: hidden !important; + border-radius: 12px !important; + background: #f3f6f8 !important; +} + +.ecommerce-standalone .ecom-quick-set-result-card figure img { + width: 100% !important; + height: 100% !important; + object-fit: cover !important; +} + +.ecommerce-standalone .ecom-quick-set-result-card > figure { + min-height: 280px !important; +} + +.ecommerce-standalone .ecom-quick-set-result-card > div { + display: grid !important; + grid-template-columns: 1fr 1fr !important; + gap: 10px !important; +} + +.ecommerce-standalone .ecom-quick-set-result-card > div figure { + min-height: 134px !important; +} + +.ecommerce-standalone .ecom-quick-set-result-card figure span { + position: absolute !important; + top: 9px !important; + left: 9px !important; + padding: 4px 9px !important; + border-radius: 999px !important; + color: #435566 !important; + background: rgba(255, 255, 255, 0.86) !important; + font-size: 11px !important; + font-weight: 950 !important; +} + +.ecommerce-standalone .ecom-quick-detail-preview-card { + display: grid !important; + grid-template-columns: repeat(2, minmax(0, 1fr)) !important; + gap: 12px !important; + width: min(620px, 88%) !important; + padding: 16px !important; + border: 1px solid rgba(16, 115, 204, 0.08) !important; + border-radius: 18px !important; + background: #ffffff !important; + box-shadow: 0 20px 56px rgba(16, 115, 204, 0.08) !important; + transform-origin: center !important; +} + +.ecommerce-standalone .ecom-quick-detail-preview-card figure, +.ecommerce-standalone .ecom-quick-detail-result { + position: relative !important; + margin: 0 !important; + overflow: hidden !important; + border-radius: 12px !important; + background: #f3f6f8 !important; +} + +.ecommerce-standalone .ecom-quick-detail-preview-card figure { + min-height: 150px !important; +} + +.ecommerce-standalone .ecom-quick-detail-preview-card img, +.ecommerce-standalone .ecom-quick-detail-result img { + width: 100% !important; + height: 100% !important; + object-fit: cover !important; +} + +.ecommerce-standalone .ecom-quick-detail-preview-card span { + position: absolute !important; + top: 9px !important; + left: 9px !important; + padding: 4px 9px !important; + border-radius: 999px !important; + color: #435566 !important; + background: rgba(255, 255, 255, 0.86) !important; + font-size: 11px !important; + font-weight: 950 !important; +} + +.ecommerce-standalone .ecom-quick-detail-result { + width: min(520px, 80%) !important; + min-height: 620px !important; + border: 1px solid rgba(16, 115, 204, 0.08) !important; + box-shadow: 0 20px 56px rgba(16, 115, 204, 0.08) !important; + transform-origin: center !important; +} + +.ecommerce-standalone .ecom-quick-detail-download { + position: absolute !important; + bottom: 16px !important; + right: 16px !important; + display: inline-flex !important; + align-items: center !important; + justify-content: center !important; + gap: 7px !important; + min-height: 36px !important; + padding: 0 16px !important; + border: 1px solid rgba(16, 115, 204, 0.14) !important; + border-radius: 10px !important; + color: #1073cc !important; + background: rgba(255, 255, 255, 0.92) !important; + backdrop-filter: blur(6px) !important; + box-shadow: 0 8px 20px rgba(16, 115, 204, 0.06) !important; + font-size: 13px !important; + font-weight: 850 !important; + cursor: pointer !important; + transition: transform 180ms ease, color 180ms ease, background 180ms ease, box-shadow 180ms ease !important; +} + +.ecommerce-standalone .ecom-quick-detail-download:hover { + color: #ffffff !important; + background: #1073cc !important; + box-shadow: 0 12px 26px rgba(16, 115, 204, 0.18) !important; + transform: translateY(-1px) !important; +} + +.ecommerce-standalone .ecom-quick-detail-download:active { + transform: scale(0.96) !important; +} + +.ecommerce-standalone .ecom-quick-set-prompt { + position: relative !important; + display: grid !important; + grid-template-columns: minmax(0, 1fr) 40px !important; + align-items: end !important; + gap: 12px !important; + min-height: 92px !important; + padding: 14px 15px !important; + border: 1px solid rgba(16, 115, 204, 0.1) !important; + border-radius: 17px !important; + background: #ffffff !important; + box-shadow: 0 14px 36px rgba(16, 115, 204, 0.05) !important; +} + +.ecommerce-standalone .ecom-quick-detail-page .ecom-quick-set-prompt { + grid-template-columns: minmax(0, 1fr) auto !important; +} + +.ecommerce-standalone .ecom-quick-detail-prompt-actions { + display: inline-flex !important; + gap: 8px !important; +} + +.ecommerce-standalone .ecom-quick-set-prompt textarea { + min-height: 62px !important; + resize: none !important; + border: 0 !important; + outline: none !important; + color: #172636 !important; + background: transparent !important; + font-size: 13px !important; + font-weight: 750 !important; +} + +.ecommerce-standalone .ecom-quick-set-prompt button { + width: 40px !important; + height: 40px !important; + border: 0 !important; + border-radius: 50% !important; + color: #ffffff !important; + background: #1073cc !important; + font-size: 18px !important; + font-weight: 950 !important; +} + +.ecommerce-standalone .ecom-quick-set-prompt button:disabled { + color: #8fa1af !important; + background: #eef2f5 !important; +} + +.ecommerce-standalone .ecom-quick-set-prompt span { + position: absolute !important; + right: 14px !important; + bottom: -22px !important; + color: #71818e !important; + font-size: 12px !important; + font-weight: 850 !important; +} + +.ecommerce-standalone .ecom-quick-set-collapse { + display: none !important; +} + +.ecommerce-standalone .ecom-quick-set-collapse:hover { + border-color: rgba(30, 189, 219, 0.5) !important; + color: #1073cc !important; + background: rgba(30, 189, 219, 0.1) !important; + transform: translateY(-50%) translateY(-1px) !important; +} + +.ecommerce-standalone .ecom-quick-set-page.is-panel-collapsed .ecom-quick-set-collapse { + left: 12px !important; +} + +.ecommerce-standalone .ecom-smart-cutout-page { + position: relative !important; + width: 100% !important; + min-width: 100% !important; + height: 100% !important; + min-height: calc(100vh - 58px) !important; + overflow: auto !important; + color: #111820 !important; + background: #feffff !important; + font-family: "PingFang SC", "Microsoft YaHei", sans-serif !important; + animation: ecom-smart-page-enter 440ms cubic-bezier(0.16, 1, 0.3, 1) both !important; +} + +.ecommerce-standalone .ecom-smart-cutout-nav { + position: sticky !important; + top: 18px !important; + left: 24px !important; + z-index: 12 !important; + display: inline-flex !important; + align-items: center !important; + gap: 10px !important; + margin: 18px 0 -52px 24px !important; + padding: 6px !important; + border: 1px solid rgba(16, 115, 204, 0.12) !important; + border-radius: 15px !important; + background: rgba(254, 255, 255, 0.86) !important; + box-shadow: 0 14px 34px rgba(16, 115, 204, 0.08) !important; + backdrop-filter: blur(12px) !important; + -webkit-backdrop-filter: blur(12px) !important; +} + +.ecommerce-standalone .ecom-smart-cutout-nav button { + display: inline-flex !important; + align-items: center !important; + justify-content: center !important; + min-width: 70px !important; + min-height: 32px !important; + padding: 0 13px !important; + border: 0 !important; + border-radius: 11px !important; + color: #1073cc !important; + background: transparent !important; + font-size: 13px !important; + font-weight: 700 !important; + cursor: pointer !important; + transition: color 180ms ease, background 180ms ease, box-shadow 180ms ease !important; +} + +.ecommerce-standalone .ecom-smart-cutout-nav button:hover { + color: #ffffff !important; + background: #1073cc !important; + box-shadow: 0 8px 18px rgba(16, 115, 204, 0.18) !important; +} + +.ecommerce-standalone .ecom-smart-cutout-transition, +.ecommerce-standalone .ecom-quick-page-transition { + position: fixed !important; + inset: 64px 0 0 !important; + z-index: 30 !important; + display: grid !important; + place-content: center !important; + justify-items: center !important; + gap: 10px !important; + color: #10202c !important; + background: rgba(248, 253, 255, 0.82) !important; + backdrop-filter: blur(18px) !important; + -webkit-backdrop-filter: blur(18px) !important; + animation: ecom-smart-transition-in 260ms ease both !important; +} + +.ecommerce-standalone .ecom-smart-cutout-transition span, +.ecommerce-standalone .ecom-quick-page-transition span { + width: 56px !important; + height: 56px !important; + border: 4px solid rgba(30, 189, 219, 0.16) !important; + border-top-color: #1ebddb !important; + border-radius: 50% !important; + box-shadow: 0 12px 30px rgba(30, 189, 219, 0.18) !important; + animation: ecom-smart-transition-spin 860ms linear infinite !important; +} + +.ecommerce-standalone .ecom-smart-cutout-transition strong, +.ecommerce-standalone .ecom-quick-page-transition strong { + margin-top: 8px !important; + color: #10202c !important; + font-size: 20px !important; + font-weight: 800 !important; +} + +.ecommerce-standalone .ecom-smart-cutout-transition em, +.ecommerce-standalone .ecom-quick-page-transition em { + color: #6d7d88 !important; + font-size: 13px !important; + font-style: normal !important; + font-weight: 600 !important; +} + +.ecommerce-standalone .ecom-smart-cutout-page.is-transitioning .ecom-smart-cutout-upload, +.ecommerce-standalone .ecom-smart-cutout-page.is-transitioning .ecom-smart-editor { + pointer-events: none !important; + animation: ecom-smart-page-hold 620ms ease both !important; +} + +.ecommerce-standalone .ecom-smart-cutout-upload { + position: relative !important; + display: grid !important; + align-content: center !important; + justify-items: center !important; + gap: 28px !important; + min-height: calc(100vh - 64px) !important; + padding: 72px 32px 96px !important; + animation: ecom-smart-upload-enter 460ms cubic-bezier(0.16, 1, 0.3, 1) both !important; +} + +.ecommerce-standalone .ecom-smart-cutout-head { + display: grid !important; + gap: 10px !important; + text-align: center !important; +} + +.ecommerce-standalone .ecom-smart-cutout-head strong { + color: #101820 !important; + font-size: 34px !important; + font-weight: 800 !important; + line-height: 1.15 !important; + letter-spacing: 0 !important; +} + +.ecommerce-standalone .ecom-smart-cutout-head span { + color: #6f7e89 !important; + font-size: 15px !important; + font-weight: 500 !important; +} + +.ecommerce-standalone .ecom-smart-cutout-upload__body { + display: grid !important; + grid-template-columns: minmax(280px, 360px) minmax(360px, 520px) !important; + gap: 32px !important; + align-items: stretch !important; + width: min(930px, 100%) !important; +} + +.ecommerce-standalone .ecom-smart-cutout-demo { + display: grid !important; + grid-template-columns: repeat(2, minmax(0, 1fr)) !important; + gap: 20px !important; + padding: 28px !important; + border: 1px solid rgba(16, 115, 204, 0.1) !important; + border-radius: 20px !important; + background: #ffffff !important; + box-shadow: 0 18px 46px rgba(16, 115, 204, 0.07) !important; +} + +.ecommerce-standalone .ecom-smart-cutout-demo__tile { + position: relative !important; + min-height: 130px !important; + overflow: hidden !important; + border-radius: 18px !important; + background: #f3f8fa !important; + box-shadow: inset 0 0 0 1px rgba(16, 115, 204, 0.06), 0 12px 24px rgba(16, 115, 204, 0.08) !important; +} + +.ecommerce-standalone .ecom-smart-cutout-demo__tile::before, +.ecommerce-standalone .ecom-smart-cutout-demo__tile::after { + position: absolute !important; + content: "" !important; +} + +.ecommerce-standalone .ecom-smart-cutout-demo__tile--flower { + background: + radial-gradient(circle at 52% 38%, #fff9c8 0 9px, transparent 10px), + radial-gradient(circle at 43% 44%, #f25f7a 0 7px, transparent 8px), + radial-gradient(circle at 61% 48%, #ff9f43 0 8px, transparent 9px), + linear-gradient(135deg, #c9a16d, #6a4622) !important; +} + +.ecommerce-standalone .ecom-smart-cutout-demo__tile--flower::before { + left: 50% !important; + bottom: 18px !important; + width: 52px !important; + height: 58px !important; + border-radius: 12px 12px 20px 20px !important; + background: rgba(255, 255, 255, 0.6) !important; + transform: translateX(-50%) !important; +} + +.ecommerce-standalone .ecom-smart-cutout-demo__tile--product { + background: + radial-gradient(circle at 50% 34%, #ffffff 0 28px, transparent 29px), + linear-gradient(135deg, #f2f5f7, #6f7680) !important; +} + +.ecommerce-standalone .ecom-smart-cutout-demo__tile--product::before { + left: 50% !important; + bottom: 18px !important; + width: 74px !important; + height: 52px !important; + border-radius: 20px 20px 26px 26px !important; + background: linear-gradient(135deg, #37424e, #d5dde4) !important; + transform: translateX(-50%) !important; +} + +.ecommerce-standalone .ecom-smart-cutout-demo__tile--poster { + background: #ffffff !important; +} + +.ecommerce-standalone .ecom-smart-cutout-demo__tile--poster::before { + inset: 24px 18px !important; + border-radius: 10px !important; + background: + radial-gradient(circle at 38% 48%, rgba(235, 81, 116, 0.42) 0 24px, transparent 25px), + linear-gradient(12deg, transparent 0 42%, #1073cc 43% 47%, transparent 48%), + linear-gradient(0deg, #f2f7fb 0 100%) !important; +} + +.ecommerce-standalone .ecom-smart-cutout-demo__tile--object { + background: linear-gradient(135deg, #f2eee8, #c7b6a0) !important; +} + +.ecommerce-standalone .ecom-smart-cutout-demo__tile--object::before { + left: 50% !important; + top: 30px !important; + width: 70px !important; + height: 70px !important; + border: 9px solid #f7fafc !important; + border-radius: 50% !important; + background: repeating-conic-gradient(from 0deg, #d7dee4 0 8deg, #ffffff 9deg 16deg) !important; + transform: translateX(-50%) !important; +} + +.ecommerce-standalone .ecom-smart-cutout-demo__tile--object::after { + left: 50% !important; + bottom: 18px !important; + width: 42px !important; + height: 48px !important; + border-radius: 12px !important; + background: #f8fbfd !important; + transform: translateX(-50%) !important; +} + +.ecommerce-standalone .ecom-smart-cutout-upload-box { + display: grid !important; + align-content: center !important; + justify-items: center !important; + gap: 12px !important; + min-height: 360px !important; + padding: 36px !important; + border: 1.5px dashed rgba(16, 115, 204, 0.46) !important; + border-radius: 20px !important; + background: #ffffff !important; + cursor: pointer !important; + transition: border-color 240ms ease, box-shadow 240ms ease, transform 240ms ease, background 240ms ease !important; +} + +.ecommerce-standalone .ecom-smart-cutout-upload-box:hover, +.ecommerce-standalone .ecom-smart-cutout-upload-box.is-dragging { + border-color: #1ebddb !important; + background: #f8fdff !important; + box-shadow: 0 18px 46px rgba(30, 189, 219, 0.12) !important; + transform: translateY(-2px) !important; +} + +.ecommerce-standalone .ecom-smart-cutout-upload-box button { + display: inline-flex !important; + align-items: center !important; + justify-content: center !important; + gap: 8px !important; + width: 190px !important; + min-height: 42px !important; + border-radius: 9px !important; + font-size: 14px !important; + font-weight: 700 !important; + cursor: pointer !important; +} + +.ecommerce-standalone .ecom-smart-cutout-upload__primary { + border: 0 !important; + color: #ffffff !important; + background: #1073cc !important; + box-shadow: 0 10px 22px rgba(16, 115, 204, 0.2) !important; +} + +.ecommerce-standalone .ecom-smart-cutout-upload__secondary { + border: 1px solid rgba(16, 115, 204, 0.16) !important; + color: #253544 !important; + background: #ffffff !important; +} + +.ecommerce-standalone .ecom-smart-cutout-upload-box > span { + margin-top: 2px !important; + color: #6b7b86 !important; + font-size: 13px !important; + font-weight: 600 !important; +} + +.ecommerce-standalone .ecom-smart-cutout-back { + display: inline-flex !important; + align-items: center !important; + justify-content: center !important; + min-height: 34px !important; + padding: 0 14px !important; + border: 1px solid rgba(16, 115, 204, 0.14) !important; + border-radius: 12px !important; + color: #1073cc !important; + background: #f4fbfd !important; + font-size: 13px !important; + font-weight: 700 !important; + cursor: pointer !important; +} + +.ecommerce-standalone .ecom-smart-cutout-upload > .ecom-smart-cutout-back { + position: absolute !important; + top: 22px !important; + left: 28px !important; +} + +.ecommerce-standalone .ecom-smart-editor { + display: grid !important; + grid-template-columns: minmax(0, 1fr) 300px !important; + gap: 32px !important; + width: min(1120px, calc(100% - 64px)) !important; + min-height: calc(100vh - 64px) !important; + margin: 0 auto !important; + padding: 22px 0 60px !important; + animation: ecom-smart-editor-enter 520ms cubic-bezier(0.16, 1, 0.3, 1) both !important; +} + +.ecommerce-standalone .ecom-smart-editor__workspace { + display: grid !important; + grid-template-rows: auto auto auto !important; + gap: 14px !important; + min-width: 0 !important; +} + +.ecommerce-standalone .ecom-smart-editor__canvas { + position: relative !important; + display: grid !important; + place-items: center !important; + min-height: 430px !important; + overflow: hidden !important; + background: #e8edf3 !important; +} + +.ecommerce-standalone .ecom-smart-editor__checker { + position: relative !important; + display: grid !important; + place-items: center !important; + width: var(--smart-cutout-frame-width, min(520px, 78%)) !important; + min-height: 430px !important; + aspect-ratio: var(--smart-cutout-frame-aspect, auto) !important; + overflow: hidden !important; + background: transparent !important; + transition: width 220ms ease, aspect-ratio 220ms ease, min-height 220ms ease !important; +} + +.ecommerce-standalone .ecom-smart-editor__background-layer { + position: absolute !important; + inset: 0 !important; + z-index: 0 !important; + background: var(--smart-cutout-bg, #ffffff) !important; + transition: background-color 180ms ease, background 180ms ease !important; +} + +.ecommerce-standalone .ecom-smart-editor__checker:not(.is-size-original):not(.is-size-trim) { + min-height: 0 !important; +} + +.ecommerce-standalone .ecom-smart-editor__checker.is-size-trim { + min-height: 320px !important; + padding: 18px !important; +} + +.ecommerce-standalone .ecom-smart-editor__checker img { + position: relative !important; + z-index: 1 !important; + display: block !important; + max-width: var(--smart-cutout-image-max-width, 78%) !important; + max-height: var(--smart-cutout-image-max-height, 310px) !important; + object-fit: contain !important; + filter: drop-shadow(0 16px 24px rgba(17, 24, 32, 0.14)) !important; + transition: max-width 220ms ease, max-height 220ms ease !important; +} + +.ecommerce-standalone .ecom-smart-editor__canvas-actions { + position: absolute !important; + top: 20px !important; + right: 18px !important; + display: flex !important; + gap: 8px !important; +} + +.ecommerce-standalone .ecom-smart-editor__canvas-actions button { + min-height: 34px !important; + padding: 0 12px !important; + border: 0 !important; + border-radius: 9px !important; + color: #1e2d38 !important; + background: rgba(255, 255, 255, 0.9) !important; + font-size: 13px !important; + font-weight: 700 !important; +} + +.ecommerce-standalone .ecom-smart-editor__tools-shell { + display: grid !important; + grid-template-columns: 24px minmax(0, 1fr) 24px !important; + grid-template-rows: auto auto !important; + align-items: start !important; + gap: 6px 5px !important; + height: auto !important; + overflow: visible !important; +} + +.ecommerce-standalone .ecom-smart-editor__tools-title { + grid-column: 1 / -1 !important; + color: #1c2a35 !important; + font-size: 16px !important; + font-weight: 800 !important; + line-height: 1.15 !important; +} + +.ecommerce-standalone .ecom-smart-editor__tools { + display: flex !important; + align-items: start !important; + gap: 5px !important; + min-width: 0 !important; + height: auto !important; + overflow-x: auto !important; + overflow-y: visible !important; + scroll-behavior: smooth !important; + scrollbar-width: none !important; +} + +.ecommerce-standalone .ecom-smart-editor__tools::-webkit-scrollbar { + display: none !important; +} + +.ecommerce-standalone .ecom-smart-editor__tools-nav { + display: inline-flex !important; + align-items: center !important; + justify-content: center !important; + width: 24px !important; + height: 100px !important; + min-width: 24px !important; + min-height: 100px !important; + border: 1px solid rgba(16, 115, 204, 0.12) !important; + border-radius: 7px !important; + color: #1073cc !important; + background: #f8fdff !important; + box-shadow: 0 6px 14px rgba(16, 115, 204, 0.06) !important; + font-size: 17px !important; + font-weight: 800 !important; + line-height: 1 !important; + cursor: pointer !important; +} + +.ecommerce-standalone .ecom-smart-editor__tools-nav:hover { + border-color: #1ebddb !important; + background: #effbfe !important; +} + +.ecommerce-standalone .ecom-smart-editor__tools button { + flex: 0 0 100px !important; + width: 100px !important; + height: 100px !important; + display: inline-grid !important; + place-items: center !important; + min-height: 100px !important; + padding: 10px 8px !important; + border: 1px solid rgba(16, 115, 204, 0.12) !important; + border-radius: 7px !important; + color: #2d3d48 !important; + background: #f2f5f7 !important; + font-size: 9px !important; + font-weight: 700 !important; + cursor: pointer !important; +} + +.ecommerce-standalone .ecom-smart-editor__tool-item { + flex: 0 0 100px !important; + display: grid !important; + gap: 6px !important; + justify-items: center !important; + width: 100px !important; +} + +.ecommerce-standalone .ecom-smart-editor__tools button.is-active { + border-color: #1073cc !important; + color: #1073cc !important; + background: #f8fdff !important; + box-shadow: 0 0 0 3px rgba(30, 189, 219, 0.16) !important; +} + +.ecommerce-standalone .ecom-smart-editor__tool-text { + display: grid !important; + gap: 2px !important; + justify-items: center !important; + max-width: 100% !important; + text-align: center !important; + line-height: 1.18 !important; + color: #2d3d48 !important; + font-size: 10px !important; + font-weight: 800 !important; +} + +.ecommerce-standalone .ecom-smart-editor__tool-text > span { + max-width: 100% !important; + overflow: hidden !important; + text-overflow: ellipsis !important; +} + +.ecommerce-standalone .ecom-smart-editor__tool-text > span:first-child { + display: -webkit-box !important; + -webkit-box-orient: vertical !important; + -webkit-line-clamp: 2 !important; +} + +.ecommerce-standalone .ecom-smart-editor__tool-text > span:last-child:not(:first-child) { + font-size: 9px !important; + font-weight: 800 !important; + color: #6a7c88 !important; +} + +.ecommerce-standalone .ecom-smart-editor__tool-icon { + position: relative !important; + display: inline-flex !important; + align-items: center !important; + justify-content: center !important; + width: 24px !important; + height: 24px !important; + color: currentColor !important; + transform: scale(0.72) !important; +} + +.ecommerce-standalone .ecom-smart-editor__tool-icon::before { + display: block !important; + border: 2px solid currentColor !important; + border-radius: 5px !important; + content: "" !important; +} + +.ecommerce-standalone .ecom-smart-editor__tool-icon--image::before { + width: 20px !important; + height: 16px !important; + border-radius: 4px !important; +} + +.ecommerce-standalone .ecom-smart-editor__tool-icon--image::after { + position: absolute !important; + left: 6px !important; + bottom: 6px !important; + width: 12px !important; + height: 7px !important; + border-radius: 2px 2px 4px 4px !important; + background: linear-gradient(135deg, transparent 0 45%, currentColor 46% 54%, transparent 55%) !important; + content: "" !important; + opacity: 0.8 !important; +} + +.ecommerce-standalone .ecom-smart-editor__tool-icon--crop::before { + width: 18px !important; + height: 18px !important; + border-radius: 3px !important; +} + +.ecommerce-standalone .ecom-smart-editor__tool-icon--crop::after { + position: absolute !important; + width: 22px !important; + height: 22px !important; + border-top: 2px solid currentColor !important; + border-left: 2px solid currentColor !important; + content: "" !important; + transform: translate(2px, 2px) rotate(-45deg) scale(0.55) !important; + opacity: 0.9 !important; +} + +.ecommerce-standalone .ecom-smart-editor__tool-icon--shop::before, +.ecommerce-standalone .ecom-smart-editor__tool-icon--pdd::before { + width: 18px !important; + height: 18px !important; + border-radius: 4px !important; +} + +.ecommerce-standalone .ecom-smart-editor__tool-icon--shop::after, +.ecommerce-standalone .ecom-smart-editor__tool-icon--pdd::after { + position: absolute !important; + right: 2px !important; + bottom: 2px !important; + color: currentColor !important; + font-size: 8px !important; + font-weight: 900 !important; + content: "淘" !important; +} + +.ecommerce-standalone .ecom-smart-editor__tool-icon--pdd::after { + content: "拼" !important; +} + +.ecommerce-standalone .ecom-smart-editor__tool-icon--text::before { + width: 19px !important; + height: 14px !important; + border-radius: 4px !important; +} + +.ecommerce-standalone .ecom-smart-editor__tool-icon--text::after { + position: absolute !important; + color: currentColor !important; + font-size: 8px !important; + font-weight: 900 !important; + content: "小红书" !important; + transform: scale(0.72) !important; +} + +.ecommerce-standalone .ecom-smart-editor__tool-icon--portrait::before, +.ecommerce-standalone .ecom-smart-editor__tool-icon--portrait-ratio::before, +.ecommerce-standalone .ecom-smart-editor__tool-icon--phone::before { + width: 12px !important; + height: 20px !important; + border-radius: 5px !important; +} + +.ecommerce-standalone .ecom-smart-editor__tool-icon--square::before { + width: 17px !important; + height: 17px !important; + border-radius: 5px !important; +} + +.ecommerce-standalone .ecom-smart-editor__tool-icon--landscape::before { + width: 20px !important; + height: 13px !important; + border-radius: 5px !important; +} + +.ecommerce-standalone .ecom-smart-editor__tool-icon--wide::before { + width: 22px !important; + height: 10px !important; + border-radius: 5px !important; +} + +.ecommerce-standalone .ecom-smart-editor__batch { + display: grid !important; + gap: 10px !important; + min-width: 0 !important; + padding: 12px !important; + border: 1px solid rgba(30, 189, 219, 0.14) !important; + border-radius: 12px !important; + background: rgba(248, 253, 255, 0.82) !important; +} + +.ecommerce-standalone .ecom-smart-editor__batch header { + display: flex !important; + align-items: center !important; + justify-content: space-between !important; + gap: 12px !important; + color: #172636 !important; +} + +.ecommerce-standalone .ecom-smart-editor__batch header strong { + font-size: 14px !important; + font-weight: 800 !important; +} + +.ecommerce-standalone .ecom-smart-editor__batch header span { + color: #6e8290 !important; + font-size: 12px !important; + font-weight: 700 !important; +} + +.ecommerce-standalone .ecom-smart-editor__batch > div { + display: flex !important; + gap: 10px !important; + min-width: 0 !important; + overflow-x: auto !important; + padding-bottom: 2px !important; +} + +.ecommerce-standalone .ecom-smart-editor__batch button { + position: relative !important; + flex: 0 0 74px !important; + width: 74px !important; + height: 74px !important; + overflow: hidden !important; + border: 2px solid transparent !important; + border-radius: 12px !important; + background: #ffffff !important; + cursor: pointer !important; + box-shadow: 0 10px 22px rgba(16, 115, 204, 0.08) !important; +} + +.ecommerce-standalone .ecom-smart-editor__batch button.is-active { + border-color: #1073cc !important; + box-shadow: 0 12px 26px rgba(16, 115, 204, 0.16) !important; +} + +.ecommerce-standalone .ecom-smart-editor__batch button img { + display: block !important; + width: 100% !important; + height: 100% !important; + object-fit: cover !important; +} + +.ecommerce-standalone .ecom-smart-editor__batch button span { + position: absolute !important; + right: 5px !important; + bottom: 5px !important; + display: inline-flex !important; + align-items: center !important; + justify-content: center !important; + min-width: 20px !important; + height: 20px !important; + padding: 0 6px !important; + border-radius: 999px !important; + color: #ffffff !important; + background: rgba(16, 115, 204, 0.88) !important; + font-size: 11px !important; + font-weight: 800 !important; +} + +.ecommerce-standalone .ecom-smart-editor__gallery { + display: grid !important; + gap: 14px !important; +} + +.ecommerce-standalone .ecom-smart-editor__gallery header { + display: flex !important; + align-items: center !important; + justify-content: space-between !important; + color: #1c2a35 !important; +} + +.ecommerce-standalone .ecom-smart-editor__gallery header strong { + font-size: 16px !important; + font-weight: 800 !important; +} + +.ecommerce-standalone .ecom-smart-editor__gallery header button { + border: 0 !important; + color: #9aa6ad !important; + background: transparent !important; + font-size: 13px !important; + font-weight: 700 !important; +} + +.ecommerce-standalone .ecom-smart-editor__swatches, +.ecommerce-standalone .ecom-smart-editor__scenes { + display: grid !important; + grid-template-columns: repeat(6, minmax(0, 1fr)) !important; + gap: 10px !important; +} + +.ecommerce-standalone .ecom-smart-editor__swatches button, +.ecommerce-standalone .ecom-smart-editor__scenes button { + position: relative !important; + min-height: 118px !important; + overflow: hidden !important; + border: 1px solid rgba(16, 115, 204, 0.08) !important; + border-radius: 8px !important; + color: #20313e !important; + background: #f3f8fa !important; + cursor: pointer !important; +} + +.ecommerce-standalone .ecom-smart-editor__swatches button { + background: var(--smart-cutout-swatch-bg, #ffffff) !important; +} + +.ecommerce-standalone .ecom-smart-editor__swatch-bg { + position: absolute !important; + inset: 0 !important; + z-index: 0 !important; + border-radius: inherit !important; + background: var(--smart-cutout-swatch-bg, #ffffff) !important; + box-shadow: inset 0 0 0 1px rgba(16, 115, 204, 0.06) !important; +} + +.ecommerce-standalone .ecom-smart-editor__swatches button img { + position: absolute !important; + left: 50% !important; + top: 50% !important; + z-index: 1 !important; + width: 46% !important; + height: 58% !important; + object-fit: contain !important; + transform: translate(-50%, -50%) !important; + filter: drop-shadow(0 10px 16px rgba(17, 24, 32, 0.12)) !important; +} + +.ecommerce-standalone .ecom-smart-editor__swatches button.is-active { + border-color: #1073cc !important; + box-shadow: 0 0 0 3px rgba(30, 189, 219, 0.16) !important; +} + +.ecommerce-standalone .ecom-smart-editor__generate { + display: grid !important; + place-items: center !important; + color: #5f83ff !important; + font-size: 20px !important; + font-weight: 800 !important; + background: linear-gradient(135deg, #eefcff, #fff5ff) !important; +} + +.ecommerce-standalone .ecom-smart-editor__scenes button:not(.ecom-smart-editor__generate) { + background: + radial-gradient(circle at 22% 18%, rgba(30, 189, 219, 0.2), transparent 34%), + linear-gradient(135deg, #eef4f7, #d9e1e7) !important; +} + +.ecommerce-standalone .ecom-smart-editor__scenes button span { + position: absolute !important; + left: 10px !important; + bottom: 9px !important; + color: #243542 !important; + font-size: 12px !important; + font-weight: 800 !important; +} + +.ecommerce-standalone .ecom-smart-editor__side { + position: sticky !important; + top: 20px !important; + align-self: start !important; + display: grid !important; + gap: 18px !important; + padding: 10px 0 !important; + color: #1c2a35 !important; +} + +.ecommerce-standalone .ecom-smart-editor__side > strong { + font-size: 15px !important; + font-weight: 800 !important; +} + +.ecommerce-standalone .ecom-smart-editor__color-row { + display: flex !important; + flex-wrap: wrap !important; + gap: 9px !important; +} + +.ecommerce-standalone .ecom-smart-editor__color-row button, +.ecommerce-standalone .ecom-smart-editor__custom-color { + position: relative !important; + display: inline-flex !important; + align-items: center !important; + justify-content: center !important; + width: 44px !important; + height: 44px !important; + border: 1px solid rgba(16, 115, 204, 0.12) !important; + border-radius: 7px !important; + cursor: pointer !important; +} + +.ecommerce-standalone .ecom-smart-editor__color-wrap { + position: relative !important; + display: inline-flex !important; +} + +.ecommerce-standalone .ecom-smart-editor__color-row button.is-active, +.ecommerce-standalone .ecom-smart-editor__custom-color.is-active, +.ecommerce-standalone .ecom-smart-editor__custom-color:focus-visible { + border-color: #1073cc !important; + box-shadow: 0 0 0 3px rgba(30, 189, 219, 0.16) !important; +} + +.ecommerce-standalone .ecom-smart-editor__custom-color { + overflow: hidden !important; + color: #ffffff !important; + font-size: 12px !important; + font-weight: 800 !important; + text-shadow: 0 1px 3px rgba(0, 0, 0, 0.32) !important; +} + +.ecommerce-standalone .ecom-smart-editor__custom-color::before { + position: absolute !important; + inset: 0 !important; + content: "" !important; + background: + linear-gradient(135deg, rgba(255, 255, 255, 0.48), transparent 42%), + linear-gradient(135deg, transparent, rgba(0, 0, 0, 0.18)) !important; +} + +.ecommerce-standalone .ecom-smart-editor__custom-color span { + position: relative !important; + z-index: 1 !important; + pointer-events: none !important; +} + +.ecommerce-standalone .ecom-smart-color-picker { + position: absolute !important; + top: -6px !important; + left: calc(100% + 12px) !important; + z-index: 80 !important; + display: grid !important; + gap: 10px !important; + width: 266px !important; + padding: 14px !important; + border: 1px solid rgba(16, 115, 204, 0.12) !important; + border-radius: 14px !important; + background: #ffffff !important; + box-shadow: 0 22px 52px rgba(18, 34, 48, 0.16) !important; + animation: ecommerce-soft-popover-in 260ms cubic-bezier(0.16, 1, 0.3, 1) both !important; +} + +.ecommerce-standalone .ecom-smart-color-picker::after { + position: absolute !important; + top: 22px !important; + left: -7px !important; + width: 14px !important; + height: 14px !important; + border-top: 1px solid rgba(16, 115, 204, 0.12) !important; + border-left: 1px solid rgba(16, 115, 204, 0.12) !important; + border-right: 0 !important; + background: #ffffff !important; + content: "" !important; + transform: rotate(-45deg) !important; +} + +.ecommerce-standalone .ecom-smart-color-picker__plane { + position: relative !important; + width: 100% !important; + height: 140px !important; + overflow: hidden !important; + border: 0 !important; + border-radius: 10px !important; + cursor: crosshair !important; +} + +.ecommerce-standalone .ecom-smart-color-picker__plane span { + position: absolute !important; + width: 13px !important; + height: 13px !important; + border: 2px solid #ffffff !important; + border-radius: 50% !important; + box-shadow: 0 1px 4px rgba(0, 0, 0, 0.36) !important; + transform: translate(-50%, -50%) !important; + pointer-events: none !important; +} + +.ecommerce-standalone .ecom-smart-color-picker__slider { + position: relative !important; + display: grid !important; + grid-template-columns: 26px minmax(0, 1fr) !important; + align-items: center !important; + gap: 8px !important; +} + +.ecommerce-standalone .ecom-smart-color-picker__slider > span { + width: 24px !important; + height: 24px !important; + border: 1px solid rgba(16, 115, 204, 0.12) !important; + border-radius: 7px !important; + box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.42) !important; +} + +.ecommerce-standalone .ecom-smart-color-picker__slider input { + width: 100% !important; + height: 16px !important; + margin: 0 !important; + padding: 0 !important; + border: 0 !important; + border-radius: 999px !important; + appearance: none !important; + cursor: pointer !important; + accent-color: #1073cc !important; +} + +.ecommerce-standalone .ecom-smart-color-picker__slider--hue input { + background: linear-gradient(90deg, #ff2b2b, #ffed00, #1dd85b, #18c8ff, #2f55ff, #b12bff, #ff2b2b) !important; +} + +.ecommerce-standalone .ecom-smart-color-picker__slider--alpha input { + background: + linear-gradient(45deg, #d8dde1 25%, transparent 25%), + linear-gradient(-45deg, #d8dde1 25%, transparent 25%), + linear-gradient(45deg, transparent 75%, #d8dde1 75%), + linear-gradient(-45deg, transparent 75%, #d8dde1 75%), + linear-gradient(90deg, transparent, var(--smart-cutout-bg, #ffffff)) !important; + background-position: 0 0, 0 8px, 8px -8px, -8px 0, 0 0 !important; + background-size: 16px 16px, 16px 16px, 16px 16px, 16px 16px, 100% 100% !important; +} + +.ecommerce-standalone .ecom-smart-color-picker__slider input::-webkit-slider-thumb { + width: 14px !important; + height: 14px !important; + border: 2px solid #ffffff !important; + border-radius: 50% !important; + background: #ffffff !important; + appearance: none !important; + box-shadow: 0 1px 5px rgba(0, 0, 0, 0.24) !important; +} + +.ecommerce-standalone .ecom-smart-color-picker__slider input::-moz-range-thumb { + width: 14px !important; + height: 14px !important; + border: 2px solid #ffffff !important; + border-radius: 50% !important; + background: #ffffff !important; + box-shadow: 0 1px 5px rgba(0, 0, 0, 0.24) !important; +} + +.ecommerce-standalone .ecom-smart-color-picker__fields { + display: grid !important; + grid-template-columns: 1fr 1.4fr 56px 28px !important; + gap: 8px !important; + align-items: center !important; +} + +.ecommerce-standalone .ecom-smart-color-picker__fields span, +.ecommerce-standalone .ecom-smart-color-picker__fields input, +.ecommerce-standalone .ecom-smart-color-picker__fields strong { + min-width: 0 !important; + height: 30px !important; + border: 1px solid rgba(16, 115, 204, 0.12) !important; + border-radius: 7px !important; + color: #5b6b76 !important; + background: #ffffff !important; + font-size: 12px !important; + font-weight: 700 !important; +} + +.ecommerce-standalone .ecom-smart-color-picker__fields span, +.ecommerce-standalone .ecom-smart-color-picker__fields strong { + display: inline-flex !important; + align-items: center !important; + justify-content: center !important; +} + +.ecommerce-standalone .ecom-smart-color-picker__fields input { + width: 100% !important; + padding: 0 8px !important; + outline: none !important; +} + +.ecommerce-standalone .ecom-smart-color-picker p { + margin: 6px 0 0 !important; + color: #657481 !important; + font-size: 12px !important; + font-weight: 700 !important; +} + +.ecommerce-standalone .ecom-smart-color-picker__presets { + display: grid !important; + grid-template-columns: repeat(9, 20px) !important; + gap: 7px !important; +} + +.ecommerce-standalone .ecom-smart-color-picker__presets button { + width: 20px !important; + height: 20px !important; + min-height: 20px !important; + border-radius: 5px !important; + box-shadow: none !important; +} + +.ecommerce-standalone .ecom-smart-editor__side label { + display: flex !important; + align-items: center !important; + justify-content: space-between !important; + gap: 16px !important; + min-height: 34px !important; + color: #1f2e39 !important; + font-size: 14px !important; + font-weight: 800 !important; +} + +.ecommerce-standalone .ecom-smart-editor__side input { + width: 34px !important; + height: 18px !important; + accent-color: #1073cc !important; +} + +.ecommerce-standalone .ecom-smart-editor__side .ecom-smart-color-picker input { + accent-color: #1073cc !important; +} + +.ecommerce-standalone .ecom-smart-editor__side .ecom-smart-color-picker__slider input { + width: 100% !important; + height: 16px !important; +} + +.ecommerce-standalone .ecom-smart-editor__side .ecom-smart-color-picker__fields input { + width: 100% !important; + height: 30px !important; +} + +.ecommerce-standalone .ecom-smart-editor__link { + justify-self: start !important; + border: 0 !important; + color: #1f2e39 !important; + background: transparent !important; + font-size: 14px !important; + font-weight: 800 !important; +} + +.ecommerce-standalone .ecom-smart-editor__side-actions { + display: grid !important; + gap: 18px !important; + margin-top: 24px !important; +} + +.ecommerce-standalone .ecom-smart-editor__side-actions button { + min-height: 46px !important; + border: 0 !important; + border-radius: 9px !important; + color: #1f2e39 !important; + background: #f1f4f6 !important; + font-size: 15px !important; + font-weight: 800 !important; + cursor: pointer !important; +} + +.ecommerce-standalone .ecom-smart-editor__download { + color: #ffffff !important; + background: #1073cc !important; + box-shadow: 0 12px 24px rgba(16, 115, 204, 0.18) !important; +} + +@media (max-width: 1020px) { + .ecommerce-standalone .ecom-smart-cutout-upload__body, + .ecommerce-standalone .ecom-smart-editor { + grid-template-columns: 1fr !important; + } + + .ecommerce-standalone .ecom-smart-editor__tools { + grid-template-columns: repeat(6, minmax(0, 1fr)) !important; + } + + .ecommerce-standalone .ecom-smart-editor__swatches, + .ecommerce-standalone .ecom-smart-editor__scenes { + grid-template-columns: repeat(3, minmax(0, 1fr)) !important; + } +} + +@keyframes ecom-smart-transition-in { + from { + opacity: 0; + } + to { + opacity: 1; + } +} + +@keyframes ecom-smart-page-enter { + from { + opacity: 0; + transform: translateY(10px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +@keyframes ecom-tool-page-enter { + from { + opacity: 0; + transform: translateY(14px) scale(0.992); + filter: saturate(0.96); + } + to { + opacity: 1; + transform: translateY(0) scale(1); + filter: saturate(1); + } +} + +@keyframes ecom-tool-panel-enter { + from { + opacity: 0; + transform: translateY(16px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +@keyframes ecom-tool-side-enter { + from { + opacity: 0; + transform: translateX(-14px); + } + to { + opacity: 1; + transform: translateX(0); + } +} + +@keyframes ecom-tool-stage-enter { + from { + opacity: 0; + transform: translateX(16px); + } + to { + opacity: 1; + transform: translateX(0); + } +} + +.ecommerce-standalone .ecom-tool-page-enter { + animation: ecom-tool-page-enter 460ms cubic-bezier(0.16, 1, 0.3, 1) both !important; + will-change: opacity, transform; +} + +.ecommerce-standalone .ecom-tool-page-enter .ecom-quick-page-sidebar, +.ecommerce-standalone .ecom-tool-page-enter .ecom-quick-set-panel, +.ecommerce-standalone .ecom-tool-page-enter .ecom-watermark-side, +.ecommerce-standalone .ecom-tool-page-enter .ecom-image-workbench-side, +.ecommerce-standalone .ecom-tool-page-enter .ecom-smart-cutout-nav { + animation: ecom-tool-side-enter 430ms cubic-bezier(0.16, 1, 0.3, 1) 40ms both !important; +} + +.ecommerce-standalone .ecom-tool-page-enter .ecom-quick-set-stage, +.ecommerce-standalone .ecom-tool-page-enter .ecom-watermark-workspace, +.ecommerce-standalone .ecom-tool-page-enter .ecom-image-workbench-stage, +.ecommerce-standalone .ecom-tool-page-enter .ecom-smart-cutout-upload, +.ecommerce-standalone .ecom-tool-page-enter .ecom-smart-editor { + animation: ecom-tool-stage-enter 500ms cubic-bezier(0.16, 1, 0.3, 1) 90ms both !important; +} + +.ecommerce-standalone .ecom-tool-page-enter .ecom-quick-set-panel > section, +.ecommerce-standalone .ecom-tool-page-enter .ecom-watermark-panel, +.ecommerce-standalone .ecom-tool-page-enter .ecom-image-workbench-panel { + animation: ecom-tool-panel-enter 420ms cubic-bezier(0.16, 1, 0.3, 1) both !important; +} + +.ecommerce-standalone .ecom-tool-page-enter .ecom-quick-set-panel > section:nth-of-type(1), +.ecommerce-standalone .ecom-tool-page-enter .ecom-watermark-panel:nth-of-type(1), +.ecommerce-standalone .ecom-tool-page-enter .ecom-image-workbench-panel:nth-of-type(1) { + animation-delay: 80ms !important; +} + +.ecommerce-standalone .ecom-tool-page-enter .ecom-quick-set-panel > section:nth-of-type(2), +.ecommerce-standalone .ecom-tool-page-enter .ecom-watermark-panel:nth-of-type(2), +.ecommerce-standalone .ecom-tool-page-enter .ecom-image-workbench-panel:nth-of-type(2) { + animation-delay: 130ms !important; +} + +.ecommerce-standalone .ecom-tool-page-enter .ecom-quick-set-panel > section:nth-of-type(3), +.ecommerce-standalone .ecom-tool-page-enter .ecom-image-workbench-panel:nth-of-type(3) { + animation-delay: 180ms !important; +} + +@keyframes ecom-smart-upload-enter { + from { + opacity: 0; + transform: translateY(14px) scale(0.992); + } + to { + opacity: 1; + transform: translateY(0) scale(1); + } +} + +@keyframes ecom-smart-transition-spin { + to { + transform: rotate(360deg); + } +} + +@keyframes ecom-smart-page-hold { + 0% { + opacity: 1; + transform: scale(1); + } + 100% { + opacity: 0.72; + transform: scale(0.985); + } +} + +@keyframes ecom-smart-editor-enter { + from { + opacity: 0; + transform: translateY(18px) scale(0.985); + } + to { + opacity: 1; + transform: translateY(0) scale(1); + } +} + +/* Final composer layering and stateful canvas texture guards. */ +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-composer-wrap { + overflow: visible !important; + z-index: 60 !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .clone-ai-input-wrapper.ecom-command-composer { + position: relative !important; + z-index: 30 !important; + overflow: visible !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover { + z-index: 120 !important; + background: #feffff !important; + box-shadow: 0 22px 54px rgba(16, 115, 204, 0.16), 0 0 0 1px rgba(30, 189, 219, 0.16) !important; + animation: ecommerce-soft-popover-in 420ms cubic-bezier(0.16, 1, 0.3, 1) both !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-popover.is-closing { + pointer-events: none !important; + animation: ecommerce-soft-popover-out 220ms cubic-bezier(0.4, 0, 0.2, 1) both !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-quick-board { + position: relative !important; + z-index: 0 !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .clone-ai-preview { + background: #f8f9fa !important; + transition: padding-top 520ms cubic-bezier(0.16, 1, 0.3, 1), + background 640ms ease !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .clone-ai-preview[data-status="generating"], +.ecommerce-standalone .product-clone-page[data-tool="clone"] .clone-ai-preview[data-status="done"] { + background: + radial-gradient(circle at 18% 18%, rgba(30, 189, 219, 0.08), transparent 24rem), + radial-gradient(circle at 82% 28%, rgba(16, 115, 204, 0.06), transparent 22rem), + linear-gradient(rgba(16, 115, 204, 0.035) 1px, transparent 1px), + linear-gradient(90deg, rgba(16, 115, 204, 0.035) 1px, transparent 1px), + #f8f9fa !important; + background-size: auto, auto, 28px 28px, 28px 28px, auto !important; +} + +.ecommerce-standalone .ecom-smart-editor__background-layer { + background-image: none !important; + background-color: var(--smart-cutout-bg, #ffffff) !important; +} + +/* P0 page polish: premium AI commerce landing surface without touching logic. */ +.ecommerce-standalone__topbar { + min-height: 66px !important; + border-bottom-color: rgba(30, 189, 219, 0.18) !important; + background: rgba(248, 249, 250, 0.86) !important; + box-shadow: 0 12px 36px rgba(16, 115, 204, 0.055) !important; + backdrop-filter: blur(18px) saturate(1.12) !important; + -webkit-backdrop-filter: blur(18px) saturate(1.12) !important; +} + +.ecommerce-standalone__brand { + min-height: 40px !important; +} + +.ecommerce-standalone__brand strong { + letter-spacing: 0 !important; +} + +.ecommerce-standalone__account button { + min-height: 40px !important; + border-radius: 12px !important; + box-shadow: 0 10px 24px rgba(16, 115, 204, 0.055) !important; + transition: border-color 180ms ease, background 180ms ease, box-shadow 180ms ease, transform 180ms ease !important; +} + +.ecommerce-standalone__account button:hover { + box-shadow: 0 14px 32px rgba(30, 189, 219, 0.12) !important; + transform: translateY(-1px) !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"]::before { + opacity: 0.82 !important; + filter: blur(70px) saturate(1.08) !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .clone-ai-preview { + background: + radial-gradient(circle at 19% 8%, rgba(30, 189, 219, 0.13), transparent 24rem), + radial-gradient(circle at 82% 11%, rgba(16, 115, 204, 0.09), transparent 26rem), + linear-gradient(180deg, #fbfdfe 0%, #f8f9fa 54%, #f5f9fb 100%) !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-title { + color: #10202c !important; + text-wrap: balance !important; + text-shadow: 0 1px 0 rgba(255, 255, 255, 0.72) !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .clone-ai-input-wrapper.ecom-command-composer { + border-color: rgba(30, 189, 219, 0.24) !important; + background: + linear-gradient(180deg, rgba(255, 255, 255, 0.98), rgba(251, 253, 254, 0.94)), + #feffff !important; + box-shadow: + 0 24px 70px rgba(16, 115, 204, 0.11), + 0 10px 26px rgba(30, 189, 219, 0.06), + inset 0 1px 0 rgba(255, 255, 255, 0.98) !important; + transition: border-color 180ms ease, box-shadow 180ms ease, transform 180ms ease !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .clone-ai-input-wrapper.ecom-command-composer:focus-within { + border-color: rgba(30, 189, 219, 0.46) !important; + box-shadow: + 0 30px 82px rgba(16, 115, 204, 0.14), + 0 0 0 4px rgba(30, 189, 219, 0.09), + inset 0 1px 0 rgba(255, 255, 255, 1) !important; + transform: translateY(-1px) !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-composer textarea { + color: #10202c !important; + caret-color: #1ebddb !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-composer textarea::placeholder { + color: #7b929e !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-reference, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-option-row button, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-history__tools button, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-history__list button { + transition: + border-color 180ms ease, + background 180ms ease, + color 180ms ease, + box-shadow 180ms ease, + transform 180ms ease !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-option-row button:hover, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-option-row button.is-active { + box-shadow: 0 10px 22px rgba(30, 189, 219, 0.08) !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-send { + background: linear-gradient(135deg, #1073cc 0%, #1ebddb 100%) !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-send:hover:not(:disabled) { + box-shadow: 0 18px 38px rgba(30, 189, 219, 0.28) !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-send:disabled { + border-color: rgba(30, 189, 219, 0.18) !important; + background: #eef6f8 !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-quick-board { + gap: 0 !important; + border-color: rgba(30, 189, 219, 0.16) !important; + background: rgba(254, 255, 255, 0.96) !important; + box-shadow: + 0 22px 56px rgba(16, 115, 204, 0.09), + inset 0 1px 0 rgba(255, 255, 255, 0.95) !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-quick-board button { + isolation: isolate !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-quick-board button::before, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-quick-board button::after { + pointer-events: none !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-quick-board button span { + width: 30px !important; + height: 30px !important; + border: 1px solid rgba(30, 189, 219, 0.16) !important; + border-radius: 10px !important; + background: rgba(30, 189, 219, 0.075) !important; + color: #1073cc !important; + font-size: 16px !important; + transition: border-color 180ms ease, background 180ms ease, color 180ms ease, transform 180ms ease !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-quick-board button strong { + max-width: 100% !important; + letter-spacing: 0 !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-quick-board button:hover { + color: #0f6678 !important; + background: linear-gradient(180deg, rgba(30, 189, 219, 0.12), rgba(30, 189, 219, 0.055)) !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-quick-board button:hover span { + border-color: rgba(30, 189, 219, 0.36) !important; + background: #ffffff !important; + color: #1ebddb !important; + transform: translateY(-1px) !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-history { + border-left-color: rgba(30, 189, 219, 0.14) !important; + background: rgba(254, 255, 255, 0.9) !important; + box-shadow: -18px 0 46px rgba(16, 115, 204, 0.065) !important; + backdrop-filter: blur(18px) saturate(1.08) !important; + -webkit-backdrop-filter: blur(18px) saturate(1.08) !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-history__heading, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-history__empty, +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-history__list button { + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.82) !important; +} + +.ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-history__empty { + color: #6d8592 !important; + background: + linear-gradient(180deg, rgba(255, 255, 255, 0.78), rgba(248, 249, 250, 0.92)), + #f8f9fa !important; +} + +@media (max-width: 900px) { + .ecommerce-standalone .product-clone-page[data-tool="clone"] { + padding-right: 0 !important; + } + + .ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-composer-wrap.is-before-generate { + left: 18px !important; + right: 18px !important; + width: auto !important; + transform: none !important; + } + + .ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-history { + display: none !important; + } + + .ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-quick-board { + grid-template-columns: repeat(3, minmax(0, 1fr)) !important; + min-height: 224px !important; + } + + .ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-quick-board button:not(:nth-child(6n + 1))::before { + content: none !important; + } + + .ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-quick-board button:not(:nth-child(3n + 1))::before { + position: absolute !important; + top: 14px !important; + bottom: 14px !important; + left: 0 !important; + width: 1px !important; + content: "" !important; + background: rgba(30, 189, 219, 0.12) !important; + } + + .ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-quick-board button:nth-child(n + 4)::after { + position: absolute !important; + top: 0 !important; + left: 14px !important; + right: 14px !important; + height: 1px !important; + content: "" !important; + background: rgba(30, 189, 219, 0.12) !important; + } +} + +@media (max-width: 640px) { + .ecommerce-standalone__topbar { + min-height: 60px !important; + } + + .ecommerce-standalone .product-clone-page[data-tool="clone"] .clone-ai-preview { + padding-inline: 18px !important; + } + + .ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-title { + font-size: clamp(26px, 8vw, 34px) !important; + } + + .ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-quick-board { + grid-template-columns: repeat(2, minmax(0, 1fr)) !important; + min-height: 300px !important; + } + + .ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-quick-board button:not(:nth-child(3n + 1))::before { + content: none !important; + } + + .ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-quick-board button:not(:nth-child(2n + 1))::before { + position: absolute !important; + top: 14px !important; + bottom: 14px !important; + left: 0 !important; + width: 1px !important; + content: "" !important; + background: rgba(30, 189, 219, 0.12) !important; + } + + .ecommerce-standalone .product-clone-page[data-tool="clone"] .ecom-command-quick-board button:nth-child(n + 3)::after { + position: absolute !important; + top: 0 !important; + left: 14px !important; + right: 14px !important; + height: 1px !important; + content: "" !important; + background: rgba(30, 189, 219, 0.12) !important; + } +} + +@keyframes ecommerce-soft-popover-out { + from { + opacity: 1; + filter: blur(0); + transform: translate3d(0, 0, 0) scale(1); + } + to { + opacity: 0; + filter: blur(1px); + transform: translate3d(0, 8px, 0) scale(0.982); + } +} + +/* ---- Typewriter cursor blink ---- */ +.typewriter-cursor { + display: inline-block; + color: #1ebddb; + font-weight: 400; + animation: typewriter-blink 0.8s steps(1) infinite; +} + +@keyframes typewriter-blink { + 0%, 100% { opacity: 1; } + 50% { opacity: 0; } +} + +/* #/imageWorkbench narrow viewport alignment and history drawer access. */ +@media (max-width: 1180px) { + .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] { + --ecom-history-offset: 0px !important; + padding-right: 0 !important; + } + + .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .clone-ai-preview.clone-ai-preview { + width: 100% !important; + max-width: none !important; + justify-items: center !important; + } + + .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-composer-wrap.ecom-command-composer-wrap { + left: 50% !important; + right: auto !important; + width: min(920px, calc(100vw - 48px)) !important; + max-width: calc(100vw - 48px) !important; + transform: translateX(-50%) !important; + } + + .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"]:not(.is-history-collapsed) { + overflow: hidden !important; + } + + .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] > .product-clone-shell.product-clone-shell { + transition: + filter 260ms ease, + opacity 260ms ease, + transform 260ms ease !important; + } + + .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"]:not(.is-history-collapsed) > .product-clone-shell.product-clone-shell { + filter: blur(12px) saturate(0.94) !important; + opacity: 0.36 !important; + transform: scale(0.992) !important; + pointer-events: none !important; + user-select: none !important; + } + + .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-history.ecom-command-history { + position: fixed !important; + top: 0 !important; + right: 0 !important; + bottom: 0 !important; + z-index: 120 !important; + display: grid !important; + width: min(292px, calc(100vw - 72px)) !important; + border-top-left-radius: 22px !important; + border-left-color: rgba(30, 189, 219, 0.28) !important; + background: + linear-gradient(180deg, rgba(240, 250, 255, 0.92), rgba(226, 243, 255, 0.9)), + rgba(254, 255, 255, 0.94) !important; + box-shadow: + -28px 0 72px rgba(16, 115, 204, 0.18), + -1px 0 0 rgba(255, 255, 255, 0.8) inset !important; + backdrop-filter: blur(22px) saturate(1.12) !important; + -webkit-backdrop-filter: blur(22px) saturate(1.12) !important; + transform: translateX(0) !important; + pointer-events: auto !important; + } + + .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"].is-history-collapsed .ecom-command-history.ecom-command-history { + display: grid !important; + transform: translateX(100%) !important; + } + + .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"].is-history-collapsed .ecom-command-history__toggle.ecom-command-history__toggle { + position: absolute !important; + top: 50% !important; + left: -52px !important; + z-index: 130 !important; + display: inline-flex !important; + visibility: visible !important; + opacity: 1 !important; + pointer-events: auto !important; + } +} + +@media (max-width: 640px) { + .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .clone-ai-preview.clone-ai-preview { + padding-inline: 0 !important; + } + + .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-composer-wrap.ecom-command-composer-wrap { + width: calc(100vw - 32px) !important; + max-width: calc(100vw - 32px) !important; + } + + .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-history.ecom-command-history { + top: 0 !important; + width: min(300px, calc(100vw - 58px)) !important; + } + + .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"].is-history-collapsed .ecom-command-history__toggle.ecom-command-history__toggle { + left: -46px !important; + width: 40px !important; + height: 40px !important; + min-height: 40px !important; + } +} + +/* #/imageWorkbench mobile composer spacing refinement. */ +@media (max-width: 640px) { + .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-composer-wrap.ecom-command-composer-wrap.is-before-generate { + top: clamp(26px, 5.6vh, 42px) !important; + gap: 18px !important; + } + + .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-title.ecom-command-title { + max-width: min(100%, 520px) !important; + margin-inline: auto !important; + background: + linear-gradient(96deg, #284a56 0%, #4f7f88 42%, #28a8bd 100%) !important; + -webkit-background-clip: text !important; + background-clip: text !important; + color: transparent !important; + font-size: clamp(26px, 6.4vw, 34px) !important; + line-height: 1.18 !important; + text-align: center !important; + text-shadow: 0 16px 38px rgba(40, 168, 189, 0.14) !important; + text-wrap: balance; + white-space: normal !important; + } + + .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .clone-ai-input-wrapper.ecom-command-composer { + min-height: 0 !important; + grid-template-columns: minmax(0, 1fr) !important; + grid-template-rows: auto auto !important; + align-items: stretch !important; + gap: 12px !important; + padding: 16px !important; + border-radius: 24px !important; + } + + .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-composer textarea { + min-height: 74px !important; + height: 74px !important; + padding: 8px 0 2px !important; + line-height: 1.6 !important; + } + + .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-toolbar { + display: flex !important; + flex-direction: column !important; + align-items: stretch !important; + justify-content: flex-start !important; + gap: 10px !important; + padding-top: 10px !important; + } + + .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-option-row { + display: grid !important; + grid-template-columns: repeat(6, 44px) !important; + flex-wrap: nowrap !important; + align-items: center !important; + justify-content: center !important; + gap: 8px !important; + width: 100% !important; + } + + .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-option-row button, + .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-upload-inline { + flex: 0 0 44px !important; + width: 44px !important; + min-width: 44px !important; + max-width: 44px !important; + height: 44px !important; + min-height: 44px !important; + justify-content: center !important; + gap: 0 !important; + padding: 0 !important; + overflow: hidden !important; + border-radius: 15px !important; + font-size: 0 !important; + } + + .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-option-row button:not(.ecom-command-reference--inline) > span:not(.ecom-command-option-icon), + .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-reference--inline strong { + display: none !important; + } + + .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-option-row .ecom-command-option-icon, + .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-reference--inline > span { + display: inline-flex !important; + width: 26px !important; + height: 26px !important; + align-items: center !important; + justify-content: center !important; + margin: 0 !important; + border-radius: 10px !important; + font-size: 16px !important; + } + + .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-submit-row { + align-self: flex-end !important; + justify-content: flex-end !important; + width: auto !important; + min-width: 46px !important; + margin-top: 0 !important; + } + + .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .clone-ai-send-button.ecom-command-send { + width: 46px !important; + height: 46px !important; + min-width: 46px !important; + min-height: 46px !important; + } +} + +@media (max-width: 420px) { + .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-composer-wrap.ecom-command-composer-wrap.is-before-generate { + top: clamp(72px, 9vh, 88px) !important; + } + + .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-title.ecom-command-title { + font-size: clamp(24px, 7.2vw, 30px) !important; + } + + .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-option-row button, + .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-upload-inline { + flex-basis: 42px !important; + width: 42px !important; + min-width: 42px !important; + max-width: 42px !important; + height: 42px !important; + min-height: 42px !important; + padding: 0 !important; + } +} + +/* #/imageWorkbench mobile header, headline, and upload clarity. */ +@media (max-width: 640px) { + .ecommerce-standalone.ecommerce-standalone .ecommerce-standalone__topbar { + display: grid !important; + grid-template-columns: minmax(116px, 1fr) auto !important; + align-items: center !important; + gap: 8px !important; + min-height: 62px !important; + padding: 8px 12px !important; + } + + .ecommerce-standalone.ecommerce-standalone .ecommerce-standalone__brand { + min-width: 0 !important; + gap: 8px !important; + padding: 0 !important; + } + + .ecommerce-standalone.ecommerce-standalone .ecommerce-standalone__logo { + flex: 0 0 36px !important; + width: 36px !important; + height: 36px !important; + } + + .ecommerce-standalone.ecommerce-standalone .ecommerce-standalone__brand strong { + min-width: 0 !important; + overflow: hidden !important; + color: #10202c !important; + font-size: 15px !important; + font-weight: 900 !important; + line-height: 1.08 !important; + text-overflow: ellipsis !important; + white-space: normal !important; + word-break: keep-all !important; + } + + .ecommerce-standalone.ecommerce-standalone .ecommerce-standalone__account { + min-width: 0 !important; + gap: 6px !important; + justify-content: flex-end !important; + } + + .ecommerce-standalone.ecommerce-standalone .ecommerce-standalone__credits { + display: inline-flex !important; + align-items: center !important; + justify-content: center !important; + min-width: 0 !important; + max-width: 94px !important; + min-height: 38px !important; + padding-inline: 10px !important; + overflow: hidden !important; + font-size: 13px !important; + font-weight: 800 !important; + text-overflow: ellipsis !important; + white-space: nowrap !important; + } + + .ecommerce-standalone.ecommerce-standalone .ecommerce-profile-menu__trigger { + min-width: 46px !important; + min-height: 40px !important; + padding: 0 7px !important; + } + + .ecommerce-standalone.ecommerce-standalone .ecommerce-profile-menu__trigger > span:not(.local-user-avatar) { + max-width: 58px !important; + overflow: hidden !important; + text-overflow: ellipsis !important; + white-space: nowrap !important; + } + + .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-title.ecom-command-title { + max-width: min(92vw, 520px) !important; + background: linear-gradient(92deg, #10202c 0%, #123d5a 46%, #1073cc 72%, #1ebddb 100%) !important; + -webkit-background-clip: text !important; + background-clip: text !important; + color: transparent !important; + text-shadow: 0 16px 40px rgba(16, 115, 204, 0.12) !important; + } + + .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-reference:not(.ecom-command-reference--inline) { + min-height: 54px !important; + grid-auto-flow: column !important; + grid-template-columns: auto minmax(0, auto) !important; + justify-content: center !important; + gap: 10px !important; + border-style: solid !important; + background: + linear-gradient(180deg, rgba(245, 253, 255, 0.98), rgba(231, 249, 254, 0.92)) !important; + } + + .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-reference:not(.ecom-command-reference--inline) span { + font-size: 18px !important; + } + + .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-reference:not(.ecom-command-reference--inline) strong { + max-width: none !important; + font-size: 13px !important; + white-space: nowrap !important; + } + + .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-reference--inline { + order: -1 !important; + flex-basis: 100% !important; + justify-content: center !important; + gap: 8px !important; + color: #0f6678 !important; + border-color: rgba(30, 189, 219, 0.32) !important; + background: + linear-gradient(180deg, rgba(241, 252, 255, 0.98), rgba(229, 248, 253, 0.92)) !important; + } + + .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-reference--inline span { + font-size: 16px !important; + } +} + +@media (max-width: 360px) { + .ecommerce-standalone.ecommerce-standalone .ecommerce-standalone__topbar { + grid-template-columns: minmax(92px, 1fr) auto !important; + gap: 6px !important; + padding-inline: 10px !important; + } + + .ecommerce-standalone.ecommerce-standalone .ecommerce-standalone__brand strong { + font-size: 0 !important; + } + + .ecommerce-standalone.ecommerce-standalone .ecommerce-standalone__brand strong::before { + content: "OmniAI" !important; + font-size: 15px !important; + } + + .ecommerce-standalone.ecommerce-standalone .ecommerce-standalone__credits { + max-width: 88px !important; + min-height: 36px !important; + font-size: 12px !important; + } + + .ecommerce-standalone.ecommerce-standalone .ecommerce-profile-menu__trigger { + width: 42px !important; + min-width: 42px !important; + padding: 0 !important; + } + + .ecommerce-standalone.ecommerce-standalone .ecommerce-profile-menu__trigger > span:not(.local-user-avatar) { + display: none !important; + } +} + +/* #/imageWorkbench unified headline tone and asset removal affordance. */ +.ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-title.ecom-command-title { + max-width: min(920px, 92vw) !important; + margin-inline: auto !important; + background: + linear-gradient(96deg, #10202c 0%, #164359 36%, #0f829b 68%, #18bfd2 100%) !important; + -webkit-background-clip: text !important; + background-clip: text !important; + color: transparent !important; + text-shadow: 0 18px 46px rgba(15, 130, 155, 0.13) !important; +} + +.ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .typewriter-cursor { + color: #18bfd2 !important; + text-shadow: 0 0 18px rgba(24, 191, 210, 0.28) !important; +} + +.ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-asset-thumb > button { + width: 30px !important; + height: 30px !important; + min-width: 30px !important; + min-height: 30px !important; + border: 1px solid rgba(255, 255, 255, 0.78) !important; + border-radius: 999px !important; + background: + linear-gradient(135deg, rgba(202, 53, 84, 0.96), rgba(145, 42, 68, 0.96)) !important; + box-shadow: + 0 12px 28px rgba(145, 42, 68, 0.24), + inset 0 1px 0 rgba(255, 255, 255, 0.32) !important; + color: #fff !important; + opacity: 0 !important; + pointer-events: none !important; + transform: translate(6px, -6px) scale(0.92) !important; + transition: + opacity 160ms ease, + transform 160ms ease, + box-shadow 160ms ease, + visibility 160ms ease !important; + visibility: hidden !important; +} + +.ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-asset-thumb:hover > button, +.ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-asset-thumb:focus-within > button { + opacity: 1 !important; + pointer-events: auto !important; + transform: translate(0, 0) scale(1) !important; + visibility: visible !important; +} + +.ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-asset-thumb > button:hover { + box-shadow: + 0 14px 32px rgba(145, 42, 68, 0.32), + inset 0 1px 0 rgba(255, 255, 255, 0.38) !important; + transform: translate(0, 0) scale(1.04) !important; +} + +.ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-asset-thumb > button .anticon { + font-size: 14px !important; +} + +/* Quick tools polish: refined layout, controls, and preview surfaces. */ +.ecommerce-standalone .ecom-quick-page-wrap, +.ecommerce-standalone .ecom-quick-set-page, +.ecommerce-standalone .ecom-watermark-page, +.ecommerce-standalone .ecom-image-workbench-page { + --quick-border: rgba(26, 74, 108, 0.11); + --quick-border-strong: rgba(16, 115, 204, 0.2); + --quick-surface: #ffffff; + --quick-surface-soft: #f7f9fb; + --quick-surface-tint: #edf8ff; + --quick-text: #162535; + --quick-muted: #657686; + --quick-accent: #1073cc; + --quick-cyan: #1ebddb; +} + +.ecommerce-standalone .ecom-quick-page-wrap { + background: + linear-gradient(90deg, rgba(255, 255, 255, 0.82), transparent 420px), + linear-gradient(rgba(16, 115, 204, 0.025) 1px, transparent 1px), + linear-gradient(90deg, rgba(16, 115, 204, 0.02) 1px, transparent 1px), + #f6f8fa !important; + background-size: auto, 28px 28px, 28px 28px, auto !important; +} + +.ecommerce-standalone .ecom-quick-page-sidebar { + width: 76px !important; + flex: 0 0 76px !important; + gap: 8px !important; + padding: 16px 8px !important; + border-right: 1px solid var(--quick-border) !important; + background: + linear-gradient(180deg, rgba(255, 255, 255, 0.98), rgba(248, 251, 253, 0.94)) !important; + box-shadow: 10px 0 28px rgba(16, 115, 204, 0.04) !important; +} + +.ecommerce-standalone .ecom-quick-page-sidebar button { + min-height: 64px !important; + padding: 8px 4px !important; + border: 1px solid transparent !important; + border-radius: 8px !important; + color: #506475 !important; + background: transparent !important; + box-shadow: none !important; +} + +.ecommerce-standalone .ecom-quick-page-sidebar button:hover { + border-color: rgba(30, 189, 219, 0.18) !important; + background: rgba(237, 248, 255, 0.82) !important; + box-shadow: 0 8px 18px rgba(16, 115, 204, 0.08) !important; +} + +.ecommerce-standalone .ecom-quick-page-sidebar button.is-active { + border-color: rgba(16, 115, 204, 0.22) !important; + color: var(--quick-accent) !important; + background: linear-gradient(180deg, #edf8ff, #f8fdff) !important; + box-shadow: 0 10px 24px rgba(16, 115, 204, 0.1) !important; +} + +.ecommerce-standalone .ecom-quick-page-sidebar button.is-active::before { + left: -8px !important; + top: 12px !important; + bottom: 12px !important; + width: 3px !important; + border-radius: 999px !important; + background: linear-gradient(180deg, var(--quick-cyan), var(--quick-accent)) !important; +} + +.ecommerce-standalone .ecom-quick-set-body { + grid-template-columns: minmax(386px, 420px) minmax(0, 1fr) !important; + background: transparent !important; +} + +.ecommerce-standalone .ecom-hot-video-page .ecom-quick-set-body { + grid-template-columns: minmax(366px, 404px) minmax(0, 1fr) !important; +} + +.ecommerce-standalone .ecom-quick-set-panel, +.ecommerce-standalone .ecom-watermark-side, +.ecommerce-standalone .ecom-image-workbench-side { + gap: 12px !important; + padding: 18px 16px !important; + border-color: var(--quick-border) !important; + border-radius: 0 !important; + background: + linear-gradient(180deg, rgba(247, 250, 252, 0.92), transparent 150px), + var(--quick-surface) !important; + box-shadow: 12px 0 32px rgba(16, 115, 204, 0.045) !important; + scrollbar-width: thin !important; + scrollbar-color: rgba(16, 115, 204, 0.32) transparent !important; +} + +.ecommerce-standalone .ecom-watermark-side, +.ecommerce-standalone .ecom-image-workbench-side { + border-radius: 8px !important; + box-shadow: 0 14px 34px rgba(16, 115, 204, 0.07) !important; +} + +.ecommerce-standalone .ecom-quick-set-panel-head { + position: sticky !important; + top: -18px !important; + z-index: 12 !important; + min-height: 42px !important; + margin: -18px -16px 2px !important; + padding: 14px 16px 10px !important; + border-bottom: 1px solid rgba(16, 115, 204, 0.08) !important; + background: rgba(255, 255, 255, 0.92) !important; + backdrop-filter: blur(14px) !important; + -webkit-backdrop-filter: blur(14px) !important; +} + +.ecommerce-standalone .ecom-quick-set-page-title { + color: var(--quick-text) !important; + font-size: 18px !important; + font-weight: 950 !important; + line-height: 1.2 !important; +} + +.ecommerce-standalone .ecom-quick-set-back { + min-height: 30px !important; + padding: 0 10px !important; + border: 1px solid rgba(16, 115, 204, 0.12) !important; + border-radius: 8px !important; + color: #526474 !important; + background: #f7fafc !important; + box-shadow: none !important; +} + +.ecommerce-standalone .ecom-quick-set-back:hover { + border-color: rgba(30, 189, 219, 0.32) !important; + color: var(--quick-accent) !important; + background: var(--quick-surface-tint) !important; +} + +.ecommerce-standalone .ecom-watermark-intro, +.ecommerce-standalone .ecom-image-workbench-intro { + margin: 0 2px 2px !important; + color: var(--quick-muted) !important; + font-size: 12px !important; + font-weight: 750 !important; + line-height: 1.65 !important; +} + +.ecommerce-standalone .ecom-quick-set-panel section, +.ecommerce-standalone .ecom-watermark-panel, +.ecommerce-standalone .ecom-image-workbench-panel { + gap: 10px !important; + padding: 13px !important; + border: 1px solid var(--quick-border) !important; + border-radius: 8px !important; + background: #ffffff !important; + box-shadow: none !important; +} + +.ecommerce-standalone .ecom-quick-set-panel section > strong, +.ecommerce-standalone .ecom-watermark-panel > strong, +.ecommerce-standalone .ecom-image-workbench-panel > strong, +.ecommerce-standalone .ecom-quick-set-panel section header strong, +.ecommerce-standalone .ecom-watermark-panel header strong, +.ecommerce-standalone .ecom-image-workbench-panel header strong { + color: var(--quick-text) !important; + font-size: 13px !important; + font-weight: 950 !important; +} + +.ecommerce-standalone .ecom-quick-set-panel header span, +.ecommerce-standalone .ecom-watermark-panel header span, +.ecommerce-standalone .ecom-image-workbench-panel header span { + border-radius: 999px !important; + color: #276987 !important; + background: #eef7fa !important; +} + +.ecommerce-standalone .ecom-quick-set-upload, +.ecommerce-standalone .ecom-watermark-upload-card, +.ecommerce-standalone .ecom-image-workbench-upload { + min-height: 112px !important; + border-color: rgba(30, 189, 219, 0.34) !important; + border-radius: 8px !important; + background: + linear-gradient(180deg, rgba(237, 248, 255, 0.72), rgba(255, 255, 255, 0.94)) !important; + transition: + border-color 160ms ease, + background 160ms ease, + box-shadow 160ms ease, + transform 160ms ease !important; +} + +.ecommerce-standalone .ecom-quick-set-upload:hover, +.ecommerce-standalone .ecom-watermark-upload-card:hover, +.ecommerce-standalone .ecom-image-workbench-upload:hover, +.ecommerce-standalone .ecom-watermark-upload-card.is-dragging, +.ecommerce-standalone .ecom-image-workbench-upload.is-dragging { + border-color: var(--quick-cyan) !important; + background: #f7fcff !important; + box-shadow: 0 10px 24px rgba(16, 115, 204, 0.09) !important; + transform: translateY(-1px) !important; +} + +.ecommerce-standalone .ecom-quick-upload-thumbs { + width: 100% !important; + padding-top: 4px !important; + justify-content: center !important; +} + +.ecommerce-standalone .ecom-command-asset-thumb.ecom-quick-upload-thumb { + border-radius: 8px !important; + box-shadow: 0 6px 16px rgba(16, 115, 204, 0.08) !important; +} + +.ecommerce-standalone .ecom-quick-set-selects button, +.ecommerce-standalone .ecom-quick-detail-types button, +.ecommerce-standalone .ecom-hot-video-options button, +.ecommerce-standalone .ecom-quick-detail-modules button, +.ecommerce-standalone .ecom-quick-set-counts article, +.ecommerce-standalone .ecom-image-workbench-ratios, +.ecommerce-standalone .ecom-image-workbench-clear, +.ecommerce-standalone .ecom-watermark-url-row input, +.ecommerce-standalone .ecom-image-workbench-url-row input, +.ecommerce-standalone .ecom-quick-set-panel textarea, +.ecommerce-standalone .ecom-image-workbench-panel textarea { + border-radius: 8px !important; +} + +.ecommerce-standalone .ecom-quick-set-selects button, +.ecommerce-standalone .ecom-quick-detail-types button, +.ecommerce-standalone .ecom-hot-video-options button, +.ecommerce-standalone .ecom-quick-detail-modules button, +.ecommerce-standalone .ecom-quick-set-counts article { + border-color: var(--quick-border) !important; + background: var(--quick-surface-soft) !important; + transition: + border-color 160ms ease, + background 160ms ease, + box-shadow 160ms ease, + transform 160ms ease !important; +} + +.ecommerce-standalone .ecom-quick-set-selects button:hover, +.ecommerce-standalone .ecom-quick-detail-types button:hover, +.ecommerce-standalone .ecom-hot-video-options button:hover, +.ecommerce-standalone .ecom-quick-detail-modules button:hover, +.ecommerce-standalone .ecom-quick-set-counts article:hover { + border-color: rgba(16, 115, 204, 0.24) !important; + background: #ffffff !important; + box-shadow: 0 8px 18px rgba(16, 115, 204, 0.07) !important; +} + +.ecommerce-standalone .ecom-quick-set-selects button.is-active, +.ecommerce-standalone .ecom-quick-detail-types button.is-active, +.ecommerce-standalone .ecom-hot-video-options button.is-active, +.ecommerce-standalone .ecom-quick-detail-modules button.is-active { + border-color: rgba(16, 115, 204, 0.34) !important; + background: linear-gradient(180deg, #edf8ff, #f8fdff) !important; + box-shadow: inset 0 0 0 1px rgba(30, 189, 219, 0.08), 0 8px 18px rgba(16, 115, 204, 0.07) !important; +} + +.ecommerce-standalone .ecom-quick-set-counts p { + border-radius: 8px !important; + background: #ffffff !important; +} + +.ecommerce-standalone .ecom-quick-set-counts p button:disabled { + color: #b3c1ca !important; + cursor: not-allowed !important; +} + +.ecommerce-standalone .ecom-quick-set-primary, +.ecommerce-standalone .ecom-watermark-primary, +.ecommerce-standalone .ecom-image-workbench-primary { + min-height: 48px !important; + border-radius: 8px !important; + background: linear-gradient(135deg, #0f6fbd 0%, #19adc8 100%) !important; + box-shadow: 0 12px 28px rgba(16, 115, 204, 0.18) !important; + transition: + transform 160ms ease, + box-shadow 160ms ease, + filter 160ms ease !important; +} + +.ecommerce-standalone .ecom-quick-set-primary:hover:not(:disabled), +.ecommerce-standalone .ecom-watermark-primary:hover:not(:disabled), +.ecommerce-standalone .ecom-image-workbench-primary:hover:not(:disabled) { + box-shadow: 0 16px 34px rgba(16, 115, 204, 0.22) !important; + filter: saturate(1.04) !important; + transform: translateY(-1px) !important; +} + +.ecommerce-standalone .ecom-quick-set-primary:disabled, +.ecommerce-standalone .ecom-watermark-primary:disabled, +.ecommerce-standalone .ecom-image-workbench-primary:disabled { + color: #8fa1af !important; + background: #edf1f4 !important; + box-shadow: none !important; + transform: none !important; +} + +.ecommerce-standalone .ecom-quick-set-stage, +.ecommerce-standalone .ecom-hot-video-page .ecom-quick-set-stage { + gap: 16px !important; + padding: 26px 32px !important; + background: + radial-gradient(circle at 20% 18%, rgba(30, 189, 219, 0.08), transparent 20rem), + radial-gradient(circle at 82% 22%, rgba(16, 115, 204, 0.055), transparent 22rem), + #f7f9fb !important; +} + +.ecommerce-standalone .ecom-quick-set-preview-head, +.ecommerce-standalone .ecom-hot-video-page .ecom-video-preview-head { + padding-bottom: 16px !important; + border-bottom-color: rgba(26, 74, 108, 0.1) !important; +} + +.ecommerce-standalone .ecom-quick-set-preview-head h1, +.ecommerce-standalone .ecom-hot-video-page .ecom-video-preview-copy h1 { + font-size: 24px !important; + font-weight: 950 !important; +} + +.ecommerce-standalone .ecom-quick-set-preview-head p, +.ecommerce-standalone .ecom-hot-video-page .ecom-video-preview-copy p { + max-width: 720px !important; + color: var(--quick-muted) !important; + line-height: 1.65 !important; +} + +.ecommerce-standalone .ecom-quick-set-preview-head div button, +.ecommerce-standalone .ecom-hot-video-page .ecom-video-flowbar__zoom button { + border: 1px solid rgba(16, 115, 204, 0.1) !important; + border-radius: 8px !important; + background: #edf8ff !important; +} + +.ecommerce-standalone .ecom-quick-set-canvas, +.ecommerce-standalone .ecom-hot-video-page .ecom-video-workspace, +.ecommerce-standalone .ecom-watermark-workspace, +.ecommerce-standalone .ecom-image-workbench-stage { + border-color: var(--quick-border) !important; + border-radius: 8px !important; + background: + linear-gradient(rgba(16, 115, 204, 0.026) 1px, transparent 1px), + linear-gradient(90deg, rgba(16, 115, 204, 0.022) 1px, transparent 1px), + #ffffff !important; + background-size: 26px 26px, 26px 26px, auto !important; + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.9), 0 12px 30px rgba(16, 115, 204, 0.05) !important; +} + +.ecommerce-standalone .ecom-quick-set-empty, +.ecommerce-standalone .ecom-watermark-dropzone, +.ecommerce-standalone .ecom-image-workbench-empty, +.ecommerce-standalone .ecom-watermark-empty, +.ecommerce-standalone .ecom-watermark-processing { + border-radius: 8px !important; + border-color: rgba(16, 115, 204, 0.13) !important; + background: rgba(255, 255, 255, 0.88) !important; + box-shadow: 0 12px 28px rgba(16, 115, 204, 0.055) !important; +} + +.ecommerce-standalone .ecom-quick-set-result-card, +.ecommerce-standalone .ecom-quick-detail-preview-card, +.ecommerce-standalone .ecom-quick-detail-result { + border-radius: 8px !important; + border-color: var(--quick-border) !important; + box-shadow: 0 18px 44px rgba(16, 115, 204, 0.08) !important; +} + +.ecommerce-standalone .ecom-quick-set-result-card figure, +.ecommerce-standalone .ecom-quick-detail-preview-card figure, +.ecommerce-standalone .ecom-quick-detail-result, +.ecommerce-standalone .ecom-watermark-preview-card > img, +.ecommerce-standalone .ecom-image-workbench-preview { + border-radius: 8px !important; +} + +.ecommerce-standalone .ecom-quick-set-prompt { + border-radius: 8px !important; + border-color: var(--quick-border) !important; + box-shadow: 0 12px 28px rgba(16, 115, 204, 0.055) !important; +} + +.ecommerce-standalone .ecom-quick-set-prompt textarea { + min-height: 70px !important; + font-size: 13px !important; +} + +.ecommerce-standalone .ecom-watermark-grid { + border: 0 !important; + border-radius: 8px !important; + gap: 1px !important; + background: rgba(16, 115, 204, 0.08) !important; +} + +.ecommerce-standalone .ecom-watermark-preview-card { + background: + linear-gradient(rgba(16, 115, 204, 0.024) 1px, transparent 1px), + linear-gradient(90deg, rgba(16, 115, 204, 0.02) 1px, transparent 1px), + #ffffff !important; + background-size: 24px 24px, 24px 24px, auto !important; +} + +.ecommerce-standalone .ecom-watermark-preview-card:first-child { + border-right: 0 !important; +} + +.ecommerce-standalone .ecom-image-workbench-canvas { + border-radius: 8px !important; +} + +.ecommerce-standalone .ecom-image-workbench-image-frame { + border-radius: 8px !important; + box-shadow: 0 16px 38px rgba(16, 115, 204, 0.1) !important; +} + +.ecommerce-standalone .ecom-hot-video-page .ecom-video-flow-canvas, +.ecommerce-standalone .ecom-hot-video-page .ecom-video-canvas { + background: + linear-gradient(rgba(16, 115, 204, 0.024) 1px, transparent 1px), + linear-gradient(90deg, rgba(16, 115, 204, 0.02) 1px, transparent 1px), + #ffffff !important; + background-size: 24px 24px, 24px 24px, auto !important; +} + +.ecommerce-standalone .ecom-quick-set-help { + border-radius: 8px !important; + color: #526474 !important; + background: rgba(255, 255, 255, 0.92) !important; + backdrop-filter: blur(12px) !important; + -webkit-backdrop-filter: blur(12px) !important; +} + +@media (max-width: 1280px) { + .ecommerce-standalone .ecom-quick-set-body { + grid-template-columns: minmax(330px, 370px) minmax(0, 1fr) !important; + } + + .ecommerce-standalone .ecom-hot-video-page .ecom-quick-set-body { + grid-template-columns: minmax(320px, 360px) minmax(0, 1fr) !important; + } +} + +/* ── Quick Page Responsive ── */ +@media (max-width: 1280px) { + .ecommerce-standalone .ecom-quick-set-body { + grid-template-columns: minmax(340px, 380px) minmax(0, 1fr) !important; + } + + .ecommerce-standalone .ecom-quick-page-sidebar { + flex: 0 0 68px !important; + width: 68px !important; + padding: 14px 6px !important; + } + + .ecommerce-standalone .ecom-quick-page-sidebar button { + min-height: 54px !important; + gap: 3px !important; + } + + .ecommerce-standalone .ecom-quick-page-sidebar button .anticon { + font-size: 18px !important; + } + + .ecommerce-standalone .ecom-quick-page-sidebar button span:last-child { + font-size: 9px !important; + } +} + +@media (max-width: 960px) { + .ecommerce-standalone .ecom-quick-set-body { + grid-template-columns: minmax(280px, 320px) minmax(0, 1fr) !important; + } + + .ecommerce-standalone .ecom-quick-page-sidebar { + flex: 0 0 56px !important; + width: 56px !important; + padding: 10px 4px !important; + } + + .ecommerce-standalone .ecom-quick-page-sidebar button { + min-height: 48px !important; + padding: 6px 3px !important; + } + + .ecommerce-standalone .ecom-quick-page-sidebar button .anticon { + font-size: 16px !important; + } + + .ecommerce-standalone .ecom-quick-page-sidebar button span:last-child { + font-size: 8px !important; + } +} + +@media (max-width: 720px) { + .ecommerce-standalone .ecom-quick-set-body { + grid-template-columns: minmax(0, 1fr) !important; + } + + .ecommerce-standalone .ecom-quick-set-stage { + display: none !important; + } + + .ecommerce-standalone .ecom-quick-page-sidebar { + flex: 0 0 48px !important; + width: 48px !important; + padding: 8px 3px !important; + gap: 2px !important; + } + + .ecommerce-standalone .ecom-quick-page-sidebar button { + min-height: 42px !important; + padding: 4px 2px !important; + border-radius: 8px !important; + } + + .ecommerce-standalone .ecom-quick-page-sidebar button .anticon { + font-size: 14px !important; + } + + .ecommerce-standalone .ecom-quick-page-sidebar button span:last-child { + font-size: 7px !important; + } + + .ecommerce-standalone .ecom-quick-page-sidebar button.is-active::before { + left: -1px !important; + width: 2px !important; + top: 8px !important; + bottom: 8px !important; + } +} + +/* ── Watermark / Image Workbench Page Responsive ── */ +@media (max-width: 960px) { + .ecommerce-standalone .ecom-watermark-grid { + grid-template-columns: minmax(0, 1fr) !important; + gap: 14px !important; + padding: 16px !important; + } + + .ecommerce-standalone .ecom-image-workbench-page .ecom-image-workbench-body { + grid-template-columns: minmax(280px, 340px) minmax(0, 1fr) !important; + } +} + +@media (max-width: 720px) { + .ecommerce-standalone .ecom-watermark-page .ecom-quick-set-body { + grid-template-columns: minmax(0, 1fr) !important; + } + + .ecommerce-standalone .ecom-watermark-grid { + grid-template-columns: minmax(0, 1fr) !important; + padding: 10px !important; + gap: 10px !important; + } + + .ecommerce-standalone .ecom-watermark-preview-card { + padding: 12px !important; + } + + .ecommerce-standalone .ecom-watermark-page .ecom-quick-set-stage { + display: none !important; + } + + .ecommerce-standalone .ecom-image-workbench-page .ecom-image-workbench-body { + grid-template-columns: minmax(0, 1fr) !important; + } + + .ecommerce-standalone .ecom-image-workbench-page .ecom-image-workbench-stage { + display: none !important; + } +} + +/* ── Smart Cutout Page Responsive ── */ +@media (max-width: 1280px) { + .ecommerce-standalone .ecom-smart-cutout-page .ecom-smart-editor { + grid-template-columns: minmax(260px, 300px) minmax(0, 1fr) !important; + } +} + +@media (max-width: 960px) { + .ecommerce-standalone .ecom-smart-cutout-page .ecom-smart-editor { + grid-template-columns: minmax(0, 1fr) !important; + } + + .ecommerce-standalone .ecom-smart-cutout-page .ecom-smart-editor__side { + order: 2 !important; + max-height: 40vh !important; + } + + .ecommerce-standalone .ecom-smart-cutout-page .ecom-smart-editor__canvas { + order: 1 !important; + } + + .ecommerce-standalone .ecom-smart-cutout-nav { + flex-wrap: wrap !important; + gap: 6px !important; + } +} + +@media (max-width: 720px) { + .ecommerce-standalone .ecom-smart-editor__scenes { + grid-template-columns: repeat(2, minmax(0, 1fr)) !important; + } +} + +@media (hover: none) { + .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-asset-thumb > button { + opacity: 1 !important; + pointer-events: auto !important; + transform: translate(0, 0) scale(1) !important; + visibility: visible !important; + } +} + +/* #/imageWorkbench SaaS entry refinement. */ +.ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] { + --ecom-entry-surface: rgba(255, 255, 255, 0.86); + --ecom-entry-surface-strong: rgba(255, 255, 255, 0.96); + --ecom-entry-border-hairline: rgba(30, 189, 219, 0.16); + --ecom-entry-border-active: rgba(30, 189, 219, 0.42); + --ecom-entry-shadow-soft: 0 18px 54px rgba(16, 115, 204, 0.09); + --ecom-entry-shadow-focus: 0 24px 72px rgba(16, 115, 204, 0.14); + background: + radial-gradient(48rem 24rem at 50% 7%, rgba(30, 189, 219, 0.15), transparent 72%), + radial-gradient(34rem 20rem at 14% 24%, rgba(16, 115, 204, 0.08), transparent 68%), + linear-gradient(180deg, #f8fbfc 0%, #f5f9fb 48%, #f8fafb 100%) !important; +} + +.ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .clone-ai-preview.clone-ai-preview { + padding-top: clamp(56px, 7.6vh, 96px) !important; +} + +.ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-composer-wrap.ecom-command-composer-wrap { + gap: clamp(16px, 2.1vw, 24px) !important; + padding-inline: clamp(20px, 3vw, 44px) !important; +} + +.ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-title.ecom-command-title { + min-height: 1.18em !important; + font-weight: 860 !important; + line-height: 1.14 !important; + text-wrap: balance; +} + +.ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .clone-ai-input-wrapper.ecom-command-composer { + border-color: var(--ecom-entry-border-hairline) !important; + border-radius: 26px !important; + background: + linear-gradient(180deg, rgba(255, 255, 255, 0.985), rgba(248, 253, 255, 0.92)), + linear-gradient(135deg, rgba(30, 189, 219, 0.075), rgba(16, 115, 204, 0.035)) !important; + box-shadow: + inset 0 1px 0 rgba(255, 255, 255, 0.94), + inset 0 -1px 0 rgba(30, 189, 219, 0.05), + var(--ecom-entry-shadow-soft) !important; +} + +.ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .clone-ai-input-wrapper.ecom-command-composer:hover, +.ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .clone-ai-input-wrapper.ecom-command-composer:focus-within { + border-color: var(--ecom-entry-border-active) !important; + box-shadow: + inset 0 1px 0 rgba(255, 255, 255, 0.96), + 0 0 0 4px rgba(30, 189, 219, 0.08), + var(--ecom-entry-shadow-focus) !important; +} + +.ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-composer textarea { + color: var(--ecom-entry-text) !important; + font-size: 15px !important; + line-height: 1.7 !important; +} + +.ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-composer textarea::placeholder { + color: rgba(16, 32, 44, 0.42) !important; +} + +.ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-toolbar { + border-top-color: rgba(30, 189, 219, 0.1) !important; +} + +.ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-option-row { + gap: 9px !important; +} + +.ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-option-row button, +.ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-upload-inline { + min-height: 40px !important; + border-color: rgba(30, 189, 219, 0.16) !important; + border-radius: 15px !important; + background: + linear-gradient(180deg, rgba(255, 255, 255, 0.94), rgba(244, 252, 254, 0.82)) !important; + color: rgba(16, 32, 44, 0.72) !important; + font-weight: 760 !important; +} + +.ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-option-row button > span, +.ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-reference--inline strong { + min-width: 0 !important; +} + +.ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-option-icon { + width: 22px !important; + height: 22px !important; + border-color: rgba(30, 189, 219, 0.12) !important; + background: rgba(232, 249, 253, 0.74) !important; + color: #0f829b !important; +} + +.ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-option-row button:hover, +.ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-upload-inline:hover, +.ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-option-row button.is-active { + border-color: var(--ecom-entry-border-active) !important; + background: + linear-gradient(180deg, rgba(246, 254, 255, 0.98), rgba(228, 249, 253, 0.92)) !important; + color: var(--ecom-entry-text) !important; +} + +.ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .clone-ai-send-button.ecom-command-send { + width: 50px !important; + height: 50px !important; + min-width: 50px !important; + border-radius: 17px !important; + box-shadow: + 0 18px 38px rgba(30, 189, 219, 0.3), + inset 0 1px 0 rgba(255, 255, 255, 0.38) !important; +} + +.ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-quick-board { + overflow: hidden !important; + border-color: rgba(30, 189, 219, 0.1) !important; + border-radius: 24px !important; + background: + linear-gradient(180deg, rgba(255, 255, 255, 0.78), rgba(248, 253, 255, 0.66)), + rgba(255, 255, 255, 0.62) !important; + box-shadow: + 0 18px 52px rgba(16, 115, 204, 0.075), + inset 0 1px 0 rgba(255, 255, 255, 0.78) !important; +} + +.ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-quick-board button { + gap: 12px !important; + border-color: rgba(30, 189, 219, 0.075) !important; + border-radius: 0 !important; + background: + linear-gradient(180deg, rgba(255, 255, 255, 0.72), rgba(246, 252, 254, 0.58)) !important; + box-shadow: none !important; +} + +.ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-quick-board button:hover { + border-color: rgba(30, 189, 219, 0.28) !important; + background: + linear-gradient(180deg, rgba(255, 255, 255, 0.98), rgba(235, 251, 254, 0.92)) !important; + box-shadow: + inset 0 1px 0 rgba(255, 255, 255, 0.84), + 0 16px 34px rgba(16, 115, 204, 0.1) !important; + transform: translateY(-1px) !important; +} + +.ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-quick-board button > span { + display: inline-flex !important; + width: 32px !important; + height: 32px !important; + align-items: center !important; + justify-content: center !important; + border: 1px solid rgba(30, 189, 219, 0.15) !important; + border-radius: 12px !important; + background: linear-gradient(180deg, rgba(231, 249, 253, 0.96), rgba(217, 244, 250, 0.86)) !important; + color: #0f829b !important; + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.74) !important; +} + +.ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-quick-board strong { + font-weight: 820 !important; +} + +.ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-history__toggle.ecom-command-history__toggle { + border-color: rgba(30, 189, 219, 0.13) !important; + background: rgba(255, 255, 255, 0.76) !important; + color: rgba(16, 32, 44, 0.62) !important; + box-shadow: 0 14px 32px rgba(16, 115, 204, 0.1) !important; +} + +@media (min-width: 1181px) { + .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-history__toggle.ecom-command-history__toggle { + opacity: 0.82 !important; + transform: translateX(2px) !important; + } +} + +@media (max-width: 760px) { + .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .clone-ai-preview.clone-ai-preview { + padding-top: 18px !important; + } + + .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-composer-wrap.ecom-command-composer-wrap { + gap: 16px !important; + padding-inline: 16px !important; + } + + .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-title.ecom-command-title { + max-width: min(100%, 520px) !important; + min-height: 2.36em !important; + overflow: visible !important; + background: + linear-gradient(96deg, #284a56 0%, #4f7f88 42%, #28a8bd 100%) !important; + -webkit-background-clip: text !important; + background-clip: text !important; + color: transparent !important; + font-size: clamp(26px, 6.4vw, 34px) !important; + line-height: 1.18 !important; + text-shadow: 0 16px 38px rgba(40, 168, 189, 0.14) !important; + text-wrap: balance; + white-space: normal !important; + } + + .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .clone-ai-input-wrapper.ecom-command-composer { + width: min(100%, 352px) !important; + margin-inline: auto !important; + padding: 15px !important; + border-radius: 24px !important; + } + + .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-composer textarea { + min-height: 86px !important; + font-size: 14px !important; + line-height: 1.62 !important; + } + + .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-toolbar { + gap: 12px !important; + padding-top: 12px !important; + } + + .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-option-row { + display: grid !important; + grid-template-columns: repeat(6, 44px) !important; + justify-content: center !important; + gap: 8px !important; + } + + .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-option-row button, + .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-upload-inline { + width: 44px !important; + min-width: 44px !important; + max-width: 44px !important; + height: 44px !important; + min-height: 44px !important; + justify-content: center !important; + gap: 0 !important; + padding: 0 !important; + overflow: hidden !important; + font-size: 0 !important; + } + + .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-option-row button:not(.ecom-command-reference--inline) > span:not(.ecom-command-option-icon), + .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-reference--inline strong { + display: none !important; + } + + .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-option-row .ecom-command-option-icon, + .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-reference--inline > span { + display: inline-flex !important; + width: 26px !important; + height: 26px !important; + align-items: center !important; + justify-content: center !important; + margin: 0 !important; + font-size: 16px !important; + } + + .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .clone-ai-send-button.ecom-command-send { + width: 48px !important; + height: 48px !important; + min-width: 48px !important; + } + + .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-quick-board { + width: min(100%, 352px) !important; + margin-inline: auto !important; + border-radius: 22px !important; + } + + .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-quick-board button { + min-height: 70px !important; + padding: 12px 10px !important; + gap: 9px !important; + } + + .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-quick-board button > span { + width: 30px !important; + height: 30px !important; + border-radius: 11px !important; + } + + .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-quick-board strong { + font-size: 13px !important; + } + + .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-popover.ecom-command-popover { + position: absolute !important; + top: calc(100% + 12px) !important; + right: auto !important; + bottom: auto !important; + left: 0 !important; + z-index: 140 !important; + box-sizing: border-box !important; + width: 100% !important; + min-width: 0 !important; + max-width: 100% !important; + max-height: min(280px, calc(100dvh - 148px)) !important; + overflow: auto !important; + border-radius: 22px !important; + animation: none !important; + box-shadow: + 0 28px 76px rgba(16, 115, 204, 0.2), + inset 0 1px 0 rgba(255, 255, 255, 0.88) !important; + transform: none !important; + translate: none !important; + } + + .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-popover.ecom-command-popover--grid, + .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-popover.ecom-command-popover--list, + .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-popover.ecom-command-popover--languages { + display: grid !important; + grid-template-columns: repeat(2, minmax(0, 1fr)) !important; + gap: 10px !important; + } + + .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-popover.ecom-command-popover button { + width: 100% !important; + min-width: 0 !important; + max-width: none !important; + overflow: hidden !important; + text-overflow: ellipsis !important; + } + + .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"].is-history-collapsed .ecom-command-history__toggle.ecom-command-history__toggle { + left: -42px !important; + width: 38px !important; + height: 44px !important; + min-width: 38px !important; + min-height: 44px !important; + opacity: 0.9 !important; + } +} diff --git a/src/styles/standalone/overrides.css b/src/styles/standalone/overrides.css new file mode 100644 index 0000000..1e7d62b --- /dev/null +++ b/src/styles/standalone/overrides.css @@ -0,0 +1,3622 @@ + +@media (max-width: 640px) { + html body .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-popover.ecom-command-popover { + position: absolute !important; + inset: calc(100% + 12px) auto auto 0 !important; + box-sizing: border-box !important; + width: 100% !important; + min-width: 0 !important; + max-width: 100% !important; + max-height: min(280px, calc(100dvh - 150px)) !important; + overflow: auto !important; + animation: none !important; + transform: none !important; + translate: none !important; + } + + html body .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-popover.ecom-command-popover--grid, + html body .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-popover.ecom-command-popover--list, + html body .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-popover.ecom-command-popover--languages { + display: grid !important; + grid-template-columns: repeat(2, minmax(0, 1fr)) !important; + gap: 10px !important; + } +} + +@media (max-width: 640px) { + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-title.ecom-command-title { + max-width: min(100%, 520px) !important; + min-height: 2.28em !important; + background: + linear-gradient(96deg, #10202c 0%, #164359 36%, #0f829b 68%, #18bfd2 100%) !important; + -webkit-background-clip: text !important; + background-clip: text !important; + color: transparent !important; + font-size: clamp(29px, 7.8vw, 34px) !important; + line-height: 1.14 !important; + text-shadow: 0 18px 46px rgba(15, 130, 155, 0.13) !important; + text-wrap: balance; + white-space: normal !important; + } + + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-option-row button, + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-upload-inline { + width: 44px !important; + min-width: 44px !important; + max-width: 44px !important; + height: 44px !important; + min-height: 44px !important; + padding: 0 !important; + overflow: hidden !important; + font-size: 0 !important; + line-height: 0 !important; + } + + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-option-row { + max-width: 100% !important; + overflow: hidden !important; + } + + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-option-row button:not(.ecom-command-reference--inline) > span:not(.ecom-command-option-icon), + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-reference--inline strong { + display: none !important; + } + + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-option-row .ecom-command-option-icon, + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-reference--inline > span { + display: inline-flex !important; + width: 26px !important; + height: 26px !important; + align-items: center !important; + justify-content: center !important; + margin: 0 !important; + font-size: 16px !important; + line-height: 1 !important; + } + + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-popover.ecom-command-popover { + position: absolute !important; + inset: calc(100% + 12px) auto auto 0 !important; + box-sizing: border-box !important; + width: 100% !important; + min-width: 0 !important; + max-width: 100% !important; + max-height: min(280px, calc(100dvh - 150px)) !important; + overflow: auto !important; + animation: none !important; + transform: none !important; + translate: none !important; + } + + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-popover.ecom-command-popover--settings { + display: grid !important; + grid-template-columns: minmax(0, 1fr) !important; + align-content: start !important; + gap: 10px !important; + max-height: min(360px, 42dvh) !important; + overflow-x: hidden !important; + overflow-y: auto !important; + padding: 14px !important; + } + + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-popover--settings header { + display: flex !important; + grid-column: 1 / -1 !important; + align-items: center !important; + justify-content: space-between !important; + gap: 12px !important; + min-width: 0 !important; + margin: 0 0 2px !important; + } + + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-popover--settings > .ecom-command-count-row { + grid-column: 1 / -1 !important; + display: grid !important; + grid-template-columns: minmax(0, 1fr) auto !important; + width: 100% !important; + min-width: 0 !important; + min-height: 78px !important; + align-items: center !important; + gap: 10px !important; + padding: 12px !important; + overflow: hidden !important; + } + + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-count-row > span { + min-width: 0 !important; + } + + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-count-row > span strong, + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-count-row > span em { + display: block !important; + max-width: 100% !important; + overflow: hidden !important; + text-overflow: ellipsis !important; + white-space: nowrap !important; + } + + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-count-row > div { + display: grid !important; + grid-template-columns: 34px 24px 34px !important; + align-items: center !important; + justify-content: end !important; + gap: 6px !important; + min-width: 98px !important; + } + + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-count-row > div button { + width: 34px !important; + min-width: 34px !important; + height: 34px !important; + min-height: 34px !important; + padding: 0 !important; + border-radius: 999px !important; + font-size: 16px !important; + line-height: 1 !important; + } + + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-count-row > div b { + min-width: 24px !important; + text-align: center !important; + } + + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-popover--settings .ecom-command-module-grid, + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-popover--settings .ecom-command-module-grid--detail, + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-popover--settings .ecom-command-module-grid--model, + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-popover--settings .ecom-command-module-grid--video, + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-popover--settings .ecom-command-hot-levels { + grid-column: 1 / -1 !important; + display: grid !important; + grid-template-columns: repeat(2, minmax(0, 1fr)) !important; + width: 100% !important; + min-width: 0 !important; + max-height: none !important; + overflow: visible !important; + gap: 8px !important; + } + + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-popover--settings .ecom-command-module-grid button, + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-popover--settings .ecom-command-hot-levels button { + width: 100% !important; + min-width: 0 !important; + max-width: none !important; + min-height: 44px !important; + overflow: hidden !important; + white-space: normal !important; + } + + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-popover--settings .ecom-command-hot-layout { + grid-column: 1 / -1 !important; + display: grid !important; + grid-template-columns: minmax(0, 1fr) !important; + width: 100% !important; + min-width: 0 !important; + gap: 10px !important; + overflow: visible !important; + } + + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-popover--settings .ecom-command-hot-upload { + width: 100% !important; + min-width: 0 !important; + min-height: 132px !important; + max-width: none !important; + } + + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-model-profile { + grid-column: 1 / -1 !important; + width: 100% !important; + min-width: 0 !important; + overflow: hidden !important; + } + + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-model-profile section > div { + display: flex !important; + flex-wrap: wrap !important; + gap: 6px !important; + min-width: 0 !important; + overflow: visible !important; + } + + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-model-profile button { + flex: 1 1 calc(50% - 6px) !important; + min-width: 0 !important; + max-width: none !important; + } +} + +@media (max-width: 420px) { + .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-title.ecom-command-title { + font-size: clamp(24px, 7.2vw, 30px) !important; + } + + .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .clone-ai-input-wrapper.ecom-command-composer { + padding: 14px !important; + } + + .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-option-row button, + .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-upload-inline { + width: 42px !important; + min-width: 42px !important; + max-width: 42px !important; + height: 42px !important; + min-height: 42px !important; + font-size: 0 !important; + } +} + +@media (max-width: 420px) { + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-title.ecom-command-title { + font-size: clamp(25px, 8vw, 30px) !important; + } + + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-option-row { + grid-template-columns: repeat(6, minmax(0, clamp(38px, 10.6vw, 42px))) !important; + gap: 7px !important; + justify-content: center !important; + overflow: hidden !important; + } + + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-option-row button, + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-upload-inline { + width: clamp(38px, 10.6vw, 42px) !important; + min-width: 0 !important; + max-width: 42px !important; + height: clamp(38px, 10.6vw, 42px) !important; + min-height: clamp(38px, 10.6vw, 42px) !important; + } +} + +@media (max-width: 640px) { + 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.ecom-command-popover--settings, + 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.ecom-command-popover--settings-set, + 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.ecom-command-popover--settings-model, + 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.ecom-command-popover--settings-hot { + inset: calc(100% + 12px) auto auto 0 !important; + left: 0 !important; + right: auto !important; + width: 100% !important; + min-width: 0 !important; + max-width: 100% !important; + margin: 0 !important; + overflow-x: hidden !important; + overflow-y: auto !important; + transform: none !important; + translate: none !important; + } +} + +/* #/imageWorkbench mid-size refinement: keep the composer and floating panels balanced on tablet/small desktop widths. */ +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-reference.ecom-command-reference--inline { + position: relative !important; + flex: 0 0 48px !important; + width: 48px !important; + min-width: 48px !important; + max-width: 48px !important; + height: 48px !important; + min-height: 48px !important; + justify-content: center !important; + gap: 0 !important; + padding: 0 !important; + border-radius: 17px !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-reference.ecom-command-reference--inline > span { + width: 0 !important; + min-width: 0 !important; + height: 0 !important; + margin: 0 !important; + overflow: hidden !important; + border: 0 !important; + background: transparent !important; + color: transparent !important; + font-size: 0 !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-reference.ecom-command-reference--inline .anticon { + display: none !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-reference.ecom-command-reference--inline strong { + position: absolute !important; + width: 1px !important; + height: 1px !important; + padding: 0 !important; + overflow: hidden !important; + clip: rect(0 0 0 0) !important; + clip-path: inset(50%) !important; + white-space: nowrap !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-reference.ecom-command-reference--inline::before { + content: "+" !important; + display: inline-grid !important; + width: 24px !important; + height: 24px !important; + place-items: center !important; + border-radius: 10px !important; + background: linear-gradient(180deg, rgba(235, 252, 255, 0.96), rgba(218, 245, 250, 0.9)) !important; + color: #0f829b !important; + font-size: 22px !important; + font-weight: 760 !important; + line-height: 1 !important; + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.78) !important; +} + +@media (min-width: 641px) and (max-width: 1280px) { + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-composer-wrap.ecom-command-composer-wrap { + width: min(1080px, calc(100vw - 96px)) !important; + gap: clamp(14px, 2.2vh, 20px) !important; + padding-inline: 0 !important; + } + + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .clone-ai-input-wrapper.ecom-command-composer { + width: 100% !important; + min-height: clamp(258px, 40vh, 304px) !important; + padding: clamp(18px, 2.8vw, 24px) !important; + border-radius: 26px !important; + } + + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-composer textarea { + min-height: clamp(76px, 14vh, 104px) !important; + max-height: clamp(104px, 18vh, 136px) !important; + } + + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-toolbar { + align-items: end !important; + gap: 12px !important; + } + + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-option-row { + display: flex !important; + flex-wrap: wrap !important; + gap: 10px !important; + max-width: min(100%, 660px) !important; + } + + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-option-row button:not(.ecom-command-reference--inline) { + min-height: 44px !important; + padding-inline: 12px !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 { + inset: calc(100% + 14px) auto auto 0 !important; + left: 0 !important; + right: auto !important; + box-sizing: border-box !important; + width: 100% !important; + min-width: 0 !important; + max-width: 100% !important; + max-height: min(386px, max(220px, calc(100dvh - 470px))) !important; + margin: 0 !important; + overflow-x: hidden !important; + overflow-y: auto !important; + border-radius: 24px !important; + background: + linear-gradient(180deg, rgba(255, 255, 255, 0.98), rgba(244, 252, 254, 0.94)) !important; + box-shadow: + 0 30px 76px rgba(16, 115, 204, 0.17), + inset 0 1px 0 rgba(255, 255, 255, 0.88) !important; + transform: none !important; + translate: none !important; + } + + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-popover.ecom-command-popover--languages { + display: grid !important; + grid-template-columns: repeat(3, minmax(0, 1fr)) !important; + gap: 10px !important; + padding: 18px !important; + } + + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-popover.ecom-command-popover--languages button { + display: grid !important; + min-height: 68px !important; + align-content: center !important; + gap: 5px !important; + padding: 11px 12px !important; + border-radius: 16px !important; + text-align: center !important; + white-space: normal !important; + } + + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-popover.ecom-command-popover--languages button strong, + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-popover.ecom-command-popover--languages button span { + min-width: 0 !important; + overflow: hidden !important; + text-overflow: ellipsis !important; + white-space: nowrap !important; + } + + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-popover.ecom-command-popover--settings { + display: grid !important; + gap: 14px !important; + padding: 18px !important; + } + + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-popover--settings-hot .ecom-command-hot-layout { + display: grid !important; + grid-template-columns: minmax(260px, 1.08fr) minmax(220px, 0.72fr) !important; + gap: 14px !important; + align-items: stretch !important; + width: 100% !important; + min-width: 0 !important; + } + + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-popover--settings-hot .ecom-command-hot-upload { + min-height: 188px !important; + border-radius: 18px !important; + background: + linear-gradient(180deg, rgba(250, 254, 255, 0.96), rgba(238, 250, 253, 0.84)) !important; + } + + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-popover--settings-hot .ecom-command-hot-levels { + display: grid !important; + grid-template-columns: minmax(0, 1fr) !important; + grid-template-rows: repeat(2, minmax(0, 1fr)) !important; + gap: 12px !important; + width: 100% !important; + min-width: 0 !important; + } + + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-popover--settings-hot .ecom-command-hot-levels button { + min-height: 88px !important; + align-content: center !important; + padding: 16px !important; + border-radius: 18px !important; + text-align: left !important; + } + + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-popover--settings-model { + grid-template-columns: minmax(230px, 0.82fr) minmax(0, 1.18fr) !important; + align-items: start !important; + } + + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-popover--settings-model header { + grid-column: 1 / -1 !important; + } + + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-popover--settings-model .ecom-command-model-profile { + grid-column: 1 !important; + grid-row: 2 !important; + width: 100% !important; + min-width: 0 !important; + max-height: 286px !important; + overflow-y: auto !important; + } + + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-popover--settings-model .ecom-command-module-grid--model { + grid-column: 2 !important; + grid-row: 2 !important; + display: grid !important; + grid-template-columns: repeat(2, minmax(0, 1fr)) !important; + width: 100% !important; + min-width: 0 !important; + max-height: 286px !important; + overflow-y: auto !important; + gap: 10px !important; + } + + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-model-profile section > div { + display: flex !important; + flex-wrap: wrap !important; + gap: 8px !important; + } + + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-model-profile button { + flex: 1 1 auto !important; + min-width: max-content !important; + max-width: 100% !important; + } +} + +@media (min-width: 641px) and (max-width: 760px) { + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-popover.ecom-command-popover--languages { + grid-template-columns: repeat(2, minmax(0, 1fr)) !important; + } + + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-popover--settings-hot .ecom-command-hot-layout, + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-popover--settings-model { + grid-template-columns: minmax(0, 1fr) !important; + } + + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-popover--settings-model .ecom-command-model-profile, + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-popover--settings-model .ecom-command-module-grid--model { + grid-column: 1 !important; + grid-row: auto !important; + } +} + +/* #/imageWorkbench targeted polish: compact setting panels and align the history trigger with the panel top. */ +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .clone-ai-char-count { + display: 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 { + box-sizing: border-box !important; + width: min(432px, calc(100vw - 48px)) !important; + min-width: 0 !important; + max-width: min(432px, calc(100vw - 48px)) !important; + max-height: min(420px, calc(100dvh - 220px)) !important; + gap: 10px !important; + padding: 14px !important; + border-radius: 20px !important; + overflow-x: hidden !important; + overflow-y: auto !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-set { + width: min(396px, calc(100vw - 48px)) !important; + max-width: min(396px, calc(100vw - 48px)) !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-popover--settings-set > .ecom-command-count-row { + min-height: 60px !important; + gap: 8px !important; + padding: 10px 11px !important; + border-radius: 15px !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-popover--settings-set .ecom-command-count-row > span strong { + font-size: 13px !important; + line-height: 1.35 !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-popover--settings-set .ecom-command-count-row > span em { + font-size: 11px !important; + line-height: 1.35 !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-popover--settings-set .ecom-command-count-row > div { + grid-template-columns: 28px 22px 28px !important; + gap: 5px !important; + min-width: 86px !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-popover--settings-set .ecom-command-count-row > div button { + width: 28px !important; + min-width: 28px !important; + height: 28px !important; + min-height: 28px !important; + font-size: 14px !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-model { + width: min(508px, calc(100vw - 48px)) !important; + max-width: min(508px, calc(100vw - 48px)) !important; + grid-template-columns: minmax(172px, 0.78fr) minmax(0, 1fr) !important; + align-items: start !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-popover--settings-model header { + grid-column: 1 / -1 !important; + margin-bottom: 0 !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-popover--settings-model .ecom-command-model-profile { + grid-column: 1 !important; + grid-row: 2 !important; + max-height: 270px !important; + padding-right: 2px !important; + overflow-y: auto !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-popover--settings-model .ecom-command-model-profile section { + gap: 7px !important; + padding: 9px 0 !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-popover--settings-model .ecom-command-model-profile section > span { + font-size: 12px !important; + line-height: 30px !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-popover--settings-model .ecom-command-model-profile section > div { + gap: 6px !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-popover--settings-model .ecom-command-model-profile button { + min-height: 30px !important; + padding: 0 10px !important; + border-radius: 999px !important; + font-size: 12px !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-popover--settings-model .ecom-command-module-grid--model { + grid-column: 2 !important; + grid-row: 2 !important; + display: grid !important; + grid-template-columns: repeat(2, minmax(0, 1fr)) !important; + gap: 8px !important; + width: 100% !important; + max-height: 270px !important; + overflow-y: auto !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-popover--settings-model .ecom-command-module-grid--model button { + min-height: 38px !important; + padding: 0 10px !important; + border-radius: 13px !important; + text-align: center !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-history__toggle { + display: inline-flex !important; + align-items: center !important; + justify-content: center !important; + font-size: 16px !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-history__toggle .anticon { + display: inline-flex !important; + align-items: center !important; + justify-content: center !important; + font-size: 18px !important; + line-height: 1 !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"].is-history-collapsed .ecom-command-history__toggle.ecom-command-history__toggle { + top: 16px !important; + transform: none !important; +} + +@media (max-width: 640px) { + 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, + 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-set, + 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-model { + width: 100% !important; + max-width: 100% !important; + } + + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-popover--settings-model { + grid-template-columns: minmax(0, 1fr) !important; + } + + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-popover--settings-model .ecom-command-model-profile, + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-popover--settings-model .ecom-command-module-grid--model { + grid-column: 1 !important; + grid-row: auto !important; + } + + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"].is-history-collapsed .ecom-command-history__toggle.ecom-command-history__toggle { + top: 12px !important; + } +} + +/* #/imageWorkbench follow-up polish: larger adaptive composer, cleaner model panel, and livelier history handle. */ +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-composer-wrap.ecom-command-composer-wrap { + width: min(1128px, calc(100vw - 120px)) !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .clone-ai-input-wrapper.ecom-command-composer { + min-height: clamp(248px, 24vh, 306px) !important; + padding: clamp(22px, 2.2vw, 28px) clamp(24px, 2.6vw, 32px) clamp(18px, 2vw, 24px) !important; + border-radius: clamp(26px, 2.2vw, 32px) !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-composer textarea { + min-height: clamp(118px, 13vh, 162px) !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-set { + width: min(372px, calc(100vw - 48px)) !important; + max-width: min(372px, calc(100vw - 48px)) !important; + padding: 13px !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-popover--settings-set > .ecom-command-count-row { + width: min(100%, 334px) !important; + margin-inline: auto !important; + grid-template-columns: minmax(0, 1fr) 82px !important; + padding: 9px 10px !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-model { + width: min(544px, calc(100vw - 48px)) !important; + max-width: min(544px, calc(100vw - 48px)) !important; + max-height: none !important; + grid-template-columns: minmax(214px, 0.9fr) minmax(0, 1fr) !important; + gap: 12px !important; + padding: 15px !important; + overflow: visible !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-popover--settings-model header { + padding-bottom: 6px !important; + border-bottom: 1px solid rgba(30, 189, 219, 0.1) !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-popover--settings-model .ecom-command-model-profile, +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-popover--settings-model .ecom-command-module-grid--model { + max-height: none !important; + overflow: visible !important; + scrollbar-width: none !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-popover--settings-model .ecom-command-model-profile::-webkit-scrollbar, +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-popover--settings-model .ecom-command-module-grid--model::-webkit-scrollbar, +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-popover--settings-model::-webkit-scrollbar { + width: 0 !important; + height: 0 !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-popover--settings-model .ecom-command-model-profile { + display: grid !important; + align-content: start !important; + gap: 8px !important; + padding: 10px !important; + border: 1px solid rgba(30, 189, 219, 0.12) !important; + border-radius: 16px !important; + background: rgba(248, 253, 255, 0.58) !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-popover--settings-model .ecom-command-model-profile__title { + margin: 0 0 1px !important; + color: rgba(16, 32, 44, 0.88) !important; + font-size: 13px !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-popover--settings-model .ecom-command-model-profile section { + display: grid !important; + grid-template-columns: 36px minmax(0, 1fr) !important; + align-items: start !important; + gap: 8px !important; + padding: 0 !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-popover--settings-model .ecom-command-model-profile section > strong { + padding-top: 7px !important; + color: rgba(16, 115, 204, 0.66) !important; + font-size: 12px !important; + line-height: 1.2 !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-popover--settings-model .ecom-command-model-profile section > div { + display: flex !important; + flex-wrap: wrap !important; + gap: 6px !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-popover--settings-model .ecom-command-module-grid--model { + align-content: start !important; + padding: 10px !important; + border: 1px solid rgba(30, 189, 219, 0.12) !important; + border-radius: 16px !important; + background: rgba(248, 253, 255, 0.58) !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-popover--settings-model .ecom-command-module-grid--model button { + min-height: 36px !important; + border-radius: 13px !important; + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.68) !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-history__toggle.ecom-command-history__toggle { + transition: + border-color 180ms ease, + background 180ms ease, + color 180ms ease, + box-shadow 180ms ease, + transform 220ms cubic-bezier(0.16, 1, 0.3, 1), + opacity 180ms ease !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-history__toggle.ecom-command-history__toggle:hover { + border-color: rgba(30, 189, 219, 0.46) !important; + background: + linear-gradient(180deg, rgba(255, 255, 255, 0.98), rgba(235, 252, 255, 0.92)) !important; + color: #1073cc !important; + box-shadow: + 0 18px 38px rgba(16, 115, 204, 0.16), + 0 0 0 4px rgba(30, 189, 219, 0.08), + inset 0 1px 0 rgba(255, 255, 255, 0.9) !important; + opacity: 1 !important; + transform: translateY(-2px) scale(1.035) !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"].is-history-collapsed .ecom-command-history__toggle.ecom-command-history__toggle:hover { + transform: translateY(-2px) translateX(-2px) scale(1.035) !important; +} + +@media (min-width: 1440px) { + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-composer-wrap.ecom-command-composer-wrap { + width: min(1180px, calc(100vw - 152px)) !important; + } + + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .clone-ai-input-wrapper.ecom-command-composer { + min-height: clamp(276px, 25vh, 334px) !important; + } +} + +@media (min-width: 761px) and (max-width: 1180px) { + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-composer-wrap.ecom-command-composer-wrap { + width: min(1000px, calc(100vw - 72px)) !important; + } +} + +@media (max-width: 760px) { + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-composer-wrap.ecom-command-composer-wrap { + width: min(100%, calc(100vw - 28px)) !important; + } + + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .clone-ai-input-wrapper.ecom-command-composer { + min-height: clamp(220px, 36vh, 278px) !important; + padding: 16px !important; + } + + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-composer textarea { + min-height: clamp(96px, 20vh, 132px) !important; + } +} + +@media (max-width: 640px) { + 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-model { + max-height: min(520px, calc(100dvh - 170px)) !important; + overflow-y: auto !important; + scrollbar-width: thin !important; + scrollbar-color: rgba(16, 115, 204, 0.2) transparent !important; + } +} + +/* #/imageWorkbench final balance: keep the original composer height while letting width breathe. */ +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-composer-wrap.ecom-command-composer-wrap { + width: min(1088px, calc(100vw - clamp(72px, 11vw, 176px))) !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .clone-ai-input-wrapper.ecom-command-composer { + min-height: clamp(218px, 18vh, 238px) !important; + padding: 20px 24px 18px !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-composer textarea { + min-height: clamp(92px, 10vh, 118px) !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-popover--settings-model .ecom-command-model-profile section > strong { + color: rgba(16, 32, 44, 0.56) !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-history__toggle.ecom-command-history__toggle:hover { + color: rgba(16, 32, 44, 0.62) !important; + background: rgba(255, 255, 255, 0.86) !important; + border-color: rgba(30, 189, 219, 0.22) !important; + box-shadow: + 0 18px 38px rgba(16, 115, 204, 0.14), + 0 0 0 4px rgba(30, 189, 219, 0.06), + inset 0 1px 0 rgba(255, 255, 255, 0.9) !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-history__toggle.ecom-command-history__toggle:hover .anticon { + color: inherit !important; +} + +@media (min-width: 1440px) { + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .clone-ai-input-wrapper.ecom-command-composer { + min-height: clamp(222px, 18vh, 246px) !important; + } +} + +@media (max-width: 760px) { + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-composer-wrap.ecom-command-composer-wrap { + width: min(100%, calc(100vw - 28px)) !important; + } + + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .clone-ai-input-wrapper.ecom-command-composer { + min-height: clamp(214px, 32vh, 250px) !important; + padding: 16px !important; + } + + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-composer textarea { + min-height: clamp(86px, 18vh, 112px) !important; + } +} + +/* #/imageWorkbench command surface refinement: quieter hierarchy for daily SaaS usage. */ +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-toolbar { + gap: 14px !important; + padding-top: 13px !important; + border-top-color: rgba(30, 189, 219, 0.085) !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-option-row { + gap: 8px !important; + align-items: center !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-option-row button:not(.ecom-command-reference--inline) { + min-height: 38px !important; + padding: 0 12px !important; + border-color: rgba(30, 189, 219, 0.14) !important; + border-radius: 14px !important; + background: + linear-gradient(180deg, rgba(255, 255, 255, 0.9), rgba(247, 252, 254, 0.78)) !important; + color: rgba(16, 32, 44, 0.76) !important; + box-shadow: + inset 0 1px 0 rgba(255, 255, 255, 0.72), + 0 8px 18px rgba(16, 115, 204, 0.035) !important; + transition: + border-color 160ms ease, + background 160ms ease, + color 160ms ease, + box-shadow 180ms ease, + transform 180ms ease !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-option-row button:not(.ecom-command-reference--inline) > span:not(.ecom-command-option-icon) { + color: rgba(16, 32, 44, 0.46) !important; + font-weight: 650 !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-option-row .ecom-command-option-icon { + width: 21px !important; + height: 21px !important; + border-color: rgba(30, 189, 219, 0.1) !important; + background: rgba(232, 249, 253, 0.62) !important; + color: rgba(15, 130, 155, 0.82) !important; + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.62) !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-option-row button:not(.ecom-command-reference--inline):hover, +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-option-row button:not(.ecom-command-reference--inline).is-active { + border-color: rgba(30, 189, 219, 0.34) !important; + background: + linear-gradient(180deg, rgba(255, 255, 255, 0.98), rgba(238, 251, 254, 0.9)) !important; + color: rgba(16, 32, 44, 0.9) !important; + box-shadow: + inset 0 1px 0 rgba(255, 255, 255, 0.84), + 0 11px 24px rgba(16, 115, 204, 0.065) !important; + transform: translateY(-1px) !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-reference.ecom-command-reference--inline { + width: 46px !important; + min-width: 46px !important; + max-width: 46px !important; + height: 38px !important; + min-height: 38px !important; + border-radius: 14px !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-reference.ecom-command-reference--inline::before { + display: none !important; + content: none !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-reference.ecom-command-reference--inline > span { + display: inline-grid !important; + width: 30px !important; + min-width: 30px !important; + height: 30px !important; + place-items: center !important; + margin: 0 !important; + overflow: visible !important; + border: 0 !important; + border-radius: 11px !important; + background: linear-gradient(180deg, rgba(232, 250, 254, 0.96), rgba(212, 244, 250, 0.88)) !important; + color: #0f829b !important; + font-size: 20px !important; + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.82) !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-reference.ecom-command-reference--inline .anticon { + display: inline-flex !important; + color: inherit !important; + font-size: 20px !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--mode { + display: grid !important; + grid-template-columns: repeat(2, minmax(190px, 1fr)) !important; + grid-auto-flow: row !important; + justify-items: stretch !important; + gap: 9px !important; + width: min(460px, calc(100vw - 56px)) !important; + padding: 10px !important; + border-radius: 18px !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-popover--mode button { + display: grid !important; + grid-template-columns: 32px minmax(0, 1fr) !important; + grid-template-rows: auto auto !important; + align-items: center !important; + justify-items: start !important; + column-gap: 8px !important; + row-gap: 1px !important; + width: 100% !important; + min-height: 58px !important; + padding: 9px 10px !important; + border: 0 !important; + border-radius: 14px !important; + text-align: left !important; + background: + radial-gradient(circle at 18% 18%, color-mix(in srgb, var(--mode-accent, #1ebddb) 16%, transparent), transparent 42%), + linear-gradient(135deg, rgba(255, 255, 255, 0.96), rgba(245, 252, 254, 0.74)) !important; + box-shadow: + inset 0 1px 0 rgba(255, 255, 255, 0.82), + 0 8px 18px rgba(16, 115, 204, 0.045) !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-popover--mode button:has(.ecom-command-mode-icon--hot) { + grid-column: 1 / -1 !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-popover--mode button.is-active, +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-popover--mode button:hover { + color: rgba(16, 32, 44, 0.92) !important; + box-shadow: + inset 0 0 0 1px color-mix(in srgb, var(--mode-accent, #1ebddb) 36%, transparent), + 0 12px 26px color-mix(in srgb, var(--mode-accent, #1ebddb) 14%, transparent) !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-mode-icon { + grid-row: 1 / span 2 !important; + display: inline-grid !important; + width: 32px !important; + height: 32px !important; + place-items: center !important; + border-radius: 12px !important; + color: var(--mode-accent, #1073cc) !important; + background: color-mix(in srgb, var(--mode-accent, #1073cc) 13%, #ffffff) !important; + font-size: 16px !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-popover--mode button:has(.ecom-command-mode-icon--set) { + --mode-accent: #0f8f72; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-popover--mode button:has(.ecom-command-mode-icon--detail) { + --mode-accent: #7a5af8; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-popover--mode button:has(.ecom-command-mode-icon--model) { + --mode-accent: #1073cc; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-popover--mode button:has(.ecom-command-mode-icon--video) { + --mode-accent: #cc6b14; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-popover--mode button:has(.ecom-command-mode-icon--hot) { + --mode-accent: #c04468; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-popover--mode button strong { + min-width: 0 !important; + color: rgba(16, 32, 44, 0.86) !important; + font-size: 13px !important; + font-weight: 820 !important; + line-height: 1.15 !important; + white-space: nowrap !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-popover--mode button em { + min-width: 0 !important; + overflow: hidden !important; + color: rgba(16, 32, 44, 0.45) !important; + font-size: 10px !important; + font-style: normal !important; + font-weight: 650 !important; + line-height: 1.2 !important; + text-overflow: ellipsis !important; + white-space: nowrap !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--ratio-picker { + grid-template-columns: repeat(auto-fit, minmax(154px, 1fr)) !important; + gap: 8px !important; + width: min(420px, calc(100vw - 56px)) !important; + padding: 10px !important; + border-radius: 18px !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-popover--ratio-picker button { + display: flex !important; + align-items: center !important; + justify-content: flex-start !important; + gap: 9px !important; + min-height: 52px !important; + padding: 8px 10px !important; + border: 0 !important; + border-radius: 14px !important; + text-align: left !important; + background: linear-gradient(135deg, rgba(255, 255, 255, 0.96), rgba(240, 250, 253, 0.78)) !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-ratio-icon { + display: inline-grid !important; + width: 30px !important; + height: 30px !important; + place-items: center !important; + flex: 0 0 30px !important; + border-radius: 11px !important; + color: #1073cc !important; + background: rgba(226, 246, 252, 0.9) !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-ratio-copy { + display: grid !important; + min-width: 0 !important; + gap: 4px !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-ratio-copy strong { + min-width: 0 !important; + overflow: hidden !important; + color: rgba(16, 32, 44, 0.82) !important; + font-size: 12px !important; + font-weight: 820 !important; + line-height: 1.15 !important; + text-overflow: ellipsis !important; + white-space: nowrap !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-ratio-copy em { + display: inline-grid !important; + width: max-content !important; + min-width: 40px !important; + height: 18px !important; + place-items: center !important; + padding: 0 7px !important; + border-radius: 999px !important; + color: #0f829b !important; + background: rgba(222, 248, 252, 0.94) !important; + font-size: 10px !important; + font-style: normal !important; + font-weight: 820 !important; + line-height: 1 !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .clone-ai-send-button.ecom-command-send { + width: 48px !important; + height: 48px !important; + min-width: 48px !important; + border-radius: 16px !important; + transition: + border-color 180ms ease, + background 180ms ease, + box-shadow 180ms ease, + color 180ms ease, + transform 180ms ease, + opacity 180ms ease !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .clone-ai-send-button.ecom-command-send:not(:disabled) { + border-color: rgba(16, 115, 204, 0.18) !important; + background: + linear-gradient(135deg, #1073cc 0%, #1ebddb 100%) !important; + box-shadow: + 0 16px 34px rgba(30, 189, 219, 0.24), + inset 0 1px 0 rgba(255, 255, 255, 0.32) !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .clone-ai-send-button.ecom-command-send:not(:disabled):hover { + box-shadow: + 0 20px 42px rgba(30, 189, 219, 0.3), + 0 0 0 4px rgba(30, 189, 219, 0.09), + inset 0 1px 0 rgba(255, 255, 255, 0.38) !important; + transform: translateY(-1px) !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .clone-ai-send-button.ecom-command-send:disabled { + border: 1px solid rgba(30, 189, 219, 0.11) !important; + background: + linear-gradient(180deg, rgba(255, 255, 255, 0.82), rgba(244, 252, 254, 0.68)) !important; + color: rgba(16, 32, 44, 0.22) !important; + box-shadow: + inset 0 1px 0 rgba(255, 255, 255, 0.72), + 0 10px 22px rgba(16, 115, 204, 0.035) !important; + cursor: default !important; + opacity: 1 !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-quick-board { + position: relative !important; + display: grid !important; + grid-template-columns: repeat(5, 1fr) !important; + gap: 10px !important; + min-height: 0 !important; + padding: 0 !important; + overflow: visible !important; + border: 0 !important; + border-radius: 0 !important; + background: 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"] .ecom-command-quick-board::before { + display: none !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-quick-board button { + min-height: 72px !important; + padding: 12px 10px !important; + gap: 8px !important; + border: 0 !important; + border-radius: 16px !important; + background: + radial-gradient(circle at 16% 18%, color-mix(in srgb, var(--quick-accent) 18%, transparent), transparent 38%), + linear-gradient(135deg, rgba(255, 255, 255, 0.94), var(--quick-bg)) !important; + color: var(--quick-text) !important; + box-shadow: + inset 0 1px 0 rgba(255, 255, 255, 0.82), + 0 10px 24px rgba(16, 32, 44, 0.04) !important; + transition: + background 170ms ease, + color 170ms ease, + box-shadow 180ms ease, + transform 180ms ease !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-quick-board button::before, +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-quick-board button::after { + display: none !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-quick-board button:hover { + background: + radial-gradient(circle at 14% 18%, color-mix(in srgb, var(--quick-accent) 28%, transparent), transparent 40%), + linear-gradient(135deg, #ffffff, color-mix(in srgb, var(--quick-bg) 84%, #ffffff)) !important; + color: var(--quick-accent) !important; + box-shadow: + inset 0 1px 0 rgba(255, 255, 255, 0.78), + 0 16px 32px color-mix(in srgb, var(--quick-accent) 14%, transparent) !important; + transform: translateY(-2px) !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-quick-board button > span { + width: 34px !important; + height: 34px !important; + border: 0 !important; + border-radius: 12px !important; + background: + linear-gradient(180deg, color-mix(in srgb, var(--quick-accent) 18%, #ffffff), color-mix(in srgb, var(--quick-accent) 8%, #ffffff)) !important; + color: var(--quick-accent) !important; + box-shadow: none !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-quick-board button:hover > span { + color: var(--quick-accent) !important; + box-shadow: + inset 0 1px 0 rgba(255, 255, 255, 0.82), + 0 10px 22px color-mix(in srgb, var(--quick-accent) 18%, transparent) !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-quick-board .ecom-command-quick-card--detail { + --quick-accent: #7a5af8; + --quick-bg: #f1edff; + --quick-text: #2f245d; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-quick-board .ecom-command-quick-card--edit { + --quick-accent: #cc6b14; + --quick-bg: #fff2e5; + --quick-text: #4e2c11; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-quick-board .ecom-command-quick-card--cutout { + --quick-accent: #1073cc; + --quick-bg: #eaf5ff; + --quick-text: #123454; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-quick-board .ecom-command-quick-card--watermark { + --quick-accent: #c04468; + --quick-bg: #fff0f5; + --quick-text: #542234; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-quick-board .ecom-command-quick-card--translate { + --quick-accent: #0891b2; + --quick-bg: #ecfeff; + --quick-text: #164e63; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-quick-board, +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-quick-board button, +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-quick-board button > span, +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-quick-board .anticon, +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-quick-board svg { + border: 0 !important; + outline: 0 !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-quick-board button > span { + background: transparent !important; + box-shadow: none !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-quick-board button:hover > span { + background: transparent !important; + box-shadow: none !important; +} + +@media (max-width: 980px) { + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-quick-board { + grid-template-columns: repeat(3, minmax(0, 1fr)) !important; + min-height: 0 !important; + } +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-history__heading { + border-color: rgba(30, 189, 219, 0.1) !important; + background: + linear-gradient(180deg, rgba(255, 255, 255, 0.86), rgba(247, 253, 254, 0.72)) !important; + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.72) !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-history__empty { + display: grid !important; + min-height: 78px !important; + place-items: center !important; + border: 1px dashed rgba(30, 189, 219, 0.18) !important; + border-radius: 16px !important; + background: + linear-gradient(180deg, rgba(255, 255, 255, 0.72), rgba(247, 253, 254, 0.54)) !important; + color: rgba(16, 32, 44, 0.42) !important; + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.66) !important; +} + +@media (max-width: 760px) { + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-quick-board { + grid-template-columns: repeat(2, minmax(0, 1fr)) !important; + padding: 10px !important; + } + + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-quick-board button { + min-height: 58px !important; + } +} + +/* #/imageWorkbench uploaded-asset balance: keep thumbnails useful without making the composer feel oversized. */ +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-composer-wrap:not(.has-generated.is-compact) .clone-ai-input-wrapper.ecom-command-composer:has(.ecom-command-asset-popover) { + grid-template-rows: 58px minmax(46px, auto) auto !important; + row-gap: 7px !important; + min-height: clamp(232px, 19vh, 252px) !important; + padding: 20px 24px 18px !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-composer-wrap:not(.has-generated.is-compact) .clone-ai-input-wrapper.ecom-command-composer:has(.ecom-command-asset-popover) .ecom-command-asset-popover { + min-height: 54px !important; + max-height: 58px !important; + padding-left: 0 !important; + gap: 8px !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-composer-wrap:not(.has-generated.is-compact) .clone-ai-input-wrapper.ecom-command-composer:has(.ecom-command-asset-popover) .ecom-command-asset-thumb { + flex-basis: 54px !important; + width: 54px !important; + height: 54px !important; + border-radius: 12px !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-composer-wrap:not(.has-generated.is-compact) .clone-ai-input-wrapper.ecom-command-composer:has(.ecom-command-asset-popover) .ecom-command-asset-add { + flex-basis: 34px !important; + width: 34px !important; + height: 34px !important; + min-height: 34px !important; + margin-top: 10px !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-composer-wrap:not(.has-generated.is-compact) .clone-ai-input-wrapper.ecom-command-composer:has(.ecom-command-asset-popover) > textarea { + min-height: 50px !important; + max-height: 68px !important; + padding-top: 4px !important; +} + +/* #/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: + 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; + max-height: none !important; + padding: 13px !important; + overflow: visible !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-popover--settings-detail header { + min-height: 24px !important; + margin-bottom: 0 !important; + padding-bottom: 4px !important; + border-bottom: 1px solid rgba(30, 189, 219, 0.08) !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-popover--settings-detail .ecom-command-module-grid--detail { + display: grid !important; + grid-template-columns: repeat(3, minmax(0, 1fr)) !important; + gap: 7px !important; + max-height: none !important; + overflow: visible !important; + scrollbar-width: none !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-popover--settings-detail .ecom-command-module-grid--detail::-webkit-scrollbar, +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-popover--settings-detail::-webkit-scrollbar { + width: 0 !important; + height: 0 !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-popover--settings-detail .ecom-command-module-grid--detail button { + min-height: 43px !important; + padding: 7px 9px !important; + border-radius: 13px !important; + align-content: center !important; + gap: 2px !important; + text-align: center !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-popover--settings-detail .ecom-command-module-grid--detail button strong, +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-popover--settings-detail .ecom-command-module-grid--detail button span { + max-width: 100% !important; + overflow: hidden !important; + text-overflow: ellipsis !important; + white-space: nowrap !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-popover--settings-detail .ecom-command-module-grid--detail button strong { + font-size: 12px !important; + line-height: 1.25 !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-popover--settings-detail .ecom-command-module-grid--detail button span { + font-size: 10px !important; + line-height: 1.25 !important; +} + +@media (max-width: 760px) { + 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 { + overflow: auto !important; + } + + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-popover--settings-detail .ecom-command-module-grid--detail { + grid-template-columns: repeat(2, minmax(0, 1fr)) !important; + } +} + +/* #/imageWorkbench topbar seamless blend: the header floats over the same canvas instead of reading as a separate band. */ +html body #root .ecommerce-standalone.web-shell { + background: + radial-gradient(circle at 19% 8%, rgba(30, 189, 219, 0.13), transparent 24rem), + radial-gradient(circle at 82% 11%, rgba(16, 115, 204, 0.09), transparent 26rem), + linear-gradient(180deg, #fbfdfe 0%, #f8f9fa 54%, #f5f9fb 100%) !important; +} + +html body #root .ecommerce-standalone.web-shell .ecommerce-standalone__topbar { + background: transparent !important; + box-shadow: none !important; +} + +html body #root .ecommerce-standalone.web-shell .ecommerce-standalone__topbar::after { + content: none !important; +} + +/* #/imageWorkbench inspiration shelves below the toolbox. */ +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .clone-ai-preview.clone-ai-preview:has(.ecom-inspiration-lab) { + overflow-x: hidden !important; + overflow-y: auto !important; + padding-bottom: 88px !important; + scrollbar-width: thin !important; + scrollbar-color: rgba(16, 115, 204, 0.2) transparent !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .clone-ai-preview.clone-ai-preview:has(.ecom-inspiration-lab)::-webkit-scrollbar { + width: 8px !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .clone-ai-preview.clone-ai-preview:has(.ecom-inspiration-lab)::-webkit-scrollbar-thumb { + border: 2px solid transparent !important; + border-radius: 999px !important; + background: rgba(16, 115, 204, 0.18) !important; + background-clip: content-box !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-composer-wrap.ecom-command-composer-wrap:has(.ecom-inspiration-lab).is-before-generate { + top: clamp(96px, 11vh, 132px) !important; + transform: translateX(-50%) !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-composer-wrap.ecom-command-composer-wrap:has(.ecom-inspiration-lab) { + width: min(1220px, calc(100vw - clamp(64px, 8vw, 148px))) !important; + gap: 16px !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-composer-wrap.ecom-command-composer-wrap:has(.ecom-inspiration-lab) .clone-ai-input-wrapper.ecom-command-composer, +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-composer-wrap.ecom-command-composer-wrap:has(.ecom-inspiration-lab) .ecom-command-quick-board, +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-inspiration-lab { + width: min(100%, 1088px) !important; + margin-inline: auto !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-inspiration-lab { + display: grid !important; + gap: 12px !important; + padding: 4px 0 24px !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-inspiration-tabs { + display: flex !important; + align-items: center !important; + gap: 6px !important; + min-height: 34px !important; + padding: 0 2px !important; + overflow-x: auto !important; + scrollbar-width: none !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-inspiration-tabs::-webkit-scrollbar { + display: none !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-inspiration-tabs button { + flex: 0 0 auto !important; + min-height: 30px !important; + padding: 0 12px !important; + border: 1px solid transparent !important; + border-radius: 999px !important; + background: transparent !important; + color: rgba(16, 32, 44, 0.54) !important; + font-size: 12px !important; + font-weight: 760 !important; + cursor: pointer !important; + transition: background 160ms ease, border-color 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"] .ecom-inspiration-tabs button:hover, +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-inspiration-tabs button.is-active { + border-color: rgba(30, 189, 219, 0.16) !important; + background: rgba(255, 255, 255, 0.72) !important; + color: rgba(16, 32, 44, 0.88) !important; + box-shadow: 0 8px 18px rgba(16, 115, 204, 0.045) !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-inspiration-rows { + display: grid !important; + gap: 14px !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-inspiration-row { + display: grid !important; + grid-template-columns: 112px minmax(0, 1fr) !important; + gap: 14px !important; + min-height: 168px !important; + padding: 14px !important; + border: 1px solid rgba(30, 189, 219, 0.1) !important; + border-radius: 22px !important; + background: + linear-gradient(180deg, rgba(255, 255, 255, 0.86), rgba(247, 253, 254, 0.66)), + rgba(255, 255, 255, 0.74) !important; + box-shadow: + 0 20px 54px rgba(16, 115, 204, 0.06), + inset 0 1px 0 rgba(255, 255, 255, 0.76) !important; + overflow: hidden !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-inspiration-row__meta { + display: grid !important; + grid-template-rows: auto auto 1fr !important; + align-content: start !important; + gap: 7px !important; + min-width: 0 !important; + padding: 10px 6px 8px !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-inspiration-row__meta strong { + color: rgba(16, 32, 44, 0.9) !important; + font-size: 15px !important; + font-weight: 860 !important; + line-height: 1.2 !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-inspiration-row__meta span { + color: rgba(16, 32, 44, 0.45) !important; + font-size: 12px !important; + line-height: 1.45 !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-inspiration-row__controls { + display: flex !important; + align-self: end !important; + gap: 8px !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-inspiration-row__controls button { + display: inline-grid !important; + width: 30px !important; + height: 30px !important; + place-items: center !important; + border: 1px solid rgba(30, 189, 219, 0.12) !important; + border-radius: 999px !important; + background: rgba(255, 255, 255, 0.72) !important; + color: rgba(16, 32, 44, 0.54) !important; + cursor: pointer !important; + transition: border-color 160ms ease, 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"] .ecom-inspiration-row__controls button:hover { + border-color: rgba(30, 189, 219, 0.28) !important; + background: rgba(235, 251, 254, 0.92) !important; + color: rgba(16, 115, 204, 0.82) !important; + transform: translateY(-1px) !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-inspiration-strip { + display: grid !important; + grid-auto-flow: column !important; + grid-auto-columns: minmax(260px, 1fr) !important; + gap: 10px !important; + min-width: 0 !important; + overflow-x: auto !important; + overflow-y: hidden !important; + overscroll-behavior-x: contain !important; + scroll-snap-type: x proximity !important; + scrollbar-width: none !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-inspiration-strip::-webkit-scrollbar { + display: none !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-inspiration-card { + position: relative !important; + display: flex !important; + flex-direction: column !important; + justify-content: flex-end !important; + min-height: 210px !important; + padding: 0 !important; + border: 1px solid rgba(30, 189, 219, 0.09) !important; + border-radius: 16px !important; + background: #edf8fb !important; + scroll-snap-align: start !important; + overflow: hidden !important; + cursor: pointer !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-inspiration-card__visual { + position: absolute !important; + inset: 0 !important; + height: 100% !important; + min-height: 0 !important; + overflow: hidden !important; + border-radius: 0 !important; + background: #edf8fb !important; + transition: transform 0.4s cubic-bezier(0.16, 1, 0.3, 1) !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-inspiration-card:hover .ecom-inspiration-card__visual { + transform: scale(1.04) !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-inspiration-card__visual img, +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-inspiration-card__visual video { + display: block !important; + width: 100% !important; + height: 100% !important; + object-fit: cover !important; + object-position: center !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-inspiration-card strong { + position: relative !important; + z-index: 2 !important; + margin-top: 0 !important; + padding: 0 14px !important; + overflow: hidden !important; + color: #fff !important; + font-size: 14px !important; + font-weight: 820 !important; + line-height: 1.28 !important; + text-overflow: ellipsis !important; + white-space: nowrap !important; + text-shadow: 0 1px 4px rgba(0, 0, 0, 0.45) !important; + opacity: 0 !important; + transform: translateY(8px) !important; + transition: opacity 0.32s cubic-bezier(0.16, 1, 0.3, 1), transform 0.32s cubic-bezier(0.16, 1, 0.3, 1) !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-inspiration-card:hover strong { + opacity: 1 !important; + transform: translateY(0) !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-inspiration-card p { + position: relative !important; + z-index: 2 !important; + margin: 3px 0 0 !important; + padding: 0 14px 14px !important; + overflow: hidden !important; + color: rgba(255, 255, 255, 0.78) !important; + font-size: 11px !important; + line-height: 1.4 !important; + text-overflow: ellipsis !important; + white-space: nowrap !important; + text-shadow: 0 1px 3px rgba(0, 0, 0, 0.4) !important; + opacity: 0 !important; + transform: translateY(8px) !important; + transition: opacity 0.32s cubic-bezier(0.16, 1, 0.3, 1) 0.04s, transform 0.32s cubic-bezier(0.16, 1, 0.3, 1) 0.04s !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-inspiration-card:hover p { + opacity: 1 !important; + transform: translateY(0) !important; +} + +/* hover 底部渐变遮罩 */ +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-inspiration-card::after { + content: "" !important; + position: absolute !important; + inset: 0 !important; + z-index: 1 !important; + background: linear-gradient(0deg, rgba(0, 0, 0, 0.58) 0%, rgba(0, 0, 0, 0) 55%) !important; + opacity: 0 !important; + transition: opacity 0.36s cubic-bezier(0.16, 1, 0.3, 1) !important; + pointer-events: none !important; + border-radius: 16px !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-inspiration-card:hover::after { + opacity: 1 !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-inspiration-card em { + position: absolute !important; + top: 12px !important; + right: 14px !important; + z-index: 3 !important; + color: rgba(255, 255, 255, 0.55) !important; + font-size: 10px !important; + font-style: normal !important; + font-weight: 800 !important; + text-shadow: 0 1px 3px rgba(0, 0, 0, 0.35) !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-inspiration-row--team .ecom-inspiration-strip { + grid-auto-columns: minmax(300px, 1fr) !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-inspiration-row--team .ecom-inspiration-card { + min-height: 210px !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-inspiration-row--listing .ecom-inspiration-card { + min-height: 260px !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-inspiration-row--video .ecom-inspiration-card { + min-height: 492px !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-inspiration-row--video .ecom-inspiration-card__visual { + inset: 0 !important; + height: 100% !important; + min-height: 0 !important; + aspect-ratio: auto !important; + background: #edf8fb !important; +} + +/* ── Inspiration fullscreen preview ── */ +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-inspiration-preview { + position: fixed !important; + inset: 0 !important; + z-index: 9999 !important; + display: flex !important; + align-items: center !important; + justify-content: center !important; + animation: ecom-preview-fade-in 0.28s cubic-bezier(0.16, 1, 0.3, 1) !important; +} + +@keyframes ecom-preview-fade-in { + from { opacity: 0; } + to { opacity: 1; } +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-inspiration-preview__backdrop { + position: absolute !important; + inset: 0 !important; + background: rgba(0, 0, 0, 0.72) !important; + backdrop-filter: blur(8px) !important; + -webkit-backdrop-filter: blur(8px) !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-inspiration-preview__content { + position: relative !important; + z-index: 1 !important; + max-width: 90vw !important; + max-height: 90vh !important; + animation: ecom-preview-scale-in 0.32s cubic-bezier(0.16, 1, 0.3, 1) !important; +} + +@keyframes ecom-preview-scale-in { + from { opacity: 0; transform: scale(0.92); } + to { opacity: 1; transform: scale(1); } +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-inspiration-preview__media { + display: block !important; + max-width: 90vw !important; + max-height: 85vh !important; + border-radius: 16px !important; + object-fit: contain !important; + box-shadow: 0 24px 80px rgba(0, 0, 0, 0.4) !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-inspiration-preview__close { + position: absolute !important; + top: -14px !important; + right: -14px !important; + z-index: 2 !important; + display: flex !important; + align-items: center !important; + justify-content: center !important; + width: 36px !important; + height: 36px !important; + border: 0 !important; + border-radius: 50% !important; + background: rgba(255, 255, 255, 0.92) !important; + color: #1a2a3a !important; + font-size: 16px !important; + line-height: 1 !important; + cursor: pointer !important; + box-shadow: 0 2px 12px rgba(0, 0, 0, 0.18) !important; + transition: background 0.2s, transform 0.2s !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-inspiration-preview__close:hover { + background: #fff !important; + transform: scale(1.1) !important; +} + +body .ecom-inspiration-preview { + position: fixed !important; + inset: 0 !important; + z-index: 2147483000 !important; + display: grid !important; + place-items: center !important; + padding: 32px !important; + overflow: hidden !important; + background: rgba(8, 18, 28, 0.62) !important; + backdrop-filter: blur(10px) !important; + -webkit-backdrop-filter: blur(10px) !important; + animation: ecom-preview-fade-in 0.22s cubic-bezier(0.16, 1, 0.3, 1) !important; +} + +body .ecom-inspiration-preview__backdrop { + position: absolute !important; + inset: 0 !important; +} + +body .ecom-inspiration-preview__content { + position: relative !important; + z-index: 1 !important; + display: grid !important; + place-items: center !important; + max-width: min(1280px, calc(100vw - 64px)) !important; + max-height: calc(100vh - 64px) !important; + overflow: hidden !important; + border-radius: 16px !important; + box-shadow: 0 24px 80px rgba(0, 0, 0, 0.34) !important; + animation: ecom-preview-scale-in 0.26s cubic-bezier(0.16, 1, 0.3, 1) !important; +} + +body .ecom-inspiration-preview__media { + display: block !important; + width: auto !important; + height: auto !important; + max-width: min(1280px, calc(100vw - 64px)) !important; + max-height: calc(100vh - 64px) !important; + object-fit: contain !important; + border-radius: 16px !important; +} + +body .ecom-inspiration-preview__close { + display: none !important; +} + +/* 灵感预览:右下角"使用此提示词"动作条,避开视频底部控制条。 */ +body .ecom-inspiration-preview__actions { + position: absolute !important; + right: 16px !important; + bottom: 16px !important; + z-index: 2 !important; + display: flex !important; + gap: 10px !important; +} + +body .ecom-inspiration-preview__use-prompt { + display: inline-flex !important; + align-items: center !important; + gap: 8px !important; + padding: 10px 20px !important; + border: 1px solid rgba(255, 255, 255, 0.28) !important; + border-radius: 999px !important; + background: rgba(16, 32, 44, 0.72) !important; + backdrop-filter: blur(8px) !important; + -webkit-backdrop-filter: blur(8px) !important; + color: #ffffff !important; + font-size: 14px !important; + font-weight: 600 !important; + cursor: pointer !important; + box-shadow: 0 8px 24px rgba(0, 0, 0, 0.28) !important; + transition: background 160ms ease, transform 160ms ease, border-color 160ms ease !important; +} + +body .ecom-inspiration-preview__use-prompt:hover { + border-color: rgba(30, 189, 219, 0.6) !important; + background: rgba(30, 189, 219, 0.92) !important; + transform: translateY(-1px) !important; +} + +@media (max-width: 760px) { + body .ecom-inspiration-preview { + padding: 14px !important; + } + + body .ecom-inspiration-preview__content, + body .ecom-inspiration-preview__media { + max-width: calc(100vw - 28px) !important; + max-height: calc(100vh - 28px) !important; + } +} + +@media (min-width: 1440px) { + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-composer-wrap.ecom-command-composer-wrap:has(.ecom-inspiration-lab) { + width: min(1360px, calc(100vw - 132px)) !important; + } + + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-inspiration-lab { + width: min(100%, 1280px) !important; + } +} + +@media (max-width: 900px) { + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-inspiration-row { + grid-template-columns: minmax(0, 1fr) !important; + } + + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-inspiration-row__meta { + grid-template-columns: minmax(0, 1fr) auto !important; + grid-template-rows: auto auto !important; + padding: 2px 2px 0 !important; + } + + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-inspiration-row__controls { + grid-column: 2 !important; + grid-row: 1 / span 2 !important; + align-self: center !important; + } +} + +/* #/imageWorkbench inspiration shelves final sizing: make the case shelves immersive without stretching the composer. */ +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"]:has(.ecom-inspiration-lab) { + --ecom-history-offset: 0px !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-composer-wrap.ecom-command-composer-wrap:has(.ecom-inspiration-lab) { + width: min(1440px, calc(100% - clamp(28px, 2.6vw, 44px))) !important; + padding-inline: clamp(12px, 1.55vw, 24px) !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-composer-wrap.ecom-command-composer-wrap:has(.ecom-inspiration-lab).is-before-generate { + top: clamp(20px, 3vh, 34px) !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-composer-wrap.ecom-command-composer-wrap:has(.ecom-inspiration-lab) .clone-ai-input-wrapper.ecom-command-composer, +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-composer-wrap.ecom-command-composer-wrap:has(.ecom-inspiration-lab) .ecom-command-quick-board { + width: min(100%, 1088px) !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-composer-wrap.ecom-command-composer-wrap:has(.ecom-inspiration-lab) .ecom-command-quick-board { + width: min(100%, 820px) !important; + min-height: 0 !important; + grid-template-columns: repeat(5, minmax(0, 1fr)) !important; + align-items: stretch !important; + gap: 10px !important; + margin-inline: auto !important; + padding: 0 !important; + border-radius: 0 !important; + background: transparent !important; + box-shadow: none !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-composer-wrap.ecom-command-composer-wrap:has(.ecom-inspiration-lab) .ecom-command-quick-board button { + min-height: 58px !important; + justify-content: center !important; + padding: 0 14px !important; + gap: 8px !important; + border-radius: 14px !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-composer-wrap.ecom-command-composer-wrap:has(.ecom-inspiration-lab) .ecom-command-quick-board button > span { + width: 28px !important; + height: 28px !important; + flex: 0 0 28px !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-composer-wrap.ecom-command-composer-wrap:has(.ecom-inspiration-lab) .ecom-command-quick-board strong { + font-size: 13px !important; + line-height: 1.2 !important; + white-space: nowrap !important; +} + +@media (max-width: 760px) { + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-composer-wrap.ecom-command-composer-wrap:has(.ecom-inspiration-lab) .ecom-command-quick-board { + width: min(100%, 480px) !important; + grid-template-columns: repeat(3, minmax(0, 1fr)) !important; + } +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-inspiration-lab { + position: relative !important; + width: 100% !important; + max-width: 1400px !important; + margin-inline: auto !important; + padding: 8px clamp(4px, 0.8vw, 12px) 28px !important; + overflow: visible !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-inspiration-lab::before { + content: "" !important; + position: absolute !important; + z-index: -1 !important; + inset: 22px calc(clamp(4px, 0.8vw, 12px) * -1) 4px !important; + border-radius: 30px !important; + background: + linear-gradient(90deg, rgba(255, 255, 255, 0), rgba(255, 255, 255, 0.72) 12%, rgba(255, 255, 255, 0.72) 88%, rgba(255, 255, 255, 0)), + linear-gradient(180deg, rgba(245, 252, 254, 0.4), rgba(245, 249, 251, 0.08)) !important; + pointer-events: none !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-inspiration-tabs { + padding-inline: clamp(4px, 0.7vw, 10px) !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-inspiration-row { + grid-template-columns: clamp(112px, 9.5vw, 142px) minmax(0, 1fr) !important; + gap: clamp(14px, 1.25vw, 20px) !important; + padding: clamp(14px, 1.15vw, 18px) !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-inspiration-strip { + grid-auto-columns: minmax(252px, 0.25fr) !important; + gap: clamp(10px, 0.85vw, 14px) !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-inspiration-row--team .ecom-inspiration-strip { + grid-auto-columns: minmax(286px, 0.25fr) !important; +} + +@media (max-width: 900px) { + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-composer-wrap.ecom-command-composer-wrap:has(.ecom-inspiration-lab) { + width: min(100%, calc(100vw - 24px)) !important; + } + + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-inspiration-lab { + padding-inline: 0 !important; + } + + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-inspiration-row { + grid-template-columns: minmax(0, 1fr) !important; + } +} + +/* #/imageWorkbench spacing correction: keep the generation composer close to the original first-screen position. */ +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .clone-ai-preview.clone-ai-preview:has(.ecom-inspiration-lab) { + padding-top: clamp(18px, 2.5vh, 30px) !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-composer-wrap.ecom-command-composer-wrap:has(.ecom-inspiration-lab) { + gap: clamp(12px, 1.25vw, 16px) !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-composer-wrap.ecom-command-composer-wrap:has(.ecom-inspiration-lab).is-before-generate { + top: clamp(8px, 1.35vh, 14px) !important; +} + +@media (max-width: 900px) { + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .clone-ai-preview.clone-ai-preview:has(.ecom-inspiration-lab) { + padding-top: 12px !important; + } + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-composer-wrap.ecom-command-composer-wrap:has(.ecom-inspiration-lab).is-before-generate { + top: 8px !important; +} +} + +/* Ecommerce viewport fit: keep standalone tool pages inside the visible app area. */ +body.ecommerce-standalone-body, +body.ecommerce-standalone-body #root { + width: 100% !important; + height: 100% !important; + overflow: hidden !important; +} + +html body #root .ecommerce-standalone.web-shell { + --ecommerce-topbar-height: 66px; + width: 100% !important; + height: 100dvh !important; + min-height: 0 !important; + overflow: hidden !important; +} + +html body #root .ecommerce-standalone.web-shell .ecommerce-standalone__topbar { + min-height: var(--ecommerce-topbar-height) !important; +} + +html body #root .ecommerce-standalone.web-shell .ecommerce-standalone__content { + box-sizing: content-box !important; + height: calc(100dvh - var(--ecommerce-topbar-height)) !important; + min-height: 0 !important; + padding-top: var(--ecommerce-topbar-height) !important; + overflow: hidden !important; +} + +html body #root .ecommerce-standalone.web-shell .ecommerce-standalone__content > .error-boundary, +html body #root .ecommerce-standalone.web-shell .ecommerce-standalone__content .product-clone-page, +html body #root .ecommerce-standalone.web-shell .product-clone-page > .product-clone-shell { + height: 100% !important; + min-height: 0 !important; + overflow: hidden !important; +} + +html body #root .ecommerce-standalone.web-shell .product-clone-page[data-tool="clone"].is-smart-cutout-page, +html body #root .ecommerce-standalone.web-shell .product-clone-page[data-tool="clone"].is-quick-set-page, +html body #root .ecommerce-standalone.web-shell .product-clone-page[data-tool="clone"].is-watermark-page { + --ecom-history-offset: 0px !important; + --ecom-history-panel-width: 0px !important; + box-sizing: border-box !important; + width: 100% !important; + height: 100% !important; + min-height: 0 !important; + padding-right: 0 !important; + overflow: hidden !important; +} + +html body #root .ecommerce-standalone.web-shell .product-clone-page[data-tool="clone"].is-translate-page { + --ecom-history-offset: 0px !important; + --ecom-history-panel-width: 0px !important; + box-sizing: border-box !important; + width: 100% !important; + height: 100% !important; + min-height: 0 !important; + padding-right: 0 !important; + overflow: hidden !important; +} + +html body #root .ecommerce-standalone.web-shell .product-clone-page[data-tool="clone"].is-smart-cutout-page > .product-clone-shell, +html body #root .ecommerce-standalone.web-shell .product-clone-page[data-tool="clone"].is-quick-set-page > .product-clone-shell, +html body #root .ecommerce-standalone.web-shell .product-clone-page[data-tool="clone"].is-watermark-page > .product-clone-shell, +html body #root .ecommerce-standalone.web-shell .product-clone-page[data-tool="clone"].is-translate-page > .product-clone-shell { + box-sizing: border-box !important; + width: 100% !important; + max-width: none !important; + padding-right: 0 !important; +} + +html body #root .ecommerce-standalone.web-shell .ecom-smart-cutout-page, +html body #root .ecommerce-standalone.web-shell .ecom-watermark-page, +html body #root .ecommerce-standalone.web-shell .ecom-translate-page, +html body #root .ecommerce-standalone.web-shell .ecom-quick-set-page { + box-sizing: border-box !important; + width: 100% !important; + max-width: none !important; + height: 100% !important; + min-height: 0 !important; + overflow: hidden !important; +} + +html body #root .ecommerce-standalone.web-shell .ecom-smart-cutout-page.is-upload { + display: grid !important; + grid-template-rows: minmax(0, 1fr) !important; +} + +html body #root .ecommerce-standalone.web-shell .ecom-smart-cutout-nav { + position: absolute !important; + top: 18px !important; + left: 24px !important; + margin: 0 !important; +} + +html body #root .ecommerce-standalone.web-shell .ecom-smart-cutout-upload { + box-sizing: border-box !important; + width: 100% !important; + height: 100% !important; + min-height: 0 !important; + align-content: center !important; + justify-items: center !important; + padding: clamp(78px, 8vh, 104px) clamp(24px, 4vw, 48px) clamp(28px, 5vh, 56px) !important; + overflow: hidden !important; +} + +html body #root .ecommerce-standalone.web-shell .ecom-smart-cutout-upload__body { + justify-content: center !important; + align-items: stretch !important; + margin-inline: auto !important; +} + +html body #root .ecommerce-standalone.web-shell .ecom-quick-set-body { + height: 100% !important; + min-height: 0 !important; + overflow: hidden !important; +} + +html body #root .ecommerce-standalone.web-shell .ecom-quick-set-panel { + min-height: 0 !important; + overflow-y: auto !important; + scrollbar-width: none !important; + -ms-overflow-style: none !important; +} + +html body #root .ecommerce-standalone.web-shell .ecom-quick-set-panel::-webkit-scrollbar { + width: 0 !important; + height: 0 !important; + display: none !important; +} + +html body #root .ecommerce-standalone.web-shell .ecom-quick-set-stage { + min-height: 0 !important; + overflow: hidden !important; +} + +html body #root .ecommerce-standalone.web-shell .ecom-quick-set-canvas { + min-height: 0 !important; + overflow: hidden !important; +} + +html body #root .ecommerce-standalone.web-shell .ecom-watermark-page { + grid-template-columns: minmax(320px, 350px) minmax(0, 1fr) !important; + padding-top: 0 !important; + padding-left: 0 !important; + padding-right: 0 !important; + padding-bottom: 0 !important; + gap: 0 !important; +} + +html body #root .ecommerce-standalone.web-shell .ecom-translate-page { + grid-template-columns: minmax(320px, 350px) minmax(0, 1fr) !important; + padding-top: 0 !important; + padding-left: 0 !important; + padding-right: 0 !important; + padding-bottom: 0 !important; + gap: 0 !important; +} + +html body #root .ecommerce-standalone.web-shell .ecom-watermark-side, +html body #root .ecommerce-standalone.web-shell .ecom-watermark-workspace { + min-height: 0 !important; + overflow: hidden !important; +} + +@media (max-width: 1020px) { + html body #root .ecommerce-standalone.web-shell .ecom-smart-cutout-upload { + overflow: auto !important; + } +} + +@media (max-width: 640px) { + html body #root .ecommerce-standalone.web-shell { + --ecommerce-topbar-height: 62px; + } +} + +/* Preview modal actions stay inside the deliberate image inspection moment. */ +html body #root .ecommerce-standalone.ecommerce-standalone .product-set-preview-modal { + gap: 14px !important; + border-color: rgba(30, 189, 219, 0.16) !important; + box-shadow: + 0 26px 72px rgba(16, 32, 44, 0.18), + 0 8px 24px rgba(16, 115, 204, 0.08), + inset 0 1px 0 rgba(255, 255, 255, 0.86) !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-set-preview-footer { + display: flex !important; + align-items: center !important; + justify-content: space-between !important; + gap: 16px !important; + min-width: 0 !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-set-preview-footer strong { + min-width: 0 !important; + overflow: hidden !important; + color: #10202c !important; + font-size: 15px !important; + font-weight: 800 !important; + line-height: 1.4 !important; + text-overflow: ellipsis !important; + white-space: nowrap !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-set-preview-actions { + display: inline-flex !important; + align-items: center !important; + justify-content: flex-end !important; + gap: 10px !important; + flex: 0 0 auto !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-set-preview-action { + display: inline-flex !important; + align-items: center !important; + justify-content: center !important; + gap: 7px !important; + height: 38px !important; + min-height: 38px !important; + padding: 0 14px !important; + border: 1px solid rgba(30, 189, 219, 0.2) !important; + border-radius: 999px !important; + color: #1073cc !important; + background: linear-gradient(180deg, rgba(255, 255, 255, 0.98), rgba(241, 251, 253, 0.92)) !important; + box-shadow: + 0 8px 18px rgba(16, 115, 204, 0.08), + inset 0 1px 0 rgba(255, 255, 255, 0.9) !important; + font-size: 14px !important; + font-weight: 750 !important; + cursor: pointer !important; + transition: + border-color 160ms ease, + color 160ms ease, + background 160ms ease, + transform 160ms ease, + box-shadow 160ms ease !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-set-preview-action:hover, +html body #root .ecommerce-standalone.ecommerce-standalone .product-set-preview-action:focus-visible { + border-color: rgba(30, 189, 219, 0.42) !important; + background: #ffffff !important; + outline: none !important; + transform: translateY(-1px) !important; + box-shadow: + 0 12px 24px rgba(16, 115, 204, 0.12), + inset 0 1px 0 rgba(255, 255, 255, 0.94) !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-set-preview-action--danger { + border-color: rgba(255, 77, 79, 0.16) !important; + color: #d84a4d !important; + background: linear-gradient(180deg, rgba(255, 255, 255, 0.98), rgba(255, 246, 246, 0.94)) !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-set-preview-action--danger:hover, +html body #root .ecommerce-standalone.ecommerce-standalone .product-set-preview-action--danger:focus-visible { + border-color: rgba(255, 77, 79, 0.28) !important; + color: #c93639 !important; +} + +@media (max-width: 640px) { + html body #root .ecommerce-standalone.ecommerce-standalone .product-set-preview-footer { + align-items: stretch !important; + flex-direction: column !important; + } + + html body #root .ecommerce-standalone.ecommerce-standalone .product-set-preview-actions { + justify-content: stretch !important; + width: 100% !important; + } + + html body #root .ecommerce-standalone.ecommerce-standalone .product-set-preview-action { + flex: 1 1 0 !important; + } +} + +/* History record detail: compact composer becomes a stable summary bar, then expands on click. */ +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"].is-history-detail { + --history-detail-workspace-width: calc(100vw - var(--ecom-history-panel-width, 292px)); +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"].is-history-detail .ecom-command-composer-wrap.has-generated.is-compact { + position: fixed !important; + top: calc(var(--ecommerce-topbar-height, 66px) + clamp(0px, 0.6vh, 6px)) !important; + left: calc(var(--history-detail-workspace-width) / 2) !important; + width: min(760px, calc(var(--history-detail-workspace-width) - clamp(48px, 8vw, 96px))) !important; + gap: 0 !important; + transform: translateX(-50%) !important; + z-index: 72 !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"].is-history-detail .ecom-command-composer-wrap.has-generated.is-compact .ecom-command-title { + display: none !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"].is-history-detail .ecom-command-composer-wrap.has-generated.is-compact .clone-ai-input-wrapper.ecom-command-composer, +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"].is-history-detail .ecom-command-composer-wrap.has-generated.is-compact .clone-ai-input-wrapper.ecom-command-composer:has(.ecom-command-asset-popover) { + display: grid !important; + grid-template-columns: auto minmax(0, 1fr) auto !important; + grid-template-rows: minmax(64px, auto) !important; + align-items: center !important; + column-gap: 16px !important; + min-height: clamp(68px, 8.8vh, 82px) !important; + max-height: 86px !important; + padding: clamp(8px, 1.2vh, 10px) 12px clamp(8px, 1.2vh, 10px) 16px !important; + overflow: hidden !important; + border: 1px solid rgba(30, 189, 219, 0.16) !important; + border-radius: 999px !important; + background: + linear-gradient(180deg, rgba(255, 255, 255, 0.98), rgba(248, 253, 254, 0.94)), + #feffff !important; + box-shadow: + 0 18px 46px rgba(16, 115, 204, 0.1), + 0 4px 14px rgba(30, 189, 219, 0.055), + inset 0 1px 0 rgba(255, 255, 255, 0.88) !important; + cursor: text !important; + backdrop-filter: blur(18px) saturate(1.08) !important; + -webkit-backdrop-filter: blur(18px) saturate(1.08) !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"].is-history-detail .ecom-command-composer-wrap.has-generated.is-compact .clone-ai-input-wrapper.ecom-command-composer:hover, +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"].is-history-detail .ecom-command-composer-wrap.has-generated.is-compact .clone-ai-input-wrapper.ecom-command-composer:focus-within { + border-color: rgba(30, 189, 219, 0.32) !important; + box-shadow: + 0 22px 54px rgba(16, 115, 204, 0.12), + 0 0 0 4px rgba(30, 189, 219, 0.055), + inset 0 1px 0 rgba(255, 255, 255, 0.9) !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"].is-history-detail .ecom-command-composer-wrap.has-generated.is-compact .clone-ai-input-wrapper.ecom-command-composer > .ecom-command-reference:not(.ecom-command-reference--inline) { + display: none !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"].is-history-detail .ecom-command-composer-wrap.has-generated.is-compact .ecom-command-asset-popover, +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"].is-history-detail .ecom-command-composer-wrap.has-generated.is-compact .clone-ai-input-wrapper.ecom-command-composer:has(.ecom-command-asset-popover) .ecom-command-asset-popover { + grid-column: 1 !important; + grid-row: 1 !important; + align-self: center !important; + display: flex !important; + align-items: center !important; + gap: 8px !important; + width: auto !important; + min-width: 52px !important; + max-width: 160px !important; + min-height: 56px !important; + max-height: 56px !important; + padding: 0 !important; + overflow: hidden !important; + border: 0 !important; + background: transparent !important; + box-shadow: none !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"].is-history-detail .ecom-command-composer-wrap.has-generated.is-compact .ecom-command-asset-thumb, +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"].is-history-detail .ecom-command-composer-wrap.has-generated.is-compact .clone-ai-input-wrapper.ecom-command-composer:has(.ecom-command-asset-popover) .ecom-command-asset-thumb { + flex: 0 0 54px !important; + width: 54px !important; + height: 54px !important; + border-radius: 18px !important; + box-shadow: 0 8px 18px rgba(16, 115, 204, 0.12) !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"].is-history-detail .ecom-command-composer-wrap.has-generated.is-compact .ecom-command-asset-thumb img, +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"].is-history-detail .ecom-command-composer-wrap.has-generated.is-compact .ecom-command-asset-thumb video { + border-radius: 18px !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"].is-history-detail .ecom-command-composer-wrap.has-generated.is-compact .ecom-command-asset-thumb > button { + display: none !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"].is-history-detail .ecom-command-composer-wrap.has-generated.is-compact .ecom-command-asset-add { + flex: 0 0 46px !important; + width: 46px !important; + height: 46px !important; + min-height: 46px !important; + margin: 0 !important; + border-radius: 50% !important; + color: #10202c !important; + background: rgba(16, 32, 44, 0.045) !important; + box-shadow: none !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"].is-history-detail .ecom-command-composer-wrap.has-generated.is-compact .ecom-command-composer textarea, +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"].is-history-detail .ecom-command-composer-wrap.has-generated.is-compact .clone-ai-input-wrapper.ecom-command-composer:has(.ecom-command-asset-popover) > textarea { + grid-column: 2 !important; + grid-row: 1 !important; + align-self: center !important; + min-height: 34px !important; + max-height: 38px !important; + height: 38px !important; + padding: 4px 0 0 !important; + overflow: hidden !important; + color: rgba(16, 32, 44, 0.72) !important; + background: transparent !important; + font-size: clamp(17px, 1.35vw, 22px) !important; + font-weight: 650 !important; + line-height: 32px !important; + text-overflow: ellipsis !important; + white-space: nowrap !important; + resize: none !important; + opacity: 1 !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"].is-history-detail .ecom-command-composer-wrap.has-generated.is-compact .ecom-command-composer textarea::placeholder { + color: rgba(16, 32, 44, 0.48) !important; + opacity: 1 !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"].is-history-detail .ecom-command-composer-wrap.has-generated.is-compact .ecom-command-toolbar, +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"].is-history-detail .ecom-command-composer-wrap.has-generated.is-compact .clone-ai-input-wrapper.ecom-command-composer:has(.ecom-command-asset-popover) .ecom-command-toolbar { + grid-column: 3 !important; + grid-row: 1 !important; + align-self: center !important; + display: flex !important; + align-items: center !important; + justify-content: center !important; + min-height: 56px !important; + padding: 0 !important; + overflow: visible !important; + border: 0 !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"].is-history-detail .ecom-command-composer-wrap.has-generated.is-compact .ecom-command-option-row { + display: none !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"].is-history-detail .ecom-command-composer-wrap.has-generated.is-compact .ecom-command-submit-row { + display: flex !important; + align-items: center !important; + justify-content: center !important; + padding: 0 !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"].is-history-detail .ecom-command-composer-wrap.has-generated.is-compact .clone-ai-send-button.ecom-command-send { + width: 58px !important; + height: 58px !important; + min-height: 58px !important; + border-radius: 50% !important; + background: linear-gradient(135deg, #1073cc 0%, #1ebddb 100%) !important; + box-shadow: + 0 14px 28px rgba(16, 115, 204, 0.22), + inset 0 1px 0 rgba(255, 255, 255, 0.32) !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"].is-history-detail .ecom-command-composer-wrap.has-generated.is-compact .clone-ai-send-button.ecom-command-send:hover:not(:disabled) { + transform: translateY(-1px) scale(1.02) !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"].is-history-detail .clone-ai-preview[data-status="done"] { + padding-top: clamp(132px, 18vh, 160px) !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"].is-history-detail .clone-ai-preview[data-status="done"]:has(.ecom-command-composer-wrap:not(.is-compact)) { + padding-top: 380px !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"].is-history-detail .clone-ai-preview-zoom-wrap { + display: flex !important; + justify-content: center !important; + width: 100% !important; + min-width: 100% !important; + transform-origin: center top !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"].is-history-detail .clone-ai-canvas-nodes { + display: flex !important; + justify-content: center !important; + box-sizing: border-box !important; + width: 100% !important; + min-width: 0 !important; + min-height: 260px !important; + padding: 22px clamp(20px, 4vw, 48px) 44px !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"].is-history-detail .clone-ai-canvas-node:not(.is-generating) { + position: relative !important; + top: auto !important; + left: auto !important; + max-width: min(860px, calc(var(--history-detail-workspace-width) - 80px)) !important; + transform: none !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"].is-history-detail .clone-ai-canvas-node .clone-ai-result-grid { + justify-content: center !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"].is-history-detail .ecom-command-history__item { + isolation: isolate !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"].is-history-detail .ecom-command-history__item .ecom-command-history__item-delete { + position: absolute !important; + top: 50% !important; + right: 14px !important; + z-index: 4 !important; + display: inline-flex !important; + align-items: center !important; + justify-content: center !important; + width: 34px !important; + height: 34px !important; + min-height: 34px !important; + margin: 0 !important; + padding: 0 !important; + border: 1px solid rgba(30, 189, 219, 0.16) !important; + border-radius: 12px !important; + color: rgba(16, 32, 44, 0.46) !important; + background: rgba(255, 255, 255, 0.86) !important; + box-shadow: + 0 8px 18px rgba(16, 115, 204, 0.075), + inset 0 1px 0 rgba(255, 255, 255, 0.82) !important; + font-size: 14px !important; + line-height: 1 !important; + transform: translateY(-50%) !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"].is-history-detail .ecom-command-history__item .ecom-command-history__item-delete:hover, +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"].is-history-detail .ecom-command-history__item .ecom-command-history__item-delete:focus-visible { + color: #ff4d4f !important; + background: rgba(255, 255, 255, 0.95) !important; + border-color: rgba(255, 77, 79, 0.2) !important; + outline: none !important; + transform: translateY(-50%) !important; +} + +@media (max-width: 900px) { + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"].is-history-detail { + --history-detail-workspace-width: 100vw; + } + + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"].is-history-detail .ecom-command-composer-wrap.has-generated.is-compact { + left: 50vw !important; + top: calc(var(--ecommerce-topbar-height, 62px) + 2px) !important; + width: min(720px, calc(100vw - 36px)) !important; + } + + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"].is-history-detail .ecom-command-composer-wrap.has-generated.is-compact .clone-ai-input-wrapper.ecom-command-composer, + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"].is-history-detail .ecom-command-composer-wrap.has-generated.is-compact .clone-ai-input-wrapper.ecom-command-composer:has(.ecom-command-asset-popover) { + column-gap: 10px !important; + padding-inline: 12px 10px !important; + min-height: 70px !important; + } + + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"].is-history-detail .ecom-command-composer-wrap.has-generated.is-compact .ecom-command-asset-popover { + max-width: 116px !important; + } + + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"].is-history-detail .clone-ai-canvas-node:not(.is-generating) { + max-width: calc(100vw - 32px) !important; + flex-wrap: wrap !important; + } +} + +/* #/imageWorkbench polish: refine quick action surface and widen inspiration shelves for an immersive first page. */ +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-composer-wrap.ecom-command-composer-wrap:has(.ecom-inspiration-lab) .ecom-command-quick-board { + width: min(100%, 920px) !important; + padding: 7px !important; + gap: 9px !important; + background: + linear-gradient(180deg, rgba(255, 255, 255, 0.76), rgba(246, 252, 254, 0.52)), + rgba(255, 255, 255, 0.5) !important; + box-shadow: + 0 18px 38px rgba(16, 115, 204, 0.05), + inset 0 1px 0 rgba(255, 255, 255, 0.78) !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-quick-board .ecom-command-quick-card--detail, +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-quick-board .ecom-command-quick-card--edit, +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-quick-board .ecom-command-quick-card--cutout, +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-quick-board .ecom-command-quick-card--watermark { + --quick-accent: #1073cc !important; + --quick-accent-soft: rgba(30, 189, 219, 0.16) !important; + --quick-bg: rgba(245, 252, 254, 0.82) !important; + --quick-text: #163447 !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-composer-wrap.ecom-command-composer-wrap:has(.ecom-inspiration-lab) .ecom-command-quick-board button { + min-height: 56px !important; + border: 1px solid rgba(30, 189, 219, 0.09) !important; + background: + linear-gradient(135deg, rgba(255, 255, 255, 0.96), rgba(246, 252, 254, 0.8)) !important; + color: #163447 !important; + box-shadow: + inset 0 1px 0 rgba(255, 255, 255, 0.88), + 0 8px 18px rgba(16, 115, 204, 0.035) !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-composer-wrap.ecom-command-composer-wrap:has(.ecom-inspiration-lab) .ecom-command-quick-board button > span { + width: 30px !important; + height: 30px !important; + flex: 0 0 30px !important; + border-radius: 11px !important; + background: + linear-gradient(180deg, rgba(30, 189, 219, 0.16), rgba(16, 115, 204, 0.08)) !important; + color: #1073cc !important; + box-shadow: + inset 0 1px 0 rgba(255, 255, 255, 0.74), + 0 7px 16px rgba(16, 115, 204, 0.08) !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-composer-wrap.ecom-command-composer-wrap:has(.ecom-inspiration-lab) .ecom-command-quick-board strong { + color: #163447 !important; + font-weight: 650 !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-composer-wrap.ecom-command-composer-wrap:has(.ecom-inspiration-lab) .ecom-command-quick-board button:hover, +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-composer-wrap.ecom-command-composer-wrap:has(.ecom-inspiration-lab) .ecom-command-quick-board button:focus-visible { + border-color: rgba(16, 115, 204, 0.18) !important; + background: + radial-gradient(circle at 16% 20%, rgba(30, 189, 219, 0.2), transparent 42%), + linear-gradient(135deg, #ffffff, rgba(241, 250, 253, 0.92)) !important; + color: #1073cc !important; + box-shadow: + inset 0 1px 0 rgba(255, 255, 255, 0.92), + 0 14px 28px rgba(16, 115, 204, 0.08) !important; + outline: none !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-composer-wrap.ecom-command-composer-wrap:has(.ecom-inspiration-lab) .ecom-command-quick-board button:hover > span, +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-composer-wrap.ecom-command-composer-wrap:has(.ecom-inspiration-lab) .ecom-command-quick-board button:focus-visible > span { + background: + linear-gradient(180deg, rgba(30, 189, 219, 0.22), rgba(16, 115, 204, 0.12)) !important; + color: #0d65b4 !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-composer-wrap.ecom-command-composer-wrap:has(.ecom-inspiration-lab) { + width: min(2360px, calc(100vw - clamp(48px, 4.2vw, 108px))) !important; + max-width: none !important; + padding-inline: clamp(12px, 1.2vw, 22px) !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-inspiration-lab { + width: 100% !important; + max-width: none !important; + padding: 8px 0 30px !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-inspiration-lab::before { + inset: 20px 0 2px !important; + border-radius: 28px !important; + background: + linear-gradient(90deg, rgba(245, 252, 254, 0.18), rgba(255, 255, 255, 0.78) 10%, rgba(255, 255, 255, 0.78) 90%, rgba(245, 252, 254, 0.18)), + linear-gradient(180deg, rgba(245, 252, 254, 0.58), rgba(255, 255, 255, 0.14)) !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-inspiration-tabs { + padding-inline: clamp(12px, 1.2vw, 22px) !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-inspiration-row { + grid-template-columns: clamp(134px, 7vw, 174px) minmax(0, 1fr) !important; + gap: clamp(16px, 1.15vw, 24px) !important; + padding: clamp(14px, 1vw, 20px) clamp(14px, 1.05vw, 22px) !important; + border-color: rgba(16, 115, 204, 0.07) !important; + background: + linear-gradient(135deg, rgba(255, 255, 255, 0.88), rgba(247, 252, 254, 0.72)) !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-inspiration-row__meta { + min-width: 0 !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-inspiration-strip { + grid-auto-columns: clamp(320px, 18.4vw, 470px) !important; + gap: clamp(12px, 0.9vw, 18px) !important; + padding-right: clamp(18px, 1.6vw, 34px) !important; + scroll-padding-inline: clamp(18px, 1.6vw, 34px) !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-inspiration-row--team .ecom-inspiration-strip { + grid-auto-columns: clamp(420px, 24vw, 620px) !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-inspiration-row--listing .ecom-inspiration-strip { + grid-auto-columns: clamp(300px, 16.2vw, 420px) !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-inspiration-row--video .ecom-inspiration-strip { + grid-auto-columns: clamp(360px, 21vw, 540px) !important; +} + +@media (max-width: 900px) { + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-composer-wrap.ecom-command-composer-wrap:has(.ecom-inspiration-lab) { + width: min(100%, calc(100vw - 24px)) !important; + padding-inline: 0 !important; + } + + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-inspiration-row { + grid-template-columns: minmax(0, 1fr) !important; + gap: 12px !important; + padding: 14px !important; + } + + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-inspiration-strip, + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-inspiration-row--team .ecom-inspiration-strip, + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-inspiration-row--listing .ecom-inspiration-strip, + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-inspiration-row--video .ecom-inspiration-strip { + grid-auto-columns: minmax(248px, 76vw) !important; + padding-right: 14px !important; + } +} + +@media (max-width: 640px) { + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-composer-wrap.ecom-command-composer-wrap:has(.ecom-inspiration-lab) .ecom-command-quick-board { + width: min(100%, 420px) !important; + grid-template-columns: repeat(2, minmax(0, 1fr)) !important; + } + + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-composer-wrap.ecom-command-composer-wrap:has(.ecom-inspiration-lab) .ecom-command-quick-board button { + padding-inline: 10px !important; + } +} + +/* #/imageWorkbench compact composer centering: when history is collapsed, center on the visible canvas. */ +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"].is-history-detail.is-history-collapsed { + --history-detail-workspace-width: 100vw !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"].is-history-detail.is-history-collapsed .ecom-command-composer-wrap.has-generated.is-compact { + left: 50vw !important; + width: min(760px, calc(100vw - clamp(32px, 6vw, 96px))) !important; + transform: translateX(-50%) !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"].is-history-detail.is-history-collapsed .ecom-command-composer-wrap.has-generated.is-compact .clone-ai-input-wrapper.ecom-command-composer, +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"].is-history-detail.is-history-collapsed .ecom-command-composer-wrap.has-generated.is-compact .clone-ai-input-wrapper.ecom-command-composer:has(.ecom-command-asset-popover) { + width: 100% !important; + margin-inline: auto !important; +} + +@media (max-width: 640px) { + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"].is-history-detail.is-history-collapsed .ecom-command-composer-wrap.has-generated.is-compact { + top: calc(var(--ecommerce-topbar-height, 62px) + 8px) !important; + width: min(100vw - 22px, 560px) !important; + } + + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"].is-history-detail.is-history-collapsed .ecom-command-composer-wrap.has-generated.is-compact .clone-ai-input-wrapper.ecom-command-composer, + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"].is-history-detail.is-history-collapsed .ecom-command-composer-wrap.has-generated.is-compact .clone-ai-input-wrapper.ecom-command-composer:has(.ecom-command-asset-popover) { + grid-template-columns: auto minmax(0, 1fr) auto !important; + column-gap: 8px !important; + min-height: 62px !important; + max-height: 72px !important; + padding: 8px 9px 8px 10px !important; + } + + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"].is-history-detail.is-history-collapsed .ecom-command-composer-wrap.has-generated.is-compact .ecom-command-asset-popover { + min-width: 42px !important; + max-width: 94px !important; + min-height: 46px !important; + max-height: 46px !important; + } + + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"].is-history-detail.is-history-collapsed .ecom-command-composer-wrap.has-generated.is-compact .ecom-command-asset-thumb { + flex-basis: 44px !important; + width: 44px !important; + height: 44px !important; + border-radius: 14px !important; + } + + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"].is-history-detail.is-history-collapsed .ecom-command-composer-wrap.has-generated.is-compact .ecom-command-asset-add { + flex-basis: 34px !important; + width: 34px !important; + height: 34px !important; + min-height: 34px !important; + } + + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"].is-history-detail.is-history-collapsed .ecom-command-composer-wrap.has-generated.is-compact .ecom-command-composer textarea, + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"].is-history-detail.is-history-collapsed .ecom-command-composer-wrap.has-generated.is-compact .clone-ai-input-wrapper.ecom-command-composer:has(.ecom-command-asset-popover) > textarea { + min-width: 0 !important; + max-height: 32px !important; + font-size: 15px !important; + line-height: 30px !important; + } + + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"].is-history-detail.is-history-collapsed .ecom-command-composer-wrap.has-generated.is-compact .clone-ai-send-button.ecom-command-send { + width: 48px !important; + height: 48px !important; + min-height: 48px !important; + } +} + +/* #/imageWorkbench quick actions final tone: restore category colors and align icon tones with labels. */ +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-quick-board .ecom-command-quick-card--detail { + --quick-accent: #7a5af8 !important; + --quick-bg: #f1edff !important; + --quick-text: #2f245d !important; + --quick-icon: #5f46d9 !important; + --quick-icon-bg: rgba(122, 90, 248, 0.13) !important; + --quick-border: rgba(122, 90, 248, 0.12) !important; + --quick-shadow: rgba(122, 90, 248, 0.1) !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-quick-board .ecom-command-quick-card--edit { + --quick-accent: #cc6b14 !important; + --quick-bg: #fff2e5 !important; + --quick-text: #4e2c11 !important; + --quick-icon: #a95616 !important; + --quick-icon-bg: rgba(204, 107, 20, 0.13) !important; + --quick-border: rgba(204, 107, 20, 0.12) !important; + --quick-shadow: rgba(204, 107, 20, 0.1) !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-quick-board .ecom-command-quick-card--cutout { + --quick-accent: #1073cc !important; + --quick-bg: #eaf5ff !important; + --quick-text: #123454 !important; + --quick-icon: #0f66b3 !important; + --quick-icon-bg: rgba(16, 115, 204, 0.13) !important; + --quick-border: rgba(16, 115, 204, 0.12) !important; + --quick-shadow: rgba(16, 115, 204, 0.1) !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-quick-board .ecom-command-quick-card--watermark { + --quick-accent: #c04468 !important; + --quick-bg: #fff0f5 !important; + --quick-text: #542234 !important; + --quick-icon: #a63a58 !important; + --quick-icon-bg: rgba(192, 68, 104, 0.13) !important; + --quick-border: rgba(192, 68, 104, 0.12) !important; + --quick-shadow: rgba(192, 68, 104, 0.1) !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-composer-wrap.ecom-command-composer-wrap:has(.ecom-inspiration-lab) .ecom-command-quick-board button { + border-color: var(--quick-border) !important; + background: + radial-gradient(circle at 14% 18%, color-mix(in srgb, var(--quick-accent) 15%, transparent), transparent 40%), + linear-gradient(135deg, rgba(255, 255, 255, 0.96), var(--quick-bg)) !important; + color: var(--quick-text) !important; + box-shadow: + inset 0 1px 0 rgba(255, 255, 255, 0.88), + 0 8px 18px rgba(16, 32, 44, 0.032) !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-composer-wrap.ecom-command-composer-wrap:has(.ecom-inspiration-lab) .ecom-command-quick-board button > span { + background: + linear-gradient(180deg, color-mix(in srgb, var(--quick-icon-bg) 78%, #ffffff), rgba(255, 255, 255, 0.62)) !important; + color: var(--quick-icon) !important; + box-shadow: + inset 0 1px 0 rgba(255, 255, 255, 0.82), + 0 7px 16px var(--quick-shadow) !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-composer-wrap.ecom-command-composer-wrap:has(.ecom-inspiration-lab) .ecom-command-quick-board strong { + color: var(--quick-text) !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-composer-wrap.ecom-command-composer-wrap:has(.ecom-inspiration-lab) .ecom-command-quick-board button:hover, +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-composer-wrap.ecom-command-composer-wrap:has(.ecom-inspiration-lab) .ecom-command-quick-board button:focus-visible { + border-color: color-mix(in srgb, var(--quick-accent) 22%, transparent) !important; + background: + radial-gradient(circle at 14% 18%, color-mix(in srgb, var(--quick-accent) 24%, transparent), transparent 42%), + linear-gradient(135deg, #ffffff, color-mix(in srgb, var(--quick-bg) 88%, #ffffff)) !important; + color: var(--quick-icon) !important; + box-shadow: + inset 0 1px 0 rgba(255, 255, 255, 0.9), + 0 14px 28px var(--quick-shadow) !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-composer-wrap.ecom-command-composer-wrap:has(.ecom-inspiration-lab) .ecom-command-quick-board button:hover > span, +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-composer-wrap.ecom-command-composer-wrap:has(.ecom-inspiration-lab) .ecom-command-quick-board button:focus-visible > span { + background: + linear-gradient(180deg, color-mix(in srgb, var(--quick-accent) 18%, #ffffff), color-mix(in srgb, var(--quick-bg) 82%, #ffffff)) !important; + color: var(--quick-icon) !important; +} + +/* #/imageWorkbench quick actions: remove visible borders while keeping the category color system. */ +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-quick-board, +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-quick-board button, +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-quick-board button > span { + border: 0 !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-composer-wrap.ecom-command-composer-wrap:has(.ecom-inspiration-lab) .ecom-command-quick-board button:hover, +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-composer-wrap.ecom-command-composer-wrap:has(.ecom-inspiration-lab) .ecom-command-quick-board button:focus-visible { + border: 0 !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-composer-wrap.ecom-command-composer-wrap:has(.ecom-inspiration-lab) .ecom-command-quick-board, +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-composer-wrap.ecom-command-composer-wrap:has(.ecom-inspiration-lab) .ecom-command-quick-board button, +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-composer-wrap.ecom-command-composer-wrap:has(.ecom-inspiration-lab) .ecom-command-quick-board button > span { + border-width: 0 !important; + border-style: none !important; + border-color: transparent !important; +} + +/* #/imageWorkbench quick actions: soften each action so the tones blend into the page. */ +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-composer-wrap.ecom-command-composer-wrap:has(.ecom-inspiration-lab) .ecom-command-quick-board { + background: rgba(255, 255, 255, 0.3) !important; + box-shadow: none !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-composer-wrap.ecom-command-composer-wrap:has(.ecom-inspiration-lab) .ecom-command-quick-board button { + background: + radial-gradient(circle at 16% 18%, color-mix(in srgb, var(--quick-accent) 10%, transparent), transparent 44%), + linear-gradient(135deg, color-mix(in srgb, var(--quick-bg) 86%, #ffffff), color-mix(in srgb, var(--quick-bg) 96%, #ffffff)) !important; + box-shadow: none !important; + color: var(--quick-text) !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-composer-wrap.ecom-command-composer-wrap:has(.ecom-inspiration-lab) .ecom-command-quick-board button > span { + background: transparent !important; + color: var(--quick-text) !important; + box-shadow: none !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-composer-wrap.ecom-command-composer-wrap:has(.ecom-inspiration-lab) .ecom-command-quick-board button > span .anticon, +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-composer-wrap.ecom-command-composer-wrap:has(.ecom-inspiration-lab) .ecom-command-quick-board button > span svg { + color: inherit !important; + fill: currentColor !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-composer-wrap.ecom-command-composer-wrap:has(.ecom-inspiration-lab) .ecom-command-quick-board button:hover, +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-composer-wrap.ecom-command-composer-wrap:has(.ecom-inspiration-lab) .ecom-command-quick-board button:focus-visible { + background: + radial-gradient(circle at 16% 18%, color-mix(in srgb, var(--quick-accent) 14%, transparent), transparent 44%), + linear-gradient(135deg, color-mix(in srgb, var(--quick-bg) 92%, #ffffff), color-mix(in srgb, var(--quick-bg) 98%, #ffffff)) !important; + box-shadow: none !important; + color: var(--quick-text) !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-composer-wrap.ecom-command-composer-wrap:has(.ecom-inspiration-lab) .ecom-command-quick-board button:hover > span, +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-composer-wrap.ecom-command-composer-wrap:has(.ecom-inspiration-lab) .ecom-command-quick-board button:focus-visible > span { + background: transparent !important; + color: var(--quick-text) !important; + box-shadow: none !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-composer-wrap.ecom-command-composer-wrap:has(.ecom-inspiration-lab) .ecom-command-quick-board button:hover > span .anticon, +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-composer-wrap.ecom-command-composer-wrap:has(.ecom-inspiration-lab) .ecom-command-quick-board button:hover > span svg, +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-composer-wrap.ecom-command-composer-wrap:has(.ecom-inspiration-lab) .ecom-command-quick-board button:focus-visible > span .anticon, +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-composer-wrap.ecom-command-composer-wrap:has(.ecom-inspiration-lab) .ecom-command-quick-board button:focus-visible > span svg { + color: inherit !important; + fill: currentColor !important; +} + +/* #/imageWorkbench generated results: remove all visual labels and their reserved space. */ +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .clone-ai-canvas-node .clone-ai-node-label, +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .clone-ai-canvas-node .clone-ai-main-result > span, +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .clone-ai-canvas-node .clone-ai-result-grid button > span { + display: none !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .clone-ai-canvas-node:not(.is-generating) { + padding-top: 20px !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .clone-ai-canvas-node:not(.is-generating) .clone-ai-node-drag-handle { + height: 100% !important; + background: transparent !important; +} + +/* #/imageWorkbench history records: keep hover delete icon centered in the row. */ +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-history__item { + position: relative !important; + display: block !important; + isolation: isolate !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-history__item .ecom-command-history__item-main { + width: 100% !important; + padding-right: 46px !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-history__item .ecom-command-history__item-delete, +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-history__item:hover .ecom-command-history__item-delete, +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-history__item.is-active .ecom-command-history__item-delete { + grid-column: auto !important; + grid-row: auto !important; + align-self: auto !important; + position: absolute !important; + top: 50% !important; + right: 10px !important; + z-index: 4 !important; + display: inline-flex !important; + align-items: center !important; + justify-content: center !important; + width: 28px !important; + height: 28px !important; + min-width: 28px !important; + min-height: 28px !important; + margin: 0 !important; + padding: 0 !important; + line-height: 1 !important; + transform: translateY(-50%) !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-history__item .ecom-command-history__item-delete .anticon, +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-history__item .ecom-command-history__item-delete svg { + display: block !important; + line-height: 1 !important; +} + +/* #/imageWorkbench composer redesign: mode tabs outside, settings and assets inside. */ +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-mode-tabs { + display: grid !important; + grid-template-columns: repeat(5, minmax(0, 1fr)) !important; + gap: 8px !important; + width: min(100%, 760px) !important; + margin: 0 auto 12px !important; + padding: 4px !important; + border: 1px solid rgba(30, 189, 219, 0.11) !important; + border-radius: 18px !important; + background: rgba(255, 255, 255, 0.64) !important; + box-shadow: + 0 14px 34px rgba(16, 115, 204, 0.055), + inset 0 1px 0 rgba(255, 255, 255, 0.78) !important; + backdrop-filter: blur(14px) saturate(1.08) !important; + -webkit-backdrop-filter: blur(14px) saturate(1.08) !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-mode-tabs button { + --mode-accent: #1073cc; + display: inline-flex !important; + align-items: center !important; + justify-content: center !important; + gap: 7px !important; + min-width: 0 !important; + min-height: 42px !important; + padding: 0 11px !important; + border: 0 !important; + border-radius: 14px !important; + background: transparent !important; + color: rgba(16, 32, 44, 0.66) !important; + box-shadow: none !important; + cursor: pointer !important; + transition: + background 180ms ease, + color 180ms ease, + box-shadow 180ms ease, + transform 180ms ease !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-mode-tabs button:has(.ecom-command-mode-icon--set) { + --mode-accent: #0f8f72; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-mode-tabs button:has(.ecom-command-mode-icon--detail) { + --mode-accent: #7a5af8; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-mode-tabs button:has(.ecom-command-mode-icon--model) { + --mode-accent: #1073cc; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-mode-tabs button:has(.ecom-command-mode-icon--video) { + --mode-accent: #cc6b14; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-mode-tabs button:has(.ecom-command-mode-icon--hot) { + --mode-accent: #c04468; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-mode-tabs button:hover, +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-mode-tabs button.is-active { + background: + radial-gradient(circle at 20% 18%, color-mix(in srgb, var(--mode-accent) 14%, transparent), transparent 58%), + linear-gradient(180deg, rgba(255, 255, 255, 0.98), rgba(247, 252, 254, 0.9)) !important; + color: rgba(16, 32, 44, 0.9) !important; + box-shadow: + inset 0 0 0 1px color-mix(in srgb, var(--mode-accent) 18%, transparent), + 0 10px 22px color-mix(in srgb, var(--mode-accent) 10%, transparent) !important; + transform: translateY(-1px) !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-mode-tabs .ecom-command-mode-icon { + display: inline-grid !important; + width: 24px !important; + height: 24px !important; + min-width: 24px !important; + place-items: center !important; + border: 0 !important; + border-radius: 9px !important; + background: color-mix(in srgb, var(--mode-accent) 11%, #ffffff) !important; + color: var(--mode-accent) !important; + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.7) !important; + font-size: 13px !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-mode-tabs strong { + min-width: 0 !important; + overflow: hidden !important; + font-size: 13px !important; + font-weight: 760 !important; + letter-spacing: 0 !important; + line-height: 1 !important; + text-overflow: ellipsis !important; + white-space: nowrap !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .clone-ai-input-wrapper.ecom-command-composer { + display: grid !important; + grid-template-columns: minmax(0, 1fr) !important; + grid-auto-rows: auto !important; + grid-template-rows: none !important; + align-content: start !important; + row-gap: 12px !important; + min-height: clamp(214px, 17vh, 236px) !important; + padding: 18px 22px 16px !important; + overflow: visible !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .clone-ai-input-wrapper.ecom-command-composer:has(.ecom-command-asset-popover) { + min-height: clamp(256px, 22vh, 286px) !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-option-row.ecom-command-option-row--settings { + grid-column: 1 !important; + grid-row: auto !important; + display: flex !important; + flex-wrap: wrap !important; + align-items: center !important; + justify-content: flex-start !important; + gap: 8px !important; + width: 100% !important; + padding: 0 0 2px !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-option-row.ecom-command-option-row--settings button { + min-width: 0 !important; + min-height: 36px !important; + padding: 0 11px !important; + border: 1px solid rgba(30, 189, 219, 0.12) !important; + border-radius: 13px !important; + background: rgba(248, 253, 255, 0.72) !important; + color: rgba(16, 32, 44, 0.72) !important; + box-shadow: none !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-option-row.ecom-command-option-row--settings button:hover, +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-option-row.ecom-command-option-row--settings button.is-active { + border-color: rgba(30, 189, 219, 0.28) !important; + background: rgba(241, 251, 254, 0.92) !important; + box-shadow: 0 8px 18px rgba(16, 115, 204, 0.055) !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-option-row.ecom-command-option-row--settings .ecom-command-option-icon { + width: 20px !important; + height: 20px !important; + border: 0 !important; + background: rgba(232, 249, 253, 0.78) !important; + color: #0f829b !important; + box-shadow: none !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-asset-popover { + position: static !important; + grid-column: 1 !important; + grid-row: auto !important; + display: flex !important; + align-items: center !important; + justify-content: flex-start !important; + gap: 8px !important; + width: 100% !important; + max-width: 100% !important; + min-height: 62px !important; + max-height: 72px !important; + padding: 8px 2px 10px !important; + overflow-x: auto !important; + overflow-y: visible !important; + border: 0 !important; + border-radius: 0 !important; + background: transparent !important; + box-shadow: none !important; + transform: none !important; + scrollbar-width: thin !important; + scrollbar-color: rgba(16, 115, 204, 0.18) transparent !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-asset-thumb { + flex: 0 0 58px !important; + width: 58px !important; + height: 58px !important; + border: 1px solid rgba(30, 189, 219, 0.12) !important; + border-radius: 14px !important; + background: rgba(246, 251, 253, 0.9) !important; + box-shadow: 0 8px 18px rgba(16, 115, 204, 0.06) !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-asset-thumb img, +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-asset-thumb video { + border-radius: 13px !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-asset-add { + flex: 0 0 38px !important; + width: 38px !important; + height: 38px !important; + min-height: 38px !important; + margin: 0 !important; + border: 0 !important; + border-radius: 12px !important; + background: rgba(232, 249, 253, 0.72) !important; + color: #0f829b !important; + font-size: 24px !important; + box-shadow: none !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-composer textarea { + grid-column: 1 !important; + grid-row: auto !important; + min-height: clamp(82px, 9vh, 106px) !important; + padding: 2px 0 4px !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .clone-ai-input-wrapper.ecom-command-composer:has(.ecom-command-asset-popover) > textarea { + min-height: clamp(68px, 7vh, 92px) !important; + max-height: 112px !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-toolbar { + grid-column: 1 !important; + grid-row: auto !important; + display: flex !important; + align-items: center !important; + justify-content: space-between !important; + gap: 12px !important; + width: 100% !important; + padding: 10px 0 0 !important; + border-top: 1px solid rgba(30, 189, 219, 0.085) !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-composer-actions { + display: flex !important; + align-items: center !important; + justify-content: flex-start !important; + min-width: 0 !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-reference.ecom-command-reference--bottom { + position: static !important; + display: inline-flex !important; + align-items: center !important; + justify-content: center !important; + gap: 7px !important; + width: auto !important; + min-width: 0 !important; + height: 38px !important; + min-height: 38px !important; + margin: 0 !important; + padding: 0 12px !important; + border: 0 !important; + border-radius: 13px !important; + background: rgba(248, 253, 255, 0.78) !important; + color: rgba(16, 32, 44, 0.68) !important; + box-shadow: none !important; + transform: none !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-reference.ecom-command-reference--bottom:hover, +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-reference.ecom-command-reference--bottom.is-dragging { + background: rgba(232, 249, 253, 0.9) !important; + color: #0f829b !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-reference.ecom-command-reference--bottom > span { + display: inline-flex !important; + width: 20px !important; + min-width: 20px !important; + height: 20px !important; + place-items: center !important; + margin: 0 !important; + font-size: 17px !important; + line-height: 1 !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-reference.ecom-command-reference--bottom strong { + display: inline !important; + font-size: 13px !important; + font-weight: 720 !important; + line-height: 1 !important; + white-space: nowrap !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-submit-row { + display: flex !important; + align-items: center !important; + justify-content: flex-end !important; + min-width: 0 !important; +} + +@media (max-width: 900px) { + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-mode-tabs { + grid-template-columns: repeat(5, minmax(94px, 1fr)) !important; + width: 100% !important; + overflow-x: auto !important; + overscroll-behavior-x: contain !important; + scrollbar-width: none !important; + } + + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-mode-tabs::-webkit-scrollbar { + display: none !important; + } +} + +@media (max-width: 640px) { + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-mode-tabs { + grid-template-columns: repeat(5, minmax(88px, 1fr)) !important; + margin-bottom: 10px !important; + } + + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-mode-tabs button { + min-height: 38px !important; + padding-inline: 8px !important; + } + + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-mode-tabs .ecom-command-mode-icon { + width: 22px !important; + height: 22px !important; + min-width: 22px !important; + } + + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .clone-ai-input-wrapper.ecom-command-composer { + min-height: 230px !important; + padding: 15px !important; + row-gap: 10px !important; + } + + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-option-row.ecom-command-option-row--settings button { + flex: 1 1 calc(50% - 5px) !important; + justify-content: flex-start !important; + } + + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-toolbar { + align-items: center !important; + } +} + +@media (max-width: 420px) { + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-option-row.ecom-command-option-row--settings { + display: grid !important; + grid-template-columns: repeat(4, minmax(0, 1fr)) !important; + gap: 7px !important; + justify-content: stretch !important; + overflow: visible !important; + } + + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-option-row.ecom-command-option-row--settings button { + display: inline-flex !important; + width: auto !important; + min-width: 0 !important; + max-width: none !important; + height: 42px !important; + min-height: 42px !important; + padding: 0 !important; + justify-content: center !important; + font-size: 0 !important; + } + + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-option-row.ecom-command-option-row--settings button > span:not(.ecom-command-option-icon) { + display: none !important; + } + + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-option-row.ecom-command-option-row--settings .ecom-command-option-icon { + display: inline-grid !important; + width: 22px !important; + height: 22px !important; + min-width: 22px !important; + margin: 0 !important; + font-size: 14px !important; + } + + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-toolbar { + flex-direction: row !important; + align-items: center !important; + justify-content: space-between !important; + min-height: 58px !important; + height: auto !important; + padding-top: 10px !important; + } + + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-composer-actions, + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-submit-row { + width: auto !important; + min-width: 0 !important; + } + + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-reference.ecom-command-reference--bottom { + width: auto !important; + min-width: 0 !important; + max-width: none !important; + height: 38px !important; + min-height: 38px !important; + padding: 0 12px !important; + font-size: 13px !important; + } + + html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-reference.ecom-command-reference--bottom strong { + display: inline !important; + } +} + +/* Compact composer override: keep the generated-state composer from growing into the canvas. */ +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-composer-wrap.has-generated.is-compact:not(.is-history-detail *) .clone-ai-input-wrapper.ecom-command-composer, +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-composer-wrap.has-generated.is-compact:not(.is-history-detail *) .clone-ai-input-wrapper.ecom-command-composer:has(.ecom-command-asset-popover) { + min-height: 156px !important; + max-height: 186px !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-composer-wrap.has-generated.is-compact:not(.is-history-detail *) .ecom-command-composer textarea { + min-height: 36px !important; + max-height: 36px !important; +} + +/* Composer menu anchors: place option popovers under the clicked control, not under the whole composer. */ +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 { + position: absolute !important; + inset: var(--composer-popover-top, 48px) auto auto var(--composer-popover-left, 0px) !important; + right: auto !important; + bottom: auto !important; + margin: 0 !important; + transform: none !important; + translate: none !important; + z-index: 160 !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--platform { + width: min(360px, calc(100% - var(--composer-popover-left, 0px))) !important; + max-width: min(360px, calc(100% - var(--composer-popover-left, 0px))) !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--languages, +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--ratio-picker { + width: min(420px, calc(100% - var(--composer-popover-left, 0px))) !important; + max-width: min(420px, calc(100% - var(--composer-popover-left, 0px))) !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 { + width: min(520px, calc(100% - var(--composer-popover-left, 0px))) !important; + max-width: min(520px, calc(100% - var(--composer-popover-left, 0px))) !important; +} + +/* Uploaded assets stay as compact attachments inside the composer hierarchy. */ +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .clone-ai-input-wrapper.ecom-command-composer:has(.ecom-command-asset-popover) { + min-height: clamp(224px, 18vh, 250px) !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-asset-popover, +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-composer-wrap:not(.has-generated.is-compact) .clone-ai-input-wrapper.ecom-command-composer:has(.ecom-command-asset-popover) .ecom-command-asset-popover { + position: static !important; + grid-column: 1 !important; + display: inline-flex !important; + align-items: center !important; + justify-content: flex-start !important; + justify-self: start !important; + gap: 8px !important; + width: auto !important; + max-width: min(100%, 420px) !important; + min-height: 48px !important; + max-height: 52px !important; + padding: 0 !important; + overflow-x: auto !important; + overflow-y: visible !important; + border: 0 !important; + border-radius: 0 !important; + background: transparent !important; + box-shadow: none !important; + transform: none !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-asset-thumb, +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-composer-wrap:not(.has-generated.is-compact) .clone-ai-input-wrapper.ecom-command-composer:has(.ecom-command-asset-popover) .ecom-command-asset-thumb { + flex: 0 0 48px !important; + width: 48px !important; + height: 48px !important; + border-radius: 12px !important; +} + +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-asset-add, +html body #root .ecommerce-standalone.ecommerce-standalone .product-clone-page[data-tool="clone"][data-tool="clone"] .ecom-command-composer-wrap:not(.has-generated.is-compact) .clone-ai-input-wrapper.ecom-command-composer:has(.ecom-command-asset-popover) .ecom-command-asset-add { + flex: 0 0 34px !important; + width: 34px !important; + height: 34px !important; + min-height: 34px !important; + margin: 0 !important; + font-size: 22px !important; +} diff --git a/src/utils/translateTaskError.test.ts b/src/utils/translateTaskError.test.ts new file mode 100644 index 0000000..35ecd22 --- /dev/null +++ b/src/utils/translateTaskError.test.ts @@ -0,0 +1,81 @@ +import { describe, it, expect } from "vitest"; +import { classifyTaskError, translateTaskError, type TaskErrorCategory } from "./translateTaskError"; + +// 每条规则至少一个正例,按规则顺序排列(classifyTaskError 先匹配先返回)。 +const RULE_CASES: Array<{ name: string; input: string; category: TaskErrorCategory }> = [ + { name: "content policy", input: "content violated our policies", category: "content_policy" }, + { name: "nsfw", input: "image flagged as nsfw", category: "content_policy" }, + { name: "auth 401", input: "401 Unauthorized", category: "auth_failure" }, + { name: "token expired", input: "token expired", category: "auth_failure" }, + { name: "insufficient balance 402", input: "402 Payment Required", category: "insufficient_balance" }, + { name: "余额不足", input: "余额不足", category: "insufficient_balance" }, + { name: "concurrency pool full", input: "concurrency pool is full", category: "concurrency_busy" }, + { name: "rate limit 429", input: "429 Too Many Requests", category: "concurrency_busy" }, + { name: "unsupported model", input: "model not found", category: "unsupported_model" }, + { name: "invalid asset", input: "invalid image format", category: "invalid_asset" }, + { name: "network ECONNREFUSED", input: "fetch failed: ECONNREFUSED", category: "network_failure" }, + { name: "timeout ETIMEDOUT", input: "ETIMEDOUT", category: "timeout" }, + { name: "quota exceeded", input: "quota exceeded", category: "insufficient_balance" }, + { name: "cancelled", input: "task was cancelled", category: "cancelled" }, + { name: "已取消", input: "任务已取消", category: "cancelled" }, + { name: "all providers failed", input: "all providers failed", category: "concurrency_busy" }, + { name: "500 server error", input: "500 Internal Server Error", category: "network_failure" }, + { name: "forbidden 403", input: "403 Forbidden", category: "auth_failure" }, + { name: "aborted", input: "request aborted", category: "timeout" }, +]; + +describe("classifyTaskError rule coverage", () => { + for (const { name, input, category } of RULE_CASES) { + it(`classifies "${name}" as ${category}`, () => { + const result = classifyTaskError(input); + expect(result.category).toBe(category); + expect(result.message).toBeTruthy(); + expect(result.action).toBeTruthy(); + }); + } +}); + +describe("classifyTaskError edge cases", () => { + it("returns unknown for empty/null/undefined", () => { + expect(classifyTaskError("").category).toBe("unknown"); + expect(classifyTaskError(undefined).category).toBe("unknown"); + expect(classifyTaskError(null).category).toBe("unknown"); + }); + + it("returns the raw (truncated) message for unrecognized Chinese errors", () => { + const result = classifyTaskError("这是一条未知的中文错误信息"); + expect(result.category).toBe("unknown"); + expect(result.message).toContain("未知"); + expect(result.message).not.toContain("服务异常"); + }); + + it("truncates long Chinese errors to 80 chars + ellipsis", () => { + const long = "错误".repeat(50); + const result = classifyTaskError(long); + expect(result.message.endsWith("...")).toBe(true); + expect(result.message.length).toBeLessThanOrEqual(83); + }); + + it("returns generic service message for unrecognized English errors", () => { + const result = classifyTaskError("something completely unexpected"); + expect(result.category).toBe("unknown"); + expect(result.message).toBe("服务异常,请稍后重试"); + }); +}); + +describe("classifyTaskError rule ordering (first match wins)", () => { + it("content_policy beats auth_failure when both patterns present", () => { + // "nsfw" appears before "401" in rule order + const result = classifyTaskError("nsfw content with 401"); + expect(result.category).toBe("content_policy"); + }); +}); + +describe("translateTaskError", () => { + it("returns the message from classifyTaskError", () => { + expect(translateTaskError("401")).toBe("登录已过期,请重新登录"); + }); + it("returns generic message for empty input", () => { + expect(translateTaskError("")).toBe("任务失败,请重试"); + }); +}); diff --git a/src/utils/videoRouting.test.ts b/src/utils/videoRouting.test.ts new file mode 100644 index 0000000..99d16dd --- /dev/null +++ b/src/utils/videoRouting.test.ts @@ -0,0 +1,87 @@ +import { describe, it, expect } from "vitest"; +import { resolveHappyHorseRequestModel, HAPPY_HORSE_UI_MODEL, HAPPY_HORSE_T2V_MODEL, HAPPY_HORSE_I2V_MODEL, HAPPY_HORSE_R2V_MODEL } from "./happyHorseRouting"; +import { resolveViduRequestModel, VIDU_UI_MODEL, VIDU_T2V_MODEL, VIDU_I2V_MODEL } from "./viduRouting"; +import { resolvePixverseRequestModel, PIXVERSE_UI_MODEL, PIXVERSE_T2V_MODEL, PIXVERSE_I2V_MODEL, PIXVERSE_KF2V_MODEL } from "./pixverseRouting"; + +type ResolveFn = (input: { model: string; referenceUrls?: string[]; imageReferenceCount?: number }) => string; + +// 三家路由在参考图数量上的分支差异是回归测试重点。 +// HappyHorse: 0->t2v, 1->i2v, >=2->r2v +// Vidu: 0->t2v, >=1->i2v (无 r2v) +// Pixverse: 0->t2v, 1->i2v, >=2->kf2v +describe.each([ + { name: "HappyHorse", resolve: resolveHappyHorseRequestModel, ui: HAPPY_HORSE_UI_MODEL, t2v: HAPPY_HORSE_T2V_MODEL, i2v: HAPPY_HORSE_I2V_MODEL, third: HAPPY_HORSE_R2V_MODEL }, + { name: "Vidu", resolve: resolveViduRequestModel, ui: VIDU_UI_MODEL, t2v: VIDU_T2V_MODEL, i2v: VIDU_I2V_MODEL, third: null }, + { name: "Pixverse", resolve: resolvePixverseRequestModel, ui: PIXVERSE_UI_MODEL, t2v: PIXVERSE_T2V_MODEL, i2v: PIXVERSE_I2V_MODEL, third: PIXVERSE_KF2V_MODEL }, +] as Array<{ name: string; resolve: ResolveFn; ui: string; t2v: string; i2v: string; third: string | null }>)( + "$name routing by imageReferenceCount", + ({ resolve, ui, t2v, i2v, third }) => { + it("returns the input model unchanged when it is not this provider", () => { + expect(resolve({ model: "some-other-model" })).toBe("some-other-model"); + }); + + it("routes 0 reference images to t2v", () => { + expect(resolve({ model: ui, imageReferenceCount: 0 })).toBe(t2v); + }); + + it("routes 1 reference image to i2v", () => { + expect(resolve({ model: ui, imageReferenceCount: 1 })).toBe(i2v); + }); + + if (third) { + it("routes >=2 reference images to the third model", () => { + expect(resolve({ model: ui, imageReferenceCount: 2 })).toBe(third); + expect(resolve({ model: ui, imageReferenceCount: 5 })).toBe(third); + }); + } else { + it("routes >=1 reference images to i2v (no third model for this provider)", () => { + expect(resolve({ model: ui, imageReferenceCount: 2 })).toBe(i2v); + expect(resolve({ model: ui, imageReferenceCount: 5 })).toBe(i2v); + }); + } + }, +); + +describe("reference count fallback (referenceUrls when imageReferenceCount omitted)", () => { + it("HappyHorse counts non-empty urls", () => { + expect( + resolveHappyHorseRequestModel({ + model: HAPPY_HORSE_UI_MODEL, + referenceUrls: ["", " ", "https://example.com/a.png"], + }), + ).toBe(HAPPY_HORSE_I2V_MODEL); + }); + + it("Vidu falls back to 0 when all urls are empty/whitespace", () => { + expect( + resolveViduRequestModel({ + model: VIDU_UI_MODEL, + referenceUrls: ["", " "], + }), + ).toBe(VIDU_T2V_MODEL); + }); + + it("Pixverse counts two non-empty urls as kf2v", () => { + expect( + resolvePixverseRequestModel({ + model: PIXVERSE_UI_MODEL, + referenceUrls: ["https://a.png", "https://b.png"], + }), + ).toBe(PIXVERSE_KF2V_MODEL); + }); + + it("imageReferenceCount takes precedence over referenceUrls length", () => { + // Even though referenceUrls has 3 entries, explicit count of 0 wins. + expect( + resolveHappyHorseRequestModel({ + model: HAPPY_HORSE_UI_MODEL, + referenceUrls: ["a", "b", "c"], + imageReferenceCount: 0, + }), + ).toBe(HAPPY_HORSE_T2V_MODEL); + }); + + it("handles undefined referenceUrls with undefined count", () => { + expect(resolveViduRequestModel({ model: VIDU_UI_MODEL })).toBe(VIDU_T2V_MODEL); + }); +}); diff --git a/tsconfig.json b/tsconfig.json index a3d0976..01ca229 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -16,5 +16,5 @@ "noEmit": true, "jsx": "react-jsx" }, - "include": ["src", "vite.config.ts"] + "include": ["src", "vite.config.ts", "vitest.config.ts"] } diff --git a/vitest.config.ts b/vitest.config.ts new file mode 100644 index 0000000..6ec49b2 --- /dev/null +++ b/vitest.config.ts @@ -0,0 +1,16 @@ +import { defineConfig } from "vitest/config"; + +// Vitest 配置独立于 vite.config.ts,避免影响 dev/build。 +// 本轮只测纯函数(颜色/比例/平台/路由/错误翻译),用 node 环境即可,无需 jsdom。 +// 后续要做组件测试时,再在 test.environment 切到 jsdom 并装 @testing-library/react。 +export default defineConfig({ + test: { + environment: "node", + include: ["src/**/*.{test,spec}.{ts,tsx}"], + coverage: { + provider: "v8", + include: ["src/**/*.{ts,tsx}"], + exclude: ["src/**/*.test.*", "src/**/*.spec.*", "src/main.tsx", "src/vite-env.d.ts"], + }, + }, +});