diff --git a/.github/workflows/deploy-site.yml b/.github/workflows/deploy-site.yml index fa7f8da..43356f4 100644 --- a/.github/workflows/deploy-site.yml +++ b/.github/workflows/deploy-site.yml @@ -5,6 +5,7 @@ on: branches: [main] paths: - 'site/**' + - 'site-internal/**' - '.github/workflows/deploy-site.yml' workflow_dispatch: @@ -26,8 +27,12 @@ jobs: with: node-version: 20 cache: npm - cache-dependency-path: site/package-lock.json + cache-dependency-path: | + site/package-lock.json + site-internal/package-lock.json - run: cd site && npm install && VITE_BASE=/multi-casual-android/ npm run build + - run: cd site-internal && npm install && VITE_BASE=/multi-casual-android/xiaomi/ npm run build + - run: mkdir -p site/dist/xiaomi && cp -R site-internal/dist/. site/dist/xiaomi/ - uses: actions/upload-pages-artifact@v3 with: path: site/dist diff --git a/site-internal/.gitignore b/site-internal/.gitignore new file mode 100644 index 0000000..5a3597b --- /dev/null +++ b/site-internal/.gitignore @@ -0,0 +1,5 @@ +node_modules/ +dist/ +.edgeone/ +*.tsbuildinfo +public/downloads/*.apk diff --git a/site-internal/README.md b/site-internal/README.md new file mode 100644 index 0000000..f7114c3 --- /dev/null +++ b/site-internal/README.md @@ -0,0 +1,78 @@ +# site-internal — Multica Xiaomi internal landing page + +A separate Vite + React landing page for the **Multica Xiaomi** internal +Android build. The public site at [`../site/`](../site/) targets the +Multi-Casual public release; this directory is a sibling project +published under the same GitHub Pages site at `/xiaomi/`. + +## Visual scope + +This page is a near-clone of the public site (`site/src/`) with three +intentional differences: + +1. The "Relationship to Multica" section is removed. +2. The source link points to the private company GitLab project. + The signed APK download points to a separate artifact-only GitHub + release repository. +3. The iOS App button is left untouched and still points at the + public iOS repo — the same `github.com/park0er/multi-casual-ios-app` + source-of-truth is reused on purpose. + +All screenshots, the promo video, the journey / workspace interactions, +the language toggle, and the layout are reused from `site/src/assets/` +so the visual stays in sync with the public site. + +## Release metadata + +`src/App.tsx` points the primary APK download button at the static +GitHub release asset: + +```text +https://github.com/park0er/multica-xiaomi-apk/releases/download/v0.1.5-xiaomi/Multica-Xiaomi-v0.1.5.apk +``` + +The APK is copied from `app/build/outputs/apk/xiaomi/release/` into +`site-internal/public/downloads/` before deployment. Current metadata: + +| Field | Value | +|---|---| +| `release.sha256` | `13e004472d33e66aa40aa7ebd58f75e22cfde8cce3a153729481f1be4d2d1414` | +| `release.gitlabUrl` | `https://git.n.xiaomi.com/zhaoxisheng/multica-xiaomi-android` | +| `release.releasesUrl` | `https://github.com/park0er/multica-xiaomi-apk/releases/download/v0.1.5-xiaomi/Multica-Xiaomi-v0.1.5.apk` | + +Also confirm the `release.apiUrl` matches the staging or production +Xiaomi Multica endpoint you want this build to talk to +(`http://staging-multica.ad.xiaomi.srv` is the build.gradle default). + +## Build + +```bash +cd site-internal +npm install +npm run build +``` + +Output goes to `site-internal/dist/` and is gitignored. + +## Deploy + +The site is hosted as a subdirectory of the public GitHub Pages site: + +``` +https://park0er.github.io/multi-casual-android/xiaomi/ +``` + +GitHub Actions builds the public site into the Pages root and this +internal Xiaomi site into `dist/xiaomi/` before deploying. + +### Publish flow + +1. Copy `site-internal/` into the public repo. +2. Commit and push the public repo. +3. GitHub Actions deploys both `site/` and `site-internal/`. + +### EdgeOne status + +Tencent EdgeOne hosting was attempted first but proved unreliable for +this internal distribution. The current source of truth for downloads is +GitHub Pages. diff --git a/site-internal/index.html b/site-internal/index.html new file mode 100644 index 0000000..6184260 --- /dev/null +++ b/site-internal/index.html @@ -0,0 +1,14 @@ + + + + + + + + Multica Xiaomi · Internal Build + + +
+ + + diff --git a/site-internal/package-lock.json b/site-internal/package-lock.json new file mode 100644 index 0000000..7c1d4f0 --- /dev/null +++ b/site-internal/package-lock.json @@ -0,0 +1,1001 @@ +{ + "name": "multica-xiaomi-internal-site", + "version": "0.1.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "multica-xiaomi-internal-site", + "version": "0.1.0", + "dependencies": { + "@vitejs/plugin-react": "latest", + "motion": "latest", + "react": "latest", + "react-dom": "latest", + "typescript": "latest", + "vite": "latest" + }, + "devDependencies": { + "@types/react": "^19.2.16", + "@types/react-dom": "^19.2.3" + } + }, + "node_modules/@emnapi/core": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.11.1.tgz", + "integrity": "sha512-RSvbQmHzdKzNsLYa/wHrbc3KN4sYLKAdPZxqiM2HATqv/SBk2/ENSHpvXGaLOMcsAyz0poEGqkmmKYG3OWiJEQ==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "@emnapi/wasi-threads": "1.2.2", + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/runtime": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.11.1.tgz", + "integrity": "sha512-vgj7R3y3Wgx24IQaGPA/R6YFXLHVMOZ0uVEyIQPaWs+rd1AzfEMXlAC22FYwO1XkKR6NPsq7mUandH8oIRdZFw==", + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/wasi-threads": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.2.tgz", + "integrity": "sha512-c95qOXkHdydNKhscBTebqEC1CVAZpyqOfVfBzQ1qgzyl3gfeldUjIggDbIZgDKsHLgnsM+igH7TJ/eAasaVuMA==", + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@napi-rs/wasm-runtime": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.6.tgz", + "integrity": "sha512-ZLv/JdUfkvOy9eCnnBaGfiO+XimbjebAeO+MRQqD/B+FR1tnRN0tpKSJHRbE8sFfS6aqsXZ67TQjfwfsxULVbg==", + "license": "MIT", + "optional": true, + "dependencies": { + "@tybys/wasm-util": "^0.10.3" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + }, + "peerDependencies": { + "@emnapi/core": "^1.7.1", + "@emnapi/runtime": "^1.7.1" + } + }, + "node_modules/@oxc-project/types": { + "version": "0.137.0", + "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.137.0.tgz", + "integrity": "sha512-WT+Gb24i8hmvo85AIv2oEYouEXkRlKAlT9WaCa3TfLgNCN+GhrJOGZuIlMouAh38Qe4QOx26eUOVsq70qXrywA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/Boshen" + } + }, + "node_modules/@rolldown/binding-android-arm64": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.1.3.tgz", + "integrity": "sha512-DT6Z3PhvioeHMvxo+xHc3KtqggrI7CCTXCmC2h/5zUlp5jVitv7XEy+9q5/7v8IolhlioawpMo8Kg0EEBy7J0g==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-darwin-arm64": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.1.3.tgz", + "integrity": "sha512-0NwgwsjM7LrsuVnXMK3koTpagBNOhloc/BNjKqZjv4V5zI5r13qx69uVhRx+o5Z0yy4Hzq+lpy7TAgUG/ocvrw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-darwin-x64": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.1.3.tgz", + "integrity": "sha512-YtiBp4disu6V560loT6PjMdiRaWmVvDNrUunAalbiFx2ggeJwxdAsgZMcoGP17uyAsTwAj5V1niksxlHnVQ1Sw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-freebsd-x64": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.1.3.tgz", + "integrity": "sha512-yD3EkEdXk2LypPxnf/kSZHirarsI8gcPzc62SukhR9VJTyvV+F9Q/GxWNuCojc7sXyuVC4DxRGhdDK4X8VSsbw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-arm-gnueabihf": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.1.3.tgz", + "integrity": "sha512-c+8vieQbsD7HNAHKIA34w0GJ9FedFFuJGD+7E6vz7Q3uqAIugL5p45fhlsj4UaAsHpcmlqugBWMhA0/j7o0sIg==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-arm64-gnu": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.1.3.tgz", + "integrity": "sha512-50jD0uUwLvur7Zz9LHz17kaAdTPjn5wN93hEgjvmYFRZwiR7ZJYovTd5ipyWJDAnXKvZ+wgc+/Ika6dwSF5OcA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-arm64-musl": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.1.3.tgz", + "integrity": "sha512-BO9+oPL8K9poZJBfYPsXNtYjPE5uM3qeehT3aFcW4LITOl+iSqhp0abzjR2nWBUNjIZeKXjAEWBZ64WjNoHd6w==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-ppc64-gnu": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.1.3.tgz", + "integrity": "sha512-f3VpLB1vQ0Eo6ecr/6cekLnvYMFF4YBFoVGkfkvPLq1bAkbAwHYQPZKoAmG6OJyTcxxoC+AvezGx/S1obNC0Mw==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-s390x-gnu": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.1.3.tgz", + "integrity": "sha512-AmurZ26Pqx/RI9N1gzEOCklkKXl927yjfXWUUS0O7Puh8ARM/Ob8qfrD3qnWksScdw6cSrW5PSHE9DyLu7+PtA==", + "cpu": [ + "s390x" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-x64-gnu": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.1.3.tgz", + "integrity": "sha512-JJpqs8bRGITDOdbkNKnlojzBabbOHrqjSvDr0IVsZObE1lBcPjxItUEY9eWIDbxaJ3cGrXPWGfGkIxFijg/URg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-x64-musl": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.1.3.tgz", + "integrity": "sha512-rSJcdjPxzA/by/6/rYs+v+bXU7UjvnbUWz8MJb6kh6+knqB1dCrtHg0uu7C/4haqJvqdkYHQ5IGn+tCH9GLW/g==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-openharmony-arm64": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.1.3.tgz", + "integrity": "sha512-hQ3/PYkDJICgevvyNcVrihVeqq7k1Pp3VZ9lY+dauAYUJKO+auqApvANhvR1An9BhmqYKvW2Mu1F9u4DXSMLxQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-wasm32-wasi": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.1.3.tgz", + "integrity": "sha512-Elcv/BtML9lXrV6JuKITc/grN2kYV9gjsQpW8Jfw4ioK0TOkjBjye0nnyqQNy9STNaI20lXNaQBRrD5gSgR0Yg==", + "cpu": [ + "wasm32" + ], + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "1.11.1", + "@emnapi/runtime": "1.11.1", + "@napi-rs/wasm-runtime": "^1.1.6" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-win32-arm64-msvc": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.1.3.tgz", + "integrity": "sha512-2DrEfhluH9yhiaFApmsjsjwrSYbNcY1oFTzYSP1a535jDbV98zCFanA/96TBUd0iDFcxGmw9QRExwGCXz3U+/g==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-win32-x64-msvc": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.1.3.tgz", + "integrity": "sha512-OL4OMk7UPXOeVGGd3qo5zJyPIljf4AFgk5QAkPPS+OoLuOOozhuaQGC18MxVTnw/06q93gShAJzlwnSCY9YtqA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/pluginutils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.1.tgz", + "integrity": "sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==", + "license": "MIT" + }, + "node_modules/@tybys/wasm-util": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.3.tgz", + "integrity": "sha512-F3fo1MYrRJYL3zER0OUOmkutjr1Vp23m7OsSgp7nq4SP6OqX6C/56XFIPAl5bt3zaBRjmW7SGz3u/6LwFpYcOg==", + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@types/react": { + "version": "19.2.17", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.17.tgz", + "integrity": "sha512-MXfmqaVPEVgkBT/aY0aGCkRWWtByiYQXo3xdQ8r5RzuFrPiRn8Gar2tQdXSUQ2GKV3bkXckek89V8wQBY2Q/Aw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "csstype": "^3.2.2" + } + }, + "node_modules/@types/react-dom": { + "version": "19.2.3", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.3.tgz", + "integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@types/react": "^19.2.0" + } + }, + "node_modules/@vitejs/plugin-react": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-6.0.3.tgz", + "integrity": "sha512-vmFvco5/QuC2f9Oj+wTk0+9XeDFkHxSamwZKYc7MxYwKICfvUvlMhqKI0VuICPltGqh1neqBKDvO4kes1ya8vg==", + "license": "MIT", + "dependencies": { + "@rolldown/pluginutils": "^1.0.1" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "peerDependencies": { + "@rolldown/plugin-babel": "^0.1.7 || ^0.2.0", + "babel-plugin-react-compiler": "^1.0.0", + "vite": "^8.0.0" + }, + "peerDependenciesMeta": { + "@rolldown/plugin-babel": { + "optional": true + }, + "babel-plugin-react-compiler": { + "optional": true + } + } + }, + "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==", + "dev": true, + "license": "MIT" + }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/framer-motion": { + "version": "12.42.0", + "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-12.42.0.tgz", + "integrity": "sha512-wp7EJnfWaaEScVygKv3e20udoRz+LbtxScsuTkakAxfXmt+ReC6WyPW2nINRAGvd+hG9odwcjBLyOTPjH5pBRA==", + "license": "MIT", + "dependencies": { + "motion-dom": "^12.42.0", + "motion-utils": "^12.39.0", + "tslib": "^2.4.0" + }, + "peerDependencies": { + "@emotion/is-prop-valid": "*", + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@emotion/is-prop-valid": { + "optional": true + }, + "react": { + "optional": true + }, + "react-dom": { + "optional": true + } + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/lightningcss": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.32.0.tgz", + "integrity": "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==", + "license": "MPL-2.0", + "dependencies": { + "detect-libc": "^2.0.3" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "lightningcss-android-arm64": "1.32.0", + "lightningcss-darwin-arm64": "1.32.0", + "lightningcss-darwin-x64": "1.32.0", + "lightningcss-freebsd-x64": "1.32.0", + "lightningcss-linux-arm-gnueabihf": "1.32.0", + "lightningcss-linux-arm64-gnu": "1.32.0", + "lightningcss-linux-arm64-musl": "1.32.0", + "lightningcss-linux-x64-gnu": "1.32.0", + "lightningcss-linux-x64-musl": "1.32.0", + "lightningcss-win32-arm64-msvc": "1.32.0", + "lightningcss-win32-x64-msvc": "1.32.0" + } + }, + "node_modules/lightningcss-android-arm64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.32.0.tgz", + "integrity": "sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==", + "cpu": [ + "arm64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-arm64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.32.0.tgz", + "integrity": "sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==", + "cpu": [ + "arm64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-x64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.32.0.tgz", + "integrity": "sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-freebsd-x64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.32.0.tgz", + "integrity": "sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm-gnueabihf": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.32.0.tgz", + "integrity": "sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==", + "cpu": [ + "arm" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-gnu": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.32.0.tgz", + "integrity": "sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==", + "cpu": [ + "arm64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-musl": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.32.0.tgz", + "integrity": "sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==", + "cpu": [ + "arm64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-gnu": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.32.0.tgz", + "integrity": "sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-musl": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.32.0.tgz", + "integrity": "sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-arm64-msvc": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.32.0.tgz", + "integrity": "sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==", + "cpu": [ + "arm64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-x64-msvc": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.32.0.tgz", + "integrity": "sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/motion": { + "version": "12.42.0", + "resolved": "https://registry.npmjs.org/motion/-/motion-12.42.0.tgz", + "integrity": "sha512-Qhwvu9sVl5/URSq5CNzwMCpSKK8Uhnrwb6VO977kZyj/wOCS7mWebJUnBoHx5cZU1Zv8a9BD5CSICWKAlrLJgA==", + "license": "MIT", + "dependencies": { + "framer-motion": "^12.42.0", + "tslib": "^2.4.0" + }, + "peerDependencies": { + "@emotion/is-prop-valid": "*", + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@emotion/is-prop-valid": { + "optional": true + }, + "react": { + "optional": true + }, + "react-dom": { + "optional": true + } + } + }, + "node_modules/motion-dom": { + "version": "12.42.0", + "resolved": "https://registry.npmjs.org/motion-dom/-/motion-dom-12.42.0.tgz", + "integrity": "sha512-M63h4n8R+quJdNhBwuLlgxM+OLYa9+I/T2pzDRboB9fLXRdbou+Gw7Zury+SkpaCyACP1JHSjHgZ1EgTkBr30w==", + "license": "MIT", + "dependencies": { + "motion-utils": "^12.39.0" + } + }, + "node_modules/motion-utils": { + "version": "12.39.0", + "resolved": "https://registry.npmjs.org/motion-utils/-/motion-utils-12.39.0.tgz", + "integrity": "sha512-8nadJAJjTtqRkmRF36FoJTrywK9nnFmnPwnSMyxaOCU7GDjN9RTMJIxx9De8ErM+vpPhMccr/6fo5WciyQLnMQ==", + "license": "MIT" + }, + "node_modules/nanoid": { + "version": "3.3.15", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.15.tgz", + "integrity": "sha512-y7Wygv/7mEOvxTuEQDB8StXdMRBWf1kR/tlhAzBRUFkB2jfcLOAxO/SHmOO2zgz1pVgK29/kyupn059/bCHdjA==", + "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/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "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==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/postcss": { + "version": "8.5.15", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.15.tgz", + "integrity": "sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==", + "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/react": { + "version": "19.2.7", + "resolved": "https://registry.npmjs.org/react/-/react-19.2.7.tgz", + "integrity": "sha512-HNe9WslTbXmFK8o8cmwgAeJFSBvt1bPdHCVKtaaV+WlAN36mpT4hcRpwbf3fY56ar2oIXzsBpOAiIRHAdY0OlQ==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "19.2.7", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.7.tgz", + "integrity": "sha512-t0BRVXvbiE/o20Hfw669rLbMCDWtYZLvmJigy2f0MxsXF+71pxhR3xOkspmsO8h3ZlNzyibAmtCa3l4lYKk6gQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "scheduler": "^0.27.0" + }, + "peerDependencies": { + "react": "^19.2.7" + } + }, + "node_modules/rolldown": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.1.3.tgz", + "integrity": "sha512-1F1eEtUBtFvcGm1HQ9TiUIUHPQG7mSAODrhIzjxoUEFuo8OcbrGLiVLkevNgj84TE4lnHvnumwFjhJO5Eu135g==", + "license": "MIT", + "dependencies": { + "@oxc-project/types": "=0.137.0", + "@rolldown/pluginutils": "^1.0.0" + }, + "bin": { + "rolldown": "bin/cli.mjs" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "optionalDependencies": { + "@rolldown/binding-android-arm64": "1.1.3", + "@rolldown/binding-darwin-arm64": "1.1.3", + "@rolldown/binding-darwin-x64": "1.1.3", + "@rolldown/binding-freebsd-x64": "1.1.3", + "@rolldown/binding-linux-arm-gnueabihf": "1.1.3", + "@rolldown/binding-linux-arm64-gnu": "1.1.3", + "@rolldown/binding-linux-arm64-musl": "1.1.3", + "@rolldown/binding-linux-ppc64-gnu": "1.1.3", + "@rolldown/binding-linux-s390x-gnu": "1.1.3", + "@rolldown/binding-linux-x64-gnu": "1.1.3", + "@rolldown/binding-linux-x64-musl": "1.1.3", + "@rolldown/binding-openharmony-arm64": "1.1.3", + "@rolldown/binding-wasm32-wasi": "1.1.3", + "@rolldown/binding-win32-arm64-msvc": "1.1.3", + "@rolldown/binding-win32-x64-msvc": "1.1.3" + } + }, + "node_modules/scheduler": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz", + "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==", + "license": "MIT" + }, + "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==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/tinyglobby": { + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz", + "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==", + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.4" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/typescript": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-6.0.3.tgz", + "integrity": "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==", + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/vite": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/vite/-/vite-8.1.0.tgz", + "integrity": "sha512-BuJcQK/56NQTWDGn4ABea3q4SSBdNPWwNZKTkkUpcMPnLoquSYH8llRtSUIgoL1KSCpHt5eghLShn50mH36y7Q==", + "license": "MIT", + "peer": true, + "dependencies": { + "lightningcss": "^1.32.0", + "picomatch": "^4.0.4", + "postcss": "^8.5.15", + "rolldown": "~1.1.2", + "tinyglobby": "^0.2.17" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^20.19.0 || >=22.12.0", + "@vitejs/devtools": "^0.3.0", + "esbuild": "^0.27.0 || ^0.28.0", + "jiti": ">=1.21.0", + "less": "^4.0.0", + "sass": "^1.70.0", + "sass-embedded": "^1.70.0", + "stylus": ">=0.54.8", + "sugarss": "^5.0.0", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "@vitejs/devtools": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + } + } +} diff --git a/site-internal/package.json b/site-internal/package.json new file mode 100644 index 0000000..ab4cc68 --- /dev/null +++ b/site-internal/package.json @@ -0,0 +1,22 @@ +{ + "name": "multica-xiaomi-internal-site", + "private": true, + "version": "0.1.0", + "scripts": { + "dev": "vite --host 127.0.0.1", + "build": "tsc -b && vite build", + "preview": "vite preview --host 127.0.0.1" + }, + "dependencies": { + "@vitejs/plugin-react": "latest", + "motion": "latest", + "react": "latest", + "react-dom": "latest", + "typescript": "latest", + "vite": "latest" + }, + "devDependencies": { + "@types/react": "^19.2.16", + "@types/react-dom": "^19.2.3" + } +} diff --git a/site-internal/protofly-redirect.html b/site-internal/protofly-redirect.html new file mode 100644 index 0000000..cca52fc --- /dev/null +++ b/site-internal/protofly-redirect.html @@ -0,0 +1,77 @@ + + + + + + + 跳转到 Multica Xiaomi + + + +
+

正在跳转到 Multica Xiaomi

+

这是小米内网入口,目标页面托管在 GitHub Pages。

+ 立即打开 + https://park0er.github.io/multi-casual-android/xiaomi/ +
+ + diff --git a/site-internal/public/favicon.png b/site-internal/public/favicon.png new file mode 100644 index 0000000..b249e4f Binary files /dev/null and b/site-internal/public/favicon.png differ diff --git a/site-internal/src/App.tsx b/site-internal/src/App.tsx new file mode 100644 index 0000000..00feae7 --- /dev/null +++ b/site-internal/src/App.tsx @@ -0,0 +1,662 @@ +import logoImg from "./assets/logo.png"; +import { useState, useEffect, useRef, useCallback, useMemo } from "react"; +import { motion, AnimatePresence, useMotionValue, useTransform, useReducedMotion } from "motion/react"; +import inboxImg from "./assets/screenshots/01-inbox.jpg"; +import issuesListImg from "./assets/screenshots/02-issues-list.jpg"; +import issuesBoardImg from "./assets/screenshots/03-issues-board.jpg"; +import issueDetailImg from "./assets/screenshots/04-issue-detail.jpg"; +import issueSubImg from "./assets/screenshots/05-issue-detail-subissues.jpg"; +import commentImg from "./assets/screenshots/06-comment-composer.jpg"; +import mentionImg from "./assets/screenshots/07-mention-picker.jpg"; +import projectsImg from "./assets/screenshots/08-projects-list.jpg"; +import projectDetailImg from "./assets/screenshots/09-project-detail.jpg"; +import agentsImg from "./assets/screenshots/10-agents-list.jpg"; +import runtimesImg from "./assets/screenshots/11-runtimes-list.jpg"; +import skillsImg from "./assets/screenshots/12-skills-list.jpg"; +import skillDetailImg from "./assets/screenshots/13-skill-detail.jpg"; +import settingsImg from "./assets/screenshots/14-settings.jpg"; +import promoVideo from "./assets/video/multica-android-promo-draft.mp4"; + +const release = { + packageName: "ai.multica.app.xiaomi", + sha256: "13e004472d33e66aa40aa7ebd58f75e22cfde8cce3a153729481f1be4d2d1414", + gitlabUrl: "https://git.n.xiaomi.com/zhaoxisheng/multica-xiaomi-android", + releasesUrl: "https://github.com/park0er/multica-xiaomi-apk/releases/download/v0.1.5-xiaomi/Multica-Xiaomi-v0.1.5.apk", + iosUrl: "https://github.com/park0er/multi-casual-ios-app", + multicaUrl: "https://multica.ai", + apiUrl: "http://staging-multica.ad.xiaomi.srv", +}; + +type Locale = "en" | "zh"; + +const copy: Record }; + workspace: { kicker: string; title: string; subtitle: string; items: Array<{ title: string; subtitle: string }> }; + video: { kicker: string; title: string; body: string }; + download: { kicker: string; title: string; package: string; api: string; sha: string; latest: string; source: string; note: string }; + trust: { kicker: string; items: string[] }; + footer: { tagline: string; multica: string; gitlab: string; ios: string; download: string }; +}> = { + en: { + nav: { brand: "Multica Xiaomi", download: "Download", trust: "Scope", language: "中文" }, + hero: { + eyebrow: "Internal Xiaomi build · Company-only distribution", + title: "Multica Xiaomi for the Xiaomi workspace.", + subtitle: "An Android app independently built from scratch by Zhao Xisheng in Xiaomi's Commercial Platform Department. Multica has not provided an official Android app to date; this internal build gives Xiaomi users a native path today.", + download: "Download APK", + gitlab: "GitLab", + multica: "Visit Multica", + ios: "iOS App", + }, + journey: { + kicker: "Interactive walkthrough", + title: "Try the flow.", + subtitle: "Click each step or scroll to see the app in action.", + cta: "Start the walkthrough", + steps: [ + { title: "Inbox notifications", subtitle: "Stay on top of activity — new issues, comments, and agent progress show up as they happen." }, + { title: "Browse issues", subtitle: "See all tasks in a clean list view, ready for triage. Filter, search, and tap into any issue." }, + { title: "Switch to board view", subtitle: "Tap the view toggle to switch to a kanban board that shows status flow at a glance." }, + { title: "Open issue detail", subtitle: "Tap an issue card to see the full detail: title, status, labels, assignee, and body text." }, + { title: "Explore context", subtitle: "Context guide points zoom into focus areas — title and status, body content, then subtasks and comments — and return to the full view between each." }, + { title: "Scroll for more", subtitle: "Keep scrolling to see subtasks, subscribers, and the comment thread — all the structured context stays on one page." }, + { title: "Draft a comment", subtitle: "Tap the comment box. The keyboard appears and a comment types out character by character." }, + { title: "Mention anyone", subtitle: "Type @ and a picker appears with people, agents, and squads. Choose who to notify." }, + { title: "Workspace overview", subtitle: "Switch between Projects, Agents, Runtimes, Skills, and Settings with workspace chips." }, + ], + }, + workspace: { + kicker: "Workspace assets", + title: "Projects, agents, and everything in between.", + subtitle: "Switch between workspace views to see the full picture.", + items: [ + { title: "Projects", subtitle: "Browse projects with progress tracking" }, + { title: "Project detail", subtitle: "Task stats, status fields, and resources" }, + { title: "Agents", subtitle: "View agent status and recent activity" }, + { title: "Runtimes", subtitle: "Check runtime availability and versions" }, + { title: "Skills", subtitle: "Browse the workspace agent skill library" }, + { title: "Skill detail", subtitle: "Inspect skill structure and documentation" }, + { title: "Settings", subtitle: "Account, workspace, and preference controls" }, + ], + }, + video: { kicker: "Product demo", title: "See it in 30 seconds.", body: "A fast walkthrough of inbox, issues, context, comments, mentions, and workspace views." }, + download: { kicker: "Internal build", title: "Download the Xiaomi internal APK from GitHub Pages.", package: "Package", api: "Service API", sha: "APK SHA256", latest: "Download APK", source: "View source", note: "Internal distribution only — not for external release." }, + trust: { + kicker: "Internal build scope", + items: [ + "Designed and implemented from scratch by Zhao Xisheng of Xiaomi's Commercial Platform Department, with no upstream Android app to inherit from.", + "Multica has not provided an official Android app to date; this project is an independent Xiaomi internal Android client for Multica workflows.", + "Company-internal distribution only. APK download is served from a separate GitHub release artifact repository after EdgeOne proved unreliable.", + "Connects to the Xiaomi Multica service endpoint, with analytics routed through OneTrack and disabled for Umeng / PostHog.", + "Source is kept in the private company GitLab project; the signed APK is distributed from GitHub Pages.", + ], + }, + footer: { tagline: "Built from scratch by Zhao Xisheng for the Xiaomi workspace. APK served via GitHub Pages.", multica: "Multica website", gitlab: "GitLab", ios: "iOS App", download: "Download APK" }, + }, + zh: { + nav: { brand: "Multica Xiaomi", download: "下载", trust: "分发说明", language: "English" }, + hero: { + eyebrow: "小米内部构建 · 仅限公司内部分发", + title: "面向小米工作区的 Multica Xiaomi 内部版。", + subtitle: "由小米商业平台部赵锡盛完全从头自研的 Android App。Multica 官方到目前为止还没有提供 Android App;这套内部构建先为小米用户补上原生移动端入口。", + download: "下载 APK", + gitlab: "GitLab", + multica: "访问 Multica", + ios: "iOS App", + }, + journey: { + kicker: "交互式演示", + title: "试试这个流程。", + subtitle: "点击每个步骤,或滚动页面查看 app 实际操作。", + cta: "开始演示", + steps: [ + { title: "Inbox 通知", subtitle: "新 issues、评论和 agent 进展会实时出现在收件箱,不错过任何动态。" }, + { title: "浏览 Issues", subtitle: "在列表视图中查看所有任务,快速筛选和进入任意 issue。" }, + { title: "切换看板视图", subtitle: "点击视图切换按钮,看板视图让你一眼看到任务状态流。" }, + { title: "打开 Issue 详情", subtitle: "点击 issue 卡片查看完整详情:标题、状态、标签、负责人和正文。" }, + { title: "探索上下文", subtitle: "Context 引导点依次放大标题与状态、正文内容、子任务与评论,然后缩回全貌。" }, + { title: "滚动查看更多", subtitle: "继续下滑查看子任务、订阅者和评论线程 —— 结构化上下文都在同一页。" }, + { title: "草拟评论", subtitle: "点击评论框,键盘出现,评论逐字输入。" }, + { title: "@ 提及任何人", subtitle: "输入 @ 弹出选择器,可选人、agent 或小队。" }, + { title: "Workspace 总览", subtitle: "通过 workspace chips 切换查看 Projects、Agents、Runtimes、Skills 和 Settings。" }, + ], + }, + workspace: { + kicker: "Workspace 资产", + title: "项目、agents,以及它们之间的一切。", + subtitle: "切换 workspace 视图,掌握全貌。", + items: [ + { title: "Projects", subtitle: "浏览项目和进度追踪" }, + { title: "项目详情", subtitle: "任务统计、状态字段和资源入口" }, + { title: "Agents", subtitle: "查看 agent 状态和最近活动" }, + { title: "Runtimes", subtitle: "检查运行时可用性和版本" }, + { title: "Skills", subtitle: "浏览 workspace agent 技能库" }, + { title: "技能详情", subtitle: "查看技能结构和文档" }, + { title: "Settings", subtitle: "账号、工作区和偏好控制" }, + ], + }, + video: { kicker: "产品演示", title: "30 秒看完核心流程。", body: "快速演示 inbox 通知、issues 看板、上下文探索、评论回复、@ 提及和 workspace 视图切换。" }, + download: { kicker: "内部构建", title: "从 GitHub Pages 下载小米内部 APK。", package: "Package", api: "Service API", sha: "APK SHA256", latest: "下载 APK", source: "查看源码", note: "仅供公司内部分发,不对外发布。" }, + trust: { + kicker: "内部构建说明", + items: [ + "由小米商业平台部赵锡盛完全从头设计和实现,不是基于 Multica 官方 Android 客户端改造。", + "Multica 官方到目前为止还没有提供 Android App;本项目是面向小米内部 Multica 工作流的独立 Android 客户端。", + "仅供公司内部分发;由于腾讯云 EdgeOne 访问不稳定,APK 下载改由单独的 GitHub Release 产物仓库托管提供。", + "连接小米 Multica 服务端点,统计走 OneTrack,Umeng / PostHog 已关闭。", + "源码保存在私有公司 GitLab 项目中;签名 APK 从 GitHub Pages 分发。", + ], + }, + footer: { tagline: "商业平台部赵锡盛从头自研,APK 由 GitHub Pages 分发。", multica: "Multica 官网", gitlab: "GitLab", ios: "iOS App", download: "下载 APK" }, + }, +}; + +const JOURNEY_STEPS = 9; +const TYPING_TEXT = "Looks good. I'll ask the agent to check the failing case and post a follow-up."; +const MENTION_ITEMS = [ + { name: "codex", color: "#1647ff" }, + { name: "Opus", color: "#7c3aed" }, + { name: "RollieOC", color: "#059669" }, +]; + +const WORKSPACE_SCREENSHOTS = [projectsImg, projectDetailImg, agentsImg, runtimesImg, skillsImg, skillDetailImg, settingsImg]; + +const fade = (reduced: boolean, delay = 0) => ({ + initial: reduced ? {} : { opacity: 0, y: 18 }, + whileInView: { opacity: 1, y: 0 }, + viewport: { once: true, margin: "-60px" }, + transition: { duration: 0.65, delay, ease: [0.25, 0.1, 0.25, 1] as const }, +}); + +const reveal = (reduced: boolean) => ({ + initial: reduced ? {} : { opacity: 0, y: 20 }, + whileInView: { opacity: 1, y: 0 }, + viewport: { once: true, margin: "-80px" }, + transition: { duration: 0.7, ease: [0.25, 0.1, 0.25, 1] as const }, +}); + +/* ── PhoneDemo ── */ +function PhoneDemo({ + src, + reduced, + zoomScale = 1, + zoomX = 0, + zoomY = 0, + children, +}: { + src: string; + reduced: boolean; + zoomScale?: number; + zoomX?: number; + zoomY?: number; + children?: React.ReactNode; +}) { + return ( +
+
+
+ + + + {children} +
+
+ ); +} + +/* ── Typewriter effect ── */ +function TypewriterEffect({ active, text, reduced }: { active: boolean; text: string; reduced: boolean }) { + const charCount = useMotionValue(0); + const chars = useMemo(() => text.split(""), [text]); + const charRefs = useRef<(HTMLSpanElement | null)[]>([]); + const intervalRef = useRef | null>(null); + + // Imperatively update char opacity from motion value (no hooks in loops) + useEffect(() => { + const unsubscribe = charCount.on("change", (v) => { + const count = Math.round(v); + charRefs.current.forEach((el, i) => { + if (el) el.style.opacity = i < count ? "1" : "0"; + }); + }); + return unsubscribe; + }, [charCount]); + + useEffect(() => { + if (intervalRef.current) clearInterval(intervalRef.current); + if (!active) { charCount.set(0); charRefs.current.forEach((el) => { if (el) el.style.opacity = "0"; }); return; } + if (reduced) { + charCount.set(chars.length); + charRefs.current.forEach((el, i) => { if (el) el.style.opacity = i < chars.length ? "1" : "0"; }); + return; + } + let i = 0; + const interval = setInterval(() => { + i++; + charCount.set(i); + if (i >= chars.length) clearInterval(interval); + }, 42); + intervalRef.current = interval; + return () => clearInterval(interval); + }, [active, reduced, chars.length]); + + return ( + + {chars.map((char, i) => ( + { charRefs.current[i] = el; }} + style={{ opacity: 0 }} + > + {char === " " ? "\u00A0" : char} + + ))} + + + ); +} + +/* ── PhoneMockup (hero) ── */ +function PhoneMockup({ reduced }: { reduced: boolean }) { + return ( +
+ + + +
+ ); +} + +/* ── Main App ── */ +export default function App() { + const reduced = useReducedMotion() ?? false; + const [lang, setLang] = useState("en"); + const [step, setStep] = useState(0); + const [activeWs, setActiveWs] = useState(0); + const [hasInteracted, setHasInteracted] = useState(false); + const completedRef = useRef>(new Set()); + const journeyRef = useRef(null); + const hasAutoPlayedRef = useRef(false); + const t = copy[lang]; + + // Auto-play journey on first scroll into view + useEffect(() => { + if (hasInteracted || hasAutoPlayedRef.current) return; + const el = journeyRef.current; + if (!el) return; + + const observer = new IntersectionObserver( + ([entry]) => { + if (entry.isIntersecting && entry.intersectionRatio > 0.3 && !hasAutoPlayedRef.current) { + hasAutoPlayedRef.current = true; + let currentStep = 0; + const advance = () => { + currentStep++; + if (currentStep < JOURNEY_STEPS) { + setStep(currentStep); + setTimeout(advance, 2200); + } + }; + setTimeout(advance, 2200); + } + }, + { threshold: 0.3 } + ); + observer.observe(el); + return () => observer.disconnect(); + }, [hasInteracted]); + + const handleStepClick = useCallback((index: number) => { + setHasInteracted(true); + setStep(index); + }, []); + + const handleWorkspaceClick = useCallback((index: number) => { + setActiveWs(index); + }, []); + + // Phone screen source based on journey step + const phoneScreenSrc = useMemo(() => { + if (step <= 1) return step === 0 ? inboxImg : issuesListImg; + if (step === 2) return issuesBoardImg; + if (step <= 5) return step === 3 ? issueDetailImg : issueSubImg; + if (step === 6) return commentImg; + if (step === 7) return mentionImg; + return projectsImg; + }, [step]); + + // Focus zoom transform for step 4 (context explore) + const focusZones = [ + { scale: 1.6, x: 0, y: -120 }, // title/status + { scale: 1.45, x: 0, y: -40 }, // body + { scale: 1.5, x: 0, y: 80 }, // subtasks/comments + ]; + const focusIdx = step === 4 ? 0 : -1; // simple: show first zone; cycle handled by auto-play + const zoom = step === 4 ? focusZones[focusIdx] || focusZones[0] : { scale: 1, x: 0, y: 0 }; + + return ( +
+ {/* Hero */} +
+
+ +
+ Multica Xiaomi + {t.nav.brand} +
+
+ {t.nav.download} + {t.nav.trust} + +
+
+
+
+ {t.hero.eyebrow} + {t.hero.title} + {t.hero.subtitle} + + {t.hero.download} + {t.hero.gitlab} + {t.hero.multica} + {t.hero.ios} + +
+ +
+
+ + {/* (Relationship section removed for the internal build.) */} + + {/* Interactive Product Journey */} +
+ +
{t.journey.kicker}
+

{t.journey.title}

+

{t.journey.subtitle}

+
+ +
+
+ {t.journey.steps.map((s, i) => ( + handleStepClick(i)} + initial={reduced ? {} : { opacity: 0, x: -16 }} + whileInView={{ opacity: 1, x: 0 }} + viewport={{ once: true }} + transition={{ duration: 0.5, delay: i * 0.06 }} + > +
{i < step ? "✓" : i + 1}
+
+

{s.title}

+

{s.subtitle}

+
+
+ ))} +
+ +
+
+ + {/* Hand + tap ripple for interactive steps */} + {step >= 1 && step <= 3 && ( + <> + 👆 + + + )} + + {/* Typing effect for step 6 */} + {step === 6 && } + + {/* Mention picker overlay for step 7 */} + + {step === 7 && ( + +
+ @ cod +
+
+ {MENTION_ITEMS.map((m, i) => ( + +
{m.name[0].toUpperCase()}
+
+
{m.name}
+
{i === 0 ? "agent" : i === 1 ? "agent" : "squad"}
+
+
+ ))} +
+
+ )} +
+ + {/* Workspace chips overlay for step 8 */} + {step === 8 && ( + + {["Projects", "Agents", "Runtimes", "Skills", "Settings"].map((label, i) => ( + + {label} + + ))} + + )} +
+
+
+
+
+ + {/* Workspace Assets Grid */} + +
+
{t.workspace.kicker}
+

