Repository: microsoft/terminal (language: cpp)

Issue:
SettingsModelLocalTests failures are on the rise
### Windows Terminal version

Commit 1ce22a87e6fc204b5fd98642723aa0a51a503749

### Windows build number

10.0.19044.1889

### Other Software

_No response_

### Steps to reproduce

!. Check out a recent version of the project.
2. Build it.
3. Run the unit tests.

### Expected Behavior

All tests should pass.

### Actual Behavior

A number of `SettingsModelLocalTests` are failing:

    SettingsModelLocalTests::DeserializationTests::TestCloseOnExitParsing [Failed]
    SettingsModelLocalTests::SerializationTests::Profile [Failed]
    SettingsModelLocalTests::SerializationTests::Actions [Failed]
    SettingsModelLocalTests::SerializationTests::LegacyFontSettings [Failed]

If I remember correctly, the first one has been around for a while now. I'm afraid I've just been ignoring it and hoping somebody else would notice. The others I think are fairly recent. Although I may be misremembering which are old and which are new.


Discussion / hints:
Looking at the test logs for those last three, it seems the failures are a result of a change in serialization of the font size from int to float (I suspect PR #14013).

The older one I suspect is the result of the new `Automatic` mode for `CloseOnExit` (PR  #13560).
I keep forgetting that we don't run them in the CI... 😞

Fix patch:
diff --git a/doc/cascadia/profiles.schema.json b/doc/cascadia/profiles.schema.json
index 3cef5d1946e..e20f8545681 100644
--- a/doc/cascadia/profiles.schema.json
+++ b/doc/cascadia/profiles.schema.json
@@ -82,7 +82,14 @@
       "properties": {
         "colorScheme": {
           "description": "The name of a color scheme to use when unfocused.",
-          "type": "string"
+          "oneOf": [
+            {
+              "$ref": "#/$defs/SchemePair"
+            },
+            {
+              "type": "string"
+            }
+          ]
         },
         "foreground": {
           "$ref": "#/$defs/Color",
@@ -233,6 +240,21 @@
       },
       "type": "object"
     },
+    "SchemePair": {
+      "description": "Contains both a light and dark color scheme for the Terminal to use, depending on the theme of the application.",
+      "properties": {
+        "light": {
+          "default": "Campbell",
+          "description": "Name of the scheme to use when the app is using light theme",
+          "type": "string"
+        },
+        "dark": {
+          "default": "Campbell",
+          "description": "Name of the scheme to use when the app is using dark theme",
+          "type": "string"
+        },
+      }
+    },
     "FontConfig": {
       "properties": {
         "face": {
@@ -2170,7 +2192,14 @@
         "colorScheme": {
           "default": "Campbell",
           "description": "Name of the terminal color scheme to use. Color schemes are defined under \"schemes\".",
-          "type": "string"
+          "oneOf": [
+            {
+              "$ref": "#/$defs/SchemePair"
+            },
+            {
+              "type": "string"
+            }
+          ]
         },
         "commandline": {
           "description": "Executable used in the profile.",
diff --git a/src/cascadia/LocalTests_SettingsModel/ColorSchemeTests.cpp b/src/cascadia/LocalTests_SettingsModel/ColorSchemeTests.cpp
index 721e426761b..b266064977a 100644
--- a/src/cascadia/LocalTests_SettingsModel/ColorSchemeTests.cpp
+++ b/src/cascadia/LocalTests_SettingsModel/ColorSchemeTests.cpp
@@ -217,6 +217,30 @@ namespace SettingsModelLocalTests
                     {
                         "name": "Different reference",
                         "colorScheme": "One Half Dark"
+                    },
+                    {
+                        "name": "rename neither",
+                        "colorScheme":
+                        {
+                            "dark": "One Half Dark",
+                            "light": "One Half Light"
+                        }
+                    },
+                    {
+                        "name": "rename only light",
+                        "colorScheme":
+                        {
+                            "dark": "One Half Dark",
+                            "light": "Campbell"
+                        }
+                    },
+                    {
+                        "name": "rename only dark",
+                        "colorScheme":
+                        {
+                            "dark": "Campbell",
+                            "light": "One Half Light"
+                        }
                     }
                 ]
             },
@@ -289,6 +313,28 @@ namespace SettingsModelLocalTests
                     "selectionBackground": "#FFFFFF",
                     "white": "#DCDFE4",
                     "yellow": "#E5C07B"
+                },
+                {
+                    "name": "One Half Light",
+                    "foreground": "#383A42",
+                    "background": "#FAFAFA",
+                    "cursorColor": "#4F525D",
+                    "black": "#383A42",
+                    "red": "#E45649",
+                    "green": "#50A14F",
+                    "yellow": "#C18301",
+                    "blue": "#0184BC",
+                    "purple": "#A626A4",
+                    "cyan": "#0997B3",
+                    "white": "#FAFAFA",
+                    "brightBlack": "#4F525D",
+                    "brightRed": "#DF6C75",
+                    "brightGreen": "#98C379",
+                    "brightYellow": "#E4C07A",
+                    "brightBlue": "#61AFEF",
+                    "brightPurple": "#C577DD",
+                    "brightCyan": "#56B5C1",
+                    "brightWhite": "#FFFFFF"
                 }
             ]
         })json" };
@@ -296,31 +342,63 @@ namespace SettingsModelLocalTests
         const auto settings{ winrt::make_self<CascadiaSettings>(settingsString) };
 
         const auto newName{ L"Campbell (renamed)" };
+
         settings->UpdateColorSchemeReferences(L"Campbell", newName);
 
-        VERIFY_ARE_EQUAL(newName, settings->ProfileDefaults().DefaultAppearance().ColorSchemeName());
-        VERIFY_IS_TRUE(settings->ProfileDefaults().DefaultAppearance().HasColorSchemeName());
+        VERIFY_ARE_EQUAL(newName, settings->ProfileDefaults().DefaultAppearance().DarkColorSchemeName());
+        VERIFY_ARE_EQUAL(newName, settings->ProfileDefaults().DefaultAppearance().LightColorSchemeName());
+        VERIFY_IS_TRUE(settings->ProfileDefaults().DefaultAppearance().HasDarkColorSchemeName());
+        VERIFY_IS_TRUE(settings->ProfileDefaults().DefaultAppearance().HasLightColorSchemeName());
 
         const auto& profiles{ settings->AllProfiles() };
         {
             const auto& prof{ profiles.GetAt(0) };
-            VERIFY_ARE_EQUAL(newName, prof.DefaultAppearance().ColorSchemeName());
-            VERIFY_IS_TRUE(prof.DefaultAppearance().HasColorSchemeName());
+            VERIFY_ARE_EQUAL(newName, prof.DefaultAppearance().DarkColorSchemeName());
+            VERIFY_IS_TRUE(prof.DefaultAppearance().HasDarkColorSchemeName());
+            VERIFY_ARE_EQUAL(newName, prof.DefaultAppearance().LightColorSchemeName());
+            VERIFY_IS_TRUE(prof.DefaultAppearance().HasLightColorSchemeName());
         }
         {
             const auto& prof{ profiles.GetAt(1) };
-            VERIFY_ARE_EQUAL(newName, prof.DefaultAppearance().ColorSchemeName());
-            VERIFY_IS_TRUE(prof.DefaultAppearance().HasColorSchemeName());
+            VERIFY_ARE_EQUAL(newName, prof.DefaultAppearance().DarkColorSchemeName());
+            VERIFY_IS_TRUE(prof.DefaultAppearance().HasDarkColorSchemeName());
+            VERIFY_ARE_EQUAL(newName, prof.DefaultAppearance().LightColorSchemeName());
+            VERIFY_IS_TRUE(prof.DefaultAppearance().HasLightColorSchemeName());
         }
         {
             const auto& prof{ profiles.GetAt(2) };
-            VERIFY_ARE_EQUAL(newName, prof.DefaultAppearance().ColorSchemeName());
-            VERIFY_IS_FALSE(prof.DefaultAppearance().HasColorSchemeName());
+            VERIFY_ARE_EQUAL(newName, prof.DefaultAppearance().DarkColorSchemeName());
+            VERIFY_IS_FALSE(prof.DefaultAppearance().HasDarkColorSchemeName());
+            VERIFY_ARE_EQUAL(newName, prof.DefaultAppearance().LightColorSchemeName());
+            VERIFY_IS_FALSE(prof.DefaultAppearance().HasLightColorSchemeName());
         }
         {
             const auto& prof{ profiles.GetAt(3) };
-            VERIFY_ARE_EQUAL(L"One Half Dark", prof.DefaultAppearance().ColorSchemeName());
-            VERIFY_IS_TRUE(prof.DefaultAppearance().HasColorSchemeName());
+            VERIFY_ARE_EQUAL(L"One Half Dark", prof.DefaultAppearance().DarkColorSchemeName());
+            VERIFY_IS_TRUE(prof.DefaultAppearance().HasDarkColorSchemeName());
+            VERIFY_ARE_EQUAL(L"One Half Dark", prof.DefaultAppearance().LightColorSchemeName());
+            VERIFY_IS_TRUE(prof.DefaultAppearance().HasLightColorSchemeName());
+        }
+        {
+            const auto& prof{ profiles.GetAt(4) };
+            VERIFY_ARE_EQUAL(L"One Half Dark", prof.DefaultAppearance().DarkColorSchemeName());
+            VERIFY_ARE_EQUAL(L"One Half Light", prof.DefaultAppearance().LightColorSchemeName());
+            VERIFY_IS_TRUE(prof.DefaultAppearance().HasDarkColorSchemeName());
+            VERIFY_IS_TRUE(prof.DefaultAppearance().HasLightColorSchemeName());
+        }
+        {
+            const auto& prof{ profiles.GetAt(5) };
+            VERIFY_ARE_EQUAL(L"One Half Dark", prof.DefaultAppearance().DarkColorSchemeName());
+            VERIFY_ARE_EQUAL(newName, prof.DefaultAppearance().LightColorSchemeName());
+            VERIFY_IS_TRUE(prof.DefaultAppearance().HasDarkColorSchemeName());
+            VERIFY_IS_TRUE(prof.DefaultAppearance().HasLightColorSchemeName());
+        }
+        {
+            const auto& prof{ profiles.GetAt(6) };
+            VERIFY_ARE_EQUAL(newName, prof.DefaultAppearance().DarkColorSchemeName());
+            VERIFY_ARE_EQUAL(L"One Half Light", prof.DefaultAppearance().LightColorSchemeName());
+            VERIFY_IS_TRUE(prof.DefaultAppearance().HasDarkColorSchemeName());
+            VERIFY_IS_TRUE(prof.DefaultAppearance().HasLightColorSchemeName());
         }
     }
 }
