# Pulse Design System

**Version:** 1.0  
**Last Updated:** 2026-02-06  
**Maintained by:** Ciphera Design Team

---

## Overview

This document defines the visual language and design patterns for Pulse Analytics. All components and pages should follow these standards to ensure consistency, accessibility, and brand alignment.

---

## 🎨 Colors

### Brand Colors

```css
/* Primary Brand Color */
--brand-orange: #FD5E0F;
--brand-orange-hover: #E54E00; /* Darker for hover states */

/* Injected by @ciphera-net/ui preset — use in SVG, Recharts, rgba() */
--color-brand-orange: #FD5E0F;
--color-brand-orange-rgb: 253, 94, 15; /* Used by .glow-orange utility; also for custom rgba(var(--color-brand-orange-rgb), 0.5) */

/* Usage */
- Primary CTAs, links, focus rings
- Accent elements, badges
- Never use for large backgrounds (too vibrant)
- var(--color-brand-orange) for SVG/Recharts where Tailwind classes don't apply
```

### Neutral Scale

Using Tailwind's neutral palette (50-950):

| Token | Light Mode | Dark Mode | Usage |
|-------|------------|-----------|--------|
| `neutral-50` | #FAFAFA | - | Subtle backgrounds |
| `neutral-100` | #F5F5F5 | - | Card backgrounds, disabled states |
| `neutral-200` | #E5E5E5 | - | Borders, dividers |
| `neutral-300` | #D4D4D4 | - | Borders (hover) |
| `neutral-400` | #A3A3A3 | #A3A3A3 | Secondary text (dark mode) |
| `neutral-500` | #737373 | - | Tertiary text, placeholders |
| `neutral-600` | #525252 | - | Body text (light mode) |
| `neutral-700` | #404040 | - | - |
| `neutral-800` | #262626 | #262626 | Borders, backgrounds (dark mode) |
| `neutral-900` | #171717 | #171717 | Headings, primary text |
| `neutral-950` | #0A0A0A | - | - |

### Semantic Colors

```css
--color-success: #10B981; /* Green for success states */
--color-warning: #F59E0B; /* Amber for warnings */
--color-error: #EF4444;   /* Red for errors, destructive actions */
```

### Color Usage Rules

**Text Colors:**
- **Headings:** `text-neutral-900 dark:text-white`
- **Body text:** `text-neutral-600 dark:text-neutral-400`
- **Secondary text:** `text-neutral-500 dark:text-neutral-400`
- **Tertiary/disabled:** `text-neutral-400 dark:text-neutral-500`
- **Links:** `text-brand-orange hover:text-brand-orange-hover`

**Backgrounds:**
- **Page:** `bg-white dark:bg-neutral-900`
- **Cards:** `bg-white dark:bg-neutral-900`
- **Subtle sections:** `bg-neutral-50 dark:bg-neutral-800/50`
- **Overlays:** `bg-white/80 dark:bg-neutral-900/80` (with backdrop-blur)

**Borders:**
- **Standard:** `border-neutral-200 dark:border-neutral-800`
- **Subtle:** `border-neutral-200/50 dark:border-neutral-800/50`
- **Focus rings:** `ring-brand-orange`
- **Danger actions:** `border-red-200 dark:border-red-900`

---

## 📝 Typography

### Font Family

```tsx
font-family: 'Plus Jakarta Sans', system-ui, sans-serif
```

Loaded via Next.js `next/font/google` in root layout.

### Heading Scale

| Element | Size (Mobile → Desktop) | Weight | Usage |
|---------|-------------------------|--------|-------|
| **H1 (Marketing)** | `text-4xl → text-5xl` | `font-bold` | Landing pages, about, FAQ, installation |
| **H1 (Hero)** | `text-5xl → text-7xl` | `font-bold` | Home page hero only |
| **H1 (App)** | `text-2xl` | `font-bold` | Dashboard, settings, app pages |
| **H2 (Section)** | `text-2xl` | `font-bold` | Major page sections |
| **H2 (Panel)** | `text-xl` | `font-semibold` | Panel headers (realtime, modals) |
| **H3 (Section)** | `text-lg` | `font-semibold` | Dashboard widgets, subsections |
| **H3 (Card)** | `text-xl` | `font-bold` | Feature cards, integration cards |
| **H4 (Label)** | `text-base` | `font-semibold` | Footer sections, small headers |

