feat(ui): apply Justine ink & parchment design system

- Map Justine tokens to shadcn CSS variables (--vibn-* aliases)
- Switch fonts to Inter + Lora via next/font (IBM Plex Mono for code)
- Base typography: body Inter, h1–h3 Lora; marketing hero + wordmark serif
- Project shell and global chrome use semantic colors
- Replace Outfit/Newsreader references across TSX inline styles

Made-with: Cursor
This commit is contained in:
2026-04-01 21:03:40 -07:00
parent 06238f958a
commit bada63452f
33 changed files with 300 additions and 286 deletions

View File

@@ -162,7 +162,7 @@ export function CooChat({ projectId }: { projectId: string }) {
margin: "8px 0 4px", opacity: 0.5,
}}>
<div style={{ flex: 1, height: 1, background: "#e8e4dc" }} />
<span style={{ fontSize: "0.58rem", color: "#b5b0a6", fontFamily: "Outfit, sans-serif", whiteSpace: "nowrap" }}>
<span style={{ fontSize: "0.58rem", color: "#b5b0a6", fontFamily: "var(--font-inter), ui-sans-serif, sans-serif", whiteSpace: "nowrap" }}>
Discovery · COO
</span>
<div style={{ flex: 1, height: 1, background: "#e8e4dc" }} />
@@ -183,7 +183,7 @@ export function CooChat({ projectId }: { projectId: string }) {
display: "flex", alignItems: "center", justifyContent: "center",
fontSize: isAtlas ? "0.48rem" : "0.48rem",
color: "#fff", flexShrink: 0,
fontFamily: isAtlas ? "Newsreader, serif" : "inherit",
fontFamily: isAtlas ? "var(--font-lora), ui-serif, serif" : "inherit",
fontWeight: isAtlas ? 700 : 400,
}}>
{isAtlas ? "A" : "◈"}
@@ -197,7 +197,7 @@ export function CooChat({ projectId }: { projectId: string }) {
borderRadius: isUser ? 10 : 0,
fontSize: isAtlas ? "0.75rem" : "0.79rem",
color: isAtlas ? "#4a4540" : "#1a1a1a",
fontFamily: "Outfit, sans-serif",
fontFamily: "var(--font-inter), ui-sans-serif, sans-serif",
lineHeight: 1.6,
whiteSpace: "pre-wrap",
wordBreak: "break-word",
@@ -248,7 +248,7 @@ export function CooChat({ projectId }: { projectId: string }) {
flex: 1, resize: "none",
border: "1px solid #e8e4dc", borderRadius: 10,
padding: "8px 10px", fontSize: "0.79rem",
fontFamily: "Outfit, sans-serif",
fontFamily: "var(--font-inter), ui-sans-serif, sans-serif",
color: "#1a1a1a", outline: "none",
background: "#faf8f5", lineHeight: 1.5,
}}
@@ -267,7 +267,7 @@ export function CooChat({ projectId }: { projectId: string }) {
}}
></button>
</div>
<div style={{ fontSize: "0.6rem", color: "#c5c0b8", marginTop: 5, fontFamily: "Outfit, sans-serif" }}>
<div style={{ fontSize: "0.6rem", color: "#c5c0b8", marginTop: 5, fontFamily: "var(--font-inter), ui-sans-serif, sans-serif" }}>
send · Shift+ newline
</div>
</div>

View File

