Skip to content

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

.btn-primary:hover {
  box-shadow: 0 0 0 1px var(--cedar-400), 0 12px 32px -8px var(--cedar-glow);
}

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:


Anti-Patterns Banned

These are explicitly REJECTED for 961tech v1.0:

  1. ❌ Bordered card grids on dark surfaces (the v0.1 mistake)
  2. ❌ Cyan-400 as the only accent color
  3. ❌ "Sticky CTA at bottom of viewport" hero pattern
  4. ❌ Three feature cards in a row with icons + 1-line titles + 1-line bodies
  5. ❌ "Trusted by 100+ companies" logo strips
  6. ❌ Animated arrows on buttons
  7. ❌ Auto-rotating testimonial carousels
  8. ❌ Step-by-step wizards for inherently iterative tasks (PC building)
  9. ❌ Empty space passed off as "minimalism"
  10. ❌ Lazy emoji 🚀 ✨ 💎 in product copy
  11. ❌ "Modern" gradients (purple-to-pink, cyan-to-blue)
  12. ❌ 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.