diff --git a/static/style.css b/static/style.css
index 0b4ce0df..e63253f1 100644
--- a/static/style.css
+++ b/static/style.css
@@ -35,6 +35,12 @@
:root[data-font-size="large"] .msg-body h2 { font-size: 19px; }
:root[data-font-size="small"] .msg-body h3 { font-size: 12px; }
:root[data-font-size="large"] .msg-body h3 { font-size: 16px; }
+ :root[data-font-size="small"] .msg-body h4 { font-size: 11px; }
+ :root[data-font-size="large"] .msg-body h4 { font-size: 15px; }
+ :root[data-font-size="small"] .msg-body h5 { font-size: 11px; }
+ :root[data-font-size="large"] .msg-body h5 { font-size: 14px; }
+ :root[data-font-size="small"] .msg-body h6 { font-size: 10px; }
+ :root[data-font-size="large"] .msg-body h6 { font-size: 13px; }
:root[data-font-size="small"] .msg-body code { font-size: 10.5px; }
:root[data-font-size="large"] .msg-body code { font-size: 14.5px; }
:root[data-font-size="small"] .msg-body pre code { font-size: 11px; }
@@ -602,8 +608,9 @@
.msg-body{font-size:14px;line-height:1.75;color:var(--text);padding-left:30px;max-width:680px;overflow-wrap:anywhere;}
.msg-body p{margin-bottom:10px;}.msg-body p:last-child{margin-bottom:0;}
.msg-body ul,.msg-body ol{margin:6px 0 10px 20px;}.msg-body li{margin-bottom:3px;}
- .msg-body h1,.msg-body h2,.msg-body h3{margin:16px 0 6px;font-weight:600;}
+ .msg-body h1,.msg-body h2,.msg-body h3,.msg-body h4,.msg-body h5,.msg-body h6{margin:16px 0 6px;font-weight:600;}
.msg-body h1{font-size:18px;}.msg-body h2{font-size:16px;}.msg-body h3{font-size:14px;}
+ .msg-body h4{font-size:13px;}.msg-body h5{font-size:12px;}.msg-body h6{font-size:11px;color:var(--muted);}
.msg-body strong{color:var(--strong);font-weight:600;}.msg-body em{color:var(--em);font-style:italic;}
.msg-body code{font-family:"SF Mono","Fira Code",ui-monospace,monospace;font-size:12.5px;background:var(--code-inline-bg);padding:1px 5px;border-radius:4px;color:var(--code-text);}
.msg-body pre{background:var(--code-bg);border:1px solid var(--border);border-radius:10px;padding:14px 16px;overflow-x:auto;margin:10px 0;}
diff --git a/static/ui.js b/static/ui.js
index f3ac942b..77c27c4b 100644
--- a/static/ui.js
+++ b/static/ui.js
@@ -990,7 +990,7 @@ function renderMd(raw){
s=s.replace(/\*([^*\n]+)\*/g,(_,t)=>`${esc(t)}`);
s=s.replace(/~~(.+?)~~/g,(_,t)=>`${esc(t)}`);
s=s.replace(/\x00O(\d+)\x00/g,(_,i)=>_ob_stash[+i]);
- s=s.replace(/^### (.+)$/gm,(_,t)=>`
content inside must not be rewritten to backticks: {out!r}"
)
assert "After paragraph." in out and "Done." in out
+
+
+class TestHeadingLevelsH1ThroughH6:
+ """Issue #1258 — `####`, `#####`, `######` previously fell through the
+ heading pass and emitted as literal text starting with `#`. Pin all six
+ levels so a future edit cannot silently regress h4–h6 again."""
+
+ def test_all_six_heading_levels_render(self, driver_path):
+ src = "# H1\n## H2\n### H3\n#### H4\n##### H5\n###### H6"
+ out = _render(driver_path, src)
+ assert "H1
" in out, f"h1 missing: {out!r}"
+ assert "H2
" in out, f"h2 missing: {out!r}"
+ assert "H3
" in out, f"h3 missing: {out!r}"
+ assert "H4
" in out, f"h4 missing: {out!r}"
+ assert "H5
" in out, f"h5 missing: {out!r}"
+ assert "H6
" in out, f"h6 missing: {out!r}"
+
+ def test_h6_does_not_partial_match_as_lower_level(self, driver_path):
+ """Replacers must run longest-first; otherwise `###### H6` could be
+ captured by the `^### ` rule and emit `### H6
`."""
+ out = _render(driver_path, "###### H6")
+ assert "H6
" in out, f"h6 must not be partial-matched: {out!r}"
+ assert "" not in out and "###" not in out
+
+ def test_h4_inline_markdown_still_processes(self, driver_path):
+ out = _render(driver_path, "#### **bold** in h4")
+ assert "bold in h4
" in out, (
+ f"inline markdown inside h4 must still render: {out!r}"
+ )