@@ -59,15 +59,15 @@ function ProjectShellInner({
<div style={{
display: "flex", flexDirection: "column",
height: "100dvh", overflow: "hidden",
fontFamily: "Outfit, sans-serif",
background: "#f6f4f0",
fontFamily: "var(--font-inter), ui-sans-serif, sans-serif",
background: "var(--background)",
}}>
{/* ── Top bar ── */}
<header style={{
height: 48, flexShrink: 0,
display: "flex", alignItems: "stretch",
background: "#fff", borderBottom: "1px solid #e8e4dc",
background: "var(--card)", borderBottom: "1px solid var(--border)",
zIndex: 10,
}}>
@@ -75,7 +75,7 @@ function ProjectShellInner({
<div style={{
display: "flex", alignItems: "center",
padding: "0 16px", gap: 9, flexShrink: 0,
borderRight: "1px solid #e8e4dc",
borderRight: "1px solid var(--border)",
}}>
<Link
href={`/${workspace}/projects`}
@@ -86,7 +86,7 @@ function ProjectShellInner({
</div>
</Link>
<span style={{
fontSize: "0.82rem", fontWeight: 600, color: "#1a1a1a",
fontSize: "0.82rem", fontWeight: 600, color: "var(--foreground)",
maxWidth: 160, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap",
}}>
{projectName}
@@ -105,13 +105,13 @@ function ProjectShellInner({
padding: "5px 12px", borderRadius: 8,
fontSize: "0.8rem",
fontWeight: isActive ? 600 : 440,
color: isActive ? "#1a1a1a" : "#8a8478",
background: isActive ? "#f0ece4" : "transparent",
color: isActive ? "var(--foreground)" : "var(--muted-foreground)",
background: isActive ? "var(--secondary)" : "transparent",
textDecoration: "none",
transition: "background 0.1s, color 0.1s",
whiteSpace: "nowrap",
}}
onMouseEnter={e => { if (!isActive) (e.currentTarget as HTMLElement).style.background = "#f6f4f0"; }}
onMouseEnter={e => { if (!isActive) (e.currentTarget as HTMLElement).style.background = "var(--muted)"; }}
onMouseLeave={e => { if (!isActive) (e.currentTarget as HTMLElement).style.background = "transparent"; }}
>
{s.label}
@@ -128,9 +128,9 @@ function ProjectShellInner({
title={`${session?.user?.name ?? session?.user?.email ?? "Account"} — Sign out`}
style={{
width: 28, height: 28, borderRadius: "50%",
background: "#f0ece4", border: "none", cursor: "pointer",
background: "var(--secondary)", border: "none", cursor: "pointer",
display: "flex", alignItems: "center", justifyContent: "center",
fontSize: "0.65rem", fontWeight: 700, color: "#6b6560", flexShrink: 0,
fontSize: "0.65rem", fontWeight: 700, color: "var(--muted-foreground)", flexShrink: 0,
}}
>
{userInitial}

View File

@@ -103,7 +103,7 @@ export function VIBNSidebar({ workspace, tabs, activeTab }: VIBNSidebarProps) {
width: w, height: "100vh",
background: "#fff", borderRight: "1px solid #e8e4dc",
display: "flex", flexDirection: "column",
fontFamily: "Outfit, sans-serif",
fontFamily: "var(--font-inter), ui-sans-serif, sans-serif",
flexShrink: 0, overflow: "hidden",
transition, position: "relative",
}}>
@@ -136,7 +136,7 @@ export function VIBNSidebar({ workspace, tabs, activeTab }: VIBNSidebarProps) {
<div style={{ width: 26, height: 26, borderRadius: 7, overflow: "hidden", flexShrink: 0 }}>
<img src="/vibn-black-circle-logo.png" alt="VIBN" style={{ width: "100%", height: "100%", objectFit: "cover" }} />
</div>
<span style={{ fontSize: "0.92rem", fontWeight: 600, color: "#1a1a1a", letterSpacing: "-0.03em", fontFamily: "Newsreader, serif", whiteSpace: "nowrap" }}>
<span style={{ fontSize: "0.92rem", fontWeight: 600, color: "#1a1a1a", letterSpacing: "-0.03em", fontFamily: "var(--font-lora), ui-serif, serif", whiteSpace: "nowrap" }}>
vibn
</span>
</Link>
@@ -334,7 +334,7 @@ export function VIBNSidebar({ workspace, tabs, activeTab }: VIBNSidebarProps) {
<button onClick={() => signOut({ callbackUrl: "/auth" })} style={{
background: "none", border: "none", padding: 0,
fontSize: "0.62rem", color: "#a09a90", cursor: "pointer",
fontFamily: "Outfit, sans-serif",
fontFamily: "var(--font-inter), ui-sans-serif, sans-serif",
}}>
Sign out
</button>