You've shipped a sample (B3) and a theme (B4). Now you'll meet the rules that keep both robust. These are distilled from `THEME_BEST_PRACTICE.md` (2800 LOC of audit history); the buyer-tier version below is what you need to ship and not regress.

## The hierarchy is sacred

Every page is one of two stacks. **Memorise both.**

```
PageElement
└── BlockElement (a row)
    └── ElementGroup
        └── PElement | HeadingElement | ImageElement | ButtonElement | …
```

```
PageElement
└── BlockElement (a row)
    └── GridElement
        └── CellElement (a column)
            └── BlockElement (a row inside the column)
                └── ElementGroup
                    └── PElement | HeadingElement | ImageElement | …
```

Three things follow:

- **You can never put a leaf element directly inside `PageElement`** — it must be wrapped in a `BlockElement`. The Block owns the row's vertical rhythm.
- **You can never put a leaf element directly inside a `GridElement`** — it must be wrapped in a `CellElement` then a `BlockElement`. Each column has its own internal stack.
- **You can never nest a Grid inside a Grid** — break the inner Grid up into multiple Blocks, or use a single Grid with more cells.

## Container width matrix

| Surface | Container width | Why |
|---------|-----------------|------|
| Email | 600 px | Industry-standard since Outlook 2007. Wider than 600 risks horizontal scroll in Apple Mail / iOS narrow window. |
| Form / checkout | 480 px | Forms read better at narrower widths — less eye-jump per field. |
| Landing page | 1200 px | Modern desktop reading width with adequate gutter. |

The shipped samples respect these widths via `Page.template.html`'s outermost `<table width>` value. When you author a sample of a given kind, don't override the width unless you have a specific reason — buyers will see it in the wrong context (a 1000-px-wide email looks broken in Outlook).

## Padding cascade

`BlockElement` carries the page's vertical rhythm:

```json
{
    "name": "BlockElement",
    "template": "Block",
    "formats": {
        "padding_top": 30,
        "padding_bottom": 30
    }
}
```

`padding_top` and `padding_bottom` only — never `padding_left` / `padding_right` at this layer (the page container's `formats.padding_*` owns horizontal). Never margin (RULE-H11; margins collapse unpredictably across email clients).

The visual rhythm rule: rows should have **uneven** top/bottom padding only if they're acting as section separators (a hero row above + a body row below probably shares 20-30 px between them; a CTA row gets 30-40 px). Even padding (top = bottom) reads as a uniform stack; varied padding reads as deliberate sections.

## The 4-colour palette cap

A sample (or theme) uses **at most 4 distinct chromatic colours**. Greyscale doesn't count toward the cap.

```
Acceptable: black, white, brand red, off-white grey, sub-text grey
            └─ chromatic ─┘  └─ chromatic ─┘  └─── greyscale ───┘
            That's 2 chromatic + 1 greyscale family. Pass.
```

```
Not acceptable: black, white, red, blue, yellow, green, off-white
                └────── 4 chromatic + black ──────┘  +1 chromatic
                That's 5 chromatic colours. Fail RULE-H8.
```

The reason: a sample with 5+ distinct hues reads as untrustworthy (Geocities-era). Buyers who paid for premium templates won't tolerate it. Keep your accent + secondary + alarm tones to one chromatic family per role.

## The 5-typography-tier cap

A sample uses **at most 5 typography tiers**. The canonical set:

| Tier | Font size (px) | Weight | Use |
|------|----------------|--------|-----|
| H1 | 32-36 | 700 | One per page. Hero headline. |
| H2 | 22-24 | 600 | Section heading. |
| H3 | 18 | 600 | Sub-section heading. |
| Body | 14-16 | 400 | Paragraphs. |
| Caption | 12 | 400 | Footer text, fine print. |

If you find yourself reaching for an 18 px H4 + a 16 px H5 in the same email, you've broken the cap. Fix: collapse to 4 tiers, or use one tier for both with bold/regular weight as the differentiator.

## Edge alignment invariants

Every element edge in a Block must align with the page container's content edge OR with another element's edge. Three concrete rules:

- **Headings + paragraphs are flush-left** (or centered, for hero blocks). Never indented except via the Block's container padding.
- **Images at full content width** are flush-left + flush-right. If the image is narrower than content, it's centered.
- **Buttons** are centered or flush-left, never floating arbitrarily.

This is the difference between "designed" and "thrown together" — buyers spot the misalignment instantly even if they can't articulate why.

## Explicit units

Every dimension is an integer in pixels. **Never** strings:

```json
"width": 600        // ✅
"width": "100%"     // ❌ — RULE-H12
"font_size": 14     // ✅
"font_size": "1em"  // ❌ — RULE-H12
```

Percentages exist only on `CellElement.formats.width` (cells in a Grid sum to 100%) and on `Image.formats.align` ("center" / "left" / "right" — that's a literal alignment, not a typed unit).

## When to use a Grid vs stacked Blocks

Use a `GridElement` when:

- The row has **logically parallel content** in N columns (image + text split, 3-up product gallery).
- Each column has **its own vertical rhythm** (multi-block content per column).

Use stacked `BlockElement`s when:

- The content is **sequential** down the page (most emails — hero → body → CTA → footer).
- One row would feel artificial if columned (a single CTA button below a hero is a Block, not a 1-column Grid).

When in doubt: stack Blocks. Grids cost more rendering (more EJS template invocations, more nested HTML), so don't reach for them when a Block does the job.

## Common mistakes the audit catches

> **"My sample looks fine on desktop, broken on mobile"** — almost always a fixed-pixel width on a Grid or an Image that exceeds 600 px. Email clients don't responsively scale by default; your samples must be designed for the narrowest realistic viewport.

> **"My new theme renders correctly but is rejected by Litmus's 22-client matrix"** — you probably edited `Page.template.html` and dropped a Outlook-conditional comment block. Restore the original wrapper structure; brand changes go in `formats` overrides.

> **"My H1 + H2 + H3 + H4 are all defined and the sample renders weird"** — you've broken the 5-tier cap. Pick 5; promote the others to bold variants of an existing tier.

> **"My gradient background looks great in DevTools but ghosts in Outlook"** — Outlook ignores most CSS3. Use solid colours for backgrounds; if you need a gradient, bake it into a hero image, not a CSS rule.

## Did you make it?

You should now be able to:

- ✅ Recite the two valid hierarchy stacks without looking.
- ✅ Pick container width by surface (email vs form vs page).
- ✅ State the 4-colour + 5-typography caps + the units rule.
- ✅ Decide between Grid vs stacked Blocks by content shape.

What's next?

- → [Build a custom Element](/docs/09-element-dev/) ⭐ — graduate from theme to engine: subclass BaseElement and ship a Countdown component.
- 🔗 `THEME_BEST_PRACTICE.md` — the canonical 2800-LOC rule library this doc distils.
