# Changelog — Hellion Chat

All user-facing changes to Hellion Chat. Format follows
[Keep a Changelog](https://keepachangelog.com/en/1.0.0/), version numbers follow
[Semantic Versioning](https://semver.org/).

Detailed release notes per version are available directly on the
[Gitea Release page](https://gitea.hellion-forge.cloud/JonKazama-Hellion/HellionChat/releases) and
in the plugin changelog block (`HellionChat/HellionChat.yaml` → `changelog:`). This file summarises
releases as an overview and links to the release pages for details.

---

## Hellion Chat 1.5.6 — Settings Overhaul + Filter & Notification Polish (2026-05-23)

- Settings window reorganised: ten tabs down to seven (General, Appearance, Chat, Window, Channels, Data & Privacy, About). Each tab now uses collapsible sections grouped by control type. Sections start collapsed every time you open a tab — less noise, easier to find what you need.
- New sender-name display options under Chat → Messages: separate world-suffix and name-format modes (Full name / First name only / Initials × Never / Other worlds only / Always).
- Plugin-only symbols now show a pre-send warning so other players do not get empty boxes (Chat → Messages → "Warn before sending plugin-only symbols").
- Separate window opacity for focused vs. inactive chat window (Appearance → Window style → "Inactive window opacity"). The slider above sets the focused value.
- Custom notification sound volume slider (General → Sound, and mirrored in Channels → per-tab → Notification). Affects only the three bundled custom sounds; the 16 game sounds are unaffected.
- The per-tab regex filter that briefly shipped earlier in this cycle has been removed — FFXIV's built-in blackword filter covers the same need.
- All 24 locale files updated for the new section labels and the v1.5.6 control labels (machine translation; native review continues via the Hellion Forge Discord).

---

## Hellion Chat 1.5.5 — Upstream-Sync Tab-Features (2026-05-21)

A backlog-sync cycle. Inherited tab items: a failed-tell warning toast, per-tab
notification sounds (16 game sounds or three bundled Hellion sounds with a
preview button), an auto-focusing 512-character tab rename, a jump-to-latest
button in the chat log header, and map-flag / item-link insertion from the chat
input. Plus the Hellion Forge fox banner becomes a real image. Schema bumped to
v18, additive fields only, no data migration.

---

## Hellion Chat 1.5.4 — Polish and Motion (2026-05-20)

A polish cycle of three P3 items. Theme switches now crossfade smoothly over ~300 ms
across every Hellion-rendered surface; the window background snaps deliberately so the
per-window opacity override from Dalamud's pinning menu stays intact. A new header
quick-picker — a palette button left of the cog — opens a compact popup for switching
themes and tabs without opening Settings. Sidebar icons and card-mode message borders
gain framerate-independent hover animations. A new "Reduce motion" toggle in Theme &
Layout disables the crossfade, hover animations and unread-tab pulse for accessibility.
No schema bump, migration v17 stays.

## Hellion Chat 1.5.3 — Localisation Wave + Bundled-Font Overhaul (2026-05-19)

Multi-language pass plus a long-standing first-frame HITCH lands as a side effect of a font-stack
rewrite. The bundled UI font swaps from Exo 2 to Inter Light. HellionChat now ships strings and
renderable glyph coverage for 24 languages.

### User-visible

- Twenty-four selectable UI languages: Catalan, Czech, Danish, Dutch, English, Finnish, French,
  German, Greek, Hungarian, Italian, Japanese, Korean, Norsk bokmål, Polish, Portuguese (Brazil),
  Portuguese (Portugal), Romanian, Russian, Spanish, Swedish, Turkish, Ukrainian, Simplified
  Chinese, Traditional Chinese. The dropdown sorts alphabetically by endonym, "None" pinned first.
  Non-native translations are AI-assisted and flagged for community native-speaker review via the
  Hellion Forge Discord.
- Bundled **Inter Light** replaces Exo 2 as the in-plugin font. Wider European coverage (Latin
  Extended-A/B, Greek polytonic, Cyrillic Supplement) so Czech, Polish, Romanian, Turkish,
  Hungarian, Greek and Ukrainian render without manual font configuration. SIL OFL 1.1, 343 KB.
- **NotoSansCjkRegular fallback** layer added as a merge-on-top so Hangul, Simplified-Chinese
  characters specific to the post-1956 reform, and other CJK glyphs the FFXIV Japanese game font
  does not ship now render correctly inside the HellionChat UI.
- First-frame **HITCH dropped from ~74 ms** (the v1.5.2 baseline that has held since v1.4.x) to a
  **median of ~20 ms** (5-reload sample: 23.6 / 20.4 / 17.9 / 20.1 / 19.2 ms, Linux/Wine; Windows
  baseline pending Jin's verification per the cross-platform-pflicht). The bundled-font path
  silently fell back to the FFXIV Axis game font for the entire v1.5.x series because of an
  early-return in the draw loop. The fix that routes `RegularFont` through draw also lands the
  defer-pattern win the v1.5.1 cycle was reaching for.
- **ExtraGlyphRanges activates automatically** when the user picks a language that needs a non-Latin
  script. Selecting Korean enables the Korean glyph range and rebuilds the atlas without a manual
  toggle in Fonts & Colours.
- New **WarningText under the language dropdown** notes that FFXIV's own chat input only fully
  supports EN, DE, FR and JA character sets. Other languages render inside HellionChat but may
  garble when typed into in-game chat or sent as messages.

### Under the hood

- Three-layer font stack in `FontManager.BuildRegularFontHandle` and `BuildItalicFontHandle`:
  Inter Light (or the user-selected global font) as primary, FFXIV JapaneseFont as merge 1 for
  native FFXIV kana/kanji style, NotoSansCjkRegular as merge 2 for everything else CJK.
- Two new `ExtraGlyphRanges` flags: `LatinExtended` (U+0100-U+024F) and `Greek` (U+0370-U+03FF +
  U+1F00-U+1FFF). Implemented as `builder.AddChar` pair lists in `SetUpRanges` (no managed-pointer
  pinning needed).
- `LanguageOverride` enum gains ten locales (Catalan, Czech, Danish, Finnish, Hungarian,
  Norwegian, Polish, Portuguese (Portugal), Turkish, Ukrainian) plus three previously
  commented-out entries (Italian, Korean, Norwegian re-enabled with code `nb` instead of `no`).
  New values are appended to the enum to keep existing user-config integer serialisation stable.
- **Crowdin gap closed:** four ChatTwo keys added after the last community sync
  (`Options_ColorSelectedInputChannelButton_Name` / `_Description`,
  `Options_HideInNewGamePlusMenu_Name` / `_Description`) are now backfilled into the thirteen
  legacy Crowdin locales with per-key AI-translated markers.
- Plugin init runs a one-shot migration that ORs in the matching `ExtraGlyphRanges` flag based on
  the user's current `LanguageOverride`. An update from v1.5.2 picks up the new coverage without
  the user having to toggle the language twice.
- `Plugin.cs:937` draw-path fixed: `RegularFont` is now pushed whenever **either** `FontsEnabled`
  **or** `UseHellionFont` is on. The previous `Config.FontsEnabled`-only check meant the bundled
  font path was silently dead whenever `FontsAndColours.cs:50` force-set `FontsEnabled = false` on
  the UseHellionFont-toggle. Source of the HITCH win.
- `ExtraGlyphRanges` settings panel is now reachable in **all** UseHellionFont / FontsEnabled
  combinations. The bundled-font branch used to short-circuit past it.
- **Resource bundle split:** fork-added strings live in `HellionStrings.resx` (24 locales, 328
  keys each) alongside the ChatTwo-Crowdin-heritage `Language.resx` (24 locales, 456 keys each).
  The `Language` siblings for the ten brand-new locales and Greek carry a Hellion Forge maintainer
  header that points reviewers at the Discord rather than the standalone-hosted Gitea.
- **Em-dash sweep** across the EN source and 18 translations: in-prose em-dashes replaced with
  period or colon per the house style guide. Russian and Ukrainian keep their typographic norm
  where the em-dash is orthographically required (subject-predicate separator).
- **Bundled font asset rotation:** `HellionFont.ttf` (Exo 2) plus its OFL notice removed from
  `Resources/`. `Inter-Light.ttf` plus `Inter-OFL.txt` take their place. `FontManager`
  references rename to `BundledFontBytes` / `TryGetBundledFontBytes()` for clarity (config field
  `UseHellionFont` keeps its name so existing user configs deserialize cleanly).

### Migration

- Migration v17 stays (no schema bump).
- Existing `UseHellionFont = true` users transition transparently from Exo 2 to Inter Light on
  first reload.
- Existing users with `LanguageOverride != None` get their matching `ExtraGlyphRanges` flag set
  on the first plugin init after the v1.5.3 update (Plugin.cs LoadAsync migration step).

### Reserved for follow-up cycles

- Native-speaker review pass for AI-assisted translations in the 13 legacy Crowdin locales (ca,
  es, fr, it, ja, ko, nl, pt-BR, ro, ru, sv, zh-Hans, zh-Hant) — corrections via the Hellion
  Forge Discord.

Based on Chat 2 1.35.3 (upstream Infiziert90/ChatTwo, EUPL-1.2).

---

## Hellion Chat 1.5.2 — First-Run Wizard Rework (2026-05-18)

UX patch. The single-page first-run wizard becomes a four-step staged-commit flow, the privacy
profile catalogue gains a fourth entry "Roleplay", and a new power-settings stage surfaces six
previously-hidden Configuration defaults. Existing v1.5.1 users see the new wizard once on first
v1.5.2 boot via a new `WizardLastShownVersion` config marker.

User-visible:

- Wizard layout: Welcome → Privacy profile → Power settings → Done. Forge-Bronze pagination dots,
  per-step Back / Decide later / Next footer. Decide-later and X-close both leave the existing
  config untouched; only the Finish ✓ click commits pending choices.
- Fourth privacy profile "Roleplay": Privacy-First whitelist plus `Say` and both emote types, with a
  30-day retention window for `Say` and 90 days for the two emote channels. `Shout`, `Yell` and
  `NoviceNetwork` stay out — public-distance noise from strangers is not story content.
- Privacy picker becomes a 2×2 grid. Casual stays the recommended option with a ★ marker.
- Power-settings stage surfaces six existing `Configuration` fields in one place: Load Previous
  Session, Filter Include Previous Sessions, Auto-Tell-Tabs History Preload, Compact Density,
  Prettier Timestamps, plus a built-in theme picker. No new settings are introduced — the stage just
  collects what was previously buried in Settings → Privacy / Chat / Data Management / Appearance.
- Inline test hint on the done stage: `type /tell <Player Name> into chat` surfaces the auto-tell-tab
  spawn mechanism for new users.
- Wizard window starts at 720×480 (was 900×560) and can shrink to 600×400. Step 1 wraps the fox
  banner in a collapsible TreeNode, folded by default — onboarding copy stays primary.
- Existing v1.5.1 users get the new wizard surfaced once on first v1.5.2 boot. A new
  `WizardLastShownVersion` config field tracks the most recent version whose wizard was shown;
  Plugin.LoadAsync resets `FirstRunCompleted` once when the constant `1.5.2` doesn't match.

Under the hood:

- `WizardStateSmokeStep` registered with `/xlperf`. Variant 1 walks the four steps with empty
  pending state to pin the no-op CommitPending path. Variant 2 picks Roleplay on Step 2, skips
  Step 3, commits, and asserts `LoadPreviousSession` / `FilterIncludePreviousSessions` stayed on
  their pre-test value — pinning the null-semantics contract. The step snapshots six privacy /
  retention fields before Variant 2 and `CleanUp()` restores them, so back-to-back runs don't drift
  the active profile.
- Twelve pure-helper xUnit Facts in the Build Suite (`Privacy/PrivacyDefaultsTests.cs`) cover all
  four profile whitelists plus the new Roleplay retention overrides.
- `Configuration` grows one optional string field `WizardLastShownVersion` (default empty). No
  schema bump — migration v17 still applies.

Based on Chat 2 1.35.3 (upstream Infiziert90/ChatTwo, EUPL-1.2).

[Full release notes on the Gitea release page.](https://gitea.hellion-forge.cloud/JonKazama-Hellion/HellionChat/releases/tag/v1.5.2)

---

## Hellion Chat 1.5.1 — FontAtlas Refactor and Hellion Forge Signature (2026-05-17)

Hybrid FontManager refactor plus an embedded Hellion Forge provenance mark.

- FontManager handle creation moves into the ctor inside a single `atlas.SuppressAutoRebuild()`
  block — the font atlas now builds once per plugin load instead of four to five times.
- Hybrid property model: `Axis`, `AxisItalic` and `FontAwesome` become init-only handles;
  `RegularFont` and `ItalicFont` stay mutable because the eight font settings still need to replace
  them at runtime via the renamed `RebuildDelegateFonts()` path, without a plugin reload.
- `FontAwesome` reuses Dalamud's `UiBuilder.IconFontFixedWidthHandle` instead of building its own
  atlas slot.
- `BuildFontsAsync` and `BuildFonts` are removed; the live mutation path is `RebuildDelegateFonts()`
  now.
- Two new self-test steps register with `/xlperf`: FontManager ctor smoke (every handle non-null, no
  atlas load-exception) and push smoke (`Push()` returns without throwing).
- Hellion Forge signature embedded in the plugin DLL: a fox-head ASCII silhouette is prepended to
  the `/xllog` bootstrap banner on every plugin load, and a full fox banner with "Hellion Forge" set
  inside the body is available as a folded `TreeNode` in the First-Run Wizard and Settings →
  Information tab. Drawn by Julia Moon.
- Honorific full-gradient port (originally scheduled for this cycle) was dropped: Honorific 3.2
  exposes no IPC for the rendered gradient frame, and an in-plugin port of the colour palette was
  declined. The integration stays at the v1.4.7 glow-only shape.

The 10× HITCH cut targeted from the v1.5.0 cross-plugin baseline did not land — HITCH stays around
80 ms because the cost lives in the UiBuilder first-frame render path, not in the atlas build (which
this cycle did reduce from 4-5 builds per load to 1). A first-frame render investigation is reserved
for a later cycle. No settings changes, no migration. v17 stays.

[Full release notes on the Gitea release page.](https://gitea.hellion-forge.cloud/JonKazama-Hellion/HellionChat/releases/tag/v1.5.1)

---

## Hellion Chat 1.5.0 — DI Foundation and Service Refactor (2026-05-17)

Major architecture cycle. The plugin bootstrap moves to a generic-host DI container
(`Microsoft.Extensions.Hosting` + `IServiceCollection`) modelled on Lightless Sync. Service logging
migrates from a static `Plugin.LogProxy` locator to typed `Microsoft.Extensions.Logging.ILogger<T>`
via constructor injection, bridged over Dalamud's `IPluginLog` by a custom `DalamudLogger` trio.

### Under the hood

- 18 instance-class services migrate to `ILogger<T>` via constructor injection across four slices:
  data layer (`MessageStore`, `MessageManager`, `AutoTellTabsService`), IPC and integrations
  (`HonorificService`, `IpcManager`, `TypingIpc`, `ExtraChat`, three `GameFunctions` classes), UI
  window layer (`ChatLogWindow`, `DbViewer`, `Popout`, three settings tabs), and root (`Commands`,
  `ThemeRegistry`, `PayloadHandler`).
- `Plugin.LogProxy` stays in place for the eight buckets ctor injection cannot reach: static helpers
  (`EmoteCache`, `AutoTranslate`, `MemoryUtil`, `WrapperUtil`), Dalamud-reflected types
  (`Configuration`), the `Message` data class, and instance classes that only log from static
  methods (`FontManager`, one `GameFunctions` site).
- Plugin.cs finishes at 1012 lines — virtually identical to the pre-cycle 1013. The new Phase-1 host
  build and `Plugin.X` bridge wiring trade out exactly the service and window allocations that
  previously lived in `LoadAsync`.
- Cross-plugin baseline confirms no performance penalty against Chat 2: HellionChat first-frame
  HITCH 77 ms median, Chat 2 74 ms median. Lightless and XIVInstantMessenger sit around 7 ms by
  deferring their font-atlas build past `Finished loading` — that pattern is the v1.5.1 follow-up
  item.

### User-visible

- Slash-command insert fix: pasting a slash command into the chat input (Friend List "/tell" action,
  plugin-driven inserts from Artisan, AllaganTools etc.) now replaces the existing input instead of
  concatenating onto whatever the user was typing. Cherry-picked from ChatTwo upstream `ee7768ac`
  with namespace adaptation.

Migration v17 stays (no schema bump).

Based on Chat 2 1.35.3 (upstream Infiziert90/ChatTwo, EUPL-1.2).

---

## Hellion Chat 1.4.10 — Symbol-Picker and Tell-History Fix (2026-05-16)

Eleventh and final sub-patch of the v1.4.x Polish-Sweep series. Symbol picker for the chat input, a
tell-history reload fix for users with many active partners, and a closing cleanup sweep before
v1.5.0 picks up the DI-container adoption.

- Symbol picker for the chat input: smile-icon button left of the channel indicator opens a popup
  with two tabs — 161 FFXIV PUA glyphs (Dalamud's SeIconChar enum) and 97 server-verified BMP
  symbols round-tripped through `/echo` and `/say` in a four-round probe. Cursor-aware splice,
  multi-insert keeps the popup open, recent-used strip floats the last sixteen picks across both
  tabs. Toggle in Settings → Chat → Message behaviour, default on.
- Pinned auto-tell tabs reload their full history again. PreloadHistory had a hidden 500-row scan
  cap that overrode the user-configurable `AutoTellTabsHistoryPreload` setting whenever you chatted
  with many partners; less-frequent pinned partners lost their backlog. The cap is removed.
- Slash-command teardown cleanup: `/hellion`, `/hellionView`, `/hellionDebugger` (and
  `#if DEBUG /hellionSeString`) wrappers are now cached as private fields so plugin teardown
  detaches the live registration instead of re-Register'ing with identical args (latent maintenance
  hazard from v1.4.9).
- v1.4.x Polish-Sweep wraps up here. The ImGuiListClipper render refactor that was on the v1.4.10
  reserve list got dropped after cross-platform smoke showed the scroll rubber-band is a Wine/Linux
  render-pipeline quirk, not universal — Windows users never saw it. It will get its own
  platform-targeted spike in a later patch. Next major cycle is v1.5.0 with the DI-container
  adoption (Microsoft.Extensions.Hosting + ILogger<T>) modelled on Lightless.
- Migration v17 stays (no schema bump).

Based on Chat 2 1.35.3 (upstream Infiziert90/ChatTwo, EUPL-1.2).

---

## Hellion Chat 1.4.9 — Plugin-Load Render Polish (2026-05-15)

Tenth sub-patch of the v1.4.x polish-sweep series. First-frame render cost drops from ~127 ms median
down to ~76 ms median — comfortably under Dalamud's 100 ms HITCH warning threshold. The remaining
~13 ms gap to ChatTwo upstream (~63 ms median) is the cost of HellionChat-only features (sidebar tab
view, custom status bar, Honorific integration).

- First-frame defer: six non-essential rendering sections inside `ChatLogWindow` skip their first
  Draw and run one frame later. Covered sections are the bottom status bar, channel-name SeString
  chunks, window bounds check, v0.6.1 hint banner, autocomplete and input-preview calculation. At 60
  fps the user sees those sections ~17 ms after plugin reload — invisible inside the ~2.5 s
  font-atlas build window every reload runs through anyway. Frame 1 stays well under 100 ms too (~40
  ms), so no secondary HITCH warning appears.
- Slash-command centralisation: `/hellion`, `/hellionView`, `/hellionSeString` and
  `/hellionDebugger` are now registered during `LoadAsync` instead of inside the corresponding
  window constructors. The commands work before their target window is opened the first time, and
  Dalamud's plugin-manager configuration / open buttons (`UiBuilder.OpenConfigUi` / `OpenMainUi`)
  hang on the same path.
- Plugin-load profiling logs stay on: `MessageStore.Connect`, `MessageStore.Migrate`,
  `FilterAllTabs` and the auto-translate warm-up timing log are now Information level rather than
  Debug. They serve as a tripwire so a future regression past 100 ms shows up directly in `/xllog`
  without re-enabling Debug.
- ChatTwo IPC compatibility layer: HellionChat now mirrors ChatTwo's full IPC surface
  (`GetChatInputState`, `ChatInputStateChanged`, `Register`, `Unregister`, `Available`, `Invoke`)
  under the `ChatTwo.*` namespace in addition to our existing `HellionChat.*` provider gates.
  Third-party integrations that historically only subscribe to ChatTwo's IPC — for example Artisan's
  and AllaganTools' context-menu hooks — keep working without requiring a code change on their side.
  Conflict detection prevents ChatTwo from loading in parallel with HellionChat, so there is no
  slot-collision risk at runtime.
- Migration v17 stays (no schema bump).
- Internal: hypothesis-triage during the R2 cycle falsified three of the four candidate root causes
  (font-atlas sync, theme-apply ABGR-cache init, multiple-window render). Actual cause is `DrawList`
  setup cost distributed across ~10 ImGui sections inside ChatLogWindow (5-20 ms each). The six
  selective defers above are the pragmatic fix — a clean structural rewrite would belong in the
  v1.5.x DI-container cycle.

Based on Chat 2 1.35.3 (upstream Infiziert90/ChatTwo, EUPL-1.2).

---

## Hellion Chat 1.4.8 — Hook-Layer and Polish Quick-Wins (2026-05-14)

Ninth sub-patch of the v1.4.x polish-sweep series. Hook-layer cluster (FTS5 full-text search,
ad-block foundation investigation) plus three polish quick-wins.

- DbViewer full-text search: optional FTS5 index across the full chat history. Built asynchronously
  on first run after the update with a progress toast (UI stays responsive, the toggle is disabled
  until the build completes). The local page-filter remains the default mode. Multi-word queries
  match as exact phrases; power users can opt into raw FTS5 `MATCH` syntax by wrapping their own
  double-quotes around the term.
- Custom theme files now auto-reload when edited while the theme is active. Save the JSON in your
  editor and the live render picks up the change within a second — no need to re-click the theme in
  the picker. Disk-stat is throttled to 1 Hz so per-frame cost stays free.
- Retention sweep no longer blocks the framework thread. `Framework.Run(...).Wait()` is replaced by
  `Framework.RunOnTick(...)`, which removes the ~194 ms hitch the sweep used to add per run.
- Status bar height is derived from `GetTextLineHeightWithSpacing()` plus a DPI-aware spacer so the
  bar renders correctly at Windows display scaling above 100 %. Linux/Wayland default of 100 % is
  unaffected.
- Receive-suppressed-tells routing was investigated this cycle and **postponed to v1.5.x**. When
  other plugins suppress tells via `CheckMessageHandled`, FFXIV's chat pipeline skips the
  `RaptureLogModule.AddMsgSourceEntry` path, which means HellionChat's `ContentIdResolverHook` does
  not fire and tell-partner identification breaks for AutoTellTab routing. The proper fix sits next
  to the planned ad-block hook layer (`RaptureLogModule.ShowMiniTalkPlayer` and friends) where the
  same patch surface comes up anyway.
- Internal: storage form of `messages.Id` clarified (declared BLOB but Microsoft.Data.Sqlite stores
  Guid parameters as TEXT). FTS bulk insert and `LoadByGuids` join now match the TEXT storage form
  on both sides. Migration v17 stays (no schema bump).

Based on Chat 2 1.35.3 (upstream Infiziert90/ChatTwo, EUPL-1.2).

---

## Hellion Chat 1.4.7 — Backlog Cleanup and Mid-Features (2026-05-13)

Eighth sub-patch of the v1.4.x polish-sweep series. First user-visible feature bundle since v1.4.5 —
pinned tell tabs that survive relog, opt-in Honorific glow rendering, a configurable sidebar, plus a
Settings-Save channel-preservation fix surfaced during smoke testing.

- TempTell Pin: right-click a TempTell tab in the sidebar and choose "Pin Tab" / "Tab anpinnen".
  Pinned tabs survive plugin reload and character logout, keep their conversation history (loaded on
  demand from the message store on rehydrate), and stay bound to the same `/tell` partner. Hard cap
  of 5 pinned tabs in a pool separate from the 15-tab auto-tell pool — total ceiling is 20 tabs. The
  sidebar groups pinned tabs into their own section with a divider header
- Honorific glow outlines now render via an 8-direction DrawList pre-pass when the title carries a
  Glow colour. Opt-in via **Settings → Integrations → Render glow outlines (Honorific)** (default
  off). Honorific's gradient surface (`Color3`, `GradientColourSet`, `GradientAnimationStyle`) is
  parsed and stashed for a later cycle but renders as the primary colour until then — the v1.4.7 DTO
  already mirrors all four extra fields so the JSON roundtrip doesn't silent-drop them
- Sidebar width configurable in **Theme & Layout** (44–160 px, default 44 stays icon-only). The icon
  button stretches with the configured width so a widened sidebar looks intentional, not a 36 px
  icon floating in empty space
- `Configuration.UpdateFrom` now preserves the runtime `CurrentChannel` across the persistent-tab
  merge alongside `Messages` and `LastSendUnread`. `TabSwitched` deep-clones the seeded channel from
  the previous tab instead of sharing the same `UsedChannel` instance. Together these fix a
  regression where Settings-Save on a Party or Linkshell tab popped the chat input back to
  `/tell <pinned-partner>` on the next interaction
- `Util/ImGuiUtil.cs` `DrawArrows` IconButton id uses `(id + 1).ToString()` with explicit
  parentheses instead of the operator-precedence quirk `id + 1.ToString()` (which resolved to
  `id.ToString() + "1"`). Single live caller is `Ui/DbViewer.cs:227` page-navigation
- Internal: `IPluginLogProxy` indirection over Dalamud's `IPluginLog` routes all ~91 `Plugin.Log`
  call sites through a testable proxy. `MessageStore.Migrate0` can now run in xUnit without loading
  `Dalamud.dll`, closing the gap F12.1 left in v1.4.6. Production wrapper `DalamudPluginLogProxy`
  and Build-Suite `FakePluginLogProxy` mirror the full `IPluginLog` surface
  (`Verbose`/`Debug`/`Information`/`Info`/`Warning`/`Error`/`Fatal`) with single-string,
  `Exception+string`, and `params object[]` overloads
- Internal: TempTab counter switched from an `Interlocked` cached field to a derived
  `Tabs.Count(predicate)`. Pin-state transitions (TryPin / Unpin / Promote) are cold-path and don't
  need lock-free reads; counter mutation surface dropped from 5 to 0 sites. Build-Suite floor 688 →
  710 (+22)
- Schema bump v16 → v17 is additive: new `Tab.IsPinned` bool, default false. Existing v16 configs
  load cleanly and get their `Version` stamp bumped after the gate check

Based on Chat 2 1.35.3 (upstream Infiziert90/ChatTwo, EUPL-1.2).

---

## 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)
- Built-in themes: Crystal Nocturne (royal sapphire and electric magenta over obsidian, by
  CRYSTALLITE) replaces Moonlit Bloom in the built-in roster. Users who had Moonlit Bloom selected
  fall back to the default Hellion Arctic on the first plugin load; an existing custom JSON copy of
  Moonlit Bloom under `pluginConfigs/HellionChat/themes/` keeps working unchanged

Modding & support: join Hellion Forge — <https://discord.gg/X9V7Kcv5gR>

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 audit backlog. No schema bump, no migration.

- `ChatLogWindow.Draw` now surfaces a one-shot warning notification when the draw path throws. The
  stack trace still goes to `/xllog` via `Plugin.Log.Error`; the notification is suppressed for the
  rest of the plugin session so a recurring failure can't spam the notification stack
  frame-by-frame. Pattern-match to the existing `Plugin.cs:505-516` migration-blocker notification
- `FirstRunWizard` 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.
  Bilingual strings (EN + DE) plus a tooltip
- `InputHistoryService.Reset` is wired into `Plugin.DisposeAsync` alongside the existing pure-memory
  cleanups. Static state used to survive a plugin reload — the next load now starts with an empty
  history
- `FontManager.GetHellionFontBytes` becomes `TryGetHellionFontBytes` with a nullable return. On miss
  (broken csproj, hand-rolled dev build) the caller falls back to the system-font path that
  `UseHellionFont=false` already uses, plus a `Plugin.Log.Warning`. The whole UiBuilder no longer
  throws if the embedded font resource is absent
- `Plugin.cs:167-168` gets a 4-line reasoning comment around the session-only
  `RemoveAll(IsTempTab)`: tells are usually privacy-filtered, resurrecting an empty crashed-session
  tab would trigger DB reconstruction on the next load. `TempTabCounter.InitFromList` mirrors the
  post-strip semantic in the Build-Suite with a pinning test
- `StatusBar.cs` drops the version slot when the chat window's content width minus the version text
  is below 200 px. The right-aligned version used to clip into the four left-side slots in narrow
  windows

Modding & support: join Hellion Forge — <https://discord.gg/X9V7Kcv5gR>

Based on Chat 2 1.35.3 (upstream Infiziert90/ChatTwo, EUPL-1.2).

---

## Hellion Chat 1.4.4 — Threading and IPC Safety Polish (2026-05-12)

Fifth sub-patch of the v1.4.x polish-sweep series. Threading assumptions are documented per-method,
a hot-path lock falls away in `AutoTellTabsService`, IPC-cleanup failures become visible, and the
privacy filter now speaks up when an unknown ChatType shows up.

- `AutoTellTabsService.ActiveTempTabCount` switches from a lock-protected LINQ `Count` to an
  `Interlocked` counter kept in sync with `Config.Tabs` from inside the existing mutation paths.
  `Initialize()` seeds the counter from the persisted Tabs list, and `SaveConfig`'s snapshot-restore
  path calls a new `ResyncTempTabCounter()` so the mid-step `RemoveAll` doesn't leave the counter
  drifting. Pure-helper test mirror lives in the Build-Suite repo
- `HonorificService` per-method threading banners replace the block comment at the bottom of the
  file. Each IPC callback (`TryInitialPull`, `OnTitleChanged`, `OnReady`, `OnDisposing`,
  `TryUnsubscribe`) and the `CurrentTitle` field carry a one-line `// Thread:` annotation so the
  framework-thread invariant is visible at the call site
- `TryUnsubscribe` log-level upgraded from `Debug` to `Warning`. A silent unsubscribe failure leaks
  a live subscription across plugin reloads, which is exactly the kind of issue that should not be
  at Debug
- `AutoTranslate.PreloadCache` thread now has `IsBackground = true` and a thread name. Without
  `IsBackground` the warmup blocks plugin unload (typically 100-300 ms). Pattern-match to
  `MessageManager` (F6.1) and `Plugin.RetentionSweep` (F9.3), both since v1.4.0
- `Configuration.IsAllowedForStorage` adds a one-line `Plugin.Log.Warning` for the first occurrence
  of any ChatType that isn't in `PrivacyPersistChannels`. Dedup via a `NonSerialized`
  `HashSet<ChatType>`, so the warning fires once per runtime — not once per frame, not once per
  install. Failsafe routing through `PrivacyPersistUnknownChannels` is unchanged
- `PrivacyPersistUnknownChannels` field default flipped from `false` to `true` for new installs via
  a constant in `PrivacyDefaults`. Existing configs keep their explicit choice — the deserializer
  overrides the initializer. No schema bump, no migration, no first-run banner

Modding & support: join Hellion Forge — <https://discord.gg/X9V7Kcv5gR>

Based on Chat 2 1.35.3 (upstream Infiziert90/ChatTwo, EUPL-1.2).

---

## Hellion Chat 1.4.3 — Plugin-Load Async-Init + Repo-Cutover (2026-05-08)

Plugin lifecycle migrated to Dalamud's `IAsyncDalamudPlugin` API. The constructor now does only the
bootstrap-essentials (config load, language init, conflict detection); migrations, service
allocations, window construction and hook subscription move to `LoadAsync`. Dalamud can keep its UI
responsive while the heavy work runs.

- `IAsyncDalamudPlugin` two-phase load with per-line `CaptureFailure` in `DisposeAsync` (mirrors
  LightlessSync's pattern); idempotency guard protects against reload races
- Schema-gate replaces the v9 → v16 migration chain. Configs on schema v16+ load directly; older
  configs trigger an "install v1.4.2 first" error so the historic migration path stays intact
- `AutoTranslate.PreloadCache` moved off the load path. First use may have a sub-second hitch
  instead of every-load; the upstream chose differently, we accept first-use latency
- `FontManager.BuildFonts` is called sync at the start of `LoadAsync`; Dalamud rebuilds the font
  atlas on its own pipeline so the custom Hellion-Exo2 font appears with a brief font-pop after load
  (matches ChatTwo's behaviour)
- Custom-repo URL moved to `gitea.hellion-forge.cloud/JonKazama-Hellion/HellionChat`. GitHub repo
  stays as a frozen v1.4.2 snapshot; new releases ship from Gitea. Existing testers need to update
  the custom-repo URL once
- Plugin-load time in this release sits at ~3.7 s median (5 reloads), comparable to v1.4.2. Async
  migration is foundational for v1.4.4 Lazy-Init optimisations rather than an immediate
  user-perceived win

Modding & support: join Hellion Forge — <https://discord.gg/X9V7Kcv5gR>

Based on Chat 2 1.35.3 (upstream Infiziert90/ChatTwo, EUPL-1.2).

---

## Hellion Chat 1.4.2 — ChatLog Frame-Hot-Path

Third sub-patch of the v1.4.x Polish Sweep series. Per-frame allocations from the chat-log render
path eliminated.

- `DrawMessages` card-mode hoists `theme`/`drawList`/`winLeft`/`winRight`/`borderColorAbgr` out of
  the per-message loop. About 500 redundant calls per frame at 100 visible messages, multiplied by
  every pop-out window
- Auto-tell tab tint and icon use a per-tab cache. Hash computation and string allocation only
  happen when the tell target name or world drifts. `AutoTellTabTint` stays a pure hash helper;
  cache lives in a thin `TabTintCache` wrapper
- Status bar gates its tab aggregation behind the same one-second cache it already used for the
  format strings. LINQ `Sum` and `Count` replaced with a single `foreach` pass that runs on roughly
  1 % of frames

Realistic frame-time recovery: 2-5 % in typical scenes, more on pop-out-heavy setups because the
card-border hoist scales per window.

Modding & support: join Hellion Forge — <https://discord.gg/X9V7Kcv5gR>

Based on Chat 2 1.35.3 (upstream Infiziert90/ChatTwo, EUPL-1.2).

---

## Hellion Chat 1.4.1 — Theme Engine Performance

Second sub-patch of the v1.4.x Polish Sweep series. Heap pressure from the theme engine's per-frame
render path removed, plus a tenth built-in theme and hardening for the custom-theme hot-reload.

- Theme records carry a pre-computed ABGR-packed cache for every color slot; cache is filled when
  the theme is registered and refreshed defensively on every `Switch()`
- `HellionStyle.PushGlobal` reads ABGR values from the cache instead of calling
  `ColourUtil.RgbaToAbgr` per slot per frame; ~13 % render-time recovery measured in typical scenes
  (plan estimate was 2–6 %, real ~10–15 %)
- `ThemeRegistry` custom-theme reload distinguishes a recoverable file lock (editor mid-save) from a
  permanent IO failure; locked themes keep their last-known-good snapshot and retry on the next
  lookup instead of dropping out of the picker
- New built-in: **Synthwave Sunset** — Hot Magenta + Cyan on midnight violet, 80s neon-grid vibes;
  tenth theme in the picker
- Author credits refreshed: brand themes are credited as "Hellion Forge"; **Mint Grove** and **Forge
  Merchantman** now credited to **Carla Beleandis** as a community thanks

No schema bump, no user-visible behaviour change other than smoother frames on GC-sensitive setups
and one additional colour option.

Modding & support: join Hellion Forge — <https://discord.gg/X9V7Kcv5gR>

Based on Chat 2 1.35.3 (upstream Infiziert90/ChatTwo, EUPL-1.2).

---

## Hellion Chat 1.4.0 — Critical Lifecycle Fixes

First sub-patch of the v1.4.x Polish Sweep series. Seven known lifecycle and race bugs eliminated
before any performance refactor sits on top.

- MessageStore disposal no longer triggers GC.Collect globally; Pooling=false on the SQLite
  connection means there's nothing left to clean up by hand
- PendingMessage and RetentionSweep worker threads are explicitly marked IsBackground=true so the
  plugin domain can unload during XIVLauncher reload without waiting for them
- EmoteCache image and gif loaders moved from async-void to async Task with a shared task tracker,
  draining on Dispose so an in-flight load can no longer write to a disposed EmoteImages entry
- DisposeAsync 10s timeout now warns loudly instead of silently leaving the worker behind
- Plugin.Dispose flushes any pending DeferredSaveFrames before tearing services down, so settings
  changes made in the last few frames before disable are no longer lost
- The v13→v14 config migration now reads the pre-v13 backup and carries HellionThemeWindowOpacity
  into the new WindowOpacity field instead of falling back to the default 0.85

Modding & support: join Hellion Forge — <https://discord.gg/X9V7Kcv5gR>

Based on Chat 2 1.35.3 (upstream Infiziert90/ChatTwo, EUPL-1.2).

---

## Hellion Chat 1.3.0 — Plugin Integrations: Honorific

First step on the plugin-integration roadmap. HellionChat now listens to Honorific and shows your
custom title in the chat header. The slot auto-hides when Honorific is not installed, when no custom
title is active, or when you are using the original FFXIV title.

- New "Integrations" settings tab
- Honorific integration with auto-detection and live updates
- "Coming soon" preview of the next five planned integrations: context menu actions, smart
  notifications, RP status block, ExtraChat channels, and quick DM compose
- Maintainer attribution buttons for Honorific repo and Caraxi
- New service-class pattern under HellionChat/Integrations/

Modding & support: join Hellion Forge — <https://discord.gg/X9V7Kcv5gR>

Based on Chat 2 1.35.3 (upstream Infiziert90/ChatTwo, EUPL-1.2).

---

## v1.2.3 — Theme Expansion (2026-05-06)

### Added

- Four new built-in themes:
  - **Night Blue** — Royal Blue on deep marine, cool tech-dashboard mood
  - **Indigo Violet** — Royal Violet on deep indigo with a turquoise-mint counter (aurora glitter
    feel)
  - **Forge Merchantman** — Patina bronze on workshop slate with warm amber counter (Hellion Forge
    identity)
  - **Hellion Spectrum** — Deuteran/Protan-safe channel colours using Wong/Okabe-Ito palette tones;
    channel identity (Tell pink, Yell yellow, Shout orange, Party blue, FC green) preserved while
    keeping every channel separable under red-green colour vision deficiency
- Built-in theme catalogue grown from five to nine

### Notes

- No engine changes, no settings touched, no migration
- Default theme unchanged (Hellion Arctic). Existing custom themes keep working.
- Hellion Spectrum covers the ~99 % of CVD cases that are red-green; a Tritan-safe variant could
  follow in a later cycle if there is demand.

---

## v1.2.1 — Settings Cleanup (2026-05-06)

### Changed

- Settings cards re-sorted thematically: 9 cards remain, each card has one clear job and a one-line
  subtitle.
- **Theme & Layout** (new) collects the theme picker, window frame style (title bar, sidebar, hide
  button, pop-out title bar) and the timestamp style options.
- **Fonts & Colours** (new) houses font choice, font size and per-channel chat colours.
- **Data Management** (new) collects retention windows, cleanup, export, the database viewer and the
  shift-click advanced tools.
- **Privacy** is now focused on the privacy filter alone.
- **Chat** absorbs the Auto-Tell-Tabs history-preload slider that used to live under Privacy.
- **General** groups the keybind mode under Input.

### Removed

- Legacy "Style override" option and the unused style-name field — both obsolete since the v1.1.0
  themes engine.
- Legacy `WindowAlpha` slider — if you had it set, the value is auto-migrated to Theme & Layout →
  Window Style → Window Transparency.
- Unused `ShowThemeQuickPicker` schema field.

### Migration

- v15 → v16 with backup at `pluginConfigs/HellionChat.json.pre-v16-backup`.
- All other settings preserved unchanged.
- One-time toast on first start if Style override was previously active.

---

## v1.2.0 — Layout Refresh (2026-05-05)

### Added

- Sidebar tab modernization: icon-only at fixed 44 px, tooltip on hover, vertical accent pill for
  active tab
- Top tabs: accent underline pill replaces background fill on active tab
- Per-tab custom icons in Settings → Tabs (15-glyph FontAwesome picker)
- Bottom status bar (22 px): channel indicator, privacy badge, counters, tells, version — updates
  1×/sec
- Card rows as default message render: sender header in channel color, subtle border between cards
- Compact-Density toggle in Appearance: switches back to single-line `[HH:mm] Sender: Text` layout
- Auto-Tell tabs: per-partner hashed icon (7-glyph pool:
  envelope/star/heart/bell/bookmark/flag/fire) plus hashed color (12-color palette) — 84 distinct
  icon+color combinations
- Unread indicator: pulsing red dot in the top-right corner of any sidebar tab icon with unread
  messages, 2-second sine-wave pulse, respects `Configuration.ReduceMotion`

### Changed

- Migration v14 → v15: deprecated Configuration fields `HellionThemeEnabled` and
  `HellionThemeWindowOpacity` removed
- Appearance settings cleaned: legacy theme-engine bindings replaced by Themes tab (introduced in
  v1.1.0)

### Fixed

- Settings save no longer wipes chat history by default — the heavy
  `ClearAllTabs + FilterAllTabsAsync` cycle now only runs when a filter-relevant setting actually
  changed (Privacy filter, persisted channels, per-tab channel selection). Cosmetic changes keep the
  in-session chat intact
- Identifier-based `MessageList` restore in `Configuration.UpdateFrom` plus TempTab skip in
  `ClearAllTabs`/`FilterAllTabs` ensure persistent tabs and Auto-Tell tabs both survive the save
- Sidebar buttons now align vertically with the first message row (top padding mirrors the chat
  header toolbar height)
- Sidebar child window no longer paints the top padding area with its frame background
- Status bar version slot (`vX.Y.Z · Hellion`) no longer clips its rightmost character

### Notes

- Polish phase (animations, theme crossfade, header quick-picker) follows in v1.3.0
- Top-Tab icon prefixes were considered but dropped: Dalamud's default font atlas does not include
  FontAwesome codepoints, so mixed-font in a single TabItem label renders as tofu. Underline pill
  alone is the v1.2.0 visual treatment for top tabs. Resolution would require Font-Atlas merge at
  FontManager level — out of scope.

---

## [1.1.0] — 2026-05-05 — Theme Foundation

First major UI cycle after v1.0.0. Theme engine, five built-in themes, custom themes via JSON,
settings card grid.

### Added

- **Theme engine** with five built-in themes: Hellion Arctic (default), Chat 2 Classic, Event
  Horizon, Moonlit Bloom, Mint Grove.
- **Settings → Themes** with mini mockup preview per theme. Clicking a card instantly switches the
  entire plugin (chat, settings, pop-outs).
- **Custom themes via JSON** in `pluginConfigs/HellionChat/themes/`. On first start,
  `example-theme.json` is placed there as a template.
- **Optional theme chat channel colours**: themes can ship their own channel colours. On switch, a
  banner appears with _Apply / Keep current_ — never applied automatically.
- **Settings card grid**: new overview on open, clicking a card navigates into the section's detail
  view. Breadcrumb + ESC navigate back.
- **`docs/THEME-AUTHORING.md`** as a guide for writing custom themes, with Hellion Forge branding.

### Changed

- **Plugin icon** updated to Hellion Forge hammer (previously a ChatTwo derivative).
- **Settings detail view** uses the full width — the second tab list on the left is gone because the
  card overview handles navigation.
- **`HellionStyle.PushGlobal`** is now theme-driven (`PushGlobal(theme, opacity)`) instead of
  const-palette-driven.
- **Configuration v13 → v14**: all users land on `hellion-arctic`. Those who prefer the upstream
  look can select `chat2-classic` in Settings → Themes.

### Deprecated

- `Configuration.HellionThemeEnabled` and `HellionThemeWindowOpacity` remain readable for one
  release as a safety net but are no longer evaluated. Removal planned for v1.2.0.

### Security

- Custom theme JSON loader validates `schemaVersion`, required fields and hex format. Invalid themes
  are skipped with a warning; the plugin continues loading with built-ins.

### Internal

- 51 local unit tests (theme records, registry, JSON round-trip, sanity per built-in theme). Tests
  are gitignored.

---

## [1.0.3] — 2026-05-04 — Polish Patch

Four small polish items from the backlog bundled together:

- **Hide on New Game+ menu**: optional global toggle that hides Hellion Chat (and all other plugin
  windows such as Settings, DB Viewer, pop-outs) while the NG+ menu is open. Settings → Window →
  Frame, default off. Skips the entire `WindowSystem.Draw()` path analogous to the existing
  LoadingScreens pattern.
- **Channel selector colouring**: optional tinting of the channel-select button (comment icon) next
  to the input field in the current channel colour. Settings → Appearance → Chat Colours, default
  on. Consistent with the existing input text colouring; ExtraChat override is carried over.
- **(De)buff icon aspect-ratio fix**: `PayloadHandler.InlineIcon` was squashing all hover icons to
  32×32. Status icons with non-square dimensions (debuffs with an arrow indicator) are now shrunk
  aspect-preserving. Standalone float-math implementation with zero-size guard instead of a
  cherry-pick from the open ChatTwo PR #157 (which had an int-division trap).
- **HideState logging sweep**: all HideState transitions (Battle/Cutscene/User/Override plus pop-out
  mirroring) log at verbose level. Off by default; enable via `/xllog set HellionChat verbose` for
  bug-report diagnostics.

[Release Notes 1.0.3](https://gitea.hellion-forge.cloud/JonKazama-Hellion/HellionChat/releases/tag/v1.0.3)

---

## [1.0.1] — 2026-05-04 — Window Position Recovery

Fixes an off-screen-window scenario the user could end up in after a monitor disconnect or display
layout change between sessions. An automatic one-shot bounds check on the first draw after plugin
load snaps the window back into the visible viewport, and a new "Reset Window Position" button in
Settings → Window → Frame serves as the manual escape hatch for edge cases.

Bundled housekeeping since v1.0.0: documentation restructured into `docs/`, stale ChatTwo/\* paths
in repo configs cleaned up, Pidgin parser library bumped from 3.3.0 to 3.5.1, GitHub Actions bumps
for `actions/setup-dotnet` (4 → 5) and `github/codeql-action` (3 → 4).

[Release Notes 1.0.1](https://gitea.hellion-forge.cloud/JonKazama-Hellion/HellionChat/releases/tag/v1.0.1)

---

## [1.0.0] — 2026-05-03 — Standalone Major Release

First fully independent release. Code namespace, IPC channels and source tree structure consolidated
under `HellionChat.*`. Plugin refuses to start alongside an active upstream Chat 2 (bilingual
conflict message). SQLite native pinned to 3.50.3 (CVE-2025-6965, CVE-2025-7709). Tab layout default
for new installs and users on config version 12 or older restructured (5 thematic tabs instead of 6+
kitchen-sink). Sweep of critical and major findings from the codebase audit incorporated.

[Release Notes 1.0.0](https://gitea.hellion-forge.cloud/JonKazama-Hellion/HellionChat/releases/tag/v1.0.0)

---

## [0.6.1] — 2026-05-03 — Pop-Out Discoverability & /tell Auto-Pop-Out

Pop-out button visible in the chat header, one-time hint banner for the pop-out feature. New setting
"Open new /tell tabs directly as pop-out". Pop-out input is now active by default. Bug fixes: ghost
windows on LRU-drop / logout, dead zone below the input bar when the hint banner is active.

[Release Notes 0.6.1](https://gitea.hellion-forge.cloud/JonKazama-Hellion/HellionChat/releases/tag/v0.6.1)

---

## [0.6.0] — 2026-05-03 — UX Polish: Pop-Out Input + Colour Presets

Two opt-in UX features. Pop-out windows optionally get a compact input bar with a channel-coloured
icon button and an independent text buffer per pop-out. Seven built-in colour presets (Classic, High
Contrast, Pastel, Dark Mode Tuned, Hellion, Night Blue, Indigo Violet) for one-click apply.
Configuration migration v10 → v11.

[Release Notes 0.6.0](https://gitea.hellion-forge.cloud/JonKazama-Hellion/HellionChat/releases/tag/v0.6.0)

---

## [0.5.4] — 2026-05-02 — WrapText Hardening

`ImGuiUtil.WrapText` rewritten from pointer arithmetic to Span- and index-based control flow.
Permanently closes the recurring CodeQL critical alert "unvalidated local pointer arithmetic". No
user-visible behaviour change — word-wrap output is byte-identical to 0.5.3.

[Release Notes 0.5.4](https://gitea.hellion-forge.cloud/JonKazama-Hellion/HellionChat/releases/tag/v0.5.4)

---

## [0.5.3] — 2026-05-02 — Pointer Arithmetic Hardening

First attempt at closing the CodeQL critical alert in `ImGuiUtil.WrapText`. Encoded byte buffer
length is validated via `GetByteCount` before pointer arithmetic.

[Release Notes 0.5.3](https://gitea.hellion-forge.cloud/JonKazama-Hellion/HellionChat/releases/tag/v0.5.3)

---

## Earlier Versions

Releases before 0.5.3 (bootstrap phase 0.1.0 to 0.5.2) are available directly on the Gitea release
stream:

[All Releases](https://gitea.hellion-forge.cloud/JonKazama-Hellion/HellionChat/releases)

---

## Maintenance Note

The source of truth for the user-facing changelog is the `changelog:` block in
`HellionChat/HellionChat.yaml`. `repo.json` and the GitHub release body are fed from there. This
file (`docs/CHANGELOG.md`) is a curated summary with links to the release pages and is updated
manually on each version bump.
