Files
dudu/web/index.html
T
wangjia 3e292ec1e0
ci / server (push) Failing after 11s
ci / design-system (push) Failing after 11s
feat(web): 官网扩充改版——特性 6 项 + 场景/隐私/FAQ 三大板块
在既有克制视觉语言(单一蓝 · 无渐变 · 1px 边线分隔 · Outfit 数字/西文)
内做精并补足信息量,所有色值走 tokens,check-code 闸通过:

- Hero 加资质 eyebrow(五端一套账号·时长永不过期)
- 指标带 3→4 项(首字延迟 / 5 端 / 3 分钟每天 / 时长不过期)
- 特性 3→6(新增 上滑取消 / 浮层不抢焦点 / 中英混说)
- 新增「使用场景」4 卡(写作·消息·代码·会议,各带你说→上屏示例 + 3× 提速角标)
- 新增「隐私与信任」深色带 4 点(只按住时录音 / 音频用完即弃 / 只往光标写 / 透明计费)
- 平台区改信息卡片(桌面/手机/平板,各附一句能力说明)
- 定价卡加权益清单 + 热门档强调
- 新增「常见问题」8 条 details 手风琴(联网/隐私/准确率/跨端时长/兼容/额度/对比/方言)
- 页脚扩为四栏(产品·购买·支持 + 品牌介绍 + 运营主体)
- 双主题 + 移动窄屏截图验收通过;reduced-motion / focus-visible 已覆盖

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 21:01:58 +08:00

