@@ -89,8 +89,98 @@ public static int Main (string [] args)
8989 var indexPath = Path . Combine ( ReportFolder , "index.html" ) ;
9090 var log = new StreamWriter ( indexPath ) ;
9191
92- log . WriteLine ( "<html><head><title>Extrospection results</title></head>" ) ;
93- log . WriteLine ( "<body><h1>Extrospection results</h1>" ) ;
92+ #region "Setup HTML Header and styles"
93+ log . WriteLine ( "<html><head><title>Extrospection results</title>"
94+ + @"<style>
95+ :root {
96+ --bg: #fff;
97+ --fg: #222;
98+ --green: #008100;
99+ --green-light: #90EE90;
100+ --red: #FF0200;
101+ --red-light: #FA8072;
102+ --yellow: #FFA502;
103+ --yellow-light: #FFDAB9;
104+ --grey: #e0e0e0;
105+ --switch-bg: #ccc;
106+ --switch-knob: #fff;
107+ }
108+ body.dark {
109+ --bg: #181a1b;
110+ --fg: #f1f1f1;
111+ --green: #388e3c;
112+ --green-light: #23422a;
113+ --red: #e57373;
114+ --red-light: #3a2323;
115+ --yellow: #ffd54f;
116+ --yellow-light: #4a3a1a;
117+ --grey: #23272a;
118+ --switch-bg: #555 !important;
119+ --switch-knob: #f1f1f1 !important;
120+ }
121+ body { background: var(--bg); color: var(--fg); transition: background 0.2s, color 0.2s; }
122+ .switch-container { position: absolute; top: 16px; right: 24px; z-index: 10; }
123+ .switch-label { cursor: pointer; font-size: 1em; user-select: none; color: var(--fg); }
124+ .switch-input { display: none; }
125+ .switch-slider { display: inline-block; width: 44px; height: 24px; background: var(--switch-bg) !important; border-radius: 12px; position: relative; vertical-align: middle; transition: background 0.2s; border: 1px solid #888; }
126+ .switch-slider:before { content: ''; position: absolute; left: 3px; top: 3px; width: 18px; height: 18px; background: var(--switch-knob) !important; border-radius: 50%; transition: left 0.2s, background 0.2s; box-shadow: 0 1px 3px #0002; border: 1px solid #888; }
127+ .switch-input:not(:checked) + .switch-slider { background: var(--switch-bg) !important; }
128+ .switch-input:checked + .switch-slider { background: #444 !important; }
129+ .switch-input:checked + .switch-slider:before { left: 23px; background: #222 !important; }
130+ .switch-label span { margin-left: 8px; }
131+ table { background: var(--bg); color: var(--fg); }
132+ td, th { color: var(--fg); }
133+ td[bgcolor='lightgreen'], th[bgcolor='lightgreen'] { background: var(--green-light) !important; color: var(--fg); }
134+ td[bgcolor='green'], th[bgcolor='green'] { background: var(--green) !important; color: #222; }
135+ td[bgcolor='red'], th[bgcolor='red'] { background: var(--red) !important; color: #222; }
136+ body.dark td[bgcolor='green'], body.dark th[bgcolor='green'] { color: #fff; }
137+ body.dark td[bgcolor='red'], body.dark th[bgcolor='red'] { color: #fff; }
138+ td[bgcolor='salmon'], th[bgcolor='salmon'] { background: var(--red-light) !important; color: var(--fg); }
139+ td[bgcolor='orange'], th[bgcolor='orange'] { background: var(--yellow) !important; color: #222; }
140+ td[bgcolor='peachpuff'], th[bgcolor='peachpuff'] { background: var(--yellow-light) !important; color: var(--fg); }
141+ td[bgcolor='lightgrey'], th[bgcolor='lightgrey'] { background: var(--grey) !important; color: var(--fg); }
142+ </style>"
143+ + @"<script>
144+ function setMode(dark, user) {
145+ document.body.classList.toggle('dark', dark);
146+ if (user) {
147+ document.documentElement.classList.add('xtro-user');
148+ localStorage.setItem('xtro-dark', dark ? '1' : '0');
149+ }
150+ updateSwitch();
151+ }
152+ function updateSwitch() {
153+ var input = document.getElementById('xtro-dark-switch');
154+ if (!input) return;
155+ // checked state should match body.dark class
156+ input.checked = document.body.classList.contains('dark');
157+ }
158+ window.addEventListener('DOMContentLoaded', function() {
159+ var userPref = localStorage.getItem('xtro-dark');
160+ var dark = false;
161+ if (userPref === '1') dark = true;
162+ else if (userPref === '0') dark = false;
163+ else dark = window.matchMedia('(prefers-color-scheme: dark)').matches;
164+ setMode(dark, false);
165+ var input = document.getElementById('xtro-dark-switch');
166+ if (input) input.addEventListener('change', function() { setMode(this.checked, true); });
167+ window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', function(e) {
168+ if (!localStorage.getItem('xtro-dark')) {
169+ setMode(e.matches, false);
170+ }
171+ });
172+ });
173+ </script>"
174+ + "</head>" ) ;
175+ log . WriteLine ( "<body>"
176+ + "<div class='switch-container'>"
177+ + "<label class='switch-label'>"
178+ + "<input type='checkbox' class='switch-input' id='xtro-dark-switch'>"
179+ + "<span class='switch-slider'></span>"
180+ + "<span>Dark Mode</span>"
181+ + "</label></div>"
182+ + "<h1>Extrospection results</h1>" ) ;
183+ #endregion "Setup HTML Header and styles"
94184
95185 log . WriteLine ( "<table border='0' cellpadding='4' cellspacing='0'>" ) ;
96186
0 commit comments