diff --git a/release-notes/v1.2.1.md b/release-notes/v1.2.1.md
new file mode 100644
index 0000000..e625b1f
--- /dev/null
+++ b/release-notes/v1.2.1.md
@@ -0,0 +1,9 @@
+## What's new
+
+- **Light or dark window.** A new theme button at the bottom of the sidebar switches the window between following Windows, always light, and always dark. Your choice is kept for the next start. Thanks to @MarcelL94 for building it (#13).
+
+## Fixes
+
+- **Black text in dark mode.** Some text in the window, such as the sidebar links, the quality preset cards and the on/off switches, showed in black on the dark background and was hard to read. It now uses the theme's text colour in both light and dark mode. Thanks to @MarcelL94 (#13).
+
+- **Photo scenery missing on the first flight after installing.** If you ticked **Launch OrthoStreamXP now** at the end of the installer and then pressed **Start XP**, X-Plane started without the photo scenery and removed the OrthoStream packages from its scenery list. Restarting OrthoStreamXP made it work. **Start XP** now starts X-Plane the same way a double-click in Windows does, so the first flight shows the photo scenery too. Your **X-Plane start options** are still passed to X-Plane as before. Thanks to @MarcelL94 for reporting it (#14).
diff --git a/src/OrthoStreamXP/Gui/App.xaml.cs b/src/OrthoStreamXP/Gui/App.xaml.cs
index c4e43ba..858f194 100644
--- a/src/OrthoStreamXP/Gui/App.xaml.cs
+++ b/src/OrthoStreamXP/Gui/App.xaml.cs
@@ -25,6 +25,7 @@ protected override void OnStartup(StartupEventArgs e)
Log.Configure(LogOutput.None, null);
DispatcherUnhandledException += OnUnhandledException;
_main = new MainViewModel();
+ _main.Preferences.Theme.Apply();
var window = new MainWindow(_main);
MainWindow = window;
window.Show();
diff --git a/src/OrthoStreamXP/Gui/AppTheme.cs b/src/OrthoStreamXP/Gui/AppTheme.cs
new file mode 100644
index 0000000..42feb26
--- /dev/null
+++ b/src/OrthoStreamXP/Gui/AppTheme.cs
@@ -0,0 +1,71 @@
+using System.Windows;
+using Microsoft.Win32;
+
+namespace OrthoStreamXP.Gui;
+
+/// The window's colours: the Windows theme (follows Windows), or always light or dark.
+internal enum AppTheme
+{
+ System,
+ Light,
+ Dark,
+}
+
+/// The sidebar's theme button: what it shows for a theme, and the theme a click switches to.
+internal sealed record ThemeChoice(string Label, string Glyph, AppTheme Theme)
+{
+ public static ThemeChoice Windows { get; } = new("Windows theme", "", AppTheme.System);
+ public static ThemeChoice Light { get; } = new("Light theme", "", AppTheme.Light);
+ public static ThemeChoice Dark { get; } = new("Dark theme", "", AppTheme.Dark);
+
+ public static ThemeChoice Of(AppTheme theme) => theme switch
+ {
+ AppTheme.Light => Light,
+ AppTheme.Dark => Dark,
+ _ => Windows,
+ };
+
+ ///
+ /// The Windows theme (follows Windows), then the other look, then Windows' look kept fixed, then the Windows theme again:
+ /// the first click always changes the colours.
+ ///
+ public ThemeChoice Next(Func windowsUsesLight)
+ {
+ ThemeChoice same = windowsUsesLight() ? Light : Dark;
+ ThemeChoice other = same == Light ? Dark : Light;
+ if (this == Windows) return other;
+ return this == other ? same : Windows;
+ }
+}
+
+internal static class AppThemeExtensions
+{
+#pragma warning disable WPF0001 // WPF's Fluent theme is marked experimental.
+ /// The WPF Fluent theme mode for the choice.
+ public static ThemeMode ToThemeMode(this AppTheme theme) => theme switch
+ {
+ AppTheme.Light => ThemeMode.Light,
+ AppTheme.Dark => ThemeMode.Dark,
+ _ => ThemeMode.System,
+ };
+
+ /// Switches the running application to the theme; the window's DynamicResource brushes follow.
+ public static void Apply(this AppTheme theme)
+ {
+ if (Application.Current is { } app) app.ThemeMode = theme.ToThemeMode();
+ }
+#pragma warning restore WPF0001
+}
+
+/// Whether Windows shows apps light or dark (Settings > Personalisation > Colours).
+internal static class WindowsTheme
+{
+ private const string Personalize = @"Software\Microsoft\Windows\CurrentVersion\Themes\Personalize";
+
+ /// True for light apps, also when Windows does not say (older versions default to light).
+ public static bool AppsUseLight()
+ {
+ using RegistryKey? key = Registry.CurrentUser.OpenSubKey(Personalize);
+ return key?.GetValue("AppsUseLightTheme") is not int value || value != 0;
+ }
+}
diff --git a/src/OrthoStreamXP/Gui/MainWindow.xaml b/src/OrthoStreamXP/Gui/MainWindow.xaml
index 419800c..d29c9fc 100644
--- a/src/OrthoStreamXP/Gui/MainWindow.xaml
+++ b/src/OrthoStreamXP/Gui/MainWindow.xaml
@@ -66,6 +66,16 @@
+
+
+
diff --git a/src/OrthoStreamXP/Gui/Theme.xaml b/src/OrthoStreamXP/Gui/Theme.xaml
index 876aee5..ae7db94 100644
--- a/src/OrthoStreamXP/Gui/Theme.xaml
+++ b/src/OrthoStreamXP/Gui/Theme.xaml
@@ -8,6 +8,11 @@
+
+