> ## Documentation Index
> Fetch the complete documentation index at: https://docs.aspfox.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Dark Mode and Theming

> CSS variable theming with next-themes, semantic Tailwind classes, and brand color customization.

## How dark mode works

`next-themes` manages the `dark` class on the `<html>` element. Tailwind's `darkMode: 'class'` strategy reads this class to activate dark-mode variants. The user's preference (light / dark / system) is stored in `localStorage` and restored on every page load.

The theme toggle in the top navigation bar cycles through three states: Light → Dark → System. "System" follows the OS preference.

When a user changes their theme, the change takes effect immediately with no flash of unstyled content (FOUC). `next-themes` injects a small blocking script before the page renders that reads `localStorage` and applies the correct class before the first paint.

## The CSS variable system

All colors are defined as CSS custom properties in `index.css`. Tailwind uses these variables through its theme configuration. Every component uses semantic variable names, not hardcoded colors.

```css theme={null}
/* index.css */
:root {
  --background: 0 0% 100%;
  --foreground: 222 47% 11%;
  --muted: 210 40% 96%;
  --muted-foreground: 215 16% 47%;
  --border: 214 32% 91%;
  --input: 214 32% 91%;
  --primary: 221 83% 47%;        /* #1A56DB */
  --primary-foreground: 0 0% 100%;
  --secondary: 210 40% 96%;
  --secondary-foreground: 222 47% 11%;
  --accent: 210 40% 96%;
  --accent-foreground: 222 47% 11%;
  --destructive: 0 84% 60%;
  --destructive-foreground: 0 0% 100%;
  --ring: 221 83% 47%;
  --radius: 0.5rem;
}

.dark {
  --background: 222 47% 4%;
  --foreground: 213 31% 91%;
  --muted: 223 47% 11%;
  --muted-foreground: 215 16% 57%;
  --border: 216 34% 17%;
  --input: 216 34% 17%;
  --primary: 221 83% 57%;
  --primary-foreground: 0 0% 100%;
  --secondary: 222 47% 11%;
  --secondary-foreground: 213 31% 91%;
  --accent: 216 34% 17%;
  --accent-foreground: 213 31% 91%;
  --destructive: 0 63% 50%;
  --destructive-foreground: 213 31% 91%;
  --ring: 221 83% 57%;
}
```

Tailwind maps these variables to utility classes via `tailwind.config.ts`:

```typescript theme={null}
theme: {
  extend: {
    colors: {
      background: 'hsl(var(--background))',
      foreground: 'hsl(var(--foreground))',
      muted: {
        DEFAULT: 'hsl(var(--muted))',
        foreground: 'hsl(var(--muted-foreground))',
      },
      primary: {
        DEFAULT: 'hsl(var(--primary))',
        foreground: 'hsl(var(--primary-foreground))',
      },
      // ...
    }
  }
}
```

## Writing dark-mode-compatible components

Use semantic class names. The variable flips between light and dark values automatically — you do not write `dark:` variants for basic colors.

**Correct — semantic classes:**

```tsx theme={null}
function ProjectCard({ name, description }: ProjectCardProps) {
  return (
    <div className="rounded-lg border border-border bg-background p-4">
      <h3 className="font-semibold text-foreground">{name}</h3>
      <p className="mt-1 text-sm text-muted-foreground">{description}</p>
    </div>
  );
}
```

**Incorrect — hardcoded colors:**

```tsx theme={null}
// This breaks dark mode. Never do this.
function ProjectCard({ name, description }: ProjectCardProps) {
  return (
    <div className="rounded-lg border border-gray-200 bg-white p-4">
      <h3 className="font-semibold text-gray-900">{name}</h3>
      <p className="mt-1 text-sm text-gray-500">{description}</p>
    </div>
  );
}
```

The semantic classes and their meaning:

| Class                     | Light       | Dark                  | Use for                        |
| ------------------------- | ----------- | --------------------- | ------------------------------ |
| `bg-background`           | white       | near-black            | Page and card backgrounds      |
| `text-foreground`         | dark gray   | near-white            | Primary text                   |
| `bg-muted`                | light gray  | dark gray             | Subtle backgrounds, table rows |
| `text-muted-foreground`   | medium gray | lighter gray          | Secondary text, placeholders   |
| `border-border`           | light gray  | dark gray             | All borders and dividers       |
| `bg-primary`              | blue        | slightly lighter blue | CTA buttons, active states     |
| `text-primary-foreground` | white       | white                 | Text on primary backgrounds    |
| `bg-destructive`          | red         | darker red            | Delete buttons, error states   |

## Customizing the brand color

To change the primary color from AspFox blue to your brand color:

1. Update `--primary` and `--ring` in `:root` in `index.css`
2. Update `--primary` and `--ring` in `.dark` in `index.css`
3. Update the `primary` color values in `tailwind.config.ts` to match

The new color propagates to every component using `bg-primary`, `text-primary`, `border-primary`, `ring-primary`, or `text-primary-foreground`. No other changes are needed.

Example — changing to green:

```css theme={null}
:root {
  --primary: 142 76% 36%;     /* #16A34A green */
  --primary-foreground: 0 0% 100%;
  --ring: 142 76% 36%;
}

.dark {
  --primary: 142 69% 42%;
  --primary-foreground: 0 0% 100%;
  --ring: 142 69% 42%;
}
```
