@@ -85,24 +85,49 @@ const providerChips = ['302.AI (97)', 'Abacus (65)', 'abliteration.ai (1)', 'AIH
8585
8686// Logos(信赖墙)— 我们没有真实合作伙伴,改成"原生支持的协议名"
8787const protocols = [' OpenAI' , ' Anthropic' , ' Gemini' , ' Ollama' , ' DeepSeek' , ' OpenAI-Response' ];
88+
89+ // Hero 装饰性均衡器条 — 纯视觉,数值确定性生成(避免 hydration 不一致)
90+ const eqColors = [' var(--grad-1)' , ' var(--grad-2)' , ' var(--grad-3)' , ' var(--grad-4)' ];
91+ function makeEqBars(count : number , seed : number ) {
92+ return Array .from ({ length: count }, (_ , i ) => {
93+ const h = 22 + Math .round (Math .abs (Math .sin (i * 0.7 + seed )) * 70 );
94+ const d = (i * 0.09 + seed * 0.13 ) % 1.6 ;
95+ const c = eqColors [(i + seed ) % eqColors .length ];
96+ return { h , d: d .toFixed (2 ), c };
97+ });
98+ }
99+ const eqLeft = makeEqBars (16 , 0 );
100+ const eqRight = makeEqBars (16 , 2 );
88101---
89102<LandingLayout >
90103 <!-- ============== HERO ============== -->
91104 <section class =" hero" >
105+ <div class =" hero-eq" aria-hidden =" true" >
106+ <div class =" col left" >
107+ { eqLeft .map ((b ) => (
108+ <span class = " bar" style = { ` --bar-h:${b .h }%; --bar-d:${b .d }s; --bar-c:${b .c }; ` } ></span >
109+ ))}
110+ </div >
111+ <div class =" col right" >
112+ { eqRight .map ((b ) => (
113+ <span class = " bar" style = { ` --bar-h:${b .h }%; --bar-d:${b .d }s; --bar-c:${b .c }; ` } ></span >
114+ ))}
115+ </div >
116+ </div >
92117 <div class =" wrap hero-grid" >
93- <div class =" fade-in" >
94- <span class =" hero-badge" ><span class =" pulse-dot" ></span >
118+ <div class =" fade-in" data-stagger >
119+ <span class =" hero-badge stagger-item " ><span class =" pulse-dot" ></span >
95120 <span data-lang =" en" >{ t .hero .badge .en } </span ><span data-lang =" zh" >{ t .hero .badge .zh } </span ><span data-lang =" ja" >{ t .hero .badge .ja } </span >
96121 </span >
97- <h1 >
122+ <h1 class = " stagger-item " >
98123 <span data-lang =" en" >{ t .hero .h1a .en } <br /><span class =" em" >{ t .hero .h1b .en } </span ></span >
99124 <span data-lang =" zh" >{ t .hero .h1a .zh } <br /><span class =" em" >{ t .hero .h1b .zh } </span ></span >
100125 <span data-lang =" ja" >{ t .hero .h1a .ja } <br /><span class =" em" >{ t .hero .h1b .ja } </span ></span >
101126 </h1 >
102- <p class =" lede" data-lang =" en" >{ t .hero .lede .en } </p >
103- <p class =" lede" data-lang =" zh" >{ t .hero .lede .zh } </p >
104- <p class =" lede" data-lang =" ja" >{ t .hero .lede .ja } </p >
105- <div class =" hero-cta" >
127+ <p class =" lede stagger-item " data-lang =" en" >{ t .hero .lede .en } </p >
128+ <p class =" lede stagger-item " data-lang =" zh" >{ t .hero .lede .zh } </p >
129+ <p class =" lede stagger-item " data-lang =" ja" >{ t .hero .lede .ja } </p >
130+ <div class =" hero-cta stagger-item " >
106131 <a class =" btn" href =" #install" >
107132 <span data-lang =" en" >{ t .hero .primary .en } </span ><span data-lang =" zh" >{ t .hero .primary .zh } </span ><span data-lang =" ja" >{ t .hero .primary .ja } </span >
108133 <span class =" arr" >→</span >
@@ -147,33 +172,7 @@ const protocols = ['OpenAI', 'Anthropic', 'Gemini', 'Ollama', 'DeepSeek', 'OpenA
147172 </div >
148173 </div >
149174 <div class =" app-body" >
150- <!-- 左侧:快捷键提示卡 + 状态栏 -->
151- <div class =" hero-side" >
152- <div class =" hero-hint" >
153- <div class =" hh-title" >
154- <svg class =" ico" viewBox =" 0 0 16 16" fill =" none" stroke =" currentColor" stroke-width =" 1.6" ><path d =" M3 11l4-4 4 4M3 7l4-4 4 4" /></svg >
155- <span data-lang =" en" >New terminal session</span ><span data-lang =" zh" >新建终端会话</span ><span data-lang =" ja" >新しいセッション</span >
156- </div >
157- <div class =" hh-row" >
158- <span class =" kbds" ><span class =" kbd" >ctrl</span ><span class =" kbd" >shift</span ><span class =" kbd" >↩</span ></span >
159- <span data-lang =" en" >New Agent chat</span ><span data-lang =" zh" >新 Agent 对话</span ><span data-lang =" ja" >新しい Agent 会話</span >
160- </div >
161- <div class =" hh-row" >
162- <span class =" kbds" ><span class =" kbd" >↑</span ></span >
163- <span data-lang =" en" >History</span ><span data-lang =" zh" >历史记录</span ><span data-lang =" ja" >履歴</span >
164- </div >
165- <div class =" hh-row" >
166- <span class =" kbds" ><span class =" kbd" >⌘</span ><span class =" kbd" >K</span ></span >
167- <span data-lang =" en" >Command palette</span ><span data-lang =" zh" >命令面板</span ><span data-lang =" ja" >コマンドパレット</span >
168- </div >
169- </div >
170- <div class =" hero-status" >
171- <span class =" ok" >anthropic / claude-4-7</span >
172- <span >local · no telemetry</span >
173- </div >
174- </div >
175-
176- <!-- 右侧:终端输出 + 可执行输入 -->
175+ <!-- 单栏 Block 时间线:终端输出 + AI 对话 + 可交互输入 -->
177176 <div class =" hero-main" >
178177 <div class =" term-stage" ></div >
179178 <div class =" term-input live" >
@@ -216,19 +215,19 @@ const protocols = ['OpenAI', 'Anthropic', 'Gemini', 'Ollama', 'DeepSeek', 'OpenA
216215 </section >
217216
218217 <!-- ============== LOGOS / PROTOCOLS ============== -->
219- <div class =" logos fade-in" >
220- <p class =" logos-title" >
218+ <div class =" logos fade-in" data-stagger >
219+ <p class =" logos-title stagger-item " >
221220 <span data-lang =" en" >{ t .logos .title .en } </span ><span data-lang =" zh" >{ t .logos .title .zh } </span ><span data-lang =" ja" >{ t .logos .title .ja } </span >
222221 </p >
223222 <div class =" logos-track" >
224- { protocols .map ((p ) => <span class = " item" >{ p } </span >)}
223+ { protocols .map ((p ) => <span class = " item stagger-item " >{ p } </span >)}
225224 </div >
226225 </div >
227226
228227 <!-- ============== FEAT 1: 终端 ============== -->
229228 <section class =" section" id =" how" >
230229 <div class =" wrap" >
231- <article class =" feat-card fade-in" >
230+ <article class =" feat-card fade-in slide-l " >
232231 <div class =" feat-text" >
233232 <div class =" feat-eyebrow" >
234233 <span data-lang =" en" >{ t .feat1 .eyebrow .en } </span ><span data-lang =" zh" >{ t .feat1 .eyebrow .zh } </span ><span data-lang =" ja" >{ t .feat1 .eyebrow .ja } </span >
@@ -281,7 +280,7 @@ const protocols = ['OpenAI', 'Anthropic', 'Gemini', 'Ollama', 'DeepSeek', 'OpenA
281280 <!-- ============== FEAT 2: 服务商(reverse 布局) ============== -->
282281 <section class =" section" id =" adapt" >
283282 <div class =" wrap" >
284- <article class =" feat-card reverse fade-in" >
283+ <article class =" feat-card reverse fade-in slide-r " >
285284 <div class =" feat-text" >
286285 <div class =" feat-eyebrow" >
287286 <span data-lang =" en" >{ t .feat2 .eyebrow .en } </span ><span data-lang =" zh" >{ t .feat2 .eyebrow .zh } </span ><span data-lang =" ja" >{ t .feat2 .eyebrow .ja } </span >
@@ -391,7 +390,7 @@ const protocols = ['OpenAI', 'Anthropic', 'Gemini', 'Ollama', 'DeepSeek', 'OpenA
391390 <!-- ============== FEAT 3: 本地化 ============== -->
392391 <section class =" section" id =" privacy" >
393392 <div class =" wrap" >
394- <article class =" feat-card fade-in" >
393+ <article class =" feat-card fade-in slide-l " >
395394 <div class =" feat-text" >
396395 <div class =" feat-eyebrow" >
397396 <span data-lang =" en" >{ t .feat3 .eyebrow .en } </span ><span data-lang =" zh" >{ t .feat3 .eyebrow .zh } </span ><span data-lang =" ja" >{ t .feat3 .eyebrow .ja } </span >
@@ -459,7 +458,7 @@ const protocols = ['OpenAI', 'Anthropic', 'Gemini', 'Ollama', 'DeepSeek', 'OpenA
459458 </section >
460459
461460 <!-- ============== QUOTE(单条) ============== -->
462- <section class =" quote fade-in" >
461+ <section class =" quote fade-in scale-in " >
463462 <div class =" wrap" >
464463 <blockquote data-lang =" en" >{ t .quote .text .en } </blockquote >
465464 <blockquote data-lang =" zh" >{ t .quote .text .zh } </blockquote >
@@ -566,24 +565,47 @@ git clone https://github.com/zerx-lab/zap.git zap
566565
567566 // 初始动画行(页面刚加载时) — 按当前 locale 渲染
568567 // 命令本身保留英文(真实 shell 也是英文),只本地化人类语言部分
568+ // 叙事:构建失败 → AI 用 block 上下文(cwd/exit code)诊断并给出修复建议
569+ // 呼应 feat1 文案 "Every Block — cwd, env, exit code — feeds an AI conversation"
569570 const initLinesByLocale: Record<'en' | 'zh' | 'ja', string[]> = {
570571 en: [
571- `<span class="p">$</span> npm run build`,
572- `<span class="dim">› vite v5.4 · production</span>`,
573- `<span class="dim">› 248 modules transformed</span>`,
574- `<span class="ok">✓ built in 1.24s</span>`,
572+ `<span class="p">$</span> cargo build --release`,
573+ `<span class="dim"> Compiling zap v0.1.0</span>`,
574+ `<span class="err">error[E0433]: failed to resolve: use of undeclared crate \`openssl\`</span>`,
575+ `<span class="err"> --> src/tls.rs:4:5</span>`,
576+ `<div class="stage-turn">
577+ <div class="st-chip">block · cwd ~/zap · exit 101</div>
578+ <div class="st-prompt">▌ Why did this fail?</div>
579+ <div class="st-think">Reading block context <span class="dots"><span></span><span></span><span></span></span></div>
580+ <div class="st-answer"><code>openssl</code> isn't in Cargo.toml. Run <code>cargo add openssl --features vendored</code>, then rebuild.</div>
581+ <div class="st-meta"><span class="ok">anthropic / claude-opus-4-7</span><span>local · no telemetry</span></div>
582+ </div>`,
575583 ],
576584 zh: [
577- `<span class="p">$</span> npm run build`,
578- `<span class="dim">› vite v5.4 · 生产构建</span>`,
579- `<span class="dim">› 已转换 248 个模块</span>`,
580- `<span class="ok">✓ 1.24s 内构建完成</span>`,
585+ `<span class="p">$</span> cargo build --release`,
586+ `<span class="dim"> 正在编译 zap v0.1.0</span>`,
587+ `<span class="err">error[E0433]: 无法解析:未声明的 crate \`openssl\`</span>`,
588+ `<span class="err"> --> src/tls.rs:4:5</span>`,
589+ `<div class="stage-turn">
590+ <div class="st-chip">block · cwd ~/zap · exit 101</div>
591+ <div class="st-prompt">▌ 为什么会失败?</div>
592+ <div class="st-think">正在读取 block 上下文 <span class="dots"><span></span><span></span><span></span></span></div>
593+ <div class="st-answer">Cargo.toml 里没有 <code>openssl</code>。运行 <code>cargo add openssl --features vendored</code> 后重新构建即可。</div>
594+ <div class="st-meta"><span class="ok">anthropic / claude-opus-4-7</span><span>本地 · 无遥测</span></div>
595+ </div>`,
581596 ],
582597 ja: [
583- `<span class="p">$</span> npm run build`,
584- `<span class="dim">› vite v5.4 · 本番ビルド</span>`,
585- `<span class="dim">› 248 モジュールを変換</span>`,
586- `<span class="ok">✓ 1.24 秒でビルド完了</span>`,
598+ `<span class="p">$</span> cargo build --release`,
599+ `<span class="dim"> zap v0.1.0 をコンパイル中</span>`,
600+ `<span class="err">error[E0433]: 解決できません: 宣言されていないクレート \`openssl\`</span>`,
601+ `<span class="err"> --> src/tls.rs:4:5</span>`,
602+ `<div class="stage-turn">
603+ <div class="st-chip">block · cwd ~/zap · exit 101</div>
604+ <div class="st-prompt">▌ なぜ失敗したの?</div>
605+ <div class="st-think">block コンテキストを読み取り中 <span class="dots"><span></span><span></span><span></span></span></div>
606+ <div class="st-answer">Cargo.toml に <code>openssl</code> がありません。<code>cargo add openssl --features vendored</code> を実行して再ビルドしてください。</div>
607+ <div class="st-meta"><span class="ok">anthropic / claude-opus-4-7</span><span>ローカル · テレメトリなし</span></div>
608+ </div>`,
587609 ],
588610 };
589611 function renderInitLines() {
@@ -871,3 +893,36 @@ git clone https://github.com/zerx-lab/zap.git zap
871893 localeObserver.observe(document.body, { attributes: true, attributeFilter: ['data-locale'] });
872894 })();
873895</script >
896+
897+ <script >
898+ // Hero 装饰性均衡器条 — 轻量视差(仅位移,GPU 合成,不触发 layout)
899+ (function () {
900+ const eq = document.querySelector<HTMLElement>('.hero-eq');
901+ if (!eq) return;
902+ const reduceMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
903+ if (reduceMotion) return;
904+ const cols = Array.from(eq.querySelectorAll<HTMLElement>('.col'));
905+ let ticking = false;
906+ function apply() {
907+ const y = window.scrollY;
908+ const heroH = (eq.closest('.hero') as HTMLElement | null)?.offsetHeight || 800;
909+ const progress = Math.min(y / heroH, 1);
910+ cols.forEach((col, i) => {
911+ const dir = i % 2 === 0 ? 1 : -1;
912+ col.style.transform = `translateY(${progress * 40 * dir}px)`;
913+ });
914+ ticking = false;
915+ }
916+ document.addEventListener(
917+ 'scroll',
918+ () => {
919+ if (!ticking) {
920+ requestAnimationFrame(apply);
921+ ticking = true;
922+ }
923+ },
924+ { passive: true },
925+ );
926+ apply();
927+ })();
928+ </script >
0 commit comments