nanobot/webui/index.html
chengyongru a7caee1186 style(webui): improve typography with Apple-inspired font stack and CJK support
- Add explicit CJK fonts (PingFang SC, Noto Sans SC, Microsoft YaHei) and
  programmer fonts (JetBrains Mono, Fira Code, Cascadia Code) to Tailwind config
- Bump prose base size from prose-sm (14px) to prose-lg (18px) for sharper CJK rendering
- Unify user/assistant message font size at 18px with CJK-aware line-height (1.8)
- Replace pure black/white foreground with Apple-style warm grays (#1d1d1f / #f5f5f7)
- Override Tailwind Typography colors to use design tokens for consistency
- Add negative letter-spacing on headings for tighter, more polished look
2026-04-20 00:03:38 +08:00

187 lines
5.9 KiB
HTML

<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="color-scheme" content="light dark" />
<meta
name="description"
content="nanobot web UI — chat with your nanobot workspace."
data-i18n-meta="description"
/>
<meta name="theme-color" content="#fafaf9" media="(prefers-color-scheme: light)" />
<meta name="theme-color" content="#161618" media="(prefers-color-scheme: dark)" />
<link rel="icon" type="image/png" sizes="32x32" href="/brand/nanobot_favicon_32.png" />
<link rel="icon" type="image/png" sizes="73x75" href="/brand/nanobot_icon.png" />
<link rel="apple-touch-icon" sizes="180x180" href="/brand/nanobot_apple_touch.png" />
<style>
html,
body,
#root {
height: 100%;
}
body {
margin: 0;
background: #ffffff;
color: #0a0a0a;
font-family:
system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
"Helvetica Neue", Arial, "Noto Sans", "Noto Sans SC",
"PingFang SC", "Hiragino Sans GB", "Microsoft YaHei",
sans-serif;
}
html.dark body {
background: #1a1a1a;
color: #fafafa;
}
.boot-splash {
display: flex;
height: 100%;
align-items: center;
justify-content: center;
}
.boot-splash-inner {
display: flex;
align-items: center;
gap: 10px;
color: rgba(255, 255, 255, 0.74);
font-size: 14px;
}
html:not(.dark) .boot-splash-inner {
color: rgba(10, 10, 10, 0.64);
}
.boot-dot {
width: 8px;
height: 8px;
border-radius: 9999px;
background: currentColor;
opacity: 0.75;
animation: boot-pulse 1s ease-in-out infinite;
}
@keyframes boot-pulse {
0%,
100% {
transform: scale(0.9);
opacity: 0.45;
}
50% {
transform: scale(1);
opacity: 0.85;
}
}
</style>
<script>
(function () {
try {
var stored = localStorage.getItem("nanobot-webui.theme");
var dark =
stored === "dark" ||
(!stored &&
window.matchMedia &&
window.matchMedia("(prefers-color-scheme: dark)").matches);
if (dark) document.documentElement.classList.add("dark");
} catch {}
})();
</script>
<script>
(function () {
var localeKey = "nanobot.locale";
var copy = {
en: {
boot: "Loading nanobot…",
description: "nanobot web UI — chat with your nanobot workspace."
},
"zh-CN": {
boot: "正在加载 nanobot…",
description: "nanobot Web UI —— 与你的 nanobot 工作区对话。"
},
"zh-TW": {
boot: "正在載入 nanobot…",
description: "nanobot Web UI —— 與你的 nanobot 工作區對話。"
},
fr: {
boot: "Chargement de nanobot…",
description: "Interface web nanobot — discutez avec votre espace de travail nanobot."
},
ja: {
boot: "nanobot を読み込み中…",
description: "nanobot Web UI — nanobot ワークスペースと会話します。"
},
ko: {
boot: "nanobot 불러오는 중…",
description: "nanobot 웹 UI — nanobot 작업공간과 대화하세요."
},
es: {
boot: "Cargando nanobot…",
description: "Interfaz web de nanobot: conversa con tu espacio de trabajo de nanobot."
},
vi: {
boot: "Đang tải nanobot…",
description: "Giao diện web nanobot — trò chuyện với workspace nanobot của bạn."
},
id: {
boot: "Memuat nanobot…",
description: "UI web nanobot — ngobrol dengan workspace nanobot Anda."
}
};
function normalizeLocale(input) {
if (!input) return "en";
var raw = String(input).trim();
if (!raw) return "en";
if (copy[raw]) return raw;
var lower = raw.toLowerCase();
if (lower === "zh" || lower.indexOf("zh-cn") === 0 || lower.indexOf("zh-sg") === 0) {
return "zh-CN";
}
if (
lower.indexOf("zh-tw") === 0 ||
lower.indexOf("zh-hk") === 0 ||
lower.indexOf("zh-mo") === 0 ||
lower.indexOf("zh-hant") === 0
) {
return "zh-TW";
}
var base = lower.split("-")[0];
return copy[base] ? base : "en";
}
try {
var stored = localStorage.getItem(localeKey);
var detected =
stored ||
(navigator.languages && navigator.languages[0]) ||
navigator.language ||
"en";
var locale = normalizeLocale(detected);
var localized = copy[locale] || copy.en;
document.documentElement.lang = locale;
var description = document.querySelector('[data-i18n-meta=\"description\"]');
if (description) description.setAttribute("content", localized.description);
var boot = document.querySelector("[data-boot-copy]");
if (boot) boot.textContent = localized.boot;
} catch {}
})();
</script>
<title>nanobot</title>
</head>
<body class="bg-background text-foreground antialiased">
<div id="root">
<div class="boot-splash">
<div class="boot-splash-inner">
<span class="boot-dot" aria-hidden="true"></span>
<span data-boot-copy>Loading nanobot…</span>
</div>
</div>
</div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>