diff --git a/HellionChat/Ui/Components/HonorificHeader.cs b/HellionChat/Ui/Components/HonorificHeader.cs index d1e2ae3..5ab5139 100644 --- a/HellionChat/Ui/Components/HonorificHeader.cs +++ b/HellionChat/Ui/Components/HonorificHeader.cs @@ -13,7 +13,8 @@ namespace HellionChat.Ui.Components; // bracketed title only appears when there is actually a title to show. internal sealed class HonorificHeader { - public const float Height = 30f; + // Scaled: MainWindow reserves body height against this, so it follows. + public static float Height => StyleEngine.Metrics.HonorificHeight; // SelfTest observables — set on the real Draw path so a headless step can // assert the gate/colour/truncation outcome instead of re-implementing it. @@ -68,7 +69,11 @@ internal sealed class HonorificHeader using (_fonts.FontAwesome.Push()) { crownWidth = ImGui.CalcTextSize(crownGlyph).X; - dl.AddText(origin + new Vector2(0f, 8f), crownColor, crownGlyph); + dl.AddText( + origin + new Vector2(0f, StyleEngine.Metrics.CenterY(Height)), + crownColor, + crownGlyph + ); } // Gate the bracketed title through the 1.5.6 contract (toggle, IPC @@ -92,12 +97,17 @@ internal sealed class HonorificHeader // TruncateToFitWidth measures the *Regular* font, so this must run // OUTSIDE the FontAwesome.Push block above (crownWidth was measured // inside it, which is correct). - var maxTitleWidth = maxWidth - crownWidth - 6f - 8f; + var gap = StyleEngine.Metrics.HonorificBracketGap; + var maxTitleWidth = maxWidth - crownWidth - gap - StyleEngine.Metrics.HonorificInset; if (maxTitleWidth > 0f) { var rendered = StringUtil.TruncateToFitWidth($"«{current.Title}»", maxTitleWidth); LastRenderedTitle = rendered; - dl.AddText(origin + new Vector2(crownWidth + 6f, 8f), titleColor, rendered); + dl.AddText( + origin + new Vector2(crownWidth + gap, StyleEngine.Metrics.CenterY(Height)), + titleColor, + rendered + ); LastTitleRendered = true; } } diff --git a/HellionChat/Ui/Components/InputBar.cs b/HellionChat/Ui/Components/InputBar.cs index 47dfe8f..a281fd1 100644 --- a/HellionChat/Ui/Components/InputBar.cs +++ b/HellionChat/Ui/Components/InputBar.cs @@ -30,7 +30,10 @@ internal sealed class InputBar // they follow automatically. The pill's own metrics live in PillStyle now. public static float Height => StyleEngine.Metrics.InputBarHeight; private const int BufferCapacity = 500; - private const float QuickButtonsReserve = 130f; + + // Scaled: the buttons themselves grow with the font, so a fixed reserve + // stops fitting them at 150%. + private static float QuickButtonsReserve => StyleEngine.Metrics.InputQuickButtonsReserve; private readonly SymbolPicker _symbolPicker; private readonly FontManager _fonts; diff --git a/HellionChat/Ui/Components/MessageList.cs b/HellionChat/Ui/Components/MessageList.cs index 6cf0ad6..67982eb 100644 --- a/HellionChat/Ui/Components/MessageList.cs +++ b/HellionChat/Ui/Components/MessageList.cs @@ -308,12 +308,17 @@ internal sealed class MessageList { // Scrolled into a gap: one full-height dummy keeps the scrollbar honest. var gap = CompensatedDummy(plan.LeadDummyHeight + plan.EndDummyHeight); - ImGui.Dummy(new Vector2(10f, gap)); + ImGui.Dummy(new Vector2(StyleEngine.Metrics.MessageDummyWidth, gap)); return; } if (plan.LeadDummyHeight > 0f) - ImGui.Dummy(new Vector2(10f, CompensatedDummy(plan.LeadDummyHeight))); + ImGui.Dummy( + new Vector2( + StyleEngine.Metrics.MessageDummyWidth, + CompensatedDummy(plan.LeadDummyHeight) + ) + ); for (var i = plan.FirstVisible; i <= plan.LastVisible; i++) { @@ -329,7 +334,12 @@ internal sealed class MessageList } if (plan.EndDummyHeight > 0f) - ImGui.Dummy(new Vector2(10f, CompensatedDummy(plan.EndDummyHeight))); + ImGui.Dummy( + new Vector2( + StyleEngine.Metrics.MessageDummyWidth, + CompensatedDummy(plan.EndDummyHeight) + ) + ); } // First-frame / post-invalidation fallback: draw + measure every row into the