# Styling & Customization

> Customize the appearance of Zest consent UI

Source: https://zest.freshjuice.dev/docs/styling/

## Theming

Zest supports three theme modes:

```javascript
window.ZestConfig = {
  theme: 'auto' // 'light', 'dark', or 'auto'
};
```

| Theme | Behavior |
|-------|----------|
| `light` | Always use light theme |
| `dark` | Always use dark theme |
| `auto` | Follow system preference (`prefers-color-scheme`) |

## Accent Color

Customize the primary button color:

```javascript
window.ZestConfig = {
  accentColor: '#0071e3' // Any valid CSS color
};
```

The accent color is used for:
- "Accept All" button background
- Toggle switches when enabled
- Focus rings and highlights

> **Validated since v2.0.0.** The value is passed through a strict color validator that accepts hex (`#0071e3`), named colors (`rebeccapurple`), and the `rgb()`, `rgba()`, `hsl()`, and `hsla()` functions. Anything else falls back silently to the default.

## Banner Position

Control where the banner appears:

```javascript
window.ZestConfig = {
  position: 'bottom-right' // 'bottom', 'bottom-left', 'bottom-right', 'top'
};
```

| Position | Description |
|----------|-------------|
| `bottom` | Full-width bar at bottom of page |
| `bottom-left` | Floating card at bottom-left corner |
| `bottom-right` | Floating card at bottom-right corner |
| `top` | Full-width bar at top of page |

## CSS Custom Properties

Zest uses CSS custom properties that you can override. Since Zest uses Shadow DOM, you need to use the `customStyles` configuration option:

```javascript
window.ZestConfig = {
  customStyles: `
    :host {
      --zest-accent: #ff6b35;
      --zest-bg: #1a1a2e;
      --zest-bg-secondary: #16213e;
      --zest-text: #edf2f7;
      --zest-text-secondary: #a0aec0;
      --zest-border: #2d3748;
      --zest-radius: 16px;
      --zest-radius-sm: 8px;
    }
  `
};
```

### Available CSS Variables

| Variable | Default (Light) | Description |
|----------|-----------------|-------------|
| `--zest-accent` | `#0071e3` | Primary accent color |
| `--zest-bg` | `#ffffff` | Background color |
| `--zest-bg-secondary` | `#f3f4f6` | Secondary background |
| `--zest-text` | `#1f2937` | Primary text color |
| `--zest-text-secondary` | `#6b7280` | Secondary text color |
| `--zest-border` | `#e5e7eb` | Border color |
| `--zest-radius` | `12px` | Large border radius |
| `--zest-radius-sm` | `8px` | Small border radius |

## Custom CSS

Inject custom CSS into the Shadow DOM.

> **Sanitized since v2.0.0.** `customStyles` is hard-capped at 20 KB, and the following are stripped before injection: `@import`, `@charset`, `expression()`, `-moz-binding`, and external `url()` values. Selectors targeting the accept/reject buttons (e.g. `.zest-btn--primary { opacity: 0 }`) are also removed to prevent clickjacking via invisible-button attacks. Theme variables and ordinary layout styles are unaffected.

```javascript
window.ZestConfig = {
  customStyles: `
    /* Custom banner styles */
    .zest-banner {
      max-width: 500px;
      box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
    }

    /* Custom button styles */
    .zest-btn--primary {
      border-radius: 9999px;
      font-weight: 600;
      text-transform: uppercase;
      letter-spacing: 0.05em;
    }

    /* Custom modal styles */
    .zest-modal {
      max-width: 600px;
    }

    /* Custom widget styles */
    .zest-widget {
      bottom: 24px;
      right: 24px;
    }
  `
};
```

### CSS Class Reference

**Banner:**
- `.zest-banner` - Main banner container
- `.zest-banner__content` - Text content area
- `.zest-banner__title` - Banner title
- `.zest-banner__description` - Banner description
- `.zest-banner__actions` - Button container

**Buttons:**
- `.zest-btn` - Base button class
- `.zest-btn--primary` - Accept all button
- `.zest-btn--secondary` - Settings/reject buttons
- `.zest-btn--text` - Text-only buttons

**Modal:**
- `.zest-modal` - Modal container
- `.zest-modal__overlay` - Background overlay
- `.zest-modal__content` - Modal content
- `.zest-modal__header` - Modal header
- `.zest-modal__body` - Modal body
- `.zest-modal__footer` - Modal footer

**Categories:**
- `.zest-category` - Category item
- `.zest-category__header` - Category header
- `.zest-category__title` - Category title
- `.zest-category__toggle` - Toggle switch

**Widget:**
- `.zest-widget` - Floating widget button

## Custom Labels

Customize all UI text:

```javascript
window.ZestConfig = {
  labels: {
    banner: {
      title: 'We value your privacy',
      description: 'We use cookies to enhance your browsing experience and analyze our traffic.',
      acceptAll: 'Accept',
      rejectAll: 'Decline',
      settings: 'Preferences'
    },
    modal: {
      title: 'Cookie Preferences',
      description: 'Manage your cookie preferences below.',
      save: 'Save',
      acceptAll: 'Accept All',
      rejectAll: 'Reject All'
    },
    widget: {
      label: 'Cookies'
    },
    categories: {
      essential: {
        title: 'Essential',
        description: 'Required for the website to function properly.'
      },
      functional: {
        title: 'Functional',
        description: 'Remember your preferences and settings.'
      },
      analytics: {
        title: 'Analytics',
        description: 'Help us understand how visitors use our site.'
      },
      marketing: {
        title: 'Marketing',
        description: 'Used to deliver relevant advertisements.'
      }
    }
  }
};
```

## Examples

### Minimal Dark Theme

```javascript
window.ZestConfig = {
  theme: 'dark',
  position: 'bottom-right',
  accentColor: '#10b981',
  customStyles: `
    .zest-banner {
      border: 1px solid var(--zest-border);
    }
    .zest-btn {
      font-size: 14px;
    }
  `
};
```

### Corporate Style

```javascript
window.ZestConfig = {
  theme: 'light',
  position: 'bottom',
  accentColor: '#1e40af',
  customStyles: `
    :host {
      --zest-radius: 4px;
      --zest-radius-sm: 2px;
    }
    .zest-banner {
      border-top: 3px solid var(--zest-accent);
    }
    .zest-btn {
      font-family: 'Inter', sans-serif;
      text-transform: uppercase;
      font-size: 12px;
      letter-spacing: 0.1em;
    }
  `
};
```

### Playful Style

```javascript
window.ZestConfig = {
  theme: 'auto',
  position: 'bottom-left',
  accentColor: '#f97316',
  customStyles: `
    :host {
      --zest-radius: 24px;
      --zest-radius-sm: 12px;
    }
    .zest-banner {
      box-shadow: 0 20px 40px rgba(0, 0, 0, 0.15);
    }
    .zest-btn--primary {
      border-radius: 9999px;
      padding: 12px 24px;
    }
  `
};
```

## Hiding the Widget

Disable the floating widget:

```javascript
window.ZestConfig = {
  showWidget: false
};
```

You can still provide a way for users to change preferences:

```html
<button onclick="Zest.showSettings()">Cookie Settings</button>
```

