> ## Documentation Index
> Fetch the complete documentation index at: https://docs.kerne.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Styling & language

> Match the screens to your brand, and translate what they say

There is no CSS file to import. The screens inject their own stylesheet once, and everything they draw resolves from `--kerne-*` custom properties — so you restyle by setting those, not by fighting selectors.

<Warning>
  There is no `styles.css` you can import or override, on purpose — theming is exclusively `appearance` and the `--kerne-*` variables below. Under a strict CSP `style-src` that omits `'unsafe-inline'`, this runtime injection is blocked and the screens render unstyled. There is no workaround today.
</Warning>

## Your colors

Set the properties anywhere in your own CSS to change every screen at once:

```css theme={"system"}
:root {
  --kerne-primary: #1d6b52;
  --kerne-accent: #1d6b52;
  --kerne-radius: 2px;
  --kerne-font: Georgia, serif;
}
```

Or per instance, with `appearance`:

```tsx theme={"system"}
<AuthFlow
  appearance={{
    primaryColor: '#1d6b52',
    radius: '2px',
    fontFamily: 'Georgia, serif',
  }}
/>
```

`primaryColor` is usually the only one you need. From it the screens also derive the label on the primary button, its hover, and the accent used for focus rings and links — so a light brand color gets a dark label instead of an unreadable white one, and a branded button no longer turns grey under the cursor. Override any of those with `primaryTextColor` and `accentColor` when you want something else.

`appearance` accepts `primaryColor`, `primaryTextColor`, `accentColor`, `textColor`, `borderColor`, `panelColor`, `background`, `surfaceColor`, `surface`, `fontFamily`, `radius`, `controlHeight`, and `theme`.

Color derivation reads `#rgb`, `#rrggbb` and `rgb()`. Anything else — a named color, `hsl()`, a `var()` reference — is used as-is and nothing is derived from it, so set `primaryTextColor` yourself in that case.

## Light and dark

The screens are light unless you say otherwise. They do **not** follow the visitor's system setting by default: your product decides what it looks like, and a light-only app should not render a dark sign-in form for half its users.

```tsx theme={"system"}
<AuthFlow appearance={{ theme: 'dark' }} />
```

If your app has its own dark mode, pass whichever one is active:

```tsx theme={"system"}
<AuthFlow appearance={{ theme: isDark ? 'dark' : 'light' }} />
```

Use `'system'` to opt into following the visitor's OS setting instead.

## Standing on their own

The screens ship flat — no card, no border — because they are built to drop into a page you already designed. When the component *is* the page (a dedicated `/login` route, a hosted portal), `surface: 'card'` gives it a container of its own:

```tsx theme={"system"}
<AuthFlow appearance={{ surface: 'card', surfaceColor: '#ffffff' }} />
```

Tell it about its background with `background` whenever the component owns the viewport — that is what lets its text and its ground resolve together instead of independently.

## Your logo

```tsx theme={"system"}
<AuthFlow logo={<img src="/logo.svg" alt="Acme" width={120} />} />
```

## What the screens do on their own

You do not wire any of this — it is what the prebuilt forms already handle:

* **Password fields** carry a show/hide toggle, warn when Caps Lock is on, and — where a password is being *set* — show the tenant's requirements as a checklist (length by default, plus uppercase/number/symbol if the tenant turned them on) until every one is met, then switch to an advisory strength meter. Only the checklist gates the submit button, and it mirrors the server's policy exactly; the meter never does, so a password it scores low can't be rejected client-side when the server would accept it.
* **Errors land on the field they belong to** rather than in one banner above the form, so there is nothing to guess at when a submit fails.
* **Buttons show a spinner while a request is in flight**, instead of only swapping their label.
* **Outcomes are announced** to screen readers — failures assertively, confirmations politely.
* **The first field is focused only where there is a real pointer**, so arriving on a phone does not throw the keyboard over the screen.

## Language

Every string the screens render — including the error messages — comes from one dictionary. Override what you need on the provider; anything you leave out stays in English.

```tsx theme={"system"}
import { KerneProvider } from '@kerne/react';

<KerneProvider
  appId="your-app-id"
  localization={{
    signIn: {
      title: 'Content de vous revoir',
      submit: 'Se connecter',
      magicSubmit: 'Recevoir un lien de connexion',
    },
    common: {
      email: 'E-mail',
      password: 'Mot de passe',
    },
  }}
>
  {children}
</KerneProvider>;
```

### Error messages

Errors are keyed by the API's error code, so you control exactly what a user reads when something fails:

```tsx theme={"system"}
localization={{
  errors: {
    K1005: 'Adresse e-mail ou mot de passe incorrect.',
    K5001: 'Vous avez atteint la limite incluse dans votre offre.',
    generic: 'Une erreur est survenue. Réessayez.',
  },
}}
```

Codes you do not map fall back to `generic`. The raw API message is never shown — it is written for you, the developer, not for your users.

See [Error codes](/concepts/error-codes) for the full list.

### French

A complete French pack ships as `fr` — pass it directly, or layer overrides on top of it with `mergeLocalization`:

```tsx theme={"system"}
import { KerneProvider } from '@kerne/react';
import { fr } from '@kerne/react/ui';

<KerneProvider appId="your-app-id" localization={fr}>
  {children}
</KerneProvider>;
```

```tsx theme={"system"}
import { mergeLocalization, fr } from '@kerne/react/ui';

// override is the first argument, the pack to merge onto is the second (defaults to English)
const localization = mergeLocalization({ common: { email: 'Adresse professionnelle' } }, fr);
```

No other language ships yet — everything else falls back to English unless you override it yourself.

### Starting from the defaults

`defaultLocalization` is exported if you want to see every key, or build a translation on top of it:

```tsx theme={"system"}
import { defaultLocalization } from '@kerne/react';
```
