📘

This guide is specific to Web SDK 2.0. If you are still using 1.x, you can find documentation [here](https://developer.incode.com/docs/web-sdk-reference). Contact your Incode Representative for upgrade information and check if you are a candidate for this upgrade.

The Incode Web SDK uses CSS custom properties (variables) for theming, making it easy to match your brand.

## Quick Start  
Import the base tokens and override the variables you want to customize:

### CSS
```css
/* Import the SDK theme (defines all CSS variables you can override) */
@import '@incodetech/web/themes/light.css';

/* Override with your brand color — easiest path */
:root {
  --primitive-color-brand-500: #0066cc;
  --primitive-color-brand-400: #1f7fdf; /* slightly lighter, used on hover */
  --primitive-color-brand-600: #0052a3; /* slightly darker, used on press */
}
```

**Note:** The SDK ships two themes — `@incodetech/web/themes/light.css` and `@incodetech/web/themes/dark.css`. Pick one as your base, then override variables to match your brand. Component layout/structure CSS lives separately in `@incodetech/web/base.css` and per-module CSS such as `@incodetech/web/flow/styles.css`. The full token catalog is documented below.

## Token Hierarchy  
The SDK uses a layered token system:

```undefined
Primitives → Semantic → Component-specific
```

Each layer references the layer above. Most overrides target the primitive or component layer; touching the semantic layer cascades broadly so use it intentionally.

### 1. Primitive Tokens  
Concrete values that nothing else customizes:

### CSS
```css
:root {
  /* Color scales (50, 100, 200, ..., 900, 1000) for: gray, brand, brand-secondary, positive, warning, negative */
  --primitive-color-gray-0: #ffffff;
  --primitive-color-gray-500: #6b7280;
  --primitive-color-gray-900: #1f2937;
  --primitive-color-brand-500: #0066cc;

/* Spacing scale (--primitive-scale-*) and the friendly --spacing-* aliases */
  --primitive-scale-4: 4px;
  --spacing-4: var(--primitive-scale-4);
  --spacing-16: var(--primitive-scale-16);

/* Typography */
  --primitive-typography-family-rethink-sans: 'Rethink Sans';
  --primitive-typography-size-16: 16px;
  --primitive-typography-weight-regular: 400;
  --primitive-typography-weight-medium: 500;

/* Border radius scale (--primitive-border-radius-0/4/8/16/24/40/64/9999) and aliases */
  --border-radius-medium: var(--primitive-border-radius-16);
  --border-radius-full: var(--primitive-border-radius-9999);
}
```

### 2. Semantic Tokens  
Purpose-based names that reference primitives. Different values resolve in `@incodetech/web/themes/light.css` vs. `dark.css`, so overriding a semantic token affects whichever theme you're on:

### CSS
```css
:root {
  /* Surfaces — backgrounds */
  --surface-neutral-0: var(--primitive-color-gray-0); /* base background */
  --surface-neutral-50: var(--primitive-color-gray-50); /* subtle elevated surface */
  --surface-neutral-900: var(--primitive-color-gray-900); /* highest contrast */
  --surface-brand-500: var(--primitive-color-brand-500); /* brand fill */
  --surface-status-negative-500: var(--primitive-color-negative-500);
  --surface-status-warning-500: var(--primitive-color-warning-500);
  --surface-status-positive-500: var(--primitive-color-positive-500);

/* Text — foreground colors */
  --text-body-800-primary: var(--primitive-color-gray-800); /* primary body text */
  --text-body-500-secondary: var(--primitive-color-gray-500); /* secondary / muted */
  --text-body-400: var(--primitive-color-gray-400); /* placeholders, disabled */
  --text-link-default: var(--primitive-color-brand-500);
  --text-link-hover: var(--primitive-color-brand-300);
  --text-accent-brand: var(--primitive-color-brand-500);

/* Borders */
  --border-neutral-100: var(--primitive-color-gray-100);
  --border-neutral-400: var(--primitive-color-gray-400);
  --border-status-negative: var(--primitive-color-negative-500);
  --border-status-focus: var(--primitive-color-brand-500);
}
```

### 3. Component Tokens  
Specific to individual components. These reference semantic tokens, so overriding a component token gives you targeted control without affecting other components:

### CSS
```css
:root {
  /* Primary button */
  --button-primary-surface-default: var(--surface-brand-500-static);
  --button-primary-surface-hover: var(--surface-brand-400-static); /* lighter on hover */
  --button-primary-surface-pressed: var(--surface-brand-600-static); /* darker on press */
  --button-primary-surface-disabled: var(--surface-neutral-100);
  --button-primary-text-default: var(--text-body-0-static);
  --button-primary-border-radius: var(--border-radius-medium);

/* Inputs */
  --input-surface-default: var(--surface-neutral-50);
  --input-surface-disabled: var(--surface-neutral-100);
  --input-border-default: var(--border-neutral-400);
  --input-border-focused: var(--border-status-focus);
  --input-border-negative: var(--border-status-negative);
  --input-text-field-default: var(--text-body-800-primary);
  --input-text-field-placeholder: var(--text-body-400);

/* Spinner */
  --spinner-surface-primary: var(--surface-brand-500-static);
  --spinner-surface-secondary: var(--surface-brand-50);
  --spinner-text-title: var(--text-body-800-primary);
  --spinner-text-subtitle: var(--text-body-500-secondary);
}
```

## Common Customizations  
### Brand colors  
The simplest path is to override the primitive brand scale. Everything semantic (`--surface-brand-*`, `--text-accent-brand`, button colors, focus rings, etc.) inherits automatically:

### CSS
```css
:root {
  --primitive-color-brand-50: #e6f0ff;
  --primitive-color-brand-100: #cce0ff;
  --primitive-color-brand-300: #4d9aff;
  --primitive-color-brand-400: #1f7fdf; /* button hover */
  --primitive-color-brand-500: #0066cc; /* main brand */
  --primitive-color-brand-600: #0052a3; /* button pressed */
}
```

If you need finer control, override the component tokens directly:

### CSS
```css
:root {
  --button-primary-surface-default: #0066cc;
  --button-primary-surface-hover: #1f7fdf;
  --button-primary-surface-pressed: #0052a3;
}
```

### Dark mode  
The SDK already ships a dark theme — import it instead of rolling your own:

### CSS
```css
@import '@incodetech/web/themes/dark.css';
```

If you want to switch themes per user preference, gate the import or apply it conditionally:

### CSS
```css
/* Default to light, switch to dark when the user prefers dark */
@import '@incodetech/web/themes/light.css';

@media (prefers-color-scheme: dark) {
  @import '@incodetech/web/themes/dark.css';
}
```

### Typography  
The SDK uses Rethink Sans by default. Override the primitive family if you want a different font everywhere:

### CSS
```css
:root {
  --primitive-typography-family-rethink-sans:
    'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
}
```

Sizes (`--primitive-typography-size-12` through `--primitive-typography-size-80`) and weights (`--primitive-typography-weight-regular`, `--primitive-typography-weight-medium`, `--primitive-typography-weight-semibold`, `--primitive-typography-weight-bold`) are also override-able primitive tokens.

### Border radius  
The radius scale is `--border-radius-{none,x-small,small,medium,large,x-large,xx-large,full}`. Components reference these via component tokens:

### CSS
```css
:root {
  /* Round all primary buttons more aggressively */
  --button-primary-border-radius: var(--border-radius-large);

/* Or change the underlying scale */
  --primitive-border-radius-16: 12px; /* shrinks --border-radius-medium */
}
```

## Container Styling  
The SDK elements fill their container. Style the parent for layout control:

### HTML
```html
<!-- Full viewport height -->
<div style="height: 100vh;">
  <incode-flow></incode-flow>
</div>

<!-- Fixed height modal -->
<div style="height: 600px; width: 400px;">
  <incode-flow></incode-flow>
</div>
```

## Spinner Customization  
The loading spinner displayed during flow initialization, module loading, and transitions exposes four tokens:

### CSS
```css
:root {
  /* Spinner icon colors */
  --spinner-surface-primary: #0066cc; /* foreground arc */
  --spinner-surface-secondary: #e6f0ff; /* track */

/* Spinner text */
  --spinner-text-title: #1a1a1a;
  --spinner-text-subtitle: #666666;
}
```

### Spinner Sizes  
The spinner component supports three sizes that you can configure via the `spinnerConfig` prop:

| Size   | Icon Dimension |
|--------|----------------|
| `small`  | 24px          |
| `medium` | 48px (default) |
| `large`  | 64px          |

### CSS Class Targeting  
You can also target spinner classes directly:

### CSS
```css
/* Main spinner container */
.IncodeSpinner {
  /* your styles */
}

/* Full-screen spinner overlay */
.IncodeSpinnerFullScreen {
  /* your styles */
}

/* Spinner content wrapper */
.IncodeSpinnerContent {
  /* your styles */
}

/* Wrapper around title + subtitle */
.IncodeSpinnerText {
  /* your styles */
}

/* Title and subtitle text */
.IncodeSpinnerTitle {
  /* your styles */
}

.IncodeSpinnerSubtitle {
  /* your styles */
}
```

## Key CSS Variables  
A high-level cheat sheet of the categories you'll most often override. The full inventory ships in `@incodetech/web/themes/light.css` and `@incodetech/web/themes/dark.css` — inspect them in your browser's devtools or your bundler's source view to see every variable.

| Category | Examples |
| --- | --- |
| **Brand** | `--primitive-color-brand-{50..600}` (override these to re-skin everything) |
| **Surfaces** | `--surface-neutral-{0..1000}`, `--surface-brand-{50,100,500,500-static,600-static}`, `--surface-status-{negative,warning,positive}-{50,500}` |
| **Text** | `--text-body-{0,400,500-secondary,800-primary}`, `--text-link-{default,hover,visited,disabled}`, `--text-accent-brand`, `--text-status-{negative,warning,positive}` |
| **Borders** | `--border-neutral-{100,400}`, `--border-status-{negative,warning,positive,focus}` |
| **Buttons** | `--button-{primary,secondary,tertiary}-{surface,text,border}-{default,hover,pressed,disabled}`, `--button-*-border-radius` |
| **Inputs** | `--input-{surface,border,icon,text-field,text-helper,text-label}-{default,focused,disabled,negative}` |
| **Spinner** | `--spinner-surface-{primary,secondary}`, `--spinner-text-{title,subtitle}` |
| **Layout** | `--spacing-{2..96}`, `--border-radius-{none,x-small,small,medium,large,x-large,xx-large,full}` |
| **Type** | `--primitive-typography-family-*`, `--primitive-typography-size-{12..80}`, `--primitive-typography-weight-{regular,medium,semibold,bold}` |
