diff --git a/README.md b/README.md
index 5c8be77..7ddf9cc 100644
--- a/README.md
+++ b/README.md
@@ -2,7 +2,7 @@
[](https://gitea.hellion-forge.cloud/JonKazama-Hellion/HellionChat/actions/workflows/build.yml)
[](LICENSE)
-[](https://gitea.hellion-forge.cloud/JonKazama-Hellion/HellionChat/releases/latest)
+[](https://gitea.hellion-forge.cloud/JonKazama-Hellion/HellionChat/releases/latest)
[](https://github.com/goatcorp/Dalamud)
[](https://dotnet.microsoft.com/)
[](https://www.finalfantasyxiv.com/)
@@ -11,7 +11,7 @@
-**Version 1.4.5** — Privacy-first chat plugin for FINAL FANTASY XIV / Dalamud, built on
+**Version 1.4.6** — Privacy-first chat plugin for FINAL FANTASY XIV / Dalamud, built on
[Chat 2](https://github.com/Infiziert90/ChatTwo) (EUPL-1.2).
Hellion Chat is a privacy-first plugin built on the Chat 2 foundation. The majority of the engine comes from Chat 2
@@ -286,18 +286,20 @@ An optional submission to the Dalamud main plugin repo (in addition to the custo
## Project Status
-**Version 1.4.5** — User-visible robustness polish on top of the v1.4.4 threading work. The chat log no longer fails
-silently: a draw-path exception now triggers a one-shot warning notification that points users at `/xllog`, while the
-stack trace itself keeps going through `Plugin.Log.Error` as before. The first-run wizard splits accept from close —
-`OnClose` no longer silently sets `FirstRunCompleted`, so closing the X leaves the wizard pending and it reopens on the
-next plugin load; a new footer "Later — keep defaults" button is the explicit path to dismiss without picking a profile.
-`InputHistoryService` clears on plugin dispose alongside the existing pure-memory cleanups, so the previous session's
-typed commands don't bleed into the next load. `FontManager.GetHellionFontBytes` becomes a `Try`-variant that falls back
-to the system-font path when the embedded resource is missing (broken csproj / dev build) instead of throwing through
-the UiBuilder. The status bar drops the right-aligned version slot when the chat window is below the threshold needed to
-fit all five slots without overlap. Internal: explicit session-only Auto-Tell-Tab invariant comment with a
-`TempTabCounter.InitFromList` pin in the Build-Suite. No schema bump, no migration. Sixth sub-patch of the v1.4.x polish
-sweep series (as of 2026-05-12).
+**Version 1.4.6** — Maintenance patch. No user-visible behaviour changes; tightens the development feedback loop and
+pulls in two ChatTwo upstream bugfixes. `scripts/preflight.sh` gains a csharpier reflow check and a markdownlint pass at
+the pre-push gate. `FontManager`'s font-fallback catch-filter now covers `InvalidOperationException` and
+`ArgumentException` on top of the IO triad, so a corrupted font config no longer takes down the atlas build.
+`BrandingLinks` and `IntegrationLinks` URLs validate themselves on plugin load — a typo in a future URL rotation throws
+at startup instead of failing silently when a user clicks the broken button. Cherry-picked from ChatTwo upstream
+`f35b7d3`: `Chat.SetChannel` no longer leaks the native `Utf8String` when the linkshell check rejects the channel, and
+`Tab.Clone` now deep-clones `UsedChannel` and `TellTarget` (the previous reference copy let PopOut and Temp tabs mutate
+each other's channel state). The active-tab underline pill scales with DPI and rounds to physical pixels for crisp
+rendering above 100 % DPI. Internal items: `HellionStyle` ChildBgAlpha extracted to a testable helper,
+`Plugin.SaveConfig` clones only the temp-tab subset, `SettingsOverview` caches the draw-list per frame,
+`Dalamud.Utility.Util` static surface routed through an `IPlatformUtil` indirection (`MessageStore`'s `IsWine` probe is
+now testable in isolation). No schema bump, no migration. Seventh sub-patch of the v1.4.x polish sweep series (as of
+2026-05-12).
Hellion Chat is a standalone plugin, no longer a fork in the repository sense. Fully completed:
diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md
index 20e8903..b4b70ea 100644
--- a/docs/CHANGELOG.md
+++ b/docs/CHANGELOG.md
@@ -10,6 +10,50 @@ to the release pages for details.
---
+## Hellion Chat 1.4.6 — Code Hygiene and Refactor (2026-05-12)
+
+Maintenance patch. No user-visible behaviour changes; tightens the development feedback loop, fixes two
+upstream-inherited bugs from ChatTwo `f35b7d3`, and prepares the code for the v1.4.7 backlog cleanup.
+
+- `scripts/preflight.sh` gains Block E (`dotnet csharpier check`) and Block F (`markdownlint-cli2`) so reflow drift and
+ markdown violations are caught at the pre-push gate. `.markdownlint.json` adds `MD024 siblings_only` and disables
+ `MD036` so the bilingual forge-post bold-emphasis headings pass linting; the `.claude/` directory is excluded from the
+ scan
+- `FontManager.AddFontWithFallback` catch-filter now covers `InvalidOperationException` and `ArgumentException` on top
+ of the existing IO triad. The warning log carries the exception type name, so the diagnostic path knows which class
+ of atlas-toolkit throw triggered the NotoSansCjkRegular fallback
+- `BrandingLinks` (5 URLs) and `Integrations/IntegrationLinks` (2 URLs) validate themselves on first module load via
+ `[ModuleInitializer]` + a shared `UrlValidation.ValidateAll` helper. A malformed URL now throws
+ `InvalidOperationException` at plugin load with the source class and the broken URL in the message
+- Cherry-picked from ChatTwo upstream `f35b7d3`: `Chat.SetChannel` no longer leaks the native `Utf8String` when the
+ linkshell check rejects the channel. The validity check is now wrapped around the `ChangeChatChannel` call instead of
+ short-circuiting before `Dtor`. `ValidAnyLinkshell` is renamed to `IsChannelOrExistingLinkshell` and the
+ `ChatLogWindow` call-site follows the rename
+- Cherry-picked from ChatTwo upstream `f35b7d3`: `Tab.Clone` now deep-clones `UsedChannel` and `TellTarget`. The old
+ `CurrentChannel = CurrentChannel` was a reference copy, so PopOut and Temp tabs mutated each other's channel state
+ (incl. tell target). `TellTarget.From(t)` static factory is replaced with an instance `Clone()`; `UsedChannel.Clone()`
+ is new and runs deep-clone on both TellTarget references
+- `ChatLogWindow` active-tab underline pill now scales with `ImGuiHelpers.GlobalScale` and rounds its DrawList
+ coordinates to physical pixels via `MathF.Round`, so the 2 px line stays crisp on 125 % and 150 % DPI setups instead
+ of bleeding into a sub-pixel blur
+- `ImGuiUtil.IconButton` width parameter no longer subtracts HUD-scaled `CellPadding.X * 2` from the raw `int` width.
+ `ImGui.Button` handles its own frame padding internally, so the measured `buttonWidth` now passes through verbatim
+ (inspired-by upstream `f35b7d3`, but our two call-sites need the parameter, so the param itself stays)
+- Internal: `HellionStyle` ChildBgAlpha threshold logic extracted to `HellionStyleHelpers.ResolveChildBgAlpha` with a
+ build-suite mirror test that pins the 0.999f cutoff. `Plugin.SaveConfig` clones only the temp-tab subset in the
+ pre-serialization snapshot instead of the full tab list. `SettingsOverview` caches `ImGui.GetWindowDrawList()` once
+ per frame and passes the pointer down to `DrawCard`
+- Internal: `Dalamud.Utility.Util` static surface (`IsWine`, `OpenLink`) routed through a new `IPlatformUtil`
+ indirection. `MessageStore`'s `IsWine` probe is now reachable from the xUnit AppDomain via a `FakePlatformUtil`
+ fixture (full isolated MessageStore construction still pending — `Plugin.Log.Information` in `Migrate0` is a separate
+ Dalamud-static surface, slated for v1.4.7)
+
+Modding & support: join Hellion Forge —
+
+Based on Chat 2 1.35.3 (upstream Infiziert90/ChatTwo, EUPL-1.2).
+
+---
+
## Hellion Chat 1.4.5 — UX and Robustness (2026-05-12)
Sixth sub-patch of the v1.4.x polish-sweep series. User-visible robustness fixes plus two doc/test polish items from the
diff --git a/docs/ROADMAP.md b/docs/ROADMAP.md
index f87088d..11271a7 100644
--- a/docs/ROADMAP.md
+++ b/docs/ROADMAP.md
@@ -10,14 +10,33 @@ the plugin's privacy-first scope during brainstorming.
---
-## Next Cycle (v1.4.6)
+## Next Cycle (v1.4.7)
-**Code-Hygiene + Refactor.** Build-side pre-commit hook with csharpier-check as a hard gate so format drift can't reach
-a commit (~30 min). Plus the cycle absorbs whatever surfaces from v1.4.5 smoke that doesn't justify a hotfix. Concrete
-scope is consolidated in the v1.4.6 brainstorm.
+**Backlog Cleanup.** Roll up the remaining audit items deferred from v1.4.0–v1.4.6 and the new entries surfaced during
+v1.4.6 (notably the `Plugin.Log` indirection that would unlock fully isolated `MessageStore` construction tests, plus
+follow-up scope hinted at in the ChatTwo upstream f35b7d3 cherry-picks). Scope is consolidated during brainstorm.
---
+## v1.4.6 — Code Hygiene and Refactor (released 2026-05-12)
+
+Seventh sub-patch of the v1.4.x Polish Sweep series. Maintenance patch — no user-visible behaviour changes; tightens
+the development feedback loop and pulls in two ChatTwo upstream bugfixes. `scripts/preflight.sh` gains a csharpier
+reflow check (Block E) and a markdownlint pass (Block F), so style drift and markdown violations are blocked at the
+pre-push gate. `FontManager.AddFontWithFallback` catch-filter now spans `InvalidOperationException` and
+`ArgumentException` on top of the existing IO triad, with the exception type name in the warning log so the
+diagnostic path can see which atlas-toolkit throw triggered the fallback. `BrandingLinks` and `IntegrationLinks` run a
+`[ModuleInitializer]` URL validation pass on plugin load; a typo in a future URL rotation now throws at startup
+instead of failing silently when a user clicks the broken button. Cherry-picked from ChatTwo upstream `f35b7d3`:
+`Chat.SetChannel` no longer leaks the native `Utf8String` when the linkshell check rejects the channel (rename to
+`IsChannelOrExistingLinkshell` plus wrap-not-return), and `Tab.Clone` now deep-clones `UsedChannel` and `TellTarget`
+(the previous reference copy let PopOut and Temp tabs mutate each other's channel state). The `ChatLogWindow`
+active-tab underline pill scales with `ImGuiHelpers.GlobalScale` and rounds to physical pixels for crisp rendering
+above 100 % DPI. Internal items: `HellionStyle` ChildBgAlpha extracted to a testable helper, `Plugin.SaveConfig`
+clones only the temp-tab subset in the snapshot path, `SettingsOverview` caches the draw-list per frame,
+`Dalamud.Utility.Util` static surface routed through an `IPlatformUtil` indirection (`MessageStore`'s `IsWine` probe
+is now testable in isolation). No schema bump, no migration.
+
## v1.4.5 — UX and Robustness (released 2026-05-12)
Sixth sub-patch of the v1.4.x Polish Sweep series. User-visible robustness polish plus two doc/test polish items from