diff --git a/src/cascadia/LocalTests_SettingsModel/DeserializationTests.cpp b/src/cascadia/LocalTests_SettingsModel/DeserializationTests.cpp
index 7008feed586..b2eaed29014 100644
--- a/src/cascadia/LocalTests_SettingsModel/DeserializationTests.cpp
+++ b/src/cascadia/LocalTests_SettingsModel/DeserializationTests.cpp
@@ -744,7 +744,8 @@ namespace SettingsModelLocalTests
         VERIFY_ARE_EQUAL(3u, settings->AllProfiles().Size());
         for (const auto& profile : settings->AllProfiles())
         {
-            VERIFY_ARE_EQUAL(L"Campbell", profile.DefaultAppearance().ColorSchemeName());
+            VERIFY_ARE_EQUAL(L"Campbell", profile.DefaultAppearance().DarkColorSchemeName());
+            VERIFY_ARE_EQUAL(L"Campbell", profile.DefaultAppearance().LightColorSchemeName());
         }
     }
 
@@ -959,6 +960,10 @@ namespace SettingsModelLocalTests
                 },
                 {
                     "name": "profile3",
+                    "closeOnExit": "automatic"
+                },
+                {
+                    "name": "profile4",
                     "closeOnExit": null
                 }
             ]
@@ -968,9 +973,10 @@ namespace SettingsModelLocalTests
         VERIFY_ARE_EQUAL(CloseOnExitMode::Graceful, settings->AllProfiles().GetAt(0).CloseOnExit());
         VERIFY_ARE_EQUAL(CloseOnExitMode::Always, settings->AllProfiles().GetAt(1).CloseOnExit());
         VERIFY_ARE_EQUAL(CloseOnExitMode::Never, settings->AllProfiles().GetAt(2).CloseOnExit());
+        VERIFY_ARE_EQUAL(CloseOnExitMode::Automatic, settings->AllProfiles().GetAt(3).CloseOnExit());
 
-        // Unknown modes parse as "Graceful"
-        VERIFY_ARE_EQUAL(CloseOnExitMode::Graceful, settings->AllProfiles().GetAt(3).CloseOnExit());
+        // Unknown modes parse as "Automatic"
+        VERIFY_ARE_EQUAL(CloseOnExitMode::Automatic, settings->AllProfiles().GetAt(4).CloseOnExit());
     }
 
     void DeserializationTests::TestCloseOnExitCompatibilityShim()
diff --git a/src/cascadia/LocalTests_SettingsModel/SerializationTests.cpp b/src/cascadia/LocalTests_SettingsModel/SerializationTests.cpp
index f0a3ed3d02a..4f9fb528f99 100644
--- a/src/cascadia/LocalTests_SettingsModel/SerializationTests.cpp
+++ b/src/cascadia/LocalTests_SettingsModel/SerializationTests.cpp
@@ -134,7 +134,7 @@ namespace SettingsModelLocalTests
 
                 "font": {
                     "face": "Cascadia Mono",
-                    "size": 12,
+                    "size": 12.0,
                     "weight": "normal"
                 },
                 "padding": "8, 8, 8, 8",
@@ -250,8 +250,8 @@ namespace SettingsModelLocalTests
 
         // complex command with key chords
         static constexpr std::string_view actionsString4A{ R"([
-                                                { "command": { "action": "adjustFontSize", "delta": 1 }, "keys": "ctrl+c" },
-                                                { "command": { "action": "adjustFontSize", "delta": 1 }, "keys": "ctrl+d" }
+                                                { "command": { "action": "adjustFontSize", "delta": 1.0 }, "keys": "ctrl+c" },
+                                                { "command": { "action": "adjustFontSize", "delta": 1.0 }, "keys": "ctrl+d" }
                                             ])" };
         // GH#13323 - these can be fragile. In the past, the order these get
         // re-serialized as has been not entirely stable. We don't really care
@@ -260,7 +260,7 @@ namespace SettingsModelLocalTests
         // itself. Feel free to change as needed.
         static constexpr std::string_view actionsString4B{ R"([
                                                 { "command": { "action": "findMatch", "direction": "prev" }, "keys": "ctrl+shift+r" },
-                                                { "command": { "action": "adjustFontSize", "delta": 1 }, "keys": "ctrl+d" }
+                                                { "command": { "action": "adjustFontSize", "delta": 1.0 }, "keys": "ctrl+d" }
                                             ])" };
 
         // command with name and icon and multiple key chords
@@ -284,8 +284,8 @@ namespace SettingsModelLocalTests
                                                 {
                                                     "name": "Change font size...",
                                                     "commands": [
-                                                        { "command": { "action": "adjustFontSize", "delta": 1 } },
-                                                        { "command": { "action": "adjustFontSize", "delta": -1 } },
+                                                        { "command": { "action": "adjustFontSize", "delta": 1.0 } },
+                                                        { "command": { "action": "adjustFontSize", "delta": -1.0 } },
                                                         { "command": "resetFontSize" },
                                                     ]
                                                 }
@@ -478,7 +478,7 @@ namespace SettingsModelLocalTests
                 "name": "Profile with legacy font settings",
 
                 "fontFace": "Cascadia Mono",
-                "fontSize": 12,
+                "fontSize": 12.0,
                 "fontWeight": "normal"
             })" };
 
@@ -488,7 +488,7 @@ namespace SettingsModelLocalTests
 
                 "font": {
                     "face": "Cascadia Mono",
-                    "size": 12,
+                    "size": 12.0,
                     "weight": "normal"
                 }
             })" };
diff --git a/src/cascadia/LocalTests_SettingsModel/TerminalSettingsTests.cpp b/src/cascadia/LocalTests_SettingsModel/TerminalSettingsTests.cpp
index 8680e7f9cd2..0ae0bcc164e 100644
--- a/src/cascadia/LocalTests_SettingsModel/TerminalSettingsTests.cpp
+++ b/src/cascadia/LocalTests_SettingsModel/TerminalSettingsTests.cpp
@@ -779,21 +779,22 @@ namespace SettingsModelLocalTests
         VERIFY_ARE_EQUAL(6u, settings->ActiveProfiles().Size());
         VERIFY_ARE_EQUAL(2u, settings->GlobalSettings().ColorSchemes().Size());
 
