diff --git a/.gitignore b/.gitignore
index ec0d3ab..95a0a31 100644
--- a/.gitignore
+++ b/.gitignore
@@ -22,3 +22,4 @@ secrets/*
!secrets/README.md
scripts/twitter/__pycache__
scripts/twitter/tests/__pycache__
+publish/quartz-patches/__pycache__
diff --git a/README.md b/README.md
index 687822c..5deb7d9 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-# Threadwell\
+# Threadwell
Recovered threads and submerged records.
diff --git a/publish/quartz-patches/apply.py b/publish/quartz-patches/apply.py
index 0390c68..6dd70e4 100644
--- a/publish/quartz-patches/apply.py
+++ b/publish/quartz-patches/apply.py
@@ -1,4 +1,4 @@
-"""Single source of truth for the Threadwell site base.
+"""Keep in-site links under the /Threadwell/ path.
Two stages:
@@ -6,13 +6,11 @@ Two stages:
relative URLs in the SPA click handler resolve from a directory base.
2. After `npx quartz build`, rewrite every built HTML file:
- - add `` so relative URL resolution works even when
- the URL bar lacks a trailing slash
- - rewrite the sidebar `` href to the absolute site
- base, not the directory the page is in
+ - set `` to that page's directory under the site path so
+ Quartz page-relative `../` links do not resolve against the domain root
+ - rewrite the sidebar `` href to the site path
-The base URL is read from `publish/quartz.config.yaml`'s `baseUrl`. Change
-that line; the next deploy uses the new value everywhere.
+`baseUrl` in `publish/quartz.config.yaml` is the single source of truth.
Idempotent. Safe to re-run.
"""
@@ -64,7 +62,9 @@ def read_base_url() -> tuple[str, str]:
ABS_BASE, REL_BASE = read_base_url()
HEAD_RE: re.Pattern[str] = re.compile(r"(]*>)", re.IGNORECASE)
-BASE_TAG = f'\n'
+BASE_RE: re.Pattern[str] = re.compile(
+ r"\s*", re.IGNORECASE
+)
TITLE_LINK: re.Pattern[str] = re.compile(
r'(