### Body Text

| Size | Class | Usage |
|------|-------|-------|
| **Large** | `text-xl` | Hero descriptions, intro paragraphs |
| **Base** | `text-base` (default) | Body text, card descriptions |
| **Small** | `text-sm` | Help text, labels, metadata |
| **Micro** | `text-xs` | Badges, timestamps, fine print |

### Font Weights

- `font-bold` (700): H1, H2, card titles, stat values
- `font-semibold` (600): H2 panels, H3 sections, buttons
- `font-medium` (500): Links, labels, secondary headings
- `font-normal` (400): Body text

### Line Height

- **Headings:** Default tight (`leading-tight` or none)
- **Body:** `leading-relaxed` for readability

### Text Color Patterns

```tsx
// Headings
className="text-neutral-900 dark:text-white"

// Body text (most readable)
className="text-neutral-600 dark:text-neutral-400"

// Secondary/helper text
className="text-neutral-500 dark:text-neutral-400"

// Disabled/placeholder
className="text-neutral-400 dark:text-neutral-500"
```

---

## 📏 Spacing System

### Padding Scale

| Value | Size | Usage |
|-------|------|-------|
| `p-3` | 12px | Icon containers, compact badges |
| `p-4` | 16px | Card headers, small cards, stat displays |
| `p-6` | 24px | Standard cards, forms, modals |
| `p-8` | 32px | Feature cards, spacious sections |
| `p-10` | 40px | Page containers |
| `p-12` | 48px | Empty states, hero sections |

### Vertical Spacing (Sections)

| Value | Size | Usage |
|-------|------|-------|
| `py-8` | 32px | App page containers |
| `py-10` | 40px | Standard pages |
| `py-16` | 64px | Content sections |
| `py-20` | 80px | Marketing hero sections |

### Gaps (Flexbox/Grid)

| Value | Size | Usage |
|-------|------|-------|
| `gap-2` | 8px | Icon+text pairs, inline elements |
| `gap-3` | 12px | Button groups, small layouts |
| `gap-4` | 16px | Form fields, button bars |
| `gap-6` | 24px | Card grids, main layouts |
| `gap-8` | 32px | Large section spacing |

### Margins

| Value | Usage |
|-------|-------|
| `mb-2` to `mb-4` | Between related elements |
| `mb-6` to `mb-8` | Between sections |
| `mb-16` to `mb-32` | Major page divisions |

---

## 🔲 Border Radius

| Element | Radius | Class | Example |
|---------|--------|-------|---------|
| **Cards** | 16px | `rounded-2xl` | Dashboard cards, feature cards |
| **Buttons** | 12px | `rounded-xl` | Primary, secondary buttons |
| **Inputs** | 8px | `rounded-lg` | Text inputs, selects, textareas |
| **Tabs** | 8px | `rounded-lg` | Tab buttons |
| **Badges** | Full | `rounded-full` | Status badges, tags |
| **Small UI** | 8px | `rounded-lg` | Small buttons, icons |

**Rule:** Larger elements = larger radius. Cards are most prominent, so `rounded-2xl`.

---

## 🎭 Shadows

### Shadow Scale

```tsx
// Subtle (cards at rest)
shadow-sm

// Medium (hover states)
shadow-md, shadow-lg

// Prominent (elevated elements, popovers)
shadow-xl, shadow-2xl

// Glow effects (CTAs)
shadow-lg shadow-brand-orange/20
```

### Usage Examples

```tsx
// Card at rest
className="rounded-2xl border border-neutral-200 dark:border-neutral-800 shadow-sm"

// Card hover
className="hover:shadow-xl hover:-translate-y-1 transition-all"

// Primary CTA
className="shadow-lg shadow-brand-orange/20"
```

