# Token Contract

Every builtin theme must define a minimum set of semantic tokens, styles, and gradients. This contract ensures that consuming applications can rely on these names existing in any theme.

## Required Tokens (26)

These tokens must be present in every builtin theme:

### Text (4)

```
text.primary
text.secondary
text.muted
text.dim
```

### Background (5)

```
bg.base
bg.panel
bg.code
bg.highlight
bg.selection
```

### Accent (4)

```
accent.primary
accent.secondary
accent.tertiary
accent.deep
```

### Status (4)

```
success
error
warning
info
```

### Border (2)

```
border.focused
border.unfocused
```

### Code (7)

```
code.keyword
code.function
code.string
code.number
code.comment
code.type
code.line_number
```

## Required Styles (13)

```
keyword
line_number
selected
active_selected
focused_border
unfocused_border
success_style
error_style
warning_style
info_style
dimmed
muted
inline_code
```

## Required Gradients (5)

```
primary
warm
success_gradient
error_gradient
aurora
```

## Name Constants

The `opaline::names` module provides compile-time constants for every required token, style, and gradient:

```rust
use opaline::names::{tokens, styles, gradients};

// tokens::TEXT_PRIMARY      → "text.primary"
// styles::KEYWORD           → "keyword"
// gradients::AURORA          → "aurora"
```

Use these instead of raw strings for autocomplete support and typo prevention.

## Enforcement

The contract is enforced by integration tests in `tests/builtins_tests.rs`. Every builtin theme is loaded and checked for all required tokens, styles, and gradients.

```rust
// From builtins_tests.rs
#[test]
fn all_builtins_have_required_tokens() {
    for &(id, _) in builtins::builtin_names() {
        let theme = builtins::load_by_name(id).expect("loads");
        for &token in REQUIRED_TOKENS {
            assert!(
                theme.has_token(token),
                "theme '{id}' missing required token: {token}"
            );
        }
    }
}
```

## Adding Tokens to Your Theme

If you're creating a custom theme, you don't need to satisfy the full contract — it's only enforced for builtins. However, following the contract ensures your theme works with any Opaline-powered app. Domain-specific semantics such as git status colors, diff colors, and mode indicators should be derived by the consuming app instead of being treated as core contract names.

Use the [custom themes template](../guide/custom-themes) as a starting point.
