fix(ci): use the intended Python interpreter for CMake discovery (#6105)

* fix(ci): pin the discovered Python to the venv/setup-python interpreter

The manylinux/musllinux images added Python 3.15 and dropped 3.13t;
FindPython's version scan then picked /usr/local/bin/python3.15 over
the uv-created venv (Python_ROOT_DIR is only a hint). Similarly, the
macOS and Windows 3.14t jobs picked a system 3.14 over setup-python's
free-threaded interpreter. Pin the interpreter explicitly in both
places, and drop the 3.13t manylinux jobs.

Assisted-by: ClaudeCode:claude-fable-5

* ci: use setup-python's python-path output instead of a locate step

Assisted-by: ClaudeCode:claude-fable-5

* Apply suggestions from code review

Co-authored-by: Ralf W. Grosse-Kunstleve <rwgkio@gmail.com>

---------

Co-authored-by: Ralf W. Grosse-Kunstleve <rwgkio@gmail.com>
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 7529df1..359741c 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -241,10 +241,6 @@
       matrix:
         include:
           - container: quay.io/pypa/manylinux_2_28_x86_64:latest
-            python-version: '3.13t'
-          - container: quay.io/pypa/musllinux_1_2_x86_64:latest
-            python-version: '3.13t'
-          - container: quay.io/pypa/manylinux_2_28_x86_64:latest
             python-version: '3.14t'
           - container: quay.io/pypa/musllinux_1_2_x86_64:latest
             python-version: '3.14t'
diff --git a/.github/workflows/reusable-standard.yml b/.github/workflows/reusable-standard.yml
index f96116a..6081f80 100644
--- a/.github/workflows/reusable-standard.yml
+++ b/.github/workflows/reusable-standard.yml
@@ -34,6 +34,7 @@
       - uses: actions/checkout@v7
 
       - name: Setup Python ${{ inputs.python-version }}
+        id: python
         uses: actions/setup-python@v6
         with:
           python-version: ${{ inputs.python-version }}
@@ -67,6 +68,9 @@
         if: runner.os != 'Windows'
         run: echo "CMAKE_GENERATOR=Ninja" >> "$GITHUB_ENV"
 
+      # Pass setup-python's resolved interpreter path to CMake so FindPython
+      # does not select a different interpreter (e.g. Homebrew's 3.14 instead
+      # of setup-python's 3.14t).
       - name: Configure
         run: >
           cmake -S. -Bbuild -Werror=dev
@@ -74,6 +78,7 @@
           -DPYBIND11_PYTEST_ARGS=-v
           -DDOWNLOAD_CATCH=ON
           -DDOWNLOAD_EIGEN=ON
+          -DPYTHON_EXECUTABLE=${{ steps.python.outputs.python-path }}
           ${{ inputs.cmake-args }}
 
       - name: Build
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 3abb3dc..5e72afc 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -177,6 +177,17 @@
       set(Python_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/.venv")
     endif()
   endif()
+
+  # Python_ROOT_DIR is only a search hint, so FindPython may select a newer
+  # Python elsewhere. Set Python_EXECUTABLE to the venv's interpreter path
+  # to bypass interpreter discovery.
+  if(DEFINED Python_ROOT_DIR AND NOT DEFINED Python_EXECUTABLE)
+    if(WIN32 AND EXISTS "${Python_ROOT_DIR}/Scripts/python.exe")
+      set(Python_EXECUTABLE "${Python_ROOT_DIR}/Scripts/python.exe")
+    elseif(EXISTS "${Python_ROOT_DIR}/bin/python")
+      set(Python_EXECUTABLE "${Python_ROOT_DIR}/bin/python")
+    endif()
+  endif()
 endif()
 
 set(PYBIND11_HEADERS