{t.workspace.title}

+

{t.workspace.subtitle}

+
+ +
+ {t.workspace.items.map((item, i) => ( + + ))} +
+ +
+ + + + + +
+ + + {t.workspace.items.map((item, i) => ( + handleWorkspaceClick(i)} + initial={reduced ? {} : { opacity: 0, y: 16 }} + whileInView={{ opacity: 1, y: 0 }} + viewport={{ once: true }} + transition={{ duration: 0.5, delay: i * 0.06 }} + > + {item.title} +
+ {item.title} + {item.subtitle} +
+
+ ))} +
+
+ + {/* Video Demo */} + +
{t.video.kicker}
+
+

{t.video.title}

+

{t.video.body}

+
+
+ + {/* Download */} +
+ +
{t.download.kicker}
+

{t.download.title}

+
+
+ {t.download.package} + {release.packageName} +
+
+ {t.download.api} + {release.apiUrl} +
+
+ {t.download.sha} + {release.sha256} +
+
+
{`adb install -r Multica-Xiaomi-v0.1.5.apk`}
+ +

+ {lang === "en" + ? <>APK downloads are served by a separate GitHub release artifact repository; source lives on the company GitLab. + : <>APK 由单独的 GitHub Release 产物仓库分发;源码保存在公司 GitLab。 + } +

