A modern, clean, and highly functional interface designed for an AI Agent platform. The design emphasizes a "high-contrast, flat" aesthetic. It moves away from mushy, ubiquitous soft shadows (shadow-sm) and brand-colored primary buttons, favoring a tempered base palette with soft whites, light greys, and charcoal blacks. Brand colors are used extremely sparingly for distinct active states and primary conversion actions (like the chat "Send" button).
- Primary / Brand (
--primary,--brand): Scheme-aware brand accent. It drives explicit brand actions, active indicators, and status dots. Default filled controls should use pale natural surfaces from the base palette instead of brand tint. - Primary Foreground (
#fafafa): Used heavily as the background for sidebars (Navigation, Session List, Metadata) to separate them from the main content area. - Background (
--background): Soft off-white, used for the central chat area, cards, alerts, and major input fields. Avoid pure white unless an asset or overlay requires it. - Foreground (
--foreground): Charcoal black. Now acts as the default visual weight for standard controls and default badges. Avoid pure black for normal UI fills. - Muted Foreground (
#737373): Mid-grey, extensively used for timestamps, secondary labels, placeholders, and inactive icons. - Accent (
#f5f5f5): Light grey, used for hover states, secondary buttons, code/badge backgrounds, and model selectors. - Border (
#e5e5e5): Very light grey, used uniformly for all structural dividers and component borders. - Destructive (
--destructive): Scheme-aware critical action color. Used exclusively for text or icons in critical actions (e.g., delete). It does not use raw colored backgrounds (e.g., nobg-red-50). - Semantic Colors: Status, event, capability, diff, terminal, and chart colors must use global tokens (
--success,--warning,--success-solid-foreground,--warning-solid-foreground,--info,--event-*,--capability-*,--diff-*,--terminal-*,--chart-*) rather than hardcoded Tailwind color families. If component states need more colors, extend the global palette tokens rather than adding component-specific color namespaces. - Color Schemes: Palettes are selected with
html[data-color-scheme]and must provide light and dark values for the full semantic set. The default scheme ismemoh.
- Headline Font: Inter Variable / Inter / MiSans / PingFang SC / Hiragino Sans GB / Microsoft YaHei UI / Noto Sans SC (the
--font-sansstack instyle.css; there is no Japanese-specific face — CJK glyphs fall through to the same Simplified-Chinese-tuned stack). - Body Font: same as Headline (
--font-sans). - Mono Font: unset in the library — falls through to Tailwind's default stack (
ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; Menlo is a fallback member, not the primary face). Web additionally lets users override--font-monoat runtime via Settings → Typography (apps/web/src/store/settings/typography.ts), defaulting toui-monospace, monospace.
Headlines and key labels use medium/semibold weights. Body text uses regular weight at 14px. Inputs size via the size prop's token ladder, not a fixed value — sm uses text-body (12px), default uses text-label (13px), lg uses text-control (14px); see sizeClass in Input.vue. Secondary information uses 11px or 12px.
The system employs a bimodal elevation strategy:
- Absolutely Flat (Zero Elevation): Interactive and atomic elements like Buttons, Inputs, Alerts, Badges, and Collapsibles have zero shadows. The default
shadow-smfrom Shadcn must be stripped out. Hierarchy is defined purely by 1px borders and background contrast. - High Floating (Shadow-lg/md):
- Large layout containers that sit above the main canvas (like a central Login
Card) use a pronouncedshadow-lgto starkly differentiate themselves from the flat UI underneath. - Popovers, Dropdowns, and Combobox menus use a tightly controlled
shadow-mdwithout thick borders.
- Large layout containers that sit above the main canvas (like a central Login
- Avatars:
size-8(32px)rounded-full,overflow-hidden,shrink-0; the size is overridable per call site viaclass(e.g.class="size-6"/size-10"). Fallback is a paired step of the warm-gray ramp —bg-[--accent-gray-soft-active]fill +text-[--accent-gray-deep]font-mediuminitials, centered andselect-none. (The oldbg-muted/text-muted-foregroundwas too light to read as a present circle and the cool muted-foreground initials looked murky; the ramp pair gives a deliberate placeholder, not an empty/disabled blob.) Still neutral — no per-identity accent tint. Status dots/badges are composed at the call site and need a 2px knockout border matching the surface behind the avatar. - Badges: 4px radius (
rounded-sm). Default usessecondary/secondary-foregroundwithborder-border. Secondary usesaccent/foreground. Destructive, success, and warning map to global status tokens. Outline usesbackground/border/foreground. Supportssize="sm"(text-[11px] px-2) alongside default. - BadgeCount: Circular numeric counter.
rounded-full,h-[18px] min-w-[18px] px-1,text-[11px] font-medium. Uses the same base/status mapping as Badge. Values above 99 display as "99+". - Buttons:
- Default / Primary: 8px radius, charcoal fill (
--btn-primary) with hover/press ramps on the pseudo-element shell. This is the standard high-emphasis action;defaultandprimaryare visual aliases. - Outline / Secondary: 8px radius, transparent rest state with a 1px inset ring, gray hover fill, and shell-only press scale.
outlineandsecondaryare visual aliases. - Ghost: No chrome at rest; soft gray hover fill. Use for toolbar/icon actions that should not carry standalone affordance.
- Destructive: Text/icon turns destructive on hover with a light destructive hover fill; avoid solid red buttons for normal destructive actions.
- Link: Muted text by default, foreground on hover, with underline feedback. Avoid brand purple for ordinary text links.
- Grouped (
ButtonGroup): Unified outer border (border-border, 8px radius). Internal items divided byborder-rorborder-b, no individual borders or radiuses. - Brand: Use
variant="brand"only for rare brand-colored actions (for example the chat Send button), following brand scarcity.
- Default / Primary: 8px radius, charcoal fill (
- In-capsule icon affordance (the X on a tag/chip, a clear button inside a pill): a small icon button (
size-4,size-3lucide glyph) that follows the shape of its host container. This is a deliberate split from the standalone ghost icon Button:- Inside a rounded-rectangle surface (toolbar, input row, card) the hover chip is a rounded rectangle (matches the host's
rounded-md). - Inside a pill / capsule (a tag chip, a count-style pill) the hover chip is a pure circle (
rounded-full) — never a rounded rectangle. The hover chip must echo the curvature of the thing it sits in. - Colour is never hand-rolled. The hover fill deepens along the same ramp the host capsule is built from: a gray chip (
--accent-gray-soft-active) deepens to that ramp's next stop (--accent-gray-border). Do not borrow the standalone ghost--btn-ghost-hoverhere — it is tuned for a white page and disappears on an already-tinted chip. Icon ismuted-foregroundat rest,foregroundon hover/focus.
- Inside a rounded-rectangle surface (toolbar, input row, card) the hover chip is a rounded rectangle (matches the host's
- Inputs: Flat design. 1px
border, purebackgroundfill, 8px/10px outer radius. Text sizes via thesizeprop (sm12px /default13px /lg14px), never a fixed 16px. Focus is not a ring — the 1px field edge swaps color in place (--field-edge-rest→--field-edge-solid, a near-black ~0.78-alpha hairline) on focus; an outer ring or a grown border width is the anti-pattern (seepackages/ui/AGENTS.md§ Borders & field edge). - Checkboxes/Radios: Flat, soft background (
bg-background). 1pxborder. The checked state marker (tick/dot) isforeground(charcoal), avoiding brand colors. - Separators: Uniformly use the 1px
bordercolor. Do not use padding/margins that detach them from the container edges (e.g., use full widthborder-bin menus instead of<Separator mx-1>). - Skeleton: Flat
bg-mutedblock,rounded-lg. The loading shimmer is a single synchronized seam across a whole cluster (avatar + lines read as one loading surface, never independent per-block pulses) — the "one paper, many windows" model. Implementation lives entirely instyle.csson[data-slot="skeleton"]: a two-close-gray gradient (--muted→--skeleton-mid→--muted) on a viewport-anchored sheet (background-attachment: fixed), tiled at--skeleton-tile(640px) and repeated, animated by exactly one tile width so it loops seamlessly. Because every block samples the same viewport-anchored sheet by its own position, the seam stays in sync without any wrapper component. Tile narrower than a typical row → a fresh seam revisits each cluster every cycle (short gap, not a viewport-wide wait). Tune speed via the2sduration, gap via--skeleton-tile. Reduced-motion freezes to flat--muted. Two deliberate trade-offs of thefixedtechnique: (1) iOS Safari ignoresbackground-attachment: fixedand degrades to element-anchored — the shimmer still animates but loses cross-block sync there; (2) atransform/filter/will-changeancestor re-anchors thefixedsheet to that box instead of the viewport (sync holds within the subtree, but tile size/gap is then relative to that box). Both are acceptable for a Chromium desktop-first product; do not "fix" this into a per-element gradient — that reintroduces the independent-pulse look this avoids.
- Cards: The exception to the flat rule. 12px radius (
rounded-xl), purebackground, 1pxborder, and strongshadow-lg. Content spacing is tight (p-6, with 6px gap between title and description). - Alerts: Flat (
bg-background), 1pxborder, 10px radius (rounded-[10px]). No variant-specific colored backgrounds; errors use red text/icons but keep the white background. - Collapsible: Flat sub-panels.
bg-backgroundinside aborder-bordercontainer, items divided byborder-b(no bottom border on last child). Usesfont-monofor code-related items. - Dropdowns / Popovers / Comboboxes:
bg-backgroundwithborder-borderandshadow-md.- 8px outer radius.
- Items use 4px inner radius and
text-sm font-normal text-foreground. - Hover states use
bg-accentandtext-foreground(no brand color tints). - Group separators must be full-bleed
border-b.
- Breadcrumb: Minimalist. 14px icons, 4px-6px gaps. Active page is
text-foreground font-normal, inactive istext-muted-foreground. - Sidebar:
- Container uses
primary-foregroundbackground. - Active items use a
sidebar-accentbackground andfont-mediumweight (no colored indicator bar or ring).
- Container uses
- Global:
rounded-lg(8px),p-4,shadow-none,gap-4. - Variants:
- Default:
bg-background, no border. - Outline:
bg-background+border border-border. - Muted:
bg-accent, no border.
- Default:
- Default page buttons:
bg-background border border-border text-foreground,rounded-lg,size-9. - Active/current page:
bg-foreground text-background border-foreground(black bg, white text — no brand purple). - Hover:
hover:bg-accent. - Disabled:
opacity-50 text-muted-foreground. - Previous/Next: ghost style, transparent bg, hover
bg-accent.
- Sonner (Toast Notifications): Uses
bg-backgroundwithborder border-borderandshadow-md. Border radius isvar(--radius-lg)(10px). Title:text-sm font-medium text-foreground. Description:text-xs text-muted-foreground. Status icons aresize-4. Action buttons usebg-foreground text-background rounded-sm text-xs font-medium. Supports 6 states: default (with action button), loading (spinner), success, info, warning, error. - Table: Wrapped in a container with
border border-border rounded-sm(6px). Header row height 41px withpy-[10px], data rows 38px withpy-[8.5px]. Footer usesbg-muted/50. Empty state centers an icon +text-muted-foregroundmessage inh-[204px]. Caption is centeredtext-sm text-muted-foreground. - TagsInput: Flat design.
rounded-lg(no shadow). Focus state usesring-ring/20 ring-2(notring-[3px]). - Chat Input (Main Area):
- Flat container (
shadow-none),border-border, 10px radius. - Divided horizontally by top/bottom 1px borders (
border-t,border-b). - Send button uniquely retains
bg-primaryfor high conversion focus. - Model selector (Badge style) floats inside the top border area, using
bg-accentorbg-backgrounddepending on state.
- Flat container (
- OTP Input (PinInput): Flat group built on reka-ui
PinInput. Each cell issize-9 bg-background text-sm shadow-none. The first cell getsborder border-border rounded-l-lg, middle cells useborder-y border-r border-border(no left border to avoid doubling), and the last cell addsrounded-r-lg. Focus state appliesborder-2 border-ring(dark ring, not primary purple). Supports an optionalPinInputSeparatorbetween groups.
To ensure visual consistency when generating images or extrapolating designs via AI based on this system, strictly adhere to the following composition rules:
- The "Flat Atom" Law: If it's a basic interactive element (button, badge, input, toggle, checkbox), it cannot have a shadow. It must rely on tokenized borders and background contrast (
--backgroundvs--accentvs--foreground). - The "Menu Underline" Law: Whenever rendering a list of items inside a container (Dropdowns, Comboboxes, Sidebar Sub-menus, Collapsibles), items must be divided by a full-width, 1px horizontal line (
border-b), terminating cleanly on the last item. Do not leave floating separators with margins. - The "Monochrome Hover" Law: Focus and hover states for secondary items must use
bg-accentandtext-foreground. Never apply the brand purple (#8b56e3) as a background highlight for menus. - The "Bimodal Elevation" Trigger: Only use heavy, soft shadows (like
shadow-lg) when rendering a standalone focal piece (like a login modal or a central dashboard card) that sits distinctly above a complex, flat background layer. - The "Brand Scarcity" Law: The scheme brand color (
--brand/--primary) is the most expensive pixel on the screen. It can only be used for:- The absolute primary completion action on a screen (e.g., the Chat "Send" button).
- Micro-indicators of "current active state" (e.g., a 2px vertical bar next to an active sidebar menu item, or a 5px status dot).
- Do use
bg-secondarywithborder-borderfor standard filled controls; reservebg-primary/bg-brandfor explicit brand actions and high-emphasis CTAs. - Don't use
shadow-smon buttons, inputs, or alerts. Keep atomic components strictly flat. - Do use
shadow-lgfor large focal cards to make them pop against the flat UI. - Don't use colored backgrounds for Alert or Badge variants (like
bg-red-50). Keep them white and use text/icon color to convey meaning (or solid red for destructive badges). - Do maintain the 1px
#e5e5e5(--border) across all structural dividing lines, ensuring they connect edge-to-edge (no floating separators). - Don't use primary colors for hover or active states in standard dropdowns and menus; stick to
bg-accentandtext-foreground.