diff --git a/.opencode/package-lock.json b/.opencode/package-lock.json
new file mode 100644
index 0000000..0b151a7
--- /dev/null
+++ b/.opencode/package-lock.json
@@ -0,0 +1,387 @@
+{
+ "name": ".opencode",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "dependencies": {
+ "@kilocode/plugin": "7.2.31",
+ "@opencode-ai/plugin": "1.0.11"
+ }
+ },
+ "node_modules/@kilocode/plugin": {
+ "version": "7.2.31",
+ "resolved": "https://registry.npmjs.org/@kilocode/plugin/-/plugin-7.2.31.tgz",
+ "integrity": "sha512-KmKTTIly7hRlJdXKhqZ/j/brvTPh0z0UTjWSjJWq5fqf4pATgYGn7G0g3ZjILnN7MUkkZXuljgqExTEeQJHGkQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@kilocode/sdk": "7.2.31",
+ "effect": "4.0.0-beta.48",
+ "zod": "4.1.8"
+ },
+ "peerDependencies": {
+ "@opentui/core": ">=0.1.100",
+ "@opentui/solid": ">=0.1.100"
+ },
+ "peerDependenciesMeta": {
+ "@opentui/core": {
+ "optional": true
+ },
+ "@opentui/solid": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@kilocode/sdk": {
+ "version": "7.2.31",
+ "resolved": "https://registry.npmjs.org/@kilocode/sdk/-/sdk-7.2.31.tgz",
+ "integrity": "sha512-Sx05yv+3TIlc6M4Ze+YGgKCLoIg8B0WRE15JXDriVncT+wz7M6+e+4mjNWkwfsuywdeOTYPfeFViqX8iO7ckKA==",
+ "license": "MIT",
+ "dependencies": {
+ "cross-spawn": "7.0.6"
+ }
+ },
+ "node_modules/@msgpackr-extract/msgpackr-extract-darwin-arm64": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-arm64/-/msgpackr-extract-darwin-arm64-3.0.3.tgz",
+ "integrity": "sha512-QZHtlVgbAdy2zAqNA9Gu1UpIuI8Xvsd1v8ic6B2pZmeFnFcMWiPLfWXh7TVw4eGEZ/C9TH281KwhVoeQUKbyjw==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ]
+ },
+ "node_modules/@msgpackr-extract/msgpackr-extract-darwin-x64": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-x64/-/msgpackr-extract-darwin-x64-3.0.3.tgz",
+ "integrity": "sha512-mdzd3AVzYKuUmiWOQ8GNhl64/IoFGol569zNRdkLReh6LRLHOXxU4U8eq0JwaD8iFHdVGqSy4IjFL4reoWCDFw==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ]
+ },
+ "node_modules/@msgpackr-extract/msgpackr-extract-linux-arm": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm/-/msgpackr-extract-linux-arm-3.0.3.tgz",
+ "integrity": "sha512-fg0uy/dG/nZEXfYilKoRe7yALaNmHoYeIoJuJ7KJ+YyU2bvY8vPv27f7UKhGRpY6euFYqEVhxCFZgAUNQBM3nw==",
+ "cpu": [
+ "arm"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@msgpackr-extract/msgpackr-extract-linux-arm64": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm64/-/msgpackr-extract-linux-arm64-3.0.3.tgz",
+ "integrity": "sha512-YxQL+ax0XqBJDZiKimS2XQaf+2wDGVa1enVRGzEvLLVFeqa5kx2bWbtcSXgsxjQB7nRqqIGFIcLteF/sHeVtQg==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@msgpackr-extract/msgpackr-extract-linux-x64": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-x64/-/msgpackr-extract-linux-x64-3.0.3.tgz",
+ "integrity": "sha512-cvwNfbP07pKUfq1uH+S6KJ7dT9K8WOE4ZiAcsrSes+UY55E/0jLYc+vq+DO7jlmqRb5zAggExKm0H7O/CBaesg==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@msgpackr-extract/msgpackr-extract-win32-x64": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-win32-x64/-/msgpackr-extract-win32-x64-3.0.3.tgz",
+ "integrity": "sha512-x0fWaQtYp4E6sktbsdAqnehxDgEc/VwM7uLsRCYWaiGu0ykYdZPiS8zCWdnjHwyiumousxfBm4SO31eXqwEZhQ==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@opencode-ai/plugin": {
+ "version": "1.0.11",
+ "dependencies": {
+ "@opencode-ai/sdk": "1.0.11",
+ "zod": "4.1.8"
+ }
+ },
+ "node_modules/@opencode-ai/sdk": {
+ "version": "1.0.11"
+ },
+ "node_modules/@standard-schema/spec": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz",
+ "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==",
+ "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==",
+ "license": "MIT",
+ "dependencies": {
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "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",
+ "optional": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/effect": {
+ "version": "4.0.0-beta.48",
+ "resolved": "https://registry.npmjs.org/effect/-/effect-4.0.0-beta.48.tgz",
+ "integrity": "sha512-MMAM/ZabuNdNmgXiin+BAanQXK7qM8mlt7nfXDoJ/Gn9V8i89JlCq+2N0AiWmqFLXjGLA0u3FjiOjSOYQk5uMw==",
+ "license": "MIT",
+ "dependencies": {
+ "@standard-schema/spec": "^1.1.0",
+ "fast-check": "^4.6.0",
+ "find-my-way-ts": "^0.1.6",
+ "ini": "^6.0.0",
+ "kubernetes-types": "^1.30.0",
+ "msgpackr": "^1.11.9",
+ "multipasta": "^0.2.7",
+ "toml": "^4.1.1",
+ "uuid": "^13.0.0",
+ "yaml": "^2.8.3"
+ }
+ },
+ "node_modules/fast-check": {
+ "version": "4.7.0",
+ "resolved": "https://registry.npmjs.org/fast-check/-/fast-check-4.7.0.tgz",
+ "integrity": "sha512-NsZRtqvSSoCP0HbNjUD+r1JH8zqZalyp6gLY9e7OYs7NK9b6AHOs2baBFeBG7bVNsuoukh89x2Yg3rPsul8ziQ==",
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://github.com/sponsors/dubzzz"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/fast-check"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "pure-rand": "^8.0.0"
+ },
+ "engines": {
+ "node": ">=12.17.0"
+ }
+ },
+ "node_modules/find-my-way-ts": {
+ "version": "0.1.6",
+ "resolved": "https://registry.npmjs.org/find-my-way-ts/-/find-my-way-ts-0.1.6.tgz",
+ "integrity": "sha512-a85L9ZoXtNAey3Y6Z+eBWW658kO/MwR7zIafkIUPUMf3isZG0NCs2pjW2wtjxAKuJPxMAsHUIP4ZPGv0o5gyTA==",
+ "license": "MIT"
+ },
+ "node_modules/ini": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/ini/-/ini-6.0.0.tgz",
+ "integrity": "sha512-IBTdIkzZNOpqm7q3dRqJvMaldXjDHWkEDfrwGEQTs5eaQMWV+djAhR+wahyNNMAa+qpbDUhBMVt4ZKNwpPm7xQ==",
+ "license": "ISC",
+ "engines": {
+ "node": "^20.17.0 || >=22.9.0"
+ }
+ },
+ "node_modules/isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
+ "license": "ISC"
+ },
+ "node_modules/kubernetes-types": {
+ "version": "1.30.0",
+ "resolved": "https://registry.npmjs.org/kubernetes-types/-/kubernetes-types-1.30.0.tgz",
+ "integrity": "sha512-Dew1okvhM/SQcIa2rcgujNndZwU8VnSapDgdxlYoB84ZlpAD43U6KLAFqYo17ykSFGHNPrg0qry0bP+GJd9v7Q==",
+ "license": "Apache-2.0"
+ },
+ "node_modules/msgpackr": {
+ "version": "1.11.10",
+ "resolved": "https://registry.npmjs.org/msgpackr/-/msgpackr-1.11.10.tgz",
+ "integrity": "sha512-iCZNq+HszvF+fC3anCm4nBmWEnbeIAfpDs6IStAEKhQ2YSgkjzVG2FF9XJqwwQh5bH3N9OUTUt4QwVN6MLMLtA==",
+ "license": "MIT",
+ "optionalDependencies": {
+ "msgpackr-extract": "^3.0.2"
+ }
+ },
+ "node_modules/msgpackr-extract": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/msgpackr-extract/-/msgpackr-extract-3.0.3.tgz",
+ "integrity": "sha512-P0efT1C9jIdVRefqjzOQ9Xml57zpOXnIuS+csaB4MdZbTdmGDLo8XhzBG1N7aO11gKDDkJvBLULeFTo46wwreA==",
+ "hasInstallScript": true,
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "node-gyp-build-optional-packages": "5.2.2"
+ },
+ "bin": {
+ "download-msgpackr-prebuilds": "bin/download-prebuilds.js"
+ },
+ "optionalDependencies": {
+ "@msgpackr-extract/msgpackr-extract-darwin-arm64": "3.0.3",
+ "@msgpackr-extract/msgpackr-extract-darwin-x64": "3.0.3",
+ "@msgpackr-extract/msgpackr-extract-linux-arm": "3.0.3",
+ "@msgpackr-extract/msgpackr-extract-linux-arm64": "3.0.3",
+ "@msgpackr-extract/msgpackr-extract-linux-x64": "3.0.3",
+ "@msgpackr-extract/msgpackr-extract-win32-x64": "3.0.3"
+ }
+ },
+ "node_modules/multipasta": {
+ "version": "0.2.7",
+ "resolved": "https://registry.npmjs.org/multipasta/-/multipasta-0.2.7.tgz",
+ "integrity": "sha512-KPA58d68KgGil15oDqXjkUBEBYc00XvbPj5/X+dyzeo/lWm9Nc25pQRlf1D+gv4OpK7NM0J1odrbu9JNNGvynA==",
+ "license": "MIT"
+ },
+ "node_modules/node-gyp-build-optional-packages": {
+ "version": "5.2.2",
+ "resolved": "https://registry.npmjs.org/node-gyp-build-optional-packages/-/node-gyp-build-optional-packages-5.2.2.tgz",
+ "integrity": "sha512-s+w+rBWnpTMwSFbaE0UXsRlg7hU4FjekKU4eyAih5T8nJuNZT1nNsskXpxmeqSK9UzkBl6UgRlnKc8hz8IEqOw==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "detect-libc": "^2.0.1"
+ },
+ "bin": {
+ "node-gyp-build-optional-packages": "bin.js",
+ "node-gyp-build-optional-packages-optional": "optional.js",
+ "node-gyp-build-optional-packages-test": "build-test.js"
+ }
+ },
+ "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==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/pure-rand": {
+ "version": "8.4.0",
+ "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-8.4.0.tgz",
+ "integrity": "sha512-IoM8YF/jY0hiugFo/wOWqfmarlE6J0wc6fDK1PhftMk7MGhVZl88sZimmqBBFomLOCSmcCCpsfj7wXASCpvK9A==",
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://github.com/sponsors/dubzzz"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/fast-check"
+ }
+ ],
+ "license": "MIT"
+ },
+ "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==",
+ "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==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/toml": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/toml/-/toml-4.1.1.tgz",
+ "integrity": "sha512-EBJnVBr3dTXdA89WVFoAIPUqkBjxPMwRqsfuo1r240tKFHXv3zgca4+NJib/h6TyvGF7vOawz0jGuryJCdNHrw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=20"
+ }
+ },
+ "node_modules/uuid": {
+ "version": "13.0.1",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-13.0.1.tgz",
+ "integrity": "sha512-9ezox2roIft6ExBVTVqibSd5dc5/47Sw/uY6b4SjQUT2TzQ0tltNquWA46y4xPQmdZYqvnio22SgWd41M86+jw==",
+ "funding": [
+ "https://github.com/sponsors/broofa",
+ "https://github.com/sponsors/ctavan"
+ ],
+ "license": "MIT",
+ "bin": {
+ "uuid": "dist-node/bin/uuid"
+ }
+ },
+ "node_modules/which": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+ "license": "ISC",
+ "dependencies": {
+ "isexe": "^2.0.0"
+ },
+ "bin": {
+ "node-which": "bin/node-which"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/yaml": {
+ "version": "2.8.3",
+ "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.3.tgz",
+ "integrity": "sha512-AvbaCLOO2Otw/lW5bmh9d/WEdcDFdQp2Z2ZUH3pX9U2ihyUY0nvLv7J6TrWowklRGPYbB/IuIMfYgxaCPg5Bpg==",
+ "license": "ISC",
+ "bin": {
+ "yaml": "bin.mjs"
+ },
+ "engines": {
+ "node": ">= 14.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/eemeli"
+ }
+ },
+ "node_modules/zod": {
+ "version": "4.1.8",
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/colinhacks"
+ }
+ }
+ }
+}
diff --git a/AGENTS.md b/AGENTS.md
new file mode 100644
index 0000000..ed92a6b
--- /dev/null
+++ b/AGENTS.md
@@ -0,0 +1,35 @@
+# AGENTS.md
+
+## Project
+React + TypeScript + Vite landing page for a healthy-oil product. Uses Chakra UI v3 and TanStack Router. No test suite.
+
+## Commands
+- `npm run dev` — Dev server on port 3000
+- `npm run build` — `tsc -b && vite build`
+- `npm run lint` — ESLint only, no typecheck script
+- `npm run preview` — Preview production build on port 3000
+
+## Architecture
+- **Entry:** `src/main.tsx` → `src/router.tsx` → `src/pages/*`
+- **Old UI (root `/`):** `src/App.tsx` with components in `src/components/*`
+- **New UI (`/40plus`):** `src/pages/main.tsx` with components in `src/components/new_ui/*`
+- **Layout wrapper:** `src/components/layout.tsx` switches footer based on route
+- **Router:** Hash-based routing for FTP server compatibility
+- **Path alias:** `@/*` maps to `./src/*`
+
+## Style Conventions
+- Component filenames: lowercase (`hero1.tsx`, `oil_info.tsx`)
+- Use **function declarations** for components, not arrow functions
+- Chakra UI props for responsive design (`base`, `sm`, `md`, `lg`, `xl`)
+- Framer Motion for animations
+- `colors.tsx` exports color tokens; `colors.css` and `fonts.css` for global styles
+
+## TypeScript
+- Strict mode with `noUnusedLocals` and `noUnusedParameters` — unused vars will error
+- `tsconfig.json` uses project references (`tsconfig.app.json` + `tsconfig.node.json`)
+
+## Important Constraints
+- **No tests** — there is no `test`, `vitest`, or `jest` config. Do not try to run tests.
+- **No typecheck script** — run `npx tsc --noEmit` if you need a standalone typecheck.
+- **Build order matters:** `build` runs `tsc -b` first, then `vite build`.
+- **Images** live in `public/images/`; reference them with absolute paths like `/images/new/...`
diff --git a/src/components/new_ui/CyclingImage.tsx b/src/components/new_ui/CyclingImage.tsx
index 25b02ae..492047f 100644
--- a/src/components/new_ui/CyclingImage.tsx
+++ b/src/components/new_ui/CyclingImage.tsx
@@ -19,6 +19,8 @@ interface CyclingImageProps {
showControls?: boolean // Show play/pause and speed controls
autoStart?: boolean // Auto-start animation
style?: CSSProperties // Additional CSS styles
+ alt?: string
+ title?: string
}
const CyclingImage = ({
@@ -38,7 +40,9 @@ const CyclingImage = ({
timingFunction = 'ease-in-out',
showControls = false,
autoStart = true,
- style = {}
+ style = {},
+ alt,
+ title
}: CyclingImageProps) => {
const [isPlaying, setIsPlaying] = useState(autoStart)
const [speed, setSpeed] = useState(cycleDuration)
@@ -93,6 +97,8 @@ const CyclingImage = ({
@@ -243,6 +255,8 @@ function Advantages() {
diff --git a/src/components/new_ui/hero2.tsx b/src/components/new_ui/hero2.tsx
index 73c2049..0585c30 100644
--- a/src/components/new_ui/hero2.tsx
+++ b/src/components/new_ui/hero2.tsx
@@ -29,6 +29,8 @@ function Hero2() {
src="/images/new/hero2title.webp"
position={'absolute'}
left="50%"
+ title="獅球嘜營萃護心油"
+ alt="獅球嘜營萃護心油"
top={{ base: "10px", sm: "20px", md: "30px", lg: "30px", xl: "40px" }}
w={{ base: "70vw", sm: "70vw", md: "35vw", lg: "35vw", xl: "28vw" }}
initial={{ opacity: 0, y: -30, x: '-50%' }}
@@ -51,6 +53,8 @@ function Hero2() {