# Colors & Fonts

## Colors & Fonts

**Files:** `src/styles/theme.css`, `src/config/fonts.json`, `src/config/config.toml` (`[settings.colorScheme]`) · **Skill level:** Beginner

A rebrand in Homio is a handful of values, not a search-and-replace. Every component uses named color tokens, so changing a token changes it everywhere, including the logo mark and the generated social cards. Homio has a light palette and a dark palette.

<div class="border border-dark">
  ![Homio homepage in dark mode](/images/homio/dark-mode.jpg)
</div>

### Where The Colors Live
Open `src/styles/theme.css`. The values are in two blocks:

- `:root { ... }`: the **light** palette (the default)
- `:root.dark { ... }`: the **dark** palette

Each value is a `--theme-*` variable. Components never use hex codes: they use Tailwind classes such as `bg-sage` or `text-primary`, which read these variables. Change a value in both blocks, and keep the variable names.

### The Color Tokens
| Role                         | Variable                 | Light     | Dark      | Tailwind classes              |
| ---------------------------- | ------------------------ | --------- | --------- | ----------------------------- |
| Page background              | `--theme-body`           | `#ffffff` | `#0e130f` | `bg-body`                     |
| Cards and white surfaces     | `--theme-card`           | `#ffffff` | `#151c16` | `bg-card`                     |
| Soft panels (reviews, blog, FAQ rows) | `--theme-sage`  | `#f2f5ee` | `#151c16` | `bg-sage`                     |
| Light green tint (icon circles, footer panel) | `--theme-mint` | `#e4f3da` | `#1b2e1c` | `bg-mint`             |
| Soft sunflower tint (service cards, quote card) | `--theme-blush` | `#fff6d1` | `#2a2410` | `bg-blush`       |
| Warm cream (the handyman home) | `--theme-cream`        | `#f3f1e6` | `#1a1d16` | `bg-cream`                    |
| **Block green** (the big brand-green blocks) | `--theme-deep` | `#24842f` | `#1d6b27` | `bg-deep`               |
| Deep green (dark blocks, dark footers) | `--theme-forest` | `#163e25` | `#0b1f12` | `bg-forest`                  |
| **Text green** (links, icons, checks) | `--theme-primary` | `#217b2c` | `#6cc576` | `text-primary`, `bg-primary` |
| Text green on hover          | `--theme-primary-hover`  | `#1c6c25` | `#8bd593` | `text-primary-hover`          |
| Text on green                | `--theme-on-primary`     | `#ffffff` | `#0e130f` | `text-on-primary`             |
| **Sunflower** (main pill buttons) | `--theme-accent`    | `#ffd23f` | `#ffd23f` | `bg-accent`                   |
| Sunflower on hover           | `--theme-accent-hover`   | `#f5c518` | `#ffdc66` | `bg-accent-hover`             |
| Text on sunflower            | `--theme-on-accent`      | `#111511` | `#111511` | `text-on-accent`              |
| Dark gold for small accents on white | `--theme-accent-strong` | `#7a5d00` | `#ffd23f` | `text-accent-strong`  |
| Headings (ink)               | `--theme-dark`           | `#111511` | `#eef3ec` | `text-dark`                   |
| Body text                    | `--theme-text-default`   | `#5a615b` | `#a9b5aa` | `text-text-default`           |
| Borders and dividers         | `--theme-border-light`   | `#e2e8dd` | `#263127` | `border-border-light`         |
| Form field borders           | `--theme-border-input`   | `#7d877f` | `#6f7c71` | `border-border-input`         |
| Focus ring                   | `--theme-focus`          | `#24842f` | `#6cc576` | `ring-focus`, `outline-focus` |
| States                       | `--theme-danger`, `--theme-success`, `--theme-warning` | `#b42318`, `#217b2c`, `#9a5a00` | `#f2726a`, `#6cc576`, `#f0b44c` | `text-danger`, ... |

`--theme-light` and `--theme-primary-soft` repeat the mint value, and `--theme-sand` repeats sage. Change them together with `--theme-mint` and `--theme-sage`.

<Aside type="note" title="Two greens: text green and block green">
  Homio uses two nearly identical greens on purpose. `--theme-deep` (`#24842f`)
  fills the big green blocks, where the text is white. `--theme-primary`
  (`#217b2c`) is one shade darker and is used for small green text, links, and
  icons, so it still has a 4.5:1 contrast on the sage and mint panels. If you
  change the brand green, change both, and keep the text green dark enough to
  read on `#f2f5ee`.
</Aside>

### Copies To Change With The Palette
A few values appear twice in `theme.css`. Update them with the main tokens:

- **`--page-*` variables** at the end of `:root` and `:root.dark` (`--page-primary`, `--page-dark`, `--page-text`, ...). Cards on a colored block (a white review card on the green block) use them to get the page colors back. Keep them equal to the matching `--theme-*` values.
- **Static helpers** in the `@theme inline` block, which stay the same in light and dark mode: `--color-emerald` (`#24842f`, the brand green for white text), `--color-sunflower` (`#ffd23f`), `--color-mist` (`#e4f3da`, white button hover), `--color-light` (`#c9d8cc`, text on the deep green footers), and `--color-body-dark` (`#111511`).
- **The colored blocks** under `@layer components`: `.block-deep` (brand-green block), `.block-forest` (deep-green block), and `.block-coral` (the name is kept from an older version: it is the **sunflower** block, with ink text). They set the text and border colors used inside each block.
- **`.band-ink`**: the near-black band, which uses the dark palette inside it.