-        auto createTerminalSettings = [&](const auto& profile, const auto& schemes) {
+        auto createTerminalSettings = [&](const auto& profile, const auto& schemes, const auto& Theme) {
             auto terminalSettings{ winrt::make_self<implementation::TerminalSettings>() };
             terminalSettings->_ApplyProfileSettings(profile);
-            terminalSettings->_ApplyAppearanceSettings(profile.DefaultAppearance(), schemes);
+            terminalSettings->_ApplyAppearanceSettings(profile.DefaultAppearance(), schemes, Theme);
             return terminalSettings;
         };
 
         const auto activeProfiles = settings->ActiveProfiles();
         const auto colorSchemes = settings->GlobalSettings().ColorSchemes();
-        const auto terminalSettings0 = createTerminalSettings(activeProfiles.GetAt(0), colorSchemes);
-        const auto terminalSettings1 = createTerminalSettings(activeProfiles.GetAt(1), colorSchemes);
-        const auto terminalSettings2 = createTerminalSettings(activeProfiles.GetAt(2), colorSchemes);
-        const auto terminalSettings3 = createTerminalSettings(activeProfiles.GetAt(3), colorSchemes);
-        const auto terminalSettings4 = createTerminalSettings(activeProfiles.GetAt(4), colorSchemes);
-        const auto terminalSettings5 = createTerminalSettings(activeProfiles.GetAt(5), colorSchemes);
+        const auto currentTheme = settings->GlobalSettings().CurrentTheme();
+        const auto terminalSettings0 = createTerminalSettings(activeProfiles.GetAt(0), colorSchemes, currentTheme);
+        const auto terminalSettings1 = createTerminalSettings(activeProfiles.GetAt(1), colorSchemes, currentTheme);
+        const auto terminalSettings2 = createTerminalSettings(activeProfiles.GetAt(2), colorSchemes, currentTheme);
+        const auto terminalSettings3 = createTerminalSettings(activeProfiles.GetAt(3), colorSchemes, currentTheme);
+        const auto terminalSettings4 = createTerminalSettings(activeProfiles.GetAt(4), colorSchemes, currentTheme);
+        const auto terminalSettings5 = createTerminalSettings(activeProfiles.GetAt(5), colorSchemes, currentTheme);
 
         VERIFY_ARE_EQUAL(til::color(0x12, 0x34, 0x56), terminalSettings0->CursorColor()); // from color scheme
         VERIFY_ARE_EQUAL(DEFAULT_CURSOR_COLOR, terminalSettings1->CursorColor()); // default
diff --git a/src/cascadia/LocalTests_SettingsModel/pch.h b/src/cascadia/LocalTests_SettingsModel/pch.h
index b018bdaa4a6..b2e15b5a7b1 100644
--- a/src/cascadia/LocalTests_SettingsModel/pch.h
+++ b/src/cascadia/LocalTests_SettingsModel/pch.h
@@ -44,6 +44,7 @@ Author(s):
 #include <Windows.Graphics.Imaging.Interop.h>
 #include <winrt/windows.ui.core.h>
 #include <winrt/Windows.ui.input.h>
+#include <winrt/Windows.UI.ViewManagement.h>
 #include <winrt/Windows.UI.Xaml.Controls.h>
 #include <winrt/Windows.UI.Xaml.Controls.Primitives.h>
 #include <winrt/Windows.ui.xaml.media.h>
diff --git a/src/cascadia/TerminalApp/App.cpp b/src/cascadia/TerminalApp/App.cpp
index c143f2eceda..4d7e5f93763 100644
--- a/src/cascadia/TerminalApp/App.cpp
+++ b/src/cascadia/TerminalApp/App.cpp
@@ -54,7 +54,7 @@ namespace winrt::TerminalApp::implementation
             {
                 auto logic = Logic();
                 logic.RunAsUwp(); // Must set UWP status first, settings might change based on it.
-                logic.LoadSettings();
+                logic.ReloadSettings();
                 logic.Create();
 
                 auto page = logic.GetRoot().as<TerminalPage>();
diff --git a/src/cascadia/TerminalApp/AppLogic.cpp b/src/cascadia/TerminalApp/AppLogic.cpp
index 7062bfd73a9..040c39d29d1 100644
--- a/src/cascadia/TerminalApp/AppLogic.cpp
+++ b/src/cascadia/TerminalApp/AppLogic.cpp
@@ -191,7 +191,7 @@ namespace winrt::TerminalApp::implementation
         _reloadSettings = std::make_shared<ThrottledFuncTrailing<>>(winrt::Windows::System::DispatcherQueue::GetForCurrentThread(), std::chrono::milliseconds(100), [weakSelf = get_weak()]() {
             if (auto self{ weakSelf.get() })
             {
-                self->_ReloadSettings();
+                self->ReloadSettings();
             }
         });
 
@@ -615,7 +615,7 @@ namespace winrt::TerminalApp::implementation
         if (!_loadedInitialSettings)
         {
             // Load settings if we haven't already
-            LoadSettings();
+            ReloadSettings();
         }
 
         winrt::Windows::Foundation::Size proposedSize{};
@@ -696,7 +696,7 @@ namespace winrt::TerminalApp::implementation
         if (!_loadedInitialSettings)
         {
             // Load settings if we haven't already
-            LoadSettings();
+            ReloadSettings();
         }
 
         // GH#4620/#5801 - If the user passed --maximized or --fullscreen on the
@@ -730,7 +730,7 @@ namespace winrt::TerminalApp::implementation
         if (!_loadedInitialSettings)
         {
             // Load settings if we haven't already
-            LoadSettings();
+            ReloadSettings();
         }
 
         auto initialPosition{ _settings.GlobalSettings().InitialPosition() };
@@ -760,7 +760,7 @@ namespace winrt::TerminalApp::implementation
         if (!_loadedInitialSettings)
         {
             // Load settings if we haven't already
-            LoadSettings();
+            ReloadSettings();
         }
         // If the position has been specified on the commandline, don't center on launch
         return _settings.GlobalSettings().CenterOnLaunch() && !_appArgs.GetPosition().has_value();
@@ -776,7 +776,7 @@ namespace winrt::TerminalApp::implementation
         if (!_loadedInitialSettings)
         {
             // Load settings if we haven't already
-            LoadSettings();
+            ReloadSettings();
         }
 
         return _settings.GlobalSettings().ShowTabsInTitlebar();
@@ -787,7 +787,7 @@ namespace winrt::TerminalApp::implementation
         if (!_loadedInitialSettings)
         {
             // Load settings if we haven't already
-            LoadSettings();
+            ReloadSettings();
         }
 
         return _settings.GlobalSettings().AlwaysOnTop();
@@ -867,36 +867,6 @@ namespace winrt::TerminalApp::implementation
         return hr;
     }
 
-    // Method Description:
-    // - Initialized our settings. See CascadiaSettings for more details.
-    //      Additionally hooks up our callbacks for keybinding events to the
-    //      keybindings object.
-    // NOTE: This must be called from a MTA if we're running as a packaged
-    //      application. The Windows.Storage APIs require a MTA. If this isn't
-    //      happening during startup, it'll need to happen on a background thread.
-    void AppLogic::LoadSettings()
-    {
-        // Attempt to load the settings.
-        // If it fails,
-        //  - use Default settings,
-        //  - don't persist them (LoadAll won't save them in this case).
-        //  - _settingsLoadedResult will be set to an error, indicating that
-        //    we should display the loading error.
-        //    * We can't display the error now, because we might not have a
-        //      UI yet. We'll display the error in _OnLoaded.
-        _settingsLoadedResult = _TryLoadSettings();
-
-        if (FAILED(_settingsLoadedResult))
-        {
-            _settings = CascadiaSettings::LoadDefaults();
-        }
-
-        _loadedInitialSettings = true;
-
-        // Register for directory change notification.
-        _RegisterSettingsChange();
-    }
-
     // Call this function after loading your _settings.
     // It handles any CPU intensive settings updates (like updating the Jumplist)
     // which should thus only occur if the settings file actually changed.
@@ -920,7 +890,7 @@ namespace winrt::TerminalApp::implementation
 
     // Method Description:
     // - Registers for changes to the settings folder and upon a updated settings
-    //      profile calls _ReloadSettings().
+    //      profile calls ReloadSettings().
     // Arguments:
     // - <none>
     // Return Value:
@@ -1055,7 +1025,14 @@ namespace winrt::TerminalApp::implementation
 
     // Method Description:
     // - Reloads the settings from the settings.json file.
-    void AppLogic::_ReloadSettings()
+    // - When this is called the first time, this initializes our settings. See
+    //   CascadiaSettings for more details. Additionally hooks up our callbacks
+    //   for keybinding events to the keybindings object.
+    //   - NOTE: when called initially, this must be called from a MTA if we're
+    //     running as a packaged application. The Windows.Storage APIs require a
+    //     MTA. If this isn't happening during startup, it'll need to happen on
+    //     a background thread.
+    void AppLogic::ReloadSettings()
     {
         // Attempt to load our settings.
         // If it fails,
@@ -1064,11 +1041,28 @@ namespace winrt::TerminalApp::implementation
         //  - display a loading error
         _settingsLoadedResult = _TryLoadSettings();
 
+        const auto initialLoad = !_loadedInitialSettings;
+        _loadedInitialSettings = true;
+
         if (FAILED(_settingsLoadedResult))
         {
-            const winrt::hstring titleKey = USES_RESOURCE(L"ReloadJsonParseErrorTitle");
-            const winrt::hstring textKey = USES_RESOURCE(L"ReloadJsonParseErrorText");
-            _ShowLoadErrorsDialog(titleKey, textKey, _settingsLoadedResult);
+            if (initialLoad)
+            {
+                _settings = CascadiaSettings::LoadDefaults();
+            }
+            else
+            {
+                const winrt::hstring titleKey = USES_RESOURCE(L"ReloadJsonParseErrorTitle");
+                const winrt::hstring textKey = USES_RESOURCE(L"ReloadJsonParseErrorText");
+                _ShowLoadErrorsDialog(titleKey, textKey, _settingsLoadedResult);
+                return;
+            }
+        }
+
+        if (initialLoad)
+        {
+            // Register for directory change notification.
+            _RegisterSettingsChange();
             return;
         }
 
@@ -1375,7 +1369,7 @@ namespace winrt::TerminalApp::implementation
         if (!_loadedInitialSettings)
         {
             // Load settings if we haven't already
-            LoadSettings();
+            ReloadSettings();
         }
 
         return AppLogic::_doFindTargetWindow(args, _settings.GlobalSettings().WindowingBehavior());
@@ -1532,7 +1526,7 @@ namespace winrt::TerminalApp::implementation
         if (!_loadedInitialSettings)
         {
             // Load settings if we haven't already
-            LoadSettings();
+            ReloadSettings();
         }
 
         return _settings.GlobalSettings().AutoHideWindow();
@@ -1553,7 +1547,7 @@ namespace winrt::TerminalApp::implementation
         if (!_loadedInitialSettings)
         {
             // Load settings if we haven't already
-            LoadSettings();
+            ReloadSettings();
         }
 
         return _root != nullptr ? _root->ShouldImmediatelyHandoffToElevated(_settings) : false;
@@ -1666,7 +1660,7 @@ namespace winrt::TerminalApp::implementation
         if (!_loadedInitialSettings)
         {
             // Load settings if we haven't already
-            LoadSettings();
+            ReloadSettings();
         }
 
         return _settings.GlobalSettings().MinimizeToNotificationArea();
@@ -1677,7 +1671,7 @@ namespace winrt::TerminalApp::implementation
         if (!_loadedInitialSettings)
         {
             // Load settings if we haven't already
-            LoadSettings();
+            ReloadSettings();
         }
 
         return _settings.GlobalSettings().AlwaysShowNotificationIcon();
@@ -1693,7 +1687,7 @@ namespace winrt::TerminalApp::implementation
         if (!_loadedInitialSettings)
         {
             // Load settings if we haven't already
-            LoadSettings();
+            ReloadSettings();
         }
         return _settings.GlobalSettings().CurrentTheme();
     }
diff --git a/src/cascadia/TerminalApp/AppLogic.h b/src/cascadia/TerminalApp/AppLogic.h
index f4abe8254f2..5534979b973 100644
--- a/src/cascadia/TerminalApp/AppLogic.h
+++ b/src/cascadia/TerminalApp/AppLogic.h
@@ -62,7 +62,8 @@ namespace winrt::TerminalApp::implementation
         bool IsUwp() const noexcept;
         void RunAsUwp();
         bool IsElevated() const noexcept;
-        void LoadSettings();
+        void ReloadSettings();
+
         [[nodiscard]] Microsoft::Terminal::Settings::Model::CascadiaSettings GetSettings() const noexcept;
 
         void Quit();
@@ -195,7 +196,6 @@ namespace winrt::TerminalApp::implementation
         void _ProcessLazySettingsChanges();
         void _RegisterSettingsChange();
         fire_and_forget _DispatchReloadSettings();
-        void _ReloadSettings();
         void _OpenSettingsUI();
 
         bool _hasCommandLineArguments{ false };
diff --git a/src/cascadia/TerminalApp/AppLogic.idl b/src/cascadia/TerminalApp/AppLogic.idl
index 0f77af0c8cd..b7a92ea1103 100644
--- a/src/cascadia/TerminalApp/AppLogic.idl
+++ b/src/cascadia/TerminalApp/AppLogic.idl
@@ -59,7 +59,7 @@ namespace TerminalApp
 
         void Quit();
 
-        void LoadSettings();
+        void ReloadSettings();
         Windows.UI.Xaml.UIElement GetRoot();
 
         void SetInboundListener();
diff --git a/src/cascadia/TerminalSettingsEditor/Appearances.cpp b/src/cascadia/TerminalSettingsEditor/Appearances.cpp
index 4b4b5a5a361..ef77b5f6f73 100644
--- a/src/cascadia/TerminalSettingsEditor/Appearances.cpp
+++ b/src/cascadia/TerminalSettingsEditor/Appearances.cpp
@@ -243,7 +243,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
                     _PropertyChangedHandlers(*this, PropertyChangedEventArgs{ L"CurrentCursorShape" });
                     _PropertyChangedHandlers(*this, PropertyChangedEventArgs{ L"IsVintageCursor" });
                 }
