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

# Styling

> Configure component styling, themes, and design tokens.

Components emit classes bound to Ekanos's semantic design tokens. You control theming through imports and CSS.

## Stylesheet options

### Option 1: Pre-compiled stylesheet (standalone)

```ts theme={null}
import '@ekanos/ui/styles.css';
```

Self-contained: Tailwind Preflight, design tokens, light and dark, and every utility class this package's components emit — derived by compiling the class strings found in the built bundles. Nothing else to install, no build step, no config; it works in Next.js, Vite, CRA, or a plain `<link rel="stylesheet">`.

**Limits:**

* A Tailwind class *you* write in your own markup (`p-8`, `grid-cols-3`) has no rule in it and does nothing. Style your own markup with plain CSS, or take the Tailwind path.
* Preflight is a global reset: it normalises margins, headings, and form controls across your whole page. If that is unwelcome, use the Tailwind path and control layering yourself.

### Option 2: Tailwind integration (with your build)

```css theme={null}
/* In your main CSS entry point */
@import 'tailwindcss';
@import '@ekanos/ui/theme.css';
```

Registers the token map (`--color-primary` → `--primary`, the `--radius-*` scale, the `shadow-*` elevation utilities), the token values for both themes, the base rules, the `dark:` variant, and an `@source` pointing at this package's bundles so your Tailwind v4 build generates the components' utilities itself. You then get the Ekanos tokens in your own class strings too.

<Warning>
  Pick **one** path. Do not also import `styles.css`: loading both means two
  copies of every utility.
</Warning>

## Individual pieces (advanced)

`theme.css` already includes both of these. They are published separately if you want the pieces:

* `@ekanos/ui/tokens.css` — just the custom properties (light and dark), no Tailwind at-rules
* `@ekanos/ui/base.css` — the base rules: a default border colour, the missing-icon placeholders, and the opt-in `.ekanos-root` page shell (no Preflight)

Neither registers the Tailwind token map or `@source`, so on their own they do not make Tailwind generate the components' utilities.

## Design tokens

### Semantic color tokens

| Token | Used for |
| - | - |
| `--primary` / `--primary-foreground` | Brand color, active states, CTAs |
| `--background` / `--foreground` | Page background, primary text |
| `--card` / `--card-foreground` | Card surfaces |
| `--secondary` / `--secondary-foreground` | Secondary actions |
| `--muted` / `--muted-foreground` | Subdued backgrounds, secondary text |
| `--accent` / `--accent-foreground` | Hover states, highlighted items |
| `--destructive` / `--destructive-foreground` | Danger actions, error states |
| `--border` | Component borders |
| `--input` | Form input borders |
| `--ring` | Focus rings |

`tokens.css` is generated from Ekanos's own design system and checked by value in the package build, so the preset matches the app exactly. As of 0.4.0 that includes the `-strong` text steps for status colors (`--destructive-strong`, `--warning-strong`, `--info-strong`, with `text-warning-strong` and `text-info-strong` utilities) and `--favorite` (`text-favorite`), which were missing or stale before. Overlays also use the elevation tiers: dialogs take `shadow-modal`, select and dropdown menus take `shadow-popover`, and inputs, textareas and select triggers fill with `bg-card` so they stay visible on the warm page background.

`tokens.css` also carries status (`success`, `warning`, `info`), chart (`--chart-1`…`--chart-5`), sidebar, and assistant tokens, the elevation scale, `--radius`, and the fonts.

### Tailwind classes

```tsx theme={null}
<div className="bg-background text-foreground">  {/* Page background */}
<div className="bg-card border border-border">   {/* Card surface */}
<button className="bg-primary text-primary-foreground">  {/* Primary button */}
<span className="text-muted-foreground">   {/* Secondary text */}
```

### Elevation tokens (shadows)

```tsx theme={null}
<div className="shadow-card">      {/* Card elevation */}
<div className="shadow-widget">    {/* Widget elevation */}
<div className="shadow-popover">   {/* Popover elevation */}
```