---

## 🎯 Focus States

### Standard Focus Pattern

For most interactive elements:
```tsx
focus:outline-none focus:ring-2 focus:ring-brand-orange focus:ring-offset-2
```

### Compact Pattern (Links, Small Elements)

```tsx
focus:outline-none focus:ring-2 focus:ring-brand-orange focus:rounded
```

### Danger Actions (Delete, Reset)

```tsx
focus:outline-none focus:ring-2 focus:ring-red-500 focus:ring-offset-2
```

### Inset Focus (Selected Elements)

```tsx
focus:outline-none focus:ring-2 focus:ring-brand-orange focus:ring-inset
```

**Rule:** ALL interactive elements must have a visible focus state for keyboard accessibility (WCAG 2.1 Level AA).

---

## 🧩 Custom CSS Classes

**Location:** `styles/globals.css`

### `.card-glass`

Glass card effect with backdrop blur (premium feel):
```css
.card-glass {
  @apply bg-white/80 dark:bg-neutral-900/80;
  @apply backdrop-blur-xl;
  @apply border border-neutral-200/50 dark:border-neutral-800/50;
  @apply rounded-2xl;
  @apply transition-all duration-300 ease-out;
}
```

**Usage:** Feature cards on home page, pricing cards

---

### `.gradient-text`

Orange gradient for emphasized text:
```css
.gradient-text {
  @apply bg-gradient-to-r from-brand-orange to-brand-orange-hover bg-clip-text text-transparent;
}
```

**Usage:** Hero headlines ("privacy-conscious" on home page)

---

### `.badge-primary`

Primary badge style (orange theme):
```css
.badge-primary {
  @apply inline-flex items-center gap-1.5 px-3 py-1 rounded-full text-xs font-semibold uppercase tracking-wider;
  @apply bg-brand-orange/10 text-brand-orange border border-brand-orange/20;
}
```

**Usage:** "Privacy-First Analytics" badge, "FAQ" badge, page indicators

---

### `.bg-grid-pattern`

Subtle dot grid background:
```css
.bg-grid-pattern {
  background-image: radial-gradient(circle at 1px 1px, currentColor 1px, transparent 0);
  background-size: 32px 32px;
}
```

**Usage:** Marketing page backgrounds (with radial mask for fade effect)

---

## 🧱 Component Patterns

### Button Variants

**Primary (Brand Action):**
```tsx
<Button variant="primary">Get Started</Button>
// Orange background, white text, shadow on hover
```

**Secondary (Neutral Action):**
```tsx
<Button variant="secondary">Cancel</Button>
// White background, border, neutral text
```

**Danger (Destructive Action):**
```tsx
<Button variant="danger">Delete</Button>
// Red background, white text (for critical actions)
```

---

### Empty States

**Pattern:**
```tsx
<div className="flex flex-col items-center justify-center text-center gap-3 p-8">
  <div className="rounded-full bg-neutral-100 dark:bg-neutral-800 p-3">
    <IconComponent className="w-6 h-6 text-neutral-500 dark:text-neutral-400" />
  </div>
  <p className="text-sm font-medium text-neutral-900 dark:text-white">
    No data yet
  </p>
  <p className="text-xs text-neutral-500 dark:text-neutral-400">
    Data will appear here once visitors arrive
  </p>
</div>
```

**Usage:** Dashboard widgets with no data, empty site lists, etc.

---

### Loading States

**Full Page Loading:**
```tsx
<LoadingOverlay 
  logoSrc="/pulse_icon_no_margins.png"
  title="Pulse"
/>
```

**Inline Loading:**
```tsx
<Button isLoading={true}>
  Saving...
</Button>
```

**Skeleton Loading:**
```tsx
<div className="animate-pulse rounded-2xl bg-neutral-100 dark:bg-neutral-800 h-48" />
```

---

### Success/Error States

**Success Toast:**
```tsx
toast.success('Site created successfully')
// Green toast with checkmark
```