+
+
+ + {/* Trust */} +
+
{t.trust.kicker}
+
+ {t.trust.items.map((item) => ( + + +

{item}

+
+ ))} +
+
+ + {/* Footer */} + +
+ ); +} diff --git a/site-internal/src/assets/logo.png b/site-internal/src/assets/logo.png new file mode 100644 index 0000000..8fa30f0 Binary files /dev/null and b/site-internal/src/assets/logo.png differ diff --git a/site-internal/src/assets/screenshots/01-inbox.jpg b/site-internal/src/assets/screenshots/01-inbox.jpg new file mode 100644 index 0000000..a8ace20 Binary files /dev/null and b/site-internal/src/assets/screenshots/01-inbox.jpg differ diff --git a/site-internal/src/assets/screenshots/02-issues-list.jpg b/site-internal/src/assets/screenshots/02-issues-list.jpg new file mode 100644 index 0000000..6bede1e Binary files /dev/null and b/site-internal/src/assets/screenshots/02-issues-list.jpg differ diff --git a/site-internal/src/assets/screenshots/03-issues-board.jpg b/site-internal/src/assets/screenshots/03-issues-board.jpg new file mode 100644 index 0000000..54b6fda Binary files /dev/null and b/site-internal/src/assets/screenshots/03-issues-board.jpg differ diff --git a/site-internal/src/assets/screenshots/04-issue-detail.jpg b/site-internal/src/assets/screenshots/04-issue-detail.jpg new file mode 100644 index 0000000..9ffb4d9 Binary files /dev/null and b/site-internal/src/assets/screenshots/04-issue-detail.jpg differ diff --git a/site-internal/src/assets/screenshots/05-issue-detail-subissues.jpg b/site-internal/src/assets/screenshots/05-issue-detail-subissues.jpg new file mode 100644 index 0000000..09de083 Binary files /dev/null and b/site-internal/src/assets/screenshots/05-issue-detail-subissues.jpg differ diff --git a/site-internal/src/assets/screenshots/06-comment-composer.jpg b/site-internal/src/assets/screenshots/06-comment-composer.jpg new file mode 100644 index 0000000..46551d9 Binary files /dev/null and b/site-internal/src/assets/screenshots/06-comment-composer.jpg differ diff --git a/site-internal/src/assets/screenshots/07-mention-picker.jpg b/site-internal/src/assets/screenshots/07-mention-picker.jpg new file mode 100644 index 0000000..0ab61a5 Binary files /dev/null and b/site-internal/src/assets/screenshots/07-mention-picker.jpg differ diff --git a/site-internal/src/assets/screenshots/08-projects-list.jpg b/site-internal/src/assets/screenshots/08-projects-list.jpg new file mode 100644 index 0000000..03710d6 Binary files /dev/null and b/site-internal/src/assets/screenshots/08-projects-list.jpg differ diff --git a/site-internal/src/assets/screenshots/09-project-detail.jpg b/site-internal/src/assets/screenshots/09-project-detail.jpg new file mode 100644 index 0000000..69398ae Binary files /dev/null and b/site-internal/src/assets/screenshots/09-project-detail.jpg differ diff --git a/site-internal/src/assets/screenshots/10-agents-list.jpg b/site-internal/src/assets/screenshots/10-agents-list.jpg new file mode 100644 index 0000000..5b1a631 Binary files /dev/null and b/site-internal/src/assets/screenshots/10-agents-list.jpg differ diff --git a/site-internal/src/assets/screenshots/11-runtimes-list.jpg b/site-internal/src/assets/screenshots/11-runtimes-list.jpg new file mode 100644 index 0000000..9b6cf4f Binary files /dev/null and b/site-internal/src/assets/screenshots/11-runtimes-list.jpg differ diff --git a/site-internal/src/assets/screenshots/12-skills-list.jpg b/site-internal/src/assets/screenshots/12-skills-list.jpg new file mode 100644 index 0000000..79b73c0 Binary files /dev/null and b/site-internal/src/assets/screenshots/12-skills-list.jpg differ diff --git a/site-internal/src/assets/screenshots/13-skill-detail.jpg b/site-internal/src/assets/screenshots/13-skill-detail.jpg new file mode 100644 index 0000000..a6a827b Binary files /dev/null and b/site-internal/src/assets/screenshots/13-skill-detail.jpg differ diff --git a/site-internal/src/assets/screenshots/14-settings.jpg b/site-internal/src/assets/screenshots/14-settings.jpg new file mode 100644 index 0000000..244035e Binary files /dev/null and b/site-internal/src/assets/screenshots/14-settings.jpg differ diff --git a/site-internal/src/assets/video/multica-android-promo-draft.mp4 b/site-internal/src/assets/video/multica-android-promo-draft.mp4 new file mode 100644 index 0000000..f36d193 Binary files /dev/null and b/site-internal/src/assets/video/multica-android-promo-draft.mp4 differ diff --git a/site-internal/src/main.tsx b/site-internal/src/main.tsx new file mode 100644 index 0000000..3589701 --- /dev/null +++ b/site-internal/src/main.tsx @@ -0,0 +1,10 @@ +import React from "react"; +import ReactDOM from "react-dom/client"; +import App from "./App"; +import "./styles.css"; + +ReactDOM.createRoot(document.getElementById("root")!).render( + + + , +); diff --git a/site-internal/src/styles.css b/site-internal/src/styles.css new file mode 100644 index 0000000..8887020 --- /dev/null +++ b/site-internal/src/styles.css @@ -0,0 +1,971 @@ +:root { + --blue: #1647ff; + --blue-2: #0f33c8; + --yellow: #ffe45c; + --ink: #101218; + --muted: #687080; + --paper: #f6f8fc; + --card: #ffffff; + --line: rgba(16, 18, 24, 0.1); + --shadow: 0 24px 70px rgba(16, 18, 24, 0.14); + font-family: -apple-system, BlinkMacSystemFont, "SF Pro Display", "Noto Sans SC", "PingFang SC", "Microsoft YaHei", sans-serif; + color: var(--ink); + background: var(--paper); +} + +* { box-sizing: border-box; } + +html { scroll-behavior: smooth; } + +body { + margin: 0; + min-width: 320px; + overflow-x: hidden; + background: + radial-gradient(circle at 82% 5%, rgba(255, 228, 92, 0.4), transparent 31%), + radial-gradient(circle at 10% 30%, rgba(22, 71, 255, 0.16), transparent 30%), + linear-gradient(180deg, #fbfcff 0%, #e8eeff 55%, #d4dff9 85%, #c4d4f5 100%); +} + +body, button, input { font: inherit; } + +button { cursor: pointer; } + +a { color: inherit; text-decoration: none; } + +.section-pad { padding: 80px clamp(22px, 5vw, 76px); } + +.hero { + min-height: 100vh; + position: relative; + overflow: hidden; + padding-top: 26px; + padding-left: clamp(16px, 5vw, 76px); + padding-right: clamp(16px, 5vw, 76px); +} + +.hero-bg { + position: absolute; + inset: 0; + background-image: + linear-gradient(rgba(16, 18, 24, 0.045) 1px, transparent 1px), + linear-gradient(90deg, rgba(16, 18, 24, 0.045) 1px, transparent 1px); + background-size: 56px 56px; + mask-image: linear-gradient(to bottom, black 0%, transparent 88%); + pointer-events: none; +} + +.topbar { + width: min(1160px, 100%); + margin: 0 auto 70px; + position: relative; + z-index: 2; + display: flex; + align-items: center; + justify-content: space-between; + gap: 24px; + padding: 12px; + border: 1px solid var(--line); + border-radius: 999px; + background: rgba(255, 255, 255, 0.72); + backdrop-filter: blur(18px); + box-shadow: 0 12px 36px rgba(16, 18, 24, 0.06); +} + +.brand, .nav-links { display: flex; align-items: center; gap: 10px; } + +.brand { font-weight: 850; letter-spacing: -0.02em; } + +.brand-mark { + width: 34px; + height: 34px; + border-radius: 10px; + object-fit: cover; + display: block; +} + +.nav-links a { + color: var(--muted); + font-size: 14px; + font-weight: 700; + padding: 8px 10px; +} + +.nav-links a:hover { color: var(--ink); } + +.language-toggle { + color: var(--blue); + font-size: 14px; + font-weight: 850; + padding: 8px 12px; + border: 1px solid rgba(22, 71, 255, 0.18); + border-radius: 999px; + background: rgba(22, 71, 255, 0.07); +} + +.language-toggle:hover { background: rgba(22, 71, 255, 0.12); } + +.hero-grid { + width: min(1160px, 100%); + margin: 0 auto; + position: relative; + z-index: 1; + display: grid; + grid-template-columns: minmax(0, 1.06fr) minmax(320px, 0.72fr); + gap: clamp(28px, 7vw, 96px); + align-items: center; +} + +.eyebrow, .section-kicker { + margin: 0 0 16px; + color: var(--blue); + font-size: 12px; + font-weight: 900; + letter-spacing: 0.15em; + text-transform: uppercase; +} + +h1, h2, h3, p { margin-top: 0; } + +h1 { + max-width: 780px; + margin-bottom: 24px; + font-size: clamp(54px, 8.2vw, 112px); + line-height: 0.9; + letter-spacing: -0.075em; +} + +h2 { + font-size: clamp(36px, 5vw, 72px); + line-height: 0.94; + letter-spacing: -0.065em; + margin-bottom: 22px; +} + +main[lang="zh-CN"] h1 { + max-width: 700px; + font-size: clamp(42px, 6.8vw, 86px); + line-height: 0.98; + letter-spacing: -0.07em; +} + +main[lang="zh-CN"] h2 { + font-size: clamp(34px, 4.6vw, 62px); + line-height: 1; +} + +h3 { + font-size: 24px; + line-height: 1.08; + letter-spacing: -0.035em; +} + +.hero-subtitle, .relationship p, .demo p, .journey-desc { + max-width: 650px; + color: #343b4a; + font-size: clamp(18px, 2vw, 23px); + line-height: 1.48; +} + +.cta-row { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 32px; } +.cta-row.compact { margin-top: 22px; } + +.button { + font-size: 15px; + display: inline-flex; + min-height: 48px; + align-items: center; + justify-content: center; + border-radius: 999px; + padding: 0 20px; + font-weight: 850; + border: 1px solid transparent; + transition: color 0.18s ease, background 0.18s ease, border-color 0.18s ease; +} + +.button.primary { color: white; background: var(--blue); box-shadow: 0 14px 34px rgba(22, 71, 255, 0.32); } +.button.secondary { background: white; border-color: var(--line); } +.button.ghost { color: var(--muted); background: rgba(255, 255, 255, 0.54); border-color: var(--line); } + +/* Phone mockup */ +.phone-wrap { + width: min(390px, 82vw); + margin: 0 auto; + position: relative; + transform-origin: center; +} + +.hero-phone-stack { + min-height: 720px; + position: relative; + perspective: 1200px; +} + +.hero-phone-stack img { + position: absolute; + width: min(310px, 54vw); + height: 676px; + border-radius: 46px; + border: 12px solid #11141d; + background: white; + object-fit: cover; + object-position: top center; + box-shadow: var(--shadow); +} + +.hero-phone-stack img:nth-child(1) { left: 2%; top: 48px; transform: rotate(-8deg) translateZ(-20px); } +.hero-phone-stack img:nth-child(2) { left: 28%; top: 0; transform: rotate(4deg) translateZ(40px); } +.hero-phone-stack img:nth-child(3) { right: 0; top: 132px; transform: rotate(10deg) translateZ(10px); } + +.phone-shell { + position: relative; + padding: 14px; + border-radius: 54px; + background: #11141d; + box-shadow: var(--shadow), inset 0 0 0 2px rgba(255,255,255,0.1); +} + +.phone-shell-compact { + position: relative; + padding: 12px; + border-radius: 48px; + background: #11141d; + box-shadow: 0 20px 56px rgba(16, 18, 24, 0.22); +} + +.speaker { + position: absolute; + top: 18px; + left: 50%; + width: 72px; + height: 8px; + transform: translateX(-50%); + border-radius: 999px; + background: rgba(255,255,255,0.18); + z-index: 2; +} + +.phone-screen { + position: relative; + overflow: hidden; + border-radius: 40px; + background: white; + aspect-ratio: 9 / 19.7; +} + +.phone-screen-compact { + position: relative; + overflow: hidden; + border-radius: 36px; + background: white; + aspect-ratio: 9 / 19.7; +} + +.phone-screen img, +.phone-screen-compact img { + width: 100%; + height: 100%; + object-fit: cover; + object-position: top center; + display: block; +} + +.phone-screen-shot { + position: absolute; + inset: 0; + width: 100%; + height: 100%; + object-fit: cover; + object-position: top center; +} + + + +.tap-ring { + position: absolute; + right: -8px; + bottom: 158px; + width: 76px; + height: 76px; + border-radius: 999px; + border: 2px solid var(--blue); + background: rgba(255, 228, 92, 0.7); + box-shadow: 0 0 0 16px rgba(255, 228, 92, 0.22); +} + +/* Shared content sections */ +.relationship, .features, .demo, .video-demo, .download, .trust, .footer { + width: min(1160px, calc(100% - 44px)); + margin: 0 auto; + padding-left: 0; + padding-right: 0; +} + +.two-col, .demo-grid { + display: grid; + grid-template-columns: minmax(0, 0.85fr) minmax(320px, 1fr); + gap: clamp(24px, 5vw, 76px); + align-items: center; +} + +/* Relationship section */ +.relationship-card { + border: 1px solid var(--line); + border-radius: 30px; + background: rgba(255,255,255,0.76); + box-shadow: 0 18px 48px rgba(16,18,24,0.08); + padding: clamp(28px, 5vw, 48px); +} + +.relationship-card p { + max-width: 800px; + margin: 0 0 16px; + font-size: clamp(16px, 1.8vw, 20px); + line-height: 1.65; + color: #343b4a; +} + +.relationship-card p:last-child { margin-bottom: 0; } + +.relationship-card a { + color: var(--blue); + text-decoration: underline; + text-decoration-color: rgba(22, 71, 255, 0.25); +} + +.relationship-card a:hover { text-decoration-color: var(--blue); } + +/* Interactive product journey */ +.journey { + width: min(1160px, calc(100% - 44px)); + margin: 0 auto; + padding: 40px 0; +} + +.journey-header { + text-align: center; + margin-bottom: 48px; +} + +.journey-header h2 { + max-width: 800px; + margin: 0 auto 16px; +} + +.journey-header p { + max-width: 600px; + margin: 0 auto; + color: var(--muted); + font-size: 16px; +} + +.journey-layout { + display: grid; + grid-template-columns: minmax(0, 1fr) minmax(280px, 440px); + gap: clamp(24px, 5vw, 64px); + align-items: start; +} + +.journey-steps { + display: flex; + flex-direction: column; + gap: 16px; +} + +.journey-step { + display: flex; + gap: 18px; + padding: 20px 24px; + border-radius: 20px; + border: 1px solid var(--line); + background: rgba(255,255,255,0.68); + cursor: pointer; + transition: background 0.2s ease, border-color 0.2s ease, box-shadow 0.2s ease; +} + +.journey-step:hover { + background: rgba(255,255,255,0.92); + border-color: rgba(22, 71, 255, 0.18); +} + +.journey-step-active { + background: white; + border-color: var(--blue); + box-shadow: 0 12px 36px rgba(22, 71, 255, 0.12); +} + +.journey-step-completed { + opacity: 0.65; + cursor: default; +} + +.journey-step-number { + width: 32px; + height: 32px; + border-radius: 999px; + background: rgba(22, 71, 255, 0.08); + color: var(--blue); + font-size: 14px; + font-weight: 900; + display: grid; + place-items: center; + flex: none; + margin-top: 2px; +} + +.journey-step-active .journey-step-number { + background: var(--blue); + color: white; +} + +.journey-step-completed .journey-step-number { + background: var(--blue); + color: white; +} + +.journey-step-content h3 { + font-size: 18px; + margin-bottom: 6px; + letter-spacing: -0.02em; +} + +.journey-step-content p { + font-size: 18px; + line-height: 1.55; + color: var(--muted); + margin: 0; +} + +.journey-phone-area { + position: sticky; + top: 40px; +} + +.journey-phone-container { + position: relative; + display: flex; + justify-content: center; +} + +/* Journey phone overlays */ +.journey-overlay { + position: absolute; + inset: 0; + z-index: 6; + border-radius: 36px; + overflow: hidden; +} + +.journey-hand { + position: absolute; + z-index: 8; + font-size: 28px; + filter: drop-shadow(0 4px 8px rgba(0,0,0,0.2)); + pointer-events: none; +} + +.journey-tap-ripple { + position: absolute; + z-index: 7; + width: 52px; + height: 52px; + border-radius: 999px; + border: 2px solid var(--blue); + background: rgba(255, 228, 92, 0.55); + box-shadow: 0 0 0 12px rgba(255, 228, 92, 0.18); + pointer-events: none; +} + +/* Focus zoom */ +.focus-zoom { + position: absolute; + z-index: 5; + border-radius: 20px; + border: 3px solid var(--blue); + background: rgba(22, 71, 255, 0.06); + pointer-events: none; +} + +/* Workspace assets grid */ +.workspace-section { + width: min(1160px, calc(100% - 44px)); + margin: 0 auto; +} + +.workspace-header { + text-align: center; + margin-bottom: 48px; +} + +.workspace-header h2 { + max-width: 700px; + margin: 0 auto 16px; +} + +.workspace-header p { + max-width: 560px; + margin: 0 auto; + color: var(--muted); + font-size: 16px; +} + +.workspace-chips { + display: flex; + justify-content: center; + flex-wrap: wrap; + gap: 10px; + margin-bottom: 36px; +} + +.workspace-chip { + padding: 10px 18px; + border-radius: 999px; + font-size: 14px; + font-weight: 850; + border: 1px solid var(--line); + background: rgba(255,255,255,0.72); + color: var(--muted); + transition: background 0.18s, color 0.18s, border-color 0.18s, box-shadow 0.18s; +} + +.workspace-chip:hover { + background: white; + color: var(--ink); +} + +.workspace-chip-active { + background: var(--blue); + color: white; + border-color: var(--blue); + box-shadow: 0 10px 24px rgba(22, 71, 255, 0.28); +} + +.workspace-phone-wrap { + display: flex; + justify-content: center; + margin-bottom: 48px; +} + +.workspace-phone-wrap .phone-shell-compact { + width: min(260px, 60vw); +} + +/* Mention picker overlay */ +.mention-overlay { + position: absolute; + bottom: 0; + left: 0; + right: 0; + z-index: 10; + background: rgba(255,255,255,0.97); + backdrop-filter: blur(12px); + border-top: 1px solid var(--line); + border-radius: 24px 24px 36px 36px; + padding: 16px 14px; + box-shadow: 0 -12px 36px rgba(16, 18, 24, 0.1); +} + +.mention-search { + display: flex; + align-items: center; + gap: 8px; + padding: 10px 14px; + border-radius: 14px; + background: #f4f6fa; + margin-bottom: 14px; + font-size: 14px; + color: var(--muted); +} + +.mention-search span { + color: var(--blue); + font-weight: 800; +} + +.mention-list { + display: flex; + flex-direction: column; + gap: 4px; +} + +.mention-item { + display: flex; + align-items: center; + gap: 12px; + padding: 10px 12px; + border-radius: 14px; + transition: background 0.12s; +} + +.mention-item-active { + background: rgba(22, 71, 255, 0.07); +} + +.mention-avatar { + width: 32px; + height: 32px; + border-radius: 999px; + display: grid; + place-items: center; + font-size: 13px; + font-weight: 900; + color: white; + flex: none; +} + +.mention-name { + font-size: 14px; + font-weight: 800; +} + +.mention-role { + font-size: 12px; + color: var(--muted); +} + +.mention-highlight { + position: absolute; + z-index: 5; + border-radius: 16px; + border: 2px solid var(--blue); + background: rgba(22, 71, 255, 0.06); + pointer-events: none; +} + +/* Typing demo */ +.typing-line { + position: absolute; + z-index: 6; + display: flex; + align-items: center; + gap: 2px; + font-size: 18px; + font-weight: 700; + color: var(--ink); + letter-spacing: -0.01em; + line-height: 1; + white-space: pre; + pointer-events: none; +} + +.typing-cursor { + display: inline-block; + width: 2px; + height: 18px; + background: var(--blue); + border-radius: 999px; + margin-left: 1px; +} + +/* Features grid (legacy, kept for reference) */ +.feature-grid, .trust-grid, .release-grid { + display: grid; + grid-template-columns: repeat(3, minmax(0, 1fr)); + gap: 18px; +} + +.feature-card, .trust-item, .release-card { + border: 1px solid var(--line); + border-radius: 30px; + background: rgba(255,255,255,0.76); + box-shadow: 0 18px 48px rgba(16,18,24,0.08); +} + +.feature-card { padding: 28px; min-height: 250px; } +.feature-card span { color: var(--blue); font-weight: 950; font-size: 13px; letter-spacing: 0.12em; } +.feature-card p, .trust-item p { color: var(--muted); line-height: 1.65; } + +.demo { overflow: hidden; } +.screenshot-stack { min-height: 560px; position: relative; overflow: hidden; border-radius: 42px; } +.shot { + position: absolute; + width: min(310px, 52vw); + height: 620px; + border-radius: 34px; + border: 10px solid #11141d; + box-shadow: var(--shadow); + background: white; + object-fit: cover; + object-position: top center; +} +.shot.back { right: 210px; top: 40px; transform: rotate(-7deg); opacity: 0.78; } +.shot.front { right: 12px; top: 0; transform: rotate(5deg); } + +.video-demo { + padding-top: 20px; +} + +.video-copy { + display: grid; + grid-template-columns: minmax(0, 0.95fr) minmax(320px, 1fr); + gap: clamp(24px, 5vw, 76px); + align-items: end; + margin-bottom: 28px; +} + +.video-copy p { + color: #343b4a; + font-size: clamp(17px, 1.7vw, 21px); + line-height: 1.55; +} + +.promo-video, .video-placeholder { + display: block; + width: 100%; + aspect-ratio: 16 / 9; + border: 1px solid var(--line); + border-radius: 34px; + background: #0e1320; + box-shadow: var(--shadow); +} + +.promo-video { object-fit: cover; z-index: 1; position: relative; } + +.video-placeholder { + display: grid; + place-items: center; + color: white; + background: + radial-gradient(circle at 70% 24%, rgba(255, 228, 92, 0.22), transparent 34%), + linear-gradient(135deg, #0e1320, #172453); +} + +.video-placeholder span { + width: 86px; + height: 86px; + display: grid; + place-items: center; + margin-bottom: 18px; + border-radius: 999px; + color: var(--blue); + background: var(--yellow); + font-size: 44px; + font-weight: 950; + box-shadow: 0 18px 42px rgba(255, 228, 92, 0.24); +} + +.video-placeholder strong { + display: block; + color: white; + font-size: clamp(22px, 3vw, 42px); + letter-spacing: -0.04em; +} + +.download { padding-top: 40px; } +.release-card { padding: clamp(28px, 5vw, 54px); } +.release-grid { margin: 30px 0 22px; } +.release-grid div { + min-width: 0; + padding: 18px; + border-radius: 20px; + background: #f7f9ff; + border: 1px solid rgba(22, 71, 255, 0.13); +} +.release-grid span { display: block; color: var(--muted); font-size: 12px; font-weight: 900; text-transform: uppercase; letter-spacing: 0.12em; margin-bottom: 8px; } +.release-grid code, pre code { font-family: "SFMono-Regular", ui-monospace, Menlo, Consolas, "PingFang SC", monospace; } +.release-grid code { display: block; overflow-wrap: anywhere; color: var(--ink); font-size: 14px; } +.hash-cell { grid-column: span 3; } +pre { + overflow: auto; + margin: 0; + padding: 18px 20px; + border-radius: 20px; + color: #eef4ff; + background: #0e1320; +} + +.trust-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } +.trust-item { display: flex; gap: 14px; padding: 22px; align-items: flex-start; } +.check { + width: 30px; + height: 30px; + display: grid; + place-items: center; + flex: none; + color: white; + border-radius: 999px; + background: var(--blue); + font-weight: 900; +} + +.footer { + display: flex; + justify-content: space-between; + gap: 24px; + align-items: flex-start; + color: var(--muted); + border-top: 1px solid var(--line); +} +.footer strong { color: var(--ink); } +.footer-links { display: flex; gap: 18px; flex-wrap: wrap; font-weight: 800; color: var(--ink); } + +/* Responsive */ +@media (max-width: 900px) { + .topbar { border-radius: 24px; align-items: flex-start; flex-direction: column; } + .nav-links { flex-wrap: wrap; } + .hero-grid, .two-col, .demo-grid, .video-copy, .feature-grid, .trust-grid, .release-grid { grid-template-columns: 1fr; } + .hero { padding-left: 16px; padding-right: 16px; padding-top: 20px; min-height: auto; } + .hero-grid { width: 100%; } + .hero-grid > div:first-child { padding-right: 0; } + .hero-phone-stack { min-height: 400px; overflow: visible; } + .hero-phone-stack img { height: 480px; width: min(240px, 42vw); border-radius: 36px; border-width: 10px; } + .hero-phone-stack img:nth-child(1) { left: -5%; top: 36px; transform: rotate(-8deg) translateZ(-20px); } + .hero-phone-stack img:nth-child(2) { left: 22%; top: 0; transform: rotate(4deg) translateZ(40px); } + .hero-phone-stack img:nth-child(3) { right: -5%; top: 100px; transform: rotate(10deg) translateZ(10px); } + .eyebrow { font-size: 11px; letter-spacing: 0.1em; } + h1 { font-size: clamp(32px, 8vw, 52px) !important; } + .hero-subtitle { font-size: 15px; } + .journey-layout { grid-template-columns: 1fr; } + .journey-phone-area { position: relative; top: 0; order: -1; } + .journey-phone-container { justify-content: center; } + .section-pad { padding: 48px 16px; } + .hash-cell { grid-column: auto; } + .screenshot-stack { min-height: 680px; } + .shot { width: min(300px, 74vw); } + .shot.back { right: auto; left: 4%; } + .shot.front { right: 4%; top: 160px; } + .footer { flex-direction: column; } + .workspace-chips { justify-content: flex-start; } +} + +@media (prefers-reduced-motion: reduce) { + *, *::before, *::after { + animation-duration: 0.01ms !important; + animation-iteration-count: 1 !important; + scroll-behavior: auto !important; + } +} + +/* Workspace card grid */ +.workspace-card-grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); + gap: 14px; + margin-top: 8px; +} + +.workspace-card { + border: 1px solid var(--line); + border-radius: 18px; + background: rgba(255, 255, 255, 0.72); + overflow: hidden; + cursor: pointer; + transition: border-color 0.18s, box-shadow 0.18s, background 0.18s; +} + +.workspace-card:hover { + background: white; + border-color: rgba(22, 71, 255, 0.18); +} + +.workspace-card-active { + border-color: var(--blue); + box-shadow: 0 10px 28px rgba(22, 71, 255, 0.12); + background: white; +} + +.workspace-card-thumb { + width: 100%; + aspect-ratio: 9 / 19.7; + object-fit: cover; + object-position: top center; + display: block; + border-bottom: 1px solid var(--line); +} + +.workspace-card-label { + padding: 10px 12px; +} + +.workspace-card-label strong { + display: block; + font-size: 13px; + font-weight: 850; + letter-spacing: -0.01em; + margin-bottom: 2px; +} + +.workspace-card-label span { + display: block; + font-size: 11px; + color: var(--muted); + line-height: 1.4; +} + +@media (max-width: 900px) { + .workspace-card-grid { + grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); + } +} + +.star-hint { + margin-top: 20px; + font-size: 18px; + color: var(--muted); + text-align: center; + font-weight: 600; +} + +.star-hint a { + text-decoration: underline; + text-underline-offset: 3px; +} + +/* ── Footer pills ── */ +.pill { + display: inline-flex; align-items: center; gap: 7px; + padding: 10px 22px; border-radius: 999px; + font-weight: 850; font-size: 15px; letter-spacing: -0.01em; + text-decoration: none; transition: all 0.22s; +} +.pill-android { + background: var(--blue); color: #fff; + box-shadow: 0 12px 30px rgba(22,71,255,0.30); +} +.pill-android:hover { background: var(--blue-2); transform: translateY(-1px); } +.pill-android .android-icon { + width: 15px; height: 15px; display: inline-block; background: #fff; + -webkit-mask: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCI+PHBhdGggZD0iTTYgMThjMCAuNTUuNDUgMSAxIDFoMXYzLjVjMCAuODMuNjcgMS41IDEuNSAxLjVzMS41LS42NyAxLjUtMS41VjE5aDJ2My41YzAgLjgzLjY3IDEuNSAxLjUgMS41czEuNS0uNjcgMS41LTEuNVYxOWgxYy41NSAwIDEtLjQ1IDEtMVY4SDZ2MTB6TTMuNSA4QzIuNjcgOCAyIDguNjcgMiA5LjV2N2MwIC44My42NyAxLjUgMS41IDEuNVM1IDE3LjMzIDUgMTYuNXYtN0M1IDguNjcgNC4zMyA4IDMuNSA4em0xNyAwYy0uODMgMC0xLjUuNjctMS41IDEuNXY3YzAgLjgzLjY3IDEuNSAxLjUgMS41czEuNS0uNjcgMS41LTEuNXYtN2MwLS44My0uNjctMS41LTEuNS0xLjV6bS00Ljk3LTUuODRsMS4zLTEuM2MuMi0uMi4yLS41MSAwLS43MS0uMi0uMi0uNTEtLjItLjcxIDBsLTEuNDggMS40OEE1Ljg0IDUuODQgMCAwMDEyIDFjLS45NiAwLTEuODYuMjMtMi42Ni42M0w3Ljg1LjE1Yy0uMi0uMi0uNTEtLjItLjcxIDAtLjIuMi0uMi41MSAwIC43MWwxLjMxIDEuMzFBNS45ODMgNS45ODMgMCAwMDYgN2gxMmMwLTIuMTItMS4xLTMuOTgtMi40Ny00Ljg0ek0xMCA1SDlWNGgxdjF6bTUgMGgtMVY0aDF2MXoiLz48L3N2Zz4=) center/contain no-repeat; + mask: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCI+PHBhdGggZD0iTTYgMThjMCAuNTUuNDUgMSAxIDFoMXYzLjVjMCAuODMuNjcgMS41IDEuNSAxLjVzMS41LS42NyAxLjUtMS41VjE5aDJ2My41YzAgLjgzLjY3IDEuNSAxLjUgMS41czEuNS0uNjcgMS41LTEuNVYxOWgxYy41NSAwIDEtLjQ1IDEtMVY4SDZ2MTB6TTMuNSA4QzIuNjcgOCAyIDguNjcgMiA5LjV2N2MwIC44My42NyAxLjUgMS41IDEuNVM1IDE3LjMzIDUgMTYuNXYtN0M1IDguNjcgNC4zMyA4IDMuNSA4em0xNyAwYy0uODMgMC0xLjUuNjctMS41IDEuNXY3YzAgLjgzLjY3IDEuNSAxLjUgMS41czEuNS0uNjcgMS41LTEuNXYtN2MwLS44My0uNjctMS41LTEuNS0xLjV6bS00Ljk3LTUuODRsMS4zLTEuM2MuMi0uMi4yLS41MSAwLS43MS0uMi0uMi0uNTEtLjItLjcxIDBsLTEuNDggMS40OEE1Ljg0IDUuODQgMCAwMDEyIDFjLS45NiAwLTEuODYuMjMtMi42Ni42M0w3Ljg1LjE1Yy0uMi0uMi0uNTEtLjItLjcxIDAtLjIuMi0uMi41MSAwIC43MWwxLjMxIDEuMzFBNS45ODMgNS45ODMgMCAwMDYgN2gxMmMwLTIuMTItMS4xLTMuOTgtMi40Ny00Ljg0ek0xMCA1SDlWNGgxdjF6bTUgMGgtMVY0aDF2MXoiLz48L3N2Zz4=) center/contain no-repeat; +} + +.pill-ios { + position: relative; overflow: hidden; + background: rgba(255,255,255,0.22); + backdrop-filter: blur(20px) saturate(1.8); + -webkit-backdrop-filter: blur(20px) saturate(1.8); + color: #1a1a2e; font-weight: 850; + border: 1px solid rgba(255,255,255,0.55); + box-shadow: 0 4px 20px rgba(0,0,0,0.08), + inset 0 1px 0 rgba(255,255,255,0.9), + inset 0 -1px 0 rgba(0,0,0,0.04); +} +.pill-ios:hover { + background: rgba(255,255,255,0.38); + transform: translateY(-1px); + box-shadow: 0 8px 28px rgba(0,0,0,0.12), + inset 0 1px 0 rgba(255,255,255,1), + inset 0 -1px 0 rgba(0,0,0,0.04); +} +.pill-ios::before { + content: ""; + position: absolute; top: 0; left: -40%; width: 180%; height: 50%; + background: linear-gradient(180deg, rgba(255,255,255,0.7) 0%, rgba(255,255,255,0) 100%); + border-radius: 999px; pointer-events: none; +} +.pill-ios::after { + content: ""; + position: absolute; bottom: -2px; left: 10%; width: 80%; height: 6px; + background: linear-gradient(90deg, #ff6b9d, #c44dff, #6b9dff, #45d4a8); + filter: blur(5px); opacity: 0.4; border-radius: 999px; + pointer-events: none; z-index: -1; +} +.pill-ios .apple-icon { + width: 14px; height: 14px; display: inline-block; background: #1a1a2e; + -webkit-mask: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCI+PHBhdGggZD0iTTE4LjcxIDE5LjVjLS44MyAxLjI0LTEuNzEgMi40NS0zLjA1IDIuNDctMS4zNC4wMy0xLjc3LS43OS0zLjI5LS43OS0xLjUzIDAtMiAuNzctMy4yNy44Mi0xLjMxLjA1LTIuMy0xLjMyLTMuMTQtMi41M0M0LjI1IDE3IDIuOTQgMTIuNDUgNC43IDkuMzljLjg3LTEuNTIgMi40My0yLjQ4IDQuMTItMi41MSAxLjI4LS4wMiAyLjUuODcgMy4yOS44Ny43OCAwIDIuMjYtMS4wNyAzLjgxLS45MS42NS4wMyAyLjQ3LjI2IDMuNjQgMS45OC0uMDkuMDYtMi4xNyAxLjI4LTIuMTUgMy44MS4wMyAzLjAyIDIuNjUgNC4wMyAyLjY4IDQuMDQtLjAzLjA3LS40MiAxLjQ0LTEuMzggMi44M00xMyAzLjVjLjczLS44MyAxLjk0LTEuNDYgMi45NC0xLjUuMTMgMS4xNy0uMzQgMi4zNS0xLjA0IDMuMTktLjY5Ljg1LTEuODMgMS41MS0yLjk1IDEuNDItLjE1LTEuMTUuNDEtMi4zNSAxLjA1LTMuMTF6Ii8+PC9zdmc+) center/contain no-repeat; + mask: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCI+PHBhdGggZD0iTTE4LjcxIDE5LjVjLS44MyAxLjI0LTEuNzEgMi40NS0zLjA1IDIuNDctMS4zNC4wMy0xLjc3LS43OS0zLjI5LS43OS0xLjUzIDAtMiAuNzctMy4yNy44Mi0xLjMxLjA1LTIuMy0xLjMyLTMuMTQtMi41M0M0LjI1IDE3IDIuOTQgMTIuNDUgNC43IDkuMzljLjg3LTEuNTIgMi40My0yLjQ4IDQuMTItMi41MSAxLjI4LS4wMiAyLjUuODcgMy4yOS44Ny43OCAwIDIuMjYtMS4wNyAzLjgxLS45MS42NS4wMyAyLjQ3LjI2IDMuNjQgMS45OC0uMDkuMDYtMi4xNyAxLjI4LTIuMTUgMy44MS4wMyAzLjAyIDIuNjUgNC4wMyAyLjY4IDQuMDQtLjAzLjA3LS40MiAxLjQ0LTEuMzggMi44M00xMyAzLjVjLjczLS44MyAxLjk0LTEuNDYgMi45NC0xLjUuMTMgMS4xNy0uMzQgMi4zNS0xLjA0IDMuMTktLjY5Ljg1LTEuODMgMS41MS0yLjk1IDEuNDItLjE1LTEuMTUuNDEtMi4zNSAxLjA1LTMuMTF6Ii8+PC9zdmc+) center/contain no-repeat; +} + +@media (max-width: 600px) { + .pill { padding: 8px 16px; font-size: 14px; } +} diff --git a/site-internal/src/vite-env.d.ts b/site-internal/src/vite-env.d.ts new file mode 100644 index 0000000..11f02fe --- /dev/null +++ b/site-internal/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/site-internal/tsconfig.json b/site-internal/tsconfig.json new file mode 100644 index 0000000..596336d --- /dev/null +++ b/site-internal/tsconfig.json @@ -0,0 +1,21 @@ +{ + "compilerOptions": { + "target": "ES2022", + "useDefineForClassFields": true, + "lib": ["DOM", "DOM.Iterable", "ES2022"], + "allowJs": false, + "skipLibCheck": true, + "esModuleInterop": true, + "allowSyntheticDefaultImports": true, + "strict": true, + "forceConsistentCasingInFileNames": true, + "module": "ESNext", + "moduleResolution": "Bundler", + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "react-jsx" + }, + "include": ["src"], + "references": [] +} diff --git a/site-internal/vite.config.ts b/site-internal/vite.config.ts new file mode 100644 index 0000000..189c8a4 --- /dev/null +++ b/site-internal/vite.config.ts @@ -0,0 +1,13 @@ +import { defineConfig } from 'vite'; +import react from '@vitejs/plugin-react'; + +export default defineConfig(() => ({ + plugins: [react()], + base: process.env.VITE_BASE || '/', + build: { + outDir: 'dist', + }, + server: { + host: '127.0.0.1', + }, +}));