diff --git a/.ci/azure-cmake-new.yml b/.ci/azure-cmake-new.yml
index 56a2fb4d9..2d9cdee8c 100644
--- a/.ci/azure-cmake-new.yml
+++ b/.ci/azure-cmake-new.yml
@@ -1,8 +1,8 @@
 steps:
   # Note that silkeh/clang does not include ca-certificates, so check the shasum for verification
   - bash: |
-      wget --no-check-certificate "https://cmake.org/files/v3.28/cmake-3.28.0-linux-x86_64.tar.gz"
-      echo "898f0b5ca6e2ea5286998e97bd33f030d7d09f18ca4b88be661fdfbad5dadd88  cmake-3.28.0-linux-x86_64.tar.gz" | shasum -sca 256
+      wget --no-check-certificate "https://cmake.org/files/v3.31/cmake-3.31.1-linux-x86_64.tar.gz"
+      echo "3b72fde0d40fa8be617667ea08d12c5ee47f6cf8950c2fbfcf2acfb5f83fb9de  cmake-3.31.1-linux-x86_64.tar.gz" | shasum -sca 256
     displayName: Download CMake
 
   - task: ExtractFiles@1
@@ -13,5 +13,5 @@ steps:
 
   - bash:
       echo
-      "##vso[task.prependpath]$(Build.SourcesDirectory)/cmake_program/cmake-3.28.0-linux-x86_64/bin"
+      "##vso[task.prependpath]$(Build.SourcesDirectory)/cmake_program/cmake-3.31.1-linux-x86_64/bin"
     displayName: Add CMake to PATH
diff --git a/azure-pipelines.yml b/azure-pipelines.yml
index 9ee72d11e..0f8a92c32 100644
--- a/azure-pipelines.yml
+++ b/azure-pipelines.yml
@@ -165,18 +165,22 @@ jobs:
       vmImage: "ubuntu-latest"
     strategy:
       matrix:
-        gcc13:
+        gcc13_17:
           containerImage: gcc:13
           cli11.std: 17
           cli11.options: -DCMAKE_CXX_FLAGS="-Wstrict-overflow=5"
-        gcc12:
+        gcc12_20:
           containerImage: gcc:12
           cli11.std: 20
           cli11.options: -DCMAKE_CXX_FLAGS="-Wredundant-decls -Wconversion"
-        clang17_20:
+        clang17_23:
           containerImage: silkeh/clang:17
           cli11.std: 23
           cli11.options: -DCMAKE_CXX_FLAGS=-std=c++23
+        clang19_26:
+          containerImage: silkeh/clang:19
+          cli11.std: 26
+          cli11.options: -DCMAKE_CXX_FLAGS=-std=c++2c
     container: $[ variables['containerImage'] ]
     steps:
       - template: .ci/azure-cmake-new.yml
diff --git a/include/CLI/Macros.hpp b/include/CLI/Macros.hpp
index 0d6d17671..d62f06739 100644
--- a/include/CLI/Macros.hpp
+++ b/include/CLI/Macros.hpp
@@ -18,11 +18,17 @@
 #define CLI11_CPP17
 #if __cplusplus > 201703L
 #define CLI11_CPP20
+#if __cplusplus > 202002L
+#define CLI11_CPP23
+#if __cplusplus > 202302L
+#define CLI11_CPP26
+#endif
+#endif
 #endif
 #endif
 #endif
 #elif defined(_MSC_VER) && __cplusplus == 199711L
-// MSVC sets _MSVC_LANG rather than __cplusplus (supposedly until the standard is fully implemented)
+// MSVC sets _MSVC_LANG rather than __cplusplus (supposedly until the standard was fully implemented)
 // Unless you use the /Zc:__cplusplus flag on Visual Studio 2017 15.7 Preview 3 or newer
 #if _MSVC_LANG >= 201402L
 #define CLI11_CPP14
@@ -30,6 +36,9 @@
 #define CLI11_CPP17
 #if _MSVC_LANG > 201703L && _MSC_VER >= 1910
 #define CLI11_CPP20
+#if _MSVC_LANG > 202002L && _MSC_VER >= 1922
+#define CLI11_CPP23
+#endif
 #endif
 #endif
 #endif
@@ -96,12 +105,22 @@
 #endif
 
 /** <codecvt> availability */
+#if !defined(CLI11_CPP26) && !defined(CLI11_HAS_CODECVT)
 #if defined(__GNUC__) && !defined(__llvm__) && !defined(__INTEL_COMPILER) && __GNUC__ < 5
 #define CLI11_HAS_CODECVT 0
 #else
 #define CLI11_HAS_CODECVT 1
 #include <codecvt>
 #endif
+#else
+#if defined(CLI11_HAS_CODECVT)
+#if CLI11_HAS_CODECVT > 0
+#include <codecvt>
+#endif
+#else
+#define CLI11_HAS_CODECVT 0
+#endif
+#endif
 
 /** disable deprecations */
 #if defined(__GNUC__)  // GCC or clang
diff --git a/include/CLI/TypeTools.hpp b/include/CLI/TypeTools.hpp
index cbae1631a..73d5abc86 100644
--- a/include/CLI/TypeTools.hpp
+++ b/include/CLI/TypeTools.hpp
@@ -295,8 +295,9 @@ template <typename T>
 struct is_wrapper<T, conditional_t<false, void_t<typename T::value_type>, void>> : public std::true_type {};
 
 // Check for tuple like types, as in classes with a tuple_size type trait
+// Even though in C++26 std::complex gains a std::tuple interface, for our purposes we treat is as NOT a tuple
 template <typename S> class is_tuple_like {
-    template <typename SS>
+    template <typename SS, enable_if_t<!is_complex<SS>::value, detail::enabler> = detail::dummy>
     // static auto test(int)
     //     -> decltype(std::conditional<(std::tuple_size<SS>::value > 0), std::true_type, std::false_type>::type());
     static auto test(int) -> decltype(std::tuple_size<typename std::decay<SS>::type>::value, std::true_type{});
diff --git a/tests/HelpersTest.cpp b/tests/HelpersTest.cpp
index 71dbee305..4d8af47f6 100644
--- a/tests/HelpersTest.cpp
+++ b/tests/HelpersTest.cpp
@@ -1520,6 +1520,7 @@ static_assert(CLI::detail::is_tuple_like<std::array<int, 10>>::value, "std::arra
 static_assert(!CLI::detail::is_tuple_like<std::string>::value, "std::string should not be like a tuple");
 static_assert(!CLI::detail::is_tuple_like<double>::value, "double should not be like a tuple");
 static_assert(CLI::detail::is_tuple_like<std::tuple<double, int, double>>::value, "tuple should look like a tuple");
+static_assert(!CLI::detail::is_tuple_like<std::complex<double>>::value, "std::complex should not be like a tuple");
 
 TEST_CASE("Types: LexicalConversionTuple2", "[helpers]") {
     CLI::results_t input = {"9.12", "19"};