- dark, angular, elegant. no rounded corners. ever. (
rounded-noneeverywhere) - lowercase text is a deliberate style choice
- simple but pleasant ux: lucide icons, subtle transparency (
bg-black/50,bg-black/80) - zinc palette with thin borders and elegant accents
- minimal, not busy. let content breathe
@theme {
--color-primary: var(--color-zinc-700);
--color-secondary: var(--color-zinc-800);
--color-border: var(--color-zinc-600);
--color-destructive: var(--color-red-900);
--color-background: var(--color-black);
--color-warning: var(--color-yellow-900);
--color-input: var(--color-zinc-600);
--color-ring: var(--color-zinc-500);
--color-tabs-active: var(--color-zinc-800);
--color-popover: var(--color-black);
}- background: pure black
#000000 - text: light warm gray
rgb(216, 211, 220) - accents: zinc-600 borders, zinc-700/800 surfaces
- destructive: deep red-900
- overlays:
bg-black/70tobg-black/80
- headings:
Playfair Display SC(serif, small caps) - imported from google fonts - body:
Source Sans Pro(sans-serif) - imported from google fonts - tailwind config extends
fontFamily: { playfair: ['Playfair Display SC', 'serif'] } - utility class
.font-titlefor applying heading font inline - line-height: 1.2 for headings, 1.5 for body
- lives at
src/components/shadcn/with subdirs:ui/,hooks/,lib/ - import pattern:
import { Button } from "@/components/shadcn/ui/button" - utility:
cn()fromlib/utils.tsusingclsx+tailwind-merge - all components use
rounded-none(no border-radius anywhere)
button (class-variance-authority):
- default variant:
bg-black/80 text-zinc-200 border-primary border-1 hover:bg-zinc-800 - outline:
border border-primary shadow-sm hover:bg-accent - ghost:
hover:bg-accent - destructive:
bg-destructive/50 - custom variants:
bottom(border-b),top(border-t),animated(hover-scale) - default variant is
outline, notdefault - all buttons:
cursor-pointer,focus:ring-0,disabled:opacity-65
card: border border-border bg-card shadow, tight padding (p-2 content, p-4 header)
dialog: bg-background border border-border p-2, overlay bg-black/80, z-250
input: bg-transparent border border-input rounded-none, focus ring via ring-ring
tabs: rounded-none, active state bg-tabs-active
switch: rounded-none, unchecked bg-zinc-900, thumb bg-zinc-400 rounded-none
tooltip: bg-zinc-900/95 text-xs, z-500
scroll-area: custom enableScrollbar prop, thumb bg-border rounded-none
sheet: overlay bg-black/70
tailwindcss-animate- for enter/exit animations on dialogs, popovers, etc.@tailwindcss/typography- prose stylingtailwind-scrollbar- custom scrollbar styling
.hover-scale {
transition: transform 300ms cubic-bezier(0.4, 0, 0.2, 1);
}
.hover-scale:hover { transform: scale(1.05); }
.animate-shimmer {
animation: shimmer 1.5s ease-in-out infinite;
/* background-position animation for loading states */
}tailwindcss (v4)
tailwindcss-animate
@tailwindcss/typography
tailwind-scrollbar
class-variance-authority
clsx
tailwind-merge
@radix-ui/react-* (dialog, tabs, scroll-area, switch, tooltip, popover, etc.)
lucide-react
- never use rounded - always
rounded-none - use lowercase text - deliberate style
- prefer tailwind for styling, CSS only when tailwind gets too verbose
- zinc palette with thin borders for everything
bg-black/50-style transparency for layered surfaces- lucide icons for all iconography
- no
anytypes - useunknownif absolutely necessary - shadcn components for all UI primitives, don't reinvent
- focus:ring-0 or minimal ring styling, not default blue rings
the current project uses:
- pure custom CSS (1600+ lines in styles.css) with CSS variables
- no tailwind, no component library, no shadcn
- react + mobx + vite
to adopt this style we need to:
- add tailwind v4 + all plugins
- copy over the full
shadcn/component directory - replace custom CSS with tailwind classes using the cnvrg theme
- swap all custom components to use shadcn primitives
- add google fonts (Playfair Display SC, Source Sans Pro)
- add lucide-react for icons