931 lines
50 KiB
HTML
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.
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>dudu — 按住说话,文字上屏</title>
<meta name="description" content="dudu 语音输入法:大模型识别,流式实时上屏。Mac / Windows / iPhone / iPad / Android 五端一套账号。每天免费 3 分钟,时长永不过期。">
<link rel="stylesheet" href="tokens.css">
<style>
/* ────────────────────────────────────────────────────────────────
令牌层由 tokens.css 提供(design/tokens/ 经 export-tokens.mjs 生成,
含 Outfit 字体内嵌,禁外部 CDN)。本页只允许 var(--*),禁字面色值
check-code 闸拦截)。深色板块用 data-theme="dark" 复用 dark 令牌。
品牌硬规则:单一品牌蓝 · 无渐变 · 无 emoji · 波形动画仅录音中
──────────────────────────────────────────────────────────────── */
:root {
/* 页面级别名 → 设计系统 token(仅别名,禁止写字面色值) */
--bg: var(--bg-app);
--card: var(--surface-card);
--sans: var(--font-sans);
--latin: var(--font-sans);
--mono: var(--font-mono);
}
* { box-sizing: border-box; margin: 0; }
html { scroll-behavior: smooth; }
body {
font-family: var(--sans);
background: var(--bg);
color: var(--text-1);
line-height: 1.6;
-webkit-font-smoothing: antialiased;
}
::selection { background: var(--accent-soft); color: var(--accent-text); }
a { color: inherit; text-decoration: none; }
.latin { font-family: var(--latin); }
/* ── 结构网格:1px 边线是主要分隔语言 ── */
.frame { max-width: 1120px; margin: 0 auto; padding: 0 32px; }
@media (max-width: 720px) { .frame { padding: 0 20px; } }
/* ── 导航 ── */
nav {
position: sticky; top: 0; z-index: 50;
background: color-mix(in srgb, var(--bg) 88%, transparent);
backdrop-filter: blur(14px); -webkit-backdrop-filter: blur(14px);
border-bottom: 1px solid var(--border-1);
}
.nav-inner {
display: flex; align-items: center; justify-content: space-between;
height: 60px;
}
.brand { display: inline-flex; align-items: center; gap: 10px; color: var(--text-1); }
.brand svg { color: var(--accent); }
.brand .name { font-family: var(--latin); font-weight: 600; font-size: 19px; letter-spacing: .02em; }
.nav-links { display: flex; align-items: center; gap: 26px; font-size: 14px; color: var(--text-2); }
.nav-links a:hover { color: var(--text-1); }
.nav-links .only-wide { display: inline; }
@media (max-width: 640px) { .nav-links .only-wide { display: none; } }
.btn {
display: inline-flex; align-items: center; justify-content: center; gap: 8px;
border: 1px solid transparent; border-radius: 6px; cursor: pointer;
font-family: var(--sans); font-weight: 500; white-space: nowrap;
transition: background 120ms var(--ease-out), border-color 120ms var(--ease-out);
}
.btn-sm { height: 32px; padding: 0 14px; font-size: 13px; }
.btn-lg { height: 48px; padding: 0 26px; font-size: 16px; border-radius: 999px; }
.btn-primary { background: var(--accent); color: var(--text-on-accent); }
.btn-primary:hover { background: var(--accent-hover); }
.btn-primary:active { background: var(--accent-press); }
.btn-secondary { background: var(--card); border-color: var(--border-2); color: var(--text-1); }
.btn-secondary:hover { background: var(--surface-2); }
.btn-ghost { background: transparent; color: var(--accent-text); }
.btn-ghost:hover { background: var(--accent-soft); }
:focus-visible { outline: none; box-shadow: var(--focus-ring); border-radius: 6px; }
/* ── Hero ── */
.hero { border-bottom: 1px solid var(--border-1); overflow: hidden; }
.hero-grid {
display: grid; grid-template-columns: 6fr 5fr; gap: 48px;
padding: 92px 0 104px; align-items: center;
}
@media (max-width: 920px) {
.hero-grid { grid-template-columns: 1fr; padding: 60px 0 68px; gap: 52px; }
}
.hero .eyebrow {
display: inline-flex; align-items: center; gap: 8px;
font-size: 13px; color: var(--text-2); font-weight: 500;
padding: 5px 13px 5px 10px; border: 1px solid var(--border-1); border-radius: 999px;
background: var(--card); margin-bottom: 22px;
}
.hero .eyebrow .pip { width: 7px; height: 7px; border-radius: 50%; background: var(--positive); flex: none; }
.hero h1 {
font-size: clamp(48px, 7.2vw, 84px);
line-height: 1.12; letter-spacing: -0.015em;
font-weight: 700;
}
.hero h1 .accent-word { color: var(--accent); }
.hero .sub {
margin-top: 22px; font-size: 18px; color: var(--text-2);
display: flex; align-items: center; flex-wrap: wrap; gap: 10px;
}
.hero .sub .dot { color: var(--text-3); }
.hero-cta { margin-top: 36px; display: flex; align-items: center; gap: 18px; flex-wrap: wrap; }
.hero-note { font-size: 13px; color: var(--text-3); }
.hero-note .num { font-family: var(--latin); }
/* ── 演示剧场 ── */
.stage { position: relative; }
.demo-window {
background: var(--card); border: 1px solid var(--border-1);
border-radius: 14px; box-shadow: var(--shadow-window); overflow: hidden;
}
.demo-titlebar {
display: flex; align-items: center; gap: 7px;
padding: 11px 14px; border-bottom: 1px solid var(--border-1); background: var(--surface-2);
}
.demo-titlebar i { width: 11px; height: 11px; border-radius: 50%; background: var(--border-2); }
.demo-titlebar span { margin-left: 8px; font-size: 12px; color: var(--text-3); }
.demo-doc { padding: 22px 24px 30px; min-height: 150px; font-size: 16px; line-height: 1.9; }
.demo-doc .placeholder { color: var(--text-3); }
.caret {
display: inline-block; width: 2px; height: 1.15em; vertical-align: -0.18em;
background: var(--accent); animation: blink 1.1s steps(1) infinite;
}
@keyframes blink { 50% { opacity: 0; } }
.overlay {
position: absolute; left: 50%; transform: translateX(-50%);
bottom: -34px; width: min(340px, 86%);
background: var(--overlay-bg); color: var(--overlay-text);
border-radius: 14px; padding: 14px 18px;
box-shadow: var(--shadow-overlay);
backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px);
opacity: 0; translate: 0 4px;
transition: opacity 200ms var(--ease-out), translate 200ms var(--ease-out);
pointer-events: none;
}
.overlay.show { opacity: 1; translate: 0 0; }
.wave { display: inline-flex; align-items: center; gap: 3px; height: 24px; color: var(--overlay-wave); }
.wave i { display: block; width: 3px; border-radius: 2px; background: currentColor; }
.recording .wave i { animation: wavebounce 0.9s cubic-bezier(0.45, 0, 0.2, 1) infinite alternate; }
@keyframes wavebounce { from { transform: scaleY(0.35); } to { transform: scaleY(1); } }
.overlay .ovl-status {
display: flex; align-items: center; gap: 8px;
color: var(--overlay-text-2); font-size: 15px; margin-top: 8px;
}
.overlay .ovl-text { font-size: 15px; line-height: 1.6; margin-top: 8px; min-height: 24px; }
.overlay .ovl-text .partial { color: var(--overlay-text-2); }
.overlay .ovl-hint { font-size: 11px; color: var(--overlay-text-3); margin-top: 8px; text-align: right; }
.micbar {
margin-top: 64px; width: 100%; height: 56px; border: none; cursor: pointer;
border-radius: 999px; background: var(--accent); color: var(--text-on-accent);
font-family: var(--sans); font-size: 16px; font-weight: 600;
display: inline-flex; align-items: center; justify-content: center; gap: 9px;
user-select: none; -webkit-user-select: none; touch-action: none;
transition: background 120ms var(--ease-out);
}
.micbar:active, .micbar.recording { background: var(--positive); }
.micbar:hover:not(.recording) { background: var(--accent-hover); }
.stage-tip { margin-top: 12px; text-align: center; font-size: 13px; color: var(--text-3); }
kbd {
font-family: var(--mono); font-size: 12px; color: var(--text-2);
background: var(--surface-2); border: 1px solid var(--border-2); border-bottom-width: 2px;
border-radius: 4px; padding: 1px 7px;
}
/* ── 指标带(墨色) ── */
.metrics { background: var(--gray-950); color: var(--text-1); border-bottom: 1px solid var(--border-1); }
.metrics-grid { display: grid; grid-template-columns: repeat(4, 1fr); }
.metric {
padding: 44px 24px; text-align: center;
border-left: 1px solid var(--border-1);
}
.metric:first-child { border-left: none; }
.metric .num {
font-family: var(--latin); font-weight: 700;
font-size: clamp(30px, 3.8vw, 46px); line-height: 1.1;
}
.metric .num small { font-size: 0.45em; font-weight: 600; color: var(--text-2); margin-left: 2px; }
.metric .label { margin-top: 8px; font-size: 13.5px; color: var(--text-2); }
@media (max-width: 820px) {
.metrics-grid { grid-template-columns: repeat(2, 1fr); }
.metric:nth-child(-n+2) { border-top: none; }
.metric:nth-child(2n+1) { border-left: none; }
.metric:nth-child(n+3) { border-top: 1px solid var(--border-1); }
}
@media (max-width: 480px) {
.metrics-grid { grid-template-columns: 1fr; }
.metric { border-left: none; border-top: 1px solid var(--border-1); padding: 28px 20px; }
.metric:first-child { border-top: none; }
}
/* ── 章节通用 ── */
section { border-bottom: 1px solid var(--border-1); }
.section-head { padding: 84px 0 0; }
.section-head.center { text-align: center; }
.section-head.center h2 { margin-left: auto; margin-right: auto; }
.kicker {
font-size: 13px; font-weight: 600; color: var(--accent-text);
letter-spacing: .12em;
}
.section-head h2 {
margin-top: 12px; font-size: clamp(30px, 4vw, 44px);
line-height: 1.25; letter-spacing: -0.01em; font-weight: 700; max-width: 18em;
}
.section-head .lead {
margin-top: 16px; font-size: 16px; color: var(--text-2); max-width: 34em;
}
.section-head.center .lead { margin-left: auto; margin-right: auto; }
.reveal { opacity: 0; translate: 0 14px; transition: opacity 320ms var(--ease-out), translate 320ms var(--ease-out); }
.reveal.in { opacity: 1; translate: 0 0; }
@media (prefers-reduced-motion: reduce) {
.reveal { opacity: 1; translate: 0 0; transition: none; }
html { scroll-behavior: auto; }
}
/* ── 特性(6 格,两行内嵌分隔线) ── */
.features {
display: grid; grid-template-columns: repeat(3, 1fr);
margin: 52px 0 92px; border: 1px solid var(--border-1); border-radius: 14px;
background: var(--card); overflow: hidden;
}
.feature { padding: 32px 28px 34px; border-left: 1px solid var(--border-1); border-top: 1px solid var(--border-1); }
.feature:nth-child(-n+3) { border-top: none; }
.feature:nth-child(3n+1) { border-left: none; }
.feature .icon {
width: 44px; height: 44px; border-radius: 10px;
background: var(--accent-soft); color: var(--accent-text);
display: inline-flex; align-items: center; justify-content: center;
}
.feature h3 { margin-top: 18px; font-size: 18px; font-weight: 600; }
.feature p { margin-top: 8px; font-size: 14.5px; color: var(--text-2); }
@media (max-width: 820px) {
.features { grid-template-columns: 1fr; }
.feature { border-left: none; border-top: 1px solid var(--border-1); }
.feature:first-child { border-top: none; }
}
/* ── 场景 ── */
.scene-head { display: flex; align-items: flex-end; justify-content: space-between; gap: 24px; flex-wrap: wrap; }
.speed-badge {
flex: none; margin-bottom: 4px; padding: 12px 20px;
border: 1px solid var(--border-1); border-radius: 14px; background: var(--card);
box-shadow: var(--shadow-card); text-align: center;
}
.speed-badge .big { font-family: var(--latin); font-weight: 700; font-size: 30px; color: var(--accent-text); line-height: 1; }
.speed-badge .cap { margin-top: 4px; font-size: 12px; color: var(--text-2); }
.scenes { display: grid; grid-template-columns: repeat(2, 1fr); gap: 18px; margin: 48px 0 92px; }
@media (max-width: 720px) { .scenes { grid-template-columns: 1fr; } }
.scene {
border: 1px solid var(--border-1); border-radius: 14px; background: var(--card);
padding: 26px 26px 24px; box-shadow: var(--shadow-card);
display: flex; flex-direction: column;
}
.scene .top { display: flex; align-items: center; gap: 12px; }
.scene .sicon {
width: 38px; height: 38px; border-radius: 9px; flex: none;
background: var(--accent-soft); color: var(--accent-text);
display: inline-flex; align-items: center; justify-content: center;
}
.scene h3 { font-size: 17px; font-weight: 600; }
.scene p { margin-top: 12px; font-size: 14px; color: var(--text-2); }
.scene .eg {
margin-top: 18px; border-top: 1px dashed var(--border-2); padding-top: 16px;
font-size: 13.5px;
}
.scene .eg .say {
display: inline-flex; align-items: center; gap: 6px;
color: var(--text-3); font-size: 12px; margin-bottom: 6px;
}
.scene .eg .quote { color: var(--text-1); }
.scene .eg .quote b { color: var(--accent-text); font-weight: 600; }
/* ── 隐私与信任(墨色带) ── */
.trust { background: var(--gray-950); color: var(--text-1); }
.trust .section-head { padding-top: 84px; }
.trust .kicker { color: var(--accent-text); }
.priv-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 16px; margin: 48px 0 88px; }
@media (max-width: 900px) { .priv-grid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 520px) { .priv-grid { grid-template-columns: 1fr; } }
.priv {
border: 1px solid var(--border-1); border-radius: 14px; background: var(--surface-card);
padding: 24px 22px 26px;
}
.priv .picon { color: var(--accent-text); }
.priv h3 { margin-top: 16px; font-size: 16px; font-weight: 600; }
.priv p { margin-top: 8px; font-size: 13.5px; color: var(--text-2); line-height: 1.6; }
/* ── 三步 ── */
.steps { display: grid; grid-template-columns: repeat(3, 1fr); gap: 32px; margin: 60px 0 92px; }
.step .no {
font-family: var(--latin); font-weight: 700; font-size: 66px; line-height: 1;
color: var(--surface-3);
}
.step h3 { margin-top: 12px; font-size: 18px; font-weight: 600; display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.step p { margin-top: 6px; font-size: 14.5px; color: var(--text-2); max-width: 26em; }
@media (max-width: 820px) { .steps { grid-template-columns: 1fr; gap: 40px; } }
/* ── 平台(卡片) ── */
.plat-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 18px; margin: 48px 0 92px; }
@media (max-width: 820px) { .plat-grid { grid-template-columns: 1fr; } }
.plat {
border: 1px solid var(--border-1); border-radius: 14px; background: var(--card);
padding: 26px 26px 24px; box-shadow: var(--shadow-card);
}
.plat .os { display: inline-flex; align-items: center; gap: 12px; color: var(--text-2); }
.plat .os svg { color: var(--text-2); }
.plat h3 { margin-top: 16px; font-size: 17px; font-weight: 600; color: var(--text-1); display: flex; align-items: center; gap: 8px; }
.plat h3 .form { font-size: 13px; font-weight: 500; color: var(--text-3); }
.plat p { margin-top: 8px; font-size: 14px; color: var(--text-2); }
.plat .soon {
display: inline-block; margin-top: 14px; font-size: 12px; font-weight: 600;
color: var(--accent-text); background: var(--accent-soft);
padding: 2px 10px; border-radius: 999px;
}
/* ── 定价 ── */
.pricing { display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; margin: 52px 0 24px; align-items: stretch; }
.price-card {
background: var(--card); border: 1px solid var(--border-1); border-radius: 14px;
padding: 30px 28px 28px; display: flex; flex-direction: column; box-shadow: var(--shadow-card);
position: relative;
}
.price-card.hot { border: 1.5px solid var(--accent); box-shadow: var(--shadow-window); }
.price-card .tag {
position: absolute; top: -11px; left: 24px;
font-size: 12px; font-weight: 600; padding: 2px 12px; border-radius: 999px;
background: var(--warning-soft); color: var(--warning);
}
.price-card.hot .tag { background: var(--accent); color: var(--text-on-accent); }
.price-card .minutes { font-size: 17px; font-weight: 600; }
.price-card .minutes .num { font-family: var(--latin); font-size: 22px; }
.price-card .price { margin-top: 12px; font-family: var(--latin); font-weight: 700; font-size: 54px; line-height: 1; }
.price-card .price .cur { font-size: 24px; font-weight: 600; vertical-align: 14px; margin-right: 2px; }
.price-card .unit { margin-top: 8px; font-size: 13px; color: var(--text-3); }
.price-card .perks { margin-top: 20px; display: flex; flex-direction: column; gap: 9px; }
.price-card .perks li { list-style: none; display: flex; align-items: flex-start; gap: 8px; font-size: 13.5px; color: var(--text-2); }
.price-card .perks svg { color: var(--positive); flex: none; margin-top: 2px; }
.price-card .btn { margin-top: 24px; width: 100%; }
.pricing-note { text-align: center; font-size: 14px; color: var(--text-2); padding-bottom: 92px; }
.pricing-note .num { font-family: var(--latin); }
@media (max-width: 820px) { .pricing { grid-template-columns: 1fr; } }
/* ── 常见问题 ── */
.faq { max-width: 820px; margin: 44px auto 92px; border: 1px solid var(--border-1); border-radius: 14px; background: var(--card); overflow: hidden; }
.faq details { border-top: 1px solid var(--border-1); }
.faq details:first-child { border-top: none; }
.faq summary {
list-style: none; cursor: pointer; padding: 20px 24px;
display: flex; align-items: center; justify-content: space-between; gap: 16px;
font-size: 16px; font-weight: 500; color: var(--text-1);
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary .chev { color: var(--text-3); transition: transform 200ms var(--ease-out); flex: none; }
.faq details[open] summary .chev { transform: rotate(180deg); }
.faq details[open] summary { color: var(--accent-text); }
.faq .answer { padding: 0 24px 22px; font-size: 14.5px; color: var(--text-2); line-height: 1.7; max-width: 60ch; }
/* ── 尾部 CTA(墨色) ── */
.cta { background: var(--gray-950); color: var(--text-1); border-bottom: 1px solid var(--border-1); }
.cta-inner { padding: 104px 0; text-align: center; }
.cta .logo-big { color: var(--accent); }
.cta h2 { margin-top: 26px; font-size: clamp(34px, 5vw, 56px); font-weight: 700; letter-spacing: -0.01em; }
.cta p { margin-top: 14px; color: var(--text-2); font-size: 16px; }
.cta .cta-btns { margin-top: 36px; display: flex; gap: 14px; justify-content: center; flex-wrap: wrap; }
.cta .microcopy { margin-top: 20px; font-size: 13px; color: var(--text-3); }
.cta .microcopy .num { font-family: var(--latin); }
/* ── 页脚 ── */
footer { background: var(--gray-950); color: var(--text-2); }
.footer-top {
display: grid; grid-template-columns: 2fr 1fr 1fr 1fr; gap: 32px;
padding: 56px 0 40px; border-bottom: 1px solid var(--border-1);
}
@media (max-width: 720px) { .footer-top { grid-template-columns: 1fr 1fr; gap: 32px 20px; } }
.footer-brand .brand { color: var(--text-1); }
.footer-brand .brand svg { color: var(--accent); }
.footer-brand p { margin-top: 14px; font-size: 13.5px; color: var(--text-2); max-width: 24em; line-height: 1.6; }
.footer-col h4 { font-size: 13px; font-weight: 600; color: var(--text-1); letter-spacing: .04em; }
.footer-col a { display: block; margin-top: 12px; font-size: 13.5px; color: var(--text-2); }
.footer-col a:hover { color: var(--text-1); }
.footer-bottom {
display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 12px;
padding: 22px 0; font-size: 12.5px; color: var(--text-3);
}
.footer-bottom .legal { display: flex; gap: 18px; flex-wrap: wrap; }
.footer-bottom a:hover { color: var(--text-1); }
</style>
</head>
<body>
<!-- ════════ 导航 ════════ -->
<nav>
<div class="frame nav-inner">
<a class="brand" href="#top">
<svg width="26" height="26" viewBox="0 0 48 48" fill="none" stroke="currentColor" stroke-width="3.5" stroke-linecap="round"><circle cx="24" cy="24" r="18"/><path d="M17 20.5v7"/><path d="M24 16.5v15"/><path d="M31 20.5v7"/></svg>
<span class="name">dudu</span>
</a>
<div class="nav-links">
<a href="#features">特性</a>
<a class="only-wide" href="#scenes">场景</a>
<a href="#how">怎么用</a>
<a class="only-wide" href="#faq">常见问题</a>
<a href="#pricing">价格</a>
<a class="btn btn-sm btn-secondary" href="#download">下载</a>
</div>
</div>
</nav>
<!-- ════════ Hero ════════ -->
<header class="hero" id="top">
<div class="frame hero-grid">
<div>
<span class="eyebrow"><span class="pip"></span>五端一套账号 · 时长永不过期</span>
<h1>按住说话<br><span class="accent-word">文字上屏</span></h1>
<div class="sub">
<span>大模型识别</span><span class="dot">·</span>
<span>流式实时</span><span class="dot">·</span>
<span>全平台输入法</span>
</div>
<div class="hero-cta">
<a class="btn btn-lg btn-primary" href="#download">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" x2="12" y1="15" y2="3"/></svg>
免费下载
</a>
<span class="hero-note">每天免费 <span class="num">3</span> 分钟 · 微信或邮箱登录即用</span>
</div>
</div>
<!-- 演示剧场:按住下方按钮(或长按空格)真实体验流式上屏 -->
<div class="stage" id="stage">
<div class="demo-window">
<div class="demo-titlebar"><i></i><i></i><i></i><span>备忘录 — 周报草稿</span></div>
<div class="demo-doc">
<span id="doc-text"></span><span class="placeholder" id="doc-placeholder">光标在这里 — 在任意应用按住快捷键即可语音输入</span><span class="caret"></span>
</div>
<div class="overlay" id="overlay">
<span class="wave" id="wave"></span>
<div class="ovl-status" id="ovl-status">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3Z"/><path d="M19 10v2a7 7 0 0 1-14 0v-2"/><line x1="12" x2="12" y1="19" y2="22"/></svg>
<span>聆听中…</span>
</div>
<div class="ovl-text" id="ovl-text" hidden></div>
<div class="ovl-hint">松开 ⌘⇧Space 完成输入</div>
</div>
</div>
<button class="micbar" id="micbar" type="button">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3Z"/><path d="M19 10v2a7 7 0 0 1-14 0v-2"/><line x1="12" x2="12" y1="19" y2="22"/></svg>
<span id="micbar-label">按住试一试</span>
</button>
<div class="stage-tip">就像在你电脑上按住 <kbd></kbd><kbd></kbd><kbd>Space</kbd> 一样</div>
</div>
</div>
</header>
<!-- ════════ 指标带 ════════ -->
<div class="metrics" data-theme="dark">
<div class="frame metrics-grid">
<div class="metric reveal">
<div class="num">&lt;500<small>ms</small></div>
<div class="label">按下到首字出现</div>
</div>
<div class="metric reveal" style="transition-delay:60ms">
<div class="num">5<small></small></div>
<div class="label">Mac · Windows · iPhone · iPad · Android</div>
</div>
<div class="metric reveal" style="transition-delay:120ms">
<div class="num">3<small>分钟/天</small></div>
<div class="label">免费试用 · 不需要先付费</div>
</div>
<div class="metric reveal" style="transition-delay:180ms">
<div class="num">0<small>过期</small></div>
<div class="label">买的时长永久有效</div>
</div>
</div>
</div>
<!-- ════════ 特性 ════════ -->
<section id="features">
<div class="frame">
<div class="section-head reveal">
<div class="kicker">为什么是 dudu</div>
<h2>识别得准,上屏得快<br>用起来像没有这层软件</h2>
</div>
<div class="features reveal">
<div class="feature">
<span class="icon"><svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M2 10v3"/><path d="M6 6v11"/><path d="M10 3v18"/><path d="M14 8v7"/><path d="M18 5v13"/><path d="M22 10v3"/></svg></span>
<h3>大模型识别</h3>
<p>云端大模型听写,中英混说、专有名词、自动标点都不在话下,说完即定稿</p>
</div>
<div class="feature">
<span class="icon"><svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2"/></svg></span>
<h3>流式实时上屏</h3>
<p>说话的同时文字就出现,不等你说完;松开按键,整句注入焦点输入框</p>
</div>
<div class="feature">
<span class="icon"><svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect width="20" height="14" x="2" y="3" rx="2"/><line x1="8" x2="16" y1="21" y2="21"/><line x1="12" x2="12" y1="17" y2="21"/></svg></span>
<h3>哪里都能用</h3>
<p>桌面端快捷键全局可用,手机上是真正的系统键盘——微信、文档、代码,焦点在哪写到哪</p>
</div>
<div class="feature">
<span class="icon"><svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m18 9-6-6-6 6"/><path d="M12 3v14"/><path d="M5 21h14"/></svg></span>
<h3>上滑随时取消</h3>
<p>话说错、想重来,按住时上滑就丢弃这一句,不会打断你的思路,也不会写错内容</p>
</div>
<div class="feature">
<span class="icon"><svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12.83 2.18a2 2 0 0 0-1.66 0L2.6 6.08a1 1 0 0 0 0 1.83l8.57 3.9a2 2 0 0 0 1.66 0l8.57-3.9a1 1 0 0 0 0-1.83Z"/><path d="m22 17.65-9.17 4.16a2 2 0 0 1-1.66 0L2 17.65"/><path d="m22 12.65-9.17 4.16a2 2 0 0 1-1.66 0L2 12.65"/></svg></span>
<h3>浮层不抢焦点</h3>
<p>识别浮层叠在当前应用之上,不夺走光标、不切走窗口——你正在做的事不受一点打断</p>
</div>
<div class="feature">
<span class="icon"><svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m5 8 6 6"/><path d="m4 14 6-6 2-3"/><path d="M2 5h12"/><path d="M7 2h1"/><path d="m22 22-5-10-5 10"/><path d="M14 18h6"/></svg></span>
<h3>中英混说不卡壳</h3>
<p>“把这个 pull request 合进 main”——中英文混着说、技术词穿插着讲,照样认得准、断得对</p>
</div>
</div>
</div>
</section>
<!-- ════════ 场景 ════════ -->
<section id="scenes">
<div class="frame">
<div class="section-head reveal">
<div class="scene-head">
<div>
<div class="kicker">用得上的时候</div>
<h2>需要动嘴的地方<br>就少动一次手</h2>
</div>
<div class="speed-badge">
<div class="big">3×</div>
<div class="cap">口述比打字约快</div>
</div>
</div>
</div>
<div class="scenes reveal">
<div class="scene">
<div class="top">
<span class="sicon"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"/><path d="M14 2v5h5"/><path d="M16 13H8"/><path d="M16 17H8"/><path d="M10 9H8"/></svg></span>
<h3>写周报、长文档、邮件</h3>
</div>
<p>先把想法一口气说成初稿,再动手改。想到哪说到哪,标点和分段它替你排好。</p>
<div class="eg">
<span class="say"><svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3Z"/><path d="M19 10v2a7 7 0 0 1-14 0v-2"/><line x1="12" x2="12" y1="19" y2="22"/></svg>你说</span>
<div class="quote">“这周主要推进了识别延迟优化,下周开始做支付联调。”</div>
</div>
</div>
<div class="scene">
<div class="top">
<span class="sicon"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg></span>
<h3>微信、消息、评论</h3>
</div>
<p>走路、做饭、通勤,腾不出两只手打字的时候,按住说完就发,长消息也不怕。</p>
<div class="eg">
<span class="say"><svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3Z"/><path d="M19 10v2a7 7 0 0 1-14 0v-2"/><line x1="12" x2="12" y1="19" y2="22"/></svg>你说</span>
<div class="quote">“我大概晚十分钟到,你们先点,给我留个 <b>靠窗</b> 的位置。”</div>
</div>
</div>
<div class="scene">
<div class="top">
<span class="sicon"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m16 18 6-6-6-6"/><path d="m8 6-6 6 6 6"/></svg></span>
<h3>代码注释、提交信息</h3>
</div>
<p>中英混说不卡壳,专有名词认得准,写注释和 commit message 时不用来回切输入法。</p>
<div class="eg">
<span class="say"><svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3Z"/><path d="M19 10v2a7 7 0 0 1-14 0v-2"/><line x1="12" x2="12" y1="19" y2="22"/></svg>你说</span>
<div class="quote">“修复 <b>WebSocket</b> 重连后丢帧的问题。”</div>
</div>
</div>
<div class="scene">
<div class="top">
<span class="sicon"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M15 14c.2-1 .7-1.7 1.5-2.5C17.7 10.3 18 9 18 7.5a6 6 0 0 0-12 0c0 1.5.5 2.8 1.5 4 .8.8 1.3 1.5 1.5 2.5"/><path d="M9 18h6"/><path d="M10 22h4"/></svg></span>
<h3>会议纪要、灵感速记</h3>
</div>
<p>开会随手记要点,脑子里冒出来的想法,说出来就落进备忘录,不怕它跑掉。</p>
<div class="eg">
<span class="say"><svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3Z"/><path d="M19 10v2a7 7 0 0 1-14 0v-2"/><line x1="12" x2="12" y1="19" y2="22"/></svg>你说</span>
<div class="quote">“下周三之前把三个方案的对比整理出来,周四评审。”</div>
</div>
</div>
</div>
</div>
</section>
<!-- ════════ 怎么用 ════════ -->
<section id="how">
<div class="frame">
<div class="section-head reveal">
<div class="kicker">怎么用</div>
<h2>三个动作,零学习成本</h2>
</div>
<div class="steps">
<div class="step reveal">
<div class="no">01</div>
<h3>按住 <kbd></kbd><kbd></kbd><kbd>Space</kbd></h3>
<p>桌面端任意输入框旁按住快捷键;手机上按住键盘的大麦克风</p>
</div>
<div class="step reveal" style="transition-delay:60ms">
<div class="no">02</div>
<h3>说话</h3>
<p>识别结果实时浮现,说错了上滑取消,不打断你的思路</p>
</div>
<div class="step reveal" style="transition-delay:120ms">
<div class="no">03</div>
<h3>松开,上屏</h3>
<p>整句文字直接写进光标处,标点已排好,接着说下一句就行</p>
</div>
</div>
</div>
</section>
<!-- ════════ 隐私与信任 ════════ -->
<section class="trust" id="trust" data-theme="dark">
<div class="frame">
<div class="section-head reveal">
<div class="kicker">隐私与信任</div>
<h2>它一直在偷听?<br>不,只在你按住的那一刻</h2>
<p class="lead">语音输入法听得见你说的每句话,所以我们把边界划得很清楚——录音、数据、计费,都不含糊。</p>
</div>
<div class="priv-grid reveal">
<div class="priv">
<span class="picon"><svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3Z"/><path d="M19 10v2a7 7 0 0 1-14 0v-2"/><line x1="12" x2="12" y1="19" y2="22"/></svg></span>
<h3>只在按住时录音</h3>
<p>松开即停,没有后台常驻监听。不按快捷键,麦克风就是关着的。</p>
</div>
<div class="priv">
<span class="picon"><svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z"/><path d="m9 12 2 2 4-4"/></svg></span>
<h3>音频用完即弃</h3>
<p>识别完成后音频即丢弃,不留存、不用于训练模型。我们要的是文字,不是你的声音。</p>
</div>
<div class="priv">
<span class="picon"><svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="4 7 4 4 20 4 20 7"/><line x1="9" x2="15" y1="20" y2="20"/><line x1="12" x2="12" y1="4" y2="20"/></svg></span>
<h3>文字只往光标处写</h3>
<p>dudu 把识别结果注入到你的输入框,不读取、不上传你在别处输入的任何内容。</p>
</div>
<div class="priv">
<span class="picon"><svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4 2v20l2-1 2 1 2-1 2 1 2-1 2 1 2-1 2 1V2l-2 1-2-1-2 1-2-1-2 1-2-1-2 1Z"/><path d="M16 8h-6a2 2 0 1 0 0 4h4a2 2 0 1 1 0 4H8"/><path d="M12 17.5v-11"/></svg></span>
<h3>按时长透明计费</h3>
<p>用多少识别时长扣多少,不订阅、不自动续费。买的时长永久有效,换设备也带得走。</p>
</div>
</div>
</div>
</section>
<!-- ════════ 平台 ════════ -->
<section id="download">
<div class="frame">
<div class="section-head reveal">
<div class="kicker">全平台</div>
<h2>你的每一台设备<br>共用一个账号和时长</h2>
</div>
<div class="plat-grid reveal">
<div class="plat">
<div class="os">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect width="20" height="14" x="2" y="3" rx="2"/><line x1="8" x2="16" y1="21" y2="21"/><line x1="12" x2="12" y1="17" y2="21"/></svg>
</div>
<h3>桌面 <span class="form">Mac · Windows</span></h3>
<p>全局快捷键 push-to-talk,任意输入框旁按住说话;识别浮层不抢焦点,不打断当前窗口。</p>
</div>
<div class="plat">
<div class="os">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect width="14" height="20" x="5" y="2" rx="2"/><path d="M12 18h.01"/></svg>
</div>
<h3>手机 <span class="form">iPhone · Android</span></h3>
<p>作为系统键盘接入,凡是能调出键盘的应用都能用。按住大麦克风说话,上滑取消。</p>
<span class="soon">陆续上架中</span>
</div>
<div class="plat">
<div class="os">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect width="18" height="22" x="3" y="1" rx="2"/><path d="M12 19h.01"/></svg>
</div>
<h3>平板 <span class="form">iPad</span></h3>
<p>键盘布局随屏幕自适应,横竖屏都顺手。和手机、桌面同一套账号,时长互通。</p>
</div>
</div>
</div>
</section>
<!-- ════════ 价格 ════════ -->
<section id="pricing">
<div class="frame">
<div class="section-head reveal">
<div class="kicker">价格</div>
<h2>按时长买,永不过期<br>不订阅、不扣月费</h2>
</div>
<div class="pricing reveal">
<div class="price-card">
<div class="minutes"><span class="num">100</span> 分钟</div>
<div class="price"><span class="cur">¥</span>9</div>
<div class="unit">约 ¥0.09 / 分钟</div>
<ul class="perks">
<li><svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5"/></svg>先试后买,随时够用</li>
<li><svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5"/></svg>时长永久有效</li>
</ul>
<a class="btn btn-lg btn-secondary" href="#download">选这档</a>
</div>
<div class="price-card hot">
<span class="tag">最多人选 · 省 13%</span>
<div class="minutes"><span class="num">500</span> 分钟</div>
<div class="price"><span class="cur">¥</span>39</div>
<div class="unit">约 ¥0.078 / 分钟</div>
<ul class="perks">
<li><svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5"/></svg>日常口述一两个月的量</li>
<li><svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5"/></svg>五端通用,一处购买处处能用</li>
</ul>
<a class="btn btn-lg btn-primary" href="#download">选这档</a>
</div>
<div class="price-card">
<span class="tag">省 28%</span>
<div class="minutes"><span class="num">2000</span> 分钟</div>
<div class="price"><span class="cur">¥</span>129</div>
<div class="unit">约 ¥0.065 / 分钟</div>
<ul class="perks">
<li><svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5"/></svg>重度使用最划算</li>
<li><svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5"/></svg>时长永久有效</li>
</ul>
<a class="btn btn-lg btn-secondary" href="#download">选这档</a>
</div>
</div>
<div class="pricing-note">每天另有 <span class="num">3</span> 分钟免费试用 · 微信支付,到账即用 · 时长永不过期,换设备照样能用</div>
</div>
</section>
<!-- ════════ 常见问题 ════════ -->
<section id="faq">
<div class="frame">
<div class="section-head center reveal">
<div class="kicker">常见问题</div>
<h2>你可能想先问的</h2>
</div>
<div class="faq reveal">
<details open>
<summary>需要联网吗?<span class="chev"><svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6"/></svg></span></summary>
<div class="answer">需要。识别由云端大模型完成,所以要联网使用。离线时会明确提示,不会静默失败或写错内容。</div>
</details>
<details>
<summary>我的语音会被保存吗?<span class="chev"><svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6"/></svg></span></summary>
<div class="answer">不会。音频在识别完成后即丢弃,既不留存、也不用于训练模型。dudu 只把结果文字写进你的输入框。</div>
</details>
<details>
<summary>识别不准怎么办?<span class="chev"><svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6"/></svg></span></summary>
<div class="answer">大模型对中英混说、专有名词、口语表达都做了优化,标点自动排好。万一说错了,按住时上滑就能取消这一句,重说即可,不会打断你正在做的事。</div>
</details>
<details>
<summary>换电脑或手机,买的时长还在吗?<span class="chev"><svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6"/></svg></span></summary>
<div class="answer">在。时长绑定你的账号,用微信或邮箱登录后,Mac、Windows、iPhone、iPad、Android 五端通用,余额实时同步。</div>
</details>
<details>
<summary>支持哪些应用和输入框?<span class="chev"><svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6"/></svg></span></summary>
<div class="answer">桌面端几乎所有可输入的地方都能用——浏览器、文档、聊天工具、代码编辑器。手机上作为系统键盘接入,凡是能调出键盘的应用都支持。</div>
</details>
<details>
<summary>免费额度用完会怎样?<span class="chev"><svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6"/></svg></span></summary>
<div class="answer">每天都有 3 分钟免费额度,次日自动恢复。想用得更多,可以购买时长包,按识别时长扣费,时长永不过期。</div>
</details>
<details>
<summary>和系统自带的语音输入有什么不同?<span class="chev"><svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6"/></svg></span></summary>
<div class="answer">dudu 用云端大模型,长句、标点、中英混说更稳,桌面端还有不抢焦点的浮层;而且五端一套账号、时长互通,跨设备体验一致。</div>
</details>
<details>
<summary>支持方言吗?<span class="chev"><svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6"/></svg></span></summary>
<div class="answer">目前以普通话为主,也支持标准粤语。更多方言的识别在逐步扩展中。</div>
</details>
</div>
</div>
</section>
<!-- ════════ 尾部 CTA ════════ -->
<div class="cta" data-theme="dark">
<div class="frame cta-inner reveal">
<svg class="logo-big" width="64" height="64" viewBox="0 0 48 48" fill="none" stroke="currentColor" stroke-width="3.5" stroke-linecap="round"><circle cx="24" cy="24" r="18"/><path d="M17 20.5v7"/><path d="M24 16.5v15"/><path d="M31 20.5v7"/></svg>
<h2>从下一句话开始<br>用说的</h2>
<p>下载 dudu,微信或邮箱登录,每天免费 3 分钟</p>
<div class="cta-btns">
<a class="btn btn-lg btn-primary" href="#download">免费下载 dudu</a>
<a class="btn btn-lg btn-secondary" href="#pricing">看看价格</a>
</div>
<div class="microcopy">无需先付费 · 时长永不过期 · 支持 <span class="num">5</span></div>
</div>
</div>
<!-- ════════ 页脚 ════════ -->
<footer data-theme="dark">
<div class="frame">
<div class="footer-top">
<div class="footer-brand">
<a class="brand" href="#top">
<svg width="22" height="22" viewBox="0 0 48 48" fill="none" stroke="currentColor" stroke-width="3.5" stroke-linecap="round"><circle cx="24" cy="24" r="18"/><path d="M17 20.5v7"/><path d="M24 16.5v15"/><path d="M31 20.5v7"/></svg>
<span class="name latin" style="font-size:17px;font-weight:600">dudu</span>
</a>
<p>按住说话,文字上屏。大模型识别的全平台语音输入法,五端一套账号,时长永不过期。</p>
</div>
<div class="footer-col">
<h4>产品</h4>
<a href="#features">特性</a>
<a href="#scenes">使用场景</a>
<a href="#how">怎么用</a>
<a href="#download">下载</a>
</div>
<div class="footer-col">
<h4>购买</h4>
<a href="#pricing">时长包价格</a>
<a href="#faq">常见问题</a>
<a href="#trust">隐私与信任</a>
</div>
<div class="footer-col">
<h4>支持</h4>
<a href="#">帮助中心</a>
<a href="#">联系我们</a>
<a href="#">更新日志</a>
</div>
</div>
<div class="footer-bottom">
<div>© 2026 dudu · 岩美北京技术有限公司</div>
<div class="legal">
<a href="#">用户协议</a>
<a href="#">隐私政策</a>
<a href="#">沪ICP备XXXXXXXX号</a>
</div>
</div>
</div>
</footer>
<script>
/* ── 波形条 ── */
const WAVE_PATTERN = [0.3, 0.55, 0.85, 0.45, 0.7, 1, 0.4, 0.6, 0.25, 0.8, 0.5, 0.35];
const wave = document.getElementById('wave');
WAVE_PATTERN.forEach((p, i) => {
const bar = document.createElement('i');
bar.style.height = Math.max(4, Math.round(p * 24)) + 'px';
bar.style.animationDelay = (i % 6) * 0.07 + 's';
wave.appendChild(bar);
});
/* ── 演示剧场:按住 = 流式识别,松开 = 上屏 ── */
const SENTENCES = [
'帮我把这份周报整理一下,重点突出本周的进展和下周的计划。',
'好的,我马上把文件发给你,大概十分钟之内。',
'明天上午十点的会改到下午三点,记得同步给项目组。',
];
const stage = document.getElementById('stage');
const overlay = document.getElementById('overlay');
const ovlStatus = document.getElementById('ovl-status');
const ovlText = document.getElementById('ovl-text');
const docText = document.getElementById('doc-text');
const docPlaceholder = document.getElementById('doc-placeholder');
const micbar = document.getElementById('micbar');
const micbarLabel = document.getElementById('micbar-label');
let timer = null, idx = 0, finalText = '', partialText = '', recording = false;
function render() {
const has = finalText || partialText;
ovlStatus.hidden = !!has;
ovlText.hidden = !has;
ovlText.innerHTML = '';
ovlText.append(finalText);
if (partialText) {
const s = document.createElement('span');
s.className = 'partial';
s.textContent = partialText;
ovlText.appendChild(s);
}
}
function start() {
if (recording) return;
recording = true;
finalText = ''; partialText = '';
render();
stage.classList.add('recording');
micbar.classList.add('recording');
micbarLabel.textContent = '松开完成输入';
overlay.classList.add('show');
const sentence = SENTENCES[idx % SENTENCES.length];
let i = 0;
timer = setInterval(() => {
i += 1;
if (i > sentence.length) { clearInterval(timer); return; }
const seen = sentence.slice(0, i);
const lastPunct = Math.max(seen.lastIndexOf(''), seen.lastIndexOf('。'));
finalText = sentence.slice(0, lastPunct + 1);
partialText = sentence.slice(lastPunct + 1, i);
render();
}, 75);
}
function stop() {
if (!recording) return;
recording = false;
clearInterval(timer);
stage.classList.remove('recording');
micbar.classList.remove('recording');
micbarLabel.textContent = '按住试一试';
overlay.classList.remove('show');
const committed = finalText + partialText;
if (committed) {
idx += 1;
docPlaceholder.hidden = true;
// 模拟注入:整句快速"打"进文档
let j = 0;
const base = docText.textContent;
const typeTimer = setInterval(() => {
j += 3;
docText.textContent = base + committed.slice(0, j);
if (j >= committed.length) clearInterval(typeTimer);
}, 16);
}
finalText = ''; partialText = '';
}
micbar.addEventListener('pointerdown', (e) => { e.preventDefault(); start(); });
window.addEventListener('pointerup', stop);
micbar.addEventListener('pointercancel', stop);
window.addEventListener('keydown', (e) => {
if (e.code === 'Space' && !e.repeat && e.target === document.body) { e.preventDefault(); start(); }
});
window.addEventListener('keyup', (e) => { if (e.code === 'Space') stop(); });
window.addEventListener('blur', stop);
/* ── 滚动浮现 ── */
const io = new IntersectionObserver((entries) => {
entries.forEach((en) => { if (en.isIntersecting) { en.target.classList.add('in'); io.unobserve(en.target); } });
}, { threshold: 0.15 });
document.querySelectorAll('.reveal').forEach((el) => io.observe(el));
</script>
</body>
</html>