@@ -26,12 +26,20 @@ private static void LayoutPillarsDiagram(
2626 g => g . Key ,
2727 g => g . OrderBy ( n => GetMetadataInt ( n . Metadata , "pillars:segmentIndex" ) ) . ToList ( ) ) ;
2828
29+ // ── Title font is 20% larger and bold ──────────────────────────────────
30+ double titleFontSize = Math . Round ( theme . FontSize * 1.2 , 1 ) ;
31+
2932 double titleOffset = ! string . IsNullOrWhiteSpace ( diagram . Title ) ? theme . TitleFontSize + 8 : 0 ;
30- double maxTextWidth = diagram . Nodes . Values . Max ( n =>
31- EnsureIconWidth ( n , theme , EstimateTextWidth ( n . Label . Text , n . Label . FontSize ?? theme . FontSize ) + theme . NodePadding * 2.5 ) ) ;
32- double colWidth = Math . Max ( minW + 24 , maxTextWidth ) ;
33+ double maxSegTextWidth = diagram . Nodes . Values
34+ . Where ( n => n . Metadata . TryGetValue ( "pillars:kind" , out var kind ) && "segment" . Equals ( kind as string , StringComparison . Ordinal ) )
35+ . Select ( n => EnsureIconWidth ( n , theme , EstimateTextWidth ( n . Label . Text , n . Label . FontSize ?? theme . FontSize ) + theme . NodePadding * 2.5 ) )
36+ . DefaultIfEmpty ( 0 )
37+ . Max ( ) ;
38+ double maxTitleTextWidth = titleNodes . Max ( n =>
39+ EnsureIconWidth ( n , theme , EstimateTextWidth ( n . Label . Text , titleFontSize ) + theme . NodePadding * 2.5 ) ) ;
40+ double colWidth = Math . Max ( minW + 24 , Math . Max ( maxSegTextWidth , maxTitleTextWidth ) ) ;
3341
34- double titleH = titleNodes . Max ( node => EnsureIconHeight ( node , Math . Max ( nodeH , ( theme . FontSize * 1.15 ) + theme . NodePadding * 2.2 ) ) ) ;
42+ double titleH = titleNodes . Max ( node => EnsureIconHeight ( node , Math . Max ( nodeH , ( titleFontSize * 1.15 ) + theme . NodePadding * 2.2 ) ) ) ;
3543 double segH = diagram . Nodes . Values
3644 . Where ( n => n . Metadata . TryGetValue ( "pillars:kind" , out var kind ) && "segment" . Equals ( kind as string , StringComparison . Ordinal ) )
3745 . Select ( node => EnsureIconHeight ( node , nodeH ) )
@@ -57,19 +65,30 @@ private static void LayoutPillarsDiagram(
5765 ? theme . NodeStrokePalette [ i % theme . NodeStrokePalette . Count ]
5866 : ColorUtils . Darken ( pillarFill , 0.18 ) ;
5967
68+ // ── Title: vibrant fill, contrast text, bolder border ──────────────
69+ string titleFill = ColorUtils . Blend ( ColorUtils . Vibrant ( pillarFill , 2.0 ) , pillarFill , 0.5 ) ;
70+ string titleTextColor = ColorUtils . ChooseTextColor ( titleFill ) ;
71+
6072 titleNode . Shape = Shape . RoundedRectangle ;
6173 titleNode . Width = colWidth ;
6274 titleNode . Height = titleH ;
6375 titleNode . X = colX ;
6476 titleNode . Y = curY ;
65- titleNode . FillColor = pillarFill ;
66- titleNode . StrokeColor = pillarStroke ;
77+ titleNode . FillColor = titleFill ;
78+ titleNode . StrokeColor = ColorUtils . Darken ( titleFill , 0.20 ) ;
79+ titleNode . Metadata [ "render:strokeWidth" ] = theme . StrokeWidth * 2.5 ;
80+ titleNode . Label . FontSize = titleFontSize ;
81+ titleNode . Label . FontWeight = "bold" ;
82+ titleNode . Label . Color = titleTextColor ;
83+ // Disable the gradient on title nodes so the solid saturated fill shows
84+ titleNode . Metadata [ "render:noGradient" ] = true ;
6785 SetLabelCenter ( titleNode , colWidth / 2 , titleH / 2 ) ;
6886 curY += titleH + segGap ;
6987
7088 if ( segmentsByPillar . TryGetValue ( pillarIdx , out var segments ) )
7189 {
7290 string segFill = ColorUtils . Lighten ( pillarFill , 0.25 ) ;
91+ string segStroke = ColorUtils . Lighten ( pillarStroke , 0.30 ) ;
7392
7493 foreach ( var segNode in segments )
7594 {
@@ -79,7 +98,7 @@ private static void LayoutPillarsDiagram(
7998 segNode . X = colX ;
8099 segNode . Y = curY ;
81100 segNode . FillColor = segFill ;
82- segNode . StrokeColor = pillarStroke ;
101+ segNode . StrokeColor = segStroke ;
83102 SetLabelCenter ( segNode , colWidth / 2 , segH / 2 ) ;
84103 curY += segH + segGap ;
85104 }
0 commit comments