Skip to content

Instantly share code, notes, and snippets.

@smallnest
Created April 14, 2026 08:48
Show Gist options
  • Select an option

  • Save smallnest/e2e55b22e305b16daac696f2e3eb1242 to your computer and use it in GitHub Desktop.

Select an option

Save smallnest/e2e55b22e305b16daac696f2e3eb1242 to your computer and use it in GitHub Desktop.
light theme for Hermes 0.9.0 dashboard
diff --git a/web/index.html b/web/index.html
index c9f0d18e..a8a1b922 100644
--- a/web/index.html
+++ b/web/index.html
@@ -5,6 +5,9 @@
<link rel="icon" type="image/svg+xml" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Hermes Agent</title>
+ <link rel="preconnect" href="https://fonts.googleapis.com" />
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
+ <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet" />
</head>
<body>
<div id="root"></div>
diff --git a/web/src/App.tsx b/web/src/App.tsx
index b2f76808..cb1ec8ab 100644
--- a/web/src/App.tsx
+++ b/web/src/App.tsx
@@ -39,8 +39,6 @@ export default function App() {
const initialRef = useRef(true);
useEffect(() => {
- // Skip the animation key bump on initial mount to avoid re-mounting
- // the default page component (which causes duplicate API requests).
if (initialRef.current) {
initialRef.current = false;
return;
@@ -52,48 +50,45 @@ export default function App() {
return (
<div className="flex min-h-screen flex-col bg-background text-foreground">
- {/* Global grain + warm glow (matches landing page) */}
+ {/* Global grain + warm glow */}
<div className="noise-overlay" />
<div className="warm-glow" />
- {/* ---- Header with grid-border nav ---- */}
- <header className="sticky top-0 z-40 border-b border-border bg-background/90 backdrop-blur-sm">
- <div className="mx-auto flex h-12 max-w-[1400px] items-stretch">
+ {/* ---- Header ---- */}
+ <header className="sticky top-0 z-40 border-b border-border bg-white/80 backdrop-blur-md">
+ <div className="mx-auto flex h-12 max-w-[1400px] items-center px-4">
{/* Brand */}
- <div className="flex items-center border-r border-border px-5 shrink-0">
- <span className="font-collapse text-xl font-bold tracking-wider uppercase blend-lighter">
- Hermes<br className="hidden sm:inline" /><span className="sm:hidden"> </span>Agent
+ <div className="flex items-center gap-2.5 shrink-0 mr-6">
+ <div className="h-7 w-7 rounded-lg bg-primary flex items-center justify-center">
+ <span className="text-white font-bold text-sm">H</span>
+ </div>
+ <span className="text-sm font-semibold tracking-tight">
+ Hermes Agent
</span>
</div>
- {/* Nav grid — Mondwest labels like the landing page nav */}
- <nav className="flex items-stretch overflow-x-auto scrollbar-none">
+ {/* Nav */}
+ <nav className="flex items-center gap-1 overflow-x-auto scrollbar-none">
{NAV_ITEMS.map(({ id, label, icon: Icon }) => (
<button
key={id}
type="button"
onClick={() => setPage(id)}
- className={`group relative inline-flex items-center gap-1.5 border-r border-border px-4 py-2 font-display text-[0.8rem] tracking-[0.12em] uppercase whitespace-nowrap transition-colors cursor-pointer shrink-0 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring ${
+ className={`group relative inline-flex items-center gap-1.5 rounded-lg px-3 py-1.5 text-sm font-medium transition-colors cursor-pointer focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring ${
page === id
- ? "text-foreground"
- : "text-muted-foreground hover:text-foreground"
+ ? "text-foreground bg-secondary"
+ : "text-muted-foreground hover:text-foreground hover:bg-secondary/60"
}`}
>
- <Icon className="h-3.5 w-3.5" />
+ <Icon className="h-4 w-4" />
{label}
- {/* Hover highlight */}
- <span className="absolute inset-0 bg-foreground pointer-events-none transition-opacity duration-150 group-hover:opacity-5 opacity-0" />
- {/* Active indicator — dither bar */}
- {page === id && (
- <span className="absolute bottom-0 left-0 right-0 h-px bg-foreground" />
- )}
</button>
))}
</nav>
{/* Version badge */}
- <div className="ml-auto flex items-center px-4 text-muted-foreground">
- <span className="font-display text-[0.7rem] tracking-[0.15em] uppercase opacity-50">
+ <div className="ml-auto flex items-center">
+ <span className="text-xs text-muted-foreground">
Web UI
</span>
</div>
@@ -109,12 +104,12 @@ export default function App() {
</main>
{/* ---- Footer ---- */}
- <footer className="relative z-2 border-t border-border">
+ <footer className="relative z-2 border-t border-border bg-white/50">
<div className="mx-auto flex max-w-[1400px] items-center justify-between px-6 py-3">
- <span className="font-display text-[0.8rem] tracking-[0.12em] uppercase opacity-50">
+ <span className="text-xs text-muted-foreground">
Hermes Agent
</span>
- <span className="font-display text-[0.7rem] tracking-[0.15em] uppercase text-foreground/40">
+ <span className="text-xs text-muted-foreground/60">
Nous Research
</span>
</div>
diff --git a/web/src/components/AutoField.tsx b/web/src/components/AutoField.tsx
index 67f6739e..bc574bed 100644
--- a/web/src/components/AutoField.tsx
+++ b/web/src/components/AutoField.tsx
@@ -85,7 +85,7 @@ export function AutoField({
<Label className="text-sm">{label}</Label>
<FieldHint schema={schema} schemaKey={schemaKey} />
<textarea
- className="flex min-h-[80px] w-full rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring"
+ className="flex min-h-[80px] w-full rounded-lg border border-input bg-white px-3 py-2 text-sm shadow-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1"
value={String(value ?? "")}
onChange={(e) => onChange(e.target.value)}
/>
diff --git a/web/src/components/OAuthLoginModal.tsx b/web/src/components/OAuthLoginModal.tsx
index 836ec4a1..0d16bb9a 100644
--- a/web/src/components/OAuthLoginModal.tsx
+++ b/web/src/components/OAuthLoginModal.tsx
@@ -192,7 +192,7 @@ export function OAuthLoginModal({ provider, onClose, onSuccess, onError }: Props
aria-modal="true"
aria-labelledby="oauth-modal-title"
>
- <div className="relative w-full max-w-md border border-border bg-card shadow-2xl">
+ <div className="relative w-full max-w-md rounded-xl border border-border bg-card shadow-2xl">
<button
type="button"
onClick={handleClose}
@@ -203,7 +203,7 @@ export function OAuthLoginModal({ provider, onClose, onSuccess, onError }: Props
</button>
<div className="p-6 flex flex-col gap-4">
<div>
- <h2 id="oauth-modal-title" className="font-display text-base tracking-wider uppercase">
+ <h2 id="oauth-modal-title" className="text-base font-semibold">
Connect {provider.name}
</h2>
{secondsLeft !== null && phase !== "approved" && phase !== "error" && (
diff --git a/web/src/components/Toast.tsx b/web/src/components/Toast.tsx
index e6bb349e..39010ed4 100644
--- a/web/src/components/Toast.tsx
+++ b/web/src/components/Toast.tsx
@@ -24,10 +24,10 @@ export function Toast({ toast }: { toast: { message: string; type: "success" | "
<div
role="status"
aria-live="polite"
- className={`fixed top-16 right-4 z-50 border px-4 py-2.5 font-courier text-xs tracking-wider uppercase backdrop-blur-sm ${
+ className={`fixed top-16 right-4 z-50 border rounded-lg px-4 py-2.5 text-sm font-medium shadow-lg backdrop-blur-sm ${
current.type === "success"
- ? "bg-success/15 text-success border-success/30"
- : "bg-destructive/15 text-destructive border-destructive/30"
+ ? "bg-white text-success border-success/20"
+ : "bg-white text-destructive border-destructive/20"
}`}
style={{
animation: visible ? "toast-in 200ms ease-out forwards" : "toast-out 200ms ease-in forwards",
diff --git a/web/src/components/ui/badge.tsx b/web/src/components/ui/badge.tsx
index 2f180510..dbabae11 100644
--- a/web/src/components/ui/badge.tsx
+++ b/web/src/components/ui/badge.tsx
@@ -2,16 +2,16 @@ import { cva, type VariantProps } from "class-variance-authority";
import { cn } from "@/lib/utils";
const badgeVariants = cva(
- "inline-flex items-center border px-2 py-0.5 font-compressed text-[0.65rem] tracking-[0.15em] uppercase transition-colors",
+ "inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-medium transition-colors",
{
variants: {
variant: {
- default: "border-foreground/20 bg-foreground/10 text-foreground",
+ default: "border-primary/20 bg-primary/10 text-primary",
secondary: "border-border bg-secondary text-secondary-foreground",
- destructive: "border-destructive/30 bg-destructive/15 text-destructive",
+ destructive: "border-red-200 bg-red-50 text-red-600",
outline: "border-border text-muted-foreground",
- success: "grain border-emerald-600/30 bg-emerald-950/70 text-emerald-400",
- warning: "border-warning/30 bg-warning/15 text-warning",
+ success: "border-emerald-200 bg-emerald-50 text-emerald-700",
+ warning: "border-amber-200 bg-amber-50 text-amber-700",
},
},
defaultVariants: {
diff --git a/web/src/components/ui/button.tsx b/web/src/components/ui/button.tsx
index 38ca7101..09582024 100644
--- a/web/src/components/ui/button.tsx
+++ b/web/src/components/ui/button.tsx
@@ -2,21 +2,22 @@ import { cva, type VariantProps } from "class-variance-authority";
import { cn } from "@/lib/utils";
const buttonVariants = cva(
- "inline-flex items-center justify-center gap-2 whitespace-nowrap font-display text-xs tracking-[0.1em] uppercase transition-colors cursor-pointer"
- + " disabled:pointer-events-none disabled:opacity-50",
+ "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-lg text-sm font-medium transition-colors cursor-pointer"
+ + " disabled:pointer-events-none disabled:opacity-50"
+ + " focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
{
variants: {
variant: {
- default: "bg-foreground/90 text-background hover:bg-foreground",
- destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90",
- outline: "border border-border bg-transparent hover:bg-foreground/10 hover:text-foreground",
+ default: "bg-primary text-primary-foreground hover:bg-primary/90",
+ destructive: "bg-red-600 text-white hover:bg-red-700",
+ outline: "border border-border bg-white hover:bg-secondary hover:text-secondary-foreground",
secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",
- ghost: "hover:bg-foreground/10 hover:text-foreground",
- link: "text-foreground underline-offset-4 hover:underline",
+ ghost: "hover:bg-secondary hover:text-secondary-foreground",
+ link: "text-primary underline-offset-4 hover:underline",
},
size: {
default: "h-9 px-4 py-2",
- sm: "h-8 px-3 text-[0.65rem]",
+ sm: "h-8 px-3 text-xs",
lg: "h-10 px-8",
icon: "h-9 w-9",
},
diff --git a/web/src/components/ui/card.tsx b/web/src/components/ui/card.tsx
index 7ff6a9ae..af731c48 100644
--- a/web/src/components/ui/card.tsx
+++ b/web/src/components/ui/card.tsx
@@ -4,7 +4,7 @@ export function Card({ className, ...props }: React.HTMLAttributes<HTMLDivElemen
return (
<div
className={cn(
- "border border-border bg-card/80 text-card-foreground",
+ "rounded-xl border border-border bg-card text-card-foreground shadow-sm",
className,
)}
{...props}
@@ -17,11 +17,11 @@ export function CardHeader({ className, ...props }: React.HTMLAttributes<HTMLDiv
}
export function CardTitle({ className, ...props }: React.HTMLAttributes<HTMLHeadingElement>) {
- return <h3 className={cn("font-expanded text-sm font-bold tracking-[0.08em] uppercase blend-lighter", className)} {...props} />;
+ return <h3 className={cn("text-sm font-semibold tracking-tight", className)} {...props} />;
}
export function CardDescription({ className, ...props }: React.HTMLAttributes<HTMLParagraphElement>) {
- return <p className={cn("font-display text-xs text-muted-foreground", className)} {...props} />;
+ return <p className={cn("text-sm text-muted-foreground", className)} {...props} />;
}
export function CardContent({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) {
diff --git a/web/src/components/ui/input.tsx b/web/src/components/ui/input.tsx
index 1e1199e6..f223a4f6 100644
--- a/web/src/components/ui/input.tsx
+++ b/web/src/components/ui/input.tsx
@@ -4,9 +4,9 @@ export function Input({ className, ...props }: React.InputHTMLAttributes<HTMLInp
return (
<input
className={cn(
- "flex h-9 w-full border border-border bg-background/40 px-3 py-1 font-courier text-sm transition-colors",
+ "flex h-9 w-full rounded-lg border border-input bg-white px-3 py-1 text-sm transition-colors",
"placeholder:text-muted-foreground",
- "focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-foreground/30 focus-visible:border-foreground/25",
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:border-primary",
"disabled:cursor-not-allowed disabled:opacity-50",
className,
)}
diff --git a/web/src/components/ui/label.tsx b/web/src/components/ui/label.tsx
index a18b2e5d..f5577fbb 100644
--- a/web/src/components/ui/label.tsx
+++ b/web/src/components/ui/label.tsx
@@ -4,7 +4,7 @@ export function Label({ className, ...props }: React.LabelHTMLAttributes<HTMLLab
return (
<label
className={cn(
- "font-display text-xs tracking-[0.1em] uppercase leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70",
+ "text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70",
className,
)}
{...props}
diff --git a/web/src/components/ui/select.tsx b/web/src/components/ui/select.tsx
index 0f42ef91..e136fdc6 100644
--- a/web/src/components/ui/select.tsx
+++ b/web/src/components/ui/select.tsx
@@ -4,8 +4,8 @@ export function Select({ className, ...props }: React.SelectHTMLAttributes<HTMLS
return (
<select
className={cn(
- "flex h-9 w-full border border-border bg-background/40 px-3 py-1 font-courier text-sm",
- "focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-foreground/30 focus-visible:border-foreground/25",
+ "flex h-9 w-full rounded-lg border border-input bg-white px-3 py-1 text-sm",
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:border-primary",
"disabled:cursor-not-allowed disabled:opacity-50",
className,
)}
diff --git a/web/src/components/ui/switch.tsx b/web/src/components/ui/switch.tsx
index fe36c775..2e007c03 100644
--- a/web/src/components/ui/switch.tsx
+++ b/web/src/components/ui/switch.tsx
@@ -18,18 +18,18 @@ export function Switch({
aria-checked={checked}
disabled={disabled}
className={cn(
- "peer inline-flex h-5 w-9 shrink-0 cursor-pointer items-center border border-border transition-colors",
- "focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-foreground/30",
+ "peer inline-flex h-5 w-9 shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent transition-colors",
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
"disabled:cursor-not-allowed disabled:opacity-50",
- checked ? "bg-foreground/15 border-foreground/30" : "bg-background",
+ checked ? "bg-primary" : "bg-muted",
className,
)}
onClick={() => onCheckedChange(!checked)}
>
<span
className={cn(
- "pointer-events-none block h-3.5 w-3.5 transition-transform",
- checked ? "translate-x-4 bg-foreground" : "translate-x-0.5 bg-muted-foreground",
+ "pointer-events-none block h-4 w-4 rounded-full bg-white shadow-sm transition-transform",
+ checked ? "translate-x-4" : "translate-x-0",
)}
/>
</button>
diff --git a/web/src/components/ui/tabs.tsx b/web/src/components/ui/tabs.tsx
index 039af02f..1a8517e3 100644
--- a/web/src/components/ui/tabs.tsx
+++ b/web/src/components/ui/tabs.tsx
@@ -37,10 +37,10 @@ export function TabsTrigger({
<button
type="button"
className={cn(
- "relative inline-flex items-center justify-center whitespace-nowrap px-3 py-1.5 font-display text-xs tracking-[0.1em] uppercase transition-all cursor-pointer",
- "focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
+ "relative inline-flex items-center justify-center whitespace-nowrap px-3 py-1.5 text-sm font-medium transition-all cursor-pointer",
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
active
- ? "text-foreground after:absolute after:bottom-0 after:left-0 after:right-0 after:h-px after:bg-foreground"
+ ? "text-foreground after:absolute after:bottom-0 after:left-0 after:right-0 after:h-0.5 after:bg-primary after:rounded-full"
: "hover:text-foreground",
className,
)}
diff --git a/web/src/index.css b/web/src/index.css
index 7846e9f9..74ed31d5 100644
--- a/web/src/index.css
+++ b/web/src/index.css
@@ -1,57 +1,46 @@
@import "tailwindcss";
/* ------------------------------------------------------------------ */
-/* Hermes Agent — Design tokens */
-/* Matched to hermes-agent.nousresearch.com (dark teal theme) */
+/* Hermes Agent — Modern Light Theme */
+/* Clean, minimal design inspired by Linear / Vercel / Stripe */
/* ------------------------------------------------------------------ */
-/* --- Font faces --- */
-@font-face { font-family: "Collapse"; src: url("/fonts/Collapse-Regular.woff2") format("woff2"); font-weight: 400; font-display: swap; }
-@font-face { font-family: "Collapse"; src: url("/fonts/Collapse-Bold.woff2") format("woff2"); font-weight: 700; font-display: swap; }
-@font-face { font-family: "Courier Prime"; src: url("/fonts/CourierPrime-Regular.woff2") format("woff2"); font-weight: 400; font-display: swap; }
-@font-face { font-family: "Courier Prime"; src: url("/fonts/CourierPrime-Bold.woff2") format("woff2"); font-weight: 700; font-display: swap; }
-@font-face { font-family: "RulesCompressed"; src: url("/fonts/RulesCompressed-Regular.woff2") format("woff2"); font-weight: 400; font-display: swap; }
-@font-face { font-family: "RulesCompressed"; src: url("/fonts/RulesCompressed-Medium.woff2") format("woff2"); font-weight: 600; font-display: swap; }
-@font-face { font-family: "RulesExpanded"; src: url("/fonts/RulesExpanded-Regular.woff2") format("woff2"); font-weight: 400; font-display: swap; }
-@font-face { font-family: "RulesExpanded"; src: url("/fonts/RulesExpanded-Bold.woff2") format("woff2"); font-weight: 700; font-display: swap; }
-@font-face { font-family: "Mondwest"; src: url("/fonts/Mondwest-Regular.woff2") format("woff2"); font-weight: 400; font-display: swap; }
-
@theme {
- /* ---- Hermes palette (dark teal, from live site) ---- */
- --color-background: #041C1C;
- --color-foreground: #ffe6cb;
- --color-card: #062424;
- --color-card-foreground: #ffe6cb;
- --color-primary: #ffe6cb;
- --color-primary-foreground: #041C1C;
- --color-secondary: #0a2e2e;
- --color-secondary-foreground: #ffe6cb;
- --color-muted: #083030;
- --color-muted-foreground: #8aaa9a;
- --color-accent: #0c3838;
- --color-accent-foreground: #ffe6cb;
- --color-destructive: #fb2c36;
- --color-destructive-foreground: #fff;
- --color-success: #4ade80;
- --color-warning: #ffbd38;
- --color-border: color-mix(in srgb, #ffe6cb 15%, transparent);
- --color-input: color-mix(in srgb, #ffe6cb 15%, transparent);
- --color-ring: #ffe6cb;
- --color-popover: #062424;
- --color-popover-foreground: #ffe6cb;
+ /* ---- Light palette ---- */
+ --color-background: #fafafa;
+ --color-foreground: #0f0f0f;
+ --color-card: #ffffff;
+ --color-card-foreground: #0f0f0f;
+ --color-primary: #6d5dfc;
+ --color-primary-foreground: #ffffff;
+ --color-secondary: #f4f4f5;
+ --color-secondary-foreground: #3f3f46;
+ --color-muted: #f4f4f5;
+ --color-muted-foreground: #71717a;
+ --color-accent: #f4f4f5;
+ --color-accent-foreground: #0f0f0f;
+ --color-destructive: #ef4444;
+ --color-destructive-foreground: #ffffff;
+ --color-success: #22c55e;
+ --color-warning: #f59e0b;
+ --color-border: #e4e4e7;
+ --color-input: #e4e4e7;
+ --color-ring: #6d5dfc;
+ --color-popover: #ffffff;
+ --color-popover-foreground: #0f0f0f;
/* ---- Font stacks ---- */
- --font-sans: "Mondwest", Arial, sans-serif;
- --font-mono: "Courier Prime", "Courier New", monospace;
- --font-display: "Mondwest", Arial, sans-serif;
- --font-expanded: "RulesExpanded", Arial, sans-serif;
- --font-compressed: "RulesCompressed", Arial, sans-serif;
+ --font-sans: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
+ --font-mono: "JetBrains Mono", "SF Mono", "Fira Code", "Cascadia Code", monospace;
+ --font-display: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
+ --font-expanded: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
+ --font-compressed: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
}
/* ---- Global body ---- */
body {
margin: 0;
- font-family: "Mondwest", Arial, sans-serif;
+ font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
background: var(--color-background);
color: var(--color-foreground);
-webkit-font-smoothing: antialiased;
@@ -61,8 +50,8 @@ body {
/* ---- Selection ---- */
::selection {
- background: var(--color-foreground);
- color: var(--color-background);
+ background: oklch(0.55 0.18 270);
+ color: #fff;
}
/* ---- Scrollbars (thin, subtle) ---- */
@@ -71,19 +60,19 @@ body {
scrollbar-color: transparent transparent;
}
*:hover {
- scrollbar-color: color-mix(in srgb, var(--color-foreground) 15%, transparent) transparent;
+ scrollbar-color: color-mix(in srgb, var(--color-foreground) 12%, transparent) transparent;
}
html, body {
- scrollbar-color: color-mix(in srgb, var(--color-foreground) 25%, transparent) transparent;
+ scrollbar-color: color-mix(in srgb, var(--color-foreground) 18%, transparent) transparent;
}
-::-webkit-scrollbar { width: 4px; height: 4px; }
+::-webkit-scrollbar { width: 5px; height: 5px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb {
- background: color-mix(in srgb, var(--color-foreground) 20%, transparent);
- border-radius: 2px;
+ background: color-mix(in srgb, var(--color-foreground) 14%, transparent);
+ border-radius: 10px;
}
::-webkit-scrollbar-thumb:hover {
- background: color-mix(in srgb, var(--color-foreground) 35%, transparent);
+ background: color-mix(in srgb, var(--color-foreground) 25%, transparent);
}
/* ---- Hide scrollbar utility ---- */
@@ -97,11 +86,12 @@ html, body {
/* ---- Code blocks ---- */
code {
- font-family: "Courier Prime", "Courier New", monospace;
+ font-family: "JetBrains Mono", "SF Mono", "Fira Code", monospace;
font-size: 0.85em;
padding: 0.15em 0.4em;
- border-radius: 0;
- background: color-mix(in srgb, var(--color-foreground) 8%, transparent);
+ border-radius: 4px;
+ background: #f0f0f3;
+ color: #5b21b6;
}
/* ---- Dither texture ---- */
@@ -136,18 +126,12 @@ code {
to { opacity: 0; transform: translateX(16px); }
}
-/* ---- Plus-lighter blend for headings ---- */
-.blend-lighter {
- mix-blend-mode: plus-lighter;
-}
-
/* ---- Font utilities ---- */
-.font-display { font-family: "Mondwest", Arial, sans-serif; }
-.font-expanded { font-family: "RulesExpanded", Arial, sans-serif; }
-.font-compressed { font-family: "RulesCompressed", Arial, sans-serif; }
-.font-courier { font-family: "Courier Prime", "Courier New", monospace; }
-.font-collapse { font-family: "Collapse", Arial, sans-serif; }
-.font-mono-ui { font-family: ui-monospace, "SF Mono", "Cascadia Mono", Menlo, monospace; }
+.font-display { font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; }
+.font-expanded { font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; }
+.font-compressed { font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; }
+.font-courier { font-family: "JetBrains Mono", "SF Mono", "Fira Code", monospace; }
+.font-mono-ui { font-family: "JetBrains Mono", "SF Mono", "Cascadia Mono", Menlo, monospace; }
/* ---- Subtle grain overlay for badges ---- */
.grain {
@@ -157,32 +141,32 @@ code {
content: "";
position: absolute;
inset: 0;
- opacity: 0.12;
+ opacity: 0.04;
pointer-events: none;
background: repeating-conic-gradient(currentColor 0% 25%, #0000 0% 50%) 0 0 / 2px 2px;
}
-/* ---- Global noise grain (canonical: color-dodge, #eaeaea, high density) ---- */
+/* ---- Subtle background texture (light) ---- */
.noise-overlay {
pointer-events: none;
position: fixed;
inset: 0;
z-index: 101;
- mix-blend-mode: color-dodge;
- opacity: 0.10;
- background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 512 512' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' fill='%23eaeaea' filter='url(%23n)' opacity='0.6'/%3E%3C/svg%3E");
+ mix-blend-mode: overlay;
+ opacity: 0.015;
+ background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 512 512' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' fill='%23999' filter='url(%23n)' opacity='0.5'/%3E%3C/svg%3E");
background-size: 512px 512px;
}
-/* ---- Vignette (canonical: top-left amber radial, lighten blend) ---- */
+/* ---- Warm glow — soft purple gradient for light theme ---- */
.warm-glow {
pointer-events: none;
position: fixed;
inset: 0;
z-index: 99;
- mix-blend-mode: lighten;
- opacity: 0.22;
- background: radial-gradient(ellipse at 0% 0%, rgba(255,189,56,0.35) 0%, rgba(255,189,56,0) 60%);
+ mix-blend-mode: multiply;
+ opacity: 0.25;
+ background: radial-gradient(ellipse at 20% 0%, rgba(109, 93, 252, 0.12) 0%, rgba(109, 93, 252, 0) 55%);
}
/* ---- Reduced motion ---- */
diff --git a/web/src/pages/AnalyticsPage.tsx b/web/src/pages/AnalyticsPage.tsx
index 9c3d6f99..cff33cc9 100644
--- a/web/src/pages/AnalyticsPage.tsx
+++ b/web/src/pages/AnalyticsPage.tsx
@@ -72,11 +72,11 @@ function TokenBarChart({ daily }: { daily: AnalyticsDailyEntry[] }) {
</div>
<div className="flex items-center gap-4 text-xs text-muted-foreground">
<div className="flex items-center gap-1.5">
- <div className="h-2.5 w-2.5 rounded-sm bg-[#ffe6cb]" />
+ <div className="h-2.5 w-2.5 rounded-sm bg-primary/60" />
Input
</div>
<div className="flex items-center gap-1.5">
- <div className="h-2.5 w-2.5 rounded-sm bg-emerald-500" />
+ <div className="h-2.5 w-2.5 rounded-sm bg-success" />
Output
</div>
</div>
@@ -104,12 +104,12 @@ function TokenBarChart({ daily }: { daily: AnalyticsDailyEntry[] }) {
</div>
{/* Input bar */}
<div
- className="w-full bg-[#ffe6cb]/70"
+ className="w-full bg-primary/50"
style={{ height: Math.max(inputH, total > 0 ? 1 : 0) }}
/>
{/* Output bar */}
<div
- className="w-full bg-emerald-500/70"
+ className="w-full bg-success/70"
style={{ height: Math.max(outputH, d.output_tokens > 0 ? 1 : 0) }}
/>
</div>
@@ -160,10 +160,10 @@ function DailyTable({ daily }: { daily: AnalyticsDailyEntry[] }) {
<td className="py-2 pr-4 font-medium">{formatDate(d.day)}</td>
<td className="text-right py-2 px-4 text-muted-foreground">{d.sessions}</td>
<td className="text-right py-2 px-4">
- <span className="text-[#ffe6cb]">{formatTokens(d.input_tokens)}</span>
+ <span className="text-primary">{formatTokens(d.input_tokens)}</span>
</td>
<td className="text-right py-2 pl-4">
- <span className="text-emerald-400">{formatTokens(d.output_tokens)}</span>
+ <span className="text-success">{formatTokens(d.output_tokens)}</span>
</td>
</tr>
);
@@ -209,9 +209,9 @@ function ModelTable({ models }: { models: AnalyticsModelEntry[] }) {
</td>
<td className="text-right py-2 px-4 text-muted-foreground">{m.sessions}</td>
<td className="text-right py-2 pl-4">
- <span className="text-[#ffe6cb]">{formatTokens(m.input_tokens)}</span>
+ <span className="text-primary font-medium">{formatTokens(m.input_tokens)}</span>
{" / "}
- <span className="text-emerald-400">{formatTokens(m.output_tokens)}</span>
+ <span className="text-emerald-600">{formatTokens(m.output_tokens)}</span>
</td>
</tr>
))}
diff --git a/web/src/pages/ConfigPage.tsx b/web/src/pages/ConfigPage.tsx
index 2e75e1d1..d3720056 100644
--- a/web/src/pages/ConfigPage.tsx
+++ b/web/src/pages/ConfigPage.tsx
@@ -333,7 +333,7 @@ export default function ConfigPage() {
</div>
) : (
<textarea
- className="flex min-h-[600px] w-full bg-transparent px-4 py-3 text-sm font-mono leading-relaxed placeholder:text-muted-foreground focus-visible:outline-none border-t border-border"
+ className="flex min-h-[600px] w-full bg-white px-4 py-3 text-sm font-mono leading-relaxed placeholder:text-muted-foreground focus-visible:outline-none border-t border-border"
value={yamlText}
onChange={(e) => setYamlText(e.target.value)}
spellCheck={false}
diff --git a/web/src/pages/CronPage.tsx b/web/src/pages/CronPage.tsx
index 418f3628..91dd8d8b 100644
--- a/web/src/pages/CronPage.tsx
+++ b/web/src/pages/CronPage.tsx
@@ -147,7 +147,7 @@ export default function CronPage() {
<Label htmlFor="cron-prompt">Prompt</Label>
<textarea
id="cron-prompt"
- className="flex min-h-[80px] w-full rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring"
+ className="flex min-h-[80px] w-full rounded-lg border border-input bg-white px-3 py-2 text-sm shadow-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1"
placeholder="What should the agent do on each run?"
value={prompt}
onChange={(e) => setPrompt(e.target.value)}
diff --git a/web/src/pages/SkillsPage.tsx b/web/src/pages/SkillsPage.tsx
index ab601c9f..1e13f762 100644
--- a/web/src/pages/SkillsPage.tsx
+++ b/web/src/pages/SkillsPage.tsx
@@ -403,7 +403,7 @@ export default function SkillsPage() {
{ts.description}
</p>
{ts.enabled && !ts.configured && (
- <p className="text-[10px] text-amber-300/80 mb-2">
+ <p className="text-[10px] text-amber-600 mb-2">
Setup needed
</p>
)}
diff --git a/web/src/pages/StatusPage.tsx b/web/src/pages/StatusPage.tsx
index 06fb7c25..4c958488 100644
--- a/web/src/pages/StatusPage.tsx
+++ b/web/src/pages/StatusPage.tsx
@@ -141,7 +141,7 @@ export default function StatusPage() {
</CardHeader>
<CardContent>
- <div className="text-2xl font-bold font-display">{value}</div>
+ <div className="text-2xl font-bold">{value}</div>
{badgeText && (
<Badge variant={badgeVariant} className="mt-2">
git apply hermes-dashboard-light-theme.patch
cd web && npx vite build
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment