# WooNooW Customer SPA Theme System

## 🎨 Design Philosophy

**SaaS Approach:** Curated options over infinite flexibility

- ✅ 4 master layouts (not infinite themes)
  - Classic, Modern, Boutique (multi-product stores)
  - Launch (single product funnels) 🆕
- ✅ Design tokens (not custom CSS)
- ✅ Preset combinations (not freestyle design)
- ✅ Accessibility built-in (WCAG 2.1 AA)
- ✅ Performance optimized (Core Web Vitals)

---

## 🏗️ Theme Architecture

### Design Token System

All styling is controlled via CSS custom properties (design tokens):

```css
:root {
  /* Colors */
  --color-primary: #3B82F6;
  --color-secondary: #8B5CF6;
  --color-accent: #10B981;
  --color-background: #FFFFFF;
  --color-text: #1F2937;
  
  /* Typography */
  --font-heading: 'Inter', sans-serif;
  --font-body: 'Lora', serif;
  --font-size-base: 16px;
  --line-height-base: 1.5;
  
  /* Spacing (8px grid) */
  --space-1: 0.5rem;   /* 8px */
  --space-2: 1rem;     /* 16px */
  --space-3: 1.5rem;   /* 24px */
  --space-4: 2rem;     /* 32px */
  --space-6: 3rem;     /* 48px */
  --space-8: 4rem;     /* 64px */
  
  /* Border Radius */
  --radius-sm: 0.25rem;  /* 4px */
  --radius-md: 0.5rem;   /* 8px */
  --radius-lg: 1rem;     /* 16px */
  
  /* Shadows */
  --shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.05);
  --shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.1);
  --shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.1);
  
  /* Transitions */
  --transition-fast: 150ms ease;
  --transition-base: 250ms ease;
  --transition-slow: 350ms ease;
}
```

---

## 📐 Master Layouts

### 1. Classic Layout

**Target Audience:** Traditional ecommerce, B2B

**Characteristics:**
- Header: Logo left, menu right, search bar
- Shop: Sidebar filters (left), product grid (right)
- Product: Image gallery left, details right
- Footer: 4-column widget areas

**File:** `customer-spa/src/layouts/ClassicLayout.tsx`

```typescript
export function ClassicLayout({ children }) {
  return (
    <div className="classic-layout">
      <Header variant="classic" />
      <main className="classic-main">
        {children}
      </main>
      <Footer variant="classic" />
    </div>
  );
}
```

**CSS:**
```css
.classic-layout {
  --header-height: 80px;
  --sidebar-width: 280px;
}

.classic-main {
  display: grid;
  grid-template-columns: var(--sidebar-width) 1fr;
  gap: var(--space-6);
  max-width: 1280px;
  margin: 0 auto;
  padding: var(--space-6);
}

@media (max-width: 768px) {
  .classic-main {
    grid-template-columns: 1fr;
  }
}
```

### 2. Modern Layout (Default)

**Target Audience:** Fashion, lifestyle, modern brands

**Characteristics:**
- Header: Centered logo, minimal menu
- Shop: Top filters (no sidebar), large product cards
- Product: Full-width gallery, sticky details
- Footer: Minimal, centered

**File:** `customer-spa/src/layouts/ModernLayout.tsx`

```typescript
export function ModernLayout({ children }) {
  return (
    <div className="modern-layout">
      <Header variant="modern" />
      <main className="modern-main">
        {children}
      </main>
      <Footer variant="modern" />
    </div>
  );
}
```

**CSS:**
```css
.modern-layout {
  --header-height: 100px;
  --content-max-width: 1440px;
}

.modern-main {
  max-width: var(--content-max-width);
  margin: 0 auto;
  padding: var(--space-8) var(--space-4);
}

.modern-layout .product-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  gap: var(--space-6);
}
```

### 3. Boutique Layout

**Target Audience:** Luxury, high-end fashion

**Characteristics:**
- Header: Full-width, transparent overlay
- Shop: Masonry grid, elegant typography
- Product: Minimal UI, focus on imagery
- Footer: Elegant, serif typography

**File:** `customer-spa/src/layouts/BoutiqueLayout.tsx`

```typescript
export function BoutiqueLayout({ children }) {
  return (
    <div className="boutique-layout">
      <Header variant="boutique" />
      <main className="boutique-main">
        {children}
      </main>
      <Footer variant="boutique" />
    </div>
  );
}
```

**CSS:**
```css
.boutique-layout {
  --header-height: 120px;
  --content-max-width: 1600px;
  font-family: var(--font-heading);
}

.boutique-main {
  max-width: var(--content-max-width);
  margin: 0 auto;
}

.boutique-layout .product-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(400px, 1fr));
  gap: var(--space-8);
}
```

### 4. Launch Layout 🆕 (Single Product Funnel)

**Target Audience:** Single product sellers, course creators, SaaS, product launchers

**Important:** Landing page is **fully custom** (user builds with their page builder). WooNooW SPA only takes over **from checkout onwards** after CTA button is clicked.

**Characteristics:**
- **Landing page:** User's custom design (Elementor, Divi, etc.) - NOT controlled by WooNooW
- **Checkout onwards:** WooNooW SPA takes full control
- **No traditional header/footer** on SPA pages (distraction-free)
- **Streamlined checkout** (one-page, minimal fields, no cart)
- **Upsell opportunity** on thank you page
- **Direct access** to product in My Account

**Page Flow:**
```
Landing Page (Custom - User's Page Builder)
    ↓
  [CTA Button Click] ← User directs to /checkout
    ↓
Checkout (WooNooW SPA - Full screen, no distractions)
    ↓
Thank You (WooNooW SPA - Upsell/downsell opportunity)
    ↓
My Account (WooNooW SPA - Access product/download)
```

**Technical Note:**
- Landing page URL: Any (/, /landing, /offer, etc.)
- CTA button links to: `/checkout` or `/checkout?add-to-cart=123`
- WooNooW SPA activates only on checkout, thank you, and account pages
- This is essentially **Checkout-Only mode** with optimized funnel design

**File:** `customer-spa/src/layouts/LaunchLayout.tsx`

```typescript
export function LaunchLayout({ children }) {
  const location = useLocation();
  const isLandingPage = location.pathname === '/' || location.pathname === '/shop';
  
  return (
    <div className="launch-layout">
      {/* Minimal header only on non-landing pages */}
      {!isLandingPage && <Header variant="minimal" />}
      
      <main className="launch-main">
        {children}
      </main>
      
      {/* No footer on landing page */}
      {!isLandingPage && <Footer variant="minimal" />}
    </div>
  );
}
```

**CSS:**
```css
.launch-layout {
  --content-max-width: 1200px;
  min-height: 100vh;
}

.launch-main {
  max-width: var(--content-max-width);
  margin: 0 auto;
}

/* Landing page: full-screen hero */
.launch-landing {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  text-align: center;
  padding: var(--space-8);
}

.launch-landing .hero-title {
  font-size: var(--text-5xl);
  font-weight: 700;
  margin-bottom: var(--space-4);
}

.launch-landing .hero-subtitle {
  font-size: var(--text-xl);
  margin-bottom: var(--space-8);
  opacity: 0.8;
}

.launch-landing .cta-button {
  font-size: var(--text-xl);
  padding: var(--space-4) var(--space-8);
  min-width: 300px;
}

/* Checkout: streamlined, no distractions */
.launch-checkout {
  max-width: 600px;
  margin: var(--space-8) auto;
  padding: var(--space-6);
}

/* Thank you: upsell opportunity */
.launch-thankyou {
  max-width: 800px;
  margin: var(--space-8) auto;
  text-align: center;
}

.launch-thankyou .upsell-section {
  margin-top: var(--space-8);
  padding: var(--space-6);
  border: 2px solid var(--color-primary);
  border-radius: var(--radius-lg);
}
```

**Perfect For:**
- Digital products (courses, ebooks, software)
- SaaS trial → paid conversions
- Webinar funnels
- High-ticket consulting
- Limited-time offers
- Crowdfunding campaigns
- Product launches

**Competitive Advantage:**
Replaces expensive tools like CartFlows ($297-997/year) with built-in, optimized funnel.

---

## 🎨 Color System

### Color Palette Generation

When user sets primary color, we auto-generate shades:

```typescript
function generateColorShades(baseColor: string) {
  return {
    50: lighten(baseColor, 0.95),
    100: lighten(baseColor, 0.90),
    200: lighten(baseColor, 0.75),
    300: lighten(baseColor, 0.60),
    400: lighten(baseColor, 0.40),
    500: baseColor,              // Base color
    600: darken(baseColor, 0.10),
    700: darken(baseColor, 0.20),
    800: darken(baseColor, 0.30),
    900: darken(baseColor, 0.40),
  };
}
```

### Contrast Checking

Ensure WCAG AA compliance:

```typescript
function ensureContrast(textColor: string, bgColor: string) {
  const contrast = getContrastRatio(textColor, bgColor);
  
  if (contrast < 4.5) {
    // Adjust text color for better contrast
    return adjustColorForContrast(textColor, bgColor, 4.5);
  }
  
  return textColor;
}
```

### Dark Mode Support

```css
@media (prefers-color-scheme: dark) {
  :root {
    --color-background: #1F2937;
    --color-text: #F9FAFB;
    /* Invert shades */
  }
}
```

---

## 📝 Typography System

### Typography Presets

#### Professional
```css
:root {
  --font-heading: 'Inter', -apple-system, sans-serif;
  --font-body: 'Lora', Georgia, serif;
  --font-weight-heading: 700;
  --font-weight-body: 400;
}
```

#### Modern
```css
:root {
  --font-heading: 'Poppins', -apple-system, sans-serif;
  --font-body: 'Roboto', -apple-system, sans-serif;
  --font-weight-heading: 600;
  --font-weight-body: 400;
}
```

#### Elegant
```css
:root {
  --font-heading: 'Playfair Display', Georgia, serif;
  --font-body: 'Source Sans Pro', -apple-system, sans-serif;
  --font-weight-heading: 700;
  --font-weight-body: 400;
}
```

#### Tech
```css
:root {
  --font-heading: 'Space Grotesk', monospace;
  --font-body: 'IBM Plex Mono', monospace;
  --font-weight-heading: 700;
  --font-weight-body: 400;
}
```

### Type Scale

```css
:root {
  --text-xs: 0.75rem;    /* 12px */
  --text-sm: 0.875rem;   /* 14px */
  --text-base: 1rem;     /* 16px */
  --text-lg: 1.125rem;   /* 18px */
  --text-xl: 1.25rem;    /* 20px */
  --text-2xl: 1.5rem;    /* 24px */
  --text-3xl: 1.875rem;  /* 30px */
  --text-4xl: 2.25rem;   /* 36px */
  --text-5xl: 3rem;      /* 48px */
}
```

---

## 🧩 Component Theming

### Button Component

```typescript
// components/ui/button.tsx
export function Button({ variant = 'primary', ...props }) {
  return (
    <button 
      className={cn('btn', `btn-${variant}`)}
      {...props}
    />
  );
}
```

```css
.btn {
  font-family: var(--font-heading);
  font-weight: 600;
  padding: var(--space-2) var(--space-4);
  border-radius: var(--radius-md);
  transition: all var(--transition-base);
}

.btn-primary {
  background: var(--color-primary);
  color: white;
}

.btn-primary:hover {
  background: var(--color-primary-600);
  transform: translateY(-1px);
  box-shadow: var(--shadow-md);
}
```

### Product Card Component

```typescript
// components/ProductCard.tsx
export function ProductCard({ product, layout }) {
  const theme = useTheme();
  
  return (
    <div className={cn('product-card', `product-card-${layout}`)}>
      <img src={product.image} alt={product.name} />
      <h3>{product.name}</h3>
      <p className="price">{product.price}</p>
      <Button variant="primary">Add to Cart</Button>
    </div>
  );
}
```

```css
.product-card {
  background: var(--color-background);
  border-radius: var(--radius-lg);
  overflow: hidden;
  transition: all var(--transition-base);
}

.product-card:hover {
  box-shadow: var(--shadow-lg);
  transform: translateY(-4px);
}

.product-card-modern {
  /* Modern layout specific styles */
  padding: var(--space-4);
}

.product-card-boutique {
  /* Boutique layout specific styles */
  padding: 0;
}
```

---

## 🎭 Theme Provider (React Context)

### Implementation

**File:** `customer-spa/src/contexts/ThemeContext.tsx`

