# Theming

> Themes, colour schemes, fonts, and per-deck styling

## Tailwind first

Every Narro component takes `className`, and it is merged with the component's
own classes rather than replacing them. Where the two conflict, yours wins:
`<Heading className="text-[13rem]">` is 13rem, not the level's default size, and
you never need an `!` prefix to say so. For most decks this is the whole theming
story:

```tsx
<Slide className="bg-gradient-to-br from-slate-900 to-blue-950">
  <Heading level={1} className="text-accent">Title</Heading>
</Slide>
```

In markdown, the same thing via the attribute syntax:

```markdown
# Title {.text-accent}
```

…or `class:` in slide frontmatter to style the whole slide, or on the deck
frontmatter to set a default for every slide.

## Colours that follow the theme

`text-accent` above is not a colour someone chose. It is the theme's accent, and
it changes when `theme:` changes — no `deck.css`, no component, no React.

Every built-in theme defines the same six colour roles and three font roles, and
Narro emits them as Tailwind theme tokens, so each one is a whole utility
namespace:

| Roles | Utilities |
| --- | --- |
| <!-- generated:theme-color-tokens -->`accent`, `background`, `foreground`, `muted`, `primary`, `secondary`<!-- /generated:theme-color-tokens --> | `text-*`, `bg-*`, `border-*`, `ring-*`, `from-*`, and the rest of the colour namespace |
| `heading`, `body`, `mono` | <!-- generated:theme-font-utilities -->`font-body`, `font-heading`, `font-mono`<!-- /generated:theme-font-utilities --> |

The whole list is in [`catalog.json`](/catalog.json) under `themeUtilities`.

**Use a role wherever the colour *is* a role.** A callout border, a highlighted
card, an emphasised heading, the good branch of a diagram — those are "the accent
colour", not "cyan 400", and writing them as roles is what lets one deck ship in
eleven themes:

```markdown
:::{.border-l-4 .border-accent .bg-foreground/5 .p-6}

This card restyles itself with the deck.

:::
```

**Reach for a palette colour when the colour is the point.** A chart series where
red means "worse", a brand swatch, a screenshot's matching background — those
should not move when the theme does. `{.bg-cyan-400}` names a fixed hue and keeps
it, which is correct here and wrong for the card above.

The distinction matters most in single-file markdown mode, where a `deck.css` is
not available: a deck built out of palette colours is locked to one theme by
construction, and a deck built out of roles is not.

## Themes

`@getnarro/marketplace` ships themes as design tokens plus optional layout
overrides:

```bash
narro themes          # browse and apply
```

```markdown
---
theme: corporate-dark
---
```

Built-in themes: <!-- generated:themes-inline -->`default`, `corporate-dark`, `minimalist-light`, `creative-gradient`, `ocean-blue`, `forest-green`, `sunset-warm`, `midnight-purple`, `tech-dark`, `startup-bold`, `academic-classic`<!-- /generated:themes-inline -->.
Colour schemes: <!-- generated:color-schemes-inline -->`ocean-blue`, `sunset-warm`, `forest-mist`, `royal-purple`, `rose-gold`, `arctic-blue`, `charcoal-slate`, `emerald-night`<!-- /generated:color-schemes-inline -->.

A theme can also supply layouts. Layout names resolve most-specific-first — the
deck's own `layouts/` directory, then the deck template, then the theme, then
the built-ins — so overriding one layout never means forking the others.

## Themes and deck templates

A theme is a palette someone else shipped. A [deck template](/docs/deck-templates)
is the house style for *your* deck: one file beside it holding the tokens, the
chrome every slide carries — footer, logo, slide numbers — and a set of layouts
addressed by id.

| | Theme | Deck template |
| --- | --- | --- |
| Where it comes from | `@getnarro/marketplace`, by name | a file beside the deck |
| What it sets | colours and fonts | colours, fonts, chrome, layouts, defaults |
| Named layouts | a theme may ship some | that is the point of it |
| Checked by `narro check` | the name exists | the whole shape, plus every id and slot |

They compose: `theme:` for the palette, `template:` for the layouts, and the
template wins where they overlap. Reach for a theme to change how a deck looks
in one line; reach for a template when the same look has to hold across forty
slides.

## Fonts

```tsx
import { applyFontPreset } from "@getnarro/core";

applyFontPreset("inter");
```

Presets: <!-- generated:font-presets-inline -->`system`, `inter`, `roboto`, `openSans`, `lato`, `montserrat`, `poppins`, `raleway`, `sourceSerif`, `playfairDisplay`, `merriweather`, `jetBrainsMono`<!-- /generated:font-presets-inline -->.

Or set them directly on the presentation:

```tsx
<Presentation
  theme={{
    fontHeading: '"Inter", sans-serif',
    fontBody: '"Inter", sans-serif',
    fontMono: '"JetBrains Mono", monospace',
  }}
>
```

Presets load from Google Fonts. If the room's network is unreliable, `system`
never fails — and a deck rendered in a fallback font is worse than one that
never asked for a webfont.

## Design tokens

Themes expose Tailwind v4 `@theme` tokens, so custom colours are available as
utilities:

```css
@theme {
  --color-brand-500: #6366f1;
}
```

```markdown
# Title {.text-brand-500}
```

## What `tone` actually looks like

`Badge`, `Card` and `Callout` take a `tone`, and it is a colour role rather than
a colour — which is worth spelling out, because a role you cannot picture is a
prop you pass and then override:

| `tone` | Colour | Follows the theme? |
| --- | --- | --- |
| `default` | The deck's foreground at 5% background, 15% border | Yes — `--slide-fg` |
| `primary` | `--slide-primary` at 12% / 45% (blue by default) | Yes |
| `accent` | `--slide-accent` at 12% / 45% (violet by default) | Yes |
| `success` | Green `#16a34a` at 14% / 50% | **No** — fixed |
| `warning` | Amber `#ca8a04` at 14% / 50% | **No** — fixed |
| `danger` | Red `#dc2626` at 14% / 50% | **No** — fixed |

The first three are the ones that carry a custom deck: they resolve through the
theme, so they change when it does. The last three are deliberately fixed —
green means passing everywhere — which also means that on a deck with its own
palette they are the three you are most likely to override with `className`.
That is expected, and `className` wins.

## Practical advice

Two font sizes and two colours will carry an entire deck. Contrast that reads on
your laptop often disappears on a washed-out projector, so err darker on light
backgrounds and lighter on dark ones. And whatever you pick, apply it on the
deck frontmatter rather than per slide — it is the difference between changing
one line later and changing forty.