Design system¶
Version 1.0 (rebuild after v0.1 prototype rejected — see postmortem). Supersedes the v0.1 zinc/cyan template.
Strategic Posture¶
This is not a Tailwind template. This is a tool that Lebanese PC builders should feel like they paid for. Reference quality bar: Linear (interaction polish), Stripe (gradient craft), PCPartPicker (data density), Vercel (typography rigor), Razer Origin (gamer cred without kitsch).
Forbidden defaults: zinc-950 + cyan-400 + bordered-card-grid pattern, generic Tailwind utilities applied without intention, system fonts (Inter, Roboto), purple-on-white gradient hero clichés, AI-generated-feeling stock layouts.
Brand Concept: "Engineered, with cedar"¶
The idea: A tool engineered like premium PC hardware itself — precise, technical, generous on detail — but with quiet warmth that signals "this was made in Beirut, by a Lebanese person, for Lebanese builders." The "961" in the name is the only overt patriotic gesture; everything else is implied through tonality.
Voice: Confident, technical, occasionally dry. Never marketing-speak. Examples:
| Avoid | Use |
|---|---|
| "Discover the best PC parts at amazing prices!" | "554 parts. 3 stores. Real prices. Real stock." |
| "Build your dream gaming rig today" | "Pick parts. Check fit. Click buy." |
| "Compare across hundreds of retailers" | "Compare across the three Lebanese retailers that matter." |
| "Trusted by gamers worldwide" | "Built in Beirut." |
Color System¶
Dark surface as primary (PC enthusiast audience leans dark mode), but with petrol blue undertones instead of pure black or zinc gray. This single decision differentiates from generic dark dashboards.
Core palette¶
/* Surfaces */
--surface-base: #0a0e14; /* petrol black — primary background */
--surface-raised: #11161f; /* card / panel background */
--surface-overlay: #1a2030; /* hover, modal background */
--surface-inset: #060a0f; /* inset wells, code blocks */
/* Text */
--text-primary: #f0e6d2; /* warm ivory — body text, headings */
--text-secondary: #a8a397; /* muted ivory — captions, metadata */
--text-tertiary: #6b6862; /* very muted — disabled, hints */
--text-inverse: #0a0e14; /* on light surfaces */
/* Accent — Cedar (the brand color) */
--cedar-50: #e8f0e3;
--cedar-200: #b3d09a;
--cedar-400: #7aa553;
--cedar-500: #5d8b3e; /* primary accent — buttons, links, focus */
--cedar-600: #4a6f31;
--cedar-800: #2d4a1c;
--cedar-glow: rgb(93 139 62 / 0.4); /* glow shadows */
/* Heat — used SPARINGLY for hot prices, deals, primary CTA */
--heat-400: #ff7a4d;
--heat-500: #ff5b1f;
--heat-600: #e84a14;
/* Semantic */
--success: #4ade80; /* in-stock indicator */
--warning: #fbbf24; /* compatibility warning */
--danger: #ef4444; /* incompatible, error */
--info: #60a5fa; /* neutral information */
/* Borders / dividers */
--border-subtle: rgba(240, 230, 210, 0.06);
--border-default: rgba(240, 230, 210, 0.12);
--border-emphasis: rgba(240, 230, 210, 0.20);
--border-cedar: rgba(93, 139, 62, 0.4);
Usage discipline:
- surface-base for body bg
- surface-raised for ALL cards/panels (subtle elevation, no hard borders)
- cedar-500 for the brand mark, primary buttons, links
- heat-500 ONLY for: best price highlight, primary CTA on landing, sale badges, "live" indicators
- Never use both cedar and heat in the same eyeline unless intentional
Typography¶
Three-font system. Fraunces (display) + Switzer (body) + JetBrains Mono (data).
Fraunces — Display (variable serif with personality)¶
Used for: hero headlines, section titles, page H1s, product model names in detail view, large numbers (totals, prices in summary).
Why: Variable serif with optical sizes, soft humanist character, distinctive "soft" feel that warms up the otherwise technical interface. NOT a Times Roman lookalike — has visible quirks (italic axis, soft serifs).
@import url('https://fonts.googleapis.com/css2?family=Fraunces:opsz,wght,SOFT,WONK@9..144,400;9..144,500;9..144,700;9..144,900&display=swap');
--font-display: 'Fraunces', Georgia, serif;
font-feature-settings: "ss01", "ss02", "ss04"; /* enable stylistic sets */
font-variation-settings: "opsz" 144, "SOFT" 50, "WONK" 0; /* tune for display */
Switzer — Body (geometric sans, FontShare)¶
Used for: body copy, navigation, button labels, form fields, table content (non-numeric).
Why: More distinctive than Inter or Geist. Slightly geometric, very legible at all sizes. From Indian Type Foundry via FontShare — free.
<link href="https://api.fontshare.com/v2/css?f[]=switzer@400,500,600,700&display=swap" rel="stylesheet">
--font-body: 'Switzer', -apple-system, system-ui, sans-serif;
font-feature-settings: "ss01", "cv11";
JetBrains Mono Variable — Data¶
Used for: prices ($549.00), specs (AM5, 7800X3D, 120W), retailer slugs, code, anything that needs digit alignment.
@import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;700&display=swap');
--font-mono: 'JetBrains Mono', 'SF Mono', Menlo, monospace;
font-feature-settings: "tnum", "cv01", "cv05", "cv09"; /* tabular numbers */
Type scale (modular, 1.25 ratio at desktop)¶
Display 1: 80px / line 0.95 / Fraunces 700 — landing hero only
Display 2: 60px / line 1.0 / Fraunces 700 — section openings
H1: 44px / line 1.1 / Fraunces 600 — page titles
H2: 32px / line 1.15 / Fraunces 600 — subsections
H3: 24px / line 1.25 / Switzer 600 — card titles
H4: 20px / line 1.3 / Switzer 600
Body L: 18px / line 1.55 / Switzer 400 — long-form
Body: 15px / line 1.55 / Switzer 400 — default
Body S: 13px / line 1.5 / Switzer 400 — captions, metadata
Mono L: 18px / line 1.4 / JetBrains 500 — large prices
Mono: 14px / line 1.4 / JetBrains 400 — table data
Eyebrow: 11px / line 1 / Switzer 600 / letter-spacing 0.1em / uppercase — labels
Spacing System¶
4px base. Use these tokens only:
--space-0: 0
--space-1: 4px (hairline)
--space-2: 8px (tight)
--space-3: 12px
--space-4: 16px (default)
--space-5: 20px
--space-6: 24px
--space-8: 32px (section internal)
--space-10: 40px
--space-12: 48px
--space-16: 64px (between sections)
--space-20: 80px
--space-24: 96px
--space-32: 128px (between major sections)
Touch targets minimum 44px.
Motion¶
Spring physics, never linear easing for user-initiated interactions.
// Framer Motion presets
const spring = { type: "spring", stiffness: 380, damping: 30 };
const springSlow = { type: "spring", stiffness: 200, damping: 35 };
const ease = [0.32, 0.72, 0, 1]; // custom cubic-bezier — sharp ease-out
// Standard durations
--motion-fast: 150ms // hover state changes
--motion-base: 240ms // most transitions
--motion-slow: 400ms // page elements
--motion-slower: 600ms // hero reveal staggers
Animation budget: one well-orchestrated landing page reveal (staggered 50ms between elements), one hover lift on cards (translateY -2px + shadow), spring on button clicks, page transitions on route change. NOT: animated emojis, bouncing arrows, parallax scrolling on every section.
Visual Effects¶
Gradient meshes (NOT solid color sections)¶
/* Hero background — petrol mesh with cedar undertones */
background:
radial-gradient(at 20% 0%, rgba(93,139,62,0.15) 0%, transparent 50%),
radial-gradient(at 80% 100%, rgba(255,91,31,0.08) 0%, transparent 50%),
radial-gradient(at 50% 50%, rgba(96,165,250,0.05) 0%, transparent 50%),
var(--surface-base);
Film grain overlay (3% opacity)¶
A <div> over the entire body with a noise SVG, low opacity, fixed position, pointer-events none. Adds analog warmth.
Cedar glow on focus / hover for primary CTAs¶
Number tickers¶
Important numbers (prices, counts, savings) animate from 0 to value on first viewport entry. Use motion's useMotionValue + spring.
Iconography¶
NOT emoji. Real icons. Use Lucide as base set (already shipped with shadcn) PLUS custom component-category icons drawn as SVG:
- CPU — pin grid pattern (8x8 dots)
- GPU — three rectangles (dual-fan card silhouette)
- Motherboard — square with slot lines
- RAM — DIMM stick with pin row
- Storage — M.2 stick OR 2.5" drive depending on type
- PSU — vented box with cable
- Case — chassis with mesh front
- Cooler — fan blade + heatsink fins
- Cedar leaf — used as brand mark accent
- Lebanon outline — used in landing footer
These give the brand visual differentiation. We're not a generic shop — we're a builder's tool.
Page Architecture¶
Information density philosophy¶
This is a TOOL, not a marketing site. Density is a feature, not a bug. Pages should pack useful info; emptiness signals "we don't have data" not "minimalism."
| Page | Density |
|---|---|
| Landing | LOW (editorial hero, generous whitespace, big imagery) |
| Browse | MEDIUM-HIGH (filter sidebar + dense card grid) |
| Product detail | HIGH (specs, prices, history, related) |
| Build page | VERY HIGH (table of slots, sticky totals, compatibility panel) |
| Build summary | MEDIUM (clear celebratory layout for the proud build) |
Layout grid¶
12-column grid at 1280px max content width, gutter 24px, padding 24px on mobile / 32px on tablet / 64px on desktop.
Break the grid intentionally on the landing page (overlap, asymmetry, full-bleed gradient sections).
Component Inventory¶
Foundation¶
- Button (primary/secondary/ghost, sm/base/lg, with optional icon, loading state)
- Badge (cedar/heat/info/success/warning/danger variants, sm/md sizes)
- Card (raised surface, optional hover-lift, optional border accent)
- Input (text, search, with icon, with prefix/suffix)
- Select / Dropdown
- Sheet (right-side drawer for filters, choose-component flow)
- Dialog (centered modal for confirmations, share)
- Toast (bottom-right notification)
- Skeleton (loading state for cards, tables, text)
- Tooltip
- Tabs
Domain¶
- PriceCell — formatted currency with optional change indicator
- StockBadge — animated dot + label
- RetailerLogo — circular avatar with initials fallback
- CompatStatus — green ✓ / amber ⚠ / red ✗ with reason tooltip
- SocketChip — mono badge for AM5/LGA1700/etc.
- PriceSparkline — Recharts mini line chart
- WattageMeter — bar showing current build wattage vs PSU rated
- ProductCard (browse view) — image + brand + model + spec row + price range
- ProductRow (build slot) — icon + label + selection or empty + actions
- PriceComparisonTable — full retailer table with sort/filter
- CartSplitVisual — retailer-grouped item cards with totals
Layout¶
- TopNav — logo, search command palette trigger, primary nav, account
- Sidebar — filter panel for browse, compatibility panel for build
- PageHeader — eyebrow + title + actions
- EmptyState — illustration + headline + supporting + action
- GradientMesh — animated SVG background
Accessibility Floor¶
- Color contrast WCAG AA minimum (verified on text-primary against surface-base = passes AAA)
- Focus indicators visible (cedar 2px outline outside element, never inside)
- All interactive elements keyboard navigable
- Skip-to-content link
- Screen reader semantic HTML
- Reduced-motion media query respected for all animations
Implementation Stack Additions (vs v0.1)¶
| Need | Tool | Why |
|---|---|---|
| Animation | Framer Motion | Spring physics, page transitions, scroll triggers |
| Component primitives | shadcn/ui (Dialog, Sheet, Command, DropdownMenu, Tabs, Toast, Skeleton, Tooltip, Slider, Checkbox) | Accessible Radix UI primitives we don't reinvent |
| Charts | Recharts | Price history sparklines, wattage bars |
| Icons | lucide-react | Already in shadcn ecosystem, comprehensive |
| Custom icons | hand-drawn SVG | Component category set |
| Fonts | Fraunces + Switzer + JetBrains Mono Variable | Distinctive, free, web-loaded |
| Forms | react-hook-form + zod | When we need real forms in M2 |
| State (build) | Zustand | Lightweight build state with localStorage persistence |
| Search | cmdk (via shadcn Command) | Spotlight-style command palette |
Page-Level Specifications¶
See sibling docs:
- Architecture → Overview — system architecture + diagrams
- Specs → 2026-04-25 aggregator design — original page-by-page design with layouts
- Plans → 2026-04-26 Month 1 prototype — task breakdown
Anti-Patterns Banned¶
These are explicitly REJECTED for 961tech v1.0:
- ❌ Bordered card grids on dark surfaces (the v0.1 mistake)
- ❌ Cyan-400 as the only accent color
- ❌ "Sticky CTA at bottom of viewport" hero pattern
- ❌ Three feature cards in a row with icons + 1-line titles + 1-line bodies
- ❌ "Trusted by 100+ companies" logo strips
- ❌ Animated arrows on buttons
- ❌ Auto-rotating testimonial carousels
- ❌ Step-by-step wizards for inherently iterative tasks (PC building)
- ❌ Empty space passed off as "minimalism"
- ❌ Lazy emoji 🚀 ✨ 💎 in product copy
- ❌ "Modern" gradients (purple-to-pink, cyan-to-blue)
- ❌ Pages without imagery (every page needs at least one rich visual element)
Iteration Discipline¶
Each page gets THREE iterations minimum: 1. Build to spec — implement against design doc 2. Self-criticize — open it, walk through, list everything that feels off 3. Rebuild what failed — fix the issues, often by re-doing entire sections
Then the build moves to the next page. Repeat. The site is never "done" — it's always in iteration N.