diff --git a/doc/sphinx/source/conf.py b/doc/sphinx/source/conf.py
index f562bf7ecf..492910f848 100644
--- a/doc/sphinx/source/conf.py
+++ b/doc/sphinx/source/conf.py
@@ -53,6 +53,7 @@
"sphinx.ext.viewcode",
"sphinx.ext.napoleon",
"autodocsumm",
+ "sphinx_design",
]
autodoc_default_options = {
diff --git a/doc/sphinx/source/tutorials/files/esmvaltool_output_header.txt b/doc/sphinx/source/tutorials/files/esmvaltool_output_header.txt
new file mode 100644
index 0000000000..f77f9be9c9
--- /dev/null
+++ b/doc/sphinx/source/tutorials/files/esmvaltool_output_header.txt
@@ -0,0 +1,31 @@
+2026-05-11 15:22:20,686 UTC [280110] INFO
+______________________________________________________________________
+ _____ ____ __ ____ __ _ _____ _
+ | ____/ ___|| \/ \ \ / /_ _| |_ _|__ ___ | |
+ | _| \___ \| |\/| |\ \ / / _` | | | |/ _ \ / _ \| |
+ | |___ ___) | | | | \ V / (_| | | | | (_) | (_) | |
+ |_____|____/|_| |_| \_/ \__,_|_| |_|\___/ \___/|_|
+______________________________________________________________________
+
+Earth System Model Evaluation Tool
+
+A community tool for the evaluation of Earth system models.
+
+https://esmvaltool.org
+
+The Earth System Model Evaluation Tool (ESMValTool) is a community
+diagnostics and performance metrics tool for the evaluation of Earth
+System Models (ESMs) that allows for routine comparison of single or
+multiple models, either against predecessor versions or against
+observations.
+
+Tutorial: https://tutorial.esmvaltool.org
+Documentation: https://docs.esmvaltool.org
+Contact: esmvaltool-dev@listserv.dfn.de
+
+If you find this software useful for your research, please cite it using
+https://doi.org/10.5281/zenodo.3387139 for ESMValCore or
+https://doi.org/10.5281/zenodo.3401363 for ESMValTool or
+any of the reference papers listed at https://esmvaltool.org/references/.
+
+Have fun!
diff --git a/doc/sphinx/source/tutorials/index.rst b/doc/sphinx/source/tutorials/index.rst
index 244fbbc453..4cfefa9d3b 100644
--- a/doc/sphinx/source/tutorials/index.rst
+++ b/doc/sphinx/source/tutorials/index.rst
@@ -1,3 +1,5 @@
+.. _tutorials:
+
Tutorials
=========
@@ -12,3 +14,16 @@ While these are tailored for ACCESS users, they are still very informative.
.. raw:: html
+
+.. The template 'Table of Contents' below
+.. will not render in the HTML documentation
+.. until the '' line below is uncommented
+.. and a filename is added
+.. (test by replacing '' with 'template').
+
+.. toctree::
+ :maxdepth: 1
+ :caption:
+
+ template
+..
diff --git a/doc/sphinx/source/tutorials/template.rst b/doc/sphinx/source/tutorials/template.rst
new file mode 100644
index 0000000000..f9147deedd
--- /dev/null
+++ b/doc/sphinx/source/tutorials/template.rst
@@ -0,0 +1,148 @@
+.. :orphan: # uncomment before merging!
+
+.. How to use this template
+..
+.. 1. Make a copy of this file.
+.. 2. Update the filename.
+.. 3. Add the filename (without the '.rst' extension)
+.. to a 'toctree' directive
+.. in the 'tutorials/index.rst' file.
+.. 4. Use the name of the tutorial for the title below
+.. and the reference label.
+.. 5. Remove ':orphan:', these comments,
+.. and 'The language of tutorials' section (below).
+..
+.. https://diataxis.fr/tutorials provides more information.
+
+.. _title_of_the_tutorial:
+
+Title of the tutorial
+=====================
+
+.. admonition:: Overview
+ :class: note
+
+ .. grid:: 2
+ :gutter: 1
+ :margin: 3 3 0 5
+
+ .. grid-item-card:: Timings
+ :columns: 12
+
+ * Teaching: X min
+ * Exercises: Y min
+
+ .. grid-item-card:: Questions
+
+ * Describe what the learner will accomplish.
+ * Question 1?
+ * Question 2?
+
+ .. grid-item-card:: Learning outcomes
+
+ * Describe the learning outcomes, i.e.
+ the knowledge, skills, or expertise the learner will gain.
+ * Objective 1.
+ * Objective 2.
+
+ .. grid-item-card:: Prerequisites
+
+ * Provide any prerequisites.
+ * Prerequisites 1.
+ * Prerequisites 2.
+
+ .. grid-item-card:: Assumptions
+
+ * Provide any assumptions.
+ * Assumption 1.
+ * Assumption 2.
+
+Question 1
+----------
+
+Add content here.
+
+* Consider including diagrams to support the text.
+* Use any free icons from `Font Awesome`_ via an ``:fa:`` directive.
+* Use admonitions from `PyData Theme documentation: Admonitions`_.
+* Link to other files within the documentation:
+
+ * Link to pages via ``:doc:`/develop/recipe```
+ (renders as :doc:`/develop/recipe`).
+ * Link to sections via ``:ref:`diagnostic_from_example```
+ (renders as :ref:`diagnostic_from_example`).
+
+* Include other files within the documentation:
+
+ .. include:: files/esmvaltool_output_header.txt
+ :code:
+
+Question 2
+----------
+
+Add content here.
+
+* Use code snippets:
+
+ .. code-block:: bash
+ :caption: Bash
+
+ my command
+
+ .. code-block:: python
+ :caption: Python
+ :linenos:
+ :emphasize-lines: 2
+
+ with line numbers
+ and code highlighting
+
+* Create expandable sections containing the
+ output / answer / solution from a command:
+
+ .. dropdown:: Output
+ :color: secondary
+ :icon: eye
+
+ .. code-block:: bash
+ :caption: Bash
+
+ my output
+
+The language of tutorials
+-------------------------
+
+We ...
+ The first-person plural
+ affirms the relationship between tutor and learner:
+ you are not alone; we are in this together.
+
+First, do x. Now, do y. Now that you have done y, do z.
+ No room for ambiguity or doubt.
+
+We must always do x before we do y. provides more details.
+ Provide minimal explanation of actions
+ in the most basic language possible.
+ Link to more detailed explanation.
+
+The output should be something like ...
+ Give your learner clear expectations.
+
+Notice that ... Remember that ... Let's check ...
+ Give your learner plenty of clues
+ to help confirm they are on the right track and orient themselves.
+
+Congratulations!
+----------------
+
+You have built a secure, three-layer hylomorphic stasis engine ...
+ Describe (and admire, in a mild way) what your learner has accomplished.
+
+.. admonition:: Key points
+ :class: important
+
+ * Key point 1
+ * Key point 2
+
+.. _`PyData Theme documentation: Admonitions`: https://pydata-sphinx-theme.readthedocs.io/en/stable/examples/kitchen-sink/admonitions.html
+.. _`Font Awesome`: https://fontawesome.com/search?ic=free-collection
diff --git a/pixi.lock b/pixi.lock
index a3333ac3cf..1618d73bb7 100644
--- a/pixi.lock
+++ b/pixi.lock
@@ -537,6 +537,7 @@ environments:
- conda: https://conda.anaconda.org/conda-forge/noarch/soupsieve-2.8.3-pyhd8ed1ab_0.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/sparse-0.18.0-pyhcf101f3_0.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/sphinx-8.2.3-pyhd8ed1ab_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/sphinx-design-0.7.0-pyhd8ed1ab_0.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/sphinxcontrib-applehelp-2.0.0-pyhd8ed1ab_1.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/sphinxcontrib-devhelp-2.0.0-pyhd8ed1ab_1.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/sphinxcontrib-htmlhelp-2.1.0-pyhd8ed1ab_1.conda
@@ -836,6 +837,7 @@ environments:
- conda: https://conda.anaconda.org/conda-forge/noarch/soupsieve-2.8.3-pyhd8ed1ab_0.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/sparse-0.18.0-pyhcf101f3_0.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/sphinx-8.2.3-pyhd8ed1ab_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/sphinx-design-0.7.0-pyhd8ed1ab_0.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/sphinxcontrib-applehelp-2.0.0-pyhd8ed1ab_1.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/sphinxcontrib-devhelp-2.0.0-pyhd8ed1ab_1.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/sphinxcontrib-htmlhelp-2.1.0-pyhd8ed1ab_1.conda
@@ -1592,6 +1594,7 @@ environments:
- conda: https://conda.anaconda.org/conda-forge/noarch/rfc3339-validator-0.1.4-pyhd8ed1ab_1.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/rfc3986-validator-0.1.1-pyh9f0ad1d_0.tar.bz2
- conda: https://conda.anaconda.org/conda-forge/noarch/rfc3987-syntax-1.1.0-pyhe01879c_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/rich-15.0.0-pyhcf101f3_0.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/roman-numerals-4.1.0-pyhd8ed1ab_0.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/roman-numerals-py-4.1.0-pyhd8ed1ab_0.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/seaborn-0.13.2-hd8ed1ab_3.conda
@@ -1607,6 +1610,7 @@ environments:
- conda: https://conda.anaconda.org/conda-forge/noarch/soupsieve-2.8.3-pyhd8ed1ab_0.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/sparse-0.18.0-pyhcf101f3_0.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/sphinx-8.2.3-pyhd8ed1ab_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/sphinx-design-0.7.0-pyhd8ed1ab_0.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/sphinxcontrib-applehelp-2.0.0-pyhd8ed1ab_1.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/sphinxcontrib-devhelp-2.0.0-pyhd8ed1ab_1.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/sphinxcontrib-htmlhelp-2.1.0-pyhd8ed1ab_1.conda
@@ -1674,7 +1678,6 @@ environments:
- pypi: https://files.pythonhosted.org/packages/79/a5/60a55bd4cb9488d21adcdce88625e1de9bc14ea454677160c162132838cb/itables-2.7.3-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/80/56/60547f7801b97c67e97491dc3d9ade9fbccbd0325058fd3dfcb2f5d98d90/cattrs-26.1.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/81/5a/2225f4c176dbfed0d809e848b50ef08f70e61daa667b7fa14b0d311ae44d/pydantic-2.13.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/82/3b/64d4899d73f91ba49a8c18a8ff3f0ea8f1c1d75481760df8c68ef5235bf5/rich-15.0.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/84/a6/b3965e1e146ef5762870bbe76117876ceba51a201e18cc31f5703e454596/httptools-0.7.1-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl
- pypi: https://files.pythonhosted.org/packages/8f/04/04d035755a8a9de0ab12e7b0597c2258c6b1673d6255239b11a3afcf3812/ncdata-0.3.2-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/9a/22/f1925cdda983ab66fc8ec6ec8014b959262747e58bdca26a4e3d1da29d56/python_multipart-0.0.26-py3-none-any.whl
@@ -1890,6 +1893,7 @@ environments:
- conda: https://conda.anaconda.org/conda-forge/noarch/rfc3339-validator-0.1.4-pyhd8ed1ab_1.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/rfc3986-validator-0.1.1-pyh9f0ad1d_0.tar.bz2
- conda: https://conda.anaconda.org/conda-forge/noarch/rfc3987-syntax-1.1.0-pyhe01879c_1.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/rich-15.0.0-pyhcf101f3_0.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/roman-numerals-4.1.0-pyhd8ed1ab_0.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/roman-numerals-py-4.1.0-pyhd8ed1ab_0.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/seaborn-0.13.2-hd8ed1ab_3.conda
@@ -1905,6 +1909,7 @@ environments:
- conda: https://conda.anaconda.org/conda-forge/noarch/soupsieve-2.8.3-pyhd8ed1ab_0.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/sparse-0.18.0-pyhcf101f3_0.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/sphinx-8.2.3-pyhd8ed1ab_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/sphinx-design-0.7.0-pyhd8ed1ab_0.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/sphinxcontrib-applehelp-2.0.0-pyhd8ed1ab_1.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/sphinxcontrib-devhelp-2.0.0-pyhd8ed1ab_1.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/sphinxcontrib-htmlhelp-2.1.0-pyhd8ed1ab_1.conda
@@ -2208,7 +2213,6 @@ environments:
- pypi: https://files.pythonhosted.org/packages/79/a5/60a55bd4cb9488d21adcdce88625e1de9bc14ea454677160c162132838cb/itables-2.7.3-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/80/56/60547f7801b97c67e97491dc3d9ade9fbccbd0325058fd3dfcb2f5d98d90/cattrs-26.1.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/81/5a/2225f4c176dbfed0d809e848b50ef08f70e61daa667b7fa14b0d311ae44d/pydantic-2.13.1-py3-none-any.whl
- - pypi: https://files.pythonhosted.org/packages/82/3b/64d4899d73f91ba49a8c18a8ff3f0ea8f1c1d75481760df8c68ef5235bf5/rich-15.0.0-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/89/8c/182a2a593195bfd39842ea68ebc084e20c850806117213f5a299dfc513d9/uvloop-0.22.1-cp313-cp313-macosx_10_13_universal2.whl
- pypi: https://files.pythonhosted.org/packages/8c/7e/e7394eeb49a41cc514b3eb49020223666cbf40d86f5721c2f07871e6d84a/legacy_cgi-2.6.4-py3-none-any.whl
- pypi: https://files.pythonhosted.org/packages/8f/04/04d035755a8a9de0ab12e7b0597c2258c6b1673d6255239b11a3afcf3812/ncdata-0.3.2-py3-none-any.whl
@@ -3599,6 +3603,7 @@ environments:
- conda: https://conda.anaconda.org/conda-forge/noarch/soupsieve-2.8.3-pyhd8ed1ab_0.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/sparse-0.18.0-pyhcf101f3_0.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/sphinx-8.2.3-pyhd8ed1ab_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/sphinx-design-0.7.0-pyhd8ed1ab_0.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/sphinxcontrib-applehelp-2.0.0-pyhd8ed1ab_1.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/sphinxcontrib-devhelp-2.0.0-pyhd8ed1ab_1.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/sphinxcontrib-htmlhelp-2.1.0-pyhd8ed1ab_1.conda
@@ -4797,6 +4802,7 @@ environments:
- conda: https://conda.anaconda.org/conda-forge/noarch/soupsieve-2.8.3-pyhd8ed1ab_0.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/sparse-0.18.0-pyhcf101f3_0.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/sphinx-8.2.3-pyhd8ed1ab_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/sphinx-design-0.7.0-pyhd8ed1ab_0.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/sphinxcontrib-applehelp-2.0.0-pyhd8ed1ab_1.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/sphinxcontrib-devhelp-2.0.0-pyhd8ed1ab_1.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/sphinxcontrib-htmlhelp-2.1.0-pyhd8ed1ab_1.conda
@@ -6986,6 +6992,7 @@ environments:
- conda: https://conda.anaconda.org/conda-forge/noarch/soupsieve-2.8.3-pyhd8ed1ab_0.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/sparse-0.18.0-pyhcf101f3_0.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/sphinx-8.2.3-pyhd8ed1ab_0.conda
+ - conda: https://conda.anaconda.org/conda-forge/noarch/sphinx-design-0.7.0-pyhd8ed1ab_0.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/sphinxcontrib-applehelp-2.0.0-pyhd8ed1ab_1.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/sphinxcontrib-devhelp-2.0.0-pyhd8ed1ab_1.conda
- conda: https://conda.anaconda.org/conda-forge/noarch/sphinxcontrib-htmlhelp-2.1.0-pyhd8ed1ab_1.conda
@@ -26307,6 +26314,18 @@ packages:
- pkg:pypi/sphinx?source=hash-mapping
size: 1424416
timestamp: 1740956642838
+- conda: https://conda.anaconda.org/conda-forge/noarch/sphinx-design-0.7.0-pyhd8ed1ab_0.conda
+ sha256: 7f8437a97e6311bebf230cfd2ae3c5bdb2230e681c41daebdb894280bf8b4ab6
+ md5: 28eddfb8b9ecdd044a6f609f985398a7
+ depends:
+ - python >=3.11
+ - sphinx >=7,<10
+ license: MIT
+ license_family: MIT
+ purls:
+ - pkg:pypi/sphinx-design?source=hash-mapping
+ size: 931118
+ timestamp: 1769032711360
- conda: https://conda.anaconda.org/conda-forge/noarch/sphinxcontrib-applehelp-2.0.0-pyhd8ed1ab_1.conda
sha256: d7433a344a9ad32a680b881c81b0034bc61618d12c39dd6e3309abeffa9577ba
md5: 16e3f039c0aa6446513e94ab18a8784b
@@ -33387,6 +33406,7 @@ packages:
- pyyaml
- rasterio>=1.3.10
- requests
+ - rich
- scikit-image
- scikit-learn>=1.4.0
- scipy
@@ -34003,15 +34023,6 @@ packages:
- email-validator>=2.0.0 ; extra == 'email'
- tzdata ; python_full_version >= '3.9' and sys_platform == 'win32' and extra == 'timezone'
requires_python: '>=3.9'
-- pypi: https://files.pythonhosted.org/packages/82/3b/64d4899d73f91ba49a8c18a8ff3f0ea8f1c1d75481760df8c68ef5235bf5/rich-15.0.0-py3-none-any.whl
- name: rich
- version: 15.0.0
- sha256: 33bd4ef74232fb73fe9279a257718407f169c09b78a87ad3d296f548e27de0bb
- requires_dist:
- - ipywidgets>=7.5.1,<9 ; extra == 'jupyter'
- - markdown-it-py>=2.2.0
- - pygments>=2.13.0,<3.0.0
- requires_python: '>=3.9.0'
- pypi: https://files.pythonhosted.org/packages/84/a6/b3965e1e146ef5762870bbe76117876ceba51a201e18cc31f5703e454596/httptools-0.7.1-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl
name: httptools
version: 0.7.1
diff --git a/pyproject.toml b/pyproject.toml
index 1b01dac5b1..30c3ea7a37 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -326,6 +326,7 @@ test-py314 = { features = ["py314", "esmvalcore", "test"], solve-group = "defaul
"myst-nb" = "*"
"pydata-sphinx-theme" = "*"
"sphinx" = ">=6.1.3,<9" # <9 due to ESMValTool/issues/4316
+"sphinx-design" = "*"
# Other development tools.
[tool.pixi.feature.dev.dependencies]