Plan viewer: fix edge/label misestimate mismatch, zero-grant text, Light-theme orange contrast - #4632
Merged
Merged
Conversation
…el (#4627) PlanEdgeColour.ForChild compared the CHILD's un-normalized total ActualRows (summed across every execution) against its per-execution EstimateRows, while the node label already divided ActualRows by ActualExecutions first. On the inner side of a Nested Loops join that ran thousands of times, the edge got the worst-misestimate colour (FluoRed) even when the label showed the estimate was close. Both now go through one shared helper, PlanRowAccuracy, so they can't disagree again. ForChild takes actualExecutions and normalizes through it; the plan canvas and minimap callers, and the node-label calculation, all call the same helper. Pinned against udf_plan.sqlplan: nodes 7, 8, 10 and 12 no longer get FluoRed, and the ratio PlanRowAccuracy returns for each is pinned too.
…4628) GrantedMemory="0" (a query that never asked for or never got a memory grant) made the percentage math fall back to a fake 100%, so the Runtime Summary card read "0 KB granted, 0 KB used (100%)". It now says "No memory grant" with no percentage, and the color key no longer runs the zero through the same utilization thresholds a real grant uses. A real grant keeps today's "X granted, Y used (Z%)" text and its existing color rules.
OrangeBrush (#FFB347), Brushes.Orange (#FFA500) and Brushes.OrangeRed (#FF4500) were fixed WPF brushes that never changed with the theme. On Light they measured 1.78:1, 1.97:1 and 3.44:1 against the node/panel backgrounds they paint text on, all under WCAG AA's 4.5:1 floor; OrangeRed was 4.46:1 on Dark too, just under it. The "warning" tier (the root node's "N warnings" badge, the missing-index impact %, the per-thread skew text, cost 25-49%) now reuses the existing theme-token WarningBrush, already proven as plan-viewer text elsewhere in this control. The "critical" tier (cost >= 50%, elapsed/CPU >= 1s, a row estimate off by 10x+) gets one new theme token, PlanCriticalOrangeBrush, added to Light, Dark and Cool Breeze in Lite, the Dashboard and the Darling Viewer (all three host apps this shared control renders in) so a theme switch can never hit a missing FindResource key. Both keep the orange/warning meaning, tuned per theme: a darker orange on Light, a lighter one on Dark. Left unconverted (non-text, not covered by WCAG's 4.5:1 text floor): the "expensive node" border (Rendering.cs/Minimap.cs, Brushes.OrangeRed) and the per-node warning-triangle icon fill (Rendering.cs, Brushes.Orange). Filed #4635 for the same fixed-OrangeRed pattern in each app's own collector health status text (MainWindow.xaml.cs / MainWindow.ServerManagement.cs) — a different subsystem, outside this shared plan-viewer code.
…to Lite and the Darling Viewer (#4632) ThemeColorOverrideTests pins every Lite/Darling Viewer theme file at exactly 18 user-overridable <Color> keys. #4629's PlanCriticalOrangeColor was a 19th, so EveryThemeFile_DeclaresExactlyThe- ExposedAndWithheldColors and TheColorDeclarationRegex_MatchesEveryDeclarationInEveryTheme_Exactly- Once failed on all six files. Follows the existing WarningTextBrush precedent: a literal-hex SolidColorBrush with no backing <Color> key, so it never enters the override palette. Renamed PlanCriticalOrangeBrush to CriticalTextBrush to match. Only Lite and the Darling Viewer carry it - the deprecated Dashboard's three theme files are reverted to dev, since the Dashboard is out of scope. PlanViewerControl's fallback for a theme with no CriticalTextBrush (the Dashboard) is Brushes.OrangeRed, the Dashboard's pre-#4629 look, not the Dark theme's #FF7043 (worse contrast than OrangeRed on white). Viewer4629Tests: the three tests that read PlanCriticalOrangeColor via DeclaredColors now read the literal CriticalTextBrush hex via a regex helper; file lists drop the three Dashboard entries and AllNineFiles is renamed AllSixFiles.
…TextBrush (#4635) Lite's and the Darling Viewer's status bar set CollectorHealthText.Foreground to the fixed Brushes.OrangeRed (#FF4500) for "N erroring" and "Capture down" - 3.44:1 on Light's status bar background (BackgroundLightColor), under WCAG AA's 4.5:1 text floor, the same defect #4629 fixed in the plan viewer. Both now resolve CriticalTextBrush the same way PlanViewerControl does, falling back to OrangeRed if the theme doesn't declare it. Left alone as non-text uses, with the reason: - Lite/MainWindow.xaml.cs ~1119 and ~1231: the tab alert badge's Background, whose text is white, set separately - not a text foreground. - PlanViewerControl.Minimap.cs ~185 and PlanViewerControl.Rendering.cs ~86: BorderBrush, held to WCAG's 3:1 non-text floor, not 4.5:1. - The deprecated Dashboard's two OrangeRed text spots (MemoryContent.PlanCache.cs, ResourceMetricsContent.TempdbStats.cs): out of scope, Dashboard is deprecated. Viewer4629Tests.CriticalTextBrush_ReadsAsTextOnNodePanelAndStatusBarBackgrounds now also asserts CriticalTextBrush clears 4.5:1 on BackgroundLightColor, the status bar's background in both apps. No hex value needed to change: the existing #4629 pins already clear it.
RepoFileAdoptionTests.ExactlyOneFile_DeclaresTheSharedRepoFileReader: Viewer4629Tests had its own private ReadRepoFile/RepoRoot pair instead of the shared RepoFile.ReadRepoFile thirty-four other classes already use. Migrated onto RepoFile.ReadRepoFile and dropped the private copy. PlanViewerControl_HasNoInlineSeverityColorLiterals: two #4629 comments in PlanViewerControl. Properties.cs and PlanViewerControl.Rendering.cs quoted the old fixed OrangeBrush's hex (#FFB347) for context, which the source-literal census cannot tell apart from a real inline color. Reworded to "hex FFB347" (no #), same meaning, outside the pin's pattern. Both predate this PR's own commits but surfaced only once the full suite ran; fixed in place rather than deferred since both are one- or two-line, in files this PR already touches.
…ng CriticalTextBrush key (#4629, #4635) Adds the first live PlanViewerControl pin (Lite.Tests/PlanViewer4632FallbackTests.cs): constructs the control inside the Dashboard's real Light theme scope (which lacks CriticalTextBrush) and asserts nothing throws and the resolved brush is the OrangeRed fallback, then repeats inside Lite's Light theme scope (which has the key) and asserts the theme hex. Also pins that no .xaml under PerformanceMonitor.Ui binds CriticalTextBrush or WarningBrush with StaticResource, which is the pattern that would throw. Rewords the six theme files' CriticalTextBrush comment and Viewer4629Tests.cs's matching prose: both named a PlanCriticalOrangeColor/PlanCriticalOrangeBrush pair that existed only inside this PR and was never on dev, and the comment predates #4635 giving the brush a second consumer (the status bar).
erikdarlingdata
marked this pull request as ready for review
September 28, 2026 20:56
This was referenced Sep 28, 2026
Closed
erikdarlingdata
added a commit
that referenced
this pull request
Sep 28, 2026
…or (#4651) (#4658) WarningColor #9E4A0B measured 4.41:1 against the plan viewer properties panel's BackgroundDarkColor, under WCAG AA's 4.5:1 text floor, once #4632 put warning-tier text there. Darkened to #9C490B, same hue, the smallest step that clears 4.5:1 on every background Cool Breeze draws WarningBrush text on. Applied identically to Lite and the Darling Viewer. Viewer4629Tests now holds Cool Breeze to the same strict floor as Light and Dark (previously exempted), and checks the card and status-bar backgrounds alongside the panel and plan nodes for both WarningBrush and CriticalTextBrush.
This was referenced Sep 29, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #4627
Fixes #4628
Fixes #4629
Fixes #4635
Why
Four defects in the shared plan-viewer code (
PerformanceMonitor.PlanAnalysis,PerformanceMonitor.Ui) and, for #4635, the same fixed-colour pattern in each app's own status bar:operator's un-normalized total
ActualRows(summed across every execution) against itsper-execution
EstimateRows, while the node label already dividedActualRowsbyActualExecutionsfirst. An operator that ran thousands of times could get the worstmisestimate colour (FluoRed) on its edge while its own label showed the estimate was close.
GrantedMemory="0"(no grant at all), printing "0 KB granted, 0 KB used (100%)".OrangeBrush#FFB347,Brushes.Orange#FFA500,Brushes.OrangeRed#FF4500) painted plan-viewer text regardless of theme. On Light they measured1.78:1, 1.97:1 and 3.44:1 against the backgrounds they sit on — all under WCAG AA's 4.5:1 floor
for text — and
Brushes.OrangeRedwas 4.46:1 on Dark too, just under it.Brushes.OrangeRed(3.44:1 on Light) painted Lite's and the DarlingViewer's status-bar collector-health text ("N erroring" / "Capture down"), a different subsystem
from the plan viewer but the identical contrast defect.
What changes
#4627 —
PerformanceMonitor.PlanAnalysis/PlanRowAccuracy.cs(new) is the one shared helper thatturns actual-vs-estimated rows into a per-execution ratio; both the node label
(
PlanViewerControl.Rendering.cs) andPlanEdgeColour.ForChild(now takingactualExecutions)call it, so they cannot disagree again. Both the plan canvas and the minimap callers were updated.
PlanEdgeColour's andGetLinkColorBrush's doc comments no longer claim to matcherikdarlingdata/PerformanceStudio's
GetLinkColorBrush"exactly" — PS has the same un-normalizedbug (erikdarlingdata/PerformanceStudio#594), so PerformanceMonitor is now ahead of PerformanceStudio
on this edge-colour calculation, on purpose, until PS's own issue closes it.
#4628 —
PerformanceMonitor.PlanAnalysis/PlanDisplayText.cs, the memory-grant row: whenGrantedMemoryKB == 0the row now reads "No memory grant" (plus a spill tag if one applies), withno percentage, and the colour key no longer runs a zero through the utilization thresholds a real
grant uses (defaults to null/neutral, escalating to
WarningBrushonly if there was a spilldespite no grant). A real grant is untouched: same "X granted, Y used (Z%)" text, same colour rules.
PerformanceStudio has the same bug: erikdarlingdata/PerformanceStudio#595.
#4629 — the "warning" tier (root-node "N warnings" badge, missing-index impact %, per-thread
skew text, cost 25-49%) now reuses the existing theme-token
WarningBrush, already proven asplan-viewer text elsewhere in this same control (the Parameters card annotations). The "critical"
tier (cost >= 50%, elapsed/CPU >= 1s, a row estimate off by 10x+) gets one new theme token,
CriticalTextBrush(renamed from this PR's earlierPlanCriticalOrangeBrush/PlanCriticalOrangeColor— see below), added toLightTheme.xaml,DarkTheme.xamlandCoolBreezeTheme.xamlin Lite and the Darling Viewer only (Light/CoolBreeze#A83A0D, Dark#FF7043; both clear 4.5:1 against every page/card/node background their own theme declares). Thestatic, always-#FFB347
OrangeBrushfield inPlanViewerControl.xaml.csis gone.Renamed and rescoped:
ThemeColorOverrideTestspins every Lite/Darling Viewer theme file at exactly eighteenuser-overridable
<Color>keys; the originalPlanCriticalOrangeColorwas a nineteenth and brokethat pin on all six files. Fixed by following the existing
WarningTextBrushprecedent — aliteral-hex
SolidColorBrushwith no backing<Color>key, so it never enters the overridepalette — and renaming it
CriticalTextBrushto match. The deprecated Dashboard is out ofscope: it is not touched by this PR at all (
git diff --stat origin/dev...HEAD -- deprecated/isempty), so its three theme files do not carry
CriticalTextBrush, andPlanViewerControl'sfallback for a theme without that key is
Brushes.OrangeRed— the Dashboard's original, pre-#4629look — not the Dark theme's
#FF7043(about 2.7:1 on white, worse than OrangeRed's 3.44:1). Thatfallback choice is a one-line comment on the property in
PlanViewerControl.xaml.cs.#4635 —
Lite/MainWindow.xaml.cs(the "Collectors: N erroring" and "Capture down: ..." statustext) and
Darling/PerformanceMonitor.Darling.Viewer/MainWindow.ServerManagement.cs(the same"Collectors: N erroring" text) now resolve
CriticalTextBrushthe same wayPlanViewerControldoes:
(TryFindResource("CriticalTextBrush") as Brush) ?? Brushes.OrangeRed. Both status bars sitdirectly on
BackgroundLightColor(Lite's statusBorderand the Darling Viewer's window bothdeclare
Background="{DynamicResource BackgroundLightBrush}"with nothing between it and thetext) — the same background the plan-viewer node card already uses, so the existing #4629 hex
values clear it with no per-theme change needed. The deprecated Dashboard has the identical pattern
in
MemoryContent.PlanCache.csandResourceMetricsContent.TempdbStats.csbut is not touched,for the same out-of-scope reason as above.
Left unconverted (non-text, not covered by WCAG's 4.5:1 text floor, which is scoped to text):
PlanViewerControl.Rendering.cs:86andPlanViewerControl.Minimap.cs:185—Brushes.OrangeRedasthe border of an "expensive node" highlight (WCAG's non-text/graphical floor is 3:1).
PlanViewerControl.Rendering.cs:147—Brushes.Orangeas the fill of the small per-nodewarning-triangle icon (a different, decorative badge from the root-node "N warnings" text the
issue named).
Lite/MainWindow.xaml.cs:1121and:1233— the per-tab alert badge'sBackground, whose text(white, set separately on the same badge) is what actually needs to clear a contrast floor, not
the fill it sits on.
Known pre-existing gap, not touched here: Cool Breeze's own
WarningColor(unchanged by thisPR) measures 4.41:1 against the properties-panel background (
BackgroundDarkColor) — a hair under4.5:1. The issue named only Light and Dark; re-tuning Cool Breeze's
WarningColorwould ripple intoevery other place that token is used app-wide, out of this PR's scope. Filed as #4651.
Test plan
Darling/Darling.Tests/Viewer4627Tests.cs, pinned againstDarling/Darling.Tests/Fixtures/OriginPlans/udf_plan.sqlplan: nodes 7, 8, 10, 12 no longerget FluoRed (now Neutral), node 9 is LightOrange, and the exact
PlanRowAccuracyratio ispinned for each. A companion fact reproduces the old (pre-fix) total-over-per-execution math
and shows it would have put all five at FluoRed. Existing
Viewer4579Tests.csupdated forForChild's newactualExecutionsparameter (inserted as1, a no-op, so every existingpinned ratio is unchanged).
Darling/Darling.Tests/Viewer4570Tests.cs: a real grant keeps"1.0 MB granted, 512 KB used (50%)"; a zero grant reads "No memory grant" with no
%and anull colour key.
Darling/Darling.Tests/Viewer4629Tests.cs, rewritten this round: reads each theme XAMLfile's real declared colours/brushes and measures with the shared
PerformanceMonitor.Ui.WcagContrasthelper.WarningColor(viaThemeXamlRewriter. DeclaredColors) andCriticalTextBrush(via a newLiteralBrushHexregex helper, since ithas no
<Color>key) both clear 4.5:1 against the node background (BackgroundLightColor),the properties-panel background (
BackgroundDarkColor), and — new for Collector health status text: fixed Brushes.OrangeRed fails WCAG contrast on Light theme #4635 — the status barbackground (
BackgroundLightColoragain, asserted as its own named constant so a futurechange to either resource is caught independently), on Light and Dark, across Lite and the
Darling Viewer only. Golden pin on
CriticalTextBrush's hex per theme (values unchanged).Existence check across all six theme files including Cool Breeze.
dotnet build Darling/Darling.Tests/Darling.Tests.csproj -c Debug— Build succeeded, 0 warnings.dotnet build Lite.Tests/Lite.Tests.csproj -c Debug— Build succeeded, 0 warnings (alsobuilds
Lite/PerformanceMonitorLite.csprojas a dependency).dotnet build deprecated/Dashboard/Dashboard.csproj -c Debug— Build succeeded, 0 warnings.Confirms the shared
PerformanceMonitor.Uichange (theCriticalTextBrushrename and theBrushes.OrangeRedfallback) still compiles for the Dashboard's own consumption, withoutediting any Dashboard source.
Darling.Tests.exerun: 16541 total, 0 errors, 1 failed, 1025 skipped, 1 not run. Theone failure,
AvailabilityGroupsTabRefreshTests.Render_UnchangedRows_StaysUnderTheHundredMillisecondBudget,is a known unrelated flake (a render-timing budget test) and is not connected to anything this PR touches.
The "not run" test and the 1025 skips were
identical across both the first (pre-fix) and final full runs, so neither moved with this PR.
Lite.Tests.exerun: 5521 total, 0 errors, 0 failed.Darling.Tests.exere-run: 16541 total, 0 errors, 0 failed, 1025skipped, 1 not run. The known-unrelated flake named above did not fire this run — it stays on
the known-flake list regardless, since flaky means intermittent, and fixing it is out of this
PR's scope.
Lite.Tests.exere-run: 5524 total, 0 errors, 0 failed (+3 overthe count above: the new live pin file below).
Lite.Tests/PlanViewer4632FallbackTests.cs(3[Fact]s, the first test ineither suite to construct a live
PlanViewerControl): constructs the control inside thedeprecated Dashboard's real Light theme scope (parsed with
XamlReader.Parse; noCriticalTextBrushkey), asserts nothing throws and the resolved brush is OrangeRed (#FF4500);repeats inside Lite's real Light theme scope (has the key) and asserts the theme hex
#A83A0D;and pins that no
.xamlunderPerformanceMonitor.UibindsCriticalTextBrushorWarningBrushwith
StaticResource. Not attempted: loading a real plan and reading a rendered node's cost-textbrush —
LoadPlanisasyncand awaitsTask.Run, and theOnStaThreadharness (like its threeprecedents in this repo) joins a thread that never pumps a
Dispatchermessage loop, so thatcontinuation would never return to it; the resolved-brush assertions already pin the exact color
that render path would hand a critical-tier node.
(
PlanViewerControl.xaml.cs:110) to(SolidColorBrush)FindResource("CriticalTextBrush")(aStaticResource-equivalent lookup that throws on a miss).Lite.Tests.exe -class Lite.Tests.PlanViewer4632FallbackTestswent RED:Total: 3, Failed: 1, with the Dashboard-scope case throwing exactly the exception the fallback guards against —System.Windows.ResourceReferenceKeyNotFoundException: 'CriticalTextBrush' resource not found.atPlanViewerControl.xaml.cs:line 110. Reverted the edit (git diffon the fileconfirmed empty), rebuilt, reran GREEN:
Total: 3, Failed: 0.CriticalTextBrushcomment andViewer4629Tests.cs's matchingprose off the retired
PlanCriticalOrangeColor/PlanCriticalOrangeBrushpair name (a pair thatexisted only inside this PR, never on
dev) to#4629/#4635and the brush's now-two consumers(plan viewer, status bar). Confirmed zero remaining repo-wide hits (outside
deprecated/) forPlanCriticalOrangeColor,PlanCriticalOrangeBrush, orwas PlanCriticalOrange.Lite.Tests.exe -class Lite.Tests.ThemeColorOverrideTests -class Lite.Tests.ThemeStatusContrastTests— 130/130.
Darling.Tests.exe -class Darling.Tests.Viewer4629Tests— 20/20.pin, which is covered in its own section below) and fixed in this same PR,
since both were one or two lines in files this PR already touches:
-
RepoFileAdoptionTests.ExactlyOneFile_DeclaresTheSharedRepoFileReader— the existingViewer4629Tests.csdeclared its own privateReadRepoFile/RepoRootpair insteadof calling the shared
RepoFile.ReadRepoFilethirty-four other classes already use.Migrated onto
RepoFile.ReadRepoFile; the private pair is gone.-
PlanViewerWarningColorAndFixTests.PlanViewerControl_HasNoInlineSeverityColorLiterals—two
#4629comments inPlanViewerControl.Properties.csandPlanViewerControl.Rendering.csquoted the old fixedOrangeBrush's hex (#FFB347) forcontext; the source-literal census cannot tell that apart from a real inline color.
Reworded to "hex FFB347" (no
#), same meaning, outside the pin's pattern.git diff --stat origin/dev...HEAD -- deprecated/prints nothing — confirmed no Dashboardsource is touched by this PR.
Root cause of the ThemeColorOverrideTests failures (now fixed)
ThemeColorOverrideTests.EveryThemeFile_DeclaresExactlyTheExposedAndWithheldColorsandTheColorDeclarationRegex_MatchesEveryDeclarationInEveryTheme_ExactlyOnceboth count<Color x:Key="...">declarations per theme file and assert exactly 18 (the twelve user-overridable keysplus six deliberately-withheld ones). The first push's
PlanCriticalOrangeColorwas a nineteenth<Color>declaration in all six Lite/Darling-Viewer theme files, so both tests failed on all six.Fixed by making the critical-tier brush a literal-hex
SolidColorBrush(renamedCriticalTextBrush)with no backing
<Color>key at all — the same shapeWarningTextBrushalready used for exactlythis reason — so the palette count returns to 18. Verified green:
Lite.Tests.exe -class Lite.Tests.ThemeColorOverrideTests -class Lite.Tests.ThemeStatusContrastTests(130/130) and
Darling.Tests.exe -class Darling.Tests.Viewer4629Tests -class Darling.Tests.ViewerThemeColorOverridesTests(24/24), plus both full suites above.
Dashboard (deprecated): unchanged, and why it can't crash
PerformanceMonitor.Ui/PlanViewerControl.xaml.cs:108-110:CriticalOrangeBrushresolves in code —
(TryFindResource("CriticalTextBrush") as SolidColorBrush) ?? Brushes.OrangeRed.TryFindResourcereturnsnullon a miss instead of throwing, so the??always has a brush to fallback to. The same shape guards
WarningBrushat:93-94. Neither is a XAMLStaticResourcebinding,which is the form that throws (
ResourceReferenceKeyNotFoundException) when the key is missing —that binding form is what would take the Dashboard's plan viewer down, and neither brush uses it.
PerformanceMonitor.Ui's XAML usesStaticResourcefor either key:grep -rn "StaticResource CriticalTextBrush\|StaticResource WarningBrush" PerformanceMonitor.Ui/—zero hits, checked across all nine
.xamlfiles in that project. Every reference to either brush inthat project's XAML is
DynamicResourceinstead (also grep-confirmed), which resolves lazily andnever throws on a miss.
Lite.Tests/PlanViewer4632FallbackTests.cs.Lite.Tests.exe -class Lite.Tests.PlanViewer4632FallbackTests->Total: 3, Failed: 1—DashboardScope_MissingCriticalTextBrush_ConstructsCleanly_AndFallsBackToOrangeRedthrewSystem.Windows.ResourceReferenceKeyNotFoundException: 'CriticalTextBrush' resource not found.(from a temporary
(SolidColorBrush)FindResource("CriticalTextBrush")edit to the fallback line,reverted immediately after).
Total: 3, Failed: 0.deprecated/Dashboardbuild, no edits:dotnet build deprecated/Dashboard/Dashboard.csproj -c Debug->Build succeeded,0 Warning(s),0 Error(s).git diff --stat origin/dev...HEAD -- deprecated/prints nothing.CHANGELOG
SECTION: Fixed
ENTRY: - Nested Loops inner-side plan edges no longer show a misestimate colour the node's own label disagrees with ([#4632]) - The plan-edge colour and the node's "X of Y" label now come from the same per-execution ratio, so an operator that ran thousands of times no longer gets a worst-misestimate red edge while its label shows the estimate was close.
REF: [#4632]: #4632
ENTRY: - The Runtime Summary no longer says a query used "100%" of a memory grant it never got ([#4632]) - When a query's memory grant was zero, the plan viewer now says "No memory grant" instead of a fabricated "0 KB granted, 0 KB used (100%)".
REF: [#4632]: #4632
ENTRY: - Plan viewer orange text now reads clearly in the Light theme ([#4632]) - In Lite and the Darling Viewer, the warning badge, missing-index impact percentage, per-thread skew text, and the node cost/elapsed/CPU/row-estimate text used a fixed orange that was too pale to read on a white background; they now use theme-aware colours that stay readable in both Light and Dark.
REF: [#4632]: #4632
ENTRY: - Collector status text in the status bar now reads clearly in the Light theme ([#4632]) - When collectors were erroring or capture was down, the status bar text used a fixed orange that was too pale to read on a white background; it now uses the same theme-aware colour the plan viewer uses, readable in both Light and Dark.
REF: [#4632]: #4632