refactor: move docs/sphinx -> docs (#2130)

The sphinx sub-dir was only temporary as the sphinx-based docgen was
implemented. With that done, the files can be moved up into the regular
docs directory.
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index 9632f4e..5733fc1 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -10,7 +10,7 @@
   - package-ecosystem: "pip"
     directories:
       # Maintain dependencies for our tools
-      - "/docs/sphinx"
+      - "/docs"
       - "/tools/publish"
     schedule:
       interval: "weekly"
diff --git a/.readthedocs.yml b/.readthedocs.yml
index f68ccc8..6613d49 100644
--- a/.readthedocs.yml
+++ b/.readthedocs.yml
@@ -11,4 +11,4 @@
     - bazel version
     # Put the actual build behind a shell script because its easier to modify than
     # the yaml config.
-    - docs/sphinx/readthedocs_build.sh
+    - docs/readthedocs_build.sh
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index cb123bf..33b296f 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -148,7 +148,7 @@
 
 * **requirements lock files**: These are usually generated by a
   `compile_pip_requirements` update target, which is usually in the same directory.
-  e.g. `bazel run //docs/sphinx:requirements.update`
+  e.g. `bazel run //docs:requirements.update`
 
 ## Core rules
 
diff --git a/MODULE.bazel b/MODULE.bazel
index c4d0e5f..9ac3e7a 100644
--- a/MODULE.bazel
+++ b/MODULE.bazel
@@ -93,7 +93,7 @@
 dev_pip.parse(
     hub_name = "dev_pip",
     python_version = "3.11",
-    requirements_lock = "//docs/sphinx:requirements.txt",
+    requirements_lock = "//docs:requirements.txt",
 )
 dev_pip.parse(
     hub_name = "pypiserver",
diff --git a/WORKSPACE b/WORKSPACE
index 695b0e9..02b3b6e 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -122,7 +122,7 @@
 pip_parse(
     name = "dev_pip",
     python_interpreter_target = interpreter,
-    requirements_lock = "//docs/sphinx:requirements.txt",
+    requirements_lock = "//docs:requirements.txt",
 )
 
 load("@dev_pip//:requirements.bzl", docs_install_deps = "install_deps")
diff --git a/docs/BUILD.bazel b/docs/BUILD.bazel
index c334fbc..56bca88 100644
--- a/docs/BUILD.bazel
+++ b/docs/BUILD.bazel
@@ -1,10 +1,10 @@
-# Copyright 2017 The Bazel Authors. All rights reserved.
+# Copyright 2023 The Bazel Authors. All rights reserved.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
 # You may obtain a copy of the License at
 #
-#    http://www.apache.org/licenses/LICENSE-2.0
+#     http://www.apache.org/licenses/LICENSE-2.0
 #
 # Unless required by applicable law or agreed to in writing, software
 # distributed under the License is distributed on an "AS IS" BASIS,
@@ -13,10 +13,199 @@
 # limitations under the License.
 
 load("@bazel_skylib//:bzl_library.bzl", "bzl_library")
+load("@bazel_skylib//rules:write_file.bzl", "write_file")
+load("@dev_pip//:requirements.bzl", "requirement")
+load("//python:py_binary.bzl", "py_binary")
+load("//python/private:bzlmod_enabled.bzl", "BZLMOD_ENABLED")  # buildifier: disable=bzl-visibility
+load("//python/private:util.bzl", "IS_BAZEL_7_OR_HIGHER")  # buildifier: disable=bzl-visibility
+load("//sphinxdocs:readthedocs.bzl", "readthedocs_install")
+load("//sphinxdocs:sphinx.bzl", "sphinx_build_binary", "sphinx_docs")
+load("//sphinxdocs:sphinx_stardoc.bzl", "sphinx_stardoc", "sphinx_stardocs")
 
-# NOTE: Only public visibility for historical reasons.
-# This package is only for rules_python to generate its own docs.
-package(default_visibility = ["//visibility:public"])
+package(default_visibility = ["//:__subpackages__"])
+
+# We only build for Linux and Mac because:
+# 1. The actual doc process only runs on Linux
+# 2. Mac is a common development platform, and is close enough to Linux
+#    it's feasible to make work.
+# Making CI happy under Windows is too much of a headache, though, so we don't
+# bother with that.
+_TARGET_COMPATIBLE_WITH = select({
+    "@platforms//os:linux": [],
+    "@platforms//os:macos": [],
+    "//conditions:default": ["@platforms//:incompatible"],
+}) if IS_BAZEL_7_OR_HIGHER else ["@platforms//:incompatible"]
+
+# See README.md for instructions. Short version:
+# * `bazel run //docs:docs.serve` in a separate terminal
+# * `ibazel build //docs:docs` to automatically rebuild docs
+sphinx_docs(
+    name = "docs",
+    srcs = glob(
+        include = [
+            "*.md",
+            "**/*.md",
+            "_static/**",
+            "_includes/**",
+        ],
+        exclude = [
+            "README.md",
+            "_*",
+            "*.inv*",
+        ],
+    ),
+    config = "conf.py",
+    formats = [
+        "html",
+    ],
+    renamed_srcs = {
+        "//:CHANGELOG.md": "changelog.md",
+        "//:CONTRIBUTING.md": "contributing.md",
+        "//sphinxdocs/inventories:bazel_inventory": "bazel_inventory.inv",
+    },
+    sphinx = ":sphinx-build",
+    strip_prefix = package_name() + "/",
+    tags = ["docs"],
+    target_compatible_with = _TARGET_COMPATIBLE_WITH,
+    deps = [
+        ":bzl_api_docs",
+        "//sphinxdocs/docs:docs_lib",
+    ],
+)
+
+sphinx_stardocs(
+    name = "bzl_api_docs",
+    srcs = [
+        "//python:defs_bzl",
+        "//python:packaging_bzl",
+        "//python:pip_bzl",
+        "//python:py_binary_bzl",
+        "//python:py_cc_link_params_info_bzl",
+        "//python:py_library_bzl",
+        "//python:py_runtime_bzl",
+        "//python:py_runtime_info_bzl",
+        "//python:py_test_bzl",
+        "//python/cc:py_cc_toolchain_info_bzl",
+        "//python/entry_points:py_console_script_binary_bzl",
+        "//python/private/common:py_binary_rule_bazel_bzl",
+        "//python/private/common:py_library_rule_bazel_bzl",
+        "//python/private/common:py_runtime_rule_bzl",
+        "//python/private/common:py_test_rule_bazel_bzl",
+    ] + ([
+        # Bazel 6 + Stardoc isn't able to parse something about the python bzlmod extension
+        "//python/extensions:python_bzl",
+    ] if IS_BAZEL_7_OR_HIGHER else []) + ([
+        # This depends on @pythons_hub, which is only created under bzlmod,
+        "//python/extensions:pip_bzl",
+    ] if IS_BAZEL_7_OR_HIGHER and BZLMOD_ENABLED else []),
+    prefix = "api/",
+    tags = ["docs"],
+    target_compatible_with = _TARGET_COMPATIBLE_WITH,
+)
+
+sphinx_stardoc(
+    name = "py_cc_toolchain",
+    src = "//python/private:py_cc_toolchain_rule.bzl",
+    prefix = "api/",
+    public_load_path = "//python/cc:py_cc_toolchain.bzl",
+    tags = ["docs"],
+    target_compatible_with = _TARGET_COMPATIBLE_WITH,
+    deps = ["//python/cc:py_cc_toolchain_bzl"],
+)
+
+sphinx_stardoc(
+    name = "py_runtime_pair",
+    src = "//python/private:py_runtime_pair_rule_bzl",
+    public_load_path = "//python:py_runtime_pair.bzl",
+    tags = ["docs"],
+    target_compatible_with = _TARGET_COMPATIBLE_WITH,
+)
+
+readthedocs_install(
+    name = "readthedocs_install",
+    docs = [":docs"],
+    target_compatible_with = _TARGET_COMPATIBLE_WITH,
+)
+
+sphinx_build_binary(
+    name = "sphinx-build",
+    target_compatible_with = _TARGET_COMPATIBLE_WITH,
+    deps = [
+        requirement("sphinx"),
+        requirement("sphinx_rtd_theme"),
+        requirement("myst_parser"),
+        requirement("readthedocs_sphinx_ext"),
+        requirement("typing_extensions"),
+        "//sphinxdocs/src/sphinx_bzl",
+    ],
+)
+
+_REQUIREMENTS_TARGET_COMPATIBLE_WITH = select({
+    "@platforms//os:linux": [],
+    "@platforms//os:macos": [],
+    "@platforms//os:windows": [],
+    "//conditions:default": ["@platforms//:incompatible"],
+}) if BZLMOD_ENABLED else ["@platforms//:incompatible"]
+
+# Run bazel run //docs:requirements.update
+genrule(
+    name = "requirements",
+    srcs = ["pyproject.toml"],
+    outs = ["_requirements.txt"],
+    cmd = "$(UV_BIN) pip compile " + " ".join([
+        "--custom-compile-command='bazel run //docs:requirements.update'",
+        "--generate-hashes",
+        "--universal",
+        "--emit-index-url",
+        "--no-strip-extras",
+        "--no-build",
+        "--python=$(PYTHON3)",
+        "$<",
+        "--output-file=$@",
+        # Always try upgrading
+        "--upgrade",
+    ]),
+    tags = [
+        "local",
+        "manual",
+        "no-cache",
+    ],
+    target_compatible_with = _REQUIREMENTS_TARGET_COMPATIBLE_WITH,
+    toolchains = [
+        "//python/uv:current_toolchain",
+        "//python:current_py_toolchain",
+    ],
+)
+
+# Write a script that can be used for updating the in-tree version of the
+# requirements file
+write_file(
+    name = "gen_update_requirements",
+    out = "requirements.update.py",
+    content = [
+        "from os import environ",
+        "from pathlib import Path",
+        "from sys import stderr",
+        "",
+        'src = Path(environ["REQUIREMENTS_FILE"])',
+        'dst = Path(environ["BUILD_WORKSPACE_DIRECTORY"]) / "docs" / "requirements.txt"',
+        'print(f"Writing requirements contents from {src} to {dst}", file=stderr)',
+        "dst.write_text(src.read_text())",
+        'print("Success!", file=stderr)',
+    ],
+    target_compatible_with = _REQUIREMENTS_TARGET_COMPATIBLE_WITH,
+)
+
+py_binary(
+    name = "requirements.update",
+    srcs = ["requirements.update.py"],
+    data = [":requirements"],
+    env = {
+        "REQUIREMENTS_FILE": "$(location :requirements)",
+    },
+    tags = ["manual"],
+    target_compatible_with = _REQUIREMENTS_TARGET_COMPATIBLE_WITH,
+)
 
 licenses(["notice"])  # Apache 2.0
 
@@ -26,18 +215,21 @@
     name = "defs",
     actual = "//python:defs_bzl",
     deprecation = "Use //python:defs_bzl instead; targets under //docs are internal.",
+    visibility = ["//visibility:public"],
 )
 
 alias(
     name = "bazel_repo_tools",
     actual = "//python/private:bazel_tools_bzl",
     deprecation = "Use @bazel_tools//tools:bzl_srcs instead; targets under //docs are internal.",
+    visibility = ["//visibility:public"],
 )
 
 bzl_library(
     name = "pip_install_bzl",
     deprecation = "Use //python:pip_bzl or //python/pip_install:pip_repository_bzl instead; " +
                   "targets under //docs are internal.",
+    visibility = ["//visibility:public"],
     deps = [
         "//python:pip_bzl",
         "//python/pip_install:pip_repository_bzl",
@@ -49,4 +241,5 @@
     actual = "//python/pip_install:pip_repository_bzl",
     deprecation = "Use //python/pip_install:pip_repository_bzl instead; Both the requirements " +
                   "parser and targets under //docs are internal",
+    visibility = ["//visibility:public"],
 )
diff --git a/docs/sphinx/README.md b/docs/README.md
similarity index 90%
rename from docs/sphinx/README.md
rename to docs/README.md
index 98420e4..d98be41 100644
--- a/docs/sphinx/README.md
+++ b/docs/README.md
@@ -18,8 +18,8 @@
 change. The quick start is:
 
 ```
-bazel run //docs/sphinx:docs.serve  # Run in separate terminal
-ibazel build //docs/sphinx:docs  # Automatically rebuilds docs
+bazel run //docs:docs.serve  # Run in separate terminal
+ibazel build //docs:docs  # Automatically rebuilds docs
 ```
 
 This will build the docs and start a local webserver at http://localhost:8000
@@ -47,14 +47,14 @@
 creating indexes, and using concise markup to generate rich documentation.
 
 MyST features and behaviors are controlled by the Sphinx configuration file,
-`docs/sphinx/conf.py`. For more info, see https://myst-parser.readthedocs.io.
+`docs/conf.py`. For more info, see https://myst-parser.readthedocs.io.
 
 ## Sphinx configuration
 
 The Sphinx-specific configuration files and input doc files live in
-docs/sphinx.
+docs/.
 
-The Sphinx configuration is `docs/sphinx/conf.py`. See
+The Sphinx configuration is `docs/conf.py`. See
 https://www.sphinx-doc.org/ for details about the configuration file.
 
 ## Readthedocs configuration
diff --git a/docs/sphinx/_includes/py_console_script_binary.md b/docs/_includes/py_console_script_binary.md
similarity index 100%
rename from docs/sphinx/_includes/py_console_script_binary.md
rename to docs/_includes/py_console_script_binary.md
diff --git a/docs/sphinx/_static/css/custom.css b/docs/_static/css/custom.css
similarity index 100%
rename from docs/sphinx/_static/css/custom.css
rename to docs/_static/css/custom.css
diff --git a/docs/sphinx/api/index.md b/docs/api/index.md
similarity index 100%
rename from docs/sphinx/api/index.md
rename to docs/api/index.md
diff --git a/docs/sphinx/api/python/cc/index.md b/docs/api/python/cc/index.md
similarity index 100%
rename from docs/sphinx/api/python/cc/index.md
rename to docs/api/python/cc/index.md
diff --git a/docs/sphinx/api/python/config_settings/index.md b/docs/api/python/config_settings/index.md
similarity index 100%
rename from docs/sphinx/api/python/config_settings/index.md
rename to docs/api/python/config_settings/index.md
diff --git a/docs/sphinx/api/python/index.md b/docs/api/python/index.md
similarity index 100%
rename from docs/sphinx/api/python/index.md
rename to docs/api/python/index.md
diff --git a/docs/sphinx/api/python/runtime_env_toolchains/index.md b/docs/api/python/runtime_env_toolchains/index.md
similarity index 100%
rename from docs/sphinx/api/python/runtime_env_toolchains/index.md
rename to docs/api/python/runtime_env_toolchains/index.md
diff --git a/docs/sphinx/api/tools/precompiler/index.md b/docs/api/tools/precompiler/index.md
similarity index 100%
rename from docs/sphinx/api/tools/precompiler/index.md
rename to docs/api/tools/precompiler/index.md
diff --git a/docs/sphinx/conf.py b/docs/conf.py
similarity index 98%
rename from docs/sphinx/conf.py
rename to docs/conf.py
index 3200466..be428a6 100644
--- a/docs/sphinx/conf.py
+++ b/docs/conf.py
@@ -16,7 +16,7 @@
 # for more settings
 
 # Any extensions here not built into Sphinx must also be added to
-# the dependencies of //docs/sphinx:sphinx-builder
+# the dependencies of //docs:sphinx-builder
 extensions = [
     "sphinx.ext.autodoc",
     "sphinx.ext.autosectionlabel",
@@ -114,7 +114,7 @@
     "READTHEDOCS": False,
     "PRODUCTION_DOMAIN": "readthedocs.org",
     # This is the path to a page's source (after the github user/repo/commit)
-    "conf_py_path": "/docs/sphinx/",
+    "conf_py_path": "/docs/",
     "github_user": "bazelbuild",
     "github_repo": "rules_python",
     # The git version that was checked out, e.g. the tag or branch name
diff --git a/docs/sphinx/coverage.md b/docs/coverage.md
similarity index 100%
rename from docs/sphinx/coverage.md
rename to docs/coverage.md
diff --git a/docs/sphinx/environment-variables.md b/docs/environment-variables.md
similarity index 100%
rename from docs/sphinx/environment-variables.md
rename to docs/environment-variables.md
diff --git a/docs/sphinx/gazelle.md b/docs/gazelle.md
similarity index 100%
rename from docs/sphinx/gazelle.md
rename to docs/gazelle.md
diff --git a/docs/sphinx/getting-started.md b/docs/getting-started.md
similarity index 100%
rename from docs/sphinx/getting-started.md
rename to docs/getting-started.md
diff --git a/docs/sphinx/glossary.md b/docs/glossary.md
similarity index 100%
rename from docs/sphinx/glossary.md
rename to docs/glossary.md
diff --git a/docs/sphinx/index.md b/docs/index.md
similarity index 100%
rename from docs/sphinx/index.md
rename to docs/index.md
diff --git a/docs/sphinx/pip.md b/docs/pip.md
similarity index 100%
rename from docs/sphinx/pip.md
rename to docs/pip.md
diff --git a/docs/sphinx/precompiling.md b/docs/precompiling.md
similarity index 100%
rename from docs/sphinx/precompiling.md
rename to docs/precompiling.md
diff --git a/docs/sphinx/pypi-dependencies.md b/docs/pypi-dependencies.md
similarity index 99%
rename from docs/sphinx/pypi-dependencies.md
rename to docs/pypi-dependencies.md
index db017d2..636fefb 100644
--- a/docs/sphinx/pypi-dependencies.md
+++ b/docs/pypi-dependencies.md
@@ -324,7 +324,7 @@
 When using this feature during the `pip` extension evaluation you will see the accessed indexes similar to below:
 ```console
 Loading: 0 packages loaded
-    currently loading: docs/sphinx
+    currently loading: docs/
     Fetching module extension pip in @@//python/extensions:pip.bzl; starting
     Fetching https://pypi.org/simple/twine/
 ```
diff --git a/docs/sphinx/pyproject.toml b/docs/pyproject.toml
similarity index 100%
rename from docs/sphinx/pyproject.toml
rename to docs/pyproject.toml
diff --git a/docs/sphinx/readthedocs_build.sh b/docs/readthedocs_build.sh
similarity index 92%
rename from docs/sphinx/readthedocs_build.sh
rename to docs/readthedocs_build.sh
index c611b7c..3f67310 100755
--- a/docs/sphinx/readthedocs_build.sh
+++ b/docs/readthedocs_build.sh
@@ -17,4 +17,4 @@
   --config=rtd \
   "--//sphinxdocs:extra_defines=version=$READTHEDOCS_VERSION" \
   "${extra_env[@]}" \
-  //docs/sphinx:readthedocs_install
+  //docs:readthedocs_install
diff --git a/docs/sphinx/requirements.txt b/docs/requirements.txt
similarity index 98%
rename from docs/sphinx/requirements.txt
rename to docs/requirements.txt
index 0bce54e..7cd0329 100644
--- a/docs/sphinx/requirements.txt
+++ b/docs/requirements.txt
@@ -1,11 +1,11 @@
 # This file was autogenerated by uv via the following command:
-#    bazel run //docs/sphinx:requirements.update
+#    bazel run //docs:requirements.update
 --index-url https://pypi.org/simple
 
 absl-py==2.1.0 \
     --hash=sha256:526a04eadab8b4ee719ce68f204172ead1027549089702d99b9059f129ff1308 \
     --hash=sha256:7820790efbb316739cde8b4e19357243fc3608a152024288513dd968d7d959ff
-    # via rules-python-docs (docs/sphinx/pyproject.toml)
+    # via rules-python-docs (docs/pyproject.toml)
 alabaster==0.7.16 \
     --hash=sha256:75a8b99c28a5dad50dd7f8ccdd447a121ddb3892da9e53d1ca5cca3106d58d65 \
     --hash=sha256:b46733c07dce03ae4e150330b975c75737fa60f0a7c591b6c8bf4928a28e2c92
@@ -215,7 +215,7 @@
 myst-parser==4.0.0 \
     --hash=sha256:851c9dfb44e36e56d15d05e72f02b80da21a9e0d07cba96baf5e2d476bb91531 \
     --hash=sha256:b9317997552424448c6096c2558872fdb6f81d3ecb3a40ce84a7518798f3f28d
-    # via rules-python-docs (docs/sphinx/pyproject.toml)
+    # via rules-python-docs (docs/pyproject.toml)
 packaging==24.1 \
     --hash=sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002 \
     --hash=sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124
@@ -282,7 +282,7 @@
 readthedocs-sphinx-ext==2.2.5 \
     --hash=sha256:ee5fd5b99db9f0c180b2396cbce528aa36671951b9526bb0272dbfce5517bd27 \
     --hash=sha256:f8c56184ea011c972dd45a90122568587cc85b0127bc9cf064d17c68bc809daa
-    # via rules-python-docs (docs/sphinx/pyproject.toml)
+    # via rules-python-docs (docs/pyproject.toml)
 requests==2.32.3 \
     --hash=sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760 \
     --hash=sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6
@@ -297,14 +297,14 @@
     --hash=sha256:242f92a7ea7e6c5b406fdc2615413890ba9f699114a9c09192d7dfead2ee9cfe \
     --hash=sha256:c2419e2135d11f1951cd994d6eb18a1835bd8fdd8429f9ca375dc1f3281bd239
     # via
-    #   rules-python-docs (docs/sphinx/pyproject.toml)
+    #   rules-python-docs (docs/pyproject.toml)
     #   myst-parser
     #   sphinx-rtd-theme
     #   sphinxcontrib-jquery
 sphinx-rtd-theme==2.0.0 \
     --hash=sha256:bd5d7b80622406762073a04ef8fadc5f9151261563d47027de09910ce03afe6b \
     --hash=sha256:ec93d0856dc280cf3aee9a4c9807c60e027c7f7b461b77aeffed682e68f0e586
-    # via rules-python-docs (docs/sphinx/pyproject.toml)
+    # via rules-python-docs (docs/pyproject.toml)
 sphinxcontrib-applehelp==2.0.0 \
     --hash=sha256:2f29ef331735ce958efa4734873f084941970894c6090408b079c61b2e1c06d1 \
     --hash=sha256:4cd3f0ec4ac5dd9c17ec65e9ab272c9b867ea77425228e68ecf08d6b28ddbdb5
@@ -336,7 +336,7 @@
 typing-extensions==4.12.2 \
     --hash=sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d \
     --hash=sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8
-    # via rules-python-docs (docs/sphinx/pyproject.toml)
+    # via rules-python-docs (docs/pyproject.toml)
 urllib3==2.2.2 \
     --hash=sha256:a448b2f64d686155468037e1ace9f2d2199776e17f0a46610480d311f73e3472 \
     --hash=sha256:dd505485549a7a552833da5e6063639d0d177c04f23bc3864e41e5dc5f612168
diff --git a/docs/sphinx/BUILD.bazel b/docs/sphinx/BUILD.bazel
deleted file mode 100644
index 03c0e44..0000000
--- a/docs/sphinx/BUILD.bazel
+++ /dev/null
@@ -1,205 +0,0 @@
-# Copyright 2023 The Bazel Authors. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-load("@bazel_skylib//rules:write_file.bzl", "write_file")
-load("@dev_pip//:requirements.bzl", "requirement")
-load("//python:py_binary.bzl", "py_binary")
-load("//python/private:bzlmod_enabled.bzl", "BZLMOD_ENABLED")  # buildifier: disable=bzl-visibility
-load("//python/private:util.bzl", "IS_BAZEL_7_OR_HIGHER")  # buildifier: disable=bzl-visibility
-load("//sphinxdocs:readthedocs.bzl", "readthedocs_install")
-load("//sphinxdocs:sphinx.bzl", "sphinx_build_binary", "sphinx_docs")
-load("//sphinxdocs:sphinx_stardoc.bzl", "sphinx_stardoc", "sphinx_stardocs")
-
-# We only build for Linux and Mac because:
-# 1. The actual doc process only runs on Linux
-# 2. Mac is a common development platform, and is close enough to Linux
-#    it's feasible to make work.
-# Making CI happy under Windows is too much of a headache, though, so we don't
-# bother with that.
-_TARGET_COMPATIBLE_WITH = select({
-    "@platforms//os:linux": [],
-    "@platforms//os:macos": [],
-    "//conditions:default": ["@platforms//:incompatible"],
-}) if IS_BAZEL_7_OR_HIGHER else ["@platforms//:incompatible"]
-
-# See README.md for instructions. Short version:
-# * `bazel run //docs/sphinx:docs.serve` in a separate terminal
-# * `ibazel build //docs/sphinx:docs` to automatically rebuild docs
-sphinx_docs(
-    name = "docs",
-    srcs = glob(
-        include = [
-            "*.md",
-            "**/*.md",
-            "_static/**",
-            "_includes/**",
-        ],
-        exclude = [
-            "README.md",
-            "_*",
-            "*.inv*",
-        ],
-    ),
-    config = "conf.py",
-    formats = [
-        "html",
-    ],
-    renamed_srcs = {
-        "//:CHANGELOG.md": "changelog.md",
-        "//:CONTRIBUTING.md": "contributing.md",
-        "//sphinxdocs/inventories:bazel_inventory": "bazel_inventory.inv",
-    },
-    sphinx = ":sphinx-build",
-    strip_prefix = package_name() + "/",
-    tags = ["docs"],
-    target_compatible_with = _TARGET_COMPATIBLE_WITH,
-    deps = [
-        ":bzl_api_docs",
-        "//sphinxdocs/docs:docs_lib",
-    ],
-)
-
-sphinx_stardocs(
-    name = "bzl_api_docs",
-    srcs = [
-        "//python:defs_bzl",
-        "//python:packaging_bzl",
-        "//python:pip_bzl",
-        "//python:py_binary_bzl",
-        "//python:py_cc_link_params_info_bzl",
-        "//python:py_library_bzl",
-        "//python:py_runtime_bzl",
-        "//python:py_runtime_info_bzl",
-        "//python:py_test_bzl",
-        "//python/cc:py_cc_toolchain_info_bzl",
-        "//python/entry_points:py_console_script_binary_bzl",
-        "//python/private/common:py_binary_rule_bazel_bzl",
-        "//python/private/common:py_library_rule_bazel_bzl",
-        "//python/private/common:py_runtime_rule_bzl",
-        "//python/private/common:py_test_rule_bazel_bzl",
-    ] + ([
-        # Bazel 6 + Stardoc isn't able to parse something about the python bzlmod extension
-        "//python/extensions:python_bzl",
-    ] if IS_BAZEL_7_OR_HIGHER else []) + ([
-        # This depends on @pythons_hub, which is only created under bzlmod,
-        "//python/extensions:pip_bzl",
-    ] if IS_BAZEL_7_OR_HIGHER and BZLMOD_ENABLED else []),
-    prefix = "api/",
-    tags = ["docs"],
-    target_compatible_with = _TARGET_COMPATIBLE_WITH,
-)
-
-sphinx_stardoc(
-    name = "py_cc_toolchain",
-    src = "//python/private:py_cc_toolchain_rule.bzl",
-    prefix = "api/",
-    public_load_path = "//python/cc:py_cc_toolchain.bzl",
-    tags = ["docs"],
-    target_compatible_with = _TARGET_COMPATIBLE_WITH,
-    deps = ["//python/cc:py_cc_toolchain_bzl"],
-)
-
-sphinx_stardoc(
-    name = "py_runtime_pair",
-    src = "//python/private:py_runtime_pair_rule_bzl",
-    public_load_path = "//python:py_runtime_pair.bzl",
-    tags = ["docs"],
-    target_compatible_with = _TARGET_COMPATIBLE_WITH,
-)
-
-readthedocs_install(
-    name = "readthedocs_install",
-    docs = [":docs"],
-    target_compatible_with = _TARGET_COMPATIBLE_WITH,
-)
-
-sphinx_build_binary(
-    name = "sphinx-build",
-    target_compatible_with = _TARGET_COMPATIBLE_WITH,
-    deps = [
-        requirement("sphinx"),
-        requirement("sphinx_rtd_theme"),
-        requirement("myst_parser"),
-        requirement("readthedocs_sphinx_ext"),
-        requirement("typing_extensions"),
-        "//sphinxdocs/src/sphinx_bzl",
-    ],
-)
-
-_REQUIREMENTS_TARGET_COMPATIBLE_WITH = select({
-    "@platforms//os:linux": [],
-    "@platforms//os:macos": [],
-    "@platforms//os:windows": [],
-    "//conditions:default": ["@platforms//:incompatible"],
-}) if BZLMOD_ENABLED else ["@platforms//:incompatible"]
-
-# Run bazel run //docs/sphinx:requirements.update
-genrule(
-    name = "requirements",
-    srcs = ["pyproject.toml"],
-    outs = ["_requirements.txt"],
-    cmd = "$(UV_BIN) pip compile " + " ".join([
-        "--custom-compile-command='bazel run //docs/sphinx:requirements.update'",
-        "--generate-hashes",
-        "--universal",
-        "--emit-index-url",
-        "--no-strip-extras",
-        "--no-build",
-        "--python=$(PYTHON3)",
-        "$<",
-        "--output-file=$@",
-        # Always try upgrading
-        "--upgrade",
-    ]),
-    tags = [
-        "local",
-        "manual",
-        "no-cache",
-    ],
-    target_compatible_with = _REQUIREMENTS_TARGET_COMPATIBLE_WITH,
-    toolchains = [
-        "//python/uv:current_toolchain",
-        "//python:current_py_toolchain",
-    ],
-)
-
-# Write a script that can be used for updating the in-tree version of the
-# requirements file
-write_file(
-    name = "gen_update_requirements",
-    out = "requirements.update.py",
-    content = [
-        "from os import environ",
-        "from pathlib import Path",
-        "from sys import stderr",
-        "",
-        'src = Path(environ["REQUIREMENTS_FILE"])',
-        'dst = Path(environ["BUILD_WORKSPACE_DIRECTORY"]) / "docs" / "sphinx" / "requirements.txt"',
-        'print(f"Writing requirements contents from {src} to {dst}", file=stderr)',
-        "dst.write_text(src.read_text())",
-        'print("Success!", file=stderr)',
-    ],
-    target_compatible_with = _REQUIREMENTS_TARGET_COMPATIBLE_WITH,
-)
-
-py_binary(
-    name = "requirements.update",
-    srcs = ["requirements.update.py"],
-    data = [":requirements"],
-    env = {
-        "REQUIREMENTS_FILE": "$(location :requirements)",
-    },
-    tags = ["manual"],
-    target_compatible_with = _REQUIREMENTS_TARGET_COMPATIBLE_WITH,
-)
diff --git a/docs/sphinx/support.md b/docs/support.md
similarity index 100%
rename from docs/sphinx/support.md
rename to docs/support.md
diff --git a/docs/sphinx/toolchains.md b/docs/toolchains.md
similarity index 100%
rename from docs/sphinx/toolchains.md
rename to docs/toolchains.md