**Error Toast:**
```tsx
toast.error('Failed to load uptime monitors')
// Red toast with X icon — always mention what failed
```

**Error Display:**
```tsx
<div className="text-red-500 text-sm text-center">
  {error}
</div>
```

---

## 🎬 Animations

### Framer Motion Patterns

#### Page Entrance
```tsx
<motion.div
  initial={{ opacity: 0, y: 20 }}
  animate={{ opacity: 1, y: 0 }}
  transition={{ duration: 0.5 }}
>
  {content}
</motion.div>
```

#### Stagger Animation
```tsx
{items.map((item, i) => (
  <motion.div
    key={i}
    initial={{ opacity: 0, y: 20 }}
    whileInView={{ opacity: 1, y: 0 }}
    viewport={{ once: true }}
    transition={{ duration: 0.5, delay: i * 0.1 }}
  >
    {item}
  </motion.div>
))}
```

#### Hover Scale
```tsx
<motion.div
  whileHover={{ scale: 1.05 }}
  transition={{ duration: 0.2 }}
>
  {content}
</motion.div>
```

#### List Item Entry/Exit
```tsx
<AnimatePresence mode="popLayout">
  {items.map(item => (
    <motion.div
      key={item.id}
      initial={{ opacity: 0, x: -10 }}
      animate={{ opacity: 1, x: 0 }}
      exit={{ opacity: 0, x: -10 }}
      transition={{ duration: 0.2 }}
    >
      {item}
    </motion.div>
  ))}
</AnimatePresence>
```

---

### CSS Transitions

**Duration Standards:**
- **Fast (200ms):** Input focus, button clicks, immediate feedback
- **Medium (300ms):** Hover effects, color changes, icon transforms
- **Slow (500ms):** Page entrances, large movements

**Easing:**
- Default: `ease-out` (feels snappy)
- Alternative: `ease-in-out` (smooth both ways)

```tsx
// Standard hover
className="transition-colors duration-200 hover:text-brand-orange"

// Card hover
className="transition-all duration-300 hover:-translate-y-1 hover:shadow-xl"
```

---

## 📱 Responsive Breakpoints

Using Tailwind defaults:

| Breakpoint | Size | Usage |
|------------|------|-------|
| `sm:` | 640px | Small tablets, large phones |
| `md:` | 768px | Tablets, small laptops |
| `lg:` | 1024px | Laptops, desktops |
| `xl:` | 1280px | Large desktops |

### Common Patterns

**Grid Layouts:**
```tsx
// 1 col mobile, 2 col tablet, 3 col desktop
className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6"
```

**Typography:**
```tsx
// Smaller on mobile, larger on desktop
className="text-4xl md:text-5xl"
```

**Padding:**
```tsx
// Less padding on mobile
className="px-4 sm:px-6"
```

---

## 🔘 Buttons

### Variant Usage

**Primary (Orange):**
- Main CTAs ("Get Started", "Create Site", "Save Changes")
- Positive actions
- One per screen section max

**Secondary (Neutral):**
- Cancel, Back, alternative actions
- Can have multiple per section

**Ghost (Minimal):**
- Tertiary actions, "View All" links
- Inline actions that shouldn't be prominent

**Danger (Red):**
- Delete, Reset Data, irreversible actions
- Always confirm before action

### Size Variants

```tsx
// Default
<Button>Save</Button>

// Large (CTAs)
<Button className="px-8 py-4 text-lg">Get Started</Button>

// Small (compact UI)
<Button className="text-sm px-4 py-2">Add</Button>
```

---

## 📦 Cards

### Standard Card

```tsx
<div className="bg-white dark:bg-neutral-900 border border-neutral-200 dark:border-neutral-800 rounded-2xl p-6">
  {content}
</div>
```

### Glass Card (Premium Feel)

```tsx
<div className="card-glass p-8 hover:-translate-y-1 hover:shadow-xl transition-all duration-300">
  {content}
</div>
```

**When to use Glass:** Marketing pages, feature showcases, hero sections

