## CSS Customization

The theme uses CSS variables with fallback defaults. Override them in your own CSS:

```css
:root {
  --layout-width-override: 1280px; /* wider layout */
  --layout-sidebar-width-override: 280px; /* left rail (nav / TOC) */
  --layout-sidebar-width-right-override: 240px; /* right on-this-page rail */
}
```

See [Page frontmatter](/api/page-frontmatter) for the adaptive 1/2/3-column
layout and [Menu collection](/api/menu-collection) for the section navigation.

For customizing theme, use `theme.hue` and `theme.saturation` in the integration config — it's the single source of truth for both the site CSS and the auto-generated OG image. `saturation` is a 0-100 multiplier applied to surfaces, text, accent, and border chromas: default 50 keeps the current look, 0 renders fully monochrome, 100 doubles every chroma. Code syntax colors use their own tuned chromas and follow the hue only, so readability is preserved at any saturation.

### Picking a theme

Enable `themePicker: true` in the integration config to show a combined hue + saturation picker on the page. Drag the hue ring and the saturation slider to find the right values, then hardcode them with `theme.hue` / `theme.saturation` and remove `themePicker`:

```js
docsTheme({
  // ...
  theme: { hue: 135, saturation: 70 },
});
```

The picker persists its values to `localStorage`, so you can test across page loads. Once you've settled, turn it off: the picker is a setup tool, not a production feature.

### Color tokens

| Token                    | Light         | Dark          |
| ------------------------ | ------------- | ------------- |
| `--color-surface-1`      | 99% lightness | 12% lightness |
| `--color-surface-2`      | 98%           | 18%           |
| `--color-surface-3`      | 96%           | 21%           |
| `--color-accent`         | 55%           | 65%           |
| `--color-text-primary`   | 15%           | 90%           |
| `--color-text-secondary` | 40%           | 75%           |
| `--color-border`         | 90%           | 25%           |

### Typography and spacing

Text sizes from `--text-xxs` (0.625rem) to `--text-2xl` (2rem). Spacing base `--spacing` is 4px. Border radii: `--radius-sm` (4px), `--radius-md` (8px).

### Responsive breakpoints

Each breakpoint comes as a max-width query and a matching min-width one, offset by 1px so the pair never both match:

```css
@custom-media --mobiles (max-width: 48rem); /* 768px */
@custom-media --min-tablets (min-width: 47.9375rem); /* 767px */
@custom-media --tablets (max-width: 64rem); /* 1024px */
@custom-media --min-laptops (min-width: 63.9375rem); /* 1023px */
@custom-media --laptops (max-width: 80rem); /* 1280px */
@custom-media --min-desktop (min-width: 79.9375rem); /* 1279px */
```

Import `astro-pigment/styles/media.css` to use these in your own CSS. The theme's own layout uses `--tablets` to collapse the rails into popovers and `--min-laptops` to hide the popover triggers, so matching those queries keeps custom CSS in step with the layout.

## Fonts

The integration auto-injects bundled **Martian Grotesk** (variable weight sans) and **Martian Mono** (400 monospace), setting `--font-sans` and `--font-mono` CSS variables. Pass `theme.fonts: false` to opt out and provide your own via Astro's top-level `fonts` field.

```js
// Opt out of bundled fonts and use your own
docsTheme({
  // ...
  theme: { fonts: false },
}),
// then in defineConfig:
fonts: [
  { provider: fontProviders.google(), name: "Inter", cssVariable: "--font-sans" },
  { provider: fontProviders.google(), name: "Fira Code", cssVariable: "--font-mono" },
],
```
