First phase of the DESIGN.md (ClickHouse-inspired) migration. Rewrites
the foundation CSS variables and theme machinery; downstream phases
(status/role dictionaries, raw utility sweep) still pending.
index.css
- Full rewrite of @theme inline block. Dark (.dark) and light (:root)
token sets per MIGRATION-PLAN sections 3 and 5:
* Dark: pure black canvas (#000000), Neon Volt primary (#faff69),
Forest Green secondary (#166534), charcoal border (rgba(65,65,65,
0.8)), near-black cards (#141414), silver muted (#a0a0a0).
* Light: near-white canvas (#fafafa), Forest primary, Volt
downgraded to dark olive (#4f5100) for border/active use only,
silver inverted to #6b6b6b. Accessibility fallback, not brand.
- Added --warning (#f59e0b / #b45309), --success, and direct brand
token refs (--volt, --volt-pale, --volt-border, --forest, --near-
black, --hover-gray, --silver, --charcoal-border) exposed as
Tailwind utilities via --color-* mirrors.
- Added --destructive: #ef4444 (#dc2626 in light).
- Radius scale collapsed to 4px sharp / 8px comfortable / 9999px pill.
- Deleted .theme-tokyo-night.dark block entirely (was dead code —
ThemeContext never applied the class).
- Rewrote hljs syntax highlighting: one dark block under .dark .hljs
using volt for keywords, pale volt for strings, silver for
comments; one light block under .hljs using forest/dark-olive/
silver. Replaced all three Catppuccin + Tokyo Night hljs rule sets.
- Rewrote scrollbar rules to use var(--muted) / var(--charcoal-
border) / var(--hover-gray) instead of hardcoded oklch values.
- Added @font-face declarations for Inter (normal + italic) from the
self-hosted woff2 files at /fonts/InterVariable*.woff2. font-weight
100-900 range unlocks weight 900 for DESIGN.md hero moments from
a single variable font.
- Set --font-sans to Inter-first stack; body rule pulls the token.
ThemeContext.tsx
- Simplified to binary Theme = "light" | "dark". Dropped "custom"
theme type, PaletteRole interface, ROLE_TO_TOKEN map, and the
/api/nexus/settings custom-theme hydration effect.
- applyTheme() now just toggles .dark on <html> and sets
colorScheme. applyCustomTheme() left as a deprecated no-op (no
external callers but keeping the export avoids churn).
- Legacy localStorage values (catppuccin-mocha, tokyo-night, custom,
catppuccin-latte) coerced to "dark" on read so existing users
don't see a crash after the migration.
- Default theme: "dark".
Layout.tsx
- Dropped THEME_META import and the THEME_CYCLE map. Theme toggle
is now a binary sun/moon flip via toggleTheme().
index.html
- Added <link rel="preload" href="/fonts/InterVariable.woff2"
as="font" type="font/woff2" crossorigin>.
- Set inline style="background:#000000; color-scheme:dark;" on
<html> so the pre-React paint is already dark — no white flash.
- Boot script coerces legacy localStorage theme values and persists
"light" or "dark" only.
ui/public/fonts/
- Added InterVariable.woff2 (344 KB) and InterVariable-Italic.woff2
(379 KB), both Inter v4.x from rsms.me/inter (the canonical
upstream). Self-hosted for LAN/offline reliability.
Not changed:
- lib/status-colors.ts, lib/agent-role-colors.ts — next phase
- Any component files — phase 3
- MIGRATION-PLAN.md — will be updated with resolved decisions later
Expected visual state: pages using theme tokens (bg-background,
text-muted-foreground, border-border, ~1,250 instances) immediately
render with the new palette. Pages using raw Tailwind utilities
(bg-red-500, text-amber-600, ~274 instances) still show old colors
until phase 3 sweep.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
51 lines
2.5 KiB
HTML
51 lines
2.5 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en" class="dark" style="background:#000000; color-scheme:dark;">
|
|
<head>
|
|
<meta charset="UTF-8" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover" />
|
|
<meta name="theme-color" content="#000000" />
|
|
<meta name="mobile-web-app-capable" content="yes" />
|
|
<meta name="apple-mobile-web-app-capable" content="yes" />
|
|
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
|
|
<meta name="apple-mobile-web-app-title" content="Nexus" />
|
|
<title>Nexus</title>
|
|
<!-- PAPERCLIP_RUNTIME_BRANDING_START -->
|
|
<!-- PAPERCLIP_RUNTIME_BRANDING_END -->
|
|
<!-- PAPERCLIP_FAVICON_START -->
|
|
<link rel="icon" href="/favicon.ico" sizes="48x48" />
|
|
<link rel="icon" href="/favicon.svg" type="image/svg+xml" />
|
|
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png" />
|
|
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png" />
|
|
<!-- PAPERCLIP_FAVICON_END -->
|
|
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" />
|
|
<link rel="preload" as="font" type="font/woff2" href="/fonts/InterVariable.woff2" crossorigin />
|
|
<link rel="manifest" href="/site.webmanifest" />
|
|
<script>
|
|
(() => {
|
|
const key = "paperclip.theme";
|
|
const LEGACY_DARK = ["catppuccin-mocha", "tokyo-night", "custom"];
|
|
try {
|
|
let stored = window.localStorage.getItem(key);
|
|
if (stored && stored !== "light" && stored !== "dark") {
|
|
// Coerce legacy values. Latte was the old light default; everything else -> dark.
|
|
stored = stored === "catppuccin-latte" ? "light" : LEGACY_DARK.includes(stored) ? "dark" : "dark";
|
|
try { window.localStorage.setItem(key, stored); } catch {}
|
|
}
|
|
const theme = stored === "light" ? "light" : "dark";
|
|
const isDark = theme === "dark";
|
|
document.documentElement.classList.toggle("dark", isDark);
|
|
document.documentElement.style.colorScheme = isDark ? "dark" : "light";
|
|
const meta = document.querySelector('meta[name="theme-color"]');
|
|
if (meta) meta.setAttribute("content", isDark ? "#000000" : "#fafafa");
|
|
} catch {
|
|
document.documentElement.classList.add("dark");
|
|
document.documentElement.style.colorScheme = "dark";
|
|
}
|
|
})();
|
|
</script>
|
|
</head>
|
|
<body>
|
|
<div id="root"></div>
|
|
<script type="module" src="/src/main.tsx"></script>
|
|
</body>
|
|
</html>
|