### Hover Effects

```tsx
// Subtle lift
className="hover:-translate-y-1 hover:shadow-md transition-all"

// Scale
className="hover:scale-105 transition-transform"
```

---

## 🏷️ Badges

### Primary Badge
```tsx
<span className="badge-primary">
  <span className="w-1.5 h-1.5 rounded-full bg-brand-orange animate-pulse" />
  Privacy-First Analytics
</span>
```

### Status Badges

**Active/Live:**
```tsx
<div className="flex items-center gap-2 rounded-full bg-green-50 px-2 py-1 text-xs font-medium text-green-700 dark:bg-green-900/20 dark:text-green-400">
  <span className="relative flex h-2 w-2">
    <span className="animate-ping absolute inline-flex h-full w-full rounded-full bg-green-400 opacity-75"></span>
    <span className="relative inline-flex rounded-full h-2 w-2 bg-green-500"></span>
  </span>
  Active
</div>
```

---

## 🎨 Special Effects

### Background Glow (Atmosphere)

```tsx
<div className="absolute inset-0 -z-10 pointer-events-none">
  <div className="absolute top-0 left-1/4 w-[500px] h-[500px] bg-brand-orange/10 rounded-full blur-[128px] opacity-60" />
  <div className="absolute bottom-0 right-1/4 w-[500px] h-[500px] bg-neutral-500/10 rounded-full blur-[128px] opacity-40" />
</div>
```

### Grid Pattern Background

```tsx
<div 
  className="absolute inset-0 bg-grid-pattern opacity-[0.02] dark:opacity-[0.05]"
  style={{ maskImage: 'radial-gradient(ellipse at center, black 0%, transparent 70%)' }}
/>
```

### SVG Underline (Accent)

```tsx
<svg className="absolute -bottom-2 left-0 w-full h-3 text-brand-orange/30" viewBox="0 0 200 12" preserveAspectRatio="none">
  <path d="M0 9C50 3 150 3 200 9" fill="none" stroke="currentColor" strokeWidth="4" strokeLinecap="round" />
</svg>
```

---

## ♿ Accessibility

### Focus Indicators

**ALL interactive elements** must have visible focus states. See "Focus States" section above.

### Semantic HTML

- Use proper heading hierarchy (H1 → H2 → H3, no skipping)
- Use `<button>` for actions, `<Link>` for navigation
- Use `<nav>` for navigation sections
- Use `<main>` for primary content

### Alt Text

- All images must have descriptive `alt` attributes
- Decorative images use `alt=""` or `aria-hidden="true"`

### Keyboard Navigation

- Tab order should follow visual order
- All actions accessible via keyboard
- No keyboard traps
- Focus visible at all times

### ARIA Attributes

**Current usage (limited but correct):**
- `aria-label` on icon-only buttons (social links)
- `aria-hidden="true"` on decorative elements (arrows, ornaments)

**Could enhance:**
- `role="tablist"` on tab navigation
- `aria-live="polite"` on realtime counters
- `role="dialog"` on modals

---

## 🌓 Dark Mode

### Implementation

Using Tailwind's `dark:` prefix with class-based switching.

### Color Adjustments

**Backgrounds:**
- Light: `bg-white`, `bg-neutral-50`
- Dark: `dark:bg-neutral-900`, `dark:bg-neutral-800`

**Text:**
- Light: `text-neutral-900`, `text-neutral-600`
- Dark: `dark:text-white`, `dark:text-neutral-400`

**Borders:**
- Light: `border-neutral-200`
- Dark: `dark:border-neutral-800`

### Testing

Always test both light and dark modes:
- Color contrast (4.5:1 minimum in both modes)
- Focus ring visibility (should stand out in both modes)
- Glass effects (should work in both modes)

---

## 📊 Dashboard Widgets

### Standard Widget Layout