-                else if (settingName == L"ColorSchemeName")
+                else if (settingName == L"DarkColorSchemeName" || settingName == L"LightColorSchemeName")
                 {
                     _PropertyChangedHandlers(*this, PropertyChangedEventArgs{ L"CurrentColorScheme" });
                 }
@@ -355,7 +355,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
 
     ColorScheme Appearances::CurrentColorScheme()
     {
-        const auto schemeName{ Appearance().ColorSchemeName() };
+        const auto schemeName{ Appearance().DarkColorSchemeName() };
         if (const auto scheme{ Appearance().Schemes().TryLookup(schemeName) })
         {
             return scheme;
@@ -370,7 +370,8 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
 
     void Appearances::CurrentColorScheme(const ColorScheme& val)
     {
-        Appearance().ColorSchemeName(val.Name());
+        Appearance().DarkColorSchemeName(val.Name());
+        Appearance().LightColorSchemeName(val.Name());
     }
 
     bool Appearances::IsVintageCursor() const
diff --git a/src/cascadia/TerminalSettingsEditor/Appearances.h b/src/cascadia/TerminalSettingsEditor/Appearances.h
index 207a1f8846a..2f67b03a9b2 100644
--- a/src/cascadia/TerminalSettingsEditor/Appearances.h
+++ b/src/cascadia/TerminalSettingsEditor/Appearances.h
@@ -87,7 +87,8 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
         OBSERVABLE_PROJECTED_SETTING(_appearance, RetroTerminalEffect);
         OBSERVABLE_PROJECTED_SETTING(_appearance, CursorShape);
         OBSERVABLE_PROJECTED_SETTING(_appearance, CursorHeight);
-        OBSERVABLE_PROJECTED_SETTING(_appearance, ColorSchemeName);
+        OBSERVABLE_PROJECTED_SETTING(_appearance, DarkColorSchemeName);
+        OBSERVABLE_PROJECTED_SETTING(_appearance, LightColorSchemeName);
         OBSERVABLE_PROJECTED_SETTING(_appearance, BackgroundImagePath);
         OBSERVABLE_PROJECTED_SETTING(_appearance, BackgroundImageOpacity);
         OBSERVABLE_PROJECTED_SETTING(_appearance, BackgroundImageStretchMode);
diff --git a/src/cascadia/TerminalSettingsEditor/Appearances.idl b/src/cascadia/TerminalSettingsEditor/Appearances.idl
index 303e94b0d4a..e31f7e41703 100644
--- a/src/cascadia/TerminalSettingsEditor/Appearances.idl
+++ b/src/cascadia/TerminalSettingsEditor/Appearances.idl
@@ -37,7 +37,8 @@ namespace Microsoft.Terminal.Settings.Editor
         OBSERVABLE_PROJECTED_APPEARANCE_SETTING(Single, FontSize);
         OBSERVABLE_PROJECTED_APPEARANCE_SETTING(Windows.UI.Text.FontWeight, FontWeight);
 
-        OBSERVABLE_PROJECTED_APPEARANCE_SETTING(String, ColorSchemeName);
+        OBSERVABLE_PROJECTED_APPEARANCE_SETTING(String, DarkColorSchemeName);
+        OBSERVABLE_PROJECTED_APPEARANCE_SETTING(String, LightColorSchemeName);
         OBSERVABLE_PROJECTED_APPEARANCE_SETTING(Boolean, RetroTerminalEffect);
         OBSERVABLE_PROJECTED_APPEARANCE_SETTING(Microsoft.Terminal.Core.CursorStyle, CursorShape);
         OBSERVABLE_PROJECTED_APPEARANCE_SETTING(UInt32, CursorHeight);
diff --git a/src/cascadia/TerminalSettingsEditor/Appearances.xaml b/src/cascadia/TerminalSettingsEditor/Appearances.xaml
index 8a6a5d45aa9..9bed48c7ef5 100644
--- a/src/cascadia/TerminalSettingsEditor/Appearances.xaml
+++ b/src/cascadia/TerminalSettingsEditor/Appearances.xaml
@@ -39,10 +39,11 @@
                        Style="{StaticResource TextBlockSubHeaderStyle}" />
 
             <!--  Color Scheme  -->
+            <!--  This currently only display the Dark color scheme, even if the user has a pair of schemes set.  -->
             <local:SettingContainer x:Uid="Profile_ColorScheme"
-                                    ClearSettingValue="{x:Bind Appearance.ClearColorSchemeName}"
-                                    HasSettingValue="{x:Bind Appearance.HasColorSchemeName, Mode=OneWay}"
-                                    SettingOverrideSource="{x:Bind Appearance.ColorSchemeNameOverrideSource, Mode=OneWay}">
+                                    ClearSettingValue="{x:Bind Appearance.ClearDarkColorSchemeName}"
+                                    HasSettingValue="{x:Bind Appearance.HasDarkColorSchemeName, Mode=OneWay}"
+                                    SettingOverrideSource="{x:Bind Appearance.DarkColorSchemeNameOverrideSource, Mode=OneWay}">
                 <ComboBox ItemsSource="{x:Bind ColorSchemeList, Mode=OneWay}"
                           SelectedItem="{x:Bind CurrentColorScheme, Mode=TwoWay}"
                           Style="{StaticResource ComboBoxSettingStyle}">
diff --git a/src/cascadia/TerminalSettingsEditor/ColorSchemeViewModel.cpp b/src/cascadia/TerminalSettingsEditor/ColorSchemeViewModel.cpp
index 62491f7418d..160f5a3839b 100644
--- a/src/cascadia/TerminalSettingsEditor/ColorSchemeViewModel.cpp
+++ b/src/cascadia/TerminalSettingsEditor/ColorSchemeViewModel.cpp
@@ -52,7 +52,9 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
 
     bool ColorSchemeViewModel::IsDefaultScheme()
     {
-        return _Name == _settings.ProfileDefaults().DefaultAppearance().ColorSchemeName();
+        const auto defaultAppearance = _settings.ProfileDefaults().DefaultAppearance();
+        return defaultAppearance.LightColorSchemeName() == defaultAppearance.DarkColorSchemeName() &&
+               _Name == defaultAppearance.LightColorSchemeName();
     }
 
     void ColorSchemeViewModel::RefreshIsDefault()
diff --git a/src/cascadia/TerminalSettingsEditor/ColorSchemesPageViewModel.cpp b/src/cascadia/TerminalSettingsEditor/ColorSchemesPageViewModel.cpp
index d5c1280f437..badc52b4ac3 100644
--- a/src/cascadia/TerminalSettingsEditor/ColorSchemesPageViewModel.cpp
+++ b/src/cascadia/TerminalSettingsEditor/ColorSchemesPageViewModel.cpp
@@ -189,7 +189,8 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
     {
         if (_CurrentScheme)
         {
-            _settings.ProfileDefaults().DefaultAppearance().ColorSchemeName(_CurrentScheme.Name());
+            _settings.ProfileDefaults().DefaultAppearance().LightColorSchemeName(_CurrentScheme.Name());
+            _settings.ProfileDefaults().DefaultAppearance().DarkColorSchemeName(_CurrentScheme.Name());
             for (const auto scheme : _AllColorSchemes)
             {
                 auto schemeImpl{ get_self<ColorSchemeViewModel>(scheme) };
diff --git a/src/cascadia/TerminalSettingsModel/AppearanceConfig.cpp b/src/cascadia/TerminalSettingsModel/AppearanceConfig.cpp
index d48763eca1c..90513b146ca 100644
--- a/src/cascadia/TerminalSettingsModel/AppearanceConfig.cpp
+++ b/src/cascadia/TerminalSettingsModel/AppearanceConfig.cpp
@@ -18,6 +18,7 @@ static constexpr std::string_view SelectionBackgroundKey{ "selectionBackground"
 static constexpr std::string_view CursorColorKey{ "cursorColor" };
 static constexpr std::string_view LegacyAcrylicTransparencyKey{ "acrylicOpacity" };
 static constexpr std::string_view OpacityKey{ "opacity" };
+static constexpr std::string_view ColorSchemeKey{ "colorScheme" };
 
 AppearanceConfig::AppearanceConfig(winrt::weak_ref<Profile> sourceProfile) :
     _sourceProfile(std::move(sourceProfile))
@@ -33,6 +34,9 @@ winrt::com_ptr<AppearanceConfig> AppearanceConfig::CopyAppearance(const Appearan
     appearance->_CursorColor = source->_CursorColor;
     appearance->_Opacity = source->_Opacity;
 
+    appearance->_DarkColorSchemeName = source->_DarkColorSchemeName;
+    appearance->_LightColorSchemeName = source->_LightColorSchemeName;
+
 #define APPEARANCE_SETTINGS_COPY(type, name, jsonKey, ...) \
     appearance->_##name = source->_##name;
     MTSM_APPEARANCE_SETTINGS(APPEARANCE_SETTINGS_COPY)
@@ -50,6 +54,19 @@ Json::Value AppearanceConfig::ToJson() const
     JsonUtils::SetValueForKey(json, SelectionBackgroundKey, _SelectionBackground);
     JsonUtils::SetValueForKey(json, CursorColorKey, _CursorColor);
     JsonUtils::SetValueForKey(json, OpacityKey, _Opacity, JsonUtils::OptionalConverter<double, IntAsFloatPercentConversionTrait>{});
+    if (HasDarkColorSchemeName() || HasLightColorSchemeName())
+    {
+        // check if the setting is coming from the UI, if so grab the ColorSchemeName until the settings UI is fixed.
+        if (_LightColorSchemeName != _DarkColorSchemeName)
+        {
+            JsonUtils::SetValueForKey(json["colorScheme"], "dark", _DarkColorSchemeName);
+            JsonUtils::SetValueForKey(json["colorScheme"], "light", _LightColorSchemeName);
+        }
+        else
+        {
+            JsonUtils::SetValueForKey(json, "colorScheme", _DarkColorSchemeName);
+        }
+    }
 
 #define APPEARANCE_SETTINGS_TO_JSON(type, name, jsonKey, ...) \
     JsonUtils::SetValueForKey(json, jsonKey, _##name);
@@ -79,6 +96,18 @@ void AppearanceConfig::LayerJson(const Json::Value& json)
 
     JsonUtils::GetValueForKey(json, LegacyAcrylicTransparencyKey, _Opacity);
     JsonUtils::GetValueForKey(json, OpacityKey, _Opacity, JsonUtils::OptionalConverter<double, IntAsFloatPercentConversionTrait>{});
+    if (json["colorScheme"].isString())
+    {
+        // to make the UI happy, set ColorSchemeName.
+        JsonUtils::GetValueForKey(json, ColorSchemeKey, _DarkColorSchemeName);
+        _LightColorSchemeName = _DarkColorSchemeName;
+    }
+    else if (json["colorScheme"].isObject())
+    {
+        // to make the UI happy, set ColorSchemeName to whatever the dark value is.
+        JsonUtils::GetValueForKey(json["colorScheme"], "dark", _DarkColorSchemeName);
+        JsonUtils::GetValueForKey(json["colorScheme"], "light", _LightColorSchemeName);
+    }
 
 #define APPEARANCE_SETTINGS_LAYER_JSON(type, name, jsonKey, ...) \
     JsonUtils::GetValueForKey(json, jsonKey, _##name);
diff --git a/src/cascadia/TerminalSettingsModel/AppearanceConfig.h b/src/cascadia/TerminalSettingsModel/AppearanceConfig.h
index bbc30927eb7..7e8f35e6633 100644
--- a/src/cascadia/TerminalSettingsModel/AppearanceConfig.h
+++ b/src/cascadia/TerminalSettingsModel/AppearanceConfig.h
@@ -42,6 +42,9 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
         INHERITABLE_NULLABLE_SETTING(Model::IAppearanceConfig, Microsoft::Terminal::Core::Color, CursorColor, nullptr);
         INHERITABLE_SETTING(Model::IAppearanceConfig, double, Opacity, 1.0);
 
+        INHERITABLE_SETTING(Model::IAppearanceConfig, hstring, DarkColorSchemeName, L"Campbell");
+        INHERITABLE_SETTING(Model::IAppearanceConfig, hstring, LightColorSchemeName, L"Campbell");
+
 #define APPEARANCE_SETTINGS_INITIALIZE(type, name, jsonKey, ...) \
     INHERITABLE_SETTING(Model::IAppearanceConfig, type, name, ##__VA_ARGS__)
         MTSM_APPEARANCE_SETTINGS(APPEARANCE_SETTINGS_INITIALIZE)
diff --git a/src/cascadia/TerminalSettingsModel/AzureCloudShellGenerator.cpp b/src/cascadia/TerminalSettingsModel/AzureCloudShellGenerator.cpp
index a69f44eaecf..948b1822f8c 100644
--- a/src/cascadia/TerminalSettingsModel/AzureCloudShellGenerator.cpp
+++ b/src/cascadia/TerminalSettingsModel/AzureCloudShellGenerator.cpp
@@ -31,7 +31,8 @@ void AzureCloudShellGenerator::GenerateProfiles(std::vector<winrt::com_ptr<imple
     {
         auto azureCloudShellProfile{ CreateDynamicProfile(L"Azure Cloud Shell") };
         azureCloudShellProfile->StartingDirectory(winrt::hstring{ DEFAULT_STARTING_DIRECTORY });
-        azureCloudShellProfile->DefaultAppearance().ColorSchemeName(L"Vintage");
+        azureCloudShellProfile->DefaultAppearance().DarkColorSchemeName(L"Vintage");
+        azureCloudShellProfile->DefaultAppearance().LightColorSchemeName(L"Vintage");
         azureCloudShellProfile->ConnectionType(AzureConnection::ConnectionType());
         profiles.emplace_back(std::move(azureCloudShellProfile));
     }
diff --git a/src/cascadia/TerminalSettingsModel/CascadiaSettings.cpp b/src/cascadia/TerminalSettingsModel/CascadiaSettings.cpp
index 9712c6e51cf..c9aa9ff8e81 100644
--- a/src/cascadia/TerminalSettingsModel/CascadiaSettings.cpp
+++ b/src/cascadia/TerminalSettingsModel/CascadiaSettings.cpp
@@ -326,6 +326,8 @@ Model::Profile CascadiaSettings::DuplicateProfile(const Model::Profile& source)
         DUPLICATE_SETTING_MACRO_SUB(appearance, target, SelectionBackground);
         DUPLICATE_SETTING_MACRO_SUB(appearance, target, CursorColor);
         DUPLICATE_SETTING_MACRO_SUB(appearance, target, Opacity);
+        DUPLICATE_SETTING_MACRO_SUB(appearance, target, DarkColorSchemeName);
+        DUPLICATE_SETTING_MACRO_SUB(appearance, target, LightColorSchemeName);
     }
 
     // UnfocusedAppearance is treated as a single setting,
@@ -430,22 +432,29 @@ void CascadiaSettings::_validateSettings()
 void CascadiaSettings::_validateAllSchemesExist()
 {
     const auto colorSchemes = _globals->ColorSchemes();
-    auto foundInvalidScheme = false;
+    auto foundInvalidDarkScheme = false;
+    auto foundInvalidLightScheme = false;
 
     for (const auto& profile : _allProfiles)
     {
         for (const auto& appearance : std::array{ profile.DefaultAppearance(), profile.UnfocusedAppearance() })
         {
-            if (appearance && !colorSchemes.HasKey(appearance.ColorSchemeName()))
+            if (appearance && !colorSchemes.HasKey(appearance.DarkColorSchemeName()))
             {
-                // Clear the user set color scheme. We'll just fallback instead.
-                appearance.ClearColorSchemeName();
-                foundInvalidScheme = true;
+                // Clear the user set dark color scheme. We'll just fallback instead.
+                appearance.ClearDarkColorSchemeName();
+                foundInvalidDarkScheme = true;
+            }
+            if (appearance && !colorSchemes.HasKey(appearance.LightColorSchemeName()))
+            {
+                // Clear the user set light color scheme. We'll just fallback instead.
+                appearance.ClearLightColorSchemeName();
+                foundInvalidLightScheme = true;
             }
         }
     }
 
-    if (foundInvalidScheme)
+    if (foundInvalidDarkScheme || foundInvalidLightScheme)
     {
         _warnings.Append(SettingsLoadWarnings::UnknownColorScheme);
     }
@@ -937,24 +946,6 @@ bool CascadiaSettings::_hasInvalidColorScheme(const Model::Command& command) con
     return invalid;
 }
 
-// Method Description:
-// - Lookup the color scheme for a given profile. If the profile doesn't exist,
-//   or the scheme name listed in the profile doesn't correspond to a scheme,
-//   this will return `nullptr`.
-// Arguments:
-// - profileGuid: the GUID of the profile to find the scheme for.
-// Return Value:
-// - a non-owning pointer to the scheme.
-Model::ColorScheme CascadiaSettings::GetColorSchemeForProfile(const Model::Profile& profile) const
-{
-    if (!profile)
-    {
-        return nullptr;
-    }
-    const auto schemeName = profile.DefaultAppearance().ColorSchemeName();
-    return _globals->ColorSchemes().TryLookup(schemeName);
-}
-
 // Method Description:
 // - updates all references to that color scheme with the new name
 // Arguments:
@@ -966,26 +957,41 @@ void CascadiaSettings::UpdateColorSchemeReferences(const winrt::hstring& oldName
 {
     // update profiles.defaults, if necessary
     if (_baseLayerProfile &&
-        _baseLayerProfile->DefaultAppearance().HasColorSchemeName() &&
-        _baseLayerProfile->DefaultAppearance().ColorSchemeName() == oldName)
+        _baseLayerProfile->DefaultAppearance().HasDarkColorSchemeName() &&
+        _baseLayerProfile->DefaultAppearance().DarkColorSchemeName() == oldName)
+    {
+        _baseLayerProfile->DefaultAppearance().DarkColorSchemeName(newName);
+    }
+    // NOT else-if, because both could match
+    if (_baseLayerProfile &&
+        _baseLayerProfile->DefaultAppearance().HasLightColorSchemeName() &&
+        _baseLayerProfile->DefaultAppearance().LightColorSchemeName() == oldName)
     {
-        _baseLayerProfile->DefaultAppearance().ColorSchemeName(newName);
+        _baseLayerProfile->DefaultAppearance().LightColorSchemeName(newName);
     }
 
     // update all profiles referencing this color scheme
     for (const auto& profile : _allProfiles)
     {
         const auto defaultAppearance = profile.DefaultAppearance();
-        if (defaultAppearance.HasColorSchemeName() && defaultAppearance.ColorSchemeName() == oldName)
+        if (defaultAppearance.HasLightColorSchemeName() && defaultAppearance.LightColorSchemeName() == oldName)
         {
-            defaultAppearance.ColorSchemeName(newName);
+            defaultAppearance.LightColorSchemeName(newName);
+        }
+        if (defaultAppearance.HasDarkColorSchemeName() && defaultAppearance.DarkColorSchemeName() == oldName)
+        {
+            defaultAppearance.DarkColorSchemeName(newName);
         }
 
-        if (profile.UnfocusedAppearance())
+        if (auto unfocused{ profile.UnfocusedAppearance() })
         {
-            if (profile.UnfocusedAppearance().HasColorSchemeName() && profile.UnfocusedAppearance().ColorSchemeName() == oldName)
+            if (unfocused.HasLightColorSchemeName() && unfocused.LightColorSchemeName() == oldName)
+            {
+                unfocused.LightColorSchemeName(newName);
+            }
+            if (unfocused.HasDarkColorSchemeName() && unfocused.DarkColorSchemeName() == oldName)
             {
-                profile.UnfocusedAppearance().ColorSchemeName(newName);
+                unfocused.DarkColorSchemeName(newName);
             }
         }
     }
diff --git a/src/cascadia/TerminalSettingsModel/CascadiaSettings.h b/src/cascadia/TerminalSettingsModel/CascadiaSettings.h
index dead1629ff2..d8543e74b5a 100644
--- a/src/cascadia/TerminalSettingsModel/CascadiaSettings.h
+++ b/src/cascadia/TerminalSettingsModel/CascadiaSettings.h
@@ -124,7 +124,6 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
         Model::Profile ProfileDefaults() const;
         Model::Profile CreateNewProfile();
         Model::Profile FindProfile(const winrt::guid& guid) const noexcept;
-        Model::ColorScheme GetColorSchemeForProfile(const Model::Profile& profile) const;
         void UpdateColorSchemeReferences(const winrt::hstring& oldName, const winrt::hstring& newName);
         Model::Profile GetProfileForArgs(const Model::NewTerminalArgs& newTerminalArgs) const;
         Model::Profile GetProfileByName(const winrt::hstring& name) const;
diff --git a/src/cascadia/TerminalSettingsModel/CascadiaSettings.idl b/src/cascadia/TerminalSettingsModel/CascadiaSettings.idl
index fb69e58ffc8..5a1987dcf3e 100644
--- a/src/cascadia/TerminalSettingsModel/CascadiaSettings.idl
+++ b/src/cascadia/TerminalSettingsModel/CascadiaSettings.idl
@@ -45,7 +45,6 @@ namespace Microsoft.Terminal.Settings.Model
 
         Profile CreateNewProfile();
         Profile FindProfile(Guid profileGuid);
-        ColorScheme GetColorSchemeForProfile(Profile profile);
         void UpdateColorSchemeReferences(String oldName, String newName);
 
         Profile GetProfileForArgs(NewTerminalArgs newTerminalArgs);
diff --git a/src/cascadia/TerminalSettingsModel/IAppearanceConfig.idl b/src/cascadia/TerminalSettingsModel/IAppearanceConfig.idl
index 2cfa305dec4..6352de64b08 100644
--- a/src/cascadia/TerminalSettingsModel/IAppearanceConfig.idl
+++ b/src/cascadia/TerminalSettingsModel/IAppearanceConfig.idl
@@ -5,7 +5,7 @@ import "Profile.idl";
 #include "IInheritable.idl.h"
 
 #define INHERITABLE_APPEARANCE_SETTING(Type, Name) \
-    _BASE_INHERITABLE_SETTING(Type, Name);      \
+    _BASE_INHERITABLE_SETTING(Type, Name);         \
     Microsoft.Terminal.Settings.Model.IAppearanceConfig Name##OverrideSource { get; }
 
 namespace Microsoft.Terminal.Settings.Model
@@ -22,9 +22,7 @@ namespace Microsoft.Terminal.Settings.Model
         Vertical_Bottom = 0x20
     };
 
-    [flags]
-    enum IntenseStyle
-    {
+    [flags] enum IntenseStyle {
         Bold = 0x1,
         Bright = 0x2,
         All = 0xffffffff
@@ -33,7 +31,10 @@ namespace Microsoft.Terminal.Settings.Model
     interface IAppearanceConfig
     {
         Microsoft.Terminal.Settings.Model.Profile SourceProfile { get; };
-        INHERITABLE_APPEARANCE_SETTING(String, ColorSchemeName);
+
+        INHERITABLE_APPEARANCE_SETTING(String, DarkColorSchemeName);
+        INHERITABLE_APPEARANCE_SETTING(String, LightColorSchemeName);
+
         INHERITABLE_APPEARANCE_SETTING(Windows.Foundation.IReference<Microsoft.Terminal.Core.Color>, Foreground);
         INHERITABLE_APPEARANCE_SETTING(Windows.Foundation.IReference<Microsoft.Terminal.Core.Color>, Background);
         INHERITABLE_APPEARANCE_SETTING(Windows.Foundation.IReference<Microsoft.Terminal.Core.Color>, SelectionBackground);
diff --git a/src/cascadia/TerminalSettingsModel/MTSMSettings.h b/src/cascadia/TerminalSettingsModel/MTSMSettings.h
index 3cae1919883..91ff1b068a4 100644
--- a/src/cascadia/TerminalSettingsModel/MTSMSettings.h
+++ b/src/cascadia/TerminalSettingsModel/MTSMSettings.h
@@ -109,7 +109,6 @@ Author(s):
     X(bool, RetroTerminalEffect, "experimental.retroTerminalEffect", false)                                                                                        \
     X(hstring, PixelShaderPath, "experimental.pixelShaderPath")                                                                                                    \
     X(ConvergedAlignment, BackgroundImageAlignment, "backgroundImageAlignment", ConvergedAlignment::Horizontal_Center | ConvergedAlignment::Vertical_Center)       \
-    X(hstring, ColorSchemeName, "colorScheme", L"Campbell")                                                                                                        \
     X(hstring, BackgroundImagePath, "backgroundImage")                                                                                                             \
     X(Model::IntenseStyle, IntenseTextStyle, "intenseTextStyle", Model::IntenseStyle::Bright)                                                                      \
     X(Core::AdjustTextMode, AdjustIndistinguishableColors, "adjustIndistinguishableColors", Core::AdjustTextMode::Never)
diff --git a/src/cascadia/TerminalSettingsModel/PowershellCoreProfileGenerator.cpp b/src/cascadia/TerminalSettingsModel/PowershellCoreProfileGenerator.cpp
index 5db52c810b6..ae04753a73c 100644
--- a/src/cascadia/TerminalSettingsModel/PowershellCoreProfileGenerator.cpp
+++ b/src/cascadia/TerminalSettingsModel/PowershellCoreProfileGenerator.cpp
@@ -319,7 +319,8 @@ void PowershellCoreProfileGenerator::GenerateProfiles(std::vector<winrt::com_ptr
         profile->Commandline(winrt::hstring{ quotedCommandline });
 
         profile->StartingDirectory(winrt::hstring{ DEFAULT_STARTING_DIRECTORY });
-        profile->DefaultAppearance().ColorSchemeName(L"Campbell");
+        profile->DefaultAppearance().DarkColorSchemeName(L"Campbell");
+        profile->DefaultAppearance().LightColorSchemeName(L"Campbell");
         profile->Icon(winrt::hstring{ WI_IsFlagSet(psI.flags, PowerShellFlags::Preview) ? POWERSHELL_PREVIEW_ICON : POWERSHELL_ICON });
 
         if (first)
diff --git a/src/cascadia/TerminalSettingsModel/TerminalSettings.cpp b/src/cascadia/TerminalSettingsModel/TerminalSettings.cpp
index 0ba57857303..39510e1b951 100644
--- a/src/cascadia/TerminalSettingsModel/TerminalSettings.cpp
+++ b/src/cascadia/TerminalSettingsModel/TerminalSettings.cpp
@@ -57,7 +57,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
         const auto globals = appSettings.GlobalSettings();
         settings->_ApplyProfileSettings(profile);
         settings->_ApplyGlobalSettings(globals);
-        settings->_ApplyAppearanceSettings(profile.DefaultAppearance(), globals.ColorSchemes());
+        settings->_ApplyAppearanceSettings(profile.DefaultAppearance(), globals.ColorSchemes(), globals.CurrentTheme());
 
         return settings;
     }
@@ -91,7 +91,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
         {
             const auto globals = appSettings.GlobalSettings();
             auto childImpl = settings->CreateChild();
-            childImpl->_ApplyAppearanceSettings(unfocusedAppearance, globals.ColorSchemes());
+            childImpl->_ApplyAppearanceSettings(unfocusedAppearance, globals.ColorSchemes(), globals.CurrentTheme());
             child = *childImpl;
         }
 
@@ -183,17 +183,50 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
         return settingsPair;
     }
 
-    void TerminalSettings::_ApplyAppearanceSettings(const IAppearanceConfig& appearance, const Windows::Foundation::Collections::IMapView<winrt::hstring, ColorScheme>& schemes)
+    // I'm not even joking, this is the recommended way to do this:
+    // https://learn.microsoft.com/en-us/windows/apps/desktop/modernize/apply-windows-themes#know-when-dark-mode-is-enabled
+    bool _isSystemInDarkTheme()
+    {
+        static auto isColorLight = [](const Windows::UI::Color& clr) -> bool {
+            return (((5 * clr.G) + (2 * clr.R) + clr.B) > (8 * 128));
+        };
+        return isColorLight(Windows::UI::ViewManagement::UISettings().GetColorValue(Windows::UI::ViewManagement::UIColorType::Foreground));
+    }
+
+    void TerminalSettings::_ApplyAppearanceSettings(const IAppearanceConfig& appearance,
+                                                    const Windows::Foundation::Collections::IMapView<winrt::hstring, ColorScheme>& schemes,
+                                                    const winrt::Microsoft::Terminal::Settings::Model::Theme currentTheme)
     {
         _CursorShape = appearance.CursorShape();
         _CursorHeight = appearance.CursorHeight();
-        if (!appearance.ColorSchemeName().empty())
+
+        auto requestedTheme = currentTheme.RequestedTheme();
+        if (requestedTheme == winrt::Windows::UI::Xaml::ElementTheme::Default)
+        {
+            requestedTheme = _isSystemInDarkTheme() ?
+                                 winrt::Windows::UI::Xaml::ElementTheme::Dark :
+                                 winrt::Windows::UI::Xaml::ElementTheme::Light;
+        }
+
+        switch (requestedTheme)
         {
-            if (const auto scheme = schemes.TryLookup(appearance.ColorSchemeName()))
+        case winrt::Windows::UI::Xaml::ElementTheme::Light:
+            if (const auto scheme = schemes.TryLookup(appearance.LightColorSchemeName()))
             {
                 ApplyColorScheme(scheme);
             }
+            break;
+        case winrt::Windows::UI::Xaml::ElementTheme::Dark:
+            if (const auto scheme = schemes.TryLookup(appearance.DarkColorSchemeName()))
+            {
+                ApplyColorScheme(scheme);
+            }
+            break;
+        case winrt::Windows::UI::Xaml::ElementTheme::Default:
+            // This shouldn't happen!
+            break;
         }
+
         if (appearance.Foreground())
         {
             _DefaultForeground = til::color{ appearance.Foreground().Value() };
diff --git a/src/cascadia/TerminalSettingsModel/TerminalSettings.h b/src/cascadia/TerminalSettingsModel/TerminalSettings.h
index 0dd65cdfbb7..e92ce3aeed9 100644
--- a/src/cascadia/TerminalSettingsModel/TerminalSettings.h
+++ b/src/cascadia/TerminalSettingsModel/TerminalSettings.h
@@ -170,7 +170,8 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
 
         void _ApplyGlobalSettings(const Model::GlobalAppSettings& globalSettings) noexcept;
         void _ApplyAppearanceSettings(const Microsoft::Terminal::Settings::Model::IAppearanceConfig& appearance,
-                                      const Windows::Foundation::Collections::IMapView<hstring, Microsoft::Terminal::Settings::Model::ColorScheme>& schemes);
+                                      const Windows::Foundation::Collections::IMapView<hstring, Microsoft::Terminal::Settings::Model::ColorScheme>& schemes,
+                                      const winrt::Microsoft::Terminal::Settings::Model::Theme currentTheme);
 
         friend class SettingsModelLocalTests::TerminalSettingsTests;
     };
diff --git a/src/cascadia/TerminalSettingsModel/WslDistroGenerator.cpp b/src/cascadia/TerminalSettingsModel/WslDistroGenerator.cpp
index 840835cf1f3..373282866a6 100644
--- a/src/cascadia/TerminalSettingsModel/WslDistroGenerator.cpp
+++ b/src/cascadia/TerminalSettingsModel/WslDistroGenerator.cpp
@@ -53,7 +53,8 @@ static winrt::com_ptr<implementation::Profile> makeProfile(const std::wstring& d
     std::wstring command{};
     THROW_IF_FAILED(wil::GetSystemDirectoryW<std::wstring>(command));
     WSLDistro->Commandline(winrt::hstring{ command + L"\\wsl.exe -d " + distName });
-    WSLDistro->DefaultAppearance().ColorSchemeName(L"Campbell");
+    WSLDistro->DefaultAppearance().DarkColorSchemeName(L"Campbell");
+    WSLDistro->DefaultAppearance().LightColorSchemeName(L"Campbell");
     if (isWslDashDashCdAvailableForLinuxPaths())
     {
         WSLDistro->StartingDirectory(winrt::hstring{ WslHomeDirectory });
diff --git a/src/cascadia/TerminalSettingsModel/pch.h b/src/cascadia/TerminalSettingsModel/pch.h
index f8266b66fd1..75b789ed581 100644
--- a/src/cascadia/TerminalSettingsModel/pch.h
+++ b/src/cascadia/TerminalSettingsModel/pch.h
@@ -35,6 +35,7 @@
 #include <winrt/Windows.Storage.Streams.h>
 #include <winrt/Windows.System.h>
 #include <winrt/Windows.UI.Core.h>
+#include <winrt/Windows.UI.ViewManagement.h>
 #include <winrt/Windows.UI.Xaml.Controls.h>
 #include <winrt/Windows.UI.Xaml.Media.h>
 #include <winrt/Windows.UI.Xaml.Media.Imaging.h>
diff --git a/src/cascadia/WindowsTerminal/AppHost.cpp b/src/cascadia/WindowsTerminal/AppHost.cpp
index 90524d9a148..4ab2d0031bd 100644
--- a/src/cascadia/WindowsTerminal/AppHost.cpp
+++ b/src/cascadia/WindowsTerminal/AppHost.cpp
@@ -390,6 +390,7 @@ void AppHost::Initialize()
     _window->DragRegionClicked([this]() { _logic.TitlebarClicked(); });
 
     _window->WindowVisibilityChanged([this](bool showOrHide) { _logic.WindowVisibilityChanged(showOrHide); });
+    _window->UpdateSettingsRequested([this]() { _logic.ReloadSettings(); });
 
     _revokers.RequestedThemeChanged = _logic.RequestedThemeChanged(winrt::auto_revoke, { this, &AppHost::_UpdateTheme });
     _revokers.FullscreenChanged = _logic.FullscreenChanged(winrt::auto_revoke, { this, &AppHost::_FullscreenChanged });
diff --git a/src/cascadia/WindowsTerminal/IslandWindow.cpp b/src/cascadia/WindowsTerminal/IslandWindow.cpp
index f42212912d2..446d1b46506 100644
--- a/src/cascadia/WindowsTerminal/IslandWindow.cpp
+++ b/src/cascadia/WindowsTerminal/IslandWindow.cpp
@@ -658,6 +658,18 @@ long IslandWindow::_calculateTotalSize(const bool isWidth, const long clientSize
         }
         break;
     }
+    case WM_SETTINGCHANGE:
+    {
+        const std::wstring param{ (wchar_t*)lparam };
+        // ImmersiveColorSet seems to be the notification that the OS theme
+        // changed. If that happens, let the app know, so it can hot-reload
+        // themes, color schemes that might depend on the OS theme
+        if (param == L"ImmersiveColorSet")
+        {
+            _UpdateSettingsRequestedHandlers();
+        }
+        break;
+    }
     case WM_ENDSESSION:
     {
         // For WM_QUERYENDSESSION and WM_ENDSESSION, refer to:
diff --git a/src/cascadia/WindowsTerminal/IslandWindow.h b/src/cascadia/WindowsTerminal/IslandWindow.h
index 368e5321e8b..b0d3efff5c5 100644
--- a/src/cascadia/WindowsTerminal/IslandWindow.h
+++ b/src/cascadia/WindowsTerminal/IslandWindow.h
@@ -81,6 +81,7 @@ class IslandWindow :
 
     WINRT_CALLBACK(WindowMoved, winrt::delegate<void()>);
     WINRT_CALLBACK(WindowVisibilityChanged, winrt::delegate<void(bool)>);
+    WINRT_CALLBACK(UpdateSettingsRequested, winrt::delegate<void()>);
 
 protected:
     void ForceResize()
diff --git a/src/cascadia/inc/ControlProperties.h b/src/cascadia/inc/ControlProperties.h
index 5911fa26183..8132d579e59 100644
--- a/src/cascadia/inc/ControlProperties.h
+++ b/src/cascadia/inc/ControlProperties.h
@@ -16,7 +16,7 @@
     X(winrt::Microsoft::Terminal::Core::AdjustTextMode, AdjustIndistinguishableColors, winrt::Microsoft::Terminal::Core::AdjustTextMode::Never)
 
 // --------------------------- Control Appearance ---------------------------
-//  All of these settings are defined in IControlSettings.
+//  All of these settings are defined in IControlAppearance.
 #define CONTROL_APPEARANCE_SETTINGS(X)                                                                                                          \
     X(til::color, SelectionBackground, DEFAULT_FOREGROUND)                                                                                      \
     X(double, Opacity, 1.0)                                                                                                                     \


Test patch: