# HTML Email Rendering Order

## CRITICAL: Regex substitution order

When converting Markdown email body to HTML, the order of operations matters:

**WRONG (produces literal `## Title` in HTML):**
1. Convert `\n` to `<br>` FIRST
2. Then try to match `^## (.+)$` — FAILS because lines are now `<br>`-delimited

**RIGHT (renders styled `<h2>` in HTML):**
1. Regex-substitute headers FIRST (`^## (.+)$` → `<h2>\1</h2>` with `re.MULTILINE`)
2. Regex-substitute horizontal rules (`^---$` → `<hr>`)
3. Convert bold (`**text**` → `<strong>`)
4. Convert newlines LAST (`\n` → `<br>`)

```python
import re

html = body
html = re.sub(r'^## (.+)$', r'<h2 style="...">\1</h2>', html, flags=re.MULTILINE)
html = re.sub(r'^### (.+)$', r'<h3 style="...">\1</h3>', html, flags=re.MULTILINE)
html = re.sub(r'^---$', r'<hr style="...">', html, flags=re.MULTILINE)
html = re.sub(r'\*\*(.+?)\*\*', r'<strong>\1</strong>', html)
html = html.replace('\n', '<br>')
```

## Always use multipart/alternative

- Plain text part first (keeps raw markdown — degrades gracefully)
- HTML part second (email clients render the last part they understand)
- Wrapped in full `<!DOCTYPE html>` with inline `<style>` block

## Common failure modes

- **Literal `##` in output** — newlines converted to `<br>` before header regex. Fix: reorder steps.
- **Raw `---` visible** — `^---$` regex didn't match because line is not at line start after `<br>` conversion.
- **`**text**` visible** — bold regex ran before or without proper newline handling.
