AkurAI Build
Menu

Public repository / 91bd2a37654909c5a3aef6ddd614991bd378ccb8

AkurAI-Framework / site/content/docs/design-system/foundations.md

Latest change d3aacc97a3d97591d3118c06cb7678a33241191b - docs: document v0.8.0 named theme system by Ólafur Búi Ólafsson

# Foundations

The foundations are the design tokens every component reads from. They are plain
CSS custom properties declared once on `:root` in `styles.css` — no
preprocessor, no theme compiler. Change a token, reload, and every component
that consumes it updates. Components must never hard-code a colour, radius, or
shadow; they reference a token so the system stays coherent and themeable.

> **Status legend** — ✅ shipped · 🟡 partial · ⬜ planned. Foundations marked
> ⬜ are tokens we intend to add as the system grows; they are named here so
> components can be specified against them before they land.

## Colour ✅

Surfaces, from furthest-back to nearest-front, then text, then semantic accents.
The token names below are the **stable contract** every component reads. Their
values come from the active theme — the multi-theme system ships 17 named themes
in both dark and light variants (see [Themes](/docs/design-system/themes)).
Values shown are the AkurAI default (dark).

```
--bg        #0a0c11   page background (deepest)
--bg-2      #0f131b   recessed background
--panel     #141925   raised surface (cards, inputs)
--panel-2   #1a2030   raised surface, one step up
--border    #232b3b   hairline divider / control border
--border-2  #2c3650   stronger border (hover, emphasis)
--fg        #e7ebf3   primary text
--muted     #8a93a8   secondary text, labels
--dim       #5c647a   tertiary text, disabled
--accent    #5b8cff   brand / primary action
--accent-2  #8a6bff   gradient companion to --accent
--ok        #3ddc84   success
--warn      #f5b945   warning
--info      #58b2ff   info
--danger    #ff6b6b   error / destructive
```

**Usage rule** — text colour comes from `--fg` / `--muted` / `--dim`; never set a
raw hex in a component. Semantic colours (`--ok`/`--warn`/`--info`/`--danger`)
are only for status meaning, never decoration. Tints are derived live with
`color-mix(in srgb, var(--ok) 10%, var(--panel))` rather than hand-mixed hexes.

## Typography 🟡

One system font stack today; a token-driven type scale is planned so headings,
body, and captions all snap to fixed steps.

```
--font-sans  ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif   ✅
--mono       ui-monospace, "SF Mono", "JetBrains Mono", Menlo, monospace                ✅

--text-xs    12px / 1.4     ⬜    captions, eyebrows, table headers
--text-sm    13px / 1.5     ⬜    labels, secondary
--text-base  16px / 1.65    ⬜    body (current default)
--text-lg    19px / 1.5     ⬜    lede
--text-xl    24px / 1.2     ⬜    section titles
--text-2xl   30px / 1.15    ⬜    page titles
--text-3xl   clamp(34px,6vw,60px) ⬜  hero
```

**Usage rule** — body sets `font: 16px/1.65 var(--font-sans)`. Headings use
negative letter-spacing (`-0.02em` to `-0.03em`) for tightness. Code uses
`var(--mono)` at ~0.88em of its context.

## Spacing ⬜

The grid is implicit today (per-component padding). We want one 4px-based scale
so gaps and padding are never arbitrary.

```
--space-1   4px      --space-4   16px     --space-8   48px
--space-2   8px      --space-5   24px     --space-10  64px
--space-3   12px     --space-6   32px     --space-12  88px
```

**Usage rule** — once shipped, every `gap`/`padding`/`margin` resolves to a
`--space-*` step. Component demos already cluster at 12/14/18/24px — those become
`--space-3`/`--space-4`/`--space-5`.

## Radius ✅

```
--radius      14px    ✅   cards, panels, large surfaces
--radius-sm   9px     🟡   inputs, small controls (in use, not yet tokenised)
--radius-btn  10px    🟡   buttons (in use, not yet tokenised)
--radius-pill 999px   🟡   badges, pills, status dots
```

**Usage rule** — promote the in-use literals (9px/10px/999px) to tokens so the
whole system rounds consistently.

## Elevation & shadow ✅

```
--shadow   0 24px 60px -28px #000   ✅   floating panels, dropdowns, modals
```

Buttons and inputs carry their own focal glow rather than a drop shadow:
`box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 25%, transparent)` for
focus, `0 10px 26px -12px var(--accent)` for the primary button. A small set of
elevation steps (`--shadow-sm`/`-md`/`-lg`) is planned ⬜.

## Motion ⬜

Interactions today use ad-hoc durations (`transform .04s`, `filter .15s`). We
want a motion scale so every transition feels of one piece.

```
--ease       cubic-bezier(.2, .7, .3, 1)   ⬜
--dur-fast   80ms     ⬜    press, hover
--dur-base   150ms    ⬜    colour / background
--dur-slow   240ms    ⬜    overlays entering
```

**Usage rule** — respect `prefers-reduced-motion`; overlays and toasts must drop
to opacity-only transitions when it is set.

## Z-index ⬜

A named stacking order prevents overlay wars. Current literals: nav `20`. Target:

```
--z-base      0       --z-dropdown  1000     --z-toast     1200
--z-sticky    20      --z-overlay   1100      --z-tooltip   1300
```

## Breakpoints 🟡

One breakpoint exists today; we name the rest for responsive component specs.

```
sm   ≤ 640px    ⬜
md   ≤ 820px    ✅   (the current grid-collapse point)
lg   ≤ 1080px   🟡   (container max-width)
xl   ≥ 1280px   ⬜
```

## Theming ✅

Because everything is tokens on `:root`, a theme is just an alternate token set.
The framework ships 17 named themes in dark and light variants, generated by
`crates/css::theme` into `/themes.css`. Each theme is a
`:root[data-theme="slug"]{…}` block that sets all the tokens above. The first
theme (`akurai`) is also emitted as the bare `:root` default so a page without an
explicit `data-theme` still renders correctly.

A zero-dependency ESM switcher (`theme.js`) reads `localStorage` and
`prefers-color-scheme` to select a theme before first paint, and mounts an
optional picker wherever a `[data-theme-picker]` slot exists. See
[Themes](/docs/design-system/themes) for the full theme list, wiring guide, and
instructions for adding a new theme.