```tsx
<div className="bg-white dark:bg-neutral-900 border border-neutral-200 dark:border-neutral-800 rounded-2xl p-6 h-full flex flex-col">
  {/* Header */}
  <div className="flex items-center justify-between mb-4">
    <h3 className="text-lg font-semibold text-neutral-900 dark:text-white">
      Widget Title
    </h3>
    <button className="text-xs font-medium text-neutral-500 hover:text-neutral-900 transition-colors focus:...">
      View All
    </button>
  </div>
  
  {/* Content */}
  <div className="flex-1 min-h-[200px]">
    {hasData ? (
      <DataDisplay />
    ) : (
      <EmptyState />
    )}
  </div>
</div>
```

### Tab Toggles (Inside Widgets)

```tsx
<div className="flex p-1 bg-neutral-100 dark:bg-neutral-800 rounded-lg">
  {tabs.map(tab => (
    <button
      key={tab}
      onClick={() => setActiveTab(tab)}
      className={`px-3 py-1 text-xs font-medium rounded-lg transition-colors focus:outline-none focus:ring-2 focus:ring-brand-orange ${
        activeTab === tab
          ? 'bg-white dark:bg-neutral-700 text-neutral-900 dark:text-white shadow-sm'
          : 'text-neutral-600 dark:text-neutral-400 hover:text-neutral-900 dark:hover:text-white'
      }`}
    >
      {tab}
    </button>
  ))}
</div>
```

---

## 📋 Forms

### Input Styling

```tsx
<Input
  id="field-name"
  placeholder="Enter value"
  className="rounded-lg"
/>
// Uses @ciphera-net/ui Input component
// Automatically includes focus states, dark mode
```

### Label Pattern

```tsx
<label htmlFor="field-name" className="block text-sm font-medium mb-2 text-neutral-700 dark:text-neutral-300">
  Field Name
</label>
```

### Help Text

```tsx
<p className="mt-2 text-sm text-neutral-600 dark:text-neutral-400">
  Additional information about this field.
</p>
```

### Error Display

```tsx
{error && (
  <div className="text-red-500 text-sm text-center">
    {error}
  </div>
)}
```

---

## 🎭 Code Blocks (Integration Pages)

### VS Code-Style Syntax Highlighting

```tsx
<div className="bg-neutral-900 rounded-xl overflow-hidden shadow-2xl border border-neutral-800">
  {/* Header bar */}
  <div className="flex items-center px-4 py-3 bg-neutral-800 border-b border-neutral-800">
    <div className="flex gap-2">
      <div className="w-3 h-3 rounded-full bg-red-500/20" />
      <div className="w-3 h-3 rounded-full bg-yellow-500/20" />
      <div className="w-3 h-3 rounded-full bg-green-500/20" />
    </div>
    <span className="ml-4 text-xs text-neutral-500 font-mono">filename.tsx</span>
  </div>
  
  {/* Code content */}
  <div className="p-6 overflow-x-auto">
    <code className="font-mono text-sm text-neutral-300">
      {/* Syntax-highlighted code */}
    </code>
  </div>
</div>
```

**Colors for syntax:**
- Blue `#61AFEF`: Keywords, tags
- Orange `#D19A66`: Strings
- Purple `#C678DD`: Functions
- Green `#98C379`: Comments
- White `#ABB2BF`: Text

---

## 🌍 Internationalization (Future)

**Currently:** English only  
**When implementing i18n:**
- Use `next-intl` or similar
- Extract all strings to translation files
- Maintain "Swiss infrastructure" messaging
- Support: EN, DE, FR, IT (Swiss languages)

---

## 📐 Layout Patterns

### Page Container

```tsx
// App pages
<div className="w-full max-w-6xl mx-auto px-4 sm:px-6 py-8">
  {content}
</div>

// Marketing pages
<div className="w-full max-w-4xl mx-auto px-4 pt-20 pb-10">
  {content}
</div>
```

### Two-Column Settings Layout

```tsx
<div className="flex flex-col md:flex-row gap-8">
  {/* Sidebar */}
  <nav className="w-full md:w-64 flex-shrink-0">
    {tabs}
  </nav>
  
  {/* Content */}
  <div className="flex-1">
    {content}
  </div>
</div>
```