```typescript
import { createContext, useContext, useEffect, ReactNode } from 'react';

interface ThemeConfig {
  layout: 'classic' | 'modern' | 'boutique';
  colors: {
    primary: string;
    secondary: string;
    accent: string;
    background: string;
    text: string;
  };
  typography: {
    preset: string;
    customFonts?: {
      heading: string;
      body: string;
    };
  };
}

const ThemeContext = createContext<ThemeConfig | null>(null);

export function ThemeProvider({ 
  config, 
  children 
}: { 
  config: ThemeConfig; 
  children: ReactNode;
}) {
  useEffect(() => {
    // Inject CSS variables
    const root = document.documentElement;
    
    // Colors
    root.style.setProperty('--color-primary', config.colors.primary);
    root.style.setProperty('--color-secondary', config.colors.secondary);
    root.style.setProperty('--color-accent', config.colors.accent);
    root.style.setProperty('--color-background', config.colors.background);
    root.style.setProperty('--color-text', config.colors.text);
    
    // Typography
    loadTypographyPreset(config.typography.preset);
    
    // Add layout class to body
    document.body.className = `layout-${config.layout}`;
  }, [config]);
  
  return (
    <ThemeContext.Provider value={config}>
      {children}
    </ThemeContext.Provider>
  );
}

export function useTheme() {
  const context = useContext(ThemeContext);
  if (!context) {
    throw new Error('useTheme must be used within ThemeProvider');
  }
  return context;
}
```

### Loading Google Fonts

```typescript
function loadTypographyPreset(preset: string) {
  const fontMap = {
    professional: ['Inter:400,600,700', 'Lora:400,700'],
    modern: ['Poppins:400,600,700', 'Roboto:400,700'],
    elegant: ['Playfair+Display:400,700', 'Source+Sans+Pro:400,700'],
    tech: ['Space+Grotesk:400,700', 'IBM+Plex+Mono:400,700'],
  };
  
  const fonts = fontMap[preset];
  if (!fonts) return;
  
  const link = document.createElement('link');
  link.href = `https://fonts.googleapis.com/css2?family=${fonts.join('&family=')}&display=swap`;
  link.rel = 'stylesheet';
  document.head.appendChild(link);
}
```

---

## 📱 Responsive Design

### Breakpoints

```css
:root {
  --breakpoint-sm: 640px;
  --breakpoint-md: 768px;
  --breakpoint-lg: 1024px;
  --breakpoint-xl: 1280px;
  --breakpoint-2xl: 1536px;
}
```

### Mobile-First Approach

```css
/* Mobile (default) */
.product-grid {
  grid-template-columns: 1fr;
  gap: var(--space-4);
}

/* Tablet */
@media (min-width: 768px) {
  .product-grid {
    grid-template-columns: repeat(2, 1fr);
    gap: var(--space-6);
  }
}

/* Desktop */
@media (min-width: 1024px) {
  .product-grid {
    grid-template-columns: repeat(3, 1fr);
  }
}

/* Large Desktop */
@media (min-width: 1280px) {
  .product-grid {
    grid-template-columns: repeat(4, 1fr);
  }
}
```

---

## ♿ Accessibility

### Focus States

```css
:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 2px;
}

button:focus-visible {
  box-shadow: 0 0 0 3px var(--color-primary-200);
}
```

### Screen Reader Support

```typescript
<button aria-label="Add to cart">
  <ShoppingCart aria-hidden="true" />
</button>
```

### Color Contrast

All text must meet WCAG AA standards (4.5:1 for normal text, 3:1 for large text).

---

## 🚀 Performance Optimization

### CSS-in-JS vs CSS Variables

We use **CSS variables** instead of CSS-in-JS for better performance:

- ✅ No runtime overhead
- ✅ Instant theme switching
- ✅ Better browser caching
- ✅ Smaller bundle size

### Critical CSS

Inline critical CSS in `<head>`:

```php
<style>
  /* Critical above-the-fold styles */
  :root { /* Design tokens */ }
  .layout-modern { /* Layout styles */ }
  .header { /* Header styles */ }
</style>
```

### Font Loading Strategy

```html
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="stylesheet" href="..." media="print" onload="this.media='all'">
```

---

## 🧪 Testing

### Visual Regression Testing

```typescript
describe('Theme System', () => {
  it('should apply modern layout correctly', () => {
    cy.visit('/shop?theme=modern');
    cy.matchImageSnapshot('shop-modern-layout');
  });
  
  it('should apply custom colors', () => {
    cy.setTheme({ colors: { primary: '#FF0000' } });
    cy.get('.btn-primary').should('have.css', 'background-color', 'rgb(255, 0, 0)');
  });
});
```

### Accessibility Testing

```typescript
it('should meet WCAG AA standards', () => {
  cy.visit('/shop');
  cy.injectAxe();
  cy.checkA11y();
});
```

---

## 📚 Related Documentation

- [Customer SPA Architecture](./CUSTOMER_SPA_ARCHITECTURE.md)
- [Customer SPA Settings](./CUSTOMER_SPA_SETTINGS.md)
- [Component Library](./COMPONENT_LIBRARY.md)
