# CMS theming and layouts

## Theme architecture

Keep four layers separate:

1. raw color palettes;
2. semantic theme variables;
3. Tailwind mappings;
4. component classes.

Universal components use semantic classes such as:

```text
bg-background
text-foreground
bg-surface
bg-card
text-muted-foreground
bg-primary
text-primary-foreground
border-border
ring-ring
```

They do not use named brand palette classes.

## Theme loading

Recommended order in a consuming application:

```css
@import "tailwindcss";
@import "@meyermedia/ui/styles.css";
@import "@customer/theme.css";

/* Application-specific overrides come last. */
```

Use `data-theme` selectors so themes can be installed at runtime without changing component source. Set `color-scheme` correctly for native controls.

## Required semantic groups

A complete theme covers:

- background and foreground;
- surface, raised surface and sunken surface;
- card and popover aliases;
- primary, secondary and accent actions with foreground pairs;
- muted surface and text;
- border, input and focus ring;
- link, selection and overlay;
- destructive, success, warning and info pairs;
- sidebar roles;
- chart colors;
- radii, shadows and optional typography;
- motion duration and easing overrides when supported.

When introducing a new required variable, update every built-in theme and document the contract change.

## User theme package

A theme package should contain CSS and optional metadata only. It should not import application components.

Suggested exports:

```json
{
  "exports": {
    "./theme.css": "./theme.css",
    "./metadata": "./dist/metadata.js"
  },
  "sideEffects": ["**/*.css"]
}
```

Metadata may include id, label, preview colors, supported color scheme, version and author. CSS remains the source of visual values.

## Scoped previews

Theme selectors may be placed on a subtree for previews:

```tsx
<section data-theme="customer-theme">
  <ComponentGallery />
</section>
```

Avoid global selectors inside a theme package that prevent scoped rendering.

## Layout architecture

A CMS layout is an installable React component that arranges named regions. It does not fetch CMS data.

Recommended contract:

```ts
interface LayoutComponentProps {
  slots: Partial<Record<string, React.ReactNode>>;
  className?: string;
}

interface LayoutDefinition {
  id: string;
  label: string;
  description?: string;
  component: React.ComponentType<LayoutComponentProps>;
  slots: readonly string[];
  metadata?: Record<string, unknown>;
}
```

Common slots include announcement, header, navigation, sidebar, main, aside and footer. Domain layouts may add named slots.

## Layout package rules

- Use package primitives and semantic tokens.
- Accept content and behavior through slots and props.
- Do not import CMS database clients, route loaders or authentication services.
- Do not assume one Next.js route structure.
- Document required slots and responsive behavior.
- Provide a preview using fixture content.
- Keep layout styles scoped and theme-compatible.

## Content adapters

WordPress, Gutenberg, Markdown, MDX and rich text styling belong in separate adapters. Do not place broad `.wp-content`, editor or vendor selectors in the universal primitive stylesheet.

Adapters may provide:

- prose typography;
- block spacing;
- figures and captions;
- tables;
- blockquotes;
- code blocks;
- embeds;
- wide and full alignment behavior;
- CMS-specific block classes.

They still consume semantic variables and must be previewed under every supported theme.

## Theme and layout verification

For every installable theme or layout, test:

- server rendering and hydration;
- scoped preview rendering;
- all primitive states;
- contrast and focus visibility;
- light or dark native form controls;
- mobile, tablet and desktop layouts;
- reduced motion;
- long content, empty slots and missing optional regions;
- LTR and RTL where supported;
- coexistence with another themed subtree.
