Files
OSGKeyboard/docs/assets/site.css
T
Rocky d5cf818134 docs(pages): restyle homepage in the logo's acrylic material
- One acrylic material in three thicknesses (canvas, panel, keycap) with grain and sheen
- Unify buttons and chips as rounded rectangles on a 10/14/24/32 radius scale
- Restrain green to logo, status, progress and the default badge
- Regroup sections: four-act story with a new hold-to-ask-AI clip, smoked privacy panel
  absorbing account info, platform reliability chips, centered FAQ, acrylic download panel
2026-10-01 14:03:18 +08:00

2613 lines
59 KiB
CSS
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*!
* OSGKeyboard 主页设计系统(2026-10 亚克力版)
* 方向:整页是一套「亚克力键帽」—— 与应用图标同一种材质:乳白、半透、顶边高光、底边厚度、柔和弥散投影。
* · 材质只有一种,分三档厚度:底板(页面)→ 面板(.acrylic 卡片)→ 键帽(.keycap 按钮 / .chip 标签)。
* · 形状只有四档圆角:标签 10 / 按钮 14 / 卡片 24 / 大面板 32;嵌套时内圆角 = 外圆角 − 内边距。
* · 品牌绿取自图标(#0B9019),只用于状态与指示,其余全部中性色。
* 动效母题:「声音变成文字」—— 声波、逐字浮现、流式转写;另加一道跟随指针的亚克力反光。
* 主题跟随系统(site.js 可手动覆盖),首屏与整页一起切换深浅。
*
* 渐进增强约定:所有「先隐藏、再显现」的初始态都挂在 html.js 之下;
* 无 JavaScript 或开启「减弱动态效果」时,页面以完整静态形态呈现。
*/
/* --------------------------------------------------------------------------
* 1. 设计令牌
* -------------------------------------------------------------------------- */
:root {
color-scheme: light dark;
/* 底板:图标乳白(#F0F2F1)略提亮 */
--canvas: #eff1f0;
--ink: #15181a;
--ink-2: #596067;
--ink-3: #8b9298;
--line: rgba(21, 24, 26, 0.08);
--line-strong: rgba(21, 24, 26, 0.14);
/* 品牌绿:图标三个圆点的颜色;--accent-ink 用于小字,保证对比度 */
--accent: #0f9124;
--accent-ink: #0c7a1f;
--accent-soft: rgba(15, 145, 36, 0.1);
/* 底板背后的环境光:亚克力需要背后有东西才能透出质感 */
--glow-1: rgba(255, 255, 255, 0.95);
--glow-2: rgba(178, 222, 192, 0.5);
--glow-3: rgba(196, 214, 232, 0.55);
/* 面板:半透乳白 + 背景模糊;阴影四层 = 顶边高光 / 底边厚度 / 发丝描边 / 弥散投影 */
--acrylic-fill: linear-gradient(180deg, rgba(255, 255, 255, 0.84), rgba(255, 255, 255, 0.6));
--acrylic-edge: rgba(21, 24, 26, 0.07);
--acrylic-shadow:
inset 0 1px 0 rgba(255, 255, 255, 1),
inset 0 -1px 0 rgba(21, 24, 26, 0.04),
0 0 0 1px var(--acrylic-edge),
0 1px 2px rgba(21, 24, 26, 0.04),
0 24px 48px -24px rgba(21, 24, 26, 0.18);
--acrylic-blur: blur(28px) saturate(1.6);
/* 键帽:比面板更实;按下时内阴影加深、整体下沉 1px */
--key-fill: linear-gradient(180deg, #ffffff, #eef0ef);
--key-shadow:
inset 0 1px 0 #fff,
inset 0 -2px 0 rgba(21, 24, 26, 0.06),
0 0 0 1px rgba(21, 24, 26, 0.09),
0 2px 3px rgba(21, 24, 26, 0.05),
0 8px 18px -8px rgba(21, 24, 26, 0.22);
--key-shadow-hover:
inset 0 1px 0 #fff,
inset 0 -2px 0 rgba(21, 24, 26, 0.06),
0 0 0 1px rgba(21, 24, 26, 0.11),
0 3px 5px rgba(21, 24, 26, 0.06),
0 14px 26px -10px rgba(21, 24, 26, 0.26);
--key-shadow-pressed:
inset 0 1px 2px rgba(21, 24, 26, 0.14),
0 0 0 1px rgba(21, 24, 26, 0.1),
0 1px 1px rgba(21, 24, 26, 0.05);
/* 指针反光:亚克力表面跟随光标的一块高光 */
--sheen: rgba(255, 255, 255, 0.75);
--sheen-edge: rgba(255, 255, 255, 0.95);
/* 烟熏亚克力:整页唯一的深色时刻(隐私面板) */
--smoke-fill: linear-gradient(165deg, rgba(34, 38, 41, 0.95), rgba(17, 19, 21, 0.97));
--smoke-ink: #f2f4f3;
--smoke-ink-2: #a5adb3;
--smoke-line: rgba(255, 255, 255, 0.09);
--smoke-accent: #4fcb68;
/* 磨砂颗粒:约 5% 的灰噪点,叠在面板最上层 */
--grain: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix values='1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 .05'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
--shadow-device: rgba(21, 24, 26, 0.24);
/* 四档圆角 */
--r-chip: 10px;
--r-btn: 14px;
--r-card: 24px;
--r-panel: 32px;
--content: min(1120px, calc(100vw - 48px));
/* 动效令牌:统一的缓动曲线与时长,所有组件只引用这里 */
--ease-out: cubic-bezier(0.16, 1, 0.3, 1);
--ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);
/* 物理弹簧(linear() 采样),用于需要「落定感」的元素:键帽、标签、胶囊 */
--ease-spring: linear(
0, 0.009, 0.035 2.1%, 0.141, 0.281 6.7%, 0.723 12.9%, 0.938 16.7%, 1.017,
1.077, 1.121, 1.149 24.3%, 1.159, 1.163, 1.161, 1.154 29.9%, 1.129 32.8%,
1.051 39.6%, 1.017 43.1%, 0.991, 0.977 51%, 0.974 53.8%, 0.975 57.1%,
0.997 69.8%, 1.003 76.9%, 1.004 83.8%, 1
);
--dur-fast: 0.22s;
--dur-base: 0.5s;
--dur-slow: 0.95s;
/* 键盘复刻色:取自 App 源码 ColorLibrary(brandAccent / aiTeal / recordRed),只用于首屏语音胶囊 */
--kb-accent: #3aa05a;
--kb-teal: #2bafa4;
--kb-red: #ff3b30;
}
html[data-theme="dark"] {
--canvas: #0e1011;
--ink: #eef1f0;
--ink-2: #a3abb1;
--ink-3: #79828a;
--line: rgba(255, 255, 255, 0.08);
--line-strong: rgba(255, 255, 255, 0.14);
--accent: #3ec45a;
--accent-ink: #5fd178;
--accent-soft: rgba(62, 196, 90, 0.14);
--glow-1: rgba(255, 255, 255, 0.05);
--glow-2: rgba(62, 196, 90, 0.1);
--glow-3: rgba(90, 130, 170, 0.13);
--acrylic-fill: linear-gradient(180deg, rgba(46, 50, 54, 0.64), rgba(28, 31, 34, 0.52));
--acrylic-edge: rgba(255, 255, 255, 0.07);
--acrylic-shadow:
inset 0 1px 0 rgba(255, 255, 255, 0.09),
inset 0 -1px 0 rgba(0, 0, 0, 0.3),
0 0 0 1px var(--acrylic-edge),
0 24px 48px -24px rgba(0, 0, 0, 0.6);
--key-fill: linear-gradient(180deg, #2d3135, #222528);
--key-shadow:
inset 0 1px 0 rgba(255, 255, 255, 0.1),
inset 0 -2px 0 rgba(0, 0, 0, 0.35),
0 0 0 1px rgba(255, 255, 255, 0.07),
0 8px 18px -8px rgba(0, 0, 0, 0.7);
--key-shadow-hover:
inset 0 1px 0 rgba(255, 255, 255, 0.12),
inset 0 -2px 0 rgba(0, 0, 0, 0.35),
0 0 0 1px rgba(255, 255, 255, 0.1),
0 14px 26px -10px rgba(0, 0, 0, 0.8);
--key-shadow-pressed:
inset 0 1px 3px rgba(0, 0, 0, 0.5),
0 0 0 1px rgba(255, 255, 255, 0.06);
--sheen: rgba(255, 255, 255, 0.07);
--sheen-edge: rgba(255, 255, 255, 0.28);
/* 深色主题下底板已经是深色,烟熏面板略微提亮、带一点绿光,仍是整页最「重」的一块 */
--smoke-fill: linear-gradient(165deg, rgba(40, 45, 48, 0.86), rgba(20, 23, 25, 0.9));
--shadow-device: rgba(0, 0, 0, 0.6);
}
/* 支持连续曲率圆角的浏览器:换成与图标一致的「方圆」,半径相应放大以保持视觉大小 */
@supports (corner-shape: squircle) {
:root {
--r-chip: 15px;
--r-btn: 21px;
--r-card: 38px;
--r-panel: 50px;
}
.acrylic,
.acrylic-smoke,
.keycap,
.chip,
.language-button,
.nav-shell,
.nav-indicator,
.mobile-nav,
.media-inset,
.story-act {
corner-shape: squircle;
}
}
/* --------------------------------------------------------------------------
* 2. 基础排版
* -------------------------------------------------------------------------- */
* {
box-sizing: border-box;
}
/* 底色挂在 html 上,body 保持透明,固定的环境光层(body::before)才能透出来 */
html {
scroll-behavior: smooth;
scroll-padding-top: 96px;
background: var(--canvas);
}
body {
margin: 0;
/* clip 不会生成滚动容器,滚动叙事的 position: sticky 才能正常工作 */
overflow-x: hidden;
overflow-x: clip;
color: var(--ink);
font-family: -apple-system, BlinkMacSystemFont, "SF Pro Text", "PingFang SC",
"Hiragino Sans GB", "Helvetica Neue", Arial, sans-serif;
font-size: 16px;
line-height: 1.65;
-webkit-font-smoothing: antialiased;
text-rendering: optimizeLegibility;
}
html[data-lang="en"] body {
font-family: "Outfit", -apple-system, BlinkMacSystemFont, "SF Pro Text",
"Helvetica Neue", Arial, sans-serif;
}
a {
color: inherit;
text-decoration: none;
}
button,
a {
-webkit-tap-highlight-color: transparent;
}
button {
color: inherit;
font: inherit;
}
img,
video {
display: block;
max-width: 100%;
}
h1,
h2,
h3,
p {
margin-top: 0;
}
h1,
h2,
h3 {
text-wrap: balance;
}
html[data-lang="zh"] h1,
html[data-lang="zh"] h2,
html[data-lang="zh"] h3 {
overflow-wrap: normal;
word-break: keep-all;
}
::selection {
background: var(--accent);
color: #fff;
}
:focus-visible {
outline: 2px solid var(--accent);
outline-offset: 3px;
border-radius: 6px;
}
.skip-link {
position: fixed;
z-index: 100;
top: 12px;
left: 12px;
padding: 9px 14px;
border-radius: var(--r-btn);
background: var(--ink);
color: var(--canvas);
transform: translateY(-160%);
}
.skip-link:focus {
transform: translateY(0);
}
/* 仅供读屏:逐字拆分的标题由它提供完整句子 */
.sr-only {
position: absolute;
overflow: hidden;
width: 1px;
height: 1px;
margin: -1px;
padding: 0;
border: 0;
clip: rect(0 0 0 0);
white-space: nowrap;
}
/* 内联 SVG 图标库容器:不可见但可被 <use> 引用 */
.svg-defs {
position: absolute;
width: 0;
height: 0;
overflow: hidden;
}
/* 内联 SVG 图标系统:currentColor 描边,随主题变色 */
.i {
width: 1.25em;
height: 1.25em;
flex: none;
fill: none;
stroke: currentColor;
stroke-width: 1.7;
stroke-linecap: round;
stroke-linejoin: round;
vertical-align: -0.28em;
}
/* --------------------------------------------------------------------------
* 3. 底板:固定的环境光,滚动时面板「滑过」柔光,模糊才有东西可透
* -------------------------------------------------------------------------- */
body::before {
position: fixed;
z-index: -1;
inset: 0;
background:
radial-gradient(55% 45% at 12% 6%, var(--glow-1), transparent 70%),
radial-gradient(45% 40% at 92% 30%, var(--glow-2), transparent 72%),
radial-gradient(55% 45% at 30% 100%, var(--glow-3), transparent 72%);
content: "";
pointer-events: none;
}
/* --------------------------------------------------------------------------
* 4. 材质:面板 / 烟熏面板 / 键帽 / 标签
* -------------------------------------------------------------------------- */
.acrylic {
border-radius: var(--r-card);
background: var(--grain), var(--acrylic-fill);
box-shadow: var(--acrylic-shadow);
-webkit-backdrop-filter: var(--acrylic-blur);
backdrop-filter: var(--acrylic-blur);
}
.acrylic-smoke {
--sheen: rgba(255, 255, 255, 0.06);
--sheen-edge: rgba(255, 255, 255, 0.3);
border-radius: var(--r-panel);
background: var(--grain), var(--smoke-fill);
box-shadow:
inset 0 1px 0 rgba(255, 255, 255, 0.12),
inset 0 -1px 0 rgba(0, 0, 0, 0.4),
0 0 0 1px rgba(0, 0, 0, 0.08),
0 40px 80px -36px rgba(10, 14, 16, 0.55);
color: var(--smoke-ink);
}
/* 键帽:所有按钮统一为圆角长方形(App Store 官方徽章除外) */
.keycap {
display: inline-flex;
min-height: 48px;
align-items: center;
justify-content: center;
gap: 9px;
padding: 0 20px;
border: 0;
border-radius: var(--r-btn);
background: var(--key-fill);
box-shadow: var(--key-shadow);
color: var(--ink);
cursor: pointer;
font-size: 0.95rem;
font-weight: 600;
letter-spacing: -0.005em;
white-space: nowrap;
transition: box-shadow 0.25s ease, translate 0.25s var(--ease-out), transform 0.5s var(--ease-spring);
}
.keycap:hover {
box-shadow: var(--key-shadow-hover);
translate: 0 -1px;
}
.keycap:active {
box-shadow: var(--key-shadow-pressed);
translate: 0 1px;
}
.keycap .i {
width: 17px;
height: 17px;
color: var(--ink-2);
transition: transform 0.5s var(--ease-spring);
}
.keycap:hover .i {
transform: translate(2px, -2px);
}
/* 标签:小一号的键帽,不可按,只有一层高光和发丝描边 */
.chip {
display: inline-flex;
align-items: center;
gap: 7px;
padding: 7px 13px;
border-radius: var(--r-chip);
background: var(--key-fill);
box-shadow:
inset 0 1px 0 rgba(255, 255, 255, 0.9),
0 0 0 1px var(--line),
0 4px 10px -6px rgba(21, 24, 26, 0.18);
color: var(--ink-2);
font-size: 0.86rem;
font-weight: 560;
}
html[data-theme="dark"] .chip {
box-shadow:
inset 0 1px 0 rgba(255, 255, 255, 0.08),
0 0 0 1px var(--line),
0 4px 10px -6px rgba(0, 0, 0, 0.6);
}
/* --------------------------------------------------------------------------
* 5. 导航:悬浮的亚克力条
* -------------------------------------------------------------------------- */
/* 页面滚动进度:导航条底边的一根细线,由 site.js 直接写 transform */
.scroll-progress {
position: absolute;
right: 18px;
bottom: 0;
left: 18px;
height: 1.5px;
border-radius: 2px;
background: var(--accent);
opacity: 0.7;
pointer-events: none;
transform: scaleX(0);
transform-origin: 0 50%;
}
.site-nav {
position: fixed;
z-index: 50;
top: 12px;
right: 0;
left: 0;
pointer-events: none;
}
.nav-shell {
position: relative;
display: flex;
width: var(--content);
height: 58px;
align-items: center;
justify-content: space-between;
gap: 24px;
margin: 0 auto;
padding: 0 10px 0 14px;
overflow: hidden;
border-radius: 18px;
background: var(--grain), var(--acrylic-fill);
box-shadow: var(--acrylic-shadow);
pointer-events: auto;
-webkit-backdrop-filter: var(--acrylic-blur);
backdrop-filter: var(--acrylic-blur);
}
.brand {
display: inline-flex;
align-items: center;
gap: 10px;
font-size: 0.98rem;
font-weight: 650;
letter-spacing: -0.01em;
}
.brand img {
width: 32px;
height: 32px;
filter: drop-shadow(0 3px 5px rgba(21, 24, 26, 0.16));
transition: transform var(--dur-base) var(--ease-spring);
}
.brand:hover img {
transform: rotate(-8deg) scale(1.06);
}
.nav-links {
position: relative;
display: flex;
align-items: center;
gap: 4px;
}
.nav-links a {
position: relative;
z-index: 1;
padding: 8px 14px;
color: var(--ink-2);
font-size: 0.92rem;
transition: color 0.2s ease;
}
.nav-links a:hover,
.nav-links a.is-active {
color: var(--ink);
}
/* 导航滑块:一颗小键帽,位置与宽度由 site.js 写入,弹簧曲线让它「跟手」 */
.nav-indicator {
position: absolute;
top: 50%;
left: 0;
width: var(--iw, 0px);
height: 36px;
border-radius: var(--r-chip);
background: var(--key-fill);
box-shadow: var(--key-shadow);
opacity: 0;
pointer-events: none;
transform: translate3d(var(--ix, 0px), -50%, 0);
transition: transform 0.55s var(--ease-spring), width 0.55s var(--ease-spring),
opacity 0.3s ease;
}
.nav-links.has-indicator .nav-indicator {
opacity: 1;
}
.nav-actions {
display: flex;
align-items: center;
gap: 6px;
}
/* 图标按钮保持圆形;语言按钮是文字按钮,与其他按钮一样用圆角长方形 */
.icon-button,
.language-button {
display: inline-grid;
min-width: 38px;
height: 38px;
align-items: center;
justify-content: center;
padding: 0;
border: 0;
background: transparent;
color: var(--ink-2);
cursor: pointer;
transition: color 0.2s ease, background 0.2s ease, box-shadow 0.2s ease,
transform 0.4s var(--ease-spring);
}
.icon-button {
border-radius: 50%;
}
.language-button {
padding: 0 10px;
border-radius: var(--r-chip);
font-size: 0.82rem;
font-weight: 650;
letter-spacing: 0.02em;
}
.icon-button:hover,
.language-button:hover {
background: var(--key-fill);
box-shadow: var(--key-shadow);
color: var(--ink);
}
.icon-button:active,
.language-button:active {
transform: scale(0.92);
}
.icon-button .i {
width: 19px;
height: 19px;
transition: transform 0.6s var(--ease-spring);
}
#themeToggle:hover .i {
transform: rotate(-24deg);
}
.mobile-menu-button {
display: none;
}
.mobile-nav {
display: none;
}
/* --------------------------------------------------------------------------
* 6. Hero:乳白(或烟熏)底板上的一颗亚克力键帽
* -------------------------------------------------------------------------- */
.hero {
position: relative;
display: flex;
min-height: 100svh;
flex-direction: column;
align-items: center;
padding: 128px 0 0;
overflow: hidden;
isolation: isolate;
text-align: center;
}
/* 背景层:柔光 + 声波涟漪 + 指针光斑 */
.hero-backdrop {
position: absolute;
z-index: -1;
inset: 0;
overflow: hidden;
pointer-events: none;
}
.aurora {
position: absolute;
border-radius: 50%;
filter: blur(80px);
opacity: 0.9;
will-change: transform;
}
.aurora-a {
top: -240px;
left: calc(50% - 680px);
width: 640px;
height: 640px;
background: radial-gradient(circle, var(--glow-2), transparent 66%);
animation: aurora-a 26s ease-in-out infinite alternate;
}
.aurora-b {
top: 60px;
right: calc(50% - 700px);
width: 580px;
height: 580px;
background: radial-gradient(circle, var(--glow-3), transparent 66%);
animation: aurora-b 30s ease-in-out infinite alternate;
}
.aurora-c {
top: 26%;
left: 50%;
width: 760px;
height: 420px;
margin-left: -380px;
background: radial-gradient(closest-side, var(--glow-1), transparent);
animation: aurora-c 21s ease-in-out infinite alternate;
}
@keyframes aurora-a {
0% { transform: translate3d(0, 0, 0) scale(1); }
50% { transform: translate3d(140px, 80px, 0) scale(1.18); }
100% { transform: translate3d(60px, 160px, 0) scale(0.94); }
}
@keyframes aurora-b {
0% { transform: translate3d(0, 0, 0) scale(1.05); }
50% { transform: translate3d(-120px, 60px, 0) scale(0.9); }
100% { transform: translate3d(-40px, -60px, 0) scale(1.15); }
}
@keyframes aurora-c {
0% { transform: translate3d(-60px, 0, 0) scale(1); }
100% { transform: translate3d(60px, -30px, 0) scale(1.1); }
}
/* 声波涟漪:三圈错相扩散,像一次持续的「开口」;中性色,只做气氛 */
.hero-rings i {
position: absolute;
top: 24%;
left: 50%;
width: 520px;
height: 520px;
margin: -260px 0 0 -260px;
border: 1px solid var(--line-strong);
border-radius: 50%;
opacity: 0;
animation: ring-pulse 8s cubic-bezier(0.2, 0.6, 0.3, 1) infinite;
}
.hero-rings i:nth-child(2) { animation-delay: 2.66s; }
.hero-rings i:nth-child(3) { animation-delay: 5.33s; }
@keyframes ring-pulse {
0% { opacity: 0; transform: scale(0.25); }
14% { opacity: 0.9; }
100% { opacity: 0; transform: scale(2); }
}
/* 指针光斑:--hx / --hy 由 site.js 以插值方式写入,像一盏灯照在亚克力上 */
.hero-spot {
position: absolute;
inset: 0;
background: radial-gradient(
520px circle at var(--hx, 50%) var(--hy, 26%),
var(--sheen),
transparent 62%
);
opacity: 0.8;
}
/* 文字层随滚动轻微上移淡出(--hp 为 Hero 滚动进度 0 → 1) */
.hero-inner {
position: relative;
width: var(--content);
opacity: calc(1 - var(--hp, 0) * 1.15);
transform: translate3d(0, calc(var(--hp, 0) * -70px), 0);
}
/* 主视觉的第一眼:放大的应用图标,本身就是一颗亚克力键帽;缓慢悬浮,一道反光定期扫过 */
.hero-mark {
position: relative;
width: 96px;
height: 96px;
margin: 0 auto 26px;
}
.hero-mark img {
width: 100%;
height: 100%;
filter: drop-shadow(0 18px 22px rgba(21, 24, 26, 0.16)) drop-shadow(0 4px 6px rgba(21, 24, 26, 0.1));
animation: mark-float 7s ease-in-out infinite;
}
/* 反光只落在图标自身的形状里(用图标本身做遮罩) */
.hero-mark::after {
position: absolute;
inset: 0;
background: linear-gradient(115deg, transparent 38%, rgba(255, 255, 255, 0.85) 50%, transparent 62%);
background-size: 300% 100%;
content: "";
-webkit-mask: url("app-icon.png?v=20260927b") center / contain no-repeat;
mask: url("app-icon.png?v=20260927b") center / contain no-repeat;
mix-blend-mode: soft-light;
animation: mark-float 7s ease-in-out infinite, mark-sheen 7s ease-in-out infinite;
}
@keyframes mark-float {
0%, 100% { translate: 0 0; rotate: 0deg; }
50% { translate: 0 -7px; rotate: -2deg; }
}
@keyframes mark-sheen {
0%, 55% { background-position: 100% 0; }
80%, 100% { background-position: 0 0; }
}
html[data-theme="dark"] .hero-mark img {
filter: drop-shadow(0 18px 26px rgba(0, 0, 0, 0.55)) drop-shadow(0 0 30px rgba(255, 255, 255, 0.06));
}
.launch-pill {
margin-bottom: 20px;
font-size: 0.8rem;
}
/* 版本标签上的绿点:整屏唯一的绿色,表示「已上线」 */
.launch-dot {
position: relative;
width: 7px;
height: 7px;
border-radius: 50%;
background: var(--accent);
}
.launch-dot::after {
position: absolute;
inset: 0;
border-radius: 50%;
background: var(--accent);
content: "";
animation: ping 2.4s cubic-bezier(0, 0, 0.2, 1) infinite;
}
@keyframes ping {
0% { opacity: 0.7; transform: scale(1); }
80%, 100% { opacity: 0; transform: scale(3); }
}
/* H1 承载品类关键词;视觉上是一行小标,一道银色反光缓慢扫过 */
.hero-kicker {
margin: 0 auto 16px;
background: linear-gradient(
100deg,
var(--ink-2) 0%,
var(--ink-2) 40%,
var(--ink-3) 50%,
var(--ink-2) 60%,
var(--ink-2) 100%
);
background-size: 250% 100%;
-webkit-background-clip: text;
background-clip: text;
color: transparent;
font-size: clamp(0.9rem, 1.3vw, 1.02rem);
font-weight: 600;
letter-spacing: 0.03em;
line-height: 1.5;
animation: shimmer 7s linear infinite;
}
@keyframes shimmer {
from { background-position: 125% 0; }
to { background-position: -125% 0; }
}
.hero-slogan {
margin: 0 0 22px;
}
.slogan-main {
display: block;
font-size: clamp(2.9rem, 7.2vw, 5.4rem);
font-weight: 680;
letter-spacing: -0.045em;
line-height: 1.04;
}
.slogan-sub {
display: block;
margin-top: 12px;
color: var(--ink-2);
font-size: clamp(1.3rem, 2.6vw, 1.95rem);
font-weight: 560;
letter-spacing: -0.02em;
line-height: 1.25;
}
.hero-copy {
max-width: 620px;
margin: 0 auto 32px;
color: var(--ink-2);
font-size: 1.06rem;
line-height: 1.7;
}
.hero-actions {
display: flex;
align-items: center;
justify-content: center;
flex-wrap: wrap;
gap: 14px;
margin-bottom: 26px;
}
/* App Store / Mac 官方徽章:按 Apple 营销规范原样使用,只加一层悬停浮起 */
.store-badge {
display: inline-flex;
border-radius: 10px;
transition: transform 0.5s var(--ease-spring), filter 0.3s ease;
}
.store-badge:hover {
filter: drop-shadow(0 10px 18px rgba(21, 24, 26, 0.22));
}
.store-badge img {
width: 171px;
height: 48px;
}
.hero-trust {
display: flex;
align-items: center;
justify-content: center;
flex-wrap: wrap;
gap: 10px 26px;
margin: 0 0 40px;
padding: 0;
color: var(--ink-3);
font-size: 0.86rem;
list-style: none;
}
.hero-trust li {
display: inline-flex;
align-items: center;
gap: 7px;
}
.hero-trust .i {
width: 16px;
height: 16px;
}
/* 主视觉舞台:透视容器,内部设备图随滚动从后仰 14° 立到正视 */
.hero-stage {
position: relative;
width: min(1060px, 94vw);
margin: auto 0 0;
perspective: 1600px;
}
.hero-devices {
transform: rotateX(calc((1 - var(--hp, 0)) * 14deg)) scale(calc(0.92 + var(--hp, 0) * 0.08));
transform-origin: 50% 100%;
will-change: transform;
}
.hero-devices img {
width: 100%;
height: auto;
filter: drop-shadow(0 40px 60px var(--shadow-device));
}
/*
* 语音胶囊:一块悬浮的亚克力面板(圆角长方形),里面的麦克风胶囊与键盘真实组件同色同形。
* 待机 = 品牌绿 + 麦克风;录音 = 红色 + 7 条声波;长按问 AI = 青色 + 声波;
* 处理中 = 半透明红 + 转圈;插入成功 = 品牌绿 + 对勾。状态类由 site.js 切换。
*/
.voice-capsule {
position: absolute;
z-index: 2;
bottom: 22%;
left: 50%;
display: flex;
max-width: 92%;
align-items: center;
gap: 14px;
padding: 9px 20px 9px 9px;
border-radius: 18px;
translate: -50% 0;
}
.capsule-mic {
position: relative;
display: grid;
width: 78px;
height: 32px;
flex: none;
place-items: center;
border-radius: 999px;
background: var(--kb-accent);
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.28), 0 6px 18px -6px color-mix(in srgb, var(--kb-accent) 80%, transparent);
color: #fff;
transition: background-color 0.35s ease, box-shadow 0.35s ease, transform 0.5s var(--ease-spring);
}
.capsule-mic > * {
grid-area: 1 / 1;
transition: opacity 0.25s ease, transform 0.45s var(--ease-spring);
}
.cap-mic {
width: 17px;
height: 17px;
stroke-width: 2.2;
}
.cap-check {
width: 18px;
height: 18px;
stroke-width: 3;
}
.capsule-wave,
.capsule-spin,
.cap-check {
opacity: 0;
transform: scale(0.6);
}
.voice-capsule.is-rec .capsule-mic {
background: var(--kb-red);
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.28), 0 6px 22px -6px color-mix(in srgb, var(--kb-red) 85%, transparent);
}
.voice-capsule.is-ai .capsule-mic {
background: var(--kb-teal);
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.28), 0 6px 22px -6px color-mix(in srgb, var(--kb-teal) 85%, transparent);
transform: scale(1.04);
}
.voice-capsule.is-busy .capsule-mic {
background: color-mix(in srgb, var(--kb-red) 72%, #2a2d31);
}
.voice-capsule:is(.is-rec, .is-ai, .is-busy, .is-done) .cap-mic {
opacity: 0;
transform: scale(0.6);
}
.voice-capsule:is(.is-rec, .is-ai) .capsule-wave,
.voice-capsule.is-busy .capsule-spin,
.voice-capsule.is-done .cap-check {
opacity: 1;
transform: none;
}
/* 声波条:site.js 每帧写 scaleY,只动 transform,不触发布局 */
.capsule-wave {
display: flex;
height: 16px;
align-items: center;
gap: 2.5px;
}
.capsule-wave i {
width: 2.5px;
height: 100%;
border-radius: 2px;
background: #ffd6d6;
transform: scaleY(0.14);
}
.voice-capsule.is-ai .capsule-wave i {
background: #fff;
}
/* 系统风格的转圈:处理中状态 */
.capsule-spin {
width: 15px;
height: 15px;
border: 2px solid rgba(255, 255, 255, 0.35);
border-top-color: #fff;
border-radius: 50%;
animation: spin 0.8s linear infinite;
}
@keyframes spin {
to { rotate: 1turn; }
}
.capsule-body {
display: flex;
min-width: min(400px, 52vw);
align-items: center;
gap: 10px;
font-size: 0.98rem;
text-align: left;
white-space: nowrap;
}
.capsule-tag {
flex: none;
padding: 3px 9px;
border-radius: 7px;
background: var(--line);
color: var(--ink-2);
font-size: 0.74rem;
font-weight: 650;
letter-spacing: 0.03em;
transition: background 0.3s ease, color 0.3s ease;
}
/* 标签颜色跟随胶囊状态:问 AI 用青色,与麦克风胶囊呼应 */
.voice-capsule:is(.is-ai, .is-ai-busy) .capsule-tag {
background: color-mix(in srgb, var(--kb-teal) 16%, transparent);
color: color-mix(in srgb, var(--kb-teal) 70%, var(--ink));
}
.capsule-line {
overflow: hidden;
min-width: 0;
text-overflow: ellipsis;
}
.caret {
display: inline-block;
width: 2px;
height: 1.1em;
flex: none;
margin-left: 1px;
border-radius: 1px;
background: var(--ink-2);
vertical-align: -0.18em;
animation: caret-blink 1.05s steps(1) infinite;
}
@keyframes caret-blink {
50% { opacity: 0; }
}
/* 向下滚动提示:圆角长方形的「鼠标」轮廓 */
.scroll-cue {
position: absolute;
z-index: 3;
right: 32px;
bottom: 30px;
display: grid;
width: 24px;
height: 38px;
justify-items: center;
padding-top: 7px;
border: 1.5px solid var(--line-strong);
border-radius: 12px;
opacity: calc(1 - var(--hp, 0) * 4);
}
.scroll-cue span {
width: 3px;
height: 8px;
border-radius: 3px;
background: var(--ink-3);
animation: cue 2s var(--ease-in-out) infinite;
}
@keyframes cue {
0% { opacity: 0; transform: translateY(-3px); }
30% { opacity: 1; }
100% { opacity: 0; transform: translateY(12px); }
}
/* 首屏进场:Hero 元素按 --d 错峰「浮现 + 去模糊」 */
html.js .hero-in {
animation: rise-in 1.1s var(--ease-out) var(--d, 0s) both;
}
@keyframes rise-in {
from { opacity: 0; filter: blur(8px); translate: 0 26px; }
to { opacity: 1; filter: none; translate: 0 0; }
}
html.js .voice-capsule {
animation: capsule-in 1.1s var(--ease-spring) 1.6s both;
}
@keyframes capsule-in {
from { opacity: 0; transform: translateY(24px) scale(0.86); }
to { opacity: 1; transform: none; }
}
/* --------------------------------------------------------------------------
* 7. 逐字动效(data-split)
* site.js 把文字拆成 .w(词,防止英文断词)与 .ch(字符),
* 每个字符带 --ci 序号,延迟 = 基础延迟 + 序号 × 步长。
* -------------------------------------------------------------------------- */
[data-split] .w {
display: inline-block;
white-space: nowrap;
}
[data-split] .ch {
display: inline-block;
}
/* 拆分完成前先隐藏,避免「整句出现 → 被拆开重播」的闪烁 */
html.js [data-split]:not(.is-split) {
opacity: 0;
}
/* Hero 口号:页面加载即播放 */
html.js .hero-slogan .ch {
animation: char-in 1s var(--ease-out) both;
animation-delay: calc(var(--base, 0.2s) + var(--ci) * var(--step, 45ms));
}
.slogan-main { --base: 0.3s; --step: 52ms; }
.slogan-sub { --base: 0.6s; --step: 24ms; }
@keyframes char-in {
from { opacity: 0; filter: blur(10px); transform: translateY(0.55em) rotate(3deg); }
to { opacity: 1; filter: none; transform: none; }
}
/* 区块标题:所在 .reveal 进入视口时播放 */
html.js .reveal [data-split] .ch {
opacity: 0;
filter: blur(8px);
transform: translateY(0.5em);
transition: opacity 0.7s ease-out, filter 0.7s ease-out, transform 0.95s var(--ease-out);
transition-delay: calc(var(--d, 0s) + 0.08s + var(--ci) * 24ms);
}
html.js .reveal.is-visible [data-split] .ch {
opacity: 1;
filter: blur(0);
transform: none;
}
/* --------------------------------------------------------------------------
* 8. 能力跑马灯:一行安静的中性色小字
* -------------------------------------------------------------------------- */
.marquee {
overflow: hidden;
padding: 14px 0;
-webkit-mask-image: linear-gradient(90deg, transparent, #000 12%, #000 88%, transparent);
mask-image: linear-gradient(90deg, transparent, #000 12%, #000 88%, transparent);
}
.marquee-track {
display: flex;
width: max-content;
animation: marquee 56s linear infinite;
}
.marquee:hover .marquee-track {
animation-play-state: paused;
}
.marquee ul {
display: flex;
margin: 0;
padding: 0;
list-style: none;
}
.marquee li {
display: flex;
align-items: center;
gap: 16px;
padding-right: 16px;
color: var(--ink-3);
font-size: clamp(0.6rem, 0.9vw, 0.72rem);
font-weight: 600;
letter-spacing: 0.01em;
white-space: nowrap;
}
.marquee li:nth-child(-n + 3) {
color: var(--ink-2);
}
.marquee li::after {
width: 4px;
height: 4px;
border-radius: 50%;
background: var(--line-strong);
content: "";
}
@keyframes marquee {
to { transform: translateX(-50%); }
}
/* --------------------------------------------------------------------------
* 9. 区块节奏:所有区块共用同一块底板,靠留白而不是色带分隔
* -------------------------------------------------------------------------- */
.section {
padding: clamp(80px, 10vw, 128px) 0;
}
.section-inner {
width: var(--content);
margin: 0 auto;
}
.eyebrow {
margin-bottom: 14px;
color: var(--ink-3);
font-size: 0.8rem;
font-weight: 650;
letter-spacing: 0.08em;
}
h2 {
margin-bottom: 18px;
font-size: clamp(1.9rem, 3.7vw, 2.75rem);
font-weight: 680;
letter-spacing: -0.026em;
line-height: 1.14;
}
h3 {
font-size: 1.1rem;
font-weight: 640;
letter-spacing: -0.01em;
}
.center-heading {
max-width: 700px;
margin: 0 auto clamp(44px, 6vw, 68px);
text-align: center;
}
.center-heading p:not(.eyebrow) {
color: var(--ink-2);
font-size: 1.05rem;
}
/* 分栏布局:文案 + 真机 */
.split-layout {
display: grid;
align-items: center;
gap: clamp(40px, 6vw, 88px);
grid-template-columns: 1.05fr 1fr;
}
.split-layout.reverse .feature-copy {
order: 2;
}
.split-layout.reverse .device-stage {
order: 1;
}
.feature-copy > p:not(.eyebrow) {
color: var(--ink-2);
font-size: 1.05rem;
}
.feature-note {
margin-top: 22px;
padding-top: 18px;
border-top: 1px solid var(--line);
color: var(--ink-3);
font-size: 0.92rem;
}
/* 嵌在面板里的小画面(截图 / 录屏):同心圆角 = 卡片圆角 − 内边距 */
.media-inset {
overflow: hidden;
border-radius: calc(var(--r-card) - 12px);
background: var(--canvas);
box-shadow: 0 0 0 1px var(--line);
}
/* --------------------------------------------------------------------------
* 10. 滚动叙事(四幕)
* 滚动进度决定当前幕;手机里播放这一幕的真机录屏,幕内进度条跟随播放进度(--ap)。
* 无 JavaScript 时四幕文案平铺,手机停在第一幕的首帧。
* -------------------------------------------------------------------------- */
.story-section {
padding-bottom: 0;
}
.story-section .center-heading {
margin-bottom: 0;
}
.story {
position: relative;
height: 520vh;
}
.story-sticky {
position: sticky;
top: 0;
display: flex;
height: 100vh;
height: 100svh;
align-items: center;
padding-top: 70px;
}
.story-layout {
display: grid;
width: var(--content);
align-items: center;
gap: clamp(40px, 7vw, 120px);
margin: 0 auto;
grid-template-columns: 1fr auto;
}
.story-acts {
display: grid;
max-width: 540px;
gap: 8px;
margin: 0;
padding: 0;
list-style: none;
}
/* 未激活的幕只是文字;激活的幕浮起成一块亚克力面板 */
.story-act {
display: flex;
gap: 20px;
padding: 18px 22px;
border-radius: var(--r-card);
opacity: 0.42;
transition: opacity 0.5s ease, background 0.5s ease, box-shadow 0.5s ease,
transform 0.7s var(--ease-out);
}
.story-act.is-active {
background: var(--grain), var(--acrylic-fill);
box-shadow: var(--acrylic-shadow);
opacity: 1;
transform: translateX(6px);
-webkit-backdrop-filter: var(--acrylic-blur);
backdrop-filter: var(--acrylic-blur);
}
.act-index {
padding-top: 2px;
color: var(--ink-3);
font-size: 0.8rem;
font-variant-numeric: tabular-nums;
font-weight: 700;
letter-spacing: 0.04em;
transition: color 0.4s ease;
}
.story-act.is-active .act-index {
color: var(--accent-ink);
}
.act-body {
flex: 1;
}
.act-kicker {
margin: 0 0 4px;
color: var(--ink-3);
font-size: 0.78rem;
font-weight: 650;
letter-spacing: 0.06em;
}
.act-body h3 {
margin-bottom: 6px;
font-size: clamp(1.16rem, 1.8vw, 1.42rem);
letter-spacing: -0.02em;
}
.act-body > p:not(.act-kicker) {
margin: 0;
color: var(--ink-2);
font-size: 0.95rem;
}
/* 未激活的幕收起正文,只留标题,四幕才放得进一屏 */
html.js .story-act:not(.is-active) .act-body > p:not(.act-kicker),
html.js .story-act:not(.is-active) .act-bar {
display: none;
}
/* 幕内进度条:--ap 由 site.js 写入(0 → 1);绿色只用在这根指示线上 */
.act-bar {
display: block;
overflow: hidden;
height: 2px;
margin-top: 14px;
border-radius: 2px;
background: var(--line);
}
.act-bar i {
display: block;
height: 100%;
background: var(--accent);
transform: scaleX(var(--ap, 0));
transform-origin: left;
transition: transform 0.3s linear;
}
/* 舞台:真机 + 背后一团呼吸的白光 */
.story-device {
position: relative;
display: grid;
place-items: center;
}
.story-device::before,
.device-stage::before {
position: absolute;
width: 130%;
height: 76%;
border-radius: 50%;
background: radial-gradient(closest-side, var(--glow-1), transparent);
content: "";
filter: blur(30px);
animation: device-glow 6s ease-in-out infinite;
}
@keyframes device-glow {
0%, 100% { opacity: 0.6; transform: scale(1); }
50% { opacity: 1; transform: scale(1.06); }
}
/* --------------------------------------------------------------------------
* 真机外框:Apple 官方 iPhone 17 Pro 机框图(原图 1350 × 2760)。
* 屏幕开口为 1206 × 2622、起点 (72, 69),换算成百分比后放置录屏;
* 模拟器录屏正是这个分辨率,像素一一对应。机框自带灵动岛与圆角,叠在录屏之上。
* -------------------------------------------------------------------------- */
.iphone {
--w: min(330px, calc((100svh - 150px) * 0.489));
position: relative;
width: var(--w);
aspect-ratio: 1350 / 2760;
filter: drop-shadow(0 40px 48px var(--shadow-device)) drop-shadow(0 12px 16px rgba(8, 12, 16, 0.12));
}
.iphone-screen {
position: absolute;
top: 2.5%;
left: 5.333%;
width: 89.333%;
height: 95%;
overflow: hidden;
/* 开口圆角约 230px:230 / 1206 与 230 / 2622 */
border-radius: 19% / 8.8%;
background: #000;
}
/* 同一屏幕里叠放多段录屏,当前一段淡入 */
.iphone-clip {
position: absolute;
inset: 0;
display: block;
width: 100%;
height: 100%;
object-fit: cover;
opacity: 0;
transition: opacity 0.5s var(--ease-out);
}
.iphone-clip.is-on {
opacity: 1;
}
.iphone-bezel {
position: absolute;
inset: 0;
width: 100%;
height: 100%;
pointer-events: none;
user-select: none;
}
/* 分栏区块里的真机:与文案并排居中 */
.device-stage {
position: relative;
display: grid;
margin: 0;
place-items: center;
}
.device-stage .iphone {
--w: min(320px, 76vw);
}
/* --------------------------------------------------------------------------
* 11. 嘴替输入法:三块面板
* -------------------------------------------------------------------------- */
.personal-grid {
display: grid;
gap: 20px;
grid-template-columns: repeat(3, 1fr);
}
.personal-card {
display: flex;
flex-direction: column;
padding: 12px;
}
/* 截图本身就是一张带底色的卡片:完整显示(contain),像一张小卡片浮在面板里 */
.personal-media {
display: grid;
aspect-ratio: 4 / 3;
place-items: center;
padding: 14px;
}
.personal-media img {
width: 100%;
height: 100%;
object-fit: contain;
filter: drop-shadow(0 8px 14px rgba(21, 24, 26, 0.1));
transition: transform 1.2s var(--ease-out);
}
.personal-media.is-video {
padding: 0;
}
.personal-media video {
width: 100%;
height: 100%;
object-fit: cover;
object-position: top center;
transition: transform 1.2s var(--ease-out);
}
.personal-card:hover .personal-media img,
.personal-card:hover .personal-media video {
transform: scale(1.03);
}
.personal-card h3 {
margin: 20px 12px 8px;
}
.personal-card p {
margin: 0;
padding: 0 12px 14px;
color: var(--ink-2);
font-size: 0.94rem;
}
/* --------------------------------------------------------------------------
* 12. 功能区块:技能 / 打字
* -------------------------------------------------------------------------- */
.mini-feature {
margin-top: 24px;
}
.mini-feature h3 {
display: flex;
align-items: center;
gap: 10px;
margin-bottom: 6px;
}
.mini-feature h3 .i {
width: 19px;
height: 19px;
color: var(--ink-3);
}
.mini-feature p {
margin: 0;
color: var(--ink-2);
font-size: 0.97rem;
}
.skill-chips {
display: flex;
flex-wrap: wrap;
gap: 9px;
margin: 26px 0 4px;
}
.skill-chips .chip {
color: var(--ink);
transition: transform 0.5s var(--ease-spring), box-shadow 0.25s ease;
}
.skill-chips .chip:hover {
transform: translateY(-3px);
}
.skill-chips .i {
width: 15px;
height: 15px;
color: var(--ink-3);
}
/* 进场用 animation 而非 transition,避免进场延迟拖慢之后的悬停反馈 */
html.js .reveal:not(.is-visible) .skill-chips .chip {
opacity: 0;
}
html.js .reveal.is-visible .skill-chips .chip {
animation: chip-in 0.8s var(--ease-spring) both;
animation-delay: calc(0.3s + var(--ci, 0) * 60ms);
}
@keyframes chip-in {
from { opacity: 0; transform: translateY(12px) scale(0.85); }
to { opacity: 1; transform: none; }
}
.quiet-list {
display: grid;
gap: 12px;
margin: 24px 0 0;
padding: 0;
color: var(--ink-2);
font-size: 0.95rem;
list-style: none;
}
.quiet-list li {
position: relative;
padding-left: 26px;
}
.quiet-list li::before {
position: absolute;
top: 3px;
left: 0;
width: 16px;
height: 16px;
color: var(--ink-3);
/* 内联 check 图标,避免外部字体依赖 */
content: "";
-webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12.5l4.5 4.5L19 7.5'/%3E%3C/svg%3E") center / contain no-repeat;
mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12.5l4.5 4.5L19 7.5'/%3E%3C/svg%3E") center / contain no-repeat;
background: currentColor;
}
/* 数字:进入视口时滚动计数(无 JS 时直接显示最终数值) */
.stat-row {
display: grid;
gap: 12px;
margin-top: 28px;
grid-template-columns: 1fr 1fr;
}
.stat {
padding: 18px 20px;
}
.stat strong {
display: block;
margin-bottom: 4px;
font-size: clamp(1.9rem, 3.4vw, 2.5rem);
font-variant-numeric: tabular-nums;
font-weight: 680;
letter-spacing: -0.04em;
line-height: 1.05;
}
.stat span {
display: block;
color: var(--ink-2);
font-size: 0.88rem;
line-height: 1.5;
}
/* --------------------------------------------------------------------------
* 13. 隐私:整页唯一的烟熏亚克力面板(含可选账号)
* -------------------------------------------------------------------------- */
.privacy-panel {
position: relative;
padding: clamp(36px, 6vw, 72px) clamp(20px, 5vw, 56px) clamp(24px, 4vw, 40px);
overflow: hidden;
isolation: isolate;
}
/* 面板顶部一团极淡的光,像灯从上方照进烟熏亚克力 */
.privacy-panel::before {
position: absolute;
z-index: -1;
top: -40%;
left: 50%;
width: 760px;
height: 520px;
margin-left: -380px;
border-radius: 50%;
background: radial-gradient(closest-side, rgba(255, 255, 255, 0.08), transparent);
content: "";
}
.privacy-panel .center-heading p:not(.eyebrow) {
color: var(--smoke-ink-2);
}
.privacy-panel .eyebrow {
color: var(--smoke-ink-2);
}
/* 端侧徽记:声波在设备轮廓内跳动,轨道粒子绕行但从不越界 */
.device-emblem {
position: relative;
width: 112px;
height: 112px;
margin: 0 auto 24px;
}
.device-emblem::before {
position: absolute;
inset: -20%;
border-radius: 50%;
background: radial-gradient(closest-side, rgba(79, 203, 104, 0.2), transparent);
content: "";
animation: breathe 4s ease-in-out infinite;
}
@keyframes breathe {
50% { opacity: 0.45; transform: scale(0.9); }
}
.device-emblem svg {
position: relative;
width: 100%;
height: 100%;
overflow: visible;
}
.emblem-orbit {
fill: none;
stroke: rgba(255, 255, 255, 0.22);
stroke-dasharray: 2 6;
stroke-width: 1;
}
.emblem-spin {
fill: var(--smoke-ink-2);
transform-origin: 80px 80px;
animation: orbit 10s linear infinite;
}
.emblem-spin-rev {
opacity: 0.6;
animation-direction: reverse;
animation-duration: 15s;
}
@keyframes orbit {
to { transform: rotate(360deg); }
}
.emblem-device {
fill: rgba(255, 255, 255, 0.05);
stroke: rgba(255, 255, 255, 0.4);
stroke-width: 1.5;
}
.emblem-wave rect {
fill: var(--smoke-accent);
transform-box: fill-box;
transform-origin: center;
animation: eq 1.3s ease-in-out infinite;
}
.emblem-wave rect:nth-child(2) { animation-delay: -0.2s; }
.emblem-wave rect:nth-child(3) { animation-delay: -0.45s; }
.emblem-wave rect:nth-child(4) { animation-delay: -0.7s; }
.emblem-wave rect:nth-child(5) { animation-delay: -0.95s; }
@keyframes eq {
0%, 100% { transform: scaleY(0.45); }
50% { transform: scaleY(1); }
}
/* 烟熏面板里的子卡片:同一种材质再叠一层,靠高光和更亮的底区分 */
.service-paths {
display: grid;
align-items: stretch;
gap: 14px;
grid-template-columns: 1.2fr 1fr 1fr;
}
.smoke-card {
position: relative;
padding: 26px 24px 22px;
border-radius: calc(var(--r-panel) - 12px);
background: rgba(255, 255, 255, 0.045);
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.08), 0 0 0 1px var(--smoke-line);
}
.smoke-card.is-primary {
background: rgba(255, 255, 255, 0.075);
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.14), 0 0 0 1px rgba(255, 255, 255, 0.14);
}
/* 「默认」标签:烟熏面板里唯一的绿色 */
.path-badge {
position: absolute;
top: 20px;
right: 20px;
padding: 4px 10px;
border-radius: 8px;
background: color-mix(in srgb, var(--smoke-accent) 18%, transparent);
color: var(--smoke-accent);
font-size: 0.72rem;
font-weight: 700;
letter-spacing: 0.05em;
}
.path-icon {
width: 24px;
height: 24px;
margin-bottom: 16px;
color: var(--smoke-ink-2);
}
.smoke-card h3 {
margin-bottom: 8px;
font-size: 1.18rem;
}
.smoke-card p {
color: var(--smoke-ink-2);
font-size: 0.94rem;
}
.path-note {
display: block;
margin-top: 16px;
padding-top: 14px;
border-top: 1px solid var(--smoke-line);
color: var(--smoke-ink-2);
font-size: 0.82rem;
letter-spacing: 0.01em;
}
/* 可选账号:并入隐私面板,标题 + 两列要点 */
.account-row {
display: grid;
align-items: start;
gap: 18px 40px;
margin-top: 14px;
padding: 26px 28px;
grid-template-columns: minmax(200px, 0.8fr) 2fr;
}
.account-row h3 {
margin: 0 0 6px;
font-size: 1.12rem;
}
.account-row > div > p {
margin: 0;
color: var(--smoke-ink-2);
font-size: 0.9rem;
}
.account-row .quiet-list {
margin: 0;
color: var(--smoke-ink-2);
font-size: 0.92rem;
grid-template-columns: 1fr 1fr;
gap: 12px 28px;
}
.account-row .quiet-list li::before {
color: rgba(255, 255, 255, 0.4);
}
.privacy-proof {
display: flex;
align-items: center;
justify-content: space-between;
gap: 28px;
margin-top: 14px;
padding: 22px 28px;
}
.privacy-proof > div {
display: flex;
align-items: center;
gap: 20px;
}
/* 「0」:0 个第三方追踪 SDK,从 99 倒数到 0 */
.privacy-proof strong {
flex: none;
font-size: 2.6rem;
font-variant-numeric: tabular-nums;
font-weight: 680;
letter-spacing: -0.04em;
line-height: 1;
}
.privacy-proof h3 {
margin: 0;
color: var(--smoke-ink);
font-size: 1rem;
font-weight: 560;
letter-spacing: 0;
}
/* 烟熏面板里的键帽:深色版 */
.acrylic-smoke .keycap {
flex: none;
background: linear-gradient(180deg, rgba(255, 255, 255, 0.12), rgba(255, 255, 255, 0.06));
box-shadow:
inset 0 1px 0 rgba(255, 255, 255, 0.16),
inset 0 -2px 0 rgba(0, 0, 0, 0.3),
0 0 0 1px rgba(255, 255, 255, 0.1),
0 8px 18px -8px rgba(0, 0, 0, 0.6);
color: var(--smoke-ink);
}
.acrylic-smoke .keycap:active {
box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.5), 0 0 0 1px rgba(255, 255, 255, 0.08);
}
.acrylic-smoke .keycap .i {
color: var(--smoke-ink-2);
}
/* --------------------------------------------------------------------------
* 14. 平台 + 稳定性
* -------------------------------------------------------------------------- */
.platform-grid {
display: grid;
gap: 20px;
grid-template-columns: 1fr 1fr;
}
.platform-card {
padding: 12px;
}
.platform-card .media-inset {
aspect-ratio: 4 / 3;
}
.platform-card .media-inset img {
width: 100%;
height: 100%;
object-fit: cover;
object-position: top center;
transition: transform 1.4s var(--ease-out);
}
.platform-card:hover .media-inset img {
transform: scale(1.03);
}
.platform-label {
display: block;
margin: 22px 16px 8px;
color: var(--ink-3);
font-size: 0.78rem;
font-weight: 700;
letter-spacing: 0.07em;
}
.platform-card h3 {
margin: 0 16px 10px;
}
.platform-card > p {
margin: 0;
padding: 0 16px 18px;
color: var(--ink-2);
font-size: 0.95rem;
}
.platform-footnote {
max-width: 720px;
margin: 28px auto 0;
color: var(--ink-3);
font-size: 0.88rem;
text-align: center;
}
/* 稳定性:一行标签,挂在平台区末尾 */
.reliability {
display: flex;
align-items: center;
justify-content: center;
flex-wrap: wrap;
gap: 10px;
margin-top: 22px;
}
.reliability-title {
margin-right: 6px;
color: var(--ink-2);
font-size: 0.9rem;
font-weight: 650;
}
.reliability .chip {
font-size: 0.82rem;
}
/* --------------------------------------------------------------------------
* 15. FAQ:居中单栏(展开高度由 site.js 用 Web Animations 过渡)
* -------------------------------------------------------------------------- */
.faq-list {
max-width: 780px;
margin: 0 auto;
padding: 8px 28px;
}
.faq-item {
overflow: hidden;
border-top: 1px solid var(--line);
}
.faq-item:first-child {
border-top: 0;
}
.faq-item summary {
position: relative;
padding: 20px 40px 20px 0;
cursor: pointer;
font-size: 1.02rem;
font-weight: 600;
letter-spacing: -0.005em;
list-style: none;
transition: color 0.2s ease;
}
.faq-item summary::-webkit-details-marker {
display: none;
}
.faq-item summary::after {
position: absolute;
top: 22px;
right: 4px;
width: 18px;
height: 18px;
color: var(--ink-3);
content: "";
-webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9.5l6 6 6-6'/%3E%3C/svg%3E") center / contain no-repeat;
mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9.5l6 6 6-6'/%3E%3C/svg%3E") center / contain no-repeat;
background: currentColor;
transition: transform 0.5s var(--ease-spring);
}
.faq-item[open] summary::after {
transform: rotate(180deg);
}
.faq-item summary:hover {
color: var(--ink-2);
}
.faq-item p {
margin: 0;
padding: 0 32px 22px 0;
color: var(--ink-2);
font-size: 0.95rem;
}
.faq-item[open] p {
animation: faq-in 0.5s var(--ease-out);
}
@keyframes faq-in {
from { opacity: 0; transform: translateY(-6px); }
to { opacity: 1; transform: none; }
}
/* --------------------------------------------------------------------------
* 16. 下载:一块大亚克力面板,与首屏的图标键帽首尾呼应
* -------------------------------------------------------------------------- */
.download-section {
padding-top: 0;
}
.download-panel {
position: relative;
display: flex;
overflow: hidden;
align-items: center;
justify-content: space-between;
gap: 40px;
padding: clamp(36px, 6vw, 72px);
border-radius: var(--r-panel);
isolation: isolate;
}
.download-backdrop {
position: absolute;
z-index: -1;
inset: 0;
pointer-events: none;
}
.download-backdrop .aurora-a {
top: -70%;
left: -14%;
width: 520px;
height: 520px;
}
.download-backdrop .aurora-b {
top: auto;
right: -16%;
bottom: -80%;
width: 520px;
height: 520px;
}
/* 声波路径:虚线沿曲线流动,两条反向错速;中性色 */
.download-wave {
position: absolute;
right: 0;
bottom: 0;
left: 0;
width: 100%;
height: 55%;
opacity: 0.5;
}
.download-wave path {
fill: none;
stroke: var(--line-strong);
stroke-dasharray: 6 12;
stroke-width: 1.5;
vector-effect: non-scaling-stroke;
animation: dash-flow 5s linear infinite;
}
.download-wave path:nth-child(2) {
opacity: 0.6;
animation-direction: reverse;
animation-duration: 8s;
}
@keyframes dash-flow {
to { stroke-dashoffset: -180; }
}
.download-mark {
width: 64px;
height: 64px;
margin-bottom: 22px;
filter: drop-shadow(0 10px 14px rgba(21, 24, 26, 0.16));
}
.download-copy h2 {
margin-bottom: 12px;
font-size: clamp(1.9rem, 4vw, 2.9rem);
}
.download-copy p {
max-width: 460px;
margin: 0;
color: var(--ink-2);
}
.download-actions {
display: flex;
flex: none;
flex-direction: column;
align-items: stretch;
gap: 12px;
}
/* --------------------------------------------------------------------------
* 17. 页脚
* -------------------------------------------------------------------------- */
.site-footer {
padding: 40px 0 52px;
}
.footer-inner {
display: flex;
width: var(--content);
align-items: center;
justify-content: space-between;
gap: 20px;
margin: 0 auto;
color: var(--ink-3);
font-size: 0.86rem;
}
.footer-links {
display: flex;
gap: 26px;
}
.footer-links a {
transition: color 0.2s ease;
}
.footer-links a:hover {
color: var(--ink);
}
/* --------------------------------------------------------------------------
* 18. 动效系统:滚动显现 / 遮罩揭示 / 亚克力反光 / 磁吸 / 主题过渡
* -------------------------------------------------------------------------- */
/*
* 进场只动 opacity + translate(独立属性),把 transform 留给悬停与视差,
* 两套动效互不覆盖。进场延迟只作用在进场属性上,悬停反馈始终即时。
*/
html.js .reveal {
opacity: 0;
translate: 0 30px;
transition-delay: var(--d, 0s), var(--d, 0s), 0s, 0s, var(--d, 0s);
transition-duration: 0.9s, 1.05s, 0.5s, 0.35s, 1.25s;
transition-property: opacity, translate, transform, box-shadow, clip-path;
transition-timing-function: ease-out, var(--ease-out), var(--ease-out), ease, var(--ease-out);
}
html.js .reveal.is-visible {
opacity: 1;
translate: 0 0;
}
/* 视差元素的 transform 每帧由脚本写入,不再叠加过渡 */
html.js .reveal[data-parallax] {
transition-duration: 0.9s, 1.05s, 0s, 0.35s, 1.25s;
}
/* 遮罩揭示:画面从内缩的圆角矩形展开,内部画面同时从 112% 回落 */
html.js .unmask.reveal {
clip-path: inset(9% 7% 9% 7% round var(--r-card));
}
html.js .unmask.reveal.is-visible {
clip-path: inset(0 0 0 0 round var(--r-card));
}
/*
* 亚克力反光:指针所在处一块柔和高光 + 边缘描光,像灯光照在亚克力上。
* --mx / --my 由脚本写入;反光颜色由 --sheen / --sheen-edge 决定,随主题与材质变化。
*/
.spot {
position: relative;
isolation: isolate;
}
.spot::before,
.spot::after {
position: absolute;
inset: 0;
border-radius: inherit;
content: "";
opacity: 0;
pointer-events: none;
transition: opacity 0.4s ease;
}
.spot::before {
z-index: -1;
background: radial-gradient(
380px circle at var(--mx, 50%) var(--my, 50%),
var(--sheen),
transparent 55%
);
}
.spot::after {
z-index: 2;
padding: 1px;
background: radial-gradient(
240px circle at var(--mx, 50%) var(--my, 50%),
var(--sheen-edge),
transparent 62%
);
-webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
-webkit-mask-composite: xor;
mask: linear-gradient(#000 0 0) content-box exclude, linear-gradient(#000 0 0);
}
.spot:hover::before,
.spot:hover::after {
opacity: 1;
}
/* 可悬停的面板:轻微浮起 */
.lift {
transition: transform 0.5s var(--ease-out), box-shadow 0.35s ease;
}
.lift:hover {
transform: translateY(-4px);
}
/* 主题切换:View Transitions 以按钮为圆心扩散(site.js 驱动 clip-path) */
html.vt-theme::view-transition-old(root),
html.vt-theme::view-transition-new(root) {
animation: none;
mix-blend-mode: normal;
}
html.vt-theme::view-transition-new(root) {
z-index: 1;
}
/* --------------------------------------------------------------------------
* 19. 减弱动态效果:所有持续动画停止,内容以最终态直接呈现
* -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
html {
scroll-behavior: auto;
}
*,
*::before,
*::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
animation-delay: 0s !important;
transition-duration: 0.01ms !important;
transition-delay: 0s !important;
}
html.js .reveal,
html.js .hero-in {
opacity: 1;
translate: none;
filter: none;
}
html.js .unmask.reveal {
clip-path: none;
}
html.js .reveal [data-split] .ch {
opacity: 1;
filter: none;
transform: none;
}
.hero-inner,
.hero-devices {
opacity: 1;
transform: none;
}
.marquee-track {
width: auto;
flex-wrap: wrap;
justify-content: center;
}
.marquee ul[aria-hidden="true"] {
display: none;
}
.marquee ul {
flex-wrap: wrap;
justify-content: center;
}
.lift:hover {
transform: none;
}
}
/* --------------------------------------------------------------------------
* 20. 响应式
* -------------------------------------------------------------------------- */
@media (max-width: 960px) {
.nav-links {
display: none;
}
.mobile-menu-button {
display: inline-grid;
}
/* 移动端菜单:导航条下方再悬浮一块亚克力面板 */
.mobile-nav {
display: block;
width: var(--content);
margin: 8px auto 0;
padding: 8px;
border-radius: 18px;
background: var(--grain), var(--acrylic-fill);
box-shadow: var(--acrylic-shadow);
pointer-events: auto;
-webkit-backdrop-filter: var(--acrylic-blur);
backdrop-filter: var(--acrylic-blur);
}
.mobile-nav[hidden] {
display: none;
}
.mobile-nav a {
display: block;
padding: 12px 14px;
border-radius: var(--r-chip);
font-size: 1rem;
}
.mobile-nav a:active {
background: var(--line);
}
.split-layout {
grid-template-columns: 1fr;
}
.split-layout.reverse .feature-copy {
order: 1;
}
.split-layout.reverse .device-stage {
order: 2;
}
.personal-grid,
.service-paths,
.platform-grid {
grid-template-columns: 1fr;
}
.account-row {
grid-template-columns: 1fr;
}
.download-panel {
flex-direction: column;
align-items: flex-start;
}
.download-actions {
align-items: flex-start;
}
/* 滚动叙事:手机在上,当前一幕的文案在下方叠放切换 */
.story {
height: 480vh;
}
.story-layout {
align-content: center;
gap: 22px;
grid-template-columns: 1fr;
justify-items: center;
}
.story-device {
order: -1;
}
.iphone {
--w: min(260px, calc((100svh - 360px) * 0.489));
}
.story-acts {
position: relative;
display: block;
width: 100%;
max-width: 520px;
height: 196px;
}
.story-act {
position: absolute;
inset: 0;
padding: 16px 20px;
opacity: 0;
pointer-events: none;
transform: translateY(14px);
}
.story-act.is-active {
opacity: 1;
pointer-events: auto;
transform: none;
}
.act-body > p:not(.act-kicker) {
font-size: 0.92rem;
}
.scroll-cue {
display: none;
}
}
@media (max-width: 600px) {
:root {
--content: calc(100vw - 32px);
}
.hero {
padding-top: 112px;
}
.hero-mark {
width: 80px;
height: 80px;
}
/* 窄屏:商店徽章独占一行,两枚键帽平分下一行,避免二加一的参差 */
.hero-actions {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 12px;
}
.hero-actions .store-badge {
grid-column: 1 / -1;
justify-self: center;
}
.hero-actions .keycap {
padding-inline: 12px;
}
.voice-capsule {
bottom: 12%;
gap: 10px;
padding: 6px 14px 6px 6px;
border-radius: 14px;
}
.capsule-mic {
width: 62px;
height: 28px;
}
.capsule-body {
min-width: min(260px, 70vw);
font-size: 0.84rem;
}
.account-row .quiet-list {
grid-template-columns: 1fr;
}
.privacy-proof {
flex-direction: column;
align-items: flex-start;
}
.faq-list {
padding: 4px 20px;
}
.footer-inner {
flex-direction: column;
align-items: flex-start;
}
}
/* 无 JavaScript:滚动叙事退化为静态展示,不保留 520vh 的空白滚动距离 */
html.no-js .story {
height: auto;
}
html.no-js .story-sticky {
position: static;
height: auto;
padding: 48px 0 0;
}
html.no-js .story-act {
position: static;
opacity: 1;
transform: none;
}
html.no-js .story-acts {
height: auto;
}