diff --git a/sites/README.md b/sites/README.md
index 8ba2664..252a325 100644
--- a/sites/README.md
+++ b/sites/README.md
@@ -4,6 +4,15 @@
正式站点地址:
+首页将 GoodBuddy 定位为“桌面助手|AI 编程工具台”,优先展示三大桌面
+系统与双架构下载入口、统一 Agent Runtime,以及知识库、魔法笔记、
+智能心跳、桌面上下文和远程消息通道等桌面助手能力。下载区位于主要
+功能说明之前,并明确列出统信 UOS、银河麒麟、海光、兆芯、鲲鹏和飞腾
+对应的 Linux x64 / arm64 包。页面不重复设置底部下载推广区。
+首屏产品界面默认正面展示,在精确指针设备上使用克制的 3D 倾斜、
+柔和跟随光效和同步浮动标签;触屏设备保持静态布局,系统启用“减少动态
+效果”时不运行该交互。
+
## 部署
`.github/workflows/pages.yml` 会在 `main` 分支中的官网文件发生变化后,
@@ -34,7 +43,7 @@ node --check sites/app.js
## 下载入口
-官网正文不展示具体版本号,所有下载入口直接指向 GitHub 最新正式
+官网正文不展示具体版本号,三个系统下载按钮直接指向 GitHub 最新正式
Release:
```text
diff --git a/sites/app.js b/sites/app.js
index 672b239..9a08416 100644
--- a/sites/app.js
+++ b/sites/app.js
@@ -7,7 +7,11 @@
const navigation = document.querySelector("[data-navigation]");
const themeToggle = document.querySelector("[data-theme-toggle]");
const themeColor = document.querySelector('meta[name="theme-color"]');
+ const tiltStage = document.querySelector("[data-tilt-stage]");
+ const tiltCard = tiltStage?.querySelector("[data-tilt-card]");
const systemTheme = window.matchMedia("(prefers-color-scheme: dark)");
+ const finePointer = window.matchMedia("(hover: hover) and (pointer: fine)");
+ const reducedMotion = window.matchMedia("(prefers-reduced-motion: reduce)");
const getSavedTheme = () => {
try {
@@ -90,6 +94,50 @@
window.addEventListener("scroll", setHeaderState, { passive: true });
+ if (tiltStage instanceof HTMLElement && tiltCard instanceof HTMLElement) {
+ let tiltFrame = 0;
+
+ const resetTilt = () => {
+ window.cancelAnimationFrame(tiltFrame);
+ tiltStage.classList.remove("is-tilting");
+ tiltStage.style.setProperty("--spotlight-x", "50%");
+ tiltStage.style.setProperty("--spotlight-y", "50%");
+ tiltCard.style.setProperty("--spotlight-x", "50%");
+ tiltCard.style.setProperty("--spotlight-y", "50%");
+ tiltStage.style.setProperty("--scene-tilt-x", "0deg");
+ tiltStage.style.setProperty("--scene-tilt-y", "0deg");
+ };
+
+ const updateTilt = (event) => {
+ if (!finePointer.matches || reducedMotion.matches) {
+ resetTilt();
+ return;
+ }
+
+ const bounds = tiltStage.getBoundingClientRect();
+ const x = Math.min(Math.max((event.clientX - bounds.left) / bounds.width, 0), 1);
+ const y = Math.min(Math.max((event.clientY - bounds.top) / bounds.height, 0), 1);
+
+ window.cancelAnimationFrame(tiltFrame);
+ tiltFrame = window.requestAnimationFrame(() => {
+ const spotlightX = `${(x * 100).toFixed(1)}%`;
+ const spotlightY = `${(y * 100).toFixed(1)}%`;
+ tiltStage.classList.add("is-tilting");
+ tiltStage.style.setProperty("--spotlight-x", spotlightX);
+ tiltStage.style.setProperty("--spotlight-y", spotlightY);
+ tiltCard.style.setProperty("--spotlight-x", spotlightX);
+ tiltCard.style.setProperty("--spotlight-y", spotlightY);
+ tiltStage.style.setProperty("--scene-tilt-x", `${((0.5 - y) * 8).toFixed(2)}deg`);
+ tiltStage.style.setProperty("--scene-tilt-y", `${((x - 0.5) * 11).toFixed(2)}deg`);
+ });
+ };
+
+ tiltStage.addEventListener("pointermove", updateTilt, { passive: true });
+ tiltStage.addEventListener("pointerleave", resetTilt);
+ finePointer.addEventListener("change", resetTilt);
+ reducedMotion.addEventListener("change", resetTilt);
+ }
+
const sections = [...document.querySelectorAll("main section[id]")];
const navLinks = [...document.querySelectorAll('.site-navigation a[href^="#"]')];
diff --git a/sites/index.html b/sites/index.html
index 413cd15..a742c41 100644
--- a/sites/index.html
+++ b/sites/index.html
@@ -5,11 +5,11 @@
-
GoodBuddy|桌面 AI 助手
+ GoodBuddy|桌面助手与 AI 编程工具台