The Tailwind path exposes the full scale: `shadow-flat`, `shadow-sunken`, `shadow-inset`, `shadow-card`, `shadow-widget`, `shadow-rail`, `shadow-popover`, `shadow-sticky`, `shadow-modal`, `shadow-overlay`. The compiled `styles.css` includes only what the components use (`shadow-card`).

### Spacing, radius, typography

```tsx theme={null}
<div className="p-5 space-y-5">            {/* Standard Tailwind spacing */}
<button className="rounded-md">            {/* --radius-md: calc(var(--radius) - 2px) */}
<h1 className="text-2xl font-heading">    {/* Heading font */}
<p className="text-sm font-sans">          {/* Body font */}
```

## Dark mode

Dark mode is applied by CSS class or attribute, with a fallback to OS preference:

| Condition | Result |
| - | - |
| `.dark` or `[data-theme='dark']` on an ancestor | Dark, beating the media query |
| `.light` or `[data-theme='light']` on `:root` | Light, beating the media query |
| `@media (prefers-color-scheme: dark)` | Dark |
| Nothing set | Light |

So an app with no theme toggle still follows the OS, and one with a toggle works by setting the class or attribute.

### With next-themes

```tsx theme={null}
import { ThemeProvider } from 'next-themes';

<ThemeProvider attribute="class" defaultTheme="system">
  <YourApp />
</ThemeProvider>;
```

### With plain JavaScript

```tsx theme={null}
function toggleDark() {
  document.documentElement.classList.toggle('dark');
}
```

### With data attributes

```tsx theme={null}
function setTheme(theme: 'light' | 'dark') {
  document.documentElement.setAttribute('data-theme', theme);
}
```

## Page background

The stylesheet doesn't force a page background. To adopt Ekanos's surface (which makes dark mode look right):

```html theme={null}
<body class="ekanos-root">
  <!-- content -->
</body>
```

`.ekanos-root` sets `background-color: var(--background)`, `color: var(--foreground)`, `font-family: var(--font-sans)`, and font smoothing. You can put it on `<body>` or on any wrapper around Ekanos UI.

Without it, the stylesheet leaves your page background alone, so in dark mode you get dark cards on whatever background your page already has.

## Customizing tokens

The token values ship inside the `base` cascade layer, so an unlayered rule that redefines a token (for example `:root { --primary: … }`) takes precedence on either path. Redefine it for dark mode too (`.dark`, `[data-theme='dark']`, and the `prefers-color-scheme` case), or the override applies only where you set it.

On the Tailwind path, add your own colours with Tailwind v4's CSS-first `@theme` block as usual; the components keep using the semantic tokens.

## Fonts

Ekanos pairs **Figtree** (body) with **Bricolage Grotesque** (headings). This package names them in `--font-sans` / `--font-heading` but doesn't load them; no webfont is bundled or fetched.

To match Ekanos exactly, load them yourself:

```html theme={null}
<link
  rel="stylesheet"
  href="https://fonts.googleapis.com/css2?family=Figtree:wght@300..700&family=Bricolage+Grotesque:wght@200..800&display=swap"
/>
```

Or use your project's fonts. Everything still renders with the package's system fallback stack.

## Troubleshooting

### Styling not applied to components

1. Check that you imported either `styles.css` (standalone) or `theme.css` (Tailwind), not both
2. If using Tailwind, import `theme.css` after `@import 'tailwindcss'`; its `@source` points Tailwind at the package's bundles, so you do not add one by hand
3. If only your own classes are unstyled on the `styles.css` path, that is expected: it contains only the components' utilities

### Dark mode not working

1. Check that an ancestor has `.dark` or `[data-theme='dark']`, or that the OS prefers dark and `:root` has no `.light` / `[data-theme='light']`
2. If using `next-themes`, verify it wraps your app with `attribute="class"`
3. If cards are dark but the page is not, add `class="ekanos-root"`

### Fonts look wrong

Load Figtree and Bricolage Grotesque from Google Fonts (or your own CDN). The package defines `--font-sans` and `--font-heading` but doesn't include the font files.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.