
# Themes

> Kesko Themes ships per-brand CSS overrides for our design tokens. Each theme swaps the themeable subset of design tokens while leaving the rest of the token set unchanged.

## Installation

To install Kesko Themes as a dependency in your project, run:

```sh [npm]
npm install @kesko/themes
```

```sh [pnpm]
pnpm add @kesko/themes
```

```sh [yarn]
yarn add @kesko/themes
```

```sh [bun]
bun add @kesko/themes
```

> Warning: Kesko Themes are in active development and not yet ready for production use. Token coverage and file names may change without notice.

---

## Usage

A theme file is an override stylesheet. Import the [CSS Framework](/css/) first, then apply a brand theme on top:

```css
@import "@kesko/css/dist/kesko.min.css";
@import "@kesko/themes/dist/kespro.css";
```

Or from HTML:

```html
<link rel="stylesheet" href="@kesko/css/dist/kesko.min.css" />
<link rel="stylesheet" href="@kesko/themes/dist/kespro.css" />
```

### Dark mode

For dark mode, load the dark variant instead of the light one:

```css
@import "@kesko/css/dist/kesko.min.css";
@import "@kesko/themes/dist/kespro-dark.css";
```

Each file also sets `color-scheme: light` or `color-scheme: dark`, so native browser UI such as scrollbars and form controls adapts automatically.

### Switching between modes

When both modes need to be available at runtime, scope each file to `prefers-color-scheme` or to an attribute you control yourself:

```html
<link rel="stylesheet" href="/css/kespro.css" media="(prefers-color-scheme: light)" />
<link rel="stylesheet" href="/css/kespro-dark.css" media="(prefers-color-scheme: dark)" />
```

For explicit user control, toggle a `data-theme-mode` attribute on the root element and load the matching file in CSS:

```css
@import "@kesko/themes/dist/kespro.css" (prefers-color-scheme: light);
@import "@kesko/themes/dist/kespro-dark.css" (prefers-color-scheme: dark);
```

---

## Themeable tokens

By default, each brand overrides a subset of `@kesko/tokens` listed below. All other tokens such as motion, shadows, layers, opacity, and the full primitive palette inherit from `@kesko/tokens` unchanged.

| Category        | Tokens                                                                                                                                        |
| --------------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
| Accent colors   | `--k-color-accent`, `--k-color-accent-secondary`                                                                                              |
| Text on surface | `--k-color-text-on-accent`, `--k-color-text-on-secondary`, `--k-color-text-on-disabled`, `--k-color-text-on-decorative`                       |
| Inline text     | `--k-color-text-link`                                                                                                                         |
| Borders         | `--k-color-border-divider`                                                                                                                    |
| Fills           | `--k-color-fill-decorative`, `--k-color-fill-secondary`                                                                                       |
| Backgrounds     | `--k-color-bg-highlight`, `--k-color-bg-disabled`, `--k-color-bg-hover`, `--k-color-bg-inverted`, `--k-color-bg-subtle`, `--k-color-bg-muted` |
| Radius          | `--k-radius-button`, `--k-radius-input`, `--k-radius-checkbox`, `--k-radius-element`                                                          |
| Spacing         | `--k-space-button`                                                                                                                            |

---

### `{brand}.css`

Light mode overrides. Contains only the themeable tokens as resolved values under `:root`.

```css
:root {
  color-scheme: light;
  --k-color-accent: #cb4700;
  --k-color-accent-secondary: #552c87;
  --k-radius-button: 0.25rem;
  /* ... */
}
```

### `{brand}-dark.css`

Complete dark mode. Contains all semantic color tokens (backgrounds, text, borders, fills, status, overlay) from the base dark theme, plus brand-specific dark overrides.

```css
:root {
  color-scheme: dark;
  --k-color-bg: #1b1b1b;
  --k-color-text: #ededed;
  --k-color-accent: #f86800;
  /* ... */
}
```

### `{brand}.json`

JSON describing both light and dark resolved values, including the original alias reference and an `auto` flag that indicates whether each dark value was auto-generated or manually overridden:

```json
{
  "meta": { "name": "kespro" },
  "light": {
    "--k-color-accent": { "value": "#cb4700", "ref": "{color.orange.800}" }
  },
  "dark": {
    "--k-color-accent": { "value": "#f86800", "ref": "{color.orange.700}", "auto": true }
  }
}
```

---

## Dark mode generation

Dark mode is produced from two layers, in order:

1. **Base dark theme:** `@kesko/tokens` ships a `dark` mode config that maps every semantic color token to its dark equivalent. It uses the dedicated `neutral-dark` palette for neutrals and the [palette symmetry rule](/colors/#dark-mode) for saturated colors.
2. **Brand dark overrides:** each brand's theme may include a `dark:` section for tokens where the auto-mirrored value needs adjustment.

```yaml

# Light mode overrides
color:
  accent:
    base:
      value: "{color.orange.800}"

# Optional: manual dark mode overrides
dark:
  color:
    accent:
      base:
        value: "{color.orange.700}"
```

When a brand token has no explicit `dark:` entry, the symmetry rule produces the mirrored value automatically and the JSON output marks it with `"auto": true`.
