Back to portfolio

Design System

Page System v1.0

Ember Design System

The foundations, tokens, components, and patterns behind this portfolio.

How it was built: with AI coding agents (Cursor and Claude Code). I set the tokens, the rules on this page, and the copy; the agents write code against them.

Contents

Foundations

Design Principles

Minimal

Every element serves a purpose. No decorative gradients, no unnecessary shadows.

Consistent

Same patterns, same tokens, same behavior across all pages and components.

Accessible

High contrast ratios, semantic HTML, keyboard navigation support.

Quick Reference

UseColorToken/Value
Brand/Accent
Orange
#fe4b00
Background
Near black / off-white
bg-background · oklch(0.08 0 0) / #f7f7f7
Primary Text
White / ink
text-foreground · oklch(0.98 0 0) / #171717
Secondary Text
Slate 300-500
text-slate-300 to text-slate-500
Cards/Surfaces
Background + 1px border
bg-background border-border

Themes

Dark is the default. The toggle in the corner switches to light; components use the same tokens in both.

TokenDarkLight
--backgroundoklch(0.08 0 0)#f7f7f7
--foregroundoklch(0.98 0 0)#171717
--cardoklch(0.12 0 0)#ffffff
--secondaryoklch(0.18 0 0)#ececec
--muted-foregroundoklch(0.65 0 0)#5c5c5c
--borderoklch(0.22 0 0)#e2e2e2
--brand#fe4b00#fe4b00

Color Palette

Brand Orange

Primary accent color used for CTAs, highlights, and interactive elements.

Orange 900

#7a2500

Orange 700

#b53800

Orange 500 (Primary)

#fe4b00

Orange 300

#ff7a3d

Orange 100

#ffb899

Usage: Use Orange 500 for primary actions, Orange 700 for hover states, Orange 900 for active states. Orange 100-300 for backgrounds with low opacity.

Neutrals (Slate)

Monochromatic scale for backgrounds, text, and borders.

Slate 900

#0f172a

Slate 800

#1e293b

Slate 700

#334155

Slate 600

#475569

Slate 500

#64748b

Slate 400

#94a3b8

Slate 300

#cbd5e1

Slate 200

#e2e8f0

Slate 100

#f1f5f9

White

#ffffff

Background

oklch(0.08)

Card

oklch(0.12)

Semantic Usage

Text Colors

Primary Texttext-white
Secondary Texttext-slate-300
Tertiary Texttext-slate-400
Muted Texttext-slate-500
Accent Texttext-[#fe4b00]

Surface Colors

Page Backgroundbg-background
Card Surfacebg-background + border-border
Quiet Fillbg-secondary/30
Borderborder-border
Accent Borderborder-[#fe4b00]

Typography

Font Family

Sans Serif

Geist

Primary typeface for all UI elements, headings, and body text.

font-sans

Monospace

Geist Mono

Used for code snippets, technical values, and tokens.

font-mono

Type Scale

Displaytext-7xl / 72px
Heading 1text-5xl / 48px
Heading 2text-3xl / 30px
Heading 3text-xl / 20px
Body Largetext-lg / 18px
Bodytext-base / 16px
Smalltext-sm / 14px
Extra Smalltext-xs / 12px

Font Weights

Regular

font-normal / 400

Medium

font-medium / 500

Semibold

font-semibold / 600

Bold

font-bold / 700

Spacing & Layout

Spacing Scale

gap-2
8px
gap-4
16px
gap-6
24px
gap-8
32px
gap-12
48px
gap-16
64px
gap-24
96px

Layout Constraints

Max Widths

Contentmax-w-6xl (1152px)
Text Blockmax-w-2xl (672px)
Narrowmax-w-md (448px)

Border Radius

Square
0 · cards, images, buttons, inputs, tabs
Round
rounded-full · avatars, dots, the call badge

Components

Buttons

Primary: bg-[#fe4b00] hover:bg-[#b53800] active:bg-[#7a2500]

Badges

PrimaryOutlineSecondary

Cards

Card Title
Card description with muted text color.

Card content goes here.

Accent Card
Card with accent border.

Used for highlighted content.

Form Elements

Tabs

Content for tab 1

Avatars & Tooltips

Patterns

Section Header

Label

Section Title

Section description with muted text color for secondary information.

Label: text-[#fe4b00] text-sm font-medium uppercase tracking-wider

Content Card Pattern

Category

Card Title

Description text explaining the content or feature.

Pattern: border-l-2 border-[#fe4b00] with category label

List with Icons

  • First item
  • Second item
  • Third item
Icon: text-[#fe4b00], Text: text-slate-300

Stats Grid

7+

Products

15

Team members

3

Years

100%

Consistency

Design Tokens

CSS Custom Properties

:root {
  /* Light theme */
  --background: #f7f7f7;
  --foreground: #171717;
  --card: #ffffff;
  --secondary: #ececec;
  --muted-foreground: #5c5c5c;
  --border: #e2e2e2;
  --brand: #fe4b00;
  --ring: #fe4b00;

  /* Radius: square everywhere. Only avatars, dots and the call badge are round. */
  --radius: 0;
}

.dark {
  /* Dark theme (default) */
  --background: oklch(0.08 0 0);
  --foreground: oklch(0.98 0 0);
  --card: oklch(0.12 0 0);
  --secondary: oklch(0.18 0 0);
  --muted-foreground: oklch(0.65 0 0);
  --border: oklch(0.22 0 0);
}

Usage Guide

Do's

  • Use #fe4b00 for primary actions and key highlights
  • Maintain high contrast with white text on dark backgrounds
  • Use slate-400 for secondary/descriptive text
  • Apply opacity (50%) to card backgrounds for depth
  • Keep borders subtle with slate-700/50

Don'ts

  • ✕Don't use gradients for decorative purposes
  • ✕Don't introduce colors outside the palette (no red, green, blue, purple)
  • ✕Don't use orange for large background areas
  • ✕Don't mix different opacity levels inconsistently
  • ✕Don't use pure black (#000) - use bg-background instead

Ember Design System v1.0

Back to portfolio