---

## 🔌 Integration with @ciphera-net/ui

### Current Usage

```tsx
import { 
  Button,
  Input,
  Select,
  Modal,
  LoadingOverlay,
  DatePicker,
  Captcha,
  // Icons
  CheckCircleIcon,
  SettingsIcon,
  // etc.
} from '@ciphera-net/ui'
```

**Version:** `^0.0.45`

### Preset

Pulse uses the Ciphera UI Tailwind preset:
```ts
// tailwind.config.ts
presets: [
  require('@ciphera-net/ui/dist/tailwind-preset').default,
]
```

**Provides:**
- Brand colors (brand-orange)
- Background gradients (bg-ciphera-gradient)
- Neutral scale extension

---

## 🎯 Design Principles

### 1. Privacy-First Visual Language
- Clean, minimal design
- No tracking pixels, no external fonts from CDNs
- Swiss aesthetic (precision, trust, neutrality)

### 2. Accessibility First
- WCAG 2.1 Level AA compliance
- Keyboard navigation throughout
- Clear focus indicators
- Readable text contrast

### 3. Performance
- Lightweight animations (opacity, translate only)
- Optimized images
- Code splitting by route
- Fast transitions (200-500ms max)

### 4. Brand Consistency
- Orange used sparingly (accents only)
- Neutral-heavy palette
- Glass effects for premium feel
- Consistent with other Ciphera products

---

## 🛠️ Component Library

### Available from @ciphera-net/ui

**Buttons:** Primary, Secondary, Danger variants  
**Forms:** Input, Select, Checkbox, DatePicker  
**Feedback:** Toast (Sonner), LoadingOverlay  
**Security:** Captcha component  
**Icons:** Full icon set from Lucide  
**Layout:** Modal component  

### Custom to Pulse

**Dashboard:** Chart, TopPages, TopReferrers, Locations, TechSpecs, Campaigns, Goals, Performance  
**Settings:** OrganizationSettings, ProfileSettings  
**Sites:** SiteList, VerificationModal  

---

## 📏 Checklist for New Components

When creating new components, ensure:

- [ ] Uses standard color tokens (no hardcoded hex values)
- [ ] Follows typography scale (no custom text sizes)
- [ ] Has dark mode support (`dark:` variants)
- [ ] Includes focus states on interactive elements
- [ ] Uses spacing system (no arbitrary padding values)
- [ ] Follows border radius standards
- [ ] Has empty state if displays lists
- [ ] Has loading state if async
- [ ] Has error state if can fail
- [ ] Responsive on mobile (<768px)
- [ ] Accessible (semantic HTML, ARIA where needed)
- [ ] Consistent with existing components

---

## 🔍 Testing Checklist

Before deploying changes:

### Visual
- [ ] Light mode looks correct
- [ ] Dark mode looks correct
- [ ] Focus rings visible on all interactive elements
- [ ] Typography hierarchy is clear
- [ ] Spacing feels consistent

### Responsive
- [ ] Works on mobile (375px)
- [ ] Works on tablet (768px)
- [ ] Works on desktop (1280px+)

### Accessibility
- [ ] Can navigate with keyboard only
- [ ] Focus visible at all times
- [ ] Screen reader friendly (test with VoiceOver/NVDA)
- [ ] Color contrast passes WCAG AA

### Cross-Browser
- [ ] Chrome/Edge (Chromium)
- [ ] Firefox
- [ ] Safari (macOS/iOS)

---

## 📚 References

- **Tailwind CSS:** https://tailwindcss.com/docs
- **Framer Motion:** https://www.framer.com/motion/
- **WCAG Guidelines:** https://www.w3.org/WAI/WCAG21/quickref/
- **Ciphera Brand:** (internal brand guidelines)

---

## 🔄 Changelog

### v1.0 (2026-02-06)
- Initial design system documentation
- Documented Tier 1 + Tier 2 standardization results
- Defined all component patterns
- Established accessibility standards

---

**This is a living document.** Update as the design system evolves.