The `#24842f` green also appears in `src/assets/images/favicon.svg` and the two standalone logo files. Regenerate the favicon after a color change (see [Site Identity & Logo](/homio/customization/site-identity-logo/#favicons)).

<Aside type="tip" title="Picking a button color">
  The main buttons are sunflower pills with dark ink text (`--theme-on-accent`).
  If your brand button color is dark, set `--theme-on-accent` to white, and
  check the contrast: aim for at least 4.5:1 between text and its background.
</Aside>

### Button Styles
Buttons in content files take their look from `variant`:

| You write               | Button                                                       |
| ----------------------- | ------------------------------------------------------------ |
| `variant: "fill"`       | The main pill button, sunflower with ink text                |
| `variant: "accent"`     | A brand-green pill with white text. One per view             |
| `variant: "soft"`       | A soft tinted pill for the second action                     |
| `variant: "outline"`    | An outlined pill                                             |
| `variant: "fill-white"` | A white pill, for photos and dark bands                      |
| `variant: "text"`       | A text link                                                  |

Some sections change a variant to fit their background; the comment next to `variant:` in the section file says when. See [Common Changes](/homio/customization/common-changes/) for every button option.

### Corners
The radius tokens are in the `@theme inline` block of `theme.css`:

| Token             | Value              | Used for                                      | Class           |
| ----------------- | ------------------ | --------------------------------------------- | --------------- |
| `--radius-btn`    | `9999px` (a pill)  | Buttons and icon buttons                      | `rounded-btn`   |
| `--radius-field`  | `0.625rem` (10 px) | Inputs, selects, segmented controls           | `rounded-field` |
| `--radius-ui`     | `1.5rem` (24 px)   | Cards, tiles, images                          | `rounded-ui`    |
| `--radius-panel`  | `2rem` (32 px)     | Large photos and soft panels                  | `rounded-panel` |
| `--radius-block`  | `2rem` (32 px)     | Color blocks and the footer panel             | `rounded-block` |
| `--radius-tag`    | `0.375rem` (6 px)  | Check squares and rating squares              | `rounded-tag`   |

For square buttons, for example, set `--radius-btn: 0.5rem;`. Homio uses no shadows: the shadow scales are reset.

### Fonts
Homio uses three fonts from Google Fonts, set in `src/config/fonts.json`, one entry per role:

| Font           | Role                                       | `cssVariable`     |
| -------------- | ------------------------------------------ | ----------------- |
| Figtree        | Body text, buttons, forms                  | `--font-primary`  |
| Lexend         | Headings and big numbers                   | `--font-heading`  |
| JetBrains Mono | Prices, totals, and ticket codes           | `--font-code`     |

```json
{
  "name": "Lexend",
  "variants": [{ "style": "normal", "weight": "300 600" }],
  "preload": true,
  "display": "swap",
  "cssVariable": "--font-heading",
  "provider": "google",
  "subsets": ["latin"],
  "fallback": "sans-serif"
}
```

To change a font, replace `name` with another Google Font name, exactly as Google writes it (`"DM Sans"`, `"Plus Jakarta Sans"`). Keep `cssVariable`, `provider`, and `fallback`, and keep a `weight` range the new font has: Homio ships 300 to 600 for headings (Lexend) and 400 to 700 for body text (Figtree). Add a subset such as `"latin-ext"` if your language needs it. Then **restart `npm run dev`**: fonts are read only when the server starts.

Astro downloads the fonts and serves them from your own site, so visitors don't load anything from Google.

### Type Sizes
Heading sizes are fluid: they grow from phone to desktop between 375 px and 1280 px wide. They are in `theme.css` as `--text-display`, `--text-h1` to `--text-h6`, `--text-stat` (big numbers), `--text-lead`, `--text-copy` (body, 16 px), `--text-label` (small caps labels), and `--text-total` / `--text-total-lg` (prices). Each has a `--line-height`, `--letter-spacing`, and `--font-weight` beside it. Headings use weight 400.

### Breakpoints
`sm` 540 px, `md` 768 px, `lg` 1024 px, `xl` 1320 px. The mobile action bar shows below `md`; the full header menu shows from `lg`.

### Dark Mode
```toml
# src/config/config.toml
[settings.colorScheme]
  default  = "system" # system | light | dark: used until a visitor picks one
  switcher = true     # Show the light/dark button in the header, mobile menu, and footer
```

- `system` follows the visitor's device setting. `light` or `dark` starts every visitor on that palette.
- The sun and moon button switches it. The visitor's choice is remembered in their browser.
- `switcher = false` hides every button. Visitors then always get `default`, and an earlier choice is ignored. Use `switcher = false` with `default = "light"` for a site without dark mode.

When you change colors, check both palettes. Photos and the sunflower buttons stay the same in dark mode.

### Do It With AI
```text
My brand colors are: green [HEX] and button color [HEX]. In src/styles/theme.css, in :root,
set --theme-deep to my green, and --theme-primary and --theme-primary-hover to darker shades of
it with at least 4.5:1 contrast on #ffffff and #f2f5ee. Set --theme-accent and
--theme-accent-hover to my button color, and --theme-on-accent to black or white, whichever
contrasts more. Make lighter versions for :root.dark. Update the matching --page-* values,
--color-emerald, and --color-sunflower. Keep every variable name. List the values and their
contrast ratios.
```

```text
Change the heading font to [GOOGLE FONT] and the body font to [GOOGLE FONT] in
src/config/fonts.json. Keep the cssVariable values, the provider, and the fallback, and use
weight ranges the fonts have. Don't edit CSS files. Then tell me to restart npm run dev.
```