diff --git a/AGENTS.md b/AGENTS.md
index 8f561ae..406f6fc 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -17,7 +17,7 @@ public/ ← build output (generated)
| File | Responsibility |
|---|---|
| `main.odin` | Entry point. Sets `context.logger`, calls `init_site`, `walk_content`, `render_site`. Optional Spall profiling via `SPALL` config flag. |
-| `site.odin` | `Flags` (parsed config), `Site` (runtime state + arena), `Feature` bit_set enum, `init_site`, `load_site_config`, `merge_flags`, `site_apply_flags`, `find_config` (walks up dir tree for `thor.json`) |
+| `site.odin` | `Flags` (CLI args), `Config_File` (from `thor.json`), `Site` (runtime state + arena), `Feature` + `Markdown_Extension` bit_set enums, `DEFAULT_MARKDOWN_EXTENSIONS`, 5-step `init_site` (defaults → flags → config → apply config → apply flags), `load_config_file`, `apply_config`, `apply_cli_flags`, `parse_extension_list`, `find_config` |
| `frontmatter.odin` | JSON frontmatter parser (`{ }` delimited) |
| `content.odin` | `Page` struct, content walker, page loader, cmark integration, full markdown pipeline, `copy_assets_dir` (recursive copy with CSS minification) |
| `footnotes.odin` | Note definition stripping (pre-cmark) + sidenote/marginnote injection (post-cmark) |
@@ -36,10 +36,16 @@ Icon SVGs live as HTML partials in `layouts/partials/icons/` (home, github, rss,
### Data flow
```
-thor.json → find_config → init_site → Flags → merge_flags → site_apply_flags → Site (config + Dynamic_Arena + features: bit_set)
- ↓
+thor.json → find_config → init_site:
+ 1. set defaults (base_url, DEFAULT_MARKDOWN_EXTENSIONS)
+ 2. parse CLI flags (Flags struct)
+ 3. load config file (Config_File from thor.json)
+ 4. apply_config — non-empty config fields override defaults
+ 5. apply_cli_flags — flags override config, -ext/-no-ext adjust extensions
+→ Site (config + Dynamic_Arena + features: bit_set + markdown_extensions: bit_set)
+ ↓
content/ → walk_content → []Page (with body_html from pipeline)
- ↓
+ ↓
layouts/*.html → parse() → mustache.Template (parsed once)
↓
render_site → mustache.render(Page_Data, partials) → optional minify_html → public/
@@ -47,12 +53,19 @@ render_site → mustache.render(Page_Data, partials) → optional minify_html
### Config system
-Config is split into `Flags` (parsed from CLI args + JSON) and `Site` (runtime state):
+Config is split into three structs with a clear 5-step initialization flow:
-- **`Flags`** — pure parsed config struct. CLI args via `core:flags`, JSON via `json.unmarshal_string`.
-- **`Site`** — runtime state: arena, resolved config values, `features: bit_set[Feature]`.
-- **`Feature` enum** — `Sections`, `Drafts`, `Minify`, `Watch`. Checked with `.Minify in site.features`.
-- **`find_config`** — walks up from CWD looking for `thor.json`. Falls back to `./thor.json`.
+- **`Flags`** — CLI args only. Parsed by `core:flags`. Includes path overrides, build-mode toggles, and `-ext`/`-no-ext` for markdown extension overrides.
+- **`Config_File`** — parsed from `thor.json` via `json.unmarshal_string`. Holds title, paths, `markdown_extensions` (JSON), `params` (JSON).
+- **`Site`** — runtime state: arena, resolved config values, `features: bit_set[Feature]`, `markdown_extensions: bit_set[Markdown_Extension]`.
+
+**`Feature` enum** — build-mode toggles: `Drafts`, `Minify`, `Watch`. Checked with `.Minify in site.features`.
+
+**`Markdown_Extension` enum** — content pipeline toggles: `Emoji`, `Sidenotes`, `Alerts`, `Highlight`, `Sections`. Default is `DEFAULT_MARKDOWN_EXTENSIONS` (currently `.Emoji, .Sidenotes, .Alerts`). Configurable via:
+- `thor.json`: `"markdown_extensions": { "emoji": true, "highlight": false, ... }`
+- CLI: `-ext:highlight,sections` (enable) / `-no-ext:emoji` (disable). Comma-separated, case-insensitive.
+
+**`find_config`** — walks up from CWD looking for `thor.json`. Falls back to `./thor.json`.
Config precedence: `CLI flags > thor.json values > hardcoded defaults`.
@@ -61,7 +74,13 @@ Config precedence: `CLI flags > thor.json values > hardcoded defaults`.
"title": "...",
"base_url": "...",
"author": "...",
- "sectionate": true,
+ "markdown_extensions": {
+ "emoji": true,
+ "sidenotes": true,
+ "alerts": true,
+ "highlight": true,
+ "sections": true
+ },
"params": {
"social": [
{ "name": "github", "url": "...", "icon": "icons/github" }
@@ -86,7 +105,7 @@ Templates use Mustache with template inheritance (`{{ markup)
- → inject_alerts (post-cmark: [!TYPE] blockquotes → styled alerts)
- → highlight_code (post-cmark: tree-sitter per code block, with error reporting)
- → wrap_sections (post-cmark: if .Sections in features, wraps content in