diff --git a/website/package-lock.json b/website/package-lock.json
index 7a20a1f..aaca5b5 100644
--- a/website/package-lock.json
+++ b/website/package-lock.json
@@ -9,6 +9,7 @@
"version": "0.6.7",
"dependencies": {
"@fontsource/fira-code": "^5.3.0",
+ "@fontsource/geist": "^5.3.0",
"@fontsource/inter": "^5.3.0",
"@phosphor-icons/react": "^2.1.10",
"react": "^18.3.1",
@@ -722,6 +723,15 @@
"url": "https://github.com/sponsors/ayuhito"
}
},
+ "node_modules/@fontsource/geist": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/@fontsource/geist/-/geist-5.3.0.tgz",
+ "integrity": "sha512-u03ftlfVwb05uijq2jGDJ03/HKGqMKaNFk7KOhkpBUex8+BhrAOfMs/XciJ2UUNUX9fEsZbZQld/RWMA2oFU7g==",
+ "license": "OFL-1.1",
+ "funding": {
+ "url": "https://github.com/sponsors/ayuhito"
+ }
+ },
"node_modules/@fontsource/inter": {
"version": "5.3.0",
"resolved": "https://registry.npmjs.org/@fontsource/inter/-/inter-5.3.0.tgz",
diff --git a/website/package.json b/website/package.json
index 308d390..2c13d24 100644
--- a/website/package.json
+++ b/website/package.json
@@ -10,6 +10,7 @@
},
"dependencies": {
"@fontsource/fira-code": "^5.3.0",
+ "@fontsource/geist": "^5.3.0",
"@fontsource/inter": "^5.3.0",
"@phosphor-icons/react": "^2.1.10",
"react": "^18.3.1",
diff --git a/website/src/components/Footer.tsx b/website/src/components/Footer.tsx
index 8a5cea5..55f104c 100644
--- a/website/src/components/Footer.tsx
+++ b/website/src/components/Footer.tsx
@@ -19,7 +19,7 @@ export default function Footer() {
{/* 推荐链接 */}
-
+
{t.footer.recommend}
@@ -32,9 +32,10 @@ export default function Footer() {
href={link.url}
target="_blank"
rel="noreferrer"
- className="group flex items-start gap-3 rounded-xl border border-border bg-card p-4 transition-all hover:-translate-y-0.5 hover:border-primary/50"
+ className="group flex items-start gap-3 rounded-2xl border border-border bg-card p-4 transition-all duration-200 hover:-translate-y-0.5 hover:border-primary/40"
+ style={{ boxShadow: "var(--shadow-soft)" }}
>
-
+
{logo ? (
-
+
{link.name}
{text && (
-
+
{text}
)}
diff --git a/website/src/components/Nav.tsx b/website/src/components/Nav.tsx
index 37b874b..27e2f07 100644
--- a/website/src/components/Nav.tsx
+++ b/website/src/components/Nav.tsx
@@ -11,7 +11,7 @@ export default function Nav() {
{ to: "/download", label: t.nav.download },
];
return (
-
+
{title}
{subtitle && (
- {subtitle}
+ {subtitle}
)}
{children}
diff --git a/website/src/i18n.tsx b/website/src/i18n.tsx
index 906ed21..b05c5cb 100644
--- a/website/src/i18n.tsx
+++ b/website/src/i18n.tsx
@@ -164,6 +164,15 @@ const zh = {
"仪表盘性能再优化:价格解析记忆化缓存,扫描从秒级降到百毫秒级;右上角新增加载耗时/数据量跟踪",
],
},
+ {
+ version: "v0.6.7",
+ date: "2026-08-01",
+ items: [
+ "应用内置 Kimi 授权登录(Device Code Flow,等同 kimi login):浏览器授权即用,无需命令行",
+ "授权后凭据自动写入,15 分钟过期自动续期,用量查询直接可用",
+ "修复外链打开问题:授权页 / 设置页超链接统一走 Rust 侧 opener 命令(更可靠)",
+ ],
+ },
{
version: "v0.6.8",
date: "2026-08-01",
@@ -310,7 +319,7 @@ const zh = {
"智谱 GLM":
"通过我的邀请链接注册 BigModel.cn,即可获得 2000 万 Tokens 大礼包,畅享新一代旗舰模型 GLM-5.2",
DeepSeek: "",
- OpenCodeGo: "",
+ OpenCodeGo: "好友订阅后,您可获得 $5,对方也可获得 $5。",
MiniMax:
"MiniMax Token Plan:订阅套餐解锁最新模型,好友订阅享 9 折 + Builder 权益,邀请人得 10% 返利",
基元律动: "",
@@ -630,7 +639,7 @@ const en: Dict = {
"智谱 GLM":
"Register on BigModel.cn via my invite link and get a 20M token gift pack for the new GLM-5.2 flagship",
DeepSeek: "",
- OpenCodeGo: "",
+ OpenCodeGo: "When a friend subscribes, you get $5 and they get $5.",
MiniMax:
"MiniMax Token Plan: subscribe to unlock the latest models. Friends get 10% off, inviters get 10% rebate",
基元律动: "",
diff --git a/website/src/index.css b/website/src/index.css
index df31cc6..f4e1b5c 100644
--- a/website/src/index.css
+++ b/website/src/index.css
@@ -1,8 +1,8 @@
-@import "@fontsource/inter/400.css";
-@import "@fontsource/inter/500.css";
-@import "@fontsource/inter/600.css";
-@import "@fontsource/inter/700.css";
-@import "@fontsource/inter/800.css";
+@import "@fontsource/geist/400.css";
+@import "@fontsource/geist/500.css";
+@import "@fontsource/geist/600.css";
+@import "@fontsource/geist/700.css";
+@import "@fontsource/geist/800.css";
@import "@fontsource/fira-code/400.css";
@import "@fontsource/fira-code/500.css";
@@ -26,6 +26,11 @@
--primary: 221 83% 53%;
--primary-foreground: 0 0% 100%;
--ring: 221 83% 53%;
+ /* 克制分层阴影(色相一致的 tinted shadow,非荧光发光) */
+ --shadow-soft: 0 1px 2px hsl(240 9% 11% / 0.05),
+ 0 8px 24px hsl(240 9% 11% / 0.06);
+ --shadow-lift: 0 1px 2px hsl(240 9% 11% / 0.05),
+ 0 12px 36px hsl(240 9% 11% / 0.1);
}
@media (prefers-color-scheme: dark) {
@@ -42,6 +47,10 @@
--primary: 217 91% 60%;
--primary-foreground: 0 0% 100%;
--ring: 217 91% 60%;
+ --shadow-soft: 0 1px 2px hsl(222 47% 2% / 0.5),
+ 0 8px 24px hsl(222 47% 2% / 0.45);
+ --shadow-lift: 0 1px 2px hsl(222 47% 2% / 0.5),
+ 0 12px 36px hsl(222 47% 2% / 0.55);
}
}
@@ -59,8 +68,8 @@
z-index: 0;
pointer-events: none;
background-image:
- linear-gradient(to right, hsl(var(--primary) / 0.05) 1px, transparent 1px),
- linear-gradient(to bottom, hsl(var(--primary) / 0.05) 1px, transparent 1px);
+ linear-gradient(to right, hsl(var(--primary) / 0.04) 1px, transparent 1px),
+ linear-gradient(to bottom, hsl(var(--primary) / 0.04) 1px, transparent 1px);
background-size: 44px 44px;
mask-image: radial-gradient(ellipse 80% 60% at 50% 0%, black 30%, transparent 75%);
}
@@ -68,6 +77,21 @@
position: relative;
z-index: 1;
}
+
+ /* 选中色与键盘焦点(无障碍) */
+ ::selection {
+ background: hsl(var(--primary) / 0.16);
+ }
+ :focus-visible {
+ outline: 2px solid hsl(var(--ring));
+ outline-offset: 2px;
+ }
+ /* 展示标题:更紧字距 + 防孤词 */
+ h1,
+ h2 {
+ text-wrap: balance;
+ letter-spacing: -0.02em;
+ }
}
@layer components {
@@ -75,27 +99,41 @@
@apply mx-auto w-full max-w-6xl px-6;
}
.btn {
- @apply inline-flex items-center justify-center gap-2 rounded-xl px-5 py-2.5 text-sm font-medium transition-colors;
+ @apply inline-flex items-center justify-center gap-2 rounded-xl px-5 py-2.5 text-sm font-medium transition-all duration-200;
}
.btn-primary {
- @apply btn bg-primary text-primary-foreground hover:opacity-90;
- box-shadow: 0 0 20px hsl(var(--primary) / 0.35);
+ @apply btn bg-primary text-primary-foreground hover:bg-primary/90 hover:-translate-y-px active:translate-y-0 active:scale-[0.98];
+ box-shadow: 0 1px 2px hsl(var(--primary) / 0.3),
+ 0 6px 16px hsl(var(--primary) / 0.22);
+ }
+ .btn-primary:hover {
+ box-shadow: 0 1px 2px hsl(var(--primary) / 0.3),
+ 0 10px 24px hsl(var(--primary) / 0.3);
}
.btn-ghost {
- @apply btn border border-border text-foreground hover:bg-accent;
+ @apply btn border border-border bg-card/60 text-foreground hover:border-foreground/25 hover:bg-accent active:scale-[0.98];
}
.card {
- @apply rounded-xl border border-border bg-card p-6 transition-shadow;
+ @apply rounded-2xl border border-border bg-card p-6;
+ box-shadow: var(--shadow-soft);
+ transition:
+ box-shadow 0.3s ease,
+ transform 0.3s ease,
+ border-color 0.3s ease;
}
.card:hover {
- box-shadow: 0 0 28px hsl(var(--primary) / 0.12);
+ box-shadow: var(--shadow-lift);
}
/* 截图容器:限定最大宽高,避免撑满页面 */
.screenshot {
- @apply overflow-hidden rounded-xl border border-border bg-muted;
- box-shadow: 0 0 36px hsl(var(--primary) / 0.1);
+ @apply overflow-hidden rounded-2xl border border-border bg-muted;
+ box-shadow: var(--shadow-lift);
}
.screenshot > img {
@apply block h-auto w-full;
}
+ /* 图标容器:统一的蓝色徽标容器 */
+ .icon-chip {
+ @apply flex h-10 w-10 items-center justify-center rounded-xl border border-primary/20 bg-primary/10 text-primary;
+ }
}
diff --git a/website/src/sections/CTA.tsx b/website/src/sections/CTA.tsx
index babe393..4b5a87c 100644
--- a/website/src/sections/CTA.tsx
+++ b/website/src/sections/CTA.tsx
@@ -10,20 +10,24 @@ export default function CTA() {
className="py-24"
>
-
- {/* 科技风光晕 */}
+
+ {/* 克制同色系光晕 + 顶部强调线(去紫,保持页面调性) */}
+
{t.cta.title}
-
+
{t.cta.subtitle}
diff --git a/website/src/sections/Changelog.tsx b/website/src/sections/Changelog.tsx
index 2eddcf4..a084f1a 100644
--- a/website/src/sections/Changelog.tsx
+++ b/website/src/sections/Changelog.tsx
@@ -18,12 +18,38 @@ function cacheKey(embedded: ChangelogEntry[]) {
return `kimi-switch-changelog-${embedded[0]?.version ?? "v1"}`;
}
-/** Parse a GitHub release body into bullet items. */
+/** Compare semantic versions like "v0.7.1" for descending order. */
+function compareVersionsDesc(a: string, b: string): number {
+ const parse = (v: string) =>
+ v.replace(/^v/, "").split(".").map((n) => Number(n) || 0);
+ const pa = parse(a);
+ const pb = parse(b);
+ for (let i = 0; i < 3; i++) {
+ const da = pa[i] ?? 0;
+ const db = pb[i] ?? 0;
+ if (da !== db) return db - da;
+ }
+ return 0;
+}
+
+/** Parse a GitHub release body into bullet items, stripping markdown syntax
+ * and the release-template "Downloads by platform" section (changelog entries
+ * are about changes, not installers). */
function parseBody(body: string): string[] {
- return body
- .split("\n")
- .map((l) => l.replace(/^\s*[-*]\s+/, "").trim())
- .filter((l) => l.length > 0 && l !== "---");
+ const items: string[] = [];
+ for (const raw of body.split("\n")) {
+ const line = raw.replace(/^\s*[-*]\s+/, "").trim();
+ if (line.length === 0 || line === "---") continue;
+ // Drop the release template's download section and everything after it.
+ if (/downloads?\s+by\s+platform/i.test(line)) break;
+ const cleaned = line
+ .replace(/^#{1,6}\s+/, "") // markdown heading markers
+ .replace(/\*\*(.+?)\*\*/g, "$1") // bold
+ .replace(/`([^`]+)`/g, "$1") // inline code
+ .trim();
+ if (cleaned.length > 0) items.push(cleaned);
+ }
+ return items;
}
async function fetchReleases(): Promise
{
@@ -94,12 +120,13 @@ export default function Changelog() {
}, []);
// 远端拉到的版本优先显示(含未翻译的新版本),内置列表补齐缺失版本。
+ // 合并后按版本倒序排序,避免未翻译版本被无脑塞到最前导致时间轴顺序错乱。
const entries: ChangelogEntry[] = [
...(remote ?? []).filter(
(r) => !embedded.some((e) => e.version === r.version),
),
...embedded,
- ];
+ ].sort((a, b) => compareVersionsDesc(a.version, b.version));
return (
-
+
{entries.map((e) => (
-
-
+
-
{e.version}
+ {e.version}
{e.items.length > 0 && (
-
+
{e.items.map((item) => (
- {item}
))}
diff --git a/website/src/sections/Download.tsx b/website/src/sections/Download.tsx
index d214c49..aae8e89 100644
--- a/website/src/sections/Download.tsx
+++ b/website/src/sections/Download.tsx
@@ -45,14 +45,14 @@ export default function Download() {
return (
-
-
{p.name}
+
{p.name}
{p.note}
{links.map((l) => (
diff --git a/website/src/sections/Features.tsx b/website/src/sections/Features.tsx
index ddfaf95..025aeb6 100644
--- a/website/src/sections/Features.tsx
+++ b/website/src/sections/Features.tsx
@@ -59,10 +59,10 @@ export default function Features() {
/>
-
+
-
{f.title}
+
{f.title}
{f.desc}
diff --git a/website/src/sections/Hero.tsx b/website/src/sections/Hero.tsx
index 59d6ce4..d5ce9f4 100644
--- a/website/src/sections/Hero.tsx
+++ b/website/src/sections/Hero.tsx
@@ -23,29 +23,29 @@ export default function Hero() {
aria-labelledby="hero-title"
className="relative overflow-hidden pt-16 pb-20 md:pt-24"
>
- {/* 科技风光晕 */}
+ {/* 克制的同色系光晕(去紫,统一蓝色 + 中性) */}
-
+
{t.hero.badge}
{t.hero.titleBefore}
-
+
{t.hero.titleAccent}
{t.hero.titleAfter}
diff --git a/website/src/sections/Performance.tsx b/website/src/sections/Performance.tsx
index d81596d..aacbac3 100644
--- a/website/src/sections/Performance.tsx
+++ b/website/src/sections/Performance.tsx
@@ -65,7 +65,7 @@ function Counter({
const v = useCountUp(target, inView);
return (
-
+
{v.toFixed(decimals)}
{suffix}
diff --git a/website/src/sections/Privacy.tsx b/website/src/sections/Privacy.tsx
index 5fc5d79..618e068 100644
--- a/website/src/sections/Privacy.tsx
+++ b/website/src/sections/Privacy.tsx
@@ -21,10 +21,10 @@ export default function Privacy() {
const Icon = icons[it.id] ?? Database;
return (
-
+
-
{it.title}
+
{it.title}
{it.desc}
diff --git a/website/tailwind.config.js b/website/tailwind.config.js
index a9dfb0f..b360a61 100644
--- a/website/tailwind.config.js
+++ b/website/tailwind.config.js
@@ -27,7 +27,7 @@ export default {
},
fontFamily: {
sans: [
- "Inter",
+ "Geist",
"-apple-system",
"BlinkMacSystemFont",
'"Segoe UI"',